@vcmap/ui 6.1.0-rc.1 → 6.1.0-rc.2

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.
Files changed (53) hide show
  1. package/dist/assets/cesium.js +1 -1
  2. package/dist/assets/{core-9d0cfec3.js → core-fd079400.js} +2 -2
  3. package/dist/assets/core.js +1 -1
  4. package/dist/assets/ol.js +1 -1
  5. package/dist/assets/ui-5135917c.css +1 -0
  6. package/dist/assets/{ui-08446666.js → ui-5135917c.js} +1218 -1190
  7. package/dist/assets/ui.js +1 -1
  8. package/dist/assets/vue.js +1 -1
  9. package/dist/assets/{vuetify-67025c41.js → vuetify-f02b7bb9.js} +1 -1
  10. package/dist/assets/vuetify.js +1 -1
  11. package/index.d.ts +2 -0
  12. package/index.js +1 -0
  13. package/package.json +1 -1
  14. package/src/application/VcsApp.vue.d.ts +4 -0
  15. package/src/application/VcsContainer.vue +5 -3
  16. package/src/application/VcsContainer.vue.d.ts +6 -0
  17. package/src/application/VcsNavbar.vue +10 -6
  18. package/src/application/VcsNavbar.vue.d.ts +2 -0
  19. package/src/components/buttons/VcsActionButtonList.vue +6 -4
  20. package/src/components/buttons/VcsToolButton.vue +0 -1
  21. package/src/components/form-inputs-controls/VcsDatePicker.vue +7 -1
  22. package/src/components/form-inputs-controls/VcsDatePicker.vue.d.ts +9 -0
  23. package/src/components/form-inputs-controls/VcsTextArea.vue +1 -1
  24. package/src/components/import/VcsImportComponent.vue +2 -0
  25. package/src/components/lists/VcsList.vue +15 -11
  26. package/src/components/lists/VcsList.vue.d.ts +9 -0
  27. package/src/components/lists/VcsTreeNode.vue +18 -11
  28. package/src/components/lists/VcsTreeview.vue +16 -8
  29. package/src/components/lists/VcsTreeview.vue.d.ts +18 -1
  30. package/src/components/tables/VcsDataTable.vue +14 -3
  31. package/src/components/tables/VcsDataTable.vue.d.ts +9 -0
  32. package/src/legend/VcsLegend.vue +1 -1
  33. package/src/manager/toolbox/ToolboxManagerComponent.vue +4 -4
  34. package/src/manager/toolbox/ToolboxManagerComponent.vue.d.ts +2 -2
  35. package/src/manager/toolbox/toolboxManager.d.ts +5 -0
  36. package/src/manager/toolbox/toolboxManager.js +7 -1
  37. package/src/manager/window/WindowComponent.vue +10 -0
  38. package/src/manager/window/WindowComponent.vue.d.ts +1 -0
  39. package/src/manager/window/WindowManager.vue +14 -4
  40. package/src/manager/window/WindowManager.vue.d.ts +1 -0
  41. package/src/navigation/MapNavigation.vue +5 -5
  42. package/src/navigation/MapNavigation.vue.d.ts +1 -1
  43. package/src/navigation/overviewMap.d.ts +6 -0
  44. package/src/navigation/overviewMap.js +14 -1
  45. package/src/search/markText.d.ts +1 -1
  46. package/src/search/markText.js +4 -4
  47. package/src/uiConfig.d.ts +9 -0
  48. package/src/uiConfig.js +1 -0
  49. package/dist/assets/ui-08446666.css +0 -1
  50. /package/dist/assets/{cesium-11e5bbc6.js → cesium-57fbd309.js} +0 -0
  51. /package/dist/assets/{ol-0d0ebb27.js → ol-50dfef96.js} +0 -0
  52. /package/dist/assets/{vue-2f81c7f8.js → vue-c3c55d88.js} +0 -0
  53. /package/dist/assets/{vuetify-67025c41.css → vuetify-f02b7bb9.css} +0 -0
package/dist/assets/ui.js CHANGED
@@ -1 +1 @@
1
- export * from "./ui-08446666.js";
1
+ export * from "./ui-5135917c.js";
@@ -1 +1 @@
1
- export * from "./vue-2f81c7f8.js";
1
+ export * from "./vue-c3c55d88.js";
@@ -10,7 +10,7 @@ function loadCss(href) {
10
10
  elem.onerror = reject;
11
11
  document.head.appendChild(elem);
12
12
  });
13
- } await loadCss('./assets/vuetify-67025c41.css');import { watch as X, onScopeDispose as tt, effectScope as Ul, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Ne, toRefs as Wt, capitalize as On, isVNode as Oc, Comment as Rc, unref as ot, warn as Ha, getCurrentInstance as Nc, ref as W, provide as Ae, inject as ye, defineComponent as Hc, camelize as Ir, h as jt, toRaw as Ee, createVNode as r, mergeProps as N, onBeforeUnmount as nt, readonly as Kl, onDeactivated as _r, onActivated as zc, onMounted as Ke, nextTick as Se, TransitionGroup as ql, Transition as Ht, isRef as _n, toRef as F, onBeforeMount as Xl, withDirectives as $e, resolveDirective as dt, vShow as xt, onUpdated as Wc, Text as jc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Uc, cloneVNode as Kc, createTextVNode as Pt, onUnmounted as qc, onBeforeUpdate as Xc, withModifiers as Pl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Tr } from "./vue-2f81c7f8.js";
13
+ } await loadCss('./assets/vuetify-f02b7bb9.css');import { watch as X, onScopeDispose as tt, effectScope as Ul, shallowRef as K, Fragment as ie, reactive as it, computed as b, watchEffect as Ne, toRefs as Wt, capitalize as On, isVNode as Oc, Comment as Rc, unref as ot, warn as Ha, getCurrentInstance as Nc, ref as W, provide as Ae, inject as ye, defineComponent as Hc, camelize as Ir, h as jt, toRaw as Ee, createVNode as r, mergeProps as N, onBeforeUnmount as nt, readonly as Kl, onDeactivated as _r, onActivated as zc, onMounted as Ke, nextTick as Se, TransitionGroup as ql, Transition as Ht, isRef as _n, toRef as F, onBeforeMount as Xl, withDirectives as $e, resolveDirective as dt, vShow as xt, onUpdated as Wc, Text as jc, resolveDynamicComponent as Yc, markRaw as Gc, Teleport as Uc, cloneVNode as Kc, createTextVNode as Pt, onUnmounted as qc, onBeforeUpdate as Xc, withModifiers as Pl, toDisplayString as Zc, vModelText as Qc, resolveComponent as Jc, render as Tr } from "./vue-c3c55d88.js";
14
14
  function rt(e, n) {
15
15
  let t;
16
16
  function a() {
@@ -1 +1 @@
1
- export * from "./vuetify-67025c41.js";
1
+ export * from "./vuetify-f02b7bb9.js";
package/index.d.ts CHANGED
@@ -240,6 +240,8 @@ export * from "./src/components/composables.js";
240
240
  export type * from "./src/components/composables.d.ts";
241
241
  export { default as Search } from "./src/search/search.js";
242
242
  export type * from "./src/search/search.d.ts";
243
+ export { markText } from "./src/search/markText.js";
244
+ export type * from "./src/search/markText.d.ts";
243
245
  export { default as ResultItemComponent } from "./src/search/ResultItem.vue";
244
246
  export type * from "./src/search/ResultItem.vue.d.ts";
245
247
  export { default as ResultsComponent } from "./src/search/ResultsComponent.vue";
package/index.js CHANGED
@@ -325,5 +325,6 @@ export * from './src/components/modelHelper.js';
325
325
  export * from './src/components/composables.js';
326
326
  export { LegendType, StyleRowType } from './src/legend/legendHelper.js';
327
327
  export { default as Search } from './src/search/search.js';
328
+ export { markText } from './src/search/markText.js';
328
329
  export { default as ResultItemComponent } from './src/search/ResultItem.vue';
329
330
  export { default as ResultsComponent } from './src/search/ResultsComponent.vue';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/ui",
3
- "version": "6.1.0-rc.1",
3
+ "version": "6.1.0-rc.2",
4
4
  "author": "Virtual City Systems",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -358,6 +358,10 @@ declare const _default: import("vue").DefineComponent<{
358
358
  * - open the legend window, if new layer has a config
359
359
  */
360
360
  readonly openLegendOnAdd?: boolean | undefined;
361
+ /**
362
+ * - can be used to apply a scale factor the the overviewMap
363
+ */
364
+ readonly overviewMapScaleFactor?: number | undefined;
361
365
  };
362
366
  showFooter: import("vue").ComputedRef<boolean>;
363
367
  footerHeight: import("vue").ComputedRef<number>;
@@ -10,13 +10,14 @@
10
10
  fluid
11
11
  absolute
12
12
  >
13
- <template v-if="xs">
13
+ <template v-if="smAndDown">
14
14
  <img
15
15
  v-if="mobileLogo"
16
16
  :src="mobileLogo"
17
17
  alt="Logo"
18
18
  draggable="false"
19
19
  class="mobile-logo"
20
+ :class="{ 'mobile-logo': sm }"
20
21
  />
21
22
  </template>
22
23
  <!--VcsButton
@@ -69,7 +70,6 @@
69
70
  left: 1rem;
70
71
  z-index: 1;
71
72
  }
72
-
73
73
  .mobile-attribution-btn {
74
74
  position: fixed;
75
75
  right: 2px;
@@ -111,10 +111,12 @@
111
111
  setup() {
112
112
  /** @type {import("../vcsUiApp.js").default} */
113
113
  const app = inject('vcsApp');
114
- const { xs } = useDisplay();
114
+ const { smAndDown, xs, sm } = useDisplay();
115
115
  return {
116
116
  config: app.uiConfig.config,
117
+ smAndDown,
117
118
  xs,
119
+ sm,
118
120
  mobileLogo: computed(
119
121
  () =>
120
122
  app.uiConfig.config.mobileLogo ??
@@ -278,8 +278,14 @@ declare const _default: import("vue").DefineComponent<{
278
278
  * - open the legend window, if new layer has a config
279
279
  */
280
280
  readonly openLegendOnAdd?: boolean | undefined;
281
+ /**
282
+ * - can be used to apply a scale factor the the overviewMap
283
+ */
284
+ readonly overviewMapScaleFactor?: number | undefined;
281
285
  };
286
+ smAndDown: import("vue").Ref<boolean>;
282
287
  xs: import("vue").Ref<boolean>;
288
+ sm: import("vue").Ref<boolean>;
283
289
  mobileLogo: import("vue").ComputedRef<any>;
284
290
  }, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
285
291
  attributionAction: {
@@ -14,7 +14,7 @@
14
14
  <div class="d-flex">
15
15
  <VcsActionButtonList
16
16
  :actions="mapActions"
17
- :overflow-count="3"
17
+ :overflow-count="smAndDown ? 2 : 3"
18
18
  :force-overflow="false"
19
19
  button="VcsToolButton"
20
20
  />
@@ -29,7 +29,7 @@
29
29
  />
30
30
  <VcsActionButtonList
31
31
  :actions="contentActions"
32
- :overflow-count="xs ? 3 : 4"
32
+ :overflow-count="smAndDown ? 2 : 3"
33
33
  :force-overflow="false"
34
34
  button="VcsToolButton"
35
35
  />
@@ -41,8 +41,9 @@
41
41
  />
42
42
  <VcsActionButtonList
43
43
  :actions="toolActions"
44
+ :overflow-count="smAndDown ? 1 : 2"
44
45
  :force-overflow="false"
45
- v-if="mdAndUp"
46
+ v-if="smAndUp"
46
47
  button="VcsToolButton"
47
48
  />
48
49
  </div>
@@ -50,7 +51,7 @@
50
51
  </v-col>
51
52
  <v-col class="d-flex justify-center flex-grow-2 mx-2">
52
53
  <div class="d-flex align-center">
53
- <template v-if="!xs">
54
+ <template v-if="!smAndDown">
54
55
  <img class="logo" :src="logo" draggable="false" alt="Logo" />
55
56
  </template>
56
57
  <div
@@ -63,10 +64,11 @@
63
64
  </div>
64
65
  </v-col>
65
66
  <v-col class="align-content-end d-flex justify-end">
66
- <v-toolbar-items v-if="mdAndUp">
67
+ <v-toolbar-items v-if="smAndUp">
67
68
  <div class="d-flex">
68
69
  <VcsActionButtonList
69
70
  :actions="projectActions"
71
+ :overflow-count="smAndDown ? 1 : 2"
70
72
  :force-overflow="false"
71
73
  button="VcsToolButton"
72
74
  />
@@ -206,7 +208,7 @@
206
208
  destroySearchAction();
207
209
  });
208
210
 
209
- const { xs, mdAndUp } = useDisplay();
211
+ const { xs, mdAndUp, smAndDown, smAndUp } = useDisplay();
210
212
 
211
213
  const density = computed(() => {
212
214
  return xs.value ? 'comfortable' : 'compact';
@@ -228,8 +230,10 @@
228
230
  config: app.uiConfig.config,
229
231
  logo,
230
232
  xs,
233
+ smAndDown,
231
234
  density,
232
235
  mdAndUp,
236
+ smAndUp,
233
237
  toolbarHeight,
234
238
  };
235
239
  },
@@ -42,8 +42,10 @@ declare const _default: import("vue").DefineComponent<{}, {
42
42
  config: any;
43
43
  logo: import("vue").ComputedRef<any>;
44
44
  xs: import("vue").Ref<boolean>;
45
+ smAndDown: import("vue").Ref<boolean>;
45
46
  density: import("vue").ComputedRef<"compact" | "comfortable">;
46
47
  mdAndUp: import("vue").Ref<boolean>;
48
+ smAndUp: import("vue").Ref<boolean>;
47
49
  toolbarHeight: import("vue").ComputedRef<number>;
48
50
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{}>>, {}, {}>;
49
51
  export default _default;
@@ -38,12 +38,14 @@
38
38
  </template>
39
39
  <VcsActionList :actions="overflowButtons" :disabled="disabled" />
40
40
  </v-menu>
41
- <v-spacer
42
- v-else-if="blockOverflow"
43
- class="flex-grow-0 d-inline-block px-2"
44
- />
41
+ <v-spacer v-else-if="blockOverflow" />
45
42
  </div>
46
43
  </template>
44
+ <style scoped lang="scss">
45
+ :deep(.v-spacer) {
46
+ width: calc(var(--v-vcs-font-size) * 1.25);
47
+ }
48
+ </style>
47
49
  <script>
48
50
  import { VIcon, VMenu, VSpacer } from 'vuetify/components';
49
51
  import VcsButton from './VcsButton.vue';
@@ -82,7 +82,6 @@
82
82
  * @vue-prop {string} icon - When given, will display an icon in the button. Replaces vuetify icon property.
83
83
  * @vue-prop {string} tooltip - Text content of a tooltip which appears on hover with default delay.
84
84
  * @vue-prop {('bottom' | 'left' | 'top' | 'right')} tooltipPosition - Position of the tooltip.
85
- * @vue-prop {Object<string, any>} tooltipProps - Properties to be passed to the tooltip {@link https://vuetifyjs.com/en/api/v-tooltip/#props|vuetify v-tooltip}
86
85
  * @vue-computed {string} appliedColor - color applied to button, depending on size and state
87
86
  * @vue-computed {boolean} hasDefaultSlot
88
87
  */
@@ -18,7 +18,8 @@
18
18
  v-model="localValue"
19
19
  hide-header
20
20
  @update:model-value="menuOpen = false"
21
- color="primary"
21
+ :color="datePickerProps.color ?? 'primary'"
22
+ v-bind="{ ...datePickerProps }"
22
23
  >
23
24
  <template #actions>
24
25
  <v-btn color="primary" @click="goToToday">
@@ -40,6 +41,7 @@
40
41
  * @description stylized wrapper around {@link https://vuetifyjs.com/en/components/date-pickers/#internationalization}.
41
42
  * @vue-prop {Date} modelValue - value of the date picker as a Date (changes to the Date Object are not tracked, handled as atomic value)
42
43
  * @vue-prop {string} [icon] - specify optional prepend icon, defaults to mdi-calendar
44
+ * @vue-prop {Object} [datePickerProps] - props that are passed to the {@link https://vuetifyjs.com/en/api/v-date-picker/ | VDatePicker}
43
45
  */
44
46
  export default {
45
47
  name: 'VcsDatePicker',
@@ -52,6 +54,10 @@
52
54
  type: String,
53
55
  default: 'mdi-calendar',
54
56
  },
57
+ datePickerProps: {
58
+ type: Object,
59
+ default: () => ({}),
60
+ },
55
61
  },
56
62
  components: {
57
63
  VMenu,
@@ -7,6 +7,10 @@ declare const _default: import("vue").DefineComponent<{
7
7
  type: StringConstructor;
8
8
  default: string;
9
9
  };
10
+ datePickerProps: {
11
+ type: ObjectConstructor;
12
+ default: () => {};
13
+ };
10
14
  }, {
11
15
  formattedDate: import("vue").WritableComputedRef<string>;
12
16
  localValue: import("vue").WritableComputedRef<Date>;
@@ -22,10 +26,15 @@ declare const _default: import("vue").DefineComponent<{
22
26
  type: StringConstructor;
23
27
  default: string;
24
28
  };
29
+ datePickerProps: {
30
+ type: ObjectConstructor;
31
+ default: () => {};
32
+ };
25
33
  }>> & {
26
34
  "onUpdate:modelValue"?: ((...args: any[]) => any) | undefined;
27
35
  }, {
28
36
  icon: string;
29
37
  modelValue: Date;
38
+ datePickerProps: Record<string, any>;
30
39
  }, {}>;
31
40
  export default _default;
@@ -110,7 +110,7 @@
110
110
  // Not color, just used if label is given
111
111
  :deep(.v-field--focused:not(.v-field--error) .v-field__outline *::after) {
112
112
  border-color: rgb(var(--v-theme-primary));
113
- border-width: 1px !important;
113
+ border-width: 0 0 1px !important;
114
114
  }
115
115
 
116
116
  // remove margin from prepended Icon
@@ -12,6 +12,7 @@
12
12
  v-bind="noListenerAttrs"
13
13
  v-model="files"
14
14
  />
15
+ <slot />
15
16
  <div class="d-flex justify-end gc-1 mx-3 pt-2 pb-1">
16
17
  <vcs-form-button
17
18
  variant="filled"
@@ -41,6 +42,7 @@
41
42
  * @vue-prop {function(Array<File>):boolean} importFiles - the callback to
42
43
  * @vue-prop {string[]} [fileTypes=[]] - accepted file types, see https://html.spec.whatwg.org/multipage/input.html#attr-input-accept
43
44
  * @vue-prop {boolean} [multiple=true] - allows or disallows importing multiple files at once
45
+ * @vue-data {#default} - Slot to add additional html after file input and before the buttons
44
46
  */
45
47
  export default {
46
48
  name: 'VcsImportComponent',
@@ -85,7 +85,6 @@
85
85
  import {
86
86
  computed,
87
87
  getCurrentInstance,
88
- inject,
89
88
  isReactive,
90
89
  reactive,
91
90
  ref,
@@ -169,7 +168,8 @@
169
168
  * @vue-prop {boolean} [selectable=false]
170
169
  * @vue-prop {boolean} [singleSelect=false]
171
170
  * @vue-prop {Array<import("./VcsListItemComponent.vue").VcsListItem>} [value=[]] - the initial items to be selected.
172
- * @vue-prop {boolean} [searchable=false] - if this list can have its items searched. you can provide your own predicate function by providing "filterPredicate" which is of type function(import("./VcsListItemComponent.vue").VcsListItem, string):boolean
171
+ * @vue-prop {boolean} [searchable=false] - if this list can have its items searched.
172
+ * @vue-prop {function(import("./VcsListItemComponent.vue").VcsListItem, string):boolean} [customFilter] - a function to customize filtering when searching.
173
173
  * @vue-prop {string} [searchbarPlaceholder] - placeholder to render inside the search field
174
174
  * @vue-prop {boolean} [showTitle=true] - show the title component
175
175
  * @vue-prop {number} [actionButtonListOverflowCount] - overflow count to use for action lists in the title and items
@@ -221,6 +221,10 @@
221
221
  type: Boolean,
222
222
  default: false,
223
223
  },
224
+ customFilter: {
225
+ type: Function,
226
+ default: undefined,
227
+ },
224
228
  searchbarPlaceholder: {
225
229
  type: String,
226
230
  default: undefined,
@@ -313,15 +317,15 @@
313
317
 
314
318
  const vm = getCurrentInstance().proxy;
315
319
  /** @type {function(import("./VcsListItemComponent.vue").VcsListItem, string):boolean} */
316
- const filterPredicate = inject(
317
- 'filterPredicate',
318
- (item, queryString = '') => {
319
- const translatedTitle = vm.$st(item.title);
320
- return translatedTitle
321
- .toLocaleLowerCase()
322
- .includes(queryString.toLocaleLowerCase());
323
- },
324
- );
320
+ const filterPredicate = (item, queryString = '') => {
321
+ if (props.customFilter) {
322
+ return props.customFilter(item, queryString);
323
+ }
324
+ const translatedTitle = vm.$st(item.title);
325
+ return translatedTitle
326
+ .toLocaleLowerCase()
327
+ .includes(queryString.toLocaleLowerCase());
328
+ };
325
329
 
326
330
  /**
327
331
  * @type {import("./VcsListItemComponent.vue").VcsListItem|null}
@@ -30,6 +30,10 @@ declare const _default: import("vue").DefineComponent<{
30
30
  type: BooleanConstructor;
31
31
  default: boolean;
32
32
  };
33
+ customFilter: {
34
+ type: FunctionConstructor;
35
+ default: undefined;
36
+ };
33
37
  searchbarPlaceholder: {
34
38
  type: StringConstructor;
35
39
  default: undefined;
@@ -119,6 +123,10 @@ declare const _default: import("vue").DefineComponent<{
119
123
  type: BooleanConstructor;
120
124
  default: boolean;
121
125
  };
126
+ customFilter: {
127
+ type: FunctionConstructor;
128
+ default: undefined;
129
+ };
122
130
  searchbarPlaceholder: {
123
131
  type: StringConstructor;
124
132
  default: undefined;
@@ -160,6 +168,7 @@ declare const _default: import("vue").DefineComponent<{
160
168
  tooltip: string;
161
169
  selectable: boolean;
162
170
  actions: unknown[];
171
+ customFilter: Function;
163
172
  searchbarPlaceholder: string;
164
173
  actionButtonListOverflowCount: number;
165
174
  singleSelect: boolean;
@@ -10,7 +10,7 @@
10
10
  class="chevron-btn"
11
11
  variant="text"
12
12
  :icon="isOpen ? 'mdi-chevron-down' : 'mdi-chevron-right'"
13
- @click="isOpen = !isOpen"
13
+ @click="bubbleItemToggled(item.name)"
14
14
  />
15
15
  <slot name="prepend" v-bind="{ item }">
16
16
  <span class="prepend">
@@ -49,11 +49,12 @@
49
49
  :key="child.name"
50
50
  :item="child"
51
51
  :search="search"
52
+ :custom-filter="customFilter"
52
53
  :level="level + 1"
53
54
  :open-on-click="openOnClick"
54
55
  :item-children="itemChildren"
55
56
  :opened="opened"
56
- @item-toggled="bubbleItemToggled(child, e)"
57
+ @item-toggled="bubbleItemToggled"
57
58
  @click="bubbleItemClicked"
58
59
  >
59
60
  <template v-for="slot of forwardSlots" #[slot]="scope">
@@ -98,6 +99,7 @@
98
99
  * @vue-prop {string} [itemChildren='children'] - The property key of the children.
99
100
  * @vue-prop {boolean} [openOnClick=false] - Whether to open items on title click..
100
101
  * @vue-prop {string} [search] - The search string to filter the tree.
102
+ * @vue-prop {function(VcsTreeNodeItem, string|undefined):boolean}} [customFilter] - a function to customize filtering when searching.
101
103
  * @vue-data {slot} [#prepend] - A slot prepended to the item, binding the item. Default fallback renders an image.
102
104
  * @vue-data {slot} [#title] - A slot to render the item title, binding the item. Default fallback renders a translatable title using the VcsTreeviewTitle component.
103
105
  * @vue-data {slot} [#append] - A slot appended to the item, binding the item. Default fallback renders the VcsActionButtonList if the item has an array of Actions.
@@ -139,6 +141,14 @@
139
141
  type: String,
140
142
  default: undefined,
141
143
  },
144
+ /**
145
+ * @param {VcsTreeNodeItem} item The item to check the match for.
146
+ * @param {string} search The search value.
147
+ */
148
+ customFilter: {
149
+ type: Function,
150
+ default: undefined,
151
+ },
142
152
  },
143
153
  emits: ['itemToggled', 'click'],
144
154
  setup(props, { emit, slots }) {
@@ -146,19 +156,16 @@
146
156
  const iconSize = useIconSize();
147
157
  const forwardSlots = getForwardSlots(slots);
148
158
 
149
- const isOpen = computed({
150
- get: () => props.opened?.includes(props.item.name),
151
- set: (value) => {
152
- emit('itemToggled', props.item.name, value);
153
- },
154
- });
155
-
159
+ const isOpen = computed(() => props.opened.includes(props.item.name));
156
160
  const children = computed(() => props.item[props.itemChildren] ?? []);
157
161
 
158
162
  const matchFilter = computed(() => {
159
163
  if (!props.search) {
160
164
  return true;
161
165
  }
166
+ if (props.customFilter) {
167
+ return props.customFilter(props.item, props.search);
168
+ }
162
169
  const translatedTitle = (item) =>
163
170
  item.title ? vm.$t(item.title) : item.name;
164
171
 
@@ -179,8 +186,8 @@
179
186
  children,
180
187
 
181
188
  // Bubble up events for the nested tree-items
182
- bubbleItemToggled: (itemName, openState) => {
183
- emit('itemToggled', itemName, openState);
189
+ bubbleItemToggled: (itemName) => {
190
+ emit('itemToggled', itemName);
184
191
  },
185
192
  bubbleItemClicked: (item, event) => {
186
193
  emit('click', item, event);
@@ -11,6 +11,7 @@
11
11
  :item="item"
12
12
  :search="localSearchValue"
13
13
  v-model:opened="localOpenedItems"
14
+ :custom-filter="customFilter"
14
15
  :open-on-click="openOnClick"
15
16
  :item-children="itemChildren"
16
17
  @item-toggled="itemToggled"
@@ -46,6 +47,7 @@
46
47
  * @vue-prop {boolean} [openOnClick=false] - Whether to open items on title click.
47
48
  * @vue-prop {string} [search=''] - The value used to filter the items.
48
49
  * @vue-prop {boolean} [showSearchbar=false] - Whether there is a searchbar for this treeview.
50
+ * @vue-prop {function(import("./VcsTreeNode.vue").VcsTreeNodeItem, string|undefined):boolean}} [customFilter] - a function to customize filtering when searching.
49
51
  * @vue-prop {string} [searchbarPlaceholder] - Placeholder text for the searchbar, will be translated.
50
52
  */
51
53
  export default {
@@ -87,6 +89,14 @@
87
89
  type: String,
88
90
  default: undefined,
89
91
  },
92
+ /**
93
+ * @param {import("./VcsTreeNode.vue").VcsTreeNodeItem} item The item to filter.
94
+ * @param {string} search The query value.
95
+ */
96
+ customFilter: {
97
+ type: Function,
98
+ default: undefined,
99
+ },
90
100
  },
91
101
  emits: ['update:search', 'update:opened'],
92
102
  setup(props, { emit, slots }) {
@@ -107,14 +117,12 @@
107
117
  );
108
118
  }
109
119
 
110
- function itemToggled(name, state) {
111
- if (state) {
112
- localOpenedItems.value.push(name);
120
+ function itemToggled(itemName) {
121
+ const idx = localOpenedItems.value.indexOf(itemName);
122
+ if (idx >= 0) {
123
+ localOpenedItems.value.splice(idx, 1);
113
124
  } else {
114
- const idx = localOpenedItems.value.indexOf(name);
115
- if (idx >= 0) {
116
- localOpenedItems.value.splice(idx, 1);
117
- }
125
+ localOpenedItems.value.push(itemName);
118
126
  }
119
127
  }
120
128
 
@@ -129,7 +137,7 @@
129
137
  item.clicked(event);
130
138
  }
131
139
  } else if ((props.openOnClick ?? false) !== false) {
132
- itemToggled(item.name, !localOpenedItems.value.includes(item.name));
140
+ itemToggled(item.name);
133
141
  }
134
142
  },
135
143
  };
@@ -31,11 +31,19 @@ declare const _default: import("vue").DefineComponent<{
31
31
  type: StringConstructor;
32
32
  default: undefined;
33
33
  };
34
+ /**
35
+ * @param {import("./VcsTreeNode.vue").VcsTreeNodeItem} item The item to filter.
36
+ * @param {string} search The query value.
37
+ */
38
+ customFilter: {
39
+ type: FunctionConstructor;
40
+ default: undefined;
41
+ };
34
42
  }, {
35
43
  localSearchValue: import("vue").Ref<any>;
36
44
  localOpenedItems: import("vue").Ref<any>;
37
45
  forwardSlots: string[];
38
- itemToggled: (name: any, state: any) => void;
46
+ itemToggled: (itemName: any) => void;
39
47
  itemClicked(item: any, event: any): void;
40
48
  }, any, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, ("update:opened" | "update:search")[], "update:opened" | "update:search", import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
41
49
  items: {
@@ -70,6 +78,14 @@ declare const _default: import("vue").DefineComponent<{
70
78
  type: StringConstructor;
71
79
  default: undefined;
72
80
  };
81
+ /**
82
+ * @param {import("./VcsTreeNode.vue").VcsTreeNodeItem} item The item to filter.
83
+ * @param {string} search The query value.
84
+ */
85
+ customFilter: {
86
+ type: FunctionConstructor;
87
+ default: undefined;
88
+ };
73
89
  }>> & {
74
90
  "onUpdate:opened"?: ((...args: any[]) => any) | undefined;
75
91
  "onUpdate:search"?: ((...args: any[]) => any) | undefined;
@@ -79,6 +95,7 @@ declare const _default: import("vue").DefineComponent<{
79
95
  items: unknown[];
80
96
  opened: unknown[];
81
97
  itemChildren: string;
98
+ customFilter: Function;
82
99
  openAll: boolean;
83
100
  showSearchbar: boolean;
84
101
  searchbarPlaceholder: string;
@@ -168,6 +168,7 @@
168
168
  * @vue-prop {boolean} [showSearchbar=true] - whether to show searchbar
169
169
  * @vue-prop {string} [searchbarPlaceholder] - placeholder for searchbar
170
170
  * @vue-prop {string} [itemSelectable='isSelectable'] - The property on each item that is used to determine if it is selectable or not. Non-selectable items are automatically disabled.
171
+ * @vue-prop {function(any, string|undefined, TableItem):boolean} [customFilter] - a function to customize filtering when searching. The first parameter represents the item values, with the function called for each of them. The second is the search term. The third is the complete item.
171
172
  * @vue-event {UpdateItemsEvent} update:items - Emits when one of the options properties is updated or on search input. Can be used to update items via API call to a server.
172
173
  * @vue-computed {Array<TableItem>} filteredItems - array of items with search filter applied on. If search string is empty, same as items array.
173
174
  * @vue-computed {Array<import("vuetify").DataTableHeader>} translatedHeaders - array of translated header items.
@@ -232,6 +233,10 @@
232
233
  type: String,
233
234
  default: 'isSelectable',
234
235
  },
236
+ customFilter: {
237
+ type: Function,
238
+ default: undefined,
239
+ },
235
240
  },
236
241
  setup(props, { attrs, emit, slots }) {
237
242
  const vm = getCurrentInstance().proxy;
@@ -272,6 +277,9 @@
272
277
  * @returns {boolean}
273
278
  */
274
279
  const handleFilter = (value, filter, item) => {
280
+ if (props.customFilter) {
281
+ return props.customFilter(value, filter, item.raw);
282
+ }
275
283
  return handleFilterInternal(value, filter, item.raw);
276
284
  };
277
285
 
@@ -300,9 +308,12 @@
300
308
  * @type {ComputedRef<Array<Object>>}
301
309
  */
302
310
  const filteredItems = computed(() =>
303
- props.items.filter((item) =>
304
- handleFilterInternal(item.value, search.value, item),
305
- ),
311
+ props.items.filter((item) => {
312
+ if (props.customFilter) {
313
+ return props.customFilter(item.value, search.value, item);
314
+ }
315
+ return handleFilterInternal(item.value, search.value, item);
316
+ }),
306
317
  );
307
318
  const numberOfItems = computed(() => {
308
319
  if (props.serverItemsLength > -1) {
@@ -40,6 +40,10 @@ declare const _default: import("vue").DefineComponent<{
40
40
  type: StringConstructor;
41
41
  default: string;
42
42
  };
43
+ customFilter: {
44
+ type: FunctionConstructor;
45
+ default: undefined;
46
+ };
43
47
  }, {
44
48
  hovering: import("vue").Ref<null>;
45
49
  search: Ref<UnwrapRef<string>>;
@@ -102,8 +106,13 @@ declare const _default: import("vue").DefineComponent<{
102
106
  type: StringConstructor;
103
107
  default: string;
104
108
  };
109
+ customFilter: {
110
+ type: FunctionConstructor;
111
+ default: undefined;
112
+ };
105
113
  }>>, {
106
114
  items: unknown[];
115
+ customFilter: Function;
107
116
  showSearchbar: boolean;
108
117
  searchbarPlaceholder: string;
109
118
  headers: unknown[];
@@ -19,7 +19,7 @@
19
19
  <div v-if="item.type === LegendType.Image">
20
20
  <img
21
21
  :src="$st(item.src)"
22
- :alt="item.src"
22
+ :alt="$st(item.src)"
23
23
  class="legend-image"
24
24
  :title="item.tooltip"
25
25
  />