@zag-js/radio-group 1.27.1 → 1.29.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.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _zag_js_anatomy from '@zag-js/anatomy';
2
- import { RequiredBy, DirectionProperty, CommonProperties, PropTypes, NormalizeProps } from '@zag-js/types';
2
+ import { RequiredBy, DirectionProperty, CommonProperties, Rect, PropTypes, NormalizeProps } from '@zag-js/types';
3
3
  import * as _zag_js_core from '@zag-js/core';
4
4
  import { Service, EventObject, Machine } from '@zag-js/core';
5
5
 
@@ -57,12 +57,6 @@ interface RadioGroupProps extends DirectionProperty, CommonProperties {
57
57
  */
58
58
  orientation?: "horizontal" | "vertical" | undefined;
59
59
  }
60
- interface IndicatorRect {
61
- left: string;
62
- top: string;
63
- width: string;
64
- height: string;
65
- }
66
60
  interface PrivateContext {
67
61
  /**
68
62
  * The value of the checked radio
@@ -76,6 +70,10 @@ interface PrivateContext {
76
70
  * The id of the focused radio
77
71
  */
78
72
  focusedValue: string | null;
73
+ /**
74
+ * The id of the radio that has focus-visible
75
+ */
76
+ focusVisibleValue: string | null;
79
77
  /**
80
78
  * The id of the hovered radio
81
79
  */
@@ -83,11 +81,7 @@ interface PrivateContext {
83
81
  /**
84
82
  * The active tab indicator's dom rect
85
83
  */
86
- indicatorRect: Partial<IndicatorRect>;
87
- /**
88
- * Whether the active tab indicator's rect can transition
89
- */
90
- canIndicatorTransition: boolean;
84
+ indicatorRect: Rect | null;
91
85
  /**
92
86
  * Whether the radio group's fieldset is disabled
93
87
  */
@@ -109,10 +103,6 @@ interface Refs {
109
103
  * Function to clean up the observer for the active tab's rect
110
104
  */
111
105
  indicatorCleanup: VoidFunction | null;
112
- /**
113
- * The value of the radio that has focus visible
114
- */
115
- focusVisibleValue: string | null;
116
106
  }
117
107
  interface RadioGroupSchema {
118
108
  state: "idle";
@@ -205,4 +195,4 @@ declare const splitProps: <Props extends Partial<RadioGroupProps>>(props: Props)
205
195
  declare const itemProps: (keyof ItemProps)[];
206
196
  declare const splitItemProps: <Props extends ItemProps>(props: Props) => [ItemProps, Omit<Props, keyof ItemProps>];
207
197
 
208
- export { type RadioGroupApi as Api, type ElementIds, type IndicatorRect, type ItemProps, type ItemState, type RadioGroupMachine as Machine, type RadioGroupProps as Props, type RadioGroupService as Service, type ValueChangeDetails, anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
198
+ export { type RadioGroupApi as Api, type ElementIds, type ItemProps, type ItemState, type RadioGroupMachine as Machine, type RadioGroupProps as Props, type RadioGroupService as Service, type ValueChangeDetails, anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _zag_js_anatomy from '@zag-js/anatomy';
2
- import { RequiredBy, DirectionProperty, CommonProperties, PropTypes, NormalizeProps } from '@zag-js/types';
2
+ import { RequiredBy, DirectionProperty, CommonProperties, Rect, PropTypes, NormalizeProps } from '@zag-js/types';
3
3
  import * as _zag_js_core from '@zag-js/core';
4
4
  import { Service, EventObject, Machine } from '@zag-js/core';
5
5
 
@@ -57,12 +57,6 @@ interface RadioGroupProps extends DirectionProperty, CommonProperties {
57
57
  */
58
58
  orientation?: "horizontal" | "vertical" | undefined;
59
59
  }
60
- interface IndicatorRect {
61
- left: string;
62
- top: string;
63
- width: string;
64
- height: string;
65
- }
66
60
  interface PrivateContext {
67
61
  /**
68
62
  * The value of the checked radio
@@ -76,6 +70,10 @@ interface PrivateContext {
76
70
  * The id of the focused radio
77
71
  */
78
72
  focusedValue: string | null;
73
+ /**
74
+ * The id of the radio that has focus-visible
75
+ */
76
+ focusVisibleValue: string | null;
79
77
  /**
80
78
  * The id of the hovered radio
81
79
  */
@@ -83,11 +81,7 @@ interface PrivateContext {
83
81
  /**
84
82
  * The active tab indicator's dom rect
85
83
  */
86
- indicatorRect: Partial<IndicatorRect>;
87
- /**
88
- * Whether the active tab indicator's rect can transition
89
- */
90
- canIndicatorTransition: boolean;
84
+ indicatorRect: Rect | null;
91
85
  /**
92
86
  * Whether the radio group's fieldset is disabled
93
87
  */
@@ -109,10 +103,6 @@ interface Refs {
109
103
  * Function to clean up the observer for the active tab's rect
110
104
  */
111
105
  indicatorCleanup: VoidFunction | null;
112
- /**
113
- * The value of the radio that has focus visible
114
- */
115
- focusVisibleValue: string | null;
116
106
  }
117
107
  interface RadioGroupSchema {
118
108
  state: "idle";
@@ -205,4 +195,4 @@ declare const splitProps: <Props extends Partial<RadioGroupProps>>(props: Props)
205
195
  declare const itemProps: (keyof ItemProps)[];
206
196
  declare const splitItemProps: <Props extends ItemProps>(props: Props) => [ItemProps, Omit<Props, keyof ItemProps>];
207
197
 
208
- export { type RadioGroupApi as Api, type ElementIds, type IndicatorRect, type ItemProps, type ItemState, type RadioGroupMachine as Machine, type RadioGroupProps as Props, type RadioGroupService as Service, type ValueChangeDetails, anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
198
+ export { type RadioGroupApi as Api, type ElementIds, type ItemProps, type ItemState, type RadioGroupMachine as Machine, type RadioGroupProps as Props, type RadioGroupService as Service, type ValueChangeDetails, anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
package/dist/index.js CHANGED
@@ -3,8 +3,8 @@
3
3
  var anatomy$1 = require('@zag-js/anatomy');
4
4
  var domQuery = require('@zag-js/dom-query');
5
5
  var focusVisible = require('@zag-js/focus-visible');
6
- var core = require('@zag-js/core');
7
6
  var utils = require('@zag-js/utils');
7
+ var core = require('@zag-js/core');
8
8
  var types = require('@zag-js/types');
9
9
 
10
10
  // src/radio-group.anatomy.ts
@@ -39,21 +39,15 @@ var getRadioEl = (ctx, value) => {
39
39
  return ctx.getById(getItemId(ctx, value));
40
40
  };
41
41
  var getOffsetRect = (el) => ({
42
- left: el?.offsetLeft ?? 0,
43
- top: el?.offsetTop ?? 0,
42
+ x: el?.offsetLeft ?? 0,
43
+ y: el?.offsetTop ?? 0,
44
44
  width: el?.offsetWidth ?? 0,
45
45
  height: el?.offsetHeight ?? 0
46
46
  });
47
- var resolveRect = (rect) => ({
48
- width: `${rect.width}px`,
49
- height: `${rect.height}px`,
50
- left: `${rect.left}px`,
51
- top: `${rect.top}px`
52
- });
53
47
 
54
48
  // src/radio-group.connect.ts
55
49
  function connect(service, normalize) {
56
- const { context, send, computed, prop, scope, refs } = service;
50
+ const { context, send, computed, prop, scope } = service;
57
51
  const groupDisabled = computed("isDisabled");
58
52
  const readOnly = prop("readOnly");
59
53
  function getItemState(props2) {
@@ -63,7 +57,7 @@ function connect(service, normalize) {
63
57
  disabled: !!props2.disabled || groupDisabled,
64
58
  checked: context.get("value") === props2.value,
65
59
  focused: context.get("focusedValue") === props2.value,
66
- focusVisible: refs.get("focusVisibleValue") === props2.value,
60
+ focusVisible: context.get("focusVisibleValue") === props2.value,
67
61
  hovered: context.get("hoveredValue") === props2.value,
68
62
  active: context.get("activeValue") === props2.value
69
63
  };
@@ -195,7 +189,7 @@ function connect(service, normalize) {
195
189
  }
196
190
  },
197
191
  onBlur() {
198
- send({ type: "SET_FOCUSED", value: null, focused: false });
192
+ send({ type: "SET_FOCUSED", value: null, focused: false, focusVisible: false });
199
193
  },
200
194
  onFocus() {
201
195
  const focusVisible$1 = focusVisible.isFocusVisible();
@@ -224,19 +218,19 @@ function connect(service, normalize) {
224
218
  id: getIndicatorId(scope),
225
219
  ...parts.indicator.attrs,
226
220
  dir: prop("dir"),
227
- hidden: context.get("value") == null,
221
+ hidden: context.get("value") == null || rect == null,
228
222
  "data-disabled": domQuery.dataAttr(groupDisabled),
229
223
  "data-orientation": prop("orientation"),
230
224
  style: {
231
225
  "--transition-property": "left, top, width, height",
232
- "--left": rect?.left,
233
- "--top": rect?.top,
234
- "--width": rect?.width,
235
- "--height": rect?.height,
226
+ "--left": utils.toPx(rect?.x),
227
+ "--top": utils.toPx(rect?.y),
228
+ "--width": utils.toPx(rect?.width),
229
+ "--height": utils.toPx(rect?.height),
236
230
  position: "absolute",
237
231
  willChange: "var(--transition-property)",
238
232
  transitionProperty: "var(--transition-property)",
239
- transitionDuration: context.get("canIndicatorTransition") ? "var(--transition-duration, 150ms)" : "0ms",
233
+ transitionDuration: "var(--transition-duration, 150ms)",
240
234
  transitionTimingFunction: "var(--transition-timing-function)",
241
235
  [prop("orientation") === "horizontal" ? "left" : "top"]: prop("orientation") === "horizontal" ? "var(--left)" : "var(--top)"
242
236
  }
@@ -270,14 +264,14 @@ var machine = core.createMachine({
270
264
  focusedValue: bindable(() => ({
271
265
  defaultValue: null
272
266
  })),
267
+ focusVisibleValue: bindable(() => ({
268
+ defaultValue: null
269
+ })),
273
270
  hoveredValue: bindable(() => ({
274
271
  defaultValue: null
275
272
  })),
276
273
  indicatorRect: bindable(() => ({
277
- defaultValue: {}
278
- })),
279
- canIndicatorTransition: bindable(() => ({
280
- defaultValue: false
274
+ defaultValue: null
281
275
  })),
282
276
  fieldsetDisabled: bindable(() => ({
283
277
  defaultValue: false
@@ -301,7 +295,7 @@ var machine = core.createMachine({
301
295
  effects: ["trackFormControlState", "trackFocusVisible"],
302
296
  watch({ track, action, context }) {
303
297
  track([() => context.get("value")], () => {
304
- action(["setIndicatorTransition", "syncIndicatorRect", "syncInputElements"]);
298
+ action(["syncIndicatorRect", "syncInputElements"]);
305
299
  });
306
300
  },
307
301
  on: {
@@ -356,9 +350,10 @@ var machine = core.createMachine({
356
350
  setActive({ context, event }) {
357
351
  context.set("activeValue", event.value);
358
352
  },
359
- setFocused({ context, event, refs }) {
353
+ setFocused({ context, event }) {
360
354
  context.set("focusedValue", event.value);
361
- refs.set("focusVisibleValue", event.focusVisible ? event.value : null);
355
+ const focusVisibleValue = event.value != null && event.focusVisible ? event.value : null;
356
+ context.set("focusVisibleValue", focusVisibleValue);
362
357
  },
363
358
  syncInputElements({ context, scope }) {
364
359
  const inputs = getInputEls(scope);
@@ -366,9 +361,6 @@ var machine = core.createMachine({
366
361
  input.checked = input.value === context.get("value");
367
362
  });
368
363
  },
369
- setIndicatorTransition({ context }) {
370
- context.set("canIndicatorTransition", utils.isString(context.get("value")));
371
- },
372
364
  cleanupObserver({ refs }) {
373
365
  refs.get("indicatorCleanup")?.();
374
366
  },
@@ -381,18 +373,14 @@ var machine = core.createMachine({
381
373
  const value = context.get("value");
382
374
  const radioEl = getRadioEl(scope, value);
383
375
  if (value == null || !radioEl) {
384
- context.set("canIndicatorTransition", false);
385
- context.set("indicatorRect", {});
376
+ context.set("indicatorRect", null);
386
377
  return;
387
378
  }
388
- const indicatorCleanup = domQuery.trackElementRect([radioEl], {
389
- measure(el) {
390
- return getOffsetRect(el);
391
- },
392
- onEntry({ rects }) {
393
- context.set("indicatorRect", resolveRect(rects[0]));
394
- }
395
- });
379
+ const exec = () => {
380
+ context.set("indicatorRect", getOffsetRect(radioEl));
381
+ };
382
+ exec();
383
+ const indicatorCleanup = domQuery.resizeObserverBorderBox.observe(radioEl, exec);
396
384
  refs.set("indicatorCleanup", indicatorCleanup);
397
385
  },
398
386
  dispatchChangeEvent({ context, scope }) {
package/dist/index.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { createAnatomy } from '@zag-js/anatomy';
2
- import { dispatchInputCheckedEvent, trackElementRect, trackFormControl, queryAll, dataAttr, visuallyHiddenStyle, isSafari, isLeftClick } from '@zag-js/dom-query';
2
+ import { dispatchInputCheckedEvent, resizeObserverBorderBox, trackFormControl, queryAll, dataAttr, visuallyHiddenStyle, isSafari, isLeftClick } from '@zag-js/dom-query';
3
3
  import { trackFocusVisible, isFocusVisible } from '@zag-js/focus-visible';
4
+ import { createSplitProps, toPx } from '@zag-js/utils';
4
5
  import { createGuards, createMachine } from '@zag-js/core';
5
- import { isString, createSplitProps } from '@zag-js/utils';
6
6
  import { createProps } from '@zag-js/types';
7
7
 
8
8
  // src/radio-group.anatomy.ts
@@ -37,21 +37,15 @@ var getRadioEl = (ctx, value) => {
37
37
  return ctx.getById(getItemId(ctx, value));
38
38
  };
39
39
  var getOffsetRect = (el) => ({
40
- left: el?.offsetLeft ?? 0,
41
- top: el?.offsetTop ?? 0,
40
+ x: el?.offsetLeft ?? 0,
41
+ y: el?.offsetTop ?? 0,
42
42
  width: el?.offsetWidth ?? 0,
43
43
  height: el?.offsetHeight ?? 0
44
44
  });
45
- var resolveRect = (rect) => ({
46
- width: `${rect.width}px`,
47
- height: `${rect.height}px`,
48
- left: `${rect.left}px`,
49
- top: `${rect.top}px`
50
- });
51
45
 
52
46
  // src/radio-group.connect.ts
53
47
  function connect(service, normalize) {
54
- const { context, send, computed, prop, scope, refs } = service;
48
+ const { context, send, computed, prop, scope } = service;
55
49
  const groupDisabled = computed("isDisabled");
56
50
  const readOnly = prop("readOnly");
57
51
  function getItemState(props2) {
@@ -61,7 +55,7 @@ function connect(service, normalize) {
61
55
  disabled: !!props2.disabled || groupDisabled,
62
56
  checked: context.get("value") === props2.value,
63
57
  focused: context.get("focusedValue") === props2.value,
64
- focusVisible: refs.get("focusVisibleValue") === props2.value,
58
+ focusVisible: context.get("focusVisibleValue") === props2.value,
65
59
  hovered: context.get("hoveredValue") === props2.value,
66
60
  active: context.get("activeValue") === props2.value
67
61
  };
@@ -193,7 +187,7 @@ function connect(service, normalize) {
193
187
  }
194
188
  },
195
189
  onBlur() {
196
- send({ type: "SET_FOCUSED", value: null, focused: false });
190
+ send({ type: "SET_FOCUSED", value: null, focused: false, focusVisible: false });
197
191
  },
198
192
  onFocus() {
199
193
  const focusVisible = isFocusVisible();
@@ -222,19 +216,19 @@ function connect(service, normalize) {
222
216
  id: getIndicatorId(scope),
223
217
  ...parts.indicator.attrs,
224
218
  dir: prop("dir"),
225
- hidden: context.get("value") == null,
219
+ hidden: context.get("value") == null || rect == null,
226
220
  "data-disabled": dataAttr(groupDisabled),
227
221
  "data-orientation": prop("orientation"),
228
222
  style: {
229
223
  "--transition-property": "left, top, width, height",
230
- "--left": rect?.left,
231
- "--top": rect?.top,
232
- "--width": rect?.width,
233
- "--height": rect?.height,
224
+ "--left": toPx(rect?.x),
225
+ "--top": toPx(rect?.y),
226
+ "--width": toPx(rect?.width),
227
+ "--height": toPx(rect?.height),
234
228
  position: "absolute",
235
229
  willChange: "var(--transition-property)",
236
230
  transitionProperty: "var(--transition-property)",
237
- transitionDuration: context.get("canIndicatorTransition") ? "var(--transition-duration, 150ms)" : "0ms",
231
+ transitionDuration: "var(--transition-duration, 150ms)",
238
232
  transitionTimingFunction: "var(--transition-timing-function)",
239
233
  [prop("orientation") === "horizontal" ? "left" : "top"]: prop("orientation") === "horizontal" ? "var(--left)" : "var(--top)"
240
234
  }
@@ -268,14 +262,14 @@ var machine = createMachine({
268
262
  focusedValue: bindable(() => ({
269
263
  defaultValue: null
270
264
  })),
265
+ focusVisibleValue: bindable(() => ({
266
+ defaultValue: null
267
+ })),
271
268
  hoveredValue: bindable(() => ({
272
269
  defaultValue: null
273
270
  })),
274
271
  indicatorRect: bindable(() => ({
275
- defaultValue: {}
276
- })),
277
- canIndicatorTransition: bindable(() => ({
278
- defaultValue: false
272
+ defaultValue: null
279
273
  })),
280
274
  fieldsetDisabled: bindable(() => ({
281
275
  defaultValue: false
@@ -299,7 +293,7 @@ var machine = createMachine({
299
293
  effects: ["trackFormControlState", "trackFocusVisible"],
300
294
  watch({ track, action, context }) {
301
295
  track([() => context.get("value")], () => {
302
- action(["setIndicatorTransition", "syncIndicatorRect", "syncInputElements"]);
296
+ action(["syncIndicatorRect", "syncInputElements"]);
303
297
  });
304
298
  },
305
299
  on: {
@@ -354,9 +348,10 @@ var machine = createMachine({
354
348
  setActive({ context, event }) {
355
349
  context.set("activeValue", event.value);
356
350
  },
357
- setFocused({ context, event, refs }) {
351
+ setFocused({ context, event }) {
358
352
  context.set("focusedValue", event.value);
359
- refs.set("focusVisibleValue", event.focusVisible ? event.value : null);
353
+ const focusVisibleValue = event.value != null && event.focusVisible ? event.value : null;
354
+ context.set("focusVisibleValue", focusVisibleValue);
360
355
  },
361
356
  syncInputElements({ context, scope }) {
362
357
  const inputs = getInputEls(scope);
@@ -364,9 +359,6 @@ var machine = createMachine({
364
359
  input.checked = input.value === context.get("value");
365
360
  });
366
361
  },
367
- setIndicatorTransition({ context }) {
368
- context.set("canIndicatorTransition", isString(context.get("value")));
369
- },
370
362
  cleanupObserver({ refs }) {
371
363
  refs.get("indicatorCleanup")?.();
372
364
  },
@@ -379,18 +371,14 @@ var machine = createMachine({
379
371
  const value = context.get("value");
380
372
  const radioEl = getRadioEl(scope, value);
381
373
  if (value == null || !radioEl) {
382
- context.set("canIndicatorTransition", false);
383
- context.set("indicatorRect", {});
374
+ context.set("indicatorRect", null);
384
375
  return;
385
376
  }
386
- const indicatorCleanup = trackElementRect([radioEl], {
387
- measure(el) {
388
- return getOffsetRect(el);
389
- },
390
- onEntry({ rects }) {
391
- context.set("indicatorRect", resolveRect(rects[0]));
392
- }
393
- });
377
+ const exec = () => {
378
+ context.set("indicatorRect", getOffsetRect(radioEl));
379
+ };
380
+ exec();
381
+ const indicatorCleanup = resizeObserverBorderBox.observe(radioEl, exec);
394
382
  refs.set("indicatorCleanup", indicatorCleanup);
395
383
  },
396
384
  dispatchChangeEvent({ context, scope }) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/radio-group",
3
- "version": "1.27.1",
3
+ "version": "1.29.0",
4
4
  "description": "Core logic for the radio group widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -27,12 +27,12 @@
27
27
  "url": "https://github.com/chakra-ui/zag/issues"
28
28
  },
29
29
  "dependencies": {
30
- "@zag-js/anatomy": "1.27.1",
31
- "@zag-js/dom-query": "1.27.1",
32
- "@zag-js/focus-visible": "1.27.1",
33
- "@zag-js/utils": "1.27.1",
34
- "@zag-js/core": "1.27.1",
35
- "@zag-js/types": "1.27.1"
30
+ "@zag-js/anatomy": "1.29.0",
31
+ "@zag-js/dom-query": "1.29.0",
32
+ "@zag-js/focus-visible": "1.29.0",
33
+ "@zag-js/utils": "1.29.0",
34
+ "@zag-js/core": "1.29.0",
35
+ "@zag-js/types": "1.29.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "clean-package": "2.2.0"