@scripso-homepad/ui 0.4.18 → 0.4.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scripso-homepad/ui",
3
- "version": "0.4.18",
3
+ "version": "0.4.19",
4
4
  "type": "module",
5
5
  "description": "Cross-platform UI components for Homepad (React Web + React Native)",
6
6
  "license": "MIT",
@@ -213,6 +213,7 @@ const styles = StyleSheet.create({
213
213
  },
214
214
  withIcon: {
215
215
  justifyContent: "space-between",
216
+ gap: 24,
216
217
  },
217
218
  disabled: {
218
219
  opacity: 0.6,
@@ -227,7 +228,6 @@ const styles = StyleSheet.create({
227
228
  labelWithIcon: {
228
229
  flex: 1,
229
230
  flexShrink: 1,
230
- marginRight: 8,
231
231
  },
232
232
  iconContainer: {
233
233
  alignItems: "center",
@@ -77,6 +77,38 @@ export interface InputProps extends TextInputProps {
77
77
  showPasswordToggle?: boolean;
78
78
  }
79
79
 
80
+ const INTEGER_KEYBOARD_TYPES = new Set([
81
+ "numeric",
82
+ "number-pad",
83
+ "phone-pad",
84
+ ]);
85
+
86
+ /** Strip non-digits for integer pads; keep one decimal separator for decimal-pad. */
87
+ function sanitizeNumericInput(
88
+ value: string,
89
+ keyboardType: TextInputProps["keyboardType"],
90
+ ): string {
91
+ if (keyboardType === "decimal-pad") {
92
+ const normalized = value.replace(/,/g, ".").replace(/[^\d.]/g, "");
93
+ const separatorIndex = normalized.indexOf(".");
94
+
95
+ if (separatorIndex === -1) {
96
+ return normalized;
97
+ }
98
+
99
+ return (
100
+ normalized.slice(0, separatorIndex + 1) +
101
+ normalized.slice(separatorIndex + 1).replace(/\./g, "")
102
+ );
103
+ }
104
+
105
+ if (keyboardType && INTEGER_KEYBOARD_TYPES.has(keyboardType)) {
106
+ return value.replace(/\D/g, "");
107
+ }
108
+
109
+ return value;
110
+ }
111
+
80
112
  export function Input({
81
113
  label,
82
114
  leftIcon,
@@ -99,6 +131,8 @@ export function Input({
99
131
  showPasswordToggle,
100
132
  onFocus,
101
133
  onBlur,
134
+ onChangeText,
135
+ keyboardType,
102
136
  multiline,
103
137
  textAlignVertical,
104
138
  ...props
@@ -143,6 +177,10 @@ export function Input({
143
177
  onBlur?.(event);
144
178
  }
145
179
 
180
+ function handleChangeText(value: string) {
181
+ onChangeText?.(sanitizeNumericInput(value, keyboardType));
182
+ }
183
+
146
184
  const helperMessage = error ?? hint;
147
185
 
148
186
  function togglePasswordVisibility() {
@@ -198,6 +236,7 @@ export function Input({
198
236
  ]}
199
237
  placeholderTextColor={fieldStyles.placeholder}
200
238
  editable={editable}
239
+ keyboardType={keyboardType}
201
240
  multiline={multiline}
202
241
  secureTextEntry={effectiveSecureTextEntry}
203
242
  textAlign="left"
@@ -206,6 +245,7 @@ export function Input({
206
245
  onBlur={handleBlur}
207
246
  accessibilityState={{ disabled: isDisabled }}
208
247
  {...props}
248
+ onChangeText={handleChangeText}
209
249
  />
210
250
  {trailingIcon ? (
211
251
  <View style={styles.iconSlot}>{trailingIcon}</View>
@@ -39,6 +39,11 @@ export interface PhoneInputProps extends Omit<TextInputProps, "style"> {
39
39
  hintClassName?: string;
40
40
  }
41
41
 
42
+ /** National phone field: digits only (blocks pasted letters/symbols). */
43
+ function sanitizePhoneDigits(value: string): string {
44
+ return value.replace(/\D/g, "");
45
+ }
46
+
42
47
  export function PhoneInput({
43
48
  label,
44
49
  countryCode,
@@ -56,6 +61,7 @@ export function PhoneInput({
56
61
  editable = true,
57
62
  onFocus,
58
63
  onBlur,
64
+ onChangeText,
59
65
  ...props
60
66
  }: PhoneInputProps) {
61
67
  const wrapperRef = useRef<ComponentRef<typeof View>>(null);
@@ -85,6 +91,10 @@ export function PhoneInput({
85
91
  onBlur?.(event);
86
92
  }
87
93
 
94
+ function handleChangeText(value: string) {
95
+ onChangeText?.(sanitizePhoneDigits(value));
96
+ }
97
+
88
98
  const helperMessage = error ?? hint;
89
99
 
90
100
  return (
@@ -129,6 +139,7 @@ export function PhoneInput({
129
139
  onBlur={handleBlur}
130
140
  accessibilityState={{ disabled: isDisabled }}
131
141
  {...props}
142
+ onChangeText={handleChangeText}
132
143
  />
133
144
  </View>
134
145
  </View>
@@ -309,14 +309,6 @@ export function Select({
309
309
  outputRange: ["0deg", "180deg"],
310
310
  });
311
311
 
312
- const hasError = Boolean(error) || Boolean(invalid);
313
- const visualState = resolveInputVisualState({
314
- focused: open,
315
- error: hasError,
316
- disabled,
317
- });
318
- const fieldStyles = getSelectFieldStyles(visualState);
319
-
320
312
  const selectedValues = useMemo(
321
313
  () => normalizeSelectedValues(multiple, value),
322
314
  [multiple, value],
@@ -330,6 +322,15 @@ export function Select({
330
322
  () => options.filter((option) => !option.disabled),
331
323
  [options],
332
324
  );
325
+ // Empty option lists cannot open — treat as disabled so the field does not look interactive.
326
+ const isEffectivelyDisabled = disabled || selectableOptions.length === 0;
327
+ const hasError = Boolean(error) || Boolean(invalid);
328
+ const visualState = resolveInputVisualState({
329
+ focused: open,
330
+ error: hasError,
331
+ disabled: isEffectivelyDisabled,
332
+ });
333
+ const fieldStyles = getSelectFieldStyles(visualState);
333
334
  const selectableIndexByValue = useMemo(
334
335
  () =>
335
336
  new Map(
@@ -364,7 +365,7 @@ export function Select({
364
365
  }
365
366
 
366
367
  function openMenu() {
367
- if (disabled || selectableOptions.length === 0) {
368
+ if (isEffectivelyDisabled) {
368
369
  return;
369
370
  }
370
371
 
@@ -425,7 +426,7 @@ export function Select({
425
426
  return (
426
427
  <View ref={wrapperRef} style={[styles.wrapper, containerStyle]}>
427
428
  {label ? (
428
- <Label disabled={disabled} style={styles.label} className={labelClassName}>
429
+ <Label disabled={isEffectivelyDisabled} style={styles.label} className={labelClassName}>
429
430
  {label}
430
431
  </Label>
431
432
  ) : null}
@@ -434,8 +435,8 @@ export function Select({
434
435
  <Pressable
435
436
  ref={triggerRef}
436
437
  accessibilityRole="button"
437
- accessibilityState={{ disabled, expanded: open }}
438
- disabled={disabled}
438
+ accessibilityState={{ disabled: isEffectivelyDisabled, expanded: open }}
439
+ disabled={isEffectivelyDisabled}
439
440
  onPress={open ? closeMenu : openMenu}
440
441
  style={[selectFieldMetrics.container, fieldStyles.container, fieldStyle]}
441
442
  >
@@ -466,7 +467,7 @@ export function Select({
466
467
  >
467
468
  <ChevronDownIcon
468
469
  size={SELECT_CHEVRON_SIZE}
469
- color={disabled ? colors.stormGray200 : SELECT_CHEVRON_COLOR}
470
+ color={isEffectivelyDisabled ? colors.stormGray200 : SELECT_CHEVRON_COLOR}
470
471
  />
471
472
  </Animated.View>
472
473
  </Pressable>
@@ -479,7 +480,13 @@ export function Select({
479
480
  ) : null}
480
481
 
481
482
  <Modal visible={open} transparent animationType="fade" onRequestClose={closeMenu}>
482
- <Pressable style={styles.overlay} onPress={closeMenu}>
483
+ <View style={styles.overlay}>
484
+ <Pressable
485
+ style={styles.backdrop}
486
+ onPress={closeMenu}
487
+ accessibilityRole="button"
488
+ accessibilityLabel="Close"
489
+ />
483
490
  {anchor ? (
484
491
  <View
485
492
  ref={menuRef}
@@ -511,7 +518,7 @@ export function Select({
511
518
  )}
512
519
  </View>
513
520
  ) : null}
514
- </Pressable>
521
+ </View>
515
522
  </Modal>
516
523
  </View>
517
524
  );
@@ -539,10 +546,14 @@ const styles = StyleSheet.create({
539
546
  },
540
547
  overlay: {
541
548
  flex: 1,
549
+ },
550
+ backdrop: {
551
+ ...StyleSheet.absoluteFillObject,
542
552
  backgroundColor: colors.transparent,
543
553
  },
544
554
  dropdown: {
545
555
  position: "absolute",
556
+ zIndex: 1,
546
557
  },
547
558
  dropdownScroll: {
548
559
  flex: 1,
@@ -215,7 +215,7 @@ export function TableActionsMenu({
215
215
  <TableActionButton
216
216
  ref={triggerRef}
217
217
  variant="menu"
218
- icon={<TableMoreIcon className="size-6" />}
218
+ icon={<TableMoreIcon className="size-5" />}
219
219
  ariaLabel={triggerAriaLabel}
220
220
  onClick={() => setOpen((current) => !current)}
221
221
  aria-expanded={open}
@@ -4,7 +4,7 @@
4
4
  }
5
5
 
6
6
  .drawer-scroll-area::-webkit-scrollbar {
7
- width: 8px;
7
+ width: 4px;
8
8
  -webkit-appearance: none;
9
9
  appearance: none;
10
10
  }
@@ -33,9 +33,3 @@
33
33
  background-color: var(--color-storm-gray-200, #d5d9dd);
34
34
  border-radius: 9999px;
35
35
  }
36
-
37
- @media (max-width: 767px) {
38
- .drawer-scroll-area::-webkit-scrollbar {
39
- width: 4px;
40
- }
41
- }
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/theme/tokens.ts","../src/icons/arrowUpRightPath.ts","../src/icons/ArrowUpRightIcon.tsx","../src/utils/useApplyWebClassName.ts","../src/components/Button.tsx","../src/components/Label.tsx","../src/icons/eyeIconPaths.ts","../src/icons/EyeIcon.tsx","../src/icons/EyeOffIcon.tsx","../src/theme/input.ts","../src/components/Input.tsx"],"names":["Platform","jsx","useRef","jsxs","Text","styles","StyleSheet","Svg","Path","View"],"mappings":"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","file":"chunk-U7OSCJKA.js","sourcesContent":["/**\n * HomePad design tokens — aligned with the Figma design system\n * (navy / storm gray / slate-blue palette from HomePad brand).\n */\n\n/** Storm Gray scale — Figma steps 0 → 8.5 */\nexport const stormGray = {\n \"0\": \"#fbfcfc\",\n \"0.5\": \"#eceef0\",\n \"1\": \"#dadde0\",\n \"1.5\": \"#c7cdd1\",\n \"2\": \"#b5bcc1\",\n \"3\": \"#8f9aa3\",\n \"4\": \"#6a7984\",\n \"5\": \"#455765\",\n \"6\": \"#374651\",\n \"7\": \"#29343d\",\n \"8\": \"#1c2328\",\n \"8.5\": \"#151a1e\",\n} as const;\n\nexport type StormGrayStep = keyof typeof stormGray;\n\n/** Navy scale — Figma steps 0 → 8.5 */\nexport const navy = {\n \"0\": \"#f6fafe\",\n \"0.5\": \"#dee5eb\",\n \"1\": \"#c6d0d8\",\n \"1.5\": \"#afbac5\",\n \"2\": \"#97a5b2\",\n \"3\": \"#677b8c\",\n \"4\": \"#385066\",\n \"5\": \"#082640\",\n \"6\": \"#061e33\",\n \"7\": \"#051726\",\n \"8\": \"#030f1a\",\n \"8.5\": \"#020b13\",\n} as const;\n\nexport type NavyStep = keyof typeof navy;\n\n/** Ruby Red scale — Figma steps 0 → 8.5 */\nexport const rubyRed = {\n \"0\": \"#fff5f6\",\n \"0.5\": \"#f7dddf\",\n \"1\": \"#efc4c8\",\n \"1.5\": \"#e7acb1\",\n \"2\": \"#df939a\",\n \"3\": \"#ce626d\",\n \"4\": \"#be313f\",\n \"5\": \"#ae0011\",\n \"6\": \"#8b000e\",\n \"7\": \"#68000a\",\n \"8\": \"#460007\",\n \"8.5\": \"#340005\",\n} as const;\n\nexport type RubyRedStep = keyof typeof rubyRed;\n\n/** Emerald Green scale — Figma steps 0 → 8.5 */\nexport const emeraldGreen = {\n \"0\": \"#f0fbf5\",\n \"0.5\": \"#dcf2e5\",\n \"1\": \"#c8e8d5\",\n \"1.5\": \"#b4dfc5\",\n \"2\": \"#a0d5b5\",\n \"3\": \"#77c394\",\n \"4\": \"#4fb074\",\n \"5\": \"#279d54\",\n \"6\": \"#1f7e43\",\n \"7\": \"#175e32\",\n \"8\": \"#103f22\",\n \"8.5\": \"#0c2f19\",\n} as const;\n\nexport type EmeraldGreenStep = keyof typeof emeraldGreen;\n\n/** Figma brand palette — primary swatch per color family */\nexport const brand = {\n slateBlue: \"#182e3c\",\n stormGray: stormGray[\"5\"],\n navy: navy[\"5\"],\n rubyRed: rubyRed[\"5\"],\n emeraldGreen: emeraldGreen[\"5\"],\n} as const;\n\nexport const colors = {\n // Brand colors\n slateBlue: brand.slateBlue,\n\n // Emerald Green — Figma scale + brand swatch\n emeraldGreen0: emeraldGreen[\"0\"],\n emeraldGreen50: emeraldGreen[\"0.5\"],\n emeraldGreen100: emeraldGreen[\"1\"],\n emeraldGreen150: emeraldGreen[\"1.5\"],\n emeraldGreen200: emeraldGreen[\"2\"],\n emeraldGreen300: emeraldGreen[\"3\"],\n emeraldGreen400: emeraldGreen[\"4\"],\n emeraldGreen500: emeraldGreen[\"5\"],\n emeraldGreen600: emeraldGreen[\"6\"],\n emeraldGreen700: emeraldGreen[\"7\"],\n emeraldGreen800: emeraldGreen[\"8\"],\n emeraldGreen850: emeraldGreen[\"8.5\"],\n\n /** Primary brand emerald green — Figma Emerald Green 5 */\n emeraldGreen: brand.emeraldGreen,\n\n // Ruby Red — Figma scale + brand swatch\n rubyRed0: rubyRed[\"0\"],\n rubyRed50: rubyRed[\"0.5\"],\n rubyRed100: rubyRed[\"1\"],\n rubyRed150: rubyRed[\"1.5\"],\n rubyRed200: rubyRed[\"2\"],\n rubyRed300: rubyRed[\"3\"],\n rubyRed400: rubyRed[\"4\"],\n rubyRed500: rubyRed[\"5\"],\n rubyRed600: rubyRed[\"6\"],\n rubyRed700: rubyRed[\"7\"],\n rubyRed800: rubyRed[\"8\"],\n rubyRed850: rubyRed[\"8.5\"],\n\n /** Primary brand ruby red — Figma Ruby Red 5 */\n rubyRed: brand.rubyRed,\n\n // Navy — Figma scale + brand swatch\n navy0: navy[\"0\"],\n navy50: navy[\"0.5\"],\n navy100: navy[\"1\"],\n navy150: navy[\"1.5\"],\n navy200: navy[\"2\"],\n navy300: navy[\"3\"],\n navy400: navy[\"4\"],\n navy500: navy[\"5\"],\n navy600: navy[\"6\"],\n navy700: navy[\"7\"],\n navy800: navy[\"8\"],\n navy850: navy[\"8.5\"],\n\n /** Primary brand navy — Figma Navy 5 */\n navy: brand.navy,\n\n // Storm Gray — Figma scale + brand swatch\n stormGray0: stormGray[\"0\"],\n stormGray50: stormGray[\"0.5\"],\n stormGray100: stormGray[\"1\"],\n stormGray150: stormGray[\"1.5\"],\n stormGray200: stormGray[\"2\"],\n stormGray300: stormGray[\"3\"],\n stormGray400: stormGray[\"4\"],\n stormGray500: stormGray[\"5\"],\n /** Figma brand swatch \"Storm Gray\" — same as `stormGray500` */\n stormGrayBrand: brand.stormGray,\n stormGray600: stormGray[\"6\"],\n stormGray700: stormGray[\"7\"],\n stormGray800: stormGray[\"8\"],\n stormGray850: stormGray[\"8.5\"],\n\n /** @deprecated Use `stormGray0` */\n storm0: stormGray[\"0\"],\n /** @deprecated Use `stormGray50` */\n storm50: stormGray[\"0.5\"],\n /** @deprecated Use `stormGray200` */\n storm200: stormGray[\"2\"],\n /** @deprecated Use `stormGray300` */\n storm300: stormGray[\"3\"],\n /** @deprecated Use `stormGray500` */\n storm500: stormGray[\"5\"],\n /** @deprecated Use `stormGray700` */\n storm700: stormGray[\"7\"],\n /** @deprecated Use `stormGray850` */\n storm900: stormGray[\"8.5\"],\n\n countrySelectorSelectedBg: `${stormGray[\"0.5\"]}99`,\n\n white: \"#ffffff\",\n error: \"#dc2626\",\n errorDark: \"#b3261e\",\n errorLight: \"#fee2e2\",\n /** @deprecated Use `rubyRed` */\n inputError: brand.rubyRed,\n inputOutlineFocus: navy[\"0.5\"],\n inputOutlineError: rubyRed[\"0.5\"],\n warning: \"#92400e\",\n warningBg: \"#fef3c7\",\n success: \"#28a745\",\n successMuted: \"#9fd4a8\",\n /** @deprecated Use `emeraldGreen` */\n green: brand.emeraldGreen,\n transparent: \"transparent\",\n} as const;\n\nexport const radii = {\n sm: 8,\n md: 12,\n lg: 16,\n xl: 20,\n full: 9999,\n} as const;\n\nexport const spacing = {\n xs: 4,\n sm: 8,\n md: 12,\n lg: 16,\n xl: 24,\n xxl: 32,\n} as const;\n\nexport const fontSize = {\n xs: 11,\n sm: 12,\n md: 14,\n base: 16,\n lg: 18,\n xl: 24,\n xxl: 32,\n} as const;\n\n/**\n * Canonical Homepad type scale (matches `.typography-*` in `src/web/styles/typography.css`).\n * font-size / line-height pairs:\n * 12/16 · 14/19 · 18/24 · 20/27 · 24/25 · 32/34\n */\nexport const typographyScale = {\n 12: { fontSize: 12, lineHeight: 16 },\n 14: { fontSize: 14, lineHeight: 19 },\n 18: { fontSize: 18, lineHeight: 24 },\n 20: { fontSize: 20, lineHeight: 27 },\n 24: { fontSize: 24, lineHeight: 25 },\n 32: { fontSize: 32, lineHeight: 34 },\n} as const;\n\nexport const fontWeight = {\n regular: \"400\" as const,\n medium: \"500\" as const,\n semibold: \"600\" as const,\n bold: \"700\" as const,\n};\n\nexport const fonts = {\n sans: \"Noto Sans Armenian\",\n} as const;\n\n/** Input label typography — Medium, typography-12 scale. */\nexport const labelTypography = {\n fontFamily: fonts.sans,\n fontSize: typographyScale[12].fontSize,\n fontWeight: fontWeight.medium,\n lineHeight: typographyScale[12].lineHeight,\n letterSpacing: 0,\n} as const;\n\n/** Button label typography — SemiBold. */\nexport const buttonTypography = {\n lg: {\n fontFamily: fonts.sans,\n fontSize: typographyScale[14].fontSize,\n fontWeight: fontWeight.semibold,\n lineHeight: typographyScale[14].lineHeight,\n letterSpacing: 0,\n },\n sm: {\n fontFamily: fonts.sans,\n fontSize: typographyScale[12].fontSize,\n fontWeight: fontWeight.semibold,\n lineHeight: typographyScale[12].lineHeight,\n letterSpacing: 0,\n },\n} as const;\n\nexport const shadows = {\n card: {\n shadowColor: colors.navy,\n shadowOffset: { width: 0, height: 4 },\n shadowOpacity: 0.05,\n shadowRadius: 20,\n elevation: 2,\n },\n cardLg: {\n shadowColor: colors.navy,\n shadowOffset: { width: 0, height: 4 },\n shadowOpacity: 0.1,\n shadowRadius: 20,\n elevation: 4,\n },\n} as const;\n","export const ARROW_UP_RIGHT_PATH =\n \"M14.1667 14.1668V5.8335H5.83333M14.1667 5.8335L5.83333 14.1668\";\n","import Svg, { Path } from \"react-native-svg\";\nimport { ARROW_UP_RIGHT_PATH } from \"./arrowUpRightPath\";\n\nexport { ARROW_UP_RIGHT_PATH } from \"./arrowUpRightPath\";\n\ninterface ArrowUpRightIconProps {\n size?: number;\n color?: string;\n strokeWidth?: number;\n}\n\n/** Native — react-native-svg (peer dependency). */\nexport function ArrowUpRightIcon({\n size = 20,\n color = \"#082640\",\n strokeWidth = 2,\n}: ArrowUpRightIconProps) {\n return (\n <Svg width={size} height={size} viewBox=\"0 0 20 20\" fill=\"none\">\n <Path\n d={ARROW_UP_RIGHT_PATH}\n stroke={color}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </Svg>\n );\n}\n","import { useLayoutEffect } from \"react\";\nimport { Platform } from \"react-native\";\n\ninterface ClassListElement {\n classList: {\n add: (...classes: string[]) => void;\n remove: (...classes: string[]) => void;\n };\n}\n\nfunction hasClassList(node: unknown): node is ClassListElement {\n return (\n typeof node === \"object\" &&\n node !== null &&\n \"classList\" in node &&\n typeof (node as ClassListElement).classList?.add === \"function\"\n );\n}\n\nfunction resolveWebElement(ref: React.RefObject<unknown>): ClassListElement | null {\n const node = ref.current;\n if (!node) return null;\n\n if (hasClassList(node)) return node;\n\n const host = node as {\n _touchableNode?: unknown;\n getScrollableNode?: () => unknown;\n };\n\n if (hasClassList(host._touchableNode)) return host._touchableNode;\n\n if (typeof host.getScrollableNode === \"function\") {\n const scrollNode = host.getScrollableNode();\n if (hasClassList(scrollNode)) return scrollNode;\n }\n\n return null;\n}\n\n/**\n * Applies CSS class names to the underlying DOM node on web.\n * Keeps TouchableOpacity/Text as the render path so default RN styles stay intact.\n *\n * Retries via rAF when the host node is not ready yet — otherwise classes like\n * `h-13` / `w-full` would only land after a later re-render (e.g. typing in a form),\n * which visibly changes button size.\n */\nexport function useApplyWebClassName(\n ref: React.RefObject<unknown>,\n className?: string,\n enabled = true,\n): void {\n useLayoutEffect(() => {\n if (!enabled || Platform.OS !== \"web\" || !className?.trim()) return;\n\n let cancelled = false;\n let rafId = 0;\n let appliedElement: ClassListElement | null = null;\n const classes = className.trim().split(/\\s+/);\n\n const apply = () => {\n if (cancelled) return;\n\n const element = resolveWebElement(ref);\n if (!element) {\n rafId = requestAnimationFrame(apply);\n return;\n }\n\n appliedElement = element;\n element.classList.add(...classes);\n };\n\n apply();\n\n return () => {\n cancelled = true;\n if (rafId) cancelAnimationFrame(rafId);\n appliedElement?.classList.remove(...classes);\n };\n }, [ref, className, enabled]);\n}\n","import { useRef, type ComponentRef, type ReactNode } from \"react\";\nimport {\n Platform,\n StyleSheet,\n Text,\n TouchableOpacity,\n View,\n type GestureResponderEvent,\n type StyleProp,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\nimport { ArrowUpRightIcon } from \"../icons/ArrowUpRightIcon\";\nimport { colors, buttonTypography } from \"../theme/tokens\";\nimport { useApplyWebClassName } from \"../utils/useApplyWebClassName\";\n\nexport type ButtonVariant = \"white\" | \"primary\" | \"green\" | \"gray\";\nexport type ButtonSize = \"lg\" | \"sm\";\n\nexport interface ButtonProps {\n title?: string;\n children?: ReactNode;\n onPress: (event: GestureResponderEvent) => void;\n disabled?: boolean;\n variant?: ButtonVariant;\n size?: ButtonSize;\n showIcon?: boolean;\n /** Custom icon inside the badge. Defaults to `ArrowUpRightIcon` when `showIcon` is true. */\n icon?: ReactNode;\n style?: StyleProp<ViewStyle>;\n textStyle?: StyleProp<TextStyle>;\n className?: string;\n textClassName?: string;\n}\n\ntype VariantStyleSet = {\n backgroundColor: string;\n textColor: string;\n iconBadgeBackgroundColor: string;\n iconColor: string;\n};\n\nconst variantConfig: Record<ButtonVariant, VariantStyleSet> = {\n white: {\n backgroundColor: colors.white,\n textColor: colors.slateBlue,\n iconBadgeBackgroundColor: colors.stormGray150,\n iconColor: colors.navy,\n },\n primary: {\n backgroundColor: colors.navy,\n textColor: colors.stormGray0,\n iconBadgeBackgroundColor: colors.white,\n iconColor: colors.navy,\n },\n green: {\n backgroundColor: colors.green,\n textColor: colors.stormGray0,\n iconBadgeBackgroundColor: colors.white,\n iconColor: colors.green,\n },\n gray: {\n backgroundColor: colors.stormGray50,\n textColor: colors.slateBlue,\n iconBadgeBackgroundColor: colors.stormGray150,\n iconColor: colors.navy,\n },\n};\n\nconst sizeConfig = {\n lg: {\n /** Matches Tailwind `h-13` so size stays stable before web classNames attach. */\n minHeight: 52,\n borderRadius: 16,\n paddingTop: 8,\n paddingRight: 8,\n paddingBottom: 8,\n paddingLeft: 24,\n paddingHorizontalCentered: 24,\n text: buttonTypography.lg,\n iconContainerSize: 36,\n iconContainerRadius: 12,\n iconContainerPadding: 8,\n iconSize: 20,\n },\n sm: {\n minHeight: 40,\n borderRadius: 12,\n paddingTop: 8,\n paddingRight: 8,\n paddingBottom: 8,\n paddingLeft: 16,\n paddingHorizontalCentered: 16,\n text: buttonTypography.sm,\n iconContainerSize: 32,\n iconContainerRadius: 8,\n iconContainerPadding: 8,\n iconSize: 16,\n },\n} as const;\n\nexport function Button({\n title,\n children,\n onPress,\n disabled = false,\n variant = \"primary\",\n size = \"lg\",\n showIcon = false,\n icon,\n style,\n textStyle,\n className,\n textClassName,\n}: ButtonProps) {\n const containerRef = useRef<ComponentRef<typeof TouchableOpacity>>(null);\n const textRef = useRef<ComponentRef<typeof Text>>(null);\n const preset = variantConfig[variant];\n const metrics = sizeConfig[size];\n\n const label = typeof children !== \"undefined\" ? children : title;\n const hasCustomChildren = typeof children !== \"undefined\";\n const customIcon =\n icon != null && typeof icon !== \"boolean\" ? icon : undefined;\n const hasIcon = showIcon || icon === true || customIcon != null;\n const resolvedContainerClassName = [\n Platform.OS === \"web\" ? \"max-md:px-4!\" : \"\",\n className,\n ]\n .filter(Boolean)\n .join(\" \");\n\n useApplyWebClassName(containerRef, resolvedContainerClassName || undefined);\n useApplyWebClassName(textRef, textClassName);\n\n const iconNode =\n customIcon ?? (\n <ArrowUpRightIcon size={metrics.iconSize} color={preset.iconColor} />\n );\n\n const containerStyle = [\n styles.base,\n {\n minHeight: metrics.minHeight,\n borderRadius: metrics.borderRadius,\n backgroundColor: preset.backgroundColor,\n paddingTop: metrics.paddingTop,\n paddingBottom: metrics.paddingBottom,\n paddingLeft: hasIcon ? metrics.paddingLeft : metrics.paddingHorizontalCentered,\n paddingRight: hasIcon ? metrics.paddingRight : metrics.paddingHorizontalCentered,\n },\n hasIcon ? styles.withIcon : styles.centered,\n disabled && styles.disabled,\n style,\n ];\n\n const labelStyle = [\n styles.label,\n metrics.text,\n { color: preset.textColor },\n Platform.OS === \"android\" ? styles.labelAndroid : null,\n !hasIcon && styles.labelCentered,\n hasIcon && styles.labelWithIcon,\n textStyle,\n ];\n\n return (\n <TouchableOpacity\n ref={containerRef}\n style={containerStyle}\n onPress={onPress}\n disabled={disabled}\n activeOpacity={0.7}\n accessibilityRole=\"button\"\n accessibilityState={{ disabled }}\n >\n {hasCustomChildren ? (\n children\n ) : (\n <Text ref={textRef} style={labelStyle}>\n {label}\n </Text>\n )}\n\n {hasIcon ? (\n <View\n style={[\n styles.iconContainer,\n {\n width: metrics.iconContainerSize,\n height: metrics.iconContainerSize,\n borderRadius: metrics.iconContainerRadius,\n padding: metrics.iconContainerPadding,\n backgroundColor: preset.iconBadgeBackgroundColor,\n },\n ]}\n >\n {iconNode}\n </View>\n ) : null}\n </TouchableOpacity>\n );\n}\n\nconst styles = StyleSheet.create({\n base: {\n flexDirection: \"row\",\n alignItems: \"center\",\n borderWidth: 0,\n },\n centered: {\n justifyContent: \"center\",\n },\n withIcon: {\n justifyContent: \"space-between\",\n },\n disabled: {\n opacity: 0.6,\n },\n label: {},\n labelAndroid: {\n includeFontPadding: false,\n },\n labelCentered: {\n textAlign: \"center\",\n },\n labelWithIcon: {\n flex: 1,\n flexShrink: 1,\n marginRight: 8,\n },\n iconContainer: {\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n },\n});\n","import { useRef, type ComponentRef, type ReactNode } from \"react\";\nimport {\n StyleSheet,\n Text,\n type StyleProp,\n type TextProps,\n type TextStyle,\n} from \"react-native\";\nimport { colors, labelTypography } from \"../theme/tokens\";\nimport { useApplyWebClassName } from \"../utils/useApplyWebClassName\";\n\nexport interface LabelProps extends TextProps {\n children: ReactNode;\n /** Render as a required field indicator. */\n required?: boolean;\n disabled?: boolean;\n style?: StyleProp<TextStyle>;\n className?: string;\n}\n\nexport function Label({\n children,\n required = false,\n disabled = false,\n style,\n className,\n ...props\n}: LabelProps) {\n const ref = useRef<ComponentRef<typeof Text>>(null);\n useApplyWebClassName(ref, className);\n\n return (\n <Text\n ref={ref}\n style={[styles.label, disabled && styles.labelDisabled, style]}\n accessibilityRole=\"text\"\n {...props}\n >\n {children}\n {required ? <Text style={styles.required}> *</Text> : null}\n </Text>\n );\n}\n\nconst styles = StyleSheet.create({\n label: {\n ...labelTypography,\n color: colors.slateBlue,\n },\n labelDisabled: {\n color: colors.stormGray400,\n },\n required: {\n color: colors.inputError,\n },\n});\n","export const EYE_OPEN_OUTLINE_PATH =\n \"M1.71835 10.2898C1.6489 10.1027 1.6489 9.89691 1.71835 9.70981C2.39476 8.06969 3.54294 6.66735 5.01732 5.68056C6.4917 4.69378 8.22588 4.16699 10 4.16699C11.7741 4.16699 13.5083 4.69378 14.9827 5.68056C16.4571 6.66735 17.6053 8.06969 18.2817 9.70981C18.3511 9.89691 18.3511 10.1027 18.2817 10.2898C17.6053 11.9299 16.4571 13.3323 14.9827 14.3191C13.5083 15.3058 11.7741 15.8326 10 15.8326C8.22588 15.8326 6.4917 15.3058 5.01732 14.3191C3.54294 13.3323 2.39476 11.9299 1.71835 10.2898Z\";\n\nexport const EYE_OPEN_PUPIL_PATH =\n \"M10 12.4998C11.3807 12.4998 12.5 11.3805 12.5 9.99981C12.5 8.6191 11.3807 7.49981 10 7.49981C8.6193 7.49981 7.50001 8.6191 7.50001 9.99981C7.50001 11.3805 8.6193 12.4998 10 12.4998Z\";\n\nexport const EYE_OFF_PATH =\n \"M10.733 5.076C13.0624 4.7984 15.4186 5.29082 17.4419 6.47805C19.4651 7.66528 21.0442 9.48208 21.938 11.651C22.0213 11.8755 22.0213 12.1225 21.938 12.347C21.5705 13.238 21.0848 14.0755 20.494 14.837M14.084 14.158C13.5182 14.7045 12.7604 15.0069 11.9738 15C11.1872 14.9932 10.4348 14.6777 9.87854 14.1215C9.32232 13.5652 9.00681 12.8128 8.99998 12.0262C8.99314 11.2396 9.29553 10.4818 9.842 9.916M17.479 17.499C16.1525 18.2848 14.6725 18.776 13.1394 18.9394C11.6063 19.1028 10.056 18.9345 8.59363 18.4459C7.13131 17.9573 5.79119 17.1599 4.66421 16.1077C3.53723 15.0556 2.64975 13.7734 2.062 12.348C1.97866 12.1235 1.97866 11.8765 2.062 11.652C2.94863 9.50186 4.50867 7.69725 6.508 6.509M2 2L22 22\";\n","import Svg, { Path } from \"react-native-svg\";\nimport { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from \"./eyeIconPaths\";\n\nexport { EYE_OPEN_OUTLINE_PATH, EYE_OPEN_PUPIL_PATH } from \"./eyeIconPaths\";\n\ninterface EyeIconProps {\n size?: number;\n color?: string;\n strokeWidth?: number;\n}\n\n/** Native — open eye (password hidden). */\nexport function EyeIcon({\n size = 20,\n color = \"#c7cdd1\",\n strokeWidth = 2,\n}: EyeIconProps) {\n return (\n <Svg width={size} height={size} viewBox=\"0 0 20 20\" fill=\"none\">\n <Path\n d={EYE_OPEN_OUTLINE_PATH}\n stroke={color}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n <Path\n d={EYE_OPEN_PUPIL_PATH}\n stroke={color}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </Svg>\n );\n}\n","import Svg, { Path } from \"react-native-svg\";\nimport { EYE_OFF_PATH } from \"./eyeIconPaths\";\n\nexport { EYE_OFF_PATH } from \"./eyeIconPaths\";\n\ninterface EyeOffIconProps {\n size?: number;\n color?: string;\n strokeWidth?: number;\n}\n\n/** Native — slashed eye (password visible). */\nexport function EyeOffIcon({\n size = 20,\n color = \"#c7cdd1\",\n strokeWidth = 2,\n}: EyeOffIconProps) {\n return (\n <Svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\">\n <Path\n d={EYE_OFF_PATH}\n stroke={color}\n strokeWidth={strokeWidth}\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </Svg>\n );\n}\n","import { Platform, StyleSheet, type TextStyle, type ViewStyle } from \"react-native\";\nimport { colors, fonts, fontSize, fontWeight, radii } from \"./tokens\";\n\nexport const INPUT_HEIGHT = 52;\nexport const INPUT_ICON_SIZE = 20;\nexport const INPUT_ICON_GAP = 10;\nexport const INPUT_OUTLINE_WIDTH = 2;\nexport const INPUT_TEXT_LINE_HEIGHT = 19;\nexport const INPUT_WEB_VERTICAL_PADDING = 14;\n\nexport type InputVisualState =\n | \"default\"\n | \"focused\"\n | \"error\"\n | \"disabled\";\n\nexport interface InputStateFlags {\n focused?: boolean;\n error?: boolean;\n disabled?: boolean;\n}\n\nexport function resolveInputVisualState({\n focused = false,\n error = false,\n disabled = false,\n}: InputStateFlags): InputVisualState {\n if (disabled) return \"disabled\";\n if (error) return \"error\";\n if (focused) return \"focused\";\n return \"default\";\n}\n\ninterface FieldStyleSet {\n container: ViewStyle;\n outline: ViewStyle;\n text: TextStyle;\n placeholder: string;\n icon: string;\n}\n\nfunction createOutlineStyle(ringColor: string): ViewStyle {\n return {\n borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,\n borderWidth: INPUT_OUTLINE_WIDTH,\n borderColor: ringColor,\n padding: 0,\n backgroundColor: colors.transparent,\n width: \"100%\",\n alignSelf: \"stretch\",\n ...(Platform.OS !== \"web\" ? { overflow: \"hidden\" as const } : null),\n };\n}\n\nconst defaultOutline: ViewStyle = {\n borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,\n borderWidth: INPUT_OUTLINE_WIDTH,\n borderColor: colors.transparent,\n padding: 0,\n backgroundColor: colors.transparent,\n width: \"100%\",\n alignSelf: \"stretch\",\n ...(Platform.OS !== \"web\" ? { overflow: \"hidden\" as const } : null),\n};\n\nexport function getInputFieldStyles(state: InputVisualState): FieldStyleSet {\n const containerBase: ViewStyle = {\n borderRadius: radii.lg,\n ...(Platform.OS !== \"web\" ? { overflow: \"hidden\" as const } : null),\n };\n\n switch (state) {\n case \"disabled\":\n return {\n outline: defaultOutline,\n container: {\n ...containerBase,\n borderWidth: 1,\n borderColor: colors.stormGray50,\n backgroundColor: colors.stormGray50,\n },\n text: { color: colors.stormGray300 },\n placeholder: colors.stormGray300,\n icon: colors.stormGray150,\n };\n case \"error\":\n return {\n outline: createOutlineStyle(colors.inputOutlineError),\n container: {\n ...containerBase,\n borderWidth: 1,\n borderColor: colors.inputError,\n backgroundColor: colors.white,\n },\n text: { color: colors.inputError },\n placeholder: colors.stormGray200,\n icon: colors.inputError,\n };\n case \"focused\":\n return {\n outline: createOutlineStyle(colors.inputOutlineFocus),\n container: {\n ...containerBase,\n borderWidth: 1,\n borderColor: colors.navy,\n backgroundColor: colors.white,\n },\n text: { color: colors.slateBlue },\n placeholder: colors.stormGray200,\n icon: colors.navy,\n };\n default:\n return {\n outline: defaultOutline,\n container: {\n ...containerBase,\n borderWidth: 1,\n borderColor: colors.stormGray50,\n backgroundColor: colors.white,\n },\n text: { color: colors.slateBlue },\n placeholder: colors.stormGray200,\n icon: colors.stormGray150,\n };\n }\n}\n\nexport const inputFieldMetrics = StyleSheet.create({\n container: {\n flexDirection: \"row\",\n alignItems: \"center\",\n height: INPUT_HEIGHT,\n borderRadius: radii.lg,\n padding: 16,\n gap: INPUT_ICON_GAP,\n ...(Platform.OS === \"web\"\n ? ({\n boxSizing: \"border-box\",\n paddingVertical: INPUT_WEB_VERTICAL_PADDING,\n paddingHorizontal: 16,\n } as ViewStyle)\n : null),\n },\n input: {\n flex: 1,\n minWidth: 0,\n width: \"100%\",\n fontFamily: fonts.sans,\n fontSize: fontSize.md,\n fontWeight: fontWeight.medium,\n paddingVertical: 0,\n paddingHorizontal: 0,\n margin: 0,\n borderWidth: 0,\n backgroundColor: colors.transparent,\n ...(Platform.OS === \"android\"\n ? { includeFontPadding: false }\n : null),\n ...(Platform.OS === \"ios\"\n ? { lineHeight: INPUT_TEXT_LINE_HEIGHT, paddingVertical: 2 }\n : null),\n ...(Platform.OS === \"web\"\n ? ({\n alignSelf: \"center\",\n outlineStyle: \"none\",\n lineHeight: INPUT_TEXT_LINE_HEIGHT,\n } as TextStyle)\n : {\n alignSelf: \"stretch\",\n }),\n },\n /** Single-line: avoid Android lineHeight jump between placeholder and typed text. */\n inputSingleLine: {\n ...(Platform.OS === \"android\"\n ? ({ textAlignVertical: \"center\" } as TextStyle)\n : null),\n },\n});\n","import {\n cloneElement,\n isValidElement,\n useRef,\n useState,\n type ComponentRef,\n type ReactNode,\n} from \"react\";\nimport {\n Pressable,\n StyleSheet,\n Text,\n TextInput,\n View,\n type NativeSyntheticEvent,\n type StyleProp,\n type TextInputFocusEventData,\n type TextInputProps,\n type TextStyle,\n type ViewStyle,\n} from \"react-native\";\nimport { EyeIcon } from \"../icons/EyeIcon\";\nimport { EyeOffIcon } from \"../icons/EyeOffIcon\";\nimport {\n getInputFieldStyles,\n inputFieldMetrics,\n INPUT_ICON_SIZE,\n resolveInputVisualState,\n} from \"../theme/input\";\nimport { colors, spacing } from \"../theme/tokens\";\nimport { useApplyWebClassName } from \"../utils/useApplyWebClassName\";\nimport { Label } from \"./Label\";\n\ntype InputIconProps = {\n size?: number;\n color?: string;\n};\n\nfunction renderInputIcon(icon: ReactNode, color: string) {\n if (!icon) return null;\n\n if (isValidElement<InputIconProps>(icon)) {\n return cloneElement(icon, {\n size: icon.props.size ?? INPUT_ICON_SIZE,\n color: icon.props.color ?? color,\n });\n }\n\n return icon;\n}\n\nexport interface InputProps extends TextInputProps {\n /** Optional field label rendered above the input. */\n label?: string;\n leftIcon?: ReactNode;\n rightIcon?: ReactNode;\n /** Validation or helper error message. Shown instead of `hint` when set. */\n error?: string;\n /** Applies error field styling without showing a message (use with a form-level error). */\n invalid?: boolean;\n /** Helper text shown below the input when there is no error. */\n hint?: string;\n containerStyle?: StyleProp<ViewStyle>;\n style?: StyleProp<TextStyle>;\n className?: string;\n /** CSS classes for the bordered field container (web). */\n fieldClassName?: string;\n /** Styles merged into the bordered field container. */\n fieldStyle?: StyleProp<ViewStyle>;\n labelClassName?: string;\n /** Styles merged into the field label. */\n labelStyles?: StyleProp<TextStyle>;\n inputClassName?: string;\n errorClassName?: string;\n hintClassName?: string;\n /** When `secureTextEntry` is set, show a toggleable eye icon. Pass `false` to disable. */\n showPasswordToggle?: boolean;\n}\n\nexport function Input({\n label,\n leftIcon,\n rightIcon,\n error,\n invalid,\n hint,\n containerStyle,\n style,\n className,\n fieldClassName,\n fieldStyle,\n labelClassName,\n labelStyles,\n inputClassName,\n errorClassName,\n hintClassName,\n editable = true,\n secureTextEntry,\n showPasswordToggle,\n onFocus,\n onBlur,\n multiline,\n textAlignVertical,\n ...props\n}: InputProps) {\n const wrapperRef = useRef<ComponentRef<typeof View>>(null);\n const fieldRef = useRef<ComponentRef<typeof View>>(null);\n const inputRef = useRef<ComponentRef<typeof TextInput>>(null);\n const helperRef = useRef<ComponentRef<typeof Text>>(null);\n const [focused, setFocused] = useState(false);\n const [passwordVisible, setPasswordVisible] = useState(false);\n\n useApplyWebClassName(wrapperRef, className);\n useApplyWebClassName(fieldRef, fieldClassName);\n useApplyWebClassName(inputRef, inputClassName);\n useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);\n\n const isDisabled = editable === false;\n const hasError = Boolean(error) || Boolean(invalid);\n const passwordToggleEnabled =\n secureTextEntry === true && showPasswordToggle !== false && rightIcon == null;\n const effectiveSecureTextEntry = passwordToggleEnabled\n ? !passwordVisible\n : secureTextEntry;\n // Keep placeholder and typed text on the same vertical line (esp. Android).\n const resolvedTextAlignVertical =\n textAlignVertical ?? (multiline ? \"top\" : \"center\");\n const visualState = resolveInputVisualState({\n focused,\n error: hasError,\n disabled: isDisabled,\n });\n const fieldStyles = getInputFieldStyles(visualState);\n const iconColor = fieldStyles.icon;\n\n function handleFocus(event: NativeSyntheticEvent<TextInputFocusEventData>) {\n setFocused(true);\n onFocus?.(event);\n }\n\n function handleBlur(event: NativeSyntheticEvent<TextInputFocusEventData>) {\n setFocused(false);\n onBlur?.(event);\n }\n\n const helperMessage = error ?? hint;\n\n function togglePasswordVisibility() {\n if (!isDisabled) {\n setPasswordVisible((visible) => !visible);\n }\n }\n\n const trailingIcon = passwordToggleEnabled ? (\n <Pressable\n onPress={togglePasswordVisibility}\n disabled={isDisabled}\n accessibilityRole=\"button\"\n accessibilityLabel={passwordVisible ? \"Hide password\" : \"Show password\"}\n hitSlop={8}\n style={styles.iconPressable}\n >\n {renderInputIcon(\n passwordVisible ? <EyeOffIcon /> : <EyeIcon />,\n iconColor,\n )}\n </Pressable>\n ) : rightIcon ? (\n renderInputIcon(rightIcon, iconColor)\n ) : null;\n\n return (\n <View ref={wrapperRef} style={[styles.wrapper, containerStyle]}>\n {label ? (\n <Label\n disabled={isDisabled}\n className={labelClassName}\n style={labelStyles}\n >\n {label}\n </Label>\n ) : null}\n <View style={fieldStyles.outline}>\n <View\n ref={fieldRef}\n style={[inputFieldMetrics.container, fieldStyles.container, fieldStyle]}\n >\n {leftIcon ? (\n <View style={styles.iconSlot}>{renderInputIcon(leftIcon, iconColor)}</View>\n ) : null}\n <TextInput\n ref={inputRef}\n style={[\n inputFieldMetrics.input,\n !multiline ? inputFieldMetrics.inputSingleLine : null,\n fieldStyles.text,\n style,\n ]}\n placeholderTextColor={fieldStyles.placeholder}\n editable={editable}\n multiline={multiline}\n secureTextEntry={effectiveSecureTextEntry}\n textAlign=\"left\"\n textAlignVertical={resolvedTextAlignVertical}\n onFocus={handleFocus}\n onBlur={handleBlur}\n accessibilityState={{ disabled: isDisabled }}\n {...props}\n />\n {trailingIcon ? (\n <View style={styles.iconSlot}>{trailingIcon}</View>\n ) : null}\n </View>\n </View>\n {helperMessage ? (\n <Text ref={helperRef} style={error ? styles.error : styles.hint}>\n {helperMessage}\n </Text>\n ) : null}\n </View>\n );\n}\n\nconst styles = StyleSheet.create({\n wrapper: {\n width: \"100%\",\n minWidth: 0,\n gap: spacing.sm,\n },\n iconSlot: {\n width: INPUT_ICON_SIZE,\n height: INPUT_ICON_SIZE,\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n },\n iconPressable: {\n width: INPUT_ICON_SIZE,\n height: INPUT_ICON_SIZE,\n alignItems: \"center\",\n justifyContent: \"center\",\n },\n error: {\n fontSize: 12,\n lineHeight: 16,\n color: colors.inputError,\n },\n hint: {\n fontSize: 12,\n lineHeight: 16,\n color: colors.stormGray300,\n },\n});\n"]}