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,839 +1,839 @@
1
- <template>
2
- <div ref="dataIteratorNode">
3
- <div
4
- class="grid w-full max-w-full grid-flow-row gap-4"
5
- :class="{
6
- 'grid-cols-[1fr_300px]': hasSidebar,
7
- }"
8
- >
9
- <div
10
- class="min-w-0"
11
- :class="{ 'col-span-1': !compactLayout, 'col-span-2': compactLayout }"
12
- >
13
- <!-- Header -->
14
- <div
15
- class="flex space-x-2 empty:mb-0"
16
- :class="{
17
- 'mb-2.5': size == 'sm',
18
- 'mb-4': size == 'md',
19
- }"
20
- >
21
- <!-- Search bar -->
22
- <div
23
- v-if="searchable"
24
- class="grow"
25
- >
26
- <div
27
- class="relative"
28
- :class="{
29
- 'h-9': size == 'sm',
30
- 'h-11': size == 'md',
31
- }"
32
- >
33
- <div
34
- class="pointer-events-none absolute left-0 top-0 flex h-full items-center justify-center pl-2.5"
35
- >
36
- <BaseIcon
37
- class="text-slate-400"
38
- :class="{
39
- 'h-5 w-5': size == 'sm',
40
- 'h-6 w-6': size == 'md',
41
- }"
42
- icon="heroicons:magnifying-glass"
43
- />
44
- </div>
45
- <input
46
- ref="searchInput"
47
- v-model="searchQuery"
48
- type="text"
49
- class="w-full h-full py-0 overflow-hidden rounded-md border border-slate-300 bg-white shadow-sm placeholder:font-light placeholder:text-sm focus:ring-blue-300 focus:ring-4"
50
- :class="{
51
- 'pl-9 pr-8': size == 'sm',
52
- 'pl-10 pr-9': size == 'md',
53
- }"
54
- :placeholder="t('sui.autocomplete_placeholder')"
55
- @input="onSearch"
56
- >
57
- <div
58
- v-if="searchQuery"
59
- class="absolute right-0 top-0 flex h-full items-center justify-center p-1"
60
- >
61
- <button
62
- type="button"
63
- class="flex appearance-none items-center rounded p-1 hover:bg-slate-100"
64
- @click="searchQuery = ''; onSearch('');"
65
- >
66
- <BaseIcon
67
- class="text-slate-500"
68
- :class="{
69
- 'h-5 w-5': size == 'sm',
70
- 'h-6 w-6': size == 'md',
71
- }"
72
- icon="heroicons:x-mark"
73
- />
74
- </button>
75
- </div>
76
- </div>
77
- </div>
78
-
79
- <template v-if="compactLayout">
80
- <template
81
- v-for="(section, i) in sectionsInternal"
82
- :key="section.name"
83
- >
84
- <BaseDataIteratorSectionButton
85
- :section="section"
86
- :size="size"
87
- @open="openSection(i)"
88
- />
89
- </template>
90
- </template>
91
-
92
- <!-- Menu -->
93
- <BaseMenu
94
- v-if="actions && actions.length"
95
- tw-menu="w-52"
96
- :size="size == 'sm' ? 'xs' : 'sm'"
97
- :items="actions"
98
- >
99
- <template #button="{ open }">
100
- <div
101
- class="flex items-center justify-center rounded-md border border-slate-300 bg-white shadow-sm duration-150 hover:bg-slate-50"
102
- :class="[
103
- open ? 'ring-2 ring-primary-500 ring-offset-2' : false,
104
- {
105
- 'h-9 w-9': size == 'sm',
106
- 'h-11 w-11': size == 'md',
107
- }
108
- ]"
109
- >
110
- <BaseIcon icon="heroicons-solid:dots-vertical" />
111
- </div>
112
- </template>
113
- </BaseMenu>
114
- </div>
115
-
116
- <slot
117
- :items="items"
118
- :loading="loading"
119
- :error="error"
120
- :first-load="firstLoad"
121
- :page="page"
122
- :sort-field="sortField"
123
- :sort-direction="sortDirection"
124
- :on-sort-change="onSortChange"
125
- :on-page-change="onPageChange"
126
- />
127
-
128
- <!-- Pagination -->
129
-
130
- <div
131
- v-if="paginationMetadata"
132
- class="mt-4"
133
- >
134
- <p
135
- class="text-center text-sm text-slate-500 sm:text-right [&>b]:font-medium [&>b]:text-slate-600"
136
- >
137
- {{ t('sui.pagination_detail_1') }}
138
-
139
- <b>{{ paginationStart }}</b> - <b>{{ paginationEnd }}</b>
140
-
141
- {{ t('sui.pagination_detail_2') }}
142
-
143
- <b>{{ paginationMetadata.total }}</b>
144
- </p>
145
- </div>
146
-
147
- <div
148
- v-if="paginationMetadata"
149
- class="mt-4"
150
- >
151
- <BasePagination
152
- :model-value="page"
153
- :last-page="lastPage"
154
- @update:model-value="onPageChange"
155
- />
156
- </div>
157
- </div>
158
-
159
- <div
160
- v-if="!compactLayout"
161
- ref="sidebar"
162
- class="space-y-3"
163
- >
164
- <slot
165
- name="sidebarTop"
166
- :pagination-metadata="paginationMetadata"
167
- />
168
-
169
- <template
170
- v-for="section in sectionsInternal"
171
- :key="section.name"
172
- >
173
- <BaseDataIteratorSectionBox :section="section">
174
- <slot
175
- :name="section.name"
176
- :query="query"
177
- :update-query="updateFilterQuery"
178
- :update-query-value="updateFilterQueryValue"
179
- />
180
- </BaseDataIteratorSectionBox>
181
- </template>
182
-
183
- <slot
184
- name="sidebarBottom"
185
- :pagination-metadata="paginationMetadata"
186
- />
187
- </div>
188
- </div>
189
-
190
- <template
191
- v-for="(section, i) in sectionsInternal"
192
- :key="section.name"
193
- >
194
- <BaseDataIteratorSectionModal
195
- :section="section"
196
- :model-value="sectionModalActive == i"
197
- @update:model-value="closeSection"
198
- >
199
- <slot
200
- :name="section.name"
201
- :query="query"
202
- :update-query="updateFilterQuery"
203
- :update-query-value="updateFilterQueryValue"
204
- />
205
- </BaseDataIteratorSectionModal>
206
- </template>
207
- </div>
208
- </template>
209
-
210
- <script lang="ts">
211
- /* eslint-disable @typescript-eslint/no-explicit-any */
212
- import { t } from '@/i18n';
213
- type Direction = 'asc' | 'desc';
214
-
215
- const DEFAULT_QUERY = {
216
- page: 1,
217
- search: '',
218
- sort: '',
219
- filter: {},
220
- } as DataTableQuery;
221
- </script>
222
-
223
- <script lang="ts" setup>
224
- import { cloneDeep, debounce, merge, set } from 'lodash';
225
- import hash from 'object-hash';
226
- import { PropType } from 'vue';
227
- import {
228
- Collection,
229
- DataIteratorSection,
230
- DataTableQuery,
231
- MenuItemInterface,
232
- PaginatedCollection,
233
- ResourceCollection,
234
- } from '@/types';
235
-
236
- import BaseMenu from './BaseMenu.vue';
237
- import BasePagination from './BasePagination.vue';
238
- import { config } from '@/index';
239
- import { useMutationObserver, useResizeObserver } from '@vueuse/core';
240
- import { useHasPaginatedData } from '@/composables/paginatedData';
241
- import BaseDataIteratorSectionButton from './BaseDataIteratorSectionButton.vue';
242
- import BaseDataIteratorSectionModal from './BaseDataIteratorSectionModal.vue';
243
- import BaseDataIteratorSectionBox from './BaseDataIteratorSectionBox.vue';
244
-
245
- const props = defineProps({
246
- /**
247
- * Base URL from which to make requests
248
- */
249
- url: {
250
- required: true,
251
- type: String,
252
- },
253
-
254
- /**
255
- * Query params that always get applied.
256
- * To add overwrite-able query params, use defaultQuery.
257
- */
258
- urlQuery: {
259
- default: undefined,
260
- type: Object as PropType<Record<string, any>>,
261
- },
262
-
263
- /**
264
- * Query params that gets applied by default.
265
- * These may be overwritten by URL params generated by the data-table or filters
266
- * To add query params that are always active, use urlQuery.
267
- */
268
- defaultQuery: {
269
- default: function () {
270
- return DEFAULT_QUERY;
271
- },
272
- type: Object as PropType<DataTableQuery>,
273
- },
274
-
275
- /**
276
- * Add a search bar.
277
- */
278
- searchable: {
279
- default: true,
280
- type: Boolean,
281
- },
282
-
283
- /**
284
- * Configure contextual actions.
285
- */
286
- actions: {
287
- default: undefined,
288
- type: Array as PropType<MenuItemInterface[]>,
289
- },
290
-
291
- /**
292
- * Save data table state in URL.
293
- */
294
- historyMode: {
295
- default: false,
296
- type: Boolean,
297
- },
298
-
299
- /**
300
- * Layout type
301
- */
302
- layout: {
303
- default: 'default',
304
- type: String as PropType<'default' | 'compact'>,
305
- },
306
-
307
- /**
308
- * Overall size and spacing of the component
309
- */
310
- size: {
311
- default: 'md',
312
- type: String as PropType<'sm' | 'md'>,
313
- },
314
-
315
- /**
316
- * Sections
317
- */
318
- sections: {
319
- default: undefined,
320
- type: Array as PropType<DataIteratorSection[]>,
321
- },
322
-
323
- /**
324
- * Scroll to top when fetching new data
325
- */
326
- scrollTopOnFetch: {
327
- default: true,
328
- type: Boolean,
329
- },
330
- });
331
-
332
- const http = config.http;
333
-
334
- const emit = defineEmits([
335
- 'click',
336
- 'delete',
337
- 'checkAll',
338
- 'update:checked-rows',
339
- 'check',
340
- 'update:query',
341
- 'will-scroll-top',
342
- 'fetch',
343
- ]);
344
-
345
- const dataIteratorNode = ref<null | HTMLElement>(null);
346
- const searchInput = ref<null | HTMLInputElement>(null);
347
-
348
- const route = useRoute();
349
- const router = useRouter();
350
- const routeName = route.name;
351
-
352
- let willUnmount = false;
353
-
354
- onBeforeUnmount(() => {
355
- willUnmount = true;
356
- });
357
-
358
- const width = ref(800);
359
- useResizeObserver(dataIteratorNode, () => {
360
- width.value = dataIteratorNode.value?.clientWidth ?? 800;
361
- });
362
-
363
- /** Data table state */
364
-
365
- const firstLoad = ref(false);
366
- const loading = ref(true);
367
- const error = ref(false);
368
- const searchQuery = ref('');
369
-
370
- let lastUrl = '';
371
- let lastQueryHash = '';
372
-
373
- // eslint-disable-next-line vue/no-setup-props-destructure
374
- const query = ref<DataTableQuery>(cloneDeep(props.defaultQuery));
375
- const slots = useSlots();
376
-
377
- const compactLayout = computed(() => {
378
- if (props.layout === 'compact') {
379
- return true;
380
- }
381
- return width.value < 1024;
382
- });
383
-
384
- const hasFilters = computed((): boolean => {
385
- const numberOfFilterSlots = slots.filters;
386
- return numberOfFilterSlots !== undefined;
387
- });
388
-
389
- /*
390
- |--------------------------------------------------------------------------
391
- | Has sidebar observer
392
- |--------------------------------------------------------------------------
393
- */
394
-
395
- const hasSidebar = ref(false);
396
- const sidebar = ref<null | HTMLElement>(null);
397
-
398
- function checkIfSidebarIsEmpty() {
399
- hasSidebar.value = (sidebar?.value?.childElementCount ?? 0) > 0;
400
- }
401
-
402
- const checkIfSidebarIsEmptyDebounce = debounce(checkIfSidebarIsEmpty, 100);
403
-
404
- useMutationObserver(sidebar, checkIfSidebarIsEmptyDebounce, {
405
- attributes: false,
406
- childList: true,
407
- });
408
-
409
- onMounted(() => {
410
- checkIfSidebarIsEmpty();
411
- });
412
-
413
- watch(
414
- () => compactLayout.value,
415
- () => {
416
- // After the sidebar appears...
417
- nextTick(() => {
418
- checkIfSidebarIsEmpty();
419
- });
420
- }
421
- );
422
-
423
- /*
424
- |--------------------------------------------------------------------------
425
- | Query params
426
- |--------------------------------------------------------------------------
427
- */
428
-
429
- function updateFilterQueryValue(key: string, value: any) {
430
- let newQuery = cloneDeep(query.value);
431
- newQuery = set(newQuery, key, value);
432
- newQuery = set(newQuery, 'page', 1);
433
- updateQuery(newQuery);
434
- }
435
-
436
- function updateFilterQuery(newQuery: DataTableQuery) {
437
- newQuery = set(newQuery, 'page', 1);
438
- updateQuery(newQuery);
439
- }
440
-
441
- function updateQuery(newQuery: DataTableQuery) {
442
- if (!props.historyMode) {
443
- query.value = newQuery;
444
- fetch();
445
- return;
446
- }
447
-
448
- if (route.name === null) {
449
- throw new Error('Route name is required for history mode');
450
- }
451
-
452
- const newRoute = router.resolve({
453
- name: route.name,
454
- params: route.params,
455
- });
456
-
457
- const newParams = config.formatQueryString(newQuery);
458
- const newRoutePath = newRoute.fullPath + '?' + newParams;
459
-
460
- const oldParamString = getRouteQuery();
461
- const oldParams = config.formatQueryString(oldParamString);
462
-
463
- // Push new route if different
464
- if (oldParams != newParams) {
465
- if (!firstLoad.value) {
466
- router.replace(newRoutePath);
467
- return;
468
- }
469
- router.push(newRoutePath);
470
- return;
471
- }
472
-
473
- // If the URL is unchanged, we must manually trigger the fetch() method
474
- // on first load.
475
-
476
- if (!firstLoad.value) {
477
- query.value = newQuery;
478
- fetch();
479
- }
480
- }
481
-
482
- function queryHash(query: DataTableQuery): string {
483
- return hash(query);
484
- }
485
-
486
- /*
487
- |--------------------------------------------------------------------------
488
- | Data fetching
489
- |--------------------------------------------------------------------------
490
- */
491
-
492
- const url = computed<string>(() => {
493
- return props.url;
494
- });
495
-
496
- /*
497
- |--------------------------------------------------------------------------
498
- | Handlers
499
- |--------------------------------------------------------------------------
500
- */
501
-
502
- function onPageChange(p: number) {
503
- const newQuery = cloneDeep(query.value);
504
-
505
- newQuery.page = p;
506
-
507
- updateQuery(newQuery);
508
-
509
- scrollIntoView();
510
- }
511
-
512
- function onSortChange(field: string, direction: Direction) {
513
- let newSort = field;
514
-
515
- if (newSort && direction == 'desc') {
516
- newSort = '-' + newSort;
517
- }
518
-
519
- const newQuery = cloneDeep(query.value);
520
-
521
- newQuery.page = 1;
522
- newQuery.sort = newSort;
523
-
524
- updateQuery(newQuery);
525
- }
526
-
527
- const onSearch = debounce((event: any) => {
528
- const newQuery = cloneDeep(query.value);
529
-
530
- newQuery.page = 1;
531
- newQuery.search = searchQuery.value;
532
-
533
- updateQuery(newQuery);
534
- }, 350);
535
-
536
- /*
537
- |--------------------------------------------------------------------------
538
- | Route watcher
539
- |--------------------------------------------------------------------------
540
- */
541
-
542
- watch(
543
- () => route.query,
544
- () => {
545
- // Wait for the willUnmount flag to be set
546
- nextTick(() => {
547
- onRouteChange();
548
- });
549
- }
550
- );
551
-
552
- watch(
553
- () => props.url,
554
- () => {
555
- fetch();
556
- }
557
- );
558
-
559
- watch(
560
- () => props.urlQuery,
561
- () => {
562
- fetch();
563
- }
564
- );
565
-
566
- function getRouteQuery() {
567
- return config.parseQueryString(window.location.search.replace(/^(\?)/, ''));
568
- }
569
-
570
- function onRouteChange() {
571
- if (!props.historyMode) {
572
- return;
573
- }
574
-
575
- if (willUnmount) {
576
- return;
577
- }
578
-
579
- // Stop if route was changed
580
- if (route.name != routeName) {
581
- return;
582
- }
583
-
584
- const routeQuery = getRouteQuery();
585
- const newQuery = routeQuery as DataTableQuery;
586
-
587
- const newQueryHash = queryHash(newQuery);
588
-
589
- if (newQueryHash == lastQueryHash) {
590
- return;
591
- }
592
-
593
- lastQueryHash = newQueryHash;
594
-
595
- query.value = newQuery;
596
-
597
- // Update search input if not in focus
598
- if (searchInput.value && searchInput.value !== document.activeElement) {
599
- updateSearchInput();
600
- }
601
-
602
- fetch();
603
- }
604
-
605
- /*
606
- |--------------------------------------------------------------------------
607
- | Fetch
608
- |--------------------------------------------------------------------------
609
- */
610
-
611
- function fetchWithLoading(force = false) {
612
- fetch(force, true);
613
- }
614
-
615
- function fetchWithoutLoading(force = false) {
616
- fetch(force, false);
617
- }
618
-
619
- function fetch(force = false, showLoading = true) {
620
- if (willUnmount) {
621
- return;
622
- }
623
-
624
- const urlSplit = url.value.split(/[?#]/);
625
-
626
- const baseUrl = urlSplit[0];
627
- const urlQueryString = urlSplit[1] ?? null;
628
- const urlQuery = config.parseQueryString(urlQueryString);
629
-
630
- // Ordered by priority
631
- const allParams = merge(
632
- cloneDeep(query.value),
633
- cloneDeep(props.urlQuery),
634
- cloneDeep(urlQuery)
635
- );
636
-
637
- const queryString = config.formatQueryString(allParams);
638
-
639
- const fullUrl = baseUrl + '?' + queryString;
640
-
641
- if (lastUrl == fullUrl && !force) {
642
- return;
643
- }
644
-
645
- if (showLoading) {
646
- loading.value = true;
647
- }
648
-
649
- lastUrl = fullUrl;
650
-
651
- http
652
- .get(fullUrl)
653
- .then((response) => {
654
- data.value = response.data;
655
- loading.value = false;
656
- error.value = false;
657
- firstLoad.value = true;
658
- emit('fetch', data.value);
659
- })
660
- .catch(() => {
661
- data.value = null;
662
- loading.value = false;
663
- error.value = true;
664
- })
665
- .finally(() => {
666
- loading.value = false;
667
- });
668
- }
669
-
670
- /*
671
- |--------------------------------------------------------------------------
672
- | Data parsing
673
- |--------------------------------------------------------------------------
674
- */
675
-
676
- const data = ref<null | ResourceCollection | PaginatedCollection | Collection>(
677
- null
678
- );
679
-
680
- const { items, paginationMetadata, lastPage } = useHasPaginatedData(data);
681
-
682
- const page = computed((): number => {
683
- if (query.value.page && parseInt(query.value.page + '')) {
684
- return parseInt(query.value.page + '');
685
- }
686
- return 1;
687
- });
688
-
689
- const sortField = computed((): string => {
690
- return query.value.sort?.trim().replace(/^(-)/, '') ?? '';
691
- });
692
-
693
- const sortDirection = computed((): Direction => {
694
- if (query.value.sort && query.value.sort.length) {
695
- if (query.value.sort[0] == '-') {
696
- return 'desc';
697
- }
698
- }
699
- return 'asc';
700
- });
701
-
702
- const searchKeywords = computed((): string => {
703
- return query.value.search ?? '';
704
- });
705
-
706
- /*
707
- |--------------------------------------------------------------------------
708
- | Helpers
709
- |--------------------------------------------------------------------------
710
- */
711
-
712
- /** Scroll into view */
713
-
714
- const scrollIntoView = () => {
715
- emit('will-scroll-top');
716
-
717
- if (!props.scrollTopOnFetch) {
718
- return;
719
- }
720
-
721
- scrollIntoViewAction();
722
- };
723
-
724
- const scrollIntoViewAction = () => {
725
- if (dataIteratorNode.value == null) {
726
- return;
727
- }
728
-
729
- dataIteratorNode.value.scrollIntoView({
730
- behavior: 'smooth',
731
- });
732
- };
733
-
734
- function updateSearchInput() {
735
- searchQuery.value = searchKeywords.value;
736
- }
737
-
738
- const paginationStart = computed(() => {
739
- if (paginationMetadata.value == null) {
740
- return '';
741
- }
742
-
743
- return (
744
- paginationMetadata.value.per_page *
745
- (paginationMetadata.value.current_page - 1) +
746
- 1
747
- );
748
- });
749
-
750
- const paginationEnd = computed(() => {
751
- if (paginationMetadata.value == null) {
752
- return '';
753
- }
754
-
755
- return Math.min(
756
- paginationMetadata.value.current_page * paginationMetadata.value.per_page,
757
- paginationMetadata.value.total
758
- );
759
- });
760
-
761
- /*
762
- |--------------------------------------------------------------------------
763
- | Created
764
- |--------------------------------------------------------------------------
765
- */
766
-
767
- let newQuery = cloneDeep(query.value);
768
- const routeQuery = getRouteQuery();
769
-
770
- newQuery = merge(newQuery, routeQuery);
771
-
772
- updateQuery(newQuery);
773
-
774
- // Update search input on first load
775
- onMounted(() => {
776
- updateSearchInput();
777
- });
778
-
779
- /*
780
- |--------------------------------------------------------------------------
781
- | Sections
782
- |--------------------------------------------------------------------------
783
- */
784
-
785
- const sectionModalActive = ref<null | number>(null);
786
-
787
- const sectionsInternal = computed<DataIteratorSection[]>(() => {
788
- const sections = props.sections ?? [];
789
-
790
- if (hasFilters.value) {
791
- return [
792
- {
793
- name: 'filters',
794
- title: t('sui.filters'),
795
- closeText: t('sui.apply_filters'),
796
- icon: 'heroicons:funnel',
797
- opened: true,
798
- },
799
- ...sections,
800
- ];
801
- }
802
-
803
- return sections;
804
- });
805
-
806
- function openSection(index: number) {
807
- if (sectionsInternal.value[index]) {
808
- sectionModalActive.value = index;
809
- } else {
810
- sectionModalActive.value = null;
811
- }
812
- }
813
-
814
- function closeSection() {
815
- sectionModalActive.value = null;
816
- }
817
-
818
- /*
819
- |--------------------------------------------------------------------------
820
- | Provide
821
- |--------------------------------------------------------------------------
822
- */
823
-
824
- provide('dataIterator:width', width);
825
-
826
- /*
827
- |--------------------------------------------------------------------------
828
- | Exposed API
829
- |--------------------------------------------------------------------------
830
- */
831
-
832
- defineExpose({
833
- fetch: () => fetch(true),
834
- fetchWithLoading: () => fetchWithLoading(true),
835
- fetchWithoutLoading: () => fetchWithoutLoading(true),
836
- scrollIntoView: scrollIntoViewAction,
837
- query,
838
- });
839
- </script>
1
+ <template>
2
+ <div ref="dataIteratorNode">
3
+ <div
4
+ class="grid w-full max-w-full grid-flow-row gap-4"
5
+ :class="{
6
+ 'grid-cols-[1fr_300px]': hasSidebar,
7
+ }"
8
+ >
9
+ <div
10
+ class="min-w-0"
11
+ :class="{ 'col-span-1': !compactLayout, 'col-span-2': compactLayout }"
12
+ >
13
+ <!-- Header -->
14
+ <div
15
+ class="flex space-x-2 empty:mb-0"
16
+ :class="{
17
+ 'mb-2.5': size == 'sm',
18
+ 'mb-4': size == 'md',
19
+ }"
20
+ >
21
+ <!-- Search bar -->
22
+ <div
23
+ v-if="searchable"
24
+ class="grow"
25
+ >
26
+ <div
27
+ class="relative"
28
+ :class="{
29
+ 'h-9': size == 'sm',
30
+ 'h-11': size == 'md',
31
+ }"
32
+ >
33
+ <div
34
+ class="pointer-events-none absolute left-0 top-0 flex h-full items-center justify-center pl-2.5"
35
+ >
36
+ <BaseIcon
37
+ class="text-slate-400"
38
+ :class="{
39
+ 'h-5 w-5': size == 'sm',
40
+ 'h-6 w-6': size == 'md',
41
+ }"
42
+ icon="heroicons:magnifying-glass"
43
+ />
44
+ </div>
45
+ <input
46
+ ref="searchInput"
47
+ v-model="searchQuery"
48
+ type="text"
49
+ class="w-full h-full py-0 overflow-hidden rounded-md border border-slate-300 bg-white shadow-sm placeholder:font-light placeholder:text-sm focus:ring-blue-300 focus:ring-4"
50
+ :class="{
51
+ 'pl-9 pr-8': size == 'sm',
52
+ 'pl-10 pr-9': size == 'md',
53
+ }"
54
+ :placeholder="t('sui.autocomplete_placeholder')"
55
+ @input="onSearch"
56
+ >
57
+ <div
58
+ v-if="searchQuery"
59
+ class="absolute right-0 top-0 flex h-full items-center justify-center p-1"
60
+ >
61
+ <button
62
+ type="button"
63
+ class="flex appearance-none items-center rounded p-1 hover:bg-slate-100"
64
+ @click="searchQuery = ''; onSearch('');"
65
+ >
66
+ <BaseIcon
67
+ class="text-slate-500"
68
+ :class="{
69
+ 'h-5 w-5': size == 'sm',
70
+ 'h-6 w-6': size == 'md',
71
+ }"
72
+ icon="heroicons:x-mark"
73
+ />
74
+ </button>
75
+ </div>
76
+ </div>
77
+ </div>
78
+
79
+ <template v-if="compactLayout">
80
+ <template
81
+ v-for="(section, i) in sectionsInternal"
82
+ :key="section.name"
83
+ >
84
+ <BaseDataIteratorSectionButton
85
+ :section="section"
86
+ :size="size"
87
+ @open="openSection(i)"
88
+ />
89
+ </template>
90
+ </template>
91
+
92
+ <!-- Menu -->
93
+ <BaseMenu
94
+ v-if="actions && actions.length"
95
+ tw-menu="w-52"
96
+ :size="size == 'sm' ? 'xs' : 'sm'"
97
+ :items="actions"
98
+ >
99
+ <template #button="{ open }">
100
+ <div
101
+ class="flex items-center justify-center rounded-md border border-slate-300 bg-white shadow-sm duration-150 hover:bg-slate-50"
102
+ :class="[
103
+ open ? 'ring-2 ring-primary-500 ring-offset-2' : false,
104
+ {
105
+ 'h-9 w-9': size == 'sm',
106
+ 'h-11 w-11': size == 'md',
107
+ }
108
+ ]"
109
+ >
110
+ <BaseIcon icon="heroicons-solid:dots-vertical" />
111
+ </div>
112
+ </template>
113
+ </BaseMenu>
114
+ </div>
115
+
116
+ <slot
117
+ :items="items"
118
+ :loading="loading"
119
+ :error="error"
120
+ :first-load="firstLoad"
121
+ :page="page"
122
+ :sort-field="sortField"
123
+ :sort-direction="sortDirection"
124
+ :on-sort-change="onSortChange"
125
+ :on-page-change="onPageChange"
126
+ />
127
+
128
+ <!-- Pagination -->
129
+
130
+ <div
131
+ v-if="paginationMetadata"
132
+ class="mt-4"
133
+ >
134
+ <p
135
+ class="text-center text-sm text-slate-500 sm:text-right [&>b]:font-medium [&>b]:text-slate-600"
136
+ >
137
+ {{ t('sui.pagination_detail_1') }}
138
+
139
+ <b>{{ paginationStart }}</b> - <b>{{ paginationEnd }}</b>
140
+
141
+ {{ t('sui.pagination_detail_2') }}
142
+
143
+ <b>{{ paginationMetadata.total }}</b>
144
+ </p>
145
+ </div>
146
+
147
+ <div
148
+ v-if="paginationMetadata"
149
+ class="mt-4"
150
+ >
151
+ <BasePagination
152
+ :model-value="page"
153
+ :last-page="lastPage"
154
+ @update:model-value="onPageChange"
155
+ />
156
+ </div>
157
+ </div>
158
+
159
+ <div
160
+ v-if="!compactLayout"
161
+ ref="sidebar"
162
+ class="space-y-3"
163
+ >
164
+ <slot
165
+ name="sidebarTop"
166
+ :pagination-metadata="paginationMetadata"
167
+ />
168
+
169
+ <template
170
+ v-for="section in sectionsInternal"
171
+ :key="section.name"
172
+ >
173
+ <BaseDataIteratorSectionBox :section="section">
174
+ <slot
175
+ :name="section.name"
176
+ :query="query"
177
+ :update-query="updateFilterQuery"
178
+ :update-query-value="updateFilterQueryValue"
179
+ />
180
+ </BaseDataIteratorSectionBox>
181
+ </template>
182
+
183
+ <slot
184
+ name="sidebarBottom"
185
+ :pagination-metadata="paginationMetadata"
186
+ />
187
+ </div>
188
+ </div>
189
+
190
+ <template
191
+ v-for="(section, i) in sectionsInternal"
192
+ :key="section.name"
193
+ >
194
+ <BaseDataIteratorSectionModal
195
+ :section="section"
196
+ :model-value="sectionModalActive == i"
197
+ @update:model-value="closeSection"
198
+ >
199
+ <slot
200
+ :name="section.name"
201
+ :query="query"
202
+ :update-query="updateFilterQuery"
203
+ :update-query-value="updateFilterQueryValue"
204
+ />
205
+ </BaseDataIteratorSectionModal>
206
+ </template>
207
+ </div>
208
+ </template>
209
+
210
+ <script lang="ts">
211
+ /* eslint-disable @typescript-eslint/no-explicit-any */
212
+ import { t } from '@/i18n';
213
+ type Direction = 'asc' | 'desc';
214
+
215
+ const DEFAULT_QUERY = {
216
+ page: 1,
217
+ search: '',
218
+ sort: '',
219
+ filter: {},
220
+ } as DataTableQuery;
221
+ </script>
222
+
223
+ <script lang="ts" setup>
224
+ import { cloneDeep, debounce, merge, set } from 'lodash';
225
+ import hash from 'object-hash';
226
+ import { PropType } from 'vue';
227
+ import {
228
+ Collection,
229
+ DataIteratorSection,
230
+ DataTableQuery,
231
+ MenuItemInterface,
232
+ PaginatedCollection,
233
+ ResourceCollection,
234
+ } from '@/types';
235
+
236
+ import BaseMenu from './BaseMenu.vue';
237
+ import BasePagination from './BasePagination.vue';
238
+ import { config } from '@/index';
239
+ import { useMutationObserver, useResizeObserver } from '@vueuse/core';
240
+ import { useHasPaginatedData } from '@/composables/paginatedData';
241
+ import BaseDataIteratorSectionButton from './BaseDataIteratorSectionButton.vue';
242
+ import BaseDataIteratorSectionModal from './BaseDataIteratorSectionModal.vue';
243
+ import BaseDataIteratorSectionBox from './BaseDataIteratorSectionBox.vue';
244
+
245
+ const props = defineProps({
246
+ /**
247
+ * Base URL from which to make requests
248
+ */
249
+ url: {
250
+ required: true,
251
+ type: String,
252
+ },
253
+
254
+ /**
255
+ * Query params that always get applied.
256
+ * To add overwrite-able query params, use defaultQuery.
257
+ */
258
+ urlQuery: {
259
+ default: undefined,
260
+ type: Object as PropType<Record<string, any>>,
261
+ },
262
+
263
+ /**
264
+ * Query params that gets applied by default.
265
+ * These may be overwritten by URL params generated by the data-table or filters
266
+ * To add query params that are always active, use urlQuery.
267
+ */
268
+ defaultQuery: {
269
+ default: function () {
270
+ return DEFAULT_QUERY;
271
+ },
272
+ type: Object as PropType<DataTableQuery>,
273
+ },
274
+
275
+ /**
276
+ * Add a search bar.
277
+ */
278
+ searchable: {
279
+ default: true,
280
+ type: Boolean,
281
+ },
282
+
283
+ /**
284
+ * Configure contextual actions.
285
+ */
286
+ actions: {
287
+ default: undefined,
288
+ type: Array as PropType<MenuItemInterface[]>,
289
+ },
290
+
291
+ /**
292
+ * Save data table state in URL.
293
+ */
294
+ historyMode: {
295
+ default: false,
296
+ type: Boolean,
297
+ },
298
+
299
+ /**
300
+ * Layout type
301
+ */
302
+ layout: {
303
+ default: 'default',
304
+ type: String as PropType<'default' | 'compact'>,
305
+ },
306
+
307
+ /**
308
+ * Overall size and spacing of the component
309
+ */
310
+ size: {
311
+ default: 'md',
312
+ type: String as PropType<'sm' | 'md'>,
313
+ },
314
+
315
+ /**
316
+ * Sections
317
+ */
318
+ sections: {
319
+ default: undefined,
320
+ type: Array as PropType<DataIteratorSection[]>,
321
+ },
322
+
323
+ /**
324
+ * Scroll to top when fetching new data
325
+ */
326
+ scrollTopOnFetch: {
327
+ default: true,
328
+ type: Boolean,
329
+ },
330
+ });
331
+
332
+ const http = config.http;
333
+
334
+ const emit = defineEmits([
335
+ 'click',
336
+ 'delete',
337
+ 'checkAll',
338
+ 'update:checked-rows',
339
+ 'check',
340
+ 'update:query',
341
+ 'will-scroll-top',
342
+ 'fetch',
343
+ ]);
344
+
345
+ const dataIteratorNode = ref<null | HTMLElement>(null);
346
+ const searchInput = ref<null | HTMLInputElement>(null);
347
+
348
+ const route = useRoute();
349
+ const router = useRouter();
350
+ const routeName = route.name;
351
+
352
+ let willUnmount = false;
353
+
354
+ onBeforeUnmount(() => {
355
+ willUnmount = true;
356
+ });
357
+
358
+ const width = ref(800);
359
+ useResizeObserver(dataIteratorNode, () => {
360
+ width.value = dataIteratorNode.value?.clientWidth ?? 800;
361
+ });
362
+
363
+ /** Data table state */
364
+
365
+ const firstLoad = ref(false);
366
+ const loading = ref(true);
367
+ const error = ref(false);
368
+ const searchQuery = ref('');
369
+
370
+ let lastUrl = '';
371
+ let lastQueryHash = '';
372
+
373
+ // eslint-disable-next-line vue/no-setup-props-destructure
374
+ const query = ref<DataTableQuery>(cloneDeep(props.defaultQuery));
375
+ const slots = useSlots();
376
+
377
+ const compactLayout = computed(() => {
378
+ if (props.layout === 'compact') {
379
+ return true;
380
+ }
381
+ return width.value < 1024;
382
+ });
383
+
384
+ const hasFilters = computed((): boolean => {
385
+ const numberOfFilterSlots = slots.filters;
386
+ return numberOfFilterSlots !== undefined;
387
+ });
388
+
389
+ /*
390
+ |--------------------------------------------------------------------------
391
+ | Has sidebar observer
392
+ |--------------------------------------------------------------------------
393
+ */
394
+
395
+ const hasSidebar = ref(false);
396
+ const sidebar = ref<null | HTMLElement>(null);
397
+
398
+ function checkIfSidebarIsEmpty() {
399
+ hasSidebar.value = (sidebar?.value?.childElementCount ?? 0) > 0;
400
+ }
401
+
402
+ const checkIfSidebarIsEmptyDebounce = debounce(checkIfSidebarIsEmpty, 100);
403
+
404
+ useMutationObserver(sidebar, checkIfSidebarIsEmptyDebounce, {
405
+ attributes: false,
406
+ childList: true,
407
+ });
408
+
409
+ onMounted(() => {
410
+ checkIfSidebarIsEmpty();
411
+ });
412
+
413
+ watch(
414
+ () => compactLayout.value,
415
+ () => {
416
+ // After the sidebar appears...
417
+ nextTick(() => {
418
+ checkIfSidebarIsEmpty();
419
+ });
420
+ }
421
+ );
422
+
423
+ /*
424
+ |--------------------------------------------------------------------------
425
+ | Query params
426
+ |--------------------------------------------------------------------------
427
+ */
428
+
429
+ function updateFilterQueryValue(key: string, value: any) {
430
+ let newQuery = cloneDeep(query.value);
431
+ newQuery = set(newQuery, key, value);
432
+ newQuery = set(newQuery, 'page', 1);
433
+ updateQuery(newQuery);
434
+ }
435
+
436
+ function updateFilterQuery(newQuery: DataTableQuery) {
437
+ newQuery = set(newQuery, 'page', 1);
438
+ updateQuery(newQuery);
439
+ }
440
+
441
+ function updateQuery(newQuery: DataTableQuery) {
442
+ if (!props.historyMode) {
443
+ query.value = newQuery;
444
+ fetch();
445
+ return;
446
+ }
447
+
448
+ if (route.name === null) {
449
+ throw new Error('Route name is required for history mode');
450
+ }
451
+
452
+ const newRoute = router.resolve({
453
+ name: route.name,
454
+ params: route.params,
455
+ });
456
+
457
+ const newParams = config.formatQueryString(newQuery);
458
+ const newRoutePath = newRoute.fullPath + '?' + newParams;
459
+
460
+ const oldParamString = getRouteQuery();
461
+ const oldParams = config.formatQueryString(oldParamString);
462
+
463
+ // Push new route if different
464
+ if (oldParams != newParams) {
465
+ if (!firstLoad.value) {
466
+ router.replace(newRoutePath);
467
+ return;
468
+ }
469
+ router.push(newRoutePath);
470
+ return;
471
+ }
472
+
473
+ // If the URL is unchanged, we must manually trigger the fetch() method
474
+ // on first load.
475
+
476
+ if (!firstLoad.value) {
477
+ query.value = newQuery;
478
+ fetch();
479
+ }
480
+ }
481
+
482
+ function queryHash(query: DataTableQuery): string {
483
+ return hash(query);
484
+ }
485
+
486
+ /*
487
+ |--------------------------------------------------------------------------
488
+ | Data fetching
489
+ |--------------------------------------------------------------------------
490
+ */
491
+
492
+ const url = computed<string>(() => {
493
+ return props.url;
494
+ });
495
+
496
+ /*
497
+ |--------------------------------------------------------------------------
498
+ | Handlers
499
+ |--------------------------------------------------------------------------
500
+ */
501
+
502
+ function onPageChange(p: number) {
503
+ const newQuery = cloneDeep(query.value);
504
+
505
+ newQuery.page = p;
506
+
507
+ updateQuery(newQuery);
508
+
509
+ scrollIntoView();
510
+ }
511
+
512
+ function onSortChange(field: string, direction: Direction) {
513
+ let newSort = field;
514
+
515
+ if (newSort && direction == 'desc') {
516
+ newSort = '-' + newSort;
517
+ }
518
+
519
+ const newQuery = cloneDeep(query.value);
520
+
521
+ newQuery.page = 1;
522
+ newQuery.sort = newSort;
523
+
524
+ updateQuery(newQuery);
525
+ }
526
+
527
+ const onSearch = debounce((event: any) => {
528
+ const newQuery = cloneDeep(query.value);
529
+
530
+ newQuery.page = 1;
531
+ newQuery.search = searchQuery.value;
532
+
533
+ updateQuery(newQuery);
534
+ }, 350);
535
+
536
+ /*
537
+ |--------------------------------------------------------------------------
538
+ | Route watcher
539
+ |--------------------------------------------------------------------------
540
+ */
541
+
542
+ watch(
543
+ () => route.query,
544
+ () => {
545
+ // Wait for the willUnmount flag to be set
546
+ nextTick(() => {
547
+ onRouteChange();
548
+ });
549
+ }
550
+ );
551
+
552
+ watch(
553
+ () => props.url,
554
+ () => {
555
+ fetch();
556
+ }
557
+ );
558
+
559
+ watch(
560
+ () => props.urlQuery,
561
+ () => {
562
+ fetch();
563
+ }
564
+ );
565
+
566
+ function getRouteQuery() {
567
+ return config.parseQueryString(window.location.search.replace(/^(\?)/, ''));
568
+ }
569
+
570
+ function onRouteChange() {
571
+ if (!props.historyMode) {
572
+ return;
573
+ }
574
+
575
+ if (willUnmount) {
576
+ return;
577
+ }
578
+
579
+ // Stop if route was changed
580
+ if (route.name != routeName) {
581
+ return;
582
+ }
583
+
584
+ const routeQuery = getRouteQuery();
585
+ const newQuery = routeQuery as DataTableQuery;
586
+
587
+ const newQueryHash = queryHash(newQuery);
588
+
589
+ if (newQueryHash == lastQueryHash) {
590
+ return;
591
+ }
592
+
593
+ lastQueryHash = newQueryHash;
594
+
595
+ query.value = newQuery;
596
+
597
+ // Update search input if not in focus
598
+ if (searchInput.value && searchInput.value !== document.activeElement) {
599
+ updateSearchInput();
600
+ }
601
+
602
+ fetch();
603
+ }
604
+
605
+ /*
606
+ |--------------------------------------------------------------------------
607
+ | Fetch
608
+ |--------------------------------------------------------------------------
609
+ */
610
+
611
+ function fetchWithLoading(force = false) {
612
+ fetch(force, true);
613
+ }
614
+
615
+ function fetchWithoutLoading(force = false) {
616
+ fetch(force, false);
617
+ }
618
+
619
+ function fetch(force = false, showLoading = true) {
620
+ if (willUnmount) {
621
+ return;
622
+ }
623
+
624
+ const urlSplit = url.value.split(/[?#]/);
625
+
626
+ const baseUrl = urlSplit[0];
627
+ const urlQueryString = urlSplit[1] ?? null;
628
+ const urlQuery = config.parseQueryString(urlQueryString);
629
+
630
+ // Ordered by priority
631
+ const allParams = merge(
632
+ cloneDeep(query.value),
633
+ cloneDeep(props.urlQuery),
634
+ cloneDeep(urlQuery)
635
+ );
636
+
637
+ const queryString = config.formatQueryString(allParams);
638
+
639
+ const fullUrl = baseUrl + '?' + queryString;
640
+
641
+ if (lastUrl == fullUrl && !force) {
642
+ return;
643
+ }
644
+
645
+ if (showLoading) {
646
+ loading.value = true;
647
+ }
648
+
649
+ lastUrl = fullUrl;
650
+
651
+ http
652
+ .get(fullUrl)
653
+ .then((response) => {
654
+ data.value = response.data;
655
+ loading.value = false;
656
+ error.value = false;
657
+ firstLoad.value = true;
658
+ emit('fetch', data.value);
659
+ })
660
+ .catch(() => {
661
+ data.value = null;
662
+ loading.value = false;
663
+ error.value = true;
664
+ })
665
+ .finally(() => {
666
+ loading.value = false;
667
+ });
668
+ }
669
+
670
+ /*
671
+ |--------------------------------------------------------------------------
672
+ | Data parsing
673
+ |--------------------------------------------------------------------------
674
+ */
675
+
676
+ const data = ref<null | ResourceCollection | PaginatedCollection | Collection>(
677
+ null
678
+ );
679
+
680
+ const { items, paginationMetadata, lastPage } = useHasPaginatedData(data);
681
+
682
+ const page = computed((): number => {
683
+ if (query.value.page && parseInt(query.value.page + '')) {
684
+ return parseInt(query.value.page + '');
685
+ }
686
+ return 1;
687
+ });
688
+
689
+ const sortField = computed((): string => {
690
+ return query.value.sort?.trim().replace(/^(-)/, '') ?? '';
691
+ });
692
+
693
+ const sortDirection = computed((): Direction => {
694
+ if (query.value.sort && query.value.sort.length) {
695
+ if (query.value.sort[0] == '-') {
696
+ return 'desc';
697
+ }
698
+ }
699
+ return 'asc';
700
+ });
701
+
702
+ const searchKeywords = computed((): string => {
703
+ return query.value.search ?? '';
704
+ });
705
+
706
+ /*
707
+ |--------------------------------------------------------------------------
708
+ | Helpers
709
+ |--------------------------------------------------------------------------
710
+ */
711
+
712
+ /** Scroll into view */
713
+
714
+ const scrollIntoView = () => {
715
+ emit('will-scroll-top');
716
+
717
+ if (!props.scrollTopOnFetch) {
718
+ return;
719
+ }
720
+
721
+ scrollIntoViewAction();
722
+ };
723
+
724
+ const scrollIntoViewAction = () => {
725
+ if (dataIteratorNode.value == null) {
726
+ return;
727
+ }
728
+
729
+ dataIteratorNode.value.scrollIntoView({
730
+ behavior: 'smooth',
731
+ });
732
+ };
733
+
734
+ function updateSearchInput() {
735
+ searchQuery.value = searchKeywords.value;
736
+ }
737
+
738
+ const paginationStart = computed(() => {
739
+ if (paginationMetadata.value == null) {
740
+ return '';
741
+ }
742
+
743
+ return (
744
+ paginationMetadata.value.per_page *
745
+ (paginationMetadata.value.current_page - 1) +
746
+ 1
747
+ );
748
+ });
749
+
750
+ const paginationEnd = computed(() => {
751
+ if (paginationMetadata.value == null) {
752
+ return '';
753
+ }
754
+
755
+ return Math.min(
756
+ paginationMetadata.value.current_page * paginationMetadata.value.per_page,
757
+ paginationMetadata.value.total
758
+ );
759
+ });
760
+
761
+ /*
762
+ |--------------------------------------------------------------------------
763
+ | Created
764
+ |--------------------------------------------------------------------------
765
+ */
766
+
767
+ let newQuery = cloneDeep(query.value);
768
+ const routeQuery = getRouteQuery();
769
+
770
+ newQuery = merge(newQuery, routeQuery);
771
+
772
+ updateQuery(newQuery);
773
+
774
+ // Update search input on first load
775
+ onMounted(() => {
776
+ updateSearchInput();
777
+ });
778
+
779
+ /*
780
+ |--------------------------------------------------------------------------
781
+ | Sections
782
+ |--------------------------------------------------------------------------
783
+ */
784
+
785
+ const sectionModalActive = ref<null | number>(null);
786
+
787
+ const sectionsInternal = computed<DataIteratorSection[]>(() => {
788
+ const sections = props.sections ?? [];
789
+
790
+ if (hasFilters.value) {
791
+ return [
792
+ {
793
+ name: 'filters',
794
+ title: t('sui.filters'),
795
+ closeText: t('sui.apply_filters'),
796
+ icon: 'heroicons:funnel',
797
+ opened: true,
798
+ },
799
+ ...sections,
800
+ ];
801
+ }
802
+
803
+ return sections;
804
+ });
805
+
806
+ function openSection(index: number) {
807
+ if (sectionsInternal.value[index]) {
808
+ sectionModalActive.value = index;
809
+ } else {
810
+ sectionModalActive.value = null;
811
+ }
812
+ }
813
+
814
+ function closeSection() {
815
+ sectionModalActive.value = null;
816
+ }
817
+
818
+ /*
819
+ |--------------------------------------------------------------------------
820
+ | Provide
821
+ |--------------------------------------------------------------------------
822
+ */
823
+
824
+ provide('dataIterator:width', width);
825
+
826
+ /*
827
+ |--------------------------------------------------------------------------
828
+ | Exposed API
829
+ |--------------------------------------------------------------------------
830
+ */
831
+
832
+ defineExpose({
833
+ fetch: () => fetch(true),
834
+ fetchWithLoading: () => fetchWithLoading(true),
835
+ fetchWithoutLoading: () => fetchWithoutLoading(true),
836
+ scrollIntoView: scrollIntoViewAction,
837
+ query,
838
+ });
839
+ </script>