@wealthx/shadcn 0.0.1 → 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 (186) hide show
  1. package/.turbo/turbo-build.log +160 -0
  2. package/CHANGELOG.md +13 -0
  3. package/CHANGES.md +345 -0
  4. package/dist/chunk-2WZVSBAY.mjs +232 -0
  5. package/dist/chunk-2Y7YJKPE.mjs +47 -0
  6. package/dist/chunk-3U7SD3MS.mjs +55 -0
  7. package/dist/chunk-3VQNJ235.mjs +114 -0
  8. package/dist/chunk-55CEW76V.mjs +35 -0
  9. package/dist/chunk-6AFMNC42.mjs +146 -0
  10. package/dist/chunk-6OJF6XRN.mjs +117 -0
  11. package/dist/chunk-7LDIMXGM.mjs +181 -0
  12. package/dist/chunk-AMJ23O53.mjs +122 -0
  13. package/dist/chunk-BBJBJSXQ.mjs +44 -0
  14. package/dist/chunk-BGP2N52Z.mjs +126 -0
  15. package/dist/chunk-BMFN37JH.mjs +41 -0
  16. package/dist/chunk-CGOKTPXU.mjs +79 -0
  17. package/dist/chunk-CZ3BW5GL.mjs +81 -0
  18. package/dist/chunk-DBHJ5KC3.mjs +55 -0
  19. package/dist/chunk-DDPA2XXS.mjs +97 -0
  20. package/dist/chunk-DS2AMHN2.mjs +30 -0
  21. package/dist/chunk-E3K6O4FZ.mjs +57 -0
  22. package/dist/chunk-FWCSY2DS.mjs +37 -0
  23. package/dist/chunk-GPRJQ24C.mjs +28 -0
  24. package/dist/chunk-HS7TFG7V.mjs +24 -0
  25. package/dist/chunk-HUVTPUV2.mjs +256 -0
  26. package/dist/chunk-IAOOZCUY.mjs +90 -0
  27. package/dist/chunk-JF4PHPD5.mjs +111 -0
  28. package/dist/chunk-JU2RUWHF.mjs +123 -0
  29. package/dist/chunk-KKHTJNMM.mjs +86 -0
  30. package/dist/chunk-MJIEMGRD.mjs +266 -0
  31. package/dist/chunk-MKFL5MNH.mjs +372 -0
  32. package/dist/chunk-MQ72DIBH.mjs +105 -0
  33. package/dist/chunk-NGYG2EA6.mjs +148 -0
  34. package/dist/chunk-NWZ46DJL.mjs +213 -0
  35. package/dist/chunk-OXQQNQZI.mjs +75 -0
  36. package/dist/chunk-PMKODV6M.mjs +161 -0
  37. package/dist/chunk-QOJ2DQD6.mjs +57 -0
  38. package/dist/chunk-RL772EH7.mjs +126 -0
  39. package/dist/chunk-SLWCCURD.mjs +99 -0
  40. package/dist/chunk-V7CNWJT3.mjs +10 -0
  41. package/dist/chunk-VG6UF6UT.mjs +68 -0
  42. package/dist/chunk-VYMHBV6D.mjs +123 -0
  43. package/dist/chunk-VZ2NR7L3.mjs +195 -0
  44. package/dist/chunk-YN5SYTOO.mjs +117 -0
  45. package/dist/chunk-Z3MK2KKZ.mjs +83 -0
  46. package/dist/chunk-ZN2QKLF6.mjs +187 -0
  47. package/dist/chunk-ZZV5JVNW.mjs +34 -0
  48. package/dist/components/ui/accordion.js +142 -0
  49. package/dist/components/ui/accordion.mjs +14 -0
  50. package/dist/components/ui/alert-dialog.js +413 -0
  51. package/dist/components/ui/alert-dialog.mjs +34 -0
  52. package/dist/components/ui/alert.js +134 -0
  53. package/dist/components/ui/alert.mjs +12 -0
  54. package/dist/components/ui/avatar.js +173 -0
  55. package/dist/components/ui/avatar.mjs +18 -0
  56. package/dist/components/ui/badge.js +163 -0
  57. package/dist/components/ui/badge.mjs +11 -0
  58. package/dist/components/ui/button.js +198 -0
  59. package/dist/components/ui/button.mjs +11 -0
  60. package/dist/components/ui/calendar.js +408 -0
  61. package/dist/components/ui/calendar.mjs +12 -0
  62. package/dist/components/ui/card.js +156 -0
  63. package/dist/components/ui/card.mjs +20 -0
  64. package/dist/components/ui/checkbox.js +166 -0
  65. package/dist/components/ui/checkbox.mjs +11 -0
  66. package/dist/components/ui/chip.js +199 -0
  67. package/dist/components/ui/chip.mjs +10 -0
  68. package/dist/components/ui/data-table.js +925 -0
  69. package/dist/components/ui/data-table.mjs +29 -0
  70. package/dist/components/ui/date-picker.js +561 -0
  71. package/dist/components/ui/date-picker.mjs +15 -0
  72. package/dist/components/ui/dialog.js +378 -0
  73. package/dist/components/ui/dialog.mjs +30 -0
  74. package/dist/components/ui/drawer.js +213 -0
  75. package/dist/components/ui/drawer.mjs +28 -0
  76. package/dist/components/ui/dropdown-menu.js +338 -0
  77. package/dist/components/ui/dropdown-menu.mjs +38 -0
  78. package/dist/components/ui/empty.js +173 -0
  79. package/dist/components/ui/empty.mjs +18 -0
  80. package/dist/components/ui/field.js +359 -0
  81. package/dist/components/ui/field.mjs +28 -0
  82. package/dist/components/ui/input-group.js +406 -0
  83. package/dist/components/ui/input-group.mjs +22 -0
  84. package/dist/components/ui/input-otp.js +149 -0
  85. package/dist/components/ui/input-otp.mjs +14 -0
  86. package/dist/components/ui/input.js +81 -0
  87. package/dist/components/ui/input.mjs +8 -0
  88. package/dist/components/ui/label.js +85 -0
  89. package/dist/components/ui/label.mjs +8 -0
  90. package/dist/components/ui/pagination.js +333 -0
  91. package/dist/components/ui/pagination.mjs +22 -0
  92. package/dist/components/ui/popover.js +167 -0
  93. package/dist/components/ui/popover.mjs +22 -0
  94. package/dist/components/ui/progress.js +97 -0
  95. package/dist/components/ui/progress.mjs +8 -0
  96. package/dist/components/ui/radio-group.js +178 -0
  97. package/dist/components/ui/radio-group.mjs +12 -0
  98. package/dist/components/ui/select.js +262 -0
  99. package/dist/components/ui/select.mjs +28 -0
  100. package/dist/components/ui/separator.js +86 -0
  101. package/dist/components/ui/separator.mjs +8 -0
  102. package/dist/components/ui/sheet.js +227 -0
  103. package/dist/components/ui/sheet.mjs +26 -0
  104. package/dist/components/ui/skeleton.js +75 -0
  105. package/dist/components/ui/skeleton.mjs +8 -0
  106. package/dist/components/ui/sonner.js +86 -0
  107. package/dist/components/ui/sonner.mjs +7 -0
  108. package/dist/components/ui/spinner.js +93 -0
  109. package/dist/components/ui/spinner.mjs +10 -0
  110. package/dist/components/ui/switch.js +178 -0
  111. package/dist/components/ui/switch.mjs +11 -0
  112. package/dist/components/ui/table.js +184 -0
  113. package/dist/components/ui/table.mjs +22 -0
  114. package/dist/components/ui/tabs.js +181 -0
  115. package/dist/components/ui/tabs.mjs +16 -0
  116. package/dist/components/ui/textarea.js +79 -0
  117. package/dist/components/ui/textarea.mjs +8 -0
  118. package/dist/components/ui/toggle-group.js +184 -0
  119. package/dist/components/ui/toggle-group.mjs +12 -0
  120. package/dist/components/ui/toggle.js +108 -0
  121. package/dist/components/ui/toggle.mjs +11 -0
  122. package/dist/components/ui/tooltip.js +140 -0
  123. package/dist/components/ui/tooltip.mjs +16 -0
  124. package/dist/index.js +4409 -0
  125. package/dist/index.mjs +462 -0
  126. package/dist/lib/colors.js +84 -0
  127. package/dist/lib/colors.mjs +13 -0
  128. package/dist/lib/theme-provider.js +150 -0
  129. package/dist/lib/theme-provider.mjs +13 -0
  130. package/dist/lib/typography.js +157 -0
  131. package/dist/lib/typography.mjs +25 -0
  132. package/dist/lib/utils.js +34 -0
  133. package/dist/lib/utils.mjs +7 -0
  134. package/dist/styles.css +2 -0
  135. package/package.json +228 -11
  136. package/scripts/build-css.ts +15 -9
  137. package/src/components/index.tsx +443 -0
  138. package/src/components/ui/accordion.tsx +99 -0
  139. package/src/components/ui/alert-dialog.tsx +239 -0
  140. package/src/components/ui/alert.tsx +81 -0
  141. package/src/components/ui/avatar.tsx +130 -0
  142. package/src/components/ui/badge.tsx +57 -0
  143. package/src/components/ui/button.tsx +69 -37
  144. package/src/components/ui/calendar.tsx +252 -0
  145. package/src/components/ui/card.tsx +106 -0
  146. package/src/components/ui/checkbox.tsx +111 -0
  147. package/src/components/ui/chip.tsx +65 -0
  148. package/src/components/ui/data-table.tsx +490 -0
  149. package/src/components/ui/date-picker.tsx +133 -0
  150. package/src/components/ui/dialog.tsx +195 -0
  151. package/src/components/ui/drawer.tsx +169 -0
  152. package/src/components/ui/dropdown-menu.tsx +315 -0
  153. package/src/components/ui/empty.tsx +128 -0
  154. package/src/components/ui/field.tsx +273 -0
  155. package/src/components/ui/input-group.tsx +190 -0
  156. package/src/components/ui/input-otp.tsx +90 -0
  157. package/src/components/ui/input.tsx +28 -0
  158. package/src/components/ui/label.tsx +24 -0
  159. package/src/components/ui/pagination.tsx +148 -0
  160. package/src/components/ui/popover.tsx +112 -0
  161. package/src/components/ui/progress.tsx +40 -0
  162. package/src/components/ui/radio-group.tsx +129 -0
  163. package/src/components/ui/select.tsx +201 -0
  164. package/src/components/ui/separator.tsx +26 -0
  165. package/src/components/ui/sheet.tsx +182 -0
  166. package/src/components/ui/skeleton.tsx +22 -0
  167. package/src/components/ui/sonner.tsx +48 -0
  168. package/src/components/ui/spinner.tsx +41 -0
  169. package/src/components/ui/switch.tsx +126 -0
  170. package/src/components/ui/table.tsx +143 -0
  171. package/src/components/ui/tabs.tsx +119 -0
  172. package/src/components/ui/textarea.tsx +28 -0
  173. package/src/components/ui/toggle-group.tsx +94 -0
  174. package/src/components/ui/toggle.tsx +59 -0
  175. package/src/components/ui/tooltip.tsx +80 -0
  176. package/src/index.ts +15 -3
  177. package/src/lib/colors.ts +74 -0
  178. package/src/lib/slot.tsx +68 -0
  179. package/src/lib/theme-provider.tsx +134 -0
  180. package/src/lib/typography.ts +153 -0
  181. package/src/lib/utils.ts +1 -1
  182. package/src/styles/globals.css +377 -107
  183. package/src/styles/styles-css.ts +1 -1
  184. package/tsup.config.ts +48 -2
  185. package/src/provider/ShadcnProvider.tsx +0 -89
  186. package/src/provider/index.ts +0 -2
@@ -0,0 +1,252 @@
1
+ import { type ReactElement } from "react"
2
+ import * as React from "react"
3
+ import {
4
+ ChevronDownIcon,
5
+ ChevronLeftIcon,
6
+ ChevronRightIcon,
7
+ } from "lucide-react"
8
+ import {
9
+ DayPicker,
10
+ getDefaultClassNames,
11
+ type DayButton,
12
+ } from "react-day-picker"
13
+ import { cn } from "@/lib/utils"
14
+ import { Button, buttonVariants } from "@/components/ui/button"
15
+
16
+ /**
17
+ * Calendar — shadcn/WealthX
18
+ * Base: npx shadcn\@latest add calendar (latest)
19
+ * Figma: Design-System---shadcn?node-id=72-2720
20
+ *
21
+ * WealthX:
22
+ * - font-sans for consistent Figtree typography
23
+ * - border + shadow-sm on root (square corners — no border radius)
24
+ * - captionLayout defaults to "dropdown" (Figma shows month/year dropdown pills)
25
+ */
26
+
27
+ export type CalendarProps = React.ComponentProps<typeof DayPicker> & {
28
+ buttonVariant?: React.ComponentProps<typeof Button>["variant"]
29
+ }
30
+
31
+ function CalendarRoot({
32
+ className,
33
+ rootRef,
34
+ ...props
35
+ }: {
36
+ className?: string
37
+ rootRef?: React.Ref<HTMLDivElement>
38
+ } & React.ComponentProps<"div">): ReactElement {
39
+ return (
40
+ <div
41
+ className={cn(className)}
42
+ data-slot="calendar"
43
+ ref={rootRef}
44
+ {...props}
45
+ />
46
+ )
47
+ }
48
+
49
+ function CalendarChevron({
50
+ className,
51
+ orientation,
52
+ ...props
53
+ }: {
54
+ className?: string
55
+ orientation?: string
56
+ } & React.ComponentProps<"svg">): ReactElement {
57
+ if (orientation === "left") {
58
+ return (
59
+ <ChevronLeftIcon className={cn("size-4", className)} {...props} />
60
+ )
61
+ }
62
+
63
+ if (orientation === "right") {
64
+ return (
65
+ <ChevronRightIcon
66
+ className={cn("size-4", className)}
67
+ {...props}
68
+ />
69
+ )
70
+ }
71
+
72
+ return (
73
+ <ChevronDownIcon className={cn("size-4", className)} {...props} />
74
+ )
75
+ }
76
+
77
+ function CalendarWeekNumber({
78
+ children,
79
+ ...props
80
+ }: React.ComponentProps<"td">): ReactElement {
81
+ return (
82
+ <td {...props}>
83
+ <div className="flex size-(--cell-size) items-center justify-center text-center">
84
+ {children}
85
+ </div>
86
+ </td>
87
+ )
88
+ }
89
+
90
+ function Calendar({
91
+ className,
92
+ classNames,
93
+ showOutsideDays = true,
94
+ captionLayout = "dropdown",
95
+ buttonVariant = "ghost",
96
+ formatters,
97
+ components,
98
+ ...props
99
+ }: CalendarProps): ReactElement {
100
+ const defaultClassNames = getDefaultClassNames()
101
+
102
+ return (
103
+ <DayPicker
104
+ captionLayout={captionLayout}
105
+ className={cn(
106
+ "group/calendar bg-background p-3 font-sans border border-border shadow-sm [--cell-size:--spacing(8)] [[data-slot=card-content]_&]:bg-transparent [[data-slot=popover-content]_&]:bg-transparent",
107
+ String.raw`rtl:**:[.rdp-button\_next>svg]:rotate-180`,
108
+ String.raw`rtl:**:[.rdp-button\_previous>svg]:rotate-180`,
109
+ className
110
+ )}
111
+ classNames={{
112
+ root: cn("w-fit", defaultClassNames.root),
113
+ months: cn(
114
+ "relative flex flex-col gap-4 md:flex-row",
115
+ defaultClassNames.months
116
+ ),
117
+ month: cn("flex w-full flex-col gap-4", defaultClassNames.month),
118
+ nav: cn(
119
+ "absolute inset-x-0 top-0 flex w-full items-center justify-between gap-1",
120
+ defaultClassNames.nav
121
+ ),
122
+ button_previous: cn(
123
+ buttonVariants({ variant: buttonVariant }),
124
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
125
+ defaultClassNames.button_previous
126
+ ),
127
+ button_next: cn(
128
+ buttonVariants({ variant: buttonVariant }),
129
+ "size-(--cell-size) p-0 select-none aria-disabled:opacity-50",
130
+ defaultClassNames.button_next
131
+ ),
132
+ month_caption: cn(
133
+ "flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)",
134
+ defaultClassNames.month_caption
135
+ ),
136
+ dropdowns: cn(
137
+ "flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium",
138
+ defaultClassNames.dropdowns
139
+ ),
140
+ dropdown_root: cn(
141
+ "relative border border-input shadow-xs has-focus:border-ring has-focus:ring-[3px] has-focus:ring-ring/50",
142
+ defaultClassNames.dropdown_root
143
+ ),
144
+ dropdown: cn(
145
+ "absolute inset-0 bg-popover opacity-0",
146
+ defaultClassNames.dropdown
147
+ ),
148
+ caption_label: cn(
149
+ "font-medium select-none",
150
+ captionLayout === "label"
151
+ ? "text-sm"
152
+ : "flex h-8 items-center gap-1 pr-1 pl-2 text-sm [&>svg]:size-3.5 [&>svg]:text-muted-foreground",
153
+ defaultClassNames.caption_label
154
+ ),
155
+ table: "w-full border-collapse",
156
+ weekdays: cn("flex", defaultClassNames.weekdays),
157
+ weekday: cn(
158
+ "flex-1 text-[0.8rem] font-normal text-muted-foreground select-none",
159
+ defaultClassNames.weekday
160
+ ),
161
+ week: cn("mt-2 flex w-full", defaultClassNames.week),
162
+ week_number_header: cn(
163
+ "w-(--cell-size) select-none",
164
+ defaultClassNames.week_number_header
165
+ ),
166
+ week_number: cn(
167
+ "text-[0.8rem] text-muted-foreground select-none",
168
+ defaultClassNames.week_number
169
+ ),
170
+ day: cn(
171
+ "group/day relative aspect-square h-full w-full p-0 text-center select-none",
172
+ defaultClassNames.day
173
+ ),
174
+ range_start: cn("bg-accent", defaultClassNames.range_start),
175
+ range_middle: cn("rounded-none", defaultClassNames.range_middle),
176
+ range_end: cn("bg-accent", defaultClassNames.range_end),
177
+ today: cn(
178
+ "bg-accent text-accent-foreground",
179
+ defaultClassNames.today
180
+ ),
181
+ outside: cn(
182
+ "text-muted-foreground aria-selected:text-muted-foreground",
183
+ defaultClassNames.outside
184
+ ),
185
+ disabled: cn(
186
+ "text-muted-foreground opacity-50",
187
+ defaultClassNames.disabled
188
+ ),
189
+ hidden: cn("invisible", defaultClassNames.hidden),
190
+ ...classNames,
191
+ }}
192
+ components={{
193
+ Root: CalendarRoot,
194
+ Chevron: CalendarChevron,
195
+ DayButton: CalendarDayButton,
196
+ WeekNumber: CalendarWeekNumber,
197
+ ...components,
198
+ }}
199
+ formatters={{
200
+ formatMonthDropdown: (date) =>
201
+ date.toLocaleString("default", { month: "short" }),
202
+ ...formatters,
203
+ }}
204
+ showOutsideDays={showOutsideDays}
205
+ {...props}
206
+ />
207
+ )
208
+ }
209
+
210
+ export type CalendarDayButtonProps = React.ComponentProps<typeof DayButton>
211
+
212
+ function CalendarDayButton({
213
+ className,
214
+ day,
215
+ modifiers,
216
+ ...props
217
+ }: CalendarDayButtonProps): ReactElement {
218
+ const defaultClassNames = getDefaultClassNames()
219
+
220
+ const ref = React.useRef<HTMLButtonElement>(null)
221
+ React.useEffect(() => {
222
+ if (modifiers.focused) ref.current?.focus()
223
+ }, [modifiers.focused])
224
+
225
+ const selectedSingle =
226
+ modifiers.selected &&
227
+ !modifiers.range_start &&
228
+ !modifiers.range_end
229
+ ? !modifiers.range_middle
230
+ : null
231
+
232
+ return (
233
+ <Button
234
+ className={cn(
235
+ "flex aspect-square size-auto w-full min-w-(--cell-size) flex-col gap-1 leading-none font-normal rounded-none group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-[3px] group-data-[focused=true]/day:ring-ring/50 data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground data-[range-middle=true]:rounded-none data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground dark:hover:text-accent-foreground [&>span]:text-xs [&>span]:opacity-70",
236
+ defaultClassNames.day,
237
+ className
238
+ )}
239
+ data-day={day.date.toLocaleDateString()}
240
+ data-range-end={modifiers.range_end}
241
+ data-range-middle={modifiers.range_middle}
242
+ data-range-start={modifiers.range_start}
243
+ data-selected-single={selectedSingle}
244
+ ref={ref}
245
+ size="icon"
246
+ variant="ghost"
247
+ {...props}
248
+ />
249
+ )
250
+ }
251
+
252
+ export { Calendar, CalendarDayButton }
@@ -0,0 +1,106 @@
1
+ import { type ReactElement } from "react"
2
+ import * as React from "react"
3
+ import { cn } from "@/lib/utils"
4
+
5
+ export type CardProps = React.ComponentProps<"div">
6
+
7
+ function Card({ className, ...props }: CardProps): ReactElement {
8
+ return (
9
+ <div
10
+ className={cn(
11
+ "flex flex-col gap-6 border bg-card py-6 text-card-foreground shadow-sm",
12
+ className
13
+ )}
14
+ data-slot="card"
15
+ {...props}
16
+ />
17
+ )
18
+ }
19
+
20
+ export type CardHeaderProps = React.ComponentProps<"div">
21
+
22
+ function CardHeader({ className, ...props }: CardHeaderProps): ReactElement {
23
+ return (
24
+ <div
25
+ className={cn(
26
+ "@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6",
27
+ className
28
+ )}
29
+ data-slot="card-header"
30
+ {...props}
31
+ />
32
+ )
33
+ }
34
+
35
+ export type CardTitleProps = React.ComponentProps<"div">
36
+
37
+ function CardTitle({ className, ...props }: CardTitleProps): ReactElement {
38
+ return (
39
+ <div
40
+ className={cn("leading-none font-semibold", className)}
41
+ data-slot="card-title"
42
+ {...props}
43
+ />
44
+ )
45
+ }
46
+
47
+ export type CardDescriptionProps = React.ComponentProps<"div">
48
+
49
+ function CardDescription({ className, ...props }: CardDescriptionProps): ReactElement {
50
+ return (
51
+ <div
52
+ className={cn("text-sm text-muted-foreground", className)}
53
+ data-slot="card-description"
54
+ {...props}
55
+ />
56
+ )
57
+ }
58
+
59
+ export type CardActionProps = React.ComponentProps<"div">
60
+
61
+ function CardAction({ className, ...props }: CardActionProps): ReactElement {
62
+ return (
63
+ <div
64
+ className={cn(
65
+ "col-start-2 row-span-2 row-start-1 self-start justify-self-end",
66
+ className
67
+ )}
68
+ data-slot="card-action"
69
+ {...props}
70
+ />
71
+ )
72
+ }
73
+
74
+ export type CardContentProps = React.ComponentProps<"div">
75
+
76
+ function CardContent({ className, ...props }: CardContentProps): ReactElement {
77
+ return (
78
+ <div
79
+ className={cn("px-6", className)}
80
+ data-slot="card-content"
81
+ {...props}
82
+ />
83
+ )
84
+ }
85
+
86
+ export type CardFooterProps = React.ComponentProps<"div">
87
+
88
+ function CardFooter({ className, ...props }: CardFooterProps): ReactElement {
89
+ return (
90
+ <div
91
+ className={cn("flex items-center px-6 [.border-t]:pt-6", className)}
92
+ data-slot="card-footer"
93
+ {...props}
94
+ />
95
+ )
96
+ }
97
+
98
+ export {
99
+ Card,
100
+ CardHeader,
101
+ CardFooter,
102
+ CardTitle,
103
+ CardAction,
104
+ CardDescription,
105
+ CardContent,
106
+ }
@@ -0,0 +1,111 @@
1
+ "use client"
2
+
3
+ import { type ReactElement, useState, type ComponentProps } from "react"
4
+ import { CheckIcon, MinusIcon } from "lucide-react"
5
+ import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox"
6
+ import { cn } from "@/lib/utils"
7
+
8
+ /**
9
+ * Checkbox — shadcn/WealthX Design System
10
+ * Figma: https://www.figma.com/design/9V9F0NGVsif8LGmEhVjOcT/Design-System---shadcn?node-id=72-2723
11
+ *
12
+ * States: unchecked | checked | indeterminate × default | disabled | error
13
+ * White-label: checked/indeterminate use `primary` token → adapts to tenant color.
14
+ * Error+checked/indeterminate: stacked variant overrides primary with destructive (higher specificity).
15
+ */
16
+ export type CheckboxProps = ComponentProps<typeof CheckboxPrimitive.Root>
17
+
18
+ function Checkbox({ className, ...props }: CheckboxProps): ReactElement {
19
+ return (
20
+ <CheckboxPrimitive.Root
21
+ className={cn(
22
+ "peer group inline-flex size-4 shrink-0 rounded-[4px] border border-input shadow-xs transition-all outline-none",
23
+ "focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
24
+ "disabled:cursor-not-allowed disabled:opacity-50",
25
+ "aria-invalid:border-destructive aria-invalid:ring-destructive/20",
26
+ "data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground",
27
+ "data-indeterminate:border-primary data-indeterminate:bg-primary data-indeterminate:text-primary-foreground",
28
+ // Dark mode (upstream shadcn)
29
+ "dark:bg-input/30 dark:aria-invalid:ring-destructive/40 dark:data-checked:bg-primary",
30
+ // Stacked (2 attr selectors) → wins over single-attr rules above
31
+ "aria-invalid:data-checked:border-destructive aria-invalid:data-checked:bg-destructive aria-invalid:data-checked:text-destructive-foreground",
32
+ "aria-invalid:data-indeterminate:border-destructive aria-invalid:data-indeterminate:bg-destructive aria-invalid:data-indeterminate:text-destructive-foreground",
33
+ className
34
+ )}
35
+ data-slot="checkbox"
36
+ {...props}
37
+ >
38
+ <CheckboxPrimitive.Indicator
39
+ className="grid place-content-center text-current transition-none"
40
+ data-slot="checkbox-indicator"
41
+ >
42
+ <CheckIcon className="size-3.5 group-data-indeterminate:hidden" />
43
+ <MinusIcon className="size-3.5 hidden group-data-indeterminate:block" />
44
+ </CheckboxPrimitive.Indicator>
45
+ </CheckboxPrimitive.Root>
46
+ )
47
+ }
48
+
49
+ /**
50
+ * CheckboxCard — card wrapper with label + optional description.
51
+ * Figma: Checkbox_card (3029:12381)
52
+ *
53
+ * Card background: primary/5 when checked/indeterminate; destructive/5 when error+checked.
54
+ * White-label: opacity modifier on primary token → adapts to tenant color.
55
+ */
56
+ export type CheckboxCardProps = ComponentProps<typeof CheckboxPrimitive.Root> & {
57
+ label: string
58
+ description?: string
59
+ error?: boolean
60
+ }
61
+
62
+ function CheckboxCard({
63
+ className,
64
+ checked,
65
+ defaultChecked,
66
+ onCheckedChange,
67
+ disabled,
68
+ error,
69
+ label,
70
+ description,
71
+ ...props
72
+ }: CheckboxCardProps): ReactElement {
73
+ const [internalChecked, setInternalChecked] = useState<boolean>(
74
+ Boolean(defaultChecked)
75
+ )
76
+
77
+ const resolvedChecked = checked ?? internalChecked
78
+ const isTinted = resolvedChecked
79
+
80
+ return (
81
+ <label
82
+ className={cn(
83
+ "flex items-start gap-3 border border-border p-4 font-sans transition-colors cursor-pointer",
84
+ error
85
+ ? ["border-destructive", isTinted && "bg-destructive/5"]
86
+ : isTinted && "border-primary bg-primary/5",
87
+ disabled && "cursor-not-allowed opacity-50",
88
+ className
89
+ )}
90
+ data-slot="checkbox-card"
91
+ >
92
+ <Checkbox
93
+ aria-invalid={error || undefined}
94
+ checked={resolvedChecked}
95
+ className="mt-0.5"
96
+ disabled={disabled}
97
+ onCheckedChange={(value, event) => {
98
+ setInternalChecked(value as boolean)
99
+ onCheckedChange?.(value, event)
100
+ }}
101
+ {...props}
102
+ />
103
+ <div className="flex flex-col gap-1">
104
+ <span className="text-sm font-medium leading-none">{label}</span>
105
+ {description ? <span className="text-sm text-muted-foreground">{description}</span> : null}
106
+ </div>
107
+ </label>
108
+ )
109
+ }
110
+
111
+ export { Checkbox, CheckboxCard }
@@ -0,0 +1,65 @@
1
+ // Chip — WealthX DS (built on Badge)
2
+ //
3
+ // Badge extended with an optional dismiss button.
4
+ // Passes all Badge props (variant, className, etc.) through unchanged.
5
+ //
6
+ // Usage:
7
+ // <Chip>Label</Chip>
8
+ // <Chip onRemove={() => handleRemove(id)}>Label</Chip>
9
+ // <Chip variant="outline" disabled onRemove={...}>Label</Chip>
10
+ import { type ReactElement } from "react"
11
+ import * as React from "react"
12
+ import { X } from "lucide-react"
13
+ import type { VariantProps } from "class-variance-authority"
14
+ import { cn } from "@/lib/utils"
15
+ import { badgeVariants } from "@/components/ui/badge"
16
+
17
+ export interface ChipProps
18
+ extends React.ComponentProps<"span">,
19
+ VariantProps<typeof badgeVariants> {
20
+ /** When provided, renders a dismiss (×) button inside the chip. */
21
+ onRemove?: () => void
22
+ disabled?: boolean
23
+ }
24
+
25
+ function Chip({
26
+ className,
27
+ variant = "secondary",
28
+ onRemove,
29
+ disabled,
30
+ children,
31
+ ...props
32
+ }: ChipProps): ReactElement {
33
+ return (
34
+ <span
35
+ aria-disabled={disabled}
36
+ className={cn(
37
+ badgeVariants({ variant }),
38
+ // extra right padding only when dismiss button is present
39
+ onRemove && "pr-1",
40
+ disabled && "pointer-events-none opacity-50",
41
+ className
42
+ )}
43
+ data-slot="chip"
44
+ data-variant={variant}
45
+ {...props}
46
+ >
47
+ {children}
48
+ {onRemove ? <button
49
+ aria-label="Remove"
50
+ className="ml-0.5 inline-flex shrink-0 items-center justify-center rounded-full p-0.5 opacity-60 hover:opacity-100 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none"
51
+ data-slot="chip-remove"
52
+ disabled={disabled}
53
+ onClick={(e) => {
54
+ e.stopPropagation()
55
+ onRemove()
56
+ }}
57
+ type="button"
58
+ >
59
+ <X className="size-3" />
60
+ </button> : null}
61
+ </span>
62
+ )
63
+ }
64
+
65
+ export { Chip }