@nexxtmove/ui 0.1.24 → 0.1.26
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/index.d.ts +75 -1
- package/dist/index.js +1500 -1066
- package/dist/nuxt.js +20 -17
- package/package.json +1 -1
- package/src/components/AnimatedNumber/AnimatedNumber.vue +4 -0
- package/src/components/TimelineEvent/TimelineEvent.stories.ts +291 -0
- package/src/components/TimelineEvent/TimelineEvent.test.ts +166 -0
- package/src/components/TimelineEvent/TimelineEvent.vue +115 -0
- package/src/components/TimelineEvent/TimelineTypes.ts +236 -0
- package/src/components/TimelinePhaseblock/TimelinePhaseblock.stories.ts +198 -0
- package/src/components/TimelinePhaseblock/TimelinePhaseblock.test.ts +283 -0
- package/src/components/TimelinePhaseblock/TimelinePhaseblock.vue +158 -0
- package/src/components/Tooltip/Tooltip.stories.ts +146 -0
- package/src/components/Tooltip/Tooltip.test.ts +122 -0
- package/src/components/Tooltip/Tooltip.vue +49 -0
- package/src/components.json +4 -1
- package/src/index.ts +3 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest'
|
|
2
|
+
import { mount } from '@vue/test-utils'
|
|
3
|
+
import { defineComponent } from 'vue'
|
|
4
|
+
import Tooltip from './Tooltip.vue'
|
|
5
|
+
|
|
6
|
+
// Stub reka-ui components so we can inspect slots and props without portal/hover behaviour
|
|
7
|
+
const TooltipProviderStub = defineComponent({ template: '<div><slot /></div>' })
|
|
8
|
+
const TooltipRootStub = defineComponent({
|
|
9
|
+
props: ['delayDuration', 'disableHoverableContent'],
|
|
10
|
+
template:
|
|
11
|
+
'<div :data-delay="delayDuration" :data-disable-hoverable="disableHoverableContent"><slot /></div>',
|
|
12
|
+
})
|
|
13
|
+
const TooltipTriggerStub = defineComponent({ template: '<div><slot /></div>' })
|
|
14
|
+
const TooltipPortalStub = defineComponent({ template: '<div><slot /></div>' })
|
|
15
|
+
const TooltipContentStub = defineComponent({
|
|
16
|
+
props: ['side', 'sideOffset', 'align'],
|
|
17
|
+
template:
|
|
18
|
+
'<div class="tooltip-content" :data-side="side" :data-side-offset="sideOffset" :data-align="align"><slot /></div>',
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
const stubs = {
|
|
22
|
+
TooltipProvider: TooltipProviderStub,
|
|
23
|
+
TooltipRoot: TooltipRootStub,
|
|
24
|
+
TooltipTrigger: TooltipTriggerStub,
|
|
25
|
+
TooltipPortal: TooltipPortalStub,
|
|
26
|
+
TooltipContent: TooltipContentStub,
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const mountTooltip = (slots = {}, props = {}) => mount(Tooltip, { props, slots, global: { stubs } })
|
|
30
|
+
|
|
31
|
+
describe('Tooltip', () => {
|
|
32
|
+
describe('trigger slot', () => {
|
|
33
|
+
it('renders the default slot as the trigger', () => {
|
|
34
|
+
const wrapper = mountTooltip({ default: '<button>Click me</button>' })
|
|
35
|
+
expect(wrapper.find('button').exists()).toBe(true)
|
|
36
|
+
expect(wrapper.find('button').text()).toBe('Click me')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
it('renders plain text in the default slot', () => {
|
|
40
|
+
const wrapper = mountTooltip({ default: 'Trigger text' })
|
|
41
|
+
expect(wrapper.text()).toContain('Trigger text')
|
|
42
|
+
})
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
describe('tooltip slot', () => {
|
|
46
|
+
it('renders the tooltip slot content', () => {
|
|
47
|
+
const wrapper = mountTooltip({ tooltip: 'Tooltip message' })
|
|
48
|
+
expect(wrapper.find('.tooltip-content').text()).toContain('Tooltip message')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('renders rich HTML in the tooltip slot', () => {
|
|
52
|
+
const wrapper = mountTooltip({ tooltip: '<strong>Bold text</strong>' })
|
|
53
|
+
expect(wrapper.find('.tooltip-content strong').exists()).toBe(true)
|
|
54
|
+
expect(wrapper.find('.tooltip-content strong').text()).toBe('Bold text')
|
|
55
|
+
})
|
|
56
|
+
|
|
57
|
+
it('renders an empty tooltip content when no tooltip slot is provided', () => {
|
|
58
|
+
const wrapper = mountTooltip()
|
|
59
|
+
expect(wrapper.find('.tooltip-content').text()).toBe('')
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe('delay prop', () => {
|
|
64
|
+
it('passes the delay to TooltipRoot', () => {
|
|
65
|
+
const wrapper = mountTooltip({}, { delay: 500 })
|
|
66
|
+
expect(wrapper.findComponent(TooltipRootStub).attributes('data-delay')).toBe('500')
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
it('defaults delay to 0', () => {
|
|
70
|
+
const wrapper = mountTooltip()
|
|
71
|
+
expect(wrapper.findComponent(TooltipRootStub).attributes('data-delay')).toBe('0')
|
|
72
|
+
})
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
describe('side prop', () => {
|
|
76
|
+
it('passes the side to TooltipContent', () => {
|
|
77
|
+
const wrapper = mountTooltip({}, { side: 'bottom' })
|
|
78
|
+
expect(wrapper.find('.tooltip-content').attributes('data-side')).toBe('bottom')
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
it('defaults side to top', () => {
|
|
82
|
+
const wrapper = mountTooltip()
|
|
83
|
+
expect(wrapper.find('.tooltip-content').attributes('data-side')).toBe('top')
|
|
84
|
+
})
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
describe('sideOffset prop', () => {
|
|
88
|
+
it('passes the sideOffset to TooltipContent', () => {
|
|
89
|
+
const wrapper = mountTooltip({}, { sideOffset: 16 })
|
|
90
|
+
expect(wrapper.find('.tooltip-content').attributes('data-side-offset')).toBe('16')
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
it('defaults sideOffset to 8', () => {
|
|
94
|
+
const wrapper = mountTooltip()
|
|
95
|
+
expect(wrapper.find('.tooltip-content').attributes('data-side-offset')).toBe('8')
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
|
|
99
|
+
describe('align prop', () => {
|
|
100
|
+
it('passes the align to TooltipContent', () => {
|
|
101
|
+
const wrapper = mountTooltip({}, { align: 'start' })
|
|
102
|
+
expect(wrapper.find('.tooltip-content').attributes('data-align')).toBe('start')
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
it('defaults align to center', () => {
|
|
106
|
+
const wrapper = mountTooltip()
|
|
107
|
+
expect(wrapper.find('.tooltip-content').attributes('data-align')).toBe('center')
|
|
108
|
+
})
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
describe('disableHoverableContent prop', () => {
|
|
112
|
+
it('passes disableHoverableContent to TooltipRoot', () => {
|
|
113
|
+
const wrapper = mountTooltip({}, { disableHoverableContent: true })
|
|
114
|
+
expect(wrapper.findComponent(TooltipRootStub).props('disableHoverableContent')).toBe(true)
|
|
115
|
+
})
|
|
116
|
+
|
|
117
|
+
it('defaults disableHoverableContent to false', () => {
|
|
118
|
+
const wrapper = mountTooltip()
|
|
119
|
+
expect(wrapper.findComponent(TooltipRootStub).props('disableHoverableContent')).toBe(false)
|
|
120
|
+
})
|
|
121
|
+
})
|
|
122
|
+
})
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
import {
|
|
3
|
+
TooltipContent,
|
|
4
|
+
TooltipPortal,
|
|
5
|
+
TooltipProvider,
|
|
6
|
+
TooltipRoot,
|
|
7
|
+
TooltipTrigger,
|
|
8
|
+
} from 'reka-ui'
|
|
9
|
+
|
|
10
|
+
defineOptions({
|
|
11
|
+
name: 'NexxtTooltip',
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
interface NexxtTooltip {
|
|
15
|
+
delay?: number
|
|
16
|
+
side?: 'top' | 'right' | 'bottom' | 'left'
|
|
17
|
+
sideOffset?: number
|
|
18
|
+
align?: 'start' | 'center' | 'end'
|
|
19
|
+
disableHoverableContent?: boolean
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
delay = 0,
|
|
24
|
+
side = 'top',
|
|
25
|
+
sideOffset = 8,
|
|
26
|
+
align = 'center',
|
|
27
|
+
disableHoverableContent = false,
|
|
28
|
+
} = defineProps<NexxtTooltip>()
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<template>
|
|
32
|
+
<TooltipProvider>
|
|
33
|
+
<TooltipRoot :delay-duration="delay" :disable-hoverable-content="disableHoverableContent">
|
|
34
|
+
<TooltipTrigger as-child>
|
|
35
|
+
<slot />
|
|
36
|
+
</TooltipTrigger>
|
|
37
|
+
<TooltipPortal>
|
|
38
|
+
<TooltipContent
|
|
39
|
+
:side="side"
|
|
40
|
+
:side-offset="sideOffset"
|
|
41
|
+
:align="align"
|
|
42
|
+
class="z-50 rounded-lg border border-gray-200 bg-white px-3 py-2 shadow-xs"
|
|
43
|
+
>
|
|
44
|
+
<slot name="tooltip" />
|
|
45
|
+
</TooltipContent>
|
|
46
|
+
</TooltipPortal>
|
|
47
|
+
</TooltipRoot>
|
|
48
|
+
</TooltipProvider>
|
|
49
|
+
</template>
|
package/src/components.json
CHANGED
|
@@ -12,5 +12,8 @@
|
|
|
12
12
|
"NexxtSocialMediaCustomTemplate": "components/SocialMediaCustomTemplate/SocialMediaCustomTemplate.vue",
|
|
13
13
|
"NexxtSocialMediaTemplate": "components/SocialMediaTemplate/SocialMediaTemplate.vue",
|
|
14
14
|
"NexxtSocialMediaType": "components/SocialMediaType/SocialMediaType.vue",
|
|
15
|
-
"NexxtStepperHeader": "components/StepperHeader/StepperHeader.vue"
|
|
15
|
+
"NexxtStepperHeader": "components/StepperHeader/StepperHeader.vue",
|
|
16
|
+
"NexxtTimelineEvent": "components/TimelineEvent/TimelineEvent.vue",
|
|
17
|
+
"NexxtTimelinePhaseblock": "components/TimelinePhaseblock/TimelinePhaseblock.vue",
|
|
18
|
+
"NexxtTooltip": "components/Tooltip/Tooltip.vue"
|
|
16
19
|
}
|
package/src/index.ts
CHANGED
|
@@ -13,3 +13,6 @@ export { default as NexxtSocialMediaCustomTemplate } from './components/SocialMe
|
|
|
13
13
|
export { default as NexxtSocialMediaTemplate } from './components/SocialMediaTemplate/SocialMediaTemplate.vue'
|
|
14
14
|
export { default as NexxtSocialMediaType } from './components/SocialMediaType/SocialMediaType.vue'
|
|
15
15
|
export { default as NexxtStepperHeader } from './components/StepperHeader/StepperHeader.vue'
|
|
16
|
+
export { default as NexxtTimelineEvent } from './components/TimelineEvent/TimelineEvent.vue'
|
|
17
|
+
export { default as NexxtTimelinePhaseblock } from './components/TimelinePhaseblock/TimelinePhaseblock.vue'
|
|
18
|
+
export { default as NexxtTooltip } from './components/Tooltip/Tooltip.vue'
|