@signal24/vue-foundation 4.25.3 → 4.25.4
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
CHANGED
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
|
|
52
52
|
<script lang="ts" setup generic="T, V = T">
|
|
53
53
|
import { debounce, groupBy, isEqual, uniq } from 'lodash';
|
|
54
|
-
import { computed, onMounted,
|
|
54
|
+
import { computed, onMounted, ref, watch } from 'vue';
|
|
55
55
|
|
|
56
56
|
import { escapeHtml } from '../helpers/string';
|
|
57
57
|
import type { VfSmartSelectOptionDescriptor } from './vf-smart-select.types';
|
|
@@ -63,6 +63,7 @@ const VALID_KEYS = `\`1234567890-=[]\\;',./~!@#$%^&*()_+{}|:"<>?qwertyuiopasdfgh
|
|
|
63
63
|
|
|
64
64
|
const props = defineProps<{
|
|
65
65
|
modelValue: V | null;
|
|
66
|
+
loadingText?: string;
|
|
66
67
|
loadOptions?: (searchText: string | null) => Promise<T[]>;
|
|
67
68
|
options?: T[];
|
|
68
69
|
prependOptions?: T[];
|
|
@@ -82,6 +83,7 @@ const props = defineProps<{
|
|
|
82
83
|
formatter?: (option: T) => string;
|
|
83
84
|
subtitleFormatter?: (option: T) => string;
|
|
84
85
|
classForOption?: (option: T) => string;
|
|
86
|
+
selectionFormatter?: (option: T) => string;
|
|
85
87
|
nullTitle?: string;
|
|
86
88
|
noResultsText?: string;
|
|
87
89
|
disabled?: boolean;
|
|
@@ -108,7 +110,7 @@ const optionsContainer = ref<HTMLDivElement>();
|
|
|
108
110
|
|
|
109
111
|
const isLoading = ref(false);
|
|
110
112
|
const isLoaded = ref(false);
|
|
111
|
-
const loadedOptions = ref<T[]>(
|
|
113
|
+
const loadedOptions = ref<T[]>();
|
|
112
114
|
const isSearching = ref(false);
|
|
113
115
|
const searchText = ref('');
|
|
114
116
|
const selectedOption = ref<T | null>(null);
|
|
@@ -120,7 +122,7 @@ const shouldShowCreateTextOnNewItem = computed(() => props.showCreateTextOnNewIt
|
|
|
120
122
|
|
|
121
123
|
const effectivePrependOptions = computed(() => props.prependOptions ?? []);
|
|
122
124
|
const effectiveAppendOptions = computed(() => props.appendOptions ?? []);
|
|
123
|
-
const effectiveDisabled = computed(() => !!props.disabled);
|
|
125
|
+
const effectiveDisabled = computed(() => !!props.disabled || (!props.options && !loadedOptions.value));
|
|
124
126
|
const effectivePlaceholder = computed(() => {
|
|
125
127
|
if (!isLoaded.value && props.preload) return 'Loading...';
|
|
126
128
|
if (props.nullTitle) return props.nullTitle;
|
|
@@ -149,8 +151,12 @@ const effectiveFormatter = computed(() => {
|
|
|
149
151
|
if (props.labelField) return (option: T) => String(option[props.labelField!]);
|
|
150
152
|
return (option: T) => String(option);
|
|
151
153
|
});
|
|
154
|
+
const effectiveSelectionFormatter = computed(() => {
|
|
155
|
+
if (props.selectionFormatter) return props.selectionFormatter;
|
|
156
|
+
return effectiveFormatter.value;
|
|
157
|
+
});
|
|
152
158
|
|
|
153
|
-
const allOptions = computed(() => [...effectivePrependOptions.value, ...loadedOptions.value, ...effectiveAppendOptions.value]);
|
|
159
|
+
const allOptions = computed(() => [...effectivePrependOptions.value, ...(loadedOptions.value ?? []), ...effectiveAppendOptions.value]);
|
|
154
160
|
const isGrouped = computed(() => !!(props.groupField || props.groupFormatter));
|
|
155
161
|
|
|
156
162
|
const optionsDescriptors = computed(() => {
|
|
@@ -249,7 +255,7 @@ watch(() => props.modelValue, handleValueChanged);
|
|
|
249
255
|
watch(
|
|
250
256
|
() => props.options,
|
|
251
257
|
() => {
|
|
252
|
-
loadedOptions.value = props.options
|
|
258
|
+
loadedOptions.value = props.options;
|
|
253
259
|
isLoaded.value = true;
|
|
254
260
|
}
|
|
255
261
|
);
|
|
@@ -301,11 +307,15 @@ onMounted(async () => {
|
|
|
301
307
|
if (props.options) {
|
|
302
308
|
loadedOptions.value = [...props.options];
|
|
303
309
|
isLoaded.value = true;
|
|
304
|
-
} else if (props.preload) {
|
|
310
|
+
} else if (props.loadOptions && props.preload) {
|
|
305
311
|
await loadRemoteOptions();
|
|
306
312
|
}
|
|
307
313
|
|
|
308
|
-
|
|
314
|
+
if (!props.options && (props.valueField || props.valueExtractor)) {
|
|
315
|
+
searchText.value = props.loadingText ?? '...';
|
|
316
|
+
} else {
|
|
317
|
+
handleValueChanged();
|
|
318
|
+
}
|
|
309
319
|
|
|
310
320
|
watch(selectedOption, () => {
|
|
311
321
|
if (selectedOption.value !== props.modelValue) {
|
|
@@ -536,7 +546,7 @@ function selectOption(option: VfSmartSelectOptionDescriptor<T>) {
|
|
|
536
546
|
const selectedDecoratedOption = optionsDescriptors.value.find(decoratedOption => decoratedOption.key == option.key);
|
|
537
547
|
const realOption = selectedDecoratedOption!.ref;
|
|
538
548
|
selectedOption.value = realOption!;
|
|
539
|
-
selectedOptionTitle.value =
|
|
549
|
+
selectedOptionTitle.value = effectiveSelectionFormatter.value(realOption!);
|
|
540
550
|
searchText.value = selectedOptionTitle.value ?? '';
|
|
541
551
|
}
|
|
542
552
|
|
|
@@ -549,7 +559,7 @@ function handleValueChanged() {
|
|
|
549
559
|
selectedOption.value = effectiveValueExtractor.value
|
|
550
560
|
? allOptions.value.find(o => props.modelValue === effectiveValueExtractor.value!(o))
|
|
551
561
|
: props.modelValue;
|
|
552
|
-
selectedOptionTitle.value = selectedOption.value !== null ?
|
|
562
|
+
selectedOptionTitle.value = selectedOption.value !== null ? effectiveSelectionFormatter.value(selectedOption.value) : null;
|
|
553
563
|
searchText.value = selectedOptionTitle.value ?? '';
|
|
554
564
|
} else {
|
|
555
565
|
selectedOption.value = null;
|
|
@@ -559,7 +569,7 @@ function handleValueChanged() {
|
|
|
559
569
|
}
|
|
560
570
|
|
|
561
571
|
function addRemoteOption(option: T) {
|
|
562
|
-
loadedOptions.value
|
|
572
|
+
loadedOptions.value!.unshift(option);
|
|
563
573
|
}
|
|
564
574
|
|
|
565
575
|
function focusNextInput() {
|