xiod-ui 1.0.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.
Files changed (224) hide show
  1. package/LICENSE +73 -0
  2. package/README.md +167 -0
  3. package/dist/components/accordion.d.ts +9 -0
  4. package/dist/components/accordion.js +46 -0
  5. package/dist/components/agent-steps.d.ts +47 -0
  6. package/dist/components/agent-steps.js +223 -0
  7. package/dist/components/alert-dialog.d.ts +21 -0
  8. package/dist/components/alert-dialog.js +74 -0
  9. package/dist/components/alert.d.ts +12 -0
  10. package/dist/components/alert.js +45 -0
  11. package/dist/components/aspect-ratio.d.ts +9 -0
  12. package/dist/components/aspect-ratio.js +22 -0
  13. package/dist/components/autocomplete.d.ts +35 -0
  14. package/dist/components/autocomplete.js +160 -0
  15. package/dist/components/avatar.d.ts +17 -0
  16. package/dist/components/avatar.js +65 -0
  17. package/dist/components/badge.d.ts +15 -0
  18. package/dist/components/badge.js +46 -0
  19. package/dist/components/breadcrumb.d.ts +12 -0
  20. package/dist/components/breadcrumb.js +75 -0
  21. package/dist/components/button-group.d.ts +14 -0
  22. package/dist/components/button-group.js +45 -0
  23. package/dist/components/button-split.d.ts +19 -0
  24. package/dist/components/button-split.js +73 -0
  25. package/dist/components/button.d.ts +15 -0
  26. package/dist/components/button.js +54 -0
  27. package/dist/components/calendar.d.ts +63 -0
  28. package/dist/components/calendar.js +425 -0
  29. package/dist/components/card.d.ts +17 -0
  30. package/dist/components/card.js +139 -0
  31. package/dist/components/carousel.d.ts +59 -0
  32. package/dist/components/carousel.js +503 -0
  33. package/dist/components/checkbox.d.ts +16 -0
  34. package/dist/components/checkbox.js +86 -0
  35. package/dist/components/circular-progress.d.ts +28 -0
  36. package/dist/components/circular-progress.js +127 -0
  37. package/dist/components/collapsible.d.ts +8 -0
  38. package/dist/components/collapsible.js +27 -0
  39. package/dist/components/color-picker.d.ts +159 -0
  40. package/dist/components/color-picker.js +1589 -0
  41. package/dist/components/combobox.d.ts +46 -0
  42. package/dist/components/combobox.js +237 -0
  43. package/dist/components/command.d.ts +22 -0
  44. package/dist/components/command.js +129 -0
  45. package/dist/components/context-menu.d.ts +38 -0
  46. package/dist/components/context-menu.js +164 -0
  47. package/dist/components/copy-to-clipboard.d.ts +32 -0
  48. package/dist/components/copy-to-clipboard.js +83 -0
  49. package/dist/components/corner-badge.d.ts +22 -0
  50. package/dist/components/corner-badge.js +84 -0
  51. package/dist/components/dashboard-grid.d.ts +83 -0
  52. package/dist/components/dashboard-grid.js +486 -0
  53. package/dist/components/date-picker.d.ts +29 -0
  54. package/dist/components/date-picker.js +261 -0
  55. package/dist/components/dialog.d.ts +26 -0
  56. package/dist/components/dialog.js +97 -0
  57. package/dist/components/dot-matrix.d.ts +32 -0
  58. package/dist/components/dot-matrix.js +707 -0
  59. package/dist/components/draggable.d.ts +42 -0
  60. package/dist/components/draggable.js +346 -0
  61. package/dist/components/drawer.d.ts +66 -0
  62. package/dist/components/drawer.js +304 -0
  63. package/dist/components/empty.d.ts +14 -0
  64. package/dist/components/empty.js +75 -0
  65. package/dist/components/field.d.ts +12 -0
  66. package/dist/components/field.js +44 -0
  67. package/dist/components/fieldset.d.ts +7 -0
  68. package/dist/components/fieldset.js +21 -0
  69. package/dist/components/file-upload.d.ts +61 -0
  70. package/dist/components/file-upload.js +482 -0
  71. package/dist/components/form.d.ts +6 -0
  72. package/dist/components/form.js +14 -0
  73. package/dist/components/frame.d.ts +10 -0
  74. package/dist/components/frame.js +47 -0
  75. package/dist/components/gauge.d.ts +27 -0
  76. package/dist/components/gauge.js +74 -0
  77. package/dist/components/grid.d.ts +26 -0
  78. package/dist/components/grid.js +204 -0
  79. package/dist/components/group.d.ts +19 -0
  80. package/dist/components/group.js +45 -0
  81. package/dist/components/input-group.d.ts +15 -0
  82. package/dist/components/input-group.js +61 -0
  83. package/dist/components/input-otp.d.ts +24 -0
  84. package/dist/components/input-otp.js +50 -0
  85. package/dist/components/input-payment.d.ts +131 -0
  86. package/dist/components/input-payment.js +1140 -0
  87. package/dist/components/input-phone.d.ts +70 -0
  88. package/dist/components/input-phone.js +657 -0
  89. package/dist/components/input-sensitive.d.ts +12 -0
  90. package/dist/components/input-sensitive.js +169 -0
  91. package/dist/components/input.d.ts +13 -0
  92. package/dist/components/input.js +26 -0
  93. package/dist/components/kbd.d.ts +6 -0
  94. package/dist/components/kbd.js +19 -0
  95. package/dist/components/kinetic-click.d.ts +48 -0
  96. package/dist/components/kinetic-click.js +1184 -0
  97. package/dist/components/label.d.ts +6 -0
  98. package/dist/components/label.js +18 -0
  99. package/dist/components/list-box.d.ts +20 -0
  100. package/dist/components/list-box.js +148 -0
  101. package/dist/components/loader.d.ts +13 -0
  102. package/dist/components/loader.js +430 -0
  103. package/dist/components/marker.d.ts +15 -0
  104. package/dist/components/marker.js +59 -0
  105. package/dist/components/menu.d.ts +42 -0
  106. package/dist/components/menu.js +186 -0
  107. package/dist/components/menubar.d.ts +40 -0
  108. package/dist/components/menubar.js +107 -0
  109. package/dist/components/message.d.ts +33 -0
  110. package/dist/components/message.js +112 -0
  111. package/dist/components/meter.d.ts +10 -0
  112. package/dist/components/meter.js +42 -0
  113. package/dist/components/morphic-toast.d.ts +61 -0
  114. package/dist/components/morphic-toast.js +916 -0
  115. package/dist/components/navigation-menu.d.ts +26 -0
  116. package/dist/components/navigation-menu.js +116 -0
  117. package/dist/components/number-field.d.ts +15 -0
  118. package/dist/components/number-field.js +86 -0
  119. package/dist/components/option-picker.d.ts +18 -0
  120. package/dist/components/option-picker.js +89 -0
  121. package/dist/components/orb.d.ts +38 -0
  122. package/dist/components/orb.js +1413 -0
  123. package/dist/components/pagination.d.ts +25 -0
  124. package/dist/components/pagination.js +147 -0
  125. package/dist/components/popover.d.ts +22 -0
  126. package/dist/components/popover.js +79 -0
  127. package/dist/components/preview-card.d.ts +16 -0
  128. package/dist/components/preview-card.js +60 -0
  129. package/dist/components/progress.d.ts +21 -0
  130. package/dist/components/progress.js +139 -0
  131. package/dist/components/radio.d.ts +16 -0
  132. package/dist/components/radio.js +68 -0
  133. package/dist/components/resizable.d.ts +58 -0
  134. package/dist/components/resizable.js +964 -0
  135. package/dist/components/ruler-picker.d.ts +27 -0
  136. package/dist/components/ruler-picker.js +253 -0
  137. package/dist/components/scroll-area.d.ts +13 -0
  138. package/dist/components/scroll-area.js +34 -0
  139. package/dist/components/scroll-bar.d.ts +13 -0
  140. package/dist/components/scroll-bar.js +47 -0
  141. package/dist/components/select.d.ts +29 -0
  142. package/dist/components/select.js +140 -0
  143. package/dist/components/separator.d.ts +6 -0
  144. package/dist/components/separator.js +15 -0
  145. package/dist/components/sidebar.d.ts +65 -0
  146. package/dist/components/sidebar.js +408 -0
  147. package/dist/components/skeleton.d.ts +5 -0
  148. package/dist/components/skeleton.js +12 -0
  149. package/dist/components/slider.d.ts +12 -0
  150. package/dist/components/slider.js +96 -0
  151. package/dist/components/sortable.d.ts +44 -0
  152. package/dist/components/sortable.js +327 -0
  153. package/dist/components/switch.d.ts +15 -0
  154. package/dist/components/switch.js +63 -0
  155. package/dist/components/table.d.ts +12 -0
  156. package/dist/components/table.js +65 -0
  157. package/dist/components/tabs.d.ts +12 -0
  158. package/dist/components/tabs.js +39 -0
  159. package/dist/components/text.d.ts +14 -0
  160. package/dist/components/text.js +69 -0
  161. package/dist/components/textarea.d.ts +9 -0
  162. package/dist/components/textarea.js +20 -0
  163. package/dist/components/theme-provider.d.ts +52 -0
  164. package/dist/components/theme-provider.js +148 -0
  165. package/dist/components/timeline.d.ts +34 -0
  166. package/dist/components/timeline.js +147 -0
  167. package/dist/components/toast.d.ts +17 -0
  168. package/dist/components/toast.js +161 -0
  169. package/dist/components/toggle-group.d.ts +14 -0
  170. package/dist/components/toggle-group.js +53 -0
  171. package/dist/components/toggle.d.ts +11 -0
  172. package/dist/components/toggle.js +36 -0
  173. package/dist/components/toolbar.d.ts +11 -0
  174. package/dist/components/toolbar.js +49 -0
  175. package/dist/components/tooltip.d.ts +17 -0
  176. package/dist/components/tooltip.js +56 -0
  177. package/dist/components/waveform.d.ts +61 -0
  178. package/dist/components/waveform.js +500 -0
  179. package/dist/components/wheel-picker.d.ts +44 -0
  180. package/dist/components/wheel-picker.js +771 -0
  181. package/dist/hooks/use-copy-to-clipboard.d.ts +9 -0
  182. package/dist/hooks/use-copy-to-clipboard.js +36 -0
  183. package/dist/hooks/use-media-query.d.ts +21 -0
  184. package/dist/hooks/use-media-query.js +58 -0
  185. package/dist/styles.css +202 -0
  186. package/dist/themes/afterglow.css +89 -0
  187. package/dist/themes/afterglow.scoped.css +90 -0
  188. package/dist/themes/blacklight.css +89 -0
  189. package/dist/themes/blacklight.scoped.css +90 -0
  190. package/dist/themes/cathode.css +89 -0
  191. package/dist/themes/cathode.scoped.css +90 -0
  192. package/dist/themes/cel.css +89 -0
  193. package/dist/themes/cel.scoped.css +90 -0
  194. package/dist/themes/cinder.css +89 -0
  195. package/dist/themes/cinder.scoped.css +90 -0
  196. package/dist/themes/clay.css +89 -0
  197. package/dist/themes/clay.scoped.css +90 -0
  198. package/dist/themes/cobalt.css +89 -0
  199. package/dist/themes/cobalt.scoped.css +90 -0
  200. package/dist/themes/crimson.css +89 -0
  201. package/dist/themes/crimson.scoped.css +90 -0
  202. package/dist/themes/ion.css +89 -0
  203. package/dist/themes/ion.scoped.css +90 -0
  204. package/dist/themes/iris.css +89 -0
  205. package/dist/themes/iris.scoped.css +90 -0
  206. package/dist/themes/lagoon.css +89 -0
  207. package/dist/themes/lagoon.scoped.css +90 -0
  208. package/dist/themes/mochi.css +89 -0
  209. package/dist/themes/mochi.scoped.css +90 -0
  210. package/dist/themes/riso.css +89 -0
  211. package/dist/themes/riso.scoped.css +90 -0
  212. package/dist/themes/roast.css +89 -0
  213. package/dist/themes/roast.scoped.css +90 -0
  214. package/dist/themes/sage.css +89 -0
  215. package/dist/themes/sage.scoped.css +90 -0
  216. package/dist/themes/sepia.css +89 -0
  217. package/dist/themes/sepia.scoped.css +90 -0
  218. package/dist/themes/sorbet.css +89 -0
  219. package/dist/themes/sorbet.scoped.css +90 -0
  220. package/dist/themes/taffy.css +89 -0
  221. package/dist/themes/taffy.scoped.css +90 -0
  222. package/dist/themes/toxin.css +89 -0
  223. package/dist/themes/toxin.scoped.css +90 -0
  224. package/package.json +140 -0
@@ -0,0 +1,771 @@
1
+ "use client";
2
+ import { cn } from "cn";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ import { cva } from "class-variance-authority";
5
+ import * as React$1 from "react";
6
+ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
7
+ //#region src/components/wheel-picker.tsx
8
+ const RESISTANCE = .3;
9
+ const MAX_VELOCITY = 30;
10
+ const easeOutCubic = (p) => (p - 1) ** 3 + 1;
11
+ const clamp = (value, min, max) => Math.max(min, Math.min(value, max));
12
+ const WheelPickerGroupContext = React$1.createContext(null);
13
+ function useWheelPickerGroup() {
14
+ return React$1.useContext(WheelPickerGroupContext);
15
+ }
16
+ function WheelPickerGroup({ className, children, ...props }) {
17
+ const [activeIndex, setActiveIndex] = useState(-1);
18
+ const counterRef = useRef(0);
19
+ const pickerRefsRef = useRef(/* @__PURE__ */ new Map());
20
+ const register = useCallback((existingIndex, ref) => {
21
+ const index = existingIndex !== null ? existingIndex : counterRef.current++;
22
+ pickerRefsRef.current.set(index, ref);
23
+ setActiveIndex((current) => current === -1 ? index : current);
24
+ return index;
25
+ }, []);
26
+ const getPickerRef = useCallback((index) => pickerRefsRef.current.get(index) ?? null, []);
27
+ const getPickerIndices = useCallback(() => Array.from(pickerRefsRef.current.keys()).toSorted((a, b) => a - b), []);
28
+ const value = useMemo(() => ({
29
+ activeIndex,
30
+ setActiveIndex,
31
+ register,
32
+ getPickerRef,
33
+ getPickerIndices
34
+ }), [
35
+ activeIndex,
36
+ register,
37
+ getPickerRef,
38
+ getPickerIndices
39
+ ]);
40
+ return /* @__PURE__ */ jsx(WheelPickerGroupContext.Provider, {
41
+ value,
42
+ children: /* @__PURE__ */ jsx("div", {
43
+ className: cn("relative flex items-stretch justify-center border border-border/80 bg-background/50 rounded-2xl p-[calc(--spacing(2)-1px)] select-none shadow-xs/5 max-w-full overflow-hidden before:pointer-events-none before:absolute before:inset-0 before:rounded-[calc(var(--radius-2xl)-1px)] before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", className),
44
+ "data-slot": "wheel-picker-group",
45
+ ...props,
46
+ children
47
+ })
48
+ });
49
+ }
50
+ const TYPEAHEAD_TIMEOUT_MS = 600;
51
+ function useTypeaheadSearch(options, { getTextValue, getCurrentIndex, onMatch }) {
52
+ const searchBufferRef = useRef("");
53
+ const timeoutRef = useRef(null);
54
+ const resetTypeahead = useCallback(() => {
55
+ searchBufferRef.current = "";
56
+ if (timeoutRef.current) {
57
+ clearTimeout(timeoutRef.current);
58
+ timeoutRef.current = null;
59
+ }
60
+ }, []);
61
+ return {
62
+ handleTypeaheadSearch: useCallback((char) => {
63
+ if (timeoutRef.current) clearTimeout(timeoutRef.current);
64
+ searchBufferRef.current += char.toLowerCase();
65
+ const searchTerm = searchBufferRef.current;
66
+ const normalizedSearch = searchTerm.length > 1 && Array.from(searchTerm).every((c) => c === searchTerm[0]) ? searchTerm[0] : searchTerm;
67
+ const currentIndex = getCurrentIndex();
68
+ const shouldCycle = normalizedSearch.length === 1;
69
+ let matchIndex = -1;
70
+ if (shouldCycle) for (let i = 1; i <= options.length; i++) {
71
+ const index = (currentIndex + i) % options.length;
72
+ if (getTextValue(options[index]).toLowerCase().startsWith(normalizedSearch)) {
73
+ matchIndex = index;
74
+ break;
75
+ }
76
+ }
77
+ else matchIndex = options.findIndex((option) => {
78
+ return getTextValue(option).toLowerCase().startsWith(normalizedSearch);
79
+ });
80
+ if (matchIndex !== -1) onMatch(matchIndex);
81
+ timeoutRef.current = setTimeout(() => {
82
+ searchBufferRef.current = "";
83
+ timeoutRef.current = null;
84
+ }, TYPEAHEAD_TIMEOUT_MS);
85
+ }, [
86
+ options,
87
+ getTextValue,
88
+ getCurrentIndex,
89
+ onMatch
90
+ ]),
91
+ resetTypeahead
92
+ };
93
+ }
94
+ function useCallbackRef(callback) {
95
+ const callbackRef = useRef(callback);
96
+ useEffect(() => {
97
+ callbackRef.current = callback;
98
+ });
99
+ return useMemo(() => ((...args) => callbackRef.current?.(...args)), []);
100
+ }
101
+ function useControllableState({ prop, defaultProp, onChange = () => {} }) {
102
+ const [uncontrolledProp, setUncontrolledProp] = useState(defaultProp);
103
+ const isControlled = prop !== void 0;
104
+ const value = isControlled ? prop : uncontrolledProp;
105
+ const handleChange = useCallbackRef(onChange);
106
+ return [value, useCallback((nextValue) => {
107
+ if (isControlled) {
108
+ const val = typeof nextValue === "function" ? nextValue(prop) : nextValue;
109
+ if (val !== prop && val !== void 0) handleChange(val);
110
+ } else setUncontrolledProp(nextValue);
111
+ }, [
112
+ isControlled,
113
+ prop,
114
+ handleChange
115
+ ])];
116
+ }
117
+ const wheelPickerVariants = cva("relative flex-1 cursor-default select-none focus:outline-none focus-visible:outline-none min-w-[70px]", {
118
+ variants: { size: {
119
+ sm: "h-[180px] rounded-lg",
120
+ md: "h-[220px] rounded-xl",
121
+ lg: "h-[260px] rounded-2xl"
122
+ } },
123
+ defaultVariants: { size: "md" }
124
+ });
125
+ function findNearestEnabledIndex(startIndex, direction, options, infinite) {
126
+ if (options.length === 0) return startIndex;
127
+ if (!options.some((opt) => !opt.disabled)) return startIndex;
128
+ const searchInDirection = (dir) => {
129
+ let currentIndex = startIndex;
130
+ let attempts = 0;
131
+ const maxAttempts = options.length;
132
+ while (attempts < maxAttempts) {
133
+ currentIndex = currentIndex + dir;
134
+ if (infinite) currentIndex = (currentIndex % options.length + options.length) % options.length;
135
+ else if (currentIndex < 0 || currentIndex >= options.length) return -1;
136
+ if (!options[currentIndex]?.disabled) return currentIndex;
137
+ attempts++;
138
+ }
139
+ return -1;
140
+ };
141
+ let nearestIndex = searchInDirection(direction);
142
+ if (nearestIndex === -1) nearestIndex = searchInDirection(direction * -1);
143
+ return nearestIndex === -1 ? startIndex : nearestIndex;
144
+ }
145
+ function WheelPicker({ className, options: optionsProp, value: valueProp, defaultValue, onValueChange, infinite = false, visibleCount = 20, dragSensitivity = 3, scrollSensitivity = 5, optionItemHeight, classNames, size = "md", ...props }) {
146
+ const itemHeight = optionItemHeight ?? (size === "sm" ? 28 : size === "lg" ? 44 : 36);
147
+ const firstEnabledValue = useMemo(() => {
148
+ return optionsProp.find((opt) => !opt.disabled)?.value ?? optionsProp[0]?.value;
149
+ }, [optionsProp]);
150
+ const [value = firstEnabledValue, setValue] = useControllableState({
151
+ prop: valueProp,
152
+ defaultProp: defaultValue,
153
+ onChange: onValueChange
154
+ });
155
+ const options = useMemo(() => {
156
+ if (!infinite || optionsProp.length === 0) return optionsProp;
157
+ const result = [];
158
+ const L = optionsProp.length;
159
+ const gcd = (a, b) => b === 0 ? a : gcd(b, a % b);
160
+ const lcm = L * visibleCount / gcd(L, visibleCount);
161
+ let targetLength = lcm;
162
+ const minLength = Math.ceil(visibleCount * 1.5);
163
+ if (targetLength < minLength) targetLength = Math.ceil(minLength / lcm) * lcm;
164
+ const k = targetLength / L;
165
+ for (let i = 0; i < k; i++) result.push(...optionsProp);
166
+ return result;
167
+ }, [
168
+ optionsProp,
169
+ infinite,
170
+ visibleCount
171
+ ]);
172
+ const halfItemHeight = itemHeight * .5;
173
+ const itemAngle = 360 / visibleCount;
174
+ const radius = itemHeight / Math.tan(itemAngle * Math.PI / 180);
175
+ const containerHeight = Math.round(radius * 2 + itemHeight * .25);
176
+ const quarterCount = visibleCount >> 2;
177
+ const baseDeceleration = dragSensitivity * 12;
178
+ const snapBackDeceleration = 10;
179
+ const containerRef = useRef(null);
180
+ const wheelItemsRef = useRef(null);
181
+ const highlightListRef = useRef(null);
182
+ const scrollRef = useRef(0);
183
+ const moveId = useRef(0);
184
+ const draggingRef = useRef(false);
185
+ useRef(0);
186
+ const wheelSnapTimeoutRef = useRef(null);
187
+ const [isFocused, setIsFocused] = useState(false);
188
+ const pickerIndexRef = useRef(-1);
189
+ const group = useWheelPickerGroup();
190
+ const containerRefCallback = useCallback((node) => {
191
+ containerRef.current = node;
192
+ if (node && group) {
193
+ const existingIndex = pickerIndexRef.current === -1 ? null : pickerIndexRef.current;
194
+ pickerIndexRef.current = group.register(existingIndex, node);
195
+ }
196
+ }, [group]);
197
+ const touchDataRef = useRef({
198
+ startY: 0,
199
+ yList: [],
200
+ touchScroll: 0,
201
+ isClick: true
202
+ });
203
+ const dragControllerRef = useRef(null);
204
+ const renderWheelItems = useMemo(() => {
205
+ const renderItem = (item, index, angle) => /* @__PURE__ */ jsx("li", {
206
+ className: cn("absolute left-0 w-full flex items-center justify-center text-muted-foreground/70 dark:text-muted-foreground/60 transition-[color] duration-150 text-sm font-medium tabular-nums select-none", item.disabled && "opacity-30 pointer-events-none", classNames?.optionItem),
207
+ "data-slot": "wheel-picker-option",
208
+ "data-index": index,
209
+ "data-disabled": item.disabled || void 0,
210
+ style: {
211
+ top: -halfItemHeight,
212
+ height: itemHeight,
213
+ lineHeight: `${itemHeight}px`,
214
+ transform: `rotateX(${angle}deg) translateZ(${radius}px)`,
215
+ backfaceVisibility: "hidden",
216
+ WebkitBackfaceVisibility: "hidden",
217
+ visibility: "hidden"
218
+ },
219
+ children: item.label
220
+ }, index);
221
+ const items = options.map((option, index) => renderItem(option, index, -itemAngle * index));
222
+ if (infinite) for (let i = 0; i < quarterCount; ++i) {
223
+ const prependIndex = -i - 1;
224
+ const appendIndex = i + options.length;
225
+ items.unshift(renderItem(options[options.length - i - 1], prependIndex, itemAngle * (i + 1)));
226
+ items.push(renderItem(options[i], appendIndex, -itemAngle * appendIndex));
227
+ }
228
+ return items;
229
+ }, [
230
+ itemHeight,
231
+ halfItemHeight,
232
+ infinite,
233
+ itemAngle,
234
+ options,
235
+ quarterCount,
236
+ radius,
237
+ classNames?.optionItem
238
+ ]);
239
+ const renderHighlightItems = useMemo(() => {
240
+ const renderItem = (item, key) => /* @__PURE__ */ jsx("li", {
241
+ className: cn("w-full flex items-center justify-center text-foreground font-semibold tabular-nums select-none transition-colors duration-150", size === "sm" ? "text-sm" : size === "lg" ? "text-lg" : "text-base", item.disabled && "opacity-30 pointer-events-none", classNames?.highlightItem),
242
+ "data-slot": "wheel-picker-highlight-item",
243
+ "data-disabled": item.disabled || void 0,
244
+ style: { height: itemHeight },
245
+ children: item.label
246
+ }, key);
247
+ const items = options.map((option, index) => renderItem(option, index));
248
+ if (infinite && options.length > 0) {
249
+ const firstItem = options[0];
250
+ const lastItem = options[options.length - 1];
251
+ items.unshift(renderItem(lastItem, "infinite-start"));
252
+ items.push(renderItem(firstItem, "infinite-end"));
253
+ }
254
+ return items;
255
+ }, [
256
+ classNames?.highlightItem,
257
+ itemHeight,
258
+ infinite,
259
+ options,
260
+ size
261
+ ]);
262
+ const wheelSegmentPositions = useMemo(() => {
263
+ let positionAlongWheel = 0;
264
+ const degToRad = Math.PI / 180;
265
+ const segmentRanges = [];
266
+ for (let i = quarterCount - 1; i >= -quarterCount + 1; --i) {
267
+ const angle = i * itemAngle;
268
+ const segmentLength = itemHeight * Math.cos(angle * degToRad);
269
+ const start = positionAlongWheel;
270
+ positionAlongWheel += segmentLength;
271
+ segmentRanges.push([start, positionAlongWheel]);
272
+ }
273
+ return segmentRanges;
274
+ }, [
275
+ itemAngle,
276
+ itemHeight,
277
+ quarterCount
278
+ ]);
279
+ const normalizeScroll = useCallback((scroll) => {
280
+ if (options.length === 0) return 0;
281
+ return (scroll % options.length + options.length) % options.length;
282
+ }, [options.length]);
283
+ const scrollTo = useCallback((scroll) => {
284
+ const normalizedScroll = infinite ? normalizeScroll(scroll) : scroll;
285
+ if (wheelItemsRef.current) {
286
+ const transform = `translateZ(${-radius}px) rotateX(${itemAngle * normalizedScroll}deg)`;
287
+ wheelItemsRef.current.style.transform = transform;
288
+ const children = wheelItemsRef.current.childNodes;
289
+ for (let i = 0; i < children.length; i++) {
290
+ const li = children[i];
291
+ const distance = Math.abs(Number(li.dataset.index) - normalizedScroll);
292
+ li.style.visibility = distance > quarterCount ? "hidden" : "visible";
293
+ const baseOpacity = li.dataset.disabled ? .3 : 1;
294
+ const opacity = distance < .5 ? distance / .5 * baseOpacity : baseOpacity;
295
+ li.style.opacity = opacity.toString();
296
+ }
297
+ }
298
+ if (highlightListRef.current) highlightListRef.current.style.transform = `translateY(${-normalizedScroll * itemHeight}px)`;
299
+ return normalizedScroll;
300
+ }, [
301
+ radius,
302
+ itemAngle,
303
+ quarterCount,
304
+ itemHeight,
305
+ infinite,
306
+ normalizeScroll
307
+ ]);
308
+ const cancelAnimation = useCallback(() => {
309
+ cancelAnimationFrame(moveId.current);
310
+ }, []);
311
+ const animateScroll = useCallback((startScroll, endScroll, duration, onComplete) => {
312
+ if (startScroll === endScroll || duration === 0) {
313
+ scrollTo(startScroll);
314
+ onComplete?.();
315
+ return;
316
+ }
317
+ const startTime = performance.now();
318
+ const totalDistance = endScroll - startScroll;
319
+ const tick = (currentTime) => {
320
+ const elapsed = (currentTime - startTime) / 1e3;
321
+ if (elapsed < duration) {
322
+ const progress = easeOutCubic(elapsed / duration);
323
+ scrollRef.current = scrollTo(startScroll + progress * totalDistance);
324
+ moveId.current = requestAnimationFrame(tick);
325
+ } else {
326
+ cancelAnimation();
327
+ scrollRef.current = scrollTo(endScroll);
328
+ onComplete?.();
329
+ }
330
+ };
331
+ requestAnimationFrame(tick);
332
+ }, [scrollTo, cancelAnimation]);
333
+ const scrollDirectionRef = useRef(1);
334
+ const selectByScroll = useCallbackRef((scroll, scrollDirection) => {
335
+ if (options.length === 0) return;
336
+ const normalized = Math.round(normalizeScroll(scroll));
337
+ const boundedScroll = infinite ? normalized : clamp(Math.round(scroll), 0, options.length - 1);
338
+ if (!infinite && boundedScroll !== scroll) return;
339
+ if (options[boundedScroll]?.disabled) {
340
+ const step = findNearestEnabledIndex(boundedScroll, scrollDirection ?? scrollDirectionRef.current, options, infinite) - scrollRef.current;
341
+ if (step !== 0) {
342
+ scrollByStep(step);
343
+ return;
344
+ }
345
+ }
346
+ scrollRef.current = scrollTo(boundedScroll);
347
+ const selected = options[scrollRef.current];
348
+ if (selected && !selected.disabled) setValue(selected.value);
349
+ });
350
+ const selectByValue = useCallbackRef((val) => {
351
+ if (options.length === 0 || draggingRef.current) return;
352
+ const currentIndex = Math.round(scrollRef.current);
353
+ let index = -1;
354
+ let minDistance = Number.MAX_VALUE;
355
+ for (let i = 0; i < options.length; i++) if (options[i].value === val) {
356
+ const distance = Math.abs(i - currentIndex);
357
+ if (distance < minDistance) {
358
+ minDistance = distance;
359
+ index = i;
360
+ }
361
+ }
362
+ if (index === -1) return;
363
+ if (options[index]?.disabled) index = findNearestEnabledIndex(index, 1, options, infinite);
364
+ cancelAnimation();
365
+ selectByScroll(index);
366
+ });
367
+ const scrollByStep = useCallbackRef((step) => {
368
+ if (options.length === 0) return;
369
+ const startScroll = scrollRef.current;
370
+ let endScroll = startScroll + step;
371
+ if (infinite) endScroll = Math.round(endScroll);
372
+ else endScroll = clamp(Math.round(endScroll), 0, options.length - 1);
373
+ const distance = Math.abs(endScroll - startScroll);
374
+ if (distance === 0) return;
375
+ const direction = step > 0 ? 1 : -1;
376
+ scrollDirectionRef.current = direction;
377
+ const duration = Math.sqrt(distance / scrollSensitivity);
378
+ cancelAnimation();
379
+ animateScroll(startScroll, endScroll, duration, () => {
380
+ selectByScroll(scrollRef.current, direction);
381
+ });
382
+ });
383
+ const handleWheelItemClick = useCallback((clientY) => {
384
+ const container = containerRef.current;
385
+ if (!container) return;
386
+ const { top } = container.getBoundingClientRect();
387
+ const clickOffsetY = clientY - top;
388
+ const clickedSegmentIndex = wheelSegmentPositions.findIndex(([start, end]) => clickOffsetY >= start && clickOffsetY <= end);
389
+ if (clickedSegmentIndex === -1) return;
390
+ const stepsToScroll = (quarterCount - clickedSegmentIndex - 1) * -1;
391
+ const targetIndex = scrollRef.current + stepsToScroll;
392
+ const normalizedIndex = infinite ? normalizeScroll(targetIndex) : Math.max(0, Math.min(targetIndex, options.length - 1));
393
+ if (options[normalizedIndex]?.disabled) return;
394
+ scrollByStep(stepsToScroll);
395
+ }, [
396
+ wheelSegmentPositions,
397
+ quarterCount,
398
+ infinite,
399
+ normalizeScroll,
400
+ options,
401
+ scrollByStep
402
+ ]);
403
+ const updateScrollDuringDrag = useCallback((e) => {
404
+ if (options.length === 0) return;
405
+ const currentY = (e instanceof MouseEvent ? e.clientY : e.touches?.[0]?.clientY) || 0;
406
+ const touchData = touchDataRef.current;
407
+ if (touchData.isClick) {
408
+ if (Math.abs(currentY - touchData.startY) > 5) touchData.isClick = false;
409
+ }
410
+ touchData.yList.push([currentY, Date.now()]);
411
+ if (touchData.yList.length > 5) touchData.yList.shift();
412
+ const dragDelta = (touchData.startY - currentY) / itemHeight;
413
+ let nextScroll = scrollRef.current + dragDelta;
414
+ if (infinite) nextScroll = normalizeScroll(nextScroll);
415
+ else {
416
+ const maxIndex = options.length - 1;
417
+ if (nextScroll < 0) nextScroll *= RESISTANCE;
418
+ else if (nextScroll > maxIndex) nextScroll = maxIndex + (nextScroll - maxIndex) * RESISTANCE;
419
+ }
420
+ touchData.touchScroll = scrollTo(nextScroll);
421
+ }, [
422
+ options.length,
423
+ itemHeight,
424
+ infinite,
425
+ normalizeScroll,
426
+ scrollTo
427
+ ]);
428
+ const decelerateAndAnimateScroll = useCallback((initialVelocity) => {
429
+ const currentScroll = scrollRef.current;
430
+ let targetScroll = currentScroll;
431
+ let duration = 0;
432
+ const direction = initialVelocity > 0 ? 1 : -1;
433
+ scrollDirectionRef.current = direction;
434
+ if (infinite) {
435
+ const signedDistance = initialVelocity * initialVelocity / (2 * baseDeceleration) * direction;
436
+ targetScroll = Math.round(currentScroll + signedDistance);
437
+ const inertiaDuration = Math.abs(initialVelocity / baseDeceleration);
438
+ const distanceToTarget = Math.abs(targetScroll - currentScroll);
439
+ const snapDuration = Math.sqrt(distanceToTarget / snapBackDeceleration);
440
+ duration = Math.max(inertiaDuration, snapDuration);
441
+ } else {
442
+ const predictedTarget = currentScroll + initialVelocity * initialVelocity / (2 * baseDeceleration) * direction;
443
+ if (predictedTarget < 0) {
444
+ targetScroll = 0;
445
+ const distance = Math.abs(currentScroll - targetScroll);
446
+ duration = Math.sqrt(distance / snapBackDeceleration);
447
+ } else if (predictedTarget > options.length - 1) {
448
+ targetScroll = options.length - 1;
449
+ const distance = Math.abs(currentScroll - targetScroll);
450
+ duration = Math.sqrt(distance / snapBackDeceleration);
451
+ } else {
452
+ targetScroll = Math.round(predictedTarget);
453
+ const inertiaDuration = Math.abs(initialVelocity / baseDeceleration);
454
+ const distanceToTarget = Math.abs(targetScroll - currentScroll);
455
+ const snapDuration = Math.sqrt(distanceToTarget / snapBackDeceleration);
456
+ duration = Math.max(inertiaDuration, snapDuration);
457
+ }
458
+ }
459
+ if (targetScroll !== currentScroll) duration = clamp(duration, .15, .8);
460
+ else duration = 0;
461
+ animateScroll(currentScroll, targetScroll, duration, () => {
462
+ selectByScroll(scrollRef.current, direction);
463
+ });
464
+ }, [
465
+ baseDeceleration,
466
+ infinite,
467
+ options.length,
468
+ animateScroll,
469
+ selectByScroll
470
+ ]);
471
+ const finalizeDragAndStartInertiaScroll = useCallback(() => {
472
+ try {
473
+ dragControllerRef.current?.abort();
474
+ dragControllerRef.current = null;
475
+ const touchData = touchDataRef.current;
476
+ if (touchData.isClick) {
477
+ handleWheelItemClick(touchData.startY);
478
+ return;
479
+ }
480
+ const yList = touchData.yList;
481
+ let velocity = 0;
482
+ if (yList.length > 1) {
483
+ const len = yList.length;
484
+ const [startY, startTime] = yList[len - 2] ?? [0, 0];
485
+ const [endY, endTime] = yList[len - 1] ?? [0, 0];
486
+ const timeDiff = endTime - startTime;
487
+ if (timeDiff > 0) {
488
+ const velocityPerSecond = (startY - endY) / itemHeight * 1e3 / timeDiff;
489
+ velocity = Math.min(Math.abs(velocityPerSecond), MAX_VELOCITY) * (velocityPerSecond > 0 ? 1 : -1);
490
+ }
491
+ }
492
+ scrollRef.current = touchData.touchScroll ?? scrollRef.current;
493
+ decelerateAndAnimateScroll(velocity);
494
+ } finally {
495
+ draggingRef.current = false;
496
+ }
497
+ }, [
498
+ handleWheelItemClick,
499
+ itemHeight,
500
+ decelerateAndAnimateScroll
501
+ ]);
502
+ const handleDragMoveEvent = useCallback((event) => {
503
+ if (event.cancelable) event.preventDefault();
504
+ updateScrollDuringDrag(event);
505
+ }, [updateScrollDuringDrag]);
506
+ const handleDragEndEvent = useCallback((event) => {
507
+ if (options.length === 0) return;
508
+ if (event.cancelable) event.preventDefault();
509
+ finalizeDragAndStartInertiaScroll();
510
+ }, [options.length, finalizeDragAndStartInertiaScroll]);
511
+ const initiateDragGesture = useCallback((event) => {
512
+ draggingRef.current = true;
513
+ const controller = new AbortController();
514
+ const { signal } = controller;
515
+ dragControllerRef.current = controller;
516
+ const opts = {
517
+ signal,
518
+ passive: false
519
+ };
520
+ containerRef.current?.addEventListener("touchmove", handleDragMoveEvent, opts);
521
+ containerRef.current?.addEventListener("touchend", handleDragEndEvent, opts);
522
+ document.addEventListener("mousemove", handleDragMoveEvent, opts);
523
+ document.addEventListener("mouseup", handleDragEndEvent, opts);
524
+ window.addEventListener("blur", finalizeDragAndStartInertiaScroll, { signal });
525
+ const startY = (event instanceof MouseEvent ? event.clientY : event.touches?.[0]?.clientY) || 0;
526
+ const touchData = touchDataRef.current;
527
+ touchData.startY = startY;
528
+ touchData.yList = [[startY, Date.now()]];
529
+ touchData.touchScroll = scrollRef.current;
530
+ touchData.isClick = true;
531
+ cancelAnimation();
532
+ }, [
533
+ handleDragMoveEvent,
534
+ handleDragEndEvent,
535
+ finalizeDragAndStartInertiaScroll,
536
+ cancelAnimation
537
+ ]);
538
+ const handleDragStartEvent = useCallback((e) => {
539
+ if (options.length === 0) return;
540
+ if (e instanceof MouseEvent && e.button !== 0) return;
541
+ if (e.cancelable) e.preventDefault();
542
+ initiateDragGesture(e);
543
+ }, [options.length, initiateDragGesture]);
544
+ const scrollByWheel = useCallback((event) => {
545
+ event.preventDefault();
546
+ cancelAnimation();
547
+ if (wheelSnapTimeoutRef.current) clearTimeout(wheelSnapTimeoutRef.current);
548
+ const delta = event.deltaY * .003 * scrollSensitivity;
549
+ let nextScroll = scrollRef.current + delta;
550
+ if (infinite) nextScroll = normalizeScroll(nextScroll);
551
+ else nextScroll = clamp(nextScroll, 0, options.length - 1);
552
+ scrollTo(nextScroll);
553
+ scrollRef.current = nextScroll;
554
+ const direction = event.deltaY > 0 ? 1 : -1;
555
+ scrollDirectionRef.current = direction;
556
+ wheelSnapTimeoutRef.current = setTimeout(() => {
557
+ const targetIndex = Math.round(scrollRef.current);
558
+ animateScroll(scrollRef.current, targetIndex, .15, () => {
559
+ selectByScroll(scrollRef.current, direction);
560
+ });
561
+ }, 150);
562
+ }, [
563
+ scrollSensitivity,
564
+ infinite,
565
+ options.length,
566
+ normalizeScroll,
567
+ scrollTo,
568
+ animateScroll,
569
+ selectByScroll,
570
+ cancelAnimation
571
+ ]);
572
+ const handleWheelEvent = useCallback((event) => {
573
+ if (options.length === 0 || !containerRef.current) return;
574
+ if (containerRef.current.contains(event.target) && event.cancelable) {
575
+ event.preventDefault();
576
+ scrollByWheel(event);
577
+ }
578
+ }, [options.length, scrollByWheel]);
579
+ const navigateToPicker = useCallback((direction) => {
580
+ const pickerIndex = pickerIndexRef.current;
581
+ if (!group || pickerIndex === -1) return;
582
+ const sortedIndices = group.getPickerIndices();
583
+ const currentPos = sortedIndices.indexOf(pickerIndex);
584
+ if (currentPos === -1) return;
585
+ let targetPos;
586
+ if (direction === "prev") targetPos = currentPos > 0 ? currentPos - 1 : sortedIndices.length - 1;
587
+ else targetPos = currentPos < sortedIndices.length - 1 ? currentPos + 1 : 0;
588
+ const targetIndex = sortedIndices[targetPos];
589
+ const targetRef = group.getPickerRef(targetIndex);
590
+ if (targetRef) {
591
+ const currentRef = containerRef.current;
592
+ if (currentRef) currentRef.tabIndex = -1;
593
+ targetRef.tabIndex = 0;
594
+ group.setActiveIndex(targetIndex);
595
+ targetRef.focus();
596
+ }
597
+ }, [group]);
598
+ const enabledOptionsMap = useMemo(() => {
599
+ const map = /* @__PURE__ */ new Map();
600
+ const reverseMap = /* @__PURE__ */ new Map();
601
+ const enabled = [];
602
+ options.forEach((option, index) => {
603
+ if (!option.disabled) {
604
+ const enabledIndex = enabled.length;
605
+ map.set(enabledIndex, index);
606
+ reverseMap.set(index, enabledIndex);
607
+ enabled.push(option);
608
+ }
609
+ });
610
+ return {
611
+ enabled,
612
+ map,
613
+ reverseMap
614
+ };
615
+ }, [options]);
616
+ const { handleTypeaheadSearch, resetTypeahead } = useTypeaheadSearch(enabledOptionsMap.enabled, {
617
+ getTextValue: (opt) => {
618
+ return opt.textValue ?? (typeof opt.label === "string" ? opt.label : String(opt.value));
619
+ },
620
+ getCurrentIndex: useCallback(() => {
621
+ const currentIndex = Math.round(scrollRef.current);
622
+ return enabledOptionsMap.reverseMap.get(currentIndex) ?? 0;
623
+ }, [enabledOptionsMap]),
624
+ onMatch: useCallback((enabledIndex) => {
625
+ const originalIndex = enabledOptionsMap.map.get(enabledIndex);
626
+ if (originalIndex !== void 0) {
627
+ const step = originalIndex - Math.round(scrollRef.current);
628
+ scrollByStep(step);
629
+ }
630
+ }, [enabledOptionsMap, scrollByStep])
631
+ });
632
+ const handleKeyDown = useCallback((event) => {
633
+ if (options.length === 0) return;
634
+ const handleVerticalNavigation = (direction) => {
635
+ event.preventDefault();
636
+ const currentIndex = Math.round(scrollRef.current);
637
+ let targetIndex = currentIndex + direction;
638
+ if (!infinite) {
639
+ if (direction === -1 && targetIndex < 0) return;
640
+ if (direction === 1 && targetIndex >= options.length) return;
641
+ }
642
+ const normalizedTarget = infinite ? (targetIndex % options.length + options.length) % options.length : targetIndex;
643
+ if (options[normalizedTarget]?.disabled) {
644
+ const nearestEnabled = findNearestEnabledIndex(normalizedTarget, direction, options, infinite);
645
+ targetIndex = currentIndex + direction + (nearestEnabled - normalizedTarget);
646
+ }
647
+ const step = targetIndex - currentIndex;
648
+ if (step !== 0) scrollByStep(step);
649
+ };
650
+ const handleHome = () => {
651
+ if (infinite) return;
652
+ event.preventDefault();
653
+ let targetIndex = 0;
654
+ if (options[0]?.disabled) targetIndex = findNearestEnabledIndex(0, 1, options, false);
655
+ const step = targetIndex - scrollRef.current;
656
+ if (step !== 0) scrollByStep(step);
657
+ };
658
+ const handleEnd = () => {
659
+ if (infinite) return;
660
+ event.preventDefault();
661
+ let targetIndex = options.length - 1;
662
+ if (options[targetIndex]?.disabled) targetIndex = findNearestEnabledIndex(targetIndex, -1, options, false);
663
+ const step = targetIndex - scrollRef.current;
664
+ if (step !== 0) scrollByStep(step);
665
+ };
666
+ const handler = {
667
+ ArrowUp: () => handleVerticalNavigation(-1),
668
+ ArrowDown: () => handleVerticalNavigation(1),
669
+ ArrowLeft: () => {
670
+ event.preventDefault();
671
+ navigateToPicker("prev");
672
+ },
673
+ ArrowRight: () => {
674
+ event.preventDefault();
675
+ navigateToPicker("next");
676
+ },
677
+ Home: handleHome,
678
+ End: handleEnd
679
+ }[event.key];
680
+ if (handler) handler();
681
+ else if (event.key.length === 1 && !event.ctrlKey && !event.metaKey && !event.altKey) {
682
+ event.preventDefault();
683
+ handleTypeaheadSearch(event.key);
684
+ }
685
+ }, [
686
+ options,
687
+ infinite,
688
+ navigateToPicker,
689
+ handleTypeaheadSearch,
690
+ scrollByStep
691
+ ]);
692
+ const handleFocus = useCallback(() => {
693
+ setIsFocused(true);
694
+ const pickerIndex = pickerIndexRef.current;
695
+ if (group && pickerIndex !== -1) group.setActiveIndex(pickerIndex);
696
+ }, [group]);
697
+ const handleBlur = useCallback(() => {
698
+ setIsFocused(false);
699
+ resetTypeahead();
700
+ }, [resetTypeahead]);
701
+ useEffect(() => {
702
+ const container = containerRef.current;
703
+ if (!container) return;
704
+ const opts = { passive: false };
705
+ container.addEventListener("touchstart", handleDragStartEvent, opts);
706
+ container.addEventListener("wheel", handleWheelEvent, opts);
707
+ container.addEventListener("mousedown", handleDragStartEvent, opts);
708
+ return () => {
709
+ container.removeEventListener("touchstart", handleDragStartEvent);
710
+ container.removeEventListener("wheel", handleWheelEvent);
711
+ container.removeEventListener("mousedown", handleDragStartEvent);
712
+ if (dragControllerRef.current) dragControllerRef.current.abort();
713
+ if (wheelSnapTimeoutRef.current) clearTimeout(wheelSnapTimeoutRef.current);
714
+ };
715
+ }, [handleDragStartEvent, handleWheelEvent]);
716
+ useEffect(() => {
717
+ selectByValue(value);
718
+ }, [value, selectByValue]);
719
+ const pickerIndex = pickerIndexRef.current;
720
+ const activeIndex = group?.activeIndex ?? -1;
721
+ const tabIndex = group && pickerIndex !== -1 ? activeIndex === pickerIndex ? 0 : -1 : 0;
722
+ const selectedIndex = optionsProp.findIndex((option) => option.value === value);
723
+ const selectedOption = selectedIndex >= 0 ? optionsProp[selectedIndex] : void 0;
724
+ const selectedText = selectedOption ? selectedOption.textValue ?? (typeof selectedOption.label === "string" || typeof selectedOption.label === "number" ? String(selectedOption.label) : String(selectedOption.value)) : void 0;
725
+ return /* @__PURE__ */ jsxs("div", {
726
+ ref: containerRefCallback,
727
+ className: cn(wheelPickerVariants({ size }), "relative flex-1 cursor-default select-none focus:outline-none focus-visible:outline-none [perspective:2000px] [transform-style:preserve-3d] pointer-coarse:after:absolute pointer-coarse:after:size-full pointer-coarse:after:min-h-11 pointer-coarse:after:min-w-11", className),
728
+ tabIndex,
729
+ role: "spinbutton",
730
+ "aria-label": props["aria-label"] ?? "Wheel picker",
731
+ "aria-valuemin": optionsProp.length > 0 ? 0 : void 0,
732
+ "aria-valuemax": optionsProp.length > 0 ? optionsProp.length - 1 : void 0,
733
+ "aria-valuenow": selectedIndex >= 0 ? selectedIndex : void 0,
734
+ "aria-valuetext": selectedText,
735
+ onKeyDown: handleKeyDown,
736
+ onFocus: handleFocus,
737
+ onBlur: handleBlur,
738
+ style: { height: containerHeight },
739
+ "data-slot": "wheel-picker",
740
+ ...props,
741
+ children: [
742
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 top-0 h-1/4 bg-gradient-to-b from-background to-transparent z-10" }),
743
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-1/4 bg-gradient-to-t from-background to-transparent z-10" }),
744
+ /* @__PURE__ */ jsx("ul", {
745
+ "aria-hidden": "true",
746
+ ref: wheelItemsRef,
747
+ className: "absolute top-1/2 left-0 block w-full h-0 m-0 p-0 list-none will-change-transform [transform-style:preserve-3d]",
748
+ "data-slot": "wheel-picker-cylinder",
749
+ children: renderWheelItems
750
+ }),
751
+ /* @__PURE__ */ jsx("div", {
752
+ className: cn("absolute top-1/2 -translate-y-1/2 w-full overflow-hidden border-y border-border/80 bg-accent/40 shadow-xs/5 before:pointer-events-none before:absolute before:inset-0 before:shadow-[0_1px_--theme(--color-black/4%)] dark:before:shadow-[0_-1px_--theme(--color-white/6%)]", isFocused && "border-primary/80 bg-accent/60 ring-2 ring-ring/30 dark:ring-ring/20", classNames?.highlightWrapper),
753
+ style: {
754
+ height: itemHeight,
755
+ lineHeight: `${itemHeight}px`
756
+ },
757
+ "data-slot": "wheel-picker-highlight-window",
758
+ children: /* @__PURE__ */ jsx("ul", {
759
+ "aria-hidden": "true",
760
+ ref: highlightListRef,
761
+ className: "absolute left-0 w-full m-0 p-0 list-none",
762
+ style: { top: infinite ? -itemHeight : void 0 },
763
+ "data-slot": "wheel-picker-highlight-list",
764
+ children: renderHighlightItems
765
+ })
766
+ })
767
+ ]
768
+ });
769
+ }
770
+ //#endregion
771
+ export { WheelPicker, WheelPickerGroup, useWheelPickerGroup, wheelPickerVariants };