@dloizides/ui-forms 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +280 -280
- package/dist/index.js +14 -13
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +14 -13
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../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/useThemedInput/useThemedInput.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx","../src/controls/controlStyles.ts","../src/AnchoredMenu/AnchoredMenu.tsx","../src/SelectControl/SelectControl.tsx","../src/controls/suggestOptions.ts","../src/TypeaheadControl/TypeaheadControl.tsx","../src/DateRangeControl/DateRangeControl.tsx"],"names":["jsxs","Text","jsx","StyleSheet","React","useUi","View","styles","Button","Platform","useState","useCallback","useMemo","IS_WEB","ThemedTextInput","TextInput","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","Pressable","TouchableOpacity","DESCRIPTION_FONT_SIZE","Switch","HINT_FONT_SIZE","useEffect","useRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\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 */\nimport React from 'react';\n\nimport { Text, type StyleProp, type TextStyle } from 'react-native';\n\nimport type { FieldMarker } from './fieldMarkers';\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 /** 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 style,\n requiredMarkStyle,\n optionalMarkStyle,\n}: FieldLabelProps): React.ReactElement {\n return (\n <Text style={style}>\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 { 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\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 id pair so the hint and error lines can be linked to the control via\n * `aria-describedby`. One counter bump per field keeps the two ids of a field in lockstep.\n */\nexport function useFieldIds(): { hintId: string; errorId: string } {\n const [ids] = React.useState(() => {\n fieldSeq += 1;\n const seq = String(fieldSeq);\n return { hintId: `field-hint-${seq}`, errorId: `field-error-${seq}` };\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 } = 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 const control = typeof children === 'function' ? children({ describedById, hasError }) : children;\n\n return (\n <View style={[spacingStyles.container, containerStyle]} testID={testID}>\n {hasLabel ? (\n <FieldLabel\n label={labelText}\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","/**\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\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 /** A readable mid-grey placeholder colour from the theme. */\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: colors.textSecondary,\n isFocused,\n isHovered,\n focusBind,\n hoverBind,\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 * 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 { Platform, TextInput, type TextInputProps } from 'react-native';\n\nimport { useThemedInput } from '../useThemedInput/useThemedInput';\n\nconst IS_WEB = Platform.OS === 'web';\n\n/**\n * Web-only ARIA attributes react-native-web forwards to the underlying `<input>` but that RN's\n * `TextInputProps` type does not enumerate. Cast through the TextInput props at the call site\n * (never `any`) so error/label semantics reach a screen reader without a type escape hatch.\n */\ninterface WebInputA11y {\n 'aria-invalid'?: boolean;\n 'aria-describedby'?: string;\n 'aria-required'?: boolean;\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\nexport const ThemedTextInput = React.forwardRef<TextInput, ThemedTextInputProps>(function ThemedTextInput(\n { hasError = false, describedById, requiredField = false, onFocus, onBlur, style, placeholderTextColor, ...rest },\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: WebInputA11y = IS_WEB\n ? {\n 'aria-invalid': hasError ? true : undefined,\n 'aria-describedby': describedById,\n 'aria-required': requiredField ? true : undefined,\n }\n : {};\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={[style, themedStyle]}\n />\n );\n});\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 { StyleSheet, type TextInputProps, type ViewStyle } from 'react-native';\n\nimport { Field } from '../Field/Field';\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\nconst INPUT_PADDING_V = 10;\nconst INPUT_PADDING_H = 12;\nconst INPUT_BORDER_RADIUS = 8;\nconst INPUT_BORDER_WIDTH = 1;\n\nconst styles = StyleSheet.create({\n input: {\n paddingVertical: INPUT_PADDING_V,\n paddingHorizontal: INPUT_PADDING_H,\n borderRadius: INPUT_BORDER_RADIUS,\n borderWidth: INPUT_BORDER_WIDTH,\n },\n});\n\nexport interface FormFieldProps extends Omit<TextInputProps, 'style'> {\n label: string;\n required?: boolean;\n error?: string;\n containerStyle?: ViewStyle;\n}\n\nexport const FormField = ({\n label,\n required = false,\n error,\n containerStyle,\n ...textInputProps\n}: FormFieldProps): React.ReactElement => (\n <Field containerStyle={containerStyle} error={error} label={label} required={required}>\n {({ describedById, hasError }) => (\n <ThemedTextInput\n accessibilityHint={`Enter ${label}`}\n accessibilityLabel={label}\n describedById={describedById}\n hasError={hasError}\n requiredField={required}\n style={styles.input}\n testID=\"form-field-input\"\n {...textInputProps}\n />\n )}\n </Field>\n);\n\nexport default FormField;\n","/**\r\n * Chip/pill selector for selecting one or multiple options.\r\n *\r\n * Two visual variants (both fully theme-driven):\r\n * - `solid` (default) — the original filled-pill look: selected = solid primary fill with\r\n * white ink. Unchanged, so existing consumers (erevna / katalogos / kefi) render identically.\r\n * - `outline` — the AML v1 console look: an outlined pill on a muted fill; selected = a subtle\r\n * tinted-outline (primary border + primary ink + a low-alpha primary wash), NOT a solid fill.\r\n * Hover (web) lifts the border/ink to the primary colour.\r\n *\r\n * The label row, the error line and the container spacing come from the shared `Field` wrapper —\r\n * NOT from a local `<Text>`. Its own label used to drift from `Field` on three of four axes\r\n * (`marginBottom: 8` vs 4, no `fontSize` at all so ~14 vs 13, `colors.text` vs `textSecondary`),\r\n * so a `ChipSelector` next to a `FormField` in a row/grid started a different distance down the\r\n * column and read as a different weight of text. Now there is exactly one label implementation.\r\n */\r\nimport React from 'react';\r\n\r\nimport {\r\n Platform,\r\n StyleSheet,\r\n View,\r\n Text,\r\n Pressable,\r\n TouchableOpacity,\r\n type StyleProp,\r\n type ViewProps,\r\n type ViewStyle,\r\n} from 'react-native';\r\n\r\nimport { useUi } from '@dloizides/ui-feedback';\r\n\r\nimport { Field } from '../Field/Field';\r\nimport type { FieldSpacing } from '../Field/fieldSpacing';\r\n\r\nconst TRANSPARENT_COLOR = 'transparent';\r\nconst WHITE_COLOR = '#fff';\r\nconst SOLID_RADIUS = 20;\r\nconst OUTLINE_RADIUS = 999;\r\nconst OUTLINE_PAD_H = 12;\r\nconst OUTLINE_PAD_V = 5;\r\nconst OUTLINE_FONT_SIZE = 13;\r\nconst OUTLINE_TINT_ALPHA = 0.1;\r\nconst HEX_SHORT_LENGTH = 3;\r\nconst HEX_RADIX = 16;\r\nconst RGB_R_START = 0;\r\nconst RGB_R_END = 2;\r\nconst RGB_G_END = 4;\r\nconst RGB_B_END = 6;\r\n/**\r\n * Chips are visually compact (≈24–26px tall). `hitSlop` expands the pressable's TOUCH area\r\n * toward the WCAG ≥44px target WITHOUT changing the rendered pill size, so existing layouts are\r\n * byte-identical while taps/clicks get an easier target.\r\n */\r\nconst CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 } as const;\r\n/** Gap between adjacent chips, horizontally and between wrapped rows. */\r\nconst CHIP_GUTTER = 8;\r\n\r\n/** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */\r\nexport type ChipVariant = 'solid' | 'outline';\r\n\r\n/**\r\n * Default chip testID stem. NOT derived from the `testID` prop, because aml-v2's unit +\r\n * Playwright specs and erevna/katalogos's `Accessibility.test.tsx` already select on\r\n * `chip-selector-chip-<value>`. `chipTestIDPrefix` is the opt-in override for consumers\r\n * (kefi) that need their own stem; the default is frozen.\r\n */\r\nconst DEFAULT_CHIP_TESTID_PREFIX = 'chip-selector-chip';\r\n\r\n/** Palette scale carrying the ink for content sitting ON the brand colour. */\r\nconst ON_BRAND_SCALE = 'onBrand';\r\n/** The one step every theme scale is guaranteed to define. */\r\nconst MAIN_STEP = '500';\r\n\r\n/**\r\n * Read the on-brand ink out of a theme palette.\r\n *\r\n * Deliberately typed as OPTIONAL rather than read through `palette.onBrand`. Two reasons:\r\n * this package's declared peer floor is `ui-feedback >= 1.1.0`, whose palette type has no\r\n * index signature at all; and even on current versions the index signature types every\r\n * scale as present, which is a lie — only `primary` is guaranteed, and most apps in the\r\n * fleet publish no `onBrand` scale today. Modelling it as absent-able is what makes the\r\n * `WHITE_COLOR` fallback honest instead of dead code.\r\n */\r\nfunction onBrandInk(palette: object): string {\r\n const scales = palette as Record<string, Record<string, string> | undefined>;\r\n return scales[ON_BRAND_SCALE]?.[MAIN_STEP] ?? WHITE_COLOR;\r\n}\r\n\r\n/** Composite a hex colour over the background at a given alpha (theme-driven tint). */\r\nfunction withAlpha(hex: string, alpha: number): string {\r\n const normalized = hex.replace('#', '');\r\n const isShort = normalized.length === HEX_SHORT_LENGTH;\r\n const full = isShort ? normalized.split('').map((c) => c + c).join('') : normalized;\r\n const r = parseInt(full.slice(RGB_R_START, RGB_R_END), HEX_RADIX);\r\n const g = parseInt(full.slice(RGB_R_END, RGB_G_END), HEX_RADIX);\r\n const b = parseInt(full.slice(RGB_G_END, RGB_B_END), HEX_RADIX);\r\n const isValid = !Number.isNaN(r) && !Number.isNaN(g) && !Number.isNaN(b);\r\n return isValid ? `rgba(${r}, ${g}, ${b}, ${alpha})` : hex;\r\n}\r\n\r\nconst styles = StyleSheet.create({\r\n chipContainer: {\r\n flexDirection: 'row',\r\n flexWrap: 'wrap',\r\n // `gap`, NOT per-chip margins plus a compensating negative container margin.\r\n //\r\n // The old form was `chipWrapper { marginRight: 8, marginBottom: 8 }` with\r\n // `chipContainer { marginBottom: -8 }`. Its comment blamed `Field`'s 16px container margin —\r\n // that was WRONG, and worth recording: F3 was briefed on the belief that the -8 compensated for\r\n // `Field` and had to move in lockstep with it. It did not. -8 cancelled the CHIP's own gutter\r\n // hanging off the last row, identically whether `Field` contributed 16, 0, or anything else.\r\n //\r\n // The pair is still the wrong tool: it holds only while the two constants agree, and it leaves\r\n // a real negative margin any measuring parent inherits. `gap` produces the byte-identical box\r\n // and is correct under BOTH of `Field`'s spacing models, not just the one it was tuned against.\r\n gap: CHIP_GUTTER,\r\n },\r\n chip: {\r\n paddingHorizontal: 12,\r\n paddingVertical: 6,\r\n borderRadius: SOLID_RADIUS,\r\n backgroundColor: TRANSPARENT_COLOR,\r\n borderWidth: 1,\r\n },\r\n chipOutline: {\r\n paddingHorizontal: OUTLINE_PAD_H,\r\n paddingVertical: OUTLINE_PAD_V,\r\n borderRadius: OUTLINE_RADIUS,\r\n borderWidth: 1,\r\n },\r\n chipText: {},\r\n chipTextOutline: { fontSize: OUTLINE_FONT_SIZE },\r\n});\r\n\r\n/** Resolved, theme-derived colours for the two variants. */\r\ninterface ChipColors {\r\n border: string;\r\n /** Strong ink for the solid variant's rest text (unchanged from the original). */\r\n textStrong: string;\r\n /** Muted ink for the outline variant's rest text (v1 ink-soft). */\r\n textMuted: string;\r\n primary: string;\r\n /**\r\n * Ink on a primary-filled chip. Reads the theme's `onBrand` scale when the app publishes one,\r\n * falling back to white. It used to be a hardcoded `#fff`, which meant a tenant whose primary\r\n * is light got white-on-light and failed contrast — the token slot is the fix, and the\r\n * fallback keeps every app that has no `onBrand` scale rendering exactly as before.\r\n */\r\n onPrimary: string;\r\n muted: string;\r\n tint: string;\r\n}\r\n\r\nexport interface ChipOption<T> {\r\n value: T;\r\n label: string;\r\n}\r\n\r\nexport interface ChipSelectorProps<T> {\r\n /** Optional — with no label, no label row is rendered (no phantom gap above the chips). */\r\n label?: string;\r\n options: Array<ChipOption<T>>;\r\n value: T | T[];\r\n onChange: (value: T) => void;\r\n multiple?: boolean;\r\n disabled?: boolean;\r\n /** Visual variant. `solid` (default) = filled selected pill; `outline` = v1 tinted-outline. */\r\n variant?: ChipVariant;\r\n /**\r\n * `StyleProp` (not a bare `ViewStyle`) so it composes the same way `Field`'s does — a caller can\r\n * pass an array instead of restating a complete style per variant.\r\n */\r\n containerStyle?: StyleProp<ViewStyle>;\r\n /**\r\n * Forwarded verbatim to the underlying `Field`. `ChipSelector` deliberately holds NO spacing\r\n * opinion of its own: it delegates, so the two cannot drift into disagreeing about how much room\r\n * a chip block occupies. The guard for that is `chipSelectorFieldLockstep` in the tests.\r\n */\r\n spacing?: FieldSpacing;\r\n /** Marks the selection mandatory — renders `Field`'s decorative `*` next to the label. */\r\n required?: boolean;\r\n /** Validation message under the chips, wired to the chip group via `aria-describedby`. */\r\n error?: string;\r\n testID?: string;\r\n /**\r\n * Stem for each chip's testID — a chip becomes `${chipTestIDPrefix}-${value}`. Defaults to\r\n * `chip-selector-chip`, which existing specs select on; supply your own when a screen has\r\n * several chip groups that must be addressed independently.\r\n */\r\n chipTestIDPrefix?: string;\r\n /**\r\n * Accessibility hint applied to every chip in the group. Supply a LOCALIZED string — the\r\n * built-in default (`Selects <label>`) is English-only and exists solely so pre-existing\r\n * consumers keep their current announcement.\r\n */\r\n optionAccessibilityHint?: string;\r\n}\r\n\r\n/**\r\n * Web-only ARIA attributes react-native-web forwards to the underlying element but that RN's\r\n * `ViewProps` type does not enumerate — same escape-hatch-free pattern `ThemedTextInput` uses.\r\n */\r\ninterface WebGroupA11y {\r\n 'aria-invalid'?: boolean;\r\n 'aria-describedby'?: string;\r\n}\r\n\r\ninterface ChipProps<T> {\r\n option: ChipOption<T>;\r\n selected: boolean;\r\n disabled: boolean;\r\n colors: ChipColors;\r\n /** Resolved `${prefix}-${value}` for this chip. */\r\n testID: string;\r\n /** Resolved hint for this chip — localized by the consumer, or the built-in English default. */\r\n accessibilityHint: string;\r\n /**\r\n * Web-only toggle state for a MULTI-select chip; `undefined` for single-select.\r\n *\r\n * Why `aria-pressed` on a button and not `role=\"checkbox\"`: react-native-web renders\r\n * `accessibilityRole=\"button\"` as a real `<button>`, but ANY other role as a plain `<div>`.\r\n * Switching a multi chip to `checkbox` therefore trades native keyboard activation for a\r\n * div that only looks right — the same RN-web trap that produced the held-Enter defect\r\n * elsewhere in this fleet. A toggle button (`role=button` + `aria-pressed`) conveys the\r\n * on/off state to assistive tech AND keeps Space/Enter working for free.\r\n *\r\n * It is passed as a literal web prop because RNW 0.21 emits NOTHING from\r\n * `accessibilityState` on web — verified, not assumed — so the `accessibilityState` below\r\n * is carrying native only.\r\n */\r\n ariaPressed?: boolean;\r\n}\r\n\r\n/**\r\n * The a11y + testID triple a chip needs, resolved once for both variants.\r\n *\r\n * Exported for direct unit testing. It has to be tested as a pure function rather than\r\n * through the DOM because react-native-web DROPS `accessibilityHint` entirely — it reaches\r\n * native, but no web attribute carries it, so no rendering assertion can tell a correctly\r\n * threaded hint from one that was never passed. Testing the resolver is the only honest way\r\n * to pin the behaviour.\r\n */\r\nexport function chipIdentity<T>(\r\n option: ChipOption<T>,\r\n selected: boolean,\r\n config: { prefix: string; hint?: string; multiple: boolean },\r\n): Pick<ChipProps<T>, 'testID' | 'accessibilityHint' | 'ariaPressed'> {\r\n return {\r\n testID: `${config.prefix}-${String(option.value)}`,\r\n // The English default is retained verbatim: erevna/katalogos assert the exact string\r\n // `Selects Red`. Consumers that localize pass `optionAccessibilityHint`.\r\n accessibilityHint: config.hint ?? `Selects ${option.label}`,\r\n ariaPressed: config.multiple ? selected : undefined,\r\n };\r\n}\r\n\r\n/** A single outline chip — owns its own hover state (web) for the border/ink lift. */\r\nfunction OutlineChip<T extends string | number>({\r\n option,\r\n selected,\r\n disabled,\r\n colors,\r\n testID,\r\n accessibilityHint,\r\n ariaPressed,\r\n onPress,\r\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\r\n const [hovered, setHovered] = React.useState(false);\r\n const active = selected || hovered;\r\n\r\n const borderColor = active ? colors.primary : colors.border;\r\n const backgroundColor = selected ? colors.tint : colors.muted;\r\n // Selected AND hovered both lift the ink to the primary colour (v1's indigo / indigo-dark);\r\n // the theme surface only guarantees the 500 step, so both use it — border + fill carry the state.\r\n const textColor = active ? colors.primary : colors.textMuted;\r\n\r\n return (\r\n <Pressable\r\n accessibilityHint={accessibilityHint}\r\n accessibilityLabel={option.label}\r\n accessibilityRole=\"button\"\r\n accessibilityState={{ selected, disabled }}\r\n aria-pressed={ariaPressed}\r\n disabled={disabled}\r\n hitSlop={CHIP_HIT_SLOP}\r\n testID={testID}\r\n onHoverIn={() => setHovered(true)}\r\n onHoverOut={() => setHovered(false)}\r\n onPress={onPress}\r\n >\r\n <View style={[styles.chipOutline, { borderColor, backgroundColor }]}>\r\n <Text style={[styles.chipText, styles.chipTextOutline, { color: textColor }]}>{option.label}</Text>\r\n </View>\r\n </Pressable>\r\n );\r\n}\r\n\r\n/** A single solid chip — the original filled-pill look (unchanged for existing consumers). */\r\nfunction SolidChip<T extends string | number>({\r\n option,\r\n selected,\r\n disabled,\r\n colors,\r\n testID,\r\n accessibilityHint,\r\n ariaPressed,\r\n onPress,\r\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\r\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\r\n const textColor = selected ? colors.onPrimary : colors.textStrong;\r\n return (\r\n <TouchableOpacity\r\n accessibilityHint={accessibilityHint}\r\n accessibilityLabel={option.label}\r\n accessibilityRole=\"button\"\r\n accessibilityState={{ selected, disabled }}\r\n aria-pressed={ariaPressed}\r\n disabled={disabled}\r\n hitSlop={CHIP_HIT_SLOP}\r\n testID={testID}\r\n onPress={onPress}\r\n >\r\n <View style={[styles.chip, { borderColor: colors.border, backgroundColor }]}>\r\n <Text style={[styles.chipText, { color: textColor }]}>{option.label}</Text>\r\n </View>\r\n </TouchableOpacity>\r\n );\r\n}\r\n\r\nconst IS_WEB = Platform.OS === 'web';\r\n\r\n/** Ties the chip group to `Field`'s error line for assistive tech (web only; no-op on native). */\r\nfunction groupA11yProps(describedById: string | undefined, hasError: boolean): WebGroupA11y {\r\n if (!IS_WEB) return {};\r\n return { 'aria-invalid': hasError ? true : undefined, 'aria-describedby': describedById };\r\n}\r\n\r\nexport const ChipSelector = <T extends string | number>({\r\n label,\r\n options,\r\n value,\r\n onChange,\r\n multiple = false,\r\n disabled = false,\r\n variant = 'solid',\r\n containerStyle,\r\n spacing,\r\n required = false,\r\n error,\r\n testID,\r\n chipTestIDPrefix = DEFAULT_CHIP_TESTID_PREFIX,\r\n optionAccessibilityHint,\r\n}: ChipSelectorProps<T>): React.ReactElement => {\r\n const { theme } = useUi();\r\n const { colors, palette } = theme;\r\n\r\n const chipColors = React.useMemo<ChipColors>(() => {\r\n const primary = palette.primary['500'];\r\n return {\r\n border: colors.border,\r\n textStrong: colors.text,\r\n textMuted: colors.textSecondary,\r\n primary,\r\n onPrimary: onBrandInk(palette),\r\n muted: colors.background,\r\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\r\n };\r\n }, [colors.border, colors.text, colors.textSecondary, colors.background, palette]);\r\n\r\n function isSelected(optionValue: T): boolean {\r\n if (multiple && Array.isArray(value))\r\n return value.includes(optionValue);\r\n\r\n return value === optionValue;\r\n }\r\n\r\n function renderChip(option: ChipOption<T>): React.ReactElement {\r\n const selected = isSelected(option.value);\r\n const chipProps = {\r\n colors: chipColors,\r\n disabled,\r\n option,\r\n selected,\r\n ...chipIdentity(option, selected, {\r\n prefix: chipTestIDPrefix,\r\n hint: optionAccessibilityHint,\r\n multiple,\r\n }),\r\n onPress: (): void => onChange(option.value),\r\n };\r\n const key = String(option.value);\r\n return variant === 'outline' ? <OutlineChip key={key} {...chipProps} /> : <SolidChip key={key} {...chipProps} />;\r\n }\r\n\r\n return (\r\n <Field\r\n containerStyle={containerStyle}\r\n error={error}\r\n label={label}\r\n required={required}\r\n spacing={spacing}\r\n testID={testID}\r\n >\r\n {({ describedById, hasError }) => (\r\n <View style={styles.chipContainer} {...(groupA11yProps(describedById, hasError) as ViewProps)}>\r\n {options.map(renderChip)}\r\n </View>\r\n )}\r\n </Field>\r\n );\r\n};\r\n\r\nexport default ChipSelector;\r\n","/**\n * Reusable form switch/toggle with an optional description.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, Switch, type TextStyle, type ViewStyle } from 'react-native';\n\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 },\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 { 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 <View\n style={[\n styles.container,\n containerStyle,\n ]}\n >\n <View style={styles.textColumn}>\n <Text style={[styles.label, themeStyles.label]}>{label}</Text>\n {hasDescription ? (\n <Text style={[styles.description, themeStyles.description]}>{description}</Text>\n ) : null}\n </View>\n <Switch\n accessibilityHint={accessibilityHint ?? label}\n accessibilityLabel={label}\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: value }}\n disabled={disabled}\n testID={testID}\n value={value}\n onValueChange={onValueChange}\n />\n </View>\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 { 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 },\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={[styles.container, containerStyle, disabled ? { opacity: DISABLED_OPACITY } : null]}\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 * `controlStyles` — the tuned metrics for the dense CONTROLS (text box, select trigger, floating\n * option menu, date-range row), promoted VERBATIM out of `@dloizides/ui-tables`' private\n * `Filters/styles.ts`.\n *\n * That file's own header said the quiet part out loud: it \"reconcile[d] the per-field styles that\n * were copy-pasted across aml-v2's filter files into one shared source\" — and then locked the\n * reconciliation inside one bar, where no other surface could reach it. These numbers are that\n * reconciliation, unchanged to the pixel, now reachable.\n *\n * Colours are applied INLINE from `useUi().theme` at render — nothing here carries a colour\n * literal, so a control re-themes per tenant without a stylesheet change.\n */\nimport { StyleSheet } from 'react-native';\n\nconst FIELD_GAP = 4;\nconst LABEL_FONT = 11;\nconst LABEL_LETTER_SPACING = 0.4;\nconst INPUT_RADIUS = 8;\nconst INPUT_PAD_H = 12;\nconst INPUT_PAD_V = 10;\nconst INPUT_FONT = 14;\nconst INPUT_BORDER = 1;\nconst DATE_ROW_GAP = 8;\nconst CHEVRON_FONT = 10;\nconst MENU_TOP_GAP = 4;\nconst MENU_RADIUS = 8;\nconst MENU_PAD_V = 4;\nconst MENU_OPT_PAD_H = 12;\nconst MENU_OPT_PAD_V = 8;\nconst MENU_MIN_WIDTH = 160;\nconst MENU_MAX_HEIGHT = 260;\nconst MENU_Z = 1000;\nconst MENU_ELEVATION = 8;\nconst MENU_BOX_SHADOW = '0px 2px 8px rgba(0, 0, 0, 0.15)';\nconst OPTION_FONT = 14;\nconst ERROR_FONT = 12;\nconst ERROR_GAP = 3;\n\nexport const controlStyles = StyleSheet.create({\n /** The shared bordered box every dense text control renders in. */\n input: {\n borderWidth: INPUT_BORDER,\n borderRadius: INPUT_RADIUS,\n paddingHorizontal: INPUT_PAD_H,\n paddingVertical: INPUT_PAD_V,\n fontSize: INPUT_FONT,\n },\n /** The select trigger: a bordered field box matching the text inputs + a chevron. */\n selectTrigger: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: DATE_ROW_GAP,\n borderWidth: INPUT_BORDER,\n borderRadius: INPUT_RADIUS,\n paddingHorizontal: INPUT_PAD_H,\n paddingVertical: INPUT_PAD_V,\n },\n selectTriggerText: { fontSize: INPUT_FONT, flexShrink: 1 },\n chevron: { fontSize: CHEVRON_FONT },\n dateRow: { flexDirection: 'row', gap: DATE_ROW_GAP },\n dateCol: { gap: FIELD_GAP, flex: 1 },\n /**\n * The micro-caption above a sub-control (a date range's From/To) and beside a switch. Note it\n * is deliberately NOT the `control` label voice: it carries no `700`/uppercase, because it\n * names a HALF of a control that already has a `control`-voice label above it. Uppercasing it\n * too would make one field shout twice.\n */\n subLabel: { fontSize: LABEL_FONT, letterSpacing: LABEL_LETTER_SPACING },\n /** Positioning context for a floating `AnchoredMenu` (`position:absolute; top:100%`). */\n anchor: { position: 'relative' },\n menu: {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: MENU_TOP_GAP,\n minWidth: MENU_MIN_WIDTH,\n maxHeight: MENU_MAX_HEIGHT,\n borderWidth: INPUT_BORDER,\n borderRadius: MENU_RADIUS,\n paddingVertical: MENU_PAD_V,\n zIndex: MENU_Z,\n boxShadow: MENU_BOX_SHADOW,\n elevation: MENU_ELEVATION,\n overflow: 'hidden',\n },\n option: { paddingHorizontal: MENU_OPT_PAD_H, paddingVertical: MENU_OPT_PAD_V },\n optionText: { fontSize: OPTION_FONT },\n error: { fontSize: ERROR_FONT, marginTop: ERROR_GAP },\n});\n","/**\n * `AnchoredMenu` — the floating option list shared by `SelectControl` and `TypeaheadControl`.\n *\n * Renders an in-tree, absolutely-positioned popover under its anchor (the pattern aml-v2's\n * CountryPicker proved: `position:absolute; top:100%; zIndex; elevation`), so it floats over\n * sibling fields without a portal. On web it dismisses on outside-click / Escape; on native the\n * caller closes it on blur/select. Purely presentational + theme-flat, so it stays reusable.\n *\n * Promoted verbatim out of `@dloizides/ui-tables`' private `Filters/components/AnchoredMenu`.\n *\n * Deliberately in-tree (no `ui-layout` dependency). That was a considered choice in `ui-tables`\n * and it still holds here: `ui-forms` is a low-level primitive and must not take a runtime\n * dependency on the higher-level `ui-layout` `ModalDropdown` — that would invert the graph for\n * every consumer. Apps needing the responsive modal/bottom-sheet variant inject it instead.\n */\nimport React, { useEffect } from 'react';\n\nimport { Pressable, Text, View } from 'react-native';\n\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\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 /** 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\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 testID,\n anchorRef,\n}: AnchoredMenuProps): React.ReactElement {\n const menuRef = React.useRef<View>(null);\n useDismiss(anchorRef, menuRef, onDismiss);\n\n return (\n <View\n ref={menuRef}\n accessibilityRole=\"menu\"\n style={[s.menu, { borderColor: colors.border, backgroundColor: colors.surface }]}\n testID={`${testID}-menu`}\n >\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 </View>\n );\n}\n\nexport default AnchoredMenu;\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 /** 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 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 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 />\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"]}
|
|
1
|
+
{"version":3,"sources":["../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/useThemedInput/useThemedInput.ts","../src/webFieldA11y/webFieldA11y.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx","../src/controls/controlStyles.ts","../src/AnchoredMenu/AnchoredMenu.tsx","../src/SelectControl/SelectControl.tsx","../src/controls/suggestOptions.ts","../src/TypeaheadControl/TypeaheadControl.tsx","../src/DateRangeControl/DateRangeControl.tsx"],"names":["jsxs","Text","jsx","StyleSheet","React","useUi","View","styles","Button","Platform","useState","useCallback","useMemo","IS_WEB","ThemedTextInput","TextInput","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","Pressable","TouchableOpacity","DESCRIPTION_FONT_SIZE","Switch","HINT_FONT_SIZE","useEffect","useRef"],"mappings":"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","file":"index.js","sourcesContent":["/**\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 */\nimport React from 'react';\n\nimport { Text, type StyleProp, type TextStyle } from 'react-native';\n\nimport type { FieldMarker } from './fieldMarkers';\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 /** 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 style,\n requiredMarkStyle,\n optionalMarkStyle,\n}: FieldLabelProps): React.ReactElement {\n return (\n <Text style={style}>\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 { 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\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 id pair so the hint and error lines can be linked to the control via\n * `aria-describedby`. One counter bump per field keeps the two ids of a field in lockstep.\n */\nexport function useFieldIds(): { hintId: string; errorId: string } {\n const [ids] = React.useState(() => {\n fieldSeq += 1;\n const seq = String(fieldSeq);\n return { hintId: `field-hint-${seq}`, errorId: `field-error-${seq}` };\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 } = 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 const control = typeof children === 'function' ? children({ describedById, hasError }) : children;\n\n return (\n <View style={[spacingStyles.container, containerStyle]} testID={testID}>\n {hasLabel ? (\n <FieldLabel\n label={labelText}\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","/**\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\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 /** A readable mid-grey placeholder colour from the theme. */\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: colors.textSecondary,\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 * 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 { TextInput, type TextInputProps } from 'react-native';\n\nimport { useThemedInput } from '../useThemedInput/useThemedInput';\nimport { webFieldA11y } from '../webFieldA11y/webFieldA11y';\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\nexport const ThemedTextInput = React.forwardRef<TextInput, ThemedTextInputProps>(function ThemedTextInput(\n { hasError = false, describedById, requiredField = false, onFocus, onBlur, style, placeholderTextColor, ...rest },\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 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={[style, themedStyle]}\n />\n );\n});\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 { StyleSheet, type TextInputProps, type ViewStyle } from 'react-native';\n\nimport { Field } from '../Field/Field';\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\nconst INPUT_PADDING_V = 10;\nconst INPUT_PADDING_H = 12;\nconst INPUT_BORDER_RADIUS = 8;\nconst INPUT_BORDER_WIDTH = 1;\n\nconst styles = StyleSheet.create({\n input: {\n paddingVertical: INPUT_PADDING_V,\n paddingHorizontal: INPUT_PADDING_H,\n borderRadius: INPUT_BORDER_RADIUS,\n borderWidth: INPUT_BORDER_WIDTH,\n },\n});\n\nexport interface FormFieldProps extends Omit<TextInputProps, 'style'> {\n label: string;\n required?: boolean;\n error?: string;\n containerStyle?: ViewStyle;\n}\n\nexport const FormField = ({\n label,\n required = false,\n error,\n containerStyle,\n ...textInputProps\n}: FormFieldProps): React.ReactElement => (\n <Field containerStyle={containerStyle} error={error} label={label} required={required}>\n {({ describedById, hasError }) => (\n <ThemedTextInput\n accessibilityHint={`Enter ${label}`}\n accessibilityLabel={label}\n describedById={describedById}\n hasError={hasError}\n requiredField={required}\n style={styles.input}\n testID=\"form-field-input\"\n {...textInputProps}\n />\n )}\n </Field>\n);\n\nexport default FormField;\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 */\nimport React from 'react';\n\nimport {\n StyleSheet,\n View,\n Text,\n Pressable,\n TouchableOpacity,\n type StyleProp,\n type ViewProps,\n type ViewStyle,\n} from 'react-native';\n\nimport { webFieldA11y } from '../webFieldA11y/webFieldA11y';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { Field } from '../Field/Field';\nimport type { FieldSpacing } from '../Field/fieldSpacing';\n\nconst TRANSPARENT_COLOR = 'transparent';\nconst WHITE_COLOR = '#fff';\nconst SOLID_RADIUS = 20;\nconst OUTLINE_RADIUS = 999;\nconst OUTLINE_PAD_H = 12;\nconst OUTLINE_PAD_V = 5;\nconst OUTLINE_FONT_SIZE = 13;\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 * Chips are visually compact (≈24–26px tall). `hitSlop` expands the pressable's TOUCH area\n * toward the WCAG ≥44px target WITHOUT changing the rendered pill size, so existing layouts are\n * byte-identical while taps/clicks get an easier target.\n */\nconst CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 } as const;\n/** Gap between adjacent chips, horizontally and between wrapped rows. */\nconst CHIP_GUTTER = 8;\n\n/** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */\nexport type ChipVariant = 'solid' | 'outline';\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 */\nconst DEFAULT_CHIP_TESTID_PREFIX = 'chip-selector-chip';\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\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 chip: {\n paddingHorizontal: 12,\n paddingVertical: 6,\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 borderRadius: OUTLINE_RADIUS,\n borderWidth: 1,\n },\n chipText: {},\n chipTextOutline: { fontSize: OUTLINE_FONT_SIZE },\n});\n\n/** Resolved, theme-derived colours for the two variants. */\ninterface ChipColors {\n border: string;\n /** Strong ink for the solid variant's rest text (unchanged from the original). */\n textStrong: string;\n /** Muted ink for the outline variant's rest text (v1 ink-soft). */\n textMuted: string;\n primary: string;\n /**\n * Ink on a primary-filled chip. Reads the theme's `onBrand` scale when the app publishes one,\n * falling back to white. It used to be a hardcoded `#fff`, which meant a tenant whose primary\n * is light got white-on-light and failed contrast — the token slot is the fix, and the\n * fallback keeps every app that has no `onBrand` scale rendering exactly as before.\n */\n onPrimary: string;\n muted: string;\n tint: string;\n}\n\nexport interface ChipOption<T> {\n value: T;\n label: string;\n}\n\nexport interface ChipSelectorProps<T> {\n /** Optional — with no label, no label row is rendered (no phantom gap above the chips). */\n label?: string;\n options: Array<ChipOption<T>>;\n value: T | T[];\n onChange: (value: T) => void;\n multiple?: boolean;\n disabled?: boolean;\n /** Visual variant. `solid` (default) = filled selected pill; `outline` = v1 tinted-outline. */\n variant?: ChipVariant;\n /**\n * `StyleProp` (not a bare `ViewStyle`) so it composes the same way `Field`'s does — a caller can\n * pass an array instead of restating a complete style per variant.\n */\n containerStyle?: StyleProp<ViewStyle>;\n /**\n * Forwarded verbatim to the underlying `Field`. `ChipSelector` deliberately holds NO spacing\n * opinion of its own: it delegates, so the two cannot drift into disagreeing about how much room\n * a chip block occupies. The guard for that is `chipSelectorFieldLockstep` in the tests.\n */\n spacing?: FieldSpacing;\n /** Marks the selection mandatory — renders `Field`'s decorative `*` next to the label. */\n required?: boolean;\n /** Validation message under the chips, wired to the chip group via `aria-describedby`. */\n error?: string;\n testID?: string;\n /**\n * Stem for each chip's testID — a chip becomes `${chipTestIDPrefix}-${value}`. Defaults to\n * `chip-selector-chip`, which existing specs select on; supply your own when a screen has\n * several chip groups that must be addressed independently.\n */\n chipTestIDPrefix?: string;\n /**\n * Accessibility hint applied to every chip in the group. Supply a LOCALIZED string — the\n * built-in default (`Selects <label>`) is English-only and exists solely so pre-existing\n * consumers keep their current announcement.\n */\n optionAccessibilityHint?: string;\n}\n\ninterface ChipProps<T> {\n option: ChipOption<T>;\n selected: boolean;\n disabled: boolean;\n colors: ChipColors;\n /** Resolved `${prefix}-${value}` for this chip. */\n testID: string;\n /** Resolved hint for this chip — localized by the consumer, or the built-in English default. */\n accessibilityHint: string;\n /**\n * Web-only toggle state for a MULTI-select chip; `undefined` for single-select.\n *\n * Why `aria-pressed` on a button and not `role=\"checkbox\"`: react-native-web renders\n * `accessibilityRole=\"button\"` as a real `<button>`, but ANY other role as a plain `<div>`.\n * Switching a multi chip to `checkbox` therefore trades native keyboard activation for a\n * div that only looks right — the same RN-web trap that produced the held-Enter defect\n * elsewhere in this fleet. A toggle button (`role=button` + `aria-pressed`) conveys the\n * on/off state to assistive tech AND keeps Space/Enter working for free.\n *\n * It is passed as a literal web prop because RNW 0.21 emits NOTHING from\n * `accessibilityState` on web — verified, not assumed — so the `accessibilityState` below\n * is carrying native only.\n */\n ariaPressed?: boolean;\n}\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 },\n): Pick<ChipProps<T>, 'testID' | 'accessibilityHint' | 'ariaPressed'> {\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 };\n}\n\n/** A single outline chip — owns its own hover state (web) for the border/ink lift. */\nfunction OutlineChip<T extends string | number>({\n option,\n selected,\n disabled,\n colors,\n testID,\n accessibilityHint,\n ariaPressed,\n onPress,\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\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 accessibilityHint={accessibilityHint}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected, disabled }}\n aria-pressed={ariaPressed}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n testID={testID}\n onHoverIn={() => setHovered(true)}\n onHoverOut={() => setHovered(false)}\n onPress={onPress}\n >\n <View style={[styles.chipOutline, { borderColor, backgroundColor }]}>\n <Text style={[styles.chipText, styles.chipTextOutline, { color: textColor }]}>{option.label}</Text>\n </View>\n </Pressable>\n );\n}\n\n/** A single solid chip — the original filled-pill look (unchanged for existing consumers). */\nfunction SolidChip<T extends string | number>({\n option,\n selected,\n disabled,\n colors,\n testID,\n accessibilityHint,\n ariaPressed,\n onPress,\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? colors.onPrimary : colors.textStrong;\n return (\n <TouchableOpacity\n accessibilityHint={accessibilityHint}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected, disabled }}\n aria-pressed={ariaPressed}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n testID={testID}\n onPress={onPress}\n >\n <View style={[styles.chip, { borderColor: colors.border, backgroundColor }]}>\n <Text style={[styles.chipText, { color: textColor }]}>{option.label}</Text>\n </View>\n </TouchableOpacity>\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}: ChipSelectorProps<T>): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n\n const chipColors = React.useMemo<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 }, [colors.border, colors.text, colors.textSecondary, colors.background, 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 function renderChip(option: ChipOption<T>): 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 }),\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 style={styles.chipContainer} {...(webFieldA11y({ describedById, hasError }) as ViewProps)}>\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 { StyleSheet, View, Text, Switch, type TextStyle, type ViewStyle } from 'react-native';\n\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 },\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 { 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 <View\n style={[\n styles.container,\n containerStyle,\n ]}\n >\n <View style={styles.textColumn}>\n <Text style={[styles.label, themeStyles.label]}>{label}</Text>\n {hasDescription ? (\n <Text style={[styles.description, themeStyles.description]}>{description}</Text>\n ) : null}\n </View>\n <Switch\n accessibilityHint={accessibilityHint ?? label}\n accessibilityLabel={label}\n accessibilityRole=\"switch\"\n accessibilityState={{ checked: value }}\n disabled={disabled}\n testID={testID}\n value={value}\n onValueChange={onValueChange}\n />\n </View>\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 { 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 },\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={[styles.container, containerStyle, disabled ? { opacity: DISABLED_OPACITY } : null]}\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 * `controlStyles` — the tuned metrics for the dense CONTROLS (text box, select trigger, floating\n * option menu, date-range row), promoted VERBATIM out of `@dloizides/ui-tables`' private\n * `Filters/styles.ts`.\n *\n * That file's own header said the quiet part out loud: it \"reconcile[d] the per-field styles that\n * were copy-pasted across aml-v2's filter files into one shared source\" — and then locked the\n * reconciliation inside one bar, where no other surface could reach it. These numbers are that\n * reconciliation, unchanged to the pixel, now reachable.\n *\n * Colours are applied INLINE from `useUi().theme` at render — nothing here carries a colour\n * literal, so a control re-themes per tenant without a stylesheet change.\n */\nimport { StyleSheet } from 'react-native';\n\nconst FIELD_GAP = 4;\nconst LABEL_FONT = 11;\nconst LABEL_LETTER_SPACING = 0.4;\nconst INPUT_RADIUS = 8;\nconst INPUT_PAD_H = 12;\nconst INPUT_PAD_V = 10;\nconst INPUT_FONT = 14;\nconst INPUT_BORDER = 1;\nconst DATE_ROW_GAP = 8;\nconst CHEVRON_FONT = 10;\nconst MENU_TOP_GAP = 4;\nconst MENU_RADIUS = 8;\nconst MENU_PAD_V = 4;\nconst MENU_OPT_PAD_H = 12;\nconst MENU_OPT_PAD_V = 8;\nconst MENU_MIN_WIDTH = 160;\nconst MENU_MAX_HEIGHT = 260;\nconst MENU_Z = 1000;\nconst MENU_ELEVATION = 8;\nconst MENU_BOX_SHADOW = '0px 2px 8px rgba(0, 0, 0, 0.15)';\nconst OPTION_FONT = 14;\nconst ERROR_FONT = 12;\nconst ERROR_GAP = 3;\n\nexport const controlStyles = StyleSheet.create({\n /** The shared bordered box every dense text control renders in. */\n input: {\n borderWidth: INPUT_BORDER,\n borderRadius: INPUT_RADIUS,\n paddingHorizontal: INPUT_PAD_H,\n paddingVertical: INPUT_PAD_V,\n fontSize: INPUT_FONT,\n },\n /** The select trigger: a bordered field box matching the text inputs + a chevron. */\n selectTrigger: {\n flexDirection: 'row',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: DATE_ROW_GAP,\n borderWidth: INPUT_BORDER,\n borderRadius: INPUT_RADIUS,\n paddingHorizontal: INPUT_PAD_H,\n paddingVertical: INPUT_PAD_V,\n },\n selectTriggerText: { fontSize: INPUT_FONT, flexShrink: 1 },\n chevron: { fontSize: CHEVRON_FONT },\n dateRow: { flexDirection: 'row', gap: DATE_ROW_GAP },\n dateCol: { gap: FIELD_GAP, flex: 1 },\n /**\n * The micro-caption above a sub-control (a date range's From/To) and beside a switch. Note it\n * is deliberately NOT the `control` label voice: it carries no `700`/uppercase, because it\n * names a HALF of a control that already has a `control`-voice label above it. Uppercasing it\n * too would make one field shout twice.\n */\n subLabel: { fontSize: LABEL_FONT, letterSpacing: LABEL_LETTER_SPACING },\n /** Positioning context for a floating `AnchoredMenu` (`position:absolute; top:100%`). */\n anchor: { position: 'relative' },\n menu: {\n position: 'absolute',\n top: '100%',\n left: 0,\n marginTop: MENU_TOP_GAP,\n minWidth: MENU_MIN_WIDTH,\n maxHeight: MENU_MAX_HEIGHT,\n borderWidth: INPUT_BORDER,\n borderRadius: MENU_RADIUS,\n paddingVertical: MENU_PAD_V,\n zIndex: MENU_Z,\n boxShadow: MENU_BOX_SHADOW,\n elevation: MENU_ELEVATION,\n overflow: 'hidden',\n },\n option: { paddingHorizontal: MENU_OPT_PAD_H, paddingVertical: MENU_OPT_PAD_V },\n optionText: { fontSize: OPTION_FONT },\n error: { fontSize: ERROR_FONT, marginTop: ERROR_GAP },\n});\n","/**\n * `AnchoredMenu` — the floating option list shared by `SelectControl` and `TypeaheadControl`.\n *\n * Renders an in-tree, absolutely-positioned popover under its anchor (the pattern aml-v2's\n * CountryPicker proved: `position:absolute; top:100%; zIndex; elevation`), so it floats over\n * sibling fields without a portal. On web it dismisses on outside-click / Escape; on native the\n * caller closes it on blur/select. Purely presentational + theme-flat, so it stays reusable.\n *\n * Promoted verbatim out of `@dloizides/ui-tables`' private `Filters/components/AnchoredMenu`.\n *\n * Deliberately in-tree (no `ui-layout` dependency). That was a considered choice in `ui-tables`\n * and it still holds here: `ui-forms` is a low-level primitive and must not take a runtime\n * dependency on the higher-level `ui-layout` `ModalDropdown` — that would invert the graph for\n * every consumer. Apps needing the responsive modal/bottom-sheet variant inject it instead.\n */\nimport React, { useEffect } from 'react';\n\nimport { Pressable, Text, View } from 'react-native';\n\nimport { controlStyles as s } from '../controls/controlStyles';\nimport type { ControlOption } from '../controls/controlTypes';\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 /** 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\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 testID,\n anchorRef,\n}: AnchoredMenuProps): React.ReactElement {\n const menuRef = React.useRef<View>(null);\n useDismiss(anchorRef, menuRef, onDismiss);\n\n return (\n <View\n ref={menuRef}\n accessibilityRole=\"menu\"\n style={[s.menu, { borderColor: colors.border, backgroundColor: colors.surface }]}\n testID={`${testID}-menu`}\n >\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 </View>\n );\n}\n\nexport default AnchoredMenu;\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 /** 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 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 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 />\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"]}
|