@zag-js/radio-group
Version:
Core logic for the radio group widget implemented as a state machine
254 lines (252 loc) • 10.3 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/radio-group.connect.ts
var radio_group_connect_exports = {};
__export(radio_group_connect_exports, {
connect: () => connect
});
module.exports = __toCommonJS(radio_group_connect_exports);
var import_dom_query = require("@zag-js/dom-query");
var import_focus_visible = require("@zag-js/focus-visible");
var import_utils = require("@zag-js/utils");
var import_radio_group = require("./radio-group.anatomy.js");
var dom = __toESM(require("./radio-group.dom.js"));
function connect(service, normalize) {
const { context, send, computed, prop, scope } = service;
const groupDisabled = computed("isDisabled");
const groupInvalid = prop("invalid");
const readOnly = prop("readOnly");
function getItemState(props) {
return {
value: props.value,
invalid: !!props.invalid || !!groupInvalid,
disabled: !!props.disabled || groupDisabled,
checked: context.get("value") === props.value,
focused: context.get("focusedValue") === props.value,
focusVisible: context.get("focusVisibleValue") === props.value,
hovered: context.get("hoveredValue") === props.value,
active: context.get("activeValue") === props.value
};
}
function getItemDataAttrs(props) {
const itemState = getItemState(props);
return {
"data-focus": (0, import_dom_query.dataAttr)(itemState.focused),
"data-focus-visible": (0, import_dom_query.dataAttr)(itemState.focusVisible),
"data-disabled": (0, import_dom_query.dataAttr)(itemState.disabled),
"data-readonly": (0, import_dom_query.dataAttr)(readOnly),
"data-state": itemState.checked ? "checked" : "unchecked",
"data-hover": (0, import_dom_query.dataAttr)(itemState.hovered),
"data-invalid": (0, import_dom_query.dataAttr)(itemState.invalid),
"data-orientation": prop("orientation"),
"data-ssr": (0, import_dom_query.dataAttr)(context.get("ssr"))
};
}
const focus = () => {
const nodeToFocus = dom.getFirstEnabledAndCheckedInputEl(scope) ?? dom.getFirstEnabledInputEl(scope);
nodeToFocus?.focus();
};
return {
focus,
value: context.get("value"),
setValue(value) {
send({ type: "SET_VALUE", value, isTrusted: false });
},
clearValue() {
send({ type: "SET_VALUE", value: null, isTrusted: false });
},
getRootProps() {
return normalize.element({
...import_radio_group.parts.root.attrs,
role: "radiogroup",
id: dom.getRootId(scope),
"aria-labelledby": dom.getLabelId(scope),
"aria-required": prop("required") || void 0,
"aria-disabled": groupDisabled || void 0,
"aria-readonly": readOnly || void 0,
"data-orientation": prop("orientation"),
"data-disabled": (0, import_dom_query.dataAttr)(groupDisabled),
"data-invalid": (0, import_dom_query.dataAttr)(groupInvalid),
"data-required": (0, import_dom_query.dataAttr)(prop("required")),
"aria-orientation": prop("orientation"),
dir: prop("dir"),
style: {
position: "relative"
}
});
},
getLabelProps() {
return normalize.element({
...import_radio_group.parts.label.attrs,
dir: prop("dir"),
"data-orientation": prop("orientation"),
"data-disabled": (0, import_dom_query.dataAttr)(groupDisabled),
"data-invalid": (0, import_dom_query.dataAttr)(groupInvalid),
"data-required": (0, import_dom_query.dataAttr)(prop("required")),
id: dom.getLabelId(scope),
onClick: focus
});
},
getItemState,
getItemProps(props) {
const itemState = getItemState(props);
return normalize.label({
...import_radio_group.parts.item.attrs,
dir: prop("dir"),
id: dom.getItemId(scope, props.value),
htmlFor: dom.getItemHiddenInputId(scope, props.value),
...getItemDataAttrs(props),
onPointerMove() {
if (itemState.disabled) return;
if (itemState.hovered) return;
send({ type: "SET_HOVERED", value: props.value, hovered: true });
},
onPointerLeave() {
if (itemState.disabled) return;
send({ type: "SET_HOVERED", value: null });
},
onPointerDown(event) {
if (itemState.disabled) return;
if (!(0, import_dom_query.isLeftClick)(event)) return;
if (itemState.focused && event.pointerType === "mouse") {
event.preventDefault();
}
send({ type: "SET_ACTIVE", value: props.value, active: true });
},
onPointerUp() {
if (itemState.disabled) return;
send({ type: "SET_ACTIVE", value: null });
},
onClick() {
if (!itemState.disabled && (0, import_dom_query.isSafari)()) {
dom.getItemHiddenInputEl(scope, props.value)?.focus();
}
}
});
},
getItemTextProps(props) {
return normalize.element({
...import_radio_group.parts.itemText.attrs,
dir: prop("dir"),
id: dom.getItemLabelId(scope, props.value),
...getItemDataAttrs(props)
});
},
getItemControlProps(props) {
const itemState = getItemState(props);
return normalize.element({
...import_radio_group.parts.itemControl.attrs,
dir: prop("dir"),
id: dom.getItemControlId(scope, props.value),
"data-active": (0, import_dom_query.dataAttr)(itemState.active),
"aria-hidden": true,
...getItemDataAttrs(props)
});
},
getItemHiddenInputProps(props) {
const itemState = getItemState(props);
return normalize.input({
"data-ownedby": dom.getRootId(scope),
id: dom.getItemHiddenInputId(scope, props.value),
type: "radio",
name: prop("name") || prop("id"),
form: prop("form"),
value: props.value,
required: prop("required"),
"aria-labelledby": dom.getItemLabelId(scope, props.value),
"aria-invalid": itemState.invalid || void 0,
onClick(event) {
if (readOnly) {
event.preventDefault();
return;
}
if (event.currentTarget.checked) {
send({ type: "SET_VALUE", value: props.value, isTrusted: true });
}
},
onBlur() {
send({ type: "SET_FOCUSED", value: null, focused: false, focusVisible: false });
},
onFocus() {
const focusVisible = (0, import_focus_visible.isFocusVisible)();
send({ type: "SET_FOCUSED", value: props.value, focused: true, focusVisible });
},
onKeyDown(event) {
if (event.defaultPrevented) return;
if (event.key === " ") {
send({ type: "SET_ACTIVE", value: props.value, active: true });
}
},
onKeyUp(event) {
if (event.defaultPrevented) return;
if (event.key === " ") {
send({ type: "SET_ACTIVE", value: null });
}
},
disabled: itemState.disabled || readOnly,
defaultChecked: itemState.checked,
style: import_dom_query.visuallyHiddenStyle
});
},
getIndicatorProps() {
const rect = context.get("indicatorRect");
const animateIndicator = context.get("animateIndicator");
return normalize.element({
id: dom.getIndicatorId(scope),
...import_radio_group.parts.indicator.attrs,
dir: prop("dir"),
hidden: context.get("value") == null || isRectEmpty(rect),
"data-disabled": (0, import_dom_query.dataAttr)(groupDisabled),
"data-orientation": prop("orientation"),
onTransitionEnd(event) {
if ((0, import_dom_query.getEventTarget)(event) !== event.currentTarget) return;
send({ type: "INDICATOR_TRANSITION_END" });
},
style: {
"--transition-property": "left, top, width, height",
"--left": (0, import_utils.toPx)(rect?.x),
"--top": (0, import_utils.toPx)(rect?.y),
"--width": (0, import_utils.toPx)(rect?.width),
"--height": (0, import_utils.toPx)(rect?.height),
position: "absolute",
willChange: animateIndicator ? "var(--transition-property)" : "auto",
transitionProperty: animateIndicator ? "var(--transition-property)" : "none",
transitionDuration: animateIndicator ? "var(--transition-duration, 150ms)" : "0ms",
transitionTimingFunction: "var(--transition-timing-function)",
[prop("orientation") === "horizontal" ? "left" : "top"]: prop("orientation") === "horizontal" ? "var(--left)" : "var(--top)"
}
});
}
};
}
var isRectEmpty = (rect) => rect == null || rect.width === 0 && rect.height === 0 && rect.x === 0 && rect.y === 0;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
connect
});