UNPKG

@postnord/web-components

Version:

PostNord Web Components

638 lines (632 loc) 43.8 kB
/*! * Built with Stencil * By PostNord. */ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client'; import { a as alert_exclamation_circle } from './alert_exclamation_circle.js'; import { a as angle_down } from './angle_down.js'; import { c as close } from './close.js'; import { u as uuidv4, j as awaitTopbar, r as ripple, h as getTotalHeightOffset, e as en } from './helpers.js'; import { d as defineCustomElement$2 } from './pn-icon2.js'; const translations = { SELECT_AN_OPTION: { en: 'Select an option', sv: 'Välj ett alternativ', da: 'Vælg en mulighed', fi: 'Valitse vaihtoehto', no: 'Velg et alternativ', }, SELECT_ALL_OPTIONS: { en: 'Select all options', sv: 'Välj alla alternativ', da: 'Vælg alle muligheder', fi: 'Valitse kaikki vaihtoehdot', no: 'Velg alle alternativer', }, SELECT_FOUND_OPTIONS: { en: 'Select {number} options', sv: 'Välj {number} alternativ', da: 'Vælg {number} muligheder', fi: 'Valitse {number} vaihtoehtoa', no: 'Velg {number} alternativer', }, SELECTED_OPTIONS: { en: 'Selected options.', sv: 'Valda alternativ.', da: 'Valgte muligheder.', fi: 'Valitut vaihtoehdot.', no: 'Valgte alternativer.', }, BUTTON_OPEN: { en: 'Open list', sv: 'Öppna listan', da: 'Open list', fi: 'Open list', no: 'Open list', }, BUTTON_CLOSE: { en: 'Close list', sv: 'Stäng listan', da: 'Close list', fi: 'Close list', no: 'Close list', }, REMOVE: { en: 'Remove', sv: 'Ta bort', da: 'Remove', fi: 'Remove', no: 'Remove', }, REMOVED: { en: 'Removed', sv: 'Tog bort', da: 'Fjernet', fi: 'Poistettu', no: 'Fjernet', }, MORE_OPTION: { en: 'more option.', sv: 'alternativ till.', da: 'mulighed mere.', fi: 'vaihtoehto lisää.', no: 'alternativ til.', }, MORE_OPTIONS: { en: 'more options.', sv: 'fler alternativ.', da: 'more options.', fi: 'more options.', no: 'more options.', }, SEARCH: { en: 'Search', sv: 'Sök', da: 'Søg', fi: 'Hae', no: 'Søk', }, RESULTS_FOUND: { en: 'options found', sv: 'alternativ hittades', da: 'muligheder fundet', fi: 'vaihtoehtoja löytyi', no: 'alternativer funnet', }, NO_SEARCH_RESULTS: { en: 'No options found', sv: 'Inga alternativ hittades', da: 'Ingen muligheder fundet', fi: 'Vaihtoehtoja ei löytynyt', no: 'Finner ingen alternativer', }, NO_OPTIONS: { en: 'No options available', sv: 'Inga alternativ tillgängliga', da: 'Ingen tilgængelige muligheder', fi: 'Ei vaihtoehtoja', no: 'Ingen tilgjengelige alternativer', }, }; const pnMultiselectCss = "pn-multiselect{display:inline-block}pn-multiselect .pn-multiselect{border:0;margin:0;padding:0}pn-multiselect .pn-multiselect[data-icon] .pn-multiselect-element{padding-left:3em}pn-multiselect .pn-multiselect[data-error] .pn-multiselect-element{padding-right:5.5em;border-color:#a70707}pn-multiselect .pn-multiselect[data-error] .pn-multiselect-element:hover{border-color:#500715}pn-multiselect .pn-multiselect[data-error] .pn-multiselect-element:focus-visible{background-color:#ffffff;border-color:#a70707;outline-color:#a70707}pn-multiselect .pn-multiselect-label{cursor:pointer;display:flex;justify-content:space-between;align-items:flex-end;font-weight:400;color:#2d2013;margin:0 0 0.25em 0;gap:0.5em;transition-property:color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1);-webkit-tap-highlight-color:transparent;width:100%}pn-multiselect .pn-multiselect-label>span{font-size:0.875em}pn-multiselect .pn-multiselect-sr-only{position:absolute;height:1px;width:1px;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);margin:-1px;white-space:nowrap}pn-multiselect .pn-multiselect-group{position:relative;padding:0;margin:0}pn-multiselect .pn-multiselect-input{position:relative}pn-multiselect .pn-multiselect-input>pn-icon{pointer-events:none;position:absolute;top:0.75em;right:3.5em}pn-multiselect .pn-multiselect-input>pn-icon[data-custom]{left:0.75em;right:unset}pn-multiselect .pn-multiselect-button{cursor:pointer;position:absolute;right:0.75em;top:50%;transform:translateY(-50%);padding:0;margin:0;border:0;width:2em;height:2em;font-size:1em;border-radius:50%;background-color:transparent;-webkit-tap-highlight-color:transparent;transition-property:background-color, outline-color, border-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1);outline:0.2rem solid transparent;outline-offset:0.2rem}pn-multiselect .pn-multiselect-button:focus-visible{outline-color:#005d92;background-color:#ffffff;border-color:#005d92}pn-multiselect .pn-multiselect-button>pn-icon>svg>path{transition-property:transform;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1);transition-delay:0.2s;transform-origin:center;transform:rotate(0deg)}pn-multiselect .pn-multiselect-button:hover{background-color:#effbff}pn-multiselect .pn-multiselect-button[aria-expanded=true]{background-color:#effbff}pn-multiselect .pn-multiselect-button[aria-expanded=true]>pn-icon>svg>path{transform:rotate(180deg);transition-delay:0s}pn-multiselect .pn-multiselect-element{color:#2d2013;background-color:#ffffff;border:0.0625em solid #969087;border-radius:0.5em;padding:0.75em;font-family:inherit;font-size:1em;font-weight:500;line-height:1.5em;-webkit-font-smoothing:antialiased;-webkit-tap-highlight-color:transparent;outline:0.2rem solid transparent;outline-offset:0.2rem;transition-property:outline-color, background-color, border-color, color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1);cursor:text;text-align:left;transition-delay:0.1s, 0.1s, 0s;width:100%;padding-right:3.5em;display:flex;align-items:center;justify-content:space-between;gap:0.5em;overflow:hidden;text-overflow:ellipsis}pn-multiselect .pn-multiselect-element:-webkit-autofill,pn-multiselect .pn-multiselect-element:-webkit-autofill:hover,pn-multiselect .pn-multiselect-element:-webkit-autofill:focus,pn-multiselect .pn-multiselect-element:-webkit-autofill:active{-webkit-box-shadow:0 0 0 10em #e0f8ff inset;-webkit-text-fill-color:#2d2013}pn-multiselect .pn-multiselect-element:focus-visible{outline-color:#005d92;background-color:#ffffff;border-color:#005d92}pn-multiselect .pn-multiselect-element::placeholder{color:#5e554a;font-weight:normal}pn-multiselect .pn-multiselect-element:hover{border-color:#005d92}pn-multiselect .pn-multiselect-element:disabled{color:#5e554a;background-color:#f3f2f2;border-color:#f3f2f2}pn-multiselect .pn-multiselect-element:disabled{color:#5e554a;background-color:#f3f2f2;border-color:#f3f2f2;pointer-events:none}pn-multiselect .pn-multiselect-element:disabled+.pn-multiselect-button{pointer-events:none}pn-multiselect .pn-multiselect-element:disabled+.pn-multiselect-button path{fill:#5e554a}pn-multiselect .pn-multiselect-element:placeholder{color:#5e554a;font-weight:normal}pn-multiselect .pn-multiselect-element[type=input]:hover{cursor:pointer;color:#2d2013;background-color:#effbff;transition-delay:0s}pn-multiselect .pn-multiselect-element[type=input]:hover[aria-invalid=true]{background-color:#fdefee}pn-multiselect .pn-multiselect-element:focus-visible{transition-delay:0s}pn-multiselect .pn-multiselect-element::-webkit-search-cancel-button,pn-multiselect .pn-multiselect-element::-webkit-search-decoration{-webkit-appearance:none;-moz-appearance:none;appearance:none}pn-multiselect .pn-multiselect-options{scroll-behavior:smooth;position:absolute;z-index:10;top:calc(100% + 0.5em);left:0;right:0;opacity:0;background-color:#ffffff;box-shadow:0em 0.075em 0.225em 0em rgba(0, 0, 0, 0.1), 0em 0.4em 0.9em 0em rgba(0, 0, 0, 0.13);border-radius:0.5em;list-style:none;margin:0;padding:0;width:var(--pn-select-options-width);max-height:var(--pn-select-max-height);overflow-y:auto;overflow-x:hidden;display:flex;flex-direction:column;visibility:hidden;transform-origin:top left;transform:scaleY(0) translateZ(0)}pn-multiselect .pn-multiselect-options[data-moving]{transition-property:transform, opacity, visibility;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}pn-multiselect .pn-multiselect-options[data-open]{opacity:1;transform:scaleY(1) translateZ(0);visibility:visible}pn-multiselect .pn-multiselect-options[data-upwards]{top:unset;bottom:calc(100% + 0.5em);transform-origin:bottom left;box-shadow:0 -0.0625em 0.125em rgba(0, 0, 0, 0.2)}pn-multiselect .pn-multiselect-options::-webkit-scrollbar{background-color:#ffffff;width:0.875em;border-radius:0.5em}pn-multiselect .pn-multiselect-options::-webkit-scrollbar-track{background-color:#ffffff;border-radius:0.5em}pn-multiselect .pn-multiselect-options::-webkit-scrollbar-thumb{cursor:pointer;background-color:#969087;border-radius:1em;border:0.25em solid #ffffff}pn-multiselect .pn-multiselect-options::-webkit-scrollbar-thumb:hover{background-color:#5e554a}pn-multiselect .pn-multiselect-options::-webkit-scrollbar-corner,pn-multiselect .pn-multiselect-options::-webkit-scrollbar-button{display:none}pn-multiselect .pn-multiselect-options>pn-input{padding:0.5em}pn-multiselect .pn-multiselect-optgroup{list-style:none;padding:0}pn-multiselect .pn-multiselect-optgroup>.pn-multiselect-option>.pn-multiselect-option-content{padding-left:2em}pn-multiselect .pn-multiselect-chips{list-style:none;display:flex;flex-wrap:wrap;gap:0.5em;padding:0;margin:0.5em 0 0 0;color:#5e554a;font-weight:400}pn-multiselect .pn-multiselect-chips:empty{display:none}pn-multiselect .pn-multiselect-chip{margin:0;display:inline-flex;align-items:center;gap:0.25em;background-color:#ffffff;border-radius:0.5em;padding:0.125em 0.25em 0.125em 0.5em;line-height:1.5em;border:0.0625em solid #5e554a;outline:0.2rem solid transparent;outline-offset:0.2rem;transition-property:background-color, outline-color, border-color, color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}pn-multiselect .pn-multiselect-chip:focus-within{color:#005d92;outline-color:#005d92;background-color:#effbff;border-color:#005d92}pn-multiselect .pn-multiselect-chip[data-count]{pointer-events:none;border:0;padding-left:0;padding-right:0;background-color:unset}pn-multiselect .pn-multiselect-chip-label{font-size:0.875em;white-space:nowrap}pn-multiselect .pn-multiselect-chip-button{cursor:pointer;font-size:1em;padding:0.25em;height:1.5em;width:1.5em;border:0;background-color:unset;border-radius:50%;transition-property:background-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1);-webkit-tap-highlight-color:transparent}pn-multiselect .pn-multiselect-chip-button:hover{background-color:#8eddf9}pn-multiselect .pn-multiselect-chip-button:focus{outline:0}pn-multiselect .pn-multiselect-no-results{margin:0;padding:0.75em}pn-multiselect .pn-multiselect-description{color:#5e554a;font-size:0.875em;font-weight:400;margin:0.25em 0 0 0;display:flex;flex-direction:column;gap:0.25em}pn-multiselect .pn-multiselect-description[role=alert]{color:#a70707}pn-multiselect .pn-multiselect-option{position:relative;margin:0;padding:0}pn-multiselect .pn-multiselect-option .pn-ripple{animation:ripple 0.4s cubic-bezier(0.7, 0, 0.3, 1);position:absolute;border-radius:50%;background-color:#005d92;transform:translate(-50%, -50%) scale(0);opacity:0.1;pointer-events:none;z-index:3}@keyframes ripple{to{transform:translate(-50%, -50%) scale(1);opacity:0}}pn-multiselect .pn-multiselect-option-input{cursor:pointer;position:absolute;opacity:0;left:0;top:0;height:100%;width:100%;margin:0;-webkit-tap-highlight-color:transparent}pn-multiselect .pn-multiselect-option-input:disabled{pointer-events:none}pn-multiselect .pn-multiselect-option-input:disabled+.pn-multiselect-option-content{color:#5e554a;background-color:#f3f2f2;border-color:#f3f2f2;pointer-events:none}pn-multiselect .pn-multiselect-option-input:disabled+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#f3f2f2;border-color:#969087}pn-multiselect .pn-multiselect-option-input:disabled+.pn-multiselect-option-content path{fill:#5e554a}pn-multiselect .pn-multiselect-option-input:disabled:checked+.pn-multiselect-option-content{color:#5e554a;background-color:#f3f2f2;border-color:#f3f2f2}pn-multiselect .pn-multiselect-option-input:disabled:checked+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#969087;border-color:#969087}pn-multiselect .pn-multiselect-option-input:disabled:checked+.pn-multiselect-option-content path{fill:#5e554a}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]+.pn-multiselect-option-content .pn-multiselect-option-checkbox{border-color:#a70707}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]+.pn-multiselect-option-content .pn-ripple{background-color:#a70707}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:checked+.pn-multiselect-option-content{background-color:#fdefee}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:checked+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#a70707;border-color:#a70707}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:checked:focus-visible+.pn-multiselect-option-content{background-color:#fdefee}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:checked:focus-visible+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#500715;border-color:#500715}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:checked:hover+.pn-multiselect-option-content{background-color:#fef7f6}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:checked:hover+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#500715;border-color:#500715}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:hover+.pn-multiselect-option-content{background-color:#fef7f6}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:hover+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#fdefee;border-color:#a70707}pn-multiselect .pn-multiselect-option-input[aria-invalid=true]:focus-visible+.pn-multiselect-option-content .pn-multiselect-option-checkbox{outline-color:#a70707;background-color:#fdefee;border-color:#a70707}pn-multiselect .pn-multiselect-option-input:hover+.pn-multiselect-option-content{background-color:#effbff}pn-multiselect .pn-multiselect-option-input:hover+.pn-multiselect-option-content .pn-multiselect-option-checkbox{border-color:#005d92;background-color:#e0f8ff}pn-multiselect .pn-multiselect-option-input:focus-visible+.pn-multiselect-option-content .pn-multiselect-option-checkbox{outline-color:#005d92;background-color:#e0f8ff;border-color:#005d92}pn-multiselect .pn-multiselect-option-input:checked+.pn-multiselect-option-content{background-color:#e0f8ff}pn-multiselect .pn-multiselect-option-input:checked+.pn-multiselect-option-content .pn-multiselect-option-checkbox{border-color:#005d92;background-color:#005d92}pn-multiselect .pn-multiselect-option-input:checked+.pn-multiselect-option-content .pn-multiselect-option-checkbox svg polyline.pn-multiselect-option-checkbox-checkmark-path{transition-delay:0.2s;stroke-dashoffset:0}pn-multiselect .pn-multiselect-option-input:checked:hover+.pn-multiselect-option-content{background-color:#effbff}pn-multiselect .pn-multiselect-option-input:checked:hover+.pn-multiselect-option-content .pn-multiselect-option-checkbox{border-color:#0d234b;background-color:#0d234b}pn-multiselect .pn-multiselect-option-input:checked:focus-visible+.pn-multiselect-option-content{background-color:#e0f8ff}pn-multiselect .pn-multiselect-option-input:checked:focus-visible+.pn-multiselect-option-content .pn-multiselect-option-checkbox{border-color:#0d234b;background-color:#0d234b}pn-multiselect .pn-multiselect-option-input:indeterminate+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#005d92;border-color:#005d92}pn-multiselect .pn-multiselect-option-input:indeterminate+.pn-multiselect-option-content svg .pn-multiselect-option-checkbox-checkmark-path{stroke-dashoffset:23}pn-multiselect .pn-multiselect-option-input:indeterminate+.pn-multiselect-option-content svg .pn-multiselect-option-checkbox-indeterminate-path{stroke-dashoffset:0}pn-multiselect .pn-multiselect-option-input:indeterminate:hover+.pn-multiselect-option-content .pn-multiselect-option-checkbox{background-color:#0d234b;border-color:#0d234b}pn-multiselect .pn-multiselect-option-content{position:relative;overflow:hidden;z-index:-1;display:flex;align-items:center;padding:0.75em 1em;gap:0.5em;background-color:#ffffff;transition-property:background-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}pn-multiselect .pn-multiselect-option-text{flex:1;text-overflow:ellipsis;overflow:hidden}pn-multiselect .pn-multiselect-option-label{color:#2d2013;font-weight:400}pn-multiselect .pn-multiselect-option-helper{color:#5e554a;margin:0}pn-multiselect .pn-multiselect-option-checkbox{background-color:#ffffff;flex:0 0 1.5em;width:1.5em;height:1.5em;border:0.0625em solid #969087;border-radius:0.25em;outline:0.2rem solid transparent;outline-offset:0.2rem;transition-property:background-color, border-color, outline-color;transition-duration:0.2s;transition-timing-function:cubic-bezier(0.7, 0, 0.3, 1)}pn-multiselect .pn-multiselect-option-checkbox svg polyline{stroke:#ffffff;stroke-linecap:round;stroke-dasharray:23;transition:stroke-dashoffset 0.2s cubic-bezier(0.7, 0, 0.3, 1) 0s}pn-multiselect .pn-multiselect-option-checkbox svg polyline.pn-multiselect-option-checkbox-checkmark-path{stroke-dashoffset:23}pn-multiselect .pn-multiselect-option-checkbox svg polyline.pn-multiselect-option-checkbox-indeterminate-path{stroke-dashoffset:23}"; const PnMultiselectStyle0 = pnMultiselectCss; const PnMultiselect$1 = /*@__PURE__*/ proxyCustomElement(class PnMultiselect extends HTMLElement { constructor() { super(); this.__registerHost(); this.toggleSelect = createEvent(this, "toggleSelect", 7); this.allOptions = createEvent(this, "allOptions", 7); this.selectedOption = createEvent(this, "selectedOption", 7); this.selectedAllOptions = createEvent(this, "selectedAllOptions", 7); this.searchInput = createEvent(this, "searchInput", 7); this.isSearching = false; this.open = false; this.moving = false; this.upwards = false; this.srMessage = undefined; this.label = undefined; this.helpertext = undefined; this.placeholder = undefined; this.name = undefined; this.selectId = this.id; this.selectName = undefined; this.icon = undefined; this.language = null; this.options = undefined; this.selectAll = false; this.allValue = 'pn_multiselect_all'; this.search = false; this.searchQuery = ''; this.itemCount = 5; this.maxHeight = undefined; this.top = false; this.bottom = false; this.required = false; this.disabled = false; this.invalid = false; this.error = undefined; } id = `pn-multiselect-${uuidv4()}`; idLegend = `${this.id}-legend`; idButton = `${this.id}-button`; idOptions = `${this.id}-options`; idHelper = `${this.id}-text`; idChips = `${this.id}-chips`; idSr = `${this.id}-sr`; elGroup; elButton; elInput; elList; elChips; movingTimer; srTimer; get hostElement() { return this; } handleOpen() { this.handleMoving(); if (this.open) { this.handleDirection(); this.handleMaxHeight(); this.handleWidth(); } } handleSearch() { if (!this.search) this.options = [ ...this.options.map(option => { const item = { ...option, hide: false, }; if (item?.group?.length) item.group.map(opt => ({ ...opt, hide: false })); return item; }), ]; } handleSearchQuery() { if (this.search && typeof this.searchQuery === 'string') this.handleInputSearch(); } handleSelectId() { const id = this.selectId; this.idLegend = `${id}-legend`; this.idButton = `${id}-button`; this.idOptions = `${id}-options`; this.idHelper = `${id}-text`; this.idChips = `${id}-chips`; this.idSr = `${id}-sr`; } /** * If the select is open and you resize the window. * Remove all css props and disable the animations entierly. **/ handleResize({ type }) { if (!this.open) return; this.toggleOpen(false); this.moving = type === 'resize'; this.elList.style.removeProperty('--pn-select-options-width'); this.elList.style.removeProperty('--pn-select-max-height'); } /** Dispatched everytime the multiselect is opened or closed. */ toggleSelect; /** This event contains the entire options array with the new props. Dispatched everytime you make changes to any option. */ allOptions; /** Dispatched when you toggle an option. Includes all the props of the option. */ selectedOption; /** * This event is dispatched when the user toggles the "Choose all options" box. * Also triggers when you click the "Select {number} options" if you are performing a search at the same time. **/ selectedAllOptions; /** * Contains the search text and the options found for that query. * Dispacthed everytime you change the search query. **/ searchInput; async componentWillLoad() { this.handleSelectId(); if (this.language === null) await awaitTopbar(this.hostElement); } componentDidLoad() { if (!!this.searchQuery?.length) this.handleSearchQuery(); } emitEvents(option, all) { this.allOptions.emit(this.options); if (option) return this.selectedOption.emit(option); const data = { checked: all, searching: this.isSearching, }; if (this.search && this.optionsTotal() !== this.optionsSearch().length) { data.query = this.searchQuery; data.found = this.optionsSearch(); } this.selectedAllOptions.emit(data); } optionsChecked() { const list = this.options?.reduce((sum, item) => { const subgroup = item.group ? [...item.group.filter(({ checked }) => checked)] : []; if (item.checked) sum.push(item); if (subgroup?.length) sum.push(...subgroup); return sum; }, []); return list; } optionsTotal() { return this.options?.reduce((sum, item) => sum + (item?.group?.length ? item.group.length + 1 : 1), 0); } optionsIndex(val) { const findNested = ({ group = [] }) => group?.findIndex(({ value }) => value === val); const indexGroup = this.options.findIndex(option => option.value === val || findNested(option) !== -1); const indexNested = findNested(this.options?.[indexGroup]); return { indexGroup, indexNested, }; } optionsCheckedTotal() { return this.optionsChecked()?.length; } optionsCheckedPreview() { return this.optionsChecked()?.slice(0, this.itemCount); } optionsCheckedLabels() { return this.optionsChecked() ?.map(({ label }) => label) ?.join(', '); } optionsSearch() { const list = this.options?.reduce((sum, item) => { const subgroup = item.group ? [...item.group.filter(({ hide }) => !hide)] : []; if (!item.hide) sum.push(item); if (subgroup?.length) sum.push(...subgroup); return sum; }, []); return list; } noResults() { return this.optionsSearch()?.length === 0; } isIndeterminate(groupIndex) { const option = this.options?.[groupIndex]; if (option?.group?.length) { const all = option.group.every(({ checked }) => checked); const none = option.group.every(({ checked }) => !checked); return !(all || none); } return false; } optionSelect({ val, checked, chip }) { if (val === this.allValue) return this.optionSelectAll(checked); const options = this.options; const { indexGroup, indexNested } = this.optionsIndex(val); const group = options[indexGroup]?.group; const nested = group?.[indexNested]; if (nested?.value) { options[indexGroup].group[indexNested].checked = checked; const allSiblingsChecked = group?.every(({ checked }) => checked); if (allSiblingsChecked) options[indexGroup].checked = true; else options[indexGroup].checked = false; } else { options[indexGroup].checked = checked; if (group?.length) options[indexGroup].group = group?.map(opt => ({ ...opt, checked: checked })); } const option = indexNested === -1 ? options[indexGroup] : options[indexGroup].group[indexNested]; this.emitEvents(option); this.options = [...options]; if (typeof chip === 'number') { this.handleSrMesssage(`${this.translate('REMOVED')} ${option.label}`); requestAnimationFrame(() => { const index = chip === this.optionsCheckedTotal() ? chip - 1 : chip; const btn = Array.from(this.elChips.children)?.[index]; btn?.querySelector('button').focus({ preventScroll: true }); }); } } optionSelectAll(checked) { this.options = [ ...this.options.map(option => { const opt = { ...option, checked: this.isSearching ? (option.hide ? option.checked : checked) : checked, }; if (opt.group) opt.group = [ ...opt.group.map(item => ({ ...item, checked: this.isSearching ? (item.hide ? item.checked : checked) : checked, })), ]; const allChecked = opt?.group?.every(({ checked }) => checked); if (opt?.group?.length) opt.checked = allChecked; return opt; }), ]; this.emitEvents(null, checked); } optionSelected(val) { return !!this.optionsChecked()?.find(({ value, checked }) => value === val && checked); } translate(prop) { const text = translations?.[prop]?.[this.language || en]; if (text.includes('{number}')) return text.replace('{number}', this.optionsSearch().length); return text; } getRect(element) { return element?.getBoundingClientRect(); } ripple({ clientX, clientY, target }) { const isKeyboard = clientX === 0 && clientY === 0; const element = target.nextElementSibling; const { x, width, y, top } = this.getRect(element); const clientCor = isKeyboard ? { clientX: x + width - 24, clientY: y - top } : { clientX, clientY }; ripple(clientCor, element); } handleMoving() { this.moving = true; clearTimeout(this.movingTimer); this.movingTimer = setTimeout(() => (this.moving = false), 200); } handleSrMesssage(text) { this.srMessage = text; clearTimeout(this.srTimer); this.srTimer = setTimeout(() => (this.srMessage = null), 2000); } handleDirection() { if (this.top) return (this.upwards = true); if (this.bottom) return (this.upwards = false); const { bottom, top } = this.getRect(this.elInput); const oneEm = 16; /* * Take the inner window height and subtract the elements bottom and 1em (16px) * If the max height of this calculation is less than the space above the element, open it upwards. * Do another calculation with the top value - 1em. */ const offsetTop = window.innerHeight - bottom - oneEm; const offsetBottom = top - oneEm; /** Always point downwards, unless the space to the bottom is less than half of the top offset space. */ this.upwards = offsetBottom / 2 > offsetTop; } handleMaxHeight() { if (this.maxHeight) return this.elGroup.style.setProperty('--pn-select-max-height', this.maxHeight); const { bottom, top } = this.getRect(this.elInput); const inputHeight = this.upwards ? top : bottom; const offsetTop = getTotalHeightOffset(); const offset = this.upwards ? offsetTop + 16 : 16; const maxHeight = this.upwards ? inputHeight - offset : window.innerHeight - inputHeight - offset; this.elGroup.style.setProperty('--pn-select-max-height', `${Math.ceil(maxHeight)}px`); } handleWidth() { const { width } = this.getRect(this.elInput); this.elGroup.style.setProperty('--pn-select-options-width', `${Math.ceil(width)}px`); } setFocus() { if (this.search) this.elInput.focus({ preventScroll: true }); else this.elButton.focus({ preventScroll: true }); } hasError() { return this.invalid || !!this.error; } hasMessage() { return !!this.helpertext || !!this.error; } toggleOpen(state) { this.open = state ?? !this.open; this.toggleSelect.emit({ open: this.open }); } handleInputKeyboard(event) { const { code } = event; if (code === 'Escape') return this.toggleOpen(false); if (!this.open && code.match(/^(Space|Enter)$|Arrow|^Key.*$/)) this.toggleOpen(); } setSearchQuery(value) { this.searchQuery = value; } handleInputSearch() { if (this.isEmpty()) return; const term = this.searchQuery; const performSearch = ({ label, helpertext, value }) => { return `${label} ${helpertext} ${value}`.trim().toLowerCase().includes(term.toLowerCase()); }; const options = this.options.map(option => { const foundNested = option?.group?.map(item => ({ ...item, hide: !performSearch(item) })) || []; const found = performSearch(option) || foundNested?.some(({ hide }) => !hide); option.hide = !found; if (option?.group?.length) option.group = [...foundNested]; return option; }); this.isSearching = term !== ''; this.options = [...options]; this.searchInput.emit({ query: term, found: this.optionsSearch() }); } getListItem(index) { const { value } = this.options[index]; return this.elList.querySelector(`.pn-multiselect-option-input[value='${value}']`); } getOptionIndex(val, triggers, code) { const total = this.optionsTotal() - 1; if (code === 'End') return total; if (code === 'Home') return 0; const valIndex = this.options.findIndex(({ value }) => value === val); const count = triggers.find(item => typeof item === 'number'); const index = valIndex + count; if (index >= total) return total; if (index <= 0) return 0; return index; } checkboxNav(e, val) { const { code } = e; const arrowUp = code === 'ArrowUp' && -1; const arrowDown = code === 'ArrowDown' && 1; const pageUp = code === 'PageUp' && -10; const pageDown = code === 'PageDown' && 10; const home = code === 'Home' && 0; const end = code === 'End' && this.optionsTotal() - 1; const tab = code === 'Tab'; const space = code === 'Space'; const enter = code === 'Enter'; const escape = code === 'Escape'; const triggers = [arrowUp, arrowDown, pageUp, pageDown, home, end, tab, space, enter, escape]; if (!triggers.some(item => typeof item === 'number' || item)) return; if (tab || space || enter) return; if (escape) { this.setFocus(); return this.toggleOpen(false); } const item = this.getOptionIndex(val, triggers, code); e.preventDefault(); return this.getListItem(item)?.focus(); } handleBlur(event) { const target = event.relatedTarget; const currentSelect = target?.closest('pn-multiselect'); const insideCurrent = currentSelect?.selectId === this.selectId; const jumpingToChips = event.relatedTarget?.className === 'pn-multiselect-chip-button'; if (!insideCurrent || jumpingToChips) this.toggleOpen(false); } handleLabel() { if (this.disabled) return; this.setFocus(); } /** Check if there are no options in the list. */ isEmpty() { return (this.options?.length || 0) === 0; } showSelectAll() { return this.selectAll && !this.isEmpty() && !this.noResults(); } /** Check if the empty/nothing found should be visible. */ showEmptyOption() { return (this.isSearching && this.noResults()) || this.isEmpty(); } getPlaceholder() { const autoTranslation = this.search ? 'SEARCH' : 'SELECT_AN_OPTION'; return this.placeholder || this.translate(autoTranslation); } handleChange({ target }) { const { value, checked } = target; this.optionSelect({ val: value, checked }); } /** Display the "X more selected options" text. */ additonalOptions() { const count = this.optionsCheckedTotal() - this.itemCount; const single = `MORE_OPTION${count === 1 ? '' : 'S'}`; return `${count} ${this.translate(single)}`; } describedBy() { const list = [this.search && this.idChips, this.srMessage && this.idSr, !!this.helpertext && this.idHelper].filter(Boolean); if (list.length) return list.join(' '); return null; } renderOption({ label, value, checked, helpertext, icon, id = `${this.selectId}-${value || label}`, invalid, disabled, hide, group, }, indexGroup, indexNested) { return (h("li", { class: "pn-multiselect-option", key: id, hidden: hide }, h("input", { type: "checkbox", id: id, class: "pn-multiselect-option-input", checked: checked ?? this.optionSelected(value), indeterminate: indexNested === undefined && this.isIndeterminate(indexGroup), name: this.name, value: value, disabled: this.disabled || disabled, required: this.required, "aria-invalid": invalid ? 'true' : null, "aria-describedby": helpertext ? `${id}-helper` : null, onClick: (event) => this.ripple(event), onKeyDown: (event) => this.checkboxNav(event, value), onBlur: (event) => this.handleBlur(event) }), h("div", { class: "pn-multiselect-option-content" }, !!icon && h("pn-icon", { icon: icon, color: "blue900" }), h("div", { class: "pn-multiselect-option-text" }, h("label", { class: "pn-multiselect-option-label", htmlFor: id }, h("span", null, label)), helpertext && (h("p", { class: "pn-multiselect-option-helper", id: `${id}-helper` }, helpertext))), h("div", { class: "pn-multiselect-option-checkbox" }, h("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 24 24", fill: "none" }, h("polyline", { class: "pn-multiselect-option-checkbox-checkmark-path", points: "4,12 9,17 20,6", "stroke-width": "3" }), h("polyline", { class: "pn-multiselect-option-checkbox-indeterminate-path", points: "4,12 20,12", "stroke-width": "3" })))), group?.length && (h("ul", { class: "pn-multiselect-optgroup" }, group?.map((option, i) => this.renderOption(option, indexGroup, i)))))); } renderOptions() { return (h("ul", { id: this.idOptions, class: "pn-multiselect-options", "data-open": this.open, "data-upwards": this.upwards, "data-moving": this.moving, onChange: (event) => this.handleChange(event), ref: el => (this.elList = el) }, this.showSelectAll() && this.renderOption({ label: this.translate(`SELECT_${this.isSearching ? 'FOUND' : 'ALL'}_OPTIONS`), value: this.allValue, checked: this.optionsTotal() === this.optionsCheckedTotal(), }), this.options?.map((option, index) => this.renderOption(option, index)), this.showEmptyOption() && (h("li", { class: "pn-multiselect-option" }, h("div", { class: "pn-multiselect-option-content", role: "alert" }, h("div", { class: "pn-multiselect-option-text" }, h("span", { class: "pn-multiselect-option-label" }, this.translate(this.isEmpty() ? 'NO_OPTIONS' : 'NO_SEARCH_RESULTS')))))))); } renderChips() { return (h("ul", { id: this.idChips, class: "pn-multiselect-chips", "aria-label": this.translate('SELECTED_OPTIONS'), ref: el => (this.elChips = el) }, this.optionsCheckedPreview()?.map(({ label, value }, index) => (h("li", { class: "pn-multiselect-chip", "aria-setsize": this.optionsCheckedTotal(), "aria-posinset": index + 1, key: `${label}-${value}` }, h("span", { class: "pn-multiselect-chip-label" }, label), h("button", { type: "button", class: "pn-multiselect-chip-button", "aria-label": `${this.translate('REMOVE')} ${label}`, onClick: () => this.optionSelect({ val: value, checked: false, chip: index }) }, h("pn-icon", { icon: close, small: true, color: "blue700" }))))), this.optionsCheckedTotal() > this.itemCount && (h("li", { class: "pn-multiselect-chip", "data-count": true }, h("span", { class: "pn-multiselect-chip-label" }, "+ ", this.additonalOptions()))))); } render() { return (h(Host, { key: '4d58fe38a9cd652173ea9f2cea2bf3c1aadfe24d' }, h("fieldset", { key: 'b0e73e9df6fb42392dec0ea6f83e906f34b04963', class: "pn-multiselect", "data-icon": !!this.icon, "data-error": this.hasError(), disabled: this.disabled }, this.label && (h("legend", { key: 'a89d4b85e3f1d4d79855fb3cf64a810f815f375a', id: this.idLegend, class: "pn-multiselect-label", onClick: () => this.handleLabel() }, h("span", { key: '4c888cc040b1c8dfba6983e62ccbdf2850d46976' }, this.label), !!this.optionsChecked()?.length && (h("span", { key: 'b648b8dc76e23abf0245f796b2368773def82b4f' }, this.optionsCheckedTotal(), "/", this.optionsTotal())))), h("div", { key: '73e0b4a56211c128071f87a7507cd286660d1dd8', class: "pn-multiselect-group", ref: el => (this.elGroup = el) }, h("div", { key: '6a23dceb2e31cd80f2b9373f2455b996c53e454b', class: "pn-multiselect-input" }, !!this.icon && h("pn-icon", { key: 'ce6bec5aac2398db1583dca4791866197ffc5379', class: "pn-multiselect-icon", "data-custom": true, icon: this.icon }), h("input", { key: '509b6ae212e7ad34a825806816be9bda9b9691a6', tabindex: this.search ? null : '-1', type: this.search ? 'search' : 'input', id: this.selectId, class: "pn-multiselect-element", value: this.search ? this.searchQuery : this.optionsCheckedLabels(), name: this.selectName, placeholder: this.getPlaceholder(), required: this.search ? null : this.required, "aria-labelledby": this.idLegend, "aria-describedby": this.describedBy(), "aria-controls": `${this.idOptions} ${this.search ? this.idChips : ''}`, "aria-invalid": this.hasError()?.toString(), disabled: this.disabled, readonly: !this.search, onClick: () => this.toggleOpen(), onKeyDown: e => this.handleInputKeyboard(e), onBlur: e => this.handleBlur(e), onInput: e => this.search && this.setSearchQuery(e.target.value), ref: el => (this.elInput = el) }), this.hasError() && (h("pn-icon", { key: 'eee58901db95ce805a247bc5c5c6e93dacbfbfb3', class: "pn-multiselect-icon", "data-error": true, icon: alert_exclamation_circle, color: "warning" })), h("button", { key: 'ddd3fadcd289b6b10f90f5d1c14bce16c9148096', id: this.idButton, type: "button", class: "pn-multiselect-button", "aria-label": this.translate(`BUTTON_${this.open ? 'CLOSE' : 'OPEN'}`), "aria-describedby": this.search ? null : this.selectId, "aria-controls": this.idOptions, "aria-expanded": this.open.toString(), onClick: () => this.toggleOpen(), ref: el => (this.elButton = el) }, h("pn-icon", { key: '5d2b2556f0696c39489863a19d36be0ccdd34644', class: "pn-multiselect-icon", icon: angle_down, color: "blue700" }))), this.renderOptions()), this.hasMessage() && (h("p", { key: '89dc5ec7faaa1f4d1d734449eafa836fc00a5b8b', id: this.idHelper, class: "pn-multiselect-description", role: !!this.error ? 'alert' : null }, h("span", { key: 'a3041c171672223c64d0d3f50f11e4b7c650873e' }, this.error || this.helpertext))), this.search && this.renderChips(), h("slot", { key: 'd420c415a2f145bd0ddd27c8b70335629a83c93b' }), this.search && (h("p", { key: 'ed08dbce5e58a3a8047317c5756b7792225f7560', id: this.idSr, class: "pn-multiselect-sr-only", role: "alert", "aria-live": "assertive" }, this.srMessage && h("span", { key: '15edfdab7417fc70f44e098c3f9943d59ad7eb8f' }, this.srMessage)))))); } static get watchers() { return { "open": ["handleOpen"], "search": ["handleSearch"], "searchQuery": ["handleSearchQuery"], "selectId": ["handleSelectId"] }; } static get style() { return PnMultiselectStyle0; } }, [4, "pn-multiselect", { "label": [1], "helpertext": [1], "placeholder": [1], "name": [1], "selectId": [1, "select-id"], "selectName": [1, "select-name"], "icon": [1], "language": [1], "options": [1040], "selectAll": [4, "select-all"], "allValue": [1, "all-value"], "search": [4], "searchQuery": [1025, "search-query"], "itemCount": [2, "item-count"], "maxHeight": [1, "max-height"], "top": [4], "bottom": [4], "required": [4], "disabled": [4], "invalid": [4], "error": [1], "isSearching": [32], "open": [32], "moving": [32], "upwards": [32], "srMessage": [32] }, [[9, "resize", "handleResize"]], { "open": ["handleOpen"], "search": ["handleSearch"], "searchQuery": ["handleSearchQuery"], "selectId": ["handleSelectId"] }]); function defineCustomElement$1() { if (typeof customElements === "undefined") { return; } const components = ["pn-multiselect", "pn-icon"]; components.forEach(tagName => { switch (tagName) { case "pn-multiselect": if (!customElements.get(tagName)) { customElements.define(tagName, PnMultiselect$1); } break; case "pn-icon": if (!customElements.get(tagName)) { defineCustomElement$2(); } break; } }); } const PnMultiselect = PnMultiselect$1; const defineCustomElement = defineCustomElement$1; export { PnMultiselect, defineCustomElement }; //# sourceMappingURL=pn-multiselect.js.map