azamat-ui-kit-cli 0.3.13 → 0.3.15

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 (37) hide show
  1. package/README.md +1 -1
  2. package/dist/index.cjs +807 -107
  3. package/package.json +1 -1
  4. package/vendor/src/components/data-table/data-table-pagination.tsx +1 -1
  5. package/vendor/src/components/data-table/data-table-toolbar.tsx +13 -12
  6. package/vendor/src/components/data-table/data-table.tsx +14 -14
  7. package/vendor/src/components/display/smart-card.tsx +17 -14
  8. package/vendor/src/components/form/form-input.tsx +3 -1
  9. package/vendor/src/components/form/form-textarea.tsx +15 -12
  10. package/vendor/src/components/inputs/async-select.tsx +106 -47
  11. package/vendor/src/components/inputs/clearable-input.tsx +1 -0
  12. package/vendor/src/components/inputs/input-chrome.tsx +1 -1
  13. package/vendor/src/components/inputs/input-decorator.tsx +16 -8
  14. package/vendor/src/components/inputs/simple-select.tsx +28 -28
  15. package/vendor/src/components/layout/app-sidebar.tsx +454 -154
  16. package/vendor/src/components/layout/breadcrumbs.tsx +67 -22
  17. package/vendor/src/components/layout/sidebar-nav.tsx +316 -128
  18. package/vendor/src/components/overlay/confirm-dialog.tsx +31 -20
  19. package/vendor/src/components/patterns/form-builder-presets.ts +13 -131
  20. package/vendor/src/components/patterns/form-builder.tsx +118 -9
  21. package/vendor/src/components/patterns/index.ts +3 -4
  22. package/vendor/src/components/patterns/public.ts +0 -1
  23. package/vendor/src/components/ui/badge.tsx +33 -32
  24. package/vendor/src/components/ui/button.tsx +15 -17
  25. package/vendor/src/components/ui/card.tsx +26 -25
  26. package/vendor/src/components/ui/dialog.tsx +6 -3
  27. package/vendor/src/components/ui/dropdown-menu.tsx +9 -9
  28. package/vendor/src/components/ui/input-primitive.tsx +1 -1
  29. package/vendor/src/components/ui/input.tsx +105 -2
  30. package/vendor/src/components/ui/popover.tsx +1 -1
  31. package/vendor/src/components/ui/select.tsx +3 -3
  32. package/vendor/src/components/ui/table.tsx +4 -4
  33. package/vendor/src/components/ui/tabs.tsx +2 -2
  34. package/vendor/src/families/form-family.ts +0 -2
  35. package/vendor/src/families/member-metadata.ts +3 -3
  36. package/vendor/src/families/member-snippets.ts +3 -3
  37. package/vendor/templates/styles/globals.css +706 -6
@@ -1,131 +1,13 @@
1
- import type { FieldPath, FieldValues } from "react-hook-form"
2
-
3
- import type {
4
- FormBuilderAsyncSelectField,
5
- FormBuilderCustomField,
6
- FormBuilderDateField,
7
- FormBuilderDateRangeField,
8
- FormBuilderInputField,
9
- FormBuilderNumberField,
10
- FormBuilderPhoneField,
11
- FormBuilderSection,
12
- FormBuilderSelectField,
13
- FormBuilderSwitchField,
14
- FormBuilderTextareaField,
15
- } from "./form-builder"
16
-
17
- type FieldBase = {
18
- id: string
19
- hidden?: boolean
20
- className?: string
21
- colSpan?: 1 | 2 | 3 | 4 | "full"
22
- }
23
-
24
- type FieldPresetOptions<TProps> = FieldBase & {
25
- props: TProps
26
- }
27
-
28
- function splitFieldOptions<TProps>(options: FieldPresetOptions<TProps>) {
29
- const { id, hidden, className, colSpan, props } = options
30
- return { base: { id, hidden, className, colSpan }, props }
31
- }
32
-
33
- function inputField<
34
- TFieldValues extends FieldValues,
35
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
36
- >(options: FieldPresetOptions<FormBuilderInputField<TFieldValues, TName>["props"]>): FormBuilderInputField<TFieldValues, TName> {
37
- const { base, props } = splitFieldOptions(options)
38
- return { ...base, type: "input", props }
39
- }
40
-
41
- function textareaField<
42
- TFieldValues extends FieldValues,
43
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
44
- >(options: FieldPresetOptions<FormBuilderTextareaField<TFieldValues, TName>["props"]>): FormBuilderTextareaField<TFieldValues, TName> {
45
- const { base, props } = splitFieldOptions(options)
46
- return { ...base, type: "textarea", props }
47
- }
48
-
49
- function selectField<
50
- TFieldValues extends FieldValues,
51
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
52
- >(options: FieldPresetOptions<FormBuilderSelectField<TFieldValues, TName>["props"]>): FormBuilderSelectField<TFieldValues, TName> {
53
- const { base, props } = splitFieldOptions(options)
54
- return { ...base, type: "select", props }
55
- }
56
-
57
- function asyncSelectField<
58
- TFieldValues extends FieldValues,
59
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
60
- >(options: FieldPresetOptions<FormBuilderAsyncSelectField<TFieldValues, TName>["props"]>): FormBuilderAsyncSelectField<TFieldValues, TName> {
61
- const { base, props } = splitFieldOptions(options)
62
- return { ...base, type: "async-select", props }
63
- }
64
-
65
- function switchField<
66
- TFieldValues extends FieldValues,
67
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
68
- >(options: FieldPresetOptions<FormBuilderSwitchField<TFieldValues, TName>["props"]>): FormBuilderSwitchField<TFieldValues, TName> {
69
- const { base, props } = splitFieldOptions(options)
70
- return { ...base, type: "switch", props }
71
- }
72
-
73
- function numberField<
74
- TFieldValues extends FieldValues,
75
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
76
- >(options: FieldPresetOptions<FormBuilderNumberField<TFieldValues, TName>["props"]>): FormBuilderNumberField<TFieldValues, TName> {
77
- const { base, props } = splitFieldOptions(options)
78
- return { ...base, type: "number", props }
79
- }
80
-
81
- function phoneField<
82
- TFieldValues extends FieldValues,
83
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
84
- >(options: FieldPresetOptions<FormBuilderPhoneField<TFieldValues, TName>["props"]>): FormBuilderPhoneField<TFieldValues, TName> {
85
- const { base, props } = splitFieldOptions(options)
86
- return { ...base, type: "phone", props }
87
- }
88
-
89
- function dateField<
90
- TFieldValues extends FieldValues,
91
- TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
92
- >(options: FieldPresetOptions<FormBuilderDateField<TFieldValues, TName>["props"]>): FormBuilderDateField<TFieldValues, TName> {
93
- const { base, props } = splitFieldOptions(options)
94
- return { ...base, type: "date", props }
95
- }
96
-
97
- function dateRangeField<
98
- TFieldValues extends FieldValues,
99
- TFromName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
100
- TToName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
101
- >(options: FieldPresetOptions<FormBuilderDateRangeField<TFieldValues, TFromName, TToName>["props"]>): FormBuilderDateRangeField<TFieldValues, TFromName, TToName> {
102
- const { base, props } = splitFieldOptions(options)
103
- return { ...base, type: "date-range", props }
104
- }
105
-
106
- function customField<TFieldValues extends FieldValues>(
107
- options: FieldBase & Pick<FormBuilderCustomField<TFieldValues>, "render">
108
- ): FormBuilderCustomField<TFieldValues> {
109
- const { id, hidden, className, colSpan, render } = options
110
- return { id, hidden, className, colSpan, type: "custom", render }
111
- }
112
-
113
- function formSection<TFieldValues extends FieldValues>(
114
- section: FormBuilderSection<TFieldValues>
115
- ): FormBuilderSection<TFieldValues> {
116
- return section
117
- }
118
-
119
- export {
120
- asyncSelectField,
121
- customField,
122
- dateField,
123
- dateRangeField,
124
- formSection,
125
- inputField,
126
- numberField,
127
- phoneField,
128
- selectField,
129
- switchField,
130
- textareaField,
131
- }
1
+ export {
2
+ asyncSelectField,
3
+ customField,
4
+ dateField,
5
+ dateRangeField,
6
+ formSection,
7
+ inputField,
8
+ numberField,
9
+ phoneField,
10
+ selectField,
11
+ switchField,
12
+ textareaField,
13
+ } from "./form-builder"
@@ -167,14 +167,109 @@ const columnsClassName: Record<1 | 2 | 3 | 4, string> = {
167
167
  4: "grid-cols-1 md:grid-cols-2 xl:grid-cols-4",
168
168
  }
169
169
 
170
- const colSpanClassName: Record<NonNullable<BaseFormBuilderField["colSpan"]>, string> = {
171
- 1: "col-span-1",
172
- 2: "md:col-span-2",
173
- 3: "xl:col-span-3",
174
- 4: "xl:col-span-4",
175
- full: "col-span-full",
176
- }
177
-
170
+ const colSpanClassName: Record<NonNullable<BaseFormBuilderField["colSpan"]>, string> = {
171
+ 1: "col-span-1",
172
+ 2: "md:col-span-2",
173
+ 3: "xl:col-span-3",
174
+ 4: "xl:col-span-4",
175
+ full: "col-span-full",
176
+ }
177
+
178
+ type FieldPresetOptions<TProps> = BaseFormBuilderField & {
179
+ props: TProps
180
+ }
181
+
182
+ function splitFieldOptions<TProps>(options: FieldPresetOptions<TProps>) {
183
+ const { id, hidden, className, colSpan, props } = options
184
+ return { base: { id, hidden, className, colSpan }, props }
185
+ }
186
+
187
+ function inputField<
188
+ TFieldValues extends FieldValues,
189
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
190
+ >(options: FieldPresetOptions<FormBuilderInputField<TFieldValues, TName>["props"]>): FormBuilderInputField<TFieldValues, TName> {
191
+ const { base, props } = splitFieldOptions(options)
192
+ return { ...base, type: "input", props }
193
+ }
194
+
195
+ function textareaField<
196
+ TFieldValues extends FieldValues,
197
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
198
+ >(options: FieldPresetOptions<FormBuilderTextareaField<TFieldValues, TName>["props"]>): FormBuilderTextareaField<TFieldValues, TName> {
199
+ const { base, props } = splitFieldOptions(options)
200
+ return { ...base, type: "textarea", props }
201
+ }
202
+
203
+ function selectField<
204
+ TFieldValues extends FieldValues,
205
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
206
+ >(options: FieldPresetOptions<FormBuilderSelectField<TFieldValues, TName>["props"]>): FormBuilderSelectField<TFieldValues, TName> {
207
+ const { base, props } = splitFieldOptions(options)
208
+ return { ...base, type: "select", props }
209
+ }
210
+
211
+ function asyncSelectField<
212
+ TFieldValues extends FieldValues,
213
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
214
+ >(options: FieldPresetOptions<FormBuilderAsyncSelectField<TFieldValues, TName>["props"]>): FormBuilderAsyncSelectField<TFieldValues, TName> {
215
+ const { base, props } = splitFieldOptions(options)
216
+ return { ...base, type: "async-select", props }
217
+ }
218
+
219
+ function switchField<
220
+ TFieldValues extends FieldValues,
221
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
222
+ >(options: FieldPresetOptions<FormBuilderSwitchField<TFieldValues, TName>["props"]>): FormBuilderSwitchField<TFieldValues, TName> {
223
+ const { base, props } = splitFieldOptions(options)
224
+ return { ...base, type: "switch", props }
225
+ }
226
+
227
+ function numberField<
228
+ TFieldValues extends FieldValues,
229
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
230
+ >(options: FieldPresetOptions<FormBuilderNumberField<TFieldValues, TName>["props"]>): FormBuilderNumberField<TFieldValues, TName> {
231
+ const { base, props } = splitFieldOptions(options)
232
+ return { ...base, type: "number", props }
233
+ }
234
+
235
+ function phoneField<
236
+ TFieldValues extends FieldValues,
237
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
238
+ >(options: FieldPresetOptions<FormBuilderPhoneField<TFieldValues, TName>["props"]>): FormBuilderPhoneField<TFieldValues, TName> {
239
+ const { base, props } = splitFieldOptions(options)
240
+ return { ...base, type: "phone", props }
241
+ }
242
+
243
+ function dateField<
244
+ TFieldValues extends FieldValues,
245
+ TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
246
+ >(options: FieldPresetOptions<FormBuilderDateField<TFieldValues, TName>["props"]>): FormBuilderDateField<TFieldValues, TName> {
247
+ const { base, props } = splitFieldOptions(options)
248
+ return { ...base, type: "date", props }
249
+ }
250
+
251
+ function dateRangeField<
252
+ TFieldValues extends FieldValues,
253
+ TFromName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
254
+ TToName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
255
+ >(options: FieldPresetOptions<FormBuilderDateRangeField<TFieldValues, TFromName, TToName>["props"]>): FormBuilderDateRangeField<TFieldValues, TFromName, TToName> {
256
+ const { base, props } = splitFieldOptions(options)
257
+ return { ...base, type: "date-range", props }
258
+ }
259
+
260
+ function customField<TFieldValues extends FieldValues>(
261
+ options: BaseFormBuilderField & Pick<FormBuilderCustomField<TFieldValues>, "render">
262
+ ): FormBuilderCustomField<TFieldValues> {
263
+ const { id, hidden, className, colSpan, render } = options
264
+ return { id, hidden, className, colSpan, type: "custom", render }
265
+ }
266
+
267
+ function formSection<TFieldValues extends FieldValues>(
268
+ section: FormBuilderSection<TFieldValues>
269
+ ): FormBuilderSection<TFieldValues> {
270
+ return section
271
+ }
272
+
178
273
  function renderFormBuilderField<TFieldValues extends FieldValues>(
179
274
  field: FormBuilderField<TFieldValues>,
180
275
  context: FormBuilderFieldRenderContext<TFieldValues>
@@ -331,4 +426,18 @@ function FormBuilder<TFieldValues extends FieldValues>({
331
426
  )
332
427
  }
333
428
 
334
- export { FormBuilder, renderFormBuilderField }
429
+ export {
430
+ FormBuilder,
431
+ asyncSelectField,
432
+ customField,
433
+ dateField,
434
+ dateRangeField,
435
+ formSection,
436
+ inputField,
437
+ numberField,
438
+ phoneField,
439
+ renderFormBuilderField,
440
+ selectField,
441
+ switchField,
442
+ textareaField,
443
+ }
@@ -1,8 +1,7 @@
1
1
  export * from './resource-page'
2
- export * from './resource-detail-page'
3
- export * from './form-builder'
4
- export * from './form-builder-presets'
5
- export * from './settings-section'
2
+ export * from './resource-detail-page'
3
+ export * from './form-builder'
4
+ export * from './settings-section'
6
5
  export * from './action-system'
7
6
  export * from './status-system'
8
7
  export * from './filter-builder'
@@ -1,4 +1,3 @@
1
1
  export * from "./resource-page"
2
2
  export * from "./resource-detail-page"
3
3
  export * from "./form-builder"
4
- export * from "./form-builder-presets"
@@ -6,28 +6,24 @@ import { cva, type VariantProps } from "class-variance-authority"
6
6
  import { cn } from "@/lib/utils"
7
7
 
8
8
  const badgeVariants = cva(
9
- "group/badge inline-flex w-fit shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-full border border-transparent font-semibold tracking-[0.01em] transition-[background-color,border-color,color,box-shadow,transform] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3!",
9
+ "group/badge inline-flex w-fit shrink-0 items-center justify-center gap-1 whitespace-nowrap rounded-full border border-transparent font-semibold tracking-[0.01em] transition-[background-color,border-color,color,box-shadow,transform] focus-visible:ring-0 has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 aria-invalid:border-destructive [&>svg]:pointer-events-none [&>svg]:size-3!",
10
10
  {
11
11
  variants: {
12
12
  variant: {
13
- default:
14
- "border-emerald-500/18 bg-emerald-500/14 text-emerald-700 shadow-none [a]:hover:bg-emerald-500/18 dark:border-emerald-400/18 dark:bg-emerald-400/16 dark:text-emerald-200",
15
- secondary:
16
- "border-border/70 bg-muted/68 text-foreground shadow-none [a]:hover:bg-muted/82 dark:bg-muted/38",
17
- destructive:
18
- "border-destructive/20 bg-destructive/10 text-destructive focus-visible:ring-destructive/20 [a]:hover:bg-destructive/14 dark:bg-destructive/16 dark:focus-visible:ring-destructive/40",
19
- outline:
20
- "border-border/72 bg-transparent text-foreground shadow-none [a]:hover:bg-muted/66 [a]:hover:text-foreground",
21
- ghost: "border-transparent bg-transparent text-muted-foreground shadow-none hover:bg-transparent hover:text-foreground",
22
- link: "border-transparent bg-transparent p-0 text-[color:var(--aui-brand-strong)] shadow-none underline-offset-4 hover:underline",
13
+ default: "",
14
+ secondary: "",
15
+ destructive: "",
16
+ outline: "",
17
+ ghost: "",
18
+ link: "border-transparent bg-transparent p-0 shadow-none underline-offset-4",
19
+ },
20
+ tone: {
21
+ neutral: "",
22
+ info: "",
23
+ success: "",
24
+ warning: "",
25
+ danger: "",
23
26
  },
24
- tone: {
25
- neutral: "",
26
- info: "border-blue-500/20 bg-blue-500/10 text-blue-700 dark:text-blue-300",
27
- success: "border-emerald-500/20 bg-emerald-500/10 text-emerald-700 dark:text-emerald-300",
28
- warning: "border-amber-500/24 bg-amber-500/12 text-amber-700 dark:text-amber-300",
29
- danger: "border-destructive/20 bg-destructive/12 text-destructive dark:bg-destructive/20",
30
- },
31
27
  size: {
32
28
  sm: "min-h-5 px-2.5 py-0.5 text-[0.64rem]",
33
29
  default: "min-h-6 px-3 py-1 text-[0.68rem]",
@@ -53,7 +49,7 @@ type BadgeProps = useRender.ComponentProps<"span"> &
53
49
  rightIcon?: React.ReactNode
54
50
  }
55
51
 
56
- function Badge({
52
+ function Badge({
57
53
  className,
58
54
  variant = "default",
59
55
  tone = "neutral",
@@ -65,22 +61,27 @@ function Badge({
65
61
  render,
66
62
  ...props
67
63
  }: BadgeProps) {
68
- return useRender({
69
- defaultTagName: "span",
70
- props: mergeProps<"span">(
71
- {
72
- className: cn(badgeVariants({ variant, tone, size, dot }), className),
73
- children: (
74
- <>
75
- {dot ? <span data-slot="badge-dot" className="size-1.5 rounded-full bg-current opacity-75" /> : null}
64
+ return useRender({
65
+ defaultTagName: "span",
66
+ props: mergeProps<"span">(
67
+ {
68
+ className: cn(badgeVariants({ variant, tone, size, dot }), className),
69
+ children: (
70
+ <>
71
+ {dot ? <span data-slot="badge-dot" className="size-1.5 rounded-full bg-current opacity-75" /> : null}
76
72
  {leftIcon ? <span data-icon="inline-start" data-slot="badge-icon" className="inline-flex shrink-0 items-center">{leftIcon}</span> : null}
77
73
  {children ? <span data-slot="badge-label">{children}</span> : null}
78
74
  {rightIcon ? <span data-icon="inline-end" data-slot="badge-icon" className="inline-flex shrink-0 items-center">{rightIcon}</span> : null}
79
- </>
80
- ),
81
- },
82
- props
83
- ),
75
+ </>
76
+ ),
77
+ } as React.HTMLAttributes<HTMLSpanElement>,
78
+ {
79
+ "data-variant": variant ?? "default",
80
+ "data-tone": tone ?? "neutral",
81
+ "data-size": size ?? "default",
82
+ } as React.HTMLAttributes<HTMLSpanElement>,
83
+ props
84
+ ),
84
85
  render,
85
86
  state: {
86
87
  slot: "badge",
@@ -5,21 +5,17 @@ import { cva, type VariantProps } from "class-variance-authority"
5
5
  import { cn } from "@/lib/utils"
6
6
 
7
7
  const buttonVariants = cva(
8
- "group/button inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent bg-clip-padding text-sm font-semibold whitespace-nowrap transition-[transform,background-color,border-color,color,box-shadow,opacity] outline-none select-none focus-visible:border-ring/60 focus-visible:ring-2 focus-visible:ring-ring/35 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:cursor-not-allowed disabled:translate-y-0 disabled:shadow-none disabled:opacity-100 aria-disabled:pointer-events-none aria-disabled:cursor-not-allowed aria-disabled:translate-y-0 aria-disabled:shadow-none aria-disabled:opacity-100 aria-invalid:border-destructive aria-invalid:ring-2 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/35 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
8
+ "group/button inline-flex shrink-0 items-center justify-center rounded-[var(--aui-control-radius,var(--radius-lg))] border border-[color:var(--aui-control-border-strong,var(--border))] bg-[color:var(--aui-control-surface,var(--background))] bg-clip-padding text-sm font-semibold text-foreground whitespace-nowrap shadow-[var(--aui-control-shadow,none)] transition-[transform,background-color,border-color,color,box-shadow,opacity] outline-none select-none hover:border-[color:var(--aui-control-hover-border,var(--ring))] hover:bg-[color:var(--aui-control-surface-hover,var(--muted))] focus-visible:ring-0 focus-visible:shadow-[var(--aui-control-shadow,none),0_0_0_1px_var(--aui-focus-ring,var(--ring)),0_0_0_5px_var(--aui-focus-ring-soft,transparent)] active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:cursor-not-allowed disabled:translate-y-0 disabled:border-[color:color-mix(in_oklch,var(--border),transparent_24%)] disabled:bg-[color:var(--aui-control-surface-disabled,var(--muted))] disabled:text-muted-foreground disabled:shadow-none disabled:opacity-100 aria-disabled:pointer-events-none aria-disabled:cursor-not-allowed aria-disabled:translate-y-0 aria-disabled:opacity-100 aria-invalid:border-destructive [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
9
9
  {
10
10
  variants: {
11
11
  variant: {
12
- default:
13
- "border-primary/20 bg-primary text-primary-foreground shadow-sm hover:-translate-y-px hover:bg-[color-mix(in_oklch,var(--primary),white_7%)] hover:shadow-md disabled:border-primary/10 disabled:bg-primary/45 disabled:text-primary-foreground/70 dark:disabled:bg-primary/34",
14
- outline:
15
- "border-border/80 bg-background text-foreground shadow-none hover:-translate-y-px hover:border-ring/38 hover:bg-accent/72 hover:text-foreground hover:shadow-sm aria-expanded:border-ring/38 aria-expanded:bg-accent/72 aria-expanded:text-foreground disabled:border-border/48 disabled:bg-muted/24 disabled:text-muted-foreground/70 dark:border-white/14 dark:bg-white/[0.045] dark:hover:bg-white/[0.08] dark:hover:text-foreground dark:disabled:bg-white/[0.035]",
16
- secondary:
17
- "border-border/70 bg-secondary text-secondary-foreground shadow-sm hover:-translate-y-px hover:border-border/86 hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)] hover:text-secondary-foreground aria-expanded:bg-secondary aria-expanded:text-secondary-foreground disabled:border-border/44 disabled:bg-muted/28 disabled:text-muted-foreground/72 dark:bg-white/[0.08] dark:hover:bg-white/[0.12] dark:disabled:bg-white/[0.035]",
18
- ghost:
19
- "border-transparent bg-transparent text-foreground/88 shadow-none hover:border-border/48 hover:bg-accent/68 hover:text-foreground aria-expanded:border-border/48 aria-expanded:bg-accent/68 aria-expanded:text-foreground disabled:text-muted-foreground/64 dark:text-foreground/86 dark:hover:bg-white/[0.075] dark:disabled:text-muted-foreground/58",
20
- destructive:
21
- "border-destructive/20 bg-destructive text-destructive-foreground shadow-sm hover:-translate-y-px hover:bg-[color-mix(in_oklch,var(--destructive),white_7%)] hover:shadow-md focus-visible:border-destructive/45 focus-visible:ring-destructive/24 disabled:border-destructive/10 disabled:bg-destructive/42 disabled:text-destructive-foreground/70 dark:focus-visible:ring-destructive/35 dark:disabled:bg-destructive/34",
22
- link: "text-primary underline-offset-4 hover:underline",
12
+ default: "border-primary bg-primary text-primary-foreground shadow-[var(--aui-button-primary-shadow,var(--aui-control-shadow,none))] hover:bg-[color:color-mix(in_oklch,var(--primary),white_10%)]",
13
+ outline: "bg-[color:var(--aui-control-surface,var(--background))] text-foreground shadow-none",
14
+ secondary: "border-border bg-secondary text-secondary-foreground",
15
+ ghost: "border-transparent bg-transparent shadow-none hover:border-[color:var(--aui-control-border-strong,var(--border))]",
16
+ destructive: "border-destructive bg-destructive text-[color:var(--aui-danger-foreground,var(--primary-foreground))] shadow-[var(--aui-button-danger-shadow,var(--aui-control-shadow,none))] hover:bg-[color:color-mix(in_oklch,var(--destructive),white_10%)]",
17
+ warning: "border-[color:color-mix(in_oklch,var(--aui-warning,var(--primary)),transparent_64%)] bg-[color:color-mix(in_oklch,var(--aui-warning,var(--primary)),transparent_82%)] text-[color:var(--aui-warning-foreground,var(--foreground))]",
18
+ link: "rounded-none border-transparent bg-transparent p-0 shadow-none underline-offset-4",
23
19
  },
24
20
  size: {
25
21
  default:
@@ -67,11 +63,13 @@ function Button({
67
63
  const isDisabled = disabled || loading
68
64
 
69
65
  return (
70
- <ButtonPrimitive
71
- data-slot="button"
72
- data-loading={loading || undefined}
73
- disabled={isDisabled}
74
- aria-busy={loading || undefined}
66
+ <ButtonPrimitive
67
+ data-slot="button"
68
+ data-variant={variant ?? "default"}
69
+ data-size={size ?? "default"}
70
+ data-loading={loading || undefined}
71
+ disabled={isDisabled}
72
+ aria-busy={loading || undefined}
75
73
  className={cn(buttonVariants({ variant, size, className }))}
76
74
  {...props}
77
75
  >
@@ -8,13 +8,11 @@ const cardVariants = cva(
8
8
  {
9
9
  variants: {
10
10
  variant: {
11
- default:
12
- "border-border/72 bg-card shadow-[0_10px_30px_rgba(15,23,42,0.05)] ring-1 ring-foreground/3",
13
- elevated:
14
- "border-border/68 bg-card shadow-[0_1px_2px_rgba(15,23,42,0.04),0_20px_46px_rgba(15,23,42,0.08)] ring-1 ring-foreground/4",
15
- outline: "border-border/72 bg-card shadow-none",
16
- soft: "border-border/40 bg-muted/28 shadow-none",
17
- ghost: "border-transparent bg-transparent shadow-none",
11
+ default: "",
12
+ elevated: "",
13
+ outline: "",
14
+ soft: "",
15
+ ghost: "border-transparent bg-transparent shadow-none ring-0",
18
16
  },
19
17
  size: {
20
18
  sm: "[--card-spacing:--spacing(4)] data-[has-footer=true]:pb-0",
@@ -26,21 +24,21 @@ const cardVariants = cva(
26
24
  default: "text-sm",
27
25
  comfortable: "text-base",
28
26
  },
29
- tone: {
30
- neutral: "",
31
- info: "border-blue-500/20 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--card),oklch(0.94_0.03_235)_32%),var(--card))]",
32
- success: "border-emerald-500/20 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--card),oklch(0.94_0.04_155)_34%),var(--card))]",
33
- warning: "border-amber-500/24 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--card),oklch(0.94_0.05_85)_34%),var(--card))]",
34
- danger: "border-destructive/24 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--card),var(--destructive)_10%),var(--card))]",
35
- },
36
- interactive: {
37
- true: "cursor-pointer hover:-translate-y-0.5 hover:border-ring/35 hover:shadow-[0_14px_34px_rgba(15,23,42,0.10)] focus-visible:outline-none focus-visible:ring-3 focus-visible:ring-ring/35",
38
- false: "",
39
- },
40
- selected: {
41
- true: "border-primary/40 ring-2 ring-primary/18",
42
- false: "",
43
- },
27
+ tone: {
28
+ neutral: "",
29
+ info: "",
30
+ success: "",
31
+ warning: "",
32
+ danger: "",
33
+ },
34
+ interactive: {
35
+ true: "cursor-pointer hover:-translate-y-0.5 focus-visible:outline-none focus-visible:ring-0",
36
+ false: "",
37
+ },
38
+ selected: {
39
+ true: "",
40
+ false: "",
41
+ },
44
42
  disabled: {
45
43
  true: "pointer-events-none opacity-55",
46
44
  false: "",
@@ -75,9 +73,12 @@ function Card({
75
73
  return (
76
74
  <div
77
75
  data-slot="card"
78
- data-size={size ?? "default"}
79
- data-interactive={interactive || undefined}
80
- data-selected={selected || undefined}
76
+ data-size={size ?? "default"}
77
+ data-variant={variant ?? "default"}
78
+ data-tone={tone ?? "neutral"}
79
+ data-density={density ?? "default"}
80
+ data-interactive={interactive || undefined}
81
+ data-selected={selected || undefined}
81
82
  data-disabled={disabled || undefined}
82
83
  aria-disabled={disabled || undefined}
83
84
  tabIndex={interactive && !disabled ? tabIndex ?? 0 : tabIndex}
@@ -41,17 +41,20 @@ function DialogContent({
41
41
  className,
42
42
  children,
43
43
  showCloseButton = true,
44
+ size = "md",
44
45
  ...props
45
46
  }: DialogPrimitive.Popup.Props & {
46
47
  showCloseButton?: boolean
48
+ size?: "xs" | "sm" | "md" | "lg" | "xl" | "full"
47
49
  }) {
48
50
  return (
49
51
  <DialogPortal>
50
52
  <DialogOverlay />
51
53
  <DialogPrimitive.Popup
52
54
  data-slot="dialog-content"
55
+ data-size={size}
53
56
  className={cn(
54
- "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-5 rounded-[var(--radius-3xl)] border border-border/72 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--popover),white_8%),var(--popover))] p-6 text-sm text-popover-foreground shadow-[0_28px_88px_color-mix(in_oklch,var(--foreground),transparent_86%)] ring-1 ring-foreground/6 backdrop-blur duration-100 outline-none sm:max-w-lg data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
57
+ "fixed top-1/2 left-1/2 z-50 grid w-full max-w-[calc(100%-2rem)] -translate-x-1/2 -translate-y-1/2 gap-5 rounded-[var(--radius-3xl)] border p-6 text-sm text-popover-foreground backdrop-blur duration-100 outline-none data-[size=xs]:sm:max-w-sm data-[size=sm]:sm:max-w-md data-[size=md]:sm:max-w-lg data-[size=lg]:sm:max-w-2xl data-[size=xl]:sm:max-w-4xl data-[size=full]:h-[min(92vh,56rem)] data-[size=full]:max-w-[min(96vw,84rem)] data-[size=full]:grid-rows-[auto_1fr] data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
55
58
  className
56
59
  )}
57
60
  {...props}
@@ -96,10 +99,10 @@ function DialogFooter({
96
99
  showCloseButton?: boolean
97
100
  }) {
98
101
  return (
99
- <div
102
+ <div
100
103
  data-slot="dialog-footer"
101
104
  className={cn(
102
- "-mx-6 -mb-6 flex flex-col-reverse gap-2 rounded-b-[var(--radius-3xl)] border-t border-border/58 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--muted),transparent_38%),color-mix(in_oklch,var(--muted),transparent_18%))] p-5 sm:flex-row sm:justify-end",
105
+ "-mx-6 -mb-6 flex flex-col-reverse gap-2 rounded-b-[var(--radius-3xl)] border-t p-5 sm:flex-row sm:justify-end",
103
106
  className
104
107
  )}
105
108
  {...props}
@@ -39,7 +39,7 @@ function DropdownMenuContent({
39
39
  >
40
40
  <MenuPrimitive.Popup
41
41
  data-slot="dropdown-menu-content"
42
- className={cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-48 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--radius-2xl)] border border-border/70 bg-[linear-gradient(180deg,color-mix(in_oklch,var(--popover),white_8%),var(--popover))] p-2 text-popover-foreground shadow-[0_18px_54px_color-mix(in_oklch,var(--foreground),transparent_88%)] ring-1 ring-foreground/6 backdrop-blur duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className)}
42
+ className={cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-48 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-[var(--radius-2xl)] border p-2 text-popover-foreground backdrop-blur duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className)}
43
43
  {...props}
44
44
  />
45
45
  </MenuPrimitive.Positioner>
@@ -86,7 +86,7 @@ function DropdownMenuItem({
86
86
  data-inset={inset}
87
87
  data-variant={variant}
88
88
  className={cn(
89
- "group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent px-3 py-2.5 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] focus:border-border/65 focus:bg-accent/65 focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-8 data-[highlighted]:border-border/58 data-[highlighted]:bg-accent/58 data-[highlighted]:text-foreground data-[highlighted]:shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 data-[variant=destructive]:focus:text-destructive dark:data-[variant=destructive]:focus:bg-destructive/20 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
89
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent px-3 py-2.5 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] data-inset:pl-8 data-[variant=destructive]:text-destructive data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 data-[variant=destructive]:*:[svg]:text-destructive",
90
90
  className
91
91
  )}
92
92
  {...props}
@@ -111,7 +111,7 @@ function DropdownMenuSubTrigger({
111
111
  data-slot="dropdown-menu-sub-trigger"
112
112
  data-inset={inset}
113
113
  className={cn(
114
- "flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent px-3 py-2.5 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] focus:border-border/65 focus:bg-accent/65 focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-8 data-popup-open:border-border/65 data-popup-open:bg-accent/65 data-popup-open:text-accent-foreground data-open:border-border/65 data-open:bg-accent/65 data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
114
+ "flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent px-3 py-2.5 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] data-inset:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
115
115
  className
116
116
  )}
117
117
  {...props}
@@ -131,10 +131,10 @@ function DropdownMenuSubContent({
131
131
  ...props
132
132
  }: React.ComponentProps<typeof DropdownMenuContent>) {
133
133
  return (
134
- <DropdownMenuContent
135
- data-slot="dropdown-menu-sub-content"
136
- className={cn("w-auto min-w-[128px] rounded-[var(--radius-2xl)] bg-[linear-gradient(180deg,color-mix(in_oklch,var(--popover),white_8%),var(--popover))] p-2 text-popover-foreground shadow-[0_18px_48px_color-mix(in_oklch,var(--foreground),transparent_88%)] ring-1 ring-foreground/6 backdrop-blur duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
137
- align={align}
134
+ <DropdownMenuContent
135
+ data-slot="dropdown-menu-sub-content"
136
+ className={cn("w-auto min-w-[128px] rounded-[var(--radius-2xl)] p-2 text-popover-foreground backdrop-blur duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className )}
137
+ align={align}
138
138
  alignOffset={alignOffset}
139
139
  side={side}
140
140
  sideOffset={sideOffset}
@@ -157,7 +157,7 @@ function DropdownMenuCheckboxItem({
157
157
  data-slot="dropdown-menu-checkbox-item"
158
158
  data-inset={inset}
159
159
  className={cn(
160
- "relative flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent py-2.5 pr-9 pl-3 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] focus:border-border/65 focus:bg-accent/65 focus:text-accent-foreground focus:**:text-accent-foreground data-[highlighted]:border-border/58 data-[highlighted]:bg-accent/58 data-[highlighted]:text-foreground data-[highlighted]:shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] data-inset:pl-8 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
160
+ "relative flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent py-2.5 pr-9 pl-3 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] data-inset:pl-8 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
161
161
  className
162
162
  )}
163
163
  checked={checked}
@@ -199,7 +199,7 @@ function DropdownMenuRadioItem({
199
199
  data-slot="dropdown-menu-radio-item"
200
200
  data-inset={inset}
201
201
  className={cn(
202
- "relative flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent py-2.5 pr-9 pl-3 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] focus:border-border/65 focus:bg-accent/65 focus:text-accent-foreground focus:**:text-accent-foreground data-[highlighted]:border-border/58 data-[highlighted]:bg-accent/58 data-[highlighted]:text-foreground data-[highlighted]:shadow-[inset_0_1px_0_rgba(255,255,255,0.08)] data-inset:pl-8 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
202
+ "relative flex cursor-default items-center gap-2 rounded-[min(var(--radius-xl),16px)] border border-transparent py-2.5 pr-9 pl-3 text-sm outline-hidden select-none transition-[background-color,border-color,color,box-shadow] data-inset:pl-8 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
203
203
  className
204
204
  )}
205
205
  {...props}
@@ -13,7 +13,7 @@ function InputPrimitive({ className, type, ...props }: InputPrimitiveProps) {
13
13
  type={type}
14
14
  data-slot="input"
15
15
  className={cn(
16
- "h-11 w-full min-w-0 rounded-[min(var(--radius-xl),18px)] border border-border/66 bg-background px-4 py-2.5 text-sm text-foreground shadow-[0_1px_2px_rgba(15,23,42,0.02)] transition-[background-color,border-color,box-shadow,color] outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground/68 hover:border-border/82 hover:bg-background focus-visible:border-ring/48 focus-visible:bg-background focus-visible:shadow-[0_0_0_1px_color-mix(in_oklch,var(--ring),transparent_56%),0_0_0_5px_color-mix(in_oklch,var(--ring),transparent_84%)] focus-visible:ring-0 disabled:pointer-events-none disabled:cursor-not-allowed disabled:border-border/48 disabled:bg-muted/22 disabled:text-muted-foreground/72 disabled:shadow-none disabled:opacity-100 read-only:border-border/58 read-only:bg-muted/16 read-only:text-foreground/84 read-only:shadow-none aria-invalid:border-destructive/60 aria-invalid:shadow-[0_0_0_1px_color-mix(in_oklch,var(--destructive),transparent_64%),0_0_0_5px_color-mix(in_oklch,var(--destructive),transparent_88%)] dark:border-white/10 dark:bg-white/[0.045] dark:hover:border-white/14 dark:hover:bg-white/[0.06] dark:focus-visible:bg-white/[0.07] dark:disabled:bg-white/[0.032] dark:read-only:bg-white/[0.028] dark:aria-invalid:border-destructive/50 dark:aria-invalid:shadow-[0_0_0_1px_color-mix(in_oklch,var(--destructive),transparent_68%),0_0_0_5px_color-mix(in_oklch,var(--destructive),transparent_88%)]",
16
+ "h-11 w-full min-w-0 rounded-[var(--aui-control-radius,var(--radius-xl))] border border-[color:var(--aui-control-border-strong,var(--input))] bg-[color:var(--aui-control-surface,var(--background))] px-4 py-2.5 text-sm text-foreground shadow-[var(--aui-control-shadow,none)] transition-[background-color,border-color,box-shadow,color] outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground/72 hover:border-[color:var(--aui-control-hover-border,var(--ring))] hover:bg-[color:var(--aui-control-surface-hover,var(--background))] focus-visible:border-[color:var(--ring)] focus-visible:ring-0 focus-visible:shadow-[var(--aui-control-shadow,none),0_0_0_1px_var(--aui-focus-ring,var(--ring)),0_0_0_5px_var(--aui-focus-ring-soft,transparent)] disabled:pointer-events-none disabled:cursor-not-allowed disabled:border-[color:color-mix(in_oklch,var(--border),transparent_18%)] disabled:bg-[color:var(--aui-control-surface-disabled,var(--muted))] disabled:opacity-100 read-only:bg-[color:var(--aui-control-surface-readonly,var(--muted))]",
17
17
  className
18
18
  )}
19
19
  {...props}