@scripso-homepad/ui 0.4.2 → 0.4.4

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