@dolanske/vui 1.2.0 → 1.3.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/README.md +4 -27
- package/dist/components/Dropdown/Dropdown.vue.d.ts +15 -21
- package/dist/components/Popout/Popout.vue.d.ts +7 -13
- package/dist/shared/helpers.d.ts +2 -0
- package/dist/vui.css +1 -1
- package/dist/vui.js +3059 -3005
- package/package.json +1 -1
- package/src/components/CopyClipboard/CopyClipboard.vue +10 -3
- package/src/components/Dropdown/Dropdown.vue +1 -15
- package/src/components/Input/Counter.vue +1 -1
- package/src/components/Input/Password.vue +1 -1
- package/src/components/Pagination/Pagination.vue +25 -10
- package/src/components/Popout/Popout.vue +30 -9
- package/src/components/Popout/popout.scss +1 -0
- package/src/components/Sheet/Sheet.vue +1 -3
- package/src/components/Sheet/sheet.scss +3 -1
- package/src/components/Table/Head.vue +23 -16
- package/src/components/Table/table.scss +7 -6
- package/src/components/Tooltip/Tooltip.vue +9 -17
- package/src/components/Tooltip/tooltip.scss +1 -4
- package/src/examples/ExampleCopyClipboard.vue +2 -2
- package/src/examples/ExamplePopouts.vue +1 -1
- package/src/examples/ExampleTables.vue +164 -0
- package/src/shared/helpers.ts +7 -0
- package/src/style/animation.scss +33 -5
- package/src/style/layout.scss +0 -35
- package/src/style/typography.scss +4 -2
package/package.json
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
|
+
import type { Placement } from '@floating-ui/vue'
|
|
2
3
|
import { autoUpdate, flip, offset, shift, useFloating } from '@floating-ui/vue'
|
|
3
4
|
import { Icon } from '@iconify/vue'
|
|
4
5
|
import { useClipboard } from '@vueuse/core'
|
|
5
6
|
import { computed, onMounted, useSlots, useTemplateRef } from 'vue'
|
|
6
|
-
import { isNil } from '../../shared/helpers'
|
|
7
|
+
import { getPlacementAnimationName, isNil } from '../../shared/helpers'
|
|
7
8
|
import Flex from '../Flex/Flex.vue'
|
|
8
9
|
import './copy-clipboard.scss'
|
|
9
10
|
|
|
@@ -20,12 +21,17 @@ interface Props {
|
|
|
20
21
|
* How long will the copy confirmation tooltip be visible in milliseconds.
|
|
21
22
|
*/
|
|
22
23
|
confirmTime?: number
|
|
24
|
+
/**
|
|
25
|
+
* Tooltip position. Default is top
|
|
26
|
+
*/
|
|
27
|
+
confirmPlacement?: Placement
|
|
23
28
|
}
|
|
24
29
|
|
|
25
30
|
const {
|
|
26
31
|
text,
|
|
27
32
|
confirm,
|
|
28
33
|
confirmTime,
|
|
34
|
+
confirmPlacement = 'top',
|
|
29
35
|
} = defineProps<Props>()
|
|
30
36
|
|
|
31
37
|
const {
|
|
@@ -61,7 +67,8 @@ const tooltipRef = useTemplateRef('tooltip')
|
|
|
61
67
|
const { floatingStyles } = useFloating(anchorRef, tooltipRef, {
|
|
62
68
|
whileElementsMounted: autoUpdate,
|
|
63
69
|
transform: false,
|
|
64
|
-
|
|
70
|
+
strategy: 'fixed',
|
|
71
|
+
placement: confirmPlacement,
|
|
65
72
|
middleware: [
|
|
66
73
|
offset(8),
|
|
67
74
|
shift(),
|
|
@@ -75,7 +82,7 @@ const { floatingStyles } = useFloating(anchorRef, tooltipRef, {
|
|
|
75
82
|
<slot :copy :copied />
|
|
76
83
|
</div>
|
|
77
84
|
|
|
78
|
-
<Transition name="
|
|
85
|
+
<Transition :name="getPlacementAnimationName(confirmPlacement)" mode="in-out">
|
|
79
86
|
<div v-if="copied && (!!parsedConfirm || $slots.confirm)" ref="tooltip" class="vui-clipboard-tooltip" :style="floatingStyles">
|
|
80
87
|
<slot name="confirm">
|
|
81
88
|
<template v-if="typeof parsedConfirm === 'string'">
|
|
@@ -104,10 +104,9 @@ onMounted(() => {
|
|
|
104
104
|
<slot name="trigger" :open :is-open="showMenu" :close :toggle />
|
|
105
105
|
</div>
|
|
106
106
|
|
|
107
|
-
<!-- <Transition name="dropdown" mode="out-in"> -->
|
|
108
107
|
<Popout
|
|
109
|
-
v-if="showMenu"
|
|
110
108
|
ref="dropdown"
|
|
109
|
+
:visible="showMenu"
|
|
111
110
|
:anchor="anchorRef"
|
|
112
111
|
class="vui-dropdown"
|
|
113
112
|
:placement
|
|
@@ -118,17 +117,4 @@ onMounted(() => {
|
|
|
118
117
|
>
|
|
119
118
|
<slot :open :close :toggle :is-open="showMenu" />
|
|
120
119
|
</Popout>
|
|
121
|
-
<!-- </Transition> -->
|
|
122
120
|
</template>
|
|
123
|
-
|
|
124
|
-
<!-- <style scoped lang="scss">
|
|
125
|
-
.dropdown-enter-active,
|
|
126
|
-
.dropdown-leave-active {
|
|
127
|
-
transition: var(--transition-fast);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
.dropdown-enter-from,
|
|
131
|
-
.dropdown-leave-to {
|
|
132
|
-
opacity: 0;
|
|
133
|
-
}
|
|
134
|
-
</style> -->
|
|
@@ -36,7 +36,7 @@ const count = defineModel<number>({
|
|
|
36
36
|
|
|
37
37
|
<template #end>
|
|
38
38
|
<ButtonGroup>
|
|
39
|
-
<Button v-if="!hideDecrement" key="decrease" :disabled="!decrementEnabled" :style="{ 'border-top-left-radius': 0, 'border-bottom-left-radius': 0 }" @click="count -= decrementBy">
|
|
39
|
+
<Button v-if="!hideDecrement" key="decrease" :disabled="!decrementEnabled" :style="{ 'border-top-left-radius': 0, 'border-bottom-left-radius': 0, 'marginRight': '-1px' }" @click="count -= decrementBy">
|
|
40
40
|
<Icon icon="ph:minus" /> {{ decrementBy > 1 ? decrementBy : '' }}
|
|
41
41
|
</Button>
|
|
42
42
|
<Button v-if="!hideIncrement" key="increase" :disabled="!incrementEnabled" @click="count += incrementBy">
|
|
@@ -25,7 +25,7 @@ const show = ref(showPassword)
|
|
|
25
25
|
<template #end>
|
|
26
26
|
<Button
|
|
27
27
|
square
|
|
28
|
-
:
|
|
28
|
+
:aria-label="show ? 'Hide' : 'Reveal'"
|
|
29
29
|
@click="show = !show"
|
|
30
30
|
>
|
|
31
31
|
<Icon :width="18" :height="18" :icon="show ? 'ph:eye-slash' : 'ph:eye'" />
|
|
@@ -4,6 +4,7 @@ import type { Pagination } from './pagination'
|
|
|
4
4
|
import { computed } from 'vue'
|
|
5
5
|
import Button from '../Button/Button.vue'
|
|
6
6
|
import Flex from '../Flex/Flex.vue'
|
|
7
|
+
import Tooltip from '../Tooltip/Tooltip.vue'
|
|
7
8
|
|
|
8
9
|
interface Props {
|
|
9
10
|
numbers?: boolean
|
|
@@ -39,11 +40,21 @@ function setPrev() {
|
|
|
39
40
|
<template>
|
|
40
41
|
<Flex inline class="vui-pagination" gap="xxs">
|
|
41
42
|
<slot name="start">
|
|
42
|
-
<
|
|
43
|
+
<Tooltip v-if="props.firstLast">
|
|
44
|
+
<Button plain :disabled="props.pagination.startPage === props.pagination.currentPage" square icon="ph:caret-double-left" @click="emit('change', props.pagination.startPage)" />
|
|
45
|
+
<template #tooltip>
|
|
46
|
+
<p>First page</p>
|
|
47
|
+
</template>
|
|
48
|
+
</Tooltip>
|
|
43
49
|
</slot>
|
|
44
50
|
|
|
45
51
|
<slot name="prev" :disabled="canPrevPage" :set-page="setPrev">
|
|
46
|
-
<
|
|
52
|
+
<Tooltip v-if="props.prevNext">
|
|
53
|
+
<Button plain :disabled="!canPrevPage" square icon="ph:caret-left" @click="setPrev" />
|
|
54
|
+
<template #tooltip>
|
|
55
|
+
<p>Previous page</p>
|
|
56
|
+
</template>
|
|
57
|
+
</Tooltip>
|
|
47
58
|
</slot>
|
|
48
59
|
|
|
49
60
|
<template v-if="props.numbers">
|
|
@@ -61,17 +72,21 @@ function setPrev() {
|
|
|
61
72
|
</Flex>
|
|
62
73
|
</template>
|
|
63
74
|
<slot name="next" :disabled="canNextPage" :set-page="setNext">
|
|
64
|
-
<
|
|
75
|
+
<Tooltip v-if="props.prevNext">
|
|
76
|
+
<Button plain :disabled="!canNextPage" square icon="ph:caret-right" @click="setNext" />
|
|
77
|
+
<template #tooltip>
|
|
78
|
+
<p>Next page</p>
|
|
79
|
+
</template>
|
|
80
|
+
</Tooltip>
|
|
65
81
|
</slot>
|
|
66
82
|
|
|
67
83
|
<slot name="end">
|
|
68
|
-
<
|
|
84
|
+
<Tooltip v-if="props.firstLast">
|
|
85
|
+
<Button plain :disabled="props.pagination.endPage === props.pagination.currentPage" square icon="ph:caret-double-right" @click="emit('change', props.pagination.endPage)" />
|
|
86
|
+
<template #tooltip>
|
|
87
|
+
<p>Last page</p>
|
|
88
|
+
</template>
|
|
89
|
+
</Tooltip>
|
|
69
90
|
</slot>
|
|
70
91
|
</Flex>
|
|
71
92
|
</template>
|
|
72
|
-
|
|
73
|
-
<style scoped>
|
|
74
|
-
[data-title-top]:before {
|
|
75
|
-
white-space: nowrap;
|
|
76
|
-
}
|
|
77
|
-
</style>
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
2
|
import type { Placement, PopoutMaybeElement } from '../../shared/types'
|
|
3
|
-
import { flip, offset, shift, useFloating } from '@floating-ui/vue'
|
|
3
|
+
import { autoUpdate, flip, offset, shift, useFloating } from '@floating-ui/vue'
|
|
4
4
|
import { onClickOutside } from '@vueuse/core'
|
|
5
|
-
import { toRef, useTemplateRef } from 'vue'
|
|
5
|
+
import { toRef, useTemplateRef, watch } from 'vue'
|
|
6
|
+
import { getPlacementAnimationName } from '../../shared/helpers'
|
|
6
7
|
import './popout.scss'
|
|
7
8
|
|
|
8
9
|
export interface Props {
|
|
@@ -18,10 +19,15 @@ export interface Props {
|
|
|
18
19
|
* Distance between the anchor and the rendered tooltip
|
|
19
20
|
*/
|
|
20
21
|
offset?: number
|
|
22
|
+
/**
|
|
23
|
+
* Set the visibility of the dropdown
|
|
24
|
+
*/
|
|
25
|
+
visible: boolean
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
const props = withDefaults(defineProps<Props>(), {
|
|
24
29
|
offset: 8,
|
|
30
|
+
placement: 'top',
|
|
25
31
|
})
|
|
26
32
|
|
|
27
33
|
const emit = defineEmits<{
|
|
@@ -30,23 +36,38 @@ const emit = defineEmits<{
|
|
|
30
36
|
const popoutRef = useTemplateRef('popout')
|
|
31
37
|
const anchorRef = toRef(props.anchor)
|
|
32
38
|
|
|
33
|
-
const { floatingStyles } = useFloating(anchorRef, popoutRef, {
|
|
39
|
+
const { floatingStyles, update } = useFloating(anchorRef, popoutRef, {
|
|
40
|
+
whileElementsMounted: autoUpdate,
|
|
41
|
+
strategy: 'fixed',
|
|
42
|
+
transform: false,
|
|
34
43
|
placement: props.placement,
|
|
35
44
|
middleware: [
|
|
36
|
-
// ...(props.placement
|
|
37
|
-
// ? []
|
|
38
|
-
// : [autoPlacement()]),
|
|
39
45
|
shift({ padding: 8 }),
|
|
40
46
|
flip(),
|
|
41
47
|
offset(props.offset),
|
|
42
48
|
],
|
|
43
49
|
})
|
|
44
50
|
|
|
51
|
+
// Make sure to update the popout when the anchor is mounted
|
|
52
|
+
watch(() => props.anchor, (value) => {
|
|
53
|
+
if (value) {
|
|
54
|
+
anchorRef.value = value
|
|
55
|
+
update()
|
|
56
|
+
}
|
|
57
|
+
})
|
|
58
|
+
|
|
45
59
|
onClickOutside(popoutRef, () => emit('clickOutside'))
|
|
46
60
|
</script>
|
|
47
61
|
|
|
48
62
|
<template>
|
|
49
|
-
<
|
|
50
|
-
<
|
|
51
|
-
|
|
63
|
+
<Transition :name="getPlacementAnimationName(props.placement)">
|
|
64
|
+
<div
|
|
65
|
+
v-if="props.visible"
|
|
66
|
+
ref="popout"
|
|
67
|
+
:style="floatingStyles"
|
|
68
|
+
class="vui-popout"
|
|
69
|
+
>
|
|
70
|
+
<slot />
|
|
71
|
+
</div>
|
|
72
|
+
</Transition>
|
|
52
73
|
</template>
|
|
@@ -62,9 +62,7 @@ const baseTransform = computed(() => {
|
|
|
62
62
|
<Backdrop v-if="open" @close="emit('close')">
|
|
63
63
|
<div v-if="open" class="vui-sheet" :class="[`vui-sheet-position-${position}`]" :style>
|
|
64
64
|
<div class="vui-sheet-header">
|
|
65
|
-
<
|
|
66
|
-
<slot name="header" :close="() => emit('close')" />
|
|
67
|
-
</div>
|
|
65
|
+
<slot name="header" :close="() => emit('close')" />
|
|
68
66
|
<Button plain square icon="ph:x" @click="emit('close')" />
|
|
69
67
|
</div>
|
|
70
68
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { Header } from './table'
|
|
3
3
|
import { computed } from 'vue'
|
|
4
4
|
import Button from '../Button/Button.vue'
|
|
5
|
+
import Tooltip from '../Tooltip/Tooltip.vue'
|
|
5
6
|
|
|
6
7
|
interface Props {
|
|
7
8
|
/**
|
|
@@ -23,16 +24,16 @@ const sortStateBind = computed(() => {
|
|
|
23
24
|
return
|
|
24
25
|
switch (props.header.sortKey) {
|
|
25
26
|
case 'asc': return {
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
icon: 'ph:sort-ascending',
|
|
28
|
+
tooltipText: 'Ascending',
|
|
28
29
|
}
|
|
29
30
|
case 'desc': return {
|
|
30
|
-
|
|
31
|
-
|
|
31
|
+
icon: 'ph:sort-descending',
|
|
32
|
+
tooltipText: 'Descending',
|
|
32
33
|
}
|
|
33
34
|
default: return {
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
icon: 'ph:arrows-down-up',
|
|
36
|
+
tooltipText: 'Sort column',
|
|
36
37
|
}
|
|
37
38
|
}
|
|
38
39
|
})
|
|
@@ -44,16 +45,22 @@ const sortStateBind = computed(() => {
|
|
|
44
45
|
<slot>
|
|
45
46
|
{{ props.header?.label }}
|
|
46
47
|
</slot>
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
<template v-if="props.sort && props.header">
|
|
49
|
+
<Tooltip placement="top">
|
|
50
|
+
<Button
|
|
51
|
+
:icon="sortStateBind?.icon"
|
|
52
|
+
class="vui-table-sort-button"
|
|
53
|
+
size="s"
|
|
54
|
+
:plain="!!!props.header.sortKey"
|
|
55
|
+
square
|
|
56
|
+
variant="gray"
|
|
57
|
+
@click="props.header.sortToggle"
|
|
58
|
+
/>
|
|
59
|
+
<template #tooltip>
|
|
60
|
+
{{ sortStateBind?.tooltipText }}
|
|
61
|
+
</template>
|
|
62
|
+
</Tooltip>
|
|
63
|
+
</template>
|
|
57
64
|
</div>
|
|
58
65
|
</th>
|
|
59
66
|
</template>
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
.vui-table-overflow {
|
|
2
|
+
display: block;
|
|
3
|
+
max-width: 100%;
|
|
4
|
+
overflow-x: auto;
|
|
5
|
+
overflow-y: visible;
|
|
6
|
+
}
|
|
7
|
+
|
|
1
8
|
.vui-table-container {
|
|
2
9
|
display: block;
|
|
3
10
|
width: 100%;
|
|
@@ -68,7 +75,6 @@
|
|
|
68
75
|
|
|
69
76
|
th,
|
|
70
77
|
td {
|
|
71
|
-
font-size: var(--font-size-m);
|
|
72
78
|
border: none;
|
|
73
79
|
border-left: none !important;
|
|
74
80
|
transition: var(--transition-fast);
|
|
@@ -139,11 +145,6 @@
|
|
|
139
145
|
.vui-table-pagination-wrap {
|
|
140
146
|
padding: var(--space-xs) var(--space-m);
|
|
141
147
|
border-top: 1px solid var(--color-border);
|
|
142
|
-
|
|
143
|
-
p {
|
|
144
|
-
font-size: var(--font-size-s);
|
|
145
|
-
color: var(--color-text-lighter);
|
|
146
|
-
}
|
|
147
148
|
}
|
|
148
149
|
}
|
|
149
150
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
<script setup lang='ts'>
|
|
2
2
|
import type { Placement } from '../../shared/types'
|
|
3
|
-
import { ref, useId, useTemplateRef, watch } from 'vue'
|
|
3
|
+
import { computed, ref, useId, useTemplateRef, watch } from 'vue'
|
|
4
4
|
import Popout from '../Popout/Popout.vue'
|
|
5
5
|
import './tooltip.scss'
|
|
6
6
|
|
|
@@ -52,35 +52,27 @@ watch(hoverAnchor, (isHovering) => {
|
|
|
52
52
|
})
|
|
53
53
|
|
|
54
54
|
const id = useId()
|
|
55
|
+
const anchor = computed(() => popoutAnchorRef.value?.children[0] as HTMLElement | null)
|
|
55
56
|
</script>
|
|
56
57
|
|
|
57
58
|
<template>
|
|
58
59
|
<div
|
|
59
60
|
ref="popoutAnchor"
|
|
60
|
-
|
|
61
|
-
width: 'fit-content',
|
|
62
|
-
}"
|
|
61
|
+
class="popout-anchor"
|
|
63
62
|
:aria-describedby="id"
|
|
64
63
|
@mouseenter="hoverAnchor = true"
|
|
65
64
|
@mouseleave="hoverAnchor = false"
|
|
66
65
|
>
|
|
67
66
|
<slot />
|
|
68
67
|
</div>
|
|
69
|
-
|
|
70
|
-
<Popout v-if="showTooltip" :id :anchor="popoutAnchorRef" class="vui-tooltip" :placement>
|
|
68
|
+
<Popout :id :visible="showTooltip" :anchor class="vui-tooltip" :placement>
|
|
71
69
|
<slot name="tooltip" />
|
|
72
70
|
</Popout>
|
|
73
|
-
<!-- </Transition> -->
|
|
74
71
|
</template>
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
.
|
|
78
|
-
|
|
79
|
-
|
|
73
|
+
<style scoped lang="scss">
|
|
74
|
+
.popout-anchor {
|
|
75
|
+
display: contents;
|
|
76
|
+
width: fit-content;
|
|
80
77
|
}
|
|
81
|
-
|
|
82
|
-
.tooltip-enter-from,
|
|
83
|
-
.tooltip-leave-to {
|
|
84
|
-
opacity: 0;
|
|
85
|
-
}
|
|
86
|
-
</style> -->
|
|
78
|
+
</style>
|
|
@@ -28,9 +28,9 @@ import Flex from '../components/Flex/Flex.vue'
|
|
|
28
28
|
</td>
|
|
29
29
|
</tr>
|
|
30
30
|
<tr>
|
|
31
|
-
<th>Custom confirm popup</th>
|
|
31
|
+
<th>Custom confirm popup & positioned at the right</th>
|
|
32
32
|
<td>
|
|
33
|
-
<CopyClipboard text="Copy me!" confirm>
|
|
33
|
+
<CopyClipboard text="Copy me!" confirm confirm-placement="right">
|
|
34
34
|
<Button>Copy me!</Button>
|
|
35
35
|
<template #confirm>
|
|
36
36
|
<Flex column gap="s" y-center>
|
|
@@ -26,7 +26,7 @@ const open = ref(false)
|
|
|
26
26
|
This popout has offset of <code>32</code> and its placement is <code>bottom-start</code>. It also has an attached event to <code>clickOutside</code> which is fired when user clicks outside of the popout. In that case, we manually close it.
|
|
27
27
|
</p>
|
|
28
28
|
</Flex>
|
|
29
|
-
<Popout
|
|
29
|
+
<Popout :visible="open" :anchor="anchRef" class="test-popout" :offset="32" placement="bottom-start" @click-outside="open = false">
|
|
30
30
|
<h3>Popout content</h3>
|
|
31
31
|
<p>Lorem ipsum dolor, sit amet consectetur adipisicing elit. Dolorem facere eligendi ex, alias itaque molestiae, vero animi, vitae vel fuga corporis aut consectetur temporibus ipsum placeat dolores perferendis. Deleniti, et!</p>
|
|
32
32
|
</Popout>
|
|
@@ -6,6 +6,7 @@ import { paginate } from '../components/Pagination/pagination'
|
|
|
6
6
|
import Pagination from '../components/Pagination/Pagination.vue'
|
|
7
7
|
import * as Table from '../components/Table/index'
|
|
8
8
|
import { defineTable } from '../components/Table/table'
|
|
9
|
+
import Tooltip from '../components/Tooltip/Tooltip.vue'
|
|
9
10
|
|
|
10
11
|
interface Item {
|
|
11
12
|
'ID Nation': string
|
|
@@ -191,5 +192,168 @@ const exampleToRender = computed(() => testData.slice(paginationExample.value.st
|
|
|
191
192
|
<Divider :size="40" class="w-40" />
|
|
192
193
|
|
|
193
194
|
<p>The <code>defineTable</code> hook can also be used with other UI components. Not just tables. That's why all the table interactivity is not within the component, but in a hook. It's very flexible and allows custom functionality.</p>
|
|
195
|
+
|
|
196
|
+
<Divider :size="40" />
|
|
197
|
+
|
|
198
|
+
<h5 class="mb-s">
|
|
199
|
+
Responsitivity
|
|
200
|
+
</h5>
|
|
201
|
+
|
|
202
|
+
<p class="mb-m">
|
|
203
|
+
Table can be made responsible if they overflow their width and are wrapped in a <code>.vui-table-container</code> element.
|
|
204
|
+
</p>
|
|
205
|
+
|
|
206
|
+
<div class="container container-m">
|
|
207
|
+
<div class="vui-table-overflow">
|
|
208
|
+
<table>
|
|
209
|
+
<thead>
|
|
210
|
+
<tr>
|
|
211
|
+
<th>
|
|
212
|
+
<Tooltip placement="top">
|
|
213
|
+
ID
|
|
214
|
+
<template #tooltip>
|
|
215
|
+
<p>ID</p>
|
|
216
|
+
</template>
|
|
217
|
+
</Tooltip>
|
|
218
|
+
</th>
|
|
219
|
+
<th>
|
|
220
|
+
<Tooltip placement="top">
|
|
221
|
+
Name
|
|
222
|
+
<template #tooltip>
|
|
223
|
+
<p>Name</p>
|
|
224
|
+
</template>
|
|
225
|
+
</Tooltip>
|
|
226
|
+
</th>
|
|
227
|
+
<th>
|
|
228
|
+
<Tooltip placement="top">
|
|
229
|
+
Email
|
|
230
|
+
<template #tooltip>
|
|
231
|
+
<p>Email</p>
|
|
232
|
+
</template>
|
|
233
|
+
</Tooltip>
|
|
234
|
+
</th>
|
|
235
|
+
<th>
|
|
236
|
+
<Tooltip placement="top">
|
|
237
|
+
Phone
|
|
238
|
+
<template #tooltip>
|
|
239
|
+
<p>Phone</p>
|
|
240
|
+
</template>
|
|
241
|
+
</Tooltip>
|
|
242
|
+
</th>
|
|
243
|
+
<th>
|
|
244
|
+
<Tooltip placement="top">
|
|
245
|
+
Address
|
|
246
|
+
<template #tooltip>
|
|
247
|
+
<p>Address</p>
|
|
248
|
+
</template>
|
|
249
|
+
</Tooltip>
|
|
250
|
+
</th>
|
|
251
|
+
<th>
|
|
252
|
+
<Tooltip placement="top">
|
|
253
|
+
City
|
|
254
|
+
<template #tooltip>
|
|
255
|
+
<p>City</p>
|
|
256
|
+
</template>
|
|
257
|
+
</Tooltip>
|
|
258
|
+
</th>
|
|
259
|
+
<th>
|
|
260
|
+
<Tooltip placement="top">
|
|
261
|
+
State
|
|
262
|
+
<template #tooltip>
|
|
263
|
+
<p>State</p>
|
|
264
|
+
</template>
|
|
265
|
+
</Tooltip>
|
|
266
|
+
</th>
|
|
267
|
+
<th>
|
|
268
|
+
<Tooltip placement="top">
|
|
269
|
+
Zip
|
|
270
|
+
<template #tooltip>
|
|
271
|
+
<p>Zip</p>
|
|
272
|
+
</template>
|
|
273
|
+
</Tooltip>
|
|
274
|
+
</th>
|
|
275
|
+
<th>
|
|
276
|
+
<Tooltip placement="top">
|
|
277
|
+
Country
|
|
278
|
+
<template #tooltip>
|
|
279
|
+
<p>Country</p>
|
|
280
|
+
</template>
|
|
281
|
+
</Tooltip>
|
|
282
|
+
</th>
|
|
283
|
+
<th>
|
|
284
|
+
<Tooltip placement="top">
|
|
285
|
+
Status
|
|
286
|
+
<template #tooltip>
|
|
287
|
+
<p>Status</p>
|
|
288
|
+
</template>
|
|
289
|
+
</Tooltip>
|
|
290
|
+
</th>
|
|
291
|
+
</tr>
|
|
292
|
+
</thead>
|
|
293
|
+
<tbody>
|
|
294
|
+
<tr>
|
|
295
|
+
<td>001</td>
|
|
296
|
+
<td>John Doe</td>
|
|
297
|
+
<td>john.doe@example.com</td>
|
|
298
|
+
<td>(555) 123-4567</td>
|
|
299
|
+
<td>123 Main St</td>
|
|
300
|
+
<td>New York</td>
|
|
301
|
+
<td>NY</td>
|
|
302
|
+
<td>10001</td>
|
|
303
|
+
<td>USA</td>
|
|
304
|
+
<td>Active</td>
|
|
305
|
+
</tr>
|
|
306
|
+
<tr>
|
|
307
|
+
<td>002</td>
|
|
308
|
+
<td>Jane Smith</td>
|
|
309
|
+
<td>jane.smith@example.com</td>
|
|
310
|
+
<td>(555) 987-6543</td>
|
|
311
|
+
<td>456 Oak Ave</td>
|
|
312
|
+
<td>Los Angeles</td>
|
|
313
|
+
<td>CA</td>
|
|
314
|
+
<td>90001</td>
|
|
315
|
+
<td>USA</td>
|
|
316
|
+
<td>Inactive</td>
|
|
317
|
+
</tr>
|
|
318
|
+
<tr>
|
|
319
|
+
<td>003</td>
|
|
320
|
+
<td>Robert Johnson</td>
|
|
321
|
+
<td>robert.j@example.com</td>
|
|
322
|
+
<td>(555) 456-7890</td>
|
|
323
|
+
<td>789 Pine Blvd</td>
|
|
324
|
+
<td>Chicago</td>
|
|
325
|
+
<td>IL</td>
|
|
326
|
+
<td>60601</td>
|
|
327
|
+
<td>USA</td>
|
|
328
|
+
<td>Active</td>
|
|
329
|
+
</tr>
|
|
330
|
+
<tr>
|
|
331
|
+
<td>004</td>
|
|
332
|
+
<td>Emily Davis</td>
|
|
333
|
+
<td>emily.d@example.com</td>
|
|
334
|
+
<td>(555) 234-5678</td>
|
|
335
|
+
<td>321 Cedar Ln</td>
|
|
336
|
+
<td>Houston</td>
|
|
337
|
+
<td>TX</td>
|
|
338
|
+
<td>77001</td>
|
|
339
|
+
<td>USA</td>
|
|
340
|
+
<td>Pending</td>
|
|
341
|
+
</tr>
|
|
342
|
+
<tr>
|
|
343
|
+
<td>005</td>
|
|
344
|
+
<td>Michael Wilson</td>
|
|
345
|
+
<td>michael.w@example.com</td>
|
|
346
|
+
<td>(555) 876-5432</td>
|
|
347
|
+
<td>654 Maple Dr</td>
|
|
348
|
+
<td>Miami</td>
|
|
349
|
+
<td>FL</td>
|
|
350
|
+
<td>33101</td>
|
|
351
|
+
<td>USA</td>
|
|
352
|
+
<td>Active</td>
|
|
353
|
+
</tr>
|
|
354
|
+
</tbody>
|
|
355
|
+
</table>
|
|
356
|
+
</div>
|
|
357
|
+
</div>
|
|
194
358
|
</div>
|
|
195
359
|
</template>
|
package/src/shared/helpers.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { Placement } from '@floating-ui/vue'
|
|
2
|
+
|
|
1
3
|
export function createArray(length: number, startOffset: number = 0): number[] {
|
|
2
4
|
return Array
|
|
3
5
|
.from({ length })
|
|
@@ -115,3 +117,8 @@ export function isObjectInSet(set: Set<any>, obj: any): boolean {
|
|
|
115
117
|
|
|
116
118
|
return false
|
|
117
119
|
}
|
|
120
|
+
|
|
121
|
+
export function getPlacementAnimationName(position: Placement): string {
|
|
122
|
+
const suffix = position.includes('-') ? position.split('-')[0] : position
|
|
123
|
+
return `fade-${suffix}`
|
|
124
|
+
}
|