UNPKG

dap-design-system

Version:

Official design system for the DÁP (dap.gov.hu)

325 lines (322 loc) 11.5 kB
import { clsx as o } from "../../node_modules/clsx/dist/clsx.js"; import "../../node_modules/@lit/reactive-element/reactive-element.js"; import "../../node_modules/lit-html/lit-html.js"; import "../../node_modules/lit-element/lit-element.js"; import { property as h } from "../../node_modules/@lit/reactive-element/decorators/property.js"; import { query as u } from "../../node_modules/@lit/reactive-element/decorators/query.js"; import { ifDefined as s } from "../../node_modules/lit-html/directives/if-defined.js"; import { html as l } from "../../node_modules/lit-html/static.js"; import { LabeledChoiceElement as f } from "../../internal/mixin/labeledChoiceElement.js"; import y from "../feedback/feedback.component.js"; import m from "../form/form-label/form-label.component.js"; import k from "../icons/system/system-check-line2/system-check-line2.component.js"; import $ from "../icons/system/system-subtract-line/system-subtract-line.component.js"; import v from "../typography/typography.component.js"; import _ from "./_styles/checkbox.scss.js"; import { unsafeCSS as g } from "../../node_modules/@lit/reactive-element/css-tag.js"; var I = Object.defineProperty, c = (b, e, a, p) => { for (var i = void 0, r = b.length - 1, d; r >= 0; r--) (d = b[r]) && (i = d(e, a, i) || i); return i && I(e, a, i), i; }, t; const n = (t = class extends f { constructor() { super(), this.indeterminate = !1, this.preventDefault = !1, this.border = !1, this.readonly = !1, this.type = "normal", t.nextId++; const e = typeof crypto != "undefined" && crypto.randomUUID ? crypto.randomUUID().slice(0, 8) : Date.now().toString(36); this.inputId = `input-${t.nextId}-${e}`, this.labelId = `label-${t.nextId}-${e}`, this.descriptionId = `description-${t.nextId}-${e}`, this.feedbackId = `feedback-${t.nextId}-${e}`; } /** * Validates property combinations and logs warnings for invalid states. * @private */ validateProperties() { this.checked && this.indeterminate && console.warn( "Checkbox: Cannot be both checked and indeterminate simultaneously. Indeterminate state will take precedence." ); } /** * Gets the aria-describedby attribute value by combining description and feedback IDs. * @returns {string | undefined} Space-separated IDs or undefined if none exist * @private */ getAriaDescribedBy() { const e = []; return this.description && e.push(this.descriptionId), this.feedback && e.push(this.feedbackId), e.length > 0 ? e.join(" ") : void 0; } /** * Gets the aria-checked attribute value based on checkbox state. * @returns {'true' | 'false' | 'mixed'} The appropriate aria-checked value * @private */ getAriaChecked() { return this.indeterminate ? "mixed" : this.checked ? "true" : "false"; } /** * Handles click events on the checkbox. * Manages the checked/indeterminate state transitions and emits change events. * @private */ handleClick(e) { if (this.preventDefault || this.disabled || this.readonly) { this.readonly && e && (e.preventDefault(), e.stopPropagation()); return; } this.validateProperties(), this.indeterminate ? (this.indeterminate = !1, this.checked = !0) : this.checked = !this.checked; const { checked: a, indeterminate: p, value: i, disabled: r } = this; try { this.emit("dds-change", { checked: a, indeterminate: p, value: i || (a ? "on" : "off"), disabled: r, readonly: this.readonly, type: "checkbox" }); } catch (d) { console.error("Error emitting checkbox change event:", d); } try { this.setValidity(); } catch (d) { console.error("Error setting checkbox validity:", d); } } /** * Handles input events on the checkbox. * Emits the dds-input event with current checkbox state. * @private */ handleInput() { const { checked: e, indeterminate: a, value: p, disabled: i } = this, r = new CustomEvent("dds-input", { bubbles: !0, cancelable: !1, composed: !0, detail: { checked: e, indeterminate: a, value: p, disabled: i, readonly: this.readonly } }); this.dispatchEvent(r); } /** * Handles keyboard events on the checkbox. * Provides enhanced keyboard navigation and accessibility. * @param {KeyboardEvent} event - The keyboard event * @private */ handleKeyDown(e) { this.readonly || e.code !== "Space" && e.code === "Enter" && (e.preventDefault(), this.handleClick()); } get focusElement() { if (!this.input) throw new Error( "Checkbox input element not found. Component may not be properly initialized." ); return this.input; } /** * Programmatically focuses the checkbox input element. * @public */ focus() { this.input && !this.disabled && !this.readonly && this.input.focus(); } /** * Programmatically blurs the checkbox input element. * @public */ blur() { this.input && this.input.blur(); } /** * Renders the appropriate icon based on checkbox state. * @returns {TemplateResult | null} The icon template or null if unchecked * @private */ renderIcon() { return this.indeterminate ? l` <dap-ds-icon-subtract-line class="checkbox__icon" part="icon" exportparts="base:icon-base" size="16" decorative></dap-ds-icon-subtract-line> ` : this.checked ? l` <dap-ds-icon-check-line2 class="checkbox__icon" part="icon" exportparts="base:icon-base" size="16" decorative></dap-ds-icon-check-line2> ` : null; } /** * Handles invalid events on the checkbox input. * Prevents the default browser validation UI from showing and manages invalid state. * @param {Event} event - The invalid event * @private */ handleInvalid(e) { e.preventDefault(), this.invalid || (this.invalid = !0); } setValidity() { if (!this.innerInput) return; const { valid: e } = this.innerInput.validity; e ? (this.required && (this.invalid = !1), this.internals.setValidity({})) : this.internals.setValidity( this.innerInput.validity, this.validationMessage, this.innerInput ); } render() { return l` <div part="base"> <label part="base-label" class=${o("checkbox choice", `checkbox--${this.size}`, { "checkbox--checked": this.checked, "checkbox--disabled": this.disabled, "checkbox--readonly": this.readonly, "checkbox--indeterminate": this.indeterminate, "checkbox--required": this.required, "choice--readonly": this.readonly, "choice--disabled": this.disabled, "choice__label--right": this.labelPlacement === "right", "choice__label--left": this.labelPlacement === "left" })}> <div part="wrapper" class=${o("input__wrapper", { "input__wrapper--background": this.type === "background", "input__wrapper--border": this.border })}> <input part="input" type="checkbox" class=${o("input", { "input--background": this.type === "background" })} name=${s(this.name ? this.name : void 0)} id=${this.inputId} .indeterminate=${this.indeterminate} .checked=${this.checked} .disabled=${this.disabled} .required=${this.required} aria-labelledby=${s( !this.ariaLabel && this.label ? this.labelId : void 0 )} aria-describedby=${this.ariaLabel ? "" : s(this.getAriaDescribedBy())} aria-checked=${this.getAriaChecked()} .aria-invalid=${this.invalid ? "true" : null} @invalid=${this.handleInvalid} @click=${this.handleClick} @input=${this.handleInput} @keydown=${this.handleKeyDown} @blur=${super.onBlur} @focus=${super.onFocus} /> <span part="control" class=${o("input__control", `input__control--${this.size}`, { "input__control--checked": this.checked, "input__control--disabled": this.disabled, "input__control--readonly": this.readonly, "input__control--indeterminate": this.indeterminate, "input__control--invalid": this.invalid })}> <span part="high-contrast" class=${o( "input__control-high-contrast", `input__control-high-contrast--${this.size}`, { "input__control-high-contrast--disabled": this.disabled, "input__control-high-contrast--readonly": this.readonly } )}></span> <slot name="iconcontent"> ${this.renderIcon()} </slot> </span> <div part="label-container" class=${o("choice__label-container", { "choice__label-container--disabled": this.disabled, "choice__label-container--readonly": this.readonly, "choice__label--bottom": this.descriptionPlacement === "top", "choice__label--top": this.descriptionPlacement === "bottom" })}> ${this.label && l`<dap-ds-form-label id=${this.labelId} class="label" part="label" .size=${this.size} .required=${this.required} .requiredLabel=${this.requiredLabel} .optional=${this.optional} aria-hidden="true" .optionalLabel=${this.optionalLabel} .disabled=${this.disabled || this.readonly} .readonly=${this.readonly} .hideLabel=${this.hideLabel} label=${s(this.label)} subtle renderAs="span"> </dap-ds-form-label>`} ${this.description && l` <dap-ds-typography class="description" variant="description" part="description" aria-hidden="true" size=${s(this.size)} id=${this.descriptionId}> ${this.description} </dap-ds-typography> `} </div> </div> ${this.feedback && l` <dap-ds-feedback part="feedback" feedbackType=${s(this.feedbackType)} feedbackSize=${s(this.size)} id="feedback" .subtle=${this.subtle}> ${this.feedback} </dap-ds-feedback> `} </label> </div> `; } }, t.tagName = "dap-ds-checkbox", t.dependencies = { "dap-ds-icon-subtract-line": $, "dap-ds-icon-check-line2": k, "dap-ds-form-label": m, "dap-ds-typography": v, "dap-ds-feedback": y }, t.nextId = 0, t.styles = g(_), t); c([ u(".input") ], n.prototype, "input"); c([ h({ type: Boolean, reflect: !0 }) ], n.prototype, "indeterminate"); c([ h({ type: Boolean, reflect: !0 }) ], n.prototype, "preventDefault"); c([ h({ type: Boolean }) ], n.prototype, "border"); c([ h({ type: Boolean, reflect: !0 }) ], n.prototype, "readonly"); c([ h({ type: String }) ], n.prototype, "type"); let j = n; export { j as default }; //# sourceMappingURL=checkbox.component.js.map