@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.
Files changed (116) hide show
  1. package/dist/components/brutal/cta-section.d.ts +7 -2
  2. package/dist/components/brutal/cta-section.js +136 -32
  3. package/dist/components/brutal/cta-section.js.map +1 -1
  4. package/dist/components/brutal/faq.d.ts +16 -0
  5. package/dist/components/brutal/faq.js +163 -0
  6. package/dist/components/brutal/faq.js.map +1 -0
  7. package/dist/components/brutal/feature-grid.d.ts +6 -2
  8. package/dist/components/brutal/feature-grid.js +73 -10
  9. package/dist/components/brutal/feature-grid.js.map +1 -1
  10. package/dist/components/brutal/footer.d.ts +14 -1
  11. package/dist/components/brutal/footer.js +181 -18
  12. package/dist/components/brutal/footer.js.map +1 -1
  13. package/dist/components/brutal/hero.d.ts +9 -2
  14. package/dist/components/brutal/hero.js +67 -22
  15. package/dist/components/brutal/hero.js.map +1 -1
  16. package/dist/components/brutal/index.d.ts +7 -2
  17. package/dist/components/brutal/index.js +1035 -128
  18. package/dist/components/brutal/index.js.map +1 -1
  19. package/dist/components/brutal/integration-grid.d.ts +1 -1
  20. package/dist/components/brutal/integration-grid.js +13 -5
  21. package/dist/components/brutal/integration-grid.js.map +1 -1
  22. package/dist/components/brutal/logo-cloud.d.ts +17 -0
  23. package/dist/components/brutal/logo-cloud.js +93 -0
  24. package/dist/components/brutal/logo-cloud.js.map +1 -0
  25. package/dist/components/brutal/nav.d.ts +3 -1
  26. package/dist/components/brutal/nav.js +166 -9
  27. package/dist/components/brutal/nav.js.map +1 -1
  28. package/dist/components/brutal/newsletter.d.ts +14 -0
  29. package/dist/components/brutal/newsletter.js +169 -0
  30. package/dist/components/brutal/newsletter.js.map +1 -0
  31. package/dist/components/brutal/pricing-table.d.ts +27 -0
  32. package/dist/components/brutal/pricing-table.js +251 -0
  33. package/dist/components/brutal/pricing-table.js.map +1 -0
  34. package/dist/components/brutal/section-divider.d.ts +14 -0
  35. package/dist/components/brutal/section-divider.js +70 -0
  36. package/dist/components/brutal/section-divider.js.map +1 -0
  37. package/dist/components/brutal/section.d.ts +7 -3
  38. package/dist/components/brutal/section.js +13 -5
  39. package/dist/components/brutal/section.js.map +1 -1
  40. package/dist/components/brutal/stats-bar.d.ts +16 -0
  41. package/dist/components/brutal/stats-bar.js +127 -0
  42. package/dist/components/brutal/stats-bar.js.map +1 -0
  43. package/dist/components/brutal/testimonials.d.ts +11 -3
  44. package/dist/components/brutal/testimonials.js +126 -33
  45. package/dist/components/brutal/testimonials.js.map +1 -1
  46. package/dist/components/brutal/wave-divider.d.ts +2 -12
  47. package/dist/components/brutal/wave-divider.js +54 -26
  48. package/dist/components/brutal/wave-divider.js.map +1 -1
  49. package/dist/components/dashboard/activity-feed.d.ts +18 -0
  50. package/dist/components/dashboard/activity-feed.js +105 -0
  51. package/dist/components/dashboard/activity-feed.js.map +1 -0
  52. package/dist/components/dashboard/app-shell.d.ts +19 -0
  53. package/dist/components/dashboard/app-shell.js +206 -0
  54. package/dist/components/dashboard/app-shell.js.map +1 -0
  55. package/dist/components/dashboard/empty-state.d.ts +14 -0
  56. package/dist/components/dashboard/empty-state.js +96 -0
  57. package/dist/components/dashboard/empty-state.js.map +1 -0
  58. package/dist/components/dashboard/file-upload.d.ts +12 -0
  59. package/dist/components/dashboard/file-upload.js +86 -0
  60. package/dist/components/dashboard/file-upload.js.map +1 -0
  61. package/dist/components/dashboard/index.d.ts +10 -0
  62. package/dist/components/dashboard/index.js +755 -0
  63. package/dist/components/dashboard/index.js.map +1 -0
  64. package/dist/components/dashboard/search-bar.d.ts +12 -0
  65. package/dist/components/dashboard/search-bar.js +49 -0
  66. package/dist/components/dashboard/search-bar.js.map +1 -0
  67. package/dist/components/dashboard/sidebar.d.ts +23 -0
  68. package/dist/components/dashboard/sidebar.js +113 -0
  69. package/dist/components/dashboard/sidebar.js.map +1 -0
  70. package/dist/components/dashboard/stat-card.d.ts +13 -0
  71. package/dist/components/dashboard/stat-card.js +55 -0
  72. package/dist/components/dashboard/stat-card.js.map +1 -0
  73. package/dist/components/dashboard/user-menu.d.ts +16 -0
  74. package/dist/components/dashboard/user-menu.js +179 -0
  75. package/dist/components/dashboard/user-menu.js.map +1 -0
  76. package/dist/components/dashboard/view-switcher.d.ts +12 -0
  77. package/dist/components/dashboard/view-switcher.js +130 -0
  78. package/dist/components/dashboard/view-switcher.js.map +1 -0
  79. package/dist/components/views/calendar-view.d.ts +17 -0
  80. package/dist/components/views/calendar-view.js +182 -0
  81. package/dist/components/views/calendar-view.js.map +1 -0
  82. package/dist/components/views/data-table.d.ts +15 -0
  83. package/dist/components/views/data-table.js +204 -0
  84. package/dist/components/views/data-table.js.map +1 -0
  85. package/dist/components/views/grid-view.d.ts +11 -0
  86. package/dist/components/views/grid-view.js +31 -0
  87. package/dist/components/views/grid-view.js.map +1 -0
  88. package/dist/components/views/index.d.ts +7 -0
  89. package/dist/components/views/index.js +542 -0
  90. package/dist/components/views/index.js.map +1 -0
  91. package/dist/components/views/kanban-board.d.ts +21 -0
  92. package/dist/components/views/kanban-board.js +153 -0
  93. package/dist/components/views/kanban-board.js.map +1 -0
  94. package/dist/components/views/list-view.d.ts +19 -0
  95. package/dist/components/views/list-view.js +96 -0
  96. package/dist/components/views/list-view.js.map +1 -0
  97. package/dist/index.d.ts +27 -3
  98. package/dist/index.js +1881 -142
  99. package/dist/index.js.map +1 -1
  100. package/dist/lib/animations.d.ts +68 -0
  101. package/dist/lib/animations.js +44 -0
  102. package/dist/lib/animations.js.map +1 -0
  103. package/dist/templates/dashboard.d.ts +40 -0
  104. package/dist/templates/dashboard.js +658 -0
  105. package/dist/templates/dashboard.js.map +1 -0
  106. package/dist/templates/index.d.ts +4 -0
  107. package/dist/templates/index.js +2001 -0
  108. package/dist/templates/index.js.map +1 -0
  109. package/dist/templates/saas-launch.d.ts +113 -0
  110. package/dist/templates/saas-launch.js +1394 -0
  111. package/dist/templates/saas-launch.js.map +1 -0
  112. package/dist/templates/studio.d.ts +72 -0
  113. package/dist/templates/studio.js +1099 -0
  114. package/dist/templates/studio.js.map +1 -0
  115. package/dist/theme.css +58 -15
  116. package/package.json +48 -2
@@ -0,0 +1,2001 @@
1
+ "use client";
2
+ import * as React from 'react';
3
+ import { createContext, useState, useEffect, useRef, useContext } from 'react';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { Button as Button$1 } from '@base-ui/react/button';
7
+ import { cva } from 'class-variance-authority';
8
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
9
+ import { Dialog } from '@base-ui/react/dialog';
10
+ import { Menu, XIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
11
+ import { mergeProps } from '@base-ui/react/merge-props';
12
+ import { useRender } from '@base-ui/react/use-render';
13
+ import { Accordion as Accordion$1 } from '@base-ui/react/accordion';
14
+ import { Input as Input$1 } from '@base-ui/react/input';
15
+ import { Menu as Menu$1 } from '@base-ui/react/menu';
16
+ import { Avatar as Avatar$1 } from '@base-ui/react/avatar';
17
+ import { Toggle } from '@base-ui/react/toggle';
18
+ import { ToggleGroup as ToggleGroup$1 } from '@base-ui/react/toggle-group';
19
+
20
+ // src/components/brutal/nav.tsx
21
+ function cn(...inputs) {
22
+ return twMerge(clsx(inputs));
23
+ }
24
+ var buttonVariants = cva(
25
+ "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",
26
+ {
27
+ variants: {
28
+ variant: {
29
+ // Primary: Black bg, white text, offset shadow
30
+ 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",
31
+ // CTA: Mint green bg — the Bannerbear signature
32
+ 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",
33
+ // Brand: Dynamic brand color bg
34
+ 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",
35
+ // Outline: White bg, black border, offset shadow
36
+ 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",
37
+ // Secondary: Light bg, border, smaller shadow
38
+ 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",
39
+ // Ghost: No border/shadow, subtle hover
40
+ ghost: "hover:bg-secondary hover:text-foreground",
41
+ // Link: Text only
42
+ link: "text-foreground underline-offset-4 hover:underline",
43
+ // Destructive
44
+ 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",
45
+ // Nav: Thin border, no shadow (for nav Sign In buttons)
46
+ nav: "border border-foreground bg-background text-foreground hover:bg-foreground hover:text-background"
47
+ },
48
+ size: {
49
+ xs: "h-7 gap-1 px-2.5 text-xs",
50
+ sm: "h-8 gap-1.5 px-3 text-sm",
51
+ default: "h-10 gap-2 px-5 text-sm",
52
+ lg: "h-12 gap-2 px-7 text-base",
53
+ xl: "h-14 gap-2.5 px-9 text-lg",
54
+ icon: "size-10",
55
+ "icon-sm": "size-8",
56
+ "icon-lg": "size-12"
57
+ }
58
+ },
59
+ defaultVariants: {
60
+ variant: "default",
61
+ size: "default"
62
+ }
63
+ }
64
+ );
65
+ function Button({
66
+ className,
67
+ variant = "default",
68
+ size = "default",
69
+ ...props
70
+ }) {
71
+ return /* @__PURE__ */ jsx(
72
+ Button$1,
73
+ {
74
+ "data-slot": "button",
75
+ className: cn(buttonVariants({ variant, size, className })),
76
+ ...props
77
+ }
78
+ );
79
+ }
80
+ function Sheet({ ...props }) {
81
+ return /* @__PURE__ */ jsx(Dialog.Root, { "data-slot": "sheet", ...props });
82
+ }
83
+ function SheetTrigger({ ...props }) {
84
+ return /* @__PURE__ */ jsx(Dialog.Trigger, { "data-slot": "sheet-trigger", ...props });
85
+ }
86
+ function SheetPortal({ ...props }) {
87
+ return /* @__PURE__ */ jsx(Dialog.Portal, { "data-slot": "sheet-portal", ...props });
88
+ }
89
+ function SheetOverlay({ className, ...props }) {
90
+ return /* @__PURE__ */ jsx(
91
+ Dialog.Backdrop,
92
+ {
93
+ "data-slot": "sheet-overlay",
94
+ className: cn(
95
+ "fixed inset-0 z-50 bg-black/60 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0",
96
+ className
97
+ ),
98
+ ...props
99
+ }
100
+ );
101
+ }
102
+ function SheetContent({
103
+ className,
104
+ children,
105
+ side = "right",
106
+ showCloseButton = true,
107
+ ...props
108
+ }) {
109
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
110
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
111
+ /* @__PURE__ */ jsxs(
112
+ Dialog.Popup,
113
+ {
114
+ "data-slot": "sheet-content",
115
+ "data-side": side,
116
+ className: cn(
117
+ "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",
118
+ className
119
+ ),
120
+ ...props,
121
+ children: [
122
+ children,
123
+ showCloseButton && /* @__PURE__ */ jsxs(
124
+ Dialog.Close,
125
+ {
126
+ "data-slot": "sheet-close",
127
+ render: /* @__PURE__ */ jsx(
128
+ Button,
129
+ {
130
+ variant: "ghost",
131
+ className: "absolute top-3 right-3",
132
+ size: "icon-sm"
133
+ }
134
+ ),
135
+ children: [
136
+ /* @__PURE__ */ jsx(
137
+ XIcon,
138
+ {}
139
+ ),
140
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
141
+ ]
142
+ }
143
+ )
144
+ ]
145
+ }
146
+ )
147
+ ] });
148
+ }
149
+ function SheetTitle({ className, ...props }) {
150
+ return /* @__PURE__ */ jsx(
151
+ Dialog.Title,
152
+ {
153
+ "data-slot": "sheet-title",
154
+ className: cn("text-base font-bold text-foreground", className),
155
+ ...props
156
+ }
157
+ );
158
+ }
159
+ function BrutalNav({
160
+ logo,
161
+ links,
162
+ ctaText = "Sign In",
163
+ ctaHref = "/admin",
164
+ variant = "solid",
165
+ className
166
+ }) {
167
+ const [mobileOpen, setMobileOpen] = useState(false);
168
+ const [isScrolled, setIsScrolled] = useState(false);
169
+ useEffect(() => {
170
+ if (variant !== "transparent") return;
171
+ const onScroll = () => setIsScrolled(window.scrollY > 20);
172
+ onScroll();
173
+ window.addEventListener("scroll", onScroll, { passive: true });
174
+ return () => window.removeEventListener("scroll", onScroll);
175
+ }, [variant]);
176
+ const variantStyles = {
177
+ solid: "sticky top-0 z-50 w-full border-b-brutal border-foreground bg-brand",
178
+ transparent: cn(
179
+ "fixed top-0 left-0 right-0 z-50 w-full transition-all duration-200",
180
+ isScrolled ? "bg-background/80 text-foreground backdrop-blur-md border-b border-foreground/10" : "bg-transparent text-white"
181
+ ),
182
+ "floating-pill": "fixed top-0 left-0 right-0 z-50 mx-4 mt-4 rounded-full border-brutal border-foreground bg-background shadow-brutal"
183
+ };
184
+ return /* @__PURE__ */ jsx("header", { className: cn(variantStyles[variant], className), children: /* @__PURE__ */ jsxs(
185
+ "div",
186
+ {
187
+ className: cn(
188
+ "flex h-14 items-center justify-between px-6",
189
+ variant === "floating-pill" ? "mx-auto max-w-7xl" : "brutal-container"
190
+ ),
191
+ children: [
192
+ /* @__PURE__ */ jsx("a", { href: "/", className: "flex items-center gap-2 text-lg font-black", children: logo }),
193
+ /* @__PURE__ */ jsx("nav", { className: "hidden items-center gap-1 md:flex", children: links.map((link) => /* @__PURE__ */ jsxs(
194
+ "a",
195
+ {
196
+ href: link.href,
197
+ className: cn(
198
+ "relative rounded-md px-3 py-1.5 text-sm font-bold transition-colors hover:opacity-70",
199
+ link.active && "bg-foreground/10"
200
+ ),
201
+ children: [
202
+ link.label,
203
+ link.badge && /* @__PURE__ */ jsx("span", { className: "absolute -top-1 -right-1 border border-foreground bg-background px-1 font-mono text-[9px] font-bold uppercase text-foreground", children: link.badge })
204
+ ]
205
+ },
206
+ link.href
207
+ )) }),
208
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
209
+ /* @__PURE__ */ jsx(
210
+ Button,
211
+ {
212
+ variant: "nav",
213
+ size: "sm",
214
+ render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
215
+ className: "hidden md:inline-flex",
216
+ children: ctaText
217
+ }
218
+ ),
219
+ /* @__PURE__ */ jsxs(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
220
+ /* @__PURE__ */ jsxs(
221
+ SheetTrigger,
222
+ {
223
+ render: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", className: "md:hidden" }),
224
+ children: [
225
+ /* @__PURE__ */ jsx(Menu, { className: "size-5" }),
226
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Menu" })
227
+ ]
228
+ }
229
+ ),
230
+ /* @__PURE__ */ jsxs(SheetContent, { side: "right", showCloseButton: true, children: [
231
+ /* @__PURE__ */ jsx(SheetTitle, { children: "Navigation" }),
232
+ /* @__PURE__ */ jsxs("nav", { className: "flex flex-col gap-1 px-2 pt-4", children: [
233
+ links.map((link) => /* @__PURE__ */ jsxs(
234
+ "a",
235
+ {
236
+ href: link.href,
237
+ onClick: () => setMobileOpen(false),
238
+ className: cn(
239
+ "flex items-center gap-2 rounded-md px-3 py-2.5 text-sm font-bold transition-colors hover:bg-foreground/5",
240
+ link.active && "bg-foreground/10"
241
+ ),
242
+ children: [
243
+ link.label,
244
+ link.badge && /* @__PURE__ */ jsx("span", { className: "border border-foreground bg-background px-1 font-mono text-[9px] font-bold uppercase text-foreground", children: link.badge })
245
+ ]
246
+ },
247
+ link.href
248
+ )),
249
+ /* @__PURE__ */ jsx("div", { className: "mt-4 border-t border-foreground/10 pt-4", children: /* @__PURE__ */ jsx(
250
+ Button,
251
+ {
252
+ variant: "default",
253
+ size: "default",
254
+ render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
255
+ className: "w-full",
256
+ children: ctaText
257
+ }
258
+ ) })
259
+ ] })
260
+ ] })
261
+ ] })
262
+ ] })
263
+ ]
264
+ }
265
+ ) });
266
+ }
267
+ var colorMap = {
268
+ white: "bg-background text-foreground",
269
+ brand: "bg-brand",
270
+ "brand-muted": "bg-brand-muted text-foreground",
271
+ black: "bg-foreground text-background",
272
+ cta: "bg-cta"
273
+ };
274
+ var containerMap = {
275
+ sm: "brutal-container-sm",
276
+ default: "brutal-container",
277
+ lg: "brutal-container-lg"
278
+ };
279
+ var paddingMap = {
280
+ sm: "brutal-section-sm",
281
+ default: "brutal-section",
282
+ lg: "brutal-section py-28 sm:py-36 md:py-44"
283
+ };
284
+ var patternMap = {
285
+ dots: "brutal-dots",
286
+ stripes: "brutal-stripes",
287
+ noise: "brutal-noise",
288
+ grain: "brutal-grain",
289
+ crosshatch: "brutal-crosshatch",
290
+ "grid-dots": "brutal-grid-dots",
291
+ "gradient-mesh": "brutal-gradient-mesh",
292
+ none: ""
293
+ };
294
+ function BrutalSection({
295
+ children,
296
+ color = "white",
297
+ className,
298
+ containerSize = "default",
299
+ padding = "default",
300
+ pattern,
301
+ dots = false,
302
+ stripes = false,
303
+ id
304
+ }) {
305
+ const resolvedPattern = pattern ?? (dots ? "dots" : void 0) ?? (stripes ? "stripes" : void 0) ?? "none";
306
+ return /* @__PURE__ */ jsx(
307
+ "section",
308
+ {
309
+ id,
310
+ className: cn(
311
+ paddingMap[padding],
312
+ colorMap[color],
313
+ patternMap[resolvedPattern],
314
+ className
315
+ ),
316
+ children: /* @__PURE__ */ jsx("div", { className: containerMap[containerSize], children })
317
+ }
318
+ );
319
+ }
320
+ function BrutalHero({
321
+ variant = "split",
322
+ badge,
323
+ badgePosition = "above",
324
+ headline,
325
+ description,
326
+ ctaText,
327
+ ctaHref = "#",
328
+ ctaVariant = "cta",
329
+ secondaryText,
330
+ secondaryHref,
331
+ visual,
332
+ color = "brand",
333
+ pattern,
334
+ proof,
335
+ className
336
+ }) {
337
+ const badgeElement = badge && /* @__PURE__ */ jsx(
338
+ "div",
339
+ {
340
+ className: cn(
341
+ "inline-flex w-fit border-brutal border-foreground bg-background px-3 py-1 font-mono text-xs font-bold uppercase tracking-widest text-foreground shadow-brutal-sm",
342
+ badgePosition === "floating" && "absolute -top-3 left-6 z-10"
343
+ ),
344
+ children: badge
345
+ }
346
+ );
347
+ const textContent = /* @__PURE__ */ jsxs("div", { className: cn(
348
+ "flex flex-col gap-6",
349
+ variant === "centered" && "items-center text-center"
350
+ ), children: [
351
+ badgePosition === "above" && badgeElement,
352
+ /* @__PURE__ */ jsxs("h1", { className: cn(
353
+ "brutal-display text-balance",
354
+ variant === "centered" && "mx-auto max-w-4xl"
355
+ ), children: [
356
+ badgePosition === "inline" && badgeElement,
357
+ headline
358
+ ] }),
359
+ /* @__PURE__ */ jsx("p", { className: cn(
360
+ "brutal-body-lg max-w-lg opacity-80",
361
+ variant === "centered" && "mx-auto"
362
+ ), children: description }),
363
+ /* @__PURE__ */ jsxs("div", { className: cn(
364
+ "flex flex-col gap-4 sm:flex-row sm:flex-wrap",
365
+ variant === "centered" && "sm:justify-center"
366
+ ), children: [
367
+ /* @__PURE__ */ jsx(Button, { variant: ctaVariant, size: "xl", className: "w-full sm:w-auto", render: /* @__PURE__ */ jsx("a", { href: ctaHref }), children: ctaText }),
368
+ secondaryText && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "xl", className: "w-full sm:w-auto", render: /* @__PURE__ */ jsx("a", { href: secondaryHref || "#" }), children: secondaryText })
369
+ ] }),
370
+ proof && /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-medium opacity-70", children: [
371
+ /* @__PURE__ */ jsx("span", { className: "inline-flex size-5 items-center justify-center border border-current text-xs", children: "\u2713" }),
372
+ proof
373
+ ] })
374
+ ] });
375
+ const layoutClass = {
376
+ split: "grid items-center gap-12 lg:grid-cols-2 lg:gap-16",
377
+ centered: "flex flex-col items-center gap-12",
378
+ overlap: "relative",
379
+ asymmetric: "grid items-center gap-12 lg:grid-cols-[3fr_2fr] lg:gap-16"
380
+ }[variant];
381
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, padding: "lg", pattern, className: cn("relative", className), children: [
382
+ badgePosition === "floating" && badgeElement,
383
+ /* @__PURE__ */ jsxs("div", { className: layoutClass, children: [
384
+ textContent,
385
+ visual && variant === "overlap" ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center opacity-20", children: visual }) : visual ? /* @__PURE__ */ jsx("div", { className: cn(
386
+ "flex items-center justify-center",
387
+ variant === "asymmetric" && "-rotate-2 transform"
388
+ ), children: visual }) : null
389
+ ] })
390
+ ] });
391
+ }
392
+ var paths = {
393
+ wave: "M0,64 C160,128 320,0 480,64 C640,128 800,0 960,64 L960,160 L0,160 Z",
394
+ jagged: "M0,80 L80,40 L160,80 L240,20 L320,80 L400,40 L480,80 L560,20 L640,80 L720,40 L800,80 L880,20 L960,80 L960,160 L0,160 Z",
395
+ curve: "M0,128 Q480,-32 960,128 L960,160 L0,160 Z",
396
+ castle: "M0,80 L0,60 L80,60 L80,80 L120,80 L120,40 L200,40 L200,80 L240,80 L240,60 L320,60 L320,80 L360,80 L360,40 L440,40 L440,80 L480,80 L480,60 L560,60 L560,80 L600,80 L600,40 L680,40 L680,80 L720,80 L720,60 L800,60 L800,80 L840,80 L840,40 L920,40 L920,80 L960,80 L960,160 L0,160 Z",
397
+ "torn-paper": "M0,70 C30,65 45,85 80,72 C115,59 130,90 170,78 C210,66 225,88 270,75 C315,62 340,92 380,79 C420,66 445,86 490,73 C535,60 560,88 600,76 C640,64 665,90 710,77 C755,64 780,84 830,71 C875,58 900,86 960,80 L960,160 L0,160 Z",
398
+ "brush-stroke": "M0,90 C80,50 120,100 200,60 C280,20 360,110 480,70 C600,30 640,100 720,80 C800,60 880,100 960,70 L960,160 L0,160 Z",
399
+ geometric: "M0,100 L120,60 L240,80 L360,40 L480,90 L600,50 L720,70 L840,30 L960,80 L960,160 L0,160 Z",
400
+ blob: "M0,80 C80,120 160,40 280,80 C400,120 440,30 560,70 C680,110 760,40 960,80 L960,160 L0,160 Z",
401
+ diagonal: "M0,160 L960,60 L960,160 Z",
402
+ zigzag: "M0,80 L60,40 L120,80 L180,40 L240,80 L300,40 L360,80 L420,40 L480,80 L540,40 L600,80 L660,40 L720,80 L780,40 L840,80 L900,40 L960,80 L960,160 L0,160 Z",
403
+ "hand-drawn": "M0,72 C20,68 35,82 60,75 C85,68 95,84 125,76 C155,68 170,85 200,77 C230,69 245,83 275,75 C305,67 320,86 350,78 C380,70 395,82 425,74 C455,66 470,84 500,76 C530,68 545,83 575,75 C605,67 620,85 650,77 C680,69 695,82 725,74 C755,66 770,84 800,76 C830,68 845,83 875,75 C905,67 920,82 960,74 L960,160 L0,160 Z"
404
+ };
405
+ function SectionDivider({
406
+ from = "hsl(var(--background))",
407
+ to = "hsl(var(--background))",
408
+ flip = false,
409
+ className = "",
410
+ variant = "wave",
411
+ layers = false
412
+ }) {
413
+ return /* @__PURE__ */ jsxs(
414
+ "div",
415
+ {
416
+ className: cn("relative -my-px w-full overflow-hidden", className),
417
+ style: { backgroundColor: from },
418
+ children: [
419
+ layers && /* @__PURE__ */ jsx(
420
+ "svg",
421
+ {
422
+ viewBox: "0 0 960 160",
423
+ preserveAspectRatio: "none",
424
+ className: "absolute inset-0 block w-full opacity-30",
425
+ style: {
426
+ height: "clamp(40px, 6vw, 80px)",
427
+ transform: flip ? "scaleY(-1) translateY(4px)" : "translateY(-4px)"
428
+ },
429
+ children: /* @__PURE__ */ jsx("path", { d: paths[variant], fill: to })
430
+ }
431
+ ),
432
+ /* @__PURE__ */ jsx(
433
+ "svg",
434
+ {
435
+ viewBox: "0 0 960 160",
436
+ preserveAspectRatio: "none",
437
+ className: "relative block w-full",
438
+ style: {
439
+ height: "clamp(40px, 6vw, 80px)",
440
+ transform: flip ? "scaleY(-1)" : void 0
441
+ },
442
+ children: /* @__PURE__ */ jsx("path", { d: paths[variant], fill: to })
443
+ }
444
+ )
445
+ ]
446
+ }
447
+ );
448
+ }
449
+ function LogoCloud({
450
+ title,
451
+ logos,
452
+ marquee = false,
453
+ color = "white",
454
+ className
455
+ }) {
456
+ const logoElements = logos.map((logo) => {
457
+ const img = /* @__PURE__ */ jsx(
458
+ "img",
459
+ {
460
+ src: logo.src,
461
+ alt: logo.alt,
462
+ className: "h-8 max-w-[120px] object-contain opacity-50 grayscale transition-all duration-200 hover:opacity-100 hover:grayscale-0"
463
+ },
464
+ logo.alt
465
+ );
466
+ return logo.href ? /* @__PURE__ */ jsx("a", { href: logo.href, className: "flex items-center px-6", children: img }, logo.alt) : /* @__PURE__ */ jsx("div", { className: "flex items-center px-6", children: img }, logo.alt);
467
+ });
468
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, padding: "sm", className, children: [
469
+ title && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-6 text-center text-muted-foreground", children: title }),
470
+ marquee ? /* @__PURE__ */ jsx("div", { className: "relative overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex animate-marquee", children: [
471
+ logoElements,
472
+ logoElements
473
+ ] }) }) : /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center justify-center gap-8", children: logoElements })
474
+ ] });
475
+ }
476
+ function Card({
477
+ className,
478
+ ...props
479
+ }) {
480
+ return /* @__PURE__ */ jsx(
481
+ "div",
482
+ {
483
+ "data-slot": "card",
484
+ className: cn(
485
+ "group/card flex flex-col gap-4 rounded-lg border-brutal border-foreground bg-card p-5 text-card-foreground shadow-brutal transition-all duration-150 hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg",
486
+ className
487
+ ),
488
+ ...props
489
+ }
490
+ );
491
+ }
492
+ function CardHeader({ className, ...props }) {
493
+ return /* @__PURE__ */ jsx(
494
+ "div",
495
+ {
496
+ "data-slot": "card-header",
497
+ className: cn("flex flex-col gap-1", className),
498
+ ...props
499
+ }
500
+ );
501
+ }
502
+ function CardTitle({ className, ...props }) {
503
+ return /* @__PURE__ */ jsx(
504
+ "div",
505
+ {
506
+ "data-slot": "card-title",
507
+ className: cn("text-lg font-bold leading-snug", className),
508
+ ...props
509
+ }
510
+ );
511
+ }
512
+ function CardDescription({ className, ...props }) {
513
+ return /* @__PURE__ */ jsx(
514
+ "div",
515
+ {
516
+ "data-slot": "card-description",
517
+ className: cn("text-sm text-muted-foreground", className),
518
+ ...props
519
+ }
520
+ );
521
+ }
522
+ function CardContent({ className, ...props }) {
523
+ return /* @__PURE__ */ jsx(
524
+ "div",
525
+ {
526
+ "data-slot": "card-content",
527
+ className: cn("", className),
528
+ ...props
529
+ }
530
+ );
531
+ }
532
+ var colMap = {
533
+ 2: "sm:grid-cols-2",
534
+ 3: "sm:grid-cols-2 lg:grid-cols-3",
535
+ 4: "sm:grid-cols-2 lg:grid-cols-4"
536
+ };
537
+ function BrutalFeatureGrid({
538
+ variant = "icon-top",
539
+ badge,
540
+ headline,
541
+ description,
542
+ features,
543
+ columns = 3,
544
+ color = "white",
545
+ className
546
+ }) {
547
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
548
+ /* @__PURE__ */ jsxs("div", { className: "mb-12 max-w-2xl", children: [
549
+ badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-brand", children: badge }),
550
+ /* @__PURE__ */ jsx("h2", { className: "brutal-h2 mb-4", children: headline }),
551
+ description && /* @__PURE__ */ jsx("p", { className: "brutal-body text-muted-foreground", children: description })
552
+ ] }),
553
+ /* @__PURE__ */ jsx(
554
+ "div",
555
+ {
556
+ className: cn(
557
+ "grid gap-6",
558
+ variant === "bento" ? "sm:grid-cols-2 lg:grid-cols-3" : colMap[columns]
559
+ ),
560
+ children: features.map((feature, i) => /* @__PURE__ */ jsx(
561
+ FeatureCard,
562
+ {
563
+ feature,
564
+ variant,
565
+ index: i
566
+ },
567
+ feature.title
568
+ ))
569
+ }
570
+ )
571
+ ] });
572
+ }
573
+ function FeatureCard({
574
+ feature,
575
+ variant,
576
+ index
577
+ }) {
578
+ const isBentoFeatured = variant === "bento" && feature.featured;
579
+ if (variant === "icon-left") {
580
+ return /* @__PURE__ */ jsxs("div", { className: "flex gap-4 border-brutal border-foreground border-l-4 border-l-brand bg-background p-5 shadow-brutal transition-all duration-150 hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg", children: [
581
+ feature.icon && /* @__PURE__ */ jsx("div", { className: "flex size-12 shrink-0 items-center justify-center border-brutal border-foreground bg-brand-muted text-2xl shadow-brutal-sm", children: feature.icon }),
582
+ /* @__PURE__ */ jsxs("div", { children: [
583
+ feature.stat && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-1 text-brand", children: feature.stat }),
584
+ /* @__PURE__ */ jsx("h3", { className: "brutal-h4 mb-1", children: feature.title }),
585
+ /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: feature.description })
586
+ ] })
587
+ ] });
588
+ }
589
+ if (variant === "numbered") {
590
+ return /* @__PURE__ */ jsxs(Card, { children: [
591
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
592
+ /* @__PURE__ */ jsx("span", { className: "brutal-display mb-2 block text-brand opacity-20", children: String(index + 1).padStart(2, "0") }),
593
+ feature.stat && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-1 text-brand", children: feature.stat }),
594
+ /* @__PURE__ */ jsx(CardTitle, { children: feature.title })
595
+ ] }),
596
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(CardDescription, { children: feature.description }) })
597
+ ] });
598
+ }
599
+ return /* @__PURE__ */ jsxs(
600
+ Card,
601
+ {
602
+ className: cn(
603
+ isBentoFeatured && "sm:col-span-2 bg-brand-muted"
604
+ ),
605
+ children: [
606
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
607
+ feature.icon && /* @__PURE__ */ jsx("div", { className: "mb-2 inline-flex size-12 items-center justify-center border-brutal border-foreground border-b-brand bg-brand-muted text-2xl shadow-brutal-sm", children: feature.icon }),
608
+ feature.stat && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-1 text-brand", children: feature.stat }),
609
+ /* @__PURE__ */ jsx(CardTitle, { children: feature.title })
610
+ ] }),
611
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(CardDescription, { children: feature.description }) })
612
+ ]
613
+ }
614
+ );
615
+ }
616
+ function useCountUp(target, inView) {
617
+ const [count, setCount] = useState(0);
618
+ useEffect(() => {
619
+ if (!inView) return;
620
+ let frame;
621
+ const duration = 1500;
622
+ const start = performance.now();
623
+ function animate(now) {
624
+ const elapsed = now - start;
625
+ const progress = Math.min(elapsed / duration, 1);
626
+ const eased = 1 - Math.pow(1 - progress, 3);
627
+ setCount(Math.round(eased * target));
628
+ if (progress < 1) frame = requestAnimationFrame(animate);
629
+ }
630
+ frame = requestAnimationFrame(animate);
631
+ return () => cancelAnimationFrame(frame);
632
+ }, [target, inView]);
633
+ return count;
634
+ }
635
+ function StatItem({ stat, inView }) {
636
+ const count = useCountUp(stat.value, inView);
637
+ return /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
638
+ /* @__PURE__ */ jsxs("p", { className: "brutal-display", children: [
639
+ stat.prefix,
640
+ count.toLocaleString(),
641
+ stat.suffix
642
+ ] }),
643
+ /* @__PURE__ */ jsx("p", { className: "brutal-label mt-2 text-muted-foreground", children: stat.label })
644
+ ] });
645
+ }
646
+ function StatsBar({ stats, color = "white", className }) {
647
+ const ref = useRef(null);
648
+ const [inView, setInView] = useState(false);
649
+ useEffect(() => {
650
+ if (!ref.current) return;
651
+ const observer = new IntersectionObserver(
652
+ ([entry]) => {
653
+ if (entry.isIntersecting) {
654
+ setInView(true);
655
+ observer.disconnect();
656
+ }
657
+ },
658
+ { threshold: 0.3 }
659
+ );
660
+ observer.observe(ref.current);
661
+ return () => observer.disconnect();
662
+ }, []);
663
+ return /* @__PURE__ */ jsx(BrutalSection, { color, padding: "sm", className, children: /* @__PURE__ */ jsx(
664
+ "div",
665
+ {
666
+ ref,
667
+ className: cn(
668
+ "grid gap-8",
669
+ stats.length === 2 && "grid-cols-2",
670
+ stats.length === 3 && "grid-cols-3",
671
+ stats.length >= 4 && "grid-cols-2 sm:grid-cols-4"
672
+ ),
673
+ children: stats.map((stat) => /* @__PURE__ */ jsx(StatItem, { stat, inView }, stat.label))
674
+ }
675
+ ) });
676
+ }
677
+ function StarRating({ rating }) {
678
+ return /* @__PURE__ */ jsx("div", { className: "flex gap-0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx(
679
+ "span",
680
+ {
681
+ className: cn(
682
+ "text-sm",
683
+ i < rating ? "text-amber-500" : "text-foreground/20"
684
+ ),
685
+ children: "\u2605"
686
+ },
687
+ i
688
+ )) });
689
+ }
690
+ function TestimonialCard({
691
+ t,
692
+ className
693
+ }) {
694
+ return /* @__PURE__ */ jsxs(
695
+ "div",
696
+ {
697
+ className: cn(
698
+ "relative break-inside-avoid border-brutal border-foreground bg-background p-5 text-foreground shadow-brutal transition-all duration-150 hover:-translate-x-0.5 hover:-translate-y-0.5 hover:shadow-brutal-lg",
699
+ className
700
+ ),
701
+ children: [
702
+ /* @__PURE__ */ jsx("span", { className: "pointer-events-none absolute top-3 right-4 select-none font-serif text-5xl leading-none text-foreground/[0.06]", children: "\u201C" }),
703
+ t.rating && /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(StarRating, { rating: t.rating }) }),
704
+ /* @__PURE__ */ jsx("p", { className: "relative mb-4 text-sm leading-relaxed", children: t.text }),
705
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
706
+ t.avatar ? /* @__PURE__ */ jsx(
707
+ "img",
708
+ {
709
+ src: t.avatar,
710
+ alt: t.name,
711
+ className: "size-9 border-2 object-cover",
712
+ style: { borderColor: "hsl(var(--brand))" }
713
+ }
714
+ ) : /* @__PURE__ */ jsx(
715
+ "div",
716
+ {
717
+ className: "flex size-9 items-center justify-center border-2 font-bold text-brand-foreground",
718
+ style: {
719
+ borderColor: "hsl(var(--brand))",
720
+ backgroundColor: "hsl(var(--brand))"
721
+ },
722
+ children: t.name[0]
723
+ }
724
+ ),
725
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
726
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-bold", children: t.name }),
727
+ (t.role || t.company) && /* @__PURE__ */ jsxs("p", { className: "truncate text-xs text-muted-foreground", children: [
728
+ t.role,
729
+ t.role && t.company && " \xB7 ",
730
+ t.company
731
+ ] }),
732
+ !t.role && !t.company && t.handle && /* @__PURE__ */ jsx("p", { className: "font-mono text-xs text-muted-foreground", children: t.handle })
733
+ ] }),
734
+ t.companyLogo && /* @__PURE__ */ jsx(
735
+ "img",
736
+ {
737
+ src: t.companyLogo,
738
+ alt: t.company || "",
739
+ className: "h-5 object-contain opacity-60"
740
+ }
741
+ )
742
+ ] })
743
+ ]
744
+ }
745
+ );
746
+ }
747
+ function MasonryLayout({ testimonials }) {
748
+ return /* @__PURE__ */ jsx("div", { className: "columns-1 gap-6 sm:columns-2 lg:columns-3", children: testimonials.map((t, i) => /* @__PURE__ */ jsx(TestimonialCard, { t, className: "mb-6" }, i)) });
749
+ }
750
+ function FeaturedGridLayout({
751
+ testimonials
752
+ }) {
753
+ const featured = testimonials.find((t) => t.featured) || testimonials[0];
754
+ const rest = testimonials.filter((t) => t !== featured);
755
+ return /* @__PURE__ */ jsxs("div", { className: "grid gap-6 lg:grid-cols-2", children: [
756
+ featured && /* @__PURE__ */ jsx(
757
+ TestimonialCard,
758
+ {
759
+ t: featured,
760
+ className: "flex flex-col justify-between p-8 lg:row-span-2"
761
+ }
762
+ ),
763
+ rest.map((t, i) => /* @__PURE__ */ jsx(TestimonialCard, { t }, i))
764
+ ] });
765
+ }
766
+ function CarouselLayout({ testimonials }) {
767
+ return /* @__PURE__ */ jsx("div", { className: "-mx-6 flex snap-x snap-mandatory gap-6 overflow-x-auto px-6 pb-4", children: testimonials.map((t, i) => /* @__PURE__ */ jsx(
768
+ TestimonialCard,
769
+ {
770
+ t,
771
+ className: "w-80 flex-none snap-center"
772
+ },
773
+ i
774
+ )) });
775
+ }
776
+ function WallOfLoveLayout({ testimonials }) {
777
+ return /* @__PURE__ */ jsxs("div", { className: "relative max-h-[600px] overflow-hidden", children: [
778
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4", children: testimonials.map((t, i) => /* @__PURE__ */ jsx(TestimonialCard, { t }, i)) }),
779
+ /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent" })
780
+ ] });
781
+ }
782
+ function BrutalTestimonials({
783
+ badge,
784
+ headline,
785
+ testimonials,
786
+ variant = "masonry",
787
+ color = "brand-muted",
788
+ pattern,
789
+ className
790
+ }) {
791
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, pattern, className, children: [
792
+ (headline || badge) && /* @__PURE__ */ jsxs("div", { className: "mb-12 text-center", children: [
793
+ badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 opacity-70", children: badge }),
794
+ headline && /* @__PURE__ */ jsx("h2", { className: "brutal-h2", children: headline })
795
+ ] }),
796
+ variant === "masonry" && /* @__PURE__ */ jsx(MasonryLayout, { testimonials }),
797
+ variant === "featured-grid" && /* @__PURE__ */ jsx(FeaturedGridLayout, { testimonials }),
798
+ variant === "carousel" && /* @__PURE__ */ jsx(CarouselLayout, { testimonials }),
799
+ variant === "wall-of-love" && /* @__PURE__ */ jsx(WallOfLoveLayout, { testimonials })
800
+ ] });
801
+ }
802
+ var badgeVariants = cva(
803
+ "group/badge inline-flex w-fit shrink-0 items-center justify-center gap-1 rounded-md whitespace-nowrap font-bold transition-all [&>svg]:pointer-events-none [&>svg]:size-3!",
804
+ {
805
+ variants: {
806
+ variant: {
807
+ default: "border-brutal border-foreground bg-primary px-3 py-1 text-xs text-primary-foreground shadow-brutal-sm",
808
+ secondary: "border-brutal border-foreground bg-secondary px-3 py-1 text-xs text-secondary-foreground shadow-brutal-sm",
809
+ brand: "border-brutal border-foreground bg-brand px-3 py-1 text-xs text-brand-foreground shadow-brutal-sm",
810
+ cta: "border-brutal border-foreground bg-cta px-3 py-1 text-xs text-cta-foreground shadow-brutal-sm",
811
+ outline: "border-brutal border-foreground bg-background px-3 py-1 text-xs text-foreground",
812
+ destructive: "border-brutal border-destructive bg-destructive/10 px-3 py-1 text-xs text-destructive",
813
+ ghost: "px-2 py-0.5 text-xs text-muted-foreground"
814
+ }
815
+ },
816
+ defaultVariants: {
817
+ variant: "default"
818
+ }
819
+ }
820
+ );
821
+ function Badge({
822
+ className,
823
+ variant = "default",
824
+ render,
825
+ ...props
826
+ }) {
827
+ return useRender({
828
+ defaultTagName: "span",
829
+ props: mergeProps(
830
+ {
831
+ className: cn(badgeVariants({ variant }), className)
832
+ },
833
+ props
834
+ ),
835
+ render,
836
+ state: {
837
+ slot: "badge",
838
+ variant
839
+ }
840
+ });
841
+ }
842
+ function PricingTable({
843
+ badge,
844
+ headline,
845
+ description,
846
+ tiers,
847
+ popularIndex,
848
+ billingToggle = true,
849
+ color = "white",
850
+ className
851
+ }) {
852
+ const [annual, setAnnual] = useState(false);
853
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
854
+ (headline || badge) && /* @__PURE__ */ jsxs("div", { className: "mb-8 text-center", children: [
855
+ badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-muted-foreground", children: badge }),
856
+ headline && /* @__PURE__ */ jsx("h2", { className: "brutal-h2 mb-4", children: headline }),
857
+ description && /* @__PURE__ */ jsx("p", { className: "brutal-body mx-auto max-w-lg text-muted-foreground", children: description })
858
+ ] }),
859
+ billingToggle && /* @__PURE__ */ jsxs("div", { className: "mb-10 flex items-center justify-center gap-3", children: [
860
+ /* @__PURE__ */ jsx("span", { className: cn("text-sm font-bold", !annual && "text-brand"), children: "Monthly" }),
861
+ /* @__PURE__ */ jsx(
862
+ "button",
863
+ {
864
+ onClick: () => setAnnual(!annual),
865
+ className: cn(
866
+ "relative h-8 w-14 border-brutal border-foreground transition-colors",
867
+ annual ? "bg-brand" : "bg-secondary"
868
+ ),
869
+ children: /* @__PURE__ */ jsx(
870
+ "span",
871
+ {
872
+ className: cn(
873
+ "absolute top-1 size-6 border border-foreground bg-background transition-transform",
874
+ annual ? "left-7" : "left-1"
875
+ )
876
+ }
877
+ )
878
+ }
879
+ ),
880
+ /* @__PURE__ */ jsx("span", { className: cn("text-sm font-bold", annual && "text-brand"), children: "Annual" }),
881
+ annual && /* @__PURE__ */ jsx(Badge, { variant: "cta", children: "Save 20%" })
882
+ ] }),
883
+ /* @__PURE__ */ jsx("div", { className: cn(
884
+ "grid gap-6",
885
+ tiers.length === 2 && "mx-auto max-w-2xl sm:grid-cols-2",
886
+ tiers.length === 3 && "lg:grid-cols-3",
887
+ tiers.length >= 4 && "sm:grid-cols-2 lg:grid-cols-4"
888
+ ), children: tiers.map((tier, i) => {
889
+ const isPopular = i === popularIndex;
890
+ const price = annual ? tier.price.annual : tier.price.monthly;
891
+ return /* @__PURE__ */ jsxs(
892
+ "div",
893
+ {
894
+ className: cn(
895
+ "relative flex flex-col border-brutal border-foreground bg-background p-6 shadow-brutal",
896
+ isPopular && "border-brand shadow-brutal-lg ring-2 ring-brand z-10 scale-105"
897
+ ),
898
+ children: [
899
+ isPopular && /* @__PURE__ */ jsx(Badge, { variant: "brand", className: "absolute -top-3 left-1/2 -translate-x-1/2", children: "Popular" }),
900
+ /* @__PURE__ */ jsx("h3", { className: "brutal-h4 mb-1", children: tier.name }),
901
+ tier.description && /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: tier.description }),
902
+ /* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
903
+ /* @__PURE__ */ jsx("span", { className: "brutal-h1", children: typeof price === "number" ? `$${price}` : price }),
904
+ typeof price === "number" && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "/mo" })
905
+ ] }),
906
+ /* @__PURE__ */ jsx("ul", { className: "mb-8 flex flex-1 flex-col gap-2", children: tier.features.map((feature) => /* @__PURE__ */ jsxs("li", { className: "flex items-start gap-2 text-sm", children: [
907
+ /* @__PURE__ */ jsx("span", { className: "mt-0.5 text-brand", children: "\u2713" }),
908
+ feature
909
+ ] }, feature)) }),
910
+ /* @__PURE__ */ jsx(
911
+ Button,
912
+ {
913
+ variant: tier.ctaVariant || (isPopular ? "cta" : "outline"),
914
+ size: "lg",
915
+ className: "w-full",
916
+ render: tier.ctaHref ? /* @__PURE__ */ jsx("a", { href: tier.ctaHref }) : void 0,
917
+ children: tier.ctaText
918
+ }
919
+ )
920
+ ]
921
+ },
922
+ tier.name
923
+ );
924
+ }) })
925
+ ] });
926
+ }
927
+ function Accordion({ className, ...props }) {
928
+ return /* @__PURE__ */ jsx(
929
+ Accordion$1.Root,
930
+ {
931
+ "data-slot": "accordion",
932
+ className: cn("flex w-full flex-col", className),
933
+ ...props
934
+ }
935
+ );
936
+ }
937
+ function AccordionItem({ className, ...props }) {
938
+ return /* @__PURE__ */ jsx(
939
+ Accordion$1.Item,
940
+ {
941
+ "data-slot": "accordion-item",
942
+ className: cn("border-brutal border-foreground rounded-lg mb-2 px-3", className),
943
+ ...props
944
+ }
945
+ );
946
+ }
947
+ function AccordionTrigger({
948
+ className,
949
+ children,
950
+ ...props
951
+ }) {
952
+ return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
953
+ Accordion$1.Trigger,
954
+ {
955
+ "data-slot": "accordion-trigger",
956
+ className: cn(
957
+ "group/accordion-trigger relative flex flex-1 items-start justify-between rounded-lg border border-transparent py-2.5 text-left text-sm font-bold transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
958
+ className
959
+ ),
960
+ ...props,
961
+ children: [
962
+ children,
963
+ /* @__PURE__ */ jsx(ChevronDownIcon, { "data-slot": "accordion-trigger-icon", className: "pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" }),
964
+ /* @__PURE__ */ jsx(ChevronUpIcon, { "data-slot": "accordion-trigger-icon", className: "pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" })
965
+ ]
966
+ }
967
+ ) });
968
+ }
969
+ function AccordionContent({
970
+ className,
971
+ children,
972
+ ...props
973
+ }) {
974
+ return /* @__PURE__ */ jsx(
975
+ Accordion$1.Panel,
976
+ {
977
+ "data-slot": "accordion-content",
978
+ className: "overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up",
979
+ ...props,
980
+ children: /* @__PURE__ */ jsx(
981
+ "div",
982
+ {
983
+ className: cn(
984
+ "h-(--accordion-panel-height) pt-0 pb-2.5 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
985
+ className
986
+ ),
987
+ children
988
+ }
989
+ )
990
+ }
991
+ );
992
+ }
993
+ function FAQ({
994
+ badge,
995
+ headline,
996
+ items,
997
+ color = "white",
998
+ className
999
+ }) {
1000
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
1001
+ (headline || badge) && /* @__PURE__ */ jsxs("div", { className: "mb-10 mx-auto max-w-2xl", children: [
1002
+ badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-brand", children: badge }),
1003
+ headline && /* @__PURE__ */ jsx("h2", { className: "brutal-h2", children: headline })
1004
+ ] }),
1005
+ /* @__PURE__ */ jsx(Accordion, { className: "mx-auto max-w-2xl", children: items.map((item, i) => /* @__PURE__ */ jsxs(
1006
+ AccordionItem,
1007
+ {
1008
+ value: `faq-${i}`,
1009
+ className: cn(
1010
+ "border-brutal border-foreground mb-3 px-5",
1011
+ i % 2 === 0 ? "bg-background" : "bg-secondary"
1012
+ ),
1013
+ children: [
1014
+ /* @__PURE__ */ jsx(AccordionTrigger, { className: "brutal-h4 py-4 text-left", children: item.question }),
1015
+ /* @__PURE__ */ jsx(AccordionContent, { className: "brutal-body pb-4 text-muted-foreground", children: item.answer })
1016
+ ]
1017
+ },
1018
+ i
1019
+ )) })
1020
+ ] });
1021
+ }
1022
+ function CTAButtons({
1023
+ ctaText,
1024
+ ctaHref = "#",
1025
+ ctaVariant = "cta",
1026
+ secondaryText,
1027
+ secondaryHref
1028
+ }) {
1029
+ return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-center", children: [
1030
+ /* @__PURE__ */ jsx(
1031
+ Button,
1032
+ {
1033
+ variant: ctaVariant,
1034
+ size: "xl",
1035
+ className: "w-full sm:w-auto",
1036
+ render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
1037
+ children: ctaText
1038
+ }
1039
+ ),
1040
+ secondaryText && /* @__PURE__ */ jsx(
1041
+ Button,
1042
+ {
1043
+ variant: "outline",
1044
+ size: "xl",
1045
+ className: "w-full sm:w-auto",
1046
+ render: /* @__PURE__ */ jsx("a", { href: secondaryHref || "#" }),
1047
+ children: secondaryText
1048
+ }
1049
+ )
1050
+ ] });
1051
+ }
1052
+ function CenteredCTA(props) {
1053
+ return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-2xl text-center", children: [
1054
+ /* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
1055
+ props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
1056
+ props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
1057
+ /* @__PURE__ */ jsx(
1058
+ CTAButtons,
1059
+ {
1060
+ ctaText: props.ctaText,
1061
+ ctaHref: props.ctaHref,
1062
+ ctaVariant: props.ctaVariant,
1063
+ secondaryText: props.secondaryText,
1064
+ secondaryHref: props.secondaryHref
1065
+ }
1066
+ )
1067
+ ] });
1068
+ }
1069
+ function SplitCTA(props) {
1070
+ return /* @__PURE__ */ jsxs("div", { className: "grid items-center gap-12 lg:grid-cols-2", children: [
1071
+ /* @__PURE__ */ jsxs("div", { children: [
1072
+ /* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
1073
+ props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
1074
+ props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
1075
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:flex-wrap", children: [
1076
+ /* @__PURE__ */ jsx(
1077
+ Button,
1078
+ {
1079
+ variant: props.ctaVariant || "cta",
1080
+ size: "xl",
1081
+ className: "w-full sm:w-auto",
1082
+ render: /* @__PURE__ */ jsx("a", { href: props.ctaHref || "#" }),
1083
+ children: props.ctaText
1084
+ }
1085
+ ),
1086
+ props.secondaryText && /* @__PURE__ */ jsx(
1087
+ Button,
1088
+ {
1089
+ variant: "outline",
1090
+ size: "xl",
1091
+ className: "w-full sm:w-auto",
1092
+ render: /* @__PURE__ */ jsx("a", { href: props.secondaryHref || "#" }),
1093
+ children: props.secondaryText
1094
+ }
1095
+ )
1096
+ ] })
1097
+ ] }),
1098
+ props.visual && /* @__PURE__ */ jsx("div", { children: props.visual })
1099
+ ] });
1100
+ }
1101
+ function WithVisualCTA(props) {
1102
+ return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
1103
+ props.visual && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center opacity-10", children: props.visual }),
1104
+ /* @__PURE__ */ jsxs("div", { className: "relative mx-auto max-w-2xl text-center", children: [
1105
+ /* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
1106
+ props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
1107
+ props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
1108
+ /* @__PURE__ */ jsx(
1109
+ CTAButtons,
1110
+ {
1111
+ ctaText: props.ctaText,
1112
+ ctaHref: props.ctaHref,
1113
+ ctaVariant: props.ctaVariant,
1114
+ secondaryText: props.secondaryText,
1115
+ secondaryHref: props.secondaryHref
1116
+ }
1117
+ )
1118
+ ] })
1119
+ ] });
1120
+ }
1121
+ function FloatingCardCTA(props) {
1122
+ return /* @__PURE__ */ jsx("div", { className: "relative z-10 -mt-16", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-2xl border-brutal border-foreground bg-background p-8 text-center text-foreground shadow-brutal-lg", children: [
1123
+ /* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
1124
+ props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
1125
+ props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
1126
+ /* @__PURE__ */ jsx(
1127
+ CTAButtons,
1128
+ {
1129
+ ctaText: props.ctaText,
1130
+ ctaHref: props.ctaHref,
1131
+ ctaVariant: props.ctaVariant,
1132
+ secondaryText: props.secondaryText,
1133
+ secondaryHref: props.secondaryHref
1134
+ }
1135
+ )
1136
+ ] }) });
1137
+ }
1138
+ function BrutalCTA({
1139
+ variant = "centered",
1140
+ color = "black",
1141
+ className,
1142
+ pattern,
1143
+ ...props
1144
+ }) {
1145
+ if (variant === "floating-card") {
1146
+ return /* @__PURE__ */ jsx("div", { className: cn("brutal-container px-6", className), children: /* @__PURE__ */ jsx(FloatingCardCTA, { ...props, variant, color }) });
1147
+ }
1148
+ return /* @__PURE__ */ jsxs(BrutalSection, { color, pattern, className, children: [
1149
+ variant === "centered" && /* @__PURE__ */ jsx(CenteredCTA, { ...props, variant, color }),
1150
+ variant === "split" && /* @__PURE__ */ jsx(SplitCTA, { ...props, variant, color }),
1151
+ variant === "with-visual" && /* @__PURE__ */ jsx(WithVisualCTA, { ...props, variant, color })
1152
+ ] });
1153
+ }
1154
+ function Input({ className, type, ...props }) {
1155
+ return /* @__PURE__ */ jsx(
1156
+ Input$1,
1157
+ {
1158
+ type,
1159
+ "data-slot": "input",
1160
+ className: cn(
1161
+ "h-10 w-full min-w-0 rounded-lg border-brutal border-foreground bg-background px-3 py-2 text-base font-medium shadow-brutal-sm transition-all outline-none placeholder:text-muted-foreground focus:shadow-brutal focus:-translate-x-0.5 focus:-translate-y-0.5 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive md:text-sm",
1162
+ className
1163
+ ),
1164
+ ...props
1165
+ }
1166
+ );
1167
+ }
1168
+ function SocialsRow({
1169
+ socials
1170
+ }) {
1171
+ const items = [
1172
+ { key: "twitter", label: "Twitter", url: socials.twitter },
1173
+ { key: "github", label: "GitHub", url: socials.github },
1174
+ { key: "linkedin", label: "LinkedIn", url: socials.linkedin },
1175
+ { key: "discord", label: "Discord", url: socials.discord }
1176
+ ].filter((s) => s.url);
1177
+ if (items.length === 0) return null;
1178
+ return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: items.map((s) => /* @__PURE__ */ jsx(
1179
+ "a",
1180
+ {
1181
+ href: s.url,
1182
+ target: "_blank",
1183
+ rel: "noopener noreferrer",
1184
+ className: "text-sm font-bold transition-colors hover:text-muted-foreground",
1185
+ children: s.label
1186
+ },
1187
+ s.key
1188
+ )) });
1189
+ }
1190
+ function NewsletterSection({
1191
+ newsletter
1192
+ }) {
1193
+ return /* @__PURE__ */ jsx("div", { className: "mb-10 border-b-brutal border-foreground pb-10", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-lg text-center", children: [
1194
+ /* @__PURE__ */ jsx("h3", { className: "brutal-h4 mb-2", children: newsletter.headline || "Stay in the loop" }),
1195
+ newsletter.description && /* @__PURE__ */ jsx("p", { className: "brutal-caption mb-4", children: newsletter.description }),
1196
+ /* @__PURE__ */ jsxs(
1197
+ "form",
1198
+ {
1199
+ onSubmit: (e) => e.preventDefault(),
1200
+ className: "flex gap-2",
1201
+ children: [
1202
+ /* @__PURE__ */ jsx(
1203
+ Input,
1204
+ {
1205
+ type: "email",
1206
+ placeholder: newsletter.placeholder || "you@email.com",
1207
+ className: "flex-1"
1208
+ }
1209
+ ),
1210
+ /* @__PURE__ */ jsx(Button, { variant: "default", size: "default", type: "submit", children: newsletter.buttonText || "Subscribe" })
1211
+ ]
1212
+ }
1213
+ )
1214
+ ] }) });
1215
+ }
1216
+ function MegaContent({
1217
+ logo,
1218
+ tagline,
1219
+ columns,
1220
+ socials
1221
+ }) {
1222
+ return /* @__PURE__ */ jsxs("div", { className: "mb-10 flex flex-col gap-8 sm:flex-row sm:items-start sm:justify-between", children: [
1223
+ /* @__PURE__ */ jsxs("div", { className: "max-w-xs", children: [
1224
+ /* @__PURE__ */ jsx("div", { className: "mb-2 text-xl font-black", children: logo }),
1225
+ tagline && /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: tagline }),
1226
+ socials && /* @__PURE__ */ jsx(SocialsRow, { socials })
1227
+ ] }),
1228
+ /* @__PURE__ */ jsx("div", { className: "grid grid-cols-2 gap-8 sm:grid-cols-3 md:gap-12", children: columns.map((col) => /* @__PURE__ */ jsxs("div", { children: [
1229
+ /* @__PURE__ */ jsx("h3", { className: "brutal-label mb-3 text-muted-foreground", children: col.title }),
1230
+ /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: col.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1231
+ "a",
1232
+ {
1233
+ href: link.href,
1234
+ className: "text-sm font-medium transition-colors hover:text-muted-foreground",
1235
+ children: link.label
1236
+ }
1237
+ ) }, link.href)) })
1238
+ ] }, col.title)) })
1239
+ ] });
1240
+ }
1241
+ function MinimalContent({
1242
+ logo,
1243
+ columns,
1244
+ socials
1245
+ }) {
1246
+ const allLinks = columns.flatMap((col) => col.links);
1247
+ return /* @__PURE__ */ jsxs("div", { className: "mb-6 flex flex-col items-center gap-4 sm:flex-row sm:justify-between", children: [
1248
+ /* @__PURE__ */ jsx("div", { className: "text-xl font-black", children: logo }),
1249
+ /* @__PURE__ */ jsx("nav", { className: "flex flex-wrap items-center justify-center gap-x-6 gap-y-2", children: allLinks.map((link) => /* @__PURE__ */ jsx(
1250
+ "a",
1251
+ {
1252
+ href: link.href,
1253
+ className: "text-sm font-medium transition-colors hover:text-muted-foreground",
1254
+ children: link.label
1255
+ },
1256
+ link.href
1257
+ )) }),
1258
+ socials && /* @__PURE__ */ jsx(SocialsRow, { socials })
1259
+ ] });
1260
+ }
1261
+ function BrutalFooter({
1262
+ logo,
1263
+ tagline,
1264
+ columns,
1265
+ bottomLeft,
1266
+ bottomRight,
1267
+ variant = "mega",
1268
+ socials,
1269
+ newsletter,
1270
+ className
1271
+ }) {
1272
+ return /* @__PURE__ */ jsx(
1273
+ "footer",
1274
+ {
1275
+ className: cn(
1276
+ "w-full border-t-4 bg-background px-6 py-12 text-foreground",
1277
+ className
1278
+ ),
1279
+ style: { borderTopColor: "hsl(var(--brand))" },
1280
+ children: /* @__PURE__ */ jsxs("div", { className: "brutal-container", children: [
1281
+ variant === "newsletter" && newsletter && /* @__PURE__ */ jsx(NewsletterSection, { newsletter }),
1282
+ variant === "minimal" ? /* @__PURE__ */ jsx(MinimalContent, { logo, columns, socials }) : /* @__PURE__ */ jsx(
1283
+ MegaContent,
1284
+ {
1285
+ logo,
1286
+ tagline,
1287
+ columns,
1288
+ socials
1289
+ }
1290
+ ),
1291
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t-brutal border-foreground pt-6 font-mono text-xs uppercase tracking-widest text-muted-foreground", children: [
1292
+ /* @__PURE__ */ jsx("span", { children: bottomLeft || "Built with care" }),
1293
+ /* @__PURE__ */ jsx("span", { children: bottomRight || (/* @__PURE__ */ new Date()).getFullYear() })
1294
+ ] })
1295
+ ] })
1296
+ }
1297
+ );
1298
+ }
1299
+ function SaaSLaunchTemplate({
1300
+ brand,
1301
+ logo,
1302
+ nav,
1303
+ hero,
1304
+ logos,
1305
+ features,
1306
+ stats,
1307
+ testimonials,
1308
+ pricing,
1309
+ faq,
1310
+ cta,
1311
+ footer
1312
+ }) {
1313
+ return /* @__PURE__ */ jsxs("div", { children: [
1314
+ /* @__PURE__ */ jsx(BrutalNav, { logo, links: nav.links, ctaText: nav.ctaText, ctaHref: nav.ctaHref, variant: "solid" }),
1315
+ /* @__PURE__ */ jsx(
1316
+ BrutalHero,
1317
+ {
1318
+ variant: "split",
1319
+ badge: hero.badge,
1320
+ headline: hero.headline,
1321
+ description: hero.description,
1322
+ ctaText: hero.ctaText,
1323
+ ctaHref: hero.ctaHref,
1324
+ secondaryText: hero.secondaryText,
1325
+ secondaryHref: hero.secondaryHref,
1326
+ visual: hero.visual,
1327
+ proof: hero.proof,
1328
+ color: "brand",
1329
+ pattern: "noise"
1330
+ }
1331
+ ),
1332
+ /* @__PURE__ */ jsx(SectionDivider, { from: "hsl(var(--brand))", to: "hsl(var(--background))", variant: "wave" }),
1333
+ logos && logos.length > 0 && /* @__PURE__ */ jsx(LogoCloud, { logos, marquee: true, title: "Trusted by teams everywhere" }),
1334
+ /* @__PURE__ */ jsx(
1335
+ BrutalFeatureGrid,
1336
+ {
1337
+ variant: "bento",
1338
+ badge: features.badge,
1339
+ headline: features.headline,
1340
+ description: features.description,
1341
+ features: features.items,
1342
+ color: "white"
1343
+ }
1344
+ ),
1345
+ stats && stats.length > 0 && /* @__PURE__ */ jsx(StatsBar, { stats, color: "brand" }),
1346
+ /* @__PURE__ */ jsx(SectionDivider, { from: "hsl(var(--brand))", to: "hsl(var(--brand-muted))", variant: "torn-paper" }),
1347
+ /* @__PURE__ */ jsx(
1348
+ BrutalTestimonials,
1349
+ {
1350
+ variant: "wall-of-love",
1351
+ badge: testimonials.badge,
1352
+ headline: testimonials.headline,
1353
+ testimonials: testimonials.items,
1354
+ color: "brand-muted"
1355
+ }
1356
+ ),
1357
+ /* @__PURE__ */ jsx(SectionDivider, { from: "hsl(var(--brand-muted))", to: "hsl(var(--background))", variant: "wave" }),
1358
+ pricing && /* @__PURE__ */ jsx(
1359
+ PricingTable,
1360
+ {
1361
+ badge: pricing.badge,
1362
+ headline: pricing.headline,
1363
+ description: pricing.description,
1364
+ tiers: pricing.tiers,
1365
+ popularIndex: pricing.popularIndex,
1366
+ color: "white"
1367
+ }
1368
+ ),
1369
+ faq && faq.length > 0 && /* @__PURE__ */ jsx(FAQ, { badge: "FAQ", headline: "Common Questions", items: faq, color: "white" }),
1370
+ /* @__PURE__ */ jsx(
1371
+ BrutalCTA,
1372
+ {
1373
+ variant: "with-visual",
1374
+ headline: cta.headline,
1375
+ description: cta.description,
1376
+ ctaText: cta.ctaText,
1377
+ ctaHref: cta.ctaHref,
1378
+ secondaryText: cta.secondaryText,
1379
+ secondaryHref: cta.secondaryHref,
1380
+ color: "black",
1381
+ pattern: "gradient-mesh"
1382
+ }
1383
+ ),
1384
+ /* @__PURE__ */ jsx(
1385
+ BrutalFooter,
1386
+ {
1387
+ variant: "mega",
1388
+ logo,
1389
+ tagline: footer.tagline,
1390
+ columns: footer.columns,
1391
+ socials: footer.socials
1392
+ }
1393
+ )
1394
+ ] });
1395
+ }
1396
+ function Newsletter({
1397
+ headline = "Stay in the loop",
1398
+ description,
1399
+ placeholder = "you@example.com",
1400
+ buttonText = "Subscribe",
1401
+ onSubmit,
1402
+ color = "white",
1403
+ className
1404
+ }) {
1405
+ return /* @__PURE__ */ jsx(BrutalSection, { color, padding: "sm", className, children: /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-md border-brutal border-foreground bg-background p-8 text-foreground shadow-brutal-lg", children: [
1406
+ /* @__PURE__ */ jsx("h3", { className: "brutal-h3 mb-2", children: headline }),
1407
+ description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-6 text-muted-foreground", children: description }),
1408
+ /* @__PURE__ */ jsxs(
1409
+ "form",
1410
+ {
1411
+ onSubmit: (e) => {
1412
+ e.preventDefault();
1413
+ const form = e.target;
1414
+ const email = new FormData(form).get("email");
1415
+ onSubmit?.(email);
1416
+ },
1417
+ className: "flex gap-3",
1418
+ children: [
1419
+ /* @__PURE__ */ jsx(Input, { type: "email", name: "email", placeholder, required: true, className: "flex-1" }),
1420
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "cta", children: buttonText })
1421
+ ]
1422
+ }
1423
+ )
1424
+ ] }) });
1425
+ }
1426
+ function StudioTemplate({
1427
+ logo,
1428
+ nav,
1429
+ hero,
1430
+ features,
1431
+ testimonials,
1432
+ newsletter,
1433
+ cta,
1434
+ footer
1435
+ }) {
1436
+ return /* @__PURE__ */ jsxs("div", { children: [
1437
+ /* @__PURE__ */ jsx(BrutalNav, { logo, links: nav.links, ctaText: nav.ctaText, ctaHref: nav.ctaHref, variant: "floating-pill" }),
1438
+ /* @__PURE__ */ jsx(
1439
+ BrutalHero,
1440
+ {
1441
+ variant: "asymmetric",
1442
+ badge: hero.badge,
1443
+ headline: hero.headline,
1444
+ description: hero.description,
1445
+ ctaText: hero.ctaText,
1446
+ ctaHref: hero.ctaHref,
1447
+ visual: hero.visual,
1448
+ proof: hero.proof,
1449
+ color: "brand",
1450
+ pattern: "grain"
1451
+ }
1452
+ ),
1453
+ /* @__PURE__ */ jsx(SectionDivider, { from: "hsl(var(--brand))", to: "hsl(var(--background))", variant: "brush-stroke" }),
1454
+ /* @__PURE__ */ jsx(
1455
+ BrutalFeatureGrid,
1456
+ {
1457
+ variant: "numbered",
1458
+ badge: features.badge,
1459
+ headline: features.headline,
1460
+ description: features.description,
1461
+ features: features.items,
1462
+ color: "white"
1463
+ }
1464
+ ),
1465
+ testimonials && /* @__PURE__ */ jsxs(Fragment, { children: [
1466
+ /* @__PURE__ */ jsx(SectionDivider, { from: "hsl(var(--background))", to: "hsl(var(--brand-muted))", variant: "diagonal" }),
1467
+ /* @__PURE__ */ jsx(
1468
+ BrutalTestimonials,
1469
+ {
1470
+ variant: "featured-grid",
1471
+ badge: testimonials.badge,
1472
+ headline: testimonials.headline,
1473
+ testimonials: testimonials.items,
1474
+ color: "brand-muted"
1475
+ }
1476
+ ),
1477
+ /* @__PURE__ */ jsx(SectionDivider, { from: "hsl(var(--brand-muted))", to: "hsl(var(--background))", variant: "diagonal", flip: true })
1478
+ ] }),
1479
+ newsletter && /* @__PURE__ */ jsx(
1480
+ Newsletter,
1481
+ {
1482
+ headline: newsletter.headline,
1483
+ description: newsletter.description,
1484
+ onSubmit: newsletter.onSubmit
1485
+ }
1486
+ ),
1487
+ /* @__PURE__ */ jsx(
1488
+ BrutalCTA,
1489
+ {
1490
+ variant: "floating-card",
1491
+ headline: cta.headline,
1492
+ description: cta.description,
1493
+ ctaText: cta.ctaText,
1494
+ ctaHref: cta.ctaHref,
1495
+ color: "brand"
1496
+ }
1497
+ ),
1498
+ /* @__PURE__ */ jsx(
1499
+ BrutalFooter,
1500
+ {
1501
+ variant: "minimal",
1502
+ logo,
1503
+ tagline: footer.tagline,
1504
+ columns: footer.columns
1505
+ }
1506
+ )
1507
+ ] });
1508
+ }
1509
+ var AppShellContext = createContext({
1510
+ collapsed: false,
1511
+ setCollapsed: () => {
1512
+ },
1513
+ mobileOpen: false,
1514
+ setMobileOpen: () => {
1515
+ }
1516
+ });
1517
+ var useAppShell = () => useContext(AppShellContext);
1518
+ function AppShell({
1519
+ sidebar,
1520
+ header,
1521
+ children,
1522
+ defaultCollapsed = false,
1523
+ className
1524
+ }) {
1525
+ const [collapsed, setCollapsed] = useState(defaultCollapsed);
1526
+ const [mobileOpen, setMobileOpen] = useState(false);
1527
+ return /* @__PURE__ */ jsx(
1528
+ AppShellContext.Provider,
1529
+ {
1530
+ value: { collapsed, setCollapsed, mobileOpen, setMobileOpen },
1531
+ children: /* @__PURE__ */ jsxs("div", { className: cn("flex h-screen bg-background", className), children: [
1532
+ /* @__PURE__ */ jsx(
1533
+ "aside",
1534
+ {
1535
+ className: cn(
1536
+ "hidden border-r-brutal border-foreground bg-background transition-all duration-200 md:block",
1537
+ collapsed ? "w-16" : "w-64"
1538
+ ),
1539
+ children: sidebar
1540
+ }
1541
+ ),
1542
+ /* @__PURE__ */ jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: /* @__PURE__ */ jsxs(SheetContent, { side: "left", className: "w-64 p-0 md:hidden", children: [
1543
+ /* @__PURE__ */ jsx(SheetTitle, { className: "sr-only", children: "Navigation" }),
1544
+ sidebar
1545
+ ] }) }),
1546
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-1 flex-col overflow-hidden", children: [
1547
+ header && /* @__PURE__ */ jsxs("header", { className: "flex h-14 items-center gap-4 border-b-brutal border-foreground px-6", children: [
1548
+ /* @__PURE__ */ jsx(
1549
+ Button,
1550
+ {
1551
+ variant: "ghost",
1552
+ size: "sm",
1553
+ className: "md:hidden",
1554
+ onClick: () => setMobileOpen(true),
1555
+ children: "\u2630"
1556
+ }
1557
+ ),
1558
+ header
1559
+ ] }),
1560
+ /* @__PURE__ */ jsx("main", { className: "flex-1 overflow-auto p-6", children })
1561
+ ] })
1562
+ ] })
1563
+ }
1564
+ );
1565
+ }
1566
+ function Sidebar({
1567
+ logo,
1568
+ logoCollapsed,
1569
+ groups,
1570
+ footer,
1571
+ className
1572
+ }) {
1573
+ const { collapsed, setCollapsed } = useAppShell();
1574
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full flex-col", className), children: [
1575
+ /* @__PURE__ */ jsxs("div", { className: "flex h-14 items-center justify-between border-b-brutal border-foreground px-4", children: [
1576
+ /* @__PURE__ */ jsx("div", { className: "font-black", children: collapsed ? logoCollapsed || logo : logo }),
1577
+ /* @__PURE__ */ jsx(
1578
+ "button",
1579
+ {
1580
+ onClick: () => setCollapsed(!collapsed),
1581
+ className: "hidden text-xs text-muted-foreground hover:text-foreground md:block",
1582
+ children: collapsed ? "\u2192" : "\u2190"
1583
+ }
1584
+ )
1585
+ ] }),
1586
+ /* @__PURE__ */ jsx("nav", { className: "flex-1 overflow-auto p-2", children: groups.map((group, gi) => /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
1587
+ group.title && !collapsed && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-2 px-2 text-muted-foreground", children: group.title }),
1588
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-0.5", children: group.links.map((link) => /* @__PURE__ */ jsxs(
1589
+ "a",
1590
+ {
1591
+ href: link.href,
1592
+ className: cn(
1593
+ "flex items-center gap-3 rounded-sm px-3 py-2 text-sm font-medium transition-colors",
1594
+ link.active ? "bg-brand text-brand-foreground" : "hover:bg-secondary",
1595
+ collapsed && "justify-center"
1596
+ ),
1597
+ title: collapsed ? link.label : void 0,
1598
+ children: [
1599
+ /* @__PURE__ */ jsx("span", { className: "size-5 shrink-0", children: link.icon }),
1600
+ !collapsed && /* @__PURE__ */ jsxs(Fragment, { children: [
1601
+ /* @__PURE__ */ jsx("span", { className: "flex-1", children: link.label }),
1602
+ link.badge !== void 0 && /* @__PURE__ */ jsx("span", { className: "border border-foreground bg-brand-muted px-1.5 font-mono text-[10px] font-bold", children: link.badge })
1603
+ ] })
1604
+ ]
1605
+ },
1606
+ link.href
1607
+ )) })
1608
+ ] }, gi)) }),
1609
+ footer && /* @__PURE__ */ jsx("div", { className: "border-t-brutal border-foreground p-3", children: footer })
1610
+ ] });
1611
+ }
1612
+ function SearchBar({
1613
+ placeholder = "Search...",
1614
+ shortcut = "\u2318K",
1615
+ value,
1616
+ onChange,
1617
+ className
1618
+ }) {
1619
+ return /* @__PURE__ */ jsxs("div", { className: cn("relative", className), children: [
1620
+ /* @__PURE__ */ jsx(
1621
+ Input,
1622
+ {
1623
+ type: "search",
1624
+ placeholder,
1625
+ value,
1626
+ onChange: (e) => onChange?.(e.target.value),
1627
+ className: "pr-12"
1628
+ }
1629
+ ),
1630
+ shortcut && /* @__PURE__ */ jsx("span", { className: "absolute right-2 top-1/2 -translate-y-1/2 border border-foreground bg-secondary px-1.5 font-mono text-[10px] text-muted-foreground", children: shortcut })
1631
+ ] });
1632
+ }
1633
+ function DropdownMenu({ ...props }) {
1634
+ return /* @__PURE__ */ jsx(Menu$1.Root, { "data-slot": "dropdown-menu", ...props });
1635
+ }
1636
+ function DropdownMenuTrigger({ ...props }) {
1637
+ return /* @__PURE__ */ jsx(Menu$1.Trigger, { "data-slot": "dropdown-menu-trigger", ...props });
1638
+ }
1639
+ function DropdownMenuContent({
1640
+ align = "start",
1641
+ alignOffset = 0,
1642
+ side = "bottom",
1643
+ sideOffset = 4,
1644
+ className,
1645
+ ...props
1646
+ }) {
1647
+ return /* @__PURE__ */ jsx(Menu$1.Portal, { children: /* @__PURE__ */ jsx(
1648
+ Menu$1.Positioner,
1649
+ {
1650
+ className: "isolate z-50 outline-none",
1651
+ align,
1652
+ alignOffset,
1653
+ side,
1654
+ sideOffset,
1655
+ children: /* @__PURE__ */ jsx(
1656
+ Menu$1.Popup,
1657
+ {
1658
+ "data-slot": "dropdown-menu-content",
1659
+ className: cn("z-50 max-h-(--available-height) w-(--anchor-width) min-w-32 origin-(--transform-origin) overflow-x-hidden overflow-y-auto rounded-lg border-brutal border-foreground bg-popover p-1 text-popover-foreground shadow-brutal duration-100 outline-none data-[side=bottom]:slide-in-from-top-2 data-[side=inline-end]:slide-in-from-left-2 data-[side=inline-start]:slide-in-from-right-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:overflow-hidden data-closed:fade-out-0 data-closed:zoom-out-95", className),
1660
+ ...props
1661
+ }
1662
+ )
1663
+ }
1664
+ ) });
1665
+ }
1666
+ function DropdownMenuGroup({ ...props }) {
1667
+ return /* @__PURE__ */ jsx(Menu$1.Group, { "data-slot": "dropdown-menu-group", ...props });
1668
+ }
1669
+ function DropdownMenuLabel({
1670
+ className,
1671
+ inset,
1672
+ ...props
1673
+ }) {
1674
+ return /* @__PURE__ */ jsx(
1675
+ Menu$1.GroupLabel,
1676
+ {
1677
+ "data-slot": "dropdown-menu-label",
1678
+ "data-inset": inset,
1679
+ className: cn(
1680
+ "px-1.5 py-1 text-xs font-medium text-muted-foreground data-inset:pl-7",
1681
+ className
1682
+ ),
1683
+ ...props
1684
+ }
1685
+ );
1686
+ }
1687
+ function DropdownMenuItem({
1688
+ className,
1689
+ inset,
1690
+ variant = "default",
1691
+ ...props
1692
+ }) {
1693
+ return /* @__PURE__ */ jsx(
1694
+ Menu$1.Item,
1695
+ {
1696
+ "data-slot": "dropdown-menu-item",
1697
+ "data-inset": inset,
1698
+ "data-variant": variant,
1699
+ className: cn(
1700
+ "group/dropdown-menu-item relative flex cursor-default items-center gap-1.5 rounded-md px-1.5 py-1 text-sm 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",
1701
+ className
1702
+ ),
1703
+ ...props
1704
+ }
1705
+ );
1706
+ }
1707
+ function DropdownMenuSeparator({
1708
+ className,
1709
+ ...props
1710
+ }) {
1711
+ return /* @__PURE__ */ jsx(
1712
+ Menu$1.Separator,
1713
+ {
1714
+ "data-slot": "dropdown-menu-separator",
1715
+ className: cn("-mx-1 my-1 h-px bg-border", className),
1716
+ ...props
1717
+ }
1718
+ );
1719
+ }
1720
+ function Avatar({
1721
+ className,
1722
+ size = "default",
1723
+ ...props
1724
+ }) {
1725
+ return /* @__PURE__ */ jsx(
1726
+ Avatar$1.Root,
1727
+ {
1728
+ "data-slot": "avatar",
1729
+ "data-size": size,
1730
+ className: cn(
1731
+ "group/avatar relative flex size-8 shrink-0 rounded-full select-none after:absolute after:inset-0 after:rounded-full after:border after:border-border after:mix-blend-darken data-[size=lg]:size-10 data-[size=sm]:size-6 dark:after:mix-blend-lighten",
1732
+ className
1733
+ ),
1734
+ ...props
1735
+ }
1736
+ );
1737
+ }
1738
+ function AvatarImage({ className, ...props }) {
1739
+ return /* @__PURE__ */ jsx(
1740
+ Avatar$1.Image,
1741
+ {
1742
+ "data-slot": "avatar-image",
1743
+ className: cn(
1744
+ "aspect-square size-full rounded-full object-cover",
1745
+ className
1746
+ ),
1747
+ ...props
1748
+ }
1749
+ );
1750
+ }
1751
+ function AvatarFallback({
1752
+ className,
1753
+ ...props
1754
+ }) {
1755
+ return /* @__PURE__ */ jsx(
1756
+ Avatar$1.Fallback,
1757
+ {
1758
+ "data-slot": "avatar-fallback",
1759
+ className: cn(
1760
+ "flex size-full items-center justify-center rounded-full bg-muted text-sm text-muted-foreground group-data-[size=sm]/avatar:text-xs",
1761
+ className
1762
+ ),
1763
+ ...props
1764
+ }
1765
+ );
1766
+ }
1767
+ function UserMenu({ name, email, avatar, items, onSignOut }) {
1768
+ return /* @__PURE__ */ jsxs(DropdownMenu, { children: [
1769
+ /* @__PURE__ */ jsxs(
1770
+ DropdownMenuTrigger,
1771
+ {
1772
+ className: "inline-flex shrink-0 cursor-pointer items-center gap-2 rounded-lg px-3 py-1.5 text-sm font-medium outline-none hover:bg-secondary",
1773
+ children: [
1774
+ /* @__PURE__ */ jsxs(Avatar, { className: "size-7", children: [
1775
+ avatar && /* @__PURE__ */ jsx(AvatarImage, { src: avatar, alt: name }),
1776
+ /* @__PURE__ */ jsx(AvatarFallback, { children: name[0] })
1777
+ ] }),
1778
+ /* @__PURE__ */ jsx("span", { className: "hidden text-sm font-medium sm:inline", children: name })
1779
+ ]
1780
+ }
1781
+ ),
1782
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "end", className: "w-48", children: [
1783
+ /* @__PURE__ */ jsxs(DropdownMenuLabel, { children: [
1784
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-bold", children: name }),
1785
+ email && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: email })
1786
+ ] }),
1787
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1788
+ items && /* @__PURE__ */ jsx(DropdownMenuGroup, { children: items.map((item) => /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: item.onClick, children: item.href ? /* @__PURE__ */ jsx("a", { href: item.href, children: item.label }) : item.label }, item.label)) }),
1789
+ onSignOut && /* @__PURE__ */ jsxs(Fragment, { children: [
1790
+ /* @__PURE__ */ jsx(DropdownMenuSeparator, {}),
1791
+ /* @__PURE__ */ jsx(DropdownMenuItem, { onClick: onSignOut, children: "Sign out" })
1792
+ ] })
1793
+ ] })
1794
+ ] });
1795
+ }
1796
+ function StatCard({
1797
+ label,
1798
+ value,
1799
+ change,
1800
+ changeLabel,
1801
+ icon,
1802
+ className
1803
+ }) {
1804
+ return /* @__PURE__ */ jsxs(
1805
+ "div",
1806
+ {
1807
+ className: cn(
1808
+ "border-brutal border-foreground bg-background p-5 shadow-brutal",
1809
+ className
1810
+ ),
1811
+ children: [
1812
+ /* @__PURE__ */ jsxs("div", { className: "mb-3 flex items-center justify-between", children: [
1813
+ /* @__PURE__ */ jsx("p", { className: "brutal-label text-muted-foreground", children: label }),
1814
+ icon && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: icon })
1815
+ ] }),
1816
+ /* @__PURE__ */ jsx("p", { className: "brutal-h1 mb-1", children: value }),
1817
+ change !== void 0 && /* @__PURE__ */ jsxs(
1818
+ "p",
1819
+ {
1820
+ className: cn(
1821
+ "flex items-center gap-1 font-mono text-xs font-bold",
1822
+ change >= 0 ? "text-cta" : "text-destructive"
1823
+ ),
1824
+ children: [
1825
+ /* @__PURE__ */ jsx("span", { children: change >= 0 ? "\u2191" : "\u2193" }),
1826
+ /* @__PURE__ */ jsxs("span", { children: [
1827
+ Math.abs(change),
1828
+ "%"
1829
+ ] }),
1830
+ changeLabel && /* @__PURE__ */ jsx("span", { className: "font-normal text-muted-foreground", children: changeLabel })
1831
+ ]
1832
+ }
1833
+ )
1834
+ ]
1835
+ }
1836
+ );
1837
+ }
1838
+ var toggleVariants = cva(
1839
+ "group/toggle inline-flex items-center justify-center gap-1 rounded-lg text-sm font-medium whitespace-nowrap transition-all outline-none hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 aria-pressed:border-brutal aria-pressed:border-foreground aria-pressed:bg-muted aria-pressed:shadow-brutal-sm data-[state=on]:border-brutal data-[state=on]:border-foreground data-[state=on]:bg-muted data-[state=on]:shadow-brutal-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1840
+ {
1841
+ variants: {
1842
+ variant: {
1843
+ default: "bg-transparent",
1844
+ outline: "border-brutal border-foreground bg-transparent shadow-brutal-sm hover:bg-muted"
1845
+ },
1846
+ size: {
1847
+ default: "h-8 min-w-8 px-2",
1848
+ sm: "h-7 min-w-7 rounded-[min(var(--radius-md),12px)] px-1.5 text-[0.8rem]",
1849
+ lg: "h-9 min-w-9 px-2.5"
1850
+ }
1851
+ },
1852
+ defaultVariants: {
1853
+ variant: "default",
1854
+ size: "default"
1855
+ }
1856
+ }
1857
+ );
1858
+ var ToggleGroupContext = React.createContext({
1859
+ size: "default",
1860
+ variant: "default",
1861
+ spacing: 0,
1862
+ orientation: "horizontal"
1863
+ });
1864
+ function ToggleGroup({
1865
+ className,
1866
+ variant,
1867
+ size,
1868
+ spacing = 0,
1869
+ orientation = "horizontal",
1870
+ children,
1871
+ ...props
1872
+ }) {
1873
+ return /* @__PURE__ */ jsx(
1874
+ ToggleGroup$1,
1875
+ {
1876
+ "data-slot": "toggle-group",
1877
+ "data-variant": variant,
1878
+ "data-size": size,
1879
+ "data-spacing": spacing,
1880
+ "data-orientation": orientation,
1881
+ style: { "--gap": spacing },
1882
+ className: cn(
1883
+ "group/toggle-group flex w-fit flex-row items-center gap-[var(--gap)] rounded-lg border-brutal border-foreground data-vertical:flex-col data-vertical:items-stretch",
1884
+ className
1885
+ ),
1886
+ ...props,
1887
+ children: /* @__PURE__ */ jsx(
1888
+ ToggleGroupContext.Provider,
1889
+ {
1890
+ value: { variant, size, spacing, orientation },
1891
+ children
1892
+ }
1893
+ )
1894
+ }
1895
+ );
1896
+ }
1897
+ function ToggleGroupItem({
1898
+ className,
1899
+ children,
1900
+ variant = "default",
1901
+ size = "default",
1902
+ ...props
1903
+ }) {
1904
+ const context = React.useContext(ToggleGroupContext);
1905
+ return /* @__PURE__ */ jsx(
1906
+ Toggle,
1907
+ {
1908
+ "data-slot": "toggle-group-item",
1909
+ "data-variant": context.variant || variant,
1910
+ "data-size": context.size || size,
1911
+ "data-spacing": context.spacing,
1912
+ className: cn(
1913
+ "shrink-0 group-data-[spacing=0]/toggle-group:rounded-none group-data-[spacing=0]/toggle-group:px-2 focus:z-10 focus-visible:z-10 group-data-horizontal/toggle-group:data-[spacing=0]:first:rounded-l-lg group-data-vertical/toggle-group:data-[spacing=0]:first:rounded-t-lg group-data-horizontal/toggle-group:data-[spacing=0]:last:rounded-r-lg group-data-vertical/toggle-group:data-[spacing=0]:last:rounded-b-lg group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:border-l-0 group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:border-t-0 group-data-horizontal/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-l group-data-vertical/toggle-group:data-[spacing=0]:data-[variant=outline]:first:border-t",
1914
+ toggleVariants({
1915
+ variant: context.variant || variant,
1916
+ size: context.size || size
1917
+ }),
1918
+ className
1919
+ ),
1920
+ ...props,
1921
+ children
1922
+ }
1923
+ );
1924
+ }
1925
+ var viewLabels = {
1926
+ table: "Table",
1927
+ kanban: "Board",
1928
+ grid: "Grid",
1929
+ calendar: "Calendar",
1930
+ list: "List"
1931
+ };
1932
+ function ViewSwitcher({
1933
+ value,
1934
+ onChange,
1935
+ views = ["table", "kanban", "grid", "calendar", "list"],
1936
+ className
1937
+ }) {
1938
+ return /* @__PURE__ */ jsx(
1939
+ ToggleGroup,
1940
+ {
1941
+ value: [value],
1942
+ onValueChange: (vals) => {
1943
+ if (vals.length > 0) {
1944
+ onChange(vals[0]);
1945
+ }
1946
+ },
1947
+ className,
1948
+ children: views.map((view) => /* @__PURE__ */ jsx(ToggleGroupItem, { value: view, className: "brutal-label text-xs", children: viewLabels[view] }, view))
1949
+ }
1950
+ );
1951
+ }
1952
+ function DashboardTemplate({
1953
+ logo,
1954
+ logoCollapsed,
1955
+ sidebarGroups,
1956
+ user,
1957
+ userMenuItems,
1958
+ onSignOut,
1959
+ stats,
1960
+ views,
1961
+ children,
1962
+ sidebarFooter
1963
+ }) {
1964
+ const [view, setView] = useState("table");
1965
+ return /* @__PURE__ */ jsxs(
1966
+ AppShell,
1967
+ {
1968
+ sidebar: /* @__PURE__ */ jsx(
1969
+ Sidebar,
1970
+ {
1971
+ logo,
1972
+ logoCollapsed,
1973
+ groups: sidebarGroups,
1974
+ footer: sidebarFooter
1975
+ }
1976
+ ),
1977
+ header: /* @__PURE__ */ jsxs(Fragment, { children: [
1978
+ /* @__PURE__ */ jsx(SearchBar, { className: "flex-1 max-w-sm" }),
1979
+ /* @__PURE__ */ jsx("div", { className: "ml-auto", children: /* @__PURE__ */ jsx(
1980
+ UserMenu,
1981
+ {
1982
+ name: user.name,
1983
+ email: user.email,
1984
+ avatar: user.avatar,
1985
+ items: userMenuItems,
1986
+ onSignOut
1987
+ }
1988
+ ) })
1989
+ ] }),
1990
+ children: [
1991
+ stats && stats.length > 0 && /* @__PURE__ */ jsx("div", { className: "mb-6 grid gap-4 sm:grid-cols-2 lg:grid-cols-4", children: stats.map((stat) => /* @__PURE__ */ jsx(StatCard, { ...stat }, stat.label)) }),
1992
+ views && views.length > 1 && /* @__PURE__ */ jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsx(ViewSwitcher, { value: view, onChange: setView, views }) }),
1993
+ children
1994
+ ]
1995
+ }
1996
+ );
1997
+ }
1998
+
1999
+ export { DashboardTemplate, SaaSLaunchTemplate, StudioTemplate };
2000
+ //# sourceMappingURL=index.js.map
2001
+ //# sourceMappingURL=index.js.map