@catalystsoftware/ui 1.0.4 → 1.0.5
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.
- package/data/tailwind.config.js +261 -3821
- package/dist/components/catalyst-ui/buttons/burger.tsx +207 -0
- package/dist/components/catalyst-ui/core/data-display/timeline.tsx +210 -0
- package/dist/components/catalyst-ui/core/feedback/alert.tsx +491 -0
- package/dist/components/catalyst-ui/core/feedback/spinner-1.tsx +65 -0
- package/dist/components/catalyst-ui/core/feedback/toast.tsx +1857 -0
- package/dist/components/catalyst-ui/core/navigation/menu.tsx +164 -0
- package/dist/components/catalyst-ui/forms/toggle-class.tsx +176 -0
- package/dist/components/catalyst-ui/hooks/use-copy-to-clipboard.tsx +419 -0
- package/dist/components/catalyst-ui/hooks/use-counter.tsx +13 -0
- package/dist/components/catalyst-ui/hooks/use-event-listener.tsx +23 -0
- package/dist/components/catalyst-ui/hooks/use-export-markdown.tsx +47 -0
- package/dist/components/catalyst-ui/hooks/use-focus.tsx +17 -0
- package/dist/components/catalyst-ui/hooks/use-interval.tsx +23 -0
- package/dist/components/catalyst-ui/hooks/use-is-client.tsx +16 -0
- package/dist/components/catalyst-ui/hooks/use-media-query.tsx +19 -0
- package/dist/components/catalyst-ui/hooks/use-mobile.tsx +19 -0
- package/dist/components/catalyst-ui/hooks/use-resize-observer.tsx +81 -0
- package/dist/components/catalyst-ui/hooks/use-timeout.tsx +21 -0
- package/dist/components/catalyst-ui/hooks/use-timer.tsx +209 -0
- package/dist/components/catalyst-ui/hooks/use-toggle.tsx +12 -0
- package/dist/components/catalyst-ui/media/image.tsx +13 -0
- package/dist/components/catalyst-ui/overlays/dual-sidebar.tsx +4142 -0
- package/dist/components/catalyst-ui/overlays/sidebar-original.tsx +726 -0
- package/dist/components/catalyst-ui/primitives/accordion.tsx +250 -0
- package/dist/components/catalyst-ui/primitives/alert-dialog.tsx +126 -0
- package/dist/components/catalyst-ui/primitives/aspect-ratio.tsx +9 -0
- package/dist/components/catalyst-ui/primitives/avatar.tsx +296 -0
- package/dist/components/catalyst-ui/primitives/badge.tsx +57 -0
- package/dist/components/catalyst-ui/primitives/breadcrumb.tsx +101 -0
- package/dist/components/catalyst-ui/primitives/button.tsx +265 -0
- package/dist/components/catalyst-ui/primitives/calendar-v4.tsx +208 -0
- package/dist/components/catalyst-ui/primitives/calendar.tsx +295 -0
- package/dist/components/catalyst-ui/primitives/card.tsx +618 -0
- package/dist/components/catalyst-ui/primitives/carousel.tsx +238 -0
- package/dist/components/catalyst-ui/primitives/chart.tsx +347 -0
- package/dist/components/catalyst-ui/primitives/checkbox.tsx +225 -0
- package/dist/components/catalyst-ui/primitives/collapsible.tsx +212 -0
- package/dist/components/catalyst-ui/primitives/command.tsx +393 -0
- package/dist/components/catalyst-ui/primitives/context-menu.tsx +236 -0
- package/dist/components/catalyst-ui/primitives/dialog.tsx +471 -0
- package/dist/components/catalyst-ui/primitives/drawer.tsx +761 -0
- package/dist/components/catalyst-ui/primitives/dropdown-menu.tsx +290 -0
- package/dist/components/catalyst-ui/primitives/empty.tsx +104 -0
- package/dist/components/catalyst-ui/primitives/field.tsx +244 -0
- package/dist/components/catalyst-ui/primitives/hover-card.tsx +124 -0
- package/dist/components/catalyst-ui/primitives/input-otp.tsx +76 -0
- package/dist/components/catalyst-ui/primitives/input.tsx +64 -0
- package/dist/components/catalyst-ui/primitives/item.tsx +196 -0
- package/dist/components/catalyst-ui/primitives/kbd.tsx +75 -0
- package/dist/components/catalyst-ui/primitives/label.tsx +24 -0
- package/dist/components/catalyst-ui/primitives/navigation-menu.tsx +150 -0
- package/dist/components/catalyst-ui/primitives/pagination.tsx +198 -0
- package/dist/components/catalyst-ui/primitives/popover.tsx +232 -0
- package/dist/components/catalyst-ui/primitives/progress.tsx +34 -0
- package/dist/components/catalyst-ui/primitives/radio-group.tsx +43 -0
- package/dist/components/catalyst-ui/primitives/resizable.tsx +56 -0
- package/dist/components/catalyst-ui/primitives/select.tsx +155 -0
- package/dist/components/catalyst-ui/primitives/separator.tsx +74 -0
- package/dist/components/catalyst-ui/primitives/sheet.tsx +126 -0
- package/dist/components/catalyst-ui/primitives/skeleton.tsx +15 -0
- package/dist/components/catalyst-ui/primitives/slider.tsx +27 -0
- package/dist/components/catalyst-ui/primitives/switch.tsx +187 -0
- package/dist/components/catalyst-ui/primitives/tabs.tsx +335 -0
- package/dist/components/catalyst-ui/primitives/textarea.tsx +24 -0
- package/dist/components/catalyst-ui/primitives/toggle-group.tsx +55 -0
- package/dist/components/catalyst-ui/primitives/toggle.tsx +42 -0
- package/dist/components/catalyst-ui/primitives/tooltip.tsx +116 -0
- package/dist/components/catalyst-ui/utils/basic-auth.tsx +40 -0
- package/dist/components/catalyst-ui/utils/context-storage.tsx +19 -0
- package/dist/components/catalyst-ui/utils/cors-middleware.tsx +71 -0
- package/dist/components/catalyst-ui/utils/deferred-content.tsx +595 -0
- package/dist/components/catalyst-ui/utils/honeypot-middleware.tsx +38 -0
- package/dist/components/catalyst-ui/utils/incId.tsx +75 -0
- package/dist/components/catalyst-ui/utils/jwk-auth.tsx +36 -0
- package/dist/components/catalyst-ui/utils/request-id.tsx +14 -0
- package/dist/components/catalyst-ui/utils/secure-headers.tsx +37 -0
- package/dist/components/catalyst-ui/utils/server-timing.tsx +23 -0
- package/dist/components/catalyst-ui/utils/utils.ts +43 -0
- package/dist/components/catalyst-ui/utils/with-cookie.tsx +43 -0
- package/dist/components/catalyst-ui/x/accordian-x.tsx +428 -0
- package/dist/components/catalyst-ui/x/alert-x.tsx +413 -0
- package/dist/components/catalyst-ui/x/animated-text-x.tsx +2242 -0
- package/dist/components/catalyst-ui/x/avatar-x.tsx +515 -0
- package/dist/components/catalyst-ui/x/badge-x.tsx +670 -0
- package/dist/components/catalyst-ui/x/button-X.tsx +2857 -0
- package/dist/components/catalyst-ui/x/button-group-x.tsx +847 -0
- package/dist/components/catalyst-ui/x/calendar-x.tsx +1910 -0
- package/dist/components/catalyst-ui/x/card-x.tsx +2597 -0
- package/dist/components/catalyst-ui/x/checkbox-x.tsx +656 -0
- package/dist/components/catalyst-ui/x/collapsible-x.tsx +1360 -0
- package/dist/components/catalyst-ui/x/combobox-x.tsx +911 -0
- package/dist/components/catalyst-ui/x/data-table-x.tsx +1753 -0
- package/dist/components/catalyst-ui/x/date-picker-x.tsx +648 -0
- package/dist/components/catalyst-ui/x/dialog-x.tsx +659 -0
- package/dist/components/catalyst-ui/x/dropdown-menu-x.tsx +612 -0
- package/dist/components/catalyst-ui/x/hover-card-x.tsx +375 -0
- package/dist/components/catalyst-ui/x/icon-x.tsx +840 -0
- package/dist/components/catalyst-ui/x/input-mask-x.tsx +981 -0
- package/dist/components/catalyst-ui/x/input-otp-x.tsx +659 -0
- package/dist/components/catalyst-ui/x/loader-x.tsx +1757 -0
- package/dist/components/catalyst-ui/x/pagination-x.tsx +622 -0
- package/dist/components/catalyst-ui/x/popover-x.tsx +744 -0
- package/dist/components/catalyst-ui/x/radio-group-x.tsx +499 -0
- package/dist/components/catalyst-ui/x/select-x.tsx +1127 -0
- package/dist/components/catalyst-ui/x/sheet-x.tsx +668 -0
- package/dist/components/catalyst-ui/x/switch-x.tsx +681 -0
- package/dist/components/catalyst-ui/x/table-x.tsx +574 -0
- package/dist/components/catalyst-ui/x/tabs-x.tsx +839 -0
- package/dist/components/catalyst-ui/x/textarea-x.tsx +1263 -0
- package/dist/components/catalyst-ui/x/tooltip-x.tsx +396 -0
- package/dist/components/catalyst-ui/x/tracker-x.tsx +560 -0
- package/dist/data/bg-data.tsx +901 -0
- package/dist/data/buttons-data.tsx +2327 -0
- package/dist/data/charts-data.tsx +102 -0
- package/dist/data/chat-data.tsx +83 -0
- package/dist/data/code-data.tsx +1040 -0
- package/dist/data/comboboxes-data.tsx +1843 -0
- package/dist/data/command-data.tsx +1381 -0
- package/dist/data/core-data.tsx +15953 -0
- package/dist/data/crm-data.tsx +47 -0
- package/dist/data/data.tsx +159 -0
- package/dist/data/date-and-time-data.tsx +554 -0
- package/dist/data/dependencies.tsx +7 -0
- package/dist/data/ecommerce-data.tsx +1387 -0
- package/dist/data/forms-data.tsx +7890 -0
- package/dist/data/hooks-data.tsx +5487 -0
- package/dist/data/index.ts +34 -0
- package/dist/data/inputs-data.tsx +557 -0
- package/dist/data/interactive-data.tsx +5394 -0
- package/dist/data/lofi-data.tsx +18295 -0
- package/dist/data/marketing-data.tsx +2546 -0
- package/dist/data/media-data.tsx +1510 -0
- package/dist/data/motion-data.tsx +5801 -0
- package/dist/data/overlay-data.tsx +4136 -0
- package/dist/data/pdf-data.tsx +124 -0
- package/dist/data/pos-data.tsx +213 -0
- package/dist/data/postcss.config.js +6 -0
- package/dist/data/primitive-data.tsx +5170 -0
- package/dist/data/prompt-data.tsx +1226 -0
- package/dist/data/requiredLibs.ts +4 -0
- package/dist/data/sandbox-data.tsx +1 -0
- package/dist/data/sidebars-data.tsx +5421 -0
- package/dist/data/stacks-data.tsx +32 -0
- package/dist/data/table-data.tsx +706 -0
- package/dist/data/tailwind.config.js +270 -0
- package/dist/data/tailwind.config.ngin.js +3830 -0
- package/dist/data/tailwind.css +431 -0
- package/dist/data/tools-data.tsx +6910 -0
- package/dist/data/typography-data.tsx +2050 -0
- package/dist/data/utils-data.tsx +6500 -0
- package/dist/data/x-data.tsx +1171 -0
- package/dist/data.tsx +159 -0
- package/package.json +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -362
|
@@ -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
|
+
}
|