@stackline/vue-multiselect-dropdown 2.0.0 → 3.0.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/README.md +15 -15
- package/dist/index.cjs +84 -18
- package/dist/index.d.cts +14 -13
- package/dist/index.d.ts +14 -13
- package/dist/index.js +84 -18
- package/package.json +11 -8
package/README.md
CHANGED
|
@@ -1,48 +1,45 @@
|
|
|
1
1
|
# @stackline/vue-multiselect-dropdown
|
|
2
2
|
|
|
3
|
-
> A maintained Vue
|
|
3
|
+
> A maintained Vue 3 multiselect dropdown with controlled state, searchable/grouped options, lazy loading hooks, render functions, skins, body-overlay positioning, and ADA-compliant keyboard/ARIA behavior.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@stackline/vue-multiselect-dropdown)
|
|
6
6
|
[](https://github.com/alexandroit/vue-multiselect-dropdown/blob/main/LICENSE)
|
|
7
|
-
[](https://alexandro.net/docs/vue/multiselect/vue-3/)
|
|
8
8
|
|
|
9
|
-
**[Documentation & Live Demos](https://alexandro.net/docs/vue/multiselect/)** | **[Vue
|
|
9
|
+
**[Documentation & Live Demos](https://alexandro.net/docs/vue/multiselect/)** | **[Vue 3 Demo](https://alexandro.net/docs/vue/multiselect/vue-3/)** | **[npm](https://www.npmjs.com/package/@stackline/vue-multiselect-dropdown)** | **[Repository](https://github.com/alexandroit/vue-multiselect-dropdown)**
|
|
10
10
|
|
|
11
|
-
**Current validation package release:** `
|
|
11
|
+
**Current validation package release:** `3.0.1` for Vue `3.x`
|
|
12
12
|
|
|
13
13
|
---
|
|
14
14
|
|
|
15
15
|
## Why this library?
|
|
16
16
|
|
|
17
|
-
`@stackline/vue-multiselect-dropdown` provides a maintained Vue
|
|
17
|
+
`@stackline/vue-multiselect-dropdown` provides a maintained Vue 3 multiselect component for applications that need predictable selection state, search, grouping, skins, keyboard support, and live tested examples.
|
|
18
18
|
|
|
19
|
-
The package follows a familiar Stackline settings contract while staying idiomatic for Vue
|
|
19
|
+
The package follows a familiar Stackline settings contract while staying idiomatic for Vue 3: bind with `v-model`, pass `:data`, customize behavior through `:settings`, and listen for `@select`, `@de-select`, `@select-all`, `@de-select-all`, `@open`, and `@close`.
|
|
20
20
|
|
|
21
21
|
## Vue Version Compatibility
|
|
22
22
|
|
|
23
23
|
| Package family | Vue family | Peer range | First tested runtime | Demo link |
|
|
24
24
|
| :---: | :---: | :---: | :---: | :--- |
|
|
25
|
-
| **
|
|
25
|
+
| **3.x** | **Vue 3 only** | **`>=3.0.0 <4.0.0`** | **3.0.0** | [Vue 3 family docs](https://alexandro.net/docs/vue/multiselect/vue-3/) |
|
|
26
26
|
|
|
27
27
|
## Installation
|
|
28
28
|
|
|
29
29
|
```bash
|
|
30
|
-
npm install @stackline/vue-multiselect-dropdown@
|
|
30
|
+
npm install @stackline/vue-multiselect-dropdown@3.0.1 --save-exact
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
## Setup
|
|
34
34
|
|
|
35
35
|
```js
|
|
36
|
-
import
|
|
36
|
+
import { createApp } from 'vue';
|
|
37
37
|
import {
|
|
38
38
|
VueMultiselect,
|
|
39
39
|
VueMultiselectDropdown
|
|
40
40
|
} from '@stackline/vue-multiselect-dropdown';
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
new Vue({
|
|
45
|
-
el: '#app',
|
|
42
|
+
const app = createApp({
|
|
46
43
|
components: { VueMultiselectDropdown },
|
|
47
44
|
data() {
|
|
48
45
|
return {
|
|
@@ -63,6 +60,9 @@ new Vue({
|
|
|
63
60
|
};
|
|
64
61
|
}
|
|
65
62
|
});
|
|
63
|
+
|
|
64
|
+
app.use(VueMultiselect);
|
|
65
|
+
app.mount('#app');
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
```html
|
|
@@ -129,10 +129,10 @@ npm run build
|
|
|
129
129
|
npm test
|
|
130
130
|
```
|
|
131
131
|
|
|
132
|
-
Vue
|
|
132
|
+
Vue 3 docs:
|
|
133
133
|
|
|
134
134
|
```bash
|
|
135
|
-
cd docs-src/vue-
|
|
135
|
+
cd docs-src/vue-3
|
|
136
136
|
npm install
|
|
137
137
|
npm run build
|
|
138
138
|
```
|
package/dist/index.cjs
CHANGED
|
@@ -27,6 +27,9 @@ __export(index_exports, {
|
|
|
27
27
|
});
|
|
28
28
|
module.exports = __toCommonJS(index_exports);
|
|
29
29
|
|
|
30
|
+
// src/VueMultiselectDropdown.ts
|
|
31
|
+
var import_vue = require("vue");
|
|
32
|
+
|
|
30
33
|
// src/styles.ts
|
|
31
34
|
var STYLE_ID = "stackline-vue-multiselect-dropdown-styles";
|
|
32
35
|
var styles = `
|
|
@@ -69,6 +72,7 @@ var styles = `
|
|
|
69
72
|
position: relative;
|
|
70
73
|
display: flex;
|
|
71
74
|
align-items: center;
|
|
75
|
+
align-content: center;
|
|
72
76
|
flex-wrap: wrap;
|
|
73
77
|
width: 100%;
|
|
74
78
|
min-height: 56px;
|
|
@@ -106,15 +110,23 @@ var styles = `
|
|
|
106
110
|
flex: 1 1 auto;
|
|
107
111
|
min-width: 0;
|
|
108
112
|
align-items: center;
|
|
113
|
+
align-content: center;
|
|
109
114
|
gap: 8px;
|
|
110
115
|
flex-wrap: wrap;
|
|
111
116
|
}
|
|
112
117
|
|
|
113
118
|
.vmsd-placeholder,
|
|
114
119
|
.vmsd-single-value {
|
|
120
|
+
display: inline-flex;
|
|
121
|
+
align-items: center;
|
|
122
|
+
align-self: center;
|
|
123
|
+
justify-content: flex-start;
|
|
115
124
|
min-width: 0;
|
|
125
|
+
max-width: 100%;
|
|
116
126
|
color: var(--vmsd-muted);
|
|
117
127
|
font-size: 0.95rem;
|
|
128
|
+
line-height: 1.25;
|
|
129
|
+
text-align: left;
|
|
118
130
|
overflow: hidden;
|
|
119
131
|
text-overflow: ellipsis;
|
|
120
132
|
white-space: nowrap;
|
|
@@ -706,6 +718,7 @@ var styles = `
|
|
|
706
718
|
|
|
707
719
|
.theme-classic .vmsd-trigger,
|
|
708
720
|
.skin-classic .vmsd-trigger {
|
|
721
|
+
align-content: center;
|
|
709
722
|
flex-wrap: nowrap;
|
|
710
723
|
gap: 6px;
|
|
711
724
|
min-height: 42px;
|
|
@@ -1063,7 +1076,7 @@ var styles = `
|
|
|
1063
1076
|
}
|
|
1064
1077
|
}
|
|
1065
1078
|
|
|
1066
|
-
/* stackline-
|
|
1079
|
+
/* stackline-vue3-live-20260527 */
|
|
1067
1080
|
`;
|
|
1068
1081
|
function ensureDropdownStyles() {
|
|
1069
1082
|
if (typeof document === "undefined") {
|
|
@@ -1141,12 +1154,45 @@ function iconPath(name) {
|
|
|
1141
1154
|
}
|
|
1142
1155
|
return "M604.501,134.782c-9.999-10.05-26.222-10.05-36.221,0L306.014,422.558L43.721,134.782c-9.999-10.05-26.223-10.05-36.222,0s-9.999,26.35,0,36.399l279.103,306.241c5.331,5.357,12.422,7.652,19.386,7.296c6.988,0.356,14.055-1.939,19.386-7.296l279.128-306.268C614.5,161.106,614.5,144.832,604.501,134.782z";
|
|
1143
1156
|
}
|
|
1144
|
-
function renderIcon(
|
|
1157
|
+
function renderIcon(h2, name, className = "vmsd-icon") {
|
|
1145
1158
|
const viewBox = name === "remove" ? "0 0 47.971 47.971" : name === "clear" ? "0 0 51.976 51.976" : name === "search" ? "0 0 615.52 615.52" : "0 0 612 612";
|
|
1146
|
-
return
|
|
1147
|
-
|
|
1159
|
+
return h2("svg", { class: className, attrs: { viewBox, focusable: "false", "aria-hidden": "true" } }, [
|
|
1160
|
+
h2("path", { attrs: { d: iconPath(name) } })
|
|
1148
1161
|
]);
|
|
1149
1162
|
}
|
|
1163
|
+
function capitalize(value) {
|
|
1164
|
+
return value ? value.charAt(0).toUpperCase() + value.slice(1) : value;
|
|
1165
|
+
}
|
|
1166
|
+
function normalizeVue2RenderData(data) {
|
|
1167
|
+
if (!data) {
|
|
1168
|
+
return null;
|
|
1169
|
+
}
|
|
1170
|
+
const props = {};
|
|
1171
|
+
for (const [key, value] of Object.entries(data)) {
|
|
1172
|
+
if (key === "attrs" || key === "domProps") {
|
|
1173
|
+
Object.assign(props, value);
|
|
1174
|
+
continue;
|
|
1175
|
+
}
|
|
1176
|
+
if (key === "on" && value && typeof value === "object") {
|
|
1177
|
+
for (const [eventName, handler] of Object.entries(value)) {
|
|
1178
|
+
props[`on${capitalize(eventName)}`] = handler;
|
|
1179
|
+
}
|
|
1180
|
+
continue;
|
|
1181
|
+
}
|
|
1182
|
+
props[key] = value;
|
|
1183
|
+
}
|
|
1184
|
+
return props;
|
|
1185
|
+
}
|
|
1186
|
+
var h = (...args) => {
|
|
1187
|
+
const [tag, data, children] = args;
|
|
1188
|
+
if (args.length === 1) {
|
|
1189
|
+
return (0, import_vue.h)(tag);
|
|
1190
|
+
}
|
|
1191
|
+
if (args.length === 2 && (Array.isArray(data) || typeof data === "string" || typeof data === "number" || data == null)) {
|
|
1192
|
+
return (0, import_vue.h)(tag, null, data);
|
|
1193
|
+
}
|
|
1194
|
+
return (0, import_vue.h)(tag, normalizeVue2RenderData(data), children);
|
|
1195
|
+
};
|
|
1150
1196
|
function isPrimitiveItem(item) {
|
|
1151
1197
|
return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
|
|
1152
1198
|
}
|
|
@@ -1235,11 +1281,11 @@ function mergeUniqueItems(base, extra, settings) {
|
|
|
1235
1281
|
}
|
|
1236
1282
|
return Array.from(bucket.values());
|
|
1237
1283
|
}
|
|
1238
|
-
function callRenderFunction(renderFunction,
|
|
1284
|
+
function callRenderFunction(renderFunction, h2, item, context) {
|
|
1239
1285
|
if (!renderFunction) {
|
|
1240
1286
|
return null;
|
|
1241
1287
|
}
|
|
1242
|
-
return renderFunction(item, context,
|
|
1288
|
+
return renderFunction(item, context, h2);
|
|
1243
1289
|
}
|
|
1244
1290
|
function escapeSelectorValue(value) {
|
|
1245
1291
|
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
@@ -1259,15 +1305,31 @@ function isTextInputTarget(target) {
|
|
|
1259
1305
|
}
|
|
1260
1306
|
var VueMultiselectDropdown = {
|
|
1261
1307
|
name: "VueMultiselectDropdown",
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1308
|
+
emits: [
|
|
1309
|
+
"update:modelValue",
|
|
1310
|
+
"input",
|
|
1311
|
+
"update:selectedItems",
|
|
1312
|
+
"change",
|
|
1313
|
+
"select",
|
|
1314
|
+
"de-select",
|
|
1315
|
+
"select-all",
|
|
1316
|
+
"de-select-all",
|
|
1317
|
+
"group-select",
|
|
1318
|
+
"group-de-select",
|
|
1319
|
+
"scroll-to-end",
|
|
1320
|
+
"add-filter-new-item",
|
|
1321
|
+
"open",
|
|
1322
|
+
"close"
|
|
1323
|
+
],
|
|
1266
1324
|
props: {
|
|
1267
1325
|
data: {
|
|
1268
1326
|
type: Array,
|
|
1269
1327
|
default: () => []
|
|
1270
1328
|
},
|
|
1329
|
+
modelValue: {
|
|
1330
|
+
type: Array,
|
|
1331
|
+
default: void 0
|
|
1332
|
+
},
|
|
1271
1333
|
value: {
|
|
1272
1334
|
type: Array,
|
|
1273
1335
|
default: void 0
|
|
@@ -1333,6 +1395,9 @@ var VueMultiselectDropdown = {
|
|
|
1333
1395
|
if (Array.isArray(this.selectedItems)) {
|
|
1334
1396
|
return this.selectedItems;
|
|
1335
1397
|
}
|
|
1398
|
+
if (Array.isArray(this.modelValue)) {
|
|
1399
|
+
return this.modelValue;
|
|
1400
|
+
}
|
|
1336
1401
|
if (Array.isArray(this.value)) {
|
|
1337
1402
|
return this.value;
|
|
1338
1403
|
}
|
|
@@ -1397,7 +1462,7 @@ var VueMultiselectDropdown = {
|
|
|
1397
1462
|
window.addEventListener("resize", this.updateMenuPosition);
|
|
1398
1463
|
window.addEventListener("scroll", this.updateMenuPosition, true);
|
|
1399
1464
|
},
|
|
1400
|
-
|
|
1465
|
+
beforeUnmount() {
|
|
1401
1466
|
document.removeEventListener("click", this.onDocumentClick, true);
|
|
1402
1467
|
document.removeEventListener("keydown", this.onDocumentKeydown, true);
|
|
1403
1468
|
window.removeEventListener("resize", this.updateMenuPosition);
|
|
@@ -1419,9 +1484,10 @@ var VueMultiselectDropdown = {
|
|
|
1419
1484
|
return this.filteredItems.filter((item) => !isDisabledItem(item));
|
|
1420
1485
|
},
|
|
1421
1486
|
emitSelection(items) {
|
|
1422
|
-
if (!Array.isArray(this.selectedItems) && !Array.isArray(this.value)) {
|
|
1487
|
+
if (!Array.isArray(this.selectedItems) && !Array.isArray(this.modelValue) && !Array.isArray(this.value)) {
|
|
1423
1488
|
this.internalSelected = items;
|
|
1424
1489
|
}
|
|
1490
|
+
this.$emit("update:modelValue", items);
|
|
1425
1491
|
this.$emit("input", items);
|
|
1426
1492
|
this.$emit("update:selectedItems", items);
|
|
1427
1493
|
this.$emit("change", items);
|
|
@@ -1786,7 +1852,7 @@ var VueMultiselectDropdown = {
|
|
|
1786
1852
|
this.menuStyle = style;
|
|
1787
1853
|
}
|
|
1788
1854
|
},
|
|
1789
|
-
render(
|
|
1855
|
+
render() {
|
|
1790
1856
|
const settings = this.resolvedSettings;
|
|
1791
1857
|
const skin = String(settings.skin || settings.theme || "classic");
|
|
1792
1858
|
const skinFallbackClass = ["classic", "material", "dark", "custom"].includes(skin) ? "" : "theme-custom";
|
|
@@ -2074,11 +2140,11 @@ var StacklineVueMultiselect = VueMultiselectDropdown;
|
|
|
2074
2140
|
|
|
2075
2141
|
// src/plugin.ts
|
|
2076
2142
|
var VueMultiselect = {
|
|
2077
|
-
install(
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2143
|
+
install(app) {
|
|
2144
|
+
app.component("StacklineVueMultiselect", VueMultiselectDropdown);
|
|
2145
|
+
app.component("VueMultiselectDropdown", VueMultiselectDropdown);
|
|
2146
|
+
app.component("vue-multiselect-dropdown", VueMultiselectDropdown);
|
|
2147
|
+
app.component("stackline-vue-multiselect", VueMultiselectDropdown);
|
|
2082
2148
|
}
|
|
2083
2149
|
};
|
|
2084
2150
|
var plugin_default = VueMultiselect;
|
package/dist/index.d.cts
CHANGED
|
@@ -70,22 +70,22 @@ interface VueMultiselectPlugin {
|
|
|
70
70
|
install: (Vue: any) => void;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
type CreateElement = (...args: any[]) => any;
|
|
74
73
|
type GroupedItems<T> = Array<{
|
|
75
74
|
name: string;
|
|
76
75
|
items: T[];
|
|
77
76
|
}>;
|
|
78
77
|
declare const VueMultiselectDropdown: {
|
|
79
78
|
name: string;
|
|
80
|
-
|
|
81
|
-
prop: string;
|
|
82
|
-
event: string;
|
|
83
|
-
};
|
|
79
|
+
emits: string[];
|
|
84
80
|
props: {
|
|
85
81
|
data: {
|
|
86
82
|
type: ArrayConstructor;
|
|
87
83
|
default: () => never[];
|
|
88
84
|
};
|
|
85
|
+
modelValue: {
|
|
86
|
+
type: ArrayConstructor;
|
|
87
|
+
default: undefined;
|
|
88
|
+
};
|
|
89
89
|
value: {
|
|
90
90
|
type: ArrayConstructor;
|
|
91
91
|
default: undefined;
|
|
@@ -151,7 +151,7 @@ declare const VueMultiselectDropdown: {
|
|
|
151
151
|
};
|
|
152
152
|
};
|
|
153
153
|
mounted(this: any): void;
|
|
154
|
-
|
|
154
|
+
beforeUnmount(this: any): void;
|
|
155
155
|
methods: {
|
|
156
156
|
getLabel(this: any, item: DropdownItem): string;
|
|
157
157
|
getKey(this: any, item: DropdownItem): string;
|
|
@@ -183,19 +183,20 @@ declare const VueMultiselectDropdown: {
|
|
|
183
183
|
restoreMenuToComponent(this: any): void;
|
|
184
184
|
updateMenuPosition(this: any): void;
|
|
185
185
|
};
|
|
186
|
-
render(this: any
|
|
186
|
+
render(this: any): any;
|
|
187
187
|
};
|
|
188
188
|
declare const StacklineVueMultiselect: {
|
|
189
189
|
name: string;
|
|
190
|
-
|
|
191
|
-
prop: string;
|
|
192
|
-
event: string;
|
|
193
|
-
};
|
|
190
|
+
emits: string[];
|
|
194
191
|
props: {
|
|
195
192
|
data: {
|
|
196
193
|
type: ArrayConstructor;
|
|
197
194
|
default: () => never[];
|
|
198
195
|
};
|
|
196
|
+
modelValue: {
|
|
197
|
+
type: ArrayConstructor;
|
|
198
|
+
default: undefined;
|
|
199
|
+
};
|
|
199
200
|
value: {
|
|
200
201
|
type: ArrayConstructor;
|
|
201
202
|
default: undefined;
|
|
@@ -261,7 +262,7 @@ declare const StacklineVueMultiselect: {
|
|
|
261
262
|
};
|
|
262
263
|
};
|
|
263
264
|
mounted(this: any): void;
|
|
264
|
-
|
|
265
|
+
beforeUnmount(this: any): void;
|
|
265
266
|
methods: {
|
|
266
267
|
getLabel(this: any, item: DropdownItem): string;
|
|
267
268
|
getKey(this: any, item: DropdownItem): string;
|
|
@@ -293,7 +294,7 @@ declare const StacklineVueMultiselect: {
|
|
|
293
294
|
restoreMenuToComponent(this: any): void;
|
|
294
295
|
updateMenuPosition(this: any): void;
|
|
295
296
|
};
|
|
296
|
-
render(this: any
|
|
297
|
+
render(this: any): any;
|
|
297
298
|
};
|
|
298
299
|
|
|
299
300
|
declare const VueMultiselect: VueMultiselectPlugin;
|
package/dist/index.d.ts
CHANGED
|
@@ -70,22 +70,22 @@ interface VueMultiselectPlugin {
|
|
|
70
70
|
install: (Vue: any) => void;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
type CreateElement = (...args: any[]) => any;
|
|
74
73
|
type GroupedItems<T> = Array<{
|
|
75
74
|
name: string;
|
|
76
75
|
items: T[];
|
|
77
76
|
}>;
|
|
78
77
|
declare const VueMultiselectDropdown: {
|
|
79
78
|
name: string;
|
|
80
|
-
|
|
81
|
-
prop: string;
|
|
82
|
-
event: string;
|
|
83
|
-
};
|
|
79
|
+
emits: string[];
|
|
84
80
|
props: {
|
|
85
81
|
data: {
|
|
86
82
|
type: ArrayConstructor;
|
|
87
83
|
default: () => never[];
|
|
88
84
|
};
|
|
85
|
+
modelValue: {
|
|
86
|
+
type: ArrayConstructor;
|
|
87
|
+
default: undefined;
|
|
88
|
+
};
|
|
89
89
|
value: {
|
|
90
90
|
type: ArrayConstructor;
|
|
91
91
|
default: undefined;
|
|
@@ -151,7 +151,7 @@ declare const VueMultiselectDropdown: {
|
|
|
151
151
|
};
|
|
152
152
|
};
|
|
153
153
|
mounted(this: any): void;
|
|
154
|
-
|
|
154
|
+
beforeUnmount(this: any): void;
|
|
155
155
|
methods: {
|
|
156
156
|
getLabel(this: any, item: DropdownItem): string;
|
|
157
157
|
getKey(this: any, item: DropdownItem): string;
|
|
@@ -183,19 +183,20 @@ declare const VueMultiselectDropdown: {
|
|
|
183
183
|
restoreMenuToComponent(this: any): void;
|
|
184
184
|
updateMenuPosition(this: any): void;
|
|
185
185
|
};
|
|
186
|
-
render(this: any
|
|
186
|
+
render(this: any): any;
|
|
187
187
|
};
|
|
188
188
|
declare const StacklineVueMultiselect: {
|
|
189
189
|
name: string;
|
|
190
|
-
|
|
191
|
-
prop: string;
|
|
192
|
-
event: string;
|
|
193
|
-
};
|
|
190
|
+
emits: string[];
|
|
194
191
|
props: {
|
|
195
192
|
data: {
|
|
196
193
|
type: ArrayConstructor;
|
|
197
194
|
default: () => never[];
|
|
198
195
|
};
|
|
196
|
+
modelValue: {
|
|
197
|
+
type: ArrayConstructor;
|
|
198
|
+
default: undefined;
|
|
199
|
+
};
|
|
199
200
|
value: {
|
|
200
201
|
type: ArrayConstructor;
|
|
201
202
|
default: undefined;
|
|
@@ -261,7 +262,7 @@ declare const StacklineVueMultiselect: {
|
|
|
261
262
|
};
|
|
262
263
|
};
|
|
263
264
|
mounted(this: any): void;
|
|
264
|
-
|
|
265
|
+
beforeUnmount(this: any): void;
|
|
265
266
|
methods: {
|
|
266
267
|
getLabel(this: any, item: DropdownItem): string;
|
|
267
268
|
getKey(this: any, item: DropdownItem): string;
|
|
@@ -293,7 +294,7 @@ declare const StacklineVueMultiselect: {
|
|
|
293
294
|
restoreMenuToComponent(this: any): void;
|
|
294
295
|
updateMenuPosition(this: any): void;
|
|
295
296
|
};
|
|
296
|
-
render(this: any
|
|
297
|
+
render(this: any): any;
|
|
297
298
|
};
|
|
298
299
|
|
|
299
300
|
declare const VueMultiselect: VueMultiselectPlugin;
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
// src/VueMultiselectDropdown.ts
|
|
2
|
+
import { h as vueH } from "vue";
|
|
3
|
+
|
|
1
4
|
// src/styles.ts
|
|
2
5
|
var STYLE_ID = "stackline-vue-multiselect-dropdown-styles";
|
|
3
6
|
var styles = `
|
|
@@ -40,6 +43,7 @@ var styles = `
|
|
|
40
43
|
position: relative;
|
|
41
44
|
display: flex;
|
|
42
45
|
align-items: center;
|
|
46
|
+
align-content: center;
|
|
43
47
|
flex-wrap: wrap;
|
|
44
48
|
width: 100%;
|
|
45
49
|
min-height: 56px;
|
|
@@ -77,15 +81,23 @@ var styles = `
|
|
|
77
81
|
flex: 1 1 auto;
|
|
78
82
|
min-width: 0;
|
|
79
83
|
align-items: center;
|
|
84
|
+
align-content: center;
|
|
80
85
|
gap: 8px;
|
|
81
86
|
flex-wrap: wrap;
|
|
82
87
|
}
|
|
83
88
|
|
|
84
89
|
.vmsd-placeholder,
|
|
85
90
|
.vmsd-single-value {
|
|
91
|
+
display: inline-flex;
|
|
92
|
+
align-items: center;
|
|
93
|
+
align-self: center;
|
|
94
|
+
justify-content: flex-start;
|
|
86
95
|
min-width: 0;
|
|
96
|
+
max-width: 100%;
|
|
87
97
|
color: var(--vmsd-muted);
|
|
88
98
|
font-size: 0.95rem;
|
|
99
|
+
line-height: 1.25;
|
|
100
|
+
text-align: left;
|
|
89
101
|
overflow: hidden;
|
|
90
102
|
text-overflow: ellipsis;
|
|
91
103
|
white-space: nowrap;
|
|
@@ -677,6 +689,7 @@ var styles = `
|
|
|
677
689
|
|
|
678
690
|
.theme-classic .vmsd-trigger,
|
|
679
691
|
.skin-classic .vmsd-trigger {
|
|
692
|
+
align-content: center;
|
|
680
693
|
flex-wrap: nowrap;
|
|
681
694
|
gap: 6px;
|
|
682
695
|
min-height: 42px;
|
|
@@ -1034,7 +1047,7 @@ var styles = `
|
|
|
1034
1047
|
}
|
|
1035
1048
|
}
|
|
1036
1049
|
|
|
1037
|
-
/* stackline-
|
|
1050
|
+
/* stackline-vue3-live-20260527 */
|
|
1038
1051
|
`;
|
|
1039
1052
|
function ensureDropdownStyles() {
|
|
1040
1053
|
if (typeof document === "undefined") {
|
|
@@ -1112,12 +1125,45 @@ function iconPath(name) {
|
|
|
1112
1125
|
}
|
|
1113
1126
|
return "M604.501,134.782c-9.999-10.05-26.222-10.05-36.221,0L306.014,422.558L43.721,134.782c-9.999-10.05-26.223-10.05-36.222,0s-9.999,26.35,0,36.399l279.103,306.241c5.331,5.357,12.422,7.652,19.386,7.296c6.988,0.356,14.055-1.939,19.386-7.296l279.128-306.268C614.5,161.106,614.5,144.832,604.501,134.782z";
|
|
1114
1127
|
}
|
|
1115
|
-
function renderIcon(
|
|
1128
|
+
function renderIcon(h2, name, className = "vmsd-icon") {
|
|
1116
1129
|
const viewBox = name === "remove" ? "0 0 47.971 47.971" : name === "clear" ? "0 0 51.976 51.976" : name === "search" ? "0 0 615.52 615.52" : "0 0 612 612";
|
|
1117
|
-
return
|
|
1118
|
-
|
|
1130
|
+
return h2("svg", { class: className, attrs: { viewBox, focusable: "false", "aria-hidden": "true" } }, [
|
|
1131
|
+
h2("path", { attrs: { d: iconPath(name) } })
|
|
1119
1132
|
]);
|
|
1120
1133
|
}
|
|
1134
|
+
function capitalize(value) {
|
|
1135
|
+
return value ? value.charAt(0).toUpperCase() + value.slice(1) : value;
|
|
1136
|
+
}
|
|
1137
|
+
function normalizeVue2RenderData(data) {
|
|
1138
|
+
if (!data) {
|
|
1139
|
+
return null;
|
|
1140
|
+
}
|
|
1141
|
+
const props = {};
|
|
1142
|
+
for (const [key, value] of Object.entries(data)) {
|
|
1143
|
+
if (key === "attrs" || key === "domProps") {
|
|
1144
|
+
Object.assign(props, value);
|
|
1145
|
+
continue;
|
|
1146
|
+
}
|
|
1147
|
+
if (key === "on" && value && typeof value === "object") {
|
|
1148
|
+
for (const [eventName, handler] of Object.entries(value)) {
|
|
1149
|
+
props[`on${capitalize(eventName)}`] = handler;
|
|
1150
|
+
}
|
|
1151
|
+
continue;
|
|
1152
|
+
}
|
|
1153
|
+
props[key] = value;
|
|
1154
|
+
}
|
|
1155
|
+
return props;
|
|
1156
|
+
}
|
|
1157
|
+
var h = (...args) => {
|
|
1158
|
+
const [tag, data, children] = args;
|
|
1159
|
+
if (args.length === 1) {
|
|
1160
|
+
return vueH(tag);
|
|
1161
|
+
}
|
|
1162
|
+
if (args.length === 2 && (Array.isArray(data) || typeof data === "string" || typeof data === "number" || data == null)) {
|
|
1163
|
+
return vueH(tag, null, data);
|
|
1164
|
+
}
|
|
1165
|
+
return vueH(tag, normalizeVue2RenderData(data), children);
|
|
1166
|
+
};
|
|
1121
1167
|
function isPrimitiveItem(item) {
|
|
1122
1168
|
return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
|
|
1123
1169
|
}
|
|
@@ -1206,11 +1252,11 @@ function mergeUniqueItems(base, extra, settings) {
|
|
|
1206
1252
|
}
|
|
1207
1253
|
return Array.from(bucket.values());
|
|
1208
1254
|
}
|
|
1209
|
-
function callRenderFunction(renderFunction,
|
|
1255
|
+
function callRenderFunction(renderFunction, h2, item, context) {
|
|
1210
1256
|
if (!renderFunction) {
|
|
1211
1257
|
return null;
|
|
1212
1258
|
}
|
|
1213
|
-
return renderFunction(item, context,
|
|
1259
|
+
return renderFunction(item, context, h2);
|
|
1214
1260
|
}
|
|
1215
1261
|
function escapeSelectorValue(value) {
|
|
1216
1262
|
if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
|
|
@@ -1230,15 +1276,31 @@ function isTextInputTarget(target) {
|
|
|
1230
1276
|
}
|
|
1231
1277
|
var VueMultiselectDropdown = {
|
|
1232
1278
|
name: "VueMultiselectDropdown",
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1279
|
+
emits: [
|
|
1280
|
+
"update:modelValue",
|
|
1281
|
+
"input",
|
|
1282
|
+
"update:selectedItems",
|
|
1283
|
+
"change",
|
|
1284
|
+
"select",
|
|
1285
|
+
"de-select",
|
|
1286
|
+
"select-all",
|
|
1287
|
+
"de-select-all",
|
|
1288
|
+
"group-select",
|
|
1289
|
+
"group-de-select",
|
|
1290
|
+
"scroll-to-end",
|
|
1291
|
+
"add-filter-new-item",
|
|
1292
|
+
"open",
|
|
1293
|
+
"close"
|
|
1294
|
+
],
|
|
1237
1295
|
props: {
|
|
1238
1296
|
data: {
|
|
1239
1297
|
type: Array,
|
|
1240
1298
|
default: () => []
|
|
1241
1299
|
},
|
|
1300
|
+
modelValue: {
|
|
1301
|
+
type: Array,
|
|
1302
|
+
default: void 0
|
|
1303
|
+
},
|
|
1242
1304
|
value: {
|
|
1243
1305
|
type: Array,
|
|
1244
1306
|
default: void 0
|
|
@@ -1304,6 +1366,9 @@ var VueMultiselectDropdown = {
|
|
|
1304
1366
|
if (Array.isArray(this.selectedItems)) {
|
|
1305
1367
|
return this.selectedItems;
|
|
1306
1368
|
}
|
|
1369
|
+
if (Array.isArray(this.modelValue)) {
|
|
1370
|
+
return this.modelValue;
|
|
1371
|
+
}
|
|
1307
1372
|
if (Array.isArray(this.value)) {
|
|
1308
1373
|
return this.value;
|
|
1309
1374
|
}
|
|
@@ -1368,7 +1433,7 @@ var VueMultiselectDropdown = {
|
|
|
1368
1433
|
window.addEventListener("resize", this.updateMenuPosition);
|
|
1369
1434
|
window.addEventListener("scroll", this.updateMenuPosition, true);
|
|
1370
1435
|
},
|
|
1371
|
-
|
|
1436
|
+
beforeUnmount() {
|
|
1372
1437
|
document.removeEventListener("click", this.onDocumentClick, true);
|
|
1373
1438
|
document.removeEventListener("keydown", this.onDocumentKeydown, true);
|
|
1374
1439
|
window.removeEventListener("resize", this.updateMenuPosition);
|
|
@@ -1390,9 +1455,10 @@ var VueMultiselectDropdown = {
|
|
|
1390
1455
|
return this.filteredItems.filter((item) => !isDisabledItem(item));
|
|
1391
1456
|
},
|
|
1392
1457
|
emitSelection(items) {
|
|
1393
|
-
if (!Array.isArray(this.selectedItems) && !Array.isArray(this.value)) {
|
|
1458
|
+
if (!Array.isArray(this.selectedItems) && !Array.isArray(this.modelValue) && !Array.isArray(this.value)) {
|
|
1394
1459
|
this.internalSelected = items;
|
|
1395
1460
|
}
|
|
1461
|
+
this.$emit("update:modelValue", items);
|
|
1396
1462
|
this.$emit("input", items);
|
|
1397
1463
|
this.$emit("update:selectedItems", items);
|
|
1398
1464
|
this.$emit("change", items);
|
|
@@ -1757,7 +1823,7 @@ var VueMultiselectDropdown = {
|
|
|
1757
1823
|
this.menuStyle = style;
|
|
1758
1824
|
}
|
|
1759
1825
|
},
|
|
1760
|
-
render(
|
|
1826
|
+
render() {
|
|
1761
1827
|
const settings = this.resolvedSettings;
|
|
1762
1828
|
const skin = String(settings.skin || settings.theme || "classic");
|
|
1763
1829
|
const skinFallbackClass = ["classic", "material", "dark", "custom"].includes(skin) ? "" : "theme-custom";
|
|
@@ -2045,11 +2111,11 @@ var StacklineVueMultiselect = VueMultiselectDropdown;
|
|
|
2045
2111
|
|
|
2046
2112
|
// src/plugin.ts
|
|
2047
2113
|
var VueMultiselect = {
|
|
2048
|
-
install(
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2114
|
+
install(app) {
|
|
2115
|
+
app.component("StacklineVueMultiselect", VueMultiselectDropdown);
|
|
2116
|
+
app.component("VueMultiselectDropdown", VueMultiselectDropdown);
|
|
2117
|
+
app.component("vue-multiselect-dropdown", VueMultiselectDropdown);
|
|
2118
|
+
app.component("stackline-vue-multiselect", VueMultiselectDropdown);
|
|
2053
2119
|
}
|
|
2054
2120
|
};
|
|
2055
2121
|
var plugin_default = VueMultiselect;
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackline/vue-multiselect-dropdown",
|
|
3
|
-
"version": "
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
|
+
"description": "Maintained Vue 3 multiselect dropdown with ADA-compliant keyboard/ARIA support, v-model state, Stackline skins, body overlays, live docs, search, grouping, lazy loading, and render functions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"vue",
|
|
7
|
-
"vue
|
|
7
|
+
"vue 3",
|
|
8
8
|
"multiselect",
|
|
9
9
|
"multiselect-dropdown",
|
|
10
10
|
"multi-select",
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"accessibility",
|
|
16
16
|
"aria"
|
|
17
17
|
],
|
|
18
|
-
"homepage": "https://alexandro.net/docs/vue/multiselect/vue-
|
|
18
|
+
"homepage": "https://alexandro.net/docs/vue/multiselect/vue-3/",
|
|
19
19
|
"bugs": {
|
|
20
20
|
"url": "https://github.com/alexandroit/vue-multiselect-dropdown/issues"
|
|
21
21
|
},
|
|
@@ -43,16 +43,19 @@
|
|
|
43
43
|
"sideEffects": false,
|
|
44
44
|
"scripts": {
|
|
45
45
|
"build": "tsup",
|
|
46
|
-
"clean": "rm -rf dist docs/vue-
|
|
46
|
+
"clean": "rm -rf dist docs/vue-3",
|
|
47
47
|
"docs:install:vue-2": "cd docs-src/vue-2 && npm install",
|
|
48
|
+
"docs:install:vue-3": "cd docs-src/vue-3 && npm install",
|
|
48
49
|
"build:docs:vue-2": "cd docs-src/vue-2 && npm run build",
|
|
49
|
-
"build:docs": "npm run build
|
|
50
|
+
"build:docs:vue-3": "cd docs-src/vue-3 && npm run build",
|
|
51
|
+
"build:docs": "npm run build:docs:vue-3",
|
|
50
52
|
"publish:verdaccio:vue-2": "npm run build && npm publish --registry=http://127.0.0.1:4873 --@stackline:registry=http://127.0.0.1:4873 --tag vue-2 --access public",
|
|
53
|
+
"publish:verdaccio:vue-3": "npm run build && npm publish --registry=http://127.0.0.1:4873 --@stackline:registry=http://127.0.0.1:4873 --tag vue-3 --access public",
|
|
51
54
|
"typecheck": "tsc --noEmit",
|
|
52
55
|
"test": "node --test tests/*.test.cjs"
|
|
53
56
|
},
|
|
54
57
|
"peerDependencies": {
|
|
55
|
-
"vue": ">=
|
|
58
|
+
"vue": ">=3.0.0 <4.0.0"
|
|
56
59
|
},
|
|
57
60
|
"publishConfig": {
|
|
58
61
|
"access": "public"
|
|
@@ -60,6 +63,6 @@
|
|
|
60
63
|
"devDependencies": {
|
|
61
64
|
"tsup": "8.5.1",
|
|
62
65
|
"typescript": "5.9.3",
|
|
63
|
-
"vue": "
|
|
66
|
+
"vue": "3.0.0"
|
|
64
67
|
}
|
|
65
68
|
}
|