@dloizides/ui-forms 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.4.0
4
+
5
+ - **Accessibility (WCAG 2.1 AA) hardening — additive + backward-compatible.**
6
+ - `FormField`: the error message is now programmatically tied to the input — the input gets
7
+ `aria-invalid` when errored and `aria-describedby` pointing at the error line (which is a
8
+ `role="alert"` live region), and `aria-required` when `required`. The required `*` is marked
9
+ decorative (`aria-hidden` / `accessibilityElementsHidden`) so a screen reader hears "required"
10
+ (via `aria-required`) instead of "star".
11
+ - `ThemedTextInput`: new optional `describedById` + `requiredField` props forward
12
+ `aria-describedby` / `aria-required`, and it emits `aria-invalid` from `hasError` (web only;
13
+ no-ops on native). Existing callers are unaffected.
14
+ - `FormCheckbox`: now keyboard-operable — the `role="checkbox"` Pressable renders a `<div>`
15
+ (no free Enter/Space), so an explicit web-only Enter/Space handler toggles it (WCAG 2.1.1).
16
+ - `ChipSelector`: chips gain a `hitSlop` so the touch target reaches ~44px WITHOUT changing the
17
+ rendered pill size, and expose `accessibilityState.disabled` when the selector is disabled.
18
+ - `useThemedInput`: the focus/hover CSS transition now collapses to instant when the user
19
+ requests `prefers-reduced-motion: reduce` (WCAG 2.3.3, web only).
20
+
3
21
  ## 1.3.0
4
22
 
5
23
  - `ChipSelector` gains a `variant` prop (`'solid' | 'outline'`, default `'solid'`). `solid` is the
package/dist/index.d.mts CHANGED
@@ -33,6 +33,13 @@ declare const FormField: ({ label, required, error, containerStyle, ...textInput
33
33
  interface ThemedTextInputProps extends TextInputProps {
34
34
  /** Render with the error border colour (matches `FormField`'s error treatment). */
35
35
  hasError?: boolean;
36
+ /**
37
+ * id of an element describing this input (e.g. an error/hint line). Linked via
38
+ * `aria-describedby` on web so a screen reader reads it after the field's name. No-op native.
39
+ */
40
+ describedById?: string;
41
+ /** Marks the field required for assistive tech (`aria-required` on web). No-op on native. */
42
+ requiredField?: boolean;
36
43
  }
37
44
  declare const ThemedTextInput: React.ForwardRefExoticComponent<ThemedTextInputProps & React.RefAttributes<TextInput>>;
38
45
 
package/dist/index.d.ts CHANGED
@@ -33,6 +33,13 @@ declare const FormField: ({ label, required, error, containerStyle, ...textInput
33
33
  interface ThemedTextInputProps extends TextInputProps {
34
34
  /** Render with the error border colour (matches `FormField`'s error treatment). */
35
35
  hasError?: boolean;
36
+ /**
37
+ * id of an element describing this input (e.g. an error/hint line). Linked via
38
+ * `aria-describedby` on web so a screen reader reads it after the field's name. No-op native.
39
+ */
40
+ describedById?: string;
41
+ /** Marks the field required for assistive tech (`aria-required` on web). No-op on native. */
42
+ requiredField?: boolean;
36
43
  }
37
44
  declare const ThemedTextInput: React.ForwardRefExoticComponent<ThemedTextInputProps & React.RefAttributes<TextInput>>;
38
45
 
package/dist/index.js CHANGED
@@ -24,6 +24,10 @@ var RED_START = 1;
24
24
  var GREEN_START = 3;
25
25
  var BLUE_START = 5;
26
26
  var CHANNEL_END_OFFSET = 2;
27
+ function prefersReducedMotion() {
28
+ if (!IS_WEB || typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
29
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
30
+ }
27
31
  function withAlpha(color, alpha) {
28
32
  const hex = color.trim();
29
33
  const isHex = hex.charAt(0) === "#" && (hex.length === HEX_FULL_LENGTH || hex.length === HEX_SHORT_LENGTH);
@@ -68,7 +72,8 @@ function useThemedInput(options = {}) {
68
72
  const ring = isFocused && !hasError ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(primary, FOCUS_RING_ALPHA)}` : "none";
69
73
  const webStyle = {
70
74
  transitionProperty: TRANSITION_PROPERTY,
71
- transitionDuration: TRANSITION_DURATION,
75
+ // Collapse the eased transition to instant when the user prefers reduced motion.
76
+ transitionDuration: prefersReducedMotion() ? "0s" : TRANSITION_DURATION,
72
77
  transitionTimingFunction: TRANSITION_TIMING,
73
78
  boxShadow: ring,
74
79
  outlineStyle: "none"
@@ -99,19 +104,26 @@ function useThemedInput(options = {}) {
99
104
  hoverBind
100
105
  };
101
106
  }
102
- var ThemedTextInput = React3__default.default.forwardRef(function ThemedTextInput2({ hasError = false, onFocus, onBlur, style, placeholderTextColor, ...rest }, ref) {
107
+ var IS_WEB2 = reactNative.Platform.OS === "web";
108
+ var ThemedTextInput = React3__default.default.forwardRef(function ThemedTextInput2({ hasError = false, describedById, requiredField = false, onFocus, onBlur, style, placeholderTextColor, ...rest }, ref) {
103
109
  const {
104
110
  style: themedStyle,
105
111
  placeholderTextColor: themedPlaceholder,
106
112
  focusBind,
107
113
  hoverBind
108
114
  } = useThemedInput({ hasError, onFocus, onBlur });
115
+ const webA11y = IS_WEB2 ? {
116
+ "aria-invalid": hasError ? true : void 0,
117
+ "aria-describedby": describedById,
118
+ "aria-required": requiredField ? true : void 0
119
+ } : {};
109
120
  return /* @__PURE__ */ jsxRuntime.jsx(
110
121
  reactNative.TextInput,
111
122
  {
112
123
  ref,
113
124
  placeholderTextColor: placeholderTextColor ?? themedPlaceholder,
114
125
  ...rest,
126
+ ...webA11y,
115
127
  ...hoverBind,
116
128
  onFocus: focusBind.onFocus,
117
129
  onBlur: focusBind.onBlur,
@@ -145,6 +157,14 @@ var styles = reactNative.StyleSheet.create({
145
157
  marginTop: 4
146
158
  }
147
159
  });
160
+ var formFieldSeq = 0;
161
+ function useErrorId() {
162
+ const [id] = React3__default.default.useState(() => {
163
+ formFieldSeq += 1;
164
+ return `form-field-error-${String(formFieldSeq)}`;
165
+ });
166
+ return id;
167
+ }
148
168
  var FormField = ({
149
169
  label,
150
170
  required = false,
@@ -156,6 +176,7 @@ var FormField = ({
156
176
  const { colors, semantic } = theme;
157
177
  const errorColor = semantic.error["500"];
158
178
  const hasError = typeof error === "string" && error !== "";
179
+ const errorId = useErrorId();
159
180
  const themeStyles = React3__default.default.useMemo(
160
181
  () => ({
161
182
  label: { color: colors.textSecondary },
@@ -168,20 +189,25 @@ var FormField = ({
168
189
  /* @__PURE__ */ jsxRuntime.jsxs(reactNative.Text, { style: [styles.label, themeStyles.label], children: [
169
190
  label,
170
191
  " ",
171
- required ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: themeStyles.requiredMark, children: "*" }) : null
192
+ required ? (
193
+ // The asterisk is decorative — `requiredField` conveys "required" to assistive tech.
194
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { "aria-hidden": true, accessibilityElementsHidden: true, importantForAccessibility: "no", style: themeStyles.requiredMark, children: "*" })
195
+ ) : null
172
196
  ] }),
173
197
  /* @__PURE__ */ jsxRuntime.jsx(
174
198
  ThemedTextInput,
175
199
  {
176
200
  accessibilityHint: `Enter ${label}`,
177
201
  accessibilityLabel: label,
202
+ describedById: hasError ? errorId : void 0,
178
203
  hasError,
204
+ requiredField: required,
179
205
  style: styles.input,
180
206
  testID: "form-field-input",
181
207
  ...textInputProps
182
208
  }
183
209
  ),
184
- hasError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles.errorText, themeStyles.errorText], children: error }) : null
210
+ hasError ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { nativeID: errorId, role: "alert", style: [styles.errorText, themeStyles.errorText], children: error }) : null
185
211
  ] });
186
212
  };
187
213
  var TRANSPARENT_COLOR = "transparent";
@@ -198,6 +224,7 @@ var RGB_R_START = 0;
198
224
  var RGB_R_END = 2;
199
225
  var RGB_G_END = 4;
200
226
  var RGB_B_END = 6;
227
+ var CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 };
201
228
  function withAlpha2(hex, alpha) {
202
229
  const normalized = hex.replace("#", "");
203
230
  const isShort = normalized.length === HEX_SHORT_LENGTH2;
@@ -255,8 +282,9 @@ function OutlineChip({
255
282
  accessibilityHint: `Selects ${option.label}`,
256
283
  accessibilityLabel: option.label,
257
284
  accessibilityRole: "button",
258
- accessibilityState: { selected },
285
+ accessibilityState: { selected, disabled },
259
286
  disabled,
287
+ hitSlop: CHIP_HIT_SLOP,
260
288
  style: styles2.chipWrapper,
261
289
  testID: `chip-selector-chip-${String(option.value)}`,
262
290
  onHoverIn: () => setHovered(true),
@@ -281,8 +309,9 @@ function SolidChip({
281
309
  accessibilityHint: `Selects ${option.label}`,
282
310
  accessibilityLabel: option.label,
283
311
  accessibilityRole: "button",
284
- accessibilityState: { selected },
312
+ accessibilityState: { selected, disabled },
285
313
  disabled,
314
+ hitSlop: CHIP_HIT_SLOP,
286
315
  style: styles2.chipWrapper,
287
316
  testID: `chip-selector-chip-${String(option.value)}`,
288
317
  onPress,
@@ -415,6 +444,7 @@ var FormSwitch = ({
415
444
  }
416
445
  );
417
446
  };
447
+ var ACTIVATION_KEYS = ["Enter", " ", "Spacebar"];
418
448
  var HINT_FONT_SIZE = 12;
419
449
  var BOX_SIZE = 20;
420
450
  var BOX_RADIUS = 5;
@@ -483,6 +513,14 @@ var FormCheckbox = ({
483
513
  if (onValueChange) onValueChange(next);
484
514
  if (onChange) onChange(next);
485
515
  };
516
+ const handleKeyDown = (event) => {
517
+ if (disabled) return;
518
+ const key = event.key ?? "";
519
+ if (!ACTIVATION_KEYS.includes(key)) return;
520
+ if (typeof event.preventDefault === "function") event.preventDefault();
521
+ toggle();
522
+ };
523
+ const keyboardProps = reactNative.Platform.OS === "web" ? { onKeyDown: handleKeyDown } : {};
486
524
  return /* @__PURE__ */ jsxRuntime.jsxs(
487
525
  reactNative.Pressable,
488
526
  {
@@ -496,6 +534,7 @@ var FormCheckbox = ({
496
534
  role: "checkbox",
497
535
  style: [styles4.container, containerStyle, disabled ? { opacity: DISABLED_OPACITY } : null],
498
536
  testID,
537
+ ...keyboardProps,
499
538
  children: [
500
539
  /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [styles4.box, value ? themeStyles.boxOn : themeStyles.boxOff], children: value ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.check, { color: colors.surface }], accessibilityElementsHidden: true, children: "\u2713" }) : null }),
501
540
  /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles4.textColumn, children: [
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useThemedInput/useThemedInput.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx"],"names":["Platform","useUi","useState","useCallback","useMemo","React","ThemedTextInput","jsx","TextInput","StyleSheet","View","jsxs","Text","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","styles","Pressable","TouchableOpacity","Switch"],"mappings":"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","file":"index.js","sourcesContent":["/**\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 */\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 const ring =\n isFocused && !hasError ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(primary, FOCUS_RING_ALPHA)}` : 'none';\n const webStyle = {\n transitionProperty: TRANSITION_PROPERTY,\n transitionDuration: 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 { TextInput, type TextInputProps } from 'react-native';\n\nimport { useThemedInput } from '../useThemedInput/useThemedInput';\n\nexport interface ThemedTextInputProps extends TextInputProps {\n /** Render with the error border colour (matches `FormField`'s error treatment). */\n hasError?: boolean;\n}\n\nexport const ThemedTextInput = React.forwardRef<TextInput, ThemedTextInputProps>(function ThemedTextInput(\n { hasError = 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 return (\n <TextInput\n ref={ref}\n placeholderTextColor={placeholderTextColor ?? themedPlaceholder}\n {...rest}\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 input itself is the shared `ThemedTextInput` primitive, so every FormField gets the\n * readable + lively treatment (dark text, subtle off-white rest background, brand focus\n * animation with a soft ring) for free, driven by the active theme.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, type TextInputProps, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\nconst CONTAINER_MARGIN_BOTTOM = 16;\nconst INPUT_PADDING_V = 10;\nconst INPUT_PADDING_H = 12;\nconst INPUT_BORDER_RADIUS = 8;\nconst ERROR_FONT_SIZE = 12;\nconst LABEL_FONT_SIZE = 13;\n\nconst styles = StyleSheet.create({\n container: {\n marginBottom: CONTAINER_MARGIN_BOTTOM,\n },\n label: {\n marginBottom: 4,\n fontSize: LABEL_FONT_SIZE,\n fontWeight: '600',\n },\n input: {\n paddingVertical: INPUT_PADDING_V,\n paddingHorizontal: INPUT_PADDING_H,\n borderRadius: INPUT_BORDER_RADIUS,\n borderWidth: 1,\n },\n errorText: {\n fontSize: ERROR_FONT_SIZE,\n marginTop: 4,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n requiredMark: TextStyle;\n errorText: TextStyle;\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 const { theme } = useUi();\n const { colors, semantic } = theme;\n const errorColor = semantic.error['500'];\n const hasError = typeof error === 'string' && error !== '';\n\n const themeStyles = React.useMemo<ThemeStyles>(\n () => ({\n label: { color: colors.textSecondary },\n requiredMark: { color: errorColor },\n errorText: { color: errorColor },\n }),\n [colors.textSecondary, errorColor],\n );\n\n return (\n <View style={[styles.container, containerStyle]}>\n <Text style={[styles.label, themeStyles.label]}>\n {label} {required ? <Text style={themeStyles.requiredMark}>*</Text> : null}\n </Text>\n <ThemedTextInput\n accessibilityHint={`Enter ${label}`}\n accessibilityLabel={label}\n hasError={hasError}\n style={styles.input}\n testID=\"form-field-input\"\n {...textInputProps}\n />\n {hasError ? <Text style={[styles.errorText, themeStyles.errorText]}>{error}</Text> : null}\n </View>\n );\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 */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, Pressable, TouchableOpacity, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\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/** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */\nexport type ChipVariant = 'solid' | 'outline';\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 label: {\n marginBottom: 8,\n fontWeight: '600',\n },\n chipContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n chipWrapper: {\n marginRight: 8,\n marginBottom: 8,\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 muted: string;\n tint: string;\n}\n\nexport interface ChipOption<T> {\n value: T;\n label: string;\n}\n\nexport interface ChipSelectorProps<T> {\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 containerStyle?: ViewStyle;\n}\n\ninterface ChipProps<T> {\n option: ChipOption<T>;\n selected: boolean;\n disabled: boolean;\n colors: ChipColors;\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 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={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected }}\n disabled={disabled}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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 onPress,\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? WHITE_COLOR : colors.textStrong;\n return (\n <TouchableOpacity\n accessibilityHint={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected }}\n disabled={disabled}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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\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}: ChipSelectorProps<T>): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const hasLabel = typeof label === 'string' && label !== '';\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 muted: colors.background,\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\n };\n }, [colors.border, colors.text, colors.textSecondary, colors.background, palette.primary]);\n\n const labelStyle = React.useMemo<TextStyle>(() => ({ color: colors.text }), [colors.text]);\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 return (\n <View style={containerStyle}>\n {hasLabel ? <Text style={[styles.label, labelStyle]}>{label}</Text> : null}\n <View style={styles.chipContainer}>\n {options.map((option) => {\n const selected = isSelected(option.value);\n const onPress = (): void => onChange(option.value);\n return variant === 'outline' ? (\n <OutlineChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n ) : (\n <SolidChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n );\n })}\n </View>\n </View>\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 { StyleSheet, View, Text, Pressable, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\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 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 >\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"]}
1
+ {"version":3,"sources":["../src/useThemedInput/useThemedInput.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx"],"names":["Platform","useUi","useState","useCallback","useMemo","IS_WEB","React","ThemedTextInput","jsx","TextInput","StyleSheet","View","jsxs","Text","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","styles","Pressable","TouchableOpacity","Switch"],"mappings":"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","file":"index.js","sourcesContent":["/**\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 const ring =\n isFocused && !hasError ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(primary, 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 input itself is the shared `ThemedTextInput` primitive, so every FormField gets the\n * readable + lively treatment (dark text, subtle off-white rest background, brand focus\n * animation with a soft ring) for free, driven by the active theme.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, type TextInputProps, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\nconst CONTAINER_MARGIN_BOTTOM = 16;\nconst INPUT_PADDING_V = 10;\nconst INPUT_PADDING_H = 12;\nconst INPUT_BORDER_RADIUS = 8;\nconst ERROR_FONT_SIZE = 12;\nconst LABEL_FONT_SIZE = 13;\n\nconst styles = StyleSheet.create({\n container: {\n marginBottom: CONTAINER_MARGIN_BOTTOM,\n },\n label: {\n marginBottom: 4,\n fontSize: LABEL_FONT_SIZE,\n fontWeight: '600',\n },\n input: {\n paddingVertical: INPUT_PADDING_V,\n paddingHorizontal: INPUT_PADDING_H,\n borderRadius: INPUT_BORDER_RADIUS,\n borderWidth: 1,\n },\n errorText: {\n fontSize: ERROR_FONT_SIZE,\n marginTop: 4,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n requiredMark: TextStyle;\n errorText: TextStyle;\n}\n\nexport interface FormFieldProps extends Omit<TextInputProps, 'style'> {\n label: string;\n required?: boolean;\n error?: string;\n containerStyle?: ViewStyle;\n}\n\nlet formFieldSeq = 0;\n/** Stable-per-instance id so the error line can be linked to the input via aria-describedby. */\nfunction useErrorId(): string {\n const [id] = React.useState(() => {\n formFieldSeq += 1;\n return `form-field-error-${String(formFieldSeq)}`;\n });\n return id;\n}\n\nexport const FormField = ({\n label,\n required = false,\n error,\n containerStyle,\n ...textInputProps\n}: FormFieldProps): React.ReactElement => {\n const { theme } = useUi();\n const { colors, semantic } = theme;\n const errorColor = semantic.error['500'];\n const hasError = typeof error === 'string' && error !== '';\n const errorId = useErrorId();\n\n const themeStyles = React.useMemo<ThemeStyles>(\n () => ({\n label: { color: colors.textSecondary },\n requiredMark: { color: errorColor },\n errorText: { color: errorColor },\n }),\n [colors.textSecondary, errorColor],\n );\n\n return (\n <View style={[styles.container, containerStyle]}>\n <Text style={[styles.label, themeStyles.label]}>\n {label}{' '}\n {required ? (\n // The asterisk is decorative — `requiredField` conveys \"required\" to assistive tech.\n <Text aria-hidden accessibilityElementsHidden importantForAccessibility=\"no\" style={themeStyles.requiredMark}>\n *\n </Text>\n ) : null}\n </Text>\n <ThemedTextInput\n accessibilityHint={`Enter ${label}`}\n accessibilityLabel={label}\n describedById={hasError ? errorId : undefined}\n hasError={hasError}\n requiredField={required}\n style={styles.input}\n testID=\"form-field-input\"\n {...textInputProps}\n />\n {hasError ? (\n <Text nativeID={errorId} role=\"alert\" style={[styles.errorText, themeStyles.errorText]}>\n {error}\n </Text>\n ) : null}\n </View>\n );\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 */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, Pressable, TouchableOpacity, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\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\n/** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */\nexport type ChipVariant = 'solid' | 'outline';\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 label: {\n marginBottom: 8,\n fontWeight: '600',\n },\n chipContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n chipWrapper: {\n marginRight: 8,\n marginBottom: 8,\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 muted: string;\n tint: string;\n}\n\nexport interface ChipOption<T> {\n value: T;\n label: string;\n}\n\nexport interface ChipSelectorProps<T> {\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 containerStyle?: ViewStyle;\n}\n\ninterface ChipProps<T> {\n option: ChipOption<T>;\n selected: boolean;\n disabled: boolean;\n colors: ChipColors;\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 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={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected, disabled }}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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 onPress,\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? WHITE_COLOR : colors.textStrong;\n return (\n <TouchableOpacity\n accessibilityHint={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected, disabled }}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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\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}: ChipSelectorProps<T>): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const hasLabel = typeof label === 'string' && label !== '';\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 muted: colors.background,\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\n };\n }, [colors.border, colors.text, colors.textSecondary, colors.background, palette.primary]);\n\n const labelStyle = React.useMemo<TextStyle>(() => ({ color: colors.text }), [colors.text]);\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 return (\n <View style={containerStyle}>\n {hasLabel ? <Text style={[styles.label, labelStyle]}>{label}</Text> : null}\n <View style={styles.chipContainer}>\n {options.map((option) => {\n const selected = isSelected(option.value);\n const onPress = (): void => onChange(option.value);\n return variant === 'outline' ? (\n <OutlineChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n ) : (\n <SolidChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n );\n })}\n </View>\n </View>\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"]}
package/dist/index.mjs CHANGED
@@ -18,6 +18,10 @@ var RED_START = 1;
18
18
  var GREEN_START = 3;
19
19
  var BLUE_START = 5;
20
20
  var CHANNEL_END_OFFSET = 2;
21
+ function prefersReducedMotion() {
22
+ if (!IS_WEB || typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
23
+ return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
24
+ }
21
25
  function withAlpha(color, alpha) {
22
26
  const hex = color.trim();
23
27
  const isHex = hex.charAt(0) === "#" && (hex.length === HEX_FULL_LENGTH || hex.length === HEX_SHORT_LENGTH);
@@ -62,7 +66,8 @@ function useThemedInput(options = {}) {
62
66
  const ring = isFocused && !hasError ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(primary, FOCUS_RING_ALPHA)}` : "none";
63
67
  const webStyle = {
64
68
  transitionProperty: TRANSITION_PROPERTY,
65
- transitionDuration: TRANSITION_DURATION,
69
+ // Collapse the eased transition to instant when the user prefers reduced motion.
70
+ transitionDuration: prefersReducedMotion() ? "0s" : TRANSITION_DURATION,
66
71
  transitionTimingFunction: TRANSITION_TIMING,
67
72
  boxShadow: ring,
68
73
  outlineStyle: "none"
@@ -93,19 +98,26 @@ function useThemedInput(options = {}) {
93
98
  hoverBind
94
99
  };
95
100
  }
96
- var ThemedTextInput = React3.forwardRef(function ThemedTextInput2({ hasError = false, onFocus, onBlur, style, placeholderTextColor, ...rest }, ref) {
101
+ var IS_WEB2 = Platform.OS === "web";
102
+ var ThemedTextInput = React3.forwardRef(function ThemedTextInput2({ hasError = false, describedById, requiredField = false, onFocus, onBlur, style, placeholderTextColor, ...rest }, ref) {
97
103
  const {
98
104
  style: themedStyle,
99
105
  placeholderTextColor: themedPlaceholder,
100
106
  focusBind,
101
107
  hoverBind
102
108
  } = useThemedInput({ hasError, onFocus, onBlur });
109
+ const webA11y = IS_WEB2 ? {
110
+ "aria-invalid": hasError ? true : void 0,
111
+ "aria-describedby": describedById,
112
+ "aria-required": requiredField ? true : void 0
113
+ } : {};
103
114
  return /* @__PURE__ */ jsx(
104
115
  TextInput,
105
116
  {
106
117
  ref,
107
118
  placeholderTextColor: placeholderTextColor ?? themedPlaceholder,
108
119
  ...rest,
120
+ ...webA11y,
109
121
  ...hoverBind,
110
122
  onFocus: focusBind.onFocus,
111
123
  onBlur: focusBind.onBlur,
@@ -139,6 +151,14 @@ var styles = StyleSheet.create({
139
151
  marginTop: 4
140
152
  }
141
153
  });
154
+ var formFieldSeq = 0;
155
+ function useErrorId() {
156
+ const [id] = React3.useState(() => {
157
+ formFieldSeq += 1;
158
+ return `form-field-error-${String(formFieldSeq)}`;
159
+ });
160
+ return id;
161
+ }
142
162
  var FormField = ({
143
163
  label,
144
164
  required = false,
@@ -150,6 +170,7 @@ var FormField = ({
150
170
  const { colors, semantic } = theme;
151
171
  const errorColor = semantic.error["500"];
152
172
  const hasError = typeof error === "string" && error !== "";
173
+ const errorId = useErrorId();
153
174
  const themeStyles = React3.useMemo(
154
175
  () => ({
155
176
  label: { color: colors.textSecondary },
@@ -162,20 +183,25 @@ var FormField = ({
162
183
  /* @__PURE__ */ jsxs(Text, { style: [styles.label, themeStyles.label], children: [
163
184
  label,
164
185
  " ",
165
- required ? /* @__PURE__ */ jsx(Text, { style: themeStyles.requiredMark, children: "*" }) : null
186
+ required ? (
187
+ // The asterisk is decorative — `requiredField` conveys "required" to assistive tech.
188
+ /* @__PURE__ */ jsx(Text, { "aria-hidden": true, accessibilityElementsHidden: true, importantForAccessibility: "no", style: themeStyles.requiredMark, children: "*" })
189
+ ) : null
166
190
  ] }),
167
191
  /* @__PURE__ */ jsx(
168
192
  ThemedTextInput,
169
193
  {
170
194
  accessibilityHint: `Enter ${label}`,
171
195
  accessibilityLabel: label,
196
+ describedById: hasError ? errorId : void 0,
172
197
  hasError,
198
+ requiredField: required,
173
199
  style: styles.input,
174
200
  testID: "form-field-input",
175
201
  ...textInputProps
176
202
  }
177
203
  ),
178
- hasError ? /* @__PURE__ */ jsx(Text, { style: [styles.errorText, themeStyles.errorText], children: error }) : null
204
+ hasError ? /* @__PURE__ */ jsx(Text, { nativeID: errorId, role: "alert", style: [styles.errorText, themeStyles.errorText], children: error }) : null
179
205
  ] });
180
206
  };
181
207
  var TRANSPARENT_COLOR = "transparent";
@@ -192,6 +218,7 @@ var RGB_R_START = 0;
192
218
  var RGB_R_END = 2;
193
219
  var RGB_G_END = 4;
194
220
  var RGB_B_END = 6;
221
+ var CHIP_HIT_SLOP = { top: 10, bottom: 10, left: 4, right: 4 };
195
222
  function withAlpha2(hex, alpha) {
196
223
  const normalized = hex.replace("#", "");
197
224
  const isShort = normalized.length === HEX_SHORT_LENGTH2;
@@ -249,8 +276,9 @@ function OutlineChip({
249
276
  accessibilityHint: `Selects ${option.label}`,
250
277
  accessibilityLabel: option.label,
251
278
  accessibilityRole: "button",
252
- accessibilityState: { selected },
279
+ accessibilityState: { selected, disabled },
253
280
  disabled,
281
+ hitSlop: CHIP_HIT_SLOP,
254
282
  style: styles2.chipWrapper,
255
283
  testID: `chip-selector-chip-${String(option.value)}`,
256
284
  onHoverIn: () => setHovered(true),
@@ -275,8 +303,9 @@ function SolidChip({
275
303
  accessibilityHint: `Selects ${option.label}`,
276
304
  accessibilityLabel: option.label,
277
305
  accessibilityRole: "button",
278
- accessibilityState: { selected },
306
+ accessibilityState: { selected, disabled },
279
307
  disabled,
308
+ hitSlop: CHIP_HIT_SLOP,
280
309
  style: styles2.chipWrapper,
281
310
  testID: `chip-selector-chip-${String(option.value)}`,
282
311
  onPress,
@@ -409,6 +438,7 @@ var FormSwitch = ({
409
438
  }
410
439
  );
411
440
  };
441
+ var ACTIVATION_KEYS = ["Enter", " ", "Spacebar"];
412
442
  var HINT_FONT_SIZE = 12;
413
443
  var BOX_SIZE = 20;
414
444
  var BOX_RADIUS = 5;
@@ -477,6 +507,14 @@ var FormCheckbox = ({
477
507
  if (onValueChange) onValueChange(next);
478
508
  if (onChange) onChange(next);
479
509
  };
510
+ const handleKeyDown = (event) => {
511
+ if (disabled) return;
512
+ const key = event.key ?? "";
513
+ if (!ACTIVATION_KEYS.includes(key)) return;
514
+ if (typeof event.preventDefault === "function") event.preventDefault();
515
+ toggle();
516
+ };
517
+ const keyboardProps = Platform.OS === "web" ? { onKeyDown: handleKeyDown } : {};
480
518
  return /* @__PURE__ */ jsxs(
481
519
  Pressable,
482
520
  {
@@ -490,6 +528,7 @@ var FormCheckbox = ({
490
528
  role: "checkbox",
491
529
  style: [styles4.container, containerStyle, disabled ? { opacity: DISABLED_OPACITY } : null],
492
530
  testID,
531
+ ...keyboardProps,
493
532
  children: [
494
533
  /* @__PURE__ */ jsx(View, { style: [styles4.box, value ? themeStyles.boxOn : themeStyles.boxOff], children: value ? /* @__PURE__ */ jsx(Text, { style: [styles4.check, { color: colors.surface }], accessibilityElementsHidden: true, children: "\u2713" }) : null }),
495
534
  /* @__PURE__ */ jsxs(View, { style: styles4.textColumn, children: [
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/useThemedInput/useThemedInput.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx"],"names":["React","ThemedTextInput","useUi","jsx","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","styles","StyleSheet","View","Text","jsxs","Pressable"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\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 */\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 const ring =\n isFocused && !hasError ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(primary, FOCUS_RING_ALPHA)}` : 'none';\n const webStyle = {\n transitionProperty: TRANSITION_PROPERTY,\n transitionDuration: 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 { TextInput, type TextInputProps } from 'react-native';\n\nimport { useThemedInput } from '../useThemedInput/useThemedInput';\n\nexport interface ThemedTextInputProps extends TextInputProps {\n /** Render with the error border colour (matches `FormField`'s error treatment). */\n hasError?: boolean;\n}\n\nexport const ThemedTextInput = React.forwardRef<TextInput, ThemedTextInputProps>(function ThemedTextInput(\n { hasError = 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 return (\n <TextInput\n ref={ref}\n placeholderTextColor={placeholderTextColor ?? themedPlaceholder}\n {...rest}\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 input itself is the shared `ThemedTextInput` primitive, so every FormField gets the\n * readable + lively treatment (dark text, subtle off-white rest background, brand focus\n * animation with a soft ring) for free, driven by the active theme.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, type TextInputProps, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\nconst CONTAINER_MARGIN_BOTTOM = 16;\nconst INPUT_PADDING_V = 10;\nconst INPUT_PADDING_H = 12;\nconst INPUT_BORDER_RADIUS = 8;\nconst ERROR_FONT_SIZE = 12;\nconst LABEL_FONT_SIZE = 13;\n\nconst styles = StyleSheet.create({\n container: {\n marginBottom: CONTAINER_MARGIN_BOTTOM,\n },\n label: {\n marginBottom: 4,\n fontSize: LABEL_FONT_SIZE,\n fontWeight: '600',\n },\n input: {\n paddingVertical: INPUT_PADDING_V,\n paddingHorizontal: INPUT_PADDING_H,\n borderRadius: INPUT_BORDER_RADIUS,\n borderWidth: 1,\n },\n errorText: {\n fontSize: ERROR_FONT_SIZE,\n marginTop: 4,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n requiredMark: TextStyle;\n errorText: TextStyle;\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 const { theme } = useUi();\n const { colors, semantic } = theme;\n const errorColor = semantic.error['500'];\n const hasError = typeof error === 'string' && error !== '';\n\n const themeStyles = React.useMemo<ThemeStyles>(\n () => ({\n label: { color: colors.textSecondary },\n requiredMark: { color: errorColor },\n errorText: { color: errorColor },\n }),\n [colors.textSecondary, errorColor],\n );\n\n return (\n <View style={[styles.container, containerStyle]}>\n <Text style={[styles.label, themeStyles.label]}>\n {label} {required ? <Text style={themeStyles.requiredMark}>*</Text> : null}\n </Text>\n <ThemedTextInput\n accessibilityHint={`Enter ${label}`}\n accessibilityLabel={label}\n hasError={hasError}\n style={styles.input}\n testID=\"form-field-input\"\n {...textInputProps}\n />\n {hasError ? <Text style={[styles.errorText, themeStyles.errorText]}>{error}</Text> : null}\n </View>\n );\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 */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, Pressable, TouchableOpacity, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\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/** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */\nexport type ChipVariant = 'solid' | 'outline';\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 label: {\n marginBottom: 8,\n fontWeight: '600',\n },\n chipContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n chipWrapper: {\n marginRight: 8,\n marginBottom: 8,\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 muted: string;\n tint: string;\n}\n\nexport interface ChipOption<T> {\n value: T;\n label: string;\n}\n\nexport interface ChipSelectorProps<T> {\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 containerStyle?: ViewStyle;\n}\n\ninterface ChipProps<T> {\n option: ChipOption<T>;\n selected: boolean;\n disabled: boolean;\n colors: ChipColors;\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 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={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected }}\n disabled={disabled}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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 onPress,\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? WHITE_COLOR : colors.textStrong;\n return (\n <TouchableOpacity\n accessibilityHint={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected }}\n disabled={disabled}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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\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}: ChipSelectorProps<T>): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const hasLabel = typeof label === 'string' && label !== '';\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 muted: colors.background,\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\n };\n }, [colors.border, colors.text, colors.textSecondary, colors.background, palette.primary]);\n\n const labelStyle = React.useMemo<TextStyle>(() => ({ color: colors.text }), [colors.text]);\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 return (\n <View style={containerStyle}>\n {hasLabel ? <Text style={[styles.label, labelStyle]}>{label}</Text> : null}\n <View style={styles.chipContainer}>\n {options.map((option) => {\n const selected = isSelected(option.value);\n const onPress = (): void => onChange(option.value);\n return variant === 'outline' ? (\n <OutlineChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n ) : (\n <SolidChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n );\n })}\n </View>\n </View>\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 { StyleSheet, View, Text, Pressable, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\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 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 >\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"]}
1
+ {"version":3,"sources":["../src/useThemedInput/useThemedInput.ts","../src/ThemedTextInput/ThemedTextInput.tsx","../src/FormField/FormField.tsx","../src/ChipSelector/ChipSelector.tsx","../src/FormSwitch/FormSwitch.tsx","../src/FormCheckbox/FormCheckbox.tsx"],"names":["IS_WEB","Platform","React","ThemedTextInput","useUi","jsx","HEX_SHORT_LENGTH","HEX_RADIX","withAlpha","styles","StyleSheet","View","Text","jsxs","Pressable"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\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 const ring =\n isFocused && !hasError ? `0 0 0 ${FOCUS_RING_WIDTH}px ${withAlpha(primary, 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 input itself is the shared `ThemedTextInput` primitive, so every FormField gets the\n * readable + lively treatment (dark text, subtle off-white rest background, brand focus\n * animation with a soft ring) for free, driven by the active theme.\n */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, type TextInputProps, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\n\nimport { ThemedTextInput } from '../ThemedTextInput/ThemedTextInput';\n\nconst CONTAINER_MARGIN_BOTTOM = 16;\nconst INPUT_PADDING_V = 10;\nconst INPUT_PADDING_H = 12;\nconst INPUT_BORDER_RADIUS = 8;\nconst ERROR_FONT_SIZE = 12;\nconst LABEL_FONT_SIZE = 13;\n\nconst styles = StyleSheet.create({\n container: {\n marginBottom: CONTAINER_MARGIN_BOTTOM,\n },\n label: {\n marginBottom: 4,\n fontSize: LABEL_FONT_SIZE,\n fontWeight: '600',\n },\n input: {\n paddingVertical: INPUT_PADDING_V,\n paddingHorizontal: INPUT_PADDING_H,\n borderRadius: INPUT_BORDER_RADIUS,\n borderWidth: 1,\n },\n errorText: {\n fontSize: ERROR_FONT_SIZE,\n marginTop: 4,\n },\n});\n\ninterface ThemeStyles {\n label: TextStyle;\n requiredMark: TextStyle;\n errorText: TextStyle;\n}\n\nexport interface FormFieldProps extends Omit<TextInputProps, 'style'> {\n label: string;\n required?: boolean;\n error?: string;\n containerStyle?: ViewStyle;\n}\n\nlet formFieldSeq = 0;\n/** Stable-per-instance id so the error line can be linked to the input via aria-describedby. */\nfunction useErrorId(): string {\n const [id] = React.useState(() => {\n formFieldSeq += 1;\n return `form-field-error-${String(formFieldSeq)}`;\n });\n return id;\n}\n\nexport const FormField = ({\n label,\n required = false,\n error,\n containerStyle,\n ...textInputProps\n}: FormFieldProps): React.ReactElement => {\n const { theme } = useUi();\n const { colors, semantic } = theme;\n const errorColor = semantic.error['500'];\n const hasError = typeof error === 'string' && error !== '';\n const errorId = useErrorId();\n\n const themeStyles = React.useMemo<ThemeStyles>(\n () => ({\n label: { color: colors.textSecondary },\n requiredMark: { color: errorColor },\n errorText: { color: errorColor },\n }),\n [colors.textSecondary, errorColor],\n );\n\n return (\n <View style={[styles.container, containerStyle]}>\n <Text style={[styles.label, themeStyles.label]}>\n {label}{' '}\n {required ? (\n // The asterisk is decorative — `requiredField` conveys \"required\" to assistive tech.\n <Text aria-hidden accessibilityElementsHidden importantForAccessibility=\"no\" style={themeStyles.requiredMark}>\n *\n </Text>\n ) : null}\n </Text>\n <ThemedTextInput\n accessibilityHint={`Enter ${label}`}\n accessibilityLabel={label}\n describedById={hasError ? errorId : undefined}\n hasError={hasError}\n requiredField={required}\n style={styles.input}\n testID=\"form-field-input\"\n {...textInputProps}\n />\n {hasError ? (\n <Text nativeID={errorId} role=\"alert\" style={[styles.errorText, themeStyles.errorText]}>\n {error}\n </Text>\n ) : null}\n </View>\n );\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 */\nimport React from 'react';\n\nimport { StyleSheet, View, Text, Pressable, TouchableOpacity, type TextStyle, type ViewStyle } from 'react-native';\n\nimport { useUi } from '@dloizides/ui-feedback';\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\n/** Visual variant. `solid` = filled selected pill (default); `outline` = v1 tinted-outline. */\nexport type ChipVariant = 'solid' | 'outline';\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 label: {\n marginBottom: 8,\n fontWeight: '600',\n },\n chipContainer: {\n flexDirection: 'row',\n flexWrap: 'wrap',\n },\n chipWrapper: {\n marginRight: 8,\n marginBottom: 8,\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 muted: string;\n tint: string;\n}\n\nexport interface ChipOption<T> {\n value: T;\n label: string;\n}\n\nexport interface ChipSelectorProps<T> {\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 containerStyle?: ViewStyle;\n}\n\ninterface ChipProps<T> {\n option: ChipOption<T>;\n selected: boolean;\n disabled: boolean;\n colors: ChipColors;\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 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={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected, disabled }}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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 onPress,\n}: ChipProps<T> & { onPress: () => void }): React.ReactElement {\n const backgroundColor = selected ? colors.primary : TRANSPARENT_COLOR;\n const textColor = selected ? WHITE_COLOR : colors.textStrong;\n return (\n <TouchableOpacity\n accessibilityHint={`Selects ${option.label}`}\n accessibilityLabel={option.label}\n accessibilityRole=\"button\"\n accessibilityState={{ selected, disabled }}\n disabled={disabled}\n hitSlop={CHIP_HIT_SLOP}\n style={styles.chipWrapper}\n testID={`chip-selector-chip-${String(option.value)}`}\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\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}: ChipSelectorProps<T>): React.ReactElement => {\n const { theme } = useUi();\n const { colors, palette } = theme;\n const hasLabel = typeof label === 'string' && label !== '';\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 muted: colors.background,\n tint: withAlpha(primary, OUTLINE_TINT_ALPHA),\n };\n }, [colors.border, colors.text, colors.textSecondary, colors.background, palette.primary]);\n\n const labelStyle = React.useMemo<TextStyle>(() => ({ color: colors.text }), [colors.text]);\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 return (\n <View style={containerStyle}>\n {hasLabel ? <Text style={[styles.label, labelStyle]}>{label}</Text> : null}\n <View style={styles.chipContainer}>\n {options.map((option) => {\n const selected = isSelected(option.value);\n const onPress = (): void => onChange(option.value);\n return variant === 'outline' ? (\n <OutlineChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n ) : (\n <SolidChip\n key={String(option.value)}\n colors={chipColors}\n disabled={disabled}\n option={option}\n selected={selected}\n onPress={onPress}\n />\n );\n })}\n </View>\n </View>\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"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dloizides/ui-forms",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "Themable, brand-agnostic React Native (RN-web) form components — FormField, ChipSelector, FormSwitch — sharing the @dloizides/ui-feedback UI context. Part of the dloizides.com shared UI kit.",
5
5
  "keywords": [
6
6
  "react",