sprintify-ui 0.2.18 → 0.2.21

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 (405) hide show
  1. package/README.md +244 -244
  2. package/dist/sprintify-ui.es.js +7675 -7686
  3. package/dist/style.css +1 -1
  4. package/dist/tailwindcss/index.js +306 -306
  5. package/dist/types/src/components/BaseActionItem.vue.d.ts +40 -40
  6. package/dist/types/src/components/BaseActionItemButton.vue.d.ts +25 -25
  7. package/dist/types/src/components/BaseAddressForm.vue.d.ts +84 -84
  8. package/dist/types/src/components/BaseAlert.vue.d.ts +51 -51
  9. package/dist/types/src/components/BaseApp.vue.d.ts +9 -9
  10. package/dist/types/src/components/BaseAppDialogs.vue.d.ts +14 -14
  11. package/dist/types/src/components/BaseAppNotifications.vue.d.ts +2 -2
  12. package/dist/types/src/components/BaseAutocomplete.vue.d.ts +237 -237
  13. package/dist/types/src/components/BaseAutocompleteDrawer.vue.d.ts +91 -91
  14. package/dist/types/src/components/BaseAutocompleteFetch.vue.d.ts +210 -210
  15. package/dist/types/src/components/BaseAvatar.vue.d.ts +52 -52
  16. package/dist/types/src/components/BaseAvatarGroup.vue.d.ts +43 -43
  17. package/dist/types/src/components/BaseBadge.vue.d.ts +54 -54
  18. package/dist/types/src/components/BaseBelongsTo.vue.d.ts +216 -216
  19. package/dist/types/src/components/BaseBoolean.vue.d.ts +10 -10
  20. package/dist/types/src/components/BaseBreadcrumbs.vue.d.ts +14 -14
  21. package/dist/types/src/components/BaseButton.vue.d.ts +23 -23
  22. package/dist/types/src/components/BaseButtonGroup.vue.d.ts +143 -143
  23. package/dist/types/src/components/BaseCard.vue.d.ts +21 -21
  24. package/dist/types/src/components/BaseCardRow.vue.d.ts +16 -16
  25. package/dist/types/src/components/BaseCharacterCounter.vue.d.ts +49 -49
  26. package/dist/types/src/components/BaseClickOutside.vue.d.ts +26 -26
  27. package/dist/types/src/components/BaseClipboard.vue.d.ts +21 -21
  28. package/dist/types/src/components/BaseColor.vue.d.ts +80 -80
  29. package/dist/types/src/components/BaseContainer.vue.d.ts +34 -34
  30. package/dist/types/src/components/BaseCounter.vue.d.ts +42 -42
  31. package/dist/types/src/components/BaseCropper.vue.d.ts +76 -76
  32. package/dist/types/src/components/BaseCropperModal.vue.d.ts +28 -28
  33. package/dist/types/src/components/BaseDataIterator.vue.d.ts +212 -212
  34. package/dist/types/src/components/BaseDataIteratorSectionBox.vue.d.ts +20 -20
  35. package/dist/types/src/components/BaseDataIteratorSectionButton.vue.d.ts +17 -17
  36. package/dist/types/src/components/BaseDataIteratorSectionColumns.vue.d.ts +637 -637
  37. package/dist/types/src/components/BaseDataIteratorSectionModal.vue.d.ts +32 -32
  38. package/dist/types/src/components/BaseDataTable.vue.d.ts +385 -385
  39. package/dist/types/src/components/BaseDataTableRowAction.vue.d.ts +21 -21
  40. package/dist/types/src/components/BaseDatePicker.vue.d.ts +124 -124
  41. package/dist/types/src/components/BaseDateSelect.vue.d.ts +79 -79
  42. package/dist/types/src/components/BaseDescriptionList.vue.d.ts +9 -9
  43. package/dist/types/src/components/BaseDescriptionListItem.vue.d.ts +10 -10
  44. package/dist/types/src/components/BaseDialog.vue.d.ts +60 -60
  45. package/dist/types/src/components/BaseDisplayRelativeTime.vue.d.ts +68 -68
  46. package/dist/types/src/components/BaseDraggable.vue.d.ts +49 -49
  47. package/dist/types/src/components/BaseDropdown.vue.d.ts +65 -65
  48. package/dist/types/src/components/BaseDropdownAutocomplete.vue.d.ts +132 -132
  49. package/dist/types/src/components/BaseField.vue.d.ts +58 -58
  50. package/dist/types/src/components/BaseFieldI18n.vue.d.ts +93 -93
  51. package/dist/types/src/components/BaseFilePicker.vue.d.ts +72 -63
  52. package/dist/types/src/components/BaseFilePickerCrop.vue.d.ts +63 -63
  53. package/dist/types/src/components/BaseFileUploader.vue.d.ts +144 -133
  54. package/dist/types/src/components/BaseForm.vue.d.ts +134 -134
  55. package/dist/types/src/components/BaseGantt.vue.d.ts +425 -425
  56. package/dist/types/src/components/BaseHasMany.vue.d.ts +149 -149
  57. package/dist/types/src/components/BaseHeader.vue.d.ts +98 -98
  58. package/dist/types/src/components/BaseIconPicker.vue.d.ts +34 -34
  59. package/dist/types/src/components/BaseInput.vue.d.ts +174 -174
  60. package/dist/types/src/components/BaseInputError.vue.d.ts +9 -9
  61. package/dist/types/src/components/BaseInputLabel.vue.d.ts +43 -43
  62. package/dist/types/src/components/BaseInputPercent.vue.d.ts +138 -138
  63. package/dist/types/src/components/BaseLayoutNotificationDropdown.vue.d.ts +36 -36
  64. package/dist/types/src/components/BaseLayoutNotificationItem.vue.d.ts +16 -16
  65. package/dist/types/src/components/BaseLayoutNotificationItemContent.vue.d.ts +21 -21
  66. package/dist/types/src/components/BaseLayoutSidebar.vue.d.ts +51 -51
  67. package/dist/types/src/components/BaseLayoutSidebarConfigurable.vue.d.ts +87 -87
  68. package/dist/types/src/components/BaseLayoutStacked.vue.d.ts +23 -23
  69. package/dist/types/src/components/BaseLayoutStackedConfigurable.vue.d.ts +78 -78
  70. package/dist/types/src/components/BaseLoadingCover.vue.d.ts +96 -96
  71. package/dist/types/src/components/BaseMediaGallery.vue.d.ts +64 -64
  72. package/dist/types/src/components/BaseMediaGalleryItem.vue.d.ts +45 -45
  73. package/dist/types/src/components/BaseMediaItem.vue.d.ts +27 -27
  74. package/dist/types/src/components/BaseMediaLibrary.vue.d.ts +199 -190
  75. package/dist/types/src/components/BaseMediaList.vue.d.ts +47 -47
  76. package/dist/types/src/components/BaseMediaListItem.vue.d.ts +47 -47
  77. package/dist/types/src/components/BaseMediaPictures.vue.d.ts +55 -55
  78. package/dist/types/src/components/BaseMediaPicturesItem.vue.d.ts +54 -54
  79. package/dist/types/src/components/BaseMediaPreview.vue.d.ts +36 -36
  80. package/dist/types/src/components/BaseMenu.vue.d.ts +68 -68
  81. package/dist/types/src/components/BaseMenuItem.vue.d.ts +61 -61
  82. package/dist/types/src/components/BaseModalCenter.vue.d.ts +80 -80
  83. package/dist/types/src/components/BaseModalSide.vue.d.ts +62 -62
  84. package/dist/types/src/components/BaseNavbar.vue.d.ts +38 -38
  85. package/dist/types/src/components/BaseNavbarItem.vue.d.ts +26 -26
  86. package/dist/types/src/components/BaseNavbarItemContent.vue.d.ts +60 -60
  87. package/dist/types/src/components/BaseNavbarSideItem.vue.d.ts +44 -44
  88. package/dist/types/src/components/BaseNavbarSideItemContent.vue.d.ts +60 -60
  89. package/dist/types/src/components/BasePagination.vue.d.ts +35 -35
  90. package/dist/types/src/components/BasePanel.vue.d.ts +31 -31
  91. package/dist/types/src/components/BasePassword.vue.d.ts +67 -67
  92. package/dist/types/src/components/BaseProgressCircle.vue.d.ts +37 -37
  93. package/dist/types/src/components/BaseRadioGroup.vue.d.ts +105 -105
  94. package/dist/types/src/components/BaseReadMore.vue.d.ts +21 -21
  95. package/dist/types/src/components/BaseRichText.vue.d.ts +92 -92
  96. package/dist/types/src/components/BaseSelect.vue.d.ts +98 -98
  97. package/dist/types/src/components/BaseShortcut.vue.d.ts +86 -86
  98. package/dist/types/src/components/BaseSideNavigation.vue.d.ts +21 -21
  99. package/dist/types/src/components/BaseSideNavigationItem.vue.d.ts +41 -41
  100. package/dist/types/src/components/BaseSkeleton.vue.d.ts +31 -31
  101. package/dist/types/src/components/BaseStatistic.vue.d.ts +56 -56
  102. package/dist/types/src/components/BaseStepper.vue.d.ts +16 -16
  103. package/dist/types/src/components/BaseStepperItem.vue.d.ts +51 -51
  104. package/dist/types/src/components/BaseSwitch.vue.d.ts +87 -87
  105. package/dist/types/src/components/BaseSystemAlert.vue.d.ts +52 -52
  106. package/dist/types/src/components/BaseTabItem.vue.d.ts +41 -41
  107. package/dist/types/src/components/BaseTable.vue.d.ts +212 -212
  108. package/dist/types/src/components/BaseTableColumn.vue.d.ts +174 -174
  109. package/dist/types/src/components/BaseTabs.vue.d.ts +21 -21
  110. package/dist/types/src/components/BaseTagAutocomplete.vue.d.ts +209 -209
  111. package/dist/types/src/components/BaseTagAutocompleteFetch.vue.d.ts +141 -141
  112. package/dist/types/src/components/BaseTextarea.vue.d.ts +103 -103
  113. package/dist/types/src/components/BaseTextareaAutoresize.vue.d.ts +113 -113
  114. package/dist/types/src/components/BaseTimeline.vue.d.ts +14 -14
  115. package/dist/types/src/components/BaseTimelineItem.vue.d.ts +14 -14
  116. package/dist/types/src/components/BaseUniqueCode.vue.d.ts +33 -33
  117. package/dist/types/src/components/SlotComponent.d.ts +43 -43
  118. package/dist/types/src/components/index.d.ts +96 -96
  119. package/dist/types/src/composables/breakpoints.d.ts +27 -27
  120. package/dist/types/src/composables/clickOutside.d.ts +8 -8
  121. package/dist/types/src/composables/field.d.ts +19 -19
  122. package/dist/types/src/composables/hasOptions.d.ts +7 -7
  123. package/dist/types/src/composables/mediaQuery.d.ts +2 -2
  124. package/dist/types/src/composables/modal.d.ts +6 -6
  125. package/dist/types/src/composables/paginatedData.d.ts +7 -7
  126. package/dist/types/src/constants/MyConstants.d.ts +1 -1
  127. package/dist/types/src/constants/index.d.ts +2 -2
  128. package/dist/types/src/i18n/index.d.ts +1 -1
  129. package/dist/types/src/index.d.ts +222 -222
  130. package/dist/types/src/services/gantt/format.d.ts +24 -24
  131. package/dist/types/src/services/gantt/timescale.d.ts +26 -26
  132. package/dist/types/src/services/gantt/types.d.ts +67 -67
  133. package/dist/types/src/stores/dialogs.d.ts +9 -9
  134. package/dist/types/src/stores/i18n.d.ts +5 -5
  135. package/dist/types/src/stores/notifications.d.ts +10 -10
  136. package/dist/types/src/stores/systemAlerts.d.ts +9 -9
  137. package/dist/types/src/svg/BaseEmptyState.vue.d.ts +2 -2
  138. package/dist/types/src/svg/BaseSpinnerLarge.vue.d.ts +2 -2
  139. package/dist/types/src/svg/BaseSpinnerSmall.vue.d.ts +2 -2
  140. package/dist/types/src/types/Color.d.ts +9 -9
  141. package/dist/types/src/types/Country.d.ts +4 -4
  142. package/dist/types/src/types/ImagePickerResult.d.ts +5 -5
  143. package/dist/types/src/types/Media.d.ts +9 -9
  144. package/dist/types/src/types/Notification.d.ts +8 -8
  145. package/dist/types/src/types/Region.d.ts +5 -5
  146. package/dist/types/src/types/Status.d.ts +5 -5
  147. package/dist/types/src/types/StepperItem.d.ts +7 -7
  148. package/dist/types/src/types/TimelineItem.d.ts +8 -8
  149. package/dist/types/src/types/UploadedFile.d.ts +10 -10
  150. package/dist/types/src/types/User.d.ts +6 -6
  151. package/dist/types/src/types/index.d.ts +218 -218
  152. package/dist/types/src/utils/blob.d.ts +3 -3
  153. package/dist/types/src/utils/colors.d.ts +13 -13
  154. package/dist/types/src/utils/cropper/avatar.d.ts +5 -5
  155. package/dist/types/src/utils/cropper/cover.d.ts +5 -5
  156. package/dist/types/src/utils/cropper/presetInterface.d.ts +7 -7
  157. package/dist/types/src/utils/cropper/presets.d.ts +6 -6
  158. package/dist/types/src/utils/fileSizeFormat.d.ts +1 -1
  159. package/dist/types/src/utils/fileValidations.d.ts +2 -2
  160. package/dist/types/src/utils/index.d.ts +6 -6
  161. package/dist/types/src/utils/resizeImageFromURI.d.ts +1 -1
  162. package/dist/types/src/utils/scrollPreventer.d.ts +3 -3
  163. package/dist/types/src/utils/toHumanList.d.ts +1 -1
  164. package/package.json +139 -136
  165. package/src/assets/flatpickr.css +243 -243
  166. package/src/assets/form.css +6 -6
  167. package/src/assets/main.css +36 -36
  168. package/src/assets/tailwind.css +2 -2
  169. package/src/components/BaseActionItem.vue +68 -68
  170. package/src/components/BaseActionItemButton.vue +75 -75
  171. package/src/components/BaseAddressForm.stories.js +103 -103
  172. package/src/components/BaseAddressForm.vue +354 -354
  173. package/src/components/BaseAlert.stories.js +52 -52
  174. package/src/components/BaseAlert.vue +158 -158
  175. package/src/components/BaseApp.vue +16 -16
  176. package/src/components/BaseAppDialogs.vue +124 -124
  177. package/src/components/BaseAppNotifications.vue +76 -76
  178. package/src/components/BaseAutocomplete.stories.js +236 -236
  179. package/src/components/BaseAutocomplete.vue +523 -523
  180. package/src/components/BaseAutocompleteDrawer.vue +372 -372
  181. package/src/components/BaseAutocompleteFetch.stories.js +224 -224
  182. package/src/components/BaseAutocompleteFetch.vue +288 -288
  183. package/src/components/BaseAvatar.stories.js +39 -39
  184. package/src/components/BaseAvatar.vue +120 -120
  185. package/src/components/BaseAvatarGroup.stories.js +71 -71
  186. package/src/components/BaseAvatarGroup.vue +148 -148
  187. package/src/components/BaseBadge.stories.js +124 -124
  188. package/src/components/BaseBadge.vue +78 -78
  189. package/src/components/BaseBelongsTo.stories.js +223 -223
  190. package/src/components/BaseBelongsTo.vue +193 -193
  191. package/src/components/BaseBoolean.stories.js +35 -35
  192. package/src/components/BaseBoolean.vue +26 -26
  193. package/src/components/BaseBreadcrumbs.stories.js +45 -45
  194. package/src/components/BaseBreadcrumbs.vue +104 -104
  195. package/src/components/BaseButton.stories.js +88 -88
  196. package/src/components/BaseButton.vue +46 -46
  197. package/src/components/BaseButtonGroup.stories.js +86 -86
  198. package/src/components/BaseButtonGroup.vue +150 -150
  199. package/src/components/BaseCard.stories.js +61 -61
  200. package/src/components/BaseCard.vue +49 -49
  201. package/src/components/BaseCardRow.vue +34 -34
  202. package/src/components/BaseCharacterCounter.stories.js +30 -30
  203. package/src/components/BaseCharacterCounter.vue +64 -64
  204. package/src/components/BaseClickOutside.vue +37 -37
  205. package/src/components/BaseClipboard.stories.js +31 -31
  206. package/src/components/BaseClipboard.vue +99 -99
  207. package/src/components/BaseColor.stories.js +46 -46
  208. package/src/components/BaseColor.vue +154 -154
  209. package/src/components/BaseContainer.stories.js +34 -34
  210. package/src/components/BaseContainer.vue +50 -50
  211. package/src/components/BaseCounter.stories.js +47 -47
  212. package/src/components/BaseCounter.vue +82 -82
  213. package/src/components/BaseCropper.stories.js +113 -113
  214. package/src/components/BaseCropper.vue +458 -458
  215. package/src/components/BaseCropperModal.stories.js +54 -54
  216. package/src/components/BaseCropperModal.vue +143 -143
  217. package/src/components/BaseDataIterator.stories.js +197 -197
  218. package/src/components/BaseDataIterator.vue +802 -802
  219. package/src/components/BaseDataIteratorSectionBox.vue +36 -36
  220. package/src/components/BaseDataIteratorSectionButton.vue +42 -42
  221. package/src/components/BaseDataIteratorSectionColumns.vue +70 -70
  222. package/src/components/BaseDataIteratorSectionModal.vue +41 -41
  223. package/src/components/BaseDataTable.stories.js +341 -341
  224. package/src/components/BaseDataTable.vue +747 -747
  225. package/src/components/BaseDataTableRowAction.vue +34 -34
  226. package/src/components/BaseDatePicker.stories.js +130 -130
  227. package/src/components/BaseDatePicker.vue +296 -296
  228. package/src/components/BaseDateSelect.stories.js +47 -47
  229. package/src/components/BaseDateSelect.vue +241 -241
  230. package/src/components/BaseDescriptionList.stories.js +35 -35
  231. package/src/components/BaseDescriptionList.vue +13 -13
  232. package/src/components/BaseDescriptionListItem.vue +47 -47
  233. package/src/components/BaseDialog.stories.js +51 -51
  234. package/src/components/BaseDialog.vue +119 -119
  235. package/src/components/BaseDisplayRelativeTime.stories.js +59 -59
  236. package/src/components/BaseDisplayRelativeTime.vue +123 -123
  237. package/src/components/BaseDraggable.vue +71 -71
  238. package/src/components/BaseDropdown.stories.js +210 -210
  239. package/src/components/BaseDropdown.vue +280 -280
  240. package/src/components/BaseDropdownAutocomplete.stories.js +187 -187
  241. package/src/components/BaseDropdownAutocomplete.vue +236 -236
  242. package/src/components/BaseField.vue +112 -112
  243. package/src/components/BaseFieldI18n.stories.js +38 -38
  244. package/src/components/BaseFieldI18n.vue +170 -170
  245. package/src/components/BaseFilePicker.stories.js +84 -78
  246. package/src/components/BaseFilePicker.vue +166 -136
  247. package/src/components/BaseFilePickerCrop.stories.js +135 -134
  248. package/src/components/BaseFilePickerCrop.vue +130 -130
  249. package/src/components/BaseFileUploader.stories.js +90 -84
  250. package/src/components/BaseFileUploader.vue +174 -163
  251. package/src/components/BaseForm.stories.js +48 -46
  252. package/src/components/BaseForm.vue +331 -331
  253. package/src/components/BaseGantt.stories.js +133 -133
  254. package/src/components/BaseGantt.vue +336 -336
  255. package/src/components/BaseHasMany.stories.js +189 -189
  256. package/src/components/BaseHasMany.vue +137 -137
  257. package/src/components/BaseHeader.stories.js +127 -127
  258. package/src/components/BaseHeader.vue +191 -191
  259. package/src/components/BaseIconPicker.stories.js +22 -22
  260. package/src/components/BaseIconPicker.vue +225 -225
  261. package/src/components/BaseInput.stories.js +167 -167
  262. package/src/components/BaseInput.vue +264 -264
  263. package/src/components/BaseInputError.vue +7 -7
  264. package/src/components/BaseInputLabel.stories.js +36 -36
  265. package/src/components/BaseInputLabel.vue +75 -75
  266. package/src/components/BaseInputPercent.stories.js +65 -65
  267. package/src/components/BaseInputPercent.vue +139 -139
  268. package/src/components/BaseLayoutNotificationDropdown.vue +150 -150
  269. package/src/components/BaseLayoutNotificationItem.vue +53 -53
  270. package/src/components/BaseLayoutNotificationItemContent.vue +30 -30
  271. package/src/components/BaseLayoutSidebar.vue +236 -236
  272. package/src/components/BaseLayoutSidebarConfigurable.stories.js +166 -166
  273. package/src/components/BaseLayoutSidebarConfigurable.vue +181 -181
  274. package/src/components/BaseLayoutStacked.vue +52 -52
  275. package/src/components/BaseLayoutStackedConfigurable.stories.js +109 -109
  276. package/src/components/BaseLayoutStackedConfigurable.vue +158 -158
  277. package/src/components/BaseLoadingCover.stories.js +55 -55
  278. package/src/components/BaseLoadingCover.vue +101 -101
  279. package/src/components/BaseMediaGallery.vue +96 -96
  280. package/src/components/BaseMediaGalleryItem.vue +101 -101
  281. package/src/components/BaseMediaItem.stories.js +41 -41
  282. package/src/components/BaseMediaItem.vue +80 -80
  283. package/src/components/BaseMediaLibrary.stories.js +267 -262
  284. package/src/components/BaseMediaLibrary.vue +323 -318
  285. package/src/components/BaseMediaList.vue +68 -68
  286. package/src/components/BaseMediaListItem.vue +181 -181
  287. package/src/components/BaseMediaPictures.vue +64 -64
  288. package/src/components/BaseMediaPicturesItem.vue +100 -100
  289. package/src/components/BaseMediaPreview.stories.js +72 -72
  290. package/src/components/BaseMediaPreview.vue +106 -106
  291. package/src/components/BaseMenu.stories.js +125 -125
  292. package/src/components/BaseMenu.vue +165 -165
  293. package/src/components/BaseMenuItem.vue +118 -118
  294. package/src/components/BaseModalCenter.stories.js +68 -68
  295. package/src/components/BaseModalCenter.vue +134 -134
  296. package/src/components/BaseModalSide.stories.js +55 -55
  297. package/src/components/BaseModalSide.vue +122 -122
  298. package/src/components/BaseNavbar.stories.js +151 -151
  299. package/src/components/BaseNavbar.vue +91 -91
  300. package/src/components/BaseNavbarItem.vue +49 -49
  301. package/src/components/BaseNavbarItemContent.vue +97 -97
  302. package/src/components/BaseNavbarSideItem.vue +114 -114
  303. package/src/components/BaseNavbarSideItemContent.vue +111 -111
  304. package/src/components/BasePagination.stories.js +35 -35
  305. package/src/components/BasePagination.vue +266 -266
  306. package/src/components/BasePanel.stories.js +56 -56
  307. package/src/components/BasePanel.vue +42 -42
  308. package/src/components/BasePassword.stories.js +57 -57
  309. package/src/components/BasePassword.vue +107 -107
  310. package/src/components/BaseProgressCircle.stories.js +27 -27
  311. package/src/components/BaseProgressCircle.vue +80 -80
  312. package/src/components/BaseRadioGroup.stories.js +88 -88
  313. package/src/components/BaseRadioGroup.vue +125 -125
  314. package/src/components/BaseReadMore.stories.js +30 -30
  315. package/src/components/BaseReadMore.vue +73 -73
  316. package/src/components/BaseRichText.stories.js +102 -102
  317. package/src/components/BaseRichText.vue +182 -182
  318. package/src/components/BaseSelect.stories.js +118 -118
  319. package/src/components/BaseSelect.vue +224 -224
  320. package/src/components/BaseShortcut.stories.js +102 -102
  321. package/src/components/BaseShortcut.vue +112 -112
  322. package/src/components/BaseSideNavigation.stories.js +80 -80
  323. package/src/components/BaseSideNavigation.vue +32 -32
  324. package/src/components/BaseSideNavigationItem.vue +95 -95
  325. package/src/components/BaseSkeleton.stories.js +36 -36
  326. package/src/components/BaseSkeleton.vue +40 -40
  327. package/src/components/BaseStatistic.stories.js +51 -51
  328. package/src/components/BaseStatistic.vue +109 -109
  329. package/src/components/BaseStepper.stories.js +94 -94
  330. package/src/components/BaseStepper.vue +72 -72
  331. package/src/components/BaseStepperItem.stories.js +65 -65
  332. package/src/components/BaseStepperItem.vue +149 -149
  333. package/src/components/BaseSwitch.stories.js +130 -130
  334. package/src/components/BaseSwitch.vue +215 -215
  335. package/src/components/BaseSystemAlert.stories.js +63 -63
  336. package/src/components/BaseSystemAlert.vue +89 -89
  337. package/src/components/BaseTabItem.vue +96 -96
  338. package/src/components/BaseTable.vue +890 -890
  339. package/src/components/BaseTableColumn.vue +124 -124
  340. package/src/components/BaseTabs.stories.js +85 -85
  341. package/src/components/BaseTabs.vue +73 -73
  342. package/src/components/BaseTagAutocomplete.stories.js +258 -258
  343. package/src/components/BaseTagAutocomplete.vue +438 -438
  344. package/src/components/BaseTagAutocompleteFetch.stories.js +185 -185
  345. package/src/components/BaseTagAutocompleteFetch.vue +220 -220
  346. package/src/components/BaseTextarea.stories.js +58 -58
  347. package/src/components/BaseTextarea.vue +103 -103
  348. package/src/components/BaseTextareaAutoresize.stories.js +102 -102
  349. package/src/components/BaseTextareaAutoresize.vue +166 -166
  350. package/src/components/BaseTimeline.stories.js +53 -53
  351. package/src/components/BaseTimeline.vue +35 -35
  352. package/src/components/BaseTimelineItem.stories.js +78 -78
  353. package/src/components/BaseTimelineItem.vue +79 -79
  354. package/src/components/BaseUniqueCode.stories.js +36 -36
  355. package/src/components/BaseUniqueCode.vue +183 -183
  356. package/src/components/SlotComponent.ts +37 -37
  357. package/src/components/index.ts +194 -194
  358. package/src/composables/breakpoints.ts +94 -94
  359. package/src/composables/clickOutside.ts +80 -80
  360. package/src/composables/field.ts +117 -117
  361. package/src/composables/hasOptions.ts +68 -68
  362. package/src/composables/mediaQuery.ts +42 -42
  363. package/src/composables/modal.ts +73 -73
  364. package/src/composables/paginatedData.ts +65 -65
  365. package/src/constants/MyConstants.ts +1 -1
  366. package/src/constants/index.ts +5 -5
  367. package/src/env.d.ts +15 -15
  368. package/src/i18n/index.ts +60 -60
  369. package/src/index.ts +111 -111
  370. package/src/lang/en.json +1 -1
  371. package/src/lang/fr.json +1 -1
  372. package/src/services/gantt/format.ts +113 -113
  373. package/src/services/gantt/timescale.ts +242 -242
  374. package/src/services/gantt/types.ts +74 -74
  375. package/src/stores/dialogs.ts +45 -45
  376. package/src/stores/i18n.ts +14 -14
  377. package/src/stores/notifications.ts +47 -47
  378. package/src/stores/systemAlerts.ts +33 -33
  379. package/src/svg/BaseEmptyState.vue +38 -38
  380. package/src/svg/BaseSpinnerLarge.vue +59 -59
  381. package/src/svg/BaseSpinnerSmall.vue +15 -15
  382. package/src/types/Color.ts +9 -9
  383. package/src/types/Country.ts +4 -4
  384. package/src/types/ImagePickerResult.ts +5 -5
  385. package/src/types/Media.ts +10 -10
  386. package/src/types/Notification.ts +10 -10
  387. package/src/types/Region.ts +5 -5
  388. package/src/types/Status.ts +5 -5
  389. package/src/types/StepperItem.ts +8 -8
  390. package/src/types/TimelineItem.ts +8 -8
  391. package/src/types/UploadedFile.ts +11 -11
  392. package/src/types/User.ts +7 -7
  393. package/src/types/index.ts +267 -267
  394. package/src/utils/blob.ts +30 -30
  395. package/src/utils/colors.ts +200 -200
  396. package/src/utils/cropper/avatar.ts +33 -33
  397. package/src/utils/cropper/cover.ts +41 -41
  398. package/src/utils/cropper/presetInterface.ts +16 -16
  399. package/src/utils/cropper/presets.ts +7 -7
  400. package/src/utils/fileSizeFormat.ts +15 -15
  401. package/src/utils/fileValidations.ts +26 -26
  402. package/src/utils/index.ts +16 -16
  403. package/src/utils/resizeImageFromURI.ts +118 -118
  404. package/src/utils/scrollPreventer.ts +11 -11
  405. package/src/utils/toHumanList.ts +20 -20
@@ -1,890 +1,890 @@
1
- <template>
2
- <div
3
- class="relative w-full overflow-hidden"
4
- :class="maxHeight ? 'base-table--has-max-height' : ''"
5
- >
6
- <div
7
- ref="slot"
8
- style="display: none"
9
- >
10
- <slot />
11
- </div>
12
-
13
- <div class="flex flex-col">
14
- <div
15
- ref="scrollable"
16
- class="overflow-x-auto overflow-y-auto"
17
- data-scroll-lock-scrollable
18
- :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
19
- >
20
- <div class="inline-block min-w-full align-middle">
21
- <div class="relative min-h-[300px]">
22
- <table class="min-w-full border-separate border-spacing-0">
23
- <thead
24
- v-if="newColumns.length"
25
- ref="thead"
26
- >
27
- <tr>
28
- <th
29
- v-if="showDetailRowIcon"
30
- class="th"
31
- :style="detailsStyles(true)"
32
- />
33
- <th
34
- v-if="checkable && checkboxPosition === 'left'"
35
- class="th group cursor-pointer py-0 pl-3"
36
- align="left"
37
- :style="checkStyles(true)"
38
- @click="checkAll"
39
- >
40
- <div class="flex items-center">
41
- <input
42
- type="checkbox"
43
- autocomplete="off"
44
- :checked="isAllChecked"
45
- :disabled="isAllUncheckable"
46
- :class="checkboxStyle"
47
- >
48
- </div>
49
- </th>
50
- <th
51
- v-for="(column, index) in visibleColumns"
52
- :key="column.newKey + ':' + index + 'header'"
53
- v-bind="column.thAttrs && column.thAttrs(column)"
54
- :style="[
55
- column.style,
56
- index == 0 ? firstColStyles(true) : {},
57
- ]"
58
- class="th group py-2 pl-3 pr-3 text-left"
59
- :class="{
60
- 'cursor-pointer': column.sortable,
61
- }"
62
- @click.stop="sort(column, undefined, $event as any)"
63
- >
64
- <button
65
- type="button"
66
- class="flex w-full items-center bg-transparent text-left text-sm font-medium leading-tight text-slate-900"
67
- :class="{
68
- 'text-blue-600':
69
- column.sortable && currentSortColumn === column,
70
- }"
71
- >
72
- <span class="whitespace-nowrap text-xs text-slate-500">
73
- {{ column.label }}
74
- </span>
75
- <div
76
- v-if="column.sortable"
77
- class="w-3"
78
- :class="[
79
- currentSortColumn === column
80
- ? ''
81
- : 'opacity-0 duration-200 group-hover:opacity-100',
82
- ]"
83
- >
84
- <svg
85
- viewBox="0 0 24 24"
86
- class="absolute top-1/2 h-5 w-5 -translate-y-1/2"
87
- >
88
- <g transform="translate(0 -3)">
89
- <path
90
- :opacity="!isAsc ? '0.5' : '1'"
91
- fill="currentColor"
92
- d="M8.71 12.29L11.3 9.7a.996.996 0 0 1 1.41 0l2.59 2.59c.63.63.18 1.71-.71 1.71H9.41c-.89 0-1.33-1.08-.7-1.71z"
93
- />
94
- </g>
95
- <g transform="translate(0 3)">
96
- <path
97
- :opacity="isAsc ? '0.5' : '1'"
98
- fill="currentColor"
99
- d="m8.71 11.71l2.59 2.59c.39.39 1.02.39 1.41 0l2.59-2.59c.63-.63.18-1.71-.71-1.71H9.41c-.89 0-1.33 1.08-.7 1.71z"
100
- />
101
- </g>
102
- </svg>
103
- </div>
104
- </button>
105
- </th>
106
- <th
107
- v-if="checkable && checkboxPosition === 'right'"
108
- class="th group cursor-pointer pr-3"
109
- align="right"
110
- @click="checkAll"
111
- >
112
- <input
113
- autocomplete="off"
114
- type="checkbox"
115
- :checked="isAllChecked"
116
- :disabled="isAllUncheckable"
117
- :class="checkboxStyle"
118
- >
119
- </th>
120
- </tr>
121
- </thead>
122
-
123
- <tbody class="bg-white">
124
- <template
125
- v-for="(row, index) in data"
126
- :key="getRowIndex(row, index)"
127
- >
128
- <tr class="item-row">
129
- <td
130
- v-if="showDetailRowIcon"
131
- class="group cursor-pointer bg-white pl-3"
132
- :class="borderBottomClasses(index, row)"
133
- :style="detailsStyles(false)"
134
- @click.stop="toggleDetails(row)"
135
- >
136
- <button
137
- type="button"
138
- class="mr-0 flex h-5 w-5 appearance-none items-center justify-center rounded-full border border-slate-300 bg-white text-slate-400 shadow duration-100 group-hover:text-slate-600 group-hover:shadow-md"
139
- >
140
- <BaseIcon
141
- v-if="hasDetailedVisible(row)"
142
- icon="mdi:chevron-down"
143
- class="h-5 w-5 duration-300"
144
- :class="{
145
- 'rotate-180': isVisibleDetailRow(row),
146
- }"
147
- />
148
- </button>
149
- </td>
150
-
151
- <td
152
- v-if="checkable && checkboxPosition === 'left'"
153
- class="group z-[1] cursor-pointer bg-white pl-3"
154
- :style="checkStyles(false)"
155
- :class="borderBottomClasses(index, row)"
156
- @click="checkRow(row, index, $event as MouseEvent)"
157
- >
158
- <div class="flex items-center">
159
- <input
160
- type="checkbox"
161
- autocomplete="off"
162
- :disabled="!isRowCheckable(row)"
163
- :checked="isRowChecked(row)"
164
- :class="checkboxStyle"
165
- >
166
- </div>
167
- </td>
168
-
169
- <SlotComponent
170
- v-for="(column, colindex) in visibleColumns"
171
- :key="column.newKey + index + ':' + colindex"
172
- v-bind="column.tdAttrs && column.tdAttrs(row, column)"
173
- :component="column"
174
- scoped
175
- name="default"
176
- tag="td"
177
- class="bg-white py-3 pl-3 pr-3 text-sm"
178
- :style="[
179
- column.style,
180
- colindex === 0 ? firstColStyles(false) : {},
181
- ]"
182
- :class="[
183
- borderBottomClasses(index, row),
184
- column.clickable ? 'cursor-pointer' : '',
185
- ]"
186
- :data-label="column.label"
187
- :props="{ row, column, index, colindex, toggleDetails }"
188
- @click="
189
- onColumnClick(row, column, index, colindex, $event)
190
- "
191
- />
192
-
193
- <td
194
- v-if="checkable && checkboxPosition === 'right'"
195
- class="group cursor-pointer pr-3"
196
- :class="borderBottomClasses(index, row)"
197
- align="right"
198
- @click="checkRow(row, index, $event as MouseEvent)"
199
- >
200
- <input
201
- type="checkbox"
202
- autocomplete="off"
203
- :disabled="!isRowCheckable(row)"
204
- :checked="isRowChecked(row)"
205
- :class="checkboxStyle"
206
- >
207
- </td>
208
- </tr>
209
-
210
- <transition :name="detailTransition">
211
- <tr
212
- v-if="isActiveDetailRow(row)"
213
- :key="getRowIndex(row, index) + 'detail'"
214
- >
215
- <td
216
- :colspan="columnCount"
217
- class="td"
218
- :class="borderBottomDetailClasses(index)"
219
- >
220
- <slot
221
- name="detail"
222
- :row="row"
223
- :index="index"
224
- />
225
- </td>
226
- </tr>
227
- </transition>
228
- </template>
229
-
230
- <tr v-if="data.length == 0">
231
- <td :colspan="columnCount">
232
- <slot name="empty" />
233
- </td>
234
- </tr>
235
- </tbody>
236
- </table>
237
-
238
- <slot name="loading">
239
- <Transition
240
- enter-active-class="transition ease-out duration-200"
241
- enter-from-class="opacity-0"
242
- enter-to-class="opacity-100"
243
- leave-active-class="transition ease-in duration-200"
244
- leave-from-class="opacity-100"
245
- leave-to-class="opacity-0"
246
- >
247
- <div
248
- v-if="loading"
249
- class="absolute inset-0 z-[1] flex h-full w-full items-start justify-center"
250
- >
251
- <div class="absolute h-full w-full bg-white bg-opacity-60" />
252
-
253
- <div class="pt-20">
254
- <BaseSpinnerLarge class="h-10 w-10 text-blue-500" />
255
- </div>
256
- </div>
257
- </Transition>
258
- </slot>
259
- </div>
260
- </div>
261
- </div>
262
- </div>
263
- </div>
264
- </template>
265
-
266
- <script lang="ts">
267
- export default {
268
- name: 'BaseTable',
269
- inheritAttrs: false,
270
- };
271
- </script>
272
-
273
- <script lang="ts" setup>
274
- import { PropType, ref } from 'vue';
275
- import { BaseTableColumn, Row } from '@/types';
276
- import SlotComponent from './SlotComponent';
277
- import { useResizeObserver, useScroll } from '@vueuse/core';
278
- import { debounce, isArray } from 'lodash';
279
- import BaseSpinnerLarge from '../svg/BaseSpinnerLarge.vue';
280
-
281
- const checkboxStyle =
282
- 'disabled:bg-slate-100 group-hover:shadow-md disabled:border-slate-300 disabled:cursor-not-allowed duration-300 cursor-pointer focus:ring-blue-300 border border-slate-300 shadow h-[18px] w-[18px] rounded';
283
- const DETAIL_ROW_WIDTH = 36;
284
- const CHECK_ROW_WIDTH = 36;
285
-
286
- provide('table', getCurrentInstance());
287
-
288
- const props = defineProps({
289
- /** Table data */
290
- data: {
291
- type: Array as PropType<Row[]>,
292
- default: () => [],
293
- },
294
- /** Loading state */
295
- loading: {
296
- default: false,
297
- type: Boolean,
298
- },
299
- visibleColumns: {
300
- default: undefined,
301
- type: Array as PropType<number[]>,
302
- },
303
- /** Allow row details */
304
- detailed: {
305
- default: false,
306
- type: Boolean,
307
- },
308
- /** Rows can be checked (multiple) */
309
- checkable: {
310
- default: false,
311
- type: Boolean,
312
- },
313
- /**
314
- * Position of the checkbox (if checkable is true)
315
- * @values left, right
316
- */
317
- checkboxPosition: {
318
- type: String as PropType<'left' | 'right'>,
319
- default: 'left',
320
- },
321
- /** Custom method to verify if a row is checkable, works when is checkable */
322
- isRowCheckable: {
323
- type: Function,
324
- default: () => true,
325
- },
326
- /** Set which rows are checked, use v-model:checkedRows to make it two-way binding */
327
- checkedRows: {
328
- default: () => [],
329
- type: Array as PropType<Row[]>,
330
- },
331
- /** Sets the default sort column field */
332
- sortField: {
333
- type: String,
334
- default: '',
335
- },
336
- /**
337
- * Sets the default sort column direction
338
- * @values asc, desc
339
- */
340
- sortDirection: {
341
- type: String,
342
- default: 'asc',
343
- },
344
- /** Controls the visibility of the trigger that toggles the detailed rows. */
345
- hasDetailedVisible: {
346
- type: Function,
347
- default: () => true,
348
- },
349
- /** Use a unique key of your data Object when use detailed or opened detailed. (id recommended) */
350
- rowKey: {
351
- type: String,
352
- default: 'id',
353
- },
354
- /* Transition name to use when toggling row details. */
355
- detailTransition: {
356
- type: String,
357
- default: '',
358
- },
359
- /* Max height (in px) */
360
- maxHeight: {
361
- default: undefined,
362
- type: Number,
363
- },
364
- });
365
-
366
- const emit = defineEmits([
367
- 'check',
368
- 'check-all',
369
- 'update:checkedRows',
370
- 'details-open',
371
- 'details-close',
372
- 'update:openedDetailed',
373
- 'sort',
374
- 'cell-click',
375
- ]);
376
-
377
- const visibleDetailRows = ref<Row[]>([]);
378
- const newCheckedRows = ref<Row[]>([...props.checkedRows]);
379
- const lastCheckedRowIndex = ref<number | null>(null);
380
- const currentSortColumn = ref<BaseTableColumn | null>(null);
381
- const isAsc = ref(true);
382
- const defaultSlots = ref<BaseTableColumn[]>([]);
383
- const sequence = ref(1);
384
-
385
- const slot = ref<HTMLElement | null>(null);
386
- const thead = ref<HTMLElement | null>(null);
387
- const theadHeight = ref(0);
388
-
389
- useResizeObserver(thead, () => setTheadHeightDebounce());
390
-
391
- const setTheadHeightDebounce = debounce(() => {
392
- setTheadHeight();
393
- }, 100);
394
-
395
- function setTheadHeight() {
396
- if (thead.value) {
397
- theadHeight.value = thead.value.clientHeight;
398
- }
399
- }
400
-
401
- const newColumns = computed(() => {
402
- return defaultSlots.value;
403
- });
404
-
405
- const visibleColumns = computed(() => {
406
- if (!newColumns.value) {
407
- return newColumns.value;
408
- }
409
-
410
- return newColumns.value.filter((column: BaseTableColumn) => {
411
- if (column.toggle === false) {
412
- return true;
413
- }
414
-
415
- if (!isArray(props.visibleColumns)) {
416
- return true;
417
- }
418
-
419
- if (props.visibleColumns.includes(column.newKey)) {
420
- return true;
421
- }
422
-
423
- return false;
424
- });
425
- });
426
-
427
- /**
428
- * Return total column count based if it's checkable or expanded
429
- */
430
- const columnCount = computed(() => {
431
- let count = visibleColumns.value.length;
432
- count += props.checkable ? 1 : 0;
433
- count += props.detailed ? 1 : 0;
434
-
435
- return count;
436
- });
437
-
438
- /**
439
- * Return if detailed row tabled
440
- * will be with chevron column & icon or not
441
- */
442
- const showDetailRowIcon = computed(() => {
443
- return props.detailed;
444
- });
445
-
446
- /**
447
- * When checkedRows prop change, update internal value without
448
- * mutating original data.
449
- */
450
- watch(
451
- () => props.checkedRows,
452
- (rows) => {
453
- newCheckedRows.value = [...rows];
454
- },
455
- { deep: true }
456
- );
457
-
458
- watch(
459
- () => props.sortField,
460
- () => {
461
- updateSortState();
462
- }
463
- );
464
-
465
- watch(
466
- () => props.sortDirection,
467
- () => {
468
- updateSortState();
469
- }
470
- );
471
-
472
- onMounted(() => {
473
- nextTick(() => {
474
- updateSortState();
475
- });
476
- });
477
-
478
- /**
479
- * Sort the column.
480
- * Toggle current direction on column if it's sortable
481
- * and not just updating the prop.
482
- */
483
- function sort(column: BaseTableColumn, updatingData = false, event = null) {
484
- if (!column || !column.sortable) {
485
- return;
486
- }
487
-
488
- if (!updatingData) {
489
- isAsc.value =
490
- column === currentSortColumn.value
491
- ? !isAsc.value
492
- : props.sortDirection.toLowerCase() !== 'desc';
493
- }
494
-
495
- /**
496
- * @property {string} field column field
497
- * @property {boolean} direction 'asc' or 'desc'
498
- * @property {Event} event native event
499
- */
500
- emit('sort', column.field, isAsc.value ? 'asc' : 'desc', event);
501
-
502
- currentSortColumn.value = column;
503
- }
504
-
505
- /**
506
- * Check if the row is checked (is added to the array).
507
- */
508
- function isRowChecked(row: Row): boolean {
509
- return (
510
- newCheckedRows.value.find((r) => r[props.rowKey] == row[props.rowKey]) !==
511
- undefined
512
- );
513
- }
514
-
515
- /**
516
- * Check if all rows in the page are checkable.
517
- */
518
- const isAllUncheckable = computed(() => {
519
- const validData = props.data.filter((row) => props.isRowCheckable(row));
520
- return validData.length === 0;
521
- });
522
-
523
- /**
524
- * Check if all rows in the page are checked.
525
- */
526
- const isAllChecked = computed(() => {
527
- const validData = props.data.filter((row) => {
528
- return props.isRowCheckable(row);
529
- });
530
-
531
- if (validData.length === 0) {
532
- return false;
533
- }
534
-
535
- const missingChecked = validData.some((currentRow) => {
536
- return !isRowChecked(currentRow);
537
- });
538
-
539
- return !missingChecked;
540
- });
541
-
542
- function getCheckedRowIndex(row: Row) {
543
- return newCheckedRows.value.findIndex(
544
- (r) => r[props.rowKey] == row[props.rowKey]
545
- );
546
- }
547
-
548
- /**
549
- * Remove a checked row from the array.
550
- */
551
- function removeCheckedRow(row: Row) {
552
- const index = getCheckedRowIndex(row);
553
- if (index >= 0) {
554
- newCheckedRows.value.splice(index, 1);
555
- }
556
- }
557
-
558
- /**
559
- * Header checkbox click listener.
560
- * Add or remove all rows in current page.
561
- */
562
- function checkAll() {
563
- if (isAllChecked.value) {
564
- newCheckedRows.value = [];
565
- } else {
566
- props.data.forEach((currentRow) => {
567
- if (props.isRowCheckable(currentRow) && !isRowChecked(currentRow)) {
568
- newCheckedRows.value.push(currentRow);
569
- }
570
- });
571
- }
572
-
573
- sendCheckUpdate();
574
- }
575
-
576
- /**
577
- * Remove all rows in current page.
578
- */
579
- function uncheckAll() {
580
- newCheckedRows.value = [];
581
-
582
- sendCheckUpdate();
583
- }
584
-
585
- function sendCheckUpdate() {
586
- emit('check', newCheckedRows.value);
587
- emit('check-all', newCheckedRows.value);
588
- emit('update:checkedRows', newCheckedRows.value);
589
- }
590
-
591
- /**
592
- * Row checkbox click listener.
593
- */
594
- function checkRow(row: Row, index: number, event: MouseEvent) {
595
- if (!props.isRowCheckable(row)) {
596
- return;
597
- }
598
-
599
- const lastIndex = lastCheckedRowIndex.value;
600
- lastCheckedRowIndex.value = index;
601
-
602
- if (event.shiftKey && lastIndex !== null && index !== lastIndex) {
603
- shiftCheckRow(row, index, lastIndex);
604
- } else if (!isRowChecked(row)) {
605
- newCheckedRows.value.push(row);
606
- } else {
607
- removeCheckedRow(row);
608
- }
609
-
610
- emit('check', newCheckedRows.value, row);
611
-
612
- // Emit checked rows to update user variable
613
- emit('update:checkedRows', newCheckedRows.value);
614
- }
615
-
616
- /**
617
- * Check row when shift is pressed.
618
- */
619
- function shiftCheckRow(row: Row, index: number, lastCheckedRowIndex: number) {
620
- // Get the subset of the list between the two indices
621
- const subset = props.data.slice(
622
- Math.min(index, lastCheckedRowIndex),
623
- Math.max(index, lastCheckedRowIndex) + 1
624
- );
625
-
626
- // Determine the operation based on the state of the clicked checkbox
627
- const shouldCheck = !isRowChecked(row);
628
-
629
- subset.forEach((item) => {
630
- removeCheckedRow(item);
631
- if (shouldCheck && props.isRowCheckable(item)) {
632
- newCheckedRows.value.push(item);
633
- }
634
- });
635
- }
636
-
637
- /**
638
- * Toggle to show/hide details slot
639
- */
640
- function toggleDetails(row: Row) {
641
- const found = isVisibleDetailRow(row);
642
-
643
- if (found) {
644
- closeDetailRow(row);
645
- emit('details-close', row);
646
- } else {
647
- openDetailRow(row);
648
- emit('details-open', row);
649
- }
650
-
651
- // Syncs the detailed rows with the parent component
652
- emit('update:openedDetailed', visibleDetailRows.value);
653
- }
654
-
655
- function openDetailRow(row: Row) {
656
- const index = getDetailedIndex(row);
657
- visibleDetailRows.value.push(index);
658
- }
659
-
660
- function closeDetailRow(row: Row) {
661
- const index = getDetailedIndex(row);
662
- const i = visibleDetailRows.value.indexOf(index);
663
- if (i >= 0) {
664
- visibleDetailRows.value.splice(i, 1);
665
- }
666
- }
667
-
668
- function isVisibleDetailRow(row: Row) {
669
- const index = getDetailedIndex(row);
670
- return visibleDetailRows.value.indexOf(index) >= 0;
671
- }
672
-
673
- function isActiveDetailRow(row: Row) {
674
- return props.detailed && isVisibleDetailRow(row);
675
- }
676
-
677
- /**
678
- * When the rowKey is defined we use the object[rowKey] as index.
679
- * If not, use the object reference by default.
680
- */
681
- function getDetailedIndex(row: Row) {
682
- const key = props.rowKey;
683
- return !key.length || !row ? row : row[key];
684
- }
685
-
686
- /**
687
- * Update sort state
688
- */
689
- function updateSortState() {
690
- const sortField = props.sortField;
691
-
692
- const sortDirection = props.sortDirection;
693
-
694
- const sortColumn = newColumns.value.filter(
695
- (column) => column.field === sortField
696
- )[0];
697
-
698
- // Set sort state
699
-
700
- if (sortColumn) {
701
- currentSortColumn.value = sortColumn;
702
- isAsc.value = sortDirection.toLowerCase() !== 'desc';
703
- } else {
704
- currentSortColumn.value = null;
705
- return;
706
- }
707
- }
708
-
709
- /*
710
- |--------------------------------------------------------------------------
711
- | BaseTableColumns functions
712
- |--------------------------------------------------------------------------
713
- */
714
-
715
- function addColumn(column: BaseTableColumn) {
716
- defaultSlots.value.push(column);
717
-
718
- const slotHTMLElement = slot.value as HTMLElement;
719
-
720
- if (slotHTMLElement && slotHTMLElement.children) {
721
- nextTick(() => {
722
- const ids = defaultSlots.value
723
- .map((it) => `[data-id="${it.newKey}"]`)
724
- .join(',');
725
-
726
- const sortedIds = Array.from(slotHTMLElement.querySelectorAll(ids)).map(
727
- (el: Element) => el.getAttribute('data-id')
728
- );
729
-
730
- defaultSlots.value = defaultSlots.value.sort((a, b) => {
731
- return (
732
- sortedIds.indexOf(`${a.newKey}`) - sortedIds.indexOf(`${b.newKey}`)
733
- );
734
- });
735
- });
736
- }
737
- }
738
-
739
- function removeColumn(column: BaseTableColumn) {
740
- defaultSlots.value = defaultSlots.value.filter(
741
- (d) => d.newKey !== column.newKey
742
- );
743
- }
744
-
745
- const borderClasses = 'border-b border-slate-200';
746
-
747
- function borderBottomClasses(index: number, row: Record<string, any>): string {
748
- if (index < props.data.length - 1) {
749
- return borderClasses;
750
- }
751
-
752
- if (isActiveDetailRow(row)) {
753
- return borderClasses;
754
- }
755
-
756
- return '';
757
- }
758
-
759
- function borderBottomDetailClasses(index: number): string {
760
- if (index < props.data.length - 1) {
761
- return borderClasses;
762
- }
763
-
764
- return '';
765
- }
766
-
767
- function onColumnClick(
768
- row: Row,
769
- column: BaseTableColumn,
770
- index: number,
771
- colindex: number,
772
- event: MouseEvent
773
- ) {
774
- if (column.clickable) {
775
- emit('cell-click', row, column, index, colindex, event);
776
- }
777
- }
778
-
779
- function nextSequence() {
780
- return sequence.value++;
781
- }
782
-
783
- function getRowIndex(row: Row, index: number): string {
784
- if (row.id) {
785
- return row.id;
786
- }
787
- if (row.key) {
788
- return row.key;
789
- }
790
- if (row.uuid) {
791
- return row.uuid;
792
- }
793
- return index + '';
794
- }
795
-
796
- // Sticky styles
797
-
798
- const horizontalScrolling = ref(false);
799
- const scrollable = ref<null | HTMLElement>(null);
800
-
801
- const { x } = useScroll(scrollable);
802
- watch(x, (value) => {
803
- horizontalScrolling.value = value > 0;
804
- });
805
-
806
- function zIndex(th: boolean) {
807
- if (th) {
808
- return props.maxHeight ? 3 : 2;
809
- }
810
- return 1;
811
- }
812
-
813
- function detailsStyles(th: boolean): any {
814
- if (props.detailed) {
815
- return {
816
- zIndex: zIndex(th),
817
- position: 'sticky',
818
- left: 0,
819
- width: DETAIL_ROW_WIDTH + 'px',
820
- minWidth: DETAIL_ROW_WIDTH + 'px',
821
- maxWidth: DETAIL_ROW_WIDTH + 'px',
822
- };
823
- }
824
- return {};
825
- }
826
-
827
- function checkStyles(th: boolean): any {
828
- if (props.checkable) {
829
- return {
830
- zIndex: zIndex(th),
831
- position: 'sticky',
832
- left: props.detailed ? DETAIL_ROW_WIDTH + 'px' : 0,
833
- width: CHECK_ROW_WIDTH + 'px',
834
- minWidth: CHECK_ROW_WIDTH + 'px',
835
- maxWidth: CHECK_ROW_WIDTH + 'px',
836
- };
837
- }
838
- return {};
839
- }
840
-
841
- function firstColStyles(th: boolean): any {
842
- let left = 0;
843
- if (props.checkable) {
844
- left += CHECK_ROW_WIDTH;
845
- }
846
- if (props.detailed) {
847
- left += DETAIL_ROW_WIDTH;
848
- }
849
- return {
850
- zIndex: zIndex(th) + 1,
851
- position: 'sticky',
852
- left: left + 'px',
853
- borderRight: horizontalScrolling.value ? '1px solid #e2e8f0' : 'none',
854
- };
855
- }
856
-
857
- function scrollTop() {
858
- if (scrollable.value) {
859
- scrollable.value.scrollTo({ top: 0, behavior: 'smooth' });
860
- }
861
- }
862
-
863
- provide('addColumn', addColumn);
864
- provide('removeColumn', removeColumn);
865
- provide('nextSequence', nextSequence);
866
-
867
- defineExpose({
868
- newColumns,
869
- uncheckAll,
870
- scrollTop,
871
- });
872
- </script>
873
-
874
- <style lang="postcss" scoped>
875
- .th {
876
- @apply relative z-[2];
877
- @apply bg-slate-50;
878
- @apply border-b border-slate-300;
879
- }
880
-
881
- .base-table--has-max-height .th {
882
- @apply sticky;
883
- @apply top-0;
884
- @apply bg-opacity-75 backdrop-blur backdrop-filter;
885
- }
886
-
887
- tbody tr.item-row:hover td {
888
- @apply bg-slate-50;
889
- }
890
- </style>
1
+ <template>
2
+ <div
3
+ class="relative w-full overflow-hidden"
4
+ :class="maxHeight ? 'base-table--has-max-height' : ''"
5
+ >
6
+ <div
7
+ ref="slot"
8
+ style="display: none"
9
+ >
10
+ <slot />
11
+ </div>
12
+
13
+ <div class="flex flex-col">
14
+ <div
15
+ ref="scrollable"
16
+ class="overflow-x-auto overflow-y-auto"
17
+ data-scroll-lock-scrollable
18
+ :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }"
19
+ >
20
+ <div class="inline-block min-w-full align-middle">
21
+ <div class="relative min-h-[300px]">
22
+ <table class="min-w-full border-separate border-spacing-0">
23
+ <thead
24
+ v-if="newColumns.length"
25
+ ref="thead"
26
+ >
27
+ <tr>
28
+ <th
29
+ v-if="showDetailRowIcon"
30
+ class="th"
31
+ :style="detailsStyles(true)"
32
+ />
33
+ <th
34
+ v-if="checkable && checkboxPosition === 'left'"
35
+ class="th group cursor-pointer py-0 pl-3"
36
+ align="left"
37
+ :style="checkStyles(true)"
38
+ @click="checkAll"
39
+ >
40
+ <div class="flex items-center">
41
+ <input
42
+ type="checkbox"
43
+ autocomplete="off"
44
+ :checked="isAllChecked"
45
+ :disabled="isAllUncheckable"
46
+ :class="checkboxStyle"
47
+ >
48
+ </div>
49
+ </th>
50
+ <th
51
+ v-for="(column, index) in visibleColumns"
52
+ :key="column.newKey + ':' + index + 'header'"
53
+ v-bind="column.thAttrs && column.thAttrs(column)"
54
+ :style="[
55
+ column.style,
56
+ index == 0 ? firstColStyles(true) : {},
57
+ ]"
58
+ class="th group py-2 pl-3 pr-3 text-left"
59
+ :class="{
60
+ 'cursor-pointer': column.sortable,
61
+ }"
62
+ @click.stop="sort(column, undefined, $event as any)"
63
+ >
64
+ <button
65
+ type="button"
66
+ class="flex w-full items-center bg-transparent text-left text-sm font-medium leading-tight text-slate-900"
67
+ :class="{
68
+ 'text-blue-600':
69
+ column.sortable && currentSortColumn === column,
70
+ }"
71
+ >
72
+ <span class="whitespace-nowrap text-xs text-slate-500">
73
+ {{ column.label }}
74
+ </span>
75
+ <div
76
+ v-if="column.sortable"
77
+ class="w-3"
78
+ :class="[
79
+ currentSortColumn === column
80
+ ? ''
81
+ : 'opacity-0 duration-200 group-hover:opacity-100',
82
+ ]"
83
+ >
84
+ <svg
85
+ viewBox="0 0 24 24"
86
+ class="absolute top-1/2 h-5 w-5 -translate-y-1/2"
87
+ >
88
+ <g transform="translate(0 -3)">
89
+ <path
90
+ :opacity="!isAsc ? '0.5' : '1'"
91
+ fill="currentColor"
92
+ d="M8.71 12.29L11.3 9.7a.996.996 0 0 1 1.41 0l2.59 2.59c.63.63.18 1.71-.71 1.71H9.41c-.89 0-1.33-1.08-.7-1.71z"
93
+ />
94
+ </g>
95
+ <g transform="translate(0 3)">
96
+ <path
97
+ :opacity="isAsc ? '0.5' : '1'"
98
+ fill="currentColor"
99
+ d="m8.71 11.71l2.59 2.59c.39.39 1.02.39 1.41 0l2.59-2.59c.63-.63.18-1.71-.71-1.71H9.41c-.89 0-1.33 1.08-.7 1.71z"
100
+ />
101
+ </g>
102
+ </svg>
103
+ </div>
104
+ </button>
105
+ </th>
106
+ <th
107
+ v-if="checkable && checkboxPosition === 'right'"
108
+ class="th group cursor-pointer pr-3"
109
+ align="right"
110
+ @click="checkAll"
111
+ >
112
+ <input
113
+ autocomplete="off"
114
+ type="checkbox"
115
+ :checked="isAllChecked"
116
+ :disabled="isAllUncheckable"
117
+ :class="checkboxStyle"
118
+ >
119
+ </th>
120
+ </tr>
121
+ </thead>
122
+
123
+ <tbody class="bg-white">
124
+ <template
125
+ v-for="(row, index) in data"
126
+ :key="getRowIndex(row, index)"
127
+ >
128
+ <tr class="item-row">
129
+ <td
130
+ v-if="showDetailRowIcon"
131
+ class="group cursor-pointer bg-white pl-3"
132
+ :class="borderBottomClasses(index, row)"
133
+ :style="detailsStyles(false)"
134
+ @click.stop="toggleDetails(row)"
135
+ >
136
+ <button
137
+ type="button"
138
+ class="mr-0 flex h-5 w-5 appearance-none items-center justify-center rounded-full border border-slate-300 bg-white text-slate-400 shadow duration-100 group-hover:text-slate-600 group-hover:shadow-md"
139
+ >
140
+ <BaseIcon
141
+ v-if="hasDetailedVisible(row)"
142
+ icon="mdi:chevron-down"
143
+ class="h-5 w-5 duration-300"
144
+ :class="{
145
+ 'rotate-180': isVisibleDetailRow(row),
146
+ }"
147
+ />
148
+ </button>
149
+ </td>
150
+
151
+ <td
152
+ v-if="checkable && checkboxPosition === 'left'"
153
+ class="group z-[1] cursor-pointer bg-white pl-3"
154
+ :style="checkStyles(false)"
155
+ :class="borderBottomClasses(index, row)"
156
+ @click="checkRow(row, index, $event as MouseEvent)"
157
+ >
158
+ <div class="flex items-center">
159
+ <input
160
+ type="checkbox"
161
+ autocomplete="off"
162
+ :disabled="!isRowCheckable(row)"
163
+ :checked="isRowChecked(row)"
164
+ :class="checkboxStyle"
165
+ >
166
+ </div>
167
+ </td>
168
+
169
+ <SlotComponent
170
+ v-for="(column, colindex) in visibleColumns"
171
+ :key="column.newKey + index + ':' + colindex"
172
+ v-bind="column.tdAttrs && column.tdAttrs(row, column)"
173
+ :component="column"
174
+ scoped
175
+ name="default"
176
+ tag="td"
177
+ class="bg-white py-3 pl-3 pr-3 text-sm"
178
+ :style="[
179
+ column.style,
180
+ colindex === 0 ? firstColStyles(false) : {},
181
+ ]"
182
+ :class="[
183
+ borderBottomClasses(index, row),
184
+ column.clickable ? 'cursor-pointer' : '',
185
+ ]"
186
+ :data-label="column.label"
187
+ :props="{ row, column, index, colindex, toggleDetails }"
188
+ @click="
189
+ onColumnClick(row, column, index, colindex, $event)
190
+ "
191
+ />
192
+
193
+ <td
194
+ v-if="checkable && checkboxPosition === 'right'"
195
+ class="group cursor-pointer pr-3"
196
+ :class="borderBottomClasses(index, row)"
197
+ align="right"
198
+ @click="checkRow(row, index, $event as MouseEvent)"
199
+ >
200
+ <input
201
+ type="checkbox"
202
+ autocomplete="off"
203
+ :disabled="!isRowCheckable(row)"
204
+ :checked="isRowChecked(row)"
205
+ :class="checkboxStyle"
206
+ >
207
+ </td>
208
+ </tr>
209
+
210
+ <transition :name="detailTransition">
211
+ <tr
212
+ v-if="isActiveDetailRow(row)"
213
+ :key="getRowIndex(row, index) + 'detail'"
214
+ >
215
+ <td
216
+ :colspan="columnCount"
217
+ class="td"
218
+ :class="borderBottomDetailClasses(index)"
219
+ >
220
+ <slot
221
+ name="detail"
222
+ :row="row"
223
+ :index="index"
224
+ />
225
+ </td>
226
+ </tr>
227
+ </transition>
228
+ </template>
229
+
230
+ <tr v-if="data.length == 0">
231
+ <td :colspan="columnCount">
232
+ <slot name="empty" />
233
+ </td>
234
+ </tr>
235
+ </tbody>
236
+ </table>
237
+
238
+ <slot name="loading">
239
+ <Transition
240
+ enter-active-class="transition ease-out duration-200"
241
+ enter-from-class="opacity-0"
242
+ enter-to-class="opacity-100"
243
+ leave-active-class="transition ease-in duration-200"
244
+ leave-from-class="opacity-100"
245
+ leave-to-class="opacity-0"
246
+ >
247
+ <div
248
+ v-if="loading"
249
+ class="absolute inset-0 z-[1] flex h-full w-full items-start justify-center"
250
+ >
251
+ <div class="absolute h-full w-full bg-white bg-opacity-60" />
252
+
253
+ <div class="pt-20">
254
+ <BaseSpinnerLarge class="h-10 w-10 text-blue-500" />
255
+ </div>
256
+ </div>
257
+ </Transition>
258
+ </slot>
259
+ </div>
260
+ </div>
261
+ </div>
262
+ </div>
263
+ </div>
264
+ </template>
265
+
266
+ <script lang="ts">
267
+ export default {
268
+ name: 'BaseTable',
269
+ inheritAttrs: false,
270
+ };
271
+ </script>
272
+
273
+ <script lang="ts" setup>
274
+ import { PropType, ref } from 'vue';
275
+ import { BaseTableColumn, Row } from '@/types';
276
+ import SlotComponent from './SlotComponent';
277
+ import { useResizeObserver, useScroll } from '@vueuse/core';
278
+ import { debounce, isArray } from 'lodash';
279
+ import BaseSpinnerLarge from '../svg/BaseSpinnerLarge.vue';
280
+
281
+ const checkboxStyle =
282
+ 'disabled:bg-slate-100 group-hover:shadow-md disabled:border-slate-300 disabled:cursor-not-allowed duration-300 cursor-pointer focus:ring-blue-300 border border-slate-300 shadow h-[18px] w-[18px] rounded';
283
+ const DETAIL_ROW_WIDTH = 36;
284
+ const CHECK_ROW_WIDTH = 36;
285
+
286
+ provide('table', getCurrentInstance());
287
+
288
+ const props = defineProps({
289
+ /** Table data */
290
+ data: {
291
+ type: Array as PropType<Row[]>,
292
+ default: () => [],
293
+ },
294
+ /** Loading state */
295
+ loading: {
296
+ default: false,
297
+ type: Boolean,
298
+ },
299
+ visibleColumns: {
300
+ default: undefined,
301
+ type: Array as PropType<number[]>,
302
+ },
303
+ /** Allow row details */
304
+ detailed: {
305
+ default: false,
306
+ type: Boolean,
307
+ },
308
+ /** Rows can be checked (multiple) */
309
+ checkable: {
310
+ default: false,
311
+ type: Boolean,
312
+ },
313
+ /**
314
+ * Position of the checkbox (if checkable is true)
315
+ * @values left, right
316
+ */
317
+ checkboxPosition: {
318
+ type: String as PropType<'left' | 'right'>,
319
+ default: 'left',
320
+ },
321
+ /** Custom method to verify if a row is checkable, works when is checkable */
322
+ isRowCheckable: {
323
+ type: Function,
324
+ default: () => true,
325
+ },
326
+ /** Set which rows are checked, use v-model:checkedRows to make it two-way binding */
327
+ checkedRows: {
328
+ default: () => [],
329
+ type: Array as PropType<Row[]>,
330
+ },
331
+ /** Sets the default sort column field */
332
+ sortField: {
333
+ type: String,
334
+ default: '',
335
+ },
336
+ /**
337
+ * Sets the default sort column direction
338
+ * @values asc, desc
339
+ */
340
+ sortDirection: {
341
+ type: String,
342
+ default: 'asc',
343
+ },
344
+ /** Controls the visibility of the trigger that toggles the detailed rows. */
345
+ hasDetailedVisible: {
346
+ type: Function,
347
+ default: () => true,
348
+ },
349
+ /** Use a unique key of your data Object when use detailed or opened detailed. (id recommended) */
350
+ rowKey: {
351
+ type: String,
352
+ default: 'id',
353
+ },
354
+ /* Transition name to use when toggling row details. */
355
+ detailTransition: {
356
+ type: String,
357
+ default: '',
358
+ },
359
+ /* Max height (in px) */
360
+ maxHeight: {
361
+ default: undefined,
362
+ type: Number,
363
+ },
364
+ });
365
+
366
+ const emit = defineEmits([
367
+ 'check',
368
+ 'check-all',
369
+ 'update:checkedRows',
370
+ 'details-open',
371
+ 'details-close',
372
+ 'update:openedDetailed',
373
+ 'sort',
374
+ 'cell-click',
375
+ ]);
376
+
377
+ const visibleDetailRows = ref<Row[]>([]);
378
+ const newCheckedRows = ref<Row[]>([...props.checkedRows]);
379
+ const lastCheckedRowIndex = ref<number | null>(null);
380
+ const currentSortColumn = ref<BaseTableColumn | null>(null);
381
+ const isAsc = ref(true);
382
+ const defaultSlots = ref<BaseTableColumn[]>([]);
383
+ const sequence = ref(1);
384
+
385
+ const slot = ref<HTMLElement | null>(null);
386
+ const thead = ref<HTMLElement | null>(null);
387
+ const theadHeight = ref(0);
388
+
389
+ useResizeObserver(thead, () => setTheadHeightDebounce());
390
+
391
+ const setTheadHeightDebounce = debounce(() => {
392
+ setTheadHeight();
393
+ }, 100);
394
+
395
+ function setTheadHeight() {
396
+ if (thead.value) {
397
+ theadHeight.value = thead.value.clientHeight;
398
+ }
399
+ }
400
+
401
+ const newColumns = computed(() => {
402
+ return defaultSlots.value;
403
+ });
404
+
405
+ const visibleColumns = computed(() => {
406
+ if (!newColumns.value) {
407
+ return newColumns.value;
408
+ }
409
+
410
+ return newColumns.value.filter((column: BaseTableColumn) => {
411
+ if (column.toggle === false) {
412
+ return true;
413
+ }
414
+
415
+ if (!isArray(props.visibleColumns)) {
416
+ return true;
417
+ }
418
+
419
+ if (props.visibleColumns.includes(column.newKey)) {
420
+ return true;
421
+ }
422
+
423
+ return false;
424
+ });
425
+ });
426
+
427
+ /**
428
+ * Return total column count based if it's checkable or expanded
429
+ */
430
+ const columnCount = computed(() => {
431
+ let count = visibleColumns.value.length;
432
+ count += props.checkable ? 1 : 0;
433
+ count += props.detailed ? 1 : 0;
434
+
435
+ return count;
436
+ });
437
+
438
+ /**
439
+ * Return if detailed row tabled
440
+ * will be with chevron column & icon or not
441
+ */
442
+ const showDetailRowIcon = computed(() => {
443
+ return props.detailed;
444
+ });
445
+
446
+ /**
447
+ * When checkedRows prop change, update internal value without
448
+ * mutating original data.
449
+ */
450
+ watch(
451
+ () => props.checkedRows,
452
+ (rows) => {
453
+ newCheckedRows.value = [...rows];
454
+ },
455
+ { deep: true }
456
+ );
457
+
458
+ watch(
459
+ () => props.sortField,
460
+ () => {
461
+ updateSortState();
462
+ }
463
+ );
464
+
465
+ watch(
466
+ () => props.sortDirection,
467
+ () => {
468
+ updateSortState();
469
+ }
470
+ );
471
+
472
+ onMounted(() => {
473
+ nextTick(() => {
474
+ updateSortState();
475
+ });
476
+ });
477
+
478
+ /**
479
+ * Sort the column.
480
+ * Toggle current direction on column if it's sortable
481
+ * and not just updating the prop.
482
+ */
483
+ function sort(column: BaseTableColumn, updatingData = false, event = null) {
484
+ if (!column || !column.sortable) {
485
+ return;
486
+ }
487
+
488
+ if (!updatingData) {
489
+ isAsc.value =
490
+ column === currentSortColumn.value
491
+ ? !isAsc.value
492
+ : props.sortDirection.toLowerCase() !== 'desc';
493
+ }
494
+
495
+ /**
496
+ * @property {string} field column field
497
+ * @property {boolean} direction 'asc' or 'desc'
498
+ * @property {Event} event native event
499
+ */
500
+ emit('sort', column.field, isAsc.value ? 'asc' : 'desc', event);
501
+
502
+ currentSortColumn.value = column;
503
+ }
504
+
505
+ /**
506
+ * Check if the row is checked (is added to the array).
507
+ */
508
+ function isRowChecked(row: Row): boolean {
509
+ return (
510
+ newCheckedRows.value.find((r) => r[props.rowKey] == row[props.rowKey]) !==
511
+ undefined
512
+ );
513
+ }
514
+
515
+ /**
516
+ * Check if all rows in the page are checkable.
517
+ */
518
+ const isAllUncheckable = computed(() => {
519
+ const validData = props.data.filter((row) => props.isRowCheckable(row));
520
+ return validData.length === 0;
521
+ });
522
+
523
+ /**
524
+ * Check if all rows in the page are checked.
525
+ */
526
+ const isAllChecked = computed(() => {
527
+ const validData = props.data.filter((row) => {
528
+ return props.isRowCheckable(row);
529
+ });
530
+
531
+ if (validData.length === 0) {
532
+ return false;
533
+ }
534
+
535
+ const missingChecked = validData.some((currentRow) => {
536
+ return !isRowChecked(currentRow);
537
+ });
538
+
539
+ return !missingChecked;
540
+ });
541
+
542
+ function getCheckedRowIndex(row: Row) {
543
+ return newCheckedRows.value.findIndex(
544
+ (r) => r[props.rowKey] == row[props.rowKey]
545
+ );
546
+ }
547
+
548
+ /**
549
+ * Remove a checked row from the array.
550
+ */
551
+ function removeCheckedRow(row: Row) {
552
+ const index = getCheckedRowIndex(row);
553
+ if (index >= 0) {
554
+ newCheckedRows.value.splice(index, 1);
555
+ }
556
+ }
557
+
558
+ /**
559
+ * Header checkbox click listener.
560
+ * Add or remove all rows in current page.
561
+ */
562
+ function checkAll() {
563
+ if (isAllChecked.value) {
564
+ newCheckedRows.value = [];
565
+ } else {
566
+ props.data.forEach((currentRow) => {
567
+ if (props.isRowCheckable(currentRow) && !isRowChecked(currentRow)) {
568
+ newCheckedRows.value.push(currentRow);
569
+ }
570
+ });
571
+ }
572
+
573
+ sendCheckUpdate();
574
+ }
575
+
576
+ /**
577
+ * Remove all rows in current page.
578
+ */
579
+ function uncheckAll() {
580
+ newCheckedRows.value = [];
581
+
582
+ sendCheckUpdate();
583
+ }
584
+
585
+ function sendCheckUpdate() {
586
+ emit('check', newCheckedRows.value);
587
+ emit('check-all', newCheckedRows.value);
588
+ emit('update:checkedRows', newCheckedRows.value);
589
+ }
590
+
591
+ /**
592
+ * Row checkbox click listener.
593
+ */
594
+ function checkRow(row: Row, index: number, event: MouseEvent) {
595
+ if (!props.isRowCheckable(row)) {
596
+ return;
597
+ }
598
+
599
+ const lastIndex = lastCheckedRowIndex.value;
600
+ lastCheckedRowIndex.value = index;
601
+
602
+ if (event.shiftKey && lastIndex !== null && index !== lastIndex) {
603
+ shiftCheckRow(row, index, lastIndex);
604
+ } else if (!isRowChecked(row)) {
605
+ newCheckedRows.value.push(row);
606
+ } else {
607
+ removeCheckedRow(row);
608
+ }
609
+
610
+ emit('check', newCheckedRows.value, row);
611
+
612
+ // Emit checked rows to update user variable
613
+ emit('update:checkedRows', newCheckedRows.value);
614
+ }
615
+
616
+ /**
617
+ * Check row when shift is pressed.
618
+ */
619
+ function shiftCheckRow(row: Row, index: number, lastCheckedRowIndex: number) {
620
+ // Get the subset of the list between the two indices
621
+ const subset = props.data.slice(
622
+ Math.min(index, lastCheckedRowIndex),
623
+ Math.max(index, lastCheckedRowIndex) + 1
624
+ );
625
+
626
+ // Determine the operation based on the state of the clicked checkbox
627
+ const shouldCheck = !isRowChecked(row);
628
+
629
+ subset.forEach((item) => {
630
+ removeCheckedRow(item);
631
+ if (shouldCheck && props.isRowCheckable(item)) {
632
+ newCheckedRows.value.push(item);
633
+ }
634
+ });
635
+ }
636
+
637
+ /**
638
+ * Toggle to show/hide details slot
639
+ */
640
+ function toggleDetails(row: Row) {
641
+ const found = isVisibleDetailRow(row);
642
+
643
+ if (found) {
644
+ closeDetailRow(row);
645
+ emit('details-close', row);
646
+ } else {
647
+ openDetailRow(row);
648
+ emit('details-open', row);
649
+ }
650
+
651
+ // Syncs the detailed rows with the parent component
652
+ emit('update:openedDetailed', visibleDetailRows.value);
653
+ }
654
+
655
+ function openDetailRow(row: Row) {
656
+ const index = getDetailedIndex(row);
657
+ visibleDetailRows.value.push(index);
658
+ }
659
+
660
+ function closeDetailRow(row: Row) {
661
+ const index = getDetailedIndex(row);
662
+ const i = visibleDetailRows.value.indexOf(index);
663
+ if (i >= 0) {
664
+ visibleDetailRows.value.splice(i, 1);
665
+ }
666
+ }
667
+
668
+ function isVisibleDetailRow(row: Row) {
669
+ const index = getDetailedIndex(row);
670
+ return visibleDetailRows.value.indexOf(index) >= 0;
671
+ }
672
+
673
+ function isActiveDetailRow(row: Row) {
674
+ return props.detailed && isVisibleDetailRow(row);
675
+ }
676
+
677
+ /**
678
+ * When the rowKey is defined we use the object[rowKey] as index.
679
+ * If not, use the object reference by default.
680
+ */
681
+ function getDetailedIndex(row: Row) {
682
+ const key = props.rowKey;
683
+ return !key.length || !row ? row : row[key];
684
+ }
685
+
686
+ /**
687
+ * Update sort state
688
+ */
689
+ function updateSortState() {
690
+ const sortField = props.sortField;
691
+
692
+ const sortDirection = props.sortDirection;
693
+
694
+ const sortColumn = newColumns.value.filter(
695
+ (column) => column.field === sortField
696
+ )[0];
697
+
698
+ // Set sort state
699
+
700
+ if (sortColumn) {
701
+ currentSortColumn.value = sortColumn;
702
+ isAsc.value = sortDirection.toLowerCase() !== 'desc';
703
+ } else {
704
+ currentSortColumn.value = null;
705
+ return;
706
+ }
707
+ }
708
+
709
+ /*
710
+ |--------------------------------------------------------------------------
711
+ | BaseTableColumns functions
712
+ |--------------------------------------------------------------------------
713
+ */
714
+
715
+ function addColumn(column: BaseTableColumn) {
716
+ defaultSlots.value.push(column);
717
+
718
+ const slotHTMLElement = slot.value as HTMLElement;
719
+
720
+ if (slotHTMLElement && slotHTMLElement.children) {
721
+ nextTick(() => {
722
+ const ids = defaultSlots.value
723
+ .map((it) => `[data-id="${it.newKey}"]`)
724
+ .join(',');
725
+
726
+ const sortedIds = Array.from(slotHTMLElement.querySelectorAll(ids)).map(
727
+ (el: Element) => el.getAttribute('data-id')
728
+ );
729
+
730
+ defaultSlots.value = defaultSlots.value.sort((a, b) => {
731
+ return (
732
+ sortedIds.indexOf(`${a.newKey}`) - sortedIds.indexOf(`${b.newKey}`)
733
+ );
734
+ });
735
+ });
736
+ }
737
+ }
738
+
739
+ function removeColumn(column: BaseTableColumn) {
740
+ defaultSlots.value = defaultSlots.value.filter(
741
+ (d) => d.newKey !== column.newKey
742
+ );
743
+ }
744
+
745
+ const borderClasses = 'border-b border-slate-200';
746
+
747
+ function borderBottomClasses(index: number, row: Record<string, any>): string {
748
+ if (index < props.data.length - 1) {
749
+ return borderClasses;
750
+ }
751
+
752
+ if (isActiveDetailRow(row)) {
753
+ return borderClasses;
754
+ }
755
+
756
+ return '';
757
+ }
758
+
759
+ function borderBottomDetailClasses(index: number): string {
760
+ if (index < props.data.length - 1) {
761
+ return borderClasses;
762
+ }
763
+
764
+ return '';
765
+ }
766
+
767
+ function onColumnClick(
768
+ row: Row,
769
+ column: BaseTableColumn,
770
+ index: number,
771
+ colindex: number,
772
+ event: MouseEvent
773
+ ) {
774
+ if (column.clickable) {
775
+ emit('cell-click', row, column, index, colindex, event);
776
+ }
777
+ }
778
+
779
+ function nextSequence() {
780
+ return sequence.value++;
781
+ }
782
+
783
+ function getRowIndex(row: Row, index: number): string {
784
+ if (row.id) {
785
+ return row.id;
786
+ }
787
+ if (row.key) {
788
+ return row.key;
789
+ }
790
+ if (row.uuid) {
791
+ return row.uuid;
792
+ }
793
+ return index + '';
794
+ }
795
+
796
+ // Sticky styles
797
+
798
+ const horizontalScrolling = ref(false);
799
+ const scrollable = ref<null | HTMLElement>(null);
800
+
801
+ const { x } = useScroll(scrollable);
802
+ watch(x, (value) => {
803
+ horizontalScrolling.value = value > 0;
804
+ });
805
+
806
+ function zIndex(th: boolean) {
807
+ if (th) {
808
+ return props.maxHeight ? 3 : 2;
809
+ }
810
+ return 1;
811
+ }
812
+
813
+ function detailsStyles(th: boolean): any {
814
+ if (props.detailed) {
815
+ return {
816
+ zIndex: zIndex(th),
817
+ position: 'sticky',
818
+ left: 0,
819
+ width: DETAIL_ROW_WIDTH + 'px',
820
+ minWidth: DETAIL_ROW_WIDTH + 'px',
821
+ maxWidth: DETAIL_ROW_WIDTH + 'px',
822
+ };
823
+ }
824
+ return {};
825
+ }
826
+
827
+ function checkStyles(th: boolean): any {
828
+ if (props.checkable) {
829
+ return {
830
+ zIndex: zIndex(th),
831
+ position: 'sticky',
832
+ left: props.detailed ? DETAIL_ROW_WIDTH + 'px' : 0,
833
+ width: CHECK_ROW_WIDTH + 'px',
834
+ minWidth: CHECK_ROW_WIDTH + 'px',
835
+ maxWidth: CHECK_ROW_WIDTH + 'px',
836
+ };
837
+ }
838
+ return {};
839
+ }
840
+
841
+ function firstColStyles(th: boolean): any {
842
+ let left = 0;
843
+ if (props.checkable) {
844
+ left += CHECK_ROW_WIDTH;
845
+ }
846
+ if (props.detailed) {
847
+ left += DETAIL_ROW_WIDTH;
848
+ }
849
+ return {
850
+ zIndex: zIndex(th) + 1,
851
+ position: 'sticky',
852
+ left: left + 'px',
853
+ borderRight: horizontalScrolling.value ? '1px solid #e2e8f0' : 'none',
854
+ };
855
+ }
856
+
857
+ function scrollTop() {
858
+ if (scrollable.value) {
859
+ scrollable.value.scrollTo({ top: 0, behavior: 'smooth' });
860
+ }
861
+ }
862
+
863
+ provide('addColumn', addColumn);
864
+ provide('removeColumn', removeColumn);
865
+ provide('nextSequence', nextSequence);
866
+
867
+ defineExpose({
868
+ newColumns,
869
+ uncheckAll,
870
+ scrollTop,
871
+ });
872
+ </script>
873
+
874
+ <style lang="postcss" scoped>
875
+ .th {
876
+ @apply relative z-[2];
877
+ @apply bg-slate-50;
878
+ @apply border-b border-slate-300;
879
+ }
880
+
881
+ .base-table--has-max-height .th {
882
+ @apply sticky;
883
+ @apply top-0;
884
+ @apply bg-opacity-75 backdrop-blur backdrop-filter;
885
+ }
886
+
887
+ tbody tr.item-row:hover td {
888
+ @apply bg-slate-50;
889
+ }
890
+ </style>