@saasflare/ui 3.0.1 → 3.1.0

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 (50) hide show
  1. package/dist/button-0Bdl7Nqm.d.ts +87 -0
  2. package/dist/button-Brb4BhPO.d.mts +87 -0
  3. package/dist/{chunk-VQQ6MF5I.js → chunk-4BOMMZEY.js} +20 -13
  4. package/dist/{chunk-OYH6LQWR.js → chunk-D5LKWKG7.js} +50 -150
  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-7UGPCRZ6.mjs → chunk-RW2S3KNB.mjs} +14 -7
  9. package/dist/chunk-WPOOC2FX.mjs +128 -0
  10. package/dist/{chunk-QWLQV6FS.mjs → chunk-WRONFPRI.mjs} +22 -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 -477
  44. package/dist/index.mjs +498 -172
  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/dist/chunk-CWW36RYE.js +0 -59
  49. package/dist/chunk-JOVJRQO3.js +0 -12
  50. package/dist/chunk-S26666D6.mjs +0 -10
@@ -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 chunkJOVJRQO3_js = require('./chunk-JOVJRQO3.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: chunkJOVJRQO3_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: chunkJOVJRQO3_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: chunkJOVJRQO3_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: chunkJOVJRQO3_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: chunkJOVJRQO3_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: chunkJOVJRQO3_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 chunkJOVJRQO3_js = require('./chunk-JOVJRQO3.js');
6
- var classVarianceAuthority = require('class-variance-authority');
7
- 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');
8
8
  var jsxRuntime = require('react/jsx-runtime');
9
9
  var nextThemes = require('next-themes');
10
- var react$1 = require('motion/react');
11
- var lucideReact = require('lucide-react');
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,7 +27,12 @@ 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);
31
+
32
+ // src/lib/utils.ts
33
+ function cn(...inputs) {
34
+ return tailwindMerge.twMerge(clsx.clsx(inputs));
35
+ }
33
36
 
34
37
  // src/lib/color.ts
35
38
  function hexToOklch(hex) {
@@ -75,12 +78,23 @@ function srgbToLinear(c) {
75
78
  function isHex(input) {
76
79
  return typeof input === "string" && /^#?[0-9a-f]{3,8}$/i.test(input.trim());
77
80
  }
78
- var AnimationContext = react.createContext(
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(
79
93
  void 0
80
94
  );
81
95
  function useAnimation() {
82
- const context = react.useContext(AnimationContext);
83
- const prefersReduced = chunkCWW36RYE_js.useReducedMotion();
96
+ const context = React2.useContext(AnimationContext);
97
+ const prefersReduced = useReducedMotion();
84
98
  if (context) return context;
85
99
  return { animated: !prefersReduced };
86
100
  }
@@ -88,9 +102,9 @@ function SmoothScrollProvider({
88
102
  children,
89
103
  enabled = true
90
104
  }) {
91
- const reduced = chunkCWW36RYE_js.useReducedMotion();
105
+ const reduced = useReducedMotion();
92
106
  const shouldSmooth = enabled && !reduced;
93
- react.useEffect(() => {
107
+ React2.useEffect(() => {
94
108
  if (!shouldSmooth) return;
95
109
  const html = document.documentElement;
96
110
  const previous = html.style.scrollBehavior;
@@ -139,18 +153,18 @@ function SaasflareScript({ nonce, palette, surface, radius, animated, storageKey
139
153
  }
140
154
  var SYNC_PREFIX = "sf-ls:";
141
155
  function useLocalStorage(key, initialValue, options) {
142
- const initialRef = react.useRef(initialValue);
143
- const optionsRef = react.useRef(options);
156
+ const initialRef = React2.useRef(initialValue);
157
+ const optionsRef = React2.useRef(options);
144
158
  optionsRef.current = options;
145
- const serialize = react.useCallback(
159
+ const serialize = React2.useCallback(
146
160
  (value) => (optionsRef.current?.serializer ?? JSON.stringify)(value),
147
161
  []
148
162
  );
149
- const deserialize = react.useCallback(
163
+ const deserialize = React2.useCallback(
150
164
  (raw) => (optionsRef.current?.deserializer ?? JSON.parse)(raw),
151
165
  []
152
166
  );
153
- const handleError = react.useCallback(
167
+ const handleError = React2.useCallback(
154
168
  (error, operation) => {
155
169
  if (optionsRef.current?.onError) {
156
170
  optionsRef.current.onError(error, operation);
@@ -160,7 +174,7 @@ function useLocalStorage(key, initialValue, options) {
160
174
  },
161
175
  [key]
162
176
  );
163
- const readValue = react.useCallback(() => {
177
+ const readValue = React2.useCallback(() => {
164
178
  if (typeof window === "undefined") return initialRef.current;
165
179
  try {
166
180
  const item = window.localStorage.getItem(key);
@@ -170,8 +184,8 @@ function useLocalStorage(key, initialValue, options) {
170
184
  return initialRef.current;
171
185
  }
172
186
  }, [key, deserialize, handleError]);
173
- const [storedValue, setStoredValue] = react.useState(() => readValue());
174
- const setValue = react.useCallback(
187
+ const [storedValue, setStoredValue] = React2.useState(() => readValue());
188
+ const setValue = React2.useCallback(
175
189
  (value) => {
176
190
  try {
177
191
  setStoredValue((prev) => {
@@ -188,7 +202,7 @@ function useLocalStorage(key, initialValue, options) {
188
202
  },
189
203
  [key, serialize, handleError]
190
204
  );
191
- const removeValue = react.useCallback(() => {
205
+ const removeValue = React2.useCallback(() => {
192
206
  try {
193
207
  if (typeof window !== "undefined") {
194
208
  window.localStorage.removeItem(key);
@@ -199,7 +213,7 @@ function useLocalStorage(key, initialValue, options) {
199
213
  handleError(error, "remove");
200
214
  }
201
215
  }, [key, handleError]);
202
- react.useEffect(() => {
216
+ React2.useEffect(() => {
203
217
  const onStorage = (e) => {
204
218
  if (e.key === key) setStoredValue(readValue());
205
219
  };
@@ -212,7 +226,7 @@ function useLocalStorage(key, initialValue, options) {
212
226
  window.removeEventListener(syncEvent, onSync);
213
227
  };
214
228
  }, [key, readValue]);
215
- react.useEffect(() => {
229
+ React2.useEffect(() => {
216
230
  setStoredValue(readValue());
217
231
  }, [readValue]);
218
232
  return [storedValue, setValue, removeValue];
@@ -228,9 +242,9 @@ var DEFAULT_CONTEXT = {
228
242
  setRadius: () => {
229
243
  }
230
244
  };
231
- var SaasflareThemeContext = react.createContext(DEFAULT_CONTEXT);
245
+ var SaasflareThemeContext = React2.createContext(DEFAULT_CONTEXT);
232
246
  function useSaasflareTheme() {
233
- return react.useContext(SaasflareThemeContext);
247
+ return React2.useContext(SaasflareThemeContext);
234
248
  }
235
249
  function applyColorAxis(root, prefix, value, injected) {
236
250
  if (isHex(value)) {
@@ -255,7 +269,7 @@ function applyColorAxis(root, prefix, value, injected) {
255
269
  }
256
270
  function CustomPaletteInjector({ palette }) {
257
271
  const { resolvedTheme } = nextThemes.useTheme();
258
- react.useEffect(() => {
272
+ React2.useEffect(() => {
259
273
  const root = document.documentElement;
260
274
  const injected = [];
261
275
  applyColorAxis(root, "primary", palette.primary, injected);
@@ -312,21 +326,21 @@ function SaasflareProvider({
312
326
  const currentPalette = isCustomPalette ? palette.name : palette ?? persisted.palette;
313
327
  const currentStyle = surface ?? persisted.surface ?? "flat";
314
328
  const currentRadius = radius ?? persisted.radius ?? "rounded";
315
- const setPalette = react.useCallback(
329
+ const setPalette = React2.useCallback(
316
330
  (id) => setPersisted((prev) => ({ ...prev, palette: id })),
317
331
  [setPersisted]
318
332
  );
319
- const setSurface = react.useCallback(
333
+ const setSurface = React2.useCallback(
320
334
  (style) => setPersisted((prev) => ({ ...prev, surface: style })),
321
335
  [setPersisted]
322
336
  );
323
- const setRadius = react.useCallback(
337
+ const setRadius = React2.useCallback(
324
338
  (r) => setPersisted((prev) => ({ ...prev, radius: r })),
325
339
  [setPersisted]
326
340
  );
327
- const prefersReduced = chunkCWW36RYE_js.useReducedMotion();
341
+ const prefersReduced = useReducedMotion();
328
342
  const effectiveAnimated = animated && !prefersReduced;
329
- react.useEffect(() => {
343
+ React2.useEffect(() => {
330
344
  const root = document.documentElement;
331
345
  if (currentPalette) {
332
346
  root.setAttribute(SAASFLARE_DATA_ATTR.palette, currentPalette);
@@ -337,7 +351,7 @@ function SaasflareProvider({
337
351
  root.setAttribute(SAASFLARE_DATA_ATTR.radius, currentRadius);
338
352
  root.setAttribute(SAASFLARE_DATA_ATTR.animated, String(effectiveAnimated));
339
353
  }, [currentPalette, currentStyle, currentRadius, effectiveAnimated]);
340
- 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(
341
355
  nextThemes.ThemeProvider,
342
356
  {
343
357
  attribute: "class",
@@ -424,7 +438,7 @@ function SaasflareShell({
424
438
  }
425
439
  function useSaasflareProps(props = {}) {
426
440
  const ctx = useSaasflareTheme();
427
- const anim = react.useContext(AnimationContext);
441
+ const anim = React2.useContext(AnimationContext);
428
442
  return {
429
443
  surface: props.surface ?? ctx.surface,
430
444
  radius: props.radius ?? ctx.radius,
@@ -432,127 +446,13 @@ function useSaasflareProps(props = {}) {
432
446
  palette: ctx.palette
433
447
  };
434
448
  }
435
- var MotionSlot = react$1.m.create(Slot__namespace.Root);
436
- var LEGACY_VARIANT_MAP = {
437
- default: { variant: "solid", intent: "primary" },
438
- destructive: { variant: "solid", intent: "danger" },
439
- secondary: { variant: "soft", intent: "neutral" }
440
- };
441
- var buttonVariants = classVarianceAuthority.cva(
442
- "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",
443
- {
444
- variants: {
445
- variant: {
446
- solid: "bg-[var(--intent)] text-[var(--intent-fg)] shadow-xs hover:brightness-110 dark:hover:brightness-125",
447
- soft: "bg-[var(--intent)]/15 text-[var(--intent)] hover:bg-[var(--intent)]/25 dark:bg-[var(--intent)]/20 dark:hover:bg-[var(--intent)]/30",
448
- 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",
449
- ghost: "text-[var(--intent)] hover:bg-[var(--intent)]/10 dark:hover:bg-[var(--intent)]/15",
450
- link: "text-[var(--intent)] underline-offset-4 hover:underline",
451
- 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)]",
452
- 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"
453
- },
454
- size: {
455
- xs: "h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3",
456
- sm: "h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5",
457
- md: "h-9 px-4 py-2 has-[>svg]:px-3",
458
- lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
459
- xl: "h-12 rounded-lg px-8 text-base has-[>svg]:px-5 [&_svg:not([class*='size-'])]:size-5",
460
- icon: "size-9",
461
- "icon-xs": "size-6 rounded-md [&_svg:not([class*='size-'])]:size-3",
462
- "icon-sm": "size-8",
463
- "icon-lg": "size-10"
464
- }
465
- },
466
- defaultVariants: {
467
- variant: "solid",
468
- size: "md"
469
- }
470
- }
471
- );
472
- function Button({
473
- className,
474
- variant: variantProp,
475
- size = "md",
476
- intent: intentProp = "primary",
477
- asChild = false,
478
- loading = false,
479
- fullWidth = false,
480
- surface,
481
- animated,
482
- disabled,
483
- children,
484
- ...props
485
- }) {
486
- const sfProps = useSaasflareProps({ surface, animated });
487
- const reduced = chunkCWW36RYE_js.useReducedMotion();
488
- const effectiveVariant = variantProp ?? (sfProps.surface === "glass" ? "glass" : "solid");
489
- let resolvedVariant = effectiveVariant;
490
- let resolvedIntent = intentProp;
491
- const legacy = LEGACY_VARIANT_MAP[effectiveVariant];
492
- if (legacy) {
493
- resolvedVariant = legacy.variant;
494
- if (legacy.intent) {
495
- resolvedIntent = legacy.intent;
496
- }
497
- }
498
- const motionDisabled = !sfProps.animated || reduced || disabled || loading;
499
- const transition = !sfProps.animated || reduced ? chunkCWW36RYE_js.noMotion : chunkCWW36RYE_js.spring;
500
- if (asChild) {
501
- return /* @__PURE__ */ jsxRuntime.jsx(
502
- MotionSlot,
503
- {
504
- "data-slot": "button",
505
- "data-variant": resolvedVariant,
506
- "data-intent": resolvedIntent,
507
- "data-size": size,
508
- "data-surface": sfProps.surface,
509
- whileHover: motionDisabled ? void 0 : { scale: 1.02 },
510
- whileTap: motionDisabled ? void 0 : { scale: 0.97 },
511
- transition,
512
- className: chunkJOVJRQO3_js.cn(
513
- buttonVariants({ variant: resolvedVariant, size }),
514
- fullWidth && "w-full",
515
- className
516
- ),
517
- ...props,
518
- children
519
- }
520
- );
521
- }
522
- return /* @__PURE__ */ jsxRuntime.jsxs(
523
- react$1.m.button,
524
- {
525
- "data-slot": "button",
526
- "data-variant": resolvedVariant,
527
- "data-intent": resolvedIntent,
528
- "data-size": size,
529
- "data-surface": sfProps.surface,
530
- whileHover: motionDisabled ? void 0 : { scale: 1.02 },
531
- whileTap: motionDisabled ? void 0 : { scale: 0.97 },
532
- transition,
533
- className: chunkJOVJRQO3_js.cn(
534
- buttonVariants({ variant: resolvedVariant, size }),
535
- fullWidth && "w-full",
536
- className
537
- ),
538
- disabled,
539
- "aria-busy": loading || void 0,
540
- "aria-disabled": disabled || void 0,
541
- ...props,
542
- children: [
543
- loading && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "animate-spin", "aria-hidden": "true" }),
544
- children
545
- ]
546
- }
547
- );
548
- }
549
449
 
550
- exports.Button = Button;
551
450
  exports.SaasflareProvider = SaasflareProvider;
552
451
  exports.SaasflareScript = SaasflareScript;
553
452
  exports.SaasflareShell = SaasflareShell;
554
453
  exports.SmoothScrollProvider = SmoothScrollProvider;
555
- exports.buttonVariants = buttonVariants;
454
+ exports.cn = cn;
556
455
  exports.useAnimation = useAnimation;
456
+ exports.useReducedMotion = useReducedMotion;
557
457
  exports.useSaasflareProps = useSaasflareProps;
558
458
  exports.useSaasflareTheme = useSaasflareTheme;