admins-components 9.0.77 → 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 +94 -87
- 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 u, defineComponent as d, nextTick as f, normalizeClass as p, normalizeStyle as ee, openBlock as m, ref as h, renderList 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,46 +33,49 @@ var x = { class: "ac-component" }, S = ["aria-disabled"], C = {
|
|
|
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(d, { expose:
|
|
45
|
-
let
|
|
46
|
-
...
|
|
47
|
-
...
|
|
48
|
-
})),
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
44
|
+
setup(d, { expose: k, emit: A }) {
|
|
45
|
+
let j = d, M = a(() => ({
|
|
46
|
+
...O,
|
|
47
|
+
...j.config
|
|
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
|
+
});
|
|
52
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
|
-
|
|
59
|
-
|
|
60
|
-
}),
|
|
61
|
-
e && (
|
|
61
|
+
v(() => [j.modelValue, j.options], ([e]) => {
|
|
62
|
+
z.value = U(e, j.options);
|
|
63
|
+
}), v(B, (e) => {
|
|
64
|
+
e && (P.value = "", M.value.filterable && f(() => L.value?.focus()), M.value.lazy && (R.value = [...z.value]));
|
|
62
65
|
});
|
|
63
66
|
function W(e) {
|
|
64
|
-
|
|
67
|
+
P.value = e, N("filter-input", e);
|
|
65
68
|
}
|
|
66
69
|
let G = a(() => {
|
|
67
|
-
if (
|
|
68
|
-
if (!
|
|
69
|
-
let e =
|
|
70
|
-
return
|
|
70
|
+
if (z.value.length === 0) return null;
|
|
71
|
+
if (!M.value.multiple) {
|
|
72
|
+
let e = z.value[0];
|
|
73
|
+
return j.options.find((t) => t.value === e?.value)?.label ?? e?.label ?? null;
|
|
71
74
|
}
|
|
72
|
-
return
|
|
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
|
-
let e =
|
|
75
|
-
return e ?
|
|
77
|
+
let e = P.value.toLowerCase();
|
|
78
|
+
return e ? j.options.filter((t) => t.label.toLowerCase().includes(e)) : j.options;
|
|
76
79
|
});
|
|
77
80
|
function q(e) {
|
|
78
81
|
return e.replace(/[&<>"']/g, (e) => ({
|
|
@@ -83,22 +86,22 @@ var x = { class: "ac-component" }, S = ["aria-disabled"], C = {
|
|
|
83
86
|
"'": "'"
|
|
84
87
|
})[e]);
|
|
85
88
|
}
|
|
86
|
-
function
|
|
87
|
-
let t =
|
|
88
|
-
if (!t || !
|
|
89
|
+
function ce(e) {
|
|
90
|
+
let t = P.value.trim();
|
|
91
|
+
if (!t || !M.value.highlight) return q(e);
|
|
89
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
95
|
let J = a(() => K.value.filter((e) => e.value)), Y = a(() => {
|
|
93
96
|
if (J.value.length === 0) return !1;
|
|
94
|
-
let e =
|
|
97
|
+
let e = M.value.lazy && B.value ? R.value : z.value;
|
|
95
98
|
return J.value.every((t) => t.value && e.some((e) => e.value === t.value));
|
|
96
99
|
});
|
|
97
100
|
function X(e) {
|
|
98
|
-
return (
|
|
101
|
+
return (M.value.lazy && B.value ? R : z).value.some((t) => t.value === e);
|
|
99
102
|
}
|
|
100
|
-
function
|
|
101
|
-
let e =
|
|
103
|
+
function le() {
|
|
104
|
+
let e = M.value.lazy && B.value ? R : z, t = J.value.filter((e) => e.value);
|
|
102
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 ?? ""));
|
|
@@ -106,7 +109,7 @@ var x = { class: "ac-component" }, S = ["aria-disabled"], C = {
|
|
|
106
109
|
let n = new Set(e.value.map((e) => e.value)), r = t.filter((e) => !n.has(e.value));
|
|
107
110
|
e.value = [...e.value, ...r];
|
|
108
111
|
}
|
|
109
|
-
|
|
112
|
+
M.value.lazy || N("update:modelValue", z.value.length > 0 ? [...z.value] : null);
|
|
110
113
|
}
|
|
111
114
|
function Z(e, t) {
|
|
112
115
|
let n = e.findIndex((e) => e.value === t.value);
|
|
@@ -114,100 +117,104 @@ var x = { class: "ac-component" }, S = ["aria-disabled"], C = {
|
|
|
114
117
|
}
|
|
115
118
|
function Q(e) {
|
|
116
119
|
if (e.callback) {
|
|
117
|
-
e.callback(),
|
|
120
|
+
e.callback(), B.value = !1;
|
|
118
121
|
return;
|
|
119
122
|
}
|
|
120
|
-
e.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
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
|
|
126
|
-
|
|
128
|
+
function ue() {
|
|
129
|
+
M.value.lazy ? R.value = [] : (z.value = [], N("update:modelValue", null));
|
|
127
130
|
}
|
|
128
|
-
function
|
|
131
|
+
function de(e, t) {
|
|
129
132
|
e.key === " " ? (e.preventDefault(), Q(t)) : e.key === "Enter" && (e.preventDefault(), $());
|
|
130
133
|
}
|
|
131
|
-
function de() {
|
|
132
|
-
N.value.disabled || (V.value = !V.value, V.value && N.value.filterable && (F.value = "", P("filter-input", "")));
|
|
133
|
-
}
|
|
134
134
|
function fe() {
|
|
135
|
-
|
|
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
|
-
|
|
138
|
+
M.value.disabled || (z.value = [], N("update:modelValue", null), B.value = !1);
|
|
139
139
|
}
|
|
140
140
|
function me() {
|
|
141
|
-
|
|
141
|
+
M.value.disabled || (B.value = !0, M.value.filterable && f(() => L.value?.focus()));
|
|
142
|
+
}
|
|
143
|
+
function he() {
|
|
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
|
-
ref:
|
|
148
|
+
ref: F,
|
|
146
149
|
class: "c-wrapper ds-wrapper"
|
|
147
150
|
}, [l("div", {
|
|
148
151
|
class: p(["c-input-row pointer", {
|
|
149
|
-
"c-input-row--sm":
|
|
150
|
-
"c-input-row--lg":
|
|
151
|
-
"c-input-row--disabled":
|
|
152
|
+
"c-input-row--sm": M.value.size === "small",
|
|
153
|
+
"c-input-row--lg": M.value.size === "large",
|
|
154
|
+
"c-input-row--disabled": M.value.disabled,
|
|
155
|
+
"c-input-row--open": _(B)
|
|
152
156
|
}]),
|
|
153
|
-
"aria-disabled":
|
|
154
|
-
onClick: a[1] ||= (e) =>
|
|
157
|
+
"aria-disabled": M.value.disabled || void 0,
|
|
158
|
+
onClick: a[1] ||= (e) => fe()
|
|
155
159
|
}, [
|
|
156
|
-
G.value ? (m(), c("span",
|
|
157
|
-
|
|
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] ||=
|
|
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: p(["c-icon-btn c-icon-btn--chevron mr-2", { "c-icon-btn--chevron-open":
|
|
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
|
-
ref:
|
|
169
|
-
class: p(["c-dropdown ds-dropdown ds-wrapper", {
|
|
170
|
-
|
|
172
|
+
ref: I,
|
|
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
|
-
|
|
173
|
-
|
|
179
|
+
M.value.filterable ? (m(), c("div", ae, [
|
|
180
|
+
M.value.multiple ? (m(), c("span", {
|
|
174
181
|
key: 0,
|
|
175
182
|
class: p(["c-checkbox ds-select-all-checkbox", { "c-checkbox--checked": Y.value }]),
|
|
176
|
-
onClick: a[2] ||=
|
|
183
|
+
onClick: a[2] ||= y((e) => le(), ["stop"]),
|
|
177
184
|
title: Y.value ? "Összes kijelölés törlése" : "Összes kijelölése"
|
|
178
|
-
}, null, 10,
|
|
185
|
+
}, null, 10, S)) : s("", !0),
|
|
179
186
|
l("input", {
|
|
180
187
|
ref_key: "filterInputRef",
|
|
181
|
-
ref:
|
|
188
|
+
ref: L,
|
|
182
189
|
type: "text",
|
|
183
190
|
id: "ds-filter-input",
|
|
184
191
|
class: "c-focus ds-filter-input",
|
|
185
|
-
value:
|
|
192
|
+
value: P.value,
|
|
186
193
|
onInput: a[3] ||= (e) => W(e.target.value),
|
|
187
194
|
autocomplete: "off",
|
|
188
|
-
placeholder:
|
|
189
|
-
onClick: a[4] ||=
|
|
190
|
-
}, null, 40,
|
|
191
|
-
|
|
195
|
+
placeholder: M.value.filterPlaceholder,
|
|
196
|
+
onClick: a[4] ||= y(() => {}, ["stop"])
|
|
197
|
+
}, null, 40, C),
|
|
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] ||=
|
|
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",
|
|
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
|
-
})])) : (m(), c(r, { key: 1 }, [(m(!0), c(r, null,
|
|
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
212
|
class: p(["d-option ds-option", { "ds-option--selected": e.value && X(e.value) }]),
|
|
206
213
|
tabindex: "0",
|
|
207
214
|
onClick: (t) => Q(e),
|
|
208
|
-
onKeydown: (t) =>
|
|
215
|
+
onKeydown: (t) => de(t, e)
|
|
209
216
|
}, [
|
|
210
|
-
|
|
217
|
+
M.value.multiple && e.value ? (m(), c("span", {
|
|
211
218
|
key: 0,
|
|
212
219
|
class: p(["c-checkbox", { "c-checkbox--checked": X(e.value) }])
|
|
213
220
|
}, null, 2)) : s("", !0),
|
|
@@ -216,15 +223,15 @@ var x = { class: "ac-component" }, S = ["aria-disabled"], C = {
|
|
|
216
223
|
class: p(["fa-fw", e.icon])
|
|
217
224
|
}, null, 2)) : s("", !0),
|
|
218
225
|
l("span", {
|
|
219
|
-
class: p(["d-option__label", { "c-truncate":
|
|
220
|
-
innerHTML:
|
|
221
|
-
}, null, 10,
|
|
222
|
-
], 42,
|
|
223
|
-
|
|
226
|
+
class: p(["d-option__label", { "c-truncate": M.value.textEllipsis }]),
|
|
227
|
+
innerHTML: ce(e.label)
|
|
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:
|
|
234
|
+
onClick: ue
|
|
228
235
|
})) : s("", !0), u(e, {
|
|
229
236
|
label: "OK",
|
|
230
237
|
type: "success",
|
|
@@ -234,4 +241,4 @@ var x = { class: "ac-component" }, S = ["aria-disabled"], C = {
|
|
|
234
241
|
}
|
|
235
242
|
});
|
|
236
243
|
//#endregion
|
|
237
|
-
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}\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 }\"\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 <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":"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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":"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"}
|
|
@@ -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}\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 }\"\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 <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
|
+
{"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"}
|