@catalystsoftware/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 (157) hide show
  1. package/README.md +7 -0
  2. package/components/catalyst-ui/buttons/burger.tsx +207 -0
  3. package/components/catalyst-ui/core/data-display/timeline.tsx +210 -0
  4. package/components/catalyst-ui/core/feedback/alert.tsx +491 -0
  5. package/components/catalyst-ui/core/feedback/spinner-1.tsx +65 -0
  6. package/components/catalyst-ui/core/feedback/toast.tsx +1857 -0
  7. package/components/catalyst-ui/core/navigation/menu.tsx +164 -0
  8. package/components/catalyst-ui/forms/toggle-class.tsx +176 -0
  9. package/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +419 -0
  10. package/components/catalyst-ui/hooks/use-counter.tsx +13 -0
  11. package/components/catalyst-ui/hooks/use-event-listener.tsx +23 -0
  12. package/components/catalyst-ui/hooks/use-export-markdown.tsx +47 -0
  13. package/components/catalyst-ui/hooks/use-focus.tsx +17 -0
  14. package/components/catalyst-ui/hooks/use-interval.tsx +23 -0
  15. package/components/catalyst-ui/hooks/use-is-client.tsx +16 -0
  16. package/components/catalyst-ui/hooks/use-media-query.tsx +19 -0
  17. package/components/catalyst-ui/hooks/use-mobile.tsx +19 -0
  18. package/components/catalyst-ui/hooks/use-resize-observer.tsx +81 -0
  19. package/components/catalyst-ui/hooks/use-timeout.tsx +21 -0
  20. package/components/catalyst-ui/hooks/use-timer.tsx +209 -0
  21. package/components/catalyst-ui/hooks/use-toggle.tsx +12 -0
  22. package/components/catalyst-ui/media/image.tsx +13 -0
  23. package/components/catalyst-ui/overlays/dual-sidebar.tsx +4142 -0
  24. package/components/catalyst-ui/overlays/sidebar-original.tsx +726 -0
  25. package/components/catalyst-ui/primitives/accordion.tsx +250 -0
  26. package/components/catalyst-ui/primitives/alert-dialog.tsx +126 -0
  27. package/components/catalyst-ui/primitives/aspect-ratio.tsx +9 -0
  28. package/components/catalyst-ui/primitives/avatar.tsx +296 -0
  29. package/components/catalyst-ui/primitives/badge.tsx +57 -0
  30. package/components/catalyst-ui/primitives/breadcrumb.tsx +101 -0
  31. package/components/catalyst-ui/primitives/button.tsx +265 -0
  32. package/components/catalyst-ui/primitives/calendar-v4.tsx +208 -0
  33. package/components/catalyst-ui/primitives/calendar.tsx +295 -0
  34. package/components/catalyst-ui/primitives/card.tsx +618 -0
  35. package/components/catalyst-ui/primitives/carousel.tsx +238 -0
  36. package/components/catalyst-ui/primitives/chart.tsx +347 -0
  37. package/components/catalyst-ui/primitives/checkbox.tsx +225 -0
  38. package/components/catalyst-ui/primitives/collapsible.tsx +212 -0
  39. package/components/catalyst-ui/primitives/command.tsx +393 -0
  40. package/components/catalyst-ui/primitives/context-menu.tsx +236 -0
  41. package/components/catalyst-ui/primitives/dialog.tsx +471 -0
  42. package/components/catalyst-ui/primitives/drawer.tsx +761 -0
  43. package/components/catalyst-ui/primitives/dropdown-menu.tsx +290 -0
  44. package/components/catalyst-ui/primitives/empty.tsx +104 -0
  45. package/components/catalyst-ui/primitives/field.tsx +244 -0
  46. package/components/catalyst-ui/primitives/hover-card.tsx +124 -0
  47. package/components/catalyst-ui/primitives/input-otp.tsx +76 -0
  48. package/components/catalyst-ui/primitives/input.tsx +64 -0
  49. package/components/catalyst-ui/primitives/item.tsx +196 -0
  50. package/components/catalyst-ui/primitives/kbd.tsx +75 -0
  51. package/components/catalyst-ui/primitives/label.tsx +24 -0
  52. package/components/catalyst-ui/primitives/navigation-menu.tsx +150 -0
  53. package/components/catalyst-ui/primitives/pagination.tsx +198 -0
  54. package/components/catalyst-ui/primitives/popover.tsx +232 -0
  55. package/components/catalyst-ui/primitives/progress.tsx +34 -0
  56. package/components/catalyst-ui/primitives/radio-group.tsx +43 -0
  57. package/components/catalyst-ui/primitives/resizable.tsx +56 -0
  58. package/components/catalyst-ui/primitives/select.tsx +155 -0
  59. package/components/catalyst-ui/primitives/separator.tsx +74 -0
  60. package/components/catalyst-ui/primitives/sheet.tsx +126 -0
  61. package/components/catalyst-ui/primitives/skeleton.tsx +15 -0
  62. package/components/catalyst-ui/primitives/slider.tsx +27 -0
  63. package/components/catalyst-ui/primitives/switch.tsx +187 -0
  64. package/components/catalyst-ui/primitives/tabs.tsx +335 -0
  65. package/components/catalyst-ui/primitives/textarea.tsx +24 -0
  66. package/components/catalyst-ui/primitives/toggle-group.tsx +55 -0
  67. package/components/catalyst-ui/primitives/toggle.tsx +42 -0
  68. package/components/catalyst-ui/primitives/tooltip.tsx +116 -0
  69. package/components/catalyst-ui/utils/basic-auth.tsx +40 -0
  70. package/components/catalyst-ui/utils/context-storage.tsx +19 -0
  71. package/components/catalyst-ui/utils/cors-middleware.tsx +71 -0
  72. package/components/catalyst-ui/utils/deferred-content.tsx +595 -0
  73. package/components/catalyst-ui/utils/honeypot-middleware.tsx +38 -0
  74. package/components/catalyst-ui/utils/incId.tsx +75 -0
  75. package/components/catalyst-ui/utils/jwk-auth.tsx +36 -0
  76. package/components/catalyst-ui/utils/request-id.tsx +14 -0
  77. package/components/catalyst-ui/utils/secure-headers.tsx +37 -0
  78. package/components/catalyst-ui/utils/server-timing.tsx +23 -0
  79. package/components/catalyst-ui/utils/utils.ts +43 -0
  80. package/components/catalyst-ui/utils/with-cookie.tsx +43 -0
  81. package/components/catalyst-ui/x/accordian-x.tsx +428 -0
  82. package/components/catalyst-ui/x/alert-x.tsx +413 -0
  83. package/components/catalyst-ui/x/animated-text-x.tsx +2242 -0
  84. package/components/catalyst-ui/x/avatar-x.tsx +515 -0
  85. package/components/catalyst-ui/x/badge-x.tsx +670 -0
  86. package/components/catalyst-ui/x/button-X.tsx +2857 -0
  87. package/components/catalyst-ui/x/button-group-x.tsx +847 -0
  88. package/components/catalyst-ui/x/calendar-x.tsx +1910 -0
  89. package/components/catalyst-ui/x/card-x.tsx +2597 -0
  90. package/components/catalyst-ui/x/checkbox-x.tsx +656 -0
  91. package/components/catalyst-ui/x/collapsible-x.tsx +1360 -0
  92. package/components/catalyst-ui/x/combobox-x.tsx +911 -0
  93. package/components/catalyst-ui/x/data-table-x.tsx +1753 -0
  94. package/components/catalyst-ui/x/date-picker-x.tsx +648 -0
  95. package/components/catalyst-ui/x/dialog-x.tsx +659 -0
  96. package/components/catalyst-ui/x/dropdown-menu-x.tsx +612 -0
  97. package/components/catalyst-ui/x/hover-card-x.tsx +375 -0
  98. package/components/catalyst-ui/x/icon-x.tsx +840 -0
  99. package/components/catalyst-ui/x/input-mask-x.tsx +981 -0
  100. package/components/catalyst-ui/x/input-otp-x.tsx +659 -0
  101. package/components/catalyst-ui/x/loader-x.tsx +1757 -0
  102. package/components/catalyst-ui/x/pagination-x.tsx +622 -0
  103. package/components/catalyst-ui/x/popover-x.tsx +744 -0
  104. package/components/catalyst-ui/x/radio-group-x.tsx +499 -0
  105. package/components/catalyst-ui/x/select-x.tsx +1127 -0
  106. package/components/catalyst-ui/x/sheet-x.tsx +668 -0
  107. package/components/catalyst-ui/x/switch-x.tsx +681 -0
  108. package/components/catalyst-ui/x/table-x.tsx +574 -0
  109. package/components/catalyst-ui/x/tabs-x.tsx +839 -0
  110. package/components/catalyst-ui/x/textarea-x.tsx +1263 -0
  111. package/components/catalyst-ui/x/tooltip-x.tsx +396 -0
  112. package/components/catalyst-ui/x/tracker-x.tsx +560 -0
  113. package/data/bg-data.tsx +901 -0
  114. package/data/buttons-data.tsx +2327 -0
  115. package/data/charts-data.tsx +102 -0
  116. package/data/chat-data.tsx +83 -0
  117. package/data/code-data.tsx +1040 -0
  118. package/data/comboboxes-data.tsx +1843 -0
  119. package/data/command-data.tsx +1381 -0
  120. package/data/core-data.tsx +15953 -0
  121. package/data/crm-data.tsx +47 -0
  122. package/data/data.tsx +159 -0
  123. package/data/date-and-time-data.tsx +554 -0
  124. package/data/dependencies.tsx +7 -0
  125. package/data/ecommerce-data.tsx +1387 -0
  126. package/data/forms-data.tsx +7890 -0
  127. package/data/hooks-data.tsx +5487 -0
  128. package/data/index.ts +34 -0
  129. package/data/inputs-data.tsx +557 -0
  130. package/data/interactive-data.tsx +5394 -0
  131. package/data/lofi-data.tsx +18295 -0
  132. package/data/marketing-data.tsx +2546 -0
  133. package/data/media-data.tsx +1510 -0
  134. package/data/motion-data.tsx +5801 -0
  135. package/data/overlay-data.tsx +4136 -0
  136. package/data/pdf-data.tsx +124 -0
  137. package/data/pos-data.tsx +213 -0
  138. package/data/postcss.config.js +6 -0
  139. package/data/primitive-data.tsx +5170 -0
  140. package/data/prompt-data.tsx +1226 -0
  141. package/data/requiredLibs.ts +4 -0
  142. package/data/sandbox-data.tsx +1 -0
  143. package/data/sidebars-data.tsx +5421 -0
  144. package/data/stacks-data.tsx +32 -0
  145. package/data/table-data.tsx +706 -0
  146. package/data/tailwind.config.js +3830 -0
  147. package/data/tailwind.config.ngin.js +3830 -0
  148. package/data/tailwind.css +431 -0
  149. package/data/tools-data.tsx +6910 -0
  150. package/data/typography-data.tsx +2050 -0
  151. package/data/utils-data.tsx +6500 -0
  152. package/data/x-data.tsx +1171 -0
  153. package/dist/index.d.ts +3 -0
  154. package/dist/index.d.ts.map +1 -0
  155. package/dist/index.js +30245 -0
  156. package/dist/index.js.map +362 -0
  157. package/package.json +50 -0
@@ -0,0 +1,656 @@
1
+ import {Field, Checkbox, FieldLabel, FieldDescription, Badge,MotionCheckbox, } from "~/components/catalyst-ui"
2
+ import { useId } from 'react'
3
+ import { HeartIcon, CircleCheckIcon, } from 'lucide-react'
4
+
5
+
6
+ /**
7
+ * ★ ━━━━ ☆ ━━━━ CheckboxX ━━━━ ☆ ━━━━ ★
8
+ * type CheckboxXType =
9
+ * | 'default' | 'Indeterminate' | 'TodoList' | 'Badge' | 'CustomIcons' // Basic & Interactive
10
+ * | 'FilledIcon' | 'Card' | 'Tree' | 'Form' // Visual & Layout
11
+ * | 'Animated' | 'AnimatedTodoList' | 'Confetti' // Animated
12
+ *
13
+ * ★ ━━━━ ☆ ━━━━ USAGE ━━━━ ☆ ━━━━ ★
14
+ *
15
+ * ★ ━━━━━━━━━ Default Checkbox ━━━━━━━━━ ★
16
+ * ```jsx
17
+ * <CheckboxX
18
+ * checked={checked}
19
+ * setChecked={setChecked}
20
+ * label="Accept terms"
21
+ * description="Click to agree"
22
+ * />
23
+ * ```
24
+ *
25
+ * ★ ━━━━━━━━━ Indeterminate Checkbox ━━━━━━━━━ ★
26
+ * ```jsx
27
+ * <CheckboxX
28
+ * checkbox="Indeterminate"
29
+ * checked={checked}
30
+ * setChecked={setChecked}
31
+ * label="Select all"
32
+ * description="Check/uncheck all items"
33
+ * />
34
+ * ```
35
+ *
36
+ * ★ ━━━━━━━━━ Todo List Checkbox ━━━━━━━━━ ★
37
+ * ```jsx
38
+ * <CheckboxX
39
+ * checkbox="TodoList"
40
+ * items={todoItems}
41
+ * setItems={setTodoItems}
42
+ * />
43
+ *
44
+ * // Todo items array structure:
45
+ * const [todoItems, setTodoItems] = useState([
46
+ * { label: 'Buy groceries', description: 'Milk, eggs, bread', checked: false },
47
+ * { label: 'Call mom', description: 'Wish happy birthday', checked: false },
48
+ * { label: 'Finish report', description: 'Due by Friday', checked: true }
49
+ * ]);
50
+ * ```
51
+ *
52
+ * ★ ━━━━━━━━━ Badge Checkbox Group ━━━━━━━━━ ★
53
+ * ```jsx
54
+ * <CheckboxX
55
+ * checkbox="Badge"
56
+ * orientation="horizontal"
57
+ * items={badgeItems}
58
+ * />
59
+ *
60
+ * // Badge items array structure:
61
+ * const badgeItems = [
62
+ * { label: 'React', checked: false },
63
+ * { label: 'TypeScript', checked: true },
64
+ * { label: 'Tailwind', checked: false }
65
+ * ];
66
+ * ```
67
+ *
68
+ * ★ ━━━━━━━━━ Custom Icons Checkbox ━━━━━━━━━ ★
69
+ * ```jsx
70
+ * import { HeartIcon, StarIcon } from 'lucide-react';
71
+ *
72
+ * <CheckboxX
73
+ * checkbox="CustomIcons"
74
+ * checked={checked}
75
+ * setChecked={setChecked}
76
+ * uncheckedIcon={HeartIcon}
77
+ * checkedIcon={StarIcon}
78
+ * label="Favorite"
79
+ * description="Add to favorites"
80
+ * ciCN="stroke-1 text-gray-400"
81
+ * uiCN="fill-yellow-400 stroke-yellow-400 stroke-1"
82
+ * />
83
+ * ```
84
+ *
85
+ * ★ ━━━━━━━━━ Filled Icon Checkbox ━━━━━━━━━ ★
86
+ * ```jsx
87
+ * <CheckboxX
88
+ * checkbox="FilledIcon"
89
+ * checked={checked}
90
+ * setChecked={setChecked}
91
+ * color="bg-blue-500 data-[state=checked]:bg-blue-500"
92
+ * label="Confirm"
93
+ * description="Circle check icon"
94
+ * />
95
+ * ```
96
+ *
97
+ * ★ ━━━━━━━━━ Card Style Checkbox ━━━━━━━━━ ★
98
+ * ```jsx
99
+ * <CheckboxX
100
+ * checkbox="Card"
101
+ * checked={checked}
102
+ * setChecked={setChecked}
103
+ * label="Premium Plan"
104
+ * description="Includes advanced features"
105
+ * />
106
+ * ```
107
+ *
108
+ * ★ ━━━━━━━━━ Tree Structure Checkbox ━━━━━━━━━ ★
109
+ * ```jsx
110
+ * <CheckboxX
111
+ * checkbox="Tree"
112
+ * checked={checked}
113
+ * setChecked={setChecked}
114
+ * selected={selectedItems}
115
+ * setSelected={setSelectedItems}
116
+ * items={['Child 1', 'Child 2', 'Child 3']}
117
+ * />
118
+ * ```
119
+ *
120
+ * ★ ━━━━━━━━━ Form Checkbox ━━━━━━━━━ ★
121
+ * ```jsx
122
+ * <CheckboxX
123
+ * checkbox="Form"
124
+ * label="Accept terms and conditions"
125
+ * description="By clicking this checkbox, you agree to the terms and conditions."
126
+ * />
127
+ * ```
128
+ *
129
+ * ★ ━━━━━━━━━ Animated Checkbox ━━━━━━━━━ ★
130
+ * ```jsx
131
+ * <CheckboxX
132
+ * checkbox="Animated"
133
+ * checked={checked}
134
+ * setChecked={setChecked}
135
+ * label="Animated toggle"
136
+ * description="Smooth animation on change"
137
+ * />
138
+ * ```
139
+ *
140
+ * ★ ━━━━━━━━━ Animated Todo List ━━━━━━━━━ ★
141
+ * ```jsx
142
+ * <CheckboxX
143
+ * checkbox="AnimatedTodoList"
144
+ * items={todoItems}
145
+ * setItems={setTodoItems}
146
+ * />
147
+ * ```
148
+ *
149
+ * ★ ━━━━━━━━━ Confetti Checkbox ━━━━━━━━━ ★
150
+ * ```jsx
151
+ * <CheckboxX
152
+ * checkbox="Confetti"
153
+ * checked={checked}
154
+ * setChecked={setChecked}
155
+ * label="Celebration!"
156
+ * description="Check to celebrate"
157
+ * />
158
+ * ```
159
+ *
160
+ * ★ ━━━━━━━━━ Props ━━━━━━━━━ ★
161
+ *
162
+ * Common Props (available for most variants):
163
+ * - `checkbox`: CheckboxXType - Specifies which variant to use
164
+ * - `checked`: boolean | 'indeterminate' - Checked state
165
+ * - `setChecked`: (checked: boolean | 'indeterminate') => void - State change callback
166
+ * - `label`: string - Label text
167
+ * - `description`: string - Description text
168
+ * - `side`: 'left' | 'right' - Label position relative to checkbox
169
+ * - `className`: string - Additional CSS classes
170
+ *
171
+ * Variant-Specific Props:
172
+ *
173
+ * TodoList:
174
+ * - `items`: Array<{ label?: string, description?: string, checked: boolean, className?: string }>
175
+ * - `setItems`: (items: TodoItem[]) => void
176
+ *
177
+ * Badge:
178
+ * - `orientation`: string - Layout orientation
179
+ * - `items`: Array<{ label?: string, description?: string, checked: boolean, className?: string }>
180
+ *
181
+ * CustomIcons:
182
+ * - `uncheckedIcon`: IconComponent - Icon to show when unchecked
183
+ * - `checkedIcon`: IconComponent - Icon to show when checked
184
+ * - `ciCN`: string - CSS classes for checked icon
185
+ * - `uiCN`: string - CSS classes for unchecked icon
186
+ *
187
+ * FilledIcon:
188
+ * - `color`: string - CSS classes for background color
189
+ *
190
+ * Tree:
191
+ * - `selected`: string[] - Array of selected child labels
192
+ * - `setSelected`: (selected: string[]) => void
193
+ * - `items`: string[] - Array of child item labels
194
+ *
195
+ * AnimatedTodoList:
196
+ * - `items`: Array<{ label?: string, description?: string, checked: boolean, className?: string }>
197
+ * - `setItems`: (items: TodoItem[]) => void
198
+ *
199
+ * Confetti:
200
+ * - Uses same props as DefaultCheckbox with confetti animation
201
+ *
202
+ * ★ ━━━━━━━━━ Import ━━━━━━━━━ ★
203
+ * ```javascript
204
+ * import { CheckboxX } from "./CheckboxX";
205
+ *
206
+ * // Lucide icons (for CustomIcons variant)
207
+ * import { HeartIcon, StarIcon, CircleCheckIcon } from 'lucide-react';
208
+ * ```
209
+ *
210
+ * ★ ━━━━━━━━━ State Management Examples ━━━━━━━━━ ★
211
+ * ```typescript
212
+ * // Single checkbox state
213
+ * const [checked, setChecked] = useState(false);
214
+ *
215
+ * // Todo list state
216
+ * const [todoItems, setTodoItems] = useState([
217
+ * { label: 'Task 1', description: 'Description', checked: false },
218
+ * { label: 'Task 2', description: 'Description', checked: true }
219
+ * ]);
220
+ *
221
+ * // Tree selection state
222
+ * const [checked, setChecked] = useState<'indeterminate' | boolean>(false);
223
+ * const [selected, setSelected] = useState<string[]>(['Child 1', 'Child 2']);
224
+ * const items = ['Child 1', 'Child 2', 'Child 3'];
225
+ * ```
226
+ *
227
+ */
228
+
229
+ export function CheckboxX({ checkbox = 'default', children, ...props }: any) {
230
+ switch (checkbox) {
231
+ case 'Indeterminate':
232
+ return <Indeterminate {...props} />
233
+ case 'TodoList':
234
+ return <TodoList {...props} />
235
+ case 'Badge':
236
+ return <BadgeCheckbox {...props} />
237
+ case 'CustomIcons':
238
+ return <CustomIcons {...props} />
239
+ case 'FilledIcon':
240
+ return <FilledIcon {...props} />
241
+ case 'Card':
242
+ return <Card {...props} />
243
+ case 'Tree':
244
+ return <Tree {...props} />
245
+ case 'Form':
246
+ return <Form {...props} />
247
+ case 'Animated':
248
+ return <Animated {...props} />
249
+ case 'AnimatedTodoList':
250
+ return <AnimatedTodoList {...props} />
251
+ case 'Confetti':
252
+ return <Confetti {...props} />
253
+ default:
254
+ return <DefaultCheckbox {...props} />;
255
+ }
256
+ }
257
+
258
+ const DefaultCheckbox = ({ checked, setChecked, label, description, className, side = "right", ...props }) => {
259
+ const id = useId()
260
+
261
+ return (
262
+ <Field className="flex items-start gap-2">
263
+ {side === 'left' && (
264
+ <div className="flex-1">
265
+ {label && (<FieldLabel>{label}</FieldLabel>)}
266
+ {description && (<FieldDescription>{description}</FieldDescription>)}
267
+ </div>
268
+ )}
269
+ <Checkbox
270
+ id={id}
271
+ checked={checked}
272
+ onCheckedChange={setChecked}
273
+ {...props}
274
+ className={className}
275
+ />
276
+ {side === 'right' && (
277
+ <div className="flex-1">
278
+ {label && (<FieldLabel>{label}</FieldLabel>)}
279
+ {description && (<FieldDescription>{description}</FieldDescription>)}
280
+ </div>
281
+ )}
282
+ </Field>
283
+ )
284
+ }
285
+ const Indeterminate = ({ checked = 'indeterminate', setChecked, label, description, className, side = "right", ...props }) => {
286
+ const id = useId()
287
+ return (
288
+ <Field className="flex items-start gap-2">
289
+ {side === 'left' && (
290
+ <div className="flex-1">
291
+ {label && (<FieldLabel>{label}</FieldLabel>)}
292
+ {description && (<FieldDescription>{description}</FieldDescription>)}
293
+ </div>
294
+ )}
295
+ <Checkbox
296
+ id={id}
297
+ checked={checked}
298
+ onCheckedChange={setChecked}
299
+ {...props}
300
+ className={className}
301
+ />
302
+ {side === 'right' && (
303
+ <div className="flex-1">
304
+ {label && (<FieldLabel>{label}</FieldLabel>)}
305
+ {description && (<FieldDescription>{description}</FieldDescription>)}
306
+ </div>
307
+ )}
308
+ </Field>
309
+ )
310
+ }
311
+ const items = [
312
+ { label: '', description: '', checked: false }
313
+ ]
314
+ const TodoList = ({ items, setItems }) => {
315
+ const handleCheckedChange = (index: number, checked: boolean) => {
316
+ const newItems = [...items]
317
+ newItems[index].checked = checked
318
+ setItems(newItems)
319
+ }
320
+ const id = useId()
321
+
322
+ return (
323
+ <div className='flex flex-col gap-2'>
324
+ {items.map((i, index) => {
325
+ return (
326
+ <Field className="flex items-start gap-2" key={index}>
327
+ <Checkbox
328
+ id={id}
329
+ checked={i.checked}
330
+ onCheckedChange={(checked) => handleCheckedChange(index, checked)}
331
+ className={i.className}
332
+ />
333
+ <div className="flex-1">
334
+ {i.label && (<FieldLabel htmlFor={id} className='after:bg-primary peer-data-[state=checked]:text-primary relative after:absolute after:top-1/2 after:left-0 after:h-px after:w-full after:origin-bottom after:scale-x-0 after:transition-transform after:duration-500 after:ease-in-out peer-data-[state=checked]:after:origin-bottom peer-data-[state=checked]:after:scale-x-100'>{i.label}</FieldLabel>)}
335
+ {i.description && (<FieldDescription htmlFor={id} className='after:bg-primary peer-data-[state=checked]:text-primary relative after:absolute after:top-1/2 after:left-0 after:h-px after:w-full after:origin-bottom after:scale-x-0 after:transition-transform after:duration-500 after:ease-in-out peer-data-[state=checked]:after:origin-bottom peer-data-[state=checked]:after:scale-x-100'>{i.description}</FieldDescription>)}
336
+ </div>
337
+ </Field>
338
+ )
339
+ })}
340
+ </div>
341
+ )
342
+ }
343
+ const BadgeCheckbox = ({ orientation, items }) => {
344
+ const handleCheckedChange = (index: number, checked: boolean) => {
345
+ const newItems = [...items]
346
+ newItems[index].checked = checked
347
+ setItems(newItems)
348
+ }
349
+ return (
350
+ <CheckboxGroup varian={orientation}>
351
+ {items.map((i, index) => {
352
+ return (
353
+ <Badge key={label} variant='secondary' className='relative gap-2 rounded-sm px-3 py-1.5'>
354
+ <Field className="flex items-start gap-2" key={index}>
355
+ <Checkbox
356
+ checked={i.checked}
357
+ onCheckedChange={(checked) => handleCheckedChange(index, checked)}
358
+ className={i.className}
359
+ />
360
+ <div className="flex-1">
361
+ {i.label && (<FieldLabel>{i.label}</FieldLabel>)}
362
+ {i.description && (<FieldDescription>{i.description}</FieldDescription>)}
363
+ </div>
364
+ </Field>
365
+ </Badge>
366
+ )
367
+ })}
368
+ </CheckboxGroup>
369
+ )
370
+ }
371
+ const CustomIcons = ({ checkedIcon, ciCN = 'stroke-1', uncheckedIcon, uiCN = 'fill-destructive stroke-destructive stroke-1', checked, setChecked, label, description, className, side = "right", ...props }) => {
372
+ const Icon1 = uncheckedIcon ? uncheckedIcon : HeartIcon
373
+ const Icon2 = checkedIcon ? checkedIcon : HeartIcon
374
+ return (
375
+ <Field className="flex items-start gap-2">
376
+ {side === 'left' && (
377
+ <div className="flex-1">
378
+ {label && (<FieldLabel>{label}</FieldLabel>)}
379
+ {description && (<FieldDescription>{description}</FieldDescription>)}
380
+ </div>
381
+ )}
382
+ <Checkbox
383
+ id={id}
384
+ checked={checked}
385
+ onCheckedChange={setChecked}
386
+ {...props}
387
+ className={className}
388
+ >
389
+ <CheckboxIndicator>
390
+ <span className='group-data-[state=checked]:hidden'>
391
+ <Icon1 className={ciCN} />
392
+ </span>
393
+ <span className='group-data-[state=unchecked]:hidden'>
394
+ <Icon2 className={uiCN} />
395
+ </span>
396
+ </CheckboxIndicator>
397
+ </Checkbox>
398
+ {side === 'right' && (
399
+ <div className="flex-1">
400
+ {label && (<FieldLabel>{label}</FieldLabel>)}
401
+ {description && (<FieldDescription>{description}</FieldDescription>)}
402
+ </div>
403
+ )}
404
+ </Field>
405
+
406
+ )
407
+ }
408
+ const FilledIcon = ({ color, checked, setChecked, label, description, className, side = "right", ...props }) => {
409
+ return (
410
+ <Field className="flex items-start gap-2">
411
+ {side === 'left' && (
412
+ <div className="flex-1">
413
+ {label && (<FieldLabel>{label}</FieldLabel>)}
414
+ {description && (<FieldDescription>{description}</FieldDescription>)}
415
+ </div>
416
+ )}
417
+ <CheckboxPrimitive.Root
418
+ data-slot='checkbox'
419
+ checked={checked}
420
+ onCheckedChange={setChecked}
421
+ {...props}
422
+ className={cn('peer bg-destructive data-[state=checked]:text-destructive focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 w-7 h-7 shrink-0 rounded-full shadow-xs transition-shadow outline-none focus-visible:ring-[3px]', color, className)}
423
+ >
424
+ <CheckboxPrimitive.Indicator data-slot='checkbox-indicator' className='flex items-center justify-center text-current transition-none' >
425
+ <CircleCheckIcon className='size-5.5 fill-white stroke-current' />
426
+ </CheckboxPrimitive.Indicator>
427
+ </CheckboxPrimitive.Root>
428
+ {side === 'right' && (
429
+ <div className="flex-1">
430
+ {label && (<FieldLabel>{label}</FieldLabel>)}
431
+ {description && (<FieldDescription>{description}</FieldDescription>)}
432
+ </div>
433
+ )}
434
+ </Field>
435
+ )
436
+ }
437
+ const Card = ({ checked, setChecked, label, description, className, side = "right", ...props }) => {
438
+ return (
439
+ <Field className="flex items-start gap-2 hover:bg-accent/50 flex items-start gap-2 rounded-lg border p-3 has-[[aria-checked=true]]:border-blue-600 has-[[aria-checked=true]]:bg-blue-50 dark:has-[[aria-checked=true]]:border-blue-900 dark:has-[[aria-checked=true]]:bg-blue-950">
440
+ {side === 'left' && (
441
+ <div className="flex-1">
442
+ {label && (<FieldLabel>{label}</FieldLabel>)}
443
+ {description && (<FieldDescription>{description}</FieldDescription>)}
444
+ </div>
445
+ )}
446
+ <Checkbox
447
+ id={id}
448
+ checked={checked}
449
+ onCheckedChange={setChecked}
450
+ {...props}
451
+ className={cn('data-[state=checked]:border-blue-600 data-[state=checked]:bg-blue-600 data-[state=checked]:text-white dark:data-[state=checked]:border-blue-700 dark:data-[state=checked]:bg-blue-700', className)}
452
+ />
453
+ {side === 'right' && (
454
+ <div className="grid gap-1.5 font-normal">
455
+ {label && (<FieldLabel className='text-sm leading-none font-medium'>{label}</FieldLabel>)}
456
+ {description && (<FieldDescription className='text-muted-foreground text-sm'>{description}</FieldDescription>)}
457
+ </div>
458
+ )}
459
+ </Field>
460
+ )
461
+ }
462
+ const Tree = ({ checked = 'indeterminate', setChecked, selected = ['Child 1', 'Child 2'], setSelected, label, description, className, side = "right", ...props }) => {
463
+ useEffect(() => {
464
+ if (selected.length === items.length) {
465
+ setChecked(true)
466
+ } else if (selected.length > 0) {
467
+ setChecked('indeterminate')
468
+ } else {
469
+ setChecked(false)
470
+ }
471
+ }, [selected])
472
+
473
+ const handleCheckedChange = (checked: CheckboxPrimitive.CheckedState) => {
474
+ setChecked(checked)
475
+
476
+ if (checked === true) {
477
+ setSelected([...items])
478
+ } else if (checked === false) {
479
+ setSelected([])
480
+ }
481
+ }
482
+
483
+ return (
484
+ <div className='flex flex-col gap-4'>
485
+ <div className='flex items-center gap-2'>
486
+ <Checkbox id='parent' checked={checked} onCheckedChange={handleCheckedChange} />
487
+ <Label htmlFor='parent'>Parent</Label>
488
+ </div>
489
+ <div className='flex flex-col gap-2 pl-6'>
490
+ {items.map(label => (
491
+ <div key={label} className='flex items-center gap-2'>
492
+ <Checkbox
493
+ id={label}
494
+ checked={selected.includes(label)}
495
+ onCheckedChange={checked =>
496
+ setSelected(checked ? [...selected, label] : selected.filter(item => item !== label))
497
+ }
498
+ />
499
+ <Label htmlFor={label}>{label}</Label>
500
+ </div>
501
+ ))}
502
+ </div>
503
+ </div>
504
+ )
505
+ }
506
+ const Form = ({ checked, setChecked, label, description, className, side = "right", ...props }) => {
507
+ const id = useId()
508
+
509
+ return (
510
+ <div className='flex items-start gap-2'>
511
+ <Checkbox id={id} defaultChecked />
512
+ <div className='grid gap-2'>
513
+ <Label htmlFor={id} className='gap-1 leading-4'>
514
+ Accept terms and conditions
515
+ </Label>
516
+ <p className='text-muted-foreground text-xs'>
517
+ By clicking this checkbox, you agree to the terms and conditions.
518
+ </p>
519
+ <div className='flex flex-wrap gap-2'>
520
+ <Button variant='outline' size='sm'>
521
+ Reset
522
+ </Button>
523
+ <Button size='sm'>Submit</Button>
524
+ </div>
525
+ </div>
526
+ </div>
527
+ )
528
+ }
529
+ const Animated = ({ checked, setChecked, label, description, className, side = "right", ...props }) => {
530
+ const id = useId()
531
+
532
+ return (
533
+ <Field className="flex items-start gap-2">
534
+ {side === 'left' && (
535
+ <div className="flex-1">
536
+ {label && (<FieldLabel>{label}</FieldLabel>)}
537
+ {description && (<FieldDescription>{description}</FieldDescription>)}
538
+ </div>
539
+ )}
540
+ <MotionCheckbox
541
+ id={id}
542
+ checked={checked}
543
+ onCheckedChange={setChecked}
544
+ {...props}
545
+ className={className}
546
+ />
547
+ {side === 'right' && (
548
+ <div className="flex-1">
549
+ {label && (<FieldLabel>{label}</FieldLabel>)}
550
+ {description && (<FieldDescription>{description}</FieldDescription>)}
551
+ </div>
552
+ )}
553
+ </Field>
554
+ )
555
+ }
556
+ const AnimatedTodoList = ({ items, setItems }) => {
557
+ const id = useId()
558
+ const handleCheckedChange = (index: number, checked: boolean) => {
559
+ const newItems = [...items]
560
+ newItems[index].checked = checked
561
+ setItems(newItems)
562
+ }
563
+ return (
564
+ <div className='flex flex-col gap-2'>
565
+ {items.map((i, index) => {
566
+ return (
567
+ <Field className="flex items-start gap-2" key={index}>
568
+ <Checkbox
569
+ id={id}
570
+ checked={i.checked}
571
+ onCheckedChange={(checked) => handleCheckedChange(index, checked)}
572
+ className={i.className}
573
+ />
574
+ <div className="flex-1">
575
+ {i.label && (<FieldLabel htmlFor={id} className='after:bg-primary peer-data-[state=checked]:text-primary relative after:absolute after:top-1/2 after:left-0 after:h-px after:w-full after:origin-bottom after:scale-x-0 after:transition-transform after:duration-500 after:ease-in-out peer-data-[state=checked]:after:origin-bottom peer-data-[state=checked]:after:scale-x-100'>{i.label}</FieldLabel>)}
576
+ {i.description && (<FieldDescription htmlFor={id} className='after:bg-primary peer-data-[state=checked]:text-primary relative after:absolute after:top-1/2 after:left-0 after:h-px after:w-full after:origin-bottom after:scale-x-0 after:transition-transform after:duration-500 after:ease-in-out peer-data-[state=checked]:after:origin-bottom peer-data-[state=checked]:after:scale-x-100'>{i.description}</FieldDescription>)}
577
+ </div>
578
+ </Field>
579
+ )
580
+ })}
581
+ </div>
582
+ )
583
+ }
584
+ const particleAnimation = ({ index, checked, setChecked, label, description, className, side = "right", ...props }) => {
585
+ const angle = Math.random() * Math.PI * 2
586
+ const distance = 30 + Math.random() * 20
587
+
588
+ return {
589
+ initial: { x: '50%', y: '50%', scale: 0, opacity: 0 },
590
+ animate: {
591
+ x: `calc(50% + ${Math.cos(angle) * distance}px)`,
592
+ y: `calc(50% + ${Math.sin(angle) * distance}px)`,
593
+ scale: [0, 1, 0],
594
+ opacity: [0, 1, 0]
595
+ },
596
+ transition: { duration: 0.4, delay: index * 0.05, ease: easeOut }
597
+ }
598
+ }
599
+ const ConfettiPiece = ({ index, checked, setChecked, label, description, className, side = "right", ...props }) => {
600
+ const colors = ['#FF0000', '#00FF00', '#0000FF', '#FFFF00', '#FF00FF', '#00FFFF']
601
+ const color = colors[index % colors.length]
602
+
603
+ return (
604
+ <motion.div
605
+ className='absolute size-1 rounded-full'
606
+ style={{ backgroundColor: color }}
607
+ {...particleAnimation(index)}
608
+ />
609
+ )
610
+ }
611
+ const Confetti = ({ checked, setChecked, label, description, className, side = "right", ...props }) => {
612
+ const [showConfetti, setShowConfetti] = useState(false)
613
+
614
+ const id = useId()
615
+
616
+ const handleCheckedChange = (checked: boolean) => {
617
+ if (checked) {
618
+ setShowConfetti(true)
619
+ setTimeout(() => setShowConfetti(false), 800)
620
+ }
621
+ setChecked(checked)
622
+ }
623
+
624
+ return (
625
+ <Field className="flex items-start gap-2">
626
+ {side === 'left' && (
627
+ <div className="flex-1">
628
+ {label && (<FieldLabel>{label}</FieldLabel>)}
629
+ {description && (<FieldDescription>{description}</FieldDescription>)}
630
+ </div>
631
+ )}
632
+ <Checkbox
633
+ id={id}
634
+ checked={checked}
635
+ onCheckedChange={handleCheckedChange}
636
+ {...props}
637
+ className={className}
638
+ />
639
+ {side === 'right' && (
640
+ <div className="flex-1">
641
+ {label && (<FieldLabel>{label}</FieldLabel>)}
642
+ {description && (<FieldDescription>{description}</FieldDescription>)}
643
+ </div>
644
+ )}
645
+ <AnimatePresence>
646
+ {showConfetti && (
647
+ <div className='pointer-events-none absolute inset-0'>
648
+ {[...Array(12)].map((_, i) => (
649
+ <ConfettiPiece key={i} index={i} />
650
+ ))}
651
+ </div>
652
+ )}
653
+ </AnimatePresence>
654
+ </Field>
655
+ )
656
+ }