@stackline/vue-multiselect-dropdown 2.0.0 → 3.0.0

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 CHANGED
@@ -1,48 +1,45 @@
1
1
  # @stackline/vue-multiselect-dropdown
2
2
 
3
- > A maintained Vue 2 multiselect dropdown with controlled state, searchable/grouped options, lazy loading hooks, render functions, skins, body-overlay positioning, and ADA-friendly keyboard/ARIA behavior.
3
+ > A maintained Vue 3 multiselect dropdown with controlled state, searchable/grouped options, lazy loading hooks, render functions, skins, body-overlay positioning, and ADA-friendly keyboard/ARIA behavior.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@stackline/vue-multiselect-dropdown.svg?style=flat-square)](https://www.npmjs.com/package/@stackline/vue-multiselect-dropdown)
6
6
  [![license](https://img.shields.io/npm/l/@stackline/vue-multiselect-dropdown.svg?style=flat-square)](https://github.com/alexandroit/vue-multiselect-dropdown/blob/main/LICENSE)
7
- [![Vue 2](https://img.shields.io/badge/Vue-2.x-42b883?style=flat-square&logo=vue.js)](https://alexandro.net/docs/vue/multiselect/vue-2/)
7
+ [![Vue 3](https://img.shields.io/badge/Vue-3.x-42b883?style=flat-square&logo=vue.js)](https://alexandro.net/docs/vue/multiselect/vue-3/)
8
8
 
9
- **[Documentation & Live Demos](https://alexandro.net/docs/vue/multiselect/)** | **[Vue 2 Demo](https://alexandro.net/docs/vue/multiselect/vue-2/)** | **[npm](https://www.npmjs.com/package/@stackline/vue-multiselect-dropdown)** | **[Repository](https://github.com/alexandroit/vue-multiselect-dropdown)**
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:** `2.0.0` for Vue `2.x`
11
+ **Current validation package release:** `3.0.0` 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 2 multiselect component for applications that need predictable selection state, search, grouping, skins, keyboard support, and live tested examples.
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 2: bind with `v-model`, pass `:data`, customize behavior through `:settings`, and listen for `@select`, `@de-select`, `@select-all`, `@de-select-all`, `@open`, and `@close`.
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
- | **2.x** | **Vue 2 only** | **`>=2.0.0 <3.0.0`** | **2.0.0** | [Vue 2 family docs](https://alexandro.net/docs/vue/multiselect/vue-2/) |
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@2.0.0 --save-exact
30
+ npm install @stackline/vue-multiselect-dropdown@3.0.0 --save-exact
31
31
  ```
32
32
 
33
33
  ## Setup
34
34
 
35
35
  ```js
36
- import Vue from 'vue';
36
+ import { createApp } from 'vue';
37
37
  import {
38
38
  VueMultiselect,
39
39
  VueMultiselectDropdown
40
40
  } from '@stackline/vue-multiselect-dropdown';
41
41
 
42
- Vue.use(VueMultiselect);
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 2 docs:
132
+ Vue 3 docs:
133
133
 
134
134
  ```bash
135
- cd docs-src/vue-2
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 = `
@@ -1063,7 +1066,7 @@ var styles = `
1063
1066
  }
1064
1067
  }
1065
1068
 
1066
- /* stackline-vue2-live-20260527 */
1069
+ /* stackline-vue3-live-20260527 */
1067
1070
  `;
1068
1071
  function ensureDropdownStyles() {
1069
1072
  if (typeof document === "undefined") {
@@ -1141,12 +1144,45 @@ function iconPath(name) {
1141
1144
  }
1142
1145
  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
1146
  }
1144
- function renderIcon(h, name, className = "vmsd-icon") {
1147
+ function renderIcon(h2, name, className = "vmsd-icon") {
1145
1148
  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 h("svg", { class: className, attrs: { viewBox, focusable: "false", "aria-hidden": "true" } }, [
1147
- h("path", { attrs: { d: iconPath(name) } })
1149
+ return h2("svg", { class: className, attrs: { viewBox, focusable: "false", "aria-hidden": "true" } }, [
1150
+ h2("path", { attrs: { d: iconPath(name) } })
1148
1151
  ]);
1149
1152
  }
1153
+ function capitalize(value) {
1154
+ return value ? value.charAt(0).toUpperCase() + value.slice(1) : value;
1155
+ }
1156
+ function normalizeVue2RenderData(data) {
1157
+ if (!data) {
1158
+ return null;
1159
+ }
1160
+ const props = {};
1161
+ for (const [key, value] of Object.entries(data)) {
1162
+ if (key === "attrs" || key === "domProps") {
1163
+ Object.assign(props, value);
1164
+ continue;
1165
+ }
1166
+ if (key === "on" && value && typeof value === "object") {
1167
+ for (const [eventName, handler] of Object.entries(value)) {
1168
+ props[`on${capitalize(eventName)}`] = handler;
1169
+ }
1170
+ continue;
1171
+ }
1172
+ props[key] = value;
1173
+ }
1174
+ return props;
1175
+ }
1176
+ var h = (...args) => {
1177
+ const [tag, data, children] = args;
1178
+ if (args.length === 1) {
1179
+ return (0, import_vue.h)(tag);
1180
+ }
1181
+ if (args.length === 2 && (Array.isArray(data) || typeof data === "string" || typeof data === "number" || data == null)) {
1182
+ return (0, import_vue.h)(tag, null, data);
1183
+ }
1184
+ return (0, import_vue.h)(tag, normalizeVue2RenderData(data), children);
1185
+ };
1150
1186
  function isPrimitiveItem(item) {
1151
1187
  return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
1152
1188
  }
@@ -1235,11 +1271,11 @@ function mergeUniqueItems(base, extra, settings) {
1235
1271
  }
1236
1272
  return Array.from(bucket.values());
1237
1273
  }
1238
- function callRenderFunction(renderFunction, h, item, context) {
1274
+ function callRenderFunction(renderFunction, h2, item, context) {
1239
1275
  if (!renderFunction) {
1240
1276
  return null;
1241
1277
  }
1242
- return renderFunction(item, context, h);
1278
+ return renderFunction(item, context, h2);
1243
1279
  }
1244
1280
  function escapeSelectorValue(value) {
1245
1281
  if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
@@ -1259,15 +1295,31 @@ function isTextInputTarget(target) {
1259
1295
  }
1260
1296
  var VueMultiselectDropdown = {
1261
1297
  name: "VueMultiselectDropdown",
1262
- model: {
1263
- prop: "value",
1264
- event: "input"
1265
- },
1298
+ emits: [
1299
+ "update:modelValue",
1300
+ "input",
1301
+ "update:selectedItems",
1302
+ "change",
1303
+ "select",
1304
+ "de-select",
1305
+ "select-all",
1306
+ "de-select-all",
1307
+ "group-select",
1308
+ "group-de-select",
1309
+ "scroll-to-end",
1310
+ "add-filter-new-item",
1311
+ "open",
1312
+ "close"
1313
+ ],
1266
1314
  props: {
1267
1315
  data: {
1268
1316
  type: Array,
1269
1317
  default: () => []
1270
1318
  },
1319
+ modelValue: {
1320
+ type: Array,
1321
+ default: void 0
1322
+ },
1271
1323
  value: {
1272
1324
  type: Array,
1273
1325
  default: void 0
@@ -1333,6 +1385,9 @@ var VueMultiselectDropdown = {
1333
1385
  if (Array.isArray(this.selectedItems)) {
1334
1386
  return this.selectedItems;
1335
1387
  }
1388
+ if (Array.isArray(this.modelValue)) {
1389
+ return this.modelValue;
1390
+ }
1336
1391
  if (Array.isArray(this.value)) {
1337
1392
  return this.value;
1338
1393
  }
@@ -1397,7 +1452,7 @@ var VueMultiselectDropdown = {
1397
1452
  window.addEventListener("resize", this.updateMenuPosition);
1398
1453
  window.addEventListener("scroll", this.updateMenuPosition, true);
1399
1454
  },
1400
- beforeDestroy() {
1455
+ beforeUnmount() {
1401
1456
  document.removeEventListener("click", this.onDocumentClick, true);
1402
1457
  document.removeEventListener("keydown", this.onDocumentKeydown, true);
1403
1458
  window.removeEventListener("resize", this.updateMenuPosition);
@@ -1419,9 +1474,10 @@ var VueMultiselectDropdown = {
1419
1474
  return this.filteredItems.filter((item) => !isDisabledItem(item));
1420
1475
  },
1421
1476
  emitSelection(items) {
1422
- if (!Array.isArray(this.selectedItems) && !Array.isArray(this.value)) {
1477
+ if (!Array.isArray(this.selectedItems) && !Array.isArray(this.modelValue) && !Array.isArray(this.value)) {
1423
1478
  this.internalSelected = items;
1424
1479
  }
1480
+ this.$emit("update:modelValue", items);
1425
1481
  this.$emit("input", items);
1426
1482
  this.$emit("update:selectedItems", items);
1427
1483
  this.$emit("change", items);
@@ -1786,7 +1842,7 @@ var VueMultiselectDropdown = {
1786
1842
  this.menuStyle = style;
1787
1843
  }
1788
1844
  },
1789
- render(h) {
1845
+ render() {
1790
1846
  const settings = this.resolvedSettings;
1791
1847
  const skin = String(settings.skin || settings.theme || "classic");
1792
1848
  const skinFallbackClass = ["classic", "material", "dark", "custom"].includes(skin) ? "" : "theme-custom";
@@ -2074,11 +2130,11 @@ var StacklineVueMultiselect = VueMultiselectDropdown;
2074
2130
 
2075
2131
  // src/plugin.ts
2076
2132
  var VueMultiselect = {
2077
- install(Vue) {
2078
- Vue.component("StacklineVueMultiselect", VueMultiselectDropdown);
2079
- Vue.component("VueMultiselectDropdown", VueMultiselectDropdown);
2080
- Vue.component("vue-multiselect-dropdown", VueMultiselectDropdown);
2081
- Vue.component("stackline-vue-multiselect", VueMultiselectDropdown);
2133
+ install(app) {
2134
+ app.component("StacklineVueMultiselect", VueMultiselectDropdown);
2135
+ app.component("VueMultiselectDropdown", VueMultiselectDropdown);
2136
+ app.component("vue-multiselect-dropdown", VueMultiselectDropdown);
2137
+ app.component("stackline-vue-multiselect", VueMultiselectDropdown);
2082
2138
  }
2083
2139
  };
2084
2140
  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
- model: {
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
- beforeDestroy(this: any): void;
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, h: CreateElement): any;
186
+ render(this: any): any;
187
187
  };
188
188
  declare const StacklineVueMultiselect: {
189
189
  name: string;
190
- model: {
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
- beforeDestroy(this: any): void;
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, h: CreateElement): 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
- model: {
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
- beforeDestroy(this: any): void;
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, h: CreateElement): any;
186
+ render(this: any): any;
187
187
  };
188
188
  declare const StacklineVueMultiselect: {
189
189
  name: string;
190
- model: {
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
- beforeDestroy(this: any): void;
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, h: CreateElement): 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 = `
@@ -1034,7 +1037,7 @@ var styles = `
1034
1037
  }
1035
1038
  }
1036
1039
 
1037
- /* stackline-vue2-live-20260527 */
1040
+ /* stackline-vue3-live-20260527 */
1038
1041
  `;
1039
1042
  function ensureDropdownStyles() {
1040
1043
  if (typeof document === "undefined") {
@@ -1112,12 +1115,45 @@ function iconPath(name) {
1112
1115
  }
1113
1116
  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
1117
  }
1115
- function renderIcon(h, name, className = "vmsd-icon") {
1118
+ function renderIcon(h2, name, className = "vmsd-icon") {
1116
1119
  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 h("svg", { class: className, attrs: { viewBox, focusable: "false", "aria-hidden": "true" } }, [
1118
- h("path", { attrs: { d: iconPath(name) } })
1120
+ return h2("svg", { class: className, attrs: { viewBox, focusable: "false", "aria-hidden": "true" } }, [
1121
+ h2("path", { attrs: { d: iconPath(name) } })
1119
1122
  ]);
1120
1123
  }
1124
+ function capitalize(value) {
1125
+ return value ? value.charAt(0).toUpperCase() + value.slice(1) : value;
1126
+ }
1127
+ function normalizeVue2RenderData(data) {
1128
+ if (!data) {
1129
+ return null;
1130
+ }
1131
+ const props = {};
1132
+ for (const [key, value] of Object.entries(data)) {
1133
+ if (key === "attrs" || key === "domProps") {
1134
+ Object.assign(props, value);
1135
+ continue;
1136
+ }
1137
+ if (key === "on" && value && typeof value === "object") {
1138
+ for (const [eventName, handler] of Object.entries(value)) {
1139
+ props[`on${capitalize(eventName)}`] = handler;
1140
+ }
1141
+ continue;
1142
+ }
1143
+ props[key] = value;
1144
+ }
1145
+ return props;
1146
+ }
1147
+ var h = (...args) => {
1148
+ const [tag, data, children] = args;
1149
+ if (args.length === 1) {
1150
+ return vueH(tag);
1151
+ }
1152
+ if (args.length === 2 && (Array.isArray(data) || typeof data === "string" || typeof data === "number" || data == null)) {
1153
+ return vueH(tag, null, data);
1154
+ }
1155
+ return vueH(tag, normalizeVue2RenderData(data), children);
1156
+ };
1121
1157
  function isPrimitiveItem(item) {
1122
1158
  return typeof item === "string" || typeof item === "number" || typeof item === "boolean";
1123
1159
  }
@@ -1206,11 +1242,11 @@ function mergeUniqueItems(base, extra, settings) {
1206
1242
  }
1207
1243
  return Array.from(bucket.values());
1208
1244
  }
1209
- function callRenderFunction(renderFunction, h, item, context) {
1245
+ function callRenderFunction(renderFunction, h2, item, context) {
1210
1246
  if (!renderFunction) {
1211
1247
  return null;
1212
1248
  }
1213
- return renderFunction(item, context, h);
1249
+ return renderFunction(item, context, h2);
1214
1250
  }
1215
1251
  function escapeSelectorValue(value) {
1216
1252
  if (typeof CSS !== "undefined" && typeof CSS.escape === "function") {
@@ -1230,15 +1266,31 @@ function isTextInputTarget(target) {
1230
1266
  }
1231
1267
  var VueMultiselectDropdown = {
1232
1268
  name: "VueMultiselectDropdown",
1233
- model: {
1234
- prop: "value",
1235
- event: "input"
1236
- },
1269
+ emits: [
1270
+ "update:modelValue",
1271
+ "input",
1272
+ "update:selectedItems",
1273
+ "change",
1274
+ "select",
1275
+ "de-select",
1276
+ "select-all",
1277
+ "de-select-all",
1278
+ "group-select",
1279
+ "group-de-select",
1280
+ "scroll-to-end",
1281
+ "add-filter-new-item",
1282
+ "open",
1283
+ "close"
1284
+ ],
1237
1285
  props: {
1238
1286
  data: {
1239
1287
  type: Array,
1240
1288
  default: () => []
1241
1289
  },
1290
+ modelValue: {
1291
+ type: Array,
1292
+ default: void 0
1293
+ },
1242
1294
  value: {
1243
1295
  type: Array,
1244
1296
  default: void 0
@@ -1304,6 +1356,9 @@ var VueMultiselectDropdown = {
1304
1356
  if (Array.isArray(this.selectedItems)) {
1305
1357
  return this.selectedItems;
1306
1358
  }
1359
+ if (Array.isArray(this.modelValue)) {
1360
+ return this.modelValue;
1361
+ }
1307
1362
  if (Array.isArray(this.value)) {
1308
1363
  return this.value;
1309
1364
  }
@@ -1368,7 +1423,7 @@ var VueMultiselectDropdown = {
1368
1423
  window.addEventListener("resize", this.updateMenuPosition);
1369
1424
  window.addEventListener("scroll", this.updateMenuPosition, true);
1370
1425
  },
1371
- beforeDestroy() {
1426
+ beforeUnmount() {
1372
1427
  document.removeEventListener("click", this.onDocumentClick, true);
1373
1428
  document.removeEventListener("keydown", this.onDocumentKeydown, true);
1374
1429
  window.removeEventListener("resize", this.updateMenuPosition);
@@ -1390,9 +1445,10 @@ var VueMultiselectDropdown = {
1390
1445
  return this.filteredItems.filter((item) => !isDisabledItem(item));
1391
1446
  },
1392
1447
  emitSelection(items) {
1393
- if (!Array.isArray(this.selectedItems) && !Array.isArray(this.value)) {
1448
+ if (!Array.isArray(this.selectedItems) && !Array.isArray(this.modelValue) && !Array.isArray(this.value)) {
1394
1449
  this.internalSelected = items;
1395
1450
  }
1451
+ this.$emit("update:modelValue", items);
1396
1452
  this.$emit("input", items);
1397
1453
  this.$emit("update:selectedItems", items);
1398
1454
  this.$emit("change", items);
@@ -1757,7 +1813,7 @@ var VueMultiselectDropdown = {
1757
1813
  this.menuStyle = style;
1758
1814
  }
1759
1815
  },
1760
- render(h) {
1816
+ render() {
1761
1817
  const settings = this.resolvedSettings;
1762
1818
  const skin = String(settings.skin || settings.theme || "classic");
1763
1819
  const skinFallbackClass = ["classic", "material", "dark", "custom"].includes(skin) ? "" : "theme-custom";
@@ -2045,11 +2101,11 @@ var StacklineVueMultiselect = VueMultiselectDropdown;
2045
2101
 
2046
2102
  // src/plugin.ts
2047
2103
  var VueMultiselect = {
2048
- install(Vue) {
2049
- Vue.component("StacklineVueMultiselect", VueMultiselectDropdown);
2050
- Vue.component("VueMultiselectDropdown", VueMultiselectDropdown);
2051
- Vue.component("vue-multiselect-dropdown", VueMultiselectDropdown);
2052
- Vue.component("stackline-vue-multiselect", VueMultiselectDropdown);
2104
+ install(app) {
2105
+ app.component("StacklineVueMultiselect", VueMultiselectDropdown);
2106
+ app.component("VueMultiselectDropdown", VueMultiselectDropdown);
2107
+ app.component("vue-multiselect-dropdown", VueMultiselectDropdown);
2108
+ app.component("stackline-vue-multiselect", VueMultiselectDropdown);
2053
2109
  }
2054
2110
  };
2055
2111
  var plugin_default = VueMultiselect;
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@stackline/vue-multiselect-dropdown",
3
- "version": "2.0.0",
4
- "description": "A maintained Vue 2 multiselect dropdown with controlled state, skins, live docs, body overlays, and ADA-friendly keyboard support.",
3
+ "version": "3.0.0",
4
+ "description": "A maintained Vue 3 multiselect dropdown with controlled state, skins, live docs, body overlays, and ADA-friendly keyboard support.",
5
5
  "keywords": [
6
6
  "vue",
7
- "vue 2",
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-2/",
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-2",
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:docs:vue-2",
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": ">=2.0.0 <3.0.0"
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": "2.0.0"
66
+ "vue": "3.0.0"
64
67
  }
65
68
  }