@antify/ui-module 1.3.0 → 1.4.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/dist/module.json +1 -1
- package/dist/runtime/components/AntTooltip.vue +69 -63
- package/dist/runtime/components/__stories/AntTooltip.stories.d.ts +5 -0
- package/dist/runtime/components/__stories/AntTooltip.stories.mjs +33 -11
- package/dist/runtime/components/buttons/AntActionButton.vue +35 -13
- package/dist/runtime/components/buttons/AntButton.vue +3 -3
- package/dist/runtime/components/buttons/AntCreateButton.vue +20 -8
- package/dist/runtime/components/buttons/AntDeleteButton.vue +20 -8
- package/dist/runtime/components/buttons/AntSaveAndNewButton.vue +21 -8
- package/dist/runtime/components/buttons/AntSaveButton.vue +20 -8
- package/dist/runtime/components/buttons/__stories/AntActionButton.stories.d.ts +1 -0
- package/dist/runtime/components/buttons/__stories/AntActionButton.stories.mjs +22 -0
- package/dist/runtime/components/buttons/__stories/AntCreateButton.stories.d.ts +1 -0
- package/dist/runtime/components/buttons/__stories/AntCreateButton.stories.mjs +9 -0
- package/dist/runtime/components/buttons/__stories/AntDeleteButton.stories.d.ts +1 -0
- package/dist/runtime/components/buttons/__stories/AntDeleteButton.stories.mjs +9 -0
- package/dist/runtime/components/buttons/__stories/AntSaveAndNewButton.stories.d.ts +1 -0
- package/dist/runtime/components/buttons/__stories/AntSaveAndNewButton.stories.mjs +9 -0
- package/dist/runtime/components/buttons/__stories/AntSaveButton.stories.d.ts +1 -0
- package/dist/runtime/components/buttons/__stories/AntSaveButton.stories.mjs +9 -0
- package/dist/runtime/components/crud/AntCrudDetailActions.vue +10 -3
- package/dist/runtime/components/crud/AntCrudDetailNav.vue +21 -15
- package/dist/runtime/components/crud/AntCrudTableFilter.vue +35 -33
- package/dist/runtime/utils.d.ts +6 -0
- package/dist/runtime/utils.mjs +21 -0
- package/package.json +1 -1
- package/src/runtime/components/AntTooltip.vue +69 -63
- package/src/runtime/components/buttons/AntActionButton.vue +35 -13
- package/src/runtime/components/buttons/AntButton.vue +3 -3
- package/src/runtime/components/buttons/AntCreateButton.vue +20 -8
- package/src/runtime/components/buttons/AntDeleteButton.vue +20 -8
- package/src/runtime/components/buttons/AntSaveAndNewButton.vue +21 -8
- package/src/runtime/components/buttons/AntSaveButton.vue +20 -8
- package/src/runtime/components/crud/AntCrudDetailActions.vue +10 -3
- package/src/runtime/components/crud/AntCrudDetailNav.vue +21 -15
- package/src/runtime/components/crud/AntCrudTableFilter.vue +35 -33
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import AntSaveButton from "../AntSaveButton.vue";
|
|
2
2
|
import { Size } from "../../../enums/Size.enum.mjs";
|
|
3
3
|
import { Grouped as _Grouped } from "../../../enums/Grouped.enum.mjs";
|
|
4
|
+
import { Position } from "../../../enums/index.mjs";
|
|
4
5
|
const meta = {
|
|
5
6
|
title: "Components/Buttons/Save Button",
|
|
6
7
|
component: AntSaveButton,
|
|
@@ -55,3 +56,11 @@ export const Expanded = {
|
|
|
55
56
|
expanded: true
|
|
56
57
|
}
|
|
57
58
|
};
|
|
59
|
+
export const InvalidPermission = {
|
|
60
|
+
render: Docs.render,
|
|
61
|
+
args: {
|
|
62
|
+
...Docs.args,
|
|
63
|
+
canSave: false,
|
|
64
|
+
invalidPermissionTooltipPosition: Position.right
|
|
65
|
+
}
|
|
66
|
+
};
|
|
@@ -8,14 +8,19 @@ defineEmits(['back', 'save', 'save-and-new']);
|
|
|
8
8
|
withDefaults(defineProps<{
|
|
9
9
|
disabled?: boolean
|
|
10
10
|
skeleton?: boolean
|
|
11
|
+
canSave?: boolean
|
|
11
12
|
}>(), {
|
|
12
13
|
disabled: false,
|
|
13
14
|
skeleton: false,
|
|
15
|
+
canSave: true
|
|
14
16
|
});
|
|
15
17
|
</script>
|
|
16
18
|
|
|
17
19
|
<template>
|
|
18
|
-
<div
|
|
20
|
+
<div
|
|
21
|
+
class="flex justify-between p-2.5 gap-2.5 bg-neutral-50"
|
|
22
|
+
data-e2e="crud-detail-actions"
|
|
23
|
+
>
|
|
19
24
|
<div class="flex gap-2.5">
|
|
20
25
|
<slot name="buttons-left">
|
|
21
26
|
<AntButton
|
|
@@ -31,21 +36,23 @@ withDefaults(defineProps<{
|
|
|
31
36
|
</div>
|
|
32
37
|
|
|
33
38
|
<div class="flex gap-2.5">
|
|
34
|
-
<slot name="before-buttons-right"/>
|
|
39
|
+
<slot name="before-buttons-right" />
|
|
35
40
|
<slot name="buttons-right">
|
|
36
41
|
<AntSaveAndNewButton
|
|
37
42
|
:skeleton="skeleton"
|
|
38
43
|
:disabled="disabled"
|
|
44
|
+
:can-save="canSave"
|
|
39
45
|
@click="$emit('save-and-new')"
|
|
40
46
|
/>
|
|
41
47
|
|
|
42
48
|
<AntSaveButton
|
|
43
49
|
:skeleton="skeleton"
|
|
44
50
|
:disabled="disabled"
|
|
51
|
+
:can-save="canSave"
|
|
45
52
|
@click="$emit('save')"
|
|
46
53
|
/>
|
|
47
54
|
</slot>
|
|
48
|
-
<slot name="after-buttons-right"/>
|
|
55
|
+
<slot name="after-buttons-right" />
|
|
49
56
|
</div>
|
|
50
57
|
</div>
|
|
51
58
|
</template>
|
|
@@ -5,40 +5,46 @@ import AntTabs from '../tabs/AntTabs.vue';
|
|
|
5
5
|
import AntDeleteButton from '../buttons/AntDeleteButton.vue';
|
|
6
6
|
import AntDeleteDialog from '../dialogs/AntDeleteDialog.vue';
|
|
7
7
|
import {ref} from 'vue';
|
|
8
|
+
import {Position} from '../../enums';
|
|
8
9
|
|
|
9
10
|
defineEmits(['delete']);
|
|
10
11
|
withDefaults(defineProps<{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
tabItems?: TabItem[]
|
|
13
|
+
deleteButtonDisabled?: boolean
|
|
14
|
+
getEntityName: () => string
|
|
15
|
+
canDelete?: boolean
|
|
14
16
|
}>(), {
|
|
15
|
-
|
|
17
|
+
deleteButtonDisabled: false,
|
|
18
|
+
canDelete: true
|
|
16
19
|
});
|
|
17
20
|
|
|
18
21
|
const dialogOpen = ref(false);
|
|
19
22
|
</script>
|
|
20
23
|
|
|
21
24
|
<template>
|
|
22
|
-
<div
|
|
25
|
+
<div
|
|
26
|
+
class="flex justify-between items-stretch gap-2.5 bg-neutral-50"
|
|
27
|
+
data-e2e="crud-detail-nav"
|
|
28
|
+
>
|
|
23
29
|
<slot name="tabs">
|
|
24
30
|
<AntTabs
|
|
25
|
-
:
|
|
31
|
+
:tab-items="tabItems"
|
|
26
32
|
/>
|
|
27
33
|
</slot>
|
|
28
34
|
|
|
29
35
|
<div class="flex gap-2.5 pr-2.5 py-2.5">
|
|
30
36
|
<slot name="buttons">
|
|
31
|
-
<slot name="before-delete-button"/>
|
|
37
|
+
<slot name="before-delete-button" />
|
|
32
38
|
|
|
33
|
-
<
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
<AntDeleteButton
|
|
40
|
+
:disabled="deleteButtonDisabled || !canDelete"
|
|
41
|
+
filled
|
|
42
|
+
:can-delete="canDelete"
|
|
43
|
+
:invalid-permission-tooltip-position="Position.left"
|
|
44
|
+
@click="() => dialogOpen = true"
|
|
45
|
+
/>
|
|
40
46
|
|
|
41
|
-
<slot name="after-delete-button"/>
|
|
47
|
+
<slot name="after-delete-button" />
|
|
42
48
|
</slot>
|
|
43
49
|
</div>
|
|
44
50
|
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
// TODO:: This component works only with vue-router. Make it work in storybook.
|
|
3
|
-
// TODO:: add skeleton
|
|
4
3
|
import AntSearch from '../form/AntSearch.vue';
|
|
5
4
|
import AntCreateButton from '../buttons/AntCreateButton.vue';
|
|
6
5
|
import AntDropdown from '../AntDropdown.vue';
|
|
7
|
-
import AntIcon from '../AntIcon.vue';
|
|
8
6
|
import {computed, ref, watch} from 'vue';
|
|
9
7
|
import AntButton from '../buttons/AntButton.vue';
|
|
10
8
|
import {faFilter, faMultiply} from '@fortawesome/free-solid-svg-icons';
|
|
@@ -12,17 +10,19 @@ import {ColorType, Grouped, Position} from '../../enums';
|
|
|
12
10
|
import {useRoute, useRouter} from 'vue-router';
|
|
13
11
|
|
|
14
12
|
const props = withDefaults(defineProps<{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
fullWidth?: boolean,
|
|
14
|
+
showFilter?: boolean,
|
|
15
|
+
searchQuery?: string,
|
|
16
|
+
hasFilter?: boolean,
|
|
17
|
+
canCreate?: boolean,
|
|
18
|
+
skeleton?: boolean,
|
|
20
19
|
}>(), {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
fullWidth: true,
|
|
21
|
+
showFilter: true,
|
|
22
|
+
searchQuery: 'search',
|
|
23
|
+
hasFilter: false,
|
|
24
|
+
canCreate: true,
|
|
25
|
+
skeleton: false,
|
|
26
26
|
});
|
|
27
27
|
const emit = defineEmits(['search', 'create', 'removeFilter']);
|
|
28
28
|
const router = useRouter();
|
|
@@ -31,32 +31,32 @@ const route = useRoute();
|
|
|
31
31
|
const showDropdown = ref(false);
|
|
32
32
|
const _fullWidth = ref(props.fullWidth)
|
|
33
33
|
const search = computed({
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
34
|
+
get: () => route.query[props.searchQuery] as string || '',
|
|
35
|
+
set: (value) => {
|
|
36
|
+
const query = {
|
|
37
|
+
...route.query,
|
|
38
|
+
[props.searchQuery]: value
|
|
39
|
+
}
|
|
40
40
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
if (!value) {
|
|
42
|
+
delete query[props.searchQuery];
|
|
43
|
+
}
|
|
44
44
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
45
|
+
(async () => {
|
|
46
|
+
await router.replace({
|
|
47
|
+
...route,
|
|
48
|
+
query
|
|
49
|
+
})
|
|
50
50
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
emit('search', value)
|
|
52
|
+
})()
|
|
53
|
+
}
|
|
54
54
|
})
|
|
55
55
|
|
|
56
56
|
watch(() => props.fullWidth, (val) => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
57
|
+
setTimeout(() => {
|
|
58
|
+
_fullWidth.value = val
|
|
59
|
+
}, val ? 250 : 300)
|
|
60
60
|
})
|
|
61
61
|
</script>
|
|
62
62
|
|
|
@@ -102,7 +102,7 @@ watch(() => props.fullWidth, (val) => {
|
|
|
102
102
|
</div>
|
|
103
103
|
|
|
104
104
|
<template #content>
|
|
105
|
-
<slot name="dropdownContent"/>
|
|
105
|
+
<slot name="dropdownContent" />
|
|
106
106
|
</template>
|
|
107
107
|
</AntDropdown>
|
|
108
108
|
</div>
|
|
@@ -112,6 +112,8 @@ watch(() => props.fullWidth, (val) => {
|
|
|
112
112
|
<AntCreateButton
|
|
113
113
|
filled
|
|
114
114
|
:skeleton="skeleton"
|
|
115
|
+
:can-create="canCreate"
|
|
116
|
+
:invalid-permission-tooltip-position="Position.left"
|
|
115
117
|
@click="() => emit('create')"
|
|
116
118
|
/>
|
|
117
119
|
</slot>
|
package/dist/runtime/utils.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Slot } from 'vue';
|
|
1
2
|
/**
|
|
2
3
|
* Convert html class syntax given as undefined, string ("text-base bg-primary-500") or
|
|
3
4
|
* object syntax ({"text-base bg-primary-500": true}) always to object syntax ({"text-base bg-primary-500": true}).
|
|
@@ -12,3 +13,8 @@ export declare function classesToObjectSyntax(classes: string | undefined | Reco
|
|
|
12
13
|
* @param className
|
|
13
14
|
*/
|
|
14
15
|
export declare function enumToPlainText(value: object, className: string): string;
|
|
16
|
+
/**
|
|
17
|
+
* Detect if the given vue template slot exists and has content.
|
|
18
|
+
* To get a slot in your component, call $slots['slotName'] or useSlots()['slotName'].
|
|
19
|
+
*/
|
|
20
|
+
export declare function hasSlotContent(slot: Slot<any> | undefined): boolean;
|
package/dist/runtime/utils.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Fragment } from "vue";
|
|
1
2
|
export function classesToObjectSyntax(classes) {
|
|
2
3
|
if (typeof classes === "object") {
|
|
3
4
|
return classes;
|
|
@@ -18,3 +19,23 @@ export function enumToPlainText(value, className) {
|
|
|
18
19
|
});
|
|
19
20
|
return text + "}";
|
|
20
21
|
}
|
|
22
|
+
export function hasSlotContent(slot) {
|
|
23
|
+
if (!slot) {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
const isVnodeEmpty = (vnodes) => {
|
|
27
|
+
return vnodes.every((node) => {
|
|
28
|
+
if (node.type === Comment) {
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
31
|
+
if (node.type === Text && typeof node.children === "string" && !node.children.trim()) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
if (node.type === Fragment && isVnodeEmpty(node.children)) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
return false;
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
return !isVnodeEmpty(slot());
|
|
41
|
+
}
|
package/package.json
CHANGED
|
@@ -3,78 +3,80 @@ import {computed, onMounted, ref} from 'vue';
|
|
|
3
3
|
import {handleEnumValidation} from '../handler';
|
|
4
4
|
import {InputColorType, Position} from '../enums';
|
|
5
5
|
import {classesToObjectSyntax} from '../utils';
|
|
6
|
+
import {hasSlotContent} from '../utils';
|
|
6
7
|
|
|
7
8
|
const props = withDefaults(defineProps<{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
position?: Position
|
|
10
|
+
tooltipClasses?: string | Record<string, boolean>
|
|
11
|
+
colorType?: InputColorType
|
|
12
|
+
expanded?: boolean
|
|
12
13
|
}>(), {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
position: Position.left,
|
|
15
|
+
tooltipClasses: '',
|
|
16
|
+
colorType: InputColorType.base,
|
|
17
|
+
expanded: false
|
|
16
18
|
});
|
|
17
19
|
const visible = ref(false);
|
|
18
20
|
const _tooltipClasses = computed(() => ({
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
'absolute w-max inline-flex': true,
|
|
22
|
+
// Position
|
|
23
|
+
'bottom-full pb-3.5': props.position === Position.top,
|
|
24
|
+
'top-full pt-3.5': props.position === Position.bottom,
|
|
25
|
+
'right-full pr-3.5': props.position === Position.left,
|
|
26
|
+
'left-full pl-3.5': props.position === Position.right,
|
|
27
|
+
...classesToObjectSyntax(props.tooltipClasses)
|
|
26
28
|
}));
|
|
27
29
|
const classes = computed(() => ({
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
'z-10 absolute flex': true,
|
|
31
|
+
'top-0 left-0 right-0 -m-[2px] justify-center': props.position === Position.bottom,
|
|
32
|
+
'bottom-0 left-0 right-0 -m-[2px] justify-center': props.position === Position.top,
|
|
33
|
+
'top-0 left-0 bottom-0 -ml-[2.2px] items-center': props.position === Position.right,
|
|
34
|
+
'top-0 right-0 bottom-0 -mr-[2.2px] items-center': props.position === Position.left,
|
|
33
35
|
}));
|
|
34
36
|
const itemContainerClasses = computed(() => ({
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
'relative flex items-center': true,
|
|
38
|
+
'justify-center': props.position === Position.bottom,
|
|
39
|
+
'justify-center rotate-180': props.position === Position.top,
|
|
40
|
+
'justify-center -rotate-90': props.position === Position.right,
|
|
41
|
+
'justify-center rotate-90': props.position === Position.left,
|
|
40
42
|
}));
|
|
41
43
|
const contentClasses = computed(() => {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
44
|
+
const variants: Record<InputColorType, string> = {
|
|
45
|
+
[InputColorType.base]: 'text-neutral-50-font bg-neutral-50 border-neutral-300',
|
|
46
|
+
[InputColorType.danger]: 'text-danger-500-font bg-danger-500 border-danger-500',
|
|
47
|
+
[InputColorType.info]: 'text-info-500-font bg-info-500 border-info-500',
|
|
48
|
+
[InputColorType.success]: 'text-success-500-font bg-success-500 border-success-500',
|
|
49
|
+
[InputColorType.warning]: 'text-warning-500-font bg-warning-500 border-warning-500',
|
|
50
|
+
};
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
return {[variants[props.colorType]]: true};
|
|
51
53
|
});
|
|
52
54
|
const svgPathClasses = computed(() => {
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
55
|
+
const variants: Record<InputColorType, string> = {
|
|
56
|
+
[InputColorType.base]: 'fill-neutral-50 stroke-neutral-50',
|
|
57
|
+
[InputColorType.danger]: 'fill-danger-500 stroke-danger-500',
|
|
58
|
+
[InputColorType.info]: 'fill-info-500 stroke-info-500',
|
|
59
|
+
[InputColorType.success]: 'fill-success-500 stroke-success-500',
|
|
60
|
+
[InputColorType.warning]: 'fill-warning-500 stroke-warning-500',
|
|
61
|
+
};
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
return {[variants[props.colorType]]: true};
|
|
62
64
|
});
|
|
63
65
|
const arrowSvgPathClasses = computed(() => {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
const variants: Record<InputColorType, string> = {
|
|
67
|
+
[InputColorType.base]: 'stroke-neutral-300',
|
|
68
|
+
[InputColorType.danger]: 'stroke-danger-500',
|
|
69
|
+
[InputColorType.info]: 'stroke-info-500',
|
|
70
|
+
[InputColorType.success]: 'stroke-success-500',
|
|
71
|
+
[InputColorType.warning]: 'stroke-warning-500',
|
|
72
|
+
};
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
return {[variants[props.colorType]]: true};
|
|
73
75
|
});
|
|
74
76
|
|
|
75
77
|
onMounted(() => {
|
|
76
|
-
|
|
77
|
-
|
|
78
|
+
handleEnumValidation(props.position, Position, 'Position')
|
|
79
|
+
handleEnumValidation(props.colorType, InputColorType, 'colorType')
|
|
78
80
|
});
|
|
79
81
|
|
|
80
82
|
/**
|
|
@@ -84,33 +86,37 @@ onMounted(() => {
|
|
|
84
86
|
const delayVisible = ref(visible.value);
|
|
85
87
|
|
|
86
88
|
function onMouseOver() {
|
|
87
|
-
|
|
89
|
+
delayVisible.value = true;
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
setTimeout(() => {
|
|
92
|
+
if (delayVisible.value) {
|
|
93
|
+
visible.value = true
|
|
94
|
+
}
|
|
95
|
+
}, 300)
|
|
94
96
|
}
|
|
95
97
|
|
|
96
98
|
function onMouseLeave() {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
+
delayVisible.value = false
|
|
100
|
+
visible.value = false
|
|
99
101
|
}
|
|
100
102
|
</script>
|
|
101
103
|
|
|
102
104
|
<template>
|
|
103
105
|
<div
|
|
104
|
-
class="relative
|
|
106
|
+
class="relative justify-center items-center"
|
|
107
|
+
:class="{'flex w-full': props.expanded, 'inline-flex': !props.expanded}"
|
|
105
108
|
data-e2e="tooltip"
|
|
106
109
|
@mouseover="onMouseOver"
|
|
107
110
|
@mouseleave="onMouseLeave"
|
|
108
111
|
>
|
|
109
|
-
<slot/>
|
|
112
|
+
<slot />
|
|
110
113
|
|
|
111
|
-
<div
|
|
114
|
+
<div
|
|
115
|
+
v-if="visible && hasSlotContent($slots.content)"
|
|
116
|
+
:class="_tooltipClasses"
|
|
117
|
+
>
|
|
112
118
|
<div
|
|
113
|
-
class="shadow-lg text-sm relative
|
|
119
|
+
class="shadow-lg text-sm relative"
|
|
114
120
|
>
|
|
115
121
|
<div
|
|
116
122
|
:class="classes"
|
|
@@ -157,7 +163,7 @@ function onMouseLeave() {
|
|
|
157
163
|
class="p-2.5 rounded-md border"
|
|
158
164
|
:class="contentClasses"
|
|
159
165
|
>
|
|
160
|
-
<slot name="content"/>
|
|
166
|
+
<slot name="content" />
|
|
161
167
|
</div>
|
|
162
168
|
</div>
|
|
163
169
|
</div>
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import {Grouped} from '../../enums/Grouped.enum';
|
|
7
7
|
import {Size} from '../../enums/Size.enum';
|
|
8
|
-
import {ColorType} from '../../enums/ColorType.enum';
|
|
8
|
+
import {ColorType, InputColorType} from '../../enums/ColorType.enum';
|
|
9
|
+
import {Position} from '../../enums/Position.enum';
|
|
9
10
|
import AntButton from './AntButton.vue';
|
|
11
|
+
import AntTooltip from '../AntTooltip.vue';
|
|
10
12
|
|
|
11
13
|
defineEmits(['click', 'blur']);
|
|
12
14
|
withDefaults(
|
|
@@ -17,25 +19,45 @@ withDefaults(
|
|
|
17
19
|
colorType?: ColorType;
|
|
18
20
|
skeleton?: boolean;
|
|
19
21
|
expanded?: boolean;
|
|
22
|
+
filled?: boolean;
|
|
23
|
+
hasPermission?: boolean;
|
|
24
|
+
invalidPermissionTooltipPosition?: Position;
|
|
20
25
|
}>(), {
|
|
21
26
|
colorType: ColorType.primary,
|
|
27
|
+
hasPermission: true,
|
|
28
|
+
filled: true
|
|
22
29
|
}
|
|
23
30
|
)
|
|
24
31
|
</script>
|
|
25
32
|
|
|
26
33
|
<template>
|
|
27
|
-
<
|
|
28
|
-
:size="size"
|
|
29
|
-
:disabled="disabled"
|
|
30
|
-
:grouped="grouped"
|
|
31
|
-
:skeleton="skeleton"
|
|
34
|
+
<AntTooltip
|
|
32
35
|
:expanded="expanded"
|
|
33
|
-
:
|
|
34
|
-
|
|
35
|
-
data-e2e="action-button"
|
|
36
|
-
@click="$emit('click')"
|
|
37
|
-
@blur="$emit('blur')"
|
|
36
|
+
:position="invalidPermissionTooltipPosition"
|
|
37
|
+
:color-type="InputColorType.info"
|
|
38
38
|
>
|
|
39
|
-
<slot
|
|
40
|
-
|
|
39
|
+
<slot name="button">
|
|
40
|
+
<AntButton
|
|
41
|
+
:size="size"
|
|
42
|
+
:disabled="disabled || !hasPermission"
|
|
43
|
+
:grouped="grouped"
|
|
44
|
+
:skeleton="skeleton"
|
|
45
|
+
:expanded="expanded"
|
|
46
|
+
:color-type="colorType"
|
|
47
|
+
:filled="filled"
|
|
48
|
+
data-e2e="action-button"
|
|
49
|
+
@click="$emit('click')"
|
|
50
|
+
@blur="$emit('blur')"
|
|
51
|
+
>
|
|
52
|
+
<slot />
|
|
53
|
+
</AntButton>
|
|
54
|
+
</slot>
|
|
55
|
+
|
|
56
|
+
<template
|
|
57
|
+
v-if="!hasPermission && !skeleton"
|
|
58
|
+
#content
|
|
59
|
+
>
|
|
60
|
+
<slot name="invalidPermissionTooltipContent" />
|
|
61
|
+
</template>
|
|
62
|
+
</AntTooltip>
|
|
41
63
|
</template>
|
|
@@ -102,7 +102,7 @@ const classes = computed(() => {
|
|
|
102
102
|
return {
|
|
103
103
|
'transition-all inline-flex items-center justify-center relative font-medium': true,
|
|
104
104
|
'focus:z-10': true,
|
|
105
|
-
'active:shadow-[inset_0_4px_4px_rgba(0,0,0,0.25)]': !
|
|
105
|
+
'active:shadow-[inset_0_4px_4px_rgba(0,0,0,0.25)]': !hasAction.value,
|
|
106
106
|
'py-1.5 px-2.5 text-xs gap-1': props.size === Size.sm,
|
|
107
107
|
'py-2.5 px-3.5 text-sm gap-2.5': props.size === Size.md,
|
|
108
108
|
'disabled:opacity-50 disabled:cursor-not-allowed': true,
|
|
@@ -115,9 +115,9 @@ const classes = computed(() => {
|
|
|
115
115
|
...groupedClassList.value,
|
|
116
116
|
[variants[props.colorType]]: true,
|
|
117
117
|
[notFilledVariants[props.colorType]]: !props.filled,
|
|
118
|
-
[notFilledHoverVariants[props.colorType]]: !props.filled && !
|
|
118
|
+
[notFilledHoverVariants[props.colorType]]: !props.filled && !hasAction.value,
|
|
119
119
|
[filledVariants[props.colorType]]: props.filled,
|
|
120
|
-
[filledHoverVariants[props.colorType]]: props.filled && !
|
|
120
|
+
[filledHoverVariants[props.colorType]]: props.filled && !hasAction.value,
|
|
121
121
|
};
|
|
122
122
|
});
|
|
123
123
|
const iconColor = computed(() => {
|
|
@@ -2,15 +2,20 @@
|
|
|
2
2
|
import {Grouped} from '../../enums/Grouped.enum';
|
|
3
3
|
import {Size} from '../../enums/Size.enum';
|
|
4
4
|
import AntActionButton from './AntActionButton.vue';
|
|
5
|
+
import {Position} from '../../enums';
|
|
5
6
|
|
|
6
7
|
defineEmits(['click', 'blur']);
|
|
7
|
-
defineProps<{
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
withDefaults(defineProps<{
|
|
9
|
+
size?: Size;
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
grouped?: Grouped;
|
|
12
|
+
skeleton?: boolean;
|
|
13
|
+
expanded?: boolean;
|
|
14
|
+
canCreate?: boolean;
|
|
15
|
+
invalidPermissionTooltipPosition?: Position;
|
|
16
|
+
}>(), {
|
|
17
|
+
canCreate: true
|
|
18
|
+
});
|
|
14
19
|
</script>
|
|
15
20
|
|
|
16
21
|
<template>
|
|
@@ -20,10 +25,17 @@ defineProps<{
|
|
|
20
25
|
:grouped="grouped"
|
|
21
26
|
:skeleton="skeleton"
|
|
22
27
|
:expanded="expanded"
|
|
28
|
+
:has-permission="canCreate"
|
|
29
|
+
:invalid-permission-tooltip-position="invalidPermissionTooltipPosition"
|
|
23
30
|
data-e2e="create-button"
|
|
24
31
|
@click="$emit('click')"
|
|
25
32
|
@blur="$emit('blur')"
|
|
26
33
|
>
|
|
27
|
-
Create
|
|
34
|
+
<template #default>Create</template>
|
|
35
|
+
|
|
36
|
+
<template #invalidPermissionTooltipContent>
|
|
37
|
+
You have no permission to create new entries.<br>
|
|
38
|
+
Please contact your administrator.
|
|
39
|
+
</template>
|
|
28
40
|
</AntActionButton>
|
|
29
41
|
</template>
|