@dloizides/ui-forms 1.18.1 → 1.18.3

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/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/Field/attachControlId.ts","../src/Field/useHtmlFor.ts","../src/Field/FieldLabel.tsx","../src/Field/fieldMarkers.ts","../src/Field/fieldSpacing.ts","../src/Field/labelVariants.ts","../src/FormGrid/formGridContext.ts","../src/Field/Field.tsx","../src/FormGrid/FormGrid.tsx","../src/FormGrid/FormCell.tsx","../src/FormSection/FormSection.tsx","../src/FormActions/FormActions.tsx","../src/controls/controlStyles.ts","../src/AnchoredMenu/menuPortal.ts","../src/AnchoredMenu/AnchoredMenu.tsx","../src/useThemedInput/useThemedInput.ts","../src/webFieldA11y/webFieldA11y.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/useRecentValues/recentValuesCore.ts","../src/useRecentValues/useRecentValues.ts","../src/FormField/RecentInputField.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/constants.ts","../src/ChipSelector/components/chipStyles.ts","../src/ChipSelector/components/ChipContent.tsx","../src/ChipSelector/components/OutlineChip.tsx","../src/ChipSelector/components/SolidChip.tsx","../src/ChipSelector/utils/radioKeyboard.ts","../src/ChipSelector/hooks/useRadioKeyboard.ts","../src/ChipSelector/utils/chipColors.ts","../src/ChipSelector/utils/chipIdentity.ts","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx","../src/SelectControl/SelectControl.tsx","../src/controls/suggestOptions.ts","../src/TypeaheadControl/TypeaheadControl.tsx","../src/DateRangeControl/DateRangeControl.tsx","../src/groupSelection/groupSelection.ts"],"names":["React","Platform","useRef","useEffect","IS_WEB","jsxs","Text","jsx","StyleSheet","useUi","View","styles","Button","MIN_TOUCH_TARGET_PX","Z_INDEX","MENU_TOP_GAP","useState","useLayoutEffect","ScrollView","Pressable","createPortal","useCallback","useMemo","ThemedTextInput","TextInput","TouchableOpacity","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","DESCRIPTION_FONT_SIZE","Switch","HINT_FONT_SIZE","CLOSE_DELAY_MS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Give a `Field`'s plain-node child the `id` its `<label for>` points at.\n *\n * ## Why cloning rather than asking the caller\n *\n * `Field`'s documented, overwhelmingly common shape is a plain child:\n *\n * ```tsx\n * <Field label={FM('guides.titleLabel')}>\n * <ThemedTextInput … />\n * </Field>\n * ```\n *\n * There is no seam in that shape to hand an id through — which is exactly why label association\n * was never wired and why a live audit found 0 controls with an `id` across an entire CMS page.\n * The alternatives were worse: making every call site switch to the render-function form is a\n * fleet-wide migration that fails open (any missed call site silently keeps the old behaviour),\n * and wrapping the control inside the `<label>` element for implicit association breaks down on\n * the controls that are not native form elements — a `SelectControl` trigger is a\n * `<div role=\"button\">`, and nesting it in a `<label>` invites a double-fire on click.\n *\n * So the id is injected here, one level deep, and only when it is safe to do so.\n *\n * ## What \"safe\" means\n *\n * - Only a single valid element is touched. Arrays, strings and `null` are returned untouched,\n * because there is no unambiguous \"the control\" to point a label at. A **fragment** is excluded\n * explicitly: `React.isValidElement` says yes to one, but a fragment accepts no props beyond\n * `key`, so cloning an `id` onto it both warns in development and attaches nothing.\n * - A child that already carries an `id` keeps it. The caller was explicit; a label that silently\n * retargets someone else's id is worse than no label.\n * - The returned `controlId` is what the label should actually use: `undefined` when nothing was\n * attached, so `FieldLabel` emits no dangling `htmlFor` pointing at an element that does not\n * exist. A `<label for>` aimed at nothing is not a smaller bug than no label — it is a lie that\n * passes a \"has a label\" check.\n */\nimport React from 'react';\n\n/** Props any RN component may carry that we read or write here. `id` is RN ≥0.71 → DOM `id`. */\ninterface IdentifiableProps {\n id?: string;\n nativeID?: string;\n /** The kit's own contract for `aria-describedby`, honoured by `ThemedTextInput`/`ChipSelector`. */\n describedById?: string;\n}\n\nexport interface AttachedControl {\n /** The child, cloned with the field wiring when it could be attached; otherwise the original. */\n node: React.ReactNode;\n /** The id the label should target, or `undefined` when nothing could safely receive one. */\n controlId?: string;\n}\n\n/**\n * Returns the child wired to its `Field`, plus the id the label should point at.\n *\n * `candidateId` is only USED when it can be attached — the caller must not assume it was.\n *\n * `describedById` is injected too, under the kit's own `describedById` prop name, so the hint and\n * error lines are announced by a plain child exactly as they are by a render-function child. That\n * they were NOT was a real gap: a YouTube field made read-only with an on-screen sentence saying\n * why gave a screen-reader user the read-only state and none of the explanation.\n *\n * A child that is not a kit control simply ignores the prop; if it needs different wiring, use\n * the render-function form, which hands over the ids and lets the caller place them.\n */\nexport function attachControlId(\n child: React.ReactNode,\n candidateId: string,\n describedById?: string,\n): AttachedControl {\n if (!React.isValidElement(child) || child.type === React.Fragment) {\n return { node: child };\n }\n\n const props = child.props as IdentifiableProps;\n const existing = props.id ?? props.nativeID;\n const element = child as React.ReactElement<IdentifiableProps>;\n\n // An explicit id from the caller is never overwritten — but the description wiring still goes\n // on, because that is the field's to give and the caller expressed no opinion about it.\n const controlId = existing !== undefined && existing !== '' ? existing : candidateId;\n const injected: IdentifiableProps = { id: controlId };\n\n if (describedById !== undefined && props.describedById === undefined) {\n injected.describedById = describedById;\n }\n\n return { node: React.cloneElement(element, injected), controlId };\n}\n","/**\n * Put a real `for` attribute on a `<label>` rendered through react-native-web.\n *\n * ## Why this is imperative, which looks like a smell and is not\n *\n * The obvious implementation — pass `htmlFor` to `<Text role=\"label\">` — does not work, and\n * fails SILENTLY. react-native-web filters props through an allowlist (`forwardedProps`), and\n * `htmlFor` is not on it, so the prop is dropped somewhere between the component and the DOM\n * with no warning. This is the same family as the hint that never arrives: `accessibilityHint`\n * has no ARIA equivalent, so RN-web discards it, which is why this kit renders hints as\n * sr-only nodes instead of trusting the prop.\n *\n * That failure mode is the reason this is worth the imperative escape. A prop-level test\n * (`expect(label.props.htmlFor).toBe(id)`) passes against a build where the attribute never\n * reaches the browser. Setting it on the node and asserting `container.querySelector('label')\n * .getAttribute('for')` is the only version that can tell the difference.\n *\n * The alternatives were each worse:\n * - **Implicit association** (nesting the control inside the `<label>`) needs no attribute, but\n * changes the DOM structure of every field in seven portals, and a label wrapping a control\n * that turns out to be activatable is the classic double-fire bug.\n * - **Rendering the label as a raw DOM element** abandons the RN style pipeline, so the label\n * would need a second, hand-maintained styling path that could drift from every other label.\n *\n * Native is a no-op: there is no `<label>` and no DOM, and the association there is already\n * carried by the control's `accessibilityLabel`.\n */\nimport { useEffect, useRef } from 'react';\n\nimport { Platform } from 'react-native';\n\nconst IS_WEB = Platform.OS === 'web';\n\n/** The sliver of the DOM this touches — no `any`, no global DOM lib dependency. */\ninterface AttributeHost {\n setAttribute: (name: string, value: string) => void;\n removeAttribute: (name: string) => void;\n ownerDocument?: { getElementById: (id: string) => unknown } | null;\n}\n\nfunction isAttributeHost(node: unknown): node is AttributeHost {\n return (\n typeof node === 'object' &&\n node !== null &&\n typeof (node as AttributeHost).setAttribute === 'function'\n );\n}\n\n/**\n * Returns a ref to attach to the label element. The `for` attribute is set only when the target\n * it names is genuinely in the document.\n *\n * ## Why the existence check is not paranoia\n *\n * `Field` cannot know whether a render-function child actually placed the id it was handed. The\n * difficulty dropdown is the case that proved it: `SelectControl` is a `<div role=\"button\">` and\n * associates itself the other way round, via `aria-labelledby`, so nothing ever received\n * `controlId` — and the label emitted `for=\"field-control-3\"` pointing at nothing. Measured on a\n * real page, that produced a label that LOOKED correct in every audit (`<label>`: yes, `for`:\n * yes) and focused nothing when clicked.\n *\n * Trusting the caller here means the guarantee holds only as long as every call site remembers.\n * Checking the document makes it hold by construction, for both the injected and the\n * render-function paths, without either having to declare which one it is.\n *\n * It runs in an effect rather than in the ref callback because the check needs the whole\n * committed tree present — the control is a LATER sibling than its label, so at ref time the\n * answer would depend on commit ordering rather than on the truth.\n */\nexport function useHtmlFor(controlId?: string): React.RefObject<unknown> {\n const ref = useRef<unknown>(null);\n\n useEffect(() => {\n const node = ref.current;\n\n if (!IS_WEB || !isAttributeHost(node)) return;\n\n const target = controlId !== undefined && controlId !== '' ? node.ownerDocument?.getElementById(controlId) : null;\n\n // No target, or a target that is not in the document: emit nothing. A `for` pointing at a\n // missing element passes every \"does this page have labels?\" check while doing nothing.\n if (target === null || target === undefined) {\n node.removeAttribute('for');\n return;\n }\n\n node.setAttribute('for', controlId as string);\n }, [controlId]);\n\n return ref;\n}\n","/**\n * `FieldLabel` — the label row of a `Field`: the label text plus at most one marker.\n *\n * Split out of `Field` so the marker rules and the two label voices stay readable, and so `Field`\n * itself remains an orchestrator small enough to review.\n *\n * ## Why this is a real `<label>` on web\n *\n * It used to render a plain `<Text>`, i.e. a `<div>`. Controls still ANNOUNCED correctly, because\n * every one of them carries an `accessibilityLabel` → `aria-label`, so an audit of screen-reader\n * naming came back clean and the gap looked like it did not exist. What was missing was the other\n * half of a label: **clicking the words did not focus the field**. A page measured live had 0\n * `<label>` elements, 0 `label[for]` and 0 controls with an `id` — every field silently throwing\n * away a free doubling of its own hit area, on top of already being under the target-size floor.\n *\n * `role=\"label\"` is react-native-web's documented escape to a real `<label>` element (it is\n * special-cased ahead of the ARIA role map, since `label` is not an ARIA role). The `for`\n * attribute is set on the node itself — see `useHtmlFor` for why the obvious `htmlFor` prop is\n * silently discarded. On native both are inert: RN has no `<label>`, and the association there\n * is already carried by `accessibilityLabel`.\n *\n * The control keeps its `aria-label`, which still WINS for the accessible name — so this adds\n * click-to-focus without changing a single screen-reader announcement.\n */\nimport React from 'react';\n\nimport { Platform, Text, type StyleProp, type TextProps, type TextStyle } from 'react-native';\n\nimport { useHtmlFor } from './useHtmlFor';\n\nimport type { FieldMarker } from './fieldMarkers';\n\nconst IS_WEB = Platform.OS === 'web';\n\n/**\n * `label` is not an ARIA role, so RN's `role` union does not admit it; react-native-web\n * special-cases it into a real `<label>` element. Cast at the spread site through the host's own\n * props rather than through `any`.\n */\ninterface WebLabelProps {\n role?: 'label';\n}\n\nexport interface FieldLabelProps {\n label: string;\n marker: FieldMarker;\n /** Pre-localized text for the optional marker. Ignored unless `marker` is `optional`. */\n optionalLabel: string;\n /**\n * `id` of the control this label names. Emits `<label for>` on web so clicking the label text\n * focuses the field. Omitted when the field wraps a control that cannot be labelled that way\n * (a `<div role=\"button\">` select trigger), which uses `aria-labelledby` instead.\n */\n controlId?: string;\n /** `id` given to the label element itself, so a non-labelable control can point back at it. */\n labelId?: string;\n /** Composed style chain: base → variant → caller's `labelStyle` (applied last). */\n style: StyleProp<TextStyle>;\n requiredMarkStyle: StyleProp<TextStyle>;\n optionalMarkStyle: StyleProp<TextStyle>;\n}\n\nexport function FieldLabel({\n label,\n marker,\n optionalLabel,\n controlId,\n labelId,\n style,\n requiredMarkStyle,\n optionalMarkStyle,\n}: FieldLabelProps): React.ReactElement {\n const webProps = (IS_WEB ? { role: 'label' } : {}) as WebLabelProps as TextProps;\n const labelRef = useHtmlFor(controlId);\n\n return (\n <Text id={labelId} ref={labelRef as React.Ref<Text>} style={style} {...webProps}>\n {label}{' '}\n {marker === 'required' ? (\n // The asterisk is decorative — the control's `aria-required` conveys \"required\" to\n // assistive tech, so a screen reader says \"required\" instead of \"star\".\n <Text aria-hidden accessibilityElementsHidden importantForAccessibility=\"no\" style={requiredMarkStyle}>\n *\n </Text>\n ) : null}\n {marker === 'optional' && optionalLabel !== '' ? (\n // Also decorative: \"optional\" is the ABSENCE of `aria-required`, which assistive tech\n // already conveys. Rendering it to a screen reader would double-announce the same fact.\n <Text aria-hidden accessibilityElementsHidden importantForAccessibility=\"no\" style={optionalMarkStyle}>\n {optionalLabel}\n </Text>\n ) : null}\n </Text>\n );\n}\n\nexport default FieldLabel;\n","/**\n * Required / optional markers, per the shared forms contract\n * (`…/wwwroot/shared/FORMS.md` → \"Required and optional markers\").\n *\n * The contract says the two markers are MUTUALLY EXCLUSIVE — a field is required or optional, never\n * annotated as both — and that you mark the MINORITY: on a mostly-required form mark the optional\n * fields, on a mostly-optional form mark the required ones. Asterisking twelve of thirteen fields\n * is noise that trains the eye to ignore the marker.\n *\n * Exclusivity is enforced here rather than in the type system so that a caller spreading a props\n * object (`<Field {...fieldProps} />`, where both flags may be computed) still gets a defined,\n * single-marker result instead of a compile error it cannot act on.\n *\n * Precedence when a caller asks for BOTH: `required` wins. That is the safe failure direction —\n * showing \"optional\" on a field the server will reject sends the user into a failed submit, while\n * showing \"required\" on a genuinely optional field costs, at worst, an unnecessary keystroke.\n */\n\n/** Which marker a field label carries. Exactly one, never both. */\nexport type FieldMarker = 'none' | 'required' | 'optional';\n\n/**\n * The English fallback for the optional marker's text.\n *\n * `@dloizides/ui-forms` contains NO i18n runtime by design — aml-v2 uses `@dloizides/i18n` with\n * positional `{0}` params while the other six apps use i18next `{{p1}}`, and nothing bridges them,\n * so all user-visible copy arrives as pre-localized props. This constant exists ONLY so a\n * single-locale app can adopt `optional` in one line. It is exported precisely so it is greppable:\n * **a localized app MUST pass `optionalLabel`.** The required marker needs no such escape — `*` is\n * a glyph, not copy.\n */\nexport const DEFAULT_OPTIONAL_LABEL = '(optional)';\n\n/**\n * Resolve the two boolean flags to the single marker actually rendered.\n * `required` beats `optional`; neither flag yields `none`.\n */\nexport function resolveFieldMarker(required: boolean, optional: boolean): FieldMarker {\n if (required) return 'required';\n if (optional) return 'optional';\n return 'none';\n}\n","/**\n * `Field`'s TWO spacing models — the F3 fix, shipped as an OPT-IN rather than a breaking change.\n *\n * ## The defect\n *\n * `Field` hard-coded a 16px bottom margin on its container and 4px margins on its label / hint /\n * error. That is the pre-flexbox model: the CHILD owns the space after itself. In a `gap`-laid-out\n * parent — which is how every modern form row in this fleet is written — the child's margin STACKS\n * on the parent's gap, so the consumer has to cancel it by hand. aml-v2 alone carries 13\n * `marginBottom: 0` cancels, each with an apologetic comment; the fleet carries 16.\n *\n * AML v1 got this right in CSS: `.ui-field { display: flex; flex-direction: column; gap: 6px; }` —\n * internal gap only, and the parent grid owns the space BETWEEN fields. That contract is written up\n * in `PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md` (\"The gap is owned by the container,\n * never by margins on the children\").\n *\n * ## Why opt-in and not a 2.0.0\n *\n * Switching every `Field` to the gap model at once moves pixels on every form in seven portals in a\n * single publish — which is exactly the change you cannot visually QA, because there is no app you\n * can look at that is still on the old behaviour to compare against. The two models are therefore\n * both implemented, selected per field:\n *\n * - `stack` (DEFAULT) — the historical margins, byte-identical to 1.8.0. Every existing consumer\n * is untouched, including the 16 that currently cancel the margin.\n * - `gap` — the FORMS.md contract: no bottom margin at all, uniform 6px internal gap. The parent\n * owns the rhythm.\n *\n * A `Field` inside a `FormGrid` resolves to `gap` automatically, so adopting the shared grid IS the\n * opt-in — the consumer deletes its hand-rolled `grid`/`field` styles and its margin cancel in the\n * same edit, and the fleet migrates one app at a time behind visual QA.\n */\nimport { StyleSheet, type TextStyle, type ViewStyle } from 'react-native';\n\n/**\n * Which spacing model a field speaks.\n *\n * A plain string union rather than a `const enum` for the same reason as `FieldLabelVariant`: this\n * type crosses the package boundary into consumers' `.d.ts`, and a cross-boundary `const enum`\n * breaks `isolatedModules` / Babel-only builds.\n */\nexport type FieldSpacing = 'stack' | 'gap';\n\n/** The historical bottom margin of a whole field block. Load-bearing for every un-migrated form. */\nexport const FIELD_STACK_MARGIN_BOTTOM = 16;\n/** The historical label→control margin. */\nexport const FIELD_STACK_LABEL_MARGIN_BOTTOM = 4;\n/** The historical control→hint and hint→error margin. */\nexport const FIELD_STACK_CHILD_MARGIN_TOP = 4;\n/** FORMS.md: one uniform gap between label, control, hint and error. Not four separate margins. */\nexport const FIELD_CONTRACT_GAP = 6;\n\nexport const fieldSpacingStyles = StyleSheet.create({\n stackContainer: { marginBottom: FIELD_STACK_MARGIN_BOTTOM },\n stackLabel: { marginBottom: FIELD_STACK_LABEL_MARGIN_BOTTOM },\n stackChild: { marginTop: FIELD_STACK_CHILD_MARGIN_TOP },\n /**\n * The gap model sets NO margins — not even zeroed ones. An explicit `marginBottom: 0` here would\n * defeat a caller who legitimately wants to push one field down via `containerStyle`, because\n * `containerStyle` composes AFTER this and a zero is indistinguishable from \"unset\" to a reader.\n */\n gapContainer: { gap: FIELD_CONTRACT_GAP },\n none: {},\n});\n\n/** The style pieces a field applies for one spacing model. */\nexport interface FieldSpacingStyles {\n container: ViewStyle;\n label: TextStyle;\n /** Applied to the hint AND the error — the two lines that sit under the control. */\n child: TextStyle;\n}\n\n/**\n * Resolve the caller's explicit choice against the surrounding grid.\n *\n * Precedence, and why: an EXPLICIT `spacing` prop always wins, so a consumer inside a `FormGrid`\n * that genuinely needs the old margin (a one-off cell that stacks two fields) can say so without\n * leaving the grid. Absent that, a grid means the grid's `gap` owns the rhythm. Absent both, the\n * historical model — the answer that changes nothing.\n */\nexport function resolveFieldSpacing(explicit: FieldSpacing | undefined, insideGrid: boolean): FieldSpacing {\n if (explicit !== undefined) return explicit;\n\n return insideGrid ? 'gap' : 'stack';\n}\n\n/**\n * The style pieces for a resolved model.\n *\n * Exported and pure so `Field` and `ChipSelector` can be proven to resolve IDENTICALLY. They drifted\n * once already — `ChipSelector` grew a `marginBottom: -8` whose comment blamed `Field`'s 16px — and a\n * shared pure function is what makes \"they agree\" a testable claim rather than a convention.\n */\nexport function fieldSpacingStyleSet(spacing: FieldSpacing): FieldSpacingStyles {\n if (spacing === 'gap') {\n return {\n container: fieldSpacingStyles.gapContainer,\n label: fieldSpacingStyles.none,\n child: fieldSpacingStyles.none,\n };\n }\n\n return {\n container: fieldSpacingStyles.stackContainer,\n label: fieldSpacingStyles.stackLabel,\n child: fieldSpacingStyles.stackChild,\n };\n}\n","/**\n * The TWO legitimate label voices, per the shared forms contract\n * (`PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md` → \"The TWO legitimate label voices\").\n *\n * - `field` — 13 / 600 / sentence case. A label that is READ: prose addressed to the person\n * filling the form. This is `Field`'s historical, unchanged default, so every\n * existing consumer renders byte-identically.\n * - `control` — 11 / 700 / UPPERCASE + letter-spacing. A label that is SCANNED: a key over a value\n * in a dense row (filter bars, compact toolbars, pager controls). These are exactly\n * the metrics `@dloizides/ui-tables` forked into its private `FieldShell` because\n * `Field` hard-coded the `field` voice and offered no way out.\n *\n * A THIRD voice is drift, not a variant. Pick the voice from the SURFACE, not the component: every\n * label on one surface uses one voice, and voices are never mixed within a single row.\n *\n * Why a plain string union and not a `const enum`: this type crosses the package boundary into\n * consumers' `.d.ts`, and a cross-boundary `const enum` breaks `isolatedModules` / Babel-only\n * builds. `@dloizides/ui-buttons` sets the same precedent for `ButtonVariant` for the same reason.\n */\nimport { StyleSheet, type TextStyle } from 'react-native';\n\n/** Which of the two contract voices a field label speaks. */\nexport type FieldLabelVariant = 'field' | 'control';\n\n/** The historical `Field` label metrics. Changing these moves pixels in every consumer. */\nconst FIELD_FONT_SIZE = 13;\nconst FIELD_FONT_WEIGHT = '600';\n\n/** The dense-control metrics, taken verbatim from `ui-tables`' `FieldShell` fork so it can retire. */\nconst CONTROL_FONT_SIZE = 11;\nconst CONTROL_FONT_WEIGHT = '700';\nconst CONTROL_LETTER_SPACING = 0.4;\n\nexport const labelVariantStyles = StyleSheet.create({\n field: {\n fontSize: FIELD_FONT_SIZE,\n fontWeight: FIELD_FONT_WEIGHT,\n },\n control: {\n fontSize: CONTROL_FONT_SIZE,\n fontWeight: CONTROL_FONT_WEIGHT,\n letterSpacing: CONTROL_LETTER_SPACING,\n textTransform: 'uppercase',\n },\n});\n\n/**\n * Resolve a variant name to its style. An unknown/absent variant falls back to `field` — the\n * historical default — so a bad value degrades to \"unchanged\" rather than to \"unstyled\".\n */\nexport function resolveLabelVariantStyle(variant?: FieldLabelVariant): TextStyle {\n return variant === 'control' ? labelVariantStyles.control : labelVariantStyles.field;\n}\n","/**\n * The two contexts the layout primitives publish.\n *\n * They are SEPARATE on purpose, because they answer different questions and have different scopes:\n *\n * - `FormGridContext` carries a row's CELL METRICS, so `FormCell` can be written `<FormCell>` at\n * the overwhelmingly common call site and still get the row's `minWidth` / `flexBasis` — the four\n * constants (200 / 220 / 240 / 260) that the fleet re-declares by hand.\n * - `GapOwnedContext` says only \"the vertical rhythm here is owned by a parent's `gap`\". A `Field`\n * that sees it drops its own 16px bottom margin, which is the whole point of F3.\n *\n * Merging them would force `FormSection` — which also spaces with `gap`, and would otherwise\n * recreate the identical double-spacing bug one level up — to publish cell metrics it has no\n * business having. A section is not a row: a `Field` directly inside a section should be full width,\n * not 260px wide.\n *\n * Nothing about gap-ownership is inferable at runtime — RN's `StyleSheet` gives a child no way to\n * ask \"does my parent space me with gap?\" — so it has to be declared. Making the declaration a side\n * effect of using the shared primitives means the correct thing happens without a second opt-in.\n */\nimport React from 'react';\n\n/** Cell metrics a `FormGrid` hands down to its `FormCell` children. */\nexport interface FormGridMetrics {\n /** Below this the cell stops shrinking and the row wraps. */\n minWidth: number;\n /** The cell's ideal width before grow/shrink — its `flexBasis`. */\n basis: number;\n}\n\n/** `null` outside a grid, so `FormCell` can fall back to the package defaults rather than throw. */\nconst FormGridContext = React.createContext<FormGridMetrics | null>(null);\n\n/**\n * `false` — the historical model — unless a primitive above says otherwise. The default is what\n * every un-migrated `Field` in the fleet reads, so it must be the answer that changes nothing.\n */\nconst GapOwnedContext = React.createContext(false);\n\nexport const FormGridProvider = FormGridContext.Provider;\nexport const GapOwnedProvider = GapOwnedContext.Provider;\n\n/** The enclosing grid's cell metrics, or `null` outside a `FormGrid`. */\nexport function useFormGridMetrics(): FormGridMetrics | null {\n return React.useContext(FormGridContext);\n}\n\n/** True when a parent primitive owns this subtree's vertical rhythm with `gap`. */\nexport function useIsGapOwned(): boolean {\n return React.useContext(GapOwnedContext);\n}\n","/**\n * Field — the generic \"label over a control, hint + error under it\" wrapper.\n *\n * `FormField` is hard-wired to a text input, so any NON-text control (a dropdown, a date picker,\n * a chip selector) had no shared way to get a label — and ended up visually misaligned next to\n * its `FormField` siblings: its box started a label-row higher, and it missed the container's\n * bottom margin so wrapped rows lost their vertical rhythm.\n *\n * `Field` is that label row + spacing, control-agnostic. Its metrics are the single source of\n * truth: `FormField` composes `Field` internally, so the two can never drift apart.\n *\n * Children may be a plain node (the common case — just wrap your control) or a render function\n * receiving `{ describedById, hasError }`, so a custom control can wire the hint AND error lines\n * into its own `aria-describedby` / invalid state exactly the way `FormField` does.\n *\n * The anatomy (label → control → hint → error), the two label voices, the mutually-exclusive\n * required/optional markers and the collapsing error slot all implement the shared cross-stack\n * contract in `PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md`.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { attachControlId } from './attachControlId';\nimport { FieldLabel } from './FieldLabel';\nimport { DEFAULT_OPTIONAL_LABEL, resolveFieldMarker } from './fieldMarkers';\nimport { fieldSpacingStyleSet, resolveFieldSpacing, type FieldSpacing } from './fieldSpacing';\nimport { resolveLabelVariantStyle, type FieldLabelVariant } from './labelVariants';\nimport { useIsGapOwned } from '../FormGrid/formGridContext';\n\nconst ERROR_FONT_SIZE = 12;\nconst HINT_FONT_SIZE = 12;\n/** The optional marker drops to normal weight so it reads as an aside inside a 600 label. */\nconst OPTIONAL_MARK_FONT_WEIGHT = '400';\n\n/**\n * The metrics that do NOT depend on the spacing model. Everything positional — the container's\n * bottom margin, the label's bottom margin, the hint/error top margins — moved to `fieldSpacing`,\n * because those are exactly the values the two models disagree about.\n */\nconst styles = StyleSheet.create({\n hintText: {\n fontSize: HINT_FONT_SIZE,\n },\n errorText: {\n fontSize: ERROR_FONT_SIZE,\n },\n optionalMark: {\n fontWeight: OPTIONAL_MARK_FONT_WEIGHT,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n requiredMark: TextStyle;\n optionalMark: TextStyle;\n hintText: TextStyle;\n errorText: TextStyle;\n}\n\n/** What a render-function child receives, so it can mirror `FormField`'s error wiring. */\nexport interface FieldChildContext {\n /**\n * Space-separated ids of the lines describing this control — the hint, the error, or both, in\n * reading order. `undefined` when there is neither. Assign straight to `aria-describedby`.\n */\n describedById?: string;\n hasError: boolean;\n /**\n * `id` this field's `<label for>` points at. Assign it to the control (RN `id` → DOM `id`) and\n * clicking the label text focuses the control — a free doubling of the hit area that every\n * field was throwing away.\n *\n * A plain-node child gets this injected automatically (see below); a render-function child has\n * to place it, because only the caller knows which element inside is the actual control.\n */\n controlId: string;\n /**\n * `id` OF the label element. For a control that `<label for>` cannot address — anything that is\n * not a native form element, e.g. the `<div role=\"button\">` a `SelectControl` trigger renders —\n * point `aria-labelledby` here instead.\n */\n labelId: string;\n}\n\nexport type FieldChildren = React.ReactNode | ((context: FieldChildContext) => React.ReactNode);\n\nexport interface FieldProps {\n /**\n * Label shown above the control. Optional so a control whose label is supplied elsewhere (or\n * which genuinely has none) can still use the shared shell for its error line + spacing: an\n * absent or empty label renders NO label row at all, rather than an empty one that would add a\n * phantom gap and misalign the control against its labelled siblings.\n */\n label?: string;\n children: FieldChildren;\n required?: boolean;\n /**\n * Marks the field explicitly optional. MUTUALLY EXCLUSIVE with `required` — if both are set,\n * `required` wins (the safe direction: an under-marked required field causes a failed submit).\n * Use it to mark the MINORITY: on a mostly-required form, marking the two optional fields is far\n * less noise than asterisking the other eleven.\n */\n optional?: boolean;\n /**\n * Pre-localized text for the optional marker. Defaults to the English `DEFAULT_OPTIONAL_LABEL`\n * so a single-locale app can adopt `optional` in one line; a localized app MUST pass this.\n */\n optionalLabel?: string;\n /**\n * Help line rendered UNDER the control and ABOVE the error — the sentence that stops the user\n * guessing. It coexists with `error` (the hint states the rule, the error says which rule was\n * broken) and both are reachable from the control via `aria-describedby`.\n *\n * Rendering a hint INSIDE the field is the point: as an outside sibling it lands past the\n * container's 16px bottom margin and detaches from the control it explains.\n */\n hint?: string;\n error?: string;\n /**\n * Which of the two contract label voices to speak: `field` (13/600 sentence case — the default,\n * unchanged) or `control` (11/700 uppercase — dense filter bars and toolbars).\n */\n labelVariant?: FieldLabelVariant;\n /**\n * Escape hatch applied AFTER `labelVariant`, for the genuine one-off a variant does not cover.\n * Prefer `labelVariant`: it is the reviewable, named choice, and a bare `labelStyle` is the thing\n * to grep for when auditing label drift.\n */\n labelStyle?: StyleProp<TextStyle>;\n /**\n * `StyleProp` (not a bare `ViewStyle`) so a caller can compose an array — e.g. a base field style\n * plus a `grow` modifier — instead of having to restate a COMPLETE style per variant.\n */\n containerStyle?: StyleProp<ViewStyle>;\n /**\n * Which of the two spacing models this field speaks — see `fieldSpacing.ts`.\n *\n * Leave it unset. Inside a `FormGrid` or `FormSection` it resolves to `gap` (the FORMS.md\n * contract: no bottom margin, the parent's `gap` owns the rhythm); anywhere else it resolves to\n * `stack` (the historical 16px margin, byte-identical to 1.8.0). Set it explicitly only to\n * override that — e.g. a cell inside a grid that genuinely stacks two fields wants `stack`.\n */\n spacing?: FieldSpacing;\n testID?: string;\n}\n\nlet fieldSeq = 0;\n/**\n * Stable-per-instance ids so the label, hint and error lines can be linked to the control via\n * `htmlFor` / `aria-labelledby` / `aria-describedby`. One counter bump per field keeps every id\n * of a field in lockstep.\n */\nexport function useFieldIds(): { hintId: string; errorId: string; controlId: string; labelId: string } {\n const [ids] = React.useState(() => {\n fieldSeq += 1;\n const seq = String(fieldSeq);\n return {\n hintId: `field-hint-${seq}`,\n errorId: `field-error-${seq}`,\n controlId: `field-control-${seq}`,\n labelId: `field-label-${seq}`,\n };\n });\n return ids;\n}\n\n/** Stable-per-instance id so the error line can be linked to the control via aria-describedby. */\nexport function useFieldErrorId(): string {\n return useFieldIds().errorId;\n}\n\n/** True only for a present, non-empty string. */\nfunction isPresent(value?: string): boolean {\n return typeof value === 'string' && value !== '';\n}\n\n/** True only for a present, non-empty error string. */\nexport function hasFieldError(error?: string): boolean {\n return isPresent(error);\n}\n\n/**\n * Join the ids of the lines describing the control, in reading order (hint then error), skipping\n * any that is not rendered. `undefined` — not `''` — when there is nothing, so the attribute is\n * omitted entirely rather than emitted empty.\n */\nexport function joinDescribedBy(hintId?: string, errorId?: string): string | undefined {\n const ids = [hintId, errorId].filter((id): id is string => isPresent(id));\n return ids.length > 0 ? ids.join(' ') : undefined;\n}\n\nexport const Field = ({\n label,\n children,\n required = false,\n optional = false,\n optionalLabel = DEFAULT_OPTIONAL_LABEL,\n hint,\n error,\n labelVariant,\n labelStyle,\n containerStyle,\n spacing,\n testID,\n}: FieldProps): React.ReactElement => {\n const { theme } = useUi();\n const gapOwned = useIsGapOwned();\n const spacingStyles = fieldSpacingStyleSet(resolveFieldSpacing(spacing, gapOwned));\n const { colors, semantic } = theme;\n const errorColor = semantic.error['500'];\n const hasError = hasFieldError(error);\n const hasHint = isPresent(hint);\n const labelText = label ?? '';\n const hasLabel = labelText !== '';\n const marker = resolveFieldMarker(required, optional);\n const { hintId, errorId, controlId, labelId } = useFieldIds();\n\n const themeStyles = React.useMemo<ThemeStyles>(\n () => ({\n label: { color: colors.textSecondary },\n requiredMark: { color: errorColor },\n // The optional marker is an aside, so it sits a step back from the label's own ink.\n optionalMark: { color: colors.textSecondary },\n hintText: { color: colors.textSecondary },\n errorText: { color: errorColor },\n }),\n [colors.textSecondary, errorColor],\n );\n\n const describedById = joinDescribedBy(hasHint ? hintId : undefined, hasError ? errorId : undefined);\n\n // A render-function child places `controlId` itself, so the label always targets it. A plain\n // node has the id injected — and `attachControlId` reports back whether that was possible, so\n // the label never emits an `htmlFor` pointing at an element that does not exist.\n const isRenderChild = typeof children === 'function';\n const attached = isRenderChild\n ? { node: children({ describedById, hasError, controlId, labelId }), controlId }\n : attachControlId(children, controlId, describedById);\n const control = attached.node;\n\n return (\n <View style={[spacingStyles.container, containerStyle]} testID={testID}>\n {hasLabel ? (\n <FieldLabel\n controlId={attached.controlId}\n label={labelText}\n labelId={labelId}\n marker={marker}\n optionalLabel={optionalLabel}\n optionalMarkStyle={[styles.optionalMark, themeStyles.optionalMark]}\n requiredMarkStyle={themeStyles.requiredMark}\n style={[spacingStyles.label, resolveLabelVariantStyle(labelVariant), themeStyles.label, labelStyle]}\n />\n ) : null}\n {control}\n {hasHint ? (\n <Text nativeID={hintId} style={[styles.hintText, spacingStyles.child, themeStyles.hintText]}>\n {hint}\n </Text>\n ) : null}\n {hasError ? (\n <Text nativeID={errorId} role=\"alert\" style={[styles.errorText, spacingStyles.child, themeStyles.errorText]}>\n {error}\n </Text>\n ) : null}\n </View>\n );\n};\n\nexport default Field;\n","/**\n * `FormGrid` — the wrapping form row, extracted from ~177 hand-rolled copies.\n *\n * Verbatim in every portal, differing only in one constant:\n *\n * ```ts\n * grid: { flexDirection: 'row', flexWrap: 'wrap', gap: 12 },\n * field: { minWidth: 220, flexGrow: 1, flexBasis: 260 }, // or 200/240/260\n * ```\n *\n * Extracting it is worth more than the deleted lines: because the grid declares itself through\n * `FormGridContext`, a `Field` inside it knows its vertical rhythm is owned by the grid's `gap` and\n * drops its own bottom margin. That kills the fleet's 16 `marginBottom: 0` cancel hacks at the same\n * time — the grid and the cancel were always two halves of one bug.\n *\n * The cell metrics live on the GRID, not on each cell, because that is how the real call sites are\n * written: one `styles.field` reused by every cell in the row, with the occasional narrow one-off.\n * `<FormCell>` with no props is therefore the common case, and `<FormCell basis={160} grow={false}>`\n * the exception — which is exactly the ratio in aml-v2's `ScreeningForm`.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { FormGridProvider, GapOwnedProvider, type FormGridMetrics } from './formGridContext';\n\n/** The gap 24 of aml-v2's 41 wrapping rows already use. The de-facto fleet default. */\nexport const FORM_GRID_DEFAULT_GAP = 12;\n/** The most common `minWidth` across the fleet's copies (the others are 200 / 240 / 260). */\nexport const FORM_GRID_DEFAULT_MIN_WIDTH = 220;\n/** The most common `flexBasis` across the fleet's copies. */\nexport const FORM_GRID_DEFAULT_BASIS = 260;\n\nconst styles = StyleSheet.create({\n grid: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n});\n\nexport interface FormGridProps {\n children: React.ReactNode;\n /**\n * Space between cells, horizontally AND between wrapped rows. This is the value that makes the\n * grid own the vertical rhythm, so it is also what a descendant `Field` is dropping its own\n * margin in favour of.\n */\n gap?: number;\n /** Default `minWidth` for every `FormCell` in this grid. */\n minWidth?: number;\n /** Default `flexBasis` for every `FormCell` in this grid. */\n basis?: number;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nexport const FormGrid = ({\n children,\n gap = FORM_GRID_DEFAULT_GAP,\n minWidth = FORM_GRID_DEFAULT_MIN_WIDTH,\n basis = FORM_GRID_DEFAULT_BASIS,\n style,\n testID,\n}: FormGridProps): React.ReactElement => {\n // Memoised on the two primitives, not the object literal: a fresh identity every render would\n // re-render every `Field` in the row on every keystroke in any one of them.\n const metrics = React.useMemo<FormGridMetrics>(() => ({ minWidth, basis }), [minWidth, basis]);\n\n return (\n <FormGridProvider value={metrics}>\n <GapOwnedProvider value>\n <View style={[styles.grid, { gap }, style]} testID={testID}>\n {children}\n </View>\n </GapOwnedProvider>\n </FormGridProvider>\n );\n};\n\nexport default FormGrid;\n","/**\n * `FormCell` — one cell of a `FormGrid`.\n *\n * Replaces the `<View style={styles.field}>` wrapper every real call site already puts around each\n * control. It inherits `minWidth` / `flexBasis` from the enclosing grid so the common case is a bare\n * `<FormCell>`, and takes per-cell overrides for the genuine one-offs (aml-v2's `fieldNarrow`:\n * `minWidth: 140, flexBasis: 160, flexGrow: 0`).\n *\n * Used OUTSIDE a `FormGrid` it still renders a sensible cell from the package defaults rather than\n * throwing — a cell is a layout hint, and a form that renders slightly wide is a better failure than\n * a form that does not render. The grid-owned SPACING behaviour, by contrast, is deliberately NOT\n * available this way: that one has to come from a real grid, because a `Field` dropping its margin\n * with nothing to replace it would collapse the form.\n */\nimport React from 'react';\n\nimport { View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport {\n FORM_GRID_DEFAULT_BASIS,\n FORM_GRID_DEFAULT_MIN_WIDTH,\n} from './FormGrid';\nimport { useFormGridMetrics } from './formGridContext';\n\n/** A cell that grows to fill the row's slack. The default — most fields want the space. */\nconst GROW = 1;\n/** A cell pinned to its basis. For the narrow one-offs (a 2-digit threshold next to a name field). */\nconst NO_GROW = 0;\n\nexport interface FormCellProps {\n children: React.ReactNode;\n /** Overrides the grid's `minWidth` for this cell only. */\n minWidth?: number;\n /** Overrides the grid's `basis` for this cell only. */\n basis?: number;\n /** `false` pins the cell to its basis instead of letting it absorb the row's slack. */\n grow?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nexport const FormCell = ({\n children,\n minWidth,\n basis,\n grow = true,\n style,\n testID,\n}: FormCellProps): React.ReactElement => {\n const metrics = useFormGridMetrics();\n const resolvedMinWidth = minWidth ?? metrics?.minWidth ?? FORM_GRID_DEFAULT_MIN_WIDTH;\n const resolvedBasis = basis ?? metrics?.basis ?? FORM_GRID_DEFAULT_BASIS;\n\n const cellStyle: ViewStyle = {\n minWidth: resolvedMinWidth,\n flexBasis: resolvedBasis,\n flexGrow: grow ? GROW : NO_GROW,\n };\n\n return (\n <View style={[cellStyle, style]} testID={testID}>\n {children}\n </View>\n );\n};\n\nexport default FormCell;\n","/**\n * `FormSection` — a titled group of fields. The React answer to v1's `<fieldset>` / `<legend>`.\n *\n * v1 has a real `<fieldset>` whose `<legend>` takes the identical label metric as a field label, so\n * a group heading reads as part of the form rather than as page furniture. Nothing in the React\n * fleet has this: zygos fakes it with a generic `Heading`, and everybody else emits an untitled\n * `<View>` — which means the grouping exists visually but not semantically, so a screen-reader user\n * tabbing into \"Threshold\" is never told it belongs to \"Advanced matching\".\n *\n * ## Why not a literal `<fieldset>`\n *\n * react-native-web has no `fieldset` mapping — a `View` is a `div`, and there is no escape hatch\n * that turns one into a `<fieldset>` with a real `<legend>`. What IS available is the pattern the\n * ARIA spec defines as the equivalent: `role=\"group\"` + `aria-labelledby` pointing at the heading.\n * Assistive tech announces \"Advanced matching, group\" exactly as it would for a fieldset. This is\n * the honest ceiling of the platform, not a shortcut — and it is why the legend is a `Text` whose\n * `nativeID` is generated the same way `Field`'s hint/error ids are.\n *\n * The legend deliberately reuses `resolveLabelVariantStyle` — the SAME function `Field` uses for its\n * label — so the two cannot drift. A section titled in one metric above fields labelled in another\n * is precisely the \"third voice is drift\" failure FORMS.md warns about.\n */\nimport React from 'react';\n\nimport { StyleSheet, Text, View, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { resolveLabelVariantStyle, type FieldLabelVariant } from '../Field/labelVariants';\nimport { GapOwnedProvider } from '../FormGrid/formGridContext';\n\n/** Space between the legend, the description and the section's content. */\nconst SECTION_GAP = 10;\n/** A description is a help line for the whole group — same size as `Field`'s hint. */\nconst DESCRIPTION_FONT_SIZE = 12;\n\nconst styles = StyleSheet.create({\n section: {\n gap: SECTION_GAP,\n },\n description: {\n fontSize: DESCRIPTION_FONT_SIZE,\n },\n});\n\nlet sectionSeq = 0;\n\n/** Stable-per-instance id so the group can point at its own legend via `aria-labelledby`. */\nfunction useSectionLegendId(): string {\n const [id] = React.useState(() => {\n sectionSeq += 1;\n return `form-section-legend-${String(sectionSeq)}`;\n });\n return id;\n}\n\n/**\n * Web-only ARIA attributes react-native-web forwards to the underlying element but that RN's\n * `ViewProps` type does not enumerate — the same escape-hatch-free pattern `ChipSelector` uses.\n */\ninterface WebSectionA11y {\n 'aria-labelledby'?: string;\n}\n\nexport interface FormSectionProps {\n /**\n * The legend — pre-localized, like every string in this package. Optional: a section with no\n * title still groups its children for layout, but renders NO legend row and NO `aria-labelledby`,\n * because a group labelled by an empty element is worse for assistive tech than an unlabelled one.\n */\n title?: string;\n /** Help line for the whole group, under the legend. The group-level sibling of `Field`'s hint. */\n description?: string;\n children: React.ReactNode;\n /**\n * Which label voice the legend speaks. Defaults to `field` — a section heading on a form the user\n * fills in. Pass `control` on a dense surface so the legend matches the controls beneath it.\n */\n labelVariant?: FieldLabelVariant;\n /** Escape hatch applied AFTER `labelVariant`, for the genuine one-off a variant does not cover. */\n titleStyle?: StyleProp<TextStyle>;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nexport const FormSection = ({\n title,\n description,\n children,\n labelVariant,\n titleStyle,\n style,\n testID,\n}: FormSectionProps): React.ReactElement => {\n const { theme } = useUi();\n const { colors } = theme;\n const legendId = useSectionLegendId();\n const hasTitle = typeof title === 'string' && title !== '';\n const hasDescription = typeof description === 'string' && description !== '';\n\n const a11y: WebSectionA11y = { 'aria-labelledby': hasTitle ? legendId : undefined };\n\n return (\n // The section spaces its children with `gap`, so it owns their vertical rhythm exactly as a\n // `FormGrid` owns a row's — without this a `Field` placed directly in a section would stack its\n // 16px margin on the section's gap and recreate the F3 bug one level up.\n <GapOwnedProvider value>\n <View role=\"group\" style={[styles.section, style]} testID={testID} {...a11y}>\n {hasTitle ? (\n <Text\n nativeID={legendId}\n style={[resolveLabelVariantStyle(labelVariant), { color: colors.text }, titleStyle]}\n >\n {title}\n </Text>\n ) : null}\n {hasDescription ? (\n <Text style={[styles.description, { color: colors.textSecondary }]}>{description}</Text>\n ) : null}\n {children}\n </View>\n </GapOwnedProvider>\n );\n};\n\nexport default FormSection;\n","/**\n * `FormActions` — the submit/cancel button row every form ends with.\n *\n * Promoted from the BYTE-IDENTICAL `erevna-web/src/components/Forms/FormActions.tsx` and\n * `katalogos-web/src/components/Forms/FormActions.tsx` (68 lines each, `diff` returns nothing);\n * all seven apps hand-roll the same row. Buttons come from the shared `@dloizides/ui-buttons` kit\n * rather than being forked here, so there is exactly one button implementation in the estate.\n *\n * The layout implements the contract's actions row\n * (`…/wwwroot/shared/FORMS.md` → \"Actions row\"): the primary action is LAST in DOM order, so tab\n * order reaches Cancel before Save, and `saving` drives the primary button's spinner rather than\n * disabling-and-relabelling it.\n *\n * Two minimal generalizations over the app-local twins:\n * 1. Labels and hints arrive as PRE-LOCALIZED props. The twins called `FM()` internally, which\n * cannot work here: aml-v2 localizes via `@dloizides/i18n` with positional `{0}` params while\n * the other six use i18next `{{p1}}`, and nothing bridges them.\n * 2. `testID`s are overridable but default to the twins' `save-button` / `cancel-button`, so the\n * existing Playwright selectors in every app keep matching.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { Button } from '@dloizides/ui-buttons';\n\n/** Gap between the actions, matching the contract's `.actions { gap: 12px }`. */\nconst ACTIONS_GAP = 12;\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: 'row',\n justifyContent: 'flex-end',\n gap: ACTIONS_GAP,\n },\n});\n\nexport interface FormActionsProps {\n /** Submit handler. May be async — the shared Button drives its own spinner for the promise. */\n onSave: () => void | Promise<unknown>;\n /** Cancel handler. Omit it entirely to render a save-only row (no empty Cancel slot). */\n onCancel?: () => void | Promise<unknown>;\n /** Pre-localized label for the primary action. */\n saveLabel: string;\n /** Pre-localized label for the cancel action. Required whenever `onCancel` is supplied. */\n cancelLabel?: string;\n /** Pre-localized accessibility hint for the primary action. Falls back to its label. */\n saveHint?: string;\n /** Pre-localized accessibility hint for the cancel action. Falls back to its label. */\n cancelHint?: string;\n /** In-flight submit: spins the primary action and disables cancel so the form can't be abandoned mid-write. */\n saving?: boolean;\n /** Disables the primary action independently of `saving` (e.g. an invalid form). */\n saveDisabled?: boolean;\n containerStyle?: StyleProp<ViewStyle>;\n saveTestID?: string;\n cancelTestID?: string;\n testID?: string;\n}\n\nexport const FormActions = ({\n onSave,\n onCancel,\n saveLabel,\n cancelLabel = '',\n saveHint,\n cancelHint,\n saving = false,\n saveDisabled = false,\n containerStyle,\n saveTestID = 'save-button',\n cancelTestID = 'cancel-button',\n testID,\n}: FormActionsProps): React.ReactElement => (\n <View style={[styles.container, containerStyle]} testID={testID}>\n {typeof onCancel === 'function' ? (\n <Button\n accessibilityHint={cancelHint ?? cancelLabel}\n accessibilityLabel={cancelLabel}\n disabled={saving}\n label={cancelLabel}\n testID={cancelTestID}\n variant=\"outline\"\n onPress={onCancel}\n />\n ) : null}\n\n <Button\n accessibilityHint={saveHint ?? saveLabel}\n accessibilityLabel={saveLabel}\n disabled={saveDisabled}\n label={saveLabel}\n loading={saving}\n testID={saveTestID}\n variant=\"primary\"\n onPress={onSave}\n />\n </View>\n);\n\nexport default FormActions;\n","/**\r\n * `controlStyles` — the tuned metrics for the dense CONTROLS (text box, select trigger, floating\r\n * option menu, date-range row), promoted VERBATIM out of `@dloizides/ui-tables`' private\r\n * `Filters/styles.ts`.\r\n *\r\n * That file's own header said the quiet part out loud: it \"reconcile[d] the per-field styles that\r\n * were copy-pasted across aml-v2's filter files into one shared source\" — and then locked the\r\n * reconciliation inside one bar, where no other surface could reach it. These numbers are that\r\n * reconciliation, unchanged to the pixel, now reachable.\r\n *\r\n * Colours are applied INLINE from `useUi().theme` at render — nothing here carries a colour\r\n * literal, so a control re-themes per tenant without a stylesheet change.\r\n */\r\nimport { StyleSheet } from 'react-native';\r\n\r\nimport { MIN_TOUCH_TARGET_PX } from '@dloizides/a11y';\r\nimport { Z_INDEX } from '@dloizides/design-tokens';\r\n\r\nconst FIELD_GAP = 4;\r\nconst LABEL_FONT = 11;\r\nconst LABEL_LETTER_SPACING = 0.4;\r\nconst INPUT_RADIUS = 8;\r\nconst INPUT_PAD_H = 12;\r\nconst INPUT_PAD_V = 10;\r\nconst INPUT_FONT = 14;\r\nconst INPUT_BORDER = 1;\r\nconst DATE_ROW_GAP = 8;\r\nconst CHEVRON_FONT = 10;\r\nconst MENU_TOP_GAP = 4;\r\nconst MENU_RADIUS = 8;\r\nconst MENU_PAD_V = 4;\r\nconst MENU_OPT_PAD_H = 12;\r\nconst MENU_OPT_PAD_V = 8;\r\nconst MENU_MIN_WIDTH = 160;\r\nconst MENU_MAX_HEIGHT = 260;\r\nconst MENU_ELEVATION = 8;\r\nconst MENU_BOX_SHADOW = '0px 2px 8px rgba(0, 0, 0, 0.15)';\r\nconst OPTION_FONT = 14;\r\nconst ERROR_FONT = 12;\r\nconst ERROR_GAP = 3;\r\n\r\nexport const controlStyles = StyleSheet.create({\r\n /**\r\n * The shared bordered box every dense text control renders in.\r\n *\r\n * `minHeight` is the kit floor: padding alone produced a ~38px box, and a bare input with no\r\n * box style at all measured **19px** in production. Height is a hit-target guarantee, so it\r\n * is stated rather than left to emerge from font size + padding.\r\n */\r\n input: {\r\n borderWidth: INPUT_BORDER,\r\n borderRadius: INPUT_RADIUS,\r\n paddingHorizontal: INPUT_PAD_H,\r\n paddingVertical: INPUT_PAD_V,\r\n fontSize: INPUT_FONT,\r\n minHeight: MIN_TOUCH_TARGET_PX,\r\n },\r\n /** The select trigger: a bordered field box matching the text inputs + a chevron. */\r\n selectTrigger: {\r\n minHeight: MIN_TOUCH_TARGET_PX,\r\n flexDirection: 'row',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n gap: DATE_ROW_GAP,\r\n borderWidth: INPUT_BORDER,\r\n borderRadius: INPUT_RADIUS,\r\n paddingHorizontal: INPUT_PAD_H,\r\n paddingVertical: INPUT_PAD_V,\r\n },\r\n selectTriggerText: { fontSize: INPUT_FONT, flexShrink: 1 },\r\n chevron: { fontSize: CHEVRON_FONT },\r\n dateRow: { flexDirection: 'row', gap: DATE_ROW_GAP },\r\n dateCol: { gap: FIELD_GAP, flex: 1 },\r\n /**\r\n * The micro-caption above a sub-control (a date range's From/To) and beside a switch. Note it\r\n * is deliberately NOT the `control` label voice: it carries no `700`/uppercase, because it\r\n * names a HALF of a control that already has a `control`-voice label above it. Uppercasing it\r\n * too would make one field shout twice.\r\n */\r\n subLabel: { fontSize: LABEL_FONT, letterSpacing: LABEL_LETTER_SPACING },\r\n /** Positioning context for a floating `AnchoredMenu` (`position:absolute; top:100%`). */\r\n anchor: { position: 'relative' },\r\n menu: {\r\n position: 'absolute',\r\n top: '100%',\r\n left: 0,\r\n marginTop: MENU_TOP_GAP,\r\n minWidth: MENU_MIN_WIDTH,\r\n maxHeight: MENU_MAX_HEIGHT,\r\n borderWidth: INPUT_BORDER,\r\n borderRadius: MENU_RADIUS,\r\n paddingVertical: MENU_PAD_V,\r\n zIndex: Z_INDEX.dropdown,\r\n boxShadow: MENU_BOX_SHADOW,\r\n elevation: MENU_ELEVATION,\r\n overflow: 'hidden',\r\n },\r\n /** A menu option is a tap target, so it carries the kit floor (SHOWCASE-1). */\r\n option: {\r\n minHeight: MIN_TOUCH_TARGET_PX,\r\n justifyContent: 'center',\r\n paddingHorizontal: MENU_OPT_PAD_H,\r\n paddingVertical: MENU_OPT_PAD_V,\r\n },\r\n optionText: { fontSize: OPTION_FONT },\r\n error: { fontSize: ERROR_FONT, marginTop: ERROR_GAP },\r\n});\r\n","/**\r\n * menuPortal — web-only stacking/positioning geometry for {@link AnchoredMenu}.\r\n *\r\n * WHY THIS EXISTS (the bug it fixes): react-native-web renders EVERY `View` with\r\n * `position: relative; z-index: 0`, so every View is its own stacking context. An in-tree\r\n * `position:absolute` popover therefore has its `zIndex` trapped inside its anchor's (and the\r\n * app's field-wrapper's) `z-index: 0` context — it can never rise above later-painting sibling\r\n * Views (the adjacent filter fields, the PEP-class guide, the results table/card). That is why the\r\n * Country typeahead menu painted UNDERNEATH the content below it (\"hidden below\").\r\n *\r\n * THE FIX: on web the menu is rendered in a PORTAL to `document.body` with `position: fixed` at the\r\n * trigger's measured viewport rect and a high `zIndex`. A portal escapes every ancestor stacking\r\n * context AND every ancestor `overflow: hidden`, so the menu always paints on top and is never\r\n * clipped. {@link useAnchorRect} keeps the fixed coordinate glued to the trigger as the page\r\n * scrolls / resizes / reflows. On native the menu stays in-tree (`position:absolute` + `elevation`).\r\n *\r\n * DUPLICATION NOTE: `@dloizides/ui-layout`'s `ModalDropdown`/`InlineMenu` and `@dloizides/ui-tables`'\r\n * `SizeDropdown` already carry the same portal mechanism. It is NOT shared from there because\r\n * `ui-forms` is the LOWEST-level UI primitive and must not depend on those higher packages (that\r\n * would invert the dependency graph). The proper DRY home is `ui-forms` itself; unifying the three\r\n * copies onto this one (ui-layout/ui-tables importing it from here) is a tracked follow-up, kept out\r\n * of this change so the proven ModalDropdown is not disturbed while fixing the typeahead.\r\n */\r\nimport { useLayoutEffect, useState } from 'react';\r\nimport type { RefObject } from 'react';\r\n\r\nimport { Platform, type ViewStyle } from 'react-native';\r\nimport type { View as RNView } from 'react-native';\r\n\r\nimport { Z_INDEX } from '@dloizides/design-tokens';\r\n\r\nconst IS_WEB = Platform.OS === 'web';\r\n\r\n/**\r\n * z-index for the open popover: the shared `popover` layer, above RN-web's body-level `Modal`\r\n * (9999) so a menu opened inside a dialog paints and clicks on top of it, and below toasts.\r\n */\r\nexport const MENU_PORTAL_Z_INDEX = Z_INDEX.popover;\r\n/** Gap between the trigger's bottom edge and the popover's top edge. */\r\nconst MENU_TOP_GAP = 4;\r\n\r\n/** The trigger's viewport-space rect (from `getBoundingClientRect`) needed to place a fixed menu. */\r\nexport interface AnchorRect {\r\n top: number;\r\n left: number;\r\n width: number;\r\n bottom: number;\r\n}\r\n\r\n/** The RN-web `View` ref is an `HTMLElement` at runtime; native refs are not. */\r\nfunction toDomNode(ref: RefObject<RNView | null>): HTMLElement | null {\r\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- RN web ref is an HTMLElement at runtime\r\n const node = ref.current as unknown as HTMLElement | null;\r\n if (node === null || typeof node.getBoundingClientRect !== 'function') return null;\r\n return node;\r\n}\r\n\r\n/** Read the anchor's viewport rect (web only). Returns null when unavailable (native / no node). */\r\nexport function readAnchorRect(ref: RefObject<RNView | null>): AnchorRect | null {\r\n if (!IS_WEB) return null;\r\n const node = toDomNode(ref);\r\n if (node === null) return null;\r\n const r = node.getBoundingClientRect();\r\n return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };\r\n}\r\n\r\n/**\r\n * Web portal popover style: `position: fixed` at the trigger rect with a high `zIndex`. Portalled to\r\n * `document.body`, so `fixed` positions it against the viewport and it tracks the trigger via the\r\n * measured rect (recomputed on scroll/resize/reflow) — clipped by nothing, above everything.\r\n */\r\nexport function buildPortalPopoverStyle(rect: AnchorRect): ViewStyle {\r\n return {\r\n // RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.\r\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value\r\n position: 'fixed' as unknown as ViewStyle['position'],\r\n top: rect.bottom + MENU_TOP_GAP,\r\n left: rect.left,\r\n width: rect.width,\r\n zIndex: MENU_PORTAL_Z_INDEX,\r\n };\r\n}\r\n\r\n/**\r\n * Track the anchor's viewport rect while `enabled`. Measures on enable, then re-measures on scroll\r\n * (capture phase, so a scroll inside ANY ancestor scroll container counts — element `scroll` events\r\n * do not bubble) + window resize + any layout reflow that moves the trigger without scrolling (an\r\n * accordion above it expanding, an async list rendering, a font swapping — caught by a\r\n * `ResizeObserver` on the anchor and `document.body`). Work is coalesced into one\r\n * `requestAnimationFrame` per frame so a momentum scroll cannot thrash layout. No-op on native\r\n * (returns null), where the in-tree absolute popover moves with its anchor automatically.\r\n */\r\nexport function useAnchorRect(ref: RefObject<RNView | null>, enabled: boolean): AnchorRect | null {\r\n const [rect, setRect] = useState<AnchorRect | null>(null);\r\n\r\n useLayoutEffect(() => {\r\n if (!IS_WEB || !enabled) {\r\n setRect(null);\r\n return undefined;\r\n }\r\n let frame: number | null = null;\r\n let disposed = false;\r\n\r\n const apply = (): void => {\r\n frame = null;\r\n if (disposed) return;\r\n setRect(readAnchorRect(ref));\r\n };\r\n const schedule = (): void => {\r\n if (frame !== null) return;\r\n frame = window.requestAnimationFrame(apply);\r\n };\r\n\r\n apply();\r\n document.addEventListener('scroll', schedule, true);\r\n window.addEventListener('resize', schedule);\r\n const node = toDomNode(ref);\r\n const observer = typeof ResizeObserver === 'function' ? new ResizeObserver(schedule) : null;\r\n if (observer !== null) {\r\n if (node !== null) observer.observe(node);\r\n observer.observe(document.body);\r\n }\r\n\r\n return () => {\r\n disposed = true;\r\n if (frame !== null) window.cancelAnimationFrame(frame);\r\n document.removeEventListener('scroll', schedule, true);\r\n window.removeEventListener('resize', schedule);\r\n if (observer !== null) observer.disconnect();\r\n };\r\n }, [ref, enabled]);\r\n\r\n return IS_WEB && enabled ? rect : null;\r\n}\r\n","/**\n * `AnchoredMenu` — the floating option list shared by `SelectControl` and `TypeaheadControl`.\n *\n * By DEFAULT (web) it renders in a PORTAL to `document.body` with `position: fixed` at the trigger's\n * measured rect: that escapes react-native-web's trapped `z-index: 0` stacking contexts and any\n * ancestor `overflow: hidden`, so the menu is never painted under / clipped by later siblings (a\n * table, a card, the next filter field). On native, and when {@link AnchoredMenuProps.usePortal} is\n * explicitly `false`, it renders an in-tree, absolutely-positioned popover under its anchor\n * (`position:absolute; top:100%; zIndex; elevation`) — which is exactly what left `SelectControl`'s\n * menu hidden behind the attendee table until the default flipped. See {@link menuPortal}.\n * On web it dismisses on outside-click / Escape; on native the caller closes it on blur/select.\n * Purely presentational + theme-flat, so it stays reusable.\n *\n * Promoted verbatim out of `@dloizides/ui-tables`' private `Filters/components/AnchoredMenu`.\n *\n * Deliberately no `ui-layout` dependency: `ui-forms` is a low-level primitive and must not take a\n * runtime dependency on the higher-level `ui-layout` `ModalDropdown` — that would invert the graph\n * for every consumer. The portal mechanism therefore lives locally in {@link menuPortal}.\n */\nimport React, { useEffect } from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { Pressable, ScrollView, Text, View } from 'react-native';\n\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\nimport { buildPortalPopoverStyle, useAnchorRect } from './menuPortal';\n\nconst IS_WEB = typeof document !== 'undefined';\nconst ESCAPE_KEY = 'Escape';\nconst ACTIVE_WEIGHT = '700' as const;\nconst IDLE_WEIGHT = '400' as const;\n\n/** The four theme colours the menu paints with — passed in, so the menu stays theme-flat. */\nexport interface AnchoredMenuColors {\n text: string;\n border: string;\n surface: string;\n brand: string;\n}\n\nexport interface AnchoredMenuProps {\n options: readonly ControlOption[];\n /** The currently-selected value, highlighted in the list ('' = none). */\n selectedValue: string;\n onSelect: (value: string) => void;\n onDismiss: () => void;\n colors: AnchoredMenuColors;\n /** PRE-LOCALIZED accessibility hint applied to every option. */\n optionHint: string;\n /**\n * PRE-LOCALIZED accessible NAME for the menu container itself (e.g. \"Recent values\"). Optional and\n * additive — omitted, the menu keeps only its `role=\"menu\"` as before, so existing callers are\n * unaffected. Supplied, a screen reader announces the list's purpose, not just \"menu\".\n */\n accessibilityLabel?: string;\n /** Base testID: the menu is `${testID}-menu`, each option `${testID}-option-${value}`. */\n testID: string;\n /** Node whose clicks count as \"inside\" (the anchor) so its own press doesn't self-dismiss. */\n anchorRef: React.RefObject<View | null>;\n /**\n * On web, render the popover in a portal to `document.body` with `position: fixed` at the anchor's\n * measured rect, so it escapes react-native-web's trapped stacking contexts and any ancestor\n * `overflow: hidden` (the fix for a menu that paints under / is clipped by the content below it).\n * No effect on native (the `IS_WEB` guard keeps native in-tree regardless).\n *\n * Default `true` — portalling is the CORRECT default: an in-tree popover is always at risk of\n * being painted under a later-painting sibling (a table, a card, the next filter field). The old\n * default was `false`, which silently left `SelectControl`'s menu hidden behind the attendee table\n * (a recurrence of the exact bug this mechanism fixed for `TypeaheadControl`). Pass `usePortal={false}`\n * only for the rare case that genuinely wants the menu clipped to its container.\n */\n usePortal?: boolean;\n}\n\n/** Web-only outside-click + Escape dismissal (no-op on native). */\nfunction useDismiss(\n anchorRef: React.RefObject<View | null>,\n menuRef: React.RefObject<View | null>,\n onDismiss: () => void,\n): void {\n useEffect(() => {\n if (!IS_WEB) return undefined;\n const onMouseDown = (event: MouseEvent): void => {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- RN web refs are HTMLElements at runtime\n const anchorNode = anchorRef.current as unknown as HTMLElement | null;\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- RN web refs are HTMLElements at runtime\n const menuNode = menuRef.current as unknown as HTMLElement | null;\n const target = event.target instanceof Node ? event.target : null;\n const insideAnchor = anchorNode !== null && target !== null && anchorNode.contains(target);\n const insideMenu = menuNode !== null && target !== null && menuNode.contains(target);\n if (!insideAnchor && !insideMenu) onDismiss();\n };\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === ESCAPE_KEY) onDismiss();\n };\n document.addEventListener('mousedown', onMouseDown);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('mousedown', onMouseDown);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [anchorRef, menuRef, onDismiss]);\n}\n\nexport function AnchoredMenu({\n options,\n selectedValue,\n onSelect,\n onDismiss,\n colors,\n optionHint,\n accessibilityLabel,\n testID,\n anchorRef,\n usePortal = true,\n}: AnchoredMenuProps): React.ReactElement {\n const menuRef = React.useRef<View>(null);\n useDismiss(anchorRef, menuRef, onDismiss);\n // Web + usePortal: track the anchor rect so the fixed, portalled menu stays glued to the trigger.\n const rect = useAnchorRect(anchorRef, usePortal);\n const portalStyle = rect !== null ? buildPortalPopoverStyle(rect) : null;\n\n const menu = (\n <View\n ref={menuRef}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole=\"menu\"\n // `portalStyle` (position:fixed at the measured rect) is appended LAST so it wins over\n // s.menu's default `position:absolute; top:100%` when portalling; null (native / no portal)\n // leaves the in-tree anchored style untouched.\n style={[s.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle]}\n testID={`${testID}-menu`}\n >\n {/* Scroll the options when they exceed the menu's maxHeight (s.menu). Without this the list was\n clipped by `overflow: hidden` with no way to reach the options below the fold. */}\n <ScrollView keyboardShouldPersistTaps=\"handled\" nestedScrollEnabled>\n {options.map((opt) => {\n const active = opt.value === selectedValue;\n return (\n <Pressable\n key={opt.value}\n accessibilityRole=\"menuitem\"\n accessibilityLabel={opt.label}\n accessibilityHint={optionHint}\n // `accessibilityState` is NATIVE-ONLY: react-native-web does not read it at all, so\n // on web the selected option was distinguished by colour + font-weight ALONE — no\n // screen reader could tell which option was current (WCAG 1.4.1, use of colour).\n // `aria-selected` is the web channel and RN-web forwards it verbatim. Both are\n // passed so each platform gets the one it honours. The trigger's `aria-expanded`\n // beside `accessibilityState` is the same pairing — this option row was simply\n // missed when that was done.\n accessibilityState={{ selected: active }}\n aria-selected={active}\n onPress={() => onSelect(opt.value)}\n style={s.option}\n testID={`${testID}-option-${opt.value}`}\n >\n <Text style={[s.optionText, { color: active ? colors.brand : colors.text, fontWeight: active ? ACTIVE_WEIGHT : IDLE_WEIGHT }]}>\n {opt.label}\n </Text>\n </Pressable>\n );\n })}\n </ScrollView>\n </View>\n );\n\n // Portal to document.body on web so no ancestor stacking context / overflow can trap or clip it.\n if (usePortal && IS_WEB) return createPortal(menu, document.body);\n return menu;\n}\n\nexport default AnchoredMenu;\n","/**\n * `useThemedInput` — the shared \"readable + lively\" text-input treatment, driven entirely by\n * the active `@dloizides/ui-feedback` theme (so it re-themes per tenant, no hard-coded hex).\n *\n * At rest: dark readable text on a subtle off-white surface with a soft border.\n * On hover (web): the border strengthens a touch.\n * On focus: the border becomes the brand primary, the background brightens to the plain surface\n * (white), and a soft 3px brand-tinted focus ring fades in.\n *\n * Kept FAST: the animation is a pure GPU-cheap CSS transition on `border-color`,\n * `background-color` and `box-shadow` (the focus ring is a `box-shadow`, so it never triggers\n * layout/reflow). There is NO `Animated`, `LayoutAnimation` or JS timer — only React state\n * toggled by focus/blur/hover. Web-only style keys (`transition*`, `boxShadow`, `outlineStyle`)\n * and the mouse-hover handlers are guarded behind `Platform.OS === 'web'`, so the hook stays\n * native-safe (native simply applies the state-driven colours instantly).\n */\nimport { useCallback, useMemo, useState } from 'react';\n\nimport { Platform, type TextInputProps, type TextStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\n/** The exact focus/blur event types of the installed `react-native` `TextInput` (version-safe). */\ntype FocusEvent = Parameters<NonNullable<TextInputProps['onFocus']>>[0];\ntype BlurEvent = Parameters<NonNullable<TextInputProps['onBlur']>>[0];\n\nconst IS_WEB = Platform.OS === 'web';\n\nconst TRANSITION_PROPERTY = 'border-color, background-color, box-shadow';\nconst TRANSITION_DURATION = '0.14s';\nconst TRANSITION_TIMING = 'ease';\nconst FOCUS_RING_WIDTH = 3;\nconst FOCUS_RING_ALPHA = 0.16;\nconst HOVER_BORDER_ALPHA = 0.22;\n/**\n * Placeholder opacity. The theme's `textSecondary` is deliberately a DARK, accessible grey\n * (design-tokens UX-11) because it also paints readable secondary *copy* — so reusing it at\n * full strength made placeholders look like already-typed text. Compositing it toward the field\n * background at this alpha keeps the hue but pulls the placeholder clearly lighter than the solid\n * entered text (`colors.text`), so \"hint\" vs \"value\" reads at a glance. Works in dark mode too\n * (it composites toward whatever the field background is). The field's real visible label — not\n * the placeholder — carries the accessible name, so a lighter hint is a usability win, not an a11y loss.\n */\nconst PLACEHOLDER_ALPHA = 0.6;\n\nconst HEX_RADIX = 16;\nconst HEX_SHORT_LENGTH = 4;\nconst HEX_FULL_LENGTH = 7;\nconst RED_START = 1;\nconst GREEN_START = 3;\nconst BLUE_START = 5;\nconst CHANNEL_END_OFFSET = 2;\n\n/**\n * Convert an `#rgb` / `#rrggbb` colour to an `rgba(...)` string at the given alpha. Any other\n * colour form (already `rgba()`, a CSS name, …) is returned unchanged — so the caller degrades\n * gracefully rather than emitting an invalid value.\n */\n/**\n * True when the user asked the OS to reduce motion (web only). Read at render so the\n * focus/hover transition collapses to an instant change for those users (WCAG 2.3.3 / the\n * `prefers-reduced-motion: reduce` contract). Safe under SSR / no `matchMedia`.\n */\nfunction prefersReducedMotion(): boolean {\n if (!IS_WEB || typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\nfunction withAlpha(color: string, alpha: number): string {\n const hex = color.trim();\n const isHex = hex.charAt(0) === '#' && (hex.length === HEX_FULL_LENGTH || hex.length === HEX_SHORT_LENGTH);\n if (!isHex) return color;\n const full =\n hex.length === HEX_SHORT_LENGTH\n ? `#${hex.charAt(1)}${hex.charAt(1)}${hex.charAt(2)}${hex.charAt(2)}${hex.charAt(3)}${hex.charAt(3)}`\n : hex;\n const r = parseInt(full.slice(RED_START, RED_START + CHANNEL_END_OFFSET), HEX_RADIX);\n const g = parseInt(full.slice(GREEN_START, GREEN_START + CHANNEL_END_OFFSET), HEX_RADIX);\n const b = parseInt(full.slice(BLUE_START, BLUE_START + CHANNEL_END_OFFSET), HEX_RADIX);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nexport interface UseThemedInputOptions {\n /** Render with the error border colour (the brand focus border is suppressed while errored). */\n hasError?: boolean;\n /** Consumer focus handler — composed with the internal focus-state toggle. */\n onFocus?: (e: FocusEvent) => void;\n /** Consumer blur handler — composed with the internal focus-state toggle. */\n onBlur?: (e: BlurEvent) => void;\n}\n\nexport interface ThemedInput {\n /** The themed input style for the current focus/hover state (memoised). Merge AFTER your box style. */\n style: TextStyle;\n /**\n * The placeholder colour: the theme's `textSecondary` composited toward the field\n * background ({@link PLACEHOLDER_ALPHA}) so a placeholder reads as a faint hint, clearly\n * lighter than the solid entered text rather than looking like an already-filled value.\n */\n placeholderTextColor: string;\n isFocused: boolean;\n isHovered: boolean;\n /** Spread/attach onto the `<TextInput>` to drive the focus treatment. */\n focusBind: {\n onFocus: (e: FocusEvent) => void;\n onBlur: (e: BlurEvent) => void;\n };\n /** Web-only mouse-hover handlers, pre-typed for `<TextInput>` (an empty object on native). */\n hoverBind: TextInputProps;\n}\n\nexport function useThemedInput(options: UseThemedInputOptions = {}): ThemedInput {\n const { hasError = false, onFocus, onBlur } = options;\n const { theme } = useUi();\n const { colors, palette, semantic } = theme;\n\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n const handleFocus = useCallback(\n (e: FocusEvent) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n const handleBlur = useCallback(\n (e: BlurEvent) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n const handleHoverIn = useCallback(() => setIsHovered(true), []);\n const handleHoverOut = useCallback(() => setIsHovered(false), []);\n\n const primary = palette.primary['500'];\n const errorColor = semantic.error['500'];\n\n const style = useMemo<TextStyle>(() => {\n const restBorder = hasError ? errorColor : colors.border;\n const focusBorder = hasError ? errorColor : primary;\n const borderColor = isFocused ? focusBorder : isHovered ? withAlpha(colors.text, HOVER_BORDER_ALPHA) : restBorder;\n const backgroundColor = isFocused ? colors.surface : colors.surfaceElevated;\n const base: TextStyle = { color: colors.text, borderColor, backgroundColor };\n if (!IS_WEB) return base;\n // A focused field ALWAYS gets a ring — an errored one just changes its colour to the error\n // tint (v1: `input.invalid:focus { box-shadow: 0 0 0 3px var(--danger-tint) }`). Suppressing\n // the ring while errored, as this did, removed the focus indicator (WCAG 2.4.7) from precisely\n // the field the user was sent back to fix, at the moment they are most likely on a keyboard.\n const ringColor = hasError ? errorColor : primary;\n const ring = isFocused ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(ringColor, FOCUS_RING_ALPHA)}` : 'none';\n const webStyle = {\n transitionProperty: TRANSITION_PROPERTY,\n // Collapse the eased transition to instant when the user prefers reduced motion.\n transitionDuration: prefersReducedMotion() ? '0s' : TRANSITION_DURATION,\n transitionTimingFunction: TRANSITION_TIMING,\n boxShadow: ring,\n outlineStyle: 'none',\n };\n return { ...base, ...webStyle } as TextStyle;\n }, [\n isFocused,\n isHovered,\n hasError,\n colors.text,\n colors.border,\n colors.surface,\n colors.surfaceElevated,\n primary,\n errorColor,\n ]);\n\n const focusBind = useMemo(() => ({ onFocus: handleFocus, onBlur: handleBlur }), [handleFocus, handleBlur]);\n\n const hoverBind = useMemo<TextInputProps>(\n () =>\n IS_WEB ? ({ onMouseEnter: handleHoverIn, onMouseLeave: handleHoverOut } as unknown as TextInputProps) : {},\n [handleHoverIn, handleHoverOut],\n );\n\n return {\n style,\n placeholderTextColor: withAlpha(colors.textSecondary, PLACEHOLDER_ALPHA),\n isFocused,\n isHovered,\n focusBind,\n hoverBind,\n };\n}\n","/**\n * Validation ARIA for a form control — web only, no-op on native.\n *\n * ## Why this is here and NOT in `@dloizides/a11y`\n *\n * This looks exactly like adapter work, and moving it into the shared accessibility package\n * is the obvious next step. It would be a mistake, and the reason is worth spelling out\n * because the next person to read this will have the same instinct.\n *\n * `@dloizides/a11y` states its own invariant in `types.ts`: `A11yState` models\n * \"only the members with a faithful expression on BOTH platforms ... so a contract can never\n * promise something one platform silently drops (the exact bug class this package exists to\n * close)\". `invalid` and `required` have NO faithful React Native expression — RN's\n * `AccessibilityState` has no `invalid`, and `accessibilityRequired` does not exist. Adding\n * them to `A11yState` would make the adapter accept a contract it can only honour on web and\n * must silently discard on native. That is precisely the failure the package was built to\n * prevent, reintroduced through its own front door.\n *\n * So the seam stays here, in the package that owns form semantics, where \"web-only\" is an\n * honest local statement rather than a promise broken at a platform boundary. Consequently\n * `@dloizides/a11y` needs no version bump for this change.\n *\n * ## Why it exists at all\n *\n * The identical branch was written twice — `ThemedTextInput` and `ChipSelector` — the second\n * even documenting itself as \"the same escape-hatch-free pattern `ThemedTextInput` uses\". Two\n * copies of one rule is two places for it to drift.\n */\nimport { Platform } from 'react-native';\n\n/**\n * Web-only ARIA attributes react-native-web forwards to the underlying DOM element but that\n * RN's prop types do not enumerate. Callers cast through their own host props at the spread\n * site (never `any`), so these semantics reach a screen reader without a type escape hatch.\n */\nexport interface WebFieldA11y {\n 'aria-invalid'?: boolean;\n 'aria-describedby'?: string;\n 'aria-required'?: boolean;\n}\n\nexport interface WebFieldA11yInput {\n /** id of the element describing this control — typically `Field`'s error/hint line. */\n describedById?: string;\n /** Announce the control as failing validation. */\n hasError?: boolean;\n /**\n * Mark the control mandatory. Omit for controls that have no required affordance; an\n * omitted value emits nothing rather than `aria-required=\"false\"`, which would tell a\n * screen reader something different from saying nothing at all.\n */\n required?: boolean;\n}\n\nconst IS_WEB = Platform.OS === 'web';\n\n/**\n * Build the validation ARIA for a form control.\n *\n * Returns an EMPTY object on native — deliberately, and not as an oversight: there is no\n * native equivalent to emit, and inventing one would mean claiming a guarantee the platform\n * cannot keep. Every attribute is `undefined` unless genuinely true, so nothing is emitted\n * that a screen reader would have to interpret as an explicit negative.\n */\nexport function webFieldA11y({ describedById, hasError = false, required = false }: WebFieldA11yInput): WebFieldA11y {\n if (!IS_WEB) {\n return {};\n }\n return {\n 'aria-invalid': hasError ? true : undefined,\n 'aria-describedby': describedById,\n 'aria-required': required ? true : undefined,\n };\n}\n","/**\n * `ThemedTextInput` — the shared, readable + lively text-input primitive. A thin `<TextInput>`\n * wrapper that applies the `useThemedInput` treatment (dark readable text, subtle off-white rest\n * background, and the brand focus animation: indigo border + white background + soft 3px ring,\n * eased over .14s via a GPU-cheap CSS transition on web; instant, native-safe off web).\n *\n * It is the ONE source of truth for the input look: `FormField` renders it, and raw filter inputs\n * (search / country / year / date fallbacks) use it directly instead of forking the styles.\n *\n * ## The box metrics are applied HERE, and that is new\n *\n * This component claimed to be the source of truth for the input look while shipping only\n * COLOURS — no border, no radius, no padding, no height. `FormField` happened to pass its own\n * private copy of those metrics, so every input reached through `FormField` looked right and the\n * gap stayed invisible. Any caller that used `ThemedTextInput` directly — the documented, blessed\n * way to use it — got a raw browser input: **19px tall**, measured in production on an admin CMS\n * where all 10 inputs failed the hit-target floor.\n *\n * So `controlStyles.input` is now the component's own base, ahead of the caller's `style` in the\n * cascade. Callers that already passed the same metrics (`FormField`) are unaffected — the values\n * are identical, which is precisely why the duplication was invisible — and callers that pass\n * their own overrides still win, because their `style` merges after the base.\n *\n * Every existing `TextInputProps` (value, placeholder, onChangeText, testID, accessibility…) is\n * forwarded untouched; `onFocus`/`onBlur` you pass are composed with the internal focus state.\n */\nimport React from 'react';\n\nimport { StyleSheet, TextInput, type TextInputProps } from 'react-native';\n\nimport { controlStyles } from '../controls/controlStyles';\nimport { useThemedInput } from '../useThemedInput/useThemedInput';\nimport { webFieldA11y } from '../webFieldA11y/webFieldA11y';\n\n/**\n * A multi-line box has to be tall enough to show that it IS multi-line. Left at the single-line\n * floor a textarea looks exactly like a text field, and an author writing a paragraph gets one\n * visible line. Two lines of content plus the box's own padding.\n */\nconst MULTILINE_MIN_HEIGHT = 96;\n\nconst boxStyles = StyleSheet.create({\n multiline: {\n minHeight: MULTILINE_MIN_HEIGHT,\n textAlignVertical: 'top',\n },\n});\n\nexport interface ThemedTextInputProps extends TextInputProps {\n /** Render with the error border colour (matches `FormField`'s error treatment). */\n hasError?: boolean;\n /**\n * id of an element describing this input (e.g. an error/hint line). Linked via\n * `aria-describedby` on web so a screen reader reads it after the field's name. No-op native.\n */\n describedById?: string;\n /** Marks the field required for assistive tech (`aria-required` on web). No-op on native. */\n requiredField?: boolean;\n /**\n * Opt OUT of the shared box metrics (border, radius, padding, the kit's min-height floor) and\n * render colours only — the pre-1.11 behaviour.\n *\n * For the rare control that supplies its own complete box, e.g. an input embedded inside an\n * already-bordered composite where a second border would double up. It is a prop rather than\n * the default because the default has to be the accessible one: the previous default shipped\n * 19px inputs to production precisely because \"no metrics\" was the silent fallback.\n */\n unstyledBox?: boolean;\n}\n\nexport const ThemedTextInput = React.forwardRef<TextInput, ThemedTextInputProps>(function ThemedTextInput(\n {\n hasError = false,\n describedById,\n requiredField = false,\n unstyledBox = false,\n onFocus,\n onBlur,\n style,\n placeholderTextColor,\n ...rest\n },\n ref,\n): React.ReactElement {\n const {\n style: themedStyle,\n placeholderTextColor: themedPlaceholder,\n focusBind,\n hoverBind,\n } = useThemedInput({ hasError, onFocus, onBlur });\n\n // aria-invalid announces the error state; aria-describedby ties the error/hint text to the\n // field; aria-required marks it mandatory. Web-only (RN-web → DOM); omitted on native.\n const webA11y = webFieldA11y({ describedById, hasError, required: requiredField });\n\n // Base box FIRST so the caller's `style` still overrides it; `themedStyle` stays last because\n // the theme's colours are not the caller's to override (unchanged from previous versions).\n const boxStyle = unstyledBox ? null : controlStyles.input;\n const multilineStyle = rest.multiline === true && !unstyledBox ? boxStyles.multiline : null;\n\n return (\n <TextInput\n ref={ref}\n placeholderTextColor={placeholderTextColor ?? themedPlaceholder}\n {...rest}\n {...(webA11y as TextInputProps)}\n {...hoverBind}\n onFocus={focusBind.onFocus}\n onBlur={focusBind.onBlur}\n style={[boxStyle, multilineStyle, style, themedStyle]}\n />\n );\n});\n","/**\n * `recentValuesCore` — the pure + storage-facing internals of {@link useRecentValues}, kept out of\n * the hook file so the list algebra (trim / de-dupe / promote / cap) and the `localStorage` access\n * are each unit-testable in isolation.\n *\n * ## RN-web storage reality\n *\n * `ui-forms` runs on react-native-web, so a component using this may mount on web (where\n * `window.localStorage` exists), on native (where it does NOT), or under SSR / a hardened browser\n * where touching `window.localStorage` THROWS (disabled cookies, privacy mode, quota). Every access\n * therefore goes through {@link getStorage}, which returns `null` rather than throwing, and every\n * read/write is wrapped so a storage failure degrades to an in-memory-only no-op instead of\n * exploding inside render. On native / when storage is unavailable the feature is simply inert and\n * the recents list is always `[]`.\n */\n\n/** The single namespace every persisted list lives under, so one product can never collide with another. */\nconst STORAGE_PREFIX = '@dloizides/ui-forms:recent:';\n\n/** Default cap on remembered values (most-recent-first). */\nexport const DEFAULT_MAX_RECENTS = 10;\n\n/** The full `localStorage` key for a caller's logical `key`. */\nexport function recentStorageKey(key: string): string {\n return `${STORAGE_PREFIX}${key}`;\n}\n\n/**\n * The active web `localStorage`, or `null` on native / SSR / when merely READING the property\n * throws (some browsers throw on `window.localStorage` access when storage is disabled). Never\n * throws — callers treat `null` as \"storage unavailable, no-op\".\n */\nfunction getStorage(): Storage | null {\n try {\n if (typeof window === 'undefined') return null;\n const storage = window.localStorage;\n return storage !== null && storage !== undefined ? storage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read the persisted list for `key`. Returns `[]` when storage is unavailable, the key is absent,\n * the stored JSON is corrupt, or the parsed value is not an array of strings — corruption is\n * tolerated, never surfaced as a throw.\n */\nexport function readRecents(key: string): string[] {\n const storage = getStorage();\n if (storage === null) return [];\n try {\n const raw = storage.getItem(recentStorageKey(key));\n if (raw === null) return [];\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter((entry): entry is string => typeof entry === 'string');\n } catch {\n return [];\n }\n}\n\n/** Persist `values` for `key`. Silent no-op when storage is unavailable or the write throws (quota). */\nexport function writeRecents(key: string, values: readonly string[]): void {\n const storage = getStorage();\n if (storage === null) return;\n try {\n storage.setItem(recentStorageKey(key), JSON.stringify(values));\n } catch {\n // Quota exceeded / storage disabled mid-session — drop the write rather than throw into render.\n }\n}\n\n/** Remove the persisted list for `key`. Silent no-op when storage is unavailable or removal throws. */\nexport function clearRecents(key: string): void {\n const storage = getStorage();\n if (storage === null) return;\n try {\n storage.removeItem(recentStorageKey(key));\n } catch {\n // Storage disabled mid-session — nothing to do.\n }\n}\n\n/**\n * The pure list algebra: fold `value` into `current`, returning the new most-recent-first list.\n *\n * - trims `value`; an empty (or whitespace-only) value is ignored, returning `current` unchanged;\n * - de-dupes case-insensitively, so \"Cyprus\" typed after \"cyprus\" does not create a second row;\n * - PROMOTES an existing (case-insensitive) match to the front, keeping the newly-typed casing;\n * - caps the result at `max` (most-recent-first), so the list can never grow without bound.\n */\nexport function computeNextRecents(current: readonly string[], value: string, max: number): string[] {\n const trimmed = value.trim();\n if (trimmed === '') return [...current];\n const lower = trimmed.toLowerCase();\n const withoutMatch = current.filter((entry) => entry.toLowerCase() !== lower);\n const promoted = [trimmed, ...withoutMatch];\n const cap = max > 0 ? max : 0;\n return promoted.slice(0, cap);\n}\n\n/** True when two lists hold the same values in the same order (reference-stability guard for state). */\nexport function recentsEqual(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((entry, index) => entry === b[index]);\n}\n","/**\n * `useRecentValues` — an opt-in \"remember the last N submitted values, show them again\" store for a\n * single logical input, persisted to `localStorage` under `@dloizides/ui-forms:recent:<key>`.\n *\n * It is the engine behind {@link FormField}'s `recentKey` prop, but is exported on its own so any\n * consumer can build a bespoke recents surface. Pure + storage-guarded (see {@link recentValuesCore}):\n * on native / SSR / disabled storage it is a silent no-op that always reports `recents: []`.\n *\n * ```ts\n * const { recents, remember, clear } = useRecentValues('invoice-search');\n * // on submit / blur: remember(text); in a menu: recents.map(...); to reset: clear();\n * ```\n */\nimport { useCallback, useEffect, useState } from 'react';\n\nimport {\n DEFAULT_MAX_RECENTS,\n clearRecents,\n computeNextRecents,\n readRecents,\n recentsEqual,\n writeRecents,\n} from './recentValuesCore';\n\nexport interface RecentValues {\n /** The remembered values, most-recent-first (never longer than `max`; `[]` when storage is unavailable). */\n recents: string[];\n /** Fold a value into the list (trim / de-dupe / promote / cap) and persist. Empty values are ignored. */\n remember: (value: string) => void;\n /** Forget every remembered value for this key and clear it from storage. */\n clear: () => void;\n}\n\n/**\n * @param key logical name for this input's history (namespaced under `@dloizides/ui-forms:recent:`).\n * @param max most-recent-first cap on remembered values. Default {@link DEFAULT_MAX_RECENTS}.\n */\nexport function useRecentValues(key: string, max: number = DEFAULT_MAX_RECENTS): RecentValues {\n // Seeded from storage on first render (lazy initialiser — no read on every render).\n const [recents, setRecents] = useState<string[]>(() => readRecents(key).slice(0, max));\n\n // Re-hydrate when the key or cap changes, so switching which input this drives shows its own history.\n useEffect(() => {\n setRecents(readRecents(key).slice(0, max));\n }, [key, max]);\n\n const remember = useCallback(\n (value: string) => {\n setRecents((current) => {\n const next = computeNextRecents(current, value, max);\n // An ignored (empty) value or an already-front value yields an identical list — keep the\n // same reference so no re-render fires and no redundant write hits storage.\n if (recentsEqual(next, current)) return current;\n writeRecents(key, next);\n return next;\n });\n },\n [key, max],\n );\n\n const clear = useCallback(() => {\n clearRecents(key);\n setRecents([]);\n }, [key]);\n\n return { recents, remember, clear };\n}\n\nexport default useRecentValues;\n","/**\n * `RecentInputField` — the `ThemedTextInput` PLUS the opt-in \"recent values\" dropdown that\n * {@link FormField} renders only when a `recentKey` is supplied. Split out of `FormField` so the\n * default (no `recentKey`) path stays a plain input with ZERO extra state, refs, effects or storage\n * access, and every consumer that never opts in pays nothing.\n *\n * On focus it surfaces the values previously submitted through this key (via {@link useRecentValues})\n * in the shared {@link AnchoredMenu} — reused rather than hand-rolled, and forced through a\n * `document.body` portal (`usePortal`) so the list is never painted behind a table / card / the next\n * field (the kit's known AnchoredMenu stacking gotcha). Picking a row fills the input (`onChangeText`)\n * and closes. A value is remembered on submit (Enter) AND on blur-with-content, so both \"hit enter\"\n * and \"typed then moved on\" are captured. Colours come only from the active theme — no literals.\n */\nimport React, { useCallback, useRef, useState } from 'react';\n\nimport { View } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { AnchoredMenu } from '../AnchoredMenu/AnchoredMenu';\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\nimport { ThemedTextInput, type ThemedTextInputProps } from '../ThemedTextInput/ThemedTextInput';\nimport { useRecentValues } from '../useRecentValues/useRecentValues';\n\n/** Delay before blur closes the menu, so a tap on a recent row registers first (matches TypeaheadControl). */\nconst CLOSE_DELAY_MS = 140;\n\n// Event types taken from the input's OWN prop signatures, so they track the installed react-native\n// version exactly (focus/blur/submit event shapes have drifted between RN releases).\ntype FocusEvent = Parameters<NonNullable<ThemedTextInputProps['onFocus']>>[0];\ntype BlurEvent = Parameters<NonNullable<ThemedTextInputProps['onBlur']>>[0];\ntype SubmitEvent = Parameters<NonNullable<ThemedTextInputProps['onSubmitEditing']>>[0];\n\nexport interface RecentInputFieldProps extends ThemedTextInputProps {\n /** Namespace under which this input's submitted values are remembered. */\n recentKey: string;\n /** Cap on remembered values (most-recent-first). Defaults to the hook's own default. */\n recentMax?: number;\n /** The field's accessible name — used to build the recents menu/row a11y strings. */\n label: string;\n}\n\nexport function RecentInputField({\n recentKey,\n recentMax,\n label,\n value,\n testID,\n onChangeText,\n onSubmitEditing,\n onFocus,\n onBlur,\n ...rest\n}: RecentInputFieldProps): React.ReactElement {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const { recents, remember } = useRecentValues(recentKey, recentMax);\n\n const anchorRef = useRef<View>(null);\n // Latest text, tracked independently of whether the field is controlled, so blur/submit can\n // remember the right value even when the parent does not pass `value`.\n const latestText = useRef<string>(typeof value === 'string' ? value : '');\n const [isOpen, setIsOpen] = useState(false);\n\n const handleChange = useCallback(\n (text: string) => {\n latestText.current = text;\n onChangeText?.(text);\n },\n [onChangeText],\n );\n\n const handleFocus = useCallback(\n (event: FocusEvent) => {\n setIsOpen(true);\n onFocus?.(event);\n },\n [onFocus],\n );\n\n const handleBlur = useCallback(\n (event: BlurEvent) => {\n // Remember on blur-with-content so \"typed then clicked away\" is captured, not only Enter.\n if (latestText.current.trim() !== '') remember(latestText.current);\n // Delay the close so a pointer-down on a recent row lands before the menu unmounts.\n setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS);\n onBlur?.(event);\n },\n [remember, onBlur],\n );\n\n const handleSubmit = useCallback(\n (event: SubmitEvent) => {\n remember(latestText.current);\n setIsOpen(false);\n onSubmitEditing?.(event);\n },\n [remember, onSubmitEditing],\n );\n\n const pick = useCallback(\n (picked: string) => {\n latestText.current = picked;\n onChangeText?.(picked);\n remember(picked);\n setIsOpen(false);\n },\n [onChangeText, remember],\n );\n\n const options: ControlOption[] = recents.map((entry) => ({ label: entry, value: entry }));\n const showMenu = isOpen && options.length > 0;\n const recentTestID = testID !== undefined ? `${testID}-recent` : 'form-field-recent';\n\n return (\n <View ref={anchorRef} style={s.anchor}>\n <ThemedTextInput\n {...rest}\n testID={testID}\n value={value}\n onChangeText={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onSubmitEditing={handleSubmit}\n />\n {showMenu ? (\n <AnchoredMenu\n accessibilityLabel={`Recent ${label} values`}\n anchorRef={anchorRef}\n colors={{ text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary['500'] }}\n onDismiss={() => setIsOpen(false)}\n onSelect={pick}\n optionHint={`Fill ${label} with this recent value`}\n options={options}\n selectedValue={typeof value === 'string' ? value : ''}\n testID={recentTestID}\n // Portal to document.body: the recents list sits above later-painting content (rows, cards,\n // the next field). Without the portal RN-web's trapped z-index paints it behind them.\n usePortal\n />\n ) : null}\n </View>\n );\n}\n\nexport default RecentInputField;\n","/**\n * Reusable form field — labelled text input with optional required mark + error.\n *\n * The label row, the required mark, the error line and the container spacing all come from the\n * generic `Field` wrapper, so a `FormField` and a `Field`-wrapped dropdown sitting next to each\n * other line up exactly and can never drift apart. FormField only adds the control itself.\n *\n * The input is the shared `ThemedTextInput` primitive, so every FormField gets the readable +\n * lively treatment (dark text, subtle off-white rest background, brand focus animation with a\n * soft ring) for free, driven by the active theme.\n */\nimport React from 'react';\n\nimport { type TextInputProps, type ViewStyle } from 'react-native';\n\nimport { Field } from '../Field/Field';\nimport { RecentInputField } from './RecentInputField';\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\n/**\n * The private `styles.input` that used to live here — padding 10/12, radius 8, border 1 — was a\n * verbatim duplicate of `controlStyles.input`, and `ThemedTextInput` now applies that itself. The\n * duplication is what hid the real defect: because `FormField` supplied metrics, inputs reached\n * through it looked correct, while every DIRECT `ThemedTextInput` caller got an unstyled 19px box\n * and nobody could see the difference from in here.\n */\nexport interface FormFieldProps extends Omit<TextInputProps, 'style'> {\n label: string;\n /**\n * Hide the VISIBLE label row while keeping the accessible name.\n *\n * For a field whose placeholder already names it (a toolbar search box, an inline\n * filter) the stacked visible label both wastes a row and misaligns the input\n * against a bare button beside it. Setting this drops ONLY the visible `<label>`:\n * the input still carries `accessibilityLabel={label}`, so a screen reader reads\n * the same name and `label` stays REQUIRED — you never lose the accessible name by\n * blanking it, which is the trap this option exists to remove. Default `false`.\n */\n labelHidden?: boolean;\n required?: boolean;\n error?: string;\n containerStyle?: ViewStyle;\n /**\n * OPT-IN \"recent values\" behaviour. When set, the values submitted through this field are\n * remembered (per this key) and offered in a dropdown on focus; picking one fills the input.\n * Values are recorded on submit (Enter) and on blur-with-content. Persisted to `localStorage`\n * under `@dloizides/ui-forms:recent:<recentKey>`; a silent no-op on native / when storage is\n * unavailable.\n *\n * Leave it UNSET (the default) and the field behaves exactly as before — nothing rendered, no\n * storage touched. NEVER set it on a password / secure field: recents must not persist secrets.\n */\n recentKey?: string;\n /** Cap on remembered values when {@link recentKey} is set (most-recent-first). Default 10. */\n recentMax?: number;\n}\n\nexport const FormField = ({\n label,\n labelHidden = false,\n required = false,\n error,\n containerStyle,\n recentKey,\n recentMax,\n ...textInputProps\n}: FormFieldProps): React.ReactElement => (\n <Field\n containerStyle={containerStyle}\n error={error}\n // An undefined label renders NO label row (see Field): that is how the visible\n // label is hidden. The accessible name is kept on the input below, so hiding\n // the label never strips the name.\n label={labelHidden ? undefined : label}\n required={required}\n >\n {({ describedById, hasError, controlId }) => {\n // Shared props for either input path — identical wiring, so a field looks and behaves the\n // same whether or not it opts into recents.\n const inputProps = {\n accessibilityHint: `Enter ${label}`,\n accessibilityLabel: label,\n describedById,\n hasError,\n id: controlId,\n requiredField: required,\n testID: 'form-field-input',\n ...textInputProps,\n };\n // recentKey set → the recents-enabled input; unset → the plain input, unchanged from before\n // (no extra state/refs/effects/storage — the default path pays nothing).\n return recentKey !== undefined && recentKey !== '' ? (\n <RecentInputField label={label} recentKey={recentKey} recentMax={recentMax} {...inputProps} />\n ) : (\n <ThemedTextInput {...inputProps} />\n );\n }}\n </Field>\n);\n\nexport default FormField;\n","/** Shared ChipSelector constants. */\n\nexport const TRANSPARENT_COLOR = 'transparent';\n\n/**\n * Extra touch margin around a chip. NATIVE ONLY — this does NOT widen the hit area on RN-web,\n * which is what these portals ship. Measured 2026-09-21 (headless Chromium, 360x640):\n * `elementFromPoint` 5px above a chip's top edge, inside `top: 10`, returns the parent, not the\n * chip. react-native-web 0.21.2 uses `hitSlop` only in the legacy `Touchable` press-retention\n * path and ignores it entirely in `Pressable`. The web target is carried by `minHeight:\n * MIN_TARGET_PX` in `chipStyles`; this constant only helps iOS/Android.\n */\nexport const CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 } as const;\n\n/** Gap between adjacent chips, horizontally and between wrapped rows. */\nexport const CHIP_GUTTER = 8;\n\n/**\n * Default chip testID stem. NOT derived from the `testID` prop, because aml-v2's unit +\n * Playwright specs and erevna/katalogos's `Accessibility.test.tsx` already select on\n * `chip-selector-chip-<value>`. `chipTestIDPrefix` is the opt-in override for consumers\n * (kefi) that need their own stem; the default is frozen.\n */\nexport const DEFAULT_CHIP_TESTID_PREFIX = 'chip-selector-chip';\n","import { StyleSheet } from 'react-native';\n\nimport { TRANSPARENT_COLOR } from '../constants';\n\nconst SOLID_RADIUS = 20;\nconst OUTLINE_RADIUS = 999;\nconst OUTLINE_PAD_H = 12;\nconst OUTLINE_PAD_V = 5;\nconst OUTLINE_FONT_SIZE = 13;\n/** Gap between an option's icon and its label. */\nconst CHIP_ICON_GAP = 6;\n/**\n * WCAG minimum touch-target edge, in CSS px. Source of truth is `MIN_TARGET_PX` in\n * `@dloizides/ui-layout`; duplicated here as a local constant rather than taking a whole\n * dependency for one integer. Keep the two in step if ui-layout ever changes it.\n *\n * Needed because `hitSlop` is NATIVE-ONLY: measured 2026-09-21 in headless Chromium at 360px,\n * `document.elementFromPoint` 5px above a chip (inside `CHIP_HIT_SLOP.top: 10`) returns the\n * PARENT, not the chip. react-native-web 0.21.2 references `hitSlop` only in the legacy\n * `Touchable` mixin's press-RETENTION path and not at all in `Pressable`, so on web the\n * rendered box IS the whole tappable area.\n */\nconst MIN_TARGET_PX = 44;\n\nexport const chipStyles = StyleSheet.create({\n chip: {\n paddingHorizontal: 12,\n paddingVertical: 6,\n minHeight: MIN_TARGET_PX,\n justifyContent: 'center',\n borderRadius: SOLID_RADIUS,\n backgroundColor: TRANSPARENT_COLOR,\n borderWidth: 1,\n },\n chipOutline: {\n paddingHorizontal: OUTLINE_PAD_H,\n paddingVertical: OUTLINE_PAD_V,\n minHeight: MIN_TARGET_PX,\n justifyContent: 'center',\n borderRadius: OUTLINE_RADIUS,\n borderWidth: 1,\n },\n chipContent: { flexDirection: 'row', alignItems: 'center', gap: CHIP_ICON_GAP },\n chipText: {},\n chipTextOutline: { fontSize: OUTLINE_FONT_SIZE },\n});\n","import React from 'react';\n\nimport { Text, View, type StyleProp, type TextStyle } from 'react-native';\n\nimport { chipStyles } from './chipStyles';\n\ninterface ChipContentProps {\n icon: React.ReactNode;\n label: string;\n textStyle: StyleProp<TextStyle>;\n}\n\n/** Chip label, preceded by the option's decorative icon when one is supplied. */\nexport function ChipContent({ icon, label, textStyle }: ChipContentProps): React.ReactElement {\n const text = <Text style={textStyle}>{label}</Text>;\n if (icon === undefined || icon === null)\n return text;\n\n return (\n <View style={chipStyles.chipContent}>\n <View aria-hidden={true}>{icon}</View>\n {text}\n </View>\n );\n}\n","import React from 'react';\n\nimport { Pressable, View } from 'react-native';\n\nimport { CHIP_HIT_SLOP } from '../constants';\nimport type { ChipProps } from '../types';\n\nimport { ChipContent } from './ChipContent';\nimport { chipStyles } from './chipStyles';\n\n/** A single outline chip — owns its own hover state (web) for the border/ink lift. */\nexport function OutlineChip<T extends string | number>(props: ChipProps<T>): React.ReactElement {\n const { option, selected, disabled, colors, testID, accessibilityHint, onPress } = props;\n const [hovered, setHovered] = React.useState(false);\n const active = selected || hovered;\n\n const borderColor = active ? colors.primary : colors.border;\n const backgroundColor = selected ? colors.tint : colors.muted;\n // Selected AND hovered both lift the ink to the primary colour (v1's indigo / indigo-dark);\n // the theme surface only guarantees the 500 step, so both use it — border + fill carry the state.\n const textColor = active ? colors.primary : colors.textMuted;\n\n return (\n <Pressable\n ref={props.hostRef}\n accessibilityHint={accessibilityHint}\n accessibilityLabel={option.label}\n accessibilityRole={props.accessibilityRole}\n accessibilityState={{ selected, disabled }}\n aria-checked={props.ariaChecked}\n aria-pressed={props.ariaPressed}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n tabIndex={props.tabIndex}\n testID={testID}\n onHoverIn={() => setHovered(true)}\n onHoverOut={() => setHovered(false)}\n onPress={onPress}\n >\n <View style={[chipStyles.chipOutline, { borderColor, backgroundColor }]}>\n <ChipContent\n icon={option.icon}\n label={option.label}\n textStyle={[chipStyles.chipText, chipStyles.chipTextOutline, { color: textColor }]}\n />\n </View>\n </Pressable>\n );\n}\n","import React from 'react';\n\nimport { TouchableOpacity, View, type ViewProps } from 'react-native';\n\nimport { CHIP_HIT_SLOP, TRANSPARENT_COLOR } from '../constants';\nimport type { ChipProps } from '../types';\n\nimport { ChipContent } from './ChipContent';\nimport { chipStyles } from './chipStyles';\n\n/** A single solid chip — the original filled-pill look (unchanged for existing consumers). */\nexport function SolidChip<T extends string | number>(props: ChipProps<T>): React.ReactElement {\n const { option, selected, disabled, colors, testID, accessibilityHint, onPress } = props;\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? colors.onPrimary : colors.textStrong;\n // RNW forwards `tabIndex` to the DOM, but RN's TouchableOpacity types omit it (ViewProps has it).\n const rovingTabStop: Pick<ViewProps, 'tabIndex'> = { tabIndex: props.tabIndex };\n return (\n <TouchableOpacity\n ref={props.hostRef}\n accessibilityHint={accessibilityHint}\n accessibilityLabel={option.label}\n accessibilityRole={props.accessibilityRole}\n accessibilityState={{ selected, disabled }}\n aria-checked={props.ariaChecked}\n aria-pressed={props.ariaPressed}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n testID={testID}\n onPress={onPress}\n {...rovingTabStop}\n >\n <View style={[chipStyles.chip, { borderColor: colors.border, backgroundColor }]}>\n <ChipContent icon={option.icon} label={option.label} textStyle={[chipStyles.chipText, { color: textColor }]} />\n </View>\n </TouchableOpacity>\n );\n}\n","/**\n * Pure key logic for the WAI-ARIA radio group pattern used by ChipSelector's opt-in radio mode.\n * Kept free of React and the DOM so every branch is unit-testable without rendering.\n */\n\nconst SPACE_KEYS: readonly string[] = [' ', 'Spacebar'];\nconst NEXT_KEYS: readonly string[] = ['ArrowRight', 'ArrowDown'];\nconst PREVIOUS_KEYS: readonly string[] = ['ArrowLeft', 'ArrowUp'];\nconst ROVING_TAB_STOP = 0;\nconst ROVING_SKIPPED = -1;\n\n/**\n * The option index a radio group should select when `key` is pressed on the chip at `index`,\n * or `null` when the key is not part of the pattern.\n *\n * - Space activates the focused chip (returns `index`).\n * - ArrowRight/ArrowDown → next chip, ArrowLeft/ArrowUp → previous, wrapping at both ends.\n * - Enter is deliberately `null`: RNW's press responder already activates a `<div>` chip on\n * Enter, so handling it here would fire `onChange` twice.\n * - Arrows in a one-chip group are `null` — there is nowhere to move, so nothing is selected.\n */\nexport function radioKeyTarget(key: string, index: number, count: number): number | null {\n const isOutOfRange = index < 0 || index >= count;\n if (isOutOfRange)\n return null;\n\n if (SPACE_KEYS.includes(key))\n return index;\n\n const isArrow = NEXT_KEYS.includes(key) || PREVIOUS_KEYS.includes(key);\n if (!isArrow || count === 1)\n return null;\n\n const step = NEXT_KEYS.includes(key) ? 1 : -1;\n return (index + step + count) % count;\n}\n\n/**\n * Roving tabindex: only the selected chip — or the first chip when nothing is selected — is a\n * tab stop. A disabled group has no tab stop at all.\n */\nexport function radioTabIndex(index: number, selectedIndex: number, disabled: boolean): 0 | -1 {\n if (disabled)\n return ROVING_SKIPPED;\n\n const tabStop = selectedIndex >= 0 ? selectedIndex : 0;\n return index === tabStop ? ROVING_TAB_STOP : ROVING_SKIPPED;\n}\n","/**\n * Keyboard + focus wiring for ChipSelector's opt-in radio group.\n *\n * One `onKeyDown` sits on the radiogroup container and catches the key events bubbling up from\n * the focused chip. It lives on the GROUP, not the chip, because RNW's `TouchableOpacity` spreads\n * its press handlers AFTER the caller's props — a chip-level `onKeyDown` on the solid variant is\n * silently overwritten. The focused chip is identified by matching `event.target` against the\n * host nodes registered through `chipRef`.\n */\nimport React from 'react';\n\nimport type { ViewProps } from 'react-native';\n\nimport { radioKeyTarget, radioTabIndex } from '../utils/radioKeyboard';\n\ninterface FocusableNode {\n focus?: () => void;\n}\n\ninterface RadioKeyEvent {\n key: string;\n target: unknown;\n preventDefault: () => void;\n}\n\nexport interface RadioKeyboardConfig<T> {\n /** `false` for button / multi-select groups: the hook then emits nothing at all. */\n enabled: boolean;\n disabled: boolean;\n values: T[];\n /** Index of the selected option, or `-1` when nothing is selected. */\n selectedIndex: number;\n onChange: (value: T) => void;\n}\n\nexport interface RadioKeyboard {\n /** Ref callback factory registering the host node of the chip at `index`. */\n chipRef: (index: number) => (node: unknown) => void;\n /** Roving tabindex for the chip at `index`; `undefined` when radio mode is off. */\n tabIndexFor: (index: number) => 0 | -1 | undefined;\n /** Web props for the group container (`onKeyDown` in radio mode, nothing otherwise). */\n groupProps: ViewProps;\n}\n\nconst NO_GROUP_PROPS: ViewProps = {};\n\nexport function useRadioKeyboard<T>(config: RadioKeyboardConfig<T>): RadioKeyboard {\n const { enabled, disabled, values, selectedIndex, onChange } = config;\n const nodes = React.useRef<unknown[]>([]);\n\n const chipRef = React.useCallback((index: number) => (node: unknown): void => {\n nodes.current[index] = node;\n }, []);\n\n const onKeyDown = (event: RadioKeyEvent): void => {\n if (disabled)\n return;\n\n const index = nodes.current.indexOf(event.target);\n const target = radioKeyTarget(event.key, index, values.length);\n const nextValue = target === null ? undefined : values[target];\n if (target === null || nextValue === undefined)\n return;\n\n // Stops Space scrolling the page and arrows scrolling a scroll container.\n event.preventDefault();\n if (target !== index)\n (nodes.current[target] as FocusableNode | null | undefined)?.focus?.();\n\n onChange(nextValue);\n };\n\n return {\n chipRef,\n tabIndexFor: (index) => (enabled ? radioTabIndex(index, selectedIndex, disabled) : undefined),\n // `onKeyDown` is a web-only View prop RN's types do not declare; RNW forwards it to the DOM.\n groupProps: enabled ? ({ onKeyDown } as unknown as ViewProps) : NO_GROUP_PROPS,\n };\n}\n","/** Theme → chip colour resolution for both ChipSelector variants. */\nimport type { ChipColors } from '../types';\n\nconst WHITE_COLOR = '#fff';\nconst OUTLINE_TINT_ALPHA = 0.1;\nconst HEX_SHORT_LENGTH = 3;\nconst HEX_RADIX = 16;\nconst RGB_R_START = 0;\nconst RGB_R_END = 2;\nconst RGB_G_END = 4;\nconst RGB_B_END = 6;\n\n/** Palette scale carrying the ink for content sitting ON the brand colour. */\nconst ON_BRAND_SCALE = 'onBrand';\n/** The one step every theme scale is guaranteed to define. */\nconst MAIN_STEP = '500';\n\n/**\n * Read the on-brand ink out of a theme palette.\n *\n * Deliberately typed as OPTIONAL rather than read through `palette.onBrand`. Two reasons:\n * this package's declared peer floor is `ui-feedback >= 1.1.0`, whose palette type has no\n * index signature at all; and even on current versions the index signature types every\n * scale as present, which is a lie — only `primary` is guaranteed, and most apps in the\n * fleet publish no `onBrand` scale today. Modelling it as absent-able is what makes the\n * `WHITE_COLOR` fallback honest instead of dead code.\n */\nfunction onBrandInk(palette: object): string {\n const scales = palette as Record<string, Record<string, string> | undefined>;\n return scales[ON_BRAND_SCALE]?.[MAIN_STEP] ?? WHITE_COLOR;\n}\n\n/** Composite a hex colour over the background at a given alpha (theme-driven tint). */\nfunction withAlpha(hex: string, alpha: number): string {\n const normalized = hex.replace('#', '');\n const isShort = normalized.length === HEX_SHORT_LENGTH;\n const full = isShort ? normalized.split('').map((c) => c + c).join('') : normalized;\n const r = parseInt(full.slice(RGB_R_START, RGB_R_END), HEX_RADIX);\n const g = parseInt(full.slice(RGB_R_END, RGB_G_END), HEX_RADIX);\n const b = parseInt(full.slice(RGB_G_END, RGB_B_END), HEX_RADIX);\n const isValid = !Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b);\n return isValid ? `rgba(${r}, ${g}, ${b}, ${alpha})` : hex;\n}\n\ninterface ThemeColorsInput {\n border: string;\n text: string;\n textSecondary: string;\n background: string;\n}\n\n/** Resolve the colours both chip variants read, from the active theme's colours + palette. */\nexport function buildChipColors(\n colors: ThemeColorsInput,\n palette: { primary: { 500: string } },\n): ChipColors {\n const primary = palette.primary[500];\n return {\n border: colors.border,\n textStrong: colors.text,\n textMuted: colors.textSecondary,\n primary,\n onPrimary: onBrandInk(palette),\n muted: colors.background,\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\n };\n}\n","import type { ChipOption, ChipProps } from '../types';\n\n/**\n * The a11y + testID triple a chip needs, resolved once for both variants.\n *\n * Exported for direct unit testing. It has to be tested as a pure function rather than\n * through the DOM because react-native-web DROPS `accessibilityHint` entirely — it reaches\n * native, but no web attribute carries it, so no rendering assertion can tell a correctly\n * threaded hint from one that was never passed. Testing the resolver is the only honest way\n * to pin the behaviour.\n */\nexport function chipIdentity<T>(\n option: ChipOption<T>,\n selected: boolean,\n config: { prefix: string; hint?: string; multiple: boolean; radio?: boolean },\n): Pick<ChipProps<T>, 'testID' | 'accessibilityHint' | 'ariaPressed' | 'accessibilityRole' | 'ariaChecked'> {\n const isRadio = config.radio === true && !config.multiple;\n return {\n testID: `${config.prefix}-${String(option.value)}`,\n // The English default is retained verbatim: erevna/katalogos assert the exact string\n // `Selects Red`. Consumers that localize pass `optionAccessibilityHint`.\n accessibilityHint: config.hint ?? `Selects ${option.label}`,\n ariaPressed: config.multiple ? selected : undefined,\n accessibilityRole: isRadio ? 'radio' : 'button',\n ariaChecked: isRadio ? selected : undefined,\n };\n}\n","/**\n * Chip/pill selector for selecting one or multiple options.\n *\n * Two visual variants (both fully theme-driven):\n * - `solid` (default) — the original filled-pill look: selected = solid primary fill with\n * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.\n * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle\n * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.\n * Hover (web) lifts the border/ink to the primary colour.\n *\n * The label row, the error line and the container spacing come from the shared `Field` wrapper —\n * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes\n * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),\n * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the\n * column and read as a different weight of text. Now there is exactly one label implementation.\n *\n * Structure: chip variants in `components/`, the radio keyboard wiring in `hooks/`, and the pure\n * resolvers (`chipIdentity`, colours, radio key logic) in `utils/`.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, type ViewProps } from 'react-native';\n\nimport { webFieldA11y } from '../webFieldA11y/webFieldA11y';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { Field } from '../Field/Field';\n\nimport { OutlineChip } from './components/OutlineChip';\nimport { SolidChip } from './components/SolidChip';\nimport { CHIP_GUTTER, DEFAULT_CHIP_TESTID_PREFIX } from './constants';\nimport { useRadioKeyboard } from './hooks/useRadioKeyboard';\nimport type { ChipColors, ChipOption, ChipSelectorProps } from './types';\nimport { buildChipColors } from './utils/chipColors';\nimport { chipIdentity } from './utils/chipIdentity';\n\nconst styles = StyleSheet.create({\n chipContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n // `gap`, NOT per-chip margins plus a compensating negative container margin.\n //\n // The old form was `chipWrapper { marginRight: 8, marginBottom: 8 }` with\n // `chipContainer { marginBottom: -8 }`. Its comment blamed `Field`'s 16px container margin —\n // that was WRONG, and worth recording: F3 was briefed on the belief that the -8 compensated for\n // `Field` and had to move in lockstep with it. It did not. -8 cancelled the CHIP's own gutter\n // hanging off the last row, identically whether `Field` contributed 16, 0, or anything else.\n //\n // The pair is still the wrong tool: it holds only while the two constants agree, and it leaves\n // a real negative margin any measuring parent inherits. `gap` produces the byte-identical box\n // and is correct under BOTH of `Field`'s spacing models, not just the one it was tuned against.\n gap: CHIP_GUTTER,\n },\n});\n\n/*\n * `groupA11yProps` + its local `WebGroupA11y` type used to live here — a copy of\n * ThemedTextInput's branch, as its own comment admitted. Both now call `webFieldA11y`.\n * The chip group passes no `required`, so nothing is emitted for it, exactly as before.\n */\n\nexport const ChipSelector = <T extends string | number>({\n label,\n options,\n value,\n onChange,\n multiple = false,\n disabled = false,\n variant = 'solid',\n containerStyle,\n spacing,\n required = false,\n error,\n testID,\n chipTestIDPrefix = DEFAULT_CHIP_TESTID_PREFIX,\n optionAccessibilityHint,\n singleSelectRole = 'button',\n}: ChipSelectorProps<T>): React.ReactElement => {\n const isRadioGroup = !multiple && singleSelectRole === 'radio';\n const { theme } = useUi();\n const { colors, palette } = theme;\n\n const chipColors = React.useMemo<ChipColors>(() => buildChipColors(colors, palette), [colors, palette]);\n\n function isSelected(optionValue: T): boolean {\n if (multiple && Array.isArray(value))\n return value.includes(optionValue);\n\n return value === optionValue;\n }\n\n const radio = useRadioKeyboard({\n enabled: isRadioGroup,\n disabled,\n values: options.map((option) => option.value),\n selectedIndex: options.findIndex((option) => isSelected(option.value)),\n onChange,\n });\n\n function renderChip(option: ChipOption<T>, index: number): React.ReactElement {\n const selected = isSelected(option.value);\n const chipProps = {\n colors: chipColors,\n disabled,\n option,\n selected,\n ...chipIdentity(option, selected, {\n prefix: chipTestIDPrefix,\n hint: optionAccessibilityHint,\n multiple,\n radio: isRadioGroup,\n }),\n // Radio mode only: roving tab stop + host node for arrow-key focus moves. Both stay\n // `undefined` otherwise, so button / multi chips keep their existing tab order.\n tabIndex: radio.tabIndexFor(index),\n hostRef: isRadioGroup ? radio.chipRef(index) : undefined,\n onPress: (): void => onChange(option.value),\n };\n const key = String(option.value);\n return variant === 'outline' ? <OutlineChip key={key} {...chipProps} /> : <SolidChip key={key} {...chipProps} />;\n }\n\n return (\n <Field\n containerStyle={containerStyle}\n error={error}\n label={label}\n required={required}\n spacing={spacing}\n testID={testID}\n >\n {({ describedById, hasError }) => (\n <View\n accessibilityRole={isRadioGroup ? 'radiogroup' : undefined}\n style={styles.chipContainer}\n {...(webFieldA11y({ describedById, hasError }) as ViewProps)}\n {...radio.groupProps}\n >\n {options.map(renderChip)}\n </View>\n )}\n </Field>\n );\n};\n\nexport default ChipSelector;\n","/**\n * Reusable form switch/toggle with an optional description.\n */\nimport React from \"react\";\n\nimport {\n StyleSheet,\n View,\n Text,\n Switch,\n Pressable,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\n\nimport { MIN_TOUCH_TARGET_PX } from \"@dloizides/a11y\";\nimport { useUi } from \"@dloizides/ui-feedback\";\n\nconst DESCRIPTION_FONT_SIZE = 12;\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 12,\n // The ROW is the hit box (SHOWCASE-1): RN-web renders Switch as a 40x20 box and ignores\n // `hitSlop`, so a pointer target smaller than the floor cannot be widened any other way.\n minHeight: MIN_TOUCH_TARGET_PX,\n },\n textColumn: {\n flex: 1,\n },\n label: {\n fontWeight: \"600\",\n },\n description: {\n fontSize: DESCRIPTION_FONT_SIZE,\n marginTop: 2,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n description: TextStyle;\n}\n\nexport interface FormSwitchProps {\n label: string;\n value: boolean;\n onValueChange: (value: boolean) => void;\n disabled?: boolean;\n description?: string;\n containerStyle?: ViewStyle;\n testID?: string;\n accessibilityHint?: string;\n}\n\nexport const FormSwitch = ({\n label,\n value,\n onValueChange,\n disabled = false,\n description,\n containerStyle,\n testID = \"form-switch\",\n accessibilityHint,\n}: FormSwitchProps): React.ReactElement => {\n const { theme } = useUi();\n const toggle = React.useCallback((): void => {\n if (!disabled) onValueChange(!value);\n }, [disabled, onValueChange, value]);\n const { colors } = theme;\n const hasDescription = typeof description === \"string\" && description !== \"\";\n\n const themeStyles = React.useMemo<ThemeStyles>(() => {\n const labelStyle: TextStyle = { color: colors.text };\n const descriptionStyle: TextStyle = { color: colors.textSecondary };\n return { label: labelStyle, description: descriptionStyle };\n }, [colors.text, colors.textSecondary]);\n\n return (\n /*\n Pointer target only: the whole row toggles on press. It is NOT an a11y element and NOT a tab\n stop (`accessible` / `focusable` false) so the native input below stays the ONE switch. The\n Switch sits under `pointerEvents=\"none\"`, so a tap on it reaches this row exactly once\n instead of toggling twice; keyboard focus + Space still reach the input directly.\n */\n <Pressable\n accessible={false}\n disabled={disabled}\n onPress={toggle}\n style={[styles.container, containerStyle]}\n // RN-web's Pressable always stamps a tabIndex (0, or -1 when disabled) and only an explicit\n // one overrides it — `focusable={false}` does not. -1 keeps the row out of the tab order.\n tabIndex={-1}\n testID={`${testID}-row`}\n >\n <View style={styles.textColumn}>\n <Text style={[styles.label, themeStyles.label]}>{label}</Text>\n {hasDescription ? (\n <Text style={[styles.description, themeStyles.description]}>\n {description}\n </Text>\n ) : null}\n </View>\n {/*\n Exactly ONE element exposes the switch (A11Y-ARIA-CHECKED-1). On web, react-native-web's\n Switch renders a wrapper <div> around a native <input type=\"checkbox\" role=\"switch\"> that\n already carries `checked` / `disabled` — the state assistive tech reads (HTML-AAM maps\n `checked` to the checked state, so no `aria-checked` is needed or allowed on it).\n Passing `accessibilityRole=\"switch\"` here put a SECOND `role=\"switch\"` on the wrapper,\n which RNW then made a `tabindex=\"0\"` stop even when disabled; literal `aria-checked` /\n `aria-disabled` would land on that role-less wrapper too. So neither is passed: the\n wrapper is plain and unfocusable, and native keeps its `switch` role from RN's Switch\n default (`accessibilityRole ?? 'switch'`) plus `accessibilityState` below.\n */}\n <View pointerEvents=\"none\">\n <Switch\n accessibilityHint={accessibilityHint ?? label}\n accessibilityLabel={label}\n accessibilityState={{ checked: value, disabled }}\n disabled={disabled}\n testID={testID}\n value={value}\n onValueChange={onValueChange}\n />\n </View>\n </Pressable>\n );\n};\n\nexport default FormSwitch;\n","/**\n * Reusable, native-safe checkbox — a themed `Pressable` (works on RN-web AND native, where RN has\n * no built-in checkbox). A small rounded square that fills with the brand colour and shows a check\n * glyph when on, with a label and an optional hint. Mirrors `FormSwitch`'s prop shape so it is a\n * drop-in replacement for the boolean toggles v1 renders as checkboxes.\n */\nimport React from 'react';\n\nimport { Platform, StyleSheet, View, Text, Pressable, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { MIN_TOUCH_TARGET_PX } from '@dloizides/a11y';\nimport { useUi } from '@dloizides/ui-feedback';\n\n/**\n * Web-only keydown prop react-native-web's `Pressable` forwards but RN's types omit. A\n * `role=\"checkbox\"` Pressable renders a `<div>` (not a native `<button>`), so — unlike a\n * button-role Pressable — it gets NO free Enter/Space activation. We add it explicitly so the\n * checkbox is keyboard-operable (WCAG 2.1.1). `preventDefault()` stops Space from scrolling.\n */\ninterface WebKeyboardProps {\n onKeyDown?: (event: { key?: string; preventDefault?: () => void }) => void;\n}\n\nconst ACTIVATION_KEYS = ['Enter', ' ', 'Spacebar'];\n\nconst HINT_FONT_SIZE = 12;\nconst BOX_SIZE = 20;\nconst BOX_RADIUS = 5;\nconst CHECK_FONT_SIZE = 14;\nconst DISABLED_OPACITY = 0.5;\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: 'row',\n alignItems: 'flex-start',\n gap: 10,\n marginBottom: 12,\n // The whole row is the Pressable, so the row IS the hit box: on RN-web `hitSlop` is inert and a\n // one-line label measured 36px tall (SHOWCASE-1). The 20px visual box keeps its size inside.\n minHeight: MIN_TOUCH_TARGET_PX,\n },\n /** With no hint the row is a single line, so centre it vertically inside the floor. */\n centered: {\n alignItems: 'center',\n },\n box: {\n width: BOX_SIZE,\n height: BOX_SIZE,\n borderRadius: BOX_RADIUS,\n borderWidth: 2,\n alignItems: 'center',\n justifyContent: 'center',\n // Nudge the box to sit on the label's first text line.\n marginTop: 1,\n },\n check: {\n fontSize: CHECK_FONT_SIZE,\n fontWeight: '700',\n lineHeight: CHECK_FONT_SIZE,\n },\n textColumn: {\n flex: 1,\n },\n label: {\n fontWeight: '600',\n },\n hint: {\n fontSize: HINT_FONT_SIZE,\n marginTop: 2,\n },\n});\n\nexport interface FormCheckboxProps {\n label: string;\n value: boolean;\n /** Primary change handler (mirrors `FormSwitch`). `onChange` is accepted as an alias. */\n onValueChange?: (value: boolean) => void;\n /** Alias for `onValueChange` so either name works as a drop-in. */\n onChange?: (value: boolean) => void;\n /** Optional secondary description shown under the label. `description` is accepted as an alias. */\n hint?: string;\n description?: string;\n disabled?: boolean;\n containerStyle?: ViewStyle;\n testID?: string;\n accessibilityLabel?: string;\n accessibilityHint?: string;\n}\n\nexport const FormCheckbox = ({\n label,\n value,\n onValueChange,\n onChange,\n hint,\n description,\n disabled = false,\n containerStyle,\n testID = 'form-checkbox',\n accessibilityLabel,\n accessibilityHint,\n}: FormCheckboxProps): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const brand = palette.primary['500'];\n const hintText = typeof hint === 'string' && hint !== '' ? hint : description;\n const hasHint = typeof hintText === 'string' && hintText !== '';\n\n const themeStyles = React.useMemo(() => {\n const boxOn: ViewStyle = { backgroundColor: brand, borderColor: brand };\n const boxOff: ViewStyle = { backgroundColor: 'transparent', borderColor: colors.border };\n const labelStyle: TextStyle = { color: colors.text };\n const hintStyle: TextStyle = { color: colors.textSecondary };\n return { boxOn, boxOff, label: labelStyle, hint: hintStyle };\n }, [brand, colors.border, colors.text, colors.textSecondary]);\n\n const toggle = (): void => {\n const next = !value;\n if (onValueChange) onValueChange(next);\n if (onChange) onChange(next);\n };\n\n const handleKeyDown = (event: { key?: string; preventDefault?: () => void }): void => {\n if (disabled) return;\n const key = event.key ?? '';\n if (!ACTIVATION_KEYS.includes(key)) return;\n if (typeof event.preventDefault === 'function') event.preventDefault();\n toggle();\n };\n\n const keyboardProps: WebKeyboardProps = Platform.OS === 'web' ? { onKeyDown: handleKeyDown } : {};\n\n return (\n <Pressable\n accessibilityHint={accessibilityHint ?? label}\n accessibilityLabel={accessibilityLabel ?? label}\n accessibilityRole=\"checkbox\"\n accessibilityState={{ checked: value, disabled }}\n // RN-web maps this to the ARIA `role=\"checkbox\"` + `aria-checked` a screen reader announces.\n aria-checked={value}\n disabled={disabled}\n onPress={toggle}\n role=\"checkbox\"\n style={[\n styles.container,\n hasHint ? null : styles.centered,\n containerStyle,\n disabled ? { opacity: DISABLED_OPACITY } : null,\n ]}\n testID={testID}\n {...keyboardProps}\n >\n <View style={[styles.box, value ? themeStyles.boxOn : themeStyles.boxOff]}>\n {value ? (\n <Text style={[styles.check, { color: colors.surface }]} accessibilityElementsHidden>\n ✓\n </Text>\n ) : null}\n </View>\n <View style={styles.textColumn}>\n <Text style={[styles.label, themeStyles.label]}>{label}</Text>\n {hasHint ? <Text style={[styles.hint, themeStyles.hint]}>{hintText}</Text> : null}\n </View>\n </Pressable>\n );\n};\n\nexport default FormCheckbox;\n","/**\n * `SelectControl` — a single-select enum/status dropdown. A bordered trigger shows the selected\n * option's label (or the placeholder when unset) plus a chevron; pressing it opens the shared\n * {@link AnchoredMenu}. Selecting fires `onChange` and closes.\n *\n * Promoted out of `@dloizides/ui-tables`' private `Filters/fields/SelectField`, where six portals\n * could see it working and none could import it — which is why the fleet grew SIX independent\n * select implementations.\n *\n * The control is LABEL-FREE by design: wrap it in a `Field` (with `labelVariant=\"control\"` on a\n * dense surface) to get the label, hint and error slots. That keeps one label implementation for\n * every control instead of one per control.\n *\n * i18n: this package never calls `t`. `accessibilityLabel`, `placeholder`, `accessibilityHint`\n * and `optionHint` are PRE-LOCALIZED strings supplied by the caller — the only shape that can\n * serve both aml-v2's positional `{0}` `@dloizides/i18n` and the other six portals' i18next\n * `{{p1}}` from one component.\n */\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { AnchoredMenu } from '../AnchoredMenu/AnchoredMenu';\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\n\nconst CHEVRON_DOWN = '▾';\nconst CHEVRON_UP = '▴';\n\nexport interface SelectControlProps {\n options: readonly ControlOption[];\n /** The selected option's `value`. `''` (or any unmatched value) renders the placeholder. */\n value: string;\n onChange: (value: string) => void;\n /** PRE-LOCALIZED text shown when the value matches no option. */\n placeholder?: string;\n /**\n * PRE-LOCALIZED accessible NAME of the trigger. It REPLACES the trigger's visible text for a\n * screen reader, so it must carry the SELECTION too — \"Status: Active\", not just \"Status\",\n * which announces the control but silently hides its value.\n */\n accessibilityLabel: string;\n accessibilityHint?: string;\n /**\n * `id` of the `Field` label naming this control — take it from the render-child context's\n * `labelId`. The trigger is a `<div role=\"button\">`, which `<label for>` cannot address (that\n * only works for native form elements), so the association runs the other way: the trigger\n * points AT the label.\n *\n * `accessibilityLabel` still wins for the accessible NAME, deliberately — it is the only one of\n * the two that carries the current selection (\"Status: Active\"). This adds the structural link\n * without changing a single announcement.\n */\n labelledById?: string;\n /** PRE-LOCALIZED accessibility hint applied to every option in the menu. */\n optionHint?: string;\n /** Merged LAST onto the anchor wrapper — the consumer always wins over the shared style. */\n style?: StyleProp<ViewStyle>;\n /** Trigger is `${testID}-trigger`, menu `${testID}-menu`, options `${testID}-option-${value}`. */\n testID: string;\n}\n\nexport function SelectControl({\n options,\n value,\n onChange,\n placeholder = '',\n accessibilityLabel,\n accessibilityHint,\n labelledById,\n optionHint = '',\n style,\n testID,\n}: SelectControlProps): React.ReactElement {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const anchorRef = useRef<View>(null);\n const [isOpen, setIsOpen] = useState(false);\n\n const selectedLabel = useMemo(() => {\n const found = options.find((o) => o.value === value);\n return found?.label ?? placeholder;\n }, [options, placeholder, value]);\n\n const close = useCallback(() => { setIsOpen(false); }, []);\n const toggle = useCallback(() => { setIsOpen((prev) => !prev); }, []);\n const select = useCallback(\n (next: string) => {\n onChange(next);\n setIsOpen(false);\n },\n [onChange],\n );\n\n return (\n <View ref={anchorRef} style={[s.anchor, style]}>\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={accessibilityHint}\n accessibilityState={{ expanded: isOpen }}\n aria-expanded={isOpen}\n aria-labelledby={labelledById}\n onPress={toggle}\n style={[s.selectTrigger, { borderColor: colors.border, backgroundColor: colors.surface }]}\n testID={`${testID}-trigger`}\n >\n <Text numberOfLines={1} style={[s.selectTriggerText, { color: value === '' ? colors.textSecondary : colors.text }]}>\n {selectedLabel}\n </Text>\n <Text aria-hidden style={[s.chevron, { color: colors.textSecondary }]}>{isOpen ? CHEVRON_UP : CHEVRON_DOWN}</Text>\n </Pressable>\n {isOpen ? (\n <AnchoredMenu\n options={options}\n selectedValue={value}\n onSelect={select}\n onDismiss={close}\n colors={{ text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary['500'] }}\n optionHint={optionHint}\n testID={testID}\n anchorRef={anchorRef}\n />\n ) : null}\n </View>\n );\n}\n\nexport default SelectControl;\n","/**\n * `suggestOptions` — the ranked substring matcher behind `TypeaheadControl`, generalized from\n * aml-v2's `suggestCountries` and promoted verbatim out of `@dloizides/ui-tables`' private\n * `Filters/utils/suggest.ts`.\n *\n * Ranks: value exact (0) > value prefix (1) > label prefix (2) > label contains (3); ties broken\n * by `label.localeCompare`. Empty/short queries return `[]` — nothing surfaces until `minChars`\n * is typed, mirroring a native `<datalist>`.\n */\nimport type { ControlOption } from './controlTypes';\n\nconst RANK_VALUE_EXACT = 0;\nconst RANK_VALUE_PREFIX = 1;\nconst RANK_LABEL_PREFIX = 2;\nconst RANK_LABEL_CONTAINS = 3;\nconst NO_MATCH = -1;\n\nfunction rankOf(option: ControlOption, needle: string): number {\n const value = option.value.toLowerCase();\n const label = option.label.toLowerCase();\n if (value === needle) return RANK_VALUE_EXACT;\n if (value.startsWith(needle)) return RANK_VALUE_PREFIX;\n if (label.startsWith(needle)) return RANK_LABEL_PREFIX;\n if (label.includes(needle)) return RANK_LABEL_CONTAINS;\n return NO_MATCH;\n}\n\n/**\n * Rank + cap the options matching `query`. Returns `[]` until `query` (trimmed) is at least\n * `minChars` long, then the best `limit` matches, ranked as documented above.\n */\nexport function suggestOptions(\n options: readonly ControlOption[],\n query: string,\n minChars: number,\n limit: number,\n): readonly ControlOption[] {\n const needle = query.trim().toLowerCase();\n if (needle.length < minChars) return [];\n\n const scored: Array<{ option: ControlOption; rank: number }> = [];\n for (const option of options) {\n const rank = rankOf(option, needle);\n if (rank !== NO_MATCH) scored.push({ option, rank });\n }\n scored.sort((a, b) => (a.rank !== b.rank ? a.rank - b.rank : a.option.label.localeCompare(b.option.label)));\n return scored.slice(0, limit).map((entry) => entry.option);\n}\n\n/** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */\nexport function isUnmatched(options: readonly ControlOption[], text: string): boolean {\n const needle = text.trim().toLowerCase();\n if (needle === '') return false;\n return !options.some((o) => o.value.toLowerCase() === needle || o.label.toLowerCase() === needle);\n}\n","/**\n * `TypeaheadControl` — a search-as-you-type combobox (aml-v2's CountryPicker, generalized). A\n * text input plus a floating {@link AnchoredMenu} of ranked suggestions ({@link suggestOptions});\n * picking one fills the canonical label.\n *\n * Free typing is PRESERVED: the value is the raw text, so a caller can accept \"CY\", \"cyprus\" or\n * \"Cyprus (CY)\" and normalise it themselves at query time, exactly as aml does. An optional\n * PRE-LOCALIZED `error` shows a persistent banner and tints the border.\n *\n * Promoted out of `@dloizides/ui-tables`' private `Filters/fields/TypeaheadField`.\n *\n * Label-free by design — wrap in a `Field` for the label/hint slots.\n */\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { TextInput, Text, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { AnchoredMenu } from '../AnchoredMenu/AnchoredMenu';\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\nimport { suggestOptions } from '../controls/suggestOptions';\n\n/** Delay before blur closes the menu, so a tap on an option registers first (aml CLOSE_DELAY_MS). */\nconst CLOSE_DELAY_MS = 140;\n\n/** Default min characters before suggestions surface. */\nexport const DEFAULT_TYPEAHEAD_MIN_CHARS = 1;\n/** Default cap on rendered suggestions. */\nexport const DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = 8;\n\nexport interface TypeaheadControlProps {\n options: readonly ControlOption[];\n /** The raw text in the box — NOT necessarily an option value. */\n value: string;\n onChange: (value: string) => void;\n /** Called on Enter/submit (after the menu closes). Omit if the surface has nothing to commit. */\n onSubmit?: () => void;\n placeholder?: string;\n /** PRE-LOCALIZED accessible name of the input. */\n accessibilityLabel: string;\n accessibilityHint?: string;\n /** PRE-LOCALIZED accessibility hint applied to every suggestion. */\n optionHint?: string;\n /** PRE-LOCALIZED inline error (e.g. \"Unrecognised country\"). Shows a persistent banner. */\n error?: string;\n /** Minimum characters before suggestions surface. Default 1. */\n minChars?: number;\n /** Cap on rendered suggestions. Default 8. */\n maxSuggestions?: number;\n /** Merged LAST onto the anchor wrapper. */\n style?: StyleProp<ViewStyle>;\n /** Input is `${testID}-input`, menu `${testID}-menu`, error `${testID}-error`. */\n testID: string;\n}\n\nexport function TypeaheadControl({\n options,\n value,\n onChange,\n onSubmit,\n placeholder,\n accessibilityLabel,\n accessibilityHint,\n optionHint = '',\n error,\n minChars = DEFAULT_TYPEAHEAD_MIN_CHARS,\n maxSuggestions = DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS,\n style,\n testID,\n}: TypeaheadControlProps): React.ReactElement {\n const { theme } = useUi();\n const { colors, palette, semantic } = theme;\n const anchorRef = useRef<View>(null);\n const [isOpen, setIsOpen] = useState(false);\n\n // Hide the menu once the field already holds an exact pick (nothing left to disambiguate).\n const exactPick = useMemo(() => options.some((o) => o.label === value), [options, value]);\n const suggestions = useMemo(\n () => (exactPick ? [] : suggestOptions(options, value, minChars, maxSuggestions)),\n [exactPick, options, value, minChars, maxSuggestions],\n );\n const showMenu = isOpen && suggestions.length > 0;\n\n const handleChange = useCallback(\n (next: string) => {\n onChange(next);\n setIsOpen(true);\n },\n [onChange],\n );\n const pick = useCallback(\n (optionValue: string) => {\n const opt = options.find((o) => o.value === optionValue);\n onChange(opt?.label ?? optionValue);\n setIsOpen(false);\n },\n [options, onChange],\n );\n const handleBlur = useCallback(() => {\n setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS);\n }, []);\n const handleSubmit = useCallback(() => {\n setIsOpen(false);\n onSubmit?.();\n }, [onSubmit]);\n\n const hasError = error !== undefined && error !== '';\n\n return (\n <View ref={anchorRef} style={[s.anchor, style]}>\n <TextInput\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={accessibilityHint}\n autoCapitalize=\"none\"\n autoCorrect={false}\n placeholder={placeholder}\n placeholderTextColor={colors.textSecondary}\n spellCheck={false}\n value={value}\n onChangeText={handleChange}\n onFocus={() => setIsOpen(true)}\n onBlur={handleBlur}\n onSubmitEditing={handleSubmit}\n style={[s.input, { borderColor: hasError ? semantic.error['500'] : colors.border, backgroundColor: colors.surface, color: colors.text }]}\n testID={`${testID}-input`}\n />\n {showMenu ? (\n <AnchoredMenu\n options={suggestions}\n selectedValue={value}\n onSelect={pick}\n onDismiss={() => setIsOpen(false)}\n colors={{ text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary['500'] }}\n optionHint={optionHint}\n testID={testID}\n anchorRef={anchorRef}\n // Portal the suggestions to document.body on web: a typeahead sits in a filter row above\n // other content (fields, guides, a results table), and the in-tree popover was painted\n // under / clipped by it (\"hidden below\"). The portal escapes that stacking + clipping.\n usePortal\n />\n ) : null}\n {hasError ? (\n <Text role=\"alert\" style={[s.error, { color: semantic.error['500'] }]} testID={`${testID}-error`}>\n {error}\n </Text>\n ) : null}\n </View>\n );\n}\n\nexport default TypeaheadControl;\n","/**\n * `DateRangeControl` — an inclusive from/to pair (aml cases `from`/`to`, kefi audit `from`/`to`).\n * Each side is a `YYYY-MM-DD` text input; on web the browser's native date UI is offered via\n * `type=\"date\"` (a react-native-web `TextInput` passes unknown props to the DOM input). Editing\n * either side patches ONLY that side, so the other survives the edit.\n *\n * Promoted out of `@dloizides/ui-tables`' private `Filters/fields/DateRangeField`, which is why\n * the fleet grew FIVE independent date fields.\n *\n * Label-free by design — the From/To sub-labels name the two HALVES; wrap in a `Field` for the\n * range's own label.\n */\nimport React from 'react';\n\nimport { TextInput, View, Text, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { DateRangeValue } from '../controls/controlTypes';\n\nconst WEB_DATE_PROPS = typeof document !== 'undefined' ? { type: 'date' } : {};\n\nexport interface DateRangeControlProps {\n value: DateRangeValue;\n onChange: (value: DateRangeValue) => void;\n /** Called on Enter/submit in either side. */\n onSubmit?: () => void;\n /** PRE-LOCALIZED sub-label for the FROM input (e.g. \"From\"). Also its accessible name. */\n fromLabel: string;\n /** PRE-LOCALIZED sub-label for the TO input (e.g. \"To\"). Also its accessible name. */\n toLabel: string;\n fromPlaceholder?: string;\n toPlaceholder?: string;\n /** PRE-LOCALIZED hint applied to BOTH inputs. */\n accessibilityHint?: string;\n /** Merged LAST onto the row wrapper. */\n style?: StyleProp<ViewStyle>;\n /** Row is `${testID}-range`, inputs `${testID}-from` / `${testID}-to`. */\n testID: string;\n}\n\ninterface DateInputProps {\n side: 'from' | 'to';\n label: string;\n placeholder?: string;\n value: string;\n color: string;\n border: string;\n surface: string;\n muted: string;\n testID: string;\n hint?: string;\n onChangeText: (v: string) => void;\n onSubmit?: () => void;\n}\n\nfunction DateInput(p: DateInputProps): React.ReactElement {\n return (\n <View style={s.dateCol}>\n <Text style={[s.subLabel, { color: p.muted }]}>{p.label}</Text>\n <TextInput\n accessibilityLabel={p.label}\n accessibilityHint={p.hint}\n placeholder={p.placeholder}\n placeholderTextColor={p.muted}\n value={p.value}\n onChangeText={p.onChangeText}\n onSubmitEditing={p.onSubmit}\n style={[s.input, { borderColor: p.border, backgroundColor: p.surface, color: p.color }]}\n testID={`${p.testID}-${p.side}`}\n {...WEB_DATE_PROPS}\n />\n </View>\n );\n}\n\nexport function DateRangeControl({\n value,\n onChange,\n onSubmit,\n fromLabel,\n toLabel,\n fromPlaceholder,\n toPlaceholder,\n accessibilityHint,\n style,\n testID,\n}: DateRangeControlProps): React.ReactElement {\n const { theme } = useUi();\n const { colors } = theme;\n\n return (\n <View style={[s.dateRow, style]} testID={`${testID}-range`}>\n <DateInput\n side=\"from\"\n label={fromLabel}\n placeholder={fromPlaceholder}\n value={value.from}\n color={colors.text}\n border={colors.border}\n surface={colors.surface}\n muted={colors.textSecondary}\n hint={accessibilityHint}\n testID={testID}\n onChangeText={(from) => onChange({ from, to: value.to })}\n onSubmit={onSubmit}\n />\n <DateInput\n side=\"to\"\n label={toLabel}\n placeholder={toPlaceholder}\n value={value.to}\n color={colors.text}\n border={colors.border}\n surface={colors.surface}\n muted={colors.textSecondary}\n hint={accessibilityHint}\n testID={testID}\n onChangeText={(to) => onChange({ from: value.from, to })}\n onSubmit={onSubmit}\n />\n </View>\n );\n}\n\nexport default DateRangeControl;\n","/**\n * Group selection — the pure tri-state logic behind a \"select all\" / \"select this category\"\n * control, kept out of any component so it is testable as LOGIC rather than through the DOM.\n *\n * ## Why it lives here and not in @dloizides/ui-tables\n *\n * `ui-tables` already had this arithmetic inside `DataTable/selection.ts`, but deliberately\n * unexported: its tri-state is a `const enum`, which in a published `.d.ts` is an ambient const\n * enum that every `isolatedModules` consumer rejects. It is also page-scoped and wired to the\n * table's select-all banner. So the second consumer (a 12-tile console picker with no table in\n * sight, and no reason to pull a table package into its bundle budget) could not reach it.\n *\n * This module is the extraction: domain-neutral (keys in, keys out — nothing here knows what a\n * key *is*), component-free, and crossing the package boundary as a plain interface rather than\n * an enum. `ui-tables` can adopt it and delete its private copy.\n */\n\n/** Nothing selected / an empty group — the empty count. */\nconst NONE = 0;\n\n/**\n * A group's tri-state, as two booleans rather than an enum.\n *\n * `all` and `some` are mutually exclusive: a fully selected group is `{ all: true, some: false }`,\n * so a caller can branch on `all` then `some` without re-deriving \"partial\" itself. Both false\n * means nothing in the group is selected — which is also what an EMPTY group reports, because an\n * empty group is neither fully nor partially selected.\n */\nexport interface GroupSelection {\n /** Every key in the group is selected (never true for an empty group). */\n readonly all: boolean;\n /** At least one, but not every, key in the group is selected — the mixed/indeterminate state. */\n readonly some: boolean;\n}\n\n/** How many of the group's keys are currently selected. */\nfunction countSelected<T>(selected: readonly T[], groupKeys: readonly T[]): number {\n return groupKeys.filter((key) => selected.includes(key)).length;\n}\n\n/**\n * Resolve a group's tri-state from the selection ∩ the group.\n *\n * Scoped to the GROUP, not to the whole selection: selected keys OUTSIDE the group must never\n * make this group look partially selected.\n */\nexport function resolveGroupSelection<T>(selected: readonly T[], groupKeys: readonly T[]): GroupSelection {\n const count = countSelected(selected, groupKeys);\n if (count === NONE) return { all: false, some: false };\n return count === groupKeys.length ? { all: true, some: false } : { all: false, some: true };\n}\n\n/**\n * The value an `aria-checked` / `accessibilityState` consumer needs for a tri-state control.\n *\n * A partially selected group is `'mixed'`, which is what makes a screen reader announce the\n * control honestly instead of claiming the whole category is on.\n */\nexport function groupAriaChecked(state: GroupSelection): boolean | 'mixed' {\n if (state.all) return true;\n return state.some ? 'mixed' : false;\n}\n\n/**\n * Toggle a whole group, returning the NEXT selection array. Pure — never mutates the input.\n *\n * All-on → off. Partial or off → on: the conventional behaviour, and the one a mixed checkbox\n * looks like it will do. Keys OUTSIDE the group always survive untouched, so a category control\n * can never silently clear a selection it does not own.\n *\n * `order`, when given, is the canonical key order the result is sorted into (catalogue order, say)\n * so the selection does not carry click order around. Without it, newly added keys are appended.\n */\nexport function toggleGroupSelection<T>(\n selected: readonly T[],\n groupKeys: readonly T[],\n order?: readonly T[],\n): T[] {\n const { all } = resolveGroupSelection(selected, groupKeys);\n if (all) return selected.filter((key) => !groupKeys.includes(key));\n const merged = [...selected];\n groupKeys.forEach((key) => {\n if (!merged.includes(key)) merged.push(key);\n });\n return order === undefined ? merged : order.filter((key) => merged.includes(key));\n}\n"]}
1
+ {"version":3,"sources":["../src/Field/attachControlId.ts","../src/Field/useHtmlFor.ts","../src/Field/FieldLabel.tsx","../src/Field/fieldMarkers.ts","../src/Field/fieldSpacing.ts","../src/Field/labelVariants.ts","../src/FormGrid/formGridContext.ts","../src/Field/Field.tsx","../src/FormGrid/FormGrid.tsx","../src/FormGrid/FormCell.tsx","../src/FormSection/FormSection.tsx","../src/FormActions/FormActions.tsx","../src/controls/controlStyles.ts","../src/AnchoredMenu/menuPortal.ts","../src/AnchoredMenu/AnchoredMenu.tsx","../src/useThemedInput/useThemedInput.ts","../src/webFieldA11y/webFieldA11y.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/useRecentValues/recentValuesCore.ts","../src/useRecentValues/useRecentValues.ts","../src/FormField/RecentInputField.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/constants.ts","../src/ChipSelector/components/chipStyles.ts","../src/ChipSelector/components/ChipContent.tsx","../src/ChipSelector/components/OutlineChip.tsx","../src/ChipSelector/components/SolidChip.tsx","../src/ChipSelector/utils/radioKeyboard.ts","../src/ChipSelector/hooks/useRadioKeyboard.ts","../src/ChipSelector/utils/chipColors.ts","../src/ChipSelector/utils/chipIdentity.ts","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx","../src/SelectControl/SelectControl.tsx","../src/controls/suggestOptions.ts","../src/TypeaheadControl/TypeaheadControl.tsx","../src/DateRangeControl/DateRangeControl.tsx","../src/groupSelection/groupSelection.ts"],"names":["React","Platform","useRef","useEffect","IS_WEB","jsxs","Text","jsx","StyleSheet","useUi","View","styles","Button","MIN_TOUCH_TARGET_PX","Z_INDEX","MENU_TOP_GAP","useState","useLayoutEffect","ScrollView","Pressable","createPortal","useCallback","useMemo","ThemedTextInput","TextInput","TouchableOpacity","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","DESCRIPTION_FONT_SIZE","Switch","HINT_FONT_SIZE","CLOSE_DELAY_MS"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Give a `Field`'s plain-node child the `id` its `<label for>` points at.\n *\n * ## Why cloning rather than asking the caller\n *\n * `Field`'s documented, overwhelmingly common shape is a plain child:\n *\n * ```tsx\n * <Field label={FM('guides.titleLabel')}>\n * <ThemedTextInput … />\n * </Field>\n * ```\n *\n * There is no seam in that shape to hand an id through — which is exactly why label association\n * was never wired and why a live audit found 0 controls with an `id` across an entire CMS page.\n * The alternatives were worse: making every call site switch to the render-function form is a\n * fleet-wide migration that fails open (any missed call site silently keeps the old behaviour),\n * and wrapping the control inside the `<label>` element for implicit association breaks down on\n * the controls that are not native form elements — a `SelectControl` trigger is a\n * `<div role=\"button\">`, and nesting it in a `<label>` invites a double-fire on click.\n *\n * So the id is injected here, one level deep, and only when it is safe to do so.\n *\n * ## What \"safe\" means\n *\n * - Only a single valid element is touched. Arrays, strings and `null` are returned untouched,\n * because there is no unambiguous \"the control\" to point a label at. A **fragment** is excluded\n * explicitly: `React.isValidElement` says yes to one, but a fragment accepts no props beyond\n * `key`, so cloning an `id` onto it both warns in development and attaches nothing.\n * - A child that already carries an `id` keeps it. The caller was explicit; a label that silently\n * retargets someone else's id is worse than no label.\n * - The returned `controlId` is what the label should actually use: `undefined` when nothing was\n * attached, so `FieldLabel` emits no dangling `htmlFor` pointing at an element that does not\n * exist. A `<label for>` aimed at nothing is not a smaller bug than no label — it is a lie that\n * passes a \"has a label\" check.\n */\nimport React from 'react';\n\n/** Props any RN component may carry that we read or write here. `id` is RN ≥0.71 → DOM `id`. */\ninterface IdentifiableProps {\n id?: string;\n nativeID?: string;\n /** The kit's own contract for `aria-describedby`, honoured by `ThemedTextInput`/`ChipSelector`. */\n describedById?: string;\n}\n\nexport interface AttachedControl {\n /** The child, cloned with the field wiring when it could be attached; otherwise the original. */\n node: React.ReactNode;\n /** The id the label should target, or `undefined` when nothing could safely receive one. */\n controlId?: string;\n}\n\n/**\n * Returns the child wired to its `Field`, plus the id the label should point at.\n *\n * `candidateId` is only USED when it can be attached — the caller must not assume it was.\n *\n * `describedById` is injected too, under the kit's own `describedById` prop name, so the hint and\n * error lines are announced by a plain child exactly as they are by a render-function child. That\n * they were NOT was a real gap: a YouTube field made read-only with an on-screen sentence saying\n * why gave a screen-reader user the read-only state and none of the explanation.\n *\n * A child that is not a kit control simply ignores the prop; if it needs different wiring, use\n * the render-function form, which hands over the ids and lets the caller place them.\n */\nexport function attachControlId(\n child: React.ReactNode,\n candidateId: string,\n describedById?: string,\n): AttachedControl {\n if (!React.isValidElement(child) || child.type === React.Fragment) {\n return { node: child };\n }\n\n const props = child.props as IdentifiableProps;\n const existing = props.id ?? props.nativeID;\n const element = child as React.ReactElement<IdentifiableProps>;\n\n // An explicit id from the caller is never overwritten — but the description wiring still goes\n // on, because that is the field's to give and the caller expressed no opinion about it.\n const controlId = existing !== undefined && existing !== '' ? existing : candidateId;\n const injected: IdentifiableProps = { id: controlId };\n\n if (describedById !== undefined && props.describedById === undefined) {\n injected.describedById = describedById;\n }\n\n return { node: React.cloneElement(element, injected), controlId };\n}\n","/**\n * Put a real `for` attribute on a `<label>` rendered through react-native-web.\n *\n * ## Why this is imperative, which looks like a smell and is not\n *\n * The obvious implementation — pass `htmlFor` to `<Text role=\"label\">` — does not work, and\n * fails SILENTLY. react-native-web filters props through an allowlist (`forwardedProps`), and\n * `htmlFor` is not on it, so the prop is dropped somewhere between the component and the DOM\n * with no warning. This is the same family as the hint that never arrives: `accessibilityHint`\n * has no ARIA equivalent, so RN-web discards it, which is why this kit renders hints as\n * sr-only nodes instead of trusting the prop.\n *\n * That failure mode is the reason this is worth the imperative escape. A prop-level test\n * (`expect(label.props.htmlFor).toBe(id)`) passes against a build where the attribute never\n * reaches the browser. Setting it on the node and asserting `container.querySelector('label')\n * .getAttribute('for')` is the only version that can tell the difference.\n *\n * The alternatives were each worse:\n * - **Implicit association** (nesting the control inside the `<label>`) needs no attribute, but\n * changes the DOM structure of every field in seven portals, and a label wrapping a control\n * that turns out to be activatable is the classic double-fire bug.\n * - **Rendering the label as a raw DOM element** abandons the RN style pipeline, so the label\n * would need a second, hand-maintained styling path that could drift from every other label.\n *\n * Native is a no-op: there is no `<label>` and no DOM, and the association there is already\n * carried by the control's `accessibilityLabel`.\n */\nimport { useEffect, useRef } from 'react';\n\nimport { Platform } from 'react-native';\n\nconst IS_WEB = Platform.OS === 'web';\n\n/** The sliver of the DOM this touches — no `any`, no global DOM lib dependency. */\ninterface AttributeHost {\n setAttribute: (name: string, value: string) => void;\n removeAttribute: (name: string) => void;\n ownerDocument?: { getElementById: (id: string) => unknown } | null;\n}\n\nfunction isAttributeHost(node: unknown): node is AttributeHost {\n return (\n typeof node === 'object' &&\n node !== null &&\n typeof (node as AttributeHost).setAttribute === 'function'\n );\n}\n\n/**\n * Returns a ref to attach to the label element. The `for` attribute is set only when the target\n * it names is genuinely in the document.\n *\n * ## Why the existence check is not paranoia\n *\n * `Field` cannot know whether a render-function child actually placed the id it was handed. The\n * difficulty dropdown is the case that proved it: `SelectControl` is a `<div role=\"button\">` and\n * associates itself the other way round, via `aria-labelledby`, so nothing ever received\n * `controlId` — and the label emitted `for=\"field-control-3\"` pointing at nothing. Measured on a\n * real page, that produced a label that LOOKED correct in every audit (`<label>`: yes, `for`:\n * yes) and focused nothing when clicked.\n *\n * Trusting the caller here means the guarantee holds only as long as every call site remembers.\n * Checking the document makes it hold by construction, for both the injected and the\n * render-function paths, without either having to declare which one it is.\n *\n * It runs in an effect rather than in the ref callback because the check needs the whole\n * committed tree present — the control is a LATER sibling than its label, so at ref time the\n * answer would depend on commit ordering rather than on the truth.\n */\nexport function useHtmlFor(controlId?: string): React.RefObject<unknown> {\n const ref = useRef<unknown>(null);\n\n useEffect(() => {\n const node = ref.current;\n\n if (!IS_WEB || !isAttributeHost(node)) return;\n\n const target = controlId !== undefined && controlId !== '' ? node.ownerDocument?.getElementById(controlId) : null;\n\n // No target, or a target that is not in the document: emit nothing. A `for` pointing at a\n // missing element passes every \"does this page have labels?\" check while doing nothing.\n if (target === null || target === undefined) {\n node.removeAttribute('for');\n return;\n }\n\n node.setAttribute('for', controlId as string);\n }, [controlId]);\n\n return ref;\n}\n","/**\n * `FieldLabel` — the label row of a `Field`: the label text plus at most one marker.\n *\n * Split out of `Field` so the marker rules and the two label voices stay readable, and so `Field`\n * itself remains an orchestrator small enough to review.\n *\n * ## Why this is a real `<label>` on web\n *\n * It used to render a plain `<Text>`, i.e. a `<div>`. Controls still ANNOUNCED correctly, because\n * every one of them carries an `accessibilityLabel` → `aria-label`, so an audit of screen-reader\n * naming came back clean and the gap looked like it did not exist. What was missing was the other\n * half of a label: **clicking the words did not focus the field**. A page measured live had 0\n * `<label>` elements, 0 `label[for]` and 0 controls with an `id` — every field silently throwing\n * away a free doubling of its own hit area, on top of already being under the target-size floor.\n *\n * `role=\"label\"` is react-native-web's documented escape to a real `<label>` element (it is\n * special-cased ahead of the ARIA role map, since `label` is not an ARIA role). The `for`\n * attribute is set on the node itself — see `useHtmlFor` for why the obvious `htmlFor` prop is\n * silently discarded. On native both are inert: RN has no `<label>`, and the association there\n * is already carried by `accessibilityLabel`.\n *\n * The control keeps its `aria-label`, which still WINS for the accessible name — so this adds\n * click-to-focus without changing a single screen-reader announcement.\n */\nimport React from 'react';\n\nimport { Platform, Text, type StyleProp, type TextProps, type TextStyle } from 'react-native';\n\nimport { useHtmlFor } from './useHtmlFor';\n\nimport type { FieldMarker } from './fieldMarkers';\n\nconst IS_WEB = Platform.OS === 'web';\n\n/**\n * `label` is not an ARIA role, so RN's `role` union does not admit it; react-native-web\n * special-cases it into a real `<label>` element. Cast at the spread site through the host's own\n * props rather than through `any`.\n */\ninterface WebLabelProps {\n role?: 'label';\n}\n\nexport interface FieldLabelProps {\n label: string;\n marker: FieldMarker;\n /** Pre-localized text for the optional marker. Ignored unless `marker` is `optional`. */\n optionalLabel: string;\n /**\n * `id` of the control this label names. Emits `<label for>` on web so clicking the label text\n * focuses the field. Omitted when the field wraps a control that cannot be labelled that way\n * (a `<div role=\"button\">` select trigger), which uses `aria-labelledby` instead.\n */\n controlId?: string;\n /** `id` given to the label element itself, so a non-labelable control can point back at it. */\n labelId?: string;\n /** Composed style chain: base → variant → caller's `labelStyle` (applied last). */\n style: StyleProp<TextStyle>;\n requiredMarkStyle: StyleProp<TextStyle>;\n optionalMarkStyle: StyleProp<TextStyle>;\n}\n\nexport function FieldLabel({\n label,\n marker,\n optionalLabel,\n controlId,\n labelId,\n style,\n requiredMarkStyle,\n optionalMarkStyle,\n}: FieldLabelProps): React.ReactElement {\n const webProps = (IS_WEB ? { role: 'label' } : {}) as WebLabelProps as TextProps;\n const labelRef = useHtmlFor(controlId);\n\n return (\n <Text id={labelId} ref={labelRef as React.Ref<Text>} style={style} {...webProps}>\n {label}{' '}\n {marker === 'required' ? (\n // The asterisk is decorative — the control's `aria-required` conveys \"required\" to\n // assistive tech, so a screen reader says \"required\" instead of \"star\".\n <Text aria-hidden accessibilityElementsHidden importantForAccessibility=\"no\" style={requiredMarkStyle}>\n *\n </Text>\n ) : null}\n {marker === 'optional' && optionalLabel !== '' ? (\n // Also decorative: \"optional\" is the ABSENCE of `aria-required`, which assistive tech\n // already conveys. Rendering it to a screen reader would double-announce the same fact.\n <Text aria-hidden accessibilityElementsHidden importantForAccessibility=\"no\" style={optionalMarkStyle}>\n {optionalLabel}\n </Text>\n ) : null}\n </Text>\n );\n}\n\nexport default FieldLabel;\n","/**\n * Required / optional markers, per the shared forms contract\n * (`…/wwwroot/shared/FORMS.md` → \"Required and optional markers\").\n *\n * The contract says the two markers are MUTUALLY EXCLUSIVE — a field is required or optional, never\n * annotated as both — and that you mark the MINORITY: on a mostly-required form mark the optional\n * fields, on a mostly-optional form mark the required ones. Asterisking twelve of thirteen fields\n * is noise that trains the eye to ignore the marker.\n *\n * Exclusivity is enforced here rather than in the type system so that a caller spreading a props\n * object (`<Field {...fieldProps} />`, where both flags may be computed) still gets a defined,\n * single-marker result instead of a compile error it cannot act on.\n *\n * Precedence when a caller asks for BOTH: `required` wins. That is the safe failure direction —\n * showing \"optional\" on a field the server will reject sends the user into a failed submit, while\n * showing \"required\" on a genuinely optional field costs, at worst, an unnecessary keystroke.\n */\n\n/** Which marker a field label carries. Exactly one, never both. */\nexport type FieldMarker = 'none' | 'required' | 'optional';\n\n/**\n * The English fallback for the optional marker's text.\n *\n * `@dloizides/ui-forms` contains NO i18n runtime by design — aml-v2 uses `@dloizides/i18n` with\n * positional `{0}` params while the other six apps use i18next `{{p1}}`, and nothing bridges them,\n * so all user-visible copy arrives as pre-localized props. This constant exists ONLY so a\n * single-locale app can adopt `optional` in one line. It is exported precisely so it is greppable:\n * **a localized app MUST pass `optionalLabel`.** The required marker needs no such escape — `*` is\n * a glyph, not copy.\n */\nexport const DEFAULT_OPTIONAL_LABEL = '(optional)';\n\n/**\n * Resolve the two boolean flags to the single marker actually rendered.\n * `required` beats `optional`; neither flag yields `none`.\n */\nexport function resolveFieldMarker(required: boolean, optional: boolean): FieldMarker {\n if (required) return 'required';\n if (optional) return 'optional';\n return 'none';\n}\n","/**\n * `Field`'s TWO spacing models — the F3 fix, shipped as an OPT-IN rather than a breaking change.\n *\n * ## The defect\n *\n * `Field` hard-coded a 16px bottom margin on its container and 4px margins on its label / hint /\n * error. That is the pre-flexbox model: the CHILD owns the space after itself. In a `gap`-laid-out\n * parent — which is how every modern form row in this fleet is written — the child's margin STACKS\n * on the parent's gap, so the consumer has to cancel it by hand. aml-v2 alone carries 13\n * `marginBottom: 0` cancels, each with an apologetic comment; the fleet carries 16.\n *\n * AML v1 got this right in CSS: `.ui-field { display: flex; flex-direction: column; gap: 6px; }` —\n * internal gap only, and the parent grid owns the space BETWEEN fields. That contract is written up\n * in `PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md` (\"The gap is owned by the container,\n * never by margins on the children\").\n *\n * ## Why opt-in and not a 2.0.0\n *\n * Switching every `Field` to the gap model at once moves pixels on every form in seven portals in a\n * single publish — which is exactly the change you cannot visually QA, because there is no app you\n * can look at that is still on the old behaviour to compare against. The two models are therefore\n * both implemented, selected per field:\n *\n * - `stack` (DEFAULT) — the historical margins, byte-identical to 1.8.0. Every existing consumer\n * is untouched, including the 16 that currently cancel the margin.\n * - `gap` — the FORMS.md contract: no bottom margin at all, uniform 6px internal gap. The parent\n * owns the rhythm.\n *\n * A `Field` inside a `FormGrid` resolves to `gap` automatically, so adopting the shared grid IS the\n * opt-in — the consumer deletes its hand-rolled `grid`/`field` styles and its margin cancel in the\n * same edit, and the fleet migrates one app at a time behind visual QA.\n */\nimport { StyleSheet, type TextStyle, type ViewStyle } from 'react-native';\n\n/**\n * Which spacing model a field speaks.\n *\n * A plain string union rather than a `const enum` for the same reason as `FieldLabelVariant`: this\n * type crosses the package boundary into consumers' `.d.ts`, and a cross-boundary `const enum`\n * breaks `isolatedModules` / Babel-only builds.\n */\nexport type FieldSpacing = 'stack' | 'gap';\n\n/** The historical bottom margin of a whole field block. Load-bearing for every un-migrated form. */\nexport const FIELD_STACK_MARGIN_BOTTOM = 16;\n/** The historical label→control margin. */\nexport const FIELD_STACK_LABEL_MARGIN_BOTTOM = 4;\n/** The historical control→hint and hint→error margin. */\nexport const FIELD_STACK_CHILD_MARGIN_TOP = 4;\n/** FORMS.md: one uniform gap between label, control, hint and error. Not four separate margins. */\nexport const FIELD_CONTRACT_GAP = 6;\n\nexport const fieldSpacingStyles = StyleSheet.create({\n stackContainer: { marginBottom: FIELD_STACK_MARGIN_BOTTOM },\n stackLabel: { marginBottom: FIELD_STACK_LABEL_MARGIN_BOTTOM },\n stackChild: { marginTop: FIELD_STACK_CHILD_MARGIN_TOP },\n /**\n * The gap model sets NO margins — not even zeroed ones. An explicit `marginBottom: 0` here would\n * defeat a caller who legitimately wants to push one field down via `containerStyle`, because\n * `containerStyle` composes AFTER this and a zero is indistinguishable from \"unset\" to a reader.\n */\n gapContainer: { gap: FIELD_CONTRACT_GAP },\n none: {},\n});\n\n/** The style pieces a field applies for one spacing model. */\nexport interface FieldSpacingStyles {\n container: ViewStyle;\n label: TextStyle;\n /** Applied to the hint AND the error — the two lines that sit under the control. */\n child: TextStyle;\n}\n\n/**\n * Resolve the caller's explicit choice against the surrounding grid.\n *\n * Precedence, and why: an EXPLICIT `spacing` prop always wins, so a consumer inside a `FormGrid`\n * that genuinely needs the old margin (a one-off cell that stacks two fields) can say so without\n * leaving the grid. Absent that, a grid means the grid's `gap` owns the rhythm. Absent both, the\n * historical model — the answer that changes nothing.\n */\nexport function resolveFieldSpacing(explicit: FieldSpacing | undefined, insideGrid: boolean): FieldSpacing {\n if (explicit !== undefined) return explicit;\n\n return insideGrid ? 'gap' : 'stack';\n}\n\n/**\n * The style pieces for a resolved model.\n *\n * Exported and pure so `Field` and `ChipSelector` can be proven to resolve IDENTICALLY. They drifted\n * once already — `ChipSelector` grew a `marginBottom: -8` whose comment blamed `Field`'s 16px — and a\n * shared pure function is what makes \"they agree\" a testable claim rather than a convention.\n */\nexport function fieldSpacingStyleSet(spacing: FieldSpacing): FieldSpacingStyles {\n if (spacing === 'gap') {\n return {\n container: fieldSpacingStyles.gapContainer,\n label: fieldSpacingStyles.none,\n child: fieldSpacingStyles.none,\n };\n }\n\n return {\n container: fieldSpacingStyles.stackContainer,\n label: fieldSpacingStyles.stackLabel,\n child: fieldSpacingStyles.stackChild,\n };\n}\n","/**\n * The TWO legitimate label voices, per the shared forms contract\n * (`PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md` → \"The TWO legitimate label voices\").\n *\n * - `field` — 13 / 600 / sentence case. A label that is READ: prose addressed to the person\n * filling the form. This is `Field`'s historical, unchanged default, so every\n * existing consumer renders byte-identically.\n * - `control` — 11 / 700 / UPPERCASE + letter-spacing. A label that is SCANNED: a key over a value\n * in a dense row (filter bars, compact toolbars, pager controls). These are exactly\n * the metrics `@dloizides/ui-tables` forked into its private `FieldShell` because\n * `Field` hard-coded the `field` voice and offered no way out.\n *\n * A THIRD voice is drift, not a variant. Pick the voice from the SURFACE, not the component: every\n * label on one surface uses one voice, and voices are never mixed within a single row.\n *\n * Why a plain string union and not a `const enum`: this type crosses the package boundary into\n * consumers' `.d.ts`, and a cross-boundary `const enum` breaks `isolatedModules` / Babel-only\n * builds. `@dloizides/ui-buttons` sets the same precedent for `ButtonVariant` for the same reason.\n */\nimport { StyleSheet, type TextStyle } from 'react-native';\n\n/** Which of the two contract voices a field label speaks. */\nexport type FieldLabelVariant = 'field' | 'control';\n\n/** The historical `Field` label metrics. Changing these moves pixels in every consumer. */\nconst FIELD_FONT_SIZE = 13;\nconst FIELD_FONT_WEIGHT = '600';\n\n/** The dense-control metrics, taken verbatim from `ui-tables`' `FieldShell` fork so it can retire. */\nconst CONTROL_FONT_SIZE = 11;\nconst CONTROL_FONT_WEIGHT = '700';\nconst CONTROL_LETTER_SPACING = 0.4;\n\nexport const labelVariantStyles = StyleSheet.create({\n field: {\n fontSize: FIELD_FONT_SIZE,\n fontWeight: FIELD_FONT_WEIGHT,\n },\n control: {\n fontSize: CONTROL_FONT_SIZE,\n fontWeight: CONTROL_FONT_WEIGHT,\n letterSpacing: CONTROL_LETTER_SPACING,\n textTransform: 'uppercase',\n },\n});\n\n/**\n * Resolve a variant name to its style. An unknown/absent variant falls back to `field` — the\n * historical default — so a bad value degrades to \"unchanged\" rather than to \"unstyled\".\n */\nexport function resolveLabelVariantStyle(variant?: FieldLabelVariant): TextStyle {\n return variant === 'control' ? labelVariantStyles.control : labelVariantStyles.field;\n}\n","/**\n * The two contexts the layout primitives publish.\n *\n * They are SEPARATE on purpose, because they answer different questions and have different scopes:\n *\n * - `FormGridContext` carries a row's CELL METRICS, so `FormCell` can be written `<FormCell>` at\n * the overwhelmingly common call site and still get the row's `minWidth` / `flexBasis` — the four\n * constants (200 / 220 / 240 / 260) that the fleet re-declares by hand.\n * - `GapOwnedContext` says only \"the vertical rhythm here is owned by a parent's `gap`\". A `Field`\n * that sees it drops its own 16px bottom margin, which is the whole point of F3.\n *\n * Merging them would force `FormSection` — which also spaces with `gap`, and would otherwise\n * recreate the identical double-spacing bug one level up — to publish cell metrics it has no\n * business having. A section is not a row: a `Field` directly inside a section should be full width,\n * not 260px wide.\n *\n * Nothing about gap-ownership is inferable at runtime — RN's `StyleSheet` gives a child no way to\n * ask \"does my parent space me with gap?\" — so it has to be declared. Making the declaration a side\n * effect of using the shared primitives means the correct thing happens without a second opt-in.\n */\nimport React from 'react';\n\n/** Cell metrics a `FormGrid` hands down to its `FormCell` children. */\nexport interface FormGridMetrics {\n /** Below this the cell stops shrinking and the row wraps. */\n minWidth: number;\n /** The cell's ideal width before grow/shrink — its `flexBasis`. */\n basis: number;\n}\n\n/** `null` outside a grid, so `FormCell` can fall back to the package defaults rather than throw. */\nconst FormGridContext = React.createContext<FormGridMetrics | null>(null);\n\n/**\n * `false` — the historical model — unless a primitive above says otherwise. The default is what\n * every un-migrated `Field` in the fleet reads, so it must be the answer that changes nothing.\n */\nconst GapOwnedContext = React.createContext(false);\n\nexport const FormGridProvider = FormGridContext.Provider;\nexport const GapOwnedProvider = GapOwnedContext.Provider;\n\n/** The enclosing grid's cell metrics, or `null` outside a `FormGrid`. */\nexport function useFormGridMetrics(): FormGridMetrics | null {\n return React.useContext(FormGridContext);\n}\n\n/** True when a parent primitive owns this subtree's vertical rhythm with `gap`. */\nexport function useIsGapOwned(): boolean {\n return React.useContext(GapOwnedContext);\n}\n","/**\n * Field — the generic \"label over a control, hint + error under it\" wrapper.\n *\n * `FormField` is hard-wired to a text input, so any NON-text control (a dropdown, a date picker,\n * a chip selector) had no shared way to get a label — and ended up visually misaligned next to\n * its `FormField` siblings: its box started a label-row higher, and it missed the container's\n * bottom margin so wrapped rows lost their vertical rhythm.\n *\n * `Field` is that label row + spacing, control-agnostic. Its metrics are the single source of\n * truth: `FormField` composes `Field` internally, so the two can never drift apart.\n *\n * Children may be a plain node (the common case — just wrap your control) or a render function\n * receiving `{ describedById, hasError }`, so a custom control can wire the hint AND error lines\n * into its own `aria-describedby` / invalid state exactly the way `FormField` does.\n *\n * The anatomy (label → control → hint → error), the two label voices, the mutually-exclusive\n * required/optional markers and the collapsing error slot all implement the shared cross-stack\n * contract in `PROOViD/AMLService/AMLService/wwwroot/shared/FORMS.md`.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { attachControlId } from './attachControlId';\nimport { FieldLabel } from './FieldLabel';\nimport { DEFAULT_OPTIONAL_LABEL, resolveFieldMarker } from './fieldMarkers';\nimport { fieldSpacingStyleSet, resolveFieldSpacing, type FieldSpacing } from './fieldSpacing';\nimport { resolveLabelVariantStyle, type FieldLabelVariant } from './labelVariants';\nimport { useIsGapOwned } from '../FormGrid/formGridContext';\n\nconst ERROR_FONT_SIZE = 12;\nconst HINT_FONT_SIZE = 12;\n/** The optional marker drops to normal weight so it reads as an aside inside a 600 label. */\nconst OPTIONAL_MARK_FONT_WEIGHT = '400';\n\n/**\n * The metrics that do NOT depend on the spacing model. Everything positional — the container's\n * bottom margin, the label's bottom margin, the hint/error top margins — moved to `fieldSpacing`,\n * because those are exactly the values the two models disagree about.\n */\nconst styles = StyleSheet.create({\n hintText: {\n fontSize: HINT_FONT_SIZE,\n },\n errorText: {\n fontSize: ERROR_FONT_SIZE,\n },\n optionalMark: {\n fontWeight: OPTIONAL_MARK_FONT_WEIGHT,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n requiredMark: TextStyle;\n optionalMark: TextStyle;\n hintText: TextStyle;\n errorText: TextStyle;\n}\n\n/** What a render-function child receives, so it can mirror `FormField`'s error wiring. */\nexport interface FieldChildContext {\n /**\n * Space-separated ids of the lines describing this control — the hint, the error, or both, in\n * reading order. `undefined` when there is neither. Assign straight to `aria-describedby`.\n */\n describedById?: string;\n hasError: boolean;\n /**\n * `id` this field's `<label for>` points at. Assign it to the control (RN `id` → DOM `id`) and\n * clicking the label text focuses the control — a free doubling of the hit area that every\n * field was throwing away.\n *\n * A plain-node child gets this injected automatically (see below); a render-function child has\n * to place it, because only the caller knows which element inside is the actual control.\n */\n controlId: string;\n /**\n * `id` OF the label element. For a control that `<label for>` cannot address — anything that is\n * not a native form element, e.g. the `<div role=\"button\">` a `SelectControl` trigger renders —\n * point `aria-labelledby` here instead.\n */\n labelId: string;\n}\n\nexport type FieldChildren = React.ReactNode | ((context: FieldChildContext) => React.ReactNode);\n\nexport interface FieldProps {\n /**\n * Label shown above the control. Optional so a control whose label is supplied elsewhere (or\n * which genuinely has none) can still use the shared shell for its error line + spacing: an\n * absent or empty label renders NO label row at all, rather than an empty one that would add a\n * phantom gap and misalign the control against its labelled siblings.\n */\n label?: string;\n children: FieldChildren;\n required?: boolean;\n /**\n * Marks the field explicitly optional. MUTUALLY EXCLUSIVE with `required` — if both are set,\n * `required` wins (the safe direction: an under-marked required field causes a failed submit).\n * Use it to mark the MINORITY: on a mostly-required form, marking the two optional fields is far\n * less noise than asterisking the other eleven.\n */\n optional?: boolean;\n /**\n * Pre-localized text for the optional marker. Defaults to the English `DEFAULT_OPTIONAL_LABEL`\n * so a single-locale app can adopt `optional` in one line; a localized app MUST pass this.\n */\n optionalLabel?: string;\n /**\n * Help line rendered UNDER the control and ABOVE the error — the sentence that stops the user\n * guessing. It coexists with `error` (the hint states the rule, the error says which rule was\n * broken) and both are reachable from the control via `aria-describedby`.\n *\n * Rendering a hint INSIDE the field is the point: as an outside sibling it lands past the\n * container's 16px bottom margin and detaches from the control it explains.\n */\n hint?: string;\n error?: string;\n /**\n * Which of the two contract label voices to speak: `field` (13/600 sentence case — the default,\n * unchanged) or `control` (11/700 uppercase — dense filter bars and toolbars).\n */\n labelVariant?: FieldLabelVariant;\n /**\n * Escape hatch applied AFTER `labelVariant`, for the genuine one-off a variant does not cover.\n * Prefer `labelVariant`: it is the reviewable, named choice, and a bare `labelStyle` is the thing\n * to grep for when auditing label drift.\n */\n labelStyle?: StyleProp<TextStyle>;\n /**\n * `StyleProp` (not a bare `ViewStyle`) so a caller can compose an array — e.g. a base field style\n * plus a `grow` modifier — instead of having to restate a COMPLETE style per variant.\n */\n containerStyle?: StyleProp<ViewStyle>;\n /**\n * Which of the two spacing models this field speaks — see `fieldSpacing.ts`.\n *\n * Leave it unset. Inside a `FormGrid` or `FormSection` it resolves to `gap` (the FORMS.md\n * contract: no bottom margin, the parent's `gap` owns the rhythm); anywhere else it resolves to\n * `stack` (the historical 16px margin, byte-identical to 1.8.0). Set it explicitly only to\n * override that — e.g. a cell inside a grid that genuinely stacks two fields wants `stack`.\n */\n spacing?: FieldSpacing;\n testID?: string;\n}\n\nlet fieldSeq = 0;\n/**\n * Stable-per-instance ids so the label, hint and error lines can be linked to the control via\n * `htmlFor` / `aria-labelledby` / `aria-describedby`. One counter bump per field keeps every id\n * of a field in lockstep.\n */\nexport function useFieldIds(): { hintId: string; errorId: string; controlId: string; labelId: string } {\n const [ids] = React.useState(() => {\n fieldSeq += 1;\n const seq = String(fieldSeq);\n return {\n hintId: `field-hint-${seq}`,\n errorId: `field-error-${seq}`,\n controlId: `field-control-${seq}`,\n labelId: `field-label-${seq}`,\n };\n });\n return ids;\n}\n\n/** Stable-per-instance id so the error line can be linked to the control via aria-describedby. */\nexport function useFieldErrorId(): string {\n return useFieldIds().errorId;\n}\n\n/** True only for a present, non-empty string. */\nfunction isPresent(value?: string): boolean {\n return typeof value === 'string' && value !== '';\n}\n\n/** True only for a present, non-empty error string. */\nexport function hasFieldError(error?: string): boolean {\n return isPresent(error);\n}\n\n/**\n * Join the ids of the lines describing the control, in reading order (hint then error), skipping\n * any that is not rendered. `undefined` — not `''` — when there is nothing, so the attribute is\n * omitted entirely rather than emitted empty.\n */\nexport function joinDescribedBy(hintId?: string, errorId?: string): string | undefined {\n const ids = [hintId, errorId].filter((id): id is string => isPresent(id));\n return ids.length > 0 ? ids.join(' ') : undefined;\n}\n\nexport const Field = ({\n label,\n children,\n required = false,\n optional = false,\n optionalLabel = DEFAULT_OPTIONAL_LABEL,\n hint,\n error,\n labelVariant,\n labelStyle,\n containerStyle,\n spacing,\n testID,\n}: FieldProps): React.ReactElement => {\n const { theme } = useUi();\n const gapOwned = useIsGapOwned();\n const spacingStyles = fieldSpacingStyleSet(resolveFieldSpacing(spacing, gapOwned));\n const { colors, semantic } = theme;\n const errorColor = semantic.error['500'];\n const hasError = hasFieldError(error);\n const hasHint = isPresent(hint);\n const labelText = label ?? '';\n const hasLabel = labelText !== '';\n const marker = resolveFieldMarker(required, optional);\n const { hintId, errorId, controlId, labelId } = useFieldIds();\n\n const themeStyles = React.useMemo<ThemeStyles>(\n () => ({\n label: { color: colors.textSecondary },\n requiredMark: { color: errorColor },\n // The optional marker is an aside, so it sits a step back from the label's own ink.\n optionalMark: { color: colors.textSecondary },\n hintText: { color: colors.textSecondary },\n errorText: { color: errorColor },\n }),\n [colors.textSecondary, errorColor],\n );\n\n const describedById = joinDescribedBy(hasHint ? hintId : undefined, hasError ? errorId : undefined);\n\n // A render-function child places `controlId` itself, so the label always targets it. A plain\n // node has the id injected — and `attachControlId` reports back whether that was possible, so\n // the label never emits an `htmlFor` pointing at an element that does not exist.\n const isRenderChild = typeof children === 'function';\n const attached = isRenderChild\n ? { node: children({ describedById, hasError, controlId, labelId }), controlId }\n : attachControlId(children, controlId, describedById);\n const control = attached.node;\n\n return (\n <View style={[spacingStyles.container, containerStyle]} testID={testID}>\n {hasLabel ? (\n <FieldLabel\n controlId={attached.controlId}\n label={labelText}\n labelId={labelId}\n marker={marker}\n optionalLabel={optionalLabel}\n optionalMarkStyle={[styles.optionalMark, themeStyles.optionalMark]}\n requiredMarkStyle={themeStyles.requiredMark}\n style={[spacingStyles.label, resolveLabelVariantStyle(labelVariant), themeStyles.label, labelStyle]}\n />\n ) : null}\n {control}\n {hasHint ? (\n <Text nativeID={hintId} style={[styles.hintText, spacingStyles.child, themeStyles.hintText]}>\n {hint}\n </Text>\n ) : null}\n {hasError ? (\n <Text nativeID={errorId} role=\"alert\" style={[styles.errorText, spacingStyles.child, themeStyles.errorText]}>\n {error}\n </Text>\n ) : null}\n </View>\n );\n};\n\nexport default Field;\n","/**\n * `FormGrid` — the wrapping form row, extracted from ~177 hand-rolled copies.\n *\n * Verbatim in every portal, differing only in one constant:\n *\n * ```ts\n * grid: { flexDirection: 'row', flexWrap: 'wrap', gap: 12 },\n * field: { minWidth: 220, flexGrow: 1, flexBasis: 260 }, // or 200/240/260\n * ```\n *\n * Extracting it is worth more than the deleted lines: because the grid declares itself through\n * `FormGridContext`, a `Field` inside it knows its vertical rhythm is owned by the grid's `gap` and\n * drops its own bottom margin. That kills the fleet's 16 `marginBottom: 0` cancel hacks at the same\n * time — the grid and the cancel were always two halves of one bug.\n *\n * The cell metrics live on the GRID, not on each cell, because that is how the real call sites are\n * written: one `styles.field` reused by every cell in the row, with the occasional narrow one-off.\n * `<FormCell>` with no props is therefore the common case, and `<FormCell basis={160} grow={false}>`\n * the exception — which is exactly the ratio in aml-v2's `ScreeningForm`.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { FormGridProvider, GapOwnedProvider, type FormGridMetrics } from './formGridContext';\n\n/** The gap 24 of aml-v2's 41 wrapping rows already use. The de-facto fleet default. */\nexport const FORM_GRID_DEFAULT_GAP = 12;\n/** The most common `minWidth` across the fleet's copies (the others are 200 / 240 / 260). */\nexport const FORM_GRID_DEFAULT_MIN_WIDTH = 220;\n/** The most common `flexBasis` across the fleet's copies. */\nexport const FORM_GRID_DEFAULT_BASIS = 260;\n\nconst styles = StyleSheet.create({\n grid: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n});\n\nexport interface FormGridProps {\n children: React.ReactNode;\n /**\n * Space between cells, horizontally AND between wrapped rows. This is the value that makes the\n * grid own the vertical rhythm, so it is also what a descendant `Field` is dropping its own\n * margin in favour of.\n */\n gap?: number;\n /** Default `minWidth` for every `FormCell` in this grid. */\n minWidth?: number;\n /** Default `flexBasis` for every `FormCell` in this grid. */\n basis?: number;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nexport const FormGrid = ({\n children,\n gap = FORM_GRID_DEFAULT_GAP,\n minWidth = FORM_GRID_DEFAULT_MIN_WIDTH,\n basis = FORM_GRID_DEFAULT_BASIS,\n style,\n testID,\n}: FormGridProps): React.ReactElement => {\n // Memoised on the two primitives, not the object literal: a fresh identity every render would\n // re-render every `Field` in the row on every keystroke in any one of them.\n const metrics = React.useMemo<FormGridMetrics>(() => ({ minWidth, basis }), [minWidth, basis]);\n\n return (\n <FormGridProvider value={metrics}>\n <GapOwnedProvider value>\n <View style={[styles.grid, { gap }, style]} testID={testID}>\n {children}\n </View>\n </GapOwnedProvider>\n </FormGridProvider>\n );\n};\n\nexport default FormGrid;\n","/**\n * `FormCell` — one cell of a `FormGrid`.\n *\n * Replaces the `<View style={styles.field}>` wrapper every real call site already puts around each\n * control. It inherits `minWidth` / `flexBasis` from the enclosing grid so the common case is a bare\n * `<FormCell>`, and takes per-cell overrides for the genuine one-offs (aml-v2's `fieldNarrow`:\n * `minWidth: 140, flexBasis: 160, flexGrow: 0`).\n *\n * Used OUTSIDE a `FormGrid` it still renders a sensible cell from the package defaults rather than\n * throwing — a cell is a layout hint, and a form that renders slightly wide is a better failure than\n * a form that does not render. The grid-owned SPACING behaviour, by contrast, is deliberately NOT\n * available this way: that one has to come from a real grid, because a `Field` dropping its margin\n * with nothing to replace it would collapse the form.\n */\nimport React from 'react';\n\nimport { View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport {\n FORM_GRID_DEFAULT_BASIS,\n FORM_GRID_DEFAULT_MIN_WIDTH,\n} from './FormGrid';\nimport { useFormGridMetrics } from './formGridContext';\n\n/** A cell that grows to fill the row's slack. The default — most fields want the space. */\nconst GROW = 1;\n/** A cell pinned to its basis. For the narrow one-offs (a 2-digit threshold next to a name field). */\nconst NO_GROW = 0;\n\nexport interface FormCellProps {\n children: React.ReactNode;\n /** Overrides the grid's `minWidth` for this cell only. */\n minWidth?: number;\n /** Overrides the grid's `basis` for this cell only. */\n basis?: number;\n /** `false` pins the cell to its basis instead of letting it absorb the row's slack. */\n grow?: boolean;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nexport const FormCell = ({\n children,\n minWidth,\n basis,\n grow = true,\n style,\n testID,\n}: FormCellProps): React.ReactElement => {\n const metrics = useFormGridMetrics();\n const resolvedMinWidth = minWidth ?? metrics?.minWidth ?? FORM_GRID_DEFAULT_MIN_WIDTH;\n const resolvedBasis = basis ?? metrics?.basis ?? FORM_GRID_DEFAULT_BASIS;\n\n const cellStyle: ViewStyle = {\n minWidth: resolvedMinWidth,\n flexBasis: resolvedBasis,\n flexGrow: grow ? GROW : NO_GROW,\n };\n\n return (\n <View style={[cellStyle, style]} testID={testID}>\n {children}\n </View>\n );\n};\n\nexport default FormCell;\n","/**\n * `FormSection` — a titled group of fields. The React answer to v1's `<fieldset>` / `<legend>`.\n *\n * v1 has a real `<fieldset>` whose `<legend>` takes the identical label metric as a field label, so\n * a group heading reads as part of the form rather than as page furniture. Nothing in the React\n * fleet has this: zygos fakes it with a generic `Heading`, and everybody else emits an untitled\n * `<View>` — which means the grouping exists visually but not semantically, so a screen-reader user\n * tabbing into \"Threshold\" is never told it belongs to \"Advanced matching\".\n *\n * ## Why not a literal `<fieldset>`\n *\n * react-native-web has no `fieldset` mapping — a `View` is a `div`, and there is no escape hatch\n * that turns one into a `<fieldset>` with a real `<legend>`. What IS available is the pattern the\n * ARIA spec defines as the equivalent: `role=\"group\"` + `aria-labelledby` pointing at the heading.\n * Assistive tech announces \"Advanced matching, group\" exactly as it would for a fieldset. This is\n * the honest ceiling of the platform, not a shortcut — and it is why the legend is a `Text` whose\n * `nativeID` is generated the same way `Field`'s hint/error ids are.\n *\n * The legend deliberately reuses `resolveLabelVariantStyle` — the SAME function `Field` uses for its\n * label — so the two cannot drift. A section titled in one metric above fields labelled in another\n * is precisely the \"third voice is drift\" failure FORMS.md warns about.\n */\nimport React from 'react';\n\nimport { StyleSheet, Text, View, type StyleProp, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { resolveLabelVariantStyle, type FieldLabelVariant } from '../Field/labelVariants';\nimport { GapOwnedProvider } from '../FormGrid/formGridContext';\n\n/** Space between the legend, the description and the section's content. */\nconst SECTION_GAP = 10;\n/** A description is a help line for the whole group — same size as `Field`'s hint. */\nconst DESCRIPTION_FONT_SIZE = 12;\n\nconst styles = StyleSheet.create({\n section: {\n gap: SECTION_GAP,\n },\n description: {\n fontSize: DESCRIPTION_FONT_SIZE,\n },\n});\n\nlet sectionSeq = 0;\n\n/** Stable-per-instance id so the group can point at its own legend via `aria-labelledby`. */\nfunction useSectionLegendId(): string {\n const [id] = React.useState(() => {\n sectionSeq += 1;\n return `form-section-legend-${String(sectionSeq)}`;\n });\n return id;\n}\n\n/**\n * Web-only ARIA attributes react-native-web forwards to the underlying element but that RN's\n * `ViewProps` type does not enumerate — the same escape-hatch-free pattern `ChipSelector` uses.\n */\ninterface WebSectionA11y {\n 'aria-labelledby'?: string;\n}\n\nexport interface FormSectionProps {\n /**\n * The legend — pre-localized, like every string in this package. Optional: a section with no\n * title still groups its children for layout, but renders NO legend row and NO `aria-labelledby`,\n * because a group labelled by an empty element is worse for assistive tech than an unlabelled one.\n */\n title?: string;\n /** Help line for the whole group, under the legend. The group-level sibling of `Field`'s hint. */\n description?: string;\n children: React.ReactNode;\n /**\n * Which label voice the legend speaks. Defaults to `field` — a section heading on a form the user\n * fills in. Pass `control` on a dense surface so the legend matches the controls beneath it.\n */\n labelVariant?: FieldLabelVariant;\n /** Escape hatch applied AFTER `labelVariant`, for the genuine one-off a variant does not cover. */\n titleStyle?: StyleProp<TextStyle>;\n style?: StyleProp<ViewStyle>;\n testID?: string;\n}\n\nexport const FormSection = ({\n title,\n description,\n children,\n labelVariant,\n titleStyle,\n style,\n testID,\n}: FormSectionProps): React.ReactElement => {\n const { theme } = useUi();\n const { colors } = theme;\n const legendId = useSectionLegendId();\n const hasTitle = typeof title === 'string' && title !== '';\n const hasDescription = typeof description === 'string' && description !== '';\n\n const a11y: WebSectionA11y = { 'aria-labelledby': hasTitle ? legendId : undefined };\n\n return (\n // The section spaces its children with `gap`, so it owns their vertical rhythm exactly as a\n // `FormGrid` owns a row's — without this a `Field` placed directly in a section would stack its\n // 16px margin on the section's gap and recreate the F3 bug one level up.\n <GapOwnedProvider value>\n <View role=\"group\" style={[styles.section, style]} testID={testID} {...a11y}>\n {hasTitle ? (\n <Text\n nativeID={legendId}\n style={[resolveLabelVariantStyle(labelVariant), { color: colors.text }, titleStyle]}\n >\n {title}\n </Text>\n ) : null}\n {hasDescription ? (\n <Text style={[styles.description, { color: colors.textSecondary }]}>{description}</Text>\n ) : null}\n {children}\n </View>\n </GapOwnedProvider>\n );\n};\n\nexport default FormSection;\n","/**\n * `FormActions` — the submit/cancel button row every form ends with.\n *\n * Promoted from the BYTE-IDENTICAL `erevna-web/src/components/Forms/FormActions.tsx` and\n * `katalogos-web/src/components/Forms/FormActions.tsx` (68 lines each, `diff` returns nothing);\n * all seven apps hand-roll the same row. Buttons come from the shared `@dloizides/ui-buttons` kit\n * rather than being forked here, so there is exactly one button implementation in the estate.\n *\n * The layout implements the contract's actions row\n * (`…/wwwroot/shared/FORMS.md` → \"Actions row\"): the primary action is LAST in DOM order, so tab\n * order reaches Cancel before Save, and `saving` drives the primary button's spinner rather than\n * disabling-and-relabelling it.\n *\n * Two minimal generalizations over the app-local twins:\n * 1. Labels and hints arrive as PRE-LOCALIZED props. The twins called `FM()` internally, which\n * cannot work here: aml-v2 localizes via `@dloizides/i18n` with positional `{0}` params while\n * the other six use i18next `{{p1}}`, and nothing bridges them.\n * 2. `testID`s are overridable but default to the twins' `save-button` / `cancel-button`, so the\n * existing Playwright selectors in every app keep matching.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { Button } from '@dloizides/ui-buttons';\n\n/** Gap between the actions, matching the contract's `.actions { gap: 12px }`. */\nconst ACTIONS_GAP = 12;\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: 'row',\n justifyContent: 'flex-end',\n gap: ACTIONS_GAP,\n },\n});\n\nexport interface FormActionsProps {\n /** Submit handler. May be async — the shared Button drives its own spinner for the promise. */\n onSave: () => void | Promise<unknown>;\n /** Cancel handler. Omit it entirely to render a save-only row (no empty Cancel slot). */\n onCancel?: () => void | Promise<unknown>;\n /** Pre-localized label for the primary action. */\n saveLabel: string;\n /** Pre-localized label for the cancel action. Required whenever `onCancel` is supplied. */\n cancelLabel?: string;\n /** Pre-localized accessibility hint for the primary action. Falls back to its label. */\n saveHint?: string;\n /** Pre-localized accessibility hint for the cancel action. Falls back to its label. */\n cancelHint?: string;\n /** In-flight submit: spins the primary action and disables cancel so the form can't be abandoned mid-write. */\n saving?: boolean;\n /** Disables the primary action independently of `saving` (e.g. an invalid form). */\n saveDisabled?: boolean;\n containerStyle?: StyleProp<ViewStyle>;\n saveTestID?: string;\n cancelTestID?: string;\n testID?: string;\n}\n\nexport const FormActions = ({\n onSave,\n onCancel,\n saveLabel,\n cancelLabel = '',\n saveHint,\n cancelHint,\n saving = false,\n saveDisabled = false,\n containerStyle,\n saveTestID = 'save-button',\n cancelTestID = 'cancel-button',\n testID,\n}: FormActionsProps): React.ReactElement => (\n <View style={[styles.container, containerStyle]} testID={testID}>\n {typeof onCancel === 'function' ? (\n <Button\n accessibilityHint={cancelHint ?? cancelLabel}\n accessibilityLabel={cancelLabel}\n disabled={saving}\n label={cancelLabel}\n testID={cancelTestID}\n variant=\"outline\"\n onPress={onCancel}\n />\n ) : null}\n\n <Button\n accessibilityHint={saveHint ?? saveLabel}\n accessibilityLabel={saveLabel}\n disabled={saveDisabled}\n label={saveLabel}\n loading={saving}\n testID={saveTestID}\n variant=\"primary\"\n onPress={onSave}\n />\n </View>\n);\n\nexport default FormActions;\n","/**\r\n * `controlStyles` — the tuned metrics for the dense CONTROLS (text box, select trigger, floating\r\n * option menu, date-range row), promoted VERBATIM out of `@dloizides/ui-tables`' private\r\n * `Filters/styles.ts`.\r\n *\r\n * That file's own header said the quiet part out loud: it \"reconcile[d] the per-field styles that\r\n * were copy-pasted across aml-v2's filter files into one shared source\" — and then locked the\r\n * reconciliation inside one bar, where no other surface could reach it. These numbers are that\r\n * reconciliation, unchanged to the pixel, now reachable.\r\n *\r\n * Colours are applied INLINE from `useUi().theme` at render — nothing here carries a colour\r\n * literal, so a control re-themes per tenant without a stylesheet change.\r\n */\r\nimport { StyleSheet } from 'react-native';\r\n\r\nimport { MIN_TOUCH_TARGET_PX } from '@dloizides/a11y';\r\nimport { Z_INDEX } from '@dloizides/design-tokens';\r\n\r\nconst FIELD_GAP = 4;\r\nconst LABEL_FONT = 11;\r\nconst LABEL_LETTER_SPACING = 0.4;\r\nconst INPUT_RADIUS = 8;\r\nconst INPUT_PAD_H = 12;\r\nconst INPUT_PAD_V = 10;\r\nconst INPUT_FONT = 14;\r\nconst INPUT_BORDER = 1;\r\nconst DATE_ROW_GAP = 8;\r\nconst CHEVRON_FONT = 10;\r\nconst MENU_TOP_GAP = 4;\r\nconst MENU_RADIUS = 8;\r\nconst MENU_PAD_V = 4;\r\nconst MENU_OPT_PAD_H = 12;\r\nconst MENU_OPT_PAD_V = 8;\r\nconst MENU_MIN_WIDTH = 160;\r\nconst MENU_MAX_HEIGHT = 260;\r\nconst MENU_ELEVATION = 8;\r\nconst MENU_BOX_SHADOW = '0px 2px 8px rgba(0, 0, 0, 0.15)';\r\nconst OPTION_FONT = 14;\r\nconst ERROR_FONT = 12;\r\nconst ERROR_GAP = 3;\r\n\r\nexport const controlStyles = StyleSheet.create({\r\n /**\r\n * The shared bordered box every dense text control renders in.\r\n *\r\n * `minHeight` is the kit floor: padding alone produced a ~38px box, and a bare input with no\r\n * box style at all measured **19px** in production. Height is a hit-target guarantee, so it\r\n * is stated rather than left to emerge from font size + padding.\r\n */\r\n input: {\r\n borderWidth: INPUT_BORDER,\r\n borderRadius: INPUT_RADIUS,\r\n paddingHorizontal: INPUT_PAD_H,\r\n paddingVertical: INPUT_PAD_V,\r\n fontSize: INPUT_FONT,\r\n minHeight: MIN_TOUCH_TARGET_PX,\r\n },\r\n /** The select trigger: a bordered field box matching the text inputs + a chevron. */\r\n selectTrigger: {\r\n minHeight: MIN_TOUCH_TARGET_PX,\r\n flexDirection: 'row',\r\n alignItems: 'center',\r\n justifyContent: 'space-between',\r\n gap: DATE_ROW_GAP,\r\n borderWidth: INPUT_BORDER,\r\n borderRadius: INPUT_RADIUS,\r\n paddingHorizontal: INPUT_PAD_H,\r\n paddingVertical: INPUT_PAD_V,\r\n },\r\n selectTriggerText: { fontSize: INPUT_FONT, flexShrink: 1 },\r\n chevron: { fontSize: CHEVRON_FONT },\r\n dateRow: { flexDirection: 'row', gap: DATE_ROW_GAP },\r\n dateCol: { gap: FIELD_GAP, flex: 1 },\r\n /**\r\n * The micro-caption above a sub-control (a date range's From/To) and beside a switch. Note it\r\n * is deliberately NOT the `control` label voice: it carries no `700`/uppercase, because it\r\n * names a HALF of a control that already has a `control`-voice label above it. Uppercasing it\r\n * too would make one field shout twice.\r\n */\r\n subLabel: { fontSize: LABEL_FONT, letterSpacing: LABEL_LETTER_SPACING },\r\n /** Positioning context for a floating `AnchoredMenu` (`position:absolute; top:100%`). */\r\n anchor: { position: 'relative' },\r\n menu: {\r\n position: 'absolute',\r\n top: '100%',\r\n left: 0,\r\n marginTop: MENU_TOP_GAP,\r\n minWidth: MENU_MIN_WIDTH,\r\n maxHeight: MENU_MAX_HEIGHT,\r\n borderWidth: INPUT_BORDER,\r\n borderRadius: MENU_RADIUS,\r\n paddingVertical: MENU_PAD_V,\r\n zIndex: Z_INDEX.dropdown,\r\n boxShadow: MENU_BOX_SHADOW,\r\n elevation: MENU_ELEVATION,\r\n overflow: 'hidden',\r\n },\r\n /** A menu option is a tap target, so it carries the kit floor (SHOWCASE-1). */\r\n option: {\r\n minHeight: MIN_TOUCH_TARGET_PX,\r\n justifyContent: 'center',\r\n paddingHorizontal: MENU_OPT_PAD_H,\r\n paddingVertical: MENU_OPT_PAD_V,\r\n },\r\n optionText: { fontSize: OPTION_FONT },\r\n error: { fontSize: ERROR_FONT, marginTop: ERROR_GAP },\r\n});\r\n","/**\r\n * menuPortal — web-only stacking/positioning geometry for {@link AnchoredMenu}.\r\n *\r\n * WHY THIS EXISTS (the bug it fixes): react-native-web renders EVERY `View` with\r\n * `position: relative; z-index: 0`, so every View is its own stacking context. An in-tree\r\n * `position:absolute` popover therefore has its `zIndex` trapped inside its anchor's (and the\r\n * app's field-wrapper's) `z-index: 0` context — it can never rise above later-painting sibling\r\n * Views (the adjacent filter fields, the PEP-class guide, the results table/card). That is why the\r\n * Country typeahead menu painted UNDERNEATH the content below it (\"hidden below\").\r\n *\r\n * THE FIX: on web the menu is rendered in a PORTAL to `document.body` with `position: fixed` at the\r\n * trigger's measured viewport rect and a high `zIndex`. A portal escapes every ancestor stacking\r\n * context AND every ancestor `overflow: hidden`, so the menu always paints on top and is never\r\n * clipped. {@link useAnchorRect} keeps the fixed coordinate glued to the trigger as the page\r\n * scrolls / resizes / reflows. On native the menu stays in-tree (`position:absolute` + `elevation`).\r\n *\r\n * DUPLICATION NOTE: `@dloizides/ui-layout`'s `ModalDropdown`/`InlineMenu` and `@dloizides/ui-tables`'\r\n * `SizeDropdown` already carry the same portal mechanism. It is NOT shared from there because\r\n * `ui-forms` is the LOWEST-level UI primitive and must not depend on those higher packages (that\r\n * would invert the dependency graph). The proper DRY home is `ui-forms` itself; unifying the three\r\n * copies onto this one (ui-layout/ui-tables importing it from here) is a tracked follow-up, kept out\r\n * of this change so the proven ModalDropdown is not disturbed while fixing the typeahead.\r\n */\r\nimport { useLayoutEffect, useState } from 'react';\r\nimport type { RefObject } from 'react';\r\n\r\nimport { Platform, type ViewStyle } from 'react-native';\r\nimport type { View as RNView } from 'react-native';\r\n\r\nimport { Z_INDEX } from '@dloizides/design-tokens';\r\n\r\nconst IS_WEB = Platform.OS === 'web';\r\n\r\n/**\r\n * z-index for the open popover: the shared `popover` layer, above RN-web's body-level `Modal`\r\n * (9999) so a menu opened inside a dialog paints and clicks on top of it, and below toasts.\r\n */\r\nexport const MENU_PORTAL_Z_INDEX = Z_INDEX.popover;\r\n/** Gap between the trigger's bottom edge and the popover's top edge. */\r\nconst MENU_TOP_GAP = 4;\r\n\r\n/** The trigger's viewport-space rect (from `getBoundingClientRect`) needed to place a fixed menu. */\r\nexport interface AnchorRect {\r\n top: number;\r\n left: number;\r\n width: number;\r\n bottom: number;\r\n}\r\n\r\n/** The RN-web `View` ref is an `HTMLElement` at runtime; native refs are not. */\r\nfunction toDomNode(ref: RefObject<RNView | null>): HTMLElement | null {\r\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- RN web ref is an HTMLElement at runtime\r\n const node = ref.current as unknown as HTMLElement | null;\r\n if (node === null || typeof node.getBoundingClientRect !== 'function') return null;\r\n return node;\r\n}\r\n\r\n/** Read the anchor's viewport rect (web only). Returns null when unavailable (native / no node). */\r\nexport function readAnchorRect(ref: RefObject<RNView | null>): AnchorRect | null {\r\n if (!IS_WEB) return null;\r\n const node = toDomNode(ref);\r\n if (node === null) return null;\r\n const r = node.getBoundingClientRect();\r\n return { top: r.top, left: r.left, width: r.width, bottom: r.bottom };\r\n}\r\n\r\n/**\r\n * Web portal popover style: `position: fixed` at the trigger rect with a high `zIndex`. Portalled to\r\n * `document.body`, so `fixed` positions it against the viewport and it tracks the trigger via the\r\n * measured rect (recomputed on scroll/resize/reflow) — clipped by nothing, above everything.\r\n */\r\nexport function buildPortalPopoverStyle(rect: AnchorRect): ViewStyle {\r\n return {\r\n // RN's ViewStyle union omits 'fixed', but react-native-web honours it at runtime.\r\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- web-only position value\r\n position: 'fixed' as unknown as ViewStyle['position'],\r\n top: rect.bottom + MENU_TOP_GAP,\r\n left: rect.left,\r\n width: rect.width,\r\n zIndex: MENU_PORTAL_Z_INDEX,\r\n };\r\n}\r\n\r\n/**\r\n * Track the anchor's viewport rect while `enabled`. Measures on enable, then re-measures on scroll\r\n * (capture phase, so a scroll inside ANY ancestor scroll container counts — element `scroll` events\r\n * do not bubble) + window resize + any layout reflow that moves the trigger without scrolling (an\r\n * accordion above it expanding, an async list rendering, a font swapping — caught by a\r\n * `ResizeObserver` on the anchor and `document.body`). Work is coalesced into one\r\n * `requestAnimationFrame` per frame so a momentum scroll cannot thrash layout. No-op on native\r\n * (returns null), where the in-tree absolute popover moves with its anchor automatically.\r\n */\r\nexport function useAnchorRect(ref: RefObject<RNView | null>, enabled: boolean): AnchorRect | null {\r\n const [rect, setRect] = useState<AnchorRect | null>(null);\r\n\r\n useLayoutEffect(() => {\r\n if (!IS_WEB || !enabled) {\r\n setRect(null);\r\n return undefined;\r\n }\r\n let frame: number | null = null;\r\n let disposed = false;\r\n\r\n const apply = (): void => {\r\n frame = null;\r\n if (disposed) return;\r\n setRect(readAnchorRect(ref));\r\n };\r\n const schedule = (): void => {\r\n if (frame !== null) return;\r\n frame = window.requestAnimationFrame(apply);\r\n };\r\n\r\n apply();\r\n document.addEventListener('scroll', schedule, true);\r\n window.addEventListener('resize', schedule);\r\n const node = toDomNode(ref);\r\n const observer = typeof ResizeObserver === 'function' ? new ResizeObserver(schedule) : null;\r\n if (observer !== null) {\r\n if (node !== null) observer.observe(node);\r\n observer.observe(document.body);\r\n }\r\n\r\n return () => {\r\n disposed = true;\r\n if (frame !== null) window.cancelAnimationFrame(frame);\r\n document.removeEventListener('scroll', schedule, true);\r\n window.removeEventListener('resize', schedule);\r\n if (observer !== null) observer.disconnect();\r\n };\r\n }, [ref, enabled]);\r\n\r\n return IS_WEB && enabled ? rect : null;\r\n}\r\n","/**\n * `AnchoredMenu` — the floating option list shared by `SelectControl` and `TypeaheadControl`.\n *\n * By DEFAULT (web) it renders in a PORTAL to `document.body` with `position: fixed` at the trigger's\n * measured rect: that escapes react-native-web's trapped `z-index: 0` stacking contexts and any\n * ancestor `overflow: hidden`, so the menu is never painted under / clipped by later siblings (a\n * table, a card, the next filter field). On native, and when {@link AnchoredMenuProps.usePortal} is\n * explicitly `false`, it renders an in-tree, absolutely-positioned popover under its anchor\n * (`position:absolute; top:100%; zIndex; elevation`) — which is exactly what left `SelectControl`'s\n * menu hidden behind the attendee table until the default flipped. See {@link menuPortal}.\n * On web it dismisses on outside-click / Escape; on native the caller closes it on blur/select.\n * Purely presentational + theme-flat, so it stays reusable.\n *\n * Promoted verbatim out of `@dloizides/ui-tables`' private `Filters/components/AnchoredMenu`.\n *\n * Deliberately no `ui-layout` dependency: `ui-forms` is a low-level primitive and must not take a\n * runtime dependency on the higher-level `ui-layout` `ModalDropdown` — that would invert the graph\n * for every consumer. The portal mechanism therefore lives locally in {@link menuPortal}.\n */\nimport React, { useEffect } from 'react';\n\nimport { createPortal } from 'react-dom';\nimport { Pressable, ScrollView, Text, View } from 'react-native';\n\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\nimport { buildPortalPopoverStyle, useAnchorRect } from './menuPortal';\n\nconst IS_WEB = typeof document !== 'undefined';\nconst ESCAPE_KEY = 'Escape';\nconst ACTIVE_WEIGHT = '700' as const;\nconst IDLE_WEIGHT = '400' as const;\n\n/** The four theme colours the menu paints with — passed in, so the menu stays theme-flat. */\nexport interface AnchoredMenuColors {\n text: string;\n border: string;\n surface: string;\n brand: string;\n}\n\nexport interface AnchoredMenuProps {\n options: readonly ControlOption[];\n /** The currently-selected value, highlighted in the list ('' = none). */\n selectedValue: string;\n onSelect: (value: string) => void;\n onDismiss: () => void;\n colors: AnchoredMenuColors;\n /** PRE-LOCALIZED accessibility hint applied to every option. */\n optionHint: string;\n /**\n * PRE-LOCALIZED accessible NAME for the menu container itself (e.g. \"Recent values\"). Optional and\n * additive — omitted, the menu keeps only its `role=\"menu\"` as before, so existing callers are\n * unaffected. Supplied, a screen reader announces the list's purpose, not just \"menu\".\n */\n accessibilityLabel?: string;\n /** Base testID: the menu is `${testID}-menu`, each option `${testID}-option-${value}`. */\n testID: string;\n /** Node whose clicks count as \"inside\" (the anchor) so its own press doesn't self-dismiss. */\n anchorRef: React.RefObject<View | null>;\n /**\n * On web, render the popover in a portal to `document.body` with `position: fixed` at the anchor's\n * measured rect, so it escapes react-native-web's trapped stacking contexts and any ancestor\n * `overflow: hidden` (the fix for a menu that paints under / is clipped by the content below it).\n * No effect on native (the `IS_WEB` guard keeps native in-tree regardless).\n *\n * Default `true` — portalling is the CORRECT default: an in-tree popover is always at risk of\n * being painted under a later-painting sibling (a table, a card, the next filter field). The old\n * default was `false`, which silently left `SelectControl`'s menu hidden behind the attendee table\n * (a recurrence of the exact bug this mechanism fixed for `TypeaheadControl`). Pass `usePortal={false}`\n * only for the rare case that genuinely wants the menu clipped to its container.\n */\n usePortal?: boolean;\n}\n\n/** Web-only outside-click + Escape dismissal (no-op on native). */\nfunction useDismiss(\n anchorRef: React.RefObject<View | null>,\n menuRef: React.RefObject<View | null>,\n onDismiss: () => void,\n): void {\n useEffect(() => {\n if (!IS_WEB) return undefined;\n const onMouseDown = (event: MouseEvent): void => {\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- RN web refs are HTMLElements at runtime\n const anchorNode = anchorRef.current as unknown as HTMLElement | null;\n // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- RN web refs are HTMLElements at runtime\n const menuNode = menuRef.current as unknown as HTMLElement | null;\n const target = event.target instanceof Node ? event.target : null;\n const insideAnchor = anchorNode !== null && target !== null && anchorNode.contains(target);\n const insideMenu = menuNode !== null && target !== null && menuNode.contains(target);\n if (!insideAnchor && !insideMenu) onDismiss();\n };\n const onKeyDown = (event: KeyboardEvent): void => {\n if (event.key === ESCAPE_KEY) onDismiss();\n };\n document.addEventListener('mousedown', onMouseDown);\n document.addEventListener('keydown', onKeyDown);\n return () => {\n document.removeEventListener('mousedown', onMouseDown);\n document.removeEventListener('keydown', onKeyDown);\n };\n }, [anchorRef, menuRef, onDismiss]);\n}\n\nexport function AnchoredMenu({\n options,\n selectedValue,\n onSelect,\n onDismiss,\n colors,\n optionHint,\n accessibilityLabel,\n testID,\n anchorRef,\n usePortal = true,\n}: AnchoredMenuProps): React.ReactElement {\n const menuRef = React.useRef<View>(null);\n useDismiss(anchorRef, menuRef, onDismiss);\n // Web + usePortal: track the anchor rect so the fixed, portalled menu stays glued to the trigger.\n const rect = useAnchorRect(anchorRef, usePortal);\n const portalStyle = rect !== null ? buildPortalPopoverStyle(rect) : null;\n\n const menu = (\n <View\n ref={menuRef}\n accessibilityLabel={accessibilityLabel}\n accessibilityRole=\"menu\"\n // `portalStyle` (position:fixed at the measured rect) is appended LAST so it wins over\n // s.menu's default `position:absolute; top:100%` when portalling; null (native / no portal)\n // leaves the in-tree anchored style untouched.\n style={[s.menu, { borderColor: colors.border, backgroundColor: colors.surface }, portalStyle]}\n testID={`${testID}-menu`}\n >\n {/* Scroll the options when they exceed the menu's maxHeight (s.menu). Without this the list was\n clipped by `overflow: hidden` with no way to reach the options below the fold. */}\n <ScrollView keyboardShouldPersistTaps=\"handled\" nestedScrollEnabled>\n {options.map((opt) => {\n const active = opt.value === selectedValue;\n return (\n <Pressable\n key={opt.value}\n accessibilityRole=\"menuitem\"\n accessibilityLabel={opt.label}\n accessibilityHint={optionHint}\n // `accessibilityState` is NATIVE-ONLY: react-native-web does not read it at all, so\n // on web the selected option was distinguished by colour + font-weight ALONE — no\n // screen reader could tell which option was current (WCAG 1.4.1, use of colour).\n // `aria-selected` is the web channel and RN-web forwards it verbatim. Both are\n // passed so each platform gets the one it honours. The trigger's `aria-expanded`\n // beside `accessibilityState` is the same pairing — this option row was simply\n // missed when that was done.\n accessibilityState={{ selected: active }}\n aria-selected={active}\n onPress={() => onSelect(opt.value)}\n style={s.option}\n testID={`${testID}-option-${opt.value}`}\n >\n <Text style={[s.optionText, { color: active ? colors.brand : colors.text, fontWeight: active ? ACTIVE_WEIGHT : IDLE_WEIGHT }]}>\n {opt.label}\n </Text>\n </Pressable>\n );\n })}\n </ScrollView>\n </View>\n );\n\n // Portal to document.body on web so no ancestor stacking context / overflow can trap or clip it.\n if (usePortal && IS_WEB) return createPortal(menu, document.body);\n return menu;\n}\n\nexport default AnchoredMenu;\n","/**\n * `useThemedInput` — the shared \"readable + lively\" text-input treatment, driven entirely by\n * the active `@dloizides/ui-feedback` theme (so it re-themes per tenant, no hard-coded hex).\n *\n * At rest: dark readable text on a subtle off-white surface with a soft border.\n * On hover (web): the border strengthens a touch.\n * On focus: the border becomes the brand primary, the background brightens to the plain surface\n * (white), and a soft 3px brand-tinted focus ring fades in.\n *\n * Kept FAST: the animation is a pure GPU-cheap CSS transition on `border-color`,\n * `background-color` and `box-shadow` (the focus ring is a `box-shadow`, so it never triggers\n * layout/reflow). There is NO `Animated`, `LayoutAnimation` or JS timer — only React state\n * toggled by focus/blur/hover. Web-only style keys (`transition*`, `boxShadow`, `outlineStyle`)\n * and the mouse-hover handlers are guarded behind `Platform.OS === 'web'`, so the hook stays\n * native-safe (native simply applies the state-driven colours instantly).\n */\nimport { useCallback, useMemo, useState } from 'react';\n\nimport { Platform, type TextInputProps, type TextStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\n/** The exact focus/blur event types of the installed `react-native` `TextInput` (version-safe). */\ntype FocusEvent = Parameters<NonNullable<TextInputProps['onFocus']>>[0];\ntype BlurEvent = Parameters<NonNullable<TextInputProps['onBlur']>>[0];\n\nconst IS_WEB = Platform.OS === 'web';\n\nconst TRANSITION_PROPERTY = 'border-color, background-color, box-shadow';\nconst TRANSITION_DURATION = '0.14s';\nconst TRANSITION_TIMING = 'ease';\nconst FOCUS_RING_WIDTH = 3;\nconst FOCUS_RING_ALPHA = 0.16;\nconst HOVER_BORDER_ALPHA = 0.22;\n/**\n * Placeholder opacity. The theme's `textSecondary` is deliberately a DARK, accessible grey\n * (design-tokens UX-11) because it also paints readable secondary *copy* — so reusing it at\n * full strength made placeholders look like already-typed text. Compositing it toward the field\n * background at this alpha keeps the hue but pulls the placeholder clearly lighter than the solid\n * entered text (`colors.text`), so \"hint\" vs \"value\" reads at a glance. Works in dark mode too\n * (it composites toward whatever the field background is). The field's real visible label — not\n * the placeholder — carries the accessible name, so a lighter hint is a usability win, not an a11y loss.\n */\nconst PLACEHOLDER_ALPHA = 0.6;\n\nconst HEX_RADIX = 16;\nconst HEX_SHORT_LENGTH = 4;\nconst HEX_FULL_LENGTH = 7;\nconst RED_START = 1;\nconst GREEN_START = 3;\nconst BLUE_START = 5;\nconst CHANNEL_END_OFFSET = 2;\n\n/**\n * Convert an `#rgb` / `#rrggbb` colour to an `rgba(...)` string at the given alpha. Any other\n * colour form (already `rgba()`, a CSS name, …) is returned unchanged — so the caller degrades\n * gracefully rather than emitting an invalid value.\n */\n/**\n * True when the user asked the OS to reduce motion (web only). Read at render so the\n * focus/hover transition collapses to an instant change for those users (WCAG 2.3.3 / the\n * `prefers-reduced-motion: reduce` contract). Safe under SSR / no `matchMedia`.\n */\nfunction prefersReducedMotion(): boolean {\n if (!IS_WEB || typeof window === 'undefined' || typeof window.matchMedia !== 'function') return false;\n return window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n}\n\nfunction withAlpha(color: string, alpha: number): string {\n const hex = color.trim();\n const isHex = hex.charAt(0) === '#' && (hex.length === HEX_FULL_LENGTH || hex.length === HEX_SHORT_LENGTH);\n if (!isHex) return color;\n const full =\n hex.length === HEX_SHORT_LENGTH\n ? `#${hex.charAt(1)}${hex.charAt(1)}${hex.charAt(2)}${hex.charAt(2)}${hex.charAt(3)}${hex.charAt(3)}`\n : hex;\n const r = parseInt(full.slice(RED_START, RED_START + CHANNEL_END_OFFSET), HEX_RADIX);\n const g = parseInt(full.slice(GREEN_START, GREEN_START + CHANNEL_END_OFFSET), HEX_RADIX);\n const b = parseInt(full.slice(BLUE_START, BLUE_START + CHANNEL_END_OFFSET), HEX_RADIX);\n return `rgba(${r}, ${g}, ${b}, ${alpha})`;\n}\n\nexport interface UseThemedInputOptions {\n /** Render with the error border colour (the brand focus border is suppressed while errored). */\n hasError?: boolean;\n /** Consumer focus handler — composed with the internal focus-state toggle. */\n onFocus?: (e: FocusEvent) => void;\n /** Consumer blur handler — composed with the internal focus-state toggle. */\n onBlur?: (e: BlurEvent) => void;\n}\n\nexport interface ThemedInput {\n /** The themed input style for the current focus/hover state (memoised). Merge AFTER your box style. */\n style: TextStyle;\n /**\n * The placeholder colour: the theme's `textSecondary` composited toward the field\n * background ({@link PLACEHOLDER_ALPHA}) so a placeholder reads as a faint hint, clearly\n * lighter than the solid entered text rather than looking like an already-filled value.\n */\n placeholderTextColor: string;\n isFocused: boolean;\n isHovered: boolean;\n /** Spread/attach onto the `<TextInput>` to drive the focus treatment. */\n focusBind: {\n onFocus: (e: FocusEvent) => void;\n onBlur: (e: BlurEvent) => void;\n };\n /** Web-only mouse-hover handlers, pre-typed for `<TextInput>` (an empty object on native). */\n hoverBind: TextInputProps;\n}\n\nexport function useThemedInput(options: UseThemedInputOptions = {}): ThemedInput {\n const { hasError = false, onFocus, onBlur } = options;\n const { theme } = useUi();\n const { colors, palette, semantic } = theme;\n\n const [isFocused, setIsFocused] = useState(false);\n const [isHovered, setIsHovered] = useState(false);\n\n const handleFocus = useCallback(\n (e: FocusEvent) => {\n setIsFocused(true);\n onFocus?.(e);\n },\n [onFocus],\n );\n const handleBlur = useCallback(\n (e: BlurEvent) => {\n setIsFocused(false);\n onBlur?.(e);\n },\n [onBlur],\n );\n const handleHoverIn = useCallback(() => setIsHovered(true), []);\n const handleHoverOut = useCallback(() => setIsHovered(false), []);\n\n const primary = palette.primary['500'];\n const errorColor = semantic.error['500'];\n\n const style = useMemo<TextStyle>(() => {\n const restBorder = hasError ? errorColor : colors.border;\n const focusBorder = hasError ? errorColor : primary;\n const borderColor = isFocused ? focusBorder : isHovered ? withAlpha(colors.text, HOVER_BORDER_ALPHA) : restBorder;\n const backgroundColor = isFocused ? colors.surface : colors.surfaceElevated;\n const base: TextStyle = { color: colors.text, borderColor, backgroundColor };\n if (!IS_WEB) return base;\n // A focused field ALWAYS gets a ring — an errored one just changes its colour to the error\n // tint (v1: `input.invalid:focus { box-shadow: 0 0 0 3px var(--danger-tint) }`). Suppressing\n // the ring while errored, as this did, removed the focus indicator (WCAG 2.4.7) from precisely\n // the field the user was sent back to fix, at the moment they are most likely on a keyboard.\n const ringColor = hasError ? errorColor : primary;\n const ring = isFocused ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(ringColor, FOCUS_RING_ALPHA)}` : 'none';\n const webStyle = {\n transitionProperty: TRANSITION_PROPERTY,\n // Collapse the eased transition to instant when the user prefers reduced motion.\n transitionDuration: prefersReducedMotion() ? '0s' : TRANSITION_DURATION,\n transitionTimingFunction: TRANSITION_TIMING,\n boxShadow: ring,\n outlineStyle: 'none',\n };\n return { ...base, ...webStyle } as TextStyle;\n }, [\n isFocused,\n isHovered,\n hasError,\n colors.text,\n colors.border,\n colors.surface,\n colors.surfaceElevated,\n primary,\n errorColor,\n ]);\n\n const focusBind = useMemo(() => ({ onFocus: handleFocus, onBlur: handleBlur }), [handleFocus, handleBlur]);\n\n const hoverBind = useMemo<TextInputProps>(\n () =>\n IS_WEB ? ({ onMouseEnter: handleHoverIn, onMouseLeave: handleHoverOut } as unknown as TextInputProps) : {},\n [handleHoverIn, handleHoverOut],\n );\n\n return {\n style,\n placeholderTextColor: withAlpha(colors.textSecondary, PLACEHOLDER_ALPHA),\n isFocused,\n isHovered,\n focusBind,\n hoverBind,\n };\n}\n","/**\n * Validation ARIA for a form control — web only, no-op on native.\n *\n * ## Why this is here and NOT in `@dloizides/a11y`\n *\n * This looks exactly like adapter work, and moving it into the shared accessibility package\n * is the obvious next step. It would be a mistake, and the reason is worth spelling out\n * because the next person to read this will have the same instinct.\n *\n * `@dloizides/a11y` states its own invariant in `types.ts`: `A11yState` models\n * \"only the members with a faithful expression on BOTH platforms ... so a contract can never\n * promise something one platform silently drops (the exact bug class this package exists to\n * close)\". `invalid` and `required` have NO faithful React Native expression — RN's\n * `AccessibilityState` has no `invalid`, and `accessibilityRequired` does not exist. Adding\n * them to `A11yState` would make the adapter accept a contract it can only honour on web and\n * must silently discard on native. That is precisely the failure the package was built to\n * prevent, reintroduced through its own front door.\n *\n * So the seam stays here, in the package that owns form semantics, where \"web-only\" is an\n * honest local statement rather than a promise broken at a platform boundary. Consequently\n * `@dloizides/a11y` needs no version bump for this change.\n *\n * ## Why it exists at all\n *\n * The identical branch was written twice — `ThemedTextInput` and `ChipSelector` — the second\n * even documenting itself as \"the same escape-hatch-free pattern `ThemedTextInput` uses\". Two\n * copies of one rule is two places for it to drift.\n */\nimport { Platform } from 'react-native';\n\n/**\n * Web-only ARIA attributes react-native-web forwards to the underlying DOM element but that\n * RN's prop types do not enumerate. Callers cast through their own host props at the spread\n * site (never `any`), so these semantics reach a screen reader without a type escape hatch.\n */\nexport interface WebFieldA11y {\n 'aria-invalid'?: boolean;\n 'aria-describedby'?: string;\n 'aria-required'?: boolean;\n}\n\nexport interface WebFieldA11yInput {\n /** id of the element describing this control — typically `Field`'s error/hint line. */\n describedById?: string;\n /** Announce the control as failing validation. */\n hasError?: boolean;\n /**\n * Mark the control mandatory. Omit for controls that have no required affordance; an\n * omitted value emits nothing rather than `aria-required=\"false\"`, which would tell a\n * screen reader something different from saying nothing at all.\n */\n required?: boolean;\n}\n\nconst IS_WEB = Platform.OS === 'web';\n\n/**\n * Build the validation ARIA for a form control.\n *\n * Returns an EMPTY object on native — deliberately, and not as an oversight: there is no\n * native equivalent to emit, and inventing one would mean claiming a guarantee the platform\n * cannot keep. Every attribute is `undefined` unless genuinely true, so nothing is emitted\n * that a screen reader would have to interpret as an explicit negative.\n */\nexport function webFieldA11y({ describedById, hasError = false, required = false }: WebFieldA11yInput): WebFieldA11y {\n if (!IS_WEB) {\n return {};\n }\n return {\n 'aria-invalid': hasError ? true : undefined,\n 'aria-describedby': describedById,\n 'aria-required': required ? true : undefined,\n };\n}\n","/**\n * `ThemedTextInput` — the shared, readable + lively text-input primitive. A thin `<TextInput>`\n * wrapper that applies the `useThemedInput` treatment (dark readable text, subtle off-white rest\n * background, and the brand focus animation: indigo border + white background + soft 3px ring,\n * eased over .14s via a GPU-cheap CSS transition on web; instant, native-safe off web).\n *\n * It is the ONE source of truth for the input look: `FormField` renders it, and raw filter inputs\n * (search / country / year / date fallbacks) use it directly instead of forking the styles.\n *\n * ## The box metrics are applied HERE, and that is new\n *\n * This component claimed to be the source of truth for the input look while shipping only\n * COLOURS — no border, no radius, no padding, no height. `FormField` happened to pass its own\n * private copy of those metrics, so every input reached through `FormField` looked right and the\n * gap stayed invisible. Any caller that used `ThemedTextInput` directly — the documented, blessed\n * way to use it — got a raw browser input: **19px tall**, measured in production on an admin CMS\n * where all 10 inputs failed the hit-target floor.\n *\n * So `controlStyles.input` is now the component's own base, ahead of the caller's `style` in the\n * cascade. Callers that already passed the same metrics (`FormField`) are unaffected — the values\n * are identical, which is precisely why the duplication was invisible — and callers that pass\n * their own overrides still win, because their `style` merges after the base.\n *\n * Every existing `TextInputProps` (value, placeholder, onChangeText, testID, accessibility…) is\n * forwarded untouched; `onFocus`/`onBlur` you pass are composed with the internal focus state.\n */\nimport React from 'react';\n\nimport { StyleSheet, TextInput, type TextInputProps } from 'react-native';\n\nimport { controlStyles } from '../controls/controlStyles';\nimport { useThemedInput } from '../useThemedInput/useThemedInput';\nimport { webFieldA11y } from '../webFieldA11y/webFieldA11y';\n\n/**\n * A multi-line box has to be tall enough to show that it IS multi-line. Left at the single-line\n * floor a textarea looks exactly like a text field, and an author writing a paragraph gets one\n * visible line. Two lines of content plus the box's own padding.\n */\nconst MULTILINE_MIN_HEIGHT = 96;\n\nconst boxStyles = StyleSheet.create({\n multiline: {\n minHeight: MULTILINE_MIN_HEIGHT,\n textAlignVertical: 'top',\n },\n});\n\nexport interface ThemedTextInputProps extends TextInputProps {\n /** Render with the error border colour (matches `FormField`'s error treatment). */\n hasError?: boolean;\n /**\n * id of an element describing this input (e.g. an error/hint line). Linked via\n * `aria-describedby` on web so a screen reader reads it after the field's name. No-op native.\n */\n describedById?: string;\n /** Marks the field required for assistive tech (`aria-required` on web). No-op on native. */\n requiredField?: boolean;\n /**\n * Opt OUT of the shared box metrics (border, radius, padding, the kit's min-height floor) and\n * render colours only — the pre-1.11 behaviour.\n *\n * For the rare control that supplies its own complete box, e.g. an input embedded inside an\n * already-bordered composite where a second border would double up. It is a prop rather than\n * the default because the default has to be the accessible one: the previous default shipped\n * 19px inputs to production precisely because \"no metrics\" was the silent fallback.\n */\n unstyledBox?: boolean;\n}\n\nexport const ThemedTextInput = React.forwardRef<TextInput, ThemedTextInputProps>(function ThemedTextInput(\n {\n hasError = false,\n describedById,\n requiredField = false,\n unstyledBox = false,\n onFocus,\n onBlur,\n style,\n placeholderTextColor,\n ...rest\n },\n ref,\n): React.ReactElement {\n const {\n style: themedStyle,\n placeholderTextColor: themedPlaceholder,\n focusBind,\n hoverBind,\n } = useThemedInput({ hasError, onFocus, onBlur });\n\n // aria-invalid announces the error state; aria-describedby ties the error/hint text to the\n // field; aria-required marks it mandatory. Web-only (RN-web → DOM); omitted on native.\n const webA11y = webFieldA11y({ describedById, hasError, required: requiredField });\n\n // Base box FIRST so the caller's `style` still overrides it; `themedStyle` stays last because\n // the theme's colours are not the caller's to override (unchanged from previous versions).\n const boxStyle = unstyledBox ? null : controlStyles.input;\n const multilineStyle = rest.multiline === true && !unstyledBox ? boxStyles.multiline : null;\n\n return (\n <TextInput\n ref={ref}\n placeholderTextColor={placeholderTextColor ?? themedPlaceholder}\n {...rest}\n {...(webA11y as TextInputProps)}\n {...hoverBind}\n onFocus={focusBind.onFocus}\n onBlur={focusBind.onBlur}\n style={[boxStyle, multilineStyle, style, themedStyle]}\n />\n );\n});\n","/**\n * `recentValuesCore` — the pure + storage-facing internals of {@link useRecentValues}, kept out of\n * the hook file so the list algebra (trim / de-dupe / promote / cap) and the `localStorage` access\n * are each unit-testable in isolation.\n *\n * ## RN-web storage reality\n *\n * `ui-forms` runs on react-native-web, so a component using this may mount on web (where\n * `window.localStorage` exists), on native (where it does NOT), or under SSR / a hardened browser\n * where touching `window.localStorage` THROWS (disabled cookies, privacy mode, quota). Every access\n * therefore goes through {@link getStorage}, which returns `null` rather than throwing, and every\n * read/write is wrapped so a storage failure degrades to an in-memory-only no-op instead of\n * exploding inside render. On native / when storage is unavailable the feature is simply inert and\n * the recents list is always `[]`.\n */\n\n/** The single namespace every persisted list lives under, so one product can never collide with another. */\nconst STORAGE_PREFIX = '@dloizides/ui-forms:recent:';\n\n/** Default cap on remembered values (most-recent-first). */\nexport const DEFAULT_MAX_RECENTS = 10;\n\n/** The full `localStorage` key for a caller's logical `key`. */\nexport function recentStorageKey(key: string): string {\n return `${STORAGE_PREFIX}${key}`;\n}\n\n/**\n * The active web `localStorage`, or `null` on native / SSR / when merely READING the property\n * throws (some browsers throw on `window.localStorage` access when storage is disabled). Never\n * throws — callers treat `null` as \"storage unavailable, no-op\".\n */\nfunction getStorage(): Storage | null {\n try {\n if (typeof window === 'undefined') return null;\n const storage = window.localStorage;\n return storage !== null && storage !== undefined ? storage : null;\n } catch {\n return null;\n }\n}\n\n/**\n * Read the persisted list for `key`. Returns `[]` when storage is unavailable, the key is absent,\n * the stored JSON is corrupt, or the parsed value is not an array of strings — corruption is\n * tolerated, never surfaced as a throw.\n */\nexport function readRecents(key: string): string[] {\n const storage = getStorage();\n if (storage === null) return [];\n try {\n const raw = storage.getItem(recentStorageKey(key));\n if (raw === null) return [];\n const parsed: unknown = JSON.parse(raw);\n if (!Array.isArray(parsed)) return [];\n return parsed.filter((entry): entry is string => typeof entry === 'string');\n } catch {\n return [];\n }\n}\n\n/** Persist `values` for `key`. Silent no-op when storage is unavailable or the write throws (quota). */\nexport function writeRecents(key: string, values: readonly string[]): void {\n const storage = getStorage();\n if (storage === null) return;\n try {\n storage.setItem(recentStorageKey(key), JSON.stringify(values));\n } catch {\n // Quota exceeded / storage disabled mid-session — drop the write rather than throw into render.\n }\n}\n\n/** Remove the persisted list for `key`. Silent no-op when storage is unavailable or removal throws. */\nexport function clearRecents(key: string): void {\n const storage = getStorage();\n if (storage === null) return;\n try {\n storage.removeItem(recentStorageKey(key));\n } catch {\n // Storage disabled mid-session — nothing to do.\n }\n}\n\n/**\n * The pure list algebra: fold `value` into `current`, returning the new most-recent-first list.\n *\n * - trims `value`; an empty (or whitespace-only) value is ignored, returning `current` unchanged;\n * - de-dupes case-insensitively, so \"Cyprus\" typed after \"cyprus\" does not create a second row;\n * - PROMOTES an existing (case-insensitive) match to the front, keeping the newly-typed casing;\n * - caps the result at `max` (most-recent-first), so the list can never grow without bound.\n */\nexport function computeNextRecents(current: readonly string[], value: string, max: number): string[] {\n const trimmed = value.trim();\n if (trimmed === '') return [...current];\n const lower = trimmed.toLowerCase();\n const withoutMatch = current.filter((entry) => entry.toLowerCase() !== lower);\n const promoted = [trimmed, ...withoutMatch];\n const cap = max > 0 ? max : 0;\n return promoted.slice(0, cap);\n}\n\n/** True when two lists hold the same values in the same order (reference-stability guard for state). */\nexport function recentsEqual(a: readonly string[], b: readonly string[]): boolean {\n if (a.length !== b.length) return false;\n return a.every((entry, index) => entry === b[index]);\n}\n","/**\n * `useRecentValues` — an opt-in \"remember the last N submitted values, show them again\" store for a\n * single logical input, persisted to `localStorage` under `@dloizides/ui-forms:recent:<key>`.\n *\n * It is the engine behind {@link FormField}'s `recentKey` prop, but is exported on its own so any\n * consumer can build a bespoke recents surface. Pure + storage-guarded (see {@link recentValuesCore}):\n * on native / SSR / disabled storage it is a silent no-op that always reports `recents: []`.\n *\n * ```ts\n * const { recents, remember, clear } = useRecentValues('invoice-search');\n * // on submit / blur: remember(text); in a menu: recents.map(...); to reset: clear();\n * ```\n */\nimport { useCallback, useEffect, useState } from 'react';\n\nimport {\n DEFAULT_MAX_RECENTS,\n clearRecents,\n computeNextRecents,\n readRecents,\n recentsEqual,\n writeRecents,\n} from './recentValuesCore';\n\nexport interface RecentValues {\n /** The remembered values, most-recent-first (never longer than `max`; `[]` when storage is unavailable). */\n recents: string[];\n /** Fold a value into the list (trim / de-dupe / promote / cap) and persist. Empty values are ignored. */\n remember: (value: string) => void;\n /** Forget every remembered value for this key and clear it from storage. */\n clear: () => void;\n}\n\n/**\n * @param key logical name for this input's history (namespaced under `@dloizides/ui-forms:recent:`).\n * @param max most-recent-first cap on remembered values. Default {@link DEFAULT_MAX_RECENTS}.\n */\nexport function useRecentValues(key: string, max: number = DEFAULT_MAX_RECENTS): RecentValues {\n // Seeded from storage on first render (lazy initialiser — no read on every render).\n const [recents, setRecents] = useState<string[]>(() => readRecents(key).slice(0, max));\n\n // Re-hydrate when the key or cap changes, so switching which input this drives shows its own history.\n useEffect(() => {\n setRecents(readRecents(key).slice(0, max));\n }, [key, max]);\n\n const remember = useCallback(\n (value: string) => {\n setRecents((current) => {\n const next = computeNextRecents(current, value, max);\n // An ignored (empty) value or an already-front value yields an identical list — keep the\n // same reference so no re-render fires and no redundant write hits storage.\n if (recentsEqual(next, current)) return current;\n writeRecents(key, next);\n return next;\n });\n },\n [key, max],\n );\n\n const clear = useCallback(() => {\n clearRecents(key);\n setRecents([]);\n }, [key]);\n\n return { recents, remember, clear };\n}\n\nexport default useRecentValues;\n","/**\n * `RecentInputField` — the `ThemedTextInput` PLUS the opt-in \"recent values\" dropdown that\n * {@link FormField} renders only when a `recentKey` is supplied. Split out of `FormField` so the\n * default (no `recentKey`) path stays a plain input with ZERO extra state, refs, effects or storage\n * access, and every consumer that never opts in pays nothing.\n *\n * On focus it surfaces the values previously submitted through this key (via {@link useRecentValues})\n * in the shared {@link AnchoredMenu} — reused rather than hand-rolled, and forced through a\n * `document.body` portal (`usePortal`) so the list is never painted behind a table / card / the next\n * field (the kit's known AnchoredMenu stacking gotcha). Picking a row fills the input (`onChangeText`)\n * and closes. A value is remembered on submit (Enter) AND on blur-with-content, so both \"hit enter\"\n * and \"typed then moved on\" are captured. Colours come only from the active theme — no literals.\n */\nimport React, { useCallback, useRef, useState } from 'react';\n\nimport { View } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { AnchoredMenu } from '../AnchoredMenu/AnchoredMenu';\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\nimport { ThemedTextInput, type ThemedTextInputProps } from '../ThemedTextInput/ThemedTextInput';\nimport { useRecentValues } from '../useRecentValues/useRecentValues';\n\n/** Delay before blur closes the menu, so a tap on a recent row registers first (matches TypeaheadControl). */\nconst CLOSE_DELAY_MS = 140;\n\n// Event types taken from the input's OWN prop signatures, so they track the installed react-native\n// version exactly (focus/blur/submit event shapes have drifted between RN releases).\ntype FocusEvent = Parameters<NonNullable<ThemedTextInputProps['onFocus']>>[0];\ntype BlurEvent = Parameters<NonNullable<ThemedTextInputProps['onBlur']>>[0];\ntype SubmitEvent = Parameters<NonNullable<ThemedTextInputProps['onSubmitEditing']>>[0];\n\nexport interface RecentInputFieldProps extends ThemedTextInputProps {\n /** Namespace under which this input's submitted values are remembered. */\n recentKey: string;\n /** Cap on remembered values (most-recent-first). Defaults to the hook's own default. */\n recentMax?: number;\n /** The field's accessible name — used to build the recents menu/row a11y strings. */\n label: string;\n}\n\nexport function RecentInputField({\n recentKey,\n recentMax,\n label,\n value,\n testID,\n onChangeText,\n onSubmitEditing,\n onFocus,\n onBlur,\n ...rest\n}: RecentInputFieldProps): React.ReactElement {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const { recents, remember } = useRecentValues(recentKey, recentMax);\n\n const anchorRef = useRef<View>(null);\n // Latest text, tracked independently of whether the field is controlled, so blur/submit can\n // remember the right value even when the parent does not pass `value`.\n const latestText = useRef<string>(typeof value === 'string' ? value : '');\n const [isOpen, setIsOpen] = useState(false);\n\n const handleChange = useCallback(\n (text: string) => {\n latestText.current = text;\n onChangeText?.(text);\n },\n [onChangeText],\n );\n\n const handleFocus = useCallback(\n (event: FocusEvent) => {\n setIsOpen(true);\n onFocus?.(event);\n },\n [onFocus],\n );\n\n const handleBlur = useCallback(\n (event: BlurEvent) => {\n // Remember on blur-with-content so \"typed then clicked away\" is captured, not only Enter.\n if (latestText.current.trim() !== '') remember(latestText.current);\n // Delay the close so a pointer-down on a recent row lands before the menu unmounts.\n setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS);\n onBlur?.(event);\n },\n [remember, onBlur],\n );\n\n const handleSubmit = useCallback(\n (event: SubmitEvent) => {\n remember(latestText.current);\n setIsOpen(false);\n onSubmitEditing?.(event);\n },\n [remember, onSubmitEditing],\n );\n\n const pick = useCallback(\n (picked: string) => {\n latestText.current = picked;\n onChangeText?.(picked);\n remember(picked);\n setIsOpen(false);\n },\n [onChangeText, remember],\n );\n\n const options: ControlOption[] = recents.map((entry) => ({ label: entry, value: entry }));\n const showMenu = isOpen && options.length > 0;\n const recentTestID = testID !== undefined ? `${testID}-recent` : 'form-field-recent';\n\n return (\n <View ref={anchorRef} style={s.anchor}>\n <ThemedTextInput\n {...rest}\n testID={testID}\n value={value}\n onChangeText={handleChange}\n onFocus={handleFocus}\n onBlur={handleBlur}\n onSubmitEditing={handleSubmit}\n />\n {showMenu ? (\n <AnchoredMenu\n accessibilityLabel={`Recent ${label} values`}\n anchorRef={anchorRef}\n colors={{ text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary['500'] }}\n onDismiss={() => setIsOpen(false)}\n onSelect={pick}\n optionHint={`Fill ${label} with this recent value`}\n options={options}\n selectedValue={typeof value === 'string' ? value : ''}\n testID={recentTestID}\n // Portal to document.body: the recents list sits above later-painting content (rows, cards,\n // the next field). Without the portal RN-web's trapped z-index paints it behind them.\n usePortal\n />\n ) : null}\n </View>\n );\n}\n\nexport default RecentInputField;\n","/**\n * Reusable form field — labelled text input with optional required mark + error.\n *\n * The label row, the required mark, the error line and the container spacing all come from the\n * generic `Field` wrapper, so a `FormField` and a `Field`-wrapped dropdown sitting next to each\n * other line up exactly and can never drift apart. FormField only adds the control itself.\n *\n * The input is the shared `ThemedTextInput` primitive, so every FormField gets the readable +\n * lively treatment (dark text, subtle off-white rest background, brand focus animation with a\n * soft ring) for free, driven by the active theme.\n */\nimport React from 'react';\n\nimport { type TextInputProps, type ViewStyle } from 'react-native';\n\nimport { Field } from '../Field/Field';\nimport { RecentInputField } from './RecentInputField';\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\n/**\n * The private `styles.input` that used to live here — padding 10/12, radius 8, border 1 — was a\n * verbatim duplicate of `controlStyles.input`, and `ThemedTextInput` now applies that itself. The\n * duplication is what hid the real defect: because `FormField` supplied metrics, inputs reached\n * through it looked correct, while every DIRECT `ThemedTextInput` caller got an unstyled 19px box\n * and nobody could see the difference from in here.\n */\nexport interface FormFieldProps extends Omit<TextInputProps, 'style'> {\n label: string;\n /**\n * Hide the VISIBLE label row while keeping the accessible name.\n *\n * For a field whose placeholder already names it (a toolbar search box, an inline\n * filter) the stacked visible label both wastes a row and misaligns the input\n * against a bare button beside it. Setting this drops ONLY the visible `<label>`:\n * the input still carries `accessibilityLabel={label}`, so a screen reader reads\n * the same name and `label` stays REQUIRED — you never lose the accessible name by\n * blanking it, which is the trap this option exists to remove. Default `false`.\n */\n labelHidden?: boolean;\n required?: boolean;\n error?: string;\n containerStyle?: ViewStyle;\n /**\n * OPT-IN \"recent values\" behaviour. When set, the values submitted through this field are\n * remembered (per this key) and offered in a dropdown on focus; picking one fills the input.\n * Values are recorded on submit (Enter) and on blur-with-content. Persisted to `localStorage`\n * under `@dloizides/ui-forms:recent:<recentKey>`; a silent no-op on native / when storage is\n * unavailable.\n *\n * Leave it UNSET (the default) and the field behaves exactly as before — nothing rendered, no\n * storage touched. NEVER set it on a password / secure field: recents must not persist secrets.\n */\n recentKey?: string;\n /** Cap on remembered values when {@link recentKey} is set (most-recent-first). Default 10. */\n recentMax?: number;\n}\n\nexport const FormField = ({\n label,\n labelHidden = false,\n required = false,\n error,\n containerStyle,\n recentKey,\n recentMax,\n ...textInputProps\n}: FormFieldProps): React.ReactElement => (\n <Field\n containerStyle={containerStyle}\n error={error}\n // An undefined label renders NO label row (see Field): that is how the visible\n // label is hidden. The accessible name is kept on the input below, so hiding\n // the label never strips the name.\n label={labelHidden ? undefined : label}\n required={required}\n >\n {({ describedById, hasError, controlId }) => {\n // Shared props for either input path — identical wiring, so a field looks and behaves the\n // same whether or not it opts into recents.\n const inputProps = {\n accessibilityHint: `Enter ${label}`,\n accessibilityLabel: label,\n describedById,\n hasError,\n id: controlId,\n requiredField: required,\n testID: 'form-field-input',\n ...textInputProps,\n };\n // recentKey set → the recents-enabled input; unset → the plain input, unchanged from before\n // (no extra state/refs/effects/storage — the default path pays nothing).\n return recentKey !== undefined && recentKey !== '' ? (\n <RecentInputField label={label} recentKey={recentKey} recentMax={recentMax} {...inputProps} />\n ) : (\n <ThemedTextInput {...inputProps} />\n );\n }}\n </Field>\n);\n\nexport default FormField;\n","/** Shared ChipSelector constants. */\n\nexport const TRANSPARENT_COLOR = 'transparent';\n\n/**\n * Extra touch margin around a chip. NATIVE ONLY — this does NOT widen the hit area on RN-web,\n * which is what these portals ship. Measured 2026-09-21 (headless Chromium, 360x640):\n * `elementFromPoint` 5px above a chip's top edge, inside `top: 10`, returns the parent, not the\n * chip. react-native-web 0.21.2 uses `hitSlop` only in the legacy `Touchable` press-retention\n * path and ignores it entirely in `Pressable`. The web target is carried by `minHeight:\n * MIN_TARGET_PX` in `chipStyles`; this constant only helps iOS/Android.\n */\nexport const CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 } as const;\n\n/** Gap between adjacent chips, horizontally and between wrapped rows. */\nexport const CHIP_GUTTER = 8;\n\n/**\n * Default chip testID stem. NOT derived from the `testID` prop, because aml-v2's unit +\n * Playwright specs and erevna/katalogos's `Accessibility.test.tsx` already select on\n * `chip-selector-chip-<value>`. `chipTestIDPrefix` is the opt-in override for consumers\n * (kefi) that need their own stem; the default is frozen.\n */\nexport const DEFAULT_CHIP_TESTID_PREFIX = 'chip-selector-chip';\n","import { StyleSheet } from 'react-native';\n\nimport { TRANSPARENT_COLOR } from '../constants';\n\nconst SOLID_RADIUS = 20;\nconst OUTLINE_RADIUS = 999;\nconst OUTLINE_PAD_H = 12;\nconst OUTLINE_PAD_V = 5;\nconst OUTLINE_FONT_SIZE = 13;\n/** Gap between an option's icon and its label. */\nconst CHIP_ICON_GAP = 6;\n/**\n * WCAG minimum touch-target edge, in CSS px. Source of truth is `MIN_TARGET_PX` in\n * `@dloizides/ui-layout`; duplicated here as a local constant rather than taking a whole\n * dependency for one integer. Keep the two in step if ui-layout ever changes it.\n *\n * Needed because `hitSlop` is NATIVE-ONLY: measured 2026-09-21 in headless Chromium at 360px,\n * `document.elementFromPoint` 5px above a chip (inside `CHIP_HIT_SLOP.top: 10`) returns the\n * PARENT, not the chip. react-native-web 0.21.2 references `hitSlop` only in the legacy\n * `Touchable` mixin's press-RETENTION path and not at all in `Pressable`, so on web the\n * rendered box IS the whole tappable area.\n */\nconst MIN_TARGET_PX = 44;\n\nexport const chipStyles = StyleSheet.create({\n chip: {\n paddingHorizontal: 12,\n paddingVertical: 6,\n minHeight: MIN_TARGET_PX,\n justifyContent: 'center',\n borderRadius: SOLID_RADIUS,\n backgroundColor: TRANSPARENT_COLOR,\n borderWidth: 1,\n },\n chipOutline: {\n paddingHorizontal: OUTLINE_PAD_H,\n paddingVertical: OUTLINE_PAD_V,\n minHeight: MIN_TARGET_PX,\n justifyContent: 'center',\n borderRadius: OUTLINE_RADIUS,\n borderWidth: 1,\n },\n chipContent: { flexDirection: 'row', alignItems: 'center', gap: CHIP_ICON_GAP },\n chipText: {},\n chipTextOutline: { fontSize: OUTLINE_FONT_SIZE },\n});\n","import React from 'react';\n\nimport { Text, View, type StyleProp, type TextStyle } from 'react-native';\n\nimport { chipStyles } from './chipStyles';\n\ninterface ChipContentProps {\n icon: React.ReactNode;\n label: string;\n textStyle: StyleProp<TextStyle>;\n}\n\n/** Chip label, preceded by the option's decorative icon when one is supplied. */\nexport function ChipContent({ icon, label, textStyle }: ChipContentProps): React.ReactElement {\n const text = <Text style={textStyle}>{label}</Text>;\n if (icon === undefined || icon === null)\n return text;\n\n return (\n <View style={chipStyles.chipContent}>\n <View aria-hidden={true}>{icon}</View>\n {text}\n </View>\n );\n}\n","import React from 'react';\n\nimport { Pressable, View } from 'react-native';\n\nimport { CHIP_HIT_SLOP } from '../constants';\nimport type { ChipProps } from '../types';\n\nimport { ChipContent } from './ChipContent';\nimport { chipStyles } from './chipStyles';\n\n/** A single outline chip — owns its own hover state (web) for the border/ink lift. */\nexport function OutlineChip<T extends string | number>(props: ChipProps<T>): React.ReactElement {\n const { option, selected, disabled, colors, testID, accessibilityHint, onPress } = props;\n const [hovered, setHovered] = React.useState(false);\n const active = selected || hovered;\n\n const borderColor = active ? colors.primary : colors.border;\n const backgroundColor = selected ? colors.tint : colors.muted;\n // Selected AND hovered both lift the ink to the primary colour (v1's indigo / indigo-dark);\n // the theme surface only guarantees the 500 step, so both use it — border + fill carry the state.\n const textColor = active ? colors.primary : colors.textMuted;\n\n return (\n <Pressable\n ref={props.hostRef}\n accessibilityHint={accessibilityHint}\n accessibilityLabel={option.label}\n accessibilityRole={props.accessibilityRole}\n accessibilityState={{ selected, disabled }}\n aria-checked={props.ariaChecked}\n aria-pressed={props.ariaPressed}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n tabIndex={props.tabIndex}\n testID={testID}\n onHoverIn={() => setHovered(true)}\n onHoverOut={() => setHovered(false)}\n onPress={onPress}\n >\n <View style={[chipStyles.chipOutline, { borderColor, backgroundColor }]}>\n <ChipContent\n icon={option.icon}\n label={option.label}\n textStyle={[chipStyles.chipText, chipStyles.chipTextOutline, { color: textColor }]}\n />\n </View>\n </Pressable>\n );\n}\n","import React from 'react';\n\nimport { TouchableOpacity, View, type ViewProps } from 'react-native';\n\nimport { CHIP_HIT_SLOP, TRANSPARENT_COLOR } from '../constants';\nimport type { ChipProps } from '../types';\n\nimport { ChipContent } from './ChipContent';\nimport { chipStyles } from './chipStyles';\n\n/** A single solid chip — the original filled-pill look (unchanged for existing consumers). */\nexport function SolidChip<T extends string | number>(props: ChipProps<T>): React.ReactElement {\n const { option, selected, disabled, colors, testID, accessibilityHint, onPress } = props;\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? colors.onPrimary : colors.textStrong;\n // RNW forwards `tabIndex` to the DOM, but RN's TouchableOpacity types omit it (ViewProps has it).\n const rovingTabStop: Pick<ViewProps, 'tabIndex'> = { tabIndex: props.tabIndex };\n return (\n <TouchableOpacity\n ref={props.hostRef}\n accessibilityHint={accessibilityHint}\n accessibilityLabel={option.label}\n accessibilityRole={props.accessibilityRole}\n accessibilityState={{ selected, disabled }}\n aria-checked={props.ariaChecked}\n aria-pressed={props.ariaPressed}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n testID={testID}\n onPress={onPress}\n {...rovingTabStop}\n >\n <View style={[chipStyles.chip, { borderColor: colors.border, backgroundColor }]}>\n <ChipContent icon={option.icon} label={option.label} textStyle={[chipStyles.chipText, { color: textColor }]} />\n </View>\n </TouchableOpacity>\n );\n}\n","/**\n * Pure key logic for the WAI-ARIA radio group pattern used by ChipSelector's opt-in radio mode.\n * Kept free of React and the DOM so every branch is unit-testable without rendering.\n */\n\nconst SPACE_KEYS: readonly string[] = [' ', 'Spacebar'];\nconst NEXT_KEYS: readonly string[] = ['ArrowRight', 'ArrowDown'];\nconst PREVIOUS_KEYS: readonly string[] = ['ArrowLeft', 'ArrowUp'];\nconst ROVING_TAB_STOP = 0;\nconst ROVING_SKIPPED = -1;\n\n/**\n * The option index a radio group should select when `key` is pressed on the chip at `index`,\n * or `null` when the key is not part of the pattern.\n *\n * - Space activates the focused chip (returns `index`).\n * - ArrowRight/ArrowDown → next chip, ArrowLeft/ArrowUp → previous, wrapping at both ends.\n * - Enter is deliberately `null`: RNW's press responder already activates a `<div>` chip on\n * Enter, so handling it here would fire `onChange` twice.\n * - Arrows in a one-chip group are `null` — there is nowhere to move, so nothing is selected.\n */\nexport function radioKeyTarget(key: string, index: number, count: number): number | null {\n const isOutOfRange = index < 0 || index >= count;\n if (isOutOfRange)\n return null;\n\n if (SPACE_KEYS.includes(key))\n return index;\n\n const isArrow = NEXT_KEYS.includes(key) || PREVIOUS_KEYS.includes(key);\n if (!isArrow || count === 1)\n return null;\n\n const step = NEXT_KEYS.includes(key) ? 1 : -1;\n return (index + step + count) % count;\n}\n\n/**\n * Roving tabindex: only the selected chip — or the first chip when nothing is selected — is a\n * tab stop. A disabled group has no tab stop at all.\n */\nexport function radioTabIndex(index: number, selectedIndex: number, disabled: boolean): 0 | -1 {\n if (disabled)\n return ROVING_SKIPPED;\n\n const tabStop = selectedIndex >= 0 ? selectedIndex : 0;\n return index === tabStop ? ROVING_TAB_STOP : ROVING_SKIPPED;\n}\n","/**\n * Keyboard + focus wiring for ChipSelector's opt-in radio group.\n *\n * One `onKeyDown` sits on the radiogroup container and catches the key events bubbling up from\n * the focused chip. It lives on the GROUP, not the chip, because RNW's `TouchableOpacity` spreads\n * its press handlers AFTER the caller's props — a chip-level `onKeyDown` on the solid variant is\n * silently overwritten. The focused chip is identified by matching `event.target` against the\n * host nodes registered through `chipRef`.\n */\nimport React from 'react';\n\nimport type { ViewProps } from 'react-native';\n\nimport { radioKeyTarget, radioTabIndex } from '../utils/radioKeyboard';\n\ninterface FocusableNode {\n focus?: () => void;\n}\n\ninterface RadioKeyEvent {\n key: string;\n target: unknown;\n preventDefault: () => void;\n}\n\nexport interface RadioKeyboardConfig<T> {\n /** `false` for button / multi-select groups: the hook then emits nothing at all. */\n enabled: boolean;\n disabled: boolean;\n values: T[];\n /** Index of the selected option, or `-1` when nothing is selected. */\n selectedIndex: number;\n onChange: (value: T) => void;\n}\n\nexport interface RadioKeyboard {\n /** Ref callback factory registering the host node of the chip at `index`. */\n chipRef: (index: number) => (node: unknown) => void;\n /** Roving tabindex for the chip at `index`; `undefined` when radio mode is off. */\n tabIndexFor: (index: number) => 0 | -1 | undefined;\n /** Web props for the group container (`onKeyDown` in radio mode, nothing otherwise). */\n groupProps: ViewProps;\n}\n\nconst NO_GROUP_PROPS: ViewProps = {};\n\nexport function useRadioKeyboard<T>(config: RadioKeyboardConfig<T>): RadioKeyboard {\n const { enabled, disabled, values, selectedIndex, onChange } = config;\n const nodes = React.useRef<unknown[]>([]);\n\n const chipRef = React.useCallback((index: number) => (node: unknown): void => {\n nodes.current[index] = node;\n }, []);\n\n const onKeyDown = (event: RadioKeyEvent): void => {\n if (disabled)\n return;\n\n const index = nodes.current.indexOf(event.target);\n const target = radioKeyTarget(event.key, index, values.length);\n const nextValue = target === null ? undefined : values[target];\n if (target === null || nextValue === undefined)\n return;\n\n // Stops Space scrolling the page and arrows scrolling a scroll container.\n event.preventDefault();\n if (target !== index)\n (nodes.current[target] as FocusableNode | null | undefined)?.focus?.();\n\n onChange(nextValue);\n };\n\n return {\n chipRef,\n tabIndexFor: (index) => (enabled ? radioTabIndex(index, selectedIndex, disabled) : undefined),\n // `onKeyDown` is a web-only View prop RN's types do not declare; RNW forwards it to the DOM.\n groupProps: enabled ? ({ onKeyDown } as unknown as ViewProps) : NO_GROUP_PROPS,\n };\n}\n","/** Theme → chip colour resolution for both ChipSelector variants. */\nimport type { ChipColors } from '../types';\n\nconst WHITE_COLOR = '#fff';\nconst OUTLINE_TINT_ALPHA = 0.1;\nconst HEX_SHORT_LENGTH = 3;\nconst HEX_RADIX = 16;\nconst RGB_R_START = 0;\nconst RGB_R_END = 2;\nconst RGB_G_END = 4;\nconst RGB_B_END = 6;\n\n/** Palette scale carrying the ink for content sitting ON the brand colour. */\nconst ON_BRAND_SCALE = 'onBrand';\n/** The one step every theme scale is guaranteed to define. */\nconst MAIN_STEP = '500';\n\n/**\n * Read the on-brand ink out of a theme palette.\n *\n * Deliberately typed as OPTIONAL rather than read through `palette.onBrand`. Two reasons:\n * this package's declared peer floor is `ui-feedback >= 1.1.0`, whose palette type has no\n * index signature at all; and even on current versions the index signature types every\n * scale as present, which is a lie — only `primary` is guaranteed, and most apps in the\n * fleet publish no `onBrand` scale today. Modelling it as absent-able is what makes the\n * `WHITE_COLOR` fallback honest instead of dead code.\n */\nfunction onBrandInk(palette: object): string {\n const scales = palette as Record<string, Record<string, string> | undefined>;\n return scales[ON_BRAND_SCALE]?.[MAIN_STEP] ?? WHITE_COLOR;\n}\n\n/** Composite a hex colour over the background at a given alpha (theme-driven tint). */\nfunction withAlpha(hex: string, alpha: number): string {\n const normalized = hex.replace('#', '');\n const isShort = normalized.length === HEX_SHORT_LENGTH;\n const full = isShort ? normalized.split('').map((c) => c + c).join('') : normalized;\n const r = parseInt(full.slice(RGB_R_START, RGB_R_END), HEX_RADIX);\n const g = parseInt(full.slice(RGB_R_END, RGB_G_END), HEX_RADIX);\n const b = parseInt(full.slice(RGB_G_END, RGB_B_END), HEX_RADIX);\n const isValid = !Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b);\n return isValid ? `rgba(${r}, ${g}, ${b}, ${alpha})` : hex;\n}\n\ninterface ThemeColorsInput {\n border: string;\n text: string;\n textSecondary: string;\n background: string;\n}\n\n/** Resolve the colours both chip variants read, from the active theme's colours + palette. */\nexport function buildChipColors(\n colors: ThemeColorsInput,\n palette: { primary: { 500: string } },\n): ChipColors {\n const primary = palette.primary[500];\n return {\n border: colors.border,\n textStrong: colors.text,\n textMuted: colors.textSecondary,\n primary,\n onPrimary: onBrandInk(palette),\n muted: colors.background,\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\n };\n}\n","import type { ChipOption, ChipProps } from '../types';\n\n/**\n * The a11y + testID triple a chip needs, resolved once for both variants.\n *\n * Exported for direct unit testing. It has to be tested as a pure function rather than\n * through the DOM because react-native-web DROPS `accessibilityHint` entirely — it reaches\n * native, but no web attribute carries it, so no rendering assertion can tell a correctly\n * threaded hint from one that was never passed. Testing the resolver is the only honest way\n * to pin the behaviour.\n */\nexport function chipIdentity<T>(\n option: ChipOption<T>,\n selected: boolean,\n config: { prefix: string; hint?: string; multiple: boolean; radio?: boolean },\n): Pick<ChipProps<T>, 'testID' | 'accessibilityHint' | 'ariaPressed' | 'accessibilityRole' | 'ariaChecked'> {\n const isRadio = config.radio === true && !config.multiple;\n return {\n testID: `${config.prefix}-${String(option.value)}`,\n // The English default is retained verbatim: erevna/katalogos assert the exact string\n // `Selects Red`. Consumers that localize pass `optionAccessibilityHint`.\n accessibilityHint: config.hint ?? `Selects ${option.label}`,\n ariaPressed: config.multiple ? selected : undefined,\n accessibilityRole: isRadio ? 'radio' : 'button',\n ariaChecked: isRadio ? selected : undefined,\n };\n}\n","/**\n * Chip/pill selector for selecting one or multiple options.\n *\n * Two visual variants (both fully theme-driven):\n * - `solid` (default) — the original filled-pill look: selected = solid primary fill with\n * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.\n * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle\n * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.\n * Hover (web) lifts the border/ink to the primary colour.\n *\n * The label row, the error line and the container spacing come from the shared `Field` wrapper —\n * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes\n * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),\n * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the\n * column and read as a different weight of text. Now there is exactly one label implementation.\n *\n * Structure: chip variants in `components/`, the radio keyboard wiring in `hooks/`, and the pure\n * resolvers (`chipIdentity`, colours, radio key logic) in `utils/`.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, type ViewProps } from 'react-native';\n\nimport { webFieldA11y } from '../webFieldA11y/webFieldA11y';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { Field } from '../Field/Field';\n\nimport { OutlineChip } from './components/OutlineChip';\nimport { SolidChip } from './components/SolidChip';\nimport { CHIP_GUTTER, DEFAULT_CHIP_TESTID_PREFIX } from './constants';\nimport { useRadioKeyboard } from './hooks/useRadioKeyboard';\nimport type { ChipColors, ChipOption, ChipSelectorProps } from './types';\nimport { buildChipColors } from './utils/chipColors';\nimport { chipIdentity } from './utils/chipIdentity';\n\nconst styles = StyleSheet.create({\n chipContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n // `gap`, NOT per-chip margins plus a compensating negative container margin.\n //\n // The old form was `chipWrapper { marginRight: 8, marginBottom: 8 }` with\n // `chipContainer { marginBottom: -8 }`. Its comment blamed `Field`'s 16px container margin —\n // that was WRONG, and worth recording: F3 was briefed on the belief that the -8 compensated for\n // `Field` and had to move in lockstep with it. It did not. -8 cancelled the CHIP's own gutter\n // hanging off the last row, identically whether `Field` contributed 16, 0, or anything else.\n //\n // The pair is still the wrong tool: it holds only while the two constants agree, and it leaves\n // a real negative margin any measuring parent inherits. `gap` produces the byte-identical box\n // and is correct under BOTH of `Field`'s spacing models, not just the one it was tuned against.\n gap: CHIP_GUTTER,\n },\n});\n\n/*\n * `groupA11yProps` + its local `WebGroupA11y` type used to live here — a copy of\n * ThemedTextInput's branch, as its own comment admitted. Both now call `webFieldA11y`.\n * The chip group passes no `required`, so nothing is emitted for it, exactly as before.\n */\n\nexport const ChipSelector = <T extends string | number>({\n label,\n options,\n value,\n onChange,\n multiple = false,\n disabled = false,\n variant = 'solid',\n containerStyle,\n spacing,\n required = false,\n error,\n testID,\n chipTestIDPrefix = DEFAULT_CHIP_TESTID_PREFIX,\n optionAccessibilityHint,\n singleSelectRole = 'button',\n}: ChipSelectorProps<T>): React.ReactElement => {\n const isRadioGroup = !multiple && singleSelectRole === 'radio';\n const { theme } = useUi();\n const { colors, palette } = theme;\n\n const chipColors = React.useMemo<ChipColors>(() => buildChipColors(colors, palette), [colors, palette]);\n\n function isSelected(optionValue: T): boolean {\n if (multiple && Array.isArray(value))\n return value.includes(optionValue);\n\n return value === optionValue;\n }\n\n const radio = useRadioKeyboard({\n enabled: isRadioGroup,\n disabled,\n values: options.map((option) => option.value),\n selectedIndex: options.findIndex((option) => isSelected(option.value)),\n onChange,\n });\n\n function renderChip(option: ChipOption<T>, index: number): React.ReactElement {\n const selected = isSelected(option.value);\n const chipProps = {\n colors: chipColors,\n disabled,\n option,\n selected,\n ...chipIdentity(option, selected, {\n prefix: chipTestIDPrefix,\n hint: optionAccessibilityHint,\n multiple,\n radio: isRadioGroup,\n }),\n // Radio mode only: roving tab stop + host node for arrow-key focus moves. Both stay\n // `undefined` otherwise, so button / multi chips keep their existing tab order.\n tabIndex: radio.tabIndexFor(index),\n hostRef: isRadioGroup ? radio.chipRef(index) : undefined,\n onPress: (): void => onChange(option.value),\n };\n const key = String(option.value);\n return variant === 'outline' ? <OutlineChip key={key} {...chipProps} /> : <SolidChip key={key} {...chipProps} />;\n }\n\n return (\n <Field\n containerStyle={containerStyle}\n error={error}\n label={label}\n required={required}\n spacing={spacing}\n testID={testID}\n >\n {({ describedById, hasError }) => (\n <View\n accessibilityRole={isRadioGroup ? 'radiogroup' : undefined}\n style={styles.chipContainer}\n {...(webFieldA11y({ describedById, hasError }) as ViewProps)}\n {...radio.groupProps}\n >\n {options.map(renderChip)}\n </View>\n )}\n </Field>\n );\n};\n\nexport default ChipSelector;\n","/**\n * Reusable form switch/toggle with an optional description.\n */\nimport React from \"react\";\n\nimport {\n StyleSheet,\n View,\n Text,\n Switch,\n Pressable,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\n\nimport { MIN_TOUCH_TARGET_PX } from \"@dloizides/a11y\";\nimport { useUi } from \"@dloizides/ui-feedback\";\n\nconst DESCRIPTION_FONT_SIZE = 12;\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: \"row\",\n justifyContent: \"space-between\",\n alignItems: \"center\",\n marginBottom: 12,\n // The ROW is the hit box (SHOWCASE-1): RN-web renders Switch as a 40x20 box and ignores\n // `hitSlop`, so a pointer target smaller than the floor cannot be widened any other way.\n minHeight: MIN_TOUCH_TARGET_PX,\n },\n switchSlot: {\n minWidth: MIN_TOUCH_TARGET_PX,\n minHeight: MIN_TOUCH_TARGET_PX,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n textColumn: {\n flex: 1,\n },\n label: {\n fontWeight: \"600\",\n },\n description: {\n fontSize: DESCRIPTION_FONT_SIZE,\n marginTop: 2,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n description: TextStyle;\n}\n\nexport interface FormSwitchProps {\n label: string;\n value: boolean;\n onValueChange: (value: boolean) => void;\n disabled?: boolean;\n description?: string;\n containerStyle?: ViewStyle;\n testID?: string;\n accessibilityHint?: string;\n}\n\nexport const FormSwitch = ({\n label,\n value,\n onValueChange,\n disabled = false,\n description,\n containerStyle,\n testID = \"form-switch\",\n accessibilityHint,\n}: FormSwitchProps): React.ReactElement => {\n const { theme } = useUi();\n const toggle = React.useCallback((): void => {\n if (!disabled) onValueChange(!value);\n }, [disabled, onValueChange, value]);\n const { colors } = theme;\n const hasDescription = typeof description === \"string\" && description !== \"\";\n\n const themeStyles = React.useMemo<ThemeStyles>(() => {\n const labelStyle: TextStyle = { color: colors.text };\n const descriptionStyle: TextStyle = { color: colors.textSecondary };\n return { label: labelStyle, description: descriptionStyle };\n }, [colors.text, colors.textSecondary]);\n\n return (\n /*\n Pointer target only: the whole row toggles on press. It is NOT an a11y element and NOT a tab\n stop (`accessible` / `focusable` false) so the native input below stays the ONE switch. The\n Switch sits under `pointerEvents=\"none\"`, so a tap on it reaches this row exactly once\n instead of toggling twice; keyboard focus + Space still reach the input directly.\n */\n <Pressable\n accessible={false}\n disabled={disabled}\n onPress={toggle}\n style={[styles.container, containerStyle]}\n // RN-web's Pressable always stamps a tabIndex (0, or -1 when disabled) and only an explicit\n // one overrides it — `focusable={false}` does not. -1 keeps the row out of the tab order.\n tabIndex={-1}\n testID={`${testID}-row`}\n >\n <View style={styles.textColumn}>\n <Text style={[styles.label, themeStyles.label]}>{label}</Text>\n {hasDescription ? (\n <Text style={[styles.description, themeStyles.description]}>\n {description}\n </Text>\n ) : null}\n </View>\n {/*\n Exactly ONE element exposes the switch (A11Y-ARIA-CHECKED-1). On web, react-native-web's\n Switch renders a wrapper <div> around a native <input type=\"checkbox\" role=\"switch\"> that\n already carries `checked` / `disabled` — the state assistive tech reads (HTML-AAM maps\n `checked` to the checked state, so no `aria-checked` is needed or allowed on it).\n Passing `accessibilityRole=\"switch\"` here put a SECOND `role=\"switch\"` on the wrapper,\n which RNW then made a `tabindex=\"0\"` stop even when disabled; literal `aria-checked` /\n `aria-disabled` would land on that role-less wrapper too. So neither is passed: the\n wrapper is plain and unfocusable, and native keeps its `switch` role from RN's Switch\n default (`accessibilityRole ?? 'switch'`) plus `accessibilityState` below.\n */}\n <View pointerEvents=\"none\" style={styles.switchSlot} testID={`${testID}-hitbox`}>\n <Switch\n accessibilityHint={accessibilityHint ?? label}\n accessibilityLabel={label}\n accessibilityState={{ checked: value, disabled }}\n disabled={disabled}\n testID={testID}\n value={value}\n onValueChange={onValueChange}\n />\n </View>\n </Pressable>\n );\n};\n\nexport default FormSwitch;\n","/**\n * Reusable, native-safe checkbox — a themed `Pressable` (works on RN-web AND native, where RN has\n * no built-in checkbox). A small rounded square that fills with the brand colour and shows a check\n * glyph when on, with a label and an optional hint. Mirrors `FormSwitch`'s prop shape so it is a\n * drop-in replacement for the boolean toggles v1 renders as checkboxes.\n */\nimport React from 'react';\n\nimport { Platform, StyleSheet, View, Text, Pressable, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { MIN_TOUCH_TARGET_PX } from '@dloizides/a11y';\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { useFieldIds } from '../Field/Field';\n\n/**\n * Web-only keydown prop react-native-web's `Pressable` forwards but RN's types omit. A\n * `role=\"checkbox\"` Pressable renders a `<div>` (not a native `<button>`), so — unlike a\n * button-role Pressable — it gets NO free Enter/Space activation. We add it explicitly so the\n * checkbox is keyboard-operable (WCAG 2.1.1). `preventDefault()` stops Space from scrolling.\n */\ninterface WebKeyboardProps {\n onKeyDown?: (event: { key?: string; preventDefault?: () => void }) => void;\n}\n\nconst ACTIVATION_KEYS = ['Enter', ' ', 'Spacebar'];\n\nconst HINT_FONT_SIZE = 12;\nconst BOX_SIZE = 20;\nconst BOX_RADIUS = 5;\nconst CHECK_FONT_SIZE = 14;\nconst DISABLED_OPACITY = 0.5;\n\nconst styles = StyleSheet.create({\n container: {\n flexDirection: 'row',\n alignItems: 'flex-start',\n gap: 10,\n marginBottom: 12,\n // The whole row is the Pressable, so the row IS the hit box: on RN-web `hitSlop` is inert and a\n // one-line label measured 36px tall (SHOWCASE-1). The 20px visual box keeps its size inside.\n minHeight: MIN_TOUCH_TARGET_PX,\n },\n /** With no hint the row is a single line, so centre it vertically inside the floor. */\n centered: {\n alignItems: 'center',\n },\n box: {\n width: BOX_SIZE,\n height: BOX_SIZE,\n borderRadius: BOX_RADIUS,\n borderWidth: 2,\n alignItems: 'center',\n justifyContent: 'center',\n // Nudge the box to sit on the label's first text line.\n marginTop: 1,\n },\n check: {\n fontSize: CHECK_FONT_SIZE,\n fontWeight: '700',\n lineHeight: CHECK_FONT_SIZE,\n },\n textColumn: {\n flex: 1,\n },\n label: {\n fontWeight: '600',\n },\n hint: {\n fontSize: HINT_FONT_SIZE,\n marginTop: 2,\n },\n});\n\nexport interface FormCheckboxProps {\n label: string;\n value: boolean;\n /** Primary change handler (mirrors `FormSwitch`). `onChange` is accepted as an alias. */\n onValueChange?: (value: boolean) => void;\n /** Alias for `onValueChange` so either name works as a drop-in. */\n onChange?: (value: boolean) => void;\n /** Optional secondary description shown under the label. `description` is accepted as an alias. */\n hint?: string;\n description?: string;\n disabled?: boolean;\n containerStyle?: ViewStyle;\n testID?: string;\n accessibilityLabel?: string;\n accessibilityHint?: string;\n}\n\nexport const FormCheckbox = ({\n label,\n value,\n onValueChange,\n onChange,\n hint,\n description,\n disabled = false,\n containerStyle,\n testID = 'form-checkbox',\n accessibilityLabel,\n accessibilityHint,\n}: FormCheckboxProps): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const brand = palette.primary['500'];\n const hintText = typeof hint === 'string' && hint !== '' ? hint : description;\n const hasHint = typeof hintText === 'string' && hintText !== '';\n const { hintId } = useFieldIds();\n\n const themeStyles = React.useMemo(() => {\n const boxOn: ViewStyle = { backgroundColor: brand, borderColor: brand };\n const boxOff: ViewStyle = { backgroundColor: 'transparent', borderColor: colors.border };\n const labelStyle: TextStyle = { color: colors.text };\n const hintStyle: TextStyle = { color: colors.textSecondary };\n return { boxOn, boxOff, label: labelStyle, hint: hintStyle };\n }, [brand, colors.border, colors.text, colors.textSecondary]);\n\n const toggle = (): void => {\n const next = !value;\n if (onValueChange) onValueChange(next);\n if (onChange) onChange(next);\n };\n\n const handleKeyDown = (event: { key?: string; preventDefault?: () => void }): void => {\n if (disabled) return;\n const key = event.key ?? '';\n if (!ACTIVATION_KEYS.includes(key)) return;\n if (typeof event.preventDefault === 'function') event.preventDefault();\n toggle();\n };\n\n const keyboardProps: WebKeyboardProps = Platform.OS === 'web' ? { onKeyDown: handleKeyDown } : {};\n\n return (\n <Pressable\n accessibilityHint={accessibilityHint ?? label}\n accessibilityLabel={accessibilityLabel ?? label}\n accessibilityRole=\"checkbox\"\n accessibilityState={{ checked: value, disabled }}\n // RN-web maps this to the ARIA `role=\"checkbox\"` + `aria-checked` a screen reader announces.\n aria-checked={value}\n aria-describedby={hasHint ? hintId : undefined}\n disabled={disabled}\n onPress={toggle}\n role=\"checkbox\"\n style={[\n styles.container,\n hasHint ? null : styles.centered,\n containerStyle,\n disabled ? { opacity: DISABLED_OPACITY } : null,\n ]}\n testID={testID}\n {...keyboardProps}\n >\n <View style={[styles.box, value ? themeStyles.boxOn : themeStyles.boxOff]}>\n {value ? (\n <Text style={[styles.check, { color: colors.surface }]} accessibilityElementsHidden>\n ✓\n </Text>\n ) : null}\n </View>\n <View style={styles.textColumn}>\n <Text style={[styles.label, themeStyles.label]}>{label}</Text>\n {hasHint ? <Text nativeID={hintId} style={[styles.hint, themeStyles.hint]}>{hintText}</Text> : null}\n </View>\n </Pressable>\n );\n};\n\nexport default FormCheckbox;\n","/**\n * `SelectControl` — a single-select enum/status dropdown. A bordered trigger shows the selected\n * option's label (or the placeholder when unset) plus a chevron; pressing it opens the shared\n * {@link AnchoredMenu}. Selecting fires `onChange` and closes.\n *\n * Promoted out of `@dloizides/ui-tables`' private `Filters/fields/SelectField`, where six portals\n * could see it working and none could import it — which is why the fleet grew SIX independent\n * select implementations.\n *\n * The control is LABEL-FREE by design: wrap it in a `Field` (with `labelVariant=\"control\"` on a\n * dense surface) to get the label, hint and error slots. That keeps one label implementation for\n * every control instead of one per control.\n *\n * i18n: this package never calls `t`. `accessibilityLabel`, `placeholder`, `accessibilityHint`\n * and `optionHint` are PRE-LOCALIZED strings supplied by the caller — the only shape that can\n * serve both aml-v2's positional `{0}` `@dloizides/i18n` and the other six portals' i18next\n * `{{p1}}` from one component.\n */\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { Pressable, Text, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { AnchoredMenu } from '../AnchoredMenu/AnchoredMenu';\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\n\nconst CHEVRON_DOWN = '▾';\nconst CHEVRON_UP = '▴';\n\nexport interface SelectControlProps {\n options: readonly ControlOption[];\n /** The selected option's `value`. `''` (or any unmatched value) renders the placeholder. */\n value: string;\n onChange: (value: string) => void;\n /** PRE-LOCALIZED text shown when the value matches no option. */\n placeholder?: string;\n /**\n * PRE-LOCALIZED accessible NAME of the trigger. It REPLACES the trigger's visible text for a\n * screen reader, so it must carry the SELECTION too — \"Status: Active\", not just \"Status\",\n * which announces the control but silently hides its value.\n */\n accessibilityLabel: string;\n accessibilityHint?: string;\n /**\n * `id` of the `Field` label naming this control — take it from the render-child context's\n * `labelId`. The trigger is a `<div role=\"button\">`, which `<label for>` cannot address (that\n * only works for native form elements), so the association runs the other way: the trigger\n * points AT the label.\n *\n * `accessibilityLabel` still wins for the accessible NAME, deliberately — it is the only one of\n * the two that carries the current selection (\"Status: Active\"). This adds the structural link\n * without changing a single announcement.\n */\n labelledById?: string;\n /** PRE-LOCALIZED accessibility hint applied to every option in the menu. */\n optionHint?: string;\n /** Merged LAST onto the anchor wrapper — the consumer always wins over the shared style. */\n style?: StyleProp<ViewStyle>;\n /** Trigger is `${testID}-trigger`, menu `${testID}-menu`, options `${testID}-option-${value}`. */\n testID: string;\n}\n\nexport function SelectControl({\n options,\n value,\n onChange,\n placeholder = '',\n accessibilityLabel,\n accessibilityHint,\n labelledById,\n optionHint = '',\n style,\n testID,\n}: SelectControlProps): React.ReactElement {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const anchorRef = useRef<View>(null);\n const [isOpen, setIsOpen] = useState(false);\n\n const selectedLabel = useMemo(() => {\n const found = options.find((o) => o.value === value);\n return found?.label ?? placeholder;\n }, [options, placeholder, value]);\n\n const close = useCallback(() => { setIsOpen(false); }, []);\n const toggle = useCallback(() => { setIsOpen((prev) => !prev); }, []);\n const select = useCallback(\n (next: string) => {\n onChange(next);\n setIsOpen(false);\n },\n [onChange],\n );\n\n return (\n <View ref={anchorRef} style={[s.anchor, style]}>\n <Pressable\n accessibilityRole=\"button\"\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={accessibilityHint}\n accessibilityState={{ expanded: isOpen }}\n aria-expanded={isOpen}\n aria-labelledby={labelledById}\n onPress={toggle}\n style={[s.selectTrigger, { borderColor: colors.border, backgroundColor: colors.surface }]}\n testID={`${testID}-trigger`}\n >\n <Text numberOfLines={1} style={[s.selectTriggerText, { color: value === '' ? colors.textSecondary : colors.text }]}>\n {selectedLabel}\n </Text>\n <Text aria-hidden style={[s.chevron, { color: colors.textSecondary }]}>{isOpen ? CHEVRON_UP : CHEVRON_DOWN}</Text>\n </Pressable>\n {isOpen ? (\n <AnchoredMenu\n options={options}\n selectedValue={value}\n onSelect={select}\n onDismiss={close}\n colors={{ text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary['500'] }}\n optionHint={optionHint}\n testID={testID}\n anchorRef={anchorRef}\n />\n ) : null}\n </View>\n );\n}\n\nexport default SelectControl;\n","/**\n * `suggestOptions` — the ranked substring matcher behind `TypeaheadControl`, generalized from\n * aml-v2's `suggestCountries` and promoted verbatim out of `@dloizides/ui-tables`' private\n * `Filters/utils/suggest.ts`.\n *\n * Ranks: value exact (0) > value prefix (1) > label prefix (2) > label contains (3); ties broken\n * by `label.localeCompare`. Empty/short queries return `[]` — nothing surfaces until `minChars`\n * is typed, mirroring a native `<datalist>`.\n */\nimport type { ControlOption } from './controlTypes';\n\nconst RANK_VALUE_EXACT = 0;\nconst RANK_VALUE_PREFIX = 1;\nconst RANK_LABEL_PREFIX = 2;\nconst RANK_LABEL_CONTAINS = 3;\nconst NO_MATCH = -1;\n\nfunction rankOf(option: ControlOption, needle: string): number {\n const value = option.value.toLowerCase();\n const label = option.label.toLowerCase();\n if (value === needle) return RANK_VALUE_EXACT;\n if (value.startsWith(needle)) return RANK_VALUE_PREFIX;\n if (label.startsWith(needle)) return RANK_LABEL_PREFIX;\n if (label.includes(needle)) return RANK_LABEL_CONTAINS;\n return NO_MATCH;\n}\n\n/**\n * Rank + cap the options matching `query`. Returns `[]` until `query` (trimmed) is at least\n * `minChars` long, then the best `limit` matches, ranked as documented above.\n */\nexport function suggestOptions(\n options: readonly ControlOption[],\n query: string,\n minChars: number,\n limit: number,\n): readonly ControlOption[] {\n const needle = query.trim().toLowerCase();\n if (needle.length < minChars) return [];\n\n const scored: Array<{ option: ControlOption; rank: number }> = [];\n for (const option of options) {\n const rank = rankOf(option, needle);\n if (rank !== NO_MATCH) scored.push({ option, rank });\n }\n scored.sort((a, b) => (a.rank !== b.rank ? a.rank - b.rank : a.option.label.localeCompare(b.option.label)));\n return scored.slice(0, limit).map((entry) => entry.option);\n}\n\n/** True when `text` is non-empty yet matches no option's value or label exactly (case-insensitive). */\nexport function isUnmatched(options: readonly ControlOption[], text: string): boolean {\n const needle = text.trim().toLowerCase();\n if (needle === '') return false;\n return !options.some((o) => o.value.toLowerCase() === needle || o.label.toLowerCase() === needle);\n}\n","/**\n * `TypeaheadControl` — a search-as-you-type combobox (aml-v2's CountryPicker, generalized). A\n * text input plus a floating {@link AnchoredMenu} of ranked suggestions ({@link suggestOptions});\n * picking one fills the canonical label.\n *\n * Free typing is PRESERVED: the value is the raw text, so a caller can accept \"CY\", \"cyprus\" or\n * \"Cyprus (CY)\" and normalise it themselves at query time, exactly as aml does. An optional\n * PRE-LOCALIZED `error` shows a persistent banner and tints the border.\n *\n * Promoted out of `@dloizides/ui-tables`' private `Filters/fields/TypeaheadField`.\n *\n * Label-free by design — wrap in a `Field` for the label/hint slots.\n */\nimport React, { useCallback, useMemo, useRef, useState } from 'react';\n\nimport { TextInput, Text, View, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { AnchoredMenu } from '../AnchoredMenu/AnchoredMenu';\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\nimport { suggestOptions } from '../controls/suggestOptions';\n\n/** Delay before blur closes the menu, so a tap on an option registers first (aml CLOSE_DELAY_MS). */\nconst CLOSE_DELAY_MS = 140;\n\n/** Default min characters before suggestions surface. */\nexport const DEFAULT_TYPEAHEAD_MIN_CHARS = 1;\n/** Default cap on rendered suggestions. */\nexport const DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS = 8;\n\nexport interface TypeaheadControlProps {\n options: readonly ControlOption[];\n /** The raw text in the box — NOT necessarily an option value. */\n value: string;\n onChange: (value: string) => void;\n /** Called on Enter/submit (after the menu closes). Omit if the surface has nothing to commit. */\n onSubmit?: () => void;\n placeholder?: string;\n /** PRE-LOCALIZED accessible name of the input. */\n accessibilityLabel: string;\n accessibilityHint?: string;\n /** PRE-LOCALIZED accessibility hint applied to every suggestion. */\n optionHint?: string;\n /** PRE-LOCALIZED inline error (e.g. \"Unrecognised country\"). Shows a persistent banner. */\n error?: string;\n /** Minimum characters before suggestions surface. Default 1. */\n minChars?: number;\n /** Cap on rendered suggestions. Default 8. */\n maxSuggestions?: number;\n /** Merged LAST onto the anchor wrapper. */\n style?: StyleProp<ViewStyle>;\n /** Input is `${testID}-input`, menu `${testID}-menu`, error `${testID}-error`. */\n testID: string;\n}\n\nexport function TypeaheadControl({\n options,\n value,\n onChange,\n onSubmit,\n placeholder,\n accessibilityLabel,\n accessibilityHint,\n optionHint = '',\n error,\n minChars = DEFAULT_TYPEAHEAD_MIN_CHARS,\n maxSuggestions = DEFAULT_TYPEAHEAD_MAX_SUGGESTIONS,\n style,\n testID,\n}: TypeaheadControlProps): React.ReactElement {\n const { theme } = useUi();\n const { colors, palette, semantic } = theme;\n const anchorRef = useRef<View>(null);\n const [isOpen, setIsOpen] = useState(false);\n\n // Hide the menu once the field already holds an exact pick (nothing left to disambiguate).\n const exactPick = useMemo(() => options.some((o) => o.label === value), [options, value]);\n const suggestions = useMemo(\n () => (exactPick ? [] : suggestOptions(options, value, minChars, maxSuggestions)),\n [exactPick, options, value, minChars, maxSuggestions],\n );\n const showMenu = isOpen && suggestions.length > 0;\n\n const handleChange = useCallback(\n (next: string) => {\n onChange(next);\n setIsOpen(true);\n },\n [onChange],\n );\n const pick = useCallback(\n (optionValue: string) => {\n const opt = options.find((o) => o.value === optionValue);\n onChange(opt?.label ?? optionValue);\n setIsOpen(false);\n },\n [options, onChange],\n );\n const handleBlur = useCallback(() => {\n setTimeout(() => setIsOpen(false), CLOSE_DELAY_MS);\n }, []);\n const handleSubmit = useCallback(() => {\n setIsOpen(false);\n onSubmit?.();\n }, [onSubmit]);\n\n const hasError = error !== undefined && error !== '';\n\n return (\n <View ref={anchorRef} style={[s.anchor, style]}>\n <TextInput\n accessibilityLabel={accessibilityLabel}\n accessibilityHint={accessibilityHint}\n autoCapitalize=\"none\"\n autoCorrect={false}\n placeholder={placeholder}\n placeholderTextColor={colors.textSecondary}\n spellCheck={false}\n value={value}\n onChangeText={handleChange}\n onFocus={() => setIsOpen(true)}\n onBlur={handleBlur}\n onSubmitEditing={handleSubmit}\n style={[s.input, { borderColor: hasError ? semantic.error['500'] : colors.border, backgroundColor: colors.surface, color: colors.text }]}\n testID={`${testID}-input`}\n />\n {showMenu ? (\n <AnchoredMenu\n options={suggestions}\n selectedValue={value}\n onSelect={pick}\n onDismiss={() => setIsOpen(false)}\n colors={{ text: colors.text, border: colors.border, surface: colors.surface, brand: palette.primary['500'] }}\n optionHint={optionHint}\n testID={testID}\n anchorRef={anchorRef}\n // Portal the suggestions to document.body on web: a typeahead sits in a filter row above\n // other content (fields, guides, a results table), and the in-tree popover was painted\n // under / clipped by it (\"hidden below\"). The portal escapes that stacking + clipping.\n usePortal\n />\n ) : null}\n {hasError ? (\n <Text role=\"alert\" style={[s.error, { color: semantic.error['500'] }]} testID={`${testID}-error`}>\n {error}\n </Text>\n ) : null}\n </View>\n );\n}\n\nexport default TypeaheadControl;\n","/**\n * `DateRangeControl` — an inclusive from/to pair (aml cases `from`/`to`, kefi audit `from`/`to`).\n * Each side is a `YYYY-MM-DD` text input; on web the browser's native date UI is offered via\n * `type=\"date\"` (a react-native-web `TextInput` passes unknown props to the DOM input). Editing\n * either side patches ONLY that side, so the other survives the edit.\n *\n * Promoted out of `@dloizides/ui-tables`' private `Filters/fields/DateRangeField`, which is why\n * the fleet grew FIVE independent date fields.\n *\n * Label-free by design — the From/To sub-labels name the two HALVES; wrap in a `Field` for the\n * range's own label.\n */\nimport React from 'react';\n\nimport { TextInput, View, Text, type StyleProp, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { DateRangeValue } from '../controls/controlTypes';\n\nconst WEB_DATE_PROPS = typeof document !== 'undefined' ? { type: 'date' } : {};\n\nexport interface DateRangeControlProps {\n value: DateRangeValue;\n onChange: (value: DateRangeValue) => void;\n /** Called on Enter/submit in either side. */\n onSubmit?: () => void;\n /** PRE-LOCALIZED sub-label for the FROM input (e.g. \"From\"). Also its accessible name. */\n fromLabel: string;\n /** PRE-LOCALIZED sub-label for the TO input (e.g. \"To\"). Also its accessible name. */\n toLabel: string;\n fromPlaceholder?: string;\n toPlaceholder?: string;\n /** PRE-LOCALIZED hint applied to BOTH inputs. */\n accessibilityHint?: string;\n /** Merged LAST onto the row wrapper. */\n style?: StyleProp<ViewStyle>;\n /** Row is `${testID}-range`, inputs `${testID}-from` / `${testID}-to`. */\n testID: string;\n}\n\ninterface DateInputProps {\n side: 'from' | 'to';\n label: string;\n placeholder?: string;\n value: string;\n color: string;\n border: string;\n surface: string;\n muted: string;\n testID: string;\n hint?: string;\n onChangeText: (v: string) => void;\n onSubmit?: () => void;\n}\n\nfunction DateInput(p: DateInputProps): React.ReactElement {\n return (\n <View style={s.dateCol}>\n <Text style={[s.subLabel, { color: p.muted }]}>{p.label}</Text>\n <TextInput\n accessibilityLabel={p.label}\n accessibilityHint={p.hint}\n placeholder={p.placeholder}\n placeholderTextColor={p.muted}\n value={p.value}\n onChangeText={p.onChangeText}\n onSubmitEditing={p.onSubmit}\n style={[s.input, { borderColor: p.border, backgroundColor: p.surface, color: p.color }]}\n testID={`${p.testID}-${p.side}`}\n {...WEB_DATE_PROPS}\n />\n </View>\n );\n}\n\nexport function DateRangeControl({\n value,\n onChange,\n onSubmit,\n fromLabel,\n toLabel,\n fromPlaceholder,\n toPlaceholder,\n accessibilityHint,\n style,\n testID,\n}: DateRangeControlProps): React.ReactElement {\n const { theme } = useUi();\n const { colors } = theme;\n\n return (\n <View style={[s.dateRow, style]} testID={`${testID}-range`}>\n <DateInput\n side=\"from\"\n label={fromLabel}\n placeholder={fromPlaceholder}\n value={value.from}\n color={colors.text}\n border={colors.border}\n surface={colors.surface}\n muted={colors.textSecondary}\n hint={accessibilityHint}\n testID={testID}\n onChangeText={(from) => onChange({ from, to: value.to })}\n onSubmit={onSubmit}\n />\n <DateInput\n side=\"to\"\n label={toLabel}\n placeholder={toPlaceholder}\n value={value.to}\n color={colors.text}\n border={colors.border}\n surface={colors.surface}\n muted={colors.textSecondary}\n hint={accessibilityHint}\n testID={testID}\n onChangeText={(to) => onChange({ from: value.from, to })}\n onSubmit={onSubmit}\n />\n </View>\n );\n}\n\nexport default DateRangeControl;\n","/**\n * Group selection — the pure tri-state logic behind a \"select all\" / \"select this category\"\n * control, kept out of any component so it is testable as LOGIC rather than through the DOM.\n *\n * ## Why it lives here and not in @dloizides/ui-tables\n *\n * `ui-tables` already had this arithmetic inside `DataTable/selection.ts`, but deliberately\n * unexported: its tri-state is a `const enum`, which in a published `.d.ts` is an ambient const\n * enum that every `isolatedModules` consumer rejects. It is also page-scoped and wired to the\n * table's select-all banner. So the second consumer (a 12-tile console picker with no table in\n * sight, and no reason to pull a table package into its bundle budget) could not reach it.\n *\n * This module is the extraction: domain-neutral (keys in, keys out — nothing here knows what a\n * key *is*), component-free, and crossing the package boundary as a plain interface rather than\n * an enum. `ui-tables` can adopt it and delete its private copy.\n */\n\n/** Nothing selected / an empty group — the empty count. */\nconst NONE = 0;\n\n/**\n * A group's tri-state, as two booleans rather than an enum.\n *\n * `all` and `some` are mutually exclusive: a fully selected group is `{ all: true, some: false }`,\n * so a caller can branch on `all` then `some` without re-deriving \"partial\" itself. Both false\n * means nothing in the group is selected — which is also what an EMPTY group reports, because an\n * empty group is neither fully nor partially selected.\n */\nexport interface GroupSelection {\n /** Every key in the group is selected (never true for an empty group). */\n readonly all: boolean;\n /** At least one, but not every, key in the group is selected — the mixed/indeterminate state. */\n readonly some: boolean;\n}\n\n/** How many of the group's keys are currently selected. */\nfunction countSelected<T>(selected: readonly T[], groupKeys: readonly T[]): number {\n return groupKeys.filter((key) => selected.includes(key)).length;\n}\n\n/**\n * Resolve a group's tri-state from the selection ∩ the group.\n *\n * Scoped to the GROUP, not to the whole selection: selected keys OUTSIDE the group must never\n * make this group look partially selected.\n */\nexport function resolveGroupSelection<T>(selected: readonly T[], groupKeys: readonly T[]): GroupSelection {\n const count = countSelected(selected, groupKeys);\n if (count === NONE) return { all: false, some: false };\n return count === groupKeys.length ? { all: true, some: false } : { all: false, some: true };\n}\n\n/**\n * The value an `aria-checked` / `accessibilityState` consumer needs for a tri-state control.\n *\n * A partially selected group is `'mixed'`, which is what makes a screen reader announce the\n * control honestly instead of claiming the whole category is on.\n */\nexport function groupAriaChecked(state: GroupSelection): boolean | 'mixed' {\n if (state.all) return true;\n return state.some ? 'mixed' : false;\n}\n\n/**\n * Toggle a whole group, returning the NEXT selection array. Pure — never mutates the input.\n *\n * All-on → off. Partial or off → on: the conventional behaviour, and the one a mixed checkbox\n * looks like it will do. Keys OUTSIDE the group always survive untouched, so a category control\n * can never silently clear a selection it does not own.\n *\n * `order`, when given, is the canonical key order the result is sorted into (catalogue order, say)\n * so the selection does not carry click order around. Without it, newly added keys are appended.\n */\nexport function toggleGroupSelection<T>(\n selected: readonly T[],\n groupKeys: readonly T[],\n order?: readonly T[],\n): T[] {\n const { all } = resolveGroupSelection(selected, groupKeys);\n if (all) return selected.filter((key) => !groupKeys.includes(key));\n const merged = [...selected];\n groupKeys.forEach((key) => {\n if (!merged.includes(key)) merged.push(key);\n });\n return order === undefined ? merged : order.filter((key) => merged.includes(key));\n}\n"]}