@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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@signal24/vue-foundation",
3
3
  "type": "module",
4
- "version": "4.25.3",
4
+ "version": "4.25.4",
5
5
  "description": "Common components, directives, and helpers for Vue 3 apps",
6
6
  "module": "./dist/vue-foundation.es.js",
7
7
  "exports": {
@@ -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, type Ref, ref, watch } from 'vue';
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[]>([]) as 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
- handleValueChanged();
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 = effectiveFormatter.value(realOption!);
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 ? effectiveFormatter.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.unshift(option);
572
+ loadedOptions.value!.unshift(option);
563
573
  }
564
574
 
565
575
  function focusNextInput() {