Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 47 additions & 7 deletions example/src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ import {
BrazilMaskComponent,
BrazilValidateComponent
} from 'react-brazil'
import { maskBr } from 'js-brasil'

import { DATA, DATAERROR } from './utils';
import { DATA, DATAERROR, GENERATORS } from './utils';

const FORMATS = ['cpf', 'cnpj', 'cep', 'rg', 'telefone', 'placa', 'renavam', 'titulo', 'time', 'currency']
const FORMATS = ['cpf', 'cnpj', 'cep', 'rg', 'telefone', 'placa', 'renavam', 'titulo', 'time', 'currency', 'pispasep']

const css = {
page: { maxWidth: 860, margin: '0 auto', padding: '24px 16px', fontFamily: 'sans-serif' },
Expand Down Expand Up @@ -37,24 +38,37 @@ const inputStyle = {
fontSize: 14,
}

const btnStyle = {
padding: '7px 18px',
background: '#0969da',
color: '#fff',
border: 'none',
borderRadius: 6,
fontWeight: 600,
fontSize: 14,
cursor: 'pointer',
}

// ValidatedRow uses a key from the parent to remount with fresh initialValue on regenerate
class ValidatedRow extends Component {
constructor(props) {
super(props)
this.state = { value: DATA[props.format] || '' }
const raw = props.initialValue || ''
const formatted = maskBr[props.format] ? maskBr[props.format](raw) : raw
this.state = { value: formatted }
}

render() {
const { format } = this.props
const { value } = this.state
// treat as empty when only mask placeholders remain (underscores)
const empty = !value || value.replace(/[_]/g, '').replace(/[^a-zA-Z0-9]/g, '').trim() === ''

return (
<tr>
<td style={css.td}><code>{format}</code></td>
<td style={css.td}>
<BrazilMaskComponent
defaultValue={DATA[format] || ''}
defaultValue={value}
format={format}
style={inputStyle}
onChange={e => this.setState({ value: e.target.value })}
Expand All @@ -79,16 +93,36 @@ class ValidatedRow extends Component {
}

export default class App extends Component {
constructor(props) {
super(props)
const values = {}
FORMATS.forEach(f => { values[f] = DATA[f] || '' })
this.state = { epoch: 0, values }
}

regenerate() {
const values = {}
FORMATS.forEach(f => {
values[f] = GENERATORS[f] ? GENERATORS[f]() : (DATA[f] || '')
})
this.setState(s => ({ epoch: s.epoch + 1, values }))
}

render() {
const { epoch, values } = this.state
return (
<div style={css.page}>
<h1>React Brazil</h1>
<div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', marginBottom: 8 }}>
<h1 style={{ margin: 0 }}>React Brazil</h1>
<button style={btnStyle} onClick={() => this.regenerate()}>Regenerate</button>
</div>

{/* ── MASK + LIVE VALIDATE ── */}
<h2>Mask &amp; Validate</h2>
<p style={{ color: '#555', marginBottom: 16 }}>
Inputs use <code>BrazilMaskComponent</code> pre-filled with example values.
Edit any field to see <code>BrazilValidateComponent</code> update in real time.
Click <strong>Regenerate</strong> to fill all inputs with new random valid values.
</p>
<table style={css.table}>
<thead>
Expand All @@ -99,7 +133,13 @@ export default class App extends Component {
</tr>
</thead>
<tbody>
{FORMATS.map(f => <ValidatedRow key={f} format={f} />)}
{FORMATS.map(f => (
<ValidatedRow
key={f + '-' + epoch}
format={f}
initialValue={values[f]}
/>
))}
</tbody>
</table>

Expand Down
120 changes: 107 additions & 13 deletions example/src/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,18 +38,11 @@ export const DATA = {
number: '1.234,56',
time: '06:33',
placa: 'ADJ-5468',
titulo: '2053.9588.0310'
renavam: '12345678900',
titulo: '123456780698',
pispasep: '12345678919'
}

// const rawIE = {};
// const rawIEError = {};
// for (const key in DATA.inscricaoestadual) {
// if (!key) {
// continue;
// }
// rawIE[key] = DATA.inscricaoestadual[key].replace(/\./g, '').replace(/\-/g, '').replace(/\//g, '').replace(/ /g, '');
// rawIEError[key] = rawIE[key] + '6';
// }
export const DATARAW = {
cpf: '15663188150',
cnpj: '40841253000102',
Expand Down Expand Up @@ -90,7 +83,9 @@ export const DATARAW = {
number: '1234,56',
time: '0633',
placa: 'ADJ5468',
titulo: '205395880384'
renavam: '12345678900',
titulo: '123456780698',
pispasep: '12345678919'
}


Expand Down Expand Up @@ -133,11 +128,110 @@ export const DATAERROR = {
number: '1000.10',
time: '0633',
placa: 'AEJ123',
titulo: '205395880384'
renavam: '12345678901',
titulo: '123456780699',
pispasep: '12345678918'
}


export const estados = ['ac', 'al', 'am', 'ap', 'ba', 'ce', 'df', 'es', 'go', 'ma',
'mg', 'ms', 'mt', 'pa', 'pb', 'pe', 'pi', 'pr', 'rj', 'rn', 'ro', 'rr', 'rs',
'sc', 'se', 'sp', 'to'
];
];

// ── Random valid-value generators ────────────────────────────────────────────

function rndDigits(n) {
return Array.from({ length: n }, () => Math.floor(Math.random() * 10)).join('');
}

function modulo11Custom(str, size, maxMult) {
for (let n = 0; n < size; n++) {
let soma = 0, mult = 2;
for (let i = str.length - 1; i >= 0; i--) {
soma += mult * parseInt(str[i]);
mult = mult >= maxMult ? 2 : mult + 1;
}
str += ((soma * 10) % 11) % 10;
}
return str;
}

export const GENERATORS = {
cpf() {
return modulo11Custom(rndDigits(9), 2, 12);
},
cnpj() {
const base = rndDigits(8) + '0001';
function check(s) {
let soma = 0, pos = s.length - 7;
for (let i = s.length; i >= 1; i--) {
soma += parseInt(s[s.length - i]) * pos--;
if (pos < 2) pos = 9;
}
return soma % 11 < 2 ? 0 : 11 - soma % 11;
}
const d1 = check(base);
return base + d1 + check(base + d1);
},
cep() {
return rndDigits(8);
},
rg() {
const states = ['MG', 'SP', 'RJ', 'RS', 'PR', 'SC', 'BA', 'GO'];
const state = states[Math.floor(Math.random() * states.length)];
return state + rndDigits(8);
},
telefone() {
const ddds = ['11', '21', '31', '41', '51', '61', '71', '81', '85', '91'];
const ddd = ddds[Math.floor(Math.random() * ddds.length)];
return ddd + '9' + rndDigits(8);
},
placa() {
const L = () => String.fromCharCode(65 + Math.floor(Math.random() * 26));
return L() + L() + L() + rndDigits(4);
},
renavam() {
const base = rndDigits(10);
const weights = [3, 2, 9, 8, 7, 6, 5, 4, 3, 2];
let sum = 0;
for (let i = 0; i < 10; i++) sum += parseInt(base[i]) * weights[i];
sum *= 10;
const dv = sum % 11 === 10 ? 0 : sum % 11;
return base + dv;
},
titulo() {
const seq = rndDigits(8);
const estado = String(1 + Math.floor(Math.random() * 27)).padStart(2, '0');
const padded = ('0' + seq + estado).split('').map(Number);
const exce = parseInt(estado) <= 2;
let dig1 = (padded[0]*2 + padded[1]*9 + padded[2]*8 + padded[3]*7 + padded[4]*6 +
padded[5]*5 + padded[6]*4 + padded[7]*3 + padded[8]*2) % 11;
if (dig1 === 0) dig1 = exce ? 1 : 0;
else if (dig1 === 1) dig1 = 0;
else dig1 = 11 - dig1;
let dig2 = (padded[9]*4 + padded[10]*3 + dig1*2) % 11;
if (dig2 === 0) dig2 = exce ? 1 : 0;
else if (dig2 === 1) dig2 = 0;
else dig2 = 11 - dig2;
return seq + estado + dig1 + dig2;
},
time() {
return String(Math.floor(Math.random() * 24)).padStart(2, '0') + ':' +
String(Math.floor(Math.random() * 60)).padStart(2, '0');
},
currency() {
const intPart = Math.floor(Math.random() * 99999) + 1;
const decPart = Math.floor(Math.random() * 100);
return intPart + ',' + String(decPart).padStart(2, '0');
},
pispasep() {
const base = rndDigits(10);
let d = 0, p = 2;
for (let c = 9; c >= 0; c--) {
d += parseInt(base[c]) * p;
p = p < 9 ? p + 1 : 2;
}
return base + ((10 * d) % 11) % 10;
},
};
Loading