@music-vine/cadence 0.1.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 (197) hide show
  1. package/README.md +146 -0
  2. package/dist/components/accordion.d.ts +35 -0
  3. package/dist/components/accordion.d.ts.map +1 -0
  4. package/dist/components/accordion.js +95 -0
  5. package/dist/components/accordion.js.map +7 -0
  6. package/dist/components/badge.d.ts +14 -0
  7. package/dist/components/badge.d.ts.map +1 -0
  8. package/dist/components/badge.js +78 -0
  9. package/dist/components/badge.js.map +7 -0
  10. package/dist/components/breadcrumb.d.ts +20 -0
  11. package/dist/components/breadcrumb.d.ts.map +1 -0
  12. package/dist/components/breadcrumb.js +98 -0
  13. package/dist/components/breadcrumb.js.map +7 -0
  14. package/dist/components/button.d.ts +47 -0
  15. package/dist/components/button.d.ts.map +1 -0
  16. package/dist/components/button.js +295 -0
  17. package/dist/components/button.js.map +7 -0
  18. package/dist/components/card.d.ts +9 -0
  19. package/dist/components/card.d.ts.map +1 -0
  20. package/dist/components/card.js +65 -0
  21. package/dist/components/card.js.map +7 -0
  22. package/dist/components/carousel-dots.d.ts +9 -0
  23. package/dist/components/carousel-dots.d.ts.map +1 -0
  24. package/dist/components/carousel-dots.js +55 -0
  25. package/dist/components/carousel-dots.js.map +7 -0
  26. package/dist/components/carousel.d.ts +33 -0
  27. package/dist/components/carousel.d.ts.map +1 -0
  28. package/dist/components/carousel.js +217 -0
  29. package/dist/components/carousel.js.map +7 -0
  30. package/dist/components/checkbox.d.ts +13 -0
  31. package/dist/components/checkbox.d.ts.map +1 -0
  32. package/dist/components/checkbox.js +57 -0
  33. package/dist/components/checkbox.js.map +7 -0
  34. package/dist/components/context-menu.d.ts +28 -0
  35. package/dist/components/context-menu.d.ts.map +1 -0
  36. package/dist/components/context-menu.js +154 -0
  37. package/dist/components/context-menu.js.map +7 -0
  38. package/dist/components/dialog.d.ts +20 -0
  39. package/dist/components/dialog.d.ts.map +1 -0
  40. package/dist/components/dialog.js +98 -0
  41. package/dist/components/dialog.js.map +7 -0
  42. package/dist/components/drawer.d.ts +26 -0
  43. package/dist/components/drawer.d.ts.map +1 -0
  44. package/dist/components/drawer.js +133 -0
  45. package/dist/components/drawer.js.map +7 -0
  46. package/dist/components/index.d.ts +35 -0
  47. package/dist/components/index.d.ts.map +1 -0
  48. package/dist/components/index.js +277 -0
  49. package/dist/components/index.js.map +7 -0
  50. package/dist/components/input.d.ts +20 -0
  51. package/dist/components/input.d.ts.map +1 -0
  52. package/dist/components/input.js +174 -0
  53. package/dist/components/input.js.map +7 -0
  54. package/dist/components/label.d.ts +6 -0
  55. package/dist/components/label.d.ts.map +1 -0
  56. package/dist/components/label.js +21 -0
  57. package/dist/components/label.js.map +7 -0
  58. package/dist/components/popover.d.ts +8 -0
  59. package/dist/components/popover.d.ts.map +1 -0
  60. package/dist/components/popover.js +38 -0
  61. package/dist/components/popover.js.map +7 -0
  62. package/dist/components/price-tag.d.ts +11 -0
  63. package/dist/components/price-tag.d.ts.map +1 -0
  64. package/dist/components/price-tag.js +31 -0
  65. package/dist/components/price-tag.js.map +7 -0
  66. package/dist/components/radio-group.d.ts +6 -0
  67. package/dist/components/radio-group.d.ts.map +1 -0
  68. package/dist/components/radio-group.js +84 -0
  69. package/dist/components/radio-group.js.map +7 -0
  70. package/dist/components/scroll-area.d.ts +15 -0
  71. package/dist/components/scroll-area.d.ts.map +1 -0
  72. package/dist/components/scroll-area.js +132 -0
  73. package/dist/components/scroll-area.js.map +7 -0
  74. package/dist/components/select.d.ts +59 -0
  75. package/dist/components/select.d.ts.map +1 -0
  76. package/dist/components/select.js +210 -0
  77. package/dist/components/select.js.map +7 -0
  78. package/dist/components/separator.d.ts +5 -0
  79. package/dist/components/separator.d.ts.map +1 -0
  80. package/dist/components/separator.js +25 -0
  81. package/dist/components/separator.js.map +7 -0
  82. package/dist/components/skeleton.d.ts +10 -0
  83. package/dist/components/skeleton.d.ts.map +1 -0
  84. package/dist/components/skeleton.js +29 -0
  85. package/dist/components/skeleton.js.map +7 -0
  86. package/dist/components/slider.d.ts +15 -0
  87. package/dist/components/slider.d.ts.map +1 -0
  88. package/dist/components/slider.js +95 -0
  89. package/dist/components/slider.js.map +7 -0
  90. package/dist/components/stacking-card.d.ts +54 -0
  91. package/dist/components/stacking-card.d.ts.map +1 -0
  92. package/dist/components/stacking-card.js +636 -0
  93. package/dist/components/stacking-card.js.map +7 -0
  94. package/dist/components/tabs.d.ts +8 -0
  95. package/dist/components/tabs.d.ts.map +1 -0
  96. package/dist/components/tabs.js +48 -0
  97. package/dist/components/tabs.js.map +7 -0
  98. package/dist/components/textarea.d.ts +11 -0
  99. package/dist/components/textarea.d.ts.map +1 -0
  100. package/dist/components/textarea.js +43 -0
  101. package/dist/components/textarea.js.map +7 -0
  102. package/dist/components/toast.d.ts +7 -0
  103. package/dist/components/toast.d.ts.map +1 -0
  104. package/dist/components/toast.js +53 -0
  105. package/dist/components/toast.js.map +7 -0
  106. package/dist/components/toggle-button.d.ts +20 -0
  107. package/dist/components/toggle-button.d.ts.map +1 -0
  108. package/dist/components/toggle-button.js +56 -0
  109. package/dist/components/toggle-button.js.map +7 -0
  110. package/dist/components/typography/heading.d.ts +18 -0
  111. package/dist/components/typography/heading.d.ts.map +1 -0
  112. package/dist/components/typography/heading.js +105 -0
  113. package/dist/components/typography/heading.js.map +7 -0
  114. package/dist/components/typography/index.d.ts +5 -0
  115. package/dist/components/typography/index.d.ts.map +1 -0
  116. package/dist/components/typography/index.js +36 -0
  117. package/dist/components/typography/index.js.map +7 -0
  118. package/dist/components/typography/list.d.ts +17 -0
  119. package/dist/components/typography/list.d.ts.map +1 -0
  120. package/dist/components/typography/list.js +73 -0
  121. package/dist/components/typography/list.js.map +7 -0
  122. package/dist/components/typography/prose.d.ts +5 -0
  123. package/dist/components/typography/prose.d.ts.map +1 -0
  124. package/dist/components/typography/prose.js +50 -0
  125. package/dist/components/typography/prose.js.map +7 -0
  126. package/dist/components/typography/text.d.ts +11 -0
  127. package/dist/components/typography/text.d.ts.map +1 -0
  128. package/dist/components/typography/text.js +38 -0
  129. package/dist/components/typography/text.js.map +7 -0
  130. package/dist/icons/custom/boards-indicator.d.ts +7 -0
  131. package/dist/icons/custom/boards-indicator.d.ts.map +1 -0
  132. package/dist/icons/custom/boards-indicator.js +70 -0
  133. package/dist/icons/custom/boards-indicator.js.map +7 -0
  134. package/dist/icons/custom/download-history.d.ts +6 -0
  135. package/dist/icons/custom/download-history.d.ts.map +1 -0
  136. package/dist/icons/custom/download-history.js +19 -0
  137. package/dist/icons/custom/download-history.js.map +7 -0
  138. package/dist/icons/custom/exclamation-mark-in-octagon.d.ts +6 -0
  139. package/dist/icons/custom/exclamation-mark-in-octagon.d.ts.map +1 -0
  140. package/dist/icons/custom/exclamation-mark-in-octagon.js +57 -0
  141. package/dist/icons/custom/exclamation-mark-in-octagon.js.map +7 -0
  142. package/dist/icons/custom/pin.d.ts +6 -0
  143. package/dist/icons/custom/pin.d.ts.map +1 -0
  144. package/dist/icons/custom/pin.js +28 -0
  145. package/dist/icons/custom/pin.js.map +7 -0
  146. package/dist/icons/custom/premium-star.d.ts +10 -0
  147. package/dist/icons/custom/premium-star.d.ts.map +1 -0
  148. package/dist/icons/custom/premium-star.js +191 -0
  149. package/dist/icons/custom/premium-star.js.map +7 -0
  150. package/dist/icons/custom/social/discord.d.ts +6 -0
  151. package/dist/icons/custom/social/discord.d.ts.map +1 -0
  152. package/dist/icons/custom/social/discord.js +27 -0
  153. package/dist/icons/custom/social/discord.js.map +7 -0
  154. package/dist/icons/custom/social/index.d.ts +4 -0
  155. package/dist/icons/custom/social/index.d.ts.map +1 -0
  156. package/dist/icons/custom/social/index.js +4 -0
  157. package/dist/icons/custom/social/index.js.map +7 -0
  158. package/dist/icons/custom/social/tiktok.d.ts +6 -0
  159. package/dist/icons/custom/social/tiktok.d.ts.map +1 -0
  160. package/dist/icons/custom/social/tiktok.js +27 -0
  161. package/dist/icons/custom/social/tiktok.js.map +7 -0
  162. package/dist/icons/custom/social/twitter-x.d.ts +6 -0
  163. package/dist/icons/custom/social/twitter-x.d.ts.map +1 -0
  164. package/dist/icons/custom/social/twitter-x.js +29 -0
  165. package/dist/icons/custom/social/twitter-x.js.map +7 -0
  166. package/dist/icons/custom/tick-in-circle.d.ts +7 -0
  167. package/dist/icons/custom/tick-in-circle.d.ts.map +1 -0
  168. package/dist/icons/custom/tick-in-circle.js +32 -0
  169. package/dist/icons/custom/tick-in-circle.js.map +7 -0
  170. package/dist/icons/custom/tick-small.d.ts +6 -0
  171. package/dist/icons/custom/tick-small.d.ts.map +1 -0
  172. package/dist/icons/custom/tick-small.js +16 -0
  173. package/dist/icons/custom/tick-small.js.map +7 -0
  174. package/dist/icons/custom/tick.d.ts +3 -0
  175. package/dist/icons/custom/tick.d.ts.map +1 -0
  176. package/dist/icons/custom/tick.js +31 -0
  177. package/dist/icons/custom/tick.js.map +7 -0
  178. package/dist/icons/custom/uppbeat-credit.d.ts +4 -0
  179. package/dist/icons/custom/uppbeat-credit.d.ts.map +1 -0
  180. package/dist/icons/custom/uppbeat-credit.js +55 -0
  181. package/dist/icons/custom/uppbeat-credit.js.map +7 -0
  182. package/dist/icons/index.d.ts +20 -0
  183. package/dist/icons/index.d.ts.map +1 -0
  184. package/dist/icons/index.js +15 -0
  185. package/dist/icons/index.js.map +7 -0
  186. package/dist/index.d.ts +19 -0
  187. package/dist/index.d.ts.map +1 -0
  188. package/dist/index.js +6 -0
  189. package/dist/index.js.map +7 -0
  190. package/dist/lib/utils.d.ts +7 -0
  191. package/dist/lib/utils.d.ts.map +1 -0
  192. package/dist/lib/utils.js +9 -0
  193. package/dist/lib/utils.js.map +7 -0
  194. package/dist/styles/index.css +3 -0
  195. package/dist/styles/storybook.css +14 -0
  196. package/package.json +107 -0
  197. package/tailwind.config.ts +299 -0
@@ -0,0 +1,636 @@
1
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
2
+ import { Check, ChevronDown } from "lucide-react";
3
+ import { motion } from "motion/react";
4
+ import * as React from "react";
5
+ import { cn } from "../lib/utils";
6
+ import { Button } from "./button";
7
+ import { DummyCheckbox } from "./checkbox";
8
+ import { Separator } from "./separator";
9
+ import { List, ListItem } from "./typography/list";
10
+ import { Text } from "./typography/text";
11
+ const motionTransition = {
12
+ duration: 0.4,
13
+ type: "spring",
14
+ bounce: 0
15
+ };
16
+ const motionVariantsChevron = {
17
+ collapsed: {
18
+ rotate: 0,
19
+ transition: motionTransition
20
+ },
21
+ expanded: {
22
+ rotate: 180,
23
+ transition: motionTransition
24
+ }
25
+ };
26
+ const useAutoHeight = () => {
27
+ const [height, setHeight] = React.useState("auto");
28
+ const ref = React.useRef(null);
29
+ React.useEffect(() => {
30
+ if (!ref.current) {
31
+ return;
32
+ }
33
+ const resizeObserver = new ResizeObserver((entries) => {
34
+ const entry = entries[0];
35
+ if (entry) {
36
+ setHeight(entry.contentRect.height);
37
+ }
38
+ });
39
+ resizeObserver.observe(ref.current);
40
+ return () => {
41
+ resizeObserver.disconnect();
42
+ };
43
+ }, []);
44
+ const variants = React.useMemo(
45
+ () => ({
46
+ collapsed: {
47
+ height: 0,
48
+ opacity: 0,
49
+ transition: motionTransition
50
+ },
51
+ expanded: {
52
+ height: height === "auto" ? "auto" : height,
53
+ opacity: 1,
54
+ transition: motionTransition
55
+ }
56
+ }),
57
+ [height]
58
+ );
59
+ return { ref, variants };
60
+ };
61
+ const StackingCardGroupContext = React.createContext(null);
62
+ const useStackingCardGroup = () => {
63
+ const context = React.useContext(StackingCardGroupContext);
64
+ return context;
65
+ };
66
+ const StackingCardContext = React.createContext({});
67
+ const useStackingCard = () => {
68
+ const context = React.useContext(StackingCardContext);
69
+ return context;
70
+ };
71
+ function StackingCard({
72
+ className,
73
+ children,
74
+ selectable = false,
75
+ selected = false,
76
+ onSelectedChange,
77
+ variant,
78
+ onClick,
79
+ value,
80
+ onKeyDown,
81
+ initiallyCollapsed = true,
82
+ "aria-label": ariaLabel,
83
+ "aria-labelledby": ariaLabelledby,
84
+ "aria-describedby": ariaDescribedby,
85
+ ref,
86
+ ...props
87
+ }) {
88
+ const [isCollapsed, setIsCollapsed] = React.useState(true);
89
+ const [hasCollapsibleContent, setHasCollapsibleContent] = React.useState(false);
90
+ const [wasSelected, setWasSelected] = React.useState(false);
91
+ const ignoreInitiallyCollapsedAfterRenderRef = React.useRef(false);
92
+ const timeoutRef = React.useRef(null);
93
+ const cardId = React.useId();
94
+ const contentId = `${cardId}-content`;
95
+ const group = useStackingCardGroup();
96
+ const isInGroup = group !== null;
97
+ const isSelected = isInGroup ? group.selectedValue === value : variant === "selected" || selected;
98
+ const justBecameSelected = isSelected && !wasSelected;
99
+ if (justBecameSelected && hasCollapsibleContent) {
100
+ if (isInGroup) {
101
+ group?.onExpandedChange?.(value ?? null);
102
+ } else {
103
+ setIsCollapsed(false);
104
+ }
105
+ }
106
+ if (isSelected !== wasSelected) {
107
+ setWasSelected(isSelected);
108
+ }
109
+ let shouldBeCollapsed = isCollapsed;
110
+ if (initiallyCollapsed && !ignoreInitiallyCollapsedAfterRenderRef.current) {
111
+ shouldBeCollapsed = true;
112
+ } else if (isInGroup) {
113
+ shouldBeCollapsed = group.expandedValue !== value;
114
+ }
115
+ const ignoreInitiallyCollapsedRef = React.useCallback(() => {
116
+ if (initiallyCollapsed && !ignoreInitiallyCollapsedAfterRenderRef.current) {
117
+ ignoreInitiallyCollapsedAfterRenderRef.current = true;
118
+ }
119
+ }, [initiallyCollapsed]);
120
+ const handleSelect = React.useCallback(() => {
121
+ if (selectable) {
122
+ if (isInGroup && value) {
123
+ group?.onValueChange?.(value);
124
+ } else if (!isInGroup && onSelectedChange) {
125
+ onSelectedChange(!selected);
126
+ }
127
+ }
128
+ }, [selectable, isInGroup, value, onSelectedChange, group, selected]);
129
+ const handleToggleCollapse = React.useCallback(() => {
130
+ if (isInGroup) {
131
+ group?.onExpandedChange?.(
132
+ group.expandedValue === value ? null : value ?? null
133
+ );
134
+ } else {
135
+ setIsCollapsed(!isCollapsed);
136
+ }
137
+ }, [isInGroup, group, value, isCollapsed]);
138
+ const handleKeyDown = React.useCallback(
139
+ (e) => {
140
+ ignoreInitiallyCollapsedRef();
141
+ if (selectable && (e.key === "Enter" || e.key === " ")) {
142
+ e.preventDefault();
143
+ handleSelect();
144
+ }
145
+ onKeyDown?.(e);
146
+ },
147
+ [selectable, handleSelect, onKeyDown, ignoreInitiallyCollapsedRef]
148
+ );
149
+ const handleClick = React.useCallback(
150
+ (e) => {
151
+ e.stopPropagation();
152
+ ignoreInitiallyCollapsedRef();
153
+ handleSelect();
154
+ if (isSelected) {
155
+ handleToggleCollapse();
156
+ }
157
+ onClick?.(e);
158
+ },
159
+ [
160
+ handleSelect,
161
+ onClick,
162
+ isSelected,
163
+ handleToggleCollapse,
164
+ ignoreInitiallyCollapsedRef
165
+ ]
166
+ );
167
+ const contextValue = React.useMemo(
168
+ () => ({
169
+ isSelected,
170
+ isCollapsed: shouldBeCollapsed,
171
+ selectable,
172
+ onSelectedChange,
173
+ onToggleCollapse: handleToggleCollapse,
174
+ setHasCollapsibleContent,
175
+ contentId
176
+ }),
177
+ [
178
+ isSelected,
179
+ shouldBeCollapsed,
180
+ selectable,
181
+ onSelectedChange,
182
+ handleToggleCollapse,
183
+ contentId
184
+ ]
185
+ );
186
+ const accessibleLabel = ariaLabel ?? (isInGroup ? `Option ${value}` : "Card");
187
+ const computeRole = () => {
188
+ if (isInGroup) {
189
+ return "radio";
190
+ }
191
+ if (selectable) {
192
+ return "button";
193
+ }
194
+ return void 0;
195
+ };
196
+ const cardRole = computeRole();
197
+ const combinedRef = React.useCallback(
198
+ (element) => {
199
+ if (typeof ref === "function") {
200
+ ref(element);
201
+ } else if (ref) {
202
+ ref.current = element;
203
+ }
204
+ if (isInGroup && value && group?.registerCardRef) {
205
+ group.registerCardRef(value, element);
206
+ }
207
+ },
208
+ [ref, isInGroup, value, group]
209
+ );
210
+ React.useEffect(() => {
211
+ if (initiallyCollapsed && !ignoreInitiallyCollapsedAfterRenderRef.current) {
212
+ if (timeoutRef.current) {
213
+ clearTimeout(timeoutRef.current);
214
+ }
215
+ timeoutRef.current = setTimeout(() => {
216
+ ignoreInitiallyCollapsedAfterRenderRef.current = true;
217
+ }, 1500);
218
+ }
219
+ return () => {
220
+ if (timeoutRef.current) {
221
+ clearTimeout(timeoutRef.current);
222
+ }
223
+ };
224
+ }, [initiallyCollapsed]);
225
+ return /* @__PURE__ */ jsx(StackingCardContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
226
+ "div",
227
+ {
228
+ "aria-checked": isInGroup ? isSelected : void 0,
229
+ "aria-describedby": ariaDescribedby,
230
+ "aria-expanded": hasCollapsibleContent ? !shouldBeCollapsed : void 0,
231
+ "aria-label": accessibleLabel,
232
+ "aria-labelledby": ariaLabelledby,
233
+ "aria-pressed": !isInGroup && selectable ? isSelected : void 0,
234
+ className: cn(
235
+ "relative flex w-full min-w-64 max-w-96 flex-col overflow-hidden border border-solid",
236
+ "rounded-2xl shadow-sm transition-colors",
237
+ selectable && "cursor-pointer",
238
+ isSelected ? "border-gray-950 dark:border-white" : "border-gray-150 dark:border-gray-800",
239
+ "focus-visible:ring-pink-500 focus-visible:ring-offset-2",
240
+ className
241
+ ),
242
+ onClick: handleClick,
243
+ onKeyDown: handleKeyDown,
244
+ ref: combinedRef,
245
+ role: cardRole,
246
+ style: props.style,
247
+ tabIndex: selectable ? 0 : void 0,
248
+ ...props,
249
+ children
250
+ },
251
+ value
252
+ ) });
253
+ }
254
+ function StackingCardHeader({
255
+ className,
256
+ children,
257
+ ref,
258
+ ...props
259
+ }) {
260
+ const { selectable, isSelected } = useStackingCard();
261
+ return /* @__PURE__ */ jsx(
262
+ "div",
263
+ {
264
+ className: cn(
265
+ "flex items-center justify-between gap-2 px-6 pt-4 pb-1",
266
+ isSelected && "bg-gray-100 dark:bg-gray-800",
267
+ className
268
+ ),
269
+ ref,
270
+ ...props,
271
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-1 items-center gap-2", children: [
272
+ selectable && /* @__PURE__ */ jsx(DummyCheckbox, { checked: isSelected, tabIndex: -1, variant: "rounded" }),
273
+ children
274
+ ] })
275
+ }
276
+ );
277
+ }
278
+ function StackingCardTitle({
279
+ className,
280
+ ref,
281
+ ...props
282
+ }) {
283
+ return /* @__PURE__ */ jsx(
284
+ Text,
285
+ {
286
+ className: cn(
287
+ "font-sans font-semibold text-gray-950 text-sm leading-6 dark:text-white",
288
+ className
289
+ ),
290
+ ref,
291
+ ...props
292
+ }
293
+ );
294
+ }
295
+ function StackingCardDescription({
296
+ className,
297
+ ref,
298
+ ...props
299
+ }) {
300
+ return /* @__PURE__ */ jsx(
301
+ Text,
302
+ {
303
+ className: cn("text-gray-700 text-sm dark:text-gray-200", className),
304
+ ref,
305
+ ...props
306
+ }
307
+ );
308
+ }
309
+ const MotionChevron = ({ isCollapsed }) => /* @__PURE__ */ jsx(
310
+ motion.div,
311
+ {
312
+ animate: isCollapsed ? "collapsed" : "expanded",
313
+ className: "flex items-center justify-center",
314
+ initial: "collapsed",
315
+ variants: motionVariantsChevron,
316
+ children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3 w-3 fill-none" })
317
+ }
318
+ );
319
+ function StackingCardContent({
320
+ className,
321
+ children,
322
+ collapsible = false,
323
+ minimal = false,
324
+ description,
325
+ ref,
326
+ ...props
327
+ }) {
328
+ const {
329
+ isCollapsed,
330
+ isSelected,
331
+ onToggleCollapse,
332
+ setHasCollapsibleContent,
333
+ contentId
334
+ } = useStackingCard();
335
+ const { ref: autoHeightRef, variants: autoHeightVariants } = useAutoHeight();
336
+ React.useEffect(() => {
337
+ if (collapsible) {
338
+ setHasCollapsibleContent?.(true);
339
+ }
340
+ return () => {
341
+ setHasCollapsibleContent?.(false);
342
+ };
343
+ }, [collapsible, setHasCollapsibleContent]);
344
+ if (!collapsible) {
345
+ return /* @__PURE__ */ jsx(
346
+ "div",
347
+ {
348
+ className: cn(
349
+ "flex flex-col gap-1.5 px-6 pt-0 pb-4",
350
+ isSelected && "bg-gray-100 dark:bg-gray-800",
351
+ className
352
+ ),
353
+ ref,
354
+ ...props,
355
+ children
356
+ }
357
+ );
358
+ }
359
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
360
+ /* @__PURE__ */ jsxs(
361
+ "div",
362
+ {
363
+ className: cn(
364
+ "flex items-center justify-between gap-2 px-6 pb-4",
365
+ isSelected && "bg-gray-100 dark:bg-gray-800"
366
+ ),
367
+ children: [
368
+ description ? /* @__PURE__ */ jsx("div", { className: "flex-1", children: description }) : /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: "flex-1" }),
369
+ /* @__PURE__ */ jsxs(
370
+ Button,
371
+ {
372
+ "aria-controls": contentId,
373
+ "aria-expanded": !isCollapsed,
374
+ "aria-label": isCollapsed ? "Show details" : "Hide details",
375
+ borderRadius: "full",
376
+ className: cn(isSelected && "bg-white dark:bg-gray-900", "h-3"),
377
+ onClick: (e) => {
378
+ e.stopPropagation();
379
+ onToggleCollapse?.();
380
+ },
381
+ onKeyDown: (e) => {
382
+ if (e.key === "Enter" || e.key === " ") {
383
+ e.stopPropagation();
384
+ }
385
+ },
386
+ size: "xs",
387
+ variant: "light",
388
+ children: [
389
+ /* @__PURE__ */ jsx("span", { className: cn({ "sr-only": minimal }), children: "Details" }),
390
+ /* @__PURE__ */ jsx(MotionChevron, { isCollapsed: isCollapsed ?? false })
391
+ ]
392
+ }
393
+ )
394
+ ]
395
+ }
396
+ ),
397
+ /* @__PURE__ */ jsx(
398
+ motion.div,
399
+ {
400
+ animate: isCollapsed ? "collapsed" : "expanded",
401
+ "aria-hidden": isCollapsed,
402
+ className: "overflow-hidden",
403
+ id: contentId,
404
+ initial: "collapsed",
405
+ variants: autoHeightVariants,
406
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", ref: autoHeightRef, children: [
407
+ /* @__PURE__ */ jsx(
408
+ Separator,
409
+ {
410
+ className: cn(
411
+ "mt-0 mb-0",
412
+ isSelected ? "bg-gray-950 dark:bg-white" : "border-gray-150 dark:border-gray-800"
413
+ )
414
+ }
415
+ ),
416
+ /* @__PURE__ */ jsx(
417
+ "div",
418
+ {
419
+ className: cn("flex flex-col gap-1.5", className),
420
+ ref,
421
+ ...props,
422
+ children
423
+ }
424
+ )
425
+ ] })
426
+ }
427
+ )
428
+ ] });
429
+ }
430
+ function StackingCardList({
431
+ className,
432
+ children,
433
+ ref,
434
+ ...props
435
+ }) {
436
+ return /* @__PURE__ */ jsx(
437
+ List,
438
+ {
439
+ className: cn("list-none px-6 pt-3 pb-5", className),
440
+ ref,
441
+ ...props,
442
+ children
443
+ }
444
+ );
445
+ }
446
+ const StackingCardCheck = React.memo(({ className, ...props }) => {
447
+ const { selectable, isSelected } = useStackingCard();
448
+ return /* @__PURE__ */ jsx(
449
+ Check,
450
+ {
451
+ className: cn(
452
+ "-mt-0.5 size-[14px] fill-none",
453
+ {
454
+ "text-current": !selectable,
455
+ "text-pink-500": isSelected && selectable,
456
+ "text-gray-950 dark:text-white": !isSelected && selectable
457
+ },
458
+ className
459
+ ),
460
+ ...props
461
+ }
462
+ );
463
+ });
464
+ StackingCardCheck.displayName = "StackingCardCheck";
465
+ function StackingCardListItem({
466
+ className,
467
+ children,
468
+ ref,
469
+ ...props
470
+ }) {
471
+ return /* @__PURE__ */ jsx(
472
+ ListItem,
473
+ {
474
+ className: cn(
475
+ "flex font-sans text-gray-700 text-sm first:mt-0 dark:text-gray-200",
476
+ className
477
+ ),
478
+ customBullet: /* @__PURE__ */ jsx(StackingCardCheck, {}),
479
+ ref,
480
+ ...props,
481
+ children
482
+ }
483
+ );
484
+ }
485
+ function StackingCardGroup({
486
+ className,
487
+ children,
488
+ value,
489
+ onValueChange,
490
+ defaultValue,
491
+ "aria-label": ariaLabel,
492
+ "aria-labelledby": ariaLabelledby,
493
+ ref,
494
+ ...props
495
+ }) {
496
+ const [internalSelectedValue, setInternalSelectedValue] = React.useState(
497
+ defaultValue ?? ""
498
+ );
499
+ const [internalExpandedValue, setInternalExpandedValue] = React.useState(defaultValue ?? null);
500
+ const [controlledExpandedValue, setControlledExpandedValue] = React.useState(value ?? null);
501
+ const effectiveSelectedValue = value !== void 0 ? value : internalSelectedValue;
502
+ const effectiveExpandedValue = value !== void 0 ? controlledExpandedValue : internalExpandedValue;
503
+ React.useEffect(() => {
504
+ if (value !== void 0) {
505
+ setControlledExpandedValue(value);
506
+ }
507
+ }, [value]);
508
+ const handleValueChange = React.useCallback(
509
+ (newValue) => {
510
+ if (value === void 0) {
511
+ setInternalSelectedValue(newValue);
512
+ setInternalExpandedValue(newValue);
513
+ } else {
514
+ setControlledExpandedValue(newValue);
515
+ }
516
+ onValueChange?.(newValue);
517
+ },
518
+ [value, onValueChange]
519
+ );
520
+ const handleExpandedChange = React.useCallback(
521
+ (newExpandedValue) => {
522
+ if (value === void 0) {
523
+ setInternalExpandedValue(newExpandedValue);
524
+ } else {
525
+ setControlledExpandedValue(newExpandedValue);
526
+ }
527
+ },
528
+ [value]
529
+ );
530
+ const cardValues = React.useMemo(() => {
531
+ const values = [];
532
+ React.Children.forEach(children, (child) => {
533
+ if (React.isValidElement(child)) {
534
+ const childValue = child.props.value;
535
+ if (typeof childValue === "string") {
536
+ values.push(childValue);
537
+ }
538
+ }
539
+ });
540
+ return values;
541
+ }, [children]);
542
+ const cardRefsRef = React.useRef(/* @__PURE__ */ new Map());
543
+ const registerCardRef = React.useCallback(
544
+ (cardValue, element) => {
545
+ if (element) {
546
+ cardRefsRef.current.set(cardValue, element);
547
+ } else {
548
+ cardRefsRef.current.delete(cardValue);
549
+ }
550
+ },
551
+ []
552
+ );
553
+ const handleKeyDown = React.useCallback(
554
+ (e) => {
555
+ if (cardValues.length === 0) {
556
+ return;
557
+ }
558
+ const currentIndex = cardValues.indexOf(effectiveSelectedValue);
559
+ let nextIndex = currentIndex;
560
+ switch (e.key) {
561
+ case "ArrowDown":
562
+ case "ArrowRight":
563
+ e.preventDefault();
564
+ nextIndex = currentIndex < cardValues.length - 1 ? currentIndex + 1 : 0;
565
+ break;
566
+ case "ArrowUp":
567
+ case "ArrowLeft":
568
+ e.preventDefault();
569
+ nextIndex = currentIndex > 0 ? currentIndex - 1 : cardValues.length - 1;
570
+ break;
571
+ case "Home":
572
+ e.preventDefault();
573
+ nextIndex = 0;
574
+ break;
575
+ case "End":
576
+ e.preventDefault();
577
+ nextIndex = cardValues.length - 1;
578
+ break;
579
+ default:
580
+ return;
581
+ }
582
+ const nextValue = cardValues[nextIndex];
583
+ if (nextValue && nextValue !== effectiveSelectedValue) {
584
+ handleValueChange(nextValue);
585
+ setTimeout(() => {
586
+ const targetCard = cardRefsRef.current.get(nextValue);
587
+ targetCard?.focus();
588
+ }, 0);
589
+ }
590
+ },
591
+ [cardValues, effectiveSelectedValue, handleValueChange]
592
+ );
593
+ const contextValue = React.useMemo(
594
+ () => ({
595
+ selectedValue: effectiveSelectedValue,
596
+ expandedValue: effectiveExpandedValue,
597
+ onValueChange: handleValueChange,
598
+ onExpandedChange: handleExpandedChange,
599
+ registerCardRef
600
+ }),
601
+ [
602
+ effectiveSelectedValue,
603
+ effectiveExpandedValue,
604
+ handleValueChange,
605
+ handleExpandedChange,
606
+ registerCardRef
607
+ ]
608
+ );
609
+ const accessibleLabel = ariaLabel ?? "Select an option";
610
+ return /* @__PURE__ */ jsx(StackingCardGroupContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx(
611
+ "div",
612
+ {
613
+ "aria-label": accessibleLabel,
614
+ "aria-labelledby": ariaLabelledby,
615
+ className: cn("flex flex-col gap-4", className),
616
+ onKeyDown: handleKeyDown,
617
+ ref,
618
+ role: "radiogroup",
619
+ tabIndex: -1,
620
+ ...props,
621
+ children
622
+ }
623
+ ) });
624
+ }
625
+ export {
626
+ StackingCard,
627
+ StackingCardCheck,
628
+ StackingCardContent,
629
+ StackingCardDescription,
630
+ StackingCardGroup,
631
+ StackingCardHeader,
632
+ StackingCardList,
633
+ StackingCardListItem,
634
+ StackingCardTitle
635
+ };
636
+ //# sourceMappingURL=stacking-card.js.map