@vellira-ui/react-native 2.31.0 → 2.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -60,18 +60,30 @@ function useTheme() {
60
60
 
61
61
  // src/theme/useThemeStyles.ts
62
62
  import { useMemo as useMemo2 } from "react";
63
- function useThemeStyles(createStyles25) {
63
+ function useThemeStyles(createStyles23) {
64
64
  const { theme } = useTheme();
65
- return useMemo2(() => createStyles25(theme), [createStyles25, theme]);
65
+ return useMemo2(() => createStyles23(theme), [createStyles23, theme]);
66
66
  }
67
67
 
68
68
  // src/components/Dropdown/Content/DropdownContent.styles.ts
69
69
  import { StyleSheet } from "react-native";
70
70
  var createStyles = (theme) => StyleSheet.create({
71
71
  modalRoot: {
72
- flex: 1,
72
+ flex: 1
73
+ },
74
+ sheet: {
73
75
  justifyContent: "flex-end"
74
76
  },
77
+ modal: {
78
+ alignItems: "center",
79
+ justifyContent: "center",
80
+ padding: theme.tokens.spacing[4]
81
+ },
82
+ popover: {
83
+ alignItems: "center",
84
+ justifyContent: "center",
85
+ padding: theme.tokens.spacing[4]
86
+ },
75
87
  backdrop: {
76
88
  ...StyleSheet.absoluteFill,
77
89
  backgroundColor: theme.semantic.overlay.backdrop
@@ -93,6 +105,24 @@ var createStyles = (theme) => StyleSheet.create({
93
105
  shadowOpacity: 0.24,
94
106
  shadowRadius: 16,
95
107
  elevation: 12
108
+ },
109
+ sheetMenu: {
110
+ width: "100%",
111
+ maxHeight: "70%",
112
+ borderTopLeftRadius: theme.tokens.radius.lg,
113
+ borderTopRightRadius: theme.tokens.radius.lg
114
+ },
115
+ modalMenu: {
116
+ width: "100%",
117
+ maxWidth: 420,
118
+ maxHeight: "70%",
119
+ borderRadius: theme.tokens.radius.lg
120
+ },
121
+ popoverMenu: {
122
+ width: "100%",
123
+ maxWidth: 360,
124
+ maxHeight: "60%",
125
+ borderRadius: theme.tokens.radius.md
96
126
  }
97
127
  });
98
128
 
@@ -103,17 +133,19 @@ function DropdownContent({
103
133
  children,
104
134
  onClose,
105
135
  contentStyle,
106
- accessibilityLabel
136
+ accessibilityLabel,
137
+ presentation
107
138
  }) {
108
139
  const styles = useThemeStyles(createStyles);
140
+ const isSheet = presentation === "sheet";
109
141
  return /* @__PURE__ */ jsx2(
110
142
  Modal,
111
143
  {
112
144
  transparent: true,
113
145
  visible: isOpen,
114
- animationType: "slide",
146
+ animationType: isSheet ? "slide" : "fade",
115
147
  onRequestClose: onClose,
116
- children: /* @__PURE__ */ jsxs(View, { style: styles.modalRoot, children: [
148
+ children: /* @__PURE__ */ jsxs(View, { style: [styles.modalRoot, styles[presentation]], children: [
117
149
  /* @__PURE__ */ jsx2(
118
150
  Pressable,
119
151
  {
@@ -128,7 +160,7 @@ function DropdownContent({
128
160
  {
129
161
  accessibilityRole: "menu",
130
162
  accessibilityLabel,
131
- style: [styles.menu, contentStyle],
163
+ style: [styles.menu, styles[`${presentation}Menu`], contentStyle],
132
164
  children
133
165
  }
134
166
  )
@@ -139,9 +171,16 @@ function DropdownContent({
139
171
  DropdownContent.displayName = "DropdownContent";
140
172
 
141
173
  // src/components/Dropdown/Dropdown.tsx
142
- import { useCallback, useMemo as useMemo3 } from "react";
174
+ import { useCallback, useEffect as useEffect2, useMemo as useMemo3, useRef as useRef2 } from "react";
143
175
  import { useDropdown } from "@vellira-ui/core";
144
- import { View as View4 } from "react-native";
176
+ import {
177
+ AccessibilityInfo,
178
+ findNodeHandle,
179
+ FlatList,
180
+ Text as Text4,
181
+ useWindowDimensions,
182
+ View as View4
183
+ } from "react-native";
145
184
 
146
185
  // src/components/Dropdown/Group/DropdownGroup.tsx
147
186
  import { Text } from "react-native";
@@ -168,8 +207,100 @@ function DropdownGroup({ label }) {
168
207
  }
169
208
  DropdownGroup.displayName = "DropdownGroup";
170
209
 
210
+ // src/components/Dropdown/internal/DropdownCollection.ts
211
+ import { Children, isValidElement } from "react";
212
+ function createDropdownSlot(name, displayName) {
213
+ const Slot = () => null;
214
+ Slot.__velliraDropdownPart = name;
215
+ Slot.displayName = displayName;
216
+ return Slot;
217
+ }
218
+ function parseDropdownChildren(children) {
219
+ let generatedId = 0;
220
+ let trigger;
221
+ let triggerProps;
222
+ let contentProps;
223
+ const entries = [];
224
+ const items = [];
225
+ const nextId = (prefix) => `${prefix}-${generatedId++}`;
226
+ function pushItem(props) {
227
+ const entry = {
228
+ type: "item",
229
+ id: nextId("item"),
230
+ props,
231
+ label: getItemLabel(props.children) || props.value || "",
232
+ disabled: props.disabled
233
+ };
234
+ items.push(entry);
235
+ entries.push(entry);
236
+ }
237
+ function visit(node) {
238
+ Children.forEach(node, (child) => {
239
+ if (!isValidElement(child)) return;
240
+ const type = child.type;
241
+ switch (type.__velliraDropdownPart) {
242
+ case "trigger":
243
+ triggerProps = child.props;
244
+ trigger = triggerProps.children;
245
+ return;
246
+ case "content":
247
+ contentProps = child.props;
248
+ visit(contentProps.children);
249
+ return;
250
+ case "group":
251
+ visit(child.props.children);
252
+ return;
253
+ case "label":
254
+ entries.push({
255
+ type: "label",
256
+ id: nextId("label"),
257
+ props: child.props
258
+ });
259
+ return;
260
+ case "separator":
261
+ entries.push({
262
+ type: "separator",
263
+ id: nextId("separator"),
264
+ props: child.props
265
+ });
266
+ return;
267
+ case "empty":
268
+ entries.push({
269
+ type: "empty",
270
+ id: nextId("empty"),
271
+ props: child.props
272
+ });
273
+ return;
274
+ case "loading":
275
+ entries.push({
276
+ type: "loading",
277
+ id: nextId("loading"),
278
+ props: child.props
279
+ });
280
+ return;
281
+ case "item":
282
+ pushItem(child.props);
283
+ return;
284
+ default:
285
+ visit(child.props.children);
286
+ }
287
+ });
288
+ }
289
+ visit(children);
290
+ return { contentProps, entries, items, trigger, triggerProps };
291
+ }
292
+ function getItemLabel(children) {
293
+ const labelParts = [];
294
+ Children.forEach(children, (child) => {
295
+ if (typeof child === "string" || typeof child === "number") {
296
+ labelParts.push(String(child));
297
+ }
298
+ });
299
+ return labelParts.join("").trim();
300
+ }
301
+
171
302
  // src/components/Dropdown/Item/DropdownItem.tsx
172
- import { cloneElement, isValidElement } from "react";
303
+ import { cloneElement, isValidElement as isValidElement2 } from "react";
173
304
  import { Pressable as Pressable2, Text as Text2 } from "react-native";
174
305
 
175
306
  // src/components/Dropdown/Item/DropdownItem.styles.ts
@@ -177,6 +308,7 @@ import { StyleSheet as StyleSheet3 } from "react-native";
177
308
  var createStyles3 = (theme) => StyleSheet3.create({
178
309
  item: {
179
310
  minWidth: 0,
311
+ minHeight: 44,
180
312
  alignItems: "center",
181
313
  flexDirection: "row",
182
314
  gap: theme.tokens.spacing[4],
@@ -235,7 +367,7 @@ function DropdownItem({
235
367
  const { theme } = useTheme();
236
368
  const styles = useThemeStyles(createStyles3);
237
369
  const renderColoredNode = (node, color) => {
238
- if (!isValidElement(node)) return node;
370
+ if (!isValidElement2(node)) return node;
239
371
  return cloneElement(node, { color });
240
372
  };
241
373
  const getContentColor = (pressed) => {
@@ -320,7 +452,7 @@ DropdownSeparator.displayName = "DropdownSeparator";
320
452
  // src/components/Dropdown/Trigger/DropdownTrigger.tsx
321
453
  import {
322
454
  cloneElement as cloneElement2,
323
- isValidElement as isValidElement2,
455
+ isValidElement as isValidElement3,
324
456
  useEffect,
325
457
  useRef,
326
458
  useState
@@ -431,6 +563,7 @@ import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
431
563
  function DropdownTrigger({
432
564
  label,
433
565
  trigger,
566
+ children,
434
567
  icon,
435
568
  arrowIcon,
436
569
  showArrow = true,
@@ -438,6 +571,7 @@ function DropdownTrigger({
438
571
  disabled = false,
439
572
  isOpen,
440
573
  triggerStyle,
574
+ triggerRef,
441
575
  accessibilityLabel,
442
576
  accessibilityHint,
443
577
  onPress
@@ -485,15 +619,34 @@ function DropdownTrigger({
485
619
  }
486
620
  );
487
621
  }
488
- if (!isValidElement2(node)) return node;
622
+ if (!isValidElement3(node)) return node;
489
623
  return cloneElement2(node, { color });
490
624
  };
491
625
  const contentColor = disabled ? theme.components.dropdown.trigger.disabled.fg : isPressed ? theme.components.dropdown.trigger.hover.fg : theme.components.dropdown.trigger.default.fg;
492
626
  const arrow = arrowIcon ? renderColoredNode(arrowIcon, contentColor) : /* @__PURE__ */ jsx6(ChevronDown, { width: 16, height: 16, color: contentColor });
493
627
  const renderedIcon = icon ? renderColoredNode(icon, contentColor) : null;
628
+ const triggerContent = trigger ?? children;
629
+ if (isValidElement3(triggerContent)) {
630
+ const child = triggerContent;
631
+ const isChildDisabled = disabled || child.props.disabled;
632
+ return cloneElement2(child, {
633
+ ref: triggerRef,
634
+ disabled: isChildDisabled,
635
+ accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : void 0),
636
+ accessibilityHint,
637
+ accessibilityState: { expanded: isOpen, disabled: isChildDisabled },
638
+ onPress: () => {
639
+ child.props.onPress?.();
640
+ if (!isChildDisabled) {
641
+ onPress();
642
+ }
643
+ }
644
+ });
645
+ }
494
646
  return /* @__PURE__ */ jsxs3(
495
647
  Pressable3,
496
648
  {
649
+ ref: triggerRef,
497
650
  disabled,
498
651
  accessibilityRole: "button",
499
652
  accessibilityLabel: accessibilityLabel ?? (typeof label === "string" ? label : void 0),
@@ -513,7 +666,7 @@ function DropdownTrigger({
513
666
  ],
514
667
  children: [
515
668
  hasIcon && /* @__PURE__ */ jsx6(View3, { style: styles.icon, children: renderedIcon }),
516
- !isIconOnly && (trigger ? renderColoredNode(trigger, contentColor) : /* @__PURE__ */ jsx6(
669
+ !isIconOnly && (triggerContent ? renderColoredNode(triggerContent, contentColor) : /* @__PURE__ */ jsx6(
517
670
  Text3,
518
671
  {
519
672
  numberOfLines: 1,
@@ -541,31 +694,38 @@ DropdownTrigger.displayName = "DropdownTrigger";
541
694
 
542
695
  // src/components/Dropdown/Dropdown.styles.ts
543
696
  import { StyleSheet as StyleSheet6 } from "react-native";
544
- var createStyles6 = () => StyleSheet6.create({
697
+ var createStyles6 = (theme) => StyleSheet6.create({
545
698
  root: {
546
699
  alignSelf: "flex-start"
700
+ },
701
+ emptyText: {
702
+ minHeight: 44,
703
+ paddingHorizontal: theme.tokens.spacing[3],
704
+ paddingVertical: theme.tokens.spacing[3],
705
+ color: theme.components.dropdown.item.disabled.fg,
706
+ fontFamily: theme.tokens.typography.family.regular,
707
+ fontSize: theme.tokens.typography.size.md,
708
+ lineHeight: theme.tokens.typography.lineHeight.md
547
709
  }
548
710
  });
549
711
 
550
- // src/components/Dropdown/types.ts
551
- var isMenuItem = (item) => item.type === void 0 || item.type === "item";
552
- var isGroup = (item) => item.type === "group";
553
- var isSeparator = (item) => item.type === "separator";
554
-
555
712
  // src/components/Dropdown/Dropdown.tsx
556
713
  import { jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
557
- function Dropdown({
714
+ function DropdownRoot({
715
+ children,
558
716
  label = "Menu",
559
717
  trigger,
560
718
  icon,
561
719
  arrowIcon,
562
720
  showArrow = true,
563
- items,
564
- onSelect,
565
721
  open,
566
722
  defaultOpen = false,
567
723
  onOpenChange,
724
+ presentation = "auto",
725
+ closeOnSelect = true,
568
726
  disabled = false,
727
+ loading = false,
728
+ loadingText = "Loading actions...",
569
729
  size = "md",
570
730
  style,
571
731
  triggerStyle,
@@ -576,13 +736,21 @@ function Dropdown({
576
736
  accessibilityHint
577
737
  }) {
578
738
  const styles = useThemeStyles(createStyles6);
739
+ const { width } = useWindowDimensions();
740
+ const triggerRef = useRef2(null);
741
+ const parsed = useMemo3(() => parseDropdownChildren(children), [children]);
742
+ const resolvedPresentation = presentation === "auto" ? width < 768 ? "sheet" : "popover" : presentation;
579
743
  const menuAccessibilityLabel = useMemo3(() => {
580
744
  if (accessibilityLabel) return accessibilityLabel;
581
745
  return typeof label === "string" ? label : "Menu";
582
746
  }, [accessibilityLabel, label]);
583
747
  const navigableItems = useMemo3(
584
- () => items.filter((item) => isMenuItem(item)),
585
- [items]
748
+ () => parsed.items.map((item) => ({
749
+ disabled: item.disabled,
750
+ label: item.label,
751
+ value: item.id
752
+ })),
753
+ [parsed.items]
586
754
  );
587
755
  const { isOpen, closeDropdown, toggleDropdown } = useDropdown({
588
756
  items: navigableItems,
@@ -590,32 +758,96 @@ function Dropdown({
590
758
  defaultOpen,
591
759
  disabled,
592
760
  onOpenChange,
593
- onSelect,
594
761
  getItemValue: (item) => item.value,
595
762
  getItemText: (item) => typeof item.label === "string" ? item.label : item.value
596
763
  });
764
+ useEffect2(() => {
765
+ if (!isOpen) return;
766
+ AccessibilityInfo.announceForAccessibility(
767
+ `${menuAccessibilityLabel} opened`
768
+ );
769
+ }, [isOpen, menuAccessibilityLabel]);
770
+ const focusTrigger = useCallback(() => {
771
+ if (typeof findNodeHandle !== "function") return;
772
+ const handle = findNodeHandle(triggerRef.current);
773
+ if (handle && AccessibilityInfo.setAccessibilityFocus) {
774
+ AccessibilityInfo.setAccessibilityFocus(handle);
775
+ }
776
+ }, []);
777
+ const closeAndFocusTrigger = useCallback(() => {
778
+ closeDropdown();
779
+ requestAnimationFrame(focusTrigger);
780
+ }, [closeDropdown, focusTrigger]);
597
781
  const handleSelect = useCallback(
598
- (value) => {
599
- onSelect?.(value);
600
- closeDropdown();
782
+ (entry) => {
783
+ if (entry.disabled || loading) return;
784
+ const event = createDropdownSelectEvent();
785
+ entry.props.onSelect?.(event);
786
+ const shouldClose = entry.props.closeOnSelect ?? closeOnSelect;
787
+ if (!event.defaultPrevented && shouldClose) {
788
+ closeAndFocusTrigger();
789
+ }
601
790
  },
602
- [closeDropdown, onSelect]
791
+ [closeAndFocusTrigger, closeOnSelect, loading]
603
792
  );
604
793
  const handleTriggerPress = useCallback(() => {
605
794
  toggleDropdown();
606
795
  }, [toggleDropdown]);
796
+ const renderEntry = useCallback(
797
+ ({ item }) => {
798
+ if (item.type === "label") {
799
+ return /* @__PURE__ */ jsx7(DropdownGroup, { label: item.props.children });
800
+ }
801
+ if (item.type === "separator") {
802
+ return /* @__PURE__ */ jsx7(DropdownSeparator, {});
803
+ }
804
+ if (item.type === "empty") {
805
+ return /* @__PURE__ */ jsx7(Text4, { style: styles.emptyText, children: item.props.children });
806
+ }
807
+ if (item.type === "loading") {
808
+ return /* @__PURE__ */ jsx7(Text4, { style: styles.emptyText, children: item.props.children });
809
+ }
810
+ return /* @__PURE__ */ jsx7(
811
+ DropdownItem,
812
+ {
813
+ label: item.props.children,
814
+ value: item.props.value ?? item.id,
815
+ icon: item.props.icon,
816
+ danger: item.props.danger,
817
+ disabled: item.props.disabled,
818
+ textWrap: item.props.textWrap,
819
+ itemStyle,
820
+ textStyle,
821
+ onSelect: () => handleSelect(item)
822
+ }
823
+ );
824
+ },
825
+ [handleSelect, itemStyle, styles.emptyText, textStyle]
826
+ );
827
+ const data = loading ? [
828
+ {
829
+ type: "loading",
830
+ id: "loading",
831
+ props: { children: loadingText }
832
+ }
833
+ ] : parsed.entries;
834
+ const contentStyleFromSlot = parsed.contentProps?.style;
835
+ const presentationFromSlot = parsed.contentProps?.presentation === "auto" ? void 0 : parsed.contentProps?.presentation;
607
836
  return /* @__PURE__ */ jsxs4(View4, { style: [styles.root, style], children: [
608
837
  /* @__PURE__ */ jsx7(
609
838
  DropdownTrigger,
610
839
  {
611
840
  label,
612
- trigger,
841
+ trigger: trigger ?? parsed.trigger,
613
842
  icon,
614
843
  arrowIcon,
615
844
  showArrow,
616
- disabled,
845
+ disabled: disabled || parsed.triggerProps?.disabled,
617
846
  isOpen,
618
847
  size,
848
+ triggerRef: (node) => {
849
+ triggerRef.current = node;
850
+ },
619
851
  triggerStyle,
620
852
  accessibilityLabel,
621
853
  accessibilityHint,
@@ -626,50 +858,82 @@ function Dropdown({
626
858
  DropdownContent,
627
859
  {
628
860
  isOpen,
629
- onClose: closeDropdown,
630
- contentStyle,
861
+ onClose: closeAndFocusTrigger,
862
+ contentStyle: [contentStyle, contentStyleFromSlot],
631
863
  accessibilityLabel: menuAccessibilityLabel,
632
- children: items.map((item, index) => {
633
- if (isGroup(item)) {
634
- return /* @__PURE__ */ jsx7(
635
- DropdownGroup,
636
- {
637
- label: item.label
638
- },
639
- `group-${item.label}-${index}`
640
- );
641
- }
642
- if (isSeparator(item)) {
643
- return /* @__PURE__ */ jsx7(DropdownSeparator, {}, `separator-${index}`);
644
- }
645
- if (!isMenuItem(item)) {
646
- return null;
864
+ presentation: presentationFromSlot ?? resolvedPresentation,
865
+ children: /* @__PURE__ */ jsx7(
866
+ FlatList,
867
+ {
868
+ data,
869
+ keyExtractor: (item) => item.id,
870
+ renderItem: renderEntry,
871
+ keyboardShouldPersistTaps: "handled",
872
+ removeClippedSubviews: data.length > 24
647
873
  }
648
- return /* @__PURE__ */ jsx7(
649
- DropdownItem,
650
- {
651
- label: item.label,
652
- value: item.value,
653
- icon: item.icon,
654
- danger: item.danger,
655
- disabled: item.disabled,
656
- textWrap: item.textWrap,
657
- itemStyle,
658
- textStyle,
659
- onSelect: handleSelect
660
- },
661
- `${item.value}-${index}`
662
- );
663
- })
874
+ )
664
875
  }
665
876
  )
666
877
  ] });
667
878
  }
668
- Dropdown.displayName = "Dropdown";
879
+ DropdownRoot.displayName = "Dropdown";
880
+ function createDropdownSelectEvent() {
881
+ let defaultPrevented = false;
882
+ return {
883
+ preventDefault: () => {
884
+ defaultPrevented = true;
885
+ },
886
+ get defaultPrevented() {
887
+ return defaultPrevented;
888
+ }
889
+ };
890
+ }
891
+ var DropdownTriggerSlot = createDropdownSlot(
892
+ "trigger",
893
+ "Dropdown.Trigger"
894
+ );
895
+ var DropdownContentSlot = createDropdownSlot(
896
+ "content",
897
+ "Dropdown.Content"
898
+ );
899
+ var DropdownItemSlot = createDropdownSlot(
900
+ "item",
901
+ "Dropdown.Item"
902
+ );
903
+ var DropdownGroupSlot = createDropdownSlot(
904
+ "group",
905
+ "Dropdown.Group"
906
+ );
907
+ var DropdownLabelSlot = createDropdownSlot(
908
+ "label",
909
+ "Dropdown.Label"
910
+ );
911
+ var DropdownSeparatorSlot = createDropdownSlot(
912
+ "separator",
913
+ "Dropdown.Separator"
914
+ );
915
+ var DropdownEmptySlot = createDropdownSlot(
916
+ "empty",
917
+ "Dropdown.Empty"
918
+ );
919
+ var DropdownLoadingSlot = createDropdownSlot(
920
+ "loading",
921
+ "Dropdown.Loading"
922
+ );
923
+ var Dropdown = Object.assign(DropdownRoot, {
924
+ Trigger: DropdownTriggerSlot,
925
+ Content: DropdownContentSlot,
926
+ Item: DropdownItemSlot,
927
+ Group: DropdownGroupSlot,
928
+ Label: DropdownLabelSlot,
929
+ Separator: DropdownSeparatorSlot,
930
+ Empty: DropdownEmptySlot,
931
+ Loading: DropdownLoadingSlot
932
+ });
669
933
 
670
934
  // src/components/Modal/Body/ModalBody.tsx
671
- import { Children, cloneElement as cloneElement3, isValidElement as isValidElement3 } from "react";
672
- import { Text as Text4, View as View5 } from "react-native";
935
+ import { Children as Children2, cloneElement as cloneElement3, isValidElement as isValidElement4 } from "react";
936
+ import { Text as Text5, View as View5 } from "react-native";
673
937
 
674
938
  // src/components/Modal/Body/ModalBody.styles.ts
675
939
  import { StyleSheet as StyleSheet7 } from "react-native";
@@ -693,10 +957,10 @@ var createStyles7 = (theme) => StyleSheet7.create({
693
957
 
694
958
  // src/components/Modal/Body/ModalBody.tsx
695
959
  import { jsx as jsx8 } from "react/jsx-runtime";
696
- var isTextElement = (child) => isValidElement3(child) && child.type === Text4;
697
- var renderBodyChildren = (children, textStyle) => Children.map(children, (child) => {
960
+ var isTextElement = (child) => isValidElement4(child) && child.type === Text5;
961
+ var renderBodyChildren = (children, textStyle) => Children2.map(children, (child) => {
698
962
  if (typeof child === "string" || typeof child === "number") {
699
- return /* @__PURE__ */ jsx8(Text4, { style: textStyle, children: child });
963
+ return /* @__PURE__ */ jsx8(Text5, { style: textStyle, children: child });
700
964
  }
701
965
  if (!isTextElement(child)) {
702
966
  return child;
@@ -770,7 +1034,7 @@ ModalFooter.displayName = "ModalFooter";
770
1034
 
771
1035
  // src/components/Modal/Header/ModalHeader.tsx
772
1036
  import { Close } from "@vellira-ui/icons";
773
- import { Pressable as Pressable4, Text as Text5, View as View8 } from "react-native";
1037
+ import { Pressable as Pressable4, Text as Text6, View as View8 } from "react-native";
774
1038
 
775
1039
  // src/components/Modal/ModalContext.tsx
776
1040
  import { createContext as createContext2, useContext as useContext2 } from "react";
@@ -829,7 +1093,7 @@ var ModalHeader = ({
829
1093
  const styles = useThemeStyles(createStyles10);
830
1094
  const { onClose } = useModalContext();
831
1095
  return /* @__PURE__ */ jsxs5(View8, { style: [styles.header, style], children: [
832
- /* @__PURE__ */ jsx11(Text5, { style: [styles.title, textStyle], children }),
1096
+ /* @__PURE__ */ jsx11(Text6, { style: [styles.title, textStyle], children }),
833
1097
  onClose && /* @__PURE__ */ jsx11(
834
1098
  Pressable4,
835
1099
  {
@@ -945,7 +1209,7 @@ import { View as View11 } from "react-native";
945
1209
 
946
1210
  // src/patterns/FormField/FormField.tsx
947
1211
  import { useId } from "react";
948
- import { Text as Text6, View as View10 } from "react-native";
1212
+ import { Text as Text7, View as View10 } from "react-native";
949
1213
 
950
1214
  // src/patterns/FormField/FormField.styles.ts
951
1215
  import { StyleSheet as StyleSheet12 } from "react-native";
@@ -1055,6 +1319,8 @@ function FormField({
1055
1319
  labelId,
1056
1320
  descriptionId,
1057
1321
  errorId,
1322
+ description,
1323
+ error,
1058
1324
  required,
1059
1325
  disabled,
1060
1326
  invalid: isInvalid,
@@ -1070,7 +1336,7 @@ function FormField({
1070
1336
  style: [styles.root, { gap: sizeTokens.gap }, style],
1071
1337
  children: [
1072
1338
  label && (typeof label === "string" || typeof label === "number" ? /* @__PURE__ */ jsxs7(
1073
- Text6,
1339
+ Text7,
1074
1340
  {
1075
1341
  style: [
1076
1342
  styles.label,
@@ -1084,7 +1350,7 @@ function FormField({
1084
1350
  children: [
1085
1351
  label,
1086
1352
  required && /* @__PURE__ */ jsx14(
1087
- Text6,
1353
+ Text7,
1088
1354
  {
1089
1355
  style: styles.required,
1090
1356
  accessible: false,
@@ -1093,7 +1359,7 @@ function FormField({
1093
1359
  }
1094
1360
  ),
1095
1361
  !required && optionalText && /* @__PURE__ */ jsx14(
1096
- Text6,
1362
+ Text7,
1097
1363
  {
1098
1364
  style: [
1099
1365
  styles.optional,
@@ -1106,7 +1372,7 @@ function FormField({
1106
1372
  }
1107
1373
  ),
1108
1374
  labelInfo && /* @__PURE__ */ jsx14(
1109
- Text6,
1375
+ Text7,
1110
1376
  {
1111
1377
  style: [
1112
1378
  styles.labelInfo,
@@ -1123,7 +1389,7 @@ function FormField({
1123
1389
  ) : /* @__PURE__ */ jsxs7(View10, { style: styles.customLabel, children: [
1124
1390
  label,
1125
1391
  required && /* @__PURE__ */ jsx14(
1126
- Text6,
1392
+ Text7,
1127
1393
  {
1128
1394
  style: styles.required,
1129
1395
  accessible: false,
@@ -1135,7 +1401,7 @@ function FormField({
1135
1401
  labelInfo
1136
1402
  ] })),
1137
1403
  description && (typeof description === "string" || typeof description === "number" ? /* @__PURE__ */ jsx14(
1138
- Text6,
1404
+ Text7,
1139
1405
  {
1140
1406
  style: [
1141
1407
  styles.description,
@@ -1151,7 +1417,7 @@ function FormField({
1151
1417
  ) : description),
1152
1418
  /* @__PURE__ */ jsx14(FormFieldContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx14(View10, { style: [styles.control, { gap: sizeTokens.gap }, controlStyle], children }) }),
1153
1419
  error && (typeof error === "string" || typeof error === "number" ? /* @__PURE__ */ jsx14(
1154
- Text6,
1420
+ Text7,
1155
1421
  {
1156
1422
  accessibilityLiveRegion: "polite",
1157
1423
  style: [
@@ -1286,184 +1552,1543 @@ var RadioGroup = forwardRef(
1286
1552
  );
1287
1553
  RadioGroup.displayName = "RadioGroup";
1288
1554
 
1289
- // src/components/Select/Select.tsx
1290
- import { useEffect as useEffect2, useState as useState2 } from "react";
1291
- import { Picker } from "@react-native-picker/picker";
1292
- import { useSelect } from "@vellira-ui/core";
1293
- import { Modal as Modal3, Pressable as Pressable7, Text as Text8, View as View13 } from "react-native";
1555
+ // src/components/Select/Content/SelectContent.tsx
1556
+ import { useEffect as useEffect4, useRef as useRef3, useState as useState2 } from "react";
1557
+ import { FlatList as FlatList2, Pressable as Pressable10, Text as Text12, View as View21 } from "react-native";
1558
+
1559
+ // src/components/Select/Group/SelectGroup.tsx
1560
+ import { Pressable as Pressable6, Text as Text8 } from "react-native";
1561
+
1562
+ // src/components/Select/internal/SelectCollection.ts
1563
+ import { Children as Children3, isValidElement as isValidElement5 } from "react";
1564
+
1565
+ // src/components/Select/internal/types.ts
1566
+ var selectSlotName = /* @__PURE__ */ Symbol("VelliraNativeSelectSlot");
1294
1567
 
1295
- // src/components/Select/SelectTrigger/SelectTrigger.tsx
1296
- import { ChevronDown as ChevronDown2 } from "@vellira-ui/icons";
1297
- import { Pressable as Pressable6, Text as Text7, View as View12 } from "react-native";
1568
+ // src/components/Select/internal/SelectCollection.ts
1569
+ var createSelectSlot = (name, displayName) => {
1570
+ const Slot = (_props) => null;
1571
+ Slot[selectSlotName] = name;
1572
+ Slot.displayName = displayName;
1573
+ return Slot;
1574
+ };
1575
+ var getSelectSlot = (type) => type?.[selectSlotName];
1576
+ var defaultSelectFilter = (option, query) => option.label.toLowerCase().includes(query.trim().toLowerCase());
1577
+ var getTextFromNode = (node) => {
1578
+ if (typeof node === "string" || typeof node === "number") {
1579
+ return String(node);
1580
+ }
1581
+ return void 0;
1582
+ };
1583
+ var getGroupLabel = (props) => {
1584
+ if (props.label) return props.label;
1585
+ let label;
1586
+ Children3.forEach(props.children, (child) => {
1587
+ if (label || !isValidElement5(child)) return;
1588
+ if (getSelectSlot(child.type) === "label") {
1589
+ label = getTextFromNode(child.props.children);
1590
+ }
1591
+ });
1592
+ return label;
1593
+ };
1594
+ var getGroupItemValues = (children) => {
1595
+ const values = [];
1596
+ const visit = (node) => {
1597
+ Children3.forEach(node, (child) => {
1598
+ if (!isValidElement5(child)) return;
1599
+ const slot = getSelectSlot(child.type);
1600
+ if (slot === "content") {
1601
+ visit(child.props.children);
1602
+ return;
1603
+ }
1604
+ if (slot === "group") {
1605
+ visit(child.props.children);
1606
+ return;
1607
+ }
1608
+ if (slot === "item") {
1609
+ values.push(child.props.value);
1610
+ }
1611
+ });
1612
+ };
1613
+ visit(children);
1614
+ return values;
1615
+ };
1616
+ var parseSelectChildren = (children) => {
1617
+ const options = [];
1618
+ const rows = [];
1619
+ let searchable = false;
1620
+ let searchPlaceholder;
1621
+ let empty;
1622
+ let loading;
1623
+ const visit = (node, group) => {
1624
+ Children3.forEach(node, (child) => {
1625
+ if (!isValidElement5(child)) return;
1626
+ const slot = getSelectSlot(child.type);
1627
+ if (slot === "content") {
1628
+ visit(child.props.children, group);
1629
+ return;
1630
+ }
1631
+ if (slot === "search") {
1632
+ searchable = true;
1633
+ searchPlaceholder = child.props.placeholder;
1634
+ return;
1635
+ }
1636
+ if (slot === "empty") {
1637
+ empty = child.props.children;
1638
+ return;
1639
+ }
1640
+ if (slot === "loading") {
1641
+ loading = child.props.children;
1642
+ return;
1643
+ }
1644
+ if (slot === "group") {
1645
+ const props = child.props;
1646
+ const groupLabel = getGroupLabel(props);
1647
+ if (groupLabel) {
1648
+ rows.push({
1649
+ type: "group",
1650
+ key: `group-${groupLabel}-${rows.length}`,
1651
+ label: groupLabel,
1652
+ selectable: props.selectable,
1653
+ selectLabel: props.selectLabel,
1654
+ itemValues: getGroupItemValues(props.children)
1655
+ });
1656
+ }
1657
+ visit(props.children, groupLabel);
1658
+ return;
1659
+ }
1660
+ if (slot === "label") {
1661
+ return;
1662
+ }
1663
+ if (slot === "separator") {
1664
+ rows.push({ type: "separator", key: `separator-${rows.length}` });
1665
+ return;
1666
+ }
1667
+ if (slot === "item") {
1668
+ const props = child.props;
1669
+ const option = {
1670
+ value: props.value,
1671
+ label: props.label,
1672
+ disabled: props.disabled,
1673
+ description: props.description,
1674
+ icon: props.icon,
1675
+ badge: props.badge,
1676
+ color: props.color,
1677
+ accessibilityLabel: props.accessibilityLabel,
1678
+ accessibilityHint: props.accessibilityHint ?? group
1679
+ };
1680
+ options.push(option);
1681
+ rows.push({
1682
+ type: "item",
1683
+ key: `item-${props.value}`,
1684
+ option
1685
+ });
1686
+ }
1687
+ });
1688
+ };
1689
+ visit(children);
1690
+ return { options, rows, searchable, searchPlaceholder, empty, loading };
1691
+ };
1298
1692
 
1299
- // src/components/Select/SelectTrigger/SelectTrigger.styles.ts
1693
+ // src/components/Select/Group/SelectGroup.styles.ts
1300
1694
  import { StyleSheet as StyleSheet14 } from "react-native";
1301
- var createStyles14 = (theme) => StyleSheet14.create({
1302
- trigger: {
1303
- width: "100%",
1304
- minWidth: 0,
1305
- alignItems: "center",
1306
- justifyContent: "space-between",
1307
- flexDirection: "row",
1308
- paddingHorizontal: theme.tokens.spacing[4],
1309
- paddingVertical: theme.tokens.spacing[3],
1310
- backgroundColor: theme.components.select.trigger.default.bg,
1311
- borderColor: theme.components.select.trigger.default.border,
1312
- borderRadius: theme.tokens.radius.md,
1313
- borderWidth: 1
1695
+ var createGroupStyles = (theme) => StyleSheet14.create({
1696
+ groupLabel: {
1697
+ paddingHorizontal: theme.tokens.spacing[3],
1698
+ paddingTop: theme.tokens.spacing[4],
1699
+ paddingBottom: theme.tokens.spacing[1],
1700
+ color: theme.components.select.dropdown.groupLabel.fg,
1701
+ fontFamily: theme.tokens.typography.family.medium,
1702
+ fontSize: theme.tokens.typography.size.xs,
1703
+ letterSpacing: 0.6,
1704
+ textTransform: "uppercase"
1314
1705
  },
1315
- sm: {
1706
+ groupAction: {
1316
1707
  minHeight: 36,
1708
+ flexDirection: "row",
1709
+ alignItems: "center",
1710
+ justifyContent: "space-between",
1711
+ gap: theme.tokens.spacing[2],
1317
1712
  paddingHorizontal: theme.tokens.spacing[3],
1318
- paddingVertical: theme.tokens.spacing[2]
1319
- },
1320
- md: {
1321
- minHeight: 44,
1322
- paddingHorizontal: theme.tokens.spacing[4],
1323
- paddingVertical: theme.tokens.spacing[3]
1324
- },
1325
- lg: {
1326
- minHeight: 52,
1327
- paddingHorizontal: theme.tokens.spacing[5],
1328
- paddingVertical: theme.tokens.spacing[4]
1329
- },
1330
- textSm: {
1331
- fontSize: theme.tokens.typography.size.sm,
1332
- lineHeight: theme.tokens.typography.lineHeight.sm
1333
- },
1334
- textMd: {
1335
- fontSize: theme.tokens.typography.size.md,
1336
- lineHeight: theme.tokens.typography.lineHeight.md
1337
- },
1338
- textLg: {
1339
- fontSize: theme.tokens.typography.size.lg,
1340
- lineHeight: theme.tokens.typography.lineHeight.lg
1341
- },
1342
- triggerOpen: {
1343
- backgroundColor: theme.components.select.trigger.focus.bg,
1344
- borderColor: theme.components.select.trigger.focus.border,
1345
- borderWidth: 2
1346
- },
1347
- triggerError: {
1348
- borderColor: theme.components.select.trigger.error.border
1349
- },
1350
- triggerErrorOpen: {
1351
- borderColor: theme.components.select.trigger.error.border,
1352
- shadowColor: theme.components.select.trigger.error.ring,
1353
- shadowOffset: {
1354
- width: 0,
1355
- height: 0
1356
- },
1357
- shadowOpacity: 0.2,
1358
- shadowRadius: 6,
1359
- elevation: 1
1360
- },
1361
- textOpen: {
1362
- color: theme.components.select.trigger.focus.fg
1363
- },
1364
- triggerDisabled: {
1365
- backgroundColor: theme.components.select.trigger.disabled.bg,
1366
- borderColor: theme.components.select.trigger.disabled.border
1367
- },
1368
- text: {
1369
- flex: 1,
1370
- minWidth: 0,
1371
- color: theme.components.select.trigger.default.fg,
1372
- fontFamily: theme.tokens.typography.family.regular
1373
- },
1374
- textDisabled: {
1375
- color: theme.components.select.trigger.disabled.fg
1713
+ paddingTop: theme.tokens.spacing[4],
1714
+ paddingBottom: theme.tokens.spacing[1]
1376
1715
  },
1377
- placeholder: {
1378
- color: theme.components.select.trigger.placeholder.fg
1716
+ groupActionText: {
1717
+ color: theme.components.select.dropdown.groupLabel.fg,
1718
+ fontFamily: theme.tokens.typography.family.medium,
1719
+ fontSize: theme.tokens.typography.size.xs,
1720
+ letterSpacing: 0.6,
1721
+ textTransform: "uppercase"
1379
1722
  },
1380
- icon: {
1381
- width: 16,
1382
- height: 16,
1383
- marginLeft: theme.tokens.spacing[2],
1384
- alignItems: "center",
1385
- justifyContent: "center"
1723
+ groupActionMeta: {
1724
+ color: theme.components.select.option.default.fg,
1725
+ fontFamily: theme.tokens.typography.family.medium,
1726
+ fontSize: theme.tokens.typography.size.xs
1386
1727
  },
1387
- iconOpen: {
1388
- transform: [{ rotate: "180deg" }]
1728
+ separator: {
1729
+ height: 1,
1730
+ marginHorizontal: theme.tokens.spacing[3],
1731
+ marginVertical: theme.tokens.spacing[2],
1732
+ backgroundColor: theme.components.select.dropdown.separator.bg
1389
1733
  }
1390
1734
  });
1391
1735
 
1392
- // src/components/Select/SelectTrigger/SelectTrigger.tsx
1736
+ // src/components/Select/Group/SelectGroup.tsx
1393
1737
  import { jsx as jsx16, jsxs as jsxs8 } from "react/jsx-runtime";
1394
- function SelectTrigger({
1395
- displayText,
1396
- isPlaceholder,
1397
- isOpen,
1398
- size = "md",
1399
- disabled = false,
1400
- required = false,
1401
- hasError = false,
1402
- accessibilityLabel,
1403
- accessibilityHint,
1404
- triggerStyle,
1405
- textStyle,
1738
+ var SelectGroup = createSelectSlot(
1739
+ "group",
1740
+ "Select.Group"
1741
+ );
1742
+ var SelectGroupLabelRow = ({ label }) => {
1743
+ const styles = useThemeStyles(createGroupStyles);
1744
+ return /* @__PURE__ */ jsx16(Text8, { style: styles.groupLabel, children: label });
1745
+ };
1746
+ var SelectGroupActionRow = ({
1747
+ label,
1748
+ selectLabel,
1749
+ selectedCount,
1750
+ itemCount,
1406
1751
  onPress
1407
- }) {
1408
- const { theme } = useTheme();
1409
- const styles = useThemeStyles(createStyles14);
1410
- const textSizeStyle = {
1411
- sm: styles.textSm,
1412
- md: styles.textMd,
1413
- lg: styles.textLg
1414
- };
1415
- const resolvedAccessibilityHint = accessibilityHint ?? (hasError ? "Invalid selection. Opens a picker" : required ? "Required. Opens a picker" : "Opens a picker");
1752
+ }) => {
1753
+ const styles = useThemeStyles(createGroupStyles);
1754
+ const isSelected = itemCount > 0 && selectedCount === itemCount;
1755
+ const isMixed = selectedCount > 0 && selectedCount < itemCount;
1756
+ const resolvedLabel = selectLabel ?? label;
1416
1757
  return /* @__PURE__ */ jsxs8(
1417
1758
  Pressable6,
1418
1759
  {
1419
- disabled,
1420
1760
  accessibilityRole: "button",
1421
- accessibilityLabel,
1422
- accessibilityHint: resolvedAccessibilityHint,
1761
+ accessibilityLabel: resolvedLabel,
1762
+ accessibilityHint: `Selects all options in ${label}`,
1423
1763
  accessibilityState: {
1424
- expanded: isOpen,
1425
- disabled
1764
+ selected: isSelected,
1765
+ checked: isMixed ? "mixed" : isSelected,
1766
+ disabled: itemCount === 0
1426
1767
  },
1768
+ disabled: itemCount === 0,
1427
1769
  onPress,
1428
- style: [
1429
- styles.trigger,
1430
- styles[size],
1431
- isOpen && styles.triggerOpen,
1432
- hasError && styles.triggerError,
1433
- disabled && styles.triggerDisabled,
1770
+ style: styles.groupAction,
1771
+ children: [
1772
+ /* @__PURE__ */ jsx16(Text8, { style: styles.groupActionText, children: resolvedLabel }),
1773
+ /* @__PURE__ */ jsxs8(Text8, { style: styles.groupActionMeta, children: [
1774
+ selectedCount,
1775
+ "/",
1776
+ itemCount
1777
+ ] })
1778
+ ]
1779
+ }
1780
+ );
1781
+ };
1782
+ SelectGroupLabelRow.displayName = "Select.GroupLabelRow";
1783
+ SelectGroupActionRow.displayName = "Select.GroupActionRow";
1784
+
1785
+ // src/components/Select/Group/SelectLabel.tsx
1786
+ var SelectLabel = createSelectSlot(
1787
+ "label",
1788
+ "Select.Label"
1789
+ );
1790
+
1791
+ // src/components/Select/Group/SelectSeparator.tsx
1792
+ import { View as View12 } from "react-native";
1793
+ import { jsx as jsx17 } from "react/jsx-runtime";
1794
+ var SelectSeparator = createSelectSlot(
1795
+ "separator",
1796
+ "Select.Separator"
1797
+ );
1798
+ var SelectSeparatorRow = () => {
1799
+ const styles = useThemeStyles(createGroupStyles);
1800
+ return /* @__PURE__ */ jsx17(View12, { style: styles.separator });
1801
+ };
1802
+ SelectSeparatorRow.displayName = "Select.SeparatorRow";
1803
+
1804
+ // src/components/Select/internal/SelectContext.tsx
1805
+ import { createContext as createContext5, useContext as useContext5 } from "react";
1806
+ var SelectContext = createContext5(null);
1807
+ var useSelectContext = () => {
1808
+ const context = useContext5(SelectContext);
1809
+ if (!context) {
1810
+ throw new Error("Select compound components must be used inside Select");
1811
+ }
1812
+ return context;
1813
+ };
1814
+
1815
+ // src/components/Select/Item/SelectItem.tsx
1816
+ import { cloneElement as cloneElement4, isValidElement as isValidElement6 } from "react";
1817
+ import { Check } from "@vellira-ui/icons";
1818
+ import { Pressable as Pressable7, Text as Text9, View as View13 } from "react-native";
1819
+
1820
+ // src/components/Select/Item/SelectItem.styles.ts
1821
+ import { StyleSheet as StyleSheet15 } from "react-native";
1822
+ var createItemStyles = (theme) => StyleSheet15.create({
1823
+ option: {
1824
+ minHeight: 44,
1825
+ flexDirection: "row",
1826
+ alignItems: "center",
1827
+ gap: theme.tokens.spacing[3],
1828
+ paddingHorizontal: theme.tokens.spacing[3],
1829
+ paddingVertical: theme.tokens.spacing[2],
1830
+ marginBottom: 2,
1831
+ borderRadius: theme.tokens.radius.md,
1832
+ borderWidth: 1,
1833
+ borderColor: "transparent"
1834
+ },
1835
+ optionDisabled: {
1836
+ opacity: 0.55
1837
+ },
1838
+ optionIcon: {
1839
+ width: 22,
1840
+ minWidth: 22,
1841
+ alignItems: "center",
1842
+ justifyContent: "center"
1843
+ },
1844
+ optionTextWrap: {
1845
+ flex: 1,
1846
+ minWidth: 0,
1847
+ gap: 2
1848
+ },
1849
+ optionLabel: {
1850
+ fontFamily: theme.tokens.typography.family.medium,
1851
+ fontSize: theme.tokens.typography.size.md,
1852
+ lineHeight: theme.tokens.typography.lineHeight.md
1853
+ },
1854
+ optionDescription: {
1855
+ color: theme.components.select.option.description.fg,
1856
+ fontFamily: theme.tokens.typography.family.regular,
1857
+ fontSize: theme.tokens.typography.size.sm,
1858
+ lineHeight: theme.tokens.typography.lineHeight.sm
1859
+ },
1860
+ badge: {
1861
+ paddingHorizontal: theme.tokens.spacing[2],
1862
+ paddingVertical: 2,
1863
+ borderRadius: 999,
1864
+ borderWidth: 1
1865
+ },
1866
+ badgeText: {
1867
+ fontFamily: theme.tokens.typography.family.medium,
1868
+ fontSize: theme.tokens.typography.size.xs,
1869
+ lineHeight: theme.tokens.typography.lineHeight.xs
1870
+ },
1871
+ check: {
1872
+ width: 20,
1873
+ height: 20,
1874
+ alignItems: "center",
1875
+ justifyContent: "center"
1876
+ }
1877
+ });
1878
+
1879
+ // src/components/Select/Item/SelectItem.tsx
1880
+ import { Fragment as Fragment2, jsx as jsx18, jsxs as jsxs9 } from "react/jsx-runtime";
1881
+ var renderNodeOrText = (node, textStyle, fallback) => {
1882
+ if (typeof node === "string" || typeof node === "number") {
1883
+ return /* @__PURE__ */ jsx18(Text9, { style: textStyle, children: node });
1884
+ }
1885
+ if (isValidElement6(node) && node.type === Text9) {
1886
+ return cloneElement4(node, {
1887
+ style: [textStyle, node.props.style]
1888
+ });
1889
+ }
1890
+ return node ?? (fallback ? /* @__PURE__ */ jsx18(Text9, { style: textStyle, children: fallback }) : null);
1891
+ };
1892
+ var SelectItem = createSelectSlot(
1893
+ "item",
1894
+ "Select.Item"
1895
+ );
1896
+ var SelectItemRow = ({
1897
+ option,
1898
+ isSelected,
1899
+ isDisabled,
1900
+ optionStyle,
1901
+ onSelect
1902
+ }) => {
1903
+ const { theme } = useTheme();
1904
+ const styles = useThemeStyles(createItemStyles);
1905
+ const { color, variant, renderOption } = useSelectContext();
1906
+ const optionPalette = theme.components.select[option.color ?? color][variant].option;
1907
+ const getOptionState = (pressed) => {
1908
+ if (isDisabled) return theme.components.select.option.disabled;
1909
+ if (isSelected) {
1910
+ return pressed ? optionPalette.selectedPressed : optionPalette.selected;
1911
+ }
1912
+ return pressed ? optionPalette.pressed : theme.components.select.option.default;
1913
+ };
1914
+ return /* @__PURE__ */ jsx18(
1915
+ Pressable7,
1916
+ {
1917
+ disabled: isDisabled,
1918
+ accessibilityRole: "button",
1919
+ accessibilityLabel: option.accessibilityLabel ?? option.label,
1920
+ accessibilityHint: option.accessibilityHint,
1921
+ accessibilityState: {
1922
+ selected: isSelected,
1923
+ disabled: isDisabled
1924
+ },
1925
+ onPress: () => onSelect(option),
1926
+ style: ({ pressed }) => {
1927
+ const optionState = getOptionState(pressed);
1928
+ return [
1929
+ styles.option,
1930
+ {
1931
+ backgroundColor: optionState.bg,
1932
+ borderColor: optionState.border
1933
+ },
1934
+ isDisabled && styles.optionDisabled,
1935
+ optionStyle
1936
+ ];
1937
+ },
1938
+ children: ({ pressed }) => {
1939
+ const optionState = getOptionState(pressed);
1940
+ const optionFg = optionState.fg;
1941
+ const descriptionFg = isSelected || pressed ? optionFg : theme.components.select.option.description.fg;
1942
+ return renderOption ? renderNodeOrText(
1943
+ renderOption(option, {
1944
+ selected: isSelected,
1945
+ disabled: isDisabled
1946
+ }),
1947
+ [styles.optionLabel, { color: optionFg }]
1948
+ ) : /* @__PURE__ */ jsxs9(Fragment2, { children: [
1949
+ option.icon && /* @__PURE__ */ jsx18(View13, { style: styles.optionIcon, children: isValidElement6(option.icon) ? cloneElement4(
1950
+ option.icon,
1951
+ {
1952
+ color: optionFg,
1953
+ size: 18
1954
+ }
1955
+ ) : option.icon }),
1956
+ /* @__PURE__ */ jsxs9(View13, { style: styles.optionTextWrap, children: [
1957
+ /* @__PURE__ */ jsx18(
1958
+ Text9,
1959
+ {
1960
+ numberOfLines: 1,
1961
+ style: [styles.optionLabel, { color: optionFg }],
1962
+ children: option.label
1963
+ }
1964
+ ),
1965
+ option.description && /* @__PURE__ */ jsx18(
1966
+ Text9,
1967
+ {
1968
+ numberOfLines: 2,
1969
+ style: [styles.optionDescription, { color: descriptionFg }],
1970
+ children: option.description
1971
+ }
1972
+ )
1973
+ ] }),
1974
+ option.badge && /* @__PURE__ */ jsx18(
1975
+ View13,
1976
+ {
1977
+ style: [
1978
+ styles.badge,
1979
+ {
1980
+ backgroundColor: optionPalette.badge.bg,
1981
+ borderColor: optionPalette.badge.border
1982
+ }
1983
+ ],
1984
+ children: renderNodeOrText(option.badge, [
1985
+ styles.badgeText,
1986
+ { color: optionPalette.badge.fg }
1987
+ ])
1988
+ }
1989
+ ),
1990
+ isSelected && /* @__PURE__ */ jsx18(View13, { style: styles.check, children: /* @__PURE__ */ jsx18(Check, { width: 16, height: 16, color: optionFg }) })
1991
+ ] });
1992
+ }
1993
+ }
1994
+ );
1995
+ };
1996
+ SelectItemRow.displayName = "Select.ItemRow";
1997
+
1998
+ // src/components/Select/Item/SelectItemBadge.tsx
1999
+ var SelectItemBadge = createSelectSlot(
2000
+ "itemBadge",
2001
+ "Select.ItemBadge"
2002
+ );
2003
+
2004
+ // src/components/Select/Item/SelectItemDescription.tsx
2005
+ var SelectItemDescription = createSelectSlot(
2006
+ "itemDescription",
2007
+ "Select.ItemDescription"
2008
+ );
2009
+
2010
+ // src/components/Select/Item/SelectItemIcon.tsx
2011
+ var SelectItemIcon = createSelectSlot(
2012
+ "itemIcon",
2013
+ "Select.ItemIcon"
2014
+ );
2015
+
2016
+ // src/components/Select/Presentation/SelectBackdrop.tsx
2017
+ import { Pressable as Pressable8 } from "react-native";
2018
+
2019
+ // src/components/Select/Presentation/SelectPresentation.styles.ts
2020
+ import { StyleSheet as StyleSheet16 } from "react-native";
2021
+ var createPresentationStyles = (theme) => StyleSheet16.create({
2022
+ modalRoot: {
2023
+ flex: 1
2024
+ },
2025
+ sheetRoot: {
2026
+ justifyContent: "flex-end"
2027
+ },
2028
+ modalPresentationRoot: {
2029
+ alignItems: "center",
2030
+ justifyContent: "center",
2031
+ padding: theme.tokens.spacing[4]
2032
+ },
2033
+ popoverRoot: {
2034
+ padding: theme.tokens.spacing[4]
2035
+ },
2036
+ popoverRootTop: {
2037
+ justifyContent: "flex-start"
2038
+ },
2039
+ popoverRootBottom: {
2040
+ justifyContent: "flex-end"
2041
+ },
2042
+ backdrop: {
2043
+ ...StyleSheet16.absoluteFill,
2044
+ backgroundColor: theme.semantic.overlay.backdrop
2045
+ },
2046
+ content: {
2047
+ overflow: "hidden",
2048
+ backgroundColor: theme.components.select.dropdown.bg,
2049
+ borderColor: theme.components.select.dropdown.border,
2050
+ borderWidth: 1
2051
+ },
2052
+ sheet: {
2053
+ maxHeight: "74%",
2054
+ borderTopLeftRadius: theme.tokens.radius.lg,
2055
+ borderTopRightRadius: theme.tokens.radius.lg,
2056
+ borderBottomWidth: 0
2057
+ },
2058
+ modalPresentation: {
2059
+ width: "100%",
2060
+ maxWidth: 420,
2061
+ maxHeight: "74%",
2062
+ borderRadius: theme.tokens.radius.lg
2063
+ },
2064
+ popover: {
2065
+ width: "100%",
2066
+ maxWidth: 420,
2067
+ maxHeight: "60%",
2068
+ alignSelf: "center",
2069
+ borderRadius: theme.tokens.radius.lg
2070
+ },
2071
+ popoverTop: {
2072
+ marginBottom: theme.tokens.spacing[8],
2073
+ alignSelf: "center"
2074
+ },
2075
+ popoverBottom: {
2076
+ marginTop: theme.tokens.spacing[8],
2077
+ alignSelf: "center"
2078
+ },
2079
+ handleWrap: {
2080
+ alignItems: "center",
2081
+ paddingTop: theme.tokens.spacing[3]
2082
+ },
2083
+ handle: {
2084
+ width: 44,
2085
+ height: 4,
2086
+ borderRadius: 999,
2087
+ backgroundColor: theme.semantic.border.muted
2088
+ }
2089
+ });
2090
+
2091
+ // src/components/Select/Presentation/SelectBackdrop.tsx
2092
+ import { jsx as jsx19 } from "react/jsx-runtime";
2093
+ var SelectBackdrop = ({
2094
+ onClose,
2095
+ dismissOnBackdropPress
2096
+ }) => {
2097
+ const styles = useThemeStyles(createPresentationStyles);
2098
+ return /* @__PURE__ */ jsx19(
2099
+ Pressable8,
2100
+ {
2101
+ style: styles.backdrop,
2102
+ onPress: dismissOnBackdropPress ? onClose : void 0,
2103
+ accessibilityRole: "button",
2104
+ accessibilityLabel: "Dismiss select"
2105
+ }
2106
+ );
2107
+ };
2108
+ SelectBackdrop.displayName = "Select.Backdrop";
2109
+
2110
+ // src/components/Select/Presentation/SelectHandle.tsx
2111
+ import { View as View14 } from "react-native";
2112
+ import { jsx as jsx20 } from "react/jsx-runtime";
2113
+ var SelectHandle = () => {
2114
+ const styles = useThemeStyles(createPresentationStyles);
2115
+ return /* @__PURE__ */ jsx20(View14, { style: styles.handleWrap, accessible: false, children: /* @__PURE__ */ jsx20(View14, { style: styles.handle }) });
2116
+ };
2117
+ SelectHandle.displayName = "Select.Handle";
2118
+
2119
+ // src/components/Select/Presentation/SelectModal.tsx
2120
+ import { Modal as Modal3, View as View15 } from "react-native";
2121
+ import { jsx as jsx21, jsxs as jsxs10 } from "react/jsx-runtime";
2122
+ var SelectModal = ({
2123
+ visible,
2124
+ onClose,
2125
+ dismissOnBackdropPress,
2126
+ contentStyle,
2127
+ children
2128
+ }) => {
2129
+ const styles = useThemeStyles(createPresentationStyles);
2130
+ return /* @__PURE__ */ jsx21(
2131
+ Modal3,
2132
+ {
2133
+ transparent: true,
2134
+ visible,
2135
+ animationType: "slide",
2136
+ onRequestClose: onClose,
2137
+ children: /* @__PURE__ */ jsxs10(
2138
+ View15,
2139
+ {
2140
+ style: [styles.modalRoot, styles.modalPresentationRoot],
2141
+ testID: "select-content-root",
2142
+ children: [
2143
+ /* @__PURE__ */ jsx21(
2144
+ SelectBackdrop,
2145
+ {
2146
+ onClose,
2147
+ dismissOnBackdropPress
2148
+ }
2149
+ ),
2150
+ /* @__PURE__ */ jsx21(
2151
+ View15,
2152
+ {
2153
+ style: [styles.content, styles.modalPresentation, contentStyle],
2154
+ testID: "select-modal",
2155
+ children
2156
+ }
2157
+ )
2158
+ ]
2159
+ }
2160
+ )
2161
+ }
2162
+ );
2163
+ };
2164
+ SelectModal.displayName = "Select.Modal";
2165
+
2166
+ // src/components/Select/Presentation/SelectPopover.tsx
2167
+ import { Modal as Modal4, View as View16 } from "react-native";
2168
+ import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
2169
+ var SelectPopover = ({
2170
+ visible,
2171
+ onClose,
2172
+ dismissOnBackdropPress,
2173
+ placement,
2174
+ matchTriggerWidth,
2175
+ triggerWidth,
2176
+ contentStyle,
2177
+ children
2178
+ }) => {
2179
+ const styles = useThemeStyles(createPresentationStyles);
2180
+ return /* @__PURE__ */ jsx22(
2181
+ Modal4,
2182
+ {
2183
+ transparent: true,
2184
+ visible,
2185
+ animationType: "fade",
2186
+ onRequestClose: onClose,
2187
+ children: /* @__PURE__ */ jsxs11(
2188
+ View16,
2189
+ {
2190
+ style: [
2191
+ styles.modalRoot,
2192
+ styles.popoverRoot,
2193
+ placement === "top" ? styles.popoverRootTop : styles.popoverRootBottom
2194
+ ],
2195
+ testID: "select-content-root",
2196
+ children: [
2197
+ /* @__PURE__ */ jsx22(
2198
+ SelectBackdrop,
2199
+ {
2200
+ onClose,
2201
+ dismissOnBackdropPress
2202
+ }
2203
+ ),
2204
+ /* @__PURE__ */ jsx22(
2205
+ View16,
2206
+ {
2207
+ style: [
2208
+ styles.content,
2209
+ styles.popover,
2210
+ placement === "top" ? styles.popoverTop : styles.popoverBottom,
2211
+ matchTriggerWidth && triggerWidth ? { width: triggerWidth } : null,
2212
+ contentStyle
2213
+ ],
2214
+ testID: "select-popover",
2215
+ children
2216
+ }
2217
+ )
2218
+ ]
2219
+ }
2220
+ )
2221
+ }
2222
+ );
2223
+ };
2224
+ SelectPopover.displayName = "Select.Popover";
2225
+
2226
+ // src/components/Select/Presentation/SelectSheet.tsx
2227
+ import { Modal as Modal5, View as View17 } from "react-native";
2228
+ import { jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
2229
+ var SelectSheet = ({
2230
+ visible,
2231
+ onClose,
2232
+ dismissOnBackdropPress,
2233
+ contentStyle,
2234
+ children
2235
+ }) => {
2236
+ const styles = useThemeStyles(createPresentationStyles);
2237
+ return /* @__PURE__ */ jsx23(
2238
+ Modal5,
2239
+ {
2240
+ transparent: true,
2241
+ visible,
2242
+ animationType: "slide",
2243
+ onRequestClose: onClose,
2244
+ children: /* @__PURE__ */ jsxs12(
2245
+ View17,
2246
+ {
2247
+ style: [styles.modalRoot, styles.sheetRoot],
2248
+ testID: "select-content-root",
2249
+ children: [
2250
+ /* @__PURE__ */ jsx23(
2251
+ SelectBackdrop,
2252
+ {
2253
+ onClose,
2254
+ dismissOnBackdropPress
2255
+ }
2256
+ ),
2257
+ /* @__PURE__ */ jsxs12(
2258
+ View17,
2259
+ {
2260
+ style: [styles.content, styles.sheet, contentStyle],
2261
+ testID: "select-sheet",
2262
+ children: [
2263
+ /* @__PURE__ */ jsx23(SelectHandle, {}),
2264
+ children
2265
+ ]
2266
+ }
2267
+ )
2268
+ ]
2269
+ }
2270
+ )
2271
+ }
2272
+ );
2273
+ };
2274
+ SelectSheet.displayName = "Select.Sheet";
2275
+
2276
+ // src/components/Select/Content/SelectContent.styles.ts
2277
+ import { StyleSheet as StyleSheet17 } from "react-native";
2278
+ var createContentStyles = (theme) => StyleSheet17.create({
2279
+ toolbar: {
2280
+ minHeight: 52,
2281
+ flexDirection: "row",
2282
+ alignItems: "center",
2283
+ justifyContent: "space-between",
2284
+ paddingHorizontal: theme.tokens.spacing[4],
2285
+ borderBottomColor: theme.components.select.dropdown.separator.bg,
2286
+ borderBottomWidth: 1
2287
+ },
2288
+ title: {
2289
+ flex: 1,
2290
+ marginHorizontal: theme.tokens.spacing[3],
2291
+ color: theme.components.select.dropdown.fg,
2292
+ fontFamily: theme.tokens.typography.family.medium,
2293
+ fontSize: theme.tokens.typography.size.md,
2294
+ lineHeight: theme.tokens.typography.lineHeight.md,
2295
+ textAlign: "center"
2296
+ },
2297
+ toolbarAction: {
2298
+ minWidth: 64,
2299
+ minHeight: 44,
2300
+ alignItems: "center",
2301
+ justifyContent: "center"
2302
+ },
2303
+ cancelText: {
2304
+ color: theme.components.select.trigger.placeholder.fg,
2305
+ fontFamily: theme.tokens.typography.family.medium,
2306
+ fontSize: theme.tokens.typography.size.md,
2307
+ lineHeight: theme.tokens.typography.lineHeight.md
2308
+ },
2309
+ doneText: {
2310
+ color: theme.semantic.text.interactive,
2311
+ fontFamily: theme.tokens.typography.family.medium,
2312
+ fontSize: theme.tokens.typography.size.md,
2313
+ lineHeight: theme.tokens.typography.lineHeight.md
2314
+ },
2315
+ list: {
2316
+ maxHeight: 420
2317
+ },
2318
+ listContent: {
2319
+ paddingHorizontal: theme.tokens.spacing[2],
2320
+ paddingVertical: theme.tokens.spacing[2]
2321
+ },
2322
+ empty: {
2323
+ minHeight: 72,
2324
+ alignItems: "center",
2325
+ justifyContent: "center",
2326
+ padding: theme.tokens.spacing[4]
2327
+ },
2328
+ emptyText: {
2329
+ color: theme.components.select.dropdown.empty.fg,
2330
+ fontFamily: theme.tokens.typography.family.regular,
2331
+ fontSize: theme.tokens.typography.size.md,
2332
+ lineHeight: theme.tokens.typography.lineHeight.md,
2333
+ textAlign: "center"
2334
+ },
2335
+ loading: {
2336
+ minHeight: 72,
2337
+ flexDirection: "row",
2338
+ alignItems: "center",
2339
+ justifyContent: "center",
2340
+ gap: theme.tokens.spacing[2],
2341
+ padding: theme.tokens.spacing[4]
2342
+ },
2343
+ loadingText: {
2344
+ color: theme.components.select.dropdown.fg,
2345
+ fontFamily: theme.tokens.typography.family.regular,
2346
+ fontSize: theme.tokens.typography.size.md,
2347
+ lineHeight: theme.tokens.typography.lineHeight.md
2348
+ }
2349
+ });
2350
+
2351
+ // src/components/Select/Content/SelectEmpty.tsx
2352
+ import { Text as Text10, View as View18 } from "react-native";
2353
+ import { jsx as jsx24 } from "react/jsx-runtime";
2354
+ var renderText = (node, style) => {
2355
+ if (typeof node === "string" || typeof node === "number") {
2356
+ return /* @__PURE__ */ jsx24(Text10, { style, children: node });
2357
+ }
2358
+ return node;
2359
+ };
2360
+ var SelectEmpty = createSelectSlot(
2361
+ "empty",
2362
+ "Select.Empty"
2363
+ );
2364
+ var SelectEmptyState = () => {
2365
+ const styles = useThemeStyles(createContentStyles);
2366
+ const { empty } = useSelectContext();
2367
+ return /* @__PURE__ */ jsx24(View18, { style: styles.empty, children: renderText(empty, styles.emptyText) });
2368
+ };
2369
+ SelectEmptyState.displayName = "Select.EmptyState";
2370
+
2371
+ // src/components/Select/Content/SelectLoading.tsx
2372
+ import { ActivityIndicator, Text as Text11, View as View19 } from "react-native";
2373
+ import { jsx as jsx25, jsxs as jsxs13 } from "react/jsx-runtime";
2374
+ var renderText2 = (node, style) => {
2375
+ if (typeof node === "string" || typeof node === "number") {
2376
+ return /* @__PURE__ */ jsx25(Text11, { style, children: node });
2377
+ }
2378
+ return node;
2379
+ };
2380
+ var SelectLoading = createSelectSlot(
2381
+ "loading",
2382
+ "Select.Loading"
2383
+ );
2384
+ var SelectLoadingState = () => {
2385
+ const { theme } = useTheme();
2386
+ const styles = useThemeStyles(createContentStyles);
2387
+ const { loadingContent } = useSelectContext();
2388
+ return /* @__PURE__ */ jsxs13(View19, { style: styles.loading, children: [
2389
+ /* @__PURE__ */ jsx25(
2390
+ ActivityIndicator,
2391
+ {
2392
+ testID: "select-content-loading-indicator",
2393
+ size: "small",
2394
+ color: theme.components.select.dropdown.fg
2395
+ }
2396
+ ),
2397
+ renderText2(loadingContent, styles.loadingText)
2398
+ ] });
2399
+ };
2400
+ SelectLoadingState.displayName = "Select.LoadingState";
2401
+
2402
+ // src/components/Select/Content/SelectSearch.tsx
2403
+ import { useEffect as useEffect3 } from "react";
2404
+ import { Close as Close2, Search } from "@vellira-ui/icons";
2405
+ import { Pressable as Pressable9, TextInput, View as View20 } from "react-native";
2406
+
2407
+ // src/components/Select/Content/SelectSearch.styles.ts
2408
+ import { StyleSheet as StyleSheet18 } from "react-native";
2409
+ var createSearchStyles = (theme) => StyleSheet18.create({
2410
+ searchWrap: {
2411
+ flexDirection: "row",
2412
+ alignItems: "center",
2413
+ marginHorizontal: theme.tokens.spacing[4],
2414
+ marginTop: theme.tokens.spacing[3],
2415
+ marginBottom: theme.tokens.spacing[2],
2416
+ paddingHorizontal: theme.tokens.spacing[3],
2417
+ minHeight: 44,
2418
+ borderWidth: 1,
2419
+ borderRadius: theme.tokens.radius.md,
2420
+ borderColor: theme.components.select.dropdown.search.border,
2421
+ backgroundColor: theme.components.select.dropdown.search.bg
2422
+ },
2423
+ searchInput: {
2424
+ flex: 1,
2425
+ minWidth: 0,
2426
+ color: theme.components.select.dropdown.search.fg,
2427
+ fontFamily: theme.tokens.typography.family.regular,
2428
+ fontSize: theme.tokens.typography.size.md,
2429
+ lineHeight: theme.tokens.typography.lineHeight.md,
2430
+ paddingVertical: 0
2431
+ },
2432
+ searchIcon: {
2433
+ width: 18,
2434
+ height: 18,
2435
+ marginRight: theme.tokens.spacing[2],
2436
+ alignItems: "center",
2437
+ justifyContent: "center"
2438
+ },
2439
+ searchClearButton: {
2440
+ width: 28,
2441
+ height: 28,
2442
+ marginLeft: theme.tokens.spacing[2],
2443
+ alignItems: "center",
2444
+ justifyContent: "center",
2445
+ borderRadius: 999,
2446
+ backgroundColor: theme.components.select.clearButton.hoverBg
2447
+ }
2448
+ });
2449
+
2450
+ // src/components/Select/Content/SelectSearch.tsx
2451
+ import { jsx as jsx26, jsxs as jsxs14 } from "react/jsx-runtime";
2452
+ var SelectSearch = createSelectSlot(
2453
+ "search",
2454
+ "Select.Search"
2455
+ );
2456
+ var SelectSearchField = () => {
2457
+ const { theme } = useTheme();
2458
+ const styles = useThemeStyles(createSearchStyles);
2459
+ const {
2460
+ query,
2461
+ setQuery,
2462
+ searchPlaceholder,
2463
+ searchInputRef,
2464
+ searchStyle,
2465
+ selectedRowIndex,
2466
+ virtual
2467
+ } = useSelectContext();
2468
+ const shouldAutoFocus = !virtual || selectedRowIndex === 0;
2469
+ useEffect3(() => {
2470
+ if (!shouldAutoFocus) return;
2471
+ const focusTimer = setTimeout(() => {
2472
+ searchInputRef.current?.focus();
2473
+ }, 0);
2474
+ return () => clearTimeout(focusTimer);
2475
+ }, [searchInputRef, shouldAutoFocus]);
2476
+ return /* @__PURE__ */ jsxs14(View20, { style: styles.searchWrap, children: [
2477
+ /* @__PURE__ */ jsx26(
2478
+ View20,
2479
+ {
2480
+ style: styles.searchIcon,
2481
+ accessibilityElementsHidden: true,
2482
+ importantForAccessibility: "no",
2483
+ children: /* @__PURE__ */ jsx26(
2484
+ Search,
2485
+ {
2486
+ width: 16,
2487
+ height: 16,
2488
+ color: theme.components.select.dropdown.search.placeholder
2489
+ }
2490
+ )
2491
+ }
2492
+ ),
2493
+ /* @__PURE__ */ jsx26(
2494
+ TextInput,
2495
+ {
2496
+ ref: searchInputRef,
2497
+ value: query,
2498
+ onChangeText: setQuery,
2499
+ placeholder: searchPlaceholder,
2500
+ autoFocus: shouldAutoFocus,
2501
+ returnKeyType: "search",
2502
+ placeholderTextColor: theme.components.select.dropdown.search.placeholder,
2503
+ accessibilityLabel: searchPlaceholder,
2504
+ style: [styles.searchInput, searchStyle]
2505
+ }
2506
+ ),
2507
+ query && /* @__PURE__ */ jsx26(
2508
+ Pressable9,
2509
+ {
2510
+ accessibilityRole: "button",
2511
+ accessibilityLabel: "Clear search",
2512
+ hitSlop: 8,
2513
+ onPress: () => setQuery(""),
2514
+ style: styles.searchClearButton,
2515
+ children: /* @__PURE__ */ jsx26(
2516
+ Close2,
2517
+ {
2518
+ width: 14,
2519
+ height: 14,
2520
+ color: theme.components.select.clearButton.hoverFg
2521
+ }
2522
+ )
2523
+ }
2524
+ )
2525
+ ] });
2526
+ };
2527
+ SelectSearchField.displayName = "Select.SearchField";
2528
+
2529
+ // src/components/Select/Content/SelectContent.tsx
2530
+ import { Fragment as Fragment3, jsx as jsx27, jsxs as jsxs15 } from "react/jsx-runtime";
2531
+ var SelectContent = createSelectSlot(
2532
+ "content",
2533
+ "Select.Content"
2534
+ );
2535
+ var SelectContentSurface = () => {
2536
+ const styles = useThemeStyles(createContentStyles);
2537
+ const wasOpenRef = useRef3(false);
2538
+ const [openCycle, setOpenCycle] = useState2(0);
2539
+ const context = useSelectContext();
2540
+ const {
2541
+ isOpen,
2542
+ resolvedPresentation,
2543
+ placement,
2544
+ dismissOnBackdropPress,
2545
+ contentStyle,
2546
+ matchTriggerWidth,
2547
+ triggerWidth,
2548
+ resolvedLabel,
2549
+ closeContent,
2550
+ searchable,
2551
+ loading,
2552
+ filteredRows,
2553
+ selectedValues,
2554
+ selectedOptions,
2555
+ maxSelected,
2556
+ optionStyle,
2557
+ selectOption,
2558
+ selectGroup,
2559
+ itemHeight,
2560
+ selectedRowIndex,
2561
+ query
2562
+ } = context;
2563
+ const shouldSeedSelectedPosition = Boolean(context.virtual) && selectedRowIndex > 0 && query === "";
2564
+ const initialScrollIndex = shouldSeedSelectedPosition ? selectedRowIndex : void 0;
2565
+ useEffect4(() => {
2566
+ if (isOpen && !wasOpenRef.current) {
2567
+ setOpenCycle((cycle) => cycle + 1);
2568
+ }
2569
+ wasOpenRef.current = isOpen;
2570
+ }, [isOpen]);
2571
+ const renderRow = ({ item }) => {
2572
+ if (item.type === "group") {
2573
+ if (item.selectable && context.multiple) {
2574
+ const enabledGroupValues = item.itemValues.filter(
2575
+ (value) => context.optionsByValue.get(value)
2576
+ );
2577
+ const selectedGroupCount = selectedOptions.filter(
2578
+ (option) => enabledGroupValues.includes(option.value)
2579
+ ).length;
2580
+ return /* @__PURE__ */ jsx27(
2581
+ SelectGroupActionRow,
2582
+ {
2583
+ label: item.label,
2584
+ selectLabel: item.selectLabel,
2585
+ selectedCount: selectedGroupCount,
2586
+ itemCount: enabledGroupValues.length,
2587
+ onPress: () => selectGroup(enabledGroupValues)
2588
+ }
2589
+ );
2590
+ }
2591
+ return /* @__PURE__ */ jsx27(SelectGroupLabelRow, { label: item.label });
2592
+ }
2593
+ if (item.type === "separator") {
2594
+ return /* @__PURE__ */ jsx27(SelectSeparatorRow, {});
2595
+ }
2596
+ const isSelected = selectedValues.includes(item.option.value);
2597
+ const maxReached = !isSelected && typeof maxSelected === "number" && selectedValues.length >= maxSelected;
2598
+ return /* @__PURE__ */ jsx27(
2599
+ SelectItemRow,
2600
+ {
2601
+ option: item.option,
2602
+ isSelected,
2603
+ isDisabled: Boolean(item.option.disabled || maxReached),
2604
+ optionStyle,
2605
+ onSelect: selectOption
2606
+ }
2607
+ );
2608
+ };
2609
+ const body = /* @__PURE__ */ jsxs15(Fragment3, { children: [
2610
+ /* @__PURE__ */ jsxs15(
2611
+ View21,
2612
+ {
2613
+ style: styles.toolbar,
2614
+ accessible: true,
2615
+ accessibilityRole: "toolbar",
2616
+ accessibilityLabel: `${resolvedLabel} selection actions`,
2617
+ children: [
2618
+ /* @__PURE__ */ jsx27(
2619
+ Pressable10,
2620
+ {
2621
+ onPress: closeContent,
2622
+ hitSlop: 8,
2623
+ style: styles.toolbarAction,
2624
+ accessibilityRole: "button",
2625
+ accessibilityLabel: "Close selection",
2626
+ children: /* @__PURE__ */ jsx27(Text12, { style: styles.cancelText, children: "Cancel" })
2627
+ }
2628
+ ),
2629
+ /* @__PURE__ */ jsx27(Text12, { style: styles.title, numberOfLines: 1, accessibilityRole: "header", children: resolvedLabel }),
2630
+ /* @__PURE__ */ jsx27(
2631
+ Pressable10,
2632
+ {
2633
+ onPress: closeContent,
2634
+ hitSlop: 8,
2635
+ style: styles.toolbarAction,
2636
+ accessibilityRole: "button",
2637
+ accessibilityLabel: "Done",
2638
+ children: /* @__PURE__ */ jsx27(Text12, { style: styles.doneText, children: "Done" })
2639
+ }
2640
+ )
2641
+ ]
2642
+ }
2643
+ ),
2644
+ searchable && /* @__PURE__ */ jsx27(SelectSearchField, {}),
2645
+ loading && filteredRows.length === 0 ? /* @__PURE__ */ jsx27(SelectLoadingState, {}) : filteredRows.length === 0 ? /* @__PURE__ */ jsx27(SelectEmptyState, {}) : /* @__PURE__ */ jsx27(
2646
+ FlatList2,
2647
+ {
2648
+ data: filteredRows,
2649
+ keyExtractor: (item) => item.key,
2650
+ renderItem: renderRow,
2651
+ style: styles.list,
2652
+ contentContainerStyle: styles.listContent,
2653
+ keyboardShouldPersistTaps: "handled",
2654
+ initialScrollIndex,
2655
+ initialNumToRender: typeof context.virtual === "object" ? context.virtual.initialNumToRender : 12,
2656
+ windowSize: typeof context.virtual === "object" ? context.virtual.windowSize : 7,
2657
+ getItemLayout: (_data, index) => ({
2658
+ length: itemHeight,
2659
+ offset: itemHeight * index,
2660
+ index
2661
+ })
2662
+ },
2663
+ `select-list-${openCycle}`
2664
+ )
2665
+ ] });
2666
+ if (resolvedPresentation === "sheet") {
2667
+ return /* @__PURE__ */ jsx27(
2668
+ SelectSheet,
2669
+ {
2670
+ visible: isOpen,
2671
+ onClose: closeContent,
2672
+ dismissOnBackdropPress,
2673
+ contentStyle,
2674
+ children: body
2675
+ }
2676
+ );
2677
+ }
2678
+ if (resolvedPresentation === "popover") {
2679
+ return /* @__PURE__ */ jsx27(
2680
+ SelectPopover,
2681
+ {
2682
+ visible: isOpen,
2683
+ onClose: closeContent,
2684
+ dismissOnBackdropPress,
2685
+ placement,
2686
+ matchTriggerWidth,
2687
+ triggerWidth,
2688
+ contentStyle,
2689
+ children: body
2690
+ }
2691
+ );
2692
+ }
2693
+ return /* @__PURE__ */ jsx27(
2694
+ SelectModal,
2695
+ {
2696
+ visible: isOpen,
2697
+ onClose: closeContent,
2698
+ dismissOnBackdropPress,
2699
+ contentStyle,
2700
+ children: body
2701
+ }
2702
+ );
2703
+ };
2704
+ SelectContentSurface.displayName = "Select.ContentSurface";
2705
+
2706
+ // src/components/Select/Root/SelectRoot.tsx
2707
+ import { useMemo as useMemo6, useRef as useRef4, useState as useState4 } from "react";
2708
+ import { useSelect } from "@vellira-ui/core";
2709
+ import { View as View23 } from "react-native";
2710
+
2711
+ // src/components/Select/internal/useSelectAccessibility.ts
2712
+ import { AccessibilityInfo as AccessibilityInfo2 } from "react-native";
2713
+ var useSelectAccessibility = ({
2714
+ accessibilityLabel,
2715
+ accessibilityHint,
2716
+ label,
2717
+ description,
2718
+ error,
2719
+ invalid,
2720
+ placeholder,
2721
+ selectedLabel,
2722
+ hasFieldContext,
2723
+ fieldDescribedBy
2724
+ }) => {
2725
+ const descriptionText = typeof description === "string" || typeof description === "number" ? String(description) : void 0;
2726
+ const errorText = typeof error === "string" || typeof error === "number" ? String(error) : void 0;
2727
+ const resolvedLabel = accessibilityLabel ?? label ?? selectedLabel ?? placeholder ?? "Select";
2728
+ const resolvedHint = accessibilityHint ?? (invalid && errorText ? errorText : descriptionText ? descriptionText : hasFieldContext && fieldDescribedBy ? "Opens a list of options" : void 0);
2729
+ return {
2730
+ resolvedLabel,
2731
+ resolvedHint,
2732
+ announce: (message) => {
2733
+ AccessibilityInfo2.announceForAccessibility?.(message);
2734
+ }
2735
+ };
2736
+ };
2737
+
2738
+ // src/components/Select/internal/useSelectCollection.ts
2739
+ import { useMemo as useMemo4 } from "react";
2740
+ var useSelectCollection = (children, optionsProp) => {
2741
+ const parsedChildren = useMemo4(
2742
+ () => parseSelectChildren(children),
2743
+ [children]
2744
+ );
2745
+ const options = useMemo4(
2746
+ () => [...optionsProp ?? [], ...parsedChildren.options],
2747
+ [optionsProp, parsedChildren.options]
2748
+ );
2749
+ const rows = useMemo4(() => {
2750
+ if (parsedChildren.rows.length > 0) {
2751
+ return parsedChildren.rows;
2752
+ }
2753
+ return options.map((option) => ({
2754
+ type: "item",
2755
+ key: `item-${option.value}`,
2756
+ option
2757
+ }));
2758
+ }, [options, parsedChildren.rows]);
2759
+ return {
2760
+ options,
2761
+ rows,
2762
+ searchableFromChildren: parsedChildren.searchable,
2763
+ searchPlaceholderFromChildren: parsedChildren.searchPlaceholder,
2764
+ emptyFromChildren: parsedChildren.empty,
2765
+ loadingFromChildren: parsedChildren.loading
2766
+ };
2767
+ };
2768
+
2769
+ // src/components/Select/internal/useSelectPresentation.ts
2770
+ import { useWindowDimensions as useWindowDimensions2 } from "react-native";
2771
+ var useSelectPresentation = (presentation = "auto") => {
2772
+ const { width } = useWindowDimensions2();
2773
+ if (presentation === "auto") {
2774
+ return width >= 768 ? "popover" : "sheet";
2775
+ }
2776
+ return presentation;
2777
+ };
2778
+
2779
+ // src/components/Select/internal/useSelectSearch.ts
2780
+ import { useEffect as useEffect5, useMemo as useMemo5, useState as useState3 } from "react";
2781
+ var useSelectSearch = ({
2782
+ rows,
2783
+ isOpen,
2784
+ searchable,
2785
+ searchableFromChildren,
2786
+ onSearch,
2787
+ filterOptions,
2788
+ filter = defaultSelectFilter
2789
+ }) => {
2790
+ const [query, setQuery] = useState3("");
2791
+ const shouldSearch = searchable ?? searchableFromChildren ?? Boolean(onSearch);
2792
+ const shouldFilter = filterOptions ?? !onSearch;
2793
+ const filteredRows = useMemo5(() => {
2794
+ if (!query || !shouldFilter) return rows;
2795
+ const visibleRows = [];
2796
+ let pendingGroup;
2797
+ rows.forEach((row) => {
2798
+ if (row.type === "group") {
2799
+ pendingGroup = row;
2800
+ return;
2801
+ }
2802
+ if (row.type === "separator") {
2803
+ if (visibleRows.length > 0 && visibleRows[visibleRows.length - 1]?.type !== "separator") {
2804
+ visibleRows.push(row);
2805
+ }
2806
+ return;
2807
+ }
2808
+ if (!filter(row.option, query)) return;
2809
+ if (pendingGroup) {
2810
+ visibleRows.push(pendingGroup);
2811
+ pendingGroup = void 0;
2812
+ }
2813
+ visibleRows.push(row);
2814
+ });
2815
+ return visibleRows.filter((row, index, collection) => {
2816
+ if (row.type !== "separator") return true;
2817
+ return index > 0 && index < collection.length - 1 && collection[index - 1]?.type !== "separator";
2818
+ });
2819
+ }, [filter, query, rows, shouldFilter]);
2820
+ useEffect5(() => {
2821
+ if (!isOpen) {
2822
+ setQuery("");
2823
+ return;
2824
+ }
2825
+ if (shouldSearch) {
2826
+ onSearch?.(query);
2827
+ }
2828
+ }, [isOpen, onSearch, query, shouldSearch]);
2829
+ return {
2830
+ query,
2831
+ setQuery,
2832
+ shouldSearch,
2833
+ filteredRows
2834
+ };
2835
+ };
2836
+
2837
+ // src/components/Select/Trigger/SelectIcon.tsx
2838
+ var SelectIcon = createSelectSlot(
2839
+ "icon",
2840
+ "Select.Icon"
2841
+ );
2842
+
2843
+ // src/components/Select/Trigger/SelectTrigger.tsx
2844
+ import { cloneElement as cloneElement5, isValidElement as isValidElement7 } from "react";
2845
+ import { ChevronDown as ChevronDown2, Close as Close3 } from "@vellira-ui/icons";
2846
+ import { ActivityIndicator as ActivityIndicator2, Pressable as Pressable11, Text as Text13, View as View22 } from "react-native";
2847
+
2848
+ // src/components/Select/Trigger/SelectTrigger.styles.ts
2849
+ import { StyleSheet as StyleSheet19 } from "react-native";
2850
+ var createTriggerStyles = (theme) => StyleSheet19.create({
2851
+ trigger: {
2852
+ width: "100%",
2853
+ minWidth: 0,
2854
+ minHeight: 44,
2855
+ alignItems: "center",
2856
+ flexDirection: "row",
2857
+ borderRadius: theme.tokens.radius.md,
2858
+ borderWidth: 1
2859
+ },
2860
+ sm: {
2861
+ minHeight: 44,
2862
+ paddingHorizontal: theme.tokens.spacing[3],
2863
+ paddingVertical: theme.tokens.spacing[2]
2864
+ },
2865
+ md: {
2866
+ minHeight: 46,
2867
+ paddingHorizontal: theme.tokens.spacing[4],
2868
+ paddingVertical: theme.tokens.spacing[3]
2869
+ },
2870
+ lg: {
2871
+ minHeight: 52,
2872
+ paddingHorizontal: theme.tokens.spacing[5],
2873
+ paddingVertical: theme.tokens.spacing[4]
2874
+ },
2875
+ value: {
2876
+ flex: 1,
2877
+ minWidth: 0
2878
+ },
2879
+ text: {
2880
+ fontFamily: theme.tokens.typography.family.regular
2881
+ },
2882
+ textSm: {
2883
+ fontSize: theme.tokens.typography.size.sm,
2884
+ lineHeight: theme.tokens.typography.lineHeight.sm
2885
+ },
2886
+ textMd: {
2887
+ fontSize: theme.tokens.typography.size.md,
2888
+ lineHeight: theme.tokens.typography.lineHeight.md
2889
+ },
2890
+ textLg: {
2891
+ fontSize: theme.tokens.typography.size.lg,
2892
+ lineHeight: theme.tokens.typography.lineHeight.lg
2893
+ },
2894
+ affix: {
2895
+ flexShrink: 0,
2896
+ color: theme.semantic.text.secondary,
2897
+ fontFamily: theme.tokens.typography.family.regular,
2898
+ fontSize: theme.tokens.typography.size.md,
2899
+ lineHeight: theme.tokens.typography.lineHeight.md
2900
+ },
2901
+ startIcon: {
2902
+ width: 18,
2903
+ height: 18,
2904
+ marginRight: theme.tokens.spacing[2],
2905
+ alignItems: "center",
2906
+ justifyContent: "center"
2907
+ },
2908
+ endIcon: {
2909
+ width: 18,
2910
+ height: 18,
2911
+ marginLeft: theme.tokens.spacing[2],
2912
+ alignItems: "center",
2913
+ justifyContent: "center"
2914
+ },
2915
+ iconOpen: {
2916
+ transform: [{ rotate: "180deg" }]
2917
+ },
2918
+ clearButton: {
2919
+ width: 28,
2920
+ height: 28,
2921
+ marginLeft: theme.tokens.spacing[2],
2922
+ alignItems: "center",
2923
+ justifyContent: "center",
2924
+ borderRadius: 999,
2925
+ backgroundColor: theme.components.select.clearButton.hoverBg
2926
+ }
2927
+ });
2928
+
2929
+ // src/components/Select/Trigger/SelectTrigger.tsx
2930
+ import { jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
2931
+ var SelectTriggerSlot = createSelectSlot(
2932
+ "trigger",
2933
+ "Select.Trigger"
2934
+ );
2935
+ function SelectTrigger({
2936
+ displayText,
2937
+ isPlaceholder,
2938
+ isOpen,
2939
+ size = "md",
2940
+ color = "primary",
2941
+ variant = "outline",
2942
+ disabled = false,
2943
+ required = false,
2944
+ hasError = false,
2945
+ hasValue = false,
2946
+ loading = false,
2947
+ clearable = false,
2948
+ startIcon,
2949
+ endIcon,
2950
+ prefix,
2951
+ suffix,
2952
+ accessibilityLabel,
2953
+ accessibilityHint,
2954
+ nativeID,
2955
+ accessibilityLabelledBy,
2956
+ ariaDescribedBy,
2957
+ triggerStyle,
2958
+ textStyle,
2959
+ onPress,
2960
+ onClear
2961
+ }) {
2962
+ const { theme } = useTheme();
2963
+ const styles = useThemeStyles(createTriggerStyles);
2964
+ const palette = theme.components.select[color][variant];
2965
+ const triggerState = isOpen ? palette.focus : palette.default;
2966
+ const resolvedIconSize = size === "lg" ? 18 : 16;
2967
+ const textSizeStyle = {
2968
+ sm: styles.textSm,
2969
+ md: styles.textMd,
2970
+ lg: styles.textLg
2971
+ };
2972
+ const resolvedAccessibilityHint = accessibilityHint ?? (hasError ? "Invalid selection. Opens a list of options" : required ? "Required. Opens a list of options" : "Opens a list of options");
2973
+ const iconColor = disabled ? theme.components.select.trigger.disabled.icon : triggerState.icon;
2974
+ const renderIcon = (icon) => isValidElement7(icon) ? cloneElement5(icon, { color: iconColor, size: resolvedIconSize }) : null;
2975
+ const renderValue = () => {
2976
+ const valueStyle = [
2977
+ styles.text,
2978
+ textSizeStyle[size],
2979
+ { color: triggerState.fg },
2980
+ isPlaceholder && { color: triggerState.placeholder },
2981
+ disabled && {
2982
+ color: theme.components.select.trigger.disabled.fg
2983
+ },
2984
+ textStyle
2985
+ ];
2986
+ if (typeof displayText === "string" || typeof displayText === "number") {
2987
+ return /* @__PURE__ */ jsx28(Text13, { numberOfLines: 1, style: valueStyle, children: displayText });
2988
+ }
2989
+ if (isValidElement7(displayText) && displayText.type === Text13) {
2990
+ return cloneElement5(displayText, {
2991
+ numberOfLines: displayText.props.numberOfLines ?? 1,
2992
+ style: [valueStyle, displayText.props.style]
2993
+ });
2994
+ }
2995
+ return displayText;
2996
+ };
2997
+ return /* @__PURE__ */ jsxs16(
2998
+ Pressable11,
2999
+ {
3000
+ nativeID,
3001
+ disabled,
3002
+ accessibilityRole: "button",
3003
+ accessibilityLabel,
3004
+ accessibilityHint: resolvedAccessibilityHint,
3005
+ accessibilityLabelledBy,
3006
+ "aria-describedby": ariaDescribedBy,
3007
+ accessibilityState: {
3008
+ expanded: isOpen,
3009
+ disabled,
3010
+ selected: hasValue,
3011
+ busy: loading
3012
+ },
3013
+ onPress,
3014
+ style: [
3015
+ styles.trigger,
3016
+ {
3017
+ backgroundColor: triggerState.bg,
3018
+ borderColor: triggerState.border
3019
+ },
3020
+ styles[size],
3021
+ isOpen && {
3022
+ shadowColor: theme.components.select[color].ring,
3023
+ shadowOffset: { width: 0, height: 0 },
3024
+ shadowOpacity: 0.16,
3025
+ shadowRadius: 6,
3026
+ elevation: 1
3027
+ },
3028
+ hasError && {
3029
+ borderColor: theme.components.select.trigger.error.border
3030
+ },
3031
+ disabled && {
3032
+ backgroundColor: theme.components.select.trigger.disabled.bg,
3033
+ borderColor: theme.components.select.trigger.disabled.border
3034
+ },
1434
3035
  triggerStyle
1435
3036
  ],
1436
3037
  children: [
1437
- /* @__PURE__ */ jsx16(
1438
- Text7,
3038
+ startIcon && /* @__PURE__ */ jsx28(
3039
+ View22,
1439
3040
  {
1440
- numberOfLines: 1,
1441
- style: [
1442
- styles.text,
1443
- textSizeStyle[size],
1444
- isPlaceholder && styles.placeholder,
1445
- isOpen && styles.textOpen,
1446
- disabled && styles.textDisabled,
1447
- textStyle
1448
- ],
1449
- children: displayText
3041
+ pointerEvents: "none",
3042
+ style: styles.startIcon,
3043
+ accessibilityElementsHidden: true,
3044
+ importantForAccessibility: "no",
3045
+ children: renderIcon(startIcon)
1450
3046
  }
1451
3047
  ),
1452
- /* @__PURE__ */ jsx16(
1453
- View12,
3048
+ prefix && /* @__PURE__ */ jsx28(Text13, { style: styles.affix, children: prefix }),
3049
+ /* @__PURE__ */ jsx28(View22, { style: styles.value, children: renderValue() }),
3050
+ suffix && /* @__PURE__ */ jsx28(Text13, { style: styles.affix, children: suffix }),
3051
+ loading ? /* @__PURE__ */ jsx28(
3052
+ ActivityIndicator2,
1454
3053
  {
1455
- style: [styles.icon, isOpen && styles.iconOpen],
1456
- accessibilityElementsHidden: true,
1457
- importantForAccessibility: "no",
1458
- children: /* @__PURE__ */ jsx16(
1459
- ChevronDown2,
3054
+ testID: "select-loading-indicator",
3055
+ size: "small",
3056
+ color: iconColor
3057
+ }
3058
+ ) : clearable && hasValue && !disabled ? /* @__PURE__ */ jsx28(
3059
+ Pressable11,
3060
+ {
3061
+ accessibilityRole: "button",
3062
+ accessibilityLabel: "Clear selection",
3063
+ hitSlop: 8,
3064
+ onPress: onClear,
3065
+ style: styles.clearButton,
3066
+ children: /* @__PURE__ */ jsx28(
3067
+ Close3,
1460
3068
  {
1461
- width: 16,
1462
- height: 16,
1463
- color: disabled ? theme.components.select.trigger.disabled.fg : theme.components.select.trigger.placeholder.fg
3069
+ width: 14,
3070
+ height: 14,
3071
+ color: theme.components.select.clearButton.hoverFg
1464
3072
  }
1465
3073
  )
1466
3074
  }
3075
+ ) : endIcon ? /* @__PURE__ */ jsx28(
3076
+ View22,
3077
+ {
3078
+ pointerEvents: "none",
3079
+ style: styles.endIcon,
3080
+ accessibilityElementsHidden: true,
3081
+ importantForAccessibility: "no",
3082
+ children: renderIcon(endIcon)
3083
+ }
3084
+ ) : /* @__PURE__ */ jsx28(
3085
+ View22,
3086
+ {
3087
+ style: [styles.endIcon, isOpen && styles.iconOpen],
3088
+ accessibilityElementsHidden: true,
3089
+ importantForAccessibility: "no",
3090
+ children: /* @__PURE__ */ jsx28(ChevronDown2, { width: 16, height: 16, color: iconColor })
3091
+ }
1467
3092
  )
1468
3093
  ]
1469
3094
  }
@@ -1471,290 +3096,371 @@ function SelectTrigger({
1471
3096
  }
1472
3097
  SelectTrigger.displayName = "SelectTrigger";
1473
3098
 
1474
- // src/components/Select/Select.styles.ts
1475
- import { StyleSheet as StyleSheet15 } from "react-native";
1476
- var createStyles15 = (theme) => StyleSheet15.create({
1477
- modalRoot: {
1478
- flex: 1,
1479
- justifyContent: "flex-end"
1480
- },
1481
- backdrop: {
1482
- ...StyleSheet15.absoluteFill,
1483
- backgroundColor: theme.semantic.overlay.backdrop
1484
- },
1485
- sheet: {
1486
- maxHeight: "50%",
1487
- overflow: "hidden",
1488
- backgroundColor: theme.components.select.dropdown.bg,
1489
- borderColor: theme.components.select.dropdown.border,
1490
- borderTopLeftRadius: theme.tokens.radius.lg,
1491
- borderTopRightRadius: theme.tokens.radius.lg,
1492
- borderWidth: 1,
1493
- borderBottomWidth: 0,
1494
- shadowColor: theme.tokens.shadows.lg.color,
1495
- shadowOffset: {
1496
- width: theme.tokens.shadows.lg.x,
1497
- height: -theme.tokens.shadows.lg.y
1498
- },
1499
- shadowOpacity: theme.tokens.shadows.lg.opacity,
1500
- shadowRadius: theme.tokens.shadows.lg.blur,
1501
- elevation: theme.tokens.shadows.lg.elevation
1502
- },
1503
- toolbar: {
1504
- minHeight: 48,
1505
- flexDirection: "row",
1506
- alignItems: "center",
1507
- justifyContent: "space-between",
1508
- paddingHorizontal: theme.tokens.spacing[4],
1509
- borderBottomColor: theme.components.select.dropdown.border,
1510
- borderBottomWidth: 1
1511
- },
1512
- title: {
1513
- flex: 1,
1514
- marginHorizontal: theme.tokens.spacing[3],
1515
- color: theme.components.select.dropdown.fg,
1516
- fontFamily: theme.tokens.typography.family.medium,
1517
- fontSize: theme.tokens.typography.size.md,
1518
- lineHeight: theme.tokens.typography.lineHeight.md,
1519
- textAlign: "center"
1520
- },
1521
- toolbarAction: {
1522
- minWidth: 64,
1523
- minHeight: 44,
1524
- alignItems: "center",
1525
- justifyContent: "center"
1526
- },
1527
- cancelText: {
1528
- color: theme.components.select.trigger.placeholder.fg,
1529
- fontFamily: theme.tokens.typography.family.medium,
1530
- fontSize: theme.tokens.typography.size.md,
1531
- lineHeight: theme.tokens.typography.lineHeight.md
1532
- },
1533
- doneText: {
1534
- color: theme.semantic.text.interactive,
1535
- fontFamily: theme.tokens.typography.family.medium,
1536
- fontSize: theme.tokens.typography.size.md,
1537
- lineHeight: theme.tokens.typography.lineHeight.md
1538
- },
1539
- picker: {
1540
- width: "100%"
1541
- }
1542
- });
3099
+ // src/components/Select/Trigger/SelectValue.tsx
3100
+ var SelectValue = createSelectSlot(
3101
+ "value",
3102
+ "Select.Value"
3103
+ );
1543
3104
 
1544
- // src/components/Select/Select.tsx
1545
- import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
1546
- function Select({
1547
- label,
1548
- description,
1549
- value,
1550
- defaultValue,
1551
- onValueChange,
1552
- options: optionsProp,
1553
- multiple = false,
1554
- maxSelected,
1555
- closeOnSelect,
1556
- placeholder = "Select...",
1557
- size = "md",
1558
- required = false,
1559
- disabled = false,
1560
- error,
1561
- style,
1562
- triggerStyle,
1563
- textStyle,
1564
- pickerStyle,
1565
- accessibilityLabel,
1566
- accessibilityHint
1567
- }) {
1568
- const { theme } = useTheme();
1569
- const styles = useThemeStyles(createStyles15);
1570
- const options = optionsProp ?? [];
3105
+ // src/components/Select/Root/SelectRoot.tsx
3106
+ import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
3107
+ function SelectRoot(props) {
3108
+ const {
3109
+ label,
3110
+ description,
3111
+ error,
3112
+ invalid = false,
3113
+ required = false,
3114
+ disabled = false,
3115
+ placeholder = "Select...",
3116
+ color = "primary",
3117
+ variant = "outline",
3118
+ size,
3119
+ open,
3120
+ defaultOpen,
3121
+ onOpenChange,
3122
+ clearable = false,
3123
+ searchable: searchableProp,
3124
+ searchPlaceholder,
3125
+ loading = false,
3126
+ loadingText = "Loading...",
3127
+ onSearch,
3128
+ filterOptions,
3129
+ filter,
3130
+ empty,
3131
+ startIcon,
3132
+ endIcon,
3133
+ prefix,
3134
+ suffix,
3135
+ renderValue,
3136
+ renderOption,
3137
+ closeOnSelect,
3138
+ maxSelected,
3139
+ presentation = "auto",
3140
+ placement = "bottom",
3141
+ matchTriggerWidth = false,
3142
+ dismissOnBackdropPress = true,
3143
+ virtual,
3144
+ options: optionsProp,
3145
+ children,
3146
+ style,
3147
+ triggerStyle,
3148
+ textStyle,
3149
+ contentStyle,
3150
+ optionStyle,
3151
+ searchStyle,
3152
+ accessibilityLabel,
3153
+ accessibilityHint,
3154
+ testID
3155
+ } = props;
3156
+ const field = useFormFieldContext();
3157
+ const hasOwnField = Boolean(label || description || error);
3158
+ const [triggerWidth, setTriggerWidth] = useState4();
3159
+ const searchInputRef = useRef4(null);
3160
+ const selectedFocusValueRef = useRef4(void 0);
3161
+ const resolvedPresentation = useSelectPresentation(presentation);
3162
+ const {
3163
+ options,
3164
+ rows,
3165
+ searchableFromChildren,
3166
+ searchPlaceholderFromChildren,
3167
+ emptyFromChildren,
3168
+ loadingFromChildren
3169
+ } = useSelectCollection(children, optionsProp);
3170
+ const resolvedSize = size ?? field?.size ?? "md";
3171
+ const isInvalid = invalid || Boolean(error) || !hasOwnField && Boolean(field?.invalid);
3172
+ const isDisabled = disabled || !hasOwnField && Boolean(field?.disabled);
3173
+ const isRequired = required || !hasOwnField && Boolean(field?.required);
3174
+ const controlledValue = props.multiple ? props.value : props.value === null ? "" : props.value;
3175
+ const controlledDefaultValue = props.multiple ? props.defaultValue : props.defaultValue === null ? "" : props.defaultValue;
1571
3176
  const {
1572
3177
  selectedValue,
1573
- selectedValues,
1574
- selectedOption,
1575
- selectedOptions,
3178
+ setSelectedValue,
1576
3179
  isOpen,
1577
- setIsOpen,
3180
+ openDropdown,
3181
+ closeDropdown,
1578
3182
  selectValue
1579
3183
  } = useSelect({
1580
- value,
1581
- defaultValue,
1582
- onValueChange,
3184
+ value: controlledValue,
3185
+ defaultValue: controlledDefaultValue,
3186
+ onValueChange: (nextValue) => {
3187
+ if (props.multiple) {
3188
+ props.onValueChange?.(
3189
+ nextValue
3190
+ );
3191
+ return;
3192
+ }
3193
+ props.onValueChange?.(
3194
+ nextValue === "" ? null : nextValue
3195
+ );
3196
+ },
1583
3197
  options,
1584
- multiple,
3198
+ multiple: props.multiple,
1585
3199
  maxSelected,
1586
3200
  closeOnSelect,
1587
- disabled
3201
+ disabled: isDisabled,
3202
+ open,
3203
+ defaultOpen,
3204
+ onOpenChange
1588
3205
  });
1589
- const resolvedSelectedValues = selectedValues ?? [];
1590
- const resolvedSelectedOptions = selectedOptions ?? [];
1591
- const selectedValueText = Array.isArray(selectedValue) ? selectedValue[0] ?? "" : selectedValue ?? "";
1592
- const [draftValue, setDraftValue] = useState2(selectedValueText);
1593
- const hasError = !!error;
1594
- useEffect2(() => {
1595
- if (isOpen) {
1596
- setDraftValue(selectedValueText);
3206
+ const selectedValues = Array.isArray(selectedValue) ? selectedValue : selectedValue ? [selectedValue] : [];
3207
+ const selectedOption = options.find(
3208
+ (option) => selectedValues.includes(option.value)
3209
+ );
3210
+ const selectedOptions = options.filter(
3211
+ (option) => selectedValues.includes(option.value)
3212
+ );
3213
+ const optionsByValue = useMemo6(
3214
+ () => new Map(
3215
+ options.filter((option) => !option.disabled).map((option) => [option.value, option])
3216
+ ),
3217
+ [options]
3218
+ );
3219
+ const { query, setQuery, shouldSearch, filteredRows } = useSelectSearch({
3220
+ rows,
3221
+ isOpen,
3222
+ searchable: searchableProp,
3223
+ searchableFromChildren,
3224
+ onSearch,
3225
+ filterOptions,
3226
+ filter
3227
+ });
3228
+ const selectedFocusValue = selectedValues.includes(
3229
+ selectedFocusValueRef.current ?? ""
3230
+ ) ? selectedFocusValueRef.current : selectedValues[0];
3231
+ const selectedRowIndex = Math.max(
3232
+ 0,
3233
+ filteredRows.findIndex(
3234
+ (row) => row.type === "item" && row.option.value === selectedFocusValue
3235
+ )
3236
+ );
3237
+ const itemHeight = typeof virtual === "object" ? virtual.estimatedItemSize ?? 46 : 46;
3238
+ const displayValue = useMemo6(() => {
3239
+ if (renderValue) {
3240
+ return renderValue(
3241
+ props.multiple ? selectedOptions : selectedOption ?? null,
3242
+ { placeholder, multiple: Boolean(props.multiple) }
3243
+ );
1597
3244
  }
1598
- }, [isOpen, selectedValueText]);
1599
- const resolvedLabel = accessibilityLabel ?? label ?? selectedOption?.label ?? placeholder ?? "Select";
1600
- const openPicker = () => {
1601
- if (disabled) return;
1602
- setDraftValue(selectedValueText);
1603
- setIsOpen(true);
3245
+ if (props.multiple && selectedOptions.length > 0) {
3246
+ const visibleLabels = selectedOptions.slice(0, 2).map((option) => option.label);
3247
+ return selectedOptions.length > 2 ? `${visibleLabels.join(", ")} +${selectedOptions.length - 2}` : visibleLabels.join(", ");
3248
+ }
3249
+ return selectedOption?.label ?? placeholder;
3250
+ }, [
3251
+ placeholder,
3252
+ props.multiple,
3253
+ renderValue,
3254
+ selectedOption,
3255
+ selectedOptions
3256
+ ]);
3257
+ const { resolvedLabel, resolvedHint, announce } = useSelectAccessibility({
3258
+ accessibilityLabel,
3259
+ accessibilityHint,
3260
+ label: !hasOwnField ? void 0 : label,
3261
+ description: !hasOwnField ? field?.description : description,
3262
+ error: !hasOwnField ? field?.error : error,
3263
+ invalid: isInvalid,
3264
+ placeholder,
3265
+ selectedLabel: selectedOption?.label,
3266
+ hasFieldContext: !hasOwnField && Boolean(field),
3267
+ fieldDescribedBy: field?.ariaDescribedBy
3268
+ });
3269
+ const hasValue = selectedValues.length > 0;
3270
+ const clearValue = () => {
3271
+ selectedFocusValueRef.current = void 0;
3272
+ selectValue("");
3273
+ announce("Selection cleared");
1604
3274
  };
1605
- const closePicker = () => {
1606
- setIsOpen(false);
3275
+ const selectOption = (option) => {
3276
+ if (option.disabled) return;
3277
+ const selectedBefore = selectedValues.includes(option.value);
3278
+ const maxReached = Boolean(props.multiple) && !selectedBefore && typeof maxSelected === "number" && selectedValues.length >= maxSelected;
3279
+ if (maxReached) return;
3280
+ selectedFocusValueRef.current = option.value;
3281
+ selectValue(option.value);
3282
+ announce(`${option.label} selected`);
1607
3283
  };
1608
- const handleValueChange = (nextValue) => {
1609
- const nextOption = options.find((option) => option.value === nextValue);
1610
- if (!nextOption || nextOption.disabled) {
3284
+ const selectGroup = (values) => {
3285
+ if (!props.multiple || values.length === 0) return;
3286
+ const enabledValues = values.filter((value) => optionsByValue.has(value));
3287
+ const selectedGroupValues = enabledValues.filter(
3288
+ (value) => selectedValues.includes(value)
3289
+ );
3290
+ const outsideSelectedCount = selectedValues.filter(
3291
+ (value) => !enabledValues.includes(value)
3292
+ ).length;
3293
+ const maxSelectableGroupCount = typeof maxSelected === "number" ? Math.max(
3294
+ 0,
3295
+ Math.min(enabledValues.length, maxSelected - outsideSelectedCount)
3296
+ ) : enabledValues.length;
3297
+ const shouldClearGroup = selectedGroupValues.length > 0 && selectedGroupValues.length >= maxSelectableGroupCount;
3298
+ if (shouldClearGroup) {
3299
+ selectedFocusValueRef.current = void 0;
3300
+ setSelectedValue(
3301
+ selectedValues.filter((value) => !enabledValues.includes(value))
3302
+ );
3303
+ announce("Group selection cleared");
1611
3304
  return;
1612
3305
  }
1613
- setDraftValue(nextValue);
1614
- };
1615
- const confirmPicker = () => {
1616
- const nextOption = options.find((option) => option.value === draftValue);
1617
- if (!nextOption || nextOption.disabled) {
1618
- setIsOpen(false);
1619
- return;
3306
+ const nextValues = [...selectedValues];
3307
+ for (const value of enabledValues) {
3308
+ if (nextValues.includes(value)) continue;
3309
+ if (typeof maxSelected === "number" && nextValues.length >= maxSelected) {
3310
+ break;
3311
+ }
3312
+ nextValues.push(value);
3313
+ }
3314
+ setSelectedValue(nextValues);
3315
+ selectedFocusValueRef.current = nextValues.at(-1);
3316
+ announce("Group selected");
3317
+ if (closeOnSelect) {
3318
+ closeDropdown();
1620
3319
  }
1621
- selectValue(draftValue);
1622
- setIsOpen(false);
1623
3320
  };
1624
- const displayText = multiple && resolvedSelectedOptions.length ? resolvedSelectedOptions.map((option) => option.label).join(", ") : selectedOption?.label ?? placeholder;
1625
- return /* @__PURE__ */ jsxs9(
1626
- FormField,
3321
+ const contextValue = {
3322
+ label,
3323
+ description,
3324
+ error,
3325
+ placeholder,
3326
+ color,
3327
+ variant,
3328
+ size: resolvedSize,
3329
+ isOpen,
3330
+ hasValue,
3331
+ loading,
3332
+ clearable,
3333
+ searchable: shouldSearch,
3334
+ multiple: Boolean(props.multiple),
3335
+ maxSelected,
3336
+ virtual,
3337
+ resolvedLabel,
3338
+ resolvedHint,
3339
+ resolvedPresentation,
3340
+ placement,
3341
+ dismissOnBackdropPress,
3342
+ matchTriggerWidth,
3343
+ triggerWidth,
3344
+ selectedValues,
3345
+ selectedOptions,
3346
+ optionsByValue,
3347
+ rows,
3348
+ filteredRows,
3349
+ selectedRowIndex,
3350
+ itemHeight,
3351
+ query,
3352
+ searchPlaceholder: searchPlaceholder ?? searchPlaceholderFromChildren ?? "Search...",
3353
+ searchInputRef,
3354
+ empty: empty ?? emptyFromChildren ?? "Nothing found",
3355
+ loadingContent: loadingFromChildren ?? loadingText,
3356
+ closeContent: closeDropdown,
3357
+ openContent: openDropdown,
3358
+ clearValue,
3359
+ selectOption,
3360
+ selectGroup,
3361
+ setQuery,
3362
+ renderValue,
3363
+ renderOption,
3364
+ startIcon,
3365
+ endIcon,
3366
+ prefix,
3367
+ suffix,
3368
+ triggerStyle,
3369
+ textStyle,
3370
+ contentStyle,
3371
+ optionStyle,
3372
+ searchStyle,
3373
+ fieldControlId: !hasOwnField ? field?.controlId : void 0,
3374
+ fieldLabelId: !hasOwnField ? field?.labelId : void 0,
3375
+ fieldDescribedBy: !hasOwnField ? field?.ariaDescribedBy : void 0
3376
+ };
3377
+ const control = /* @__PURE__ */ jsx29(SelectContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs17(
3378
+ View23,
1627
3379
  {
1628
- label,
1629
- description,
1630
- error,
1631
- required,
1632
- disabled,
1633
- style,
3380
+ testID,
3381
+ onLayout: (event) => setTriggerWidth(event.nativeEvent.layout.width),
1634
3382
  children: [
1635
- /* @__PURE__ */ jsx17(
3383
+ /* @__PURE__ */ jsx29(
1636
3384
  SelectTrigger,
1637
3385
  {
1638
- displayText,
1639
- isPlaceholder: resolvedSelectedValues.length === 0,
3386
+ displayText: displayValue,
3387
+ isPlaceholder: !hasValue,
1640
3388
  isOpen,
1641
- size,
1642
- disabled,
1643
- required,
1644
- hasError,
3389
+ hasValue,
3390
+ size: resolvedSize,
3391
+ color,
3392
+ variant,
3393
+ disabled: isDisabled,
3394
+ required: isRequired,
3395
+ hasError: isInvalid,
3396
+ loading,
3397
+ clearable,
3398
+ startIcon,
3399
+ endIcon,
3400
+ prefix,
3401
+ suffix,
3402
+ nativeID: !hasOwnField ? field?.controlId : void 0,
1645
3403
  accessibilityLabel: resolvedLabel,
1646
- accessibilityHint,
3404
+ accessibilityHint: resolvedHint,
3405
+ accessibilityLabelledBy: !hasOwnField ? field?.labelId : void 0,
3406
+ ariaDescribedBy: !hasOwnField ? field?.ariaDescribedBy : void 0,
1647
3407
  triggerStyle,
1648
3408
  textStyle,
1649
- onPress: openPicker
3409
+ onPress: openDropdown,
3410
+ onClear: clearValue
1650
3411
  }
1651
3412
  ),
1652
- /* @__PURE__ */ jsx17(
1653
- Modal3,
1654
- {
1655
- transparent: true,
1656
- visible: isOpen,
1657
- animationType: "slide",
1658
- onRequestClose: closePicker,
1659
- children: /* @__PURE__ */ jsxs9(View13, { style: styles.modalRoot, children: [
1660
- /* @__PURE__ */ jsx17(Pressable7, { style: styles.backdrop, onPress: closePicker }),
1661
- /* @__PURE__ */ jsxs9(View13, { style: styles.sheet, children: [
1662
- /* @__PURE__ */ jsxs9(
1663
- View13,
1664
- {
1665
- style: styles.toolbar,
1666
- accessible: true,
1667
- accessibilityRole: "toolbar",
1668
- accessibilityLabel: `${resolvedLabel} picker actions`,
1669
- children: [
1670
- /* @__PURE__ */ jsx17(
1671
- Pressable7,
1672
- {
1673
- onPress: closePicker,
1674
- hitSlop: 8,
1675
- style: styles.toolbarAction,
1676
- accessibilityRole: "button",
1677
- accessibilityLabel: "Cancel selection",
1678
- accessibilityHint: "Closes the picker without changing the selected value",
1679
- children: /* @__PURE__ */ jsx17(Text8, { style: styles.cancelText, children: "Cancel" })
1680
- }
1681
- ),
1682
- /* @__PURE__ */ jsx17(
1683
- Text8,
1684
- {
1685
- style: styles.title,
1686
- numberOfLines: 1,
1687
- accessibilityRole: "header",
1688
- children: resolvedLabel
1689
- }
1690
- ),
1691
- /* @__PURE__ */ jsx17(
1692
- Pressable7,
1693
- {
1694
- onPress: confirmPicker,
1695
- hitSlop: 8,
1696
- style: styles.toolbarAction,
1697
- accessibilityRole: "button",
1698
- accessibilityLabel: "Confirm selection",
1699
- accessibilityHint: "Applies the highlighted picker value",
1700
- children: /* @__PURE__ */ jsx17(Text8, { style: styles.doneText, children: "Done" })
1701
- }
1702
- )
1703
- ]
1704
- }
1705
- ),
1706
- /* @__PURE__ */ jsxs9(
1707
- Picker,
1708
- {
1709
- selectedValue: draftValue,
1710
- onValueChange: handleValueChange,
1711
- enabled: !disabled,
1712
- style: [styles.picker, pickerStyle],
1713
- itemStyle: {
1714
- color: theme.components.select.option.default.fg
1715
- },
1716
- children: [
1717
- /* @__PURE__ */ jsx17(
1718
- Picker.Item,
1719
- {
1720
- label: placeholder,
1721
- value: "",
1722
- enabled: false,
1723
- color: theme.components.select.option.disabled.fg
1724
- }
1725
- ),
1726
- options.map((option) => /* @__PURE__ */ jsx17(
1727
- Picker.Item,
1728
- {
1729
- label: option.disabled ? `${option.label} - unavailable` : option.label,
1730
- value: option.value,
1731
- enabled: !option.disabled,
1732
- color: option.disabled ? theme.components.select.option.disabled.fg : theme.components.select.option.default.fg
1733
- },
1734
- option.value
1735
- ))
1736
- ]
1737
- }
1738
- )
1739
- ] })
1740
- ] })
1741
- }
1742
- )
3413
+ /* @__PURE__ */ jsx29(SelectContentSurface, {})
1743
3414
  ]
1744
3415
  }
3416
+ ) });
3417
+ if (!hasOwnField && field) {
3418
+ return control;
3419
+ }
3420
+ return /* @__PURE__ */ jsx29(
3421
+ FormField,
3422
+ {
3423
+ label,
3424
+ description,
3425
+ error,
3426
+ required: isRequired,
3427
+ disabled: isDisabled,
3428
+ invalid: isInvalid,
3429
+ size: resolvedSize,
3430
+ style,
3431
+ children: control
3432
+ }
1745
3433
  );
1746
3434
  }
1747
- Select.displayName = "Select";
3435
+ SelectRoot.displayName = "Select";
3436
+
3437
+ // src/components/Select/Select.tsx
3438
+ var Select = Object.assign(SelectRoot, {
3439
+ Trigger: SelectTriggerSlot,
3440
+ Value: SelectValue,
3441
+ Icon: SelectIcon,
3442
+ Content: SelectContent,
3443
+ Search: SelectSearch,
3444
+ Group: SelectGroup,
3445
+ Label: SelectLabel,
3446
+ Item: SelectItem,
3447
+ ItemIcon: SelectItemIcon,
3448
+ ItemDescription: SelectItemDescription,
3449
+ ItemBadge: SelectItemBadge,
3450
+ Separator: SelectSeparator,
3451
+ Empty: SelectEmpty,
3452
+ Loading: SelectLoading
3453
+ });
1748
3454
 
1749
3455
  // src/components/Tabs/List/TabsList.tsx
1750
- import { View as View14 } from "react-native";
3456
+ import { View as View24 } from "react-native";
1751
3457
 
1752
3458
  // src/components/Tabs/TabsContext.tsx
1753
- import { createContext as createContext5, useContext as useContext5 } from "react";
1754
- var TabsContext = createContext5(null);
3459
+ import { createContext as createContext6, useContext as useContext6 } from "react";
3460
+ var TabsContext = createContext6(null);
1755
3461
  var TabsProvider = TabsContext.Provider;
1756
3462
  var useTabs = () => {
1757
- const context = useContext5(TabsContext);
3463
+ const context = useContext6(TabsContext);
1758
3464
  if (!context) {
1759
3465
  throw new Error("Tabs components must be used inside <Tabs>.");
1760
3466
  }
@@ -1763,8 +3469,8 @@ var useTabs = () => {
1763
3469
  TabsContext.displayName = "TabsContext";
1764
3470
 
1765
3471
  // src/components/Tabs/List/TabsList.styles.ts
1766
- import { StyleSheet as StyleSheet16 } from "react-native";
1767
- var createStyles16 = (theme) => StyleSheet16.create({
3472
+ import { StyleSheet as StyleSheet20 } from "react-native";
3473
+ var createStyles14 = (theme) => StyleSheet20.create({
1768
3474
  list: {
1769
3475
  flexDirection: "row",
1770
3476
  alignSelf: "stretch",
@@ -1790,12 +3496,12 @@ var createStyles16 = (theme) => StyleSheet16.create({
1790
3496
  });
1791
3497
 
1792
3498
  // src/components/Tabs/List/TabsList.tsx
1793
- import { jsx as jsx18 } from "react/jsx-runtime";
3499
+ import { jsx as jsx30 } from "react/jsx-runtime";
1794
3500
  var TabsList = ({ children, style }) => {
1795
- const styles = useThemeStyles(createStyles16);
3501
+ const styles = useThemeStyles(createStyles14);
1796
3502
  const { orientation, appearance } = useTabs();
1797
- return /* @__PURE__ */ jsx18(
1798
- View14,
3503
+ return /* @__PURE__ */ jsx30(
3504
+ View24,
1799
3505
  {
1800
3506
  accessibilityRole: "tablist",
1801
3507
  style: [
@@ -1811,11 +3517,11 @@ var TabsList = ({ children, style }) => {
1811
3517
  TabsList.displayName = "TabsList";
1812
3518
 
1813
3519
  // src/components/Tabs/Panel/TabsPanel.tsx
1814
- import { View as View15 } from "react-native";
3520
+ import { View as View25 } from "react-native";
1815
3521
 
1816
3522
  // src/components/Tabs/Panel/TabsPanel.styles.ts
1817
- import { StyleSheet as StyleSheet17 } from "react-native";
1818
- var createStyles17 = (theme) => StyleSheet17.create({
3523
+ import { StyleSheet as StyleSheet21 } from "react-native";
3524
+ var createStyles15 = (theme) => StyleSheet21.create({
1819
3525
  panel: {
1820
3526
  width: "100%",
1821
3527
  minWidth: 0,
@@ -1842,13 +3548,13 @@ var createStyles17 = (theme) => StyleSheet17.create({
1842
3548
  });
1843
3549
 
1844
3550
  // src/components/Tabs/Panel/TabsPanel.tsx
1845
- import { jsx as jsx19 } from "react/jsx-runtime";
3551
+ import { jsx as jsx31 } from "react/jsx-runtime";
1846
3552
  var TabsPanel = ({ index, children, style }) => {
1847
- const styles = useThemeStyles(createStyles17);
3553
+ const styles = useThemeStyles(createStyles15);
1848
3554
  const { activeIndex, orientation } = useTabs();
1849
3555
  if (activeIndex !== index) return null;
1850
- return /* @__PURE__ */ jsx19(
1851
- View15,
3556
+ return /* @__PURE__ */ jsx31(
3557
+ View25,
1852
3558
  {
1853
3559
  style: [
1854
3560
  styles.panel,
@@ -1862,13 +3568,13 @@ var TabsPanel = ({ index, children, style }) => {
1862
3568
  TabsPanel.displayName = "TabsPanel";
1863
3569
 
1864
3570
  // src/components/Tabs/Tab/Tab.tsx
1865
- import { cloneElement as cloneElement4, isValidElement as isValidElement4 } from "react";
1866
- import { Pressable as Pressable8, Text as Text9, View as View16 } from "react-native";
3571
+ import { cloneElement as cloneElement6, isValidElement as isValidElement8 } from "react";
3572
+ import { Pressable as Pressable12, Text as Text14, View as View26 } from "react-native";
1867
3573
 
1868
3574
  // src/components/Tabs/Tab/Tab.styles.ts
1869
- import { StyleSheet as StyleSheet18 } from "react-native";
3575
+ import { StyleSheet as StyleSheet22 } from "react-native";
1870
3576
  var fontWeight2 = (value) => value;
1871
- var createStyles18 = (theme) => StyleSheet18.create({
3577
+ var createStyles16 = (theme) => StyleSheet22.create({
1872
3578
  tab: {
1873
3579
  minHeight: 40,
1874
3580
  alignItems: "center",
@@ -1986,7 +3692,7 @@ var createStyles18 = (theme) => StyleSheet18.create({
1986
3692
  });
1987
3693
 
1988
3694
  // src/components/Tabs/Tab/Tab.tsx
1989
- import { Fragment as Fragment2, jsx as jsx20, jsxs as jsxs10 } from "react/jsx-runtime";
3695
+ import { Fragment as Fragment4, jsx as jsx32, jsxs as jsxs18 } from "react/jsx-runtime";
1990
3696
  var Tab = ({
1991
3697
  index,
1992
3698
  children,
@@ -1996,7 +3702,7 @@ var Tab = ({
1996
3702
  textStyle
1997
3703
  }) => {
1998
3704
  const { theme } = useTheme();
1999
- const styles = useThemeStyles(createStyles18);
3705
+ const styles = useThemeStyles(createStyles16);
2000
3706
  const { activeIndex, appearance, orientation, setActiveIndex } = useTabs();
2001
3707
  const isActive = activeIndex === index;
2002
3708
  const isPills = appearance === "pills";
@@ -2004,11 +3710,11 @@ var Tab = ({
2004
3710
  const isDefault = appearance === "default";
2005
3711
  const isVertical = orientation === "vertical";
2006
3712
  const iconColor = isPills && isActive ? theme.components.tabs.pills.active.fg : isActive ? theme.components.tabs.trigger.active.fg : theme.components.tabs.trigger.default.fg;
2007
- const renderedIcon = isValidElement4(icon) ? cloneElement4(icon, {
3713
+ const renderedIcon = isValidElement8(icon) ? cloneElement6(icon, {
2008
3714
  color: iconColor
2009
3715
  }) : icon;
2010
- return /* @__PURE__ */ jsx20(
2011
- Pressable8,
3716
+ return /* @__PURE__ */ jsx32(
3717
+ Pressable12,
2012
3718
  {
2013
3719
  disabled,
2014
3720
  accessibilityRole: "tab",
@@ -2028,9 +3734,9 @@ var Tab = ({
2028
3734
  disabled && styles.tabDisabled,
2029
3735
  style
2030
3736
  ],
2031
- children: ({ pressed }) => /* @__PURE__ */ jsxs10(Fragment2, { children: [
2032
- isUnderline && !isVertical && /* @__PURE__ */ jsx20(
2033
- View16,
3737
+ children: ({ pressed }) => /* @__PURE__ */ jsxs18(Fragment4, { children: [
3738
+ isUnderline && !isVertical && /* @__PURE__ */ jsx32(
3739
+ View26,
2034
3740
  {
2035
3741
  pointerEvents: "none",
2036
3742
  style: [
@@ -2039,8 +3745,8 @@ var Tab = ({
2039
3745
  ]
2040
3746
  }
2041
3747
  ),
2042
- isUnderline && isVertical && /* @__PURE__ */ jsx20(
2043
- View16,
3748
+ isUnderline && isVertical && /* @__PURE__ */ jsx32(
3749
+ View26,
2044
3750
  {
2045
3751
  pointerEvents: "none",
2046
3752
  style: [
@@ -2050,9 +3756,9 @@ var Tab = ({
2050
3756
  ]
2051
3757
  }
2052
3758
  ),
2053
- icon != null && /* @__PURE__ */ jsx20(View16, { style: styles.tabIcon, children: renderedIcon }),
2054
- children != null && /* @__PURE__ */ jsx20(
2055
- Text9,
3759
+ icon != null && /* @__PURE__ */ jsx32(View26, { style: styles.tabIcon, children: renderedIcon }),
3760
+ children != null && /* @__PURE__ */ jsx32(
3761
+ Text14,
2056
3762
  {
2057
3763
  numberOfLines: 2,
2058
3764
  ellipsizeMode: "tail",
@@ -2073,13 +3779,13 @@ var Tab = ({
2073
3779
  Tab.displayName = "Tab";
2074
3780
 
2075
3781
  // src/components/Tabs/Tabs.tsx
2076
- import { useMemo as useMemo4 } from "react";
3782
+ import { useMemo as useMemo7 } from "react";
2077
3783
  import { useTabs as useTabs2 } from "@vellira-ui/core";
2078
- import { View as View17 } from "react-native";
3784
+ import { View as View27 } from "react-native";
2079
3785
 
2080
3786
  // src/components/Tabs/Tabs.styles.ts
2081
- import { StyleSheet as StyleSheet19 } from "react-native";
2082
- var createStyles19 = (theme) => StyleSheet19.create({
3787
+ import { StyleSheet as StyleSheet23 } from "react-native";
3788
+ var createStyles17 = (theme) => StyleSheet23.create({
2083
3789
  root: {
2084
3790
  width: "100%",
2085
3791
  minWidth: 0
@@ -2094,7 +3800,7 @@ var createStyles19 = (theme) => StyleSheet19.create({
2094
3800
  });
2095
3801
 
2096
3802
  // src/components/Tabs/Tabs.tsx
2097
- import { jsx as jsx21 } from "react/jsx-runtime";
3803
+ import { jsx as jsx33 } from "react/jsx-runtime";
2098
3804
  var TabsRoot = ({
2099
3805
  children,
2100
3806
  activeIndex: controlledActiveIndex,
@@ -2104,19 +3810,19 @@ var TabsRoot = ({
2104
3810
  appearance = "pills",
2105
3811
  style
2106
3812
  }) => {
2107
- const styles = useThemeStyles(createStyles19);
3813
+ const styles = useThemeStyles(createStyles17);
2108
3814
  const { activeIndex, setActiveIndex } = useTabs2({
2109
3815
  activeIndex: controlledActiveIndex,
2110
3816
  defaultActiveIndex,
2111
3817
  onChange,
2112
3818
  orientation
2113
3819
  });
2114
- const value = useMemo4(
3820
+ const value = useMemo7(
2115
3821
  () => ({ activeIndex, appearance, orientation, setActiveIndex }),
2116
3822
  [activeIndex, appearance, orientation, setActiveIndex]
2117
3823
  );
2118
- return /* @__PURE__ */ jsx21(TabsProvider, { value, children: /* @__PURE__ */ jsx21(
2119
- View17,
3824
+ return /* @__PURE__ */ jsx33(TabsProvider, { value, children: /* @__PURE__ */ jsx33(
3825
+ View27,
2120
3826
  {
2121
3827
  style: [
2122
3828
  styles.root,
@@ -2137,20 +3843,20 @@ var Tabs = Object.assign(TabsRoot, {
2137
3843
  });
2138
3844
 
2139
3845
  // src/components/Tooltip/Tooltip.tsx
2140
- import { useEffect as useEffect3, useRef as useRef3, useState as useState4 } from "react";
2141
- import { Modal as Modal4, Pressable as Pressable9, Text as Text10, View as View18 } from "react-native";
3846
+ import { useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
3847
+ import { Modal as Modal6, Pressable as Pressable13, Text as Text15, View as View28 } from "react-native";
2142
3848
 
2143
3849
  // src/hooks/useNativeFloatingPosition.ts
2144
- import { useCallback as useCallback2, useRef as useRef2, useState as useState3 } from "react";
3850
+ import { useCallback as useCallback2, useRef as useRef5, useState as useState5 } from "react";
2145
3851
  import { Dimensions } from "react-native";
2146
3852
  var safePadding = 12;
2147
3853
  function useNativeFloatingPosition(placement = "top", offset = 8) {
2148
- const [position, setPosition] = useState3({ top: 0, left: 0 });
2149
- const floatingSizeRef = useRef2({
3854
+ const [position, setPosition] = useState5({ top: 0, left: 0 });
3855
+ const floatingSizeRef = useRef5({
2150
3856
  width: 0,
2151
3857
  height: 0
2152
3858
  });
2153
- const lastTriggerRef = useRef2(null);
3859
+ const lastTriggerRef = useRef5(null);
2154
3860
  const clamp = useCallback2((value, min, max) => {
2155
3861
  return Math.min(Math.max(value, min), Math.max(min, max));
2156
3862
  }, []);
@@ -2207,13 +3913,13 @@ function useNativeFloatingPosition(placement = "top", offset = 8) {
2207
3913
  }
2208
3914
 
2209
3915
  // src/components/Tooltip/Tooltip.styles.ts
2210
- import { StyleSheet as StyleSheet20 } from "react-native";
2211
- var createStyles20 = (theme) => StyleSheet20.create({
3916
+ import { StyleSheet as StyleSheet24 } from "react-native";
3917
+ var createStyles18 = (theme) => StyleSheet24.create({
2212
3918
  root: {
2213
3919
  alignSelf: "flex-start"
2214
3920
  },
2215
3921
  overlay: {
2216
- ...StyleSheet20.absoluteFill
3922
+ ...StyleSheet24.absoluteFill
2217
3923
  },
2218
3924
  bubble: {
2219
3925
  position: "absolute",
@@ -2245,7 +3951,7 @@ var createStyles20 = (theme) => StyleSheet20.create({
2245
3951
  });
2246
3952
 
2247
3953
  // src/components/Tooltip/Tooltip.tsx
2248
- import { jsx as jsx22, jsxs as jsxs11 } from "react/jsx-runtime";
3954
+ import { jsx as jsx34, jsxs as jsxs19 } from "react/jsx-runtime";
2249
3955
  function Tooltip({
2250
3956
  children,
2251
3957
  content,
@@ -2257,10 +3963,10 @@ function Tooltip({
2257
3963
  contentStyle,
2258
3964
  textStyle
2259
3965
  }) {
2260
- const styles = useThemeStyles(createStyles20);
2261
- const [visible, setVisible] = useState4(false);
2262
- const triggerRef = useRef3(null);
2263
- const closeTimerRef = useRef3(null);
3966
+ const styles = useThemeStyles(createStyles18);
3967
+ const [visible, setVisible] = useState6(false);
3968
+ const triggerRef = useRef6(null);
3969
+ const closeTimerRef = useRef6(null);
2264
3970
  const { position, updatePosition, onFloatingLayout } = useNativeFloatingPosition(placement, 8);
2265
3971
  const hideDelay = delay?.close ?? 2500;
2266
3972
  const clearCloseTimer = () => {
@@ -2279,21 +3985,21 @@ function Tooltip({
2279
3985
  closeTimerRef.current = null;
2280
3986
  }, hideDelay);
2281
3987
  };
2282
- useEffect3(() => {
3988
+ useEffect6(() => {
2283
3989
  return clearCloseTimer;
2284
3990
  }, []);
2285
- return /* @__PURE__ */ jsxs11(View18, { style: [styles.root, style], children: [
2286
- /* @__PURE__ */ jsx22(Pressable9, { ref: triggerRef, onLongPress: showTooltip, children }),
2287
- /* @__PURE__ */ jsx22(Modal4, { visible: visible && !disabled, transparent: true, animationType: "fade", children: /* @__PURE__ */ jsx22(
2288
- Pressable9,
3991
+ return /* @__PURE__ */ jsxs19(View28, { style: [styles.root, style], children: [
3992
+ /* @__PURE__ */ jsx34(Pressable13, { ref: triggerRef, onLongPress: showTooltip, children }),
3993
+ /* @__PURE__ */ jsx34(Modal6, { visible: visible && !disabled, transparent: true, animationType: "fade", children: /* @__PURE__ */ jsx34(
3994
+ Pressable13,
2289
3995
  {
2290
3996
  style: styles.overlay,
2291
3997
  onPress: () => {
2292
3998
  clearCloseTimer();
2293
3999
  setVisible(false);
2294
4000
  },
2295
- children: /* @__PURE__ */ jsx22(
2296
- View18,
4001
+ children: /* @__PURE__ */ jsx34(
4002
+ View28,
2297
4003
  {
2298
4004
  pointerEvents: "none",
2299
4005
  style: [
@@ -2306,7 +4012,7 @@ function Tooltip({
2306
4012
  contentStyle
2307
4013
  ],
2308
4014
  onLayout: onFloatingLayout,
2309
- children: typeof content === "string" ? /* @__PURE__ */ jsx22(Text10, { style: [styles.text, textStyle], children: content }) : content
4015
+ children: typeof content === "string" ? /* @__PURE__ */ jsx34(Text15, { style: [styles.text, textStyle], children: content }) : content
2310
4016
  }
2311
4017
  )
2312
4018
  }
@@ -2316,8 +4022,8 @@ function Tooltip({
2316
4022
  Tooltip.displayName = "Tooltip";
2317
4023
 
2318
4024
  // src/primitives/Button/Button.tsx
2319
- import { cloneElement as cloneElement5, useState as useState5 } from "react";
2320
- import { ActivityIndicator, Pressable as Pressable10, Text as Text11, View as View19 } from "react-native";
4025
+ import { cloneElement as cloneElement7, useState as useState7 } from "react";
4026
+ import { ActivityIndicator as ActivityIndicator3, Pressable as Pressable14, Text as Text16, View as View29 } from "react-native";
2321
4027
 
2322
4028
  // src/utils/devWarning.ts
2323
4029
  var devWarning = (condition, message) => {
@@ -2327,9 +4033,9 @@ var devWarning = (condition, message) => {
2327
4033
  };
2328
4034
 
2329
4035
  // src/primitives/Button/Button.styles.ts
2330
- import { StyleSheet as StyleSheet21 } from "react-native";
4036
+ import { StyleSheet as StyleSheet25 } from "react-native";
2331
4037
  var fontWeight3 = (value) => value;
2332
- var createStyles21 = (theme) => StyleSheet21.create({
4038
+ var createStyles19 = (theme) => StyleSheet25.create({
2333
4039
  button: {
2334
4040
  flexDirection: "row",
2335
4041
  alignItems: "center",
@@ -2394,7 +4100,7 @@ var createStyles21 = (theme) => StyleSheet21.create({
2394
4100
  });
2395
4101
 
2396
4102
  // src/primitives/Button/Button.tsx
2397
- import { Fragment as Fragment3, jsx as jsx23, jsxs as jsxs12 } from "react/jsx-runtime";
4103
+ import { Fragment as Fragment5, jsx as jsx35, jsxs as jsxs20 } from "react/jsx-runtime";
2398
4104
  var sizeMap = {
2399
4105
  sm: {
2400
4106
  px: 12,
@@ -2446,13 +4152,13 @@ function Button({
2446
4152
  ...props
2447
4153
  }) {
2448
4154
  const { theme } = useTheme();
2449
- const styles = useThemeStyles(createStyles21);
4155
+ const styles = useThemeStyles(createStyles19);
2450
4156
  const config = sizeMap[size];
2451
4157
  const radius = shape === "square" ? theme.tokens.radius.sm : shape === "rounded" ? theme.tokens.radius.md : theme.tokens.radius.full;
2452
4158
  const appearanceTheme = theme.components.button[color][appearance];
2453
- const [isHovered, setIsHovered] = useState5(false);
2454
- const [isFocused, setIsFocused] = useState5(false);
2455
- const [labelWidth, setLabelWidth] = useState5(0);
4159
+ const [isHovered, setIsHovered] = useState7(false);
4160
+ const [isFocused, setIsFocused] = useState7(false);
4161
+ const [labelWidth, setLabelWidth] = useState7(0);
2456
4162
  const isDisabled = disabled || loading;
2457
4163
  const iconOnly = iconOnlyProp || !children && Boolean(iconStart || iconEnd);
2458
4164
  const content = loading && loadingText ? loadingText : children;
@@ -2478,7 +4184,7 @@ function Button({
2478
4184
  setIsHovered(false);
2479
4185
  onHoverOut?.(event);
2480
4186
  };
2481
- const renderIcon = (icon, iconColor) => cloneElement5(icon, {
4187
+ const renderIcon = (icon, iconColor) => cloneElement7(icon, {
2482
4188
  color: iconColor,
2483
4189
  size: resolvedIconSize
2484
4190
  });
@@ -2489,8 +4195,8 @@ function Button({
2489
4195
  );
2490
4196
  };
2491
4197
  const getInteractionTheme = (pressed) => isDisabled ? theme.components.button.disabled : pressed ? appearanceTheme.pressed : isHovered ? appearanceTheme.hover : appearanceTheme.default;
2492
- return /* @__PURE__ */ jsx23(
2493
- Pressable10,
4198
+ return /* @__PURE__ */ jsx35(
4199
+ Pressable14,
2494
4200
  {
2495
4201
  ...props,
2496
4202
  testID,
@@ -2526,12 +4232,12 @@ function Button({
2526
4232
  children: ({ pressed }) => {
2527
4233
  const interactionTheme = getInteractionTheme(pressed);
2528
4234
  const contentColor = interactionTheme.fg;
2529
- return /* @__PURE__ */ jsxs12(Fragment3, { children: [
2530
- loading && /* @__PURE__ */ jsx23(ActivityIndicator, { size: "small", color: contentColor }),
4235
+ return /* @__PURE__ */ jsxs20(Fragment5, { children: [
4236
+ loading && /* @__PURE__ */ jsx35(ActivityIndicator3, { size: "small", color: contentColor }),
2531
4237
  !loading && iconStart && renderIcon(iconStart, contentColor),
2532
- content && !iconOnly && /* @__PURE__ */ jsxs12(View19, { style: styles.labelSlot, children: [
2533
- /* @__PURE__ */ jsx23(
2534
- Text11,
4238
+ content && !iconOnly && /* @__PURE__ */ jsxs20(View29, { style: styles.labelSlot, children: [
4239
+ /* @__PURE__ */ jsx35(
4240
+ Text16,
2535
4241
  {
2536
4242
  onLayout: handleLabelLayout,
2537
4243
  style: [
@@ -2546,8 +4252,8 @@ function Button({
2546
4252
  children: content
2547
4253
  }
2548
4254
  ),
2549
- measureLabel && /* @__PURE__ */ jsx23(
2550
- Text11,
4255
+ measureLabel && /* @__PURE__ */ jsx35(
4256
+ Text16,
2551
4257
  {
2552
4258
  accessibilityElementsHidden: true,
2553
4259
  importantForAccessibility: "no-hide-descendants",
@@ -2564,8 +4270,8 @@ function Button({
2564
4270
  }
2565
4271
  )
2566
4272
  ] }),
2567
- badge && !iconOnly && /* @__PURE__ */ jsx23(
2568
- Text11,
4273
+ badge && !iconOnly && /* @__PURE__ */ jsx35(
4274
+ Text16,
2569
4275
  {
2570
4276
  style: [
2571
4277
  styles.badge,
@@ -2577,8 +4283,8 @@ function Button({
2577
4283
  children: badge
2578
4284
  }
2579
4285
  ),
2580
- shortcut && !iconOnly && /* @__PURE__ */ jsx23(
2581
- Text11,
4286
+ shortcut && !iconOnly && /* @__PURE__ */ jsx35(
4287
+ Text16,
2582
4288
  {
2583
4289
  style: [
2584
4290
  styles.shortcut,
@@ -2597,14 +4303,14 @@ function Button({
2597
4303
  }
2598
4304
 
2599
4305
  // src/primitives/Checkbox/Checkbox.tsx
2600
- import { forwardRef as forwardRef2, useEffect as useEffect4 } from "react";
4306
+ import { forwardRef as forwardRef2, useEffect as useEffect7 } from "react";
2601
4307
  import { useControllableState as useControllableState3 } from "@vellira-ui/core";
2602
- import { Check } from "@vellira-ui/icons";
2603
- import { Pressable as Pressable11, Text as Text12, View as View20 } from "react-native";
4308
+ import { Check as Check2 } from "@vellira-ui/icons";
4309
+ import { Pressable as Pressable15, Text as Text17, View as View30 } from "react-native";
2604
4310
 
2605
4311
  // src/primitives/Checkbox/Checkbox.styles.ts
2606
- import { StyleSheet as StyleSheet22 } from "react-native";
2607
- var createStyles22 = (theme) => StyleSheet22.create({
4312
+ import { StyleSheet as StyleSheet26 } from "react-native";
4313
+ var createStyles20 = (theme) => StyleSheet26.create({
2608
4314
  container: {
2609
4315
  gap: theme.tokens.spacing[2]
2610
4316
  },
@@ -2747,7 +4453,7 @@ var createStyles22 = (theme) => StyleSheet22.create({
2747
4453
  });
2748
4454
 
2749
4455
  // src/primitives/Checkbox/Checkbox.tsx
2750
- import { Fragment as Fragment4, jsx as jsx24, jsxs as jsxs13 } from "react/jsx-runtime";
4456
+ import { Fragment as Fragment6, jsx as jsx36, jsxs as jsxs21 } from "react/jsx-runtime";
2751
4457
  var iconSizeBySize = {
2752
4458
  sm: 10,
2753
4459
  md: 12,
@@ -2775,7 +4481,7 @@ var Checkbox = forwardRef2(
2775
4481
  ...PressableProps
2776
4482
  }, ref) => {
2777
4483
  const { theme } = useTheme();
2778
- const styles = useThemeStyles(createStyles22);
4484
+ const styles = useThemeStyles(createStyles20);
2779
4485
  const checkboxColor = theme.components.checkbox[color];
2780
4486
  const boxSizeStyle = {
2781
4487
  sm: styles.boxSm,
@@ -2805,15 +4511,15 @@ var Checkbox = forwardRef2(
2805
4511
  const resolvedAccessibilityLabel = accessibilityLabel ?? label;
2806
4512
  const resolvedAccessibilityHint = [accessibilityHint, description, error].filter(Boolean).join(" ");
2807
4513
  const accessibilityChecked = indeterminate ? "mixed" : isChecked;
2808
- useEffect4(() => {
4514
+ useEffect7(() => {
2809
4515
  devWarning(
2810
4516
  Boolean(resolvedAccessibilityLabel),
2811
4517
  "Checkbox: an accessible label must be provided through label or accessibilityLabel."
2812
4518
  );
2813
4519
  }, [resolvedAccessibilityLabel]);
2814
- return /* @__PURE__ */ jsxs13(View20, { style: styles.container, children: [
2815
- /* @__PURE__ */ jsx24(
2816
- Pressable11,
4520
+ return /* @__PURE__ */ jsxs21(View30, { style: styles.container, children: [
4521
+ /* @__PURE__ */ jsx36(
4522
+ Pressable15,
2817
4523
  {
2818
4524
  ...PressableProps,
2819
4525
  ref,
@@ -2836,9 +4542,9 @@ var Checkbox = forwardRef2(
2836
4542
  children: ({ pressed }) => {
2837
4543
  const isSelected = isChecked || indeterminate;
2838
4544
  const checkColor = disabled ? theme.components.checkbox.disabled.fg : pressed && isSelected ? checkboxColor.pressed.fg : checkboxColor.default.fg;
2839
- return /* @__PURE__ */ jsxs13(Fragment4, { children: [
2840
- /* @__PURE__ */ jsx24(
2841
- View20,
4545
+ return /* @__PURE__ */ jsxs21(Fragment6, { children: [
4546
+ /* @__PURE__ */ jsx36(
4547
+ View30,
2842
4548
  {
2843
4549
  style: [
2844
4550
  styles.box,
@@ -2855,8 +4561,8 @@ var Checkbox = forwardRef2(
2855
4561
  hasError && styles.boxError,
2856
4562
  disabled && styles.boxDisabled
2857
4563
  ],
2858
- children: indeterminate ? indeterminateIcon ?? /* @__PURE__ */ jsx24(
2859
- View20,
4564
+ children: indeterminate ? indeterminateIcon ?? /* @__PURE__ */ jsx36(
4565
+ View30,
2860
4566
  {
2861
4567
  style: [
2862
4568
  styles.indeterminateMark,
@@ -2865,11 +4571,11 @@ var Checkbox = forwardRef2(
2865
4571
  }
2866
4572
  ]
2867
4573
  }
2868
- ) : isChecked && (icon ?? /* @__PURE__ */ jsx24(Check, { size: iconSizeBySize[size], color: checkColor }))
4574
+ ) : isChecked && (icon ?? /* @__PURE__ */ jsx36(Check2, { size: iconSizeBySize[size], color: checkColor }))
2869
4575
  }
2870
4576
  ),
2871
- label && /* @__PURE__ */ jsxs13(
2872
- Text12,
4577
+ label && /* @__PURE__ */ jsxs21(
4578
+ Text17,
2873
4579
  {
2874
4580
  style: [
2875
4581
  styles.label,
@@ -2882,7 +4588,7 @@ var Checkbox = forwardRef2(
2882
4588
  ],
2883
4589
  children: [
2884
4590
  label,
2885
- required && /* @__PURE__ */ jsx24(Text12, { style: styles.requiredMark, children: " *" })
4591
+ required && /* @__PURE__ */ jsx36(Text17, { style: styles.requiredMark, children: " *" })
2886
4592
  ]
2887
4593
  }
2888
4594
  )
@@ -2890,8 +4596,8 @@ var Checkbox = forwardRef2(
2890
4596
  }
2891
4597
  }
2892
4598
  ),
2893
- description && /* @__PURE__ */ jsx24(
2894
- Text12,
4599
+ description && /* @__PURE__ */ jsx36(
4600
+ Text17,
2895
4601
  {
2896
4602
  style: [
2897
4603
  styles.descriptionText,
@@ -2901,21 +4607,21 @@ var Checkbox = forwardRef2(
2901
4607
  children: description
2902
4608
  }
2903
4609
  ),
2904
- hasError && /* @__PURE__ */ jsx24(Text12, { style: [styles.errorText, helperTextSizeStyle[size]], children: error })
4610
+ hasError && /* @__PURE__ */ jsx36(Text17, { style: [styles.errorText, helperTextSizeStyle[size]], children: error })
2905
4611
  ] });
2906
4612
  }
2907
4613
  );
2908
4614
  Checkbox.displayName = "Checkbox";
2909
4615
 
2910
4616
  // src/primitives/Input/Input.tsx
2911
- import { cloneElement as cloneElement6, forwardRef as forwardRef3, useState as useState6 } from "react";
2912
- import { Pressable as Pressable12, Text as Text13, TextInput, View as View21 } from "react-native";
4617
+ import { cloneElement as cloneElement8, forwardRef as forwardRef3, useState as useState8 } from "react";
4618
+ import { Pressable as Pressable16, Text as Text18, TextInput as TextInput2, View as View31 } from "react-native";
2913
4619
 
2914
4620
  // src/primitives/Input/Input.styles.ts
2915
- import { StyleSheet as StyleSheet23 } from "react-native";
4621
+ import { StyleSheet as StyleSheet27 } from "react-native";
2916
4622
  var getDisabledPlaceholderTextColor = (theme) => theme.components.input.disabled.placeholder;
2917
4623
  var resolveRingColor = (ring) => typeof ring === "string" ? ring : ring.color;
2918
- var createStyles23 = (theme) => StyleSheet23.create({
4624
+ var createStyles21 = (theme) => StyleSheet27.create({
2919
4625
  inputWrapper: {
2920
4626
  position: "relative",
2921
4627
  width: "100%",
@@ -3059,7 +4765,7 @@ var createStyles23 = (theme) => StyleSheet23.create({
3059
4765
  });
3060
4766
 
3061
4767
  // src/primitives/Input/Input.tsx
3062
- import { jsx as jsx25, jsxs as jsxs14 } from "react/jsx-runtime";
4768
+ import { jsx as jsx37, jsxs as jsxs22 } from "react/jsx-runtime";
3063
4769
  var keyboardTypeByInputType = {
3064
4770
  text: "default",
3065
4771
  email: "email-address",
@@ -3157,11 +4863,11 @@ var Input = forwardRef3(
3157
4863
  ...props
3158
4864
  }, ref) => {
3159
4865
  const { theme } = useTheme();
3160
- const styles = useThemeStyles(createStyles23);
4866
+ const styles = useThemeStyles(createStyles21);
3161
4867
  const field = useFormFieldContext();
3162
4868
  const hasOwnField = Boolean(label || description || error);
3163
- const [isFocused, setIsFocused] = useState6(false);
3164
- const [uncontrolledValue, setUncontrolledValue] = useState6(
4869
+ const [isFocused, setIsFocused] = useState8(false);
4870
+ const [uncontrolledValue, setUncontrolledValue] = useState8(
3165
4871
  defaultValue ?? ""
3166
4872
  );
3167
4873
  const isControlled = value !== void 0;
@@ -3178,7 +4884,7 @@ var Input = forwardRef3(
3178
4884
  const isReadOnly = readOnly || loading;
3179
4885
  const placeholderTextColor = isDisabled ? getDisabledPlaceholderTextColor(theme) : readOnly ? theme.components.input.readOnly.placeholder : inputState.placeholder;
3180
4886
  const isPassword = type === "password";
3181
- const [isPasswordRevealed, setIsPasswordRevealed] = useState6(false);
4887
+ const [isPasswordRevealed, setIsPasswordRevealed] = useState8(false);
3182
4888
  const resolvedIconSize = iconSize ?? 16;
3183
4889
  const handleFocus = (event) => {
3184
4890
  setIsFocused(true);
@@ -3209,22 +4915,22 @@ var Input = forwardRef3(
3209
4915
  const startIconColor = isDisabled ? theme.components.input.disabled.icon : theme.components.input.icon[startIconTone];
3210
4916
  const endIconColor = isDisabled ? theme.components.input.disabled.icon : theme.components.input.icon[endIconTone];
3211
4917
  const clearIconColor = isDisabled ? theme.components.input.disabled.icon : theme.components.input.icon[clearIconTone];
3212
- const control = /* @__PURE__ */ jsxs14(View21, { style: styles.inputWrapper, children: [
3213
- startIcon && /* @__PURE__ */ jsx25(
3214
- View21,
4918
+ const control = /* @__PURE__ */ jsxs22(View31, { style: styles.inputWrapper, children: [
4919
+ startIcon && /* @__PURE__ */ jsx37(
4920
+ View31,
3215
4921
  {
3216
4922
  pointerEvents: "none",
3217
4923
  style: styles.leftIcon,
3218
4924
  accessibilityElementsHidden: true,
3219
4925
  importantForAccessibility: "no",
3220
- children: cloneElement6(startIcon, {
4926
+ children: cloneElement8(startIcon, {
3221
4927
  color: startIconColor,
3222
4928
  size: resolvedIconSize
3223
4929
  })
3224
4930
  }
3225
4931
  ),
3226
- /* @__PURE__ */ jsx25(
3227
- TextInput,
4932
+ /* @__PURE__ */ jsx37(
4933
+ TextInput2,
3228
4934
  {
3229
4935
  ...props,
3230
4936
  ref,
@@ -3279,37 +4985,37 @@ var Input = forwardRef3(
3279
4985
  ]
3280
4986
  }
3281
4987
  ),
3282
- showClearButton ? /* @__PURE__ */ jsx25(
3283
- Pressable12,
4988
+ showClearButton ? /* @__PURE__ */ jsx37(
4989
+ Pressable16,
3284
4990
  {
3285
4991
  accessibilityRole: "button",
3286
4992
  accessibilityLabel: "Clear input",
3287
4993
  hitSlop: 8,
3288
4994
  onPress: handleClear,
3289
4995
  style: styles.clearButton,
3290
- children: clearIcon ? cloneElement6(clearIcon, {
4996
+ children: clearIcon ? cloneElement8(clearIcon, {
3291
4997
  color: clearIconColor,
3292
4998
  size: resolvedIconSize
3293
- }) : /* @__PURE__ */ jsx25(Text13, { style: [styles.clearButtonText, { color: clearIconColor }], children: "\xD7" })
4999
+ }) : /* @__PURE__ */ jsx37(Text18, { style: [styles.clearButtonText, { color: clearIconColor }], children: "\xD7" })
3294
5000
  }
3295
- ) : showRevealButton ? /* @__PURE__ */ jsx25(
3296
- Pressable12,
5001
+ ) : showRevealButton ? /* @__PURE__ */ jsx37(
5002
+ Pressable16,
3297
5003
  {
3298
5004
  accessibilityRole: "button",
3299
5005
  accessibilityLabel: isPasswordRevealed ? "Hide password" : "Show password",
3300
5006
  hitSlop: 8,
3301
5007
  onPress: () => setIsPasswordRevealed((revealed) => !revealed),
3302
5008
  style: styles.revealButton,
3303
- children: /* @__PURE__ */ jsx25(Text13, { style: styles.revealButtonText, children: isPasswordRevealed ? "Hide" : "Show" })
5009
+ children: /* @__PURE__ */ jsx37(Text18, { style: styles.revealButtonText, children: isPasswordRevealed ? "Hide" : "Show" })
3304
5010
  }
3305
- ) : showRightIcon && endIcon && /* @__PURE__ */ jsx25(
3306
- View21,
5011
+ ) : showRightIcon && endIcon && /* @__PURE__ */ jsx37(
5012
+ View31,
3307
5013
  {
3308
5014
  pointerEvents: "none",
3309
5015
  style: styles.rightIcon,
3310
5016
  accessibilityElementsHidden: true,
3311
5017
  importantForAccessibility: "no",
3312
- children: cloneElement6(endIcon, {
5018
+ children: cloneElement8(endIcon, {
3313
5019
  color: endIconColor,
3314
5020
  size: resolvedIconSize
3315
5021
  })
@@ -3319,7 +5025,7 @@ var Input = forwardRef3(
3319
5025
  if (!hasOwnField && field) {
3320
5026
  return control;
3321
5027
  }
3322
- return /* @__PURE__ */ jsx25(
5028
+ return /* @__PURE__ */ jsx37(
3323
5029
  FormField,
3324
5030
  {
3325
5031
  label,
@@ -3338,17 +5044,17 @@ var Input = forwardRef3(
3338
5044
  Input.displayName = "Input";
3339
5045
 
3340
5046
  // src/primitives/Radio/Radio.tsx
3341
- import { forwardRef as forwardRef4, useEffect as useEffect5 } from "react";
5047
+ import { forwardRef as forwardRef4, useEffect as useEffect8 } from "react";
3342
5048
  import { useControllableState as useControllableState4 } from "@vellira-ui/core";
3343
5049
  import {
3344
- Pressable as Pressable13,
3345
- Text as Text14,
3346
- View as View22
5050
+ Pressable as Pressable17,
5051
+ Text as Text19,
5052
+ View as View32
3347
5053
  } from "react-native";
3348
5054
 
3349
5055
  // src/primitives/Radio/Radio.styles.ts
3350
- import { StyleSheet as StyleSheet24 } from "react-native";
3351
- var createStyles24 = (theme) => StyleSheet24.create({
5056
+ import { StyleSheet as StyleSheet28 } from "react-native";
5057
+ var createStyles22 = (theme) => StyleSheet28.create({
3352
5058
  root: {
3353
5059
  alignSelf: "flex-start"
3354
5060
  },
@@ -3433,7 +5139,7 @@ var createStyles24 = (theme) => StyleSheet24.create({
3433
5139
  });
3434
5140
 
3435
5141
  // src/primitives/Radio/Radio.tsx
3436
- import { Fragment as Fragment5, jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
5142
+ import { Fragment as Fragment7, jsx as jsx38, jsxs as jsxs23 } from "react/jsx-runtime";
3437
5143
  var controlSizeBySize = {
3438
5144
  sm: 14,
3439
5145
  md: 16,
@@ -3468,7 +5174,7 @@ var Radio = forwardRef4(
3468
5174
  ...rest
3469
5175
  }, ref) => {
3470
5176
  const { theme } = useTheme();
3471
- const styles = createStyles24(theme);
5177
+ const styles = createStyles22(theme);
3472
5178
  const group = useRadioGroupContext();
3473
5179
  const isInsideGroup = group !== null;
3474
5180
  const [standaloneChecked, setStandaloneChecked] = useControllableState4({
@@ -3507,7 +5213,7 @@ var Radio = forwardRef4(
3507
5213
  };
3508
5214
  const typographySize = typographySizeByRadioSize[resolvedSize];
3509
5215
  const controlMarginTop = (typographySize.labelLineHeight - controlSize) / 2;
3510
- useEffect5(() => {
5216
+ useEffect8(() => {
3511
5217
  if (typeof __DEV__ !== "undefined" && __DEV__ && !label && !accessibilityLabel) {
3512
5218
  console.warn(
3513
5219
  "Radio requires either a visible label or accessibilityLabel."
@@ -3536,9 +5242,9 @@ var Radio = forwardRef4(
3536
5242
  state.pressed && !resolvedDisabled && styles.pressablePressed,
3537
5243
  typeof style === "function" ? style(state) : style
3538
5244
  ];
3539
- return /* @__PURE__ */ jsxs15(View22, { style: [styles.root, containerStyle], children: [
3540
- /* @__PURE__ */ jsx26(
3541
- Pressable13,
5245
+ return /* @__PURE__ */ jsxs23(View32, { style: [styles.root, containerStyle], children: [
5246
+ /* @__PURE__ */ jsx38(
5247
+ Pressable17,
3542
5248
  {
3543
5249
  ...rest,
3544
5250
  ref,
@@ -3552,9 +5258,9 @@ var Radio = forwardRef4(
3552
5258
  disabled: resolvedDisabled,
3553
5259
  onPress: handlePress,
3554
5260
  style: resolvePressableStyle,
3555
- children: (state) => /* @__PURE__ */ jsxs15(Fragment5, { children: [
3556
- /* @__PURE__ */ jsx26(
3557
- View22,
5261
+ children: (state) => /* @__PURE__ */ jsxs23(Fragment7, { children: [
5262
+ /* @__PURE__ */ jsx38(
5263
+ View32,
3558
5264
  {
3559
5265
  pointerEvents: "none",
3560
5266
  style: [
@@ -3577,8 +5283,8 @@ var Radio = forwardRef4(
3577
5283
  resolvedDisabled && styles.controlDisabled,
3578
5284
  resolvedChecked && resolvedDisabled && styles.controlCheckedDisabled
3579
5285
  ],
3580
- children: resolvedChecked && (icon ?? /* @__PURE__ */ jsx26(
3581
- View22,
5286
+ children: resolvedChecked && (icon ?? /* @__PURE__ */ jsx38(
5287
+ View32,
3582
5288
  {
3583
5289
  style: [
3584
5290
  styles.indicator,
@@ -3593,9 +5299,9 @@ var Radio = forwardRef4(
3593
5299
  ))
3594
5300
  }
3595
5301
  ),
3596
- (label || description) && /* @__PURE__ */ jsxs15(View22, { pointerEvents: "none", style: styles.content, children: [
3597
- label && (typeof label === "string" ? /* @__PURE__ */ jsx26(
3598
- Text14,
5302
+ (label || description) && /* @__PURE__ */ jsxs23(View32, { pointerEvents: "none", style: styles.content, children: [
5303
+ label && (typeof label === "string" ? /* @__PURE__ */ jsx38(
5304
+ Text19,
3599
5305
  {
3600
5306
  style: [
3601
5307
  styles.label,
@@ -3616,8 +5322,8 @@ var Radio = forwardRef4(
3616
5322
  children: label
3617
5323
  }
3618
5324
  ) : label),
3619
- description && (typeof description === "string" ? /* @__PURE__ */ jsx26(
3620
- Text14,
5325
+ description && (typeof description === "string" ? /* @__PURE__ */ jsx38(
5326
+ Text19,
3621
5327
  {
3622
5328
  style: [
3623
5329
  styles.description,
@@ -3635,8 +5341,8 @@ var Radio = forwardRef4(
3635
5341
  ] })
3636
5342
  }
3637
5343
  ),
3638
- error && /* @__PURE__ */ jsx26(
3639
- Text14,
5344
+ error && /* @__PURE__ */ jsx38(
5345
+ Text19,
3640
5346
  {
3641
5347
  accessibilityLiveRegion: "polite",
3642
5348
  style: [