beez-ui 2.7.1 → 3.0.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 (110) hide show
  1. package/CHANGELOG.md +78 -0
  2. package/README.md +43 -13
  3. package/THIRD_PARTY_NOTICES.md +1 -1
  4. package/dist/components/account-menu.d.ts +4 -3
  5. package/dist/components/account-menu.js +63 -54
  6. package/dist/components/alert.d.ts +15 -15
  7. package/dist/components/alert.js +289 -270
  8. package/dist/components/animated-theme-toggler.js +1 -1
  9. package/dist/components/avatar.d.ts +56 -31
  10. package/dist/components/avatar.js +394 -277
  11. package/dist/components/badge.d.ts +8 -28
  12. package/dist/components/badge.js +55 -108
  13. package/dist/components/calendar.d.ts +36 -26
  14. package/dist/components/calendar.js +132 -1227
  15. package/dist/components/card.d.ts +36 -25
  16. package/dist/components/card.js +895 -72
  17. package/dist/components/carousel.d.ts +63 -47
  18. package/dist/components/carousel.js +496 -777
  19. package/dist/components/data-table.d.ts +5 -4
  20. package/dist/components/data-table.js +7 -6
  21. package/dist/components/dialog-surface.d.ts +23 -1
  22. package/dist/components/dialog-surface.js +99 -3
  23. package/dist/components/dialog.d.ts +80 -45
  24. package/dist/components/dialog.js +258 -503
  25. package/dist/components/dropdown-menu.d.ts +56 -73
  26. package/dist/components/dropdown-menu.js +79 -714
  27. package/dist/components/field.d.ts +3 -1
  28. package/dist/components/field.js +49 -39
  29. package/dist/components/filter-presets-bar.js +2 -2
  30. package/dist/components/filter-query-bar.js +1 -1
  31. package/dist/components/hover-card.d.ts +42 -41
  32. package/dist/components/hover-card.js +57 -483
  33. package/dist/components/pagination.d.ts +53 -31
  34. package/dist/components/pagination.js +176 -412
  35. package/dist/components/popover.d.ts +11 -23
  36. package/dist/components/popover.js +19 -304
  37. package/dist/components/{alert-dialog.d.ts → primitives/alert-dialog.d.ts} +17 -5
  38. package/dist/components/{alert-dialog.js → primitives/alert-dialog.js} +102 -54
  39. package/dist/components/primitives/avatar.d.ts +46 -0
  40. package/dist/components/primitives/avatar.js +268 -0
  41. package/dist/components/primitives/calendar.d.ts +37 -0
  42. package/dist/components/primitives/calendar.js +1250 -0
  43. package/dist/components/primitives/carousel.d.ts +106 -0
  44. package/dist/components/primitives/carousel.js +928 -0
  45. package/dist/components/primitives/dialog.d.ts +62 -0
  46. package/dist/components/primitives/dialog.js +490 -0
  47. package/dist/components/primitives/dropdown-menu-items.d.ts +59 -0
  48. package/dist/components/primitives/dropdown-menu-items.js +265 -0
  49. package/dist/components/primitives/dropdown-menu.d.ts +64 -0
  50. package/dist/components/primitives/dropdown-menu.js +557 -0
  51. package/dist/components/primitives/hover-card.d.ts +50 -0
  52. package/dist/components/primitives/hover-card.js +507 -0
  53. package/dist/components/primitives/pagination.d.ts +65 -0
  54. package/dist/components/primitives/pagination.js +373 -0
  55. package/dist/components/primitives/popover.d.ts +22 -0
  56. package/dist/components/primitives/popover.js +213 -0
  57. package/dist/components/primitives/select.d.ts +36 -0
  58. package/dist/components/primitives/select.js +407 -0
  59. package/dist/components/primitives/tooltip.d.ts +30 -0
  60. package/dist/components/primitives/tooltip.js +277 -0
  61. package/dist/components/radio-group.d.ts +30 -17
  62. package/dist/components/radio-group.js +266 -315
  63. package/dist/components/rich-link-editor.js +1 -1
  64. package/dist/components/select.d.ts +51 -42
  65. package/dist/components/select.js +163 -495
  66. package/dist/components/skeleton.d.ts +16 -15
  67. package/dist/components/skeleton.js +99 -205
  68. package/dist/components/split-button.js +1 -1
  69. package/dist/components/switch.d.ts +3 -6
  70. package/dist/components/switch.js +163 -170
  71. package/dist/components/tabs.d.ts +3 -11
  72. package/dist/components/tabs.js +61 -75
  73. package/dist/components/themed-toaster.d.ts +1 -1
  74. package/dist/components/themed-toaster.js +1 -1
  75. package/dist/components/toaster.d.ts +1 -1
  76. package/dist/components/toaster.js +1 -1
  77. package/dist/components/tooltip.d.ts +36 -31
  78. package/dist/components/tooltip.js +44 -284
  79. package/dist/constants/alert.d.ts +5 -1
  80. package/dist/constants/alert.js +5 -1
  81. package/dist/constants/avatar.d.ts +29 -1
  82. package/dist/constants/avatar.js +25 -0
  83. package/dist/constants/calendar.d.ts +12 -0
  84. package/dist/constants/calendar.js +12 -0
  85. package/dist/constants/card.d.ts +23 -0
  86. package/dist/constants/card.js +20 -0
  87. package/dist/constants/carousel.d.ts +31 -13
  88. package/dist/constants/carousel.js +32 -11
  89. package/dist/constants/dialog.d.ts +6 -1
  90. package/dist/constants/dialog.js +5 -1
  91. package/dist/constants/dropdown-menu.d.ts +2 -2
  92. package/dist/constants/dropdown-menu.js +2 -2
  93. package/dist/constants/pagination.d.ts +13 -2
  94. package/dist/constants/pagination.js +13 -2
  95. package/dist/constants/select.d.ts +4 -2
  96. package/dist/constants/select.js +4 -2
  97. package/dist/constants/switch.d.ts +5 -16
  98. package/dist/constants/switch.js +6 -14
  99. package/dist/hooks/use-today.d.ts +7 -0
  100. package/dist/hooks/use-today.js +50 -0
  101. package/dist/hooks.d.ts +1 -0
  102. package/dist/hooks.js +1 -0
  103. package/dist/index.d.ts +0 -1
  104. package/dist/index.js +0 -1
  105. package/dist/motion/glide-indicator.d.ts +1 -1
  106. package/dist/motion/glide-indicator.js +1 -1
  107. package/dist/motion/presence.d.ts +0 -1
  108. package/dist/motion/presence.js +0 -1
  109. package/dist/styles.css +1 -1
  110. package/package.json +1 -6
@@ -1,11 +1,10 @@
1
1
  "use client";
2
2
  import { c as _c } from "react/compiler-runtime";
3
3
  /**
4
- * Arc's RadioGroup (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md) on Radix's radio group: the mark dips
5
- * on press, previews a faint dot while held, and the new dot springs in while the old one shrinks away. Items with a
6
- * `label` render Arc's option rows, and one highlight travels to the chosen row on the morph spring, so a change reads
7
- * as a single physical move; arrow keys take the same path. Bare items keep the plain mark for compositions that place
8
- * their own label.
4
+ * Arc's RadioGroup (https://uiarc.dev, MIT License, see THIRD_PARTY_NOTICES.md) on Radix's radio group: a fieldset
5
+ * whose legend names the choice and whose options render as Arc's rows. The mark dips on press, previews a faint dot
6
+ * while held, and the new dot springs in while the old one shrinks away; one highlight travels to the chosen row on
7
+ * the morph spring, so a change reads as a single physical move. Arrow keys take the same path.
9
8
  */
10
9
  import { createContext, useContext, useEffect, useId, useLayoutEffect, useRef, useState } from "react";
11
10
  import { RadioGroup as RadioGroupPrimitive } from "radix-ui";
@@ -14,12 +13,12 @@ import { RADIO_GROUP_DOT_HIDDEN_SCALE, RADIO_GROUP_OPTION_ID_SUFFIX, RADIO_GROUP
14
13
  import { usePrefersReducedMotion } from "../hooks/use-prefers-reduced-motion.js";
15
14
  import { cn } from "../lib/utils.js";
16
15
  import { ARC_DURATION, ARC_SPRING_MORPH, ARC_SPRING_SNAPPY } from "../motion/arc-tokens.js";
17
- import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
16
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
18
17
  /** Selector of the option row that holds the checked radio. */
19
18
  const CHECKED_OPTION_SELECTOR = "[data-slot=\"radio-group-option\"]:has([data-slot=\"radio-group-item\"][data-state=\"checked\"])";
20
19
  /** Selector of every option row, observed so the highlight follows rows that resize. */
21
20
  const OPTION_SELECTOR = "[data-slot=\"radio-group-option\"]";
22
- /** The value chosen in the enclosing group, read by each item to spring its dot in or out. */
21
+ /** The value chosen in the enclosing group, read by each option to spring its dot in or out. */
23
22
  const RadioGroupValueContext = createContext(undefined);
24
23
  /**
25
24
  * Sizes the highlight to the chosen row. A new choice glides on the morph spring; the first paint and resizes place it
@@ -61,381 +60,333 @@ function placeHighlight(highlight, row, placedAt, shouldGlide) {
61
60
  animate(highlight, target, { duration: 0 });
62
61
  }
63
62
  /**
64
- * Hosts the radios, controlled or uncontrolled like Radix's radio group, and moves the highlight of option rows.
65
- * @param radioGroupProps - Every Radix radio group prop, including `ref`.
66
- * @returns The radio group.
63
+ * Arc's mark recipe: the faint preview dot and the press dip answer the whole row.
67
64
  */
68
- function RadioGroup(t0) {
69
- const $ = _c(36);
70
- let asChild;
71
- let children;
72
- let className;
73
- let defaultValue;
74
- let onValueChange;
75
- let props;
76
- let ref;
77
- let value;
78
- if ($[0] !== t0) {
79
- ({className, children, value, defaultValue, onValueChange, ref, asChild, ...props} = t0);
80
- $[0] = t0;
81
- $[1] = asChild;
82
- $[2] = children;
83
- $[3] = className;
84
- $[4] = defaultValue;
85
- $[5] = onValueChange;
86
- $[6] = props;
87
- $[7] = ref;
88
- $[8] = value;
89
- } else {
90
- asChild = $[1];
91
- children = $[2];
92
- className = $[3];
93
- defaultValue = $[4];
94
- onValueChange = $[5];
95
- props = $[6];
96
- ref = $[7];
97
- value = $[8];
98
- }
65
+ const radioGroupItemClassName = "peer group/radio-group-item relative z-2 grid aspect-square size-[17px] shrink-0 cursor-pointer place-items-center rounded-full border border-border-strong bg-transparent p-0 [-webkit-tap-highlight-color:transparent] [transition:border-color_var(--duration-fast)_var(--ease-standard),background-color_var(--duration-fast)_var(--ease-standard),scale_var(--duration-spring)_var(--ease-spring)] before:size-[7px] before:rounded-full before:bg-foreground before:opacity-0 before:transition-opacity before:duration-(--duration-instant) before:ease-(--ease-standard) before:[grid-area:1/1] before:content-[''] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-(--control-on) data-[state=checked]:bg-(--control-on) aria-invalid:data-[state=unchecked]:border-danger hover-fine:data-[state=unchecked]:not-disabled:border-text-muted active:not-disabled:scale-[.88] active:not-disabled:[transition:border-color_var(--duration-fast)_var(--ease-standard),background-color_var(--duration-fast)_var(--ease-standard),scale_100ms_var(--ease-standard)] active:not-disabled:data-[state=unchecked]:before:opacity-[.22] group-active/radio-group-option:not-disabled:scale-[.88] group-active/radio-group-option:not-disabled:data-[state=unchecked]:before:opacity-[.22] motion-reduce:scale-100 motion-reduce:transition-none motion-reduce:before:transition-none";
66
+ /** Arc's option row: answers a press with color only, while the mark is what moves. */
67
+ const optionClassName = "group/radio-group-option relative flex cursor-pointer items-center gap-(--space-3) rounded-(--radius-control) border border-border p-(--space-3) [-webkit-tap-highlight-color:transparent] transition-[background-color,border-color] duration-(--duration-fast) ease-(--ease-standard) hover-fine:bg-surface-muted active:bg-surface-muted has-disabled:cursor-not-allowed has-disabled:opacity-50 [[data-slot=radio-group]:not([data-ready])_&]:has-data-[state=checked]:border-(--control-on) [[data-slot=radio-group]:not([data-ready])_&]:has-data-[state=checked]:bg-[color-mix(in_oklab,var(--control-on)_5%,transparent)] motion-reduce:transition-none";
68
+ /**
69
+ * One option row: the radio mark and its copy.
70
+ * @param option - The option to render.
71
+ * @returns The row, a label that activates its radio.
72
+ */
73
+ function RadioGroupOptionRow(t0) {
74
+ const $ = _c(26);
75
+ const { value, label, description, disabled } = t0;
76
+ const rowId = useId();
77
+ const labelId = `${rowId}-${RADIO_GROUP_OPTION_ID_SUFFIX.label}`;
78
+ const descriptionId = `${rowId}-${RADIO_GROUP_OPTION_ID_SUFFIX.description}`;
99
79
  const reduceMotion = usePrefersReducedMotion();
100
- const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
101
- const selectedValue = value ?? uncontrolledValue;
102
- const groupRef = useRef(null);
103
- const highlightRef = useRef(null);
104
- const shownValue = useRef(null);
105
- const placedAt = useRef("");
106
- let t1;
107
- if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
108
- t1 = () => groupRef.current?.querySelector(CHECKED_OPTION_SELECTOR) ?? null;
109
- $[9] = t1;
80
+ const isChecked = useContext(RadioGroupValueContext) === value;
81
+ const t1 = description ? descriptionId : undefined;
82
+ let t2;
83
+ if ($[0] !== isChecked) {
84
+ t2 = isChecked ? {
85
+ scale: 1,
86
+ opacity: 1
87
+ } : {
88
+ scale: RADIO_GROUP_DOT_HIDDEN_SCALE,
89
+ opacity: 0
90
+ };
91
+ $[0] = isChecked;
92
+ $[1] = t2;
110
93
  } else {
111
- t1 = $[9];
94
+ t2 = $[1];
112
95
  }
113
- const findCheckedRow = t1;
114
- let t2;
115
96
  let t3;
116
- if ($[10] !== reduceMotion || $[11] !== selectedValue) {
117
- t2 = () => {
118
- const hasChanged = shownValue.current !== null && shownValue.current !== selectedValue;
119
- placeHighlight(highlightRef.current, findCheckedRow(), placedAt, hasChanged && !reduceMotion);
120
- shownValue.current = selectedValue;
121
- if (highlightRef.current) {
122
- groupRef.current?.setAttribute(RADIO_GROUP_READY_ATTRIBUTE, "");
123
- }
97
+ if ($[2] !== isChecked || $[3] !== reduceMotion) {
98
+ t3 = reduceMotion ? { duration: 0 } : {
99
+ ...ARC_SPRING_SNAPPY,
100
+ opacity: { duration: isChecked ? ARC_DURATION.fast : ARC_DURATION.instant }
124
101
  };
125
- t3 = [selectedValue, reduceMotion];
126
- $[10] = reduceMotion;
127
- $[11] = selectedValue;
128
- $[12] = t2;
129
- $[13] = t3;
102
+ $[2] = isChecked;
103
+ $[3] = reduceMotion;
104
+ $[4] = t3;
130
105
  } else {
131
- t2 = $[12];
132
- t3 = $[13];
106
+ t3 = $[4];
133
107
  }
134
- useLayoutEffect(t2, t3);
135
108
  let t4;
136
- if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
137
- t4 = () => {
138
- const group = groupRef.current;
139
- if (!group || typeof ResizeObserver === "undefined") {
140
- return;
141
- }
142
- const observer = new ResizeObserver(() => placeHighlight(highlightRef.current, findCheckedRow(), placedAt, false));
143
- observer.observe(group);
144
- group.querySelectorAll(OPTION_SELECTOR).forEach((row) => observer.observe(row));
145
- return () => observer.disconnect();
146
- };
147
- $[14] = t4;
109
+ if ($[5] !== t2 || $[6] !== t3) {
110
+ t4 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Indicator, {
111
+ forceMount: true,
112
+ asChild: true,
113
+ children: /* @__PURE__ */ _jsx(motion.span, {
114
+ "data-slot": "radio-group-indicator",
115
+ className: "pointer-events-none block size-[7px] rounded-full bg-(--control-glyph) [grid-area:1/1]",
116
+ initial: false,
117
+ animate: t2,
118
+ transition: t3
119
+ })
120
+ });
121
+ $[5] = t2;
122
+ $[6] = t3;
123
+ $[7] = t4;
148
124
  } else {
149
- t4 = $[14];
125
+ t4 = $[7];
150
126
  }
151
- useEffect(t4);
152
127
  let t5;
153
- if ($[15] !== className) {
154
- t5 = cn("relative grid w-full gap-2", className);
155
- $[15] = className;
156
- $[16] = t5;
128
+ if ($[8] !== disabled || $[9] !== labelId || $[10] !== t1 || $[11] !== t4 || $[12] !== value) {
129
+ t5 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Item, {
130
+ "data-slot": "radio-group-item",
131
+ className: radioGroupItemClassName,
132
+ value,
133
+ disabled,
134
+ "aria-labelledby": labelId,
135
+ "aria-describedby": t1,
136
+ children: t4
137
+ });
138
+ $[8] = disabled;
139
+ $[9] = labelId;
140
+ $[10] = t1;
141
+ $[11] = t4;
142
+ $[12] = value;
143
+ $[13] = t5;
157
144
  } else {
158
- t5 = $[16];
145
+ t5 = $[13];
159
146
  }
160
147
  let t6;
161
- if ($[17] !== ref) {
162
- t6 = (node) => {
163
- groupRef.current = node;
164
- if (typeof ref === "function") {
165
- return ref(node);
166
- }
167
- if (ref) {
168
- ref.current = node;
169
- }
170
- };
171
- $[17] = ref;
172
- $[18] = t6;
148
+ if ($[14] !== label || $[15] !== labelId) {
149
+ t6 = /* @__PURE__ */ _jsx("span", {
150
+ id: labelId,
151
+ "data-slot": "radio-group-option-label",
152
+ className: "block text-sm font-medium text-text-secondary transition-colors duration-(--duration-standard) ease-(--ease-standard) group-has-data-[state=checked]/radio-group-option:text-foreground motion-reduce:transition-none",
153
+ children: label
154
+ });
155
+ $[14] = label;
156
+ $[15] = labelId;
157
+ $[16] = t6;
173
158
  } else {
174
- t6 = $[18];
159
+ t6 = $[16];
175
160
  }
176
161
  let t7;
177
- if ($[19] !== onValueChange || $[20] !== value) {
178
- t7 = (nextValue) => {
179
- if (value === undefined) {
180
- setUncontrolledValue(nextValue);
181
- }
182
- onValueChange?.(nextValue);
183
- };
184
- $[19] = onValueChange;
185
- $[20] = value;
186
- $[21] = t7;
162
+ if ($[17] !== description || $[18] !== descriptionId) {
163
+ t7 = description ? /* @__PURE__ */ _jsx("span", {
164
+ id: descriptionId,
165
+ "data-slot": "radio-group-option-description",
166
+ className: "mt-0.5 block text-xs text-text-muted",
167
+ children: description
168
+ }) : null;
169
+ $[17] = description;
170
+ $[18] = descriptionId;
171
+ $[19] = t7;
187
172
  } else {
188
- t7 = $[21];
173
+ t7 = $[19];
189
174
  }
190
175
  let t8;
191
- if ($[22] !== asChild || $[23] !== children) {
192
- t8 = asChild ? children : /* @__PURE__ */ _jsxs(_Fragment, { children: [/* @__PURE__ */ _jsx("span", {
193
- ref: highlightRef,
194
- "data-slot": "radio-group-highlight",
195
- "aria-hidden": "true",
196
- className: "pointer-events-none absolute top-0 left-0 z-1 box-border rounded-(--radius-control) border border-(--control-on) bg-[color-mix(in_oklab,var(--control-on)_5%,transparent)] opacity-0"
197
- }), children] });
198
- $[22] = asChild;
199
- $[23] = children;
200
- $[24] = t8;
176
+ if ($[20] !== t6 || $[21] !== t7) {
177
+ t8 = /* @__PURE__ */ _jsxs("span", {
178
+ className: "relative z-2 min-w-0",
179
+ children: [t6, t7]
180
+ });
181
+ $[20] = t6;
182
+ $[21] = t7;
183
+ $[22] = t8;
201
184
  } else {
202
- t8 = $[24];
185
+ t8 = $[22];
203
186
  }
204
187
  let t9;
205
- if ($[25] !== asChild || $[26] !== props || $[27] !== selectedValue || $[28] !== t5 || $[29] !== t6 || $[30] !== t7 || $[31] !== t8) {
206
- t9 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Root, {
207
- "data-slot": "radio-group",
208
- className: t5,
209
- ...props,
210
- asChild,
211
- ref: t6,
212
- value: selectedValue,
213
- onValueChange: t7,
214
- children: t8
188
+ if ($[23] !== t5 || $[24] !== t8) {
189
+ t9 = /* @__PURE__ */ _jsxs("label", {
190
+ "data-slot": "radio-group-option",
191
+ className: optionClassName,
192
+ onClick: _temp,
193
+ children: [t5, t8]
215
194
  });
216
- $[25] = asChild;
217
- $[26] = props;
218
- $[27] = selectedValue;
219
- $[28] = t5;
220
- $[29] = t6;
221
- $[30] = t7;
222
- $[31] = t8;
223
- $[32] = t9;
195
+ $[23] = t5;
196
+ $[24] = t8;
197
+ $[25] = t9;
224
198
  } else {
225
- t9 = $[32];
199
+ t9 = $[25];
226
200
  }
227
- let t10;
228
- if ($[33] !== selectedValue || $[34] !== t9) {
229
- t10 = /* @__PURE__ */ _jsx(RadioGroupValueContext.Provider, {
230
- value: selectedValue,
231
- children: t9
232
- });
233
- $[33] = selectedValue;
234
- $[34] = t9;
235
- $[35] = t10;
236
- } else {
237
- t10 = $[35];
201
+ return t9;
202
+ }
203
+ function _temp(event) {
204
+ const radio = event.currentTarget.querySelector("[data-slot=\"radio-group-item\"]");
205
+ if (radio && !radio.disabled && event.target !== radio) {
206
+ radio.focus({ preventScroll: true });
238
207
  }
239
- return t10;
240
208
  }
241
209
  /**
242
- * Arc's mark recipe. The bare mark keeps its 17px box and widens its hit area with a pseudo-element; the faint preview
243
- * dot and the press dip answer the mark itself, or its whole row when it has a label.
244
- */
245
- const radioGroupItemClassName = "peer group/radio-group-item relative grid aspect-square size-[17px] shrink-0 cursor-pointer place-items-center rounded-full border border-border-strong bg-transparent p-0 [-webkit-tap-highlight-color:transparent] [transition:border-color_var(--duration-fast)_var(--ease-standard),background-color_var(--duration-fast)_var(--ease-standard),scale_var(--duration-spring)_var(--ease-spring)] before:size-[7px] before:rounded-full before:bg-foreground before:opacity-0 before:transition-opacity before:duration-(--duration-instant) before:ease-(--ease-standard) before:[grid-area:1/1] before:content-[''] after:absolute after:-inset-[13px] disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-(--control-on) data-[state=checked]:bg-(--control-on) aria-invalid:data-[state=unchecked]:border-danger hover-fine:data-[state=unchecked]:not-disabled:border-text-muted active:not-disabled:scale-[.88] active:not-disabled:[transition:border-color_var(--duration-fast)_var(--ease-standard),background-color_var(--duration-fast)_var(--ease-standard),scale_100ms_var(--ease-standard)] active:not-disabled:data-[state=unchecked]:before:opacity-[.22] group-active/radio-group-option:not-disabled:scale-[.88] group-active/radio-group-option:not-disabled:data-[state=unchecked]:before:opacity-[.22] motion-reduce:scale-100 motion-reduce:transition-none motion-reduce:before:transition-none";
246
- /** Arc's option row: answers a press with color only, while the mark is what moves. */
247
- const optionClassName = "group/radio-group-option relative flex cursor-pointer items-center gap-(--space-3) rounded-(--radius-control) border border-border p-(--space-3) [-webkit-tap-highlight-color:transparent] transition-[background-color,border-color] duration-(--duration-fast) ease-(--ease-standard) hover-fine:bg-surface-muted active:bg-surface-muted has-disabled:cursor-not-allowed has-disabled:opacity-50 [[data-slot=radio-group]:not([data-ready])_&]:has-data-[state=checked]:border-(--control-on) [[data-slot=radio-group]:not([data-ready])_&]:has-data-[state=checked]:bg-[color-mix(in_oklab,var(--control-on)_5%,transparent)] motion-reduce:transition-none";
248
- /**
249
- * One radio of the group: a bare mark, or Arc's option row when it receives a `label`.
250
- * @param radioGroupItemProps - Every Radix radio item prop, including `ref`, plus optional Arc `label` and `description`.
251
- * @returns The radio, wrapped in its option row when it has a label.
210
+ * A choice of one option from a visible set, controlled with `value` or uncontrolled with `defaultValue`.
211
+ * @param props - Legend, options, value, change handler, form name and classes.
212
+ * @returns The fieldset with its legend and option rows.
252
213
  */
253
- function RadioGroupItem(t0) {
254
- const $ = _c(43);
255
- let className;
256
- let description;
257
- let id;
258
- let label;
259
- let props;
260
- let value;
261
- if ($[0] !== t0) {
262
- ({className, label, description, id, value, ...props} = t0);
263
- $[0] = t0;
264
- $[1] = className;
265
- $[2] = description;
266
- $[3] = id;
267
- $[4] = label;
268
- $[5] = props;
269
- $[6] = value;
214
+ function RadioGroup(t0) {
215
+ const $ = _c(32);
216
+ const { label, options, value, defaultValue, onValueChange, name, className } = t0;
217
+ const reduceMotion = usePrefersReducedMotion();
218
+ const generatedId = useId();
219
+ const legendId = `${generatedId}-legend`;
220
+ const [uncontrolledValue, setUncontrolledValue] = useState(defaultValue);
221
+ const selectedValue = value ?? uncontrolledValue;
222
+ const groupRef = useRef(null);
223
+ const optionsRef = useRef(null);
224
+ const highlightRef = useRef(null);
225
+ const shownValue = useRef(null);
226
+ const placedAt = useRef("");
227
+ let t1;
228
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
229
+ t1 = () => optionsRef.current?.querySelector(CHECKED_OPTION_SELECTOR) ?? null;
230
+ $[0] = t1;
270
231
  } else {
271
- className = $[1];
272
- description = $[2];
273
- id = $[3];
274
- label = $[4];
275
- props = $[5];
276
- value = $[6];
232
+ t1 = $[0];
277
233
  }
278
- const generatedId = useId();
279
- const rowId = id ?? generatedId;
280
- const labelId = `${rowId}-${RADIO_GROUP_OPTION_ID_SUFFIX.label}`;
281
- const descriptionId = `${rowId}-${RADIO_GROUP_OPTION_ID_SUFFIX.description}`;
282
- const reduceMotion = usePrefersReducedMotion();
283
- const isChecked = useContext(RadioGroupValueContext) === value;
284
- const hasRow = Boolean(label);
285
- const t1 = hasRow && "z-2 after:hidden";
234
+ const findCheckedRow = t1;
286
235
  let t2;
287
- if ($[7] !== className || $[8] !== t1) {
288
- t2 = cn(radioGroupItemClassName, t1, className);
289
- $[7] = className;
290
- $[8] = t1;
291
- $[9] = t2;
236
+ let t3;
237
+ if ($[1] !== reduceMotion || $[2] !== selectedValue) {
238
+ t2 = () => {
239
+ const hasChanged = shownValue.current !== null && shownValue.current !== selectedValue;
240
+ placeHighlight(highlightRef.current, findCheckedRow(), placedAt, hasChanged && !reduceMotion);
241
+ shownValue.current = selectedValue;
242
+ groupRef.current?.setAttribute(RADIO_GROUP_READY_ATTRIBUTE, "");
243
+ };
244
+ t3 = [selectedValue, reduceMotion];
245
+ $[1] = reduceMotion;
246
+ $[2] = selectedValue;
247
+ $[3] = t2;
248
+ $[4] = t3;
292
249
  } else {
293
- t2 = $[9];
250
+ t2 = $[3];
251
+ t3 = $[4];
294
252
  }
295
- const t3 = hasRow ? props["aria-labelledby"] ?? labelId : props["aria-labelledby"];
253
+ useLayoutEffect(t2, t3);
296
254
  let t4;
297
- if ($[10] !== description || $[11] !== descriptionId || $[12] !== hasRow || $[13] !== props) {
298
- t4 = [props["aria-describedby"], hasRow && description ? descriptionId : undefined].filter(Boolean).join(" ") || undefined;
299
- $[10] = description;
300
- $[11] = descriptionId;
301
- $[12] = hasRow;
302
- $[13] = props;
303
- $[14] = t4;
304
- } else {
305
- t4 = $[14];
306
- }
307
- let t5;
308
- if ($[15] !== isChecked) {
309
- t5 = isChecked ? {
310
- scale: 1,
311
- opacity: 1
312
- } : {
313
- scale: RADIO_GROUP_DOT_HIDDEN_SCALE,
314
- opacity: 0
255
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
256
+ t4 = () => {
257
+ const list = optionsRef.current;
258
+ if (!list || typeof ResizeObserver === "undefined") {
259
+ return;
260
+ }
261
+ const observer = new ResizeObserver(() => placeHighlight(highlightRef.current, findCheckedRow(), placedAt, false));
262
+ observer.observe(list);
263
+ list.querySelectorAll(OPTION_SELECTOR).forEach((row) => observer.observe(row));
264
+ return () => observer.disconnect();
315
265
  };
316
- $[15] = isChecked;
317
- $[16] = t5;
266
+ $[5] = t4;
318
267
  } else {
319
- t5 = $[16];
268
+ t4 = $[5];
320
269
  }
270
+ useEffect(t4);
271
+ const t5 = name ?? generatedId;
321
272
  let t6;
322
- if ($[17] !== isChecked || $[18] !== reduceMotion) {
323
- t6 = reduceMotion ? { duration: 0 } : {
324
- ...ARC_SPRING_SNAPPY,
325
- opacity: { duration: isChecked ? ARC_DURATION.fast : ARC_DURATION.instant }
273
+ if ($[6] !== onValueChange || $[7] !== value) {
274
+ t6 = (nextValue) => {
275
+ if (value === undefined) {
276
+ setUncontrolledValue(nextValue);
277
+ }
278
+ onValueChange?.(nextValue);
326
279
  };
327
- $[17] = isChecked;
328
- $[18] = reduceMotion;
329
- $[19] = t6;
280
+ $[6] = onValueChange;
281
+ $[7] = value;
282
+ $[8] = t6;
330
283
  } else {
331
- t6 = $[19];
284
+ t6 = $[8];
332
285
  }
333
286
  let t7;
334
- if ($[20] !== t5 || $[21] !== t6) {
335
- t7 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Indicator, {
336
- forceMount: true,
337
- asChild: true,
338
- children: /* @__PURE__ */ _jsx(motion.span, {
339
- "data-slot": "radio-group-indicator",
340
- className: "pointer-events-none block size-[7px] rounded-full bg-(--control-glyph) [grid-area:1/1]",
341
- initial: false,
342
- animate: t5,
343
- transition: t6
344
- })
345
- });
346
- $[20] = t5;
347
- $[21] = t6;
348
- $[22] = t7;
287
+ if ($[9] !== className) {
288
+ t7 = cn("m-0 grid min-w-0 border-0 p-0", className);
289
+ $[9] = className;
290
+ $[10] = t7;
349
291
  } else {
350
- t7 = $[22];
292
+ t7 = $[10];
351
293
  }
352
294
  let t8;
353
- if ($[23] !== id || $[24] !== props || $[25] !== t2 || $[26] !== t3 || $[27] !== t4 || $[28] !== t7 || $[29] !== value) {
354
- t8 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Item, {
355
- "data-slot": "radio-group-item",
356
- className: t2,
357
- ...props,
358
- id,
359
- value,
360
- "aria-labelledby": t3,
361
- "aria-describedby": t4,
362
- children: t7
295
+ if ($[11] !== label || $[12] !== legendId) {
296
+ t8 = /* @__PURE__ */ _jsx("legend", {
297
+ id: legendId,
298
+ "data-slot": "radio-group-label",
299
+ className: "mb-(--space-2) p-0 text-sm font-medium text-foreground",
300
+ children: label
363
301
  });
364
- $[23] = id;
365
- $[24] = props;
366
- $[25] = t2;
367
- $[26] = t3;
368
- $[27] = t4;
369
- $[28] = t7;
370
- $[29] = value;
371
- $[30] = t8;
302
+ $[11] = label;
303
+ $[12] = legendId;
304
+ $[13] = t8;
372
305
  } else {
373
- t8 = $[30];
374
- }
375
- const item = t8;
376
- if (!hasRow) {
377
- return item;
306
+ t8 = $[13];
378
307
  }
379
308
  let t9;
380
- if ($[31] !== label || $[32] !== labelId) {
309
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
381
310
  t9 = /* @__PURE__ */ _jsx("span", {
382
- id: labelId,
383
- "data-slot": "radio-group-option-label",
384
- className: "block text-sm font-medium text-text-secondary transition-colors duration-(--duration-standard) ease-(--ease-standard) group-has-data-[state=checked]/radio-group-option:text-foreground motion-reduce:transition-none",
385
- children: label
311
+ ref: highlightRef,
312
+ "data-slot": "radio-group-highlight",
313
+ "aria-hidden": "true",
314
+ className: "pointer-events-none absolute top-0 left-0 z-1 box-border rounded-(--radius-control) border border-(--control-on) bg-[color-mix(in_oklab,var(--control-on)_5%,transparent)] opacity-0"
386
315
  });
387
- $[31] = label;
388
- $[32] = labelId;
389
- $[33] = t9;
316
+ $[14] = t9;
390
317
  } else {
391
- t9 = $[33];
318
+ t9 = $[14];
392
319
  }
393
320
  let t10;
394
- if ($[34] !== description || $[35] !== descriptionId) {
395
- t10 = description ? /* @__PURE__ */ _jsx("span", {
396
- id: descriptionId,
397
- "data-slot": "radio-group-option-description",
398
- className: "mt-0.5 block text-xs text-text-muted",
399
- children: description
400
- }) : null;
401
- $[34] = description;
402
- $[35] = descriptionId;
403
- $[36] = t10;
321
+ if ($[15] !== options) {
322
+ t10 = options.map(_temp2);
323
+ $[15] = options;
324
+ $[16] = t10;
404
325
  } else {
405
- t10 = $[36];
326
+ t10 = $[16];
406
327
  }
407
328
  let t11;
408
- if ($[37] !== t10 || $[38] !== t9) {
409
- t11 = /* @__PURE__ */ _jsxs("span", {
410
- className: "relative z-2 min-w-0",
329
+ if ($[17] !== t10) {
330
+ t11 = /* @__PURE__ */ _jsxs("div", {
331
+ ref: optionsRef,
332
+ "data-slot": "radio-group-options",
333
+ className: "relative grid w-full gap-(--space-2)",
411
334
  children: [t9, t10]
412
335
  });
413
- $[37] = t10;
414
- $[38] = t9;
415
- $[39] = t11;
336
+ $[17] = t10;
337
+ $[18] = t11;
416
338
  } else {
417
- t11 = $[39];
339
+ t11 = $[18];
418
340
  }
419
341
  let t12;
420
- if ($[40] !== item || $[41] !== t11) {
421
- t12 = /* @__PURE__ */ _jsxs("label", {
422
- "data-slot": "radio-group-option",
423
- className: optionClassName,
424
- onClick: _temp,
425
- children: [item, t11]
342
+ if ($[19] !== legendId || $[20] !== t11 || $[21] !== t7 || $[22] !== t8) {
343
+ t12 = /* @__PURE__ */ _jsxs("fieldset", {
344
+ ref: groupRef,
345
+ "data-slot": "radio-group",
346
+ "aria-labelledby": legendId,
347
+ className: t7,
348
+ children: [t8, t11]
426
349
  });
427
- $[40] = item;
428
- $[41] = t11;
429
- $[42] = t12;
350
+ $[19] = legendId;
351
+ $[20] = t11;
352
+ $[21] = t7;
353
+ $[22] = t8;
354
+ $[23] = t12;
430
355
  } else {
431
- t12 = $[42];
356
+ t12 = $[23];
432
357
  }
433
- return t12;
434
- }
435
- function _temp(event) {
436
- const radio = event.currentTarget.querySelector("[data-slot=\"radio-group-item\"]");
437
- if (radio && !radio.disabled && event.target !== radio) {
438
- radio.focus({ preventScroll: true });
358
+ let t13;
359
+ if ($[24] !== selectedValue || $[25] !== t12 || $[26] !== t5 || $[27] !== t6) {
360
+ t13 = /* @__PURE__ */ _jsx(RadioGroupPrimitive.Root, {
361
+ asChild: true,
362
+ name: t5,
363
+ value: selectedValue,
364
+ onValueChange: t6,
365
+ children: t12
366
+ });
367
+ $[24] = selectedValue;
368
+ $[25] = t12;
369
+ $[26] = t5;
370
+ $[27] = t6;
371
+ $[28] = t13;
372
+ } else {
373
+ t13 = $[28];
439
374
  }
375
+ let t14;
376
+ if ($[29] !== selectedValue || $[30] !== t13) {
377
+ t14 = /* @__PURE__ */ _jsx(RadioGroupValueContext.Provider, {
378
+ value: selectedValue,
379
+ children: t13
380
+ });
381
+ $[29] = selectedValue;
382
+ $[30] = t13;
383
+ $[31] = t14;
384
+ } else {
385
+ t14 = $[31];
386
+ }
387
+ return t14;
388
+ }
389
+ function _temp2(option) {
390
+ return /* @__PURE__ */ _jsx(RadioGroupOptionRow, { ...option }, option.value);
440
391
  }
441
- export { RadioGroup, RadioGroupItem };
392
+ export { RadioGroup };