@snow-labs/brutal-ui 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/brutal/cta-section.d.ts +7 -2
- package/dist/components/brutal/cta-section.js +136 -32
- package/dist/components/brutal/cta-section.js.map +1 -1
- package/dist/components/brutal/faq.d.ts +16 -0
- package/dist/components/brutal/faq.js +163 -0
- package/dist/components/brutal/faq.js.map +1 -0
- package/dist/components/brutal/feature-grid.d.ts +6 -2
- package/dist/components/brutal/feature-grid.js +73 -10
- package/dist/components/brutal/feature-grid.js.map +1 -1
- package/dist/components/brutal/footer.d.ts +14 -1
- package/dist/components/brutal/footer.js +181 -18
- package/dist/components/brutal/footer.js.map +1 -1
- package/dist/components/brutal/hero.d.ts +9 -2
- package/dist/components/brutal/hero.js +67 -22
- package/dist/components/brutal/hero.js.map +1 -1
- package/dist/components/brutal/index.d.ts +7 -2
- package/dist/components/brutal/index.js +1035 -128
- package/dist/components/brutal/index.js.map +1 -1
- package/dist/components/brutal/integration-grid.d.ts +1 -1
- package/dist/components/brutal/integration-grid.js +13 -5
- package/dist/components/brutal/integration-grid.js.map +1 -1
- package/dist/components/brutal/logo-cloud.d.ts +17 -0
- package/dist/components/brutal/logo-cloud.js +93 -0
- package/dist/components/brutal/logo-cloud.js.map +1 -0
- package/dist/components/brutal/nav.d.ts +3 -1
- package/dist/components/brutal/nav.js +166 -9
- package/dist/components/brutal/nav.js.map +1 -1
- package/dist/components/brutal/newsletter.d.ts +14 -0
- package/dist/components/brutal/newsletter.js +169 -0
- package/dist/components/brutal/newsletter.js.map +1 -0
- package/dist/components/brutal/pricing-table.d.ts +27 -0
- package/dist/components/brutal/pricing-table.js +251 -0
- package/dist/components/brutal/pricing-table.js.map +1 -0
- package/dist/components/brutal/section-divider.d.ts +14 -0
- package/dist/components/brutal/section-divider.js +70 -0
- package/dist/components/brutal/section-divider.js.map +1 -0
- package/dist/components/brutal/section.d.ts +7 -3
- package/dist/components/brutal/section.js +13 -5
- package/dist/components/brutal/section.js.map +1 -1
- package/dist/components/brutal/stats-bar.d.ts +16 -0
- package/dist/components/brutal/stats-bar.js +127 -0
- package/dist/components/brutal/stats-bar.js.map +1 -0
- package/dist/components/brutal/testimonials.d.ts +11 -3
- package/dist/components/brutal/testimonials.js +126 -33
- package/dist/components/brutal/testimonials.js.map +1 -1
- package/dist/components/brutal/wave-divider.d.ts +2 -12
- package/dist/components/brutal/wave-divider.js +54 -26
- package/dist/components/brutal/wave-divider.js.map +1 -1
- package/dist/components/dashboard/activity-feed.d.ts +18 -0
- package/dist/components/dashboard/activity-feed.js +105 -0
- package/dist/components/dashboard/activity-feed.js.map +1 -0
- package/dist/components/dashboard/app-shell.d.ts +19 -0
- package/dist/components/dashboard/app-shell.js +206 -0
- package/dist/components/dashboard/app-shell.js.map +1 -0
- package/dist/components/dashboard/empty-state.d.ts +14 -0
- package/dist/components/dashboard/empty-state.js +96 -0
- package/dist/components/dashboard/empty-state.js.map +1 -0
- package/dist/components/dashboard/file-upload.d.ts +12 -0
- package/dist/components/dashboard/file-upload.js +86 -0
- package/dist/components/dashboard/file-upload.js.map +1 -0
- package/dist/components/dashboard/index.d.ts +10 -0
- package/dist/components/dashboard/index.js +755 -0
- package/dist/components/dashboard/index.js.map +1 -0
- package/dist/components/dashboard/search-bar.d.ts +12 -0
- package/dist/components/dashboard/search-bar.js +49 -0
- package/dist/components/dashboard/search-bar.js.map +1 -0
- package/dist/components/dashboard/sidebar.d.ts +23 -0
- package/dist/components/dashboard/sidebar.js +113 -0
- package/dist/components/dashboard/sidebar.js.map +1 -0
- package/dist/components/dashboard/stat-card.d.ts +13 -0
- package/dist/components/dashboard/stat-card.js +55 -0
- package/dist/components/dashboard/stat-card.js.map +1 -0
- package/dist/components/dashboard/user-menu.d.ts +16 -0
- package/dist/components/dashboard/user-menu.js +179 -0
- package/dist/components/dashboard/user-menu.js.map +1 -0
- package/dist/components/dashboard/view-switcher.d.ts +12 -0
- package/dist/components/dashboard/view-switcher.js +130 -0
- package/dist/components/dashboard/view-switcher.js.map +1 -0
- package/dist/components/views/calendar-view.d.ts +17 -0
- package/dist/components/views/calendar-view.js +182 -0
- package/dist/components/views/calendar-view.js.map +1 -0
- package/dist/components/views/data-table.d.ts +15 -0
- package/dist/components/views/data-table.js +204 -0
- package/dist/components/views/data-table.js.map +1 -0
- package/dist/components/views/grid-view.d.ts +11 -0
- package/dist/components/views/grid-view.js +31 -0
- package/dist/components/views/grid-view.js.map +1 -0
- package/dist/components/views/index.d.ts +7 -0
- package/dist/components/views/index.js +542 -0
- package/dist/components/views/index.js.map +1 -0
- package/dist/components/views/kanban-board.d.ts +21 -0
- package/dist/components/views/kanban-board.js +153 -0
- package/dist/components/views/kanban-board.js.map +1 -0
- package/dist/components/views/list-view.d.ts +19 -0
- package/dist/components/views/list-view.js +96 -0
- package/dist/components/views/list-view.js.map +1 -0
- package/dist/index.d.ts +27 -3
- package/dist/index.js +1881 -142
- package/dist/index.js.map +1 -1
- package/dist/lib/animations.d.ts +68 -0
- package/dist/lib/animations.js +44 -0
- package/dist/lib/animations.js.map +1 -0
- package/dist/templates/dashboard.d.ts +40 -0
- package/dist/templates/dashboard.js +658 -0
- package/dist/templates/dashboard.js.map +1 -0
- package/dist/templates/index.d.ts +4 -0
- package/dist/templates/index.js +2001 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/templates/saas-launch.d.ts +113 -0
- package/dist/templates/saas-launch.js +1394 -0
- package/dist/templates/saas-launch.js.map +1 -0
- package/dist/templates/studio.d.ts +72 -0
- package/dist/templates/studio.js +1099 -0
- package/dist/templates/studio.js.map +1 -0
- package/dist/theme.css +58 -15
- package/package.json +48 -2
|
@@ -4,6 +4,13 @@ import { twMerge } from 'tailwind-merge';
|
|
|
4
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
5
|
import { Button as Button$1 } from '@base-ui/react/button';
|
|
6
6
|
import { cva } from 'class-variance-authority';
|
|
7
|
+
import { useState, useEffect, useRef } from 'react';
|
|
8
|
+
import { Dialog } from '@base-ui/react/dialog';
|
|
9
|
+
import { Menu, XIcon, ChevronDownIcon, ChevronUpIcon } from 'lucide-react';
|
|
10
|
+
import { Input as Input$1 } from '@base-ui/react/input';
|
|
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';
|
|
7
14
|
|
|
8
15
|
// src/lib/utils.ts
|
|
9
16
|
function cn(...inputs) {
|
|
@@ -13,9 +20,6 @@ var colorMap = {
|
|
|
13
20
|
white: "bg-background text-foreground",
|
|
14
21
|
brand: "bg-brand",
|
|
15
22
|
"brand-muted": "bg-brand-muted text-foreground",
|
|
16
|
-
blue: "bg-section-blue",
|
|
17
|
-
gray: "bg-section-gray text-foreground",
|
|
18
|
-
cream: "bg-section-cream text-foreground",
|
|
19
23
|
black: "bg-foreground text-background",
|
|
20
24
|
cta: "bg-cta"
|
|
21
25
|
};
|
|
@@ -29,16 +33,28 @@ var paddingMap = {
|
|
|
29
33
|
default: "brutal-section",
|
|
30
34
|
lg: "brutal-section py-28 sm:py-36 md:py-44"
|
|
31
35
|
};
|
|
36
|
+
var patternMap = {
|
|
37
|
+
dots: "brutal-dots",
|
|
38
|
+
stripes: "brutal-stripes",
|
|
39
|
+
noise: "brutal-noise",
|
|
40
|
+
grain: "brutal-grain",
|
|
41
|
+
crosshatch: "brutal-crosshatch",
|
|
42
|
+
"grid-dots": "brutal-grid-dots",
|
|
43
|
+
"gradient-mesh": "brutal-gradient-mesh",
|
|
44
|
+
none: ""
|
|
45
|
+
};
|
|
32
46
|
function BrutalSection({
|
|
33
47
|
children,
|
|
34
48
|
color = "white",
|
|
35
49
|
className,
|
|
36
50
|
containerSize = "default",
|
|
37
51
|
padding = "default",
|
|
52
|
+
pattern,
|
|
38
53
|
dots = false,
|
|
39
54
|
stripes = false,
|
|
40
55
|
id
|
|
41
56
|
}) {
|
|
57
|
+
const resolvedPattern = pattern ?? (dots ? "dots" : void 0) ?? (stripes ? "stripes" : void 0) ?? "none";
|
|
42
58
|
return /* @__PURE__ */ jsx(
|
|
43
59
|
"section",
|
|
44
60
|
{
|
|
@@ -46,45 +62,67 @@ function BrutalSection({
|
|
|
46
62
|
className: cn(
|
|
47
63
|
paddingMap[padding],
|
|
48
64
|
colorMap[color],
|
|
49
|
-
|
|
50
|
-
stripes && "brutal-stripes",
|
|
65
|
+
patternMap[resolvedPattern],
|
|
51
66
|
className
|
|
52
67
|
),
|
|
53
68
|
children: /* @__PURE__ */ jsx("div", { className: containerMap[containerSize], children })
|
|
54
69
|
}
|
|
55
70
|
);
|
|
56
71
|
}
|
|
57
|
-
|
|
72
|
+
var paths = {
|
|
73
|
+
wave: "M0,64 C160,128 320,0 480,64 C640,128 800,0 960,64 L960,160 L0,160 Z",
|
|
74
|
+
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",
|
|
75
|
+
curve: "M0,128 Q480,-32 960,128 L960,160 L0,160 Z",
|
|
76
|
+
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",
|
|
77
|
+
"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",
|
|
78
|
+
"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",
|
|
79
|
+
geometric: "M0,100 L120,60 L240,80 L360,40 L480,90 L600,50 L720,70 L840,30 L960,80 L960,160 L0,160 Z",
|
|
80
|
+
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",
|
|
81
|
+
diagonal: "M0,160 L960,60 L960,160 Z",
|
|
82
|
+
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",
|
|
83
|
+
"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"
|
|
84
|
+
};
|
|
85
|
+
function SectionDivider({
|
|
58
86
|
from = "hsl(var(--background))",
|
|
59
87
|
to = "hsl(var(--background))",
|
|
60
88
|
flip = false,
|
|
61
89
|
className = "",
|
|
62
|
-
variant = "wave"
|
|
90
|
+
variant = "wave",
|
|
91
|
+
layers = false
|
|
63
92
|
}) {
|
|
64
|
-
|
|
65
|
-
wave: "M0,64 C160,128 320,0 480,64 C640,128 800,0 960,64 L960,160 L0,160 Z",
|
|
66
|
-
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",
|
|
67
|
-
curve: "M0,128 Q480,-32 960,128 L960,160 L0,160 Z",
|
|
68
|
-
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"
|
|
69
|
-
};
|
|
70
|
-
return /* @__PURE__ */ jsx(
|
|
93
|
+
return /* @__PURE__ */ jsxs(
|
|
71
94
|
"div",
|
|
72
95
|
{
|
|
73
|
-
className:
|
|
96
|
+
className: cn("relative -my-px w-full overflow-hidden", className),
|
|
74
97
|
style: { backgroundColor: from },
|
|
75
|
-
children:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
98
|
+
children: [
|
|
99
|
+
layers && /* @__PURE__ */ jsx(
|
|
100
|
+
"svg",
|
|
101
|
+
{
|
|
102
|
+
viewBox: "0 0 960 160",
|
|
103
|
+
preserveAspectRatio: "none",
|
|
104
|
+
className: "absolute inset-0 block w-full opacity-30",
|
|
105
|
+
style: {
|
|
106
|
+
height: "clamp(40px, 6vw, 80px)",
|
|
107
|
+
transform: flip ? "scaleY(-1) translateY(4px)" : "translateY(-4px)"
|
|
108
|
+
},
|
|
109
|
+
children: /* @__PURE__ */ jsx("path", { d: paths[variant], fill: to })
|
|
110
|
+
}
|
|
111
|
+
),
|
|
112
|
+
/* @__PURE__ */ jsx(
|
|
113
|
+
"svg",
|
|
114
|
+
{
|
|
115
|
+
viewBox: "0 0 960 160",
|
|
116
|
+
preserveAspectRatio: "none",
|
|
117
|
+
className: "relative block w-full",
|
|
118
|
+
style: {
|
|
119
|
+
height: "clamp(40px, 6vw, 80px)",
|
|
120
|
+
transform: flip ? "scaleY(-1)" : void 0
|
|
121
|
+
},
|
|
122
|
+
children: /* @__PURE__ */ jsx("path", { d: paths[variant], fill: to })
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
]
|
|
88
126
|
}
|
|
89
127
|
);
|
|
90
128
|
}
|
|
@@ -145,39 +183,76 @@ function Button({
|
|
|
145
183
|
);
|
|
146
184
|
}
|
|
147
185
|
function BrutalHero({
|
|
186
|
+
variant = "split",
|
|
148
187
|
badge,
|
|
188
|
+
badgePosition = "above",
|
|
149
189
|
headline,
|
|
150
190
|
description,
|
|
151
191
|
ctaText,
|
|
152
192
|
ctaHref = "#",
|
|
153
193
|
ctaVariant = "cta",
|
|
194
|
+
secondaryText,
|
|
195
|
+
secondaryHref,
|
|
154
196
|
visual,
|
|
155
197
|
color = "brand",
|
|
198
|
+
pattern,
|
|
156
199
|
proof,
|
|
157
200
|
className
|
|
158
201
|
}) {
|
|
159
|
-
|
|
202
|
+
const badgeElement = badge && /* @__PURE__ */ jsx(
|
|
160
203
|
"div",
|
|
161
204
|
{
|
|
162
205
|
className: cn(
|
|
163
|
-
"
|
|
164
|
-
|
|
206
|
+
"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",
|
|
207
|
+
badgePosition === "floating" && "absolute -top-3 left-6 z-10"
|
|
165
208
|
),
|
|
166
|
-
children:
|
|
167
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-6", children: [
|
|
168
|
-
badge && /* @__PURE__ */ jsx("div", { className: "inline-flex w-fit border-brutal border-foreground bg-background px-3 py-1 font-mono text-xs font-bold uppercase tracking-widest shadow-brutal-sm", children: badge }),
|
|
169
|
-
/* @__PURE__ */ jsx("h1", { className: "brutal-display text-balance", children: headline }),
|
|
170
|
-
/* @__PURE__ */ jsx("p", { className: "brutal-body-lg max-w-lg opacity-80", children: description }),
|
|
171
|
-
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsx(Button, { variant: ctaVariant, size: "xl", render: /* @__PURE__ */ jsx("a", { href: ctaHref }), children: ctaText }) }),
|
|
172
|
-
proof && /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-medium opacity-70", children: [
|
|
173
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex size-5 items-center justify-center border border-current text-xs", children: "\u2713" }),
|
|
174
|
-
proof
|
|
175
|
-
] })
|
|
176
|
-
] }),
|
|
177
|
-
visual && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center", children: visual })
|
|
178
|
-
]
|
|
209
|
+
children: badge
|
|
179
210
|
}
|
|
180
|
-
)
|
|
211
|
+
);
|
|
212
|
+
const textContent = /* @__PURE__ */ jsxs("div", { className: cn(
|
|
213
|
+
"flex flex-col gap-6",
|
|
214
|
+
variant === "centered" && "items-center text-center"
|
|
215
|
+
), children: [
|
|
216
|
+
badgePosition === "above" && badgeElement,
|
|
217
|
+
/* @__PURE__ */ jsxs("h1", { className: cn(
|
|
218
|
+
"brutal-display text-balance",
|
|
219
|
+
variant === "centered" && "mx-auto max-w-4xl"
|
|
220
|
+
), children: [
|
|
221
|
+
badgePosition === "inline" && badgeElement,
|
|
222
|
+
headline
|
|
223
|
+
] }),
|
|
224
|
+
/* @__PURE__ */ jsx("p", { className: cn(
|
|
225
|
+
"brutal-body-lg max-w-lg opacity-80",
|
|
226
|
+
variant === "centered" && "mx-auto"
|
|
227
|
+
), children: description }),
|
|
228
|
+
/* @__PURE__ */ jsxs("div", { className: cn(
|
|
229
|
+
"flex flex-col gap-4 sm:flex-row sm:flex-wrap",
|
|
230
|
+
variant === "centered" && "sm:justify-center"
|
|
231
|
+
), children: [
|
|
232
|
+
/* @__PURE__ */ jsx(Button, { variant: ctaVariant, size: "xl", className: "w-full sm:w-auto", render: /* @__PURE__ */ jsx("a", { href: ctaHref }), children: ctaText }),
|
|
233
|
+
secondaryText && /* @__PURE__ */ jsx(Button, { variant: "outline", size: "xl", className: "w-full sm:w-auto", render: /* @__PURE__ */ jsx("a", { href: secondaryHref || "#" }), children: secondaryText })
|
|
234
|
+
] }),
|
|
235
|
+
proof && /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-2 text-sm font-medium opacity-70", children: [
|
|
236
|
+
/* @__PURE__ */ jsx("span", { className: "inline-flex size-5 items-center justify-center border border-current text-xs", children: "\u2713" }),
|
|
237
|
+
proof
|
|
238
|
+
] })
|
|
239
|
+
] });
|
|
240
|
+
const layoutClass = {
|
|
241
|
+
split: "grid items-center gap-12 lg:grid-cols-2 lg:gap-16",
|
|
242
|
+
centered: "flex flex-col items-center gap-12",
|
|
243
|
+
overlap: "relative",
|
|
244
|
+
asymmetric: "grid items-center gap-12 lg:grid-cols-[3fr_2fr] lg:gap-16"
|
|
245
|
+
}[variant];
|
|
246
|
+
return /* @__PURE__ */ jsxs(BrutalSection, { color, padding: "lg", pattern, className: cn("relative", className), children: [
|
|
247
|
+
badgePosition === "floating" && badgeElement,
|
|
248
|
+
/* @__PURE__ */ jsxs("div", { className: layoutClass, children: [
|
|
249
|
+
textContent,
|
|
250
|
+
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(
|
|
251
|
+
"flex items-center justify-center",
|
|
252
|
+
variant === "asymmetric" && "-rotate-2 transform"
|
|
253
|
+
), children: visual }) : null
|
|
254
|
+
] })
|
|
255
|
+
] });
|
|
181
256
|
}
|
|
182
257
|
function Card({
|
|
183
258
|
className,
|
|
@@ -241,6 +316,7 @@ var colMap = {
|
|
|
241
316
|
4: "sm:grid-cols-2 lg:grid-cols-4"
|
|
242
317
|
};
|
|
243
318
|
function BrutalFeatureGrid({
|
|
319
|
+
variant = "icon-top",
|
|
244
320
|
badge,
|
|
245
321
|
headline,
|
|
246
322
|
description,
|
|
@@ -251,57 +327,196 @@ function BrutalFeatureGrid({
|
|
|
251
327
|
}) {
|
|
252
328
|
return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
|
|
253
329
|
/* @__PURE__ */ jsxs("div", { className: "mb-12 max-w-2xl", children: [
|
|
254
|
-
badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-
|
|
330
|
+
badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-brand", children: badge }),
|
|
255
331
|
/* @__PURE__ */ jsx("h2", { className: "brutal-h2 mb-4", children: headline }),
|
|
256
332
|
description && /* @__PURE__ */ jsx("p", { className: "brutal-body text-muted-foreground", children: description })
|
|
257
333
|
] }),
|
|
258
|
-
/* @__PURE__ */ jsx(
|
|
334
|
+
/* @__PURE__ */ jsx(
|
|
335
|
+
"div",
|
|
336
|
+
{
|
|
337
|
+
className: cn(
|
|
338
|
+
"grid gap-6",
|
|
339
|
+
variant === "bento" ? "sm:grid-cols-2 lg:grid-cols-3" : colMap[columns]
|
|
340
|
+
),
|
|
341
|
+
children: features.map((feature, i) => /* @__PURE__ */ jsx(
|
|
342
|
+
FeatureCard,
|
|
343
|
+
{
|
|
344
|
+
feature,
|
|
345
|
+
variant,
|
|
346
|
+
index: i
|
|
347
|
+
},
|
|
348
|
+
feature.title
|
|
349
|
+
))
|
|
350
|
+
}
|
|
351
|
+
)
|
|
352
|
+
] });
|
|
353
|
+
}
|
|
354
|
+
function FeatureCard({
|
|
355
|
+
feature,
|
|
356
|
+
variant,
|
|
357
|
+
index
|
|
358
|
+
}) {
|
|
359
|
+
const isBentoFeatured = variant === "bento" && feature.featured;
|
|
360
|
+
if (variant === "icon-left") {
|
|
361
|
+
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: [
|
|
362
|
+
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 }),
|
|
363
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
364
|
+
feature.stat && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-1 text-brand", children: feature.stat }),
|
|
365
|
+
/* @__PURE__ */ jsx("h3", { className: "brutal-h4 mb-1", children: feature.title }),
|
|
366
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: feature.description })
|
|
367
|
+
] })
|
|
368
|
+
] });
|
|
369
|
+
}
|
|
370
|
+
if (variant === "numbered") {
|
|
371
|
+
return /* @__PURE__ */ jsxs(Card, { children: [
|
|
259
372
|
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
260
|
-
|
|
373
|
+
/* @__PURE__ */ jsx("span", { className: "brutal-display mb-2 block text-brand opacity-20", children: String(index + 1).padStart(2, "0") }),
|
|
374
|
+
feature.stat && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-1 text-brand", children: feature.stat }),
|
|
261
375
|
/* @__PURE__ */ jsx(CardTitle, { children: feature.title })
|
|
262
376
|
] }),
|
|
263
377
|
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(CardDescription, { children: feature.description }) })
|
|
264
|
-
] }
|
|
378
|
+
] });
|
|
379
|
+
}
|
|
380
|
+
return /* @__PURE__ */ jsxs(
|
|
381
|
+
Card,
|
|
382
|
+
{
|
|
383
|
+
className: cn(
|
|
384
|
+
isBentoFeatured && "sm:col-span-2 bg-brand-muted"
|
|
385
|
+
),
|
|
386
|
+
children: [
|
|
387
|
+
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
388
|
+
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 }),
|
|
389
|
+
feature.stat && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-1 text-brand", children: feature.stat }),
|
|
390
|
+
/* @__PURE__ */ jsx(CardTitle, { children: feature.title })
|
|
391
|
+
] }),
|
|
392
|
+
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(CardDescription, { children: feature.description }) })
|
|
393
|
+
]
|
|
394
|
+
}
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
function StarRating({ rating }) {
|
|
398
|
+
return /* @__PURE__ */ jsx("div", { className: "flex gap-0.5", children: Array.from({ length: 5 }, (_, i) => /* @__PURE__ */ jsx(
|
|
399
|
+
"span",
|
|
400
|
+
{
|
|
401
|
+
className: cn(
|
|
402
|
+
"text-sm",
|
|
403
|
+
i < rating ? "text-amber-500" : "text-foreground/20"
|
|
404
|
+
),
|
|
405
|
+
children: "\u2605"
|
|
406
|
+
},
|
|
407
|
+
i
|
|
408
|
+
)) });
|
|
409
|
+
}
|
|
410
|
+
function TestimonialCard({
|
|
411
|
+
t,
|
|
412
|
+
className
|
|
413
|
+
}) {
|
|
414
|
+
return /* @__PURE__ */ jsxs(
|
|
415
|
+
"div",
|
|
416
|
+
{
|
|
417
|
+
className: cn(
|
|
418
|
+
"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",
|
|
419
|
+
className
|
|
420
|
+
),
|
|
421
|
+
children: [
|
|
422
|
+
/* @__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" }),
|
|
423
|
+
t.rating && /* @__PURE__ */ jsx("div", { className: "mb-3", children: /* @__PURE__ */ jsx(StarRating, { rating: t.rating }) }),
|
|
424
|
+
/* @__PURE__ */ jsx("p", { className: "relative mb-4 text-sm leading-relaxed", children: t.text }),
|
|
425
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
426
|
+
t.avatar ? /* @__PURE__ */ jsx(
|
|
427
|
+
"img",
|
|
428
|
+
{
|
|
429
|
+
src: t.avatar,
|
|
430
|
+
alt: t.name,
|
|
431
|
+
className: "size-9 border-2 object-cover",
|
|
432
|
+
style: { borderColor: "hsl(var(--brand))" }
|
|
433
|
+
}
|
|
434
|
+
) : /* @__PURE__ */ jsx(
|
|
435
|
+
"div",
|
|
436
|
+
{
|
|
437
|
+
className: "flex size-9 items-center justify-center border-2 font-bold text-brand-foreground",
|
|
438
|
+
style: {
|
|
439
|
+
borderColor: "hsl(var(--brand))",
|
|
440
|
+
backgroundColor: "hsl(var(--brand))"
|
|
441
|
+
},
|
|
442
|
+
children: t.name[0]
|
|
443
|
+
}
|
|
444
|
+
),
|
|
445
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
446
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-bold", children: t.name }),
|
|
447
|
+
(t.role || t.company) && /* @__PURE__ */ jsxs("p", { className: "truncate text-xs text-muted-foreground", children: [
|
|
448
|
+
t.role,
|
|
449
|
+
t.role && t.company && " \xB7 ",
|
|
450
|
+
t.company
|
|
451
|
+
] }),
|
|
452
|
+
!t.role && !t.company && t.handle && /* @__PURE__ */ jsx("p", { className: "font-mono text-xs text-muted-foreground", children: t.handle })
|
|
453
|
+
] }),
|
|
454
|
+
t.companyLogo && /* @__PURE__ */ jsx(
|
|
455
|
+
"img",
|
|
456
|
+
{
|
|
457
|
+
src: t.companyLogo,
|
|
458
|
+
alt: t.company || "",
|
|
459
|
+
className: "h-5 object-contain opacity-60"
|
|
460
|
+
}
|
|
461
|
+
)
|
|
462
|
+
] })
|
|
463
|
+
]
|
|
464
|
+
}
|
|
465
|
+
);
|
|
466
|
+
}
|
|
467
|
+
function MasonryLayout({ testimonials }) {
|
|
468
|
+
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)) });
|
|
469
|
+
}
|
|
470
|
+
function FeaturedGridLayout({
|
|
471
|
+
testimonials
|
|
472
|
+
}) {
|
|
473
|
+
const featured = testimonials.find((t) => t.featured) || testimonials[0];
|
|
474
|
+
const rest = testimonials.filter((t) => t !== featured);
|
|
475
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid gap-6 lg:grid-cols-2", children: [
|
|
476
|
+
featured && /* @__PURE__ */ jsx(
|
|
477
|
+
TestimonialCard,
|
|
478
|
+
{
|
|
479
|
+
t: featured,
|
|
480
|
+
className: "flex flex-col justify-between p-8 lg:row-span-2"
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
rest.map((t, i) => /* @__PURE__ */ jsx(TestimonialCard, { t }, i))
|
|
484
|
+
] });
|
|
485
|
+
}
|
|
486
|
+
function CarouselLayout({ testimonials }) {
|
|
487
|
+
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(
|
|
488
|
+
TestimonialCard,
|
|
489
|
+
{
|
|
490
|
+
t,
|
|
491
|
+
className: "w-80 flex-none snap-center"
|
|
492
|
+
},
|
|
493
|
+
i
|
|
494
|
+
)) });
|
|
495
|
+
}
|
|
496
|
+
function WallOfLoveLayout({ testimonials }) {
|
|
497
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative max-h-[600px] overflow-hidden", children: [
|
|
498
|
+
/* @__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)) }),
|
|
499
|
+
/* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-x-0 bottom-0 h-32 bg-gradient-to-t from-background to-transparent" })
|
|
265
500
|
] });
|
|
266
501
|
}
|
|
267
502
|
function BrutalTestimonials({
|
|
268
503
|
badge,
|
|
269
504
|
headline,
|
|
270
505
|
testimonials,
|
|
271
|
-
|
|
506
|
+
variant = "masonry",
|
|
507
|
+
color = "brand-muted",
|
|
508
|
+
pattern,
|
|
272
509
|
className
|
|
273
510
|
}) {
|
|
274
|
-
return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
|
|
511
|
+
return /* @__PURE__ */ jsxs(BrutalSection, { color, pattern, className, children: [
|
|
275
512
|
(headline || badge) && /* @__PURE__ */ jsxs("div", { className: "mb-12 text-center", children: [
|
|
276
513
|
badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 opacity-70", children: badge }),
|
|
277
514
|
headline && /* @__PURE__ */ jsx("h2", { className: "brutal-h2", children: headline })
|
|
278
515
|
] }),
|
|
279
|
-
/* @__PURE__ */ jsx(
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
"mb-6 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"
|
|
284
|
-
),
|
|
285
|
-
children: [
|
|
286
|
-
/* @__PURE__ */ jsx("p", { className: "mb-4 text-sm leading-relaxed", children: t.text }),
|
|
287
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
288
|
-
t.avatar ? /* @__PURE__ */ jsx(
|
|
289
|
-
"img",
|
|
290
|
-
{
|
|
291
|
-
src: t.avatar,
|
|
292
|
-
alt: t.name,
|
|
293
|
-
className: "size-9 border-brutal border-foreground object-cover"
|
|
294
|
-
}
|
|
295
|
-
) : /* @__PURE__ */ jsx("div", { className: "flex size-9 items-center justify-center border-brutal border-foreground bg-brand font-bold text-brand-foreground", children: t.name[0] }),
|
|
296
|
-
/* @__PURE__ */ jsxs("div", { children: [
|
|
297
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm font-bold", children: t.name }),
|
|
298
|
-
t.handle && /* @__PURE__ */ jsx("p", { className: "font-mono text-xs text-muted-foreground", children: t.handle })
|
|
299
|
-
] })
|
|
300
|
-
] })
|
|
301
|
-
]
|
|
302
|
-
},
|
|
303
|
-
i
|
|
304
|
-
)) })
|
|
516
|
+
variant === "masonry" && /* @__PURE__ */ jsx(MasonryLayout, { testimonials }),
|
|
517
|
+
variant === "featured-grid" && /* @__PURE__ */ jsx(FeaturedGridLayout, { testimonials }),
|
|
518
|
+
variant === "carousel" && /* @__PURE__ */ jsx(CarouselLayout, { testimonials }),
|
|
519
|
+
variant === "wall-of-love" && /* @__PURE__ */ jsx(WallOfLoveLayout, { testimonials })
|
|
305
520
|
] });
|
|
306
521
|
}
|
|
307
522
|
function BrutalIntegrationGrid({
|
|
@@ -342,63 +557,259 @@ function BrutalIntegrationGrid({
|
|
|
342
557
|
}) })
|
|
343
558
|
] });
|
|
344
559
|
}
|
|
345
|
-
function
|
|
346
|
-
headline,
|
|
347
|
-
description,
|
|
560
|
+
function CTAButtons({
|
|
348
561
|
ctaText,
|
|
349
562
|
ctaHref = "#",
|
|
350
563
|
ctaVariant = "cta",
|
|
351
564
|
secondaryText,
|
|
352
|
-
secondaryHref
|
|
353
|
-
color = "black",
|
|
354
|
-
className
|
|
565
|
+
secondaryHref
|
|
355
566
|
}) {
|
|
356
|
-
return /* @__PURE__ */
|
|
357
|
-
/* @__PURE__ */ jsx(
|
|
358
|
-
|
|
359
|
-
|
|
567
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:flex-wrap sm:items-center sm:justify-center", children: [
|
|
568
|
+
/* @__PURE__ */ jsx(
|
|
569
|
+
Button,
|
|
570
|
+
{
|
|
571
|
+
variant: ctaVariant,
|
|
572
|
+
size: "xl",
|
|
573
|
+
className: "w-full sm:w-auto",
|
|
574
|
+
render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
|
|
575
|
+
children: ctaText
|
|
576
|
+
}
|
|
577
|
+
),
|
|
578
|
+
secondaryText && /* @__PURE__ */ jsx(
|
|
579
|
+
Button,
|
|
580
|
+
{
|
|
581
|
+
variant: "outline",
|
|
582
|
+
size: "xl",
|
|
583
|
+
className: "w-full sm:w-auto",
|
|
584
|
+
render: /* @__PURE__ */ jsx("a", { href: secondaryHref || "#" }),
|
|
585
|
+
children: secondaryText
|
|
586
|
+
}
|
|
587
|
+
)
|
|
588
|
+
] });
|
|
589
|
+
}
|
|
590
|
+
function CenteredCTA(props) {
|
|
591
|
+
return /* @__PURE__ */ jsxs("div", { className: "mx-auto max-w-2xl text-center", children: [
|
|
592
|
+
/* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
|
|
593
|
+
props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
|
|
594
|
+
props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
|
|
595
|
+
/* @__PURE__ */ jsx(
|
|
596
|
+
CTAButtons,
|
|
597
|
+
{
|
|
598
|
+
ctaText: props.ctaText,
|
|
599
|
+
ctaHref: props.ctaHref,
|
|
600
|
+
ctaVariant: props.ctaVariant,
|
|
601
|
+
secondaryText: props.secondaryText,
|
|
602
|
+
secondaryHref: props.secondaryHref
|
|
603
|
+
}
|
|
604
|
+
)
|
|
605
|
+
] });
|
|
606
|
+
}
|
|
607
|
+
function SplitCTA(props) {
|
|
608
|
+
return /* @__PURE__ */ jsxs("div", { className: "grid items-center gap-12 lg:grid-cols-2", children: [
|
|
609
|
+
/* @__PURE__ */ jsxs("div", { children: [
|
|
610
|
+
/* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
|
|
611
|
+
props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
|
|
612
|
+
props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
|
|
613
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 sm:flex-row sm:flex-wrap", children: [
|
|
614
|
+
/* @__PURE__ */ jsx(
|
|
615
|
+
Button,
|
|
616
|
+
{
|
|
617
|
+
variant: props.ctaVariant || "cta",
|
|
618
|
+
size: "xl",
|
|
619
|
+
className: "w-full sm:w-auto",
|
|
620
|
+
render: /* @__PURE__ */ jsx("a", { href: props.ctaHref || "#" }),
|
|
621
|
+
children: props.ctaText
|
|
622
|
+
}
|
|
623
|
+
),
|
|
624
|
+
props.secondaryText && /* @__PURE__ */ jsx(
|
|
625
|
+
Button,
|
|
626
|
+
{
|
|
627
|
+
variant: "outline",
|
|
628
|
+
size: "xl",
|
|
629
|
+
className: "w-full sm:w-auto",
|
|
630
|
+
render: /* @__PURE__ */ jsx("a", { href: props.secondaryHref || "#" }),
|
|
631
|
+
children: props.secondaryText
|
|
632
|
+
}
|
|
633
|
+
)
|
|
634
|
+
] })
|
|
635
|
+
] }),
|
|
636
|
+
props.visual && /* @__PURE__ */ jsx("div", { children: props.visual })
|
|
637
|
+
] });
|
|
638
|
+
}
|
|
639
|
+
function WithVisualCTA(props) {
|
|
640
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
641
|
+
props.visual && /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center opacity-10", children: props.visual }),
|
|
642
|
+
/* @__PURE__ */ jsxs("div", { className: "relative mx-auto max-w-2xl text-center", children: [
|
|
643
|
+
/* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
|
|
644
|
+
props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
|
|
645
|
+
props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
|
|
360
646
|
/* @__PURE__ */ jsx(
|
|
361
|
-
|
|
647
|
+
CTAButtons,
|
|
362
648
|
{
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
),
|
|
369
|
-
secondaryText && /* @__PURE__ */ jsx(
|
|
370
|
-
Button,
|
|
371
|
-
{
|
|
372
|
-
variant: "outline",
|
|
373
|
-
size: "lg",
|
|
374
|
-
render: /* @__PURE__ */ jsx("a", { href: secondaryHref || "#" }),
|
|
375
|
-
children: secondaryText
|
|
649
|
+
ctaText: props.ctaText,
|
|
650
|
+
ctaHref: props.ctaHref,
|
|
651
|
+
ctaVariant: props.ctaVariant,
|
|
652
|
+
secondaryText: props.secondaryText,
|
|
653
|
+
secondaryHref: props.secondaryHref
|
|
376
654
|
}
|
|
377
655
|
)
|
|
378
656
|
] })
|
|
657
|
+
] });
|
|
658
|
+
}
|
|
659
|
+
function FloatingCardCTA(props) {
|
|
660
|
+
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: [
|
|
661
|
+
/* @__PURE__ */ jsx("h2", { className: "brutal-h1 mb-6", children: props.headline }),
|
|
662
|
+
props.description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-4 opacity-80", children: props.description }),
|
|
663
|
+
props.stats && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-8 opacity-60", children: props.stats }),
|
|
664
|
+
/* @__PURE__ */ jsx(
|
|
665
|
+
CTAButtons,
|
|
666
|
+
{
|
|
667
|
+
ctaText: props.ctaText,
|
|
668
|
+
ctaHref: props.ctaHref,
|
|
669
|
+
ctaVariant: props.ctaVariant,
|
|
670
|
+
secondaryText: props.secondaryText,
|
|
671
|
+
secondaryHref: props.secondaryHref
|
|
672
|
+
}
|
|
673
|
+
)
|
|
379
674
|
] }) });
|
|
380
675
|
}
|
|
676
|
+
function BrutalCTA({
|
|
677
|
+
variant = "centered",
|
|
678
|
+
color = "black",
|
|
679
|
+
className,
|
|
680
|
+
pattern,
|
|
681
|
+
...props
|
|
682
|
+
}) {
|
|
683
|
+
if (variant === "floating-card") {
|
|
684
|
+
return /* @__PURE__ */ jsx("div", { className: cn("brutal-container px-6", className), children: /* @__PURE__ */ jsx(FloatingCardCTA, { ...props, variant, color }) });
|
|
685
|
+
}
|
|
686
|
+
return /* @__PURE__ */ jsxs(BrutalSection, { color, pattern, className, children: [
|
|
687
|
+
variant === "centered" && /* @__PURE__ */ jsx(CenteredCTA, { ...props, variant, color }),
|
|
688
|
+
variant === "split" && /* @__PURE__ */ jsx(SplitCTA, { ...props, variant, color }),
|
|
689
|
+
variant === "with-visual" && /* @__PURE__ */ jsx(WithVisualCTA, { ...props, variant, color })
|
|
690
|
+
] });
|
|
691
|
+
}
|
|
692
|
+
function Sheet({ ...props }) {
|
|
693
|
+
return /* @__PURE__ */ jsx(Dialog.Root, { "data-slot": "sheet", ...props });
|
|
694
|
+
}
|
|
695
|
+
function SheetTrigger({ ...props }) {
|
|
696
|
+
return /* @__PURE__ */ jsx(Dialog.Trigger, { "data-slot": "sheet-trigger", ...props });
|
|
697
|
+
}
|
|
698
|
+
function SheetPortal({ ...props }) {
|
|
699
|
+
return /* @__PURE__ */ jsx(Dialog.Portal, { "data-slot": "sheet-portal", ...props });
|
|
700
|
+
}
|
|
701
|
+
function SheetOverlay({ className, ...props }) {
|
|
702
|
+
return /* @__PURE__ */ jsx(
|
|
703
|
+
Dialog.Backdrop,
|
|
704
|
+
{
|
|
705
|
+
"data-slot": "sheet-overlay",
|
|
706
|
+
className: cn(
|
|
707
|
+
"fixed inset-0 z-50 bg-black/60 transition-opacity duration-150 data-ending-style:opacity-0 data-starting-style:opacity-0",
|
|
708
|
+
className
|
|
709
|
+
),
|
|
710
|
+
...props
|
|
711
|
+
}
|
|
712
|
+
);
|
|
713
|
+
}
|
|
714
|
+
function SheetContent({
|
|
715
|
+
className,
|
|
716
|
+
children,
|
|
717
|
+
side = "right",
|
|
718
|
+
showCloseButton = true,
|
|
719
|
+
...props
|
|
720
|
+
}) {
|
|
721
|
+
return /* @__PURE__ */ jsxs(SheetPortal, { children: [
|
|
722
|
+
/* @__PURE__ */ jsx(SheetOverlay, {}),
|
|
723
|
+
/* @__PURE__ */ jsxs(
|
|
724
|
+
Dialog.Popup,
|
|
725
|
+
{
|
|
726
|
+
"data-slot": "sheet-content",
|
|
727
|
+
"data-side": side,
|
|
728
|
+
className: cn(
|
|
729
|
+
"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",
|
|
730
|
+
className
|
|
731
|
+
),
|
|
732
|
+
...props,
|
|
733
|
+
children: [
|
|
734
|
+
children,
|
|
735
|
+
showCloseButton && /* @__PURE__ */ jsxs(
|
|
736
|
+
Dialog.Close,
|
|
737
|
+
{
|
|
738
|
+
"data-slot": "sheet-close",
|
|
739
|
+
render: /* @__PURE__ */ jsx(
|
|
740
|
+
Button,
|
|
741
|
+
{
|
|
742
|
+
variant: "ghost",
|
|
743
|
+
className: "absolute top-3 right-3",
|
|
744
|
+
size: "icon-sm"
|
|
745
|
+
}
|
|
746
|
+
),
|
|
747
|
+
children: [
|
|
748
|
+
/* @__PURE__ */ jsx(
|
|
749
|
+
XIcon,
|
|
750
|
+
{}
|
|
751
|
+
),
|
|
752
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
753
|
+
]
|
|
754
|
+
}
|
|
755
|
+
)
|
|
756
|
+
]
|
|
757
|
+
}
|
|
758
|
+
)
|
|
759
|
+
] });
|
|
760
|
+
}
|
|
761
|
+
function SheetTitle({ className, ...props }) {
|
|
762
|
+
return /* @__PURE__ */ jsx(
|
|
763
|
+
Dialog.Title,
|
|
764
|
+
{
|
|
765
|
+
"data-slot": "sheet-title",
|
|
766
|
+
className: cn("text-base font-bold text-foreground", className),
|
|
767
|
+
...props
|
|
768
|
+
}
|
|
769
|
+
);
|
|
770
|
+
}
|
|
381
771
|
function BrutalNav({
|
|
382
772
|
logo,
|
|
383
773
|
links,
|
|
384
774
|
ctaText = "Sign In",
|
|
385
775
|
ctaHref = "/admin",
|
|
776
|
+
variant = "solid",
|
|
386
777
|
className
|
|
387
778
|
}) {
|
|
388
|
-
|
|
389
|
-
|
|
779
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
780
|
+
const [isScrolled, setIsScrolled] = useState(false);
|
|
781
|
+
useEffect(() => {
|
|
782
|
+
if (variant !== "transparent") return;
|
|
783
|
+
const onScroll = () => setIsScrolled(window.scrollY > 20);
|
|
784
|
+
onScroll();
|
|
785
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
786
|
+
return () => window.removeEventListener("scroll", onScroll);
|
|
787
|
+
}, [variant]);
|
|
788
|
+
const variantStyles = {
|
|
789
|
+
solid: "sticky top-0 z-50 w-full border-b-brutal border-foreground bg-brand",
|
|
790
|
+
transparent: cn(
|
|
791
|
+
"fixed top-0 left-0 right-0 z-50 w-full transition-all duration-200",
|
|
792
|
+
isScrolled ? "bg-background/80 text-foreground backdrop-blur-md border-b border-foreground/10" : "bg-transparent text-white"
|
|
793
|
+
),
|
|
794
|
+
"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"
|
|
795
|
+
};
|
|
796
|
+
return /* @__PURE__ */ jsx("header", { className: cn(variantStyles[variant], className), children: /* @__PURE__ */ jsxs(
|
|
797
|
+
"div",
|
|
390
798
|
{
|
|
391
799
|
className: cn(
|
|
392
|
-
"
|
|
393
|
-
|
|
800
|
+
"flex h-14 items-center justify-between px-6",
|
|
801
|
+
variant === "floating-pill" ? "mx-auto max-w-7xl" : "brutal-container"
|
|
394
802
|
),
|
|
395
|
-
children:
|
|
803
|
+
children: [
|
|
396
804
|
/* @__PURE__ */ jsx("a", { href: "/", className: "flex items-center gap-2 text-lg font-black", children: logo }),
|
|
397
805
|
/* @__PURE__ */ jsx("nav", { className: "hidden items-center gap-1 md:flex", children: links.map((link) => /* @__PURE__ */ jsxs(
|
|
398
806
|
"a",
|
|
399
807
|
{
|
|
400
808
|
href: link.href,
|
|
401
|
-
className:
|
|
809
|
+
className: cn(
|
|
810
|
+
"relative rounded-md px-3 py-1.5 text-sm font-bold transition-colors hover:opacity-70",
|
|
811
|
+
link.active && "bg-foreground/10"
|
|
812
|
+
),
|
|
402
813
|
children: [
|
|
403
814
|
link.label,
|
|
404
815
|
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 })
|
|
@@ -406,44 +817,202 @@ function BrutalNav({
|
|
|
406
817
|
},
|
|
407
818
|
link.href
|
|
408
819
|
)) }),
|
|
409
|
-
/* @__PURE__ */
|
|
410
|
-
|
|
820
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
821
|
+
/* @__PURE__ */ jsx(
|
|
822
|
+
Button,
|
|
823
|
+
{
|
|
824
|
+
variant: "nav",
|
|
825
|
+
size: "sm",
|
|
826
|
+
render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
|
|
827
|
+
className: "hidden md:inline-flex",
|
|
828
|
+
children: ctaText
|
|
829
|
+
}
|
|
830
|
+
),
|
|
831
|
+
/* @__PURE__ */ jsxs(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: [
|
|
832
|
+
/* @__PURE__ */ jsxs(
|
|
833
|
+
SheetTrigger,
|
|
834
|
+
{
|
|
835
|
+
render: /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "icon-sm", className: "md:hidden" }),
|
|
836
|
+
children: [
|
|
837
|
+
/* @__PURE__ */ jsx(Menu, { className: "size-5" }),
|
|
838
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Menu" })
|
|
839
|
+
]
|
|
840
|
+
}
|
|
841
|
+
),
|
|
842
|
+
/* @__PURE__ */ jsxs(SheetContent, { side: "right", showCloseButton: true, children: [
|
|
843
|
+
/* @__PURE__ */ jsx(SheetTitle, { children: "Navigation" }),
|
|
844
|
+
/* @__PURE__ */ jsxs("nav", { className: "flex flex-col gap-1 px-2 pt-4", children: [
|
|
845
|
+
links.map((link) => /* @__PURE__ */ jsxs(
|
|
846
|
+
"a",
|
|
847
|
+
{
|
|
848
|
+
href: link.href,
|
|
849
|
+
onClick: () => setMobileOpen(false),
|
|
850
|
+
className: cn(
|
|
851
|
+
"flex items-center gap-2 rounded-md px-3 py-2.5 text-sm font-bold transition-colors hover:bg-foreground/5",
|
|
852
|
+
link.active && "bg-foreground/10"
|
|
853
|
+
),
|
|
854
|
+
children: [
|
|
855
|
+
link.label,
|
|
856
|
+
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 })
|
|
857
|
+
]
|
|
858
|
+
},
|
|
859
|
+
link.href
|
|
860
|
+
)),
|
|
861
|
+
/* @__PURE__ */ jsx("div", { className: "mt-4 border-t border-foreground/10 pt-4", children: /* @__PURE__ */ jsx(
|
|
862
|
+
Button,
|
|
863
|
+
{
|
|
864
|
+
variant: "default",
|
|
865
|
+
size: "default",
|
|
866
|
+
render: /* @__PURE__ */ jsx("a", { href: ctaHref }),
|
|
867
|
+
className: "w-full",
|
|
868
|
+
children: ctaText
|
|
869
|
+
}
|
|
870
|
+
) })
|
|
871
|
+
] })
|
|
872
|
+
] })
|
|
873
|
+
] })
|
|
874
|
+
] })
|
|
875
|
+
]
|
|
876
|
+
}
|
|
877
|
+
) });
|
|
878
|
+
}
|
|
879
|
+
function Input({ className, type, ...props }) {
|
|
880
|
+
return /* @__PURE__ */ jsx(
|
|
881
|
+
Input$1,
|
|
882
|
+
{
|
|
883
|
+
type,
|
|
884
|
+
"data-slot": "input",
|
|
885
|
+
className: cn(
|
|
886
|
+
"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",
|
|
887
|
+
className
|
|
888
|
+
),
|
|
889
|
+
...props
|
|
411
890
|
}
|
|
412
891
|
);
|
|
413
892
|
}
|
|
893
|
+
function SocialsRow({
|
|
894
|
+
socials
|
|
895
|
+
}) {
|
|
896
|
+
const items = [
|
|
897
|
+
{ key: "twitter", label: "Twitter", url: socials.twitter },
|
|
898
|
+
{ key: "github", label: "GitHub", url: socials.github },
|
|
899
|
+
{ key: "linkedin", label: "LinkedIn", url: socials.linkedin },
|
|
900
|
+
{ key: "discord", label: "Discord", url: socials.discord }
|
|
901
|
+
].filter((s) => s.url);
|
|
902
|
+
if (items.length === 0) return null;
|
|
903
|
+
return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-4", children: items.map((s) => /* @__PURE__ */ jsx(
|
|
904
|
+
"a",
|
|
905
|
+
{
|
|
906
|
+
href: s.url,
|
|
907
|
+
target: "_blank",
|
|
908
|
+
rel: "noopener noreferrer",
|
|
909
|
+
className: "text-sm font-bold transition-colors hover:text-muted-foreground",
|
|
910
|
+
children: s.label
|
|
911
|
+
},
|
|
912
|
+
s.key
|
|
913
|
+
)) });
|
|
914
|
+
}
|
|
915
|
+
function NewsletterSection({
|
|
916
|
+
newsletter
|
|
917
|
+
}) {
|
|
918
|
+
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: [
|
|
919
|
+
/* @__PURE__ */ jsx("h3", { className: "brutal-h4 mb-2", children: newsletter.headline || "Stay in the loop" }),
|
|
920
|
+
newsletter.description && /* @__PURE__ */ jsx("p", { className: "brutal-caption mb-4", children: newsletter.description }),
|
|
921
|
+
/* @__PURE__ */ jsxs(
|
|
922
|
+
"form",
|
|
923
|
+
{
|
|
924
|
+
onSubmit: (e) => e.preventDefault(),
|
|
925
|
+
className: "flex gap-2",
|
|
926
|
+
children: [
|
|
927
|
+
/* @__PURE__ */ jsx(
|
|
928
|
+
Input,
|
|
929
|
+
{
|
|
930
|
+
type: "email",
|
|
931
|
+
placeholder: newsletter.placeholder || "you@email.com",
|
|
932
|
+
className: "flex-1"
|
|
933
|
+
}
|
|
934
|
+
),
|
|
935
|
+
/* @__PURE__ */ jsx(Button, { variant: "default", size: "default", type: "submit", children: newsletter.buttonText || "Subscribe" })
|
|
936
|
+
]
|
|
937
|
+
}
|
|
938
|
+
)
|
|
939
|
+
] }) });
|
|
940
|
+
}
|
|
941
|
+
function MegaContent({
|
|
942
|
+
logo,
|
|
943
|
+
tagline,
|
|
944
|
+
columns,
|
|
945
|
+
socials
|
|
946
|
+
}) {
|
|
947
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-10 flex flex-col gap-8 sm:flex-row sm:items-start sm:justify-between", children: [
|
|
948
|
+
/* @__PURE__ */ jsxs("div", { className: "max-w-xs", children: [
|
|
949
|
+
/* @__PURE__ */ jsx("div", { className: "mb-2 text-xl font-black", children: logo }),
|
|
950
|
+
tagline && /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: tagline }),
|
|
951
|
+
socials && /* @__PURE__ */ jsx(SocialsRow, { socials })
|
|
952
|
+
] }),
|
|
953
|
+
/* @__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: [
|
|
954
|
+
/* @__PURE__ */ jsx("h3", { className: "brutal-label mb-3 text-muted-foreground", children: col.title }),
|
|
955
|
+
/* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-2", children: col.links.map((link) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
|
|
956
|
+
"a",
|
|
957
|
+
{
|
|
958
|
+
href: link.href,
|
|
959
|
+
className: "text-sm font-medium transition-colors hover:text-muted-foreground",
|
|
960
|
+
children: link.label
|
|
961
|
+
}
|
|
962
|
+
) }, link.href)) })
|
|
963
|
+
] }, col.title)) })
|
|
964
|
+
] });
|
|
965
|
+
}
|
|
966
|
+
function MinimalContent({
|
|
967
|
+
logo,
|
|
968
|
+
columns,
|
|
969
|
+
socials
|
|
970
|
+
}) {
|
|
971
|
+
const allLinks = columns.flatMap((col) => col.links);
|
|
972
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-6 flex flex-col items-center gap-4 sm:flex-row sm:justify-between", children: [
|
|
973
|
+
/* @__PURE__ */ jsx("div", { className: "text-xl font-black", children: logo }),
|
|
974
|
+
/* @__PURE__ */ jsx("nav", { className: "flex flex-wrap items-center justify-center gap-x-6 gap-y-2", children: allLinks.map((link) => /* @__PURE__ */ jsx(
|
|
975
|
+
"a",
|
|
976
|
+
{
|
|
977
|
+
href: link.href,
|
|
978
|
+
className: "text-sm font-medium transition-colors hover:text-muted-foreground",
|
|
979
|
+
children: link.label
|
|
980
|
+
},
|
|
981
|
+
link.href
|
|
982
|
+
)) }),
|
|
983
|
+
socials && /* @__PURE__ */ jsx(SocialsRow, { socials })
|
|
984
|
+
] });
|
|
985
|
+
}
|
|
414
986
|
function BrutalFooter({
|
|
415
987
|
logo,
|
|
416
988
|
tagline,
|
|
417
989
|
columns,
|
|
418
990
|
bottomLeft,
|
|
419
991
|
bottomRight,
|
|
992
|
+
variant = "mega",
|
|
993
|
+
socials,
|
|
994
|
+
newsletter,
|
|
420
995
|
className
|
|
421
996
|
}) {
|
|
422
997
|
return /* @__PURE__ */ jsx(
|
|
423
998
|
"footer",
|
|
424
999
|
{
|
|
425
1000
|
className: cn(
|
|
426
|
-
"w-full border-t-
|
|
1001
|
+
"w-full border-t-4 bg-background px-6 py-12 text-foreground",
|
|
427
1002
|
className
|
|
428
1003
|
),
|
|
1004
|
+
style: { borderTopColor: "hsl(var(--brand))" },
|
|
429
1005
|
children: /* @__PURE__ */ jsxs("div", { className: "brutal-container", children: [
|
|
430
|
-
/* @__PURE__ */
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
href: link.href,
|
|
441
|
-
className: "text-sm font-medium transition-colors hover:text-muted-foreground",
|
|
442
|
-
children: link.label
|
|
443
|
-
}
|
|
444
|
-
) }, link.href)) })
|
|
445
|
-
] }, col.title)) })
|
|
446
|
-
] }),
|
|
1006
|
+
variant === "newsletter" && newsletter && /* @__PURE__ */ jsx(NewsletterSection, { newsletter }),
|
|
1007
|
+
variant === "minimal" ? /* @__PURE__ */ jsx(MinimalContent, { logo, columns, socials }) : /* @__PURE__ */ jsx(
|
|
1008
|
+
MegaContent,
|
|
1009
|
+
{
|
|
1010
|
+
logo,
|
|
1011
|
+
tagline,
|
|
1012
|
+
columns,
|
|
1013
|
+
socials
|
|
1014
|
+
}
|
|
1015
|
+
),
|
|
447
1016
|
/* @__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: [
|
|
448
1017
|
/* @__PURE__ */ jsx("span", { children: bottomLeft || "Built with care" }),
|
|
449
1018
|
/* @__PURE__ */ jsx("span", { children: bottomRight || (/* @__PURE__ */ new Date()).getFullYear() })
|
|
@@ -452,7 +1021,345 @@ function BrutalFooter({
|
|
|
452
1021
|
}
|
|
453
1022
|
);
|
|
454
1023
|
}
|
|
1024
|
+
var badgeVariants = cva(
|
|
1025
|
+
"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!",
|
|
1026
|
+
{
|
|
1027
|
+
variants: {
|
|
1028
|
+
variant: {
|
|
1029
|
+
default: "border-brutal border-foreground bg-primary px-3 py-1 text-xs text-primary-foreground shadow-brutal-sm",
|
|
1030
|
+
secondary: "border-brutal border-foreground bg-secondary px-3 py-1 text-xs text-secondary-foreground shadow-brutal-sm",
|
|
1031
|
+
brand: "border-brutal border-foreground bg-brand px-3 py-1 text-xs text-brand-foreground shadow-brutal-sm",
|
|
1032
|
+
cta: "border-brutal border-foreground bg-cta px-3 py-1 text-xs text-cta-foreground shadow-brutal-sm",
|
|
1033
|
+
outline: "border-brutal border-foreground bg-background px-3 py-1 text-xs text-foreground",
|
|
1034
|
+
destructive: "border-brutal border-destructive bg-destructive/10 px-3 py-1 text-xs text-destructive",
|
|
1035
|
+
ghost: "px-2 py-0.5 text-xs text-muted-foreground"
|
|
1036
|
+
}
|
|
1037
|
+
},
|
|
1038
|
+
defaultVariants: {
|
|
1039
|
+
variant: "default"
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
);
|
|
1043
|
+
function Badge({
|
|
1044
|
+
className,
|
|
1045
|
+
variant = "default",
|
|
1046
|
+
render,
|
|
1047
|
+
...props
|
|
1048
|
+
}) {
|
|
1049
|
+
return useRender({
|
|
1050
|
+
defaultTagName: "span",
|
|
1051
|
+
props: mergeProps(
|
|
1052
|
+
{
|
|
1053
|
+
className: cn(badgeVariants({ variant }), className)
|
|
1054
|
+
},
|
|
1055
|
+
props
|
|
1056
|
+
),
|
|
1057
|
+
render,
|
|
1058
|
+
state: {
|
|
1059
|
+
slot: "badge",
|
|
1060
|
+
variant
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
1063
|
+
}
|
|
1064
|
+
function PricingTable({
|
|
1065
|
+
badge,
|
|
1066
|
+
headline,
|
|
1067
|
+
description,
|
|
1068
|
+
tiers,
|
|
1069
|
+
popularIndex,
|
|
1070
|
+
billingToggle = true,
|
|
1071
|
+
color = "white",
|
|
1072
|
+
className
|
|
1073
|
+
}) {
|
|
1074
|
+
const [annual, setAnnual] = useState(false);
|
|
1075
|
+
return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
|
|
1076
|
+
(headline || badge) && /* @__PURE__ */ jsxs("div", { className: "mb-8 text-center", children: [
|
|
1077
|
+
badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-muted-foreground", children: badge }),
|
|
1078
|
+
headline && /* @__PURE__ */ jsx("h2", { className: "brutal-h2 mb-4", children: headline }),
|
|
1079
|
+
description && /* @__PURE__ */ jsx("p", { className: "brutal-body mx-auto max-w-lg text-muted-foreground", children: description })
|
|
1080
|
+
] }),
|
|
1081
|
+
billingToggle && /* @__PURE__ */ jsxs("div", { className: "mb-10 flex items-center justify-center gap-3", children: [
|
|
1082
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-sm font-bold", !annual && "text-brand"), children: "Monthly" }),
|
|
1083
|
+
/* @__PURE__ */ jsx(
|
|
1084
|
+
"button",
|
|
1085
|
+
{
|
|
1086
|
+
onClick: () => setAnnual(!annual),
|
|
1087
|
+
className: cn(
|
|
1088
|
+
"relative h-8 w-14 border-brutal border-foreground transition-colors",
|
|
1089
|
+
annual ? "bg-brand" : "bg-secondary"
|
|
1090
|
+
),
|
|
1091
|
+
children: /* @__PURE__ */ jsx(
|
|
1092
|
+
"span",
|
|
1093
|
+
{
|
|
1094
|
+
className: cn(
|
|
1095
|
+
"absolute top-1 size-6 border border-foreground bg-background transition-transform",
|
|
1096
|
+
annual ? "left-7" : "left-1"
|
|
1097
|
+
)
|
|
1098
|
+
}
|
|
1099
|
+
)
|
|
1100
|
+
}
|
|
1101
|
+
),
|
|
1102
|
+
/* @__PURE__ */ jsx("span", { className: cn("text-sm font-bold", annual && "text-brand"), children: "Annual" }),
|
|
1103
|
+
annual && /* @__PURE__ */ jsx(Badge, { variant: "cta", children: "Save 20%" })
|
|
1104
|
+
] }),
|
|
1105
|
+
/* @__PURE__ */ jsx("div", { className: cn(
|
|
1106
|
+
"grid gap-6",
|
|
1107
|
+
tiers.length === 2 && "mx-auto max-w-2xl sm:grid-cols-2",
|
|
1108
|
+
tiers.length === 3 && "lg:grid-cols-3",
|
|
1109
|
+
tiers.length >= 4 && "sm:grid-cols-2 lg:grid-cols-4"
|
|
1110
|
+
), children: tiers.map((tier, i) => {
|
|
1111
|
+
const isPopular = i === popularIndex;
|
|
1112
|
+
const price = annual ? tier.price.annual : tier.price.monthly;
|
|
1113
|
+
return /* @__PURE__ */ jsxs(
|
|
1114
|
+
"div",
|
|
1115
|
+
{
|
|
1116
|
+
className: cn(
|
|
1117
|
+
"relative flex flex-col border-brutal border-foreground bg-background p-6 shadow-brutal",
|
|
1118
|
+
isPopular && "border-brand shadow-brutal-lg ring-2 ring-brand z-10 scale-105"
|
|
1119
|
+
),
|
|
1120
|
+
children: [
|
|
1121
|
+
isPopular && /* @__PURE__ */ jsx(Badge, { variant: "brand", className: "absolute -top-3 left-1/2 -translate-x-1/2", children: "Popular" }),
|
|
1122
|
+
/* @__PURE__ */ jsx("h3", { className: "brutal-h4 mb-1", children: tier.name }),
|
|
1123
|
+
tier.description && /* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: tier.description }),
|
|
1124
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-6", children: [
|
|
1125
|
+
/* @__PURE__ */ jsx("span", { className: "brutal-h1", children: typeof price === "number" ? `$${price}` : price }),
|
|
1126
|
+
typeof price === "number" && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: "/mo" })
|
|
1127
|
+
] }),
|
|
1128
|
+
/* @__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: [
|
|
1129
|
+
/* @__PURE__ */ jsx("span", { className: "mt-0.5 text-brand", children: "\u2713" }),
|
|
1130
|
+
feature
|
|
1131
|
+
] }, feature)) }),
|
|
1132
|
+
/* @__PURE__ */ jsx(
|
|
1133
|
+
Button,
|
|
1134
|
+
{
|
|
1135
|
+
variant: tier.ctaVariant || (isPopular ? "cta" : "outline"),
|
|
1136
|
+
size: "lg",
|
|
1137
|
+
className: "w-full",
|
|
1138
|
+
render: tier.ctaHref ? /* @__PURE__ */ jsx("a", { href: tier.ctaHref }) : void 0,
|
|
1139
|
+
children: tier.ctaText
|
|
1140
|
+
}
|
|
1141
|
+
)
|
|
1142
|
+
]
|
|
1143
|
+
},
|
|
1144
|
+
tier.name
|
|
1145
|
+
);
|
|
1146
|
+
}) })
|
|
1147
|
+
] });
|
|
1148
|
+
}
|
|
1149
|
+
function LogoCloud({
|
|
1150
|
+
title,
|
|
1151
|
+
logos,
|
|
1152
|
+
marquee = false,
|
|
1153
|
+
color = "white",
|
|
1154
|
+
className
|
|
1155
|
+
}) {
|
|
1156
|
+
const logoElements = logos.map((logo) => {
|
|
1157
|
+
const img = /* @__PURE__ */ jsx(
|
|
1158
|
+
"img",
|
|
1159
|
+
{
|
|
1160
|
+
src: logo.src,
|
|
1161
|
+
alt: logo.alt,
|
|
1162
|
+
className: "h-8 max-w-[120px] object-contain opacity-50 grayscale transition-all duration-200 hover:opacity-100 hover:grayscale-0"
|
|
1163
|
+
},
|
|
1164
|
+
logo.alt
|
|
1165
|
+
);
|
|
1166
|
+
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);
|
|
1167
|
+
});
|
|
1168
|
+
return /* @__PURE__ */ jsxs(BrutalSection, { color, padding: "sm", className, children: [
|
|
1169
|
+
title && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-6 text-center text-muted-foreground", children: title }),
|
|
1170
|
+
marquee ? /* @__PURE__ */ jsx("div", { className: "relative overflow-hidden", children: /* @__PURE__ */ jsxs("div", { className: "flex animate-marquee", children: [
|
|
1171
|
+
logoElements,
|
|
1172
|
+
logoElements
|
|
1173
|
+
] }) }) : /* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center justify-center gap-8", children: logoElements })
|
|
1174
|
+
] });
|
|
1175
|
+
}
|
|
1176
|
+
function useCountUp(target, inView) {
|
|
1177
|
+
const [count, setCount] = useState(0);
|
|
1178
|
+
useEffect(() => {
|
|
1179
|
+
if (!inView) return;
|
|
1180
|
+
let frame;
|
|
1181
|
+
const duration = 1500;
|
|
1182
|
+
const start = performance.now();
|
|
1183
|
+
function animate(now) {
|
|
1184
|
+
const elapsed = now - start;
|
|
1185
|
+
const progress = Math.min(elapsed / duration, 1);
|
|
1186
|
+
const eased = 1 - Math.pow(1 - progress, 3);
|
|
1187
|
+
setCount(Math.round(eased * target));
|
|
1188
|
+
if (progress < 1) frame = requestAnimationFrame(animate);
|
|
1189
|
+
}
|
|
1190
|
+
frame = requestAnimationFrame(animate);
|
|
1191
|
+
return () => cancelAnimationFrame(frame);
|
|
1192
|
+
}, [target, inView]);
|
|
1193
|
+
return count;
|
|
1194
|
+
}
|
|
1195
|
+
function StatItem({ stat, inView }) {
|
|
1196
|
+
const count = useCountUp(stat.value, inView);
|
|
1197
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-center", children: [
|
|
1198
|
+
/* @__PURE__ */ jsxs("p", { className: "brutal-display", children: [
|
|
1199
|
+
stat.prefix,
|
|
1200
|
+
count.toLocaleString(),
|
|
1201
|
+
stat.suffix
|
|
1202
|
+
] }),
|
|
1203
|
+
/* @__PURE__ */ jsx("p", { className: "brutal-label mt-2 text-muted-foreground", children: stat.label })
|
|
1204
|
+
] });
|
|
1205
|
+
}
|
|
1206
|
+
function StatsBar({ stats, color = "white", className }) {
|
|
1207
|
+
const ref = useRef(null);
|
|
1208
|
+
const [inView, setInView] = useState(false);
|
|
1209
|
+
useEffect(() => {
|
|
1210
|
+
if (!ref.current) return;
|
|
1211
|
+
const observer = new IntersectionObserver(
|
|
1212
|
+
([entry]) => {
|
|
1213
|
+
if (entry.isIntersecting) {
|
|
1214
|
+
setInView(true);
|
|
1215
|
+
observer.disconnect();
|
|
1216
|
+
}
|
|
1217
|
+
},
|
|
1218
|
+
{ threshold: 0.3 }
|
|
1219
|
+
);
|
|
1220
|
+
observer.observe(ref.current);
|
|
1221
|
+
return () => observer.disconnect();
|
|
1222
|
+
}, []);
|
|
1223
|
+
return /* @__PURE__ */ jsx(BrutalSection, { color, padding: "sm", className, children: /* @__PURE__ */ jsx(
|
|
1224
|
+
"div",
|
|
1225
|
+
{
|
|
1226
|
+
ref,
|
|
1227
|
+
className: cn(
|
|
1228
|
+
"grid gap-8",
|
|
1229
|
+
stats.length === 2 && "grid-cols-2",
|
|
1230
|
+
stats.length === 3 && "grid-cols-3",
|
|
1231
|
+
stats.length >= 4 && "grid-cols-2 sm:grid-cols-4"
|
|
1232
|
+
),
|
|
1233
|
+
children: stats.map((stat) => /* @__PURE__ */ jsx(StatItem, { stat, inView }, stat.label))
|
|
1234
|
+
}
|
|
1235
|
+
) });
|
|
1236
|
+
}
|
|
1237
|
+
function Accordion({ className, ...props }) {
|
|
1238
|
+
return /* @__PURE__ */ jsx(
|
|
1239
|
+
Accordion$1.Root,
|
|
1240
|
+
{
|
|
1241
|
+
"data-slot": "accordion",
|
|
1242
|
+
className: cn("flex w-full flex-col", className),
|
|
1243
|
+
...props
|
|
1244
|
+
}
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1247
|
+
function AccordionItem({ className, ...props }) {
|
|
1248
|
+
return /* @__PURE__ */ jsx(
|
|
1249
|
+
Accordion$1.Item,
|
|
1250
|
+
{
|
|
1251
|
+
"data-slot": "accordion-item",
|
|
1252
|
+
className: cn("border-brutal border-foreground rounded-lg mb-2 px-3", className),
|
|
1253
|
+
...props
|
|
1254
|
+
}
|
|
1255
|
+
);
|
|
1256
|
+
}
|
|
1257
|
+
function AccordionTrigger({
|
|
1258
|
+
className,
|
|
1259
|
+
children,
|
|
1260
|
+
...props
|
|
1261
|
+
}) {
|
|
1262
|
+
return /* @__PURE__ */ jsx(Accordion$1.Header, { className: "flex", children: /* @__PURE__ */ jsxs(
|
|
1263
|
+
Accordion$1.Trigger,
|
|
1264
|
+
{
|
|
1265
|
+
"data-slot": "accordion-trigger",
|
|
1266
|
+
className: cn(
|
|
1267
|
+
"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",
|
|
1268
|
+
className
|
|
1269
|
+
),
|
|
1270
|
+
...props,
|
|
1271
|
+
children: [
|
|
1272
|
+
children,
|
|
1273
|
+
/* @__PURE__ */ jsx(ChevronDownIcon, { "data-slot": "accordion-trigger-icon", className: "pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden" }),
|
|
1274
|
+
/* @__PURE__ */ jsx(ChevronUpIcon, { "data-slot": "accordion-trigger-icon", className: "pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline" })
|
|
1275
|
+
]
|
|
1276
|
+
}
|
|
1277
|
+
) });
|
|
1278
|
+
}
|
|
1279
|
+
function AccordionContent({
|
|
1280
|
+
className,
|
|
1281
|
+
children,
|
|
1282
|
+
...props
|
|
1283
|
+
}) {
|
|
1284
|
+
return /* @__PURE__ */ jsx(
|
|
1285
|
+
Accordion$1.Panel,
|
|
1286
|
+
{
|
|
1287
|
+
"data-slot": "accordion-content",
|
|
1288
|
+
className: "overflow-hidden text-sm data-open:animate-accordion-down data-closed:animate-accordion-up",
|
|
1289
|
+
...props,
|
|
1290
|
+
children: /* @__PURE__ */ jsx(
|
|
1291
|
+
"div",
|
|
1292
|
+
{
|
|
1293
|
+
className: cn(
|
|
1294
|
+
"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",
|
|
1295
|
+
className
|
|
1296
|
+
),
|
|
1297
|
+
children
|
|
1298
|
+
}
|
|
1299
|
+
)
|
|
1300
|
+
}
|
|
1301
|
+
);
|
|
1302
|
+
}
|
|
1303
|
+
function FAQ({
|
|
1304
|
+
badge,
|
|
1305
|
+
headline,
|
|
1306
|
+
items,
|
|
1307
|
+
color = "white",
|
|
1308
|
+
className
|
|
1309
|
+
}) {
|
|
1310
|
+
return /* @__PURE__ */ jsxs(BrutalSection, { color, className, children: [
|
|
1311
|
+
(headline || badge) && /* @__PURE__ */ jsxs("div", { className: "mb-10 mx-auto max-w-2xl", children: [
|
|
1312
|
+
badge && /* @__PURE__ */ jsx("p", { className: "brutal-label mb-4 text-brand", children: badge }),
|
|
1313
|
+
headline && /* @__PURE__ */ jsx("h2", { className: "brutal-h2", children: headline })
|
|
1314
|
+
] }),
|
|
1315
|
+
/* @__PURE__ */ jsx(Accordion, { className: "mx-auto max-w-2xl", children: items.map((item, i) => /* @__PURE__ */ jsxs(
|
|
1316
|
+
AccordionItem,
|
|
1317
|
+
{
|
|
1318
|
+
value: `faq-${i}`,
|
|
1319
|
+
className: cn(
|
|
1320
|
+
"border-brutal border-foreground mb-3 px-5",
|
|
1321
|
+
i % 2 === 0 ? "bg-background" : "bg-secondary"
|
|
1322
|
+
),
|
|
1323
|
+
children: [
|
|
1324
|
+
/* @__PURE__ */ jsx(AccordionTrigger, { className: "brutal-h4 py-4 text-left", children: item.question }),
|
|
1325
|
+
/* @__PURE__ */ jsx(AccordionContent, { className: "brutal-body pb-4 text-muted-foreground", children: item.answer })
|
|
1326
|
+
]
|
|
1327
|
+
},
|
|
1328
|
+
i
|
|
1329
|
+
)) })
|
|
1330
|
+
] });
|
|
1331
|
+
}
|
|
1332
|
+
function Newsletter({
|
|
1333
|
+
headline = "Stay in the loop",
|
|
1334
|
+
description,
|
|
1335
|
+
placeholder = "you@example.com",
|
|
1336
|
+
buttonText = "Subscribe",
|
|
1337
|
+
onSubmit,
|
|
1338
|
+
color = "white",
|
|
1339
|
+
className
|
|
1340
|
+
}) {
|
|
1341
|
+
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: [
|
|
1342
|
+
/* @__PURE__ */ jsx("h3", { className: "brutal-h3 mb-2", children: headline }),
|
|
1343
|
+
description && /* @__PURE__ */ jsx("p", { className: "brutal-body mb-6 text-muted-foreground", children: description }),
|
|
1344
|
+
/* @__PURE__ */ jsxs(
|
|
1345
|
+
"form",
|
|
1346
|
+
{
|
|
1347
|
+
onSubmit: (e) => {
|
|
1348
|
+
e.preventDefault();
|
|
1349
|
+
const form = e.target;
|
|
1350
|
+
const email = new FormData(form).get("email");
|
|
1351
|
+
onSubmit?.(email);
|
|
1352
|
+
},
|
|
1353
|
+
className: "flex gap-3",
|
|
1354
|
+
children: [
|
|
1355
|
+
/* @__PURE__ */ jsx(Input, { type: "email", name: "email", placeholder, required: true, className: "flex-1" }),
|
|
1356
|
+
/* @__PURE__ */ jsx(Button, { type: "submit", variant: "cta", children: buttonText })
|
|
1357
|
+
]
|
|
1358
|
+
}
|
|
1359
|
+
)
|
|
1360
|
+
] }) });
|
|
1361
|
+
}
|
|
455
1362
|
|
|
456
|
-
export { BrutalCTA, BrutalFeatureGrid, BrutalFooter, BrutalHero, BrutalIntegrationGrid, BrutalNav, BrutalSection, BrutalTestimonials, WaveDivider };
|
|
1363
|
+
export { BrutalCTA, BrutalFeatureGrid, BrutalFooter, BrutalHero, BrutalIntegrationGrid, BrutalNav, BrutalSection, BrutalTestimonials, FAQ, LogoCloud, Newsletter, PricingTable, SectionDivider, StatsBar, SectionDivider as WaveDivider };
|
|
457
1364
|
//# sourceMappingURL=index.js.map
|
|
458
1365
|
//# sourceMappingURL=index.js.map
|