@mikenotthepope/substrateui 0.1.1 → 0.1.2
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/base/substrate.css +163 -0
- package/dist/index.d.mts +12 -2
- package/dist/index.d.ts +12 -2
- package/dist/index.js +224 -91
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +223 -91
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -3271,30 +3271,58 @@ import * as React40 from "react";
|
|
|
3271
3271
|
// components/ThemeProvider.tsx
|
|
3272
3272
|
import { createContext as createContext3, useContext as useContext3, useEffect, useState as useState2, useCallback, useMemo as useMemo2 } from "react";
|
|
3273
3273
|
import { jsx as jsx43 } from "react/jsx-runtime";
|
|
3274
|
+
var VALID_THEMES = ["light", "dark", "system"];
|
|
3275
|
+
var COLOR_THEMES = ["blue", "plum", "plum-trio"];
|
|
3274
3276
|
var ThemeContext = createContext3(void 0);
|
|
3275
3277
|
var STORAGE_KEY = "substrateui-theme";
|
|
3278
|
+
var COLOR_STORAGE_KEY = "substrateui-color-theme";
|
|
3276
3279
|
function getSystemTheme() {
|
|
3277
3280
|
if (typeof window === "undefined") return "light";
|
|
3278
3281
|
return window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light";
|
|
3279
3282
|
}
|
|
3283
|
+
function readStoredTheme(key, fallback) {
|
|
3284
|
+
if (typeof window === "undefined") return fallback;
|
|
3285
|
+
const stored = localStorage.getItem(key);
|
|
3286
|
+
return VALID_THEMES.includes(stored) ? stored : fallback;
|
|
3287
|
+
}
|
|
3288
|
+
function readStoredColorTheme(key, fallback) {
|
|
3289
|
+
if (typeof window === "undefined") return fallback;
|
|
3290
|
+
const stored = localStorage.getItem(key);
|
|
3291
|
+
return COLOR_THEMES.includes(stored != null ? stored : "") ? stored : fallback;
|
|
3292
|
+
}
|
|
3280
3293
|
function applyClass(resolved) {
|
|
3281
3294
|
document.documentElement.classList.remove("light", "dark");
|
|
3282
3295
|
document.documentElement.classList.add(resolved);
|
|
3283
3296
|
}
|
|
3297
|
+
function applyColorTheme(colorTheme) {
|
|
3298
|
+
for (const t of COLOR_THEMES) {
|
|
3299
|
+
document.documentElement.classList.remove(`theme-${t}`);
|
|
3300
|
+
}
|
|
3301
|
+
if (colorTheme !== "blue") {
|
|
3302
|
+
document.documentElement.classList.add(`theme-${colorTheme}`);
|
|
3303
|
+
}
|
|
3304
|
+
}
|
|
3284
3305
|
function ThemeProvider({
|
|
3285
3306
|
children,
|
|
3286
3307
|
defaultTheme = "system",
|
|
3287
|
-
|
|
3308
|
+
defaultColorTheme = "blue",
|
|
3309
|
+
storageKey = STORAGE_KEY,
|
|
3310
|
+
colorStorageKey = COLOR_STORAGE_KEY
|
|
3288
3311
|
}) {
|
|
3289
|
-
const [theme, setThemeState] = useState2(
|
|
3290
|
-
|
|
3291
|
-
|
|
3292
|
-
|
|
3312
|
+
const [theme, setThemeState] = useState2(
|
|
3313
|
+
() => readStoredTheme(storageKey, defaultTheme)
|
|
3314
|
+
);
|
|
3315
|
+
const [colorTheme, setColorThemeState] = useState2(
|
|
3316
|
+
() => readStoredColorTheme(colorStorageKey, defaultColorTheme)
|
|
3317
|
+
);
|
|
3293
3318
|
const [systemTheme, setSystemTheme] = useState2(getSystemTheme);
|
|
3294
3319
|
const resolvedTheme = theme === "system" ? systemTheme : theme;
|
|
3295
3320
|
useEffect(() => {
|
|
3296
3321
|
applyClass(resolvedTheme);
|
|
3297
3322
|
}, [resolvedTheme]);
|
|
3323
|
+
useEffect(() => {
|
|
3324
|
+
applyColorTheme(colorTheme);
|
|
3325
|
+
}, [colorTheme]);
|
|
3298
3326
|
useEffect(() => {
|
|
3299
3327
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
3300
3328
|
const handler = (e) => {
|
|
@@ -3303,6 +3331,23 @@ function ThemeProvider({
|
|
|
3303
3331
|
mq.addEventListener("change", handler);
|
|
3304
3332
|
return () => mq.removeEventListener("change", handler);
|
|
3305
3333
|
}, []);
|
|
3334
|
+
useEffect(() => {
|
|
3335
|
+
const handler = (e) => {
|
|
3336
|
+
var _a;
|
|
3337
|
+
if (e.key === storageKey) {
|
|
3338
|
+
setThemeState(
|
|
3339
|
+
VALID_THEMES.includes(e.newValue) ? e.newValue : defaultTheme
|
|
3340
|
+
);
|
|
3341
|
+
}
|
|
3342
|
+
if (e.key === colorStorageKey) {
|
|
3343
|
+
setColorThemeState(
|
|
3344
|
+
COLOR_THEMES.includes((_a = e.newValue) != null ? _a : "") ? e.newValue : defaultColorTheme
|
|
3345
|
+
);
|
|
3346
|
+
}
|
|
3347
|
+
};
|
|
3348
|
+
window.addEventListener("storage", handler);
|
|
3349
|
+
return () => window.removeEventListener("storage", handler);
|
|
3350
|
+
}, [storageKey, colorStorageKey, defaultTheme, defaultColorTheme]);
|
|
3306
3351
|
const setTheme = useCallback(
|
|
3307
3352
|
(newTheme) => {
|
|
3308
3353
|
localStorage.setItem(storageKey, newTheme);
|
|
@@ -3310,9 +3355,16 @@ function ThemeProvider({
|
|
|
3310
3355
|
},
|
|
3311
3356
|
[storageKey]
|
|
3312
3357
|
);
|
|
3358
|
+
const setColorTheme = useCallback(
|
|
3359
|
+
(newColorTheme) => {
|
|
3360
|
+
localStorage.setItem(colorStorageKey, newColorTheme);
|
|
3361
|
+
setColorThemeState(newColorTheme);
|
|
3362
|
+
},
|
|
3363
|
+
[colorStorageKey]
|
|
3364
|
+
);
|
|
3313
3365
|
const value = useMemo2(
|
|
3314
|
-
() => ({ theme, resolvedTheme, setTheme }),
|
|
3315
|
-
[theme, resolvedTheme, setTheme]
|
|
3366
|
+
() => ({ theme, resolvedTheme, setTheme, colorTheme, setColorTheme, colorThemes: COLOR_THEMES }),
|
|
3367
|
+
[theme, resolvedTheme, setTheme, colorTheme, setColorTheme]
|
|
3316
3368
|
);
|
|
3317
3369
|
return /* @__PURE__ */ jsx43(ThemeContext.Provider, { value, children });
|
|
3318
3370
|
}
|
|
@@ -5836,6 +5888,83 @@ function ThemeToggle(_a) {
|
|
|
5836
5888
|
);
|
|
5837
5889
|
}
|
|
5838
5890
|
|
|
5891
|
+
// components/ColorThemeToggle.tsx
|
|
5892
|
+
import { useSyncExternalStore as useSyncExternalStore2 } from "react";
|
|
5893
|
+
import { jsx as jsx65, jsxs as jsxs33 } from "react/jsx-runtime";
|
|
5894
|
+
var subscribe2 = () => () => {
|
|
5895
|
+
};
|
|
5896
|
+
var getSnapshot2 = () => true;
|
|
5897
|
+
var getServerSnapshot2 = () => false;
|
|
5898
|
+
var COLOR_SWATCHES = {
|
|
5899
|
+
blue: "#5294FF",
|
|
5900
|
+
plum: "#B254CF",
|
|
5901
|
+
"plum-trio": "#B254CF"
|
|
5902
|
+
};
|
|
5903
|
+
var COLOR_LABELS = {
|
|
5904
|
+
blue: "Blue",
|
|
5905
|
+
plum: "Plum",
|
|
5906
|
+
"plum-trio": "Plum Trio"
|
|
5907
|
+
};
|
|
5908
|
+
function ColorThemeToggle(_a) {
|
|
5909
|
+
var _b = _a, {
|
|
5910
|
+
variant = "ghost",
|
|
5911
|
+
size = "md",
|
|
5912
|
+
className
|
|
5913
|
+
} = _b, props = __objRest(_b, [
|
|
5914
|
+
"variant",
|
|
5915
|
+
"size",
|
|
5916
|
+
"className"
|
|
5917
|
+
]);
|
|
5918
|
+
const { colorTheme, setColorTheme, colorThemes } = useTheme();
|
|
5919
|
+
const mounted = useSyncExternalStore2(subscribe2, getSnapshot2, getServerSnapshot2);
|
|
5920
|
+
return /* @__PURE__ */ jsxs33(DropdownMenuComponent, { children: [
|
|
5921
|
+
/* @__PURE__ */ jsx65(DropdownMenuComponent.Trigger, { asChild: true, children: /* @__PURE__ */ jsx65(
|
|
5922
|
+
IconButton,
|
|
5923
|
+
__spreadProps(__spreadValues({
|
|
5924
|
+
variant,
|
|
5925
|
+
size,
|
|
5926
|
+
className,
|
|
5927
|
+
"aria-label": mounted ? `Color theme: ${colorTheme}` : "Color theme"
|
|
5928
|
+
}, props), {
|
|
5929
|
+
children: /* @__PURE__ */ jsx65(
|
|
5930
|
+
"span",
|
|
5931
|
+
{
|
|
5932
|
+
className: "block w-4 h-4 border-2 border-border",
|
|
5933
|
+
style: {
|
|
5934
|
+
backgroundColor: mounted ? COLOR_SWATCHES[colorTheme] : void 0,
|
|
5935
|
+
borderRadius: "var(--radius, 0)"
|
|
5936
|
+
}
|
|
5937
|
+
}
|
|
5938
|
+
)
|
|
5939
|
+
})
|
|
5940
|
+
) }),
|
|
5941
|
+
/* @__PURE__ */ jsxs33(DropdownMenuComponent.Content, { align: "end", children: [
|
|
5942
|
+
/* @__PURE__ */ jsx65(DropdownMenuComponent.Label, { children: "Color Theme" }),
|
|
5943
|
+
/* @__PURE__ */ jsx65(DropdownMenuComponent.Separator, {}),
|
|
5944
|
+
/* @__PURE__ */ jsx65(
|
|
5945
|
+
DropdownMenuComponent.RadioGroup,
|
|
5946
|
+
{
|
|
5947
|
+
value: colorTheme,
|
|
5948
|
+
onValueChange: (v) => setColorTheme(v),
|
|
5949
|
+
children: colorThemes.map((theme) => /* @__PURE__ */ jsxs33(DropdownMenuComponent.RadioItem, { value: theme, children: [
|
|
5950
|
+
/* @__PURE__ */ jsx65(
|
|
5951
|
+
"span",
|
|
5952
|
+
{
|
|
5953
|
+
className: "inline-block w-3 h-3 border border-border mr-1",
|
|
5954
|
+
style: {
|
|
5955
|
+
backgroundColor: COLOR_SWATCHES[theme],
|
|
5956
|
+
borderRadius: "var(--radius, 0)"
|
|
5957
|
+
}
|
|
5958
|
+
}
|
|
5959
|
+
),
|
|
5960
|
+
COLOR_LABELS[theme]
|
|
5961
|
+
] }, theme))
|
|
5962
|
+
}
|
|
5963
|
+
)
|
|
5964
|
+
] })
|
|
5965
|
+
] });
|
|
5966
|
+
}
|
|
5967
|
+
|
|
5839
5968
|
// lib/create-theme.ts
|
|
5840
5969
|
function createTheme(name, config) {
|
|
5841
5970
|
const declarations = [];
|
|
@@ -5876,7 +6005,7 @@ ${declarations.join("\n")}
|
|
|
5876
6005
|
}
|
|
5877
6006
|
|
|
5878
6007
|
// components/landing/Hero.tsx
|
|
5879
|
-
import { jsx as
|
|
6008
|
+
import { jsx as jsx66, jsxs as jsxs34 } from "react/jsx-runtime";
|
|
5880
6009
|
function Hero({
|
|
5881
6010
|
badge,
|
|
5882
6011
|
title,
|
|
@@ -5886,14 +6015,14 @@ function Hero({
|
|
|
5886
6015
|
className,
|
|
5887
6016
|
align = "center"
|
|
5888
6017
|
}) {
|
|
5889
|
-
return /* @__PURE__ */
|
|
6018
|
+
return /* @__PURE__ */ jsx66(
|
|
5890
6019
|
"section",
|
|
5891
6020
|
{
|
|
5892
6021
|
className: cn(
|
|
5893
6022
|
"w-full border-b-2 bg-background",
|
|
5894
6023
|
className
|
|
5895
6024
|
),
|
|
5896
|
-
children: /* @__PURE__ */
|
|
6025
|
+
children: /* @__PURE__ */ jsxs34(
|
|
5897
6026
|
"div",
|
|
5898
6027
|
{
|
|
5899
6028
|
className: cn(
|
|
@@ -5902,10 +6031,10 @@ function Hero({
|
|
|
5902
6031
|
align === "left" && "items-start text-left"
|
|
5903
6032
|
),
|
|
5904
6033
|
children: [
|
|
5905
|
-
badge && /* @__PURE__ */
|
|
5906
|
-
/* @__PURE__ */
|
|
5907
|
-
subtitle && /* @__PURE__ */
|
|
5908
|
-
actions && /* @__PURE__ */
|
|
6034
|
+
badge && /* @__PURE__ */ jsx66("div", { children: badge }),
|
|
6035
|
+
/* @__PURE__ */ jsx66("h1", { className: "font-head text-4xl sm:text-5xl lg:text-6xl max-w-4xl", children: title }),
|
|
6036
|
+
subtitle && /* @__PURE__ */ jsx66("p", { className: "font-sans text-lg lg:text-xl text-muted-foreground max-w-2xl", children: subtitle }),
|
|
6037
|
+
actions && /* @__PURE__ */ jsx66("div", { className: "flex flex-wrap gap-3 mt-2", children: actions }),
|
|
5909
6038
|
children
|
|
5910
6039
|
]
|
|
5911
6040
|
}
|
|
@@ -5916,7 +6045,7 @@ function Hero({
|
|
|
5916
6045
|
|
|
5917
6046
|
// components/landing/Section.tsx
|
|
5918
6047
|
import { cva as cva20 } from "class-variance-authority";
|
|
5919
|
-
import { jsx as
|
|
6048
|
+
import { jsx as jsx67, jsxs as jsxs35 } from "react/jsx-runtime";
|
|
5920
6049
|
var sectionVariants = cva20("w-full py-16 lg:py-24 scroll-mt-[120px]", {
|
|
5921
6050
|
variants: {
|
|
5922
6051
|
background: {
|
|
@@ -5946,13 +6075,13 @@ function Section(_a) {
|
|
|
5946
6075
|
"background",
|
|
5947
6076
|
"align"
|
|
5948
6077
|
]);
|
|
5949
|
-
return /* @__PURE__ */
|
|
6078
|
+
return /* @__PURE__ */ jsx67(
|
|
5950
6079
|
"section",
|
|
5951
6080
|
__spreadProps(__spreadValues({
|
|
5952
6081
|
className: cn(sectionVariants({ background }), className)
|
|
5953
6082
|
}, props), {
|
|
5954
|
-
children: /* @__PURE__ */
|
|
5955
|
-
(title || subtitle) && /* @__PURE__ */
|
|
6083
|
+
children: /* @__PURE__ */ jsxs35("div", { className: "mx-auto max-w-6xl px-4", children: [
|
|
6084
|
+
(title || subtitle) && /* @__PURE__ */ jsxs35(
|
|
5956
6085
|
"div",
|
|
5957
6086
|
{
|
|
5958
6087
|
className: cn(
|
|
@@ -5961,8 +6090,8 @@ function Section(_a) {
|
|
|
5961
6090
|
align === "left" && "text-left"
|
|
5962
6091
|
),
|
|
5963
6092
|
children: [
|
|
5964
|
-
title && /* @__PURE__ */
|
|
5965
|
-
subtitle && /* @__PURE__ */
|
|
6093
|
+
title && /* @__PURE__ */ jsx67("h2", { className: "font-head text-3xl lg:text-4xl mb-3", children: title }),
|
|
6094
|
+
subtitle && /* @__PURE__ */ jsx67("p", { className: "font-sans text-lg text-muted-foreground max-w-2xl mx-auto", children: subtitle })
|
|
5966
6095
|
]
|
|
5967
6096
|
}
|
|
5968
6097
|
),
|
|
@@ -5973,7 +6102,7 @@ function Section(_a) {
|
|
|
5973
6102
|
}
|
|
5974
6103
|
|
|
5975
6104
|
// components/landing/Footer.tsx
|
|
5976
|
-
import { jsx as
|
|
6105
|
+
import { jsx as jsx68, jsxs as jsxs36 } from "react/jsx-runtime";
|
|
5977
6106
|
function Footer({
|
|
5978
6107
|
brand,
|
|
5979
6108
|
tagline,
|
|
@@ -5981,15 +6110,15 @@ function Footer({
|
|
|
5981
6110
|
bottom,
|
|
5982
6111
|
className
|
|
5983
6112
|
}) {
|
|
5984
|
-
return /* @__PURE__ */
|
|
5985
|
-
/* @__PURE__ */
|
|
5986
|
-
/* @__PURE__ */
|
|
5987
|
-
/* @__PURE__ */
|
|
5988
|
-
tagline && /* @__PURE__ */
|
|
6113
|
+
return /* @__PURE__ */ jsx68("footer", { className: cn("w-full border-t-2 bg-background", className), children: /* @__PURE__ */ jsxs36("div", { className: "mx-auto max-w-6xl px-4 py-12 lg:py-16", children: [
|
|
6114
|
+
/* @__PURE__ */ jsxs36("div", { className: "grid gap-8 lg:grid-cols-[1.5fr_repeat(auto-fit,1fr)]", children: [
|
|
6115
|
+
/* @__PURE__ */ jsxs36("div", { className: "max-w-xs", children: [
|
|
6116
|
+
/* @__PURE__ */ jsx68("div", { className: "font-head text-2xl mb-2", children: brand }),
|
|
6117
|
+
tagline && /* @__PURE__ */ jsx68("p", { className: "font-sans text-sm text-muted-foreground", children: tagline })
|
|
5989
6118
|
] }),
|
|
5990
|
-
groups.length > 0 && /* @__PURE__ */
|
|
5991
|
-
/* @__PURE__ */
|
|
5992
|
-
/* @__PURE__ */
|
|
6119
|
+
groups.length > 0 && /* @__PURE__ */ jsx68("div", { className: "grid gap-8 sm:grid-cols-2 lg:grid-cols-3 col-span-full lg:col-span-1", children: groups.map((group) => /* @__PURE__ */ jsxs36("div", { children: [
|
|
6120
|
+
/* @__PURE__ */ jsx68("h4", { className: "font-head text-sm uppercase mb-3", children: group.title }),
|
|
6121
|
+
/* @__PURE__ */ jsx68("ul", { className: "flex flex-col gap-2", children: group.links.map((link) => /* @__PURE__ */ jsx68("li", { children: /* @__PURE__ */ jsx68(
|
|
5993
6122
|
"a",
|
|
5994
6123
|
{
|
|
5995
6124
|
href: link.href,
|
|
@@ -5999,21 +6128,21 @@ function Footer({
|
|
|
5999
6128
|
) }, link.label)) })
|
|
6000
6129
|
] }, group.title)) })
|
|
6001
6130
|
] }),
|
|
6002
|
-
bottom && /* @__PURE__ */
|
|
6131
|
+
bottom && /* @__PURE__ */ jsx68("div", { className: "mt-12 pt-6 border-t-2 font-sans text-sm text-muted-foreground", children: bottom })
|
|
6003
6132
|
] }) });
|
|
6004
6133
|
}
|
|
6005
6134
|
|
|
6006
6135
|
// components/landing/PricingTable.tsx
|
|
6007
|
-
import { jsx as
|
|
6136
|
+
import { jsx as jsx69, jsxs as jsxs37 } from "react/jsx-runtime";
|
|
6008
6137
|
function PricingTable({ tiers, className }) {
|
|
6009
|
-
return /* @__PURE__ */
|
|
6138
|
+
return /* @__PURE__ */ jsx69(
|
|
6010
6139
|
"div",
|
|
6011
6140
|
{
|
|
6012
6141
|
className: cn(
|
|
6013
6142
|
"grid gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
6014
6143
|
className
|
|
6015
6144
|
),
|
|
6016
|
-
children: tiers.map((tier) => /* @__PURE__ */
|
|
6145
|
+
children: tiers.map((tier) => /* @__PURE__ */ jsxs37(
|
|
6017
6146
|
"div",
|
|
6018
6147
|
{
|
|
6019
6148
|
className: cn(
|
|
@@ -6021,15 +6150,15 @@ function PricingTable({ tiers, className }) {
|
|
|
6021
6150
|
tier.highlighted ? "shadow-lg border-primary ring-2 ring-primary scale-[1.02]" : "shadow-md"
|
|
6022
6151
|
),
|
|
6023
6152
|
children: [
|
|
6024
|
-
/* @__PURE__ */
|
|
6025
|
-
/* @__PURE__ */
|
|
6026
|
-
/* @__PURE__ */
|
|
6153
|
+
/* @__PURE__ */ jsxs37("div", { className: "p-6 border-b-2", children: [
|
|
6154
|
+
/* @__PURE__ */ jsxs37("div", { className: "flex items-center justify-between mb-2", children: [
|
|
6155
|
+
/* @__PURE__ */ jsx69("h3", { className: "font-head text-xl", children: tier.name }),
|
|
6027
6156
|
tier.badge
|
|
6028
6157
|
] }),
|
|
6029
|
-
/* @__PURE__ */
|
|
6030
|
-
tier.description && /* @__PURE__ */
|
|
6158
|
+
/* @__PURE__ */ jsx69("div", { className: "font-head text-4xl mb-1", children: tier.price }),
|
|
6159
|
+
tier.description && /* @__PURE__ */ jsx69("p", { className: "font-sans text-sm text-muted-foreground", children: tier.description })
|
|
6031
6160
|
] }),
|
|
6032
|
-
/* @__PURE__ */
|
|
6161
|
+
/* @__PURE__ */ jsx69("div", { className: "p-6 flex-1", children: /* @__PURE__ */ jsx69("ul", { className: "flex flex-col gap-3", children: tier.features.map((feature) => /* @__PURE__ */ jsxs37(
|
|
6033
6162
|
"li",
|
|
6034
6163
|
{
|
|
6035
6164
|
className: cn(
|
|
@@ -6037,7 +6166,7 @@ function PricingTable({ tiers, className }) {
|
|
|
6037
6166
|
!feature.included && "text-muted-foreground line-through"
|
|
6038
6167
|
),
|
|
6039
6168
|
children: [
|
|
6040
|
-
/* @__PURE__ */
|
|
6169
|
+
/* @__PURE__ */ jsx69(
|
|
6041
6170
|
"span",
|
|
6042
6171
|
{
|
|
6043
6172
|
className: cn(
|
|
@@ -6052,7 +6181,7 @@ function PricingTable({ tiers, className }) {
|
|
|
6052
6181
|
},
|
|
6053
6182
|
feature.text
|
|
6054
6183
|
)) }) }),
|
|
6055
|
-
/* @__PURE__ */
|
|
6184
|
+
/* @__PURE__ */ jsx69("div", { className: "p-6 border-t-2", children: tier.cta })
|
|
6056
6185
|
]
|
|
6057
6186
|
},
|
|
6058
6187
|
tier.name
|
|
@@ -6062,7 +6191,7 @@ function PricingTable({ tiers, className }) {
|
|
|
6062
6191
|
}
|
|
6063
6192
|
|
|
6064
6193
|
// components/landing/FeatureSection.tsx
|
|
6065
|
-
import { jsx as
|
|
6194
|
+
import { jsx as jsx70, jsxs as jsxs38 } from "react/jsx-runtime";
|
|
6066
6195
|
var columnClasses2 = {
|
|
6067
6196
|
2: "grid gap-6 sm:grid-cols-2",
|
|
6068
6197
|
3: "grid gap-6 sm:grid-cols-2 lg:grid-cols-3",
|
|
@@ -6073,14 +6202,14 @@ function FeatureSection({
|
|
|
6073
6202
|
columns = 3,
|
|
6074
6203
|
className
|
|
6075
6204
|
}) {
|
|
6076
|
-
return /* @__PURE__ */
|
|
6205
|
+
return /* @__PURE__ */ jsx70("div", { className: cn(columnClasses2[columns], className), children: features.map((feature) => /* @__PURE__ */ jsxs38(
|
|
6077
6206
|
"div",
|
|
6078
6207
|
{
|
|
6079
6208
|
className: "border-2 p-6 bg-card shadow-md",
|
|
6080
6209
|
children: [
|
|
6081
|
-
feature.icon && /* @__PURE__ */
|
|
6082
|
-
/* @__PURE__ */
|
|
6083
|
-
/* @__PURE__ */
|
|
6210
|
+
feature.icon && /* @__PURE__ */ jsx70("div", { className: "mb-4 inline-flex items-center justify-center h-12 w-12 border-2 bg-primary text-primary-foreground shadow-sm", children: feature.icon }),
|
|
6211
|
+
/* @__PURE__ */ jsx70("h3", { className: "font-head text-lg mb-2", children: feature.title }),
|
|
6212
|
+
/* @__PURE__ */ jsx70("p", { className: "font-sans text-sm text-muted-foreground", children: feature.description })
|
|
6084
6213
|
]
|
|
6085
6214
|
},
|
|
6086
6215
|
feature.title
|
|
@@ -6088,7 +6217,7 @@ function FeatureSection({
|
|
|
6088
6217
|
}
|
|
6089
6218
|
|
|
6090
6219
|
// components/landing/Testimonial.tsx
|
|
6091
|
-
import { jsx as
|
|
6220
|
+
import { jsx as jsx71, jsxs as jsxs39 } from "react/jsx-runtime";
|
|
6092
6221
|
var columnClasses3 = {
|
|
6093
6222
|
1: "grid gap-6 max-w-2xl mx-auto",
|
|
6094
6223
|
2: "grid gap-6 sm:grid-cols-2",
|
|
@@ -6099,21 +6228,21 @@ function Testimonial({
|
|
|
6099
6228
|
columns = 3,
|
|
6100
6229
|
className
|
|
6101
6230
|
}) {
|
|
6102
|
-
return /* @__PURE__ */
|
|
6231
|
+
return /* @__PURE__ */ jsx71("div", { className: cn(columnClasses3[columns], className), children: testimonials.map((t) => /* @__PURE__ */ jsxs39(
|
|
6103
6232
|
"div",
|
|
6104
6233
|
{
|
|
6105
6234
|
className: "border-2 p-6 bg-card shadow-md flex flex-col",
|
|
6106
6235
|
children: [
|
|
6107
|
-
/* @__PURE__ */
|
|
6236
|
+
/* @__PURE__ */ jsxs39("blockquote", { className: "font-sans text-sm leading-relaxed flex-1 mb-6", children: [
|
|
6108
6237
|
"\u201C",
|
|
6109
6238
|
t.quote,
|
|
6110
6239
|
"\u201D"
|
|
6111
6240
|
] }),
|
|
6112
|
-
/* @__PURE__ */
|
|
6113
|
-
t.avatar && /* @__PURE__ */
|
|
6114
|
-
/* @__PURE__ */
|
|
6115
|
-
/* @__PURE__ */
|
|
6116
|
-
(t.role || t.company) && /* @__PURE__ */
|
|
6241
|
+
/* @__PURE__ */ jsxs39("div", { className: "flex items-center gap-3 border-t-2 pt-4", children: [
|
|
6242
|
+
t.avatar && /* @__PURE__ */ jsx71("div", { className: "h-10 w-10 shrink-0 border-2 overflow-hidden", children: t.avatar }),
|
|
6243
|
+
/* @__PURE__ */ jsxs39("div", { children: [
|
|
6244
|
+
/* @__PURE__ */ jsx71("p", { className: "font-head text-sm", children: t.name }),
|
|
6245
|
+
(t.role || t.company) && /* @__PURE__ */ jsx71("p", { className: "font-sans text-xs text-muted-foreground", children: [t.role, t.company].filter(Boolean).join(", ") })
|
|
6117
6246
|
] })
|
|
6118
6247
|
] })
|
|
6119
6248
|
]
|
|
@@ -6123,9 +6252,9 @@ function Testimonial({
|
|
|
6123
6252
|
}
|
|
6124
6253
|
|
|
6125
6254
|
// components/landing/LogoCloud.tsx
|
|
6126
|
-
import { jsx as
|
|
6255
|
+
import { jsx as jsx72 } from "react/jsx-runtime";
|
|
6127
6256
|
function LogoCloud({ children, className }) {
|
|
6128
|
-
return /* @__PURE__ */
|
|
6257
|
+
return /* @__PURE__ */ jsx72(
|
|
6129
6258
|
"div",
|
|
6130
6259
|
{
|
|
6131
6260
|
className: cn(
|
|
@@ -6138,24 +6267,24 @@ function LogoCloud({ children, className }) {
|
|
|
6138
6267
|
}
|
|
6139
6268
|
|
|
6140
6269
|
// components/landing/CTABanner.tsx
|
|
6141
|
-
import { jsx as
|
|
6270
|
+
import { jsx as jsx73, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
6142
6271
|
function CTABanner({
|
|
6143
6272
|
title,
|
|
6144
6273
|
subtitle,
|
|
6145
6274
|
actions,
|
|
6146
6275
|
className
|
|
6147
6276
|
}) {
|
|
6148
|
-
return /* @__PURE__ */
|
|
6277
|
+
return /* @__PURE__ */ jsx73(
|
|
6149
6278
|
"section",
|
|
6150
6279
|
{
|
|
6151
6280
|
className: cn(
|
|
6152
6281
|
"w-full border-y-2 bg-primary text-primary-foreground",
|
|
6153
6282
|
className
|
|
6154
6283
|
),
|
|
6155
|
-
children: /* @__PURE__ */
|
|
6156
|
-
/* @__PURE__ */
|
|
6157
|
-
subtitle && /* @__PURE__ */
|
|
6158
|
-
actions && /* @__PURE__ */
|
|
6284
|
+
children: /* @__PURE__ */ jsxs40("div", { className: "mx-auto max-w-6xl px-4 py-16 lg:py-20 flex flex-col items-center text-center gap-4", children: [
|
|
6285
|
+
/* @__PURE__ */ jsx73("h2", { className: "font-head text-3xl lg:text-4xl", children: title }),
|
|
6286
|
+
subtitle && /* @__PURE__ */ jsx73("p", { className: "font-sans text-lg max-w-xl", children: subtitle }),
|
|
6287
|
+
actions && /* @__PURE__ */ jsx73("div", { className: "flex flex-wrap gap-3 mt-2", children: actions })
|
|
6159
6288
|
] })
|
|
6160
6289
|
}
|
|
6161
6290
|
);
|
|
@@ -6164,20 +6293,20 @@ function CTABanner({
|
|
|
6164
6293
|
// components/landing/FAQ.tsx
|
|
6165
6294
|
import * as React60 from "react";
|
|
6166
6295
|
import { ChevronDown as ChevronDown6 } from "lucide-react";
|
|
6167
|
-
import { jsx as
|
|
6296
|
+
import { jsx as jsx74, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
6168
6297
|
function FAQ({ items, className }) {
|
|
6169
6298
|
const [openIndex, setOpenIndex] = React60.useState(null);
|
|
6170
|
-
return /* @__PURE__ */
|
|
6299
|
+
return /* @__PURE__ */ jsx74("div", { className: cn("w-full max-w-3xl mx-auto", className), children: items.map((item, i) => {
|
|
6171
6300
|
const isOpen = openIndex === i;
|
|
6172
|
-
return /* @__PURE__ */
|
|
6173
|
-
/* @__PURE__ */
|
|
6301
|
+
return /* @__PURE__ */ jsxs41("div", { className: "border-2 border-b-0 last:border-b-2", children: [
|
|
6302
|
+
/* @__PURE__ */ jsxs41(
|
|
6174
6303
|
"button",
|
|
6175
6304
|
{
|
|
6176
6305
|
onClick: () => setOpenIndex(isOpen ? null : i),
|
|
6177
6306
|
className: "w-full flex items-center justify-between p-4 text-left cursor-pointer hover:bg-accent/30 transition-colors",
|
|
6178
6307
|
children: [
|
|
6179
|
-
/* @__PURE__ */
|
|
6180
|
-
/* @__PURE__ */
|
|
6308
|
+
/* @__PURE__ */ jsx74("span", { className: "font-head text-sm pr-4", children: item.question }),
|
|
6309
|
+
/* @__PURE__ */ jsx74(
|
|
6181
6310
|
ChevronDown6,
|
|
6182
6311
|
{
|
|
6183
6312
|
className: cn(
|
|
@@ -6189,24 +6318,24 @@ function FAQ({ items, className }) {
|
|
|
6189
6318
|
]
|
|
6190
6319
|
}
|
|
6191
6320
|
),
|
|
6192
|
-
isOpen && /* @__PURE__ */
|
|
6321
|
+
isOpen && /* @__PURE__ */ jsx74("div", { className: "px-4 pb-4 font-sans text-sm text-muted-foreground", children: item.answer })
|
|
6193
6322
|
] }, i);
|
|
6194
6323
|
}) });
|
|
6195
6324
|
}
|
|
6196
6325
|
|
|
6197
6326
|
// components/landing/StatsBar.tsx
|
|
6198
|
-
import { jsx as
|
|
6327
|
+
import { jsx as jsx75, jsxs as jsxs42 } from "react/jsx-runtime";
|
|
6199
6328
|
function StatsBar({ stats, className }) {
|
|
6200
|
-
return /* @__PURE__ */
|
|
6329
|
+
return /* @__PURE__ */ jsx75(
|
|
6201
6330
|
"div",
|
|
6202
6331
|
{
|
|
6203
6332
|
className: cn(
|
|
6204
6333
|
"w-full border-y-2 bg-card",
|
|
6205
6334
|
className
|
|
6206
6335
|
),
|
|
6207
|
-
children: /* @__PURE__ */
|
|
6208
|
-
/* @__PURE__ */
|
|
6209
|
-
/* @__PURE__ */
|
|
6336
|
+
children: /* @__PURE__ */ jsx75("div", { className: "mx-auto max-w-6xl px-4 py-10 grid grid-cols-2 lg:grid-cols-4 gap-8", children: stats.map((stat) => /* @__PURE__ */ jsxs42("div", { className: "text-center", children: [
|
|
6337
|
+
/* @__PURE__ */ jsx75("div", { className: "font-head text-3xl lg:text-4xl mb-1", children: stat.value }),
|
|
6338
|
+
/* @__PURE__ */ jsx75("div", { className: "font-sans text-sm text-muted-foreground uppercase", children: stat.label })
|
|
6210
6339
|
] }, stat.label)) })
|
|
6211
6340
|
}
|
|
6212
6341
|
);
|
|
@@ -6215,37 +6344,39 @@ function StatsBar({ stats, className }) {
|
|
|
6215
6344
|
// components/landing/AnnouncementBanner.tsx
|
|
6216
6345
|
import * as React61 from "react";
|
|
6217
6346
|
import { X as X4 } from "lucide-react";
|
|
6218
|
-
import { jsx as
|
|
6347
|
+
import { jsx as jsx76, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
6219
6348
|
function AnnouncementBanner({
|
|
6220
6349
|
children,
|
|
6221
6350
|
dismissible = true,
|
|
6222
6351
|
className
|
|
6223
6352
|
}) {
|
|
6224
|
-
const [visible, setVisible] = React61.useState(
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6353
|
+
const [visible, setVisible] = React61.useState(true);
|
|
6354
|
+
React61.useEffect(() => {
|
|
6355
|
+
if (sessionStorage.getItem("announcement-dismissed") === "true") {
|
|
6356
|
+
setVisible(false);
|
|
6357
|
+
}
|
|
6358
|
+
}, []);
|
|
6228
6359
|
const handleDismiss = () => {
|
|
6229
6360
|
setVisible(false);
|
|
6230
6361
|
sessionStorage.setItem("announcement-dismissed", "true");
|
|
6231
6362
|
};
|
|
6232
6363
|
if (!visible) return null;
|
|
6233
|
-
return /* @__PURE__ */
|
|
6364
|
+
return /* @__PURE__ */ jsx76(
|
|
6234
6365
|
"div",
|
|
6235
6366
|
{
|
|
6236
6367
|
className: cn(
|
|
6237
6368
|
"w-full bg-primary text-primary-foreground border-b-2",
|
|
6238
6369
|
className
|
|
6239
6370
|
),
|
|
6240
|
-
children: /* @__PURE__ */
|
|
6241
|
-
/* @__PURE__ */
|
|
6242
|
-
dismissible && /* @__PURE__ */
|
|
6371
|
+
children: /* @__PURE__ */ jsxs43("div", { className: "mx-auto max-w-6xl px-4 py-2 flex items-center justify-center gap-3", children: [
|
|
6372
|
+
/* @__PURE__ */ jsx76("p", { className: "font-sans text-sm text-center flex-1", children }),
|
|
6373
|
+
dismissible && /* @__PURE__ */ jsx76(
|
|
6243
6374
|
"button",
|
|
6244
6375
|
{
|
|
6245
6376
|
onClick: handleDismiss,
|
|
6246
6377
|
className: "shrink-0 p-2 min-w-[44px] min-h-[44px] inline-flex items-center justify-center hover:bg-foreground/10 transition-colors cursor-pointer",
|
|
6247
6378
|
"aria-label": "Dismiss",
|
|
6248
|
-
children: /* @__PURE__ */
|
|
6379
|
+
children: /* @__PURE__ */ jsx76(X4, { className: "h-4 w-4" })
|
|
6249
6380
|
}
|
|
6250
6381
|
)
|
|
6251
6382
|
] })
|
|
@@ -6254,7 +6385,7 @@ function AnnouncementBanner({
|
|
|
6254
6385
|
}
|
|
6255
6386
|
|
|
6256
6387
|
// components/landing/NewsletterSignup.tsx
|
|
6257
|
-
import { jsx as
|
|
6388
|
+
import { jsx as jsx77, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
6258
6389
|
function NewsletterSignup({
|
|
6259
6390
|
title = "Stay in the loop",
|
|
6260
6391
|
subtitle,
|
|
@@ -6262,16 +6393,16 @@ function NewsletterSignup({
|
|
|
6262
6393
|
buttonLabel = "Subscribe",
|
|
6263
6394
|
className
|
|
6264
6395
|
}) {
|
|
6265
|
-
return /* @__PURE__ */
|
|
6266
|
-
title && /* @__PURE__ */
|
|
6267
|
-
subtitle && /* @__PURE__ */
|
|
6268
|
-
/* @__PURE__ */
|
|
6396
|
+
return /* @__PURE__ */ jsxs44("div", { className: cn("w-full max-w-md mx-auto", className), children: [
|
|
6397
|
+
title && /* @__PURE__ */ jsx77("h3", { className: "font-head text-xl mb-2 text-center", children: title }),
|
|
6398
|
+
subtitle && /* @__PURE__ */ jsx77("p", { className: "font-sans text-sm text-muted-foreground text-center mb-4", children: subtitle }),
|
|
6399
|
+
/* @__PURE__ */ jsxs44(
|
|
6269
6400
|
"form",
|
|
6270
6401
|
{
|
|
6271
6402
|
onSubmit: (e) => e.preventDefault(),
|
|
6272
6403
|
className: "flex gap-2",
|
|
6273
6404
|
children: [
|
|
6274
|
-
/* @__PURE__ */
|
|
6405
|
+
/* @__PURE__ */ jsx77(
|
|
6275
6406
|
"input",
|
|
6276
6407
|
{
|
|
6277
6408
|
type: "email",
|
|
@@ -6280,7 +6411,7 @@ function NewsletterSignup({
|
|
|
6280
6411
|
required: true
|
|
6281
6412
|
}
|
|
6282
6413
|
),
|
|
6283
|
-
/* @__PURE__ */
|
|
6414
|
+
/* @__PURE__ */ jsx77(
|
|
6284
6415
|
"button",
|
|
6285
6416
|
{
|
|
6286
6417
|
type: "submit",
|
|
@@ -6310,6 +6441,7 @@ export {
|
|
|
6310
6441
|
ChartComponent as Chart,
|
|
6311
6442
|
Checkbox,
|
|
6312
6443
|
CollapsibleComponent as Collapsible,
|
|
6444
|
+
ColorThemeToggle,
|
|
6313
6445
|
ComboboxComponent as Combobox,
|
|
6314
6446
|
CommandComponent as Command,
|
|
6315
6447
|
Container,
|