@auto-engineer/generate-react-client 1.64.0 → 1.66.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.
- package/CHANGELOG.md +140 -0
- package/dist/starter/.storybook/main.ts +17 -22
- package/dist/starter/.storybook/manager-head.html +31 -31
- package/dist/starter/.storybook/manager.ts +133 -133
- package/dist/starter/.storybook/preview-head.html +12 -12
- package/dist/starter/.storybook/preview.tsx +79 -79
- package/dist/starter/biome.json +126 -0
- package/dist/starter/codegen.ts +11 -11
- package/dist/starter/components.json +27 -27
- package/dist/starter/package.json +86 -80
- package/dist/starter/public/mockServiceWorker.js +261 -261
- package/dist/starter/scripts/build-component-db.ts +17 -20
- package/dist/starter/src/App.tsx +15 -17
- package/dist/starter/src/components/ui/Accordion.stories.tsx +35 -35
- package/dist/starter/src/components/ui/Accordion.tsx +33 -33
- package/dist/starter/src/components/ui/Alert.stories.tsx +15 -15
- package/dist/starter/src/components/ui/Alert.tsx +32 -32
- package/dist/starter/src/components/ui/AlertDialog.stories.tsx +50 -50
- package/dist/starter/src/components/ui/AlertDialog.tsx +114 -115
- package/dist/starter/src/components/ui/AspectRatio.stories.tsx +20 -20
- package/dist/starter/src/components/ui/AspectRatio.tsx +1 -1
- package/dist/starter/src/components/ui/Avatar.stories.tsx +27 -27
- package/dist/starter/src/components/ui/Avatar.tsx +63 -63
- package/dist/starter/src/components/ui/Badge.stories.tsx +14 -14
- package/dist/starter/src/components/ui/Badge.tsx +27 -27
- package/dist/starter/src/components/ui/Breadcrumb.stories.tsx +38 -38
- package/dist/starter/src/components/ui/Breadcrumb.tsx +63 -62
- package/dist/starter/src/components/ui/Button.stories.tsx +55 -55
- package/dist/starter/src/components/ui/Button.tsx +49 -49
- package/dist/starter/src/components/ui/ButtonGroup.stories.tsx +17 -17
- package/dist/starter/src/components/ui/ButtonGroup.tsx +52 -53
- package/dist/starter/src/components/ui/Calendar.stories.tsx +20 -19
- package/dist/starter/src/components/ui/Calendar.tsx +142 -143
- package/dist/starter/src/components/ui/Card.stories.tsx +29 -29
- package/dist/starter/src/components/ui/Card.tsx +31 -31
- package/dist/starter/src/components/ui/Carousel.stories.tsx +41 -41
- package/dist/starter/src/components/ui/Carousel.tsx +171 -172
- package/dist/starter/src/components/ui/Chart.stories.tsx +21 -21
- package/dist/starter/src/components/ui/Chart.tsx +244 -247
- package/dist/starter/src/components/ui/Checkbox.stories.tsx +11 -11
- package/dist/starter/src/components/ui/Checkbox.tsx +18 -18
- package/dist/starter/src/components/ui/Collapsible.stories.tsx +40 -40
- package/dist/starter/src/components/ui/Collapsible.tsx +3 -3
- package/dist/starter/src/components/ui/Combobox.stories.tsx +48 -48
- package/dist/starter/src/components/ui/Combobox.tsx +204 -205
- package/dist/starter/src/components/ui/Command.stories.tsx +55 -55
- package/dist/starter/src/components/ui/Command.tsx +102 -103
- package/dist/starter/src/components/ui/ContextMenu.stories.tsx +52 -52
- package/dist/starter/src/components/ui/ContextMenu.tsx +151 -151
- package/dist/starter/src/components/ui/DesignSystem-Colors.stories.tsx +92 -92
- package/dist/starter/src/components/ui/DesignSystem-Layout.stories.tsx +139 -139
- package/dist/starter/src/components/ui/DesignSystem-Overview.stories.tsx +676 -657
- package/dist/starter/src/components/ui/DesignSystem-Typography.stories.tsx +59 -59
- package/dist/starter/src/components/ui/Dialog.stories.tsx +56 -56
- package/dist/starter/src/components/ui/Dialog.tsx +97 -98
- package/dist/starter/src/components/ui/Direction.stories.tsx +20 -20
- package/dist/starter/src/components/ui/Direction.tsx +7 -7
- package/dist/starter/src/components/ui/Drawer.stories.tsx +54 -54
- package/dist/starter/src/components/ui/Drawer.tsx +70 -70
- package/dist/starter/src/components/ui/DropdownMenu.stories.tsx +58 -58
- package/dist/starter/src/components/ui/DropdownMenu.tsx +157 -157
- package/dist/starter/src/components/ui/Empty.stories.tsx +22 -22
- package/dist/starter/src/components/ui/Empty.tsx +58 -58
- package/dist/starter/src/components/ui/Field.stories.tsx +31 -31
- package/dist/starter/src/components/ui/Field.tsx +180 -181
- package/dist/starter/src/components/ui/Form.stories.tsx +29 -29
- package/dist/starter/src/components/ui/Form.tsx +93 -96
- package/dist/starter/src/components/ui/HoverCard.stories.tsx +34 -34
- package/dist/starter/src/components/ui/HoverCard.tsx +21 -21
- package/dist/starter/src/components/ui/Input.stories.tsx +18 -18
- package/dist/starter/src/components/ui/Input.tsx +14 -14
- package/dist/starter/src/components/ui/InputGroup.stories.tsx +34 -34
- package/dist/starter/src/components/ui/InputGroup.tsx +110 -111
- package/dist/starter/src/components/ui/InputOTP.stories.tsx +28 -28
- package/dist/starter/src/components/ui/InputOTP.tsx +43 -43
- package/dist/starter/src/components/ui/Item.stories.tsx +45 -45
- package/dist/starter/src/components/ui/Item.tsx +113 -114
- package/dist/starter/src/components/ui/Kbd.stories.tsx +31 -31
- package/dist/starter/src/components/ui/Kbd.tsx +11 -11
- package/dist/starter/src/components/ui/Label.stories.tsx +62 -62
- package/dist/starter/src/components/ui/Label.tsx +26 -25
- package/dist/starter/src/components/ui/Menubar.stories.tsx +62 -62
- package/dist/starter/src/components/ui/Menubar.tsx +173 -173
- package/dist/starter/src/components/ui/NativeSelect.stories.tsx +26 -26
- package/dist/starter/src/components/ui/NativeSelect.tsx +29 -29
- package/dist/starter/src/components/ui/NavigationMenu.stories.tsx +64 -64
- package/dist/starter/src/components/ui/NavigationMenu.tsx +103 -103
- package/dist/starter/src/components/ui/Pagination.stories.tsx +61 -61
- package/dist/starter/src/components/ui/Pagination.tsx +69 -71
- package/dist/starter/src/components/ui/Popover.stories.tsx +38 -38
- package/dist/starter/src/components/ui/Popover.tsx +25 -25
- package/dist/starter/src/components/ui/Progress.stories.tsx +9 -9
- package/dist/starter/src/components/ui/Progress.tsx +14 -14
- package/dist/starter/src/components/ui/RadioGroup.stories.tsx +35 -35
- package/dist/starter/src/components/ui/RadioGroup.tsx +19 -19
- package/dist/starter/src/components/ui/Resizable.stories.tsx +54 -54
- package/dist/starter/src/components/ui/Resizable.tsx +29 -29
- package/dist/starter/src/components/ui/ScrollArea.stories.tsx +27 -27
- package/dist/starter/src/components/ui/ScrollArea.tsx +34 -34
- package/dist/starter/src/components/ui/Select.stories.tsx +43 -43
- package/dist/starter/src/components/ui/Select.tsx +120 -120
- package/dist/starter/src/components/ui/Separator.stories.tsx +27 -27
- package/dist/starter/src/components/ui/Separator.tsx +17 -17
- package/dist/starter/src/components/ui/Sheet.stories.tsx +53 -53
- package/dist/starter/src/components/ui/Sheet.tsx +69 -69
- package/dist/starter/src/components/ui/Sidebar.stories.tsx +77 -77
- package/dist/starter/src/components/ui/Sidebar.tsx +563 -564
- package/dist/starter/src/components/ui/Skeleton.stories.tsx +25 -25
- package/dist/starter/src/components/ui/Skeleton.tsx +1 -1
- package/dist/starter/src/components/ui/Slider.stories.tsx +5 -5
- package/dist/starter/src/components/ui/Slider.tsx +45 -44
- package/dist/starter/src/components/ui/Sonner.stories.tsx +32 -32
- package/dist/starter/src/components/ui/Sonner.tsx +23 -23
- package/dist/starter/src/components/ui/Spinner.stories.tsx +8 -8
- package/dist/starter/src/components/ui/Spinner.tsx +1 -1
- package/dist/starter/src/components/ui/Switch.stories.tsx +16 -17
- package/dist/starter/src/components/ui/Switch.tsx +24 -24
- package/dist/starter/src/components/ui/Table.stories.tsx +50 -50
- package/dist/starter/src/components/ui/Table.tsx +45 -45
- package/dist/starter/src/components/ui/Tabs.stories.tsx +39 -39
- package/dist/starter/src/components/ui/Tabs.tsx +47 -47
- package/dist/starter/src/components/ui/Textarea.stories.tsx +9 -9
- package/dist/starter/src/components/ui/Textarea.tsx +11 -11
- package/dist/starter/src/components/ui/Toast.stories.tsx +77 -77
- package/dist/starter/src/components/ui/Toast.tsx +75 -75
- package/dist/starter/src/components/ui/Toaster.tsx +17 -19
- package/dist/starter/src/components/ui/Toggle.stories.tsx +20 -20
- package/dist/starter/src/components/ui/Toggle.tsx +26 -26
- package/dist/starter/src/components/ui/ToggleGroup.stories.tsx +41 -41
- package/dist/starter/src/components/ui/ToggleGroup.tsx +61 -62
- package/dist/starter/src/components/ui/Tooltip.stories.tsx +26 -26
- package/dist/starter/src/components/ui/Tooltip.tsx +24 -24
- package/dist/starter/src/gql/execute.ts +1 -1
- package/dist/starter/src/gql/fragment-masking.ts +1 -1
- package/dist/starter/src/gql/graphql.ts +3 -0
- package/dist/starter/src/hooks/use-mobile.ts +11 -11
- package/dist/starter/src/hooks/use-toast.ts +135 -135
- package/dist/starter/src/index.css +105 -105
- package/dist/starter/src/lib/utils.ts +1 -1
- package/dist/starter/src/main.tsx +4 -1
- package/dist/starter/tsconfig.app.json +24 -24
- package/dist/starter/tsconfig.json +8 -8
- package/dist/starter/vite.config.ts +38 -37
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import * as React from 'react';
|
|
4
3
|
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
|
|
5
4
|
import { DropdownMenu as DropdownMenuPrimitive } from 'radix-ui';
|
|
5
|
+
import type * as React from 'react';
|
|
6
6
|
|
|
7
7
|
import { cn } from '@/lib/utils';
|
|
8
8
|
|
|
9
9
|
/** Action menu triggered by a button click. Supports submenus, checkbox/radio items, and keyboard shortcuts. */
|
|
10
10
|
function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
|
11
|
-
|
|
11
|
+
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
/** Renders dropdown menu content into a React portal. */
|
|
15
15
|
function DropdownMenuPortal({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
|
16
|
-
|
|
16
|
+
return <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
/** Button or element that toggles the dropdown menu open/closed. */
|
|
20
20
|
function DropdownMenuTrigger({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
|
|
21
|
-
|
|
21
|
+
return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
/** The positioned popup container for dropdown menu items. Portals to the document body. */
|
|
25
25
|
function DropdownMenuContent({
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
className,
|
|
27
|
+
sideOffset = 4,
|
|
28
|
+
...props
|
|
29
29
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
30
|
+
return (
|
|
31
|
+
<DropdownMenuPrimitive.Portal>
|
|
32
|
+
<DropdownMenuPrimitive.Content
|
|
33
|
+
data-slot="dropdown-menu-content"
|
|
34
|
+
sideOffset={sideOffset}
|
|
35
|
+
className={cn(
|
|
36
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md',
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
</DropdownMenuPrimitive.Portal>
|
|
42
|
+
);
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
/** Groups related dropdown menu items for accessibility. */
|
|
46
46
|
function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
|
47
|
-
|
|
47
|
+
return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
|
48
48
|
}
|
|
49
49
|
|
|
50
50
|
/**
|
|
@@ -52,188 +52,188 @@ function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMen
|
|
|
52
52
|
* Use variant="destructive" for dangerous actions like delete or logout.
|
|
53
53
|
*/
|
|
54
54
|
function DropdownMenuItem({
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
className,
|
|
56
|
+
/** Adds left padding to align with items that have icons or indicators. */
|
|
57
|
+
inset,
|
|
58
|
+
/** Use "destructive" for dangerous actions. */
|
|
59
|
+
variant = 'default',
|
|
60
|
+
...props
|
|
61
61
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
inset?: boolean;
|
|
63
|
+
variant?: 'default' | 'destructive';
|
|
64
64
|
}) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
65
|
+
return (
|
|
66
|
+
<DropdownMenuPrimitive.Item
|
|
67
|
+
data-slot="dropdown-menu-item"
|
|
68
|
+
data-inset={inset}
|
|
69
|
+
data-variant={variant}
|
|
70
|
+
className={cn(
|
|
71
|
+
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
72
|
+
className,
|
|
73
|
+
)}
|
|
74
|
+
{...props}
|
|
75
|
+
/>
|
|
76
|
+
);
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
/** A toggleable checkbox item within the dropdown menu. Shows a check indicator when active. */
|
|
80
80
|
function DropdownMenuCheckboxItem({
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
className,
|
|
82
|
+
children,
|
|
83
|
+
checked,
|
|
84
|
+
...props
|
|
85
85
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
86
|
+
return (
|
|
87
|
+
<DropdownMenuPrimitive.CheckboxItem
|
|
88
|
+
data-slot="dropdown-menu-checkbox-item"
|
|
89
|
+
className={cn(
|
|
90
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
91
|
+
className,
|
|
92
|
+
)}
|
|
93
|
+
checked={checked}
|
|
94
|
+
{...props}
|
|
95
|
+
>
|
|
96
|
+
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
97
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
98
|
+
<CheckIcon className="size-4" />
|
|
99
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
100
|
+
</span>
|
|
101
|
+
{children}
|
|
102
|
+
</DropdownMenuPrimitive.CheckboxItem>
|
|
103
|
+
);
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
/** Groups radio items for single-selection within the dropdown menu. */
|
|
107
107
|
function DropdownMenuRadioGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
|
|
108
|
-
|
|
108
|
+
return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/** A radio-selectable item within a DropdownMenuRadioGroup. Shows a dot indicator when selected. */
|
|
112
112
|
function DropdownMenuRadioItem({
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
113
|
+
className,
|
|
114
|
+
children,
|
|
115
|
+
...props
|
|
116
116
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
117
|
+
return (
|
|
118
|
+
<DropdownMenuPrimitive.RadioItem
|
|
119
|
+
data-slot="dropdown-menu-radio-item"
|
|
120
|
+
className={cn(
|
|
121
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
122
|
+
className,
|
|
123
|
+
)}
|
|
124
|
+
{...props}
|
|
125
|
+
>
|
|
126
|
+
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
127
|
+
<DropdownMenuPrimitive.ItemIndicator>
|
|
128
|
+
<CircleIcon className="size-2 fill-current" />
|
|
129
|
+
</DropdownMenuPrimitive.ItemIndicator>
|
|
130
|
+
</span>
|
|
131
|
+
{children}
|
|
132
|
+
</DropdownMenuPrimitive.RadioItem>
|
|
133
|
+
);
|
|
134
134
|
}
|
|
135
135
|
|
|
136
136
|
/** Non-interactive label within a dropdown menu, used for section headings. */
|
|
137
137
|
function DropdownMenuLabel({
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
138
|
+
className,
|
|
139
|
+
inset,
|
|
140
|
+
...props
|
|
141
141
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
|
|
142
|
-
|
|
142
|
+
inset?: boolean;
|
|
143
143
|
}) {
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
144
|
+
return (
|
|
145
|
+
<DropdownMenuPrimitive.Label
|
|
146
|
+
data-slot="dropdown-menu-label"
|
|
147
|
+
data-inset={inset}
|
|
148
|
+
className={cn('px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', className)}
|
|
149
|
+
{...props}
|
|
150
|
+
/>
|
|
151
|
+
);
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
/** Visual divider between groups of dropdown menu items. */
|
|
155
155
|
function DropdownMenuSeparator({ className, ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
156
|
+
return (
|
|
157
|
+
<DropdownMenuPrimitive.Separator
|
|
158
|
+
data-slot="dropdown-menu-separator"
|
|
159
|
+
className={cn('bg-border -mx-1 my-1 h-px', className)}
|
|
160
|
+
{...props}
|
|
161
|
+
/>
|
|
162
|
+
);
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
/** Displays a keyboard shortcut hint aligned to the right side of a dropdown menu item. */
|
|
166
166
|
function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
167
|
+
return (
|
|
168
|
+
<span
|
|
169
|
+
data-slot="dropdown-menu-shortcut"
|
|
170
|
+
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
|
171
|
+
{...props}
|
|
172
|
+
/>
|
|
173
|
+
);
|
|
174
174
|
}
|
|
175
175
|
|
|
176
176
|
/** Container for a submenu within the dropdown menu. */
|
|
177
177
|
function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
|
178
|
-
|
|
178
|
+
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
|
|
179
179
|
}
|
|
180
180
|
|
|
181
181
|
/** Menu item that opens a nested submenu on hover or keyboard navigation. Shows a chevron indicator. */
|
|
182
182
|
function DropdownMenuSubTrigger({
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
className,
|
|
184
|
+
inset,
|
|
185
|
+
children,
|
|
186
|
+
...props
|
|
187
187
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
188
|
-
|
|
188
|
+
inset?: boolean;
|
|
189
189
|
}) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
190
|
+
return (
|
|
191
|
+
<DropdownMenuPrimitive.SubTrigger
|
|
192
|
+
data-slot="dropdown-menu-sub-trigger"
|
|
193
|
+
data-inset={inset}
|
|
194
|
+
className={cn(
|
|
195
|
+
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
196
|
+
className,
|
|
197
|
+
)}
|
|
198
|
+
{...props}
|
|
199
|
+
>
|
|
200
|
+
{children}
|
|
201
|
+
<ChevronRightIcon className="ml-auto size-4" />
|
|
202
|
+
</DropdownMenuPrimitive.SubTrigger>
|
|
203
|
+
);
|
|
204
204
|
}
|
|
205
205
|
|
|
206
206
|
/** Popup content for a nested submenu. */
|
|
207
207
|
function DropdownMenuSubContent({
|
|
208
|
-
|
|
209
|
-
|
|
208
|
+
className,
|
|
209
|
+
...props
|
|
210
210
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
211
|
+
return (
|
|
212
|
+
<DropdownMenuPrimitive.SubContent
|
|
213
|
+
data-slot="dropdown-menu-sub-content"
|
|
214
|
+
className={cn(
|
|
215
|
+
'bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 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 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg',
|
|
216
|
+
className,
|
|
217
|
+
)}
|
|
218
|
+
{...props}
|
|
219
|
+
/>
|
|
220
|
+
);
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
export {
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
224
|
+
DropdownMenu,
|
|
225
|
+
DropdownMenuPortal,
|
|
226
|
+
DropdownMenuTrigger,
|
|
227
|
+
DropdownMenuContent,
|
|
228
|
+
DropdownMenuGroup,
|
|
229
|
+
DropdownMenuLabel,
|
|
230
|
+
DropdownMenuItem,
|
|
231
|
+
DropdownMenuCheckboxItem,
|
|
232
|
+
DropdownMenuRadioGroup,
|
|
233
|
+
DropdownMenuRadioItem,
|
|
234
|
+
DropdownMenuSeparator,
|
|
235
|
+
DropdownMenuShortcut,
|
|
236
|
+
DropdownMenuSub,
|
|
237
|
+
DropdownMenuSubTrigger,
|
|
238
|
+
DropdownMenuSubContent,
|
|
239
239
|
};
|
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
import type { Meta, StoryObj } from '@storybook/react-vite';
|
|
2
|
-
import { Empty, EmptyHeader, EmptyTitle, EmptyDescription, EmptyMedia } from '@/components/ui/Empty';
|
|
3
2
|
import { InboxIcon } from 'lucide-react';
|
|
3
|
+
import { Empty, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle } from '@/components/ui/Empty';
|
|
4
4
|
|
|
5
5
|
const meta: Meta<typeof Empty> = {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
title: 'UI Components/Empty',
|
|
7
|
+
component: Empty,
|
|
8
8
|
};
|
|
9
9
|
export default meta;
|
|
10
10
|
type Story = StoryObj<typeof Empty>;
|
|
11
11
|
|
|
12
12
|
/** Shows a basic empty state with a title and description text. */
|
|
13
13
|
export const Default: Story = {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
render: () => (
|
|
15
|
+
<Empty>
|
|
16
|
+
<EmptyHeader>
|
|
17
|
+
<EmptyTitle>No results found</EmptyTitle>
|
|
18
|
+
<EmptyDescription>Try adjusting your search or filter to find what you are looking for.</EmptyDescription>
|
|
19
|
+
</EmptyHeader>
|
|
20
|
+
</Empty>
|
|
21
|
+
),
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
/** Shows an empty state with a styled icon container above the title and description. */
|
|
25
25
|
export const WithIcon: Story = {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
render: () => (
|
|
27
|
+
<Empty>
|
|
28
|
+
<EmptyHeader>
|
|
29
|
+
<EmptyMedia variant="icon">
|
|
30
|
+
<InboxIcon />
|
|
31
|
+
</EmptyMedia>
|
|
32
|
+
<EmptyTitle>Your inbox is empty</EmptyTitle>
|
|
33
|
+
<EmptyDescription>New messages will appear here when you receive them.</EmptyDescription>
|
|
34
|
+
</EmptyHeader>
|
|
35
|
+
</Empty>
|
|
36
|
+
),
|
|
37
37
|
};
|
|
@@ -8,42 +8,42 @@ import { cn } from '@/lib/utils';
|
|
|
8
8
|
* to build structured empty state layouts with icons and call-to-action areas.
|
|
9
9
|
*/
|
|
10
10
|
function Empty({ className, ...props }: React.ComponentProps<'div'>) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
11
|
+
return (
|
|
12
|
+
<div
|
|
13
|
+
data-slot="empty"
|
|
14
|
+
className={cn(
|
|
15
|
+
'flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12',
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
/** Container for the title, description, and optional media in an empty state. */
|
|
24
24
|
function EmptyHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
25
|
+
return (
|
|
26
|
+
<div
|
|
27
|
+
data-slot="empty-header"
|
|
28
|
+
className={cn('flex max-w-sm flex-col items-center gap-2 text-center', className)}
|
|
29
|
+
{...props}
|
|
30
|
+
/>
|
|
31
|
+
);
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const emptyMediaVariants = cva(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
35
|
+
'flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
36
|
+
{
|
|
37
|
+
variants: {
|
|
38
|
+
variant: {
|
|
39
|
+
default: 'bg-transparent',
|
|
40
|
+
icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
defaultVariants: {
|
|
44
|
+
variant: 'default',
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
47
|
);
|
|
48
48
|
|
|
49
49
|
/**
|
|
@@ -51,48 +51,48 @@ const emptyMediaVariants = cva(
|
|
|
51
51
|
* Use variant="icon" for a styled icon container with a muted background.
|
|
52
52
|
*/
|
|
53
53
|
function EmptyMedia({
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
54
|
+
className,
|
|
55
|
+
variant = 'default',
|
|
56
|
+
...props
|
|
57
57
|
}: React.ComponentProps<'div'> & VariantProps<typeof emptyMediaVariants>) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
58
|
+
return (
|
|
59
|
+
<div
|
|
60
|
+
data-slot="empty-icon"
|
|
61
|
+
data-variant={variant}
|
|
62
|
+
className={cn(emptyMediaVariants({ variant, className }))}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
68
|
/** Title text for the empty state message. */
|
|
69
69
|
function EmptyTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
70
|
-
|
|
70
|
+
return <div data-slot="empty-title" className={cn('text-lg font-medium tracking-tight', className)} {...props} />;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
/** Descriptive text explaining why the content is empty or what the user can do. */
|
|
74
74
|
function EmptyDescription({ className, ...props }: React.ComponentProps<'p'>) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
75
|
+
return (
|
|
76
|
+
<div
|
|
77
|
+
data-slot="empty-description"
|
|
78
|
+
className={cn(
|
|
79
|
+
'text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4',
|
|
80
|
+
className,
|
|
81
|
+
)}
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
);
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
/** Container for action buttons or additional content below the empty state message. */
|
|
88
88
|
function EmptyContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
89
|
+
return (
|
|
90
|
+
<div
|
|
91
|
+
data-slot="empty-content"
|
|
92
|
+
className={cn('flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance', className)}
|
|
93
|
+
{...props}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
98
|
export { Empty, EmptyHeader, EmptyTitle, EmptyDescription, EmptyContent, EmptyMedia };
|