@oslokommune/punkt-elements
Version:
Komponentbiblioteket til Punkt, et designsystem laget av Oslo Origo
985 lines (982 loc) • 37.1 kB
JavaScript
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"
=${this.handleInputClick}
>
<div class="pkt-contents" slot="helptext">${s(this, "helptext")}</div>
<div class="pkt-combobox" =${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"}
=${this.handleInputClick}
=${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" =${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}
=${this.handleSearch}
-toggle=${this.handleOptionToggled}
-all=${this.addAllOptions}
-options=${() => this._isOptionsOpen = !1}
-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)}
=${this.handleInput}
=${(e) => {
e.stopPropagation(), e.stopImmediatePropagation();
}}
=${this.handleInputKeydown}
=${this.handleFocus}
=${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"
=${i ? n : (e) => e.stopPropagation()}
=${i ? n : (e) => e.preventDefault()}
>
<pkt-tag
skin=${o || "blue-dark"}
?closeTag=${!this.disabled}
.buttonTabindex=${i ? void 0 : -1}
=${() => this.handleTagRemove(e)}
=${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 };