@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
@@ -4,14 +4,16 @@ interface NavLink {
4
4
  label: string;
5
5
  href: string;
6
6
  badge?: string;
7
+ active?: boolean;
7
8
  }
8
9
  interface BrutalNavProps {
9
10
  logo: React.ReactNode;
10
11
  links: NavLink[];
11
12
  ctaText?: string;
12
13
  ctaHref?: string;
14
+ variant?: "solid" | "transparent" | "floating-pill";
13
15
  className?: string;
14
16
  }
15
- declare function BrutalNav({ logo, links, ctaText, ctaHref, className, }: BrutalNavProps): react_jsx_runtime.JSX.Element;
17
+ declare function BrutalNav({ logo, links, ctaText, ctaHref, variant, className, }: BrutalNavProps): react_jsx_runtime.JSX.Element;
16
18
 
17
19
  export { BrutalNav };
@@ -1,9 +1,12 @@
1
1
  "use client";
2
+ import { useState, useEffect } from 'react';
2
3
  import { clsx } from 'clsx';
3
4
  import { twMerge } from 'tailwind-merge';
4
5
  import { Button as Button$1 } from '@base-ui/react/button';
5
6
  import { cva } from 'class-variance-authority';
6
7
  import { jsx, jsxs } from 'react/jsx-runtime';
8
+ import { Dialog } from '@base-ui/react/dialog';
9
+ import { Menu, XIcon } from 'lucide-react';
7
10
 
8
11
  function cn(...inputs) {
9
12
  return twMerge(clsx(inputs));
@@ -64,27 +67,127 @@ function Button({
64
67
  }
65
68
  );
66
69
  }
70
+ function Sheet({ ...props }) {
71
+ return /* @__PURE__ */ jsx(Dialog.Root, { "data-slot": "sheet", ...props });
72
+ }
73
+ function SheetTrigger({ ...props }) {
74
+ return /* @__PURE__ */ jsx(Dialog.Trigger, { "data-slot": "sheet-trigger", ...props });
75
+ }
76
+ function SheetPortal({ ...props }) {
77
+ return /* @__PURE__ */ jsx(Dialog.Portal, { "data-slot": "sheet-portal", ...props });
78
+ }
79
+ function SheetOverlay({ className, ...props }) {
80
+ return /* @__PURE__ */ jsx(
81
+ Dialog.Backdrop,
82
+ {
83
+ "data-slot": "sheet-overlay",
84
+ className: cn(
85
+ "fixed inset-0 z-50 bg-black/60 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0",
86
+ className
87
+ ),
88
+ ...props
89
+ }
90
+ );
91
+ }
92
+ function SheetContent({
93
+ className,
94
+ children,
95
+ side = "right",
96
+ showCloseButton = true,
97
+ ...props
98
+ }) {
99
+ return /* @__PURE__ */ jsxs(SheetPortal, { children: [
100
+ /* @__PURE__ */ jsx(SheetOverlay, {}),
101
+ /* @__PURE__ */ jsxs(
102
+ Dialog.Popup,
103
+ {
104
+ "data-slot": "sheet-content",
105
+ "data-side": side,
106
+ className: cn(
107
+ "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",
108
+ className
109
+ ),
110
+ ...props,
111
+ children: [
112
+ children,
113
+ showCloseButton && /* @__PURE__ */ jsxs(
114
+ Dialog.Close,
115
+ {
116
+ "data-slot": "sheet-close",
117
+ render: /* @__PURE__ */ jsx(
118
+ Button,
119
+ {
120
+ variant: "ghost",
121
+ className: "absolute top-3 right-3",
122
+ size: "icon-sm"
123
+ }
124
+ ),
125
+ children: [
126
+ /* @__PURE__ */ jsx(
127
+ XIcon,
128
+ {}
129
+ ),
130
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
131
+ ]
132
+ }
133
+ )
134
+ ]
135
+ }
136
+ )
137
+ ] });
138
+ }
139
+ function SheetTitle({ className, ...props }) {
140
+ return /* @__PURE__ */ jsx(
141
+ Dialog.Title,
142
+ {
143
+ "data-slot": "sheet-title",
144
+ className: cn("text-base font-bold text-foreground", className),
145
+ ...props
146
+ }
147
+ );
148
+ }
67
149
  function BrutalNav({
68
150
  logo,
69
151
  links,
70
152
  ctaText = "Sign In",
71
153
  ctaHref = "/admin",
154
+ variant = "solid",
72
155
  className
73
156
  }) {
74
- return /* @__PURE__ */ jsx(
75
- "header",
157
+ const [mobileOpen, setMobileOpen] = useState(false);
158
+ const [isScrolled, setIsScrolled] = useState(false);
159
+ useEffect(() => {
160
+ if (variant !== "transparent") return;
161
+ const onScroll = () => setIsScrolled(window.scrollY > 20);
162
+ onScroll();
163
+ window.addEventListener("scroll", onScroll, { passive: true });
164
+ return () => window.removeEventListener("scroll", onScroll);
165
+ }, [variant]);
166
+ const variantStyles = {
167
+ solid: "sticky top-0 z-50 w-full border-b-brutal border-foreground bg-brand",
168
+ transparent: cn(
169
+ "fixed top-0 left-0 right-0 z-50 w-full transition-all duration-200",
170
+ isScrolled ? "bg-background/80 text-foreground backdrop-blur-md border-b border-foreground/10" : "bg-transparent text-white"
171
+ ),
172
+ "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"
173
+ };
174
+ return /* @__PURE__ */ jsx("header", { className: cn(variantStyles[variant], className), children: /* @__PURE__ */ jsxs(
175
+ "div",
76
176
  {
77
177
  className: cn(
78
- "sticky top-0 z-50 w-full border-b-brutal border-foreground bg-brand",
79
- className
178
+ "flex h-14 items-center justify-between px-6",
179
+ variant === "floating-pill" ? "mx-auto max-w-7xl" : "brutal-container"
80
180
  ),
81
- children: /* @__PURE__ */ jsxs("div", { className: "brutal-container flex h-14 items-center justify-between px-6", children: [
181
+ children: [
82
182
  /* @__PURE__ */ jsx("a", { href: "/", className: "flex items-center gap-2 text-lg font-black", children: logo }),
83
183
  /* @__PURE__ */ jsx("nav", { className: "hidden items-center gap-1 md:flex", children: links.map((link) => /* @__PURE__ */ jsxs(
84
184
  "a",
85
185
  {
86
186
  href: link.href,
87
- className: "relative px-3 py-1.5 text-sm font-bold transition-colors hover:opacity-70",
187
+ className: cn(
188
+ "relative rounded-md px-3 py-1.5 text-sm font-bold transition-colors hover:opacity-70",
189
+ link.active && "bg-foreground/10"
190
+ ),
88
191
  children: [
89
192
  link.label,
90
193
  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 })
@@ -92,10 +195,64 @@ function BrutalNav({
92
195
  },
93
196
  link.href
94
197
  )) }),
95
- /* @__PURE__ */ jsx(Button, { variant: "nav", size: "sm", render: /* @__PURE__ */ jsx("a", { href: ctaHref }), children: ctaText })
96
- ] })
198
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
199
+ /* @__PURE__ */ jsx(
200
+ Button,
201
+ {
202
+ variant: "nav",
203
+ size: "sm",
204
+ render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
205
+ className: "hidden md:inline-flex",
206
+ children: ctaText
207
+ }
208
+ ),
209
+ /* @__PURE__ */ jsxs(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
210
+ /* @__PURE__ */ jsxs(
211
+ SheetTrigger,
212
+ {
213
+ render: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", className: "md:hidden" }),
214
+ children: [
215
+ /* @__PURE__ */ jsx(Menu, { className: "size-5" }),
216
+ /* @__PURE__ */ jsx("span", { className: "sr-only", children: "Menu" })
217
+ ]
218
+ }
219
+ ),
220
+ /* @__PURE__ */ jsxs(SheetContent, { side: "right", showCloseButton: true, children: [
221
+ /* @__PURE__ */ jsx(SheetTitle, { children: "Navigation" }),
222
+ /* @__PURE__ */ jsxs("nav", { className: "flex flex-col gap-1 px-2 pt-4", children: [
223
+ links.map((link) => /* @__PURE__ */ jsxs(
224
+ "a",
225
+ {
226
+ href: link.href,
227
+ onClick: () => setMobileOpen(false),
228
+ className: cn(
229
+ "flex items-center gap-2 rounded-md px-3 py-2.5 text-sm font-bold transition-colors hover:bg-foreground/5",
230
+ link.active && "bg-foreground/10"
231
+ ),
232
+ children: [
233
+ link.label,
234
+ 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 })
235
+ ]
236
+ },
237
+ link.href
238
+ )),
239
+ /* @__PURE__ */ jsx("div", { className: "mt-4 border-t border-foreground/10 pt-4", children: /* @__PURE__ */ jsx(
240
+ Button,
241
+ {
242
+ variant: "default",
243
+ size: "default",
244
+ render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
245
+ className: "w-full",
246
+ children: ctaText
247
+ }
248
+ ) })
249
+ ] })
250
+ ] })
251
+ ] })
252
+ ] })
253
+ ]
97
254
  }
98
- );
255
+ ) });
99
256
  }
100
257
 
101
258
  export { BrutalNav };
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/button.tsx","../../../src/components/brutal/nav.tsx"],"names":["ButtonPrimitive","jsx"],"mappings":"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","file":"nav.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 { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\n\ninterface NavLink {\n label: string;\n href: string;\n badge?: string;\n}\n\ninterface BrutalNavProps {\n logo: React.ReactNode;\n links: NavLink[];\n ctaText?: string;\n ctaHref?: string;\n className?: string;\n}\n\nexport function BrutalNav({\n logo,\n links,\n ctaText = \"Sign In\",\n ctaHref = \"/admin\",\n className,\n}: BrutalNavProps) {\n return (\n <header\n className={cn(\n \"sticky top-0 z-50 w-full border-b-brutal border-foreground bg-brand\",\n className\n )}\n >\n <div className=\"brutal-container flex h-14 items-center justify-between px-6\">\n {/* Logo */}\n <a href=\"/\" className=\"flex items-center gap-2 text-lg font-black\">\n {logo}\n </a>\n\n {/* Center links (desktop) */}\n <nav className=\"hidden items-center gap-1 md:flex\">\n {links.map((link) => (\n <a\n key={link.href}\n href={link.href}\n className=\"relative px-3 py-1.5 text-sm font-bold transition-colors hover:opacity-70\"\n >\n {link.label}\n {link.badge && (\n <span className=\"absolute -top-1 -right-1 border border-foreground bg-background px-1 font-mono text-[9px] font-bold uppercase text-foreground\">\n {link.badge}\n </span>\n )}\n </a>\n ))}\n </nav>\n\n {/* CTA */}\n <Button variant=\"nav\" size=\"sm\" render={<a href={ctaHref} />}>\n {ctaText}\n </Button>\n </div>\n </header>\n );\n}\n"]}
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/button.tsx","../../../src/components/ui/sheet.tsx","../../../src/components/brutal/nav.tsx"],"names":["ButtonPrimitive","jsx","SheetPrimitive","jsxs"],"mappings":"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","file":"nav.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 { useState, useEffect } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport { Button } from \"../ui/button\";\nimport {\n Sheet,\n SheetContent,\n SheetTrigger,\n SheetTitle,\n} from \"../ui/sheet\";\nimport { Menu } from \"lucide-react\";\n\ninterface NavLink {\n label: string;\n href: string;\n badge?: string;\n active?: boolean;\n}\n\ninterface BrutalNavProps {\n logo: React.ReactNode;\n links: NavLink[];\n ctaText?: string;\n ctaHref?: string;\n variant?: \"solid\" | \"transparent\" | \"floating-pill\";\n className?: string;\n}\n\nexport function BrutalNav({\n logo,\n links,\n ctaText = \"Sign In\",\n ctaHref = \"/admin\",\n variant = \"solid\",\n className,\n}: BrutalNavProps) {\n const [mobileOpen, setMobileOpen] = useState(false);\n const [isScrolled, setIsScrolled] = useState(false);\n\n useEffect(() => {\n if (variant !== \"transparent\") return;\n const onScroll = () => setIsScrolled(window.scrollY > 20);\n onScroll(); // check on mount\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n return () => window.removeEventListener(\"scroll\", onScroll);\n }, [variant]);\n\n const variantStyles = {\n solid: \"sticky top-0 z-50 w-full border-b-brutal border-foreground bg-brand\",\n transparent: cn(\n \"fixed top-0 left-0 right-0 z-50 w-full transition-all duration-200\",\n isScrolled\n ? \"bg-background/80 text-foreground backdrop-blur-md border-b border-foreground/10\"\n : \"bg-transparent text-white\"\n ),\n \"floating-pill\":\n \"fixed top-0 left-0 right-0 z-50 mx-4 mt-4 rounded-full border-brutal border-foreground bg-background shadow-brutal\",\n };\n\n return (\n <header className={cn(variantStyles[variant], className)}>\n <div\n className={cn(\n \"flex h-14 items-center justify-between px-6\",\n variant === \"floating-pill\" ? \"mx-auto max-w-7xl\" : \"brutal-container\"\n )}\n >\n {/* Logo */}\n <a href=\"/\" className=\"flex items-center gap-2 text-lg font-black\">\n {logo}\n </a>\n\n {/* Center links (desktop) */}\n <nav className=\"hidden items-center gap-1 md:flex\">\n {links.map((link) => (\n <a\n key={link.href}\n href={link.href}\n className={cn(\n \"relative rounded-md px-3 py-1.5 text-sm font-bold transition-colors hover:opacity-70\",\n link.active && \"bg-foreground/10\"\n )}\n >\n {link.label}\n {link.badge && (\n <span className=\"absolute -top-1 -right-1 border border-foreground bg-background px-1 font-mono text-[9px] font-bold uppercase text-foreground\">\n {link.badge}\n </span>\n )}\n </a>\n ))}\n </nav>\n\n {/* Right side: CTA + Hamburger */}\n <div className=\"flex items-center gap-2\">\n <Button\n variant=\"nav\"\n size=\"sm\"\n render={<a href={ctaHref} />}\n className=\"hidden md:inline-flex\"\n >\n {ctaText}\n </Button>\n\n {/* Mobile hamburger */}\n <Sheet open={mobileOpen} onOpenChange={setMobileOpen}>\n <SheetTrigger\n render={\n <Button variant=\"ghost\" size=\"icon-sm\" className=\"md:hidden\" />\n }\n >\n <Menu className=\"size-5\" />\n <span className=\"sr-only\">Menu</span>\n </SheetTrigger>\n <SheetContent side=\"right\" showCloseButton>\n <SheetTitle>Navigation</SheetTitle>\n <nav className=\"flex flex-col gap-1 px-2 pt-4\">\n {links.map((link) => (\n <a\n key={link.href}\n href={link.href}\n onClick={() => setMobileOpen(false)}\n className={cn(\n \"flex items-center gap-2 rounded-md px-3 py-2.5 text-sm font-bold transition-colors hover:bg-foreground/5\",\n link.active && \"bg-foreground/10\"\n )}\n >\n {link.label}\n {link.badge && (\n <span className=\"border border-foreground bg-background px-1 font-mono text-[9px] font-bold uppercase text-foreground\">\n {link.badge}\n </span>\n )}\n </a>\n ))}\n <div className=\"mt-4 border-t border-foreground/10 pt-4\">\n <Button\n variant=\"default\"\n size=\"default\"\n render={<a href={ctaHref} />}\n className=\"w-full\"\n >\n {ctaText}\n </Button>\n </div>\n </nav>\n </SheetContent>\n </Sheet>\n </div>\n </div>\n </header>\n );\n}\n"]}
@@ -0,0 +1,14 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface NewsletterProps {
4
+ headline?: string;
5
+ description?: string;
6
+ placeholder?: string;
7
+ buttonText?: string;
8
+ onSubmit?: (email: string) => void;
9
+ color?: "white" | "brand" | "black";
10
+ className?: string;
11
+ }
12
+ declare function Newsletter({ headline, description, placeholder, buttonText, onSubmit, color, className, }: NewsletterProps): react_jsx_runtime.JSX.Element;
13
+
14
+ export { Newsletter };
@@ -0,0 +1,169 @@
1
+ "use client";
2
+ import { Button as Button$1 } from '@base-ui/react/button';
3
+ import { cva } from 'class-variance-authority';
4
+ import { clsx } from 'clsx';
5
+ import { twMerge } from 'tailwind-merge';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+ import { Input as Input$1 } from '@base-ui/react/input';
8
+
9
+ // src/components/ui/button.tsx
10
+ function cn(...inputs) {
11
+ return twMerge(clsx(inputs));
12
+ }
13
+ var buttonVariants = cva(
14
+ "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",
15
+ {
16
+ variants: {
17
+ variant: {
18
+ // Primary: Black bg, white text, offset shadow
19
+ 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",
20
+ // CTA: Mint green bg — the Bannerbear signature
21
+ 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",
22
+ // Brand: Dynamic brand color bg
23
+ 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",
24
+ // Outline: White bg, black border, offset shadow
25
+ 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",
26
+ // Secondary: Light bg, border, smaller shadow
27
+ 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",
28
+ // Ghost: No border/shadow, subtle hover
29
+ ghost: "hover:bg-secondary hover:text-foreground",
30
+ // Link: Text only
31
+ link: "text-foreground underline-offset-4 hover:underline",
32
+ // Destructive
33
+ 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",
34
+ // Nav: Thin border, no shadow (for nav Sign In buttons)
35
+ nav: "border border-foreground bg-background text-foreground hover:bg-foreground hover:text-background"
36
+ },
37
+ size: {
38
+ xs: "h-7 gap-1 px-2.5 text-xs",
39
+ sm: "h-8 gap-1.5 px-3 text-sm",
40
+ default: "h-10 gap-2 px-5 text-sm",
41
+ lg: "h-12 gap-2 px-7 text-base",
42
+ xl: "h-14 gap-2.5 px-9 text-lg",
43
+ icon: "size-10",
44
+ "icon-sm": "size-8",
45
+ "icon-lg": "size-12"
46
+ }
47
+ },
48
+ defaultVariants: {
49
+ variant: "default",
50
+ size: "default"
51
+ }
52
+ }
53
+ );
54
+ function Button({
55
+ className,
56
+ variant = "default",
57
+ size = "default",
58
+ ...props
59
+ }) {
60
+ return /* @__PURE__ */ jsx(
61
+ Button$1,
62
+ {
63
+ "data-slot": "button",
64
+ className: cn(buttonVariants({ variant, size, className })),
65
+ ...props
66
+ }
67
+ );
68
+ }
69
+ function Input({ className, type, ...props }) {
70
+ return /* @__PURE__ */ jsx(
71
+ Input$1,
72
+ {
73
+ type,
74
+ "data-slot": "input",
75
+ className: cn(
76
+ "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",
77
+ className
78
+ ),
79
+ ...props
80
+ }
81
+ );
82
+ }
83
+ var colorMap = {
84
+ white: "bg-background text-foreground",
85
+ brand: "bg-brand",
86
+ "brand-muted": "bg-brand-muted text-foreground",
87
+ black: "bg-foreground text-background",
88
+ cta: "bg-cta"
89
+ };
90
+ var containerMap = {
91
+ sm: "brutal-container-sm",
92
+ default: "brutal-container",
93
+ lg: "brutal-container-lg"
94
+ };
95
+ var paddingMap = {
96
+ sm: "brutal-section-sm",
97
+ default: "brutal-section",
98
+ lg: "brutal-section py-28 sm:py-36 md:py-44"
99
+ };
100
+ var patternMap = {
101
+ dots: "brutal-dots",
102
+ stripes: "brutal-stripes",
103
+ noise: "brutal-noise",
104
+ grain: "brutal-grain",
105
+ crosshatch: "brutal-crosshatch",
106
+ "grid-dots": "brutal-grid-dots",
107
+ "gradient-mesh": "brutal-gradient-mesh",
108
+ none: ""
109
+ };
110
+ function BrutalSection({
111
+ children,
112
+ color = "white",
113
+ className,
114
+ containerSize = "default",
115
+ padding = "default",
116
+ pattern,
117
+ dots = false,
118
+ stripes = false,
119
+ id
120
+ }) {
121
+ const resolvedPattern = pattern ?? (dots ? "dots" : void 0) ?? (stripes ? "stripes" : void 0) ?? "none";
122
+ return /* @__PURE__ */ jsx(
123
+ "section",
124
+ {
125
+ id,
126
+ className: cn(
127
+ paddingMap[padding],
128
+ colorMap[color],
129
+ patternMap[resolvedPattern],
130
+ className
131
+ ),
132
+ children: /* @__PURE__ */ jsx("div", { className: containerMap[containerSize], children })
133
+ }
134
+ );
135
+ }
136
+ function Newsletter({
137
+ headline = "Stay in the loop",
138
+ description,
139
+ placeholder = "you@example.com",
140
+ buttonText = "Subscribe",
141
+ onSubmit,
142
+ color = "white",
143
+ className
144
+ }) {
145
+ 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: [
146
+ /* @__PURE__ */ jsx("h3", { className: "brutal-h3 mb-2", children: headline }),
147
+ description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-6 text-muted-foreground", children: description }),
148
+ /* @__PURE__ */ jsxs(
149
+ "form",
150
+ {
151
+ onSubmit: (e) => {
152
+ e.preventDefault();
153
+ const form = e.target;
154
+ const email = new FormData(form).get("email");
155
+ onSubmit?.(email);
156
+ },
157
+ className: "flex gap-3",
158
+ children: [
159
+ /* @__PURE__ */ jsx(Input, { type: "email", name: "email", placeholder, required: true, className: "flex-1" }),
160
+ /* @__PURE__ */ jsx(Button, { type: "submit", variant: "cta", children: buttonText })
161
+ ]
162
+ }
163
+ )
164
+ ] }) });
165
+ }
166
+
167
+ export { Newsletter };
168
+ //# sourceMappingURL=newsletter.js.map
169
+ //# sourceMappingURL=newsletter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/lib/utils.ts","../../../src/components/ui/button.tsx","../../../src/components/ui/input.tsx","../../../src/components/brutal/section.tsx","../../../src/components/brutal/newsletter.tsx"],"names":["ButtonPrimitive","jsx","InputPrimitive"],"mappings":"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","file":"newsletter.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 * as React from \"react\";\nimport { Input as InputPrimitive } from \"@base-ui/react/input\";\n\nimport { cn } from \"../../lib/utils\";\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <InputPrimitive\n type={type}\n data-slot=\"input\"\n className={cn(\n \"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\",\n className\n )}\n {...props}\n />\n );\n}\n\nexport { Input };\n","import { cn } from \"../../lib/utils\";\n\nexport type SectionColor =\n | \"white\"\n | \"brand\"\n | \"brand-muted\"\n | \"black\"\n | \"cta\";\n\nexport type SectionPattern =\n | \"dots\"\n | \"stripes\"\n | \"noise\"\n | \"grain\"\n | \"crosshatch\"\n | \"grid-dots\"\n | \"gradient-mesh\"\n | \"none\";\n\ninterface BrutalSectionProps {\n children: React.ReactNode;\n color?: SectionColor;\n className?: string;\n containerSize?: \"sm\" | \"default\" | \"lg\";\n padding?: \"sm\" | \"default\" | \"lg\";\n pattern?: SectionPattern;\n /** @deprecated Use pattern=\"dots\" instead */\n dots?: boolean;\n /** @deprecated Use pattern=\"stripes\" instead */\n stripes?: boolean;\n id?: string;\n}\n\nconst colorMap: Record<SectionColor, string> = {\n white: \"bg-background text-foreground\",\n brand: \"bg-brand\",\n \"brand-muted\": \"bg-brand-muted text-foreground\",\n black: \"bg-foreground text-background\",\n cta: \"bg-cta\",\n};\n\nconst containerMap = {\n sm: \"brutal-container-sm\",\n default: \"brutal-container\",\n lg: \"brutal-container-lg\",\n};\n\nconst paddingMap = {\n sm: \"brutal-section-sm\",\n default: \"brutal-section\",\n lg: \"brutal-section py-28 sm:py-36 md:py-44\",\n};\n\nconst patternMap: Record<SectionPattern, string> = {\n dots: \"brutal-dots\",\n stripes: \"brutal-stripes\",\n noise: \"brutal-noise\",\n grain: \"brutal-grain\",\n crosshatch: \"brutal-crosshatch\",\n \"grid-dots\": \"brutal-grid-dots\",\n \"gradient-mesh\": \"brutal-gradient-mesh\",\n none: \"\",\n};\n\nexport function BrutalSection({\n children,\n color = \"white\",\n className,\n containerSize = \"default\",\n padding = \"default\",\n pattern,\n dots = false,\n stripes = false,\n id,\n}: BrutalSectionProps) {\n const resolvedPattern = pattern\n ?? (dots ? \"dots\" : undefined)\n ?? (stripes ? \"stripes\" : undefined)\n ?? \"none\";\n\n return (\n <section\n id={id}\n className={cn(\n paddingMap[padding],\n colorMap[color],\n patternMap[resolvedPattern],\n className\n )}\n >\n <div className={containerMap[containerSize]}>{children}</div>\n </section>\n );\n}\n","import { Button } from \"../ui/button\";\nimport { Input } from \"../ui/input\";\nimport { BrutalSection } from \"./section\";\n\ninterface NewsletterProps {\n headline?: string;\n description?: string;\n placeholder?: string;\n buttonText?: string;\n onSubmit?: (email: string) => void;\n color?: \"white\" | \"brand\" | \"black\";\n className?: string;\n}\n\nexport function Newsletter({\n headline = \"Stay in the loop\",\n description,\n placeholder = \"you@example.com\",\n buttonText = \"Subscribe\",\n onSubmit,\n color = \"white\",\n className,\n}: NewsletterProps) {\n return (\n <BrutalSection color={color} padding=\"sm\" className={className}>\n <div className=\"mx-auto max-w-md border-brutal border-foreground bg-background p-8 text-foreground shadow-brutal-lg\">\n <h3 className=\"brutal-h3 mb-2\">{headline}</h3>\n {description && (\n <p className=\"brutal-body mb-6 text-muted-foreground\">{description}</p>\n )}\n <form\n onSubmit={(e) => {\n e.preventDefault();\n const form = e.target as HTMLFormElement;\n const email = new FormData(form).get(\"email\") as string;\n onSubmit?.(email);\n }}\n className=\"flex gap-3\"\n >\n <Input type=\"email\" name=\"email\" placeholder={placeholder} required className=\"flex-1\" />\n <Button type=\"submit\" variant=\"cta\">{buttonText}</Button>\n </form>\n </div>\n </BrutalSection>\n );\n}\n"]}
@@ -0,0 +1,27 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface PricingTier {
4
+ name: string;
5
+ description?: string;
6
+ price: {
7
+ monthly: number | string;
8
+ annual: number | string;
9
+ };
10
+ features: string[];
11
+ ctaText: string;
12
+ ctaHref?: string;
13
+ ctaVariant?: "cta" | "brand" | "default" | "outline";
14
+ }
15
+ interface PricingTableProps {
16
+ badge?: string;
17
+ headline?: string;
18
+ description?: string;
19
+ tiers: PricingTier[];
20
+ popularIndex?: number;
21
+ billingToggle?: boolean;
22
+ color?: "white" | "black";
23
+ className?: string;
24
+ }
25
+ declare function PricingTable({ badge, headline, description, tiers, popularIndex, billingToggle, color, className, }: PricingTableProps): react_jsx_runtime.JSX.Element;
26
+
27
+ export { PricingTable };