@snow-labs/brutal-ui 0.1.1 → 0.2.1
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/dist/components/brutal/cta-section.d.ts +7 -2
- package/dist/components/brutal/cta-section.js +136 -32
- package/dist/components/brutal/cta-section.js.map +1 -1
- package/dist/components/brutal/faq.d.ts +16 -0
- package/dist/components/brutal/faq.js +163 -0
- package/dist/components/brutal/faq.js.map +1 -0
- package/dist/components/brutal/feature-grid.d.ts +6 -2
- package/dist/components/brutal/feature-grid.js +73 -10
- package/dist/components/brutal/feature-grid.js.map +1 -1
- package/dist/components/brutal/footer.d.ts +14 -1
- package/dist/components/brutal/footer.js +181 -18
- package/dist/components/brutal/footer.js.map +1 -1
- package/dist/components/brutal/hero.d.ts +9 -2
- package/dist/components/brutal/hero.js +67 -22
- package/dist/components/brutal/hero.js.map +1 -1
- package/dist/components/brutal/index.d.ts +7 -2
- package/dist/components/brutal/index.js +1035 -128
- package/dist/components/brutal/index.js.map +1 -1
- package/dist/components/brutal/integration-grid.d.ts +1 -1
- package/dist/components/brutal/integration-grid.js +13 -5
- package/dist/components/brutal/integration-grid.js.map +1 -1
- package/dist/components/brutal/logo-cloud.d.ts +17 -0
- package/dist/components/brutal/logo-cloud.js +93 -0
- package/dist/components/brutal/logo-cloud.js.map +1 -0
- package/dist/components/brutal/nav.d.ts +3 -1
- package/dist/components/brutal/nav.js +166 -9
- package/dist/components/brutal/nav.js.map +1 -1
- package/dist/components/brutal/newsletter.d.ts +14 -0
- package/dist/components/brutal/newsletter.js +169 -0
- package/dist/components/brutal/newsletter.js.map +1 -0
- package/dist/components/brutal/pricing-table.d.ts +27 -0
- package/dist/components/brutal/pricing-table.js +251 -0
- package/dist/components/brutal/pricing-table.js.map +1 -0
- package/dist/components/brutal/section-divider.d.ts +14 -0
- package/dist/components/brutal/section-divider.js +70 -0
- package/dist/components/brutal/section-divider.js.map +1 -0
- package/dist/components/brutal/section.d.ts +7 -3
- package/dist/components/brutal/section.js +13 -5
- package/dist/components/brutal/section.js.map +1 -1
- package/dist/components/brutal/stats-bar.d.ts +16 -0
- package/dist/components/brutal/stats-bar.js +127 -0
- package/dist/components/brutal/stats-bar.js.map +1 -0
- package/dist/components/brutal/testimonials.d.ts +11 -3
- package/dist/components/brutal/testimonials.js +126 -33
- package/dist/components/brutal/testimonials.js.map +1 -1
- package/dist/components/brutal/wave-divider.d.ts +2 -12
- package/dist/components/brutal/wave-divider.js +54 -26
- package/dist/components/brutal/wave-divider.js.map +1 -1
- package/dist/components/dashboard/activity-feed.d.ts +18 -0
- package/dist/components/dashboard/activity-feed.js +105 -0
- package/dist/components/dashboard/activity-feed.js.map +1 -0
- package/dist/components/dashboard/app-shell.d.ts +19 -0
- package/dist/components/dashboard/app-shell.js +206 -0
- package/dist/components/dashboard/app-shell.js.map +1 -0
- package/dist/components/dashboard/empty-state.d.ts +14 -0
- package/dist/components/dashboard/empty-state.js +96 -0
- package/dist/components/dashboard/empty-state.js.map +1 -0
- package/dist/components/dashboard/file-upload.d.ts +12 -0
- package/dist/components/dashboard/file-upload.js +86 -0
- package/dist/components/dashboard/file-upload.js.map +1 -0
- package/dist/components/dashboard/index.d.ts +10 -0
- package/dist/components/dashboard/index.js +755 -0
- package/dist/components/dashboard/index.js.map +1 -0
- package/dist/components/dashboard/search-bar.d.ts +12 -0
- package/dist/components/dashboard/search-bar.js +49 -0
- package/dist/components/dashboard/search-bar.js.map +1 -0
- package/dist/components/dashboard/sidebar.d.ts +23 -0
- package/dist/components/dashboard/sidebar.js +113 -0
- package/dist/components/dashboard/sidebar.js.map +1 -0
- package/dist/components/dashboard/stat-card.d.ts +13 -0
- package/dist/components/dashboard/stat-card.js +55 -0
- package/dist/components/dashboard/stat-card.js.map +1 -0
- package/dist/components/dashboard/user-menu.d.ts +16 -0
- package/dist/components/dashboard/user-menu.js +179 -0
- package/dist/components/dashboard/user-menu.js.map +1 -0
- package/dist/components/dashboard/view-switcher.d.ts +12 -0
- package/dist/components/dashboard/view-switcher.js +130 -0
- package/dist/components/dashboard/view-switcher.js.map +1 -0
- package/dist/components/views/calendar-view.d.ts +17 -0
- package/dist/components/views/calendar-view.js +182 -0
- package/dist/components/views/calendar-view.js.map +1 -0
- package/dist/components/views/data-table.d.ts +15 -0
- package/dist/components/views/data-table.js +204 -0
- package/dist/components/views/data-table.js.map +1 -0
- package/dist/components/views/grid-view.d.ts +11 -0
- package/dist/components/views/grid-view.js +31 -0
- package/dist/components/views/grid-view.js.map +1 -0
- package/dist/components/views/index.d.ts +7 -0
- package/dist/components/views/index.js +542 -0
- package/dist/components/views/index.js.map +1 -0
- package/dist/components/views/kanban-board.d.ts +21 -0
- package/dist/components/views/kanban-board.js +153 -0
- package/dist/components/views/kanban-board.js.map +1 -0
- package/dist/components/views/list-view.d.ts +19 -0
- package/dist/components/views/list-view.js +96 -0
- package/dist/components/views/list-view.js.map +1 -0
- package/dist/index.d.ts +27 -3
- package/dist/index.js +1881 -142
- package/dist/index.js.map +1 -1
- package/dist/lib/animations.d.ts +68 -0
- package/dist/lib/animations.js +44 -0
- package/dist/lib/animations.js.map +1 -0
- package/dist/templates/dashboard.d.ts +40 -0
- package/dist/templates/dashboard.js +658 -0
- package/dist/templates/dashboard.js.map +1 -0
- package/dist/templates/index.d.ts +4 -0
- package/dist/templates/index.js +2001 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/saas-launch.d.ts +113 -0
- package/dist/templates/saas-launch.js +1394 -0
- package/dist/templates/saas-launch.js.map +1 -0
- package/dist/templates/studio.d.ts +72 -0
- package/dist/templates/studio.js +1099 -0
- package/dist/templates/studio.js.map +1 -0
- package/dist/theme.css +58 -15
- package/package.json +48 -2
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { createContext, useContext, useState } from 'react';
|
|
5
|
+
import { Dialog } from '@base-ui/react/dialog';
|
|
6
|
+
import { Button as Button$1 } from '@base-ui/react/button';
|
|
7
|
+
import { cva } from 'class-variance-authority';
|
|
8
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
|
+
import { XIcon } from 'lucide-react';
|
|
10
|
+
|
|
11
|
+
function cn(...inputs) {
|
|
12
|
+
return twMerge(clsx(inputs));
|
|
13
|
+
}
|
|
14
|
+
var buttonVariants = cva(
|
|
15
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-lg whitespace-nowrap font-bold transition-all duration-150 select-none outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
16
|
+
{
|
|
17
|
+
variants: {
|
|
18
|
+
variant: {
|
|
19
|
+
// Primary: Black bg, white text, offset shadow
|
|
20
|
+
default: "border-brutal border-foreground bg-primary text-primary-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
21
|
+
// CTA: Mint green bg — the Bannerbear signature
|
|
22
|
+
cta: "border-brutal border-foreground bg-cta text-cta-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
23
|
+
// Brand: Dynamic brand color bg
|
|
24
|
+
brand: "border-brutal border-foreground bg-brand text-brand-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
25
|
+
// Outline: White bg, black border, offset shadow
|
|
26
|
+
outline: "border-brutal border-foreground bg-background text-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
27
|
+
// Secondary: Light bg, border, smaller shadow
|
|
28
|
+
secondary: "border-brutal border-foreground bg-secondary text-secondary-foreground shadow-brutal-sm hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal active:translate-x-px active:translate-y-px active:shadow-none",
|
|
29
|
+
// Ghost: No border/shadow, subtle hover
|
|
30
|
+
ghost: "hover:bg-secondary hover:text-foreground",
|
|
31
|
+
// Link: Text only
|
|
32
|
+
link: "text-foreground underline-offset-4 hover:underline",
|
|
33
|
+
// Destructive
|
|
34
|
+
destructive: "border-brutal border-destructive bg-destructive text-destructive-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
35
|
+
// Nav: Thin border, no shadow (for nav Sign In buttons)
|
|
36
|
+
nav: "border border-foreground bg-background text-foreground hover:bg-foreground hover:text-background"
|
|
37
|
+
},
|
|
38
|
+
size: {
|
|
39
|
+
xs: "h-7 gap-1 px-2.5 text-xs",
|
|
40
|
+
sm: "h-8 gap-1.5 px-3 text-sm",
|
|
41
|
+
default: "h-10 gap-2 px-5 text-sm",
|
|
42
|
+
lg: "h-12 gap-2 px-7 text-base",
|
|
43
|
+
xl: "h-14 gap-2.5 px-9 text-lg",
|
|
44
|
+
icon: "size-10",
|
|
45
|
+
"icon-sm": "size-8",
|
|
46
|
+
"icon-lg": "size-12"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
defaultVariants: {
|
|
50
|
+
variant: "default",
|
|
51
|
+
size: "default"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
);
|
|
55
|
+
function Button({
|
|
56
|
+
className,
|
|
57
|
+
variant = "default",
|
|
58
|
+
size = "default",
|
|
59
|
+
...props
|
|
60
|
+
}) {
|
|
61
|
+
return /* @__PURE__ */ jsx(
|
|
62
|
+
Button$1,
|
|
63
|
+
{
|
|
64
|
+
"data-slot": "button",
|
|
65
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
66
|
+
...props
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
function Sheet({ ...props }) {
|
|
71
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { "data-slot": "sheet", ...props });
|
|
72
|
+
}
|
|
73
|
+
function SheetPortal({ ...props }) {
|
|
74
|
+
return /* @__PURE__ */ jsx(Dialog.Portal, { "data-slot": "sheet-portal", ...props });
|
|
75
|
+
}
|
|
76
|
+
function SheetOverlay({ className, ...props }) {
|
|
77
|
+
return /* @__PURE__ */ jsx(
|
|
78
|
+
Dialog.Backdrop,
|
|
79
|
+
{
|
|
80
|
+
"data-slot": "sheet-overlay",
|
|
81
|
+
className: cn(
|
|
82
|
+
"fixed inset-0 z-50 bg-black/60 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0",
|
|
83
|
+
className
|
|
84
|
+
),
|
|
85
|
+
...props
|
|
86
|
+
}
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
function SheetContent({
|
|
90
|
+
className,
|
|
91
|
+
children,
|
|
92
|
+
side = "right",
|
|
93
|
+
showCloseButton = true,
|
|
94
|
+
...props
|
|
95
|
+
}) {
|
|
96
|
+
return /* @__PURE__ */ jsxs(SheetPortal, { children: [
|
|
97
|
+
/* @__PURE__ */ jsx(SheetOverlay, {}),
|
|
98
|
+
/* @__PURE__ */ jsxs(
|
|
99
|
+
Dialog.Popup,
|
|
100
|
+
{
|
|
101
|
+
"data-slot": "sheet-content",
|
|
102
|
+
"data-side": side,
|
|
103
|
+
className: cn(
|
|
104
|
+
"fixed z-50 flex flex-col gap-4 border-brutal border-foreground bg-background bg-clip-padding text-sm shadow-brutal-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]: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]: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]: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]: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",
|
|
105
|
+
className
|
|
106
|
+
),
|
|
107
|
+
...props,
|
|
108
|
+
children: [
|
|
109
|
+
children,
|
|
110
|
+
showCloseButton && /* @__PURE__ */ jsxs(
|
|
111
|
+
Dialog.Close,
|
|
112
|
+
{
|
|
113
|
+
"data-slot": "sheet-close",
|
|
114
|
+
render: /* @__PURE__ */ jsx(
|
|
115
|
+
Button,
|
|
116
|
+
{
|
|
117
|
+
variant: "ghost",
|
|
118
|
+
className: "absolute top-3 right-3",
|
|
119
|
+
size: "icon-sm"
|
|
120
|
+
}
|
|
121
|
+
),
|
|
122
|
+
children: [
|
|
123
|
+
/* @__PURE__ */ jsx(
|
|
124
|
+
XIcon,
|
|
125
|
+
{}
|
|
126
|
+
),
|
|
127
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
128
|
+
]
|
|
129
|
+
}
|
|
130
|
+
)
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
] });
|
|
135
|
+
}
|
|
136
|
+
function SheetTitle({ className, ...props }) {
|
|
137
|
+
return /* @__PURE__ */ jsx(
|
|
138
|
+
Dialog.Title,
|
|
139
|
+
{
|
|
140
|
+
"data-slot": "sheet-title",
|
|
141
|
+
className: cn("text-base font-bold text-foreground", className),
|
|
142
|
+
...props
|
|
143
|
+
}
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
var AppShellContext = createContext({
|
|
147
|
+
collapsed: false,
|
|
148
|
+
setCollapsed: () => {
|
|
149
|
+
},
|
|
150
|
+
mobileOpen: false,
|
|
151
|
+
setMobileOpen: () => {
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
var useAppShell = () => useContext(AppShellContext);
|
|
155
|
+
function AppShell({
|
|
156
|
+
sidebar,
|
|
157
|
+
header,
|
|
158
|
+
children,
|
|
159
|
+
defaultCollapsed = false,
|
|
160
|
+
className
|
|
161
|
+
}) {
|
|
162
|
+
const [collapsed, setCollapsed] = useState(defaultCollapsed);
|
|
163
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
164
|
+
return /* @__PURE__ */ jsx(
|
|
165
|
+
AppShellContext.Provider,
|
|
166
|
+
{
|
|
167
|
+
value: { collapsed, setCollapsed, mobileOpen, setMobileOpen },
|
|
168
|
+
children: /* @__PURE__ */ jsxs("div", { className: cn("flex h-screen bg-background", className), children: [
|
|
169
|
+
/* @__PURE__ */ jsx(
|
|
170
|
+
"aside",
|
|
171
|
+
{
|
|
172
|
+
className: cn(
|
|
173
|
+
"hidden border-r-brutal border-foreground bg-background transition-all duration-200 md:block",
|
|
174
|
+
collapsed ? "w-16" : "w-64"
|
|
175
|
+
),
|
|
176
|
+
children: sidebar
|
|
177
|
+
}
|
|
178
|
+
),
|
|
179
|
+
/* @__PURE__ */ jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-64 p-0 md:hidden", children: [
|
|
180
|
+
/* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
|
|
181
|
+
sidebar
|
|
182
|
+
] }) }),
|
|
183
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
|
|
184
|
+
header && /* @__PURE__ */ jsxs("header", { className: "flex h-14 items-center gap-4 border-b-brutal border-foreground px-6", children: [
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
Button,
|
|
187
|
+
{
|
|
188
|
+
variant: "ghost",
|
|
189
|
+
size: "sm",
|
|
190
|
+
className: "md:hidden",
|
|
191
|
+
onClick: () => setMobileOpen(true),
|
|
192
|
+
children: "\u2630"
|
|
193
|
+
}
|
|
194
|
+
),
|
|
195
|
+
header
|
|
196
|
+
] }),
|
|
197
|
+
/* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto p-6", children })
|
|
198
|
+
] })
|
|
199
|
+
] })
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export { AppShell, useAppShell };
|
|
205
|
+
//# sourceMappingURL=app-shell.js.map
|
|
206
|
+
//# sourceMappingURL=app-shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/button.tsx","../../../src/components/ui/sheet.tsx","../../../src/components/dashboard/app-shell.tsx"],"names":["ButtonPrimitive","jsx","SheetPrimitive","jsxs"],"mappings":"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","file":"app-shell.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\";\n\nimport { Button as ButtonPrimitive } from \"@base-ui/react/button\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg whitespace-nowrap font-bold transition-all duration-150 select-none outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n // Primary: Black bg, white text, offset shadow\n default:\n \"border-brutal border-foreground bg-primary text-primary-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // CTA: Mint green bg — the Bannerbear signature\n cta: \"border-brutal border-foreground bg-cta text-cta-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Brand: Dynamic brand color bg\n brand:\n \"border-brutal border-foreground bg-brand text-brand-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Outline: White bg, black border, offset shadow\n outline:\n \"border-brutal border-foreground bg-background text-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Secondary: Light bg, border, smaller shadow\n secondary:\n \"border-brutal border-foreground bg-secondary text-secondary-foreground shadow-brutal-sm hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal active:translate-x-px active:translate-y-px active:shadow-none\",\n // Ghost: No border/shadow, subtle hover\n ghost: \"hover:bg-secondary hover:text-foreground\",\n // Link: Text only\n link: \"text-foreground underline-offset-4 hover:underline\",\n // Destructive\n destructive:\n \"border-brutal border-destructive bg-destructive text-destructive-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Nav: Thin border, no shadow (for nav Sign In buttons)\n nav: \"border border-foreground bg-background text-foreground hover:bg-foreground hover:text-background\",\n },\n size: {\n xs: \"h-7 gap-1 px-2.5 text-xs\",\n sm: \"h-8 gap-1.5 px-3 text-sm\",\n default: \"h-10 gap-2 px-5 text-sm\",\n lg: \"h-12 gap-2 px-7 text-base\",\n xl: \"h-14 gap-2.5 px-9 text-lg\",\n icon: \"size-10\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Dialog as SheetPrimitive } from \"@base-ui/react/dialog\"\n\nimport { cn } from \"../../lib/utils\"\nimport { Button } from \"./button\"\nimport { XIcon } from \"lucide-react\"\n\nfunction Sheet({ ...props }: SheetPrimitive.Root.Props) {\n return <SheetPrimitive.Root data-slot=\"sheet\" {...props} />\n}\n\nfunction SheetTrigger({ ...props }: SheetPrimitive.Trigger.Props) {\n return <SheetPrimitive.Trigger data-slot=\"sheet-trigger\" {...props} />\n}\n\nfunction SheetClose({ ...props }: SheetPrimitive.Close.Props) {\n return <SheetPrimitive.Close data-slot=\"sheet-close\" {...props} />\n}\n\nfunction SheetPortal({ ...props }: SheetPrimitive.Portal.Props) {\n return <SheetPrimitive.Portal data-slot=\"sheet-portal\" {...props} />\n}\n\nfunction SheetOverlay({ className, ...props }: SheetPrimitive.Backdrop.Props) {\n return (\n <SheetPrimitive.Backdrop\n data-slot=\"sheet-overlay\"\n className={cn(\n \"fixed inset-0 z-50 bg-black/60 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction SheetContent({\n className,\n children,\n side = \"right\",\n showCloseButton = true,\n ...props\n}: SheetPrimitive.Popup.Props & {\n side?: \"top\" | \"right\" | \"bottom\" | \"left\"\n showCloseButton?: boolean\n}) {\n return (\n <SheetPortal>\n <SheetOverlay />\n <SheetPrimitive.Popup\n data-slot=\"sheet-content\"\n data-side={side}\n className={cn(\n \"fixed z-50 flex flex-col gap-4 border-brutal border-foreground bg-background bg-clip-padding text-sm shadow-brutal-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]: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]: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]: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]: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\",\n className\n )}\n {...props}\n >\n {children}\n {showCloseButton && (\n <SheetPrimitive.Close\n data-slot=\"sheet-close\"\n render={\n <Button\n variant=\"ghost\"\n className=\"absolute top-3 right-3\"\n size=\"icon-sm\"\n />\n }\n >\n <XIcon\n />\n <span className=\"sr-only\">Close</span>\n </SheetPrimitive.Close>\n )}\n </SheetPrimitive.Popup>\n </SheetPortal>\n )\n}\n\nfunction SheetHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-header\"\n className={cn(\"flex flex-col gap-0.5 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"sheet-footer\"\n className={cn(\"mt-auto flex flex-col gap-2 p-4\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetTitle({ className, ...props }: SheetPrimitive.Title.Props) {\n return (\n <SheetPrimitive.Title\n data-slot=\"sheet-title\"\n className={cn(\"text-base font-bold text-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction SheetDescription({\n className,\n ...props\n}: SheetPrimitive.Description.Props) {\n return (\n <SheetPrimitive.Description\n data-slot=\"sheet-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Sheet,\n SheetTrigger,\n SheetClose,\n SheetContent,\n SheetHeader,\n SheetFooter,\n SheetTitle,\n SheetDescription,\n}\n","\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { useState, createContext, useContext } from \"react\";\nimport { Sheet, SheetContent, SheetTitle } from \"../ui/sheet\";\nimport { Button } from \"../ui/button\";\n\ninterface AppShellContextValue {\n collapsed: boolean;\n setCollapsed: (v: boolean) => void;\n mobileOpen: boolean;\n setMobileOpen: (v: boolean) => void;\n}\n\nconst AppShellContext = createContext<AppShellContextValue>({\n collapsed: false,\n setCollapsed: () => {},\n mobileOpen: false,\n setMobileOpen: () => {},\n});\n\nexport const useAppShell = () => useContext(AppShellContext);\n\ninterface AppShellProps {\n sidebar: React.ReactNode;\n header?: React.ReactNode;\n children: React.ReactNode;\n defaultCollapsed?: boolean;\n className?: string;\n}\n\nexport function AppShell({\n sidebar,\n header,\n children,\n defaultCollapsed = false,\n className,\n}: AppShellProps) {\n const [collapsed, setCollapsed] = useState(defaultCollapsed);\n const [mobileOpen, setMobileOpen] = useState(false);\n\n return (\n <AppShellContext.Provider\n value={{ collapsed, setCollapsed, mobileOpen, setMobileOpen }}\n >\n <div className={cn(\"flex h-screen bg-background\", className)}>\n <aside\n className={cn(\n \"hidden border-r-brutal border-foreground bg-background transition-all duration-200 md:block\",\n collapsed ? \"w-16\" : \"w-64\"\n )}\n >\n {sidebar}\n </aside>\n <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>\n <SheetContent side=\"left\" className=\"w-64 p-0 md:hidden\">\n <SheetTitle className=\"sr-only\">Navigation</SheetTitle>\n {sidebar}\n </SheetContent>\n </Sheet>\n <div className=\"flex flex-1 flex-col overflow-hidden\">\n {header && (\n <header className=\"flex h-14 items-center gap-4 border-b-brutal border-foreground px-6\">\n <Button\n variant=\"ghost\"\n size=\"sm\"\n className=\"md:hidden\"\n onClick={() => setMobileOpen(true)}\n >\n ☰\n </Button>\n {header}\n </header>\n )}\n <main className=\"flex-1 overflow-auto p-6\">{children}</main>\n </div>\n </div>\n </AppShellContext.Provider>\n );\n}\n"]}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface EmptyStateProps {
|
|
4
|
+
icon?: React.ReactNode;
|
|
5
|
+
headline: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
ctaText?: string;
|
|
8
|
+
ctaHref?: string;
|
|
9
|
+
onAction?: () => void;
|
|
10
|
+
className?: string;
|
|
11
|
+
}
|
|
12
|
+
declare function EmptyState({ icon, headline, description, ctaText, ctaHref, onAction, className, }: EmptyStateProps): react_jsx_runtime.JSX.Element;
|
|
13
|
+
|
|
14
|
+
export { EmptyState };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { Button as Button$1 } from '@base-ui/react/button';
|
|
5
|
+
import { cva } from 'class-variance-authority';
|
|
6
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
7
|
+
|
|
8
|
+
// src/lib/utils.ts
|
|
9
|
+
function cn(...inputs) {
|
|
10
|
+
return twMerge(clsx(inputs));
|
|
11
|
+
}
|
|
12
|
+
var buttonVariants = cva(
|
|
13
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-lg whitespace-nowrap font-bold transition-all duration-150 select-none outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
14
|
+
{
|
|
15
|
+
variants: {
|
|
16
|
+
variant: {
|
|
17
|
+
// Primary: Black bg, white text, offset shadow
|
|
18
|
+
default: "border-brutal border-foreground bg-primary text-primary-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
19
|
+
// CTA: Mint green bg — the Bannerbear signature
|
|
20
|
+
cta: "border-brutal border-foreground bg-cta text-cta-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
21
|
+
// Brand: Dynamic brand color bg
|
|
22
|
+
brand: "border-brutal border-foreground bg-brand text-brand-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
23
|
+
// Outline: White bg, black border, offset shadow
|
|
24
|
+
outline: "border-brutal border-foreground bg-background text-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
25
|
+
// Secondary: Light bg, border, smaller shadow
|
|
26
|
+
secondary: "border-brutal border-foreground bg-secondary text-secondary-foreground shadow-brutal-sm hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal active:translate-x-px active:translate-y-px active:shadow-none",
|
|
27
|
+
// Ghost: No border/shadow, subtle hover
|
|
28
|
+
ghost: "hover:bg-secondary hover:text-foreground",
|
|
29
|
+
// Link: Text only
|
|
30
|
+
link: "text-foreground underline-offset-4 hover:underline",
|
|
31
|
+
// Destructive
|
|
32
|
+
destructive: "border-brutal border-destructive bg-destructive text-destructive-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm",
|
|
33
|
+
// Nav: Thin border, no shadow (for nav Sign In buttons)
|
|
34
|
+
nav: "border border-foreground bg-background text-foreground hover:bg-foreground hover:text-background"
|
|
35
|
+
},
|
|
36
|
+
size: {
|
|
37
|
+
xs: "h-7 gap-1 px-2.5 text-xs",
|
|
38
|
+
sm: "h-8 gap-1.5 px-3 text-sm",
|
|
39
|
+
default: "h-10 gap-2 px-5 text-sm",
|
|
40
|
+
lg: "h-12 gap-2 px-7 text-base",
|
|
41
|
+
xl: "h-14 gap-2.5 px-9 text-lg",
|
|
42
|
+
icon: "size-10",
|
|
43
|
+
"icon-sm": "size-8",
|
|
44
|
+
"icon-lg": "size-12"
|
|
45
|
+
}
|
|
46
|
+
},
|
|
47
|
+
defaultVariants: {
|
|
48
|
+
variant: "default",
|
|
49
|
+
size: "default"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
function Button({
|
|
54
|
+
className,
|
|
55
|
+
variant = "default",
|
|
56
|
+
size = "default",
|
|
57
|
+
...props
|
|
58
|
+
}) {
|
|
59
|
+
return /* @__PURE__ */ jsx(
|
|
60
|
+
Button$1,
|
|
61
|
+
{
|
|
62
|
+
"data-slot": "button",
|
|
63
|
+
className: cn(buttonVariants({ variant, size, className })),
|
|
64
|
+
...props
|
|
65
|
+
}
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
function EmptyState({
|
|
69
|
+
icon,
|
|
70
|
+
headline,
|
|
71
|
+
description,
|
|
72
|
+
ctaText,
|
|
73
|
+
ctaHref,
|
|
74
|
+
onAction,
|
|
75
|
+
className
|
|
76
|
+
}) {
|
|
77
|
+
return /* @__PURE__ */ jsxs(
|
|
78
|
+
"div",
|
|
79
|
+
{
|
|
80
|
+
className: cn(
|
|
81
|
+
"flex flex-col items-center justify-center py-16 text-center",
|
|
82
|
+
className
|
|
83
|
+
),
|
|
84
|
+
children: [
|
|
85
|
+
icon && /* @__PURE__ */ jsx("div", { className: "mb-4 flex size-16 items-center justify-center border-brutal border-foreground bg-secondary text-3xl shadow-brutal-sm", children: icon }),
|
|
86
|
+
/* @__PURE__ */ jsx("h3", { className: "brutal-h3 mb-2", children: headline }),
|
|
87
|
+
description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-6 max-w-sm text-muted-foreground", children: description }),
|
|
88
|
+
ctaText && (ctaHref ? /* @__PURE__ */ jsx(Button, { variant: "cta", render: /* @__PURE__ */ jsx("a", { href: ctaHref }), children: ctaText }) : /* @__PURE__ */ jsx(Button, { variant: "cta", onClick: onAction, children: ctaText }))
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export { EmptyState };
|
|
95
|
+
//# sourceMappingURL=empty-state.js.map
|
|
96
|
+
//# sourceMappingURL=empty-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/button.tsx","../../../src/components/dashboard/empty-state.tsx"],"names":["ButtonPrimitive","jsx"],"mappings":";;;;;;;AAGO,SAAS,MAAM,MAAA,EAAsB;AAC1C,EAAA,OAAO,OAAA,CAAQ,IAAA,CAAK,MAAM,CAAC,CAAA;AAC7B;ACEA,IAAM,cAAA,GAAiB,GAAA;AAAA,EACrB,8RAAA;AAAA,EACA;AAAA,IACE,QAAA,EAAU;AAAA,MACR,OAAA,EAAS;AAAA;AAAA,QAEP,OAAA,EACE,2NAAA;AAAA;AAAA,QAEF,GAAA,EAAK,mNAAA;AAAA;AAAA,QAEL,KAAA,EACE,uNAAA;AAAA;AAAA,QAEF,OAAA,EACE,sNAAA;AAAA;AAAA,QAEF,SAAA,EACE,0NAAA;AAAA;AAAA,QAEF,KAAA,EAAO,0CAAA;AAAA;AAAA,QAEP,IAAA,EAAM,oDAAA;AAAA;AAAA,QAEN,WAAA,EACE,oOAAA;AAAA;AAAA,QAEF,GAAA,EAAK;AAAA,OACP;AAAA,MACA,IAAA,EAAM;AAAA,QACJ,EAAA,EAAI,0BAAA;AAAA,QACJ,EAAA,EAAI,0BAAA;AAAA,QACJ,OAAA,EAAS,yBAAA;AAAA,QACT,EAAA,EAAI,2BAAA;AAAA,QACJ,EAAA,EAAI,2BAAA;AAAA,QACJ,IAAA,EAAM,SAAA;AAAA,QACN,SAAA,EAAW,QAAA;AAAA,QACX,SAAA,EAAW;AAAA;AACb,KACF;AAAA,IACA,eAAA,EAAiB;AAAA,MACf,OAAA,EAAS,SAAA;AAAA,MACT,IAAA,EAAM;AAAA;AACR;AAEJ,CAAA;AAEA,SAAS,MAAA,CAAO;AAAA,EACd,SAAA;AAAA,EACA,OAAA,GAAU,SAAA;AAAA,EACV,IAAA,GAAO,SAAA;AAAA,EACP,GAAG;AACL,CAAA,EAAgE;AAC9D,EAAA,uBACE,GAAA;AAAA,IAACA,QAAA;AAAA,IAAA;AAAA,MACC,WAAA,EAAU,QAAA;AAAA,MACV,SAAA,EAAW,GAAG,cAAA,CAAe,EAAE,SAAS,IAAA,EAAM,SAAA,EAAW,CAAC,CAAA;AAAA,MACzD,GAAG;AAAA;AAAA,GACN;AAEJ;ACtDO,SAAS,UAAA,CAAW;AAAA,EACzB,IAAA;AAAA,EACA,QAAA;AAAA,EACA,WAAA;AAAA,EACA,OAAA;AAAA,EACA,OAAA;AAAA,EACA,QAAA;AAAA,EACA;AACF,CAAA,EAAoB;AAClB,EAAA,uBACE,IAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,6DAAA;AAAA,QACA;AAAA,OACF;AAAA,MAEC,QAAA,EAAA;AAAA,QAAA,IAAA,oBACCC,GAAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,wHACZ,QAAA,EAAA,IAAA,EACH,CAAA;AAAA,wBAEFA,GAAAA,CAAC,IAAA,EAAA,EAAG,SAAA,EAAU,kBAAkB,QAAA,EAAA,QAAA,EAAS,CAAA;AAAA,QACxC,+BACCA,GAAAA,CAAC,GAAA,EAAA,EAAE,SAAA,EAAU,mDACV,QAAA,EAAA,WAAA,EACH,CAAA;AAAA,QAED,OAAA,KACE,0BACCA,GAAAA,CAAC,UAAO,OAAA,EAAQ,KAAA,EAAM,MAAA,kBAAQA,GAAAA,CAAC,GAAA,EAAA,EAAE,MAAM,OAAA,EAAS,CAAA,EAC7C,QAAA,EAAA,OAAA,EACH,CAAA,mBAEAA,GAAAA,CAAC,UAAO,OAAA,EAAQ,KAAA,EAAM,OAAA,EAAS,QAAA,EAC5B,QAAA,EAAA,OAAA,EACH,CAAA;AAAA;AAAA;AAAA,GAEN;AAEJ","file":"empty-state.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\";\n\nimport { Button as ButtonPrimitive } from \"@base-ui/react/button\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\n\nimport { cn } from \"../../lib/utils\";\n\nconst buttonVariants = cva(\n \"group/button inline-flex shrink-0 items-center justify-center rounded-lg whitespace-nowrap font-bold transition-all duration-150 select-none outline-none disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n // Primary: Black bg, white text, offset shadow\n default:\n \"border-brutal border-foreground bg-primary text-primary-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // CTA: Mint green bg — the Bannerbear signature\n cta: \"border-brutal border-foreground bg-cta text-cta-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Brand: Dynamic brand color bg\n brand:\n \"border-brutal border-foreground bg-brand text-brand-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Outline: White bg, black border, offset shadow\n outline:\n \"border-brutal border-foreground bg-background text-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Secondary: Light bg, border, smaller shadow\n secondary:\n \"border-brutal border-foreground bg-secondary text-secondary-foreground shadow-brutal-sm hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal active:translate-x-px active:translate-y-px active:shadow-none\",\n // Ghost: No border/shadow, subtle hover\n ghost: \"hover:bg-secondary hover:text-foreground\",\n // Link: Text only\n link: \"text-foreground underline-offset-4 hover:underline\",\n // Destructive\n destructive:\n \"border-brutal border-destructive bg-destructive text-destructive-foreground shadow-brutal hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg active:translate-x-px active:translate-y-px active:shadow-brutal-sm\",\n // Nav: Thin border, no shadow (for nav Sign In buttons)\n nav: \"border border-foreground bg-background text-foreground hover:bg-foreground hover:text-background\",\n },\n size: {\n xs: \"h-7 gap-1 px-2.5 text-xs\",\n sm: \"h-8 gap-1.5 px-3 text-sm\",\n default: \"h-10 gap-2 px-5 text-sm\",\n lg: \"h-12 gap-2 px-7 text-base\",\n xl: \"h-14 gap-2.5 px-9 text-lg\",\n icon: \"size-10\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-12\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n ...props\n}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {\n return (\n <ButtonPrimitive\n data-slot=\"button\"\n className={cn(buttonVariants({ variant, size, className }))}\n {...props}\n />\n );\n}\n\nexport { Button, buttonVariants };\n","import { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\n\ninterface EmptyStateProps {\n icon?: React.ReactNode;\n headline: string;\n description?: string;\n ctaText?: string;\n ctaHref?: string;\n onAction?: () => void;\n className?: string;\n}\n\nexport function EmptyState({\n icon,\n headline,\n description,\n ctaText,\n ctaHref,\n onAction,\n className,\n}: EmptyStateProps) {\n return (\n <div\n className={cn(\n \"flex flex-col items-center justify-center py-16 text-center\",\n className\n )}\n >\n {icon && (\n <div className=\"mb-4 flex size-16 items-center justify-center border-brutal border-foreground bg-secondary text-3xl shadow-brutal-sm\">\n {icon}\n </div>\n )}\n <h3 className=\"brutal-h3 mb-2\">{headline}</h3>\n {description && (\n <p className=\"brutal-body mb-6 max-w-sm text-muted-foreground\">\n {description}\n </p>\n )}\n {ctaText &&\n (ctaHref ? (\n <Button variant=\"cta\" render={<a href={ctaHref} />}>\n {ctaText}\n </Button>\n ) : (\n <Button variant=\"cta\" onClick={onAction}>\n {ctaText}\n </Button>\n ))}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
interface FileUploadProps {
|
|
4
|
+
onFiles: (files: File[]) => void;
|
|
5
|
+
accept?: string;
|
|
6
|
+
maxFiles?: number;
|
|
7
|
+
maxSize?: number;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
declare function FileUpload({ onFiles, accept, maxFiles, maxSize, className, }: FileUploadProps): react_jsx_runtime.JSX.Element;
|
|
11
|
+
|
|
12
|
+
export { FileUpload };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { clsx } from 'clsx';
|
|
3
|
+
import { twMerge } from 'tailwind-merge';
|
|
4
|
+
import { useState, useCallback } from 'react';
|
|
5
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
|
+
|
|
7
|
+
function cn(...inputs) {
|
|
8
|
+
return twMerge(clsx(inputs));
|
|
9
|
+
}
|
|
10
|
+
function FileUpload({
|
|
11
|
+
onFiles,
|
|
12
|
+
accept,
|
|
13
|
+
maxFiles = 10,
|
|
14
|
+
maxSize,
|
|
15
|
+
className
|
|
16
|
+
}) {
|
|
17
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
18
|
+
const [files, setFiles] = useState([]);
|
|
19
|
+
const handleFiles = useCallback(
|
|
20
|
+
(newFiles) => {
|
|
21
|
+
const arr = Array.from(newFiles).slice(0, maxFiles);
|
|
22
|
+
setFiles(arr);
|
|
23
|
+
onFiles(arr);
|
|
24
|
+
},
|
|
25
|
+
[maxFiles, onFiles]
|
|
26
|
+
);
|
|
27
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-4", className), children: [
|
|
28
|
+
/* @__PURE__ */ jsxs(
|
|
29
|
+
"div",
|
|
30
|
+
{
|
|
31
|
+
onDragOver: (e) => {
|
|
32
|
+
e.preventDefault();
|
|
33
|
+
setIsDragging(true);
|
|
34
|
+
},
|
|
35
|
+
onDragLeave: () => setIsDragging(false),
|
|
36
|
+
onDrop: (e) => {
|
|
37
|
+
e.preventDefault();
|
|
38
|
+
setIsDragging(false);
|
|
39
|
+
handleFiles(e.dataTransfer.files);
|
|
40
|
+
},
|
|
41
|
+
className: cn(
|
|
42
|
+
"flex cursor-pointer flex-col items-center justify-center border-2 border-dashed border-foreground p-8 text-center transition-colors",
|
|
43
|
+
isDragging && "border-brand bg-brand-muted"
|
|
44
|
+
),
|
|
45
|
+
onClick: () => {
|
|
46
|
+
const input = document.createElement("input");
|
|
47
|
+
input.type = "file";
|
|
48
|
+
input.multiple = maxFiles > 1;
|
|
49
|
+
if (accept) input.accept = accept;
|
|
50
|
+
input.onchange = (e) => {
|
|
51
|
+
const target = e.target;
|
|
52
|
+
if (target.files) handleFiles(target.files);
|
|
53
|
+
};
|
|
54
|
+
input.click();
|
|
55
|
+
},
|
|
56
|
+
children: [
|
|
57
|
+
/* @__PURE__ */ jsx("p", { className: "brutal-h4 mb-1", children: "Drop files here" }),
|
|
58
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "or click to browse" }),
|
|
59
|
+
maxSize && /* @__PURE__ */ jsxs("p", { className: "mt-2 font-mono text-xs text-muted-foreground", children: [
|
|
60
|
+
"Max ",
|
|
61
|
+
Math.round(maxSize / 1024 / 1024),
|
|
62
|
+
"MB"
|
|
63
|
+
] })
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
),
|
|
67
|
+
files.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: files.map((file, i) => /* @__PURE__ */ jsxs(
|
|
68
|
+
"div",
|
|
69
|
+
{
|
|
70
|
+
className: "flex items-center justify-between border border-foreground bg-secondary px-3 py-2 text-sm",
|
|
71
|
+
children: [
|
|
72
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: file.name }),
|
|
73
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground", children: [
|
|
74
|
+
(file.size / 1024).toFixed(0),
|
|
75
|
+
"KB"
|
|
76
|
+
] })
|
|
77
|
+
]
|
|
78
|
+
},
|
|
79
|
+
i
|
|
80
|
+
)) })
|
|
81
|
+
] });
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export { FileUpload };
|
|
85
|
+
//# sourceMappingURL=file-upload.js.map
|
|
86
|
+
//# sourceMappingURL=file-upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/dashboard/file-upload.tsx"],"names":[],"mappings":"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","file":"file-upload.js","sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\";\n\nimport { cn } from \"../../lib/utils\";\nimport { useState, useCallback } from \"react\";\n\ninterface FileUploadProps {\n onFiles: (files: File[]) => void;\n accept?: string;\n maxFiles?: number;\n maxSize?: number;\n className?: string;\n}\n\nexport function FileUpload({\n onFiles,\n accept,\n maxFiles = 10,\n maxSize,\n className,\n}: FileUploadProps) {\n const [isDragging, setIsDragging] = useState(false);\n const [files, setFiles] = useState<File[]>([]);\n\n const handleFiles = useCallback(\n (newFiles: FileList | File[]) => {\n const arr = Array.from(newFiles).slice(0, maxFiles);\n setFiles(arr);\n onFiles(arr);\n },\n [maxFiles, onFiles]\n );\n\n return (\n <div className={cn(\"flex flex-col gap-4\", className)}>\n <div\n onDragOver={(e) => {\n e.preventDefault();\n setIsDragging(true);\n }}\n onDragLeave={() => setIsDragging(false)}\n onDrop={(e) => {\n e.preventDefault();\n setIsDragging(false);\n handleFiles(e.dataTransfer.files);\n }}\n className={cn(\n \"flex cursor-pointer flex-col items-center justify-center border-2 border-dashed border-foreground p-8 text-center transition-colors\",\n isDragging && \"border-brand bg-brand-muted\"\n )}\n onClick={() => {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.multiple = maxFiles > 1;\n if (accept) input.accept = accept;\n input.onchange = (e) => {\n const target = e.target as HTMLInputElement;\n if (target.files) handleFiles(target.files);\n };\n input.click();\n }}\n >\n <p className=\"brutal-h4 mb-1\">Drop files here</p>\n <p className=\"text-sm text-muted-foreground\">or click to browse</p>\n {maxSize && (\n <p className=\"mt-2 font-mono text-xs text-muted-foreground\">\n Max {Math.round(maxSize / 1024 / 1024)}MB\n </p>\n )}\n </div>\n\n {files.length > 0 && (\n <div className=\"flex flex-col gap-2\">\n {files.map((file, i) => (\n <div\n key={i}\n className=\"flex items-center justify-between border border-foreground bg-secondary px-3 py-2 text-sm\"\n >\n <span className=\"truncate\">{file.name}</span>\n <span className=\"font-mono text-xs text-muted-foreground\">\n {(file.size / 1024).toFixed(0)}KB\n </span>\n </div>\n ))}\n </div>\n )}\n </div>\n );\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { AppShell, useAppShell } from './app-shell.js';
|
|
2
|
+
export { Sidebar } from './sidebar.js';
|
|
3
|
+
export { StatCard } from './stat-card.js';
|
|
4
|
+
export { ActivityFeed } from './activity-feed.js';
|
|
5
|
+
export { EmptyState } from './empty-state.js';
|
|
6
|
+
export { SearchBar } from './search-bar.js';
|
|
7
|
+
export { UserMenu } from './user-menu.js';
|
|
8
|
+
export { ViewSwitcher } from './view-switcher.js';
|
|
9
|
+
export { FileUpload } from './file-upload.js';
|
|
10
|
+
import 'react/jsx-runtime';
|