@milaboratories/uikit 2.6.5 → 2.7.1
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/.turbo/turbo-build.log +43 -31
- package/.turbo/turbo-type-check.log +1 -1
- package/CHANGELOG.md +19 -0
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.d.ts +1 -5
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.js +46 -47
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.js.map +1 -1
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.js +29 -30
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.js.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue.js +101 -101
- package/dist/components/PlDropdown/PlDropdown.vue.js.map +1 -1
- package/package.json +5 -5
- package/src/components/PlAutocomplete/PlAutocomplete.vue +3 -10
- package/src/components/PlAutocompleteMulti/PlAutocompleteMulti.vue +8 -7
- package/src/components/PlAutocompleteMulti/__tests__/PlAutocompleteMulti.spec.ts +0 -6
- package/src/components/PlDropdown/PlDropdown.vue +10 -2
- package/dist/components/PlAccordion/ExpandTransition.vue2.js +0 -27
- package/dist/components/PlAccordion/ExpandTransition.vue2.js.map +0 -1
- package/dist/components/PlAutocompleteMulti/PlAutocompleteMulti.vue.d.ts +0 -111
|
@@ -1,40 +1,40 @@
|
|
|
1
1
|
(function(){"use strict";try{if(typeof document<"u"){var o=document.createElement("style");o.appendChild(document.createTextNode(`.double-contour.top>div{border-bottom-right-radius:0;border-bottom-left-radius:0}.double-contour.bottom>div{border-top-right-radius:0;border-top-left-radius:0}.double-contour.left>div{border-top-right-radius:0;border-bottom-right-radius:0}.double-contour.right>div{border-top-left-radius:0;border-bottom-left-radius:0}.double-contour.top-left>div{border-top-right-radius:0;border-bottom-left-radius:0;border-bottom-right-radius:0}.double-contour.top-right>div{border-bottom-right-radius:0;border-top-left-radius:0;border-top-right-radius:0}.double-contour.bottom-left>div{border-top-right-radius:0;border-bottom-right-radius:0;border-top-left-radius:0}.double-contour.bottom-right>div{border-top-right-radius:0;border-bottom-left-radius:0;border-top-left-radius:0}.double-contour.middle>div{border-radius:0}
|
|
2
2
|
.ui-lt-container{min-width:0;white-space:nowrap;overflow:hidden;position:relative;border-radius:5px}.ui-lt-container span{display:inline-block;overflow:hidden;text-overflow:ellipsis;width:100%;vertical-align:bottom;pointer-events:all!important}.ui-lt-container .ui-lt-animate{position:relative;animation:left-to-right var(--v5deba9de) infinite alternate linear;overflow:unset!important;text-overflow:unset!important;width:fit-content!important}@keyframes left-to-right{0%{transform:translate(0);left:0%}to{transform:translate(-101%);left:101%}}
|
|
3
3
|
.pl-dropdown__options{--option-hover-bg: var(--btn-sec-hover-grey);z-index:var(--z-dropdown-options);border:1px solid var(--border-color-div-grey);position:absolute;background-color:var(--pl-dropdown-options-bg);border-radius:6px;max-height:244px;box-shadow:0 4px 12px -2px #0f244d14,0 6px 24px -2px #0f244d14;--thumb-color: var(--ic-02);overflow-y:auto}.pl-dropdown__options::-webkit-scrollbar{width:var(--scrollbar-width, 6px);height:5px;background-color:transparent;display:block}.pl-dropdown__options::-webkit-scrollbar-thumb{background:var(--thumb-color);border-radius:5px}.pl-dropdown__options::-webkit-scrollbar-thumb:hover{--thumb-color: var(--border-color-focus)}.pl-dropdown__options .nothing-found{padding:0 10px;height:var(--control-height);line-height:var(--control-height);background-color:#fff;opacity:.5;font-style:italic}.pl-dropdown__options .group-container{padding:4px 0}.pl-dropdown{--contour-color: var(--txt-01);--contour-border-width: 1px;--label-offset-left-x: 8px;--label-offset-right-x: 8px;--label-color: var(--txt-01);position:relative;outline:none;min-height:var(--control-height);border-radius:6px;font-family:var(--font-family-base);font-size:var(--font-size-base);font-weight:var(--font-weigh-base)}.pl-dropdown__envelope{font-family:var(--control-font-family);min-width:160px}.pl-dropdown label{display:flex;align-items:center;gap:4px;position:absolute;top:0;transform:translateY(-60%);left:var(--label-offset-left-x);padding:0 4px;max-width:calc(100% - 16px);overflow:hidden;white-space:pre;text-overflow:ellipsis;cursor:inherit;color:var(--label-color);font-size:12px;font-weight:500;border-bottom-right-radius:4px;border-bottom-left-radius:4px;background:var(--bg-elevated-01)}.pl-dropdown label>span{overflow:hidden;white-space:pre;text-overflow:ellipsis}.pl-dropdown__container{position:absolute;top:0;left:0;right:0;border-radius:6px;min-height:var(--control-height);color:var(--txt-01)}.pl-dropdown__contour{border-radius:var(--border-radius-control);border:var(--contour-border-width) solid var(--contour-color);box-shadow:var(--contour-box-shadow);z-index:0;pointer-events:none}.pl-dropdown__field{position:relative;border-radius:6px;overflow:hidden;background:transparent;padding-left:11px;min-height:var(--control-height);line-height:var(--control-height);display:flex;flex-direction:row;align-items:center;cursor:pointer}.pl-dropdown__field .input-value{position:absolute;top:0;left:0;bottom:0;right:0;display:flex;flex-direction:row;align-items:center;padding:0 60px 0 11px;pointer-events:none;line-height:20px;color:var(--txt-01);overflow:hidden;white-space:pre;text-overflow:ellipsis;cursor:inherit}.pl-dropdown__field input{min-height:calc(var(--control-height) - 2px);line-height:20px;font-family:inherit;font-size:inherit;background-color:transparent;border:none;padding:0;width:calc(100% - 40px);color:var(--txt-01);caret-color:var(--border-color-focus)}.pl-dropdown__field input:focus{outline:none}.pl-dropdown__field input:placeholder-shown{text-overflow:ellipsis}.pl-dropdown__field input::placeholder{color:var(--color-placeholder)}.pl-dropdown__helper{font-size:12px;color:var(--txt-03);padding:2px 0 0;white-space:pre-wrap;text-overflow:ellipsis;font-weight:500;line-height:16px;margin-top:6px}.pl-dropdown__error{font-size:12px;color:var(--txt-error);padding:2px 0 0;white-space:pre-wrap;text-overflow:ellipsis;font-weight:500;line-height:16px;margin-top:6px}.pl-dropdown__controls{display:flex;flex-direction:row;align-items:center;gap:6px;margin-left:auto}.pl-dropdown__controls .mask-16,.pl-dropdown__controls .mask-24{cursor:pointer}.pl-dropdown__controls .clear{--icon-color: var(--ic-02)}.pl-dropdown__controls .mask-loading{--icon-color: var(--ic-accent);animation:spin 2.5s linear infinite}.pl-dropdown__arrow-wrapper{display:flex;align-items:center;min-height:var(--control-height);padding-right:11px}.pl-dropdown .arrow-icon{cursor:pointer}.pl-dropdown .arrow-icon.arrow-icon-default{transition:transform .2s}.pl-dropdown.open,.pl-dropdown:focus-within{z-index:1;--label-color: var(--txt-focus)}.pl-dropdown.open .pl-dropdown__container{z-index:1000}.pl-dropdown.open .pl-dropdown__field{border-radius:6px 6px 0 0}.pl-dropdown.open .arrow-icon.arrow-icon-default{transform:rotate(-180deg)}.pl-dropdown:hover{--contour-color: var(--control-hover-color)}.pl-dropdown:focus-within:not(.error){--label-color: var(--txt-focus);--contour-color: var(--border-color-focus);--contour-border-width: 2px;--contour-box-shadow: 0 0 0 4px var(--border-color-focus-shadow)}.pl-dropdown:focus-within.error{--contour-border-width: 2px;--contour-box-shadow: 0 0 0 4px var(--color-error-shadow)}.pl-dropdown.error{--contour-color: var(--txt-error);--label-color: var(--txt-error)}.pl-dropdown.disabled{--contour-color: var(--color-dis-01);--icon-color: var(--color-dis-01);--label-color: var(--color-dis-01);cursor:not-allowed;pointer-events:none;-webkit-user-select:none;user-select:none}.pl-dropdown.disabled .input-value{color:var(--dis-01)}`)),document.head.appendChild(o)}}catch(r){console.error("vite-plugin-css-injected-by-js",r)}})();
|
|
4
|
-
import { defineComponent as
|
|
5
|
-
import
|
|
6
|
-
import { getErrorMessage as
|
|
7
|
-
import { tap as
|
|
4
|
+
import { defineComponent as ae, ref as P, useTemplateRef as ie, reactive as se, computed as i, unref as s, watch as D, watchPostEffect as de, createElementBlock as v, openBlock as l, createElementVNode as f, createCommentVNode as c, normalizeClass as ce, createBlock as u, createVNode as $, withDirectives as ue, vModelText as pe, withCtx as z, createTextVNode as fe, toDisplayString as h, renderSlot as M, withModifiers as T } from "vue";
|
|
5
|
+
import me from "../../assets/images/required.svg.js";
|
|
6
|
+
import { getErrorMessage as ve } from "../../helpers/error.js";
|
|
7
|
+
import { tap as he } from "../../helpers/functions.js";
|
|
8
8
|
import { deepEqual as x } from "../../helpers/objects.js";
|
|
9
|
-
import { normalizeListOptions as
|
|
10
|
-
import
|
|
9
|
+
import { normalizeListOptions as we } from "../../helpers/utils.js";
|
|
10
|
+
import ge from "../../utils/DoubleContour.vue.js";
|
|
11
11
|
|
|
12
|
-
import { useLabelNotch as
|
|
13
|
-
import
|
|
12
|
+
import { useLabelNotch as ye } from "../../utils/useLabelNotch.js";
|
|
13
|
+
import ke from "../LongText.vue.js";
|
|
14
14
|
|
|
15
15
|
import _ from "../PlIcon16/PlIcon16.vue.js";
|
|
16
|
-
import
|
|
17
|
-
import
|
|
18
|
-
import
|
|
19
|
-
import
|
|
16
|
+
import F from "../PlIcon24/PlIcon24.vue.js";
|
|
17
|
+
import Ie from "../PlSvg/PlSvg.vue.js";
|
|
18
|
+
import xe from "../PlTooltip/PlTooltip.vue.js";
|
|
19
|
+
import _e from "./OptionList.vue.js";
|
|
20
20
|
|
|
21
|
-
import { useGroupBy as
|
|
22
|
-
const Ve = ["tabindex"],
|
|
21
|
+
import { useGroupBy as be } from "./useGroupBy.js";
|
|
22
|
+
const Ve = ["tabindex"], Le = { class: "pl-dropdown__container" }, Ce = { class: "pl-dropdown__field" }, Ee = ["disabled", "placeholder"], Re = {
|
|
23
23
|
key: 0,
|
|
24
24
|
class: "input-value"
|
|
25
|
-
},
|
|
25
|
+
}, Se = { class: "pl-dropdown__controls" }, Oe = { key: 0 }, Ae = {
|
|
26
26
|
key: 0,
|
|
27
27
|
class: "pl-dropdown__error"
|
|
28
|
-
},
|
|
28
|
+
}, Be = {
|
|
29
29
|
key: 1,
|
|
30
30
|
class: "pl-dropdown__helper"
|
|
31
|
-
},
|
|
31
|
+
}, Pe = {
|
|
32
32
|
key: 2,
|
|
33
33
|
class: "pl-dropdown__helper"
|
|
34
|
-
},
|
|
34
|
+
}, De = {
|
|
35
35
|
name: "PlDropdown"
|
|
36
|
-
},
|
|
37
|
-
...
|
|
36
|
+
}, eo = /* @__PURE__ */ ae({
|
|
37
|
+
...De,
|
|
38
38
|
props: {
|
|
39
39
|
modelValue: {},
|
|
40
40
|
label: { default: "" },
|
|
@@ -53,54 +53,54 @@ const Ve = ["tabindex"], be = { class: "pl-dropdown__container" }, Le = { class:
|
|
|
53
53
|
groupPosition: { default: void 0 }
|
|
54
54
|
},
|
|
55
55
|
emits: ["update:modelValue"],
|
|
56
|
-
setup(
|
|
57
|
-
const
|
|
56
|
+
setup(r, { emit: N }) {
|
|
57
|
+
const b = N, n = r, d = P(), w = P(), g = ie("optionListRef"), o = se({
|
|
58
58
|
search: "",
|
|
59
59
|
activeIndex: -1,
|
|
60
60
|
open: !1,
|
|
61
61
|
optionsHeight: 0
|
|
62
|
-
}),
|
|
63
|
-
|
|
62
|
+
}), q = () => he(
|
|
63
|
+
S.value.findIndex((e) => x(e.value, n.modelValue)),
|
|
64
64
|
(e) => e < 0 ? 0 : e
|
|
65
|
-
),
|
|
66
|
-
if (!
|
|
67
|
-
if (
|
|
68
|
-
return
|
|
69
|
-
if (
|
|
65
|
+
), H = () => o.activeIndex = q(), y = i(() => n.options === void 0), V = i(() => !n.disabled && y.value), k = i(() => y.value ? !0 : n.disabled), L = i(() => (n.options ?? []).findIndex((e) => x(e.value, n.modelValue))), C = i(() => {
|
|
66
|
+
if (!y.value) {
|
|
67
|
+
if (n.error)
|
|
68
|
+
return ve(n.error);
|
|
69
|
+
if (n.modelValue !== void 0 && L.value === -1)
|
|
70
70
|
return "The selected value is not one of the options";
|
|
71
71
|
}
|
|
72
|
-
}),
|
|
73
|
-
() =>
|
|
72
|
+
}), E = i(
|
|
73
|
+
() => we(n.options ?? []).map((e, t) => ({
|
|
74
74
|
...e,
|
|
75
75
|
index: t,
|
|
76
|
-
isSelected: t ===
|
|
76
|
+
isSelected: t === L.value,
|
|
77
77
|
isActive: t === o.activeIndex
|
|
78
78
|
}))
|
|
79
|
-
),
|
|
80
|
-
const t =
|
|
81
|
-
return (t == null ? void 0 : t.label) ||
|
|
82
|
-
}),
|
|
83
|
-
const e =
|
|
79
|
+
), R = i(() => {
|
|
80
|
+
const t = s(E).find((a) => x(a.value, n.modelValue));
|
|
81
|
+
return (t == null ? void 0 : t.label) || n.modelValue;
|
|
82
|
+
}), U = i(() => !o.open && n.modelValue !== void 0 ? "" : n.modelValue ? String(R.value) : n.placeholder), K = i(() => n.modelValue !== void 0 && n.modelValue !== null), G = i(() => {
|
|
83
|
+
const e = E.value;
|
|
84
84
|
return o.search ? e.filter((t) => {
|
|
85
85
|
const a = o.search.toLowerCase();
|
|
86
86
|
return t.label.toLowerCase().includes(a) || t.description && t.description.toLowerCase().includes(a) ? !0 : typeof t.value == "string" ? t.value.toLowerCase().includes(a) : t.value === o.search;
|
|
87
87
|
}) : e;
|
|
88
|
-
}), { orderedRef:
|
|
88
|
+
}), { orderedRef: S, groupsRef: W, restRef: j } = be(G, "group"), J = i(() => k.value ? void 0 : "0"), O = (e) => {
|
|
89
89
|
var t;
|
|
90
|
-
|
|
91
|
-
},
|
|
90
|
+
b("update:modelValue", e), o.search = "", o.open = !1, (t = d == null ? void 0 : d.value) == null || t.focus();
|
|
91
|
+
}, Q = (e) => {
|
|
92
92
|
O(e);
|
|
93
|
-
},
|
|
93
|
+
}, X = () => b("update:modelValue", void 0), Y = () => {
|
|
94
94
|
var e;
|
|
95
|
-
return (e =
|
|
96
|
-
},
|
|
95
|
+
return (e = w.value) == null ? void 0 : e.focus();
|
|
96
|
+
}, Z = () => {
|
|
97
97
|
o.open = !o.open, o.open || (o.search = "");
|
|
98
|
-
},
|
|
98
|
+
}, ee = () => o.open = !0, oe = (e) => {
|
|
99
99
|
var a, p, m;
|
|
100
100
|
const t = e.relatedTarget;
|
|
101
|
-
!((a = d.value) != null && a.contains(t)) && !((m = (p =
|
|
102
|
-
},
|
|
103
|
-
var
|
|
101
|
+
!((a = d.value) != null && a.contains(t)) && !((m = (p = g.value) == null ? void 0 : p.listRef) != null && m.contains(t)) && (o.search = "", o.open = !1);
|
|
102
|
+
}, te = (e) => {
|
|
103
|
+
var A, B;
|
|
104
104
|
if (["ArrowDown", "ArrowUp", "Enter", "Escape"].includes(e.code))
|
|
105
105
|
e.preventDefault();
|
|
106
106
|
else
|
|
@@ -110,84 +110,84 @@ const Ve = ["tabindex"], be = { class: "pl-dropdown__container" }, Le = { class:
|
|
|
110
110
|
e.code === "Enter" && (o.open = !0);
|
|
111
111
|
return;
|
|
112
112
|
}
|
|
113
|
-
e.code === "Escape" && (o.open = !1, (
|
|
114
|
-
const p =
|
|
113
|
+
e.code === "Escape" && (o.open = !1, (A = d.value) == null || A.focus());
|
|
114
|
+
const p = S.value, { length: m } = p;
|
|
115
115
|
if (!m)
|
|
116
116
|
return;
|
|
117
|
-
e.code === "Enter" && O((
|
|
118
|
-
const
|
|
119
|
-
o.activeIndex = p[
|
|
117
|
+
e.code === "Enter" && O((B = p.find((I) => I.index === a)) == null ? void 0 : B.value);
|
|
118
|
+
const ne = p.findIndex((I) => I.index === a) ?? -1, re = e.code === "ArrowDown" ? 1 : e.code === "ArrowUp" ? -1 : 0, le = Math.abs(ne + re + m) % m;
|
|
119
|
+
o.activeIndex = p[le].index ?? -1;
|
|
120
120
|
};
|
|
121
|
-
return
|
|
121
|
+
return ye(d), D(() => n.modelValue, H, { immediate: !0 }), D(
|
|
122
122
|
() => o.open,
|
|
123
123
|
(e) => {
|
|
124
124
|
var t;
|
|
125
|
-
return e ? (t =
|
|
125
|
+
return e ? (t = w.value) == null ? void 0 : t.focus() : "";
|
|
126
126
|
}
|
|
127
|
-
),
|
|
127
|
+
), de(() => {
|
|
128
128
|
var e;
|
|
129
|
-
o.search, o.activeIndex >= 0 && o.open && ((e =
|
|
129
|
+
o.search, o.activeIndex >= 0 && o.open && ((e = g.value) == null || e.scrollIntoActive());
|
|
130
130
|
}), (e, t) => (l(), v("div", {
|
|
131
131
|
class: "pl-dropdown__envelope",
|
|
132
|
-
onClick:
|
|
132
|
+
onClick: Y
|
|
133
133
|
}, [
|
|
134
134
|
f("div", {
|
|
135
135
|
ref_key: "rootRef",
|
|
136
136
|
ref: d,
|
|
137
|
-
tabindex:
|
|
138
|
-
class:
|
|
139
|
-
onKeydown:
|
|
140
|
-
onFocusout:
|
|
137
|
+
tabindex: J.value,
|
|
138
|
+
class: ce(["pl-dropdown", { open: o.open, error: r.error || r.errorStatus, disabled: k.value }]),
|
|
139
|
+
onKeydown: te,
|
|
140
|
+
onFocusout: oe
|
|
141
141
|
}, [
|
|
142
|
-
f("div",
|
|
143
|
-
f("div",
|
|
144
|
-
|
|
142
|
+
f("div", Le, [
|
|
143
|
+
f("div", Ce, [
|
|
144
|
+
ue(f("input", {
|
|
145
145
|
ref_key: "input",
|
|
146
|
-
ref:
|
|
146
|
+
ref: w,
|
|
147
147
|
"onUpdate:modelValue": t[0] || (t[0] = (a) => o.search = a),
|
|
148
148
|
type: "text",
|
|
149
149
|
tabindex: "-1",
|
|
150
150
|
disabled: k.value,
|
|
151
|
-
placeholder:
|
|
151
|
+
placeholder: U.value,
|
|
152
152
|
spellcheck: "false",
|
|
153
153
|
autocomplete: "chrome-off",
|
|
154
|
-
onFocus:
|
|
155
|
-
}, null, 40,
|
|
156
|
-
[
|
|
154
|
+
onFocus: ee
|
|
155
|
+
}, null, 40, Ee), [
|
|
156
|
+
[pe, o.search]
|
|
157
157
|
]),
|
|
158
|
-
o.open ? c("", !0) : (l(), v("div",
|
|
159
|
-
|
|
160
|
-
default:
|
|
161
|
-
|
|
158
|
+
o.open ? c("", !0) : (l(), v("div", Re, [
|
|
159
|
+
$(ke, null, {
|
|
160
|
+
default: z(() => [
|
|
161
|
+
fe(h(R.value), 1)
|
|
162
162
|
]),
|
|
163
163
|
_: 1
|
|
164
164
|
})
|
|
165
165
|
])),
|
|
166
|
-
f("div",
|
|
167
|
-
|
|
166
|
+
f("div", Se, [
|
|
167
|
+
V.value ? (l(), u(s(F), {
|
|
168
168
|
key: 0,
|
|
169
169
|
name: "loading"
|
|
170
170
|
})) : c("", !0),
|
|
171
|
-
|
|
171
|
+
r.clearable && K.value ? (l(), u(s(_), {
|
|
172
172
|
key: 1,
|
|
173
173
|
class: "clear",
|
|
174
174
|
name: "delete-clear",
|
|
175
|
-
onClick:
|
|
175
|
+
onClick: T(X, ["stop"])
|
|
176
176
|
})) : c("", !0),
|
|
177
|
-
|
|
177
|
+
M(e.$slots, "append"),
|
|
178
178
|
f("div", {
|
|
179
179
|
class: "pl-dropdown__arrow-wrapper",
|
|
180
|
-
onClick:
|
|
180
|
+
onClick: T(Z, ["stop"])
|
|
181
181
|
}, [
|
|
182
|
-
|
|
182
|
+
r.arrowIconLarge ? (l(), u(s(F), {
|
|
183
183
|
key: 0,
|
|
184
|
-
name:
|
|
184
|
+
name: r.arrowIconLarge,
|
|
185
185
|
class: "arrow-icon"
|
|
186
|
-
}, null, 8, ["name"])) :
|
|
186
|
+
}, null, 8, ["name"])) : r.arrowIcon ? (l(), u(s(_), {
|
|
187
187
|
key: 1,
|
|
188
|
-
name:
|
|
188
|
+
name: r.arrowIcon,
|
|
189
189
|
class: "arrow-icon"
|
|
190
|
-
}, null, 8, ["name"])) : (l(), u(
|
|
190
|
+
}, null, 8, ["name"])) : (l(), u(s(_), {
|
|
191
191
|
key: 2,
|
|
192
192
|
name: "chevron-down",
|
|
193
193
|
class: "arrow-icon arrow-icon-default"
|
|
@@ -195,44 +195,44 @@ const Ve = ["tabindex"], be = { class: "pl-dropdown__container" }, Le = { class:
|
|
|
195
195
|
])
|
|
196
196
|
])
|
|
197
197
|
]),
|
|
198
|
-
|
|
199
|
-
|
|
198
|
+
r.label ? (l(), v("label", Oe, [
|
|
199
|
+
r.required ? (l(), u(s(Ie), {
|
|
200
200
|
key: 0,
|
|
201
|
-
uri:
|
|
201
|
+
uri: s(me)
|
|
202
202
|
}, null, 8, ["uri"])) : c("", !0),
|
|
203
|
-
f("span", null, h(
|
|
204
|
-
e.$slots.tooltip ? (l(), u(
|
|
203
|
+
f("span", null, h(r.label), 1),
|
|
204
|
+
e.$slots.tooltip ? (l(), u(s(xe), {
|
|
205
205
|
key: 1,
|
|
206
206
|
class: "info",
|
|
207
207
|
position: "top"
|
|
208
208
|
}, {
|
|
209
|
-
tooltip:
|
|
210
|
-
|
|
209
|
+
tooltip: z(() => [
|
|
210
|
+
M(e.$slots, "tooltip")
|
|
211
211
|
]),
|
|
212
212
|
_: 3
|
|
213
213
|
})) : c("", !0)
|
|
214
214
|
])) : c("", !0),
|
|
215
|
-
o.open ? (l(), u(
|
|
215
|
+
o.open ? (l(), u(_e, {
|
|
216
216
|
key: 1,
|
|
217
217
|
ref_key: "optionListRef",
|
|
218
|
-
ref:
|
|
218
|
+
ref: g,
|
|
219
219
|
"root-ref": d.value,
|
|
220
|
-
groups:
|
|
221
|
-
rest:
|
|
222
|
-
"option-size":
|
|
223
|
-
"select-option":
|
|
220
|
+
groups: s(W),
|
|
221
|
+
rest: s(j),
|
|
222
|
+
"option-size": r.optionSize,
|
|
223
|
+
"select-option": Q
|
|
224
224
|
}, null, 8, ["root-ref", "groups", "rest", "option-size"])) : c("", !0),
|
|
225
|
-
|
|
225
|
+
$(ge, {
|
|
226
226
|
class: "pl-dropdown__contour",
|
|
227
|
-
"group-position":
|
|
227
|
+
"group-position": r.groupPosition
|
|
228
228
|
}, null, 8, ["group-position"])
|
|
229
229
|
])
|
|
230
230
|
], 42, Ve),
|
|
231
|
-
|
|
231
|
+
C.value ? (l(), v("div", Ae, h(C.value), 1)) : V.value && r.loadingOptionsHelper ? (l(), v("div", Be, h(r.loadingOptionsHelper), 1)) : r.helper ? (l(), v("div", Pe, h(r.helper), 1)) : c("", !0)
|
|
232
232
|
]));
|
|
233
233
|
}
|
|
234
234
|
});
|
|
235
235
|
export {
|
|
236
|
-
|
|
236
|
+
eo as default
|
|
237
237
|
};
|
|
238
238
|
//# sourceMappingURL=PlDropdown.vue.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlDropdown.vue.js","sources":["../../../src/components/PlDropdown/PlDropdown.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting one value from a list of options\n */\nexport default {\n name: 'PlDropdown',\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport { computed, reactive, ref, unref, useTemplateRef, watch, watchPostEffect } from 'vue';\nimport SvgRequired from '../../assets/images/required.svg?raw';\nimport { getErrorMessage } from '../../helpers/error.ts';\nimport { tap } from '../../helpers/functions';\nimport { deepEqual } from '../../helpers/objects';\nimport { normalizeListOptions } from '../../helpers/utils';\nimport type { ListOption, ListOptionNormalized, MaskIconName16, MaskIconName24 } from '../../types';\nimport DoubleContour from '../../utils/DoubleContour.vue';\nimport { useLabelNotch } from '../../utils/useLabelNotch';\nimport LongText from '../LongText.vue';\nimport { PlIcon16 } from '../PlIcon16';\nimport { PlIcon24 } from '../PlIcon24';\nimport { PlSvg } from '../PlSvg';\nimport { PlTooltip } from '../PlTooltip';\nimport OptionList from './OptionList.vue';\nimport './pl-dropdown.scss';\nimport type { LOption } from './types';\nimport { useGroupBy } from './useGroupBy';\n\nconst emit = defineEmits<{\n /**\n * Emitted when the model value is updated.\n */\n (e: 'update:modelValue', value: M | undefined): void;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected value of the dropdown.\n */\n modelValue: M;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<ListOption<M>[]>;\n /**\n * A helper text displayed below the dropdown when there are no errors (optional).\n */\n helper?: string;\n /**\n * A helper text displayed below the dropdown when there are no options yet or options is undefined (optional).\n */\n loadingOptionsHelper?: string;\n /**\n * Error message displayed below the dropdown (optional)\n */\n error?: unknown;\n /**\n * Shows red border even without an error message\n */\n errorStatus?: boolean;\n /**\n * Placeholder text shown when no value is selected.\n */\n placeholder?: string;\n /**\n * Enables a button to clear the selected value (default: false)\n */\n clearable?: boolean;\n /**\n * If `true`, the dropdown component is marked as required.\n */\n required?: boolean;\n /**\n * If `true`, the dropdown component is disabled and cannot be interacted with.\n */\n disabled?: boolean;\n /**\n * Custom icon (16px) class for the dropdown arrow (optional)\n */\n arrowIcon?: MaskIconName16;\n /**\n * Custom icon (24px) class for the dropdown arrow (optional)\n */\n arrowIconLarge?: MaskIconName24;\n /**\n * Option list item size\n */\n optionSize?: 'small' | 'medium';\n /**\n * Makes some of corners not rounded\n * */\n groupPosition?: 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'middle';\n }>(),\n {\n label: '',\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n showErrorMessage: true,\n placeholder: '...',\n clearable: false,\n required: false,\n disabled: false,\n arrowIcon: undefined,\n arrowIconLarge: undefined,\n optionSize: 'small',\n options: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = ref<HTMLInputElement | undefined>();\n\nconst optionListRef = useTemplateRef<InstanceType<typeof OptionList>>('optionListRef');\n\nconst data = reactive({\n search: '',\n activeIndex: -1,\n open: false,\n optionsHeight: 0,\n});\n\nconst findActiveIndex = () =>\n tap(\n orderedRef.value.findIndex((o) => deepEqual(o.value, props.modelValue)),\n (v) => (v < 0 ? 0 : v),\n );\n\nconst updateActive = () => (data.activeIndex = findActiveIndex());\n\nconst isLoadingOptions = computed(() => {\n return props.options === undefined;\n});\n\nconst isDisabled = computed(() => {\n if (isLoadingOptions.value) {\n return true;\n }\n\n return props.disabled;\n});\n\nconst selectedIndex = computed(() => {\n return (props.options ?? []).findIndex((o) => deepEqual(o.value, props.modelValue));\n});\n\nconst computedError = computed(() => {\n if (isLoadingOptions.value) {\n return undefined;\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (props.modelValue !== undefined && selectedIndex.value === -1) {\n return 'The selected value is not one of the options';\n }\n\n return undefined;\n});\n\nconst optionsRef = computed<LOption<M>[]>(() =>\n normalizeListOptions(props.options ?? []).map((opt, index) => ({\n ...opt,\n index,\n isSelected: index === selectedIndex.value,\n isActive: index === data.activeIndex,\n })),\n);\n\nconst textValue = computed(() => {\n const options = unref(optionsRef);\n\n const item: ListOption | undefined = options.find((o) => deepEqual(o.value, props.modelValue));\n\n return item?.label || props.modelValue; // @todo show inner value?\n});\n\nconst computedPlaceholder = computed(() => {\n if (!data.open && props.modelValue !== undefined) {\n return '';\n }\n\n return props.modelValue ? String(textValue.value) : props.placeholder;\n});\n\nconst hasValue = computed(() => {\n return props.modelValue !== undefined && props.modelValue !== null;\n});\n\nconst filteredRef = computed(() => {\n const options = optionsRef.value;\n\n if (data.search) {\n return options.filter((o: ListOptionNormalized) => {\n const search = data.search.toLowerCase();\n\n if (o.label.toLowerCase().includes(search)) {\n return true;\n }\n\n if (o.description && o.description.toLowerCase().includes(search)) {\n return true;\n }\n\n if (typeof o.value === 'string') {\n return o.value.toLowerCase().includes(search);\n }\n\n return o.value === data.search;\n });\n }\n\n return options;\n});\n\nconst { orderedRef, groupsRef, restRef } = useGroupBy(filteredRef, 'group');\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : '0'));\n\nconst selectOption = (v: M | undefined) => {\n emit('update:modelValue', v);\n data.search = '';\n data.open = false;\n rootRef?.value?.focus();\n};\n\nconst selectOptionWrapper = (v: unknown) => {\n selectOption(v as M | undefined);\n};\n\nconst clear = () => emit('update:modelValue', undefined);\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleOpen = () => {\n data.open = !data.open;\n if (!data.open) {\n data.search = '';\n }\n};\n\nconst onInputFocus = () => (data.open = true);\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !optionListRef.value?.listRef?.contains(relatedTarget)) {\n data.search = '';\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n if (!['ArrowDown', 'ArrowUp', 'Enter', 'Escape'].includes(e.code)) {\n return;\n } else {\n e.preventDefault();\n }\n\n const { open, activeIndex } = data;\n\n if (!open) {\n if (e.code === 'Enter') {\n data.open = true;\n }\n return;\n }\n\n if (e.code === 'Escape') {\n data.open = false;\n rootRef.value?.focus();\n }\n\n const ordered = orderedRef.value;\n\n const { length } = ordered;\n\n if (!length) {\n return;\n }\n\n if (e.code === 'Enter') {\n selectOption(ordered.find((it) => it.index === activeIndex)?.value);\n }\n\n const localIndex = ordered.findIndex((it) => it.index === activeIndex) ?? -1;\n\n const delta = e.code === 'ArrowDown' ? 1 : e.code === 'ArrowUp' ? -1 : 0;\n\n const newIndex = Math.abs(localIndex + delta + length) % length;\n\n data.activeIndex = ordered[newIndex].index ?? -1;\n};\n\nuseLabelNotch(rootRef);\n\nwatch(() => props.modelValue, updateActive, { immediate: true });\n\nwatch(\n () => data.open,\n (open) => (open ? input.value?.focus() : ''),\n);\n\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n data.search; // to watch\n\n if (data.activeIndex >= 0 && data.open) {\n optionListRef.value?.scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"pl-dropdown__envelope\" @click=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-dropdown\"\n :class=\"{ open: data.open, error: error || errorStatus, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-dropdown__container\">\n <div class=\"pl-dropdown__field\">\n <input\n ref=\"input\"\n v-model=\"data.search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"computedPlaceholder\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"onInputFocus\"\n />\n\n <div v-if=\"!data.open\" class=\"input-value\">\n <LongText> {{ textValue }} </LongText>\n </div>\n\n <div class=\"pl-dropdown__controls\">\n <PlIcon24 v-if=\"isLoadingOptions\" name=\"loading\" />\n <PlIcon16 v-if=\"clearable && hasValue\" class=\"clear\" name=\"delete-clear\" @click.stop=\"clear\" />\n <slot name=\"append\" />\n <div class=\"pl-dropdown__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <PlIcon24 v-if=\"arrowIconLarge\" :name=\"arrowIconLarge\" class=\"arrow-icon\" />\n <PlIcon16 v-else-if=\"arrowIcon\" :name=\"arrowIcon\" class=\"arrow-icon\" />\n <PlIcon16 v-else name=\"chevron-down\" class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" />\n <span>{{ label }}</span>\n <PlTooltip v-if=\"$slots.tooltip\" class=\"info\" position=\"top\">\n <template #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlTooltip>\n </label>\n <OptionList\n v-if=\"data.open\"\n ref=\"optionListRef\"\n :root-ref=\"rootRef!\"\n :groups=\"groupsRef\"\n :rest=\"restRef\"\n :option-size=\"optionSize\"\n :select-option=\"selectOptionWrapper\"\n />\n <DoubleContour class=\"pl-dropdown__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-dropdown__error\">{{ computedError }}</div>\n <div v-else-if=\"isLoadingOptions && loadingOptionsHelper\" class=\"pl-dropdown__helper\">{{ loadingOptionsHelper }}</div>\n <div v-else-if=\"helper\" class=\"pl-dropdown__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"names":["__default__","emit","__emit","props","__props","rootRef","ref","input","optionListRef","useTemplateRef","data","reactive","findActiveIndex","tap","orderedRef","o","deepEqual","v","updateActive","isLoadingOptions","computed","isDisabled","selectedIndex","computedError","getErrorMessage","optionsRef","normalizeListOptions","opt","index","textValue","item","unref","computedPlaceholder","hasValue","filteredRef","options","search","groupsRef","restRef","useGroupBy","tabindex","selectOption","_a","selectOptionWrapper","clear","setFocusOnInput","toggleOpen","onInputFocus","onFocusOut","event","relatedTarget","_c","_b","handleKeydown","open","activeIndex","ordered","length","it","localIndex","delta","newIndex","useLabelNotch","watch","watchPostEffect","_createElementBlock","_createElementVNode","_normalizeClass","_hoisted_2","_hoisted_3","_cache","$event","_vModelText","_openBlock","_hoisted_5","_createVNode","LongText","_hoisted_6","_createBlock","_unref","PlIcon24","PlIcon16","_renderSlot","_ctx","_hoisted_7","PlSvg","SvgRequired","$slots","PlTooltip","OptionList","DoubleContour","_hoisted_8","_toDisplayString","_hoisted_9","_hoisted_10"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlDropdown.vue.js","sources":["../../../src/components/PlDropdown/PlDropdown.vue"],"sourcesContent":["<script lang=\"ts\">\n/**\n * A component for selecting one value from a list of options\n */\nexport default {\n name: 'PlDropdown',\n};\n</script>\n\n<script lang=\"ts\" setup generic=\"M = unknown\">\nimport { computed, reactive, ref, unref, useTemplateRef, watch, watchPostEffect } from 'vue';\nimport SvgRequired from '../../assets/images/required.svg?raw';\nimport { getErrorMessage } from '../../helpers/error.ts';\nimport { tap } from '../../helpers/functions';\nimport { deepEqual } from '../../helpers/objects';\nimport { normalizeListOptions } from '../../helpers/utils';\nimport type { ListOption, ListOptionNormalized, MaskIconName16, MaskIconName24 } from '../../types';\nimport DoubleContour from '../../utils/DoubleContour.vue';\nimport { useLabelNotch } from '../../utils/useLabelNotch';\nimport LongText from '../LongText.vue';\nimport { PlIcon16 } from '../PlIcon16';\nimport { PlIcon24 } from '../PlIcon24';\nimport { PlSvg } from '../PlSvg';\nimport { PlTooltip } from '../PlTooltip';\nimport OptionList from './OptionList.vue';\nimport './pl-dropdown.scss';\nimport type { LOption } from './types';\nimport { useGroupBy } from './useGroupBy';\n\nconst emit = defineEmits<{\n /**\n * Emitted when the model value is updated.\n */\n (e: 'update:modelValue', value: M | undefined): void;\n}>();\n\nconst props = withDefaults(\n defineProps<{\n /**\n * The current selected value of the dropdown.\n */\n modelValue: M;\n /**\n * The label text for the dropdown field (optional)\n */\n label?: string;\n /**\n * List of available options for the dropdown\n */\n options?: Readonly<ListOption<M>[]>;\n /**\n * A helper text displayed below the dropdown when there are no errors (optional).\n */\n helper?: string;\n /**\n * A helper text displayed below the dropdown when there are no options yet or options is undefined (optional).\n */\n loadingOptionsHelper?: string;\n /**\n * Error message displayed below the dropdown (optional)\n */\n error?: unknown;\n /**\n * Shows red border even without an error message\n */\n errorStatus?: boolean;\n /**\n * Placeholder text shown when no value is selected.\n */\n placeholder?: string;\n /**\n * Enables a button to clear the selected value (default: false)\n */\n clearable?: boolean;\n /**\n * If `true`, the dropdown component is marked as required.\n */\n required?: boolean;\n /**\n * If `true`, the dropdown component is disabled and cannot be interacted with.\n */\n disabled?: boolean;\n /**\n * Custom icon (16px) class for the dropdown arrow (optional)\n */\n arrowIcon?: MaskIconName16;\n /**\n * Custom icon (24px) class for the dropdown arrow (optional)\n */\n arrowIconLarge?: MaskIconName24;\n /**\n * Option list item size\n */\n optionSize?: 'small' | 'medium';\n /**\n * Makes some of corners not rounded\n * */\n groupPosition?: 'top' | 'bottom' | 'left' | 'right' | 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right' | 'middle';\n }>(),\n {\n label: '',\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n showErrorMessage: true,\n placeholder: '...',\n clearable: false,\n required: false,\n disabled: false,\n arrowIcon: undefined,\n arrowIconLarge: undefined,\n optionSize: 'small',\n options: undefined,\n groupPosition: undefined,\n },\n);\n\nconst rootRef = ref<HTMLElement | undefined>();\nconst input = ref<HTMLInputElement | undefined>();\n\nconst optionListRef = useTemplateRef<InstanceType<typeof OptionList>>('optionListRef');\n\nconst data = reactive({\n search: '',\n activeIndex: -1,\n open: false,\n optionsHeight: 0,\n});\n\nconst findActiveIndex = () =>\n tap(\n orderedRef.value.findIndex((o) => deepEqual(o.value, props.modelValue)),\n (v) => (v < 0 ? 0 : v),\n );\n\nconst updateActive = () => (data.activeIndex = findActiveIndex());\n\nconst isLoadingOptions = computed(() => {\n return props.options === undefined;\n});\n\n/**\n * Loading spinner should not be shown when the dropdown is explicitly disabled,\n * even if options are undefined. The disabled state takes precedence.\n */\nconst showLoadingSpinner = computed(() => {\n return !props.disabled && isLoadingOptions.value;\n});\n\nconst isDisabled = computed(() => {\n if (isLoadingOptions.value) {\n return true;\n }\n\n return props.disabled;\n});\n\nconst selectedIndex = computed(() => {\n return (props.options ?? []).findIndex((o) => deepEqual(o.value, props.modelValue));\n});\n\nconst computedError = computed(() => {\n if (isLoadingOptions.value) {\n return undefined;\n }\n\n if (props.error) {\n return getErrorMessage(props.error);\n }\n\n if (props.modelValue !== undefined && selectedIndex.value === -1) {\n return 'The selected value is not one of the options';\n }\n\n return undefined;\n});\n\nconst optionsRef = computed<LOption<M>[]>(() =>\n normalizeListOptions(props.options ?? []).map((opt, index) => ({\n ...opt,\n index,\n isSelected: index === selectedIndex.value,\n isActive: index === data.activeIndex,\n })),\n);\n\nconst textValue = computed(() => {\n const options = unref(optionsRef);\n\n const item: ListOption | undefined = options.find((o) => deepEqual(o.value, props.modelValue));\n\n return item?.label || props.modelValue; // @todo show inner value?\n});\n\nconst computedPlaceholder = computed(() => {\n if (!data.open && props.modelValue !== undefined) {\n return '';\n }\n\n return props.modelValue ? String(textValue.value) : props.placeholder;\n});\n\nconst hasValue = computed(() => {\n return props.modelValue !== undefined && props.modelValue !== null;\n});\n\nconst filteredRef = computed(() => {\n const options = optionsRef.value;\n\n if (data.search) {\n return options.filter((o: ListOptionNormalized) => {\n const search = data.search.toLowerCase();\n\n if (o.label.toLowerCase().includes(search)) {\n return true;\n }\n\n if (o.description && o.description.toLowerCase().includes(search)) {\n return true;\n }\n\n if (typeof o.value === 'string') {\n return o.value.toLowerCase().includes(search);\n }\n\n return o.value === data.search;\n });\n }\n\n return options;\n});\n\nconst { orderedRef, groupsRef, restRef } = useGroupBy(filteredRef, 'group');\n\nconst tabindex = computed(() => (isDisabled.value ? undefined : '0'));\n\nconst selectOption = (v: M | undefined) => {\n emit('update:modelValue', v);\n data.search = '';\n data.open = false;\n rootRef?.value?.focus();\n};\n\nconst selectOptionWrapper = (v: unknown) => {\n selectOption(v as M | undefined);\n};\n\nconst clear = () => emit('update:modelValue', undefined);\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleOpen = () => {\n data.open = !data.open;\n if (!data.open) {\n data.search = '';\n }\n};\n\nconst onInputFocus = () => (data.open = true);\n\nconst onFocusOut = (event: FocusEvent) => {\n const relatedTarget = event.relatedTarget as Node | null;\n\n if (!rootRef.value?.contains(relatedTarget) && !optionListRef.value?.listRef?.contains(relatedTarget)) {\n data.search = '';\n data.open = false;\n }\n};\n\nconst handleKeydown = (e: { code: string; preventDefault(): void }) => {\n if (!['ArrowDown', 'ArrowUp', 'Enter', 'Escape'].includes(e.code)) {\n return;\n } else {\n e.preventDefault();\n }\n\n const { open, activeIndex } = data;\n\n if (!open) {\n if (e.code === 'Enter') {\n data.open = true;\n }\n return;\n }\n\n if (e.code === 'Escape') {\n data.open = false;\n rootRef.value?.focus();\n }\n\n const ordered = orderedRef.value;\n\n const { length } = ordered;\n\n if (!length) {\n return;\n }\n\n if (e.code === 'Enter') {\n selectOption(ordered.find((it) => it.index === activeIndex)?.value);\n }\n\n const localIndex = ordered.findIndex((it) => it.index === activeIndex) ?? -1;\n\n const delta = e.code === 'ArrowDown' ? 1 : e.code === 'ArrowUp' ? -1 : 0;\n\n const newIndex = Math.abs(localIndex + delta + length) % length;\n\n data.activeIndex = ordered[newIndex].index ?? -1;\n};\n\nuseLabelNotch(rootRef);\n\nwatch(() => props.modelValue, updateActive, { immediate: true });\n\nwatch(\n () => data.open,\n (open) => (open ? input.value?.focus() : ''),\n);\n\nwatchPostEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n data.search; // to watch\n\n if (data.activeIndex >= 0 && data.open) {\n optionListRef.value?.scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"pl-dropdown__envelope\" @click=\"setFocusOnInput\">\n <div\n ref=\"rootRef\"\n :tabindex=\"tabindex\"\n class=\"pl-dropdown\"\n :class=\"{ open: data.open, error: error || errorStatus, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"pl-dropdown__container\">\n <div class=\"pl-dropdown__field\">\n <input\n ref=\"input\"\n v-model=\"data.search\"\n type=\"text\"\n tabindex=\"-1\"\n :disabled=\"isDisabled\"\n :placeholder=\"computedPlaceholder\"\n spellcheck=\"false\"\n autocomplete=\"chrome-off\"\n @focus=\"onInputFocus\"\n />\n\n <div v-if=\"!data.open\" class=\"input-value\">\n <LongText> {{ textValue }} </LongText>\n </div>\n\n <div class=\"pl-dropdown__controls\">\n <PlIcon24 v-if=\"showLoadingSpinner\" name=\"loading\" />\n <PlIcon16 v-if=\"clearable && hasValue\" class=\"clear\" name=\"delete-clear\" @click.stop=\"clear\" />\n <slot name=\"append\" />\n <div class=\"pl-dropdown__arrow-wrapper\" @click.stop=\"toggleOpen\">\n <PlIcon24 v-if=\"arrowIconLarge\" :name=\"arrowIconLarge\" class=\"arrow-icon\" />\n <PlIcon16 v-else-if=\"arrowIcon\" :name=\"arrowIcon\" class=\"arrow-icon\" />\n <PlIcon16 v-else name=\"chevron-down\" class=\"arrow-icon arrow-icon-default\" />\n </div>\n </div>\n </div>\n <label v-if=\"label\">\n <PlSvg v-if=\"required\" :uri=\"SvgRequired\" />\n <span>{{ label }}</span>\n <PlTooltip v-if=\"$slots.tooltip\" class=\"info\" position=\"top\">\n <template #tooltip>\n <slot name=\"tooltip\" />\n </template>\n </PlTooltip>\n </label>\n <OptionList\n v-if=\"data.open\"\n ref=\"optionListRef\"\n :root-ref=\"rootRef!\"\n :groups=\"groupsRef\"\n :rest=\"restRef\"\n :option-size=\"optionSize\"\n :select-option=\"selectOptionWrapper\"\n />\n <DoubleContour class=\"pl-dropdown__contour\" :group-position=\"groupPosition\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"pl-dropdown__error\">{{ computedError }}</div>\n <div v-else-if=\"showLoadingSpinner && loadingOptionsHelper\" class=\"pl-dropdown__helper\">{{ loadingOptionsHelper }}</div>\n <div v-else-if=\"helper\" class=\"pl-dropdown__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"names":["__default__","emit","__emit","props","__props","rootRef","ref","input","optionListRef","useTemplateRef","data","reactive","findActiveIndex","tap","orderedRef","o","deepEqual","v","updateActive","isLoadingOptions","computed","showLoadingSpinner","isDisabled","selectedIndex","computedError","getErrorMessage","optionsRef","normalizeListOptions","opt","index","textValue","item","unref","computedPlaceholder","hasValue","filteredRef","options","search","groupsRef","restRef","useGroupBy","tabindex","selectOption","_a","selectOptionWrapper","clear","setFocusOnInput","toggleOpen","onInputFocus","onFocusOut","event","relatedTarget","_c","_b","handleKeydown","open","activeIndex","ordered","length","it","localIndex","delta","newIndex","useLabelNotch","watch","watchPostEffect","_createElementBlock","_createElementVNode","_normalizeClass","_hoisted_2","_hoisted_3","_cache","$event","_vModelText","_openBlock","_hoisted_5","_createVNode","LongText","_hoisted_6","_createBlock","_unref","PlIcon24","PlIcon16","_renderSlot","_ctx","_hoisted_7","PlSvg","SvgRequired","$slots","PlTooltip","OptionList","DoubleContour","_hoisted_8","_toDisplayString","_hoisted_9","_hoisted_10"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/uikit",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.7.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"resize-observer-polyfill": "^1.5.1",
|
|
33
33
|
"canonicalize": "~2.1.0",
|
|
34
34
|
"@milaboratories/helpers": "1.12.0",
|
|
35
|
-
"@platforma-sdk/model": "1.
|
|
35
|
+
"@platforma-sdk/model": "1.46.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"jsdom": "^25.0.1",
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"yarpm": "^1.2.0",
|
|
41
41
|
"svgo": "^3.3.2",
|
|
42
42
|
"typescript": "~5.6.3",
|
|
43
|
-
"@milaboratories/
|
|
43
|
+
"@milaboratories/eslint-config": "1.0.5",
|
|
44
44
|
"@milaboratories/build-configs": "1.0.8",
|
|
45
|
-
"@milaboratories/ts-
|
|
46
|
-
"@milaboratories/
|
|
45
|
+
"@milaboratories/ts-configs": "1.0.6",
|
|
46
|
+
"@milaboratories/ts-builder": "1.0.5"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"dev": "ts-builder serve --target browser-lib --build-config ./build.browser-lib.config.js",
|
|
@@ -39,11 +39,7 @@ const props = withDefaults(
|
|
|
39
39
|
/**
|
|
40
40
|
* Lambda for requesting of available options for the dropdown by search string.
|
|
41
41
|
*/
|
|
42
|
-
optionsSearch: (
|
|
43
|
-
/**
|
|
44
|
-
* Lambda for requesting of corresponding option for current model value. If empty, optionsSearch is used for this.
|
|
45
|
-
*/
|
|
46
|
-
modelSearch?: (v: NonNullable<M>) => Promise<ListOption<NonNullable<M>>>;
|
|
42
|
+
optionsSearch: (string: string, type: 'value' | 'label') => Promise<ListOption<M>[]>;
|
|
47
43
|
/**
|
|
48
44
|
* The label text for the dropdown field (optional)
|
|
49
45
|
*/
|
|
@@ -301,17 +297,14 @@ const searchDebounced = refDebounced(search, 300, { maxWait: 1000 });
|
|
|
301
297
|
|
|
302
298
|
const optionsRequest = useWatchFetch(() => searchDebounced.value, async (v) => {
|
|
303
299
|
if (v !== null) { // search is null when dropdown is closed;
|
|
304
|
-
return props.optionsSearch(v);
|
|
300
|
+
return props.optionsSearch(v, 'label');
|
|
305
301
|
}
|
|
306
302
|
return undefined;
|
|
307
303
|
});
|
|
308
304
|
|
|
309
305
|
const modelOptionRequest = useWatchFetch(() => model.value, async (v) => {
|
|
310
306
|
if (v != null && !deepEqual(modelOptionRef.value?.value, v)) { // load label for selected value if it was updated from outside the component
|
|
311
|
-
|
|
312
|
-
return props.modelSearch(v);
|
|
313
|
-
}
|
|
314
|
-
return (await props.optionsSearch(String(v)))?.[0];
|
|
307
|
+
return (await props.optionsSearch(String(v), 'value'))?.[0];
|
|
315
308
|
}
|
|
316
309
|
return modelOptionRef.value;
|
|
317
310
|
});
|
|
@@ -65,6 +65,11 @@ const emitModel = (v: M[]) => emit('update:modelValue', v);
|
|
|
65
65
|
|
|
66
66
|
const slots = useSlots();
|
|
67
67
|
|
|
68
|
+
interface OptionsSearch {
|
|
69
|
+
(s: string, type: 'label'): Promise<Readonly<ListOptionBase<M>[]>>;
|
|
70
|
+
(s: M[], type: 'value'): Promise<Readonly<ListOptionBase<M>[]>>;
|
|
71
|
+
}
|
|
72
|
+
|
|
68
73
|
const props = withDefaults(
|
|
69
74
|
defineProps<{
|
|
70
75
|
/**
|
|
@@ -74,11 +79,7 @@ const props = withDefaults(
|
|
|
74
79
|
/**
|
|
75
80
|
* Lambda for requesting of available options for the dropdown by search string.
|
|
76
81
|
*/
|
|
77
|
-
optionsSearch:
|
|
78
|
-
/**
|
|
79
|
-
* Lambda for requesting options that correspond to the current model values.
|
|
80
|
-
*/
|
|
81
|
-
modelSearch: (values: M[]) => Promise<Readonly<ListOptionBase<M>[]>>;
|
|
82
|
+
optionsSearch: OptionsSearch;
|
|
82
83
|
/**
|
|
83
84
|
* Unique identifier for the source of the options, changing it will invalidate the options cache.
|
|
84
85
|
*/
|
|
@@ -170,14 +171,14 @@ const placeholderRef = computed(() => {
|
|
|
170
171
|
const debounce = toRef(props, 'debounce');
|
|
171
172
|
|
|
172
173
|
const searchOptionsRef = useWatchFetch(() => [data.search, data.open, props.sourceId] as const, async ([search, _open]) => {
|
|
173
|
-
return props.optionsSearch(search);
|
|
174
|
+
return props.optionsSearch(search, 'label');
|
|
174
175
|
}, {
|
|
175
176
|
filterWatchResult: ([_search, open]) => open,
|
|
176
177
|
debounce,
|
|
177
178
|
});
|
|
178
179
|
|
|
179
180
|
const modelOptionsRef = useWatchFetch(() => [props.modelValue, props.sourceId] as const, async ([v]) => {
|
|
180
|
-
return props.
|
|
181
|
+
return props.optionsSearch(v, 'value');
|
|
181
182
|
}, {
|
|
182
183
|
debounce,
|
|
183
184
|
});
|
|
@@ -11,12 +11,6 @@ describe('PlAutocompleteMulti', () => {
|
|
|
11
11
|
'modelValue': [1],
|
|
12
12
|
'onUpdate:modelValue': (e) => wrapper.setProps({ modelValue: e }),
|
|
13
13
|
'debounce': 0,
|
|
14
|
-
'modelSearch': async (values) => {
|
|
15
|
-
return [
|
|
16
|
-
{ label: 'Option 1', value: 1 },
|
|
17
|
-
{ label: 'Option 2', value: 2 },
|
|
18
|
-
].filter((v) => values.includes(v.value));
|
|
19
|
-
},
|
|
20
14
|
'optionsSearch': async () => {
|
|
21
15
|
return [
|
|
22
16
|
{ label: 'Option 1', value: 1 },
|
|
@@ -139,6 +139,14 @@ const isLoadingOptions = computed(() => {
|
|
|
139
139
|
return props.options === undefined;
|
|
140
140
|
});
|
|
141
141
|
|
|
142
|
+
/**
|
|
143
|
+
* Loading spinner should not be shown when the dropdown is explicitly disabled,
|
|
144
|
+
* even if options are undefined. The disabled state takes precedence.
|
|
145
|
+
*/
|
|
146
|
+
const showLoadingSpinner = computed(() => {
|
|
147
|
+
return !props.disabled && isLoadingOptions.value;
|
|
148
|
+
});
|
|
149
|
+
|
|
142
150
|
const isDisabled = computed(() => {
|
|
143
151
|
if (isLoadingOptions.value) {
|
|
144
152
|
return true;
|
|
@@ -349,7 +357,7 @@ watchPostEffect(() => {
|
|
|
349
357
|
</div>
|
|
350
358
|
|
|
351
359
|
<div class="pl-dropdown__controls">
|
|
352
|
-
<PlIcon24 v-if="
|
|
360
|
+
<PlIcon24 v-if="showLoadingSpinner" name="loading" />
|
|
353
361
|
<PlIcon16 v-if="clearable && hasValue" class="clear" name="delete-clear" @click.stop="clear" />
|
|
354
362
|
<slot name="append" />
|
|
355
363
|
<div class="pl-dropdown__arrow-wrapper" @click.stop="toggleOpen">
|
|
@@ -381,7 +389,7 @@ watchPostEffect(() => {
|
|
|
381
389
|
</div>
|
|
382
390
|
</div>
|
|
383
391
|
<div v-if="computedError" class="pl-dropdown__error">{{ computedError }}</div>
|
|
384
|
-
<div v-else-if="
|
|
392
|
+
<div v-else-if="showLoadingSpinner && loadingOptionsHelper" class="pl-dropdown__helper">{{ loadingOptionsHelper }}</div>
|
|
385
393
|
<div v-else-if="helper" class="pl-dropdown__helper">{{ helper }}</div>
|
|
386
394
|
</div>
|
|
387
395
|
</template>
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { defineComponent as n, createBlock as r, openBlock as a, Transition as s, withCtx as p, renderSlot as c } from "vue";
|
|
2
|
-
const f = /* @__PURE__ */ n({
|
|
3
|
-
__name: "ExpandTransition",
|
|
4
|
-
setup(l) {
|
|
5
|
-
const t = (e) => {
|
|
6
|
-
e.classList.add("expand-collapse-fix"), e.style.setProperty("--component-height", e.scrollHeight + "px");
|
|
7
|
-
}, o = (e) => {
|
|
8
|
-
e.style.removeProperty("--component-height"), e.classList.remove("expand-collapse-fix");
|
|
9
|
-
};
|
|
10
|
-
return (e, i) => (a(), r(s, {
|
|
11
|
-
name: "expand-collapse",
|
|
12
|
-
onEnter: t,
|
|
13
|
-
onLeave: t,
|
|
14
|
-
onAfterEnter: o,
|
|
15
|
-
onAfterLeave: o
|
|
16
|
-
}, {
|
|
17
|
-
default: p(() => [
|
|
18
|
-
c(e.$slots, "default")
|
|
19
|
-
]),
|
|
20
|
-
_: 3
|
|
21
|
-
}));
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
export {
|
|
25
|
-
f as default
|
|
26
|
-
};
|
|
27
|
-
//# sourceMappingURL=ExpandTransition.vue2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ExpandTransition.vue2.js","sources":["../../../src/components/PlAccordion/ExpandTransition.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nconst onStart = (el: Element) => {\n el.classList.add('expand-collapse-fix');\n (el as HTMLElement).style.setProperty('--component-height', el.scrollHeight + 'px');\n};\n\nconst onAfter = (el: Element) => {\n (el as HTMLElement).style.removeProperty('--component-height');\n el.classList.remove('expand-collapse-fix');\n};\n</script>\n\n<template>\n <Transition name=\"expand-collapse\" @enter=\"onStart\" @leave=\"onStart\" @after-enter=\"onAfter\" @after-leave=\"onAfter\">\n <slot/>\n </Transition>\n</template>\n\n<style>\n.expand-collapse-fix {\n overflow: hidden;\n}\n\n.expand-collapse-enter-active,\n.expand-collapse-leave-active {\n transition:\n height 0.2s ease-in-out,\n opacity 0.2s ease-in-out;\n height: var(--component-height);\n}\n\n.expand-collapse-enter-from,\n.expand-collapse-leave-to {\n opacity: 0.5;\n height: 0;\n}\n</style>\n"],"names":["onStart","el","onAfter","_createBlock","_Transition","_renderSlot","_ctx"],"mappings":";;;;AACA,UAAMA,IAAU,CAACC,MAAgB;AAC/B,MAAAA,EAAG,UAAU,IAAI,qBAAqB,GACrCA,EAAmB,MAAM,YAAY,sBAAsBA,EAAG,eAAe,IAAI;AAAA,IACpF,GAEMC,IAAU,CAACD,MAAgB;AAC9B,MAAAA,EAAmB,MAAM,eAAe,oBAAoB,GAC7DA,EAAG,UAAU,OAAO,qBAAqB;AAAA,IAC3C;2BAIEE,EAEaC,GAAA;AAAA,MAFD,MAAK;AAAA,MAAmB,SAAOJ;AAAA,MAAU,SAAOA;AAAA,MAAU,cAAaE;AAAA,MAAU,cAAaA;AAAA,IAAA;iBACxG,MAAO;AAAA,QAAPG,EAAOC,EAAA,QAAA,SAAA;AAAA,MAAA;;;;;"}
|