@12-apps/payments-frontend 3.10.0 → 3.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/card/copy.ts +14 -0
- package/src/card/fields.tsx +1 -1
- package/src/card/format.ts +3 -3
- package/src/card/pt-BR.ts +3 -0
- package/src/components/ConnectionCard.tsx +1 -1
- package/src/components/ProviderSetupGuide.tsx +3 -1
- package/src/components/settings-copy.ts +8 -0
- package/src/components/settings-pt-BR.ts +3 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@12-apps/payments-frontend",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Browser half of the vendor-agnostic payments platform: plug-and-play MUI components for the per-provider settings page (credential form from each provider's schema, masked hints, verify/enable) and the checkout page (PIX QR + polling, card tokenization, hosted-checkout redirect), plus the headless hooks and fetch clients they build on. Talks only to the host's payments HTTP surface — never to a provider directly. Microfrontend-ready: no app coupling, host injects theme and auth.",
|
|
6
6
|
"exports": {
|
package/src/card/copy.ts
CHANGED
|
@@ -42,6 +42,12 @@ export interface CardFieldCopy {
|
|
|
42
42
|
*/
|
|
43
43
|
expiryLabel: string;
|
|
44
44
|
cvvLabel: string;
|
|
45
|
+
/**
|
|
46
|
+
* The expiry field holds something that is not yet `MM/AA` at all — too few
|
|
47
|
+
* digits, or the wrong shape. Distinct from {@link monthInvalid}, which is a
|
|
48
|
+
* well-formed date with an impossible month.
|
|
49
|
+
*/
|
|
50
|
+
expiryIncomplete: string;
|
|
45
51
|
/** A month outside 1–12 — a typo, not an expiry. */
|
|
46
52
|
monthInvalid: string;
|
|
47
53
|
/** A well-formed date that has already passed. */
|
|
@@ -51,6 +57,8 @@ export interface CardFieldCopy {
|
|
|
51
57
|
* the expiry as one string and only learns it is unusable.
|
|
52
58
|
*/
|
|
53
59
|
expiryInvalid: string;
|
|
60
|
+
/** No CVV typed at all — distinct from one of the wrong length. */
|
|
61
|
+
cvvRequired: string;
|
|
54
62
|
cvvInvalid: string;
|
|
55
63
|
/**
|
|
56
64
|
* The CVV is the wrong length for the detected network — Amex wants four,
|
|
@@ -64,6 +72,12 @@ export interface CardFieldCopy {
|
|
|
64
72
|
cpfInvalid: string;
|
|
65
73
|
/** The saved-cards radio group's own label. */
|
|
66
74
|
savedCardsLabel: string;
|
|
75
|
+
/**
|
|
76
|
+
* A saved card's second line — the expiry, already zero-padded and split
|
|
77
|
+
* into month and year. The WORD in front of it is this host's; the order it
|
|
78
|
+
* reads in is the same order {@link expiryLabel} promised.
|
|
79
|
+
*/
|
|
80
|
+
savedCardExpiry(month: string, year: number): string;
|
|
67
81
|
/** The trailing option that opens the new-card form. */
|
|
68
82
|
newCard: string;
|
|
69
83
|
newCardDescription: string;
|
package/src/card/fields.tsx
CHANGED
|
@@ -41,7 +41,7 @@ export function SavedCardsPicker({
|
|
|
41
41
|
...savedCards.map((saved) => ({
|
|
42
42
|
value: saved.id,
|
|
43
43
|
label: `${saved.brand} •••• ${saved.last4}`,
|
|
44
|
-
description:
|
|
44
|
+
description: copy.savedCardExpiry(String(saved.expMonth).padStart(2, "0"), saved.expYear),
|
|
45
45
|
})),
|
|
46
46
|
{ value: NEW_CARD, label: copy.newCard, description: copy.newCardDescription },
|
|
47
47
|
]}
|
package/src/card/format.ts
CHANGED
|
@@ -97,10 +97,10 @@ export function validateExpiry(
|
|
|
97
97
|
now: Date = new Date(),
|
|
98
98
|
): string | undefined {
|
|
99
99
|
const match = /^(\d{2})\/(\d{2})$/.exec(value.trim());
|
|
100
|
-
if (!match) return
|
|
100
|
+
if (!match) return copy.expiryIncomplete;
|
|
101
101
|
const mm = match[1];
|
|
102
102
|
const yy = match[2];
|
|
103
|
-
if (mm === undefined || yy === undefined) return
|
|
103
|
+
if (mm === undefined || yy === undefined) return copy.expiryIncomplete;
|
|
104
104
|
const month = Number(mm);
|
|
105
105
|
if (month < 1 || month > 12) return copy.monthInvalid;
|
|
106
106
|
const endOfMonth = new Date(2000 + Number(yy), month, 0, 23, 59, 59, 999);
|
|
@@ -113,7 +113,7 @@ export function validateCvv(
|
|
|
113
113
|
brand: CardBrand = "Unknown",
|
|
114
114
|
): string | undefined {
|
|
115
115
|
const digits = onlyDigits(value);
|
|
116
|
-
if (!digits) return
|
|
116
|
+
if (!digits) return copy.cvvRequired;
|
|
117
117
|
const len = cvvLength(brand);
|
|
118
118
|
return digits.length === len ? undefined : copy.cvvDigits(len);
|
|
119
119
|
}
|
package/src/card/pt-BR.ts
CHANGED
|
@@ -20,14 +20,17 @@ export const PT_BR_CARD_COPY: CardCopy = {
|
|
|
20
20
|
holderRequired: 'Informe o nome impresso no cartão.',
|
|
21
21
|
expiryLabel: 'Validade (MM/AA)',
|
|
22
22
|
cvvLabel: 'CVV',
|
|
23
|
+
expiryIncomplete: 'Validade incompleta (MM/AA).',
|
|
23
24
|
monthInvalid: 'Mês inválido.',
|
|
24
25
|
expired: 'Cartão expirado.',
|
|
25
26
|
expiryInvalid: 'Validade inválida ou expirada.',
|
|
27
|
+
cvvRequired: 'Informe o CVV.',
|
|
26
28
|
cvvInvalid: 'CVV inválido.',
|
|
27
29
|
cvvDigits: (length) => `CVV deve ter ${length} dígitos.`,
|
|
28
30
|
cpfRequired: 'CPF obrigatório.',
|
|
29
31
|
cpfInvalid: 'CPF inválido.',
|
|
30
32
|
savedCardsLabel: 'Cartão',
|
|
33
|
+
savedCardExpiry: (month, year) => `Validade ${month}/${year}`,
|
|
31
34
|
newCard: 'Novo cartão',
|
|
32
35
|
newCardDescription: 'Inserir outro cartão',
|
|
33
36
|
saveCard: 'Salvar cartão para próximas compras',
|
|
@@ -219,7 +219,7 @@ export function DisconnectDialog(props: {
|
|
|
219
219
|
{props.busy ? <CircularProgress size={18} sx={{ color: '#fff' }} /> : copy.removeAction}
|
|
220
220
|
</Button>
|
|
221
221
|
<Button fullWidth onClick={props.onCancel} disabled={props.busy} sx={LINKISH_SX}>
|
|
222
|
-
|
|
222
|
+
{copy.cancel}
|
|
223
223
|
</Button>
|
|
224
224
|
</DialogActions>
|
|
225
225
|
</Dialog>
|
|
@@ -31,6 +31,7 @@ import {
|
|
|
31
31
|
} from './panel-tokens';
|
|
32
32
|
|
|
33
33
|
import { richText } from './rich-text';
|
|
34
|
+
import { usePaymentsSettingsCopy } from './settings-copy-context';
|
|
34
35
|
|
|
35
36
|
/**
|
|
36
37
|
* Renders a provider's step-by-step onboarding walkthrough — the reusable
|
|
@@ -104,6 +105,7 @@ function CopyField({
|
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
function CopyRow({ label, text }: { label: string; text: string }) {
|
|
108
|
+
const copy = usePaymentsSettingsCopy().setupGuide;
|
|
107
109
|
const [copied, setCopied] = useState(false);
|
|
108
110
|
return (
|
|
109
111
|
<Stack direction="row" spacing={1} alignItems="center" sx={{ width: '100%' }}>
|
|
@@ -114,7 +116,7 @@ function CopyRow({ label, text }: { label: string; text: string }) {
|
|
|
114
116
|
*/}
|
|
115
117
|
<TextField fullWidth size="small" disabled value={text} />
|
|
116
118
|
<IconButton
|
|
117
|
-
aria-label={copied ?
|
|
119
|
+
aria-label={copied ? copy.copied : copy.copyValue(label)}
|
|
118
120
|
onClick={() => {
|
|
119
121
|
void navigator.clipboard.writeText(text).then(() => setCopied(true));
|
|
120
122
|
}}
|
|
@@ -176,6 +176,8 @@ export interface ConnectionCardCopy {
|
|
|
176
176
|
* taking orders — the offer that makes the destructive button safe to show.
|
|
177
177
|
*/
|
|
178
178
|
pauseInstead: string;
|
|
179
|
+
/** The dialog's plain dismiss, under the two offers above. */
|
|
180
|
+
cancel: string;
|
|
179
181
|
}
|
|
180
182
|
|
|
181
183
|
/** The credential form: its fields, its probe, and what it says while testing. */
|
|
@@ -287,6 +289,12 @@ export interface SetupGuideCopy {
|
|
|
287
289
|
confirmedByYou: string;
|
|
288
290
|
/** Reopen a section the owner already confirmed. */
|
|
289
291
|
reviewAction: string;
|
|
292
|
+
/**
|
|
293
|
+
* The copy-to-clipboard button beside a reference value, and what it says
|
|
294
|
+
* for the two seconds after a successful copy.
|
|
295
|
+
*/
|
|
296
|
+
copyValue(fieldLabel: string): string;
|
|
297
|
+
copied: string;
|
|
290
298
|
}
|
|
291
299
|
|
|
292
300
|
/** The whole settings surface, in one object a host passes at the mount. */
|
|
@@ -108,6 +108,7 @@ export const PT_BR_PAYMENTS_SETTINGS_COPY: PaymentsSettingsCopy = {
|
|
|
108
108
|
`Pagamentos já aprovados e estornos em andamento seguem normalmente pelo ${displayName}.`,
|
|
109
109
|
removeRestartsSetup: 'Para reconectar, os passos recomeçam do zero.',
|
|
110
110
|
pauseInstead: 'Só pausar o recebimento',
|
|
111
|
+
cancel: 'Cancelar',
|
|
111
112
|
},
|
|
112
113
|
credentials: {
|
|
113
114
|
configuredKeepBlank: 'Configurado — deixe em branco para manter o valor atual.',
|
|
@@ -165,5 +166,7 @@ export const PT_BR_PAYMENTS_SETTINGS_COPY: PaymentsSettingsCopy = {
|
|
|
165
166
|
defaultConfirmLabel: 'Já habilitei o Checkout Integrado',
|
|
166
167
|
confirmedByYou: 'Confirmado por você',
|
|
167
168
|
reviewAction: 'Revisar',
|
|
169
|
+
copyValue: (fieldLabel) => `Copiar ${fieldLabel}`,
|
|
170
|
+
copied: 'Copiado',
|
|
168
171
|
},
|
|
169
172
|
};
|