sprintify-ui 0.4.5 → 0.4.7

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