admins-components 9.0.76 → 9.0.78
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.
- package/dist/admins-components100.js.map +1 -1
- package/dist/admins-components102.js.map +1 -1
- package/dist/admins-components103.js.map +1 -1
- package/dist/admins-components105.js.map +1 -1
- package/dist/admins-components109.js.map +1 -1
- package/dist/admins-components11.js.map +1 -1
- package/dist/admins-components112.js.map +1 -1
- package/dist/admins-components12.js +44 -29
- package/dist/admins-components12.js.map +1 -1
- package/dist/admins-components13.js.map +1 -1
- package/dist/admins-components14.js.map +1 -1
- package/dist/admins-components169.js.map +1 -1
- package/dist/admins-components173.js +2 -2
- package/dist/admins-components173.js.map +1 -1
- package/dist/admins-components174.js.map +1 -1
- package/dist/admins-components179.js.map +1 -1
- package/dist/admins-components21.js.map +1 -1
- package/dist/admins-components22.js.map +1 -1
- package/dist/admins-components26.js +88 -82
- package/dist/admins-components26.js.map +1 -1
- package/dist/admins-components28.js.map +1 -1
- package/dist/admins-components31.js.map +1 -1
- package/dist/admins-components35.js +25 -23
- package/dist/admins-components35.js.map +1 -1
- package/dist/admins-components37.js.map +1 -1
- package/dist/admins-components46.js.map +1 -1
- package/dist/admins-components48.js.map +1 -1
- package/dist/admins-components54.js.map +1 -1
- package/dist/admins-components56.js.map +1 -1
- package/dist/admins-components65.js.map +1 -1
- package/dist/admins-components68.js.map +1 -1
- package/dist/admins-components70.js.map +1 -1
- package/dist/admins-components75.js.map +1 -1
- package/dist/admins-components77.js.map +1 -1
- package/dist/admins-components79.js.map +1 -1
- package/dist/admins-components8.js.map +1 -1
- package/dist/admins-components80.js.map +1 -1
- package/dist/admins-components82.js.map +1 -1
- package/dist/admins-components83.js.map +1 -1
- package/dist/admins-components85.js.map +1 -1
- package/dist/admins-components86.js.map +1 -1
- package/dist/admins-components87.js.map +1 -1
- package/dist/admins-components91.js.map +1 -1
- package/dist/admins-components93.js.map +1 -1
- package/dist/main.css +1 -1
- package/dist/main.css.map +1 -1
- package/dist/src/components/HeaderComponent.vue.d.ts +3 -0
- package/dist/src/composables/useDropdownAnchor.d.ts +2 -0
- package/dist/src/composables/useSwipeToClose.d.ts +0 -31
- package/dist/src/utils/dataFilters.d.ts +0 -8
- package/dist/src/utils/dataListConverters.d.ts +0 -10
- package/dist/src/utils/url.d.ts +0 -11
- package/dist/styles/components/dropdown-select.scss_vue_type_style_index_0_src_true_lang.css +1 -1
- package/dist/styles/components/header.scss_vue_type_style_index_0_src_true_lang.css +1 -1
- package/dist/vueformelements/ArticlePickerElement.vue_vue_type_style_index_0_scoped_54217a66_lang.css +1 -0
- package/package.json +1 -1
- package/dist/vueformelements/ArticlePickerElement.vue_vue_type_style_index_0_scoped_43c54caa_lang.css +0 -1
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
import e from "./admins-components6.js";
|
|
2
2
|
import { useDropdownAnchor as t } from "./admins-components12.js";
|
|
3
3
|
import n from "./admins-components25.js";
|
|
4
|
-
import { Fragment as r, Teleport as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createVNode as
|
|
4
|
+
import { Fragment as r, Teleport as i, computed as a, createBlock as o, createCommentVNode as s, createElementBlock as c, createElementVNode as l, createVNode as u, defineComponent as d, nextTick as f, normalizeClass as p, normalizeStyle as ee, openBlock as m, ref as h, renderList as te, toDisplayString as g, unref as _, watch as v, withModifiers as y } from "vue";
|
|
5
5
|
//#region src/components/DropdownSelect.vue?vue&type=script&setup=true&lang.ts
|
|
6
|
-
var
|
|
6
|
+
var b = { class: "ac-component" }, x = ["aria-disabled"], ne = {
|
|
7
7
|
key: 0,
|
|
8
8
|
class: "c-truncate ds-value"
|
|
9
|
-
},
|
|
9
|
+
}, re = {
|
|
10
10
|
key: 1,
|
|
11
11
|
class: "c-placeholder"
|
|
12
|
-
},
|
|
12
|
+
}, ie = { class: "ac-component" }, ae = {
|
|
13
13
|
key: 0,
|
|
14
14
|
class: "ds-filter"
|
|
15
|
-
},
|
|
15
|
+
}, S = ["title"], C = ["value", "placeholder"], w = { class: "ds-options c-scroll" }, oe = {
|
|
16
16
|
key: 0,
|
|
17
17
|
class: "ds-option ds-option--loading"
|
|
18
|
-
},
|
|
18
|
+
}, se = ["onClick", "onKeydown"], T = ["innerHTML"], E = {
|
|
19
19
|
key: 0,
|
|
20
20
|
class: "ds-option ds-option--empty"
|
|
21
|
-
},
|
|
21
|
+
}, D = {
|
|
22
22
|
key: 1,
|
|
23
23
|
class: "c-footer"
|
|
24
|
-
},
|
|
24
|
+
}, O = {
|
|
25
25
|
placeholder: "Válassz...",
|
|
26
26
|
filterable: !0,
|
|
27
27
|
filterPlaceholder: "Kezdj el gépelni...",
|
|
@@ -33,48 +33,51 @@ var ne = { class: "ac-component" }, b = ["aria-disabled"], x = {
|
|
|
33
33
|
size: "normal",
|
|
34
34
|
highlight: !0,
|
|
35
35
|
disabled: !1
|
|
36
|
-
},
|
|
36
|
+
}, k = /*@__PURE__*/ d({
|
|
37
37
|
__name: "DropdownSelect",
|
|
38
38
|
props: {
|
|
39
39
|
modelValue: { default: null },
|
|
40
40
|
options: {},
|
|
41
|
-
config: { default: () => ({ ...
|
|
41
|
+
config: { default: () => ({ ...O }) }
|
|
42
42
|
},
|
|
43
43
|
emits: ["update:modelValue", "filter-input"],
|
|
44
|
-
setup(
|
|
45
|
-
let j =
|
|
46
|
-
...
|
|
44
|
+
setup(d, { expose: k, emit: A }) {
|
|
45
|
+
let j = d, M = a(() => ({
|
|
46
|
+
...O,
|
|
47
47
|
...j.config
|
|
48
|
-
})), N =
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
})), N = A, P = h(""), F = h(null), I = h(null), L = h(null), R = h([]), z = h(U(j.modelValue, j.options)), { isOpen: B, dropdownStyle: V, placement: H } = t(F, I, {
|
|
49
|
+
extraStyle: (e) => ({
|
|
50
|
+
minWidth: `${e.width}px`,
|
|
51
|
+
maxWidth: `${e.width}px`
|
|
52
|
+
}),
|
|
53
|
+
maxHeight: "17rem"
|
|
54
|
+
});
|
|
55
|
+
function U(e, t) {
|
|
53
56
|
return e == null ? [] : (Array.isArray(e) ? e : [e]).map((e) => e == null ? null : typeof e == "object" && "label" in e ? e : typeof e == "string" ? t.find((t) => t.value === e) ?? {
|
|
54
57
|
value: e,
|
|
55
58
|
label: e
|
|
56
59
|
} : null).filter((e) => e !== null);
|
|
57
60
|
}
|
|
58
61
|
v(() => [j.modelValue, j.options], ([e]) => {
|
|
59
|
-
z.value =
|
|
62
|
+
z.value = U(e, j.options);
|
|
60
63
|
}), v(B, (e) => {
|
|
61
|
-
e && (P.value = "", M.value.filterable &&
|
|
64
|
+
e && (P.value = "", M.value.filterable && f(() => L.value?.focus()), M.value.lazy && (R.value = [...z.value]));
|
|
62
65
|
});
|
|
63
|
-
function
|
|
66
|
+
function W(e) {
|
|
64
67
|
P.value = e, N("filter-input", e);
|
|
65
68
|
}
|
|
66
|
-
let
|
|
69
|
+
let G = a(() => {
|
|
67
70
|
if (z.value.length === 0) return null;
|
|
68
71
|
if (!M.value.multiple) {
|
|
69
72
|
let e = z.value[0];
|
|
70
73
|
return j.options.find((t) => t.value === e?.value)?.label ?? e?.label ?? null;
|
|
71
74
|
}
|
|
72
75
|
return z.value.length > 2 ? `${z.value.length} kiválasztva` : z.value.map((e) => j.options.find((t) => t.value === e.value)?.label ?? e.label ?? e.value).join(", ");
|
|
73
|
-
}),
|
|
76
|
+
}), K = a(() => {
|
|
74
77
|
let e = P.value.toLowerCase();
|
|
75
78
|
return e ? j.options.filter((t) => t.label.toLowerCase().includes(e)) : j.options;
|
|
76
79
|
});
|
|
77
|
-
function
|
|
80
|
+
function q(e) {
|
|
78
81
|
return e.replace(/[&<>"']/g, (e) => ({
|
|
79
82
|
"&": "&",
|
|
80
83
|
"<": "<",
|
|
@@ -85,21 +88,21 @@ var ne = { class: "ac-component" }, b = ["aria-disabled"], x = {
|
|
|
85
88
|
}
|
|
86
89
|
function ce(e) {
|
|
87
90
|
let t = P.value.trim();
|
|
88
|
-
if (!t || !M.value.highlight) return
|
|
89
|
-
let n =
|
|
91
|
+
if (!t || !M.value.highlight) return q(e);
|
|
92
|
+
let n = q(e), r = q(t), i = new RegExp(r.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"), "ig");
|
|
90
93
|
return n.replace(i, (e) => `<mark class="ds-option__highlight">${e}</mark>`);
|
|
91
94
|
}
|
|
92
|
-
let
|
|
93
|
-
if (
|
|
95
|
+
let J = a(() => K.value.filter((e) => e.value)), Y = a(() => {
|
|
96
|
+
if (J.value.length === 0) return !1;
|
|
94
97
|
let e = M.value.lazy && B.value ? R.value : z.value;
|
|
95
|
-
return
|
|
98
|
+
return J.value.every((t) => t.value && e.some((e) => e.value === t.value));
|
|
96
99
|
});
|
|
97
|
-
function
|
|
100
|
+
function X(e) {
|
|
98
101
|
return (M.value.lazy && B.value ? R : z).value.some((t) => t.value === e);
|
|
99
102
|
}
|
|
100
103
|
function le() {
|
|
101
|
-
let e = M.value.lazy && B.value ? R : z, t =
|
|
102
|
-
if (
|
|
104
|
+
let e = M.value.lazy && B.value ? R : z, t = J.value.filter((e) => e.value);
|
|
105
|
+
if (Y.value) {
|
|
103
106
|
let n = new Set(t.map((e) => e.value));
|
|
104
107
|
e.value = e.value.filter((e) => !n.has(e.value ?? ""));
|
|
105
108
|
} else {
|
|
@@ -108,74 +111,78 @@ var ne = { class: "ac-component" }, b = ["aria-disabled"], x = {
|
|
|
108
111
|
}
|
|
109
112
|
M.value.lazy || N("update:modelValue", z.value.length > 0 ? [...z.value] : null);
|
|
110
113
|
}
|
|
111
|
-
function
|
|
114
|
+
function Z(e, t) {
|
|
112
115
|
let n = e.findIndex((e) => e.value === t.value);
|
|
113
116
|
return n >= 0 ? e.filter((e, t) => t !== n) : [...e, t];
|
|
114
117
|
}
|
|
115
|
-
function
|
|
118
|
+
function Q(e) {
|
|
116
119
|
if (e.callback) {
|
|
117
120
|
e.callback(), B.value = !1;
|
|
118
121
|
return;
|
|
119
122
|
}
|
|
120
|
-
e.value && (M.value.multiple ? M.value.lazy ? R.value =
|
|
123
|
+
e.value && (M.value.multiple ? M.value.lazy ? R.value = Z(R.value, e) : (z.value = Z(z.value, e), N("update:modelValue", z.value.length > 0 ? [...z.value] : null)) : (z.value = [e], N("update:modelValue", e), B.value = !1));
|
|
121
124
|
}
|
|
122
|
-
function
|
|
125
|
+
function $() {
|
|
123
126
|
M.value.lazy && (z.value = [...R.value], N("update:modelValue", R.value.length > 0 ? [...R.value] : null)), B.value = !1;
|
|
124
127
|
}
|
|
125
|
-
function
|
|
128
|
+
function ue() {
|
|
126
129
|
M.value.lazy ? R.value = [] : (z.value = [], N("update:modelValue", null));
|
|
127
130
|
}
|
|
128
|
-
function
|
|
129
|
-
e.key === " " ? (e.preventDefault(),
|
|
130
|
-
}
|
|
131
|
-
function de() {
|
|
132
|
-
M.value.disabled || (B.value = !B.value, B.value && M.value.filterable && (P.value = "", N("filter-input", "")));
|
|
131
|
+
function de(e, t) {
|
|
132
|
+
e.key === " " ? (e.preventDefault(), Q(t)) : e.key === "Enter" && (e.preventDefault(), $());
|
|
133
133
|
}
|
|
134
134
|
function fe() {
|
|
135
|
-
M.value.disabled || (
|
|
135
|
+
M.value.disabled || (B.value = !B.value, B.value && M.value.filterable && (P.value = "", N("filter-input", "")));
|
|
136
136
|
}
|
|
137
137
|
function pe() {
|
|
138
|
-
M.value.disabled || (
|
|
138
|
+
M.value.disabled || (z.value = [], N("update:modelValue", null), B.value = !1);
|
|
139
139
|
}
|
|
140
140
|
function me() {
|
|
141
|
+
M.value.disabled || (B.value = !0, M.value.filterable && f(() => L.value?.focus()));
|
|
142
|
+
}
|
|
143
|
+
function he() {
|
|
141
144
|
P.value = "", N("filter-input", "");
|
|
142
145
|
}
|
|
143
|
-
return
|
|
146
|
+
return k({ focusAndOpen: me }), (t, a) => (m(), c("div", b, [l("div", {
|
|
144
147
|
ref_key: "wrapperRef",
|
|
145
148
|
ref: F,
|
|
146
149
|
class: "c-wrapper ds-wrapper"
|
|
147
150
|
}, [l("div", {
|
|
148
|
-
class:
|
|
151
|
+
class: p(["c-input-row pointer", {
|
|
149
152
|
"c-input-row--sm": M.value.size === "small",
|
|
150
153
|
"c-input-row--lg": M.value.size === "large",
|
|
151
|
-
"c-input-row--disabled": M.value.disabled
|
|
154
|
+
"c-input-row--disabled": M.value.disabled,
|
|
155
|
+
"c-input-row--open": _(B)
|
|
152
156
|
}]),
|
|
153
157
|
"aria-disabled": M.value.disabled || void 0,
|
|
154
|
-
onClick: a[1] ||= (e) =>
|
|
158
|
+
onClick: a[1] ||= (e) => fe()
|
|
155
159
|
}, [
|
|
156
|
-
|
|
157
|
-
M.value.clearable && z.value.length > 0 ? (
|
|
160
|
+
G.value ? (m(), c("span", ne, g(G.value), 1)) : (m(), c("span", re, g(M.value.placeholder), 1)),
|
|
161
|
+
M.value.clearable && z.value.length > 0 ? (m(), c("button", {
|
|
158
162
|
key: 2,
|
|
159
163
|
type: "button",
|
|
160
164
|
class: "c-icon-btn c-icon-btn--clear ds-clear-btn",
|
|
161
|
-
onClick: a[0] ||= y((e) =>
|
|
165
|
+
onClick: a[0] ||= y((e) => pe(), ["stop"]),
|
|
162
166
|
"aria-label": "Törlés"
|
|
163
167
|
}, [...a[6] ||= [l("i", { class: "fa-solid fa-fw fa-xmark" }, null, -1)]])) : s("", !0),
|
|
164
|
-
l("span", { class:
|
|
165
|
-
], 10,
|
|
168
|
+
l("span", { class: p(["c-icon-btn c-icon-btn--chevron mr-2", { "c-icon-btn--chevron-open": _(B) }]) }, [...a[7] ||= [l("i", { class: "fa-solid fa-fw fa-chevron-down" }, null, -1)]], 2)
|
|
169
|
+
], 10, x)], 512), (m(), o(i, { to: "body" }, [l("div", ie, [_(B) ? (m(), c("div", {
|
|
166
170
|
key: 0,
|
|
167
171
|
ref_key: "dropdownRef",
|
|
168
172
|
ref: I,
|
|
169
|
-
class:
|
|
170
|
-
|
|
173
|
+
class: p(["c-dropdown ds-dropdown ds-wrapper", {
|
|
174
|
+
"ds-dropdown--multiple": M.value.multiple,
|
|
175
|
+
"ds-dropdown--up": _(H) === "up"
|
|
176
|
+
}]),
|
|
177
|
+
style: ee(_(V))
|
|
171
178
|
}, [
|
|
172
|
-
M.value.filterable ? (
|
|
173
|
-
M.value.multiple ? (
|
|
179
|
+
M.value.filterable ? (m(), c("div", ae, [
|
|
180
|
+
M.value.multiple ? (m(), c("span", {
|
|
174
181
|
key: 0,
|
|
175
|
-
class:
|
|
182
|
+
class: p(["c-checkbox ds-select-all-checkbox", { "c-checkbox--checked": Y.value }]),
|
|
176
183
|
onClick: a[2] ||= y((e) => le(), ["stop"]),
|
|
177
|
-
title:
|
|
178
|
-
}, null, 10,
|
|
184
|
+
title: Y.value ? "Összes kijelölés törlése" : "Összes kijelölése"
|
|
185
|
+
}, null, 10, S)) : s("", !0),
|
|
179
186
|
l("input", {
|
|
180
187
|
ref_key: "filterInputRef",
|
|
181
188
|
ref: L,
|
|
@@ -183,56 +190,55 @@ var ne = { class: "ac-component" }, b = ["aria-disabled"], x = {
|
|
|
183
190
|
id: "ds-filter-input",
|
|
184
191
|
class: "c-focus ds-filter-input",
|
|
185
192
|
value: P.value,
|
|
186
|
-
onInput: a[3] ||= (e) =>
|
|
193
|
+
onInput: a[3] ||= (e) => W(e.target.value),
|
|
187
194
|
autocomplete: "off",
|
|
188
195
|
placeholder: M.value.filterPlaceholder,
|
|
189
196
|
onClick: a[4] ||= y(() => {}, ["stop"])
|
|
190
197
|
}, null, 40, C),
|
|
191
|
-
P.value ? (
|
|
198
|
+
P.value ? (m(), c("button", {
|
|
192
199
|
key: 1,
|
|
193
200
|
type: "button",
|
|
194
201
|
class: "c-icon-btn c-icon-btn--clear ds-filter-clear",
|
|
195
|
-
onClick: a[5] ||= y((e) =>
|
|
202
|
+
onClick: a[5] ||= y((e) => he(), ["stop"]),
|
|
196
203
|
"aria-label": "Szűrők törlése"
|
|
197
204
|
}, [...a[8] ||= [l("i", { class: "fa-solid fa-xmark" }, null, -1)]])) : s("", !0)
|
|
198
205
|
])) : s("", !0),
|
|
199
|
-
l("ul", w, [M.value.loading ? (
|
|
206
|
+
l("ul", w, [M.value.loading ? (m(), c("li", oe, [u(n, {
|
|
200
207
|
size: "2rem",
|
|
201
208
|
color: "var(--neutral-300)",
|
|
202
209
|
class: "m-auto p-3"
|
|
203
|
-
})])) : (
|
|
210
|
+
})])) : (m(), c(r, { key: 1 }, [(m(!0), c(r, null, te(K.value, (e, t) => (m(), c("li", {
|
|
204
211
|
key: e.value ?? `cb-${t}`,
|
|
205
|
-
class:
|
|
212
|
+
class: p(["d-option ds-option", { "ds-option--selected": e.value && X(e.value) }]),
|
|
206
213
|
tabindex: "0",
|
|
207
|
-
onClick: (t) =>
|
|
208
|
-
onKeydown: (t) =>
|
|
214
|
+
onClick: (t) => Q(e),
|
|
215
|
+
onKeydown: (t) => de(t, e)
|
|
209
216
|
}, [
|
|
210
|
-
M.value.multiple && e.value ? (
|
|
217
|
+
M.value.multiple && e.value ? (m(), c("span", {
|
|
211
218
|
key: 0,
|
|
212
|
-
class:
|
|
219
|
+
class: p(["c-checkbox", { "c-checkbox--checked": X(e.value) }])
|
|
213
220
|
}, null, 2)) : s("", !0),
|
|
214
|
-
e.icon ? (
|
|
221
|
+
e.icon ? (m(), c("i", {
|
|
215
222
|
key: 1,
|
|
216
|
-
class:
|
|
223
|
+
class: p(["fa-fw", e.icon])
|
|
217
224
|
}, null, 2)) : s("", !0),
|
|
218
225
|
l("span", {
|
|
219
|
-
class:
|
|
226
|
+
class: p(["d-option__label", { "c-truncate": M.value.textEllipsis }]),
|
|
220
227
|
innerHTML: ce(e.label)
|
|
221
|
-
}, null, 10,
|
|
222
|
-
], 42,
|
|
223
|
-
M.value.multiple
|
|
228
|
+
}, null, 10, T)
|
|
229
|
+
], 42, se))), 128)), K.value.length === 0 ? (m(), c("li", E, " Nincs találat ")) : s("", !0)], 64))]),
|
|
230
|
+
M.value.multiple ? (m(), c("div", D, [M.value.clearable && z.value.length > 0 ? (m(), o(e, {
|
|
224
231
|
key: 0,
|
|
225
232
|
label: "Törlés",
|
|
226
233
|
outline: "",
|
|
227
|
-
onClick:
|
|
228
|
-
})) : s("", !0),
|
|
229
|
-
key: 1,
|
|
234
|
+
onClick: ue
|
|
235
|
+
})) : s("", !0), u(e, {
|
|
230
236
|
label: "OK",
|
|
231
237
|
type: "success",
|
|
232
|
-
onClick:
|
|
233
|
-
})
|
|
238
|
+
onClick: $
|
|
239
|
+
})])) : s("", !0)
|
|
234
240
|
], 6)) : s("", !0)])]))]));
|
|
235
241
|
}
|
|
236
242
|
});
|
|
237
243
|
//#endregion
|
|
238
|
-
export {
|
|
244
|
+
export { k as default, O as dropdownSelectConfigDefaults };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components26.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({\n minWidth: `${rect.width}px`,\n maxWidth: `${rect.width * 1.5}px`,\n }),\n})\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n //debouncedEmit(text)\n}\n\n/* const debouncedEmit = debounce((raw: string) => {\n emit('filter-input', raw)\n}) */\n\n// Display\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n // Prefer the label from the live options list, fall back to the stored label\n return props.options.find((o) => o.value === sel?.value)?.label ?? sel?.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value ?? ''))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\n// Actions\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n </div>\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div\n v-if=\"isOpen\"\n ref=\"dropdownRef\"\n class=\"c-dropdown ds-dropdown ds-wrapper\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple }\"\n :style=\"dropdownStyle\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n\n <div v-if=\"cfg.multiple || (cfg.clearable && selection.length > 0)\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable\" label=\"Törlés\" outline @click=\"clear\" />\n <Button v-if=\"cfg.multiple\" label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"admins-components26.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\nconst { isOpen, dropdownStyle, placement } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({\n minWidth: `${rect.width}px`,\n maxWidth: `${rect.width}px`,\n }),\n maxHeight: '17rem',\n})\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n}\n\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n\n return props.options.find((o) => o.value === sel?.value)?.label ?? sel?.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value ?? ''))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n 'c-input-row--open': isOpen,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n </div>\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div\n v-if=\"isOpen\"\n ref=\"dropdownRef\"\n class=\"c-dropdown ds-dropdown ds-wrapper\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple, 'ds-dropdown--up': placement === 'up' }\"\n :style=\"dropdownStyle\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n <div v-if=\"cfg.multiple\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable && selection.length > 0\" label=\"Törlés\" outline @click=\"clear\" />\n <Button label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;GAea,IAAqD;CAChE,aAAa;CACb,YAAY;CACZ,mBAAmB;CACnB,WAAW;CACX,cAAc;CACd,UAAU;CACV,MAAM;CACN,SAAS;CACT,MAAM;CACN,WAAW;CACX,UAAU;AACZ;;;;;;;;;EAuBA,IAAM,IAAQ,GAKR,IAAM,SAAgB;GAAE,GAAG;GAA8B,GAAG,EAAM;EAAO,EAAE,GAE3E,IAAO,GAKP,IAAa,EAAI,EAAE,GACnB,IAAa,EAAwB,IAAI,GACzC,IAAc,EAAwB,IAAI,GAC1C,IAAiB,EAA6B,IAAI,GAClD,IAAS,EAAsB,CAAC,CAAC,GACjC,IAAY,EAAsB,EAAmB,EAAM,YAAY,EAAM,OAAO,CAAC,GAErF,EAAE,WAAQ,kBAAe,iBAAc,EAAkB,GAAY,GAAa;GACtF,aAAa,OAAU;IACrB,UAAU,GAAG,EAAK,MAAM;IACxB,UAAU,GAAG,EAAK,MAAM;GAC1B;GACA,WAAW;EACb,CAAC;EAGD,SAAS,EACP,GACA,GACkB;GAGlB,OAFI,KAAO,OAAa,CAAC,KACb,MAAM,QAAQ,CAAG,IAAI,IAAM,CAAC,CAAG,EAAA,CAExC,KAAK,MACA,KAAS,OAAa,OACtB,OAAO,KAAU,YAAY,WAAW,IACnC,IAEL,OAAO,KAAU,WACL,EAAQ,MAAM,MAAM,EAAE,UAAU,CACvC,KAAS;IAAE,OAAO;IAAO,OAAO;GAAM,IAExC,IACR,CAAA,CACA,QAAQ,MAA2B,MAAM,IAAI;EAClD;EASA,AAPA,QACQ,CAAC,EAAM,YAAY,EAAM,OAAO,IACrC,CAAC,OAAO;GACP,EAAU,QAAQ,EAAmB,GAA8B,EAAM,OAAO;EAClF,CACF,GAEA,EAAM,IAAS,MAAS;GACtB,AAAI,MACF,EAAW,QAAQ,IACf,EAAI,MAAM,cAAY,QAAe,EAAe,OAAO,MAAM,CAAC,GAClE,EAAI,MAAM,SAAM,EAAO,QAAQ,CAAC,GAAG,EAAU,KAAK;EAE1D,CAAC;EAED,SAAS,EAAc,GAAc;GAEnC,AADA,EAAW,QAAQ,GACnB,EAAK,gBAAgB,CAAI;EAC3B;EAEA,IAAM,IAAgB,QAAe;GACnC,IAAI,EAAU,MAAM,WAAW,GAAG,OAAO;GACzC,IAAI,CAAC,EAAI,MAAM,UAAU;IACvB,IAAM,IAAM,EAAU,MAAM;IAE5B,OAAO,EAAM,QAAQ,MAAM,MAAM,EAAE,UAAU,GAAK,KAAK,CAAC,EAAE,SAAS,GAAK,SAAS;GACnF;GAEA,OADI,EAAU,MAAM,SAAS,IAAU,GAAG,EAAU,MAAM,OAAO,gBAC1D,EAAU,MACd,KAAK,MAAQ,EAAM,QAAQ,MAAM,MAAM,EAAE,UAAU,EAAI,KAAK,CAAC,EAAE,SAAS,EAAI,SAAS,EAAI,KAAK,CAAA,CAC9F,KAAK,IAAI;EACd,CAAC,GAEK,IAAkB,QAAe;GACrC,IAAM,IAAI,EAAW,MAAM,YAAY;GACvC,OAAO,IAAI,EAAM,QAAQ,QAAQ,MAAM,EAAE,MAAM,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,EAAM;EACpF,CAAC;EAED,SAAS,EAAW,GAAa;GAC/B,OAAO,EAAI,QACT,aACC,OAAO;IAAE,KAAK;IAAS,KAAK;IAAQ,KAAK;IAAQ,MAAK;IAAU,KAAK;GAAQ,EAAA,CAAG,EACnF;EACF;EAEA,SAAS,GAAU,GAAe;GAChC,IAAM,IAAI,EAAW,MAAM,KAAK;GAChC,IAAI,CAAC,KAAK,CAAC,EAAI,MAAM,WAAW,OAAO,EAAW,CAAK;GAEvD,IAAM,IAAY,EAAW,CAAK,GAC5B,IAAQ,EAAW,CAAC,GAEpB,IAAK,IAAI,OAAO,EAAM,QAAQ,uBAAuB,MAAM,GAAG,IAAI;GACxE,OAAO,EAAU,QAAQ,IAAK,MAAM,sCAAsC,EAAE,QAAQ;EACtF;EAEA,IAAM,IAAoB,QACjB,EAAgB,MAAM,QAAQ,MAAM,EAAE,KAAK,CACnD,GAEK,IAAqB,QAAe;GACxC,IAAI,EAAkB,MAAM,WAAW,GAAG,OAAO;GACjD,IAAM,IAAc,EAAI,MAAM,QAAQ,EAAO,QAAQ,EAAO,QAAQ,EAAU;GAC9E,OAAO,EAAkB,MAAM,OAAO,MAAM,EAAE,SAAS,EAAY,MAAM,MAAM,EAAE,UAAU,EAAE,KAAK,CAAC;EACrG,CAAC;EAED,SAAS,EAAW,GAAwB;GAE1C,QADa,EAAI,MAAM,QAAQ,EAAO,QAAQ,IAAS,EAAA,CAC3C,MAAM,MAAM,MAAM,EAAE,UAAU,CAAK;EACjD;EAEA,SAAS,KAAmB;GAC1B,IAAM,IAAc,EAAI,MAAM,QAAQ,EAAO,QAAQ,IAAS,GACxD,IAAiB,EAAkB,MAAM,QAAQ,MAAM,EAAE,KAAK;GAEpE,IAAI,EAAmB,OAAO;IAC5B,IAAM,IAAmB,IAAI,IAAI,EAAe,KAAK,MAAM,EAAE,KAAe,CAAC;IAC7E,EAAY,QAAQ,EAAY,MAAM,QAAQ,MAAM,CAAC,EAAiB,IAAI,EAAE,SAAS,EAAE,CAAC;GAC1F,OAAO;IACL,IAAM,IAAiB,IAAI,IAAI,EAAY,MAAM,KAAK,MAAM,EAAE,KAAK,CAAC,GAC9D,IAAQ,EAAe,QAAQ,MAAM,CAAC,EAAe,IAAI,EAAE,KAAe,CAAC;IACjF,EAAY,QAAQ,CAAC,GAAG,EAAY,OAAO,GAAG,CAAK;GACrD;GAEA,AAAK,EAAI,MAAM,QACb,EAAK,qBAAqB,EAAU,MAAM,SAAS,IAAI,CAAC,GAAG,EAAU,KAAK,IAAI,IAAI;EAEtF;EAEA,SAAS,EAAW,GAAwB,GAAuC;GACjF,IAAM,IAAM,EAAK,WAAW,MAAM,EAAE,UAAU,EAAI,KAAK;GACvD,OAAO,KAAO,IAAI,EAAK,QAAQ,GAAG,MAAM,MAAM,CAAG,IAAI,CAAC,GAAG,GAAM,CAAG;EACpE;EAEA,SAAS,EAAa,GAAqB;GACzC,IAAI,EAAI,UAAU;IAEhB,AADA,EAAI,SAAS,GACb,EAAO,QAAQ;IACf;GACF;GAEc,EAAI,UAGd,EAAI,MAAM,WACR,EAAI,MAAM,OACZ,EAAO,QAAQ,EAAW,EAAO,OAAO,CAAG,KAE3C,EAAU,QAAQ,EAAW,EAAU,OAAO,CAAG,GACjD,EAAK,qBAAqB,EAAU,MAAM,SAAS,IAAI,CAAC,GAAG,EAAU,KAAK,IAAI,IAAI,MAGpF,EAAU,QAAQ,CAAC,CAAG,GACtB,EAAK,qBAAqB,CAAG,GAC7B,EAAO,QAAQ;EAEnB;EAEA,SAAS,IAAU;GAKjB,AAJI,EAAI,MAAM,SACZ,EAAU,QAAQ,CAAC,GAAG,EAAO,KAAK,GAClC,EAAK,qBAAqB,EAAO,MAAM,SAAS,IAAI,CAAC,GAAG,EAAO,KAAK,IAAI,IAAI,IAE9E,EAAO,QAAQ;EACjB;EAEA,SAAS,KAAQ;GACf,AAAI,EAAI,MAAM,OACZ,EAAO,QAAQ,CAAC,KAEhB,EAAU,QAAQ,CAAC,GACnB,EAAK,qBAAqB,IAAI;EAElC;EAEA,SAAS,GAAgB,GAAkB,GAAqB;GAC9D,AAAI,EAAE,QAAQ,OACZ,EAAE,eAAe,GACjB,EAAa,CAAG,KACP,EAAE,QAAQ,YACnB,EAAE,eAAe,GACjB,EAAQ;EAEZ;EAEA,SAAS,KAAa;GAChB,EAAI,MAAM,aACd,EAAO,QAAQ,CAAC,EAAO,OACnB,EAAO,SACL,EAAI,MAAM,eACZ,EAAW,QAAQ,IACnB,EAAK,gBAAgB,EAAE;EAG7B;EAEA,SAAS,KAAa;GAChB,EAAI,MAAM,aACd,EAAU,QAAQ,CAAC,GACnB,EAAK,qBAAqB,IAAI,GAC9B,EAAO,QAAQ;EACjB;EAEA,SAAS,KAAe;GAClB,EAAI,MAAM,aACd,EAAO,QAAQ,IACX,EAAI,MAAM,cAAY,QAAe,EAAe,OAAO,MAAM,CAAC;EACxE;EAEA,SAAS,KAAoB;GAE3B,AADA,EAAW,QAAQ,IACnB,EAAK,gBAAgB,EAAE;EACzB;SAEA,EAAa,EAAE,iBAAa,CAAC,cAI3B,EAAA,GAAA,EA6GM,OA7GN,GA6GM,CA5GJ,EA8BM,OAAA;GA9BG,SAAA;GAAJ,KAAI;GAAa,OAAM;EAC1B,GAAA,CAAA,EA4BM,OAAA;GA3BJ,OAAK,EAAA,CAAC,uBAAqB;IACY,mBAAA,EAAA,MAAI,SAAI;IAA2C,mBAAA,EAAA,MAAI,SAAI;IAAiD,yBAAA,EAAA,MAAI;IAAyC,qBAAA,EAAA,CAAA;;GAM/L,iBAAe,EAAA,MAAI,YAAY,KAAA;GAC/B,SAAK,AAAA,EAAA,QAAA,MAAE,GAAU;;GAEN,EAAA,SAAZ,EAAA,GAAA,EAAiF,QAAjF,IAAiF,EAAvB,EAAA,KAAa,GAAA,CAAA,MACvE,EAAA,GAAA,EAA+D,QAA/D,IAA+D,EAAzB,EAAA,MAAI,WAAW,GAAA,CAAA;GAE7C,EAAA,MAAI,aAAa,EAAA,MAAU,SAAM,KADzC,EAAA,GAAA,EAQS,UAAA;;IANP,MAAK;IACL,OAAM;IACL,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,GAAU,GAAA,CAAA,MAAA,CAAA;IACvB,cAAW;GAEX,GAAA,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAuC,KAAA,EAApC,OAAM,0BAAyB,GAAA,MAAA,EAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;GAEpC,EAKO,QAAA,EAJL,OAAK,EAAA,CAAC,uCAAqC,EAAA,4BACL,EAAA,CAAA,EAAM,CAAA,CAAA,EAAA,GAAA,CAAA,GAAA,AAAA,EAAA,OAAA,CAE5C,EAA8C,KAAA,EAA3C,OAAM,iCAAgC,GAAA,MAAA,EAAA,CAAA,CAAA,GAAA,CAAA;EAI/C,GAAA,IAAA,CAAA,CAAA,GAAA,GAAA,IAAA,EAAA,GAAA,EA4EW,GAAA,EA5ED,IAAG,OAAM,GAAA,CACjB,EA0EM,OA1EN,IA0EM,CAxEI,EAAA,CAAA,KADR,EAAA,GAAA,EAwEM,OAAA;;GAtEA,SAAA;GAAJ,KAAI;GACJ,OAAK,EAAA,CAAC,qCAAmC;IAAA,yBACN,EAAA,MAAI;IAAQ,mBAAqB,EAAA,CAAA,MAAS;GAAA,CAAA,CAAA;GAC5E,OAAK,GAAE,EAAA,CAAA,CAAa;;GAEZ,EAAA,MAAI,cAAf,EAAA,GAAA,EA4BM,OA5BN,IA4BM;IA1BI,EAAA,MAAI,YADZ,EAAA,GAAA,EAMQ,QAAA;;KAJN,OAAK,EAAA,CAAC,qCAAmC,EAAA,uBACR,EAAA,MAAkB,CAAA,CAAA;KAClD,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,GAAgB,GAAA,CAAA,MAAA,CAAA;KAC5B,OAAO,EAAA,QAAkB,6BAAA;;IAE5B,EAUE,SAAA;KATI,SAAA;KAAJ,KAAI;KACJ,MAAK;KACL,IAAG;KACH,OAAM;KACL,OAAO,EAAA;KACP,SAAK,AAAA,EAAA,QAAA,MAAE,EAAe,EAAO,OAA4B,KAAK;KAC/D,cAAa;KACZ,aAAa,EAAA,MAAI;KACjB,SAAK,AAAA,EAAA,OAAA,QAAN,CAAA,GAAW,CAAA,MAAA,CAAA;;IAGL,EAAA,SADR,EAAA,GAAA,EAQS,UAAA;;KANP,MAAK;KACL,OAAM;KACL,SAAK,AAAA,EAAA,OAAA,GAAA,MAAO,GAAiB,GAAA,CAAA,MAAA,CAAA;KAC9B,cAAW;IAEX,GAAA,CAAA,GAAA,AAAA,EAAA,OAAA,CAAA,EAAiC,KAAA,EAA9B,OAAM,oBAAmB,GAAA,MAAA,EAAA,CAAA,CAAA,CAAA,KAAA,EAAA,IAAA,EAAA;;GAIhC,EA8BK,MA9BL,GA8BK,CA7BO,EAAA,MAAI,WAAd,EAAA,GAAA,EAEK,MAFL,IAEK,CADH,EAAoE,GAAA;IAA5D,MAAK;IAAO,OAAM;IAAqB,OAAM;GAEvD,CAAA,CAAA,CAAA,MAAA,EAAA,GAAA,EAyBW,GAAA,EAAA,KAAA,EAAA,GAAA,EAxBT,EAAA,EAAA,GAAA,EAoBK,GAAA,MAAA,GAnBkB,EAAA,QAAb,GAAK,OADf,EAAA,GAAA,EAoBK,MAAA;IAlBF,KAAK,EAAI,SAAK,MAAU;IACzB,OAAK,EAAA,CAAC,sBAAoB,EAAA,uBACO,EAAI,SAAS,EAAW,EAAI,KAAK,EAAA,CAAA,CAAA;IAClE,UAAS;IACR,UAAK,MAAE,EAAa,CAAG;IACvB,YAAO,MAAE,GAAgB,GAAQ,CAAG;;IAG7B,EAAA,MAAI,YAAY,EAAI,SAD5B,EAAA,GAAA,EAIQ,QAAA;;KAFN,OAAK,EAAA,CAAC,cAAY,EAAA,uBACe,EAAW,EAAI,KAAK,EAAA,CAAA,CAAA;;IAE9C,EAAI,QAAb,EAAA,GAAA,EAAuD,KAAA;;KAApC,OAAK,EAAA,CAAC,SAAgB,EAAI,IAAI,CAAA;;IACjD,EAIQ,QAAA;KAHN,OAAK,EAAA,CAAC,mBAAiB,EAAA,cACC,EAAA,MAAI,aAAY,CAAA,CAAA;KACxC,WAAQ,GAAU,EAAI,KAAK;;cAGrB,GAAA,GAAA,IAAA,EAAA,MAAgB,WAAM,KAAhC,EAAA,GAAA,EAEK,MAFL,GAA2E,iBAE3E,KAAA,EAAA,IAAA,EAAA,CAAA,GAAA,EAAA,EAAA,CAAA;GAGO,EAAA,MAAI,YAAf,EAAA,GAAA,EAGM,OAHN,GAGM,CAFU,EAAA,MAAI,aAAa,EAAA,MAAU,SAAM,KAA/C,EAAA,GAAA,EAA6F,GAAA;;IAAxC,OAAM;IAAS,SAAA;IAAS,SAAO;GACpF,CAAA,KAAA,EAAA,IAAA,EAAA,GAAA,EAAqD,GAAA;IAA7C,OAAM;IAAK,MAAK;IAAW,SAAO"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components28.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\nconst { isOpen, dropdownStyle } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({\n minWidth: `${rect.width}px`,\n maxWidth: `${rect.width * 1.5}px`,\n }),\n})\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n //debouncedEmit(text)\n}\n\n/* const debouncedEmit = debounce((raw: string) => {\n emit('filter-input', raw)\n}) */\n\n// Display\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n // Prefer the label from the live options list, fall back to the stored label\n return props.options.find((o) => o.value === sel?.value)?.label ?? sel?.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value ?? ''))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\n// Actions\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n </div>\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div\n v-if=\"isOpen\"\n ref=\"dropdownRef\"\n class=\"c-dropdown ds-dropdown ds-wrapper\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple }\"\n :style=\"dropdownStyle\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n\n <div v-if=\"cfg.multiple || (cfg.clearable && selection.length > 0)\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable\" label=\"Törlés\" outline @click=\"clear\" />\n <Button v-if=\"cfg.multiple\" label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":""}
|
|
1
|
+
{"version":3,"file":"admins-components28.js","names":[],"sources":["../src/components/DropdownSelect.vue"],"sourcesContent":["<script lang=\"ts\">\nexport interface DropdownSelectConfig {\n placeholder?: string\n filterable?: boolean\n filterPlaceholder?: string\n clearable?: boolean\n textEllipsis?: boolean\n multiple?: boolean\n lazy?: boolean\n size?: ControlSize\n loading?: boolean\n highlight?: boolean\n disabled?: boolean\n}\n\nexport const dropdownSelectConfigDefaults: DropdownSelectConfig = {\n placeholder: 'Válassz...',\n filterable: true,\n filterPlaceholder: 'Kezdj el gépelni...',\n clearable: true,\n textEllipsis: true,\n multiple: false,\n lazy: false,\n loading: false,\n size: 'normal' as ControlSize,\n highlight: true,\n disabled: false,\n}\n\nexport interface DropdownOption {\n icon?: string\n value?: string\n label: string\n callback?: () => void\n}\n\nexport interface DropdownSelectProps {\n modelValue?: DropdownOption | DropdownOption[] | string | string[] | null\n options: DropdownOption[]\n config?: DropdownSelectConfig\n}\n</script>\n\n<script setup lang=\"ts\">\nimport { ref, computed, watch, nextTick } from 'vue'\nimport Button from '@/components/Button.vue'\nimport type { ControlSize } from '@/types/types'\nimport Loader from '@/components/Loader.vue'\nimport { useDropdownAnchor } from '@/composables/useDropdownAnchor'\n\nconst props = withDefaults(defineProps<DropdownSelectProps>(), {\n modelValue: null,\n config: () => ({ ...dropdownSelectConfigDefaults }),\n})\n\nconst cfg = computed(() => ({ ...dropdownSelectConfigDefaults, ...props.config }))\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: DropdownOption | DropdownOption[] | null]\n 'filter-input': [filterText: string]\n}>()\n\nconst filterText = ref('')\nconst wrapperRef = ref<HTMLElement | null>(null)\nconst dropdownRef = ref<HTMLElement | null>(null)\nconst filterInputRef = ref<HTMLInputElement | null>(null)\nconst buffer = ref<DropdownOption[]>([])\nconst selection = ref<DropdownOption[]>(normalizeToOptions(props.modelValue, props.options))\n\nconst { isOpen, dropdownStyle, placement } = useDropdownAnchor(wrapperRef, dropdownRef, {\n extraStyle: (rect) => ({\n minWidth: `${rect.width}px`,\n maxWidth: `${rect.width}px`,\n }),\n maxHeight: '17rem',\n})\n\n\nfunction normalizeToOptions(\n val: DropdownOption | DropdownOption[] | string | string[] | null | undefined,\n options: DropdownOption[],\n): DropdownOption[] {\n if (val == null) return []\n const arr = Array.isArray(val) ? val : [val]\n return arr\n .map((entry): DropdownOption | null => {\n if (entry == null) return null\n if (typeof entry === 'object' && 'label' in entry) {\n return entry as DropdownOption\n }\n if (typeof entry === 'string') {\n const found = options.find((o) => o.value === entry)\n return found ?? { value: entry, label: entry }\n }\n return null\n })\n .filter((o): o is DropdownOption => o !== null)\n}\n\nwatch(\n () => [props.modelValue, props.options],\n ([v]) => {\n selection.value = normalizeToOptions(v as typeof props.modelValue, props.options)\n },\n)\n\nwatch(isOpen, (open) => {\n if (open) {\n filterText.value = ''\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n if (cfg.value.lazy) buffer.value = [...selection.value]\n }\n})\n\nfunction onFilterInput(text: string) {\n filterText.value = text\n emit('filter-input', text)\n}\n\nconst selectedLabel = computed(() => {\n if (selection.value.length === 0) return null\n if (!cfg.value.multiple) {\n const sel = selection.value[0]\n\n return props.options.find((o) => o.value === sel?.value)?.label ?? sel?.label ?? null\n }\n if (selection.value.length > 2) return `${selection.value.length} kiválasztva`\n return selection.value\n .map((sel) => props.options.find((o) => o.value === sel.value)?.label ?? sel.label ?? sel.value)\n .join(', ')\n})\n\nconst filteredOptions = computed(() => {\n const q = filterText.value.toLowerCase()\n return q ? props.options.filter((o) => o.label.toLowerCase().includes(q)) : props.options\n})\n\nfunction escapeHtml(str: string) {\n return str.replace(\n /[&<>\"']/g,\n (m) => ({ '&': '&', '<': '<', '>': '>', '\"': '"', \"'\": ''' })[m]!,\n )\n}\n\nfunction highlight(label: string) {\n const q = filterText.value.trim()\n if (!q || !cfg.value.highlight) return escapeHtml(label)\n\n const safeLabel = escapeHtml(label)\n const safeQ = escapeHtml(q)\n\n const re = new RegExp(safeQ.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&'), 'ig')\n return safeLabel.replace(re, (m) => `<mark class=\"ds-option__highlight\">${m}</mark>`)\n}\n\nconst selectableOptions = computed(() => {\n return filteredOptions.value.filter((o) => o.value)\n})\n\nconst allOptionsSelected = computed(() => {\n if (selectableOptions.value.length === 0) return false\n const currentList = cfg.value.lazy && isOpen.value ? buffer.value : selection.value\n return selectableOptions.value.every((o) => o.value && currentList.some((s) => s.value === o.value))\n})\n\nfunction isSelected(value: string): boolean {\n const list = cfg.value.lazy && isOpen.value ? buffer : selection\n return list.value.some((s) => s.value === value)\n}\n\nfunction toggleAllOptions() {\n const currentList = cfg.value.lazy && isOpen.value ? buffer : selection\n const selectableOpts = selectableOptions.value.filter((o) => o.value)\n\n if (allOptionsSelected.value) {\n const selectableValues = new Set(selectableOpts.map((o) => o.value as string))\n currentList.value = currentList.value.filter((s) => !selectableValues.has(s.value ?? ''))\n } else {\n const existingValues = new Set(currentList.value.map((s) => s.value))\n const toAdd = selectableOpts.filter((o) => !existingValues.has(o.value as string))\n currentList.value = [...currentList.value, ...toAdd]\n }\n\n if (!cfg.value.lazy) {\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n}\n\nfunction toggleList(list: DropdownOption[], opt: DropdownOption): DropdownOption[] {\n const idx = list.findIndex((s) => s.value === opt.value)\n return idx >= 0 ? list.filter((_, i) => i !== idx) : [...list, opt]\n}\n\nfunction selectOption(opt: DropdownOption) {\n if (opt.callback) {\n opt.callback()\n isOpen.value = false\n return\n }\n\n const value = opt.value\n if (!value) return\n\n if (cfg.value.multiple) {\n if (cfg.value.lazy) {\n buffer.value = toggleList(buffer.value, opt)\n } else {\n selection.value = toggleList(selection.value, opt)\n emit('update:modelValue', selection.value.length > 0 ? [...selection.value] : null)\n }\n } else {\n selection.value = [opt]\n emit('update:modelValue', opt)\n isOpen.value = false\n }\n}\n\nfunction confirm() {\n if (cfg.value.lazy) {\n selection.value = [...buffer.value]\n emit('update:modelValue', buffer.value.length > 0 ? [...buffer.value] : null)\n }\n isOpen.value = false\n}\n\nfunction clear() {\n if (cfg.value.lazy) {\n buffer.value = []\n } else {\n selection.value = []\n emit('update:modelValue', null)\n }\n}\n\nfunction onOptionKeydown(e: KeyboardEvent, opt: DropdownOption) {\n if (e.key === ' ') {\n e.preventDefault()\n selectOption(opt)\n } else if (e.key === 'Enter') {\n e.preventDefault()\n confirm()\n }\n}\n\nfunction toggleOpen() {\n if (cfg.value.disabled) return\n isOpen.value = !isOpen.value\n if (isOpen.value) {\n if (cfg.value.filterable) {\n filterText.value = ''\n emit('filter-input', '')\n }\n }\n}\n\nfunction clearInput() {\n if (cfg.value.disabled) return\n selection.value = []\n emit('update:modelValue', null)\n isOpen.value = false\n}\n\nfunction focusAndOpen() {\n if (cfg.value.disabled) return\n isOpen.value = true\n if (cfg.value.filterable) nextTick(() => filterInputRef.value?.focus())\n}\n\nfunction handleFilterClear() {\n filterText.value = ''\n emit('filter-input', '')\n}\n\ndefineExpose({ focusAndOpen })\n</script>\n\n<template>\n <div class=\"ac-component\">\n <div ref=\"wrapperRef\" class=\"c-wrapper ds-wrapper\">\n <div\n class=\"c-input-row pointer\"\n :class=\"{\n 'c-input-row--sm': cfg.size === 'small',\n 'c-input-row--lg': cfg.size === 'large',\n 'c-input-row--disabled': cfg.disabled,\n 'c-input-row--open': isOpen,\n }\"\n :aria-disabled=\"cfg.disabled || undefined\"\n @click=\"toggleOpen()\"\n >\n <span v-if=\"selectedLabel\" class=\"c-truncate ds-value\">{{ selectedLabel }}</span>\n <span v-else class=\"c-placeholder\">{{ cfg.placeholder }}</span>\n <button\n v-if=\"cfg.clearable && selection.length > 0\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-clear-btn\"\n @click.stop=\"clearInput()\"\n aria-label=\"Törlés\"\n >\n <i class=\"fa-solid fa-fw fa-xmark\"></i>\n </button>\n <span\n class=\"c-icon-btn c-icon-btn--chevron mr-2\"\n :class=\"{ 'c-icon-btn--chevron-open': isOpen }\"\n >\n <i class=\"fa-solid fa-fw fa-chevron-down\"></i>\n </span>\n </div>\n </div>\n <Teleport to=\"body\">\n <div class=\"ac-component\">\n <div\n v-if=\"isOpen\"\n ref=\"dropdownRef\"\n class=\"c-dropdown ds-dropdown ds-wrapper\"\n :class=\"{ 'ds-dropdown--multiple': cfg.multiple, 'ds-dropdown--up': placement === 'up' }\"\n :style=\"dropdownStyle\"\n >\n <div v-if=\"cfg.filterable\" class=\"ds-filter\">\n <span\n v-if=\"cfg.multiple\"\n class=\"c-checkbox ds-select-all-checkbox\"\n :class=\"{ 'c-checkbox--checked': allOptionsSelected }\"\n @click.stop=\"toggleAllOptions()\"\n :title=\"allOptionsSelected ? 'Összes kijelölés törlése' : 'Összes kijelölése'\"\n ></span>\n <input\n ref=\"filterInputRef\"\n type=\"text\"\n id=\"ds-filter-input\"\n class=\"c-focus ds-filter-input\"\n :value=\"filterText\"\n @input=\"onFilterInput(($event.target as HTMLInputElement).value)\"\n autocomplete=\"off\"\n :placeholder=\"cfg.filterPlaceholder\"\n @click.stop\n />\n <button\n v-if=\"filterText\"\n type=\"button\"\n class=\"c-icon-btn c-icon-btn--clear ds-filter-clear\"\n @click.stop=\"handleFilterClear()\"\n aria-label=\"Szűrők törlése\"\n >\n <i class=\"fa-solid fa-xmark\"></i>\n </button>\n </div>\n\n <ul class=\"ds-options c-scroll\">\n <li v-if=\"cfg.loading\" class=\"ds-option ds-option--loading\">\n <Loader size=\"2rem\" color=\"var(--neutral-300)\" class=\"m-auto p-3\" />\n </li>\n <template v-else>\n <li\n v-for=\"(opt, idx) in filteredOptions\"\n :key=\"opt.value ?? `cb-${idx}`\"\n class=\"d-option ds-option\"\n :class=\"{ 'ds-option--selected': opt.value && isSelected(opt.value) }\"\n tabindex=\"0\"\n @click=\"selectOption(opt)\"\n @keydown=\"onOptionKeydown($event, opt)\"\n >\n <span\n v-if=\"cfg.multiple && opt.value\"\n class=\"c-checkbox\"\n :class=\"{ 'c-checkbox--checked': isSelected(opt.value) }\"\n ></span>\n <i v-if=\"opt.icon\" class=\"fa-fw\" :class=\"opt.icon\"></i>\n <span\n class=\"d-option__label\"\n :class=\"{ 'c-truncate': cfg.textEllipsis }\"\n v-html=\"highlight(opt.label)\"\n ></span>\n </li>\n <li v-if=\"filteredOptions.length === 0\" class=\"ds-option ds-option--empty\">\n Nincs találat\n </li>\n </template>\n </ul>\n <div v-if=\"cfg.multiple\" class=\"c-footer\">\n <Button v-if=\"cfg.clearable && selection.length > 0\" label=\"Törlés\" outline @click=\"clear\" />\n <Button label=\"OK\" type=\"success\" @click=\"confirm\" />\n </div>\n </div>\n </div>\n </Teleport>\n </div>\n</template>\n\n<style lang=\"scss\" src=\"@/styles/components/dropdown-select.scss\"></style>\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"admins-components31.js","names":[],"sources":["../src/composables/useSwipeToClose.ts"],"sourcesContent":["import { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport type { Ref } from 'vue'\n\nexport interface UseSwipeToCloseOptions {\n
|
|
1
|
+
{"version":3,"file":"admins-components31.js","names":[],"sources":["../src/composables/useSwipeToClose.ts"],"sourcesContent":["import { computed, onBeforeUnmount, onMounted, ref } from 'vue'\nimport type { Ref } from 'vue'\n\nexport interface UseSwipeToCloseOptions {\n position: Ref<'left' | 'right' | 'top' | 'bottom'>\n onClose: () => void\n distanceThreshold?: number\n velocityThreshold?: number\n verticalRatio?: number\n closeDirections?: 'away' | 'both'\n}\n\nexport interface UseSwipeToCloseReturn {\n isDragging: Ref<boolean>\n panelStyle: Ref<Record<string, string> | undefined>\n touchHandlers: {\n onTouchstart: (e: TouchEvent) => void\n onTouchend: (e: TouchEvent) => void\n onTouchcancel: () => void\n }\n}\n\nexport function useSwipeToClose(\n panelRef: Ref<HTMLElement | null>,\n options: UseSwipeToCloseOptions,\n): UseSwipeToCloseReturn {\n const {\n position,\n onClose,\n distanceThreshold = 0.35,\n velocityThreshold = 0.4,\n verticalRatio = 0.7,\n closeDirections = 'away',\n } = options\n\n const isDragging = ref(false)\n const dragOffset = ref(0)\n\n let startX = 0\n let startY = 0\n let startTime = 0\n let trackingPointer: number | null = null\n let panelWidth = 0\n\n const isHorizontal = computed(() => position.value === 'left' || position.value === 'right')\n\n function onTouchStart(e: TouchEvent) {\n if (!isHorizontal.value || e.touches.length !== 1) return\n const touch = e.touches[0]\n if (!touch) return\n const panel = panelRef.value\n if (!panel) return\n\n startX = touch.clientX\n startY = touch.clientY\n startTime = performance.now()\n panelWidth = panel.offsetWidth\n isDragging.value = true\n dragOffset.value = 0\n trackingPointer = touch.identifier\n }\n\n function onTouchMove(e: TouchEvent) {\n if (!isDragging.value || trackingPointer === null) return\n const touch = Array.from(e.touches).find((t) => t.identifier === trackingPointer)\n if (!touch) return\n\n const dx = touch.clientX - startX\n const dy = touch.clientY - startY\n\n if (Math.abs(dy) > Math.abs(dx) * verticalRatio && Math.abs(dy) > 10) {\n isDragging.value = false\n dragOffset.value = 0\n return\n }\n\n if (position.value === 'left') {\n dragOffset.value = closeDirections === 'both' ? dx : Math.min(0, dx)\n } else {\n dragOffset.value = closeDirections === 'both' ? dx : Math.max(0, dx)\n }\n\n if (e.cancelable) e.preventDefault()\n }\n\n function onTouchEnd(e: TouchEvent) {\n if (!isDragging.value) return\n\n const touch =\n Array.from(e.changedTouches).find((t) => t.identifier === trackingPointer) ??\n e.changedTouches[0]\n\n const dx = touch ? touch.clientX - startX : 0\n const dt = Math.max(1, performance.now() - startTime)\n const velocity = Math.abs(dx) / dt\n const distanceRatio = Math.abs(dx) / Math.max(panelWidth, 1)\n\n const shouldClose = distanceRatio >= distanceThreshold || velocity >= velocityThreshold\n const swipedTowardEdge =\n (position.value === 'left' && dx < 0) || (position.value === 'right' && dx > 0)\n\n if (shouldClose && (closeDirections === 'both' || swipedTowardEdge)) {\n onClose()\n }\n\n isDragging.value = false\n trackingPointer = null\n dragOffset.value = 0\n }\n\n function onTouchCancel() {\n isDragging.value = false\n trackingPointer = null\n dragOffset.value = 0\n }\n\n const panelStyle = computed<Record<string, string> | undefined>(() => {\n if (!isDragging.value || dragOffset.value === 0) return undefined\n return {\n transform: `translateX(${dragOffset.value}px)`,\n transition: 'none',\n }\n })\n\n onMounted(() => {\n document.addEventListener('touchmove', onTouchMove, { passive: false })\n })\n\n onBeforeUnmount(() => {\n document.removeEventListener('touchmove', onTouchMove)\n })\n\n return {\n isDragging,\n panelStyle,\n touchHandlers: {\n onTouchstart: onTouchStart,\n onTouchend: onTouchEnd,\n onTouchcancel: onTouchCancel,\n },\n }\n}\n"],"mappings":";;AAsBA,SAAgB,EACd,GACA,GACuB;CACvB,IAAM,EACJ,aACA,YACA,uBAAoB,KACpB,uBAAoB,IACpB,mBAAgB,IAChB,qBAAkB,WAChB,GAEE,IAAa,EAAI,EAAK,GACtB,IAAa,EAAI,CAAC,GAEpB,IAAS,GACT,IAAS,GACT,IAAY,GACZ,IAAiC,MACjC,IAAa,GAEX,IAAe,QAAe,EAAS,UAAU,UAAU,EAAS,UAAU,OAAO;CAE3F,SAAS,EAAa,GAAe;EACnC,IAAI,CAAC,EAAa,SAAS,EAAE,QAAQ,WAAW,GAAG;EACnD,IAAM,IAAQ,EAAE,QAAQ;EACxB,IAAI,CAAC,GAAO;EACZ,IAAM,IAAQ,EAAS;EAClB,MAEL,IAAS,EAAM,SACf,IAAS,EAAM,SACf,IAAY,YAAY,IAAI,GAC5B,IAAa,EAAM,aACnB,EAAW,QAAQ,IACnB,EAAW,QAAQ,GACnB,IAAkB,EAAM;CAC1B;CAEA,SAAS,EAAY,GAAe;EAClC,IAAI,CAAC,EAAW,SAAS,MAAoB,MAAM;EACnD,IAAM,IAAQ,MAAM,KAAK,EAAE,OAAO,CAAC,CAAC,MAAM,MAAM,EAAE,eAAe,CAAe;EAChF,IAAI,CAAC,GAAO;EAEZ,IAAM,IAAK,EAAM,UAAU,GACrB,IAAK,EAAM,UAAU;EAE3B,IAAI,KAAK,IAAI,CAAE,IAAI,KAAK,IAAI,CAAE,IAAI,KAAiB,KAAK,IAAI,CAAE,IAAI,IAAI;GAEpE,AADA,EAAW,QAAQ,IACnB,EAAW,QAAQ;GACnB;EACF;EAQA,AANI,EAAS,UAAU,SACrB,EAAW,QAAQ,MAAoB,SAAS,IAAK,KAAK,IAAI,GAAG,CAAE,IAEnE,EAAW,QAAQ,MAAoB,SAAS,IAAK,KAAK,IAAI,GAAG,CAAE,GAGjE,EAAE,cAAY,EAAE,eAAe;CACrC;CAEA,SAAS,EAAW,GAAe;EACjC,IAAI,CAAC,EAAW,OAAO;EAEvB,IAAM,IACJ,MAAM,KAAK,EAAE,cAAc,CAAC,CAAC,MAAM,MAAM,EAAE,eAAe,CAAe,KACzE,EAAE,eAAe,IAEb,IAAK,IAAQ,EAAM,UAAU,IAAS,GACtC,IAAK,KAAK,IAAI,GAAG,YAAY,IAAI,IAAI,CAAS,GAC9C,IAAW,KAAK,IAAI,CAAE,IAAI,GAG1B,IAFgB,KAAK,IAAI,CAAE,IAAI,KAAK,IAAI,GAAY,CAAC,KAEtB,KAAqB,KAAY,GAChE,IACH,EAAS,UAAU,UAAU,IAAK,KAAO,EAAS,UAAU,WAAW,IAAK;EAQ/E,AANI,MAAgB,MAAoB,UAAU,MAChD,EAAQ,GAGV,EAAW,QAAQ,IACnB,IAAkB,MAClB,EAAW,QAAQ;CACrB;CAEA,SAAS,IAAgB;EAGvB,AAFA,EAAW,QAAQ,IACnB,IAAkB,MAClB,EAAW,QAAQ;CACrB;CAEA,IAAM,IAAa,QAAmD;EAChE,OAAC,EAAW,SAAS,EAAW,UAAU,IAC9C,OAAO;GACL,WAAW,cAAc,EAAW,MAAM;GAC1C,YAAY;EACd;CACF,CAAC;CAUD,OARA,QAAgB;EACd,SAAS,iBAAiB,aAAa,GAAa,EAAE,SAAS,GAAM,CAAC;CACxE,CAAC,GAED,QAAsB;EACpB,SAAS,oBAAoB,aAAa,CAAW;CACvD,CAAC,GAEM;EACL;EACA;EACA,eAAe;GACb,cAAc;GACd,YAAY;GACZ,eAAe;EACjB;CACF;AACF"}
|