@scripso-homepad/ui 0.3.6 → 0.3.8

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.
Files changed (38) hide show
  1. package/README.md +238 -79
  2. package/dist/index.cjs +1225 -85
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +324 -18
  5. package/dist/index.d.ts +324 -18
  6. package/dist/index.js +1204 -89
  7. package/dist/index.js.map +1 -1
  8. package/package.json +18 -6
  9. package/src/components/Button.stories.tsx +77 -57
  10. package/src/components/Button.tsx +154 -123
  11. package/src/components/CountryCodeSelector.stories.tsx +61 -0
  12. package/src/components/CountryCodeSelector.tsx +273 -0
  13. package/src/components/Input.stories.tsx +126 -0
  14. package/src/components/Input.tsx +221 -0
  15. package/src/components/Label.tsx +56 -0
  16. package/src/components/PhoneInput.stories.tsx +85 -0
  17. package/src/components/PhoneInput.tsx +172 -0
  18. package/src/data/countries.ts +98 -0
  19. package/src/icons/ArrowUpRightIcon.tsx +29 -0
  20. package/src/icons/ArrowUpRightIcon.web.tsx +35 -0
  21. package/src/icons/ChevronDownIcon.tsx +29 -0
  22. package/src/icons/ChevronDownIcon.web.tsx +35 -0
  23. package/src/icons/EyeIcon.tsx +36 -0
  24. package/src/icons/EyeIcon.web.tsx +42 -0
  25. package/src/icons/EyeOffIcon.tsx +29 -0
  26. package/src/icons/EyeOffIcon.web.tsx +35 -0
  27. package/src/icons/KeyIcon.tsx +36 -0
  28. package/src/icons/KeyIcon.web.tsx +42 -0
  29. package/src/icons/arrowUpRightPath.ts +2 -0
  30. package/src/icons/chevronDownPath.ts +1 -0
  31. package/src/icons/eyeIconPaths.ts +8 -0
  32. package/src/icons/keyIconPaths.ts +5 -0
  33. package/src/index.ts +42 -0
  34. package/src/theme/input.ts +154 -0
  35. package/src/theme/tokens.ts +272 -0
  36. package/src/utils/countryDropdownScrollStyles.ts +52 -0
  37. package/src/utils/countryFlag.ts +9 -0
  38. package/src/utils/useApplyWebClassName.ts +3 -2
package/dist/index.js CHANGED
@@ -1,8 +1,259 @@
1
- import { useRef, useLayoutEffect } from 'react';
2
- import { StyleSheet, TouchableOpacity, Text, Platform } from 'react-native';
3
- import { jsx } from 'react/jsx-runtime';
1
+ import { useRef, useState, useLayoutEffect, isValidElement, cloneElement } from 'react';
2
+ import { StyleSheet, Platform, TouchableOpacity, Text, View, Pressable, TextInput, ScrollView, Modal, Dimensions } from 'react-native';
3
+ import Svg, { Path } from 'react-native-svg';
4
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
5
 
5
6
  // src/components/Button.tsx
7
+
8
+ // src/icons/arrowUpRightPath.ts
9
+ var ARROW_UP_RIGHT_PATH = "M14.1667 14.1668V5.8335H5.83333M14.1667 5.8335L5.83333 14.1668";
10
+ function ArrowUpRightIcon({
11
+ size = 20,
12
+ color = "#08275d",
13
+ strokeWidth = 2
14
+ }) {
15
+ return /* @__PURE__ */ jsx(Svg, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
16
+ Path,
17
+ {
18
+ d: ARROW_UP_RIGHT_PATH,
19
+ stroke: color,
20
+ strokeWidth,
21
+ strokeLinecap: "round",
22
+ strokeLinejoin: "round"
23
+ }
24
+ ) });
25
+ }
26
+
27
+ // src/theme/tokens.ts
28
+ var stormGray = {
29
+ "0": "#fbfcfc",
30
+ "0.5": "#eceef0",
31
+ "1": "#dadde0",
32
+ "1.5": "#c7cdd1",
33
+ "2": "#b5bcc1",
34
+ "3": "#8f9aa3",
35
+ "4": "#6a7984",
36
+ "5": "#455765",
37
+ "6": "#374651",
38
+ "7": "#29343d",
39
+ "8": "#1c2328",
40
+ "8.5": "#151a1e"
41
+ };
42
+ var navy = {
43
+ "0": "#f8f9fb",
44
+ "0.5": "#e5e9ef",
45
+ "1": "#cdd3df",
46
+ "1.5": "#b4bece",
47
+ "2": "#9ca8be",
48
+ "3": "#6a7d9e",
49
+ "4": "#39527d",
50
+ "5": "#08275d",
51
+ "6": "#061f4a",
52
+ "7": "#051738",
53
+ "8": "#031025",
54
+ "8.5": "#020c1c"
55
+ };
56
+ var rubyRed = {
57
+ "0": "#fff5f6",
58
+ "0.5": "#f7dddf",
59
+ "1": "#efc4c8",
60
+ "1.5": "#e7acb1",
61
+ "2": "#df939a",
62
+ "3": "#ce626d",
63
+ "4": "#be313f",
64
+ "5": "#ae0011",
65
+ "6": "#8b000e",
66
+ "7": "#68000a",
67
+ "8": "#460007",
68
+ "8.5": "#340005"
69
+ };
70
+ var emeraldGreen = {
71
+ "0": "#f0fbf5",
72
+ "0.5": "#dcf2e5",
73
+ "1": "#c8e8d5",
74
+ "1.5": "#b4dfc5",
75
+ "2": "#a0d5b5",
76
+ "3": "#77c394",
77
+ "4": "#4fb074",
78
+ "5": "#279d54",
79
+ "6": "#1f7e43",
80
+ "7": "#175e32",
81
+ "8": "#103f22",
82
+ "8.5": "#0c2f19"
83
+ };
84
+ var brand = {
85
+ slateBlue: "#182e3c",
86
+ stormGray: stormGray["5"],
87
+ navy: navy["5"],
88
+ rubyRed: rubyRed["5"],
89
+ emeraldGreen: emeraldGreen["5"]
90
+ };
91
+ var colors = {
92
+ // Brand colors
93
+ slateBlue: brand.slateBlue,
94
+ // Emerald Green — Figma scale + brand swatch
95
+ emeraldGreen0: emeraldGreen["0"],
96
+ emeraldGreen50: emeraldGreen["0.5"],
97
+ emeraldGreen100: emeraldGreen["1"],
98
+ emeraldGreen150: emeraldGreen["1.5"],
99
+ emeraldGreen200: emeraldGreen["2"],
100
+ emeraldGreen300: emeraldGreen["3"],
101
+ emeraldGreen400: emeraldGreen["4"],
102
+ emeraldGreen500: emeraldGreen["5"],
103
+ emeraldGreen600: emeraldGreen["6"],
104
+ emeraldGreen700: emeraldGreen["7"],
105
+ emeraldGreen800: emeraldGreen["8"],
106
+ emeraldGreen850: emeraldGreen["8.5"],
107
+ /** Primary brand emerald green — Figma Emerald Green 5 */
108
+ emeraldGreen: brand.emeraldGreen,
109
+ // Ruby Red — Figma scale + brand swatch
110
+ rubyRed0: rubyRed["0"],
111
+ rubyRed50: rubyRed["0.5"],
112
+ rubyRed100: rubyRed["1"],
113
+ rubyRed150: rubyRed["1.5"],
114
+ rubyRed200: rubyRed["2"],
115
+ rubyRed300: rubyRed["3"],
116
+ rubyRed400: rubyRed["4"],
117
+ rubyRed500: rubyRed["5"],
118
+ rubyRed600: rubyRed["6"],
119
+ rubyRed700: rubyRed["7"],
120
+ rubyRed800: rubyRed["8"],
121
+ rubyRed850: rubyRed["8.5"],
122
+ /** Primary brand ruby red — Figma Ruby Red 5 */
123
+ rubyRed: brand.rubyRed,
124
+ // Navy — Figma scale + brand swatch
125
+ navy0: navy["0"],
126
+ navy50: navy["0.5"],
127
+ navy100: navy["1"],
128
+ navy150: navy["1.5"],
129
+ navy200: navy["2"],
130
+ navy300: navy["3"],
131
+ navy400: navy["4"],
132
+ navy500: navy["5"],
133
+ navy600: navy["6"],
134
+ navy700: navy["7"],
135
+ navy800: navy["8"],
136
+ navy850: navy["8.5"],
137
+ /** Primary brand navy — Figma Navy 5 */
138
+ navy: brand.navy,
139
+ // Storm Gray — Figma scale + brand swatch
140
+ stormGray0: stormGray["0"],
141
+ stormGray50: stormGray["0.5"],
142
+ stormGray100: stormGray["1"],
143
+ stormGray150: stormGray["1.5"],
144
+ stormGray200: stormGray["2"],
145
+ stormGray300: stormGray["3"],
146
+ stormGray400: stormGray["4"],
147
+ stormGray500: stormGray["5"],
148
+ /** Figma brand swatch "Storm Gray" — same as `stormGray500` */
149
+ stormGrayBrand: brand.stormGray,
150
+ stormGray600: stormGray["6"],
151
+ stormGray700: stormGray["7"],
152
+ stormGray800: stormGray["8"],
153
+ stormGray850: stormGray["8.5"],
154
+ /** @deprecated Use `stormGray0` */
155
+ storm0: stormGray["0"],
156
+ /** @deprecated Use `stormGray50` */
157
+ storm50: stormGray["0.5"],
158
+ /** @deprecated Use `stormGray200` */
159
+ storm200: stormGray["2"],
160
+ /** @deprecated Use `stormGray300` */
161
+ storm300: stormGray["3"],
162
+ /** @deprecated Use `stormGray500` */
163
+ storm500: stormGray["5"],
164
+ /** @deprecated Use `stormGray700` */
165
+ storm700: stormGray["7"],
166
+ /** @deprecated Use `stormGray850` */
167
+ storm900: stormGray["8.5"],
168
+ countrySelectorSelectedBg: `${stormGray["0.5"]}99`,
169
+ white: "#ffffff",
170
+ error: "#dc2626",
171
+ errorDark: "#b3261e",
172
+ errorLight: "#fee2e2",
173
+ /** @deprecated Use `rubyRed` */
174
+ inputError: brand.rubyRed,
175
+ inputOutlineFocus: navy["0.5"],
176
+ inputOutlineError: rubyRed["0.5"],
177
+ warning: "#92400e",
178
+ warningBg: "#fef3c7",
179
+ success: "#28a745",
180
+ successMuted: "#9fd4a8",
181
+ /** @deprecated Use `emeraldGreen` */
182
+ green: brand.emeraldGreen,
183
+ transparent: "transparent"
184
+ };
185
+ var radii = {
186
+ sm: 8,
187
+ md: 12,
188
+ lg: 16,
189
+ xl: 20,
190
+ full: 9999
191
+ };
192
+ var spacing = {
193
+ xs: 4,
194
+ sm: 8,
195
+ md: 12,
196
+ lg: 16,
197
+ xl: 24,
198
+ xxl: 32
199
+ };
200
+ var fontSize = {
201
+ xs: 11,
202
+ sm: 12,
203
+ md: 14,
204
+ base: 16,
205
+ lg: 18,
206
+ xl: 24,
207
+ xxl: 32
208
+ };
209
+ var fontWeight = {
210
+ regular: "400",
211
+ medium: "500",
212
+ semibold: "600",
213
+ bold: "700"
214
+ };
215
+ var fonts = {
216
+ sans: "Noto Sans Armenian"
217
+ };
218
+ var labelTypography = {
219
+ fontFamily: fonts.sans,
220
+ fontSize: fontSize.sm,
221
+ fontWeight: fontWeight.medium,
222
+ lineHeight: fontSize.sm,
223
+ letterSpacing: 0
224
+ };
225
+ var buttonTypography = {
226
+ lg: {
227
+ fontFamily: fonts.sans,
228
+ fontSize: 14,
229
+ fontWeight: fontWeight.semibold,
230
+ lineHeight: 18,
231
+ letterSpacing: 0
232
+ },
233
+ sm: {
234
+ fontFamily: fonts.sans,
235
+ fontSize: 12,
236
+ fontWeight: fontWeight.semibold,
237
+ lineHeight: 16,
238
+ letterSpacing: 0
239
+ }
240
+ };
241
+ var shadows = {
242
+ card: {
243
+ shadowColor: colors.navy,
244
+ shadowOffset: { width: 0, height: 4 },
245
+ shadowOpacity: 0.05,
246
+ shadowRadius: 20,
247
+ elevation: 2
248
+ },
249
+ cardLg: {
250
+ shadowColor: colors.navy,
251
+ shadowOffset: { width: 0, height: 4 },
252
+ shadowOpacity: 0.1,
253
+ shadowRadius: 20,
254
+ elevation: 4
255
+ }
256
+ };
6
257
  function hasClassList(node) {
7
258
  return typeof node === "object" && node !== null && "classList" in node && typeof node.classList?.add === "function";
8
259
  }
@@ -18,9 +269,9 @@ function resolveWebElement(ref) {
18
269
  }
19
270
  return null;
20
271
  }
21
- function useApplyWebClassName(ref, className) {
272
+ function useApplyWebClassName(ref, className, enabled = true) {
22
273
  useLayoutEffect(() => {
23
- if (Platform.OS !== "web" || !className?.trim()) return;
274
+ if (!enabled || Platform.OS !== "web" || !className?.trim()) return;
24
275
  const element = resolveWebElement(ref);
25
276
  if (!element) return;
26
277
  const classes = className.trim().split(/\s+/);
@@ -28,14 +279,73 @@ function useApplyWebClassName(ref, className) {
28
279
  return () => {
29
280
  element.classList.remove(...classes);
30
281
  };
31
- }, [ref, className]);
282
+ }, [ref, className, enabled]);
32
283
  }
284
+ var variantConfig = {
285
+ white: {
286
+ backgroundColor: colors.white,
287
+ textColor: colors.slateBlue,
288
+ iconBadgeBackgroundColor: colors.stormGray150,
289
+ iconColor: colors.navy
290
+ },
291
+ primary: {
292
+ backgroundColor: colors.navy,
293
+ textColor: colors.stormGray0,
294
+ iconBadgeBackgroundColor: colors.white,
295
+ iconColor: colors.navy
296
+ },
297
+ green: {
298
+ backgroundColor: colors.green,
299
+ textColor: colors.stormGray0,
300
+ iconBadgeBackgroundColor: colors.white,
301
+ iconColor: colors.green
302
+ },
303
+ gray: {
304
+ backgroundColor: colors.stormGray50,
305
+ textColor: colors.slateBlue,
306
+ iconBadgeBackgroundColor: colors.stormGray150,
307
+ iconColor: colors.navy
308
+ }
309
+ };
310
+ var sizeConfig = {
311
+ lg: {
312
+ borderRadius: 16,
313
+ paddingTop: 8,
314
+ paddingRight: 8,
315
+ paddingBottom: 8,
316
+ paddingLeft: 24,
317
+ paddingHorizontalCentered: 24,
318
+ minHeight: 52,
319
+ text: buttonTypography.lg,
320
+ iconContainerSize: 36,
321
+ iconContainerRadius: 12,
322
+ iconContainerPadding: 8,
323
+ iconSize: 20
324
+ },
325
+ sm: {
326
+ borderRadius: 12,
327
+ paddingTop: 8,
328
+ paddingRight: 8,
329
+ paddingBottom: 8,
330
+ paddingLeft: 16,
331
+ paddingHorizontalCentered: 16,
332
+ minHeight: 48,
333
+ text: buttonTypography.sm,
334
+ iconContainerSize: 32,
335
+ iconContainerRadius: 8,
336
+ iconContainerPadding: 8,
337
+ iconSize: 16
338
+ }
339
+ };
33
340
  function Button({
34
341
  title,
342
+ children,
35
343
  onPress,
36
344
  disabled = false,
37
345
  variant = "primary",
38
- size = "medium",
346
+ size = "lg",
347
+ showIcon = false,
348
+ icon,
39
349
  style,
40
350
  textStyle,
41
351
  className,
@@ -43,23 +353,40 @@ function Button({
43
353
  }) {
44
354
  const containerRef = useRef(null);
45
355
  const textRef = useRef(null);
356
+ const preset = variantConfig[variant];
357
+ const metrics = sizeConfig[size];
46
358
  useApplyWebClassName(containerRef, className);
47
359
  useApplyWebClassName(textRef, textClassName);
360
+ const label = typeof children !== "undefined" ? children : title;
361
+ const hasCustomChildren = typeof children !== "undefined";
362
+ const customIcon = icon != null && typeof icon !== "boolean" ? icon : void 0;
363
+ const hasIcon = showIcon || icon === true || customIcon != null;
364
+ const iconNode = customIcon ?? /* @__PURE__ */ jsx(ArrowUpRightIcon, { size: metrics.iconSize, color: preset.iconColor });
48
365
  const containerStyle = [
49
366
  styles.base,
50
- variantStyles[variant],
51
- sizeStyles[size],
52
- disabled && disabledVariantStyles[variant],
367
+ {
368
+ borderRadius: metrics.borderRadius,
369
+ backgroundColor: preset.backgroundColor,
370
+ minHeight: metrics.minHeight,
371
+ paddingTop: metrics.paddingTop,
372
+ paddingBottom: metrics.paddingBottom,
373
+ paddingLeft: hasIcon ? metrics.paddingLeft : metrics.paddingHorizontalCentered,
374
+ paddingRight: hasIcon ? metrics.paddingRight : metrics.paddingHorizontalCentered
375
+ },
376
+ hasIcon ? styles.withIcon : styles.centered,
377
+ disabled && styles.disabled,
53
378
  style
54
379
  ];
55
380
  const labelStyle = [
56
- textBaseStyles.base,
57
- textVariantStyles[variant],
58
- textSizeStyles[size],
59
- disabled && textDisabledStyles[variant],
381
+ styles.label,
382
+ metrics.text,
383
+ { color: preset.textColor },
384
+ Platform.OS === "android" ? styles.labelAndroid : null,
385
+ !hasIcon && styles.labelCentered,
386
+ hasIcon && styles.labelWithIcon,
60
387
  textStyle
61
388
  ];
62
- return /* @__PURE__ */ jsx(
389
+ return /* @__PURE__ */ jsxs(
63
390
  TouchableOpacity,
64
391
  {
65
392
  ref: containerRef,
@@ -69,113 +396,901 @@ function Button({
69
396
  activeOpacity: 0.7,
70
397
  accessibilityRole: "button",
71
398
  accessibilityState: { disabled },
72
- children: /* @__PURE__ */ jsx(Text, { ref: textRef, style: labelStyle, children: title })
399
+ children: [
400
+ hasCustomChildren ? children : /* @__PURE__ */ jsx(Text, { ref: textRef, style: labelStyle, children: label }),
401
+ hasIcon ? /* @__PURE__ */ jsx(
402
+ View,
403
+ {
404
+ style: [
405
+ styles.iconContainer,
406
+ {
407
+ width: metrics.iconContainerSize,
408
+ height: metrics.iconContainerSize,
409
+ borderRadius: metrics.iconContainerRadius,
410
+ padding: metrics.iconContainerPadding,
411
+ backgroundColor: preset.iconBadgeBackgroundColor
412
+ }
413
+ ],
414
+ children: iconNode
415
+ }
416
+ ) : null
417
+ ]
73
418
  }
74
419
  );
75
420
  }
76
421
  var styles = StyleSheet.create({
77
422
  base: {
423
+ flexDirection: "row",
78
424
  alignItems: "center",
79
- justifyContent: "center",
80
- borderRadius: 8,
81
425
  borderWidth: 0
82
- }
83
- });
84
- var variantStyles = StyleSheet.create({
85
- primary: {
86
- backgroundColor: "#2563eb"
87
426
  },
88
- secondary: {
89
- backgroundColor: "#4b5563"
427
+ centered: {
428
+ justifyContent: "center"
90
429
  },
91
- outline: {
92
- backgroundColor: "transparent",
93
- borderWidth: 1,
94
- borderColor: "#2563eb"
430
+ withIcon: {
431
+ justifyContent: "space-between"
95
432
  },
96
- ghost: {
97
- backgroundColor: "transparent"
433
+ disabled: {
434
+ opacity: 0.6
435
+ },
436
+ label: {},
437
+ labelAndroid: {
438
+ includeFontPadding: false
439
+ },
440
+ labelCentered: {
441
+ textAlign: "center"
442
+ },
443
+ labelWithIcon: {
444
+ flex: 1,
445
+ flexShrink: 1,
446
+ marginRight: 8
447
+ },
448
+ iconContainer: {
449
+ alignItems: "center",
450
+ justifyContent: "center",
451
+ flexShrink: 0
98
452
  }
99
453
  });
100
- var sizeStyles = StyleSheet.create({
101
- small: {
102
- paddingVertical: 8,
103
- paddingHorizontal: 16,
104
- minWidth: 96
105
- },
106
- medium: {
107
- paddingVertical: 12,
108
- paddingHorizontal: 24,
109
- minWidth: 120
110
- },
111
- large: {
112
- paddingVertical: 16,
113
- paddingHorizontal: 32,
114
- minWidth: 160
454
+
455
+ // src/icons/eyeIconPaths.ts
456
+ var EYE_OPEN_OUTLINE_PATH = "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";
457
+ var EYE_OPEN_PUPIL_PATH = "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";
458
+ var EYE_OFF_PATH = "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";
459
+ function EyeIcon({
460
+ size = 20,
461
+ color = "#c7cdd1",
462
+ strokeWidth = 2
463
+ }) {
464
+ return /* @__PURE__ */ jsxs(Svg, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
465
+ /* @__PURE__ */ jsx(
466
+ Path,
467
+ {
468
+ d: EYE_OPEN_OUTLINE_PATH,
469
+ stroke: color,
470
+ strokeWidth,
471
+ strokeLinecap: "round",
472
+ strokeLinejoin: "round"
473
+ }
474
+ ),
475
+ /* @__PURE__ */ jsx(
476
+ Path,
477
+ {
478
+ d: EYE_OPEN_PUPIL_PATH,
479
+ stroke: color,
480
+ strokeWidth,
481
+ strokeLinecap: "round",
482
+ strokeLinejoin: "round"
483
+ }
484
+ )
485
+ ] });
486
+ }
487
+ function EyeOffIcon({
488
+ size = 20,
489
+ color = "#c7cdd1",
490
+ strokeWidth = 2
491
+ }) {
492
+ return /* @__PURE__ */ jsx(Svg, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsx(
493
+ Path,
494
+ {
495
+ d: EYE_OFF_PATH,
496
+ stroke: color,
497
+ strokeWidth,
498
+ strokeLinecap: "round",
499
+ strokeLinejoin: "round"
500
+ }
501
+ ) });
502
+ }
503
+ var INPUT_HEIGHT = 52;
504
+ var INPUT_ICON_SIZE = 20;
505
+ var INPUT_ICON_GAP = 10;
506
+ var INPUT_OUTLINE_WIDTH = 2;
507
+ function resolveInputVisualState({
508
+ focused = false,
509
+ error = false,
510
+ disabled = false
511
+ }) {
512
+ if (disabled) return "disabled";
513
+ if (error) return "error";
514
+ if (focused) return "focused";
515
+ return "default";
516
+ }
517
+ function createOutlineStyle(ringColor) {
518
+ return {
519
+ borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,
520
+ borderWidth: INPUT_OUTLINE_WIDTH,
521
+ borderColor: ringColor,
522
+ padding: 0,
523
+ backgroundColor: colors.transparent,
524
+ width: "100%",
525
+ alignSelf: "stretch",
526
+ ...Platform.OS !== "web" ? { overflow: "hidden" } : null
527
+ };
528
+ }
529
+ var defaultOutline = createOutlineStyle(colors.transparent);
530
+ function getInputFieldStyles(state) {
531
+ const containerBase = {
532
+ borderRadius: radii.lg,
533
+ ...Platform.OS !== "web" ? { overflow: "hidden" } : null
534
+ };
535
+ switch (state) {
536
+ case "disabled":
537
+ return {
538
+ outline: defaultOutline,
539
+ container: {
540
+ ...containerBase,
541
+ borderWidth: 1,
542
+ borderColor: colors.stormGray50,
543
+ backgroundColor: colors.stormGray50
544
+ },
545
+ text: { color: colors.stormGray300 },
546
+ placeholder: colors.stormGray300,
547
+ icon: colors.stormGray150
548
+ };
549
+ case "error":
550
+ return {
551
+ outline: createOutlineStyle(colors.inputOutlineError),
552
+ container: {
553
+ ...containerBase,
554
+ borderWidth: 1,
555
+ borderColor: colors.inputError,
556
+ backgroundColor: colors.white
557
+ },
558
+ text: { color: colors.inputError },
559
+ placeholder: colors.stormGray200,
560
+ icon: colors.inputError
561
+ };
562
+ case "focused":
563
+ return {
564
+ outline: createOutlineStyle(colors.inputOutlineFocus),
565
+ container: {
566
+ ...containerBase,
567
+ borderWidth: 1,
568
+ borderColor: colors.navy,
569
+ backgroundColor: colors.white
570
+ },
571
+ text: { color: colors.slateBlue },
572
+ placeholder: colors.stormGray200,
573
+ icon: colors.navy
574
+ };
575
+ default:
576
+ return {
577
+ outline: defaultOutline,
578
+ container: {
579
+ ...containerBase,
580
+ borderWidth: 1,
581
+ borderColor: colors.stormGray50,
582
+ backgroundColor: colors.white
583
+ },
584
+ text: { color: colors.slateBlue },
585
+ placeholder: colors.stormGray200,
586
+ icon: colors.stormGray150
587
+ };
115
588
  }
116
- });
117
- var disabledVariantStyles = StyleSheet.create({
118
- primary: {
119
- backgroundColor: "#93c5fd",
120
- opacity: 0.7
589
+ }
590
+ var inputFieldMetrics = StyleSheet.create({
591
+ container: {
592
+ flexDirection: "row",
593
+ alignItems: "center",
594
+ height: INPUT_HEIGHT,
595
+ minHeight: INPUT_HEIGHT,
596
+ maxHeight: INPUT_HEIGHT,
597
+ borderRadius: radii.lg,
598
+ padding: 16,
599
+ gap: INPUT_ICON_GAP,
600
+ ...Platform.OS === "web" ? { boxSizing: "border-box" } : null
121
601
  },
122
- secondary: {
123
- backgroundColor: "#9ca3af",
124
- opacity: 0.7
602
+ input: {
603
+ flex: 1,
604
+ alignSelf: "stretch",
605
+ fontFamily: fonts.sans,
606
+ fontSize: fontSize.md,
607
+ fontWeight: fontWeight.medium,
608
+ lineHeight: Platform.OS === "web" ? fontSize.md : 20,
609
+ paddingVertical: 0,
610
+ paddingHorizontal: 0,
611
+ margin: 0,
612
+ borderWidth: 0,
613
+ backgroundColor: colors.transparent,
614
+ ...Platform.OS === "android" ? { includeFontPadding: false } : null,
615
+ ...Platform.OS === "web" ? {
616
+ height: "100%",
617
+ minHeight: 0,
618
+ outlineStyle: "none"
619
+ } : null
620
+ }
621
+ });
622
+ function Label({
623
+ children,
624
+ required = false,
625
+ disabled = false,
626
+ style,
627
+ className,
628
+ ...props
629
+ }) {
630
+ const ref = useRef(null);
631
+ useApplyWebClassName(ref, className);
632
+ return /* @__PURE__ */ jsxs(
633
+ Text,
634
+ {
635
+ ref,
636
+ style: [styles2.label, disabled && styles2.labelDisabled, style],
637
+ accessibilityRole: "text",
638
+ ...props,
639
+ children: [
640
+ children,
641
+ required ? /* @__PURE__ */ jsx(Text, { style: styles2.required, children: " *" }) : null
642
+ ]
643
+ }
644
+ );
645
+ }
646
+ var styles2 = StyleSheet.create({
647
+ label: {
648
+ ...labelTypography,
649
+ color: colors.slateBlue
125
650
  },
126
- outline: {
127
- borderColor: "#93c5fd",
128
- opacity: 0.7
651
+ labelDisabled: {
652
+ color: colors.stormGray400
129
653
  },
130
- ghost: {
131
- opacity: 0.5
654
+ required: {
655
+ color: colors.inputError
132
656
  }
133
657
  });
134
- var textBaseStyles = StyleSheet.create({
135
- base: {
136
- fontWeight: "600"
658
+ function renderInputIcon(icon, color) {
659
+ if (!icon) return null;
660
+ if (isValidElement(icon)) {
661
+ return cloneElement(icon, {
662
+ size: icon.props.size ?? INPUT_ICON_SIZE,
663
+ color: icon.props.color ?? color
664
+ });
137
665
  }
138
- });
139
- var textVariantStyles = StyleSheet.create({
140
- primary: {
141
- color: "#ffffff"
666
+ return icon;
667
+ }
668
+ function Input({
669
+ label,
670
+ leftIcon,
671
+ rightIcon,
672
+ error,
673
+ hint,
674
+ containerStyle,
675
+ style,
676
+ className,
677
+ labelClassName,
678
+ inputClassName,
679
+ errorClassName,
680
+ hintClassName,
681
+ editable = true,
682
+ secureTextEntry,
683
+ showPasswordToggle,
684
+ onFocus,
685
+ onBlur,
686
+ ...props
687
+ }) {
688
+ const wrapperRef = useRef(null);
689
+ const inputRef = useRef(null);
690
+ const helperRef = useRef(null);
691
+ const [focused, setFocused] = useState(false);
692
+ const [passwordVisible, setPasswordVisible] = useState(false);
693
+ useApplyWebClassName(wrapperRef, className);
694
+ useApplyWebClassName(inputRef, inputClassName);
695
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
696
+ const isDisabled = editable === false;
697
+ const passwordToggleEnabled = secureTextEntry === true && showPasswordToggle !== false && rightIcon == null;
698
+ const effectiveSecureTextEntry = passwordToggleEnabled ? !passwordVisible : secureTextEntry;
699
+ const visualState = resolveInputVisualState({
700
+ focused,
701
+ error: Boolean(error),
702
+ disabled: isDisabled
703
+ });
704
+ const fieldStyles = getInputFieldStyles(visualState);
705
+ const iconColor = fieldStyles.icon;
706
+ function handleFocus(event) {
707
+ setFocused(true);
708
+ onFocus?.(event);
709
+ }
710
+ function handleBlur(event) {
711
+ setFocused(false);
712
+ onBlur?.(event);
713
+ }
714
+ const helperMessage = error ?? hint;
715
+ function togglePasswordVisibility() {
716
+ if (!isDisabled) {
717
+ setPasswordVisible((visible) => !visible);
718
+ }
719
+ }
720
+ const trailingIcon = passwordToggleEnabled ? /* @__PURE__ */ jsx(
721
+ Pressable,
722
+ {
723
+ onPress: togglePasswordVisibility,
724
+ disabled: isDisabled,
725
+ accessibilityRole: "button",
726
+ accessibilityLabel: passwordVisible ? "Hide password" : "Show password",
727
+ hitSlop: 8,
728
+ style: styles3.iconPressable,
729
+ children: renderInputIcon(
730
+ passwordVisible ? /* @__PURE__ */ jsx(EyeOffIcon, {}) : /* @__PURE__ */ jsx(EyeIcon, {}),
731
+ iconColor
732
+ )
733
+ }
734
+ ) : rightIcon ? renderInputIcon(rightIcon, iconColor) : null;
735
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles3.wrapper, containerStyle], children: [
736
+ label ? /* @__PURE__ */ jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
737
+ /* @__PURE__ */ jsx(View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxs(View, { style: [inputFieldMetrics.container, fieldStyles.container], children: [
738
+ leftIcon ? /* @__PURE__ */ jsx(View, { style: styles3.iconSlot, children: renderInputIcon(leftIcon, iconColor) }) : null,
739
+ /* @__PURE__ */ jsx(
740
+ TextInput,
741
+ {
742
+ ref: inputRef,
743
+ style: [
744
+ inputFieldMetrics.input,
745
+ fieldStyles.text,
746
+ style
747
+ ],
748
+ placeholderTextColor: fieldStyles.placeholder,
749
+ editable,
750
+ secureTextEntry: effectiveSecureTextEntry,
751
+ onFocus: handleFocus,
752
+ onBlur: handleBlur,
753
+ accessibilityState: { disabled: isDisabled },
754
+ ...props
755
+ }
756
+ ),
757
+ trailingIcon ? /* @__PURE__ */ jsx(View, { style: styles3.iconSlot, children: trailingIcon }) : null
758
+ ] }) }),
759
+ helperMessage ? /* @__PURE__ */ jsx(Text, { ref: helperRef, style: error ? styles3.error : styles3.hint, children: helperMessage }) : null
760
+ ] });
761
+ }
762
+ var styles3 = StyleSheet.create({
763
+ wrapper: {
764
+ width: "100%",
765
+ gap: spacing.sm
142
766
  },
143
- secondary: {
144
- color: "#ffffff"
767
+ iconSlot: {
768
+ width: INPUT_ICON_SIZE,
769
+ height: INPUT_ICON_SIZE,
770
+ alignItems: "center",
771
+ justifyContent: "center",
772
+ flexShrink: 0
773
+ },
774
+ iconPressable: {
775
+ width: INPUT_ICON_SIZE,
776
+ height: INPUT_ICON_SIZE,
777
+ alignItems: "center",
778
+ justifyContent: "center"
145
779
  },
146
- outline: {
147
- color: "#2563eb"
780
+ error: {
781
+ fontSize: 12,
782
+ lineHeight: 16,
783
+ color: colors.inputError
148
784
  },
149
- ghost: {
150
- color: "#2563eb"
785
+ hint: {
786
+ fontSize: 12,
787
+ lineHeight: 16,
788
+ color: colors.stormGray300
151
789
  }
152
790
  });
153
- var textSizeStyles = StyleSheet.create({
154
- small: {
155
- fontSize: 14
791
+
792
+ // src/data/countries.ts
793
+ var defaultCountry = {
794
+ code: "AM",
795
+ name: "Armenia",
796
+ dialCode: "+374"
797
+ };
798
+ var countries = [
799
+ defaultCountry,
800
+ { code: "AF", name: "Afghanistan", dialCode: "+93" },
801
+ { code: "AL", name: "Albania", dialCode: "+355" },
802
+ { code: "DZ", name: "Algeria", dialCode: "+213" },
803
+ { code: "AR", name: "Argentina", dialCode: "+54" },
804
+ { code: "AU", name: "Australia", dialCode: "+61" },
805
+ { code: "AT", name: "Austria", dialCode: "+43" },
806
+ { code: "AZ", name: "Azerbaijan", dialCode: "+994" },
807
+ { code: "BH", name: "Bahrain", dialCode: "+973" },
808
+ { code: "BY", name: "Belarus", dialCode: "+375" },
809
+ { code: "BE", name: "Belgium", dialCode: "+32" },
810
+ { code: "BR", name: "Brazil", dialCode: "+55" },
811
+ { code: "BG", name: "Bulgaria", dialCode: "+359" },
812
+ { code: "CA", name: "Canada", dialCode: "+1" },
813
+ { code: "CL", name: "Chile", dialCode: "+56" },
814
+ { code: "CN", name: "China", dialCode: "+86" },
815
+ { code: "CO", name: "Colombia", dialCode: "+57" },
816
+ { code: "HR", name: "Croatia", dialCode: "+385" },
817
+ { code: "CY", name: "Cyprus", dialCode: "+357" },
818
+ { code: "CZ", name: "Czech Republic", dialCode: "+420" },
819
+ { code: "DK", name: "Denmark", dialCode: "+45" },
820
+ { code: "EG", name: "Egypt", dialCode: "+20" },
821
+ { code: "EE", name: "Estonia", dialCode: "+372" },
822
+ { code: "FI", name: "Finland", dialCode: "+358" },
823
+ { code: "FR", name: "France", dialCode: "+33" },
824
+ { code: "GE", name: "Georgia", dialCode: "+995" },
825
+ { code: "DE", name: "Germany", dialCode: "+49" },
826
+ { code: "GR", name: "Greece", dialCode: "+30" },
827
+ { code: "HK", name: "Hong Kong", dialCode: "+852" },
828
+ { code: "HU", name: "Hungary", dialCode: "+36" },
829
+ { code: "IN", name: "India", dialCode: "+91" },
830
+ { code: "ID", name: "Indonesia", dialCode: "+62" },
831
+ { code: "IR", name: "Iran", dialCode: "+98" },
832
+ { code: "IQ", name: "Iraq", dialCode: "+964" },
833
+ { code: "IE", name: "Ireland", dialCode: "+353" },
834
+ { code: "IL", name: "Israel", dialCode: "+972" },
835
+ { code: "IT", name: "Italy", dialCode: "+39" },
836
+ { code: "JP", name: "Japan", dialCode: "+81" },
837
+ { code: "JO", name: "Jordan", dialCode: "+962" },
838
+ { code: "KZ", name: "Kazakhstan", dialCode: "+7" },
839
+ { code: "KW", name: "Kuwait", dialCode: "+965" },
840
+ { code: "LV", name: "Latvia", dialCode: "+371" },
841
+ { code: "LB", name: "Lebanon", dialCode: "+961" },
842
+ { code: "LT", name: "Lithuania", dialCode: "+370" },
843
+ { code: "LU", name: "Luxembourg", dialCode: "+352" },
844
+ { code: "MY", name: "Malaysia", dialCode: "+60" },
845
+ { code: "MX", name: "Mexico", dialCode: "+52" },
846
+ { code: "MD", name: "Moldova", dialCode: "+373" },
847
+ { code: "NL", name: "Netherlands", dialCode: "+31" },
848
+ { code: "NZ", name: "New Zealand", dialCode: "+64" },
849
+ { code: "NG", name: "Nigeria", dialCode: "+234" },
850
+ { code: "NO", name: "Norway", dialCode: "+47" },
851
+ { code: "PK", name: "Pakistan", dialCode: "+92" },
852
+ { code: "PS", name: "Palestine", dialCode: "+970" },
853
+ { code: "PH", name: "Philippines", dialCode: "+63" },
854
+ { code: "PL", name: "Poland", dialCode: "+48" },
855
+ { code: "PT", name: "Portugal", dialCode: "+351" },
856
+ { code: "QA", name: "Qatar", dialCode: "+974" },
857
+ { code: "RO", name: "Romania", dialCode: "+40" },
858
+ { code: "RU", name: "Russia", dialCode: "+7" },
859
+ { code: "SA", name: "Saudi Arabia", dialCode: "+966" },
860
+ { code: "RS", name: "Serbia", dialCode: "+381" },
861
+ { code: "SG", name: "Singapore", dialCode: "+65" },
862
+ { code: "SK", name: "Slovakia", dialCode: "+421" },
863
+ { code: "SI", name: "Slovenia", dialCode: "+386" },
864
+ { code: "ZA", name: "South Africa", dialCode: "+27" },
865
+ { code: "KR", name: "South Korea", dialCode: "+82" },
866
+ { code: "ES", name: "Spain", dialCode: "+34" },
867
+ { code: "SE", name: "Sweden", dialCode: "+46" },
868
+ { code: "CH", name: "Switzerland", dialCode: "+41" },
869
+ { code: "SY", name: "Syria", dialCode: "+963" },
870
+ { code: "TW", name: "Taiwan", dialCode: "+886" },
871
+ { code: "TH", name: "Thailand", dialCode: "+66" },
872
+ { code: "TR", name: "Turkey", dialCode: "+90" },
873
+ { code: "UA", name: "Ukraine", dialCode: "+380" },
874
+ { code: "AE", name: "United Arab Emirates", dialCode: "+971" },
875
+ { code: "GB", name: "United Kingdom", dialCode: "+44" },
876
+ { code: "US", name: "United States", dialCode: "+1" },
877
+ { code: "UZ", name: "Uzbekistan", dialCode: "+998" },
878
+ { code: "VN", name: "Vietnam", dialCode: "+84" }
879
+ ];
880
+ function findCountry(code) {
881
+ return countries.find((country) => country.code === code) ?? defaultCountry;
882
+ }
883
+
884
+ // src/icons/chevronDownPath.ts
885
+ var CHEVRON_DOWN_PATH = "M4 6L8 10L12 6";
886
+ function ChevronDownIcon({
887
+ size = 16,
888
+ color = "#dadde0",
889
+ strokeWidth = 2
890
+ }) {
891
+ return /* @__PURE__ */ jsx(Svg, { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx(
892
+ Path,
893
+ {
894
+ d: CHEVRON_DOWN_PATH,
895
+ stroke: color,
896
+ strokeWidth,
897
+ strokeLinecap: "round",
898
+ strokeLinejoin: "round"
899
+ }
900
+ ) });
901
+ }
902
+
903
+ // src/utils/countryFlag.ts
904
+ function countryCodeToFlagEmoji(code) {
905
+ const upper = code.trim().toUpperCase();
906
+ if (upper.length !== 2) return "";
907
+ return String.fromCodePoint(
908
+ ...upper.split("").map((char) => 127462 - 65 + char.charCodeAt(0))
909
+ );
910
+ }
911
+ var COUNTRY_DROPDOWN_SCROLL_CLASS = "hp-country-dropdown-scroll";
912
+ var STYLE_ID = "hp-country-dropdown-scroll-styles";
913
+ var countryDropdownScrollCss = `
914
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS} {
915
+ scrollbar-width: thin;
916
+ scrollbar-color: ${colors.stormGray300} transparent;
917
+ overflow-y: auto;
918
+ }
919
+
920
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar {
921
+ width: 4px;
922
+ }
923
+
924
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-corner {
925
+ background: transparent;
926
+ }
927
+
928
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button,
929
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:single-button,
930
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:vertical:start:decrement,
931
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:vertical:end:increment {
932
+ display: none;
933
+ width: 0;
934
+ height: 0;
935
+ -webkit-appearance: none;
936
+ appearance: none;
937
+ }
938
+
939
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-track {
940
+ background: transparent;
941
+ }
942
+
943
+ .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-thumb {
944
+ background-color: ${colors.stormGray300};
945
+ border-radius: 9999px;
946
+ }
947
+ `;
948
+ function ensureCountryDropdownScrollStyles() {
949
+ if (Platform.OS !== "web" || typeof document === "undefined") return;
950
+ if (document.getElementById(STYLE_ID)) return;
951
+ const style = document.createElement("style");
952
+ style.id = STYLE_ID;
953
+ style.textContent = countryDropdownScrollCss;
954
+ document.head.appendChild(style);
955
+ }
956
+ var DROPDOWN_GAP = 10;
957
+ var DROPDOWN_HEIGHT = 186;
958
+ var DROPDOWN_PADDING = 8;
959
+ var OPTION_GAP = 10;
960
+ var OPTION_HEIGHT = 35;
961
+ var TRIGGER_HEIGHT = 52;
962
+ var CHEVRON_SIZE = 16;
963
+ function resolveDropdownTop(anchor) {
964
+ const windowHeight = Dimensions.get("window").height;
965
+ const topBelow = anchor.y + anchor.height + DROPDOWN_GAP;
966
+ const topAbove = anchor.y - DROPDOWN_GAP - DROPDOWN_HEIGHT;
967
+ const fitsBelow = topBelow + DROPDOWN_HEIGHT <= windowHeight;
968
+ if (fitsBelow) return topBelow;
969
+ if (topAbove >= 0) return topAbove;
970
+ return Math.max(0, Math.min(topBelow, windowHeight - DROPDOWN_HEIGHT));
971
+ }
972
+ function CountryCodeSelector({
973
+ value = defaultCountry.code,
974
+ onValueChange,
975
+ options = countries,
976
+ disabled = false,
977
+ style,
978
+ className
979
+ }) {
980
+ const wrapperRef = useRef(null);
981
+ const triggerRef = useRef(null);
982
+ const scrollRef = useRef(null);
983
+ const [open, setOpen] = useState(false);
984
+ const [anchor, setAnchor] = useState(null);
985
+ useApplyWebClassName(wrapperRef, className);
986
+ useApplyWebClassName(
987
+ scrollRef,
988
+ COUNTRY_DROPDOWN_SCROLL_CLASS,
989
+ open && Boolean(anchor)
990
+ );
991
+ useLayoutEffect(() => {
992
+ ensureCountryDropdownScrollStyles();
993
+ }, []);
994
+ const selected = findCountry(value);
995
+ const textColor = disabled ? colors.stormGray200 : colors.slateBlue;
996
+ function closeDropdown() {
997
+ setOpen(false);
998
+ setAnchor(null);
999
+ }
1000
+ function handleOpen() {
1001
+ if (disabled) return;
1002
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
1003
+ setAnchor({ x, y, width, height });
1004
+ setOpen(true);
1005
+ });
1006
+ }
1007
+ function handleSelect(code) {
1008
+ onValueChange?.(code);
1009
+ closeDropdown();
1010
+ }
1011
+ const dropdownTop = anchor ? resolveDropdownTop(anchor) : 0;
1012
+ const optionList = options.map((item, index) => {
1013
+ const isSelected = item.code === selected.code;
1014
+ const isLast = index === options.length - 1;
1015
+ return /* @__PURE__ */ jsxs(
1016
+ Pressable,
1017
+ {
1018
+ accessibilityRole: "button",
1019
+ onPress: () => handleSelect(item.code),
1020
+ style: [
1021
+ styles4.option,
1022
+ isSelected && styles4.optionSelected,
1023
+ !isLast && styles4.optionSpacing
1024
+ ],
1025
+ children: [
1026
+ /* @__PURE__ */ jsx(Text, { style: styles4.flag, children: countryCodeToFlagEmoji(item.code) }),
1027
+ /* @__PURE__ */ jsx(Text, { style: styles4.optionDialCode, children: item.dialCode })
1028
+ ]
1029
+ },
1030
+ item.code
1031
+ );
1032
+ });
1033
+ const dropdownList = /* @__PURE__ */ jsx(
1034
+ ScrollView,
1035
+ {
1036
+ ref: scrollRef,
1037
+ style: styles4.dropdownScroll,
1038
+ contentContainerStyle: styles4.dropdownContent,
1039
+ keyboardShouldPersistTaps: "handled",
1040
+ showsVerticalScrollIndicator: true,
1041
+ bounces: false,
1042
+ nestedScrollEnabled: true,
1043
+ children: optionList
1044
+ }
1045
+ );
1046
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles4.root, style], children: [
1047
+ /* @__PURE__ */ jsxs(
1048
+ Pressable,
1049
+ {
1050
+ ref: triggerRef,
1051
+ accessibilityRole: "button",
1052
+ disabled,
1053
+ onPress: handleOpen,
1054
+ style: [
1055
+ styles4.trigger,
1056
+ disabled ? styles4.triggerDisabled : styles4.triggerEnabled,
1057
+ Platform.OS === "web" ? styles4.triggerWeb : null
1058
+ ],
1059
+ children: [
1060
+ /* @__PURE__ */ jsx(Text, { style: styles4.flag, children: countryCodeToFlagEmoji(selected.code) }),
1061
+ /* @__PURE__ */ jsx(Text, { style: [styles4.dialCode, { color: textColor }], children: selected.dialCode }),
1062
+ /* @__PURE__ */ jsx(ChevronDownIcon, { size: CHEVRON_SIZE, color: colors.stormGray100 })
1063
+ ]
1064
+ }
1065
+ ),
1066
+ /* @__PURE__ */ jsx(
1067
+ Modal,
1068
+ {
1069
+ visible: open,
1070
+ transparent: true,
1071
+ animationType: "fade",
1072
+ onRequestClose: closeDropdown,
1073
+ children: /* @__PURE__ */ jsx(Pressable, { style: styles4.overlay, onPress: closeDropdown, children: anchor ? /* @__PURE__ */ jsx(
1074
+ View,
1075
+ {
1076
+ style: [
1077
+ styles4.dropdown,
1078
+ {
1079
+ top: dropdownTop,
1080
+ left: anchor.x,
1081
+ width: anchor.width
1082
+ }
1083
+ ],
1084
+ children: dropdownList
1085
+ }
1086
+ ) : null })
1087
+ }
1088
+ )
1089
+ ] });
1090
+ }
1091
+ var styles4 = StyleSheet.create({
1092
+ root: {
1093
+ alignSelf: "flex-start",
1094
+ flexShrink: 0
1095
+ },
1096
+ trigger: {
1097
+ flexDirection: "row",
1098
+ alignItems: "center",
1099
+ alignSelf: "flex-start",
1100
+ flexGrow: 0,
1101
+ flexShrink: 0,
1102
+ height: TRIGGER_HEIGHT,
1103
+ borderRadius: radii.lg,
1104
+ borderWidth: 1,
1105
+ padding: spacing.lg,
1106
+ gap: spacing.sm
1107
+ },
1108
+ triggerEnabled: {
1109
+ borderColor: colors.stormGray50,
1110
+ backgroundColor: colors.white
1111
+ },
1112
+ triggerDisabled: {
1113
+ borderColor: colors.stormGray50,
1114
+ backgroundColor: colors.stormGray50
1115
+ },
1116
+ triggerWeb: {
1117
+ width: "max-content"
1118
+ },
1119
+ flag: {
1120
+ fontSize: 18,
1121
+ lineHeight: 22
1122
+ },
1123
+ dialCode: {
1124
+ fontSize: fontSize.md,
1125
+ fontWeight: fontWeight.medium
1126
+ },
1127
+ overlay: {
1128
+ flex: 1,
1129
+ backgroundColor: "transparent"
1130
+ },
1131
+ dropdown: {
1132
+ position: "absolute",
1133
+ height: DROPDOWN_HEIGHT,
1134
+ borderRadius: radii.lg,
1135
+ borderWidth: 1,
1136
+ borderColor: colors.stormGray50,
1137
+ backgroundColor: colors.white,
1138
+ padding: DROPDOWN_PADDING,
1139
+ overflow: "hidden"
1140
+ },
1141
+ dropdownScroll: {
1142
+ flex: 1
1143
+ },
1144
+ dropdownContent: {
1145
+ flexGrow: 1
1146
+ },
1147
+ option: {
1148
+ flexDirection: "row",
1149
+ alignItems: "center",
1150
+ height: OPTION_HEIGHT,
1151
+ borderRadius: radii.sm,
1152
+ padding: spacing.sm,
1153
+ gap: spacing.sm
156
1154
  },
157
- medium: {
158
- fontSize: 16
1155
+ optionSpacing: {
1156
+ marginBottom: OPTION_GAP
159
1157
  },
160
- large: {
161
- fontSize: 18
1158
+ optionSelected: {
1159
+ backgroundColor: colors.countrySelectorSelectedBg
1160
+ },
1161
+ optionDialCode: {
1162
+ fontFamily: fonts.sans,
1163
+ fontSize: fontSize.md,
1164
+ fontWeight: fontWeight.regular,
1165
+ lineHeight: fontSize.md,
1166
+ letterSpacing: 0,
1167
+ textAlign: "center",
1168
+ color: colors.slateBlue
162
1169
  }
163
1170
  });
164
- var textDisabledStyles = StyleSheet.create({
165
- primary: {
166
- color: "#e5e7eb"
1171
+ function PhoneInput({
1172
+ label,
1173
+ countryCode,
1174
+ onCountryCodeChange,
1175
+ error,
1176
+ hint,
1177
+ containerStyle,
1178
+ style,
1179
+ className,
1180
+ labelClassName,
1181
+ inputClassName,
1182
+ errorClassName,
1183
+ hintClassName,
1184
+ editable = true,
1185
+ onFocus,
1186
+ onBlur,
1187
+ ...props
1188
+ }) {
1189
+ const wrapperRef = useRef(null);
1190
+ const inputRef = useRef(null);
1191
+ const helperRef = useRef(null);
1192
+ const [focused, setFocused] = useState(false);
1193
+ useApplyWebClassName(wrapperRef, className);
1194
+ useApplyWebClassName(inputRef, inputClassName);
1195
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
1196
+ const isDisabled = editable === false;
1197
+ const phoneVisualState = resolveInputVisualState({
1198
+ focused,
1199
+ error: Boolean(error),
1200
+ disabled: isDisabled
1201
+ });
1202
+ const phoneFieldStyles = getInputFieldStyles(phoneVisualState);
1203
+ function handleFocus(event) {
1204
+ setFocused(true);
1205
+ onFocus?.(event);
1206
+ }
1207
+ function handleBlur(event) {
1208
+ setFocused(false);
1209
+ onBlur?.(event);
1210
+ }
1211
+ const helperMessage = error ?? hint;
1212
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles5.wrapper, containerStyle], children: [
1213
+ label ? /* @__PURE__ */ jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
1214
+ /* @__PURE__ */ jsxs(View, { style: styles5.row, children: [
1215
+ /* @__PURE__ */ jsx(
1216
+ CountryCodeSelector,
1217
+ {
1218
+ value: countryCode,
1219
+ onValueChange: onCountryCodeChange,
1220
+ disabled: isDisabled,
1221
+ style: styles5.countrySelector
1222
+ }
1223
+ ),
1224
+ /* @__PURE__ */ jsxs(View, { style: styles5.phoneColumn, children: [
1225
+ /* @__PURE__ */ jsx(View, { style: [phoneFieldStyles.outline, styles5.phoneOutline], children: /* @__PURE__ */ jsx(
1226
+ View,
1227
+ {
1228
+ style: [
1229
+ inputFieldMetrics.container,
1230
+ phoneFieldStyles.container,
1231
+ styles5.phoneField
1232
+ ],
1233
+ children: /* @__PURE__ */ jsx(
1234
+ TextInput,
1235
+ {
1236
+ ref: inputRef,
1237
+ style: [
1238
+ inputFieldMetrics.input,
1239
+ phoneFieldStyles.text,
1240
+ style
1241
+ ],
1242
+ keyboardType: "phone-pad",
1243
+ placeholderTextColor: phoneFieldStyles.placeholder,
1244
+ editable,
1245
+ onFocus: handleFocus,
1246
+ onBlur: handleBlur,
1247
+ accessibilityState: { disabled: isDisabled },
1248
+ ...props
1249
+ }
1250
+ )
1251
+ }
1252
+ ) }),
1253
+ helperMessage ? /* @__PURE__ */ jsx(Text, { ref: helperRef, style: error ? styles5.error : styles5.hint, children: helperMessage }) : null
1254
+ ] })
1255
+ ] })
1256
+ ] });
1257
+ }
1258
+ var styles5 = StyleSheet.create({
1259
+ wrapper: {
1260
+ width: "100%",
1261
+ gap: spacing.sm
1262
+ },
1263
+ row: {
1264
+ flexDirection: "row",
1265
+ alignItems: "flex-start",
1266
+ gap: INPUT_ICON_GAP
1267
+ },
1268
+ countrySelector: {
1269
+ flexShrink: 0,
1270
+ alignSelf: "flex-start"
1271
+ },
1272
+ phoneColumn: {
1273
+ flex: 1,
1274
+ gap: spacing.sm
1275
+ },
1276
+ phoneOutline: {
1277
+ width: "100%"
167
1278
  },
168
- secondary: {
169
- color: "#f3f4f6"
1279
+ phoneField: {
1280
+ flex: 1
170
1281
  },
171
- outline: {
172
- color: "#93c5fd"
1282
+ error: {
1283
+ fontSize: 12,
1284
+ lineHeight: 16,
1285
+ color: colors.inputError
173
1286
  },
174
- ghost: {
175
- color: "#93c5fd"
1287
+ hint: {
1288
+ fontSize: 12,
1289
+ lineHeight: 16,
1290
+ color: colors.stormGray300
176
1291
  }
177
1292
  });
178
1293
 
179
- export { Button };
1294
+ export { Button, CountryCodeSelector, Input, Label, PhoneInput, brand, buttonTypography, colors, countries, defaultCountry, emeraldGreen, findCountry, fontSize, fontWeight, fonts, labelTypography, navy, radii, rubyRed, shadows, spacing, stormGray };
180
1295
  //# sourceMappingURL=index.js.map
181
1296
  //# sourceMappingURL=index.js.map