@weni/unnnic-system 3.9.1-alpha.4 → 3.9.2

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 (233) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/dist/components/Accordion/Accordion.vue.d.ts +1 -1
  3. package/dist/components/Alert/Alert.vue.d.ts +116 -17
  4. package/dist/components/Alert/Alert.vue.d.ts.map +1 -1
  5. package/dist/components/Alert/Version1dot1.vue.d.ts +38 -2
  6. package/dist/components/Alert/Version1dot1.vue.d.ts.map +1 -1
  7. package/dist/components/AudioRecorder/AudioHandler.vue.d.ts +2 -2
  8. package/dist/components/AudioRecorder/AudioPlayer.vue.d.ts +1 -1
  9. package/dist/components/AudioRecorder/AudioRecorder.vue.d.ts +5 -5
  10. package/dist/components/AvatarIcon/AvatarIcon.vue.d.ts +3 -3
  11. package/dist/components/Banner/Banner.vue.d.ts +1 -1
  12. package/dist/components/Banner/InfoBanner.vue.d.ts +1 -1
  13. package/dist/components/Breadcrumb/Breadcrumb.vue.d.ts +1 -1
  14. package/dist/components/Button/Button.vue.d.ts +1 -1
  15. package/dist/components/Button/Button.vue.d.ts.map +1 -1
  16. package/dist/components/Button/ButtonIcon.vue.d.ts +1 -1
  17. package/dist/components/Button/types.d.ts +1 -1
  18. package/dist/components/Button/types.d.ts.map +1 -1
  19. package/dist/components/Card/AccountCard.vue.d.ts +5 -5
  20. package/dist/components/Card/BlankCard.vue.d.ts +1 -1
  21. package/dist/components/Card/Card.vue.d.ts +27 -27
  22. package/dist/components/Card/CardCompany.vue.d.ts +414 -11
  23. package/dist/components/Card/CardData.vue.d.ts +1 -1
  24. package/dist/components/Card/CardStatusesContainer.vue.d.ts +5 -5
  25. package/dist/components/Card/ContentCard.vue.d.ts +3 -3
  26. package/dist/components/Card/DashCard.vue.d.ts +5 -5
  27. package/dist/components/Card/DefaultCard.vue.d.ts +1 -1
  28. package/dist/components/Card/MarketplaceCard.vue.d.ts +2 -2
  29. package/dist/components/Card/SimpleCard.vue.d.ts +3 -3
  30. package/dist/components/Card/StatusCard.vue.d.ts +2 -2
  31. package/dist/components/Card/TitleCard.vue.d.ts +3 -3
  32. package/dist/components/CardImage/CardImage.vue.d.ts +31 -24
  33. package/dist/components/CardInformation/CardInformation.vue.d.ts +5 -5
  34. package/dist/components/CardProject/CardProject.vue.d.ts +3 -3
  35. package/dist/components/Carousel/Carousel.vue.d.ts +416 -13
  36. package/dist/components/Carousel/TagCarousel.vue.d.ts +415 -12
  37. package/dist/components/ChartBar/ChartBar.vue.d.ts +5 -5
  38. package/dist/components/ChartLine/ChartLine.vue.d.ts +1 -1
  39. package/dist/components/ChatText/ChatText.vue.d.ts +2 -2
  40. package/dist/components/ChatsContact/ChatsContact.vue.d.ts +446 -21
  41. package/dist/components/ChatsDashboardTagLive/ChatsDashboardTagLive.vue.d.ts +1 -1
  42. package/dist/components/ChatsHeader/ChatsHeader.vue.d.ts +1 -1
  43. package/dist/components/ChatsHeader/ChatsHeader.vue.d.ts.map +1 -1
  44. package/dist/components/ChatsMessage/ChatsMessage.vue.d.ts +5 -5
  45. package/dist/components/ChatsMessage/ChatsMessageStatusBackdrop.vue.d.ts +2 -2
  46. package/dist/components/ChatsNavbar/ChatsNavbar.vue.d.ts +1 -1
  47. package/dist/components/ChatsUserAvatar/ChatsUserAvatar.vue.d.ts +2 -2
  48. package/dist/components/Checkbox/Checkbox.vue.d.ts +26 -19
  49. package/dist/components/Checkbox/Checkbox.vue.d.ts.map +1 -1
  50. package/dist/components/Comment/Comment.vue.d.ts +1 -1
  51. package/dist/components/DataArea/DataArea.vue.d.ts +2 -2
  52. package/dist/components/DataTable/index.vue.d.ts +12 -2
  53. package/dist/components/DataTable/index.vue.d.ts.map +1 -1
  54. package/dist/components/DateFilter/DateFilter.vue.d.ts +39 -170
  55. package/dist/components/DatePicker/DatePicker.vue.d.ts +4 -4
  56. package/dist/components/Drawer/Drawer.vue.d.ts +4 -4
  57. package/dist/components/Dropdown/Dropdown.vue.d.ts +1 -1
  58. package/dist/components/Dropdown/LanguageSelect.vue.d.ts +3 -3
  59. package/dist/components/Flag.vue.d.ts +2 -2
  60. package/dist/components/FormElement/FormElement.vue.d.ts +28 -51
  61. package/dist/components/FormElement/FormElement.vue.d.ts.map +1 -1
  62. package/dist/components/Icon.vue.d.ts +1 -1
  63. package/dist/components/Icon.vue.d.ts.map +1 -1
  64. package/dist/components/IconLoading/IconLoading.vue.d.ts +1 -1
  65. package/dist/components/ImportCard/ImportCard.vue.d.ts +4 -4
  66. package/dist/components/Input/BaseInput.vue.d.ts +2 -11
  67. package/dist/components/Input/BaseInput.vue.d.ts.map +1 -1
  68. package/dist/components/Input/Input.vue.d.ts +39 -170
  69. package/dist/components/Input/Input.vue.d.ts.map +1 -1
  70. package/dist/components/Input/TextInput.vue.d.ts +24 -33
  71. package/dist/components/Input/TextInput.vue.d.ts.map +1 -1
  72. package/dist/components/InputDatePicker/InputDatePicker.vue.d.ts +44 -175
  73. package/dist/components/InputNext/InputNext.vue.d.ts +4 -4
  74. package/dist/components/Label/Label.vue.d.ts +15 -9
  75. package/dist/components/Label/Label.vue.d.ts.map +1 -1
  76. package/dist/components/Modal/Modal.vue.d.ts +2 -2
  77. package/dist/components/ModalDialog/ModalDialog.vue.d.ts +6 -6
  78. package/dist/components/ModalNext/ModalNext.vue.d.ts +44 -175
  79. package/dist/components/ModalUpload/ModalUpload.vue.d.ts +9 -9
  80. package/dist/components/MoodRating/MoodRating.vue.d.ts +1 -1
  81. package/dist/components/MultiSelect/MultiSelect.vue.d.ts +14 -26
  82. package/dist/components/Pagination/Pagination.vue.d.ts +3 -3
  83. package/dist/components/ProgressBar/ProgressBar.vue.d.ts +1 -1
  84. package/dist/components/Radio/Radio.vue.d.ts +6 -10
  85. package/dist/components/Radio/Radio.vue.d.ts.map +1 -1
  86. package/dist/components/SelectSmart/SelectSmart.vue.d.ts +512 -69
  87. package/dist/components/SelectSmart/SelectSmart.vue.d.ts.map +1 -1
  88. package/dist/components/SelectSmart/SelectSmartMultipleHeader.vue.d.ts +414 -11
  89. package/dist/components/SelectSmart/SelectSmartOption.vue.d.ts +28 -21
  90. package/dist/components/SelectSmart/SelectSmartOption.vue.d.ts.map +1 -1
  91. package/dist/components/SelectTime/index.vue.d.ts +24 -33
  92. package/dist/components/SkeletonLoading/skeletonTheme.vue.d.ts +1 -1
  93. package/dist/components/Slider/Slider.vue.d.ts +2 -2
  94. package/dist/components/StarRating/StarRating.vue.d.ts +1 -1
  95. package/dist/components/Switch/Switch.vue.d.ts +21 -55
  96. package/dist/components/Switch/Switch.vue.d.ts.map +1 -1
  97. package/dist/components/Tab/Tab.vue.d.ts +2 -13
  98. package/dist/components/TableNext/TableBodyCell.vue.d.ts +2 -2
  99. package/dist/components/TableNext/TablePagination.vue.d.ts +3 -3
  100. package/dist/components/TabsExpanded/TabsExpanded.vue.d.ts +1 -1
  101. package/dist/components/Tag/BrandTag.vue.d.ts +51 -0
  102. package/dist/components/Tag/BrandTag.vue.d.ts.map +1 -0
  103. package/dist/components/Tag/DefaultTag.vue.d.ts +83 -4
  104. package/dist/components/Tag/DefaultTag.vue.d.ts.map +1 -1
  105. package/dist/components/Tag/IndicatorTag.vue.d.ts +151 -0
  106. package/dist/components/Tag/IndicatorTag.vue.d.ts.map +1 -0
  107. package/dist/components/Tag/Tag.vue.d.ts +414 -12
  108. package/dist/components/Tag/Tag.vue.d.ts.map +1 -1
  109. package/dist/components/Tag/TagNext.vue.d.ts +24 -0
  110. package/dist/components/Tag/TagNext.vue.d.ts.map +1 -0
  111. package/dist/components/TextArea/TextArea.vue.d.ts +30 -75
  112. package/dist/components/TextArea/TextArea.vue.d.ts.map +1 -1
  113. package/dist/components/ToolTip/ToolTip.vue.d.ts +1 -1
  114. package/dist/components/Tour/Tour.vue.d.ts +3 -3
  115. package/dist/components/Tour/TourPopover.vue.d.ts +3 -3
  116. package/dist/components/UploadArea/UploadArea.vue.d.ts +4 -4
  117. package/dist/components/index.d.ts +6402 -4331
  118. package/dist/components/index.d.ts.map +1 -1
  119. package/dist/components/ui/popover/PopoverContent.vue.d.ts +1 -1
  120. package/dist/components/ui/popover/PopoverContent.vue.d.ts.map +1 -1
  121. package/dist/{es-db30a2ff.mjs → es-4aab69cb.mjs} +1 -1
  122. package/dist/{index-761bb714.mjs → index-789225a6.mjs} +10023 -10092
  123. package/dist/{pt-br-569fa4c1.mjs → pt-br-2f695ddd.mjs} +1 -1
  124. package/dist/style.css +1 -1
  125. package/dist/unnnic.mjs +151 -158
  126. package/dist/unnnic.umd.js +43 -42
  127. package/dist/utils/call.d.ts +1 -2
  128. package/dist/utils/call.d.ts.map +1 -1
  129. package/package.json +2 -2
  130. package/src/components/Alert/Alert.vue +135 -26
  131. package/src/components/Alert/AlertBanner.vue +182 -0
  132. package/src/components/Alert/AlertCaller.vue +49 -0
  133. package/src/components/Alert/Version1dot1.vue +36 -0
  134. package/src/components/Alert/__tests__/Alert.spec.js +45 -2
  135. package/src/components/Alert/__tests__/AlertBanner.spec.js +89 -0
  136. package/src/components/Alert/__tests__/AlertCaller.spec.js +98 -0
  137. package/src/components/Alert/__tests__/Version1dot1.spec.js +21 -0
  138. package/src/components/Alert/__tests__/__snapshots__/Alert.spec.js.snap +7 -11
  139. package/src/components/Alert/__tests__/__snapshots__/AlertBanner.spec.js.snap +2 -2
  140. package/src/components/Alert/__tests__/__snapshots__/Version1dot1.spec.js.snap +1 -1
  141. package/src/components/Button/Button.vue +117 -67
  142. package/src/components/Button/types.ts +1 -0
  143. package/src/components/ChatsContact/ChatsContact.vue +6 -10
  144. package/src/components/Checkbox/Checkbox.vue +65 -117
  145. package/src/components/Checkbox/__tests__/Checkbox.spec.js +21 -6
  146. package/src/components/DataTable/index.vue +48 -0
  147. package/src/components/FormElement/FormElement.vue +93 -63
  148. package/src/components/Icon.vue +0 -2
  149. package/src/components/Input/BaseInput.vue +12 -12
  150. package/src/components/Input/Input.scss +20 -19
  151. package/src/components/Input/Input.vue +55 -60
  152. package/src/components/Input/TextInput.vue +54 -25
  153. package/src/components/Input/__test__/Input.spec.js +33 -13
  154. package/src/components/Input/__test__/TextInput.spec.js +8 -6
  155. package/src/components/Input/__test__/__snapshots__/Input.spec.js.snap +5 -14
  156. package/src/components/Input/__test__/__snapshots__/TextInput.spec.js.snap +1 -1
  157. package/src/components/Label/Label.vue +21 -52
  158. package/src/components/Label/__tests__/Label.spec.js +1 -1
  159. package/src/components/Label/__tests__/__snapshots__/Label.spec.js.snap +1 -1
  160. package/src/components/Radio/Radio.vue +66 -118
  161. package/src/components/Radio/__test__/Radio.spec.js +20 -14
  162. package/src/components/Radio/__test__/__snapshots__/Radio.spec.js.snap +3 -4
  163. package/src/components/SelectSmart/SelectSmart.vue +129 -28
  164. package/src/components/SelectSmart/__tests__/SelectSmart.spec.js +180 -4
  165. package/src/components/Switch/Switch.vue +91 -132
  166. package/src/components/Switch/__tests__/Switch.spec.js +75 -8
  167. package/src/components/Switch/__tests__/__snapshots__/Switch.spec.js.snap +6 -5
  168. package/src/components/Tab/Tab.vue +23 -37
  169. package/src/components/Tab/__test__/__snapshots__/Tab.spec.js.snap +1 -1
  170. package/src/components/TableNext/__test__/__snapshots__/TableNext.spec.js.snap +2 -2
  171. package/src/components/TableNext/__test__/__snapshots__/TablePagination.spec.js.snap +2 -2
  172. package/src/components/Tag/BrandTag.vue +96 -0
  173. package/src/components/Tag/DefaultTag.vue +107 -51
  174. package/src/components/Tag/IndicatorTag.vue +107 -0
  175. package/src/components/Tag/Tag.vue +79 -32
  176. package/src/components/Tag/TagNext.vue +60 -0
  177. package/src/components/TextArea/TextArea.vue +11 -40
  178. package/src/components/TextArea/__test__/__snapshots__/TextArea.spec.js.snap +3 -11
  179. package/src/components/index.ts +18 -33
  180. package/src/stories/Alert.stories.js +67 -6
  181. package/src/stories/Button.stories.js +39 -29
  182. package/src/stories/Checkbox.stories.js +4 -11
  183. package/src/stories/DataTable.stories.js +192 -0
  184. package/src/stories/Input.stories.js +76 -71
  185. package/src/stories/Label.stories.js +0 -7
  186. package/src/stories/Radio.stories.js +1 -28
  187. package/src/stories/SelectSmart.stories.js +289 -0
  188. package/src/stories/Switch.stories.js +5 -10
  189. package/src/stories/Tab.stories.js +4 -11
  190. package/src/stories/Tag.stories.js +43 -24
  191. package/src/stories/TextArea.stories.js +2 -14
  192. package/src/types/scheme-colors.d.ts +0 -1
  193. package/src/utils/call.js +18 -46
  194. package/dist/assets/tokens/colors.json.d.ts +0 -376
  195. package/dist/components/CheckboxGroup/CheckboxGroup.vue.d.ts +0 -28
  196. package/dist/components/CheckboxGroup/CheckboxGroup.vue.d.ts.map +0 -1
  197. package/dist/components/PageHeader/PageHeader.vue.d.ts +0 -28
  198. package/dist/components/PageHeader/PageHeader.vue.d.ts.map +0 -1
  199. package/dist/components/PageHeader/index.d.ts +0 -3
  200. package/dist/components/PageHeader/index.d.ts.map +0 -1
  201. package/dist/components/PageHeader/types.d.ts +0 -9
  202. package/dist/components/PageHeader/types.d.ts.map +0 -1
  203. package/dist/components/Tag/types.d.ts +0 -18
  204. package/dist/components/Tag/types.d.ts.map +0 -1
  205. package/dist/components/Toast/Toast.vue.d.ts +0 -16
  206. package/dist/components/Toast/Toast.vue.d.ts.map +0 -1
  207. package/dist/components/Toast/ToastManager.d.ts +0 -14
  208. package/dist/components/Toast/ToastManager.d.ts.map +0 -1
  209. package/dist/components/Toast/types.d.ts +0 -35
  210. package/dist/components/Toast/types.d.ts.map +0 -1
  211. package/src/assets/icons/checkbox-checked-disabled.svg +0 -3
  212. package/src/assets/icons/checkbox-checked.svg +0 -3
  213. package/src/assets/icons/checkbox-less-disabled.svg +0 -3
  214. package/src/assets/icons/checkbox-less.svg +0 -3
  215. package/src/assets/icons/radio-checked.svg +0 -3
  216. package/src/assets/icons/switch-checked-disabled.svg +0 -3
  217. package/src/assets/icons/switch-checked.svg +0 -3
  218. package/src/components/CheckboxGroup/CheckboxGroup.vue +0 -96
  219. package/src/components/PageHeader/PageHeader.vue +0 -148
  220. package/src/components/PageHeader/index.ts +0 -2
  221. package/src/components/PageHeader/types.ts +0 -10
  222. package/src/components/RadioGroup/RadioGroup.vue +0 -142
  223. package/src/components/Tag/types.ts +0 -19
  224. package/src/components/Toast/Toast.vue +0 -246
  225. package/src/components/Toast/ToastManager.ts +0 -110
  226. package/src/components/Toast/__tests__/Toast.spec.js +0 -291
  227. package/src/components/Toast/__tests__/ToastManager.spec.js +0 -294
  228. package/src/components/Toast/types.ts +0 -57
  229. package/src/stories/CheckboxGroup.stories.js +0 -105
  230. package/src/stories/PageHeader.stories.js +0 -330
  231. package/src/stories/RadioGroup.stories.js +0 -144
  232. package/src/stories/Toast.mdx +0 -123
  233. package/src/stories/Toast.stories.js +0 -126
@@ -258,17 +258,15 @@ describe('SelectSmart.vue', () => {
258
258
  });
259
259
 
260
260
  it('should emit onActiveChange when toggling dropdown visibility', async () => {
261
- // Open dropdown
262
261
  await input().trigger('click');
263
262
 
264
- // Close dropdown
265
263
  await input().trigger('click');
266
264
 
267
265
  const emittedEvents = wrapper.emitted('onActiveChange');
268
266
  expect(emittedEvents).toBeTruthy();
269
267
  expect(emittedEvents.length).toBe(2);
270
- expect(emittedEvents[0][0]).toBe(true); // opened
271
- expect(emittedEvents[1][0]).toBe(false); // closed
268
+ expect(emittedEvents[0][0]).toBe(true);
269
+ expect(emittedEvents[1][0]).toBe(false);
272
270
  });
273
271
 
274
272
  it('should emit onActiveChange when closing dropdown with escape key', async () => {
@@ -348,4 +346,182 @@ describe('SelectSmart.vue', () => {
348
346
  expect(option.props('activeColor')).toBe('primary');
349
347
  });
350
348
  });
349
+
350
+ describe('Infinite Scroll', () => {
351
+ beforeEach(() => {
352
+ mountWrapper({
353
+ options,
354
+ infiniteScroll: true,
355
+ infiniteScrollDistance: 20,
356
+ });
357
+ });
358
+
359
+ it('should have infiniteScrollLoading state initialized as false', () => {
360
+ expect(wrapper.vm.infiniteScrollLoading).toBe(false);
361
+ });
362
+
363
+ it('should not setup infinite scroll when infiniteScroll prop is false', async () => {
364
+ await wrapper.setProps({ infiniteScroll: false });
365
+ const setupSpy = vi.spyOn(wrapper.vm, 'setupInfiniteScroll');
366
+
367
+ wrapper.vm.active = true;
368
+ await nextTick();
369
+
370
+ expect(setupSpy).not.toHaveBeenCalled();
371
+ });
372
+
373
+ it('should set infiniteScrollLoading to false when finishInfiniteScroll is called', async () => {
374
+ wrapper.vm.infiniteScrollLoading = true;
375
+
376
+ wrapper.vm.finishInfiniteScroll();
377
+
378
+ expect(wrapper.vm.infiniteScrollLoading).toBe(false);
379
+ });
380
+
381
+ it('should reset infiniteScrollLoading when resetInfiniteScroll is called', () => {
382
+ wrapper.vm.infiniteScrollLoading = true;
383
+
384
+ wrapper.vm.resetInfiniteScroll();
385
+
386
+ expect(wrapper.vm.infiniteScrollLoading).toBe(false);
387
+ });
388
+
389
+ it('should emit scroll-end event when infinite scroll is triggered', async () => {
390
+ wrapper.vm.active = true;
391
+ await nextTick();
392
+
393
+ wrapper.vm.infiniteScrollLoading = false;
394
+ wrapper.vm.$emit('scroll-end');
395
+
396
+ expect(wrapper.emitted('scroll-end')).toBeTruthy();
397
+ });
398
+
399
+ it('should not emit scroll-end when infiniteScrollLoading is true', async () => {
400
+ wrapper.vm.active = true;
401
+ wrapper.vm.infiniteScrollLoading = true;
402
+ await nextTick();
403
+
404
+ wrapper.vm.infiniteScrollCanLoadMore();
405
+
406
+ expect(wrapper.vm.infiniteScrollLoading).toBe(true);
407
+ });
408
+
409
+ it('should setup infinite scroll when dropdown opens', async () => {
410
+ const setupSpy = vi.spyOn(wrapper.vm, 'setupInfiniteScroll');
411
+
412
+ wrapper.vm.active = true;
413
+ await nextTick();
414
+ await nextTick();
415
+
416
+ expect(setupSpy).toHaveBeenCalled();
417
+ });
418
+
419
+ it('should display loading indicator when infiniteScrollLoading is true', async () => {
420
+ await wrapper.setProps({ infiniteScroll: true });
421
+ wrapper.vm.active = true;
422
+ wrapper.vm.infiniteScrollLoading = true;
423
+ await nextTick();
424
+
425
+ const loadingIndicator = wrapper.find(
426
+ '.unnnic-select-smart__options-infinite-loading',
427
+ );
428
+ expect(loadingIndicator.exists()).toBe(true);
429
+ });
430
+
431
+ it('should not display loading indicator when infiniteScrollLoading is false', async () => {
432
+ await wrapper.setProps({ infiniteScroll: true });
433
+ wrapper.vm.active = true;
434
+ wrapper.vm.infiniteScrollLoading = false;
435
+ await nextTick();
436
+
437
+ const loadingIndicator = wrapper.find(
438
+ '.unnnic-select-smart__options-infinite-loading',
439
+ );
440
+ expect(loadingIndicator.exists()).toBe(false);
441
+ });
442
+
443
+ it('should not display infinite scroll loading when infiniteScroll is false', async () => {
444
+ await wrapper.setProps({ infiniteScroll: false });
445
+ wrapper.vm.active = true;
446
+ wrapper.vm.infiniteScrollLoading = true;
447
+ await nextTick();
448
+
449
+ const loadingIndicator = wrapper.find(
450
+ '.unnnic-select-smart__options-infinite-loading',
451
+ );
452
+ expect(loadingIndicator.exists()).toBe(false);
453
+ });
454
+
455
+ it('should not interfere with initial isLoading prop', async () => {
456
+ await wrapper.setProps({
457
+ isLoading: true,
458
+ infiniteScroll: true,
459
+ });
460
+ wrapper.vm.active = true;
461
+ await nextTick();
462
+
463
+ const mainLoading = wrapper.findComponent({ name: 'UnnnicIconLoading' });
464
+ expect(mainLoading.exists()).toBe(true);
465
+
466
+ expect(wrapper.vm.infiniteScrollLoading).toBe(false);
467
+ });
468
+ });
469
+
470
+ describe('External Search (disableInternalFilter)', () => {
471
+ const searchOptions = [
472
+ { label: 'Apple', value: 'apple' },
473
+ { label: 'Banana', value: 'banana' },
474
+ { label: 'Orange', value: 'orange' },
475
+ ];
476
+
477
+ beforeEach(() => {
478
+ mountWrapper({
479
+ options: searchOptions,
480
+ autocomplete: true,
481
+ });
482
+ });
483
+
484
+ it('should apply internal filter by default', async () => {
485
+ wrapper.vm.active = true;
486
+ await wrapper.setData({ searchValue: 'ap' });
487
+
488
+ const filteredOptions = wrapper.vm.filterOptions(searchOptions);
489
+
490
+ expect(filteredOptions.length).toBe(1);
491
+ expect(filteredOptions[0].label).toBe('Apple');
492
+ });
493
+
494
+ it('should skip internal filter when disableInternalFilter is true', async () => {
495
+ await wrapper.setProps({ disableInternalFilter: true });
496
+ wrapper.vm.active = true;
497
+ await wrapper.setData({ searchValue: 'ap' });
498
+
499
+ const filteredOptions = wrapper.vm.filterOptions(searchOptions);
500
+
501
+ expect(filteredOptions.length).toBe(3);
502
+ expect(filteredOptions).toEqual(searchOptions);
503
+ });
504
+
505
+ it('should emit update:searchValue when user types', async () => {
506
+ wrapper.vm.active = true;
507
+ await wrapper.setData({ searchValue: 'test' });
508
+
509
+ expect(wrapper.emitted('update:searchValue')).toBeTruthy();
510
+ expect(wrapper.emitted('update:searchValue')[0][0]).toBe('test');
511
+ });
512
+
513
+ it('should allow parent to control filtering via options prop', async () => {
514
+ await wrapper.setProps({ disableInternalFilter: true });
515
+ wrapper.vm.active = true;
516
+ await nextTick();
517
+
518
+ const filteredByParent = [{ label: 'Apple', value: 'apple' }];
519
+ await wrapper.setProps({ options: filteredByParent });
520
+
521
+ const displayedOptions = wrapper.vm.filterOptions(filteredByParent);
522
+
523
+ expect(displayedOptions.length).toBe(1);
524
+ expect(displayedOptions[0].label).toBe('Apple');
525
+ });
526
+ });
351
527
  });
@@ -1,60 +1,49 @@
1
1
  <template>
2
- <section class="unnnic-switch">
3
- <UnnnicLabel
4
- v-if="label"
5
- :label="label"
6
- :tooltip="labelTooltip"
7
- :useHtmlTooltip="labelUseHtmlTooltip"
8
- class="unnnic-switch__label"
2
+ <div class="unnnic-switch">
3
+ <div
4
+ v-if="textLeft"
5
+ data-test-id="switch-text-left"
6
+ :class="[
7
+ 'unnnic-switch__label',
8
+ 'unnnic-switch__label__left',
9
+ `unnnic-switch__label__${size}`,
10
+ ]"
11
+ >
12
+ {{ textLeft }}
13
+ </div>
14
+
15
+ <UnnnicIcon
16
+ :class="{ 'unnnic-switch__icon': true, active: isActive }"
17
+ :icon="currentIcon"
18
+ :size="iconSize"
19
+ :scheme="iconScheme"
20
+ :lineHeight="iconLineHeight"
21
+ :disabled="disabled"
22
+ :clickable="!disabled"
23
+ data-test-id="switch-icon"
24
+ @click="toggleState"
9
25
  />
10
26
 
11
- <label
27
+ <div
28
+ v-if="textRight"
29
+ data-test-id="switch-text-right"
12
30
  :class="[
13
- 'unnnic-switch__input-wrapper',
14
- { 'unnnic-switch__input-wrapper--disabled': disabled },
31
+ 'unnnic-switch__label',
32
+ 'unnnic-switch__label__right',
33
+ `unnnic-switch__label__${size}`,
15
34
  ]"
16
35
  >
17
- <input
18
- class="unnnic-switch__input"
19
- type="checkbox"
20
- :disabled="disabled"
21
- :checked="modelValue"
22
- @change="toggleState"
23
- v-bind="pick($attrs, ['id', 'name'])"
24
- />
25
-
26
- <p
27
- v-if="option || textLeft || textRight"
28
- :class="[
29
- 'unnnic-switch__option',
30
- { 'unnnic-switch__option--disabled': disabled },
31
- ]"
32
- data-testid="switch-option"
33
- >
34
- {{ option }}
35
- {{ textLeft }}
36
- {{ textRight }}
37
- </p>
38
- </label>
39
-
40
- <p
41
- v-if="helper"
42
- class="unnnic-switch__helper"
43
- >
44
- {{ helper }}
45
- </p>
46
- </section>
36
+ {{ textRight }}
37
+ </div>
38
+ </div>
47
39
  </template>
48
40
 
49
41
  <script>
50
- import { pick } from 'lodash';
51
- import UnnnicLabel from '../Label/Label.vue';
42
+ import UnnnicIcon from '../Icon.vue';
52
43
 
53
44
  export default {
54
45
  name: 'UnnnicSwitch',
55
- components: {
56
- UnnnicLabel,
57
- },
46
+ components: { UnnnicIcon },
58
47
  props: {
59
48
  size: {
60
49
  type: String,
@@ -63,32 +52,6 @@ export default {
63
52
  return ['small', 'medium'].indexOf(value) !== -1;
64
53
  },
65
54
  },
66
-
67
- label: {
68
- type: String,
69
- default: '',
70
- },
71
-
72
- labelTooltip: {
73
- type: String,
74
- default: '',
75
- },
76
-
77
- labelUseHtmlTooltip: {
78
- type: Boolean,
79
- default: false,
80
- },
81
-
82
- option: {
83
- type: String,
84
- default: '',
85
- },
86
-
87
- helper: {
88
- type: String,
89
- default: '',
90
- },
91
-
92
55
  textLeft: {
93
56
  type: String,
94
57
  default: '',
@@ -115,6 +78,33 @@ export default {
115
78
  isActive: false,
116
79
  };
117
80
  },
81
+ computed: {
82
+ currentIcon() {
83
+ if (this.disabled) {
84
+ return this.isActive
85
+ ? 'switch-selected-disabled'
86
+ : 'switch-default-disabled';
87
+ }
88
+
89
+ return 'switch-default';
90
+ },
91
+
92
+ iconSize() {
93
+ return this.size === 'small' ? 'sm' : 'md';
94
+ },
95
+
96
+ iconScheme() {
97
+ if (this.disabled) {
98
+ return 'neutral-soft';
99
+ }
100
+
101
+ return this.isActive === false ? 'neutral-soft' : 'brand-weni';
102
+ },
103
+
104
+ iconLineHeight() {
105
+ return this.size === 'small' ? 'sm' : '';
106
+ },
107
+ },
118
108
 
119
109
  watch: {
120
110
  modelValue: {
@@ -126,8 +116,6 @@ export default {
126
116
  },
127
117
 
128
118
  methods: {
129
- pick,
130
-
131
119
  toggleState() {
132
120
  if (!this.disabled) {
133
121
  if (this.useVModel) {
@@ -145,80 +133,51 @@ export default {
145
133
  <style lang="scss" scoped>
146
134
  @use '@/assets/scss/unnnic' as *;
147
135
 
148
- $switch-width: 38px;
149
- $switch-height: 20px;
150
-
151
136
  .unnnic-switch {
152
137
  display: flex;
153
- flex-direction: column;
154
-
155
- &__input-wrapper {
156
- width: fit-content;
138
+ flex-direction: row;
157
139
 
158
- display: flex;
159
- align-items: center;
160
- column-gap: $unnnic-space-2;
140
+ &__label {
141
+ font-family: $unnnic-font-family-secondary;
142
+ font-weight: $unnnic-font-weight-regular;
143
+ color: $unnnic-color-neutral-dark;
161
144
 
162
- cursor: pointer;
145
+ margin: $unnnic-spacing-stack-nano 0;
146
+ margin-right: $unnnic-inline-nano;
163
147
 
164
- &--disabled {
165
- cursor: not-allowed;
148
+ &__small {
149
+ font-size: $unnnic-font-size-body-md;
150
+ line-height: $unnnic-font-size-body-md + $unnnic-line-height-md;
166
151
  }
167
- }
168
-
169
- &__input {
170
- appearance: none;
171
- width: $switch-width;
172
- min-width: $switch-width;
173
- height: $switch-height;
174
- margin: 0;
175
- background-color: $unnnic-color-bg-muted;
176
- border-radius: $unnnic-radius-3;
177
- box-sizing: border-box;
178
- outline: none;
179
-
180
- background-image: url('@/assets/icons/switch-checked.svg');
181
- background-repeat: no-repeat;
182
- background-position: 4px center;
183
-
184
- transition:
185
- 120ms linear background-position,
186
- 120ms linear background-color;
187
-
188
- cursor: pointer;
189
-
190
- &:checked {
191
- background-color: $unnnic-color-bg-active;
192
- background-position: 20px center;
193
- }
194
-
195
- &:disabled {
196
- background-color: $unnnic-color-bg-muted;
197
- background-image: url('@/assets/icons/switch-checked-disabled.svg');
198
152
 
199
- cursor: not-allowed;
153
+ &__medium {
154
+ font-size: $unnnic-font-size-body-gt;
155
+ line-height: $unnnic-font-size-body-gt + $unnnic-line-height-md;
200
156
  }
201
157
  }
202
158
 
203
- &__label {
204
- margin-bottom: $unnnic-space-3;
205
- }
159
+ &__icon {
160
+ align-self: center;
161
+ margin: $unnnic-spacing-stack-nano $unnnic-inline-nano;
206
162
 
207
- &__option {
208
- margin: 0;
209
- font: $unnnic-font-body;
210
- color: $unnnic-color-fg-emphasized;
163
+ :deep(#default-circle) {
164
+ transition: 0.2s linear transform;
165
+ }
211
166
 
212
- &--disabled {
213
- color: $unnnic-color-fg-muted;
167
+ &.active {
168
+ :deep(#default-circle) {
169
+ transform: translateX(45%);
170
+ }
214
171
  }
215
172
  }
173
+ }
216
174
 
217
- &__helper {
218
- margin: 0;
219
- margin-left: $switch-width + $unnnic-space-2;
220
- font: $unnnic-font-caption-2;
221
- color: $unnnic-color-fg-base;
175
+ .unnnic-icon__size {
176
+ &--md {
177
+ width: 3 * $unnnic-font-size;
178
+ }
179
+ &--sm {
180
+ width: 2 * $unnnic-font-size;
222
181
  }
223
182
  }
224
183
  </style>
@@ -12,26 +12,93 @@ describe('Switch', () => {
12
12
  beforeEach(() => {
13
13
  wrapper = createWrapper({ modelValue: false });
14
14
  });
15
+ it('should render the component correctly with default props', () => {
16
+ expect(wrapper.exists()).toBe(true);
17
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).exists()).toBe(true);
18
+ expect(wrapper.text()).toBe('');
19
+ });
20
+
21
+ it('should render the left text (textLeft) when provided', async () => {
22
+ await wrapper.setProps({ textLeft: 'Left Text' });
23
+
24
+ // This check ensures that the icon is placed before the switch text
25
+ const switchChildren = wrapper.findComponent(Switch).element.children;
26
+ expect(switchChildren[0].getAttribute('data-test-id')).toBe(
27
+ 'switch-text-left',
28
+ );
29
+ expect(switchChildren[1].getAttribute('data-test-id')).toBe('switch-icon');
30
+ });
31
+
32
+ it('should render the right text (textRight) when provided', async () => {
33
+ await wrapper.setProps({ textRight: 'Right Text' });
34
+
35
+ // This check ensures that the icon is placed after the switch text
36
+ const switchChildren = wrapper.findComponent(Switch).element.children;
37
+ expect(switchChildren[0].getAttribute('data-test-id')).toBe('switch-icon');
38
+ expect(switchChildren[1].getAttribute('data-test-id')).toBe(
39
+ 'switch-text-right',
40
+ );
41
+ });
42
+
43
+ it('should render the correct icon when the switch is disabled/enabled', async () => {
44
+ await wrapper.setProps({ disabled: true });
45
+ const disabledIconComponent = wrapper.findComponent({ name: 'UnnnicIcon' });
46
+ expect(disabledIconComponent.props('icon')).toBe('switch-default-disabled');
15
47
 
16
- it('should render the option when provided', async () => {
17
- await wrapper.setProps({ option: 'Option Text' });
48
+ await wrapper.setProps({ modelValue: true });
49
+ const enabledIconComponent = wrapper.findComponent({ name: 'UnnnicIcon' });
50
+ expect(enabledIconComponent.props('icon')).toBe('switch-selected-disabled');
51
+ });
18
52
 
19
- const switchOption = wrapper.find('[data-testid="switch-option"]');
20
- expect(switchOption.text()).toBe('Option Text');
53
+ it('should render the correct icon based on the isActive state', async () => {
54
+ expect(wrapper.vm.isActive).toBe(false);
55
+ await wrapper.setProps({ modelValue: true });
56
+ expect(wrapper.vm.isActive).toBe(true);
57
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).props('icon')).toBe(
58
+ 'switch-default',
59
+ );
60
+ });
61
+
62
+ it('should render the correct icon size based on the size prop', async () => {
63
+ await wrapper.setProps({ size: 'small' });
64
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).props('size')).toBe(
65
+ 'sm',
66
+ );
67
+
68
+ await wrapper.setProps({ size: 'medium' });
69
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).props('size')).toBe(
70
+ 'md',
71
+ );
72
+ });
73
+
74
+ it('should change the icon color based on the state', async () => {
75
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).props('scheme')).toBe(
76
+ 'neutral-soft',
77
+ );
78
+
79
+ await wrapper.setProps({ modelValue: true });
80
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).props('scheme')).toBe(
81
+ 'brand-weni',
82
+ );
83
+
84
+ await wrapper.setProps({ disabled: true });
85
+ expect(wrapper.findComponent({ name: 'UnnnicIcon' }).props('scheme')).toBe(
86
+ 'neutral-soft',
87
+ );
21
88
  });
22
89
 
23
90
  it('should toggle isActive state and emit the correct event when toggleState is called', async () => {
24
91
  const initialIsActive = wrapper.vm.isActive;
25
- const switchInput = wrapper.find('input[type="checkbox"]');
26
- await switchInput.trigger('change');
92
+ const switchIcon = wrapper.findComponent('[ data-test-id="switch-icon"]');
93
+ await switchIcon.trigger('click');
27
94
  expect(wrapper.emitted('update:model-value')).toBeTruthy();
28
95
  expect(wrapper.vm.isActive).toBe(!initialIsActive);
29
96
  });
30
97
 
31
98
  it('should not change state when disabled is true', async () => {
32
99
  await wrapper.setProps({ disabled: true });
33
- const switchInput = wrapper.find('input[type="checkbox"]');
34
- await switchInput.trigger('change');
100
+ const switchIcon = wrapper.findComponent('[ data-test-id="switch-icon"]');
101
+ await switchIcon.trigger('click');
35
102
  expect(wrapper.emitted('update:model-value')).toBeFalsy();
36
103
  expect(wrapper.vm.isActive).toBe(false);
37
104
  });
@@ -1,10 +1,11 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`Switch > should match the snapshot 1`] = `
4
- "<section data-v-e4356c9d="" class="unnnic-switch">
5
- <!--v-if--><label data-v-e4356c9d="" class="unnnic-switch__input-wrapper"><input data-v-e4356c9d="" class="unnnic-switch__input" type="checkbox">
6
- <!--v-if-->
7
- </label>
4
+ "<div data-v-e4356c9d="" class="unnnic-switch">
5
+ <!--v-if--><svg data-v-3d58a7dd="" data-v-26446d8e="" data-v-e4356c9d="" id="default" width="80" height="40" viewBox="0 0 80 40" xmlns="http://www.w3.org/2000/svg" class="unnnic-icon unnnic-icon--size-svg-md unnnic-icon__size--md unnnic--clickable unnnic-icon-scheme--neutral-soft unnnic-switch__icon" data-testid="custom-icon" lineHeight="" disabled="false" data-test-id="switch-icon">
6
+ <rect data-v-3d58a7dd="" x="4.20013" y="2.10046" width="71.6" height="35.8" rx="17.9" class="primary"></rect>
7
+ <circle data-v-3d58a7dd="" id="default-circle" cx="22.5" cy="20.0005" r="12.5" fill="white"></circle>
8
+ </svg>
8
9
  <!--v-if-->
9
- </section>"
10
+ </div>"
10
11
  `;