@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.js CHANGED
@@ -1,9 +1,9 @@
1
- import { colors, buttonTypography, fontSize, fontWeight, fonts, spacing, radii, INPUT_ICON_GAP, useApplyWebClassName, resolveInputVisualState, getInputFieldStyles, Label, inputFieldMetrics } from './chunk-C7GHBVMM.js';
2
- export { Input, Label, brand, buttonTypography, colors, emeraldGreen, fontSize, fontWeight, fonts, labelTypography, navy, radii, rubyRed, shadows, spacing, stormGray } from './chunk-C7GHBVMM.js';
3
- import { useRef, useState, useLayoutEffect } from 'react';
4
- import { StyleSheet, Platform, TouchableOpacity, Text, View, Pressable, ScrollView, Modal, TextInput, Dimensions } from 'react-native';
5
- import Svg, { Path } from 'react-native-svg';
6
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { colors, buttonTypography, spacing, fontSize, fontWeight, fonts, radii, INPUT_ICON_GAP, useApplyWebClassName, resolveInputVisualState, Label, getInputFieldStyles, inputFieldMetrics } from './chunk-66WR57JJ.js';
2
+ export { Input, Label, brand, buttonTypography, colors, emeraldGreen, fontSize, fontWeight, fonts, labelTypography, navy, radii, rubyRed, shadows, spacing, stormGray } from './chunk-66WR57JJ.js';
3
+ import { createContext, useRef, useState, useEffect, useMemo, useLayoutEffect, useContext, isValidElement, cloneElement } from 'react';
4
+ import { StyleSheet, Platform, TouchableOpacity, Text, View, Animated, Easing, Pressable, Modal, ScrollView, TextInput, Dimensions } from 'react-native';
5
+ import Svg3, { Path } from 'react-native-svg';
6
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
7
7
 
8
8
  // src/icons/arrowUpRightPath.ts
9
9
  var ARROW_UP_RIGHT_PATH = "M14.1667 14.1668V5.8335H5.83333M14.1667 5.8335L5.83333 14.1668";
@@ -12,7 +12,7 @@ function ArrowUpRightIcon({
12
12
  color = "#08275d",
13
13
  strokeWidth = 2
14
14
  }) {
15
- return /* @__PURE__ */ jsx(Svg, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
15
+ return /* @__PURE__ */ jsx(Svg3, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
16
16
  Path,
17
17
  {
18
18
  d: ARROW_UP_RIGHT_PATH,
@@ -194,6 +194,671 @@ var styles = StyleSheet.create({
194
194
  }
195
195
  });
196
196
 
197
+ // src/icons/chevronDownPath.ts
198
+ var CHEVRON_DOWN_PATH = "M4 6L8 10L12 6";
199
+ var CHEVRON_DOWN_PATH_20 = "M5 7.5L10 12.5L15 7.5";
200
+ function ChevronDownIcon({
201
+ size = 16,
202
+ color = "#dadde0",
203
+ strokeWidth = 2
204
+ }) {
205
+ const useLarge = size >= 20;
206
+ return /* @__PURE__ */ jsx(
207
+ Svg3,
208
+ {
209
+ width: size,
210
+ height: size,
211
+ viewBox: useLarge ? "0 0 20 20" : "0 0 16 16",
212
+ fill: "none",
213
+ children: /* @__PURE__ */ jsx(
214
+ Path,
215
+ {
216
+ d: useLarge ? CHEVRON_DOWN_PATH_20 : CHEVRON_DOWN_PATH,
217
+ stroke: color,
218
+ strokeWidth,
219
+ strokeLinecap: "round",
220
+ strokeLinejoin: "round"
221
+ }
222
+ )
223
+ }
224
+ );
225
+ }
226
+ var SELECT_HEIGHT = 52;
227
+ var SELECT_PADDING = 16;
228
+ var SELECT_INNER_GAP = 10;
229
+ var SELECT_ICON_SIZE = 20;
230
+ var SELECT_LABEL_GAP = spacing.sm;
231
+ var SELECT_DROPDOWN_GAP = spacing.sm;
232
+ var SELECT_DROPDOWN_PADDING = spacing.sm;
233
+ var SELECT_DROPDOWN_MAX_HEIGHT = 317;
234
+ var SELECT_OPTION_HEIGHT = 43;
235
+ var SELECT_OPTION_GAP = spacing.sm;
236
+ var SELECT_CHEVRON_SIZE = 20;
237
+ var SELECT_CHEVRON_COLOR = colors.stormGray150;
238
+ var SELECT_CHEVRON_ROTATION_MS = 200;
239
+ var selectLabelTypography = {
240
+ fontFamily: fonts.sans,
241
+ fontSize: fontSize.sm,
242
+ fontWeight: fontWeight.medium,
243
+ lineHeight: fontSize.sm,
244
+ letterSpacing: 0,
245
+ color: colors.slateBlue
246
+ };
247
+ var selectValueTypography = {
248
+ fontFamily: fonts.sans,
249
+ fontSize: fontSize.md,
250
+ fontWeight: fontWeight.regular,
251
+ lineHeight: fontSize.md,
252
+ letterSpacing: 0,
253
+ textAlign: "left"
254
+ };
255
+ var INPUT_OUTLINE_WIDTH = 2;
256
+ function createOutlineStyle(ringColor) {
257
+ return {
258
+ borderRadius: radii.lg + INPUT_OUTLINE_WIDTH,
259
+ borderWidth: INPUT_OUTLINE_WIDTH,
260
+ borderColor: ringColor,
261
+ padding: 0,
262
+ backgroundColor: colors.transparent,
263
+ width: "100%",
264
+ alignSelf: "stretch",
265
+ ...Platform.OS !== "web" ? { overflow: "hidden" } : null
266
+ };
267
+ }
268
+ var defaultOutline = createOutlineStyle(colors.transparent);
269
+ function getSelectFieldStyles(state) {
270
+ const containerBase = {
271
+ borderRadius: radii.lg,
272
+ ...Platform.OS !== "web" ? { overflow: "hidden" } : null
273
+ };
274
+ const valueBase = {
275
+ ...selectValueTypography,
276
+ color: colors.slateBlue
277
+ };
278
+ switch (state) {
279
+ case "disabled":
280
+ return {
281
+ outline: defaultOutline,
282
+ container: {
283
+ ...containerBase,
284
+ borderWidth: 1,
285
+ borderColor: colors.stormGray50,
286
+ backgroundColor: colors.stormGray50
287
+ },
288
+ value: { ...valueBase, color: colors.stormGray300 },
289
+ placeholder: colors.stormGray300,
290
+ icon: colors.stormGray150
291
+ };
292
+ case "error":
293
+ return {
294
+ outline: createOutlineStyle(colors.inputOutlineError),
295
+ container: {
296
+ ...containerBase,
297
+ borderWidth: 1,
298
+ borderColor: colors.inputError,
299
+ backgroundColor: colors.white
300
+ },
301
+ value: { ...valueBase, color: colors.inputError },
302
+ placeholder: colors.stormGray200,
303
+ icon: colors.inputError
304
+ };
305
+ case "focused":
306
+ return {
307
+ outline: createOutlineStyle(colors.inputOutlineFocus),
308
+ container: {
309
+ ...containerBase,
310
+ borderWidth: 1,
311
+ borderColor: colors.navy,
312
+ backgroundColor: colors.white
313
+ },
314
+ value: valueBase,
315
+ placeholder: colors.stormGray200,
316
+ icon: colors.navy
317
+ };
318
+ default:
319
+ return {
320
+ outline: defaultOutline,
321
+ container: {
322
+ ...containerBase,
323
+ borderWidth: 1,
324
+ borderColor: colors.stormGray50,
325
+ backgroundColor: colors.white
326
+ },
327
+ value: valueBase,
328
+ placeholder: colors.stormGray200,
329
+ icon: colors.stormGray150
330
+ };
331
+ }
332
+ }
333
+ var selectFieldMetrics = StyleSheet.create({
334
+ container: {
335
+ flexDirection: "row",
336
+ alignItems: "center",
337
+ height: SELECT_HEIGHT,
338
+ minHeight: SELECT_HEIGHT,
339
+ maxHeight: SELECT_HEIGHT,
340
+ borderRadius: radii.lg,
341
+ padding: SELECT_PADDING,
342
+ gap: SELECT_INNER_GAP,
343
+ ...Platform.OS === "web" ? {
344
+ boxSizing: "border-box"
345
+ } : null
346
+ },
347
+ value: {
348
+ flex: 1,
349
+ minWidth: 0,
350
+ ...selectValueTypography,
351
+ paddingVertical: 0,
352
+ paddingHorizontal: 0,
353
+ margin: 0,
354
+ ...Platform.OS === "android" ? { includeFontPadding: false } : null,
355
+ ...Platform.OS === "web" ? {
356
+ outlineStyle: "none"
357
+ } : null
358
+ }
359
+ });
360
+ var selectDropdownMetrics = StyleSheet.create({
361
+ menu: {
362
+ borderRadius: radii.lg,
363
+ borderWidth: 1,
364
+ borderColor: colors.stormGray50,
365
+ backgroundColor: colors.white,
366
+ padding: SELECT_DROPDOWN_PADDING,
367
+ overflow: "hidden"
368
+ },
369
+ option: {
370
+ width: "100%",
371
+ height: SELECT_OPTION_HEIGHT,
372
+ minHeight: SELECT_OPTION_HEIGHT,
373
+ maxHeight: SELECT_OPTION_HEIGHT,
374
+ paddingTop: 12,
375
+ paddingRight: spacing.sm,
376
+ paddingBottom: 12,
377
+ paddingLeft: spacing.sm,
378
+ justifyContent: "center",
379
+ alignItems: "flex-start"
380
+ },
381
+ optionLabel: {
382
+ fontFamily: fonts.sans,
383
+ fontSize: fontSize.md,
384
+ fontWeight: fontWeight.regular,
385
+ lineHeight: fontSize.md,
386
+ letterSpacing: 0,
387
+ textAlign: "left",
388
+ color: colors.slateBlue,
389
+ width: "100%"
390
+ },
391
+ optionLabelSelected: {
392
+ fontWeight: fontWeight.medium,
393
+ color: colors.slateBlue
394
+ },
395
+ optionSelected: {
396
+ opacity: 1,
397
+ borderRadius: radii.sm,
398
+ paddingTop: 12,
399
+ paddingRight: spacing.sm,
400
+ paddingBottom: 12,
401
+ paddingLeft: spacing.sm,
402
+ backgroundColor: colors.countrySelectorSelectedBg
403
+ },
404
+ optionHighlighted: {
405
+ backgroundColor: colors.stormGray0
406
+ }
407
+ });
408
+ function resolveSelectDropdownHeight(optionCount) {
409
+ const contentHeight = optionCount * SELECT_OPTION_HEIGHT + Math.max(0, optionCount - 1) * SELECT_OPTION_GAP + SELECT_DROPDOWN_PADDING * 2;
410
+ return Math.min(contentHeight, SELECT_DROPDOWN_MAX_HEIGHT);
411
+ }
412
+ function resolveSelectDropdownTop(anchor, dropdownHeight) {
413
+ const windowHeight = Dimensions.get("window").height;
414
+ const spaceBelow = windowHeight - (anchor.y + anchor.height + SELECT_DROPDOWN_GAP);
415
+ const spaceAbove = anchor.y - SELECT_DROPDOWN_GAP;
416
+ const topBelow = anchor.y + anchor.height + SELECT_DROPDOWN_GAP;
417
+ const topAbove = anchor.y - SELECT_DROPDOWN_GAP - dropdownHeight;
418
+ if (spaceBelow >= dropdownHeight) {
419
+ return topBelow;
420
+ }
421
+ if (spaceAbove >= dropdownHeight) {
422
+ return topAbove;
423
+ }
424
+ if (spaceAbove > spaceBelow) {
425
+ return Math.max(0, topAbove);
426
+ }
427
+ return Math.max(0, Math.min(topBelow, windowHeight - dropdownHeight));
428
+ }
429
+ var COUNTRY_DROPDOWN_SCROLL_CLASS = "hp-country-dropdown-scroll";
430
+ var SELECT_DROPDOWN_SCROLL_CLASS = "hp-select-dropdown-scroll";
431
+ var STYLE_ID = "hp-dropdown-scroll-styles";
432
+ function createDropdownScrollCss(className) {
433
+ return `
434
+ .${className} {
435
+ scrollbar-width: thin;
436
+ scrollbar-color: ${colors.stormGray300} transparent;
437
+ overflow-y: auto;
438
+ }
439
+
440
+ .${className}::-webkit-scrollbar {
441
+ width: 4px;
442
+ -webkit-appearance: none;
443
+ appearance: none;
444
+ }
445
+
446
+ .${className}::-webkit-scrollbar-corner {
447
+ background: transparent;
448
+ }
449
+
450
+ .${className}::-webkit-scrollbar-button,
451
+ .${className}::-webkit-scrollbar-button:single-button,
452
+ .${className}::-webkit-scrollbar-button:double-button,
453
+ .${className}::-webkit-scrollbar-button:horizontal:decrement,
454
+ .${className}::-webkit-scrollbar-button:horizontal:increment,
455
+ .${className}::-webkit-scrollbar-button:horizontal:start:decrement,
456
+ .${className}::-webkit-scrollbar-button:horizontal:end:increment,
457
+ .${className}::-webkit-scrollbar-button:vertical:decrement,
458
+ .${className}::-webkit-scrollbar-button:vertical:increment,
459
+ .${className}::-webkit-scrollbar-button:vertical:start:decrement,
460
+ .${className}::-webkit-scrollbar-button:vertical:end:increment,
461
+ .${className}::-webkit-scrollbar-button:start:decrement,
462
+ .${className}::-webkit-scrollbar-button:end:increment,
463
+ .${className}::-webkit-scrollbar-button:decrement,
464
+ .${className}::-webkit-scrollbar-button:increment {
465
+ display: none;
466
+ width: 0;
467
+ height: 0;
468
+ max-width: 0;
469
+ max-height: 0;
470
+ min-width: 0;
471
+ min-height: 0;
472
+ padding: 0;
473
+ margin: 0;
474
+ border: 0;
475
+ background: transparent;
476
+ -webkit-appearance: none;
477
+ appearance: none;
478
+ }
479
+
480
+ .${className}::-webkit-scrollbar-track {
481
+ background: transparent;
482
+ }
483
+
484
+ .${className}::-webkit-scrollbar-thumb {
485
+ background-color: ${colors.stormGray300};
486
+ border-radius: 9999px;
487
+ }
488
+ `;
489
+ }
490
+ var dropdownScrollCss = [
491
+ createDropdownScrollCss(COUNTRY_DROPDOWN_SCROLL_CLASS),
492
+ createDropdownScrollCss(SELECT_DROPDOWN_SCROLL_CLASS)
493
+ ].join("\n");
494
+ function ensureDropdownScrollStyles() {
495
+ if (Platform.OS !== "web" || typeof document === "undefined") return;
496
+ if (document.getElementById(STYLE_ID)) return;
497
+ const style = document.createElement("style");
498
+ style.id = STYLE_ID;
499
+ style.textContent = dropdownScrollCss;
500
+ document.head.appendChild(style);
501
+ }
502
+ function ensureCountryDropdownScrollStyles() {
503
+ ensureDropdownScrollStyles();
504
+ }
505
+ function ensureSelectDropdownScrollStyles() {
506
+ ensureDropdownScrollStyles();
507
+ }
508
+
509
+ // src/utils/formatMultiSelectDisplay.ts
510
+ var MULTI_SELECT_SUFFIX = " ... + ";
511
+ var MULTI_SELECT_SUFFIX_UNIT = " items";
512
+ function estimateTextWidth(text, size = fontSize.md) {
513
+ return text.length * size * 0.58;
514
+ }
515
+ function formatMultiSelectDisplay(labels, maxWidth, textSize = fontSize.md) {
516
+ if (labels.length === 0) {
517
+ return "";
518
+ }
519
+ if (labels.length === 1) {
520
+ return labels[0];
521
+ }
522
+ const fits = (text) => estimateTextWidth(text, textSize) <= maxWidth;
523
+ const fullText = labels.join(", ");
524
+ if (fits(fullText)) {
525
+ return fullText;
526
+ }
527
+ for (let visibleCount = labels.length - 1; visibleCount >= 1; visibleCount -= 1) {
528
+ const hiddenCount = labels.length - visibleCount;
529
+ const truncatedText = `${labels.slice(0, visibleCount).join(", ")}${MULTI_SELECT_SUFFIX}${hiddenCount}${MULTI_SELECT_SUFFIX_UNIT}`;
530
+ if (fits(truncatedText)) {
531
+ return truncatedText;
532
+ }
533
+ }
534
+ return `... + ${labels.length}${MULTI_SELECT_SUFFIX_UNIT}`;
535
+ }
536
+ function resolveSelectedLabels(options, selectedValues) {
537
+ if (selectedValues.length === 0) {
538
+ return [];
539
+ }
540
+ const labelByValue = new Map(options.map((option) => [option.value, option.label]));
541
+ return selectedValues.map((value) => labelByValue.get(value)).filter((label) => Boolean(label));
542
+ }
543
+ function renderSelectIcon(icon, color) {
544
+ if (!icon) return null;
545
+ if (isValidElement(icon)) {
546
+ return cloneElement(icon, {
547
+ size: icon.props.size ?? SELECT_ICON_SIZE,
548
+ color: icon.props.color ?? color
549
+ });
550
+ }
551
+ return icon;
552
+ }
553
+ var useIsomorphicLayoutEffect = typeof window === "undefined" ? useEffect : useLayoutEffect;
554
+ function normalizeSelectedValues(multiple, value) {
555
+ if (multiple) {
556
+ if (Array.isArray(value)) {
557
+ return value;
558
+ }
559
+ return value ? [value] : [];
560
+ }
561
+ return typeof value === "string" && value.length > 0 ? [value] : [];
562
+ }
563
+ function Select({
564
+ label,
565
+ placeholder = "placeholder",
566
+ value,
567
+ onValueChange,
568
+ options,
569
+ leftIcon,
570
+ multiple = false,
571
+ disabled = false,
572
+ error,
573
+ invalid,
574
+ hint,
575
+ containerStyle,
576
+ className,
577
+ fieldClassName,
578
+ menuClassName,
579
+ labelClassName,
580
+ errorClassName,
581
+ hintClassName
582
+ }) {
583
+ const wrapperRef = useRef(null);
584
+ const triggerRef = useRef(null);
585
+ const menuRef = useRef(null);
586
+ const scrollRef = useRef(null);
587
+ const helperRef = useRef(null);
588
+ const chevronRotation = useRef(new Animated.Value(0)).current;
589
+ const [open, setOpen] = useState(false);
590
+ const [anchor, setAnchor] = useState(null);
591
+ const [highlightedIndex, setHighlightedIndex] = useState(-1);
592
+ const [valueContainerWidth, setValueContainerWidth] = useState(0);
593
+ useApplyWebClassName(wrapperRef, className);
594
+ useApplyWebClassName(triggerRef, fieldClassName);
595
+ useApplyWebClassName(menuRef, menuClassName);
596
+ useApplyWebClassName(scrollRef, SELECT_DROPDOWN_SCROLL_CLASS, open && Boolean(anchor));
597
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
598
+ useIsomorphicLayoutEffect(() => {
599
+ ensureSelectDropdownScrollStyles();
600
+ }, []);
601
+ useEffect(() => {
602
+ Animated.timing(chevronRotation, {
603
+ toValue: open ? 1 : 0,
604
+ duration: SELECT_CHEVRON_ROTATION_MS,
605
+ easing: Easing.out(Easing.ease),
606
+ useNativeDriver: true
607
+ }).start();
608
+ }, [chevronRotation, open]);
609
+ const chevronRotate = chevronRotation.interpolate({
610
+ inputRange: [0, 1],
611
+ outputRange: ["0deg", "180deg"]
612
+ });
613
+ const hasError = Boolean(error) || Boolean(invalid);
614
+ const visualState = resolveInputVisualState({
615
+ focused: open,
616
+ error: hasError,
617
+ disabled
618
+ });
619
+ const fieldStyles = getSelectFieldStyles(visualState);
620
+ const selectedValues = useMemo(
621
+ () => normalizeSelectedValues(multiple, value),
622
+ [multiple, value]
623
+ );
624
+ const selectedValueSet = useMemo(() => new Set(selectedValues), [selectedValues]);
625
+ const selectedLabels = useMemo(
626
+ () => resolveSelectedLabels(options, selectedValues),
627
+ [options, selectedValues]
628
+ );
629
+ const selectableOptions = useMemo(
630
+ () => options.filter((option) => !option.disabled),
631
+ [options]
632
+ );
633
+ const selectableIndexByValue = useMemo(
634
+ () => new Map(
635
+ selectableOptions.map((option, index) => [option.value, index])
636
+ ),
637
+ [selectableOptions]
638
+ );
639
+ const displayLabel = useMemo(() => {
640
+ if (selectedLabels.length === 0) {
641
+ return placeholder;
642
+ }
643
+ if (!multiple) {
644
+ return selectedLabels[0];
645
+ }
646
+ if (valueContainerWidth <= 0) {
647
+ return selectedLabels.join(", ");
648
+ }
649
+ return formatMultiSelectDisplay(selectedLabels, valueContainerWidth);
650
+ }, [multiple, placeholder, selectedLabels, valueContainerWidth]);
651
+ const isPlaceholder = selectedLabels.length === 0;
652
+ const dropdownHeight = resolveSelectDropdownHeight(options.length);
653
+ const helperMessage = error ?? hint;
654
+ function closeMenu() {
655
+ setOpen(false);
656
+ setAnchor(null);
657
+ setHighlightedIndex(-1);
658
+ }
659
+ function openMenu() {
660
+ if (disabled || selectableOptions.length === 0) {
661
+ return;
662
+ }
663
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
664
+ const selectedIndex = selectableOptions.findIndex(
665
+ (option) => selectedValueSet.has(option.value)
666
+ );
667
+ setHighlightedIndex(selectedIndex >= 0 ? selectedIndex : 0);
668
+ setAnchor({ x, y, width, height });
669
+ setOpen(true);
670
+ });
671
+ }
672
+ function handleSelect(nextValue) {
673
+ if (multiple) {
674
+ const nextValues = selectedValues.includes(nextValue) ? selectedValues.filter((item) => item !== nextValue) : [...selectedValues, nextValue];
675
+ onValueChange?.(nextValues);
676
+ return;
677
+ }
678
+ onValueChange?.(nextValue);
679
+ closeMenu();
680
+ }
681
+ const optionList = options.map((option, index) => {
682
+ const selectableIndex = selectableIndexByValue.get(option.value) ?? -1;
683
+ const isSelected = selectedValueSet.has(option.value);
684
+ const isHighlighted = selectableIndex === highlightedIndex;
685
+ const isLast = index === options.length - 1;
686
+ return /* @__PURE__ */ jsx(
687
+ Pressable,
688
+ {
689
+ accessibilityRole: "button",
690
+ accessibilityState: { disabled: option.disabled, selected: isSelected },
691
+ disabled: option.disabled,
692
+ onPress: () => {
693
+ if (!option.disabled) {
694
+ handleSelect(option.value);
695
+ }
696
+ },
697
+ onHoverIn: () => {
698
+ if (!option.disabled && selectableIndex >= 0) {
699
+ setHighlightedIndex(selectableIndex);
700
+ }
701
+ },
702
+ style: [
703
+ selectDropdownMetrics.option,
704
+ isSelected && selectDropdownMetrics.optionSelected,
705
+ isHighlighted && !isSelected && !option.disabled ? selectDropdownMetrics.optionHighlighted : null,
706
+ !isLast && styles2.optionSpacing,
707
+ option.disabled && styles2.optionDisabled
708
+ ],
709
+ children: /* @__PURE__ */ jsx(
710
+ Text,
711
+ {
712
+ style: [
713
+ selectDropdownMetrics.optionLabel,
714
+ isSelected && selectDropdownMetrics.optionLabelSelected,
715
+ option.disabled && styles2.optionLabelDisabled
716
+ ],
717
+ numberOfLines: 1,
718
+ children: option.label
719
+ }
720
+ )
721
+ },
722
+ option.value
723
+ );
724
+ });
725
+ const dropdownTop = anchor ? resolveSelectDropdownTop(anchor, dropdownHeight) : 0;
726
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles2.wrapper, containerStyle], children: [
727
+ label ? /* @__PURE__ */ jsx(Label, { disabled, style: styles2.label, className: labelClassName, children: label }) : null,
728
+ /* @__PURE__ */ jsx(View, { style: fieldStyles.outline, children: /* @__PURE__ */ jsxs(
729
+ Pressable,
730
+ {
731
+ ref: triggerRef,
732
+ accessibilityRole: "button",
733
+ accessibilityState: { disabled, expanded: open },
734
+ disabled,
735
+ onPress: open ? closeMenu : openMenu,
736
+ style: [selectFieldMetrics.container, fieldStyles.container],
737
+ children: [
738
+ leftIcon ? /* @__PURE__ */ jsx(View, { style: styles2.iconSlot, children: renderSelectIcon(leftIcon, fieldStyles.icon) }) : null,
739
+ /* @__PURE__ */ jsx(
740
+ View,
741
+ {
742
+ style: styles2.valueContainer,
743
+ onLayout: (event) => {
744
+ setValueContainerWidth(event.nativeEvent.layout.width);
745
+ },
746
+ children: /* @__PURE__ */ jsx(
747
+ Text,
748
+ {
749
+ style: [
750
+ selectFieldMetrics.value,
751
+ fieldStyles.value,
752
+ isPlaceholder && { color: fieldStyles.placeholder }
753
+ ],
754
+ numberOfLines: 1,
755
+ children: displayLabel
756
+ }
757
+ )
758
+ }
759
+ ),
760
+ /* @__PURE__ */ jsx(
761
+ Animated.View,
762
+ {
763
+ style: [styles2.iconSlot, { transform: [{ rotate: chevronRotate }] }],
764
+ children: /* @__PURE__ */ jsx(
765
+ ChevronDownIcon,
766
+ {
767
+ size: SELECT_CHEVRON_SIZE,
768
+ color: disabled ? colors.stormGray200 : SELECT_CHEVRON_COLOR
769
+ }
770
+ )
771
+ }
772
+ )
773
+ ]
774
+ }
775
+ ) }),
776
+ helperMessage ? /* @__PURE__ */ jsx(Text, { ref: helperRef, style: error ? styles2.error : styles2.hint, children: helperMessage }) : null,
777
+ /* @__PURE__ */ jsx(Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: closeMenu, children: /* @__PURE__ */ jsx(Pressable, { style: styles2.overlay, onPress: closeMenu, children: anchor ? /* @__PURE__ */ jsx(
778
+ View,
779
+ {
780
+ ref: menuRef,
781
+ style: [
782
+ selectDropdownMetrics.menu,
783
+ styles2.dropdown,
784
+ {
785
+ top: dropdownTop,
786
+ left: anchor.x,
787
+ width: anchor.width,
788
+ height: dropdownHeight
789
+ }
790
+ ],
791
+ children: /* @__PURE__ */ jsx(
792
+ ScrollView,
793
+ {
794
+ ref: scrollRef,
795
+ style: styles2.dropdownScroll,
796
+ contentContainerStyle: styles2.dropdownContent,
797
+ keyboardShouldPersistTaps: "handled",
798
+ showsVerticalScrollIndicator: true,
799
+ bounces: false,
800
+ nestedScrollEnabled: true,
801
+ children: optionList
802
+ }
803
+ )
804
+ }
805
+ ) : null }) })
806
+ ] });
807
+ }
808
+ var styles2 = StyleSheet.create({
809
+ wrapper: {
810
+ width: "100%",
811
+ gap: SELECT_LABEL_GAP
812
+ },
813
+ label: {
814
+ ...selectLabelTypography
815
+ },
816
+ iconSlot: {
817
+ width: SELECT_ICON_SIZE,
818
+ height: SELECT_ICON_SIZE,
819
+ alignItems: "center",
820
+ justifyContent: "center",
821
+ flexShrink: 0
822
+ },
823
+ valueContainer: {
824
+ flex: 1,
825
+ minWidth: 0,
826
+ justifyContent: "center"
827
+ },
828
+ overlay: {
829
+ flex: 1,
830
+ backgroundColor: colors.transparent
831
+ },
832
+ dropdown: {
833
+ position: "absolute"
834
+ },
835
+ dropdownScroll: {
836
+ flex: 1
837
+ },
838
+ dropdownContent: {
839
+ flexGrow: 1
840
+ },
841
+ optionSpacing: {
842
+ marginBottom: SELECT_OPTION_GAP
843
+ },
844
+ optionDisabled: {
845
+ opacity: 0.5
846
+ },
847
+ optionLabelDisabled: {
848
+ color: colors.stormGray300
849
+ },
850
+ error: {
851
+ fontSize: 12,
852
+ lineHeight: 12,
853
+ color: colors.inputError
854
+ },
855
+ hint: {
856
+ fontSize: 12,
857
+ lineHeight: 12,
858
+ color: colors.stormGray300
859
+ }
860
+ });
861
+
197
862
  // src/data/countries.ts
198
863
  var defaultCountry = {
199
864
  code: "AM",
@@ -286,25 +951,6 @@ function findCountry(code) {
286
951
  return countries.find((country) => country.code === code) ?? defaultCountry;
287
952
  }
288
953
 
289
- // src/icons/chevronDownPath.ts
290
- var CHEVRON_DOWN_PATH = "M4 6L8 10L12 6";
291
- function ChevronDownIcon({
292
- size = 16,
293
- color = "#dadde0",
294
- strokeWidth = 2
295
- }) {
296
- return /* @__PURE__ */ jsx(Svg, { width: size, height: size, viewBox: "0 0 16 16", fill: "none", children: /* @__PURE__ */ jsx(
297
- Path,
298
- {
299
- d: CHEVRON_DOWN_PATH,
300
- stroke: color,
301
- strokeWidth,
302
- strokeLinecap: "round",
303
- strokeLinejoin: "round"
304
- }
305
- ) });
306
- }
307
-
308
954
  // src/utils/countryFlag.ts
309
955
  function countryCodeToFlagEmoji(code) {
310
956
  const upper = code.trim().toUpperCase();
@@ -313,51 +959,6 @@ function countryCodeToFlagEmoji(code) {
313
959
  ...upper.split("").map((char) => 127462 - 65 + char.charCodeAt(0))
314
960
  );
315
961
  }
316
- var COUNTRY_DROPDOWN_SCROLL_CLASS = "hp-country-dropdown-scroll";
317
- var STYLE_ID = "hp-country-dropdown-scroll-styles";
318
- var countryDropdownScrollCss = `
319
- .${COUNTRY_DROPDOWN_SCROLL_CLASS} {
320
- scrollbar-width: thin;
321
- scrollbar-color: ${colors.stormGray300} transparent;
322
- overflow-y: auto;
323
- }
324
-
325
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar {
326
- width: 4px;
327
- }
328
-
329
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-corner {
330
- background: transparent;
331
- }
332
-
333
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button,
334
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:single-button,
335
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:vertical:start:decrement,
336
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-button:vertical:end:increment {
337
- display: none;
338
- width: 0;
339
- height: 0;
340
- -webkit-appearance: none;
341
- appearance: none;
342
- }
343
-
344
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-track {
345
- background: transparent;
346
- }
347
-
348
- .${COUNTRY_DROPDOWN_SCROLL_CLASS}::-webkit-scrollbar-thumb {
349
- background-color: ${colors.stormGray300};
350
- border-radius: 9999px;
351
- }
352
- `;
353
- function ensureCountryDropdownScrollStyles() {
354
- if (Platform.OS !== "web" || typeof document === "undefined") return;
355
- if (document.getElementById(STYLE_ID)) return;
356
- const style = document.createElement("style");
357
- style.id = STYLE_ID;
358
- style.textContent = countryDropdownScrollCss;
359
- document.head.appendChild(style);
360
- }
361
962
  var DROPDOWN_GAP = 10;
362
963
  var DROPDOWN_HEIGHT = 186;
363
964
  var DROPDOWN_PADDING = 8;
@@ -423,13 +1024,13 @@ function CountryCodeSelector({
423
1024
  accessibilityRole: "button",
424
1025
  onPress: () => handleSelect(item.code),
425
1026
  style: [
426
- styles2.option,
427
- isSelected && styles2.optionSelected,
428
- !isLast && styles2.optionSpacing
1027
+ styles3.option,
1028
+ isSelected && styles3.optionSelected,
1029
+ !isLast && styles3.optionSpacing
429
1030
  ],
430
1031
  children: [
431
- /* @__PURE__ */ jsx(Text, { style: styles2.flag, children: countryCodeToFlagEmoji(item.code) }),
432
- /* @__PURE__ */ jsx(Text, { style: styles2.optionDialCode, children: item.dialCode })
1032
+ /* @__PURE__ */ jsx(Text, { style: styles3.flag, children: countryCodeToFlagEmoji(item.code) }),
1033
+ /* @__PURE__ */ jsx(Text, { style: styles3.optionDialCode, children: item.dialCode })
433
1034
  ]
434
1035
  },
435
1036
  item.code
@@ -439,8 +1040,8 @@ function CountryCodeSelector({
439
1040
  ScrollView,
440
1041
  {
441
1042
  ref: scrollRef,
442
- style: styles2.dropdownScroll,
443
- contentContainerStyle: styles2.dropdownContent,
1043
+ style: styles3.dropdownScroll,
1044
+ contentContainerStyle: styles3.dropdownContent,
444
1045
  keyboardShouldPersistTaps: "handled",
445
1046
  showsVerticalScrollIndicator: true,
446
1047
  bounces: false,
@@ -448,7 +1049,7 @@ function CountryCodeSelector({
448
1049
  children: optionList
449
1050
  }
450
1051
  );
451
- return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles2.root, style], children: [
1052
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles3.root, style], children: [
452
1053
  /* @__PURE__ */ jsxs(
453
1054
  Pressable,
454
1055
  {
@@ -457,13 +1058,13 @@ function CountryCodeSelector({
457
1058
  disabled,
458
1059
  onPress: handleOpen,
459
1060
  style: [
460
- styles2.trigger,
461
- disabled ? styles2.triggerDisabled : styles2.triggerEnabled,
462
- Platform.OS === "web" ? styles2.triggerWeb : null
1061
+ styles3.trigger,
1062
+ disabled ? styles3.triggerDisabled : styles3.triggerEnabled,
1063
+ Platform.OS === "web" ? styles3.triggerWeb : null
463
1064
  ],
464
1065
  children: [
465
- /* @__PURE__ */ jsx(Text, { style: styles2.flag, children: countryCodeToFlagEmoji(selected.code) }),
466
- /* @__PURE__ */ jsx(Text, { style: [styles2.dialCode, { color: textColor }], children: selected.dialCode }),
1066
+ /* @__PURE__ */ jsx(Text, { style: styles3.flag, children: countryCodeToFlagEmoji(selected.code) }),
1067
+ /* @__PURE__ */ jsx(Text, { style: [styles3.dialCode, { color: textColor }], children: selected.dialCode }),
467
1068
  /* @__PURE__ */ jsx(ChevronDownIcon, { size: CHEVRON_SIZE, color: colors.stormGray100 })
468
1069
  ]
469
1070
  }
@@ -475,11 +1076,11 @@ function CountryCodeSelector({
475
1076
  transparent: true,
476
1077
  animationType: "fade",
477
1078
  onRequestClose: closeDropdown,
478
- children: /* @__PURE__ */ jsx(Pressable, { style: styles2.overlay, onPress: closeDropdown, children: anchor ? /* @__PURE__ */ jsx(
1079
+ children: /* @__PURE__ */ jsx(Pressable, { style: styles3.overlay, onPress: closeDropdown, children: anchor ? /* @__PURE__ */ jsx(
479
1080
  View,
480
1081
  {
481
1082
  style: [
482
- styles2.dropdown,
1083
+ styles3.dropdown,
483
1084
  {
484
1085
  top: dropdownTop,
485
1086
  left: anchor.x,
@@ -493,7 +1094,7 @@ function CountryCodeSelector({
493
1094
  )
494
1095
  ] });
495
1096
  }
496
- var styles2 = StyleSheet.create({
1097
+ var styles3 = StyleSheet.create({
497
1098
  root: {
498
1099
  alignSelf: "flex-start",
499
1100
  flexShrink: 0
@@ -614,26 +1215,26 @@ function PhoneInput({
614
1215
  onBlur?.(event);
615
1216
  }
616
1217
  const helperMessage = error ?? hint;
617
- return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles3.wrapper, containerStyle], children: [
1218
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles4.wrapper, containerStyle], children: [
618
1219
  label ? /* @__PURE__ */ jsx(Label, { disabled: isDisabled, className: labelClassName, children: label }) : null,
619
- /* @__PURE__ */ jsxs(View, { style: styles3.row, children: [
1220
+ /* @__PURE__ */ jsxs(View, { style: styles4.row, children: [
620
1221
  /* @__PURE__ */ jsx(
621
1222
  CountryCodeSelector,
622
1223
  {
623
1224
  value: countryCode,
624
1225
  onValueChange: onCountryCodeChange,
625
1226
  disabled: isDisabled,
626
- style: styles3.countrySelector
1227
+ style: styles4.countrySelector
627
1228
  }
628
1229
  ),
629
- /* @__PURE__ */ jsxs(View, { style: styles3.phoneColumn, children: [
630
- /* @__PURE__ */ jsx(View, { style: [phoneFieldStyles.outline, styles3.phoneOutline], children: /* @__PURE__ */ jsx(
1230
+ /* @__PURE__ */ jsxs(View, { style: styles4.phoneColumn, children: [
1231
+ /* @__PURE__ */ jsx(View, { style: [phoneFieldStyles.outline, styles4.phoneOutline], children: /* @__PURE__ */ jsx(
631
1232
  View,
632
1233
  {
633
1234
  style: [
634
1235
  inputFieldMetrics.container,
635
1236
  phoneFieldStyles.container,
636
- styles3.phoneField
1237
+ styles4.phoneField
637
1238
  ],
638
1239
  children: /* @__PURE__ */ jsx(
639
1240
  TextInput,
@@ -655,12 +1256,12 @@ function PhoneInput({
655
1256
  )
656
1257
  }
657
1258
  ) }),
658
- helperMessage ? /* @__PURE__ */ jsx(Text, { ref: helperRef, style: error ? styles3.error : styles3.hint, children: helperMessage }) : null
1259
+ helperMessage ? /* @__PURE__ */ jsx(Text, { ref: helperRef, style: error ? styles4.error : styles4.hint, children: helperMessage }) : null
659
1260
  ] })
660
1261
  ] })
661
1262
  ] });
662
1263
  }
663
- var styles3 = StyleSheet.create({
1264
+ var styles4 = StyleSheet.create({
664
1265
  wrapper: {
665
1266
  width: "100%",
666
1267
  gap: spacing.sm
@@ -696,6 +1297,1287 @@ var styles3 = StyleSheet.create({
696
1297
  }
697
1298
  });
698
1299
 
699
- export { Button, CountryCodeSelector, PhoneInput, countries, defaultCountry, findCountry };
1300
+ // src/icons/chevronNavPaths.ts
1301
+ var CHEVRON_LEFT_PATH = "M12.5 15L7.5 10L12.5 5";
1302
+ var CHEVRON_RIGHT_PATH = "M7.5 15L12.5 10L7.5 5";
1303
+ function ChevronLeftIcon({
1304
+ size = 20,
1305
+ color = "#151a1e",
1306
+ strokeWidth = 2
1307
+ }) {
1308
+ return /* @__PURE__ */ jsx(Svg3, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
1309
+ Path,
1310
+ {
1311
+ d: CHEVRON_LEFT_PATH,
1312
+ stroke: color,
1313
+ strokeWidth,
1314
+ strokeLinecap: "round",
1315
+ strokeLinejoin: "round"
1316
+ }
1317
+ ) });
1318
+ }
1319
+ function ChevronRightIcon({
1320
+ size = 20,
1321
+ color = "#151a1e",
1322
+ strokeWidth = 2
1323
+ }) {
1324
+ return /* @__PURE__ */ jsx(Svg3, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
1325
+ Path,
1326
+ {
1327
+ d: CHEVRON_RIGHT_PATH,
1328
+ stroke: color,
1329
+ strokeWidth,
1330
+ strokeLinecap: "round",
1331
+ strokeLinejoin: "round"
1332
+ }
1333
+ ) });
1334
+ }
1335
+ var CALENDAR_DROPDOWN_GAP = spacing.sm;
1336
+ var CALENDAR_PANEL_WIDTH = 296;
1337
+ var CALENDAR_PANEL_PADDING = spacing.md;
1338
+ var CALENDAR_PANEL_GAP = spacing.md;
1339
+ var CALENDAR_CONTENT_WIDTH = CALENDAR_PANEL_WIDTH - CALENDAR_PANEL_PADDING * 2;
1340
+ var CALENDAR_HEADER_HEIGHT = 20;
1341
+ var CALENDAR_WEEKDAY_CELL_SIZE = 32;
1342
+ var CALENDAR_WEEKDAY_GAP = spacing.sm;
1343
+ var CALENDAR_WEEKDAY_RADIUS = 6;
1344
+ var CALENDAR_DAY_SIZE = CALENDAR_WEEKDAY_CELL_SIZE;
1345
+ var CALENDAR_DAY_GRID_WIDTH = CALENDAR_CONTENT_WIDTH;
1346
+ var CALENDAR_DAY_GAP_X = spacing.sm;
1347
+ var CALENDAR_DAY_GAP_Y = spacing.lg;
1348
+ var CALENDAR_DAY_ROWS = 6;
1349
+ var CALENDAR_DAY_GRID_HEIGHT = CALENDAR_DAY_SIZE * CALENDAR_DAY_ROWS + CALENDAR_DAY_GAP_Y * (CALENDAR_DAY_ROWS - 1);
1350
+ var CALENDAR_PICKER_COLUMNS = 3;
1351
+ var CALENDAR_YEARS_PER_PAGE = 12;
1352
+ var CALENDAR_PICKER_CELL_WIDTH = (CALENDAR_DAY_GRID_WIDTH - CALENDAR_DAY_GAP_X * (CALENDAR_PICKER_COLUMNS - 1)) / CALENDAR_PICKER_COLUMNS;
1353
+ var CALENDAR_PICKER_CELL_HEIGHT = 36;
1354
+ var CALENDAR_PICKER_BODY_HEIGHT = CALENDAR_WEEKDAY_CELL_SIZE + CALENDAR_WEEKDAY_GAP + CALENDAR_DAY_GRID_HEIGHT;
1355
+ var CALENDAR_DAY_DOT_SIZE = 3;
1356
+ var CALENDAR_TODAY_TEXT_COLOR = "#082640";
1357
+ var CALENDAR_TODAY_DOT_COLOR = "#0033A0";
1358
+ var CALENDAR_NAV_ICON_SIZE = 20;
1359
+ var CALENDAR_NAV_ICON_COLOR = colors.stormGray850;
1360
+ var CALENDAR_FIELD_ICON_SIZE = 20;
1361
+ var CALENDAR_FIELD_WIDTH = CALENDAR_PANEL_WIDTH;
1362
+ var CALENDAR_FIELD_HEIGHT = 52;
1363
+ var CALENDAR_FIELD_PADDING = spacing.lg;
1364
+ var CALENDAR_FIELD_GAP = spacing.sm;
1365
+ var CALENDAR_FIELD_PLACEHOLDER_COLOR = colors.stormGray200;
1366
+ var CALENDAR_PANEL_TOTAL_HEIGHT = CALENDAR_PANEL_PADDING * 2 + CALENDAR_HEADER_HEIGHT + CALENDAR_PANEL_GAP * 2 + CALENDAR_WEEKDAY_CELL_SIZE + CALENDAR_DAY_GRID_HEIGHT;
1367
+ var CALENDAR_PANEL_HEIGHT = CALENDAR_PANEL_TOTAL_HEIGHT;
1368
+ var calendarLabelTypography = {
1369
+ fontFamily: fonts.sans,
1370
+ fontSize: fontSize.sm,
1371
+ fontWeight: fontWeight.medium,
1372
+ lineHeight: fontSize.sm,
1373
+ letterSpacing: 0,
1374
+ color: colors.slateBlue
1375
+ };
1376
+ var calendarFieldTypography = {
1377
+ fontFamily: fonts.sans,
1378
+ fontSize: fontSize.md,
1379
+ fontWeight: fontWeight.regular,
1380
+ lineHeight: fontSize.md,
1381
+ letterSpacing: 0,
1382
+ textAlign: "left"
1383
+ };
1384
+ var calendarFieldPlaceholderTypography = {
1385
+ ...calendarFieldTypography,
1386
+ color: CALENDAR_FIELD_PLACEHOLDER_COLOR
1387
+ };
1388
+ var calendarDropdownMetrics = StyleSheet.create({
1389
+ panel: {
1390
+ width: CALENDAR_PANEL_WIDTH,
1391
+ height: CALENDAR_PANEL_HEIGHT,
1392
+ borderRadius: radii.lg,
1393
+ borderWidth: 1,
1394
+ borderColor: colors.stormGray50,
1395
+ backgroundColor: colors.white,
1396
+ padding: CALENDAR_PANEL_PADDING,
1397
+ gap: CALENDAR_PANEL_GAP,
1398
+ overflow: "hidden",
1399
+ flexDirection: "column",
1400
+ opacity: 1,
1401
+ ...Platform.OS === "web" ? {
1402
+ boxSizing: "border-box"
1403
+ } : null
1404
+ },
1405
+ header: {
1406
+ flexDirection: "row",
1407
+ alignItems: "center",
1408
+ justifyContent: "space-between",
1409
+ height: CALENDAR_HEADER_HEIGHT,
1410
+ minHeight: CALENDAR_HEADER_HEIGHT,
1411
+ maxHeight: CALENDAR_HEADER_HEIGHT
1412
+ },
1413
+ headerTitle: {
1414
+ textAlign: "center",
1415
+ fontFamily: fonts.sans,
1416
+ fontSize: fontSize.md,
1417
+ fontWeight: fontWeight.bold,
1418
+ lineHeight: 18,
1419
+ letterSpacing: 0,
1420
+ color: colors.stormGray850
1421
+ },
1422
+ headerTitlePressable: {
1423
+ flex: 1,
1424
+ alignItems: "center",
1425
+ justifyContent: "center",
1426
+ minHeight: CALENDAR_HEADER_HEIGHT
1427
+ },
1428
+ navButton: {
1429
+ width: CALENDAR_NAV_ICON_SIZE,
1430
+ height: CALENDAR_NAV_ICON_SIZE,
1431
+ alignItems: "center",
1432
+ justifyContent: "center"
1433
+ },
1434
+ weekdayRow: {
1435
+ flexDirection: "row",
1436
+ gap: CALENDAR_WEEKDAY_GAP,
1437
+ height: CALENDAR_WEEKDAY_CELL_SIZE,
1438
+ minHeight: CALENDAR_WEEKDAY_CELL_SIZE,
1439
+ maxHeight: CALENDAR_WEEKDAY_CELL_SIZE,
1440
+ opacity: 1
1441
+ },
1442
+ weekdayCell: {
1443
+ width: CALENDAR_WEEKDAY_CELL_SIZE,
1444
+ height: CALENDAR_WEEKDAY_CELL_SIZE,
1445
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
1446
+ padding: spacing.xs,
1447
+ backgroundColor: colors.stormGray0,
1448
+ alignItems: "center",
1449
+ justifyContent: "center",
1450
+ opacity: 1,
1451
+ ...Platform.OS === "web" ? {
1452
+ boxSizing: "border-box"
1453
+ } : null
1454
+ },
1455
+ weekdayLabel: {
1456
+ fontFamily: fonts.sans,
1457
+ fontSize: fontSize.sm,
1458
+ fontWeight: fontWeight.regular,
1459
+ lineHeight: fontSize.sm,
1460
+ letterSpacing: 0,
1461
+ textAlign: "center",
1462
+ color: colors.stormGray300,
1463
+ textTransform: "uppercase"
1464
+ },
1465
+ dayGrid: {
1466
+ width: CALENDAR_DAY_GRID_WIDTH,
1467
+ height: CALENDAR_DAY_GRID_HEIGHT,
1468
+ flexDirection: "row",
1469
+ flexWrap: "wrap",
1470
+ columnGap: CALENDAR_DAY_GAP_X,
1471
+ rowGap: CALENDAR_DAY_GAP_Y,
1472
+ alignContent: "flex-start",
1473
+ opacity: 1
1474
+ },
1475
+ dayCell: {
1476
+ width: CALENDAR_DAY_SIZE,
1477
+ height: CALENDAR_DAY_SIZE,
1478
+ minHeight: CALENDAR_DAY_SIZE,
1479
+ maxHeight: CALENDAR_DAY_SIZE,
1480
+ alignItems: "center",
1481
+ justifyContent: "center",
1482
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
1483
+ padding: spacing.xs,
1484
+ backgroundColor: colors.white,
1485
+ opacity: 1,
1486
+ position: "relative",
1487
+ ...Platform.OS === "web" ? {
1488
+ boxSizing: "border-box"
1489
+ } : null
1490
+ },
1491
+ dayCellPast: {
1492
+ backgroundColor: colors.stormGray50
1493
+ },
1494
+ dayCellSelected: {
1495
+ backgroundColor: colors.navy
1496
+ },
1497
+ dayLabel: {
1498
+ fontFamily: fonts.sans,
1499
+ fontSize: fontSize.md,
1500
+ fontWeight: fontWeight.regular,
1501
+ lineHeight: 18,
1502
+ letterSpacing: 0,
1503
+ textAlign: "center",
1504
+ color: colors.navy,
1505
+ includeFontPadding: false,
1506
+ textAlignVertical: "center"
1507
+ },
1508
+ dayLabelToday: {
1509
+ color: CALENDAR_TODAY_TEXT_COLOR
1510
+ },
1511
+ dayLabelSelected: {
1512
+ fontWeight: fontWeight.semibold,
1513
+ color: colors.white
1514
+ },
1515
+ dayLabelFuture: {
1516
+ color: colors.navy
1517
+ },
1518
+ dayLabelMuted: {
1519
+ color: colors.stormGray300
1520
+ },
1521
+ dayLabelOutsideMonth: {
1522
+ color: colors.stormGray300
1523
+ },
1524
+ dayLabelDisabled: {
1525
+ color: colors.stormGray300,
1526
+ opacity: 0.5
1527
+ },
1528
+ todayDot: {
1529
+ position: "absolute",
1530
+ bottom: 5,
1531
+ left: "50%",
1532
+ width: CALENDAR_DAY_DOT_SIZE,
1533
+ height: CALENDAR_DAY_DOT_SIZE,
1534
+ borderRadius: 15,
1535
+ backgroundColor: CALENDAR_TODAY_DOT_COLOR,
1536
+ marginLeft: -1.5,
1537
+ zIndex: 1
1538
+ },
1539
+ pickerBody: {
1540
+ width: CALENDAR_DAY_GRID_WIDTH,
1541
+ height: CALENDAR_PICKER_BODY_HEIGHT,
1542
+ justifyContent: "center"
1543
+ },
1544
+ pickerGrid: {
1545
+ width: CALENDAR_DAY_GRID_WIDTH,
1546
+ flexDirection: "row",
1547
+ flexWrap: "wrap",
1548
+ columnGap: CALENDAR_DAY_GAP_X,
1549
+ rowGap: CALENDAR_DAY_GAP_Y,
1550
+ alignContent: "flex-start"
1551
+ },
1552
+ pickerCell: {
1553
+ width: CALENDAR_PICKER_CELL_WIDTH,
1554
+ minHeight: CALENDAR_PICKER_CELL_HEIGHT,
1555
+ alignItems: "center",
1556
+ justifyContent: "center",
1557
+ borderRadius: CALENDAR_WEEKDAY_RADIUS,
1558
+ paddingHorizontal: spacing.xs,
1559
+ paddingVertical: spacing.xs,
1560
+ backgroundColor: colors.white,
1561
+ ...Platform.OS === "web" ? {
1562
+ boxSizing: "border-box"
1563
+ } : null
1564
+ },
1565
+ pickerCellSelected: {
1566
+ backgroundColor: colors.navy
1567
+ },
1568
+ pickerLabel: {
1569
+ fontFamily: fonts.sans,
1570
+ fontSize: fontSize.md,
1571
+ fontWeight: fontWeight.regular,
1572
+ lineHeight: 18,
1573
+ letterSpacing: 0,
1574
+ textAlign: "center",
1575
+ color: colors.navy,
1576
+ includeFontPadding: false,
1577
+ ...Platform.OS === "android" ? { textAlignVertical: "center" } : null
1578
+ },
1579
+ pickerLabelSelected: {
1580
+ fontWeight: fontWeight.semibold,
1581
+ color: colors.white
1582
+ },
1583
+ pickerLabelDisabled: {
1584
+ color: colors.stormGray300,
1585
+ opacity: 0.5
1586
+ },
1587
+ pickerLabelCurrent: {
1588
+ color: CALENDAR_TODAY_TEXT_COLOR
1589
+ }
1590
+ });
1591
+ function resolveCalendarDropdownTop(anchor, panelHeight = CALENDAR_PANEL_HEIGHT) {
1592
+ const windowHeight = Dimensions.get("window").height;
1593
+ const spaceBelow = windowHeight - (anchor.y + anchor.height + CALENDAR_DROPDOWN_GAP);
1594
+ const spaceAbove = anchor.y - CALENDAR_DROPDOWN_GAP;
1595
+ const topBelow = anchor.y + anchor.height + CALENDAR_DROPDOWN_GAP;
1596
+ const topAbove = anchor.y - CALENDAR_DROPDOWN_GAP - panelHeight;
1597
+ if (spaceBelow >= panelHeight) {
1598
+ return topBelow;
1599
+ }
1600
+ if (spaceAbove >= panelHeight) {
1601
+ return topAbove;
1602
+ }
1603
+ if (spaceAbove > spaceBelow) {
1604
+ return Math.max(0, topAbove);
1605
+ }
1606
+ return Math.max(0, Math.min(topBelow, windowHeight - panelHeight));
1607
+ }
1608
+ function resolveCalendarDropdownLeft(anchor, panelWidth = CALENDAR_PANEL_WIDTH) {
1609
+ const windowWidth = Dimensions.get("window").width;
1610
+ const maxLeft = Math.max(0, windowWidth - panelWidth);
1611
+ return Math.max(0, Math.min(anchor.x, maxLeft));
1612
+ }
1613
+ var calendarFieldMetrics = StyleSheet.create({
1614
+ container: {
1615
+ flexDirection: "row",
1616
+ alignItems: "center",
1617
+ width: CALENDAR_FIELD_WIDTH,
1618
+ minWidth: CALENDAR_FIELD_WIDTH,
1619
+ maxWidth: CALENDAR_FIELD_WIDTH,
1620
+ height: CALENDAR_FIELD_HEIGHT,
1621
+ minHeight: CALENDAR_FIELD_HEIGHT,
1622
+ maxHeight: CALENDAR_FIELD_HEIGHT,
1623
+ borderRadius: radii.lg,
1624
+ padding: CALENDAR_FIELD_PADDING,
1625
+ gap: CALENDAR_FIELD_GAP,
1626
+ opacity: 1,
1627
+ ...Platform.OS === "web" ? {
1628
+ boxSizing: "border-box"
1629
+ } : null
1630
+ },
1631
+ value: {
1632
+ flex: 1,
1633
+ minWidth: 0,
1634
+ ...calendarFieldTypography,
1635
+ paddingVertical: 0,
1636
+ paddingHorizontal: 0,
1637
+ margin: 0,
1638
+ ...Platform.OS === "android" ? { includeFontPadding: false } : null,
1639
+ ...Platform.OS === "web" ? {
1640
+ outlineStyle: "none"
1641
+ } : null
1642
+ }
1643
+ });
1644
+
1645
+ // src/utils/calendarDays.ts
1646
+ function stripTime(date) {
1647
+ return new Date(date.getFullYear(), date.getMonth(), date.getDate());
1648
+ }
1649
+ function normalizeDateRange(range) {
1650
+ if (!range?.start) {
1651
+ return {};
1652
+ }
1653
+ const start = stripTime(range.start);
1654
+ if (!range.end) {
1655
+ return { start };
1656
+ }
1657
+ const end = stripTime(range.end);
1658
+ if (isBeforeDay(end, start)) {
1659
+ return { start: end, end: start };
1660
+ }
1661
+ return { start, end };
1662
+ }
1663
+ function isInDateRange(date, start, end) {
1664
+ if (!start) {
1665
+ return false;
1666
+ }
1667
+ const day = stripTime(date);
1668
+ if (!end) {
1669
+ return isSameDay(day, start);
1670
+ }
1671
+ return !isBeforeDay(day, start) && !isAfterDay(day, end);
1672
+ }
1673
+ function selectRangeDate(clicked, current) {
1674
+ const clickedDate = stripTime(clicked);
1675
+ if (!current?.start || current.end) {
1676
+ return { start: clickedDate };
1677
+ }
1678
+ const start = stripTime(current.start);
1679
+ if (isSameDay(clickedDate, start)) {
1680
+ return { start, end: clickedDate };
1681
+ }
1682
+ if (isBeforeDay(clickedDate, start)) {
1683
+ return { start: clickedDate };
1684
+ }
1685
+ return { start, end: clickedDate };
1686
+ }
1687
+ function isSameDay(left, right) {
1688
+ return left.getFullYear() === right.getFullYear() && left.getMonth() === right.getMonth() && left.getDate() === right.getDate();
1689
+ }
1690
+ function isBeforeDay(left, right) {
1691
+ return stripTime(left).getTime() < stripTime(right).getTime();
1692
+ }
1693
+ function isAfterDay(left, right) {
1694
+ return stripTime(left).getTime() > stripTime(right).getTime();
1695
+ }
1696
+ function addMonths(date, amount) {
1697
+ return new Date(date.getFullYear(), date.getMonth() + amount, 1);
1698
+ }
1699
+ function isDateDisabled(date, minDate, maxDate) {
1700
+ if (minDate && isBeforeDay(date, minDate)) {
1701
+ return true;
1702
+ }
1703
+ if (maxDate && isAfterDay(date, maxDate)) {
1704
+ return true;
1705
+ }
1706
+ return false;
1707
+ }
1708
+ var CALENDAR_VISIBLE_DAY_COUNT = 42;
1709
+ var MONDAY_WEEK_START = 1;
1710
+ function buildCalendarDays({
1711
+ viewDate,
1712
+ selectedDate,
1713
+ selectedRange,
1714
+ today,
1715
+ minDate,
1716
+ maxDate
1717
+ }) {
1718
+ const { start: rangeStart, end: rangeEnd } = normalizeDateRange(selectedRange);
1719
+ const year = viewDate.getFullYear();
1720
+ const month = viewDate.getMonth();
1721
+ const firstOfMonth = new Date(year, month, 1);
1722
+ const startOffset = (firstOfMonth.getDay() - MONDAY_WEEK_START + 7) % 7;
1723
+ const gridStart = new Date(year, month, 1 - startOffset);
1724
+ const days = [];
1725
+ for (let index = 0; index < CALENDAR_VISIBLE_DAY_COUNT; index += 1) {
1726
+ const date = new Date(
1727
+ gridStart.getFullYear(),
1728
+ gridStart.getMonth(),
1729
+ gridStart.getDate() + index
1730
+ );
1731
+ const inCurrentMonth = date.getMonth() === month;
1732
+ const isPast = inCurrentMonth && isBeforeDay(date, today);
1733
+ const isDisabled = isDateDisabled(date, minDate, maxDate);
1734
+ const isRangeStart = rangeStart ? isSameDay(date, rangeStart) : false;
1735
+ const isRangeEnd = rangeEnd ? isSameDay(date, rangeEnd) : false;
1736
+ const inSelectedRange = rangeStart && rangeEnd ? isInDateRange(date, rangeStart, rangeEnd) : false;
1737
+ const isInRange = inSelectedRange && !isRangeStart && !isRangeEnd;
1738
+ const isSelected = selectedDate ? isSameDay(date, selectedDate) : inSelectedRange || Boolean(rangeStart && !rangeEnd && isRangeStart);
1739
+ days.push({
1740
+ date,
1741
+ inCurrentMonth,
1742
+ isToday: isSameDay(date, today),
1743
+ isSelected,
1744
+ isRangeStart,
1745
+ isRangeEnd,
1746
+ isInRange,
1747
+ isPast,
1748
+ isDisabled
1749
+ });
1750
+ }
1751
+ return days;
1752
+ }
1753
+ function formatCalendarYear(year, locale) {
1754
+ return new Intl.DateTimeFormat(locale, { year: "numeric" }).format(new Date(year, 0, 1));
1755
+ }
1756
+ function getYearPageStart(year, yearsPerPage = 12) {
1757
+ return Math.floor(year / yearsPerPage) * yearsPerPage;
1758
+ }
1759
+ function isMonthDisabled(year, month, minDate, maxDate) {
1760
+ const firstDay = new Date(year, month, 1);
1761
+ const lastDay = new Date(year, month + 1, 0);
1762
+ if (minDate && isBeforeDay(lastDay, minDate)) {
1763
+ return true;
1764
+ }
1765
+ if (maxDate && isAfterDay(firstDay, maxDate)) {
1766
+ return true;
1767
+ }
1768
+ return false;
1769
+ }
1770
+ function isYearDisabled(year, minDate, maxDate) {
1771
+ const firstDay = new Date(year, 0, 1);
1772
+ const lastDay = new Date(year, 11, 31);
1773
+ if (minDate && isBeforeDay(lastDay, minDate)) {
1774
+ return true;
1775
+ }
1776
+ if (maxDate && isAfterDay(firstDay, maxDate)) {
1777
+ return true;
1778
+ }
1779
+ return false;
1780
+ }
1781
+ function formatCalendarDate(date, locale) {
1782
+ return new Intl.DateTimeFormat(locale, {
1783
+ day: "numeric",
1784
+ month: "long",
1785
+ year: "numeric"
1786
+ }).format(date);
1787
+ }
1788
+ function formatCalendarDateRange(range, locale, separator = " \u2013 ") {
1789
+ const { start, end } = normalizeDateRange(range);
1790
+ if (!start) {
1791
+ return "";
1792
+ }
1793
+ if (!end) {
1794
+ return formatCalendarDate(start, locale);
1795
+ }
1796
+ return `${formatCalendarDate(start, locale)}${separator}${formatCalendarDate(end, locale)}`;
1797
+ }
1798
+
1799
+ // src/utils/calendarLocalization.ts
1800
+ var calendarTranslations = {
1801
+ "hy-AM": {
1802
+ weekdays: ["\u0535\u0550", "\u0535\u0554", "\u0549\u0550", "\u0540\u0546", "\u0548\u0552\u0550", "\u0547\u0532", "\u053F\u0550"],
1803
+ monthsShort: [
1804
+ "\u0540\u0576\u057E",
1805
+ "\u0553\u057F\u057E",
1806
+ "\u0544\u0580\u057F",
1807
+ "\u0531\u057A\u0580",
1808
+ "\u0544\u0575\u057D",
1809
+ "\u0540\u0578\u0582\u0576",
1810
+ "\u0540\u0578\u0582\u056C",
1811
+ "\u0555\u0563\u057D",
1812
+ "\u054D\u0565\u057A",
1813
+ "\u0540\u0578\u056F",
1814
+ "\u0546\u0578\u0575",
1815
+ "\u0534\u0565\u056F"
1816
+ ],
1817
+ monthsLong: [
1818
+ "\u0540\u0578\u0582\u0576\u057E\u0561\u0580",
1819
+ "\u0553\u0565\u057F\u0580\u057E\u0561\u0580",
1820
+ "\u0544\u0561\u0580\u057F",
1821
+ "\u0531\u057A\u0580\u056B\u056C",
1822
+ "\u0544\u0561\u0575\u056B\u057D",
1823
+ "\u0540\u0578\u0582\u0576\u056B\u057D",
1824
+ "\u0540\u0578\u0582\u056C\u056B\u057D",
1825
+ "\u0555\u0563\u0578\u057D\u057F\u0578\u057D",
1826
+ "\u054D\u0565\u057A\u057F\u0565\u0574\u0562\u0565\u0580",
1827
+ "\u0540\u0578\u056F\u057F\u0565\u0574\u0562\u0565\u0580",
1828
+ "\u0546\u0578\u0575\u0565\u0574\u0562\u0565\u0580",
1829
+ "\u0534\u0565\u056F\u057F\u0565\u0574\u0562\u0565\u0580"
1830
+ ],
1831
+ datePlaceholder: "\u0538\u0576\u057F\u0580\u0565\u056C \u0561\u0574\u057D\u0561\u0569\u056B\u057E",
1832
+ rangePlaceholder: "\u0538\u0576\u057F\u0580\u0565\u056C \u056A\u0561\u0574\u0561\u0576\u0561\u056F\u0561\u0570\u0561\u057F\u057E\u0561\u056E",
1833
+ previousMonth: "\u0546\u0561\u056D\u0578\u0580\u0564 \u0561\u0574\u056B\u057D",
1834
+ nextMonth: "\u0540\u0561\u057B\u0578\u0580\u0564 \u0561\u0574\u056B\u057D",
1835
+ previousYear: "\u0546\u0561\u056D\u0578\u0580\u0564 \u057F\u0561\u0580\u056B",
1836
+ nextYear: "\u0540\u0561\u057B\u0578\u0580\u0564 \u057F\u0561\u0580\u056B",
1837
+ previousYears: "\u0546\u0561\u056D\u0578\u0580\u0564 \u057F\u0561\u0580\u056B\u0576\u0565\u0580",
1838
+ nextYears: "\u0540\u0561\u057B\u0578\u0580\u0564 \u057F\u0561\u0580\u056B\u0576\u0565\u0580",
1839
+ selectMonth: "\u0538\u0576\u057F\u0580\u0565\u056C \u0561\u0574\u056B\u057D",
1840
+ selectYear: "\u0538\u0576\u057F\u0580\u0565\u056C \u057F\u0561\u0580\u056B",
1841
+ closeCalendar: "\u0553\u0561\u056F\u0565\u056C \u0585\u0580\u0561\u0581\u0578\u0582\u0575\u0581\u0568"
1842
+ },
1843
+ "en-US": {
1844
+ weekdays: ["MO", "TU", "WE", "TH", "FR", "SA", "SU"],
1845
+ monthsShort: [
1846
+ "Jan",
1847
+ "Feb",
1848
+ "Mar",
1849
+ "Apr",
1850
+ "May",
1851
+ "Jun",
1852
+ "Jul",
1853
+ "Aug",
1854
+ "Sep",
1855
+ "Oct",
1856
+ "Nov",
1857
+ "Dec"
1858
+ ],
1859
+ monthsLong: [
1860
+ "January",
1861
+ "February",
1862
+ "March",
1863
+ "April",
1864
+ "May",
1865
+ "June",
1866
+ "July",
1867
+ "August",
1868
+ "September",
1869
+ "October",
1870
+ "November",
1871
+ "December"
1872
+ ],
1873
+ datePlaceholder: "Select date",
1874
+ rangePlaceholder: "Select date range",
1875
+ previousMonth: "Previous month",
1876
+ nextMonth: "Next month",
1877
+ previousYear: "Previous year",
1878
+ nextYear: "Next year",
1879
+ previousYears: "Previous years",
1880
+ nextYears: "Next years",
1881
+ selectMonth: "Select month",
1882
+ selectYear: "Select year",
1883
+ closeCalendar: "Close calendar"
1884
+ },
1885
+ "ru-RU": {
1886
+ weekdays: ["\u041F\u041D", "\u0412\u0422", "\u0421\u0420", "\u0427\u0422", "\u041F\u0422", "\u0421\u0411", "\u0412\u0421"],
1887
+ monthsShort: [
1888
+ "\u042F\u043D\u0432",
1889
+ "\u0424\u0435\u0432",
1890
+ "\u041C\u0430\u0440",
1891
+ "\u0410\u043F\u0440",
1892
+ "\u041C\u0430\u0439",
1893
+ "\u0418\u044E\u043D",
1894
+ "\u0418\u044E\u043B",
1895
+ "\u0410\u0432\u0433",
1896
+ "\u0421\u0435\u043D",
1897
+ "\u041E\u043A\u0442",
1898
+ "\u041D\u043E\u044F",
1899
+ "\u0414\u0435\u043A"
1900
+ ],
1901
+ monthsLong: [
1902
+ "\u042F\u043D\u0432\u0430\u0440\u044C",
1903
+ "\u0424\u0435\u0432\u0440\u0430\u043B\u044C",
1904
+ "\u041C\u0430\u0440\u0442",
1905
+ "\u0410\u043F\u0440\u0435\u043B\u044C",
1906
+ "\u041C\u0430\u0439",
1907
+ "\u0418\u044E\u043D\u044C",
1908
+ "\u0418\u044E\u043B\u044C",
1909
+ "\u0410\u0432\u0433\u0443\u0441\u0442",
1910
+ "\u0421\u0435\u043D\u0442\u044F\u0431\u0440\u044C",
1911
+ "\u041E\u043A\u0442\u044F\u0431\u0440\u044C",
1912
+ "\u041D\u043E\u044F\u0431\u0440\u044C",
1913
+ "\u0414\u0435\u043A\u0430\u0431\u0440\u044C"
1914
+ ],
1915
+ datePlaceholder: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0434\u0430\u0442\u0443",
1916
+ rangePlaceholder: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043F\u0435\u0440\u0438\u043E\u0434",
1917
+ previousMonth: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u043C\u0435\u0441\u044F\u0446",
1918
+ nextMonth: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u043C\u0435\u0441\u044F\u0446",
1919
+ previousYear: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0433\u043E\u0434",
1920
+ nextYear: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0433\u043E\u0434",
1921
+ previousYears: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0435 \u0433\u043E\u0434\u044B",
1922
+ nextYears: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0435 \u0433\u043E\u0434\u044B",
1923
+ selectMonth: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u043C\u0435\u0441\u044F\u0446",
1924
+ selectYear: "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0433\u043E\u0434",
1925
+ closeCalendar: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C \u043A\u0430\u043B\u0435\u043D\u0434\u0430\u0440\u044C"
1926
+ }
1927
+ };
1928
+ function resolveCalendarLocale(locale) {
1929
+ const normalizedLocale = locale.toLowerCase();
1930
+ if (normalizedLocale.startsWith("hy")) {
1931
+ return "hy-AM";
1932
+ }
1933
+ if (normalizedLocale.startsWith("ru")) {
1934
+ return "ru-RU";
1935
+ }
1936
+ return "en-US";
1937
+ }
1938
+ function getCalendarTranslations(locale) {
1939
+ return calendarTranslations[resolveCalendarLocale(locale)];
1940
+ }
1941
+ function resolveWeekdayLabels(locale) {
1942
+ return getCalendarTranslations(locale).weekdays;
1943
+ }
1944
+ function getCalendarMonthLabels(locale, width = "short") {
1945
+ const translations = getCalendarTranslations(locale);
1946
+ return width === "short" ? translations.monthsShort : translations.monthsLong;
1947
+ }
1948
+ function formatLocalizedCalendarMonthYear(date, locale) {
1949
+ return `${getCalendarMonthLabels(locale)[date.getMonth()]} ${date.getFullYear()}`;
1950
+ }
1951
+ var LOCALE_STORAGE_KEY = "homepad.locale";
1952
+ var LOCALE_CHANGE_EVENT = "homepad:locale-change";
1953
+ var DEFAULT_CALENDAR_LOCALE = "hy-AM";
1954
+ var CalendarLocaleContext = createContext(void 0);
1955
+ function CalendarLocaleProvider({ locale, children }) {
1956
+ return /* @__PURE__ */ jsx(CalendarLocaleContext.Provider, { value: locale, children });
1957
+ }
1958
+ function normalizeProjectLocale(locale) {
1959
+ if (!locale) {
1960
+ return null;
1961
+ }
1962
+ return resolveCalendarLocale(locale);
1963
+ }
1964
+ function readBrowserLocale() {
1965
+ if (typeof window === "undefined") {
1966
+ return null;
1967
+ }
1968
+ let storedLocale = null;
1969
+ try {
1970
+ storedLocale = normalizeProjectLocale(window.localStorage.getItem(LOCALE_STORAGE_KEY));
1971
+ } catch {
1972
+ storedLocale = null;
1973
+ }
1974
+ if (storedLocale) {
1975
+ return storedLocale;
1976
+ }
1977
+ const documentLocale = normalizeProjectLocale(window.document?.documentElement.lang);
1978
+ if (documentLocale) {
1979
+ return documentLocale;
1980
+ }
1981
+ return normalizeProjectLocale(window.navigator.language);
1982
+ }
1983
+ function useCalendarLocale(locale) {
1984
+ const contextLocale = useContext(CalendarLocaleContext);
1985
+ const controlledLocale = locale ?? contextLocale;
1986
+ const [browserLocale, setBrowserLocale] = useState(
1987
+ () => readBrowserLocale() ?? DEFAULT_CALENDAR_LOCALE
1988
+ );
1989
+ useEffect(() => {
1990
+ if (controlledLocale !== void 0 || typeof window === "undefined") {
1991
+ return;
1992
+ }
1993
+ const syncLocale = () => {
1994
+ setBrowserLocale(readBrowserLocale() ?? DEFAULT_CALENDAR_LOCALE);
1995
+ };
1996
+ const handleLocaleChange = (event) => {
1997
+ const customEvent = event;
1998
+ const nextLocale = normalizeProjectLocale(customEvent.detail);
1999
+ if (nextLocale) {
2000
+ setBrowserLocale(nextLocale);
2001
+ return;
2002
+ }
2003
+ syncLocale();
2004
+ };
2005
+ window.addEventListener(LOCALE_CHANGE_EVENT, handleLocaleChange);
2006
+ window.addEventListener("storage", syncLocale);
2007
+ return () => {
2008
+ window.removeEventListener(LOCALE_CHANGE_EVENT, handleLocaleChange);
2009
+ window.removeEventListener("storage", syncLocale);
2010
+ };
2011
+ }, [controlledLocale]);
2012
+ return useMemo(
2013
+ () => normalizeProjectLocale(controlledLocale) ?? browserLocale,
2014
+ [browserLocale, controlledLocale]
2015
+ );
2016
+ }
2017
+ function resolveDayCellStyle(day) {
2018
+ if (day.isDisabled) {
2019
+ return [calendarDropdownMetrics.dayCell];
2020
+ }
2021
+ if (day.isSelected) {
2022
+ return [calendarDropdownMetrics.dayCell, calendarDropdownMetrics.dayCellSelected];
2023
+ }
2024
+ return [
2025
+ calendarDropdownMetrics.dayCell,
2026
+ day.inCurrentMonth && day.isPast && !day.isToday ? calendarDropdownMetrics.dayCellPast : null
2027
+ ];
2028
+ }
2029
+ function resolveDayLabelStyle(day) {
2030
+ if (day.isDisabled) {
2031
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelDisabled];
2032
+ }
2033
+ if (day.isSelected) {
2034
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelSelected];
2035
+ }
2036
+ if (!day.inCurrentMonth) {
2037
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelOutsideMonth];
2038
+ }
2039
+ if (day.isToday) {
2040
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelToday];
2041
+ }
2042
+ if (day.isPast) {
2043
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelMuted];
2044
+ }
2045
+ return [calendarDropdownMetrics.dayLabel, calendarDropdownMetrics.dayLabelFuture];
2046
+ }
2047
+ function Calendar(props) {
2048
+ const rangeProps = props.mode === "range" ? props : null;
2049
+ const singleProps = props.mode === "range" ? null : props;
2050
+ const {
2051
+ viewDate,
2052
+ defaultViewDate,
2053
+ onViewDateChange,
2054
+ locale,
2055
+ labels,
2056
+ minDate,
2057
+ maxDate,
2058
+ today = /* @__PURE__ */ new Date(),
2059
+ style,
2060
+ className
2061
+ } = props;
2062
+ const rootRef = useRef(null);
2063
+ const [internalViewDate, setInternalViewDate] = useState(() => {
2064
+ if (defaultViewDate) {
2065
+ return defaultViewDate;
2066
+ }
2067
+ if (rangeProps) {
2068
+ return rangeProps.value?.start ?? today;
2069
+ }
2070
+ return singleProps?.value ?? today;
2071
+ });
2072
+ const activeViewDate = viewDate ?? internalViewDate;
2073
+ const [pickerView, setPickerView] = useState("days");
2074
+ const [pickerYear, setPickerYear] = useState(() => activeViewDate.getFullYear());
2075
+ const [yearPageStart, setYearPageStart] = useState(
2076
+ () => getYearPageStart(activeViewDate.getFullYear(), CALENDAR_YEARS_PER_PAGE)
2077
+ );
2078
+ const customWeekdayLabels = labels?.weekdays;
2079
+ const formatMonthYearLabel = labels?.formatMonthYear;
2080
+ const resolvedLocale = useCalendarLocale(locale);
2081
+ const translations = useMemo(
2082
+ () => getCalendarTranslations(resolvedLocale),
2083
+ [resolvedLocale]
2084
+ );
2085
+ useApplyWebClassName(rootRef, className);
2086
+ const weekdayLabels = useMemo(
2087
+ () => customWeekdayLabels ?? resolveWeekdayLabels(resolvedLocale),
2088
+ [customWeekdayLabels, resolvedLocale]
2089
+ );
2090
+ const monthLabels = useMemo(() => getCalendarMonthLabels(resolvedLocale), [resolvedLocale]);
2091
+ const monthYearLabel = useMemo(() => {
2092
+ if (formatMonthYearLabel) {
2093
+ return formatMonthYearLabel(activeViewDate);
2094
+ }
2095
+ return formatLocalizedCalendarMonthYear(activeViewDate, resolvedLocale);
2096
+ }, [activeViewDate, formatMonthYearLabel, resolvedLocale]);
2097
+ const headerLabel = useMemo(() => {
2098
+ if (pickerView === "months") {
2099
+ return formatCalendarYear(pickerYear, resolvedLocale);
2100
+ }
2101
+ if (pickerView === "years") {
2102
+ const endYear = yearPageStart + CALENDAR_YEARS_PER_PAGE - 1;
2103
+ return `${yearPageStart} \u2013 ${endYear}`;
2104
+ }
2105
+ return monthYearLabel;
2106
+ }, [monthYearLabel, pickerView, pickerYear, resolvedLocale, yearPageStart]);
2107
+ const days = useMemo(
2108
+ () => buildCalendarDays({
2109
+ viewDate: activeViewDate,
2110
+ selectedDate: singleProps?.value,
2111
+ selectedRange: rangeProps?.value,
2112
+ today,
2113
+ minDate,
2114
+ maxDate
2115
+ }),
2116
+ [activeViewDate, maxDate, minDate, rangeProps?.value, singleProps?.value, today]
2117
+ );
2118
+ const yearOptions = useMemo(
2119
+ () => Array.from({ length: CALENDAR_YEARS_PER_PAGE }, (_, index) => yearPageStart + index),
2120
+ [yearPageStart]
2121
+ );
2122
+ function getLabel(key) {
2123
+ return labels?.[key] ?? translations[key];
2124
+ }
2125
+ function setViewDate(nextDate) {
2126
+ if (viewDate === void 0) {
2127
+ setInternalViewDate(nextDate);
2128
+ }
2129
+ onViewDateChange?.(nextDate);
2130
+ }
2131
+ function handlePrevious() {
2132
+ if (pickerView === "months") {
2133
+ setPickerYear((year) => year - 1);
2134
+ return;
2135
+ }
2136
+ if (pickerView === "years") {
2137
+ setYearPageStart((start) => start - CALENDAR_YEARS_PER_PAGE);
2138
+ return;
2139
+ }
2140
+ setViewDate(addMonths(activeViewDate, -1));
2141
+ }
2142
+ function handleNext() {
2143
+ if (pickerView === "months") {
2144
+ setPickerYear((year) => year + 1);
2145
+ return;
2146
+ }
2147
+ if (pickerView === "years") {
2148
+ setYearPageStart((start) => start + CALENDAR_YEARS_PER_PAGE);
2149
+ return;
2150
+ }
2151
+ setViewDate(addMonths(activeViewDate, 1));
2152
+ }
2153
+ function handleHeaderPress() {
2154
+ if (pickerView === "days") {
2155
+ setPickerYear(activeViewDate.getFullYear());
2156
+ setPickerView("months");
2157
+ return;
2158
+ }
2159
+ if (pickerView === "months") {
2160
+ setYearPageStart(getYearPageStart(pickerYear, CALENDAR_YEARS_PER_PAGE));
2161
+ setPickerView("years");
2162
+ }
2163
+ }
2164
+ function handleMonthSelect(month) {
2165
+ setViewDate(new Date(pickerYear, month, 1));
2166
+ setPickerView("days");
2167
+ }
2168
+ function handleYearSelect(year) {
2169
+ setPickerYear(year);
2170
+ setPickerView("months");
2171
+ }
2172
+ function handleDayPress(date) {
2173
+ if (rangeProps) {
2174
+ rangeProps.onChange?.(selectRangeDate(date, rangeProps.value));
2175
+ return;
2176
+ }
2177
+ singleProps?.onChange?.(date);
2178
+ }
2179
+ const headerIsPressable = pickerView === "days" || pickerView === "months";
2180
+ return /* @__PURE__ */ jsxs(View, { ref: rootRef, style: [calendarDropdownMetrics.panel, style], children: [
2181
+ /* @__PURE__ */ jsxs(View, { style: calendarDropdownMetrics.header, children: [
2182
+ /* @__PURE__ */ jsx(
2183
+ Pressable,
2184
+ {
2185
+ accessibilityRole: "button",
2186
+ accessibilityLabel: pickerView === "months" ? getLabel("previousYear") : pickerView === "years" ? getLabel("previousYears") : getLabel("previousMonth"),
2187
+ onPress: handlePrevious,
2188
+ style: calendarDropdownMetrics.navButton,
2189
+ children: /* @__PURE__ */ jsx(ChevronLeftIcon, { size: CALENDAR_NAV_ICON_SIZE, color: CALENDAR_NAV_ICON_COLOR })
2190
+ }
2191
+ ),
2192
+ headerIsPressable ? /* @__PURE__ */ jsx(
2193
+ Pressable,
2194
+ {
2195
+ accessibilityRole: "button",
2196
+ accessibilityLabel: pickerView === "days" ? getLabel("selectMonth") : getLabel("selectYear"),
2197
+ onPress: handleHeaderPress,
2198
+ style: calendarDropdownMetrics.headerTitlePressable,
2199
+ children: /* @__PURE__ */ jsx(Text, { style: calendarDropdownMetrics.headerTitle, children: headerLabel })
2200
+ }
2201
+ ) : /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.headerTitlePressable, children: /* @__PURE__ */ jsx(Text, { style: calendarDropdownMetrics.headerTitle, children: headerLabel }) }),
2202
+ /* @__PURE__ */ jsx(
2203
+ Pressable,
2204
+ {
2205
+ accessibilityRole: "button",
2206
+ accessibilityLabel: pickerView === "months" ? getLabel("nextYear") : pickerView === "years" ? getLabel("nextYears") : getLabel("nextMonth"),
2207
+ onPress: handleNext,
2208
+ style: calendarDropdownMetrics.navButton,
2209
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, { size: CALENDAR_NAV_ICON_SIZE, color: CALENDAR_NAV_ICON_COLOR })
2210
+ }
2211
+ )
2212
+ ] }),
2213
+ pickerView === "days" ? /* @__PURE__ */ jsxs(Fragment, { children: [
2214
+ /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.weekdayRow, children: weekdayLabels.map((weekday) => /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.weekdayCell, children: /* @__PURE__ */ jsx(Text, { style: calendarDropdownMetrics.weekdayLabel, children: weekday }) }, weekday)) }),
2215
+ /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.dayGrid, children: days.map((day) => /* @__PURE__ */ jsxs(
2216
+ Pressable,
2217
+ {
2218
+ accessibilityRole: "button",
2219
+ accessibilityState: {
2220
+ selected: day.isSelected,
2221
+ disabled: day.isDisabled
2222
+ },
2223
+ disabled: day.isDisabled,
2224
+ onPress: () => handleDayPress(day.date),
2225
+ style: resolveDayCellStyle(day),
2226
+ children: [
2227
+ /* @__PURE__ */ jsx(Text, { style: resolveDayLabelStyle(day), children: day.date.getDate() }),
2228
+ day.isToday && day.inCurrentMonth && !day.isSelected ? /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.todayDot }) : null
2229
+ ]
2230
+ },
2231
+ day.date.toISOString()
2232
+ )) })
2233
+ ] }) : /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.pickerBody, children: /* @__PURE__ */ jsx(View, { style: calendarDropdownMetrics.pickerGrid, children: pickerView === "months" ? monthLabels.map((monthLabel, month) => {
2234
+ const isSelected = activeViewDate.getFullYear() === pickerYear && activeViewDate.getMonth() === month;
2235
+ const isCurrent = today.getFullYear() === pickerYear && today.getMonth() === month;
2236
+ const disabled = isMonthDisabled(pickerYear, month, minDate, maxDate);
2237
+ return /* @__PURE__ */ jsx(
2238
+ Pressable,
2239
+ {
2240
+ accessibilityRole: "button",
2241
+ accessibilityState: { selected: isSelected, disabled },
2242
+ disabled,
2243
+ onPress: () => handleMonthSelect(month),
2244
+ style: [
2245
+ calendarDropdownMetrics.pickerCell,
2246
+ isSelected ? calendarDropdownMetrics.pickerCellSelected : null
2247
+ ],
2248
+ children: /* @__PURE__ */ jsx(
2249
+ Text,
2250
+ {
2251
+ style: [
2252
+ calendarDropdownMetrics.pickerLabel,
2253
+ isSelected ? calendarDropdownMetrics.pickerLabelSelected : null,
2254
+ !isSelected && isCurrent ? calendarDropdownMetrics.pickerLabelCurrent : null,
2255
+ disabled ? calendarDropdownMetrics.pickerLabelDisabled : null
2256
+ ],
2257
+ children: monthLabel
2258
+ }
2259
+ )
2260
+ },
2261
+ monthLabel
2262
+ );
2263
+ }) : yearOptions.map((year) => {
2264
+ const isSelected = activeViewDate.getFullYear() === year;
2265
+ const isCurrent = today.getFullYear() === year;
2266
+ const disabled = isYearDisabled(year, minDate, maxDate);
2267
+ return /* @__PURE__ */ jsx(
2268
+ Pressable,
2269
+ {
2270
+ accessibilityRole: "button",
2271
+ accessibilityState: { selected: isSelected, disabled },
2272
+ disabled,
2273
+ onPress: () => handleYearSelect(year),
2274
+ style: [
2275
+ calendarDropdownMetrics.pickerCell,
2276
+ isSelected ? calendarDropdownMetrics.pickerCellSelected : null
2277
+ ],
2278
+ children: /* @__PURE__ */ jsx(
2279
+ Text,
2280
+ {
2281
+ style: [
2282
+ calendarDropdownMetrics.pickerLabel,
2283
+ isSelected ? calendarDropdownMetrics.pickerLabelSelected : null,
2284
+ !isSelected && isCurrent ? calendarDropdownMetrics.pickerLabelCurrent : null,
2285
+ disabled ? calendarDropdownMetrics.pickerLabelDisabled : null
2286
+ ],
2287
+ children: year
2288
+ }
2289
+ )
2290
+ },
2291
+ year
2292
+ );
2293
+ }) }) })
2294
+ ] });
2295
+ }
2296
+
2297
+ // src/icons/calendarIconPaths.ts
2298
+ 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";
2299
+ function CalendarIcon({
2300
+ size = 20,
2301
+ color = "#C7CDD1",
2302
+ strokeWidth = 2
2303
+ }) {
2304
+ return /* @__PURE__ */ jsx(Svg3, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
2305
+ Path,
2306
+ {
2307
+ d: CALENDAR_ICON_BODY_PATH,
2308
+ stroke: color,
2309
+ strokeWidth,
2310
+ strokeLinecap: "round",
2311
+ strokeLinejoin: "round"
2312
+ }
2313
+ ) });
2314
+ }
2315
+ function DatePicker(props) {
2316
+ const {
2317
+ label,
2318
+ placeholder,
2319
+ locale,
2320
+ labels,
2321
+ minDate,
2322
+ maxDate,
2323
+ today,
2324
+ viewDate,
2325
+ defaultViewDate,
2326
+ onViewDateChange,
2327
+ disabled = false,
2328
+ error,
2329
+ invalid,
2330
+ hint,
2331
+ containerStyle,
2332
+ className,
2333
+ fieldClassName,
2334
+ panelClassName,
2335
+ labelClassName,
2336
+ errorClassName,
2337
+ hintClassName,
2338
+ defaultOpen = false
2339
+ } = props;
2340
+ const mode = props.mode ?? "single";
2341
+ const closeOnRangeComplete = props.mode === "range" ? props.closeOnRangeComplete ?? true : false;
2342
+ const resolvedLocale = useCalendarLocale(locale);
2343
+ const translations = getCalendarTranslations(resolvedLocale);
2344
+ const resolvedPlaceholder = placeholder ?? (mode === "range" ? translations.rangePlaceholder : translations.datePlaceholder);
2345
+ const wrapperRef = useRef(null);
2346
+ const triggerRef = useRef(null);
2347
+ const helperRef = useRef(null);
2348
+ const [open, setOpen] = useState(defaultOpen);
2349
+ const [anchor, setAnchor] = useState(null);
2350
+ useApplyWebClassName(wrapperRef, className);
2351
+ useApplyWebClassName(triggerRef, fieldClassName);
2352
+ useApplyWebClassName(helperRef, error ? errorClassName : hintClassName);
2353
+ useEffect(() => {
2354
+ if (!defaultOpen || disabled) {
2355
+ return;
2356
+ }
2357
+ const frame = requestAnimationFrame(() => {
2358
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
2359
+ setAnchor({ x, y, width, height });
2360
+ setOpen(true);
2361
+ });
2362
+ });
2363
+ return () => cancelAnimationFrame(frame);
2364
+ }, [defaultOpen, disabled]);
2365
+ const hasError = Boolean(error) || Boolean(invalid);
2366
+ const fieldStyles = getSelectFieldStyles(
2367
+ resolveInputVisualState({
2368
+ error: hasError,
2369
+ disabled
2370
+ })
2371
+ );
2372
+ const hasValue = mode === "single" ? Boolean(props.value) : Boolean(props.mode === "range" && props.value?.start);
2373
+ const displayValue = (() => {
2374
+ if (props.mode === "range") {
2375
+ if (!props.value?.start) {
2376
+ return resolvedPlaceholder;
2377
+ }
2378
+ return props.formatRange?.(props.value) ?? formatCalendarDateRange(props.value, resolvedLocale, props.rangeSeparator);
2379
+ }
2380
+ if (props.value) {
2381
+ return props.formatDate?.(props.value) ?? formatCalendarDate(props.value, resolvedLocale);
2382
+ }
2383
+ return resolvedPlaceholder;
2384
+ })();
2385
+ const isPlaceholder = !hasValue;
2386
+ const valueTextStyle = isPlaceholder ? {
2387
+ ...calendarFieldPlaceholderTypography,
2388
+ color: disabled ? colors.stormGray300 : calendarFieldPlaceholderTypography.color
2389
+ } : {
2390
+ ...calendarFieldTypography,
2391
+ color: fieldStyles.value.color
2392
+ };
2393
+ const helperMessage = error ?? hint;
2394
+ const panelWidth = CALENDAR_PANEL_WIDTH;
2395
+ const panelLeft = anchor ? resolveCalendarDropdownLeft(anchor, panelWidth) : 0;
2396
+ const dropdownTop = anchor ? resolveCalendarDropdownTop(anchor) : 0;
2397
+ const resolvedDefaultViewDate = defaultViewDate ?? (props.mode === "range" ? props.value?.start : props.value) ?? today;
2398
+ function closePicker() {
2399
+ setOpen(false);
2400
+ setAnchor(null);
2401
+ }
2402
+ function openPicker() {
2403
+ if (disabled) {
2404
+ return;
2405
+ }
2406
+ triggerRef.current?.measureInWindow((x, y, width, height) => {
2407
+ setAnchor({ x, y, width, height });
2408
+ setOpen(true);
2409
+ });
2410
+ }
2411
+ function handleSingleSelect(date) {
2412
+ if (props.mode === "range") {
2413
+ return;
2414
+ }
2415
+ props.onChange?.(date);
2416
+ closePicker();
2417
+ }
2418
+ function handleRangeSelect(range) {
2419
+ if (props.mode !== "range") {
2420
+ return;
2421
+ }
2422
+ props.onChange?.(range);
2423
+ if (closeOnRangeComplete && range.end) {
2424
+ closePicker();
2425
+ }
2426
+ }
2427
+ return /* @__PURE__ */ jsxs(View, { ref: wrapperRef, style: [styles5.wrapper, containerStyle], children: [
2428
+ label ? /* @__PURE__ */ jsx(Label, { disabled, style: styles5.label, className: labelClassName, children: label }) : null,
2429
+ /* @__PURE__ */ jsx(View, { style: [fieldStyles.outline, styles5.fieldOutline], children: /* @__PURE__ */ jsxs(
2430
+ Pressable,
2431
+ {
2432
+ ref: triggerRef,
2433
+ accessibilityRole: "button",
2434
+ accessibilityState: { disabled, expanded: open },
2435
+ disabled,
2436
+ onPress: openPicker,
2437
+ style: [calendarFieldMetrics.container, fieldStyles.container],
2438
+ children: [
2439
+ /* @__PURE__ */ jsx(
2440
+ Text,
2441
+ {
2442
+ style: [calendarFieldMetrics.value, valueTextStyle],
2443
+ numberOfLines: 1,
2444
+ children: displayValue
2445
+ }
2446
+ ),
2447
+ /* @__PURE__ */ jsx(View, { style: styles5.iconSlot, children: /* @__PURE__ */ jsx(
2448
+ CalendarIcon,
2449
+ {
2450
+ size: CALENDAR_FIELD_ICON_SIZE,
2451
+ color: disabled ? colors.stormGray200 : colors.stormGray150
2452
+ }
2453
+ ) })
2454
+ ]
2455
+ }
2456
+ ) }),
2457
+ helperMessage ? /* @__PURE__ */ jsx(Text, { ref: helperRef, style: error ? styles5.error : styles5.hint, children: helperMessage }) : null,
2458
+ /* @__PURE__ */ jsx(Modal, { visible: open, transparent: true, animationType: "fade", onRequestClose: closePicker, children: /* @__PURE__ */ jsxs(View, { style: styles5.modalRoot, children: [
2459
+ /* @__PURE__ */ jsx(
2460
+ Pressable,
2461
+ {
2462
+ style: styles5.backdrop,
2463
+ onPress: closePicker,
2464
+ accessibilityRole: "button",
2465
+ accessibilityLabel: labels?.closeCalendar ?? translations.closeCalendar
2466
+ }
2467
+ ),
2468
+ anchor ? /* @__PURE__ */ jsx(
2469
+ View,
2470
+ {
2471
+ style: [
2472
+ styles5.panelPosition,
2473
+ {
2474
+ top: dropdownTop,
2475
+ left: panelLeft,
2476
+ width: panelWidth,
2477
+ height: CALENDAR_PANEL_HEIGHT
2478
+ }
2479
+ ],
2480
+ children: props.mode === "range" ? /* @__PURE__ */ jsx(
2481
+ Calendar,
2482
+ {
2483
+ mode: "range",
2484
+ value: props.value,
2485
+ onChange: handleRangeSelect,
2486
+ viewDate,
2487
+ defaultViewDate: resolvedDefaultViewDate,
2488
+ onViewDateChange,
2489
+ locale: resolvedLocale,
2490
+ labels,
2491
+ minDate,
2492
+ maxDate,
2493
+ today,
2494
+ className: panelClassName
2495
+ }
2496
+ ) : /* @__PURE__ */ jsx(
2497
+ Calendar,
2498
+ {
2499
+ mode: "single",
2500
+ value: props.value,
2501
+ onChange: handleSingleSelect,
2502
+ viewDate,
2503
+ defaultViewDate: resolvedDefaultViewDate,
2504
+ onViewDateChange,
2505
+ locale: resolvedLocale,
2506
+ labels,
2507
+ minDate,
2508
+ maxDate,
2509
+ today,
2510
+ className: panelClassName
2511
+ }
2512
+ )
2513
+ }
2514
+ ) : null
2515
+ ] }) })
2516
+ ] });
2517
+ }
2518
+ var styles5 = StyleSheet.create({
2519
+ wrapper: {
2520
+ width: CALENDAR_FIELD_WIDTH,
2521
+ maxWidth: "100%",
2522
+ gap: SELECT_LABEL_GAP
2523
+ },
2524
+ fieldOutline: {
2525
+ width: CALENDAR_FIELD_WIDTH,
2526
+ maxWidth: "100%",
2527
+ alignSelf: "flex-start"
2528
+ },
2529
+ label: {
2530
+ ...calendarLabelTypography
2531
+ },
2532
+ iconSlot: {
2533
+ width: CALENDAR_FIELD_ICON_SIZE,
2534
+ height: CALENDAR_FIELD_ICON_SIZE,
2535
+ alignItems: "center",
2536
+ justifyContent: "center",
2537
+ flexShrink: 0
2538
+ },
2539
+ modalRoot: {
2540
+ flex: 1
2541
+ },
2542
+ backdrop: {
2543
+ ...StyleSheet.absoluteFillObject,
2544
+ backgroundColor: colors.transparent
2545
+ },
2546
+ panelPosition: {
2547
+ position: "absolute",
2548
+ zIndex: 1
2549
+ },
2550
+ error: {
2551
+ fontSize: 12,
2552
+ lineHeight: 12,
2553
+ color: colors.inputError
2554
+ },
2555
+ hint: {
2556
+ fontSize: 12,
2557
+ lineHeight: 12,
2558
+ color: colors.stormGray300
2559
+ }
2560
+ });
2561
+
2562
+ // src/icons/lockIconPaths.ts
2563
+ 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";
2564
+ function LockIcon({
2565
+ size = 20,
2566
+ color = "#c7cdd1",
2567
+ strokeWidth = 2
2568
+ }) {
2569
+ return /* @__PURE__ */ jsx(Svg3, { width: size, height: size, viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx(
2570
+ Path,
2571
+ {
2572
+ d: LOCK_ICON_PATH,
2573
+ stroke: color,
2574
+ strokeWidth,
2575
+ strokeLinecap: "round",
2576
+ strokeLinejoin: "round"
2577
+ }
2578
+ ) });
2579
+ }
2580
+
2581
+ export { Button, Calendar, CalendarIcon, CalendarLocaleProvider, CountryCodeSelector, DatePicker, LockIcon, PhoneInput, Select, calendarTranslations, countries, defaultCountry, findCountry, formatLocalizedCalendarMonthYear, getCalendarMonthLabels, getCalendarTranslations, resolveCalendarLocale, resolveWeekdayLabels, useCalendarLocale };
700
2582
  //# sourceMappingURL=index.js.map
701
2583
  //# sourceMappingURL=index.js.map