@signal24/vue-foundation 3.3.4 → 3.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/package.json +9 -9
- package/src/components/smart-select.vue +100 -57
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@signal24/vue-foundation",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.1",
|
|
4
4
|
"description": "Common components, directives, and helpers for Vue 3 apps",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,21 +8,21 @@
|
|
|
8
8
|
},
|
|
9
9
|
"license": "MIT",
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"axios": "^0.
|
|
11
|
+
"axios": "^0.26.0",
|
|
12
12
|
"jquery": "^3.6.0",
|
|
13
13
|
"lodash": "^4.17.21",
|
|
14
14
|
"moment": "^2.29.1",
|
|
15
|
-
"vue": "^3.2.29",
|
|
16
15
|
"vue-stash-nested": "fergusean/vue-stash-nested#vue-foundation-3"
|
|
17
16
|
},
|
|
18
17
|
"devDependencies": {
|
|
19
|
-
"@vue/eslint-config-prettier": "^
|
|
20
|
-
"eslint": "^
|
|
21
|
-
"eslint-plugin-prettier": "^
|
|
18
|
+
"@vue/eslint-config-prettier": "^7.0.0",
|
|
19
|
+
"eslint": "^8.10.0",
|
|
20
|
+
"eslint-plugin-prettier": "^4.0.0",
|
|
22
21
|
"eslint-plugin-simple-import-sort": "^7.0.0",
|
|
23
|
-
"eslint-plugin-vue": "^
|
|
22
|
+
"eslint-plugin-vue": "^8.5.0",
|
|
24
23
|
"prettier": "^2.5.1",
|
|
25
|
-
"sass": "^1.49.
|
|
26
|
-
"sass-loader": "^
|
|
24
|
+
"sass": "^1.49.9",
|
|
25
|
+
"sass-loader": "^12",
|
|
26
|
+
"vue": "^3.2.31"
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -41,14 +41,16 @@ import debounce from 'lodash/debounce';
|
|
|
41
41
|
const nullSymbol = Symbol(null);
|
|
42
42
|
const createSymbol = Symbol('create');
|
|
43
43
|
|
|
44
|
-
const VALID_KEYS = `\`1234567890-=[]
|
|
44
|
+
const VALID_KEYS = `\`1234567890-=[]\\;',./~!@#$%^&*()_+{}|:"<>?qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM`;
|
|
45
45
|
|
|
46
46
|
export default {
|
|
47
|
-
emits: ['optionsLoaded', 'createItem'],
|
|
47
|
+
emits: ['optionsLoaded', 'createItem', 'update:modelValue'],
|
|
48
48
|
|
|
49
49
|
props: [
|
|
50
50
|
'modelValue',
|
|
51
51
|
'options',
|
|
52
|
+
'prependOptions',
|
|
53
|
+
'appendOptions',
|
|
52
54
|
'preload',
|
|
53
55
|
'url',
|
|
54
56
|
'urlParams',
|
|
@@ -71,8 +73,7 @@ export default {
|
|
|
71
73
|
data() {
|
|
72
74
|
return {
|
|
73
75
|
isLoaded: false,
|
|
74
|
-
|
|
75
|
-
decoratedOptions: [],
|
|
76
|
+
loadedOptions: [],
|
|
76
77
|
isSearching: false,
|
|
77
78
|
searchText: '',
|
|
78
79
|
selectedOption: null,
|
|
@@ -84,8 +85,11 @@ export default {
|
|
|
84
85
|
},
|
|
85
86
|
|
|
86
87
|
computed: {
|
|
88
|
+
/**
|
|
89
|
+
* EFFECTIVE PROPS
|
|
90
|
+
*/
|
|
87
91
|
effectiveDisabled() {
|
|
88
|
-
return this.disabled || !this.
|
|
92
|
+
return this.disabled || !this.loadedOptions;
|
|
89
93
|
},
|
|
90
94
|
|
|
91
95
|
effectivePlaceholder() {
|
|
@@ -94,8 +98,73 @@ export default {
|
|
|
94
98
|
return this.placeholder || '';
|
|
95
99
|
},
|
|
96
100
|
|
|
101
|
+
effectiveIdKey() {
|
|
102
|
+
return this.idKey || 'id';
|
|
103
|
+
},
|
|
104
|
+
|
|
105
|
+
effectiveTitleKey() {
|
|
106
|
+
return this.titleKey || 'name';
|
|
107
|
+
},
|
|
108
|
+
|
|
109
|
+
effectiveValueKey() {
|
|
110
|
+
if (this.valueKey) return this.valueKey;
|
|
111
|
+
if (this.options && !Array.isArray(this.options)) return this.effectiveIdKey;
|
|
112
|
+
return undefined;
|
|
113
|
+
},
|
|
114
|
+
|
|
115
|
+
effectiveNoResultsText() {
|
|
116
|
+
return this.noResultsText || 'No options match your search.';
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* OPTIONS GENERATION
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
loadedOptionsArray() {
|
|
124
|
+
return this.arrayifyOptions(this.loadedOptions);
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
prependOptionsArray() {
|
|
128
|
+
return this.prependOptions ? this.arrayifyOptions(this.prependOptions) : [];
|
|
129
|
+
},
|
|
130
|
+
|
|
131
|
+
appendOptionsArray() {
|
|
132
|
+
return this.appendOptions ? this.arrayifyOptions(this.appendOptions) : [];
|
|
133
|
+
},
|
|
134
|
+
|
|
135
|
+
fullOptionsArray() {
|
|
136
|
+
return [...this.prependOptionsArray, ...this.loadedOptionsArray, ...this.appendOptionsArray];
|
|
137
|
+
},
|
|
138
|
+
|
|
139
|
+
optionsDescriptors() {
|
|
140
|
+
return this.fullOptionsArray.map((option, index) => {
|
|
141
|
+
const title = this.getOptionTitle(option);
|
|
142
|
+
const subtitle = this.getOptionSubtitle(option);
|
|
143
|
+
const strippedTitle = title ? title.text.trim().toLowerCase() : '';
|
|
144
|
+
const strippedSubtitle = subtitle ? subtitle.text.trim().toLowerCase() : '';
|
|
145
|
+
|
|
146
|
+
let searchContent = [];
|
|
147
|
+
if (this.searchFields) {
|
|
148
|
+
this.searchFields.forEach(field => {
|
|
149
|
+
option[field] && searchContent.push(String(option[field]).toLowerCase());
|
|
150
|
+
});
|
|
151
|
+
} else {
|
|
152
|
+
searchContent.push(strippedTitle);
|
|
153
|
+
strippedSubtitle && searchContent.push(strippedSubtitle);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return {
|
|
157
|
+
key: typeof option == 'object' ? option[this.effectiveIdKey] || index : option,
|
|
158
|
+
titleHtml: title.html,
|
|
159
|
+
subtitleHtml: subtitle?.html,
|
|
160
|
+
searchContent: searchContent.join(''),
|
|
161
|
+
ref: option
|
|
162
|
+
};
|
|
163
|
+
});
|
|
164
|
+
},
|
|
165
|
+
|
|
97
166
|
effectiveOptions() {
|
|
98
|
-
let options = [...this.
|
|
167
|
+
let options = [...this.optionsDescriptors];
|
|
99
168
|
|
|
100
169
|
if (this.isSearching) {
|
|
101
170
|
const strippedSearchText = this.searchText.trim().toLowerCase();
|
|
@@ -133,18 +202,6 @@ export default {
|
|
|
133
202
|
}
|
|
134
203
|
|
|
135
204
|
return options;
|
|
136
|
-
},
|
|
137
|
-
|
|
138
|
-
effectiveIdKey() {
|
|
139
|
-
return this.idKey || 'id';
|
|
140
|
-
},
|
|
141
|
-
|
|
142
|
-
effectiveTitleKey() {
|
|
143
|
-
return this.titleKey || 'name';
|
|
144
|
-
},
|
|
145
|
-
|
|
146
|
-
effectiveNoResultsText() {
|
|
147
|
-
return this.noResultsText || 'No options match your search.';
|
|
148
205
|
}
|
|
149
206
|
},
|
|
150
207
|
|
|
@@ -156,7 +213,7 @@ export default {
|
|
|
156
213
|
},
|
|
157
214
|
|
|
158
215
|
options() {
|
|
159
|
-
this.
|
|
216
|
+
this.loadedOptions = this.options;
|
|
160
217
|
},
|
|
161
218
|
|
|
162
219
|
url() {
|
|
@@ -169,32 +226,7 @@ export default {
|
|
|
169
226
|
|
|
170
227
|
// data
|
|
171
228
|
|
|
172
|
-
|
|
173
|
-
this.decoratedOptions = this.resolvedOptions.map((option, index) => {
|
|
174
|
-
const title = this.getOptionTitle(option);
|
|
175
|
-
const subtitle = this.getOptionSubtitle(option);
|
|
176
|
-
const strippedTitle = title ? title.text.trim().toLowerCase() : '';
|
|
177
|
-
const strippedSubtitle = subtitle ? subtitle.text.trim().toLowerCase() : '';
|
|
178
|
-
|
|
179
|
-
let searchContent = [];
|
|
180
|
-
if (this.searchFields) {
|
|
181
|
-
this.searchFields.forEach(field => {
|
|
182
|
-
option[field] && searchContent.push(String(option[field]).toLowerCase());
|
|
183
|
-
});
|
|
184
|
-
} else {
|
|
185
|
-
searchContent.push(strippedTitle);
|
|
186
|
-
strippedSubtitle && searchContent.push(strippedSubtitle);
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return {
|
|
190
|
-
key: typeof option == 'object' ? option[this.effectiveIdKey] || index : option,
|
|
191
|
-
titleHtml: title.html,
|
|
192
|
-
subtitleHtml: subtitle?.html,
|
|
193
|
-
searchContent: searchContent.join(''),
|
|
194
|
-
ref: option
|
|
195
|
-
};
|
|
196
|
-
});
|
|
197
|
-
|
|
229
|
+
optionsDescriptors() {
|
|
198
230
|
this.shouldDisplayOptions && setTimeout(this.highlightInitialOption, 0);
|
|
199
231
|
},
|
|
200
232
|
|
|
@@ -225,17 +257,19 @@ export default {
|
|
|
225
257
|
this.shouldShowCreateOption = this.$attrs['onCreateItem'] !== undefined;
|
|
226
258
|
|
|
227
259
|
if (this.options) {
|
|
228
|
-
this.
|
|
260
|
+
this.loadedOptions = this.options;
|
|
229
261
|
this.isLoaded = true;
|
|
230
262
|
} else if (this.$isPropTruthy(this.preload)) {
|
|
231
|
-
this.performInitialLoad();
|
|
263
|
+
await this.performInitialLoad();
|
|
232
264
|
}
|
|
233
265
|
|
|
234
266
|
this.handleValueChanged();
|
|
235
267
|
|
|
236
268
|
this.$watch('selectedOption', () => {
|
|
237
269
|
const newValue =
|
|
238
|
-
this.selectedOption && this.
|
|
270
|
+
this.selectedOption && this.effectiveValueKey
|
|
271
|
+
? this.selectedOption[this.effectiveValueKey]
|
|
272
|
+
: this.selectedOption;
|
|
239
273
|
newValue === this.modelValue || this.$emit('update:modelValue', newValue);
|
|
240
274
|
});
|
|
241
275
|
},
|
|
@@ -243,7 +277,7 @@ export default {
|
|
|
243
277
|
methods: {
|
|
244
278
|
async performInitialLoad() {
|
|
245
279
|
await this.reloadOptions();
|
|
246
|
-
this.$emit('optionsLoaded', this.
|
|
280
|
+
this.$emit('optionsLoaded', this.loadedOptions);
|
|
247
281
|
|
|
248
282
|
if (this.$isPropTruthy(this.remoteSearch)) {
|
|
249
283
|
this.$watch('searchText', debounce(this.reloadOptionsIfSearching, 250));
|
|
@@ -254,7 +288,7 @@ export default {
|
|
|
254
288
|
if (this.preload) return this.reloadOptions();
|
|
255
289
|
if (!this.isLoaded) return;
|
|
256
290
|
this.isLoaded = false;
|
|
257
|
-
this.
|
|
291
|
+
this.loadedOptions = [];
|
|
258
292
|
},
|
|
259
293
|
|
|
260
294
|
async reloadOptions() {
|
|
@@ -263,7 +297,7 @@ export default {
|
|
|
263
297
|
this.$isPropTruthy(this.remoteSearch) && this.searchText && (params.q = this.searchText);
|
|
264
298
|
|
|
265
299
|
const result = await this.$http.get(this.url, { params: params });
|
|
266
|
-
this.
|
|
300
|
+
this.loadedOptions = result.data;
|
|
267
301
|
this.isLoaded = true;
|
|
268
302
|
},
|
|
269
303
|
|
|
@@ -429,10 +463,10 @@ export default {
|
|
|
429
463
|
this.selectedOptionTitle = null;
|
|
430
464
|
this.$emit('createItem', createText);
|
|
431
465
|
} else {
|
|
432
|
-
const
|
|
466
|
+
const selectedDecoratedOption = this.optionsDescriptors.find(
|
|
433
467
|
decoratedOption => decoratedOption.key == option.key
|
|
434
468
|
);
|
|
435
|
-
const realOption =
|
|
469
|
+
const realOption = selectedDecoratedOption.ref;
|
|
436
470
|
this.selectedOption = realOption;
|
|
437
471
|
this.selectedOptionTitle = this.getOptionTitle(this.selectedOption).text;
|
|
438
472
|
this.searchText = this.selectedOptionTitle || '';
|
|
@@ -443,9 +477,9 @@ export default {
|
|
|
443
477
|
|
|
444
478
|
handleValueChanged() {
|
|
445
479
|
if (this.modelValue) {
|
|
446
|
-
if (this.
|
|
447
|
-
this.selectedOption = this.
|
|
448
|
-
option => option[this.
|
|
480
|
+
if (this.effectiveValueKey) {
|
|
481
|
+
this.selectedOption = this.fullOptionsArray.find(
|
|
482
|
+
option => option[this.effectiveValueKey] === this.modelValue
|
|
449
483
|
);
|
|
450
484
|
} else {
|
|
451
485
|
this.selectedOption = this.modelValue;
|
|
@@ -509,7 +543,16 @@ export default {
|
|
|
509
543
|
},
|
|
510
544
|
|
|
511
545
|
addRemoteOption(option) {
|
|
512
|
-
this.
|
|
546
|
+
this.loadedOptions.push(option);
|
|
547
|
+
},
|
|
548
|
+
|
|
549
|
+
arrayifyOptions(options) {
|
|
550
|
+
return Array.isArray(options)
|
|
551
|
+
? options
|
|
552
|
+
: Object.entries(options).map(entry => ({
|
|
553
|
+
[this.effectiveIdKey]: entry[0],
|
|
554
|
+
[this.effectiveTitleKey]: entry[1]
|
|
555
|
+
}));
|
|
513
556
|
}
|
|
514
557
|
}
|
|
515
558
|
};
|