@12-apps/ui 6.96.2 → 6.97.1
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/dist/_internal/components/data-display/DataViews/DataViewsGrid.js +12 -12
- package/dist/_internal/components/data-display/DataViews/DataViewsTableBase.js +13 -13
- package/dist/_internal/components/data-display/DataViews/data-views-filter-panel.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-grid-parts.js +11 -11
- package/dist/_internal/components/data-display/DataViews/data-views-inline-bar.js +9 -9
- package/dist/_internal/components/data-display/DataViews/data-views-more-fields.js +7 -7
- package/dist/_internal/components/data-display/DataViews/data-views-more-filters.js +8 -8
- package/dist/_internal/components/data-display/DataViews/data-views-range-bounds.js +5 -5
- package/dist/_internal/components/data-display/DataViews/data-views-range-calendar.js +4 -4
- package/dist/_internal/components/data-display/DataViews/data-views-range-pill.js +6 -6
- package/dist/_internal/components/form/Calendar/Calendar.js +3 -3
- package/dist/_internal/components/form/Calendar/CalendarMonth.js +1 -1
- package/dist/_internal/components/form/Calendar/CalendarSelectorsMonth.js +2 -2
- package/dist/_internal/components/form/CepField/CepField.js +1 -1
- package/dist/_internal/components/form/DateRangePicker/DateRangePicker.js +4 -4
- package/dist/_internal/components/form/index.js +5 -5
- package/dist/_internal/components/form/total-form/Fields/CepField.js +2 -2
- package/dist/_internal/components/form/total-form/Fields/index.js +3 -3
- package/dist/_internal/components/index.js +5 -5
- package/dist/{chunk-24G3BWKD.js → chunk-3BMG6VMB.js} +2 -2
- package/dist/{chunk-J2GDA64N.js → chunk-3CSKB57B.js} +2 -2
- package/dist/{chunk-RNIJL54W.js → chunk-55MYYWOV.js} +2 -2
- package/dist/{chunk-37SNQQ7P.js → chunk-CQOJUYTT.js} +2 -2
- package/dist/{chunk-C7IFBYIJ.js → chunk-EB25XITI.js} +3 -3
- package/dist/{chunk-OKDKKBLI.js → chunk-F5OERPU4.js} +2 -2
- package/dist/{chunk-VCQFDQM3.js → chunk-G3WG77QY.js} +7 -2
- package/dist/chunk-G3WG77QY.js.map +1 -0
- package/dist/{chunk-KHDKG7XB.js → chunk-GTE4TW3W.js} +2 -2
- package/dist/{chunk-X37NTEVS.js → chunk-HBRBIPNF.js} +2 -2
- package/dist/{chunk-ZPWPA6FR.js → chunk-IS3L67TF.js} +2 -2
- package/dist/{chunk-UTWEHMAP.js → chunk-LYVVXC3J.js} +11 -3
- package/dist/chunk-LYVVXC3J.js.map +1 -0
- package/dist/{chunk-BRFL7OWI.js → chunk-N2J24TJ3.js} +2 -2
- package/dist/{chunk-BMC5KGH2.js → chunk-QWI7IPYJ.js} +3 -3
- package/dist/{chunk-KXVWH3JM.js → chunk-QZRWOF4R.js} +2 -2
- package/dist/{chunk-FYAW5GBF.js → chunk-STOZ6JB5.js} +3 -3
- package/dist/{chunk-XALDXR3F.js → chunk-UIS3E72B.js} +2 -2
- package/dist/{chunk-HRES2S3Q.js → chunk-W3IFJA35.js} +2 -2
- package/dist/data-display/DataViews.js +13 -13
- package/dist/form/Calendar.js +3 -3
- package/dist/form/CepField.js +1 -1
- package/dist/form/DateRangePicker.js +4 -4
- package/dist/form/total-form.js +3 -3
- package/dist/types/components/form/Calendar/CalendarMonth.d.ts +5 -2
- package/dist/types/components/form/Calendar/CalendarMonth.d.ts.map +1 -1
- package/dist/types/components/form/CepField/CepField.d.ts +1 -1
- package/dist/types/components/form/CepField/CepField.d.ts.map +1 -1
- package/dist/types/components/form/CepField/CepField.types.d.ts +9 -0
- package/dist/types/components/form/CepField/CepField.types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/form/Calendar/CalendarMonth.tsx +9 -2
- package/src/components/form/CepField/CepField.md +4 -0
- package/src/components/form/CepField/CepField.tsx +14 -1
- package/src/components/form/CepField/CepField.types.ts +9 -0
- package/dist/chunk-UTWEHMAP.js.map +0 -1
- package/dist/chunk-VCQFDQM3.js.map +0 -1
- /package/dist/{chunk-24G3BWKD.js.map → chunk-3BMG6VMB.js.map} +0 -0
- /package/dist/{chunk-J2GDA64N.js.map → chunk-3CSKB57B.js.map} +0 -0
- /package/dist/{chunk-RNIJL54W.js.map → chunk-55MYYWOV.js.map} +0 -0
- /package/dist/{chunk-37SNQQ7P.js.map → chunk-CQOJUYTT.js.map} +0 -0
- /package/dist/{chunk-C7IFBYIJ.js.map → chunk-EB25XITI.js.map} +0 -0
- /package/dist/{chunk-OKDKKBLI.js.map → chunk-F5OERPU4.js.map} +0 -0
- /package/dist/{chunk-KHDKG7XB.js.map → chunk-GTE4TW3W.js.map} +0 -0
- /package/dist/{chunk-X37NTEVS.js.map → chunk-HBRBIPNF.js.map} +0 -0
- /package/dist/{chunk-ZPWPA6FR.js.map → chunk-IS3L67TF.js.map} +0 -0
- /package/dist/{chunk-BRFL7OWI.js.map → chunk-N2J24TJ3.js.map} +0 -0
- /package/dist/{chunk-BMC5KGH2.js.map → chunk-QWI7IPYJ.js.map} +0 -0
- /package/dist/{chunk-KXVWH3JM.js.map → chunk-QZRWOF4R.js.map} +0 -0
- /package/dist/{chunk-FYAW5GBF.js.map → chunk-STOZ6JB5.js.map} +0 -0
- /package/dist/{chunk-XALDXR3F.js.map → chunk-UIS3E72B.js.map} +0 -0
- /package/dist/{chunk-HRES2S3Q.js.map → chunk-W3IFJA35.js.map} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CepField.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/CepField/CepField.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD;;GAEG;AAEH;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAExE,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,IAAI,EAAE,YAAY,CAAC;IACnB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACvD;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACpC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"CepField.types.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/CepField/CepField.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AACrD;;GAEG;AAEH;;;;;;;;;GASG;AACH,MAAM,WAAW,UAAU;IACzB,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,2CAA2C;IAC3C,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,cAAc;IACd,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,iBAAiB;IACjB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,UAAU;IACV,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,oEAAoE;AACpE,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,CAAC;AAExE,MAAM,WAAW,aAAa;IAC5B,6DAA6D;IAC7D,IAAI,EAAE,YAAY,CAAC;IACnB,8EAA8E;IAC9E,KAAK,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACvD;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,KAAK,IAAI,CAAC;IAC3C;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,wCAAwC;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,uEAAuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,6DAA6D;IAC7D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;;OAQG;IACH,cAAc,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IACpC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;OAOG;IACH,gBAAgB,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;CACvC"}
|
package/package.json
CHANGED
|
@@ -7,7 +7,8 @@ import type { FC } from 'react';
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
|
|
9
9
|
import type { CalendarLabels } from '../../../copy/labels';
|
|
10
|
-
import {
|
|
10
|
+
import type { Theme } from '@mui/material/styles/index.js';
|
|
11
|
+
import { rem, sxRem } from '../../../tokens/relative';
|
|
11
12
|
|
|
12
13
|
import { getMonthName } from './Calendar.dates';
|
|
13
14
|
import type { CalendarProps, MonthMatrix } from './Calendar.types';
|
|
@@ -35,8 +36,14 @@ const GRID_SX = {
|
|
|
35
36
|
* (304 design px: what 7 × 40 cells and 6 × 4 gaps came to before the gaps
|
|
36
37
|
* went, FUT-4162). Months side by side keep a 280 basis,
|
|
37
38
|
* so a multi-month calendar still wraps rather than squeezing every month.
|
|
39
|
+
* The basis is a theme callback: `sxRem` interpolated into the string wrote a
|
|
40
|
+
* function's source, and Emotion's whole `flex` was dropped (FUT-4486).
|
|
38
41
|
*/
|
|
39
|
-
export const MONTH_SX = {
|
|
42
|
+
export const MONTH_SX = {
|
|
43
|
+
flex: (theme: Theme) => `1 1 ${rem(theme, 280)}`,
|
|
44
|
+
minWidth: 0,
|
|
45
|
+
maxWidth: sxRem(304),
|
|
46
|
+
} as const;
|
|
40
47
|
|
|
41
48
|
/** The two arrows' accessible names; an icon alone names nothing. */
|
|
42
49
|
export type MonthArrowLabels = Pick<CalendarLabels, 'previousMonth' | 'nextMonth'>;
|
|
@@ -52,6 +52,10 @@ serves a supplier form, a store-location form or a delivery checkout.
|
|
|
52
52
|
form for somebody else's address (a supplier), or the browser offers the signed-in
|
|
53
53
|
person's own CEP and the lookup then fills their street (FUT-4140). Same prop on
|
|
54
54
|
`Fields.CepField`
|
|
55
|
+
- `passwordManagers`: `offer` (default) or `ignore`. `ignore` puts `data-lpignore`,
|
|
56
|
+
`data-1p-ignore` and `data-bwignore` on the `<input>`, so LastPass, 1Password and
|
|
57
|
+
Bitwarden stop drawing their icon in a lone CEP box they read as a login field
|
|
58
|
+
(FUT-4444). The browser's own `autocomplete` still offers a saved CEP
|
|
55
59
|
|
|
56
60
|
### State Props
|
|
57
61
|
|
|
@@ -121,6 +121,18 @@ function CepStatus({
|
|
|
121
121
|
/** What only the `<input>` can act on. Hoisted: one object for every render. */
|
|
122
122
|
const CEP_INPUT_PROPS = { inputMode: 'numeric' } as const;
|
|
123
123
|
|
|
124
|
+
/** The same, plus each password manager's own "not mine" flag (`passwordManagers="ignore"`, FUT-4444). */
|
|
125
|
+
const CEP_INPUT_PROPS_NO_MANAGERS = {
|
|
126
|
+
...CEP_INPUT_PROPS,
|
|
127
|
+
'data-lpignore': 'true',
|
|
128
|
+
'data-1p-ignore': 'true',
|
|
129
|
+
'data-bwignore': 'true',
|
|
130
|
+
} as const;
|
|
131
|
+
|
|
132
|
+
/** The `<input>`'s own props: the keypad always, the managers' flags only when asked (`offer` is the default). */
|
|
133
|
+
const inputPropsOf = (passwordManagers: 'offer' | 'ignore' | undefined) =>
|
|
134
|
+
passwordManagers === 'ignore' ? CEP_INPUT_PROPS_NO_MANAGERS : CEP_INPUT_PROPS;
|
|
135
|
+
|
|
124
136
|
/** `postal-code` unless the caller said otherwise (`off` for somebody else's address). */
|
|
125
137
|
const autoCompleteOf = (autoComplete: string | undefined): string => autoComplete ?? 'postal-code';
|
|
126
138
|
|
|
@@ -188,6 +200,7 @@ export function CepField({
|
|
|
188
200
|
size, // undefined reaches `Input`, whose own default is `md`
|
|
189
201
|
labelPlacement = 'above',
|
|
190
202
|
autoComplete,
|
|
203
|
+
passwordManagers,
|
|
191
204
|
}: CepFieldProps): React.ReactElement {
|
|
192
205
|
const testId = dataTestId ?? `cep-field-${name}`;
|
|
193
206
|
|
|
@@ -217,7 +230,7 @@ export function CepField({
|
|
|
217
230
|
// prop `Input` does not recognise, so it landed on the wrapper `div`
|
|
218
231
|
// and the phone kept opening the letter keyboard for eight digits
|
|
219
232
|
// (FUT-1440's CepField row).
|
|
220
|
-
inputProps={
|
|
233
|
+
inputProps={inputPropsOf(passwordManagers)}
|
|
221
234
|
autoComplete={autoCompleteOf(autoComplete)}
|
|
222
235
|
size={size}
|
|
223
236
|
// `inside`: the label is the Input's own, drawn in the box and floating
|
|
@@ -97,4 +97,13 @@ export interface CepFieldProps {
|
|
|
97
97
|
* (FUT-4140).
|
|
98
98
|
*/
|
|
99
99
|
autoComplete?: string;
|
|
100
|
+
/**
|
|
101
|
+
* Whether password managers may treat the box as theirs. `offer` (default)
|
|
102
|
+
* leaves them alone, as the field always has. `ignore` marks the `<input>`
|
|
103
|
+
* with `data-lpignore`, `data-1p-ignore` and `data-bwignore`, so LastPass,
|
|
104
|
+
* 1Password and Bitwarden keep their icon and fill out of a lone CEP box that
|
|
105
|
+
* their heuristics read as a login field (FUT-4444). The browser's own
|
|
106
|
+
* `autocomplete` is untouched: a saved CEP is still offered.
|
|
107
|
+
*/
|
|
108
|
+
passwordManagers?: 'offer' | 'ignore';
|
|
100
109
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/form/CepField/CepField.tsx"],"sourcesContent":["'use client';\n\nimport type { CepFieldCopy } from \"../../../copy\";\nimport React, { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { cepDigits, formatCep, isValidCep } from '@12-apps/forms-core';\n\nimport { FormControl, FormLabel, FormMessage } from '../Form';\n// The outlined entry: CepField renders no variant, and the generic one would\n// ship MUI's FilledInput and Input to every screen with a CEP field (FUT-1054).\nimport { Input } from '../Input/outlined';\nimport type { CepAddress, CepFieldProps, CepLookupStatus } from './CepField.types';\n\n/** Everything {@link useCepLookup} needs, so the hook signature stays flat. */\ninterface LookupOptions {\n digits: string;\n complete: boolean;\n disabled: boolean;\n debounceMs: number;\n onLookup?: (cep: string) => Promise<CepAddress | null>;\n onResolved?: (address: CepAddress) => void;\n onNotFound?: () => void;\n}\n\n/**\n * Debounced, race-safe CEP resolution.\n *\n * Two guards earn their keep here: a monotonic sequence id, bumped\n * synchronously on every new query, so a slow response for a since-edited CEP\n * can never land; and a \"last queried\" marker, so re-rendering (or the caller\n * re-masking the same value) never re-hits the provider.\n */\nfunction useCepLookup({\n digits,\n complete,\n disabled,\n debounceMs,\n onLookup,\n onResolved,\n onNotFound,\n}: LookupOptions): CepLookupStatus {\n const [status, setStatus] = useState<CepLookupStatus>('idle');\n const lastQueriedRef = useRef('');\n const seqRef = useRef(0);\n // Latest callbacks, read at call time — keeps them out of the effect deps so\n // an inline arrow from the caller doesn't re-trigger the lookup every render.\n const lookupRef = useRef(onLookup);\n const resolvedRef = useRef(onResolved);\n const notFoundRef = useRef(onNotFound);\n lookupRef.current = onLookup;\n resolvedRef.current = onResolved;\n notFoundRef.current = onNotFound;\n\n useEffect(() => {\n if (!complete || disabled || !lookupRef.current) {\n // Editing away from a complete CEP drops any stale status and forgets the\n // last query, so re-typing the same CEP resolves again.\n seqRef.current += 1;\n setStatus('idle');\n lastQueriedRef.current = '';\n return;\n }\n if (lastQueriedRef.current === digits) return;\n\n const mySeq = (seqRef.current += 1);\n const handle = setTimeout(() => {\n lastQueriedRef.current = digits;\n setStatus('loading');\n void (async () => {\n // A failing lookup is treated exactly like \"not found\" — the user types\n // the address instead. Never surfaced as a crash. Going through\n // `Promise.resolve().then` rather than calling directly covers the two\n // failure modes an `await … .catch()` misses: a lookup that throws\n // SYNCHRONOUSLY, and one that returns something other than a promise.\n const address = await Promise.resolve()\n .then(() => lookupRef.current?.(digits))\n .catch(() => null);\n if (seqRef.current !== mySeq) return;\n setStatus(address ? 'found' : 'notfound');\n // A miss is reported too, so a caller that filled from a PREVIOUS CEP\n // can undo it rather than leaving that address under this CEP.\n if (address) resolvedRef.current?.(address);\n else notFoundRef.current?.();\n })();\n }, debounceMs);\n\n return () => clearTimeout(handle);\n }, [digits, complete, disabled, debounceMs]);\n\n return status;\n}\n\n/**\n * The lookup outcome as a live region, so screen readers announce it without\n * stealing focus. Silent while idle, and while the caller is showing its own\n * validation error (which would otherwise stack two messages).\n */\nfunction CepStatus({\n status,\n testId,\n suppressed,\n copy,\n}: {\n status: CepLookupStatus;\n testId: string;\n suppressed: boolean;\n copy: CepFieldCopy;\n}): React.ReactElement {\n const visible = !suppressed && status !== 'idle';\n return (\n <span id={`${testId}-status`} role=\"status\" aria-live=\"polite\">\n {visible && (\n <FormMessage error={status === 'notfound'} dataTestId={`${testId}-${status}`}>\n {copy[status as Exclude<CepLookupStatus, 'idle'>]}\n </FormMessage>\n )}\n </span>\n );\n}\n\n/** What only the `<input>` can act on. Hoisted: one object for every render. */\nconst CEP_INPUT_PROPS = { inputMode: 'numeric' } as const;\n\n/** `postal-code` unless the caller said otherwise (`off` for somebody else's address). */\nconst autoCompleteOf = (autoComplete: string | undefined): string => autoComplete ?? 'postal-code';\n\n/** The stacked label over the box (`labelPlacement=\"above\"`), or nothing when there is no label. */\nfunction AboveLabel({\n name,\n label,\n error,\n}: {\n name: string;\n label?: string;\n error?: string;\n}): React.ReactElement | null {\n if (!label) return null;\n return (\n <FormLabel htmlFor={name} error={Boolean(error)}>\n {label}\n </FormLabel>\n );\n}\n\n/** The label handed to the `Input`, which draws it in the box: only for `inside`. */\nfunction insideLabel(label: string | undefined, placement: 'above' | 'inside'): string | undefined {\n return placement === 'inside' ? label : undefined;\n}\n\n/**\n * A CEP input that fills the rest of the address in.\n *\n * The pattern every Brazilian form has used for twenty years: type eight\n * digits, and logradouro/bairro/cidade/UF arrive on their own. This is the\n * reusable half — masking, validation, debouncing, race-safety and status —\n * with the actual lookup injected via `onLookup`, so the same component serves\n * a supplier form, a store-location form or a delivery checkout without\n * knowing anything about providers or auth.\n *\n * Resolution is best-effort by design. A provider outage, an unknown CEP or a\n * timeout leaves the field exactly as usable as a plain text input — the user\n * types the address themselves. Autofill never blocks.\n *\n * @example\n * ```tsx\n * <CepField\n * value={cep}\n * onChange={setCep}\n * onLookup={(c) => fetch(`/api/…/lookup/cep/${c}`).then((r) => r.json()).then((b) => b.data)}\n * onResolved={(a) => { setStreet(a.street ?? ''); setCity(a.city ?? ''); }}\n * />\n * ```\n */\nexport function CepField({\n value,\n onChange,\n onLookup,\n onResolved,\n onNotFound,\n label = 'CEP',\n placeholder = '00000-000',\n error,\n disabled = false,\n debounceMs = 500,\n name = 'postalCode',\n dataTestId,\n copy,\n size, // undefined reaches `Input`, whose own default is `md`\n labelPlacement = 'above',\n autoComplete,\n}: CepFieldProps): React.ReactElement {\n const testId = dataTestId ?? `cep-field-${name}`;\n\n const status = useCepLookup({\n digits: cepDigits(value),\n complete: isValidCep(value),\n disabled,\n debounceMs,\n onLookup,\n onResolved,\n onNotFound,\n });\n\n const handleChange = useCallback(\n (event: React.ChangeEvent<HTMLInputElement>) => onChange(formatCep(event.target.value)),\n [onChange],\n );\n\n return (\n <FormControl fullWidth>\n {labelPlacement === 'above' && <AboveLabel name={name} label={label} error={error} />}\n <Input\n id={name}\n name={name}\n type=\"text\"\n // On the `<input>`, through `inputProps`: a top-level `inputMode` is a\n // prop `Input` does not recognise, so it landed on the wrapper `div`\n // and the phone kept opening the letter keyboard for eight digits\n // (FUT-1440's CepField row).\n inputProps={CEP_INPUT_PROPS}\n autoComplete={autoCompleteOf(autoComplete)}\n size={size}\n // `inside`: the label is the Input's own, drawn in the box and floating\n // up on focus or a value — what every other `Input` in the form does.\n // `above` keeps the stacked `FormLabel`, for callers that never opted in.\n label={insideLabel(label, labelPlacement)}\n placeholder={placeholder}\n value={value}\n error={Boolean(error)}\n disabled={disabled}\n loading={status === 'loading'}\n onChange={handleChange}\n data-testid={testId}\n aria-describedby={`${testId}-status`}\n aria-busy={status === 'loading'}\n />\n {error && (\n <FormMessage error dataTestId={`${testId}-message`}>\n {error}\n </FormMessage>\n )}\n <CepStatus status={status} testId={testId} suppressed={Boolean(error)} copy={copy} />\n </FormControl>\n );\n}\n\nexport default CepField;\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/components/form/Calendar/CalendarMonth.tsx"],"sourcesContent":["import ChevronLeft from '@mui/icons-material/ChevronLeft';\nimport ChevronRight from '@mui/icons-material/ChevronRight';\nimport Box from '@mui/material/Box/index.js';\nimport IconButton from '@mui/material/IconButton/index.js';\nimport Typography from '@mui/material/Typography/index.js';\nimport type { FC } from 'react';\nimport React from 'react';\n\nimport type { CalendarLabels } from '../../../copy/labels';\nimport { sxRem } from '../../../tokens/relative';\n\nimport { getMonthName } from './Calendar.dates';\nimport type { CalendarProps, MonthMatrix } from './Calendar.types';\nimport type { DayCellContext } from './CalendarDayCell';\nimport { CalendarDayCell } from './CalendarDayCell';\n\n/** The nav spacer's width and the weekday row's height, 32 design px through the type scale. */\nconst SPACER_WIDTH = sxRem(32);\n\n// `minmax(0, 1fr)`, not `1fr`: a bare `1fr` keeps each column at least its\n// content's width, which is what held the grid at 304px (FUT-3861). No column\n// gap: a selected range is one band across the days, and a gap cut it into\n// tiles (FUT-4162). Rows keep theirs. Items centre in their column: the built-in\n// day stretches across it, a host's `renderDay` cell sits in its middle.\nconst GRID_SX = {\n display: 'grid',\n justifyItems: 'center',\n gridTemplateColumns: 'repeat(7, minmax(0, 1fr))',\n columnGap: 0,\n rowGap: 0.5,\n} as const;\n\n/**\n * A month takes the room it is given, from nothing up to seven full columns\n * (304 design px: what 7 × 40 cells and 6 × 4 gaps came to before the gaps\n * went, FUT-4162). Months side by side keep a 280 basis,\n * so a multi-month calendar still wraps rather than squeezing every month.\n */\nexport const MONTH_SX = { flex: `1 1 ${sxRem(280)}`, minWidth: 0, maxWidth: sxRem(304) } as const;\n\n/** The two arrows' accessible names; an icon alone names nothing. */\nexport type MonthArrowLabels = Pick<CalendarLabels, 'previousMonth' | 'nextMonth'>;\n\n// Only the outermost months carry arrows; the ones between get a spacer so their\n// titles stay centred.\nconst MonthNavHeader: FC<{\n title: React.ReactNode;\n showPrevious: boolean;\n showNext: boolean;\n labels?: MonthArrowLabels;\n onPreviousMonth: () => void;\n onNextMonth: () => void;\n}> = ({ title, showPrevious, showNext, labels, onPreviousMonth, onNextMonth }) => (\n <Box\n sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', mb: 2 }}\n data-testid=\"calendar-header\"\n >\n {showPrevious && (\n <IconButton\n onClick={onPreviousMonth}\n size=\"small\"\n aria-label={labels?.previousMonth}\n data-testid=\"calendar-prev-month\"\n >\n <ChevronLeft />\n </IconButton>\n )}\n\n <Typography\n variant=\"h6\"\n component=\"h2\"\n sx={{ fontWeight: 'bold', flex: 1, textAlign: 'center' }}\n >\n {title}\n </Typography>\n\n {showNext && (\n <IconButton\n onClick={onNextMonth}\n size=\"small\"\n aria-label={labels?.nextMonth}\n data-testid=\"calendar-next-month\"\n >\n <ChevronRight />\n </IconButton>\n )}\n\n {!showPrevious && !showNext && <Box sx={{ width: SPACER_WIDTH }} />}\n </Box>\n);\n\nconst WeekdayHeader: FC<{ weekdayNames: string[] }> = ({ weekdayNames }) => (\n <Box sx={{ ...GRID_SX, mb: 1 }}>\n {weekdayNames.map((weekday, index) => (\n <Box\n // Narrow weekday names repeat within a week ('S', 'T'), so position is\n // the only stable key here.\n key={`weekday-${index}`}\n role=\"columnheader\"\n data-testid={`calendar-weekday-${index}`}\n sx={{\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n height: SPACER_WIDTH,\n fontSize: sxRem(14),\n fontWeight: 'bold',\n color: 'text.secondary',\n }}\n >\n {weekday}\n </Box>\n ))}\n </Box>\n);\n\n/** The weekday row and the day grid under a month's caption. */\nexport const MonthDays: FC<{\n matrix: MonthMatrix;\n monthIndex: number;\n weekdayNames: string[];\n dayContext: DayCellContext;\n}> = ({ matrix, weekdayNames, dayContext }) => (\n <>\n <WeekdayHeader weekdayNames={weekdayNames} />\n\n <Box\n role=\"grid\"\n // Named by its month in words. It pointed at an id nothing carried, so\n // the grid had no name at all and a two-month calendar read as two\n // anonymous grids.\n aria-label={getMonthName(matrix.month, matrix.year, dayContext.locale)}\n data-testid=\"calendar-grid\"\n sx={GRID_SX}\n >\n {matrix.weeks.flat().map((day) => (\n <CalendarDayCell key={day.key} day={day} {...dayContext} />\n ))}\n </Box>\n </>\n);\n\nexport interface CalendarMonthProps {\n matrix: MonthMatrix;\n monthIndex: number;\n monthsToShow: number;\n locale: string;\n weekdayNames: string[];\n renderHeader?: CalendarProps['renderHeader'];\n /** The arrows' accessible names. */\n labels?: MonthArrowLabels;\n onPreviousMonth: () => void;\n onNextMonth: () => void;\n dayContext: DayCellContext;\n}\n\nexport const CalendarMonth: FC<CalendarMonthProps> = ({\n matrix,\n monthIndex,\n monthsToShow,\n locale,\n weekdayNames,\n renderHeader,\n labels,\n onPreviousMonth,\n onNextMonth,\n dayContext,\n}) => {\n const monthName = getMonthName(matrix.month, matrix.year, locale);\n const title = renderHeader ? renderHeader({ month: matrix.month, year: matrix.year }) : monthName;\n\n return (\n /* The month is addressable by its position, because in a multi-month\n calendar every day number appears once PER MONTH — `calendar-date-5` is\n January's 5th and February's. Without a per-month hook a test can only\n reach a day positionally, which is exactly what the flakiness gate\n refuses. Additive: `calendar-grid` below is unchanged. */\n <Box sx={MONTH_SX} data-testid={`calendar-month-${monthIndex}`}>\n <MonthNavHeader\n title={title}\n showPrevious={monthIndex === 0}\n showNext={monthIndex === monthsToShow - 1}\n labels={labels}\n onPreviousMonth={onPreviousMonth}\n onNextMonth={onNextMonth}\n />\n\n <MonthDays\n matrix={matrix}\n monthIndex={monthIndex}\n weekdayNames={weekdayNames}\n dayContext={dayContext}\n />\n </Box>\n );\n};\n"],"mappings":"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","names":[]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|