beez-ui 0.5.2 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +66 -3
  3. package/dist/components/alert-dialog.js +72 -28
  4. package/dist/components/alert.js +9 -5
  5. package/dist/components/animated-theme-toggler.js +113 -97
  6. package/dist/components/avatar.js +22 -15
  7. package/dist/components/badge.js +9 -5
  8. package/dist/components/button.js +11 -7
  9. package/dist/components/card.js +9 -5
  10. package/dist/components/carousel.js +59 -55
  11. package/dist/components/checkbox.js +16 -9
  12. package/dist/components/dialog.js +77 -33
  13. package/dist/components/dropdown-menu.js +126 -49
  14. package/dist/components/form.js +16 -9
  15. package/dist/components/highlighter.js +18 -12
  16. package/dist/components/hover-card.js +60 -21
  17. package/dist/components/input-group.js +9 -5
  18. package/dist/components/input.js +9 -5
  19. package/dist/components/label.js +8 -4
  20. package/dist/components/link.d.ts +0 -1
  21. package/dist/components/link.js +28 -20
  22. package/dist/components/popover.js +66 -25
  23. package/dist/components/radio-group.js +16 -9
  24. package/dist/components/select.js +34 -24
  25. package/dist/components/separator.js +9 -5
  26. package/dist/components/sheet.js +78 -34
  27. package/dist/components/sidebar.js +21 -14
  28. package/dist/components/skeleton.js +8 -4
  29. package/dist/components/svgs/whatsappIcon.js +14 -9
  30. package/dist/components/switch.js +16 -9
  31. package/dist/components/table.js +8 -4
  32. package/dist/components/tabs.js +15 -8
  33. package/dist/components/textarea.js +8 -4
  34. package/dist/components/themed-toaster.js +61 -27
  35. package/dist/components/tooltip.js +70 -29
  36. package/dist/components/typing-animation.js +80 -58
  37. package/dist/constants/motion.d.ts +2 -0
  38. package/dist/constants/motion.js +2 -0
  39. package/dist/hooks/use-prefers-reduced-motion.d.ts +2 -0
  40. package/dist/hooks/use-prefers-reduced-motion.js +27 -0
  41. package/dist/lib/utils.d.ts +1 -1
  42. package/dist/lib/utils.js +1 -1
  43. package/dist/motion/motion-slot.d.ts +9 -0
  44. package/dist/motion/motion-slot.js +353 -0
  45. package/dist/motion/presence.d.ts +33 -0
  46. package/dist/motion/presence.js +92 -0
  47. package/dist/motion/tokens.d.ts +13 -0
  48. package/dist/motion/tokens.js +17 -0
  49. package/dist/providers/beez-ui-provider.js +7 -3
  50. package/dist/styles.css +1 -1
  51. package/package.json +13 -5
@@ -1,6 +1,7 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  import * as React from "react";
4
+ import { MotionSlot } from "../motion/motion-slot.js";
4
5
  import { cn } from "../lib/utils.js";
5
6
  import { jsx as _jsx } from "react/jsx-runtime";
6
7
  function Table(t0) {
@@ -174,10 +175,13 @@ function TableRow(t0) {
174
175
  }
175
176
  let t2;
176
177
  if ($[5] !== props || $[6] !== t1) {
177
- t2 = /* @__PURE__ */ _jsx("tr", {
178
- "data-slot": "table-row",
179
- className: t1,
180
- ...props
178
+ t2 = /* @__PURE__ */ _jsx(MotionSlot, {
179
+ kind: "row",
180
+ children: /* @__PURE__ */ _jsx("tr", {
181
+ "data-slot": "table-row",
182
+ className: t1,
183
+ ...props
184
+ })
181
185
  });
182
186
  $[5] = props;
183
187
  $[6] = t1;
@@ -3,6 +3,7 @@ import { c as _c } from "react/compiler-runtime";
3
3
  import * as React from "react";
4
4
  import { cva } from "class-variance-authority";
5
5
  import { Tabs as TabsPrimitive } from "radix-ui";
6
+ import { MotionSlot } from "../motion/motion-slot.js";
6
7
  import { cn } from "../lib/utils.js";
7
8
  import { jsx as _jsx } from "react/jsx-runtime";
8
9
  function Tabs(t0) {
@@ -120,10 +121,13 @@ function TabsTrigger(t0) {
120
121
  }
121
122
  let t2;
122
123
  if ($[5] !== props || $[6] !== t1) {
123
- t2 = /* @__PURE__ */ _jsx(TabsPrimitive.Trigger, {
124
- "data-slot": "tabs-trigger",
125
- className: t1,
126
- ...props
124
+ t2 = /* @__PURE__ */ _jsx(MotionSlot, {
125
+ kind: "press",
126
+ children: /* @__PURE__ */ _jsx(TabsPrimitive.Trigger, {
127
+ "data-slot": "tabs-trigger",
128
+ className: t1,
129
+ ...props
130
+ })
127
131
  });
128
132
  $[5] = props;
129
133
  $[6] = t1;
@@ -156,10 +160,13 @@ function TabsContent(t0) {
156
160
  }
157
161
  let t2;
158
162
  if ($[5] !== props || $[6] !== t1) {
159
- t2 = /* @__PURE__ */ _jsx(TabsPrimitive.Content, {
160
- "data-slot": "tabs-content",
161
- className: t1,
162
- ...props
163
+ t2 = /* @__PURE__ */ _jsx(MotionSlot, {
164
+ kind: "fade",
165
+ children: /* @__PURE__ */ _jsx(TabsPrimitive.Content, {
166
+ "data-slot": "tabs-content",
167
+ className: t1,
168
+ ...props
169
+ })
163
170
  });
164
171
  $[5] = props;
165
172
  $[6] = t1;
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { MotionSlot } from "../motion/motion-slot.js";
2
3
  import { cn } from "../lib/utils.js";
3
4
  import { jsx as _jsx } from "react/jsx-runtime";
4
5
  /**
@@ -7,10 +8,13 @@ import { jsx as _jsx } from "react/jsx-runtime";
7
8
  * @returns The styled primitive with its original interaction contract.
8
9
  */
9
10
  function Textarea({ className, ...props }) {
10
- return /* @__PURE__ */ _jsx("textarea", {
11
- "data-slot": "textarea",
12
- className: cn("flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className),
13
- ...props
11
+ return /* @__PURE__ */ _jsx(MotionSlot, {
12
+ kind: "field",
13
+ children: /* @__PURE__ */ _jsx("textarea", {
14
+ "data-slot": "textarea",
15
+ className: cn("flex field-sizing-content min-h-16 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40", className),
16
+ ...props
17
+ })
14
18
  });
15
19
  }
16
20
  export { Textarea };
@@ -1,12 +1,13 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
+ import { MotionSlot } from "../motion/motion-slot.js";
3
4
  import { Toaster as Sonner } from "sonner";
4
5
  import { useTheme } from "next-themes";
5
6
  import { CircleCheck, Info, TriangleAlert, OctagonAlert, Loader } from "lucide-react";
6
7
  import { jsx as _jsx } from "react/jsx-runtime";
7
8
  /** Renders shared notification styling using the consumer's resolved theme. */
8
9
  const ThemedToaster = (t0) => {
9
- const $ = _c(9);
10
+ const $ = _c(12);
10
11
  let props;
11
12
  let theme;
12
13
  if ($[0] !== t0) {
@@ -21,50 +22,83 @@ const ThemedToaster = (t0) => {
21
22
  const { resolvedTheme } = useTheme();
22
23
  const activeTheme = theme ?? (resolvedTheme === "dark" ? "dark" : "light");
23
24
  let t1;
24
- let t2;
25
25
  if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
26
- t1 = {
27
- success: /* @__PURE__ */ _jsx(CircleCheck, { className: "size-4" }),
28
- info: /* @__PURE__ */ _jsx(Info, { className: "size-4" }),
29
- warning: /* @__PURE__ */ _jsx(TriangleAlert, { className: "size-4" }),
30
- error: /* @__PURE__ */ _jsx(OctagonAlert, { className: "size-4" }),
31
- loading: /* @__PURE__ */ _jsx(Loader, { className: "size-4 animate-spin" })
32
- };
33
- t2 = {
34
- "--normal-bg": "var(--popover)",
35
- "--normal-text": "var(--popover-foreground)",
36
- "--normal-border": "var(--border)",
37
- "--border-radius": "var(--radius)"
38
- };
26
+ t1 = /* @__PURE__ */ _jsx(MotionSlot, {
27
+ kind: "selection",
28
+ children: /* @__PURE__ */ _jsx(CircleCheck, { className: "size-4" })
29
+ });
39
30
  $[3] = t1;
40
- $[4] = t2;
41
31
  } else {
42
32
  t1 = $[3];
33
+ }
34
+ let t2;
35
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
36
+ t2 = /* @__PURE__ */ _jsx(MotionSlot, {
37
+ kind: "selection",
38
+ children: /* @__PURE__ */ _jsx(Info, { className: "size-4" })
39
+ });
40
+ $[4] = t2;
41
+ } else {
43
42
  t2 = $[4];
44
43
  }
45
44
  let t3;
46
45
  if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
47
- t3 = { classNames: { toast: "cn-toast" } };
46
+ t3 = /* @__PURE__ */ _jsx(MotionSlot, {
47
+ kind: "selection",
48
+ children: /* @__PURE__ */ _jsx(TriangleAlert, { className: "size-4" })
49
+ });
48
50
  $[5] = t3;
49
51
  } else {
50
52
  t3 = $[5];
51
53
  }
52
54
  let t4;
53
- if ($[6] !== activeTheme || $[7] !== props) {
54
- t4 = /* @__PURE__ */ _jsx(Sonner, {
55
+ let t5;
56
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
57
+ t4 = {
58
+ success: t1,
59
+ info: t2,
60
+ warning: t3,
61
+ error: /* @__PURE__ */ _jsx(MotionSlot, {
62
+ kind: "selection",
63
+ children: /* @__PURE__ */ _jsx(OctagonAlert, { className: "size-4" })
64
+ }),
65
+ loading: /* @__PURE__ */ _jsx(Loader, { className: "size-4 animate-spin" })
66
+ };
67
+ t5 = {
68
+ "--normal-bg": "var(--popover)",
69
+ "--normal-text": "var(--popover-foreground)",
70
+ "--normal-border": "var(--border)",
71
+ "--border-radius": "var(--radius)"
72
+ };
73
+ $[6] = t4;
74
+ $[7] = t5;
75
+ } else {
76
+ t4 = $[6];
77
+ t5 = $[7];
78
+ }
79
+ let t6;
80
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
81
+ t6 = { classNames: { toast: "cn-toast" } };
82
+ $[8] = t6;
83
+ } else {
84
+ t6 = $[8];
85
+ }
86
+ let t7;
87
+ if ($[9] !== activeTheme || $[10] !== props) {
88
+ t7 = /* @__PURE__ */ _jsx(Sonner, {
55
89
  theme: activeTheme,
56
90
  className: "toaster group",
57
- icons: t1,
58
- style: t2,
59
- toastOptions: t3,
91
+ icons: t4,
92
+ style: t5,
93
+ toastOptions: t6,
60
94
  ...props
61
95
  });
62
- $[6] = activeTheme;
63
- $[7] = props;
64
- $[8] = t4;
96
+ $[9] = activeTheme;
97
+ $[10] = props;
98
+ $[11] = t7;
65
99
  } else {
66
- t4 = $[8];
100
+ t7 = $[11];
67
101
  }
68
- return t4;
102
+ return t7;
69
103
  };
70
104
  export { ThemedToaster };
@@ -2,6 +2,8 @@
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  import * as React from "react";
4
4
  import { Tooltip as TooltipPrimitive } from "radix-ui";
5
+ import { MotionSlot } from "../motion/motion-slot.js";
6
+ import { MotionPresence, MotionOpenProvider, useMotionOpenState } from "../motion/presence.js";
5
7
  import { cn } from "../lib/utils.js";
6
8
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
9
  function TooltipProvider(t0) {
@@ -34,7 +36,7 @@ function TooltipProvider(t0) {
34
36
  return t2;
35
37
  }
36
38
  function Tooltip(t0) {
37
- const $ = _c(4);
39
+ const $ = _c(9);
38
40
  let props;
39
41
  if ($[0] !== t0) {
40
42
  ({...props} = t0);
@@ -43,18 +45,36 @@ function Tooltip(t0) {
43
45
  } else {
44
46
  props = $[1];
45
47
  }
48
+ const [motionOpen, setMotionOpen] = useMotionOpenState(props);
46
49
  let t1;
47
- if ($[2] !== props) {
50
+ if ($[2] !== motionOpen || $[3] !== props || $[4] !== setMotionOpen) {
48
51
  t1 = /* @__PURE__ */ _jsx(TooltipPrimitive.Root, {
49
52
  "data-slot": "tooltip",
50
- ...props
53
+ ...props,
54
+ open: motionOpen,
55
+ onOpenChange: setMotionOpen
51
56
  });
52
- $[2] = props;
53
- $[3] = t1;
57
+ $[2] = motionOpen;
58
+ $[3] = props;
59
+ $[4] = setMotionOpen;
60
+ $[5] = t1;
54
61
  } else {
55
- t1 = $[3];
62
+ t1 = $[5];
56
63
  }
57
- return t1;
64
+ let t2;
65
+ if ($[6] !== motionOpen || $[7] !== t1) {
66
+ t2 = /* @__PURE__ */ _jsx(MotionOpenProvider, {
67
+ scope: "tooltip",
68
+ open: motionOpen,
69
+ children: t1
70
+ });
71
+ $[6] = motionOpen;
72
+ $[7] = t1;
73
+ $[8] = t2;
74
+ } else {
75
+ t2 = $[8];
76
+ }
77
+ return t2;
58
78
  }
59
79
  function TooltipTrigger(t0) {
60
80
  const $ = _c(4);
@@ -80,7 +100,7 @@ function TooltipTrigger(t0) {
80
100
  return t1;
81
101
  }
82
102
  function TooltipContent(t0) {
83
- const $ = _c(13);
103
+ const $ = _c(16);
84
104
  let children;
85
105
  let className;
86
106
  let props;
@@ -99,38 +119,59 @@ function TooltipContent(t0) {
99
119
  t1 = $[4];
100
120
  }
101
121
  const sideOffset = t1 === undefined ? 0 : t1;
102
- let t2;
122
+ const t2 = props.forceMount;
123
+ let t3;
103
124
  if ($[5] !== className) {
104
- t2 = cn("z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm data-[state=delayed-open]:animate-in data-[state=delayed-open]:fade-in-0 data-[state=delayed-open]:zoom-in-95 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95", className);
125
+ t3 = cn("z-50 inline-flex w-fit max-w-xs origin-(--radix-tooltip-content-transform-origin) items-center gap-1.5 rounded-md bg-foreground px-3 py-1.5 text-xs text-background has-data-[slot=kbd]:pr-1.5 **:data-[slot=kbd]:relative **:data-[slot=kbd]:isolate **:data-[slot=kbd]:z-50 **:data-[slot=kbd]:rounded-sm ", className);
105
126
  $[5] = className;
106
- $[6] = t2;
127
+ $[6] = t3;
107
128
  } else {
108
- t2 = $[6];
129
+ t3 = $[6];
109
130
  }
110
- let t3;
131
+ let t4;
111
132
  if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
112
- t3 = /* @__PURE__ */ _jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" });
113
- $[7] = t3;
133
+ t4 = /* @__PURE__ */ _jsx(TooltipPrimitive.Arrow, { className: "z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] bg-foreground fill-foreground" });
134
+ $[7] = t4;
114
135
  } else {
115
- t3 = $[7];
136
+ t4 = $[7];
116
137
  }
117
- let t4;
118
- if ($[8] !== children || $[9] !== props || $[10] !== sideOffset || $[11] !== t2) {
119
- t4 = /* @__PURE__ */ _jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ _jsxs(TooltipPrimitive.Content, {
120
- "data-slot": "tooltip-content",
121
- sideOffset,
122
- className: t2,
123
- ...props,
124
- children: [children, t3]
125
- }) });
138
+ let t5;
139
+ if ($[8] !== children || $[9] !== props || $[10] !== sideOffset || $[11] !== t3) {
140
+ t5 = /* @__PURE__ */ _jsx(MotionSlot, {
141
+ kind: "surface",
142
+ children: /* @__PURE__ */ _jsxs(TooltipPrimitive.Content, {
143
+ forceMount: true,
144
+ "data-slot": "tooltip-content",
145
+ sideOffset,
146
+ className: t3,
147
+ ...props,
148
+ children: [children, t4]
149
+ })
150
+ });
126
151
  $[8] = children;
127
152
  $[9] = props;
128
153
  $[10] = sideOffset;
129
- $[11] = t2;
130
- $[12] = t4;
154
+ $[11] = t3;
155
+ $[12] = t5;
156
+ } else {
157
+ t5 = $[12];
158
+ }
159
+ let t6;
160
+ if ($[13] !== props.forceMount || $[14] !== t5) {
161
+ t6 = /* @__PURE__ */ _jsx(TooltipPrimitive.Portal, {
162
+ forceMount: true,
163
+ children: /* @__PURE__ */ _jsx(MotionPresence, {
164
+ scope: "tooltip",
165
+ forceMount: t2,
166
+ children: t5
167
+ })
168
+ });
169
+ $[13] = props.forceMount;
170
+ $[14] = t5;
171
+ $[15] = t6;
131
172
  } else {
132
- t4 = $[12];
173
+ t6 = $[15];
133
174
  }
134
- return t4;
175
+ return t6;
135
176
  }
136
177
  export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger };
@@ -2,6 +2,7 @@
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { motion } from "motion/react";
5
+ import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
5
6
  import { cn } from "../lib/utils.js";
6
7
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
7
8
  const motionElements = {
@@ -19,7 +20,7 @@ const motionElements = {
19
20
  span: motion.span
20
21
  };
21
22
  export function TypingAnimation(t0) {
22
- const $ = _c(64);
23
+ const $ = _c(67);
23
24
  let children;
24
25
  let className;
25
26
  let deleteSpeed;
@@ -79,6 +80,8 @@ export function TypingAnimation(t0) {
79
80
  const showCursor = t7 === undefined ? true : t7;
80
81
  const blinkCursor = t8 === undefined ? true : t8;
81
82
  const cursorStyle = t9 === undefined ? "line" : t9;
83
+ const shouldReduceMotion = usePrefersReducedMotion();
84
+ const wasReducedMotionRef = useRef(false);
82
85
  const MotionComponent = motionElements[Component];
83
86
  const [displayedText, setDisplayedText] = useState("");
84
87
  const [currentWordIndex, setCurrentWordIndex] = useState(0);
@@ -154,11 +157,18 @@ export function TypingAnimation(t0) {
154
157
  useEffect(t13, t14);
155
158
  let t15;
156
159
  let t16;
157
- if ($[28] !== animationSourceKey) {
160
+ if ($[28] !== animationSourceKey || $[29] !== shouldReduceMotion || $[30] !== wordsToAnimate) {
158
161
  t15 = () => {
159
- if (lastResetSourceKeyRef.current === animationSourceKey) {
162
+ if (shouldReduceMotion) {
163
+ wasReducedMotionRef.current = true;
164
+ lastResetSourceKeyRef.current = animationSourceKey;
165
+ setDisplayedText(wordsToAnimate.join(" · "));
160
166
  return;
161
167
  }
168
+ if (lastResetSourceKeyRef.current === animationSourceKey && !wasReducedMotionRef.current) {
169
+ return;
170
+ }
171
+ wasReducedMotionRef.current = false;
162
172
  lastResetSourceKeyRef.current = animationSourceKey;
163
173
  const resetTimeout = setTimeout(() => {
164
174
  setDisplayedText("");
@@ -170,26 +180,35 @@ export function TypingAnimation(t0) {
170
180
  clearTimeout(resetTimeout);
171
181
  };
172
182
  };
173
- t16 = [animationSourceKey];
183
+ t16 = [
184
+ animationSourceKey,
185
+ shouldReduceMotion,
186
+ wordsToAnimate
187
+ ];
174
188
  $[28] = animationSourceKey;
175
- $[29] = t15;
176
- $[30] = t16;
189
+ $[29] = shouldReduceMotion;
190
+ $[30] = wordsToAnimate;
191
+ $[31] = t15;
192
+ $[32] = t16;
177
193
  } else {
178
- t15 = $[29];
179
- t16 = $[30];
194
+ t15 = $[31];
195
+ t16 = $[32];
180
196
  }
181
197
  useEffect(t15, t16);
182
198
  let t17;
183
199
  let t18;
184
- if ($[31] !== currentCharIndex || $[32] !== currentWordIndex || $[33] !== delay || $[34] !== deletingSpeed || $[35] !== displayedText || $[36] !== hasMultipleWords || $[37] !== loop || $[38] !== pauseDelay || $[39] !== phase || $[40] !== shouldStart || $[41] !== typingSpeed || $[42] !== wordsToAnimate) {
200
+ if ($[33] !== currentCharIndex || $[34] !== currentWordIndex || $[35] !== delay || $[36] !== deletingSpeed || $[37] !== displayedText || $[38] !== hasMultipleWords || $[39] !== loop || $[40] !== pauseDelay || $[41] !== phase || $[42] !== shouldReduceMotion || $[43] !== shouldStart || $[44] !== typingSpeed || $[45] !== wordsToAnimate) {
185
201
  t17 = () => {
202
+ if (shouldReduceMotion) {
203
+ return;
204
+ }
186
205
  let timeout = null;
187
206
  if (shouldStart && wordsToAnimate.length > 0) {
188
207
  const timeoutDelay = delay > 0 && displayedText === "" ? delay : phase === "typing" ? typingSpeed : phase === "deleting" ? deletingSpeed : pauseDelay;
189
208
  timeout = setTimeout(() => {
190
209
  const currentWord = wordsToAnimate[currentWordIndex] || "";
191
210
  const graphemes = Array.from(currentWord);
192
- bb126: switch (phase) {
211
+ bb136: switch (phase) {
193
212
  case "typing": {
194
213
  if (currentCharIndex < graphemes.length) {
195
214
  setDisplayedText(graphemes.slice(0, currentCharIndex + 1).join(""));
@@ -202,11 +221,11 @@ export function TypingAnimation(t0) {
202
221
  }
203
222
  }
204
223
  }
205
- break bb126;
224
+ break bb136;
206
225
  }
207
226
  case "pause": {
208
227
  setPhase("deleting");
209
- break bb126;
228
+ break bb136;
210
229
  }
211
230
  case "deleting": {
212
231
  if (currentCharIndex > 0) {
@@ -229,6 +248,7 @@ export function TypingAnimation(t0) {
229
248
  };
230
249
  t18 = [
231
250
  shouldStart,
251
+ shouldReduceMotion,
232
252
  phase,
233
253
  currentCharIndex,
234
254
  currentWordIndex,
@@ -241,39 +261,40 @@ export function TypingAnimation(t0) {
241
261
  pauseDelay,
242
262
  delay
243
263
  ];
244
- $[31] = currentCharIndex;
245
- $[32] = currentWordIndex;
246
- $[33] = delay;
247
- $[34] = deletingSpeed;
248
- $[35] = displayedText;
249
- $[36] = hasMultipleWords;
250
- $[37] = loop;
251
- $[38] = pauseDelay;
252
- $[39] = phase;
253
- $[40] = shouldStart;
254
- $[41] = typingSpeed;
255
- $[42] = wordsToAnimate;
256
- $[43] = t17;
257
- $[44] = t18;
264
+ $[33] = currentCharIndex;
265
+ $[34] = currentWordIndex;
266
+ $[35] = delay;
267
+ $[36] = deletingSpeed;
268
+ $[37] = displayedText;
269
+ $[38] = hasMultipleWords;
270
+ $[39] = loop;
271
+ $[40] = pauseDelay;
272
+ $[41] = phase;
273
+ $[42] = shouldReduceMotion;
274
+ $[43] = shouldStart;
275
+ $[44] = typingSpeed;
276
+ $[45] = wordsToAnimate;
277
+ $[46] = t17;
278
+ $[47] = t18;
258
279
  } else {
259
- t17 = $[43];
260
- t18 = $[44];
280
+ t17 = $[46];
281
+ t18 = $[47];
261
282
  }
262
283
  useEffect(t17, t18);
263
284
  let t19;
264
- if ($[45] !== currentWordIndex || $[46] !== wordsToAnimate) {
285
+ if ($[48] !== currentWordIndex || $[49] !== wordsToAnimate) {
265
286
  t19 = Array.from(wordsToAnimate[currentWordIndex] || "");
266
- $[45] = currentWordIndex;
267
- $[46] = wordsToAnimate;
268
- $[47] = t19;
287
+ $[48] = currentWordIndex;
288
+ $[49] = wordsToAnimate;
289
+ $[50] = t19;
269
290
  } else {
270
- t19 = $[47];
291
+ t19 = $[50];
271
292
  }
272
293
  const currentWordGraphemes = t19;
273
294
  const isComplete = !loop && currentWordIndex === wordsToAnimate.length - 1 && currentCharIndex >= currentWordGraphemes.length && phase !== "deleting";
274
- const shouldShowCursor = showCursor && !isComplete && (hasMultipleWords || loop || currentCharIndex < currentWordGraphemes.length);
295
+ const shouldShowCursor = showCursor && !shouldReduceMotion && !isComplete && (hasMultipleWords || loop || currentCharIndex < currentWordGraphemes.length);
275
296
  let t20;
276
- if ($[48] !== cursorStyle) {
297
+ if ($[51] !== cursorStyle) {
277
298
  t20 = () => {
278
299
  switch (cursorStyle) {
279
300
  case "block": {
@@ -288,53 +309,54 @@ export function TypingAnimation(t0) {
288
309
  }
289
310
  }
290
311
  };
291
- $[48] = cursorStyle;
292
- $[49] = t20;
312
+ $[51] = cursorStyle;
313
+ $[52] = t20;
293
314
  } else {
294
- t20 = $[49];
315
+ t20 = $[52];
295
316
  }
296
317
  const getCursorChar = t20;
297
318
  const t21 = Component === "h1" && "text-3xl font-bold leading-tight md:text-4xl";
298
319
  const t22 = Component === "span" && "inline-block";
299
320
  let t23;
300
- if ($[50] !== className || $[51] !== t21 || $[52] !== t22) {
321
+ if ($[53] !== className || $[54] !== t21 || $[55] !== t22) {
301
322
  t23 = cn("tracking-[-0.02em]", t21, t22, className);
302
- $[50] = className;
303
- $[51] = t21;
304
- $[52] = t22;
305
- $[53] = t23;
323
+ $[53] = className;
324
+ $[54] = t21;
325
+ $[55] = t22;
326
+ $[56] = t23;
306
327
  } else {
307
- t23 = $[53];
328
+ t23 = $[56];
308
329
  }
309
330
  let t24;
310
- if ($[54] !== blinkCursor || $[55] !== getCursorChar || $[56] !== shouldShowCursor) {
331
+ if ($[57] !== blinkCursor || $[58] !== getCursorChar || $[59] !== shouldShowCursor) {
311
332
  t24 = shouldShowCursor && /* @__PURE__ */ _jsx("span", {
312
333
  className: cn("inline-block", blinkCursor && "animate-blink-cursor"),
313
334
  children: getCursorChar()
314
335
  });
315
- $[54] = blinkCursor;
316
- $[55] = getCursorChar;
317
- $[56] = shouldShowCursor;
318
- $[57] = t24;
336
+ $[57] = blinkCursor;
337
+ $[58] = getCursorChar;
338
+ $[59] = shouldShowCursor;
339
+ $[60] = t24;
319
340
  } else {
320
- t24 = $[57];
341
+ t24 = $[60];
321
342
  }
322
343
  let t25;
323
- if ($[58] !== MotionComponent || $[59] !== displayedText || $[60] !== props || $[61] !== t23 || $[62] !== t24) {
344
+ if ($[61] !== MotionComponent || $[62] !== displayedText || $[63] !== props || $[64] !== t23 || $[65] !== t24) {
324
345
  t25 = /* @__PURE__ */ _jsxs(MotionComponent, {
325
346
  ref: elementRef,
347
+ "data-slot": "typing-animation",
326
348
  className: t23,
327
349
  ...props,
328
350
  children: [displayedText, t24]
329
351
  });
330
- $[58] = MotionComponent;
331
- $[59] = displayedText;
332
- $[60] = props;
333
- $[61] = t23;
334
- $[62] = t24;
335
- $[63] = t25;
352
+ $[61] = MotionComponent;
353
+ $[62] = displayedText;
354
+ $[63] = props;
355
+ $[64] = t23;
356
+ $[65] = t24;
357
+ $[66] = t25;
336
358
  } else {
337
- t25 = $[63];
359
+ t25 = $[66];
338
360
  }
339
361
  return t25;
340
362
  }
@@ -0,0 +1,2 @@
1
+ /** Shares the operating-system preference across CSS-adjacent and JavaScript animations. */
2
+ export declare const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
@@ -0,0 +1,2 @@
1
+ /** Shares the operating-system preference across CSS-adjacent and JavaScript animations. */
2
+ export const REDUCED_MOTION_QUERY = "(prefers-reduced-motion: reduce)";
@@ -0,0 +1,2 @@
1
+ /** Returns a live preference for animations that cannot be controlled with CSS alone. */
2
+ export declare function usePrefersReducedMotion(): boolean;
@@ -0,0 +1,27 @@
1
+ "use client";
2
+ /** Reads motion preferences without changing the initial server/hydration markup. */
3
+ import { useSyncExternalStore } from "react";
4
+ import { REDUCED_MOTION_QUERY } from "../constants/motion.js";
5
+ /** Subscribes to preference changes, including browsers exposing the legacy media API. */
6
+ function subscribe(onChange) {
7
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return () => {};
8
+ const query = window.matchMedia(REDUCED_MOTION_QUERY);
9
+ if (typeof query.addEventListener === "function") {
10
+ query.addEventListener("change", onChange);
11
+ return () => query.removeEventListener("change", onChange);
12
+ }
13
+ query.addListener?.(onChange);
14
+ return () => query.removeListener?.(onChange);
15
+ }
16
+ /** Resolves the current browser setting while tolerating non-browser test environments. */
17
+ function getSnapshot() {
18
+ return typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia(REDUCED_MOTION_QUERY).matches;
19
+ }
20
+ /** Keeps the initial client tree consistent with the server-rendered tree. */
21
+ function getServerSnapshot() {
22
+ return false;
23
+ }
24
+ /** Returns a live preference for animations that cannot be controlled with CSS alone. */
25
+ export function usePrefersReducedMotion() {
26
+ return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
27
+ }
@@ -1,2 +1,2 @@
1
1
  /** Shares class composition and Tailwind conflict resolution across consumers. */
2
- export { cn } from "cnfast";
2
+ export { cn } from "cn";
package/dist/lib/utils.js CHANGED
@@ -1,2 +1,2 @@
1
1
  /** Shares class composition and Tailwind conflict resolution across consumers. */
2
- export { cn } from "cnfast";
2
+ export { cn } from "cn";