sprintify-ui 0.2.19 → 0.2.22

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