@milaboratories/uikit 2.15.28 → 2.15.30
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 +17 -17
- package/.turbo/turbo-formatter$colon$check.log +2 -2
- package/.turbo/turbo-linter$colon$check.log +2 -2
- package/.turbo/turbo-types$colon$check.log +1 -1
- package/CHANGELOG.md +12 -0
- package/dist/components/PlAutocomplete/PlAutocomplete.js.map +1 -1
- package/dist/components/PlAutocomplete/PlAutocomplete.vue.d.ts.map +1 -1
- package/dist/components/PlAutocomplete/PlAutocomplete.vue2.js +90 -87
- package/dist/components/PlAutocomplete/PlAutocomplete.vue2.js.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.js.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue.d.ts.map +1 -1
- package/dist/components/PlDropdown/PlDropdown.vue2.js +76 -71
- package/dist/components/PlDropdown/PlDropdown.vue2.js.map +1 -1
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.js.map +1 -1
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue.d.ts.map +1 -1
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue2.js +69 -62
- package/dist/components/PlDropdownLegacy/PlDropdownLegacy.vue2.js.map +1 -1
- package/package.json +5 -5
- package/src/components/PlAutocomplete/PlAutocomplete.vue +5 -1
- package/src/components/PlDropdown/PlDropdown.vue +10 -1
- package/src/components/PlDropdownLegacy/PlDropdownLegacy.vue +9 -1
|
@@ -6,20 +6,20 @@ import "../PlTooltip/index.js";
|
|
|
6
6
|
import { getErrorMessage as a } from "../../helpers/error.js";
|
|
7
7
|
import o from "../LongText.js";
|
|
8
8
|
import { scrollIntoView as s } from "../../helpers/dom.js";
|
|
9
|
-
import
|
|
9
|
+
import ee from "../PlSvg/PlSvg.js";
|
|
10
10
|
import "../PlSvg/index.js";
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import
|
|
11
|
+
import te from "../PlIcon24/PlIcon24.js";
|
|
12
|
+
import c from "../PlIcon16/PlIcon16.js";
|
|
13
|
+
import l from "../../utils/DoubleContour.js";
|
|
14
14
|
import { useLabelNotch as ne } from "../../utils/useLabelNotch.js";
|
|
15
15
|
import { deepEqual as u } from "../../helpers/objects.js";
|
|
16
16
|
import "../PlIcon16/index.js";
|
|
17
17
|
import "../PlMaskIcon24/index.js";
|
|
18
18
|
import re from "../../assets/images/required.js";
|
|
19
19
|
/* empty css */
|
|
20
|
-
import { Fragment as
|
|
20
|
+
import { Fragment as ie, computed as d, createBlock as f, createCommentVNode as p, createElementBlock as m, createElementVNode as h, createTextVNode as ae, createVNode as g, defineComponent as _, normalizeClass as v, openBlock as y, reactive as b, ref as x, renderList as S, renderSlot as C, toDisplayString as w, unref as T, useSlots as oe, vModelText as se, watch as E, watchPostEffect as ce, withCtx as D, withDirectives as le, withModifiers as O } from "vue";
|
|
21
21
|
//#region src/components/PlDropdownLegacy/PlDropdownLegacy.vue?vue&type=script&setup=true&lang.ts
|
|
22
|
-
var ue = { class: "ui-dropdown__envelope" }, de = ["tabindex"], fe = { class: "ui-dropdown__container" }, pe =
|
|
22
|
+
var ue = { class: "ui-dropdown__envelope" }, de = ["tabindex"], fe = { class: "ui-dropdown__container" }, pe = ["title"], k = ["disabled", "placeholder"], A = { class: "ui-dropdown__controls" }, j = { key: 0 }, M = {
|
|
23
23
|
key: 0,
|
|
24
24
|
class: "nothing-found"
|
|
25
25
|
}, N = {
|
|
@@ -31,7 +31,7 @@ var ue = { class: "ui-dropdown__envelope" }, de = ["tabindex"], fe = { class: "u
|
|
|
31
31
|
}, F = {
|
|
32
32
|
key: 2,
|
|
33
33
|
class: "ui-dropdown__helper"
|
|
34
|
-
}, I = /* @__PURE__ */
|
|
34
|
+
}, I = /* @__PURE__ */ _({
|
|
35
35
|
name: "PlDropdown",
|
|
36
36
|
props: {
|
|
37
37
|
modelValue: {},
|
|
@@ -58,37 +58,41 @@ var ue = { class: "ui-dropdown__envelope" }, de = ["tabindex"], fe = { class: "u
|
|
|
58
58
|
optionSize: { default: "small" }
|
|
59
59
|
},
|
|
60
60
|
emits: ["update:modelValue"],
|
|
61
|
-
setup(
|
|
62
|
-
let L = I, R =
|
|
61
|
+
setup(_, { emit: I }) {
|
|
62
|
+
let L = I, R = _, z = oe(), B = x(), V = x(), H = x(), U = b({
|
|
63
63
|
search: "",
|
|
64
64
|
activeIndex: -1,
|
|
65
65
|
open: !1
|
|
66
|
-
}), me = () => t(X.value.findIndex((e) => u(e.value, R.modelValue)), (e) => e < 0 ? 0 : e), he = () => U.activeIndex = me(), W =
|
|
66
|
+
}), me = () => t(X.value.findIndex((e) => u(e.value, R.modelValue)), (e) => e < 0 ? 0 : e), he = () => U.activeIndex = me(), W = d(() => R.options === void 0), G = d(() => W.value ? !0 : R.disabled), K = d(() => (R.options ?? []).findIndex((e) => u(e.value, R.modelValue))), q = d(() => {
|
|
67
67
|
if (!W.value) {
|
|
68
68
|
if (R.error) return a(R.error);
|
|
69
69
|
if (R.modelValue !== void 0 && K.value === -1) return "The selected value is not one of the options";
|
|
70
70
|
}
|
|
71
|
-
}), J =
|
|
71
|
+
}), J = d(() => r(R.options ?? []).map((e, t) => ({
|
|
72
72
|
...e,
|
|
73
73
|
index: t,
|
|
74
74
|
isSelected: t === K.value,
|
|
75
75
|
isActive: t === U.activeIndex
|
|
76
|
-
}))), Y =
|
|
76
|
+
}))), Y = d(() => T(J).find((e) => u(e.value, R.modelValue))?.label || R.modelValue), ge = d(() => {
|
|
77
|
+
if (U.open) return;
|
|
78
|
+
let e = Y.value;
|
|
79
|
+
return e != null && e !== "" ? String(e) : void 0;
|
|
80
|
+
}), _e = d(() => !U.open && R.modelValue ? "" : R.modelValue ? String(Y.value) : R.placeholder), ve = d(() => R.modelValue !== void 0 && R.modelValue !== null), X = d(() => {
|
|
77
81
|
let e = J.value;
|
|
78
82
|
return U.search ? e.filter((e) => {
|
|
79
83
|
let t = U.search.toLowerCase();
|
|
80
84
|
return e.label.toLowerCase().includes(t) || e.description && e.description.toLowerCase().includes(t) ? !0 : typeof e.value == "string" ? e.value.toLowerCase().includes(t) : e.value === U.search;
|
|
81
85
|
}) : e;
|
|
82
|
-
}), Z =
|
|
86
|
+
}), Z = d(() => G.value ? void 0 : "0"), Q = (e) => {
|
|
83
87
|
L("update:modelValue", e), U.search = "", U.open = !1, B?.value?.focus();
|
|
84
|
-
},
|
|
88
|
+
}, ye = () => L("update:modelValue", void 0), be = () => H.value?.focus(), $ = () => U.open = !U.open, xe = () => U.open = !0, Se = (e) => {
|
|
85
89
|
B?.value?.contains(e.relatedTarget) || (U.search = "", U.open = !1);
|
|
86
|
-
},
|
|
90
|
+
}, Ce = () => {
|
|
87
91
|
let e = V.value;
|
|
88
92
|
e && n(e.querySelector(".hovered-item"), (t) => {
|
|
89
93
|
s(e, t);
|
|
90
94
|
});
|
|
91
|
-
},
|
|
95
|
+
}, we = (e) => {
|
|
92
96
|
if ([
|
|
93
97
|
"ArrowDown",
|
|
94
98
|
"ArrowUp",
|
|
@@ -102,99 +106,102 @@ var ue = { class: "ui-dropdown__envelope" }, de = ["tabindex"], fe = { class: "u
|
|
|
102
106
|
return;
|
|
103
107
|
}
|
|
104
108
|
e.code === "Escape" && (U.open = !1, B.value?.focus());
|
|
105
|
-
let r =
|
|
109
|
+
let r = T(X), { length: i } = r;
|
|
106
110
|
if (!i) return;
|
|
107
111
|
e.code === "Enter" && Q(r.find((e) => e.index === n)?.value);
|
|
108
112
|
let a = r.findIndex((e) => e.index === n) ?? -1, o = e.code === "ArrowDown" ? 1 : e.code === "ArrowUp" ? -1 : 0, s = Math.abs(a + o + i) % i;
|
|
109
113
|
U.activeIndex = X.value[s].index ?? -1;
|
|
110
114
|
};
|
|
111
|
-
return ne(B),
|
|
112
|
-
U.search, U.activeIndex >= 0 && U.open &&
|
|
113
|
-
}), (t, n) => (
|
|
115
|
+
return ne(B), E(() => R.modelValue, he, { immediate: !0 }), E(() => U.open, (e) => e ? H.value?.focus() : ""), ce(() => {
|
|
116
|
+
U.search, U.activeIndex >= 0 && U.open && Ce();
|
|
117
|
+
}), (t, n) => (y(), m("div", ue, [h("div", {
|
|
114
118
|
ref_key: "root",
|
|
115
119
|
ref: B,
|
|
116
120
|
tabindex: Z.value,
|
|
117
|
-
class:
|
|
121
|
+
class: v(["ui-dropdown", {
|
|
118
122
|
open: U.open,
|
|
119
|
-
error:
|
|
123
|
+
error: _.error,
|
|
120
124
|
disabled: G.value
|
|
121
125
|
}]),
|
|
122
|
-
onKeydown:
|
|
123
|
-
onFocusout:
|
|
124
|
-
}, [
|
|
125
|
-
|
|
126
|
-
|
|
126
|
+
onKeydown: we,
|
|
127
|
+
onFocusout: Se
|
|
128
|
+
}, [h("div", fe, [
|
|
129
|
+
h("div", {
|
|
130
|
+
class: "ui-dropdown__field",
|
|
131
|
+
title: ge.value
|
|
132
|
+
}, [
|
|
133
|
+
le(h("input", {
|
|
127
134
|
ref_key: "input",
|
|
128
135
|
ref: H,
|
|
129
136
|
"onUpdate:modelValue": n[0] ||= (e) => U.search = e,
|
|
130
137
|
type: "text",
|
|
131
138
|
tabindex: "-1",
|
|
132
139
|
disabled: G.value,
|
|
133
|
-
placeholder:
|
|
140
|
+
placeholder: _e.value,
|
|
134
141
|
spellcheck: "false",
|
|
135
142
|
autocomplete: "chrome-off",
|
|
136
|
-
onFocus:
|
|
137
|
-
}, null, 40, k), [[
|
|
138
|
-
U.open ?
|
|
143
|
+
onFocus: xe
|
|
144
|
+
}, null, 40, k), [[se, U.search]]),
|
|
145
|
+
U.open ? p("", !0) : (y(), m("div", {
|
|
139
146
|
key: 0,
|
|
140
|
-
onClick:
|
|
141
|
-
}, [
|
|
142
|
-
default: D(() => [
|
|
147
|
+
onClick: be
|
|
148
|
+
}, [g(o, { class: "input-value" }, {
|
|
149
|
+
default: D(() => [ae(w(Y.value), 1)]),
|
|
143
150
|
_: 1
|
|
144
151
|
})])),
|
|
145
|
-
|
|
146
|
-
W.value ? (
|
|
152
|
+
h("div", A, [
|
|
153
|
+
W.value ? (y(), f(T(te), {
|
|
147
154
|
key: 0,
|
|
148
155
|
name: "loading"
|
|
149
|
-
})) :
|
|
150
|
-
|
|
156
|
+
})) : p("", !0),
|
|
157
|
+
_.clearable && ve.value ? (y(), f(T(c), {
|
|
151
158
|
key: 1,
|
|
152
159
|
class: "clear",
|
|
153
160
|
name: "delete-clear",
|
|
154
|
-
onClick: O(
|
|
155
|
-
})) :
|
|
156
|
-
|
|
157
|
-
|
|
161
|
+
onClick: O(ye, ["stop"])
|
|
162
|
+
})) : p("", !0),
|
|
163
|
+
C(t.$slots, "append"),
|
|
164
|
+
_.arrowIconLarge ? (y(), m("div", {
|
|
158
165
|
key: 2,
|
|
159
|
-
class:
|
|
166
|
+
class: v(["arrow-icon", [`icon-24 ${_.arrowIconLarge}`]]),
|
|
160
167
|
onClick: O($, ["stop"])
|
|
161
|
-
}, null, 2)) :
|
|
168
|
+
}, null, 2)) : _.arrowIcon ? (y(), m("div", {
|
|
162
169
|
key: 3,
|
|
163
|
-
class:
|
|
170
|
+
class: v(["arrow-icon", [`icon-16 ${_.arrowIcon}`]]),
|
|
164
171
|
onClick: O($, ["stop"])
|
|
165
|
-
}, null, 2)) : (
|
|
172
|
+
}, null, 2)) : (y(), m("div", {
|
|
166
173
|
key: 4,
|
|
167
174
|
class: "arrow-icon arrow-icon-default",
|
|
168
175
|
onClick: O($, ["stop"])
|
|
169
176
|
}))
|
|
170
177
|
])
|
|
171
|
-
]),
|
|
172
|
-
|
|
173
|
-
|
|
178
|
+
], 8, pe),
|
|
179
|
+
_.label ? (y(), m("label", j, [
|
|
180
|
+
_.required ? (y(), f(T(ee), {
|
|
174
181
|
key: 0,
|
|
175
|
-
uri:
|
|
176
|
-
}, null, 8, ["uri"])) :
|
|
177
|
-
|
|
178
|
-
|
|
182
|
+
uri: T(re)
|
|
183
|
+
}, null, 8, ["uri"])) : p("", !0),
|
|
184
|
+
h("span", null, w(_.label), 1),
|
|
185
|
+
T(z).tooltip ? (y(), f(T(i), {
|
|
179
186
|
key: 1,
|
|
180
187
|
class: "info",
|
|
181
188
|
position: "top"
|
|
182
189
|
}, {
|
|
183
|
-
tooltip: D(() => [
|
|
190
|
+
tooltip: D(() => [C(t.$slots, "tooltip")]),
|
|
184
191
|
_: 3
|
|
185
|
-
})) :
|
|
186
|
-
])) :
|
|
187
|
-
U.open ? (
|
|
192
|
+
})) : p("", !0)
|
|
193
|
+
])) : p("", !0),
|
|
194
|
+
U.open ? (y(), m("div", {
|
|
188
195
|
key: 1,
|
|
189
196
|
ref_key: "list",
|
|
190
197
|
ref: V,
|
|
191
198
|
class: "ui-dropdown__options"
|
|
192
|
-
}, [(
|
|
199
|
+
}, [(y(!0), m(ie, null, S(X.value, (t, n) => (y(), f(e, {
|
|
193
200
|
key: n,
|
|
194
201
|
option: t,
|
|
195
202
|
"is-selected": t.isSelected,
|
|
196
203
|
"is-hovered": t.isActive,
|
|
197
|
-
size:
|
|
204
|
+
size: _.optionSize,
|
|
198
205
|
onClick: O((e) => Q(t.value), ["stop"])
|
|
199
206
|
}, null, 8, [
|
|
200
207
|
"option",
|
|
@@ -202,9 +209,9 @@ var ue = { class: "ui-dropdown__envelope" }, de = ["tabindex"], fe = { class: "u
|
|
|
202
209
|
"is-hovered",
|
|
203
210
|
"size",
|
|
204
211
|
"onClick"
|
|
205
|
-
]))), 128)), X.value.length ?
|
|
206
|
-
|
|
207
|
-
])], 42, de), q.value ? (
|
|
212
|
+
]))), 128)), X.value.length ? p("", !0) : (y(), m("div", M, "Nothing found"))], 512)) : p("", !0),
|
|
213
|
+
g(l, { class: "ui-dropdown__contour" })
|
|
214
|
+
])], 42, de), q.value ? (y(), m("div", N, w(q.value), 1)) : W.value && _.loadingOptionsHelper ? (y(), m("div", P, w(_.loadingOptionsHelper), 1)) : _.helper ? (y(), m("div", F, w(_.helper), 1)) : p("", !0)]));
|
|
208
215
|
}
|
|
209
216
|
});
|
|
210
217
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlDropdownLegacy.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlDropdownLegacy/PlDropdownLegacy.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 \"./pl-dropdown-legacy.scss\";\nimport { computed, reactive, ref, unref, useSlots, watch, watchPostEffect } from \"vue\";\nimport { tap, tapIf } from \"../../helpers/functions\";\nimport { PlTooltip } from \"../PlTooltip\";\nimport DoubleContour from \"../../utils/DoubleContour.vue\";\nimport { useLabelNotch } from \"../../utils/useLabelNotch\";\nimport type { ListOption, ListOptionNormalized } from \"../../types\";\nimport { scrollIntoView } from \"../../helpers/dom\";\nimport { deepEqual } from \"../../helpers/objects\";\nimport DropdownListItem from \"../DropdownListItem.vue\";\nimport LongText from \"../LongText.vue\";\nimport { PlIcon16 } from \"../PlIcon16\";\nimport { PlMaskIcon24 } from \"../PlMaskIcon24\";\nimport { normalizeListOptions } from \"../../helpers/utils\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { PlSvg } from \"../PlSvg\";\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\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 * 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?: string;\n /**\n * Custom icon (24px) class for the dropdown arrow (optional)\n */\n arrowIconLarge?: string;\n /**\n * Option list item size\n */\n optionSize?: \"small\" | \"medium\";\n }>(),\n {\n label: \"\",\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: \"...\",\n clearable: false,\n required: false,\n disabled: false,\n arrowIcon: undefined,\n arrowIconLarge: undefined,\n optionSize: \"small\",\n options: undefined,\n },\n);\n\nconst slots = useSlots();\n\nconst root = ref<HTMLElement | undefined>();\nconst list = ref<HTMLElement | undefined>();\nconst input = ref<HTMLInputElement | undefined>();\n\nconst data = reactive({\n search: \"\",\n activeIndex: -1,\n open: false,\n});\n\nconst findActiveIndex = () =>\n tap(\n filteredRef.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(() =>\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) {\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 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 root?.value?.focus();\n};\n\nconst clear = () => emit(\"update:modelValue\", undefined);\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleOpen = () => (data.open = !data.open);\n\nconst onInputFocus = () => (data.open = true);\n\nconst onFocusOut = (event: FocusEvent) => {\n if (!root?.value?.contains(event.relatedTarget as Node | null)) {\n data.search = \"\";\n data.open = false;\n }\n};\n\nconst scrollIntoActive = () => {\n const $list = list.value;\n\n if (!$list) {\n return;\n }\n\n tapIf($list.querySelector(\".hovered-item\") as HTMLElement, (opt) => {\n scrollIntoView($list, opt);\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 root.value?.focus();\n }\n\n const filtered = unref(filteredRef);\n\n const { length } = filtered;\n\n if (!length) {\n return;\n }\n\n if (e.code === \"Enter\") {\n selectOption(filtered.find((it) => it.index === activeIndex)?.value);\n }\n\n const localIndex = filtered.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 = filteredRef.value[newIndex].index ?? -1;\n};\n\nuseLabelNotch(root);\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 scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"ui-dropdown__envelope\">\n <div\n ref=\"root\"\n :tabindex=\"tabindex\"\n class=\"ui-dropdown\"\n :class=\"{ open: data.open, error, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"ui-dropdown__container\">\n <div class=\"ui-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\" @click=\"setFocusOnInput\">\n <LongText class=\"input-value\"> {{ textValue }} </LongText>\n </div>\n\n <div class=\"ui-dropdown__controls\">\n <PlMaskIcon24 v-if=\"isLoadingOptions\" name=\"loading\" />\n <PlIcon16\n v-if=\"clearable && hasValue\"\n class=\"clear\"\n name=\"delete-clear\"\n @click.stop=\"clear\"\n />\n <slot name=\"append\" />\n <div\n v-if=\"arrowIconLarge\"\n class=\"arrow-icon\"\n :class=\"[`icon-24 ${arrowIconLarge}`]\"\n @click.stop=\"toggleOpen\"\n />\n <div\n v-else-if=\"arrowIcon\"\n class=\"arrow-icon\"\n :class=\"[`icon-16 ${arrowIcon}`]\"\n @click.stop=\"toggleOpen\"\n />\n <div v-else class=\"arrow-icon arrow-icon-default\" @click.stop=\"toggleOpen\" />\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 <div v-if=\"data.open\" ref=\"list\" class=\"ui-dropdown__options\">\n <DropdownListItem\n v-for=\"(item, index) in filteredRef\"\n :key=\"index\"\n :option=\"item\"\n :is-selected=\"item.isSelected\"\n :is-hovered=\"item.isActive\"\n :size=\"optionSize\"\n @click.stop=\"selectOption(item.value)\"\n />\n <div v-if=\"!filteredRef.length\" class=\"nothing-found\">Nothing found</div>\n </div>\n <DoubleContour class=\"ui-dropdown__contour\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"ui-dropdown__error\">{{ computedError }}</div>\n <div v-else-if=\"isLoadingOptions && loadingOptionsHelper\" class=\"ui-dropdown__helper\">\n {{ loadingOptionsHelper }}\n </div>\n <div v-else-if=\"helper\" class=\"ui-dropdown__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"PlDropdownLegacy.vue_vue_type_script_setup_true_lang.js","names":[],"sources":["../../../src/components/PlDropdownLegacy/PlDropdownLegacy.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 \"./pl-dropdown-legacy.scss\";\nimport { computed, reactive, ref, unref, useSlots, watch, watchPostEffect } from \"vue\";\nimport { tap, tapIf } from \"../../helpers/functions\";\nimport { PlTooltip } from \"../PlTooltip\";\nimport DoubleContour from \"../../utils/DoubleContour.vue\";\nimport { useLabelNotch } from \"../../utils/useLabelNotch\";\nimport type { ListOption, ListOptionNormalized } from \"../../types\";\nimport { scrollIntoView } from \"../../helpers/dom\";\nimport { deepEqual } from \"../../helpers/objects\";\nimport DropdownListItem from \"../DropdownListItem.vue\";\nimport LongText from \"../LongText.vue\";\nimport { PlIcon16 } from \"../PlIcon16\";\nimport { PlMaskIcon24 } from \"../PlMaskIcon24\";\nimport { normalizeListOptions } from \"../../helpers/utils\";\nimport { getErrorMessage } from \"../../helpers/error.ts\";\nimport { PlSvg } from \"../PlSvg\";\nimport SvgRequired from \"../../assets/images/required.svg?raw\";\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 * 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?: string;\n /**\n * Custom icon (24px) class for the dropdown arrow (optional)\n */\n arrowIconLarge?: string;\n /**\n * Option list item size\n */\n optionSize?: \"small\" | \"medium\";\n }>(),\n {\n label: \"\",\n helper: undefined,\n loadingOptionsHelper: undefined,\n error: undefined,\n placeholder: \"...\",\n clearable: false,\n required: false,\n disabled: false,\n arrowIcon: undefined,\n arrowIconLarge: undefined,\n optionSize: \"small\",\n options: undefined,\n },\n);\n\nconst slots = useSlots();\n\nconst root = ref<HTMLElement | undefined>();\nconst list = ref<HTMLElement | undefined>();\nconst input = ref<HTMLInputElement | undefined>();\n\nconst data = reactive({\n search: \"\",\n activeIndex: -1,\n open: false,\n});\n\nconst findActiveIndex = () =>\n tap(\n filteredRef.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(() =>\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\n// Native tooltip with the full selected value; the value layer itself has\n// `pointer-events: none`, so the title goes on the field wrapper.\nconst fieldTitle = computed(() => {\n if (data.open) return undefined;\n const v = textValue.value;\n return v !== undefined && v !== null && v !== \"\" ? String(v) : undefined;\n});\n\nconst computedPlaceholder = computed(() => {\n if (!data.open && props.modelValue) {\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 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 root?.value?.focus();\n};\n\nconst clear = () => emit(\"update:modelValue\", undefined);\n\nconst setFocusOnInput = () => input.value?.focus();\n\nconst toggleOpen = () => (data.open = !data.open);\n\nconst onInputFocus = () => (data.open = true);\n\nconst onFocusOut = (event: FocusEvent) => {\n if (!root?.value?.contains(event.relatedTarget as Node | null)) {\n data.search = \"\";\n data.open = false;\n }\n};\n\nconst scrollIntoActive = () => {\n const $list = list.value;\n\n if (!$list) {\n return;\n }\n\n tapIf($list.querySelector(\".hovered-item\") as HTMLElement, (opt) => {\n scrollIntoView($list, opt);\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 root.value?.focus();\n }\n\n const filtered = unref(filteredRef);\n\n const { length } = filtered;\n\n if (!length) {\n return;\n }\n\n if (e.code === \"Enter\") {\n selectOption(filtered.find((it) => it.index === activeIndex)?.value);\n }\n\n const localIndex = filtered.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 = filteredRef.value[newIndex].index ?? -1;\n};\n\nuseLabelNotch(root);\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 scrollIntoActive();\n }\n});\n</script>\n\n<template>\n <div class=\"ui-dropdown__envelope\">\n <div\n ref=\"root\"\n :tabindex=\"tabindex\"\n class=\"ui-dropdown\"\n :class=\"{ open: data.open, error, disabled: isDisabled }\"\n @keydown=\"handleKeydown\"\n @focusout=\"onFocusOut\"\n >\n <div class=\"ui-dropdown__container\">\n <div class=\"ui-dropdown__field\" :title=\"fieldTitle\">\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\" @click=\"setFocusOnInput\">\n <LongText class=\"input-value\"> {{ textValue }} </LongText>\n </div>\n\n <div class=\"ui-dropdown__controls\">\n <PlMaskIcon24 v-if=\"isLoadingOptions\" name=\"loading\" />\n <PlIcon16\n v-if=\"clearable && hasValue\"\n class=\"clear\"\n name=\"delete-clear\"\n @click.stop=\"clear\"\n />\n <slot name=\"append\" />\n <div\n v-if=\"arrowIconLarge\"\n class=\"arrow-icon\"\n :class=\"[`icon-24 ${arrowIconLarge}`]\"\n @click.stop=\"toggleOpen\"\n />\n <div\n v-else-if=\"arrowIcon\"\n class=\"arrow-icon\"\n :class=\"[`icon-16 ${arrowIcon}`]\"\n @click.stop=\"toggleOpen\"\n />\n <div v-else class=\"arrow-icon arrow-icon-default\" @click.stop=\"toggleOpen\" />\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 <div v-if=\"data.open\" ref=\"list\" class=\"ui-dropdown__options\">\n <DropdownListItem\n v-for=\"(item, index) in filteredRef\"\n :key=\"index\"\n :option=\"item\"\n :is-selected=\"item.isSelected\"\n :is-hovered=\"item.isActive\"\n :size=\"optionSize\"\n @click.stop=\"selectOption(item.value)\"\n />\n <div v-if=\"!filteredRef.length\" class=\"nothing-found\">Nothing found</div>\n </div>\n <DoubleContour class=\"ui-dropdown__contour\" />\n </div>\n </div>\n <div v-if=\"computedError\" class=\"ui-dropdown__error\">{{ computedError }}</div>\n <div v-else-if=\"isLoadingOptions && loadingOptionsHelper\" class=\"ui-dropdown__helper\">\n {{ loadingOptionsHelper }}\n </div>\n <div v-else-if=\"helper\" class=\"ui-dropdown__helper\">{{ helper }}</div>\n </div>\n</template>\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/uikit",
|
|
3
|
-
"version": "2.15.
|
|
3
|
+
"version": "2.15.30",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"exports": {
|
|
@@ -31,8 +31,8 @@
|
|
|
31
31
|
"resize-observer-polyfill": "^1.5.1",
|
|
32
32
|
"sortablejs": "^1.15.6",
|
|
33
33
|
"vue": "3.5.24",
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
34
|
+
"@milaboratories/helpers": "1.14.5",
|
|
35
|
+
"@platforma-sdk/model": "1.83.17"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
@@ -41,8 +41,8 @@
|
|
|
41
41
|
"typescript": "7.0.2",
|
|
42
42
|
"vitest": "^4.1.3",
|
|
43
43
|
"@milaboratories/build-configs": "2.0.1",
|
|
44
|
-
"@milaboratories/ts-
|
|
45
|
-
"@milaboratories/ts-
|
|
44
|
+
"@milaboratories/ts-configs": "1.4.0",
|
|
45
|
+
"@milaboratories/ts-builder": "1.7.2"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"dev": "ts-builder serve --target browser-lib --build-config ./build.browser-lib.config.js",
|
|
@@ -198,6 +198,10 @@ const textValue = computed(() => {
|
|
|
198
198
|
return item?.label || (model.value ? props.formatValue(model.value) : "");
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
+
// Native tooltip with the full selected value; the value layer itself has
|
|
202
|
+
// `pointer-events: none`, so the title goes on the field wrapper.
|
|
203
|
+
const fieldTitle = computed(() => (!data.open && textValue.value ? textValue.value : undefined));
|
|
204
|
+
|
|
201
205
|
const computedPlaceholder = computed(() => {
|
|
202
206
|
if (!data.open && model.value) {
|
|
203
207
|
return "";
|
|
@@ -384,7 +388,7 @@ watch(
|
|
|
384
388
|
@focusout="onFocusOut"
|
|
385
389
|
>
|
|
386
390
|
<div class="pl-autocomplete__container">
|
|
387
|
-
<div class="pl-autocomplete__field">
|
|
391
|
+
<div class="pl-autocomplete__field" :title="fieldTitle">
|
|
388
392
|
<input
|
|
389
393
|
ref="input"
|
|
390
394
|
v-model="search"
|
|
@@ -211,6 +211,15 @@ const textValue = computed(() => {
|
|
|
211
211
|
return item?.label;
|
|
212
212
|
});
|
|
213
213
|
|
|
214
|
+
// Native tooltip with the full selected value. The `.input-value` layer has
|
|
215
|
+
// `pointer-events: none`, so the title must sit on the field wrapper, which is
|
|
216
|
+
// what actually receives the hover.
|
|
217
|
+
const fieldTitle = computed(() => {
|
|
218
|
+
if (data.open) return undefined;
|
|
219
|
+
if (isMissing.value) return props.missingValueLabel;
|
|
220
|
+
return textValue.value !== undefined ? String(textValue.value) : undefined;
|
|
221
|
+
});
|
|
222
|
+
|
|
214
223
|
const computedPlaceholder = computed(() => {
|
|
215
224
|
if (!data.open && hasValue.value) {
|
|
216
225
|
return "";
|
|
@@ -357,7 +366,7 @@ watchPostEffect(() => {
|
|
|
357
366
|
@focusout="onFocusOut"
|
|
358
367
|
>
|
|
359
368
|
<div class="pl-dropdown__container">
|
|
360
|
-
<div class="pl-dropdown__field">
|
|
369
|
+
<div class="pl-dropdown__field" :title="fieldTitle">
|
|
361
370
|
<input
|
|
362
371
|
ref="input"
|
|
363
372
|
v-model="data.search"
|
|
@@ -173,6 +173,14 @@ const textValue = computed(() => {
|
|
|
173
173
|
return item?.label || props.modelValue; // @todo show inner value?
|
|
174
174
|
});
|
|
175
175
|
|
|
176
|
+
// Native tooltip with the full selected value; the value layer itself has
|
|
177
|
+
// `pointer-events: none`, so the title goes on the field wrapper.
|
|
178
|
+
const fieldTitle = computed(() => {
|
|
179
|
+
if (data.open) return undefined;
|
|
180
|
+
const v = textValue.value;
|
|
181
|
+
return v !== undefined && v !== null && v !== "" ? String(v) : undefined;
|
|
182
|
+
});
|
|
183
|
+
|
|
176
184
|
const computedPlaceholder = computed(() => {
|
|
177
185
|
if (!data.open && props.modelValue) {
|
|
178
186
|
return "";
|
|
@@ -319,7 +327,7 @@ watchPostEffect(() => {
|
|
|
319
327
|
@focusout="onFocusOut"
|
|
320
328
|
>
|
|
321
329
|
<div class="ui-dropdown__container">
|
|
322
|
-
<div class="ui-dropdown__field">
|
|
330
|
+
<div class="ui-dropdown__field" :title="fieldTitle">
|
|
323
331
|
<input
|
|
324
332
|
ref="input"
|
|
325
333
|
v-model="data.search"
|