react-marketing-ui 0.0.2 → 0.0.4
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/accordion.js +1 -1
- package/dist/accordion.js.map +1 -1
- package/dist/accordion.mjs +222 -2
- package/dist/accordion.mjs.map +1 -1
- package/dist/action-swap.js +1 -0
- package/dist/action-swap.mjs +77 -3
- package/dist/action-swap.mjs.map +1 -1
- package/dist/animated-beam.js +1 -0
- package/dist/animated-beam.mjs +127 -2
- package/dist/animated-beam.mjs.map +1 -1
- package/dist/button.js +1 -1
- package/dist/button.js.map +1 -1
- package/dist/button.mjs +115 -2
- package/dist/button.mjs.map +1 -1
- package/dist/card.js +1 -2
- package/dist/card.js.map +1 -1
- package/dist/card.mjs +135 -3
- package/dist/card.mjs.map +1 -1
- package/dist/dia-text-reveal.js +1 -0
- package/dist/dia-text-reveal.mjs +331 -2
- package/dist/dia-text-reveal.mjs.map +1 -1
- package/dist/elevated-input.js +1 -1
- package/dist/elevated-input.js.map +1 -1
- package/dist/elevated-input.mjs +48 -2
- package/dist/elevated-input.mjs.map +1 -1
- package/dist/fade-in.js +1 -0
- package/dist/fade-in.mjs +84 -2
- package/dist/fade-in.mjs.map +1 -1
- package/dist/feature-card.js +1 -1
- package/dist/feature-card.js.map +1 -1
- package/dist/feature-card.mjs +34 -2
- package/dist/feature-card.mjs.map +1 -1
- package/dist/flowchart-parts.js +1 -1
- package/dist/flowchart-parts.js.map +1 -1
- package/dist/flowchart-parts.mjs +91 -2
- package/dist/flowchart-parts.mjs.map +1 -1
- package/dist/glossy-button.js +1 -1
- package/dist/glossy-button.js.map +1 -1
- package/dist/glossy-button.mjs +82 -2
- package/dist/glossy-button.mjs.map +1 -1
- package/dist/grainient.js +1 -0
- package/dist/grainient.mjs +327 -2
- package/dist/grainient.mjs.map +1 -1
- package/dist/highlighter.js +1 -0
- package/dist/highlighter.mjs +122 -3
- package/dist/highlighter.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2642 -32
- package/dist/index.mjs.map +1 -1
- package/dist/input.js +1 -0
- package/dist/input.mjs +107 -2
- package/dist/input.mjs.map +1 -1
- package/dist/lib/breakpoints.js +1 -1
- package/dist/lib/breakpoints.js.map +1 -1
- package/dist/lib/breakpoints.mjs +34 -1
- package/dist/lib/breakpoints.mjs.map +1 -1
- package/dist/lib/cn.js +1 -1
- package/dist/lib/cn.js.map +1 -1
- package/dist/lib/cn.mjs +17 -1
- package/dist/lib/cn.mjs.map +1 -1
- package/dist/lib/ease.js +1 -0
- package/dist/lib/ease.mjs +9 -1
- package/dist/lib/ease.mjs.map +1 -1
- package/dist/lib/surface.js +1 -0
- package/dist/lib/surface.mjs +37 -1
- package/dist/lib/surface.mjs.map +1 -1
- package/dist/lib/use-media-query.js +1 -0
- package/dist/lib/use-media-query.mjs +16 -1
- package/dist/lib/use-media-query.mjs.map +1 -1
- package/dist/liquid-metal.js +1 -0
- package/dist/liquid-metal.mjs +40 -2
- package/dist/liquid-metal.mjs.map +1 -1
- package/dist/navigation-menu-icons.js +1 -1
- package/dist/navigation-menu-icons.js.map +1 -1
- package/dist/navigation-menu-icons.mjs +36 -1
- package/dist/navigation-menu-icons.mjs.map +1 -1
- package/dist/navigation-menu-styles.js +1 -1
- package/dist/navigation-menu-styles.js.map +1 -1
- package/dist/navigation-menu-styles.mjs +11 -1
- package/dist/navigation-menu-styles.mjs.map +1 -1
- package/dist/navigation-menu.js +1 -2
- package/dist/navigation-menu.js.map +1 -1
- package/dist/navigation-menu.mjs +350 -5
- package/dist/navigation-menu.mjs.map +1 -1
- package/dist/password-input.js +1 -0
- package/dist/password-input.mjs +171 -3
- package/dist/password-input.mjs.map +1 -1
- package/dist/rainbow-button.js +1 -0
- package/dist/rainbow-button.mjs +45 -2
- package/dist/rainbow-button.mjs.map +1 -1
- package/dist/range-slider.js +1 -0
- package/dist/range-slider.mjs +82 -1
- package/dist/range-slider.mjs.map +1 -1
- package/dist/rolling-badge.js +1 -0
- package/dist/rolling-badge.mjs +68 -2
- package/dist/rolling-badge.mjs.map +1 -1
- package/dist/savings-badge.js +1 -1
- package/dist/savings-badge.js.map +1 -1
- package/dist/savings-badge.mjs +22 -2
- package/dist/savings-badge.mjs.map +1 -1
- package/dist/shine-border.js +1 -0
- package/dist/shine-border.mjs +44 -2
- package/dist/shine-border.mjs.map +1 -1
- package/dist/sparkles-text.js +1 -0
- package/dist/sparkles-text.mjs +84 -3
- package/dist/sparkles-text.mjs.map +1 -1
- package/dist/tabs.js +1 -0
- package/dist/tabs.mjs +118 -2
- package/dist/tabs.mjs.map +1 -1
- package/dist/theme-toggle.js +1 -0
- package/dist/theme-toggle.mjs +248 -5
- package/dist/theme-toggle.mjs.map +1 -1
- package/package.json +68 -68
- package/dist/chunk-3SB6HUBA.mjs +0 -31
- package/dist/chunk-3SB6HUBA.mjs.map +0 -1
- package/dist/chunk-4PBVBXGY.mjs +0 -84
- package/dist/chunk-4PBVBXGY.mjs.map +0 -1
- package/dist/chunk-4VCFWVSJ.mjs +0 -42
- package/dist/chunk-4VCFWVSJ.mjs.map +0 -1
- package/dist/chunk-5QQAPGR2.mjs +0 -109
- package/dist/chunk-5QQAPGR2.mjs.map +0 -1
- package/dist/chunk-6MB4UKRX.mjs +0 -19
- package/dist/chunk-6MB4UKRX.mjs.map +0 -1
- package/dist/chunk-6T5LR34O.mjs +0 -45
- package/dist/chunk-6T5LR34O.mjs.map +0 -1
- package/dist/chunk-AYLCYDUM.mjs +0 -275
- package/dist/chunk-AYLCYDUM.mjs.map +0 -1
- package/dist/chunk-AYY7D2RJ.mjs +0 -112
- package/dist/chunk-AYY7D2RJ.mjs.map +0 -1
- package/dist/chunk-CTZEI2YS.mjs +0 -324
- package/dist/chunk-CTZEI2YS.mjs.map +0 -1
- package/dist/chunk-DA3I3Y5O.mjs +0 -71
- package/dist/chunk-DA3I3Y5O.mjs.map +0 -1
- package/dist/chunk-EYHT2EWJ.mjs +0 -18
- package/dist/chunk-EYHT2EWJ.mjs.map +0 -1
- package/dist/chunk-IHLGCS63.mjs +0 -36
- package/dist/chunk-IHLGCS63.mjs.map +0 -1
- package/dist/chunk-JVXJ6SFX.mjs +0 -38
- package/dist/chunk-JVXJ6SFX.mjs.map +0 -1
- package/dist/chunk-KBHYXLRG.mjs +0 -13
- package/dist/chunk-KBHYXLRG.mjs.map +0 -1
- package/dist/chunk-KMXUQYR3.mjs +0 -74
- package/dist/chunk-KMXUQYR3.mjs.map +0 -1
- package/dist/chunk-KNPOZ34H.mjs +0 -88
- package/dist/chunk-KNPOZ34H.mjs.map +0 -1
- package/dist/chunk-KRNWCJ4D.mjs +0 -219
- package/dist/chunk-KRNWCJ4D.mjs.map +0 -1
- package/dist/chunk-M5MESV26.mjs +0 -124
- package/dist/chunk-M5MESV26.mjs.map +0 -1
- package/dist/chunk-MJYBPJBA.mjs +0 -115
- package/dist/chunk-MJYBPJBA.mjs.map +0 -1
- package/dist/chunk-NNHPQ67J.mjs +0 -10
- package/dist/chunk-NNHPQ67J.mjs.map +0 -1
- package/dist/chunk-OCZFHVVD.mjs +0 -71
- package/dist/chunk-OCZFHVVD.mjs.map +0 -1
- package/dist/chunk-QAWSH567.mjs +0 -19
- package/dist/chunk-QAWSH567.mjs.map +0 -1
- package/dist/chunk-R2E2J42H.mjs +0 -38
- package/dist/chunk-R2E2J42H.mjs.map +0 -1
- package/dist/chunk-TPGLLSYV.mjs +0 -65
- package/dist/chunk-TPGLLSYV.mjs.map +0 -1
- package/dist/chunk-VJENJHXJ.mjs +0 -72
- package/dist/chunk-VJENJHXJ.mjs.map +0 -1
- package/dist/chunk-W22G7XHR.mjs +0 -104
- package/dist/chunk-W22G7XHR.mjs.map +0 -1
- package/dist/chunk-WDR5VPZJ.mjs +0 -79
- package/dist/chunk-WDR5VPZJ.mjs.map +0 -1
- package/dist/chunk-WLUGKBH7.mjs +0 -37
- package/dist/chunk-WLUGKBH7.mjs.map +0 -1
- package/dist/chunk-WYJYLDUA.mjs +0 -84
- package/dist/chunk-WYJYLDUA.mjs.map +0 -1
- package/dist/chunk-XZEDZVXT.mjs +0 -38
- package/dist/chunk-XZEDZVXT.mjs.map +0 -1
- package/dist/chunk-YKGP5JIL.mjs +0 -328
- package/dist/chunk-YKGP5JIL.mjs.map +0 -1
- package/dist/chunk-YM3U2OBE.mjs +0 -99
- package/dist/chunk-YM3U2OBE.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,34 +1,2644 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { Accordion as Accordion$1 } from '@base-ui/react/accordion';
|
|
3
|
+
import { clsx } from 'clsx';
|
|
4
|
+
import { twMerge } from 'tailwind-merge';
|
|
5
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
+
import { useReducedMotion, AnimatePresence, motion, useInView, useSpring, useTransform } from 'framer-motion';
|
|
7
|
+
import { createContext, useRef, useState, useLayoutEffect, useId, useEffect, useMemo, useCallback, useContext, useSyncExternalStore } from 'react';
|
|
8
|
+
import { cva } from 'class-variance-authority';
|
|
9
|
+
import { Renderer, Triangle, Mesh, Program } from 'ogl';
|
|
10
|
+
import { annotate } from 'rough-notation';
|
|
11
|
+
import { LiquidMetal as LiquidMetal$1 } from '@paper-design/shaders-react';
|
|
12
|
+
import { NavigationMenu as NavigationMenu$1 } from '@base-ui/react/navigation-menu';
|
|
13
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
14
|
+
|
|
15
|
+
function cn(...inputs) {
|
|
16
|
+
return twMerge(clsx(inputs));
|
|
17
|
+
}
|
|
18
|
+
function validCssVars(style) {
|
|
19
|
+
return style;
|
|
20
|
+
}
|
|
21
|
+
function hasKey(key, obj) {
|
|
22
|
+
return obj !== null && typeof obj === "object" && Object.hasOwn(obj, key);
|
|
23
|
+
}
|
|
24
|
+
function noop() {
|
|
25
|
+
}
|
|
26
|
+
function Accordion({
|
|
27
|
+
className,
|
|
28
|
+
multiple = false,
|
|
29
|
+
variant = "default",
|
|
30
|
+
...props
|
|
31
|
+
}) {
|
|
32
|
+
return /* @__PURE__ */ jsx(
|
|
33
|
+
Accordion$1.Root,
|
|
34
|
+
{
|
|
35
|
+
"data-slot": "accordion",
|
|
36
|
+
"data-variant": variant,
|
|
37
|
+
multiple,
|
|
38
|
+
className: cn(
|
|
39
|
+
"group flex w-full flex-col",
|
|
40
|
+
variant === "split" && "space-y-2",
|
|
41
|
+
variant === "outline" && "overflow-hidden rounded-lg border bg-(--surface)",
|
|
42
|
+
variant === "nested" && "rounded-lg border bg-muted p-1",
|
|
43
|
+
className
|
|
44
|
+
),
|
|
45
|
+
...props
|
|
46
|
+
}
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
function AccordionItem({ className, ...props }) {
|
|
50
|
+
return /* @__PURE__ */ jsx(
|
|
51
|
+
Accordion$1.Item,
|
|
52
|
+
{
|
|
53
|
+
"data-slot": "accordion-item",
|
|
54
|
+
className: cn(
|
|
55
|
+
"transition-[margin,border-radius,border] duration-250 ease-out-expo",
|
|
56
|
+
// Default variant styles
|
|
57
|
+
"group-data-[variant=default]:border-(--border) group-data-[variant=default]:border-b group-data-[variant=default]:last:border-b-0",
|
|
58
|
+
// Split variant styles (individual cards)
|
|
59
|
+
"group-data-[variant=split]:overflow-hidden group-data-[variant=split]:rounded-lg group-data-[variant=split]:border group-data-[variant=split]:border-(--border) group-data-[variant=split]:bg-(--surface)",
|
|
60
|
+
// Outline variant styles (items within single card)
|
|
61
|
+
"group-data-[variant=outline]:border-(--border) group-data-[variant=outline]:border-b group-data-[variant=outline]:last:border-b-0",
|
|
62
|
+
// Nested variant styles - items within the single outer card
|
|
63
|
+
"group-data-[variant=nested]:mt-0.5 group-data-[variant=nested]:first:mt-0",
|
|
64
|
+
// Isolated bordered variant styles - dynamically separates open items from closed ones
|
|
65
|
+
// Base styles: all items have borders and background to look like cards
|
|
66
|
+
"group-data-[variant=isolated-bordered]:overflow-hidden group-data-[variant=isolated-bordered]:border group-data-[variant=isolated-bordered]:border-(--border) group-data-[variant=isolated-bordered]:bg-(--surface)",
|
|
67
|
+
// Closed items: group together by overlapping borders with negative margin
|
|
68
|
+
// Only apply to closed items that follow another closed item (not open items, first item, or items after open items)
|
|
69
|
+
"group-data-[variant=isolated-bordered]:relative group-data-[variant=isolated-bordered]:not-first:not-data-open:not-[[data-open]+&]:-mt-px",
|
|
70
|
+
// Opened item - separated with margins
|
|
71
|
+
"group-data-[variant=isolated-bordered]:data-open:mt-2 group-data-[variant=isolated-bordered]:data-open:mb-2 group-data-[variant=isolated-bordered]:data-open:rounded-lg",
|
|
72
|
+
// First item
|
|
73
|
+
"group-data-[variant=isolated-bordered]:first:rounded-t-lg group-data-[variant=isolated-bordered]:data-open:first:mt-0",
|
|
74
|
+
// Last item
|
|
75
|
+
"group-data-[variant=isolated-bordered]:last:rounded-b-lg group-data-[variant=isolated-bordered]:data-open:last:mb-0",
|
|
76
|
+
// Item after open item: round top corners (start of new group)
|
|
77
|
+
"group-data-[variant=isolated-bordered]:[[data-open]+&]:rounded-t-lg",
|
|
78
|
+
// Item before open item: round bottom corners (end of group)
|
|
79
|
+
"group-data-[variant=isolated-bordered]:[&:has(+_[data-open])]:rounded-b-lg",
|
|
80
|
+
// Isolated filled variant
|
|
81
|
+
"group-data-[variant=isolated-filled]:overflow-hidden group-data-[variant=isolated-filled]:bg-muted",
|
|
82
|
+
// Opened item - separated with margins and rounded
|
|
83
|
+
"group-data-[variant=isolated-filled]:data-open:my-2 group-data-[variant=isolated-filled]:data-open:rounded-lg",
|
|
84
|
+
// First item
|
|
85
|
+
"group-data-[variant=isolated-filled]:first:rounded-t-lg group-data-[variant=isolated-filled]:data-open:first:mt-0",
|
|
86
|
+
// Last item
|
|
87
|
+
"group-data-[variant=isolated-filled]:last:rounded-b-lg group-data-[variant=isolated-filled]:data-open:last:mb-0",
|
|
88
|
+
// Item after open item: round top corners (start of new group)
|
|
89
|
+
"group-data-[variant=isolated-filled]:[[data-open]+&]:rounded-t-lg",
|
|
90
|
+
// Item before open item: round bottom corners (end of group)
|
|
91
|
+
"group-data-[variant=isolated-filled]:[&:has(+_[data-open])]:rounded-b-lg",
|
|
92
|
+
// Isolated filled bordered variant - filled background with borders between closed items
|
|
93
|
+
"group-data-[variant=isolated-filled-bordered]:overflow-hidden group-data-[variant=isolated-filled-bordered]:bg-muted",
|
|
94
|
+
// All items except last have border-bottom to prevent layout shift, default to visible border
|
|
95
|
+
"group-data-[variant=isolated-filled-bordered]:not-last:border-(--border) group-data-[variant=isolated-filled-bordered]:not-last:border-b",
|
|
96
|
+
// Make border transparent (invisible) for: items before open items, and open items themselves
|
|
97
|
+
"group-data-[variant=isolated-filled-bordered]:[&:has(+_[data-open])]:border-transparent",
|
|
98
|
+
"group-data-[variant=isolated-filled-bordered]:data-open:border-transparent",
|
|
99
|
+
// Opened item - separated with margins and rounded
|
|
100
|
+
"group-data-[variant=isolated-filled-bordered]:data-open:my-2 group-data-[variant=isolated-filled-bordered]:data-open:rounded-lg",
|
|
101
|
+
// First item
|
|
102
|
+
"group-data-[variant=isolated-filled-bordered]:first:rounded-t-lg group-data-[variant=isolated-filled-bordered]:data-open:first:mt-0",
|
|
103
|
+
// Last item
|
|
104
|
+
"group-data-[variant=isolated-filled-bordered]:last:rounded-b-lg group-data-[variant=isolated-filled-bordered]:data-open:last:mb-0",
|
|
105
|
+
// Item after open item: round top corners (start of new group)
|
|
106
|
+
"group-data-[variant=isolated-filled-bordered]:[[data-open]+&]:rounded-t-lg",
|
|
107
|
+
// Item before open item: round bottom corners (end of group)
|
|
108
|
+
"group-data-[variant=isolated-filled-bordered]:[&:has(+_[data-open])]:rounded-b-lg",
|
|
109
|
+
className
|
|
110
|
+
),
|
|
111
|
+
...props
|
|
112
|
+
}
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
function AccordionHeader({ className, ...props }) {
|
|
116
|
+
return /* @__PURE__ */ jsx(
|
|
117
|
+
Accordion$1.Header,
|
|
118
|
+
{
|
|
119
|
+
"data-slot": "accordion-header",
|
|
120
|
+
className: cn("not-prose", className),
|
|
121
|
+
...props
|
|
122
|
+
}
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
function AccordionTrigger({
|
|
126
|
+
children,
|
|
127
|
+
className,
|
|
128
|
+
showIndicator = true,
|
|
129
|
+
indicatorType = "plus",
|
|
130
|
+
indicatorPosition = "end",
|
|
131
|
+
indicatorColor,
|
|
132
|
+
icon,
|
|
133
|
+
subtitle,
|
|
134
|
+
...props
|
|
135
|
+
}) {
|
|
136
|
+
const hasStartIndicator = showIndicator && indicatorPosition === "start";
|
|
137
|
+
const hasEndIndicator = showIndicator && indicatorPosition === "end";
|
|
138
|
+
const renderIndicator = () => {
|
|
139
|
+
if (!showIndicator) return null;
|
|
140
|
+
const indicatorClassName = cn("size-4 shrink-0 transition-transform duration-200 ease-out-expo", indicatorColor);
|
|
141
|
+
const indicatorIcon = indicatorType === "chevron" ? /* @__PURE__ */ jsx(ChevronDownIcon, { "data-slot": "accordion-indicator", className: indicatorClassName }) : /* @__PURE__ */ jsx(PlusIcon, { "data-slot": "accordion-indicator", className: indicatorClassName });
|
|
142
|
+
return /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: indicatorIcon });
|
|
143
|
+
};
|
|
144
|
+
return /* @__PURE__ */ jsx(AccordionHeader, { children: /* @__PURE__ */ jsxs(
|
|
145
|
+
Accordion$1.Trigger,
|
|
146
|
+
{
|
|
147
|
+
"data-slot": "accordion-trigger",
|
|
148
|
+
"data-has-icon": hasStartIndicator ? "true" : void 0,
|
|
149
|
+
className: cn(
|
|
150
|
+
"group/trigger flex w-full cursor-pointer items-center justify-between gap-3 py-5 px-3.5 text-left font-medium text-sm outline-none disabled:pointer-events-none disabled:opacity-60",
|
|
151
|
+
// Default variant styles
|
|
152
|
+
"group-data-[variant=default]:px-0",
|
|
153
|
+
// Split variant styles
|
|
154
|
+
"group-data-[variant=split]:rounded-t-lg",
|
|
155
|
+
// Nested variant styles - trigger with subtle interaction
|
|
156
|
+
"group-data-[variant=nested]:rounded-sm group-data-[variant=nested]:px-3 group-data-[variant=nested]:py-2.5 group-data-[variant=nested]:hover:bg-background group-data-[variant=nested]:dark:hover:bg-background/50",
|
|
157
|
+
// Indicator rotation animations
|
|
158
|
+
indicatorType === "chevron" && "[&[data-panel-open]_[data-slot=accordion-indicator]]:rotate-180",
|
|
159
|
+
indicatorType === "plus" && "[&[data-panel-open]_[data-slot=accordion-indicator]]:rotate-90",
|
|
160
|
+
className
|
|
161
|
+
),
|
|
162
|
+
...props,
|
|
163
|
+
children: [
|
|
164
|
+
hasStartIndicator ? renderIndicator() : null,
|
|
165
|
+
icon && !hasStartIndicator && /* @__PURE__ */ jsx("span", { className: "shrink-0 text-muted-foreground", "aria-hidden": "true", children: icon }),
|
|
166
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-0.5", children: [
|
|
167
|
+
/* @__PURE__ */ jsx("span", { className: "underline-offset-2 group-hover/trigger:underline", children }),
|
|
168
|
+
subtitle ? /* @__PURE__ */ jsx("span", { className: "text-muted-foreground text-sm no-underline", children: subtitle }) : null
|
|
169
|
+
] }),
|
|
170
|
+
hasEndIndicator ? renderIndicator() : null
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
) });
|
|
174
|
+
}
|
|
175
|
+
function AccordionContent({ children, className, ...props }) {
|
|
176
|
+
return /* @__PURE__ */ jsx(
|
|
177
|
+
Accordion$1.Panel,
|
|
178
|
+
{
|
|
179
|
+
"data-slot": "accordion-content",
|
|
180
|
+
className: cn(
|
|
181
|
+
"h-(--accordion-panel-height) overflow-hidden text-sm transition-[height,opacity] duration-250 ease-out-expo data-ending-style:h-0 data-starting-style:h-0 data-ending-style:opacity-0 data-starting-style:opacity-0"
|
|
182
|
+
),
|
|
183
|
+
...props,
|
|
184
|
+
children: /* @__PURE__ */ jsx(
|
|
185
|
+
"div",
|
|
186
|
+
{
|
|
187
|
+
className: cn(
|
|
188
|
+
"p-3.5 text-muted-foreground",
|
|
189
|
+
"group-data-[variant=default]:px-0 group-data-[variant=default]:pt-0",
|
|
190
|
+
"group-data-[variant=split]:pt-0",
|
|
191
|
+
"group-data-[variant=outline]:pt-0",
|
|
192
|
+
// Nested variant
|
|
193
|
+
"group-data-[variant=nested]:mt-1 group-data-[variant=nested]:mb-0.5 group-data-[variant=nested]:rounded-sm group-data-[variant=nested]:border group-data-[variant=nested]:bg-background group-data-[variant=nested]:p-3 group-data-[variant=nested]:[[data-slot=accordion-item]:last-child_&]:mb-0",
|
|
194
|
+
// Isolated bordered variant
|
|
195
|
+
"group-data-[variant=isolated-bordered]:pt-0",
|
|
196
|
+
// Isolated filled variant
|
|
197
|
+
"group-data-[variant=isolated-filled]:pt-0",
|
|
198
|
+
// Isolated filled bordered variant
|
|
199
|
+
"group-data-[variant=isolated-filled-bordered]:pt-0",
|
|
200
|
+
// Icon alignment - add left padding when parent item contains a trigger with icon
|
|
201
|
+
"[[data-slot=accordion-item]:has([data-has-icon])_&]:pl-[calc(1rem+0.75rem)]",
|
|
202
|
+
"[[data-slot=accordion-item]:has([data-has-icon])_&]:group-data-[variant=default]:pl-[calc(1rem+0.75rem)]",
|
|
203
|
+
className
|
|
204
|
+
),
|
|
205
|
+
children
|
|
206
|
+
}
|
|
207
|
+
)
|
|
208
|
+
}
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
function PlusIcon(props) {
|
|
212
|
+
return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", viewBox: "0 0 24 24", fill: "none", ...props, children: [
|
|
213
|
+
/* @__PURE__ */ jsx(
|
|
214
|
+
"path",
|
|
215
|
+
{
|
|
216
|
+
fillRule: "evenodd",
|
|
217
|
+
clipRule: "evenodd",
|
|
218
|
+
d: "M2.75 12C2.75 11.3096 3.30964 10.75 4 10.75H20C20.6904 10.75 21.25 11.3096 21.25 12C21.25 12.6904 20.6904 13.25 20 13.25H4C3.30964 13.25 2.75 12.6904 2.75 12Z",
|
|
219
|
+
fill: "currentColor",
|
|
220
|
+
className: "in-data-panel-open:opacity-0 transition-opacity duration-200 ease-out-expo"
|
|
221
|
+
}
|
|
222
|
+
),
|
|
223
|
+
/* @__PURE__ */ jsx(
|
|
224
|
+
"path",
|
|
225
|
+
{
|
|
226
|
+
fillRule: "evenodd",
|
|
227
|
+
clipRule: "evenodd",
|
|
228
|
+
d: "M12 2.75C12.6904 2.75 13.25 3.30964 13.25 4V20C13.25 20.6904 12.6904 21.25 12 21.25C11.3096 21.25 10.75 20.6904 10.75 20V4C10.75 3.30964 11.3096 2.75 12 2.75Z",
|
|
229
|
+
fill: "currentColor"
|
|
230
|
+
}
|
|
231
|
+
)
|
|
232
|
+
] });
|
|
233
|
+
}
|
|
234
|
+
function ChevronDownIcon(props) {
|
|
235
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", ...props, children: /* @__PURE__ */ jsx("path", { d: "M1 3.5L5 7.5L9 3.5", stroke: "currentColor", strokeWidth: "1.5" }) });
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/lib/ease.ts
|
|
239
|
+
var easeOut = [0.22, 1, 0.36, 1];
|
|
240
|
+
var easeOutBack = [0.34, 1.56, 0.64, 1];
|
|
241
|
+
var EASE_OUT = [0.16, 1, 0.3, 1];
|
|
242
|
+
var EASE_OUT_CSS = "cubic-bezier(0.16, 1, 0.3, 1)";
|
|
243
|
+
var SPRING_SWAP = { type: "spring", stiffness: 460, damping: 30, mass: 0.55 };
|
|
244
|
+
var ROLL_EXIT_TRANSITION = { duration: 0.14, ease: EASE_OUT };
|
|
245
|
+
var ROLL_BLUR = "blur(3px)";
|
|
246
|
+
var AT_REST = { opacity: 1, y: 0, filter: "blur(0px)" };
|
|
247
|
+
var TEXT_VARIANTS = {
|
|
248
|
+
initial: { opacity: 0, y: "90%", filter: ROLL_BLUR },
|
|
249
|
+
animate: { opacity: 1, y: "0%", filter: "blur(0px)", transition: SPRING_SWAP },
|
|
250
|
+
exit: { opacity: 0, y: "-90%", filter: ROLL_BLUR, transition: ROLL_EXIT_TRANSITION }
|
|
251
|
+
};
|
|
252
|
+
var ICON_VARIANTS = {
|
|
253
|
+
initial: { opacity: 0, y: 12, filter: ROLL_BLUR },
|
|
254
|
+
animate: { opacity: 1, y: 0, filter: "blur(0px)", transition: SPRING_SWAP },
|
|
255
|
+
exit: { opacity: 0, y: -12, filter: ROLL_BLUR, transition: ROLL_EXIT_TRANSITION }
|
|
256
|
+
};
|
|
257
|
+
function ActionSwapRollText({ value, children, className }) {
|
|
258
|
+
const reduce = useReducedMotion() ?? false;
|
|
259
|
+
const measureRef = useRef(null);
|
|
260
|
+
const [width, setWidth] = useState();
|
|
261
|
+
useLayoutEffect(() => {
|
|
262
|
+
const nextWidth = measureRef.current?.offsetWidth;
|
|
263
|
+
if (!nextWidth) return;
|
|
264
|
+
setWidth((current) => current === nextWidth ? current : nextWidth);
|
|
265
|
+
});
|
|
266
|
+
return /* @__PURE__ */ jsxs(
|
|
267
|
+
"span",
|
|
268
|
+
{
|
|
269
|
+
className: cn("relative inline-block overflow-hidden whitespace-nowrap align-bottom", className),
|
|
270
|
+
style: { width, transition: reduce ? void 0 : `width 220ms ${EASE_OUT_CSS}` },
|
|
271
|
+
children: [
|
|
272
|
+
/* @__PURE__ */ jsx("span", { ref: measureRef, "aria-hidden": true, className: "invisible inline-block whitespace-nowrap", children }),
|
|
273
|
+
/* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: /* @__PURE__ */ jsx(
|
|
274
|
+
motion.span,
|
|
275
|
+
{
|
|
276
|
+
variants: TEXT_VARIANTS,
|
|
277
|
+
initial: reduce ? false : "initial",
|
|
278
|
+
animate: reduce ? AT_REST : "animate",
|
|
279
|
+
exit: reduce ? void 0 : "exit",
|
|
280
|
+
className: "absolute top-0 left-0 inline-block will-change-[opacity,filter,transform]",
|
|
281
|
+
children
|
|
282
|
+
},
|
|
283
|
+
value
|
|
284
|
+
) })
|
|
285
|
+
]
|
|
286
|
+
}
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
function ActionSwapRollIcon({ value, children, className }) {
|
|
290
|
+
const reduce = useReducedMotion() ?? false;
|
|
291
|
+
return /* @__PURE__ */ jsx("span", { className: cn("relative inline-grid shrink-0 place-items-center overflow-hidden", className), children: /* @__PURE__ */ jsx(AnimatePresence, { mode: "popLayout", initial: false, children: /* @__PURE__ */ jsx(
|
|
292
|
+
motion.span,
|
|
293
|
+
{
|
|
294
|
+
"aria-hidden": true,
|
|
295
|
+
variants: ICON_VARIANTS,
|
|
296
|
+
initial: reduce ? false : "initial",
|
|
297
|
+
animate: reduce ? AT_REST : "animate",
|
|
298
|
+
exit: reduce ? void 0 : "exit",
|
|
299
|
+
className: "col-start-1 row-start-1 inline-flex items-center justify-center will-change-[opacity,filter,transform]",
|
|
300
|
+
children
|
|
301
|
+
},
|
|
302
|
+
value
|
|
303
|
+
) }) });
|
|
304
|
+
}
|
|
305
|
+
function AnimatedBeam({
|
|
306
|
+
className,
|
|
307
|
+
containerRef,
|
|
308
|
+
fromRef,
|
|
309
|
+
toRef,
|
|
310
|
+
curvature = 0,
|
|
311
|
+
reverse = false,
|
|
312
|
+
duration = 5,
|
|
313
|
+
delay = 0,
|
|
314
|
+
pathColor = "gray",
|
|
315
|
+
pathWidth = 2,
|
|
316
|
+
pathOpacity = 0.2,
|
|
317
|
+
gradientStartColor = "#ffaa40",
|
|
318
|
+
gradientStopColor = "#9c40ff",
|
|
319
|
+
repeat = Number.POSITIVE_INFINITY,
|
|
320
|
+
repeatDelay = 0,
|
|
321
|
+
startXOffset = 0,
|
|
322
|
+
startYOffset = 0,
|
|
323
|
+
endXOffset = 0,
|
|
324
|
+
endYOffset = 0
|
|
325
|
+
}) {
|
|
326
|
+
const id = useId();
|
|
327
|
+
const [pathD, setPathD] = useState("");
|
|
328
|
+
const [svgDimensions, setSvgDimensions] = useState({
|
|
329
|
+
width: 0,
|
|
330
|
+
height: 0
|
|
331
|
+
});
|
|
332
|
+
const gradientCoordinates = reverse ? {
|
|
333
|
+
x1: ["90%", "-10%"],
|
|
334
|
+
x2: ["100%", "0%"],
|
|
335
|
+
y1: ["0%", "0%"],
|
|
336
|
+
y2: ["0%", "0%"]
|
|
337
|
+
} : {
|
|
338
|
+
x1: ["10%", "110%"],
|
|
339
|
+
x2: ["0%", "100%"],
|
|
340
|
+
y1: ["0%", "0%"],
|
|
341
|
+
y2: ["0%", "0%"]
|
|
342
|
+
};
|
|
343
|
+
useEffect(() => {
|
|
344
|
+
const updatePath = () => {
|
|
345
|
+
if (containerRef.current && fromRef.current && toRef.current) {
|
|
346
|
+
const containerRect = containerRef.current.getBoundingClientRect();
|
|
347
|
+
const rectA = fromRef.current.getBoundingClientRect();
|
|
348
|
+
const rectB = toRef.current.getBoundingClientRect();
|
|
349
|
+
const svgWidth = containerRect.width;
|
|
350
|
+
const svgHeight = containerRect.height;
|
|
351
|
+
setSvgDimensions({ width: svgWidth, height: svgHeight });
|
|
352
|
+
const startX = rectA.left - containerRect.left + rectA.width / 2 + startXOffset;
|
|
353
|
+
const startY = rectA.top - containerRect.top + rectA.height / 2 + startYOffset;
|
|
354
|
+
const endX = rectB.left - containerRect.left + rectB.width / 2 + endXOffset;
|
|
355
|
+
const endY = rectB.top - containerRect.top + rectB.height / 2 + endYOffset;
|
|
356
|
+
const controlY = startY - curvature;
|
|
357
|
+
const d = `M ${startX},${startY} Q ${(startX + endX) / 2},${controlY} ${endX},${endY}`;
|
|
358
|
+
setPathD(d);
|
|
359
|
+
}
|
|
360
|
+
};
|
|
361
|
+
const resizeObserver = new ResizeObserver(() => {
|
|
362
|
+
updatePath();
|
|
363
|
+
});
|
|
364
|
+
if (containerRef.current) resizeObserver.observe(containerRef.current);
|
|
365
|
+
updatePath();
|
|
366
|
+
return () => {
|
|
367
|
+
resizeObserver.disconnect();
|
|
368
|
+
};
|
|
369
|
+
}, [containerRef, fromRef, toRef, curvature, startXOffset, startYOffset, endXOffset, endYOffset]);
|
|
370
|
+
return /* @__PURE__ */ jsxs(
|
|
371
|
+
"svg",
|
|
372
|
+
{
|
|
373
|
+
"aria-hidden": "true",
|
|
374
|
+
fill: "none",
|
|
375
|
+
width: svgDimensions.width,
|
|
376
|
+
height: svgDimensions.height,
|
|
377
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
378
|
+
className: cn("pointer-events-none absolute top-0 left-0 transform-gpu stroke-2", className),
|
|
379
|
+
viewBox: `0 0 ${svgDimensions.width} ${svgDimensions.height}`,
|
|
380
|
+
children: [
|
|
381
|
+
/* @__PURE__ */ jsx("path", { d: pathD, stroke: pathColor, strokeWidth: pathWidth, strokeOpacity: pathOpacity, strokeLinecap: "round" }),
|
|
382
|
+
/* @__PURE__ */ jsx("path", { d: pathD, strokeWidth: pathWidth, stroke: `url(#${id})`, strokeOpacity: "1", strokeLinecap: "round" }),
|
|
383
|
+
/* @__PURE__ */ jsx("defs", { children: /* @__PURE__ */ jsxs(
|
|
384
|
+
motion.linearGradient,
|
|
385
|
+
{
|
|
386
|
+
className: "transform-gpu",
|
|
387
|
+
id,
|
|
388
|
+
gradientUnits: "userSpaceOnUse",
|
|
389
|
+
initial: {
|
|
390
|
+
x1: "0%",
|
|
391
|
+
x2: "0%",
|
|
392
|
+
y1: "0%",
|
|
393
|
+
y2: "0%"
|
|
394
|
+
},
|
|
395
|
+
animate: {
|
|
396
|
+
x1: gradientCoordinates.x1,
|
|
397
|
+
x2: gradientCoordinates.x2,
|
|
398
|
+
y1: gradientCoordinates.y1,
|
|
399
|
+
y2: gradientCoordinates.y2
|
|
400
|
+
},
|
|
401
|
+
transition: {
|
|
402
|
+
delay,
|
|
403
|
+
duration,
|
|
404
|
+
ease: [0.16, 1, 0.3, 1],
|
|
405
|
+
repeat,
|
|
406
|
+
repeatDelay
|
|
407
|
+
},
|
|
408
|
+
children: [
|
|
409
|
+
/* @__PURE__ */ jsx("stop", { stopColor: gradientStartColor, stopOpacity: "0" }),
|
|
410
|
+
/* @__PURE__ */ jsx("stop", { stopColor: gradientStartColor }),
|
|
411
|
+
/* @__PURE__ */ jsx("stop", { offset: "32.5%", stopColor: gradientStopColor }),
|
|
412
|
+
/* @__PURE__ */ jsx("stop", { offset: "100%", stopColor: gradientStopColor, stopOpacity: "0" })
|
|
413
|
+
]
|
|
414
|
+
}
|
|
415
|
+
) })
|
|
416
|
+
]
|
|
417
|
+
}
|
|
418
|
+
);
|
|
419
|
+
}
|
|
420
|
+
var buttonVariants = cva(
|
|
421
|
+
"group inline-flex items-center justify-center gap-1.5 font-medium [transition:opacity_.24s_80ms,transform_.15s_cubic-bezier(.4,0,.2,1),box-shadow_.15s_cubic-bezier(.4,0,.2,1),filter_.15s_cubic-bezier(.4,0,.2,1)] disabled:[transition:opacity_.1s]",
|
|
422
|
+
{
|
|
423
|
+
variants: {
|
|
424
|
+
variant: {
|
|
425
|
+
filled: "bg-(--foreground) text-(--primary-foreground) shadow-elevated-3 hover:opacity-90",
|
|
426
|
+
bordered: "border border-(--border-hi) bg-surface-3 text-foreground shadow-elevated-3 hover:bg-(--muted)",
|
|
427
|
+
ghost: "text-(--foreground-secondary) hover:bg-(--surface-hover) hover:text-(--foreground)"
|
|
428
|
+
},
|
|
429
|
+
size: {
|
|
430
|
+
sm: "h-8 px-3.5 text-[15px]",
|
|
431
|
+
md: "h-9 px-5 text-[17px]",
|
|
432
|
+
lg: "h-11 px-6 text-[17px]",
|
|
433
|
+
icon: "size-11"
|
|
434
|
+
},
|
|
435
|
+
shape: {
|
|
436
|
+
rounded: "rounded-interactive",
|
|
437
|
+
pill: "rounded-full"
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
// Pill is the house standard — every CTA is fully rounded.
|
|
441
|
+
defaultVariants: { variant: "filled", size: "md", shape: "pill" }
|
|
442
|
+
}
|
|
443
|
+
);
|
|
444
|
+
function Button({
|
|
445
|
+
variant,
|
|
446
|
+
size,
|
|
447
|
+
shape,
|
|
448
|
+
showArrow = false,
|
|
449
|
+
external = false,
|
|
450
|
+
title,
|
|
451
|
+
actionOrLink,
|
|
452
|
+
children,
|
|
453
|
+
className,
|
|
454
|
+
"aria-label": ariaLabel,
|
|
455
|
+
"aria-expanded": ariaExpanded
|
|
456
|
+
}) {
|
|
457
|
+
const buttonClassName = cn(buttonVariants({ variant, size, shape }), className);
|
|
458
|
+
const arrowSlot = showArrow && /* @__PURE__ */ jsxs(
|
|
459
|
+
"svg",
|
|
460
|
+
{
|
|
461
|
+
viewBox: "0 0 14 14",
|
|
462
|
+
width: "14",
|
|
463
|
+
height: "14",
|
|
464
|
+
fill: "none",
|
|
465
|
+
stroke: "currentColor",
|
|
466
|
+
strokeWidth: "2",
|
|
467
|
+
strokeLinecap: "round",
|
|
468
|
+
strokeLinejoin: "round",
|
|
469
|
+
"aria-hidden": true,
|
|
470
|
+
className: "shrink-0",
|
|
471
|
+
children: [
|
|
472
|
+
/* @__PURE__ */ jsx(
|
|
473
|
+
"line",
|
|
474
|
+
{
|
|
475
|
+
x1: "0",
|
|
476
|
+
y1: "7",
|
|
477
|
+
x2: "9",
|
|
478
|
+
y2: "7",
|
|
479
|
+
strokeDasharray: "9",
|
|
480
|
+
className: "[stroke-dashoffset:9] [transition:stroke-dashoffset_.08s_cubic-bezier(.22,1,.36,1)] group-hover:[stroke-dashoffset:0] group-hover:[transition-duration:.22s]"
|
|
481
|
+
}
|
|
482
|
+
),
|
|
483
|
+
/* @__PURE__ */ jsx(
|
|
484
|
+
"path",
|
|
485
|
+
{
|
|
486
|
+
d: "M5 3l4 4-4 4",
|
|
487
|
+
className: "[transform:translateX(0)] [transition:transform_.22s_cubic-bezier(.22,1,.36,1)] group-hover:[transform:translateX(2px)]"
|
|
488
|
+
}
|
|
489
|
+
)
|
|
490
|
+
]
|
|
491
|
+
}
|
|
492
|
+
);
|
|
493
|
+
if (typeof actionOrLink === "string")
|
|
494
|
+
return /* @__PURE__ */ jsxs(
|
|
495
|
+
"a",
|
|
496
|
+
{
|
|
497
|
+
href: actionOrLink,
|
|
498
|
+
className: cn(buttonClassName, "no-underline"),
|
|
499
|
+
"aria-label": ariaLabel,
|
|
500
|
+
title,
|
|
501
|
+
...external ? { target: "_blank", rel: "noopener noreferrer" } : {},
|
|
502
|
+
children: [
|
|
503
|
+
children,
|
|
504
|
+
arrowSlot
|
|
505
|
+
]
|
|
506
|
+
}
|
|
507
|
+
);
|
|
508
|
+
return /* @__PURE__ */ jsxs(
|
|
509
|
+
"button",
|
|
510
|
+
{
|
|
511
|
+
type: "button",
|
|
512
|
+
className: buttonClassName,
|
|
513
|
+
onClick: actionOrLink,
|
|
514
|
+
"aria-label": ariaLabel,
|
|
515
|
+
"aria-expanded": ariaExpanded,
|
|
516
|
+
title,
|
|
517
|
+
children: [
|
|
518
|
+
children,
|
|
519
|
+
arrowSlot
|
|
520
|
+
]
|
|
521
|
+
}
|
|
522
|
+
);
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// src/lib/surface.ts
|
|
526
|
+
var SURFACE_BG = {
|
|
527
|
+
1: "bg-surface-1",
|
|
528
|
+
2: "bg-surface-2",
|
|
529
|
+
3: "bg-surface-3",
|
|
530
|
+
4: "bg-surface-4",
|
|
531
|
+
5: "bg-surface-5",
|
|
532
|
+
6: "bg-surface-6",
|
|
533
|
+
7: "bg-surface-7",
|
|
534
|
+
8: "bg-surface-8"
|
|
535
|
+
};
|
|
536
|
+
var SURFACE_VAR = {
|
|
537
|
+
1: "[--popup-surface:var(--surface-1)]",
|
|
538
|
+
2: "[--popup-surface:var(--surface-2)]",
|
|
539
|
+
3: "[--popup-surface:var(--surface-3)]",
|
|
540
|
+
4: "[--popup-surface:var(--surface-4)]",
|
|
541
|
+
5: "[--popup-surface:var(--surface-5)]",
|
|
542
|
+
6: "[--popup-surface:var(--surface-6)]",
|
|
543
|
+
7: "[--popup-surface:var(--surface-7)]",
|
|
544
|
+
8: "[--popup-surface:var(--surface-8)]"
|
|
545
|
+
};
|
|
546
|
+
var SURFACE_SHADOW_COMBINED = {
|
|
547
|
+
1: "shadow-elevated-1",
|
|
548
|
+
2: "shadow-elevated-2",
|
|
549
|
+
3: "shadow-elevated-3",
|
|
550
|
+
4: "shadow-elevated-4",
|
|
551
|
+
5: "shadow-elevated-5",
|
|
552
|
+
6: "shadow-elevated-6",
|
|
553
|
+
7: "shadow-elevated-7",
|
|
554
|
+
8: "shadow-elevated-8"
|
|
555
|
+
};
|
|
556
|
+
function solidSurface(level, shadowLevel = level) {
|
|
557
|
+
return `${SURFACE_BG[level]} ${SURFACE_SHADOW_COMBINED[shadowLevel]} ${SURFACE_VAR[level]}`;
|
|
558
|
+
}
|
|
559
|
+
var cardVariants = cva("text-foreground flex flex-col", {
|
|
560
|
+
variants: {
|
|
561
|
+
variant: {
|
|
562
|
+
default: "gap-6 rounded-2xl py-6",
|
|
563
|
+
inset: "rounded-2xl p-1"
|
|
564
|
+
}
|
|
565
|
+
},
|
|
566
|
+
defaultVariants: {
|
|
567
|
+
variant: "default"
|
|
568
|
+
}
|
|
569
|
+
});
|
|
570
|
+
function Card({ className, variant = "default", level = 3, shadowLevel = 1, ...props }) {
|
|
571
|
+
return /* @__PURE__ */ jsx(
|
|
572
|
+
"div",
|
|
573
|
+
{
|
|
574
|
+
"data-slot": "card",
|
|
575
|
+
"data-variant": variant,
|
|
576
|
+
"data-level": level,
|
|
577
|
+
className: cn(
|
|
578
|
+
cardVariants({ variant }),
|
|
579
|
+
solidSurface(level, shadowLevel),
|
|
580
|
+
// bg-muted overrides solidSurface's bg, making the outer a gray frame
|
|
581
|
+
// while keeping its shadow, rim, and --popup-surface.
|
|
582
|
+
variant === "inset" && "bg-muted",
|
|
583
|
+
className
|
|
584
|
+
),
|
|
585
|
+
...props
|
|
586
|
+
}
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
function CardHeader({ className, ...props }) {
|
|
590
|
+
return /* @__PURE__ */ jsx(
|
|
591
|
+
"div",
|
|
592
|
+
{
|
|
593
|
+
"data-slot": "card-header",
|
|
594
|
+
className: cn(
|
|
595
|
+
"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start has-[[data-slot=card-action]]:grid-cols-[1fr_auto] [.border-b]:pb-6",
|
|
596
|
+
"[[data-variant=default]>_&]:gap-1.5 [[data-variant=default]>_&]:px-6",
|
|
597
|
+
"[[data-variant=inset]>_&]:px-3 [[data-variant=inset]>_&]:py-2 [[data-variant=inset]>_&]:pt-1",
|
|
598
|
+
className
|
|
599
|
+
),
|
|
600
|
+
...props
|
|
601
|
+
}
|
|
602
|
+
);
|
|
603
|
+
}
|
|
604
|
+
function CardTitle({ className, ...props }) {
|
|
605
|
+
return /* @__PURE__ */ jsx("div", { "data-slot": "card-title", className: cn("font-semibold [[data-variant=default]_&]:leading-none", className), ...props });
|
|
606
|
+
}
|
|
607
|
+
function CardDescription({ className, ...props }) {
|
|
608
|
+
return /* @__PURE__ */ jsx("div", { "data-slot": "card-description", className: cn("text-muted-foreground text-sm", className), ...props });
|
|
609
|
+
}
|
|
610
|
+
function CardAction({ className, ...props }) {
|
|
611
|
+
return /* @__PURE__ */ jsx(
|
|
612
|
+
"div",
|
|
613
|
+
{
|
|
614
|
+
"data-slot": "card-action",
|
|
615
|
+
className: cn("col-start-2 row-span-2 row-start-1 self-start justify-self-end", className),
|
|
616
|
+
...props
|
|
617
|
+
}
|
|
618
|
+
);
|
|
619
|
+
}
|
|
620
|
+
function CardContent({ className, ...props }) {
|
|
621
|
+
return /* @__PURE__ */ jsx(
|
|
622
|
+
"div",
|
|
623
|
+
{
|
|
624
|
+
"data-slot": "card-content",
|
|
625
|
+
className: cn(
|
|
626
|
+
"[[data-variant=default]>_&]:px-6",
|
|
627
|
+
"[[data-variant=inset]>_&]:flex [[data-variant=inset]>_&]:flex-1 [[data-variant=inset]>_&]:flex-col [[data-variant=inset]>_&]:rounded-lg [[data-variant=inset]>_&]:bg-surface-3 [[data-variant=inset]>_&]:p-4 [[data-variant=inset]>_&]:shadow-elevated-3 [[data-variant=inset]>_&]:[--popup-surface:var(--surface-3)]",
|
|
628
|
+
className
|
|
629
|
+
),
|
|
630
|
+
...props
|
|
631
|
+
}
|
|
632
|
+
);
|
|
633
|
+
}
|
|
634
|
+
function CardFooter({ className, ...props }) {
|
|
635
|
+
return /* @__PURE__ */ jsx(
|
|
636
|
+
"div",
|
|
637
|
+
{
|
|
638
|
+
"data-slot": "card-footer",
|
|
639
|
+
className: cn(
|
|
640
|
+
"flex items-center [.border-t]:pt-6",
|
|
641
|
+
"[[data-variant=default]>_&]:px-6",
|
|
642
|
+
"[[data-variant=inset]>_&]:mt-auto [[data-variant=inset]>_&]:justify-end [[data-variant=inset]>_&]:pt-4",
|
|
643
|
+
className
|
|
644
|
+
),
|
|
645
|
+
...props
|
|
646
|
+
}
|
|
647
|
+
);
|
|
648
|
+
}
|
|
649
|
+
function HeightClipper({ height, delay, children }) {
|
|
650
|
+
return /* @__PURE__ */ jsx(
|
|
651
|
+
motion.span,
|
|
652
|
+
{
|
|
653
|
+
className: "block w-full overflow-hidden",
|
|
654
|
+
animate: height === void 0 ? {} : { height },
|
|
655
|
+
transition: {
|
|
656
|
+
height: { duration: 0.4, ease: [0.4, 0, 0.2, 1], delay }
|
|
657
|
+
},
|
|
658
|
+
children
|
|
659
|
+
}
|
|
660
|
+
);
|
|
661
|
+
}
|
|
662
|
+
function ExitingLine({ text, textColor, duration, fallDuration, opacityEase, wrap = false, onDone }) {
|
|
663
|
+
return /* @__PURE__ */ jsx(
|
|
664
|
+
motion.span,
|
|
665
|
+
{
|
|
666
|
+
"aria-hidden": true,
|
|
667
|
+
className: cn(
|
|
668
|
+
wrap ? "pointer-events-none absolute top-0 left-0 w-full" : "pointer-events-none absolute top-0 left-1/2 whitespace-nowrap"
|
|
669
|
+
),
|
|
670
|
+
style: { color: textColor },
|
|
671
|
+
initial: wrap ? { opacity: 1, y: 0 } : { opacity: 1, x: "-50%", y: 0 },
|
|
672
|
+
animate: wrap ? { opacity: 0, y: 14 } : { opacity: 0, x: "-50%", y: 14 },
|
|
673
|
+
transition: {
|
|
674
|
+
opacity: { duration, ease: opacityEase },
|
|
675
|
+
y: { duration: fallDuration, ease: [0.22, 0.61, 0.36, 1] }
|
|
676
|
+
},
|
|
677
|
+
onAnimationComplete: onDone,
|
|
678
|
+
children: text
|
|
679
|
+
}
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
function WidthReservation({ texts }) {
|
|
683
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "invisible block h-0 overflow-hidden", children: texts.map((t) => /* @__PURE__ */ jsx("span", { className: "block", children: t }, t)) });
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// src/components/dia-text-reveal.sweep.ts
|
|
687
|
+
var BAND_HALF = 17;
|
|
688
|
+
var SWEEP_START = -BAND_HALF;
|
|
689
|
+
var SWEEP_END = 100 + BAND_HALF;
|
|
690
|
+
var sweepEaseFn = (t) => t < 0.5 ? 4 * t ** 3 : 1 - (-2 * t + 2) ** 3 / 2;
|
|
691
|
+
var coverageAt = (progress) => Math.min(1, sweepEaseFn(progress) * (SWEEP_END - SWEEP_START) / 100);
|
|
692
|
+
var COVERAGE_SPAN = (() => {
|
|
693
|
+
let lo = 0;
|
|
694
|
+
let hi = 1;
|
|
695
|
+
for (let i = 0; i < 40; i += 1) {
|
|
696
|
+
const mid = (lo + hi) / 2;
|
|
697
|
+
if (coverageAt(mid) < 1) lo = mid;
|
|
698
|
+
else hi = mid;
|
|
699
|
+
}
|
|
700
|
+
return hi;
|
|
701
|
+
})();
|
|
702
|
+
var EXIT_FADE_BIAS = 0.4;
|
|
703
|
+
var exitEase = (t) => coverageAt(t * COVERAGE_SPAN) ** EXIT_FADE_BIAS;
|
|
704
|
+
var makeExitEase = (leadFraction) => {
|
|
705
|
+
if (leadFraction <= 0) return exitEase;
|
|
706
|
+
if (leadFraction >= 1) return () => 0;
|
|
707
|
+
return (t) => t <= leadFraction ? 0 : exitEase((t - leadFraction) / (1 - leadFraction));
|
|
708
|
+
};
|
|
709
|
+
var SWEEP_SCALE = 3;
|
|
710
|
+
var BAND_HALF_IMAGE = BAND_HALF / SWEEP_SCALE;
|
|
711
|
+
var positionFor = (pos) => (pos - 50 * SWEEP_SCALE) / (1 - SWEEP_SCALE);
|
|
712
|
+
var SWEEP_FROM = `${positionFor(SWEEP_START).toFixed(3)}%`;
|
|
713
|
+
var SWEEP_TO = `${positionFor(SWEEP_END).toFixed(3)}%`;
|
|
714
|
+
var SWEEP_SIZE = `${SWEEP_SCALE * 100}% 100%`;
|
|
715
|
+
var EASE_SAMPLES = 24;
|
|
716
|
+
var sweepEaseCss = `linear(${Array.from({ length: EASE_SAMPLES + 1 }, (_, i) => sweepEaseFn(i / EASE_SAMPLES).toFixed(5)).join(
|
|
717
|
+
", "
|
|
718
|
+
)})`;
|
|
719
|
+
function buildSweepGradient(colors, textColor) {
|
|
720
|
+
const bandStart = 50 - BAND_HALF_IMAGE;
|
|
721
|
+
const bandEnd = 50 + BAND_HALF_IMAGE;
|
|
722
|
+
const n = colors.length;
|
|
723
|
+
const parts = [`${textColor} 0%`, `${textColor} ${bandStart.toFixed(3)}%`];
|
|
724
|
+
for (const [i, c] of colors.entries()) {
|
|
725
|
+
const pct = n === 1 ? 50 : bandStart + i / (n - 1) * BAND_HALF_IMAGE * 2;
|
|
726
|
+
parts.push(`${c} ${pct.toFixed(3)}%`);
|
|
727
|
+
}
|
|
728
|
+
parts.push(`transparent ${bandEnd.toFixed(3)}%`, "transparent 100%");
|
|
729
|
+
return `linear-gradient(90deg, ${parts.join(", ")})`;
|
|
730
|
+
}
|
|
731
|
+
function buildSweepStyle({ colors, textColor, duration, delay, sweep, paused, reduced }) {
|
|
732
|
+
return {
|
|
733
|
+
color: "transparent",
|
|
734
|
+
backgroundClip: "text",
|
|
735
|
+
WebkitBackgroundClip: "text",
|
|
736
|
+
backgroundImage: buildSweepGradient(colors, textColor),
|
|
737
|
+
backgroundRepeat: "no-repeat",
|
|
738
|
+
backgroundSize: SWEEP_SIZE,
|
|
739
|
+
backgroundPositionX: reduced ? SWEEP_TO : SWEEP_FROM,
|
|
740
|
+
"--dia-sweep-from": SWEEP_FROM,
|
|
741
|
+
"--dia-sweep-to": SWEEP_TO,
|
|
742
|
+
...sweep !== null && !reduced && {
|
|
743
|
+
animationName: sweep.cycle % 2 === 0 ? "dia-sweep-a" : "dia-sweep-b",
|
|
744
|
+
animationDuration: `${duration}s`,
|
|
745
|
+
animationDelay: `${delay}s`,
|
|
746
|
+
animationTimingFunction: sweepEaseCss,
|
|
747
|
+
animationFillMode: "both",
|
|
748
|
+
animationIterationCount: 1,
|
|
749
|
+
animationPlayState: paused ? "paused" : "running"
|
|
750
|
+
}
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// src/components/dia-text-reveal.utils.ts
|
|
755
|
+
function measureWidths(el, texts) {
|
|
756
|
+
const parent = el.parentElement;
|
|
757
|
+
if (!parent) return texts.map(() => 0);
|
|
758
|
+
const ghost = el.cloneNode();
|
|
759
|
+
if (!(ghost instanceof HTMLElement)) return texts.map(() => 0);
|
|
760
|
+
Object.assign(ghost.style, {
|
|
761
|
+
position: "absolute",
|
|
762
|
+
visibility: "hidden",
|
|
763
|
+
pointerEvents: "none",
|
|
764
|
+
width: "auto",
|
|
765
|
+
whiteSpace: "nowrap"
|
|
766
|
+
});
|
|
767
|
+
parent.appendChild(ghost);
|
|
768
|
+
const widths = texts.map((t) => {
|
|
769
|
+
ghost.textContent = t;
|
|
770
|
+
return ghost.getBoundingClientRect().width;
|
|
771
|
+
});
|
|
772
|
+
ghost.remove();
|
|
773
|
+
return widths;
|
|
774
|
+
}
|
|
775
|
+
var DEFAULT_COLORS = ["#c679c4", "#fa3d1d", "#ffb005", "#e1e1fe", "#0358f7"];
|
|
776
|
+
var EXIT_LEAD_RATIO = 0.3;
|
|
777
|
+
function DiaTextReveal({
|
|
778
|
+
text,
|
|
779
|
+
colors = DEFAULT_COLORS,
|
|
780
|
+
textColor = "var(--color-foreground)",
|
|
781
|
+
duration = 1,
|
|
782
|
+
delay = 0,
|
|
783
|
+
repeat = false,
|
|
784
|
+
repeatDelay = 0.5,
|
|
785
|
+
exitDuration,
|
|
786
|
+
exitLead,
|
|
787
|
+
startOnView = true,
|
|
788
|
+
start = true,
|
|
789
|
+
once = true,
|
|
790
|
+
className,
|
|
791
|
+
fixedWidth = false,
|
|
792
|
+
wrap = false,
|
|
793
|
+
...props
|
|
794
|
+
}) {
|
|
795
|
+
const texts = Array.isArray(text) ? text : [text];
|
|
796
|
+
const isMulti = texts.length > 1;
|
|
797
|
+
const prefersReducedMotion2 = useReducedMotion();
|
|
798
|
+
const exitSpan = exitDuration ?? duration * COVERAGE_SPAN;
|
|
799
|
+
const lead = Math.max(0, exitLead ?? duration * EXIT_LEAD_RATIO);
|
|
800
|
+
const exitTotal = lead + exitSpan;
|
|
801
|
+
const leadFraction = exitTotal > 0 ? lead / exitTotal : 0;
|
|
802
|
+
const exitOpacityEase = useMemo(() => makeExitEase(leadFraction), [leadFraction]);
|
|
803
|
+
const spanRef = useRef(null);
|
|
804
|
+
const optsRef = useRef({ repeat, repeatDelay, texts });
|
|
805
|
+
optsRef.current = { repeat, repeatDelay, texts };
|
|
806
|
+
const indexRef = useRef(0);
|
|
807
|
+
const hasPlayedRef = useRef(false);
|
|
808
|
+
const timerRef = useRef(void 0);
|
|
809
|
+
const pendingRepeatRef = useRef(false);
|
|
810
|
+
const [activeIndex, setActiveIndex] = useState(0);
|
|
811
|
+
const [sweep, setSweep] = useState(null);
|
|
812
|
+
const [exiting, setExiting] = useState(null);
|
|
813
|
+
const clearExiting = useCallback(() => setExiting(null), []);
|
|
814
|
+
const [measuredWidths, setMeasuredWidths] = useState([]);
|
|
815
|
+
const [wrapHeight, setWrapHeight] = useState(null);
|
|
816
|
+
const innerRef = useRef(null);
|
|
817
|
+
const isInView = useInView(spanRef, { once, amount: 0.1 });
|
|
818
|
+
const isLiveInView = useInView(spanRef, {
|
|
819
|
+
once: false,
|
|
820
|
+
amount: 0.1
|
|
821
|
+
});
|
|
822
|
+
useEffect(() => {
|
|
823
|
+
const el = spanRef.current;
|
|
824
|
+
if (!(el && isMulti) || wrap) return;
|
|
825
|
+
const measure = () => setMeasuredWidths(measureWidths(el, texts));
|
|
826
|
+
measure();
|
|
827
|
+
if (document.fonts.status !== "loaded") document.fonts.ready.then(measure);
|
|
828
|
+
}, [Array.isArray(text) ? text.join("\0") : text, isMulti, wrap, texts]);
|
|
829
|
+
useEffect(() => {
|
|
830
|
+
const el = innerRef.current;
|
|
831
|
+
if (!(el && wrap && isMulti)) return;
|
|
832
|
+
const observer = new ResizeObserver(([entry]) => {
|
|
833
|
+
if (!entry) return;
|
|
834
|
+
const h = entry.contentRect.height;
|
|
835
|
+
setWrapHeight(
|
|
836
|
+
(prev) => prev !== null && prev.h === h ? prev : {
|
|
837
|
+
h,
|
|
838
|
+
shrink: prev !== null && h < prev.h
|
|
839
|
+
}
|
|
840
|
+
);
|
|
841
|
+
});
|
|
842
|
+
observer.observe(el);
|
|
843
|
+
return () => observer.disconnect();
|
|
844
|
+
}, [wrap, isMulti]);
|
|
845
|
+
const advance = useCallback(() => {
|
|
846
|
+
const opts = optsRef.current;
|
|
847
|
+
const current = indexRef.current;
|
|
848
|
+
const next = (current + 1) % opts.texts.length;
|
|
849
|
+
indexRef.current = next;
|
|
850
|
+
setExiting({ index: current, token: Date.now() });
|
|
851
|
+
setActiveIndex(next);
|
|
852
|
+
setSweep((prev) => ({
|
|
853
|
+
cycle: (prev?.cycle ?? 0) + 1,
|
|
854
|
+
lead: true
|
|
855
|
+
}));
|
|
856
|
+
}, []);
|
|
857
|
+
const scheduleRepeat = useCallback(() => {
|
|
858
|
+
timerRef.current = setTimeout(() => {
|
|
859
|
+
timerRef.current = void 0;
|
|
860
|
+
advance();
|
|
861
|
+
}, optsRef.current.repeatDelay * 1e3);
|
|
862
|
+
}, [advance]);
|
|
863
|
+
const onSweepEnd = useCallback(
|
|
864
|
+
(event) => {
|
|
865
|
+
if (!event.animationName.startsWith("dia-sweep")) return;
|
|
866
|
+
if (!optsRef.current.repeat) return;
|
|
867
|
+
scheduleRepeat();
|
|
868
|
+
},
|
|
869
|
+
[scheduleRepeat]
|
|
870
|
+
);
|
|
871
|
+
useEffect(() => {
|
|
872
|
+
if (prefersReducedMotion2) return;
|
|
873
|
+
if (startOnView && !isInView) return;
|
|
874
|
+
if (!start) return;
|
|
875
|
+
if (once && hasPlayedRef.current) return;
|
|
876
|
+
hasPlayedRef.current = true;
|
|
877
|
+
setSweep((prev) => prev === null ? { cycle: 0, lead: false } : { cycle: prev.cycle + 1, lead: false });
|
|
878
|
+
}, [isInView, start, startOnView, once, prefersReducedMotion2]);
|
|
879
|
+
useEffect(() => {
|
|
880
|
+
if (!repeat || prefersReducedMotion2) return;
|
|
881
|
+
if (!isLiveInView) {
|
|
882
|
+
if (timerRef.current === void 0) return;
|
|
883
|
+
clearTimeout(timerRef.current);
|
|
884
|
+
timerRef.current = void 0;
|
|
885
|
+
pendingRepeatRef.current = true;
|
|
886
|
+
} else if (pendingRepeatRef.current) {
|
|
887
|
+
pendingRepeatRef.current = false;
|
|
888
|
+
scheduleRepeat();
|
|
889
|
+
}
|
|
890
|
+
}, [isLiveInView, repeat, prefersReducedMotion2, scheduleRepeat]);
|
|
891
|
+
useEffect(() => () => clearTimeout(timerRef.current), []);
|
|
892
|
+
const paused = repeat && sweep !== null && !isLiveInView;
|
|
893
|
+
const revealStyle = buildSweepStyle({
|
|
894
|
+
colors,
|
|
895
|
+
textColor,
|
|
896
|
+
duration,
|
|
897
|
+
delay: delay + (sweep?.lead ? lead : 0),
|
|
898
|
+
sweep,
|
|
899
|
+
paused,
|
|
900
|
+
reduced: prefersReducedMotion2 === true
|
|
901
|
+
});
|
|
902
|
+
if (!isMulti)
|
|
903
|
+
return /* @__PURE__ */ jsx(
|
|
904
|
+
motion.span,
|
|
905
|
+
{
|
|
906
|
+
ref: spanRef,
|
|
907
|
+
className: cn("align-baseline text-inherit leading-[100%]", className),
|
|
908
|
+
style: revealStyle,
|
|
909
|
+
...props,
|
|
910
|
+
onAnimationEnd: onSweepEnd,
|
|
911
|
+
children: texts[activeIndex]
|
|
912
|
+
}
|
|
913
|
+
);
|
|
914
|
+
const fixedW = !wrap && fixedWidth && measuredWidths.length > 0 ? Math.max(...measuredWidths) : void 0;
|
|
915
|
+
const animatedW = wrap || fixedWidth ? void 0 : measuredWidths[activeIndex];
|
|
916
|
+
const animatedH = wrap ? wrapHeight?.h : void 0;
|
|
917
|
+
const heightDelay = exiting !== null && wrapHeight?.shrink ? exitTotal : 0;
|
|
918
|
+
const incoming = /* @__PURE__ */ jsx(
|
|
919
|
+
"span",
|
|
920
|
+
{
|
|
921
|
+
ref: innerRef,
|
|
922
|
+
className: cn("inline-block", wrap && "w-full", !wrap && "whitespace-nowrap"),
|
|
923
|
+
style: revealStyle,
|
|
924
|
+
onAnimationEnd: onSweepEnd,
|
|
925
|
+
children: texts[activeIndex]
|
|
926
|
+
}
|
|
927
|
+
);
|
|
928
|
+
return /* @__PURE__ */ jsxs(
|
|
929
|
+
motion.span,
|
|
930
|
+
{
|
|
931
|
+
ref: spanRef,
|
|
932
|
+
className: cn(
|
|
933
|
+
wrap ? "relative inline-block w-full text-center align-baseline text-inherit" : "relative inline-block whitespace-nowrap text-center align-baseline text-inherit leading-[100%]",
|
|
934
|
+
className
|
|
935
|
+
),
|
|
936
|
+
style: {
|
|
937
|
+
...fixedW !== void 0 && { width: fixedW }
|
|
938
|
+
},
|
|
939
|
+
animate: {
|
|
940
|
+
...animatedW !== void 0 && { width: animatedW }
|
|
941
|
+
},
|
|
942
|
+
transition: {
|
|
943
|
+
width: { duration: 0.4, ease: [0.4, 0, 0.2, 1] }
|
|
944
|
+
},
|
|
945
|
+
...props,
|
|
946
|
+
children: [
|
|
947
|
+
wrap ? /* @__PURE__ */ jsxs(HeightClipper, { height: animatedH, delay: heightDelay, children: [
|
|
948
|
+
/* @__PURE__ */ jsx(WidthReservation, { texts }),
|
|
949
|
+
incoming
|
|
950
|
+
] }) : incoming,
|
|
951
|
+
exiting && !prefersReducedMotion2 && /* @__PURE__ */ jsx(
|
|
952
|
+
ExitingLine,
|
|
953
|
+
{
|
|
954
|
+
text: texts[exiting.index],
|
|
955
|
+
textColor,
|
|
956
|
+
duration: 0.4,
|
|
957
|
+
fallDuration: 0.25,
|
|
958
|
+
opacityEase: exitOpacityEase,
|
|
959
|
+
wrap,
|
|
960
|
+
onDone: clearExiting
|
|
961
|
+
},
|
|
962
|
+
exiting.token
|
|
963
|
+
)
|
|
964
|
+
]
|
|
965
|
+
}
|
|
966
|
+
);
|
|
967
|
+
}
|
|
968
|
+
function ElevatedInput({
|
|
969
|
+
className,
|
|
970
|
+
type = "text",
|
|
971
|
+
ref,
|
|
972
|
+
...props
|
|
973
|
+
}) {
|
|
974
|
+
return /* @__PURE__ */ jsx(
|
|
975
|
+
"input",
|
|
976
|
+
{
|
|
977
|
+
ref,
|
|
978
|
+
type,
|
|
979
|
+
className: cn(
|
|
980
|
+
// Layout & shape
|
|
981
|
+
"relative w-full overflow-hidden rounded-lg",
|
|
982
|
+
// Typography
|
|
983
|
+
"text-(--color-foreground) text-sm placeholder:text-(--color-muted-foreground)",
|
|
984
|
+
// Sizing
|
|
985
|
+
"h-9 px-3",
|
|
986
|
+
// Reset native input chrome
|
|
987
|
+
"appearance-none border-none outline-none",
|
|
988
|
+
// Background — a barely-there top darkening that reads as cavity depth.
|
|
989
|
+
"bg-[linear-gradient(to_bottom,oklch(0_0_0/0.04),transparent)]",
|
|
990
|
+
"dark:bg-[linear-gradient(to_bottom,oklch(1_0_0/0.04),transparent)]",
|
|
991
|
+
// Shadow stack — light mode
|
|
992
|
+
"shadow-[inset_0_1px_0_0_oklch(1_0_0/0.08),inset_0_2px_2px_-1px_oklch(0_0_0/0.08),inset_0_4px_4px_-2px_oklch(0_0_0/0.08),0_1px_0_0_oklch(0_0_0/0.12),inset_0_0_0_1px_oklch(0_0_0/0.16)]",
|
|
993
|
+
// Shadow stack — dark mode
|
|
994
|
+
"dark:shadow-[inset_0_1px_0_0_oklch(1_0_0/0.1),inset_0_2px_2px_-1px_oklch(0_0_0/0.28),inset_0_4px_4px_-2px_oklch(0_0_0/0.22),0_1px_0_0_oklch(0_0_0/0.36),inset_0_0_0_1px_oklch(1_0_0/0.16)]",
|
|
995
|
+
// Focus
|
|
996
|
+
"focus-visible:shadow-[inset_0_1px_0_0_oklch(1_0_0/0.08),inset_0_2px_2px_-1px_oklch(0_0_0/0.04),inset_0_4px_4px_-2px_oklch(0_0_0/0.04),0_0_0_3px_oklch(0_0_0/0.08),inset_0_0_0_1.5px_oklch(0_0_0/0.36)]",
|
|
997
|
+
"dark:focus-visible:shadow-[inset_0_1px_0_0_oklch(1_0_0/0.12),inset_0_2px_2px_-1px_oklch(0_0_0/0.16),inset_0_4px_4px_-2px_oklch(0_0_0/0.12),0_0_0_3px_oklch(1_0_0/0.08),inset_0_0_0_1.5px_oklch(1_0_0/0.28)]",
|
|
998
|
+
"transition-shadow duration-150",
|
|
999
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
1000
|
+
className
|
|
1001
|
+
),
|
|
1002
|
+
...props
|
|
1003
|
+
}
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
var viewport = { once: true, margin: "-60px" };
|
|
1007
|
+
var ROW_TOLERANCE = 8;
|
|
1008
|
+
var StaggerContext = createContext(null);
|
|
1009
|
+
function FadeIn({ children, className, delay = 0, duration = 1, yOffset = 20, start = true }) {
|
|
1010
|
+
const ref = useRef(null);
|
|
1011
|
+
const inView = useInView(ref, viewport);
|
|
1012
|
+
const hidden = { opacity: 0, y: yOffset };
|
|
1013
|
+
return /* @__PURE__ */ jsx(
|
|
1014
|
+
motion.div,
|
|
1015
|
+
{
|
|
1016
|
+
ref,
|
|
1017
|
+
className,
|
|
1018
|
+
initial: hidden,
|
|
1019
|
+
animate: inView && start ? { opacity: 1, y: 0 } : hidden,
|
|
1020
|
+
transition: { duration, delay, ease: easeOut },
|
|
1021
|
+
children
|
|
1022
|
+
}
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
1025
|
+
function Stagger({ children, className, staggerDelay = 0.15, baseDelay = 0, start = true }) {
|
|
1026
|
+
const queue = useRef([]);
|
|
1027
|
+
const frame = useRef(null);
|
|
1028
|
+
const started = useRef(start);
|
|
1029
|
+
started.current = start;
|
|
1030
|
+
const flush = useCallback(() => {
|
|
1031
|
+
frame.current = null;
|
|
1032
|
+
const batch = queue.current;
|
|
1033
|
+
queue.current = [];
|
|
1034
|
+
const positioned = batch.map((entry) => ({
|
|
1035
|
+
...entry,
|
|
1036
|
+
rect: entry.element.getBoundingClientRect()
|
|
1037
|
+
}));
|
|
1038
|
+
positioned.sort(
|
|
1039
|
+
(a, b) => Math.abs(a.rect.top - b.rect.top) > ROW_TOLERANCE ? a.rect.top - b.rect.top : a.rect.left - b.rect.left
|
|
1040
|
+
);
|
|
1041
|
+
for (const [index, entry] of positioned.entries()) entry.reveal(baseDelay + index * staggerDelay);
|
|
1042
|
+
}, [baseDelay, staggerDelay]);
|
|
1043
|
+
const register = useCallback(
|
|
1044
|
+
(element, reveal) => {
|
|
1045
|
+
queue.current.push({ element, reveal });
|
|
1046
|
+
if (started.current) frame.current ??= requestAnimationFrame(flush);
|
|
1047
|
+
},
|
|
1048
|
+
[flush]
|
|
1049
|
+
);
|
|
1050
|
+
useEffect(() => {
|
|
1051
|
+
if (start && queue.current.length > 0) frame.current ??= requestAnimationFrame(flush);
|
|
1052
|
+
}, [start, flush]);
|
|
1053
|
+
return /* @__PURE__ */ jsx(StaggerContext, { value: register, children: /* @__PURE__ */ jsx("div", { className, children }) });
|
|
1054
|
+
}
|
|
1055
|
+
function StaggerItem({ children, className }) {
|
|
1056
|
+
const register = useContext(StaggerContext);
|
|
1057
|
+
const ref = useRef(null);
|
|
1058
|
+
const claimed = useRef(false);
|
|
1059
|
+
const [delay, setDelay] = useState(null);
|
|
1060
|
+
const onViewportEnter = useCallback(() => {
|
|
1061
|
+
if (claimed.current) return;
|
|
1062
|
+
claimed.current = true;
|
|
1063
|
+
const element = ref.current;
|
|
1064
|
+
if (register && element) register(element, setDelay);
|
|
1065
|
+
else setDelay(0);
|
|
1066
|
+
}, [register]);
|
|
1067
|
+
return /* @__PURE__ */ jsx(
|
|
1068
|
+
motion.div,
|
|
1069
|
+
{
|
|
1070
|
+
ref,
|
|
1071
|
+
className,
|
|
1072
|
+
initial: { opacity: 0, y: 18 },
|
|
1073
|
+
animate: delay === null ? { opacity: 0, y: 18 } : { opacity: 1, y: 0 },
|
|
1074
|
+
transition: { duration: 0.45, delay: delay ?? 0, ease: easeOut },
|
|
1075
|
+
viewport,
|
|
1076
|
+
onViewportEnter,
|
|
1077
|
+
children
|
|
1078
|
+
}
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
function FeatureCard({ icon, title, body, iconColor, className }) {
|
|
1082
|
+
return /* @__PURE__ */ jsxs(
|
|
1083
|
+
"div",
|
|
1084
|
+
{
|
|
1085
|
+
className: cn(
|
|
1086
|
+
"flex w-full flex-col justify-between gap-6 rounded-[20px] bg-(--muted) p-6 lg:gap-8 lg:rounded-3xl lg:p-8 xl:gap-10 xl:p-10",
|
|
1087
|
+
className
|
|
1088
|
+
),
|
|
1089
|
+
children: [
|
|
1090
|
+
/* @__PURE__ */ jsx("div", { className: "flex size-10 items-center justify-center rounded-[10px] bg-(--surface) shadow-(--shadow-sm) lg:size-12 lg:rounded-md", children: /* @__PURE__ */ jsx(
|
|
1091
|
+
"span",
|
|
1092
|
+
{
|
|
1093
|
+
className: cn("flex h-5 w-5 items-center justify-center lg:h-6 lg:w-6", iconColor ?? "text-(--foreground-secondary)"),
|
|
1094
|
+
children: icon
|
|
1095
|
+
}
|
|
1096
|
+
) }),
|
|
1097
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
1098
|
+
/* @__PURE__ */ jsx("h3", { className: "font-semibold text-[15px] text-foreground lg:text-base", children: title }),
|
|
1099
|
+
/* @__PURE__ */ jsx("p", { className: "text-(--foreground-secondary) text-[13px] leading-relaxed lg:text-sm", children: body })
|
|
1100
|
+
] })
|
|
1101
|
+
]
|
|
1102
|
+
}
|
|
1103
|
+
);
|
|
1104
|
+
}
|
|
1105
|
+
var downChevronClass = "absolute left-1/2 top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)";
|
|
1106
|
+
var rightChevronClass = "absolute right-0 top-1/2 size-2 translate-x-1/2 -translate-y-1/2 rotate-45 border-t border-r border-(--foreground-muted)";
|
|
1107
|
+
var leftChevronClass = "absolute left-0 top-1/2 size-2 -translate-x-1/2 -translate-y-1/2 -rotate-45 border-t border-l border-(--foreground-muted)";
|
|
1108
|
+
var microLabelClass = "absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 whitespace-nowrap rounded-full border border-(--border) bg-(--muted) px-1.5 py-px font-mono text-[8.5px] leading-tight text-(--foreground-secondary)";
|
|
1109
|
+
function ArrowRight({ label, className }) {
|
|
1110
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center", className), children: [
|
|
1111
|
+
/* @__PURE__ */ jsx("span", { className: "h-px w-full bg-(--foreground-muted)" }),
|
|
1112
|
+
/* @__PURE__ */ jsx("span", { className: rightChevronClass }),
|
|
1113
|
+
label ? /* @__PURE__ */ jsx("span", { className: microLabelClass, children: label }) : null
|
|
1114
|
+
] });
|
|
1115
|
+
}
|
|
1116
|
+
function ArrowLeft({ label, className }) {
|
|
1117
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative flex items-center", className), children: [
|
|
1118
|
+
/* @__PURE__ */ jsx("span", { className: "h-px w-full bg-(--foreground-muted)" }),
|
|
1119
|
+
/* @__PURE__ */ jsx("span", { className: leftChevronClass }),
|
|
1120
|
+
label ? /* @__PURE__ */ jsx("span", { className: microLabelClass, children: label }) : null
|
|
1121
|
+
] });
|
|
1122
|
+
}
|
|
1123
|
+
function TurnDown({ className }) {
|
|
1124
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative h-4", className), children: [
|
|
1125
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 h-full w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1126
|
+
/* @__PURE__ */ jsx("span", { className: downChevronClass })
|
|
1127
|
+
] });
|
|
1128
|
+
}
|
|
1129
|
+
function SplitArrow({ leftLabel, rightLabel, className }) {
|
|
1130
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative h-12", className), children: [
|
|
1131
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1132
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)" }),
|
|
1133
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1134
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1135
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)" }),
|
|
1136
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)" }),
|
|
1137
|
+
leftLabel ? /* @__PURE__ */ jsx("span", { className: "absolute left-[30%] top-1/2 -translate-y-1/2 rounded-full border border-(--border) bg-(--muted) px-2 py-0.5 font-mono text-[10px] text-(--foreground-secondary)", children: leftLabel }) : null,
|
|
1138
|
+
rightLabel ? /* @__PURE__ */ jsx("span", { className: "absolute right-[30%] top-1/2 -translate-y-1/2 rounded-full border border-(--border) bg-(--muted) px-2 py-0.5 font-mono text-[10px] text-(--foreground-secondary)", children: rightLabel }) : null
|
|
1139
|
+
] });
|
|
1140
|
+
}
|
|
1141
|
+
function JoinArrow({ className }) {
|
|
1142
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative h-12", className), children: [
|
|
1143
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[25%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1144
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[75%] top-0 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1145
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-[25%] right-[25%] top-1/2 h-px -translate-y-1/2 bg-(--foreground-muted)" }),
|
|
1146
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-1/2 h-1/2 w-px -translate-x-1/2 bg-(--foreground-muted)" }),
|
|
1147
|
+
/* @__PURE__ */ jsx("span", { className: "absolute left-1/2 top-full size-2 -translate-x-1/2 -translate-y-1/2 rotate-45 border-b border-r border-(--foreground-muted)" })
|
|
1148
|
+
] });
|
|
1149
|
+
}
|
|
1150
|
+
function FlowNode({ icon, chipClass, title, body, tag, children, className }) {
|
|
1151
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full flex-col rounded-[12px] border border-(--border) bg-(--surface) p-2.5", className), children: [
|
|
1152
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
1153
|
+
icon ? /* @__PURE__ */ jsx("div", { className: cn("flex size-7 shrink-0 items-center justify-center rounded-[8px]", chipClass ?? "bg-(--muted)"), children: icon }) : null,
|
|
1154
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1155
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-1.5 gap-y-0.5", children: [
|
|
1156
|
+
/* @__PURE__ */ jsx("p", { className: "font-semibold text-[11px] leading-snug text-foreground sm:text-[12px]", children: title }),
|
|
1157
|
+
tag ? /* @__PURE__ */ jsx("span", { className: "rounded-full border border-(--border) px-1.5 py-px font-mono text-[8.5px] text-(--foreground-muted)", children: tag }) : null
|
|
1158
|
+
] }),
|
|
1159
|
+
body ? /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-[9.5px] leading-snug text-(--foreground-secondary) sm:text-[10px]", children: body }) : null
|
|
1160
|
+
] })
|
|
1161
|
+
] }),
|
|
1162
|
+
children ? /* @__PURE__ */ jsx("div", { className: "mt-2", children }) : null
|
|
1163
|
+
] });
|
|
1164
|
+
}
|
|
1165
|
+
function FlowPill({ title, className }) {
|
|
1166
|
+
return /* @__PURE__ */ jsx(
|
|
1167
|
+
"div",
|
|
1168
|
+
{
|
|
1169
|
+
className: cn(
|
|
1170
|
+
"mx-auto flex w-fit max-w-full items-center justify-center rounded-full border border-(--border) bg-(--surface) px-4 py-2 text-center",
|
|
1171
|
+
className
|
|
1172
|
+
),
|
|
1173
|
+
children: /* @__PURE__ */ jsx("p", { className: "text-[12px] font-semibold leading-snug text-foreground", children: title })
|
|
1174
|
+
}
|
|
1175
|
+
);
|
|
1176
|
+
}
|
|
1177
|
+
function FlowDiamond({ label, sub, className }) {
|
|
1178
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("relative h-14 w-36 justify-self-center sm:h-16 sm:w-44", className), children: [
|
|
1179
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 bg-(--border-hi) [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]" }),
|
|
1180
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute inset-[1px] flex flex-col items-center justify-center gap-0.5 bg-(--surface) px-6 text-center [clip-path:polygon(50%_0,100%_50%,50%_100%,0_50%)]", children: [
|
|
1181
|
+
/* @__PURE__ */ jsx("p", { className: "text-[11px] font-semibold leading-tight text-foreground sm:text-[12px]", children: label }),
|
|
1182
|
+
sub ? /* @__PURE__ */ jsx("p", { className: "text-[8.5px] leading-tight text-(--foreground-muted)", children: sub }) : null
|
|
1183
|
+
] })
|
|
1184
|
+
] });
|
|
1185
|
+
}
|
|
1186
|
+
var glossLayer = cn(
|
|
1187
|
+
"pointer-events-none absolute inset-0 z-[-1] rounded-[inherit]",
|
|
1188
|
+
"[background-color:var(--btn-face)] [box-shadow:var(--shadow-button)]",
|
|
1189
|
+
"transition-shadow duration-150",
|
|
1190
|
+
// Pressed (and disabled): bevel + cast go transparent, the rim stays.
|
|
1191
|
+
"group-active/glossy:[box-shadow:var(--shadow-button-pressed)]",
|
|
1192
|
+
"group-disabled/glossy:[box-shadow:var(--shadow-button-pressed)]",
|
|
1193
|
+
// Dome — fixed direction, per-variant stops. Above the face, below the tint.
|
|
1194
|
+
"before:absolute before:inset-0 before:rounded-[inherit] before:content-[''] before:[background-image:var(--gradient-button)]",
|
|
1195
|
+
// Interaction tint. Hidden outright when disabled, and on touch (no hover
|
|
1196
|
+
// state to speak of) so the root's active:opacity can carry the press instead.
|
|
1197
|
+
"after:absolute after:inset-0 after:rounded-[inherit] after:content-[''] after:opacity-0",
|
|
1198
|
+
"after:[background-color:var(--btn-tint-hover)] after:transition-opacity after:duration-150 after:[will-change:opacity]",
|
|
1199
|
+
"group-hover/glossy:after:opacity-100",
|
|
1200
|
+
"group-active/glossy:after:[background-color:var(--btn-tint-active)]",
|
|
1201
|
+
"group-disabled/glossy:after:hidden [@media(hover:none)]:after:hidden"
|
|
1202
|
+
);
|
|
1203
|
+
var glossyButtonVariants = cva(
|
|
1204
|
+
cn(
|
|
1205
|
+
"glossy group/glossy relative isolate inline-flex cursor-pointer select-none items-center justify-center gap-1 whitespace-nowrap rounded-full font-normal",
|
|
1206
|
+
// Label colour rides the variant. Kept as a utility rather than a plain
|
|
1207
|
+
// declaration on `.glossy` so a caller's own text-* class still wins.
|
|
1208
|
+
"[color:var(--btn-fg)]",
|
|
1209
|
+
"disabled:cursor-default disabled:opacity-50",
|
|
1210
|
+
// Touch devices get no hover layer, so the whole key dims on press instead.
|
|
1211
|
+
"[@media(hover:none)]:active:opacity-80"
|
|
1212
|
+
),
|
|
1213
|
+
{
|
|
1214
|
+
variants: {
|
|
1215
|
+
size: {
|
|
1216
|
+
sm: "h-8 px-2.5 text-sm",
|
|
1217
|
+
md: "h-9 px-5 text-[17px]",
|
|
1218
|
+
lg: "h-11 px-6 text-[17px]"
|
|
1219
|
+
},
|
|
1220
|
+
/**
|
|
1221
|
+
* Written out as literal class names — Tailwind's scanner is static, so a
|
|
1222
|
+
* `glossy-${variant}` template would never make it into the stylesheet.
|
|
1223
|
+
* `neutral` is the bare recipe, so it needs no class of its own.
|
|
1224
|
+
*/
|
|
1225
|
+
variant: {
|
|
1226
|
+
neutral: "",
|
|
1227
|
+
accent: "glossy-accent",
|
|
1228
|
+
destructive: "glossy-destructive",
|
|
1229
|
+
special: "glossy-special",
|
|
1230
|
+
positive: "glossy-positive",
|
|
1231
|
+
attention: "glossy-attention",
|
|
1232
|
+
highlight: "glossy-highlight",
|
|
1233
|
+
inverse: "glossy-inverse"
|
|
1234
|
+
}
|
|
1235
|
+
},
|
|
1236
|
+
defaultVariants: { size: "md", variant: "neutral" }
|
|
1237
|
+
}
|
|
1238
|
+
);
|
|
1239
|
+
function GlossyButton({
|
|
1240
|
+
size,
|
|
1241
|
+
variant,
|
|
1242
|
+
actionOrLink,
|
|
1243
|
+
children,
|
|
1244
|
+
disabled,
|
|
1245
|
+
className,
|
|
1246
|
+
"aria-label": ariaLabel
|
|
1247
|
+
}) {
|
|
1248
|
+
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1249
|
+
/* @__PURE__ */ jsx("span", { "data-fx-layer": "gloss", "aria-hidden": true, className: glossLayer }),
|
|
1250
|
+
/* @__PURE__ */ jsx("span", { className: "px-0.5", children })
|
|
1251
|
+
] });
|
|
1252
|
+
const buttonClassName = cn(glossyButtonVariants({ size, variant }), className);
|
|
1253
|
+
if (typeof actionOrLink === "string")
|
|
1254
|
+
return /* @__PURE__ */ jsx("a", { href: actionOrLink, className: cn(buttonClassName, "no-underline"), "aria-label": ariaLabel, children: content });
|
|
1255
|
+
return /* @__PURE__ */ jsx("button", { type: "button", className: buttonClassName, onClick: actionOrLink, disabled, "aria-label": ariaLabel, children: content });
|
|
1256
|
+
}
|
|
1257
|
+
var vertex = `#version 300 es
|
|
1258
|
+
in vec2 position;
|
|
1259
|
+
void main() {
|
|
1260
|
+
gl_Position = vec4(position, 0.0, 1.0);
|
|
1261
|
+
}
|
|
1262
|
+
`;
|
|
1263
|
+
var fragment = `#version 300 es
|
|
1264
|
+
precision highp float;
|
|
1265
|
+
uniform vec2 iResolution;
|
|
1266
|
+
uniform float iTime;
|
|
1267
|
+
uniform float uTimeSpeed;
|
|
1268
|
+
uniform float uColorBalance;
|
|
1269
|
+
uniform float uWarpStrength;
|
|
1270
|
+
uniform float uWarpFrequency;
|
|
1271
|
+
uniform float uWarpSpeed;
|
|
1272
|
+
uniform float uWarpAmplitude;
|
|
1273
|
+
uniform float uBlendAngle;
|
|
1274
|
+
uniform float uBlendSoftness;
|
|
1275
|
+
uniform float uRotationAmount;
|
|
1276
|
+
uniform float uNoiseScale;
|
|
1277
|
+
uniform float uGrainAmount;
|
|
1278
|
+
uniform float uGrainScale;
|
|
1279
|
+
uniform float uGrainAnimated;
|
|
1280
|
+
uniform float uContrast;
|
|
1281
|
+
uniform float uGamma;
|
|
1282
|
+
uniform float uSaturation;
|
|
1283
|
+
uniform vec2 uCenterOffset;
|
|
1284
|
+
uniform float uZoom;
|
|
1285
|
+
uniform vec3 uColor1;
|
|
1286
|
+
uniform vec3 uColor2;
|
|
1287
|
+
uniform vec3 uColor3;
|
|
1288
|
+
out vec4 fragColor;
|
|
1289
|
+
#define S(a,b,t) smoothstep(a,b,t)
|
|
1290
|
+
mat2 Rot(float a){float s=sin(a),c=cos(a);return mat2(c,-s,s,c);}
|
|
1291
|
+
vec2 hash(vec2 p){p=vec2(dot(p,vec2(2127.1,81.17)),dot(p,vec2(1269.5,283.37)));return fract(sin(p)*43758.5453);}
|
|
1292
|
+
float noise(vec2 p){vec2 i=floor(p),f=fract(p),u=f*f*(3.0-2.0*f);float n=mix(mix(dot(-1.0+2.0*hash(i+vec2(0.0,0.0)),f-vec2(0.0,0.0)),dot(-1.0+2.0*hash(i+vec2(1.0,0.0)),f-vec2(1.0,0.0)),u.x),mix(dot(-1.0+2.0*hash(i+vec2(0.0,1.0)),f-vec2(0.0,1.0)),dot(-1.0+2.0*hash(i+vec2(1.0,1.0)),f-vec2(1.0,1.0)),u.x),u.y);return 0.5+0.5*n;}
|
|
1293
|
+
void mainImage(out vec4 o, vec2 C){
|
|
1294
|
+
float t=iTime*uTimeSpeed;
|
|
1295
|
+
vec2 uv=C/iResolution.xy;
|
|
1296
|
+
float ratio=iResolution.x/iResolution.y;
|
|
1297
|
+
vec2 tuv=uv-0.5+uCenterOffset;
|
|
1298
|
+
tuv/=max(uZoom,0.001);
|
|
1299
|
+
float degree=noise(vec2(t*0.1,tuv.x*tuv.y)*uNoiseScale);
|
|
1300
|
+
tuv.y*=1.0/ratio;
|
|
1301
|
+
tuv*=Rot(radians((degree-0.5)*uRotationAmount+180.0));
|
|
1302
|
+
tuv.y*=ratio;
|
|
1303
|
+
float frequency=uWarpFrequency;
|
|
1304
|
+
float ws=max(uWarpStrength,0.001);
|
|
1305
|
+
float amplitude=uWarpAmplitude/ws;
|
|
1306
|
+
float warpTime=t*uWarpSpeed;
|
|
1307
|
+
tuv.x+=sin(tuv.y*frequency+warpTime)/amplitude;
|
|
1308
|
+
tuv.y+=sin(tuv.x*(frequency*1.5)+warpTime)/(amplitude*0.5);
|
|
1309
|
+
vec3 colLav=uColor1;
|
|
1310
|
+
vec3 colOrg=uColor2;
|
|
1311
|
+
vec3 colDark=uColor3;
|
|
1312
|
+
float b=uColorBalance;
|
|
1313
|
+
float s=max(uBlendSoftness,0.0);
|
|
1314
|
+
mat2 blendRot=Rot(radians(uBlendAngle));
|
|
1315
|
+
float blendX=(tuv*blendRot).x;
|
|
1316
|
+
float edge0=-0.3-b-s;
|
|
1317
|
+
float edge1=0.2-b+s;
|
|
1318
|
+
float v0=0.5-b+s;
|
|
1319
|
+
float v1=-0.3-b-s;
|
|
1320
|
+
vec3 layer1=mix(colDark,colOrg,S(edge0,edge1,blendX));
|
|
1321
|
+
vec3 layer2=mix(colOrg,colLav,S(edge0,edge1,blendX));
|
|
1322
|
+
vec3 col=mix(layer1,layer2,S(v0,v1,tuv.y));
|
|
1323
|
+
vec2 grainUv=uv*max(uGrainScale,0.001);
|
|
1324
|
+
if(uGrainAnimated>0.5){grainUv+=vec2(iTime*0.05);}
|
|
1325
|
+
float grain=fract(sin(dot(grainUv,vec2(12.9898,78.233)))*43758.5453);
|
|
1326
|
+
col+=(grain-0.5)*uGrainAmount;
|
|
1327
|
+
col=(col-0.5)*uContrast+0.5;
|
|
1328
|
+
float luma=dot(col,vec3(0.2126,0.7152,0.0722));
|
|
1329
|
+
col=mix(vec3(luma),col,uSaturation);
|
|
1330
|
+
col=pow(max(col,0.0),vec3(1.0/max(uGamma,0.001)));
|
|
1331
|
+
col=clamp(col,0.0,1.0);
|
|
1332
|
+
o=vec4(col,1.0);
|
|
1333
|
+
}
|
|
1334
|
+
void main(){
|
|
1335
|
+
vec4 o=vec4(0.0);
|
|
1336
|
+
mainImage(o,gl_FragCoord.xy);
|
|
1337
|
+
fragColor=o;
|
|
1338
|
+
}
|
|
1339
|
+
`;
|
|
1340
|
+
function createGrainientProgram(gl) {
|
|
1341
|
+
return new Program(gl, {
|
|
1342
|
+
vertex,
|
|
1343
|
+
fragment,
|
|
1344
|
+
uniforms: {
|
|
1345
|
+
iTime: { value: 0 },
|
|
1346
|
+
iResolution: { value: new Float32Array([1, 1]) },
|
|
1347
|
+
uTimeSpeed: { value: 0.25 },
|
|
1348
|
+
uColorBalance: { value: 0 },
|
|
1349
|
+
uWarpStrength: { value: 1 },
|
|
1350
|
+
uWarpFrequency: { value: 5 },
|
|
1351
|
+
uWarpSpeed: { value: 2 },
|
|
1352
|
+
uWarpAmplitude: { value: 50 },
|
|
1353
|
+
uBlendAngle: { value: 0 },
|
|
1354
|
+
uBlendSoftness: { value: 0.05 },
|
|
1355
|
+
uRotationAmount: { value: 500 },
|
|
1356
|
+
uNoiseScale: { value: 2 },
|
|
1357
|
+
uGrainAmount: { value: 0.1 },
|
|
1358
|
+
uGrainScale: { value: 2 },
|
|
1359
|
+
uGrainAnimated: { value: 0 },
|
|
1360
|
+
uContrast: { value: 1.5 },
|
|
1361
|
+
uGamma: { value: 1 },
|
|
1362
|
+
uSaturation: { value: 1 },
|
|
1363
|
+
uCenterOffset: { value: new Float32Array([0, 0]) },
|
|
1364
|
+
uZoom: { value: 0.9 },
|
|
1365
|
+
uColor1: { value: new Float32Array([1, 1, 1]) },
|
|
1366
|
+
uColor2: { value: new Float32Array([1, 1, 1]) },
|
|
1367
|
+
uColor3: { value: new Float32Array([1, 1, 1]) }
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1371
|
+
var ctxMap = /* @__PURE__ */ new WeakMap();
|
|
1372
|
+
var HEX_COLOR_RE = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i;
|
|
1373
|
+
var hexToRgb = (hex) => {
|
|
1374
|
+
const result = HEX_COLOR_RE.exec(hex);
|
|
1375
|
+
if (!result) return [1, 1, 1];
|
|
1376
|
+
const [, r = "ff", g = "ff", b = "ff"] = result;
|
|
1377
|
+
return [Number.parseInt(r, 16) / 255, Number.parseInt(g, 16) / 255, Number.parseInt(b, 16) / 255];
|
|
1378
|
+
};
|
|
1379
|
+
var prefersReducedMotion = () => typeof globalThis !== "undefined" && globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
1380
|
+
var isLowPowerClient = () => {
|
|
1381
|
+
if (typeof globalThis === "undefined") return false;
|
|
1382
|
+
const narrow = globalThis.matchMedia?.("(max-width: 1023px)").matches === true;
|
|
1383
|
+
const fewCores = typeof navigator !== "undefined" && typeof navigator.hardwareConcurrency === "number" && navigator.hardwareConcurrency <= 4;
|
|
1384
|
+
return narrow || fewCores;
|
|
1385
|
+
};
|
|
1386
|
+
var GRAIN_LAYER = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.12'/%3E%3C/svg%3E")`;
|
|
1387
|
+
var fallbackGradient = (c1, c2, c3) => `${GRAIN_LAYER}, linear-gradient(135deg, ${c1} 0%, ${c2} 55%, ${c3} 100%)`;
|
|
1388
|
+
var applyStaticBg = (el, src) => {
|
|
1389
|
+
el.style.backgroundImage = `url(${src})`;
|
|
1390
|
+
el.style.backgroundSize = "cover";
|
|
1391
|
+
el.style.backgroundPosition = "center";
|
|
1392
|
+
};
|
|
1393
|
+
function initGrainient(container) {
|
|
1394
|
+
const renderer = new Renderer({
|
|
1395
|
+
webgl: 2,
|
|
1396
|
+
alpha: true,
|
|
1397
|
+
antialias: false,
|
|
1398
|
+
dpr: Math.min(globalThis.devicePixelRatio || 1, 2)
|
|
1399
|
+
});
|
|
1400
|
+
const gl = renderer.gl;
|
|
1401
|
+
const canvas = gl.canvas;
|
|
1402
|
+
canvas.style.width = "100%";
|
|
1403
|
+
canvas.style.height = "100%";
|
|
1404
|
+
canvas.style.display = "block";
|
|
1405
|
+
container.appendChild(canvas);
|
|
1406
|
+
const geometry = new Triangle(gl);
|
|
1407
|
+
const program = createGrainientProgram(gl);
|
|
1408
|
+
const mesh = new Mesh(gl, { geometry, program });
|
|
1409
|
+
ctxMap.set(container, { renderer, program, mesh });
|
|
1410
|
+
const setSize = () => {
|
|
1411
|
+
const rect = container.getBoundingClientRect();
|
|
1412
|
+
renderer.setSize(Math.max(1, Math.floor(rect.width)), Math.max(1, Math.floor(rect.height)));
|
|
1413
|
+
const res = program.uniforms.iResolution.value;
|
|
1414
|
+
res[0] = gl.drawingBufferWidth;
|
|
1415
|
+
res[1] = gl.drawingBufferHeight;
|
|
1416
|
+
renderer.render({ scene: mesh });
|
|
1417
|
+
};
|
|
1418
|
+
const ro = new ResizeObserver(setSize);
|
|
1419
|
+
ro.observe(container);
|
|
1420
|
+
setSize();
|
|
1421
|
+
let raf = 0;
|
|
1422
|
+
let isVisible = true;
|
|
1423
|
+
let isPageVisible = !document.hidden;
|
|
1424
|
+
const t0 = performance.now();
|
|
1425
|
+
const loop = (t) => {
|
|
1426
|
+
program.uniforms.iTime.value = (t - t0) * 1e-3;
|
|
1427
|
+
renderer.render({ scene: mesh });
|
|
1428
|
+
raf = requestAnimationFrame(loop);
|
|
1429
|
+
};
|
|
1430
|
+
const tryStart = () => {
|
|
1431
|
+
if (isVisible && isPageVisible && raf === 0) raf = requestAnimationFrame(loop);
|
|
1432
|
+
};
|
|
1433
|
+
const tryStop = () => {
|
|
1434
|
+
if (raf !== 0) {
|
|
1435
|
+
cancelAnimationFrame(raf);
|
|
1436
|
+
raf = 0;
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1439
|
+
const reduce = prefersReducedMotion();
|
|
1440
|
+
const io = new IntersectionObserver(
|
|
1441
|
+
([entry]) => {
|
|
1442
|
+
if (!entry) return;
|
|
1443
|
+
isVisible = entry.isIntersecting;
|
|
1444
|
+
if (isVisible) tryStart();
|
|
1445
|
+
else tryStop();
|
|
1446
|
+
},
|
|
1447
|
+
{ threshold: 0 }
|
|
1448
|
+
);
|
|
1449
|
+
if (!reduce) io.observe(container);
|
|
1450
|
+
const onVisibility = () => {
|
|
1451
|
+
isPageVisible = !document.hidden;
|
|
1452
|
+
if (isPageVisible) tryStart();
|
|
1453
|
+
else tryStop();
|
|
1454
|
+
};
|
|
1455
|
+
if (!reduce) document.addEventListener("visibilitychange", onVisibility);
|
|
1456
|
+
if (!reduce) tryStart();
|
|
1457
|
+
return () => {
|
|
1458
|
+
tryStop();
|
|
1459
|
+
ro.disconnect();
|
|
1460
|
+
io.disconnect();
|
|
1461
|
+
document.removeEventListener("visibilitychange", onVisibility);
|
|
1462
|
+
ctxMap.delete(container);
|
|
1463
|
+
try {
|
|
1464
|
+
container.removeChild(canvas);
|
|
1465
|
+
} catch {
|
|
1466
|
+
}
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
var Grainient = (props) => {
|
|
1470
|
+
const {
|
|
1471
|
+
timeSpeed = 0.25,
|
|
1472
|
+
colorBalance = 0,
|
|
1473
|
+
warpStrength = 1,
|
|
1474
|
+
warpFrequency = 5,
|
|
1475
|
+
warpSpeed = 2,
|
|
1476
|
+
warpAmplitude = 50,
|
|
1477
|
+
blendAngle = 0,
|
|
1478
|
+
blendSoftness = 0.05,
|
|
1479
|
+
rotationAmount = 500,
|
|
1480
|
+
noiseScale = 2,
|
|
1481
|
+
grainAmount = 0.1,
|
|
1482
|
+
grainScale = 2,
|
|
1483
|
+
grainAnimated = false,
|
|
1484
|
+
contrast = 1.5,
|
|
1485
|
+
gamma = 1,
|
|
1486
|
+
saturation = 1,
|
|
1487
|
+
centerX = 0,
|
|
1488
|
+
centerY = 0,
|
|
1489
|
+
zoom = 0.9,
|
|
1490
|
+
color1 = "#FF9FFC",
|
|
1491
|
+
color2 = "#5227FF",
|
|
1492
|
+
color3 = "#B497CF",
|
|
1493
|
+
staticSrc = "",
|
|
1494
|
+
className = ""
|
|
1495
|
+
} = props;
|
|
1496
|
+
const containerRef = useRef(null);
|
|
1497
|
+
const fallbackRef = useRef(false);
|
|
1498
|
+
useEffect(() => {
|
|
1499
|
+
const container = containerRef.current;
|
|
1500
|
+
if (!container) return;
|
|
1501
|
+
if (isLowPowerClient() || prefersReducedMotion()) {
|
|
1502
|
+
fallbackRef.current = true;
|
|
1503
|
+
container.dataset.fallback = "true";
|
|
1504
|
+
if (staticSrc) applyStaticBg(container, staticSrc);
|
|
1505
|
+
else container.style.background = fallbackGradient(color1, color2, color3);
|
|
1506
|
+
return;
|
|
1507
|
+
}
|
|
1508
|
+
return initGrainient(container);
|
|
1509
|
+
}, []);
|
|
1510
|
+
useEffect(() => {
|
|
1511
|
+
const container = containerRef.current;
|
|
1512
|
+
if (!container) return;
|
|
1513
|
+
if (fallbackRef.current) {
|
|
1514
|
+
if (staticSrc) applyStaticBg(container, staticSrc);
|
|
1515
|
+
else container.style.background = fallbackGradient(color1, color2, color3);
|
|
1516
|
+
return;
|
|
1517
|
+
}
|
|
1518
|
+
const ctx = ctxMap.get(container);
|
|
1519
|
+
if (!ctx) return;
|
|
1520
|
+
const { program, renderer, mesh } = ctx;
|
|
1521
|
+
const u = program.uniforms;
|
|
1522
|
+
u.uTimeSpeed.value = timeSpeed;
|
|
1523
|
+
u.uColorBalance.value = colorBalance;
|
|
1524
|
+
u.uWarpStrength.value = warpStrength;
|
|
1525
|
+
u.uWarpFrequency.value = warpFrequency;
|
|
1526
|
+
u.uWarpSpeed.value = warpSpeed;
|
|
1527
|
+
u.uWarpAmplitude.value = warpAmplitude;
|
|
1528
|
+
u.uBlendAngle.value = blendAngle;
|
|
1529
|
+
u.uBlendSoftness.value = blendSoftness;
|
|
1530
|
+
u.uRotationAmount.value = rotationAmount;
|
|
1531
|
+
u.uNoiseScale.value = noiseScale;
|
|
1532
|
+
u.uGrainAmount.value = grainAmount;
|
|
1533
|
+
u.uGrainScale.value = grainScale;
|
|
1534
|
+
u.uGrainAnimated.value = grainAnimated ? 1 : 0;
|
|
1535
|
+
u.uContrast.value = contrast;
|
|
1536
|
+
u.uGamma.value = gamma;
|
|
1537
|
+
u.uSaturation.value = saturation;
|
|
1538
|
+
u.uCenterOffset.value = new Float32Array([centerX, centerY]);
|
|
1539
|
+
u.uZoom.value = zoom;
|
|
1540
|
+
u.uColor1.value = new Float32Array(hexToRgb(color1));
|
|
1541
|
+
u.uColor2.value = new Float32Array(hexToRgb(color2));
|
|
1542
|
+
u.uColor3.value = new Float32Array(hexToRgb(color3));
|
|
1543
|
+
if (prefersReducedMotion()) renderer.render({ scene: mesh });
|
|
1544
|
+
}, [
|
|
1545
|
+
timeSpeed,
|
|
1546
|
+
colorBalance,
|
|
1547
|
+
warpStrength,
|
|
1548
|
+
warpFrequency,
|
|
1549
|
+
warpSpeed,
|
|
1550
|
+
warpAmplitude,
|
|
1551
|
+
blendAngle,
|
|
1552
|
+
blendSoftness,
|
|
1553
|
+
rotationAmount,
|
|
1554
|
+
noiseScale,
|
|
1555
|
+
grainAmount,
|
|
1556
|
+
grainScale,
|
|
1557
|
+
grainAnimated,
|
|
1558
|
+
contrast,
|
|
1559
|
+
gamma,
|
|
1560
|
+
saturation,
|
|
1561
|
+
centerX,
|
|
1562
|
+
centerY,
|
|
1563
|
+
zoom,
|
|
1564
|
+
color1,
|
|
1565
|
+
color2,
|
|
1566
|
+
color3,
|
|
1567
|
+
staticSrc
|
|
1568
|
+
]);
|
|
1569
|
+
return /* @__PURE__ */ jsx("div", { ref: containerRef, className: cn("grainient-container", className) });
|
|
1570
|
+
};
|
|
1571
|
+
var grainient_default = Grainient;
|
|
1572
|
+
function useMediaQuery(query, defaultState = false) {
|
|
1573
|
+
const [matches, setMatches] = useState(defaultState);
|
|
1574
|
+
useEffect(() => {
|
|
1575
|
+
const mql = globalThis.matchMedia(query);
|
|
1576
|
+
setMatches(mql.matches);
|
|
1577
|
+
const onChange = (e) => setMatches(e.matches);
|
|
1578
|
+
mql.addEventListener("change", onChange);
|
|
1579
|
+
return () => mql.removeEventListener("change", onChange);
|
|
1580
|
+
}, [query]);
|
|
1581
|
+
return matches;
|
|
1582
|
+
}
|
|
1583
|
+
function resolveColor(element, color) {
|
|
1584
|
+
if (!color.startsWith("var(")) return color;
|
|
1585
|
+
const token = color.slice(4, -1).trim();
|
|
1586
|
+
return globalThis.getComputedStyle(element).getPropertyValue(token).trim() || color;
|
|
1587
|
+
}
|
|
1588
|
+
var BREAKPOINTS = [
|
|
1589
|
+
["xs", 30],
|
|
1590
|
+
["sm", 40],
|
|
1591
|
+
["md", 50],
|
|
1592
|
+
["lg", 64],
|
|
1593
|
+
["xl", 80],
|
|
1594
|
+
["2xl", 96]
|
|
1595
|
+
];
|
|
1596
|
+
function getBreakpoint() {
|
|
1597
|
+
let current = "base";
|
|
1598
|
+
for (const [name, rem] of BREAKPOINTS) {
|
|
1599
|
+
if (globalThis.matchMedia(`(min-width: ${rem}rem)`).matches) current = name;
|
|
1600
|
+
}
|
|
1601
|
+
return current;
|
|
1602
|
+
}
|
|
1603
|
+
function onBreakpointChange(listener) {
|
|
1604
|
+
const queries = BREAKPOINTS.map(([, rem]) => globalThis.matchMedia(`(min-width: ${rem}rem)`));
|
|
1605
|
+
for (const query of queries) query.addEventListener("change", listener);
|
|
1606
|
+
return () => {
|
|
1607
|
+
for (const query of queries) query.removeEventListener("change", listener);
|
|
1608
|
+
};
|
|
1609
|
+
}
|
|
1610
|
+
function Highlighter({
|
|
1611
|
+
children,
|
|
1612
|
+
className,
|
|
1613
|
+
action = "highlight",
|
|
1614
|
+
color = "var(--marker-highlight)",
|
|
1615
|
+
strokeWidth = 1.5,
|
|
1616
|
+
animationDuration = 600,
|
|
1617
|
+
delay = 0,
|
|
1618
|
+
iterations = 2,
|
|
1619
|
+
padding = 2,
|
|
1620
|
+
multiline = true,
|
|
1621
|
+
isView = false
|
|
1622
|
+
}) {
|
|
1623
|
+
const elementRef = useRef(null);
|
|
1624
|
+
const isInView = useInView(elementRef, { once: true, margin: "-10%" });
|
|
1625
|
+
const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
1626
|
+
const [themeVersion, setThemeVersion] = useState(0);
|
|
1627
|
+
const shouldShow = !isView || isInView;
|
|
1628
|
+
useLayoutEffect(() => {
|
|
1629
|
+
const observer = new MutationObserver(() => setThemeVersion((v) => v + 1));
|
|
1630
|
+
observer.observe(document.documentElement, { attributes: true, attributeFilter: ["class"] });
|
|
1631
|
+
return () => observer.disconnect();
|
|
1632
|
+
}, []);
|
|
1633
|
+
useLayoutEffect(() => {
|
|
1634
|
+
const element = elementRef.current;
|
|
1635
|
+
if (!(shouldShow && element)) return;
|
|
1636
|
+
let annotation;
|
|
1637
|
+
let untrack;
|
|
1638
|
+
const draw = () => {
|
|
1639
|
+
annotation = annotate(element, {
|
|
1640
|
+
type: action,
|
|
1641
|
+
color: resolveColor(element, color),
|
|
1642
|
+
strokeWidth,
|
|
1643
|
+
animationDuration,
|
|
1644
|
+
animate: !reducedMotion,
|
|
1645
|
+
iterations,
|
|
1646
|
+
padding,
|
|
1647
|
+
multiline
|
|
1648
|
+
});
|
|
1649
|
+
annotation.show();
|
|
1650
|
+
let drawnAt = getBreakpoint();
|
|
1651
|
+
untrack = onBreakpointChange(() => {
|
|
1652
|
+
const current = getBreakpoint();
|
|
1653
|
+
if (current === drawnAt) return;
|
|
1654
|
+
drawnAt = current;
|
|
1655
|
+
annotation?.show();
|
|
1656
|
+
});
|
|
1657
|
+
};
|
|
1658
|
+
const startDelay = reducedMotion ? 0 : delay;
|
|
1659
|
+
const timer2 = startDelay > 0 ? globalThis.setTimeout(draw, startDelay) : void 0;
|
|
1660
|
+
if (timer2 === void 0) draw();
|
|
1661
|
+
return () => {
|
|
1662
|
+
globalThis.clearTimeout(timer2);
|
|
1663
|
+
untrack?.();
|
|
1664
|
+
annotation?.remove();
|
|
1665
|
+
};
|
|
1666
|
+
}, [
|
|
1667
|
+
shouldShow,
|
|
1668
|
+
action,
|
|
1669
|
+
color,
|
|
1670
|
+
strokeWidth,
|
|
1671
|
+
animationDuration,
|
|
1672
|
+
delay,
|
|
1673
|
+
iterations,
|
|
1674
|
+
padding,
|
|
1675
|
+
multiline,
|
|
1676
|
+
reducedMotion,
|
|
1677
|
+
themeVersion
|
|
1678
|
+
]);
|
|
1679
|
+
return /* @__PURE__ */ jsx("span", { className: cn("relative inline-block bg-transparent", className), children: /* @__PURE__ */ jsx("span", { ref: elementRef, children }) });
|
|
1680
|
+
}
|
|
1681
|
+
var FIELD_BORDER = {
|
|
1682
|
+
idle: "border-(--color-border)",
|
|
1683
|
+
focused: "border-(--color-foreground)/40",
|
|
1684
|
+
error: "border-(--color-destructive)"
|
|
1685
|
+
};
|
|
1686
|
+
var FIELD_HEIGHT = {
|
|
1687
|
+
sm: "h-8",
|
|
1688
|
+
md: "h-9",
|
|
1689
|
+
lg: "h-11"
|
|
1690
|
+
};
|
|
1691
|
+
var FIELD_SHAPE = {
|
|
1692
|
+
rounded: "rounded-lg",
|
|
1693
|
+
pill: "rounded-full"
|
|
1694
|
+
};
|
|
1695
|
+
var INPUT_SIZE = {
|
|
1696
|
+
sm: "text-xs",
|
|
1697
|
+
md: "text-sm",
|
|
1698
|
+
lg: "text-base"
|
|
1699
|
+
};
|
|
1700
|
+
var INPUT_PAD = {
|
|
1701
|
+
sm: "px-2.5",
|
|
1702
|
+
md: "px-3",
|
|
1703
|
+
lg: "px-3.5"
|
|
1704
|
+
};
|
|
1705
|
+
function Input({
|
|
1706
|
+
label,
|
|
1707
|
+
error,
|
|
1708
|
+
hint,
|
|
1709
|
+
leftAdornment,
|
|
1710
|
+
rightAdornment,
|
|
1711
|
+
size = "md",
|
|
1712
|
+
shape = "rounded",
|
|
1713
|
+
className,
|
|
1714
|
+
inputClassName,
|
|
1715
|
+
inputType = "text",
|
|
1716
|
+
id: idProp,
|
|
1717
|
+
onFocus,
|
|
1718
|
+
onBlur,
|
|
1719
|
+
disabled,
|
|
1720
|
+
autoFocus,
|
|
1721
|
+
...inputProps
|
|
1722
|
+
}) {
|
|
1723
|
+
const autoId = useId();
|
|
1724
|
+
const id = idProp ?? autoId;
|
|
1725
|
+
const [focused, setFocused] = useState(false);
|
|
1726
|
+
const hasError = Boolean(error);
|
|
1727
|
+
const errorMessage = typeof error === "string" ? error : null;
|
|
1728
|
+
const state = hasError ? "error" : focused ? "focused" : "idle";
|
|
1729
|
+
const hasLeft = Boolean(leftAdornment);
|
|
1730
|
+
const hasRight = Boolean(rightAdornment);
|
|
1731
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1.5", className), children: [
|
|
1732
|
+
label ? /* @__PURE__ */ jsx("label", { htmlFor: id, className: "px-1 font-medium text-(--color-foreground) text-sm", children: label }) : null,
|
|
1733
|
+
/* @__PURE__ */ jsxs(
|
|
1734
|
+
"div",
|
|
1735
|
+
{
|
|
1736
|
+
className: cn(
|
|
1737
|
+
"relative flex flex-row items-center overflow-hidden border",
|
|
1738
|
+
FIELD_BORDER[state],
|
|
1739
|
+
FIELD_HEIGHT[size],
|
|
1740
|
+
FIELD_SHAPE[shape],
|
|
1741
|
+
disabled && "opacity-60"
|
|
1742
|
+
),
|
|
1743
|
+
children: [
|
|
1744
|
+
hasLeft ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute top-0 bottom-0 left-3 z-10 flex items-center justify-center", children: leftAdornment }) : null,
|
|
1745
|
+
/* @__PURE__ */ jsx(
|
|
1746
|
+
"input",
|
|
1747
|
+
{
|
|
1748
|
+
id,
|
|
1749
|
+
type: inputType,
|
|
1750
|
+
disabled,
|
|
1751
|
+
autoFocus,
|
|
1752
|
+
onFocus: (event_) => {
|
|
1753
|
+
setFocused(true);
|
|
1754
|
+
onFocus?.(event_);
|
|
1755
|
+
},
|
|
1756
|
+
onBlur: (event_) => {
|
|
1757
|
+
setFocused(false);
|
|
1758
|
+
onBlur?.(event_);
|
|
1759
|
+
},
|
|
1760
|
+
className: cn(
|
|
1761
|
+
"h-full min-w-0 flex-1 bg-transparent text-(--color-foreground) outline-none",
|
|
1762
|
+
INPUT_SIZE[size],
|
|
1763
|
+
hasLeft ? "pl-10" : INPUT_PAD[size],
|
|
1764
|
+
hasRight ? "pr-10" : INPUT_PAD[size],
|
|
1765
|
+
inputClassName
|
|
1766
|
+
),
|
|
1767
|
+
...inputProps
|
|
1768
|
+
}
|
|
1769
|
+
),
|
|
1770
|
+
hasRight ? /* @__PURE__ */ jsx("div", { className: "pointer-events-none absolute top-0 right-3 bottom-0 z-10 flex items-center justify-center", children: rightAdornment }) : null
|
|
1771
|
+
]
|
|
1772
|
+
}
|
|
1773
|
+
),
|
|
1774
|
+
errorMessage ? /* @__PURE__ */ jsx("p", { role: "alert", className: "px-1 text-(--color-destructive) text-xs", children: errorMessage }) : hint ? /* @__PURE__ */ jsx("p", { className: "px-1 text-(--color-muted-foreground) text-xs", children: hint }) : null
|
|
1775
|
+
] });
|
|
1776
|
+
}
|
|
1777
|
+
function LiquidMetal({
|
|
1778
|
+
colorBack = "#aaaaac",
|
|
1779
|
+
colorTint = "#ffffff",
|
|
1780
|
+
speed = 0.5,
|
|
1781
|
+
repetition = 4,
|
|
1782
|
+
distortion = 0.1,
|
|
1783
|
+
scale = 1,
|
|
1784
|
+
className,
|
|
1785
|
+
style
|
|
1786
|
+
}) {
|
|
1787
|
+
return /* @__PURE__ */ jsx("div", { "aria-hidden": true, className: cn("pointer-events-none absolute inset-0 z-0 overflow-hidden", className), style, children: /* @__PURE__ */ jsx(
|
|
1788
|
+
LiquidMetal$1,
|
|
1789
|
+
{
|
|
1790
|
+
colorBack,
|
|
1791
|
+
colorTint,
|
|
1792
|
+
speed,
|
|
1793
|
+
repetition,
|
|
1794
|
+
distortion,
|
|
1795
|
+
softness: 0,
|
|
1796
|
+
shiftRed: 0.3,
|
|
1797
|
+
shiftBlue: -0.3,
|
|
1798
|
+
angle: 45,
|
|
1799
|
+
shape: "none",
|
|
1800
|
+
scale,
|
|
1801
|
+
fit: "cover",
|
|
1802
|
+
style: { width: "100%", height: "100%" }
|
|
1803
|
+
}
|
|
1804
|
+
) });
|
|
1805
|
+
}
|
|
1806
|
+
function ChevronDownIcon2(props) {
|
|
1807
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", ...props, children: /* @__PURE__ */ jsx("path", { d: "M1 3.5L5 7.5L9 3.5", stroke: "currentColor", strokeWidth: "1.5" }) });
|
|
1808
|
+
}
|
|
1809
|
+
function ChevronRightIcon(props) {
|
|
1810
|
+
return /* @__PURE__ */ jsx("svg", { "aria-hidden": "true", width: "10", height: "10", viewBox: "0 0 10 10", fill: "none", ...props, children: /* @__PURE__ */ jsx("path", { d: "M3.5 1L7.5 5L3.5 9", stroke: "currentColor", strokeWidth: "1.5" }) });
|
|
1811
|
+
}
|
|
1812
|
+
function ArrowSvg(props) {
|
|
1813
|
+
return /* @__PURE__ */ jsxs("svg", { "aria-hidden": "true", width: "20", height: "10", viewBox: "0 0 20 10", fill: "none", ...props, children: [
|
|
1814
|
+
/* @__PURE__ */ jsx(
|
|
1815
|
+
"path",
|
|
1816
|
+
{
|
|
1817
|
+
d: "M9.66437 2.60207L4.80758 6.97318C4.07308 7.63423 3.11989 8 2.13172 8H0V10H20V8H18.5349C17.5468 8 16.5936 7.63423 15.8591 6.97318L11.0023 2.60207C10.622 2.2598 10.0447 2.25979 9.66437 2.60207Z",
|
|
1818
|
+
className: "fill-(--popup-surface,var(--surface-3))"
|
|
1819
|
+
}
|
|
1820
|
+
),
|
|
1821
|
+
/* @__PURE__ */ jsx(
|
|
1822
|
+
"path",
|
|
1823
|
+
{
|
|
1824
|
+
d: "M8.99542 1.85876C9.75604 1.17425 10.9106 1.17422 11.6713 1.85878L16.5281 6.22989C17.0789 6.72568 17.7938 7.00001 18.5349 7.00001L15.89 7L11.0023 2.60207C10.622 2.2598 10.0447 2.2598 9.66436 2.60207L4.77734 7L2.13171 7.00001C2.87284 7.00001 3.58774 6.72568 4.13861 6.22989L8.99542 1.85876Z",
|
|
1825
|
+
className: "fill-border"
|
|
1826
|
+
}
|
|
1827
|
+
),
|
|
1828
|
+
/* @__PURE__ */ jsx(
|
|
1829
|
+
"path",
|
|
1830
|
+
{
|
|
1831
|
+
d: "M10.3333 3.34539L5.47654 7.71648C4.55842 8.54279 3.36693 9 2.13172 9H0V8H2.13172C3.11989 8 4.07308 7.63423 4.80758 6.97318L9.66437 2.60207C10.0447 2.25979 10.622 2.2598 11.0023 2.60207L15.8591 6.97318C16.5936 7.63423 17.5468 8 18.5349 8H20V9H18.5349C17.2998 9 16.1083 8.54278 15.1901 7.71648L10.3333 3.34539Z",
|
|
1832
|
+
className: "fill-border"
|
|
1833
|
+
}
|
|
1834
|
+
)
|
|
1835
|
+
] });
|
|
1836
|
+
}
|
|
1837
|
+
var navigationMenuTriggerStyle = cva(
|
|
1838
|
+
"box-border flex items-center justify-center gap-1.5 h-10 px-2.5 xs:px-3 m-0 rounded-md text-foreground font-medium !text-[15px] leading-6 select-none no-underline hover:text-foreground data-[popup-open]:bg-black/[0.07] dark:data-[popup-open]:bg-white/[0.07] data-[popup-open]:text-foreground focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-ring focus-visible:relative"
|
|
1839
|
+
);
|
|
1840
|
+
var navigationMenuSubTriggerStyle = cva(
|
|
1841
|
+
"w-full text-left relative block rounded-md p-2.5 xs:p-3 no-underline text-inherit hover:bg-black/[0.07] dark:hover:bg-white/[0.07] hover:text-foreground active:bg-black/[0.11] dark:active:bg-white/[0.11] focus-visible:relative focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-1 focus-visible:outline-ring data-[popup-open]:bg-black/[0.07] dark:data-[popup-open]:bg-white/[0.07] data-[popup-open]:text-foreground"
|
|
1842
|
+
);
|
|
1843
|
+
function NavigationMenu({
|
|
1844
|
+
className,
|
|
1845
|
+
children,
|
|
1846
|
+
side,
|
|
1847
|
+
sideOffset = 10,
|
|
1848
|
+
align,
|
|
1849
|
+
alignOffset,
|
|
1850
|
+
collisionPadding = { top: 5, bottom: 5, left: 20, right: 20 },
|
|
1851
|
+
collisionBoundary,
|
|
1852
|
+
arrow = false,
|
|
1853
|
+
positionMethod = "fixed",
|
|
1854
|
+
level = 2,
|
|
1855
|
+
shadowLevel = 2,
|
|
1856
|
+
...props
|
|
1857
|
+
}) {
|
|
1858
|
+
return /* @__PURE__ */ jsxs(
|
|
1859
|
+
NavigationMenu$1.Root,
|
|
1860
|
+
{
|
|
1861
|
+
"data-slot": "navigation-menu",
|
|
1862
|
+
"data-level": level,
|
|
1863
|
+
className: cn("min-w-max rounded-md p-1 text-foreground", solidSurface(level, shadowLevel), className),
|
|
1864
|
+
...props,
|
|
1865
|
+
children: [
|
|
1866
|
+
children,
|
|
1867
|
+
/* @__PURE__ */ jsx(
|
|
1868
|
+
NavigationMenuViewport,
|
|
1869
|
+
{
|
|
1870
|
+
side,
|
|
1871
|
+
sideOffset,
|
|
1872
|
+
align,
|
|
1873
|
+
alignOffset,
|
|
1874
|
+
collisionPadding,
|
|
1875
|
+
collisionBoundary,
|
|
1876
|
+
arrow,
|
|
1877
|
+
positionMethod
|
|
1878
|
+
}
|
|
1879
|
+
)
|
|
1880
|
+
]
|
|
1881
|
+
}
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
function NavigationMenuList({ className, ...props }) {
|
|
1885
|
+
return /* @__PURE__ */ jsx(NavigationMenu$1.List, { "data-slot": "navigation-menu-list", className: cn("relative flex", className), ...props });
|
|
1886
|
+
}
|
|
1887
|
+
function NavigationMenuItem({ className, ...props }) {
|
|
1888
|
+
return /* @__PURE__ */ jsx(NavigationMenu$1.Item, { "data-slot": "navigation-menu-item", className: cn("relative", className), ...props });
|
|
1889
|
+
}
|
|
1890
|
+
function NavigationMenuTrigger({ className, children, ...props }) {
|
|
1891
|
+
return /* @__PURE__ */ jsxs(
|
|
1892
|
+
NavigationMenu$1.Trigger,
|
|
1893
|
+
{
|
|
1894
|
+
"data-slot": "navigation-menu-trigger",
|
|
1895
|
+
className: cn(navigationMenuTriggerStyle(), className),
|
|
1896
|
+
...props,
|
|
1897
|
+
children: [
|
|
1898
|
+
children,
|
|
1899
|
+
/* @__PURE__ */ jsx(NavigationMenuIcon, {})
|
|
1900
|
+
]
|
|
1901
|
+
}
|
|
1902
|
+
);
|
|
1903
|
+
}
|
|
1904
|
+
function NavigationMenuIcon({
|
|
1905
|
+
className,
|
|
1906
|
+
render = /* @__PURE__ */ jsx(ChevronDownIcon2, {}),
|
|
1907
|
+
...props
|
|
1908
|
+
}) {
|
|
1909
|
+
return /* @__PURE__ */ jsx(
|
|
1910
|
+
NavigationMenu$1.Icon,
|
|
1911
|
+
{
|
|
1912
|
+
className: cn("transition-transform duration-200 ease-in-out data-[popup-open]:rotate-180", className),
|
|
1913
|
+
render,
|
|
1914
|
+
...props
|
|
1915
|
+
}
|
|
1916
|
+
);
|
|
1917
|
+
}
|
|
1918
|
+
function NavigationMenuSubTrigger({
|
|
1919
|
+
className,
|
|
1920
|
+
children,
|
|
1921
|
+
...props
|
|
1922
|
+
}) {
|
|
1923
|
+
return /* @__PURE__ */ jsxs(
|
|
1924
|
+
NavigationMenu$1.Trigger,
|
|
1925
|
+
{
|
|
1926
|
+
"data-slot": "navigation-menu-sub-trigger",
|
|
1927
|
+
className: cn(navigationMenuSubTriggerStyle(), className),
|
|
1928
|
+
...props,
|
|
1929
|
+
children: [
|
|
1930
|
+
children,
|
|
1931
|
+
/* @__PURE__ */ jsx(
|
|
1932
|
+
NavigationMenu$1.Icon,
|
|
1933
|
+
{
|
|
1934
|
+
className: "absolute top-1/2 right-2.5 flex h-2.5 w-2.5 -translate-y-1/2 items-center justify-center transition-transform duration-200 ease-in-out data-[popup-open]:rotate-180",
|
|
1935
|
+
render: /* @__PURE__ */ jsx(ChevronRightIcon, {})
|
|
1936
|
+
}
|
|
1937
|
+
)
|
|
1938
|
+
]
|
|
1939
|
+
}
|
|
1940
|
+
);
|
|
1941
|
+
}
|
|
1942
|
+
function NavigationMenuContent({ className, ...props }) {
|
|
1943
|
+
return /* @__PURE__ */ jsx(
|
|
1944
|
+
NavigationMenu$1.Content,
|
|
1945
|
+
{
|
|
1946
|
+
"data-slot": "navigation-menu-content",
|
|
1947
|
+
className: cn(
|
|
1948
|
+
"h-full w-[calc(100vw-2.5rem)] p-4 sm:w-max",
|
|
1949
|
+
// Transitions for opacity/transform/filter
|
|
1950
|
+
"transition-[opacity,transform,filter,scale,translate] duration-(--duration) ease-(--easing)",
|
|
1951
|
+
// Starting/ending opacity
|
|
1952
|
+
"data-ending-style:opacity-0 data-starting-style:opacity-0",
|
|
1953
|
+
// Direction-aware slide (starting)
|
|
1954
|
+
"data-starting-style:data-[activation-direction=left]:-translate-x-1/2",
|
|
1955
|
+
"data-starting-style:data-[activation-direction=right]:translate-x-1/2",
|
|
1956
|
+
// Direction-aware slide (ending)
|
|
1957
|
+
"data-ending-style:data-[activation-direction=left]:translate-x-1/2",
|
|
1958
|
+
"data-ending-style:data-[activation-direction=right]:-translate-x-1/2",
|
|
1959
|
+
// Blur effect during transitions
|
|
1960
|
+
"data-ending-style:blur-[4px] data-starting-style:blur-[4px]",
|
|
1961
|
+
// scale effect during transitions
|
|
1962
|
+
"data-ending-style:scale-97 data-starting-style:scale-97",
|
|
1963
|
+
// Motion reduce support
|
|
1964
|
+
"motion-reduce:transition-none",
|
|
1965
|
+
className
|
|
1966
|
+
),
|
|
1967
|
+
...props
|
|
1968
|
+
}
|
|
1969
|
+
);
|
|
1970
|
+
}
|
|
1971
|
+
function NavigationMenuLink({ className, standalone, ...props }) {
|
|
1972
|
+
return /* @__PURE__ */ jsx(
|
|
1973
|
+
NavigationMenu$1.Link,
|
|
1974
|
+
{
|
|
1975
|
+
"data-slot": "navigation-menu-link",
|
|
1976
|
+
className: cn(
|
|
1977
|
+
standalone ? navigationMenuTriggerStyle() : "block rounded-md p-2.5 xs:p-3 text-inherit no-underline duration-150 hover:text-foreground hover:duration-0 focus-visible:relative focus-visible:outline-2 focus-visible:outline-ring focus-visible:-outline-offset-1",
|
|
1978
|
+
className
|
|
1979
|
+
),
|
|
1980
|
+
...props
|
|
1981
|
+
}
|
|
1982
|
+
);
|
|
1983
|
+
}
|
|
1984
|
+
function NavigationMenuBackdrop({ ...props }) {
|
|
1985
|
+
return /* @__PURE__ */ jsx(NavigationMenu$1.Backdrop, { "data-slot": "navigation-menu-backdrop", ...props });
|
|
1986
|
+
}
|
|
1987
|
+
function NavigationMenuPortal({ ...props }) {
|
|
1988
|
+
return /* @__PURE__ */ jsx(NavigationMenu$1.Portal, { "data-slot": "navigation-menu-portal", ...props });
|
|
1989
|
+
}
|
|
1990
|
+
function NavigationMenuArrow({ ...props }) {
|
|
1991
|
+
return /* @__PURE__ */ jsx(
|
|
1992
|
+
NavigationMenu$1.Arrow,
|
|
1993
|
+
{
|
|
1994
|
+
className: "flex transition-[left] duration-[var(--duration)] ease-[var(--easing)] data-[side=bottom]:top-[-8px] data-[side=left]:right-[-13px] data-[side=top]:bottom-[-8px] data-[side=right]:left-[-13px] data-[side=left]:rotate-90 data-[side=right]:-rotate-90 data-[side=top]:rotate-180",
|
|
1995
|
+
...props,
|
|
1996
|
+
children: /* @__PURE__ */ jsx(ArrowSvg, {})
|
|
1997
|
+
}
|
|
1998
|
+
);
|
|
1999
|
+
}
|
|
2000
|
+
function NavigationMenuViewport({
|
|
2001
|
+
className,
|
|
2002
|
+
children,
|
|
2003
|
+
side,
|
|
2004
|
+
sideOffset,
|
|
2005
|
+
align,
|
|
2006
|
+
alignOffset,
|
|
2007
|
+
collisionPadding,
|
|
2008
|
+
collisionBoundary,
|
|
2009
|
+
arrow = false,
|
|
2010
|
+
positionMethod = "fixed",
|
|
2011
|
+
...props
|
|
2012
|
+
}) {
|
|
2013
|
+
return /* @__PURE__ */ jsx(NavigationMenuPortal, { children: /* @__PURE__ */ jsx(
|
|
2014
|
+
NavigationMenu$1.Positioner,
|
|
2015
|
+
{
|
|
2016
|
+
"data-slot": "navigation-menu-positioner",
|
|
2017
|
+
side,
|
|
2018
|
+
sideOffset,
|
|
2019
|
+
align,
|
|
2020
|
+
alignOffset,
|
|
2021
|
+
collisionPadding,
|
|
2022
|
+
collisionBoundary,
|
|
2023
|
+
positionMethod,
|
|
2024
|
+
className: "z-50 box-border h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-(--duration) ease-(--easing) before:absolute before:content-[''] data-instant:transition-none data-[side=bottom]:before:-top-2.5 data-[side=left]:before:top-0 data-[side=right]:before:top-0 data-[side=bottom]:before:right-0 data-[side=left]:before:-right-2.5 data-[side=top]:before:right-0 data-[side=left]:before:bottom-0 data-[side=right]:before:bottom-0 data-[side=top]:before:-bottom-2.5 data-[side=bottom]:before:left-0 data-[side=right]:before:-left-2.5 data-[side=top]:before:left-0 data-[side=bottom]:before:h-2.5 data-[side=top]:before:h-2.5 data-[side=left]:before:w-2.5 data-[side=right]:before:w-2.5",
|
|
2025
|
+
style: validCssVars({ "--duration": "0.35s", "--easing": "cubic-bezier(0.22, 1, 0.36, 1)" }),
|
|
2026
|
+
children: /* @__PURE__ */ jsxs(
|
|
2027
|
+
NavigationMenu$1.Popup,
|
|
2028
|
+
{
|
|
2029
|
+
"data-slot": "navigation-menu-content",
|
|
2030
|
+
className: cn(
|
|
2031
|
+
"relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) overflow-hidden rounded-md text-foreground transition-[opacity,transform,width,height,scale,translate] duration-(--duration) ease-(--easing) data-ending-style:scale-90 data-starting-style:scale-90 data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:duration-150",
|
|
2032
|
+
solidSurface(3, 3)
|
|
2033
|
+
),
|
|
2034
|
+
children: [
|
|
2035
|
+
arrow ? /* @__PURE__ */ jsx(NavigationMenuArrow, {}) : null,
|
|
2036
|
+
/* @__PURE__ */ jsx(
|
|
2037
|
+
NavigationMenu$1.Viewport,
|
|
2038
|
+
{
|
|
2039
|
+
"data-slot": "navigation-menu-viewport",
|
|
2040
|
+
className: cn("relative h-full w-full overflow-hidden", className),
|
|
2041
|
+
...props,
|
|
2042
|
+
children
|
|
2043
|
+
}
|
|
2044
|
+
)
|
|
2045
|
+
]
|
|
2046
|
+
}
|
|
2047
|
+
)
|
|
2048
|
+
}
|
|
2049
|
+
) });
|
|
2050
|
+
}
|
|
2051
|
+
function NavigationMenuSub({
|
|
2052
|
+
className,
|
|
2053
|
+
children,
|
|
2054
|
+
orientation = "vertical",
|
|
2055
|
+
side = "right",
|
|
2056
|
+
sideOffset = 24,
|
|
2057
|
+
align = "end",
|
|
2058
|
+
alignOffset = -24,
|
|
2059
|
+
arrow = false,
|
|
2060
|
+
...props
|
|
2061
|
+
}) {
|
|
2062
|
+
return /* @__PURE__ */ jsxs(
|
|
2063
|
+
NavigationMenu$1.Root,
|
|
2064
|
+
{
|
|
2065
|
+
"data-slot": "navigation-menu-sub",
|
|
2066
|
+
className: cn("", className),
|
|
2067
|
+
orientation,
|
|
2068
|
+
...props,
|
|
2069
|
+
children: [
|
|
2070
|
+
children,
|
|
2071
|
+
/* @__PURE__ */ jsx(NavigationMenuPortal, { children: /* @__PURE__ */ jsx(
|
|
2072
|
+
NavigationMenu$1.Positioner,
|
|
2073
|
+
{
|
|
2074
|
+
"data-slot": "navigation-menu-sub-positioner",
|
|
2075
|
+
sideOffset,
|
|
2076
|
+
alignOffset,
|
|
2077
|
+
align,
|
|
2078
|
+
side,
|
|
2079
|
+
className: "box-border h-(--positioner-height) w-(--positioner-width) max-w-(--available-width) transition-[top,left,right,bottom] duration-(--duration) ease-(--easing) before:absolute before:content-[''] data-instant:transition-none data-[side=bottom]:before:-top-2.5 data-[side=left]:before:top-0 data-[side=right]:before:top-0 data-[side=bottom]:before:right-0 data-[side=left]:before:-right-2.5 data-[side=top]:before:right-0 data-[side=left]:before:bottom-0 data-[side=right]:before:bottom-0 data-[side=top]:before:-bottom-2.5 data-[side=bottom]:before:left-0 data-[side=right]:before:-left-2.5 data-[side=top]:before:left-0 data-[side=bottom]:before:h-2.5 data-[side=top]:before:h-2.5 data-[side=left]:before:w-2.5 data-[side=right]:before:w-2.5",
|
|
2080
|
+
style: validCssVars({ "--duration": "0.35s", "--easing": "cubic-bezier(0.22, 1, 0.36, 1)" }),
|
|
2081
|
+
children: /* @__PURE__ */ jsxs(
|
|
2082
|
+
NavigationMenu$1.Popup,
|
|
2083
|
+
{
|
|
2084
|
+
"data-slot": "navigation-menu-sub-content",
|
|
2085
|
+
className: cn(
|
|
2086
|
+
"relative h-(--popup-height) w-(--popup-width) origin-(--transform-origin) overflow-hidden rounded-md text-foreground transition-[opacity,transform,width,height,scale,translate] duration-(--duration) ease-(--easing) data-ending-style:scale-90 data-starting-style:scale-90 data-ending-style:opacity-0 data-starting-style:opacity-0 data-ending-style:duration-150",
|
|
2087
|
+
solidSurface(5, 5)
|
|
2088
|
+
),
|
|
2089
|
+
children: [
|
|
2090
|
+
arrow ? /* @__PURE__ */ jsx(NavigationMenuArrow, {}) : null,
|
|
2091
|
+
/* @__PURE__ */ jsx(
|
|
2092
|
+
NavigationMenu$1.Viewport,
|
|
2093
|
+
{
|
|
2094
|
+
"data-slot": "navigation-menu-sub-viewport",
|
|
2095
|
+
className: "relative h-full w-full overflow-hidden"
|
|
2096
|
+
}
|
|
2097
|
+
)
|
|
2098
|
+
]
|
|
2099
|
+
}
|
|
2100
|
+
)
|
|
2101
|
+
}
|
|
2102
|
+
) })
|
|
2103
|
+
]
|
|
2104
|
+
}
|
|
2105
|
+
);
|
|
2106
|
+
}
|
|
2107
|
+
function PasswordInput({ inputType = "password", ...props }) {
|
|
2108
|
+
const [visible, setVisible] = useState(false);
|
|
2109
|
+
const toggle = useCallback(() => setVisible((v) => !v), []);
|
|
2110
|
+
const eye = /* @__PURE__ */ jsx(
|
|
2111
|
+
"button",
|
|
2112
|
+
{
|
|
2113
|
+
type: "button",
|
|
2114
|
+
onClick: toggle,
|
|
2115
|
+
className: "pointer-events-auto cursor-pointer text-(--color-muted-foreground) hover:text-(--color-foreground)",
|
|
2116
|
+
"aria-label": visible ? "Hide password" : "Show password",
|
|
2117
|
+
tabIndex: -1,
|
|
2118
|
+
children: visible ? /* @__PURE__ */ jsx(EyeOffIcon, { className: "size-5" }) : /* @__PURE__ */ jsx(EyeIcon, { className: "size-5" })
|
|
2119
|
+
}
|
|
2120
|
+
);
|
|
2121
|
+
return /* @__PURE__ */ jsx(
|
|
2122
|
+
Input,
|
|
2123
|
+
{
|
|
2124
|
+
...props,
|
|
2125
|
+
inputType: visible ? "text" : "password",
|
|
2126
|
+
rightAdornment: eye,
|
|
2127
|
+
autoComplete: inputType === "new-password" ? "new-password" : "current-password"
|
|
2128
|
+
}
|
|
2129
|
+
);
|
|
2130
|
+
}
|
|
2131
|
+
function EyeIcon(props) {
|
|
2132
|
+
return /* @__PURE__ */ jsxs(
|
|
2133
|
+
"svg",
|
|
2134
|
+
{
|
|
2135
|
+
"aria-hidden": "true",
|
|
2136
|
+
viewBox: "0 0 24 24",
|
|
2137
|
+
fill: "none",
|
|
2138
|
+
stroke: "currentColor",
|
|
2139
|
+
strokeWidth: "2",
|
|
2140
|
+
strokeLinecap: "round",
|
|
2141
|
+
strokeLinejoin: "round",
|
|
2142
|
+
...props,
|
|
2143
|
+
children: [
|
|
2144
|
+
/* @__PURE__ */ jsx("path", { d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0" }),
|
|
2145
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "3" })
|
|
2146
|
+
]
|
|
2147
|
+
}
|
|
2148
|
+
);
|
|
2149
|
+
}
|
|
2150
|
+
function EyeOffIcon(props) {
|
|
2151
|
+
return /* @__PURE__ */ jsxs(
|
|
2152
|
+
"svg",
|
|
2153
|
+
{
|
|
2154
|
+
"aria-hidden": "true",
|
|
2155
|
+
viewBox: "0 0 24 24",
|
|
2156
|
+
fill: "none",
|
|
2157
|
+
stroke: "currentColor",
|
|
2158
|
+
strokeWidth: "2",
|
|
2159
|
+
strokeLinecap: "round",
|
|
2160
|
+
strokeLinejoin: "round",
|
|
2161
|
+
...props,
|
|
2162
|
+
children: [
|
|
2163
|
+
/* @__PURE__ */ jsx("path", { d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.747 10.747 0 0 1-1.444 2.49" }),
|
|
2164
|
+
/* @__PURE__ */ jsx("path", { d: "M14.084 14.158a3 3 0 0 1-4.242-4.242" }),
|
|
2165
|
+
/* @__PURE__ */ jsx("path", { d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143" }),
|
|
2166
|
+
/* @__PURE__ */ jsx("path", { d: "m2 2 20 20" })
|
|
2167
|
+
]
|
|
2168
|
+
}
|
|
2169
|
+
);
|
|
2170
|
+
}
|
|
2171
|
+
var rainbowButtonVariants = cva(
|
|
2172
|
+
cn(
|
|
2173
|
+
"relative cursor-pointer group transition-transform animate-rainbow",
|
|
2174
|
+
"inline-flex items-center justify-center gap-2 shrink-0",
|
|
2175
|
+
"rounded-sm outline-none focus-visible:ring-[3px] aria-invalid:border-destructive",
|
|
2176
|
+
"text-sm font-medium whitespace-nowrap",
|
|
2177
|
+
"disabled:pointer-events-none disabled:opacity-50",
|
|
2178
|
+
"[&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 [&_svg]:shrink-0"
|
|
2179
|
+
),
|
|
2180
|
+
{
|
|
2181
|
+
variants: {
|
|
2182
|
+
variant: {
|
|
2183
|
+
default: "border-0 bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] bg-[length:200%] text-primary-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.125rem)_solid_transparent] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))]",
|
|
2184
|
+
outline: "border border-input border-b-transparent bg-[linear-gradient(#ffffff,#ffffff),linear-gradient(#ffffff_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] bg-[length:200%] text-accent-foreground [background-clip:padding-box,border-box,border-box] [background-origin:border-box] before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))] before:bg-[length:200%] before:[filter:blur(0.75rem)] dark:bg-[linear-gradient(#0a0a0a,#0a0a0a),linear-gradient(#0a0a0a_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,var(--color-rainbow-1),var(--color-rainbow-5),var(--color-rainbow-3),var(--color-rainbow-4),var(--color-rainbow-2))]"
|
|
2185
|
+
},
|
|
2186
|
+
size: {
|
|
2187
|
+
default: "h-9 px-4 py-2",
|
|
2188
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
2189
|
+
lg: "h-11 rounded-md px-8",
|
|
2190
|
+
icon: "size-9"
|
|
2191
|
+
}
|
|
2192
|
+
},
|
|
2193
|
+
defaultVariants: {
|
|
2194
|
+
variant: "default",
|
|
2195
|
+
size: "default"
|
|
2196
|
+
}
|
|
2197
|
+
}
|
|
2198
|
+
);
|
|
2199
|
+
function RainbowButton({ className, variant, size, asChild = false, ref, ...props }) {
|
|
2200
|
+
const Comp = asChild ? Slot : "button";
|
|
2201
|
+
return /* @__PURE__ */ jsx(Comp, { "data-slot": "button", className: cn(rainbowButtonVariants({ variant, size, className })), ref, ...props });
|
|
2202
|
+
}
|
|
2203
|
+
RainbowButton.displayName = "RainbowButton";
|
|
2204
|
+
function nearestIndex(steps, value) {
|
|
2205
|
+
return steps.reduce((best, s, i) => Math.abs(s - value) < Math.abs(steps[best] - value) ? i : best, 0);
|
|
2206
|
+
}
|
|
2207
|
+
function RangeSlider({ label, value, steps, ticks, valueLabel, onChange }) {
|
|
2208
|
+
const min = steps[0];
|
|
2209
|
+
const max = steps.at(-1) ?? min;
|
|
2210
|
+
const pct = (value - min) / (max - min) * 100;
|
|
2211
|
+
const index = nearestIndex(steps, value);
|
|
2212
|
+
const handleChange = useCallback(
|
|
2213
|
+
(event_) => onChange(steps[Number(event_.target.value)]),
|
|
2214
|
+
[onChange, steps]
|
|
2215
|
+
);
|
|
2216
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full", children: [
|
|
2217
|
+
/* @__PURE__ */ jsxs("div", { className: "mb-5 flex items-baseline justify-between gap-2", children: [
|
|
2218
|
+
/* @__PURE__ */ jsx("p", { className: "font-semibold text-[15px] text-(--color-foreground)", children: label }),
|
|
2219
|
+
/* @__PURE__ */ jsx("p", { className: "font-bold font-numeric text-[20px] text-(--color-foreground) tabular-nums", children: valueLabel })
|
|
2220
|
+
] }),
|
|
2221
|
+
/* @__PURE__ */ jsxs("div", { className: "relative", style: { height: 20 }, children: [
|
|
2222
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-x-0 top-1/2 h-1.5 -translate-y-1/2 rounded-full bg-(--color-border)" }),
|
|
2223
|
+
/* @__PURE__ */ jsx(
|
|
2224
|
+
"div",
|
|
2225
|
+
{
|
|
2226
|
+
className: "pointer-events-none absolute top-1/2 left-0 h-1.5 -translate-y-1/2 rounded-full bg-(--color-foreground)",
|
|
2227
|
+
style: { width: `${pct}%` }
|
|
2228
|
+
}
|
|
2229
|
+
),
|
|
2230
|
+
/* @__PURE__ */ jsx(
|
|
2231
|
+
"input",
|
|
2232
|
+
{
|
|
2233
|
+
type: "range",
|
|
2234
|
+
min: 0,
|
|
2235
|
+
max: steps.length - 1,
|
|
2236
|
+
step: 1,
|
|
2237
|
+
value: index,
|
|
2238
|
+
onChange: handleChange,
|
|
2239
|
+
className: "peer absolute inset-0 z-10 h-full w-full cursor-pointer opacity-0",
|
|
2240
|
+
"aria-label": label,
|
|
2241
|
+
"aria-valuetext": valueLabel
|
|
2242
|
+
}
|
|
2243
|
+
),
|
|
2244
|
+
/* @__PURE__ */ jsx(
|
|
2245
|
+
"div",
|
|
2246
|
+
{
|
|
2247
|
+
className: "pointer-events-none absolute top-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-(--color-foreground) peer-focus-visible:outline-2 peer-focus-visible:outline-(--color-foreground) peer-focus-visible:outline-offset-2",
|
|
2248
|
+
style: {
|
|
2249
|
+
left: `${pct}%`,
|
|
2250
|
+
width: 16,
|
|
2251
|
+
height: 16,
|
|
2252
|
+
boxShadow: "0 2px 8px rgba(0,0,0,0.15)"
|
|
2253
|
+
}
|
|
2254
|
+
}
|
|
2255
|
+
)
|
|
2256
|
+
] }),
|
|
2257
|
+
/* @__PURE__ */ jsx("div", { className: "relative mt-2", style: { height: 16 }, children: ticks.map((tick2, i) => {
|
|
2258
|
+
const tp = (tick2.value - min) / (max - min) * 100;
|
|
2259
|
+
const isFirst = i === 0;
|
|
2260
|
+
const isLast = i === ticks.length - 1;
|
|
2261
|
+
let left = `${tp}%`;
|
|
2262
|
+
if (isFirst) left = 0;
|
|
2263
|
+
else if (isLast) left = void 0;
|
|
2264
|
+
return /* @__PURE__ */ jsx(
|
|
2265
|
+
"span",
|
|
2266
|
+
{
|
|
2267
|
+
className: "absolute font-numeric text-(--color-muted-foreground) text-[11px] tabular-nums",
|
|
2268
|
+
style: {
|
|
2269
|
+
left,
|
|
2270
|
+
right: isLast ? 0 : void 0,
|
|
2271
|
+
transform: isFirst || isLast ? void 0 : "translateX(-50%)"
|
|
2272
|
+
},
|
|
2273
|
+
children: tick2.label
|
|
2274
|
+
},
|
|
2275
|
+
tick2.value
|
|
2276
|
+
);
|
|
2277
|
+
}) })
|
|
2278
|
+
] });
|
|
2279
|
+
}
|
|
2280
|
+
var tick = 0;
|
|
2281
|
+
var listeners = /* @__PURE__ */ new Set();
|
|
2282
|
+
var timer = null;
|
|
2283
|
+
function subscribe(onChange) {
|
|
2284
|
+
listeners.add(onChange);
|
|
2285
|
+
if (timer === null)
|
|
2286
|
+
timer = setInterval(() => {
|
|
2287
|
+
tick += 1;
|
|
2288
|
+
for (const l of listeners) l();
|
|
2289
|
+
}, ROTATE_MS);
|
|
2290
|
+
return () => {
|
|
2291
|
+
listeners.delete(onChange);
|
|
2292
|
+
if (listeners.size === 0 && timer !== null) {
|
|
2293
|
+
clearInterval(timer);
|
|
2294
|
+
timer = null;
|
|
2295
|
+
}
|
|
2296
|
+
};
|
|
2297
|
+
}
|
|
2298
|
+
var getSnapshot = () => tick;
|
|
2299
|
+
var getServerSnapshot = () => 0;
|
|
2300
|
+
var ROTATE_MS = 4e3;
|
|
2301
|
+
function RollingBadge({ badges, className }) {
|
|
2302
|
+
const index = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot) % badges.length;
|
|
2303
|
+
const badge = badges[index];
|
|
2304
|
+
if (badges.length === 0 || !badge) return null;
|
|
2305
|
+
return /* @__PURE__ */ jsx(
|
|
2306
|
+
motion.div,
|
|
2307
|
+
{
|
|
2308
|
+
layout: true,
|
|
2309
|
+
className: cn(
|
|
2310
|
+
"relative inline-flex h-8 items-center overflow-hidden rounded-full border border-(--color-border) bg-background px-3.5 shadow-sm",
|
|
2311
|
+
className
|
|
2312
|
+
),
|
|
2313
|
+
children: /* @__PURE__ */ jsx(AnimatePresence, { initial: false, mode: "popLayout", children: /* @__PURE__ */ jsxs(
|
|
2314
|
+
motion.span,
|
|
2315
|
+
{
|
|
2316
|
+
layout: "position",
|
|
2317
|
+
initial: { y: "120%", opacity: 0 },
|
|
2318
|
+
animate: { y: "0%", opacity: 1 },
|
|
2319
|
+
exit: { y: "-120%", opacity: 0 },
|
|
2320
|
+
transition: {
|
|
2321
|
+
type: "spring",
|
|
2322
|
+
stiffness: 320,
|
|
2323
|
+
damping: 32
|
|
2324
|
+
},
|
|
2325
|
+
className: "flex items-center gap-1.5 whitespace-nowrap font-medium text-[12.5px]",
|
|
2326
|
+
children: [
|
|
2327
|
+
/* @__PURE__ */ jsx("span", { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": true, children: badge.icon }),
|
|
2328
|
+
badge.label
|
|
2329
|
+
]
|
|
2330
|
+
},
|
|
2331
|
+
index
|
|
2332
|
+
) })
|
|
2333
|
+
}
|
|
2334
|
+
);
|
|
2335
|
+
}
|
|
2336
|
+
function SavingsBadge({ className, ...props }) {
|
|
2337
|
+
return /* @__PURE__ */ jsx(
|
|
2338
|
+
"span",
|
|
2339
|
+
{
|
|
2340
|
+
className: cn(
|
|
2341
|
+
"rounded-full bg-emerald-500/15 px-2.5 py-0.5 font-numeric font-semibold text-[11px] text-emerald-500 tabular-nums",
|
|
2342
|
+
className
|
|
2343
|
+
),
|
|
2344
|
+
...props
|
|
2345
|
+
}
|
|
2346
|
+
);
|
|
2347
|
+
}
|
|
2348
|
+
function ShineBorder({
|
|
2349
|
+
borderWidth = 1,
|
|
2350
|
+
duration = 14,
|
|
2351
|
+
shineColor = "#000000",
|
|
2352
|
+
className,
|
|
2353
|
+
style,
|
|
2354
|
+
...props
|
|
2355
|
+
}) {
|
|
2356
|
+
return /* @__PURE__ */ jsx(
|
|
2357
|
+
"div",
|
|
2358
|
+
{
|
|
2359
|
+
style: validCssVars({
|
|
2360
|
+
"--border-width": `${borderWidth}px`,
|
|
2361
|
+
"--duration": `${duration}s`,
|
|
2362
|
+
backgroundImage: `radial-gradient(transparent,transparent, ${Array.isArray(shineColor) ? shineColor.join(",") : shineColor},transparent,transparent)`,
|
|
2363
|
+
backgroundSize: "300% 300%",
|
|
2364
|
+
mask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
|
|
2365
|
+
WebkitMask: "linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)",
|
|
2366
|
+
WebkitMaskComposite: "xor",
|
|
2367
|
+
maskComposite: "exclude",
|
|
2368
|
+
padding: "var(--border-width)",
|
|
2369
|
+
...style
|
|
2370
|
+
}),
|
|
2371
|
+
className: cn(
|
|
2372
|
+
"pointer-events-none absolute inset-0 size-full rounded-[inherit] will-change-[background-position] motion-safe:animate-shine",
|
|
2373
|
+
className
|
|
2374
|
+
),
|
|
2375
|
+
...props
|
|
2376
|
+
}
|
|
2377
|
+
);
|
|
2378
|
+
}
|
|
2379
|
+
var STAR_PATH = "M9.82531 0.843845C10.0553 0.215178 10.9446 0.215178 11.1746 0.843845L11.8618 2.72026C12.4006 4.19229 12.3916 6.39157 13.5 7.5C14.6084 8.60843 16.8077 8.59935 18.2797 9.13822L20.1561 9.82534C20.7858 10.0553 20.7858 10.9447 20.1561 11.1747L18.2797 11.8618C16.8077 12.4007 14.6084 12.3916 13.5 13.5C12.3916 14.6084 12.4006 16.8077 11.8618 18.2798L11.1746 20.1562C10.9446 20.7858 10.0553 20.7858 9.82531 20.1562L9.13819 18.2798C8.59932 16.8077 8.60843 14.6084 7.5 13.5C6.39157 12.3916 4.19225 12.4007 2.72023 11.8618L0.843814 11.1747C0.215148 10.9447 0.215148 10.0553 0.843814 9.82534L2.72023 9.13822C4.19225 8.59935 6.39157 8.60843 7.5 7.5C8.60843 6.39157 8.59932 4.19229 9.13819 2.72026L9.82531 0.843845Z";
|
|
2380
|
+
var DEFAULT_COLORS2 = {
|
|
2381
|
+
first: "var(--color-accent-brand)",
|
|
2382
|
+
second: "var(--color-accent-brand-soft)"
|
|
2383
|
+
};
|
|
2384
|
+
function SparkleStar({ x, y, color, delay, scale }) {
|
|
2385
|
+
return /* @__PURE__ */ jsx(
|
|
2386
|
+
motion.svg,
|
|
2387
|
+
{
|
|
2388
|
+
className: "pointer-events-none absolute z-20",
|
|
2389
|
+
initial: { opacity: 0, left: x, top: y },
|
|
2390
|
+
animate: {
|
|
2391
|
+
opacity: [0, 1, 0],
|
|
2392
|
+
scale: [0, scale, 0],
|
|
2393
|
+
rotate: [75, 120, 150]
|
|
2394
|
+
},
|
|
2395
|
+
transition: {
|
|
2396
|
+
duration: 0.8,
|
|
2397
|
+
repeat: Number.POSITIVE_INFINITY,
|
|
2398
|
+
delay
|
|
2399
|
+
},
|
|
2400
|
+
width: "21",
|
|
2401
|
+
height: "21",
|
|
2402
|
+
viewBox: "0 0 21 21",
|
|
2403
|
+
"aria-hidden": true,
|
|
2404
|
+
children: /* @__PURE__ */ jsx("path", { d: STAR_PATH, fill: color })
|
|
2405
|
+
}
|
|
2406
|
+
);
|
|
2407
|
+
}
|
|
2408
|
+
function SparklesText({ children, className, sparklesCount = 10, colors = DEFAULT_COLORS2 }) {
|
|
2409
|
+
const reducedMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
|
|
2410
|
+
const [sparkles, setSparkles] = useState([]);
|
|
2411
|
+
const { first, second } = colors;
|
|
2412
|
+
useEffect(() => {
|
|
2413
|
+
if (reducedMotion) {
|
|
2414
|
+
setSparkles([]);
|
|
2415
|
+
return;
|
|
2416
|
+
}
|
|
2417
|
+
const spawn = () => ({
|
|
2418
|
+
x: `${Math.random() * 100}%`,
|
|
2419
|
+
y: `${Math.random() * 100}%`,
|
|
2420
|
+
color: Math.random() > 0.5 ? first : second,
|
|
2421
|
+
delay: Math.random() * 2,
|
|
2422
|
+
scale: Math.random() + 0.3,
|
|
2423
|
+
expiresAt: performance.now() + (Math.random() * 10 + 5) * 1e3
|
|
2424
|
+
});
|
|
2425
|
+
setSparkles(Array.from({ length: sparklesCount }, spawn));
|
|
2426
|
+
const interval = setInterval(() => {
|
|
2427
|
+
setSparkles((current) => {
|
|
2428
|
+
const now = performance.now();
|
|
2429
|
+
if (!current.some((sparkle) => sparkle.expiresAt <= now)) return current;
|
|
2430
|
+
return current.map((sparkle) => sparkle.expiresAt <= now ? spawn() : sparkle);
|
|
2431
|
+
});
|
|
2432
|
+
}, 500);
|
|
2433
|
+
return () => clearInterval(interval);
|
|
2434
|
+
}, [first, second, sparklesCount, reducedMotion]);
|
|
2435
|
+
return /* @__PURE__ */ jsxs("span", { className: cn("relative inline-block", className), children: [
|
|
2436
|
+
sparkles.map((sparkle) => /* @__PURE__ */ jsx(SparkleStar, { ...sparkle }, `${sparkle.x}-${sparkle.y}-${sparkle.expiresAt}`)),
|
|
2437
|
+
children
|
|
2438
|
+
] });
|
|
2439
|
+
}
|
|
2440
|
+
var PULL = 0.035;
|
|
2441
|
+
function pillTarget(activeIdx, hoverIdx, rects, pull) {
|
|
2442
|
+
const active = rects[activeIdx];
|
|
2443
|
+
if (!active) throw new Error(`No rect at index ${activeIdx}`);
|
|
2444
|
+
if (hoverIdx === null || hoverIdx === activeIdx) return active;
|
|
2445
|
+
const hover = rects[hoverIdx];
|
|
2446
|
+
if (!hover) return active;
|
|
2447
|
+
const activeRight = active.left + active.width;
|
|
2448
|
+
const hoverRight = hover.left + hover.width;
|
|
2449
|
+
const left = Math.min(active.left, active.left + (hover.left - active.left) * pull);
|
|
2450
|
+
const right = Math.max(activeRight, activeRight + (hoverRight - activeRight) * pull);
|
|
2451
|
+
return { left, width: right - left };
|
|
2452
|
+
}
|
|
2453
|
+
var labelBox = "flex items-center gap-2.5 px-5 py-1.5 font-semibold text-[13px]";
|
|
2454
|
+
var badgeBox = "font-bold text-(--color-accent-brand-soft) text-[11px] whitespace-nowrap";
|
|
2455
|
+
function Tabs({ tabs, value, onChange, label, className }) {
|
|
2456
|
+
const reduced = useReducedMotion();
|
|
2457
|
+
const pull = reduced ? 0 : PULL;
|
|
2458
|
+
const trackRef = useRef(null);
|
|
2459
|
+
const [rects, setRects] = useState([]);
|
|
2460
|
+
const [trackWidth, setTrackWidth] = useState(0);
|
|
2461
|
+
const [hovered, setHovered] = useState(null);
|
|
2462
|
+
const [ready, setReady] = useState(false);
|
|
2463
|
+
const foundIdx = tabs.findIndex((t) => t.id === value);
|
|
2464
|
+
const activeIdx = foundIdx === -1 ? 0 : foundIdx;
|
|
2465
|
+
const springConfig = reduced ? { stiffness: 700, damping: 60 } : { stiffness: 420, damping: 34, mass: 0.7 };
|
|
2466
|
+
const pillLeft = useSpring(0, springConfig);
|
|
2467
|
+
const pillWidth = useSpring(0, springConfig);
|
|
2468
|
+
const innerX = useTransform(pillLeft, (v) => -v);
|
|
2469
|
+
const measure = useCallback(() => {
|
|
2470
|
+
const track = trackRef.current;
|
|
2471
|
+
if (!track) return;
|
|
2472
|
+
setTrackWidth(track.offsetWidth);
|
|
2473
|
+
const btns = track.querySelectorAll("button[data-index]");
|
|
2474
|
+
setRects(
|
|
2475
|
+
Array.from(btns, (el) => ({
|
|
2476
|
+
left: el.offsetLeft,
|
|
2477
|
+
width: el.offsetWidth
|
|
2478
|
+
}))
|
|
2479
|
+
);
|
|
2480
|
+
}, []);
|
|
2481
|
+
useEffect(() => {
|
|
2482
|
+
measure();
|
|
2483
|
+
const track = trackRef.current;
|
|
2484
|
+
if (!track) return;
|
|
2485
|
+
const ro = new ResizeObserver(measure);
|
|
2486
|
+
ro.observe(track);
|
|
2487
|
+
return () => ro.disconnect();
|
|
2488
|
+
}, [measure]);
|
|
2489
|
+
useEffect(() => {
|
|
2490
|
+
if (rects.length !== tabs.length) return;
|
|
2491
|
+
const target = pillTarget(activeIdx, hovered, rects, pull);
|
|
2492
|
+
if (ready) {
|
|
2493
|
+
pillLeft.set(target.left);
|
|
2494
|
+
pillWidth.set(target.width);
|
|
2495
|
+
} else {
|
|
2496
|
+
pillLeft.jump(target.left);
|
|
2497
|
+
pillWidth.jump(target.width);
|
|
2498
|
+
setReady(true);
|
|
2499
|
+
}
|
|
2500
|
+
}, [rects, tabs.length, activeIdx, hovered, pull, ready, pillLeft, pillWidth]);
|
|
2501
|
+
const handleClick = useCallback(
|
|
2502
|
+
(e) => onChange(tabs[Number(e.currentTarget.dataset.index)].id),
|
|
2503
|
+
[onChange, tabs]
|
|
2504
|
+
);
|
|
2505
|
+
const handleEnter = useCallback((e) => setHovered(Number(e.currentTarget.dataset.index)), []);
|
|
2506
|
+
const handleLeave = useCallback(() => setHovered(null), []);
|
|
2507
|
+
return /* @__PURE__ */ jsx(
|
|
2508
|
+
"fieldset",
|
|
2509
|
+
{
|
|
2510
|
+
"aria-label": label,
|
|
2511
|
+
className: cn("inline-flex items-center rounded-full border border-(--color-border) bg-(--color-surface) p-1", className),
|
|
2512
|
+
children: /* @__PURE__ */ jsxs("div", { ref: trackRef, className: "relative inline-flex items-center", children: [
|
|
2513
|
+
tabs.map((tab, i) => /* @__PURE__ */ jsxs(
|
|
2514
|
+
"button",
|
|
2515
|
+
{
|
|
2516
|
+
type: "button",
|
|
2517
|
+
"data-index": i,
|
|
2518
|
+
onClick: handleClick,
|
|
2519
|
+
onMouseEnter: handleEnter,
|
|
2520
|
+
onMouseLeave: handleLeave,
|
|
2521
|
+
"aria-pressed": value === tab.id,
|
|
2522
|
+
className: cn(labelBox, "text-(--color-muted-foreground) hover:text-(--color-foreground)"),
|
|
2523
|
+
children: [
|
|
2524
|
+
tab.label,
|
|
2525
|
+
tab.badge ? /* @__PURE__ */ jsx("span", { className: badgeBox, children: tab.badge }) : null
|
|
2526
|
+
]
|
|
2527
|
+
},
|
|
2528
|
+
tab.id
|
|
2529
|
+
)),
|
|
2530
|
+
/* @__PURE__ */ jsx(
|
|
2531
|
+
motion.div,
|
|
2532
|
+
{
|
|
2533
|
+
"aria-hidden": true,
|
|
2534
|
+
className: "pointer-events-none absolute inset-y-0 select-none overflow-hidden rounded-full bg-(--color-foreground)",
|
|
2535
|
+
style: { left: pillLeft, width: pillWidth, opacity: ready ? 1 : 0 },
|
|
2536
|
+
children: /* @__PURE__ */ jsx(motion.div, { className: "absolute inset-y-0 left-0 flex items-center", style: { width: trackWidth, x: innerX }, children: tabs.map((tab) => /* @__PURE__ */ jsxs("span", { className: cn(labelBox, "text-(--color-surface)"), children: [
|
|
2537
|
+
tab.label,
|
|
2538
|
+
tab.badge ? /* @__PURE__ */ jsx("span", { className: badgeBox, children: tab.badge }) : null
|
|
2539
|
+
] }, tab.id)) })
|
|
2540
|
+
}
|
|
2541
|
+
)
|
|
2542
|
+
] })
|
|
2543
|
+
}
|
|
2544
|
+
);
|
|
2545
|
+
}
|
|
2546
|
+
var ICON_LAYOUT = "w-8 p-0";
|
|
2547
|
+
var LABELED_LAYOUT = "gap-2 px-3 text-[13px]";
|
|
2548
|
+
function SunIcon() {
|
|
2549
|
+
return /* @__PURE__ */ jsxs(
|
|
2550
|
+
"svg",
|
|
2551
|
+
{
|
|
2552
|
+
width: 14,
|
|
2553
|
+
height: 14,
|
|
2554
|
+
viewBox: "0 0 24 24",
|
|
2555
|
+
fill: "none",
|
|
2556
|
+
stroke: "currentColor",
|
|
2557
|
+
strokeWidth: 2,
|
|
2558
|
+
strokeLinecap: "round",
|
|
2559
|
+
strokeLinejoin: "round",
|
|
2560
|
+
"aria-hidden": true,
|
|
2561
|
+
children: [
|
|
2562
|
+
/* @__PURE__ */ jsx("circle", { cx: "12", cy: "12", r: "4" }),
|
|
2563
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "3", x2: "12", y2: "1" }),
|
|
2564
|
+
/* @__PURE__ */ jsx("line", { x1: "12", y1: "23", x2: "12", y2: "21" }),
|
|
2565
|
+
/* @__PURE__ */ jsx("line", { x1: "3", y1: "12", x2: "1", y2: "12" }),
|
|
2566
|
+
/* @__PURE__ */ jsx("line", { x1: "23", y1: "12", x2: "21", y2: "12" }),
|
|
2567
|
+
/* @__PURE__ */ jsx("line", { x1: "5", y1: "5", x2: "3.5", y2: "3.5" }),
|
|
2568
|
+
/* @__PURE__ */ jsx("line", { x1: "20.5", y1: "20.5", x2: "19", y2: "19" }),
|
|
2569
|
+
/* @__PURE__ */ jsx("line", { x1: "19", y1: "5", x2: "20.5", y2: "3.5" }),
|
|
2570
|
+
/* @__PURE__ */ jsx("line", { x1: "4.5", y1: "20.5", x2: "3", y2: "19" })
|
|
2571
|
+
]
|
|
2572
|
+
}
|
|
2573
|
+
);
|
|
2574
|
+
}
|
|
2575
|
+
function MoonIcon() {
|
|
2576
|
+
return /* @__PURE__ */ jsx(
|
|
2577
|
+
"svg",
|
|
2578
|
+
{
|
|
2579
|
+
width: 14,
|
|
2580
|
+
height: 14,
|
|
2581
|
+
viewBox: "0 0 24 24",
|
|
2582
|
+
fill: "none",
|
|
2583
|
+
stroke: "currentColor",
|
|
2584
|
+
strokeWidth: 2,
|
|
2585
|
+
strokeLinecap: "round",
|
|
2586
|
+
strokeLinejoin: "round",
|
|
2587
|
+
"aria-hidden": true,
|
|
2588
|
+
children: /* @__PURE__ */ jsx("path", { d: "M21 12.8A9 9 0 1 1 11.2 3 7 7 0 0 0 21 12.8z" })
|
|
2589
|
+
}
|
|
2590
|
+
);
|
|
2591
|
+
}
|
|
2592
|
+
function ThemeToggle({ theme, onToggle, showLabel = false }) {
|
|
2593
|
+
const size = showLabel ? "md" : "sm";
|
|
2594
|
+
const layoutClassName = showLabel ? LABELED_LAYOUT : ICON_LAYOUT;
|
|
2595
|
+
const isDark = theme === "dark";
|
|
2596
|
+
const label = isDark ? "Switch to light mode" : "Switch to dark mode";
|
|
2597
|
+
return /* @__PURE__ */ jsxs(
|
|
2598
|
+
Button,
|
|
2599
|
+
{
|
|
2600
|
+
variant: "filled",
|
|
2601
|
+
size,
|
|
2602
|
+
actionOrLink: onToggle,
|
|
2603
|
+
className: layoutClassName,
|
|
2604
|
+
"aria-label": label,
|
|
2605
|
+
children: [
|
|
2606
|
+
/* @__PURE__ */ jsx(ActionSwapRollIcon, { value: theme, className: "h-4 w-4", children: isDark ? /* @__PURE__ */ jsx(SunIcon, {}) : /* @__PURE__ */ jsx(MoonIcon, {}) }),
|
|
2607
|
+
showLabel ? /* @__PURE__ */ jsx(ActionSwapRollText, { value: theme, children: label }) : null
|
|
2608
|
+
]
|
|
2609
|
+
}
|
|
2610
|
+
);
|
|
2611
|
+
}
|
|
2612
|
+
var BREAKPOINTS2 = [
|
|
2613
|
+
["xs", 30],
|
|
2614
|
+
["sm", 40],
|
|
2615
|
+
["md", 50],
|
|
2616
|
+
["lg", 64],
|
|
2617
|
+
["xl", 80],
|
|
2618
|
+
["2xl", 96]
|
|
2619
|
+
];
|
|
2620
|
+
function getBreakpoint2() {
|
|
2621
|
+
let current = "base";
|
|
2622
|
+
for (const [name, rem] of BREAKPOINTS2) {
|
|
2623
|
+
if (globalThis.matchMedia(`(min-width: ${rem}rem)`).matches) current = name;
|
|
2624
|
+
}
|
|
2625
|
+
return current;
|
|
2626
|
+
}
|
|
2627
|
+
function onBreakpointChange2(listener) {
|
|
2628
|
+
const queries = BREAKPOINTS2.map(([, rem]) => globalThis.matchMedia(`(min-width: ${rem}rem)`));
|
|
2629
|
+
for (const query of queries) query.addEventListener("change", listener);
|
|
2630
|
+
return () => {
|
|
2631
|
+
for (const query of queries) query.removeEventListener("change", listener);
|
|
2632
|
+
};
|
|
2633
|
+
}
|
|
2634
|
+
function getBreakpointServer() {
|
|
2635
|
+
return "base";
|
|
2636
|
+
}
|
|
2637
|
+
function useBreakpoint() {
|
|
2638
|
+
const subscribe2 = useCallback(onBreakpointChange2, []);
|
|
2639
|
+
return useSyncExternalStore(subscribe2, getBreakpoint2, getBreakpointServer);
|
|
2640
|
+
}
|
|
2641
|
+
|
|
2642
|
+
export { Accordion, AccordionContent, AccordionHeader, AccordionItem, AccordionTrigger, ActionSwapRollIcon, ActionSwapRollText, AnimatedBeam, ArrowLeft, ArrowRight, ArrowSvg, BREAKPOINTS2 as BREAKPOINTS, Button, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChevronDownIcon2 as ChevronDownIcon, ChevronRightIcon, DiaTextReveal, EASE_OUT, EASE_OUT_CSS, ElevatedInput, FadeIn, FeatureCard, FlowDiamond, FlowNode, FlowPill, GlossyButton, grainient_default as Grainient, Highlighter, Input, JoinArrow, LiquidMetal, NavigationMenu, NavigationMenuArrow, NavigationMenuBackdrop, NavigationMenuContent, NavigationMenuIcon, NavigationMenuItem, NavigationMenuLink, NavigationMenuList, NavigationMenuPortal, NavigationMenuSub, NavigationMenuSubTrigger, NavigationMenuTrigger, NavigationMenuViewport, PasswordInput, RainbowButton, RangeSlider, RollingBadge, SPRING_SWAP, SavingsBadge, ShineBorder, SparklesText, SplitArrow, Stagger, StaggerItem, Tabs, ThemeToggle, TurnDown, cn, easeOut, easeOutBack, getBreakpoint2 as getBreakpoint, glossyButtonVariants, hasKey, navigationMenuSubTriggerStyle, navigationMenuTriggerStyle, noop, onBreakpointChange2 as onBreakpointChange, rainbowButtonVariants, solidSurface, useBreakpoint, validCssVars };
|
|
33
2643
|
//# sourceMappingURL=index.mjs.map
|
|
34
2644
|
//# sourceMappingURL=index.mjs.map
|