@weni/unnnic-system 3.7.1 → 3.8.2-alpha.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 (263) hide show
  1. package/CHANGELOG.md +16 -1
  2. package/dist/components/Accordion/Accordion.vue.d.ts +1 -1
  3. package/dist/components/Alert/Alert.vue.d.ts +17 -116
  4. package/dist/components/Alert/Alert.vue.d.ts.map +1 -1
  5. package/dist/components/Alert/Version1dot1.vue.d.ts +2 -38
  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 +5 -5
  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 +24 -31
  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 +7 -7
  36. package/dist/components/Carousel/TagCarousel.vue.d.ts +6 -6
  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 +27 -34
  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 +19 -26
  49. package/dist/components/Checkbox/Checkbox.vue.d.ts.map +1 -1
  50. package/dist/components/CheckboxGroup/CheckboxGroup.vue.d.ts +28 -0
  51. package/dist/components/CheckboxGroup/CheckboxGroup.vue.d.ts.map +1 -0
  52. package/dist/components/Comment/Comment.vue.d.ts +1 -1
  53. package/dist/components/DataArea/DataArea.vue.d.ts +2 -2
  54. package/dist/components/DataTable/index.vue.d.ts +1 -1
  55. package/dist/components/DataTable/index.vue.d.ts.map +1 -1
  56. package/dist/components/DateFilter/DateFilter.vue.d.ts +251 -41
  57. package/dist/components/DatePicker/DatePicker.vue.d.ts +4 -4
  58. package/dist/components/Drawer/Drawer.vue.d.ts +4 -4
  59. package/dist/components/Dropdown/Dropdown.vue.d.ts +1 -1
  60. package/dist/components/Dropdown/LanguageSelect.vue.d.ts +3 -3
  61. package/dist/components/Flag.vue.d.ts +2 -2
  62. package/dist/components/FormElement/FormElement.vue.d.ts +51 -28
  63. package/dist/components/FormElement/FormElement.vue.d.ts.map +1 -1
  64. package/dist/components/Icon.vue.d.ts +1 -1
  65. package/dist/components/Icon.vue.d.ts.map +1 -1
  66. package/dist/components/IconLoading/IconLoading.vue.d.ts +1 -1
  67. package/dist/components/ImportCard/ImportCard.vue.d.ts +4 -4
  68. package/dist/components/Input/BaseInput.vue.d.ts +33 -2
  69. package/dist/components/Input/BaseInput.vue.d.ts.map +1 -1
  70. package/dist/components/Input/Input.vue.d.ts +251 -41
  71. package/dist/components/Input/Input.vue.d.ts.map +1 -1
  72. package/dist/components/Input/TextInput.vue.d.ts +85 -25
  73. package/dist/components/Input/TextInput.vue.d.ts.map +1 -1
  74. package/dist/components/InputDatePicker/InputDatePicker.vue.d.ts +257 -47
  75. package/dist/components/InputNext/InputNext.vue.d.ts +5 -5
  76. package/dist/components/Label/Label.vue.d.ts +9 -15
  77. package/dist/components/Label/Label.vue.d.ts.map +1 -1
  78. package/dist/components/Modal/Modal.vue.d.ts +2 -2
  79. package/dist/components/ModalDialog/ModalDialog.vue.d.ts +199 -34
  80. package/dist/components/ModalDialog/ModalDialog.vue.d.ts.map +1 -1
  81. package/dist/components/ModalNext/ModalNext.vue.d.ts +256 -46
  82. package/dist/components/ModalUpload/ModalUpload.vue.d.ts +8 -8
  83. package/dist/components/MoodRating/MoodRating.vue.d.ts +1 -1
  84. package/dist/components/MultiSelect/MultiSelect.vue.d.ts +20 -14
  85. package/dist/components/Pagination/Pagination.vue.d.ts +3 -3
  86. package/dist/components/ProgressBar/ProgressBar.vue.d.ts +1 -1
  87. package/dist/components/Radio/Radio.vue.d.ts +8 -6
  88. package/dist/components/Radio/Radio.vue.d.ts.map +1 -1
  89. package/dist/components/SelectSmart/SelectSmart.vue.d.ts +113 -60
  90. package/dist/components/SelectSmart/SelectSmartMultipleHeader.vue.d.ts +5 -5
  91. package/dist/components/SelectSmart/SelectSmartOption.vue.d.ts +21 -28
  92. package/dist/components/SelectSmart/SelectSmartOption.vue.d.ts.map +1 -1
  93. package/dist/components/SelectTime/index.vue.d.ts +85 -25
  94. package/dist/components/SkeletonLoading/skeletonTheme.vue.d.ts +1 -1
  95. package/dist/components/Slider/Slider.vue.d.ts +2 -2
  96. package/dist/components/StarRating/StarRating.vue.d.ts +1 -1
  97. package/dist/components/Switch/Switch.vue.d.ts +55 -21
  98. package/dist/components/Switch/Switch.vue.d.ts.map +1 -1
  99. package/dist/components/Tab/Tab.vue.d.ts +13 -2
  100. package/dist/components/TableNext/TableBodyCell.vue.d.ts +2 -2
  101. package/dist/components/TableNext/TablePagination.vue.d.ts +3 -3
  102. package/dist/components/TabsExpanded/TabsExpanded.vue.d.ts +1 -1
  103. package/dist/components/Tag/BrandTag.vue.d.ts +1 -1
  104. package/dist/components/Tag/DefaultTag.vue.d.ts +1 -1
  105. package/dist/components/Tag/IndicatorTag.vue.d.ts +2 -2
  106. package/dist/components/Tag/Tag.vue.d.ts +5 -5
  107. package/dist/components/TextArea/TextArea.vue.d.ts +66 -30
  108. package/dist/components/TextArea/TextArea.vue.d.ts.map +1 -1
  109. package/dist/components/Toast/Toast.vue.d.ts +16 -0
  110. package/dist/components/Toast/Toast.vue.d.ts.map +1 -0
  111. package/dist/components/Toast/ToastManager.d.ts +14 -0
  112. package/dist/components/Toast/ToastManager.d.ts.map +1 -0
  113. package/dist/components/Toast/types.d.ts +35 -0
  114. package/dist/components/Toast/types.d.ts.map +1 -0
  115. package/dist/components/ToolTip/ToolTip.vue.d.ts +1 -1
  116. package/dist/components/Tour/Tour.vue.d.ts +3 -3
  117. package/dist/components/Tour/TourPopover.vue.d.ts +3 -3
  118. package/dist/components/UploadArea/UploadArea.vue.d.ts +4 -4
  119. package/dist/components/index.d.ts +3993 -1340
  120. package/dist/components/index.d.ts.map +1 -1
  121. package/dist/components/ui/dialog/Dialog.vue.d.ts +23 -0
  122. package/dist/components/ui/dialog/Dialog.vue.d.ts.map +1 -0
  123. package/dist/components/ui/dialog/DialogClose.vue.d.ts +19 -0
  124. package/dist/components/ui/dialog/DialogClose.vue.d.ts.map +1 -0
  125. package/dist/components/ui/dialog/DialogContent.vue.d.ts +40 -0
  126. package/dist/components/ui/dialog/DialogContent.vue.d.ts.map +1 -0
  127. package/dist/components/ui/dialog/DialogFooter.vue.d.ts +25 -0
  128. package/dist/components/ui/dialog/DialogFooter.vue.d.ts.map +1 -0
  129. package/dist/components/ui/dialog/DialogHeader.vue.d.ts +29 -0
  130. package/dist/components/ui/dialog/DialogHeader.vue.d.ts.map +1 -0
  131. package/dist/components/ui/dialog/DialogTitle.vue.d.ts +23 -0
  132. package/dist/components/ui/dialog/DialogTitle.vue.d.ts.map +1 -0
  133. package/dist/components/ui/dialog/DialogTrigger.vue.d.ts +19 -0
  134. package/dist/components/ui/dialog/DialogTrigger.vue.d.ts.map +1 -0
  135. package/dist/components/ui/dialog/index.d.ts +8 -0
  136. package/dist/components/ui/dialog/index.d.ts.map +1 -0
  137. package/dist/components/ui/popover/Popover.vue.d.ts +23 -0
  138. package/dist/components/ui/popover/Popover.vue.d.ts.map +1 -0
  139. package/dist/components/ui/popover/PopoverContent.vue.d.ts +28 -0
  140. package/dist/components/ui/popover/PopoverContent.vue.d.ts.map +1 -0
  141. package/dist/components/ui/popover/PopoverFooter.vue.d.ts +18 -0
  142. package/dist/components/ui/popover/PopoverFooter.vue.d.ts.map +1 -0
  143. package/dist/components/ui/popover/PopoverTrigger.vue.d.ts +19 -0
  144. package/dist/components/ui/popover/PopoverTrigger.vue.d.ts.map +1 -0
  145. package/dist/components/ui/popover/index.d.ts +6 -0
  146. package/dist/components/ui/popover/index.d.ts.map +1 -0
  147. package/dist/{es-484b4c46.mjs → es-4bdcf86e.mjs} +1 -1
  148. package/dist/{index-dc007393.mjs → index-0d6fa367.mjs} +18908 -11929
  149. package/dist/locales/en.json.d.ts +2 -1
  150. package/dist/locales/es.json.d.ts +2 -1
  151. package/dist/locales/pt_br.json.d.ts +2 -1
  152. package/dist/{pt-br-f73c4b3a.mjs → pt-br-51af7f2a.mjs} +1 -1
  153. package/dist/style.css +1 -1
  154. package/dist/unnnic.mjs +197 -172
  155. package/dist/unnnic.umd.js +56 -50
  156. package/dist/utils/call.d.ts +2 -1
  157. package/dist/utils/call.d.ts.map +1 -1
  158. package/package.json +3 -2
  159. package/src/assets/icons/checkbox-checked-disabled.svg +3 -0
  160. package/src/assets/icons/checkbox-checked.svg +3 -0
  161. package/src/assets/icons/checkbox-less-disabled.svg +3 -0
  162. package/src/assets/icons/checkbox-less.svg +3 -0
  163. package/src/assets/icons/radio-checked.svg +3 -0
  164. package/src/assets/icons/switch-checked-disabled.svg +3 -0
  165. package/src/assets/icons/switch-checked.svg +3 -0
  166. package/src/assets/scss/tailwind.scss +8 -0
  167. package/src/components/Alert/Alert.vue +26 -135
  168. package/src/components/Alert/SIMPLE_MIGRATION_GUIDE.md +152 -0
  169. package/src/components/Alert/Version1dot1.vue +0 -36
  170. package/src/components/Alert/__tests__/Alert.spec.js +2 -45
  171. package/src/components/Alert/__tests__/Version1dot1.spec.js +0 -21
  172. package/src/components/Alert/__tests__/__snapshots__/Alert.spec.js.snap +11 -7
  173. package/src/components/Alert/__tests__/__snapshots__/Version1dot1.spec.js.snap +2 -2
  174. package/src/components/Button/Button.vue +68 -117
  175. package/src/components/Button/types.ts +0 -1
  176. package/src/components/Checkbox/Checkbox.vue +98 -64
  177. package/src/components/Checkbox/__tests__/Checkbox.spec.js +6 -21
  178. package/src/components/CheckboxGroup/CheckboxGroup.vue +96 -0
  179. package/src/components/FormElement/FormElement.vue +63 -93
  180. package/src/components/Icon.vue +2 -0
  181. package/src/components/Input/BaseInput.vue +33 -14
  182. package/src/components/Input/Input.scss +20 -21
  183. package/src/components/Input/Input.vue +79 -56
  184. package/src/components/Input/TextInput.vue +80 -68
  185. package/src/components/Input/__test__/Input.spec.js +13 -33
  186. package/src/components/Input/__test__/TextInput.spec.js +6 -8
  187. package/src/components/Input/__test__/__snapshots__/Input.spec.js.snap +14 -5
  188. package/src/components/Input/__test__/__snapshots__/TextInput.spec.js.snap +1 -1
  189. package/src/components/Label/Label.vue +52 -21
  190. package/src/components/Label/__tests__/Label.spec.js +1 -1
  191. package/src/components/Label/__tests__/__snapshots__/Label.spec.js.snap +1 -1
  192. package/src/components/ModalDialog/ModalDialog.vue +60 -146
  193. package/src/components/ModalDialog/__tests__/__snapshots__/ModalDialog.spec.js.snap +1 -22
  194. package/src/components/Popover/__tests__/Popover.spec.js +147 -0
  195. package/src/components/Popover/__tests__/__snapshots__/Popover.spec.js.snap +8 -0
  196. package/src/components/Popover/index.vue +146 -0
  197. package/src/components/Radio/Radio.vue +80 -67
  198. package/src/components/Radio/__test__/Radio.spec.js +14 -20
  199. package/src/components/Radio/__test__/__snapshots__/Radio.spec.js.snap +3 -3
  200. package/src/components/RadioGroup/RadioGroup.vue +142 -0
  201. package/src/components/Select/SelectOption.vue +65 -0
  202. package/src/components/Select/__tests__/Select.spec.js +412 -0
  203. package/src/components/Select/__tests__/SelectItem.spec.js +330 -0
  204. package/src/components/Select/__tests__/SelectOption.spec.js +174 -0
  205. package/src/components/Select/__tests__/__snapshots__/Select.spec.js.snap +97 -0
  206. package/src/components/Select/__tests__/__snapshots__/SelectItem.spec.js.snap +15 -0
  207. package/src/components/Select/__tests__/__snapshots__/SelectOption.spec.js.snap +25 -0
  208. package/src/components/Select/index.vue +245 -0
  209. package/src/components/SelectSmart/SelectSmart.vue +4 -3
  210. package/src/components/Switch/Switch.vue +123 -96
  211. package/src/components/Switch/__tests__/Switch.spec.js +8 -75
  212. package/src/components/Switch/__tests__/__snapshots__/Switch.spec.js.snap +5 -6
  213. package/src/components/Tab/Tab.vue +37 -23
  214. package/src/components/Tab/__test__/__snapshots__/Tab.spec.js.snap +1 -1
  215. package/src/components/TableNext/__test__/__snapshots__/TableNext.spec.js.snap +2 -2
  216. package/src/components/TableNext/__test__/__snapshots__/TablePagination.spec.js.snap +2 -2
  217. package/src/components/TextArea/TextArea.vue +34 -11
  218. package/src/components/TextArea/__test__/__snapshots__/TextArea.spec.js.snap +11 -3
  219. package/src/components/Toast/Toast.vue +246 -0
  220. package/src/components/Toast/ToastManager.ts +110 -0
  221. package/src/components/Toast/__tests__/Toast.spec.js +284 -0
  222. package/src/components/Toast/__tests__/ToastManager.spec.js +294 -0
  223. package/src/components/Toast/types.ts +57 -0
  224. package/src/components/index.ts +61 -9
  225. package/src/components/ui/dialog/Dialog.vue +15 -0
  226. package/src/components/ui/dialog/DialogClose.vue +25 -0
  227. package/src/components/ui/dialog/DialogContent.vue +114 -0
  228. package/src/components/ui/dialog/DialogFooter.vue +46 -0
  229. package/src/components/ui/dialog/DialogHeader.vue +78 -0
  230. package/src/components/ui/dialog/DialogTitle.vue +34 -0
  231. package/src/components/ui/dialog/DialogTrigger.vue +12 -0
  232. package/src/components/ui/dialog/index.ts +7 -0
  233. package/src/components/ui/popover/Popover.vue +19 -0
  234. package/src/components/ui/popover/PopoverContent.vue +109 -0
  235. package/src/components/ui/popover/PopoverFooter.vue +32 -0
  236. package/src/components/ui/popover/PopoverTrigger.vue +23 -0
  237. package/src/components/ui/popover/index.ts +5 -0
  238. package/src/locales/en.json +2 -1
  239. package/src/locales/es.json +2 -1
  240. package/src/locales/pt_br.json +2 -1
  241. package/src/stories/Alert.stories.js +6 -67
  242. package/src/stories/Button.stories.js +29 -39
  243. package/src/stories/Checkbox.stories.js +11 -4
  244. package/src/stories/CheckboxGroup.stories.js +105 -0
  245. package/src/stories/Dialog.stories.js +832 -0
  246. package/src/stories/Input.stories.js +71 -76
  247. package/src/stories/Label.stories.js +7 -0
  248. package/src/stories/ModalDialog.mdx +3 -0
  249. package/src/stories/ModalDialog.stories.js +1 -1
  250. package/src/stories/Popover.stories.js +396 -0
  251. package/src/stories/RadioGroup.stories.js +144 -0
  252. package/src/stories/Select.stories.js +158 -0
  253. package/src/stories/Switch.stories.js +10 -5
  254. package/src/stories/Tab.stories.js +11 -4
  255. package/src/stories/TextArea.stories.js +13 -2
  256. package/src/stories/Toast.mdx +123 -0
  257. package/src/stories/Toast.stories.js +126 -0
  258. package/src/types/scheme-colors.d.ts +1 -0
  259. package/src/utils/call.js +46 -18
  260. package/src/components/Alert/AlertBanner.vue +0 -182
  261. package/src/components/Alert/AlertCaller.vue +0 -49
  262. package/src/components/Alert/__tests__/AlertBanner.spec.js +0 -89
  263. package/src/components/Alert/__tests__/AlertCaller.spec.js +0 -98
@@ -0,0 +1,245 @@
1
+ <template>
2
+ <div
3
+ class="unnnic-select"
4
+ @keydown="handleKeyDown"
5
+ >
6
+ <UnnnicPopover
7
+ v-model="openPopover"
8
+ :popoverBalloonProps="{ maxHeight: calculatedMaxHeight }"
9
+ >
10
+ <template #trigger>
11
+ <UnnnicInput
12
+ :modelValue="inputValue"
13
+ class="unnnic-select__input"
14
+ readonly
15
+ :forceActiveStatus="openPopover"
16
+ :size="props.size"
17
+ :placeholder="props.placeholder"
18
+ :label="props.label"
19
+ :errors="props.errors"
20
+ :message="props.message"
21
+ :iconRight="openPopover ? 'keyboard_arrow_up' : 'keyboard_arrow_down'"
22
+ :disabled="props.disabled"
23
+ showClear
24
+ @clear="emit('update:modelValue', '')"
25
+ />
26
+ </template>
27
+ <template #content>
28
+ <div class="unnnic-select__content">
29
+ <UnnnicInput
30
+ v-if="props.enableSearch"
31
+ class="unnnic-select__input-search"
32
+ :modelValue="props.search"
33
+ :placeholder="$t('search')"
34
+ iconLeft="search"
35
+ @update:model-value="handleSearch"
36
+ />
37
+ <UnnnicSelectOption
38
+ v-for="(option, index) in filteredOptions"
39
+ :key="option[props.itemValue]"
40
+ :data-option-index="index"
41
+ :label="option[props.itemLabel]"
42
+ :active="
43
+ option[props.itemValue] === selectedItem?.[props.itemValue]
44
+ "
45
+ :focused="focusedOptionIndex === index"
46
+ :disabled="option.disabled"
47
+ @click="handleSelectOption(option)"
48
+ />
49
+ </div>
50
+ </template>
51
+ </UnnnicPopover>
52
+ </div>
53
+ </template>
54
+
55
+ <script setup lang="ts">
56
+ import { computed, ref, watch, nextTick } from 'vue';
57
+ import UnnnicInput from '../Input/Input.vue';
58
+ import UnnnicPopover from '../Popover/index.vue';
59
+ import UnnnicSelectOption from './SelectOption.vue';
60
+ import UnnnicI18n from '../../mixins/i18n';
61
+
62
+ defineOptions({
63
+ name: 'UnnnicSelect',
64
+ mixins: [UnnnicI18n],
65
+ });
66
+
67
+ interface SelectProps {
68
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
69
+ options: Array<{ [key: string]: any }>;
70
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
71
+ modelValue: any;
72
+ returnObject?: boolean;
73
+ itemLabel?: string;
74
+ itemValue?: string;
75
+ placeholder?: string;
76
+ label?: string;
77
+ type?: 'normal' | 'error';
78
+ errors?: string | Array<string>;
79
+ message?: string;
80
+ size?: 'sm' | 'md';
81
+ optionsLines?: number;
82
+ enableSearch?: boolean;
83
+ search?: string;
84
+ locale?: string;
85
+ disabled?: boolean;
86
+ }
87
+
88
+ const props = withDefaults(defineProps<SelectProps>(), {
89
+ size: 'md',
90
+ type: 'normal',
91
+ placeholder: '',
92
+ optionsLines: 5,
93
+ returnObject: false,
94
+ itemLabel: 'label',
95
+ itemValue: 'value',
96
+ locale: 'en',
97
+ enableSearch: false,
98
+ disabled: false,
99
+ });
100
+
101
+ const emit = defineEmits<{
102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
+ 'update:modelValue': [value: any];
104
+ 'update:search': [value: string];
105
+ }>();
106
+
107
+ const openPopover = ref(false);
108
+
109
+ watch(openPopover, () => {
110
+ if (!openPopover.value) {
111
+ handleSearch('');
112
+ } else {
113
+ focusedOptionIndex.value = -1;
114
+ }
115
+
116
+ if (openPopover.value && props.modelValue) {
117
+ const selectedOptionIndex = props.options.findIndex(
118
+ (option) =>
119
+ option[props.itemValue] === selectedItem.value[props.itemValue],
120
+ );
121
+ scrollToOption(selectedOptionIndex, 'instant', 'center');
122
+ }
123
+ });
124
+
125
+ const handleKeyDown = (event) => {
126
+ const { key } = event;
127
+ const validKeys = ['ArrowUp', 'ArrowDown', 'Enter'];
128
+ if (validKeys.includes(key)) {
129
+ event.preventDefault();
130
+ if (key === 'ArrowUp') {
131
+ if (focusedOptionIndex.value === 0) return;
132
+ focusedOptionIndex.value--;
133
+ scrollToOption(focusedOptionIndex.value);
134
+ }
135
+ if (key === 'ArrowDown') {
136
+ if (focusedOptionIndex.value === filteredOptions.value.length - 1) return;
137
+ focusedOptionIndex.value++;
138
+ scrollToOption(focusedOptionIndex.value);
139
+ }
140
+ if (key === 'Enter') {
141
+ handleSelectOption(filteredOptions.value[focusedOptionIndex.value]);
142
+ }
143
+ }
144
+ };
145
+
146
+ const focusedOptionIndex = ref<number>(-1);
147
+
148
+ const scrollToOption = (
149
+ index: number,
150
+ behavior: 'smooth' | 'instant' = 'smooth',
151
+ block: 'center' | 'start' | 'end' | 'nearest' = 'center',
152
+ ) => {
153
+ nextTick(() => {
154
+ const option = document.querySelector(`[data-option-index="${index}"]`);
155
+ if (option) {
156
+ option.scrollIntoView({ behavior, block });
157
+ }
158
+ });
159
+ };
160
+
161
+ const calculatedMaxHeight = computed(() => {
162
+ if (!props.options || props.options.length === 0) return 'unset';
163
+ const popoverPadding = 32;
164
+ const popoverGap = 4;
165
+ // 37 = 21px (height) + 16px (padding)
166
+ const fieldsHeight = 37 * props.optionsLines;
167
+ const size =
168
+ fieldsHeight + popoverPadding + (popoverGap * props.optionsLines - 2);
169
+ return `${props.enableSearch ? size + 54 : size}px`;
170
+ });
171
+
172
+ const selectedItem = computed(() => {
173
+ if (props.returnObject) return props.modelValue;
174
+
175
+ return props.options.find(
176
+ (option) => option[props.itemValue] === props.modelValue,
177
+ );
178
+ });
179
+
180
+ const inputValue = computed(() => {
181
+ return selectedItem.value?.[props.itemLabel];
182
+ });
183
+
184
+ const handleSelectOption = (option) => {
185
+ if (
186
+ option[props.itemValue] === selectedItem.value?.[props.itemValue] ||
187
+ option.disabled
188
+ )
189
+ return;
190
+
191
+ emit(
192
+ 'update:modelValue',
193
+ props.returnObject ? option : option[props.itemValue],
194
+ );
195
+ openPopover.value = false;
196
+ };
197
+
198
+ const handleSearch = (value: string) => {
199
+ emit('update:search', value);
200
+ };
201
+
202
+ const filteredOptions = computed(() => {
203
+ if (!props.enableSearch || !props.search) return props.options;
204
+
205
+ return props.options.filter(
206
+ (option) =>
207
+ option[props.itemLabel]
208
+ .toLowerCase()
209
+ .includes(props.search?.toLowerCase()) ||
210
+ option[props.itemValue]
211
+ .toLowerCase()
212
+ .includes(props.search?.toLowerCase()),
213
+ );
214
+ });
215
+ </script>
216
+
217
+ <style lang="scss" scoped>
218
+ @use '@/assets/scss/unnnic' as *;
219
+
220
+ :deep(.unnnic-select__input) {
221
+ cursor: pointer;
222
+ }
223
+
224
+ :deep(.unnnic-select__input-search) {
225
+ > .icon-left {
226
+ color: $unnnic-color-fg-base;
227
+ }
228
+ }
229
+
230
+ :deep(.unnnic-select__input) {
231
+ > .icon-right {
232
+ color: $unnnic-color-fg-base;
233
+ }
234
+ }
235
+
236
+ .unnnic-select {
237
+ &__content {
238
+ display: flex;
239
+ flex-direction: column;
240
+ padding: 0;
241
+ margin: 0;
242
+ gap: $unnnic-space-1;
243
+ }
244
+ }
245
+ </style>
@@ -636,9 +636,10 @@ export default {
636
636
 
637
637
  margin-top: $unnnic-spacing-nano;
638
638
 
639
- border-radius: $unnnic-border-radius-sm;
639
+ border-radius: $unnnic-radius-2;
640
+ border: 1px solid $unnnic-color-border-base;
640
641
 
641
- box-shadow: $unnnic-shadow-level-near;
642
+ box-shadow: $unnnic-shadow-1;
642
643
 
643
644
  background-color: $unnnic-color-background-snow;
644
645
 
@@ -655,7 +656,7 @@ export default {
655
656
 
656
657
  display: grid;
657
658
 
658
- margin: $unnnic-spacing-xs;
659
+ margin: $unnnic-space-4;
659
660
  margin-right: $unnnic-inline-xs;
660
661
  padding-right: $unnnic-inline-xs;
661
662
 
@@ -1,49 +1,55 @@
1
1
  <template>
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"
2
+ <section class="unnnic-switch-wrapper">
3
+ <UnnnicLabel
4
+ v-if="label"
5
+ :label="label"
6
+ :tooltip="labelTooltip"
7
+ :useHtmlTooltip="labelUseHtmlTooltip"
8
+ class="unnnic-switch__label"
25
9
  />
26
10
 
27
- <div
28
- v-if="textRight"
29
- data-test-id="switch-text-right"
30
- :class="[
31
- 'unnnic-switch__label',
32
- 'unnnic-switch__label__right',
33
- `unnnic-switch__label__${size}`,
34
- ]"
11
+ <label>
12
+ <input
13
+ class="unnnic-switch"
14
+ type="checkbox"
15
+ :disabled="disabled"
16
+ :checked="modelValue"
17
+ @change="toggleState"
18
+ v-bind="pick($attrs, ['id', 'name'])"
19
+ />
20
+
21
+ <p
22
+ v-if="option || textLeft || textRight"
23
+ :class="[
24
+ 'unnnic-switch__option',
25
+ { 'unnnic-switch__option--disabled': disabled },
26
+ ]"
27
+ data-testid="switch-option"
28
+ >
29
+ {{ option }}
30
+ {{ textLeft }}
31
+ {{ textRight }}
32
+ </p>
33
+ </label>
34
+
35
+ <p
36
+ v-if="helper"
37
+ class="unnnic-switch__helper"
35
38
  >
36
- {{ textRight }}
37
- </div>
38
- </div>
39
+ {{ helper }}
40
+ </p>
41
+ </section>
39
42
  </template>
40
43
 
41
44
  <script>
42
- import UnnnicIcon from '../Icon.vue';
45
+ import { pick } from 'lodash';
46
+ import UnnnicLabel from '../Label/Label.vue';
43
47
 
44
48
  export default {
45
49
  name: 'UnnnicSwitch',
46
- components: { UnnnicIcon },
50
+ components: {
51
+ UnnnicLabel,
52
+ },
47
53
  props: {
48
54
  size: {
49
55
  type: String,
@@ -52,6 +58,32 @@ export default {
52
58
  return ['small', 'medium'].indexOf(value) !== -1;
53
59
  },
54
60
  },
61
+
62
+ label: {
63
+ type: String,
64
+ default: '',
65
+ },
66
+
67
+ labelTooltip: {
68
+ type: String,
69
+ default: '',
70
+ },
71
+
72
+ labelUseHtmlTooltip: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+
77
+ option: {
78
+ type: String,
79
+ default: '',
80
+ },
81
+
82
+ helper: {
83
+ type: String,
84
+ default: '',
85
+ },
86
+
55
87
  textLeft: {
56
88
  type: String,
57
89
  default: '',
@@ -78,33 +110,6 @@ export default {
78
110
  isActive: false,
79
111
  };
80
112
  },
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
- },
108
113
 
109
114
  watch: {
110
115
  modelValue: {
@@ -116,6 +121,8 @@ export default {
116
121
  },
117
122
 
118
123
  methods: {
124
+ pick,
125
+
119
126
  toggleState() {
120
127
  if (!this.disabled) {
121
128
  if (this.useVModel) {
@@ -133,51 +140,71 @@ export default {
133
140
  <style lang="scss" scoped>
134
141
  @use '@/assets/scss/unnnic' as *;
135
142
 
136
- .unnnic-switch {
143
+ $switch-width: 38px;
144
+ $switch-height: 20px;
145
+
146
+ .unnnic-switch-wrapper {
137
147
  display: flex;
138
- flex-direction: row;
148
+ flex-direction: column;
139
149
 
140
- &__label {
141
- font-family: $unnnic-font-family-secondary;
142
- font-weight: $unnnic-font-weight-regular;
143
- color: $unnnic-color-neutral-dark;
150
+ label {
151
+ display: flex;
152
+ align-items: center;
153
+ column-gap: $unnnic-space-2;
154
+ }
155
+ }
144
156
 
145
- margin: $unnnic-spacing-stack-nano 0;
146
- margin-right: $unnnic-inline-nano;
157
+ .unnnic-switch {
158
+ appearance: none;
159
+ width: $switch-width;
160
+ height: $switch-height;
161
+ margin: 0;
162
+ background-color: $unnnic-color-bg-muted;
163
+ border-radius: $unnnic-radius-3;
164
+ box-sizing: border-box;
165
+ outline: none;
166
+
167
+ background-image: url('@/assets/icons/switch-checked.svg');
168
+ background-repeat: no-repeat;
169
+ background-position: 4px center;
170
+
171
+ transition:
172
+ 120ms linear background-position,
173
+ 120ms linear background-color;
174
+
175
+ cursor: pointer;
176
+
177
+ &:checked {
178
+ background-color: $unnnic-color-bg-active;
179
+ background-position: 20px center;
180
+ }
147
181
 
148
- &__small {
149
- font-size: $unnnic-font-size-body-md;
150
- line-height: $unnnic-font-size-body-md + $unnnic-line-height-md;
151
- }
182
+ &:disabled {
183
+ background-color: $unnnic-color-bg-muted;
184
+ background-image: url('@/assets/icons/switch-checked-disabled.svg');
152
185
 
153
- &__medium {
154
- font-size: $unnnic-font-size-body-gt;
155
- line-height: $unnnic-font-size-body-gt + $unnnic-line-height-md;
156
- }
186
+ cursor: not-allowed;
157
187
  }
158
188
 
159
- &__icon {
160
- align-self: center;
161
- margin: $unnnic-spacing-stack-nano $unnnic-inline-nano;
189
+ &__label {
190
+ margin-bottom: $unnnic-space-3;
191
+ }
162
192
 
163
- :deep(#default-circle) {
164
- transition: 0.2s linear transform;
165
- }
193
+ &__option {
194
+ margin: 0;
195
+ font: $unnnic-font-body;
196
+ color: $unnnic-color-fg-emphasized;
166
197
 
167
- &.active {
168
- :deep(#default-circle) {
169
- transform: translateX(45%);
170
- }
198
+ &--disabled {
199
+ color: $unnnic-color-fg-muted;
171
200
  }
172
201
  }
173
- }
174
202
 
175
- .unnnic-icon__size {
176
- &--md {
177
- width: 3 * $unnnic-font-size;
178
- }
179
- &--sm {
180
- width: 2 * $unnnic-font-size;
203
+ &__helper {
204
+ margin: 0;
205
+ margin-left: $switch-width + $unnnic-space-2;
206
+ font: $unnnic-font-caption-2;
207
+ color: $unnnic-color-fg-base;
181
208
  }
182
209
  }
183
210
  </style>
@@ -12,93 +12,26 @@ 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');
47
15
 
48
- await wrapper.setProps({ modelValue: true });
49
- const enabledIconComponent = wrapper.findComponent({ name: 'UnnnicIcon' });
50
- expect(enabledIconComponent.props('icon')).toBe('switch-selected-disabled');
51
- });
16
+ it('should render the option when provided', async () => {
17
+ await wrapper.setProps({ option: 'Option Text' });
52
18
 
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
- );
19
+ const switchOption = wrapper.find('[data-testid="switch-option"]');
20
+ expect(switchOption.text()).toBe('Option Text');
88
21
  });
89
22
 
90
23
  it('should toggle isActive state and emit the correct event when toggleState is called', async () => {
91
24
  const initialIsActive = wrapper.vm.isActive;
92
- const switchIcon = wrapper.findComponent('[ data-test-id="switch-icon"]');
93
- await switchIcon.trigger('click');
25
+ const switchInput = wrapper.find('input[type="checkbox"]');
26
+ await switchInput.trigger('change');
94
27
  expect(wrapper.emitted('update:model-value')).toBeTruthy();
95
28
  expect(wrapper.vm.isActive).toBe(!initialIsActive);
96
29
  });
97
30
 
98
31
  it('should not change state when disabled is true', async () => {
99
32
  await wrapper.setProps({ disabled: true });
100
- const switchIcon = wrapper.findComponent('[ data-test-id="switch-icon"]');
101
- await switchIcon.trigger('click');
33
+ const switchInput = wrapper.find('input[type="checkbox"]');
34
+ await switchInput.trigger('change');
102
35
  expect(wrapper.emitted('update:model-value')).toBeFalsy();
103
36
  expect(wrapper.vm.isActive).toBe(false);
104
37
  });
@@ -1,11 +1,10 @@
1
1
  // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2
2
 
3
3
  exports[`Switch > should match the snapshot 1`] = `
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>
4
+ "<section data-v-e4356c9d="" class="unnnic-switch-wrapper">
5
+ <!--v-if--><label data-v-e4356c9d=""><input data-v-e4356c9d="" class="unnnic-switch" type="checkbox">
6
+ <!--v-if-->
7
+ </label>
9
8
  <!--v-if-->
10
- </div>"
9
+ </section>"
11
10
  `;