UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

516 lines (513 loc) 23.2 kB
import { E as y, x as d, n as r, a as k } from "./element-CgEWt74-.js"; import { o as f } from "./if-defined-CmuO4Vz9.js"; import { r as c } from "./state-Bo2bck5_.js"; import { e as _, n as v } from "./ref-BBYSqgeW.js"; import { e as w } from "./class-map-BpTj9gtz.js"; import { c as R } from "./repeat-C8BeHwYx.js"; import { P as V } from "./input-element-NnrDmp4r.js"; import { P as S } from "./pkt-options-controller-CZO1nxZ8.js"; import { P as C } from "./pkt-slot-controller-BPGj-LC5.js"; import "./input-wrapper-Dr__Sxql.js"; import "./icon-CC1js8eR.js"; import "./tag-BWm6s48d.js"; import "./listbox-CLsSW32I.js"; const A = { displayValueAs: { default: "label" } }, T = { props: A }; var M = Object.defineProperty, F = Object.getOwnPropertyDescriptor, o = (t, e, i, s) => { for (var l = s > 1 ? void 0 : s ? F(e, i) : e, n = t.length - 1, a; n >= 0; n--) (a = t[n]) && (l = (s ? a(e, i, l) : a(l)) || l); return s && l && M(e, i, l), l; }; let h = class extends V { constructor() { super(), this.helptextSlot = _(), this.value = "", this.options = [], this.defaultOptions = [], this.allowUserInput = !1, this.typeahead = !1, this.includeSearch = !1, this.searchPlaceholder = "", this.multiple = !1, this.maxlength = null, this.displayValueAs = T.props.displayValueAs.default, this.tagPlacement = null, this._options = [], this._isOptionsOpen = !1, this._value = [], this._userInfoMessage = "", this._addValueText = null, this._maxIsReached = !1, this._search = "", this._inputFocus = !1, this._editingSingleValue = !1, this.inputRef = _(), this.arrowRef = _(), this.listboxRef = _(), this.focusRef = _(), this.optionTagRef = _(), this.optionsController = new S(this), this.slotController = new C(this, this.helptextSlot), this.slotController.skipOptions = !0; } // Lifecycle methods connectedCallback() { var t; if (super.connectedCallback(), document && document.body.addEventListener("click", (e) => { this._isOptionsOpen && !this.contains(e.target) && this.handleFocusOut(e); }), this._options = [], this.defaultOptions && this.defaultOptions.length) { const e = ((t = this.options) == null ? void 0 : t.filter((i) => i.userAdded)) || []; this.options = [...e, ...JSON.parse(JSON.stringify(this.defaultOptions))], this._options = [...this.options]; } if (this.optionsController.nodes.length) { const e = []; this.optionsController.nodes.forEach((i) => { if (!i.textContent && !i.getAttribute("value")) return null; const s = { value: i.getAttribute("value") || i.textContent || "", label: i.textContent || i.getAttribute("value") || "" }; i.getAttribute("data-prefix") && (s.prefix = i.getAttribute("data-prefix") || void 0), i.getAttribute("tagskincolor") && (s.tagSkinColor = i.getAttribute("tagskincolor")), i.getAttribute("description") && (s.description = i.getAttribute("description") || void 0), s.fulltext = s.value + s.label + (s.prefix || ""), e.push(s); }), e.length && (this.options = [...e], this._options = [...e]); } } updated(t) { var e; if (t.has("_value") && this.valueChanged(this._value, t.get("_value")), t.has("value") && (this._value = Array.isArray(this.value) ? this.value : this.value ? this.value.split(",") : [], !this.multiple && this._value.length > 1 && (this._value = [this._value[0]]), this.isMaxItemsReached()), t.has("defaultOptions") && this.defaultOptions.length) { const i = ((e = this.options) == null ? void 0 : e.filter((s) => s.userAdded)) || []; this.options = [...i, ...JSON.parse(JSON.stringify(this.defaultOptions))], this._options = [...this.options]; } if (t.has("options") && this.options.length) { const s = this._options.filter((l) => l.userAdded).filter( (l) => !this.options.some((n) => n.value === l.value) ); this._options = [...s, ...this.options], this._options.forEach((l) => { if (l.value && !l.label && (l.label = l.value), l.selected && !this._value.includes(l.value)) { const n = [...this._value]; this._value = [...this._value, l.value], this.valueChanged(this._value, n); } l.fulltext = l.value + l.label + (l.prefix || ""), l.selected = l.selected || this._value.includes(l.value); }); } t.has("_search") && this.dispatchEvent( new CustomEvent("search", { detail: this._search, bubbles: !1 }) ), super.updated(t); } attributeChangedCallback(t, e, i) { t === "value" && (this._value = Array.isArray(this.value) ? this.value : this.value ? this.value.split(",") : [], !this.multiple && this._value.length > 1 && (this._value = [this._value[0]])), t === "options" && (this._options = this.options, this._options.forEach((s) => { s.value && !s.label && (s.label = s.value), s.selected && !this._value.includes(s.value) && (this._value = [...this._value, s.value]), s.fulltext = s.value + s.label + (s.prefix || ""); }), this._search = ""), super.attributeChangedCallback(t, e, i); } // Render methods render() { return d` <pkt-input-wrapper .label=${this.label} .helptext=${this.helptext} .helptextDropdown=${f(this.helptextDropdown)} .helptextDropdownButton=${f(this.helptextDropdownButton)} ?fullwidth=${this.fullwidth} ?hasError=${this.hasError} ?inline=${this.inline} ?disabled=${this.disabled} .errorMessage=${this.errorMessage} ?optionalTag=${this.optionalTag} .optionalText=${this.optionalText} ?requiredTag=${this.requiredTag} .requiredText=${this.requiredText} .tagText=${this.tagText} ?useWrapper=${this.useWrapper} .forId=${this.allowUserInput || this.typeahead ? this.id + "-input" : this.id + "-arrow"} class="pkt-combobox__wrapper" @labelClick=${this.handleInputClick} > <div class="pkt-contents" ${v(this.helptextSlot)} name="helptext" slot="helptext"></div> <div class="pkt-combobox" @focusout=${this.handleFocusOut}> <div class=${w({ "pkt-combobox__input": !0, "pkt-combobox__input--fullwidth": this.fullwidth, "pkt-combobox__input--open": this._isOptionsOpen, "pkt-combobox__input--error": this.hasError, "pkt-combobox__input--disabled": this.disabled })} tabindex="-1" @click=${this.handleInputClick} > ${this.placeholder && (!this._value.length || this.multiple && this.tagPlacement == "outside") && !this._inputFocus ? d`<span class="pkt-combobox__placeholder">${this.placeholder}</span>` : this.tagPlacement !== "outside" ? this.renderSingleOrMultipleValues() : y} ${this.renderInputField()} <div class="pkt-btn pkt-btn--tertiary pkt-combobox__arrow" @click=${this.handleArrowClick} @keydown=${this.handleArrowClick} id="${this.id}-arrow" ${v(this.arrowRef)} aria-expanded=${this._isOptionsOpen} aria-controls="${this.id}-listbox" aria-haspopup="listbox" aria-label="Åpne liste" ?disabled=${this.disabled} ?data-disabled=${this.disabled} role="button" tabindex="${this.disabled ? "-1" : "0"}" > <pkt-icon class=${w({ "pkt-combobox__arrow-icon": !0, "pkt-combobox__arrow-icon--open": this._isOptionsOpen })} name="chevron-thin-down" ></pkt-icon> </div> <div ${v(this.focusRef)} tabindex="-1" @keydown=${this.handleArrowClick}></div> </div> <pkt-listbox id="${this.id}-listbox" .options=${this._options} .isOpen=${this._isOptionsOpen} .searchPlaceholder=${this.searchPlaceholder} .label="Liste: ${this.label || ""}" ?includeSearch=${this.includeSearch} ?isMultiSelect=${this.multiple} ?allowUserInput=${this.allowUserInput && !this._maxIsReached} ?maxIsReached=${this._maxIsReached} .customUserInput=${f(this._addValueText)} .userMessage=${this._userInfoMessage} @search=${this.handleSearch} @option-toggle=${this.handleOptionToggled} @select-all=${this.addAllOptions} @close-options=${() => this._isOptionsOpen = !1} .searchValue=${this._search || null} .maxLength=${this.maxlength || 0} ${v(this.listboxRef)} ></pkt-listbox> </div> ${this.tagPlacement === "outside" && this.multiple ? d`<div class="pkt-combobox__tags-outside"> ${this.renderSingleOrMultipleValues()} </div>` : y} </pkt-input-wrapper> `; } renderInputField() { return this.typeahead || this.allowUserInput ? d` <div class="pkt-combobox__input-div combobox__input"> <input type="text" id="${this.id}-input" name=${(this.name || this.id) + "-input"} @input=${this.handleInput} @keydown=${this.handleInputKeydown} @focus=${this.handleFocus} @blur=${this.handleBlur} autocomplete="off" role="combobox" aria-label=${f(this.label)} aria-autocomplete=${this.typeahead ? "both" : "list"} aria-controls="${this.id}-listbox" aria-multiselectable=${f(this.multiple ? "true" : void 0)} aria-activedescendant=${f( this._value[0] && this.findValueInOptions(this._value[0]) ? `${this.id}-listbox-${this.findIndexInOptions(this._value[0])}` : void 0 )} ${v(this.inputRef)} /> </div> ` : d` <input type="hidden" id="${this.id}-input" name=${(this.name || this.id) + "-input"} .value=${this._value.join(",")} ${v(this.inputRef)} /> `; } renderSingleOrMultipleValues() { const t = !this.multiple, e = this._editingSingleValue ? null : this.renderValueTag(this.findValueInOptions(this._value[0])), i = R( this._value, (s) => s, (s) => { var a; const l = this.findValueInOptions(s), n = (a = this.options.find((u) => u.value === s)) == null ? void 0 : a.tagSkinColor; return d` <pkt-tag skin=${n || "blue-dark"} ?closeTag=${!this.disabled} @close=${() => this.handleTagRemove(s)} > ${this.renderValueTag(l)} </pkt-tag> `; } ); return t ? e : i; } renderValueTag(t) { if (!t) return ""; switch (this.displayValueAs) { case "prefixAndValue": return d`<span data-focusfix=${this.id}>${t.prefix || ""} ${t.value}</span>`; case "value": return d`<span data-focusfix=${this.id}>${t.value}</span>`; case "label": default: return d`<span data-focusfix=${this.id}>${t.label || t.value}</span>`; } } // Event handlers handleInput(t) { if (t.stopPropagation(), t.stopImmediatePropagation(), this.disabled) return; this.touched = !0; const e = t.target; if (this._search = e.value, this.checkForMatches(), this.typeahead) if (this._search) { if (this._options = this.options.filter( (i) => { var s; return (s = i.fulltext) == null ? void 0 : s.toLowerCase().includes(this._search.toLowerCase()); } ), t.inputType !== "deleteContentBackward") { const i = this._options.filter( (s) => { var l; return !s.selected && ((l = s.label) == null ? void 0 : l.toLowerCase().startsWith(this._search.toLowerCase())); } ); if (i.length > 0 && this.inputRef.value && this.inputRef.value.type !== "hidden") { const s = i[0]; s != null && s.label && (e.value = s.label, window.setTimeout( () => e.setSelectionRange(this._search.length, e.value.length), 0 ), e.selectionDirection = "backward"); } } } else this._options = [...this.options]; } handleFocus() { if (!this.disabled) { if (!this.multiple && this._value[0] && this.inputRef.value && this.inputRef.value.type !== "hidden") { const t = this.findValueInOptions(this._value[0]); this._editingSingleValue = !0, this.inputRef.value.value = this.displayValueAs === "label" && (t != null && t.label) ? t.label : this._value[0]; } this._inputFocus = !0, this._search = "", this._options = [...this.options], this._isOptionsOpen = !0, this.onFocus(), this.requestUpdate(); } } handleFocusOut(t) { var e, i, s, l, n; if (!this.disabled && ((i = (e = t.relatedTarget) == null ? void 0 : e.closest("pkt-combobox")) == null ? void 0 : i.id) !== this.id && ((l = (s = t.relatedTarget) == null ? void 0 : s.closest("pkt-combobox")) == null ? void 0 : l.id) !== this.id && ((n = t.target) == null ? void 0 : n.getAttribute("data-focusfix")) !== this.id && t.relatedTarget !== this.focusRef.value && t.relatedTarget !== this.inputRef.value && t.relatedTarget !== this.arrowRef.value && this._isOptionsOpen) { if (this._inputFocus = !1, this._addValueText = null, this._userInfoMessage = "", this._search = "", this.inputRef.value && this.inputRef.value.type !== "hidden" && this.inputRef.value.value !== "") { const a = this.inputRef.value.value, u = this.findValueInOptions(a); !this._value.includes(a) && !u ? this.allowUserInput ? this.addNewUserValue(a) : this.multiple || this.removeValue(this._value[0]) : u && !this._value.includes(u.value) && this.setSelected(u.value), this.inputRef.value.value = ""; } this._isOptionsOpen = !1, this.onBlur(); } } handleBlur() { this._inputFocus = !1, this._editingSingleValue = !1, this.onBlur(); } handleInputClick(t) { var e, i; this.disabled || (t.currentTarget && t.currentTarget !== this.arrowRef.value && ((e = this.inputRef.value) == null ? void 0 : e.type) !== "hidden" ? (i = this.inputRef.value) == null || i.focus() : this.handleArrowClick(t)); } handleArrowClick(t) { var e, i; this.disabled || t instanceof KeyboardEvent && t.key && t.key !== "Enter" && t.key !== " " && t.key !== "ArrowDown" || (t.stopImmediatePropagation(), t.preventDefault(), this._isOptionsOpen = !this._isOptionsOpen, this._isOptionsOpen ? (e = this.listboxRef.value) == null || e.focusFirstOrSelectedOption() : (i = this.arrowRef.value) == null || i.focus()); } handleOptionToggled(t) { this.toggleValue(t.detail); } handleSearch(t) { t.stopPropagation(), this._search = t.detail.toLowerCase(); } handleInputKeydown(t) { var e, i, s; switch (t.key) { case ",": case "Enter": t.preventDefault(), this.addValue(); break; case "Backspace": !this._search && ((e = this.inputRef.value) == null ? void 0 : e.type) === "hidden" && this.removeLastValue(t); break; case "Tab": case "ArrowDown": t.shiftKey || ((i = this.listboxRef.value) == null || i.focusFirstOrSelectedOption(), t.preventDefault()); break; case "Escape": this._isOptionsOpen = !1, (s = this.arrowRef.value) == null || s.focus(), t.preventDefault(); break; } } handleTagRemove(t) { this.removeSelected(t); } blurInput() { this.inputRef.value && this.inputRef.value.matches(":focus") && this.inputRef.value.blur(); } checkForMatches() { var n; const t = ((n = this.inputRef.value) == null ? void 0 : n.value) || this._search || "", e = t.trim().toLowerCase() || ""; if (!e) { !this.multiple && this._value[0] && this.removeValue(this._value[0]), this.resetComboboxInput(!1); return; } const i = this._value.find((a) => a.toLowerCase() === e), s = this._options.filter( (a) => { var u; return ((u = a.label) == null ? void 0 : u.toLowerCase().includes(e)) ?? !1; } ), l = s.find( (a) => { var u; return ((u = a.label) == null ? void 0 : u.toLowerCase()) === e || a.value.toLowerCase() === e; } ); switch (!0) { case ((s.length === 0 || !l) && this.allowUserInput): this._addValueText = t, this._userInfoMessage = ""; break; case (s.length === 0 && !this.allowUserInput): this._addValueText = null, this._userInfoMessage = "Ingen match i søket"; break; case !!i: this._addValueText = null, this._userInfoMessage = "Verdien er allerede valgt"; break; case s.length > 1: this._addValueText = null, this._userInfoMessage = ""; break; default: this._addValueText = null, this._userInfoMessage = ""; } } findValueInOptions(t) { return this.options.find((e) => e.value === t || e.label === t) || null; } findIndexInOptions(t) { return this._options.findIndex((e) => e.value === t || e.label === t); } isMaxItemsReached() { const t = this.maxlength !== null && this._value.length >= this.maxlength; return t ? this._maxIsReached = !0 : this._maxIsReached = !1, t; } toggleValue(t) { var $, I; if (this.disabled) return; this.touched = !0, this._userInfoMessage = "", this._addValueText = null; const e = (($ = this.findValueInOptions(t)) == null ? void 0 : $.value) || null, i = this._value.includes(t || e || ""), s = !!e, l = ((I = this._options.find((m) => m.value === t)) == null ? void 0 : I.disabled) || !1, n = !(t != null && t.trim()), a = !this.multiple, u = this.multiple, O = this.isMaxItemsReached(); let p = !1, b = !0, g = "", x = ""; l || (!s && this.allowUserInput && !n ? (this.addNewUserValue(t), g = "Ny verdi lagt til", p = !u) : !s && !this.allowUserInput ? (a && this._value[0] && this.removeValue(this._value[0]), b = !1, p = !0, g = "Ingen treff i søket") : i ? (this.removeValue(e), p = !0) : n && a ? (this.removeAllSelected(), p = !0) : a ? (this._value[0] && this.removeSelected(this._value[0]), this.setSelected(e), p = !1, this.inputRef.value && this.inputRef.value.type !== "hidden" && (this.inputRef.value.value = "", this.inputRef.value.blur())) : u && !O ? (this.setSelected(e), p = !0) : u && O ? (this._userInfoMessage = "Maks antall valg nådd", b = !1, x = t) : (a && this.removeAllSelected(), this._userInfoMessage = "Ingen gyldig verdi valgt", b = !1, p = !0, x = t), this._isOptionsOpen = p, p || window.setTimeout(() => { var m; (m = this.focusRef.value) == null || m.focus(); }, 0), this._userInfoMessage = g, this._search = x || "", this.resetComboboxInput(b), u && this.isMaxItemsReached()); } setSelected(t) { if (!this._value.includes(t)) { if (this.multiple && this.isMaxItemsReached()) { this._userInfoMessage = "Maks antall valg nådd"; return; } !this.multiple && this.removeAllSelected(), this._value = t ? [...this._value, t] : this._value, this._options = this._options.map((e) => (e.value === t && (e.selected = !0), e)), this.resetComboboxInput(!0); } } removeSelected(t) { if (!t) return; this._value = this._value.filter((i) => i !== t); const e = this.findValueInOptions(t); e ? (e.selected = !1, e.userAdded ? (this._options = [...this._options.filter((i) => i.value !== t)], this.options = [...this.options.filter((i) => i.value !== t)]) : this._options = [...this._options, e]) : !t && !this.multiple && (this._options = this._options.map((i) => (i.selected = !1, i))); } addAllOptions() { if (this.multiple) { if (this.maxlength && this._options.length > this.maxlength) { this._userInfoMessage = "For mange valgt"; return; } this._value = this._options.map((t) => t.value), this._options = this._options.map((t) => (t.selected = !0, t)), this.requestUpdate(); } } removeAllSelected() { this._value = [], this._options = this._options.map((t) => (t.selected = !1, t)), this._options = this._options.filter((t) => !t.userAdded), this.requestUpdate(); } addValue() { var e; const t = ((e = this.inputRef.value) == null ? void 0 : e.value.trim()) || ""; this._search = t, this.toggleValue(t); } removeValue(t) { this._value = this.multiple ? this._value.filter((e) => e !== t) : [], this.removeSelected(t); } addNewUserValue(t) { if (!t || t.trim() === "") return; if (!this.multiple) this._value[0] && this.removeSelected(this._value[0]), this._value = [t], this._isOptionsOpen = !1, this.blurInput(); else if (!this.findValueInOptions(t)) { if (this.isMaxItemsReached()) return; this._value = [...this._value, t]; } const e = { value: t, label: t, userAdded: !0 }; this.options = [e, ...this.options], this._options = [e, ...this._options], this.setSelected(t), this.requestUpdate(); } resetComboboxInput(t = !0) { if (this._addValueText = null, this.inputRef.value && this.inputRef.value.type !== "hidden" && t) if (this._search = "", this.multiple) this.inputRef.value.value = ""; else { const e = this.findValueInOptions(this._value[0]); window.setTimeout(() => { !this.inputRef.value || this.inputRef.value.type === "hidden" || (this.inputRef.value.value = this.displayValueAs === "label" && (e != null && e.label) ? e.label : this._value[0] || ""); }, 0), this._userInfoMessage = ""; } this._options = [...this.options]; } removeLastValue(t) { if (this._value.length === 0) return; t.preventDefault(); const e = this._value[this._value.length - 1]; e && this.removeSelected(e), this.isMaxItemsReached(); } }; o([ r({ type: String, reflect: !0 }) ], h.prototype, "value", 2); o([ r({ type: Array }) ], h.prototype, "options", 2); o([ r({ type: Array }) ], h.prototype, "defaultOptions", 2); o([ r({ type: Boolean }) ], h.prototype, "allowUserInput", 2); o([ r({ type: Boolean }) ], h.prototype, "typeahead", 2); o([ r({ type: Boolean }) ], h.prototype, "includeSearch", 2); o([ r({ type: String }) ], h.prototype, "searchPlaceholder", 2); o([ r({ type: Boolean }) ], h.prototype, "multiple", 2); o([ r({ type: Number }) ], h.prototype, "maxlength", 2); o([ r({ type: String }) ], h.prototype, "displayValueAs", 2); o([ r({ type: String }) ], h.prototype, "tagPlacement", 2); o([ c() ], h.prototype, "_options", 2); o([ c() ], h.prototype, "_isOptionsOpen", 2); o([ c() ], h.prototype, "_value", 2); o([ c() ], h.prototype, "_userInfoMessage", 2); o([ c() ], h.prototype, "_addValueText", 2); o([ c() ], h.prototype, "_maxIsReached", 2); o([ c() ], h.prototype, "_search", 2); o([ c() ], h.prototype, "_inputFocus", 2); o([ c() ], h.prototype, "_editingSingleValue", 2); h = o([ k("pkt-combobox") ], h); export { h as P };