/** * Specify {@link UwcInputElement#type | `[type=checkbox]`} to render a checkbox. * * @example * A plain and simple checkbox. * * ```html * * ``` * * @example * An indeterminate checkbox * * ```html * * ``` * * One notable difference from regular `` elements is that `` * will always set at least `"true"` | `"false"` into the nearest form. * * @example * ```html *
* * *
* * ``` * * @module */ import { create, createEventRegistrar, dispatch, } from "@hesxenon/prelude/Dom.js"; import { Connect } from "../uwc-input"; import { Events } from "../events"; import * as Root from "../parts/root"; import { backup } from "../../utils/ElementBackup"; const initializeInput: Connect = (input: UwcInputElement, { disconnect }) => { backup(input, disconnect); input.checked = input.checked ?? false; input.role = input.role ?? "checkbox"; input.tabIndex = input.tabIndex === -1 ? 0 : input.tabIndex; }; /** * @internal */ export const connectCheckbox: Connect = (input, opts) => { const initial: Partial = { checked: input.checked, value: input.value, }; const syncFormValues = () => { dispatch(input, { type: Events.formValuesChanged, detail: input.disabled ? [] : !input.value ? [String(input.checked)] : input.checked ? [String(input.value)] : [], }); }; const validate = () => { dispatch(input, { type: Events.validityStateChanged, detail: input.readonly || input.disabled ? {} : { valueMissing: input.required && !input.checked, }, }); }; const handleUserSelected = (e: Event) => { if (e.defaultPrevented || input.readonly || input.disabled) { return; } e.preventDefault(); e.stopPropagation(); input.checked = !input.checked; dispatch(input, { type: "input" }); dispatch(input, { type: "change" }); }; const on = createEventRegistrar(input, opts.disconnect); on("click", handleUserSelected); on([Events.checkedChanged, Events.indeterminateChanged], () => { input.setAttribute( "aria-checked", input.checked ? (input.indeterminate ? "mixed" : "true") : "false", ); syncFormValues(); }); on( [Events.nameChanged, Events.valueChanged, Events.formAssociated], syncFormValues, ); on(Events.formValuesChanged, validate); on(Events.clear, () => { input.checked = false; }); on("keydown", (e) => { if (e.key === " ") { handleUserSelected(e); } }); on(Events.formReset, () => { Object.assign(input, initial); }); const checkmark = Root.getFor(input).querySelector("[part=checkmark]") ?? create("div", { part: "checkmark" }); Root.replaceChildren(input, [checkmark]); initializeInput(input, opts); };