@antify/ui 1.1.0 → 1.2.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/components/AntAccordion.vue +15 -7
- package/dist/components/AntAccordionItem.vue +19 -5
- package/dist/components/AntAlert.vue +8 -6
- package/dist/components/AntDropdown.vue +50 -36
- package/dist/components/AntIcon.vue +8 -6
- package/dist/components/AntKeycap.vue +10 -10
- package/dist/components/AntListGroup.vue +5 -3
- package/dist/components/AntModal.vue +17 -7
- package/dist/components/AntPopover.vue +118 -42
- package/dist/components/AntSkeleton.vue +1 -1
- package/dist/components/AntTooltip.vue +102 -76
- package/dist/components/__stories/AntAccordion.stories.js +12 -3
- package/dist/components/__stories/AntAccordion.stories.mjs +12 -3
- package/dist/components/__stories/AntDropdown.stories.js +27 -23
- package/dist/components/__stories/AntDropdown.stories.mjs +26 -22
- package/dist/components/__stories/AntListGroup.stories.js +1 -1
- package/dist/components/__stories/AntListGroup.stories.mjs +1 -1
- package/dist/components/__stories/AntModal.stories.js +2 -1
- package/dist/components/__stories/AntModal.stories.mjs +2 -1
- package/dist/components/__stories/AntPopover.stories.js +22 -21
- package/dist/components/__stories/AntPopover.stories.mjs +22 -20
- package/dist/components/__stories/AntTooltip.stories.d.ts +0 -10
- package/dist/components/__stories/AntTooltip.stories.js +32 -212
- package/dist/components/__stories/AntTooltip.stories.mjs +29 -193
- package/dist/components/buttons/AntButton.vue +41 -44
- package/dist/components/crud/AntCrud.vue +1 -1
- package/dist/components/crud/AntCrudDetailActions.vue +1 -0
- package/dist/components/crud/AntCrudTableFilter.vue +20 -18
- package/dist/components/forms/AntField.vue +7 -2
- package/dist/components/forms/__stories/AntField.stories.js +0 -16
- package/dist/components/forms/__stories/AntField.stories.mjs +2 -16
- package/dist/components/index.d.ts +2 -2
- package/dist/components/index.js +7 -7
- package/dist/components/index.mjs +2 -2
- package/dist/components/inputs/AntCheckbox.vue +25 -6
- package/dist/components/inputs/AntDateInput.vue +1 -1
- package/dist/components/inputs/AntRadio.vue +2 -1
- package/dist/components/inputs/AntSelect.vue +25 -22
- package/dist/components/inputs/AntSwitch.vue +2 -7
- package/dist/components/inputs/AntTagInput.vue +91 -114
- package/dist/components/inputs/AntTextarea.vue +7 -3
- package/dist/components/inputs/Elements/AntBaseInput.vue +2 -2
- package/dist/components/inputs/Elements/{AntDropDown.vue → AntSelectMenu.vue} +85 -40
- package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.d.ts +0 -1
- package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.js +1 -29
- package/dist/components/inputs/Elements/__stories/AntBaseInput.stories.mjs +0 -22
- package/dist/components/inputs/Elements/index.d.ts +2 -1
- package/dist/components/inputs/Elements/index.js +7 -0
- package/dist/components/inputs/Elements/index.mjs +3 -1
- package/dist/components/inputs/__stories/AntCheckbox.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntCheckbox.stories.js +1 -43
- package/dist/components/inputs/__stories/AntCheckbox.stories.mjs +0 -35
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.js +1 -31
- package/dist/components/inputs/__stories/AntCheckboxGroup.stories.mjs +0 -28
- package/dist/components/inputs/__stories/AntDateInput.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntDateInput.stories.js +1 -32
- package/dist/components/inputs/__stories/AntDateInput.stories.mjs +0 -28
- package/dist/components/inputs/__stories/AntNumberInput.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntNumberInput.stories.js +1 -65
- package/dist/components/inputs/__stories/AntNumberInput.stories.mjs +1 -54
- package/dist/components/inputs/__stories/AntPasswordInput.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntPasswordInput.stories.js +1 -35
- package/dist/components/inputs/__stories/AntPasswordInput.stories.mjs +0 -25
- package/dist/components/inputs/__stories/AntRadioGroup.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntRadioGroup.stories.js +1 -47
- package/dist/components/inputs/__stories/AntRadioGroup.stories.mjs +0 -46
- package/dist/components/inputs/__stories/AntRangeSlider.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntRangeSlider.stories.js +1 -33
- package/dist/components/inputs/__stories/AntRangeSlider.stories.mjs +1 -28
- package/dist/components/inputs/__stories/AntSelect.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntSelect.stories.js +18 -46
- package/dist/components/inputs/__stories/AntSelect.stories.mjs +16 -47
- package/dist/components/inputs/__stories/AntSwitch.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntSwitch.stories.js +1 -42
- package/dist/components/inputs/__stories/AntSwitch.stories.mjs +1 -37
- package/dist/components/inputs/__stories/AntSwitcher.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntSwitcher.stories.js +1 -51
- package/dist/components/inputs/__stories/AntSwitcher.stories.mjs +1 -51
- package/dist/components/inputs/__stories/AntTagInput.stories.d.ts +0 -1
- package/dist/components/inputs/__stories/AntTagInput.stories.js +1 -35
- package/dist/components/inputs/__stories/AntTagInput.stories.mjs +0 -33
- package/dist/components/inputs/__stories/AntTextInput.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntTextInput.stories.js +1 -107
- package/dist/components/inputs/__stories/AntTextInput.stories.mjs +0 -104
- package/dist/components/inputs/__stories/AntTextarea.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntTextarea.stories.js +7 -66
- package/dist/components/inputs/__stories/AntTextarea.stories.mjs +6 -55
- package/dist/components/inputs/__stories/AntUnitInput.stories.d.ts +0 -2
- package/dist/components/inputs/__stories/AntUnitInput.stories.js +1 -61
- package/dist/components/inputs/__stories/AntUnitInput.stories.mjs +0 -53
- package/dist/components/table/AntTable.vue +17 -15
- package/dist/components/table/AntTd.vue +1 -2
- package/dist/components/table/__stories/AntTable.stories.js +7 -14
- package/dist/components/table/__stories/AntTable.stories.mjs +7 -15
- package/dist/components/tabs/AntTabItem.vue +16 -6
- package/dist/components/tabs/AntTabs.vue +8 -0
- package/dist/components/tabs/__types/AntTabItem.types.d.ts +1 -0
- package/package.json +2 -1
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import AntAccordionItem from './AntAccordionItem.vue';
|
|
3
3
|
import {onMounted, ref} from 'vue';
|
|
4
4
|
import {CollapseStrategy} from './__types/AntAccordion.types';
|
|
5
|
+
import AntSkeleton from "./AntSkeleton.vue";
|
|
5
6
|
|
|
6
7
|
const props = withDefaults(defineProps<{
|
|
7
8
|
items: {
|
|
@@ -16,8 +17,10 @@ const props = withDefaults(defineProps<{
|
|
|
16
17
|
inactiveIconClasses?: string;
|
|
17
18
|
}[];
|
|
18
19
|
collapseStrategy?: CollapseStrategy;
|
|
20
|
+
skeleton?: boolean;
|
|
19
21
|
}>(), {
|
|
20
|
-
collapseStrategy: CollapseStrategy.single
|
|
22
|
+
collapseStrategy: CollapseStrategy.single,
|
|
23
|
+
skeleton: false
|
|
21
24
|
});
|
|
22
25
|
|
|
23
26
|
const openItems = ref<number[]>([]);
|
|
@@ -59,6 +62,7 @@ function onClose(index: number) {
|
|
|
59
62
|
:activeIconClasses="item.activeIconClasses"
|
|
60
63
|
:inactiveLabelClasses="item.inactiveLabelClasses"
|
|
61
64
|
:inactiveIconClasses="item.inactiveIconClasses"
|
|
65
|
+
:skeleton="skeleton"
|
|
62
66
|
@open="() => onOpen(index)"
|
|
63
67
|
@close="() => onClose(index)"
|
|
64
68
|
>
|
|
@@ -69,12 +73,16 @@ function onClose(index: number) {
|
|
|
69
73
|
/>
|
|
70
74
|
</template>
|
|
71
75
|
|
|
72
|
-
<
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
76
|
+
<div class="relative">
|
|
77
|
+
<slot
|
|
78
|
+
name="item-content"
|
|
79
|
+
v-bind="{item, index}"
|
|
80
|
+
>
|
|
81
|
+
<div v-html="item.content"/>
|
|
82
|
+
|
|
83
|
+
<AntSkeleton v-if="skeleton" absolute rounded/>
|
|
84
|
+
</slot>
|
|
85
|
+
</div>
|
|
78
86
|
</AntAccordionItem>
|
|
79
87
|
</slot>
|
|
80
88
|
</div>
|
|
@@ -4,6 +4,7 @@ import AntIcon from './AntIcon.vue';
|
|
|
4
4
|
import AntTransitionCollapseHeight from './transitions/AntTransitionCollapseHeight.vue';
|
|
5
5
|
import {IconSize} from './__types/AntIcon.types';
|
|
6
6
|
import {computed} from 'vue';
|
|
7
|
+
import AntSkeleton from "../components/AntSkeleton.vue";
|
|
7
8
|
|
|
8
9
|
const props = withDefaults(defineProps<{
|
|
9
10
|
isOpen: boolean;
|
|
@@ -15,10 +16,12 @@ const props = withDefaults(defineProps<{
|
|
|
15
16
|
activeIconClasses?: string;
|
|
16
17
|
inactiveLabelClasses?: string;
|
|
17
18
|
inactiveIconClasses?: string;
|
|
19
|
+
skeleton?: boolean;
|
|
18
20
|
}>(), {
|
|
19
21
|
collapseTransition: 'slide',
|
|
20
22
|
iconLeft: false,
|
|
21
23
|
contentPadding: true,
|
|
24
|
+
skeleton: false,
|
|
22
25
|
activeLabelClasses: 'bg-primary-500 text-primary-500-font',
|
|
23
26
|
activeIconClasses: 'text-primary-500-font',
|
|
24
27
|
inactiveLabelClasses: 'bg-white text-for-white-bg-font',
|
|
@@ -28,6 +31,10 @@ const emit = defineEmits(['close', 'open']);
|
|
|
28
31
|
|
|
29
32
|
// TODO:: Stehengeblieben: delays machen
|
|
30
33
|
function onClick() {
|
|
34
|
+
if (props.skeleton) {
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
31
38
|
if (props.isOpen) {
|
|
32
39
|
emit('close');
|
|
33
40
|
} else {
|
|
@@ -37,13 +44,14 @@ function onClick() {
|
|
|
37
44
|
|
|
38
45
|
const labelClasses = computed(() => ({
|
|
39
46
|
[props.activeLabelClasses]: props.isOpen,
|
|
40
|
-
[props.inactiveLabelClasses]: !props.isOpen
|
|
47
|
+
[props.inactiveLabelClasses]: !props.isOpen,
|
|
48
|
+
'cursor-pointer': !props.skeleton
|
|
41
49
|
}))
|
|
42
50
|
</script>
|
|
43
51
|
|
|
44
52
|
<template>
|
|
45
53
|
<div
|
|
46
|
-
class="p-2 select-none
|
|
54
|
+
class="p-2 select-none transition-colors"
|
|
47
55
|
:class="labelClasses"
|
|
48
56
|
@click="onClick"
|
|
49
57
|
>
|
|
@@ -61,17 +69,23 @@ const labelClasses = computed(() => ({
|
|
|
61
69
|
:size="IconSize.sm"
|
|
62
70
|
:icon="faQuestionCircle"
|
|
63
71
|
:color="isOpen ? activeIconClasses : inactiveIconClasses"
|
|
72
|
+
:skeleton="skeleton"
|
|
64
73
|
/>
|
|
65
74
|
</slot>
|
|
66
75
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
76
|
+
|
|
77
|
+
<div class="relative">
|
|
78
|
+
<div class="text-sm font-semibold">
|
|
79
|
+
{{ label }}
|
|
80
|
+
</div>
|
|
81
|
+
<AntSkeleton v-if="skeleton" absolute rounded/>
|
|
82
|
+
</div>
|
|
70
83
|
</div>
|
|
71
84
|
|
|
72
85
|
<AntIcon
|
|
73
86
|
:icon="isOpen ? faAngleUp : faAngleDown"
|
|
74
87
|
:color="isOpen ? activeIconClasses : inactiveIconClasses"
|
|
88
|
+
:skeleton="skeleton"
|
|
75
89
|
/>
|
|
76
90
|
</div>
|
|
77
91
|
</slot>
|
|
@@ -114,12 +114,14 @@ onMounted(() => {
|
|
|
114
114
|
<div class="flex gap-2">
|
|
115
115
|
<div v-if="hasQuestionMark">
|
|
116
116
|
<slot name="questionMarkText">
|
|
117
|
-
<AntTooltip
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
117
|
+
<AntTooltip >
|
|
118
|
+
<template #reference>
|
|
119
|
+
<AntIcon
|
|
120
|
+
:icon="faCircleQuestion"
|
|
121
|
+
:color="iconColor"
|
|
122
|
+
:size="IconSize.sm"
|
|
123
|
+
/>
|
|
124
|
+
</template>
|
|
123
125
|
|
|
124
126
|
<template #content>
|
|
125
127
|
{{ questionMarkText }}
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
|
|
3
|
-
* TODO:: Emit if there's enough space for the dropdown content. If not, reposition it automatically like the
|
|
4
|
-
* browsers select dropdown content does.
|
|
5
|
-
* TODO:: Known issue: open dropdown, click between button and dropdown. Dropdown will not click.
|
|
6
|
-
* The v-on-click-outside does not trigger, because it think it's the dropdown itself.
|
|
7
|
-
* Solution is using margin only (calc(50% + 0.625rem)) and not padding.
|
|
8
|
-
*/
|
|
9
|
-
import {computed, onMounted} from 'vue';
|
|
10
|
-
import {handleEnumValidation} from '../handler';
|
|
11
|
-
import {Position} from '../enums';
|
|
2
|
+
import {computed, ref} from 'vue';
|
|
12
3
|
import {classesToObjectSyntax} from '../utils';
|
|
13
4
|
import {vOnClickOutside} from '@vueuse/components';
|
|
14
5
|
import {onKeyStroke} from '@vueuse/core';
|
|
6
|
+
import {autoUpdate, flip, offset, useFloating, shift} from "@floating-ui/vue";
|
|
15
7
|
|
|
16
8
|
const props = withDefaults(defineProps<{
|
|
17
9
|
showDropdown: boolean,
|
|
18
|
-
position?: Position,
|
|
19
10
|
dropdownClasses?: string | Record<string, boolean>,
|
|
20
|
-
contentPadding?: boolean
|
|
11
|
+
contentPadding?: boolean,
|
|
12
|
+
isClickable?: boolean,
|
|
21
13
|
}>(), {
|
|
22
|
-
showDropdown: false,
|
|
23
14
|
contentPadding: true,
|
|
24
|
-
position: Position.bottom,
|
|
25
15
|
dropdownClasses: '',
|
|
16
|
+
isClickable: true,
|
|
26
17
|
});
|
|
27
18
|
const emit = defineEmits(['update:showDropdown']);
|
|
28
19
|
|
|
20
|
+
const reference = ref<HTMLElement | null>(null)
|
|
21
|
+
const floating = ref<HTMLElement | null>(null)
|
|
22
|
+
|
|
23
|
+
const {floatingStyles} = useFloating(reference, floating, {
|
|
24
|
+
transform: false,
|
|
25
|
+
placement: 'bottom-start',
|
|
26
|
+
whileElementsMounted: autoUpdate,
|
|
27
|
+
middleware: [
|
|
28
|
+
offset(8),
|
|
29
|
+
shift(),
|
|
30
|
+
flip({
|
|
31
|
+
fallbackPlacements: ['top-start'],
|
|
32
|
+
}),
|
|
33
|
+
]
|
|
34
|
+
});
|
|
35
|
+
|
|
29
36
|
const _dropdownClasses = computed(() => ({
|
|
30
|
-
'
|
|
31
|
-
'bottom-0 left-0 mb-[50%] pb-2.5': props.position === Position.top,
|
|
32
|
-
'top-0 left-0 mt-[50%] pt-2.5': props.position === Position.bottom,
|
|
33
|
-
'right-0 top-0 mr-[100%] pr-2.5': props.position === Position.left,
|
|
34
|
-
'left-0 top-0 ml-[100%] pl-2.5': props.position === Position.right,
|
|
37
|
+
'min-w-[10rem] z-[90]': true,
|
|
35
38
|
...classesToObjectSyntax(props.dropdownClasses)
|
|
36
39
|
}));
|
|
37
40
|
|
|
38
|
-
onMounted(() => {
|
|
39
|
-
handleEnumValidation(props.position, Position, 'Position');
|
|
40
|
-
});
|
|
41
41
|
onKeyStroke('Escape', (e: KeyboardEvent) => {
|
|
42
42
|
if (props.showDropdown) {
|
|
43
43
|
e.preventDefault();
|
|
@@ -45,31 +45,45 @@ onKeyStroke('Escape', (e: KeyboardEvent) => {
|
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
const onClickOutside = [
|
|
49
|
+
(ev) => {
|
|
50
|
+
emit('update:showDropdown', false);
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
ignore: [floating]
|
|
54
|
+
}
|
|
55
|
+
]
|
|
51
56
|
</script>
|
|
52
57
|
|
|
53
58
|
<template>
|
|
54
59
|
<div
|
|
55
|
-
|
|
56
|
-
class="relative inline-flex justify-center items-end z-40"
|
|
60
|
+
class="relative flex"
|
|
57
61
|
data-e2e="dropdown"
|
|
58
62
|
>
|
|
59
|
-
<
|
|
63
|
+
<div
|
|
64
|
+
ref="reference"
|
|
65
|
+
class="h-full w-full"
|
|
66
|
+
v-on-click-outside="onClickOutside"
|
|
67
|
+
>
|
|
68
|
+
<slot/>
|
|
69
|
+
</div>
|
|
60
70
|
|
|
61
71
|
<Transition name="bounce">
|
|
62
|
-
<
|
|
63
|
-
v-if="showDropdown"
|
|
64
|
-
:class="_dropdownClasses"
|
|
65
|
-
>
|
|
72
|
+
<teleport to="body">
|
|
66
73
|
<div
|
|
67
|
-
|
|
68
|
-
:class="
|
|
74
|
+
v-if="showDropdown"
|
|
75
|
+
:class="_dropdownClasses"
|
|
76
|
+
ref="floating"
|
|
77
|
+
:style="floatingStyles"
|
|
69
78
|
>
|
|
70
|
-
<
|
|
79
|
+
<div
|
|
80
|
+
class="shadow-lg border border-neutral-300 rounded-md text-sm relative inline-flex flex-col bg-white text-for-white-bg-font w-full overflow-hidden"
|
|
81
|
+
:class="{'p-2': contentPadding}"
|
|
82
|
+
>
|
|
83
|
+
<slot name="content"/>
|
|
84
|
+
</div>
|
|
71
85
|
</div>
|
|
72
|
-
</
|
|
86
|
+
</teleport>
|
|
73
87
|
</Transition>
|
|
74
88
|
</div>
|
|
75
89
|
</template>
|
|
@@ -3,10 +3,12 @@ import {computed, onMounted} from 'vue';
|
|
|
3
3
|
import {handleEnumValidation} from '../handler';
|
|
4
4
|
import {type IconDefinition} from '@fortawesome/free-solid-svg-icons';
|
|
5
5
|
import {IconSize} from './__types/AntIcon.types';
|
|
6
|
+
import AntSkeleton from "./AntSkeleton.vue";
|
|
6
7
|
|
|
7
8
|
const props = withDefaults(defineProps<{
|
|
8
9
|
icon: IconDefinition;
|
|
9
10
|
size?: IconSize;
|
|
11
|
+
skeleton?: boolean;
|
|
10
12
|
|
|
11
13
|
/**
|
|
12
14
|
* A css text-* class
|
|
@@ -14,11 +16,12 @@ const props = withDefaults(defineProps<{
|
|
|
14
16
|
color?: string;
|
|
15
17
|
}>(), {
|
|
16
18
|
size: IconSize.sm,
|
|
17
|
-
color: 'text-for-white-bg-font'
|
|
19
|
+
color: 'text-for-white-bg-font',
|
|
20
|
+
skeleton: false,
|
|
18
21
|
});
|
|
19
22
|
|
|
20
23
|
const containerClasses = computed(() => ({
|
|
21
|
-
'inline-flex items-center justify-center': true,
|
|
24
|
+
'inline-flex items-center justify-center relative': true,
|
|
22
25
|
'w-3 h-3': props.size === IconSize.xs2,
|
|
23
26
|
'w-4 h-4': props.size === IconSize.xs,
|
|
24
27
|
'w-5 h-5': props.size === IconSize.sm,
|
|
@@ -44,13 +47,12 @@ onMounted(() => {
|
|
|
44
47
|
</script>
|
|
45
48
|
|
|
46
49
|
<template>
|
|
47
|
-
<span
|
|
48
|
-
v-if="icon"
|
|
49
|
-
:class="containerClasses"
|
|
50
|
-
>
|
|
50
|
+
<span :class="containerClasses">
|
|
51
51
|
<FaIcon
|
|
52
|
+
v-if="icon"
|
|
52
53
|
:icon="icon"
|
|
53
54
|
:class="iconClasses"
|
|
54
55
|
/>
|
|
56
|
+
<AntSkeleton v-if="skeleton" absolute rounded/>
|
|
55
57
|
</span>
|
|
56
58
|
</template>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
2
|
// TODO:: Fix typo KeyCap with upperchar C
|
|
3
3
|
import AntIcon from './AntIcon.vue';
|
|
4
|
+
import AntSkeleton from "./AntSkeleton.vue";
|
|
4
5
|
import {type IconDefinition} from '@fortawesome/free-solid-svg-icons';
|
|
5
6
|
import {IconSize} from './__types';
|
|
6
7
|
import {AntKeycapSize} from './__types/AntKeycap.types';
|
|
@@ -9,9 +10,10 @@ import {computed} from 'vue';
|
|
|
9
10
|
const props = withDefaults(defineProps<{
|
|
10
11
|
icon?: IconDefinition
|
|
11
12
|
size?: AntKeycapSize
|
|
12
|
-
|
|
13
|
+
skeleton?: boolean
|
|
13
14
|
}>(), {
|
|
14
|
-
size: AntKeycapSize.sm
|
|
15
|
+
size: AntKeycapSize.sm,
|
|
16
|
+
skeleton: false
|
|
15
17
|
});
|
|
16
18
|
|
|
17
19
|
const classes = computed(() => {
|
|
@@ -35,16 +37,14 @@ const iconClasses = computed(() => {
|
|
|
35
37
|
</script>
|
|
36
38
|
|
|
37
39
|
<template>
|
|
38
|
-
<
|
|
39
|
-
|
|
40
|
-
:class="classes"
|
|
41
|
-
>
|
|
42
|
-
<AntIcon
|
|
40
|
+
<div class="inline-flex relative justify-center items-center bg-neutral-300 rounded-md text-center text-neutral-300-font font-medium" :class="classes">
|
|
41
|
+
<AntIcon
|
|
43
42
|
v-if="icon"
|
|
44
43
|
:icon="icon"
|
|
45
44
|
:size="iconClasses"
|
|
46
|
-
|
|
45
|
+
/>
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
<slot v-else/>
|
|
48
|
+
<AntSkeleton v-if="skeleton" absolute rounded/>
|
|
49
|
+
</div>
|
|
50
50
|
</template>
|
|
@@ -3,9 +3,11 @@ import AntSkeleton from './AntSkeleton.vue';
|
|
|
3
3
|
|
|
4
4
|
withDefaults(
|
|
5
5
|
defineProps<{
|
|
6
|
-
skeleton?: boolean
|
|
6
|
+
skeleton?: boolean,
|
|
7
|
+
shadow?: boolean
|
|
7
8
|
}>(), {
|
|
8
|
-
skeleton: false
|
|
9
|
+
skeleton: false,
|
|
10
|
+
shadow: false,
|
|
9
11
|
}
|
|
10
12
|
)
|
|
11
13
|
</script>
|
|
@@ -16,7 +18,7 @@ withDefaults(
|
|
|
16
18
|
|
|
17
19
|
<div
|
|
18
20
|
class="flex flex-col rounded-md bg-neutral-300 gap-px relative border border-neutral-300 overflow-hidden"
|
|
19
|
-
:class="{'invisible': skeleton}"
|
|
21
|
+
:class="{'invisible': skeleton, 'shadow-md': shadow}"
|
|
20
22
|
>
|
|
21
23
|
<slot/>
|
|
22
24
|
</div>
|
|
@@ -2,14 +2,19 @@
|
|
|
2
2
|
import {ref, useSlots, watch} from 'vue';
|
|
3
3
|
import {faXmark} from '@fortawesome/free-solid-svg-icons';
|
|
4
4
|
import AntButton from './buttons/AntButton.vue';
|
|
5
|
+
import AntSkeleton from "./AntSkeleton.vue";
|
|
5
6
|
|
|
6
7
|
const emit = defineEmits(['update:open', 'close']);
|
|
7
8
|
const props = withDefaults(defineProps<{
|
|
8
9
|
title: string,
|
|
9
10
|
open: boolean,
|
|
10
|
-
fullscreen?: boolean
|
|
11
|
+
fullscreen?: boolean,
|
|
12
|
+
padding?: boolean
|
|
13
|
+
skeleton?: boolean
|
|
11
14
|
}>(), {
|
|
12
|
-
fullscreen: false
|
|
15
|
+
fullscreen: false,
|
|
16
|
+
padding: false,
|
|
17
|
+
skeleton: false
|
|
13
18
|
});
|
|
14
19
|
const openModal = ref(props.open);
|
|
15
20
|
const openBackground = ref(props.open);
|
|
@@ -53,21 +58,26 @@ function closeModal() {
|
|
|
53
58
|
:class="{'w-full h-full': fullscreen, 'border border-neutral-300 rounded-md shadow-md': !fullscreen}"
|
|
54
59
|
>
|
|
55
60
|
<div
|
|
56
|
-
class="bg-white p-2 flex items-center justify-between
|
|
61
|
+
class="bg-white p-2 flex items-center justify-between"
|
|
57
62
|
>
|
|
58
63
|
<slot name="title">
|
|
59
|
-
|
|
64
|
+
<div class="relative text-for-white-bg-font text-lg font-medium">
|
|
65
|
+
{{ title }}
|
|
66
|
+
<AntSkeleton v-if="skeleton" absolute rounded/>
|
|
67
|
+
</div>
|
|
60
68
|
</slot>
|
|
61
69
|
|
|
62
70
|
<AntButton
|
|
71
|
+
:skeleton="skeleton"
|
|
63
72
|
:icon-left="faXmark"
|
|
64
|
-
:outlined="false"
|
|
65
|
-
filled
|
|
66
73
|
@click="closeModal"
|
|
67
74
|
/>
|
|
68
75
|
</div>
|
|
69
76
|
|
|
70
|
-
<div
|
|
77
|
+
<div
|
|
78
|
+
class="bg-white text-for-white-bg-font grow overflow-y-auto"
|
|
79
|
+
:class="{'p-2': padding}"
|
|
80
|
+
>
|
|
71
81
|
<slot/>
|
|
72
82
|
</div>
|
|
73
83
|
|
|
@@ -1,57 +1,145 @@
|
|
|
1
1
|
<script lang="ts" setup>
|
|
2
|
-
import {computed,
|
|
3
|
-
import {handleEnumValidation} from '../handler';
|
|
2
|
+
import {computed, ref} from 'vue';
|
|
4
3
|
import {Position} from '../enums/Position.enum';
|
|
5
4
|
import {classesToObjectSyntax} from '../utils';
|
|
5
|
+
import {arrow, autoUpdate, flip, offset, useFloating, shift, limitShift} from "@floating-ui/vue";
|
|
6
|
+
import {vOnClickOutside} from '@vueuse/components';
|
|
7
|
+
import {onKeyStroke} from "@vueuse/core";
|
|
6
8
|
|
|
7
9
|
const props = withDefaults(defineProps<{
|
|
8
10
|
showPopover: boolean,
|
|
9
11
|
title?: string,
|
|
10
|
-
|
|
12
|
+
isClickable?: boolean,
|
|
11
13
|
popoverClasses?: string | Record<string, boolean>
|
|
12
14
|
}>(), {
|
|
15
|
+
isClickable: true,
|
|
13
16
|
showPopover: false,
|
|
14
|
-
|
|
17
|
+
preferredPosition: Position.top,
|
|
15
18
|
popoverClasses: ''
|
|
16
19
|
});
|
|
20
|
+
|
|
21
|
+
const emit = defineEmits(['update:showPopover']);
|
|
22
|
+
|
|
23
|
+
const reference = ref<HTMLElement | null>(null)
|
|
24
|
+
const floating = ref<HTMLElement | null>(null)
|
|
25
|
+
const floatingArrow = ref<HTMLElement | null>(null);
|
|
26
|
+
|
|
27
|
+
const {floatingStyles, middlewareData, placement} = useFloating(reference, floating, {
|
|
28
|
+
transform: false,
|
|
29
|
+
placement: 'right',
|
|
30
|
+
whileElementsMounted: autoUpdate,
|
|
31
|
+
middleware: [
|
|
32
|
+
offset(() => 16),
|
|
33
|
+
shift({
|
|
34
|
+
limiter: limitShift({
|
|
35
|
+
offset: {
|
|
36
|
+
mainAxis: 62,
|
|
37
|
+
}
|
|
38
|
+
}),
|
|
39
|
+
}),
|
|
40
|
+
flip({
|
|
41
|
+
fallbackPlacements: ['top', 'bottom', 'left'],
|
|
42
|
+
}),
|
|
43
|
+
arrow({element: floatingArrow})
|
|
44
|
+
]
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const side = computed(() => placement.value.split('-')[0]);
|
|
48
|
+
const staticSide = computed(() => {
|
|
49
|
+
return {
|
|
50
|
+
top: "bottom",
|
|
51
|
+
right: "left",
|
|
52
|
+
bottom: "top",
|
|
53
|
+
left: "right"
|
|
54
|
+
}[side.value] as string
|
|
55
|
+
})
|
|
56
|
+
const arrowTransform = computed(() => {
|
|
57
|
+
if (placement.value === 'bottom') {
|
|
58
|
+
return 'rotate(0deg)'
|
|
59
|
+
} else if (placement.value === 'top') {
|
|
60
|
+
return 'rotate(180deg)'
|
|
61
|
+
} else if (placement.value === 'left') {
|
|
62
|
+
return 'rotate(90deg)'
|
|
63
|
+
} else {
|
|
64
|
+
return 'rotate(270deg)'
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
17
68
|
const _popoverClasses = computed(() => ({
|
|
18
|
-
'
|
|
19
|
-
'bottom-0 mb-[50%] pb-3.5': props.position === Position.top,
|
|
20
|
-
'top-0 mt-[50%] pt-3.5': props.position === Position.bottom,
|
|
21
|
-
'right-0 mr-[100%] pr-3.5': props.position === Position.left,
|
|
22
|
-
'left-0 ml-[100%] pl-3.5': props.position === Position.right,
|
|
69
|
+
'z-[90] min-w-[10rem]': true,
|
|
23
70
|
...classesToObjectSyntax(props.popoverClasses)
|
|
24
71
|
}));
|
|
25
|
-
const classes = computed(() => ({
|
|
26
|
-
'z-10 absolute flex': true,
|
|
27
|
-
'top-0 left-0 right-0 -m-[2.5px] justify-center': props.position === Position.bottom,
|
|
28
|
-
'bottom-0 left-0 right-0 -m-[2.5px] justify-center': props.position === Position.top,
|
|
29
|
-
'top-0 left-0 bottom-0 -ml-[2.5px] items-end pb-1': props.position === Position.right,
|
|
30
|
-
'top-0 right-0 bottom-0 -mr-[2.5px] items-end pb-1': props.position === Position.left,
|
|
31
|
-
}));
|
|
32
72
|
const itemContainerClasses = computed(() => ({
|
|
33
|
-
'relative flex items-center': true,
|
|
34
|
-
'justify-center': props.position === Position.bottom,
|
|
35
|
-
'justify-center rotate-180': props.position === Position.top,
|
|
36
|
-
'justify-start -rotate-90': props.position === Position.right,
|
|
37
|
-
'justify-end rotate-90': props.position === Position.left,
|
|
73
|
+
'relative flex items-center justify-center': true,
|
|
38
74
|
}));
|
|
39
75
|
|
|
40
|
-
|
|
41
|
-
|
|
76
|
+
onKeyStroke('Escape', (e: KeyboardEvent) => {
|
|
77
|
+
if (props.showPopover) {
|
|
78
|
+
e.preventDefault();
|
|
79
|
+
emit('update:showPopover', false);
|
|
80
|
+
}
|
|
42
81
|
});
|
|
82
|
+
|
|
83
|
+
const onClickOutside = [
|
|
84
|
+
(ev) => {
|
|
85
|
+
emit('update:showPopover', false);
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
ignore: [floating]
|
|
89
|
+
}
|
|
90
|
+
]
|
|
43
91
|
</script>
|
|
44
92
|
|
|
45
93
|
<template>
|
|
46
94
|
<div class="relative inline-flex justify-center items-end">
|
|
47
|
-
<
|
|
95
|
+
<div
|
|
96
|
+
v-on-click-outside="onClickOutside"
|
|
97
|
+
ref="reference"
|
|
98
|
+
>
|
|
99
|
+
<slot/>
|
|
100
|
+
</div>
|
|
48
101
|
|
|
49
102
|
<Transition name="bounce">
|
|
50
103
|
<template v-if="showPopover">
|
|
51
|
-
<
|
|
52
|
-
<div
|
|
104
|
+
<teleport to="body">
|
|
105
|
+
<div
|
|
106
|
+
:class="_popoverClasses"
|
|
107
|
+
ref="floating"
|
|
108
|
+
:style="floatingStyles"
|
|
109
|
+
>
|
|
110
|
+
<div class="shadow-lg border-neutral-300 rounded-md text-sm relative inline-flex flex-col">
|
|
111
|
+
|
|
112
|
+
<div
|
|
113
|
+
class="border-neutral-300 border-b p-2 bg-neutral-100 rounded-t-md border-t border-l border-r text-neutral-100-font font-semibold"
|
|
114
|
+
>
|
|
115
|
+
<slot name="title">
|
|
116
|
+
{{ title }}
|
|
117
|
+
</slot>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div
|
|
121
|
+
class="p-2 rounded-b-md text-for-white-bg-font border-neutral-300 border-l border-b border-r bg-white"
|
|
122
|
+
>
|
|
123
|
+
<slot name="content"/>
|
|
124
|
+
</div>
|
|
125
|
+
</div>
|
|
126
|
+
|
|
53
127
|
<div
|
|
54
|
-
|
|
128
|
+
class="flex items-center justify-center"
|
|
129
|
+
ref="floatingArrow"
|
|
130
|
+
:style="{
|
|
131
|
+
position: 'absolute',
|
|
132
|
+
left:
|
|
133
|
+
middlewareData.arrow?.x != null
|
|
134
|
+
? `${middlewareData.arrow.x}px`
|
|
135
|
+
: '',
|
|
136
|
+
top:
|
|
137
|
+
middlewareData.arrow?.y != null
|
|
138
|
+
? `${middlewareData.arrow.y}px`
|
|
139
|
+
: '',
|
|
140
|
+
[staticSide]: '-2.5px',
|
|
141
|
+
transform: arrowTransform
|
|
142
|
+
}"
|
|
55
143
|
>
|
|
56
144
|
<div
|
|
57
145
|
:class="itemContainerClasses"
|
|
@@ -66,12 +154,12 @@ onMounted(() => {
|
|
|
66
154
|
>
|
|
67
155
|
<path
|
|
68
156
|
d="M20.3284 1.82843L23.1569 4.65685C24.6571 6.15715 26.692 7 28.8137 7L6.18629 7C8.30802 7 10.3429 6.15715 11.8431 4.65686L14.6716 1.82843C16.2337 0.266331 18.7663 0.266328 20.3284 1.82843Z"
|
|
69
|
-
:class="{'fill-neutral-100':
|
|
157
|
+
:class="{'fill-neutral-100': placement === Position.bottom, 'fill-white': placement === Position.top || placement === Position.right || placement === Position.left}"
|
|
70
158
|
/>
|
|
71
159
|
|
|
72
160
|
<path
|
|
73
161
|
d="M34.5 7L28.8137 7C26.692 7 24.6571 6.15715 23.1569 4.65685L20.3284 1.82843C18.7663 0.266328 16.2337 0.266331 14.6716 1.82843L11.8431 4.65686C10.3429 6.15715 8.30802 7 6.18629 7L0.5 7L34.5 7Z"
|
|
74
|
-
:class="{'stroke-neutral-100':
|
|
162
|
+
:class="{'stroke-neutral-100': placement === Position.bottom, 'stroke-white': placement === Position.top || placement === Position.right || placement === Position.left}"
|
|
75
163
|
/>
|
|
76
164
|
</svg>
|
|
77
165
|
|
|
@@ -90,20 +178,8 @@ onMounted(() => {
|
|
|
90
178
|
</svg>
|
|
91
179
|
</div>
|
|
92
180
|
</div>
|
|
93
|
-
|
|
94
|
-
<div
|
|
95
|
-
class="border-neutral-300 border-b p-2 bg-neutral-100 rounded-t-md border-t border-l border-r text-neutral-100-font font-semibold"
|
|
96
|
-
>
|
|
97
|
-
{{ title }}
|
|
98
|
-
</div>
|
|
99
|
-
|
|
100
|
-
<div
|
|
101
|
-
class="p-2 rounded-b-md text-for-white-bg-font border-neutral-300 border-l border-b border-r bg-white"
|
|
102
|
-
>
|
|
103
|
-
<slot name="content"/>
|
|
104
|
-
</div>
|
|
105
181
|
</div>
|
|
106
|
-
</
|
|
182
|
+
</teleport>
|
|
107
183
|
</template>
|
|
108
184
|
</Transition>
|
|
109
185
|
</div>
|
|
@@ -25,7 +25,7 @@ const classList = computed(() => ({
|
|
|
25
25
|
'animate-skeleton min-h-[1px] min-w-[1px] inline-block': true,
|
|
26
26
|
'absolute inset-0 w-full h-full z-40': props.absolute,
|
|
27
27
|
'rounded-md': props.rounded && props.grouped === Grouped.none,
|
|
28
|
-
'rounded-
|
|
28
|
+
'rounded-full': props.roundedFull && props.grouped === Grouped.none,
|
|
29
29
|
...groupedClassList.value
|
|
30
30
|
}));
|
|
31
31
|
</script>
|