slim-select
Version:
Slim advanced select dropdown
1,147 lines • 77.7 kB
JavaScript
import re, { forwardRef as oe, useRef as I, useImperativeHandle as ce, useEffect as $ } from "react";
var V = { exports: {} }, M = {};
var ee;
function he() {
if (ee) return M;
ee = 1;
var p = /* @__PURE__ */ Symbol.for("react.transitional.element"), e = /* @__PURE__ */ Symbol.for("react.fragment");
function t(s, i, n) {
var l = null;
if (n !== void 0 && (l = "" + n), i.key !== void 0 && (l = "" + i.key), "key" in i) {
n = {};
for (var r in i)
r !== "key" && (n[r] = i[r]);
} else n = i;
return i = n.ref, {
$$typeof: p,
type: s,
key: l,
ref: i !== void 0 ? i : null,
props: n
};
}
return M.Fragment = e, M.jsx = t, M.jsxs = t, M;
}
var _ = {};
var te;
function de() {
return te || (te = 1, process.env.NODE_ENV !== "production" && (function() {
function p(a) {
if (a == null) return null;
if (typeof a == "function")
return a.$$typeof === ne ? null : a.displayName || a.name || null;
if (typeof a == "string") return a;
switch (a) {
case A:
return "Fragment";
case v:
return "Profiler";
case S:
return "StrictMode";
case D:
return "Suspense";
case P:
return "SuspenseList";
case R:
return "Activity";
}
if (typeof a == "object")
switch (typeof a.tag == "number" && console.error(
"Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."
), a.$$typeof) {
case g:
return "Portal";
case L:
return a.displayName || "Context";
case k:
return (a._context.displayName || "Context") + ".Consumer";
case C:
var u = a.render;
return a = a.displayName, a || (a = u.displayName || u.name || "", a = a !== "" ? "ForwardRef(" + a + ")" : "ForwardRef"), a;
case B:
return u = a.displayName || null, u !== null ? u : p(a.type) || "Memo";
case T:
u = a._payload, a = a._init;
try {
return p(a(u));
} catch {
}
}
return null;
}
function e(a) {
return "" + a;
}
function t(a) {
try {
e(a);
var u = !1;
} catch {
u = !0;
}
if (u) {
u = console;
var w = u.error, O = typeof Symbol == "function" && Symbol.toStringTag && a[Symbol.toStringTag] || a.constructor.name || "Object";
return w.call(
u,
"The provided key is an unsupported type %s. This value must be coerced to a string before using it here.",
O
), e(a);
}
}
function s(a) {
if (a === A) return "<>";
if (typeof a == "object" && a !== null && a.$$typeof === T)
return "<...>";
try {
var u = p(a);
return u ? "<" + u + ">" : "<...>";
} catch {
return "<...>";
}
}
function i() {
var a = j.A;
return a === null ? null : a.getOwner();
}
function n() {
return Error("react-stack-top-frame");
}
function l(a) {
if (J.call(a, "key")) {
var u = Object.getOwnPropertyDescriptor(a, "key").get;
if (u && u.isReactWarning) return !1;
}
return a.key !== void 0;
}
function r(a, u) {
function w() {
G || (G = !0, console.error(
"%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)",
u
));
}
w.isReactWarning = !0, Object.defineProperty(a, "key", {
get: w,
configurable: !0
});
}
function c() {
var a = p(this.type);
return X[a] || (X[a] = !0, console.error(
"Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release."
)), a = this.props.ref, a !== void 0 ? a : null;
}
function h(a, u, w, O, F, U) {
var y = w.ref;
return a = {
$$typeof: E,
type: a,
key: u,
props: w,
_owner: O
}, (y !== void 0 ? y : null) !== null ? Object.defineProperty(a, "ref", {
enumerable: !1,
get: c
}) : Object.defineProperty(a, "ref", { enumerable: !1, value: null }), a._store = {}, Object.defineProperty(a._store, "validated", {
configurable: !1,
enumerable: !1,
writable: !0,
value: 0
}), Object.defineProperty(a, "_debugInfo", {
configurable: !1,
enumerable: !1,
writable: !0,
value: null
}), Object.defineProperty(a, "_debugStack", {
configurable: !1,
enumerable: !1,
writable: !0,
value: F
}), Object.defineProperty(a, "_debugTask", {
configurable: !1,
enumerable: !1,
writable: !0,
value: U
}), Object.freeze && (Object.freeze(a.props), Object.freeze(a)), a;
}
function o(a, u, w, O, F, U) {
var y = u.children;
if (y !== void 0)
if (O)
if (le(y)) {
for (O = 0; O < y.length; O++)
d(y[O]);
Object.freeze && Object.freeze(y);
} else
console.error(
"React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead."
);
else d(y);
if (J.call(u, "key")) {
y = p(a);
var N = Object.keys(u).filter(function(ae) {
return ae !== "key";
});
O = 0 < N.length ? "{key: someKey, " + N.join(": ..., ") + ": ...}" : "{key: someKey}", Q[y + O] || (N = 0 < N.length ? "{" + N.join(": ..., ") + ": ...}" : "{}", console.error(
`A props object containing a "key" prop is being spread into JSX:
let props = %s;
<%s {...props} />
React keys must be passed directly to JSX without using spread:
let props = %s;
<%s key={someKey} {...props} />`,
O,
y,
N,
y
), Q[y + O] = !0);
}
if (y = null, w !== void 0 && (t(w), y = "" + w), l(u) && (t(u.key), y = "" + u.key), "key" in u) {
w = {};
for (var W in u)
W !== "key" && (w[W] = u[W]);
} else w = u;
return y && r(
w,
typeof a == "function" ? a.displayName || a.name || "Unknown" : a
), h(
a,
y,
w,
i(),
F,
U
);
}
function d(a) {
m(a) ? a._store && (a._store.validated = 1) : typeof a == "object" && a !== null && a.$$typeof === T && (a._payload.status === "fulfilled" ? m(a._payload.value) && a._payload.value._store && (a._payload.value._store.validated = 1) : a._store && (a._store.validated = 1));
}
function m(a) {
return typeof a == "object" && a !== null && a.$$typeof === E;
}
var f = re, E = /* @__PURE__ */ Symbol.for("react.transitional.element"), g = /* @__PURE__ */ Symbol.for("react.portal"), A = /* @__PURE__ */ Symbol.for("react.fragment"), S = /* @__PURE__ */ Symbol.for("react.strict_mode"), v = /* @__PURE__ */ Symbol.for("react.profiler"), k = /* @__PURE__ */ Symbol.for("react.consumer"), L = /* @__PURE__ */ Symbol.for("react.context"), C = /* @__PURE__ */ Symbol.for("react.forward_ref"), D = /* @__PURE__ */ Symbol.for("react.suspense"), P = /* @__PURE__ */ Symbol.for("react.suspense_list"), B = /* @__PURE__ */ Symbol.for("react.memo"), T = /* @__PURE__ */ Symbol.for("react.lazy"), R = /* @__PURE__ */ Symbol.for("react.activity"), ne = /* @__PURE__ */ Symbol.for("react.client.reference"), j = f.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, J = Object.prototype.hasOwnProperty, le = Array.isArray, q = console.createTask ? console.createTask : function() {
return null;
};
f = {
react_stack_bottom_frame: function(a) {
return a();
}
};
var G, X = {}, K = f.react_stack_bottom_frame.bind(
f,
n
)(), Z = q(s(n)), Q = {};
_.Fragment = A, _.jsx = function(a, u, w) {
var O = 1e4 > j.recentlyCreatedOwnerStacks++;
return o(
a,
u,
w,
!1,
O ? Error("react-stack-top-frame") : K,
O ? q(s(a)) : Z
);
}, _.jsxs = function(a, u, w) {
var O = 1e4 > j.recentlyCreatedOwnerStacks++;
return o(
a,
u,
w,
!0,
O ? Error("react-stack-top-frame") : K,
O ? q(s(a)) : Z
);
};
})()), _;
}
var se;
function ue() {
return se || (se = 1, process.env.NODE_ENV === "production" ? V.exports = he() : V.exports = de()), V.exports;
}
var fe = ue();
class pe {
main;
// Placeholder
placeholder;
// Values
values;
single;
max;
value;
valueText;
valueDelete;
valueOut;
// Deselect
deselect;
deselectPath;
// Not a class but whatever
// Arrow
arrow;
arrowClose;
// Not a class but whatever
arrowOpen;
// Not a class but whatever
// Content
content;
contentOpen;
dirAbove;
dirBelow;
// Search
search;
searchHighlighter;
searching;
addable;
addablePath;
// Not a class but whatever
// List optgroups/options
list;
// Optgroup
optgroup;
optgroupLabel;
optgroupLabelText;
optgroupActions;
optgroupSelectAll;
// optgroup select all
optgroupSelectAllBox;
// Not a class but whatever
optgroupSelectAllCheck;
// Not a class but whatever
optgroupClosable;
// Option
option;
optionDelete;
// Not a class but whatever
highlighted;
// Misc
mainOpen;
close;
selected;
error;
disabled;
hide;
constructor(e) {
e || (e = {});
let t = (s = "", i = "") => `${s} ${i}`.trim();
this.main = t("ss-main", e.main), this.placeholder = t("ss-placeholder", e.placeholder), this.values = t("ss-values", e.values), this.single = t("ss-single", e.single), this.max = t("ss-max", e.max), this.value = t("ss-value", e.value), this.valueText = t("ss-value-text", e.valueText), this.valueDelete = t("ss-value-delete", e.valueDelete), this.valueOut = t("ss-value-out", e.valueOut), this.deselect = t("ss-deselect", e.deselect), this.deselectPath = e.deselectPath || "M10,10 L90,90 M10,90 L90,10", this.arrow = t("ss-arrow", e.arrow), this.arrowClose = e.arrowClose || "M10,30 L50,70 L90,30", this.arrowOpen = e.arrowOpen || "M10,70 L50,30 L90,70", this.content = t("ss-content", e.content), this.contentOpen = t("ss-open", e.contentOpen), this.dirAbove = t("ss-dir-above", e.dirAbove), this.dirBelow = t("ss-dir-below", e.dirBelow), this.search = t("ss-search", e.search), this.searchHighlighter = t("ss-search-highlight", e.searchHighlighter), this.searching = t("ss-searching", e.searching), this.addable = t("ss-addable", e.addable), this.addablePath = e.addablePath || "M50,10 L50,90 M10,50 L90,50", this.list = t("ss-list", e.list), this.optgroup = t("ss-optgroup", e.optgroup), this.optgroupLabel = t("ss-optgroup-label", e.optgroupLabel), this.optgroupLabelText = t("ss-optgroup-label-text", e.optgroupLabelText), this.optgroupActions = t("ss-optgroup-actions", e.optgroupActions), this.optgroupSelectAll = t("ss-selectall", e.optgroupSelectAll), this.optgroupSelectAllBox = e.optgroupSelectAllBox || "M60,10 L10,10 L10,90 L90,90 L90,50", this.optgroupSelectAllCheck = e.optgroupSelectAllCheck || "M30,45 L50,70 L90,10", this.optgroupClosable = t("ss-closable", e.optgroupClosable), this.option = t("ss-option", e.option), this.optionDelete = e.optionDelete || "M10,10 L90,90 M10,90 L90,10", this.highlighted = t("ss-highlighted", e.highlighted), this.mainOpen = t("ss-open", e.mainOpen), this.close = t("ss-close", e.close), this.selected = t("ss-selected", e.selected), this.error = t("ss-error", e.error), this.disabled = t("ss-disabled", e.disabled), this.hide = t("ss-hide", e.hide);
}
getFirst(e) {
return this[e].split(" ")[0];
}
}
function z() {
return Math.random().toString(36).substring(2, 10);
}
function ie(p, e) {
function t(i, n) {
return n && i && i.classList && i.classList.contains(n) || n && i && i.dataset && i.dataset.id && i.dataset.id === e ? i : null;
}
function s(i, n) {
return !i || i === document ? null : t(i, n) ? i : s(i.parentNode, n);
}
return t(p, e) || s(p, e);
}
function H(p, e = 50, t = !1) {
let s;
return function(...i) {
const n = self, l = () => {
s = null, t || p.apply(n, i);
}, r = t && !s;
clearTimeout(s), s = setTimeout(l, e), r && p.apply(n, i);
};
}
function Y(p, e) {
return JSON.stringify(p) === JSON.stringify(e);
}
function me(p) {
const e = p.replace(/[A-Z\u00C0-\u00D6\u00D8-\u00DE]/g, (t) => "-" + t.toLowerCase());
return p[0] === p[0].toUpperCase() ? e.substring(1) : e;
}
class b {
id;
value;
text;
html;
defaultSelected;
selected;
display;
disabled;
placeholder;
class;
style;
data;
mandatory;
constructor(e) {
this.id = !e.id || e.id === "" ? z() : e.id, this.value = e.value === void 0 ? e.text || "" : e.value || "", this.text = e.text || "", this.html = e.html || "", this.defaultSelected = e.defaultSelected !== void 0 ? e.defaultSelected : !1, this.selected = e.selected !== void 0 ? e.selected : !1, this.display = e.display !== void 0 ? e.display : !0, this.disabled = e.disabled !== void 0 ? e.disabled : !1, this.mandatory = e.mandatory !== void 0 ? e.mandatory : !1, this.placeholder = e.placeholder !== void 0 ? e.placeholder : !1, this.class = e.class || "", this.style = e.style || "", this.data = e.data || {};
}
}
class x {
id;
label;
selectAll;
selectAllText;
closable;
options;
constructor(e) {
if (this.id = !e.id || e.id === "" ? z() : e.id, this.label = e.label || "", this.selectAll = e.selectAll === void 0 ? !1 : e.selectAll, this.selectAllText = e.selectAllText || "Select All", this.closable = e.closable || "off", this.options = [], e.options)
for (const t of e.options)
this.options.push(new b(t));
}
}
class ge {
selectType = "single";
// Main data set, never null
data = [];
selectedOrder = [];
constructor(e, t) {
this.selectType = e, this.setData(t);
}
// Validate DataArrayPartial
validateDataArray(e) {
if (!Array.isArray(e))
return new Error("Data must be an array");
for (let t of e)
if (t)
if (t instanceof x || "label" in t) {
if (!("label" in t))
return new Error("Optgroup must have a label");
if ("options" in t && t.options)
for (let s of t.options) {
const i = this.validateOption(s);
if (i)
return i;
}
} else if (t instanceof b || "text" in t) {
const s = this.validateOption(t);
if (s)
return s;
} else
return new Error("Data object must be a valid optgroup or option");
return null;
}
// Validate Option
validateOption(e) {
return "text" in e ? null : new Error("Option must have a text");
}
partialToFullData(e) {
let t = [];
return e.forEach((s) => {
if (s) {
if (s instanceof x || "label" in s) {
let i = [];
"options" in s && s.options && s.options.forEach((n) => {
i.push(new b(n));
}), i.length > 0 && t.push(new x(s));
}
(s instanceof b || "text" in s) && t.push(new b(s));
}
}), t;
}
setData(e, t = !1) {
const s = this.partialToFullData(e);
let i = [];
if (t) {
i = this.getSelectedOptions();
const n = [];
i.forEach((l) => {
let r = !1;
for (const c of s) {
if (c instanceof b && c.id === l.id) {
r = !0;
break;
}
if (c instanceof x) {
for (const h of c.options)
if (h.id === l.id) {
r = !0;
break;
}
}
}
r || n.push(l);
}), this.data = [...n, ...s];
} else
this.data = s;
if (this.selectType === "single") {
const n = t && i.length === 0;
this.setSelectedBy("id", this.getSelected(), n);
}
}
// Get data will return all the data
getData() {
return this.filter(null, !0);
}
// Get data options will return the data as a
// flat array of just options
getDataOptions() {
return this.filter(null, !1);
}
addOption(e, t = !1) {
if (t) {
let s = [new b(e)];
this.setData(s.concat(this.getData()));
} else
this.setData(this.getData().concat(new b(e)));
}
// Pass in an array of id that will loop through
// each option and set the selected property to true
// but also clean selected by determining selectType
// When allowEmptySelection is true (e.g. after search with no prior selection), single select will not auto-select the first option
setSelectedBy(e, t, s = !1) {
let i = null, n = !1;
const l = [];
for (let c of this.data) {
if (c instanceof x)
for (let h of c.options) {
i || (i = h);
let o = h[e] || "";
h.selected = n ? !1 : t.includes(o), h.selected && (l.push(h), this.selectType === "single" && (n = !0));
}
c instanceof b && (i || (i = c), c.selected = n ? !1 : t.includes(c[e]), c.selected && (l.push(c), this.selectType === "single" && (n = !0)));
}
this.selectType === "single" && i && !n && !s && (i.selected = !0, l.push(i));
const r = t.map((c) => l.find((h) => h[e] === c)?.id || "");
this.selectedOrder = r;
}
getSelected() {
return this.getSelectedOptions().map((e) => e.id);
}
getSelectedValues() {
return this.getSelectedOptions().map((e) => e.value);
}
getSelectedOptions() {
return this.filter((e) => e.selected, !1);
}
getOptgroupByID(e) {
for (let t of this.data)
if (t instanceof x && t.id === e)
return t;
return null;
}
getOptionByID(e) {
let t = this.filter((s) => s.id === e, !1);
return t.length ? t[0] : null;
}
getSelectType() {
return this.selectType;
}
getFirstOption() {
let e = null;
for (let t of this.data)
if (t instanceof x ? e = t.options[0] : t instanceof b && (e = t), e)
break;
return e;
}
// Take in search string and return filtered list of values
search(e, t) {
return e = e.trim(), e === "" ? this.getData() : this.filter((s) => t(s, e), !0);
}
// Filter takes in a function that will be used to filter the data
// This will also keep optgroups of sub options meet the filter requirements
filter(e, t) {
const s = [];
return this.data.forEach((i) => {
if (i instanceof x) {
let n = [];
if (i.options.forEach((r) => {
(!e || e(r)) && (t ? n.push(new b(r)) : s.push(new b(r)));
}), n.length > 0) {
let r = new x(i);
r.options = n, s.push(r);
}
}
i instanceof b && (!e || e(i)) && s.push(new b(i));
}), s;
}
// Take in an array of options and reoder them based upon the selected order
selectedOrderOptions(e) {
const t = [];
return this.selectedOrder.forEach((s) => {
const i = e.find((n) => n.id === s);
i && t.push(i);
}), e.forEach((s) => {
let i = !1;
t.forEach((n) => {
if (s.id === n.id) {
i = !0;
return;
}
}), i || t.push(s);
}), t;
}
}
class ve {
settings;
store;
callbacks;
// Used to compute the range selection
lastSelectedOption;
lastRenderedOptions;
// Timeout tracking for cleanup
closeAnimationTimeout = null;
// Elements
main;
content;
// Classes
classes;
constructor(e, t, s, i) {
this.store = s, this.settings = e, this.classes = t, this.callbacks = i, this.lastSelectedOption = null, this.lastRenderedOptions = [], this.main = this.mainDiv(), this.content = this.contentDiv(), this.updateClassStyles(), this.updateAriaAttributes(), this.settings.contentPosition !== "relative" && (this.content.main.style.top = "-9999px", this.content.main.style.left = "-9999px", this.content.main.style.margin = "0", this.content.main.style.width = "auto"), this.settings.contentLocation && this.settings.contentLocation.appendChild(this.content.main);
}
// Helper method to add classes that may contain spaces
// Splits by spaces and adds each class individually to avoid DOMException
addClasses(e, t) {
if (!t || t.trim() === "")
return;
const s = t.split(" ").filter((i) => i.trim() !== "");
for (const i of s)
e.classList.add(i.trim());
}
// Helper method to remove classes that may contain spaces
removeClasses(e, t) {
if (!t || t.trim() === "")
return;
const s = t.split(" ").filter((i) => i.trim() !== "");
for (const i of s)
e.classList.remove(i.trim());
}
// Remove disabled classes
enable() {
this.removeClasses(this.main.main, this.classes.disabled), this.main.main.setAttribute("aria-disabled", "false"), this.content.search.input.disabled = !1;
}
// Set disabled classes
disable() {
this.addClasses(this.main.main, this.classes.disabled), this.main.main.setAttribute("aria-disabled", "true"), this.content.search.input.disabled = !0;
}
open() {
this.main.arrow.path.setAttribute("d", this.classes.arrowOpen), this.main.main.setAttribute("aria-expanded", "true"), this.closeAnimationTimeout && (clearTimeout(this.closeAnimationTimeout), this.closeAnimationTimeout = null);
const t = this.settings.openPosition === "up" ? this.classes.dirAbove : this.classes.dirBelow;
this.addClasses(this.main.main, t), this.addClasses(this.content.main, t), this.addClasses(this.content.main, this.classes.contentOpen), this.content.search.input.removeAttribute("aria-hidden"), this.moveContent();
const s = this.store.getSelectedOptions();
if (s.length) {
const i = s[s.length - 1].id, n = this.content.list.querySelector('[data-id="' + i + '"]');
n && this.ensureElementInView(this.content.list, n);
}
}
close() {
this.main.main.setAttribute("aria-expanded", "false"), this.main.arrow.path.setAttribute("d", this.classes.arrowClose), this.removeClasses(this.content.main, this.classes.contentOpen), this.content.search.input.setAttribute("aria-hidden", "true"), this.main.main.removeAttribute("aria-activedescendant");
const e = this.getAnimationTiming();
this.closeAnimationTimeout = setTimeout(() => {
this.removeClasses(this.main.main, this.classes.dirAbove), this.removeClasses(this.main.main, this.classes.dirBelow), this.removeClasses(this.content.main, this.classes.dirAbove), this.removeClasses(this.content.main, this.classes.dirBelow), this.closeAnimationTimeout = null;
}, e);
}
getAnimationTiming() {
const t = getComputedStyle(this.content.main).getPropertyValue("--ss-animation-timing").trim();
if (t) {
if (t.endsWith("ms"))
return parseFloat(t);
if (t.endsWith("s"))
return parseFloat(t) * 1e3;
}
return 200;
}
updateClassStyles() {
if (this.main.main.className = "", this.main.main.removeAttribute("style"), this.content.main.className = "", this.content.main.removeAttribute("style"), this.addClasses(this.main.main, this.classes.main), this.addClasses(this.content.main, this.classes.content), this.settings.style !== "" && (this.main.main.style.cssText = this.settings.style, this.content.main.style.cssText = this.settings.style), this.settings.class.length)
for (const e of this.settings.class)
e.trim() !== "" && (this.main.main.classList.add(e.trim()), this.content.main.classList.add(e.trim()));
(this.settings.contentPosition === "relative" || this.settings.contentPosition === "fixed") && this.content.main.classList.add("ss-" + this.settings.contentPosition);
}
updateAriaAttributes() {
const e = this.content.list.id;
this.main.main.role = "combobox", this.main.main.setAttribute("aria-haspopup", "listbox"), this.main.main.setAttribute("aria-controls", e), this.main.main.setAttribute("aria-expanded", "false"), this.content.list.setAttribute("role", "listbox"), this.content.list.setAttribute("aria-label", this.settings.ariaLabel + " listbox"), this.settings.isMultiple && this.content.list.setAttribute("aria-multiselectable", "true"), this.content.search.input.setAttribute("aria-controls", e);
}
mainDiv() {
const e = document.createElement("div");
e.dataset.id = this.settings.id, e.setAttribute("aria-label", this.settings.ariaLabel), e.tabIndex = 0, e.onkeydown = (h) => {
switch (h.key) {
case "ArrowUp":
case "ArrowDown":
return this.callbacks.open(), h.key === "ArrowDown" ? this.highlight("down") : this.highlight("up"), !1;
case "Tab":
return this.callbacks.close(), !0;
// Continue doing normal tabbing
case "Enter":
case " ":
this.callbacks.open();
const o = this.content.list.querySelector(
"." + this.classes.getFirst("highlighted")
);
return o && o.click(), !1;
case "Escape":
return this.callbacks.close(), !1;
}
return h.key.length === 1 && this.callbacks.open(), !0;
}, e.onclick = (h) => {
this.settings.disabled || (this.settings.isOpen ? this.callbacks.close() : this.callbacks.open());
};
const t = document.createElement("div");
this.addClasses(t, this.classes.values), e.appendChild(t);
const s = document.createElement("div");
this.addClasses(s, this.classes.deselect);
const i = this.store?.getSelectedOptions();
!this.settings.allowDeselect || this.settings.isMultiple && i && i.length <= 0 ? this.addClasses(s, this.classes.hide) : this.removeClasses(s, this.classes.hide), s.onclick = (h) => {
if (h.stopPropagation(), this.settings.disabled)
return;
let o = !0;
const d = this.store.getSelectedOptions(), m = [];
if (this.callbacks.beforeChange && (o = this.callbacks.beforeChange(m, d) === !0), o) {
if (this.settings.isMultiple)
this.callbacks.setSelected([], !1), this.updateDeselectAll();
else {
const f = this.store.getFirstOption(), E = f ? f.id : "";
this.callbacks.setSelected(E, !1);
}
this.settings.closeOnSelect && this.callbacks.close(), this.callbacks.afterChange && this.callbacks.afterChange(this.store.getSelectedOptions());
}
};
const n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
n.setAttribute("viewBox", "0 0 100 100");
const l = document.createElementNS("http://www.w3.org/2000/svg", "path");
l.setAttribute("d", this.classes.deselectPath), n.appendChild(l), s.appendChild(n), e.appendChild(s);
const r = document.createElementNS("http://www.w3.org/2000/svg", "svg");
this.addClasses(r, this.classes.arrow), r.setAttribute("viewBox", "0 0 100 100");
const c = document.createElementNS("http://www.w3.org/2000/svg", "path");
return c.setAttribute("d", this.classes.arrowClose), this.settings.alwaysOpen && this.addClasses(r, this.classes.hide), r.appendChild(c), e.appendChild(r), {
main: e,
values: t,
deselect: {
main: s,
svg: n,
path: l
},
arrow: {
main: r,
path: c
}
};
}
mainFocus(e) {
e !== "click" && this.main.main.focus({ preventScroll: !0 });
}
placeholder() {
const e = this.store.filter((i) => i.placeholder, !1);
let t = this.settings.placeholderText;
e.length && (e[0].html !== "" ? t = e[0].html : e[0].text !== "" && (t = e[0].text));
const s = document.createElement("div");
return this.addClasses(s, this.classes.placeholder), s.innerHTML = t, s;
}
// Get selected values and append to multiSelected values container
// and remove those who shouldnt exist
renderValues() {
if (!this.settings.isMultiple) {
this.renderSingleValue();
return;
}
this.renderMultipleValues(), this.updateDeselectAll();
}
renderSingleValue() {
const e = this.store.filter((s) => s.selected && !s.placeholder, !1), t = e.length > 0 ? e[0] : null;
if (!t)
this.main.values.innerHTML = this.placeholder().outerHTML;
else {
const s = document.createElement("div");
this.addClasses(s, this.classes.single), t.html ? s.innerHTML = t.html : s.innerText = t.text, this.main.values.innerHTML = s.outerHTML;
}
!this.settings.allowDeselect || !e.length ? this.addClasses(this.main.deselect.main, this.classes.hide) : this.removeClasses(this.main.deselect.main, this.classes.hide);
}
renderMultipleValues() {
let e = this.main.values.childNodes, t = this.store.filter((i) => i.selected && i.display, !1);
if (t.length === 0) {
this.main.values.innerHTML = this.placeholder().outerHTML;
return;
} else {
const i = this.main.values.querySelector("." + this.classes.getFirst("placeholder"));
i && i.remove();
}
if (t.length > this.settings.maxValuesShown) {
const i = document.createElement("div");
this.addClasses(i, this.classes.max), i.textContent = this.settings.maxValuesMessage.replace("{number}", t.length.toString()), this.main.values.innerHTML = i.outerHTML;
return;
} else {
const i = this.main.values.querySelector("." + this.classes.getFirst("max"));
i && i.remove();
}
this.settings.keepOrder && (t = this.store.selectedOrderOptions(t));
let s = [];
for (let i = 0; i < e.length; i++) {
const n = e[i], l = n.getAttribute("data-id");
l && (t.filter((c) => c.id === l, !1).length || s.push(n));
}
for (const i of s)
this.addClasses(i, this.classes.valueOut), setTimeout(() => {
this.main.values.hasChildNodes() && this.main.values.contains(i) && this.main.values.removeChild(i);
}, 100);
e = this.main.values.childNodes;
for (let i = 0; i < t.length; i++) {
let n = !0;
for (let l = 0; l < e.length; l++)
t[i].id === String(e[l].dataset.id) && (n = !1);
n && (this.settings.keepOrder ? this.main.values.appendChild(this.multipleValue(t[i])) : e.length === 0 ? this.main.values.appendChild(this.multipleValue(t[i])) : i === 0 ? this.main.values.insertBefore(this.multipleValue(t[i]), e[i]) : e[i - 1].insertAdjacentElement("afterend", this.multipleValue(t[i])));
}
}
multipleValue(e) {
const t = document.createElement("div");
this.addClasses(t, this.classes.value), t.dataset.id = e.id;
const s = document.createElement("div");
if (this.addClasses(s, this.classes.valueText), s.textContent = e.text, t.appendChild(s), !e.mandatory) {
const i = document.createElement("div");
this.addClasses(i, this.classes.valueDelete), i.setAttribute("tabindex", "0"), i.onclick = (r) => {
if (r.preventDefault(), r.stopPropagation(), this.settings.disabled)
return;
let c = !0;
const h = this.store.getSelectedOptions(), o = h.filter((d) => d.selected && d.id !== e.id, !0);
if (!(this.settings.minSelected && o.length < this.settings.minSelected) && (this.callbacks.beforeChange && (c = this.callbacks.beforeChange(o, h) === !0), c)) {
let d = [];
for (const m of o) {
if (m instanceof x)
for (const f of m.options)
f.id && d.push(f.id);
m instanceof b && d.push(m.id);
}
this.callbacks.setSelected(d, !1), this.settings.closeOnSelect && this.callbacks.close(), this.callbacks.afterChange && this.callbacks.afterChange(o), this.updateDeselectAll();
}
};
const n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
n.setAttribute("viewBox", "0 0 100 100");
const l = document.createElementNS("http://www.w3.org/2000/svg", "path");
l.setAttribute("d", this.classes.optionDelete), n.appendChild(l), i.appendChild(n), t.appendChild(i), i.onkeydown = (r) => {
r.key === "Enter" && i.click();
};
}
return t;
}
contentDiv() {
const e = document.createElement("div");
e.dataset.id = this.settings.id;
const t = this.searchDiv();
e.appendChild(t.main);
const s = this.listDiv();
return e.appendChild(s), {
main: e,
search: t,
list: s
};
}
moveContent() {
if (this.settings.contentPosition === "relative") {
this.moveContentBelow();
return;
}
if (this.settings.openPosition === "down") {
this.moveContentBelow();
return;
} else if (this.settings.openPosition === "up") {
this.moveContentAbove();
return;
}
this.putContent() === "up" ? this.moveContentAbove() : this.moveContentBelow();
}
searchDiv() {
const e = document.createElement("div"), t = document.createElement("input"), s = document.createElement("div");
this.addClasses(e, this.classes.search);
const i = {
main: e,
input: t
};
if (this.settings.showSearch || (this.addClasses(e, this.classes.hide), t.readOnly = !0), t.type = "search", t.placeholder = this.settings.searchPlaceholder, t.tabIndex = -1, t.setAttribute("aria-label", this.settings.searchPlaceholder), t.setAttribute("aria-autocomplete", "list"), t.setAttribute("autocapitalize", "off"), t.setAttribute("autocomplete", "off"), t.setAttribute("autocorrect", "off"), t.setAttribute("aria-hidden", "true"), t.oninput = H((n) => {
this.callbacks.search(n.target.value);
}, 100), t.onkeydown = (n) => {
switch (n.key) {
case "ArrowUp":
case "ArrowDown":
return n.key === "ArrowDown" ? this.highlight("down") : this.highlight("up"), !1;
case "Tab":
return this.callbacks.close(), !0;
// Continue doing normal tabbing
case "Escape":
return this.callbacks.close(), !1;
case " ":
const l = this.content.list.querySelector(
"." + this.classes.getFirst("highlighted")
);
return l ? (l.click(), !1) : !0;
case "Enter":
const r = this.content.list.querySelector(
"." + this.classes.getFirst("highlighted")
);
return r ? (r.click(), !1) : this.callbacks.addable ? (s.click(), !1) : !0;
}
return !0;
}, e.appendChild(t), this.callbacks.addable) {
this.addClasses(s, this.classes.addable);
const n = document.createElementNS("http://www.w3.org/2000/svg", "svg");
n.setAttribute("viewBox", "0 0 100 100");
const l = document.createElementNS("http://www.w3.org/2000/svg", "path");
l.setAttribute("d", this.classes.addablePath), n.appendChild(l), s.appendChild(n), s.onclick = (r) => {
if (r.preventDefault(), r.stopPropagation(), !this.callbacks.addable)
return;
const c = this.content.search.input.value.trim();
if (c === "") {
this.content.search.input.focus();
return;
}
const h = (d) => {
let m = new b(d);
if (this.callbacks.addOption(m), this.settings.isMultiple) {
let f = this.store.getSelected();
f.push(m.id), this.callbacks.setSelected(f, !0);
} else
this.callbacks.setSelected([m.id], !0);
this.callbacks.search(""), this.settings.closeOnSelect && setTimeout(() => {
this.callbacks.close();
}, 100);
}, o = this.callbacks.addable(c);
o === !1 || o === void 0 || o === null || (o instanceof Promise ? o.then((d) => {
typeof d == "string" ? h({
text: d,
value: d
}) : o instanceof Error ? this.renderError(o.message) : h(d);
}) : typeof o == "string" ? h({
text: o,
value: o
}) : o instanceof Error ? this.renderError(o.message) : h(o));
}, e.appendChild(s), i.addable = {
main: s,
svg: n,
path: l
};
}
return i;
}
searchFocus() {
this.content.search.input.focus({ preventScroll: !0 });
}
getOptions(e = !1, t = !1, s = !1) {
let i = "." + this.classes.getFirst("option");
return e && (i += ":not(." + this.classes.getFirst("placeholder") + ")"), t && (i += ":not(." + this.classes.getFirst("disabled") + ")"), s && (i += ":not(." + this.classes.getFirst("hide") + ")"), Array.from(this.content.list.querySelectorAll(i));
}
// highlightUp is used to highlight the previous option in the list
highlight(e) {
const t = this.getOptions(!0, !0, !0);
if (t.length === 0)
return;
if (t.length === 1 && !t[0].classList.contains(this.classes.getFirst("highlighted"))) {
this.addClasses(t[0], this.classes.highlighted);
return;
}
let s = !1;
for (const n of t)
n.classList.contains(this.classes.getFirst("highlighted")) && (s = !0);
if (!s) {
for (const n of t)
if (n.classList.contains(this.classes.getFirst("selected"))) {
this.addClasses(n, this.classes.highlighted);
break;
}
}
for (let n = 0; n < t.length; n++)
if (t[n].classList.contains(this.classes.getFirst("highlighted"))) {
const l = t[n];
this.removeClasses(l, this.classes.highlighted);
const r = l.parentElement;
if (r && r.classList.contains(this.classes.getFirst("mainOpen"))) {
const o = r.querySelector("." + this.classes.getFirst("optgroupLabel"));
o && o.click();
}
let c = t[e === "down" ? n + 1 < t.length ? n + 1 : 0 : n - 1 >= 0 ? n - 1 : t.length - 1];
this.addClasses(c, this.classes.highlighted), this.ensureElementInView(this.content.list, c), c.id && this.main.main.setAttribute("aria-activedescendant", c.id);
const h = c.parentElement;
if (h && h.classList.contains(this.classes.getFirst("close"))) {
const o = h.querySelector(
"." + this.classes.getFirst("optgroupLabel")
);
o && o.click();
}
return;
}
const i = t[e === "down" ? 0 : t.length - 1];
this.addClasses(i, this.classes.highlighted), i.id && this.main.main.setAttribute("aria-activedescendant", i.id), this.ensureElementInView(this.content.list, i);
}
// Create main container that options will reside
listDiv() {
const e = document.createElement("div");
this.addClasses(e, this.classes.list);
const t = this.settings.id + "-list";
return e.id = t, e.dataset.id = t, e;
}
renderError(e) {
this.content.list.innerHTML = "";
const t = document.createElement("div");
this.addClasses(t, this.classes.error), t.textContent = e, this.content.list.appendChild(t);
}
renderSearching() {
this.content.list.innerHTML = "";
const e = document.createElement("div");
this.addClasses(e, this.classes.searching), e.textContent = this.settings.searchingText, this.content.list.appendChild(e);
}
// Take in data and add options to
renderOptions(e) {
if (this.lastRenderedOptions = e.map((s) => s instanceof b ? [s] : s.options.map((i) => new b(i))).flat(), this.content.list.innerHTML = "", e.length === 0) {
const s = document.createElement("div");
this.addClasses(s, this.classes.search), this.callbacks.addable ? s.innerHTML = this.settings.addableText.replace("{value}", this.content.search.input.value) : s.innerHTML = this.settings.searchText, this.content.list.appendChild(s);
return;
}
this.settings.allowDeselect && !this.settings.isMultiple && (this.store.filter((i) => i.placeholder, !1).length || this.store.addOption(
new b({
text: "",
value: "",
selected: !1,
placeholder: !0
}),
!0
));
const t = document.createDocumentFragment();
for (const s of e) {
if (s instanceof x) {
const i = document.createElement("div");
this.addClasses(i, this.classes.optgroup);
const n = document.createElement("div");
this.addClasses(n, this.classes.optgroupLabel), i.appendChild(n);
const l = document.createElement("div");
this.addClasses(l, this.classes.optgroupLabelText), l.textContent = s.label, n.appendChild(l);
const r = document.createElement("div");
if (this.addClasses(r, this.classes.optgroupActions), n.appendChild(r), this.settings.isMultiple && s.selectAll) {
const c = document.createElement("div");
this.addClasses(c, this.classes.optgroupSelectAll);
let h = !0;
for (const E of s.options)
if (!E.selected) {
h = !1;
break;
}
h && this.addClasses(c, this.classes.selected);
const o = document.createElement("span");
o.textContent = s.selectAllText, c.appendChild(o);
const d = document.createElementNS("http://www.w3.org/2000/svg", "svg");
d.setAttribute("viewBox", "0 0 100 100"), c.appendChild(d);
const m = document.createElementNS("http://www.w3.org/2000/svg", "path");
m.setAttribute("d", this.classes.optgroupSelectAllBox), d.appendChild(m);
const f = document.createElementNS("http://www.w3.org/2000/svg", "path");
f.setAttribute("d", this.classes.optgroupSelectAllCheck), d.appendChild(f), c.addEventListener("click", (E) => {
E.preventDefault(), E.stopPropagation();
const g = this.store.getSelected();
if (h) {
const A = g.filter((S) => {
for (const v of s.options)
if (S === v.id)
return !1;
return !0;
});
this.callbacks.setSelected(A, !0);
return;
} else {
let A = s.options.map((v) => v.id).filter((v) => v !== void 0);
const S = g.concat(A);
for (const v of s.options)
v.id && !this.store.getOptionByID(v.id) && this.callbacks.addOption(new b(v));
this.callbacks.setSelected(S, !0);
return;
}
}), r.appendChild(c);
}
if (s.closable !== "off") {
const c = document.createElement("div");
this.addClasses(c, this.classes.optgroupClosable);
const h = document.createElementNS("http://www.w3.org/2000/svg", "svg");
h.setAttribute("viewBox", "0 0 100 100"), this.addClasses(h, this.classes.arrow), c.appendChild(h);
const o = document.createElementNS("http://www.w3.org/2000/svg", "path");
h.appendChild(o), s.options.some((d) => d.selected) || this.content.search.input.value.trim() !== "" ? (this.addClasses(c, this.classes.mainOpen), o.setAttribute("d", this.classes.arrowOpen)) : s.closable === "open" ? (this.addClasses(i, this.classes.mainOpen), o.setAttribute("d", this.classes.arrowOpen)) : s.closable === "close" && (this.addClasses(i, this.classes.close), o.setAttribute("d", this.classes.arrowClose)), n.addEventListener("click", (d) => {
d.preventDefault(), d.stopPropagation(), i.classList.contains(this.classes.getFirst("close")) ? (this.removeClasses(i, this.classes.close), this.addClasses(i, this.classes.mainOpen), o.setAttribute("d", this.classes.arrowOpen)) : (this.removeClasses(i, this.classes.mainOpen), this.addClasses(i, this.classes.close), o.setAttribute("d", this.classes.arrowClose));
}), r.appendChild(c);
}
i.appendChild(n);
for (const c of s.options)
i.appendChild(this.option(new b(c))), t.appendChild(i);
}
s instanceof b && t.appendChild(this.option(s));
}
this.content.list.appendChild(t);
}
// Create option div element
option(e) {
if (e.placeholder) {
const s = document.createElement("div");
return this.addClasses(s, this.classes.option), this.addClasses(s, this.classes.hide), s;
}
const t = document.createElement("div");
return t.dataset.id = e.id, t.id = this.settings.id + "-" + e.id, this.addClasses(t, this.classes.option), t.setAttribute("role", "option"), e.class && e.class.split(" ").forEach((s) => {
t.classList.add(s);
}), e.style && (t.style.cssText = e.style), this.settings.searchHighlight && this.content.search.input.value.trim() !== "" ? t.innerHTML = this.highlightText(
e.html !== "" ? e.html : e.text,
this.content.search.input.value,
this.classes.searchHighlighter
) : e.html !== "" ? t.innerHTML = e.html : t.textContent = e.text, this.settings.showOptionTooltips && t.textContent && t.setAttribute("title", t.textContent), e.display || this.addClasses(t, this.classes.hide), e.disabled && this.addClasses(t, this.classes.disabled), e.selected && this.settings.hideSelected && this.addClasses(t, this.classes.hide), e.selected ? (this.addClasses(t, this.classes.selected), t.setAttribute("aria-selected", "true"), this.main.main.setAttribute("aria-activedescendant", t.id)) : (this.removeClasses(t, this.classes.selected), t.setAttribute("aria-selected", "false")), t.addEventListener("click", (s) => {
s.preventDefault(), s.stopPropagation();
const i = this.store.getSelected(), n = s.currentTarget, l = String(n.dataset.id), r = s.ctrlKey || s.metaKey;
if (e.disabled || !this.settings.isMultiple && e.selected && !this.settings.allowDeselect || e.selected && e.mandatory || this.settings.isMultiple && this.settings.maxSelected <= i.length && !e.selected || this.settings.isMultiple && this.settings.minSelected >= i.length && e.selected && !r)
return;
let c = !1;
const h = this.store.getSelectedOptions();
let o = [];
if (this.settings.isMultiple) {
const d = h.some((f) => f.id === l);
if (s.shiftKey && this.lastSelectedOption) {
const f = this.lastRenderedOptions, E = f.findIndex((A) => A.id === this.lastSelectedOption.id), g = f.findIndex((A) => A.id === e.id);
if (E >= 0 && g >= 0) {
const A = Math.min(E, g), S = Math.max(E, g), k = f.slice(A, S + 1).filter((L) => !h.find((C) => C.id === L.id));
h.length + k.length <= this.settings.maxSelected ? o = h.concat(k) : o = h;
} else
o = h;
} else r ? (d ? o = h.filter((f) => f.id !== l) : o = h.concat(e), this.lastSelectedOption = e) : (d ? o = h.filter((f) => f.id !== l) : o = h.concat(e), this.lastSelectedOption = e);
}
if (this.settings.isMultiple || (e.selected ? o = [] : o = [e]), this.callbacks.beforeChange || (c = !0), this.callbacks.beforeChange && (this.callbacks.beforeChange(o, h) === !1 ? c = !1 : c = !0), c) {
this.store.getOptionByID(l) || this.callbacks.addOption(e), this.callbacks.setSelected(
o.map((f) => f.id),
!1
);
const d = s.ctrlKey || s.metaKey || s.shiftKey;
this.settings.closeOnSelect && !(this.settings.isMultiple && d) && this.callbacks.close(), this.callbacks.afterChange && this.callbacks.afterChange(o);
}
}), t;
}
destroy() {
this.closeAnimationTimeout && (clearTimeout(this.closeAnimationTimeout), this.closeAnimationTimeout = null), this.main.main.remove(), this.content.main.remove();
}
highlightText(e, t, s) {
const i = t.trim();
if (i === "")
return e;
const n = i.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), l = document.createElement("div");
l.innerHTML = e;
const r = (c) => {
if (c.nodeType === Node.TEXT_NODE) {
const h = c.textContent || "", o = new RegExp("(" + n + ")", "i");
if (o.test(h)) {
const d = document.createElement("span");
h.split(o).forEach((f, E) => {
if (f && o.test(f)) {
const g = document.createElement("mark");
g.className = s, g.textContent = f, d.appendChild(g);
} else f && d.appendChild(document.createTextNode(f));
}), c.parentNode?.replaceChild(d, c);
}
} else c.nodeType === Node.ELEMENT_NODE && Array.from(c.childNodes).forEach((h) => r(h));
};
return Array.from(l.childNodes).forEach((c) => r(c)), l.innerHTML;
}
setContentDirection(e) {
const t = e === "above", s = t ? this.classes.dirAbove : this.classes.dirBelow, i = t ? this.classes.dirBelow : this.classes.dirAbove;
if (this.removeClasses(this.main.main, i), this.addClasses(this.main.main, s), this.removeClasses(this.content.main, i), this.addClasses(this.content.main, s), t) {
const n = this.main.main.offsetHeight, l = this.content.main.offsetHeight;
this.content.main.style.margin = "-" + (n + l - 1) + "px 0px 0px 0px";
} else
this.content.main.style.margin = "-1px 0px 0px 0px";
}
setContentPosition() {
if (this.settings.contentPosition === "relative")
return;
const e = this.main.main.getBoundingClientRect();
let t, s;
this.settings.contentPosition === "fixed" ? (t = e.top + e.height, s = e.left) : (t = e.top + window.scrollY + e.height, s = e.left + window.scrollX), this.content.main.style.top = t + "px", this.content.main.style.left = s + "px";
const i = this.settings.contentWidth;
this.content.main.style.width = "", this.content.main.style.minWidth = "", this.content.main.style.maxWidth = "", i ? i.startsWith(">") ? this.content.main.style.minWidth = i.slice(1) : i.startsWith("<") ? this.content.main.style.maxWidth = i.slice(1) : this.content.main.style.width = i : this.content.main.style.width = e.width + "px";
const n = 20, l = window.innerWidth - n, r = () => {
const h = this.content.main.getBoundingClientRect().right;
if (h <= l) return;
const o = h - l, d = parseFloat(this.content.main.style.left) || 0;
if (this.settings.contentPosition === "fixed") {
const m = Math.max(n, d - o);
this.c