@xwiki/cristal-dsvuetify 0.11.0 → 0.13.0

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/CHANGELOG.md +29 -0
  2. package/dist/components/vuetifyDesignSystemLoader.d.ts +1 -1
  3. package/dist/{index-BMliq0dk.js → index-UP1o6s9t.js} +4151 -4114
  4. package/dist/index-UP1o6s9t.js.map +1 -0
  5. package/dist/index.es.js +5 -4
  6. package/dist/index.umd.js +9 -8
  7. package/dist/index.umd.js.map +1 -1
  8. package/dist/vue/x-alert.vue.d.ts +15 -1
  9. package/dist/vue/x-dialog.vue.d.ts +1 -0
  10. package/dist/vue/x-navigation-tree.vue.d.ts +1 -3
  11. package/dist/x-alert-Bmt4mXHQ.js +45 -0
  12. package/dist/x-alert-Bmt4mXHQ.js.map +1 -0
  13. package/dist/x-avatar-But_Z7ic.js.map +1 -1
  14. package/dist/x-breadcrumb-C2iUd4Sf.js.map +1 -1
  15. package/dist/x-btn-DNlhiqjD.js.map +1 -1
  16. package/dist/x-card-CRM9KUby.js.map +1 -1
  17. package/dist/x-dialog-C-dMkFJk.js +49 -0
  18. package/dist/x-dialog-C-dMkFJk.js.map +1 -0
  19. package/dist/{x-file-input-8euR7G64.js → x-file-input-BsaodA0p.js} +10 -9
  20. package/dist/x-file-input-BsaodA0p.js.map +1 -0
  21. package/dist/{x-form-UiBYkCKP.js → x-form-iQFXj1PW.js} +2 -2
  22. package/dist/{x-form-UiBYkCKP.js.map → x-form-iQFXj1PW.js.map} +1 -1
  23. package/dist/x-img-BYgs_O1F.js.map +1 -1
  24. package/dist/x-navigation-tree-DN2Qz7Sm.js +501 -0
  25. package/dist/x-navigation-tree-DN2Qz7Sm.js.map +1 -0
  26. package/dist/x-tab-group-ngNByee3.js.map +1 -1
  27. package/dist/x-text-field-CTsLZhLE.js +31 -0
  28. package/dist/x-text-field-CTsLZhLE.js.map +1 -0
  29. package/langs/translation-de.json +4 -0
  30. package/package.json +18 -10
  31. package/src/components/componentsInit.ts +1 -1
  32. package/src/components/vuetifyDesignSystemLoader.ts +12 -9
  33. package/src/vue/__tests__/utils/vuetify.ts +1 -0
  34. package/src/vue/__tests__/x-btn.test.ts +4 -3
  35. package/src/vue/css/style.css +12 -4
  36. package/src/vue/form/x-file-input.vue +3 -4
  37. package/src/vue/form/x-text-field.vue +9 -4
  38. package/src/vue/x-alert.vue +4 -1
  39. package/src/vue/x-btn.vue +1 -1
  40. package/src/vue/x-dialog.vue +14 -1
  41. package/src/vue/x-navigation-tree.vue +136 -46
  42. package/tsconfig.json +14 -8
  43. package/vitest.config.ts +1 -1
  44. package/dist/index-BMliq0dk.js.map +0 -1
  45. package/dist/x-alert-D8oy1BPL.js +0 -40
  46. package/dist/x-alert-D8oy1BPL.js.map +0 -1
  47. package/dist/x-dialog-Ce8KWptm.js +0 -38
  48. package/dist/x-dialog-Ce8KWptm.js.map +0 -1
  49. package/dist/x-file-input-8euR7G64.js.map +0 -1
  50. package/dist/x-navigation-tree-DkVWsvlI.js +0 -449
  51. package/dist/x-navigation-tree-DkVWsvlI.js.map +0 -1
  52. package/dist/x-text-field-uL1ePP_x.js +0 -29
  53. package/dist/x-text-field-uL1ePP_x.js.map +0 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xwiki/cristal-dsvuetify",
3
- "version": "0.11.0",
3
+ "version": "0.13.0",
4
4
  "license": "LGPL 2.1",
5
5
  "author": "XWiki Org Community <contact@xwiki.org>",
6
6
  "homepage": "https://cristal.xwiki.org/",
@@ -22,18 +22,26 @@
22
22
  },
23
23
  "main": "./dist/index.es.js",
24
24
  "dependencies": {
25
- "inversify": "6.0.2",
26
- "vue": "3.5.12",
27
- "vue-i18n": "10.0.4",
28
- "vuetify": "3.7.2",
29
- "@xwiki/cristal-api": "0.11.0",
30
- "@xwiki/cristal-dsapi": "0.11.0",
31
- "@xwiki/cristal-navigation-tree-api": "0.11.0"
25
+ "inversify": "6.2.0",
26
+ "vue": "3.5.13",
27
+ "vue-i18n": "10.0.5",
28
+ "vuetify": "3.7.5",
29
+ "@xwiki/cristal-document-api": "0.13.0",
30
+ "@xwiki/cristal-navigation-tree-api": "0.13.0",
31
+ "@xwiki/cristal-api": "0.13.0",
32
+ "@xwiki/cristal-dsapi": "0.13.0",
33
+ "@xwiki/cristal-model-api": "0.13.0"
34
+ },
35
+ "peerDependencies": {
36
+ "reflect-metadata": "0.2.2"
32
37
  },
33
38
  "devDependencies": {
34
39
  "@vue/test-utils": "2.4.6",
35
- "vue-tsc": "2.1.6",
36
- "@xwiki/cristal-dev-config": "0.11.0"
40
+ "reflect-metadata": "0.2.2",
41
+ "typescript": "5.6.3",
42
+ "vite": "6.0.3",
43
+ "vue-tsc": "2.1.10",
44
+ "@xwiki/cristal-dev-config": "0.13.0"
37
45
  },
38
46
  "scripts": {
39
47
  "build": "pnpm compile",
@@ -18,9 +18,9 @@
18
18
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19
19
  */
20
20
 
21
+ import { VuetifyDesignSystemLoader } from "./vuetifyDesignSystemLoader";
21
22
  import type { DesignSystemLoader } from "@xwiki/cristal-api";
22
23
  import type { Container } from "inversify";
23
- import { VuetifyDesignSystemLoader } from "./vuetifyDesignSystemLoader";
24
24
 
25
25
  export default class ComponentInit {
26
26
  constructor(container: Container) {
@@ -18,20 +18,23 @@
18
18
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19
19
  */
20
20
 
21
- import type { App } from "vue";
21
+ import { registerAsyncComponent } from "@xwiki/cristal-api";
22
+ import { injectable } from "inversify";
23
+ import { createVuetify } from "vuetify";
24
+ // eslint-disable-next-line import/namespace
22
25
  import * as components from "vuetify/components";
23
26
  import { VCol, VContainer, VRow, VTextField } from "vuetify/components";
24
- import type { DesignSystemLoader } from "@xwiki/cristal-api";
25
27
 
26
- import { createVuetify } from "vuetify";
27
- import colors from "vuetify/util/colors";
28
- import { mdi } from "vuetify/iconsets/mdi";
29
28
  import * as directives from "vuetify/directives";
30
- import { injectable } from "inversify";
31
- import { registerAsyncComponent } from "@xwiki/cristal-api";
29
+ import { mdi } from "vuetify/iconsets/mdi";
30
+ import { blue, blueGrey } from "vuetify/util/colors";
31
+ import type { DesignSystemLoader } from "@xwiki/cristal-api";
32
+ import type { App } from "vue";
32
33
 
33
34
  @injectable()
34
35
  export class VuetifyDesignSystemLoader implements DesignSystemLoader {
36
+ // TODO: reduce the number of statements in the following method and reactivate the disabled eslint rule.
37
+ // eslint-disable-next-line max-statements
35
38
  loadDesignSystem(app: App): void {
36
39
  /*
37
40
  // Manuel importing to reduce build size
@@ -63,8 +66,8 @@ export class VuetifyDesignSystemLoader implements DesignSystemLoader {
63
66
  dark: false,
64
67
  colors: {
65
68
  background: "#FFFFFF",
66
- primary: colors.blue.darken4,
67
- secondary: colors.blueGrey.darken4,
69
+ primary: blue.darken4,
70
+ secondary: blueGrey.darken4,
68
71
  },
69
72
  },
70
73
  },
@@ -19,6 +19,7 @@
19
19
  */
20
20
 
21
21
  import { createVuetify } from "vuetify";
22
+ // eslint-disable-next-line import/namespace
22
23
  import * as components from "vuetify/components";
23
24
  import * as directives from "vuetify/directives";
24
25
 
@@ -17,10 +17,11 @@
17
17
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18
18
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19
19
  */
20
- import { describe, expect, it } from "vitest";
21
- import { mount, VueWrapper } from "@vue/test-utils";
22
- import XBtn from "../x-btn.vue";
20
+
23
21
  import { addVuetifyOptions } from "./utils/vuetify";
22
+ import XBtn from "../x-btn.vue";
23
+ import { VueWrapper, mount } from "@vue/test-utils";
24
+ import { describe, expect, it } from "vitest";
24
25
 
25
26
  /**
26
27
  * Mount a XBtn component with the default configuration.
@@ -17,6 +17,7 @@
17
17
  * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18
18
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19
19
  */
20
+
20
21
  .load-spinner {
21
22
  background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200"><circle fill="%23B9B9B9" stroke="%23B9B9B9" stroke-width="6" r="15" cx="40" cy="100"><animate attributeName="opacity" calcMode="spline" dur="2" values="1;0;1;" keySplines=".5 0 .5 1;.5 0 .5 1" repeatCount="indefinite" begin="-.4"></animate></circle><circle fill="%23B9B9B9" stroke="%23B9B9B9" stroke-width="6" r="15" cx="100" cy="100"><animate attributeName="opacity" calcMode="spline" dur="2" values="1;0;1;" keySplines=".5 0 .5 1;.5 0 .5 1" repeatCount="indefinite" begin="-.2"></animate></circle><circle fill="%23B9B9B9" stroke="%23B9B9B9" stroke-width="6" r="15" cx="160" cy="100"><animate attributeName="opacity" calcMode="spline" dur="2" values="1;0;1;" keySplines=".5 0 .5 1;.5 0 .5 1" repeatCount="indefinite" begin="0"></animate></circle></svg>');
22
23
  background-size: cover;
@@ -31,7 +32,8 @@
31
32
  --cr-sizes-collapsed-main-sidebar-width: 32px; /*The width of the bar that gets shown containing the menu button to reopen the standard main main sidebar*/
32
33
  --cr-base-font-size: 16px;
33
34
  --cr-base-text-color: var(--cr-color-gray-950);
34
-
35
+ --cr-base-link-color: var(--cr-color-sky-700);
36
+ --cr-base-visited-link-color: var(--cr-color-blue-700);
35
37
 
36
38
  /*
37
39
  * Typography
@@ -81,9 +83,9 @@
81
83
  --cr-focus-ring: var(--cr-focus-ring-style) var(--cr-focus-ring-width) var(--cr-focus-ring-color);
82
84
  --cr-focus-ring-offset: 1px;
83
85
 
84
- /*
85
- * Color Primitives
86
- */
86
+ /*
87
+ * Color Primitives
88
+ */
87
89
 
88
90
  /* Gray */
89
91
  --cr-color-gray-50: hsl(0 0% 97.5%);
@@ -534,6 +536,12 @@
534
536
  --cr-panel-border-color: var(--cr-color-neutral-200);
535
537
  --cr-panel-border-width: 1px;
536
538
 
539
+ /*
540
+ * Header
541
+ */
542
+
543
+ --cr-panel-background-color: var(--cr-color-neutral-0);
544
+
537
545
  /*
538
546
  * Tooltips
539
547
  */
@@ -1,10 +1,9 @@
1
1
  <script setup lang="ts">
2
- import type { TextFieldModel, TextFieldProps } from "@xwiki/cristal-dsapi";
3
- import { computed } from "vue";
4
- import { VFileInput } from "vuetify/components/VFileInput";
5
2
  import messages from "../../translations";
3
+ import { computed, defineModel } from "vue";
6
4
  import { useI18n } from "vue-i18n";
7
- import { defineModel } from "vue";
5
+ import { VFileInput } from "vuetify/components/VFileInput";
6
+ import type { TextFieldModel, TextFieldProps } from "@xwiki/cristal-dsapi";
8
7
 
9
8
  const { t } = useI18n({
10
9
  messages,
@@ -1,9 +1,9 @@
1
1
  <script setup lang="ts">
2
- import { type TextFieldProps } from "@xwiki/cristal-dsapi";
3
- import { computed } from "vue";
4
- import { VTextField } from "vuetify/components/VTextField";
5
2
  import messages from "../../translations";
3
+ import { computed } from "vue";
6
4
  import { useI18n } from "vue-i18n";
5
+ import { VTextField } from "vuetify/components/VTextField";
6
+ import type { TextFieldProps } from "@xwiki/cristal-dsapi";
7
7
 
8
8
  const { t } = useI18n({
9
9
  messages,
@@ -26,7 +26,12 @@ const rules = computed(() => {
26
26
  </script>
27
27
 
28
28
  <template>
29
- <v-text-field :label="label" :name="name" :rules="rules"></v-text-field>
29
+ <v-text-field
30
+ :label="label"
31
+ :name="name"
32
+ :autofocus="autofocus"
33
+ :rules="rules"
34
+ ></v-text-field>
30
35
  </template>
31
36
 
32
37
  <style scoped></style>
@@ -23,7 +23,7 @@ import type { AlertProps } from "@xwiki/cristal-dsapi";
23
23
  defineProps<AlertProps>();
24
24
  </script>
25
25
  <template>
26
- <v-alert closable :title="title" :type="type" :text="description">
26
+ <v-alert :closable="closable" :title="title" :type="type" :text="description">
27
27
  <x-btn
28
28
  v-for="action of actions"
29
29
  :key="action.name"
@@ -32,5 +32,8 @@ defineProps<AlertProps>();
32
32
  @click="action.callback"
33
33
  >{{ action.name }}</x-btn
34
34
  >
35
+ <br v-if="details" />
36
+ <small v-if="details">{{ details }}</small>
37
+ <slot />
35
38
  </v-alert>
36
39
  </template>
package/src/vue/x-btn.vue CHANGED
@@ -19,7 +19,7 @@ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
19
19
  -->
20
20
  <script lang="ts" setup>
21
21
  import { computed } from "vue";
22
- import { type BtnProps } from "@xwiki/cristal-dsapi";
22
+ import type { BtnProps } from "@xwiki/cristal-dsapi";
23
23
 
24
24
  const { variant } = defineProps<BtnProps>();
25
25
 
@@ -18,16 +18,20 @@ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18
18
  02110-1301 USA, or see the FSF site: http://www.fsf.org.
19
19
  -->
20
20
  <script lang="ts" setup>
21
+ import { useSlots } from "vue";
22
+
21
23
  defineProps<{
22
24
  title: string;
23
25
  width: string | number | undefined;
24
26
  }>();
25
27
 
28
+ const slots = useSlots();
29
+
26
30
  // const innerIsActive = ref(props.isActive);
27
31
  </script>
28
32
 
29
33
  <template>
30
- <v-dialog :width="width">
34
+ <v-dialog :width="width" scrollable>
31
35
  <template #activator="{ props }">
32
36
  <span v-bind="props">
33
37
  <slot name="activator" />
@@ -38,7 +42,16 @@ defineProps<{
38
42
  <v-card-text>
39
43
  <slot name="default" />
40
44
  </v-card-text>
45
+ <v-card-actions v-if="slots.footer">
46
+ <slot name="footer" />
47
+ </v-card-actions>
41
48
  </v-card>
42
49
  </template>
43
50
  </v-dialog>
44
51
  </template>
52
+
53
+ <style scoped>
54
+ :deep(.v-card-actions) {
55
+ padding: var(--cr-spacing-large);
56
+ }
57
+ </style>
@@ -29,38 +29,51 @@ Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
29
29
  * item was disabled. Default hover effects, such as darkening or changing
30
30
  * the cursor on items, were also disabled.
31
31
  */
32
- import { Ref, onBeforeMount, ref, watch } from "vue";
32
+ import { inject, onBeforeMount, ref, watch } from "vue";
33
33
  import { VTreeview } from "vuetify/labs/VTreeview";
34
- import { type PageData } from "@xwiki/cristal-api";
34
+ import type { CristalApp, PageData } from "@xwiki/cristal-api";
35
+ import type { DocumentService } from "@xwiki/cristal-document-api";
36
+ import type { SpaceReference } from "@xwiki/cristal-model-api";
35
37
  import type {
36
- NavigationTreeSource,
37
38
  NavigationTreeNode,
39
+ NavigationTreeSource,
40
+ NavigationTreeSourceProvider,
38
41
  } from "@xwiki/cristal-navigation-tree-api";
42
+ import type { Ref } from "vue";
39
43
 
40
44
  type TreeItem = {
41
45
  id: string;
42
46
  title: string;
43
47
  href: string;
44
48
  children?: Array<TreeItem>;
45
- _location: string;
49
+ _location: SpaceReference;
46
50
  };
47
51
 
48
52
  type OnClickAction = (node: NavigationTreeNode) => void;
49
53
 
54
+ const cristal: CristalApp = inject<CristalApp>("cristal")!;
55
+ const documentService: DocumentService = cristal
56
+ .getContainer()
57
+ .get<DocumentService>("DocumentService");
58
+ const treeSource: NavigationTreeSource = cristal
59
+ .getContainer()
60
+ .get<NavigationTreeSourceProvider>("NavigationTreeSourceProvider")
61
+ .get();
62
+
50
63
  const rootNodes: Ref<Array<TreeItem>> = ref([]);
51
64
  const tree: Ref<VTreeview | undefined> = ref(undefined);
52
65
 
53
66
  const activatedNodes: Ref<Array<string>> = ref(new Array<string>());
54
67
  const expandedNodes: Ref<Array<string>> = ref(new Array<string>());
68
+ var isExpanding: boolean = false;
55
69
 
56
70
  const props = defineProps<{
57
- treeSource: NavigationTreeSource;
58
71
  clickAction?: OnClickAction;
59
72
  currentPage?: PageData;
60
73
  }>();
61
74
 
62
75
  onBeforeMount(async () => {
63
- for (const node of await props.treeSource.getChildNodes("")) {
76
+ for (const node of await treeSource.getChildNodes("")) {
64
77
  rootNodes.value.push({
65
78
  id: node.id,
66
79
  title: node.label,
@@ -69,62 +82,62 @@ onBeforeMount(async () => {
69
82
  _location: node.location,
70
83
  });
71
84
  }
72
- if (props.currentPage !== undefined) {
73
- await expandTree();
74
- }
85
+ await expandTree();
86
+
87
+ documentService.registerDocumentChangeListener("delete", onDocumentDelete);
88
+ documentService.registerDocumentChangeListener("update", onDocumentUpdate);
75
89
  });
76
90
 
77
- watch(
78
- () => props.currentPage,
79
- async () => {
80
- if (props.currentPage) {
81
- await expandTree();
82
- }
83
- },
84
- );
91
+ watch(() => props.currentPage, expandTree);
85
92
 
93
+ // TODO: reduce the number of statements in the following method and reactivate the disabled eslint rule.
94
+ // eslint-disable-next-line max-statements
86
95
  async function expandTree() {
87
- const newExpandedNodes = props.treeSource.getParentNodesId(props.currentPage);
88
- let i;
89
- let currentNodes = rootNodes.value;
90
- for (i = 0; i < newExpandedNodes.length - 1; i++) {
91
- if (currentNodes) {
92
- for (const node of currentNodes) {
93
- if (node.id == newExpandedNodes[i]) {
94
- if (node.children?.length == 0) {
95
- await lazyLoadChildren(node);
96
+ if (props.currentPage && !isExpanding) {
97
+ isExpanding = true;
98
+ const newExpandedNodes = treeSource.getParentNodesId(props.currentPage);
99
+ let i;
100
+ let currentNodes = rootNodes.value;
101
+ for (i = 0; i < newExpandedNodes.length - 1; i++) {
102
+ if (currentNodes) {
103
+ for (const node of currentNodes) {
104
+ if (node.id == newExpandedNodes[i]) {
105
+ if (node.children?.length == 0) {
106
+ await lazyLoadChildren(node);
107
+ }
108
+ if (!expandedNodes.value.includes(node.id)) {
109
+ expandedNodes.value.push(node.id);
110
+ }
111
+ currentNodes = node.children!;
96
112
  }
97
- if (!expandedNodes.value.includes(node.id)) {
98
- expandedNodes.value.push(node.id);
99
- }
100
- currentNodes = node.children!;
101
113
  }
102
114
  }
103
115
  }
104
- }
105
- if (currentNodes) {
106
- for (const node of currentNodes) {
107
- if (node.id == newExpandedNodes[i]) {
108
- activatedNodes.value = [node.id];
109
- // If we have a custom click action, we want to use it on dynamic
110
- // selection.
111
- if (props.clickAction) {
112
- props.clickAction({
113
- id: node.id,
114
- label: node.title,
115
- location: node._location,
116
- url: node.href,
117
- has_children: node.children !== undefined,
118
- });
116
+ if (currentNodes) {
117
+ for (const node of currentNodes) {
118
+ if (node.id == newExpandedNodes[i]) {
119
+ activatedNodes.value = [node.id];
120
+ // If we have a custom click action, we want to use it on dynamic
121
+ // selection.
122
+ if (props.clickAction) {
123
+ props.clickAction({
124
+ id: node.id,
125
+ label: node.title,
126
+ location: node._location,
127
+ url: node.href,
128
+ has_children: node.children !== undefined,
129
+ });
130
+ }
119
131
  }
120
132
  }
121
133
  }
134
+ isExpanding = false;
122
135
  }
123
136
  }
124
137
 
125
138
  async function lazyLoadChildren(item: unknown) {
126
139
  const treeItem = item as TreeItem;
127
- const childNodes = await props.treeSource.getChildNodes(treeItem.id);
140
+ const childNodes = await treeSource.getChildNodes(treeItem.id);
128
141
  for (const child of childNodes) {
129
142
  treeItem.children?.push({
130
143
  id: child.id,
@@ -148,6 +161,83 @@ function clearSelection() {
148
161
  activatedNodes.value.pop();
149
162
  }
150
163
  }
164
+
165
+ // TODO: reduce the number of statements in the following method and reactivate the disabled eslint rule.
166
+ // eslint-disable-next-line max-statements
167
+ async function onDocumentDelete(page: PageData) {
168
+ const parents = treeSource.getParentNodesId(page);
169
+ let currentItems: TreeItem[] | undefined = rootNodes.value;
170
+ while (currentItems) {
171
+ for (const i of currentItems.keys()) {
172
+ if (currentItems[i].id == parents[0]) {
173
+ if (parents.length == 1) {
174
+ currentItems.splice(i, 1);
175
+ return;
176
+ } else {
177
+ currentItems = currentItems[i].children;
178
+ parents.shift();
179
+ break;
180
+ }
181
+ }
182
+ }
183
+ }
184
+ }
185
+
186
+ // TODO: reduce the number of statements in the following method and reactivate the disabled eslint rule.
187
+ // eslint-disable-next-line max-statements
188
+ async function onDocumentUpdate(page: PageData) {
189
+ const parents = treeSource.getParentNodesId(page);
190
+ let currentParent: string | undefined = undefined;
191
+ let currentItems: TreeItem[] | undefined = rootNodes.value;
192
+ let notFound = false;
193
+
194
+ currentItemsLoop: while (currentItems && !notFound) {
195
+ for (const i of currentItems.keys()) {
196
+ if (currentItems[i].id == parents[0]) {
197
+ if (parents.length == 1) {
198
+ // Page update
199
+ const newItems = await treeSource.getChildNodes(
200
+ currentParent ? currentParent : "",
201
+ );
202
+ for (const newItem of newItems) {
203
+ if (newItem.id == currentItems[i].id) {
204
+ currentItems[i].title = newItem.label;
205
+ return;
206
+ }
207
+ }
208
+ } else {
209
+ currentParent = currentItems[i].id;
210
+ if (!currentItems[i].children) {
211
+ currentItems[i].children = [];
212
+ }
213
+ currentItems = currentItems[i].children;
214
+ parents.shift();
215
+ continue currentItemsLoop;
216
+ }
217
+ }
218
+ }
219
+ notFound = true;
220
+ }
221
+
222
+ // New page
223
+ const newItems = await treeSource.getChildNodes(
224
+ currentParent ? currentParent : "",
225
+ );
226
+ newItemsLoop: for (const newItem of newItems) {
227
+ for (const i of currentItems!.keys()) {
228
+ if (newItem.id == currentItems![i].id) {
229
+ continue newItemsLoop;
230
+ }
231
+ }
232
+ currentItems!.push({
233
+ id: newItem.id,
234
+ title: newItem.label,
235
+ href: newItem.url,
236
+ children: newItem.has_children ? [] : undefined,
237
+ _location: newItem.location,
238
+ });
239
+ }
240
+ }
151
241
  </script>
152
242
 
153
243
  <template>
package/tsconfig.json CHANGED
@@ -1,10 +1,16 @@
1
1
  {
2
- "compilerOptions": {
3
- "rootDir" : "src",
4
- "outDir" : "dist",
5
- "isolatedDeclarations": false
6
- },
7
- "extends": "./../../tsconfig.json",
8
- "include": ["./src/index.ts", "./src/**/*"],
9
- "exclude": ["**/*.spec.ts", "**/*.test.ts"]
2
+ "compilerOptions": {
3
+ "rootDir": "src",
4
+ "outDir": "dist",
5
+ "isolatedDeclarations": false
6
+ },
7
+ "extends": "./../../tsconfig.json",
8
+ "include": [
9
+ "./src/index.ts",
10
+ "./src/**/*"
11
+ ],
12
+ "exclude": [
13
+ "**/*.spec.ts",
14
+ "**/*.test.ts"
15
+ ]
10
16
  }
package/vitest.config.ts CHANGED
@@ -18,9 +18,9 @@
18
18
  * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
19
19
  */
20
20
 
21
+ import localConfig from "./vite.config";
21
22
  import { defineConfig, mergeConfig } from "vitest/config";
22
23
  import defaultConfig from "@xwiki/cristal-dev-config/vitest-vue.config";
23
- import localConfig from "./vite.config";
24
24
 
25
25
  export default mergeConfig(
26
26
  mergeConfig(defaultConfig, localConfig),