@signal24/vue-foundation 3.7.1 → 3.7.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,6 +1,6 @@
1
1
  {
2
2
  "name": "@signal24/vue-foundation",
3
- "version": "3.7.1",
3
+ "version": "3.7.4",
4
4
  "description": "Common components, directives, and helpers for Vue 3 apps",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
@@ -1,30 +1,39 @@
1
1
  <template>
2
- <div class="vf-overlay vf-modal-wrap">
3
- <form
4
- action="."
5
- class="vf-modal"
6
- :class="{ scrolls: $isPropTruthy(this.scrolls) }"
7
- @submit.prevent="$emit('formSubmit')"
8
- >
9
- <div v-if="$slots.header" class="vf-modal-header">
10
- <slot name="header" />
11
- <i v-if="$isPropTruthy(this.closeX)" class="close" @click="$parent.$dismiss()"></i>
12
- </div>
13
- <div class="vf-modal-content">
14
- <slot />
15
- </div>
16
- <div v-if="$slots.footer" class="vf-modal-footer">
17
- <slot name="footer" />
18
- </div>
19
- </form>
20
- </div>
2
+ <Teleport to="#vf-modal-target">
3
+ <div class="vf-overlay vf-modal-wrap" :class="class">
4
+ <form
5
+ action="."
6
+ class="vf-modal"
7
+ :class="{ scrolls: $isPropTruthy(this.scrolls) }"
8
+ @submit.prevent="$emit('formSubmit')"
9
+ >
10
+ <div v-if="$slots.header" class="vf-modal-header">
11
+ <slot name="header" />
12
+ <i v-if="$isPropTruthy(this.closeX)" class="close" @click="$parent.$dismiss()"></i>
13
+ </div>
14
+ <div class="vf-modal-content">
15
+ <slot />
16
+ </div>
17
+ <div v-if="$slots.footer" class="vf-modal-footer">
18
+ <slot name="footer" />
19
+ </div>
20
+ </form>
21
+ </div>
22
+ </Teleport>
21
23
  </template>
22
24
 
23
25
  <script>
24
26
  export default {
25
- props: ['closeOnMaskClick', 'scrolls', 'closeX'],
27
+ props: ['closeOnMaskClick', 'scrolls', 'closeX', 'class'],
26
28
  emits: ['formSubmit'],
27
29
 
30
+ beforeCreate() {
31
+ const targetEl = document.getElementById('vf-modal-target') ?? document.createElement('div');
32
+ targetEl.id = 'vf-modal-target';
33
+ targetEl.removeAttribute('inert');
34
+ document.body.appendChild(targetEl);
35
+ },
36
+
28
37
  mounted() {
29
38
  window.addEventListener('keydown', this.handleEscapeKey);
30
39
  document.body.classList.add('vf-modal-open');
@@ -37,6 +37,7 @@
37
37
 
38
38
  <script>
39
39
  import debounce from 'lodash/debounce';
40
+ import isEqual from 'lodash/isEqual';
40
41
 
41
42
  const nullSymbol = Symbol(null);
42
43
  const createSymbol = Symbol('create');
@@ -116,6 +117,10 @@ export default {
116
117
  return this.noResultsText || 'No options match your search.';
117
118
  },
118
119
 
120
+ effectiveRemoteSearch() {
121
+ return this.$isPropTruthy(this.remoteSearch);
122
+ },
123
+
119
124
  /**
120
125
  * OPTIONS GENERATION
121
126
  */
@@ -217,21 +222,33 @@ export default {
217
222
  },
218
223
 
219
224
  url() {
225
+ console.log('url changed');
220
226
  this.handleSourceUpdate();
221
227
  },
222
228
 
223
- urlParams() {
224
- this.handleSourceUpdate();
229
+ // we should probably solve this more consistently across the board,
230
+ // but for now: urlParams may be a hardcoded object in the parent, so
231
+ // on re-render, a new object literal may be created, which is *technically*
232
+ // a change that will fire this
233
+ urlParams(newValue, oldValue) {
234
+ if (!isEqual(oldValue, newValue)) {
235
+ this.handleSourceUpdate();
236
+ }
225
237
  },
226
238
 
227
239
  // data
228
240
 
229
241
  optionsDescriptors() {
230
- this.shouldDisplayOptions && setTimeout(this.highlightInitialOption, 0);
242
+ if (this.shouldDisplayOptions) {
243
+ setTimeout(this.highlightInitialOption, 0);
244
+ }
231
245
  },
232
246
 
233
247
  searchText() {
234
- if (this.isSearching && !this.searchText.trim().length) this.isSearching = false;
248
+ // don't disable searching here if it's remote search, as that will need to be done after the fetch
249
+ if (this.isSearching && !this.effectiveRemoteSearch && !this.searchText.trim().length) {
250
+ this.isSearching = false;
251
+ }
235
252
  },
236
253
 
237
254
  shouldDisplayOptions() {
@@ -260,7 +277,7 @@ export default {
260
277
  this.loadedOptions = this.options;
261
278
  this.isLoaded = true;
262
279
  } else if (this.$isPropTruthy(this.preload)) {
263
- await this.performInitialLoad();
280
+ await this.loadRemoteOptions();
264
281
  }
265
282
 
266
283
  this.handleValueChanged();
@@ -270,21 +287,24 @@ export default {
270
287
  this.selectedOption && this.effectiveValueKey
271
288
  ? this.selectedOption[this.effectiveValueKey]
272
289
  : this.selectedOption;
273
- newValue === this.modelValue || this.$emit('update:modelValue', newValue);
290
+ if (newValue !== this.modelValue) {
291
+ this.$emit('update:modelValue', newValue);
292
+ }
274
293
  });
294
+
295
+ if (this.effectiveRemoteSearch) {
296
+ this.$watch('searchText', debounce(this.reloadOptionsIfSearching, 250));
297
+ }
275
298
  },
276
299
 
277
300
  methods: {
278
- async performInitialLoad() {
301
+ async loadRemoteOptions() {
279
302
  await this.reloadOptions();
280
303
  this.$emit('optionsLoaded', this.loadedOptions);
281
-
282
- if (this.$isPropTruthy(this.remoteSearch)) {
283
- this.$watch('searchText', debounce(this.reloadOptionsIfSearching, 250));
284
- }
285
304
  },
286
305
 
287
306
  handleSourceUpdate() {
307
+ console.log('source updated');
288
308
  if (this.preload) return this.reloadOptions();
289
309
  if (!this.isLoaded) return;
290
310
  this.isLoaded = false;
@@ -294,7 +314,10 @@ export default {
294
314
  async reloadOptions() {
295
315
  let params = {};
296
316
  this.urlParams && Object.assign(params, this.urlParams);
297
- this.$isPropTruthy(this.remoteSearch) && this.searchText && (params.q = this.searchText);
317
+
318
+ if (this.effectiveRemoteSearch && this.isSearching && this.searchText) {
319
+ params.q = this.searchText;
320
+ }
298
321
 
299
322
  const result = await this.$http.get(this.url, { params: params });
300
323
  this.loadedOptions = result.data;
@@ -302,7 +325,10 @@ export default {
302
325
  },
303
326
 
304
327
  reloadOptionsIfSearching() {
305
- this.isSearching && this.reloadOptions();
328
+ if (this.isSearching) {
329
+ this.reloadOptions();
330
+ this.isSearching = this.searchText.trim().length > 0;
331
+ }
306
332
  },
307
333
 
308
334
  handleKeyDown(e) {
@@ -344,7 +370,9 @@ export default {
344
370
  }
345
371
 
346
372
  if (e.key === 'Delete' || e.key === 'Backspace') {
347
- if (this.searchText.length > 1) this.isSearching = true;
373
+ if (this.searchText.length > 1) {
374
+ this.isSearching = true;
375
+ }
348
376
  return;
349
377
  }
350
378
 
@@ -376,7 +404,7 @@ export default {
376
404
  },
377
405
 
378
406
  handleOptionsDisplayed() {
379
- this.isLoaded || this.$isPropTruthy(this.preload) || this.performInitialLoad();
407
+ this.isLoaded || this.loadRemoteOptions();
380
408
  this.teleportOptionsContainer();
381
409
  this.optionsListId && this.$refs.optionsContainer.setAttribute('id', this.optionsListId);
382
410
  },
@@ -452,6 +480,8 @@ export default {
452
480
  },
453
481
 
454
482
  selectOption(option) {
483
+ this.isSearching = false;
484
+
455
485
  if (option.key == nullSymbol) {
456
486
  this.searchText = '';
457
487
  this.selectedOption = null;