UNPKG

@postnord/web-components

Version:
588 lines (587 loc) 24 kB
/*! * Built with Stencil * By PostNord. */ import { uuidv4 } from "../../../globals/helpers"; import { h, Host, Mixin } from "@stencil/core"; import { animateHeightFactory } from "../../../globals/mixins/index"; /** * The `pn-checkbox` is built with a native `input[type="checkbox"]` in the background. * This means you can use native events to listen to the changes. * * @nativeChange Use the `change` event to listen when the checkbox state is being toggled. * * @slot - The default slot for adding custom HTML under the label/helpertext. {@since v7.17.0} * @slot helpertext - Use this slot to add custom HTML inside of the helpertext element. * Only recommended if you need a link without the `tile` prop. {@since v7.17.0} * @slot content - When using the `tile` and `expand` props, this slot will be revealed when the input is checked. {@since v7.17.0} */ export class PnCheckbox extends Mixin(animateHeightFactory) { constructor() { super(); } id = `pn-checkbox-${uuidv4()}`; idHelpertext = `${this.id}-helpertext`; contentArea; hostElement; /** The checkbox label, this is required for the checkbox to be 100% accessible out of the box. */ label; /** This adds an optional helpertext under the label. */ helpertext; /** This will be emitted on change and input events. @category Native attributes */ value; /** The name of the checkbox group. @category Native attributes */ name; /** Programmatically check the input. @category Native attributes */ checked = false; /** Set the checkbox as required. @category Native attributes */ required = false; /** Disable the checkbox. @category Native attributes */ disabled = false; /** * If set to true, color scheme will turn red, indicating that there is an issue related to the checkbox. * @category Native attributes */ invalid = false; /** * Sets the checkbox to an indeterminate state, allowing for a mixed or intermediate checkbox state. * @category Native attributes */ indeterminate = false; /** * Turn the checkbox into a clickable tile. A border and padding is added. * * **Do not** use interactive elements (links/buttons) inside of the slots when using this prop. * An exception is made when using the `tile` + `expand` props together, * which allows you to use interactive elements. * * @category Features */ tile = false; /** * Allow the checkbox to control the slot area "content". * When checked, the area is visible, when unchecked, the area is hidden. * * The prop `tile` must be used at the same time. * @see {@link tile} * @since v7.17.0 * @category Features */ expand = false; /** * Add an icon on the right of your checkbox tile. The `tile` prop must be `true` for the icon to work. * @see {@link tile} * @category Features */ icon = null; /** A unique HTML ID for the checkbox. @since v7.25.0 @category HTML attributes */ pnId; /** * Provide the label via an aria attribute. * We strongly recommend you use the `label` prop instead. * @since v7.25.0 * @category HTML attributes */ pnAriaLabel; /** * Provide the label from another element via its ID. * We strongly recommend you use the `label` prop instead. * @since v7.25.0 * @category HTML attributes */ pnAriaLabelledby; /** A unique HTML ID for the checkbox. @deprecated Use `pn-id` instead. @category HTML attributes */ checkboxid; handleId() { this.idHelpertext = `${this.getId()}-helpertext`; } handleChecked() { if (this.displayContent()) { this.checked ? this.openDropdown(this.contentArea) : this.closeDropdown(this.contentArea); } } /** * This is the same as the native `change` event, but without bubbling. * This is useful when you want to listen to the event directly on the `pn-checkbox` element without * having to worry about catching events from nested pn-checkboxes. * * @since v7.25.0 **/ pnCheckboxChange; componentDidLoad() { if (this.displayContent() && this.checked) { requestAnimationFrame(() => this.openDropdown(this.contentArea)); } } getId() { return this.pnId || this.checkboxid || this.id; } handleChange(e) { const { checked } = e.target; this.indeterminate = false; this.checked = checked; this.pnCheckboxChange.emit(e); } isInvalid() { return this.invalid && !this.disabled; } displayText() { return this.displayLabel() || this.displayHelpertext(); } displayLabel() { return !!this.label; } displayHelpertext() { return !!(this.helpertext || this.hostElement.querySelector('[slot="helpertext"]')?.textContent); } displayIcon() { return this.tile && !!this.icon; } /** Allow the checkbox to expand and control the slot area "content". */ displayContent() { return this.tile && this.expand; } getAriaLabel() { return !this.displayLabel() && !this.pnAriaLabelledby ? this.pnAriaLabel : null; } getAriaLabelledby() { return !this.displayLabel() && !this.pnAriaLabel ? this.pnAriaLabelledby : null; } render() { return (h(Host, { key: '4952d473c243232a6ee267cfac9414c8feb3e9c7' }, h("input", { key: 'e478ca15bde8fdf54833fe5b5a834513813db65e', type: "checkbox", id: this.getId(), class: "pn-checkbox-input", value: this.value, name: this.name, disabled: this.disabled, checked: this.checked, required: this.required, indeterminate: this.indeterminate, "aria-label": this.getAriaLabel(), "aria-labelledby": this.getAriaLabelledby(), "aria-describedby": this.displayHelpertext() && this.idHelpertext, "aria-invalid": this.isInvalid()?.toString(), "data-tile": this.tile, "data-expand": this.expand, onChange: e => this.handleChange(e) }), h("div", { key: 'e918f05ea8a0f5e26a7963dcdbd9cef7a1ae8a57', class: "pn-checkbox", "data-tile": this.tile, "data-expand": this.expand, "data-invalid": this.isInvalid() }, h("div", { key: 'e876cc7ae77d0496c745da65de5883404d0a01c7', class: "pn-checkbox-outer" }, h("svg", { key: '2349e0a978e6824658b572462eb5baf9ccda2ec9', class: "pn-checkbox-svg", xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none" }, h("polyline", { key: 'c01925a07dfb5bbed352ecb741a3e9c830a32b3b', class: "pn-checkbox-svg-line pn-checkbox-svg-checkmark", points: "4,12 9,17 20,6", "stroke-width": "3" }), h("polyline", { key: '0d4dfa8da28e602bf0c579c6ca48fda9f1748a38', class: "pn-checkbox-svg-line pn-checkbox-svg-indeterminate", points: "4,12 20,12", "stroke-width": "3" }))), h("div", { key: 'd3c1f4a8d7aa27d7d9ca192438b84619574fcf39', class: "pn-checkbox-content", hidden: !this.displayText() }, h("label", { key: '467ca071291cbd977670300bb45affc7153ae7f4', htmlFor: this.getId(), class: "pn-checkbox-label", hidden: !this.displayLabel() }, this.label), h("p", { key: '5c790a6b8583415168a3e92c7b6d3a38125b39cd', id: this.idHelpertext, class: "pn-checkbox-helpertext", hidden: !this.displayHelpertext() }, this.helpertext && h("span", { key: 'e35b4ac4a6abd759d7fb5e1d41fd2f198515e106' }, this.helpertext), h("slot", { key: 'ac060762533af07379cc80225a83de6e01ca26e4', name: "helpertext" })), h("slot", { key: '4f0309028f9266d016f19d8983343ff010d89195' })), this.displayIcon() && h("pn-icon", { key: '742b544ed4ed61ff311de992eea37b768cc6efef', icon: this.icon, color: "gray900" }), h("div", { key: '45cdad0df43248b340feed887659d6c63e90b85f', class: "pn-checkbox-container", "data-open": this.checked, hidden: !this.displayContent(), style: { height: '0px' }, ref: el => (this.contentArea = el) }, h("div", { key: '060550d9876021ba85a1821c51c60b1bb34b8a3c', class: "pn-checkbox-area" }, h("slot", { key: 'bbe34f9d29a922ab20b8696595a9ed469005f59e', name: "content" })))))); } static get is() { return "pn-checkbox"; } static get originalStyleUrls() { return { "$": ["pn-checkbox.scss"] }; } static get styleUrls() { return { "$": ["pn-checkbox.css"] }; } static get properties() { return { "label": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The checkbox label, this is required for the checkbox to be 100% accessible out of the box." }, "getter": false, "setter": false, "reflect": false, "attribute": "label" }, "helpertext": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "This adds an optional helpertext under the label." }, "getter": false, "setter": false, "reflect": false, "attribute": "helpertext" }, "value": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": true, "optional": false, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "This will be emitted on change and input events." }, "getter": false, "setter": false, "reflect": true, "attribute": "value" }, "name": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "The name of the checkbox group." }, "getter": false, "setter": false, "reflect": false, "attribute": "name" }, "checked": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "Programmatically check the input." }, "getter": false, "setter": false, "reflect": true, "attribute": "checked", "defaultValue": "false" }, "required": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "Set the checkbox as required." }, "getter": false, "setter": false, "reflect": false, "attribute": "required", "defaultValue": "false" }, "disabled": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "Disable the checkbox." }, "getter": false, "setter": false, "reflect": false, "attribute": "disabled", "defaultValue": "false" }, "invalid": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "If set to true, color scheme will turn red, indicating that there is an issue related to the checkbox." }, "getter": false, "setter": false, "reflect": false, "attribute": "invalid", "defaultValue": "false" }, "indeterminate": { "type": "boolean", "mutable": true, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [{ "name": "category", "text": "Native attributes" }], "text": "Sets the checkbox to an indeterminate state, allowing for a mixed or intermediate checkbox state." }, "getter": false, "setter": false, "reflect": false, "attribute": "indeterminate", "defaultValue": "false" }, "tile": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "category", "text": "Features" }], "text": "Turn the checkbox into a clickable tile. A border and padding is added.\n\n**Do not** use interactive elements (links/buttons) inside of the slots when using this prop.\nAn exception is made when using the `tile` + `expand` props together,\nwhich allows you to use interactive elements." }, "getter": false, "setter": false, "reflect": false, "attribute": "tile", "defaultValue": "false" }, "expand": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "see", "text": "{@link tile }" }, { "name": "since", "text": "v7.17.0" }, { "name": "category", "text": "Features" }], "text": "Allow the checkbox to control the slot area \"content\".\nWhen checked, the area is visible, when unchecked, the area is hidden.\n\nThe prop `tile` must be used at the same time." }, "getter": false, "setter": false, "reflect": false, "attribute": "expand", "defaultValue": "false" }, "icon": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "see", "text": "{@link tile }" }, { "name": "category", "text": "Features" }], "text": "Add an icon on the right of your checkbox tile. The `tile` prop must be `true` for the icon to work." }, "getter": false, "setter": false, "reflect": false, "attribute": "icon", "defaultValue": "null" }, "pnId": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.25.0" }, { "name": "category", "text": "HTML attributes" }], "text": "A unique HTML ID for the checkbox." }, "getter": false, "setter": false, "reflect": false, "attribute": "pn-id" }, "pnAriaLabel": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.25.0" }, { "name": "category", "text": "HTML attributes" }], "text": "Provide the label via an aria attribute.\nWe strongly recommend you use the `label` prop instead." }, "getter": false, "setter": false, "reflect": false, "attribute": "pn-aria-label" }, "pnAriaLabelledby": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "since", "text": "v7.25.0" }, { "name": "category", "text": "HTML attributes" }], "text": "Provide the label from another element via its ID.\nWe strongly recommend you use the `label` prop instead." }, "getter": false, "setter": false, "reflect": false, "attribute": "pn-aria-labelledby" }, "checkboxid": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string", "references": {} }, "required": false, "optional": true, "docs": { "tags": [{ "name": "deprecated", "text": "Use `pn-id` instead." }, { "name": "category", "text": "HTML attributes" }], "text": "A unique HTML ID for the checkbox." }, "getter": false, "setter": false, "reflect": false, "attribute": "checkboxid" } }; } static get events() { return [{ "method": "pnCheckboxChange", "name": "pnCheckboxChange", "bubbles": false, "cancelable": true, "composed": true, "docs": { "tags": [{ "name": "since", "text": "v7.25.0" }], "text": "This is the same as the native `change` event, but without bubbling.\nThis is useful when you want to listen to the event directly on the `pn-checkbox` element without\nhaving to worry about catching events from nested pn-checkboxes." }, "complexType": { "original": "Event", "resolved": "Event", "references": { "Event": { "location": "import", "path": "@stencil/core", "id": "node_modules::Event", "referenceLocation": "Event" } } } }]; } static get elementRef() { return "hostElement"; } static get watchers() { return [{ "propName": "checkboxid", "methodName": "handleId" }, { "propName": "pnId", "methodName": "handleId", "handlerOptions": { "immediate": true } }, { "propName": "checked", "methodName": "handleChecked" }]; } }