Assinaturas ReactJS e Email com suas particularidades

Dec 10 2022
Em primeiro lugar, quero muito agradecer aos leitores que chegaram aqui, e a equipe de desenvolvimento que participo no Brasil, Vá de Táxi! Pesquisando muito na internet, encontrei trechos de como fazer uma assinatura de e-mail que era uma das minhas tarefas a cumprir. Com isso, tive um atraso na entrega do conteúdo, mas agora com mais facilidade em abordar o tema, estarei postando aqui para os senhores leitores.

Em primeiro lugar, quero muito agradecer aos leitores que chegaram aqui, e a equipe de desenvolvimento que participo no Brasil, Vá de Táxi! Pesquisando muito na internet, encontrei trechos de como fazer uma assinatura de e-mail que era uma das minhas tarefas a cumprir. Com isso, tive um atraso na entrega do conteúdo, mas agora com mais facilidade em abordar o tema, estarei postando aqui para os senhores leitores. Teremos que partir do pressuposto de que e-mail não é uma coisa muito tecnológica, e interpreta uma assinatura de e-mail em tabelas, com o código em HTML. Então temos que criar uma tabela com HTML e o estilo tem que ser inline, ficaria mais ou menos assim:

<table>
  <tbody>
    <tr>
      <td>
        <img src="" style="ANY STYLE" />YOUR LOGO IMAGE
      </td>
      <td>
        OPCIONAL DIV
      </td>
      <table>
        <tbody>
          <tr>
            <td>
              <span style="ANY STYLE">YOUR NAME</span> &nbsp; <span style="ANY STYLE">LAST NAME OR CARRER NAME</span>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tbody>
          <tr>
            <td>
              <img src="" style="ANY STYLE"/>PHONE ICON
            </td>
            <td>
              <span style="ANY STYLE">YOUR PHONE</span>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tbody>
          <tr>
            <td>
              <img src="" style="ANY STYLE"/> SITE ICON
            </td>
            <td>
              <span style="ANY STYLE">YOUR SITE</span>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tbody>
          <tr>
            <td>
              <img src="" style="ANY STYLE"/> FACEBOOK ICON
            </td>
            <td>
              <img src="" style="ANY STYLE"/> INSTAGRAM ICON
            </td>
            <td>
              <img src="" style="ANY STYLE"/> LINKEDIN ICON
            </td>
          </tr>
        </tbody>
      </table>
    </tr>
  </tbody>
</table>


table, th, td {
  border: 1px solid;
}

Temos um componente de assinatura de e-mail onde separamos o estilo por grade esquerda e direita. Coloque o css ao seu gosto

import React, { Fragment, useState } from 'react';

import Infos from '../Infos/index';
import Preview from '../Preview/index';
import { EmailSignatureStyle } from './styles';

const EmailSignature = () => {
  const [user, setUser] = useState([]);

  return (
      <Grid className="container" container spacing={0}>
        <Grid item xs={4}>
          <Box className="boxLeft">
            <Infos setUser={setUser} />
          </Box>
        </Grid>
        <Grid item xs={8}>
          <Box className="boxRight">
            <Preview user={user} />
          </Box>
        </Grid>
      </Grid>
  );
};

export default EmailSignature;

import PropTypes from 'prop-types';
import React, { useState } from 'react';

import Input from '../Input/index';

const Infos = (props) => {
  const { setUser } = props;
  const classes = useStyles();
  const [userData, setUserData] = useState({
    name: '',
    carrer: '',
    phone: '',
  });
  const handleChangeField = (field) => (event) => {
    const value = event?.target?.value || '';
    setUserData((prev) => ({ ...prev, [field]: value }));
  };
  setUser(userData);

  return (
    <div className="container">
      <div className="title">
        {' '}
        <span>Insira as informações que serão exibidas na assinatura</span>{' '}
      </div>
      <Input
        label="Name"
        value={userData.name}
        onChange={handleChangeField('name')}
      />
      <Input
        className="carrer"
        label="Carrer"
        value={userData.carrer}
        onChange={handleChangeField('carrer')}
      />
      <Input
        type="number"
        label="Phone"
        value={
          userData.phone
        }
        onChange={handleChangeField('phone')}
      />
    </div>
  );
};

Infos.propTypes = {
  setUser: PropTypes.isRequired,
};

export default Infos;

import { TextField } from '@mui/material';
import PropTypes from 'prop-types';
import React from 'react';

const Input = (props) => {
  const classes = useStyles();
  const { id, label, defaultValue, error, helperText, type, value, onChange } =
    props;

  return (
    <TextField
      id={id}
      type={type}
      label={label}
      error={error}
      helperText={helperText}
      className="input"
      defaultValue={defaultValue}
      value={value}
      onChange={onChange}
    />
  );
};

Input.propTypes = {
  id: PropTypes.isRequired,
  label: PropTypes.isRequired,
  defaultValue: PropTypes.isRequired,
  error: PropTypes.isRequired,
  helperText: PropTypes.isRequired,
  type: PropTypes.isRequired,
  value: PropTypes.isRequired,
  onChange: PropTypes.isRequired,
};

export default Input;

Colocar texto na área de transferência é feito rapidamente. Mas como você lidaria com imagens ou outros formatos de texto, como richtext ou HTML? É possível colocá-los na área de transferência com JavaScript também?

Há outro método disponível para colocar conteúdo na área de transferência — ( clipboard.write ).

clipboard.writenão aceita strings mas ClipboardItems. A principal diferença entre os dois métodos é que, se você quiser colocar qualquer coisa além de texto simples na área de transferência, deverá definir o tipo MIME correspondente usando uma extensão ClipboardItem.

É mais código para escrever, mas ainda assim uma experiência decente na minha opinião. Doce!

import PropTypes from 'prop-types';
import React, { useState, useRef } from 'react';

const Preview = (props) => {
  const { user } = props;
  const div = useRef(null);
  const [copySuccess, setCopySuccess] = useState(false);
  const classes = useStyles();

  const copyToClipboard = async () => {
    const html = div.current;

    try {
      const success = await navigator.clipboard.write([
        new ClipboardItem({
          'text/html': new Blob([html.innerHTML], {
            type: 'text/html',
          }),
        }),
      ]);
      setCopySuccess(true);
      return success;
    } catch (e) {
      console.log('Fail', e);
    }
    setCopySuccess(true);
  }

  return (
    <div>
      <div>
        <span className="spanHeader">
          TITLE
        </span>
      </div>
      <div className="contentDesc">
        <span className="spanDescription">
          DESCRIPTION <br />
        </span>
      </div>
      <div className="contentTable">
        {user.name && (
          <table ref={div}>
            <tbody>
              <tr>
                <td>
                  <table>
                    <tbody>
                      <tr>
                        <td>
                          <img
                            style={{ width: '12vw', margin: '0 20px 0 0' }}
                            className={classes.logo}
                            src=""
                            alt="logo"
                          />
                        </td>
                          <table>
                            <tbody>
                              <tr>
                                <td style={{ textAlign: 'initial' }}>
                                  <span
                                    style={{
                                      fontWeight: 'bold',
                                      fontSize: '12pt',
                                      color: '#1d71a5',
                                      textTransform: 'capitalize',
                                      fontFamily: 'Verdana',
                                    }}
                                  >
                                    {user.name} -
                                  </span>
                                  <span>&nbsp;</span>
                                  <span
                                    style={{
                                      fontWeight: 'bold',
                                      fontSize: '12pt',
                                      color: '#4D4D4D',
                                      textTransform: 'capitalize',
                                      fontFamily: 'Verdana',
                                    }}
                                  >
                                    {user.carrer}
                                  </span>
                                  {user.phone && (
                                    <table
                                      style={{
                                        margin: '5px 0 0 0',
                                      }}
                                    >
                                      <tbody>
                                        <tr>
                                          <td
                                            style={{
                                              margin: '5px 0',
                                            }}
                                          >
                                            <img
                                              src="https://i.postimg.cc/xdCDbRcX/icone-telefone-assinatura-email.png"
                                              color="#1d71a5"
                                              alt="Telefone icon"
                                              style={{
                                                width: '12px',
                                                display: 'block',
                                                margin: '0 10px 0 0',
                                              }}
                                            />
                                          </td>
                                          <td>
                                            <span
                                              style={{
                                                fontSize: '12px',
                                                color: '#000',
                                                textTransform: 'capitalize',
                                              }}
                                            >
                                              user.phone
                                            </span>
                                          </td>
                                        </tr>
                                      </tbody>
                                    </table>
                                  )}
                                  {user.phone && (
                                    <table
                                      style={{
                                        margin: '5px 0 0 0',
                                      }}
                                    >
                                      <tbody>
                                        <tr>
                                          <td
                                            style={{
                                              margin: '5px 0',
                                            }}
                                          >
                                            <img
                                              src="https://i.postimg.cc/nhTfz5c8/icone-site-assinatura-email.png"
                                              color="#1d71a5"
                                              alt="Website URL icon"
                                              style={{
                                                width: '12px',
                                                display: 'block',
                                                margin: '0 10px 0 0',
                                              }}
                                            />
                                          </td>
                                          <td>
                                            <span
                                              style={{
                                                fontSize: '12px',
                                                color: '#000',
                                                textDecoration: 'none',
                                              }}
                                            >
                                              YOUR SITE
                                            </span>
                                          </td>
                                        </tr>
                                      </tbody>
                                    </table>
                                  )}
                                  {user.phone && (
                                    <table
                                      style={{
                                        marginTop: '-5px',
                                      }}
                                    >
                                      <tbody>
                                        <tr>
                                          <td
                                            style={{
                                              margin: '5px 0',
                                            }}
                                          >
                                            <a
                                              href=""
                                              style={{
                                                display: 'inline-block',
                                                padding: '0px',
                                                margin: '5px 0 0 5px',
                                              }}
                                            >
                                              <img
                                                src="https://cdn2.hubspot.net/hubfs/53/tools/email-signature-generator/icons/facebook-icon.png"
                                                alt="facebook"
                                                style={{
                                                  backgroundColor: '#1d71a5',
                                                  maxWidth: '135px',
                                                  display: 'block',
                                                  width: '80%',
                                                }}
                                              />
                                            </a>
                                          </td>
                                          <td>
                                            <a
                                              href=""
                                              style={{
                                                display: 'inline-block',
                                                padding: '0px',
                                                margin: '5px 0 0 5px',
                                              }}
                                            >
                                              <img
                                                src="https://cdn2.hubspot.net/hubfs/53/tools/email-signature-generator/icons/instagram-icon.png"
                                                alt="facebook"
                                                color="#1d71a5"
                                                style={{
                                                  backgroundColor: '#1d71a5',
                                                  maxWidth: '135px',
                                                  display: 'block',
                                                  width: '80%',
                                                }}
                                              />
                                            </a>
                                          </td>
                                          <td>
                                            <a
                                              href=""
                                              color="#1d71a5"
                                              style={{
                                                display: 'inline-block',
                                                padding: '0px',
                                                margin: '5px 0 0 5px',
                                              }}
                                            >
                                              <img
                                                src="https://cdn2.hubspot.net/hubfs/53/tools/email-signature-generator/icons/linkedin-icon.png"
                                                alt="facebook"
                                                color="#1d71a5"
                                                style={{
                                                  backgroundColor: '#1d71a5',
                                                  maxWidth: '135px',
                                                  display: 'block',
                                                  width: '80%',
                                                }}
                                              />
                                            </a>
                                          </td>
                                        </tr>
                                      </tbody>
                                    </table>
                                  )}
                                </td>
                              </tr>
                            </tbody>
                          </table>
                      </tr>
                    </tbody>
                  </table>
                  <table
                    style={{
                      maxWidth: '540px',
                    }}
                  >
                    <tbody>
                      <tr>
                        <td
                          style={{
                            fontSize: '6pt',
                            width: '80%',
                            color: '#9FA6AE',
                          }}
                        >
                          ANY TEXT HERE
                        </td>
                      </tr>
                    </tbody>
                  </table>
                </td>
              </tr>
            </tbody>
          </table>
        )}
      </div>

      <div>
        {user.name && (
          <button
            type="submit"
            style={{
              marginTop: '30px',
              marginBottom: '10px',
              height: '45px',
              width: '85px',
              backgroundColor: '#1d71a5',
              color: '#fff',
              border: 'none',
              borderRadius: '5px',
              fontSize: '16px',
              cursor: 'pointer',
            }}
            onClick={copyToClipboard}
          >
            Copy
          </button>
        )}
        {copySuccess && (
          <div style={{ color: 'green' }}> ✔︎ Copy with Sucess! </div>
        )}
      </div>
    </div>
  );
};

Preview.propTypes = {
  user: PropTypes.isRequired,
};

export default Preview;

Eu não fiz a pesquisa, mas se você está procurando uma solução entre navegadores para colocar outras coisas além de texto na área de transferência, tenho certeza de que algumas bibliotecas o cobriram.

Você já pode imaginar como o truque de mágica funciona agora que você viu algum código?

Isso mesmo; o truque é baseado em diferentes tipos MIME de conteúdo. Campos de entrada e áreas de texto lidam bem com texto simples colado, mas obviamente existem outros tipos MIME disponíveis.

Uma prancheta pode conter tipos de image/gif, image/jpeg, text/rtf, o bom e velho text/html, e todos os tipos de fantasia.

E graças à API da área de transferência, você controla o tipo MIME e pode até armazenar texto e imagens na mesma operação de gravação.

E não é apenas uma única operação; é até mesmo uma única entrada na área de transferência .

avigator.clipboard.write([
  new ClipboardItem({
    'text/plain': new Blob(["That's some cool plain text, isn't it?"], {
      type: 'text/plain',
    }),
    'text/html': new Blob(
      [
        '<div style="/* some styles */">Oh yeah - text/html!</div>',
      ],
      {
        type: 'text/html',
      }
    ),
  }),
]);