@spark-ui/components 10.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 (296) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/LICENSE.md +21 -0
  3. package/README.md +19 -0
  4. package/dist/DialogTrigger-5SI4dvpK.d.mts +142 -0
  5. package/dist/DialogTrigger-5SI4dvpK.d.ts +142 -0
  6. package/dist/Input-g0LpWuv0.d.mts +17 -0
  7. package/dist/Input-g0LpWuv0.d.ts +17 -0
  8. package/dist/InputGroup-aoaZxCLk.d.mts +28 -0
  9. package/dist/InputGroup-aoaZxCLk.d.ts +28 -0
  10. package/dist/InputTrailingIcon-BBp7sE6D.d.mts +20 -0
  11. package/dist/InputTrailingIcon-ZZx8PoJy.d.ts +20 -0
  12. package/dist/LabelRequiredIndicator-DRnCzHMU.d.mts +19 -0
  13. package/dist/LabelRequiredIndicator-DRnCzHMU.d.ts +19 -0
  14. package/dist/accordion/index.d.mts +85 -0
  15. package/dist/accordion/index.d.ts +85 -0
  16. package/dist/accordion/index.js +461 -0
  17. package/dist/accordion/index.js.map +1 -0
  18. package/dist/accordion/index.mjs +249 -0
  19. package/dist/accordion/index.mjs.map +1 -0
  20. package/dist/alert-dialog/index.d.mts +119 -0
  21. package/dist/alert-dialog/index.d.ts +119 -0
  22. package/dist/alert-dialog/index.js +1451 -0
  23. package/dist/alert-dialog/index.js.map +1 -0
  24. package/dist/alert-dialog/index.mjs +177 -0
  25. package/dist/alert-dialog/index.mjs.map +1 -0
  26. package/dist/badge/index.d.mts +47 -0
  27. package/dist/badge/index.d.ts +47 -0
  28. package/dist/badge/index.js +122 -0
  29. package/dist/badge/index.js.map +1 -0
  30. package/dist/badge/index.mjs +95 -0
  31. package/dist/badge/index.mjs.map +1 -0
  32. package/dist/breadcrumb/index.d.mts +64 -0
  33. package/dist/breadcrumb/index.d.ts +64 -0
  34. package/dist/breadcrumb/index.js +326 -0
  35. package/dist/breadcrumb/index.js.map +1 -0
  36. package/dist/breadcrumb/index.mjs +149 -0
  37. package/dist/breadcrumb/index.mjs.map +1 -0
  38. package/dist/button/index.d.mts +40 -0
  39. package/dist/button/index.d.ts +40 -0
  40. package/dist/button/index.js +877 -0
  41. package/dist/button/index.js.map +1 -0
  42. package/dist/button/index.mjs +10 -0
  43. package/dist/button/index.mjs.map +1 -0
  44. package/dist/carousel/index.d.mts +253 -0
  45. package/dist/carousel/index.d.ts +253 -0
  46. package/dist/carousel/index.js +1678 -0
  47. package/dist/carousel/index.js.map +1 -0
  48. package/dist/carousel/index.mjs +716 -0
  49. package/dist/carousel/index.mjs.map +1 -0
  50. package/dist/checkbox/index.d.mts +120 -0
  51. package/dist/checkbox/index.d.ts +120 -0
  52. package/dist/checkbox/index.js +873 -0
  53. package/dist/checkbox/index.js.map +1 -0
  54. package/dist/checkbox/index.mjs +349 -0
  55. package/dist/checkbox/index.mjs.map +1 -0
  56. package/dist/chip/index.d.mts +97 -0
  57. package/dist/chip/index.d.ts +97 -0
  58. package/dist/chip/index.js +905 -0
  59. package/dist/chip/index.js.map +1 -0
  60. package/dist/chip/index.mjs +793 -0
  61. package/dist/chip/index.mjs.map +1 -0
  62. package/dist/chunk-2KPFQEAA.mjs +52 -0
  63. package/dist/chunk-2KPFQEAA.mjs.map +1 -0
  64. package/dist/chunk-4F5DOL57.mjs +26 -0
  65. package/dist/chunk-4F5DOL57.mjs.map +1 -0
  66. package/dist/chunk-6JOA37TZ.mjs +742 -0
  67. package/dist/chunk-6JOA37TZ.mjs.map +1 -0
  68. package/dist/chunk-7PMPYEHJ.mjs +379 -0
  69. package/dist/chunk-7PMPYEHJ.mjs.map +1 -0
  70. package/dist/chunk-AESXFMCC.mjs +68 -0
  71. package/dist/chunk-AESXFMCC.mjs.map +1 -0
  72. package/dist/chunk-B42LOFIZ.mjs +308 -0
  73. package/dist/chunk-B42LOFIZ.mjs.map +1 -0
  74. package/dist/chunk-FGOZHKBT.mjs +97 -0
  75. package/dist/chunk-FGOZHKBT.mjs.map +1 -0
  76. package/dist/chunk-HLXYG643.mjs +52 -0
  77. package/dist/chunk-HLXYG643.mjs.map +1 -0
  78. package/dist/chunk-JKNBJHD5.mjs +601 -0
  79. package/dist/chunk-JKNBJHD5.mjs.map +1 -0
  80. package/dist/chunk-K7VP7DH3.mjs +66 -0
  81. package/dist/chunk-K7VP7DH3.mjs.map +1 -0
  82. package/dist/chunk-MUNDKRAE.mjs +80 -0
  83. package/dist/chunk-MUNDKRAE.mjs.map +1 -0
  84. package/dist/chunk-NBZKMCHF.mjs +36 -0
  85. package/dist/chunk-NBZKMCHF.mjs.map +1 -0
  86. package/dist/chunk-PZWESKAR.mjs +314 -0
  87. package/dist/chunk-PZWESKAR.mjs.map +1 -0
  88. package/dist/collapsible/index.d.mts +60 -0
  89. package/dist/collapsible/index.d.ts +60 -0
  90. package/dist/collapsible/index.js +140 -0
  91. package/dist/collapsible/index.js.map +1 -0
  92. package/dist/collapsible/index.mjs +8 -0
  93. package/dist/collapsible/index.mjs.map +1 -0
  94. package/dist/combobox/index.d.mts +285 -0
  95. package/dist/combobox/index.d.ts +285 -0
  96. package/dist/combobox/index.js +2920 -0
  97. package/dist/combobox/index.js.map +1 -0
  98. package/dist/combobox/index.mjs +1267 -0
  99. package/dist/combobox/index.mjs.map +1 -0
  100. package/dist/dialog/index.d.mts +33 -0
  101. package/dist/dialog/index.d.ts +33 -0
  102. package/dist/dialog/index.js +1286 -0
  103. package/dist/dialog/index.js.map +1 -0
  104. package/dist/dialog/index.mjs +13 -0
  105. package/dist/dialog/index.mjs.map +1 -0
  106. package/dist/divider/index.d.mts +61 -0
  107. package/dist/divider/index.d.ts +61 -0
  108. package/dist/divider/index.js +223 -0
  109. package/dist/divider/index.js.map +1 -0
  110. package/dist/divider/index.mjs +196 -0
  111. package/dist/divider/index.mjs.map +1 -0
  112. package/dist/drawer/index.d.mts +148 -0
  113. package/dist/drawer/index.d.ts +148 -0
  114. package/dist/drawer/index.js +1266 -0
  115. package/dist/drawer/index.js.map +1 -0
  116. package/dist/drawer/index.mjs +299 -0
  117. package/dist/drawer/index.mjs.map +1 -0
  118. package/dist/dropdown/index.d.mts +233 -0
  119. package/dist/dropdown/index.d.ts +233 -0
  120. package/dist/dropdown/index.js +2402 -0
  121. package/dist/dropdown/index.js.map +1 -0
  122. package/dist/dropdown/index.mjs +741 -0
  123. package/dist/dropdown/index.mjs.map +1 -0
  124. package/dist/form-field/index.d.mts +176 -0
  125. package/dist/form-field/index.d.ts +176 -0
  126. package/dist/form-field/index.js +540 -0
  127. package/dist/form-field/index.js.map +1 -0
  128. package/dist/form-field/index.mjs +13 -0
  129. package/dist/form-field/index.mjs.map +1 -0
  130. package/dist/icon/index.d.mts +28 -0
  131. package/dist/icon/index.d.ts +28 -0
  132. package/dist/icon/index.js +127 -0
  133. package/dist/icon/index.js.map +1 -0
  134. package/dist/icon/index.mjs +9 -0
  135. package/dist/icon/index.mjs.map +1 -0
  136. package/dist/icon-button/index.d.mts +16 -0
  137. package/dist/icon-button/index.d.ts +16 -0
  138. package/dist/icon-button/index.js +921 -0
  139. package/dist/icon-button/index.js.map +1 -0
  140. package/dist/icon-button/index.mjs +11 -0
  141. package/dist/icon-button/index.mjs.map +1 -0
  142. package/dist/input/index.d.mts +78 -0
  143. package/dist/input/index.d.ts +78 -0
  144. package/dist/input/index.js +1119 -0
  145. package/dist/input/index.js.map +1 -0
  146. package/dist/input/index.mjs +16 -0
  147. package/dist/input/index.mjs.map +1 -0
  148. package/dist/kbd/index.d.mts +9 -0
  149. package/dist/kbd/index.d.ts +9 -0
  150. package/dist/kbd/index.js +46 -0
  151. package/dist/kbd/index.js.map +1 -0
  152. package/dist/kbd/index.mjs +19 -0
  153. package/dist/kbd/index.mjs.map +1 -0
  154. package/dist/label/index.d.mts +11 -0
  155. package/dist/label/index.d.ts +11 -0
  156. package/dist/label/index.js +78 -0
  157. package/dist/label/index.js.map +1 -0
  158. package/dist/label/index.mjs +7 -0
  159. package/dist/label/index.mjs.map +1 -0
  160. package/dist/link-box/index.d.mts +34 -0
  161. package/dist/link-box/index.d.ts +34 -0
  162. package/dist/link-box/index.js +92 -0
  163. package/dist/link-box/index.js.map +1 -0
  164. package/dist/link-box/index.mjs +58 -0
  165. package/dist/link-box/index.mjs.map +1 -0
  166. package/dist/pagination/index.d.mts +143 -0
  167. package/dist/pagination/index.d.ts +143 -0
  168. package/dist/pagination/index.js +1303 -0
  169. package/dist/pagination/index.js.map +1 -0
  170. package/dist/pagination/index.mjs +326 -0
  171. package/dist/pagination/index.mjs.map +1 -0
  172. package/dist/popover/index.d.mts +93 -0
  173. package/dist/popover/index.d.ts +93 -0
  174. package/dist/popover/index.js +1280 -0
  175. package/dist/popover/index.js.map +1 -0
  176. package/dist/popover/index.mjs +13 -0
  177. package/dist/popover/index.mjs.map +1 -0
  178. package/dist/portal/index.d.mts +13 -0
  179. package/dist/portal/index.d.ts +13 -0
  180. package/dist/portal/index.js +37 -0
  181. package/dist/portal/index.js.map +1 -0
  182. package/dist/portal/index.mjs +10 -0
  183. package/dist/portal/index.mjs.map +1 -0
  184. package/dist/progress/index.d.mts +48 -0
  185. package/dist/progress/index.d.ts +48 -0
  186. package/dist/progress/index.js +201 -0
  187. package/dist/progress/index.js.map +1 -0
  188. package/dist/progress/index.mjs +174 -0
  189. package/dist/progress/index.mjs.map +1 -0
  190. package/dist/progress-tracker/index.d.mts +81 -0
  191. package/dist/progress-tracker/index.d.ts +81 -0
  192. package/dist/progress-tracker/index.js +834 -0
  193. package/dist/progress-tracker/index.js.map +1 -0
  194. package/dist/progress-tracker/index.mjs +716 -0
  195. package/dist/progress-tracker/index.mjs.map +1 -0
  196. package/dist/radio-group/index.d.mts +100 -0
  197. package/dist/radio-group/index.d.ts +100 -0
  198. package/dist/radio-group/index.js +824 -0
  199. package/dist/radio-group/index.js.map +1 -0
  200. package/dist/radio-group/index.mjs +297 -0
  201. package/dist/radio-group/index.mjs.map +1 -0
  202. package/dist/rating/index.d.mts +78 -0
  203. package/dist/rating/index.d.ts +78 -0
  204. package/dist/rating/index.js +362 -0
  205. package/dist/rating/index.js.map +1 -0
  206. package/dist/rating/index.mjs +247 -0
  207. package/dist/rating/index.mjs.map +1 -0
  208. package/dist/scrolling-list/index.d.mts +105 -0
  209. package/dist/scrolling-list/index.d.ts +105 -0
  210. package/dist/scrolling-list/index.js +1367 -0
  211. package/dist/scrolling-list/index.js.map +1 -0
  212. package/dist/scrolling-list/index.mjs +407 -0
  213. package/dist/scrolling-list/index.mjs.map +1 -0
  214. package/dist/select/index.d.mts +167 -0
  215. package/dist/select/index.d.ts +167 -0
  216. package/dist/select/index.js +991 -0
  217. package/dist/select/index.js.map +1 -0
  218. package/dist/select/index.mjs +470 -0
  219. package/dist/select/index.mjs.map +1 -0
  220. package/dist/skeleton/index.d.mts +67 -0
  221. package/dist/skeleton/index.d.ts +67 -0
  222. package/dist/skeleton/index.js +206 -0
  223. package/dist/skeleton/index.js.map +1 -0
  224. package/dist/skeleton/index.mjs +147 -0
  225. package/dist/skeleton/index.mjs.map +1 -0
  226. package/dist/slider/index.d.mts +97 -0
  227. package/dist/slider/index.d.ts +97 -0
  228. package/dist/slider/index.js +209 -0
  229. package/dist/slider/index.js.map +1 -0
  230. package/dist/slider/index.mjs +182 -0
  231. package/dist/slider/index.mjs.map +1 -0
  232. package/dist/slot/index.d.mts +17 -0
  233. package/dist/slot/index.d.ts +17 -0
  234. package/dist/slot/index.js +51 -0
  235. package/dist/slot/index.js.map +1 -0
  236. package/dist/slot/index.mjs +11 -0
  237. package/dist/slot/index.mjs.map +1 -0
  238. package/dist/snackbar/index.d.mts +158 -0
  239. package/dist/snackbar/index.d.ts +158 -0
  240. package/dist/snackbar/index.js +1693 -0
  241. package/dist/snackbar/index.js.map +1 -0
  242. package/dist/snackbar/index.mjs +733 -0
  243. package/dist/snackbar/index.mjs.map +1 -0
  244. package/dist/spinner/index.d.mts +21 -0
  245. package/dist/spinner/index.d.ts +21 -0
  246. package/dist/spinner/index.js +139 -0
  247. package/dist/spinner/index.js.map +1 -0
  248. package/dist/spinner/index.mjs +9 -0
  249. package/dist/spinner/index.mjs.map +1 -0
  250. package/dist/stepper/index.d.mts +82 -0
  251. package/dist/stepper/index.d.ts +82 -0
  252. package/dist/stepper/index.js +2178 -0
  253. package/dist/stepper/index.js.map +1 -0
  254. package/dist/stepper/index.mjs +229 -0
  255. package/dist/stepper/index.mjs.map +1 -0
  256. package/dist/switch/index.d.mts +64 -0
  257. package/dist/switch/index.d.ts +64 -0
  258. package/dist/switch/index.js +768 -0
  259. package/dist/switch/index.js.map +1 -0
  260. package/dist/switch/index.mjs +245 -0
  261. package/dist/switch/index.mjs.map +1 -0
  262. package/dist/tabs/index.d.mts +103 -0
  263. package/dist/tabs/index.d.ts +103 -0
  264. package/dist/tabs/index.js +1315 -0
  265. package/dist/tabs/index.js.map +1 -0
  266. package/dist/tabs/index.mjs +391 -0
  267. package/dist/tabs/index.mjs.map +1 -0
  268. package/dist/tag/index.d.mts +27 -0
  269. package/dist/tag/index.d.ts +27 -0
  270. package/dist/tag/index.js +269 -0
  271. package/dist/tag/index.js.map +1 -0
  272. package/dist/tag/index.mjs +237 -0
  273. package/dist/tag/index.mjs.map +1 -0
  274. package/dist/text-link/index.d.mts +20 -0
  275. package/dist/text-link/index.d.ts +20 -0
  276. package/dist/text-link/index.js +99 -0
  277. package/dist/text-link/index.js.map +1 -0
  278. package/dist/text-link/index.mjs +8 -0
  279. package/dist/text-link/index.mjs.map +1 -0
  280. package/dist/textarea/index.d.mts +47 -0
  281. package/dist/textarea/index.d.ts +47 -0
  282. package/dist/textarea/index.js +1180 -0
  283. package/dist/textarea/index.js.map +1 -0
  284. package/dist/textarea/index.mjs +77 -0
  285. package/dist/textarea/index.mjs.map +1 -0
  286. package/dist/visually-hidden/index.d.mts +16 -0
  287. package/dist/visually-hidden/index.d.ts +16 -0
  288. package/dist/visually-hidden/index.js +67 -0
  289. package/dist/visually-hidden/index.js.map +1 -0
  290. package/dist/visually-hidden/index.mjs +8 -0
  291. package/dist/visually-hidden/index.mjs.map +1 -0
  292. package/global.d.ts +12 -0
  293. package/package.json +75 -0
  294. package/tsconfig.build.json +9 -0
  295. package/tsconfig.json +9 -0
  296. package/tsup.config.ts +11 -0
@@ -0,0 +1,716 @@
1
+ import {
2
+ IconButton
3
+ } from "../chunk-2KPFQEAA.mjs";
4
+ import "../chunk-6JOA37TZ.mjs";
5
+ import "../chunk-MUNDKRAE.mjs";
6
+ import {
7
+ Icon
8
+ } from "../chunk-AESXFMCC.mjs";
9
+ import "../chunk-NBZKMCHF.mjs";
10
+ import "../chunk-4F5DOL57.mjs";
11
+
12
+ // src/carousel/Carousel.tsx
13
+ import { cx } from "class-variance-authority";
14
+ import { createContext, useContext } from "react";
15
+
16
+ // src/carousel/useCarousel.ts
17
+ import {
18
+ useCallback as useCallback2,
19
+ useEffect as useEffect3,
20
+ useId,
21
+ useLayoutEffect as useLayoutEffect3,
22
+ useRef as useRef4,
23
+ useState as useState2
24
+ } from "react";
25
+
26
+ // src/carousel/useEvent.ts
27
+ import { useCallback, useLayoutEffect, useRef } from "react";
28
+ function useEvent(callback) {
29
+ const ref = useRef(() => {
30
+ throw new Error("Cannot call an event handler while rendering.");
31
+ });
32
+ useLayoutEffect(() => {
33
+ ref.current = callback;
34
+ });
35
+ return useCallback((...args) => ref.current?.(...args), []);
36
+ }
37
+
38
+ // src/carousel/useIsMounted.ts
39
+ import { useEffect, useRef as useRef2 } from "react";
40
+ var useIsMounted = () => {
41
+ const isMounted = useRef2(false);
42
+ useEffect(() => {
43
+ isMounted.current = true;
44
+ return () => {
45
+ isMounted.current = false;
46
+ };
47
+ }, []);
48
+ return isMounted;
49
+ };
50
+
51
+ // src/carousel/useScrollEnd.ts
52
+ import { useEffect as useEffect2, useRef as useRef3 } from "react";
53
+ function useScrollEnd(scrollRef, callback) {
54
+ const scrollLeft = useRef3(0);
55
+ const safariTimeout = useRef3(null);
56
+ useEffect2(() => {
57
+ const element = scrollRef.current;
58
+ if (!element) return;
59
+ const supportsScrollend = "onscrollend" in window;
60
+ const handleScrollEnd = () => {
61
+ callback();
62
+ };
63
+ const handleSafariScroll = () => {
64
+ if (safariTimeout.current) {
65
+ clearTimeout(safariTimeout.current);
66
+ }
67
+ if (scrollRef.current) {
68
+ scrollLeft.current = scrollRef.current.scrollLeft;
69
+ safariTimeout.current = setTimeout(() => {
70
+ if (scrollRef.current) {
71
+ handleScrollEnd();
72
+ }
73
+ }, 150);
74
+ }
75
+ };
76
+ if (supportsScrollend) {
77
+ element.addEventListener("scrollend", handleScrollEnd);
78
+ } else {
79
+ element.addEventListener("scroll", handleSafariScroll);
80
+ }
81
+ return () => {
82
+ if (safariTimeout.current) {
83
+ clearTimeout(safariTimeout.current);
84
+ }
85
+ if (supportsScrollend) {
86
+ element.removeEventListener("scrollend", handleScrollEnd);
87
+ } else {
88
+ element.removeEventListener("scroll", handleSafariScroll);
89
+ }
90
+ };
91
+ }, [callback, scrollRef]);
92
+ }
93
+
94
+ // src/carousel/useSnapPoints.ts
95
+ import { useMemo, useState } from "react";
96
+
97
+ // src/carousel/useResizeObserver.ts
98
+ import { useLayoutEffect as useLayoutEffect2 } from "react";
99
+ function useResizeObserver(ref, callback) {
100
+ useLayoutEffect2(() => {
101
+ const element = ref.current;
102
+ if (!element) return;
103
+ const observer = new ResizeObserver((entries) => {
104
+ for (const entry of entries) {
105
+ callback(entry.contentRect.width);
106
+ }
107
+ });
108
+ observer.observe(element);
109
+ return () => observer.disconnect();
110
+ }, [ref, callback]);
111
+ }
112
+
113
+ // src/carousel/utils.ts
114
+ function getSnapIndices({
115
+ totalSlides,
116
+ slidesPerMove,
117
+ slidesPerPage
118
+ }) {
119
+ const slideBy = slidesPerMove === "auto" ? slidesPerPage : slidesPerMove;
120
+ const snapPoints = [];
121
+ const lastSnapIndex = Math.floor((totalSlides - slidesPerPage) / slideBy) * slideBy;
122
+ for (let i = 0; i <= lastSnapIndex; i += slideBy) {
123
+ snapPoints.push(i);
124
+ }
125
+ if (snapPoints[snapPoints.length - 1] !== totalSlides - slidesPerPage) {
126
+ snapPoints.push(totalSlides - slidesPerPage);
127
+ }
128
+ return snapPoints;
129
+ }
130
+ function getSlideElements(container) {
131
+ return container ? Array.from(container.querySelectorAll('[data-part="item"]')) : [];
132
+ }
133
+ function isSnapPoint(slideIndex, {
134
+ container,
135
+ slidesPerMove,
136
+ slidesPerPage
137
+ }) {
138
+ return getSnapIndices({
139
+ totalSlides: getSlideElements(container).length,
140
+ slidesPerPage,
141
+ slidesPerMove
142
+ }).includes(slideIndex);
143
+ }
144
+ function getSnapPositions({
145
+ container,
146
+ slidesPerMove,
147
+ slidesPerPage
148
+ }) {
149
+ if (!container) return [];
150
+ return getSlideElements(container).filter((_, index) => {
151
+ return isSnapPoint(index, {
152
+ slidesPerMove,
153
+ slidesPerPage,
154
+ container
155
+ });
156
+ }).map((slide) => slide.offsetLeft);
157
+ }
158
+
159
+ // src/carousel/useSnapPoints.ts
160
+ function useSnapPoints(initialSnapPoints = [], {
161
+ carouselRef,
162
+ slidesPerMove,
163
+ slidesPerPage
164
+ }) {
165
+ const [pageSnapPoints, setPageSnapPoints] = useState(initialSnapPoints);
166
+ const stableSnapPoints = useMemo(() => pageSnapPoints, [pageSnapPoints]);
167
+ useResizeObserver(carouselRef, () => {
168
+ const newSnapPoints = getSnapPositions({
169
+ slidesPerMove,
170
+ slidesPerPage,
171
+ container: carouselRef.current
172
+ });
173
+ if (JSON.stringify(pageSnapPoints) !== JSON.stringify(newSnapPoints)) {
174
+ setPageSnapPoints(newSnapPoints);
175
+ }
176
+ });
177
+ return [stableSnapPoints, setPageSnapPoints];
178
+ }
179
+
180
+ // src/carousel/useCarousel.ts
181
+ var DATA_SCOPE = "carousel";
182
+ var DIRECTION = "ltr";
183
+ var useCarousel = ({
184
+ defaultPage,
185
+ gap = 16,
186
+ snapType = "mandatory",
187
+ snapStop = "always",
188
+ scrollPadding = 0,
189
+ slidesPerPage = 1,
190
+ slidesPerMove = "auto",
191
+ scrollBehavior = "smooth",
192
+ loop = false,
193
+ // state control
194
+ page: controlledPage,
195
+ onPageChange: onPageChangeProp
196
+ }) => {
197
+ const carouselId = useId();
198
+ const [pageState, setPageState] = useState2(defaultPage || controlledPage || 0);
199
+ const carouselRef = useRef4(null);
200
+ const pageIndicatorsRefs = useRef4([]);
201
+ const isMountedRef = useIsMounted();
202
+ const isMounted = isMountedRef.current;
203
+ const onPageChange = useEvent(onPageChangeProp);
204
+ const [pageSnapPoints] = useSnapPoints([], {
205
+ carouselRef,
206
+ slidesPerMove,
207
+ slidesPerPage
208
+ });
209
+ const canScrollPrev = useRef4(loop || pageState > 0);
210
+ const canScrollNext = useRef4(loop || pageState < pageSnapPoints.length - 1);
211
+ canScrollPrev.current = loop || pageState > 0;
212
+ canScrollNext.current = loop || pageState < pageSnapPoints.length - 1;
213
+ const handlePageChange = useCallback2(
214
+ (page) => {
215
+ if (page !== pageState) {
216
+ setPageState(page);
217
+ onPageChange?.(page);
218
+ }
219
+ },
220
+ [onPageChange, pageState]
221
+ );
222
+ const scrollTo = useCallback2(
223
+ (page, behavior) => {
224
+ if (carouselRef.current) {
225
+ carouselRef.current.scrollTo({
226
+ left: pageSnapPoints[page],
227
+ behavior: behavior === "instant" ? "auto" : "smooth"
228
+ });
229
+ handlePageChange(page);
230
+ }
231
+ },
232
+ [handlePageChange, pageSnapPoints]
233
+ );
234
+ const scrollPrev = useCallback2(
235
+ (cb) => {
236
+ if (canScrollPrev) {
237
+ const targetPage = loop && pageState === 0 ? pageSnapPoints.length - 1 : Math.max(pageState - 1, 0);
238
+ scrollTo(targetPage, scrollBehavior);
239
+ cb?.(targetPage);
240
+ }
241
+ },
242
+ [loop, pageSnapPoints, pageState, scrollBehavior, scrollTo]
243
+ );
244
+ const scrollNext = useCallback2(
245
+ (cb) => {
246
+ if (canScrollNext) {
247
+ const targetPage = loop && pageState === pageSnapPoints.length - 1 ? 0 : Math.min(pageState + 1, pageSnapPoints.length - 1);
248
+ scrollTo(targetPage, scrollBehavior);
249
+ cb?.(targetPage);
250
+ }
251
+ },
252
+ [loop, pageSnapPoints, pageState, scrollBehavior, scrollTo]
253
+ );
254
+ useEffect3(() => {
255
+ if (controlledPage != null) {
256
+ scrollTo(controlledPage, scrollBehavior);
257
+ }
258
+ }, [controlledPage, scrollBehavior, scrollTo]);
259
+ useLayoutEffect3(() => {
260
+ if (defaultPage != null && !isMounted && carouselRef.current) {
261
+ const snapPositions = getSnapPositions({
262
+ container: carouselRef.current,
263
+ slidesPerMove,
264
+ slidesPerPage
265
+ });
266
+ carouselRef.current.scrollTo({
267
+ left: snapPositions[defaultPage],
268
+ behavior: "instant"
269
+ });
270
+ }
271
+ }, [defaultPage, isMounted, slidesPerMove, slidesPerPage]);
272
+ const syncPageStateWithScrollPosition = useCallback2(() => {
273
+ if (!carouselRef.current || pageSnapPoints.length === 0) return;
274
+ const { scrollLeft } = carouselRef.current;
275
+ const distances = pageSnapPoints.map((pagePosition) => Math.abs(scrollLeft - pagePosition));
276
+ const pageInViewport = distances.indexOf(Math.min(...distances));
277
+ if (pageInViewport !== -1) {
278
+ handlePageChange(pageInViewport);
279
+ }
280
+ }, [pageSnapPoints, handlePageChange]);
281
+ useScrollEnd(carouselRef, syncPageStateWithScrollPosition);
282
+ const contextValue = {
283
+ ref: carouselRef,
284
+ pageIndicatorsRefs,
285
+ // props
286
+ gap,
287
+ snapType,
288
+ snapStop,
289
+ scrollPadding,
290
+ slidesPerPage,
291
+ slidesPerMove,
292
+ scrollBehavior,
293
+ loop,
294
+ // computed state
295
+ page: pageState,
296
+ pageSnapPoints,
297
+ canScrollNext: canScrollNext.current,
298
+ canScrollPrev: canScrollPrev.current,
299
+ scrollTo,
300
+ scrollPrev,
301
+ scrollNext,
302
+ // anatomy
303
+ getRootProps: () => ({
304
+ id: `carousel::${carouselId}:`,
305
+ role: "region",
306
+ "aria-roledescription": "carousel",
307
+ "data-scope": DATA_SCOPE,
308
+ "data-part": "root",
309
+ "data-orientation": "horizontal",
310
+ dir: DIRECTION,
311
+ style: {
312
+ "--slides-per-page": slidesPerPage,
313
+ "--slide-spacing": `${gap}px`,
314
+ "--slide-item-size": "calc(100% / var(--slides-per-page) - var(--slide-spacing) * (var(--slides-per-page) - 1) / var(--slides-per-page))"
315
+ }
316
+ }),
317
+ getControlProps: () => ({
318
+ "data-scope": DATA_SCOPE,
319
+ "data-part": "control",
320
+ "data-orientation": "horizontal"
321
+ }),
322
+ getPrevTriggerProps: () => ({
323
+ id: `carousel::${carouselId}::prev-trigger`,
324
+ "aria-controls": `carousel::${carouselId}::item-group`,
325
+ "data-scope": DATA_SCOPE,
326
+ "data-part": "prev-trigger",
327
+ "data-orientation": "horizontal",
328
+ type: "button",
329
+ dir: DIRECTION,
330
+ disabled: !canScrollPrev.current,
331
+ onClick: () => scrollPrev()
332
+ }),
333
+ getNextTriggerProps: () => ({
334
+ id: `carousel::${carouselId}::next-trigger`,
335
+ "aria-controls": `carousel::${carouselId}::item-group`,
336
+ "data-scope": DATA_SCOPE,
337
+ "data-part": "next-trigger",
338
+ "data-orientation": "horizontal",
339
+ type: "button",
340
+ dir: DIRECTION,
341
+ disabled: !canScrollNext.current,
342
+ onClick: () => scrollNext()
343
+ }),
344
+ getSlidesContainerProps: () => ({
345
+ id: `carousel::${carouselId}::item-group`,
346
+ "aria-live": slidesPerPage > 1 ? "off" : "polite",
347
+ "data-scope": DATA_SCOPE,
348
+ "data-part": "item-group",
349
+ "data-orientation": "horizontal",
350
+ dir: DIRECTION,
351
+ tabIndex: 0,
352
+ style: {
353
+ display: "grid",
354
+ gap: "var(--slide-spacing)",
355
+ scrollSnapType: `x ${snapType}`,
356
+ gridAutoFlow: "column",
357
+ scrollbarWidth: "none",
358
+ overscrollBehavior: "contain",
359
+ gridAutoColumns: "var(--slide-item-size)",
360
+ overflowX: "auto"
361
+ },
362
+ ref: carouselRef
363
+ }),
364
+ getSlideProps: ({ index }) => {
365
+ const isStopPoint = isSnapPoint(index, {
366
+ container: carouselRef.current,
367
+ slidesPerMove,
368
+ slidesPerPage
369
+ });
370
+ return {
371
+ id: `carousel::${carouselId}::item:${index}`,
372
+ role: "group",
373
+ "aria-roledescription": "slide",
374
+ "data-scope": DATA_SCOPE,
375
+ "data-part": "item",
376
+ "data-index": index,
377
+ "data-orientation": "horizontal",
378
+ dir: DIRECTION,
379
+ style: {
380
+ ...isStopPoint && {
381
+ scrollSnapAlign: "start",
382
+ scrollSnapStop: snapStop
383
+ }
384
+ }
385
+ };
386
+ },
387
+ getIndicatorGroupProps: () => ({
388
+ role: "radiogroup",
389
+ id: `carousel::${carouselId}::indicator-group`,
390
+ "data-scope": DATA_SCOPE,
391
+ "data-part": "indicator-group",
392
+ "data-orientation": "horizontal",
393
+ dir: DIRECTION
394
+ }),
395
+ getIndicatorProps: ({ index }) => {
396
+ const isActivePage = index === pageState;
397
+ return {
398
+ role: "radio",
399
+ id: `carousel::${carouselId}::indicator:${index}`,
400
+ "aria-checked": isActivePage,
401
+ "data-scope": DATA_SCOPE,
402
+ "data-part": "indicator",
403
+ "data-orientation": "horizontal",
404
+ "data-index": index,
405
+ "data-state": isActivePage ? "active" : "inactive",
406
+ tabIndex: isActivePage ? 0 : -1,
407
+ onClick: () => {
408
+ scrollTo(index, scrollBehavior);
409
+ },
410
+ onKeyDown: (event) => {
411
+ const focusActiveIndicator = (page) => {
412
+ pageIndicatorsRefs.current[page]?.focus();
413
+ };
414
+ if (event.key === "ArrowRight" && canScrollNext) {
415
+ scrollNext(focusActiveIndicator);
416
+ } else if (event.key === "ArrowLeft" && canScrollPrev) {
417
+ scrollPrev(focusActiveIndicator);
418
+ }
419
+ }
420
+ };
421
+ }
422
+ };
423
+ return contextValue;
424
+ };
425
+
426
+ // src/carousel/Carousel.tsx
427
+ import { jsx } from "react/jsx-runtime";
428
+ var CarouselContext = createContext(null);
429
+ var Carousel = ({
430
+ className,
431
+ snapType = "mandatory",
432
+ snapStop = "always",
433
+ scrollBehavior = "smooth",
434
+ slidesPerMove = "auto",
435
+ slidesPerPage = 1,
436
+ loop = false,
437
+ children,
438
+ gap = 16,
439
+ defaultPage,
440
+ page,
441
+ onPageChange
442
+ }) => {
443
+ const carouselApi = useCarousel({
444
+ defaultPage,
445
+ slidesPerPage,
446
+ slidesPerMove,
447
+ loop,
448
+ gap,
449
+ scrollBehavior,
450
+ snapStop,
451
+ snapType,
452
+ page,
453
+ onPageChange
454
+ });
455
+ return /* @__PURE__ */ jsx(
456
+ CarouselContext.Provider,
457
+ {
458
+ value: {
459
+ ...carouselApi,
460
+ scrollBehavior
461
+ },
462
+ children: /* @__PURE__ */ jsx(
463
+ "div",
464
+ {
465
+ className: cx("gap-lg relative box-border flex flex-col", className),
466
+ ...carouselApi.getRootProps(),
467
+ children
468
+ }
469
+ )
470
+ }
471
+ );
472
+ };
473
+ Carousel.displayName = "Carousel";
474
+ var useCarouselContext = () => {
475
+ const context = useContext(CarouselContext);
476
+ if (!context) {
477
+ throw Error("useCarouselContext must be used within a Carousel provider");
478
+ }
479
+ return context;
480
+ };
481
+
482
+ // src/carousel/CarouselControls.tsx
483
+ import { jsx as jsx2 } from "react/jsx-runtime";
484
+ var CarouselControls = ({ children }) => {
485
+ const ctx = useCarouselContext();
486
+ return /* @__PURE__ */ jsx2(
487
+ "div",
488
+ {
489
+ className: "default:px-lg pointer-events-none absolute inset-0 flex flex-row items-center justify-between",
490
+ ...ctx.getControlProps(),
491
+ children
492
+ }
493
+ );
494
+ };
495
+ CarouselControls.displayName = "Carousel.Controls";
496
+
497
+ // src/carousel/CarouselNextButton.tsx
498
+ import { ArrowVerticalRight } from "@spark-ui/icons/ArrowVerticalRight";
499
+ import { jsx as jsx3 } from "react/jsx-runtime";
500
+ var CarouselNextButton = ({
501
+ "aria-label": ariaLabel,
502
+ ...buttonProps
503
+ }) => {
504
+ const ctx = useCarouselContext();
505
+ return /* @__PURE__ */ jsx3(
506
+ IconButton,
507
+ {
508
+ ...ctx.getNextTriggerProps(),
509
+ intent: "surface",
510
+ design: "filled",
511
+ className: "pointer-events-auto cursor-pointer shadow-sm disabled:invisible",
512
+ "aria-label": ariaLabel,
513
+ ...buttonProps,
514
+ children: /* @__PURE__ */ jsx3(Icon, { children: /* @__PURE__ */ jsx3(ArrowVerticalRight, {}) })
515
+ }
516
+ );
517
+ };
518
+ CarouselNextButton.displayName = "Carousel.NextButton";
519
+
520
+ // src/carousel/CarouselPageIndicator.tsx
521
+ import { cx as cx2 } from "class-variance-authority";
522
+ import { useEffect as useEffect4, useRef as useRef5 } from "react";
523
+ import { jsx as jsx4 } from "react/jsx-runtime";
524
+ var CarouselPageIndicator = ({
525
+ children,
526
+ unstyled = false,
527
+ index,
528
+ "aria-label": ariaLabel,
529
+ className
530
+ }) => {
531
+ const ctx = useCarouselContext();
532
+ const ref = useRef5(null);
533
+ useEffect4(() => {
534
+ if (ctx.pageIndicatorsRefs.current) {
535
+ ctx.pageIndicatorsRefs.current[index] = ref.current;
536
+ }
537
+ });
538
+ const styles = cx2(
539
+ "group h-sz-16 relative flex",
540
+ "hover:cursor-pointer",
541
+ "w-sz-16 data-[state=active]:w-sz-44"
542
+ );
543
+ const dotsStyles = cx2(
544
+ "before:rounded-sm before:block before:size-md",
545
+ "before:absolute before:left-1/2 before:top-1/2 before:-translate-x-1/2 before:-translate-y-1/2",
546
+ "data-[state=active]:before:w-sz-32 data-[state=active]:before:bg-basic",
547
+ "data-[state=inactive]:before:bg-on-surface/dim-3"
548
+ );
549
+ return /* @__PURE__ */ jsx4(
550
+ "button",
551
+ {
552
+ ref,
553
+ ...ctx.getIndicatorProps({ index }),
554
+ "aria-label": ariaLabel,
555
+ className: cx2(
556
+ {
557
+ [styles]: !unstyled,
558
+ [dotsStyles]: !unstyled
559
+ },
560
+ className
561
+ ),
562
+ children
563
+ },
564
+ index
565
+ );
566
+ };
567
+ CarouselPageIndicator.displayName = "Carousel.PageIndicator";
568
+
569
+ // src/carousel/CarouselPagePicker.tsx
570
+ import { cx as cx3 } from "class-variance-authority";
571
+ import { Fragment, jsx as jsx5 } from "react/jsx-runtime";
572
+ var CarouselPagePicker = ({ children, className }) => {
573
+ const ctx = useCarouselContext();
574
+ return /* @__PURE__ */ jsx5(Fragment, { children: /* @__PURE__ */ jsx5(
575
+ "div",
576
+ {
577
+ ...ctx.getIndicatorGroupProps(),
578
+ className: cx3(
579
+ "default:min-h-sz-16 flex w-full flex-wrap items-center justify-center",
580
+ className
581
+ ),
582
+ children: ctx.pageSnapPoints.length <= 1 ? null : children({
583
+ ...ctx,
584
+ pages: Array.from({ length: ctx.pageSnapPoints.length }, (_, i) => i)
585
+ })
586
+ }
587
+ ) });
588
+ };
589
+ CarouselPagePicker.displayName = "Carousel.PagePicker";
590
+
591
+ // src/carousel/CarouselPrevButton.tsx
592
+ import { ArrowVerticalLeft } from "@spark-ui/icons/ArrowVerticalLeft";
593
+ import { jsx as jsx6 } from "react/jsx-runtime";
594
+ var CarouselPrevButton = ({
595
+ "aria-label": ariaLabel,
596
+ ...buttonProps
597
+ }) => {
598
+ const ctx = useCarouselContext();
599
+ return /* @__PURE__ */ jsx6(
600
+ IconButton,
601
+ {
602
+ ...ctx.getPrevTriggerProps(),
603
+ intent: "surface",
604
+ design: "filled",
605
+ className: "pointer-events-auto cursor-pointer shadow-sm disabled:invisible",
606
+ "aria-label": ariaLabel,
607
+ ...buttonProps,
608
+ children: /* @__PURE__ */ jsx6(Icon, { children: /* @__PURE__ */ jsx6(ArrowVerticalLeft, {}) })
609
+ }
610
+ );
611
+ };
612
+ CarouselPrevButton.displayName = "Carousel.PrevButton";
613
+
614
+ // src/carousel/CarouselSlide.tsx
615
+ import { cx as cx4 } from "class-variance-authority";
616
+ import { useRef as useRef6 } from "react";
617
+
618
+ // src/carousel/useIsVisible.ts
619
+ import { useLayoutEffect as useLayoutEffect4, useState as useState3 } from "react";
620
+ function useIsVisible(elementRef, parentRef) {
621
+ const [isVisible, setIsVisible] = useState3(true);
622
+ useLayoutEffect4(() => {
623
+ const el = elementRef.current;
624
+ const parent = parentRef.current;
625
+ if (!parent || !el) return;
626
+ const observer = new IntersectionObserver(
627
+ ([entry]) => {
628
+ if (entry) {
629
+ setIsVisible(entry.isIntersecting);
630
+ }
631
+ },
632
+ { root: parent, threshold: 0.2 }
633
+ );
634
+ observer.observe(el);
635
+ return () => observer.disconnect();
636
+ });
637
+ return isVisible;
638
+ }
639
+
640
+ // src/carousel/CarouselSlide.tsx
641
+ import { jsx as jsx7 } from "react/jsx-runtime";
642
+ var CarouselSlide = ({
643
+ children,
644
+ index = 0,
645
+ totalSlides,
646
+ className = "",
647
+ ...props
648
+ }) => {
649
+ const itemRef = useRef6(null);
650
+ const ctx = useCarouselContext();
651
+ const isVisible = useIsVisible(itemRef, ctx.ref);
652
+ return /* @__PURE__ */ jsx7(
653
+ "div",
654
+ {
655
+ ref: itemRef,
656
+ ...ctx.getSlideProps({ index, totalSlides }),
657
+ className: cx4("default:bg-surface relative overflow-hidden", className),
658
+ "aria-hidden": !isVisible,
659
+ inert: !isVisible,
660
+ ...props,
661
+ children
662
+ }
663
+ );
664
+ };
665
+ CarouselSlide.displayName = "Carousel.Slide";
666
+
667
+ // src/carousel/CarouselSlides.tsx
668
+ import { cx as cx5 } from "class-variance-authority";
669
+ import { Children, cloneElement, isValidElement } from "react";
670
+ import { jsx as jsx8 } from "react/jsx-runtime";
671
+ var CarouselSlides = ({ children, className = "" }) => {
672
+ const ctx = useCarouselContext();
673
+ const childrenElements = Children.toArray(children);
674
+ return /* @__PURE__ */ jsx8(
675
+ "div",
676
+ {
677
+ ...ctx.getSlidesContainerProps(),
678
+ className: cx5(
679
+ "focus-visible:u-outline relative w-full",
680
+ "[-ms-overflow-style:none] [scrollbar-width:none] [&::-webkit-scrollbar]:hidden",
681
+ className
682
+ ),
683
+ children: childrenElements.map(
684
+ (child, index) => isValidElement(child) ? cloneElement(child, {
685
+ index,
686
+ totalSlides: childrenElements.length
687
+ }) : child
688
+ )
689
+ }
690
+ );
691
+ };
692
+ CarouselSlides.displayName = "Carousel.Slides";
693
+
694
+ // src/carousel/CarouselViewport.tsx
695
+ import { jsx as jsx9 } from "react/jsx-runtime";
696
+ var CarouselViewport = ({ children }) => {
697
+ return /* @__PURE__ */ jsx9("div", { className: "relative flex items-center justify-around p-0", children });
698
+ };
699
+ CarouselViewport.displayName = "Carousel.Viewport";
700
+
701
+ // src/carousel/index.ts
702
+ var Carousel2 = Object.assign(Carousel, {
703
+ Controls: CarouselControls,
704
+ NextButton: CarouselNextButton,
705
+ PrevButton: CarouselPrevButton,
706
+ Slide: CarouselSlide,
707
+ Slides: CarouselSlides,
708
+ Viewport: CarouselViewport,
709
+ PagePicker: CarouselPagePicker,
710
+ PageIndicator: CarouselPageIndicator
711
+ });
712
+ Carousel2.displayName = "Carousel";
713
+ export {
714
+ Carousel2 as Carousel
715
+ };
716
+ //# sourceMappingURL=index.mjs.map