@weni/unnnic-system 3.12.7 → 3.12.8-alpha-teleports.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.
Files changed (82) hide show
  1. package/README.md +9 -1
  2. package/dist/{es-c84c6e0c.mjs → es-2f6793d2.mjs} +1 -1
  3. package/dist/{index-71322a23.mjs → index-799af668.mjs} +99557 -96712
  4. package/dist/index.d.ts +5001 -1654
  5. package/dist/{pt-br-f53036d2.mjs → pt-br-f5121b47.mjs} +1 -1
  6. package/dist/style.css +1 -1
  7. package/dist/unnnic.mjs +231 -203
  8. package/dist/unnnic.umd.js +48 -44
  9. package/package.json +3 -2
  10. package/src/assets/scss/tailwind.scss +8 -0
  11. package/src/components/Alert/__tests__/__snapshots__/Alert.spec.js.snap +1 -1
  12. package/src/components/ChartFunnel/DefaultFunnel/ChartDefaultFunnelBase.vue +2 -1
  13. package/src/components/ChartFunnel/SvgFunnel/ChartFunnelTwoRows.vue +61 -60
  14. package/src/components/Checkbox/Checkbox.vue +2 -8
  15. package/src/components/CheckboxGroup/CheckboxGroup.vue +5 -7
  16. package/src/components/Chip/Chip.vue +1 -1
  17. package/src/components/DatePicker/DatePicker.vue +11 -1
  18. package/src/components/Drawer/Drawer.vue +180 -270
  19. package/src/components/Drawer/__tests__/Drawer.spec.js +32 -43
  20. package/src/components/Drawer/__tests__/__snapshots__/Drawer.spec.js.snap +18 -19
  21. package/src/components/FormElement/FormElement.vue +87 -96
  22. package/src/components/Input/Input.vue +2 -2
  23. package/src/components/InputDatePicker/InputDatePicker.vue +68 -73
  24. package/src/components/InputDatePicker/__test__/InputDatePicker.spec.js +31 -24
  25. package/src/components/ModalDialog/ModalDialog.vue +63 -154
  26. package/src/components/ModalDialog/__tests__/ModalDialog.spec.js +30 -210
  27. package/src/components/ModalDialog/__tests__/__snapshots__/ModalDialog.spec.js.snap +1 -22
  28. package/src/components/Radio/Radio.vue +6 -12
  29. package/src/components/Radio/__test__/Radio.spec.js +1 -3
  30. package/src/components/RadioGroup/RadioGroup.vue +10 -18
  31. package/src/components/Switch/Switch.vue +3 -10
  32. package/src/components/Tab/__test__/__snapshots__/Tab.spec.js.snap +3 -1
  33. package/src/components/TemplatePreview/TemplatePreview.vue +25 -28
  34. package/src/components/TemplatePreview/TemplatePreviewModal.vue +10 -10
  35. package/src/components/TemplatePreview/types.d.ts +3 -3
  36. package/src/components/Toast/Toast.vue +4 -1
  37. package/src/components/Toast/ToastManager.ts +4 -1
  38. package/src/components/Toast/__tests__/ToastManager.spec.js +10 -6
  39. package/src/components/ToolTip/ToolTip.vue +25 -177
  40. package/src/components/ToolTip/__tests__/ToolTip.spec.js +339 -61
  41. package/src/components/index.ts +56 -0
  42. package/src/components/ui/dialog/Dialog.vue +19 -0
  43. package/src/components/ui/dialog/DialogClose.vue +29 -0
  44. package/src/components/ui/dialog/DialogContent.vue +140 -0
  45. package/src/components/ui/dialog/DialogFooter.vue +50 -0
  46. package/src/components/ui/dialog/DialogHeader.vue +83 -0
  47. package/src/components/ui/dialog/DialogTitle.vue +38 -0
  48. package/src/components/ui/dialog/DialogTrigger.vue +16 -0
  49. package/src/components/ui/dialog/index.ts +7 -0
  50. package/src/components/ui/drawer/Drawer.vue +27 -0
  51. package/src/components/ui/drawer/DrawerClose.vue +31 -0
  52. package/src/components/ui/drawer/DrawerContent.vue +113 -0
  53. package/src/components/ui/drawer/DrawerDescription.vue +40 -0
  54. package/src/components/ui/drawer/DrawerFooter.vue +38 -0
  55. package/src/components/ui/drawer/DrawerHeader.vue +57 -0
  56. package/src/components/ui/drawer/DrawerOverlay.vue +33 -0
  57. package/src/components/ui/drawer/DrawerTitle.vue +37 -0
  58. package/src/components/ui/drawer/DrawerTrigger.vue +31 -0
  59. package/src/components/ui/drawer/index.ts +10 -0
  60. package/src/components/ui/popover/PopoverContent.vue +33 -11
  61. package/src/components/ui/popover/PopoverOption.vue +1 -1
  62. package/src/components/ui/popover/PopoverTrigger.vue +5 -1
  63. package/src/components/ui/tooltip/Tooltip.vue +21 -0
  64. package/src/components/ui/tooltip/TooltipContent.vue +77 -0
  65. package/src/components/ui/tooltip/TooltipTrigger.vue +24 -0
  66. package/src/components/ui/tooltip/index.ts +3 -0
  67. package/src/index.ts +9 -2
  68. package/src/lib/__tests__/teleport-target.spec.ts +73 -0
  69. package/src/lib/layer-manager.ts +64 -0
  70. package/src/lib/teleport-target.ts +46 -0
  71. package/src/stories/Dialog.stories.js +832 -0
  72. package/src/stories/Drawer.stories.js +1 -1
  73. package/src/stories/DrawerNext.stories.js +611 -0
  74. package/src/stories/LayerManager.docs.mdx +40 -0
  75. package/src/stories/LayerManager.stories.js +407 -0
  76. package/src/stories/ModalDialog.mdx +3 -0
  77. package/src/stories/ModalDialog.stories.js +96 -1
  78. package/src/stories/Popover.stories.js +5 -0
  79. package/src/stories/TemplatePreview.stories.js +27 -27
  80. package/src/stories/TemplatePreviewModal.stories.js +31 -31
  81. package/.vscode/extensions.json +0 -3
  82. package/CHANGELOG.md +0 -1080
@@ -1,23 +1,22 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`Drawer.vue > Component Rendering > Component Rendering > matches the snapshot 1`] = `
4
- "<aside data-v-196de012="" class="unnnic-drawer" data-testid="drawer">
5
- <section data-v-196de012="" class="unnnic-drawer__overlay" data-testid="overlay"></section>
6
- <transition-stub data-v-196de012="" name="drawer" appear="true" persisted="false" css="true">
7
- <section data-v-196de012="" data-testid="drawer-container" class="unnnic-drawer__container unnnic-drawer__container--md">
8
- <header data-v-196de012="" class="unnnic-drawer__header">
9
- <section data-v-196de012="" class="unnnic-drawer__title-container">
10
- <h1 data-v-196de012="" class="unnnic-drawer__title" data-testid="drawer-title">Test Title</h1>
11
- <p data-v-196de012="" class="unnnic-drawer__description" data-testid="drawer-description">Test Description</p>
12
- </section>
13
- <unnnic-icon-stub data-v-196de012="" filled="false" icon="arrow_back" clickable="true" size="avatar-nano" scheme="neutral-darkest" class="unnnic-drawer__close" data-testid="close-icon"></unnnic-icon-stub>
14
- </header>
15
- <section data-v-196de012="" class="unnnic-drawer__content"></section>
16
- <footer data-v-196de012="" class="unnnic-drawer__footer" data-testid="footer">
17
- <unnnic-button-stub data-v-196de012="" size="large" text="Secondary Action" type="tertiary" float="false" iconleft="" iconright="" iconcenter="" iconsfilled="false" disabled="false" loading="false" data-testid="secondary-button"></unnnic-button-stub>
18
- <unnnic-button-stub data-v-196de012="" size="large" text="Primary Action" type="primary" float="false" iconleft="" iconright="" iconcenter="" iconsfilled="false" disabled="false" loading="false" data-testid="primary-button"></unnnic-button-stub>
19
- </footer>
20
- </section>
21
- </transition-stub>
22
- </aside>"
4
+ "<div data-v-196de012="" class="unnnic-drawer" data-testid="drawer" open="true">
5
+ <div data-v-196de012="" showoverlay="true" data-testid="drawer-container" size="medium" class="unnnic-drawer__container unnnic-drawer__container--md">
6
+ <header data-v-39d0dfb8="" data-v-196de012="" class="unnnic-drawer__header unnnic-drawer__header">
7
+ <section data-v-196de012="" class="unnnic-drawer__title-container">
8
+ <div data-v-196de012="" class="unnnic-drawer__title" data-testid="drawer-title">Test Title</div>
9
+ <div data-v-196de012="" class="unnnic-drawer__description" data-testid="drawer-description">Test Description</div>
10
+ </section>
11
+ <div data-v-196de012="">
12
+ <unnnic-button-stub data-v-196de012="" size="small" text="" type="tertiary" float="false" iconleft="" iconright="" iconcenter="arrow_forward" iconsfilled="false" disabled="false" loading="false" class="unnnic-drawer__close-icon" data-testid="close-icon"></unnnic-button-stub>
13
+ </div>
14
+ </header>
15
+ <section data-v-196de012="" class="unnnic-drawer__content"></section>
16
+ <div data-v-196de012="" class="unnnic-drawer__footer" data-testid="footer">
17
+ <unnnic-button-stub data-v-196de012="" size="large" text="Secondary Action" type="tertiary" float="false" iconleft="" iconright="" iconcenter="" iconsfilled="false" disabled="false" loading="false" data-testid="secondary-button"></unnnic-button-stub>
18
+ <unnnic-button-stub data-v-196de012="" size="large" text="Primary Action" type="primary" float="false" iconleft="" iconright="" iconcenter="" iconsfilled="false" disabled="false" loading="false" data-testid="primary-button"></unnnic-button-stub>
19
+ </div>
20
+ </div>
21
+ </div>"
23
22
  `;
@@ -1,37 +1,28 @@
1
1
  <template>
2
- <section
3
- class="unnnic-form-element"
4
- :class="{ 'unnnic-form-element--disabled': disabled }"
5
- >
6
- <UnnnicLabel
7
- v-if="label"
8
- :label="label"
2
+ <section class="unnnic-form-element" :class="{ 'unnnic-form-element--disabled': disabled }">
3
+ <UnnnicLabel
4
+ v-if="label"
5
+ :label="label"
9
6
  :tooltip="tooltip"
10
7
  :class="[
11
8
  'unnnic-form-element__label',
12
9
  {
13
10
  'unnnic-form-element__label--fixed': fixedLabel,
14
11
  },
15
- ]"
12
+ ]"
16
13
  />
17
14
 
18
15
  <slot></slot>
19
16
 
20
- <section
17
+ <section
21
18
  class="unnnic-form-element__hints-container"
22
19
  v-if="message || error || !!$slots.rightMessage"
23
20
  >
24
21
  <section class="unnnic-form-element__message-container">
25
- <p
26
- v-if="message"
27
- class="unnnic-form-element__message"
28
- >
22
+ <p v-if="message" class="unnnic-form-element__message">
29
23
  {{ fullySanitize(message) }}
30
24
  </p>
31
- <p
32
- v-if="!!error?.length"
33
- class="unnnic-form-element__message error"
34
- >
25
+ <p v-if="!!error?.length" class="unnnic-form-element__message error">
35
26
  {{ Array.isArray(error) ? error.join(', ') : error }}
36
27
  </p>
37
28
  </section>
@@ -43,104 +34,104 @@
43
34
  </template>
44
35
 
45
36
  <script lang="js">
46
- import { fullySanitize } from '../../utils/sanitize';
47
- import UnnnicLabel from '../Label/Label.vue';
48
-
49
- export default {
50
- components: {
51
- UnnnicLabel,
52
- },
53
- props: {
54
- size: {
55
- type: String,
56
- default: 'md',
57
- validator: (size) => ['md', 'sm'].includes(size),
37
+ import { fullySanitize } from '../../utils/sanitize';
38
+ import UnnnicLabel from '../Label/Label.vue';
39
+
40
+ export default {
41
+ components: {
42
+ UnnnicLabel,
58
43
  },
44
+ props: {
45
+ size: {
46
+ type: String,
47
+ default: 'md',
48
+ validator: (size) => ['md', 'sm'].includes(size),
49
+ },
59
50
 
60
- label: { type: String, default: '' },
51
+ label: { type: String, default: '' },
61
52
 
62
- fixedLabel: { type: Boolean, default: false },
53
+ fixedLabel: { type: Boolean, default: false },
63
54
 
64
- error: {
65
- type: [Boolean, String],
66
- default: false,
67
- },
55
+ error: {
56
+ type: [Boolean, String],
57
+ default: false,
58
+ },
68
59
 
69
- message: { type: String, default: '' },
60
+ message: { type: String, default: '' },
70
61
 
71
- disabled: { type: Boolean, default: false },
62
+ disabled: { type: Boolean, default: false },
72
63
 
73
- tooltip: { type: String, default: '' },
74
- },
75
- methods: {
76
- fullySanitize,
77
- },
78
- };
64
+ tooltip: { type: String, default: '' },
65
+ },
66
+ methods: {
67
+ fullySanitize,
68
+ },
69
+ };
79
70
  </script>
80
71
 
81
72
  <style lang="scss" scoped>
82
- @use '@/assets/scss/unnnic' as *;
83
-
84
- * {
85
- margin: $unnnic-space-0;
86
- padding: $unnnic-space-0;
87
- box-sizing: border-box;
88
- }
89
-
90
- .unnnic-form-element {
91
- &__label {
92
- font: $unnnic-font-body;
93
- color: $unnnic-color-neutral-cloudy;
94
- margin-bottom: $unnnic-space-1;
95
- display: flex;
96
- align-items: center;
97
- gap: $unnnic-space-2;
98
-
99
- &--fixed {
100
- margin-top: -$unnnic-font-size-body-gt - $unnnic-space-2 + $unnnic-space-1;
101
- }
73
+ @use '@/assets/scss/unnnic' as *;
74
+
75
+ * {
76
+ margin: $unnnic-space-0;
77
+ padding: $unnnic-space-0;
78
+ box-sizing: border-box;
79
+ }
102
80
 
103
- &--fixed {
104
- margin-bottom: $unnnic-space-0;
105
- position: absolute;
106
- padding: $unnnic-space-0 $unnnic-space-1;
107
- margin-left: $unnnic-space-2;
81
+ .unnnic-form-element {
82
+ &__label {
83
+ font: $unnnic-font-body;
84
+ color: $unnnic-color-neutral-cloudy;
85
+ margin-bottom: $unnnic-space-1;
86
+ display: flex;
87
+ align-items: center;
88
+ gap: $unnnic-space-2;
89
+
90
+ &--fixed {
91
+ margin-top: -$unnnic-font-size-body-gt - $unnnic-space-2 + $unnnic-space-1;
92
+ }
108
93
 
109
- &:after {
110
- content: ' ';
94
+ &--fixed {
95
+ margin-bottom: $unnnic-space-0;
111
96
  position: absolute;
112
- left: $unnnic-space-0;
113
- bottom: $unnnic-space-1 - $unnnic-border-width-thinner;
114
- width: 100%;
115
- height: $unnnic-border-width-thinner;
116
- background-color: $unnnic-color-white;
97
+ padding: $unnnic-space-0 $unnnic-space-1;
98
+ margin-left: $unnnic-space-2;
99
+
100
+ &:after {
101
+ content: ' ';
102
+ position: absolute;
103
+ left: $unnnic-space-0;
104
+ bottom: $unnnic-space-1 - $unnnic-border-width-thinner;
105
+ width: 100%;
106
+ height: $unnnic-border-width-thinner;
107
+ background-color: $unnnic-color-white;
108
+ }
117
109
  }
118
110
  }
119
- }
120
111
 
121
- &__message {
122
- &.error {
123
- color: $unnnic-color-fg-critical;
112
+ &__message {
113
+ &.error {
114
+ color: $unnnic-color-fg-critical;
115
+ }
124
116
  }
125
- }
126
117
 
127
- &__hints-container {
128
- display: flex;
129
- justify-content: space-between;
130
- margin-top: $unnnic-space-1;
131
- font: $unnnic-font-caption-2;
132
- color: $unnnic-color-fg-base;
133
- }
118
+ &__hints-container {
119
+ display: flex;
120
+ justify-content: space-between;
121
+ margin-top: $unnnic-space-1;
122
+ font: $unnnic-font-caption-2;
123
+ color: $unnnic-color-fg-base;
124
+ }
134
125
 
135
- &__message-container {
136
- display: flex;
137
- flex-direction: column;
138
- gap: $unnnic-space-1;
139
- }
126
+ &__message-container {
127
+ display: flex;
128
+ flex-direction: column;
129
+ gap: $unnnic-space-1;
130
+ }
140
131
 
141
- &--disabled .unnnic-form-element__label,
142
- &--disabled .unnnic-form-element__message {
143
- user-select: none;
132
+ &--disabled .unnnic-form-element__label,
133
+ &--disabled .unnnic-form-element__message {
134
+ user-select: none;
135
+ }
144
136
  }
145
- }
146
137
  </style>
@@ -43,8 +43,8 @@ import UnnnicFormElement from '../FormElement/FormElement.vue';
43
43
 
44
44
  export default {
45
45
  name: 'UnnnicInput',
46
- components: {
47
- TextInput,
46
+ components: {
47
+ TextInput,
48
48
  UnnnicFormElement,
49
49
  },
50
50
  props: {
@@ -1,51 +1,61 @@
1
1
  <template>
2
- <div
3
- ref="dropdown"
4
- :class="['dropdown', { active: showCalendarFilter, 'fill-w': fillW }]"
5
- >
6
- <UnnnicInput
7
- :class="['input', { 'date-picker-input-next': next }]"
8
- :size="size"
9
- :iconLeft="iconPosition === 'left' ? 'calendar_month' : undefined"
10
- :iconRight="iconPosition === 'right' ? 'calendar_month' : undefined"
11
- hasCloudyColor
12
- readonly
13
- :modelValue="overwrittenValue || filterText || ''"
14
- @focus="showCalendarFilter = true"
15
- />
16
-
17
- <div
18
- class="dropdown-data"
19
- :style="{ [position]: '0' }"
20
- >
21
- <UnnnicDatePicker
22
- v-if="showCalendarFilter"
23
- v-model:equivalentOption="overwrittenValue"
24
- :type="type"
25
- :clearLabel="clearText"
26
- :actionLabel="actionText"
27
- :months="months"
28
- :days="days"
29
- :options="options"
30
- :periodBaseDate="periodBaseDate"
31
- :initialStartDate="initialStartDate"
32
- :initialEndDate="initialEndDate"
33
- :minDate="minDate"
34
- :maxDate="maxDate"
35
- :disableClear="disableClear"
36
- @change="emitSelectDate"
37
- @submit="changeDate"
38
- />
39
- </div>
2
+ <div :class="['dropdown', { 'fill-w': fillW }]">
3
+ <UnnnicPopover v-model:open="isPopoverOpen">
4
+ <UnnnicPopoverTrigger :asChild="true">
5
+ <UnnnicInput
6
+ data-testid="input"
7
+ :class="['input', { 'date-picker-input-next': next }]"
8
+ :size="size"
9
+ :iconLeft="iconPosition === 'left' ? 'calendar_month' : undefined"
10
+ :iconRight="iconPosition === 'right' ? 'calendar_month' : undefined"
11
+ readonly
12
+ :modelValue="overwrittenValue || filterText || ''"
13
+ @click="openPopover"
14
+ @focus="openPopover"
15
+ />
16
+ </UnnnicPopoverTrigger>
17
+
18
+ <UnnnicPopoverContent
19
+ width="auto"
20
+ side="bottom"
21
+ :align="popoverAlign"
22
+ class="date-picker-popover-content"
23
+ >
24
+ <UnnnicDatePicker
25
+ v-model:equivalentOption="overwrittenValue"
26
+ data-testid="date-picker"
27
+ variant="popover"
28
+ :type="type"
29
+ :clearLabel="clearText"
30
+ :actionLabel="actionText"
31
+ :months="months"
32
+ :days="days"
33
+ :options="options"
34
+ :periodBaseDate="periodBaseDate"
35
+ :initialStartDate="initialStartDate"
36
+ :initialEndDate="initialEndDate"
37
+ :minDate="minDate"
38
+ :maxDate="maxDate"
39
+ :disableClear="disableClear"
40
+ @change="emitSelectDate"
41
+ @submit="changeDate"
42
+ />
43
+ </UnnnicPopoverContent>
44
+ </UnnnicPopover>
40
45
  </div>
41
46
  </template>
42
47
 
43
48
  <script setup lang="ts">
44
- import { computed, onBeforeUnmount, onMounted, ref } from 'vue';
49
+ import { computed, ref } from 'vue';
45
50
  import moment from 'moment';
46
51
 
47
52
  import UnnnicInput from '../Input/Input.vue';
48
53
  import UnnnicDatePicker from '../DatePicker/DatePicker.vue';
54
+ import {
55
+ Popover as UnnnicPopover,
56
+ PopoverContent as UnnnicPopoverContent,
57
+ PopoverTrigger as UnnnicPopoverTrigger,
58
+ } from '../ui/popover';
49
59
 
50
60
  defineOptions({
51
61
  name: 'UnnnicInputDatePicker',
@@ -112,9 +122,11 @@ const emit = defineEmits<{
112
122
  (e: 'selectDate', value: DateRangeValue): void;
113
123
  }>();
114
124
 
115
- const dropdown = ref<HTMLElement | null>(null);
116
- const showCalendarFilter = ref(false);
125
+ const isPopoverOpen = ref(false);
117
126
  const overwrittenValue = ref('');
127
+ const popoverAlign = computed<'start' | 'end'>(() =>
128
+ props.position === 'right' ? 'end' : 'start',
129
+ );
118
130
 
119
131
  const filterText = computed(() => {
120
132
  const dates: string[] = [];
@@ -160,20 +172,12 @@ function emitSelectDate(date: { startDate: string; endDate: string }) {
160
172
  emit('selectDate', formattedDates);
161
173
  }
162
174
 
163
- function mouseout(event: MouseEvent | { target: EventTarget | null }) {
164
- if (dropdown.value?.contains(event.target as Node)) {
165
- return;
166
- }
167
-
168
- showCalendarFilter.value = false;
169
- }
170
-
171
175
  function changeDate(value: { startDate: string; endDate: string }) {
172
176
  const startDate = value.startDate.replace(/(\d+)-(\d+)-(\d+)/, '$3-$1-$2');
173
177
 
174
178
  const endDate = value.endDate.replace(/(\d+)-(\d+)-(\d+)/, '$3-$1-$2');
175
179
 
176
- showCalendarFilter.value = false;
180
+ isPopoverOpen.value = false;
177
181
 
178
182
  emit('update:model-value', {
179
183
  start: startDate
@@ -183,39 +187,30 @@ function changeDate(value: { startDate: string; endDate: string }) {
183
187
  });
184
188
  }
185
189
 
186
- onMounted(() => {
187
- window.document.body.addEventListener('click', mouseout as any);
188
- });
189
-
190
- onBeforeUnmount(() => {
191
- window.document.body.removeEventListener('click', mouseout as any);
192
- });
190
+ function openPopover() {
191
+ isPopoverOpen.value = true;
192
+ }
193
193
  </script>
194
194
 
195
+ <style lang="scss">
196
+ @use '@/assets/scss/unnnic' as *;
197
+
198
+ .date-picker-popover-content {
199
+ overflow: hidden;
200
+ border-radius: $unnnic-radius-2;
201
+ padding: 0;
202
+ }
203
+ </style>
204
+
195
205
  <style lang="scss" scoped>
196
206
  @use '@/assets/scss/unnnic' as *;
197
207
  .fill-w {
198
208
  width: 100%;
199
209
  }
210
+
200
211
  .dropdown {
201
- position: relative;
202
212
  display: inline-block;
203
213
 
204
- .dropdown-data {
205
- position: absolute;
206
- pointer-events: none;
207
- display: none;
208
- top: 100%;
209
- z-index: 2;
210
- margin-top: $unnnic-spacing-stack-nano;
211
- width: max-content;
212
- }
213
-
214
- &.active .dropdown-data {
215
- pointer-events: auto;
216
- display: block;
217
- }
218
-
219
214
  .input {
220
215
  display: inline-block;
221
216
  }
@@ -1,5 +1,6 @@
1
1
  import { mount } from '@vue/test-utils';
2
- import { beforeEach, describe, expect, it } from 'vitest';
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
3
+
3
4
  import InputDatePicker from '../InputDatePicker.vue';
4
5
 
5
6
  const factory = (props = {}) =>
@@ -11,20 +12,7 @@ const factory = (props = {}) =>
11
12
  },
12
13
  ...props,
13
14
  },
14
- global: {
15
- stubs: {
16
- UnnnicInput: {
17
- name: 'UnnnicInput',
18
- template:
19
- '<input data-testid="input" v-bind="$attrs" @focus="$emit(\'focus\', $event)" />',
20
- },
21
- UnnnicDatePicker: {
22
- name: 'UnnnicDatePicker',
23
- props: ['minDate', 'maxDate', 'periodBaseDate', 'options'],
24
- template: '<div data-testid="datepicker"></div>',
25
- },
26
- },
27
- },
15
+ attachTo: document.body,
28
16
  });
29
17
 
30
18
  describe('InputDatePicker.vue', () => {
@@ -34,6 +22,12 @@ describe('InputDatePicker.vue', () => {
34
22
  wrapper = factory();
35
23
  });
36
24
 
25
+ afterEach(() => {
26
+ if (wrapper) {
27
+ wrapper.unmount();
28
+ }
29
+ });
30
+
37
31
  it('renders input and does not show datepicker by default', () => {
38
32
  expect(wrapper.find('[data-testid="input"]').exists()).toBe(true);
39
33
  expect(wrapper.find('[data-testid="datepicker"]').exists()).toBe(false);
@@ -42,13 +36,23 @@ describe('InputDatePicker.vue', () => {
42
36
  it('opens datepicker when input receives focus', async () => {
43
37
  const input = wrapper.find('[data-testid="input"]');
44
38
  await input.trigger('focus');
39
+ await wrapper.vm.$nextTick();
45
40
 
46
- wrapper.vm.showCalendarFilter = true;
41
+ expect(wrapper.findComponent({ name: 'UnnnicDatePicker' }).exists()).toBe(
42
+ true,
43
+ );
44
+ expect(wrapper.vm.isPopoverOpen).toBe(true);
45
+ });
46
+
47
+ it('opens datepicker when input receives click', async () => {
48
+ const input = wrapper.find('[data-testid="input"]');
49
+ await input.trigger('click');
47
50
  await wrapper.vm.$nextTick();
48
51
 
49
52
  expect(wrapper.findComponent({ name: 'UnnnicDatePicker' }).exists()).toBe(
50
53
  true,
51
54
  );
55
+ expect(wrapper.vm.isPopoverOpen).toBe(true);
52
56
  });
53
57
 
54
58
  it('computes filterText placeholder when there is no date selected', () => {
@@ -66,6 +70,7 @@ describe('InputDatePicker.vue', () => {
66
70
  });
67
71
 
68
72
  expect(withDates.vm.filterText).toBe('01-10-2025 ~ 01-20-2025');
73
+ withDates.unmount();
69
74
  });
70
75
 
71
76
  it('computes initialStartDate and initialEndDate for DatePicker', () => {
@@ -78,10 +83,11 @@ describe('InputDatePicker.vue', () => {
78
83
 
79
84
  expect(withDates.vm.initialStartDate).toBe('01 10 2025');
80
85
  expect(withDates.vm.initialEndDate).toBe('01 20 2025');
86
+ withDates.unmount();
81
87
  });
82
88
 
83
89
  it('emits selectDate with formatted dates when DatePicker emits change', async () => {
84
- wrapper.vm.showCalendarFilter = true;
90
+ wrapper.vm.isPopoverOpen = true;
85
91
  await wrapper.vm.$nextTick();
86
92
 
87
93
  const datePicker = wrapper.findComponent({ name: 'UnnnicDatePicker' });
@@ -104,7 +110,7 @@ describe('InputDatePicker.vue', () => {
104
110
  });
105
111
 
106
112
  it('emits update:model-value and closes dropdown when DatePicker emits submit', async () => {
107
- wrapper.vm.showCalendarFilter = true;
113
+ wrapper.vm.isPopoverOpen = true;
108
114
  await wrapper.vm.$nextTick();
109
115
 
110
116
  const datePicker = wrapper.findComponent({ name: 'UnnnicDatePicker' });
@@ -125,7 +131,7 @@ describe('InputDatePicker.vue', () => {
125
131
  end: '2025-01-20',
126
132
  });
127
133
 
128
- expect(wrapper.vm.showCalendarFilter).toBe(false);
134
+ expect(wrapper.vm.isPopoverOpen).toBe(false);
129
135
  });
130
136
 
131
137
  it('passes minDate, maxDate, options and periodBaseDate down to DatePicker', async () => {
@@ -137,7 +143,7 @@ describe('InputDatePicker.vue', () => {
137
143
  };
138
144
 
139
145
  wrapper = factory(props);
140
- wrapper.vm.showCalendarFilter = true;
146
+ wrapper.vm.isPopoverOpen = true;
141
147
  await wrapper.vm.$nextTick();
142
148
 
143
149
  const datePicker = wrapper.findComponent({ name: 'UnnnicDatePicker' });
@@ -147,13 +153,14 @@ describe('InputDatePicker.vue', () => {
147
153
  expect(dpProps.maxDate).toBe(props.maxDate);
148
154
  expect(dpProps.periodBaseDate).toBe(props.periodBaseDate);
149
155
  expect(dpProps.options).toEqual(props.options);
156
+ expect(dpProps.variant).toBe('popover');
150
157
  });
151
158
 
152
- it('closes dropdown on mouseout when clicking outside', () => {
153
- wrapper.vm.showCalendarFilter = true;
159
+ it('aligns the popover to the end when position is right', () => {
160
+ const rightWrapper = factory({ position: 'right' });
154
161
 
155
- wrapper.vm.mouseout({ target: document.createElement('div') });
162
+ expect(rightWrapper.vm.popoverAlign).toBe('end');
156
163
 
157
- expect(wrapper.vm.showCalendarFilter).toBe(false);
164
+ rightWrapper.unmount();
158
165
  });
159
166
  });