@saasflare/ui 3.0.2 → 3.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/button-0Bdl7Nqm.d.ts +87 -0
- package/dist/button-Brb4BhPO.d.mts +87 -0
- package/dist/{chunk-XXT4HKND.js → chunk-4BOMMZEY.js} +20 -13
- package/dist/{chunk-YAE5VBWJ.js → chunk-D5LKWKG7.js} +96 -152
- package/dist/chunk-DNLCSV5M.js +151 -0
- package/dist/{chunk-W53NTFPB.mjs → chunk-EJHYM2HP.mjs} +7 -16
- package/dist/chunk-FT66KYRN.js +30 -0
- package/dist/{chunk-2DNKXA5A.mjs → chunk-RW2S3KNB.mjs} +14 -7
- package/dist/chunk-WPOOC2FX.mjs +128 -0
- package/dist/{chunk-ORB66UYT.mjs → chunk-WRONFPRI.mjs} +66 -121
- package/dist/{dialog-CwyBJeNl.d.mts → dialog-BmY55WSX.d.ts} +4 -1
- package/dist/{dialog-CwyBJeNl.d.ts → dialog-CcaHMAsS.d.mts} +4 -1
- package/dist/entries/calendar.d.mts +5 -3
- package/dist/entries/calendar.d.ts +5 -3
- package/dist/entries/calendar.js +44 -36
- package/dist/entries/calendar.mjs +11 -3
- package/dist/entries/carousel.d.mts +4 -3
- package/dist/entries/carousel.d.ts +4 -3
- package/dist/entries/carousel.js +18 -11
- package/dist/entries/carousel.mjs +11 -4
- package/dist/entries/chart.d.mts +4 -2
- package/dist/entries/chart.d.ts +4 -2
- package/dist/entries/chart.js +17 -10
- package/dist/entries/chart.mjs +8 -1
- package/dist/entries/command.d.mts +5 -2
- package/dist/entries/command.d.ts +5 -2
- package/dist/entries/command.js +25 -18
- package/dist/entries/command.mjs +12 -5
- package/dist/entries/drawer.d.mts +4 -1
- package/dist/entries/drawer.d.ts +4 -1
- package/dist/entries/drawer.js +15 -8
- package/dist/entries/drawer.mjs +9 -2
- package/dist/entries/input-otp.d.mts +4 -2
- package/dist/entries/input-otp.d.ts +4 -2
- package/dist/entries/input-otp.js +13 -6
- package/dist/entries/input-otp.mjs +10 -3
- package/dist/entries/resizable.d.mts +3 -1
- package/dist/entries/resizable.d.ts +3 -1
- package/dist/entries/resizable.js +12 -5
- package/dist/entries/resizable.mjs +10 -3
- package/dist/index.d.mts +181 -79
- package/dist/index.d.ts +181 -79
- package/dist/index.js +807 -476
- package/dist/index.mjs +498 -171
- package/dist/{button-DUQJ0X7e.d.mts → use-saasflare-props-NrM2Glmp.d.mts} +1 -86
- package/dist/{button-DUQJ0X7e.d.ts → use-saasflare-props-NrM2Glmp.d.ts} +1 -86
- package/package.json +1 -1
- package/styles/theme.css +1 -1
- package/dist/chunk-BIU2MD4T.mjs +0 -56
- package/dist/chunk-CWW36RYE.js +0 -59
- package/dist/chunk-M3ICCPCU.js +0 -60
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
import { c as SaasflareComponentProps } from './use-saasflare-props-NrM2Glmp.js';
|
|
6
|
+
|
|
7
|
+
declare const INTENTS: readonly ["primary", "neutral", "success", "warning", "danger", "info"];
|
|
8
|
+
type Intent = (typeof INTENTS)[number];
|
|
9
|
+
/**
|
|
10
|
+
* Button variant definitions using the 3-axis system.
|
|
11
|
+
*
|
|
12
|
+
* Axes:
|
|
13
|
+
* variant — visual treatment: solid, soft, outline, ghost, link, glass, shadow
|
|
14
|
+
* intent — color intent via data-intent attribute + CSS tokens
|
|
15
|
+
* size — dimensional: xs, sm, md, lg, xl, icon, icon-xs, icon-sm, icon-lg
|
|
16
|
+
*/
|
|
17
|
+
declare const buttonVariants: (props?: ({
|
|
18
|
+
variant?: "outline" | "link" | "glass" | "soft" | "solid" | "ghost" | "shadow" | null | undefined;
|
|
19
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
20
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
21
|
+
/** Framer-motion event overrides that conflict with React HTML events */
|
|
22
|
+
type MotionConflicts = "onDrag" | "onDragStart" | "onDragEnd" | "onAnimationStart" | "onAnimationEnd";
|
|
23
|
+
/**
|
|
24
|
+
* Props for the Saasflare Button component.
|
|
25
|
+
*
|
|
26
|
+
* Extends {@link SaasflareComponentProps} to accept `surface` and `animated`
|
|
27
|
+
* overrides that are resolved against the <SaasflareProvider> context.
|
|
28
|
+
*/
|
|
29
|
+
interface ButtonProps extends Omit<React.ComponentProps<"button">, MotionConflicts>, VariantProps<typeof buttonVariants>, SaasflareComponentProps {
|
|
30
|
+
/** Render as child element (Radix Slot pattern) */
|
|
31
|
+
asChild?: boolean;
|
|
32
|
+
/** Semantic color intent */
|
|
33
|
+
intent?: Intent;
|
|
34
|
+
/** Show loading spinner (replaces left icon, keeps text visible) */
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
/** Stretch to full width of container */
|
|
37
|
+
fullWidth?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Primary interactive button with motion, loading, and intent support.
|
|
41
|
+
*
|
|
42
|
+
* Resolves `surface` and `animated` via {@link useSaasflareProps} with the
|
|
43
|
+
* precedence: component prop > <SaasflareProvider> context > hardcoded default.
|
|
44
|
+
*
|
|
45
|
+
* When no explicit `variant` is set and the resolved surface is `"glass"`, the
|
|
46
|
+
* button promotes itself to `variant="glass"`. An explicit `variant` prop always
|
|
47
|
+
* wins over the surface-based promotion.
|
|
48
|
+
*
|
|
49
|
+
* @component
|
|
50
|
+
* @layer ui
|
|
51
|
+
*
|
|
52
|
+
* @param {string} variant - Visual treatment: "solid" | "soft" | "outline" | "ghost" | "link" | "glass" | "shadow"
|
|
53
|
+
* @param {string} intent - Color intent: "primary" | "neutral" | "success" | "warning" | "danger" | "info"
|
|
54
|
+
* @param {string} size - Button size: "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
|
|
55
|
+
* @param {string} surface - Surface style override: "flat" | "glass" (inherits from provider when omitted)
|
|
56
|
+
* @param {boolean} animated - Gate motion effects (inherits from provider when omitted)
|
|
57
|
+
* @param {boolean} loading - Shows spinner, sets aria-busy, preserves width
|
|
58
|
+
* @param {boolean} fullWidth - Stretches to container width
|
|
59
|
+
* @param {boolean} asChild - Render as child element (Slot pattern)
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Solid primary (default)
|
|
63
|
+
* <Button>Save Changes</Button>
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Outline danger
|
|
67
|
+
* <Button variant="outline" intent="danger">Delete Account</Button>
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Inherits surface from provider — auto-promotes to glass variant
|
|
71
|
+
* <SaasflareProvider surface="glass"><Button>Frosted</Button></SaasflareProvider>
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // Loading state
|
|
75
|
+
* <Button loading>Processing...</Button>
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Icon button
|
|
79
|
+
* <Button variant="ghost" size="icon"><SettingsIcon /></Button>
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // Legacy API (deprecated but supported)
|
|
83
|
+
* <Button variant="destructive">Delete</Button>
|
|
84
|
+
*/
|
|
85
|
+
declare function Button({ className, variant: variantProp, size, intent: intentProp, asChild, loading, fullWidth, surface, radius, animated, disabled, children, ...props }: ButtonProps): react_jsx_runtime.JSX.Element;
|
|
86
|
+
|
|
87
|
+
export { Button as B, type Intent as I, type ButtonProps as a, buttonVariants as b };
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { VariantProps } from 'class-variance-authority';
|
|
5
|
+
import { c as SaasflareComponentProps } from './use-saasflare-props-NrM2Glmp.mjs';
|
|
6
|
+
|
|
7
|
+
declare const INTENTS: readonly ["primary", "neutral", "success", "warning", "danger", "info"];
|
|
8
|
+
type Intent = (typeof INTENTS)[number];
|
|
9
|
+
/**
|
|
10
|
+
* Button variant definitions using the 3-axis system.
|
|
11
|
+
*
|
|
12
|
+
* Axes:
|
|
13
|
+
* variant — visual treatment: solid, soft, outline, ghost, link, glass, shadow
|
|
14
|
+
* intent — color intent via data-intent attribute + CSS tokens
|
|
15
|
+
* size — dimensional: xs, sm, md, lg, xl, icon, icon-xs, icon-sm, icon-lg
|
|
16
|
+
*/
|
|
17
|
+
declare const buttonVariants: (props?: ({
|
|
18
|
+
variant?: "outline" | "link" | "glass" | "soft" | "solid" | "ghost" | "shadow" | null | undefined;
|
|
19
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
20
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
21
|
+
/** Framer-motion event overrides that conflict with React HTML events */
|
|
22
|
+
type MotionConflicts = "onDrag" | "onDragStart" | "onDragEnd" | "onAnimationStart" | "onAnimationEnd";
|
|
23
|
+
/**
|
|
24
|
+
* Props for the Saasflare Button component.
|
|
25
|
+
*
|
|
26
|
+
* Extends {@link SaasflareComponentProps} to accept `surface` and `animated`
|
|
27
|
+
* overrides that are resolved against the <SaasflareProvider> context.
|
|
28
|
+
*/
|
|
29
|
+
interface ButtonProps extends Omit<React.ComponentProps<"button">, MotionConflicts>, VariantProps<typeof buttonVariants>, SaasflareComponentProps {
|
|
30
|
+
/** Render as child element (Radix Slot pattern) */
|
|
31
|
+
asChild?: boolean;
|
|
32
|
+
/** Semantic color intent */
|
|
33
|
+
intent?: Intent;
|
|
34
|
+
/** Show loading spinner (replaces left icon, keeps text visible) */
|
|
35
|
+
loading?: boolean;
|
|
36
|
+
/** Stretch to full width of container */
|
|
37
|
+
fullWidth?: boolean;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Primary interactive button with motion, loading, and intent support.
|
|
41
|
+
*
|
|
42
|
+
* Resolves `surface` and `animated` via {@link useSaasflareProps} with the
|
|
43
|
+
* precedence: component prop > <SaasflareProvider> context > hardcoded default.
|
|
44
|
+
*
|
|
45
|
+
* When no explicit `variant` is set and the resolved surface is `"glass"`, the
|
|
46
|
+
* button promotes itself to `variant="glass"`. An explicit `variant` prop always
|
|
47
|
+
* wins over the surface-based promotion.
|
|
48
|
+
*
|
|
49
|
+
* @component
|
|
50
|
+
* @layer ui
|
|
51
|
+
*
|
|
52
|
+
* @param {string} variant - Visual treatment: "solid" | "soft" | "outline" | "ghost" | "link" | "glass" | "shadow"
|
|
53
|
+
* @param {string} intent - Color intent: "primary" | "neutral" | "success" | "warning" | "danger" | "info"
|
|
54
|
+
* @param {string} size - Button size: "xs" | "sm" | "md" | "lg" | "xl" | "icon" | "icon-xs" | "icon-sm" | "icon-lg"
|
|
55
|
+
* @param {string} surface - Surface style override: "flat" | "glass" (inherits from provider when omitted)
|
|
56
|
+
* @param {boolean} animated - Gate motion effects (inherits from provider when omitted)
|
|
57
|
+
* @param {boolean} loading - Shows spinner, sets aria-busy, preserves width
|
|
58
|
+
* @param {boolean} fullWidth - Stretches to container width
|
|
59
|
+
* @param {boolean} asChild - Render as child element (Slot pattern)
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* // Solid primary (default)
|
|
63
|
+
* <Button>Save Changes</Button>
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Outline danger
|
|
67
|
+
* <Button variant="outline" intent="danger">Delete Account</Button>
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* // Inherits surface from provider — auto-promotes to glass variant
|
|
71
|
+
* <SaasflareProvider surface="glass"><Button>Frosted</Button></SaasflareProvider>
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* // Loading state
|
|
75
|
+
* <Button loading>Processing...</Button>
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* // Icon button
|
|
79
|
+
* <Button variant="ghost" size="icon"><SettingsIcon /></Button>
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* // Legacy API (deprecated but supported)
|
|
83
|
+
* <Button variant="destructive">Delete</Button>
|
|
84
|
+
*/
|
|
85
|
+
declare function Button({ className, variant: variantProp, size, intent: intentProp, asChild, loading, fullWidth, surface, radius, animated, disabled, children, ...props }: ButtonProps): react_jsx_runtime.JSX.Element;
|
|
86
|
+
|
|
87
|
+
export { Button as B, type Intent as I, type ButtonProps as a, buttonVariants as b };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
4
|
+
var chunkFT66KYRN_js = require('./chunk-FT66KYRN.js');
|
|
5
|
+
var chunkD5LKWKG7_js = require('./chunk-D5LKWKG7.js');
|
|
6
6
|
var react = require('motion/react');
|
|
7
7
|
var DialogPrimitive = require('@radix-ui/react-dialog');
|
|
8
8
|
var lucideReact = require('lucide-react');
|
|
@@ -56,7 +56,7 @@ function DialogOverlay({
|
|
|
56
56
|
DialogPrimitive__namespace.Overlay,
|
|
57
57
|
{
|
|
58
58
|
"data-slot": "dialog-overlay",
|
|
59
|
-
className:
|
|
59
|
+
className: chunkD5LKWKG7_js.cn(
|
|
60
60
|
"fixed inset-0 z-50 bg-black/50 backdrop-blur-[2px] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
61
61
|
className
|
|
62
62
|
),
|
|
@@ -67,25 +67,32 @@ function DialogOverlay({
|
|
|
67
67
|
function DialogContent({
|
|
68
68
|
className,
|
|
69
69
|
children,
|
|
70
|
+
surface,
|
|
71
|
+
radius,
|
|
72
|
+
animated,
|
|
70
73
|
...props
|
|
71
74
|
}) {
|
|
72
|
-
const
|
|
75
|
+
const sf = chunkD5LKWKG7_js.useSaasflareProps({ surface, radius, animated });
|
|
76
|
+
const motion = chunkFT66KYRN_js.useSaasflareMotion(sf.animated, chunkFT66KYRN_js.springBouncy);
|
|
73
77
|
return /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
|
|
74
78
|
/* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
|
|
75
79
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
76
80
|
DialogPrimitive__namespace.Content,
|
|
77
81
|
{
|
|
82
|
+
...props,
|
|
78
83
|
"data-slot": "dialog-content",
|
|
79
84
|
asChild: true,
|
|
80
|
-
...props,
|
|
81
85
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
82
86
|
react.m.div,
|
|
83
87
|
{
|
|
84
|
-
|
|
88
|
+
"data-surface": sf.surface,
|
|
89
|
+
"data-radius": sf.radius,
|
|
90
|
+
"data-animated": String(sf.animated),
|
|
91
|
+
initial: motion.disabled ? { opacity: 1 } : { opacity: 0, scale: 0.95, y: 10 },
|
|
85
92
|
animate: { opacity: 1, scale: 1, y: 0 },
|
|
86
|
-
exit:
|
|
87
|
-
transition:
|
|
88
|
-
className:
|
|
93
|
+
exit: motion.disabled ? { opacity: 0 } : { opacity: 0, scale: 0.95, y: 10 },
|
|
94
|
+
transition: motion.transition,
|
|
95
|
+
className: chunkD5LKWKG7_js.cn(
|
|
89
96
|
"fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border bg-background p-6 shadow-lg sm:max-w-lg",
|
|
90
97
|
className
|
|
91
98
|
),
|
|
@@ -107,7 +114,7 @@ function DialogHeader({ className, ...props }) {
|
|
|
107
114
|
"div",
|
|
108
115
|
{
|
|
109
116
|
"data-slot": "dialog-header",
|
|
110
|
-
className:
|
|
117
|
+
className: chunkD5LKWKG7_js.cn("flex flex-col gap-2 text-center sm:text-left", className),
|
|
111
118
|
...props
|
|
112
119
|
}
|
|
113
120
|
);
|
|
@@ -117,7 +124,7 @@ function DialogFooter({ className, ...props }) {
|
|
|
117
124
|
"div",
|
|
118
125
|
{
|
|
119
126
|
"data-slot": "dialog-footer",
|
|
120
|
-
className:
|
|
127
|
+
className: chunkD5LKWKG7_js.cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", className),
|
|
121
128
|
...props
|
|
122
129
|
}
|
|
123
130
|
);
|
|
@@ -130,7 +137,7 @@ function DialogTitle({
|
|
|
130
137
|
DialogPrimitive__namespace.Title,
|
|
131
138
|
{
|
|
132
139
|
"data-slot": "dialog-title",
|
|
133
|
-
className:
|
|
140
|
+
className: chunkD5LKWKG7_js.cn("text-lg leading-none font-semibold", className),
|
|
134
141
|
...props
|
|
135
142
|
}
|
|
136
143
|
);
|
|
@@ -143,7 +150,7 @@ function DialogDescription({
|
|
|
143
150
|
DialogPrimitive__namespace.Description,
|
|
144
151
|
{
|
|
145
152
|
"data-slot": "dialog-description",
|
|
146
|
-
className:
|
|
153
|
+
className: chunkD5LKWKG7_js.cn("text-sm text-muted-foreground", className),
|
|
147
154
|
...props
|
|
148
155
|
}
|
|
149
156
|
);
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
var
|
|
5
|
-
var
|
|
6
|
-
var
|
|
4
|
+
var clsx = require('clsx');
|
|
5
|
+
var tailwindMerge = require('tailwind-merge');
|
|
6
|
+
var React2 = require('react');
|
|
7
|
+
require('class-variance-authority');
|
|
7
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
9
|
var nextThemes = require('next-themes');
|
|
9
|
-
var react
|
|
10
|
-
var lucideReact = require('lucide-react');
|
|
11
|
-
var classVarianceAuthority = require('class-variance-authority');
|
|
12
|
-
var Slot = require('@radix-ui/react-slot');
|
|
10
|
+
var react = require('motion/react');
|
|
13
11
|
|
|
14
12
|
function _interopNamespace(e) {
|
|
15
13
|
if (e && e.__esModule) return e;
|
|
@@ -29,14 +27,74 @@ function _interopNamespace(e) {
|
|
|
29
27
|
return Object.freeze(n);
|
|
30
28
|
}
|
|
31
29
|
|
|
32
|
-
var
|
|
30
|
+
var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
|
|
33
31
|
|
|
34
|
-
|
|
32
|
+
// src/lib/utils.ts
|
|
33
|
+
function cn(...inputs) {
|
|
34
|
+
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/lib/color.ts
|
|
38
|
+
function hexToOklch(hex) {
|
|
39
|
+
const normalized = normalizeHex(hex);
|
|
40
|
+
if (!normalized) return null;
|
|
41
|
+
const r = srgbToLinear(parseInt(normalized.slice(0, 2), 16) / 255);
|
|
42
|
+
const g = srgbToLinear(parseInt(normalized.slice(2, 4), 16) / 255);
|
|
43
|
+
const b = srgbToLinear(parseInt(normalized.slice(4, 6), 16) / 255);
|
|
44
|
+
const l_ = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
|
|
45
|
+
const m_ = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
|
|
46
|
+
const s_ = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
|
|
47
|
+
const lc = Math.cbrt(l_);
|
|
48
|
+
const mc = Math.cbrt(m_);
|
|
49
|
+
const sc = Math.cbrt(s_);
|
|
50
|
+
const L = 0.2104542553 * lc + 0.793617785 * mc - 0.0040720468 * sc;
|
|
51
|
+
const a = 1.9779984951 * lc - 2.428592205 * mc + 0.4505937099 * sc;
|
|
52
|
+
const b2 = 0.0259040371 * lc + 0.7827717662 * mc - 0.808675766 * sc;
|
|
53
|
+
const c = Math.sqrt(a * a + b2 * b2);
|
|
54
|
+
let h = Math.atan2(b2, a) * 180 / Math.PI;
|
|
55
|
+
if (h < 0) h += 360;
|
|
56
|
+
return { l: L, c, h };
|
|
57
|
+
}
|
|
58
|
+
function normalizeHex(input) {
|
|
59
|
+
if (typeof input !== "string") return null;
|
|
60
|
+
const s = input.trim().replace(/^#/, "").toLowerCase();
|
|
61
|
+
if (/^[0-9a-f]{3}$/.test(s)) {
|
|
62
|
+
return s[0] + s[0] + s[1] + s[1] + s[2] + s[2];
|
|
63
|
+
}
|
|
64
|
+
if (/^[0-9a-f]{4}$/.test(s)) {
|
|
65
|
+
return s[0] + s[0] + s[1] + s[1] + s[2] + s[2];
|
|
66
|
+
}
|
|
67
|
+
if (/^[0-9a-f]{6}$/.test(s)) {
|
|
68
|
+
return s;
|
|
69
|
+
}
|
|
70
|
+
if (/^[0-9a-f]{8}$/.test(s)) {
|
|
71
|
+
return s.slice(0, 6);
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
function srgbToLinear(c) {
|
|
76
|
+
return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
|
|
77
|
+
}
|
|
78
|
+
function isHex(input) {
|
|
79
|
+
return typeof input === "string" && /^#?[0-9a-f]{3,8}$/i.test(input.trim());
|
|
80
|
+
}
|
|
81
|
+
var QUERY = "(prefers-reduced-motion: reduce)";
|
|
82
|
+
var subscribe = (cb) => {
|
|
83
|
+
const mql = window.matchMedia(QUERY);
|
|
84
|
+
mql.addEventListener("change", cb);
|
|
85
|
+
return () => mql.removeEventListener("change", cb);
|
|
86
|
+
};
|
|
87
|
+
var getSnapshot = () => window.matchMedia(QUERY).matches;
|
|
88
|
+
var getServerSnapshot = () => false;
|
|
89
|
+
function useReducedMotion() {
|
|
90
|
+
return React2__namespace.useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
91
|
+
}
|
|
92
|
+
var AnimationContext = React2.createContext(
|
|
35
93
|
void 0
|
|
36
94
|
);
|
|
37
95
|
function useAnimation() {
|
|
38
|
-
const context =
|
|
39
|
-
const prefersReduced =
|
|
96
|
+
const context = React2.useContext(AnimationContext);
|
|
97
|
+
const prefersReduced = useReducedMotion();
|
|
40
98
|
if (context) return context;
|
|
41
99
|
return { animated: !prefersReduced };
|
|
42
100
|
}
|
|
@@ -44,9 +102,9 @@ function SmoothScrollProvider({
|
|
|
44
102
|
children,
|
|
45
103
|
enabled = true
|
|
46
104
|
}) {
|
|
47
|
-
const reduced =
|
|
105
|
+
const reduced = useReducedMotion();
|
|
48
106
|
const shouldSmooth = enabled && !reduced;
|
|
49
|
-
|
|
107
|
+
React2.useEffect(() => {
|
|
50
108
|
if (!shouldSmooth) return;
|
|
51
109
|
const html = document.documentElement;
|
|
52
110
|
const previous = html.style.scrollBehavior;
|
|
@@ -95,18 +153,18 @@ function SaasflareScript({ nonce, palette, surface, radius, animated, storageKey
|
|
|
95
153
|
}
|
|
96
154
|
var SYNC_PREFIX = "sf-ls:";
|
|
97
155
|
function useLocalStorage(key, initialValue, options) {
|
|
98
|
-
const initialRef =
|
|
99
|
-
const optionsRef =
|
|
156
|
+
const initialRef = React2.useRef(initialValue);
|
|
157
|
+
const optionsRef = React2.useRef(options);
|
|
100
158
|
optionsRef.current = options;
|
|
101
|
-
const serialize =
|
|
159
|
+
const serialize = React2.useCallback(
|
|
102
160
|
(value) => (optionsRef.current?.serializer ?? JSON.stringify)(value),
|
|
103
161
|
[]
|
|
104
162
|
);
|
|
105
|
-
const deserialize =
|
|
163
|
+
const deserialize = React2.useCallback(
|
|
106
164
|
(raw) => (optionsRef.current?.deserializer ?? JSON.parse)(raw),
|
|
107
165
|
[]
|
|
108
166
|
);
|
|
109
|
-
const handleError =
|
|
167
|
+
const handleError = React2.useCallback(
|
|
110
168
|
(error, operation) => {
|
|
111
169
|
if (optionsRef.current?.onError) {
|
|
112
170
|
optionsRef.current.onError(error, operation);
|
|
@@ -116,7 +174,7 @@ function useLocalStorage(key, initialValue, options) {
|
|
|
116
174
|
},
|
|
117
175
|
[key]
|
|
118
176
|
);
|
|
119
|
-
const readValue =
|
|
177
|
+
const readValue = React2.useCallback(() => {
|
|
120
178
|
if (typeof window === "undefined") return initialRef.current;
|
|
121
179
|
try {
|
|
122
180
|
const item = window.localStorage.getItem(key);
|
|
@@ -126,8 +184,8 @@ function useLocalStorage(key, initialValue, options) {
|
|
|
126
184
|
return initialRef.current;
|
|
127
185
|
}
|
|
128
186
|
}, [key, deserialize, handleError]);
|
|
129
|
-
const [storedValue, setStoredValue] =
|
|
130
|
-
const setValue =
|
|
187
|
+
const [storedValue, setStoredValue] = React2.useState(() => readValue());
|
|
188
|
+
const setValue = React2.useCallback(
|
|
131
189
|
(value) => {
|
|
132
190
|
try {
|
|
133
191
|
setStoredValue((prev) => {
|
|
@@ -144,7 +202,7 @@ function useLocalStorage(key, initialValue, options) {
|
|
|
144
202
|
},
|
|
145
203
|
[key, serialize, handleError]
|
|
146
204
|
);
|
|
147
|
-
const removeValue =
|
|
205
|
+
const removeValue = React2.useCallback(() => {
|
|
148
206
|
try {
|
|
149
207
|
if (typeof window !== "undefined") {
|
|
150
208
|
window.localStorage.removeItem(key);
|
|
@@ -155,7 +213,7 @@ function useLocalStorage(key, initialValue, options) {
|
|
|
155
213
|
handleError(error, "remove");
|
|
156
214
|
}
|
|
157
215
|
}, [key, handleError]);
|
|
158
|
-
|
|
216
|
+
React2.useEffect(() => {
|
|
159
217
|
const onStorage = (e) => {
|
|
160
218
|
if (e.key === key) setStoredValue(readValue());
|
|
161
219
|
};
|
|
@@ -168,7 +226,7 @@ function useLocalStorage(key, initialValue, options) {
|
|
|
168
226
|
window.removeEventListener(syncEvent, onSync);
|
|
169
227
|
};
|
|
170
228
|
}, [key, readValue]);
|
|
171
|
-
|
|
229
|
+
React2.useEffect(() => {
|
|
172
230
|
setStoredValue(readValue());
|
|
173
231
|
}, [readValue]);
|
|
174
232
|
return [storedValue, setValue, removeValue];
|
|
@@ -184,13 +242,13 @@ var DEFAULT_CONTEXT = {
|
|
|
184
242
|
setRadius: () => {
|
|
185
243
|
}
|
|
186
244
|
};
|
|
187
|
-
var SaasflareThemeContext =
|
|
245
|
+
var SaasflareThemeContext = React2.createContext(DEFAULT_CONTEXT);
|
|
188
246
|
function useSaasflareTheme() {
|
|
189
|
-
return
|
|
247
|
+
return React2.useContext(SaasflareThemeContext);
|
|
190
248
|
}
|
|
191
249
|
function applyColorAxis(root, prefix, value, injected) {
|
|
192
|
-
if (
|
|
193
|
-
const oklch =
|
|
250
|
+
if (isHex(value)) {
|
|
251
|
+
const oklch = hexToOklch(value);
|
|
194
252
|
if (oklch) {
|
|
195
253
|
const hKey = `--${prefix}-h`;
|
|
196
254
|
const cKey = `--${prefix}-c`;
|
|
@@ -211,7 +269,7 @@ function applyColorAxis(root, prefix, value, injected) {
|
|
|
211
269
|
}
|
|
212
270
|
function CustomPaletteInjector({ palette }) {
|
|
213
271
|
const { resolvedTheme } = nextThemes.useTheme();
|
|
214
|
-
|
|
272
|
+
React2.useEffect(() => {
|
|
215
273
|
const root = document.documentElement;
|
|
216
274
|
const injected = [];
|
|
217
275
|
applyColorAxis(root, "primary", palette.primary, injected);
|
|
@@ -268,21 +326,21 @@ function SaasflareProvider({
|
|
|
268
326
|
const currentPalette = isCustomPalette ? palette.name : palette ?? persisted.palette;
|
|
269
327
|
const currentStyle = surface ?? persisted.surface ?? "flat";
|
|
270
328
|
const currentRadius = radius ?? persisted.radius ?? "rounded";
|
|
271
|
-
const setPalette =
|
|
329
|
+
const setPalette = React2.useCallback(
|
|
272
330
|
(id) => setPersisted((prev) => ({ ...prev, palette: id })),
|
|
273
331
|
[setPersisted]
|
|
274
332
|
);
|
|
275
|
-
const setSurface =
|
|
333
|
+
const setSurface = React2.useCallback(
|
|
276
334
|
(style) => setPersisted((prev) => ({ ...prev, surface: style })),
|
|
277
335
|
[setPersisted]
|
|
278
336
|
);
|
|
279
|
-
const setRadius =
|
|
337
|
+
const setRadius = React2.useCallback(
|
|
280
338
|
(r) => setPersisted((prev) => ({ ...prev, radius: r })),
|
|
281
339
|
[setPersisted]
|
|
282
340
|
);
|
|
283
|
-
const prefersReduced =
|
|
341
|
+
const prefersReduced = useReducedMotion();
|
|
284
342
|
const effectiveAnimated = animated && !prefersReduced;
|
|
285
|
-
|
|
343
|
+
React2.useEffect(() => {
|
|
286
344
|
const root = document.documentElement;
|
|
287
345
|
if (currentPalette) {
|
|
288
346
|
root.setAttribute(SAASFLARE_DATA_ATTR.palette, currentPalette);
|
|
@@ -293,7 +351,7 @@ function SaasflareProvider({
|
|
|
293
351
|
root.setAttribute(SAASFLARE_DATA_ATTR.radius, currentRadius);
|
|
294
352
|
root.setAttribute(SAASFLARE_DATA_ATTR.animated, String(effectiveAnimated));
|
|
295
353
|
}, [currentPalette, currentStyle, currentRadius, effectiveAnimated]);
|
|
296
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react
|
|
354
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.LazyMotion, { features: react.domAnimation, strict: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
297
355
|
nextThemes.ThemeProvider,
|
|
298
356
|
{
|
|
299
357
|
attribute: "class",
|
|
@@ -380,7 +438,7 @@ function SaasflareShell({
|
|
|
380
438
|
}
|
|
381
439
|
function useSaasflareProps(props = {}) {
|
|
382
440
|
const ctx = useSaasflareTheme();
|
|
383
|
-
const anim =
|
|
441
|
+
const anim = React2.useContext(AnimationContext);
|
|
384
442
|
return {
|
|
385
443
|
surface: props.surface ?? ctx.surface,
|
|
386
444
|
radius: props.radius ?? ctx.radius,
|
|
@@ -388,127 +446,13 @@ function useSaasflareProps(props = {}) {
|
|
|
388
446
|
palette: ctx.palette
|
|
389
447
|
};
|
|
390
448
|
}
|
|
391
|
-
var MotionSlot = react$1.m.create(Slot__namespace.Root);
|
|
392
|
-
var LEGACY_VARIANT_MAP = {
|
|
393
|
-
default: { variant: "solid", intent: "primary" },
|
|
394
|
-
destructive: { variant: "solid", intent: "danger" },
|
|
395
|
-
secondary: { variant: "soft", intent: "neutral" }
|
|
396
|
-
};
|
|
397
|
-
var buttonVariants = classVarianceAuthority.cva(
|
|
398
|
-
"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
399
|
-
{
|
|
400
|
-
variants: {
|
|
401
|
-
variant: {
|
|
402
|
-
solid: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-xs hover:brightness-110 dark:hover:brightness-125",
|
|
403
|
-
soft: "bg-[var(--intent)]/15 text-[var(--intent)] hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
|
|
404
|
-
outline: "border border-[var(--intent)]/30 text-[var(--intent)] shadow-xs hover:bg-[var(--intent)]/10 dark:border-[var(--intent)]/40 dark:hover:bg-[var(--intent)]/15",
|
|
405
|
-
ghost: "text-[var(--intent)] hover:bg-[var(--intent)]/10 dark:hover:bg-[var(--intent)]/15",
|
|
406
|
-
link: "text-[var(--intent)] underline-offset-4 hover:underline",
|
|
407
|
-
glass: "bg-[var(--glass-bg)] text-[var(--intent)] border border-[var(--glass-border)] backdrop-blur-lg shadow-[var(--glass-shadow)] hover:bg-[var(--glass-bg-hover)] hover:border-[var(--glass-border-hover)]",
|
|
408
|
-
shadow: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-[var(--btn-shadow)] hover:shadow-[var(--btn-shadow-hover)] hover:brightness-110 dark:hover:brightness-125"
|
|
409
|
-
},
|
|
410
|
-
size: {
|
|
411
|
-
xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
412
|
-
sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
|
|
413
|
-
md: "h-9 px-4 py-2 has-[>svg]:px-3",
|
|
414
|
-
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
|
|
415
|
-
xl: "h-12 rounded-lg px-8 text-base has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5",
|
|
416
|
-
icon: "size-9",
|
|
417
|
-
"icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
418
|
-
"icon-sm": "size-8",
|
|
419
|
-
"icon-lg": "size-10"
|
|
420
|
-
}
|
|
421
|
-
},
|
|
422
|
-
defaultVariants: {
|
|
423
|
-
variant: "solid",
|
|
424
|
-
size: "md"
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
|
-
);
|
|
428
|
-
function Button({
|
|
429
|
-
className,
|
|
430
|
-
variant: variantProp,
|
|
431
|
-
size = "md",
|
|
432
|
-
intent: intentProp = "primary",
|
|
433
|
-
asChild = false,
|
|
434
|
-
loading = false,
|
|
435
|
-
fullWidth = false,
|
|
436
|
-
surface,
|
|
437
|
-
animated,
|
|
438
|
-
disabled,
|
|
439
|
-
children,
|
|
440
|
-
...props
|
|
441
|
-
}) {
|
|
442
|
-
const sfProps = useSaasflareProps({ surface, animated });
|
|
443
|
-
const reduced = chunkCWW36RYE_js.useReducedMotion();
|
|
444
|
-
const effectiveVariant = variantProp ?? (sfProps.surface === "glass" ? "glass" : "solid");
|
|
445
|
-
let resolvedVariant = effectiveVariant;
|
|
446
|
-
let resolvedIntent = intentProp;
|
|
447
|
-
const legacy = LEGACY_VARIANT_MAP[effectiveVariant];
|
|
448
|
-
if (legacy) {
|
|
449
|
-
resolvedVariant = legacy.variant;
|
|
450
|
-
if (legacy.intent) {
|
|
451
|
-
resolvedIntent = legacy.intent;
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
const motionDisabled = !sfProps.animated || reduced || disabled || loading;
|
|
455
|
-
const transition = !sfProps.animated || reduced ? chunkCWW36RYE_js.noMotion : chunkCWW36RYE_js.spring;
|
|
456
|
-
if (asChild) {
|
|
457
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
458
|
-
MotionSlot,
|
|
459
|
-
{
|
|
460
|
-
"data-slot": "button",
|
|
461
|
-
"data-variant": resolvedVariant,
|
|
462
|
-
"data-intent": resolvedIntent,
|
|
463
|
-
"data-size": size,
|
|
464
|
-
"data-surface": sfProps.surface,
|
|
465
|
-
whileHover: motionDisabled ? void 0 : { scale: 1.02 },
|
|
466
|
-
whileTap: motionDisabled ? void 0 : { scale: 0.97 },
|
|
467
|
-
transition,
|
|
468
|
-
className: chunkM3ICCPCU_js.cn(
|
|
469
|
-
buttonVariants({ variant: resolvedVariant, size }),
|
|
470
|
-
fullWidth && "w-full",
|
|
471
|
-
className
|
|
472
|
-
),
|
|
473
|
-
...props,
|
|
474
|
-
children
|
|
475
|
-
}
|
|
476
|
-
);
|
|
477
|
-
}
|
|
478
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
479
|
-
react$1.m.button,
|
|
480
|
-
{
|
|
481
|
-
"data-slot": "button",
|
|
482
|
-
"data-variant": resolvedVariant,
|
|
483
|
-
"data-intent": resolvedIntent,
|
|
484
|
-
"data-size": size,
|
|
485
|
-
"data-surface": sfProps.surface,
|
|
486
|
-
whileHover: motionDisabled ? void 0 : { scale: 1.02 },
|
|
487
|
-
whileTap: motionDisabled ? void 0 : { scale: 0.97 },
|
|
488
|
-
transition,
|
|
489
|
-
className: chunkM3ICCPCU_js.cn(
|
|
490
|
-
buttonVariants({ variant: resolvedVariant, size }),
|
|
491
|
-
fullWidth && "w-full",
|
|
492
|
-
className
|
|
493
|
-
),
|
|
494
|
-
disabled,
|
|
495
|
-
"aria-busy": loading || void 0,
|
|
496
|
-
"aria-disabled": disabled || void 0,
|
|
497
|
-
...props,
|
|
498
|
-
children: [
|
|
499
|
-
loading && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "animate-spin", "aria-hidden": "true" }),
|
|
500
|
-
children
|
|
501
|
-
]
|
|
502
|
-
}
|
|
503
|
-
);
|
|
504
|
-
}
|
|
505
449
|
|
|
506
|
-
exports.Button = Button;
|
|
507
450
|
exports.SaasflareProvider = SaasflareProvider;
|
|
508
451
|
exports.SaasflareScript = SaasflareScript;
|
|
509
452
|
exports.SaasflareShell = SaasflareShell;
|
|
510
453
|
exports.SmoothScrollProvider = SmoothScrollProvider;
|
|
511
|
-
exports.
|
|
454
|
+
exports.cn = cn;
|
|
512
455
|
exports.useAnimation = useAnimation;
|
|
456
|
+
exports.useReducedMotion = useReducedMotion;
|
|
513
457
|
exports.useSaasflareProps = useSaasflareProps;
|
|
514
458
|
exports.useSaasflareTheme = useSaasflareTheme;
|