@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.
Files changed (51) hide show
  1. package/dist/button-0Bdl7Nqm.d.ts +87 -0
  2. package/dist/button-Brb4BhPO.d.mts +87 -0
  3. package/dist/{chunk-XXT4HKND.js → chunk-4BOMMZEY.js} +20 -13
  4. package/dist/{chunk-YAE5VBWJ.js → chunk-D5LKWKG7.js} +96 -152
  5. package/dist/chunk-DNLCSV5M.js +151 -0
  6. package/dist/{chunk-W53NTFPB.mjs → chunk-EJHYM2HP.mjs} +7 -16
  7. package/dist/chunk-FT66KYRN.js +30 -0
  8. package/dist/{chunk-2DNKXA5A.mjs → chunk-RW2S3KNB.mjs} +14 -7
  9. package/dist/chunk-WPOOC2FX.mjs +128 -0
  10. package/dist/{chunk-ORB66UYT.mjs → chunk-WRONFPRI.mjs} +66 -121
  11. package/dist/{dialog-CwyBJeNl.d.mts → dialog-BmY55WSX.d.ts} +4 -1
  12. package/dist/{dialog-CwyBJeNl.d.ts → dialog-CcaHMAsS.d.mts} +4 -1
  13. package/dist/entries/calendar.d.mts +5 -3
  14. package/dist/entries/calendar.d.ts +5 -3
  15. package/dist/entries/calendar.js +44 -36
  16. package/dist/entries/calendar.mjs +11 -3
  17. package/dist/entries/carousel.d.mts +4 -3
  18. package/dist/entries/carousel.d.ts +4 -3
  19. package/dist/entries/carousel.js +18 -11
  20. package/dist/entries/carousel.mjs +11 -4
  21. package/dist/entries/chart.d.mts +4 -2
  22. package/dist/entries/chart.d.ts +4 -2
  23. package/dist/entries/chart.js +17 -10
  24. package/dist/entries/chart.mjs +8 -1
  25. package/dist/entries/command.d.mts +5 -2
  26. package/dist/entries/command.d.ts +5 -2
  27. package/dist/entries/command.js +25 -18
  28. package/dist/entries/command.mjs +12 -5
  29. package/dist/entries/drawer.d.mts +4 -1
  30. package/dist/entries/drawer.d.ts +4 -1
  31. package/dist/entries/drawer.js +15 -8
  32. package/dist/entries/drawer.mjs +9 -2
  33. package/dist/entries/input-otp.d.mts +4 -2
  34. package/dist/entries/input-otp.d.ts +4 -2
  35. package/dist/entries/input-otp.js +13 -6
  36. package/dist/entries/input-otp.mjs +10 -3
  37. package/dist/entries/resizable.d.mts +3 -1
  38. package/dist/entries/resizable.d.ts +3 -1
  39. package/dist/entries/resizable.js +12 -5
  40. package/dist/entries/resizable.mjs +10 -3
  41. package/dist/index.d.mts +181 -79
  42. package/dist/index.d.ts +181 -79
  43. package/dist/index.js +807 -476
  44. package/dist/index.mjs +498 -171
  45. package/dist/{button-DUQJ0X7e.d.mts → use-saasflare-props-NrM2Glmp.d.mts} +1 -86
  46. package/dist/{button-DUQJ0X7e.d.ts → use-saasflare-props-NrM2Glmp.d.ts} +1 -86
  47. package/package.json +1 -1
  48. package/styles/theme.css +1 -1
  49. package/dist/chunk-BIU2MD4T.mjs +0 -56
  50. package/dist/chunk-CWW36RYE.js +0 -59
  51. 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 chunkCWW36RYE_js = require('./chunk-CWW36RYE.js');
5
- var chunkM3ICCPCU_js = require('./chunk-M3ICCPCU.js');
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: chunkM3ICCPCU_js.cn(
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 reduced = chunkCWW36RYE_js.useReducedMotion();
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
- initial: reduced ? { opacity: 1 } : { opacity: 0, scale: 0.95, y: 10 },
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: reduced ? { opacity: 0 } : { opacity: 0, scale: 0.95, y: 10 },
87
- transition: reduced ? chunkCWW36RYE_js.noMotion : chunkCWW36RYE_js.springBouncy,
88
- className: chunkM3ICCPCU_js.cn(
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: chunkM3ICCPCU_js.cn("flex flex-col gap-2 text-center sm:text-left", 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: chunkM3ICCPCU_js.cn("flex flex-col-reverse gap-2 sm:flex-row sm:justify-end", 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: chunkM3ICCPCU_js.cn("text-lg leading-none font-semibold", 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: chunkM3ICCPCU_js.cn("text-sm text-muted-foreground", 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 chunkCWW36RYE_js = require('./chunk-CWW36RYE.js');
5
- var chunkM3ICCPCU_js = require('./chunk-M3ICCPCU.js');
6
- var react = require('react');
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$1 = require('motion/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 Slot__namespace = /*#__PURE__*/_interopNamespace(Slot);
30
+ var React2__namespace = /*#__PURE__*/_interopNamespace(React2);
33
31
 
34
- var AnimationContext = react.createContext(
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 = react.useContext(AnimationContext);
39
- const prefersReduced = chunkCWW36RYE_js.useReducedMotion();
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 = chunkCWW36RYE_js.useReducedMotion();
105
+ const reduced = useReducedMotion();
48
106
  const shouldSmooth = enabled && !reduced;
49
- react.useEffect(() => {
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 = react.useRef(initialValue);
99
- const optionsRef = react.useRef(options);
156
+ const initialRef = React2.useRef(initialValue);
157
+ const optionsRef = React2.useRef(options);
100
158
  optionsRef.current = options;
101
- const serialize = react.useCallback(
159
+ const serialize = React2.useCallback(
102
160
  (value) => (optionsRef.current?.serializer ?? JSON.stringify)(value),
103
161
  []
104
162
  );
105
- const deserialize = react.useCallback(
163
+ const deserialize = React2.useCallback(
106
164
  (raw) => (optionsRef.current?.deserializer ?? JSON.parse)(raw),
107
165
  []
108
166
  );
109
- const handleError = react.useCallback(
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 = react.useCallback(() => {
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] = react.useState(() => readValue());
130
- const setValue = react.useCallback(
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 = react.useCallback(() => {
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
- react.useEffect(() => {
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
- react.useEffect(() => {
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 = react.createContext(DEFAULT_CONTEXT);
245
+ var SaasflareThemeContext = React2.createContext(DEFAULT_CONTEXT);
188
246
  function useSaasflareTheme() {
189
- return react.useContext(SaasflareThemeContext);
247
+ return React2.useContext(SaasflareThemeContext);
190
248
  }
191
249
  function applyColorAxis(root, prefix, value, injected) {
192
- if (chunkM3ICCPCU_js.isHex(value)) {
193
- const oklch = chunkM3ICCPCU_js.hexToOklch(value);
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
- react.useEffect(() => {
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 = react.useCallback(
329
+ const setPalette = React2.useCallback(
272
330
  (id) => setPersisted((prev) => ({ ...prev, palette: id })),
273
331
  [setPersisted]
274
332
  );
275
- const setSurface = react.useCallback(
333
+ const setSurface = React2.useCallback(
276
334
  (style) => setPersisted((prev) => ({ ...prev, surface: style })),
277
335
  [setPersisted]
278
336
  );
279
- const setRadius = react.useCallback(
337
+ const setRadius = React2.useCallback(
280
338
  (r) => setPersisted((prev) => ({ ...prev, radius: r })),
281
339
  [setPersisted]
282
340
  );
283
- const prefersReduced = chunkCWW36RYE_js.useReducedMotion();
341
+ const prefersReduced = useReducedMotion();
284
342
  const effectiveAnimated = animated && !prefersReduced;
285
- react.useEffect(() => {
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$1.LazyMotion, { features: react$1.domAnimation, strict: true, children: /* @__PURE__ */ jsxRuntime.jsxs(
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 = react.useContext(AnimationContext);
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.buttonVariants = buttonVariants;
454
+ exports.cn = cn;
512
455
  exports.useAnimation = useAnimation;
456
+ exports.useReducedMotion = useReducedMotion;
513
457
  exports.useSaasflareProps = useSaasflareProps;
514
458
  exports.useSaasflareTheme = useSaasflareTheme;