@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 +18 -0
- package/dist/index.d.mts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +45 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +45 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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
|
-
|
|
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
|
|
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 ?
|
|
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
|
-
|
|
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
|
|
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 ?
|
|
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: [
|
package/dist/index.mjs.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":["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
|
+
"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",
|