UNPKG

@oslokommune/punkt-elements

Version:

Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo

985 lines (982 loc) 37.1 kB
import { c as e, d as t, l as n, o as r, r as i, s as a } from "./element-cZ85T_aa.js"; import { t as o } from "./class-map-C8HuhNzZ.js"; import { n as s } from "./element-with-slot-4J2o3SeU.js"; import "./icon-Co72KtgF.js"; import { t as c } from "./if-defined-Cjj8qN-Z.js"; import { n as l, t as u } from "./ref-RS8Uv6uC.js"; import "./tag-hl59gziI.js"; import { t as d } from "./repeat-DV1O43YU.js"; import { a as f, c as p, i as m, o as h, r as g, s as _ } from "./listbox-0NHJvNjz.js"; import { t as v } from "./input-element-B1ciW1N2.js"; import { t as y } from "./pkt-options-controller-CCB15L_G.js"; import "./input-wrapper-DVU68NcJ.js"; //#region ../../shared-utils/combobox/input-utils.ts var b = (e, t, n) => { switch (e) { case ",": return n ? "addValue" : null; case "Enter": return "addValue"; case "Tab": case "ArrowDown": return t ? null : "focusListbox"; case "Escape": return "closeOptions"; default: return null; } }, x = (e, t, n, r, i) => { if (!e) return { action: "none", value: null }; let a = m(n, e); return !t.includes(e) && !a ? r ? { action: "addUserValue", value: e } : i ? { action: "none", value: null } : { action: "removeValue", value: t[0] } : a && !t.includes(a.value) ? { action: "selectOption", value: a.value } : { action: "none", value: null }; }, S = (e, t, n, r, i) => e.trim().toLowerCase() ? { ..._(e, t, n, r), shouldRemoveValue: !1, shouldResetInput: !1 } : { addValueText: null, userInfoMessage: "", shouldRemoveValue: !i && !!t[0], shouldResetInput: !0 }, C = (e, t, n) => { let r = m(t, e); return n === "label" && r?.label ? r.label : e; }, w = { markOptionSelected(e, t) { if (t) { for (let n of e) if (n.value === t) { n.selected = !0; break; } } }, markOptionDeselected(e, t) { if (t) { for (let n of e) if (n.value === t) { n.selected = !1; break; } } }, markAllSelected(e) { for (let t of e) t.selected = !0; }, markAllDeselected(e) { for (let t of e) t.selected = !1; }, removeUserAddedOptions(e) { return e.filter((e) => !e.userAdded); } }, T = { parseOptionsFromSlot(e) { let t = []; return e.forEach((e) => { if (!e.textContent && !e.getAttribute("value")) return; let n = { value: e.getAttribute("value") || e.textContent || "", label: e.textContent || e.getAttribute("value") || "" }; e.getAttribute("data-prefix") && (n.prefix = e.getAttribute("data-prefix") || void 0), e.getAttribute("tagskincolor") && (n.tagSkinColor = e.getAttribute("tagskincolor")), e.getAttribute("description") && (n.description = e.getAttribute("description") || void 0), n.fulltext = g(n), t.push(n); }), t; } }, E = { syncOptionsWithValues(e, t) { let n = [...t]; return e.forEach((e) => { e.value && !e.label && (e.label = e.value), e.selected && !n.includes(e.value) && n.push(e.value), e.fulltext = g(e), e.selected = e.selected || n.includes(e.value); }), { options: e, newValues: n }; }, mergeWithUserAdded(e, t) { return [...t.filter((e) => e?.userAdded && e.selected).filter((t) => !(Array.isArray(e) ? e : []).some((e) => e.value === t.value)), ...e]; } }, D = { name: "pkt-combobox", react: "PktCombobox", "css-class": "pkt-combobox", isElement: !0, isPureReact: !0, props: { name: { type: "string", name: "Navn", description: "Navn som brukes i skjema ved innsending", category: "tech" }, id: { type: "string", name: "ID", description: "Unik ID for feltet", category: "tech" }, label: { type: "string", name: "Etikett/label", description: "Tekst som vises over feltet", category: "contents" }, placeholder: { name: "Hint", description: "Spesifiserer en kort hint som beskriver forventet verdi av feltet.", type: "string", category: "contents", required: !1 }, multiple: { type: "boolean", name: "Flervalg", default: !1, description: "Mulighet for å velge flere valg", category: "functionality" }, tagPlacement: { attribute: "tag-placement", type: ["inside", "outside"], name: "Plassering av tags i flervalg", description: "Plassering av valgte verdier i feltet ved flervalg", category: "functionality", showIf: { multiple: !0 } }, maxlength: { type: "number", name: "Maks antall i flervalg", description: "Maks antall valg dersom flervalg er aktivert", category: "functionality", showIf: { multiple: !0 } }, typeahead: { type: "boolean", name: "Typeahead", default: !1, description: "Mulighet for automatisk utfylling av feltet fra listen over valg", category: "functionality" }, includeSearch: { attribute: "include-search", type: "boolean", name: "Inkluder søk", description: "Mulighet for å søke etter valg inni dropdown", category: "functionality" }, allowUserInput: { attribute: "allow-user-input", type: "boolean", name: "Brukervalgte verdier", description: "Mulighet for å skrive inn egne verdier", category: "functionality" }, searchPlaceholder: { attribute: "search-placeholder", type: "string", name: "Søke-plassholder", description: "Plassholdertekst for søkefeltet i dropdown", category: "contents", showIf: { includeSearch: !0 } }, displayValueAs: { attribute: "display-value-as", type: [ "label", "value", "prefixAndValue" ], name: "Visning av valgt verdi", description: "Hvordan valgt verdi vises i feltet", default: "label", category: "ui" }, value: { name: "Verdi", type: "string", description: "Valgt verdi. Streng ved enkelt valg, array av strenger ved flervalg.", category: "tech" }, helptext: { type: "string", name: "Hjelpetekst", description: "Hjelpetekst som vises over feltet", category: "contents" }, helptextDropdown: { type: "string", name: "Utvidet hjelpetekst", description: "Hjelpetekst som vises i en lukket boks man kan åpne", category: "contents" }, helptextDropdownButton: { type: "string", name: "Knappetekst for hjelpetekst", description: "Tekst som vises på knappen for å åpne/lukke utvidet hjelpetekst", category: "contents", default: "Les mer" }, disabled: { type: "boolean", name: "Deaktivert", description: "Feltet er deaktivert", category: "tech" }, hasError: { type: "boolean", name: "Feil", description: "Feltet har en feil", category: "ui" }, errorMessage: { type: "string", name: "Feilmelding", description: "Tekst som vises under feltet ved feil", category: "contents" }, required: { type: "boolean", name: "Påkrevd", description: "Feltet må fylles ut", category: "tech" }, requiredTag: { type: "boolean", name: "Påkrevd-merking", description: "Viser en merking som indikerer at feltet er påkrevd", category: "ui" }, requiredText: { type: "string", name: "Påkrevd-tekst", description: "Tekst som vises i påkrevd-merkingen", category: "contents" }, optionalTag: { type: "boolean", name: "Valgfritt-merking", description: "Viser en merking som indikerer at feltet er valgfritt", category: "ui" }, optionalText: { type: "string", name: "Valgfritt-tekst", description: "Tekst som vises i valgfritt-merkingen", category: "contents" }, tagText: { type: "string", name: "Tag-tekst", description: "Tekst som vises i en tag ved siden av label", category: "ui" }, fullwidth: { type: "boolean", name: "Full bredde", description: "Skal feltet ta opp hele bredden?", category: "ui" }, defaultOptions: { attribute: "default-options", name: "Initielle valg (default options)", description: "Liste over valg som kan velges, om options sendes inn som array med objekter (denne vil ikke modifiseres ved endring innad i komponenten)", type: "array", default: [], previewDefault: [ { value: "bfr", label: "Frogner" }, { value: "bgo", label: "Gamle Oslo" }, { value: "bgr", label: "Grorud" }, { value: "bxx", label: "Andre bydeler" } ], items: { type: "object", properties: { value: { type: "string", description: "Verdi som sendes ved valg" }, label: { type: "string", description: "Tekst som vises for valget" }, prefix: { type: "string", description: "Tekst som vises før valget" }, description: { type: "string", description: "Beskrivelse av valget" }, disabled: { type: "boolean", description: "Valget er deaktivert" }, selected: { type: "boolean", description: "Valget er valgt" }, tagSkinColor: { type: [ "blue", "blue-dark", "blue-light", "green", "red", "yellow", "beige", "gray", "grey" ], description: "Farge på tag" } }, required: ["value"] }, category: "contents" }, options: { name: "Valg", type: "array", description: "Liste over valg som kan velges, om options sendes inn som array med objekter", default: [], items: { type: "object", properties: { value: { type: "string", description: "Verdi som sendes ved valg" }, label: { type: "string", description: "Tekst som vises for valget" }, prefix: { type: "string", description: "Tekst som vises før valget" }, description: { type: "string", description: "Beskrivelse av valget" }, disabled: { type: "boolean", description: "Valget er deaktivert" }, selected: { type: "boolean", description: "Valget er valgt" }, tagSkinColor: { type: [ "blue", "blue-dark", "blue-light", "green", "red", "yellow", "beige", "gray", "grey" ], description: "Farge på tag" } }, required: ["value"] }, category: "contents" } }, events: { change: { type: "Event", description: "Returnerer valgt verdi som streng. Ved flervalg returneres kommaseparerte verdier." }, "value-change": { type: "CustomEvent", description: "Returnerer valgt verdi. Ved enkeltvalg en streng, ved flervalg en <code>string[]</code>." }, search: { type: "CustomEvent", description: "Returnerer søketeksten som streng i <code>event.detail</code> når brukeren skriver i søkefeltet" }, toggleHelpText: { type: "CustomEvent", description: "Returnerer <code>event.detail { isOpen: true }</code> eller <code>event.detail { isOpen: false }</code> når hjelpeteksten åpnes eller lukkes" } } }, O = class extends v { constructor() { super(), 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 = D.props.displayValueAs.default, this.tagPlacement = null, this.isOpen = !1, this._options = [], this._value = [], this._isOptionsOpen = !1, this._userInfoMessage = "", this._addValueText = null, this._maxIsReached = !1, this._search = "", this._inputFocus = !1, this._internalValueSync = !1, this._optionsFromSlot = !1, this._lastSlotGeneration = 0, this._suppressNextOpen = !1, this.inputRef = u(), this.triggerRef = u(), this.listboxRef = u(), this.optionsController = new y(this); } get _hasTextInput() { return this.typeahead || this.allowUserInput; } get _selectionDescription() { if (!(!this.multiple || this._value.length === 0)) return `${this._value.length} valgt`; } focusTrigger() { this._hasTextInput ? this.inputRef.value?.focus() : this.triggerRef.value?.focus(); } parseValue() { return Array.isArray(this.value) ? this.multiple ? this.value : this.value.length > 0 ? [this.value[0]] : [] : this.value && this.multiple ? this.value.split(",") : this.value ? [this.value] : []; } updateMaxReached() { this._maxIsReached = p(this._value.length, this.maxlength); } syncValueAndDispatch(e) { let t = this._value, n = this.multiple ? t.join(",") : t[0] || ""; if (n !== (Array.isArray(this.value) ? this.value.join(",") : String(this.value || "")) && (this._internalValueSync = !0, this.value = n), e?.join(",") !== t.join(",")) { let e = this.multiple ? [...t] : t[0] || ""; this.onChange(e); } else t.length === 0 && e && e.length > 0 && this.clearInputValue(); } onChange(e) { this.touched = !0, super.onChange(e); } valueChanged() {} }; i([a({ type: String, reflect: !0 })], O.prototype, "value", void 0), i([a({ type: Array })], O.prototype, "options", void 0), i([a({ type: Array, attribute: "default-options" })], O.prototype, "defaultOptions", void 0), i([a({ type: Boolean, attribute: "allow-user-input" })], O.prototype, "allowUserInput", void 0), i([a({ type: Boolean })], O.prototype, "typeahead", void 0), i([a({ type: Boolean, attribute: "include-search" })], O.prototype, "includeSearch", void 0), i([a({ type: String, attribute: "search-placeholder" })], O.prototype, "searchPlaceholder", void 0), i([a({ type: Boolean })], O.prototype, "multiple", void 0), i([a({ type: Number })], O.prototype, "maxlength", void 0), i([a({ type: String, attribute: "display-value-as" })], O.prototype, "displayValueAs", void 0), i([a({ type: String, attribute: "tag-placement" })], O.prototype, "tagPlacement", void 0), i([a({ type: Boolean, attribute: "open" })], O.prototype, "isOpen", void 0), i([r()], O.prototype, "_options", void 0), i([r()], O.prototype, "_value", void 0), i([r()], O.prototype, "_isOptionsOpen", void 0), i([r()], O.prototype, "_userInfoMessage", void 0), i([r()], O.prototype, "_addValueText", void 0), i([r()], O.prototype, "_maxIsReached", void 0), i([r()], O.prototype, "_search", void 0), i([r()], O.prototype, "_inputFocus", void 0); //#endregion //#region src/components/combobox/combobox-value.ts var k = class extends O { toggleValue(e) { if (this.disabled) return; this.touched = !0, this._userInfoMessage = "", this._addValueText = null; let t = m(this.options, e)?.value || null, n = this._value.includes(e || t || ""), r = !!t, i = this._options.find((t) => t.value === e)?.disabled || !1, a = !e?.trim(), o = !this.multiple, s = this.multiple, c = p(this._value.length, this.maxlength), l = !1, u = !0, d = "", f = ""; i || (!r && this.allowUserInput && !a ? (this.addNewUserValue(e), d = "Ny verdi lagt til", l = s) : !r && !this.allowUserInput ? (o && this._value[0] && this.removeValue(this._value[0]), u = !1, l = !0, d = "Ingen treff i søket") : n ? (this.removeValue(t), l = !0, o && this._hasTextInput && this.inputRef.value && this.inputRef.value.type !== "hidden" && (this.inputRef.value.value = "")) : a && o ? (this.removeAllSelected(), l = !0) : o ? (this._value[0] && this.removeSelected(this._value[0]), this.setSelected(t), l = !1) : s && !c ? (this.setSelected(t), l = !0) : s && c ? (d = "Maks antall valg nådd", u = !1, f = e) : (o && this.removeAllSelected(), d = "Ingen gyldig verdi valgt", u = !1, l = !0, f = e), this._isOptionsOpen = l, l || (o && this._hasTextInput && (this._suppressNextOpen = !0), window.setTimeout(() => { this.focusTrigger(); }, 0)), this._userInfoMessage = d, this._search = f || "", this.resetComboboxInput(u), s && this.updateMaxReached()); } setSelected(e) { if (!this._value.includes(e)) { if (this.multiple && p(this._value.length, this.maxlength)) { this._userInfoMessage = "Maks antall valg nådd"; return; } !this.multiple && this.removeAllSelected(), this._value = e ? [...this._value, e] : this._value, w.markOptionSelected(this._options, e), this.resetComboboxInput(!0); } } removeSelected(e) { if (!e) return; this._value = this._value.filter((t) => t !== e); let t = m(this.options, e); t && (w.markOptionDeselected(this.options, e), t.userAdded ? (this._options = [...this._options.filter((t) => t.value !== e)], this.options = [...this.options.filter((t) => t.value !== e)]) : this._options.some((t) => t.value === e) || (this._options = [...this._options, t])); } addAllOptions() { if (this.multiple) { if (this.maxlength && this._options.length > this.maxlength) { this._userInfoMessage = "For mange valgt"; return; } this._value = this._options.map((e) => e.value), w.markAllSelected(this._options), this.requestUpdate(); } } removeAllSelected() { this._value = [], w.markAllDeselected(this._options), this._options = w.removeUserAddedOptions(this._options), this.requestUpdate(); } addValue() { let e = this.inputRef.value?.value.trim() || ""; if (this._search = e, e && this._value.includes(e)) { this.resetComboboxInput(!0), this._userInfoMessage = "Verdien er allerede valgt"; return; } this.toggleValue(e); } removeValue(e) { this._value = this.multiple ? this._value.filter((t) => t !== e) : [], this.removeSelected(e); } addNewUserValue(e) { if (!e || e.trim() === "") return; if (!this.multiple) this._value[0] && this.removeSelected(this._value[0]), this._value = [e]; else if (!m(this.options, e)) { if (p(this._value.length, this.maxlength)) return; this._value = [...this._value, e]; } let t = { value: e, label: e, userAdded: !0, selected: !0 }; this.options = [t, ...this.options], this._options = [t, ...this._options], this.resetComboboxInput(!0), this.multiple || (this._isOptionsOpen = !1, this._hasTextInput && (this._suppressNextOpen = !0), window.setTimeout(() => { this.focusTrigger(); }, 0)), this.requestUpdate(); } resetComboboxInput(e = !0) { this._addValueText = null, this.inputRef.value && this.inputRef.value.type !== "hidden" && e && (this._search = "", this.multiple ? this.inputRef.value.value = "" : (this.inputRef.value.value = this._value[0] ? C(this._value[0], this.options, this.displayValueAs) : "", this._userInfoMessage = "")), this._options = [...this.options]; } removeLastValue(e) { if (this._value.length === 0) return; e.preventDefault(); let t = this._value[this._value.length - 1]; t && this.removeSelected(t), this.updateMaxReached(); } }, A = class extends k { handleInput(e) { if (e.stopPropagation(), e.stopImmediatePropagation(), this.disabled) return; this.touched = !0; let t = e.target; if (this._search = t.value, this.checkForMatches(), this.typeahead) if (this._search) { let { filtered: n, suggestion: r } = h(this.options, this._search); this._options = n, e.inputType !== "deleteContentBackward" && r?.label && this.inputRef.value && this.inputRef.value.type !== "hidden" && (t.value = r.label, window.setTimeout(() => t.setSelectionRange(this._search.length, t.value.length), 0), t.selectionDirection = "backward"); } else this._options = [...this.options]; } handleFocus() { if (!this.disabled) { if (this._suppressNextOpen) { this._suppressNextOpen = !1, this._inputFocus = !0, this.requestUpdate(); return; } !this.multiple && this._value[0] && this.inputRef.value && this.inputRef.value.type !== "hidden" && (this.inputRef.value.value = C(this._value[0], this.options, this.displayValueAs)), this._inputFocus = !0, this._search = "", this._options = [...this.options], this._isOptionsOpen = !0, this.onFocus(), this.requestUpdate(); } } handleFocusOut(e) { if (this.disabled || !this._isOptionsOpen) return; let t = e.relatedTarget; t?.closest("pkt-combobox")?.id === this.id || e.target?.getAttribute("data-focusfix") === this.id || t === this.inputRef.value || t === this.triggerRef.value || this.closeAndProcessInput(); } closeAndProcessInput() { if (this._inputFocus = !1, this._addValueText = null, this._userInfoMessage = "", this._search = "", this.inputRef.value && this.inputRef.value.type !== "hidden") { let e = this.inputRef.value.value; if (!this.multiple) if (!e) this._value[0] && this.removeSelected(this._value[0]); else { let t = m(this.options, e); t && t.value !== this._value[0] ? (this._value[0] && this.removeSelected(this._value[0]), this.setSelected(t.value)) : !t && this.allowUserInput && (this._value[0] && this.removeSelected(this._value[0]), this.addNewUserValue(e)); } else if (e !== "") { let { action: t, value: n } = x(e, this._value, this.options, this.allowUserInput, this.multiple); switch (t) { case "addUserValue": this.addNewUserValue(n); break; case "selectOption": this.setSelected(n); break; case "removeValue": this.removeValue(n); break; } } !this.multiple && this._value[0] ? this.inputRef.value.value = C(this._value[0], this.options, this.displayValueAs) : this.inputRef.value.value = ""; } this._isOptionsOpen = !1, this.onBlur(); } handleBlur() { this._inputFocus = !1, this.onBlur(); } handleInputClick(e) { if (this.disabled) { e.preventDefault(), e.stopImmediatePropagation(); return; } this._hasTextInput ? (this.inputRef.value?.focus(), this.requestUpdate()) : (e.stopImmediatePropagation(), e.preventDefault(), this._isOptionsOpen = !this._isOptionsOpen, this._isOptionsOpen && this.listboxRef.value?.focusFirstOrSelectedOption()); } handlePlaceholderClick(e) { this.disabled || (e.stopPropagation(), this._hasTextInput && this.inputRef.value ? (this.inputRef.value.focus(), this._inputFocus = !0, this.requestUpdate()) : (this._isOptionsOpen = !this._isOptionsOpen, this.requestUpdate())); } handleSelectOnlyKeydown(e) { if (!this.disabled) switch (e.key) { case "Enter": case " ": case "ArrowDown": case "ArrowUp": e.preventDefault(), this._isOptionsOpen ? this._isOptionsOpen = !1 : (this._isOptionsOpen = !0, this.listboxRef.value?.focusFirstOrSelectedOption()); break; case "Escape": this._isOptionsOpen &&= (e.preventDefault(), !1); break; case "Home": case "End": e.preventDefault(), this._isOptionsOpen ||= !0, this.listboxRef.value?.focusFirstOrSelectedOption(); break; case "ArrowLeft": this.multiple && this._value.length > 0 && (e.preventDefault(), this.focusTag(this._value.length - 1)); break; case "Backspace": case "Delete": this.multiple && this._value.length > 0 && (e.preventDefault(), this.removeSelected(this._value[this._value.length - 1])); break; } } handleOptionToggled(e) { this.toggleValue(e.detail); } handleSearch(e) { e.stopPropagation(), this._search = e.detail.toLowerCase(), this.checkForMatches(); } handleInputKeydown(e) { if (e.key === "Backspace") { let t = !this.inputRef.value?.value; !this._search && t && this.multiple && this._value.length > 0 && this.removeLastValue(e); return; } if (e.key === "ArrowLeft" && this.multiple && this._value.length > 0) { let t = this.inputRef.value; if (t && t.selectionStart === 0 && !t.value) { e.preventDefault(), this.focusTag(this._value.length - 1); return; } } let t = b(e.key, e.shiftKey, this.multiple); if (t && !(e.key === "Tab" && !this._isOptionsOpen)) { if (t === "focusListbox" && e.key === "Tab" && !this.listboxRef.value?.querySelector("[role=\"option\"]:not([data-disabled]), [data-type=\"new-option\"]")) { this.closeAndProcessInput(); return; } switch (e.preventDefault(), t) { case "addValue": this.addValue(); break; case "focusListbox": this.listboxRef.value?.focusFirstOrSelectedOption(); break; case "closeOptions": this._isOptionsOpen = !1; break; } } } handleTagRemove(e) { this.removeSelected(e), this._hasTextInput && this.inputRef.value && (this._inputFocus = !0, this.inputRef.value.focus(), this.requestUpdate()); } getInsideTags() { return Array.from(this.querySelectorAll(".pkt-combobox__input .pkt-combobox__tag-list pkt-tag")); } focusTag(e) { let t = this.getInsideTags(); t.forEach((t, n) => { t.buttonTabindex = n === e ? 0 : -1; }), (t[e]?.querySelector("button"))?.focus(); } resetTagTabindices() { this.getInsideTags().forEach((e) => { e.buttonTabindex = -1; }); } handleTagKeydown(e, t) { e.stopPropagation(); let n = () => { this.resetTagTabindices(), this._hasTextInput && this.inputRef.value ? this.inputRef.value.focus() : this.triggerRef.value?.focus(); }; switch (e.key) { case "ArrowLeft": e.preventDefault(), t > 0 && this.focusTag(t - 1); break; case "ArrowRight": e.preventDefault(), t < this._value.length - 1 ? this.focusTag(t + 1) : n(); break; case "Backspace": case "Delete": e.preventDefault(); { let e = this._value[t], r = t >= this._value.length - 1 ? t - 1 : t; this.removeSelected(e), r >= 0 ? (this.requestUpdate(), this.updateComplete.then(() => this.focusTag(r))) : n(); } break; case "Tab": this.resetTagTabindices(); break; case "Escape": e.preventDefault(), n(); break; } } checkForMatches() { let e = S(this.inputRef.value?.value || this._search || "", this._value, this.options, this.allowUserInput, this.multiple); if (e.shouldRemoveValue && this.removeValue(this._value[0]), e.shouldResetInput) { this.resetComboboxInput(!1); return; } this._addValueText = e.addValueText, this._userInfoMessage = e.userInfoMessage; } }, j = class extends A { constructor(...e) { super(...e), this.handleBodyClick = (e) => { this._isOptionsOpen && !this.contains(e.target) && this.closeAndProcessInput(); }; } connectedCallback() { if (super.connectedCallback(), document?.body.addEventListener("click", this.handleBodyClick), this._options = [], this.defaultOptions && this.defaultOptions.length && (this.options = [...this.options?.filter((e) => e.userAdded) || [], ...JSON.parse(JSON.stringify(this.defaultOptions))], this._options = Array.isArray(this.options) ? [...this.options] : []), this.optionsController?.nodes && this.optionsController.nodes.length) { let e = T.parseOptionsFromSlot(this.optionsController.nodes); e.length && (this.options = [...e], this._options = [...e], this._optionsFromSlot = !0, this._lastSlotGeneration = this.optionsController.generation); } } willUpdate(e) { if (this._optionsFromSlot && this.optionsController) { let e = this.optionsController.generation; if (e !== this._lastSlotGeneration) { this._lastSlotGeneration = e; let t = T.parseOptionsFromSlot(this.optionsController.nodes); this.options = [...this._options.filter((e) => e.userAdded), ...t]; } } super.willUpdate(e); } disconnectedCallback() { super.disconnectedCallback(), document?.body.removeEventListener("click", this.handleBodyClick); } firstUpdated(e) { this.defaultValue !== null && !this.value && (this.value = this.defaultValue), super.firstUpdated(e); } updated(e) { e.has("isOpen") && (this._isOptionsOpen = this.isOpen); let t = e.has("value"), n = e.has("_value"); if (t && this._internalValueSync) this._internalValueSync = !1, n && this.syncValueAndDispatch(e.get("_value")); else if (t) { let e = [...this._value], t = this.parseValue(); t.join(",") !== this._value.join(",") && (this._value = t), this.updateMaxReached(), this.syncValueAndDispatch(e); } else n && this.syncValueAndDispatch(e.get("_value")); if (e.has("defaultOptions") && this.defaultOptions.length && (this.options = [...(Array.isArray(this.options) ? this.options : []).filter((e) => e.userAdded) || [], ...JSON.parse(JSON.stringify(this.defaultOptions))], this._options = Array.isArray(this.options) ? [...this.options] : []), e.has("options")) { let t = e.get("options") || this._options || [], n = E.mergeWithUserAdded(this.options, t); this._options = n, n.length > this.options.length && (this.options = n); let r = E.syncOptionsWithValues(this._options, this._value); if (this._options = r.options, r.newValues.length > this._value.length) { let e = [...this._value]; this._value = r.newValues, this.syncValueAndDispatch(e); } } if (e.has("_search") && this.dispatchEvent(new CustomEvent("search", { detail: this._search, bubbles: !1 })), !this._isOptionsOpen && !this.multiple && this._hasTextInput && this.inputRef.value && this.inputRef.value.type !== "hidden") { let e = this._value[0] ? C(this._value[0], this.options, this.displayValueAs) : ""; this.inputRef.value.value !== e && (this.inputRef.value.value = e); } super.updated(e); } formResetCallback() { this.touched = !1, this.value = this.defaultValue || (this.multiple, ""), this._value = this.parseValue(), this._options = this._options.filter((e) => !e.userAdded).map((e) => ({ ...e, selected: this._value.includes(e.value) })), this.options = this.options.filter((e) => !e.userAdded).map((e) => ({ ...e, selected: this._value.includes(e.value) })), this._search = "", this._isOptionsOpen = !1, this._userInfoMessage = "", this._addValueText = null, this._inputFocus = !1, this.updateMaxReached(), this.inputRef.value && this.inputRef.value.type !== "hidden" && (this.inputRef.value.value = ""), this.internals.setFormValue(""), this.internals.ariaInvalid = "false", this.requestUpdate(); } attributeChangedCallback(e, t, n) { if (e === "options") { this._options = Array.isArray(this.options) ? [...this.options] : []; let e = E.syncOptionsWithValues(this._options, this._value); this._options = e.options, e.newValues.length > this._value.length && (this._value = e.newValues), this._search = ""; } super.attributeChangedCallback(e, t, n); } render() { return t` <pkt-input-wrapper .label=${this.label} .helptext=${this.helptext} .helptextDropdown=${c(this.helptextDropdown)} .helptextDropdownButton=${c(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._hasTextInput ? this.id + "-input" : this.id + "-combobox"} ?hasFieldset=${!this._hasTextInput} class="pkt-combobox__wrapper" @labelClick=${this.handleInputClick} > <div class="pkt-contents" slot="helptext">${s(this, "helptext")}</div> <div class="pkt-combobox" @focusout=${this.handleFocusOut}> <div class=${o({ "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 })} id=${c(this._hasTextInput ? void 0 : `${this.id}-combobox`)} role=${c(this._hasTextInput ? void 0 : "combobox")} aria-expanded=${c(this._hasTextInput ? void 0 : this._isOptionsOpen ? "true" : "false")} aria-controls=${c(this._hasTextInput ? void 0 : `${this.id}-listbox`)} aria-haspopup=${c(this._hasTextInput ? void 0 : "listbox")} aria-labelledby=${c(this._hasTextInput ? void 0 : `${this.id}-combobox-label`)} aria-activedescendant=${c(!this._hasTextInput && this._value[0] && m(this.options, this._value[0]) ? `${this.id}-listbox-${f(this._options, this._value[0])}` : void 0)} aria-description=${c(this._selectionDescription || void 0)} tabindex=${this._hasTextInput || this.disabled ? "-1" : "0"} @click=${this.handleInputClick} @keydown=${this._hasTextInput ? n : this.handleSelectOnlyKeydown} ${l(this.triggerRef)} > ${!this._hasTextInput && this.placeholder && (!this._value.length || this.multiple && this.tagPlacement == "outside") && !this._inputFocus ? t`<span class="pkt-combobox__placeholder" @click=${this.handlePlaceholderClick} >${this.placeholder}</span >` : this.tagPlacement === "outside" ? n : this.renderSingleOrMultipleValues()} ${this.renderInputField()} <pkt-icon class=${o({ "pkt-combobox__arrow-icon": !0, "pkt-combobox__arrow-icon--open": this._isOptionsOpen })} name="chevron-thin-down" aria-hidden="true" ></pkt-icon> </div> <pkt-listbox id="${this.id}-listbox" .options=${this._options} .isOpen=${this._isOptionsOpen} .searchPlaceholder=${this.searchPlaceholder} .label="Liste: ${this.label || ""}" ?include-search=${this.includeSearch} ?is-multi-select=${this.multiple} ?allow-user-input=${this.allowUserInput && !this._maxIsReached} ?max-is-reached=${this._maxIsReached} .customUserInput=${c(this._addValueText)} .userMessage=${this._userInfoMessage} @search=${this.handleSearch} @option-toggle=${this.handleOptionToggled} @select-all=${this.addAllOptions} @close-options=${() => this._isOptionsOpen = !1} @tab-close=${() => this.closeAndProcessInput()} .searchValue=${this._search || null} .maxLength=${this.maxlength || 0} ${l(this.listboxRef)} ></pkt-listbox> </div> ${this.tagPlacement === "outside" && this.multiple ? t`<div class="pkt-combobox__tags-outside"> ${this.renderSingleOrMultipleValues()} </div>` : n} </pkt-input-wrapper> `; } renderInputField() { return this.typeahead || this.allowUserInput ? t` <div class="pkt-combobox__input-div combobox__input"> <input type="text" id="${this.id}-input" name=${(this.name || this.id) + "-input"} placeholder=${c(!this._value.length || this.multiple && this.tagPlacement === "outside" ? this.placeholder : void 0)} @input=${this.handleInput} @change=${(e) => { e.stopPropagation(), e.stopImmediatePropagation(); }} @keydown=${this.handleInputKeydown} @focus=${this.handleFocus} @blur=${this.handleBlur} autocomplete="off" role="combobox" aria-expanded=${this._isOptionsOpen ? "true" : "false"} aria-label=${c(this.label)} aria-autocomplete=${this.typeahead ? "both" : this.allowUserInput ? "list" : "none"} aria-controls="${this.id}-listbox" aria-activedescendant=${c(this._value[0] && m(this.options, this._value[0]) ? `${this.id}-listbox-${f(this._options, this._value[0])}` : void 0)} aria-description=${c(this._selectionDescription || void 0)} ${l(this.inputRef)} /> </div> ` : t` <input type="hidden" id="${this.id}-input" name=${(this.name || this.id) + "-input"} .value=${this._value.join(",")} ${l(this.inputRef)} /> `; } renderSingleOrMultipleValues() { if (!this.multiple && this._hasTextInput) return n; let e = !this.multiple, r = this.renderValueTag(m(this.options, this._value[0])), i = this.tagPlacement === "outside", a = t` <ul role="list" class="pkt-combobox__tag-list"> ${d(this._value, (e) => e, (e, r) => { let a = m(this.options, e), o = a?.tagSkinColor; return t` <li role="listitem" @click=${i ? n : (e) => e.stopPropagation()} @mousedown=${i ? n : (e) => e.preventDefault()} > <pkt-tag skin=${o || "blue-dark"} ?closeTag=${!this.disabled} .buttonTabindex=${i ? void 0 : -1} @close=${() => this.handleTagRemove(e)} @keydown=${i ? n : (e) => this.handleTagKeydown(e, r)} > ${this.renderValueTag(a)} </pkt-tag> </li> `; })} </ul> `; return e ? r : a; } renderValueTag(e) { if (!e) return ""; switch (this.displayValueAs) { case "prefixAndValue": return t`<span class="pkt-combobox__value" data-focusfix=${this.id} >${e.prefix || ""} ${e.value}</span >`; case "value": return t`<span class="pkt-combobox__value" data-focusfix=${this.id} >${e.value}</span >`; default: return t`<span class="pkt-combobox__value" data-focusfix=${this.id} >${e.label || e.value}</span >`; } } }; try { e("pkt-combobox")(j); } catch { console.warn("Forsøker å definere <pkt-combobox>, men den er allerede definert"); } //#endregion //#region src/components/combobox/index.ts var M = j; //#endregion export { j as n, M as t };