dap-design-system
Version:
Official design system for the DÁP (dap.gov.hu)
325 lines (322 loc) • 11.5 kB
JavaScript
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}
=${this.handleInvalid}
=${this.handleClick}
=${this.handleInput}
=${this.handleKeyDown}
=${super.onBlur}
=${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