UNPKG

@postnord/web-components

Version:
180 lines (176 loc) 15.1 kB
/*! * Built with Stencil * By PostNord. */ import { t as transformTag, M as Mixin, r as registerInstance, c as createEvent, g as getElement, h, a as Host } from './index-XKg-ydzH.js'; import { uuidv4 } from './index.js'; import { a as animateHeightFactory } from './index-DyhO6xPY.js'; const pnRadioButtonCss = () => `${transformTag("pn-radio-button")}{position:relative;display:inline-block}${transformTag("pn-radio-button")} .pn-radio{position:relative;display:flex;flex-wrap:wrap;flex-direction:row}${transformTag("pn-radio-button")} .pn-radio-label{cursor:pointer;color:#2d2013;-webkit-tap-highlight-color:transparent}${transformTag("pn-radio-button")} .pn-radio-helpertext{color:#5e554a;margin:0 0 0.5em 0;display:flex;flex-direction:column}${transformTag("pn-radio-button")} .pn-radio-helpertext:last-child{margin:0}${transformTag("pn-radio-button")} .pn-radio-content{display:flex;flex-direction:column;align-items:flex-start;font-weight:400;line-height:1.5;flex:1;margin:0 0 0 0.75em}${transformTag("pn-radio-button")} .pn-radio-button{display:flex;gap:0.75em;padding:0}${transformTag("pn-radio-button")} .pn-radio-outer{background-color:#ffffff;border:0.0625em solid #969087;border-radius:50%;height:1.5em;width:1.5em;display:flex;justify-content:center;align-items:center;outline:0.2rem solid transparent;outline-offset:0.2rem;transition-property:border-color, background-color, outline-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${transformTag("pn-radio-button")} .pn-radio-outer{transition-duration:0s;transition-delay:0s}}${transformTag("pn-radio-button")} .pn-radio-inner{height:0.75em;width:0.75em;background-color:#005d92;border-radius:50%;transform:scale(0);transform-origin:center center;transition-property:background-color, transform;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${transformTag("pn-radio-button")} .pn-radio-inner{transition-duration:0s;transition-delay:0s}}${transformTag("pn-radio-button")} .pn-radio[data-tile]{padding:1em;border:0.0625em solid #969087;border-radius:0.5em;background-color:#ffffff;outline:0.2rem solid transparent;outline-offset:0.2rem;transition-property:border-color, background-color, outline-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}@media (prefers-reduced-motion: reduce){${transformTag("pn-radio-button")} .pn-radio[data-tile]{transition-duration:0s;transition-delay:0s}}${transformTag("pn-radio-button")} .pn-radio[data-tile] .pn-radio-outer{outline:none}${transformTag("pn-radio-button")} .pn-radio[data-invalid]{border-color:#a70707}${transformTag("pn-radio-button")} .pn-radio[data-invalid] .pn-radio-outer{border-color:#a70707}${transformTag("pn-radio-button")} .pn-radio[data-invalid] .pn-radio-inner{background-color:#a70707}${transformTag("pn-radio-button")} .pn-radio-container{flex:1 1 100%;overflow:hidden;visibility:hidden}${transformTag("pn-radio-button")} .pn-radio-container[data-open]{visibility:visible;overflow:unset}${transformTag("pn-radio-button")} .pn-radio-container[data-moving]{visibility:visible;overflow:hidden}${transformTag("pn-radio-button")} .pn-radio-area{padding:0.75em 0 0 2.25em;display:flex;flex-direction:column;flex-wrap:nowrap;gap:1em}${transformTag("pn-radio-button")} .pn-radio>${transformTag("pn-icon")}{margin-left:0.75em}${transformTag("pn-radio-button")}>input[type=radio]{cursor:pointer;opacity:0;position:absolute;margin:0;z-index:1;top:0;left:0;font-size:1em;width:1.5em;height:1.5em;-webkit-tap-highlight-color:transparent}${transformTag("pn-radio-button")}>input[type=radio][data-tile]:not([data-expand]){width:100%;height:100%}${transformTag("pn-radio-button")}>input[type=radio][data-expand]{top:1em;left:1em}${transformTag("pn-radio-button")}>input[type=radio][aria-describedby]+.pn-radio[data-tile] .pn-radio-label{font-weight:500}${transformTag("pn-radio-button")}>input[type=radio]:hover+.pn-radio[data-tile]{border-color:#005d92;background-color:#e0f8ff}${transformTag("pn-radio-button")}>input[type=radio]:hover+.pn-radio[data-tile] .pn-radio-outer{background-color:#e0f8ff}${transformTag("pn-radio-button")}>input[type=radio]:hover+.pn-radio[data-tile][data-invalid]{border-color:#a70707;background-color:#fdefee}${transformTag("pn-radio-button")}>input[type=radio]:hover+.pn-radio[data-tile][data-invalid] .pn-radio-outer{background-color:#fdefee}${transformTag("pn-radio-button")}>input[type=radio]:hover+.pn-radio[data-invalid] .pn-radio-outer{border-color:#a70707;background-color:#fdefee}${transformTag("pn-radio-button")}>input[type=radio]:hover+.pn-radio .pn-radio-outer{border-color:#005d92;background-color:#e0f8ff}${transformTag("pn-radio-button")}>input[type=radio]:checked:hover+.pn-radio[data-tile][data-invalid]{border-color:#500715}${transformTag("pn-radio-button")}>input[type=radio]:checked:hover+.pn-radio[data-invalid]>.pn-radio-button>.pn-radio-outer{border-color:#500715}${transformTag("pn-radio-button")}>input[type=radio]:focus-visible+.pn-radio .pn-radio-outer{outline-color:#005d92}${transformTag("pn-radio-button")}>input[type=radio]:focus-visible+.pn-radio[data-invalid] .pn-radio-outer{outline-color:#a70707}${transformTag("pn-radio-button")}>input[type=radio]:focus-visible+.pn-radio[data-tile]{outline-color:#005d92;border-color:#005d92}${transformTag("pn-radio-button")}>input[type=radio]:focus-visible+.pn-radio[data-tile][data-invalid]{outline-color:#a70707;border-color:#a70707}${transformTag("pn-radio-button")}>input[type=radio]:focus-visible+.pn-radio[data-tile]>.pn-radio-button>.pn-radio-outer{outline:none}${transformTag("pn-radio-button")}>input[type=radio]:checked+.pn-radio[data-tile]{border-color:#005d92;background-color:#e0f8ff}${transformTag("pn-radio-button")}>input[type=radio]:checked+.pn-radio[data-tile][data-invalid]{border-color:#a70707;background-color:#fdefee}${transformTag("pn-radio-button")}>input[type=radio]:checked+.pn-radio>.pn-radio-button>.pn-radio-outer{border-color:#005d92}${transformTag("pn-radio-button")}>input[type=radio]:checked+.pn-radio>.pn-radio-button>.pn-radio-outer>.pn-radio-inner{transform:scale(1);background-color:#005d92}${transformTag("pn-radio-button")}>input[type=radio]:checked+.pn-radio[data-invalid]>.pn-radio-button>.pn-radio-outer{border-color:#a70707}${transformTag("pn-radio-button")}>input[type=radio]:checked+.pn-radio[data-invalid]>.pn-radio-button>.pn-radio-outer>.pn-radio-inner{background-color:#a70707}${transformTag("pn-radio-button")}>input[type=radio]:disabled{pointer-events:none}${transformTag("pn-radio-button")}>input[type=radio]:disabled+.pn-radio .pn-radio-label{pointer-events:none}${transformTag("pn-radio-button")}>input[type=radio]:disabled+.pn-radio[data-tile]{background-color:#f3f2f2;border-color:#f3f2f2}${transformTag("pn-radio-button")}>input[type=radio]:disabled+.pn-radio[data-tile]>${transformTag("pn-icon")} .pn-icon-svg path{fill:#5e554a}${transformTag("pn-radio-button")}>input[type=radio]:disabled+.pn-radio[data-tile]>.pn-radio-content>.pn-radio-label{color:#5e554a}${transformTag("pn-radio-button")}>input[type=radio]:disabled+.pn-radio>.pn-radio-button>.pn-radio-outer{background-color:#f3f2f2;border-color:#969087;outline:none}${transformTag("pn-radio-button")}>input[type=radio]:disabled+.pn-radio>.pn-radio-button>.pn-radio-outer>.pn-radio-inner{background-color:#969087}`; const PnRadioButton = class extends Mixin(animateHeightFactory) { constructor(hostRef) { super(); registerInstance(this, hostRef); this.pnRadioChange = createEvent(this, "pnRadioChange", 3); } id = `pn-radio-${uuidv4()}`; idHelpertext = `${this.id}-helpertext`; contentArea; radioInput; get hostElement() { return getElement(this); } /** The radio label */ 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 radio group. @category Native attributes */ name; /** Programmatically check the input. @category Native attributes */ checked = false; /** Set the radio as required. @category Native attributes */ required = false; /** Disable the radio. @category Native attributes */ disabled = false; /** * Turn the radio 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 radio 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 radio tile. The `tile` prop must be `true` for the icon to work. * @see {@link tile} * @category Features */ icon = null; /** * If set to true, color scheme will turn red, indicating that there is an issue or incorrect input related the radio. * @category Features */ invalid = false; /** A unique HTML ID for the radio. @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 radio. * @deprecated Use `pn-id` instead. * @category HTML attributes */ radioid; handleId() { this.idHelpertext = `${this.getId()}-helpertext`; } handleChecked(checked) { this.checked = checked ?? this.radioInput.checked; if (!this.displayContent()) return; if (this.checked) { this.openDropdown(this.contentArea); this.uncheckOtherRadios(); } else { this.closeDropdown(this.contentArea); } } handleChange(e) { const target = e.target; const { name } = target; const isSameRadioGroup = name === this.name; const isSameRadio = target === this.radioInput && target.checked; /** * Since content can be nested inside of this component, * double check that the event is coming from this specific radio. */ if (isSameRadioGroup) this.checked = isSameRadio; } /** * 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-radio-button` element without * having to worry about catching events from nested pn-radio-buttons. * * @since v7.25.0 **/ pnRadioChange; componentDidLoad() { requestAnimationFrame(() => this.displayContent() && this.checked && this.openDropdown(this.contentArea)); } getId() { return this.pnId || this.radioid || this.id; } uncheckOtherRadios() { if (!this.name) return; const selector = `pn-radio-button[name="${this.name}"]`; const list = document.querySelectorAll(selector); const radios = Array.from(list); radios.forEach(radio => radio !== this.hostElement && (radio.checked = false)); } 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; } 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: '52305f6cf3826500739510f0cf1fd0ab2abc7dc2' }, h("input", { key: 'cc4f799fb58073ca59af798601d70baf88263aca', type: "radio", id: this.getId(), class: "pn-radio-input", value: this.value, name: this.name, disabled: this.disabled, checked: this.checked, required: this.required, "aria-label": this.getAriaLabel(), "aria-labelledby": this.getAriaLabelledby(), "aria-invalid": this.isInvalid()?.toString(), "aria-describedby": this.displayHelpertext() ? this.idHelpertext : null, "data-tile": this.tile, "data-expand": this.expand, onChange: event => this.pnRadioChange.emit(event), ref: el => (this.radioInput = el) }), h("div", { key: '05e2a10face9b2ca1b0ced1f6f38f1173f15d1c0', class: "pn-radio", "data-tile": this.tile, "data-expand": this.expand, "data-invalid": this.isInvalid() }, h("div", { key: 'b5274e03c47ac3d53103af945b3e8ce211eec827', class: "pn-radio-button" }, h("div", { key: '1f4a592f7d243312e00259f67ce60836a449f42d', class: "pn-radio-outer" }, h("div", { key: '05cb629b8c45724c6831271a40620ba5ec6e66ef', class: "pn-radio-inner" }))), h("div", { key: 'a91835bcaa01888fd2a2b1b768def02203b58038', class: "pn-radio-content", hidden: !this.displayText() }, h("label", { key: 'c11016410fd25dbb3288640ef5f239553991f0f8', htmlFor: this.getId(), class: "pn-radio-label", hidden: !this.displayLabel() }, this.label), h("p", { key: '6d4d46978e2a4f326af1558c4c6dd04c3c29956b', id: this.idHelpertext, class: "pn-radio-helpertext", hidden: !this.displayHelpertext() }, this.helpertext, h("slot", { key: '3167af1f4d47e1a9c8010bc9316b32c5499f66ee', name: "helpertext" })), h("slot", { key: '1a4b466d8a8ba4e06ae96977e33fad1c502d5ea2' })), this.displayIcon() && h("pn-icon", { key: '67f80f5c1db91e7310cf5baefdf6f3c346c83397', icon: this.icon, color: "gray900" }), h("div", { key: 'e296239a734c33c40035b489d79b1edf44f1a2b7', class: "pn-radio-container", "data-open": this.checked, hidden: !this.displayContent(), style: { height: '0px' }, ref: el => (this.contentArea = el) }, h("div", { key: 'f6245b5b2c9611da4b59a3fdb3047fe8365f1678', class: "pn-radio-area" }, h("slot", { key: 'b985712da1ea4504025d17cc507588f14d9ebfff', name: "content" })))))); } static get watchers() { return { "radioid": [{ "handleId": 0 }], "pnId": [{ "handleId": 1 }], "checked": [{ "handleChecked": 0 }] }; } }; PnRadioButton.style = pnRadioButtonCss(); export { PnRadioButton as pn_radio_button };