@vc-shell/framework 1.0.231 → 1.0.233
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 +36 -0
- package/core/types/index.ts +14 -1
- package/dist/core/types/index.d.ts +12 -2
- package/dist/core/types/index.d.ts.map +1 -1
- package/dist/framework.js +14875 -14580
- package/dist/index.css +1 -1
- package/dist/locales/en.json +8 -2
- package/dist/shared/components/notifications/components/notification-container/index.d.ts +1 -1
- package/dist/shared/components/user-dropdown-button/user-dropdown-button.vue.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/SchemaRender.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/GalleryField.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/components/fields/StatusField.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/pages/dynamic-blade-form.vue.d.ts.map +1 -1
- package/dist/shared/modules/dynamic/types/index.d.ts +10 -5
- package/dist/shared/modules/dynamic/types/index.d.ts.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/ui/components/atoms/vc-badge/vc-badge.stories.d.ts +187 -17
- package/dist/ui/components/atoms/vc-badge/vc-badge.stories.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts +19 -3
- package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-button/vc-button.stories.d.ts +91 -91
- package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts +1 -1
- package/dist/ui/components/atoms/vc-icon/vc-icon.stories.d.ts +9 -9
- package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts +1 -1
- package/dist/ui/components/atoms/vc-image/index.d.ts +12 -3
- package/dist/ui/components/atoms/vc-image/index.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-image/vc-image.stories.d.ts +12 -3
- package/dist/ui/components/atoms/vc-image/vc-image.stories.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-image/vc-image.vue.d.ts +5 -1
- package/dist/ui/components/atoms/vc-image/vc-image.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-status/vc-status.stories.d.ts +7 -7
- package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts +2 -2
- package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-widget/index.d.ts +6 -0
- package/dist/ui/components/atoms/vc-widget/index.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-widget/vc-widget.stories.d.ts +6 -0
- package/dist/ui/components/atoms/vc-widget/vc-widget.stories.d.ts.map +1 -1
- package/dist/ui/components/atoms/vc-widget/vc-widget.vue.d.ts +1 -0
- package/dist/ui/components/atoms/vc-widget/vc-widget.vue.d.ts.map +1 -1
- package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.stories.d.ts +3 -3
- package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts +1 -1
- package/dist/ui/components/molecules/vc-editor/vc-editor.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-input-currency/vc-input-currency.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts +1 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts +1 -0
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue.d.ts.map +1 -1
- 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-toolbar/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue.d.ts +1 -1
- package/dist/ui/components/organisms/vc-blade/vc-blade.stories.d.ts +2 -0
- package/dist/ui/components/organisms/vc-blade/vc-blade.stories.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts +2 -0
- package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue.d.ts +3 -0
- package/dist/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue.d.ts.map +1 -1
- package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
- package/package.json +4 -4
- package/shared/components/app-switcher/components/vc-app-switcher/vc-app-switcher.vue +1 -1
- package/shared/components/user-dropdown-button/user-dropdown-button.vue +11 -3
- package/shared/modules/dynamic/components/SchemaRender.ts +0 -2
- package/shared/modules/dynamic/components/fields/Card.ts +1 -1
- package/shared/modules/dynamic/components/fields/GalleryField.ts +1 -0
- package/shared/modules/dynamic/components/fields/StatusField.ts +39 -3
- package/shared/modules/dynamic/pages/dynamic-blade-form.vue +17 -22
- package/shared/modules/dynamic/types/index.ts +15 -7
- package/ui/components/atoms/vc-badge/vc-badge.stories.ts +3 -3
- package/ui/components/atoms/vc-badge/vc-badge.vue +58 -10
- package/ui/components/atoms/vc-container/vc-container.vue +2 -2
- package/ui/components/atoms/vc-image/vc-image.vue +3 -1
- package/ui/components/atoms/vc-status/vc-status.vue +5 -2
- package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +1 -1
- package/ui/components/atoms/vc-widget/vc-widget.vue +42 -22
- package/ui/components/molecules/vc-editor/vc-editor.vue +5 -1
- package/ui/components/molecules/vc-input/vc-input.vue +17 -2
- package/ui/components/molecules/vc-input-currency/vc-input-currency.vue +20 -0
- package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +1 -1
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +21 -10
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +3 -0
- package/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +59 -9
- package/ui/components/organisms/vc-app/vc-app.vue +0 -1
- package/ui/components/organisms/vc-blade/vc-blade.vue +89 -2
- package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +72 -56
- package/ui/components/organisms/vc-table/_internal/vc-table-mobile-item/vc-table-mobile-item.vue +27 -7
- package/ui/components/organisms/vc-table/vc-table.stories.ts +1 -1
- package/ui/components/organisms/vc-table/vc-table.vue +138 -62
|
@@ -58,6 +58,8 @@
|
|
|
58
58
|
:disabled="disabled"
|
|
59
59
|
:placeholder="holder"
|
|
60
60
|
@blur="handleBlur"
|
|
61
|
+
@keydown="handleKeyDown"
|
|
62
|
+
@paste="handlePaste"
|
|
61
63
|
/>
|
|
62
64
|
</template>
|
|
63
65
|
<template
|
|
@@ -242,6 +244,8 @@ const { inputRef, setOptions, numberValue, setValue } = useCurrencyInput(
|
|
|
242
244
|
currencyDisplay: props.currencyDisplay as CurrencyDisplay,
|
|
243
245
|
hideGroupingSeparatorOnFocus: false,
|
|
244
246
|
precision: props.precision,
|
|
247
|
+
hideCurrencySymbolOnFocus: false,
|
|
248
|
+
hideNegligibleDecimalDigitsOnFocus: false,
|
|
245
249
|
},
|
|
246
250
|
false,
|
|
247
251
|
);
|
|
@@ -256,6 +260,9 @@ watch(
|
|
|
256
260
|
currency: newVal,
|
|
257
261
|
currencyDisplay: props.currencyDisplay as CurrencyDisplay,
|
|
258
262
|
hideGroupingSeparatorOnFocus: false,
|
|
263
|
+
precision: props.precision,
|
|
264
|
+
hideCurrencySymbolOnFocus: false,
|
|
265
|
+
hideNegligibleDecimalDigitsOnFocus: false,
|
|
259
266
|
});
|
|
260
267
|
},
|
|
261
268
|
);
|
|
@@ -280,4 +287,17 @@ function updateModel(value: string | number | Date | null | undefined) {
|
|
|
280
287
|
function handleBlur(event: Event) {
|
|
281
288
|
emit("blur", event);
|
|
282
289
|
}
|
|
290
|
+
|
|
291
|
+
function handleKeyDown(e: KeyboardEvent) {
|
|
292
|
+
if (e.key === "-" || e.key === "e") {
|
|
293
|
+
e.preventDefault();
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function handlePaste(e: ClipboardEvent) {
|
|
298
|
+
const pasteData = e.clipboardData?.getData("text/plain");
|
|
299
|
+
if (typeof pasteData !== "undefined" && parseInt(pasteData) < 0) {
|
|
300
|
+
e.preventDefault();
|
|
301
|
+
}
|
|
302
|
+
}
|
|
283
303
|
</script>
|
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
class="vc-app-menu-item"
|
|
4
4
|
:class="[
|
|
5
5
|
{
|
|
6
|
-
'vc-app-menu-item_active':
|
|
6
|
+
'vc-app-menu-item_active': isMenuItemActive,
|
|
7
7
|
'vc-app-menu-item_no-hover': !children?.length,
|
|
8
|
-
'vc-app-menu-item_child-opened': isOpened,
|
|
8
|
+
'vc-app-menu-item_child-opened': expand && isOpened,
|
|
9
9
|
},
|
|
10
10
|
]"
|
|
11
11
|
@click="onMenuItemClick"
|
|
@@ -28,7 +28,10 @@
|
|
|
28
28
|
size="m"
|
|
29
29
|
/>
|
|
30
30
|
</div>
|
|
31
|
-
<div
|
|
31
|
+
<div
|
|
32
|
+
v-if="expand"
|
|
33
|
+
class="vc-app-menu-item__title tw-capitalize"
|
|
34
|
+
>
|
|
32
35
|
{{ title }}
|
|
33
36
|
<VcIcon
|
|
34
37
|
v-if="!!children?.length || false"
|
|
@@ -40,7 +43,7 @@
|
|
|
40
43
|
</div>
|
|
41
44
|
<!-- Nested menu items -->
|
|
42
45
|
<div
|
|
43
|
-
v-show="isOpened"
|
|
46
|
+
v-show="isOpened && expand"
|
|
44
47
|
class="vc-app-menu-item__child"
|
|
45
48
|
>
|
|
46
49
|
<template
|
|
@@ -69,7 +72,7 @@
|
|
|
69
72
|
</div>
|
|
70
73
|
</template>
|
|
71
74
|
<script lang="ts" setup>
|
|
72
|
-
import { ref, watch } from "vue";
|
|
75
|
+
import { ref, watch, computed } from "vue";
|
|
73
76
|
import { MenuItem } from "../../../../../../../../../core/types";
|
|
74
77
|
import { VcIcon } from "./../../../../../../../";
|
|
75
78
|
import { useRoute } from "vue-router";
|
|
@@ -80,6 +83,7 @@ export interface Props {
|
|
|
80
83
|
icon: string;
|
|
81
84
|
title?: string;
|
|
82
85
|
url?: string;
|
|
86
|
+
expand?: boolean;
|
|
83
87
|
}
|
|
84
88
|
|
|
85
89
|
export interface Emits {
|
|
@@ -96,6 +100,12 @@ const isOpened = ref(false);
|
|
|
96
100
|
const route = useRoute();
|
|
97
101
|
const params = Object.fromEntries(Object.entries(route.params).filter(([key]) => key !== "pathMatch"));
|
|
98
102
|
|
|
103
|
+
const isMenuItemActive = computed(
|
|
104
|
+
() =>
|
|
105
|
+
(isActive(props.url ?? "") && !props.children?.length) ||
|
|
106
|
+
(!props.expand && isOpened.value && props.children?.some((x) => isActive(x.url ?? ""))),
|
|
107
|
+
);
|
|
108
|
+
|
|
99
109
|
watch(
|
|
100
110
|
() => route.path,
|
|
101
111
|
() => {
|
|
@@ -128,7 +138,9 @@ const isActive = (url: string) => {
|
|
|
128
138
|
}
|
|
129
139
|
|
|
130
140
|
return active;
|
|
131
|
-
} else
|
|
141
|
+
} else {
|
|
142
|
+
return false;
|
|
143
|
+
}
|
|
132
144
|
};
|
|
133
145
|
</script>
|
|
134
146
|
|
|
@@ -182,10 +194,9 @@ const isActive = (url: string) => {
|
|
|
182
194
|
}
|
|
183
195
|
|
|
184
196
|
&__icon {
|
|
185
|
-
@apply tw-
|
|
186
|
-
tw-text-[color:var(--app-menu-item-icon-color)]
|
|
197
|
+
@apply tw-text-[color:var(--app-menu-item-icon-color)]
|
|
187
198
|
tw-overflow-hidden tw-flex
|
|
188
|
-
tw-justify-center tw-shrink-0
|
|
199
|
+
tw-justify-center tw-shrink-0 tw-transition-[color] tw-duration-200 tw-pr-[7px];
|
|
189
200
|
}
|
|
190
201
|
|
|
191
202
|
&_active &__icon {
|
|
@@ -196,7 +207,7 @@ const isActive = (url: string) => {
|
|
|
196
207
|
@apply tw-truncate
|
|
197
208
|
tw-text-lg
|
|
198
209
|
tw-font-medium
|
|
199
|
-
tw-
|
|
210
|
+
tw-pr-2
|
|
200
211
|
tw-text-[color:var(--app-menu-item-title-color)]
|
|
201
212
|
[transition:color_0.2s_ease]
|
|
202
213
|
tw-opacity-100 tw-w-full tw-flex tw-justify-between tw-items-center;
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
:icon="icon ?? ''"
|
|
12
12
|
:title="title ?? ''"
|
|
13
13
|
:url="url"
|
|
14
|
+
:expand="expand"
|
|
14
15
|
@on-click="$emit('click')"
|
|
15
16
|
/>
|
|
16
17
|
</router-link>
|
|
@@ -22,6 +23,7 @@
|
|
|
22
23
|
:sticky="sticky"
|
|
23
24
|
:icon="icon ?? ''"
|
|
24
25
|
:title="title ?? ''"
|
|
26
|
+
:expand="expand"
|
|
25
27
|
@on-click="$emit('click', $event)"
|
|
26
28
|
/>
|
|
27
29
|
</template>
|
|
@@ -39,6 +41,7 @@ export interface Props {
|
|
|
39
41
|
icon?: string;
|
|
40
42
|
title?: string;
|
|
41
43
|
children?: MenuItem[];
|
|
44
|
+
expand?: boolean;
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
export interface Emits {
|
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
v-if="isMenuVisible"
|
|
4
|
-
class="tw-relative tw-w-[var(--app-menu-width)]
|
|
4
|
+
class="tw-relative tw-w-[var(--app-menu-width)] [transition:width_300ms_cubic-bezier(0.2,0,0,1)_0s] tw-pt-[22px]"
|
|
5
5
|
:class="{
|
|
6
6
|
'vc-app-menu_mobile tw-hidden !tw-fixed !tw-left-0 !tw-top-0 !tw-w-full !tw-bottom-0 !tw-z-[9999]':
|
|
7
7
|
$isMobile.value,
|
|
8
8
|
'!tw-block': isMobileVisible,
|
|
9
|
+
'!tw-w-[63px]': $isDesktop.value && !isExpanded,
|
|
9
10
|
}"
|
|
11
|
+
@mouseenter="!isExpanded && expandOverHandler(true)"
|
|
12
|
+
@mouseover="!isExpanded && expandOverHandler(true)"
|
|
13
|
+
@mouseleave="expandOverHandler(false)"
|
|
10
14
|
>
|
|
11
15
|
<!-- Show backdrop overlay on mobile devices -->
|
|
12
16
|
<div
|
|
@@ -14,17 +18,40 @@
|
|
|
14
18
|
class="tw-absolute tw-left-0 tw-top-0 tw-right-0 tw-bottom-0 tw-z-[9998] tw-bg-[#808c99] tw-opacity-60"
|
|
15
19
|
@click="isMobileVisible = false"
|
|
16
20
|
></div>
|
|
17
|
-
<div
|
|
21
|
+
<div
|
|
22
|
+
class="!tw-absolute vc-app-menu__inner tw-flex tw-flex-col tw-h-full [transition:width_300ms_cubic-bezier(0.2,0,0,1)_0s] tw-z-[9999] tw-left-0 tw-top-0 tw-bottom-0 tw-bg-[color:var(--app-background)] tw-pt-[22px] tw-shadow-[inset_0px_2px_5px_0px_#3654751A]"
|
|
23
|
+
:class="{
|
|
24
|
+
'!tw-w-[63px] !tw-shadow-[inset_4px_2px_5px_0px_#3654751A]': $isDesktop.value && !isExpanded && !isExpandedOver,
|
|
25
|
+
'tw-w-[var(--app-menu-width)]': $isDesktop.value && (isExpanded || isExpandedOver),
|
|
26
|
+
'tw-shadow-none': $isDesktop.value && isExpanded,
|
|
27
|
+
}"
|
|
28
|
+
>
|
|
18
29
|
<!-- Show menu close handler on mobile devices -->
|
|
19
30
|
<div
|
|
20
31
|
v-if="$isMobile.value"
|
|
21
32
|
class="tw-text-[#319ed4] tw-flex tw-justify-end tw-items-center tw-p-4 tw-cursor-pointer"
|
|
22
33
|
>
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
<button @click="isMobileVisible = false">
|
|
35
|
+
<VcIcon
|
|
36
|
+
icon="fas fa-times"
|
|
37
|
+
size="xl"
|
|
38
|
+
></VcIcon>
|
|
39
|
+
</button>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<div
|
|
43
|
+
v-if="$isDesktop.value"
|
|
44
|
+
class="tw-pl-[21px] tw-pb-2"
|
|
45
|
+
>
|
|
46
|
+
<button
|
|
47
|
+
class="tw-p-[10px] tw-h-[var(--app-menu-item-height)] tw-rounded tw-text-[color:var(--app-menu-burger-color)] hover:tw-bg-[color:var(--app-menu-burger-background-color)]"
|
|
48
|
+
@click="toggleMenu"
|
|
49
|
+
>
|
|
50
|
+
<VcIcon
|
|
51
|
+
icon="fas fa-bars"
|
|
52
|
+
size="xl"
|
|
53
|
+
></VcIcon>
|
|
54
|
+
</button>
|
|
28
55
|
</div>
|
|
29
56
|
|
|
30
57
|
<!-- Show scrollable area with menu items -->
|
|
@@ -32,7 +59,13 @@
|
|
|
32
59
|
:no-padding="true"
|
|
33
60
|
class="tw-grow tw-basis-0"
|
|
34
61
|
>
|
|
35
|
-
<div
|
|
62
|
+
<div
|
|
63
|
+
class="tw-gap-[5px] tw-flex tw-flex-col tw-h-full"
|
|
64
|
+
:class="{
|
|
65
|
+
'tw-px-[21px]': ($isDesktop.value && (isExpanded || isExpandedOver)) || $isMobile.value,
|
|
66
|
+
'tw-pl-[21px] tw-pr-[2px]': $isDesktop.value && !isExpanded && !isExpandedOver,
|
|
67
|
+
}"
|
|
68
|
+
>
|
|
36
69
|
<slot
|
|
37
70
|
v-if="!$isDesktop.value"
|
|
38
71
|
name="mobile"
|
|
@@ -48,6 +81,7 @@
|
|
|
48
81
|
:icon="item.icon"
|
|
49
82
|
:title="item.title as string"
|
|
50
83
|
:children="item.children"
|
|
84
|
+
:expand="$isDesktop.value ? isExpanded || isExpandedOver : true"
|
|
51
85
|
@click="
|
|
52
86
|
(event) => {
|
|
53
87
|
$emit('item:click', event ? event : item);
|
|
@@ -58,7 +92,7 @@
|
|
|
58
92
|
</div>
|
|
59
93
|
</VcContainer>
|
|
60
94
|
<div
|
|
61
|
-
class="tw-text-[color:var(--app-menu-version-color)] tw-text-xs tw-mt-auto tw-self-
|
|
95
|
+
class="tw-text-[color:var(--app-menu-version-color)] tw-text-xs tw-mt-auto tw-self-start tw-py-1 tw-pl-4"
|
|
62
96
|
@click="$emit('version:click')"
|
|
63
97
|
>
|
|
64
98
|
{{ version }}
|
|
@@ -73,6 +107,7 @@ import VcAppMenuItem from "./_internal/vc-app-menu-item/vc-app-menu-item.vue";
|
|
|
73
107
|
import { VcContainer, VcIcon } from "./../../../../";
|
|
74
108
|
import { useMenuService } from "../../../../../../core/composables";
|
|
75
109
|
import { MenuItem } from "../../../../../../core/types";
|
|
110
|
+
import { useLocalStorage } from "@vueuse/core";
|
|
76
111
|
|
|
77
112
|
export interface Props {
|
|
78
113
|
version: string;
|
|
@@ -91,6 +126,8 @@ withDefaults(defineProps<Props>(), {
|
|
|
91
126
|
|
|
92
127
|
defineEmits<Emits>();
|
|
93
128
|
const { menuItems } = useMenuService();
|
|
129
|
+
const isExpanded = useLocalStorage("VC_APP_MENU_EXPANDED", true);
|
|
130
|
+
const isExpandedOver = ref(false);
|
|
94
131
|
|
|
95
132
|
const isMobileVisible = ref(false);
|
|
96
133
|
|
|
@@ -98,6 +135,16 @@ const isMenuVisible = computed(() => {
|
|
|
98
135
|
return !!menuItems.value.length;
|
|
99
136
|
});
|
|
100
137
|
|
|
138
|
+
function toggleMenu() {
|
|
139
|
+
isExpanded.value = !isExpanded.value;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function expandOverHandler(state: boolean) {
|
|
143
|
+
if (isExpandedOver.value !== state) {
|
|
144
|
+
isExpandedOver.value = state;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
101
148
|
defineExpose({
|
|
102
149
|
isMobileVisible,
|
|
103
150
|
});
|
|
@@ -108,6 +155,9 @@ defineExpose({
|
|
|
108
155
|
--app-menu-width: 230px;
|
|
109
156
|
--app-menu-background-color: #ffffff;
|
|
110
157
|
--app-menu-version-color: #838d9a;
|
|
158
|
+
|
|
159
|
+
--app-menu-burger-background-color: rgba(255, 255, 255, 0.5);
|
|
160
|
+
--app-menu-burger-color: #319ed4;
|
|
111
161
|
}
|
|
112
162
|
|
|
113
163
|
.vc-app-menu {
|
|
@@ -70,12 +70,64 @@
|
|
|
70
70
|
class="tw-shrink-0"
|
|
71
71
|
:items="toolbarItems"
|
|
72
72
|
></VcBladeToolbar>
|
|
73
|
-
|
|
73
|
+
|
|
74
|
+
<div class="tw-flex-1 tw-overflow-auto">
|
|
75
|
+
<div
|
|
76
|
+
class="tw-flex tw-flex-row tw-h-full"
|
|
77
|
+
:class="{
|
|
78
|
+
'tw-flex-col': $isMobile.value,
|
|
79
|
+
}"
|
|
80
|
+
>
|
|
81
|
+
<slot></slot>
|
|
82
|
+
|
|
83
|
+
<div
|
|
84
|
+
v-show="$slots['widgets'] && !isWidgetContainerEmpty"
|
|
85
|
+
ref="widgetsRef"
|
|
86
|
+
class="vc-blade__widgets tw-flex"
|
|
87
|
+
:class="{
|
|
88
|
+
'tw-w-[var(--blade-widgets-width)] tw-flex-col': $isDesktop.value && !isExpanded,
|
|
89
|
+
'tw-w-[var(--blade-widgets-width-expanded)] tw-flex-col': $isDesktop.value && isExpanded,
|
|
90
|
+
'tw-w-auto tw-border-t tw-border-solid tw-border-t-[#eaedf3] tw-flex-row': $isMobile.value,
|
|
91
|
+
}"
|
|
92
|
+
>
|
|
93
|
+
<div
|
|
94
|
+
ref="widgetsContainerRef"
|
|
95
|
+
class="vc-blade__widget-container tw-flex tw-overflow-auto"
|
|
96
|
+
:class="{
|
|
97
|
+
'tw-flex-col': $isDesktop.value,
|
|
98
|
+
'tw-flex-row': $isMobile.value,
|
|
99
|
+
}"
|
|
100
|
+
>
|
|
101
|
+
<slot
|
|
102
|
+
name="widgets"
|
|
103
|
+
:is-expanded="isExpanded"
|
|
104
|
+
></slot>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div
|
|
108
|
+
class="tw-flex tw-flex-auto"
|
|
109
|
+
:class="{
|
|
110
|
+
'tw-flex-col tw-justify-end': $isDesktop.value,
|
|
111
|
+
'tw-w-12 tw-max-w-12 tw-bg-white tw-items-center tw-justify-center tw-px-4 tw-ml-auto': $isMobile.value,
|
|
112
|
+
}"
|
|
113
|
+
>
|
|
114
|
+
<VcIcon
|
|
115
|
+
class="tw-self-center tw-justify-self-center tw-text-[#a1c0d4] tw-cursor-pointer hover:tw-text-[#7ea8c4]"
|
|
116
|
+
:class="{
|
|
117
|
+
'tw-mb-4': $isDesktop.value,
|
|
118
|
+
}"
|
|
119
|
+
:icon="`fas fa-chevron-${$isDesktop.value ? (isExpanded ? 'right' : 'left') : isExpanded ? 'up' : 'down'}`"
|
|
120
|
+
@click="toggleWidgets"
|
|
121
|
+
></VcIcon>
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
74
126
|
</div>
|
|
75
127
|
</template>
|
|
76
128
|
|
|
77
129
|
<script lang="ts" setup>
|
|
78
|
-
import { computed, Ref, reactive, useAttrs, toRefs, toValue } from "vue";
|
|
130
|
+
import { computed, Ref, reactive, useAttrs, toRefs, toValue, ref, onMounted, onUpdated } from "vue";
|
|
79
131
|
import { IBladeToolbar } from "../../../../core/types";
|
|
80
132
|
import { usePopup } from "./../../../../shared";
|
|
81
133
|
import { useI18n } from "vue-i18n";
|
|
@@ -83,6 +135,7 @@ import VcBladeHeader from "./_internal/vc-blade-header/vc-blade-header.vue";
|
|
|
83
135
|
import VcBladeToolbar from "./_internal/vc-blade-toolbar/vc-blade-toolbar.vue";
|
|
84
136
|
import { VcButton, VcIcon } from "./../../";
|
|
85
137
|
import vcPopupError from "../../../../shared/components/common/popup/vc-popup-error.vue";
|
|
138
|
+
import { useLocalStorage } from "@vueuse/core";
|
|
86
139
|
|
|
87
140
|
export interface Props {
|
|
88
141
|
icon?: string;
|
|
@@ -117,12 +170,39 @@ withDefaults(defineProps<Props>(), {
|
|
|
117
170
|
defineSlots<{
|
|
118
171
|
actions: void;
|
|
119
172
|
default: void;
|
|
173
|
+
widgets: void;
|
|
120
174
|
}>();
|
|
121
175
|
|
|
122
176
|
defineEmits<Emits>();
|
|
123
177
|
const attrs = useAttrs();
|
|
124
178
|
const { maximized, error }: { maximized?: Ref<boolean>; error?: Ref<string> } = toRefs(reactive(attrs));
|
|
125
179
|
const { t } = useI18n({ useScope: "global" });
|
|
180
|
+
const widgetsRef = ref();
|
|
181
|
+
const widgetsContainerRef = ref();
|
|
182
|
+
|
|
183
|
+
const isExpanded = useLocalStorage("VC_BLADE_WIDGETS_IS_EXPANDED", true);
|
|
184
|
+
|
|
185
|
+
const toggleWidgets = () => {
|
|
186
|
+
isExpanded.value = !isExpanded.value;
|
|
187
|
+
};
|
|
188
|
+
const isWidgetContainerEmpty = ref(false);
|
|
189
|
+
|
|
190
|
+
const checkEmpty = (el: HTMLElement) => {
|
|
191
|
+
const isEmpty = !el.innerText.trim() && Array.from(el.children).every((node) => node.nodeType === Node.COMMENT_NODE);
|
|
192
|
+
isWidgetContainerEmpty.value = isEmpty;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
onMounted(() => {
|
|
196
|
+
if (widgetsRef.value) {
|
|
197
|
+
checkEmpty(widgetsContainerRef.value);
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
onUpdated(() => {
|
|
202
|
+
if (widgetsRef.value) {
|
|
203
|
+
checkEmpty(widgetsContainerRef.value);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
126
206
|
|
|
127
207
|
const { open } = usePopup({
|
|
128
208
|
component: vcPopupError,
|
|
@@ -142,9 +222,16 @@ const { open } = usePopup({
|
|
|
142
222
|
--blade-color-error: #f14e4e;
|
|
143
223
|
--blade-color-unsaved-changes: #82a6bd;
|
|
144
224
|
--blade-color-unsaved-changes: #82a6bd;
|
|
225
|
+
|
|
226
|
+
--blade-widgets-width: 36px;
|
|
227
|
+
--blade-widgets-width-expanded: 80px;
|
|
145
228
|
}
|
|
146
229
|
|
|
147
230
|
.vc-app_mobile .vc-blade {
|
|
148
231
|
@apply tw-m-0 tw-rounded-none;
|
|
149
232
|
}
|
|
233
|
+
|
|
234
|
+
.vc-app_mobile .vc-blade__widgets {
|
|
235
|
+
@apply tw-flex tw-flex-row;
|
|
236
|
+
}
|
|
150
237
|
</style>
|
|
@@ -23,29 +23,34 @@
|
|
|
23
23
|
:model-value="value"
|
|
24
24
|
:rules="cell.rules"
|
|
25
25
|
>
|
|
26
|
-
<
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
26
|
+
<VcTooltip placement="bottom">
|
|
27
|
+
<template #default>
|
|
28
|
+
<VcInputCurrency
|
|
29
|
+
:model-value="value"
|
|
30
|
+
:options="[]"
|
|
31
|
+
:option="(item[cell.currencyField || 'currency'] as string) || 'USD'"
|
|
32
|
+
currency-display="symbol"
|
|
33
|
+
class="tw-w-full"
|
|
34
|
+
:error="errors.length > 0"
|
|
35
|
+
:error-message="$isMobile.value ? errorMessage : undefined"
|
|
36
|
+
@update:model-value="$emit('update', { field: cell.id, value: $event })"
|
|
37
|
+
@blur="onBlur({ row: index, field: cell.id, errors })"
|
|
38
|
+
>
|
|
39
|
+
<template
|
|
40
|
+
v-if="$isDesktop.value && errors.length > 0"
|
|
41
|
+
#append-inner
|
|
42
|
+
>
|
|
43
|
+
<VcIcon icon="fas fa-exclamation-circle tw-text-[color:var(--error-color)]"></VcIcon>
|
|
44
|
+
</template>
|
|
45
|
+
</VcInputCurrency>
|
|
46
|
+
</template>
|
|
37
47
|
<template
|
|
38
|
-
v-if="
|
|
39
|
-
#
|
|
48
|
+
v-if="errors.length > 0"
|
|
49
|
+
#tooltip
|
|
40
50
|
>
|
|
41
|
-
<
|
|
42
|
-
<VcIcon icon="fas fa-exclamation-circle tw-text-[color:var(--error-color)]"></VcIcon>
|
|
43
|
-
<template #tooltip>
|
|
44
|
-
<div class="tw-text-[color:var(--error-color)]">{{ errorMessage }}</div>
|
|
45
|
-
</template>
|
|
46
|
-
</VcTooltip>
|
|
51
|
+
<div class="tw-text-[color:var(--error-color)]">{{ errorMessage }}</div>
|
|
47
52
|
</template>
|
|
48
|
-
</
|
|
53
|
+
</VcTooltip>
|
|
49
54
|
</Field>
|
|
50
55
|
</template>
|
|
51
56
|
<template v-else>
|
|
@@ -124,6 +129,7 @@
|
|
|
124
129
|
size="s"
|
|
125
130
|
aspect="1x1"
|
|
126
131
|
:src="value as string"
|
|
132
|
+
:empty-icon="('emptyIcon' in cell && cell.emptyIcon) || undefined"
|
|
127
133
|
background="contain"
|
|
128
134
|
/>
|
|
129
135
|
</template>
|
|
@@ -156,27 +162,32 @@
|
|
|
156
162
|
:model-value="value"
|
|
157
163
|
:rules="cell.rules"
|
|
158
164
|
>
|
|
159
|
-
<
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
165
|
+
<VcTooltip placement="bottom">
|
|
166
|
+
<template #default>
|
|
167
|
+
<VcInput
|
|
168
|
+
:model-value="value"
|
|
169
|
+
class="tw-w-full"
|
|
170
|
+
type="number"
|
|
171
|
+
:error="errors.length > 0"
|
|
172
|
+
:error-message="$isMobile.value ? errorMessage : undefined"
|
|
173
|
+
@update:model-value="$emit('update', { field: cell.id, value: $event })"
|
|
174
|
+
@blur="onBlur({ row: index, field: cell.id, errors })"
|
|
175
|
+
>
|
|
176
|
+
<template
|
|
177
|
+
v-if="$isDesktop.value && errors.length > 0"
|
|
178
|
+
#append-inner
|
|
179
|
+
>
|
|
180
|
+
<VcIcon icon="fas fa-exclamation-circle tw-text-[color:var(--error-color)]"></VcIcon>
|
|
181
|
+
</template>
|
|
182
|
+
</VcInput>
|
|
183
|
+
</template>
|
|
168
184
|
<template
|
|
169
|
-
v-if="
|
|
170
|
-
#
|
|
185
|
+
v-if="errors.length > 0"
|
|
186
|
+
#tooltip
|
|
171
187
|
>
|
|
172
|
-
<
|
|
173
|
-
<VcIcon icon="fas fa-exclamation-circle tw-text-[color:var(--error-color)]"></VcIcon>
|
|
174
|
-
<template #tooltip>
|
|
175
|
-
<div class="tw-text-[color:var(--error-color)]">{{ errorMessage }}</div>
|
|
176
|
-
</template>
|
|
177
|
-
</VcTooltip>
|
|
188
|
+
<div class="tw-text-[color:var(--error-color)]">{{ errorMessage }}</div>
|
|
178
189
|
</template>
|
|
179
|
-
</
|
|
190
|
+
</VcTooltip>
|
|
180
191
|
</Field>
|
|
181
192
|
</template>
|
|
182
193
|
<template v-else>
|
|
@@ -220,26 +231,30 @@
|
|
|
220
231
|
:model-value="value"
|
|
221
232
|
:rules="cell.rules"
|
|
222
233
|
>
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
234
|
+
<VcTooltip placement="bottom">
|
|
235
|
+
<template #default>
|
|
236
|
+
<VcInput
|
|
237
|
+
:model-value="value"
|
|
238
|
+
class="tw-w-full"
|
|
239
|
+
:error="errors.length > 0"
|
|
240
|
+
:error-message="$isMobile.value ? errorMessage : undefined"
|
|
241
|
+
@update:model-value="$emit('update', { field: cell.id, value: $event })"
|
|
242
|
+
@blur="onBlur({ row: index, field: cell.id, errors })"
|
|
243
|
+
>
|
|
244
|
+
<template
|
|
245
|
+
v-if="$isDesktop.value && errors.length > 0"
|
|
246
|
+
#append-inner
|
|
247
|
+
>
|
|
248
|
+
<VcIcon icon="fas fa-exclamation-circle tw-text-[color:var(--error-color)]"></VcIcon> </template
|
|
249
|
+
></VcInput>
|
|
250
|
+
</template>
|
|
231
251
|
<template
|
|
232
|
-
v-if="
|
|
233
|
-
#
|
|
252
|
+
v-if="errors.length > 0"
|
|
253
|
+
#tooltip
|
|
234
254
|
>
|
|
235
|
-
<
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
<div class="tw-text-[color:var(--error-color)]">{{ errorMessage }}</div>
|
|
239
|
-
</template>
|
|
240
|
-
</VcTooltip>
|
|
241
|
-
</template></VcInput
|
|
242
|
-
>
|
|
255
|
+
<div class="tw-text-[color:var(--error-color)]">{{ errorMessage }}</div>
|
|
256
|
+
</template>
|
|
257
|
+
</VcTooltip>
|
|
243
258
|
</Field>
|
|
244
259
|
</template>
|
|
245
260
|
<template v-else>
|
|
@@ -259,6 +274,7 @@ import htmlTruncate from "truncate-html";
|
|
|
259
274
|
import * as DOMPurify from "dompurify";
|
|
260
275
|
import VcInputCurrency from "../../../../molecules/vc-input-currency/vc-input-currency.vue";
|
|
261
276
|
import VcInput from "../../../../molecules/vc-input/vc-input.vue";
|
|
277
|
+
import VcTooltip from "../../../../atoms/vc-tooltip/vc-tooltip.vue";
|
|
262
278
|
import { Field } from "vee-validate";
|
|
263
279
|
|
|
264
280
|
export interface Props {
|