@vc-shell/framework 1.1.68 → 1.1.70
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 +13 -0
- package/core/services/app-bar-mobile-buttons-service.ts +6 -2
- package/dist/core/services/app-bar-mobile-buttons-service.d.ts.map +1 -1
- package/dist/framework.js +6236 -6189
- package/dist/index.css +1 -1
- package/dist/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue.d.ts.map +1 -1
- package/dist/shared/components/generic-dropdown/generic-dropdown.vue.d.ts.map +1 -1
- package/dist/shared/components/notification-dropdown/notification-dropdown.vue.d.ts.map +1 -1
- package/dist/shared/components/sidebar/sidebar.vue.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-tooltip/vc-tooltip.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-multivalue/vc-multivalue.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-select/vc-select.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarContent.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarHeader.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarOverlay.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarSlots.vue.d.ts +3 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarSlots.vue.d.ts.map +1 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/composables/useAppSlots.d.ts +28 -0
- package/dist/ui/components/organisms/vc-app/composables/useAppSlots.d.ts.map +1 -0
- package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-row/vc-table-row.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableColumnResize.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/composables/useTableState.d.ts.map +1 -1
- package/dist/{vendor-date-fns-CdFbeoHV.js → vendor-date-fns-sZ1zMzTH.js} +1109 -1090
- package/dist/{vendor-floating-ui-core-DpX2jufl.js → vendor-floating-ui-core-3dy7r5mx.js} +1 -1
- package/dist/{vendor-floating-ui-dom-C4AKN5Mo.js → vendor-floating-ui-dom-DCjH_QK4.js} +6 -6
- package/dist/{vendor-floating-ui-utils-CRaCuFxS.js → vendor-floating-ui-utils-D2sT7feD.js} +15 -15
- package/dist/{vendor-floating-ui-vue-OwtolkBv.js → vendor-floating-ui-vue-BUBCqiRN.js} +12 -12
- package/dist/vendor-vuepic-vue-datepicker-Chx5s5I-.js +5116 -0
- package/package.json +5 -5
- package/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue +3 -1
- package/shared/components/generic-dropdown/generic-dropdown.vue +15 -10
- package/shared/components/notification-dropdown/notification-dropdown.vue +1 -0
- package/shared/components/sidebar/sidebar.vue +1 -1
- package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +1 -1
- package/ui/components/molecules/vc-input/vc-input.vue +8 -0
- package/ui/components/molecules/vc-multivalue/vc-multivalue.vue +1 -1
- package/ui/components/molecules/vc-select/vc-select.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarContent.vue +5 -5
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarHeader.vue +5 -8
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarOverlay.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/AppBarSlots.vue +118 -0
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/_internal/MenuSidebar.vue +12 -8
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +3 -74
- package/ui/components/organisms/vc-app/composables/useAppSlots.ts +75 -0
- package/ui/components/organisms/vc-app/vc-app.vue +30 -42
- package/ui/components/organisms/vc-blade/_internal/vc-blade-header/vc-blade-header.vue +1 -1
- package/ui/components/organisms/vc-table/_internal/vc-table-desktop-view/_internal/vc-table-row/vc-table-row.vue +5 -1
- package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +0 -1
- package/ui/components/organisms/vc-table/composables/useTableState.ts +17 -16
- package/dist/vendor-vuepic-vue-datepicker-DkHsqyoL.js +0 -4997
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/framework",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.70",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/framework.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"@tiptap/vue-3": "^2.25.0",
|
|
59
59
|
"@vee-validate/i18n": "^4.12.4",
|
|
60
60
|
"@vee-validate/rules": "^4.12.4",
|
|
61
|
-
"@vuepic/vue-datepicker": "^
|
|
61
|
+
"@vuepic/vue-datepicker": "^11.0.2",
|
|
62
62
|
"@vueuse/components": "^10.7.1",
|
|
63
63
|
"@vueuse/core": "^10.7.1",
|
|
64
64
|
"@vueuse/integrations": "^10.7.1",
|
|
@@ -85,9 +85,9 @@
|
|
|
85
85
|
"@fullhuman/postcss-purgecss": "^7.0.2",
|
|
86
86
|
"@laynezh/vite-plugin-lib-assets": "v1.1.0",
|
|
87
87
|
"@types/dompurify": "^3.0.5",
|
|
88
|
-
"@vc-shell/api-client-generator": "^1.1.
|
|
89
|
-
"@vc-shell/config-generator": "^1.1.
|
|
90
|
-
"@vc-shell/ts-config": "^1.1.
|
|
88
|
+
"@vc-shell/api-client-generator": "^1.1.70",
|
|
89
|
+
"@vc-shell/config-generator": "^1.1.70",
|
|
90
|
+
"@vc-shell/ts-config": "^1.1.70",
|
|
91
91
|
"@vitejs/plugin-vue": "^5.2.3",
|
|
92
92
|
"@vue/test-utils": "^2.4.5",
|
|
93
93
|
"cypress-signalr-mock": "^1.5.0",
|
|
@@ -6,8 +6,10 @@
|
|
|
6
6
|
@contextmenu.prevent
|
|
7
7
|
>
|
|
8
8
|
<GenericDropdown
|
|
9
|
+
:opened="true"
|
|
9
10
|
:items="appsList"
|
|
10
11
|
:is-item-active="(item) => locationHandler(item.relativeUrl ?? '')"
|
|
12
|
+
max-height="auto"
|
|
11
13
|
@item-click="switchApp"
|
|
12
14
|
>
|
|
13
15
|
<template #item="{ item }">
|
|
@@ -67,7 +69,7 @@ const switchApp = (app: AppDescriptor) => {
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
.vc-app-switcher {
|
|
70
|
-
@apply tw-relative tw-flex tw-shrink-0;
|
|
72
|
+
@apply tw-relative tw-flex tw-shrink-0 tw-h-full;
|
|
71
73
|
|
|
72
74
|
&__item {
|
|
73
75
|
@apply tw-flex tw-items-center tw-w-full tw-p-3 tw-w-full;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="vc-dropdown">
|
|
3
3
|
<div
|
|
4
|
+
v-if="$slots.trigger"
|
|
4
5
|
ref="referenceEl"
|
|
5
6
|
class="vc-dropdown__trigger"
|
|
6
7
|
>
|
|
@@ -11,7 +12,8 @@
|
|
|
11
12
|
</div>
|
|
12
13
|
|
|
13
14
|
<teleport
|
|
14
|
-
to="
|
|
15
|
+
to=".vc-app"
|
|
16
|
+
defer
|
|
15
17
|
:disabled="!floating"
|
|
16
18
|
>
|
|
17
19
|
<div
|
|
@@ -25,10 +27,7 @@
|
|
|
25
27
|
}"
|
|
26
28
|
:class="dropdownClasses"
|
|
27
29
|
>
|
|
28
|
-
<div
|
|
29
|
-
class="vc-dropdown__content"
|
|
30
|
-
@click.stop
|
|
31
|
-
>
|
|
30
|
+
<div class="vc-dropdown__content">
|
|
32
31
|
<slot
|
|
33
32
|
name="items-container"
|
|
34
33
|
:items="items"
|
|
@@ -95,7 +94,7 @@ export interface Props<T> {
|
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
const props = withDefaults(defineProps<Props<T>>(), {
|
|
98
|
-
opened:
|
|
97
|
+
opened: false,
|
|
99
98
|
items: () => [],
|
|
100
99
|
floating: false,
|
|
101
100
|
placement: "bottom",
|
|
@@ -119,17 +118,23 @@ defineSlots<{
|
|
|
119
118
|
"items-container"?: (args: { items: T[]; close: () => void }) => any;
|
|
120
119
|
}>();
|
|
121
120
|
|
|
122
|
-
const isMobile = inject("isMobile")
|
|
121
|
+
const isMobile = inject<Ref<boolean>>("isMobile", ref(false));
|
|
123
122
|
|
|
124
123
|
const referenceEl = ref<HTMLElement | null>(null);
|
|
125
124
|
const floatingEl = ref<HTMLElement | null>(null);
|
|
126
125
|
|
|
127
|
-
const
|
|
126
|
+
const { floatingStyles, placement, update, x, y } = useFloating(referenceEl, floatingEl, {
|
|
128
127
|
placement: props.placement,
|
|
129
|
-
whileElementsMounted: autoUpdate,
|
|
128
|
+
whileElementsMounted: props.floating ? autoUpdate : undefined,
|
|
130
129
|
middleware: [shift({ padding: 8 }), flip({ padding: 8 }), floatingOffset(props.offset)],
|
|
131
130
|
});
|
|
132
131
|
|
|
132
|
+
const floater = {
|
|
133
|
+
placement,
|
|
134
|
+
x,
|
|
135
|
+
y,
|
|
136
|
+
};
|
|
137
|
+
|
|
133
138
|
const dropdownClasses = computed(() => {
|
|
134
139
|
const placement = floater.placement.value;
|
|
135
140
|
return [
|
|
@@ -181,7 +186,7 @@ const calcHeight = computed(() => {
|
|
|
181
186
|
}
|
|
182
187
|
|
|
183
188
|
&__dropdown {
|
|
184
|
-
@apply tw-rounded-[6px] tw-w-full tw-overflow-auto tw-flex tw-flex-col tw-relative tw-h-
|
|
189
|
+
@apply tw-rounded-[6px] tw-w-full tw-overflow-auto tw-flex tw-flex-col tw-relative tw-h-full;
|
|
185
190
|
|
|
186
191
|
&--mobile {
|
|
187
192
|
@apply tw-w-full;
|
|
@@ -772,6 +772,12 @@ function handleFocus() {
|
|
|
772
772
|
& > div {
|
|
773
773
|
@apply tw-w-full tw-h-full tw-flex tw-items-center;
|
|
774
774
|
}
|
|
775
|
+
|
|
776
|
+
.vc-app_mobile & {
|
|
777
|
+
& > div {
|
|
778
|
+
@apply tw-w-auto tw-h-auto tw-flex-auto tw-items-center;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
775
781
|
}
|
|
776
782
|
|
|
777
783
|
.dp__pm_am_button {
|
|
@@ -790,6 +796,8 @@ function handleFocus() {
|
|
|
790
796
|
.dp__input {
|
|
791
797
|
@apply tw-font-jakarta #{!important};
|
|
792
798
|
|
|
799
|
+
--dp-input-padding: 6px 12px 6px 12px;
|
|
800
|
+
|
|
793
801
|
&::-ms-reveal,
|
|
794
802
|
&::-ms-clear {
|
|
795
803
|
@apply tw-hidden;
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
class="app-bar-content"
|
|
4
|
-
:class="{
|
|
4
|
+
:class="{
|
|
5
|
+
'app-bar-content--collapsed': !expanded,
|
|
6
|
+
// 'app-bar-content--embedded': isEmbedded
|
|
7
|
+
}"
|
|
5
8
|
>
|
|
6
9
|
<div class="app-bar-content__main">
|
|
7
10
|
<slot name="navmenu" />
|
|
8
11
|
</div>
|
|
9
|
-
<div
|
|
10
|
-
v-if="!isEmbedded"
|
|
11
|
-
class="app-bar-content__footer"
|
|
12
|
-
>
|
|
12
|
+
<div class="app-bar-content__footer">
|
|
13
13
|
<slot name="user-dropdown" />
|
|
14
14
|
</div>
|
|
15
15
|
</div>
|
|
@@ -34,10 +34,7 @@
|
|
|
34
34
|
v-if="$isMobile.value"
|
|
35
35
|
class="app-bar-header__actions"
|
|
36
36
|
>
|
|
37
|
-
<slot
|
|
38
|
-
v-if="$isMobile.value"
|
|
39
|
-
name="actions"
|
|
40
|
-
/>
|
|
37
|
+
<slot name="actions" />
|
|
41
38
|
</div>
|
|
42
39
|
|
|
43
40
|
<Transition
|
|
@@ -93,10 +90,10 @@ const isMobile = inject("isMobile") as Ref<boolean>;
|
|
|
93
90
|
const isDesktop = inject("isDesktop") as Ref<boolean>;
|
|
94
91
|
|
|
95
92
|
const showAppBar = computed(() => {
|
|
96
|
-
if (isEmbedded) {
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
return (isMobile.value && blades.value.length <= 1) || isDesktop.value;
|
|
93
|
+
// if (isEmbedded) {
|
|
94
|
+
// return false;
|
|
95
|
+
// }
|
|
96
|
+
return (isMobile.value && blades.value.length <= 1) || (isDesktop.value && !isEmbedded);
|
|
100
97
|
});
|
|
101
98
|
|
|
102
99
|
watchEffect(
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<!-- Desktop version -->
|
|
3
|
+
<template v-if="isDesktop && !isMenuOpen">
|
|
4
|
+
<AppBarContent :expanded="isExpanded">
|
|
5
|
+
<template #navmenu>
|
|
6
|
+
<component
|
|
7
|
+
:is="slots.navmenu"
|
|
8
|
+
v-if="slots.navmenu"
|
|
9
|
+
/>
|
|
10
|
+
</template>
|
|
11
|
+
<template #user-dropdown>
|
|
12
|
+
<component
|
|
13
|
+
:is="slots.userDropdown"
|
|
14
|
+
v-if="slots.userDropdown"
|
|
15
|
+
/>
|
|
16
|
+
</template>
|
|
17
|
+
</AppBarContent>
|
|
18
|
+
</template>
|
|
19
|
+
|
|
20
|
+
<!-- Menu sidebar (both desktop and mobile) -->
|
|
21
|
+
<MenuSidebar
|
|
22
|
+
v-if="isMenuOpen"
|
|
23
|
+
:is-opened="isMenuOpen"
|
|
24
|
+
:expanded="isExpanded"
|
|
25
|
+
@update:is-opened="closeMenu"
|
|
26
|
+
>
|
|
27
|
+
<template #navmenu>
|
|
28
|
+
<component
|
|
29
|
+
:is="slots.navmenu"
|
|
30
|
+
v-if="slots.navmenu"
|
|
31
|
+
/>
|
|
32
|
+
</template>
|
|
33
|
+
<template #user-dropdown>
|
|
34
|
+
<component
|
|
35
|
+
:is="slots.userDropdown"
|
|
36
|
+
v-if="slots.userDropdown"
|
|
37
|
+
/>
|
|
38
|
+
</template>
|
|
39
|
+
<template #app-switcher>
|
|
40
|
+
<component
|
|
41
|
+
:is="slots.appSwitcher"
|
|
42
|
+
v-if="slots.appSwitcher"
|
|
43
|
+
/>
|
|
44
|
+
</template>
|
|
45
|
+
<template #widgets>
|
|
46
|
+
<AppBarWidgetsMenu />
|
|
47
|
+
</template>
|
|
48
|
+
<template #widgets-active-content>
|
|
49
|
+
<AppBarWidgetContent />
|
|
50
|
+
</template>
|
|
51
|
+
</MenuSidebar>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script lang="ts" setup>
|
|
55
|
+
import { computed, inject, ref, h, defineComponent } from "vue";
|
|
56
|
+
import { useAppMenuState } from "../../composables/useAppMenuState";
|
|
57
|
+
import { useAppSlots } from "../../../composables/useAppSlots";
|
|
58
|
+
import { useAppBarWidgets } from "../composables/useAppBarWidgets";
|
|
59
|
+
import AppBarContent from "./AppBarContent.vue";
|
|
60
|
+
import MenuSidebar from "./MenuSidebar.vue";
|
|
61
|
+
import AppBarWidgetsMenu from "./AppBarWidgetsMenu.vue";
|
|
62
|
+
|
|
63
|
+
// Create AppBarWidgetContent component inline
|
|
64
|
+
|
|
65
|
+
const AppBarWidgetContent = defineComponent({
|
|
66
|
+
setup() {
|
|
67
|
+
const { currentWidget, hideAllWidgets, isAnyWidgetVisible } = useAppBarWidgets();
|
|
68
|
+
const isMobile = inject("isMobile", ref(false));
|
|
69
|
+
|
|
70
|
+
return () => {
|
|
71
|
+
if (!isAnyWidgetVisible.value || !currentWidget.value?.component) return null;
|
|
72
|
+
|
|
73
|
+
return h(
|
|
74
|
+
"div",
|
|
75
|
+
{
|
|
76
|
+
class: [
|
|
77
|
+
"app-bar-widget-content",
|
|
78
|
+
{
|
|
79
|
+
"app-bar-widget-content--mobile": isMobile.value,
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
},
|
|
83
|
+
[
|
|
84
|
+
h(currentWidget.value.component, {
|
|
85
|
+
...currentWidget.value.props,
|
|
86
|
+
onClose: hideAllWidgets,
|
|
87
|
+
}),
|
|
88
|
+
],
|
|
89
|
+
);
|
|
90
|
+
};
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const { state, closeAll } = useAppMenuState();
|
|
95
|
+
const slots = useAppSlots();
|
|
96
|
+
|
|
97
|
+
const isDesktop = inject("isDesktop", ref(true));
|
|
98
|
+
|
|
99
|
+
const isExpanded = computed(() => state.value.isSidebarExpanded);
|
|
100
|
+
const isMenuOpen = computed(() => state.value.isMenuOpen);
|
|
101
|
+
|
|
102
|
+
const closeMenu = () => {
|
|
103
|
+
closeAll();
|
|
104
|
+
};
|
|
105
|
+
</script>
|
|
106
|
+
|
|
107
|
+
<style lang="scss">
|
|
108
|
+
.app-bar-slots {
|
|
109
|
+
@apply tw-h-full;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.app-bar-widget-content {
|
|
113
|
+
@apply tw-overflow-auto tw-max-h-[250px];
|
|
114
|
+
&--mobile {
|
|
115
|
+
// Mobile specific styles if needed
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
</style>
|
|
@@ -11,11 +11,12 @@
|
|
|
11
11
|
<div
|
|
12
12
|
class="menu-sidebar__wrapper"
|
|
13
13
|
:class="{
|
|
14
|
+
'menu-sidebar__wrapper--desktop': $isDesktop.value,
|
|
14
15
|
'menu-sidebar__wrapper--expanded': $isDesktop.value && expanded,
|
|
15
|
-
'menu-sidebar__wrapper--collapsed': $isDesktop.value && !expanded,
|
|
16
16
|
}"
|
|
17
17
|
>
|
|
18
18
|
<div
|
|
19
|
+
v-if="!isEmbedded"
|
|
19
20
|
class="menu-sidebar__header"
|
|
20
21
|
:class="{
|
|
21
22
|
'menu-sidebar__header--mobile': $isMobile.value,
|
|
@@ -64,7 +65,8 @@
|
|
|
64
65
|
<!-- eslint-disable @typescript-eslint/no-explicit-any -->
|
|
65
66
|
<script lang="ts" setup>
|
|
66
67
|
import { Sidebar } from "../../../../../../../shared/components/sidebar";
|
|
67
|
-
import { MaybeRef } from "vue";
|
|
68
|
+
import { MaybeRef, inject } from "vue";
|
|
69
|
+
import { EMBEDDED_MODE } from "../../../../../../../injection-keys";
|
|
68
70
|
|
|
69
71
|
defineProps<{
|
|
70
72
|
isOpened: boolean;
|
|
@@ -82,24 +84,26 @@ defineSlots<{
|
|
|
82
84
|
"widgets-active-content": (props: any) => any;
|
|
83
85
|
widgets: (props: any) => any;
|
|
84
86
|
}>();
|
|
87
|
+
|
|
88
|
+
const isEmbedded = inject(EMBEDDED_MODE);
|
|
85
89
|
</script>
|
|
86
90
|
|
|
87
91
|
<style lang="scss">
|
|
88
92
|
.menu-sidebar {
|
|
89
93
|
&__wrapper {
|
|
90
|
-
@apply tw-absolute tw-top-0 tw-left-0 tw-w-full
|
|
94
|
+
@apply tw-absolute tw-top-0 tw-left-0 tw-w-full tw-bottom-0 tw-z-10 tw-flex tw-flex-col;
|
|
91
95
|
|
|
92
|
-
&--
|
|
93
|
-
@apply tw-
|
|
96
|
+
&--desktop {
|
|
97
|
+
@apply tw-w-[var(--app-bar-width)] tw-z-[12];
|
|
94
98
|
}
|
|
95
99
|
|
|
96
|
-
&--
|
|
97
|
-
@apply tw-
|
|
100
|
+
&--expanded {
|
|
101
|
+
@apply tw-absolute tw-top-0 tw-left-0;
|
|
98
102
|
}
|
|
99
103
|
}
|
|
100
104
|
|
|
101
105
|
&__content {
|
|
102
|
-
@apply tw-flex tw-flex-col tw-h-
|
|
106
|
+
@apply tw-flex tw-flex-col tw-h-[calc(100vh-var(--app-bar-height))] tw-bg-[var(--app-bar-background)] tw-flex-1 tw-relative;
|
|
103
107
|
|
|
104
108
|
&:before {
|
|
105
109
|
content: "";
|
|
@@ -37,8 +37,6 @@
|
|
|
37
37
|
'vc-app-bar__wrapper--mobile': $isMobile.value,
|
|
38
38
|
'vc-app-bar__wrapper--hover-collapsed': $isDesktop.value && !isHoverExpanded && !state.isSidebarExpanded,
|
|
39
39
|
}"
|
|
40
|
-
@mouseenter="collapseButtonHover = true"
|
|
41
|
-
@mouseleave="collapseButtonHover = false"
|
|
42
40
|
>
|
|
43
41
|
<AppBarHeader
|
|
44
42
|
:logo="logo"
|
|
@@ -59,49 +57,7 @@
|
|
|
59
57
|
</template>
|
|
60
58
|
</AppBarHeader>
|
|
61
59
|
|
|
62
|
-
<
|
|
63
|
-
v-if="state.isMenuOpen"
|
|
64
|
-
:is-opened="state.isMenuOpen"
|
|
65
|
-
:expanded="state.isSidebarExpanded"
|
|
66
|
-
@update:is-opened="handleMenuClose"
|
|
67
|
-
>
|
|
68
|
-
<template #navmenu>
|
|
69
|
-
<slot name="navmenu" />
|
|
70
|
-
</template>
|
|
71
|
-
<template #user-dropdown>
|
|
72
|
-
<slot name="user-dropdown" />
|
|
73
|
-
</template>
|
|
74
|
-
<template #app-switcher>
|
|
75
|
-
<slot name="app-switcher" />
|
|
76
|
-
</template>
|
|
77
|
-
<template #widgets>
|
|
78
|
-
<AppBarWidgetsMenu />
|
|
79
|
-
</template>
|
|
80
|
-
<template #widgets-active-content>
|
|
81
|
-
<div
|
|
82
|
-
v-if="isAnyWidgetVisible"
|
|
83
|
-
:class="['vc-app-bar__menu-dropdowns', { 'vc-app-bar__menu-dropdowns--mobile': $isMobile.value }]"
|
|
84
|
-
>
|
|
85
|
-
<component
|
|
86
|
-
:is="currentWidget?.component"
|
|
87
|
-
v-bind="currentWidget?.props || {}"
|
|
88
|
-
@close="hideAllWidgets"
|
|
89
|
-
/>
|
|
90
|
-
</div>
|
|
91
|
-
</template>
|
|
92
|
-
</MenuSidebar>
|
|
93
|
-
|
|
94
|
-
<AppBarContent
|
|
95
|
-
v-if="$isDesktop.value"
|
|
96
|
-
:expanded="state.isSidebarExpanded"
|
|
97
|
-
>
|
|
98
|
-
<template #navmenu>
|
|
99
|
-
<slot name="navmenu" />
|
|
100
|
-
</template>
|
|
101
|
-
<template #user-dropdown>
|
|
102
|
-
<slot name="user-dropdown" />
|
|
103
|
-
</template>
|
|
104
|
-
</AppBarContent>
|
|
60
|
+
<AppBarSlots />
|
|
105
61
|
</div>
|
|
106
62
|
</div>
|
|
107
63
|
</div>
|
|
@@ -110,12 +66,9 @@
|
|
|
110
66
|
<script lang="ts" setup>
|
|
111
67
|
import { VcIcon } from "../../../../";
|
|
112
68
|
import { useAppMenuState } from "../composables/useAppMenuState";
|
|
113
|
-
import { useAppBarWidgets } from "./composables/useAppBarWidgets";
|
|
114
69
|
import AppBarHeader from "./_internal/AppBarHeader.vue";
|
|
115
70
|
import AppBarMobileActions from "./_internal/AppBarMobileActions.vue";
|
|
116
|
-
import
|
|
117
|
-
import AppBarContent from "./_internal/AppBarContent.vue";
|
|
118
|
-
import AppBarWidgetsMenu from "./_internal/AppBarWidgetsMenu.vue";
|
|
71
|
+
import AppBarSlots from "./_internal/AppBarSlots.vue";
|
|
119
72
|
import { ref, computed, provide, inject } from "vue";
|
|
120
73
|
|
|
121
74
|
export interface Props {
|
|
@@ -139,38 +92,14 @@ defineProps<Props>();
|
|
|
139
92
|
defineEmits<Emits>();
|
|
140
93
|
defineSlots<Slots>();
|
|
141
94
|
|
|
142
|
-
const {
|
|
143
|
-
state,
|
|
144
|
-
toggleSidebar,
|
|
145
|
-
toggleMenu: toggleMenuState,
|
|
146
|
-
closeAll,
|
|
147
|
-
toggleHoverExpanded,
|
|
148
|
-
isHoverExpanded,
|
|
149
|
-
} = useAppMenuState();
|
|
150
|
-
|
|
151
|
-
const { currentWidget, hideAllWidgets, isAnyWidgetVisible } = useAppBarWidgets();
|
|
95
|
+
const { state, toggleSidebar, toggleMenu, closeAll, toggleHoverExpanded, isHoverExpanded } = useAppMenuState();
|
|
152
96
|
|
|
153
97
|
const isMobile = inject("isMobile", ref(false));
|
|
154
98
|
const isDesktop = inject("isDesktop", ref(true));
|
|
155
|
-
const collapseButtonHover = ref(false);
|
|
156
99
|
|
|
157
100
|
// Provide appMenuState for child components
|
|
158
101
|
provide("appMenuState", { closeAll });
|
|
159
102
|
|
|
160
|
-
const toggleMenu = () => {
|
|
161
|
-
toggleMenuState();
|
|
162
|
-
if (!state.value.isMenuOpen) {
|
|
163
|
-
hideAllWidgets();
|
|
164
|
-
}
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const handleMenuClose = (value: boolean) => {
|
|
168
|
-
if (!value) {
|
|
169
|
-
closeAll();
|
|
170
|
-
hideAllWidgets();
|
|
171
|
-
}
|
|
172
|
-
};
|
|
173
|
-
|
|
174
103
|
// Simple hover effect processing
|
|
175
104
|
const handleHoverExpand = (shouldExpand?: boolean) => {
|
|
176
105
|
toggleHoverExpanded(shouldExpand);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { inject, provide, InjectionKey, Slots, VNode, h, Ref } from "vue";
|
|
2
|
+
import VcAppMenu from "../_internal/vc-app-menu/vc-app-menu.vue";
|
|
3
|
+
import { UserDropdownButton } from "../../../../../shared/components";
|
|
4
|
+
import { components } from "../../../../../shared/components/app-switcher";
|
|
5
|
+
import { AppDescriptor } from "../../../../../core/api/platform";
|
|
6
|
+
import { EMBEDDED_MODE } from "../../../../../injection-keys";
|
|
7
|
+
|
|
8
|
+
export interface AppSlots {
|
|
9
|
+
navmenu?: () => VNode | VNode[];
|
|
10
|
+
userDropdown?: () => VNode | VNode[];
|
|
11
|
+
appSwitcher?: () => VNode | VNode[];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const APP_SLOTS_KEY: InjectionKey<AppSlots> = Symbol("app-slots");
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Provide app slots to child components
|
|
18
|
+
*/
|
|
19
|
+
export function provideAppSlots(
|
|
20
|
+
slots: Slots,
|
|
21
|
+
props: {
|
|
22
|
+
disableMenu?: boolean;
|
|
23
|
+
disableAppSwitcher?: boolean;
|
|
24
|
+
version?: string;
|
|
25
|
+
avatar?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
role?: string;
|
|
28
|
+
appsList?: Ref<AppDescriptor[]>;
|
|
29
|
+
isEmbedded?: boolean;
|
|
30
|
+
},
|
|
31
|
+
handlers: {
|
|
32
|
+
onMenuItemClick?: (item: any) => void;
|
|
33
|
+
switchApp?: (event: any) => void;
|
|
34
|
+
},
|
|
35
|
+
) {
|
|
36
|
+
|
|
37
|
+
const appSlots: AppSlots = {
|
|
38
|
+
navmenu: () => {
|
|
39
|
+
if (props.disableMenu) return [];
|
|
40
|
+
return h(VcAppMenu, {
|
|
41
|
+
version: props.version,
|
|
42
|
+
onItemClick: handlers.onMenuItemClick,
|
|
43
|
+
});
|
|
44
|
+
},
|
|
45
|
+
userDropdown: () => {
|
|
46
|
+
if (props.isEmbedded) return [];
|
|
47
|
+
return h(UserDropdownButton, {
|
|
48
|
+
avatarUrl: props.avatar,
|
|
49
|
+
name: props.name,
|
|
50
|
+
role: props.role,
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
appSwitcher: () => {
|
|
54
|
+
if (props.disableAppSwitcher) return [];
|
|
55
|
+
return (
|
|
56
|
+
slots["app-switcher"]?.() ||
|
|
57
|
+
h(components.VcAppSwitcher, {
|
|
58
|
+
appsList: props.appsList?.value ?? [],
|
|
59
|
+
onClick: handlers.switchApp,
|
|
60
|
+
})
|
|
61
|
+
);
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
provide(APP_SLOTS_KEY, appSlots);
|
|
66
|
+
return appSlots;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Inject app slots in child components
|
|
71
|
+
*/
|
|
72
|
+
export function useAppSlots() {
|
|
73
|
+
const slots = inject(APP_SLOTS_KEY, {});
|
|
74
|
+
return slots;
|
|
75
|
+
}
|