@caffeinebounce/ui 0.62.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/LICENSE +21 -0
- package/README.md +39 -0
- package/dist/FinancialStatementTable-BNUrdTU4.d.cts +249 -0
- package/dist/FinancialStatementTable-BNUrdTU4.d.ts +249 -0
- package/dist/NewsletterSignup-BPreFi5W.d.cts +37 -0
- package/dist/NewsletterSignup-BPreFi5W.d.ts +37 -0
- package/dist/TestimonialsSection-DtPu2OeR.d.ts +736 -0
- package/dist/TestimonialsSection-z-yotRfv.d.cts +736 -0
- package/dist/UnifiedTableControls-CG299y9h.d.ts +1233 -0
- package/dist/UnifiedTableControls-CIjRpNhy.d.cts +1233 -0
- package/dist/blog.d.cts +99 -0
- package/dist/blog.d.ts +99 -0
- package/dist/blog.js +292 -0
- package/dist/blog.mjs +279 -0
- package/dist/button-BHnoRUkF.d.cts +34 -0
- package/dist/button-BHnoRUkF.d.ts +34 -0
- package/dist/charts.d.cts +80 -0
- package/dist/charts.d.ts +80 -0
- package/dist/charts.js +19 -0
- package/dist/charts.mjs +2 -0
- package/dist/chunk-33JR5SYE.js +44 -0
- package/dist/chunk-3NDB4YPC.js +247 -0
- package/dist/chunk-5RW4PYZ6.js +1504 -0
- package/dist/chunk-5THF4YP6.mjs +155 -0
- package/dist/chunk-6BUBNZPG.mjs +164 -0
- package/dist/chunk-6DVWMJ3H.mjs +7029 -0
- package/dist/chunk-6TGV2DNP.js +120 -0
- package/dist/chunk-72JGQ7IJ.mjs +1498 -0
- package/dist/chunk-7DHKQODW.mjs +2932 -0
- package/dist/chunk-7IKHZKAC.js +160 -0
- package/dist/chunk-ADIDI7AJ.js +11 -0
- package/dist/chunk-BFWX5GJZ.mjs +940 -0
- package/dist/chunk-BMFQG6RA.mjs +5537 -0
- package/dist/chunk-C4UT5V3P.js +65 -0
- package/dist/chunk-CC4KUIKC.js +2004 -0
- package/dist/chunk-D3QXPL47.mjs +1814 -0
- package/dist/chunk-DQWHYBV2.js +36 -0
- package/dist/chunk-E42B4GSB.js +993 -0
- package/dist/chunk-ESZ7CBA2.js +1007 -0
- package/dist/chunk-EYJJQVV4.js +111 -0
- package/dist/chunk-FRRS2YZH.mjs +129 -0
- package/dist/chunk-G5TQWWQA.mjs +37 -0
- package/dist/chunk-GAIQJCAZ.js +5612 -0
- package/dist/chunk-GMBGWOCR.mjs +48 -0
- package/dist/chunk-GUSTCU2W.mjs +105 -0
- package/dist/chunk-HBLKVQIQ.mjs +23 -0
- package/dist/chunk-HMAMMC72.js +26 -0
- package/dist/chunk-IMKLN273.mjs +9 -0
- package/dist/chunk-J6OLBSZR.js +250 -0
- package/dist/chunk-JAE45W2T.js +28 -0
- package/dist/chunk-JORVSG52.js +606 -0
- package/dist/chunk-KB7UXIQZ.mjs +984 -0
- package/dist/chunk-KGGQ5NZV.js +186 -0
- package/dist/chunk-KHCC5UKW.mjs +22 -0
- package/dist/chunk-KRRIRS6A.mjs +1945 -0
- package/dist/chunk-LQCVRWVF.js +48 -0
- package/dist/chunk-MHZXUOGN.mjs +168 -0
- package/dist/chunk-MPZFPU4X.js +349 -0
- package/dist/chunk-MVYRNJA6.js +74 -0
- package/dist/chunk-N6AFNFZR.mjs +565 -0
- package/dist/chunk-OFQLWSUR.mjs +214 -0
- package/dist/chunk-OLAAXLXY.mjs +219 -0
- package/dist/chunk-OZZWDIOY.js +1859 -0
- package/dist/chunk-PZRI43EZ.js +111 -0
- package/dist/chunk-Q256HRYD.js +176 -0
- package/dist/chunk-Q52ZEL62.mjs +223 -0
- package/dist/chunk-R26Y7LGJ.js +142 -0
- package/dist/chunk-RBUYW6QQ.js +39 -0
- package/dist/chunk-RVEFPVZF.mjs +43 -0
- package/dist/chunk-SORWLKOK.js +96 -0
- package/dist/chunk-STEP6C4C.mjs +33 -0
- package/dist/chunk-T5R6HUDG.mjs +22 -0
- package/dist/chunk-T6ZBA6VJ.js +7109 -0
- package/dist/chunk-UM7WMXIU.js +2995 -0
- package/dist/chunk-VBD4Q5LL.mjs +117 -0
- package/dist/chunk-WOITB4JL.js +195 -0
- package/dist/chunk-YKZEKJMZ.mjs +71 -0
- package/dist/chunk-YL7RZRHM.mjs +103 -0
- package/dist/chunk-YSLD2HLP.mjs +346 -0
- package/dist/chunk-ZFLZA7UP.mjs +140 -0
- package/dist/chunk-ZKUIUE7W.mjs +26 -0
- package/dist/chunk-ZOA7B32D.js +248 -0
- package/dist/data-table.d.cts +46 -0
- package/dist/data-table.d.ts +46 -0
- package/dist/data-table.js +270 -0
- package/dist/data-table.mjs +13 -0
- package/dist/editor.d.cts +89 -0
- package/dist/editor.d.ts +89 -0
- package/dist/editor.js +10 -0
- package/dist/editor.mjs +1 -0
- package/dist/forms.d.cts +142 -0
- package/dist/forms.d.ts +142 -0
- package/dist/forms.js +24 -0
- package/dist/forms.mjs +11 -0
- package/dist/hooks-8ORd7T1A.d.cts +751 -0
- package/dist/hooks-B2jU1GVT.d.ts +751 -0
- package/dist/hooks.d.cts +6 -0
- package/dist/hooks.d.ts +6 -0
- package/dist/hooks.js +99 -0
- package/dist/hooks.mjs +10 -0
- package/dist/index.d.cts +3141 -0
- package/dist/index.d.ts +3141 -0
- package/dist/index.js +7332 -0
- package/dist/index.mjs +5876 -0
- package/dist/layouts-DPfDDF53.d.cts +1001 -0
- package/dist/layouts-DPfDDF53.d.ts +1001 -0
- package/dist/layouts.d.cts +4 -0
- package/dist/layouts.d.ts +4 -0
- package/dist/layouts.js +100 -0
- package/dist/layouts.mjs +11 -0
- package/dist/marketing-3d.d.cts +51 -0
- package/dist/marketing-3d.d.ts +51 -0
- package/dist/marketing-3d.js +553 -0
- package/dist/marketing-3d.mjs +526 -0
- package/dist/marketing.d.cts +583 -0
- package/dist/marketing.d.ts +583 -0
- package/dist/marketing.js +299 -0
- package/dist/marketing.mjs +10 -0
- package/dist/media.d.cts +29 -0
- package/dist/media.d.ts +29 -0
- package/dist/media.js +189 -0
- package/dist/media.mjs +182 -0
- package/dist/navigation.d.cts +591 -0
- package/dist/navigation.d.ts +591 -0
- package/dist/navigation.js +108 -0
- package/dist/navigation.mjs +15 -0
- package/dist/portal.d.cts +58 -0
- package/dist/portal.d.ts +58 -0
- package/dist/portal.js +403 -0
- package/dist/portal.mjs +395 -0
- package/dist/primitives.d.cts +508 -0
- package/dist/primitives.d.ts +508 -0
- package/dist/primitives.js +295 -0
- package/dist/primitives.mjs +14 -0
- package/dist/settings.d.cts +216 -0
- package/dist/settings.d.ts +216 -0
- package/dist/settings.js +34 -0
- package/dist/settings.mjs +9 -0
- package/dist/shared-Dqn36QHZ.d.cts +4 -0
- package/dist/shared-Dqn36QHZ.d.ts +4 -0
- package/dist/styles.css +1213 -0
- package/package.json +189 -0
- package/styles.css +1 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkADIDI7AJ_js = require('./chunk-ADIDI7AJ.js');
|
|
4
|
+
var classVarianceAuthority = require('class-variance-authority');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
var alertVariants = classVarianceAuthority.cva(
|
|
8
|
+
"relative w-full rounded-box border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current",
|
|
9
|
+
{
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-card text-card-foreground",
|
|
13
|
+
destructive: "border-destructive text-destructive bg-card [&>svg]:text-current *:data-[slot=alert-description]:text-destructive/90"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
defaultVariants: {
|
|
17
|
+
variant: "default"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
function Alert({
|
|
22
|
+
className,
|
|
23
|
+
variant,
|
|
24
|
+
...props
|
|
25
|
+
}) {
|
|
26
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27
|
+
"div",
|
|
28
|
+
{
|
|
29
|
+
"data-slot": "alert",
|
|
30
|
+
role: "alert",
|
|
31
|
+
className: chunkADIDI7AJ_js.cn(alertVariants({ variant }), className),
|
|
32
|
+
...props
|
|
33
|
+
}
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
function AlertTitle({ className, ...props }) {
|
|
37
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
38
|
+
"div",
|
|
39
|
+
{
|
|
40
|
+
"data-slot": "alert-title",
|
|
41
|
+
className: chunkADIDI7AJ_js.cn(
|
|
42
|
+
"col-start-2 line-clamp-1 min-h-4 font-medium tracking-tight",
|
|
43
|
+
className
|
|
44
|
+
),
|
|
45
|
+
...props
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function AlertDescription({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}) {
|
|
53
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
54
|
+
"div",
|
|
55
|
+
{
|
|
56
|
+
"data-slot": "alert-description",
|
|
57
|
+
className: chunkADIDI7AJ_js.cn(
|
|
58
|
+
"text-muted-foreground col-start-2 grid justify-items-start gap-1 text-sm [&_p]:leading-relaxed",
|
|
59
|
+
className
|
|
60
|
+
),
|
|
61
|
+
...props
|
|
62
|
+
}
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
var badgeVariants = classVarianceAuthority.cva(
|
|
66
|
+
"inline-flex items-center border font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
|
|
67
|
+
{
|
|
68
|
+
variants: {
|
|
69
|
+
variant: {
|
|
70
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
71
|
+
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
72
|
+
destructive: "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
|
|
73
|
+
outline: "text-foreground",
|
|
74
|
+
success: "border-transparent bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400",
|
|
75
|
+
warning: "border-transparent bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400",
|
|
76
|
+
muted: "border-transparent bg-muted text-muted-foreground"
|
|
77
|
+
},
|
|
78
|
+
shape: {
|
|
79
|
+
pill: "rounded-full",
|
|
80
|
+
rounded: "rounded-md",
|
|
81
|
+
square: "rounded-none"
|
|
82
|
+
},
|
|
83
|
+
size: {
|
|
84
|
+
sm: "px-1 text-[9px]",
|
|
85
|
+
default: "px-1.5 text-[10px]",
|
|
86
|
+
lg: "px-2 py-0.5 text-xs"
|
|
87
|
+
}
|
|
88
|
+
},
|
|
89
|
+
defaultVariants: {
|
|
90
|
+
variant: "default",
|
|
91
|
+
shape: "pill",
|
|
92
|
+
size: "default"
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
);
|
|
96
|
+
function Badge({ className, variant, shape, size, ...props }) {
|
|
97
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
98
|
+
"div",
|
|
99
|
+
{
|
|
100
|
+
"data-slot": "badge",
|
|
101
|
+
className: chunkADIDI7AJ_js.cn(badgeVariants({ variant, shape, size }), className),
|
|
102
|
+
...props
|
|
103
|
+
}
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
exports.Alert = Alert;
|
|
108
|
+
exports.AlertDescription = AlertDescription;
|
|
109
|
+
exports.AlertTitle = AlertTitle;
|
|
110
|
+
exports.Badge = Badge;
|
|
111
|
+
exports.badgeVariants = badgeVariants;
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var lucideReact = require('lucide-react');
|
|
4
|
+
|
|
5
|
+
// src/utils/avatar-gradient.ts
|
|
6
|
+
var GRADIENT_PAIRS = [
|
|
7
|
+
// Vibrant contrasts
|
|
8
|
+
{ from: "#f97316", to: "#ec4899" },
|
|
9
|
+
// Orange → Pink
|
|
10
|
+
{ from: "#ef4444", to: "#a855f7" },
|
|
11
|
+
// Red → Purple
|
|
12
|
+
{ from: "#f59e0b", to: "#ef4444" },
|
|
13
|
+
// Amber → Red
|
|
14
|
+
{ from: "#ec4899", to: "#8b5cf6" },
|
|
15
|
+
// Pink → Violet
|
|
16
|
+
{ from: "#f43f5e", to: "#fb923c" },
|
|
17
|
+
// Rose → Orange
|
|
18
|
+
// Cool gradients
|
|
19
|
+
{ from: "#3b82f6", to: "#a855f7" },
|
|
20
|
+
// Blue → Purple
|
|
21
|
+
{ from: "#6366f1", to: "#ec4899" },
|
|
22
|
+
// Indigo → Pink
|
|
23
|
+
{ from: "#8b5cf6", to: "#06b6d4" },
|
|
24
|
+
// Violet → Cyan
|
|
25
|
+
{ from: "#a855f7", to: "#3b82f6" },
|
|
26
|
+
// Purple → Blue
|
|
27
|
+
{ from: "#06b6d4", to: "#10b981" },
|
|
28
|
+
// Cyan → Emerald
|
|
29
|
+
// Bold combos
|
|
30
|
+
{ from: "#10b981", to: "#3b82f6" },
|
|
31
|
+
// Emerald → Blue
|
|
32
|
+
{ from: "#14b8a6", to: "#8b5cf6" },
|
|
33
|
+
// Teal → Violet
|
|
34
|
+
{ from: "#22c55e", to: "#06b6d4" },
|
|
35
|
+
// Green → Cyan
|
|
36
|
+
{ from: "#0ea5e9", to: "#f43f5e" },
|
|
37
|
+
// Sky → Rose
|
|
38
|
+
{ from: "#eab308", to: "#22c55e" }
|
|
39
|
+
// Yellow → Green
|
|
40
|
+
];
|
|
41
|
+
function hashString(str) {
|
|
42
|
+
let hash = 0;
|
|
43
|
+
for (let i = 0; i < str.length; i++) {
|
|
44
|
+
const char = str.charCodeAt(i);
|
|
45
|
+
hash = (hash << 5) - hash + char;
|
|
46
|
+
hash = hash & hash;
|
|
47
|
+
}
|
|
48
|
+
return Math.abs(hash);
|
|
49
|
+
}
|
|
50
|
+
function getAvatarGradient(userId) {
|
|
51
|
+
const index = hashString(userId) % GRADIENT_PAIRS.length;
|
|
52
|
+
const gradient = GRADIENT_PAIRS[index];
|
|
53
|
+
return {
|
|
54
|
+
from: gradient.from,
|
|
55
|
+
to: gradient.to,
|
|
56
|
+
style: {
|
|
57
|
+
background: `linear-gradient(135deg, ${gradient.from} 0%, ${gradient.to} 100%)`
|
|
58
|
+
},
|
|
59
|
+
className: "text-white"
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function getGradientIndex(userId) {
|
|
63
|
+
return hashString(userId) % GRADIENT_PAIRS.length;
|
|
64
|
+
}
|
|
65
|
+
function getGradientPairs() {
|
|
66
|
+
return GRADIENT_PAIRS;
|
|
67
|
+
}
|
|
68
|
+
var DATA_STATE_COPY = {
|
|
69
|
+
loading: {
|
|
70
|
+
title: "Loading data",
|
|
71
|
+
description: "Please wait while we prepare your finance data."
|
|
72
|
+
},
|
|
73
|
+
empty: {
|
|
74
|
+
title: "No data yet",
|
|
75
|
+
description: "There\u2019s no data for this selection yet."
|
|
76
|
+
},
|
|
77
|
+
stale: {
|
|
78
|
+
title: "Showing older data",
|
|
79
|
+
description: "This view may be out of date. Refresh to see the latest values."
|
|
80
|
+
},
|
|
81
|
+
partial: {
|
|
82
|
+
title: "Some data is missing",
|
|
83
|
+
description: "We loaded what we could, but part of this view is unavailable."
|
|
84
|
+
},
|
|
85
|
+
error: {
|
|
86
|
+
title: "Something went wrong",
|
|
87
|
+
description: "We couldn\u2019t load this data right now. Please try again."
|
|
88
|
+
},
|
|
89
|
+
unauthorized: {
|
|
90
|
+
title: "Access needed",
|
|
91
|
+
description: "You don\u2019t currently have permission to view this data."
|
|
92
|
+
},
|
|
93
|
+
misconfigured: {
|
|
94
|
+
title: "Setup required",
|
|
95
|
+
description: "This view needs additional setup before data can be shown."
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
function resolveDataState({
|
|
99
|
+
error,
|
|
100
|
+
data,
|
|
101
|
+
metadata,
|
|
102
|
+
hasData
|
|
103
|
+
}) {
|
|
104
|
+
const normalizedError = error;
|
|
105
|
+
const isUnauthorized = metadata?.isUnauthorized || normalizedError?.status === 401 || normalizedError?.status === 403 || normalizedError?.code === "unauthorized";
|
|
106
|
+
const isMisconfigured = metadata?.isMisconfigured || normalizedError?.status === 501 || normalizedError?.code === "misconfigured";
|
|
107
|
+
const computedHasData = hasData ? hasData(data) : metadata?.hasData ?? (Array.isArray(data) ? data.length > 0 : data != null && (typeof data !== "object" || Object.keys(data).length > 0));
|
|
108
|
+
if (metadata?.isLoading || metadata?.isFetching) {
|
|
109
|
+
return {
|
|
110
|
+
state: "loading",
|
|
111
|
+
retryable: false,
|
|
112
|
+
copy: DATA_STATE_COPY.loading
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (isUnauthorized) {
|
|
116
|
+
return {
|
|
117
|
+
state: "unauthorized",
|
|
118
|
+
retryable: false,
|
|
119
|
+
copy: DATA_STATE_COPY.unauthorized
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
if (isMisconfigured) {
|
|
123
|
+
return {
|
|
124
|
+
state: "misconfigured",
|
|
125
|
+
retryable: false,
|
|
126
|
+
copy: DATA_STATE_COPY.misconfigured
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
if (error) {
|
|
130
|
+
return { state: "error", retryable: true, copy: DATA_STATE_COPY.error };
|
|
131
|
+
}
|
|
132
|
+
if (metadata?.isPartial) {
|
|
133
|
+
return { state: "partial", retryable: true, copy: DATA_STATE_COPY.partial };
|
|
134
|
+
}
|
|
135
|
+
if (metadata?.isStale) {
|
|
136
|
+
return { state: "stale", retryable: true, copy: DATA_STATE_COPY.stale };
|
|
137
|
+
}
|
|
138
|
+
if (metadata?.isEmpty || !computedHasData) {
|
|
139
|
+
return { state: "empty", retryable: false, copy: DATA_STATE_COPY.empty };
|
|
140
|
+
}
|
|
141
|
+
return { state: null, retryable: false };
|
|
142
|
+
}
|
|
143
|
+
function getDataStateIcon(state) {
|
|
144
|
+
switch (state) {
|
|
145
|
+
case "loading":
|
|
146
|
+
return lucideReact.LoaderCircle;
|
|
147
|
+
case "empty":
|
|
148
|
+
return lucideReact.Database;
|
|
149
|
+
case "error":
|
|
150
|
+
case "unauthorized":
|
|
151
|
+
case "misconfigured":
|
|
152
|
+
return lucideReact.AlertCircle;
|
|
153
|
+
case "partial":
|
|
154
|
+
return lucideReact.AlertTriangle;
|
|
155
|
+
default:
|
|
156
|
+
return lucideReact.RefreshCcw;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function getDataStateIconClassName(state) {
|
|
160
|
+
switch (state) {
|
|
161
|
+
case "loading":
|
|
162
|
+
return "animate-spin";
|
|
163
|
+
case "empty":
|
|
164
|
+
return "animate-pulse";
|
|
165
|
+
default:
|
|
166
|
+
return "";
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
exports.DATA_STATE_COPY = DATA_STATE_COPY;
|
|
171
|
+
exports.getAvatarGradient = getAvatarGradient;
|
|
172
|
+
exports.getDataStateIcon = getDataStateIcon;
|
|
173
|
+
exports.getDataStateIconClassName = getDataStateIconClassName;
|
|
174
|
+
exports.getGradientIndex = getGradientIndex;
|
|
175
|
+
exports.getGradientPairs = getGradientPairs;
|
|
176
|
+
exports.resolveDataState = resolveDataState;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { cn } from './chunk-IMKLN273.mjs';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Tooltip } from 'recharts';
|
|
4
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
var ChartContext = React.createContext(null);
|
|
7
|
+
function useChart() {
|
|
8
|
+
const context = React.useContext(ChartContext);
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error("useChart must be used within a <ChartContainer />");
|
|
11
|
+
}
|
|
12
|
+
return context;
|
|
13
|
+
}
|
|
14
|
+
var ChartContainer = React.forwardRef(({ id, className, children, config, ...props }, ref) => {
|
|
15
|
+
const uniqueId = React.useId();
|
|
16
|
+
const chartId = `chart-${id || uniqueId.replace(/:/g, "")}`;
|
|
17
|
+
const containerRef = React.useRef(null);
|
|
18
|
+
const [_dimensions, setDimensions] = React.useState(null);
|
|
19
|
+
React.useImperativeHandle(ref, () => containerRef.current);
|
|
20
|
+
React.useEffect(() => {
|
|
21
|
+
const container = containerRef.current;
|
|
22
|
+
if (!container) return;
|
|
23
|
+
const updateDimensions = () => {
|
|
24
|
+
const { width, height } = container.getBoundingClientRect();
|
|
25
|
+
if (width > 0 && height > 0) {
|
|
26
|
+
setDimensions({ width: Math.floor(width), height: Math.floor(height) });
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const timeout = setTimeout(updateDimensions, 50);
|
|
30
|
+
const resizeObserver = new ResizeObserver((entries) => {
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const { width, height } = entry.contentRect;
|
|
33
|
+
if (width > 0 && height > 0) {
|
|
34
|
+
setDimensions({
|
|
35
|
+
width: Math.floor(width),
|
|
36
|
+
height: Math.floor(height)
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
resizeObserver.observe(container);
|
|
42
|
+
return () => {
|
|
43
|
+
clearTimeout(timeout);
|
|
44
|
+
resizeObserver.disconnect();
|
|
45
|
+
};
|
|
46
|
+
}, []);
|
|
47
|
+
return /* @__PURE__ */ jsx(ChartContext.Provider, { value: { config }, children: /* @__PURE__ */ jsxs(
|
|
48
|
+
"div",
|
|
49
|
+
{
|
|
50
|
+
"data-chart": chartId,
|
|
51
|
+
ref: containerRef,
|
|
52
|
+
className: cn(
|
|
53
|
+
"flex aspect-video justify-center text-xs [&_.recharts-cartesian-axis-tick_text]:fill-muted-foreground [&_.recharts-cartesian-grid_line[stroke='#ccc']]:stroke-border/50 [&_.recharts-curve.recharts-tooltip-cursor]:stroke-border [&_.recharts-dot[stroke='#fff']]:stroke-transparent [&_.recharts-layer]:outline-none [&_.recharts-polar-grid_[stroke='#ccc']]:stroke-border [&_.recharts-radial-bar-background-sector]:fill-muted [&_.recharts-rectangle.recharts-tooltip-cursor]:fill-muted [&_.recharts-reference-line_[stroke='#ccc']]:stroke-border [&_.recharts-sector[stroke='#fff']]:stroke-transparent [&_.recharts-sector]:outline-none [&_.recharts-surface]:outline-none",
|
|
54
|
+
className
|
|
55
|
+
),
|
|
56
|
+
...props,
|
|
57
|
+
children: [
|
|
58
|
+
/* @__PURE__ */ jsx(ChartStyle, { id: chartId, config }),
|
|
59
|
+
children
|
|
60
|
+
]
|
|
61
|
+
}
|
|
62
|
+
) });
|
|
63
|
+
});
|
|
64
|
+
ChartContainer.displayName = "ChartContainer";
|
|
65
|
+
var ChartStyle = ({ id, config }) => {
|
|
66
|
+
const colorConfig = Object.entries(config).filter(
|
|
67
|
+
([_, config2]) => config2.theme || config2.color
|
|
68
|
+
);
|
|
69
|
+
if (!colorConfig.length) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
return /* @__PURE__ */ jsx(
|
|
73
|
+
"style",
|
|
74
|
+
{
|
|
75
|
+
dangerouslySetInnerHTML: {
|
|
76
|
+
__html: Object.entries(config).map(([key, item]) => {
|
|
77
|
+
const color = item.theme || item.color;
|
|
78
|
+
if (color && typeof color === "string") {
|
|
79
|
+
return `
|
|
80
|
+
[data-chart=${id}] {
|
|
81
|
+
--color-${key}: ${color};
|
|
82
|
+
}
|
|
83
|
+
`;
|
|
84
|
+
}
|
|
85
|
+
if (color && typeof color === "object") {
|
|
86
|
+
return `
|
|
87
|
+
[data-chart=${id}] {
|
|
88
|
+
--color-${key}: ${color.light};
|
|
89
|
+
}
|
|
90
|
+
.dark [data-chart=${id}] {
|
|
91
|
+
--color-${key}: ${color.dark};
|
|
92
|
+
}
|
|
93
|
+
`;
|
|
94
|
+
}
|
|
95
|
+
return "";
|
|
96
|
+
}).join("\n")
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
var ChartTooltip = Tooltip;
|
|
102
|
+
var ChartTooltipContent = React.forwardRef(
|
|
103
|
+
({
|
|
104
|
+
active,
|
|
105
|
+
payload,
|
|
106
|
+
className,
|
|
107
|
+
indicator = "dot",
|
|
108
|
+
hideLabel = false,
|
|
109
|
+
hideIndicator = false,
|
|
110
|
+
label,
|
|
111
|
+
labelFormatter,
|
|
112
|
+
labelKey,
|
|
113
|
+
nameKey,
|
|
114
|
+
color
|
|
115
|
+
}, ref) => {
|
|
116
|
+
const { config } = useChart();
|
|
117
|
+
const tooltipLabel = React.useMemo(() => {
|
|
118
|
+
if (hideLabel || !payload?.length) {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
const [item] = payload;
|
|
122
|
+
const key = `${labelKey || item.dataKey || item.name || "value"}`;
|
|
123
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
124
|
+
const value = !labelKey && typeof label === "string" ? config[label]?.label || label : itemConfig?.label;
|
|
125
|
+
if (labelFormatter) {
|
|
126
|
+
return /* @__PURE__ */ jsx("div", { className: cn("font-medium", className), children: labelFormatter(value, payload) });
|
|
127
|
+
}
|
|
128
|
+
if (!value) {
|
|
129
|
+
return null;
|
|
130
|
+
}
|
|
131
|
+
return /* @__PURE__ */ jsx("div", { className: cn("font-medium", className), children: value });
|
|
132
|
+
}, [
|
|
133
|
+
label,
|
|
134
|
+
labelFormatter,
|
|
135
|
+
payload,
|
|
136
|
+
hideLabel,
|
|
137
|
+
className,
|
|
138
|
+
config,
|
|
139
|
+
labelKey
|
|
140
|
+
]);
|
|
141
|
+
if (!active || !payload?.length) {
|
|
142
|
+
return null;
|
|
143
|
+
}
|
|
144
|
+
const nestLabel = payload.length === 1 && indicator !== "dot";
|
|
145
|
+
return /* @__PURE__ */ jsxs(
|
|
146
|
+
"div",
|
|
147
|
+
{
|
|
148
|
+
ref,
|
|
149
|
+
className: cn(
|
|
150
|
+
"grid min-w-[8rem] items-start gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl",
|
|
151
|
+
className
|
|
152
|
+
),
|
|
153
|
+
children: [
|
|
154
|
+
!nestLabel ? tooltipLabel : null,
|
|
155
|
+
/* @__PURE__ */ jsx("div", { className: "grid gap-1.5", children: payload.map((item, _index) => {
|
|
156
|
+
const key = `${nameKey || item.name || item.dataKey || "value"}`;
|
|
157
|
+
const itemConfig = getPayloadConfigFromPayload(config, item, key);
|
|
158
|
+
const indicatorColor = color || item.payload?.fill || item.color;
|
|
159
|
+
return /* @__PURE__ */ jsxs(
|
|
160
|
+
"div",
|
|
161
|
+
{
|
|
162
|
+
className: cn(
|
|
163
|
+
"flex w-full flex-wrap items-stretch gap-2 [&>svg]:h-2.5 [&>svg]:w-2.5 [&>svg]:text-muted-foreground",
|
|
164
|
+
indicator === "dot" && "items-center"
|
|
165
|
+
),
|
|
166
|
+
children: [
|
|
167
|
+
itemConfig?.icon ? /* @__PURE__ */ jsx(itemConfig.icon, {}) : !hideIndicator && /* @__PURE__ */ jsx(
|
|
168
|
+
"div",
|
|
169
|
+
{
|
|
170
|
+
className: cn(
|
|
171
|
+
"shrink-0 rounded-[2px] border-[--color-border] bg-[--color-bg]",
|
|
172
|
+
{
|
|
173
|
+
"h-2.5 w-2.5": indicator === "dot",
|
|
174
|
+
"w-1": indicator === "line",
|
|
175
|
+
"w-0 border-[1.5px] border-dashed bg-transparent": indicator === "dashed",
|
|
176
|
+
"my-0.5": nestLabel && indicator === "dashed"
|
|
177
|
+
}
|
|
178
|
+
),
|
|
179
|
+
style: {
|
|
180
|
+
"--color-bg": indicatorColor,
|
|
181
|
+
"--color-border": indicatorColor
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
),
|
|
185
|
+
/* @__PURE__ */ jsxs(
|
|
186
|
+
"div",
|
|
187
|
+
{
|
|
188
|
+
className: cn(
|
|
189
|
+
"flex flex-1 justify-between leading-none",
|
|
190
|
+
nestLabel ? "items-end" : "items-center"
|
|
191
|
+
),
|
|
192
|
+
children: [
|
|
193
|
+
/* @__PURE__ */ jsxs("div", { className: "grid gap-1.5", children: [
|
|
194
|
+
nestLabel ? tooltipLabel : null,
|
|
195
|
+
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: itemConfig?.label || item.name })
|
|
196
|
+
] }),
|
|
197
|
+
item.value && /* @__PURE__ */ jsx("span", { className: "font-mono font-medium tabular-nums text-foreground", children: item.value.toLocaleString() })
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
]
|
|
202
|
+
},
|
|
203
|
+
item.dataKey
|
|
204
|
+
);
|
|
205
|
+
}) })
|
|
206
|
+
]
|
|
207
|
+
}
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
);
|
|
211
|
+
ChartTooltipContent.displayName = "ChartTooltipContent";
|
|
212
|
+
function getPayloadConfigFromPayload(config, payload, key) {
|
|
213
|
+
const payloadPayload = payload.payload;
|
|
214
|
+
let configLabelKey = key;
|
|
215
|
+
if (key in payload && typeof payload[key] === "string") {
|
|
216
|
+
configLabelKey = payload[key];
|
|
217
|
+
} else if (payloadPayload && key in payloadPayload && typeof payloadPayload[key] === "string") {
|
|
218
|
+
configLabelKey = payloadPayload[key];
|
|
219
|
+
}
|
|
220
|
+
return configLabelKey in config ? config[configLabelKey] : config[key];
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
export { ChartContainer, ChartTooltip, ChartTooltipContent };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkJAE45W2T_js = require('./chunk-JAE45W2T.js');
|
|
4
|
+
var chunk6TGV2DNP_js = require('./chunk-6TGV2DNP.js');
|
|
5
|
+
var chunkDQWHYBV2_js = require('./chunk-DQWHYBV2.js');
|
|
6
|
+
var lucideReact = require('lucide-react');
|
|
7
|
+
var react = require('react');
|
|
8
|
+
var sonner = require('sonner');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
|
|
11
|
+
var SHAKE_STYLE_ID = "newsletter-shake-keyframes";
|
|
12
|
+
function injectShakeKeyframes() {
|
|
13
|
+
if (typeof document === "undefined") return;
|
|
14
|
+
if (document.getElementById(SHAKE_STYLE_ID)) return;
|
|
15
|
+
const style = document.createElement("style");
|
|
16
|
+
style.id = SHAKE_STYLE_ID;
|
|
17
|
+
style.textContent = `
|
|
18
|
+
@keyframes shake {
|
|
19
|
+
0%, 100% { transform: translateX(0); }
|
|
20
|
+
10%, 30%, 50%, 70%, 90% { transform: translateX(-4px); }
|
|
21
|
+
20%, 40%, 60%, 80% { transform: translateX(4px); }
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
document.head.appendChild(style);
|
|
25
|
+
}
|
|
26
|
+
function NewsletterSignup({
|
|
27
|
+
className,
|
|
28
|
+
endpoint = "/api/newsletter/subscribe",
|
|
29
|
+
source,
|
|
30
|
+
placeholder = "Enter your email",
|
|
31
|
+
inputLabel = "Email address",
|
|
32
|
+
buttonLabel = "Subscribe",
|
|
33
|
+
submittingLabel = "Subscribing...",
|
|
34
|
+
successTitle = "You're subscribed!",
|
|
35
|
+
successDescription = "Check your email to confirm.",
|
|
36
|
+
errorMessage = "Something went wrong. Please try again.",
|
|
37
|
+
inputClassName,
|
|
38
|
+
buttonClassName,
|
|
39
|
+
successClassName
|
|
40
|
+
}) {
|
|
41
|
+
const [email, setEmail] = react.useState("");
|
|
42
|
+
const [isSubmitting, setIsSubmitting] = react.useState(false);
|
|
43
|
+
const [submitted, setSubmitted] = react.useState(false);
|
|
44
|
+
const [hasError, setHasError] = react.useState(false);
|
|
45
|
+
react.useEffect(() => {
|
|
46
|
+
injectShakeKeyframes();
|
|
47
|
+
}, []);
|
|
48
|
+
const handleSubmit = async (e) => {
|
|
49
|
+
e.preventDefault();
|
|
50
|
+
if (!email) return;
|
|
51
|
+
setIsSubmitting(true);
|
|
52
|
+
setHasError(false);
|
|
53
|
+
try {
|
|
54
|
+
const response = await fetch(endpoint, {
|
|
55
|
+
method: "POST",
|
|
56
|
+
headers: { "Content-Type": "application/json" },
|
|
57
|
+
body: JSON.stringify({ email, source })
|
|
58
|
+
});
|
|
59
|
+
if (response.ok) {
|
|
60
|
+
setSubmitted(true);
|
|
61
|
+
setEmail("");
|
|
62
|
+
} else {
|
|
63
|
+
const data = await response.json();
|
|
64
|
+
sonner.toast.error(data.error || errorMessage);
|
|
65
|
+
setHasError(true);
|
|
66
|
+
setTimeout(() => setHasError(false), 500);
|
|
67
|
+
}
|
|
68
|
+
} catch {
|
|
69
|
+
sonner.toast.error(
|
|
70
|
+
"Unable to connect. Please check your connection and try again."
|
|
71
|
+
);
|
|
72
|
+
setHasError(true);
|
|
73
|
+
setTimeout(() => setHasError(false), 500);
|
|
74
|
+
} finally {
|
|
75
|
+
setIsSubmitting(false);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
if (submitted) {
|
|
79
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
80
|
+
"div",
|
|
81
|
+
{
|
|
82
|
+
className: chunkJAE45W2T_js.cx(
|
|
83
|
+
"flex items-center justify-center gap-3 rounded-box border border-border px-4 py-3",
|
|
84
|
+
className,
|
|
85
|
+
successClassName
|
|
86
|
+
),
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground animate-in zoom-in duration-300", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
89
|
+
lucideReact.Check,
|
|
90
|
+
{
|
|
91
|
+
className: "h-4 w-4 animate-in fade-in duration-500 delay-150",
|
|
92
|
+
strokeWidth: 3
|
|
93
|
+
}
|
|
94
|
+
) }),
|
|
95
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "animate-in slide-in-from-left-2 fade-in duration-300 delay-100 text-left", children: [
|
|
96
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-foreground", children: successTitle }),
|
|
97
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-muted-foreground", children: successDescription })
|
|
98
|
+
] })
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
104
|
+
"form",
|
|
105
|
+
{
|
|
106
|
+
onSubmit: handleSubmit,
|
|
107
|
+
className: chunkJAE45W2T_js.cx("flex", hasError && "animate-shake", className),
|
|
108
|
+
style: hasError ? { animation: "shake 0.5s ease-in-out" } : void 0,
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
111
|
+
chunkDQWHYBV2_js.Input,
|
|
112
|
+
{
|
|
113
|
+
"aria-label": inputLabel,
|
|
114
|
+
type: "email",
|
|
115
|
+
placeholder,
|
|
116
|
+
value: email,
|
|
117
|
+
onChange: (e) => setEmail(e.target.value),
|
|
118
|
+
required: true,
|
|
119
|
+
className: chunkJAE45W2T_js.cx(
|
|
120
|
+
"flex-1 rounded-r-none border-r-0 focus-visible:z-10",
|
|
121
|
+
inputClassName
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
),
|
|
125
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
126
|
+
chunk6TGV2DNP_js.Button,
|
|
127
|
+
{
|
|
128
|
+
type: "submit",
|
|
129
|
+
disabled: isSubmitting || !email,
|
|
130
|
+
className: chunkJAE45W2T_js.cx("rounded-l-none", buttonClassName),
|
|
131
|
+
children: [
|
|
132
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Mail, { className: "mr-2 h-4 w-4" }),
|
|
133
|
+
isSubmitting ? submittingLabel : buttonLabel
|
|
134
|
+
]
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
exports.NewsletterSignup = NewsletterSignup;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/hooks/useScrollDirection.ts
|
|
6
|
+
function useScrollDirection({
|
|
7
|
+
threshold = 10,
|
|
8
|
+
topThreshold = 50
|
|
9
|
+
} = {}) {
|
|
10
|
+
const [direction, setDirection] = react.useState(null);
|
|
11
|
+
const [isAtTop, setIsAtTop] = react.useState(true);
|
|
12
|
+
const lastScrollY = react.useRef(0);
|
|
13
|
+
const ticking = react.useRef(false);
|
|
14
|
+
const updateScrollDirection = react.useCallback(() => {
|
|
15
|
+
const scrollY = window.scrollY;
|
|
16
|
+
setIsAtTop(scrollY < topThreshold);
|
|
17
|
+
const diff = scrollY - lastScrollY.current;
|
|
18
|
+
if (Math.abs(diff) >= threshold) {
|
|
19
|
+
setDirection(diff > 0 ? "down" : "up");
|
|
20
|
+
lastScrollY.current = scrollY;
|
|
21
|
+
}
|
|
22
|
+
ticking.current = false;
|
|
23
|
+
}, [threshold, topThreshold]);
|
|
24
|
+
const onScroll = react.useCallback(() => {
|
|
25
|
+
if (!ticking.current) {
|
|
26
|
+
window.requestAnimationFrame(updateScrollDirection);
|
|
27
|
+
ticking.current = true;
|
|
28
|
+
}
|
|
29
|
+
}, [updateScrollDirection]);
|
|
30
|
+
react.useEffect(() => {
|
|
31
|
+
lastScrollY.current = window.scrollY;
|
|
32
|
+
setIsAtTop(window.scrollY < topThreshold);
|
|
33
|
+
window.addEventListener("scroll", onScroll, { passive: true });
|
|
34
|
+
return () => window.removeEventListener("scroll", onScroll);
|
|
35
|
+
}, [onScroll, topThreshold]);
|
|
36
|
+
return { direction, isAtTop };
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
exports.useScrollDirection = useScrollDirection;
|