@zag-js/radio-group 0.16.0 → 0.18.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 { PropTypes, RequiredBy, DirectionProperty, CommonProperties, Context, NormalizeProps } from '@zag-js/types';
2
+ import { RequiredBy, PropTypes, DirectionProperty, CommonProperties, Context, NormalizeProps } from '@zag-js/types';
3
3
  import * as _zag_js_core from '@zag-js/core';
4
4
  import { StateMachine } from '@zag-js/core';
5
5
 
@@ -36,10 +36,6 @@ type PublicContext = DirectionProperty & CommonProperties & {
36
36
  * If `true`, the radio group will be disabled
37
37
  */
38
38
  disabled?: boolean;
39
- /**
40
- * If `true`, the radio group will be readonly
41
- */
42
- readOnly?: boolean;
43
39
  /**
44
40
  * Function called once a radio is checked
45
41
  * @param value the value of the checked radio
@@ -52,7 +48,43 @@ type PublicContext = DirectionProperty & CommonProperties & {
52
48
  */
53
49
  orientation?: "horizontal" | "vertical";
54
50
  };
55
- type PublicApi<T extends PropTypes = PropTypes> = {
51
+ type PrivateContext = Context<{}>;
52
+ type UserDefinedContext = RequiredBy<PublicContext, "id">;
53
+ type ComputedContext = Readonly<{
54
+ /**
55
+ * Whether the radio group is disabled
56
+ */
57
+ isDisabled: boolean;
58
+ }>;
59
+ type MachineContext = PublicContext & PrivateContext & ComputedContext;
60
+ type MachineState = {
61
+ value: "idle";
62
+ };
63
+ type State = StateMachine.State<MachineContext, MachineState>;
64
+ type Send = StateMachine.Send<StateMachine.AnyEventObject>;
65
+ type RadioProps = {
66
+ value: string;
67
+ /**
68
+ * If `true`, the radio will be disabled
69
+ */
70
+ disabled?: boolean;
71
+ /**
72
+ * If `true`, the radio is marked as invalid.
73
+ */
74
+ invalid?: boolean;
75
+ };
76
+ type InputProps = RadioProps & {
77
+ /**
78
+ * If `true` and `disabled` is passed, the radio will
79
+ * remain tabbable but not interactive
80
+ */
81
+ focusable?: boolean;
82
+ /**
83
+ * If `true`, the radio input is marked as required,
84
+ */
85
+ required?: boolean;
86
+ };
87
+ type MachineApi<T extends PropTypes = PropTypes> = {
56
88
  /**
57
89
  * The current value of the radio group
58
90
  */
@@ -93,44 +125,9 @@ type PublicApi<T extends PropTypes = PropTypes> = {
93
125
  getRadioHiddenInputProps(props: InputProps): T["input"];
94
126
  indicatorProps: T["element"];
95
127
  };
96
- type PrivateContext = Context<{}>;
97
- type UserDefinedContext = RequiredBy<PublicContext, "id">;
98
- type ComputedContext = Readonly<{}>;
99
- type MachineContext = PublicContext & PrivateContext & ComputedContext;
100
- type MachineState = {
101
- value: "idle";
102
- };
103
- type State = StateMachine.State<MachineContext, MachineState>;
104
- type Send = StateMachine.Send<StateMachine.AnyEventObject>;
105
- type RadioProps = {
106
- value: string;
107
- /**
108
- * If `true`, the radio will be disabled
109
- */
110
- disabled?: boolean;
111
- /**
112
- * If `true`, the radio will be readonly
113
- */
114
- readOnly?: boolean;
115
- /**
116
- * If `true`, the radio is marked as invalid.
117
- */
118
- invalid?: boolean;
119
- };
120
- type InputProps = RadioProps & {
121
- /**
122
- * If `true` and `disabled` is passed, the radio will
123
- * remain tabbable but not interactive
124
- */
125
- focusable?: boolean;
126
- /**
127
- * If `true`, the radio input is marked as required,
128
- */
129
- required?: boolean;
130
- };
131
128
 
132
- declare function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): PublicApi<T>;
129
+ declare function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T>;
133
130
 
134
131
  declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
135
132
 
136
- export { UserDefinedContext as Context, PublicApi, anatomy, connect, machine };
133
+ export { MachineApi as Api, UserDefinedContext as Context, anatomy, connect, machine };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _zag_js_anatomy from '@zag-js/anatomy';
2
- import { PropTypes, RequiredBy, DirectionProperty, CommonProperties, Context, NormalizeProps } from '@zag-js/types';
2
+ import { RequiredBy, PropTypes, DirectionProperty, CommonProperties, Context, NormalizeProps } from '@zag-js/types';
3
3
  import * as _zag_js_core from '@zag-js/core';
4
4
  import { StateMachine } from '@zag-js/core';
5
5
 
@@ -36,10 +36,6 @@ type PublicContext = DirectionProperty & CommonProperties & {
36
36
  * If `true`, the radio group will be disabled
37
37
  */
38
38
  disabled?: boolean;
39
- /**
40
- * If `true`, the radio group will be readonly
41
- */
42
- readOnly?: boolean;
43
39
  /**
44
40
  * Function called once a radio is checked
45
41
  * @param value the value of the checked radio
@@ -52,7 +48,43 @@ type PublicContext = DirectionProperty & CommonProperties & {
52
48
  */
53
49
  orientation?: "horizontal" | "vertical";
54
50
  };
55
- type PublicApi<T extends PropTypes = PropTypes> = {
51
+ type PrivateContext = Context<{}>;
52
+ type UserDefinedContext = RequiredBy<PublicContext, "id">;
53
+ type ComputedContext = Readonly<{
54
+ /**
55
+ * Whether the radio group is disabled
56
+ */
57
+ isDisabled: boolean;
58
+ }>;
59
+ type MachineContext = PublicContext & PrivateContext & ComputedContext;
60
+ type MachineState = {
61
+ value: "idle";
62
+ };
63
+ type State = StateMachine.State<MachineContext, MachineState>;
64
+ type Send = StateMachine.Send<StateMachine.AnyEventObject>;
65
+ type RadioProps = {
66
+ value: string;
67
+ /**
68
+ * If `true`, the radio will be disabled
69
+ */
70
+ disabled?: boolean;
71
+ /**
72
+ * If `true`, the radio is marked as invalid.
73
+ */
74
+ invalid?: boolean;
75
+ };
76
+ type InputProps = RadioProps & {
77
+ /**
78
+ * If `true` and `disabled` is passed, the radio will
79
+ * remain tabbable but not interactive
80
+ */
81
+ focusable?: boolean;
82
+ /**
83
+ * If `true`, the radio input is marked as required,
84
+ */
85
+ required?: boolean;
86
+ };
87
+ type MachineApi<T extends PropTypes = PropTypes> = {
56
88
  /**
57
89
  * The current value of the radio group
58
90
  */
@@ -93,44 +125,9 @@ type PublicApi<T extends PropTypes = PropTypes> = {
93
125
  getRadioHiddenInputProps(props: InputProps): T["input"];
94
126
  indicatorProps: T["element"];
95
127
  };
96
- type PrivateContext = Context<{}>;
97
- type UserDefinedContext = RequiredBy<PublicContext, "id">;
98
- type ComputedContext = Readonly<{}>;
99
- type MachineContext = PublicContext & PrivateContext & ComputedContext;
100
- type MachineState = {
101
- value: "idle";
102
- };
103
- type State = StateMachine.State<MachineContext, MachineState>;
104
- type Send = StateMachine.Send<StateMachine.AnyEventObject>;
105
- type RadioProps = {
106
- value: string;
107
- /**
108
- * If `true`, the radio will be disabled
109
- */
110
- disabled?: boolean;
111
- /**
112
- * If `true`, the radio will be readonly
113
- */
114
- readOnly?: boolean;
115
- /**
116
- * If `true`, the radio is marked as invalid.
117
- */
118
- invalid?: boolean;
119
- };
120
- type InputProps = RadioProps & {
121
- /**
122
- * If `true` and `disabled` is passed, the radio will
123
- * remain tabbable but not interactive
124
- */
125
- focusable?: boolean;
126
- /**
127
- * If `true`, the radio input is marked as required,
128
- */
129
- required?: boolean;
130
- };
131
128
 
132
- declare function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): PublicApi<T>;
129
+ declare function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T>;
133
130
 
134
131
  declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
135
132
 
136
- export { UserDefinedContext as Context, PublicApi, anatomy, connect, machine };
133
+ export { MachineApi as Api, UserDefinedContext as Context, anatomy, connect, machine };
package/dist/index.js CHANGED
@@ -51,7 +51,7 @@ var dom = (0, import_dom_query.createScope)({
51
51
  getRadioHiddenInputId: (ctx, value) => ctx.ids?.radioHiddenInput?.(value) ?? `radio-group:${ctx.id}:radio:input:${value}`,
52
52
  getRadioControlId: (ctx, value) => ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,
53
53
  getRadioLabelId: (ctx, value) => ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,
54
- getIndicatorId: (ctx) => ctx.ids?.indicator ?? `tabs:${ctx.id}:indicator`,
54
+ getIndicatorId: (ctx) => ctx.ids?.indicator ?? `radio-group:${ctx.id}:indicator`,
55
55
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
56
56
  getRadioHiddenInputEl: (ctx, value) => dom.getById(ctx, dom.getRadioHiddenInputId(ctx, value)),
57
57
  getIndicatorEl: (ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),
@@ -67,33 +67,29 @@ var dom = (0, import_dom_query.createScope)({
67
67
  return;
68
68
  return dom.getById(ctx, dom.getRadioId(ctx, ctx.value));
69
69
  },
70
- getOffsetRect: (el) => {
71
- return {
72
- left: el?.offsetLeft ?? 0,
73
- top: el?.offsetTop ?? 0,
74
- width: el?.offsetWidth ?? 0,
75
- height: el?.offsetHeight ?? 0
76
- };
77
- },
70
+ getOffsetRect: (el) => ({
71
+ left: el?.offsetLeft ?? 0,
72
+ top: el?.offsetTop ?? 0,
73
+ width: el?.offsetWidth ?? 0,
74
+ height: el?.offsetHeight ?? 0
75
+ }),
78
76
  getRectById: (ctx, id) => {
79
77
  const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id));
80
78
  if (!radioEl)
81
79
  return;
82
80
  return dom.resolveRect(dom.getOffsetRect(radioEl));
83
81
  },
84
- resolveRect(rect) {
85
- return {
86
- width: `${rect.width}px`,
87
- height: `${rect.height}px`,
88
- left: `${rect.left}px`,
89
- top: `${rect.top}px`
90
- };
91
- }
82
+ resolveRect: (rect) => ({
83
+ width: `${rect.width}px`,
84
+ height: `${rect.height}px`,
85
+ left: `${rect.left}px`,
86
+ top: `${rect.top}px`
87
+ })
92
88
  });
93
89
 
94
90
  // src/radio-group.connect.ts
95
91
  function connect(state, send, normalize) {
96
- const isGroupDisabled = state.context.disabled;
92
+ const isGroupDisabled = state.context.isDisabled;
97
93
  function getRadioState(props) {
98
94
  const radioState = {
99
95
  isInvalid: props.invalid,
@@ -292,15 +288,20 @@ function machine(userContext) {
292
288
  activeId: null,
293
289
  focusedId: null,
294
290
  hoveredId: null,
291
+ disabled: false,
292
+ ...ctx,
295
293
  indicatorRect: {},
296
294
  canIndicatorTransition: false,
297
- ...ctx
295
+ fieldsetDisabled: false
296
+ },
297
+ computed: {
298
+ isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled
298
299
  },
299
300
  entry: ["syncIndicatorRect"],
300
301
  exit: ["cleanupObserver"],
301
302
  activities: ["trackFormControlState"],
302
303
  watch: {
303
- value: ["setIndicatorTransition", "invokeOnChange", "syncIndicatorRect", "syncInputElements"]
304
+ value: ["setIndicatorTransition", "syncIndicatorRect", "syncInputElements"]
304
305
  },
305
306
  on: {
306
307
  SET_VALUE: {
@@ -324,8 +325,8 @@ function machine(userContext) {
324
325
  activities: {
325
326
  trackFormControlState(ctx2, _evt, { send, initialContext }) {
326
327
  return (0, import_form_utils.trackFormControl)(dom.getRootEl(ctx2), {
327
- onFieldsetDisabled() {
328
- ctx2.disabled = true;
328
+ onFieldsetDisabledChange(disabled) {
329
+ ctx2.fieldsetDisabled = disabled;
329
330
  },
330
331
  onFormReset() {
331
332
  send({ type: "SET_VALUE", value: initialContext.value });
@@ -335,7 +336,7 @@ function machine(userContext) {
335
336
  },
336
337
  actions: {
337
338
  setValue(ctx2, evt) {
338
- ctx2.value = evt.value;
339
+ set.value(ctx2, evt.value);
339
340
  },
340
341
  setHovered(ctx2, evt) {
341
342
  ctx2.hoveredId = evt.value;
@@ -346,9 +347,6 @@ function machine(userContext) {
346
347
  setFocused(ctx2, evt) {
347
348
  ctx2.focusedId = evt.value;
348
349
  },
349
- invokeOnChange(ctx2, evt) {
350
- ctx2.onChange?.({ value: evt.value });
351
- },
352
350
  syncInputElements(ctx2) {
353
351
  const inputs = dom.getInputEls(ctx2);
354
352
  inputs.forEach((input) => {
@@ -389,6 +387,19 @@ function machine(userContext) {
389
387
  }
390
388
  );
391
389
  }
390
+ var invoke = {
391
+ change: (ctx) => {
392
+ if (ctx.value == null)
393
+ return;
394
+ ctx.onChange?.({ value: ctx.value });
395
+ }
396
+ };
397
+ var set = {
398
+ value: (ctx, value) => {
399
+ ctx.value = value;
400
+ invoke.change(ctx);
401
+ }
402
+ };
392
403
  // Annotate the CommonJS export names for ESM import in node:
393
404
  0 && (module.exports = {
394
405
  anatomy,
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/radio-group.anatomy.ts","../src/radio-group.connect.ts","../src/radio-group.dom.ts","../src/radio-group.machine.ts"],"sourcesContent":["export { anatomy } from \"./radio-group.anatomy\"\nexport { connect } from \"./radio-group.connect\"\nexport { machine } from \"./radio-group.machine\"\nexport type { UserDefinedContext as Context, PublicApi } from \"./radio-group.types\"\n","import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"radio-group\").parts(\n \"root\",\n \"label\",\n \"radio\",\n \"radioLabel\",\n \"radioControl\",\n \"indicator\",\n)\nexport const parts = anatomy.build()\n","import { ariaAttr, dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { visuallyHiddenStyle } from \"@zag-js/visually-hidden\"\nimport { parts } from \"./radio-group.anatomy\"\nimport { dom } from \"./radio-group.dom\"\nimport type { InputProps, PublicApi, RadioProps, Send, State } from \"./radio-group.types\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): PublicApi<T> {\n const isGroupDisabled = state.context.disabled\n\n function getRadioState<T extends RadioProps>(props: T) {\n const radioState = {\n isInvalid: props.invalid,\n isDisabled: props.disabled || isGroupDisabled,\n isChecked: state.context.value === props.value,\n isFocused: state.context.focusedId === props.value,\n isHovered: state.context.hoveredId === props.value,\n isActive: state.context.activeId === props.value,\n }\n return {\n ...radioState,\n isInteractive: !radioState.isDisabled,\n }\n }\n\n function getRadioDataAttrs<T extends RadioProps>(props: T) {\n const radioState = getRadioState(props)\n return {\n \"data-focus\": dataAttr(radioState.isFocused),\n \"data-disabled\": dataAttr(radioState.isDisabled),\n \"data-state\": radioState.isChecked ? \"checked\" : \"unchecked\",\n \"data-hover\": dataAttr(radioState.isHovered),\n \"data-invalid\": dataAttr(radioState.isInvalid),\n \"data-orientation\": state.context.orientation,\n }\n }\n\n const focus = () => {\n const firstEnabledAndCheckedInput = dom.getFirstEnabledAndCheckedInputEl(state.context)\n\n if (firstEnabledAndCheckedInput) {\n firstEnabledAndCheckedInput.focus()\n return\n }\n\n const firstEnabledInput = dom.getFirstEnabledInputEl(state.context)\n firstEnabledInput?.focus()\n }\n\n return {\n value: state.context.value,\n\n setValue(value: string) {\n send({ type: \"SET_VALUE\", value, manual: true })\n },\n\n clearValue() {\n send({ type: \"SET_VALUE\", value: null, manual: true })\n },\n\n focus,\n\n blur() {\n const focusedElement = dom.getActiveElement(state.context)\n const inputEls = dom.getInputEls(state.context)\n const radioHiddenInputIsFocused = inputEls.some((el) => el === focusedElement)\n if (radioHiddenInputIsFocused) focusedElement?.blur()\n },\n\n getRadioState,\n\n rootProps: normalize.element({\n ...parts.root.attrs,\n role: \"radiogroup\",\n id: dom.getRootId(state.context),\n \"aria-labelledby\": dom.getLabelId(state.context),\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"aria-orientation\": state.context.orientation,\n dir: state.context.dir,\n }),\n\n labelProps: normalize.element({\n ...parts.label.attrs,\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n id: dom.getLabelId(state.context),\n onClick: focus,\n }),\n\n getRadioProps(props: RadioProps) {\n const rootState = getRadioState(props)\n\n return normalize.label({\n ...parts.radio.attrs,\n id: dom.getRadioId(state.context, props.value),\n htmlFor: dom.getRadioHiddenInputId(state.context, props.value),\n ...getRadioDataAttrs(props),\n\n onPointerMove() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: props.value, hovered: true })\n },\n onPointerLeave() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: null })\n },\n onPointerDown(event) {\n if (!rootState.isInteractive) return\n // On pointerdown, the input blurs and returns focus to the `body`,\n // we need to prevent this.\n if (rootState.isFocused && event.pointerType === \"mouse\") {\n event.preventDefault()\n }\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n },\n onPointerUp() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_ACTIVE\", value: null })\n },\n })\n },\n\n getRadioLabelProps(props: RadioProps) {\n return normalize.element({\n ...parts.radioLabel.attrs,\n id: dom.getRadioLabelId(state.context, props.value),\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioControlProps(props: RadioProps) {\n const controlState = getRadioState(props)\n\n return normalize.element({\n ...parts.radioControl.attrs,\n id: dom.getRadioControlId(state.context, props.value),\n \"data-active\": dataAttr(controlState.isActive),\n \"aria-hidden\": true,\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioHiddenInputProps(props: InputProps) {\n const inputState = getRadioState(props)\n\n const isRequired = props.required\n const trulyDisabled = inputState.isDisabled && !props.focusable\n\n return normalize.input({\n \"data-ownedby\": dom.getRootId(state.context),\n id: dom.getRadioHiddenInputId(state.context, props.value),\n type: \"radio\",\n name: state.context.name || state.context.id,\n form: state.context.form,\n value: props.value,\n onChange(event) {\n if (inputState.isDisabled) return\n\n if (event.target.checked) {\n send({ type: \"SET_VALUE\", value: props.value })\n }\n },\n onBlur() {\n send({ type: \"SET_FOCUSED\", value: null })\n },\n onFocus() {\n send({ type: \"SET_FOCUSED\", value: props.value, focused: true })\n },\n onKeyDown(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n }\n },\n onKeyUp(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: null })\n }\n },\n disabled: trulyDisabled,\n required: isRequired,\n defaultChecked: inputState.isChecked,\n \"data-disabled\": dataAttr(inputState.isDisabled),\n \"aria-required\": ariaAttr(isRequired),\n \"aria-invalid\": ariaAttr(inputState.isInvalid),\n \"aria-disabled\": ariaAttr(trulyDisabled),\n \"aria-checked\": ariaAttr(inputState.isChecked),\n style: visuallyHiddenStyle,\n })\n },\n\n indicatorProps: normalize.element({\n id: dom.getIndicatorId(state.context),\n ...parts.indicator.attrs,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"data-orientation\": state.context.orientation,\n style: {\n \"--transition-duration\": \"150ms\",\n \"--transition-property\": \"left, top, width, height\",\n position: \"absolute\",\n willChange: \"var(--transition-property)\",\n transitionProperty: \"var(--transition-property)\",\n transitionDuration: state.context.canIndicatorTransition ? \"var(--transition-duration)\" : \"0ms\",\n transitionTimingFunction: \"var(--transition-timing-function)\",\n ...state.context.indicatorRect,\n },\n }),\n }\n}\n","import { createScope, queryAll } from \"@zag-js/dom-query\"\nimport type { MachineContext as Ctx } from \"./radio-group.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `radio-group:${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `radio-group:${ctx.id}:label`,\n getRadioId: (ctx: Ctx, value: string) => ctx.ids?.radio?.(value) ?? `radio-group:${ctx.id}:radio:${value}`,\n getRadioHiddenInputId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioHiddenInput?.(value) ?? `radio-group:${ctx.id}:radio:input:${value}`,\n getRadioControlId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,\n getRadioLabelId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,\n getIndicatorId: (ctx: Ctx) => ctx.ids?.indicator ?? `tabs:${ctx.id}:indicator`,\n\n getRootEl: (ctx: Ctx) => dom.getById(ctx, dom.getRootId(ctx)),\n getRadioHiddenInputEl: (ctx: Ctx, value: string) =>\n dom.getById<HTMLInputElement>(ctx, dom.getRadioHiddenInputId(ctx, value)),\n getIndicatorEl: (ctx: Ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),\n\n getFirstEnabledInputEl: (ctx: Ctx) => dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled)\"),\n getFirstEnabledAndCheckedInputEl: (ctx: Ctx) =>\n dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled):checked\"),\n\n getInputEls: (ctx: Ctx) => {\n const ownerId = CSS.escape(dom.getRootId(ctx))\n const selector = `input[type=radio][data-ownedby='${ownerId}']:not([disabled])`\n return queryAll<HTMLInputElement>(dom.getRootEl(ctx), selector)\n },\n\n getActiveRadioEl: (ctx: Ctx) => {\n if (!ctx.value) return\n return dom.getById(ctx, dom.getRadioId(ctx, ctx.value))\n },\n\n getOffsetRect: (el: HTMLElement | undefined) => {\n return {\n left: el?.offsetLeft ?? 0,\n top: el?.offsetTop ?? 0,\n width: el?.offsetWidth ?? 0,\n height: el?.offsetHeight ?? 0,\n }\n },\n\n getRectById: (ctx: Ctx, id: string) => {\n const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id))\n if (!radioEl) return\n return dom.resolveRect(dom.getOffsetRect(radioEl))\n },\n\n resolveRect(rect: Record<\"width\" | \"height\" | \"left\" | \"top\", number>) {\n return {\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n }\n },\n})\n","import { createMachine } from \"@zag-js/core\"\nimport { nextTick } from \"@zag-js/dom-query\"\nimport { trackElementRect } from \"@zag-js/element-rect\"\nimport { trackFormControl } from \"@zag-js/form-utils\"\nimport { compact, isString } from \"@zag-js/utils\"\nimport { dom } from \"./radio-group.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./radio-group.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"radio\",\n initial: \"idle\",\n context: {\n value: null,\n activeId: null,\n focusedId: null,\n hoveredId: null,\n indicatorRect: {},\n canIndicatorTransition: false,\n ...ctx,\n },\n\n entry: [\"syncIndicatorRect\"],\n\n exit: [\"cleanupObserver\"],\n\n activities: [\"trackFormControlState\"],\n\n watch: {\n value: [\"setIndicatorTransition\", \"invokeOnChange\", \"syncIndicatorRect\", \"syncInputElements\"],\n },\n\n on: {\n SET_VALUE: {\n actions: [\"setValue\"],\n },\n SET_HOVERED: {\n actions: \"setHovered\",\n },\n SET_ACTIVE: {\n actions: \"setActive\",\n },\n SET_FOCUSED: {\n actions: \"setFocused\",\n },\n },\n\n states: {\n idle: {},\n },\n },\n\n {\n activities: {\n trackFormControlState(ctx, _evt, { send, initialContext }) {\n return trackFormControl(dom.getRootEl(ctx), {\n onFieldsetDisabled() {\n ctx.disabled = true\n },\n onFormReset() {\n send({ type: \"SET_VALUE\", value: initialContext.value })\n },\n })\n },\n },\n\n actions: {\n setValue(ctx, evt) {\n ctx.value = evt.value\n },\n setHovered(ctx, evt) {\n ctx.hoveredId = evt.value\n },\n setActive(ctx, evt) {\n ctx.activeId = evt.value\n },\n setFocused(ctx, evt) {\n ctx.focusedId = evt.value\n },\n invokeOnChange(ctx, evt) {\n ctx.onChange?.({ value: evt.value })\n },\n syncInputElements(ctx) {\n const inputs = dom.getInputEls(ctx)\n inputs.forEach((input) => {\n input.checked = input.value === ctx.value\n })\n },\n setIndicatorTransition(ctx) {\n ctx.canIndicatorTransition = isString(ctx.value)\n },\n cleanupObserver(ctx) {\n ctx.indicatorCleanup?.()\n },\n syncIndicatorRect(ctx) {\n ctx.indicatorCleanup?.()\n\n if (!dom.getIndicatorEl(ctx)) return\n\n const value = ctx.value\n\n if (value == null) {\n ctx.indicatorRect = {}\n return\n }\n\n const radioEl = dom.getActiveRadioEl(ctx)\n if (!radioEl) return\n\n ctx.indicatorCleanup = trackElementRect(radioEl, {\n getRect(el) {\n return dom.getOffsetRect(el)\n },\n onChange(rect) {\n ctx.indicatorRect = dom.resolveRect(rect)\n nextTick(() => {\n ctx.canIndicatorTransition = false\n })\n },\n })\n },\n },\n },\n )\n}\n"],"mappings":"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","names":["import_dom_query","import_dom_query","ctx"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/radio-group.anatomy.ts","../src/radio-group.connect.ts","../src/radio-group.dom.ts","../src/radio-group.machine.ts"],"sourcesContent":["export { anatomy } from \"./radio-group.anatomy\"\nexport { connect } from \"./radio-group.connect\"\nexport { machine } from \"./radio-group.machine\"\nexport type { UserDefinedContext as Context, MachineApi as Api } from \"./radio-group.types\"\n","import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"radio-group\").parts(\n \"root\",\n \"label\",\n \"radio\",\n \"radioLabel\",\n \"radioControl\",\n \"indicator\",\n)\nexport const parts = anatomy.build()\n","import { ariaAttr, dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { visuallyHiddenStyle } from \"@zag-js/visually-hidden\"\nimport { parts } from \"./radio-group.anatomy\"\nimport { dom } from \"./radio-group.dom\"\nimport type { InputProps, MachineApi, RadioProps, Send, State } from \"./radio-group.types\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const isGroupDisabled = state.context.isDisabled\n\n function getRadioState<T extends RadioProps>(props: T) {\n const radioState = {\n isInvalid: props.invalid,\n isDisabled: props.disabled || isGroupDisabled,\n isChecked: state.context.value === props.value,\n isFocused: state.context.focusedId === props.value,\n isHovered: state.context.hoveredId === props.value,\n isActive: state.context.activeId === props.value,\n }\n return {\n ...radioState,\n isInteractive: !radioState.isDisabled,\n }\n }\n\n function getRadioDataAttrs<T extends RadioProps>(props: T) {\n const radioState = getRadioState(props)\n return {\n \"data-focus\": dataAttr(radioState.isFocused),\n \"data-disabled\": dataAttr(radioState.isDisabled),\n \"data-state\": radioState.isChecked ? \"checked\" : \"unchecked\",\n \"data-hover\": dataAttr(radioState.isHovered),\n \"data-invalid\": dataAttr(radioState.isInvalid),\n \"data-orientation\": state.context.orientation,\n }\n }\n\n const focus = () => {\n const firstEnabledAndCheckedInput = dom.getFirstEnabledAndCheckedInputEl(state.context)\n\n if (firstEnabledAndCheckedInput) {\n firstEnabledAndCheckedInput.focus()\n return\n }\n\n const firstEnabledInput = dom.getFirstEnabledInputEl(state.context)\n firstEnabledInput?.focus()\n }\n\n return {\n value: state.context.value,\n\n setValue(value: string) {\n send({ type: \"SET_VALUE\", value, manual: true })\n },\n\n clearValue() {\n send({ type: \"SET_VALUE\", value: null, manual: true })\n },\n\n focus,\n\n blur() {\n const focusedElement = dom.getActiveElement(state.context)\n const inputEls = dom.getInputEls(state.context)\n const radioHiddenInputIsFocused = inputEls.some((el) => el === focusedElement)\n if (radioHiddenInputIsFocused) focusedElement?.blur()\n },\n\n getRadioState,\n\n rootProps: normalize.element({\n ...parts.root.attrs,\n role: \"radiogroup\",\n id: dom.getRootId(state.context),\n \"aria-labelledby\": dom.getLabelId(state.context),\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"aria-orientation\": state.context.orientation,\n dir: state.context.dir,\n }),\n\n labelProps: normalize.element({\n ...parts.label.attrs,\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n id: dom.getLabelId(state.context),\n onClick: focus,\n }),\n\n getRadioProps(props: RadioProps) {\n const rootState = getRadioState(props)\n\n return normalize.label({\n ...parts.radio.attrs,\n id: dom.getRadioId(state.context, props.value),\n htmlFor: dom.getRadioHiddenInputId(state.context, props.value),\n ...getRadioDataAttrs(props),\n\n onPointerMove() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: props.value, hovered: true })\n },\n onPointerLeave() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: null })\n },\n onPointerDown(event) {\n if (!rootState.isInteractive) return\n // On pointerdown, the input blurs and returns focus to the `body`,\n // we need to prevent this.\n if (rootState.isFocused && event.pointerType === \"mouse\") {\n event.preventDefault()\n }\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n },\n onPointerUp() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_ACTIVE\", value: null })\n },\n })\n },\n\n getRadioLabelProps(props: RadioProps) {\n return normalize.element({\n ...parts.radioLabel.attrs,\n id: dom.getRadioLabelId(state.context, props.value),\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioControlProps(props: RadioProps) {\n const controlState = getRadioState(props)\n\n return normalize.element({\n ...parts.radioControl.attrs,\n id: dom.getRadioControlId(state.context, props.value),\n \"data-active\": dataAttr(controlState.isActive),\n \"aria-hidden\": true,\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioHiddenInputProps(props: InputProps) {\n const inputState = getRadioState(props)\n\n const isRequired = props.required\n const trulyDisabled = inputState.isDisabled && !props.focusable\n\n return normalize.input({\n \"data-ownedby\": dom.getRootId(state.context),\n id: dom.getRadioHiddenInputId(state.context, props.value),\n type: \"radio\",\n name: state.context.name || state.context.id,\n form: state.context.form,\n value: props.value,\n onChange(event) {\n if (inputState.isDisabled) return\n\n if (event.target.checked) {\n send({ type: \"SET_VALUE\", value: props.value })\n }\n },\n onBlur() {\n send({ type: \"SET_FOCUSED\", value: null })\n },\n onFocus() {\n send({ type: \"SET_FOCUSED\", value: props.value, focused: true })\n },\n onKeyDown(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n }\n },\n onKeyUp(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: null })\n }\n },\n disabled: trulyDisabled,\n required: isRequired,\n defaultChecked: inputState.isChecked,\n \"data-disabled\": dataAttr(inputState.isDisabled),\n \"aria-required\": ariaAttr(isRequired),\n \"aria-invalid\": ariaAttr(inputState.isInvalid),\n \"aria-disabled\": ariaAttr(trulyDisabled),\n \"aria-checked\": ariaAttr(inputState.isChecked),\n style: visuallyHiddenStyle,\n })\n },\n\n indicatorProps: normalize.element({\n id: dom.getIndicatorId(state.context),\n ...parts.indicator.attrs,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"data-orientation\": state.context.orientation,\n style: {\n \"--transition-duration\": \"150ms\",\n \"--transition-property\": \"left, top, width, height\",\n position: \"absolute\",\n willChange: \"var(--transition-property)\",\n transitionProperty: \"var(--transition-property)\",\n transitionDuration: state.context.canIndicatorTransition ? \"var(--transition-duration)\" : \"0ms\",\n transitionTimingFunction: \"var(--transition-timing-function)\",\n ...state.context.indicatorRect,\n },\n }),\n }\n}\n","import { createScope, queryAll } from \"@zag-js/dom-query\"\nimport type { MachineContext as Ctx } from \"./radio-group.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `radio-group:${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `radio-group:${ctx.id}:label`,\n getRadioId: (ctx: Ctx, value: string) => ctx.ids?.radio?.(value) ?? `radio-group:${ctx.id}:radio:${value}`,\n getRadioHiddenInputId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioHiddenInput?.(value) ?? `radio-group:${ctx.id}:radio:input:${value}`,\n getRadioControlId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,\n getRadioLabelId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,\n getIndicatorId: (ctx: Ctx) => ctx.ids?.indicator ?? `radio-group:${ctx.id}:indicator`,\n\n getRootEl: (ctx: Ctx) => dom.getById(ctx, dom.getRootId(ctx)),\n getRadioHiddenInputEl: (ctx: Ctx, value: string) =>\n dom.getById<HTMLInputElement>(ctx, dom.getRadioHiddenInputId(ctx, value)),\n getIndicatorEl: (ctx: Ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),\n\n getFirstEnabledInputEl: (ctx: Ctx) => dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled)\"),\n getFirstEnabledAndCheckedInputEl: (ctx: Ctx) =>\n dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled):checked\"),\n\n getInputEls: (ctx: Ctx) => {\n const ownerId = CSS.escape(dom.getRootId(ctx))\n const selector = `input[type=radio][data-ownedby='${ownerId}']:not([disabled])`\n return queryAll<HTMLInputElement>(dom.getRootEl(ctx), selector)\n },\n\n getActiveRadioEl: (ctx: Ctx) => {\n if (!ctx.value) return\n return dom.getById(ctx, dom.getRadioId(ctx, ctx.value))\n },\n\n getOffsetRect: (el: HTMLElement | undefined) => ({\n left: el?.offsetLeft ?? 0,\n top: el?.offsetTop ?? 0,\n width: el?.offsetWidth ?? 0,\n height: el?.offsetHeight ?? 0,\n }),\n\n getRectById: (ctx: Ctx, id: string) => {\n const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id))\n if (!radioEl) return\n return dom.resolveRect(dom.getOffsetRect(radioEl))\n },\n\n resolveRect: (rect: Record<\"width\" | \"height\" | \"left\" | \"top\", number>) => ({\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n }),\n})\n","import { createMachine } from \"@zag-js/core\"\nimport { nextTick } from \"@zag-js/dom-query\"\nimport { trackElementRect } from \"@zag-js/element-rect\"\nimport { trackFormControl } from \"@zag-js/form-utils\"\nimport { compact, isString } from \"@zag-js/utils\"\nimport { dom } from \"./radio-group.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./radio-group.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"radio\",\n initial: \"idle\",\n context: {\n value: null,\n activeId: null,\n focusedId: null,\n hoveredId: null,\n disabled: false,\n ...ctx,\n indicatorRect: {},\n canIndicatorTransition: false,\n fieldsetDisabled: false,\n },\n\n computed: {\n isDisabled: (ctx) => !!ctx.disabled || ctx.fieldsetDisabled,\n },\n\n entry: [\"syncIndicatorRect\"],\n\n exit: [\"cleanupObserver\"],\n\n activities: [\"trackFormControlState\"],\n\n watch: {\n value: [\"setIndicatorTransition\", \"syncIndicatorRect\", \"syncInputElements\"],\n },\n\n on: {\n SET_VALUE: {\n actions: [\"setValue\"],\n },\n SET_HOVERED: {\n actions: \"setHovered\",\n },\n SET_ACTIVE: {\n actions: \"setActive\",\n },\n SET_FOCUSED: {\n actions: \"setFocused\",\n },\n },\n\n states: {\n idle: {},\n },\n },\n\n {\n activities: {\n trackFormControlState(ctx, _evt, { send, initialContext }) {\n return trackFormControl(dom.getRootEl(ctx), {\n onFieldsetDisabledChange(disabled) {\n ctx.fieldsetDisabled = disabled\n },\n onFormReset() {\n send({ type: \"SET_VALUE\", value: initialContext.value })\n },\n })\n },\n },\n\n actions: {\n setValue(ctx, evt) {\n set.value(ctx, evt.value)\n },\n setHovered(ctx, evt) {\n ctx.hoveredId = evt.value\n },\n setActive(ctx, evt) {\n ctx.activeId = evt.value\n },\n setFocused(ctx, evt) {\n ctx.focusedId = evt.value\n },\n syncInputElements(ctx) {\n const inputs = dom.getInputEls(ctx)\n inputs.forEach((input) => {\n input.checked = input.value === ctx.value\n })\n },\n setIndicatorTransition(ctx) {\n ctx.canIndicatorTransition = isString(ctx.value)\n },\n cleanupObserver(ctx) {\n ctx.indicatorCleanup?.()\n },\n syncIndicatorRect(ctx) {\n ctx.indicatorCleanup?.()\n\n if (!dom.getIndicatorEl(ctx)) return\n\n const value = ctx.value\n\n if (value == null) {\n ctx.indicatorRect = {}\n return\n }\n\n const radioEl = dom.getActiveRadioEl(ctx)\n if (!radioEl) return\n\n ctx.indicatorCleanup = trackElementRect(radioEl, {\n getRect(el) {\n return dom.getOffsetRect(el)\n },\n onChange(rect) {\n ctx.indicatorRect = dom.resolveRect(rect)\n nextTick(() => {\n ctx.canIndicatorTransition = false\n })\n },\n })\n },\n },\n },\n )\n}\n\nconst invoke = {\n change: (ctx: MachineContext) => {\n if (ctx.value == null) return\n ctx.onChange?.({ value: ctx.value })\n },\n}\n\nconst set = {\n value: (ctx: MachineContext, value: string) => {\n ctx.value = value\n invoke.change(ctx)\n },\n}\n"],"mappings":"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","names":["import_dom_query","import_dom_query","ctx"]}
package/dist/index.mjs CHANGED
@@ -23,7 +23,7 @@ var dom = createScope({
23
23
  getRadioHiddenInputId: (ctx, value) => ctx.ids?.radioHiddenInput?.(value) ?? `radio-group:${ctx.id}:radio:input:${value}`,
24
24
  getRadioControlId: (ctx, value) => ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,
25
25
  getRadioLabelId: (ctx, value) => ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,
26
- getIndicatorId: (ctx) => ctx.ids?.indicator ?? `tabs:${ctx.id}:indicator`,
26
+ getIndicatorId: (ctx) => ctx.ids?.indicator ?? `radio-group:${ctx.id}:indicator`,
27
27
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
28
28
  getRadioHiddenInputEl: (ctx, value) => dom.getById(ctx, dom.getRadioHiddenInputId(ctx, value)),
29
29
  getIndicatorEl: (ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),
@@ -39,33 +39,29 @@ var dom = createScope({
39
39
  return;
40
40
  return dom.getById(ctx, dom.getRadioId(ctx, ctx.value));
41
41
  },
42
- getOffsetRect: (el) => {
43
- return {
44
- left: el?.offsetLeft ?? 0,
45
- top: el?.offsetTop ?? 0,
46
- width: el?.offsetWidth ?? 0,
47
- height: el?.offsetHeight ?? 0
48
- };
49
- },
42
+ getOffsetRect: (el) => ({
43
+ left: el?.offsetLeft ?? 0,
44
+ top: el?.offsetTop ?? 0,
45
+ width: el?.offsetWidth ?? 0,
46
+ height: el?.offsetHeight ?? 0
47
+ }),
50
48
  getRectById: (ctx, id) => {
51
49
  const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id));
52
50
  if (!radioEl)
53
51
  return;
54
52
  return dom.resolveRect(dom.getOffsetRect(radioEl));
55
53
  },
56
- resolveRect(rect) {
57
- return {
58
- width: `${rect.width}px`,
59
- height: `${rect.height}px`,
60
- left: `${rect.left}px`,
61
- top: `${rect.top}px`
62
- };
63
- }
54
+ resolveRect: (rect) => ({
55
+ width: `${rect.width}px`,
56
+ height: `${rect.height}px`,
57
+ left: `${rect.left}px`,
58
+ top: `${rect.top}px`
59
+ })
64
60
  });
65
61
 
66
62
  // src/radio-group.connect.ts
67
63
  function connect(state, send, normalize) {
68
- const isGroupDisabled = state.context.disabled;
64
+ const isGroupDisabled = state.context.isDisabled;
69
65
  function getRadioState(props) {
70
66
  const radioState = {
71
67
  isInvalid: props.invalid,
@@ -264,15 +260,20 @@ function machine(userContext) {
264
260
  activeId: null,
265
261
  focusedId: null,
266
262
  hoveredId: null,
263
+ disabled: false,
264
+ ...ctx,
267
265
  indicatorRect: {},
268
266
  canIndicatorTransition: false,
269
- ...ctx
267
+ fieldsetDisabled: false
268
+ },
269
+ computed: {
270
+ isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled
270
271
  },
271
272
  entry: ["syncIndicatorRect"],
272
273
  exit: ["cleanupObserver"],
273
274
  activities: ["trackFormControlState"],
274
275
  watch: {
275
- value: ["setIndicatorTransition", "invokeOnChange", "syncIndicatorRect", "syncInputElements"]
276
+ value: ["setIndicatorTransition", "syncIndicatorRect", "syncInputElements"]
276
277
  },
277
278
  on: {
278
279
  SET_VALUE: {
@@ -296,8 +297,8 @@ function machine(userContext) {
296
297
  activities: {
297
298
  trackFormControlState(ctx2, _evt, { send, initialContext }) {
298
299
  return trackFormControl(dom.getRootEl(ctx2), {
299
- onFieldsetDisabled() {
300
- ctx2.disabled = true;
300
+ onFieldsetDisabledChange(disabled) {
301
+ ctx2.fieldsetDisabled = disabled;
301
302
  },
302
303
  onFormReset() {
303
304
  send({ type: "SET_VALUE", value: initialContext.value });
@@ -307,7 +308,7 @@ function machine(userContext) {
307
308
  },
308
309
  actions: {
309
310
  setValue(ctx2, evt) {
310
- ctx2.value = evt.value;
311
+ set.value(ctx2, evt.value);
311
312
  },
312
313
  setHovered(ctx2, evt) {
313
314
  ctx2.hoveredId = evt.value;
@@ -318,9 +319,6 @@ function machine(userContext) {
318
319
  setFocused(ctx2, evt) {
319
320
  ctx2.focusedId = evt.value;
320
321
  },
321
- invokeOnChange(ctx2, evt) {
322
- ctx2.onChange?.({ value: evt.value });
323
- },
324
322
  syncInputElements(ctx2) {
325
323
  const inputs = dom.getInputEls(ctx2);
326
324
  inputs.forEach((input) => {
@@ -361,6 +359,19 @@ function machine(userContext) {
361
359
  }
362
360
  );
363
361
  }
362
+ var invoke = {
363
+ change: (ctx) => {
364
+ if (ctx.value == null)
365
+ return;
366
+ ctx.onChange?.({ value: ctx.value });
367
+ }
368
+ };
369
+ var set = {
370
+ value: (ctx, value) => {
371
+ ctx.value = value;
372
+ invoke.change(ctx);
373
+ }
374
+ };
364
375
  export {
365
376
  anatomy,
366
377
  connect,
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/radio-group.anatomy.ts","../src/radio-group.connect.ts","../src/radio-group.dom.ts","../src/radio-group.machine.ts"],"sourcesContent":["import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"radio-group\").parts(\n \"root\",\n \"label\",\n \"radio\",\n \"radioLabel\",\n \"radioControl\",\n \"indicator\",\n)\nexport const parts = anatomy.build()\n","import { ariaAttr, dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { visuallyHiddenStyle } from \"@zag-js/visually-hidden\"\nimport { parts } from \"./radio-group.anatomy\"\nimport { dom } from \"./radio-group.dom\"\nimport type { InputProps, PublicApi, RadioProps, Send, State } from \"./radio-group.types\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): PublicApi<T> {\n const isGroupDisabled = state.context.disabled\n\n function getRadioState<T extends RadioProps>(props: T) {\n const radioState = {\n isInvalid: props.invalid,\n isDisabled: props.disabled || isGroupDisabled,\n isChecked: state.context.value === props.value,\n isFocused: state.context.focusedId === props.value,\n isHovered: state.context.hoveredId === props.value,\n isActive: state.context.activeId === props.value,\n }\n return {\n ...radioState,\n isInteractive: !radioState.isDisabled,\n }\n }\n\n function getRadioDataAttrs<T extends RadioProps>(props: T) {\n const radioState = getRadioState(props)\n return {\n \"data-focus\": dataAttr(radioState.isFocused),\n \"data-disabled\": dataAttr(radioState.isDisabled),\n \"data-state\": radioState.isChecked ? \"checked\" : \"unchecked\",\n \"data-hover\": dataAttr(radioState.isHovered),\n \"data-invalid\": dataAttr(radioState.isInvalid),\n \"data-orientation\": state.context.orientation,\n }\n }\n\n const focus = () => {\n const firstEnabledAndCheckedInput = dom.getFirstEnabledAndCheckedInputEl(state.context)\n\n if (firstEnabledAndCheckedInput) {\n firstEnabledAndCheckedInput.focus()\n return\n }\n\n const firstEnabledInput = dom.getFirstEnabledInputEl(state.context)\n firstEnabledInput?.focus()\n }\n\n return {\n value: state.context.value,\n\n setValue(value: string) {\n send({ type: \"SET_VALUE\", value, manual: true })\n },\n\n clearValue() {\n send({ type: \"SET_VALUE\", value: null, manual: true })\n },\n\n focus,\n\n blur() {\n const focusedElement = dom.getActiveElement(state.context)\n const inputEls = dom.getInputEls(state.context)\n const radioHiddenInputIsFocused = inputEls.some((el) => el === focusedElement)\n if (radioHiddenInputIsFocused) focusedElement?.blur()\n },\n\n getRadioState,\n\n rootProps: normalize.element({\n ...parts.root.attrs,\n role: \"radiogroup\",\n id: dom.getRootId(state.context),\n \"aria-labelledby\": dom.getLabelId(state.context),\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"aria-orientation\": state.context.orientation,\n dir: state.context.dir,\n }),\n\n labelProps: normalize.element({\n ...parts.label.attrs,\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n id: dom.getLabelId(state.context),\n onClick: focus,\n }),\n\n getRadioProps(props: RadioProps) {\n const rootState = getRadioState(props)\n\n return normalize.label({\n ...parts.radio.attrs,\n id: dom.getRadioId(state.context, props.value),\n htmlFor: dom.getRadioHiddenInputId(state.context, props.value),\n ...getRadioDataAttrs(props),\n\n onPointerMove() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: props.value, hovered: true })\n },\n onPointerLeave() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: null })\n },\n onPointerDown(event) {\n if (!rootState.isInteractive) return\n // On pointerdown, the input blurs and returns focus to the `body`,\n // we need to prevent this.\n if (rootState.isFocused && event.pointerType === \"mouse\") {\n event.preventDefault()\n }\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n },\n onPointerUp() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_ACTIVE\", value: null })\n },\n })\n },\n\n getRadioLabelProps(props: RadioProps) {\n return normalize.element({\n ...parts.radioLabel.attrs,\n id: dom.getRadioLabelId(state.context, props.value),\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioControlProps(props: RadioProps) {\n const controlState = getRadioState(props)\n\n return normalize.element({\n ...parts.radioControl.attrs,\n id: dom.getRadioControlId(state.context, props.value),\n \"data-active\": dataAttr(controlState.isActive),\n \"aria-hidden\": true,\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioHiddenInputProps(props: InputProps) {\n const inputState = getRadioState(props)\n\n const isRequired = props.required\n const trulyDisabled = inputState.isDisabled && !props.focusable\n\n return normalize.input({\n \"data-ownedby\": dom.getRootId(state.context),\n id: dom.getRadioHiddenInputId(state.context, props.value),\n type: \"radio\",\n name: state.context.name || state.context.id,\n form: state.context.form,\n value: props.value,\n onChange(event) {\n if (inputState.isDisabled) return\n\n if (event.target.checked) {\n send({ type: \"SET_VALUE\", value: props.value })\n }\n },\n onBlur() {\n send({ type: \"SET_FOCUSED\", value: null })\n },\n onFocus() {\n send({ type: \"SET_FOCUSED\", value: props.value, focused: true })\n },\n onKeyDown(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n }\n },\n onKeyUp(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: null })\n }\n },\n disabled: trulyDisabled,\n required: isRequired,\n defaultChecked: inputState.isChecked,\n \"data-disabled\": dataAttr(inputState.isDisabled),\n \"aria-required\": ariaAttr(isRequired),\n \"aria-invalid\": ariaAttr(inputState.isInvalid),\n \"aria-disabled\": ariaAttr(trulyDisabled),\n \"aria-checked\": ariaAttr(inputState.isChecked),\n style: visuallyHiddenStyle,\n })\n },\n\n indicatorProps: normalize.element({\n id: dom.getIndicatorId(state.context),\n ...parts.indicator.attrs,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"data-orientation\": state.context.orientation,\n style: {\n \"--transition-duration\": \"150ms\",\n \"--transition-property\": \"left, top, width, height\",\n position: \"absolute\",\n willChange: \"var(--transition-property)\",\n transitionProperty: \"var(--transition-property)\",\n transitionDuration: state.context.canIndicatorTransition ? \"var(--transition-duration)\" : \"0ms\",\n transitionTimingFunction: \"var(--transition-timing-function)\",\n ...state.context.indicatorRect,\n },\n }),\n }\n}\n","import { createScope, queryAll } from \"@zag-js/dom-query\"\nimport type { MachineContext as Ctx } from \"./radio-group.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `radio-group:${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `radio-group:${ctx.id}:label`,\n getRadioId: (ctx: Ctx, value: string) => ctx.ids?.radio?.(value) ?? `radio-group:${ctx.id}:radio:${value}`,\n getRadioHiddenInputId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioHiddenInput?.(value) ?? `radio-group:${ctx.id}:radio:input:${value}`,\n getRadioControlId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,\n getRadioLabelId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,\n getIndicatorId: (ctx: Ctx) => ctx.ids?.indicator ?? `tabs:${ctx.id}:indicator`,\n\n getRootEl: (ctx: Ctx) => dom.getById(ctx, dom.getRootId(ctx)),\n getRadioHiddenInputEl: (ctx: Ctx, value: string) =>\n dom.getById<HTMLInputElement>(ctx, dom.getRadioHiddenInputId(ctx, value)),\n getIndicatorEl: (ctx: Ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),\n\n getFirstEnabledInputEl: (ctx: Ctx) => dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled)\"),\n getFirstEnabledAndCheckedInputEl: (ctx: Ctx) =>\n dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled):checked\"),\n\n getInputEls: (ctx: Ctx) => {\n const ownerId = CSS.escape(dom.getRootId(ctx))\n const selector = `input[type=radio][data-ownedby='${ownerId}']:not([disabled])`\n return queryAll<HTMLInputElement>(dom.getRootEl(ctx), selector)\n },\n\n getActiveRadioEl: (ctx: Ctx) => {\n if (!ctx.value) return\n return dom.getById(ctx, dom.getRadioId(ctx, ctx.value))\n },\n\n getOffsetRect: (el: HTMLElement | undefined) => {\n return {\n left: el?.offsetLeft ?? 0,\n top: el?.offsetTop ?? 0,\n width: el?.offsetWidth ?? 0,\n height: el?.offsetHeight ?? 0,\n }\n },\n\n getRectById: (ctx: Ctx, id: string) => {\n const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id))\n if (!radioEl) return\n return dom.resolveRect(dom.getOffsetRect(radioEl))\n },\n\n resolveRect(rect: Record<\"width\" | \"height\" | \"left\" | \"top\", number>) {\n return {\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n }\n },\n})\n","import { createMachine } from \"@zag-js/core\"\nimport { nextTick } from \"@zag-js/dom-query\"\nimport { trackElementRect } from \"@zag-js/element-rect\"\nimport { trackFormControl } from \"@zag-js/form-utils\"\nimport { compact, isString } from \"@zag-js/utils\"\nimport { dom } from \"./radio-group.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./radio-group.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"radio\",\n initial: \"idle\",\n context: {\n value: null,\n activeId: null,\n focusedId: null,\n hoveredId: null,\n indicatorRect: {},\n canIndicatorTransition: false,\n ...ctx,\n },\n\n entry: [\"syncIndicatorRect\"],\n\n exit: [\"cleanupObserver\"],\n\n activities: [\"trackFormControlState\"],\n\n watch: {\n value: [\"setIndicatorTransition\", \"invokeOnChange\", \"syncIndicatorRect\", \"syncInputElements\"],\n },\n\n on: {\n SET_VALUE: {\n actions: [\"setValue\"],\n },\n SET_HOVERED: {\n actions: \"setHovered\",\n },\n SET_ACTIVE: {\n actions: \"setActive\",\n },\n SET_FOCUSED: {\n actions: \"setFocused\",\n },\n },\n\n states: {\n idle: {},\n },\n },\n\n {\n activities: {\n trackFormControlState(ctx, _evt, { send, initialContext }) {\n return trackFormControl(dom.getRootEl(ctx), {\n onFieldsetDisabled() {\n ctx.disabled = true\n },\n onFormReset() {\n send({ type: \"SET_VALUE\", value: initialContext.value })\n },\n })\n },\n },\n\n actions: {\n setValue(ctx, evt) {\n ctx.value = evt.value\n },\n setHovered(ctx, evt) {\n ctx.hoveredId = evt.value\n },\n setActive(ctx, evt) {\n ctx.activeId = evt.value\n },\n setFocused(ctx, evt) {\n ctx.focusedId = evt.value\n },\n invokeOnChange(ctx, evt) {\n ctx.onChange?.({ value: evt.value })\n },\n syncInputElements(ctx) {\n const inputs = dom.getInputEls(ctx)\n inputs.forEach((input) => {\n input.checked = input.value === ctx.value\n })\n },\n setIndicatorTransition(ctx) {\n ctx.canIndicatorTransition = isString(ctx.value)\n },\n cleanupObserver(ctx) {\n ctx.indicatorCleanup?.()\n },\n syncIndicatorRect(ctx) {\n ctx.indicatorCleanup?.()\n\n if (!dom.getIndicatorEl(ctx)) return\n\n const value = ctx.value\n\n if (value == null) {\n ctx.indicatorRect = {}\n return\n }\n\n const radioEl = dom.getActiveRadioEl(ctx)\n if (!radioEl) return\n\n ctx.indicatorCleanup = trackElementRect(radioEl, {\n getRect(el) {\n return dom.getOffsetRect(el)\n },\n onChange(rect) {\n ctx.indicatorRect = dom.resolveRect(rect)\n nextTick(() => {\n ctx.canIndicatorTransition = false\n })\n },\n })\n },\n },\n },\n )\n}\n"],"mappings":"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","names":["ctx"]}
1
+ {"version":3,"sources":["../src/radio-group.anatomy.ts","../src/radio-group.connect.ts","../src/radio-group.dom.ts","../src/radio-group.machine.ts"],"sourcesContent":["import { createAnatomy } from \"@zag-js/anatomy\"\n\nexport const anatomy = createAnatomy(\"radio-group\").parts(\n \"root\",\n \"label\",\n \"radio\",\n \"radioLabel\",\n \"radioControl\",\n \"indicator\",\n)\nexport const parts = anatomy.build()\n","import { ariaAttr, dataAttr } from \"@zag-js/dom-query\"\nimport type { NormalizeProps, PropTypes } from \"@zag-js/types\"\nimport { visuallyHiddenStyle } from \"@zag-js/visually-hidden\"\nimport { parts } from \"./radio-group.anatomy\"\nimport { dom } from \"./radio-group.dom\"\nimport type { InputProps, MachineApi, RadioProps, Send, State } from \"./radio-group.types\"\n\nexport function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {\n const isGroupDisabled = state.context.isDisabled\n\n function getRadioState<T extends RadioProps>(props: T) {\n const radioState = {\n isInvalid: props.invalid,\n isDisabled: props.disabled || isGroupDisabled,\n isChecked: state.context.value === props.value,\n isFocused: state.context.focusedId === props.value,\n isHovered: state.context.hoveredId === props.value,\n isActive: state.context.activeId === props.value,\n }\n return {\n ...radioState,\n isInteractive: !radioState.isDisabled,\n }\n }\n\n function getRadioDataAttrs<T extends RadioProps>(props: T) {\n const radioState = getRadioState(props)\n return {\n \"data-focus\": dataAttr(radioState.isFocused),\n \"data-disabled\": dataAttr(radioState.isDisabled),\n \"data-state\": radioState.isChecked ? \"checked\" : \"unchecked\",\n \"data-hover\": dataAttr(radioState.isHovered),\n \"data-invalid\": dataAttr(radioState.isInvalid),\n \"data-orientation\": state.context.orientation,\n }\n }\n\n const focus = () => {\n const firstEnabledAndCheckedInput = dom.getFirstEnabledAndCheckedInputEl(state.context)\n\n if (firstEnabledAndCheckedInput) {\n firstEnabledAndCheckedInput.focus()\n return\n }\n\n const firstEnabledInput = dom.getFirstEnabledInputEl(state.context)\n firstEnabledInput?.focus()\n }\n\n return {\n value: state.context.value,\n\n setValue(value: string) {\n send({ type: \"SET_VALUE\", value, manual: true })\n },\n\n clearValue() {\n send({ type: \"SET_VALUE\", value: null, manual: true })\n },\n\n focus,\n\n blur() {\n const focusedElement = dom.getActiveElement(state.context)\n const inputEls = dom.getInputEls(state.context)\n const radioHiddenInputIsFocused = inputEls.some((el) => el === focusedElement)\n if (radioHiddenInputIsFocused) focusedElement?.blur()\n },\n\n getRadioState,\n\n rootProps: normalize.element({\n ...parts.root.attrs,\n role: \"radiogroup\",\n id: dom.getRootId(state.context),\n \"aria-labelledby\": dom.getLabelId(state.context),\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"aria-orientation\": state.context.orientation,\n dir: state.context.dir,\n }),\n\n labelProps: normalize.element({\n ...parts.label.attrs,\n \"data-orientation\": state.context.orientation,\n \"data-disabled\": dataAttr(isGroupDisabled),\n id: dom.getLabelId(state.context),\n onClick: focus,\n }),\n\n getRadioProps(props: RadioProps) {\n const rootState = getRadioState(props)\n\n return normalize.label({\n ...parts.radio.attrs,\n id: dom.getRadioId(state.context, props.value),\n htmlFor: dom.getRadioHiddenInputId(state.context, props.value),\n ...getRadioDataAttrs(props),\n\n onPointerMove() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: props.value, hovered: true })\n },\n onPointerLeave() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_HOVERED\", value: null })\n },\n onPointerDown(event) {\n if (!rootState.isInteractive) return\n // On pointerdown, the input blurs and returns focus to the `body`,\n // we need to prevent this.\n if (rootState.isFocused && event.pointerType === \"mouse\") {\n event.preventDefault()\n }\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n },\n onPointerUp() {\n if (!rootState.isInteractive) return\n send({ type: \"SET_ACTIVE\", value: null })\n },\n })\n },\n\n getRadioLabelProps(props: RadioProps) {\n return normalize.element({\n ...parts.radioLabel.attrs,\n id: dom.getRadioLabelId(state.context, props.value),\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioControlProps(props: RadioProps) {\n const controlState = getRadioState(props)\n\n return normalize.element({\n ...parts.radioControl.attrs,\n id: dom.getRadioControlId(state.context, props.value),\n \"data-active\": dataAttr(controlState.isActive),\n \"aria-hidden\": true,\n ...getRadioDataAttrs(props),\n })\n },\n\n getRadioHiddenInputProps(props: InputProps) {\n const inputState = getRadioState(props)\n\n const isRequired = props.required\n const trulyDisabled = inputState.isDisabled && !props.focusable\n\n return normalize.input({\n \"data-ownedby\": dom.getRootId(state.context),\n id: dom.getRadioHiddenInputId(state.context, props.value),\n type: \"radio\",\n name: state.context.name || state.context.id,\n form: state.context.form,\n value: props.value,\n onChange(event) {\n if (inputState.isDisabled) return\n\n if (event.target.checked) {\n send({ type: \"SET_VALUE\", value: props.value })\n }\n },\n onBlur() {\n send({ type: \"SET_FOCUSED\", value: null })\n },\n onFocus() {\n send({ type: \"SET_FOCUSED\", value: props.value, focused: true })\n },\n onKeyDown(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: props.value, active: true })\n }\n },\n onKeyUp(event) {\n if (event.key === \" \") {\n send({ type: \"SET_ACTIVE\", value: null })\n }\n },\n disabled: trulyDisabled,\n required: isRequired,\n defaultChecked: inputState.isChecked,\n \"data-disabled\": dataAttr(inputState.isDisabled),\n \"aria-required\": ariaAttr(isRequired),\n \"aria-invalid\": ariaAttr(inputState.isInvalid),\n \"aria-disabled\": ariaAttr(trulyDisabled),\n \"aria-checked\": ariaAttr(inputState.isChecked),\n style: visuallyHiddenStyle,\n })\n },\n\n indicatorProps: normalize.element({\n id: dom.getIndicatorId(state.context),\n ...parts.indicator.attrs,\n \"data-disabled\": dataAttr(isGroupDisabled),\n \"data-orientation\": state.context.orientation,\n style: {\n \"--transition-duration\": \"150ms\",\n \"--transition-property\": \"left, top, width, height\",\n position: \"absolute\",\n willChange: \"var(--transition-property)\",\n transitionProperty: \"var(--transition-property)\",\n transitionDuration: state.context.canIndicatorTransition ? \"var(--transition-duration)\" : \"0ms\",\n transitionTimingFunction: \"var(--transition-timing-function)\",\n ...state.context.indicatorRect,\n },\n }),\n }\n}\n","import { createScope, queryAll } from \"@zag-js/dom-query\"\nimport type { MachineContext as Ctx } from \"./radio-group.types\"\n\nexport const dom = createScope({\n getRootId: (ctx: Ctx) => ctx.ids?.root ?? `radio-group:${ctx.id}`,\n getLabelId: (ctx: Ctx) => ctx.ids?.label ?? `radio-group:${ctx.id}:label`,\n getRadioId: (ctx: Ctx, value: string) => ctx.ids?.radio?.(value) ?? `radio-group:${ctx.id}:radio:${value}`,\n getRadioHiddenInputId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioHiddenInput?.(value) ?? `radio-group:${ctx.id}:radio:input:${value}`,\n getRadioControlId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,\n getRadioLabelId: (ctx: Ctx, value: string) =>\n ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,\n getIndicatorId: (ctx: Ctx) => ctx.ids?.indicator ?? `radio-group:${ctx.id}:indicator`,\n\n getRootEl: (ctx: Ctx) => dom.getById(ctx, dom.getRootId(ctx)),\n getRadioHiddenInputEl: (ctx: Ctx, value: string) =>\n dom.getById<HTMLInputElement>(ctx, dom.getRadioHiddenInputId(ctx, value)),\n getIndicatorEl: (ctx: Ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),\n\n getFirstEnabledInputEl: (ctx: Ctx) => dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled)\"),\n getFirstEnabledAndCheckedInputEl: (ctx: Ctx) =>\n dom.getRootEl(ctx)?.querySelector<HTMLInputElement>(\"input:not(:disabled):checked\"),\n\n getInputEls: (ctx: Ctx) => {\n const ownerId = CSS.escape(dom.getRootId(ctx))\n const selector = `input[type=radio][data-ownedby='${ownerId}']:not([disabled])`\n return queryAll<HTMLInputElement>(dom.getRootEl(ctx), selector)\n },\n\n getActiveRadioEl: (ctx: Ctx) => {\n if (!ctx.value) return\n return dom.getById(ctx, dom.getRadioId(ctx, ctx.value))\n },\n\n getOffsetRect: (el: HTMLElement | undefined) => ({\n left: el?.offsetLeft ?? 0,\n top: el?.offsetTop ?? 0,\n width: el?.offsetWidth ?? 0,\n height: el?.offsetHeight ?? 0,\n }),\n\n getRectById: (ctx: Ctx, id: string) => {\n const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id))\n if (!radioEl) return\n return dom.resolveRect(dom.getOffsetRect(radioEl))\n },\n\n resolveRect: (rect: Record<\"width\" | \"height\" | \"left\" | \"top\", number>) => ({\n width: `${rect.width}px`,\n height: `${rect.height}px`,\n left: `${rect.left}px`,\n top: `${rect.top}px`,\n }),\n})\n","import { createMachine } from \"@zag-js/core\"\nimport { nextTick } from \"@zag-js/dom-query\"\nimport { trackElementRect } from \"@zag-js/element-rect\"\nimport { trackFormControl } from \"@zag-js/form-utils\"\nimport { compact, isString } from \"@zag-js/utils\"\nimport { dom } from \"./radio-group.dom\"\nimport type { MachineContext, MachineState, UserDefinedContext } from \"./radio-group.types\"\n\nexport function machine(userContext: UserDefinedContext) {\n const ctx = compact(userContext)\n return createMachine<MachineContext, MachineState>(\n {\n id: \"radio\",\n initial: \"idle\",\n context: {\n value: null,\n activeId: null,\n focusedId: null,\n hoveredId: null,\n disabled: false,\n ...ctx,\n indicatorRect: {},\n canIndicatorTransition: false,\n fieldsetDisabled: false,\n },\n\n computed: {\n isDisabled: (ctx) => !!ctx.disabled || ctx.fieldsetDisabled,\n },\n\n entry: [\"syncIndicatorRect\"],\n\n exit: [\"cleanupObserver\"],\n\n activities: [\"trackFormControlState\"],\n\n watch: {\n value: [\"setIndicatorTransition\", \"syncIndicatorRect\", \"syncInputElements\"],\n },\n\n on: {\n SET_VALUE: {\n actions: [\"setValue\"],\n },\n SET_HOVERED: {\n actions: \"setHovered\",\n },\n SET_ACTIVE: {\n actions: \"setActive\",\n },\n SET_FOCUSED: {\n actions: \"setFocused\",\n },\n },\n\n states: {\n idle: {},\n },\n },\n\n {\n activities: {\n trackFormControlState(ctx, _evt, { send, initialContext }) {\n return trackFormControl(dom.getRootEl(ctx), {\n onFieldsetDisabledChange(disabled) {\n ctx.fieldsetDisabled = disabled\n },\n onFormReset() {\n send({ type: \"SET_VALUE\", value: initialContext.value })\n },\n })\n },\n },\n\n actions: {\n setValue(ctx, evt) {\n set.value(ctx, evt.value)\n },\n setHovered(ctx, evt) {\n ctx.hoveredId = evt.value\n },\n setActive(ctx, evt) {\n ctx.activeId = evt.value\n },\n setFocused(ctx, evt) {\n ctx.focusedId = evt.value\n },\n syncInputElements(ctx) {\n const inputs = dom.getInputEls(ctx)\n inputs.forEach((input) => {\n input.checked = input.value === ctx.value\n })\n },\n setIndicatorTransition(ctx) {\n ctx.canIndicatorTransition = isString(ctx.value)\n },\n cleanupObserver(ctx) {\n ctx.indicatorCleanup?.()\n },\n syncIndicatorRect(ctx) {\n ctx.indicatorCleanup?.()\n\n if (!dom.getIndicatorEl(ctx)) return\n\n const value = ctx.value\n\n if (value == null) {\n ctx.indicatorRect = {}\n return\n }\n\n const radioEl = dom.getActiveRadioEl(ctx)\n if (!radioEl) return\n\n ctx.indicatorCleanup = trackElementRect(radioEl, {\n getRect(el) {\n return dom.getOffsetRect(el)\n },\n onChange(rect) {\n ctx.indicatorRect = dom.resolveRect(rect)\n nextTick(() => {\n ctx.canIndicatorTransition = false\n })\n },\n })\n },\n },\n },\n )\n}\n\nconst invoke = {\n change: (ctx: MachineContext) => {\n if (ctx.value == null) return\n ctx.onChange?.({ value: ctx.value })\n },\n}\n\nconst set = {\n value: (ctx: MachineContext, value: string) => {\n ctx.value = value\n invoke.change(ctx)\n },\n}\n"],"mappings":"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","names":["ctx"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/radio-group",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
4
4
  "description": "Core logic for the radio group widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -28,14 +28,14 @@
28
28
  "url": "https://github.com/chakra-ui/zag/issues"
29
29
  },
30
30
  "dependencies": {
31
- "@zag-js/anatomy": "0.16.0",
32
- "@zag-js/dom-query": "0.16.0",
33
- "@zag-js/element-rect": "0.16.0",
34
- "@zag-js/form-utils": "0.16.0",
35
- "@zag-js/visually-hidden": "0.16.0",
36
- "@zag-js/utils": "0.16.0",
37
- "@zag-js/core": "0.16.0",
38
- "@zag-js/types": "0.16.0"
31
+ "@zag-js/anatomy": "0.18.0",
32
+ "@zag-js/dom-query": "0.18.0",
33
+ "@zag-js/element-rect": "0.18.0",
34
+ "@zag-js/form-utils": "0.18.0",
35
+ "@zag-js/visually-hidden": "0.18.0",
36
+ "@zag-js/utils": "0.18.0",
37
+ "@zag-js/core": "0.18.0",
38
+ "@zag-js/types": "0.18.0"
39
39
  },
40
40
  "devDependencies": {
41
41
  "clean-package": "2.2.0"
package/src/index.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  export { anatomy } from "./radio-group.anatomy"
2
2
  export { connect } from "./radio-group.connect"
3
3
  export { machine } from "./radio-group.machine"
4
- export type { UserDefinedContext as Context, PublicApi } from "./radio-group.types"
4
+ export type { UserDefinedContext as Context, MachineApi as Api } from "./radio-group.types"
@@ -3,10 +3,10 @@ import type { NormalizeProps, PropTypes } from "@zag-js/types"
3
3
  import { visuallyHiddenStyle } from "@zag-js/visually-hidden"
4
4
  import { parts } from "./radio-group.anatomy"
5
5
  import { dom } from "./radio-group.dom"
6
- import type { InputProps, PublicApi, RadioProps, Send, State } from "./radio-group.types"
6
+ import type { InputProps, MachineApi, RadioProps, Send, State } from "./radio-group.types"
7
7
 
8
- export function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): PublicApi<T> {
9
- const isGroupDisabled = state.context.disabled
8
+ export function connect<T extends PropTypes>(state: State, send: Send, normalize: NormalizeProps<T>): MachineApi<T> {
9
+ const isGroupDisabled = state.context.isDisabled
10
10
 
11
11
  function getRadioState<T extends RadioProps>(props: T) {
12
12
  const radioState = {
@@ -11,7 +11,7 @@ export const dom = createScope({
11
11
  ctx.ids?.radioControl?.(value) ?? `radio-group:${ctx.id}:radio:control:${value}`,
12
12
  getRadioLabelId: (ctx: Ctx, value: string) =>
13
13
  ctx.ids?.radioLabel?.(value) ?? `radio-group:${ctx.id}:radio:label:${value}`,
14
- getIndicatorId: (ctx: Ctx) => ctx.ids?.indicator ?? `tabs:${ctx.id}:indicator`,
14
+ getIndicatorId: (ctx: Ctx) => ctx.ids?.indicator ?? `radio-group:${ctx.id}:indicator`,
15
15
 
16
16
  getRootEl: (ctx: Ctx) => dom.getById(ctx, dom.getRootId(ctx)),
17
17
  getRadioHiddenInputEl: (ctx: Ctx, value: string) =>
@@ -33,14 +33,12 @@ export const dom = createScope({
33
33
  return dom.getById(ctx, dom.getRadioId(ctx, ctx.value))
34
34
  },
35
35
 
36
- getOffsetRect: (el: HTMLElement | undefined) => {
37
- return {
38
- left: el?.offsetLeft ?? 0,
39
- top: el?.offsetTop ?? 0,
40
- width: el?.offsetWidth ?? 0,
41
- height: el?.offsetHeight ?? 0,
42
- }
43
- },
36
+ getOffsetRect: (el: HTMLElement | undefined) => ({
37
+ left: el?.offsetLeft ?? 0,
38
+ top: el?.offsetTop ?? 0,
39
+ width: el?.offsetWidth ?? 0,
40
+ height: el?.offsetHeight ?? 0,
41
+ }),
44
42
 
45
43
  getRectById: (ctx: Ctx, id: string) => {
46
44
  const radioEl = dom.getById(ctx, dom.getRadioId(ctx, id))
@@ -48,12 +46,10 @@ export const dom = createScope({
48
46
  return dom.resolveRect(dom.getOffsetRect(radioEl))
49
47
  },
50
48
 
51
- resolveRect(rect: Record<"width" | "height" | "left" | "top", number>) {
52
- return {
53
- width: `${rect.width}px`,
54
- height: `${rect.height}px`,
55
- left: `${rect.left}px`,
56
- top: `${rect.top}px`,
57
- }
58
- },
49
+ resolveRect: (rect: Record<"width" | "height" | "left" | "top", number>) => ({
50
+ width: `${rect.width}px`,
51
+ height: `${rect.height}px`,
52
+ left: `${rect.left}px`,
53
+ top: `${rect.top}px`,
54
+ }),
59
55
  })
@@ -17,9 +17,15 @@ export function machine(userContext: UserDefinedContext) {
17
17
  activeId: null,
18
18
  focusedId: null,
19
19
  hoveredId: null,
20
+ disabled: false,
21
+ ...ctx,
20
22
  indicatorRect: {},
21
23
  canIndicatorTransition: false,
22
- ...ctx,
24
+ fieldsetDisabled: false,
25
+ },
26
+
27
+ computed: {
28
+ isDisabled: (ctx) => !!ctx.disabled || ctx.fieldsetDisabled,
23
29
  },
24
30
 
25
31
  entry: ["syncIndicatorRect"],
@@ -29,7 +35,7 @@ export function machine(userContext: UserDefinedContext) {
29
35
  activities: ["trackFormControlState"],
30
36
 
31
37
  watch: {
32
- value: ["setIndicatorTransition", "invokeOnChange", "syncIndicatorRect", "syncInputElements"],
38
+ value: ["setIndicatorTransition", "syncIndicatorRect", "syncInputElements"],
33
39
  },
34
40
 
35
41
  on: {
@@ -56,8 +62,8 @@ export function machine(userContext: UserDefinedContext) {
56
62
  activities: {
57
63
  trackFormControlState(ctx, _evt, { send, initialContext }) {
58
64
  return trackFormControl(dom.getRootEl(ctx), {
59
- onFieldsetDisabled() {
60
- ctx.disabled = true
65
+ onFieldsetDisabledChange(disabled) {
66
+ ctx.fieldsetDisabled = disabled
61
67
  },
62
68
  onFormReset() {
63
69
  send({ type: "SET_VALUE", value: initialContext.value })
@@ -68,7 +74,7 @@ export function machine(userContext: UserDefinedContext) {
68
74
 
69
75
  actions: {
70
76
  setValue(ctx, evt) {
71
- ctx.value = evt.value
77
+ set.value(ctx, evt.value)
72
78
  },
73
79
  setHovered(ctx, evt) {
74
80
  ctx.hoveredId = evt.value
@@ -79,9 +85,6 @@ export function machine(userContext: UserDefinedContext) {
79
85
  setFocused(ctx, evt) {
80
86
  ctx.focusedId = evt.value
81
87
  },
82
- invokeOnChange(ctx, evt) {
83
- ctx.onChange?.({ value: evt.value })
84
- },
85
88
  syncInputElements(ctx) {
86
89
  const inputs = dom.getInputEls(ctx)
87
90
  inputs.forEach((input) => {
@@ -125,3 +128,17 @@ export function machine(userContext: UserDefinedContext) {
125
128
  },
126
129
  )
127
130
  }
131
+
132
+ const invoke = {
133
+ change: (ctx: MachineContext) => {
134
+ if (ctx.value == null) return
135
+ ctx.onChange?.({ value: ctx.value })
136
+ },
137
+ }
138
+
139
+ const set = {
140
+ value: (ctx: MachineContext, value: string) => {
141
+ ctx.value = value
142
+ invoke.change(ctx)
143
+ },
144
+ }
@@ -35,10 +35,6 @@ type PublicContext = DirectionProperty &
35
35
  * If `true`, the radio group will be disabled
36
36
  */
37
37
  disabled?: boolean
38
- /**
39
- * If `true`, the radio group will be readonly
40
- */
41
- readOnly?: boolean
42
38
  /**
43
39
  * Function called once a radio is checked
44
40
  * @param value the value of the checked radio
@@ -49,49 +45,6 @@ type PublicContext = DirectionProperty &
49
45
  */
50
46
  orientation?: "horizontal" | "vertical"
51
47
  }
52
- export type PublicApi<T extends PropTypes = PropTypes> = {
53
- /**
54
- * The current value of the radio group
55
- */
56
- value: string | null
57
- /**
58
- * Function to set the value of the radio group
59
- */
60
- setValue(value: string): void
61
- /**
62
- * Function to clear the value of the radio group
63
- */
64
- clearValue(): void
65
- /**
66
- * Function to focus the radio group
67
- */
68
- focus: () => void
69
- /**
70
- * Function to blur the currently focused radio input in the radio group
71
- */
72
- blur(): void
73
- /**
74
- * Returns the state details of a radio input
75
- */
76
- getRadioState: <T_1 extends RadioProps>(
77
- props: T_1,
78
- ) => {
79
- isInteractive: boolean
80
- isInvalid: boolean | undefined
81
- isDisabled: boolean | undefined
82
- isChecked: boolean
83
- isFocused: boolean
84
- isHovered: boolean
85
- isActive: boolean
86
- }
87
- rootProps: T["element"]
88
- labelProps: T["element"]
89
- getRadioProps(props: RadioProps): T["label"]
90
- getRadioLabelProps(props: RadioProps): T["element"]
91
- getRadioControlProps(props: RadioProps): T["element"]
92
- getRadioHiddenInputProps(props: InputProps): T["input"]
93
- indicatorProps: T["element"]
94
- }
95
48
 
96
49
  type PrivateContext = Context<{
97
50
  /**
@@ -124,11 +77,21 @@ type PrivateContext = Context<{
124
77
  * Function to clean up the observer for the active tab's rect
125
78
  */
126
79
  indicatorCleanup?: VoidFunction | null
80
+ /**
81
+ * @internal
82
+ * Whether the radio group's fieldset is disabled
83
+ */
84
+ fieldsetDisabled: boolean
127
85
  }>
128
86
 
129
87
  export type UserDefinedContext = RequiredBy<PublicContext, "id">
130
88
 
131
- type ComputedContext = Readonly<{}>
89
+ type ComputedContext = Readonly<{
90
+ /**
91
+ * Whether the radio group is disabled
92
+ */
93
+ isDisabled: boolean
94
+ }>
132
95
 
133
96
  export type MachineContext = PublicContext & PrivateContext & ComputedContext
134
97
 
@@ -146,10 +109,6 @@ export type RadioProps = {
146
109
  * If `true`, the radio will be disabled
147
110
  */
148
111
  disabled?: boolean
149
- /**
150
- * If `true`, the radio will be readonly
151
- */
152
- readOnly?: boolean
153
112
  /**
154
113
  * If `true`, the radio is marked as invalid.
155
114
  */
@@ -167,3 +126,47 @@ export type InputProps = RadioProps & {
167
126
  */
168
127
  required?: boolean
169
128
  }
129
+
130
+ export type MachineApi<T extends PropTypes = PropTypes> = {
131
+ /**
132
+ * The current value of the radio group
133
+ */
134
+ value: string | null
135
+ /**
136
+ * Function to set the value of the radio group
137
+ */
138
+ setValue(value: string): void
139
+ /**
140
+ * Function to clear the value of the radio group
141
+ */
142
+ clearValue(): void
143
+ /**
144
+ * Function to focus the radio group
145
+ */
146
+ focus: () => void
147
+ /**
148
+ * Function to blur the currently focused radio input in the radio group
149
+ */
150
+ blur(): void
151
+ /**
152
+ * Returns the state details of a radio input
153
+ */
154
+ getRadioState: <T_1 extends RadioProps>(
155
+ props: T_1,
156
+ ) => {
157
+ isInteractive: boolean
158
+ isInvalid: boolean | undefined
159
+ isDisabled: boolean | undefined
160
+ isChecked: boolean
161
+ isFocused: boolean
162
+ isHovered: boolean
163
+ isActive: boolean
164
+ }
165
+ rootProps: T["element"]
166
+ labelProps: T["element"]
167
+ getRadioProps(props: RadioProps): T["label"]
168
+ getRadioLabelProps(props: RadioProps): T["element"]
169
+ getRadioControlProps(props: RadioProps): T["element"]
170
+ getRadioHiddenInputProps(props: InputProps): T["input"]
171
+ indicatorProps: T["element"]
172
+ }