/**
* 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);
};