beez-ui 3.0.1 → 4.0.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 (56) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/README.md +45 -47
  3. package/dist/components/account-menu.js +1 -1
  4. package/dist/components/alert.js +3 -7
  5. package/dist/components/animated-collapse.js +51 -38
  6. package/dist/components/animated-list-item.js +33 -34
  7. package/dist/components/animated-theme-toggler.d.ts +5 -1
  8. package/dist/components/animated-theme-toggler.js +75 -120
  9. package/dist/components/badge.js +7 -11
  10. package/dist/components/card.js +13 -16
  11. package/dist/components/dialog-surface.js +8 -21
  12. package/dist/components/filter-query-bar.js +7 -11
  13. package/dist/components/input-group.js +5 -9
  14. package/dist/components/input.js +8 -12
  15. package/dist/components/label.js +4 -8
  16. package/dist/components/link.d.ts +1 -0
  17. package/dist/components/link.js +2 -16
  18. package/dist/components/presence-swap.d.ts +1 -1
  19. package/dist/components/presence-swap.js +44 -32
  20. package/dist/components/primitives/avatar.js +6 -9
  21. package/dist/components/primitives/dropdown-menu.d.ts +2 -2
  22. package/dist/components/primitives/dropdown-menu.js +8 -5
  23. package/dist/components/primitives/select.d.ts +2 -1
  24. package/dist/components/primitives/select.js +104 -83
  25. package/dist/components/reaction-button.d.ts +5 -6
  26. package/dist/components/reaction-button.js +139 -75
  27. package/dist/components/rich-link-editor.js +1 -1
  28. package/dist/components/separator.js +5 -9
  29. package/dist/components/sheet.js +8 -11
  30. package/dist/components/sidebar.d.ts +6 -6
  31. package/dist/components/sidebar.js +221 -184
  32. package/dist/components/svgs/whatsappIcon.js +10 -14
  33. package/dist/components/table.js +4 -8
  34. package/dist/components/textarea.js +7 -11
  35. package/dist/components/themed-toaster.js +28 -62
  36. package/dist/constants/dropdown-menu.d.ts +6 -1
  37. package/dist/constants/dropdown-menu.js +33 -1
  38. package/dist/constants/popover.js +2 -8
  39. package/dist/constants/select.d.ts +3 -1
  40. package/dist/constants/select.js +30 -1
  41. package/dist/motion/arc-tokens.d.ts +6 -0
  42. package/dist/motion/arc-tokens.js +6 -0
  43. package/dist/motion/glide-indicator.d.ts +6 -21
  44. package/dist/motion/glide-indicator.js +8 -17
  45. package/dist/motion/motion-slot.d.ts +6 -3
  46. package/dist/motion/motion-slot.js +100 -411
  47. package/dist/motion/presence.d.ts +8 -0
  48. package/dist/motion/presence.js +11 -1
  49. package/dist/motion/surface-keyframes.d.ts +2 -2
  50. package/dist/motion/surface-keyframes.js +40 -141
  51. package/dist/motion/tokens.d.ts +10 -114
  52. package/dist/motion/tokens.js +11 -116
  53. package/dist/styles.css +1 -1
  54. package/package.json +1 -1
  55. package/dist/motion/shared-layout-bg.d.ts +0 -16
  56. package/dist/motion/shared-layout-bg.js +0 -181
@@ -1,125 +1,189 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
+ /**
4
+ * Toggle for likes and similar reactions: the icon gets Arc's kick (https://uiarc.dev, MIT License, see
5
+ * THIRD_PARTY_NOTICES.md) when the viewer reacts and the counter rolls in the direction of the change. The (optimistic) reaction state is owned by the caller.
6
+ */
7
+ import { useEffect, useRef } from "react";
3
8
  import { HeartIcon } from "lucide-react";
4
- import { motion } from "motion/react";
9
+ import { animate, motion, useMotionValue } from "motion/react";
5
10
  import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
6
11
  import { cn } from "../lib/utils.js";
7
- import { MOTION_EASE, MOTION_TIMING } from "../motion/tokens.js";
8
12
  import { AnimatedCount } from "./animated-count.js";
9
13
  import { ControlButton } from "./control-button.js";
10
14
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
- /** Peak scale the icon reaches while popping into the active state. */
12
- const REACTION_ICON_POP_SCALE = 1.28;
13
- const REACTION_ICON_VARIANTS = {
14
- idle: { scale: 1 },
15
- active: {
16
- scale: [
17
- 1,
18
- REACTION_ICON_POP_SCALE,
19
- 1
20
- ],
21
- transition: {
22
- duration: MOTION_TIMING.pop,
23
- ease: MOTION_EASE
24
- }
25
- }
15
+ /**
16
+ * Arc's kick: an impulse rather than a keyframe. The icon starts at rest with velocity, overshoots and settles, and a
17
+ * quick second reaction adds to the running motion instead of restarting it.
18
+ */
19
+ const REACTION_KICK = {
20
+ type: "spring",
21
+ stiffness: 420,
22
+ damping: 17
26
23
  };
24
+ /** Scale velocity, per second, the kick gives the icon. */
25
+ const REACTION_KICK_SCALE_VELOCITY = 11;
26
+ /** Rotation velocity, in degrees per second, the kick gives the icon. */
27
+ const REACTION_KICK_ROTATE_VELOCITY = -420;
27
28
  /**
28
- * Renders an outline toggle button exposing its state with `aria-pressed`. The icon starts at
29
- * rest (`initial={false}`), so server-rendered and already-active reactions never pop on load;
30
- * only a change to active does, and not at all with reduced motion.
29
+ * Renders an outline toggle button exposing its state with `aria-pressed`. Server-rendered and already-active
30
+ * reactions never kick on load; only a change to active does, and not at all with reduced motion.
31
31
  * @param props - Accessible name, state, count, click handler and optional icon.
32
32
  * @returns The reaction button.
33
33
  */
34
34
  export function ReactionButton(t0) {
35
- const $ = _c(22);
35
+ const $ = _c(32);
36
36
  const { ariaLabel, isActive, count, onClick, isDisabled: t1, icon: t2, formatCount, activeColor, className } = t0;
37
37
  const isDisabled = t1 === undefined ? false : t1;
38
38
  const Icon = t2 === undefined ? HeartIcon : t2;
39
39
  const shouldReduceMotion = usePrefersReducedMotion();
40
+ const scale = useMotionValue(1);
41
+ const rotate = useMotionValue(0);
42
+ const wasActive = useRef(isActive);
40
43
  let t3;
41
- if ($[0] !== activeColor) {
42
- t3 = activeColor ? { "--beez-reaction-active-color": activeColor } : undefined;
43
- $[0] = activeColor;
44
- $[1] = t3;
44
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
45
+ t3 = [];
46
+ $[0] = t3;
45
47
  } else {
46
- t3 = $[1];
48
+ t3 = $[0];
47
49
  }
48
- const activeColorStyle = t3;
49
- const t4 = isActive || undefined;
50
+ const kickControls = useRef(t3);
51
+ let t4;
50
52
  let t5;
51
- if ($[2] !== className) {
52
- t5 = cn("group/reaction", className);
53
- $[2] = className;
54
- $[3] = t5;
53
+ if ($[1] !== isActive || $[2] !== rotate || $[3] !== scale || $[4] !== shouldReduceMotion) {
54
+ t4 = () => {
55
+ const becameActive = isActive && !wasActive.current;
56
+ wasActive.current = isActive;
57
+ if (shouldReduceMotion) {
58
+ kickControls.current.forEach(_temp);
59
+ kickControls.current = [];
60
+ scale.jump(1);
61
+ rotate.jump(0);
62
+ return;
63
+ }
64
+ if (!becameActive) {
65
+ return;
66
+ }
67
+ kickControls.current = [animate(scale, 1, {
68
+ ...REACTION_KICK,
69
+ velocity: scale.getVelocity() + REACTION_KICK_SCALE_VELOCITY
70
+ }), animate(rotate, 0, {
71
+ ...REACTION_KICK,
72
+ velocity: rotate.getVelocity() + REACTION_KICK_ROTATE_VELOCITY
73
+ })];
74
+ };
75
+ t5 = [
76
+ isActive,
77
+ rotate,
78
+ scale,
79
+ shouldReduceMotion
80
+ ];
81
+ $[1] = isActive;
82
+ $[2] = rotate;
83
+ $[3] = scale;
84
+ $[4] = shouldReduceMotion;
85
+ $[5] = t4;
86
+ $[6] = t5;
55
87
  } else {
56
- t5 = $[3];
88
+ t4 = $[5];
89
+ t5 = $[6];
57
90
  }
58
- const t6 = isActive && !shouldReduceMotion ? "active" : "idle";
59
- let t7;
60
- if ($[4] !== Icon) {
61
- t7 = /* @__PURE__ */ _jsx(Icon, { className: "size-4 transition-[fill,color] group-data-active/reaction:fill-current group-data-active/reaction:text-[var(--beez-reaction-active-color,var(--destructive))]" });
62
- $[4] = Icon;
63
- $[5] = t7;
91
+ useEffect(t4, t5);
92
+ let t6;
93
+ if ($[7] !== activeColor) {
94
+ t6 = activeColor ? { "--beez-reaction-active-color": activeColor } : undefined;
95
+ $[7] = activeColor;
96
+ $[8] = t6;
64
97
  } else {
65
- t7 = $[5];
98
+ t6 = $[8];
66
99
  }
100
+ const activeColorStyle = t6;
101
+ const t7 = isActive || undefined;
67
102
  let t8;
68
- if ($[6] !== t6 || $[7] !== t7) {
69
- t8 = /* @__PURE__ */ _jsx(motion.span, {
70
- animate: t6,
103
+ if ($[9] !== className) {
104
+ t8 = cn("group/reaction", className);
105
+ $[9] = className;
106
+ $[10] = t8;
107
+ } else {
108
+ t8 = $[10];
109
+ }
110
+ let t9;
111
+ if ($[11] !== rotate || $[12] !== scale) {
112
+ t9 = {
113
+ scale,
114
+ rotate
115
+ };
116
+ $[11] = rotate;
117
+ $[12] = scale;
118
+ $[13] = t9;
119
+ } else {
120
+ t9 = $[13];
121
+ }
122
+ let t10;
123
+ if ($[14] !== Icon) {
124
+ t10 = /* @__PURE__ */ _jsx(Icon, { className: "size-4 transition-[fill,color] group-data-active/reaction:fill-current group-data-active/reaction:text-[var(--beez-reaction-active-color,var(--destructive))]" });
125
+ $[14] = Icon;
126
+ $[15] = t10;
127
+ } else {
128
+ t10 = $[15];
129
+ }
130
+ let t11;
131
+ if ($[16] !== t10 || $[17] !== t9) {
132
+ t11 = /* @__PURE__ */ _jsx(motion.span, {
71
133
  "aria-hidden": true,
72
134
  className: "inline-flex origin-center items-center justify-center",
73
- initial: false,
74
- variants: REACTION_ICON_VARIANTS,
75
- children: t7
135
+ style: t9,
136
+ children: t10
76
137
  });
77
- $[6] = t6;
78
- $[7] = t7;
79
- $[8] = t8;
138
+ $[16] = t10;
139
+ $[17] = t9;
140
+ $[18] = t11;
80
141
  } else {
81
- t8 = $[8];
142
+ t11 = $[18];
82
143
  }
83
- let t9;
84
- if ($[9] !== count || $[10] !== formatCount) {
85
- t9 = /* @__PURE__ */ _jsx(AnimatedCount, {
144
+ let t12;
145
+ if ($[19] !== count || $[20] !== formatCount) {
146
+ t12 = /* @__PURE__ */ _jsx(AnimatedCount, {
86
147
  className: "min-w-[1ch]",
87
148
  value: count,
88
149
  format: formatCount
89
150
  });
90
- $[9] = count;
91
- $[10] = formatCount;
92
- $[11] = t9;
151
+ $[19] = count;
152
+ $[20] = formatCount;
153
+ $[21] = t12;
93
154
  } else {
94
- t9 = $[11];
155
+ t12 = $[21];
95
156
  }
96
- let t10;
97
- if ($[12] !== activeColorStyle || $[13] !== ariaLabel || $[14] !== isActive || $[15] !== isDisabled || $[16] !== onClick || $[17] !== t4 || $[18] !== t5 || $[19] !== t8 || $[20] !== t9) {
98
- t10 = /* @__PURE__ */ _jsxs(ControlButton, {
157
+ let t13;
158
+ if ($[22] !== activeColorStyle || $[23] !== ariaLabel || $[24] !== isActive || $[25] !== isDisabled || $[26] !== onClick || $[27] !== t11 || $[28] !== t12 || $[29] !== t7 || $[30] !== t8) {
159
+ t13 = /* @__PURE__ */ _jsxs(ControlButton, {
99
160
  "data-slot": "reaction-button",
100
- "data-active": t4,
161
+ "data-active": t7,
101
162
  "aria-label": ariaLabel,
102
163
  "aria-pressed": isActive,
103
- className: t5,
164
+ className: t8,
104
165
  disabled: isDisabled,
105
166
  onClick,
106
167
  style: activeColorStyle,
107
168
  type: "button",
108
169
  variant: "outline",
109
- children: [t8, t9]
170
+ children: [t11, t12]
110
171
  });
111
- $[12] = activeColorStyle;
112
- $[13] = ariaLabel;
113
- $[14] = isActive;
114
- $[15] = isDisabled;
115
- $[16] = onClick;
116
- $[17] = t4;
117
- $[18] = t5;
118
- $[19] = t8;
119
- $[20] = t9;
120
- $[21] = t10;
172
+ $[22] = activeColorStyle;
173
+ $[23] = ariaLabel;
174
+ $[24] = isActive;
175
+ $[25] = isDisabled;
176
+ $[26] = onClick;
177
+ $[27] = t11;
178
+ $[28] = t12;
179
+ $[29] = t7;
180
+ $[30] = t8;
181
+ $[31] = t13;
121
182
  } else {
122
- t10 = $[21];
183
+ t13 = $[31];
123
184
  }
124
- return t10;
185
+ return t13;
186
+ }
187
+ function _temp(controls) {
188
+ return controls.stop();
125
189
  }
@@ -24,7 +24,7 @@ const RICH_LINK_EDITOR_CLASS_NAMES = {
24
24
  editorInvalid: "rounded-[0.35rem] shadow-[inset_0_-2px_0_var(--destructive)] outline-0",
25
25
  editorLink: "cursor-pointer rounded-[0.2rem] font-medium text-primary underline decoration-[0.08em] underline-offset-[0.18em] transition-colors hover:text-[color-mix(in_oklab,var(--primary)_72%,var(--foreground))] focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring",
26
26
  popover: "gap-3",
27
- editForm: "grid gap-3 animate-in fade-in slide-in-from-bottom-1 duration-200",
27
+ editForm: "grid gap-3 animate-in fade-in slide-in-from-bottom-1 duration-(--duration-standard) ease-(--ease-enter)",
28
28
  actions: "flex flex-wrap items-center gap-2",
29
29
  label: "grid gap-[0.35rem] text-[0.85rem] font-medium text-muted-foreground",
30
30
  input: "min-h-8 rounded-lg border border-border/80 bg-background px-[0.65rem] font-normal text-foreground outline-0 transition-[border-color,box-shadow] [font:inherit] focus-visible:border-ring focus-visible:shadow-[0_0_0_3px_color-mix(in_oklab,var(--ring)_35%,transparent)] aria-invalid:border-destructive aria-invalid:focus-visible:shadow-[0_0_0_3px_color-mix(in_oklab,var(--destructive)_25%,transparent)] max-md:text-base"
@@ -1,7 +1,6 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  import { Separator as SeparatorPrimitive } from "@base-ui/react/separator";
4
- import { MotionSlot } from "../motion/motion-slot.js";
5
4
  import { cn } from "../lib/utils.js";
6
5
  import { jsx as _jsx } from "react/jsx-runtime";
7
6
  function Separator(t0) {
@@ -31,14 +30,11 @@ function Separator(t0) {
31
30
  }
32
31
  let t3;
33
32
  if ($[6] !== orientation || $[7] !== props || $[8] !== t2) {
34
- t3 = /* @__PURE__ */ _jsx(MotionSlot, {
35
- kind: "fade",
36
- children: /* @__PURE__ */ _jsx(SeparatorPrimitive, {
37
- "data-slot": "separator",
38
- orientation,
39
- className: t2,
40
- ...props
41
- })
33
+ t3 = /* @__PURE__ */ _jsx(SeparatorPrimitive, {
34
+ "data-slot": "separator",
35
+ orientation,
36
+ className: t2,
37
+ ...props
42
38
  });
43
39
  $[6] = orientation;
44
40
  $[7] = props;
@@ -216,17 +216,14 @@ function SheetContent(t0) {
216
216
  t7 = showCloseButton && /* @__PURE__ */ _jsx(SheetPrimitive.Close, {
217
217
  "data-slot": "sheet-close",
218
218
  asChild: true,
219
- children: /* @__PURE__ */ _jsx(MotionSlot, {
220
- kind: "delayed-pop",
221
- children: /* @__PURE__ */ _jsxs(ControlButton, {
222
- variant: "ghost",
223
- className: "absolute top-4 right-4",
224
- size: "icon-sm",
225
- children: [/* @__PURE__ */ _jsx(XIcon, {}), /* @__PURE__ */ _jsx("span", {
226
- className: "sr-only",
227
- children: "Close"
228
- })]
229
- })
219
+ children: /* @__PURE__ */ _jsxs(ControlButton, {
220
+ variant: "ghost",
221
+ className: "absolute top-4 right-4",
222
+ size: "icon-sm",
223
+ children: [/* @__PURE__ */ _jsx(XIcon, {}), /* @__PURE__ */ _jsx("span", {
224
+ className: "sr-only",
225
+ children: "Close"
226
+ })]
230
227
  })
231
228
  });
232
229
  $[11] = showCloseButton;
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Animated application sidebar adapted from beui.dev/components/motion/animated-sidebar: the rail
3
- * morphs its width with a spring, labels fade out of the icon rail, a shared pill follows the
4
- * hovered and active items, submenus unfold with a stagger, and small screens get a focus-trapped
5
- * sheet. Links route through the `BeezUIProvider` adapter and the open state keeps the
2
+ * Application sidebar on the motion of Arc's sidebar rail: the rail springs its width without
3
+ * overshoot, labels fade and drift out of the icon rail, the active item's highlight glides between
4
+ * items, hovered items only change color, submenus open their height on the smooth spring, and
5
+ * small screens get a focus-trapped sheet that slides in from its edge. Links route through the `BeezUIProvider` adapter and the open state keeps the
6
6
  * `sidebar_state` cookie contract read by server entrypoints.
7
7
  */
8
8
  import * as React from "react";
@@ -140,7 +140,7 @@ declare function SidebarGroup({ className, ...props }: React.ComponentProps<"div
140
140
  /** Section heading that fades out of the icon rail and is hidden from assistive technology there. */
141
141
  declare function SidebarGroupLabel({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
142
142
  declare function SidebarGroupContent({ className, ...props }: React.ComponentProps<"div">): React.JSX.Element;
143
- /** Menu list whose items share a hover pill that glides between them. */
143
+ /** Menu list; hovered items answer in color, as in Arc's sidebar rail. */
144
144
  declare function SidebarMenu({ className, ...props }: React.ComponentProps<"ul">): React.JSX.Element;
145
145
  declare function SidebarMenuItem({ className, ...props }: HTMLMotionProps<"li">): React.JSX.Element;
146
146
  export type SidebarMenuSubProps = Omit<HTMLMotionProps<"ul">, "children"> & {
@@ -149,7 +149,7 @@ export type SidebarMenuSubProps = Omit<HTMLMotionProps<"ul">, "children"> & {
149
149
  children?: React.ReactNode;
150
150
  };
151
151
  /**
152
- * Nested list that unfolds with a clip and staggered items.
152
+ * Nested list that opens its height on Arc's smooth spring.
153
153
  * @param props - Open state and motion-enabled list attributes.
154
154
  * @returns The submenu while open and the sidebar is expanded.
155
155
  */