Assinaturas ReactJS e Email com suas particularidades
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> <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> </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',
}
),
}),
]);




































![O que é uma lista vinculada, afinal? [Parte 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)