@weni/unnnic-system 3.14.0-alpha-teleports.0 → 3.14.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 +1 -9
- package/dist/{es-0d53b5b2.mjs → es-91ae9eed.mjs} +1 -1
- package/dist/{index-d7070de8.mjs → index-3b503557.mjs} +26122 -28965
- package/dist/index.d.ts +1485 -4826
- package/dist/{pt-br-bf4e1f97.mjs → pt-br-9553a558.mjs} +1 -1
- package/dist/style.css +1 -1
- package/dist/unnnic.mjs +204 -232
- package/dist/unnnic.umd.js +44 -48
- package/package.json +2 -3
- package/src/assets/scss/tailwind.scss +0 -8
- package/src/components/Alert/__tests__/__snapshots__/Alert.spec.js.snap +1 -1
- package/src/components/ChartFunnel/DefaultFunnel/ChartDefaultFunnelBase.vue +1 -2
- package/src/components/ChartFunnel/SvgFunnel/ChartFunnelTwoRows.vue +60 -61
- package/src/components/CheckboxGroup/CheckboxGroup.vue +7 -5
- package/src/components/Chip/Chip.vue +1 -1
- package/src/components/DatePicker/DatePicker.vue +1 -10
- package/src/components/Drawer/Drawer.vue +270 -180
- package/src/components/Drawer/__tests__/Drawer.spec.js +43 -32
- package/src/components/Drawer/__tests__/__snapshots__/Drawer.spec.js.snap +19 -18
- package/src/components/FormElement/FormElement.vue +96 -87
- package/src/components/InputDatePicker/InputDatePicker.vue +73 -68
- package/src/components/InputDatePicker/__test__/InputDatePicker.spec.js +24 -31
- package/src/components/ModalDialog/ModalDialog.vue +154 -63
- package/src/components/ModalDialog/__tests__/ModalDialog.spec.js +210 -30
- package/src/components/ModalDialog/__tests__/__snapshots__/ModalDialog.spec.js.snap +22 -1
- package/src/components/Radio/Radio.vue +12 -6
- package/src/components/Radio/__test__/Radio.spec.js +3 -1
- package/src/components/RadioGroup/RadioGroup.vue +18 -10
- package/src/components/Select/__tests__/SelectItem.spec.js +35 -15
- package/src/components/Switch/Switch.vue +10 -3
- package/src/components/Tab/__test__/__snapshots__/Tab.spec.js.snap +1 -3
- package/src/components/TemplatePreview/TemplatePreview.vue +28 -25
- package/src/components/TemplatePreview/TemplatePreviewModal.vue +10 -10
- package/src/components/TemplatePreview/types.d.ts +3 -3
- package/src/components/Toast/Toast.vue +1 -4
- package/src/components/Toast/ToastManager.ts +1 -4
- package/src/components/Toast/__tests__/ToastManager.spec.js +6 -10
- package/src/components/ToolTip/ToolTip.vue +177 -25
- package/src/components/ToolTip/__tests__/ToolTip.spec.js +61 -339
- package/src/components/index.ts +0 -56
- package/src/components/ui/popover/PopoverContent.vue +4 -7
- package/src/components/ui/popover/PopoverTrigger.vue +1 -5
- package/src/index.ts +2 -9
- package/src/stories/Drawer.stories.js +1 -1
- package/src/stories/ModalDialog.mdx +0 -3
- package/src/stories/ModalDialog.stories.js +1 -96
- package/src/stories/TemplatePreview.stories.js +27 -27
- package/src/stories/TemplatePreviewModal.stories.js +31 -31
- package/src/components/ui/dialog/Dialog.vue +0 -19
- package/src/components/ui/dialog/DialogClose.vue +0 -29
- package/src/components/ui/dialog/DialogContent.vue +0 -140
- package/src/components/ui/dialog/DialogFooter.vue +0 -50
- package/src/components/ui/dialog/DialogHeader.vue +0 -83
- package/src/components/ui/dialog/DialogTitle.vue +0 -38
- package/src/components/ui/dialog/DialogTrigger.vue +0 -16
- package/src/components/ui/dialog/index.ts +0 -7
- package/src/components/ui/drawer/Drawer.vue +0 -27
- package/src/components/ui/drawer/DrawerClose.vue +0 -31
- package/src/components/ui/drawer/DrawerContent.vue +0 -113
- package/src/components/ui/drawer/DrawerDescription.vue +0 -40
- package/src/components/ui/drawer/DrawerFooter.vue +0 -38
- package/src/components/ui/drawer/DrawerHeader.vue +0 -57
- package/src/components/ui/drawer/DrawerOverlay.vue +0 -33
- package/src/components/ui/drawer/DrawerTitle.vue +0 -37
- package/src/components/ui/drawer/DrawerTrigger.vue +0 -31
- package/src/components/ui/drawer/index.ts +0 -10
- package/src/components/ui/tooltip/Tooltip.vue +0 -21
- package/src/components/ui/tooltip/TooltipContent.vue +0 -77
- package/src/components/ui/tooltip/TooltipTrigger.vue +0 -24
- package/src/components/ui/tooltip/index.ts +0 -3
- package/src/lib/__tests__/teleport-target.spec.ts +0 -73
- package/src/lib/layer-manager.ts +0 -64
- package/src/lib/teleport-target.ts +0 -46
- package/src/stories/Dialog.stories.js +0 -832
- package/src/stories/DrawerNext.stories.js +0 -611
- package/src/stories/LayerManager.docs.mdx +0 -40
- package/src/stories/LayerManager.stories.js +0 -407
|
@@ -1,25 +1,23 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<
|
|
3
|
-
|
|
4
|
-
:
|
|
5
|
-
|
|
2
|
+
<div
|
|
3
|
+
ref="tooltip"
|
|
4
|
+
:class="{
|
|
5
|
+
'unnnic-tooltip': enabled || forceOpen,
|
|
6
|
+
'force-open': forceOpen,
|
|
7
|
+
}"
|
|
8
|
+
@mouseover="handleResize"
|
|
6
9
|
>
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<TooltipContent
|
|
10
|
+
<slot />
|
|
11
|
+
<span
|
|
12
|
+
v-show="enabled || forceOpen"
|
|
13
|
+
ref="label"
|
|
12
14
|
:class="['unnnic-tooltip-label', `unnnic-tooltip-label-${side}`]"
|
|
13
|
-
:style="{ maxWidth: maxWidth }"
|
|
14
|
-
|
|
15
|
-
data-testid="tooltip-content"
|
|
15
|
+
:style="{ maxWidth: maxWidth, left: leftPos, top: topPos }"
|
|
16
|
+
data-testid="tooltip-label"
|
|
16
17
|
>
|
|
17
18
|
<template v-if="enableHtml">
|
|
18
19
|
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
19
|
-
<section
|
|
20
|
-
v-html="text"
|
|
21
|
-
data-testid="tooltip-html-content"
|
|
22
|
-
></section>
|
|
20
|
+
<section v-html="text"></section>
|
|
23
21
|
</template>
|
|
24
22
|
<template
|
|
25
23
|
v-for="(line, index) in text.split('\n')"
|
|
@@ -29,20 +27,22 @@
|
|
|
29
27
|
{{ line }}
|
|
30
28
|
<br />
|
|
31
29
|
</template>
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
|
|
31
|
+
<template v-if="shortcutText">
|
|
32
|
+
<span
|
|
33
|
+
class="unnnic-tooltip-label-shortcut"
|
|
34
|
+
data-testid="tooltip-label-shortcut"
|
|
35
|
+
>
|
|
36
|
+
{{ shortcutText }}
|
|
37
|
+
</span>
|
|
38
|
+
</template>
|
|
39
|
+
</span>
|
|
40
|
+
</div>
|
|
34
41
|
</template>
|
|
35
42
|
|
|
36
43
|
<script>
|
|
37
|
-
import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';
|
|
38
|
-
|
|
39
44
|
export default {
|
|
40
45
|
name: 'UnnnicTooltip',
|
|
41
|
-
components: {
|
|
42
|
-
Tooltip,
|
|
43
|
-
TooltipTrigger,
|
|
44
|
-
TooltipContent,
|
|
45
|
-
},
|
|
46
46
|
props: {
|
|
47
47
|
text: {
|
|
48
48
|
type: String,
|
|
@@ -67,10 +67,162 @@ export default {
|
|
|
67
67
|
type: String,
|
|
68
68
|
default: '',
|
|
69
69
|
},
|
|
70
|
+
shortcutText: {
|
|
71
|
+
type: String,
|
|
72
|
+
default: null,
|
|
73
|
+
},
|
|
70
74
|
enableHtml: {
|
|
71
75
|
type: Boolean,
|
|
72
76
|
default: false,
|
|
73
77
|
},
|
|
74
78
|
},
|
|
79
|
+
data() {
|
|
80
|
+
return {
|
|
81
|
+
topPos: null,
|
|
82
|
+
leftPos: null,
|
|
83
|
+
};
|
|
84
|
+
},
|
|
85
|
+
watch: {
|
|
86
|
+
side() {
|
|
87
|
+
this.getRightPost(this.$refs.tooltip);
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
mounted() {
|
|
91
|
+
this.handleResize();
|
|
92
|
+
|
|
93
|
+
window.addEventListener('scroll', this.handleResize);
|
|
94
|
+
window.addEventListener('resize', this.handleResize);
|
|
95
|
+
},
|
|
96
|
+
unmounted() {
|
|
97
|
+
window.removeEventListener('scroll', this.handleResize);
|
|
98
|
+
window.removeEventListener('resize', this.handleResize);
|
|
99
|
+
},
|
|
100
|
+
methods: {
|
|
101
|
+
handleResize() {
|
|
102
|
+
this.getRightPost(this.$refs.tooltip);
|
|
103
|
+
},
|
|
104
|
+
getRightPost(element) {
|
|
105
|
+
const elementPos = element.getBoundingClientRect();
|
|
106
|
+
|
|
107
|
+
if (element && this.$refs.label) {
|
|
108
|
+
if (this.side === 'right') {
|
|
109
|
+
this.leftPos = `${elementPos.x + elementPos.width + 8}px`;
|
|
110
|
+
this.topPos = `${elementPos.y + elementPos.height / 2 - this.$refs.label.offsetHeight / 2}px`;
|
|
111
|
+
} else if (this.side === 'left') {
|
|
112
|
+
this.leftPos = `${elementPos.x - this.$refs.label.offsetWidth - 8}px`;
|
|
113
|
+
this.topPos = `${elementPos.y + elementPos.height / 2 - this.$refs.label.offsetHeight / 2}px`;
|
|
114
|
+
} else if (this.side === 'top') {
|
|
115
|
+
this.leftPos = `${elementPos.x + elementPos.width / 2 - this.$refs.label.clientWidth / 2}px`;
|
|
116
|
+
this.topPos = `${elementPos.y - this.$refs.label.offsetHeight - 8}px`;
|
|
117
|
+
} else if (this.side === 'bottom') {
|
|
118
|
+
this.leftPos = `${elementPos.x + elementPos.width / 2 - this.$refs.label.clientWidth / 2}px`;
|
|
119
|
+
this.topPos = `${elementPos.y + elementPos.height + 8}px`;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
},
|
|
123
|
+
},
|
|
75
124
|
};
|
|
76
125
|
</script>
|
|
126
|
+
|
|
127
|
+
<style lang="scss" scoped>
|
|
128
|
+
@use '@/assets/scss/unnnic' as *;
|
|
129
|
+
|
|
130
|
+
.unnnic-tooltip {
|
|
131
|
+
position: relative;
|
|
132
|
+
display: inline-block;
|
|
133
|
+
overflow-wrap: break-word;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.unnnic-tooltip-label {
|
|
137
|
+
z-index: 1;
|
|
138
|
+
visibility: hidden;
|
|
139
|
+
text-align: center;
|
|
140
|
+
position: fixed;
|
|
141
|
+
width: max-content;
|
|
142
|
+
min-width: 2 * $unnnic-font-size;
|
|
143
|
+
box-sizing: border-box;
|
|
144
|
+
width: auto;
|
|
145
|
+
display: flex;
|
|
146
|
+
justify-content: center;
|
|
147
|
+
gap: $unnnic-spacing-xs;
|
|
148
|
+
align-items: center;
|
|
149
|
+
|
|
150
|
+
background-color: $unnnic-color-neutral-black;
|
|
151
|
+
color: $unnnic-color-neutral-snow;
|
|
152
|
+
border-radius: $unnnic-border-radius-sm;
|
|
153
|
+
padding: $unnnic-inset-nano;
|
|
154
|
+
box-shadow: $unnnic-shadow-level-near;
|
|
155
|
+
font-size: $unnnic-font-size-body-md;
|
|
156
|
+
font-family: $unnnic-font-family-secondary;
|
|
157
|
+
font-weight: $unnnic-font-weight-regular;
|
|
158
|
+
line-height: ($unnnic-font-size-body-md + $unnnic-line-height-medium);
|
|
159
|
+
|
|
160
|
+
&::after {
|
|
161
|
+
content: '';
|
|
162
|
+
position: absolute;
|
|
163
|
+
border-width: 5px;
|
|
164
|
+
border-style: solid;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
&-top {
|
|
168
|
+
position: fixed;
|
|
169
|
+
&::after {
|
|
170
|
+
top: 100%;
|
|
171
|
+
left: 50%;
|
|
172
|
+
margin-left: -5px;
|
|
173
|
+
border-color: $unnnic-color-neutral-black transparent transparent
|
|
174
|
+
transparent;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
&-bottom {
|
|
179
|
+
position: fixed;
|
|
180
|
+
&::after {
|
|
181
|
+
bottom: 100%;
|
|
182
|
+
left: 50%;
|
|
183
|
+
margin-left: -5px;
|
|
184
|
+
border-color: transparent transparent $unnnic-color-neutral-black
|
|
185
|
+
transparent;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
&-right {
|
|
189
|
+
position: fixed;
|
|
190
|
+
&::after {
|
|
191
|
+
top: 50%;
|
|
192
|
+
right: 100%;
|
|
193
|
+
margin-top: -5px;
|
|
194
|
+
border-color: transparent $unnnic-color-neutral-black transparent
|
|
195
|
+
transparent;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
&-left {
|
|
199
|
+
position: fixed;
|
|
200
|
+
&::after {
|
|
201
|
+
top: 50%;
|
|
202
|
+
left: 100%;
|
|
203
|
+
margin-top: -5px;
|
|
204
|
+
border-color: transparent transparent transparent
|
|
205
|
+
$unnnic-color-neutral-black;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
&-shortcut {
|
|
210
|
+
background-color: $unnnic-color-neutral-darkest;
|
|
211
|
+
border-radius: $unnnic-border-radius-sm;
|
|
212
|
+
padding: calc($unnnic-inset-nano / 2) $unnnic-inset-nano;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.unnnic-tooltip.force-open {
|
|
217
|
+
.unnnic-tooltip-label {
|
|
218
|
+
visibility: visible;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.unnnic-tooltip:hover {
|
|
223
|
+
.unnnic-tooltip-label {
|
|
224
|
+
visibility: visible;
|
|
225
|
+
width: auto;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
</style>
|
|
@@ -3,380 +3,102 @@ import { mount } from '@vue/test-utils';
|
|
|
3
3
|
|
|
4
4
|
import ToolTip from '../ToolTip.vue';
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
unobserve: vi.fn(),
|
|
9
|
-
disconnect: vi.fn(),
|
|
10
|
-
}));
|
|
11
|
-
|
|
12
|
-
const createWrapper = (props = {}, slots = {}) => {
|
|
13
|
-
return mount(ToolTip, {
|
|
14
|
-
props,
|
|
15
|
-
slots: {
|
|
16
|
-
default: '<button data-testid="trigger-button">Hover me</button>',
|
|
17
|
-
...slots,
|
|
18
|
-
},
|
|
19
|
-
attachTo: document.body,
|
|
20
|
-
global: {
|
|
21
|
-
stubs: {
|
|
22
|
-
teleport: true,
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
});
|
|
6
|
+
const createWrapper = (props) => {
|
|
7
|
+
return mount(ToolTip, { props });
|
|
26
8
|
};
|
|
27
9
|
|
|
28
10
|
describe('ToolTip', () => {
|
|
29
11
|
let wrapper;
|
|
30
|
-
|
|
31
12
|
beforeEach(() => {
|
|
32
|
-
wrapper = createWrapper({ text: '
|
|
13
|
+
wrapper = createWrapper({ text: 'Text', enabled: true });
|
|
33
14
|
});
|
|
34
15
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
16
|
+
it('should not display the tooltip when enabled is false', async () => {
|
|
17
|
+
await wrapper.setProps({ enabled: false });
|
|
18
|
+
const tooltipLabel = wrapper.find('[data-testid="tooltip-label"]');
|
|
19
|
+
expect(tooltipLabel.isVisible()).toBe(false);
|
|
39
20
|
});
|
|
40
21
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
expect(wrapper.vm).toBeTruthy();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should render slot content', () => {
|
|
48
|
-
const triggerButton = wrapper.find('[data-testid="trigger-button"]');
|
|
49
|
-
expect(triggerButton.exists()).toBe(true);
|
|
50
|
-
expect(triggerButton.text()).toBe('Hover me');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should render custom slot content', () => {
|
|
54
|
-
const customWrapper = createWrapper(
|
|
55
|
-
{ text: 'Tooltip text', enabled: true },
|
|
56
|
-
{
|
|
57
|
-
default: '<span data-testid="custom-trigger">Custom Content</span>',
|
|
58
|
-
},
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
const customTrigger = customWrapper.find(
|
|
62
|
-
'[data-testid="custom-trigger"]',
|
|
63
|
-
);
|
|
64
|
-
expect(customTrigger.exists()).toBe(true);
|
|
65
|
-
expect(customTrigger.text()).toBe('Custom Content');
|
|
66
|
-
|
|
67
|
-
customWrapper.unmount();
|
|
68
|
-
});
|
|
22
|
+
it('should display the tooltip when enabled is true', async () => {
|
|
23
|
+
const tooltipLabel = wrapper.find('[data-testid="tooltip-label"]');
|
|
24
|
+
expect(tooltipLabel.isVisible()).toBe(true);
|
|
69
25
|
});
|
|
70
26
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
expect(wrapper.vm.$props.text).toBe('Tooltip text');
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it('should accept enabled prop', () => {
|
|
77
|
-
expect(wrapper.vm.$props.enabled).toBe(true);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should accept forceOpen prop', () => {
|
|
81
|
-
const testWrapper = createWrapper({ text: 'Text', forceOpen: true });
|
|
82
|
-
expect(testWrapper.vm.$props.forceOpen).toBe(true);
|
|
83
|
-
testWrapper.unmount();
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
it('should accept side prop with valid values', () => {
|
|
87
|
-
const sides = ['top', 'right', 'bottom', 'left'];
|
|
88
|
-
|
|
89
|
-
sides.forEach((side) => {
|
|
90
|
-
const sideWrapper = createWrapper({
|
|
91
|
-
text: 'Text',
|
|
92
|
-
enabled: true,
|
|
93
|
-
side,
|
|
94
|
-
});
|
|
95
|
-
expect(sideWrapper.vm.$props.side).toBe(side);
|
|
96
|
-
sideWrapper.unmount();
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should default to "right" side when not specified', () => {
|
|
101
|
-
expect(wrapper.vm.$props.side).toBe('right');
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
it('should accept maxWidth prop', () => {
|
|
105
|
-
const maxWidthWrapper = createWrapper({
|
|
106
|
-
text: 'Text',
|
|
107
|
-
enabled: true,
|
|
108
|
-
maxWidth: '200px',
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
expect(maxWidthWrapper.vm.$props.maxWidth).toBe('200px');
|
|
27
|
+
it('should force open the tooltip when forceOpen is true', async () => {
|
|
28
|
+
await wrapper.setProps({ enabled: false, forceOpen: true });
|
|
112
29
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
it('should accept enableHtml prop', () => {
|
|
117
|
-
const htmlWrapper = createWrapper({
|
|
118
|
-
text: 'Text',
|
|
119
|
-
enableHtml: true,
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
expect(htmlWrapper.vm.$props.enableHtml).toBe(true);
|
|
123
|
-
|
|
124
|
-
htmlWrapper.unmount();
|
|
125
|
-
});
|
|
126
|
-
});
|
|
127
|
-
|
|
128
|
-
describe('Boolean Props', () => {
|
|
129
|
-
it('should handle enabled false', () => {
|
|
130
|
-
const disabledWrapper = createWrapper({
|
|
131
|
-
text: 'Text',
|
|
132
|
-
enabled: false,
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
expect(disabledWrapper.vm.$props.enabled).toBe(false);
|
|
136
|
-
|
|
137
|
-
disabledWrapper.unmount();
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it('should handle forceOpen true', () => {
|
|
141
|
-
const forceOpenWrapper = createWrapper({
|
|
142
|
-
text: 'Text',
|
|
143
|
-
enabled: false,
|
|
144
|
-
forceOpen: true,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
expect(forceOpenWrapper.vm.$props.forceOpen).toBe(true);
|
|
148
|
-
|
|
149
|
-
forceOpenWrapper.unmount();
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it('should handle enableHtml false', () => {
|
|
153
|
-
expect(wrapper.vm.$props.enableHtml).toBe(false);
|
|
154
|
-
});
|
|
30
|
+
const tooltipLabel = wrapper.find('[data-testid="tooltip-label"]');
|
|
31
|
+
expect(tooltipLabel.isVisible()).toBe(true);
|
|
155
32
|
});
|
|
156
33
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const plainWrapper = createWrapper({
|
|
160
|
-
text: 'Simple tooltip text',
|
|
161
|
-
enabled: true,
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
expect(plainWrapper.vm.$props.text).toBe('Simple tooltip text');
|
|
34
|
+
it('should position the tooltip correctly based on the side prop', async () => {
|
|
35
|
+
const sideValues = ['top', 'right', 'bottom', 'left'];
|
|
165
36
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
text: 'First line\nSecond line\nThird line',
|
|
172
|
-
enabled: true,
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
expect(multilineWrapper.vm.$props.text).toBe(
|
|
176
|
-
'First line\nSecond line\nThird line',
|
|
177
|
-
);
|
|
178
|
-
|
|
179
|
-
multilineWrapper.unmount();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it('should handle empty text', () => {
|
|
183
|
-
const emptyWrapper = createWrapper({ text: '', enabled: true });
|
|
184
|
-
|
|
185
|
-
expect(emptyWrapper.vm.$props.text).toBe('');
|
|
186
|
-
expect(emptyWrapper.exists()).toBe(true);
|
|
187
|
-
|
|
188
|
-
emptyWrapper.unmount();
|
|
189
|
-
});
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
describe('HTML Content', () => {
|
|
193
|
-
it('should accept HTML text with enableHtml prop set to true', () => {
|
|
194
|
-
const htmlWrapper = createWrapper({
|
|
195
|
-
enableHtml: true,
|
|
196
|
-
enabled: true,
|
|
197
|
-
text: 'Tooltip with <strong>bold</strong> text',
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
expect(htmlWrapper.vm.$props.enableHtml).toBe(true);
|
|
201
|
-
expect(htmlWrapper.vm.$props.text).toBe(
|
|
202
|
-
'Tooltip with <strong>bold</strong> text',
|
|
203
|
-
);
|
|
204
|
-
|
|
205
|
-
htmlWrapper.unmount();
|
|
206
|
-
});
|
|
207
|
-
|
|
208
|
-
it('should accept HTML link with enableHtml prop', () => {
|
|
209
|
-
const linkWrapper = createWrapper({
|
|
210
|
-
enableHtml: true,
|
|
211
|
-
enabled: true,
|
|
212
|
-
text: 'Visit <a href="https://weni.ai/" target="_blank">Weni</a>',
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
expect(linkWrapper.vm.$props.enableHtml).toBe(true);
|
|
216
|
-
expect(linkWrapper.vm.$props.text).toContain('href="https://weni.ai/"');
|
|
217
|
-
expect(linkWrapper.vm.$props.text).toContain('target="_blank"');
|
|
218
|
-
|
|
219
|
-
linkWrapper.unmount();
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should handle plain text when enableHtml is false', () => {
|
|
223
|
-
const plainWrapper = createWrapper({
|
|
224
|
-
enableHtml: false,
|
|
225
|
-
enabled: true,
|
|
226
|
-
text: 'Tooltip with <strong>bold</strong> text',
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
expect(plainWrapper.vm.$props.enableHtml).toBe(false);
|
|
230
|
-
expect(plainWrapper.vm.$props.text).toBe(
|
|
231
|
-
'Tooltip with <strong>bold</strong> text',
|
|
232
|
-
);
|
|
233
|
-
|
|
234
|
-
plainWrapper.unmount();
|
|
235
|
-
});
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
describe('Component Structure', () => {
|
|
239
|
-
it('should have Tooltip component', () => {
|
|
240
|
-
expect(wrapper.findComponent({ name: 'Tooltip' }).exists()).toBe(true);
|
|
241
|
-
});
|
|
242
|
-
|
|
243
|
-
it('should have TooltipTrigger component', () => {
|
|
244
|
-
expect(wrapper.findComponent({ name: 'TooltipTrigger' }).exists()).toBe(
|
|
245
|
-
true,
|
|
246
|
-
);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
it('should have TooltipContent component', () => {
|
|
250
|
-
expect(wrapper.findComponent({ name: 'TooltipContent' }).exists()).toBe(
|
|
251
|
-
true,
|
|
252
|
-
);
|
|
253
|
-
});
|
|
37
|
+
for (let side of sideValues) {
|
|
38
|
+
await wrapper.setProps({ side });
|
|
39
|
+
const tooltipLabel = wrapper.find('[data-testid="tooltip-label"]');
|
|
40
|
+
expect(tooltipLabel.classes()).include(`unnnic-tooltip-label-${side}`);
|
|
41
|
+
}
|
|
254
42
|
});
|
|
255
43
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
const sides = ['top', 'right', 'bottom', 'left'];
|
|
44
|
+
it('should split tooltip text into multiple lines', async () => {
|
|
45
|
+
await wrapper.setProps({ text: 'First line\nSecond line' });
|
|
259
46
|
|
|
260
|
-
|
|
261
|
-
const sideWrapper = createWrapper({
|
|
262
|
-
text: 'Text',
|
|
263
|
-
enabled: true,
|
|
264
|
-
side,
|
|
265
|
-
});
|
|
47
|
+
const tooltipLabel = wrapper.find('[data-testid="tooltip-label"]');
|
|
266
48
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
});
|
|
270
|
-
expect(tooltipContent.exists()).toBe(true);
|
|
271
|
-
expect(tooltipContent.props('side')).toBe(side);
|
|
49
|
+
expect(tooltipLabel.text()).toContain('First line');
|
|
50
|
+
expect(tooltipLabel.text()).toContain('Second line');
|
|
272
51
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it('should pass class prop to TooltipContent component', () => {
|
|
278
|
-
const tooltipContent = wrapper.findComponent({ name: 'TooltipContent' });
|
|
279
|
-
expect(tooltipContent.exists()).toBe(true);
|
|
280
|
-
expect(tooltipContent.props('class')).toContain('unnnic-tooltip-label');
|
|
281
|
-
});
|
|
52
|
+
const brElements = tooltipLabel.findAll('br');
|
|
53
|
+
expect(brElements.length).toBe(2);
|
|
282
54
|
});
|
|
283
55
|
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
const validator = wrapper.vm.$options.props.side.validator;
|
|
56
|
+
it('should display shortcutText when provided', async () => {
|
|
57
|
+
await wrapper.setProps({ shortcutText: 'Ctrl+C' });
|
|
287
58
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
});
|
|
59
|
+
const tooltipShortcut = wrapper.find(
|
|
60
|
+
'[data-testid="tooltip-label-shortcut"]',
|
|
61
|
+
);
|
|
62
|
+
expect(tooltipShortcut.exists()).toBe(true);
|
|
63
|
+
expect(tooltipShortcut.text()).toBe('Ctrl+C');
|
|
294
64
|
});
|
|
295
65
|
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
const defaultWrapper = createWrapper();
|
|
66
|
+
it('should calculate tooltip position based on element coordinates', async () => {
|
|
67
|
+
await wrapper.setProps({ side: 'right' });
|
|
299
68
|
|
|
300
|
-
|
|
301
|
-
expect(defaultWrapper.vm.$props.enabled).toBe(false);
|
|
302
|
-
expect(defaultWrapper.vm.$props.forceOpen).toBe(false);
|
|
303
|
-
expect(defaultWrapper.vm.$props.side).toBe('right');
|
|
304
|
-
expect(defaultWrapper.vm.$props.maxWidth).toBe('');
|
|
305
|
-
expect(defaultWrapper.vm.$props.enableHtml).toBe(false);
|
|
69
|
+
await wrapper.vm.$nextTick();
|
|
306
70
|
|
|
307
|
-
|
|
308
|
-
|
|
71
|
+
expect(wrapper.vm.leftPos).toBeDefined();
|
|
72
|
+
expect(wrapper.vm.topPos).toBeDefined();
|
|
309
73
|
});
|
|
310
74
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
const maxWidthWrapper = createWrapper({
|
|
314
|
-
text: 'Text',
|
|
315
|
-
enabled: true,
|
|
316
|
-
maxWidth: '250px',
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
expect(maxWidthWrapper.vm.$props.maxWidth).toBe('250px');
|
|
320
|
-
|
|
321
|
-
maxWidthWrapper.unmount();
|
|
322
|
-
});
|
|
323
|
-
|
|
324
|
-
it('should handle different maxWidth values', () => {
|
|
325
|
-
const values = ['100px', '50%', '20rem', '300px'];
|
|
326
|
-
|
|
327
|
-
values.forEach((maxWidth) => {
|
|
328
|
-
const testWrapper = createWrapper({
|
|
329
|
-
text: 'Text',
|
|
330
|
-
enabled: true,
|
|
331
|
-
maxWidth,
|
|
332
|
-
});
|
|
75
|
+
it('should remove event listeners on unmount', () => {
|
|
76
|
+
const removeEventListenerSpy = vi.spyOn(window, 'removeEventListener');
|
|
333
77
|
|
|
334
|
-
|
|
78
|
+
wrapper.unmount();
|
|
335
79
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
80
|
+
expect(removeEventListenerSpy).toHaveBeenCalledWith(
|
|
81
|
+
'scroll',
|
|
82
|
+
expect.any(Function),
|
|
83
|
+
);
|
|
84
|
+
expect(removeEventListenerSpy).toHaveBeenCalledWith(
|
|
85
|
+
'resize',
|
|
86
|
+
expect.any(Function),
|
|
87
|
+
);
|
|
339
88
|
});
|
|
340
89
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
expect(props.text.type).toBe(String);
|
|
346
|
-
expect(props.enabled.type).toBe(Boolean);
|
|
347
|
-
expect(props.forceOpen.type).toBe(Boolean);
|
|
348
|
-
expect(props.side.type).toBe(String);
|
|
349
|
-
expect(props.maxWidth.type).toBe(String);
|
|
350
|
-
expect(props.enableHtml.type).toBe(Boolean);
|
|
351
|
-
});
|
|
90
|
+
it('should call handleResize on mouseover event', async () => {
|
|
91
|
+
const handlResizeSpy = vi.spyOn(wrapper.vm, 'handleResize');
|
|
92
|
+
await wrapper.trigger('mouseover');
|
|
93
|
+
expect(handlResizeSpy).toHaveBeenCalled();
|
|
352
94
|
});
|
|
353
95
|
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
enabled: false,
|
|
359
|
-
forceOpen: false,
|
|
360
|
-
});
|
|
361
|
-
|
|
362
|
-
expect(disabledWrapper.vm.$props.enabled).toBe(false);
|
|
363
|
-
expect(disabledWrapper.vm.$props.forceOpen).toBe(false);
|
|
364
|
-
|
|
365
|
-
disabledWrapper.unmount();
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it('should override disabled state when forceOpen is true', () => {
|
|
369
|
-
const forceOpenWrapper = createWrapper({
|
|
370
|
-
text: 'Text',
|
|
371
|
-
enabled: false,
|
|
372
|
-
forceOpen: true,
|
|
373
|
-
});
|
|
374
|
-
|
|
375
|
-
expect(forceOpenWrapper.vm.$props.enabled).toBe(false);
|
|
376
|
-
expect(forceOpenWrapper.vm.$props.forceOpen).toBe(true);
|
|
377
|
-
expect(forceOpenWrapper.html()).toContain('unnnic-tooltip');
|
|
378
|
-
|
|
379
|
-
forceOpenWrapper.unmount();
|
|
96
|
+
it('should render html link variation', async () => {
|
|
97
|
+
await wrapper.setProps({
|
|
98
|
+
enableHtml: true,
|
|
99
|
+
text: 'tooltip with <a data-testid="weni-link" href="https://weni.ai/" target="_blank" style="color: white;">weni</a> link',
|
|
380
100
|
});
|
|
101
|
+
const link = wrapper.find('a[data-testid="weni-link"]');
|
|
102
|
+
expect(link.exists()).toBeTruthy();
|
|
381
103
|
});
|
|
382
104
|
});
|