create-cs-object 0.1.1 → 0.1.3
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/README.md +47 -2
- package/dist/cli.js +29 -2
- package/package.json +5 -2
- package/template/.gitattributes +2 -0
- package/template/AGENTS.md +11 -2
- package/template/README.md +60 -2
- package/template/authoring.md +247 -18
- package/template/components.json +25 -0
- package/template/gitignore +1 -0
- package/template/index.html +12 -0
- package/template/references/README.md +134 -0
- package/template/reports.json +8 -0
- package/template/scripts/dev.ts +104 -33
- package/template/scripts/reports.ts +24 -0
- package/template/src/App.tsx +681 -0
- package/template/src/components/theme-provider.tsx +230 -0
- package/template/src/components/ui/badge.tsx +51 -0
- package/template/src/components/ui/button.tsx +55 -0
- package/template/src/components/ui/card.tsx +102 -0
- package/template/src/components/ui/dropdown-menu.tsx +274 -0
- package/template/src/components/ui/input.tsx +19 -0
- package/template/src/components/ui/label.tsx +17 -0
- package/template/src/components/ui/separator.tsx +22 -0
- package/template/src/components/ui/sheet.tsx +137 -0
- package/template/src/hooks/use-mobile.ts +19 -0
- package/template/src/index.css +131 -0
- package/template/src/lib/utils.ts +1 -0
- package/template/src/main.tsx +9 -0
- package/template/tsconfig.app.json +29 -0
- package/template/tsconfig.json +12 -0
- package/template/tsconfig.node.json +24 -0
- package/template/vite.config.ts +144 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import { Menu as MenuPrimitive } from '@base-ui/react/menu';
|
|
2
|
+
import { ArrowRight01Icon, Tick02Icon } from '@hugeicons/core-free-icons';
|
|
3
|
+
import { HugeiconsIcon } from '@hugeicons/react';
|
|
4
|
+
import { cn } from 'cn';
|
|
5
|
+
import type * as React from 'react';
|
|
6
|
+
|
|
7
|
+
function DropdownMenu({ ...props }: MenuPrimitive.Root.Props) {
|
|
8
|
+
return <MenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function DropdownMenuPortal({ ...props }: MenuPrimitive.Portal.Props) {
|
|
12
|
+
return <MenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function DropdownMenuTrigger({ ...props }: MenuPrimitive.Trigger.Props) {
|
|
16
|
+
return <MenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function DropdownMenuContent({
|
|
20
|
+
align = 'start',
|
|
21
|
+
alignOffset = 0,
|
|
22
|
+
side = 'bottom',
|
|
23
|
+
sideOffset = 4,
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: MenuPrimitive.Popup.Props &
|
|
27
|
+
Pick<
|
|
28
|
+
MenuPrimitive.Positioner.Props,
|
|
29
|
+
'align' | 'alignOffset' | 'side' | 'sideOffset'
|
|
30
|
+
>) {
|
|
31
|
+
return (
|
|
32
|
+
<MenuPrimitive.Portal>
|
|
33
|
+
<MenuPrimitive.Positioner
|
|
34
|
+
className="isolate z-[70] outline-none"
|
|
35
|
+
align={align}
|
|
36
|
+
alignOffset={alignOffset}
|
|
37
|
+
side={side}
|
|
38
|
+
sideOffset={sideOffset}
|
|
39
|
+
>
|
|
40
|
+
<MenuPrimitive.Popup
|
|
41
|
+
data-slot="dropdown-menu-content"
|
|
42
|
+
className={cn(
|
|
43
|
+
'z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-none text-popover-foreground shadow-md ring-1 ring-foreground/10 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 animate-none! relative bg-popover/70 before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:rounded-[inherit] before:backdrop-blur-2xl before:backdrop-saturate-150 **:data-[slot$=-item]:focus:bg-foreground/10 **:data-[slot$=-item]:data-highlighted:bg-foreground/10 **:data-[slot$=-separator]:bg-foreground/5 **:data-[slot$=-trigger]:focus:bg-foreground/10 **:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! **:data-[variant=destructive]:focus:bg-foreground/10! **:data-[variant=destructive]:text-accent-foreground! **:data-[variant=destructive]:**:text-accent-foreground!',
|
|
44
|
+
className,
|
|
45
|
+
)}
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
</MenuPrimitive.Positioner>
|
|
49
|
+
</MenuPrimitive.Portal>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function DropdownMenuGroup({ ...props }: MenuPrimitive.Group.Props) {
|
|
54
|
+
return <MenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function DropdownMenuLabel({
|
|
58
|
+
className,
|
|
59
|
+
inset,
|
|
60
|
+
...props
|
|
61
|
+
}: MenuPrimitive.GroupLabel.Props & {
|
|
62
|
+
inset?: boolean;
|
|
63
|
+
}) {
|
|
64
|
+
return (
|
|
65
|
+
<MenuPrimitive.GroupLabel
|
|
66
|
+
data-slot="dropdown-menu-label"
|
|
67
|
+
data-inset={inset}
|
|
68
|
+
className={cn(
|
|
69
|
+
'px-2 py-2 text-xs text-muted-foreground data-inset:pl-7',
|
|
70
|
+
className,
|
|
71
|
+
)}
|
|
72
|
+
{...props}
|
|
73
|
+
/>
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function DropdownMenuItem({
|
|
78
|
+
className,
|
|
79
|
+
inset,
|
|
80
|
+
variant = 'default',
|
|
81
|
+
...props
|
|
82
|
+
}: MenuPrimitive.Item.Props & {
|
|
83
|
+
inset?: boolean;
|
|
84
|
+
variant?: 'default' | 'destructive';
|
|
85
|
+
}) {
|
|
86
|
+
return (
|
|
87
|
+
<MenuPrimitive.Item
|
|
88
|
+
data-slot="dropdown-menu-item"
|
|
89
|
+
data-inset={inset}
|
|
90
|
+
data-variant={variant}
|
|
91
|
+
className={cn(
|
|
92
|
+
"group/dropdown-menu-item relative flex cursor-default items-center gap-2 rounded-none px-2 py-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 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",
|
|
93
|
+
className,
|
|
94
|
+
)}
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function DropdownMenuSub({ ...props }: MenuPrimitive.SubmenuRoot.Props) {
|
|
101
|
+
return <MenuPrimitive.SubmenuRoot data-slot="dropdown-menu-sub" {...props} />;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function DropdownMenuSubTrigger({
|
|
105
|
+
className,
|
|
106
|
+
inset,
|
|
107
|
+
children,
|
|
108
|
+
...props
|
|
109
|
+
}: MenuPrimitive.SubmenuTrigger.Props & {
|
|
110
|
+
inset?: boolean;
|
|
111
|
+
}) {
|
|
112
|
+
return (
|
|
113
|
+
<MenuPrimitive.SubmenuTrigger
|
|
114
|
+
data-slot="dropdown-menu-sub-trigger"
|
|
115
|
+
data-inset={inset}
|
|
116
|
+
className={cn(
|
|
117
|
+
"flex cursor-default items-center gap-2 rounded-none px-2 py-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-inset:pl-7 data-popup-open:bg-accent data-popup-open:text-accent-foreground data-open:bg-accent data-open:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
118
|
+
className,
|
|
119
|
+
)}
|
|
120
|
+
{...props}
|
|
121
|
+
>
|
|
122
|
+
{children}
|
|
123
|
+
<HugeiconsIcon
|
|
124
|
+
icon={ArrowRight01Icon}
|
|
125
|
+
strokeWidth={2}
|
|
126
|
+
className="ml-auto"
|
|
127
|
+
/>
|
|
128
|
+
</MenuPrimitive.SubmenuTrigger>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function DropdownMenuSubContent({
|
|
133
|
+
align = 'start',
|
|
134
|
+
alignOffset = -3,
|
|
135
|
+
side = 'right',
|
|
136
|
+
sideOffset = 0,
|
|
137
|
+
className,
|
|
138
|
+
...props
|
|
139
|
+
}: React.ComponentProps<typeof DropdownMenuContent>) {
|
|
140
|
+
return (
|
|
141
|
+
<DropdownMenuContent
|
|
142
|
+
data-slot="dropdown-menu-sub-content"
|
|
143
|
+
className={cn(
|
|
144
|
+
'w-auto min-w-[96px] rounded-none text-popover-foreground shadow-lg ring-1 ring-foreground/10 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 animate-none! relative bg-popover/70 before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:rounded-[inherit] before:backdrop-blur-2xl before:backdrop-saturate-150 **:data-[slot$=-item]:focus:bg-foreground/10 **:data-[slot$=-item]:data-highlighted:bg-foreground/10 **:data-[slot$=-separator]:bg-foreground/5 **:data-[slot$=-trigger]:focus:bg-foreground/10 **:data-[slot$=-trigger]:aria-expanded:bg-foreground/10! **:data-[variant=destructive]:focus:bg-foreground/10! **:data-[variant=destructive]:text-accent-foreground! **:data-[variant=destructive]:**:text-accent-foreground!',
|
|
145
|
+
className,
|
|
146
|
+
)}
|
|
147
|
+
align={align}
|
|
148
|
+
alignOffset={alignOffset}
|
|
149
|
+
side={side}
|
|
150
|
+
sideOffset={sideOffset}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function DropdownMenuCheckboxItem({
|
|
157
|
+
className,
|
|
158
|
+
children,
|
|
159
|
+
checked,
|
|
160
|
+
inset,
|
|
161
|
+
...props
|
|
162
|
+
}: MenuPrimitive.CheckboxItem.Props & {
|
|
163
|
+
inset?: boolean;
|
|
164
|
+
}) {
|
|
165
|
+
return (
|
|
166
|
+
<MenuPrimitive.CheckboxItem
|
|
167
|
+
data-slot="dropdown-menu-checkbox-item"
|
|
168
|
+
data-inset={inset}
|
|
169
|
+
className={cn(
|
|
170
|
+
"relative flex cursor-default items-center gap-2 rounded-none py-2 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
171
|
+
className,
|
|
172
|
+
)}
|
|
173
|
+
checked={checked}
|
|
174
|
+
{...props}
|
|
175
|
+
>
|
|
176
|
+
<span
|
|
177
|
+
className="pointer-events-none absolute right-2 flex items-center justify-center"
|
|
178
|
+
data-slot="dropdown-menu-checkbox-item-indicator"
|
|
179
|
+
>
|
|
180
|
+
<MenuPrimitive.CheckboxItemIndicator>
|
|
181
|
+
<HugeiconsIcon icon={Tick02Icon} strokeWidth={2} />
|
|
182
|
+
</MenuPrimitive.CheckboxItemIndicator>
|
|
183
|
+
</span>
|
|
184
|
+
{children}
|
|
185
|
+
</MenuPrimitive.CheckboxItem>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function DropdownMenuRadioGroup({ ...props }: MenuPrimitive.RadioGroup.Props) {
|
|
190
|
+
return (
|
|
191
|
+
<MenuPrimitive.RadioGroup
|
|
192
|
+
data-slot="dropdown-menu-radio-group"
|
|
193
|
+
{...props}
|
|
194
|
+
/>
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function DropdownMenuRadioItem({
|
|
199
|
+
className,
|
|
200
|
+
children,
|
|
201
|
+
inset,
|
|
202
|
+
...props
|
|
203
|
+
}: MenuPrimitive.RadioItem.Props & {
|
|
204
|
+
inset?: boolean;
|
|
205
|
+
}) {
|
|
206
|
+
return (
|
|
207
|
+
<MenuPrimitive.RadioItem
|
|
208
|
+
data-slot="dropdown-menu-radio-item"
|
|
209
|
+
data-inset={inset}
|
|
210
|
+
className={cn(
|
|
211
|
+
"relative flex cursor-default items-center gap-2 rounded-none py-2 pr-8 pl-2 text-xs outline-hidden select-none focus:bg-accent focus:text-accent-foreground focus:**:text-accent-foreground data-inset:pl-7 data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
212
|
+
className,
|
|
213
|
+
)}
|
|
214
|
+
{...props}
|
|
215
|
+
>
|
|
216
|
+
<span
|
|
217
|
+
className="pointer-events-none absolute right-2 flex items-center justify-center"
|
|
218
|
+
data-slot="dropdown-menu-radio-item-indicator"
|
|
219
|
+
>
|
|
220
|
+
<MenuPrimitive.RadioItemIndicator>
|
|
221
|
+
<HugeiconsIcon icon={Tick02Icon} strokeWidth={2} />
|
|
222
|
+
</MenuPrimitive.RadioItemIndicator>
|
|
223
|
+
</span>
|
|
224
|
+
{children}
|
|
225
|
+
</MenuPrimitive.RadioItem>
|
|
226
|
+
);
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function DropdownMenuSeparator({
|
|
230
|
+
className,
|
|
231
|
+
...props
|
|
232
|
+
}: MenuPrimitive.Separator.Props) {
|
|
233
|
+
return (
|
|
234
|
+
<MenuPrimitive.Separator
|
|
235
|
+
data-slot="dropdown-menu-separator"
|
|
236
|
+
className={cn('-mx-1 h-px bg-border', className)}
|
|
237
|
+
{...props}
|
|
238
|
+
/>
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
function DropdownMenuShortcut({
|
|
243
|
+
className,
|
|
244
|
+
...props
|
|
245
|
+
}: React.ComponentProps<'span'>) {
|
|
246
|
+
return (
|
|
247
|
+
<span
|
|
248
|
+
data-slot="dropdown-menu-shortcut"
|
|
249
|
+
className={cn(
|
|
250
|
+
'ml-auto text-xs tracking-widest text-muted-foreground group-focus/dropdown-menu-item:text-accent-foreground',
|
|
251
|
+
className,
|
|
252
|
+
)}
|
|
253
|
+
{...props}
|
|
254
|
+
/>
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export {
|
|
259
|
+
DropdownMenu,
|
|
260
|
+
DropdownMenuCheckboxItem,
|
|
261
|
+
DropdownMenuContent,
|
|
262
|
+
DropdownMenuGroup,
|
|
263
|
+
DropdownMenuItem,
|
|
264
|
+
DropdownMenuLabel,
|
|
265
|
+
DropdownMenuPortal,
|
|
266
|
+
DropdownMenuRadioGroup,
|
|
267
|
+
DropdownMenuRadioItem,
|
|
268
|
+
DropdownMenuSeparator,
|
|
269
|
+
DropdownMenuShortcut,
|
|
270
|
+
DropdownMenuSub,
|
|
271
|
+
DropdownMenuSubContent,
|
|
272
|
+
DropdownMenuSubTrigger,
|
|
273
|
+
DropdownMenuTrigger,
|
|
274
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { Input as InputPrimitive } from "@base-ui/react/input"
|
|
3
|
+
import { cn } from "cn"
|
|
4
|
+
|
|
5
|
+
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
6
|
+
return (
|
|
7
|
+
<InputPrimitive
|
|
8
|
+
type={type}
|
|
9
|
+
data-slot="input"
|
|
10
|
+
className={cn(
|
|
11
|
+
"h-8 w-full min-w-0 rounded-none border border-input bg-transparent px-2.5 py-1 text-xs transition-colors outline-none file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-xs file:font-medium file:text-foreground placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-1 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-1 aria-invalid:ring-destructive/20 md:text-xs dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
12
|
+
className
|
|
13
|
+
)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export { Input }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cn } from "cn"
|
|
3
|
+
|
|
4
|
+
function Label({ className, ...props }: React.ComponentProps<"label">) {
|
|
5
|
+
return (
|
|
6
|
+
<label
|
|
7
|
+
data-slot="label"
|
|
8
|
+
className={cn(
|
|
9
|
+
"flex items-center gap-2 text-xs leading-none select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
10
|
+
className
|
|
11
|
+
)}
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { Label }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Separator as SeparatorPrimitive } from "@base-ui/react/separator"
|
|
2
|
+
import { cn } from "cn"
|
|
3
|
+
|
|
4
|
+
function Separator({
|
|
5
|
+
className,
|
|
6
|
+
orientation = "horizontal",
|
|
7
|
+
...props
|
|
8
|
+
}: SeparatorPrimitive.Props) {
|
|
9
|
+
return (
|
|
10
|
+
<SeparatorPrimitive
|
|
11
|
+
data-slot="separator"
|
|
12
|
+
orientation={orientation}
|
|
13
|
+
className={cn(
|
|
14
|
+
"shrink-0 bg-border data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { Separator }
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Dialog as SheetPrimitive } from '@base-ui/react/dialog';
|
|
2
|
+
import { Cancel01Icon } from '@hugeicons/core-free-icons';
|
|
3
|
+
import { HugeiconsIcon } from '@hugeicons/react';
|
|
4
|
+
import { cn } from 'cn';
|
|
5
|
+
import type * as React from 'react';
|
|
6
|
+
import { Button } from '@/components/ui/button';
|
|
7
|
+
|
|
8
|
+
function Sheet({ ...props }: SheetPrimitive.Root.Props) {
|
|
9
|
+
return <SheetPrimitive.Root data-slot="sheet" {...props} />;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {
|
|
13
|
+
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function SheetClose({ ...props }: SheetPrimitive.Close.Props) {
|
|
17
|
+
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {
|
|
21
|
+
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {
|
|
25
|
+
return (
|
|
26
|
+
<SheetPrimitive.Backdrop
|
|
27
|
+
data-slot="sheet-overlay"
|
|
28
|
+
className={cn(
|
|
29
|
+
'fixed inset-0 z-50 bg-black/10 text-xs/relaxed transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0 supports-backdrop-filter:backdrop-blur-xs',
|
|
30
|
+
className,
|
|
31
|
+
)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function SheetContent({
|
|
38
|
+
className,
|
|
39
|
+
children,
|
|
40
|
+
side = 'right',
|
|
41
|
+
showCloseButton = true,
|
|
42
|
+
showOverlay = true,
|
|
43
|
+
...props
|
|
44
|
+
}: SheetPrimitive.Popup.Props & {
|
|
45
|
+
side?: 'top' | 'right' | 'bottom' | 'left';
|
|
46
|
+
showCloseButton?: boolean;
|
|
47
|
+
showOverlay?: boolean;
|
|
48
|
+
}) {
|
|
49
|
+
return (
|
|
50
|
+
<SheetPortal>
|
|
51
|
+
{showOverlay && <SheetOverlay />}
|
|
52
|
+
<SheetPrimitive.Popup
|
|
53
|
+
data-slot="sheet-content"
|
|
54
|
+
data-side={side}
|
|
55
|
+
className={cn(
|
|
56
|
+
'fixed z-50 flex flex-col bg-popover bg-clip-padding text-xs/relaxed text-popover-foreground shadow-lg transition duration-200 ease-in-out data-ending-style:opacity-0 data-starting-style:opacity-0 data-[side=bottom]:inset-x-0 data-[side=bottom]:bottom-0 data-[side=bottom]:h-auto data-[side=bottom]:border-t data-[side=bottom]:data-ending-style:translate-y-[2.5rem] data-[side=bottom]:data-starting-style:translate-y-[2.5rem] data-[side=left]:inset-y-0 data-[side=left]:left-0 data-[side=left]:h-full data-[side=left]:w-3/4 data-[side=left]:border-r data-[side=left]:data-ending-style:translate-x-[-2.5rem] data-[side=left]:data-starting-style:translate-x-[-2.5rem] data-[side=right]:inset-y-0 data-[side=right]:right-0 data-[side=right]:h-full data-[side=right]:w-3/4 data-[side=right]:border-l data-[side=right]:data-ending-style:translate-x-[2.5rem] data-[side=right]:data-starting-style:translate-x-[2.5rem] data-[side=top]:inset-x-0 data-[side=top]:top-0 data-[side=top]:h-auto data-[side=top]:border-b data-[side=top]:data-ending-style:translate-y-[-2.5rem] data-[side=top]:data-starting-style:translate-y-[-2.5rem] data-[side=left]:sm:max-w-sm data-[side=right]:sm:max-w-sm',
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
{showCloseButton && (
|
|
63
|
+
<SheetPrimitive.Close
|
|
64
|
+
data-slot="sheet-close"
|
|
65
|
+
render={
|
|
66
|
+
<Button
|
|
67
|
+
variant="ghost"
|
|
68
|
+
className="absolute top-3 right-3"
|
|
69
|
+
size="icon-sm"
|
|
70
|
+
/>
|
|
71
|
+
}
|
|
72
|
+
>
|
|
73
|
+
<HugeiconsIcon icon={Cancel01Icon} strokeWidth={2} />
|
|
74
|
+
<span className="sr-only">Close</span>
|
|
75
|
+
</SheetPrimitive.Close>
|
|
76
|
+
)}
|
|
77
|
+
</SheetPrimitive.Popup>
|
|
78
|
+
</SheetPortal>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
data-slot="sheet-header"
|
|
86
|
+
className={cn('flex flex-col gap-0.5 p-4', className)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
93
|
+
return (
|
|
94
|
+
<div
|
|
95
|
+
data-slot="sheet-footer"
|
|
96
|
+
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {
|
|
103
|
+
return (
|
|
104
|
+
<SheetPrimitive.Title
|
|
105
|
+
data-slot="sheet-title"
|
|
106
|
+
className={cn(
|
|
107
|
+
'font-heading text-sm font-medium text-foreground',
|
|
108
|
+
className,
|
|
109
|
+
)}
|
|
110
|
+
{...props}
|
|
111
|
+
/>
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function SheetDescription({
|
|
116
|
+
className,
|
|
117
|
+
...props
|
|
118
|
+
}: SheetPrimitive.Description.Props) {
|
|
119
|
+
return (
|
|
120
|
+
<SheetPrimitive.Description
|
|
121
|
+
data-slot="sheet-description"
|
|
122
|
+
className={cn('text-xs/relaxed text-muted-foreground', className)}
|
|
123
|
+
{...props}
|
|
124
|
+
/>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export {
|
|
129
|
+
Sheet,
|
|
130
|
+
SheetClose,
|
|
131
|
+
SheetContent,
|
|
132
|
+
SheetDescription,
|
|
133
|
+
SheetFooter,
|
|
134
|
+
SheetHeader,
|
|
135
|
+
SheetTitle,
|
|
136
|
+
SheetTrigger,
|
|
137
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
const MOBILE_BREAKPOINT = 768
|
|
4
|
+
|
|
5
|
+
export function useIsMobile() {
|
|
6
|
+
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
|
7
|
+
|
|
8
|
+
React.useEffect(() => {
|
|
9
|
+
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
10
|
+
const onChange = () => {
|
|
11
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
|
+
}
|
|
13
|
+
mql.addEventListener("change", onChange)
|
|
14
|
+
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
|
+
return () => mql.removeEventListener("change", onChange)
|
|
16
|
+
}, [])
|
|
17
|
+
|
|
18
|
+
return !!isMobile
|
|
19
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
@import "tailwindcss";
|
|
2
|
+
@import "tw-animate-css";
|
|
3
|
+
@import "shadcn/tailwind.css";
|
|
4
|
+
@import "@fontsource-variable/geist-mono";
|
|
5
|
+
@import "@fontsource-variable/raleway";
|
|
6
|
+
|
|
7
|
+
@custom-variant dark (&:is(.dark *));
|
|
8
|
+
|
|
9
|
+
:root {
|
|
10
|
+
--background: oklch(1 0 0);
|
|
11
|
+
--foreground: oklch(0.147 0.004 49.3);
|
|
12
|
+
--card: oklch(1 0 0);
|
|
13
|
+
--card-foreground: oklch(0.147 0.004 49.3);
|
|
14
|
+
--popover: oklch(1 0 0);
|
|
15
|
+
--popover-foreground: oklch(0.147 0.004 49.3);
|
|
16
|
+
--primary: oklch(0.508 0.118 165.612);
|
|
17
|
+
--primary-foreground: oklch(0.979 0.021 166.113);
|
|
18
|
+
--secondary: oklch(0.967 0.001 286.375);
|
|
19
|
+
--secondary-foreground: oklch(0.21 0.006 285.885);
|
|
20
|
+
--muted: oklch(0.96 0.002 17.2);
|
|
21
|
+
--muted-foreground: oklch(0.547 0.021 43.1);
|
|
22
|
+
--accent: oklch(0.96 0.002 17.2);
|
|
23
|
+
--accent-foreground: oklch(0.214 0.009 43.1);
|
|
24
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
25
|
+
--border: oklch(0.922 0.005 34.3);
|
|
26
|
+
--input: oklch(0.922 0.005 34.3);
|
|
27
|
+
--ring: oklch(0.714 0.014 41.2);
|
|
28
|
+
--chart-1: oklch(0.845 0.143 164.978);
|
|
29
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
30
|
+
--chart-3: oklch(0.596 0.145 163.225);
|
|
31
|
+
--chart-4: oklch(0.508 0.118 165.612);
|
|
32
|
+
--chart-5: oklch(0.432 0.095 166.913);
|
|
33
|
+
--radius: 0.625rem;
|
|
34
|
+
--sidebar: oklch(0.986 0.002 67.8);
|
|
35
|
+
--sidebar-foreground: oklch(0.147 0.004 49.3);
|
|
36
|
+
--sidebar-primary: oklch(0.596 0.145 163.225);
|
|
37
|
+
--sidebar-primary-foreground: oklch(0.979 0.021 166.113);
|
|
38
|
+
--sidebar-accent: oklch(0.96 0.002 17.2);
|
|
39
|
+
--sidebar-accent-foreground: oklch(0.214 0.009 43.1);
|
|
40
|
+
--sidebar-border: oklch(0.922 0.005 34.3);
|
|
41
|
+
--sidebar-ring: oklch(0.714 0.014 41.2);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
.dark {
|
|
45
|
+
--background: oklch(0.147 0.004 49.3);
|
|
46
|
+
--foreground: oklch(0.986 0.002 67.8);
|
|
47
|
+
--card: oklch(0.214 0.009 43.1);
|
|
48
|
+
--card-foreground: oklch(0.986 0.002 67.8);
|
|
49
|
+
--popover: oklch(0.214 0.009 43.1);
|
|
50
|
+
--popover-foreground: oklch(0.986 0.002 67.8);
|
|
51
|
+
--primary: oklch(0.432 0.095 166.913);
|
|
52
|
+
--primary-foreground: oklch(0.979 0.021 166.113);
|
|
53
|
+
--secondary: oklch(0.274 0.006 286.033);
|
|
54
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
55
|
+
--muted: oklch(0.268 0.011 36.5);
|
|
56
|
+
--muted-foreground: oklch(0.714 0.014 41.2);
|
|
57
|
+
--accent: oklch(0.268 0.011 36.5);
|
|
58
|
+
--accent-foreground: oklch(0.986 0.002 67.8);
|
|
59
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
60
|
+
--border: oklch(1 0 0 / 10%);
|
|
61
|
+
--input: oklch(1 0 0 / 15%);
|
|
62
|
+
--ring: oklch(0.547 0.021 43.1);
|
|
63
|
+
--chart-1: oklch(0.845 0.143 164.978);
|
|
64
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
65
|
+
--chart-3: oklch(0.596 0.145 163.225);
|
|
66
|
+
--chart-4: oklch(0.508 0.118 165.612);
|
|
67
|
+
--chart-5: oklch(0.432 0.095 166.913);
|
|
68
|
+
--sidebar: oklch(0.214 0.009 43.1);
|
|
69
|
+
--sidebar-foreground: oklch(0.986 0.002 67.8);
|
|
70
|
+
--sidebar-primary: oklch(0.696 0.17 162.48);
|
|
71
|
+
--sidebar-primary-foreground: oklch(0.262 0.051 172.552);
|
|
72
|
+
--sidebar-accent: oklch(0.268 0.011 36.5);
|
|
73
|
+
--sidebar-accent-foreground: oklch(0.986 0.002 67.8);
|
|
74
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
75
|
+
--sidebar-ring: oklch(0.547 0.021 43.1);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
@theme inline {
|
|
79
|
+
--font-mono: 'Geist Mono Variable', monospace;
|
|
80
|
+
--font-heading: 'Raleway Variable', sans-serif;
|
|
81
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
82
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
83
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
84
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
85
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
86
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
87
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
88
|
+
--color-sidebar: var(--sidebar);
|
|
89
|
+
--color-chart-5: var(--chart-5);
|
|
90
|
+
--color-chart-4: var(--chart-4);
|
|
91
|
+
--color-chart-3: var(--chart-3);
|
|
92
|
+
--color-chart-2: var(--chart-2);
|
|
93
|
+
--color-chart-1: var(--chart-1);
|
|
94
|
+
--color-ring: var(--ring);
|
|
95
|
+
--color-input: var(--input);
|
|
96
|
+
--color-border: var(--border);
|
|
97
|
+
--color-destructive: var(--destructive);
|
|
98
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
99
|
+
--color-accent: var(--accent);
|
|
100
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
101
|
+
--color-muted: var(--muted);
|
|
102
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
103
|
+
--color-secondary: var(--secondary);
|
|
104
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
105
|
+
--color-primary: var(--primary);
|
|
106
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
107
|
+
--color-popover: var(--popover);
|
|
108
|
+
--color-card-foreground: var(--card-foreground);
|
|
109
|
+
--color-card: var(--card);
|
|
110
|
+
--color-foreground: var(--foreground);
|
|
111
|
+
--color-background: var(--background);
|
|
112
|
+
--radius-sm: calc(var(--radius) * 0.6);
|
|
113
|
+
--radius-md: calc(var(--radius) * 0.8);
|
|
114
|
+
--radius-lg: var(--radius);
|
|
115
|
+
--radius-xl: calc(var(--radius) * 1.4);
|
|
116
|
+
--radius-2xl: calc(var(--radius) * 1.8);
|
|
117
|
+
--radius-3xl: calc(var(--radius) * 2.2);
|
|
118
|
+
--radius-4xl: calc(var(--radius) * 2.6);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@layer base {
|
|
122
|
+
* {
|
|
123
|
+
@apply border-border outline-ring/50;
|
|
124
|
+
}
|
|
125
|
+
body {
|
|
126
|
+
@apply bg-background text-foreground;
|
|
127
|
+
}
|
|
128
|
+
html {
|
|
129
|
+
@apply font-mono;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { cn } from "cn"
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { StrictMode } from 'react';
|
|
2
|
+
import { createRoot } from 'react-dom/client';
|
|
3
|
+
import { ThemeProvider } from '@/components/theme-provider';
|
|
4
|
+
import App from './App';
|
|
5
|
+
import './index.css';
|
|
6
|
+
|
|
7
|
+
const root = document.getElementById('root');
|
|
8
|
+
if (!root) throw new Error('Missing application root');
|
|
9
|
+
createRoot(root).render(<StrictMode><ThemeProvider><App /></ThemeProvider></StrictMode>);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
|
|
4
|
+
"target": "es2023",
|
|
5
|
+
"lib": ["ES2023", "DOM"],
|
|
6
|
+
"module": "esnext",
|
|
7
|
+
"types": ["vite/client"],
|
|
8
|
+
"skipLibCheck": true,
|
|
9
|
+
|
|
10
|
+
/* Bundler mode */
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"allowImportingTsExtensions": true,
|
|
13
|
+
"verbatimModuleSyntax": true,
|
|
14
|
+
"moduleDetection": "force",
|
|
15
|
+
"noEmit": true,
|
|
16
|
+
"jsx": "react-jsx",
|
|
17
|
+
|
|
18
|
+
/* Linting */
|
|
19
|
+
"strict": true,
|
|
20
|
+
"noUnusedLocals": true,
|
|
21
|
+
"noUnusedParameters": true,
|
|
22
|
+
"erasableSyntaxOnly": true,
|
|
23
|
+
"noFallthroughCasesInSwitch": true,
|
|
24
|
+
"paths": {
|
|
25
|
+
"@/*": ["./src/*"]
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"include": ["src"]
|
|
29
|
+
}
|