@loop8/vue-select 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,600 @@
1
+ import { defineComponent as Ce, ref as x, computed as N, nextTick as A, onMounted as Ie, onBeforeUnmount as Ee, watch as J, openBlock as y, createElementBlock as V, normalizeClass as we, withModifiers as R, createElementVNode as T, Fragment as Y, renderSlot as ae, toDisplayString as F, renderList as ie, withKeys as q, createCommentVNode as ee, unref as Ue, isRef as $e, createTextVNode as Be, toRaw as Ke } from "vue";
2
+ const Ne = { class: "loop-select-selection" }, _e = { class: "loop-select-single-selection" }, Fe = { class: "loop-select-selected-text" }, qe = {
3
+ key: 1,
4
+ class: "loop-select-placeholder"
5
+ }, He = {
6
+ key: 0,
7
+ class: "loop-select-tags-container"
8
+ }, Ge = ["onClick"], De = {
9
+ key: 1,
10
+ class: "loop-select-placeholder"
11
+ }, Me = { class: "loop-select-search-container" }, Je = ["onKeydown"], Qe = {
12
+ key: 0,
13
+ class: "loop-select-search-spinner"
14
+ }, ze = ["tabindex", "onKeydown"], We = {
15
+ key: 0,
16
+ class: "loop-select-no-results"
17
+ }, Xe = ["onClick", "onMouseover"], Ye = {
18
+ key: 0,
19
+ class: "loop-select-loading-more"
20
+ }, Ze = ["multiple", "name", "required", "disabled"], el = {
21
+ key: 0,
22
+ value: "",
23
+ disabled: "",
24
+ selected: ""
25
+ }, ll = ["value"], tl = ["value"], xe = /* @__PURE__ */ Ce({
26
+ name: "Loop8Select",
27
+ __name: "Loop8Select",
28
+ props: {
29
+ modelValue: {
30
+ type: [Array, String, Number, Object, Boolean],
31
+ default: null
32
+ },
33
+ options: {
34
+ type: Array,
35
+ default: () => []
36
+ },
37
+ placeholder: {
38
+ type: String,
39
+ default: "Select an option"
40
+ },
41
+ multiple: {
42
+ type: Boolean,
43
+ default: !1
44
+ },
45
+ disabled: {
46
+ type: Boolean,
47
+ default: !1
48
+ },
49
+ required: {
50
+ type: Boolean,
51
+ default: !1
52
+ },
53
+ name: {
54
+ type: String,
55
+ default: ""
56
+ },
57
+ loading: {
58
+ type: Boolean,
59
+ default: !1
60
+ },
61
+ valueKey: {
62
+ type: String,
63
+ default: "value"
64
+ },
65
+ labelKey: {
66
+ type: String,
67
+ default: "text"
68
+ },
69
+ ajax: {
70
+ type: Object,
71
+ default: null
72
+ }
73
+ },
74
+ emits: ["update:modelValue", "invalid-option", "update:selectedOptions"],
75
+ setup(S, { emit: Ae }) {
76
+ const l = S, I = Ae, K = x(!1), L = x(""), c = x(-1), se = x(null), ce = x(null), d = x(null), j = x(null), H = x(l.loading), p = x([]), E = x(null), oe = x({}), Q = x(1), z = x(!1), U = x(!1), O = x({}), $ = N(() => !!l.ajax), Z = N(() => {
77
+ var e;
78
+ return $.value && !!((e = l.ajax) != null && e.pagination);
79
+ }), ne = N(() => {
80
+ var a;
81
+ if (!$.value)
82
+ return !0;
83
+ const e = ((a = l.ajax) == null ? void 0 : a.minimumInputLength) || 0;
84
+ return L.value.length >= e;
85
+ }), W = N(() => {
86
+ const e = $.value ? [...l.options, ...p.value] : l.options, a = Object.values(O.value);
87
+ if (a.length > 0) {
88
+ const t = a.filter(
89
+ (o) => !e.some((s) => u(s) === u(o))
90
+ );
91
+ return [...e, ...t];
92
+ }
93
+ return e;
94
+ }), B = N(() => {
95
+ if (l.multiple) {
96
+ if (!l.modelValue || !Array.isArray(l.modelValue))
97
+ return [];
98
+ const e = Array.isArray(l.modelValue) ? l.modelValue : [l.modelValue], a = [], t = e.map((o) => {
99
+ if (o != null && O.value[String(o)])
100
+ return O.value[String(o)];
101
+ const s = W.value.find((i) => u(i) === o);
102
+ if (s)
103
+ return O.value[String(o)] = s, s;
104
+ const n = p.value.find((i) => u(i) === o);
105
+ return n ? (O.value[String(o)] = n, n) : (a.push(o), null);
106
+ }).filter((o) => o !== null);
107
+ return a.length > 0 && (I("invalid-option", a), A(() => {
108
+ const o = e.filter((s) => !a.includes(s));
109
+ I("update:modelValue", o);
110
+ })), t;
111
+ } else {
112
+ if (l.modelValue === null || l.modelValue === void 0)
113
+ return [];
114
+ const e = l.modelValue;
115
+ if (e != null && O.value[String(e)])
116
+ return [O.value[String(e)]];
117
+ const a = W.value.find(
118
+ (o) => u(o) === e
119
+ );
120
+ if (a)
121
+ return O.value[String(e)] = a, [a];
122
+ const t = p.value.find((o) => u(o) === e);
123
+ return t ? (O.value[String(e)] = t, [t]) : (I("invalid-option", e), A(() => {
124
+ I("update:modelValue", null);
125
+ }), []);
126
+ }
127
+ }), G = N(() => B.value.length > 0 ? B.value[0] : null), de = N(() => G.value ? u(G.value) : null);
128
+ N(() => {
129
+ const e = B.value[0];
130
+ return e ? D(e) : "";
131
+ });
132
+ const P = N(() => {
133
+ if ($.value)
134
+ return ne.value ? p.value : [];
135
+ if (!L.value)
136
+ return l.options;
137
+ const e = L.value.toLowerCase();
138
+ return l.options.filter((a) => D(a).toLowerCase().includes(e));
139
+ }), u = (e) => typeof e == "object" && e !== null ? e[l.valueKey] : e, D = (e) => typeof e == "object" && e !== null ? e[l.labelKey] || e[l.valueKey] || "" : String(e), ve = (e) => {
140
+ const a = u(e);
141
+ return l.multiple && Array.isArray(l.modelValue) ? l.modelValue.includes(a) : l.modelValue === a;
142
+ }, fe = (e) => {
143
+ const a = u(e);
144
+ if (O.value[String(a)] = e, l.multiple) {
145
+ let t = [];
146
+ Array.isArray(l.modelValue) ? l.modelValue.includes(a) ? t = l.modelValue.filter((s) => s !== a) : t = [...l.modelValue, a] : t = [a], I("update:modelValue", t);
147
+ const o = t.map((s) => s === a ? e : Ke(O.value[String(s)]) || W.value.find((n) => u(n) === s)).filter(Boolean);
148
+ I("update:selectedOptions", o);
149
+ } else
150
+ I("update:modelValue", a), I("update:selectedOptions", [e]), le();
151
+ L.value = "", d.value && (d.value.value = ""), $.value && (p.value.some((t) => u(t) === a) || (p.value = [...p.value, e])), l.multiple && A(() => {
152
+ d.value && d.value.focus();
153
+ });
154
+ }, pe = (e) => {
155
+ const a = u(e);
156
+ if (l.multiple && Array.isArray(l.modelValue)) {
157
+ const t = l.modelValue.filter((o) => o !== a);
158
+ I("update:modelValue", t), I("update:selectedOptions", B.value), t.includes(a) || delete O.value[String(a)];
159
+ }
160
+ }, Oe = () => {
161
+ l.disabled || (K.value = !K.value, K.value && (L.value = "", ue(), A(() => {
162
+ d.value && !C && (d.value.value = "", d.value.focus()), A(() => {
163
+ P.value.length > 0 ? (c.value = 0, _()) : c.value = -1;
164
+ });
165
+ })));
166
+ }, le = () => {
167
+ K.value = !1, L.value = "", d.value && (d.value.value = ""), ue();
168
+ }, ue = () => {
169
+ Q.value = 1, z.value = !1, (!Z.value || !l.modelValue) && (p.value = []), U.value = !1;
170
+ };
171
+ let X = -1, g = !1, C = !1;
172
+ const me = () => {
173
+ U.value || (X = c.value, g = X >= 0, g && (C = !0), console.log(`Loading more results, page ${Q.value + 1}`), Q.value++, U.value = !0, he(L.value, !0));
174
+ }, he = async (e, a = !1) => {
175
+ if (!$.value || !ne.value)
176
+ return Promise.resolve();
177
+ const t = l.ajax, o = Z.value ? `${e}_${Q.value}` : e;
178
+ let s = [];
179
+ if (l.modelValue && (s = [...B.value]), t.cache && oe.value[o]) {
180
+ const w = oe.value[o];
181
+ if (a)
182
+ p.value = [...p.value, ...w.results];
183
+ else {
184
+ const h = w.results, r = l.multiple && Array.isArray(l.modelValue) ? l.modelValue : l.modelValue ? [l.modelValue] : [], f = s.filter(
185
+ (k) => {
186
+ const b = u(k);
187
+ return r.includes(b) && !h.some((M) => u(M) === b);
188
+ }
189
+ );
190
+ p.value = [...f, ...h];
191
+ }
192
+ return z.value = w.more, U.value = !1, Promise.resolve();
193
+ }
194
+ !a && E.value !== null && (window.clearTimeout(E.value), E.value = null);
195
+ const n = t.method || "GET";
196
+ let i = t.url;
197
+ t.urlBuilder && typeof t.urlBuilder == "function" && (i = t.urlBuilder(e, i), console.log("Using dynamically built URL:", i));
198
+ const m = t.headers || {
199
+ "Content-Type": "application/json",
200
+ Accept: "application/json"
201
+ };
202
+ let v = {};
203
+ if (t.params)
204
+ if (typeof t.params == "function") {
205
+ const w = Z.value ? {
206
+ page: Q.value,
207
+ limit: t.limit || 10
208
+ } : void 0;
209
+ v = t.params(e, w);
210
+ } else
211
+ v = { ...t.params, query: e };
212
+ else
213
+ v = t.urlBuilder ? {} : { query: e };
214
+ if (Z.value) {
215
+ const w = t.limit || 10;
216
+ if (!("page" in v) && !("per_page" in v)) {
217
+ const h = t.pageParam || "page", r = t.limitParam || "per_page";
218
+ v[h] = Q.value, v[r] = w;
219
+ }
220
+ }
221
+ return a || (H.value = !0), new Promise((w) => {
222
+ let h;
223
+ if (n === "GET") {
224
+ const r = new URLSearchParams(v).toString(), f = r ? `${i}?${r}` : i;
225
+ console.log("Making request to:", f), h = fetch(f, {
226
+ method: n,
227
+ headers: m
228
+ });
229
+ } else
230
+ h = fetch(i, {
231
+ method: n,
232
+ headers: m,
233
+ body: JSON.stringify(v)
234
+ });
235
+ h.then((r) => r.json()).then((r) => {
236
+ let f = [], k = !1;
237
+ if (t.processResults) {
238
+ const b = t.processResults(r);
239
+ f = b.results, k = b.more;
240
+ } else
241
+ Array.isArray(r) ? (f = r, k = !1) : r.results && Array.isArray(r.results) ? (f = r.results, k = !!r.more) : (f = [], k = !1);
242
+ if (console.log(`Fetched ${f.length} results, more: ${k}`), a)
243
+ p.value = [...p.value, ...f], A(() => {
244
+ if (g) {
245
+ const b = Math.min(X, P.value.length - 1);
246
+ c.value = b, _(), j.value && j.value.focus(), setTimeout(() => {
247
+ C = !1;
248
+ }, 100);
249
+ }
250
+ });
251
+ else {
252
+ const b = l.multiple && Array.isArray(l.modelValue) ? l.modelValue : l.modelValue ? [l.modelValue] : [], M = s.filter(
253
+ (te) => {
254
+ const je = u(te);
255
+ return b.includes(je) && !f.some((Le) => u(Le) === je);
256
+ }
257
+ );
258
+ p.value = [...M, ...f];
259
+ }
260
+ z.value = k, t.cache && (oe.value[o] = { results: f, more: k }), w();
261
+ }).catch((r) => {
262
+ console.error("Error fetching options:", r), a || (p.value = s), z.value = !1, w();
263
+ }).finally(() => {
264
+ H.value = !1, U.value = !1, a && g && A(() => {
265
+ setTimeout(() => {
266
+ C = !1;
267
+ }, 100);
268
+ });
269
+ });
270
+ });
271
+ }, ke = (e) => {
272
+ g = !1, C = !1, e.stopPropagation();
273
+ }, be = () => {
274
+ g = !1, C = !1;
275
+ }, Re = (e) => {
276
+ var t;
277
+ L.value;
278
+ const a = e.target.value;
279
+ if (L.value = a, g = !1, $.value) {
280
+ if (ue(), E.value !== null && (window.clearTimeout(E.value), E.value = null), !ne.value) {
281
+ p.value = [];
282
+ return;
283
+ }
284
+ const o = ((t = l.ajax) == null ? void 0 : t.delay) || 300;
285
+ E.value = window.setTimeout(() => {
286
+ const s = document.activeElement === d.value;
287
+ s && (g = !1, C = !1), he(L.value).then(() => {
288
+ A(() => {
289
+ P.value.length > 0 && (c.value = 0, _());
290
+ const n = document.activeElement === d.value;
291
+ (s || n) && d.value ? d.value.focus() : g && P.value.length > 0 && j.value && j.value.focus();
292
+ });
293
+ });
294
+ }, o);
295
+ }
296
+ }, _ = () => {
297
+ A(() => {
298
+ if (c.value < 0 || !ce.value || !j.value)
299
+ return;
300
+ const e = j.value.querySelector(".loop-select-option-highlighted");
301
+ if (e) {
302
+ const a = j.value, t = a.clientHeight, o = e, s = o.offsetTop, n = o.clientHeight, i = a.scrollTop, m = s < i, v = s + n > i + t;
303
+ m ? a.scrollTop = s : v && (a.scrollTop = s + n - t);
304
+ }
305
+ });
306
+ };
307
+ Ie(() => {
308
+ document.addEventListener("click", ge), $.value && l.modelValue && W.value.length === 0 && (l.multiple ? Array.isArray(l.modelValue) && l.modelValue.length > 0 : l.modelValue !== null && l.modelValue !== void 0) && (console.log("Initial value present, fetching option data"), Pe());
309
+ }), Ee(() => {
310
+ document.removeEventListener("click", ge), E.value !== null && (window.clearTimeout(E.value), E.value = null);
311
+ }), J(() => l.loading, (e) => {
312
+ H.value = e;
313
+ }), J(P, (e, a) => {
314
+ if (!U.value) {
315
+ e.length > 0 ? (c.value = 0, g && A(() => {
316
+ j.value && j.value.focus();
317
+ })) : c.value = -1;
318
+ return;
319
+ }
320
+ A(() => {
321
+ if (g && X >= 0 && e.length > a.length) {
322
+ const t = Math.min(X, e.length - 1);
323
+ c.value = t, _();
324
+ }
325
+ });
326
+ }), J(L, (e) => {
327
+ d.value && d.value.value !== e && (d.value.value = e);
328
+ }), J(c, () => {
329
+ c.value >= 0 && _();
330
+ }), J(() => l.modelValue, (e) => {
331
+ $.value && e && (l.multiple && Array.isArray(e) ? e : [e]).forEach((t) => {
332
+ if (!W.value.find((s) => u(s) === t) && B.value) {
333
+ const s = B.value.find((n) => u(n) === t);
334
+ s && (p.value.find((n) => u(n) === t) || p.value.push(s));
335
+ }
336
+ });
337
+ }, { immediate: !0 });
338
+ const ge = (e) => {
339
+ se.value && !se.value.contains(e.target) && K.value && le();
340
+ }, Te = () => {
341
+ if (!Z.value || !z.value || U.value)
342
+ return;
343
+ const e = j.value;
344
+ if (!e)
345
+ return;
346
+ const a = e.scrollTop + e.clientHeight, t = 20;
347
+ a >= e.scrollHeight - t && (console.log("Reached bottom of options list, loading more results..."), me());
348
+ }, ye = () => {
349
+ P.value.length !== 0 && (g = !0, c.value < P.value.length - 1 ? (c.value++, _(), A(() => {
350
+ j.value && j.value.focus();
351
+ })) : z.value && !U.value && (g = !0, C = !0, X = c.value, me()));
352
+ }, Ve = () => {
353
+ P.value.length !== 0 && (g = !0, c.value > 0 && (c.value--, _(), A(() => {
354
+ j.value && j.value.focus();
355
+ })));
356
+ }, Se = () => {
357
+ c.value >= 0 && P.value[c.value] && (fe(P.value[c.value]), l.multiple && A(() => {
358
+ K.value && d.value && d.value.focus();
359
+ }));
360
+ };
361
+ J(K, (e) => {
362
+ e && A(() => {
363
+ d.value && !C && d.value.focus();
364
+ });
365
+ }), J(() => U.value, (e, a) => {
366
+ a === !0 && e === !1 && setTimeout(() => {
367
+ C && !g && (C = !1);
368
+ }, 200);
369
+ });
370
+ const Pe = async () => {
371
+ var t, o;
372
+ if (!$.value)
373
+ return;
374
+ const e = l.multiple && Array.isArray(l.modelValue) ? l.modelValue : [l.modelValue];
375
+ if (e.length === 0)
376
+ return;
377
+ const a = e.filter((s) => !(s == null || O.value[String(s)] || W.value.some((n) => u(n) === s)));
378
+ if (a.length !== 0) {
379
+ H.value = !0;
380
+ try {
381
+ let s = [];
382
+ if ((t = l.ajax) != null && t.initialValueResolver) {
383
+ console.log("Using custom initialValueResolver to fetch option details");
384
+ const n = a.map(async (m) => {
385
+ const v = await l.ajax.initialValueResolver(m);
386
+ return v || null;
387
+ });
388
+ s = (await Promise.all(n)).filter((m) => m !== null);
389
+ } else if ((o = l.ajax) != null && o.initialValueUrl) {
390
+ console.log("Using initialValueUrl to fetch option details");
391
+ const n = l.ajax.initialValueUrl, i = l.ajax.method || "GET";
392
+ let m = {};
393
+ l.ajax.initialValueParams ? typeof l.ajax.initialValueParams == "function" ? m = l.ajax.initialValueParams(a) : m = l.ajax.initialValueParams : m = { ids: a.join(",") };
394
+ const v = l.ajax.headers || {
395
+ "Content-Type": "application/json",
396
+ Accept: "application/json"
397
+ };
398
+ let w;
399
+ if (i === "GET") {
400
+ const r = new URLSearchParams(m).toString(), f = r ? `${n}?${r}` : n;
401
+ console.log("Fetching initial values from:", f), w = await fetch(f, { method: i, headers: v });
402
+ } else
403
+ w = await fetch(n, {
404
+ method: i,
405
+ headers: v,
406
+ body: JSON.stringify(m)
407
+ });
408
+ const h = await w.json();
409
+ l.ajax.processResults ? s = l.ajax.processResults(h).results : s = Array.isArray(h) ? h : h.results || [];
410
+ } else {
411
+ console.log("Using regular ajax URL with id parameter to fetch option details");
412
+ const n = l.multiple ? a : [a[0]];
413
+ for (const i of n) {
414
+ const m = l.ajax.url, v = l.ajax.method || "GET";
415
+ let h = { [l.ajax.idParam || "id"]: i };
416
+ l.ajax.params && (typeof l.ajax.params == "function" ? h = { ...h, ...l.ajax.params("") } : h = { ...h, ...l.ajax.params });
417
+ const r = l.ajax.headers || {
418
+ "Content-Type": "application/json",
419
+ Accept: "application/json"
420
+ };
421
+ let f;
422
+ if (v === "GET") {
423
+ const M = new URLSearchParams(h).toString(), te = M ? `${m}?${M}` : m;
424
+ console.log("Fetching initial value from:", te), f = await fetch(te, { method: v, headers: r });
425
+ } else
426
+ f = await fetch(m, {
427
+ method: v,
428
+ headers: r,
429
+ body: JSON.stringify(h)
430
+ });
431
+ const k = await f.json();
432
+ let b = [];
433
+ l.ajax.processResults ? b = l.ajax.processResults(k).results : b = Array.isArray(k) ? k : k.results || [], s = [...s, ...b];
434
+ }
435
+ }
436
+ console.log("Resolved initial options:", s), s.forEach((n) => {
437
+ const i = u(n);
438
+ i != null && (O.value[String(i)] = n, p.value.some((m) => u(m) === i) || p.value.push(n));
439
+ });
440
+ } catch (s) {
441
+ console.error("Error fetching initial value details:", s);
442
+ } finally {
443
+ H.value = !1;
444
+ }
445
+ }
446
+ };
447
+ return (e, a) => (y(), V("div", {
448
+ class: we([
449
+ "loop-select-container",
450
+ { "loop-select-open": K.value, "loop-select-disabled": S.disabled }
451
+ ]),
452
+ onClick: R(Oe, ["stop"]),
453
+ ref_key: "containerRef",
454
+ ref: se
455
+ }, [
456
+ T("div", Ne, [
457
+ T("div", _e, [
458
+ S.multiple ? (y(), V(Y, { key: 1 }, [
459
+ B.value.length ? (y(), V("div", He, [
460
+ (y(!0), V(Y, null, ie(B.value, (t) => (y(), V("div", {
461
+ key: u(t),
462
+ class: "loop-select-selected-item"
463
+ }, [
464
+ ae(e.$slots, "selected-option", {
465
+ option: t,
466
+ remove: () => pe(t)
467
+ }, () => [
468
+ T("span", null, F(D(t)), 1),
469
+ T("button", {
470
+ class: "loop-select-remove-item",
471
+ onClick: R((o) => pe(t), ["stop"]),
472
+ type: "button"
473
+ }, " × ", 8, Ge)
474
+ ])
475
+ ]))), 128))
476
+ ])) : (y(), V("span", De, F(S.placeholder), 1))
477
+ ], 64)) : (y(), V(Y, { key: 0 }, [
478
+ G.value ? ae(e.$slots, "selected-option", {
479
+ key: 0,
480
+ option: G.value,
481
+ remove: () => {
482
+ }
483
+ }, () => [
484
+ T("span", Fe, F(D(G.value)), 1)
485
+ ]) : (y(), V("span", qe, F(S.placeholder), 1))
486
+ ], 64))
487
+ ]),
488
+ a[1] || (a[1] = T("div", { class: "loop-select-arrow" }, [
489
+ T("span", null, "▼")
490
+ ], -1))
491
+ ]),
492
+ K.value ? (y(), V("div", {
493
+ key: 0,
494
+ class: "loop-select-dropdown",
495
+ ref_key: "dropdownRef",
496
+ ref: ce
497
+ }, [
498
+ T("div", Me, [
499
+ T("input", {
500
+ ref_key: "searchInputRef",
501
+ ref: d,
502
+ class: "loop-select-search",
503
+ type: "text",
504
+ onInput: Re,
505
+ onKeydown: [
506
+ a[0] || (a[0] = R(() => {
507
+ }, ["stop"])),
508
+ q(R(ye, ["prevent"]), ["down"]),
509
+ q(R(Ve, ["prevent"]), ["up"]),
510
+ q(R(Se, ["prevent"]), ["enter"]),
511
+ q(R(le, ["prevent"]), ["esc"])
512
+ ],
513
+ onClick: R(ke, ["stop"]),
514
+ onFocus: be,
515
+ placeholder: "Search..."
516
+ }, null, 40, Je),
517
+ S.loading || H.value ? (y(), V("div", Qe, a[2] || (a[2] = [
518
+ T("div", { class: "lds-dual-ring" }, null, -1)
519
+ ]))) : ee("", !0)
520
+ ]),
521
+ T("ul", {
522
+ class: "loop-select-options",
523
+ onScroll: Te,
524
+ ref_key: "optionsListRef",
525
+ ref: j,
526
+ tabindex: Ue(g) ? 0 : -1,
527
+ onKeydown: [
528
+ q(R(ye, ["prevent"]), ["down"]),
529
+ q(R(Ve, ["prevent"]), ["up"]),
530
+ q(R(Se, ["prevent"]), ["enter"]),
531
+ q(R(le, ["prevent"]), ["esc"])
532
+ ]
533
+ }, [
534
+ P.value.length === 0 && !S.loading && !H.value ? (y(), V("li", We, "No results found")) : (y(), V(Y, { key: 1 }, [
535
+ (y(!0), V(Y, null, ie(P.value, (t, o) => (y(), V("li", {
536
+ key: u(t),
537
+ class: we([
538
+ "loop-select-option",
539
+ {
540
+ "loop-select-option-selected": ve(t),
541
+ "loop-select-option-highlighted": o === c.value
542
+ }
543
+ ]),
544
+ onClick: R((s) => fe(t), ["stop"]),
545
+ onMouseover: () => {
546
+ c.value = o, _(), $e(g) ? g.value = !1 : g = !1;
547
+ }
548
+ }, [
549
+ ae(e.$slots, "option", {
550
+ option: t,
551
+ selected: ve(t),
552
+ highlighted: o === c.value,
553
+ index: o
554
+ }, () => [
555
+ Be(F(D(t)), 1)
556
+ ])
557
+ ], 42, Xe))), 128)),
558
+ U.value ? (y(), V("li", Ye, [
559
+ ae(e.$slots, "loading-more", {}, () => [
560
+ a[3] || (a[3] = T("div", { class: "lds-dual-ring" }, null, -1))
561
+ ])
562
+ ])) : ee("", !0)
563
+ ], 64))
564
+ ], 40, ze)
565
+ ], 512)) : ee("", !0),
566
+ T("select", {
567
+ multiple: S.multiple,
568
+ name: S.name,
569
+ required: S.required,
570
+ disabled: S.disabled,
571
+ tabindex: "-1",
572
+ class: "loop-select-hidden",
573
+ "aria-hidden": "true"
574
+ }, [
575
+ !S.multiple && !de.value ? (y(), V("option", el, F(S.placeholder), 1)) : ee("", !0),
576
+ S.multiple ? (y(!0), V(Y, { key: 1 }, ie(B.value, (t) => (y(), V("option", {
577
+ key: u(t),
578
+ value: u(t),
579
+ selected: ""
580
+ }, F(D(t)), 9, ll))), 128)) : G.value ? (y(), V("option", {
581
+ key: 2,
582
+ value: de.value,
583
+ selected: ""
584
+ }, F(D(G.value)), 9, tl)) : ee("", !0)
585
+ ], 8, Ze)
586
+ ], 2));
587
+ }
588
+ });
589
+ let re = null;
590
+ typeof window < "u" && (re = window.Vue);
591
+ re && re.component("Loop8Select", xe);
592
+ const sl = {
593
+ install: (S) => {
594
+ S.component("Loop8Select", xe);
595
+ }
596
+ };
597
+ export {
598
+ xe as Loop8Select,
599
+ sl as default
600
+ };
@@ -0,0 +1 @@
1
+ (function(C,e){typeof exports=="object"&&typeof module<"u"?e(exports,require("vue")):typeof define=="function"&&define.amd?define(["exports","vue"],e):(C=typeof globalThis<"u"?globalThis:C||self,e(C.Loop8Select={},C.Vue))})(this,function(C,e){"use strict";const Me="",Ue="",de={class:"loop-select-selection"},fe={class:"loop-select-single-selection"},pe={class:"loop-select-selected-text"},me={key:1,class:"loop-select-placeholder"},he={key:0,class:"loop-select-tags-container"},ge=["onClick"],ve={key:1,class:"loop-select-placeholder"},ye={class:"loop-select-search-container"},ke=["onKeydown"],Ve={key:0,class:"loop-select-search-spinner"},we=["tabindex","onKeydown"],Se={key:0,class:"loop-select-no-results"},xe=["onClick","onMouseover"],Be={key:0,class:"loop-select-loading-more"},je=["multiple","name","required","disabled"],Ee={key:0,value:"",disabled:"",selected:""},Te=["value"],Ae=["value"],J=e.defineComponent({name:"Loop8Select",__name:"Loop8Select",props:{modelValue:{type:[Array,String,Number,Object,Boolean],default:null},options:{type:Array,default:()=>[]},placeholder:{type:String,default:"Select an option"},multiple:{type:Boolean,default:!1},disabled:{type:Boolean,default:!1},required:{type:Boolean,default:!1},name:{type:String,default:""},loading:{type:Boolean,default:!1},valueKey:{type:String,default:"value"},labelKey:{type:String,default:"text"},ajax:{type:Object,default:null}},emits:["update:modelValue","invalid-option","update:selectedOptions"],setup(k,{emit:be}){const t=k,A=be,P=e.ref(!1),E=e.ref(""),d=e.ref(-1),Q=e.ref(null),Z=e.ref(null),f=e.ref(null),V=e.ref(null),I=e.ref(t.loading),h=e.ref([]),O=e.ref(null),W=e.ref({}),$=e.ref(1),F=e.ref(!1),b=e.ref(!1),S=e.ref({}),R=e.computed(()=>!!t.ajax),q=e.computed(()=>{var l;return R.value&&!!((l=t.ajax)!=null&&l.pagination)}),X=e.computed(()=>{var o;if(!R.value)return!0;const l=((o=t.ajax)==null?void 0:o.minimumInputLength)||0;return E.value.length>=l}),_=e.computed(()=>{const l=R.value?[...t.options,...h.value]:t.options,o=Object.values(S.value);if(o.length>0){const a=o.filter(s=>!l.some(n=>r(n)===r(s)));return[...l,...a]}return l}),N=e.computed(()=>{if(t.multiple){if(!t.modelValue||!Array.isArray(t.modelValue))return[];const l=Array.isArray(t.modelValue)?t.modelValue:[t.modelValue],o=[],a=l.map(s=>{if(s!=null&&S.value[String(s)])return S.value[String(s)];const n=_.value.find(c=>r(c)===s);if(n)return S.value[String(s)]=n,n;const i=h.value.find(c=>r(c)===s);return i?(S.value[String(s)]=i,i):(o.push(s),null)}).filter(s=>s!==null);return o.length>0&&(A("invalid-option",o),e.nextTick(()=>{const s=l.filter(n=>!o.includes(n));A("update:modelValue",s)})),a}else{if(t.modelValue===null||t.modelValue===void 0)return[];const l=t.modelValue;if(l!=null&&S.value[String(l)])return[S.value[String(l)]];const o=_.value.find(s=>r(s)===l);if(o)return S.value[String(l)]=o,[o];const a=h.value.find(s=>r(s)===l);return a?(S.value[String(l)]=a,[a]):(A("invalid-option",l),e.nextTick(()=>{A("update:modelValue",null)}),[])}}),K=e.computed(()=>N.value.length>0?N.value[0]:null),ee=e.computed(()=>K.value?r(K.value):null);e.computed(()=>{const l=N.value[0];return l?M(l):""});const j=e.computed(()=>{if(R.value)return X.value?h.value:[];if(!E.value)return t.options;const l=E.value.toLowerCase();return t.options.filter(o=>M(o).toLowerCase().includes(l))}),r=l=>typeof l=="object"&&l!==null?l[t.valueKey]:l,M=l=>typeof l=="object"&&l!==null?l[t.labelKey]||l[t.valueKey]||"":String(l),le=l=>{const o=r(l);return t.multiple&&Array.isArray(t.modelValue)?t.modelValue.includes(o):t.modelValue===o},te=l=>{const o=r(l);if(S.value[String(o)]=l,t.multiple){let a=[];Array.isArray(t.modelValue)?t.modelValue.includes(o)?a=t.modelValue.filter(n=>n!==o):a=[...t.modelValue,o]:a=[o],A("update:modelValue",a);const s=a.map(n=>n===o?l:e.toRaw(S.value[String(n)])||_.value.find(i=>r(i)===n)).filter(Boolean);A("update:selectedOptions",s)}else A("update:modelValue",o),A("update:selectedOptions",[l]),H();E.value="",f.value&&(f.value.value=""),R.value&&(h.value.some(a=>r(a)===o)||(h.value=[...h.value,l])),t.multiple&&e.nextTick(()=>{f.value&&f.value.focus()})},ae=l=>{const o=r(l);if(t.multiple&&Array.isArray(t.modelValue)){const a=t.modelValue.filter(s=>s!==o);A("update:modelValue",a),A("update:selectedOptions",N.value),a.includes(o)||delete S.value[String(o)]}},Re=()=>{t.disabled||(P.value=!P.value,P.value&&(E.value="",Y(),e.nextTick(()=>{f.value&&!T&&(f.value.value="",f.value.focus()),e.nextTick(()=>{j.value.length>0?(d.value=0,L()):d.value=-1})})))},H=()=>{P.value=!1,E.value="",f.value&&(f.value.value=""),Y()},Y=()=>{$.value=1,F.value=!1,(!q.value||!t.modelValue)&&(h.value=[]),b.value=!1};let D=-1,y=!1,T=!1;const oe=()=>{b.value||(D=d.value,y=D>=0,y&&(T=!0),console.log(`Loading more results, page ${$.value+1}`),$.value++,b.value=!0,ne(E.value,!0))},ne=async(l,o=!1)=>{if(!R.value||!X.value)return Promise.resolve();const a=t.ajax,s=q.value?`${l}_${$.value}`:l;let n=[];if(t.modelValue&&(n=[...N.value]),a.cache&&W.value[s]){const w=W.value[s];if(o)h.value=[...h.value,...w.results];else{const v=w.results,u=t.multiple&&Array.isArray(t.modelValue)?t.modelValue:t.modelValue?[t.modelValue]:[],m=n.filter(x=>{const B=r(x);return u.includes(B)&&!v.some(U=>r(U)===B)});h.value=[...m,...v]}return F.value=w.more,b.value=!1,Promise.resolve()}!o&&O.value!==null&&(window.clearTimeout(O.value),O.value=null);const i=a.method||"GET";let c=a.url;a.urlBuilder&&typeof a.urlBuilder=="function"&&(c=a.urlBuilder(l,c),console.log("Using dynamically built URL:",c));const g=a.headers||{"Content-Type":"application/json",Accept:"application/json"};let p={};if(a.params)if(typeof a.params=="function"){const w=q.value?{page:$.value,limit:a.limit||10}:void 0;p=a.params(l,w)}else p={...a.params,query:l};else p=a.urlBuilder?{}:{query:l};if(q.value){const w=a.limit||10;if(!("page"in p)&&!("per_page"in p)){const v=a.pageParam||"page",u=a.limitParam||"per_page";p[v]=$.value,p[u]=w}}return o||(I.value=!0),new Promise(w=>{let v;if(i==="GET"){const u=new URLSearchParams(p).toString(),m=u?`${c}?${u}`:c;console.log("Making request to:",m),v=fetch(m,{method:i,headers:g})}else v=fetch(c,{method:i,headers:g,body:JSON.stringify(p)});v.then(u=>u.json()).then(u=>{let m=[],x=!1;if(a.processResults){const B=a.processResults(u);m=B.results,x=B.more}else Array.isArray(u)?(m=u,x=!1):u.results&&Array.isArray(u.results)?(m=u.results,x=!!u.more):(m=[],x=!1);if(console.log(`Fetched ${m.length} results, more: ${x}`),o)h.value=[...h.value,...m],e.nextTick(()=>{if(y){const B=Math.min(D,j.value.length-1);d.value=B,L(),V.value&&V.value.focus(),setTimeout(()=>{T=!1},100)}});else{const B=t.multiple&&Array.isArray(t.modelValue)?t.modelValue:t.modelValue?[t.modelValue]:[],U=n.filter(G=>{const ue=r(G);return B.includes(ue)&&!m.some(Ke=>r(Ke)===ue)});h.value=[...U,...m]}F.value=x,a.cache&&(W.value[s]={results:m,more:x}),w()}).catch(u=>{console.error("Error fetching options:",u),o||(h.value=n),F.value=!1,w()}).finally(()=>{I.value=!1,b.value=!1,o&&y&&e.nextTick(()=>{setTimeout(()=>{T=!1},100)})})})},Ne=l=>{y=!1,T=!1,l.stopPropagation()},Pe=()=>{y=!1,T=!1},Ce=l=>{var a;E.value;const o=l.target.value;if(E.value=o,y=!1,R.value){if(Y(),O.value!==null&&(window.clearTimeout(O.value),O.value=null),!X.value){h.value=[];return}const s=((a=t.ajax)==null?void 0:a.delay)||300;O.value=window.setTimeout(()=>{const n=document.activeElement===f.value;n&&(y=!1,T=!1),ne(E.value).then(()=>{e.nextTick(()=>{j.value.length>0&&(d.value=0,L());const i=document.activeElement===f.value;(n||i)&&f.value?f.value.focus():y&&j.value.length>0&&V.value&&V.value.focus()})})},s)}},L=()=>{e.nextTick(()=>{if(d.value<0||!Z.value||!V.value)return;const l=V.value.querySelector(".loop-select-option-highlighted");if(l){const o=V.value,a=o.clientHeight,s=l,n=s.offsetTop,i=s.clientHeight,c=o.scrollTop,g=n<c,p=n+i>c+a;g?o.scrollTop=n:p&&(o.scrollTop=n+i-a)}})};e.onMounted(()=>{document.addEventListener("click",se),R.value&&t.modelValue&&_.value.length===0&&(t.multiple?Array.isArray(t.modelValue)&&t.modelValue.length>0:t.modelValue!==null&&t.modelValue!==void 0)&&(console.log("Initial value present, fetching option data"),Ie())}),e.onBeforeUnmount(()=>{document.removeEventListener("click",se),O.value!==null&&(window.clearTimeout(O.value),O.value=null)}),e.watch(()=>t.loading,l=>{I.value=l}),e.watch(j,(l,o)=>{if(!b.value){l.length>0?(d.value=0,y&&e.nextTick(()=>{V.value&&V.value.focus()})):d.value=-1;return}e.nextTick(()=>{if(y&&D>=0&&l.length>o.length){const a=Math.min(D,l.length-1);d.value=a,L()}})}),e.watch(E,l=>{f.value&&f.value.value!==l&&(f.value.value=l)}),e.watch(d,()=>{d.value>=0&&L()}),e.watch(()=>t.modelValue,l=>{R.value&&l&&(t.multiple&&Array.isArray(l)?l:[l]).forEach(a=>{if(!_.value.find(n=>r(n)===a)&&N.value){const n=N.value.find(i=>r(i)===a);n&&(h.value.find(i=>r(i)===a)||h.value.push(n))}})},{immediate:!0});const se=l=>{Q.value&&!Q.value.contains(l.target)&&P.value&&H()},Le=()=>{if(!q.value||!F.value||b.value)return;const l=V.value;if(!l)return;const o=l.scrollTop+l.clientHeight,a=20;o>=l.scrollHeight-a&&(console.log("Reached bottom of options list, loading more results..."),oe())},ie=()=>{j.value.length!==0&&(y=!0,d.value<j.value.length-1?(d.value++,L(),e.nextTick(()=>{V.value&&V.value.focus()})):F.value&&!b.value&&(y=!0,T=!0,D=d.value,oe()))},re=()=>{j.value.length!==0&&(y=!0,d.value>0&&(d.value--,L(),e.nextTick(()=>{V.value&&V.value.focus()})))},ce=()=>{d.value>=0&&j.value[d.value]&&(te(j.value[d.value]),t.multiple&&e.nextTick(()=>{P.value&&f.value&&f.value.focus()}))};e.watch(P,l=>{l&&e.nextTick(()=>{f.value&&!T&&f.value.focus()})}),e.watch(()=>b.value,(l,o)=>{o===!0&&l===!1&&setTimeout(()=>{T&&!y&&(T=!1)},200)});const Ie=async()=>{var a,s;if(!R.value)return;const l=t.multiple&&Array.isArray(t.modelValue)?t.modelValue:[t.modelValue];if(l.length===0)return;const o=l.filter(n=>!(n==null||S.value[String(n)]||_.value.some(i=>r(i)===n)));if(o.length!==0){I.value=!0;try{let n=[];if((a=t.ajax)!=null&&a.initialValueResolver){console.log("Using custom initialValueResolver to fetch option details");const i=o.map(async g=>{const p=await t.ajax.initialValueResolver(g);return p||null});n=(await Promise.all(i)).filter(g=>g!==null)}else if((s=t.ajax)!=null&&s.initialValueUrl){console.log("Using initialValueUrl to fetch option details");const i=t.ajax.initialValueUrl,c=t.ajax.method||"GET";let g={};t.ajax.initialValueParams?typeof t.ajax.initialValueParams=="function"?g=t.ajax.initialValueParams(o):g=t.ajax.initialValueParams:g={ids:o.join(",")};const p=t.ajax.headers||{"Content-Type":"application/json",Accept:"application/json"};let w;if(c==="GET"){const u=new URLSearchParams(g).toString(),m=u?`${i}?${u}`:i;console.log("Fetching initial values from:",m),w=await fetch(m,{method:c,headers:p})}else w=await fetch(i,{method:c,headers:p,body:JSON.stringify(g)});const v=await w.json();t.ajax.processResults?n=t.ajax.processResults(v).results:n=Array.isArray(v)?v:v.results||[]}else{console.log("Using regular ajax URL with id parameter to fetch option details");const i=t.multiple?o:[o[0]];for(const c of i){const g=t.ajax.url,p=t.ajax.method||"GET";let v={[t.ajax.idParam||"id"]:c};t.ajax.params&&(typeof t.ajax.params=="function"?v={...v,...t.ajax.params("")}:v={...v,...t.ajax.params});const u=t.ajax.headers||{"Content-Type":"application/json",Accept:"application/json"};let m;if(p==="GET"){const U=new URLSearchParams(v).toString(),G=U?`${g}?${U}`:g;console.log("Fetching initial value from:",G),m=await fetch(G,{method:p,headers:u})}else m=await fetch(g,{method:p,headers:u,body:JSON.stringify(v)});const x=await m.json();let B=[];t.ajax.processResults?B=t.ajax.processResults(x).results:B=Array.isArray(x)?x:x.results||[],n=[...n,...B]}}console.log("Resolved initial options:",n),n.forEach(i=>{const c=r(i);c!=null&&(S.value[String(c)]=i,h.value.some(g=>r(g)===c)||h.value.push(i))})}catch(n){console.error("Error fetching initial value details:",n)}finally{I.value=!1}}};return(l,o)=>(e.openBlock(),e.createElementBlock("div",{class:e.normalizeClass(["loop-select-container",{"loop-select-open":P.value,"loop-select-disabled":k.disabled}]),onClick:e.withModifiers(Re,["stop"]),ref_key:"containerRef",ref:Q},[e.createElementVNode("div",de,[e.createElementVNode("div",fe,[k.multiple?(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[N.value.length?(e.openBlock(),e.createElementBlock("div",he,[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(N.value,a=>(e.openBlock(),e.createElementBlock("div",{key:r(a),class:"loop-select-selected-item"},[e.renderSlot(l.$slots,"selected-option",{option:a,remove:()=>ae(a)},()=>[e.createElementVNode("span",null,e.toDisplayString(M(a)),1),e.createElementVNode("button",{class:"loop-select-remove-item",onClick:e.withModifiers(s=>ae(a),["stop"]),type:"button"}," × ",8,ge)])]))),128))])):(e.openBlock(),e.createElementBlock("span",ve,e.toDisplayString(k.placeholder),1))],64)):(e.openBlock(),e.createElementBlock(e.Fragment,{key:0},[K.value?e.renderSlot(l.$slots,"selected-option",{key:0,option:K.value,remove:()=>{}},()=>[e.createElementVNode("span",pe,e.toDisplayString(M(K.value)),1)]):(e.openBlock(),e.createElementBlock("span",me,e.toDisplayString(k.placeholder),1))],64))]),o[1]||(o[1]=e.createElementVNode("div",{class:"loop-select-arrow"},[e.createElementVNode("span",null,"▼")],-1))]),P.value?(e.openBlock(),e.createElementBlock("div",{key:0,class:"loop-select-dropdown",ref_key:"dropdownRef",ref:Z},[e.createElementVNode("div",ye,[e.createElementVNode("input",{ref_key:"searchInputRef",ref:f,class:"loop-select-search",type:"text",onInput:Ce,onKeydown:[o[0]||(o[0]=e.withModifiers(()=>{},["stop"])),e.withKeys(e.withModifiers(ie,["prevent"]),["down"]),e.withKeys(e.withModifiers(re,["prevent"]),["up"]),e.withKeys(e.withModifiers(ce,["prevent"]),["enter"]),e.withKeys(e.withModifiers(H,["prevent"]),["esc"])],onClick:e.withModifiers(Ne,["stop"]),onFocus:Pe,placeholder:"Search..."},null,40,ke),k.loading||I.value?(e.openBlock(),e.createElementBlock("div",Ve,o[2]||(o[2]=[e.createElementVNode("div",{class:"lds-dual-ring"},null,-1)]))):e.createCommentVNode("",!0)]),e.createElementVNode("ul",{class:"loop-select-options",onScroll:Le,ref_key:"optionsListRef",ref:V,tabindex:e.unref(y)?0:-1,onKeydown:[e.withKeys(e.withModifiers(ie,["prevent"]),["down"]),e.withKeys(e.withModifiers(re,["prevent"]),["up"]),e.withKeys(e.withModifiers(ce,["prevent"]),["enter"]),e.withKeys(e.withModifiers(H,["prevent"]),["esc"])]},[j.value.length===0&&!k.loading&&!I.value?(e.openBlock(),e.createElementBlock("li",Se,"No results found")):(e.openBlock(),e.createElementBlock(e.Fragment,{key:1},[(e.openBlock(!0),e.createElementBlock(e.Fragment,null,e.renderList(j.value,(a,s)=>(e.openBlock(),e.createElementBlock("li",{key:r(a),class:e.normalizeClass(["loop-select-option",{"loop-select-option-selected":le(a),"loop-select-option-highlighted":s===d.value}]),onClick:e.withModifiers(n=>te(a),["stop"]),onMouseover:()=>{d.value=s,L(),e.isRef(y)?y.value=!1:y=!1}},[e.renderSlot(l.$slots,"option",{option:a,selected:le(a),highlighted:s===d.value,index:s},()=>[e.createTextVNode(e.toDisplayString(M(a)),1)])],42,xe))),128)),b.value?(e.openBlock(),e.createElementBlock("li",Be,[e.renderSlot(l.$slots,"loading-more",{},()=>[o[3]||(o[3]=e.createElementVNode("div",{class:"lds-dual-ring"},null,-1))])])):e.createCommentVNode("",!0)],64))],40,we)],512)):e.createCommentVNode("",!0),e.createElementVNode("select",{multiple:k.multiple,name:k.name,required:k.required,disabled:k.disabled,tabindex:"-1",class:"loop-select-hidden","aria-hidden":"true"},[!k.multiple&&!ee.value?(e.openBlock(),e.createElementBlock("option",Ee,e.toDisplayString(k.placeholder),1)):e.createCommentVNode("",!0),k.multiple?(e.openBlock(!0),e.createElementBlock(e.Fragment,{key:1},e.renderList(N.value,a=>(e.openBlock(),e.createElementBlock("option",{key:r(a),value:r(a),selected:""},e.toDisplayString(M(a)),9,Te))),128)):K.value?(e.openBlock(),e.createElementBlock("option",{key:2,value:ee.value,selected:""},e.toDisplayString(M(K.value)),9,Ae)):e.createCommentVNode("",!0)],8,je)],2))}});let z=null;typeof window<"u"&&(z=window.Vue),z&&z.component("Loop8Select",J);const Oe={install:k=>{k.component("Loop8Select",J)}};C.Loop8Select=J,C.default=Oe,Object.defineProperties(C,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
package/dist/style.css ADDED
@@ -0,0 +1 @@
1
+ .loop-select-container{position:relative;width:100%;border:1px solid #ccc;border-radius:4px;box-sizing:border-box;cursor:pointer}.loop-select-disabled{opacity:.6;cursor:not-allowed}.loop-select-selection{min-height:36px;padding:4px 8px;display:flex;align-items:center;flex-wrap:nowrap}.loop-select-single-selection{flex:1;display:flex;align-items:center;overflow:hidden;min-width:0}.loop-select-tags-container{display:flex;flex-wrap:wrap;gap:4px;max-width:100%;overflow:hidden;align-items:center}.loop-select-selected-item{display:inline-flex;align-items:center;background-color:#e4e4e4;border-radius:3px;padding:2px 6px;margin-right:4px;margin-bottom:2px;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loop-select-remove-item{background:none;border:none;color:#666;cursor:pointer;margin-left:4px;padding:0;line-height:1;font-size:16px;flex-shrink:0}.loop-select-remove-item:hover{color:#333}.loop-select-search-container{padding:6px 8px;border-bottom:1px solid #eee;position:relative;display:flex;align-items:center}.loop-select-search{border:1px solid #ccc;border-radius:3px;outline:none;background:transparent;width:100%;padding:6px 8px;margin:0;font-size:14px;box-sizing:border-box}.loop-select-search-spinner{position:absolute;right:14px;top:50%;transform:translateY(-50%);pointer-events:none;display:flex;align-items:center;justify-content:center;height:20px;line-height:0}.loop-select-search-spinner .lds-dual-ring{width:18px;height:18px;line-height:0;vertical-align:middle}.loop-select-search-spinner .lds-dual-ring:after{width:14px;height:14px;margin:2px;border-width:1.5px;vertical-align:middle}.loop-select-placeholder{color:#999;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loop-select-selected-text{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.loop-select-arrow{display:flex;align-items:center;margin-left:8px;flex-shrink:0}.loop-select-dropdown{position:absolute;width:100%;max-height:250px;background:white;border:1px solid #ccc;border-top:none;border-radius:0 0 4px 4px;z-index:1000;box-shadow:0 2px 4px #0000001a;box-sizing:border-box;display:flex;flex-direction:column}.loop-select-options{list-style:none;margin:0;padding:0;overflow-y:auto;max-height:200px;flex:1;outline:none}.loop-select-options:focus{box-shadow:inset 0 0 2px #0003}.loop-select-option{padding:8px 12px;cursor:pointer}.loop-select-option:hover{background-color:#f5f5f5}.loop-select-option-selected{background-color:#e6f7ff}.loop-select-option-highlighted{background-color:#f0f0f0}.loop-select-loading,.loop-select-no-results{padding:8px 12px;text-align:center;color:#999}.loop-select-loading-more{padding:8px 12px;text-align:center;color:#999;font-style:italic;font-size:.9em;background-color:#f9f9f9;display:flex;justify-content:center;align-items:center;line-height:0}.loop-select-loading-more .lds-dual-ring{width:24px;height:24px;vertical-align:middle;line-height:0}.loop-select-loading-more .lds-dual-ring:after{width:18px;height:18px;margin:3px;border-width:2px;vertical-align:middle}.loop-select-hidden{position:absolute;width:0;height:0;overflow:hidden;clip:rect(0 0 0 0);margin:-1px;padding:0;border:0}.lds-dual-ring{display:inline-block;width:24px;height:24px}.lds-dual-ring:after{content:" ";display:block;width:18px;height:18px;margin:3px;border-radius:50%;border:2px solid #666;border-color:#666 transparent #666 transparent;animation:lds-dual-ring 1.2s linear infinite}@keyframes lds-dual-ring{0%{transform:rotate(0)}to{transform:rotate(360deg)}}