@12-apps/ui 6.96.2 → 6.97.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.
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  CepField,
4
4
  CepField_default
5
- } from "../../../../chunk-UTWEHMAP.js";
5
+ } from "../../../../chunk-LYVVXC3J.js";
6
6
  import "../../../../chunk-WGKBZ7DN.js";
7
7
  import "../../../../chunk-ASBFGGJB.js";
8
8
  import "../../../../chunk-PD7MKJCM.js";
@@ -116,7 +116,7 @@ import "../../../chunk-JXS56EW5.js";
116
116
  import "../../../chunk-6XLMTOJ3.js";
117
117
  import {
118
118
  CepField
119
- } from "../../../chunk-UTWEHMAP.js";
119
+ } from "../../../chunk-LYVVXC3J.js";
120
120
  import "../../../chunk-WGKBZ7DN.js";
121
121
  import "../../../chunk-IDMG332I.js";
122
122
  import {
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
  import {
3
3
  CepField
4
- } from "../../../../../chunk-KXVWH3JM.js";
4
+ } from "../../../../../chunk-QZRWOF4R.js";
5
5
  import "../../../../../chunk-4XK6JQ4D.js";
6
6
  import "../../../../../chunk-6XLMTOJ3.js";
7
- import "../../../../../chunk-UTWEHMAP.js";
7
+ import "../../../../../chunk-LYVVXC3J.js";
8
8
  import "../../../../../chunk-WGKBZ7DN.js";
9
9
  import "../../../../../chunk-ASBFGGJB.js";
10
10
  import "../../../../../chunk-PD7MKJCM.js";
@@ -1,4 +1,4 @@
1
- import "../../../../../chunk-BRFL7OWI.js";
1
+ import "../../../../../chunk-N2J24TJ3.js";
2
2
  import {
3
3
  ToggleField
4
4
  } from "../../../../../chunk-RLTYBV4N.js";
@@ -10,7 +10,7 @@ import {
10
10
  } from "../../../../../chunk-6YSGP2WS.js";
11
11
  import {
12
12
  CepField
13
- } from "../../../../../chunk-KXVWH3JM.js";
13
+ } from "../../../../../chunk-QZRWOF4R.js";
14
14
  import {
15
15
  CategoryField
16
16
  } from "../../../../../chunk-6AKDAQSS.js";
@@ -24,7 +24,7 @@ import "../../../../../chunk-OQW4OERS.js";
24
24
  import "../../../../../chunk-6VTOGR36.js";
25
25
  import "../../../../../chunk-IYC7NPX7.js";
26
26
  import "../../../../../chunk-6XLMTOJ3.js";
27
- import "../../../../../chunk-UTWEHMAP.js";
27
+ import "../../../../../chunk-LYVVXC3J.js";
28
28
  import "../../../../../chunk-WGKBZ7DN.js";
29
29
  import "../../../../../chunk-QYKDY4EI.js";
30
30
  import "../../../../../chunk-ZJY7OK6H.js";
@@ -346,7 +346,7 @@ import "../../chunk-JXS56EW5.js";
346
346
  import "../../chunk-6XLMTOJ3.js";
347
347
  import {
348
348
  CepField
349
- } from "../../chunk-UTWEHMAP.js";
349
+ } from "../../chunk-LYVVXC3J.js";
350
350
  import "../../chunk-WGKBZ7DN.js";
351
351
  import "../../chunk-IDMG332I.js";
352
352
  import {
@@ -63,6 +63,13 @@ function CepStatus({
63
63
  return /* @__PURE__ */ jsx("span", { id: `${testId}-status`, role: "status", "aria-live": "polite", children: visible && /* @__PURE__ */ jsx(FormMessage, { error: status === "notfound", dataTestId: `${testId}-${status}`, children: copy[status] }) });
64
64
  }
65
65
  var CEP_INPUT_PROPS = { inputMode: "numeric" };
66
+ var CEP_INPUT_PROPS_NO_MANAGERS = {
67
+ ...CEP_INPUT_PROPS,
68
+ "data-lpignore": "true",
69
+ "data-1p-ignore": "true",
70
+ "data-bwignore": "true"
71
+ };
72
+ var inputPropsOf = (passwordManagers) => passwordManagers === "ignore" ? CEP_INPUT_PROPS_NO_MANAGERS : CEP_INPUT_PROPS;
66
73
  var autoCompleteOf = (autoComplete) => autoComplete ?? "postal-code";
67
74
  function AboveLabel({
68
75
  name,
@@ -92,7 +99,8 @@ function CepField({
92
99
  size,
93
100
  // undefined reaches `Input`, whose own default is `md`
94
101
  labelPlacement = "above",
95
- autoComplete
102
+ autoComplete,
103
+ passwordManagers
96
104
  }) {
97
105
  const testId = dataTestId ?? `cep-field-${name}`;
98
106
  const status = useCepLookup({
@@ -116,7 +124,7 @@ function CepField({
116
124
  id: name,
117
125
  name,
118
126
  type: "text",
119
- inputProps: CEP_INPUT_PROPS,
127
+ inputProps: inputPropsOf(passwordManagers),
120
128
  autoComplete: autoCompleteOf(autoComplete),
121
129
  size,
122
130
  label: insideLabel(label, labelPlacement),
@@ -141,4 +149,4 @@ export {
141
149
  CepField,
142
150
  CepField_default
143
151
  };
144
- //# sourceMappingURL=chunk-UTWEHMAP.js.map
152
+ //# sourceMappingURL=chunk-LYVVXC3J.js.map
@@ -0,0 +1 @@
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/** The same, plus each password manager's own \"not mine\" flag (`passwordManagers=\"ignore\"`, FUT-4444). */\nconst CEP_INPUT_PROPS_NO_MANAGERS = {\n ...CEP_INPUT_PROPS,\n 'data-lpignore': 'true',\n 'data-1p-ignore': 'true',\n 'data-bwignore': 'true',\n} as const;\n\n/** The `<input>`'s own props: the keypad always, the managers' flags only when asked (`offer` is the default). */\nconst inputPropsOf = (passwordManagers: 'offer' | 'ignore' | undefined) =>\n passwordManagers === 'ignore' ? CEP_INPUT_PROPS_NO_MANAGERS : CEP_INPUT_PROPS;\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 passwordManagers,\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={inputPropsOf(passwordManagers)}\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":[]}
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-6YSGP2WS.js";
10
10
  import {
11
11
  CepField
12
- } from "./chunk-KXVWH3JM.js";
12
+ } from "./chunk-QZRWOF4R.js";
13
13
  import {
14
14
  CategoryField
15
15
  } from "./chunk-6AKDAQSS.js";
@@ -30,4 +30,4 @@ __export(Fields_exports, {
30
30
  export {
31
31
  Fields_exports
32
32
  };
33
- //# sourceMappingURL=chunk-BRFL7OWI.js.map
33
+ //# sourceMappingURL=chunk-N2J24TJ3.js.map
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-4XK6JQ4D.js";
4
4
  import {
5
5
  CepField
6
- } from "./chunk-UTWEHMAP.js";
6
+ } from "./chunk-LYVVXC3J.js";
7
7
 
8
8
  // src/components/form/total-form/Fields/CepField.tsx
9
9
  import { useCallback, useMemo, useRef } from "react";
@@ -86,4 +86,4 @@ function CepField2({
86
86
  export {
87
87
  CepField2 as CepField
88
88
  };
89
- //# sourceMappingURL=chunk-KXVWH3JM.js.map
89
+ //# sourceMappingURL=chunk-QZRWOF4R.js.map
@@ -1,7 +1,7 @@
1
1
  import "../chunk-6XLMTOJ3.js";
2
2
  import {
3
3
  CepField
4
- } from "../chunk-UTWEHMAP.js";
4
+ } from "../chunk-LYVVXC3J.js";
5
5
  import "../chunk-WGKBZ7DN.js";
6
6
  import "../chunk-ASBFGGJB.js";
7
7
  import "../chunk-PD7MKJCM.js";
@@ -9,7 +9,7 @@ import {
9
9
  } from "../chunk-CPAJYJUD.js";
10
10
  import {
11
11
  Fields_exports
12
- } from "../chunk-BRFL7OWI.js";
12
+ } from "../chunk-N2J24TJ3.js";
13
13
  import "../chunk-RLTYBV4N.js";
14
14
  import {
15
15
  TextField
@@ -17,7 +17,7 @@ import {
17
17
  import {
18
18
  SelectField
19
19
  } from "../chunk-6YSGP2WS.js";
20
- import "../chunk-KXVWH3JM.js";
20
+ import "../chunk-QZRWOF4R.js";
21
21
  import {
22
22
  CategoryField
23
23
  } from "../chunk-6AKDAQSS.js";
@@ -34,7 +34,7 @@ import "../chunk-OQW4OERS.js";
34
34
  import "../chunk-6VTOGR36.js";
35
35
  import "../chunk-IYC7NPX7.js";
36
36
  import "../chunk-6XLMTOJ3.js";
37
- import "../chunk-UTWEHMAP.js";
37
+ import "../chunk-LYVVXC3J.js";
38
38
  import "../chunk-WGKBZ7DN.js";
39
39
  import "../chunk-JD5BVIM7.js";
40
40
  import "../chunk-T77OVQEO.js";
@@ -25,6 +25,6 @@ import type { CepFieldProps } from './CepField.types';
25
25
  * ```
26
26
  */
27
27
  export declare function CepField({ value, onChange, onLookup, onResolved, onNotFound, label, placeholder, error, disabled, debounceMs, name, dataTestId, copy, size, // undefined reaches `Input`, whose own default is `md`
28
- labelPlacement, autoComplete, }: CepFieldProps): React.ReactElement;
28
+ labelPlacement, autoComplete, passwordManagers, }: CepFieldProps): React.ReactElement;
29
29
  export default CepField;
30
30
  //# sourceMappingURL=CepField.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CepField.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/CepField/CepField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAQxE,OAAO,KAAK,EAAc,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AA0InF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,EACV,KAAa,EACb,WAAyB,EACzB,KAAK,EACL,QAAgB,EAChB,UAAgB,EAChB,IAAmB,EACnB,UAAU,EACV,IAAI,EACJ,IAAI,EAAE,uDAAuD;AAC7D,cAAwB,EACxB,YAAY,GACb,EAAE,aAAa,GAAG,KAAK,CAAC,YAAY,CAsDpC;AAED,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"CepField.d.ts","sourceRoot":"","sources":["../../../../../src/components/form/CepField/CepField.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAmD,MAAM,OAAO,CAAC;AAQxE,OAAO,KAAK,EAAc,aAAa,EAAmB,MAAM,kBAAkB,CAAC;AAsJnF;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,QAAQ,CAAC,EACvB,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,EACV,KAAa,EACb,WAAyB,EACzB,KAAK,EACL,QAAgB,EAChB,UAAgB,EAChB,IAAmB,EACnB,UAAU,EACV,IAAI,EACJ,IAAI,EAAE,uDAAuD;AAC7D,cAAwB,EACxB,YAAY,EACZ,gBAAgB,GACjB,EAAE,aAAa,GAAG,KAAK,CAAC,YAAY,CAsDpC;AAED,eAAe,QAAQ,CAAC"}
@@ -94,5 +94,14 @@ export interface CepFieldProps {
94
94
  * (FUT-4140).
95
95
  */
96
96
  autoComplete?: string;
97
+ /**
98
+ * Whether password managers may treat the box as theirs. `offer` (default)
99
+ * leaves them alone, as the field always has. `ignore` marks the `<input>`
100
+ * with `data-lpignore`, `data-1p-ignore` and `data-bwignore`, so LastPass,
101
+ * 1Password and Bitwarden keep their icon and fill out of a lone CEP box that
102
+ * their heuristics read as a login field (FUT-4444). The browser's own
103
+ * `autocomplete` is untouched: a saved CEP is still offered.
104
+ */
105
+ passwordManagers?: 'offer' | 'ignore';
97
106
  }
98
107
  //# sourceMappingURL=CepField.types.d.ts.map
@@ -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;CACvB"}
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@12-apps/ui",
3
- "version": "6.96.2",
3
+ "version": "6.97.0",
4
4
  "license": "MIT",
5
5
  "packageManager": "pnpm@10.34.5",
6
6
  "type": "module",
@@ -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={CEP_INPUT_PROPS}
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":[]}