@zag-js/checkbox
Version:
Core logic for the checkbox widget implemented as a state machine
123 lines (122 loc) • 3.85 kB
JavaScript
// src/checkbox.connect.ts
import { dataAttr, getEventTarget, visuallyHiddenStyle } from "@zag-js/dom-query";
import { isFocusVisible } from "@zag-js/focus-visible";
import { parts } from "./checkbox.anatomy.mjs";
import * as dom from "./checkbox.dom.mjs";
function connect(service, normalize) {
const { send, context, prop, computed, scope } = service;
const disabled = !!prop("disabled");
const readOnly = !!prop("readOnly");
const required = !!prop("required");
const invalid = !!prop("invalid");
const focused = !disabled && context.get("focused");
const focusVisible = !disabled && context.get("focusVisible");
const checked = computed("checked");
const indeterminate = computed("indeterminate");
const checkedState = context.get("checked");
const dataAttrs = {
"data-active": dataAttr(context.get("active")),
"data-focus": dataAttr(focused),
"data-focus-visible": dataAttr(focusVisible),
"data-readonly": dataAttr(readOnly),
"data-hover": dataAttr(context.get("hovered")),
"data-disabled": dataAttr(disabled),
"data-state": indeterminate ? "indeterminate" : checked ? "checked" : "unchecked",
"data-invalid": dataAttr(invalid),
"data-required": dataAttr(required)
};
return {
checked,
disabled,
indeterminate,
focused,
checkedState,
setChecked(checked2) {
send({ type: "CHECKED.SET", checked: checked2, isTrusted: false });
},
toggleChecked() {
send({ type: "CHECKED.TOGGLE", checked, isTrusted: false });
},
getRootProps() {
return normalize.label({
...parts.root.attrs,
...dataAttrs,
dir: prop("dir"),
id: dom.getRootId(scope),
htmlFor: dom.getHiddenInputId(scope),
onPointerMove() {
if (disabled) return;
send({ type: "CONTEXT.SET", context: { hovered: true } });
},
onPointerLeave() {
if (disabled) return;
send({ type: "CONTEXT.SET", context: { hovered: false } });
},
onClick(event) {
const target = getEventTarget(event);
if (target === dom.getHiddenInputEl(scope)) {
event.stopPropagation();
}
}
});
},
getLabelProps() {
return normalize.element({
...parts.label.attrs,
...dataAttrs,
dir: prop("dir"),
id: dom.getLabelId(scope)
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
...dataAttrs,
dir: prop("dir"),
id: dom.getControlId(scope),
"aria-hidden": true
});
},
getIndicatorProps() {
return normalize.element({
...parts.indicator.attrs,
...dataAttrs,
dir: prop("dir"),
hidden: !indeterminate && !checked
});
},
getHiddenInputProps() {
return normalize.input({
id: dom.getHiddenInputId(scope),
type: "checkbox",
required: prop("required"),
defaultChecked: checked,
disabled,
"aria-labelledby": dom.getLabelId(scope),
"aria-invalid": invalid,
name: prop("name"),
form: prop("form"),
value: prop("value"),
style: visuallyHiddenStyle,
onFocus() {
const focusVisible2 = isFocusVisible();
send({ type: "CONTEXT.SET", context: { focused: true, focusVisible: focusVisible2 } });
},
onBlur() {
send({ type: "CONTEXT.SET", context: { focused: false, focusVisible: false } });
},
onClick(event) {
if (readOnly) {
event.preventDefault();
return;
}
const checked2 = event.currentTarget.checked;
send({ type: "CHECKED.SET", checked: checked2, isTrusted: true });
}
});
}
};
}
export {
connect
};