@scripso-homepad/ui 0.4.1 → 0.4.3

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 (86) hide show
  1. package/dist/{chunk-C7GHBVMM.js → chunk-66WR57JJ.js} +53 -10
  2. package/dist/chunk-66WR57JJ.js.map +1 -0
  3. package/dist/index.cjs +2297 -391
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +144 -2
  6. package/dist/index.d.ts +144 -2
  7. package/dist/index.js +1978 -96
  8. package/dist/index.js.map +1 -1
  9. package/dist/web/index.cjs +30411 -759
  10. package/dist/web/index.cjs.map +1 -1
  11. package/dist/web/index.css +78 -0
  12. package/dist/web/index.css.map +1 -0
  13. package/dist/web/index.d.cts +267 -6
  14. package/dist/web/index.d.ts +267 -6
  15. package/dist/web/index.js +30179 -601
  16. package/dist/web/index.js.map +1 -1
  17. package/package.json +5 -4
  18. package/src/components/Calendar.stories.tsx +337 -0
  19. package/src/components/Calendar.tsx +441 -0
  20. package/src/components/DatePicker.stories.tsx +219 -0
  21. package/src/components/DatePicker.tsx +366 -0
  22. package/src/components/Input.tsx +5 -1
  23. package/src/components/Select.stories.tsx +134 -0
  24. package/src/components/Select.tsx +462 -0
  25. package/src/css.d.ts +1 -0
  26. package/src/icons/CalendarIcon.tsx +28 -0
  27. package/src/icons/CalendarIcon.web.tsx +34 -0
  28. package/src/icons/ChevronDownIcon.tsx +11 -4
  29. package/src/icons/ChevronDownIcon.web.tsx +6 -4
  30. package/src/icons/ChevronNavIcons.tsx +44 -0
  31. package/src/icons/ChevronNavIcons.web.tsx +57 -0
  32. package/src/icons/LockIcon.tsx +30 -0
  33. package/src/icons/LockIcon.web.tsx +35 -0
  34. package/src/icons/calendarIconPaths.ts +2 -0
  35. package/src/icons/chevronDownPath.ts +1 -0
  36. package/src/icons/chevronNavPaths.ts +2 -0
  37. package/src/icons/lockIconPaths.ts +2 -0
  38. package/src/index.ts +43 -0
  39. package/src/theme/calendar.ts +357 -0
  40. package/src/theme/input.ts +16 -6
  41. package/src/theme/select.ts +249 -0
  42. package/src/utils/calendarDays.ts +273 -0
  43. package/src/utils/calendarLocaleContext.tsx +95 -0
  44. package/src/utils/calendarLocalization.ts +187 -0
  45. package/src/utils/countryDropdownScrollStyles.ts +53 -13
  46. package/src/utils/formatMultiSelectDisplay.ts +56 -0
  47. package/src/web/components/Badge.stories.tsx +43 -0
  48. package/src/web/components/Badge.tsx +35 -0
  49. package/src/web/components/Pagination.stories.tsx +78 -0
  50. package/src/web/components/Pagination.tsx +153 -0
  51. package/src/web/components/StatusBadge.tsx +20 -0
  52. package/src/web/components/Table.stories.tsx +415 -0
  53. package/src/web/components/Table.tsx +3 -0
  54. package/src/web/components/TableActionButton.tsx +67 -0
  55. package/src/web/components/TableActionsMenu.tsx +208 -0
  56. package/src/web/components/TableIconText.tsx +23 -0
  57. package/src/web/components/TableRowStatusActions.tsx +33 -0
  58. package/src/web/components/TableStatusActionsCell.tsx +29 -0
  59. package/src/web/components/pagination-utils.ts +39 -0
  60. package/src/web/components/table/DataTable.tsx +123 -0
  61. package/src/web/components/table/TablePrimitives.tsx +214 -0
  62. package/src/web/components/table/TableScrollArea.tsx +51 -0
  63. package/src/web/components/table/constants.ts +59 -0
  64. package/src/web/components/table/data-table-class-names.ts +26 -0
  65. package/src/web/components/table/index.ts +44 -0
  66. package/src/web/components/table/table-row-context.tsx +19 -0
  67. package/src/web/components/table/use-horizontal-scroll-state.ts +72 -0
  68. package/src/web/components/table-scroll.css +81 -0
  69. package/src/web/hooks/useOnClickOutside.ts +20 -5
  70. package/src/web/icons/TableMenuActivateIcon.tsx +27 -0
  71. package/src/web/icons/TableMenuCheckIcon.tsx +27 -0
  72. package/src/web/icons/TableMenuCloseIcon.tsx +27 -0
  73. package/src/web/icons/TableMenuEditIcon.tsx +27 -0
  74. package/src/web/icons/TableMenuInfoIcon.tsx +27 -0
  75. package/src/web/icons/TableMenuRefreshIcon.tsx +27 -0
  76. package/src/web/icons/TableMenuSuspendIcon.tsx +34 -0
  77. package/src/web/icons/TableMenuTrashIcon.tsx +27 -0
  78. package/src/web/icons/TableMoreIcon.tsx +41 -0
  79. package/src/web/icons/TableSortIcon.tsx +37 -0
  80. package/src/web/index.ts +74 -0
  81. package/src/web/layout/AppHeader.stories.tsx +2 -0
  82. package/src/web/layout/AppHeader.tsx +18 -14
  83. package/src/web/layout/DashboardLayout.stories.tsx +1 -0
  84. package/src/web/layout/DashboardLayout.tsx +8 -4
  85. package/src/web/layout/story-helpers.tsx +10 -2
  86. package/dist/chunk-C7GHBVMM.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -2,12 +2,12 @@
2
2
 
3
3
  var react = require('react');
4
4
  var reactNative = require('react-native');
5
- var Svg = require('react-native-svg');
5
+ var Svg5 = require('react-native-svg');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
 
8
8
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
9
 
10
- var Svg__default = /*#__PURE__*/_interopDefault(Svg);
10
+ var Svg5__default = /*#__PURE__*/_interopDefault(Svg5);
11
11
 
12
12
  // src/components/Button.tsx
13
13
 
@@ -18,8 +18,8 @@ function ArrowUpRightIcon({
18
18
  color = "#08275d",
19
19
  strokeWidth = 2
20
20
  }) {
21
- return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
22
- Svg.Path,
21
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg5__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
22
+ Svg5.Path,
23
23
  {
24
24
  d: ARROW_UP_RIGHT_PATH,
25
25
  stroke: color,
@@ -467,9 +467,9 @@ function EyeIcon({
467
467
  color = "#c7cdd1",
468
468
  strokeWidth = 2
469
469
  }) {
470
- return /* @__PURE__ */ jsxRuntime.jsxs(Svg__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
470
+ return /* @__PURE__ */ jsxRuntime.jsxs(Svg5__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: [
471
471
  /* @__PURE__ */ jsxRuntime.jsx(
472
- Svg.Path,
472
+ Svg5.Path,
473
473
  {
474
474
  d: EYE_OPEN_OUTLINE_PATH,
475
475
  stroke: color,
@@ -479,7 +479,7 @@ function EyeIcon({
479
479
  }
480
480
  ),
481
481
  /* @__PURE__ */ jsxRuntime.jsx(
482
- Svg.Path,
482
+ Svg5.Path,
483
483
  {
484
484
  d: EYE_OPEN_PUPIL_PATH,
485
485
  stroke: color,
@@ -495,8 +495,8 @@ function EyeOffIcon({
495
495
  color = "#c7cdd1",
496
496
  strokeWidth = 2
497
497
  }) {
498
- return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
499
- Svg.Path,
498
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg5__default.default, { width: size, height: size, viewBox: "0 0 24 24", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
499
+ Svg5.Path,
500
500
  {
501
501
  d: EYE_OFF_PATH,
502
502
  stroke: color,
@@ -510,6 +510,9 @@ var INPUT_HEIGHT = 52;
510
510
  var INPUT_ICON_SIZE = 20;
511
511
  var INPUT_ICON_GAP = 10;
512
512
  var INPUT_OUTLINE_WIDTH = 2;
513
+ var INPUT_INNER_LINE_HEIGHT = 20;
514
+ var INPUT_WEB_INNER_LINE_HEIGHT = 22;
515
+ var INPUT_WEB_VERTICAL_PADDING = 14;
513
516
  function resolveInputVisualState({
514
517
  focused = false,
515
518
  error = false,
@@ -603,15 +606,19 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
603
606
  borderRadius: radii.lg,
604
607
  padding: 16,
605
608
  gap: INPUT_ICON_GAP,
606
- ...reactNative.Platform.OS === "web" ? { boxSizing: "border-box" } : null
609
+ ...reactNative.Platform.OS === "web" ? {
610
+ boxSizing: "border-box",
611
+ paddingVertical: INPUT_WEB_VERTICAL_PADDING,
612
+ paddingHorizontal: 16
613
+ } : null
607
614
  },
608
615
  input: {
609
616
  flex: 1,
610
- alignSelf: "stretch",
617
+ minWidth: 0,
611
618
  fontFamily: fonts.sans,
612
619
  fontSize: fontSize.md,
613
620
  fontWeight: fontWeight.medium,
614
- lineHeight: reactNative.Platform.OS === "web" ? fontSize.md : 20,
621
+ lineHeight: INPUT_INNER_LINE_HEIGHT,
615
622
  paddingVertical: 0,
616
623
  paddingHorizontal: 0,
617
624
  margin: 0,
@@ -619,10 +626,12 @@ var inputFieldMetrics = reactNative.StyleSheet.create({
619
626
  backgroundColor: colors.transparent,
620
627
  ...reactNative.Platform.OS === "android" ? { includeFontPadding: false } : null,
621
628
  ...reactNative.Platform.OS === "web" ? {
622
- height: "100%",
623
- minHeight: 0,
629
+ alignSelf: "center",
630
+ lineHeight: INPUT_WEB_INNER_LINE_HEIGHT,
624
631
  outlineStyle: "none"
625
- } : null
632
+ } : {
633
+ alignSelf: "stretch"
634
+ }
626
635
  }
627
636
  });
628
637
  function Label({
@@ -676,6 +685,7 @@ function Input({
676
685
  leftIcon,
677
686
  rightIcon,
678
687
  error,
688
+ invalid,
679
689
  hint,
680
690
  containerStyle,
681
691
  style,
@@ -704,11 +714,12 @@ function Input({
704
714
  useApplyWebClassName(inputRef, inputClassName);
705
715
  useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
706
716
  const isDisabled = editable === false;
717
+ const hasError = Boolean(error) || Boolean(invalid);
707
718
  const passwordToggleEnabled = secureTextEntry === true && showPasswordToggle !== false && rightIcon == null;
708
719
  const effectiveSecureTextEntry = passwordToggleEnabled ? !passwordVisible : secureTextEntry;
709
720
  const visualState = resolveInputVisualState({
710
721
  focused,
711
- error: Boolean(error),
722
+ error: hasError,
712
723
  disabled: isDisabled
713
724
  });
714
725
  const fieldStyles = getInputFieldStyles(visualState);
@@ -806,354 +817,643 @@ var styles3 = reactNative.StyleSheet.create({
806
817
  }
807
818
  });
808
819
 
809
- // src/data/countries.ts
810
- var defaultCountry = {
811
- code: "AM",
812
- name: "Armenia",
813
- dialCode: "+374"
814
- };
815
- var countries = [
816
- defaultCountry,
817
- { code: "AF", name: "Afghanistan", dialCode: "+93" },
818
- { code: "AL", name: "Albania", dialCode: "+355" },
819
- { code: "DZ", name: "Algeria", dialCode: "+213" },
820
- { code: "AR", name: "Argentina", dialCode: "+54" },
821
- { code: "AU", name: "Australia", dialCode: "+61" },
822
- { code: "AT", name: "Austria", dialCode: "+43" },
823
- { code: "AZ", name: "Azerbaijan", dialCode: "+994" },
824
- { code: "BH", name: "Bahrain", dialCode: "+973" },
825
- { code: "BY", name: "Belarus", dialCode: "+375" },
826
- { code: "BE", name: "Belgium", dialCode: "+32" },
827
- { code: "BR", name: "Brazil", dialCode: "+55" },
828
- { code: "BG", name: "Bulgaria", dialCode: "+359" },
829
- { code: "CA", name: "Canada", dialCode: "+1" },
830
- { code: "CL", name: "Chile", dialCode: "+56" },
831
- { code: "CN", name: "China", dialCode: "+86" },
832
- { code: "CO", name: "Colombia", dialCode: "+57" },
833
- { code: "HR", name: "Croatia", dialCode: "+385" },
834
- { code: "CY", name: "Cyprus", dialCode: "+357" },
835
- { code: "CZ", name: "Czech Republic", dialCode: "+420" },
836
- { code: "DK", name: "Denmark", dialCode: "+45" },
837
- { code: "EG", name: "Egypt", dialCode: "+20" },
838
- { code: "EE", name: "Estonia", dialCode: "+372" },
839
- { code: "FI", name: "Finland", dialCode: "+358" },
840
- { code: "FR", name: "France", dialCode: "+33" },
841
- { code: "GE", name: "Georgia", dialCode: "+995" },
842
- { code: "DE", name: "Germany", dialCode: "+49" },
843
- { code: "GR", name: "Greece", dialCode: "+30" },
844
- { code: "HK", name: "Hong Kong", dialCode: "+852" },
845
- { code: "HU", name: "Hungary", dialCode: "+36" },
846
- { code: "IN", name: "India", dialCode: "+91" },
847
- { code: "ID", name: "Indonesia", dialCode: "+62" },
848
- { code: "IR", name: "Iran", dialCode: "+98" },
849
- { code: "IQ", name: "Iraq", dialCode: "+964" },
850
- { code: "IE", name: "Ireland", dialCode: "+353" },
851
- { code: "IL", name: "Israel", dialCode: "+972" },
852
- { code: "IT", name: "Italy", dialCode: "+39" },
853
- { code: "JP", name: "Japan", dialCode: "+81" },
854
- { code: "JO", name: "Jordan", dialCode: "+962" },
855
- { code: "KZ", name: "Kazakhstan", dialCode: "+7" },
856
- { code: "KW", name: "Kuwait", dialCode: "+965" },
857
- { code: "LV", name: "Latvia", dialCode: "+371" },
858
- { code: "LB", name: "Lebanon", dialCode: "+961" },
859
- { code: "LT", name: "Lithuania", dialCode: "+370" },
860
- { code: "LU", name: "Luxembourg", dialCode: "+352" },
861
- { code: "MY", name: "Malaysia", dialCode: "+60" },
862
- { code: "MX", name: "Mexico", dialCode: "+52" },
863
- { code: "MD", name: "Moldova", dialCode: "+373" },
864
- { code: "NL", name: "Netherlands", dialCode: "+31" },
865
- { code: "NZ", name: "New Zealand", dialCode: "+64" },
866
- { code: "NG", name: "Nigeria", dialCode: "+234" },
867
- { code: "NO", name: "Norway", dialCode: "+47" },
868
- { code: "PK", name: "Pakistan", dialCode: "+92" },
869
- { code: "PS", name: "Palestine", dialCode: "+970" },
870
- { code: "PH", name: "Philippines", dialCode: "+63" },
871
- { code: "PL", name: "Poland", dialCode: "+48" },
872
- { code: "PT", name: "Portugal", dialCode: "+351" },
873
- { code: "QA", name: "Qatar", dialCode: "+974" },
874
- { code: "RO", name: "Romania", dialCode: "+40" },
875
- { code: "RU", name: "Russia", dialCode: "+7" },
876
- { code: "SA", name: "Saudi Arabia", dialCode: "+966" },
877
- { code: "RS", name: "Serbia", dialCode: "+381" },
878
- { code: "SG", name: "Singapore", dialCode: "+65" },
879
- { code: "SK", name: "Slovakia", dialCode: "+421" },
880
- { code: "SI", name: "Slovenia", dialCode: "+386" },
881
- { code: "ZA", name: "South Africa", dialCode: "+27" },
882
- { code: "KR", name: "South Korea", dialCode: "+82" },
883
- { code: "ES", name: "Spain", dialCode: "+34" },
884
- { code: "SE", name: "Sweden", dialCode: "+46" },
885
- { code: "CH", name: "Switzerland", dialCode: "+41" },
886
- { code: "SY", name: "Syria", dialCode: "+963" },
887
- { code: "TW", name: "Taiwan", dialCode: "+886" },
888
- { code: "TH", name: "Thailand", dialCode: "+66" },
889
- { code: "TR", name: "Turkey", dialCode: "+90" },
890
- { code: "UA", name: "Ukraine", dialCode: "+380" },
891
- { code: "AE", name: "United Arab Emirates", dialCode: "+971" },
892
- { code: "GB", name: "United Kingdom", dialCode: "+44" },
893
- { code: "US", name: "United States", dialCode: "+1" },
894
- { code: "UZ", name: "Uzbekistan", dialCode: "+998" },
895
- { code: "VN", name: "Vietnam", dialCode: "+84" }
896
- ];
897
- function findCountry(code) {
898
- return countries.find((country) => country.code === code) ?? defaultCountry;
899
- }
900
-
901
820
  // src/icons/chevronDownPath.ts
902
821
  var CHEVRON_DOWN_PATH = "M4 6L8 10L12 6";
822
+ var CHEVRON_DOWN_PATH_20 = "M5 7.5L10 12.5L15 7.5";
903
823
  function ChevronDownIcon({
904
824
  size = 16,
905
825
  color = "#dadde0",
906
826
  strokeWidth = 2
907
827
  }) {
908
- return /* @__PURE__ */ jsxRuntime.jsx(Svg__default.default, { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
909
- Svg.Path,
828
+ const useLarge = size >= 20;
829
+ return /* @__PURE__ */ jsxRuntime.jsx(
830
+ Svg5__default.default,
910
831
  {
911
- d: CHEVRON_DOWN_PATH,
912
- stroke: color,
913
- strokeWidth,
914
- strokeLinecap: "round",
915
- strokeLinejoin: "round"
832
+ width: size,
833
+ height: size,
834
+ viewBox: useLarge ? "0 0 20 20" : "0 0 16 16",
835
+ fill: "none",
836
+ children: /* @__PURE__ */ jsxRuntime.jsx(
837
+ Svg5.Path,
838
+ {
839
+ d: useLarge ? CHEVRON_DOWN_PATH_20 : CHEVRON_DOWN_PATH,
840
+ stroke: color,
841
+ strokeWidth,
842
+ strokeLinecap: "round",
843
+ strokeLinejoin: "round"
844
+ }
845
+ )
916
846
  }
917
- ) });
918
- }
919
-
920
- // src/utils/countryFlag.ts
921
- function countryCodeToFlagEmoji(code) {
922
- const upper = code.trim().toUpperCase();
923
- if (upper.length !== 2) return "";
924
- return String.fromCodePoint(
925
- ...upper.split("").map((char) => 127462 - 65 + char.charCodeAt(0))
926
847
  );
927
848
  }
849
+ var SELECT_HEIGHT = 52;
850
+ var SELECT_PADDING = 16;
851
+ var SELECT_INNER_GAP = 10;
852
+ var SELECT_ICON_SIZE = 20;
853
+ var SELECT_LABEL_GAP = spacing.sm;
854
+ var SELECT_DROPDOWN_GAP = spacing.sm;
855
+ var SELECT_DROPDOWN_PADDING = spacing.sm;
856
+ var SELECT_DROPDOWN_MAX_HEIGHT = 317;
857
+ var SELECT_OPTION_HEIGHT = 43;
858
+ var SELECT_OPTION_GAP = spacing.sm;
859
+ var SELECT_CHEVRON_SIZE = 20;
860
+ var SELECT_CHEVRON_COLOR = colors.stormGray150;
861
+ var SELECT_CHEVRON_ROTATION_MS = 200;
862
+ var selectLabelTypography = {
863
+ fontFamily: fonts.sans,
864
+ fontSize: fontSize.sm,
865
+ fontWeight: fontWeight.medium,
866
+ lineHeight: fontSize.sm,
867
+ letterSpacing: 0,
868
+ color: colors.slateBlue
869
+ };
870
+ var selectValueTypography = {
871
+ fontFamily: fonts.sans,
872
+ fontSize: fontSize.md,
873
+ fontWeight: fontWeight.regular,
874
+ lineHeight: fontSize.md,
875
+ letterSpacing: 0,
876
+ textAlign: "left"
877
+ };
878
+ var INPUT_OUTLINE_WIDTH2 = 2;
879
+ function createOutlineStyle2(ringColor) {
880
+ return {
881
+ borderRadius: radii.lg + INPUT_OUTLINE_WIDTH2,
882
+ borderWidth: INPUT_OUTLINE_WIDTH2,
883
+ borderColor: ringColor,
884
+ padding: 0,
885
+ backgroundColor: colors.transparent,
886
+ width: "100%",
887
+ alignSelf: "stretch",
888
+ ...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
889
+ };
890
+ }
891
+ var defaultOutline2 = createOutlineStyle2(colors.transparent);
892
+ function getSelectFieldStyles(state) {
893
+ const containerBase = {
894
+ borderRadius: radii.lg,
895
+ ...reactNative.Platform.OS !== "web" ? { overflow: "hidden" } : null
896
+ };
897
+ const valueBase = {
898
+ ...selectValueTypography,
899
+ color: colors.slateBlue
900
+ };
901
+ switch (state) {
902
+ case "disabled":
903
+ return {
904
+ outline: defaultOutline2,
905
+ container: {
906
+ ...containerBase,
907
+ borderWidth: 1,
908
+ borderColor: colors.stormGray50,
909
+ backgroundColor: colors.stormGray50
910
+ },
911
+ value: { ...valueBase, color: colors.stormGray300 },
912
+ placeholder: colors.stormGray300,
913
+ icon: colors.stormGray150
914
+ };
915
+ case "error":
916
+ return {
917
+ outline: createOutlineStyle2(colors.inputOutlineError),
918
+ container: {
919
+ ...containerBase,
920
+ borderWidth: 1,
921
+ borderColor: colors.inputError,
922
+ backgroundColor: colors.white
923
+ },
924
+ value: { ...valueBase, color: colors.inputError },
925
+ placeholder: colors.stormGray200,
926
+ icon: colors.inputError
927
+ };
928
+ case "focused":
929
+ return {
930
+ outline: createOutlineStyle2(colors.inputOutlineFocus),
931
+ container: {
932
+ ...containerBase,
933
+ borderWidth: 1,
934
+ borderColor: colors.navy,
935
+ backgroundColor: colors.white
936
+ },
937
+ value: valueBase,
938
+ placeholder: colors.stormGray200,
939
+ icon: colors.navy
940
+ };
941
+ default:
942
+ return {
943
+ outline: defaultOutline2,
944
+ container: {
945
+ ...containerBase,
946
+ borderWidth: 1,
947
+ borderColor: colors.stormGray50,
948
+ backgroundColor: colors.white
949
+ },
950
+ value: valueBase,
951
+ placeholder: colors.stormGray200,
952
+ icon: colors.stormGray150
953
+ };
954
+ }
955
+ }
956
+ var selectFieldMetrics = reactNative.StyleSheet.create({
957
+ container: {
958
+ flexDirection: "row",
959
+ alignItems: "center",
960
+ height: SELECT_HEIGHT,
961
+ minHeight: SELECT_HEIGHT,
962
+ maxHeight: SELECT_HEIGHT,
963
+ borderRadius: radii.lg,
964
+ padding: SELECT_PADDING,
965
+ gap: SELECT_INNER_GAP,
966
+ ...reactNative.Platform.OS === "web" ? {
967
+ boxSizing: "border-box"
968
+ } : null
969
+ },
970
+ value: {
971
+ flex: 1,
972
+ minWidth: 0,
973
+ ...selectValueTypography,
974
+ paddingVertical: 0,
975
+ paddingHorizontal: 0,
976
+ margin: 0,
977
+ ...reactNative.Platform.OS === "android" ? { includeFontPadding: false } : null,
978
+ ...reactNative.Platform.OS === "web" ? {
979
+ outlineStyle: "none"
980
+ } : null
981
+ }
982
+ });
983
+ var selectDropdownMetrics = reactNative.StyleSheet.create({
984
+ menu: {
985
+ borderRadius: radii.lg,
986
+ borderWidth: 1,
987
+ borderColor: colors.stormGray50,
988
+ backgroundColor: colors.white,
989
+ padding: SELECT_DROPDOWN_PADDING,
990
+ overflow: "hidden"
991
+ },
992
+ option: {
993
+ width: "100%",
994
+ height: SELECT_OPTION_HEIGHT,
995
+ minHeight: SELECT_OPTION_HEIGHT,
996
+ maxHeight: SELECT_OPTION_HEIGHT,
997
+ paddingTop: 12,
998
+ paddingRight: spacing.sm,
999
+ paddingBottom: 12,
1000
+ paddingLeft: spacing.sm,
1001
+ justifyContent: "center",
1002
+ alignItems: "flex-start"
1003
+ },
1004
+ optionLabel: {
1005
+ fontFamily: fonts.sans,
1006
+ fontSize: fontSize.md,
1007
+ fontWeight: fontWeight.regular,
1008
+ lineHeight: fontSize.md,
1009
+ letterSpacing: 0,
1010
+ textAlign: "left",
1011
+ color: colors.slateBlue,
1012
+ width: "100%"
1013
+ },
1014
+ optionLabelSelected: {
1015
+ fontWeight: fontWeight.medium,
1016
+ color: colors.slateBlue
1017
+ },
1018
+ optionSelected: {
1019
+ opacity: 1,
1020
+ borderRadius: radii.sm,
1021
+ paddingTop: 12,
1022
+ paddingRight: spacing.sm,
1023
+ paddingBottom: 12,
1024
+ paddingLeft: spacing.sm,
1025
+ backgroundColor: colors.countrySelectorSelectedBg
1026
+ },
1027
+ optionHighlighted: {
1028
+ backgroundColor: colors.stormGray0
1029
+ }
1030
+ });
1031
+ function resolveSelectDropdownHeight(optionCount) {
1032
+ const contentHeight = optionCount * SELECT_OPTION_HEIGHT + Math.max(0, optionCount - 1) * SELECT_OPTION_GAP + SELECT_DROPDOWN_PADDING * 2;
1033
+ return Math.min(contentHeight, SELECT_DROPDOWN_MAX_HEIGHT);
1034
+ }
1035
+ function resolveSelectDropdownTop(anchor, dropdownHeight) {
1036
+ const windowHeight = reactNative.Dimensions.get("window").height;
1037
+ const spaceBelow = windowHeight - (anchor.y + anchor.height + SELECT_DROPDOWN_GAP);
1038
+ const spaceAbove = anchor.y - SELECT_DROPDOWN_GAP;
1039
+ const topBelow = anchor.y + anchor.height + SELECT_DROPDOWN_GAP;
1040
+ const topAbove = anchor.y - SELECT_DROPDOWN_GAP - dropdownHeight;
1041
+ if (spaceBelow >= dropdownHeight) {
1042
+ return topBelow;
1043
+ }
1044
+ if (spaceAbove >= dropdownHeight) {
1045
+ return topAbove;
1046
+ }
1047
+ if (spaceAbove > spaceBelow) {
1048
+ return Math.max(0, topAbove);
1049
+ }
1050
+ return Math.max(0, Math.min(topBelow, windowHeight - dropdownHeight));
1051
+ }
928
1052
  var COUNTRY_DROPDOWN_SCROLL_CLASS = "hp-country-dropdown-scroll";
929
- var STYLE_ID = "hp-country-dropdown-scroll-styles";
930
- var countryDropdownScrollCss = `
931
- .${COUNTRY_DROPDOWN_SCROLL_CLASS} {
1053
+ var SELECT_DROPDOWN_SCROLL_CLASS = "hp-select-dropdown-scroll";
1054
+ var STYLE_ID = "hp-dropdown-scroll-styles";
1055
+ function createDropdownScrollCss(className) {
1056
+ return `
1057
+ .${className} {
932
1058
  scrollbar-width: thin;
933
1059
  scrollbar-color: ${colors.stormGray300} transparent;
934
1060
  overflow-y: auto;
935
1061
  }
936
1062
 
937
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar {
1063
+ .${className}::-webkit-scrollbar {
938
1064
  width: 4px;
1065
+ -webkit-appearance: none;
1066
+ appearance: none;
939
1067
  }
940
1068
 
941
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-corner {
1069
+ .${className}::-webkit-scrollbar-corner {
942
1070
  background: transparent;
943
1071
  }
944
1072
 
945
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button,
946
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:single-button,
947
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:vertical:start:decrement,
948
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:vertical:end:increment {
1073
+ .${className}::-webkit-scrollbar-button,
1074
+ .${className}::-webkit-scrollbar-button:single-button,
1075
+ .${className}::-webkit-scrollbar-button:double-button,
1076
+ .${className}::-webkit-scrollbar-button:horizontal:decrement,
1077
+ .${className}::-webkit-scrollbar-button:horizontal:increment,
1078
+ .${className}::-webkit-scrollbar-button:horizontal:start:decrement,
1079
+ .${className}::-webkit-scrollbar-button:horizontal:end:increment,
1080
+ .${className}::-webkit-scrollbar-button:vertical:decrement,
1081
+ .${className}::-webkit-scrollbar-button:vertical:increment,
1082
+ .${className}::-webkit-scrollbar-button:vertical:start:decrement,
1083
+ .${className}::-webkit-scrollbar-button:vertical:end:increment,
1084
+ .${className}::-webkit-scrollbar-button:start:decrement,
1085
+ .${className}::-webkit-scrollbar-button:end:increment,
1086
+ .${className}::-webkit-scrollbar-button:decrement,
1087
+ .${className}::-webkit-scrollbar-button:increment {
949
1088
  display: none;
950
1089
  width: 0;
951
1090
  height: 0;
1091
+ max-width: 0;
1092
+ max-height: 0;
1093
+ min-width: 0;
1094
+ min-height: 0;
1095
+ padding: 0;
1096
+ margin: 0;
1097
+ border: 0;
1098
+ background: transparent;
952
1099
  -webkit-appearance: none;
953
1100
  appearance: none;
954
1101
  }
955
1102
 
956
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-track {
1103
+ .${className}::-webkit-scrollbar-track {
957
1104
  background: transparent;
958
1105
  }
959
1106
 
960
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-thumb {
1107
+ .${className}::-webkit-scrollbar-thumb {
961
1108
  background-color: ${colors.stormGray300};
962
1109
  border-radius: 9999px;
963
1110
  }
964
1111
  `;
965
- function ensureCountryDropdownScrollStyles() {
1112
+ }
1113
+ var dropdownScrollCss = [
1114
+ createDropdownScrollCss(COUNTRY_DROPDOWN_SCROLL_CLASS),
1115
+ createDropdownScrollCss(SELECT_DROPDOWN_SCROLL_CLASS)
1116
+ ].join("\n");
1117
+ function ensureDropdownScrollStyles() {
966
1118
  if (reactNative.Platform.OS !== "web" || typeof document === "undefined") return;
967
1119
  if (document.getElementById(STYLE_ID)) return;
968
1120
  const style = document.createElement("style");
969
1121
  style.id = STYLE_ID;
970
- style.textContent = countryDropdownScrollCss;
1122
+ style.textContent = dropdownScrollCss;
971
1123
  document.head.appendChild(style);
972
1124
  }
973
- var DROPDOWN_GAP = 10;
974
- var DROPDOWN_HEIGHT = 186;
975
- var DROPDOWN_PADDING = 8;
976
- var OPTION_GAP = 10;
977
- var OPTION_HEIGHT = 35;
978
- var TRIGGER_HEIGHT = 52;
979
- var CHEVRON_SIZE = 16;
980
- function resolveDropdownTop(anchor) {
981
- const windowHeight = reactNative.Dimensions.get("window").height;
982
- const topBelow = anchor.y + anchor.height + DROPDOWN_GAP;
983
- const topAbove = anchor.y - DROPDOWN_GAP - DROPDOWN_HEIGHT;
984
- const fitsBelow = topBelow + DROPDOWN_HEIGHT <= windowHeight;
985
- if (fitsBelow) return topBelow;
986
- if (topAbove >= 0) return topAbove;
987
- return Math.max(0, Math.min(topBelow, windowHeight - DROPDOWN_HEIGHT));
1125
+ function ensureCountryDropdownScrollStyles() {
1126
+ ensureDropdownScrollStyles();
988
1127
  }
989
- function CountryCodeSelector({
990
- value = defaultCountry.code,
991
- onValueChange,
992
- options = countries,
1128
+ function ensureSelectDropdownScrollStyles() {
1129
+ ensureDropdownScrollStyles();
1130
+ }
1131
+
1132
+ // src/utils/formatMultiSelectDisplay.ts
1133
+ var MULTI_SELECT_SUFFIX = " ... + ";
1134
+ var MULTI_SELECT_SUFFIX_UNIT = " items";
1135
+ function estimateTextWidth(text, size = fontSize.md) {
1136
+ return text.length * size * 0.58;
1137
+ }
1138
+ function formatMultiSelectDisplay(labels, maxWidth, textSize = fontSize.md) {
1139
+ if (labels.length === 0) {
1140
+ return "";
1141
+ }
1142
+ if (labels.length === 1) {
1143
+ return labels[0];
1144
+ }
1145
+ const fits = (text) => estimateTextWidth(text, textSize) <= maxWidth;
1146
+ const fullText = labels.join(", ");
1147
+ if (fits(fullText)) {
1148
+ return fullText;
1149
+ }
1150
+ for (let visibleCount = labels.length - 1; visibleCount >= 1; visibleCount -= 1) {
1151
+ const hiddenCount = labels.length - visibleCount;
1152
+ const truncatedText = `${labels.slice(0, visibleCount).join(", ")}${MULTI_SELECT_SUFFIX}${hiddenCount}${MULTI_SELECT_SUFFIX_UNIT}`;
1153
+ if (fits(truncatedText)) {
1154
+ return truncatedText;
1155
+ }
1156
+ }
1157
+ return `... + ${labels.length}${MULTI_SELECT_SUFFIX_UNIT}`;
1158
+ }
1159
+ function resolveSelectedLabels(options, selectedValues) {
1160
+ if (selectedValues.length === 0) {
1161
+ return [];
1162
+ }
1163
+ const labelByValue = new Map(options.map((option) => [option.value, option.label]));
1164
+ return selectedValues.map((value) => labelByValue.get(value)).filter((label) => Boolean(label));
1165
+ }
1166
+ function renderSelectIcon(icon, color) {
1167
+ if (!icon) return null;
1168
+ if (react.isValidElement(icon)) {
1169
+ return react.cloneElement(icon, {
1170
+ size: icon.props.size ?? SELECT_ICON_SIZE,
1171
+ color: icon.props.color ?? color
1172
+ });
1173
+ }
1174
+ return icon;
1175
+ }
1176
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? react.useEffect : react.useLayoutEffect;
1177
+ function normalizeSelectedValues(multiple, value) {
1178
+ if (multiple) {
1179
+ if (Array.isArray(value)) {
1180
+ return value;
1181
+ }
1182
+ return value ? [value] : [];
1183
+ }
1184
+ return typeof value === "string" && value.length > 0 ? [value] : [];
1185
+ }
1186
+ function Select({
1187
+ label,
1188
+ placeholder = "placeholder",
1189
+ value,
1190
+ onValueChange,
1191
+ options,
1192
+ leftIcon,
1193
+ multiple = false,
993
1194
  disabled = false,
994
- style,
995
- className
1195
+ error,
1196
+ invalid,
1197
+ hint,
1198
+ containerStyle,
1199
+ className,
1200
+ fieldClassName,
1201
+ menuClassName,
1202
+ labelClassName,
1203
+ errorClassName,
1204
+ hintClassName
996
1205
  }) {
997
1206
  const wrapperRef = react.useRef(null);
998
1207
  const triggerRef = react.useRef(null);
1208
+ const menuRef = react.useRef(null);
999
1209
  const scrollRef = react.useRef(null);
1210
+ const helperRef = react.useRef(null);
1211
+ const chevronRotation = react.useRef(new reactNative.Animated.Value(0)).current;
1000
1212
  const [open, setOpen] = react.useState(false);
1001
1213
  const [anchor, setAnchor] = react.useState(null);
1214
+ const [highlightedIndex, setHighlightedIndex] = react.useState(-1);
1215
+ const [valueContainerWidth, setValueContainerWidth] = react.useState(0);
1002
1216
  useApplyWebClassName(wrapperRef, className);
1003
- useApplyWebClassName(
1004
- scrollRef,
1005
- COUNTRY_DROPDOWN_SCROLL_CLASS,
1006
- open && Boolean(anchor)
1007
- );
1008
- react.useLayoutEffect(() => {
1009
- ensureCountryDropdownScrollStyles();
1217
+ useApplyWebClassName(triggerRef, fieldClassName);
1218
+ useApplyWebClassName(menuRef, menuClassName);
1219
+ useApplyWebClassName(scrollRef, SELECT_DROPDOWN_SCROLL_CLASS, open && Boolean(anchor));
1220
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
1221
+ useIsomorphicLayoutEffect(() => {
1222
+ ensureSelectDropdownScrollStyles();
1010
1223
  }, []);
1011
- const selected = findCountry(value);
1012
- const textColor = disabled ? colors.stormGray200 : colors.slateBlue;
1013
- function closeDropdown() {
1224
+ react.useEffect(() => {
1225
+ reactNative.Animated.timing(chevronRotation, {
1226
+ toValue: open ? 1 : 0,
1227
+ duration: SELECT_CHEVRON_ROTATION_MS,
1228
+ easing: reactNative.Easing.out(reactNative.Easing.ease),
1229
+ useNativeDriver: true
1230
+ }).start();
1231
+ }, [chevronRotation, open]);
1232
+ const chevronRotate = chevronRotation.interpolate({
1233
+ inputRange: [0, 1],
1234
+ outputRange: ["0deg", "180deg"]
1235
+ });
1236
+ const hasError = Boolean(error) || Boolean(invalid);
1237
+ const visualState = resolveInputVisualState({
1238
+ focused: open,
1239
+ error: hasError,
1240
+ disabled
1241
+ });
1242
+ const fieldStyles = getSelectFieldStyles(visualState);
1243
+ const selectedValues = react.useMemo(
1244
+ () => normalizeSelectedValues(multiple, value),
1245
+ [multiple, value]
1246
+ );
1247
+ const selectedValueSet = react.useMemo(() => new Set(selectedValues), [selectedValues]);
1248
+ const selectedLabels = react.useMemo(
1249
+ () => resolveSelectedLabels(options, selectedValues),
1250
+ [options, selectedValues]
1251
+ );
1252
+ const selectableOptions = react.useMemo(
1253
+ () => options.filter((option) => !option.disabled),
1254
+ [options]
1255
+ );
1256
+ const selectableIndexByValue = react.useMemo(
1257
+ () => new Map(
1258
+ selectableOptions.map((option, index) => [option.value, index])
1259
+ ),
1260
+ [selectableOptions]
1261
+ );
1262
+ const displayLabel = react.useMemo(() => {
1263
+ if (selectedLabels.length === 0) {
1264
+ return placeholder;
1265
+ }
1266
+ if (!multiple) {
1267
+ return selectedLabels[0];
1268
+ }
1269
+ if (valueContainerWidth <= 0) {
1270
+ return selectedLabels.join(", ");
1271
+ }
1272
+ return formatMultiSelectDisplay(selectedLabels, valueContainerWidth);
1273
+ }, [multiple, placeholder, selectedLabels, valueContainerWidth]);
1274
+ const isPlaceholder = selectedLabels.length === 0;
1275
+ const dropdownHeight = resolveSelectDropdownHeight(options.length);
1276
+ const helperMessage = error ?? hint;
1277
+ function closeMenu() {
1014
1278
  setOpen(false);
1015
1279
  setAnchor(null);
1280
+ setHighlightedIndex(-1);
1016
1281
  }
1017
- function handleOpen() {
1018
- if (disabled) return;
1282
+ function openMenu() {
1283
+ if (disabled || selectableOptions.length === 0) {
1284
+ return;
1285
+ }
1019
1286
  triggerRef.current?.measureInWindow((x, y, width, height) => {
1287
+ const selectedIndex = selectableOptions.findIndex(
1288
+ (option) => selectedValueSet.has(option.value)
1289
+ );
1290
+ setHighlightedIndex(selectedIndex >= 0 ? selectedIndex : 0);
1020
1291
  setAnchor({ x, y, width, height });
1021
1292
  setOpen(true);
1022
1293
  });
1023
1294
  }
1024
- function handleSelect(code) {
1025
- onValueChange?.(code);
1026
- closeDropdown();
1295
+ function handleSelect(nextValue) {
1296
+ if (multiple) {
1297
+ const nextValues = selectedValues.includes(nextValue) ? selectedValues.filter((item) => item !== nextValue) : [...selectedValues, nextValue];
1298
+ onValueChange?.(nextValues);
1299
+ return;
1300
+ }
1301
+ onValueChange?.(nextValue);
1302
+ closeMenu();
1027
1303
  }
1028
- const dropdownTop = anchor ? resolveDropdownTop(anchor) : 0;
1029
- const optionList = options.map((item, index) => {
1030
- const isSelected = item.code === selected.code;
1304
+ const optionList = options.map((option, index) => {
1305
+ const selectableIndex = selectableIndexByValue.get(option.value) ?? -1;
1306
+ const isSelected = selectedValueSet.has(option.value);
1307
+ const isHighlighted = selectableIndex === highlightedIndex;
1031
1308
  const isLast = index === options.length - 1;
1032
- return /* @__PURE__ */ jsxRuntime.jsxs(
1309
+ return /* @__PURE__ */ jsxRuntime.jsx(
1033
1310
  reactNative.Pressable,
1034
1311
  {
1035
1312
  accessibilityRole: "button",
1036
- onPress: () => handleSelect(item.code),
1313
+ accessibilityState: { disabled: option.disabled, selected: isSelected },
1314
+ disabled: option.disabled,
1315
+ onPress: () => {
1316
+ if (!option.disabled) {
1317
+ handleSelect(option.value);
1318
+ }
1319
+ },
1320
+ onHoverIn: () => {
1321
+ if (!option.disabled && selectableIndex >= 0) {
1322
+ setHighlightedIndex(selectableIndex);
1323
+ }
1324
+ },
1037
1325
  style: [
1038
- styles4.option,
1039
- isSelected && styles4.optionSelected,
1040
- !isLast && styles4.optionSpacing
1326
+ selectDropdownMetrics.option,
1327
+ isSelected && selectDropdownMetrics.optionSelected,
1328
+ isHighlighted && !isSelected && !option.disabled ? selectDropdownMetrics.optionHighlighted : null,
1329
+ !isLast && styles4.optionSpacing,
1330
+ option.disabled && styles4.optionDisabled
1041
1331
  ],
1042
- children: [
1043
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.flag, children: countryCodeToFlagEmoji(item.code) }),
1044
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.optionDialCode, children: item.dialCode })
1045
- ]
1332
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1333
+ reactNative.Text,
1334
+ {
1335
+ style: [
1336
+ selectDropdownMetrics.optionLabel,
1337
+ isSelected && selectDropdownMetrics.optionLabelSelected,
1338
+ option.disabled && styles4.optionLabelDisabled
1339
+ ],
1340
+ numberOfLines: 1,
1341
+ children: option.label
1342
+ }
1343
+ )
1046
1344
  },
1047
- item.code
1345
+ option.value
1048
1346
  );
1049
1347
  });
1050
- const dropdownList = /* @__PURE__ */ jsxRuntime.jsx(
1051
- reactNative.ScrollView,
1052
- {
1053
- ref: scrollRef,
1054
- style: styles4.dropdownScroll,
1055
- contentContainerStyle: styles4.dropdownContent,
1056
- keyboardShouldPersistTaps: "handled",
1057
- showsVerticalScrollIndicator: true,
1058
- bounces: false,
1059
- nestedScrollEnabled: true,
1060
- children: optionList
1061
- }
1062
- );
1063
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles4.root, style], children: [
1064
- /* @__PURE__ */ jsxRuntime.jsxs(
1348
+ const dropdownTop = anchor ? resolveSelectDropdownTop(anchor, dropdownHeight) : 0;
1349
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles4.wrapper, containerStyle], children: [
1350
+ label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled, style: styles4.label, className: labelClassName, children: label }) : null,
1351
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxRuntime.jsxs(
1065
1352
  reactNative.Pressable,
1066
1353
  {
1067
1354
  ref: triggerRef,
1068
1355
  accessibilityRole: "button",
1356
+ accessibilityState: { disabled, expanded: open },
1069
1357
  disabled,
1070
- onPress: handleOpen,
1071
- style: [
1072
- styles4.trigger,
1073
- disabled ? styles4.triggerDisabled : styles4.triggerEnabled,
1074
- reactNative.Platform.OS === "web" ? styles4.triggerWeb : null
1075
- ],
1358
+ onPress: open ? closeMenu : openMenu,
1359
+ style: [selectFieldMetrics.container, fieldStyles.container],
1076
1360
  children: [
1077
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles4.flag, children: countryCodeToFlagEmoji(selected.code) }),
1078
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles4.dialCode, { color: textColor }], children: selected.dialCode }),
1079
- /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: CHEVRON_SIZE, color: colors.stormGray100 })
1361
+ leftIcon ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles4.iconSlot, children: renderSelectIcon(leftIcon, fieldStyles.icon) }) : null,
1362
+ /* @__PURE__ */ jsxRuntime.jsx(
1363
+ reactNative.View,
1364
+ {
1365
+ style: styles4.valueContainer,
1366
+ onLayout: (event) => {
1367
+ setValueContainerWidth(event.nativeEvent.layout.width);
1368
+ },
1369
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1370
+ reactNative.Text,
1371
+ {
1372
+ style: [
1373
+ selectFieldMetrics.value,
1374
+ fieldStyles.value,
1375
+ isPlaceholder && { color: fieldStyles.placeholder }
1376
+ ],
1377
+ numberOfLines: 1,
1378
+ children: displayLabel
1379
+ }
1380
+ )
1381
+ }
1382
+ ),
1383
+ /* @__PURE__ */ jsxRuntime.jsx(
1384
+ reactNative.Animated.View,
1385
+ {
1386
+ style: [styles4.iconSlot, { transform: [{ rotate: chevronRotate }] }],
1387
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1388
+ ChevronDownIcon,
1389
+ {
1390
+ size: SELECT_CHEVRON_SIZE,
1391
+ color: disabled ? colors.stormGray200 : SELECT_CHEVRON_COLOR
1392
+ }
1393
+ )
1394
+ }
1395
+ )
1080
1396
  ]
1081
1397
  }
1082
- ),
1083
- /* @__PURE__ */ jsxRuntime.jsx(
1084
- reactNative.Modal,
1398
+ ) }),
1399
+ helperMessage ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: helperRef, style: error ? styles4.error : styles4.hint, children: helperMessage }) : null,
1400
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: closeMenu, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: styles4.overlay, onPress: closeMenu, children: anchor ? /* @__PURE__ */ jsxRuntime.jsx(
1401
+ reactNative.View,
1085
1402
  {
1086
- visible: open,
1087
- transparent: true,
1088
- animationType: "fade",
1089
- onRequestClose: closeDropdown,
1090
- children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: styles4.overlay, onPress: closeDropdown, children: anchor ? /* @__PURE__ */ jsxRuntime.jsx(
1091
- reactNative.View,
1403
+ ref: menuRef,
1404
+ style: [
1405
+ selectDropdownMetrics.menu,
1406
+ styles4.dropdown,
1092
1407
  {
1093
- style: [
1094
- styles4.dropdown,
1095
- {
1096
- top: dropdownTop,
1097
- left: anchor.x,
1098
- width: anchor.width
1099
- }
1100
- ],
1101
- children: dropdownList
1408
+ top: dropdownTop,
1409
+ left: anchor.x,
1410
+ width: anchor.width,
1411
+ height: dropdownHeight
1102
1412
  }
1103
- ) : null })
1413
+ ],
1414
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1415
+ reactNative.ScrollView,
1416
+ {
1417
+ ref: scrollRef,
1418
+ style: styles4.dropdownScroll,
1419
+ contentContainerStyle: styles4.dropdownContent,
1420
+ keyboardShouldPersistTaps: "handled",
1421
+ showsVerticalScrollIndicator: true,
1422
+ bounces: false,
1423
+ nestedScrollEnabled: true,
1424
+ children: optionList
1425
+ }
1426
+ )
1104
1427
  }
1105
- )
1428
+ ) : null }) })
1106
1429
  ] });
1107
1430
  }
1108
1431
  var styles4 = reactNative.StyleSheet.create({
1109
- root: {
1110
- alignSelf: "flex-start",
1111
- flexShrink: 0
1112
- },
1113
- trigger: {
1114
- flexDirection: "row",
1115
- alignItems: "center",
1116
- alignSelf: "flex-start",
1117
- flexGrow: 0,
1118
- flexShrink: 0,
1119
- height: TRIGGER_HEIGHT,
1120
- borderRadius: radii.lg,
1121
- borderWidth: 1,
1122
- padding: spacing.lg,
1123
- gap: spacing.sm
1124
- },
1125
- triggerEnabled: {
1126
- borderColor: colors.stormGray50,
1127
- backgroundColor: colors.white
1128
- },
1129
- triggerDisabled: {
1130
- borderColor: colors.stormGray50,
1131
- backgroundColor: colors.stormGray50
1432
+ wrapper: {
1433
+ width: "100%",
1434
+ gap: SELECT_LABEL_GAP
1132
1435
  },
1133
- triggerWeb: {
1134
- width: "max-content"
1436
+ label: {
1437
+ ...selectLabelTypography
1135
1438
  },
1136
- flag: {
1137
- fontSize: 18,
1138
- lineHeight: 22
1439
+ iconSlot: {
1440
+ width: SELECT_ICON_SIZE,
1441
+ height: SELECT_ICON_SIZE,
1442
+ alignItems: "center",
1443
+ justifyContent: "center",
1444
+ flexShrink: 0
1139
1445
  },
1140
- dialCode: {
1141
- fontSize: fontSize.md,
1142
- fontWeight: fontWeight.medium
1446
+ valueContainer: {
1447
+ flex: 1,
1448
+ minWidth: 0,
1449
+ justifyContent: "center"
1143
1450
  },
1144
1451
  overlay: {
1145
1452
  flex: 1,
1146
- backgroundColor: "transparent"
1453
+ backgroundColor: colors.transparent
1147
1454
  },
1148
1455
  dropdown: {
1149
- position: "absolute",
1150
- height: DROPDOWN_HEIGHT,
1151
- borderRadius: radii.lg,
1152
- borderWidth: 1,
1153
- borderColor: colors.stormGray50,
1154
- backgroundColor: colors.white,
1155
- padding: DROPDOWN_PADDING,
1156
- overflow: "hidden"
1456
+ position: "absolute"
1157
1457
  },
1158
1458
  dropdownScroll: {
1159
1459
  flex: 1
@@ -1161,160 +1461,1760 @@ var styles4 = reactNative.StyleSheet.create({
1161
1461
  dropdownContent: {
1162
1462
  flexGrow: 1
1163
1463
  },
1164
- option: {
1165
- flexDirection: "row",
1166
- alignItems: "center",
1167
- height: OPTION_HEIGHT,
1168
- borderRadius: radii.sm,
1169
- padding: spacing.sm,
1170
- gap: spacing.sm
1171
- },
1172
1464
  optionSpacing: {
1173
- marginBottom: OPTION_GAP
1465
+ marginBottom: SELECT_OPTION_GAP
1174
1466
  },
1175
- optionSelected: {
1176
- backgroundColor: colors.countrySelectorSelectedBg
1467
+ optionDisabled: {
1468
+ opacity: 0.5
1177
1469
  },
1178
- optionDialCode: {
1179
- fontFamily: fonts.sans,
1180
- fontSize: fontSize.md,
1181
- fontWeight: fontWeight.regular,
1182
- lineHeight: fontSize.md,
1183
- letterSpacing: 0,
1184
- textAlign: "center",
1185
- color: colors.slateBlue
1470
+ optionLabelDisabled: {
1471
+ color: colors.stormGray300
1472
+ },
1473
+ error: {
1474
+ fontSize: 12,
1475
+ lineHeight: 12,
1476
+ color: colors.inputError
1477
+ },
1478
+ hint: {
1479
+ fontSize: 12,
1480
+ lineHeight: 12,
1481
+ color: colors.stormGray300
1186
1482
  }
1187
1483
  });
1188
- function PhoneInput({
1189
- label,
1190
- countryCode,
1191
- onCountryCodeChange,
1192
- error,
1193
- hint,
1194
- containerStyle,
1195
- style,
1196
- className,
1197
- labelClassName,
1198
- inputClassName,
1199
- errorClassName,
1200
- hintClassName,
1201
- editable = true,
1202
- onFocus,
1203
- onBlur,
1204
- ...props
1205
- }) {
1206
- const wrapperRef = react.useRef(null);
1207
- const inputRef = react.useRef(null);
1208
- const helperRef = react.useRef(null);
1209
- const [focused, setFocused] = react.useState(false);
1210
- useApplyWebClassName(wrapperRef, className);
1211
- useApplyWebClassName(inputRef, inputClassName);
1212
- useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
1213
- const isDisabled = editable === false;
1214
- const phoneVisualState = resolveInputVisualState({
1215
- focused,
1216
- error: Boolean(error),
1217
- disabled: isDisabled
1218
- });
1219
- const phoneFieldStyles = getInputFieldStyles(phoneVisualState);
1220
- function handleFocus(event) {
1221
- setFocused(true);
1222
- onFocus?.(event);
1223
- }
1224
- function handleBlur(event) {
1225
- setFocused(false);
1226
- onBlur?.(event);
1227
- }
1228
- const helperMessage = error ?? hint;
1229
- return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles5.wrapper, containerStyle], children: [
1230
- label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
1231
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.row, children: [
1232
- /* @__PURE__ */ jsxRuntime.jsx(
1233
- CountryCodeSelector,
1234
- {
1235
- value: countryCode,
1236
- onValueChange: onCountryCodeChange,
1237
- disabled: isDisabled,
1238
- style: styles5.countrySelector
1239
- }
1484
+
1485
+ // src/data/countries.ts
1486
+ var defaultCountry = {
1487
+ code: "AM",
1488
+ name: "Armenia",
1489
+ dialCode: "+374"
1490
+ };
1491
+ var countries = [
1492
+ defaultCountry,
1493
+ { code: "AF", name: "Afghanistan", dialCode: "+93" },
1494
+ { code: "AL", name: "Albania", dialCode: "+355" },
1495
+ { code: "DZ", name: "Algeria", dialCode: "+213" },
1496
+ { code: "AR", name: "Argentina", dialCode: "+54" },
1497
+ { code: "AU", name: "Australia", dialCode: "+61" },
1498
+ { code: "AT", name: "Austria", dialCode: "+43" },
1499
+ { code: "AZ", name: "Azerbaijan", dialCode: "+994" },
1500
+ { code: "BH", name: "Bahrain", dialCode: "+973" },
1501
+ { code: "BY", name: "Belarus", dialCode: "+375" },
1502
+ { code: "BE", name: "Belgium", dialCode: "+32" },
1503
+ { code: "BR", name: "Brazil", dialCode: "+55" },
1504
+ { code: "BG", name: "Bulgaria", dialCode: "+359" },
1505
+ { code: "CA", name: "Canada", dialCode: "+1" },
1506
+ { code: "CL", name: "Chile", dialCode: "+56" },
1507
+ { code: "CN", name: "China", dialCode: "+86" },
1508
+ { code: "CO", name: "Colombia", dialCode: "+57" },
1509
+ { code: "HR", name: "Croatia", dialCode: "+385" },
1510
+ { code: "CY", name: "Cyprus", dialCode: "+357" },
1511
+ { code: "CZ", name: "Czech Republic", dialCode: "+420" },
1512
+ { code: "DK", name: "Denmark", dialCode: "+45" },
1513
+ { code: "EG", name: "Egypt", dialCode: "+20" },
1514
+ { code: "EE", name: "Estonia", dialCode: "+372" },
1515
+ { code: "FI", name: "Finland", dialCode: "+358" },
1516
+ { code: "FR", name: "France", dialCode: "+33" },
1517
+ { code: "GE", name: "Georgia", dialCode: "+995" },
1518
+ { code: "DE", name: "Germany", dialCode: "+49" },
1519
+ { code: "GR", name: "Greece", dialCode: "+30" },
1520
+ { code: "HK", name: "Hong Kong", dialCode: "+852" },
1521
+ { code: "HU", name: "Hungary", dialCode: "+36" },
1522
+ { code: "IN", name: "India", dialCode: "+91" },
1523
+ { code: "ID", name: "Indonesia", dialCode: "+62" },
1524
+ { code: "IR", name: "Iran", dialCode: "+98" },
1525
+ { code: "IQ", name: "Iraq", dialCode: "+964" },
1526
+ { code: "IE", name: "Ireland", dialCode: "+353" },
1527
+ { code: "IL", name: "Israel", dialCode: "+972" },
1528
+ { code: "IT", name: "Italy", dialCode: "+39" },
1529
+ { code: "JP", name: "Japan", dialCode: "+81" },
1530
+ { code: "JO", name: "Jordan", dialCode: "+962" },
1531
+ { code: "KZ", name: "Kazakhstan", dialCode: "+7" },
1532
+ { code: "KW", name: "Kuwait", dialCode: "+965" },
1533
+ { code: "LV", name: "Latvia", dialCode: "+371" },
1534
+ { code: "LB", name: "Lebanon", dialCode: "+961" },
1535
+ { code: "LT", name: "Lithuania", dialCode: "+370" },
1536
+ { code: "LU", name: "Luxembourg", dialCode: "+352" },
1537
+ { code: "MY", name: "Malaysia", dialCode: "+60" },
1538
+ { code: "MX", name: "Mexico", dialCode: "+52" },
1539
+ { code: "MD", name: "Moldova", dialCode: "+373" },
1540
+ { code: "NL", name: "Netherlands", dialCode: "+31" },
1541
+ { code: "NZ", name: "New Zealand", dialCode: "+64" },
1542
+ { code: "NG", name: "Nigeria", dialCode: "+234" },
1543
+ { code: "NO", name: "Norway", dialCode: "+47" },
1544
+ { code: "PK", name: "Pakistan", dialCode: "+92" },
1545
+ { code: "PS", name: "Palestine", dialCode: "+970" },
1546
+ { code: "PH", name: "Philippines", dialCode: "+63" },
1547
+ { code: "PL", name: "Poland", dialCode: "+48" },
1548
+ { code: "PT", name: "Portugal", dialCode: "+351" },
1549
+ { code: "QA", name: "Qatar", dialCode: "+974" },
1550
+ { code: "RO", name: "Romania", dialCode: "+40" },
1551
+ { code: "RU", name: "Russia", dialCode: "+7" },
1552
+ { code: "SA", name: "Saudi Arabia", dialCode: "+966" },
1553
+ { code: "RS", name: "Serbia", dialCode: "+381" },
1554
+ { code: "SG", name: "Singapore", dialCode: "+65" },
1555
+ { code: "SK", name: "Slovakia", dialCode: "+421" },
1556
+ { code: "SI", name: "Slovenia", dialCode: "+386" },
1557
+ { code: "ZA", name: "South Africa", dialCode: "+27" },
1558
+ { code: "KR", name: "South Korea", dialCode: "+82" },
1559
+ { code: "ES", name: "Spain", dialCode: "+34" },
1560
+ { code: "SE", name: "Sweden", dialCode: "+46" },
1561
+ { code: "CH", name: "Switzerland", dialCode: "+41" },
1562
+ { code: "SY", name: "Syria", dialCode: "+963" },
1563
+ { code: "TW", name: "Taiwan", dialCode: "+886" },
1564
+ { code: "TH", name: "Thailand", dialCode: "+66" },
1565
+ { code: "TR", name: "Turkey", dialCode: "+90" },
1566
+ { code: "UA", name: "Ukraine", dialCode: "+380" },
1567
+ { code: "AE", name: "United Arab Emirates", dialCode: "+971" },
1568
+ { code: "GB", name: "United Kingdom", dialCode: "+44" },
1569
+ { code: "US", name: "United States", dialCode: "+1" },
1570
+ { code: "UZ", name: "Uzbekistan", dialCode: "+998" },
1571
+ { code: "VN", name: "Vietnam", dialCode: "+84" }
1572
+ ];
1573
+ function findCountry(code) {
1574
+ return countries.find((country) => country.code === code) ?? defaultCountry;
1575
+ }
1576
+
1577
+ // src/utils/countryFlag.ts
1578
+ function countryCodeToFlagEmoji(code) {
1579
+ const upper = code.trim().toUpperCase();
1580
+ if (upper.length !== 2) return "";
1581
+ return String.fromCodePoint(
1582
+ ...upper.split("").map((char) => 127462 - 65 + char.charCodeAt(0))
1583
+ );
1584
+ }
1585
+ var DROPDOWN_GAP = 10;
1586
+ var DROPDOWN_HEIGHT = 186;
1587
+ var DROPDOWN_PADDING = 8;
1588
+ var OPTION_GAP = 10;
1589
+ var OPTION_HEIGHT = 35;
1590
+ var TRIGGER_HEIGHT = 52;
1591
+ var CHEVRON_SIZE = 16;
1592
+ function resolveDropdownTop(anchor) {
1593
+ const windowHeight = reactNative.Dimensions.get("window").height;
1594
+ const topBelow = anchor.y + anchor.height + DROPDOWN_GAP;
1595
+ const topAbove = anchor.y - DROPDOWN_GAP - DROPDOWN_HEIGHT;
1596
+ const fitsBelow = topBelow + DROPDOWN_HEIGHT <= windowHeight;
1597
+ if (fitsBelow) return topBelow;
1598
+ if (topAbove >= 0) return topAbove;
1599
+ return Math.max(0, Math.min(topBelow, windowHeight - DROPDOWN_HEIGHT));
1600
+ }
1601
+ function CountryCodeSelector({
1602
+ value = defaultCountry.code,
1603
+ onValueChange,
1604
+ options = countries,
1605
+ disabled = false,
1606
+ style,
1607
+ className
1608
+ }) {
1609
+ const wrapperRef = react.useRef(null);
1610
+ const triggerRef = react.useRef(null);
1611
+ const scrollRef = react.useRef(null);
1612
+ const [open, setOpen] = react.useState(false);
1613
+ const [anchor, setAnchor] = react.useState(null);
1614
+ useApplyWebClassName(wrapperRef, className);
1615
+ useApplyWebClassName(
1616
+ scrollRef,
1617
+ COUNTRY_DROPDOWN_SCROLL_CLASS,
1618
+ open && Boolean(anchor)
1619
+ );
1620
+ react.useLayoutEffect(() => {
1621
+ ensureCountryDropdownScrollStyles();
1622
+ }, []);
1623
+ const selected = findCountry(value);
1624
+ const textColor = disabled ? colors.stormGray200 : colors.slateBlue;
1625
+ function closeDropdown() {
1626
+ setOpen(false);
1627
+ setAnchor(null);
1628
+ }
1629
+ function handleOpen() {
1630
+ if (disabled) return;
1631
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
1632
+ setAnchor({ x, y, width, height });
1633
+ setOpen(true);
1634
+ });
1635
+ }
1636
+ function handleSelect(code) {
1637
+ onValueChange?.(code);
1638
+ closeDropdown();
1639
+ }
1640
+ const dropdownTop = anchor ? resolveDropdownTop(anchor) : 0;
1641
+ const optionList = options.map((item, index) => {
1642
+ const isSelected = item.code === selected.code;
1643
+ const isLast = index === options.length - 1;
1644
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1645
+ reactNative.Pressable,
1646
+ {
1647
+ accessibilityRole: "button",
1648
+ onPress: () => handleSelect(item.code),
1649
+ style: [
1650
+ styles5.option,
1651
+ isSelected && styles5.optionSelected,
1652
+ !isLast && styles5.optionSpacing
1653
+ ],
1654
+ children: [
1655
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles5.flag, children: countryCodeToFlagEmoji(item.code) }),
1656
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles5.optionDialCode, children: item.dialCode })
1657
+ ]
1658
+ },
1659
+ item.code
1660
+ );
1661
+ });
1662
+ const dropdownList = /* @__PURE__ */ jsxRuntime.jsx(
1663
+ reactNative.ScrollView,
1664
+ {
1665
+ ref: scrollRef,
1666
+ style: styles5.dropdownScroll,
1667
+ contentContainerStyle: styles5.dropdownContent,
1668
+ keyboardShouldPersistTaps: "handled",
1669
+ showsVerticalScrollIndicator: true,
1670
+ bounces: false,
1671
+ nestedScrollEnabled: true,
1672
+ children: optionList
1673
+ }
1674
+ );
1675
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles5.root, style], children: [
1676
+ /* @__PURE__ */ jsxRuntime.jsxs(
1677
+ reactNative.Pressable,
1678
+ {
1679
+ ref: triggerRef,
1680
+ accessibilityRole: "button",
1681
+ disabled,
1682
+ onPress: handleOpen,
1683
+ style: [
1684
+ styles5.trigger,
1685
+ disabled ? styles5.triggerDisabled : styles5.triggerEnabled,
1686
+ reactNative.Platform.OS === "web" ? styles5.triggerWeb : null
1687
+ ],
1688
+ children: [
1689
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: styles5.flag, children: countryCodeToFlagEmoji(selected.code) }),
1690
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: [styles5.dialCode, { color: textColor }], children: selected.dialCode }),
1691
+ /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { size: CHEVRON_SIZE, color: colors.stormGray100 })
1692
+ ]
1693
+ }
1694
+ ),
1695
+ /* @__PURE__ */ jsxRuntime.jsx(
1696
+ reactNative.Modal,
1697
+ {
1698
+ visible: open,
1699
+ transparent: true,
1700
+ animationType: "fade",
1701
+ onRequestClose: closeDropdown,
1702
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Pressable, { style: styles5.overlay, onPress: closeDropdown, children: anchor ? /* @__PURE__ */ jsxRuntime.jsx(
1703
+ reactNative.View,
1704
+ {
1705
+ style: [
1706
+ styles5.dropdown,
1707
+ {
1708
+ top: dropdownTop,
1709
+ left: anchor.x,
1710
+ width: anchor.width
1711
+ }
1712
+ ],
1713
+ children: dropdownList
1714
+ }
1715
+ ) : null })
1716
+ }
1717
+ )
1718
+ ] });
1719
+ }
1720
+ var styles5 = reactNative.StyleSheet.create({
1721
+ root: {
1722
+ alignSelf: "flex-start",
1723
+ flexShrink: 0
1724
+ },
1725
+ trigger: {
1726
+ flexDirection: "row",
1727
+ alignItems: "center",
1728
+ alignSelf: "flex-start",
1729
+ flexGrow: 0,
1730
+ flexShrink: 0,
1731
+ height: TRIGGER_HEIGHT,
1732
+ borderRadius: radii.lg,
1733
+ borderWidth: 1,
1734
+ padding: spacing.lg,
1735
+ gap: spacing.sm
1736
+ },
1737
+ triggerEnabled: {
1738
+ borderColor: colors.stormGray50,
1739
+ backgroundColor: colors.white
1740
+ },
1741
+ triggerDisabled: {
1742
+ borderColor: colors.stormGray50,
1743
+ backgroundColor: colors.stormGray50
1744
+ },
1745
+ triggerWeb: {
1746
+ width: "max-content"
1747
+ },
1748
+ flag: {
1749
+ fontSize: 18,
1750
+ lineHeight: 22
1751
+ },
1752
+ dialCode: {
1753
+ fontSize: fontSize.md,
1754
+ fontWeight: fontWeight.medium
1755
+ },
1756
+ overlay: {
1757
+ flex: 1,
1758
+ backgroundColor: "transparent"
1759
+ },
1760
+ dropdown: {
1761
+ position: "absolute",
1762
+ height: DROPDOWN_HEIGHT,
1763
+ borderRadius: radii.lg,
1764
+ borderWidth: 1,
1765
+ borderColor: colors.stormGray50,
1766
+ backgroundColor: colors.white,
1767
+ padding: DROPDOWN_PADDING,
1768
+ overflow: "hidden"
1769
+ },
1770
+ dropdownScroll: {
1771
+ flex: 1
1772
+ },
1773
+ dropdownContent: {
1774
+ flexGrow: 1
1775
+ },
1776
+ option: {
1777
+ flexDirection: "row",
1778
+ alignItems: "center",
1779
+ height: OPTION_HEIGHT,
1780
+ borderRadius: radii.sm,
1781
+ padding: spacing.sm,
1782
+ gap: spacing.sm
1783
+ },
1784
+ optionSpacing: {
1785
+ marginBottom: OPTION_GAP
1786
+ },
1787
+ optionSelected: {
1788
+ backgroundColor: colors.countrySelectorSelectedBg
1789
+ },
1790
+ optionDialCode: {
1791
+ fontFamily: fonts.sans,
1792
+ fontSize: fontSize.md,
1793
+ fontWeight: fontWeight.regular,
1794
+ lineHeight: fontSize.md,
1795
+ letterSpacing: 0,
1796
+ textAlign: "center",
1797
+ color: colors.slateBlue
1798
+ }
1799
+ });
1800
+ function PhoneInput({
1801
+ label,
1802
+ countryCode,
1803
+ onCountryCodeChange,
1804
+ error,
1805
+ hint,
1806
+ containerStyle,
1807
+ style,
1808
+ className,
1809
+ labelClassName,
1810
+ inputClassName,
1811
+ errorClassName,
1812
+ hintClassName,
1813
+ editable = true,
1814
+ onFocus,
1815
+ onBlur,
1816
+ ...props
1817
+ }) {
1818
+ const wrapperRef = react.useRef(null);
1819
+ const inputRef = react.useRef(null);
1820
+ const helperRef = react.useRef(null);
1821
+ const [focused, setFocused] = react.useState(false);
1822
+ useApplyWebClassName(wrapperRef, className);
1823
+ useApplyWebClassName(inputRef, inputClassName);
1824
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
1825
+ const isDisabled = editable === false;
1826
+ const phoneVisualState = resolveInputVisualState({
1827
+ focused,
1828
+ error: Boolean(error),
1829
+ disabled: isDisabled
1830
+ });
1831
+ const phoneFieldStyles = getInputFieldStyles(phoneVisualState);
1832
+ function handleFocus(event) {
1833
+ setFocused(true);
1834
+ onFocus?.(event);
1835
+ }
1836
+ function handleBlur(event) {
1837
+ setFocused(false);
1838
+ onBlur?.(event);
1839
+ }
1840
+ const helperMessage = error ?? hint;
1841
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles6.wrapper, containerStyle], children: [
1842
+ label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
1843
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.row, children: [
1844
+ /* @__PURE__ */ jsxRuntime.jsx(
1845
+ CountryCodeSelector,
1846
+ {
1847
+ value: countryCode,
1848
+ onValueChange: onCountryCodeChange,
1849
+ disabled: isDisabled,
1850
+ style: styles6.countrySelector
1851
+ }
1852
+ ),
1853
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles6.phoneColumn, children: [
1854
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [phoneFieldStyles.outline, styles6.phoneOutline], children: /* @__PURE__ */ jsxRuntime.jsx(
1855
+ reactNative.View,
1856
+ {
1857
+ style: [
1858
+ inputFieldMetrics.container,
1859
+ phoneFieldStyles.container,
1860
+ styles6.phoneField
1861
+ ],
1862
+ children: /* @__PURE__ */ jsxRuntime.jsx(
1863
+ reactNative.TextInput,
1864
+ {
1865
+ ref: inputRef,
1866
+ style: [
1867
+ inputFieldMetrics.input,
1868
+ phoneFieldStyles.text,
1869
+ style
1870
+ ],
1871
+ keyboardType: "phone-pad",
1872
+ placeholderTextColor: phoneFieldStyles.placeholder,
1873
+ editable,
1874
+ onFocus: handleFocus,
1875
+ onBlur: handleBlur,
1876
+ accessibilityState: { disabled: isDisabled },
1877
+ ...props
1878
+ }
1879
+ )
1880
+ }
1881
+ ) }),
1882
+ helperMessage ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: helperRef, style: error ? styles6.error : styles6.hint, children: helperMessage }) : null
1883
+ ] })
1884
+ ] })
1885
+ ] });
1886
+ }
1887
+ var styles6 = reactNative.StyleSheet.create({
1888
+ wrapper: {
1889
+ width: "100%",
1890
+ gap: spacing.sm
1891
+ },
1892
+ row: {
1893
+ flexDirection: "row",
1894
+ alignItems: "flex-start",
1895
+ gap: INPUT_ICON_GAP
1896
+ },
1897
+ countrySelector: {
1898
+ flexShrink: 0,
1899
+ alignSelf: "flex-start"
1900
+ },
1901
+ phoneColumn: {
1902
+ flex: 1,
1903
+ gap: spacing.sm
1904
+ },
1905
+ phoneOutline: {
1906
+ width: "100%"
1907
+ },
1908
+ phoneField: {
1909
+ flex: 1
1910
+ },
1911
+ error: {
1912
+ fontSize: 12,
1913
+ lineHeight: 16,
1914
+ color: colors.inputError
1915
+ },
1916
+ hint: {
1917
+ fontSize: 12,
1918
+ lineHeight: 16,
1919
+ color: colors.stormGray300
1920
+ }
1921
+ });
1922
+
1923
+ // src/icons/chevronNavPaths.ts
1924
+ var CHEVRON_LEFT_PATH = "M12.5 15L7.5 10L12.5 5";
1925
+ var CHEVRON_RIGHT_PATH = "M7.5 15L12.5 10L7.5 5";
1926
+ function ChevronLeftIcon({
1927
+ size = 20,
1928
+ color = "#151a1e",
1929
+ strokeWidth = 2
1930
+ }) {
1931
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg5__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
1932
+ Svg5.Path,
1933
+ {
1934
+ d: CHEVRON_LEFT_PATH,
1935
+ stroke: color,
1936
+ strokeWidth,
1937
+ strokeLinecap: "round",
1938
+ strokeLinejoin: "round"
1939
+ }
1940
+ ) });
1941
+ }
1942
+ function ChevronRightIcon({
1943
+ size = 20,
1944
+ color = "#151a1e",
1945
+ strokeWidth = 2
1946
+ }) {
1947
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg5__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
1948
+ Svg5.Path,
1949
+ {
1950
+ d: CHEVRON_RIGHT_PATH,
1951
+ stroke: color,
1952
+ strokeWidth,
1953
+ strokeLinecap: "round",
1954
+ strokeLinejoin: "round"
1955
+ }
1956
+ ) });
1957
+ }
1958
+ var CALENDAR_DROPDOWN_GAP = spacing.sm;
1959
+ var CALENDAR_PANEL_WIDTH = 296;
1960
+ var CALENDAR_PANEL_PADDING = spacing.md;
1961
+ var CALENDAR_PANEL_GAP = spacing.md;
1962
+ var CALENDAR_CONTENT_WIDTH = CALENDAR_PANEL_WIDTH - CALENDAR_PANEL_PADDING * 2;
1963
+ var CALENDAR_HEADER_HEIGHT = 20;
1964
+ var CALENDAR_WEEKDAY_CELL_SIZE = 32;
1965
+ var CALENDAR_WEEKDAY_GAP = spacing.sm;
1966
+ var CALENDAR_WEEKDAY_RADIUS = 6;
1967
+ var CALENDAR_DAY_SIZE = CALENDAR_WEEKDAY_CELL_SIZE;
1968
+ var CALENDAR_DAY_GRID_WIDTH = CALENDAR_CONTENT_WIDTH;
1969
+ var CALENDAR_DAY_GAP_X = spacing.sm;
1970
+ var CALENDAR_DAY_GAP_Y = spacing.lg;
1971
+ var CALENDAR_DAY_ROWS = 6;
1972
+ var CALENDAR_DAY_GRID_HEIGHT = CALENDAR_DAY_SIZE * CALENDAR_DAY_ROWS + CALENDAR_DAY_GAP_Y * (CALENDAR_DAY_ROWS - 1);
1973
+ var CALENDAR_PICKER_COLUMNS = 3;
1974
+ var CALENDAR_YEARS_PER_PAGE = 12;
1975
+ var CALENDAR_PICKER_CELL_WIDTH = (CALENDAR_DAY_GRID_WIDTH - CALENDAR_DAY_GAP_X * (CALENDAR_PICKER_COLUMNS - 1)) / CALENDAR_PICKER_COLUMNS;
1976
+ var CALENDAR_PICKER_CELL_HEIGHT = 36;
1977
+ var CALENDAR_PICKER_BODY_HEIGHT = CALENDAR_WEEKDAY_CELL_SIZE + CALENDAR_WEEKDAY_GAP + CALENDAR_DAY_GRID_HEIGHT;
1978
+ var CALENDAR_DAY_DOT_SIZE = 3;
1979
+ var CALENDAR_TODAY_TEXT_COLOR = "#082640";
1980
+ var CALENDAR_TODAY_DOT_COLOR = "#0033A0";
1981
+ var CALENDAR_NAV_ICON_SIZE = 20;
1982
+ var CALENDAR_NAV_ICON_COLOR = colors.stormGray850;
1983
+ var CALENDAR_FIELD_ICON_SIZE = 20;
1984
+ var CALENDAR_FIELD_WIDTH = CALENDAR_PANEL_WIDTH;
1985
+ var CALENDAR_FIELD_HEIGHT = 52;
1986
+ var CALENDAR_FIELD_PADDING = spacing.lg;
1987
+ var CALENDAR_FIELD_GAP = spacing.sm;
1988
+ var CALENDAR_FIELD_PLACEHOLDER_COLOR = colors.stormGray200;
1989
+ var CALENDAR_PANEL_TOTAL_HEIGHT = CALENDAR_PANEL_PADDING * 2 + CALENDAR_HEADER_HEIGHT + CALENDAR_PANEL_GAP * 2 + CALENDAR_WEEKDAY_CELL_SIZE + CALENDAR_DAY_GRID_HEIGHT;
1990
+ var CALENDAR_PANEL_HEIGHT = CALENDAR_PANEL_TOTAL_HEIGHT;
1991
+ var calendarLabelTypography = {
1992
+ fontFamily: fonts.sans,
1993
+ fontSize: fontSize.sm,
1994
+ fontWeight: fontWeight.medium,
1995
+ lineHeight: fontSize.sm,
1996
+ letterSpacing: 0,
1997
+ color: colors.slateBlue
1998
+ };
1999
+ var calendarFieldTypography = {
2000
+ fontFamily: fonts.sans,
2001
+ fontSize: fontSize.md,
2002
+ fontWeight: fontWeight.regular,
2003
+ lineHeight: fontSize.md,
2004
+ letterSpacing: 0,
2005
+ textAlign: "left"
2006
+ };
2007
+ var calendarFieldPlaceholderTypography = {
2008
+ ...calendarFieldTypography,
2009
+ color: CALENDAR_FIELD_PLACEHOLDER_COLOR
2010
+ };
2011
+ var calendarDropdownMetrics = reactNative.StyleSheet.create({
2012
+ panel: {
2013
+ width: CALENDAR_PANEL_WIDTH,
2014
+ height: CALENDAR_PANEL_HEIGHT,
2015
+ borderRadius: radii.lg,
2016
+ borderWidth: 1,
2017
+ borderColor: colors.stormGray50,
2018
+ backgroundColor: colors.white,
2019
+ padding: CALENDAR_PANEL_PADDING,
2020
+ gap: CALENDAR_PANEL_GAP,
2021
+ overflow: "hidden",
2022
+ flexDirection: "column",
2023
+ opacity: 1,
2024
+ ...reactNative.Platform.OS === "web" ? {
2025
+ boxSizing: "border-box"
2026
+ } : null
2027
+ },
2028
+ header: {
2029
+ flexDirection: "row",
2030
+ alignItems: "center",
2031
+ justifyContent: "space-between",
2032
+ height: CALENDAR_HEADER_HEIGHT,
2033
+ minHeight: CALENDAR_HEADER_HEIGHT,
2034
+ maxHeight: CALENDAR_HEADER_HEIGHT
2035
+ },
2036
+ headerTitle: {
2037
+ textAlign: "center",
2038
+ fontFamily: fonts.sans,
2039
+ fontSize: fontSize.md,
2040
+ fontWeight: fontWeight.bold,
2041
+ lineHeight: 18,
2042
+ letterSpacing: 0,
2043
+ color: colors.stormGray850
2044
+ },
2045
+ headerTitlePressable: {
2046
+ flex: 1,
2047
+ alignItems: "center",
2048
+ justifyContent: "center",
2049
+ minHeight: CALENDAR_HEADER_HEIGHT
2050
+ },
2051
+ navButton: {
2052
+ width: CALENDAR_NAV_ICON_SIZE,
2053
+ height: CALENDAR_NAV_ICON_SIZE,
2054
+ alignItems: "center",
2055
+ justifyContent: "center"
2056
+ },
2057
+ weekdayRow: {
2058
+ flexDirection: "row",
2059
+ gap: CALENDAR_WEEKDAY_GAP,
2060
+ height: CALENDAR_WEEKDAY_CELL_SIZE,
2061
+ minHeight: CALENDAR_WEEKDAY_CELL_SIZE,
2062
+ maxHeight: CALENDAR_WEEKDAY_CELL_SIZE,
2063
+ opacity: 1
2064
+ },
2065
+ weekdayCell: {
2066
+ width: CALENDAR_WEEKDAY_CELL_SIZE,
2067
+ height: CALENDAR_WEEKDAY_CELL_SIZE,
2068
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
2069
+ padding: spacing.xs,
2070
+ backgroundColor: colors.stormGray0,
2071
+ alignItems: "center",
2072
+ justifyContent: "center",
2073
+ opacity: 1,
2074
+ ...reactNative.Platform.OS === "web" ? {
2075
+ boxSizing: "border-box"
2076
+ } : null
2077
+ },
2078
+ weekdayLabel: {
2079
+ fontFamily: fonts.sans,
2080
+ fontSize: fontSize.sm,
2081
+ fontWeight: fontWeight.regular,
2082
+ lineHeight: fontSize.sm,
2083
+ letterSpacing: 0,
2084
+ textAlign: "center",
2085
+ color: colors.stormGray300,
2086
+ textTransform: "uppercase"
2087
+ },
2088
+ dayGrid: {
2089
+ width: CALENDAR_DAY_GRID_WIDTH,
2090
+ height: CALENDAR_DAY_GRID_HEIGHT,
2091
+ flexDirection: "row",
2092
+ flexWrap: "wrap",
2093
+ columnGap: CALENDAR_DAY_GAP_X,
2094
+ rowGap: CALENDAR_DAY_GAP_Y,
2095
+ alignContent: "flex-start",
2096
+ opacity: 1
2097
+ },
2098
+ dayCell: {
2099
+ width: CALENDAR_DAY_SIZE,
2100
+ height: CALENDAR_DAY_SIZE,
2101
+ minHeight: CALENDAR_DAY_SIZE,
2102
+ maxHeight: CALENDAR_DAY_SIZE,
2103
+ alignItems: "center",
2104
+ justifyContent: "center",
2105
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
2106
+ padding: spacing.xs,
2107
+ backgroundColor: colors.white,
2108
+ opacity: 1,
2109
+ position: "relative",
2110
+ ...reactNative.Platform.OS === "web" ? {
2111
+ boxSizing: "border-box"
2112
+ } : null
2113
+ },
2114
+ dayCellPast: {
2115
+ backgroundColor: colors.stormGray50
2116
+ },
2117
+ dayCellSelected: {
2118
+ backgroundColor: colors.navy
2119
+ },
2120
+ dayLabel: {
2121
+ fontFamily: fonts.sans,
2122
+ fontSize: fontSize.md,
2123
+ fontWeight: fontWeight.regular,
2124
+ lineHeight: 18,
2125
+ letterSpacing: 0,
2126
+ textAlign: "center",
2127
+ color: colors.navy,
2128
+ includeFontPadding: false,
2129
+ textAlignVertical: "center"
2130
+ },
2131
+ dayLabelToday: {
2132
+ color: CALENDAR_TODAY_TEXT_COLOR
2133
+ },
2134
+ dayLabelSelected: {
2135
+ fontWeight: fontWeight.semibold,
2136
+ color: colors.white
2137
+ },
2138
+ dayLabelFuture: {
2139
+ color: colors.navy
2140
+ },
2141
+ dayLabelMuted: {
2142
+ color: colors.stormGray300
2143
+ },
2144
+ dayLabelOutsideMonth: {
2145
+ color: colors.stormGray300
2146
+ },
2147
+ dayLabelDisabled: {
2148
+ color: colors.stormGray300,
2149
+ opacity: 0.5
2150
+ },
2151
+ todayDot: {
2152
+ position: "absolute",
2153
+ bottom: 5,
2154
+ left: "50%",
2155
+ width: CALENDAR_DAY_DOT_SIZE,
2156
+ height: CALENDAR_DAY_DOT_SIZE,
2157
+ borderRadius: 15,
2158
+ backgroundColor: CALENDAR_TODAY_DOT_COLOR,
2159
+ marginLeft: -1.5,
2160
+ zIndex: 1
2161
+ },
2162
+ pickerBody: {
2163
+ width: CALENDAR_DAY_GRID_WIDTH,
2164
+ height: CALENDAR_PICKER_BODY_HEIGHT,
2165
+ justifyContent: "center"
2166
+ },
2167
+ pickerGrid: {
2168
+ width: CALENDAR_DAY_GRID_WIDTH,
2169
+ flexDirection: "row",
2170
+ flexWrap: "wrap",
2171
+ columnGap: CALENDAR_DAY_GAP_X,
2172
+ rowGap: CALENDAR_DAY_GAP_Y,
2173
+ alignContent: "flex-start"
2174
+ },
2175
+ pickerCell: {
2176
+ width: CALENDAR_PICKER_CELL_WIDTH,
2177
+ minHeight: CALENDAR_PICKER_CELL_HEIGHT,
2178
+ alignItems: "center",
2179
+ justifyContent: "center",
2180
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
2181
+ paddingHorizontal: spacing.xs,
2182
+ paddingVertical: spacing.xs,
2183
+ backgroundColor: colors.white,
2184
+ ...reactNative.Platform.OS === "web" ? {
2185
+ boxSizing: "border-box"
2186
+ } : null
2187
+ },
2188
+ pickerCellSelected: {
2189
+ backgroundColor: colors.navy
2190
+ },
2191
+ pickerLabel: {
2192
+ fontFamily: fonts.sans,
2193
+ fontSize: fontSize.md,
2194
+ fontWeight: fontWeight.regular,
2195
+ lineHeight: 18,
2196
+ letterSpacing: 0,
2197
+ textAlign: "center",
2198
+ color: colors.navy,
2199
+ includeFontPadding: false,
2200
+ ...reactNative.Platform.OS === "android" ? { textAlignVertical: "center" } : null
2201
+ },
2202
+ pickerLabelSelected: {
2203
+ fontWeight: fontWeight.semibold,
2204
+ color: colors.white
2205
+ },
2206
+ pickerLabelDisabled: {
2207
+ color: colors.stormGray300,
2208
+ opacity: 0.5
2209
+ },
2210
+ pickerLabelCurrent: {
2211
+ color: CALENDAR_TODAY_TEXT_COLOR
2212
+ }
2213
+ });
2214
+ function resolveCalendarDropdownTop(anchor, panelHeight = CALENDAR_PANEL_HEIGHT) {
2215
+ const windowHeight = reactNative.Dimensions.get("window").height;
2216
+ const spaceBelow = windowHeight - (anchor.y + anchor.height + CALENDAR_DROPDOWN_GAP);
2217
+ const spaceAbove = anchor.y - CALENDAR_DROPDOWN_GAP;
2218
+ const topBelow = anchor.y + anchor.height + CALENDAR_DROPDOWN_GAP;
2219
+ const topAbove = anchor.y - CALENDAR_DROPDOWN_GAP - panelHeight;
2220
+ if (spaceBelow >= panelHeight) {
2221
+ return topBelow;
2222
+ }
2223
+ if (spaceAbove >= panelHeight) {
2224
+ return topAbove;
2225
+ }
2226
+ if (spaceAbove > spaceBelow) {
2227
+ return Math.max(0, topAbove);
2228
+ }
2229
+ return Math.max(0, Math.min(topBelow, windowHeight - panelHeight));
2230
+ }
2231
+ function resolveCalendarDropdownLeft(anchor, panelWidth = CALENDAR_PANEL_WIDTH) {
2232
+ const windowWidth = reactNative.Dimensions.get("window").width;
2233
+ const maxLeft = Math.max(0, windowWidth - panelWidth);
2234
+ return Math.max(0, Math.min(anchor.x, maxLeft));
2235
+ }
2236
+ var calendarFieldMetrics = reactNative.StyleSheet.create({
2237
+ container: {
2238
+ flexDirection: "row",
2239
+ alignItems: "center",
2240
+ width: CALENDAR_FIELD_WIDTH,
2241
+ minWidth: CALENDAR_FIELD_WIDTH,
2242
+ maxWidth: CALENDAR_FIELD_WIDTH,
2243
+ height: CALENDAR_FIELD_HEIGHT,
2244
+ minHeight: CALENDAR_FIELD_HEIGHT,
2245
+ maxHeight: CALENDAR_FIELD_HEIGHT,
2246
+ borderRadius: radii.lg,
2247
+ padding: CALENDAR_FIELD_PADDING,
2248
+ gap: CALENDAR_FIELD_GAP,
2249
+ opacity: 1,
2250
+ ...reactNative.Platform.OS === "web" ? {
2251
+ boxSizing: "border-box"
2252
+ } : null
2253
+ },
2254
+ value: {
2255
+ flex: 1,
2256
+ minWidth: 0,
2257
+ ...calendarFieldTypography,
2258
+ paddingVertical: 0,
2259
+ paddingHorizontal: 0,
2260
+ margin: 0,
2261
+ ...reactNative.Platform.OS === "android" ? { includeFontPadding: false } : null,
2262
+ ...reactNative.Platform.OS === "web" ? {
2263
+ outlineStyle: "none"
2264
+ } : null
2265
+ }
2266
+ });
2267
+
2268
+ // src/utils/calendarDays.ts
2269
+ function stripTime(date) {
2270
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
2271
+ }
2272
+ function normalizeDateRange(range) {
2273
+ if (!range?.start) {
2274
+ return {};
2275
+ }
2276
+ const start = stripTime(range.start);
2277
+ if (!range.end) {
2278
+ return { start };
2279
+ }
2280
+ const end = stripTime(range.end);
2281
+ if (isBeforeDay(end, start)) {
2282
+ return { start: end, end: start };
2283
+ }
2284
+ return { start, end };
2285
+ }
2286
+ function isInDateRange(date, start, end) {
2287
+ if (!start) {
2288
+ return false;
2289
+ }
2290
+ const day = stripTime(date);
2291
+ if (!end) {
2292
+ return isSameDay(day, start);
2293
+ }
2294
+ return !isBeforeDay(day, start) && !isAfterDay(day, end);
2295
+ }
2296
+ function selectRangeDate(clicked, current) {
2297
+ const clickedDate = stripTime(clicked);
2298
+ if (!current?.start || current.end) {
2299
+ return { start: clickedDate };
2300
+ }
2301
+ const start = stripTime(current.start);
2302
+ if (isSameDay(clickedDate, start)) {
2303
+ return { start, end: clickedDate };
2304
+ }
2305
+ if (isBeforeDay(clickedDate, start)) {
2306
+ return { start: clickedDate };
2307
+ }
2308
+ return { start, end: clickedDate };
2309
+ }
2310
+ function isSameDay(left, right) {
2311
+ return left.getFullYear() === right.getFullYear() && left.getMonth() === right.getMonth() && left.getDate() === right.getDate();
2312
+ }
2313
+ function isBeforeDay(left, right) {
2314
+ return stripTime(left).getTime() < stripTime(right).getTime();
2315
+ }
2316
+ function isAfterDay(left, right) {
2317
+ return stripTime(left).getTime() > stripTime(right).getTime();
2318
+ }
2319
+ function addMonths(date, amount) {
2320
+ return new Date(date.getFullYear(), date.getMonth() + amount, 1);
2321
+ }
2322
+ function isDateDisabled(date, minDate, maxDate) {
2323
+ if (minDate && isBeforeDay(date, minDate)) {
2324
+ return true;
2325
+ }
2326
+ if (maxDate && isAfterDay(date, maxDate)) {
2327
+ return true;
2328
+ }
2329
+ return false;
2330
+ }
2331
+ var CALENDAR_VISIBLE_DAY_COUNT = 42;
2332
+ var MONDAY_WEEK_START = 1;
2333
+ function buildCalendarDays({
2334
+ viewDate,
2335
+ selectedDate,
2336
+ selectedRange,
2337
+ today,
2338
+ minDate,
2339
+ maxDate
2340
+ }) {
2341
+ const { start: rangeStart, end: rangeEnd } = normalizeDateRange(selectedRange);
2342
+ const year = viewDate.getFullYear();
2343
+ const month = viewDate.getMonth();
2344
+ const firstOfMonth = new Date(year, month, 1);
2345
+ const startOffset = (firstOfMonth.getDay() - MONDAY_WEEK_START + 7) % 7;
2346
+ const gridStart = new Date(year, month, 1 - startOffset);
2347
+ const days = [];
2348
+ for (let index = 0; index < CALENDAR_VISIBLE_DAY_COUNT; index += 1) {
2349
+ const date = new Date(
2350
+ gridStart.getFullYear(),
2351
+ gridStart.getMonth(),
2352
+ gridStart.getDate() + index
2353
+ );
2354
+ const inCurrentMonth = date.getMonth() === month;
2355
+ const isPast = inCurrentMonth && isBeforeDay(date, today);
2356
+ const isDisabled = isDateDisabled(date, minDate, maxDate);
2357
+ const isRangeStart = rangeStart ? isSameDay(date, rangeStart) : false;
2358
+ const isRangeEnd = rangeEnd ? isSameDay(date, rangeEnd) : false;
2359
+ const inSelectedRange = rangeStart && rangeEnd ? isInDateRange(date, rangeStart, rangeEnd) : false;
2360
+ const isInRange = inSelectedRange && !isRangeStart && !isRangeEnd;
2361
+ const isSelected = selectedDate ? isSameDay(date, selectedDate) : inSelectedRange || Boolean(rangeStart && !rangeEnd && isRangeStart);
2362
+ days.push({
2363
+ date,
2364
+ inCurrentMonth,
2365
+ isToday: isSameDay(date, today),
2366
+ isSelected,
2367
+ isRangeStart,
2368
+ isRangeEnd,
2369
+ isInRange,
2370
+ isPast,
2371
+ isDisabled
2372
+ });
2373
+ }
2374
+ return days;
2375
+ }
2376
+ function formatCalendarYear(year, locale) {
2377
+ return new Intl.DateTimeFormat(locale, { year: "numeric" }).format(new Date(year, 0, 1));
2378
+ }
2379
+ function getYearPageStart(year, yearsPerPage = 12) {
2380
+ return Math.floor(year / yearsPerPage) * yearsPerPage;
2381
+ }
2382
+ function isMonthDisabled(year, month, minDate, maxDate) {
2383
+ const firstDay = new Date(year, month, 1);
2384
+ const lastDay = new Date(year, month + 1, 0);
2385
+ if (minDate && isBeforeDay(lastDay, minDate)) {
2386
+ return true;
2387
+ }
2388
+ if (maxDate && isAfterDay(firstDay, maxDate)) {
2389
+ return true;
2390
+ }
2391
+ return false;
2392
+ }
2393
+ function isYearDisabled(year, minDate, maxDate) {
2394
+ const firstDay = new Date(year, 0, 1);
2395
+ const lastDay = new Date(year, 11, 31);
2396
+ if (minDate && isBeforeDay(lastDay, minDate)) {
2397
+ return true;
2398
+ }
2399
+ if (maxDate && isAfterDay(firstDay, maxDate)) {
2400
+ return true;
2401
+ }
2402
+ return false;
2403
+ }
2404
+ function formatCalendarDate(date, locale) {
2405
+ return new Intl.DateTimeFormat(locale, {
2406
+ day: "numeric",
2407
+ month: "long",
2408
+ year: "numeric"
2409
+ }).format(date);
2410
+ }
2411
+ function formatCalendarDateRange(range, locale, separator = " \u2013 ") {
2412
+ const { start, end } = normalizeDateRange(range);
2413
+ if (!start) {
2414
+ return "";
2415
+ }
2416
+ if (!end) {
2417
+ return formatCalendarDate(start, locale);
2418
+ }
2419
+ return `${formatCalendarDate(start, locale)}${separator}${formatCalendarDate(end, locale)}`;
2420
+ }
2421
+
2422
+ // src/utils/calendarLocalization.ts
2423
+ var calendarTranslations = {
2424
+ "hy-AM": {
2425
+ weekdays: ["\u0535\u0550", "\u0535\u0554", "\u0549\u0550", "\u0540\u0546", "\u0548\u0552\u0550", "\u0547\u0532", "\u053F\u0550"],
2426
+ monthsShort: [
2427
+ "\u0540\u0576\u057E",
2428
+ "\u0553\u057F\u057E",
2429
+ "\u0544\u0580\u057F",
2430
+ "\u0531\u057A\u0580",
2431
+ "\u0544\u0575\u057D",
2432
+ "\u0540\u0578\u0582\u0576",
2433
+ "\u0540\u0578\u0582\u056C",
2434
+ "\u0555\u0563\u057D",
2435
+ "\u054D\u0565\u057A",
2436
+ "\u0540\u0578\u056F",
2437
+ "\u0546\u0578\u0575",
2438
+ "\u0534\u0565\u056F"
2439
+ ],
2440
+ monthsLong: [
2441
+ "\u0540\u0578\u0582\u0576\u057E\u0561\u0580",
2442
+ "\u0553\u0565\u057F\u0580\u057E\u0561\u0580",
2443
+ "\u0544\u0561\u0580\u057F",
2444
+ "\u0531\u057A\u0580\u056B\u056C",
2445
+ "\u0544\u0561\u0575\u056B\u057D",
2446
+ "\u0540\u0578\u0582\u0576\u056B\u057D",
2447
+ "\u0540\u0578\u0582\u056C\u056B\u057D",
2448
+ "\u0555\u0563\u0578\u057D\u057F\u0578\u057D",
2449
+ "\u054D\u0565\u057A\u057F\u0565\u0574\u0562\u0565\u0580",
2450
+ "\u0540\u0578\u056F\u057F\u0565\u0574\u0562\u0565\u0580",
2451
+ "\u0546\u0578\u0575\u0565\u0574\u0562\u0565\u0580",
2452
+ "\u0534\u0565\u056F\u057F\u0565\u0574\u0562\u0565\u0580"
2453
+ ],
2454
+ datePlaceholder: "\u0538\u0576\u057F\u0580\u0565\u056C \u0561\u0574\u057D\u0561\u0569\u056B\u057E",
2455
+ rangePlaceholder: "\u0538\u0576\u057F\u0580\u0565\u056C \u056A\u0561\u0574\u0561\u0576\u0561\u056F\u0561\u0570\u0561\u057F\u057E\u0561\u056E",
2456
+ previousMonth: "\u0546\u0561\u056D\u0578\u0580\u0564 \u0561\u0574\u056B\u057D",
2457
+ nextMonth: "\u0540\u0561\u057B\u0578\u0580\u0564 \u0561\u0574\u056B\u057D",
2458
+ previousYear: "\u0546\u0561\u056D\u0578\u0580\u0564 \u057F\u0561\u0580\u056B",
2459
+ nextYear: "\u0540\u0561\u057B\u0578\u0580\u0564 \u057F\u0561\u0580\u056B",
2460
+ previousYears: "\u0546\u0561\u056D\u0578\u0580\u0564 \u057F\u0561\u0580\u056B\u0576\u0565\u0580",
2461
+ nextYears: "\u0540\u0561\u057B\u0578\u0580\u0564 \u057F\u0561\u0580\u056B\u0576\u0565\u0580",
2462
+ selectMonth: "\u0538\u0576\u057F\u0580\u0565\u056C \u0561\u0574\u056B\u057D",
2463
+ selectYear: "\u0538\u0576\u057F\u0580\u0565\u056C \u057F\u0561\u0580\u056B",
2464
+ closeCalendar: "\u0553\u0561\u056F\u0565\u056C \u0585\u0580\u0561\u0581\u0578\u0582\u0575\u0581\u0568"
2465
+ },
2466
+ "en-US": {
2467
+ weekdays: ["MO", "TU", "WE", "TH", "FR", "SA", "SU"],
2468
+ monthsShort: [
2469
+ "Jan",
2470
+ "Feb",
2471
+ "Mar",
2472
+ "Apr",
2473
+ "May",
2474
+ "Jun",
2475
+ "Jul",
2476
+ "Aug",
2477
+ "Sep",
2478
+ "Oct",
2479
+ "Nov",
2480
+ "Dec"
2481
+ ],
2482
+ monthsLong: [
2483
+ "January",
2484
+ "February",
2485
+ "March",
2486
+ "April",
2487
+ "May",
2488
+ "June",
2489
+ "July",
2490
+ "August",
2491
+ "September",
2492
+ "October",
2493
+ "November",
2494
+ "December"
2495
+ ],
2496
+ datePlaceholder: "Select date",
2497
+ rangePlaceholder: "Select date range",
2498
+ previousMonth: "Previous month",
2499
+ nextMonth: "Next month",
2500
+ previousYear: "Previous year",
2501
+ nextYear: "Next year",
2502
+ previousYears: "Previous years",
2503
+ nextYears: "Next years",
2504
+ selectMonth: "Select month",
2505
+ selectYear: "Select year",
2506
+ closeCalendar: "Close calendar"
2507
+ },
2508
+ "ru-RU": {
2509
+ weekdays: ["\u041F\u041D", "\u0412\u0422", "\u0421\u0420", "\u0427\u0422", "\u041F\u0422", "\u0421\u0411", "\u0412\u0421"],
2510
+ monthsShort: [
2511
+ "\u042F\u043D\u0432",
2512
+ "\u0424\u0435\u0432",
2513
+ "\u041C\u0430\u0440",
2514
+ "\u0410\u043F\u0440",
2515
+ "\u041C\u0430\u0439",
2516
+ "\u0418\u044E\u043D",
2517
+ "\u0418\u044E\u043B",
2518
+ "\u0410\u0432\u0433",
2519
+ "\u0421\u0435\u043D",
2520
+ "\u041E\u043A\u0442",
2521
+ "\u041D\u043E\u044F",
2522
+ "\u0414\u0435\u043A"
2523
+ ],
2524
+ monthsLong: [
2525
+ "\u042F\u043D\u0432\u0430\u0440\u044C",
2526
+ "\u0424\u0435\u0432\u0440\u0430\u043B\u044C",
2527
+ "\u041C\u0430\u0440\u0442",
2528
+ "\u0410\u043F\u0440\u0435\u043B\u044C",
2529
+ "\u041C\u0430\u0439",
2530
+ "\u0418\u044E\u043D\u044C",
2531
+ "\u0418\u044E\u043B\u044C",
2532
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
2533
+ "\u0421\u0435\u043D\u0442\u044F\u0431\u0440\u044C",
2534
+ "\u041E\u043A\u0442\u044F\u0431\u0440\u044C",
2535
+ "\u041D\u043E\u044F\u0431\u0440\u044C",
2536
+ "\u0414\u0435\u043A\u0430\u0431\u0440\u044C"
2537
+ ],
2538
+ datePlaceholder: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0434\u0430\u0442\u0443",
2539
+ rangePlaceholder: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043F\u0435\u0440\u0438\u043E\u0434",
2540
+ previousMonth: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u043C\u0435\u0441\u044F\u0446",
2541
+ nextMonth: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u043C\u0435\u0441\u044F\u0446",
2542
+ previousYear: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0433\u043E\u0434",
2543
+ nextYear: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0433\u043E\u0434",
2544
+ previousYears: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0435 \u0433\u043E\u0434\u044B",
2545
+ nextYears: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u0433\u043E\u0434\u044B",
2546
+ selectMonth: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043C\u0435\u0441\u044F\u0446",
2547
+ selectYear: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0433\u043E\u0434",
2548
+ closeCalendar: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u044C"
2549
+ }
2550
+ };
2551
+ function resolveCalendarLocale(locale) {
2552
+ const normalizedLocale = locale.toLowerCase();
2553
+ if (normalizedLocale.startsWith("hy")) {
2554
+ return "hy-AM";
2555
+ }
2556
+ if (normalizedLocale.startsWith("ru")) {
2557
+ return "ru-RU";
2558
+ }
2559
+ return "en-US";
2560
+ }
2561
+ function getCalendarTranslations(locale) {
2562
+ return calendarTranslations[resolveCalendarLocale(locale)];
2563
+ }
2564
+ function resolveWeekdayLabels(locale) {
2565
+ return getCalendarTranslations(locale).weekdays;
2566
+ }
2567
+ function getCalendarMonthLabels(locale, width = "short") {
2568
+ const translations = getCalendarTranslations(locale);
2569
+ return width === "short" ? translations.monthsShort : translations.monthsLong;
2570
+ }
2571
+ function formatLocalizedCalendarMonthYear(date, locale) {
2572
+ return `${getCalendarMonthLabels(locale)[date.getMonth()]} ${date.getFullYear()}`;
2573
+ }
2574
+ var LOCALE_STORAGE_KEY = "homepad.locale";
2575
+ var LOCALE_CHANGE_EVENT = "homepad:locale-change";
2576
+ var DEFAULT_CALENDAR_LOCALE = "hy-AM";
2577
+ var CalendarLocaleContext = react.createContext(void 0);
2578
+ function CalendarLocaleProvider({ locale, children }) {
2579
+ return /* @__PURE__ */ jsxRuntime.jsx(CalendarLocaleContext.Provider, { value: locale, children });
2580
+ }
2581
+ function normalizeProjectLocale(locale) {
2582
+ if (!locale) {
2583
+ return null;
2584
+ }
2585
+ return resolveCalendarLocale(locale);
2586
+ }
2587
+ function readBrowserLocale() {
2588
+ if (typeof window === "undefined") {
2589
+ return null;
2590
+ }
2591
+ let storedLocale = null;
2592
+ try {
2593
+ storedLocale = normalizeProjectLocale(window.localStorage.getItem(LOCALE_STORAGE_KEY));
2594
+ } catch {
2595
+ storedLocale = null;
2596
+ }
2597
+ if (storedLocale) {
2598
+ return storedLocale;
2599
+ }
2600
+ const documentLocale = normalizeProjectLocale(window.document?.documentElement.lang);
2601
+ if (documentLocale) {
2602
+ return documentLocale;
2603
+ }
2604
+ return normalizeProjectLocale(window.navigator.language);
2605
+ }
2606
+ function useCalendarLocale(locale) {
2607
+ const contextLocale = react.useContext(CalendarLocaleContext);
2608
+ const controlledLocale = locale ?? contextLocale;
2609
+ const [browserLocale, setBrowserLocale] = react.useState(
2610
+ () => readBrowserLocale() ?? DEFAULT_CALENDAR_LOCALE
2611
+ );
2612
+ react.useEffect(() => {
2613
+ if (controlledLocale !== void 0 || typeof window === "undefined") {
2614
+ return;
2615
+ }
2616
+ const syncLocale = () => {
2617
+ setBrowserLocale(readBrowserLocale() ?? DEFAULT_CALENDAR_LOCALE);
2618
+ };
2619
+ const handleLocaleChange = (event) => {
2620
+ const customEvent = event;
2621
+ const nextLocale = normalizeProjectLocale(customEvent.detail);
2622
+ if (nextLocale) {
2623
+ setBrowserLocale(nextLocale);
2624
+ return;
2625
+ }
2626
+ syncLocale();
2627
+ };
2628
+ window.addEventListener(LOCALE_CHANGE_EVENT, handleLocaleChange);
2629
+ window.addEventListener("storage", syncLocale);
2630
+ return () => {
2631
+ window.removeEventListener(LOCALE_CHANGE_EVENT, handleLocaleChange);
2632
+ window.removeEventListener("storage", syncLocale);
2633
+ };
2634
+ }, [controlledLocale]);
2635
+ return react.useMemo(
2636
+ () => normalizeProjectLocale(controlledLocale) ?? browserLocale,
2637
+ [browserLocale, controlledLocale]
2638
+ );
2639
+ }
2640
+ function resolveDayCellStyle(day) {
2641
+ if (day.isDisabled) {
2642
+ return [calendarDropdownMetrics.dayCell];
2643
+ }
2644
+ if (day.isSelected) {
2645
+ return [calendarDropdownMetrics.dayCell, calendarDropdownMetrics.dayCellSelected];
2646
+ }
2647
+ return [
2648
+ calendarDropdownMetrics.dayCell,
2649
+ day.inCurrentMonth && day.isPast && !day.isToday ? calendarDropdownMetrics.dayCellPast : null
2650
+ ];
2651
+ }
2652
+ function resolveDayLabelStyle(day) {
2653
+ if (day.isDisabled) {
2654
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelDisabled];
2655
+ }
2656
+ if (day.isSelected) {
2657
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelSelected];
2658
+ }
2659
+ if (!day.inCurrentMonth) {
2660
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelOutsideMonth];
2661
+ }
2662
+ if (day.isToday) {
2663
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelToday];
2664
+ }
2665
+ if (day.isPast) {
2666
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelMuted];
2667
+ }
2668
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelFuture];
2669
+ }
2670
+ function Calendar(props) {
2671
+ const rangeProps = props.mode === "range" ? props : null;
2672
+ const singleProps = props.mode === "range" ? null : props;
2673
+ const {
2674
+ viewDate,
2675
+ defaultViewDate,
2676
+ onViewDateChange,
2677
+ locale,
2678
+ labels,
2679
+ minDate,
2680
+ maxDate,
2681
+ today = /* @__PURE__ */ new Date(),
2682
+ style,
2683
+ className
2684
+ } = props;
2685
+ const rootRef = react.useRef(null);
2686
+ const [internalViewDate, setInternalViewDate] = react.useState(() => {
2687
+ if (defaultViewDate) {
2688
+ return defaultViewDate;
2689
+ }
2690
+ if (rangeProps) {
2691
+ return rangeProps.value?.start ?? today;
2692
+ }
2693
+ return singleProps?.value ?? today;
2694
+ });
2695
+ const activeViewDate = viewDate ?? internalViewDate;
2696
+ const [pickerView, setPickerView] = react.useState("days");
2697
+ const [pickerYear, setPickerYear] = react.useState(() => activeViewDate.getFullYear());
2698
+ const [yearPageStart, setYearPageStart] = react.useState(
2699
+ () => getYearPageStart(activeViewDate.getFullYear(), CALENDAR_YEARS_PER_PAGE)
2700
+ );
2701
+ const customWeekdayLabels = labels?.weekdays;
2702
+ const formatMonthYearLabel = labels?.formatMonthYear;
2703
+ const resolvedLocale = useCalendarLocale(locale);
2704
+ const translations = react.useMemo(
2705
+ () => getCalendarTranslations(resolvedLocale),
2706
+ [resolvedLocale]
2707
+ );
2708
+ useApplyWebClassName(rootRef, className);
2709
+ const weekdayLabels = react.useMemo(
2710
+ () => customWeekdayLabels ?? resolveWeekdayLabels(resolvedLocale),
2711
+ [customWeekdayLabels, resolvedLocale]
2712
+ );
2713
+ const monthLabels = react.useMemo(() => getCalendarMonthLabels(resolvedLocale), [resolvedLocale]);
2714
+ const monthYearLabel = react.useMemo(() => {
2715
+ if (formatMonthYearLabel) {
2716
+ return formatMonthYearLabel(activeViewDate);
2717
+ }
2718
+ return formatLocalizedCalendarMonthYear(activeViewDate, resolvedLocale);
2719
+ }, [activeViewDate, formatMonthYearLabel, resolvedLocale]);
2720
+ const headerLabel = react.useMemo(() => {
2721
+ if (pickerView === "months") {
2722
+ return formatCalendarYear(pickerYear, resolvedLocale);
2723
+ }
2724
+ if (pickerView === "years") {
2725
+ const endYear = yearPageStart + CALENDAR_YEARS_PER_PAGE - 1;
2726
+ return `${yearPageStart} \u2013 ${endYear}`;
2727
+ }
2728
+ return monthYearLabel;
2729
+ }, [monthYearLabel, pickerView, pickerYear, resolvedLocale, yearPageStart]);
2730
+ const days = react.useMemo(
2731
+ () => buildCalendarDays({
2732
+ viewDate: activeViewDate,
2733
+ selectedDate: singleProps?.value,
2734
+ selectedRange: rangeProps?.value,
2735
+ today,
2736
+ minDate,
2737
+ maxDate
2738
+ }),
2739
+ [activeViewDate, maxDate, minDate, rangeProps?.value, singleProps?.value, today]
2740
+ );
2741
+ const yearOptions = react.useMemo(
2742
+ () => Array.from({ length: CALENDAR_YEARS_PER_PAGE }, (_, index) => yearPageStart + index),
2743
+ [yearPageStart]
2744
+ );
2745
+ function getLabel(key) {
2746
+ return labels?.[key] ?? translations[key];
2747
+ }
2748
+ function setViewDate(nextDate) {
2749
+ if (viewDate === void 0) {
2750
+ setInternalViewDate(nextDate);
2751
+ }
2752
+ onViewDateChange?.(nextDate);
2753
+ }
2754
+ function handlePrevious() {
2755
+ if (pickerView === "months") {
2756
+ setPickerYear((year) => year - 1);
2757
+ return;
2758
+ }
2759
+ if (pickerView === "years") {
2760
+ setYearPageStart((start) => start - CALENDAR_YEARS_PER_PAGE);
2761
+ return;
2762
+ }
2763
+ setViewDate(addMonths(activeViewDate, -1));
2764
+ }
2765
+ function handleNext() {
2766
+ if (pickerView === "months") {
2767
+ setPickerYear((year) => year + 1);
2768
+ return;
2769
+ }
2770
+ if (pickerView === "years") {
2771
+ setYearPageStart((start) => start + CALENDAR_YEARS_PER_PAGE);
2772
+ return;
2773
+ }
2774
+ setViewDate(addMonths(activeViewDate, 1));
2775
+ }
2776
+ function handleHeaderPress() {
2777
+ if (pickerView === "days") {
2778
+ setPickerYear(activeViewDate.getFullYear());
2779
+ setPickerView("months");
2780
+ return;
2781
+ }
2782
+ if (pickerView === "months") {
2783
+ setYearPageStart(getYearPageStart(pickerYear, CALENDAR_YEARS_PER_PAGE));
2784
+ setPickerView("years");
2785
+ }
2786
+ }
2787
+ function handleMonthSelect(month) {
2788
+ setViewDate(new Date(pickerYear, month, 1));
2789
+ setPickerView("days");
2790
+ }
2791
+ function handleYearSelect(year) {
2792
+ setPickerYear(year);
2793
+ setPickerView("months");
2794
+ }
2795
+ function handleDayPress(date) {
2796
+ if (rangeProps) {
2797
+ rangeProps.onChange?.(selectRangeDate(date, rangeProps.value));
2798
+ return;
2799
+ }
2800
+ singleProps?.onChange?.(date);
2801
+ }
2802
+ const headerIsPressable = pickerView === "days" || pickerView === "months";
2803
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: rootRef, style: [calendarDropdownMetrics.panel, style], children: [
2804
+ /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: calendarDropdownMetrics.header, children: [
2805
+ /* @__PURE__ */ jsxRuntime.jsx(
2806
+ reactNative.Pressable,
2807
+ {
2808
+ accessibilityRole: "button",
2809
+ accessibilityLabel: pickerView === "months" ? getLabel("previousYear") : pickerView === "years" ? getLabel("previousYears") : getLabel("previousMonth"),
2810
+ onPress: handlePrevious,
2811
+ style: calendarDropdownMetrics.navButton,
2812
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronLeftIcon, { size: CALENDAR_NAV_ICON_SIZE, color: CALENDAR_NAV_ICON_COLOR })
2813
+ }
1240
2814
  ),
1241
- /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles5.phoneColumn, children: [
1242
- /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [phoneFieldStyles.outline, styles5.phoneOutline], children: /* @__PURE__ */ jsxRuntime.jsx(
1243
- reactNative.View,
1244
- {
1245
- style: [
1246
- inputFieldMetrics.container,
1247
- phoneFieldStyles.container,
1248
- styles5.phoneField
1249
- ],
1250
- children: /* @__PURE__ */ jsxRuntime.jsx(
1251
- reactNative.TextInput,
1252
- {
1253
- ref: inputRef,
1254
- style: [
1255
- inputFieldMetrics.input,
1256
- phoneFieldStyles.text,
1257
- style
1258
- ],
1259
- keyboardType: "phone-pad",
1260
- placeholderTextColor: phoneFieldStyles.placeholder,
1261
- editable,
1262
- onFocus: handleFocus,
1263
- onBlur: handleBlur,
1264
- accessibilityState: { disabled: isDisabled },
1265
- ...props
1266
- }
1267
- )
1268
- }
1269
- ) }),
1270
- helperMessage ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: helperRef, style: error ? styles5.error : styles5.hint, children: helperMessage }) : null
1271
- ] })
1272
- ] })
2815
+ headerIsPressable ? /* @__PURE__ */ jsxRuntime.jsx(
2816
+ reactNative.Pressable,
2817
+ {
2818
+ accessibilityRole: "button",
2819
+ accessibilityLabel: pickerView === "days" ? getLabel("selectMonth") : getLabel("selectYear"),
2820
+ onPress: handleHeaderPress,
2821
+ style: calendarDropdownMetrics.headerTitlePressable,
2822
+ children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: calendarDropdownMetrics.headerTitle, children: headerLabel })
2823
+ }
2824
+ ) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.headerTitlePressable, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: calendarDropdownMetrics.headerTitle, children: headerLabel }) }),
2825
+ /* @__PURE__ */ jsxRuntime.jsx(
2826
+ reactNative.Pressable,
2827
+ {
2828
+ accessibilityRole: "button",
2829
+ accessibilityLabel: pickerView === "months" ? getLabel("nextYear") : pickerView === "years" ? getLabel("nextYears") : getLabel("nextMonth"),
2830
+ onPress: handleNext,
2831
+ style: calendarDropdownMetrics.navButton,
2832
+ children: /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { size: CALENDAR_NAV_ICON_SIZE, color: CALENDAR_NAV_ICON_COLOR })
2833
+ }
2834
+ )
2835
+ ] }),
2836
+ pickerView === "days" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
2837
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.weekdayRow, children: weekdayLabels.map((weekday) => /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.weekdayCell, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: calendarDropdownMetrics.weekdayLabel, children: weekday }) }, weekday)) }),
2838
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.dayGrid, children: days.map((day) => /* @__PURE__ */ jsxRuntime.jsxs(
2839
+ reactNative.Pressable,
2840
+ {
2841
+ accessibilityRole: "button",
2842
+ accessibilityState: {
2843
+ selected: day.isSelected,
2844
+ disabled: day.isDisabled
2845
+ },
2846
+ disabled: day.isDisabled,
2847
+ onPress: () => handleDayPress(day.date),
2848
+ style: resolveDayCellStyle(day),
2849
+ children: [
2850
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { style: resolveDayLabelStyle(day), children: day.date.getDate() }),
2851
+ day.isToday && day.inCurrentMonth && !day.isSelected ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.todayDot }) : null
2852
+ ]
2853
+ },
2854
+ day.date.toISOString()
2855
+ )) })
2856
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.pickerBody, children: /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: calendarDropdownMetrics.pickerGrid, children: pickerView === "months" ? monthLabels.map((monthLabel, month) => {
2857
+ const isSelected = activeViewDate.getFullYear() === pickerYear && activeViewDate.getMonth() === month;
2858
+ const isCurrent = today.getFullYear() === pickerYear && today.getMonth() === month;
2859
+ const disabled = isMonthDisabled(pickerYear, month, minDate, maxDate);
2860
+ return /* @__PURE__ */ jsxRuntime.jsx(
2861
+ reactNative.Pressable,
2862
+ {
2863
+ accessibilityRole: "button",
2864
+ accessibilityState: { selected: isSelected, disabled },
2865
+ disabled,
2866
+ onPress: () => handleMonthSelect(month),
2867
+ style: [
2868
+ calendarDropdownMetrics.pickerCell,
2869
+ isSelected ? calendarDropdownMetrics.pickerCellSelected : null
2870
+ ],
2871
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2872
+ reactNative.Text,
2873
+ {
2874
+ style: [
2875
+ calendarDropdownMetrics.pickerLabel,
2876
+ isSelected ? calendarDropdownMetrics.pickerLabelSelected : null,
2877
+ !isSelected && isCurrent ? calendarDropdownMetrics.pickerLabelCurrent : null,
2878
+ disabled ? calendarDropdownMetrics.pickerLabelDisabled : null
2879
+ ],
2880
+ children: monthLabel
2881
+ }
2882
+ )
2883
+ },
2884
+ monthLabel
2885
+ );
2886
+ }) : yearOptions.map((year) => {
2887
+ const isSelected = activeViewDate.getFullYear() === year;
2888
+ const isCurrent = today.getFullYear() === year;
2889
+ const disabled = isYearDisabled(year, minDate, maxDate);
2890
+ return /* @__PURE__ */ jsxRuntime.jsx(
2891
+ reactNative.Pressable,
2892
+ {
2893
+ accessibilityRole: "button",
2894
+ accessibilityState: { selected: isSelected, disabled },
2895
+ disabled,
2896
+ onPress: () => handleYearSelect(year),
2897
+ style: [
2898
+ calendarDropdownMetrics.pickerCell,
2899
+ isSelected ? calendarDropdownMetrics.pickerCellSelected : null
2900
+ ],
2901
+ children: /* @__PURE__ */ jsxRuntime.jsx(
2902
+ reactNative.Text,
2903
+ {
2904
+ style: [
2905
+ calendarDropdownMetrics.pickerLabel,
2906
+ isSelected ? calendarDropdownMetrics.pickerLabelSelected : null,
2907
+ !isSelected && isCurrent ? calendarDropdownMetrics.pickerLabelCurrent : null,
2908
+ disabled ? calendarDropdownMetrics.pickerLabelDisabled : null
2909
+ ],
2910
+ children: year
2911
+ }
2912
+ )
2913
+ },
2914
+ year
2915
+ );
2916
+ }) }) })
1273
2917
  ] });
1274
2918
  }
1275
- var styles5 = reactNative.StyleSheet.create({
2919
+
2920
+ // src/icons/calendarIconPaths.ts
2921
+ var CALENDAR_ICON_BODY_PATH = "M6.66667 1.6665V4.99984M13.3333 1.6665V4.99984M2.5 8.33317H17.5M4.16667 3.33317H15.8333C16.7538 3.33317 17.5 4.07936 17.5 4.99984V16.6665C17.5 17.587 16.7538 18.3332 15.8333 18.3332H4.16667C3.24619 18.3332 2.5 17.587 2.5 16.6665V4.99984C2.5 4.07936 3.24619 3.33317 4.16667 3.33317Z";
2922
+ function CalendarIcon({
2923
+ size = 20,
2924
+ color = "#C7CDD1",
2925
+ strokeWidth = 2
2926
+ }) {
2927
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg5__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
2928
+ Svg5.Path,
2929
+ {
2930
+ d: CALENDAR_ICON_BODY_PATH,
2931
+ stroke: color,
2932
+ strokeWidth,
2933
+ strokeLinecap: "round",
2934
+ strokeLinejoin: "round"
2935
+ }
2936
+ ) });
2937
+ }
2938
+ function DatePicker(props) {
2939
+ const {
2940
+ label,
2941
+ placeholder,
2942
+ locale,
2943
+ labels,
2944
+ minDate,
2945
+ maxDate,
2946
+ today,
2947
+ viewDate,
2948
+ defaultViewDate,
2949
+ onViewDateChange,
2950
+ disabled = false,
2951
+ error,
2952
+ invalid,
2953
+ hint,
2954
+ containerStyle,
2955
+ className,
2956
+ fieldClassName,
2957
+ panelClassName,
2958
+ labelClassName,
2959
+ errorClassName,
2960
+ hintClassName,
2961
+ defaultOpen = false
2962
+ } = props;
2963
+ const mode = props.mode ?? "single";
2964
+ const closeOnRangeComplete = props.mode === "range" ? props.closeOnRangeComplete ?? true : false;
2965
+ const resolvedLocale = useCalendarLocale(locale);
2966
+ const translations = getCalendarTranslations(resolvedLocale);
2967
+ const resolvedPlaceholder = placeholder ?? (mode === "range" ? translations.rangePlaceholder : translations.datePlaceholder);
2968
+ const wrapperRef = react.useRef(null);
2969
+ const triggerRef = react.useRef(null);
2970
+ const helperRef = react.useRef(null);
2971
+ const [open, setOpen] = react.useState(defaultOpen);
2972
+ const [anchor, setAnchor] = react.useState(null);
2973
+ useApplyWebClassName(wrapperRef, className);
2974
+ useApplyWebClassName(triggerRef, fieldClassName);
2975
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
2976
+ react.useEffect(() => {
2977
+ if (!defaultOpen || disabled) {
2978
+ return;
2979
+ }
2980
+ const frame = requestAnimationFrame(() => {
2981
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
2982
+ setAnchor({ x, y, width, height });
2983
+ setOpen(true);
2984
+ });
2985
+ });
2986
+ return () => cancelAnimationFrame(frame);
2987
+ }, [defaultOpen, disabled]);
2988
+ const hasError = Boolean(error) || Boolean(invalid);
2989
+ const fieldStyles = getSelectFieldStyles(
2990
+ resolveInputVisualState({
2991
+ error: hasError,
2992
+ disabled
2993
+ })
2994
+ );
2995
+ const hasValue = mode === "single" ? Boolean(props.value) : Boolean(props.mode === "range" && props.value?.start);
2996
+ const displayValue = (() => {
2997
+ if (props.mode === "range") {
2998
+ if (!props.value?.start) {
2999
+ return resolvedPlaceholder;
3000
+ }
3001
+ return props.formatRange?.(props.value) ?? formatCalendarDateRange(props.value, resolvedLocale, props.rangeSeparator);
3002
+ }
3003
+ if (props.value) {
3004
+ return props.formatDate?.(props.value) ?? formatCalendarDate(props.value, resolvedLocale);
3005
+ }
3006
+ return resolvedPlaceholder;
3007
+ })();
3008
+ const isPlaceholder = !hasValue;
3009
+ const valueTextStyle = isPlaceholder ? {
3010
+ ...calendarFieldPlaceholderTypography,
3011
+ color: disabled ? colors.stormGray300 : calendarFieldPlaceholderTypography.color
3012
+ } : {
3013
+ ...calendarFieldTypography,
3014
+ color: fieldStyles.value.color
3015
+ };
3016
+ const helperMessage = error ?? hint;
3017
+ const panelWidth = CALENDAR_PANEL_WIDTH;
3018
+ const panelLeft = anchor ? resolveCalendarDropdownLeft(anchor, panelWidth) : 0;
3019
+ const dropdownTop = anchor ? resolveCalendarDropdownTop(anchor) : 0;
3020
+ const resolvedDefaultViewDate = defaultViewDate ?? (props.mode === "range" ? props.value?.start : props.value) ?? today;
3021
+ function closePicker() {
3022
+ setOpen(false);
3023
+ setAnchor(null);
3024
+ }
3025
+ function openPicker() {
3026
+ if (disabled) {
3027
+ return;
3028
+ }
3029
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
3030
+ setAnchor({ x, y, width, height });
3031
+ setOpen(true);
3032
+ });
3033
+ }
3034
+ function handleSingleSelect(date) {
3035
+ if (props.mode === "range") {
3036
+ return;
3037
+ }
3038
+ props.onChange?.(date);
3039
+ closePicker();
3040
+ }
3041
+ function handleRangeSelect(range) {
3042
+ if (props.mode !== "range") {
3043
+ return;
3044
+ }
3045
+ props.onChange?.(range);
3046
+ if (closeOnRangeComplete && range.end) {
3047
+ closePicker();
3048
+ }
3049
+ }
3050
+ return /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { ref: wrapperRef, style: [styles7.wrapper, containerStyle], children: [
3051
+ label ? /* @__PURE__ */ jsxRuntime.jsx(Label, { disabled, style: styles7.label, className: labelClassName, children: label }) : null,
3052
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: [fieldStyles.outline, styles7.fieldOutline], children: /* @__PURE__ */ jsxRuntime.jsxs(
3053
+ reactNative.Pressable,
3054
+ {
3055
+ ref: triggerRef,
3056
+ accessibilityRole: "button",
3057
+ accessibilityState: { disabled, expanded: open },
3058
+ disabled,
3059
+ onPress: openPicker,
3060
+ style: [calendarFieldMetrics.container, fieldStyles.container],
3061
+ children: [
3062
+ /* @__PURE__ */ jsxRuntime.jsx(
3063
+ reactNative.Text,
3064
+ {
3065
+ style: [calendarFieldMetrics.value, valueTextStyle],
3066
+ numberOfLines: 1,
3067
+ children: displayValue
3068
+ }
3069
+ ),
3070
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.View, { style: styles7.iconSlot, children: /* @__PURE__ */ jsxRuntime.jsx(
3071
+ CalendarIcon,
3072
+ {
3073
+ size: CALENDAR_FIELD_ICON_SIZE,
3074
+ color: disabled ? colors.stormGray200 : colors.stormGray150
3075
+ }
3076
+ ) })
3077
+ ]
3078
+ }
3079
+ ) }),
3080
+ helperMessage ? /* @__PURE__ */ jsxRuntime.jsx(reactNative.Text, { ref: helperRef, style: error ? styles7.error : styles7.hint, children: helperMessage }) : null,
3081
+ /* @__PURE__ */ jsxRuntime.jsx(reactNative.Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: closePicker, children: /* @__PURE__ */ jsxRuntime.jsxs(reactNative.View, { style: styles7.modalRoot, children: [
3082
+ /* @__PURE__ */ jsxRuntime.jsx(
3083
+ reactNative.Pressable,
3084
+ {
3085
+ style: styles7.backdrop,
3086
+ onPress: closePicker,
3087
+ accessibilityRole: "button",
3088
+ accessibilityLabel: labels?.closeCalendar ?? translations.closeCalendar
3089
+ }
3090
+ ),
3091
+ anchor ? /* @__PURE__ */ jsxRuntime.jsx(
3092
+ reactNative.View,
3093
+ {
3094
+ style: [
3095
+ styles7.panelPosition,
3096
+ {
3097
+ top: dropdownTop,
3098
+ left: panelLeft,
3099
+ width: panelWidth,
3100
+ height: CALENDAR_PANEL_HEIGHT
3101
+ }
3102
+ ],
3103
+ children: props.mode === "range" ? /* @__PURE__ */ jsxRuntime.jsx(
3104
+ Calendar,
3105
+ {
3106
+ mode: "range",
3107
+ value: props.value,
3108
+ onChange: handleRangeSelect,
3109
+ viewDate,
3110
+ defaultViewDate: resolvedDefaultViewDate,
3111
+ onViewDateChange,
3112
+ locale: resolvedLocale,
3113
+ labels,
3114
+ minDate,
3115
+ maxDate,
3116
+ today,
3117
+ className: panelClassName
3118
+ }
3119
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
3120
+ Calendar,
3121
+ {
3122
+ mode: "single",
3123
+ value: props.value,
3124
+ onChange: handleSingleSelect,
3125
+ viewDate,
3126
+ defaultViewDate: resolvedDefaultViewDate,
3127
+ onViewDateChange,
3128
+ locale: resolvedLocale,
3129
+ labels,
3130
+ minDate,
3131
+ maxDate,
3132
+ today,
3133
+ className: panelClassName
3134
+ }
3135
+ )
3136
+ }
3137
+ ) : null
3138
+ ] }) })
3139
+ ] });
3140
+ }
3141
+ var styles7 = reactNative.StyleSheet.create({
1276
3142
  wrapper: {
1277
- width: "100%",
1278
- gap: spacing.sm
1279
- },
1280
- row: {
1281
- flexDirection: "row",
1282
- alignItems: "flex-start",
1283
- gap: INPUT_ICON_GAP
3143
+ width: CALENDAR_FIELD_WIDTH,
3144
+ maxWidth: "100%",
3145
+ gap: SELECT_LABEL_GAP
1284
3146
  },
1285
- countrySelector: {
1286
- flexShrink: 0,
3147
+ fieldOutline: {
3148
+ width: CALENDAR_FIELD_WIDTH,
3149
+ maxWidth: "100%",
1287
3150
  alignSelf: "flex-start"
1288
3151
  },
1289
- phoneColumn: {
1290
- flex: 1,
1291
- gap: spacing.sm
3152
+ label: {
3153
+ ...calendarLabelTypography
1292
3154
  },
1293
- phoneOutline: {
1294
- width: "100%"
3155
+ iconSlot: {
3156
+ width: CALENDAR_FIELD_ICON_SIZE,
3157
+ height: CALENDAR_FIELD_ICON_SIZE,
3158
+ alignItems: "center",
3159
+ justifyContent: "center",
3160
+ flexShrink: 0
1295
3161
  },
1296
- phoneField: {
3162
+ modalRoot: {
1297
3163
  flex: 1
1298
3164
  },
3165
+ backdrop: {
3166
+ ...reactNative.StyleSheet.absoluteFillObject,
3167
+ backgroundColor: colors.transparent
3168
+ },
3169
+ panelPosition: {
3170
+ position: "absolute",
3171
+ zIndex: 1
3172
+ },
1299
3173
  error: {
1300
3174
  fontSize: 12,
1301
- lineHeight: 16,
3175
+ lineHeight: 12,
1302
3176
  color: colors.inputError
1303
3177
  },
1304
3178
  hint: {
1305
3179
  fontSize: 12,
1306
- lineHeight: 16,
3180
+ lineHeight: 12,
1307
3181
  color: colors.stormGray300
1308
3182
  }
1309
3183
  });
1310
3184
 
3185
+ // src/icons/lockIconPaths.ts
3186
+ var LOCK_ICON_PATH = "M5.83333 8.33317V5.83317C5.83333 4.7281 6.27232 3.66829 7.05372 2.88689C7.83512 2.10549 8.89493 1.6665 10 1.6665C11.1051 1.6665 12.1649 2.10549 12.9463 2.88689C13.7277 3.66829 14.1667 4.7281 14.1667 5.83317V8.33317M10.8333 13.3332C10.8333 13.7934 10.4602 14.1665 10 14.1665C9.53976 14.1665 9.16667 13.7934 9.16667 13.3332C9.16667 12.8729 9.53976 12.4998 10 12.4998C10.4602 12.4998 10.8333 12.8729 10.8333 13.3332ZM4.16667 8.33317H15.8333C16.7538 8.33317 17.5 9.07936 17.5 9.99984V16.6665C17.5 17.587 16.7538 18.3332 15.8333 18.3332H4.16667C3.24619 18.3332 2.5 17.587 2.5 16.6665V9.99984C2.5 9.07936 3.24619 8.33317 4.16667 8.33317Z";
3187
+ function LockIcon({
3188
+ size = 20,
3189
+ color = "#c7cdd1",
3190
+ strokeWidth = 2
3191
+ }) {
3192
+ return /* @__PURE__ */ jsxRuntime.jsx(Svg5__default.default, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx(
3193
+ Svg5.Path,
3194
+ {
3195
+ d: LOCK_ICON_PATH,
3196
+ stroke: color,
3197
+ strokeWidth,
3198
+ strokeLinecap: "round",
3199
+ strokeLinejoin: "round"
3200
+ }
3201
+ ) });
3202
+ }
3203
+
1311
3204
  exports.Button = Button;
3205
+ exports.Calendar = Calendar;
3206
+ exports.CalendarIcon = CalendarIcon;
3207
+ exports.CalendarLocaleProvider = CalendarLocaleProvider;
1312
3208
  exports.CountryCodeSelector = CountryCodeSelector;
3209
+ exports.DatePicker = DatePicker;
1313
3210
  exports.Input = Input;
1314
3211
  exports.Label = Label;
3212
+ exports.LockIcon = LockIcon;
1315
3213
  exports.PhoneInput = PhoneInput;
3214
+ exports.Select = Select;
1316
3215
  exports.brand = brand;
1317
3216
  exports.buttonTypography = buttonTypography;
3217
+ exports.calendarTranslations = calendarTranslations;
1318
3218
  exports.colors = colors;
1319
3219
  exports.countries = countries;
1320
3220
  exports.defaultCountry = defaultCountry;
@@ -1323,12 +3223,18 @@ exports.findCountry = findCountry;
1323
3223
  exports.fontSize = fontSize;
1324
3224
  exports.fontWeight = fontWeight;
1325
3225
  exports.fonts = fonts;
3226
+ exports.formatLocalizedCalendarMonthYear = formatLocalizedCalendarMonthYear;
3227
+ exports.getCalendarMonthLabels = getCalendarMonthLabels;
3228
+ exports.getCalendarTranslations = getCalendarTranslations;
1326
3229
  exports.labelTypography = labelTypography;
1327
3230
  exports.navy = navy;
1328
3231
  exports.radii = radii;
3232
+ exports.resolveCalendarLocale = resolveCalendarLocale;
3233
+ exports.resolveWeekdayLabels = resolveWeekdayLabels;
1329
3234
  exports.rubyRed = rubyRed;
1330
3235
  exports.shadows = shadows;
1331
3236
  exports.spacing = spacing;
1332
3237
  exports.stormGray = stormGray;
3238
+ exports.useCalendarLocale = useCalendarLocale;
1333
3239
  //# sourceMappingURL=index.cjs.map
1334
3240
  //# sourceMappingURL=index.cjs.map