@xaui/native 0.9.1-alpha.36 → 0.9.1-alpha.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. package/dist/{chunk-V5IVMZQJ.js → chunk-2PMXMKS5.js} +13 -8
  2. package/dist/{chunk-FVKIQBHS.cjs → chunk-3P6M2R4S.cjs} +6 -6
  3. package/dist/{chunk-RPOKLFRB.cjs → chunk-437QULXO.cjs} +7 -7
  4. package/dist/{chunk-BAPXLO5N.js → chunk-4PTWZCOK.js} +9 -9
  5. package/dist/{chunk-E5ZW7MBW.js → chunk-5PPNDKRX.js} +16 -16
  6. package/dist/{chunk-K7GAHNMJ.js → chunk-6G3XWPNP.js} +5 -5
  7. package/dist/{chunk-ISPOIMGX.cjs → chunk-7B3UBUC6.cjs} +3 -3
  8. package/dist/{chunk-5GMU7ESV.js → chunk-7LSY4WFL.js} +2 -2
  9. package/dist/{chunk-HQVVQGYV.cjs → chunk-ACAPTWE3.cjs} +16 -12
  10. package/dist/{chunk-2L7FOIWY.cjs → chunk-AP6RVIIK.cjs} +21 -21
  11. package/dist/{chunk-SAGMDVFU.js → chunk-BORJJYDW.js} +4 -4
  12. package/dist/{chunk-ADQVA2FQ.cjs → chunk-C5VDFRAD.cjs} +3 -3
  13. package/dist/{chunk-FYCDRRJ2.cjs → chunk-CUQTAPBU.cjs} +22 -22
  14. package/dist/{chunk-GPZSTEEI.cjs → chunk-DKH6BNPF.cjs} +15 -15
  15. package/dist/{chunk-2SCE7TFZ.cjs → chunk-DRMT346W.cjs} +64 -64
  16. package/dist/chunk-DVDQSW7U.cjs +1006 -0
  17. package/dist/{chunk-U3HFQHGZ.js → chunk-E3X5ODKQ.js} +3 -3
  18. package/dist/{chunk-RSGIJ6RI.js → chunk-EOJ5MYAQ.js} +5 -5
  19. package/dist/{chunk-MFXZHLOU.cjs → chunk-FTQHDJYL.cjs} +14 -14
  20. package/dist/{chunk-GHKJ6MUH.cjs → chunk-GTT4NHS2.cjs} +11 -11
  21. package/dist/{chunk-OWE5IID7.js → chunk-HXW4ANVB.js} +3 -3
  22. package/dist/{chunk-N2U63JUX.cjs → chunk-IGLKACSR.cjs} +7 -7
  23. package/dist/{chunk-VWATEE5O.js → chunk-IKJVLJKT.js} +15 -15
  24. package/dist/{chunk-AZRMOWRG.cjs → chunk-ITURCQMQ.cjs} +7 -7
  25. package/dist/{chunk-PGQWUASE.cjs → chunk-JB5LGQ54.cjs} +3 -3
  26. package/dist/{chunk-4XFEEBPU.js → chunk-JDSE4TQL.js} +1 -1
  27. package/dist/{chunk-6U5IUUAR.js → chunk-JXNFOOKC.js} +7 -7
  28. package/dist/{chunk-6N5ZCEAB.cjs → chunk-LEWW24RQ.cjs} +7 -7
  29. package/dist/{chunk-OSCW7I4H.js → chunk-M63GFNKV.js} +19 -4
  30. package/dist/chunk-MESKS6AI.js +0 -0
  31. package/dist/{chunk-CVCE7TW5.js → chunk-NKPTXTTS.js} +3 -3
  32. package/dist/{chunk-2LNE4PWB.cjs → chunk-NTD3NPRX.cjs} +3 -3
  33. package/dist/{chunk-2OZPOWFB.js → chunk-O3A3DBSZ.js} +3 -3
  34. package/dist/chunk-OJCCV65P.cjs +1 -0
  35. package/dist/{chunk-B6OKVLC7.js → chunk-OULTSBKU.js} +3 -3
  36. package/dist/{chunk-TE7KVFE4.cjs → chunk-P747CRAY.cjs} +9 -9
  37. package/dist/{chunk-DL2PGB5G.js → chunk-RGKWNK4T.js} +58 -58
  38. package/dist/{chunk-DOLWSO7A.js → chunk-RVRVGG73.js} +4 -4
  39. package/dist/{chunk-3YZSUDZ2.js → chunk-SMW6ZWMH.js} +3 -3
  40. package/dist/{chunk-AQXNEV6J.cjs → chunk-SNIHUKDA.cjs} +16 -16
  41. package/dist/{chunk-OMV5MUTM.js → chunk-SO5UAGIU.js} +15 -15
  42. package/dist/{chunk-KZVHC4FL.js → chunk-TDYPY2J7.js} +8 -8
  43. package/dist/{chunk-QZO57TPX.js → chunk-TJHYSSBZ.js} +3 -3
  44. package/dist/{chunk-K3AVOT6L.cjs → chunk-TK44VBIE.cjs} +22 -7
  45. package/dist/{chunk-ZU3XQZ63.cjs → chunk-UBOXW5WO.cjs} +63 -63
  46. package/dist/{chunk-UCW25LL6.js → chunk-UGF35NSE.js} +75 -75
  47. package/dist/{chunk-LCDHTLSG.cjs → chunk-VFTT3Q4B.cjs} +4 -4
  48. package/dist/{chunk-5BNIIDQD.cjs → chunk-WDDXU3OH.cjs} +14 -9
  49. package/dist/{chunk-JB5XANQY.js → chunk-WKCQ6VGW.js} +15 -11
  50. package/dist/{chunk-XARBUUIE.cjs → chunk-WVLSQO6K.cjs} +9 -9
  51. package/dist/chunk-XWY4DF37.js +1143 -0
  52. package/dist/{chunk-EFPWXJAJ.cjs → chunk-ZJWEVFAO.cjs} +12 -12
  53. package/dist/components/alert/index.cjs +7 -8
  54. package/dist/components/alert/index.d.cts +1 -1
  55. package/dist/components/alert/index.d.ts +1 -1
  56. package/dist/components/alert/index.js +6 -7
  57. package/dist/components/avatar/index.cjs +4 -5
  58. package/dist/components/avatar/index.d.cts +3 -3
  59. package/dist/components/avatar/index.d.ts +3 -3
  60. package/dist/components/avatar/index.js +3 -4
  61. package/dist/components/badge/index.cjs +3 -4
  62. package/dist/components/badge/index.d.cts +1 -1
  63. package/dist/components/badge/index.d.ts +1 -1
  64. package/dist/components/badge/index.js +2 -3
  65. package/dist/components/button/index.cjs +6 -7
  66. package/dist/components/button/index.d.cts +168 -168
  67. package/dist/components/button/index.d.ts +168 -168
  68. package/dist/components/button/index.js +5 -6
  69. package/dist/components/card/index.cjs +5 -6
  70. package/dist/components/card/index.d.cts +169 -169
  71. package/dist/components/card/index.d.ts +169 -169
  72. package/dist/components/card/index.js +4 -5
  73. package/dist/components/checkbox/index.cjs +5 -6
  74. package/dist/components/checkbox/index.d.cts +336 -336
  75. package/dist/components/checkbox/index.d.ts +336 -336
  76. package/dist/components/checkbox/index.js +4 -5
  77. package/dist/components/chip/index.cjs +7 -8
  78. package/dist/components/chip/index.d.cts +169 -169
  79. package/dist/components/chip/index.d.ts +169 -169
  80. package/dist/components/chip/index.js +6 -7
  81. package/dist/components/divider/index.cjs +3 -4
  82. package/dist/components/divider/index.d.cts +1 -1
  83. package/dist/components/divider/index.d.ts +1 -1
  84. package/dist/components/divider/index.js +2 -3
  85. package/dist/components/field-group/index.cjs +5 -6
  86. package/dist/components/field-group/index.d.cts +6 -6
  87. package/dist/components/field-group/index.d.ts +6 -6
  88. package/dist/components/field-group/index.js +4 -5
  89. package/dist/components/input-otp/index.cjs +3 -4
  90. package/dist/components/input-otp/index.d.cts +1 -1
  91. package/dist/components/input-otp/index.d.ts +1 -1
  92. package/dist/components/input-otp/index.js +2 -3
  93. package/dist/components/radio/index.cjs +5 -6
  94. package/dist/components/radio/index.d.cts +336 -336
  95. package/dist/components/radio/index.d.ts +336 -336
  96. package/dist/components/radio/index.js +4 -5
  97. package/dist/components/select/index.cjs +47 -0
  98. package/dist/components/select/index.d.cts +519 -0
  99. package/dist/components/select/index.d.ts +519 -0
  100. package/dist/components/select/index.js +47 -0
  101. package/dist/components/skeleton/index.cjs +3 -4
  102. package/dist/components/skeleton/index.d.cts +1 -1
  103. package/dist/components/skeleton/index.d.ts +1 -1
  104. package/dist/components/skeleton/index.js +2 -3
  105. package/dist/components/spinner/index.cjs +4 -5
  106. package/dist/components/spinner/index.d.cts +1 -1
  107. package/dist/components/spinner/index.d.ts +1 -1
  108. package/dist/components/spinner/index.js +3 -4
  109. package/dist/components/switch/index.cjs +5 -6
  110. package/dist/components/switch/index.d.cts +338 -338
  111. package/dist/components/switch/index.d.ts +338 -338
  112. package/dist/components/switch/index.js +4 -5
  113. package/dist/components/text-area/index.cjs +4 -5
  114. package/dist/components/text-area/index.js +3 -4
  115. package/dist/components/text-field/index.cjs +3 -4
  116. package/dist/components/text-field/index.d.cts +3 -3
  117. package/dist/components/text-field/index.d.ts +3 -3
  118. package/dist/components/text-field/index.js +2 -3
  119. package/dist/components/typography/index.cjs +3 -4
  120. package/dist/components/typography/index.d.cts +2 -2
  121. package/dist/components/typography/index.d.ts +2 -2
  122. package/dist/components/typography/index.js +2 -3
  123. package/dist/components/view/index.cjs +3 -4
  124. package/dist/components/view/index.d.cts +6 -6
  125. package/dist/components/view/index.d.ts +6 -6
  126. package/dist/components/view/index.js +2 -3
  127. package/dist/index.cjs +64 -28
  128. package/dist/index.d.cts +1 -0
  129. package/dist/index.d.ts +1 -0
  130. package/dist/index.js +80 -44
  131. package/dist/system/index.cjs +10 -10
  132. package/dist/system/index.d.cts +15 -2
  133. package/dist/system/index.d.ts +15 -2
  134. package/dist/system/index.js +8 -8
  135. package/dist/theme/index.cjs +4 -3
  136. package/dist/theme/index.d.cts +21 -1
  137. package/dist/theme/index.d.ts +21 -1
  138. package/dist/theme/index.js +3 -2
  139. package/package.json +11 -1
  140. package/dist/chunk-FJ5TLRT3.js +0 -21
  141. package/dist/chunk-HT7H35GU.cjs +0 -21
@@ -0,0 +1,1143 @@
1
+ import { Portal, PortalContext } from "./chunk-2PMXMKS5.js";
2
+ import { Icon, IconContext } from "./chunk-HXW4ANVB.js";
3
+ import { PressableFeedback } from "./chunk-UGF35NSE.js";
4
+ import { usePressState } from "./chunk-423RQBOX.js";
5
+ import { childrenToString, createSlotContext } from "./chunk-YXPYOOHU.js";
6
+ import { mergeRefs } from "./chunk-36PRYGAM.js";
7
+ import { createRecipe, radiusAxis } from "./chunk-4GTAZM2C.js";
8
+ import { useXAUITheme } from "./chunk-A3EGFI6T.js";
9
+ import { useStyleProps } from "./chunk-M63GFNKV.js";
10
+
11
+ // src/components/select/select-content.tsx
12
+ import { forwardRef as forwardRef3, useContext, useEffect as useEffect2, useState } from "react";
13
+ import { ScrollView, useWindowDimensions } from "react-native";
14
+ import Animated from "react-native-reanimated";
15
+
16
+ // src/components/select/select.context.ts
17
+ var [SelectProvider, useSelect] = createSlotContext("Select");
18
+ var [SelectItemProvider, useSelectItem] = createSlotContext("Select.Item");
19
+
20
+ // src/components/select/select.animation.ts
21
+ import { Easing, Keyframe } from "react-native-reanimated";
22
+ var INDICATOR_SPRING = {
23
+ damping: 140,
24
+ stiffness: 1e3,
25
+ mass: 4
26
+ };
27
+ var INDICATOR_ROTATION = [0, -180];
28
+ var ENTER_MS = 200;
29
+ var EXIT_MS = 150;
30
+ function contentEntering(placement) {
31
+ const from = placement === "bottom" ? -8 : 8;
32
+ return new Keyframe({
33
+ 0: {
34
+ opacity: 0,
35
+ transform: [{
36
+ translateY: from
37
+ }, {
38
+ scale: 0.95
39
+ }]
40
+ },
41
+ 100: {
42
+ opacity: 1,
43
+ transform: [{
44
+ translateY: 0
45
+ }, {
46
+ scale: 1
47
+ }],
48
+ easing: Easing.out(Easing.cubic)
49
+ }
50
+ }).duration(ENTER_MS);
51
+ }
52
+ function contentExiting(placement) {
53
+ const to = placement === "bottom" ? -8 : 8;
54
+ return new Keyframe({
55
+ 0: {
56
+ opacity: 1,
57
+ transform: [{
58
+ translateY: 0
59
+ }, {
60
+ scale: 1
61
+ }]
62
+ },
63
+ 100: {
64
+ opacity: 0,
65
+ transform: [{
66
+ translateY: to
67
+ }, {
68
+ scale: 0.95
69
+ }],
70
+ easing: Easing.in(Easing.cubic)
71
+ }
72
+ }).duration(EXIT_MS);
73
+ }
74
+ var overlayEntering = new Keyframe({
75
+ 0: {
76
+ opacity: 0
77
+ },
78
+ 100: {
79
+ opacity: 1
80
+ }
81
+ }).duration(ENTER_MS);
82
+ var overlayExiting = new Keyframe({
83
+ 0: {
84
+ opacity: 1
85
+ },
86
+ 100: {
87
+ opacity: 0
88
+ }
89
+ }).duration(EXIT_MS);
90
+
91
+ // src/components/select/select-item.tsx
92
+ import { forwardRef as forwardRef2, useCallback, useEffect, useMemo } from "react";
93
+
94
+ // src/components/select/select-item-label.tsx
95
+ import { forwardRef } from "react";
96
+ import { Text } from "react-native";
97
+ import { jsx } from "react/jsx-runtime";
98
+ var SelectItemLabel = forwardRef(function SelectItemLabel2({
99
+ children,
100
+ numberOfLines = 1,
101
+ style,
102
+ ...props
103
+ }, ref) {
104
+ const {
105
+ itemLabelStyle
106
+ } = useSelect();
107
+ const [styleProps, rest] = useStyleProps(props);
108
+ return /* @__PURE__ */jsx(Text, {
109
+ ref,
110
+ numberOfLines,
111
+ ...rest,
112
+ style: [itemLabelStyle, styleProps, style],
113
+ children
114
+ });
115
+ });
116
+ SelectItemLabel.displayName = "XAUI.Select.ItemLabel";
117
+
118
+ // src/components/select/select-item.tsx
119
+ import { Fragment, jsx as jsx2 } from "react/jsx-runtime";
120
+ var SelectItem = forwardRef2(function SelectItem2({
121
+ value,
122
+ label,
123
+ children,
124
+ isDisabled = false,
125
+ asChild = false,
126
+ accessibilityRole = "menuitem",
127
+ accessibilityState,
128
+ style,
129
+ onPress,
130
+ onPressIn,
131
+ onPressOut,
132
+ ...props
133
+ }, ref) {
134
+ const {
135
+ itemStyle,
136
+ itemPressedStyle,
137
+ value: selected,
138
+ select,
139
+ registerLabel
140
+ } = useSelect();
141
+ const [styleProps, rest] = useStyleProps(props);
142
+ const [isPressed, press] = usePressState({
143
+ onPressIn,
144
+ onPressOut
145
+ });
146
+ const isSelected = selected === value;
147
+ const text = typeof children === "function" ? null : childrenToString(children);
148
+ const registered = label ?? text ?? void 0;
149
+ useEffect(() => {
150
+ if (registered !== void 0) registerLabel(value, registered);
151
+ }, [registerLabel, value, registered]);
152
+ const handlePress = useCallback(event => {
153
+ onPress?.(event);
154
+ select(value, registered);
155
+ }, [onPress, select, value, registered]);
156
+ const context = useMemo(() => ({
157
+ isSelected,
158
+ isPressed,
159
+ isDisabled
160
+ }), [isSelected, isPressed, isDisabled]);
161
+ return /* @__PURE__ */jsx2(SelectItemProvider, {
162
+ value: context,
163
+ children: /* @__PURE__ */jsx2(PressableFeedback, {
164
+ ref,
165
+ isPressed,
166
+ isDisabled,
167
+ asChild,
168
+ accessibilityRole,
169
+ accessibilityState: {
170
+ disabled: isDisabled,
171
+ selected: isSelected,
172
+ ...accessibilityState
173
+ },
174
+ ...rest,
175
+ style: [itemStyle, isPressed && itemPressedStyle, styleProps, typeof style === "function" ? style({
176
+ pressed: isPressed
177
+ }) : style],
178
+ onPress: handlePress,
179
+ onPressIn: press.onPressIn,
180
+ onPressOut: press.onPressOut,
181
+ children: typeof children === "function" ? children(context) : /* @__PURE__ */jsx2(Fragment, {
182
+ children: text !== null ? /* @__PURE__ */jsx2(SelectItemLabel, {
183
+ children: text
184
+ }) : children
185
+ })
186
+ })
187
+ });
188
+ });
189
+ SelectItem.displayName = "XAUI.Select.Item";
190
+
191
+ // src/components/select/select.utils.ts
192
+ import { Children, isValidElement } from "react";
193
+ function resolvePlacement(input) {
194
+ const {
195
+ anchor,
196
+ content,
197
+ window,
198
+ offset,
199
+ alignOffset,
200
+ insets
201
+ } = input;
202
+ const available = window.width - insets.start - insets.end;
203
+ const width = Math.min(resolveWidth(input), Math.max(available, 0));
204
+ const placement = choosePlacement(input);
205
+ const maxHeight = Math.max(roomFor(placement, input), 0);
206
+ const height = Math.min(content.height, maxHeight);
207
+ const top = placement === "bottom" ? anchor.y + anchor.height + offset : anchor.y - offset - height;
208
+ const start = clamp(alignedStart(input, width) + alignOffset, insets.start, Math.max(window.width - insets.end - width, insets.start));
209
+ return {
210
+ top,
211
+ start,
212
+ width,
213
+ maxHeight,
214
+ placement
215
+ };
216
+ }
217
+ function resolveWidth({
218
+ width,
219
+ anchor,
220
+ content
221
+ }) {
222
+ if (width === "trigger") return anchor.width;
223
+ if (width === "content-fit") return content.width;
224
+ return width;
225
+ }
226
+ function choosePlacement(input) {
227
+ const {
228
+ placement,
229
+ avoidCollisions,
230
+ content
231
+ } = input;
232
+ if (!avoidCollisions) return placement;
233
+ if (roomFor(placement, input) >= content.height) return placement;
234
+ const other = placement === "bottom" ? "top" : "bottom";
235
+ return roomFor(other, input) > roomFor(placement, input) ? other : placement;
236
+ }
237
+ function roomFor(placement, input) {
238
+ const {
239
+ anchor,
240
+ window,
241
+ offset,
242
+ insets
243
+ } = input;
244
+ return placement === "bottom" ? window.height - insets.bottom - (anchor.y + anchor.height) - offset : anchor.y - insets.top - offset;
245
+ }
246
+ function alignedStart({
247
+ align,
248
+ anchor
249
+ }, width) {
250
+ if (align === "start") return anchor.x;
251
+ if (align === "end") return anchor.x + anchor.width - width;
252
+ return anchor.x + (anchor.width - width) / 2;
253
+ }
254
+ function clamp(value, min, max) {
255
+ return Math.min(Math.max(value, min), max);
256
+ }
257
+ function collectItemLabels(children, isItem) {
258
+ const found = [];
259
+ const walk = node => {
260
+ Children.forEach(node, child => {
261
+ if (!isValidElement(child)) return;
262
+ const props = child.props;
263
+ if (isItem(child.type) && typeof props.value === "string") {
264
+ const label = props.label ?? childrenToString(props.children);
265
+ if (label !== null && label !== void 0) found.push([props.value, label]);
266
+ return;
267
+ }
268
+ walk(props.children);
269
+ });
270
+ };
271
+ walk(children);
272
+ return found;
273
+ }
274
+
275
+ // src/components/select/select-content.tsx
276
+ import { jsx as jsx3 } from "react/jsx-runtime";
277
+ var DEFAULT_OFFSET = 8;
278
+ var ZERO = {
279
+ x: 0,
280
+ y: 0
281
+ };
282
+ var isSelectItem = type => type === SelectItem;
283
+ var DEFAULT_INSETS = {
284
+ top: 12,
285
+ bottom: 12,
286
+ start: 12,
287
+ end: 12
288
+ };
289
+ var SelectContent = forwardRef3(function SelectContent2({
290
+ children,
291
+ placement = "bottom",
292
+ align = "center",
293
+ width = "trigger",
294
+ offset = DEFAULT_OFFSET,
295
+ alignOffset = 0,
296
+ avoidCollisions = true,
297
+ insets,
298
+ style,
299
+ onLayout,
300
+ ...props
301
+ }, ref) {
302
+ const context = useSelect();
303
+ const {
304
+ contentStyle,
305
+ isOpen,
306
+ anchor
307
+ } = context;
308
+ const [styleProps, rest] = useStyleProps(props);
309
+ const window = useWindowDimensions();
310
+ const origin = useContext(PortalContext)?.origin ?? ZERO;
311
+ const [measured, setMeasured] = useState(null);
312
+ const {
313
+ registerLabel
314
+ } = context;
315
+ useEffect2(() => {
316
+ for (const [value, label] of collectItemLabels(children, isSelectItem)) {
317
+ registerLabel(value, label);
318
+ }
319
+ }, [children, registerLabel]);
320
+ if (!isOpen && measured !== null) setMeasured(null);
321
+ if (!isOpen || anchor === null) return null;
322
+ const measure = event => {
323
+ onLayout?.(event);
324
+ const {
325
+ width: w,
326
+ height: h
327
+ } = event.nativeEvent.layout;
328
+ if (measured === null || measured.height !== h || measured.width !== w) {
329
+ setMeasured({
330
+ width: w,
331
+ height: h
332
+ });
333
+ }
334
+ };
335
+ const local = {
336
+ ...anchor,
337
+ x: anchor.x - origin.x,
338
+ y: anchor.y - origin.y
339
+ };
340
+ const position = measured && resolvePlacement({
341
+ anchor: local,
342
+ content: measured,
343
+ // The window in the host's own coordinates, for the same reason as the anchor.
344
+ window: {
345
+ width: window.width - origin.x,
346
+ height: window.height - origin.y
347
+ },
348
+ placement,
349
+ align,
350
+ width,
351
+ offset,
352
+ alignOffset,
353
+ avoidCollisions,
354
+ insets: {
355
+ ...DEFAULT_INSETS,
356
+ ...insets
357
+ }
358
+ });
359
+ return /* @__PURE__ */jsx3(Portal, {
360
+ children: /* @__PURE__ */jsx3(SelectProvider, {
361
+ value: context,
362
+ children: /* @__PURE__ */jsx3(Animated.View, {
363
+ ref,
364
+ entering: position ? contentEntering(position.placement) : void 0,
365
+ exiting: position ? contentExiting(position.placement) : void 0,
366
+ onLayout: measure,
367
+ ...rest,
368
+ style: [contentStyle,
369
+ // The measuring pass: laid out at the trigger's width so the rows wrap as they
370
+ // finally will, and invisible so the reader never sees it at the wrong place.
371
+ position === null ? {
372
+ opacity: 0,
373
+ top: 0,
374
+ start: 0,
375
+ width: local.width
376
+ } : {
377
+ top: position.top,
378
+ start: position.start,
379
+ width: position.width,
380
+ maxHeight: position.maxHeight
381
+ }, styleProps, style],
382
+ children: /* @__PURE__ */jsx3(ScrollView, {
383
+ bounces: false,
384
+ keyboardShouldPersistTaps: "handled",
385
+ showsVerticalScrollIndicator: false,
386
+ children
387
+ })
388
+ }, position?.placement ?? "measuring")
389
+ })
390
+ });
391
+ });
392
+ SelectContent.displayName = "XAUI.Select.Content";
393
+
394
+ // src/components/select/select-indicator.tsx
395
+ import { useEffect as useEffect3 } from "react";
396
+ import Animated2, { interpolate, useAnimatedStyle, useSharedValue, withSpring } from "react-native-reanimated";
397
+
398
+ // src/components/select/chevron-down-icon.tsx
399
+ import { Path, Svg } from "react-native-svg";
400
+ import { jsx as jsx4 } from "react/jsx-runtime";
401
+ function ChevronDownIcon({
402
+ size = 20,
403
+ color = "currentColor"
404
+ }) {
405
+ return /* @__PURE__ */jsx4(Svg, {
406
+ width: size,
407
+ height: size,
408
+ viewBox: "0 0 24 24",
409
+ fill: "none",
410
+ children: /* @__PURE__ */jsx4(Path, {
411
+ d: "m6 9 6 6 6-6",
412
+ stroke: color,
413
+ strokeWidth: 2,
414
+ strokeLinecap: "round",
415
+ strokeLinejoin: "round"
416
+ })
417
+ });
418
+ }
419
+ ChevronDownIcon.displayName = "XAUI.Select.ChevronDownIcon";
420
+
421
+ // src/components/select/select-indicator.tsx
422
+ import { jsx as jsx5 } from "react/jsx-runtime";
423
+ const _worklet_11336077885044_init_data = {
424
+ code: "function chunkXWY4DF37Js1(){const{interpolate,progress,INDICATOR_ROTATION}=this.__closure;return{transform:[{rotate:interpolate(progress.get(),[0,1],[INDICATOR_ROTATION[0],INDICATOR_ROTATION[1]])+\"deg\"}]};}",
425
+ location: "/home/runner/work/xaui/xaui/packages/native/dist/chunk-XWY4DF37.js",
426
+ sourceMap: "{\"version\":3,\"names\":[\"chunkXWY4DF37Js1\",\"interpolate\",\"progress\",\"INDICATOR_ROTATION\",\"__closure\",\"transform\",\"rotate\",\"get\"],\"sources\":[\"/home/runner/work/xaui/xaui/packages/native/dist/chunk-XWY4DF37.js\"],\"mappings\":\"AA4XoC,SAAAA,iBAAA,QAAAC,WAAA,CAAAC,QAAA,CAAAC,kBAAA,OAAAC,SAAA,OAAO,CACvCC,SAAS,CAAE,CACT,CACEC,MAAM,CAAKL,WAAW,CAACC,QAAQ,CAACK,GAAG,CAAC,CAAC,CAAE,CAAC,CAAC,CAAE,CAAC,CAAC,CAAE,CAACJ,kBAAkB,CAAC,CAAC,CAAC,CAAEA,kBAAkB,CAAC,CAAC,CAAC,CAAC,CAAC,MAChG,CAAC,CAEL,CAAC\",\"ignoreList\":[]}"
427
+ };
428
+ function SelectIndicator({
429
+ as = ChevronDownIcon,
430
+ ...props
431
+ }) {
432
+ const {
433
+ indicatorStyle,
434
+ isOpen
435
+ } = useSelect();
436
+ const progress = useSharedValue(isOpen ? 1 : 0);
437
+ useEffect3(() => {
438
+ progress.set(withSpring(isOpen ? 1 : 0, INDICATOR_SPRING));
439
+ }, [isOpen, progress]);
440
+ const rotation = useAnimatedStyle(function chunkXWY4DF37Js1Factory({
441
+ _worklet_11336077885044_init_data,
442
+ interpolate,
443
+ progress,
444
+ INDICATOR_ROTATION
445
+ }) {
446
+ const _e = [new global.Error(), -4, -27];
447
+ const chunkXWY4DF37Js1 = () => ({
448
+ transform: [{
449
+ rotate: `${interpolate(progress.get(), [0, 1], [INDICATOR_ROTATION[0], INDICATOR_ROTATION[1]])}deg`
450
+ }]
451
+ });
452
+ chunkXWY4DF37Js1.__closure = {
453
+ interpolate,
454
+ progress,
455
+ INDICATOR_ROTATION
456
+ };
457
+ chunkXWY4DF37Js1.__workletHash = 11336077885044;
458
+ chunkXWY4DF37Js1.__pluginVersion = "0.7.4";
459
+ chunkXWY4DF37Js1.__initData = _worklet_11336077885044_init_data;
460
+ chunkXWY4DF37Js1.__stackDetails = _e;
461
+ return chunkXWY4DF37Js1;
462
+ }({
463
+ _worklet_11336077885044_init_data,
464
+ interpolate,
465
+ progress,
466
+ INDICATOR_ROTATION
467
+ }));
468
+ return /* @__PURE__ */jsx5(Animated2.View, {
469
+ style: [indicatorStyle, rotation],
470
+ children: /* @__PURE__ */jsx5(Icon, {
471
+ as,
472
+ ...props
473
+ })
474
+ });
475
+ }
476
+ SelectIndicator.displayName = "XAUI.Select.Indicator";
477
+
478
+ // src/components/select/select-item-description.tsx
479
+ import { forwardRef as forwardRef4 } from "react";
480
+ import { Text as Text2 } from "react-native";
481
+ import { jsx as jsx6 } from "react/jsx-runtime";
482
+ var SelectItemDescription = forwardRef4(function SelectItemDescription2({
483
+ children,
484
+ style,
485
+ ...props
486
+ }, ref) {
487
+ const {
488
+ itemDescriptionStyle
489
+ } = useSelect();
490
+ const [styleProps, rest] = useStyleProps(props);
491
+ return /* @__PURE__ */jsx6(Text2, {
492
+ ref,
493
+ ...rest,
494
+ style: [itemDescriptionStyle, styleProps, style],
495
+ children
496
+ });
497
+ });
498
+ SelectItemDescription.displayName = "XAUI.Select.ItemDescription";
499
+
500
+ // src/components/select/select-item-indicator.tsx
501
+ import { View } from "react-native";
502
+
503
+ // src/components/select/check-icon.tsx
504
+ import { Path as Path2, Svg as Svg2 } from "react-native-svg";
505
+ import { jsx as jsx7 } from "react/jsx-runtime";
506
+ function CheckIcon({
507
+ size = 20,
508
+ color = "currentColor"
509
+ }) {
510
+ return /* @__PURE__ */jsx7(Svg2, {
511
+ width: size,
512
+ height: size,
513
+ viewBox: "0 0 24 24",
514
+ fill: "none",
515
+ children: /* @__PURE__ */jsx7(Path2, {
516
+ d: "m20 6-11 11-5-5",
517
+ stroke: color,
518
+ strokeWidth: 2,
519
+ strokeLinecap: "round",
520
+ strokeLinejoin: "round"
521
+ })
522
+ });
523
+ }
524
+ CheckIcon.displayName = "XAUI.Select.CheckIcon";
525
+
526
+ // src/components/select/select-item-indicator.tsx
527
+ import { jsx as jsx8 } from "react/jsx-runtime";
528
+ function SelectItemIndicator({
529
+ as = CheckIcon,
530
+ color,
531
+ ...props
532
+ }) {
533
+ const {
534
+ itemIndicatorStyle,
535
+ checkColor
536
+ } = useSelect();
537
+ const {
538
+ isSelected
539
+ } = useSelectItem();
540
+ return /* @__PURE__ */jsx8(View, {
541
+ style: itemIndicatorStyle,
542
+ children: isSelected ? /* @__PURE__ */jsx8(Icon, {
543
+ as,
544
+ color: color ?? checkColor,
545
+ ...props
546
+ }) : null
547
+ });
548
+ }
549
+ SelectItemIndicator.displayName = "XAUI.Select.ItemIndicator";
550
+
551
+ // src/components/select/select-label.tsx
552
+ import { forwardRef as forwardRef5 } from "react";
553
+ import { Text as Text3 } from "react-native";
554
+ import { jsx as jsx9 } from "react/jsx-runtime";
555
+ var SelectLabel = forwardRef5(function SelectLabel2({
556
+ children,
557
+ accessibilityRole = "header",
558
+ style,
559
+ ...props
560
+ }, ref) {
561
+ const {
562
+ labelStyle
563
+ } = useSelect();
564
+ const [styleProps, rest] = useStyleProps(props);
565
+ return /* @__PURE__ */jsx9(Text3, {
566
+ ref,
567
+ accessibilityRole,
568
+ ...rest,
569
+ style: [labelStyle, styleProps, style],
570
+ children
571
+ });
572
+ });
573
+ SelectLabel.displayName = "XAUI.Select.Label";
574
+
575
+ // src/components/select/select-overlay.tsx
576
+ import { forwardRef as forwardRef6 } from "react";
577
+ import { Pressable } from "react-native";
578
+ import Animated3 from "react-native-reanimated";
579
+ import { jsx as jsx10 } from "react/jsx-runtime";
580
+ var AnimatedPressable = Animated3.createAnimatedComponent(Pressable);
581
+ var SelectOverlay = forwardRef6(function SelectOverlay2({
582
+ children,
583
+ isDismissable = true,
584
+ style,
585
+ ...props
586
+ }, ref) {
587
+ const context = useSelect();
588
+ const {
589
+ overlayStyle,
590
+ isOpen,
591
+ close
592
+ } = context;
593
+ const [styleProps, rest] = useStyleProps(props);
594
+ if (!isOpen) return null;
595
+ return /* @__PURE__ */jsx10(Portal, {
596
+ children: /* @__PURE__ */jsx10(SelectProvider, {
597
+ value: context,
598
+ children: /* @__PURE__ */jsx10(AnimatedPressable, {
599
+ ref,
600
+ entering: overlayEntering,
601
+ exiting: overlayExiting,
602
+ accessibilityRole: "none",
603
+ importantForAccessibility: "no",
604
+ onPress: isDismissable ? close : void 0,
605
+ ...rest,
606
+ style: [overlayStyle, styleProps, style],
607
+ children
608
+ })
609
+ })
610
+ });
611
+ });
612
+ SelectOverlay.displayName = "XAUI.Select.Overlay";
613
+
614
+ // src/components/select/select-trigger.tsx
615
+ import { forwardRef as forwardRef7, useCallback as useCallback2, useEffect as useEffect4, useMemo as useMemo2, useRef } from "react";
616
+ import { jsx as jsx11 } from "react/jsx-runtime";
617
+ var SelectTrigger = forwardRef7(function SelectTrigger2({
618
+ children,
619
+ asChild = false,
620
+ accessibilityRole = "button",
621
+ accessibilityState,
622
+ style,
623
+ onLayout,
624
+ onPressIn,
625
+ onPressOut,
626
+ onPress,
627
+ ...props
628
+ }, ref) {
629
+ const {
630
+ triggerStyle,
631
+ triggerPressedStyle,
632
+ glyph,
633
+ isOpen,
634
+ isDisabled,
635
+ isInvalid,
636
+ toggle,
637
+ setAnchor
638
+ } = useSelect();
639
+ const [styleProps, rest] = useStyleProps(props);
640
+ const [isPressed, press] = usePressState({
641
+ onPressIn,
642
+ onPressOut
643
+ });
644
+ const node = useRef(null);
645
+ const refs = useMemo2(() => mergeRefs(node, ref), [ref]);
646
+ const measure = useCallback2(() => {
647
+ node.current?.measureInWindow((x, y, width, height) => {
648
+ setAnchor({
649
+ x,
650
+ y,
651
+ width,
652
+ height
653
+ });
654
+ });
655
+ }, [setAnchor]);
656
+ const handleLayout = useCallback2(event => {
657
+ onLayout?.(event);
658
+ measure();
659
+ }, [measure, onLayout]);
660
+ useEffect4(() => {
661
+ if (isOpen) measure();
662
+ }, [isOpen, measure]);
663
+ const handlePress = useCallback2(event => {
664
+ onPress?.(event);
665
+ measure();
666
+ toggle();
667
+ }, [measure, onPress, toggle]);
668
+ return /* @__PURE__ */jsx11(IconContext.Provider, {
669
+ value: glyph,
670
+ children: /* @__PURE__ */jsx11(PressableFeedback, {
671
+ ref: refs,
672
+ isPressed,
673
+ isDisabled,
674
+ asChild,
675
+ accessibilityRole,
676
+ accessibilityState: {
677
+ disabled: isDisabled,
678
+ expanded: isOpen,
679
+ ...accessibilityState
680
+ },
681
+ "aria-invalid": isInvalid || void 0,
682
+ ...rest,
683
+ onLayout: handleLayout,
684
+ style: [triggerStyle, isPressed && triggerPressedStyle, styleProps, typeof style === "function" ? style({
685
+ pressed: isPressed
686
+ }) : style],
687
+ onPress: handlePress,
688
+ onPressIn: press.onPressIn,
689
+ onPressOut: press.onPressOut,
690
+ children
691
+ })
692
+ });
693
+ });
694
+ SelectTrigger.displayName = "XAUI.Select.Trigger";
695
+
696
+ // src/components/select/select-value.tsx
697
+ import { forwardRef as forwardRef8 } from "react";
698
+ import { Text as Text4 } from "react-native";
699
+ import { jsx as jsx12 } from "react/jsx-runtime";
700
+ var SelectValue = forwardRef8(function SelectValue2({
701
+ placeholder,
702
+ children,
703
+ numberOfLines = 1,
704
+ style,
705
+ ...props
706
+ }, ref) {
707
+ const {
708
+ valueStyle,
709
+ placeholderStyle,
710
+ value,
711
+ labelFor
712
+ } = useSelect();
713
+ const [styleProps, rest] = useStyleProps(props);
714
+ const label = children ?? (value !== void 0 ? labelFor(value) : void 0);
715
+ const isEmpty = label === void 0 || label === "";
716
+ return /* @__PURE__ */jsx12(Text4, {
717
+ ref,
718
+ numberOfLines,
719
+ ...rest,
720
+ style: [valueStyle, isEmpty && placeholderStyle, styleProps, style],
721
+ children: isEmpty ? placeholder : label
722
+ });
723
+ });
724
+ SelectValue.displayName = "XAUI.Select.Value";
725
+
726
+ // src/components/select/select.tsx
727
+ import { useCallback as useCallback4, useMemo as useMemo4, useState as useState3 } from "react";
728
+ import { StyleSheet } from "react-native";
729
+
730
+ // src/components/select/select.hook.ts
731
+ import { useCallback as useCallback3, useMemo as useMemo3, useRef as useRef2, useState as useState2 } from "react";
732
+ function useControllableState({
733
+ value,
734
+ defaultValue,
735
+ onChange
736
+ }) {
737
+ const isControlled = useRef2(value !== void 0).current;
738
+ const [uncontrolled, setUncontrolled] = useState2(defaultValue);
739
+ const set = useCallback3(next => {
740
+ if (!isControlled) setUncontrolled(next);
741
+ onChange?.(next);
742
+ }, [isControlled, onChange]);
743
+ return [isControlled ? value : uncontrolled, set];
744
+ }
745
+ function useLabelRegistry() {
746
+ const labels = useRef2(/* @__PURE__ */new Map());
747
+ const [, force] = useState2(0);
748
+ const registerLabel = useCallback3((value, label) => {
749
+ if (labels.current.get(value) === label) return;
750
+ labels.current.set(value, label);
751
+ force(n => n + 1);
752
+ }, []);
753
+ const labelFor = useCallback3(value => labels.current.get(value), []);
754
+ return useMemo3(() => ({
755
+ labelFor,
756
+ registerLabel
757
+ }), [labelFor, registerLabel]);
758
+ }
759
+
760
+ // src/components/select/select.recipe.ts
761
+ var SLOTS = ["trigger", "value", "placeholder", "indicator", "overlay", "content", "label", "item", "itemLabel", "itemDescription", "itemIndicator"];
762
+ var VARIANT_TOKENS = {
763
+ primary: {
764
+ bg: "fieldBackground",
765
+ border: "fieldBorder",
766
+ borderFocus: "fieldBorderFocus",
767
+ fg: "fieldForeground"
768
+ },
769
+ secondary: {
770
+ bg: "default",
771
+ border: "fieldBorder",
772
+ borderFocus: "fieldBorderFocus",
773
+ fg: "fieldForeground"
774
+ },
775
+ tertiary: {
776
+ border: "fieldBorder",
777
+ borderFocus: "fieldBorderFocus",
778
+ fg: "fieldForeground"
779
+ },
780
+ ghost: {
781
+ borderFocus: "fieldBorderFocus",
782
+ fg: "fieldForeground"
783
+ }
784
+ };
785
+ var SIZES = {
786
+ sm: {
787
+ control: "sm",
788
+ padding: 3,
789
+ gap: 2.5,
790
+ value: "md",
791
+ glyph: "lg",
792
+ listLabel: "xs",
793
+ description: "xs"
794
+ },
795
+ md: {
796
+ control: "md",
797
+ padding: 3,
798
+ gap: 3,
799
+ value: "md",
800
+ glyph: "lg",
801
+ listLabel: "sm",
802
+ description: "sm"
803
+ },
804
+ lg: {
805
+ control: "lg",
806
+ padding: 4,
807
+ gap: 3,
808
+ value: "lg",
809
+ glyph: "xl",
810
+ listLabel: "md",
811
+ description: "md"
812
+ }
813
+ };
814
+ var LIST = {
815
+ /** Panel padding, and the inset the rows sit in. */
816
+ padding: 3,
817
+ itemPaddingHorizontal: 2,
818
+ itemPaddingVertical: 3,
819
+ itemGap: 2,
820
+ labelPaddingHorizontal: 2,
821
+ labelPaddingVertical: 1.5,
822
+ /** The check's box, in spacing steps like the rest — five of them, HeroUI's twenty. */
823
+ indicator: 5
824
+ };
825
+ function sizeAxis(step) {
826
+ const {
827
+ control,
828
+ padding,
829
+ gap,
830
+ value,
831
+ glyph,
832
+ listLabel,
833
+ description
834
+ } = step;
835
+ return theme => {
836
+ const valueType = {
837
+ fontSize: theme.fontSizes[value],
838
+ lineHeight: theme.lineHeights[value]
839
+ };
840
+ return {
841
+ trigger: {
842
+ // Fixed, not a minimum: a control has a height, and a label too long for it
843
+ // truncates rather than deforming the field it shares a row with.
844
+ height: theme.controlHeights[control],
845
+ paddingHorizontal: theme.spacing(padding),
846
+ gap: theme.spacing(gap)
847
+ },
848
+ value: valueType,
849
+ placeholder: valueType,
850
+ indicator: {
851
+ fontSize: theme.fontSizes[glyph]
852
+ },
853
+ label: {
854
+ fontSize: theme.fontSizes[listLabel],
855
+ lineHeight: theme.lineHeights[listLabel]
856
+ },
857
+ itemLabel: valueType,
858
+ itemDescription: {
859
+ fontSize: theme.fontSizes[description],
860
+ lineHeight: theme.lineHeights[description]
861
+ }
862
+ };
863
+ };
864
+ }
865
+ var selectRecipe = createRecipe({
866
+ slots: SLOTS,
867
+ base: theme => ({
868
+ trigger: {
869
+ flexDirection: "row",
870
+ alignItems: "center",
871
+ justifyContent: "space-between",
872
+ borderWidth: theme.borderWidth.field,
873
+ borderRadius: theme.radius.field,
874
+ borderCurve: "continuous"
875
+ },
876
+ value: {
877
+ fontFamily: theme.fontFamilies.body,
878
+ // `regular`, as on the field: a chosen value is content, not the control's label.
879
+ fontWeight: theme.fontWeights.regular,
880
+ // Without it a long value pushes the chevron off the end of the trigger instead of
881
+ // truncating, because a row gives a text node its intrinsic width by default.
882
+ flexShrink: 1
883
+ },
884
+ placeholder: {
885
+ color: theme.colors.fieldPlaceholder
886
+ },
887
+ indicator: {
888
+ alignItems: "center",
889
+ justifyContent: "center"
890
+ },
891
+ overlay: {
892
+ position: "absolute",
893
+ top: 0,
894
+ bottom: 0,
895
+ start: 0,
896
+ end: 0
897
+ },
898
+ content: {
899
+ position: "absolute",
900
+ backgroundColor: theme.colors.overlay,
901
+ padding: theme.spacing(LIST.padding),
902
+ // The panel is not the field, so it is rounder — but not by three steps of our
903
+ // scale. HeroUI's panel is their `--radius-3xl` on a base of 8, which is 24 points;
904
+ // ours is a base of 12, so the same 24 is `2xl`. Reading their key rather than
905
+ // their number is what put a 36-point corner on it and made it read as a pill.
906
+ borderRadius: theme.radius["2xl"],
907
+ borderCurve: "continuous",
908
+ ...theme.shadows.overlay
909
+ },
910
+ label: {
911
+ fontFamily: theme.fontFamilies.body,
912
+ fontWeight: theme.fontWeights.medium,
913
+ color: theme.colors.muted,
914
+ paddingHorizontal: theme.spacing(LIST.labelPaddingHorizontal),
915
+ paddingVertical: theme.spacing(LIST.labelPaddingVertical)
916
+ },
917
+ item: {
918
+ flexDirection: "row",
919
+ alignItems: "center",
920
+ justifyContent: "space-between",
921
+ gap: theme.spacing(LIST.itemGap),
922
+ paddingHorizontal: theme.spacing(LIST.itemPaddingHorizontal),
923
+ paddingVertical: theme.spacing(LIST.itemPaddingVertical),
924
+ borderRadius: theme.radius.md,
925
+ borderCurve: "continuous"
926
+ },
927
+ itemLabel: {
928
+ fontFamily: theme.fontFamilies.body,
929
+ // `medium`, unlike the trigger's value: a row in a list is a target being offered,
930
+ // and the weight is what separates it from the description under it.
931
+ fontWeight: theme.fontWeights.medium,
932
+ color: theme.colors.overlayForeground,
933
+ flexShrink: 1
934
+ },
935
+ itemDescription: {
936
+ fontFamily: theme.fontFamilies.body,
937
+ color: theme.colors.muted
938
+ },
939
+ itemIndicator: {
940
+ width: theme.spacing(LIST.indicator),
941
+ height: theme.spacing(LIST.indicator),
942
+ alignItems: "center",
943
+ justifyContent: "center"
944
+ }
945
+ }),
946
+ variantTokens: VARIANT_TOKENS,
947
+ /**
948
+ * The variant paints the **trigger only**. The list is a floating surface of the
949
+ * theme's own — a `ghost` select does not open a ghost panel, it opens the same panel
950
+ * every other select opens, because the panel is not part of the control's emphasis.
951
+ */
952
+ paint: (theme, colors) => ({
953
+ trigger: {
954
+ backgroundColor: colors.bg,
955
+ borderColor: colors.border,
956
+ borderWidth: colors.border ? theme.borderWidth.field : 0
957
+ },
958
+ value: {
959
+ color: colors.fg
960
+ },
961
+ indicator: {
962
+ color: theme.colors.fieldPlaceholder
963
+ }
964
+ }),
965
+ variants: {
966
+ size: {
967
+ sm: sizeAxis(SIZES.sm),
968
+ md: sizeAxis(SIZES.md),
969
+ lg: sizeAxis(SIZES.lg)
970
+ },
971
+ radius: radiusAxis("trigger"),
972
+ /**
973
+ * Open is not `focused`: the field's focus border is what a keyboard gives a text
974
+ * input, and a select that is open has no caret in it. It borrows the same token
975
+ * because the two mean the same thing to the eye — this control is the live one.
976
+ */
977
+ isOpen: {
978
+ true: theme => ({
979
+ trigger: {
980
+ borderColor: theme.colors.fieldBorderFocus
981
+ }
982
+ })
983
+ },
984
+ isInvalid: {
985
+ true: theme => ({
986
+ trigger: {
987
+ borderColor: theme.colors.danger
988
+ }
989
+ })
990
+ }
991
+ },
992
+ states: {
993
+ pressed: theme => ({
994
+ trigger: {
995
+ backgroundColor: theme.colors.fieldPressed
996
+ },
997
+ item: {
998
+ backgroundColor: theme.colors.defaultSoftPressed
999
+ }
1000
+ }),
1001
+ disabled: theme => ({
1002
+ trigger: {
1003
+ opacity: theme.opacity.disabled
1004
+ }
1005
+ })
1006
+ },
1007
+ defaultVariants: {
1008
+ variant: "primary",
1009
+ size: "md"
1010
+ }
1011
+ });
1012
+
1013
+ // src/components/select/select.tsx
1014
+ import { jsx as jsx13 } from "react/jsx-runtime";
1015
+ function Select({
1016
+ children,
1017
+ variant,
1018
+ size,
1019
+ radius,
1020
+ color,
1021
+ value: controlledValue,
1022
+ defaultValue,
1023
+ onValueChange,
1024
+ isOpen: controlledOpen,
1025
+ defaultOpen = false,
1026
+ onOpenChange,
1027
+ isDisabled = false,
1028
+ isInvalid = false
1029
+ }) {
1030
+ const theme = useXAUITheme();
1031
+ const {
1032
+ labelFor,
1033
+ registerLabel
1034
+ } = useLabelRegistry();
1035
+ const [anchor, setAnchor] = useState3(null);
1036
+ const [value, setValue] = useControllableState({
1037
+ value: controlledValue,
1038
+ defaultValue,
1039
+ onChange: onValueChange
1040
+ });
1041
+ const [isOpen = false, setOpen] = useControllableState({
1042
+ value: controlledOpen,
1043
+ defaultValue: defaultOpen,
1044
+ onChange: onOpenChange
1045
+ });
1046
+ const selection = {
1047
+ variant,
1048
+ size,
1049
+ radius,
1050
+ isOpen: isOpen ? "true" : void 0,
1051
+ isInvalid: isInvalid ? "true" : void 0
1052
+ };
1053
+ const styles = selectRecipe.resolve({
1054
+ theme,
1055
+ selection,
1056
+ states: {
1057
+ disabled: isDisabled
1058
+ }
1059
+ });
1060
+ const pressed = selectRecipe.resolve({
1061
+ theme,
1062
+ selection,
1063
+ states: {
1064
+ pressed: true
1065
+ }
1066
+ });
1067
+ const tint = color ? selectRecipe.tint({
1068
+ theme,
1069
+ color,
1070
+ selection
1071
+ }) : void 0;
1072
+ const open = useCallback4(() => setOpen(true), [setOpen]);
1073
+ const close = useCallback4(() => setOpen(false), [setOpen]);
1074
+ const toggle = useCallback4(() => setOpen(!isOpen), [isOpen, setOpen]);
1075
+ const select = useCallback4((next, label) => {
1076
+ if (label !== void 0) registerLabel(next, label);
1077
+ setValue(next);
1078
+ setOpen(false);
1079
+ }, [registerLabel, setValue, setOpen]);
1080
+ const context = useMemo4(() => {
1081
+ const indicator = StyleSheet.flatten([styles.indicator, tint?.indicator]);
1082
+ const itemLabel = StyleSheet.flatten([styles.itemLabel]);
1083
+ const tintedPlaceholder = tint ? StyleSheet.flatten([tint.value]).color : void 0;
1084
+ return {
1085
+ triggerStyle: tint ? [styles.trigger, tint.trigger] : styles.trigger,
1086
+ triggerPressedStyle: pressed.trigger,
1087
+ valueStyle: tint ? [styles.value, tint.value] : styles.value,
1088
+ placeholderStyle: tintedPlaceholder ? [styles.placeholder, {
1089
+ color: tintedPlaceholder
1090
+ }] : styles.placeholder,
1091
+ indicatorStyle: styles.indicator,
1092
+ overlayStyle: styles.overlay,
1093
+ contentStyle: styles.content,
1094
+ labelStyle: styles.label,
1095
+ itemStyle: styles.item,
1096
+ itemPressedStyle: pressed.item,
1097
+ itemLabelStyle: styles.itemLabel,
1098
+ itemDescriptionStyle: styles.itemDescription,
1099
+ itemIndicatorStyle: styles.itemIndicator,
1100
+ glyph: {
1101
+ size: indicator.fontSize,
1102
+ // `ColorValue` also covers the platform's opaque colours, which `Icon` cannot
1103
+ // hand to a third-party component expecting a string.
1104
+ color: typeof indicator.color === "string" ? indicator.color : void 0
1105
+ },
1106
+ // The check reads the row's own colour rather than the chevron's: it belongs to the
1107
+ // list, and the chevron belongs to the field.
1108
+ checkColor: typeof itemLabel.color === "string" ? itemLabel.color : void 0,
1109
+ value,
1110
+ isOpen,
1111
+ isDisabled,
1112
+ isInvalid,
1113
+ open,
1114
+ close,
1115
+ toggle,
1116
+ select,
1117
+ anchor,
1118
+ setAnchor,
1119
+ labelFor,
1120
+ registerLabel
1121
+ };
1122
+ }, [styles, pressed, tint, value, isOpen, isDisabled, isInvalid, open, close, toggle, select, anchor, labelFor, registerLabel]);
1123
+ return /* @__PURE__ */jsx13(SelectProvider, {
1124
+ value: context,
1125
+ children
1126
+ });
1127
+ }
1128
+ Select.displayName = "XAUI.Select.Root";
1129
+
1130
+ // src/components/select/index.ts
1131
+ var Select2 = Object.assign(Select, {
1132
+ Trigger: SelectTrigger,
1133
+ Value: SelectValue,
1134
+ Indicator: SelectIndicator,
1135
+ Overlay: SelectOverlay,
1136
+ Content: SelectContent,
1137
+ Label: SelectLabel,
1138
+ Item: SelectItem,
1139
+ ItemLabel: SelectItemLabel,
1140
+ ItemDescription: SelectItemDescription,
1141
+ ItemIndicator: SelectItemIndicator
1142
+ });
1143
+ export { useSelect, useSelectItem, SelectItemLabel, SelectItem, SelectContent, ChevronDownIcon, SelectIndicator, SelectItemDescription, CheckIcon, SelectItemIndicator, SelectLabel, SelectOverlay, SelectTrigger, SelectValue, selectRecipe, Select, Select2 };