@xwiki/cristal-dsvuetify 0.9.0 → 0.11.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.
- package/CHANGELOG.md +26 -0
- package/dist/components/componentsInit.d.ts +0 -1
- package/dist/components/vuetifyDesignSystemLoader.d.ts +0 -1
- package/dist/{index-CkW0K4NP.js → index-BMliq0dk.js} +7749 -7612
- package/dist/index-BMliq0dk.js.map +1 -0
- package/dist/index.d.ts +0 -1
- package/dist/index.es.js +7 -4
- package/dist/index.umd.js +12 -7
- package/dist/index.umd.js.map +1 -1
- package/dist/{translations-CFfpgNrx.js → translations-BNEIsfPR.js} +3 -3
- package/dist/{translations-CFfpgNrx.js.map → translations-BNEIsfPR.js.map} +1 -1
- package/dist/vue/__tests__/utils/vuetify.d.ts +5 -0
- package/dist/vue/form/x-file-input.vue.d.ts +10 -31
- package/dist/vue/form/x-form.vue.d.ts +9 -4
- package/dist/vue/form/x-text-field.vue.d.ts +1 -11
- package/dist/vue/x-alert.vue.d.ts +2 -22
- package/dist/vue/x-avatar.vue.d.ts +3 -3
- package/dist/vue/x-breadcrumb.vue.d.ts +1 -11
- package/dist/vue/x-btn.vue.d.ts +9 -3
- package/dist/vue/x-card.vue.d.ts +3 -3
- package/dist/vue/x-dialog.vue.d.ts +11 -15
- package/dist/vue/x-divider.vue.d.ts +1 -1
- package/dist/vue/x-img.vue.d.ts +3 -3
- package/dist/vue/x-load.vue.d.ts +1 -2
- package/dist/vue/x-menu-item.vue.d.ts +12 -16
- package/dist/vue/x-menu-label.vue.d.ts +16 -0
- package/dist/vue/x-menu.vue.d.ts +9 -17
- package/dist/vue/x-navigation-tree.vue.d.ts +13 -0
- package/dist/vue/x-search.vue.d.ts +1 -1
- package/dist/vue/x-tab-group.vue.d.ts +10 -5
- package/dist/vue/x-tab-panel.vue.d.ts +8 -13
- package/dist/vue/x-tab.vue.d.ts +8 -13
- package/dist/x-alert-D8oy1BPL.js +40 -0
- package/dist/x-alert-D8oy1BPL.js.map +1 -0
- package/dist/x-breadcrumb-C2iUd4Sf.js +22 -0
- package/dist/{x-breadcrumb-DBZVExfF.js.map → x-breadcrumb-C2iUd4Sf.js.map} +1 -1
- package/dist/x-btn-DNlhiqjD.js +48 -0
- package/dist/x-btn-DNlhiqjD.js.map +1 -0
- package/dist/x-divider-Buudf0KI.js +12 -0
- package/dist/x-divider-Buudf0KI.js.map +1 -0
- package/dist/{x-file-input-COSLRt5u.js → x-file-input-8euR7G64.js} +9 -9
- package/dist/{x-file-input-COSLRt5u.js.map → x-file-input-8euR7G64.js.map} +1 -1
- package/dist/{x-form-B5rljfJA.js → x-form-UiBYkCKP.js} +2 -2
- package/dist/{x-form-B5rljfJA.js.map → x-form-UiBYkCKP.js.map} +1 -1
- package/dist/x-menu-DDC7z1Wb.js +31 -0
- package/dist/x-menu-DDC7z1Wb.js.map +1 -0
- package/dist/x-menu-item-ByE5R9Bf.js +22 -0
- package/dist/x-menu-item-ByE5R9Bf.js.map +1 -0
- package/dist/x-menu-label-DniImc0U.js +17 -0
- package/dist/x-menu-label-DniImc0U.js.map +1 -0
- package/dist/x-navigation-tree-DkVWsvlI.js +449 -0
- package/dist/x-navigation-tree-DkVWsvlI.js.map +1 -0
- package/dist/x-tab-group-ngNByee3.js +49 -0
- package/dist/{x-tab-group-DTR-H8Sn.js.map → x-tab-group-ngNByee3.js.map} +1 -1
- package/dist/{x-text-field-Ccv2SH00.js → x-text-field-uL1ePP_x.js} +6 -6
- package/dist/{x-text-field-Ccv2SH00.js.map → x-text-field-uL1ePP_x.js.map} +1 -1
- package/langs/translation-fr.json +1 -0
- package/package.json +11 -9
- package/src/components/vuetifyDesignSystemLoader.ts +23 -0
- package/src/vue/__tests__/utils/vuetify.ts +42 -0
- package/src/vue/__tests__/x-btn.test.ts +53 -0
- package/src/vue/css/style.css +4 -3
- package/src/vue/x-alert.vue +14 -17
- package/src/vue/x-breadcrumb.vue +5 -1
- package/src/vue/x-btn.vue +34 -1
- package/src/vue/x-divider.vue +1 -1
- package/src/vue/x-menu-item.vue +2 -2
- package/src/vue/x-menu-label.vue +25 -0
- package/src/vue/x-menu.vue +13 -6
- package/src/vue/x-navigation-tree.vue +204 -0
- package/src/vue/x-tab-group.vue +4 -2
- package/tsconfig.json +2 -1
- package/{src/vue.d.ts → vitest.config.ts} +17 -7
- package/dist/index-CkW0K4NP.js.map +0 -1
- package/dist/x-alert-Cm6mzRpR.js +0 -29
- package/dist/x-alert-Cm6mzRpR.js.map +0 -1
- package/dist/x-breadcrumb-DBZVExfF.js +0 -21
- package/dist/x-btn-DsACLwMY.js +0 -17
- package/dist/x-btn-DsACLwMY.js.map +0 -1
- package/dist/x-divider-7cmRuxTV.js +0 -16
- package/dist/x-divider-7cmRuxTV.js.map +0 -1
- package/dist/x-menu-VerLAd9F.js +0 -32
- package/dist/x-menu-VerLAd9F.js.map +0 -1
- package/dist/x-menu-item-DGurfOCF.js +0 -22
- package/dist/x-menu-item-DGurfOCF.js.map +0 -1
- package/dist/x-tab-group-DTR-H8Sn.js +0 -49
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
See the LICENSE file distributed with this work for additional
|
|
3
|
+
information regarding copyright ownership.
|
|
4
|
+
|
|
5
|
+
This is free software; you can redistribute it and/or modify it
|
|
6
|
+
under the terms of the GNU Lesser General Public License as
|
|
7
|
+
published by the Free Software Foundation; either version 2.1 of
|
|
8
|
+
the License, or (at your option) any later version.
|
|
9
|
+
|
|
10
|
+
This software is distributed in the hope that it will be useful,
|
|
11
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
12
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
13
|
+
Lesser General Public License for more details.
|
|
14
|
+
|
|
15
|
+
You should have received a copy of the GNU Lesser General Public
|
|
16
|
+
License along with this software; if not, write to the Free
|
|
17
|
+
Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
|
|
18
|
+
02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
|
19
|
+
-->
|
|
20
|
+
<script setup lang="ts">
|
|
21
|
+
/**
|
|
22
|
+
* Navigation Tree implemented using Vuetify's VTreeView component.
|
|
23
|
+
* In order to use the initial component as a proper Navigation Tree for
|
|
24
|
+
* Cristal, a few changes were made:
|
|
25
|
+
* - The only node activated matches the current page, or the clicked link if
|
|
26
|
+
* the component has a custom clickAction. We want to use actual links so
|
|
27
|
+
* that the user can click them normally (to e.g., open them in a new tab).
|
|
28
|
+
* So the default behavior of activating a node by clicking anywhere on the
|
|
29
|
+
* item was disabled. Default hover effects, such as darkening or changing
|
|
30
|
+
* the cursor on items, were also disabled.
|
|
31
|
+
*/
|
|
32
|
+
import { Ref, onBeforeMount, ref, watch } from "vue";
|
|
33
|
+
import { VTreeview } from "vuetify/labs/VTreeview";
|
|
34
|
+
import { type PageData } from "@xwiki/cristal-api";
|
|
35
|
+
import type {
|
|
36
|
+
NavigationTreeSource,
|
|
37
|
+
NavigationTreeNode,
|
|
38
|
+
} from "@xwiki/cristal-navigation-tree-api";
|
|
39
|
+
|
|
40
|
+
type TreeItem = {
|
|
41
|
+
id: string;
|
|
42
|
+
title: string;
|
|
43
|
+
href: string;
|
|
44
|
+
children?: Array<TreeItem>;
|
|
45
|
+
_location: string;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
type OnClickAction = (node: NavigationTreeNode) => void;
|
|
49
|
+
|
|
50
|
+
const rootNodes: Ref<Array<TreeItem>> = ref([]);
|
|
51
|
+
const tree: Ref<VTreeview | undefined> = ref(undefined);
|
|
52
|
+
|
|
53
|
+
const activatedNodes: Ref<Array<string>> = ref(new Array<string>());
|
|
54
|
+
const expandedNodes: Ref<Array<string>> = ref(new Array<string>());
|
|
55
|
+
|
|
56
|
+
const props = defineProps<{
|
|
57
|
+
treeSource: NavigationTreeSource;
|
|
58
|
+
clickAction?: OnClickAction;
|
|
59
|
+
currentPage?: PageData;
|
|
60
|
+
}>();
|
|
61
|
+
|
|
62
|
+
onBeforeMount(async () => {
|
|
63
|
+
for (const node of await props.treeSource.getChildNodes("")) {
|
|
64
|
+
rootNodes.value.push({
|
|
65
|
+
id: node.id,
|
|
66
|
+
title: node.label,
|
|
67
|
+
href: node.url,
|
|
68
|
+
children: node.has_children ? [] : undefined,
|
|
69
|
+
_location: node.location,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (props.currentPage !== undefined) {
|
|
73
|
+
await expandTree();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
watch(
|
|
78
|
+
() => props.currentPage,
|
|
79
|
+
async () => {
|
|
80
|
+
if (props.currentPage) {
|
|
81
|
+
await expandTree();
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
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
|
+
}
|
|
97
|
+
if (!expandedNodes.value.includes(node.id)) {
|
|
98
|
+
expandedNodes.value.push(node.id);
|
|
99
|
+
}
|
|
100
|
+
currentNodes = node.children!;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
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
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
async function lazyLoadChildren(item: unknown) {
|
|
126
|
+
const treeItem = item as TreeItem;
|
|
127
|
+
const childNodes = await props.treeSource.getChildNodes(treeItem.id);
|
|
128
|
+
for (const child of childNodes) {
|
|
129
|
+
treeItem.children?.push({
|
|
130
|
+
id: child.id,
|
|
131
|
+
title: child.label,
|
|
132
|
+
href: child.url,
|
|
133
|
+
children: child.has_children ? [] : undefined,
|
|
134
|
+
_location: child.location,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
// If the node doesn't have any children, we update it.
|
|
138
|
+
if (childNodes.length == 0) {
|
|
139
|
+
treeItem.children = undefined;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function clearSelection() {
|
|
144
|
+
// Clicking on a node would activate it and this can't be disabled easily.
|
|
145
|
+
// With this listener, we ensure that only the first activated node stays
|
|
146
|
+
// active.
|
|
147
|
+
if (activatedNodes.value.length > 1) {
|
|
148
|
+
activatedNodes.value.pop();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<template>
|
|
154
|
+
<v-treeview
|
|
155
|
+
ref="tree"
|
|
156
|
+
v-model:opened="expandedNodes"
|
|
157
|
+
density="compact"
|
|
158
|
+
:activated="activatedNodes"
|
|
159
|
+
:items="rootNodes"
|
|
160
|
+
:load-children="lazyLoadChildren"
|
|
161
|
+
activatable
|
|
162
|
+
active-strategy="independent"
|
|
163
|
+
item-value="id"
|
|
164
|
+
open-strategy="multiple"
|
|
165
|
+
@update:activated="clearSelection"
|
|
166
|
+
>
|
|
167
|
+
<template #title="{ item }: { item: any }">
|
|
168
|
+
<a
|
|
169
|
+
v-if="props.clickAction"
|
|
170
|
+
:href="item.href"
|
|
171
|
+
@click.prevent="
|
|
172
|
+
activatedNodes = [item.id];
|
|
173
|
+
clickAction!({
|
|
174
|
+
id: item.id,
|
|
175
|
+
label: item.title,
|
|
176
|
+
location: item._location,
|
|
177
|
+
url: item.href,
|
|
178
|
+
has_children: item.children !== undefined,
|
|
179
|
+
});
|
|
180
|
+
"
|
|
181
|
+
>{{ item.title }}</a
|
|
182
|
+
>
|
|
183
|
+
<a v-else :href="item.href">{{ item.title }}</a>
|
|
184
|
+
</template>
|
|
185
|
+
</v-treeview>
|
|
186
|
+
</template>
|
|
187
|
+
|
|
188
|
+
<style scoped>
|
|
189
|
+
.v-list {
|
|
190
|
+
background: none;
|
|
191
|
+
}
|
|
192
|
+
:deep(a) {
|
|
193
|
+
text-decoration: none;
|
|
194
|
+
color: var(--cr-base-text-color);
|
|
195
|
+
}
|
|
196
|
+
/* Disable hover on items. */
|
|
197
|
+
:deep(.v-list-item__overlay) {
|
|
198
|
+
--v-hover-opacity: 0;
|
|
199
|
+
}
|
|
200
|
+
/* Disable hand cursor on items, since we disable the default click action. */
|
|
201
|
+
:deep(.v-list-item--link) {
|
|
202
|
+
cursor: default;
|
|
203
|
+
}
|
|
204
|
+
</style>
|
package/src/vue/x-tab-group.vue
CHANGED
|
@@ -23,8 +23,10 @@ const tab = ref(null);
|
|
|
23
23
|
|
|
24
24
|
const emits = defineEmits(["change"]);
|
|
25
25
|
|
|
26
|
-
function change(tabId:
|
|
27
|
-
|
|
26
|
+
function change(tabId: unknown) {
|
|
27
|
+
if (typeof tabId == "string") {
|
|
28
|
+
emits("change", tabId);
|
|
29
|
+
}
|
|
28
30
|
}
|
|
29
31
|
</script>
|
|
30
32
|
|
package/tsconfig.json
CHANGED
|
@@ -18,10 +18,20 @@
|
|
|
18
18
|
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
21
|
+
import { defineConfig, mergeConfig } from "vitest/config";
|
|
22
|
+
import defaultConfig from "@xwiki/cristal-dev-config/vitest-vue.config";
|
|
23
|
+
import localConfig from "./vite.config";
|
|
24
|
+
|
|
25
|
+
export default mergeConfig(
|
|
26
|
+
mergeConfig(defaultConfig, localConfig),
|
|
27
|
+
defineConfig({
|
|
28
|
+
test: {
|
|
29
|
+
server: {
|
|
30
|
+
deps: {
|
|
31
|
+
// see https://github.com/vitest-dev/vitest/discussions/2677#discussioncomment-7035566
|
|
32
|
+
inline: ["vuetify"],
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
}),
|
|
37
|
+
);
|