@weni/unnnic-system 3.11.1-alpha.1 → 3.11.1-alpha.4

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 (47) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/components/DatePicker/DatePicker.vue.d.ts +69 -249
  3. package/dist/components/DatePicker/DatePicker.vue.d.ts.map +1 -1
  4. package/dist/components/Drawer/Drawer.vue.d.ts.map +1 -1
  5. package/dist/components/InputDatePicker/InputDatePicker.vue.d.ts +47 -911
  6. package/dist/components/InputDatePicker/InputDatePicker.vue.d.ts.map +1 -1
  7. package/dist/components/Select/SelectItem.vue.d.ts +1 -1
  8. package/dist/components/SelectSmart/SelectSmart.vue.d.ts +1 -1
  9. package/dist/components/SelectSmart/SelectSmartOption.vue.d.ts +1 -1
  10. package/dist/components/Sidebar/SidebarItem.vue.d.ts +2 -2
  11. package/dist/components/ui/drawer/Drawer.vue.d.ts.map +1 -1
  12. package/dist/components/ui/drawer/DrawerClose.vue.d.ts.map +1 -1
  13. package/dist/components/ui/drawer/DrawerContent.vue.d.ts.map +1 -1
  14. package/dist/components/ui/drawer/DrawerDescription.vue.d.ts.map +1 -1
  15. package/dist/components/ui/drawer/DrawerFooter.vue.d.ts.map +1 -1
  16. package/dist/components/ui/drawer/DrawerHeader.vue.d.ts.map +1 -1
  17. package/dist/components/ui/drawer/DrawerOverlay.vue.d.ts.map +1 -1
  18. package/dist/components/ui/drawer/DrawerTitle.vue.d.ts.map +1 -1
  19. package/dist/components/ui/drawer/DrawerTrigger.vue.d.ts.map +1 -1
  20. package/dist/{es-1e5cce64.mjs → es-fc643bdb.mjs} +1 -1
  21. package/dist/{index-8d75623f.mjs → index-4601aaf4.mjs} +9050 -9107
  22. package/dist/{pt-br-defd03da.mjs → pt-br-0b82e6d2.mjs} +1 -1
  23. package/dist/style.css +1 -1
  24. package/dist/unnnic.mjs +1 -1
  25. package/dist/unnnic.umd.js +42 -42
  26. package/package.json +1 -1
  27. package/src/components/DatePicker/DatePicker.vue +628 -516
  28. package/src/components/DatePicker/__tests__/DatePicker.spec.js +227 -0
  29. package/src/components/Drawer/Drawer.vue +6 -2
  30. package/src/components/Drawer/__tests__/Drawer.spec.js +11 -15
  31. package/src/components/Drawer/__tests__/__snapshots__/Drawer.spec.js.snap +9 -9
  32. package/src/components/InputDatePicker/InputDatePicker.vue +149 -183
  33. package/src/components/InputDatePicker/__test__/InputDatePicker.spec.js +159 -0
  34. package/src/components/Tab/__test__/__snapshots__/Tab.spec.js.snap +1 -1
  35. package/src/components/ui/drawer/Drawer.vue +4 -0
  36. package/src/components/ui/drawer/DrawerClose.vue +4 -0
  37. package/src/components/ui/drawer/DrawerContent.vue +5 -1
  38. package/src/components/ui/drawer/DrawerDescription.vue +4 -0
  39. package/src/components/ui/drawer/DrawerFooter.vue +5 -1
  40. package/src/components/ui/drawer/DrawerHeader.vue +5 -1
  41. package/src/components/ui/drawer/DrawerOverlay.vue +5 -1
  42. package/src/components/ui/drawer/DrawerTitle.vue +5 -1
  43. package/src/components/ui/drawer/DrawerTrigger.vue +4 -0
  44. package/src/stories/DatePicker.stories.js +71 -0
  45. package/src/stories/InputDatePicker.stories.js +22 -0
  46. package/dist/components/index.d.ts +0 -25946
  47. package/dist/components/index.d.ts.map +0 -1
@@ -0,0 +1,227 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import { describe, it, expect, beforeEach } from 'vitest';
3
+ import DatePicker from '../DatePicker.vue';
4
+
5
+ const factory = (props = {}) =>
6
+ mount(DatePicker, {
7
+ props: {
8
+ size: 'large',
9
+ type: 'day',
10
+ ...props,
11
+ },
12
+ global: {
13
+ mocks: {
14
+ $i18n: { locale: 'en-us' },
15
+ },
16
+ stubs: {
17
+ UnnnicButton: true,
18
+ },
19
+ },
20
+ });
21
+
22
+ const findFirstSelectableDay = (wrapper) =>
23
+ wrapper
24
+ .findAll('[data-testid="date-picker-day"]')
25
+ .find((day) => day.classes().includes('selectable'));
26
+
27
+ describe('DatePicker.vue', () => {
28
+ let wrapper;
29
+
30
+ beforeEach(() => {
31
+ wrapper = factory({
32
+ options: [
33
+ { name: 'Last 7 days', id: 'last-7-days' },
34
+ { name: 'Custom', id: 'custom' },
35
+ ],
36
+ });
37
+ });
38
+
39
+ it('renders day view with two months and options', () => {
40
+ expect(wrapper.find('[data-testid="date-picker-root"]').exists()).toBe(
41
+ true,
42
+ );
43
+ expect(
44
+ wrapper.findAll('[data-testid="date-picker-month-container"]').length,
45
+ ).toBe(2);
46
+ expect(wrapper.findAll('[data-testid="date-picker-option"]').length).toBe(
47
+ 2,
48
+ );
49
+ });
50
+
51
+ it('selects a date range and emits change', async () => {
52
+ const first = findFirstSelectableDay(wrapper);
53
+ const second = wrapper
54
+ .findAll('[data-testid="date-picker-day"]')
55
+ .reverse()
56
+ .find((day) => day.classes().includes('selectable'));
57
+
58
+ await first.trigger('click');
59
+ await second.trigger('click');
60
+
61
+ const emittedChange = wrapper.emitted('change');
62
+ expect(emittedChange).toBeTruthy();
63
+ const [{ startDate, endDate }] = emittedChange.pop();
64
+ expect(startDate).not.toBe('');
65
+ expect(endDate).not.toBe('');
66
+ });
67
+
68
+ it('clears selection when clear button is clicked', async () => {
69
+ const day = findFirstSelectableDay(wrapper);
70
+ await day.trigger('click');
71
+
72
+ await wrapper.find('[data-testid="date-picker-clear"]').trigger('click');
73
+
74
+ expect(wrapper.vm.startDate).toBe('');
75
+ expect(wrapper.vm.endDate).toBe('');
76
+ expect(wrapper.vm.optionSelected).toBe('');
77
+ });
78
+
79
+ it('submits with selected period and emits equivalent option name', async () => {
80
+ await wrapper.vm.autoSelect('last-7-days');
81
+ await wrapper.find('[data-testid="date-picker-submit"]').trigger('click');
82
+
83
+ const submit = wrapper.emitted('submit');
84
+ const updateEquivalent = wrapper.emitted('update:equivalentOption');
85
+
86
+ expect(submit).toBeTruthy();
87
+ expect(submit[0][0]).toHaveProperty('startDate');
88
+ expect(submit[0][0]).toHaveProperty('endDate');
89
+
90
+ expect(updateEquivalent[0][0]).toBe('Last 7 days');
91
+ });
92
+
93
+ it('submits with custom selection and clears equivalent option', async () => {
94
+ wrapper.vm.optionSelected = 'custom';
95
+ await wrapper.find('[data-testid="date-picker-submit"]').trigger('click');
96
+
97
+ const updateEquivalent = wrapper.emitted('update:equivalentOption');
98
+ expect(updateEquivalent[0][0]).toBe('');
99
+ });
100
+
101
+ it('uses periodBaseDate to compute relative ranges', async () => {
102
+ const base = '2025-01-15';
103
+ wrapper = factory({
104
+ periodBaseDate: base,
105
+ options: [{ name: 'Last 7 days', id: 'last-7-days' }],
106
+ });
107
+
108
+ await wrapper.vm.autoSelect('last-7-days');
109
+
110
+ const [year, month, day] = base.split('-');
111
+ const baseDate = new Date(Number(year), Number(month) - 1, Number(day));
112
+ const expectedEnd = wrapper.vm.dateToString(baseDate);
113
+
114
+ expect(wrapper.vm.endDate).toBe(expectedEnd);
115
+ });
116
+
117
+ it('renders month view and selects a month', async () => {
118
+ wrapper = factory({
119
+ type: 'month',
120
+ options: [{ name: 'Last 12 months', id: 'last-12-months' }],
121
+ });
122
+
123
+ const monthCell = wrapper.find('[data-testid="date-picker-month-cell"]');
124
+ await monthCell.trigger('click');
125
+
126
+ expect(wrapper.vm.startDate).not.toBe('');
127
+ expect(wrapper.vm.endDate).not.toBe('');
128
+ });
129
+
130
+ it('renders year view and selects a year', async () => {
131
+ wrapper = factory({
132
+ type: 'year',
133
+ options: [{ name: 'Previous year', id: 'previous-year' }],
134
+ });
135
+
136
+ const yearCell = wrapper.find('[data-testid="date-picker-year-cell"]');
137
+ await yearCell.trigger('click');
138
+
139
+ expect(wrapper.vm.startDate).not.toBe('');
140
+ expect(wrapper.vm.endDate).not.toBe('');
141
+ });
142
+
143
+ it('hides options when size is small and respects disableClear', async () => {
144
+ wrapper = factory({
145
+ size: 'small',
146
+ options: [{ name: 'Last 7 days', id: 'last-7-days' }],
147
+ });
148
+ expect(wrapper.find('[data-testid="date-picker-options"]').exists()).toBe(
149
+ false,
150
+ );
151
+
152
+ wrapper = factory({
153
+ disableClear: true,
154
+ options: [{ name: 'Last 7 days', id: 'last-7-days' }],
155
+ });
156
+ expect(wrapper.find('[data-testid="date-picker-clear"]').exists()).toBe(
157
+ false,
158
+ );
159
+ expect(wrapper.find('[data-testid="date-picker-submit"]').exists()).toBe(
160
+ true,
161
+ );
162
+ });
163
+
164
+ it('navigates between months using navigation buttons', async () => {
165
+ const initialReference = wrapper.vm.referenceDate;
166
+
167
+ const nextButton = wrapper.find('[data-testid="date-picker-nav-right"]');
168
+ await nextButton.trigger('click');
169
+
170
+ expect(wrapper.vm.referenceDate).not.toBe(initialReference);
171
+ });
172
+
173
+ it('exposes i18n helper compatible with previous mixin', () => {
174
+ const text = wrapper.vm.i18n('clean', 'Clean');
175
+ expect(text).toBeTruthy();
176
+ });
177
+
178
+ it('computes previous-month period correctly based on periodBaseDate', () => {
179
+ const base = '2025-03-15';
180
+ wrapper = factory({
181
+ periodBaseDate: base,
182
+ options: [{ name: 'Previous month', id: 'previous-month' }],
183
+ });
184
+
185
+ const { startDate, endDate } =
186
+ wrapper.vm.getStartAndEndDateByPeriod('previous-month');
187
+
188
+ const baseDate = new Date(base);
189
+ const firstPrevMonth = new Date(
190
+ baseDate.getFullYear(),
191
+ baseDate.getMonth() - 1,
192
+ 1,
193
+ );
194
+ const lastPrevMonth = new Date(
195
+ firstPrevMonth.getFullYear(),
196
+ firstPrevMonth.getMonth() + 1,
197
+ 0,
198
+ );
199
+
200
+ const expectedStart = wrapper.vm.dateToString(firstPrevMonth);
201
+ const expectedEnd = wrapper.vm.dateToString(lastPrevMonth);
202
+
203
+ expect(startDate).toBe(expectedStart);
204
+ expect(endDate).toBe(expectedEnd);
205
+ });
206
+
207
+ it('marks dates outside minDate and maxDate as out of range', () => {
208
+ const min = '2025-02-10';
209
+ const max = '2025-02-20';
210
+
211
+ wrapper = factory({
212
+ minDate: min,
213
+ maxDate: max,
214
+ });
215
+
216
+ const [year, month] = min.split('-');
217
+ const reference = `${Number(month)} 1 ${year}`;
218
+
219
+ const dates = wrapper.vm.getDatesOfTheMonth(reference);
220
+
221
+ const hasOutOfRange = dates.some((d) =>
222
+ d.properties.includes('out of range'),
223
+ );
224
+
225
+ expect(hasOutOfRange).toBe(true);
226
+ });
227
+ });
@@ -1,9 +1,9 @@
1
1
  <template>
2
2
  <Drawer
3
- :open="modelValue"
4
- @update:open="$emit('update:modelValue', $event)"
5
3
  class="unnnic-drawer"
6
4
  data-testid="drawer"
5
+ :open="modelValue"
6
+ @update:open="$emit('update:modelValue', $event)"
7
7
  >
8
8
  <DrawerContent
9
9
  :showOverlay="!withoutOverlay"
@@ -96,6 +96,10 @@ import {
96
96
  DrawerDescription,
97
97
  } from '../ui/drawer';
98
98
 
99
+ defineOptions({
100
+ name: 'UnnnicDrawer',
101
+ });
102
+
99
103
  const props = defineProps({
100
104
  title: {
101
105
  type: String,
@@ -10,12 +10,6 @@ describe('Drawer.vue', () => {
10
10
  UnnnicIcon: true,
11
11
  UnnnicButton: true,
12
12
  Teleport: templateSlot,
13
- Drawer: templateSlot,
14
- DrawerContent: templateSlot,
15
- DrawerFooter: templateSlot,
16
- DrawerClose: templateSlot,
17
- DrawerTitle: templateSlot,
18
- DrawerDescription: templateSlot,
19
13
  };
20
14
 
21
15
  beforeEach(() => {
@@ -35,7 +29,7 @@ describe('Drawer.vue', () => {
35
29
 
36
30
  const element = (id) => wrapper.find(`[data-testid="${id}"]`);
37
31
  const component = (id) => wrapper.findComponent(`[data-testid="${id}"]`);
38
- const drawer = () => element('drawer');
32
+ const drawerRoot = () => wrapper.findComponent({ name: 'UnnnicDrawerNext' });
39
33
  const title = () => element('drawer-title');
40
34
  const description = () => element('drawer-description');
41
35
  const primaryButton = () => component('primary-button');
@@ -43,6 +37,8 @@ describe('Drawer.vue', () => {
43
37
  const footer = () => element('footer');
44
38
  const closeIcon = () => component('close-icon');
45
39
  const drawerContainer = () => element('drawer-container');
40
+ const drawerContentComponent = () =>
41
+ wrapper.findComponent({ name: 'UnnnicDrawerContent' });
46
42
 
47
43
  describe('Component Rendering', () => {
48
44
  describe('Component Rendering', () => {
@@ -51,23 +47,21 @@ describe('Drawer.vue', () => {
51
47
  });
52
48
 
53
49
  it('should render the drawer when modelValue is true', () => {
54
- expect(drawer().attributes('open')).toBe('true');
50
+ expect(drawerRoot().props('open')).toBe(true);
55
51
  });
56
52
 
57
53
  it('should not render the drawer when modelValue is false', async () => {
58
54
  await wrapper.setProps({ modelValue: false });
59
- expect(drawer().attributes('open')).toBe('false');
55
+ expect(drawerRoot().props('open')).toBe(false);
60
56
  });
61
57
 
62
58
  it('should render the overlay when withoutOverlay is false', () => {
63
- console.log('wrapper.html()', wrapper.html());
64
-
65
- expect(drawerContainer().attributes('showoverlay')).toBe('true');
59
+ expect(drawerContentComponent().props('showOverlay')).toBe(true);
66
60
  });
67
61
 
68
62
  it('should not render the overlay when withoutOverlay is true', async () => {
69
63
  await wrapper.setProps({ withoutOverlay: true });
70
- expect(drawerContainer().attributes('showoverlay')).toBe('false');
64
+ expect(drawerContentComponent().props('showOverlay')).toBe(false);
71
65
  });
72
66
 
73
67
  it('should display the title and description correctly', () => {
@@ -217,14 +211,16 @@ describe('Drawer.vue', () => {
217
211
  describe('Props and Computed Properties', () => {
218
212
  it('should render the correct size class based on size prop', async () => {
219
213
  await wrapper.setProps({ size: 'lg' });
220
- expect(drawerContainer().classes()).toContain(
214
+ expect(drawerContentComponent().props('class')).toContain(
221
215
  'unnnic-drawer__container--lg',
222
216
  );
217
+ expect(drawerContentComponent().props('size')).toBe('large');
223
218
 
224
219
  await wrapper.setProps({ size: 'xl' });
225
- expect(drawerContainer().classes()).toContain(
220
+ expect(drawerContentComponent().props('class')).toContain(
226
221
  'unnnic-drawer__container--xl',
227
222
  );
223
+ expect(drawerContentComponent().props('size')).toBe('extra-large');
228
224
  });
229
225
 
230
226
  it('should display footer if either primaryButtonText or secondaryButtonText is provided', async () => {
@@ -1,22 +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
- "<div data-v-196de012="" open="true" class="unnnic-drawer" data-testid="drawer">
5
- <div data-v-196de012="" showoverlay="true" data-testid="drawer-container" size="medium" class="unnnic-drawer__container unnnic-drawer__container--md">
4
+ "<div data-v-e761d31f="" data-v-196de012="" disabled="false" defer="false" forcemount="false" data-testid="drawer-container">
5
+ <div data-v-7f241b30="" data-v-e761d31f="" data-state="open" style="pointer-events: auto;" data-vaul-overlay="" data-vaul-snap-points="false" data-vaul-snap-points-overlay="true" class="unnnic-drawer__overlay"></div>
6
+ <div data-v-e761d31f="" data-dismissable-layer="" style="--snap-point-height: 0; --initial-transform: calc(100% + 8px); pointer-events: auto;" tabindex="-1" data-vaul-drawer="" data-vaul-drawer-direction="right" data-vaul-delayed-snap-points="false" data-vaul-snap-points="false" size="medium" showoverlay="true" class="unnnic-drawer__content unnnic-drawer__content--medium unnnic-drawer__container unnnic-drawer__container--md" id="" role="dialog" aria-describedby="reka-dialog-description-v-1" aria-labelledby="reka-dialog-title-v-0" data-state="open">
6
7
  <header data-v-39d0dfb8="" data-v-196de012="" class="unnnic-drawer__header unnnic-drawer__header">
7
8
  <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="">
9
+ <h2 data-v-97709962="" data-v-196de012="" id="reka-dialog-title-v-0" class="unnnic-drawer__title unnnic-drawer__title" data-testid="drawer-title">Test Title</h2>
10
+ <p data-v-750ea255="" data-v-196de012="" id="reka-dialog-description-v-1" class="unnnic-drawer__description unnnic-drawer__description" data-testid="drawer-description">Test Description</p>
11
+ </section><button data-v-4a771f40="" data-v-196de012="" type="button" class="unnnic-drawer__close">
12
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>
13
+ </button>
14
14
  </header>
15
15
  <section data-v-196de012="" class="unnnic-drawer__content"></section>
16
- <div data-v-196de012="" class="unnnic-drawer__footer" data-testid="footer">
16
+ <footer data-v-02ebc5b4="" data-v-196de012="" class="unnnic-drawer__footer unnnic-drawer__footer" data-testid="footer">
17
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
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>
19
+ </footer>
20
20
  </div>
21
21
  </div>"
22
22
  `;