@anzusystems/common-admin 2.0.0-rc.5 → 2.0.0-rc.6

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 (679) hide show
  1. package/dist/AnzuSystemsCommonAdmin.d.ts +42 -32
  2. package/dist/AnzuSystemsCommonAdmin.js.map +1 -1
  3. package/dist/common-admin.css +1 -1
  4. package/dist/common-admin.js +282 -282
  5. package/dist/domains/anzuUser/api/anzuUserApi.d.ts +9 -12
  6. package/dist/domains/anzuUser/api/anzuUserApi.js.map +1 -1
  7. package/dist/domains/anzuUser/components/AAnzuUserDatatable.js.map +1 -1
  8. package/dist/domains/anzuUser/components/AAnzuUserDatatable.vue.d.ts +38 -44
  9. package/dist/domains/anzuUser/components/AAnzuUserDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  10. package/dist/domains/anzuUser/components/AAnzuUserFilter.js.map +1 -1
  11. package/dist/domains/anzuUser/components/AAnzuUserFilter.vue.d.ts +12 -13
  12. package/dist/domains/anzuUser/components/AAnzuUserFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  13. package/dist/domains/anzuUser/components/AAnzuUserForm.js.map +1 -1
  14. package/dist/domains/anzuUser/components/AAnzuUserForm.vue.d.ts +18 -20
  15. package/dist/domains/anzuUser/components/AAnzuUserForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  16. package/dist/domains/anzuUser/components/AAnzuUserRoleAutocomplete.js.map +1 -1
  17. package/dist/domains/anzuUser/components/AAnzuUserRoleAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  18. package/dist/domains/anzuUser/components/AUserBulkActionDialog.js.map +1 -1
  19. package/dist/domains/anzuUser/components/AUserBulkActionDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  20. package/dist/domains/anzuUser/components/AUserCopyPermissionsDialog.js.map +1 -1
  21. package/dist/domains/anzuUser/components/AUserCopyPermissionsDialog.vue.d.ts +2 -3
  22. package/dist/domains/anzuUser/components/AUserCopyPermissionsDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  23. package/dist/domains/anzuUser/components/AUserCreateInSystemButton.js.map +1 -1
  24. package/dist/domains/anzuUser/components/AUserCreateInSystemButton.vue.d.ts +9 -15
  25. package/dist/domains/anzuUser/components/AUserCreateInSystemButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  26. package/dist/domains/anzuUser/components/AUserEnabledSwitch.js.map +1 -1
  27. package/dist/domains/anzuUser/components/AUserEnabledSwitch.vue.d.ts +8 -7
  28. package/dist/domains/anzuUser/components/AUserEnabledSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  29. package/dist/domains/anzuUser/components/AUserManageButton.js.map +1 -1
  30. package/dist/domains/anzuUser/components/AUserManageButton.vue.d.ts +0 -1
  31. package/dist/domains/anzuUser/components/AUserManageButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  32. package/dist/domains/anzuUser/components/AUserMetadataForm.js.map +1 -1
  33. package/dist/domains/anzuUser/components/AUserMetadataForm.vue.d.ts +8 -9
  34. package/dist/domains/anzuUser/components/AUserMetadataForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  35. package/dist/domains/anzuUser/components/AUserMetadataRepairDialog.js.map +1 -1
  36. package/dist/domains/anzuUser/components/AUserMetadataRepairDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  37. package/dist/domains/anzuUser/components/AUserOtherSystemsTable.js.map +1 -1
  38. package/dist/domains/anzuUser/components/AUserOtherSystemsTable.vue.d.ts +1 -2
  39. package/dist/domains/anzuUser/components/AUserOtherSystemsTable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  40. package/dist/domains/anzuUser/components/AUserSystemOverview.js.map +1 -1
  41. package/dist/domains/anzuUser/components/AUserSystemOverview.vue_vue_type_script_setup_true_lang.js.map +1 -1
  42. package/dist/domains/anzuUser/components/AUserSystemPanel.js.map +1 -1
  43. package/dist/domains/anzuUser/components/AUserSystemPanel.vue.d.ts +2 -2
  44. package/dist/domains/anzuUser/components/AUserSystemPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  45. package/dist/domains/anzuUser/components/AUserSystemStatusChip.js.map +1 -1
  46. package/dist/domains/anzuUser/components/AUserSystemStatusChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  47. package/dist/domains/anzuUser/components/AUserTabsShell.js.map +1 -1
  48. package/dist/domains/anzuUser/components/AUserTabsShell.vue.d.ts +17 -22
  49. package/dist/domains/anzuUser/components/AUserTabsShell.vue_vue_type_script_setup_true_lang.js.map +1 -1
  50. package/dist/domains/anzuUser/composables/anzuUserActions.d.ts +5 -9
  51. package/dist/domains/anzuUser/composables/anzuUserActions.js.map +1 -1
  52. package/dist/domains/anzuUser/composables/anzuUserValidations.d.ts +4 -6
  53. package/dist/domains/anzuUser/composables/anzuUserValidations.js.map +1 -1
  54. package/dist/domains/anzuUser/composables/cachedAnzuUsers.d.ts +3 -3
  55. package/dist/domains/anzuUser/composables/cachedAnzuUsers.js.map +1 -1
  56. package/dist/domains/anzuUser/composables/userCrossSystemSearch.d.ts +2 -4
  57. package/dist/domains/anzuUser/composables/userCrossSystemSearch.js.map +1 -1
  58. package/dist/domains/anzuUser/composables/userCrossSystemWrites.d.ts +5 -11
  59. package/dist/domains/anzuUser/composables/userCrossSystemWrites.js.map +1 -1
  60. package/dist/domains/anzuUser/composables/userSystemDescriptor.d.ts +33 -57
  61. package/dist/domains/anzuUser/composables/userSystemDescriptor.js.map +1 -1
  62. package/dist/domains/anzuUser/composables/userSystemProbe.d.ts +7 -27
  63. package/dist/domains/anzuUser/composables/userSystemProbe.js.map +1 -1
  64. package/dist/domains/anzuUser/filter/anzuUserFilter.d.ts +6 -16
  65. package/dist/domains/anzuUser/filter/anzuUserFilter.js.map +1 -1
  66. package/dist/domains/anzuUser/store/anzuUserStore.d.ts +1 -5
  67. package/dist/domains/anzuUser/store/anzuUserStore.js.map +1 -1
  68. package/dist/domains/anzuUser/store/userCrossSystemStore.d.ts +3 -14
  69. package/dist/domains/anzuUser/store/userCrossSystemStore.js.map +1 -1
  70. package/dist/domains/anzuUser/utils/userMetadataDiff.d.ts +7 -19
  71. package/dist/domains/anzuUser/utils/userMetadataDiff.js.map +1 -1
  72. package/dist/domains/anzuUser/utils/userSystemState.d.ts +12 -30
  73. package/dist/domains/anzuUser/utils/userSystemState.js.map +1 -1
  74. package/dist/domains/anzuUser/utils/userTabs.d.ts +1 -3
  75. package/dist/domains/anzuUser/utils/userTabs.js.map +1 -1
  76. package/dist/domains/api/composables/defineApiClient.d.ts +4 -8
  77. package/dist/domains/api/composables/defineApiClient.js.map +1 -1
  78. package/dist/domains/api/composables/request.d.ts +18 -48
  79. package/dist/domains/api/composables/request.js.map +1 -1
  80. package/dist/domains/api/composables/useApiFetchByIds.d.ts +7 -21
  81. package/dist/domains/api/composables/useApiFetchByIds.js.map +1 -1
  82. package/dist/domains/api/composables/useApiFetchItems.d.ts +18 -57
  83. package/dist/domains/api/composables/useApiFetchItems.js.map +1 -1
  84. package/dist/domains/api/composables/useApiFetchList.d.ts +7 -23
  85. package/dist/domains/api/composables/useApiFetchList.js.map +1 -1
  86. package/dist/domains/api/composables/useApiFetchListBatch.d.ts +5 -22
  87. package/dist/domains/api/composables/useApiFetchListBatch.js.map +1 -1
  88. package/dist/domains/api/composables/useApiQueryBuilder.js.map +1 -1
  89. package/dist/domains/api/composables/useApiRequest.d.ts +16 -39
  90. package/dist/domains/api/composables/useApiRequest.js.map +1 -1
  91. package/dist/domains/api/utils/apiErrors.d.ts +28 -55
  92. package/dist/domains/api/utils/apiErrors.js.map +1 -1
  93. package/dist/domains/api/utils/listBody.d.ts +22 -43
  94. package/dist/domains/api/utils/listBody.js.map +1 -1
  95. package/dist/domains/auth/components/Acl.js.map +1 -1
  96. package/dist/domains/auth/components/Acl.vue_vue_type_script_setup_true_lang.js.map +1 -1
  97. package/dist/domains/auth/composables/aclAllowed.d.ts +2 -3
  98. package/dist/domains/auth/composables/aclAllowed.js.map +1 -1
  99. package/dist/domains/auth/composables/defineAuth.js.map +1 -1
  100. package/dist/domains/auth/composables/refreshSession.d.ts +10 -13
  101. package/dist/domains/auth/composables/refreshSession.js.map +1 -1
  102. package/dist/domains/cached/components/ACachedChip.js.map +1 -1
  103. package/dist/domains/cached/components/ACachedChip.vue.d.ts +13 -11
  104. package/dist/domains/cached/components/ACachedChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  105. package/dist/domains/cached/components/ACachedUserChip.js +1 -1
  106. package/dist/domains/cached/components/ACachedUserChip.js.map +1 -1
  107. package/dist/domains/cached/components/ACachedUserChip.vue.d.ts +3 -3
  108. package/dist/domains/cached/components/ACachedUserChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  109. package/dist/domains/cached/composables/createUserAndTimeTrackingFields.d.ts +9 -9
  110. package/dist/domains/cached/composables/createUserAndTimeTrackingFields.js.map +1 -1
  111. package/dist/domains/cached/composables/defineCached.d.ts +13 -11
  112. package/dist/domains/cached/composables/defineCached.js.map +1 -1
  113. package/dist/domains/cached/composables/useCachedItem.d.ts +7 -8
  114. package/dist/domains/cached/composables/useCachedItem.js.map +1 -1
  115. package/dist/domains/collab/components/ACollabLockedByUser.js.map +1 -1
  116. package/dist/domains/collab/components/ACollabLockedByUser.vue_vue_type_script_setup_true_lang.js.map +1 -1
  117. package/dist/domains/collab/composables/collabAnyDataChange.js.map +1 -1
  118. package/dist/domains/collab/composables/collabField.d.ts +5 -3
  119. package/dist/domains/collab/composables/collabField.js.map +1 -1
  120. package/dist/domains/collab/composables/collabInit.js +58 -54
  121. package/dist/domains/collab/composables/collabInit.js.map +1 -1
  122. package/dist/domains/collab/composables/collabRecovery.d.ts +49 -0
  123. package/dist/domains/collab/composables/collabRecovery.js +99 -0
  124. package/dist/domains/collab/composables/collabRecovery.js.map +1 -0
  125. package/dist/domains/collab/composables/collabRoom.js +106 -106
  126. package/dist/domains/collab/composables/collabRoom.js.map +1 -1
  127. package/dist/domains/collab/composables/collabState.d.ts +11 -4
  128. package/dist/domains/collab/composables/collabState.js +34 -25
  129. package/dist/domains/collab/composables/collabState.js.map +1 -1
  130. package/dist/domains/collab/composables/commonAdminCollabOptions.d.ts +4 -2
  131. package/dist/domains/collab/types/Collab.d.ts +31 -5
  132. package/dist/domains/collab/types/Collab.js +23 -11
  133. package/dist/domains/collab/types/Collab.js.map +1 -1
  134. package/dist/domains/customDataForm/components/ACustomDataForm.js.map +1 -1
  135. package/dist/domains/customDataForm/components/ACustomDataForm.vue.d.ts +7 -5
  136. package/dist/domains/customDataForm/components/ACustomDataForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  137. package/dist/domains/customDataForm/components/ACustomDataFormElement.js.map +1 -1
  138. package/dist/domains/customDataForm/components/ACustomDataFormElement.vue_vue_type_script_setup_true_lang.js.map +1 -1
  139. package/dist/domains/customDataForm/components/ACustomDataFormHiddenPart.js.map +1 -1
  140. package/dist/domains/customDataForm/components/ACustomDataFormHiddenPart.vue.d.ts +5 -3
  141. package/dist/domains/customDataForm/components/ACustomDataFormHiddenPart.vue_vue_type_script_setup_true_lang.js.map +1 -1
  142. package/dist/domains/customDataForm/composables/useCustomDataForm.js.map +1 -1
  143. package/dist/domains/customDataForm/types/CustomDataForm.d.ts +4 -1
  144. package/dist/domains/dam/api/damAssetApi.d.ts +7 -7
  145. package/dist/domains/dam/api/damAssetApi.js.map +1 -1
  146. package/dist/domains/dam/api/damAssetLicenceApi.d.ts +1 -1
  147. package/dist/domains/dam/api/damAssetLicenceApi.js.map +1 -1
  148. package/dist/domains/dam/api/damConstants.js.map +1 -1
  149. package/dist/domains/dam/api/damEndPoints.js.map +1 -1
  150. package/dist/domains/dam/api/damImageApi.js.map +1 -1
  151. package/dist/domains/dam/api/uploadApi.js.map +1 -1
  152. package/dist/domains/dam/assetDetail/components/AssetCustomMetadataForm.js.map +1 -1
  153. package/dist/domains/dam/assetDetail/components/AssetCustomMetadataForm.vue.d.ts +7 -5
  154. package/dist/domains/dam/assetDetail/components/AssetCustomMetadataForm.vue_vue_type_script_setup_true_lang.js.map +1 -1
  155. package/dist/domains/dam/assetDetail/components/AssetDetailDialog.js.map +1 -1
  156. package/dist/domains/dam/assetDetail/components/AssetDetailDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  157. package/dist/domains/dam/assetDetail/components/AssetDetailDialogFrame.js.map +1 -1
  158. package/dist/domains/dam/assetDetail/components/AssetDetailDialogFrame.vue.d.ts +1 -1
  159. package/dist/domains/dam/assetDetail/components/AssetDetailDialogFrame.vue_vue_type_script_setup_true_lang.js.map +1 -1
  160. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarActionsWrapper.vue.d.ts +5 -3
  161. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarFrame.js.map +1 -1
  162. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarFrame.vue_vue_type_script_setup_true_lang.js.map +1 -1
  163. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarMetadata.js.map +1 -1
  164. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  165. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarROI.js.map +1 -1
  166. package/dist/domains/dam/assetDetail/components/AssetDetailSidebarROI.vue_vue_type_script_setup_true_lang.js.map +1 -1
  167. package/dist/domains/dam/assetDetail/components/AssetFileInfoPanel.js.map +1 -1
  168. package/dist/domains/dam/assetDetail/components/AssetFileInfoPanel.vue.d.ts +1 -1
  169. package/dist/domains/dam/assetDetail/components/AssetFileInfoPanel.vue_vue_type_script_setup_true_lang.js.map +1 -1
  170. package/dist/domains/dam/assetDetail/components/AssetImage.js.map +1 -1
  171. package/dist/domains/dam/assetDetail/components/AssetImage.vue.d.ts +1 -1
  172. package/dist/domains/dam/assetDetail/components/AssetImage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  173. package/dist/domains/dam/assetDetail/components/AssetImageMetaIcons.js.map +1 -1
  174. package/dist/domains/dam/assetDetail/components/AssetImageMetaIcons.vue.d.ts +2 -2
  175. package/dist/domains/dam/assetDetail/components/AssetImageMetaIcons.vue_vue_type_script_setup_true_lang.js.map +1 -1
  176. package/dist/domains/dam/assetDetail/components/AssetInfobox.js.map +1 -1
  177. package/dist/domains/dam/assetDetail/components/AssetInfobox.vue_vue_type_script_setup_true_lang.js.map +1 -1
  178. package/dist/domains/dam/assetDetail/components/AssetMetadata.js.map +1 -1
  179. package/dist/domains/dam/assetDetail/components/AssetMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  180. package/dist/domains/dam/assetDetail/composables/assetDetailExtSystem.d.ts +5 -6
  181. package/dist/domains/dam/assetDetail/composables/assetDetailExtSystem.js.map +1 -1
  182. package/dist/domains/dam/assetDetail/composables/assetDetailView.d.ts +10 -10
  183. package/dist/domains/dam/assetDetail/composables/assetDetailView.js.map +1 -1
  184. package/dist/domains/dam/assetDetail/store/assetDetailStore.js.map +1 -1
  185. package/dist/domains/dam/assetDetail/utils/assetMetadataMayStillChange.d.ts +4 -3
  186. package/dist/domains/dam/assetDetail/utils/assetMetadataMayStillChange.js.map +1 -1
  187. package/dist/domains/dam/assetSelect/api/damPodcastApi.js.map +1 -1
  188. package/dist/domains/dam/assetSelect/components/AAssetListInner.js.map +1 -1
  189. package/dist/domains/dam/assetSelect/components/AAssetListInner.vue.d.ts +789 -787
  190. package/dist/domains/dam/assetSelect/components/AAssetListInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  191. package/dist/domains/dam/assetSelect/components/AAssetSelect.js.map +1 -1
  192. package/dist/domains/dam/assetSelect/components/AAssetSelect.vue.d.ts +395 -393
  193. package/dist/domains/dam/assetSelect/components/AAssetSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  194. package/dist/domains/dam/assetSelect/components/AAssetSelectMedia.js.map +1 -1
  195. package/dist/domains/dam/assetSelect/components/AAssetSelectMedia.vue.d.ts +14 -12
  196. package/dist/domains/dam/assetSelect/components/AAssetSelectMedia.vue_vue_type_script_setup_true_lang.js.map +1 -1
  197. package/dist/domains/dam/assetSelect/components/AssetDistributionServiceNameFilter.js.map +1 -1
  198. package/dist/domains/dam/assetSelect/components/AssetDistributionServiceNameFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  199. package/dist/domains/dam/assetSelect/components/AssetSelectListBar.js.map +1 -1
  200. package/dist/domains/dam/assetSelect/components/AssetSelectListBar.vue.d.ts +9 -7
  201. package/dist/domains/dam/assetSelect/components/AssetSelectListBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  202. package/dist/domains/dam/assetSelect/components/AssetSelectTableRowItem.js.map +1 -1
  203. package/dist/domains/dam/assetSelect/components/AssetSelectTableRowItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  204. package/dist/domains/dam/assetSelect/composables/assetSelectListActions.js.map +1 -1
  205. package/dist/domains/dam/assetSelect/store/assetSelectStore.js.map +1 -1
  206. package/dist/domains/dam/author/api/authorApi.js.map +1 -1
  207. package/dist/domains/dam/author/components/AuthorCreateButton.js.map +1 -1
  208. package/dist/domains/dam/author/components/AuthorCreateButton.vue.d.ts +1 -1
  209. package/dist/domains/dam/author/components/AuthorCreateButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  210. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChip.js.map +1 -1
  211. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChip.vue.d.ts +9 -6
  212. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  213. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChipConflicts.js.map +1 -1
  214. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteCachedAuthorChipConflicts.vue_vue_type_script_setup_true_lang.js.map +1 -1
  215. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.js +1 -1
  216. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.js.map +1 -1
  217. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.vue.d.ts +2 -2
  218. package/dist/domains/dam/author/components/AuthorRemoteAutocompleteWithCached.vue_vue_type_script_setup_true_lang.js.map +1 -1
  219. package/dist/domains/dam/author/components/DamAuthorFilterRemoteAutocomplete.js.map +1 -1
  220. package/dist/domains/dam/author/components/DamAuthorFilterRemoteAutocomplete.vue.d.ts +1 -1
  221. package/dist/domains/dam/author/components/DamAuthorFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  222. package/dist/domains/dam/author/composables/cachedAuthors.d.ts +5 -4
  223. package/dist/domains/dam/author/composables/cachedAuthors.js.map +1 -1
  224. package/dist/domains/dam/author/composables/cachedUsers.d.ts +5 -4
  225. package/dist/domains/dam/author/composables/cachedUsers.js.map +1 -1
  226. package/dist/domains/dam/author/composables/damAuthorConfig.d.ts +2 -2
  227. package/dist/domains/dam/author/composables/damAuthorConfig.js.map +1 -1
  228. package/dist/domains/dam/components/DamAdminAssetLink.js.map +1 -1
  229. package/dist/domains/dam/components/DamAdminAssetLink.vue_vue_type_script_setup_true_lang.js.map +1 -1
  230. package/dist/domains/dam/composables/commonAdminCoreDamOptions.d.ts +10 -8
  231. package/dist/domains/dam/composables/commonAdminCoreDamOptions.js.map +1 -1
  232. package/dist/domains/dam/composables/damConfigName.d.ts +8 -9
  233. package/dist/domains/dam/composables/damConfigName.js.map +1 -1
  234. package/dist/domains/dam/composables/damNotifications.d.ts +9 -9
  235. package/dist/domains/dam/composables/damNotifications.js.map +1 -1
  236. package/dist/domains/dam/composables/damNotificationsConnection.d.ts +4 -4
  237. package/dist/domains/dam/composables/damNotificationsConnection.js.map +1 -1
  238. package/dist/domains/dam/composables/damNotificationsEventBus.d.ts +2 -2
  239. package/dist/domains/dam/composables/damNotificationsEventBus.js.map +1 -1
  240. package/dist/domains/dam/composables/extSystemIdForCached.d.ts +5 -4
  241. package/dist/domains/dam/composables/extSystemIdForCached.js.map +1 -1
  242. package/dist/domains/dam/config/api/damAssetCustomFormApi.js.map +1 -1
  243. package/dist/domains/dam/config/api/damConfigApi.js.map +1 -1
  244. package/dist/domains/dam/config/composables/damConfigState.d.ts +5 -5
  245. package/dist/domains/dam/config/composables/damConfigState.js.map +1 -1
  246. package/dist/domains/dam/config/store/damConfigStore.d.ts +5 -4
  247. package/dist/domains/dam/config/store/damConfigStore.js.map +1 -1
  248. package/dist/domains/dam/config/utils/damFilterUserAllowedUploadConfigs.d.ts +3 -1
  249. package/dist/domains/dam/config/utils/damFilterUserAllowedUploadConfigs.js.map +1 -1
  250. package/dist/domains/dam/cropper/components/ACropper.js.map +1 -1
  251. package/dist/domains/dam/cropper/components/ACropper.vue.d.ts +8 -16
  252. package/dist/domains/dam/cropper/components/ACropper.vue_vue_type_script_setup_true_lang.js.map +1 -1
  253. package/dist/domains/dam/cropper/components/DamAssetImageRoiSelect.js.map +1 -1
  254. package/dist/domains/dam/cropper/components/DamAssetImageRoiSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  255. package/dist/domains/dam/cropper/store/imageRoiStore.d.ts +9 -12
  256. package/dist/domains/dam/cropper/store/imageRoiStore.js.map +1 -1
  257. package/dist/domains/dam/cropper/utils/cropperGeometry.d.ts +24 -38
  258. package/dist/domains/dam/cropper/utils/cropperGeometry.js.map +1 -1
  259. package/dist/domains/dam/cropper/utils/cropperJsService.d.ts +3 -7
  260. package/dist/domains/dam/cropper/utils/cropperJsService.js +10 -3
  261. package/dist/domains/dam/cropper/utils/cropperJsService.js.map +1 -1
  262. package/dist/domains/dam/cropper/utils/cropperTypes.d.ts +3 -6
  263. package/dist/domains/dam/cropper/utils/damAssetImageRoiSelectLoader.d.ts +5 -5
  264. package/dist/domains/dam/cropper/utils/damAssetImageRoiSelectLoader.js.map +1 -1
  265. package/dist/domains/dam/imageWidget/components/AImageMediaWidget.js.map +1 -1
  266. package/dist/domains/dam/imageWidget/components/AImageMediaWidget.vue_vue_type_script_setup_true_lang.js.map +1 -1
  267. package/dist/domains/dam/imageWidget/components/AImagePublicInput.js.map +1 -1
  268. package/dist/domains/dam/imageWidget/components/AImagePublicInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  269. package/dist/domains/dam/imageWidget/components/AImageWidget.js.map +1 -1
  270. package/dist/domains/dam/imageWidget/components/AImageWidget.vue_vue_type_script_setup_true_lang.js.map +1 -1
  271. package/dist/domains/dam/imageWidget/components/AImageWidgetMultiple.js.map +1 -1
  272. package/dist/domains/dam/imageWidget/components/AImageWidgetMultiple.vue_vue_type_script_setup_true_lang.js.map +1 -1
  273. package/dist/domains/dam/imageWidget/components/AImageWidgetSimple.vue.d.ts +43 -41
  274. package/dist/domains/dam/imageWidget/components/AMediaWidgetSimple.vue.d.ts +31 -29
  275. package/dist/domains/dam/imageWidget/components/ImageDetailDialogMetadata.js.map +1 -1
  276. package/dist/domains/dam/imageWidget/components/ImageDetailDialogMetadata.vue.d.ts +29 -27
  277. package/dist/domains/dam/imageWidget/components/ImageDetailDialogMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  278. package/dist/domains/dam/imageWidget/components/ImageMassOperations.js.map +1 -1
  279. package/dist/domains/dam/imageWidget/components/ImageMassOperations.vue.d.ts +1 -1
  280. package/dist/domains/dam/imageWidget/components/ImageMassOperations.vue_vue_type_script_setup_true_lang.js.map +1 -1
  281. package/dist/domains/dam/imageWidget/components/ImageMediaWidgetInner.js.map +1 -1
  282. package/dist/domains/dam/imageWidget/components/ImageMediaWidgetInner.vue.d.ts +68 -66
  283. package/dist/domains/dam/imageWidget/components/ImageMediaWidgetInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  284. package/dist/domains/dam/imageWidget/components/ImageWidgetInner.js.map +1 -1
  285. package/dist/domains/dam/imageWidget/components/ImageWidgetInner.vue.d.ts +402 -400
  286. package/dist/domains/dam/imageWidget/components/ImageWidgetInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  287. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleInner.js.map +1 -1
  288. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleInner.vue.d.ts +384 -382
  289. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleInner.vue_vue_type_script_setup_true_lang.js.map +1 -1
  290. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleItem.js.map +1 -1
  291. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleItem.vue_vue_type_script_setup_true_lang.js.map +1 -1
  292. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleLimitDialog.js.map +1 -1
  293. package/dist/domains/dam/imageWidget/components/ImageWidgetMultipleLimitDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  294. package/dist/domains/dam/imageWidget/components/MediaWidgetSimpleDialog.vue.d.ts +7 -5
  295. package/dist/domains/dam/imageWidget/composables/commonAdminImageOptions.js.map +1 -1
  296. package/dist/domains/dam/imageWidget/composables/imageApiCms.js.map +1 -1
  297. package/dist/domains/dam/imageWidget/composables/imageDialogDamAuthors.d.ts +11 -13
  298. package/dist/domains/dam/imageWidget/composables/imageDialogDamAuthors.js.map +1 -1
  299. package/dist/domains/dam/imageWidget/composables/useImageMassOperations.js.map +1 -1
  300. package/dist/domains/dam/imageWidget/store/imageMediaWidgetStore.js.map +1 -1
  301. package/dist/domains/dam/imageWidget/store/imageStore.js.map +1 -1
  302. package/dist/domains/dam/imageWidget/utils/damImage.d.ts +5 -6
  303. package/dist/domains/dam/imageWidget/utils/damImage.js.map +1 -1
  304. package/dist/domains/dam/imageWidget/utils/fieldLockTurns.d.ts +1 -2
  305. package/dist/domains/dam/imageWidget/utils/fieldLockTurns.js.map +1 -1
  306. package/dist/domains/dam/imageWidget/utils/imageSaves.d.ts +10 -14
  307. package/dist/domains/dam/imageWidget/utils/imageSaves.js.map +1 -1
  308. package/dist/domains/dam/imageWidget/utils/metadataToImageMap.js.map +1 -1
  309. package/dist/domains/dam/imageWidget/utils/waitLimit.d.ts +4 -6
  310. package/dist/domains/dam/imageWidget/utils/waitLimit.js.map +1 -1
  311. package/dist/domains/dam/keyword/api/keywordApi.js.map +1 -1
  312. package/dist/domains/dam/keyword/components/DamKeywordFilterRemoteAutocomplete.js.map +1 -1
  313. package/dist/domains/dam/keyword/components/DamKeywordFilterRemoteAutocomplete.vue.d.ts +1 -1
  314. package/dist/domains/dam/keyword/components/DamKeywordFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  315. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteCachedKeywordChip.js.map +1 -1
  316. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteCachedKeywordChip.vue.d.ts +8 -5
  317. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteCachedKeywordChip.vue_vue_type_script_setup_true_lang.js.map +1 -1
  318. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.js +1 -1
  319. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.js.map +1 -1
  320. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.vue.d.ts +2 -2
  321. package/dist/domains/dam/keyword/components/KeywordRemoteAutocompleteWithCached.vue_vue_type_script_setup_true_lang.js.map +1 -1
  322. package/dist/domains/dam/keyword/composables/cachedKeywords.d.ts +5 -4
  323. package/dist/domains/dam/keyword/composables/cachedKeywords.js.map +1 -1
  324. package/dist/domains/dam/keyword/composables/damKeywordConfig.d.ts +2 -2
  325. package/dist/domains/dam/keyword/composables/damKeywordConfig.js.map +1 -1
  326. package/dist/domains/dam/types/Asset.d.ts +1 -1
  327. package/dist/domains/dam/types/Asset.js.map +1 -1
  328. package/dist/domains/dam/types/UploadQueue.d.ts +5 -4
  329. package/dist/domains/dam/types/UploadQueue.js.map +1 -1
  330. package/dist/domains/dam/uploadQueue/components/AssetCustomMetadataFormMassOperations.js.map +1 -1
  331. package/dist/domains/dam/uploadQueue/components/AssetCustomMetadataFormMassOperations.vue_vue_type_script_setup_true_lang.js.map +1 -1
  332. package/dist/domains/dam/uploadQueue/components/AssetQueueSelectedSidebar.js.map +1 -1
  333. package/dist/domains/dam/uploadQueue/components/AssetQueueSelectedSidebar.vue.d.ts +2 -2
  334. package/dist/domains/dam/uploadQueue/components/AssetQueueSelectedSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  335. package/dist/domains/dam/uploadQueue/components/UploadQueueDialog.js.map +1 -1
  336. package/dist/domains/dam/uploadQueue/components/UploadQueueDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  337. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingle.js.map +1 -1
  338. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingle.vue_vue_type_script_setup_true_lang.js.map +1 -1
  339. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebar.js.map +1 -1
  340. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebar.vue.d.ts +6 -4
  341. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  342. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadata.js.map +1 -1
  343. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadata.vue.d.ts +1 -1
  344. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadata.vue_vue_type_script_setup_true_lang.js.map +1 -1
  345. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadataContent.js.map +1 -1
  346. package/dist/domains/dam/uploadQueue/components/UploadQueueDialogSingleSidebarMetadataContent.vue_vue_type_script_setup_true_lang.js.map +1 -1
  347. package/dist/domains/dam/uploadQueue/components/UploadQueueEditable.js.map +1 -1
  348. package/dist/domains/dam/uploadQueue/components/UploadQueueEditable.vue.d.ts +6 -6
  349. package/dist/domains/dam/uploadQueue/components/UploadQueueEditable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  350. package/dist/domains/dam/uploadQueue/components/UploadQueueItemEditable.js.map +1 -1
  351. package/dist/domains/dam/uploadQueue/components/UploadQueueItemEditable.vue.d.ts +13 -13
  352. package/dist/domains/dam/uploadQueue/components/UploadQueueItemEditable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  353. package/dist/domains/dam/uploadQueue/components/uploadQueueBindings.d.ts +13 -13
  354. package/dist/domains/dam/uploadQueue/components/uploadQueueBindings.js.map +1 -1
  355. package/dist/domains/dam/uploadQueue/composables/damUploadChunkSize.d.ts +2 -2
  356. package/dist/domains/dam/uploadQueue/composables/damUploadChunkSize.js.map +1 -1
  357. package/dist/domains/dam/uploadQueue/composables/uploadMeter.d.ts +12 -12
  358. package/dist/domains/dam/uploadQueue/composables/uploadMeter.js.map +1 -1
  359. package/dist/domains/dam/uploadQueue/composables/uploadQueueItemRefresh.d.ts +5 -5
  360. package/dist/domains/dam/uploadQueue/composables/uploadQueueItemRefresh.js.map +1 -1
  361. package/dist/domains/dam/uploadQueue/composables/uploadService.d.ts +2 -3
  362. package/dist/domains/dam/uploadQueue/composables/uploadService.js.map +1 -1
  363. package/dist/domains/dam/uploadQueue/composables/useUploadQueueDialog.d.ts +5 -4
  364. package/dist/domains/dam/uploadQueue/composables/useUploadQueueDialog.js.map +1 -1
  365. package/dist/domains/dam/uploadQueue/core/uploadQueueCore.d.ts +3 -2
  366. package/dist/domains/dam/uploadQueue/core/uploadQueueCore.js.map +1 -1
  367. package/dist/domains/dam/uploadQueue/core/uploadQueueCoreTypes.d.ts +8 -5
  368. package/dist/domains/dam/uploadQueue/core/uploadQueueCoreTypes.js.map +1 -1
  369. package/dist/domains/dam/uploadQueue/core/uploadQueueFill.d.ts +3 -3
  370. package/dist/domains/dam/uploadQueue/core/uploadQueueFill.js.map +1 -1
  371. package/dist/domains/dam/uploadQueue/presets/queuePresets.d.ts +8 -5
  372. package/dist/domains/dam/uploadQueue/presets/queuePresets.js.map +1 -1
  373. package/dist/domains/dam/uploadQueue/presets/uploadPresets.d.ts +15 -13
  374. package/dist/domains/dam/uploadQueue/presets/uploadPresets.js.map +1 -1
  375. package/dist/domains/dam/uploadQueue/settlement/uploadPollSchedule.d.ts +7 -7
  376. package/dist/domains/dam/uploadQueue/settlement/uploadPollSchedule.js.map +1 -1
  377. package/dist/domains/dam/uploadQueue/settlement/uploadPoller.d.ts +4 -4
  378. package/dist/domains/dam/uploadQueue/settlement/uploadPoller.js.map +1 -1
  379. package/dist/domains/dam/uploadQueue/settlement/uploadSettle.d.ts +28 -30
  380. package/dist/domains/dam/uploadQueue/settlement/uploadSettle.js.map +1 -1
  381. package/dist/domains/dam/uploadQueue/settlement/uploadSettlement.d.ts +2 -2
  382. package/dist/domains/dam/uploadQueue/settlement/uploadSettlement.js.map +1 -1
  383. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementRuntime.d.ts +2 -2
  384. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementRuntime.js.map +1 -1
  385. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementTypes.d.ts +63 -73
  386. package/dist/domains/dam/uploadQueue/settlement/uploadSettlementTypes.js.map +1 -1
  387. package/dist/domains/dam/uploadQueue/store/uploadQueuesStore.d.ts +8 -9
  388. package/dist/domains/dam/uploadQueue/store/uploadQueuesStore.js.map +1 -1
  389. package/dist/domains/dam/user/api/userApi.d.ts +2 -2
  390. package/dist/domains/dam/user/api/userApi.js.map +1 -1
  391. package/dist/domains/dam/user/components/DamDistributionServiceSelect.js.map +1 -1
  392. package/dist/domains/dam/user/components/DamDistributionServiceSelect.vue.d.ts +1 -1
  393. package/dist/domains/dam/user/components/DamDistributionServiceSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  394. package/dist/domains/dam/user/components/DamExternalProviderAssetSelect.js.map +1 -1
  395. package/dist/domains/dam/user/components/DamExternalProviderAssetSelect.vue.d.ts +1 -1
  396. package/dist/domains/dam/user/components/DamExternalProviderAssetSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  397. package/dist/domains/dam/user/components/DamUserRemoteAutocomplete.js.map +1 -1
  398. package/dist/domains/dam/user/components/DamUserRemoteAutocomplete.vue.d.ts +1 -1
  399. package/dist/domains/dam/user/components/DamUserRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  400. package/dist/domains/dam/user/composables/damUserSelectActions.d.ts +1 -1
  401. package/dist/domains/dam/user/composables/damUserSelectActions.js.map +1 -1
  402. package/dist/domains/dam/user/types/DamDistributionServiceType.d.ts +2 -2
  403. package/dist/domains/dam/user/types/DamDistributionServiceType.js.map +1 -1
  404. package/dist/domains/dam/user/types/DamExternalProviderAssetType.d.ts +1 -1
  405. package/dist/domains/dam/user/types/DamExternalProviderAssetType.js.map +1 -1
  406. package/dist/domains/filters/bookmarks/components/FilterBookmarkDialog.js.map +1 -1
  407. package/dist/domains/filters/bookmarks/components/FilterBookmarkDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  408. package/dist/domains/filters/bookmarks/store/bookmarksStore.d.ts +3 -3
  409. package/dist/domains/filters/bookmarks/store/bookmarksStore.js.map +1 -1
  410. package/dist/domains/filters/components/AFilterDatetimePicker.js.map +1 -1
  411. package/dist/domains/filters/components/AFilterDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  412. package/dist/domains/filters/components/AFilterInteger.js.map +1 -1
  413. package/dist/domains/filters/components/AFilterInteger.vue_vue_type_script_setup_true_lang.js.map +1 -1
  414. package/dist/domains/filters/components/AFilterString.js.map +1 -1
  415. package/dist/domains/filters/components/AFilterString.vue_vue_type_script_setup_true_lang.js.map +1 -1
  416. package/dist/domains/filters/components/AFilterTimeInterval.js +1 -1
  417. package/dist/domains/filters/components/AFilterTimeInterval.js.map +1 -1
  418. package/dist/domains/filters/components/AFilterTimeInterval.vue.d.ts +5 -3
  419. package/dist/domains/filters/components/AFilterTimeInterval.vue_vue_type_script_setup_true_lang.js.map +1 -1
  420. package/dist/domains/filters/components/AFilterValueObjectOptionsSelect.js.map +1 -1
  421. package/dist/domains/filters/components/AFilterValueObjectOptionsSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  422. package/dist/domains/filters/components/AFilterWrapper.vue.d.ts +17 -15
  423. package/dist/domains/filters/components/AFilterWrapperSidebar.vue.d.ts +5 -3
  424. package/dist/domains/filters/components/FiltersSelected.js.map +1 -1
  425. package/dist/domains/filters/components/FiltersSelected.vue_vue_type_script_setup_true_lang.js.map +1 -1
  426. package/dist/domains/filters/composables/filterFactory.d.ts +16 -26
  427. package/dist/domains/filters/composables/filterFactory.js +38 -31
  428. package/dist/domains/filters/composables/filterFactory.js.map +1 -1
  429. package/dist/domains/filters/datatable/components/ADatatableOrdering.js.map +1 -1
  430. package/dist/domains/filters/datatable/components/ADatatableOrdering.vue_vue_type_script_setup_true_lang.js +3 -1
  431. package/dist/domains/filters/datatable/components/ADatatableOrdering.vue_vue_type_script_setup_true_lang.js.map +1 -1
  432. package/dist/domains/filters/datatable/components/ADatatablePagination.js.map +1 -1
  433. package/dist/domains/filters/datatable/components/ADatatablePagination.vue_vue_type_script_setup_true_lang.js +2 -4
  434. package/dist/domains/filters/datatable/components/ADatatablePagination.vue_vue_type_script_setup_true_lang.js.map +1 -1
  435. package/dist/domains/filters/utils/filterInjectionKeys.js.map +1 -1
  436. package/dist/domains/form/components/AFormDatetimePicker.js.map +1 -1
  437. package/dist/domains/form/components/AFormDatetimePicker.vue.d.ts +7 -5
  438. package/dist/domains/form/components/AFormDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  439. package/dist/domains/form/components/AFormFlagDatetimePicker.js.map +1 -1
  440. package/dist/domains/form/components/AFormFlagDatetimePicker.vue.d.ts +7 -5
  441. package/dist/domains/form/components/AFormFlagDatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  442. package/dist/domains/form/components/AFormSwitch.vue.d.ts +7 -5
  443. package/dist/domains/form/components/AFormTextField.js.map +1 -1
  444. package/dist/domains/form/components/AFormTextField.vue.d.ts +9 -7
  445. package/dist/domains/form/components/AFormTextField.vue_vue_type_script_setup_true_lang.js.map +1 -1
  446. package/dist/domains/form/components/AFormTextarea.vue.d.ts +13 -11
  447. package/dist/domains/form/components/AFormValueObjectOptionsSelect.vue.d.ts +7 -5
  448. package/dist/domains/form/components/ASystemEntityScope.vue.d.ts +5 -3
  449. package/dist/domains/job/api/jobApi.js.map +1 -1
  450. package/dist/domains/job/components/AJobDetailCommon.vue.d.ts +5 -3
  451. package/dist/domains/listEditor/components/AListEditor.js.map +1 -1
  452. package/dist/domains/listEditor/components/AListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  453. package/dist/domains/listEditor/components/ANestedSortableListEditor.js.map +1 -1
  454. package/dist/domains/listEditor/components/ANestedSortableListEditor.vue.d.ts +2 -3
  455. package/dist/domains/listEditor/components/ANestedSortableListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  456. package/dist/domains/listEditor/components/ASortableListEditor.js.map +1 -1
  457. package/dist/domains/listEditor/components/ASortableListEditor.vue.d.ts +2 -3
  458. package/dist/domains/listEditor/components/ASortableListEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  459. package/dist/domains/listEditor/composables/useListEditorController.d.ts +4 -5
  460. package/dist/domains/listEditor/composables/useListEditorController.js.map +1 -1
  461. package/dist/domains/listEditor/composables/useNestedListEditor.d.ts +3 -4
  462. package/dist/domains/listEditor/composables/useNestedListEditor.js.map +1 -1
  463. package/dist/domains/listEditor/composables/useNestedListEditorController.d.ts +5 -4
  464. package/dist/domains/listEditor/composables/useNestedListEditorController.js.map +1 -1
  465. package/dist/domains/listEditor/composables/useReorderMode.js.map +1 -1
  466. package/dist/domains/listEditor/types/listEditorTypes.d.ts +2 -2
  467. package/dist/domains/listEditor/utils/listEditorLoader.d.ts +5 -5
  468. package/dist/domains/listEditor/utils/listEditorLoader.js.map +1 -1
  469. package/dist/domains/listEditor/utils/resolveCompactText.js.map +1 -1
  470. package/dist/domains/log/api/logApi.d.ts +2 -3
  471. package/dist/domains/log/api/logApi.js.map +1 -1
  472. package/dist/domains/log/components/ALogDatatable.js.map +1 -1
  473. package/dist/domains/log/components/ALogDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  474. package/dist/domains/log/components/ALogDetailView.js.map +1 -1
  475. package/dist/domains/log/components/ALogDetailView.vue.d.ts +1 -1
  476. package/dist/domains/log/components/ALogDetailView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  477. package/dist/domains/log/components/ALogFilter.js.map +1 -1
  478. package/dist/domains/log/components/ALogFilter.vue_vue_type_script_setup_true_lang.js.map +1 -1
  479. package/dist/domains/log/components/ALogListView.js.map +1 -1
  480. package/dist/domains/log/components/ALogListView.vue.d.ts +1 -1
  481. package/dist/domains/log/components/ALogListView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  482. package/dist/domains/log/composables/logActions.d.ts +4 -5
  483. package/dist/domains/log/composables/logActions.js.map +1 -1
  484. package/dist/domains/log/composables/logType.d.ts +6 -7
  485. package/dist/domains/log/composables/logType.js.map +1 -1
  486. package/dist/domains/log/filter/logFilter.d.ts +8 -11
  487. package/dist/domains/log/filter/logFilter.js.map +1 -1
  488. package/dist/domains/permission/components/APermissionEditor.js.map +1 -1
  489. package/dist/domains/permission/components/APermissionEditor.vue.d.ts +4 -4
  490. package/dist/domains/permission/components/APermissionEditor.vue_vue_type_script_setup_true_lang.js.map +1 -1
  491. package/dist/domains/permission/composables/permissionActions.d.ts +3 -6
  492. package/dist/domains/permission/composables/permissionActions.js.map +1 -1
  493. package/dist/domains/permission/config/api/permissionConfigApi.d.ts +2 -2
  494. package/dist/domains/permission/config/api/permissionConfigApi.js.map +1 -1
  495. package/dist/domains/permission/config/composables/permissionConfigActions.d.ts +3 -7
  496. package/dist/domains/permission/config/composables/permissionConfigActions.js.map +1 -1
  497. package/dist/domains/permission/config/store/permissionConfigStore.d.ts +2 -4
  498. package/dist/domains/permission/config/store/permissionConfigStore.js.map +1 -1
  499. package/dist/domains/permission/group/api/permissionGroupApi.d.ts +8 -10
  500. package/dist/domains/permission/group/api/permissionGroupApi.js.map +1 -1
  501. package/dist/domains/permission/group/components/APermissionGroupDatatable.js.map +1 -1
  502. package/dist/domains/permission/group/components/APermissionGroupDatatable.vue.d.ts +12 -10
  503. package/dist/domains/permission/group/components/APermissionGroupDatatable.vue_vue_type_script_setup_true_lang.js.map +1 -1
  504. package/dist/domains/permission/group/components/APermissionGroupDetail.js.map +1 -1
  505. package/dist/domains/permission/group/components/APermissionGroupDetail.vue.d.ts +21 -22
  506. package/dist/domains/permission/group/components/APermissionGroupDetail.vue_vue_type_script_setup_true_lang.js.map +1 -1
  507. package/dist/domains/permission/group/components/APermissionGroupManage.js.map +1 -1
  508. package/dist/domains/permission/group/components/APermissionGroupManage.vue.d.ts +21 -22
  509. package/dist/domains/permission/group/components/APermissionGroupManage.vue_vue_type_script_setup_true_lang.js.map +1 -1
  510. package/dist/domains/permission/group/composables/cachedPermissionGroups.js.map +1 -1
  511. package/dist/domains/permission/group/composables/permissionGroupActions.d.ts +6 -8
  512. package/dist/domains/permission/group/composables/permissionGroupActions.js.map +1 -1
  513. package/dist/domains/permission/group/composables/permissionGroupValidations.d.ts +2 -3
  514. package/dist/domains/permission/group/composables/permissionGroupValidations.js.map +1 -1
  515. package/dist/domains/permission/group/filter/permissionGroupFilter.d.ts +2 -3
  516. package/dist/domains/permission/group/filter/permissionGroupFilter.js.map +1 -1
  517. package/dist/domains/permission/group/store/permissionGroupStore.d.ts +3 -6
  518. package/dist/domains/permission/group/store/permissionGroupStore.js.map +1 -1
  519. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocomplete.js.map +1 -1
  520. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  521. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocompleteWithMinimal.js.map +1 -1
  522. package/dist/domains/remoteAutocomplete/components/AFilterRemoteAutocompleteWithMinimal.vue_vue_type_script_setup_true_lang.js.map +1 -1
  523. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocomplete.js.map +1 -1
  524. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocomplete.vue_vue_type_script_setup_true_lang.js.map +1 -1
  525. package/dist/domains/remoteAutocomplete/components/AFormRemoteAutocompleteWithCached.vue.d.ts +5 -3
  526. package/dist/domains/remoteAutocomplete/composables/createRemoteAutocomplete.d.ts +11 -13
  527. package/dist/domains/remoteAutocomplete/composables/createRemoteAutocomplete.js.map +1 -1
  528. package/dist/domains/subjectSelect/components/AFilterWrapperSubjectSelect.vue.d.ts +13 -11
  529. package/dist/domains/subjectSelect/components/ASubjectSelect.js.map +1 -1
  530. package/dist/domains/subjectSelect/components/ASubjectSelect.vue_vue_type_script_setup_true_lang.js.map +1 -1
  531. package/dist/domains/subjectSelect/composables/useSubjectSelect.js +53 -51
  532. package/dist/domains/subjectSelect/composables/useSubjectSelect.js.map +1 -1
  533. package/dist/domains/system/appShell/components/AActionbar.vue.d.ts +7 -5
  534. package/dist/domains/system/appShell/components/ALayoutSwitch.js.map +1 -1
  535. package/dist/domains/system/appShell/components/ALayoutSwitch.vue.d.ts +7 -5
  536. package/dist/domains/system/appShell/components/ALayoutSwitch.vue_vue_type_script_setup_true_lang.js.map +1 -1
  537. package/dist/domains/system/appShell/composables/teleportSlot.d.ts +0 -1
  538. package/dist/domains/system/appShell/composables/teleportSlot.js.map +1 -1
  539. package/dist/domains/system/components/AAlerts.js.map +1 -1
  540. package/dist/domains/system/components/AAlerts.vue_vue_type_script_setup_true_lang.js.map +1 -1
  541. package/dist/domains/system/composables/alerts.js.map +1 -1
  542. package/dist/domains/system/composables/breadcrumbs.d.ts +3 -3
  543. package/dist/domains/system/composables/breadcrumbs.js.map +1 -1
  544. package/dist/domains/system/composables/languageSettings.js.map +1 -1
  545. package/dist/domains/system/composables/loginStatus.js.map +1 -1
  546. package/dist/domains/system/composables/navigationError.d.ts +6 -8
  547. package/dist/domains/system/composables/navigationError.js.map +1 -1
  548. package/dist/domains/system/composables/pageNavigation.d.ts +9 -10
  549. package/dist/domains/system/composables/pageNavigation.js.map +1 -1
  550. package/dist/domains/system/composables/recordActions.d.ts +14 -22
  551. package/dist/domains/system/composables/recordActions.js.map +1 -1
  552. package/dist/domains/system/composables/recordPage.d.ts +23 -38
  553. package/dist/domains/system/composables/recordPage.js.map +1 -1
  554. package/dist/domains/system/composables/routeHistory.d.ts +4 -5
  555. package/dist/domains/system/composables/routeHistory.js.map +1 -1
  556. package/dist/domains/system/composables/sentry.js.map +1 -1
  557. package/dist/domains/system/composables/useDebugFeatures.d.ts +3 -6
  558. package/dist/domains/system/composables/useDebugFeatures.js.map +1 -1
  559. package/dist/domains/system/store/datatablePageStore.d.ts +8 -1
  560. package/dist/domains/system/store/datatablePageStore.js +10 -3
  561. package/dist/domains/system/store/datatablePageStore.js.map +1 -1
  562. package/dist/domains/system/systemBar/components/ASystemBar.js.map +1 -1
  563. package/dist/domains/system/systemBar/components/ASystemBar.vue_vue_type_script_setup_true_lang.js.map +1 -1
  564. package/dist/domains/system/systemBar/utils/appReload.d.ts +5 -5
  565. package/dist/domains/system/systemBar/utils/appReload.js.map +1 -1
  566. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.js.map +1 -1
  567. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.vue.d.ts +2 -3
  568. package/dist/domains/ui/buttons/action/components/AActionCloseButtonHistory.vue_vue_type_script_setup_true_lang.js.map +1 -1
  569. package/dist/domains/ui/buttons/action/components/AActionDeleteButton.js.map +1 -1
  570. package/dist/domains/ui/buttons/action/components/AActionDeleteButton.vue_vue_type_script_setup_true_lang.js.map +1 -1
  571. package/dist/domains/ui/buttons/components/ABtnSplit.vue.d.ts +9 -7
  572. package/dist/domains/ui/components/AAvatarColorPicker.js.map +1 -1
  573. package/dist/domains/ui/components/AAvatarColorPicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  574. package/dist/domains/ui/components/ACard.js.map +1 -1
  575. package/dist/domains/ui/components/ACard.vue.d.ts +7 -3
  576. package/dist/domains/ui/components/ACard.vue_vue_type_script_setup_true_lang.js +6 -2
  577. package/dist/domains/ui/components/ACard.vue_vue_type_script_setup_true_lang.js.map +1 -1
  578. package/dist/domains/ui/components/ACardLoader.js.map +1 -1
  579. package/dist/domains/ui/components/ACardLoader.vue.d.ts +1 -0
  580. package/dist/domains/ui/components/ACardLoader.vue_vue_type_script_setup_true_lang.js +13 -7
  581. package/dist/domains/ui/components/ACardLoader.vue_vue_type_script_setup_true_lang.js.map +1 -1
  582. package/dist/domains/ui/components/AChipNoLink.vue.d.ts +5 -3
  583. package/dist/domains/ui/components/ACopyText.vue.d.ts +9 -7
  584. package/dist/domains/ui/components/ACreateDialog.js.map +1 -1
  585. package/dist/domains/ui/components/ACreateDialog.vue.d.ts +11 -9
  586. package/dist/domains/ui/components/ACreateDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  587. package/dist/domains/ui/components/ADialogToolbar.vue.d.ts +5 -3
  588. package/dist/domains/ui/components/ARow.vue.d.ts +5 -3
  589. package/dist/domains/ui/components/ATimeTrackingFields.js.map +1 -1
  590. package/dist/domains/ui/components/ATimeTrackingFields.vue_vue_type_script_setup_true_lang.js.map +1 -1
  591. package/dist/domains/ui/components/AUserAndTimeTrackingFields.js.map +1 -1
  592. package/dist/domains/ui/components/AUserAndTimeTrackingFields.vue.d.ts +3 -5
  593. package/dist/domains/ui/components/AUserAndTimeTrackingFields.vue_vue_type_script_setup_true_lang.js.map +1 -1
  594. package/dist/domains/ui/datetime/components/ADatetimePicker.js +1 -1
  595. package/dist/domains/ui/datetime/components/ADatetimePicker.js.map +1 -1
  596. package/dist/domains/ui/datetime/components/ADatetimePicker.vue.d.ts +5 -3
  597. package/dist/domains/ui/datetime/components/ADatetimePicker.vue_vue_type_script_setup_true_lang.js.map +1 -1
  598. package/dist/domains/ui/file/components/AFileDropzone.js.map +1 -1
  599. package/dist/domains/ui/file/components/AFileDropzone.vue.d.ts +1 -1
  600. package/dist/domains/ui/file/components/AFileDropzone.vue_vue_type_script_setup_true_lang.js.map +1 -1
  601. package/dist/domains/ui/file/components/AFileInput.js.map +1 -1
  602. package/dist/domains/ui/file/components/AFileInput.vue.d.ts +9 -7
  603. package/dist/domains/ui/file/components/AFileInput.vue_vue_type_script_setup_true_lang.js.map +1 -1
  604. package/dist/domains/ui/file/components/AFileInputDialog.js.map +1 -1
  605. package/dist/domains/ui/file/components/AFileInputDialog.vue.d.ts +9 -7
  606. package/dist/domains/ui/file/components/AFileInputDialog.vue_vue_type_script_setup_true_lang.js.map +1 -1
  607. package/dist/domains/ui/file/composables/dropzone.js.map +1 -1
  608. package/dist/domains/ui/file/composables/formatAndSizeCheck.js.map +1 -1
  609. package/dist/domains/ui/view/components/AGenericView.vue.d.ts +7 -5
  610. package/dist/domains/ui/view/components/ALoginView.js +1 -1
  611. package/dist/domains/ui/view/components/ALoginView.js.map +1 -1
  612. package/dist/domains/ui/view/components/ALoginView.vue.d.ts +5 -3
  613. package/dist/domains/ui/view/components/ALoginView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  614. package/dist/domains/ui/view/components/ALogoutView.js.map +1 -1
  615. package/dist/domains/ui/view/components/ALogoutView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  616. package/dist/domains/ui/view/components/ANotFoundView.js.map +1 -1
  617. package/dist/domains/ui/view/components/ANotFoundView.vue_vue_type_script_setup_true_lang.js.map +1 -1
  618. package/dist/domains/unsavedGuard/composables/useUnsavedChangesGuard.d.ts +6 -7
  619. package/dist/domains/unsavedGuard/composables/useUnsavedChangesGuard.js.map +1 -1
  620. package/dist/lib.d.ts +2 -2
  621. package/dist/plugins/commonVuetifyConfig.d.ts +3 -3
  622. package/dist/plugins/commonVuetifyConfig.js.map +1 -1
  623. package/dist/plugins/i18n.d.ts +4 -5
  624. package/dist/plugins/i18n.js.map +1 -1
  625. package/dist/plugins/pluginOptions.d.ts +4 -2
  626. package/dist/plugins/pluginOptions.js.map +1 -1
  627. package/dist/plugins/webfontloader.js.map +1 -1
  628. package/dist/shared/error/AnzuApiCancelledError.d.ts +5 -8
  629. package/dist/shared/error/AnzuApiCancelledError.js.map +1 -1
  630. package/dist/shared/error/AnzuError.d.ts +3 -5
  631. package/dist/shared/error/AnzuError.js.map +1 -1
  632. package/dist/shared/error/AuthUnavailableError.d.ts +3 -3
  633. package/dist/shared/error/AuthUnavailableError.js.map +1 -1
  634. package/dist/shared/error/isInCauseChain.d.ts +2 -2
  635. package/dist/shared/error/isInCauseChain.js.map +1 -1
  636. package/dist/shared/types/UserAndTimeTracking.d.ts +5 -5
  637. package/dist/shared/types/Validation.d.ts +4 -5
  638. package/dist/shared/types/common.d.ts +1 -3
  639. package/dist/shared/types/globalComponents.d.ts +5 -6
  640. package/dist/shared/utils/common.js.map +1 -1
  641. package/dist/shared/utils/datetime.d.ts +0 -1
  642. package/dist/shared/utils/datetime.js.map +1 -1
  643. package/dist/shared/utils/datetimePickerValue.d.ts +4 -7
  644. package/dist/shared/utils/datetimePickerValue.js.map +1 -1
  645. package/dist/shared/utils/development.d.ts +3 -3
  646. package/dist/shared/utils/development.js.map +1 -1
  647. package/dist/shared/utils/envConfig.d.ts +4 -4
  648. package/dist/shared/utils/envConfig.js.map +1 -1
  649. package/dist/shared/utils/json.d.ts +1 -1
  650. package/dist/shared/utils/json.js.map +1 -1
  651. package/dist/shared/utils/userAndTimeTracking.d.ts +5 -7
  652. package/dist/shared/utils/userAndTimeTracking.js.map +1 -1
  653. package/dist/shared/validators/vuelidate/common/useValidateHexColor.d.ts +3 -5
  654. package/dist/shared/validators/vuelidate/common/useValidateHexColor.js.map +1 -1
  655. package/dist/testing/appShell.d.ts +11 -11
  656. package/dist/testing/appShell.js.map +1 -1
  657. package/dist/testing/closeButtons.d.ts +9 -11
  658. package/dist/testing/closeButtons.js.map +1 -1
  659. package/dist/testing/declaredDependencies.d.ts +7 -7
  660. package/dist/testing/declaredDependencies.js.map +1 -1
  661. package/dist/testing/generatedRoutes.d.ts +6 -11
  662. package/dist/testing/generatedRoutes.js.map +1 -1
  663. package/dist/testing/routeHistory.d.ts +5 -12
  664. package/dist/testing/routeHistory.js.map +1 -1
  665. package/dist/testing/sortableLists.d.ts +16 -21
  666. package/dist/testing/sortableLists.js.map +1 -1
  667. package/dist/testing/typedRouter.d.ts +0 -1
  668. package/dist/testing/typedRouter.js.map +1 -1
  669. package/package.json +27 -27
  670. package/src/eslint/adminConfig.mjs +19 -27
  671. package/src/eslint/globalComponentNames.mjs +3 -4
  672. package/src/eslint/oxlint.mjs +7 -20
  673. package/src/eslint/plugin.d.mts +2 -4
  674. package/src/eslint/plugin.mjs +18 -34
  675. package/src/eslint/validRouteName.mjs +6 -7
  676. package/src/vite/devWatch.mjs +30 -43
  677. package/src/vite/index.d.mts +5 -5
  678. package/src/vite/sentry.mjs +7 -12
  679. package/src/vite/sourcemaps.mjs +4 -8
@@ -1 +1 @@
1
- {"version":3,"file":"useNestedListEditorController.js","names":["flatten","out","walk","n","nodes","tree","walkNodes","visit","useNestedListEditorController","keyField","options","keyOf","item","keyFieldName","positionOpt","managedPosition","positionField","positionMultiplier","parentField","model","computed","v","useNestedListEditor","action","items","viewItems","dirtyExclude","toValue","normalize","copy","f","baselineHashes","ref","baselineParents","baselineTree","cloneTree","cloneDeep","captureBaseline","hashes","parents","key","parentKey","t","watch","submitted","registeredValidity","reactive","isItemDirty","saved","baselineTreeRow","node","baseHash","addedBaseline","editedKeys","deletedKeys","live","base","stale","revived","isRowEdited","hit","treeHasKey","found","unsavedKeys","isUnsaved","hasPendingMove","hasUnsaved","unsavedCount","keys","resolveValidity","registered","invalidKeys","hasErrors","rowState","invalid","editing","warning","validateAll","buildPayload","row","getPayload","getChanges","added","updated","moved","reparented","payload","byKey","baseParent","nowParent","deleted","commit","source","normalized","next","previous","nextListEditorTempId","acceptRows","wanted","detach","i","baseSiblings","siblings","at","index","seen","s","reset","restore","addItem","data","hint","addAfter","afterKey","addChild","updateItem","markDirty","dropFromBaseline","removed","opts","targetParentKey","targetIndex","isValid"],"sources":["../../../../src/domains/listEditor/composables/useNestedListEditorController.ts"],"sourcesContent":["import {\n computed,\n reactive,\n ref,\n toValue,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n type ShallowUnwrapRef,\n} from 'vue'\nimport type {\n ListEditorKey,\n ListEditorValidationState,\n NestedPositionHint,\n NestedTree,\n NestedTreeNode,\n} from '@/domains/listEditor/types/listEditorTypes'\nimport { useNestedListEditor, type NestedViewItem } from '@/domains/listEditor/composables/useNestedListEditor'\nimport type {\n GetKey,\n ListEditorValidationResult,\n PositionOption,\n PositionStrategy,\n} from '@/domains/listEditor/composables/useListEditorController'\nimport { nextListEditorTempId } from '@/domains/listEditor/utils/tempId'\nimport { cloneDeep } from '@/shared/utils/common'\n\nexport type { ListEditorValidationResult, GetKey, PositionOption, PositionStrategy }\n\n/** Flattened ordered row carrying its resolved key (for change-sets + payload). */\nexport interface NestedListEditorChanges<TItem> {\n added: TItem[]\n updated: TItem[]\n moved: TItem[]\n deleted: TItem[]\n /**\n * Rows whose parent changed since the last commit (BUG-13 — persisted even\n * when the position number is unchanged).\n */\n reparented: TItem[]\n}\n\nexport interface UseNestedListEditorControllerOptions<TItem extends Record<string, any>> {\n /** Read the live tree (the editor's v-model, or a consumer store getter). */\n get: () => NestedTree<TItem>\n /** Write the tree back. */\n set: (tree: NestedTree<TItem>) => void\n /** New-row factory. Optional for read-only / no-add trees. Should mint a stable temp id. */\n factory?: () => TItem\n /** Stable row identity. Default `'id'`. Never point this at the position field. */\n getKey?: GetKey<TItem>\n /** Managed order field. Default `'position'`. `false` opts out of position management. */\n position?: PositionOption<TItem>\n /** Parent-key field written onto reparented rows. Default `'parent'`. */\n parentField?: string\n /** Maximum nesting depth (1-based). Enforced by indent/outdent/moveTo. */\n maxDepth: number\n /**\n * Extra top-level fields to drop from the dirty content-hash (position +\n * parent are always dropped). Same purpose as the flat controller — a child\n * collection tracked by a separate editor shouldn't flip its owner amber.\n * Accepts a getter/ref so a `computed` set is honoured reactively.\n */\n dirtyExclude?: MaybeRefOrGetter<string[]>\n /** Per-row validity — `true` = valid. Drives the red rail + `hasErrors`. */\n validate?: (item: TItem) => ListEditorValidationResult\n /** Custom dirty predicate (override the default `meta.dirty ∪ content-diff`). */\n isDirty?: (current: TItem, saved: TItem | undefined) => boolean\n /** Custom save payload (overrides `getPayload`). Receives the flattened ordered rows. */\n payload?: (items: TItem[]) => TItem[]\n /** Resolve a saved row's key on commit (default: existing key, else mint a temp id). */\n commitKey?: (saved: TItem, previous: TItem | undefined) => ListEditorKey\n /** Normalize the server tree before it becomes the new baseline on commit. */\n normalizeSaved?: (saved: NestedTree<TItem>) => NestedTree<TItem>\n}\n\n/**\n * Tree-shaped state controller for the nested list editor (v2). A superset of\n * the flat `ListEditorHandle`: same dirty/validate/commit/reset semantics, but\n * the row set is a flattened ordered projection of a `NestedTree` and the\n * mutators are tree ops (indent / outdent / moveTo / addChild …) delegated to\n * `useNestedListEditor`. Each flattened payload row carries its resolved\n * `position` and parent key written onto it.\n */\nexport interface NestedListEditorHandle<TItem extends Record<string, any>> {\n /** Flattened ordered rows (depth-first), matching the rendered order. */\n items: ComputedRef<TItem[]>\n /** Tree view rows (key/index/raw/depth/parent…), as consumed by the renderer. */\n viewItems: ComputedRef<NestedViewItem<TItem>[]>\n hasUnsaved: ComputedRef<boolean>\n /** Count of distinct unconfirmed changes (added/edited/moved/reparented rows + deferred deletions). */\n unsavedCount: ComputedRef<number>\n hasErrors: ComputedRef<boolean>\n invalidKeys: ComputedRef<Set<ListEditorKey>>\n /** Amber: is this row added / edited / moved / reparented since the last commit? */\n isUnsaved: (key: ListEditorKey) => boolean\n /** Red rail (gated): 'invalid' only once the row is unsaved or `validateAll()` ran. */\n rowState: (item: TItem, key: ListEditorKey, editing?: boolean) => ListEditorValidationState\n /** Force-show all invalid rows + return whether the tree is valid. The save guard. */\n validateAll: () => boolean\n /** Flattened ordered array (each row carrying its resolved position + parent key) for a full-DTO save. */\n getPayload: () => TItem[]\n /** Change-set for partial-save endpoints (added/updated/moved/deleted/reparented), keyed. */\n getChanges: () => NestedListEditorChanges<TItem>\n /** Adopt the saved tree as the new baseline; backfill keys; clear dirty/submitted. */\n commit: (saved?: NestedTree<TItem>) => void\n /** Adopt only these rows as saved (a server-confirmed single-row op); other pending work stays. */\n acceptRows: (keys: ListEditorKey[]) => void\n /** Discard unsaved edits back to the last committed baseline (or a given tree). */\n reset: (tree?: NestedTree<TItem>) => void\n\n // Tree mutations — delegate to useNestedListEditor (which carries BUG-13).\n addItem: (item?: TItem, hint?: NestedPositionHint) => void\n addAfter: (afterKey: ListEditorKey, item?: TItem, childrenAllowed?: boolean) => void\n addChild: (parentKey: ListEditorKey, item?: TItem, childrenAllowed?: boolean) => void\n updateItem: (key: ListEditorKey, data: TItem, markDirty?: boolean) => void\n deleteItem: (key: ListEditorKey, opts?: { trackDeleted?: boolean; renumber?: boolean }) => void\n restoreDeleted: (key: ListEditorKey) => void\n moveUp: (key: ListEditorKey) => boolean\n moveDown: (key: ListEditorKey) => boolean\n moveTop: (key: ListEditorKey) => boolean\n moveBottom: (key: ListEditorKey) => boolean\n indent: (key: ListEditorKey) => boolean\n outdent: (key: ListEditorKey) => boolean\n moveTo: (key: ListEditorKey, targetParentKey: ListEditorKey | null, targetIndex: number) => boolean\n recalculatePositions: () => void\n\n /** Escape hatch: a row form (e.g. vuelidate) reports its own validity instead of `validate`. */\n registerValidity: (key: ListEditorKey, isValid: () => boolean) => () => void\n\n // Internal handles the editor needs to drive the tree directly (find a node,\n // subtree depth for drag, the underlying `editor.moveTo` returning the tree).\n findNode: (key: ListEditorKey) => {\n node: NestedTreeNode<TItem> | null\n parent: NestedTreeNode<TItem> | null\n }\n calculateSubtreeDepth: (node: NestedTreeNode<TItem>) => number\n}\n\n/**\n * Consumer-facing shape of a nested-list-editor handle read through a template/function ref — Vue's\n * `expose` proxy unwraps the exposed refs, so read `handle.hasUnsaved` (a boolean), not\n * `handle.hasUnsaved.value`. See {@link ExposedListEditorHandle}.\n */\nexport type ExposedNestedListEditorHandle<TItem extends Record<string, any>> = ShallowUnwrapRef<\n NestedListEditorHandle<TItem>\n>\n\n/** What `ANestedSortableListEditor` exposes on top of the controller handle. */\nexport interface NestedSortableListEditorExtras {\n /**\n * Runs a tree mutation the server has already made (a row created through a dialog) and adopts as\n * saved only the rows it added or edited, plus `keys`. Siblings it only renumbered and other pending\n * work stay unsaved (the server may not have renumbered them), and so does the position of a created\n * row the op renumbered. `commit()` would adopt the whole tree instead.\n */\n acceptChanges: (op: () => void, keys?: ListEditorKey[]) => void\n enterReorderMode: () => void\n cancelReorderMode: () => void\n applyReorder: () => Promise<void>\n expand: (id: ListEditorKey) => void\n collapse: (id: ListEditorKey) => void\n toggleExpand: (id: ListEditorKey) => void\n expandDetail: (id: ListEditorKey) => void\n collapseDetail: (id: ListEditorKey) => void\n}\n\n/** `ANestedSortableListEditor` read through a template ref: the unwrapped handle and its extras. */\nexport type ExposedNestedSortableListEditorHandle<TItem extends Record<string, any>> =\n ExposedNestedListEditorHandle<TItem> & NestedSortableListEditorExtras\n\nconst flatten = <TItem extends Record<string, any>>(tree: NestedTree<TItem>): TItem[] => {\n const out: TItem[] = []\n const walk = (nodes: NestedTreeNode<TItem>[]) => {\n for (const n of nodes) {\n out.push(n.data)\n if (n.children && n.children.length) walk(n.children)\n }\n }\n walk(tree.children)\n return out\n}\n\nconst walkNodes = <TItem extends Record<string, any>>(\n tree: NestedTree<TItem>,\n visit: (node: NestedTreeNode<TItem>) => void\n): void => {\n const walk = (nodes: NestedTreeNode<TItem>[]) => {\n for (const n of nodes) {\n visit(n)\n if (n.children && n.children.length) walk(n.children)\n }\n }\n walk(tree.children)\n}\n\nexport function useNestedListEditorController<TItem extends Record<string, any>>(\n options: UseNestedListEditorControllerOptions<TItem>\n): NestedListEditorHandle<TItem> {\n const keyField = (typeof options.getKey === 'function' ? null : (options.getKey ?? 'id')) as keyof TItem | null\n const keyOf = (item: TItem): ListEditorKey =>\n typeof options.getKey === 'function' ? options.getKey(item) : (item[keyField as keyof TItem] as ListEditorKey)\n const keyFieldName = (keyField ?? 'id') as string\n\n const positionOpt = options.position ?? 'position'\n const managedPosition = positionOpt !== false\n const positionField = (\n typeof positionOpt === 'object' ? positionOpt.field : positionOpt === false ? 'position' : positionOpt\n ) as string\n const positionMultiplier = typeof positionOpt === 'object' && positionOpt.multiplier ? positionOpt.multiplier : 1\n const parentField = options.parentField ?? 'parent'\n\n // Two-way bridge to the consumer's tree: the composable's per-op\n // `model.value = cloned` writes back via `set`, the getter re-reads live edits.\n const model = computed<NestedTree<TItem>>({\n get: () => options.get(),\n set: (v) => options.set(v),\n }) as unknown as Ref<NestedTree<TItem>>\n\n const tree = useNestedListEditor<TItem>(model, {\n keyField: keyFieldName,\n // Pass the controller's keyOf so tree ops resolve keys identically to\n // invalidKeys/dirty tracking — supports a function get-key, not just a field.\n getKey: keyOf,\n positionField,\n parentField,\n positionMultiplier,\n managedPosition,\n positionStrategyFor: (action) =>\n (typeof positionOpt === 'object' && (positionOpt.strategyOverrides?.[action] ?? positionOpt.strategy)) ||\n 'renumber',\n maxDepth: options.maxDepth,\n })\n\n const items = computed<TItem[]>(() => flatten(options.get()))\n const viewItems = tree.viewItems\n\n // Baseline = last committed snapshot. `hashes` powers content-diff dirty\n // (position + parent excluded so a reorder/reparent never lights up via the\n // content hash — meta.dirty / the reparented set carries those instead).\n const dirtyExclude = computed<string[]>(() => toValue(options.dirtyExclude) ?? [])\n const normalize = (item: TItem): string => {\n const copy = { ...item } as Record<string, unknown>\n if (managedPosition) delete copy[positionField]\n delete copy[parentField]\n for (const f of dirtyExclude.value) delete copy[f]\n return JSON.stringify(copy)\n }\n const baselineHashes = ref(new Map<ListEditorKey, string>()) as Ref<Map<ListEditorKey, string>>\n // Parent-key per row at baseline — drives reparented detection (BUG-13).\n const baselineParents = ref(new Map<ListEditorKey, ListEditorKey | null>()) as Ref<\n Map<ListEditorKey, ListEditorKey | null>\n >\n const baselineTree = ref<NestedTree<TItem> | null>(null) as Ref<NestedTree<TItem> | null>\n\n const cloneTree = (t: NestedTree<TItem>): NestedTree<TItem> => cloneDeep(t)\n\n const captureBaseline = (t: NestedTree<TItem>) => {\n const hashes = new Map<ListEditorKey, string>()\n const parents = new Map<ListEditorKey, ListEditorKey | null>()\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n for (const n of nodes) {\n const key = keyOf(n.data)\n hashes.set(key, normalize(n.data))\n parents.set(key, parentKey)\n if (n.children && n.children.length) walk(n.children, key)\n }\n }\n walk(t.children, null)\n baselineHashes.value = hashes\n baselineParents.value = parents\n baselineTree.value = cloneTree(t)\n }\n captureBaseline(options.get())\n // Re-hash when the excluded-field set changes; `sync` so baseline + live\n // normalize() never disagree mid-flush. (Mirrors the flat controller.)\n watch(\n dirtyExclude,\n () => {\n if (!baselineTree.value) return\n const hashes = new Map<ListEditorKey, string>()\n walkNodes(baselineTree.value, (n) => hashes.set(keyOf(n.data), normalize(n.data)))\n baselineHashes.value = hashes\n },\n { flush: 'sync' }\n )\n\n const submitted = ref(false)\n // Reactive so a row form (re)registering its validity re-runs invalidKeys/rowState.\n const registeredValidity = reactive(new Map<ListEditorKey, () => boolean>())\n\n // Amber = added OR content-edited OR reparented (vs baseline). Position is\n // excluded, so a displaced sibling's pure renumber is NOT amber (matches the flat\n // editor + the \"only the actively-moved subtree lights up\" UX); BUG-13 adds the\n // parent-changed signal so a reparent registers even at an unchanged position\n // number. `getChanges().moved` reads meta.dirty, so displaced siblings' new\n // positions are still persisted; `hasPendingMove` (below) feeds the leave guard.\n const isItemDirty = (node: NestedTreeNode<TItem>, key: ListEditorKey, parentKey: ListEditorKey | null): boolean => {\n if (options.isDirty) {\n const saved = baselineTreeRow(key)\n return options.isDirty(node.data, saved)\n }\n const baseHash = baselineHashes.value.get(key)\n if (baseHash === undefined) return true // added\n if (baseHash !== normalize(node.data)) return true // content-edited (pos/parent excluded)\n // Reparented vs baseline (BUG-13).\n if (baselineParents.value.has(key)) {\n const baseParent = baselineParents.value.get(key) ?? null\n if ((baseParent ?? null) !== (parentKey ?? null)) return true\n }\n return false\n }\n\n // `addedBaseline` = first-seen content hash of each ADDED node; `editedKeys` = STICKY set of\n // nodes whose content has since diverged. Gates the validation rail on \"has this row been edited\"\n // rather than just \"is it unsaved\" (sticky like vuelidate `$dirty`) — mirrors the flat controller.\n const addedBaseline = ref(new Map<ListEditorKey, string>()) as Ref<Map<ListEditorKey, string>>\n const editedKeys = ref(new Set<ListEditorKey>()) as Ref<Set<ListEditorKey>>\n // Deferred-deletion tombstones (baseline keys removed but not yet saved). Immediate deletes skip\n // this so they don't read as unsaved. Drives hasUnsaved / unsavedCount / getChanges().deleted.\n const deletedKeys = ref(new Set<ListEditorKey>()) as Ref<Set<ListEditorKey>>\n watch(\n () => options.get(),\n (tree) => {\n const live = new Set<ListEditorKey>()\n walkNodes(tree, (n) => {\n const key = keyOf(n.data)\n live.add(key)\n if (!baselineHashes.value.has(key) && !addedBaseline.value.has(key)) {\n addedBaseline.value.set(key, normalize(n.data))\n }\n if (!editedKeys.value.has(key)) {\n const base = baselineHashes.value.get(key) ?? addedBaseline.value.get(key)\n if (base !== undefined && base !== normalize(n.data)) editedKeys.value.add(key)\n }\n })\n const stale: ListEditorKey[] = []\n for (const key of addedBaseline.value.keys()) if (!live.has(key)) stale.push(key)\n for (const key of stale) addedBaseline.value.delete(key)\n // A tombstoned key that becomes live again (re-add before save) drops its tombstone.\n const revived: ListEditorKey[] = []\n for (const key of deletedKeys.value) if (live.has(key)) revived.push(key)\n for (const key of revived) deletedKeys.value.delete(key)\n },\n { immediate: true, deep: true }\n )\n\n const isRowEdited = (key: ListEditorKey): boolean => editedKeys.value.has(key)\n\n const baselineTreeRow = (key: ListEditorKey): TItem | undefined => {\n if (!baselineTree.value) return undefined\n let hit: TItem | undefined\n walkNodes(baselineTree.value, (n) => {\n if (hit === undefined && keyOf(n.data) === key) hit = n.data\n })\n return hit\n }\n\n const treeHasKey = (key: ListEditorKey): boolean => {\n let found = false\n walkNodes(options.get(), (n) => {\n if (!found && keyOf(n.data) === key) found = true\n })\n return found\n }\n\n const unsavedKeys = computed<Set<ListEditorKey>>(() => {\n const out = new Set<ListEditorKey>()\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n for (const n of nodes) {\n const key = keyOf(n.data)\n if (isItemDirty(n, key, parentKey)) out.add(key)\n if (n.children && n.children.length) walk(n.children, key)\n }\n }\n walk(options.get().children, null)\n return out\n })\n\n const isUnsaved = (key: ListEditorKey): boolean => unsavedKeys.value.has(key)\n // A pure position reorder sets meta.dirty (recalculateSiblings) but is deliberately\n // kept OUT of per-row amber (only the actively-moved subtree lights up). It IS a\n // pending change though, so it must arm the leave guard — surface it as an aggregate\n // signal (M2b) that survives Apply and clears on commit (which resets meta.dirty).\n const hasPendingMove = computed<boolean>(() => {\n let found = false\n walkNodes(options.get(), (n) => {\n if (n.meta.dirty) found = true\n })\n return found\n })\n const hasUnsaved = computed<boolean>(\n () => unsavedKeys.value.size > 0 || deletedKeys.value.size > 0 || hasPendingMove.value\n )\n // Distinct unconfirmed changes = union of live dirty keys (added/edited/moved/reparented) and\n // deferred-deletion tombstones. Drives the \"N unconfirmed changes\" indicator.\n const unsavedCount = computed<number>(() => {\n const keys = new Set<ListEditorKey>(unsavedKeys.value)\n for (const key of deletedKeys.value) keys.add(key)\n return keys.size\n })\n\n const resolveValidity = (item: TItem, key: ListEditorKey): { invalid: boolean; warning: boolean } => {\n const registered = registeredValidity.get(key)\n if (registered) return { invalid: !registered(), warning: false }\n if (!options.validate) return { invalid: false, warning: false }\n const r = options.validate(item)\n if (typeof r === 'boolean') return { invalid: !r, warning: false }\n return { invalid: !r.valid, warning: r.valid && r.state === 'warning' }\n }\n\n const invalidKeys = computed<Set<ListEditorKey>>(() => {\n const out = new Set<ListEditorKey>()\n walkNodes(options.get(), (n) => {\n const key = keyOf(n.data)\n if (resolveValidity(n.data, key).invalid) out.add(key)\n })\n return out\n })\n const hasErrors = computed<boolean>(() => invalidKeys.value.size > 0)\n\n // Red rail for an invalid row that has been edited, is unsaved (added), or after a save attempt —\n // mirrors the flat controller. The editor suppresses the red while the row is the one being edited,\n // so a still-being-filled row reads amber and only goes red once collapsed. (QA 85050 batch 7)\n const rowState = (item: TItem, key: ListEditorKey, editing = false): ListEditorValidationState => {\n const { invalid, warning } = resolveValidity(item, key)\n // See flat controller: red when edited/unsaved/submitted, amber while being filled, red once\n // collapsed; a save attempt (`submitted`) reds it even while open. (QA 85050 batch 7)\n if (invalid) {\n if (submitted.value) return 'invalid'\n if (editing) return null\n return isRowEdited(key) || isUnsaved(key) ? 'invalid' : null\n }\n if (warning) return 'warning'\n return null\n }\n\n const validateAll = (): boolean => {\n submitted.value = true\n return invalidKeys.value.size === 0\n }\n\n // Flattened ordered payload; parent key is resolved from tree structure (so a\n // reparent is reflected even if the node's own parent field lagged).\n const buildPayload = (): TItem[] => {\n const out: TItem[] = []\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n for (const n of nodes) {\n const row = { ...n.data } as TItem\n ;(row as Record<string, unknown>)[parentField] = parentKey\n out.push(row)\n if (n.children && n.children.length) walk(n.children, keyOf(n.data))\n }\n }\n walk(options.get().children, null)\n return out\n }\n\n const getPayload = (): TItem[] => (options.payload ? options.payload(buildPayload()) : buildPayload())\n\n const getChanges = (): NestedListEditorChanges<TItem> => {\n const added: TItem[] = []\n const updated: TItem[] = []\n const moved: TItem[] = []\n const reparented: TItem[] = []\n const payload = buildPayload()\n const byKey = new Map<ListEditorKey, TItem>()\n for (const row of payload) byKey.set(keyOf(row), row)\n\n walkNodes(options.get(), (n) => {\n const key = keyOf(n.data)\n const row = byKey.get(key) ?? n.data\n const baseHash = baselineHashes.value.get(key)\n if (baseHash === undefined) {\n added.push(row)\n } else if (baseHash !== normalize(n.data)) {\n updated.push(row)\n }\n // meta.dirty without a content change => a move/reparent (position/parent\n // changed). recalculateSiblings + BUG-13 set meta.dirty on those.\n if (baseHash !== undefined && n.meta.dirty && baseHash === normalize(n.data)) {\n moved.push(row)\n }\n // Reparented = parent key differs from baseline (subset of moved, but\n // surfaced separately for partial-multi saves that re-link parents).\n if (baselineParents.value.has(key)) {\n const baseParent = baselineParents.value.get(key) ?? null\n const nowParent = (row as Record<string, unknown>)[parentField] as ListEditorKey | null\n if ((baseParent ?? null) !== (nowParent ?? null)) reparented.push(row)\n }\n })\n\n // Deferred deletions come from the tombstone set, so an IMMEDIATE delete (already persisted on the\n // backend, no tombstone) does not re-appear here as a local deleted change.\n const deleted: TItem[] = []\n for (const key of deletedKeys.value) {\n const row = baselineTreeRow(key)\n if (row !== undefined) deleted.push(row)\n }\n return { added, updated, moved, deleted, reparented }\n }\n\n const commit = (saved?: NestedTree<TItem>): void => {\n const source = saved ?? options.get()\n const normalized = options.normalizeSaved ? options.normalizeSaved(source) : source\n // Backfill missing keys + clear meta.dirty on the committed tree.\n const next = cloneTree(normalized)\n walkNodes(next, (n) => {\n const previous = baselineTreeRow(keyOf(n.data))\n const resolvedKey = options.commitKey ? options.commitKey(n.data, previous) : keyOf(n.data)\n if (resolvedKey === undefined || resolvedKey === null) {\n if (keyField) (n.data as Record<string, unknown>)[keyFieldName] = nextListEditorTempId()\n }\n n.meta.dirty = false\n })\n options.set(next)\n captureBaseline(next)\n addedBaseline.value = new Map()\n editedKeys.value = new Set()\n deletedKeys.value = new Set()\n submitted.value = false\n }\n\n // Adopt ONLY the given rows as saved (server-confirmed single-row ops); other pending work stays.\n // The saved tree follows along — reset() and getChanges().deleted read it: an accepted row takes its\n // current data and place there, an accepted key no longer in the tree leaves it.\n const acceptRows = (keys: ListEditorKey[]): void => {\n if (keys.length === 0) return\n const wanted = new Set(keys)\n const next = cloneTree(options.get())\n const hashes = new Map(baselineHashes.value)\n const parents = new Map(baselineParents.value)\n const base: NestedTree<TItem> = baselineTree.value ? cloneTree(baselineTree.value) : { ...next, children: [] }\n type Detached = { node: NestedTreeNode<TItem>; siblings: NestedTreeNode<TItem>[]; index: number }\n const detach = (nodes: NestedTreeNode<TItem>[], key: ListEditorKey): Detached | undefined => {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!\n if (keyOf(node.data) === key) return { node: nodes.splice(i, 1)[0]!, siblings: nodes, index: i }\n const found = node.children?.length ? detach(node.children, key) : undefined\n if (found) return found\n }\n return undefined\n }\n const baseSiblings = (parentKey: ListEditorKey | null): NestedTreeNode<TItem>[] | undefined => {\n if (parentKey === null) return base.children\n let hit: NestedTreeNode<TItem> | undefined\n walkNodes(base, (n) => {\n if (hit === undefined && keyOf(n.data) === parentKey) hit = n\n })\n if (!hit) return undefined\n if (!hit.children) hit.children = []\n return hit.children\n }\n const live = new Set<ListEditorKey>()\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n nodes.forEach((n, index) => {\n const key = keyOf(n.data)\n live.add(key)\n if (wanted.has(key)) {\n hashes.set(key, normalize(n.data))\n parents.set(key, parentKey)\n n.meta.dirty = false\n addedBaseline.value.delete(key)\n editedKeys.value.delete(key)\n const previous = detach(base.children, key)\n const saved = cloneDeep(n)\n // A row added without children allowed stays without them; a saved row keeps its saved children.\n saved.children = previous ? previous.node.children : n.children ? [] : undefined\n saved.meta = { ...saved.meta, dirty: false }\n const siblings = baseSiblings(parentKey)\n if (!siblings) {\n // The new parent is not in the saved tree (e.g. it was this row's own saved child, detached\n // with it): keep the row where it was saved rather than drop it and its children.\n if (previous) previous.siblings.splice(previous.index, 0, saved)\n } else {\n // After the nearest preceding sibling the saved tree knows, so pending rows don't skew it.\n let at = 0\n for (let i = index - 1; i >= 0; i--) {\n const seen = siblings.findIndex((s) => keyOf(s.data) === keyOf(nodes[i]!.data))\n if (seen !== -1) {\n at = seen + 1\n break\n }\n }\n siblings.splice(at, 0, saved)\n }\n }\n if (n.children && n.children.length) walk(n.children, key)\n })\n }\n walk(next.children, null)\n for (const key of wanted) {\n if (live.has(key)) continue\n hashes.delete(key)\n parents.delete(key)\n // Gone from the backend: no longer a pending deletion either.\n deletedKeys.value.delete(key)\n detach(base.children, key)\n }\n baselineHashes.value = hashes\n baselineParents.value = parents\n baselineTree.value = base\n options.set(next)\n }\n\n const reset = (t?: NestedTree<TItem>): void => {\n const restore = t ?? (baselineTree.value ? cloneTree(baselineTree.value) : options.get())\n options.set(restore)\n addedBaseline.value = new Map()\n editedKeys.value = new Set()\n deletedKeys.value = new Set()\n submitted.value = false\n }\n\n // --- Tree mutations (delegate to useNestedListEditor) -----------------------\n\n const addItem = (item?: TItem, hint?: NestedPositionHint): void => {\n const data = item ?? options.factory?.()\n if (data === undefined) return // no item + no factory (read-only) → no-op\n tree.addItem(data, hint)\n }\n const addAfter = (afterKey: ListEditorKey, item?: TItem, childrenAllowed = true): void => {\n const data = item ?? options.factory?.()\n if (data === undefined) return\n tree.addItem(data, { afterId: afterKey, childrenAllowed })\n }\n const addChild = (parentKey: ListEditorKey, item?: TItem, childrenAllowed = true): void => {\n const data = item ?? options.factory?.()\n if (data === undefined) return\n tree.addItem(data, { parentId: parentKey, childrenAllowed })\n }\n const updateItem = (key: ListEditorKey, data: TItem, markDirty = true): void => {\n tree.updateItem(key, data, markDirty)\n }\n // An immediate delete: the row is gone on the backend, and the editor removes it with its subtree, so\n // neither is part of the saved tree `reset()` restores any more.\n const dropFromBaseline = (key: ListEditorKey): void => {\n if (!baselineTree.value) return\n const base = cloneTree(baselineTree.value)\n const detach = (nodes: NestedTreeNode<TItem>[]): NestedTreeNode<TItem> | undefined => {\n for (let i = 0; i < nodes.length; i++) {\n if (keyOf(nodes[i]!.data) === key) return nodes.splice(i, 1)[0]\n const found = nodes[i]!.children?.length ? detach(nodes[i]!.children!) : undefined\n if (found) return found\n }\n return undefined\n }\n const removed = detach(base.children)\n if (!removed) return\n const hashes = new Map(baselineHashes.value)\n const parents = new Map(baselineParents.value)\n walkNodes({ ...base, children: [removed] }, (n) => {\n hashes.delete(keyOf(n.data))\n parents.delete(keyOf(n.data))\n })\n baselineHashes.value = hashes\n baselineParents.value = parents\n baselineTree.value = base\n }\n\n const deleteItem = (key: ListEditorKey, opts?: { trackDeleted?: boolean; renumber?: boolean }): void => {\n // A previously-saved row removed in deferred mode is tombstoned (counts as unsaved + reported in\n // getChanges().deleted). `trackDeleted: false` (immediate — already deleted on the backend) skips it.\n // `treeHasKey` guards against a phantom tombstone: an immediate delete removes the row in the\n // component's own handler (trackDeleted:false), then a consumer removing it again (acceptChanges\n // around deleteItem) re-calls deleteItem for the now-gone key — without the guard that second call\n // would tombstone a baseline row that is already deleted, surfacing a bogus unconfirmed change.\n if (baselineHashes.value.has(key) && opts?.trackDeleted !== false && treeHasKey(key)) {\n deletedKeys.value.add(key)\n } else if (baselineHashes.value.has(key) && treeHasKey(key)) {\n dropFromBaseline(key)\n }\n tree.deleteItem(key, { renumber: opts?.renumber })\n }\n\n const restoreDeleted = (key: ListEditorKey): void => {\n deletedKeys.value.delete(key)\n }\n const moveUp = (key: ListEditorKey): boolean => tree.moveUp(key) !== null\n const moveDown = (key: ListEditorKey): boolean => tree.moveDown(key) !== null\n const moveTop = (key: ListEditorKey): boolean => tree.moveTop(key) !== null\n const moveBottom = (key: ListEditorKey): boolean => tree.moveBottom(key) !== null\n const indent = (key: ListEditorKey): boolean => tree.indent(key) !== null\n const outdent = (key: ListEditorKey): boolean => tree.outdent(key) !== null\n const moveTo = (key: ListEditorKey, targetParentKey: ListEditorKey | null, targetIndex: number): boolean =>\n tree.moveTo(key, targetParentKey, targetIndex) !== null\n const recalculatePositions = (): void => {\n options.set(tree.recalculatePositions(options.get()))\n }\n\n const registerValidity = (key: ListEditorKey, isValid: () => boolean): (() => void) => {\n registeredValidity.set(key, isValid)\n return () => registeredValidity.delete(key)\n }\n\n return {\n items,\n viewItems,\n hasUnsaved,\n unsavedCount,\n hasErrors,\n invalidKeys,\n isUnsaved,\n rowState,\n validateAll,\n getPayload,\n getChanges,\n commit,\n acceptRows,\n reset,\n addItem,\n addAfter,\n addChild,\n updateItem,\n deleteItem,\n restoreDeleted,\n moveUp,\n moveDown,\n moveTop,\n moveBottom,\n indent,\n outdent,\n moveTo,\n recalculatePositions,\n registerValidity,\n findNode: tree.findNode,\n calculateSubtreeDepth: tree.calculateSubtreeDepth,\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useNestedListEditorController.js","names":["flatten","out","walk","n","nodes","tree","walkNodes","visit","useNestedListEditorController","keyField","options","keyOf","item","keyFieldName","positionOpt","managedPosition","positionField","positionMultiplier","parentField","model","computed","v","useNestedListEditor","action","items","viewItems","dirtyExclude","toValue","normalize","copy","f","baselineHashes","ref","baselineParents","baselineTree","cloneTree","cloneDeep","captureBaseline","hashes","parents","key","parentKey","t","watch","submitted","registeredValidity","reactive","isItemDirty","saved","baselineTreeRow","node","baseHash","addedBaseline","editedKeys","deletedKeys","live","base","stale","revived","isRowEdited","hit","treeHasKey","found","unsavedKeys","isUnsaved","hasPendingMove","hasUnsaved","unsavedCount","keys","resolveValidity","registered","invalidKeys","hasErrors","rowState","invalid","editing","warning","validateAll","buildPayload","row","getPayload","getChanges","added","updated","moved","reparented","payload","byKey","baseParent","nowParent","deleted","commit","source","normalized","next","previous","nextListEditorTempId","acceptRows","wanted","detach","i","baseSiblings","siblings","at","index","seen","s","reset","restore","addItem","data","hint","addAfter","afterKey","addChild","updateItem","markDirty","dropFromBaseline","removed","opts","targetParentKey","targetIndex","isValid"],"sources":["../../../../src/domains/listEditor/composables/useNestedListEditorController.ts"],"sourcesContent":["import {\n computed,\n reactive,\n ref,\n toValue,\n watch,\n type ComputedRef,\n type MaybeRefOrGetter,\n type Ref,\n type ShallowUnwrapRef,\n} from 'vue'\nimport type {\n ListEditorKey,\n ListEditorValidationState,\n NestedPositionHint,\n NestedTree,\n NestedTreeNode,\n} from '@/domains/listEditor/types/listEditorTypes'\nimport { useNestedListEditor, type NestedViewItem } from '@/domains/listEditor/composables/useNestedListEditor'\nimport type {\n GetKey,\n ListEditorValidationResult,\n PositionOption,\n PositionStrategy,\n} from '@/domains/listEditor/composables/useListEditorController'\nimport { nextListEditorTempId } from '@/domains/listEditor/utils/tempId'\nimport { cloneDeep } from '@/shared/utils/common'\n\nexport type { ListEditorValidationResult, GetKey, PositionOption, PositionStrategy }\n\n/** Flattened ordered row carrying its resolved key (for change-sets + payload). */\nexport interface NestedListEditorChanges<TItem> {\n added: TItem[]\n updated: TItem[]\n moved: TItem[]\n deleted: TItem[]\n /**\n * Rows whose parent changed since the last commit (BUG-13 — persisted even\n * when the position number is unchanged).\n */\n reparented: TItem[]\n}\n\nexport interface UseNestedListEditorControllerOptions<TItem extends Record<string, any>> {\n /** Read the live tree (the editor's v-model, or a consumer store getter). */\n get: () => NestedTree<TItem>\n /** Write the tree back. */\n set: (tree: NestedTree<TItem>) => void\n /** New-row factory. Optional for read-only / no-add trees. Should mint a stable temp id. */\n factory?: () => TItem\n /** Stable row identity. Default `'id'`. Never point this at the position field. */\n getKey?: GetKey<TItem>\n /** Managed order field. Default `'position'`. `false` opts out of position management. */\n position?: PositionOption<TItem>\n /** Parent-key field written onto reparented rows. Default `'parent'`. */\n parentField?: string\n /** Maximum nesting depth (1-based). Enforced by indent/outdent/moveTo. */\n maxDepth: number\n /**\n * Extra top-level fields to drop from the dirty content-hash (position +\n * parent are always dropped). Same purpose as the flat controller — a child\n * collection tracked by a separate editor shouldn't flip its owner amber.\n * Accepts a getter/ref so a `computed` set is honoured reactively.\n */\n dirtyExclude?: MaybeRefOrGetter<string[]>\n /** Per-row validity — `true` = valid. Drives the red rail + `hasErrors`. */\n validate?: (item: TItem) => ListEditorValidationResult\n /** Custom dirty predicate (override the default `meta.dirty ∪ content-diff`). */\n isDirty?: (current: TItem, saved: TItem | undefined) => boolean\n /** Custom save payload (overrides `getPayload`). Receives the flattened ordered rows. */\n payload?: (items: TItem[]) => TItem[]\n /** Resolve a saved row's key on commit (default: existing key, else mint a temp id). */\n commitKey?: (saved: TItem, previous: TItem | undefined) => ListEditorKey\n /** Normalize the server tree before it becomes the new baseline on commit. */\n normalizeSaved?: (saved: NestedTree<TItem>) => NestedTree<TItem>\n}\n\n/**\n * Tree-shaped state controller for the nested list editor (v2). A superset of\n * the flat `ListEditorHandle`: same dirty/validate/commit/reset semantics, but\n * the row set is a flattened ordered projection of a `NestedTree` and the\n * mutators are tree ops (indent / outdent / moveTo / addChild …) delegated to\n * `useNestedListEditor`. Each flattened payload row carries its resolved\n * `position` and parent key written onto it.\n */\nexport interface NestedListEditorHandle<TItem extends Record<string, any>> {\n /** Flattened ordered rows (depth-first), matching the rendered order. */\n items: ComputedRef<TItem[]>\n /** Tree view rows (key/index/raw/depth/parent…), as consumed by the renderer. */\n viewItems: ComputedRef<NestedViewItem<TItem>[]>\n hasUnsaved: ComputedRef<boolean>\n /** Count of distinct unconfirmed changes (added/edited/moved/reparented rows + deferred deletions). */\n unsavedCount: ComputedRef<number>\n hasErrors: ComputedRef<boolean>\n invalidKeys: ComputedRef<Set<ListEditorKey>>\n /** Amber: is this row added / edited / moved / reparented since the last commit? */\n isUnsaved: (key: ListEditorKey) => boolean\n /** Red rail (gated): 'invalid' only once the row is unsaved or `validateAll()` ran. */\n rowState: (item: TItem, key: ListEditorKey, editing?: boolean) => ListEditorValidationState\n /** Force-show all invalid rows + return whether the tree is valid. The save guard. */\n validateAll: () => boolean\n /** Flattened ordered array (each row carrying its resolved position + parent key) for a full-DTO save. */\n getPayload: () => TItem[]\n /** Change-set for partial-save endpoints (added/updated/moved/deleted/reparented), keyed. */\n getChanges: () => NestedListEditorChanges<TItem>\n /** Adopt the saved tree as the new baseline; backfill keys; clear dirty/submitted. */\n commit: (saved?: NestedTree<TItem>) => void\n /** Adopt only these rows as saved (a server-confirmed single-row op); other pending work stays. */\n acceptRows: (keys: ListEditorKey[]) => void\n /** Discard unsaved edits back to the last committed baseline (or a given tree). */\n reset: (tree?: NestedTree<TItem>) => void\n\n // Tree mutations — delegate to useNestedListEditor (which carries BUG-13).\n addItem: (item?: TItem, hint?: NestedPositionHint) => void\n addAfter: (afterKey: ListEditorKey, item?: TItem, childrenAllowed?: boolean) => void\n addChild: (parentKey: ListEditorKey, item?: TItem, childrenAllowed?: boolean) => void\n updateItem: (key: ListEditorKey, data: TItem, markDirty?: boolean) => void\n deleteItem: (key: ListEditorKey, opts?: { trackDeleted?: boolean; renumber?: boolean }) => void\n restoreDeleted: (key: ListEditorKey) => void\n moveUp: (key: ListEditorKey) => boolean\n moveDown: (key: ListEditorKey) => boolean\n moveTop: (key: ListEditorKey) => boolean\n moveBottom: (key: ListEditorKey) => boolean\n indent: (key: ListEditorKey) => boolean\n outdent: (key: ListEditorKey) => boolean\n moveTo: (key: ListEditorKey, targetParentKey: ListEditorKey | null, targetIndex: number) => boolean\n recalculatePositions: () => void\n\n /** Escape hatch: a row form (e.g. vuelidate) reports its own validity instead of `validate`. */\n registerValidity: (key: ListEditorKey, isValid: () => boolean) => () => void\n\n // Internal handles the editor needs to drive the tree directly (find a node,\n // subtree depth for drag, the underlying `editor.moveTo` returning the tree).\n findNode: (key: ListEditorKey) => {\n node: NestedTreeNode<TItem> | null\n parent: NestedTreeNode<TItem> | null\n }\n calculateSubtreeDepth: (node: NestedTreeNode<TItem>) => number\n}\n\n/**\n * Consumer-facing shape of a nested-list-editor handle read through a template/function ref — Vue's\n * `expose` proxy unwraps the exposed refs, so read `handle.hasUnsaved` (a boolean), not\n * `handle.hasUnsaved.value`. See {@link ExposedListEditorHandle}.\n */\nexport type ExposedNestedListEditorHandle<TItem extends Record<string, any>> = ShallowUnwrapRef<\n NestedListEditorHandle<TItem>\n>\n\n/** What `ANestedSortableListEditor` exposes on top of the controller handle. */\nexport interface NestedSortableListEditorExtras {\n /**\n * Runs a tree mutation the server already made (e.g. a row created through a dialog).\n * Adopts as saved only the rows it added or edited, plus `keys`.\n * Siblings it only renumbered, other pending work and a renumbered position of\n * a created row stay unsaved, because the server may not have renumbered them.\n * `commit()` would adopt the whole tree instead.\n */\n acceptChanges: (op: () => void, keys?: ListEditorKey[]) => void\n enterReorderMode: () => void\n cancelReorderMode: () => void\n applyReorder: () => Promise<void>\n expand: (id: ListEditorKey) => void\n collapse: (id: ListEditorKey) => void\n toggleExpand: (id: ListEditorKey) => void\n expandDetail: (id: ListEditorKey) => void\n collapseDetail: (id: ListEditorKey) => void\n}\n\n/** `ANestedSortableListEditor` read through a template ref: the unwrapped handle and its extras. */\nexport type ExposedNestedSortableListEditorHandle<TItem extends Record<string, any>> =\n ExposedNestedListEditorHandle<TItem> & NestedSortableListEditorExtras\n\nconst flatten = <TItem extends Record<string, any>>(tree: NestedTree<TItem>): TItem[] => {\n const out: TItem[] = []\n const walk = (nodes: NestedTreeNode<TItem>[]) => {\n for (const n of nodes) {\n out.push(n.data)\n if (n.children && n.children.length) walk(n.children)\n }\n }\n walk(tree.children)\n return out\n}\n\nconst walkNodes = <TItem extends Record<string, any>>(\n tree: NestedTree<TItem>,\n visit: (node: NestedTreeNode<TItem>) => void\n): void => {\n const walk = (nodes: NestedTreeNode<TItem>[]) => {\n for (const n of nodes) {\n visit(n)\n if (n.children && n.children.length) walk(n.children)\n }\n }\n walk(tree.children)\n}\n\nexport function useNestedListEditorController<TItem extends Record<string, any>>(\n options: UseNestedListEditorControllerOptions<TItem>\n): NestedListEditorHandle<TItem> {\n const keyField = (typeof options.getKey === 'function' ? null : (options.getKey ?? 'id')) as keyof TItem | null\n const keyOf = (item: TItem): ListEditorKey =>\n typeof options.getKey === 'function' ? options.getKey(item) : (item[keyField as keyof TItem] as ListEditorKey)\n const keyFieldName = (keyField ?? 'id') as string\n\n const positionOpt = options.position ?? 'position'\n const managedPosition = positionOpt !== false\n const positionField = (\n typeof positionOpt === 'object' ? positionOpt.field : positionOpt === false ? 'position' : positionOpt\n ) as string\n const positionMultiplier = typeof positionOpt === 'object' && positionOpt.multiplier ? positionOpt.multiplier : 1\n const parentField = options.parentField ?? 'parent'\n\n // Two-way bridge to the consumer's tree: the composable's per-op\n // `model.value = cloned` writes back via `set`, the getter re-reads live edits.\n const model = computed<NestedTree<TItem>>({\n get: () => options.get(),\n set: (v) => options.set(v),\n }) as unknown as Ref<NestedTree<TItem>>\n\n const tree = useNestedListEditor<TItem>(model, {\n keyField: keyFieldName,\n // Pass the controller's keyOf so tree ops resolve keys identically to\n // invalidKeys/dirty tracking — supports a function get-key, not just a field.\n getKey: keyOf,\n positionField,\n parentField,\n positionMultiplier,\n managedPosition,\n positionStrategyFor: (action) =>\n (typeof positionOpt === 'object' && (positionOpt.strategyOverrides?.[action] ?? positionOpt.strategy)) ||\n 'renumber',\n maxDepth: options.maxDepth,\n })\n\n const items = computed<TItem[]>(() => flatten(options.get()))\n const viewItems = tree.viewItems\n\n // Baseline = last committed snapshot. `hashes` powers content-diff dirty\n // (position + parent excluded so a reorder/reparent never lights up via the\n // content hash — meta.dirty / the reparented set carries those instead).\n const dirtyExclude = computed<string[]>(() => toValue(options.dirtyExclude) ?? [])\n const normalize = (item: TItem): string => {\n const copy = { ...item } as Record<string, unknown>\n if (managedPosition) delete copy[positionField]\n delete copy[parentField]\n for (const f of dirtyExclude.value) delete copy[f]\n return JSON.stringify(copy)\n }\n const baselineHashes = ref(new Map<ListEditorKey, string>()) as Ref<Map<ListEditorKey, string>>\n // Parent-key per row at baseline — drives reparented detection (BUG-13).\n const baselineParents = ref(new Map<ListEditorKey, ListEditorKey | null>()) as Ref<\n Map<ListEditorKey, ListEditorKey | null>\n >\n const baselineTree = ref<NestedTree<TItem> | null>(null) as Ref<NestedTree<TItem> | null>\n\n const cloneTree = (t: NestedTree<TItem>): NestedTree<TItem> => cloneDeep(t)\n\n const captureBaseline = (t: NestedTree<TItem>) => {\n const hashes = new Map<ListEditorKey, string>()\n const parents = new Map<ListEditorKey, ListEditorKey | null>()\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n for (const n of nodes) {\n const key = keyOf(n.data)\n hashes.set(key, normalize(n.data))\n parents.set(key, parentKey)\n if (n.children && n.children.length) walk(n.children, key)\n }\n }\n walk(t.children, null)\n baselineHashes.value = hashes\n baselineParents.value = parents\n baselineTree.value = cloneTree(t)\n }\n captureBaseline(options.get())\n // Re-hash when the excluded-field set changes; `sync` so baseline + live\n // normalize() never disagree mid-flush. (Mirrors the flat controller.)\n watch(\n dirtyExclude,\n () => {\n if (!baselineTree.value) return\n const hashes = new Map<ListEditorKey, string>()\n walkNodes(baselineTree.value, (n) => hashes.set(keyOf(n.data), normalize(n.data)))\n baselineHashes.value = hashes\n },\n { flush: 'sync' }\n )\n\n const submitted = ref(false)\n // Reactive so a row form (re)registering its validity re-runs invalidKeys/rowState.\n const registeredValidity = reactive(new Map<ListEditorKey, () => boolean>())\n\n // Amber = added OR content-edited OR reparented (vs baseline). Position is\n // excluded, so a displaced sibling's pure renumber is NOT amber (matches the flat\n // editor + the \"only the actively-moved subtree lights up\" UX); BUG-13 adds the\n // parent-changed signal so a reparent registers even at an unchanged position\n // number. `getChanges().moved` reads meta.dirty, so displaced siblings' new\n // positions are still persisted; `hasPendingMove` (below) feeds the leave guard.\n const isItemDirty = (node: NestedTreeNode<TItem>, key: ListEditorKey, parentKey: ListEditorKey | null): boolean => {\n if (options.isDirty) {\n const saved = baselineTreeRow(key)\n return options.isDirty(node.data, saved)\n }\n const baseHash = baselineHashes.value.get(key)\n if (baseHash === undefined) return true // added\n if (baseHash !== normalize(node.data)) return true // content-edited (pos/parent excluded)\n // Reparented vs baseline (BUG-13).\n if (baselineParents.value.has(key)) {\n const baseParent = baselineParents.value.get(key) ?? null\n if ((baseParent ?? null) !== (parentKey ?? null)) return true\n }\n return false\n }\n\n // `addedBaseline` = first-seen content hash of each ADDED node; `editedKeys` = STICKY set of\n // nodes whose content has since diverged. Gates the validation rail on \"has this row been edited\"\n // rather than just \"is it unsaved\" (sticky like vuelidate `$dirty`) — mirrors the flat controller.\n const addedBaseline = ref(new Map<ListEditorKey, string>()) as Ref<Map<ListEditorKey, string>>\n const editedKeys = ref(new Set<ListEditorKey>()) as Ref<Set<ListEditorKey>>\n // Deferred-deletion tombstones (baseline keys removed but not yet saved). Immediate deletes skip\n // this so they don't read as unsaved. Drives hasUnsaved / unsavedCount / getChanges().deleted.\n const deletedKeys = ref(new Set<ListEditorKey>()) as Ref<Set<ListEditorKey>>\n watch(\n () => options.get(),\n (tree) => {\n const live = new Set<ListEditorKey>()\n walkNodes(tree, (n) => {\n const key = keyOf(n.data)\n live.add(key)\n if (!baselineHashes.value.has(key) && !addedBaseline.value.has(key)) {\n addedBaseline.value.set(key, normalize(n.data))\n }\n if (!editedKeys.value.has(key)) {\n const base = baselineHashes.value.get(key) ?? addedBaseline.value.get(key)\n if (base !== undefined && base !== normalize(n.data)) editedKeys.value.add(key)\n }\n })\n const stale: ListEditorKey[] = []\n for (const key of addedBaseline.value.keys()) if (!live.has(key)) stale.push(key)\n for (const key of stale) addedBaseline.value.delete(key)\n // A tombstoned key that becomes live again (re-add before save) drops its tombstone.\n const revived: ListEditorKey[] = []\n for (const key of deletedKeys.value) if (live.has(key)) revived.push(key)\n for (const key of revived) deletedKeys.value.delete(key)\n },\n { immediate: true, deep: true }\n )\n\n const isRowEdited = (key: ListEditorKey): boolean => editedKeys.value.has(key)\n\n const baselineTreeRow = (key: ListEditorKey): TItem | undefined => {\n if (!baselineTree.value) return undefined\n let hit: TItem | undefined\n walkNodes(baselineTree.value, (n) => {\n if (hit === undefined && keyOf(n.data) === key) hit = n.data\n })\n return hit\n }\n\n const treeHasKey = (key: ListEditorKey): boolean => {\n let found = false\n walkNodes(options.get(), (n) => {\n if (!found && keyOf(n.data) === key) found = true\n })\n return found\n }\n\n const unsavedKeys = computed<Set<ListEditorKey>>(() => {\n const out = new Set<ListEditorKey>()\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n for (const n of nodes) {\n const key = keyOf(n.data)\n if (isItemDirty(n, key, parentKey)) out.add(key)\n if (n.children && n.children.length) walk(n.children, key)\n }\n }\n walk(options.get().children, null)\n return out\n })\n\n const isUnsaved = (key: ListEditorKey): boolean => unsavedKeys.value.has(key)\n // A pure position reorder sets meta.dirty (recalculateSiblings) but is deliberately\n // kept OUT of per-row amber (only the actively-moved subtree lights up). It IS a\n // pending change though, so it must arm the leave guard — surface it as an aggregate\n // signal (M2b) that survives Apply and clears on commit (which resets meta.dirty).\n const hasPendingMove = computed<boolean>(() => {\n let found = false\n walkNodes(options.get(), (n) => {\n if (n.meta.dirty) found = true\n })\n return found\n })\n const hasUnsaved = computed<boolean>(\n () => unsavedKeys.value.size > 0 || deletedKeys.value.size > 0 || hasPendingMove.value\n )\n // Distinct unconfirmed changes = union of live dirty keys (added/edited/moved/reparented) and\n // deferred-deletion tombstones. Drives the \"N unconfirmed changes\" indicator.\n const unsavedCount = computed<number>(() => {\n const keys = new Set<ListEditorKey>(unsavedKeys.value)\n for (const key of deletedKeys.value) keys.add(key)\n return keys.size\n })\n\n const resolveValidity = (item: TItem, key: ListEditorKey): { invalid: boolean; warning: boolean } => {\n const registered = registeredValidity.get(key)\n if (registered) return { invalid: !registered(), warning: false }\n if (!options.validate) return { invalid: false, warning: false }\n const r = options.validate(item)\n if (typeof r === 'boolean') return { invalid: !r, warning: false }\n return { invalid: !r.valid, warning: r.valid && r.state === 'warning' }\n }\n\n const invalidKeys = computed<Set<ListEditorKey>>(() => {\n const out = new Set<ListEditorKey>()\n walkNodes(options.get(), (n) => {\n const key = keyOf(n.data)\n if (resolveValidity(n.data, key).invalid) out.add(key)\n })\n return out\n })\n const hasErrors = computed<boolean>(() => invalidKeys.value.size > 0)\n\n // Red rail for an invalid row that has been edited, is unsaved (added), or after a save attempt —\n // mirrors the flat controller. The editor suppresses the red while the row is the one being edited,\n // so a still-being-filled row reads amber and only goes red once collapsed. (QA 85050 batch 7)\n const rowState = (item: TItem, key: ListEditorKey, editing = false): ListEditorValidationState => {\n const { invalid, warning } = resolveValidity(item, key)\n // See flat controller: red when edited/unsaved/submitted, amber while being filled, red once\n // collapsed; a save attempt (`submitted`) reds it even while open. (QA 85050 batch 7)\n if (invalid) {\n if (submitted.value) return 'invalid'\n if (editing) return null\n return isRowEdited(key) || isUnsaved(key) ? 'invalid' : null\n }\n if (warning) return 'warning'\n return null\n }\n\n const validateAll = (): boolean => {\n submitted.value = true\n return invalidKeys.value.size === 0\n }\n\n // Flattened ordered payload; parent key is resolved from tree structure (so a\n // reparent is reflected even if the node's own parent field lagged).\n const buildPayload = (): TItem[] => {\n const out: TItem[] = []\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n for (const n of nodes) {\n const row = { ...n.data } as TItem\n ;(row as Record<string, unknown>)[parentField] = parentKey\n out.push(row)\n if (n.children && n.children.length) walk(n.children, keyOf(n.data))\n }\n }\n walk(options.get().children, null)\n return out\n }\n\n const getPayload = (): TItem[] => (options.payload ? options.payload(buildPayload()) : buildPayload())\n\n const getChanges = (): NestedListEditorChanges<TItem> => {\n const added: TItem[] = []\n const updated: TItem[] = []\n const moved: TItem[] = []\n const reparented: TItem[] = []\n const payload = buildPayload()\n const byKey = new Map<ListEditorKey, TItem>()\n for (const row of payload) byKey.set(keyOf(row), row)\n\n walkNodes(options.get(), (n) => {\n const key = keyOf(n.data)\n const row = byKey.get(key) ?? n.data\n const baseHash = baselineHashes.value.get(key)\n if (baseHash === undefined) {\n added.push(row)\n } else if (baseHash !== normalize(n.data)) {\n updated.push(row)\n }\n // meta.dirty without a content change => a move/reparent (position/parent\n // changed). recalculateSiblings + BUG-13 set meta.dirty on those.\n if (baseHash !== undefined && n.meta.dirty && baseHash === normalize(n.data)) {\n moved.push(row)\n }\n // Reparented = parent key differs from baseline (subset of moved, but\n // surfaced separately for partial-multi saves that re-link parents).\n if (baselineParents.value.has(key)) {\n const baseParent = baselineParents.value.get(key) ?? null\n const nowParent = (row as Record<string, unknown>)[parentField] as ListEditorKey | null\n if ((baseParent ?? null) !== (nowParent ?? null)) reparented.push(row)\n }\n })\n\n // Deferred deletions come from the tombstone set, so an IMMEDIATE delete (already persisted on the\n // backend, no tombstone) does not re-appear here as a local deleted change.\n const deleted: TItem[] = []\n for (const key of deletedKeys.value) {\n const row = baselineTreeRow(key)\n if (row !== undefined) deleted.push(row)\n }\n return { added, updated, moved, deleted, reparented }\n }\n\n const commit = (saved?: NestedTree<TItem>): void => {\n const source = saved ?? options.get()\n const normalized = options.normalizeSaved ? options.normalizeSaved(source) : source\n // Backfill missing keys + clear meta.dirty on the committed tree.\n const next = cloneTree(normalized)\n walkNodes(next, (n) => {\n const previous = baselineTreeRow(keyOf(n.data))\n const resolvedKey = options.commitKey ? options.commitKey(n.data, previous) : keyOf(n.data)\n if (resolvedKey === undefined || resolvedKey === null) {\n if (keyField) (n.data as Record<string, unknown>)[keyFieldName] = nextListEditorTempId()\n }\n n.meta.dirty = false\n })\n options.set(next)\n captureBaseline(next)\n addedBaseline.value = new Map()\n editedKeys.value = new Set()\n deletedKeys.value = new Set()\n submitted.value = false\n }\n\n // The saved tree is updated too, because `reset()` and `getChanges().deleted` read it.\n // An accepted row takes its current data and place there. An accepted key no longer in the tree leaves it.\n const acceptRows = (keys: ListEditorKey[]): void => {\n if (keys.length === 0) return\n const wanted = new Set(keys)\n const next = cloneTree(options.get())\n const hashes = new Map(baselineHashes.value)\n const parents = new Map(baselineParents.value)\n const base: NestedTree<TItem> = baselineTree.value ? cloneTree(baselineTree.value) : { ...next, children: [] }\n type Detached = { node: NestedTreeNode<TItem>; siblings: NestedTreeNode<TItem>[]; index: number }\n const detach = (nodes: NestedTreeNode<TItem>[], key: ListEditorKey): Detached | undefined => {\n for (let i = 0; i < nodes.length; i++) {\n const node = nodes[i]!\n if (keyOf(node.data) === key) return { node: nodes.splice(i, 1)[0]!, siblings: nodes, index: i }\n const found = node.children?.length ? detach(node.children, key) : undefined\n if (found) return found\n }\n return undefined\n }\n const baseSiblings = (parentKey: ListEditorKey | null): NestedTreeNode<TItem>[] | undefined => {\n if (parentKey === null) return base.children\n let hit: NestedTreeNode<TItem> | undefined\n walkNodes(base, (n) => {\n if (hit === undefined && keyOf(n.data) === parentKey) hit = n\n })\n if (!hit) return undefined\n if (!hit.children) hit.children = []\n return hit.children\n }\n const live = new Set<ListEditorKey>()\n const walk = (nodes: NestedTreeNode<TItem>[], parentKey: ListEditorKey | null) => {\n nodes.forEach((n, index) => {\n const key = keyOf(n.data)\n live.add(key)\n if (wanted.has(key)) {\n hashes.set(key, normalize(n.data))\n parents.set(key, parentKey)\n n.meta.dirty = false\n addedBaseline.value.delete(key)\n editedKeys.value.delete(key)\n const previous = detach(base.children, key)\n const saved = cloneDeep(n)\n // A row added without children allowed stays without them; a saved row keeps its saved children.\n saved.children = previous ? previous.node.children : n.children ? [] : undefined\n saved.meta = { ...saved.meta, dirty: false }\n const siblings = baseSiblings(parentKey)\n if (!siblings) {\n // The new parent is not in the saved tree, e.g. it was this row's own saved child detached with it.\n // Keep the row at its saved place rather than drop it and its children.\n if (previous) previous.siblings.splice(previous.index, 0, saved)\n } else {\n // Insert after the nearest preceding sibling the saved tree knows, so pending rows do not skew the index.\n let at = 0\n for (let i = index - 1; i >= 0; i--) {\n const seen = siblings.findIndex((s) => keyOf(s.data) === keyOf(nodes[i]!.data))\n if (seen !== -1) {\n at = seen + 1\n break\n }\n }\n siblings.splice(at, 0, saved)\n }\n }\n if (n.children && n.children.length) walk(n.children, key)\n })\n }\n walk(next.children, null)\n for (const key of wanted) {\n if (live.has(key)) continue\n hashes.delete(key)\n parents.delete(key)\n // Gone from the backend: no longer a pending deletion either.\n deletedKeys.value.delete(key)\n detach(base.children, key)\n }\n baselineHashes.value = hashes\n baselineParents.value = parents\n baselineTree.value = base\n options.set(next)\n }\n\n const reset = (t?: NestedTree<TItem>): void => {\n const restore = t ?? (baselineTree.value ? cloneTree(baselineTree.value) : options.get())\n options.set(restore)\n addedBaseline.value = new Map()\n editedKeys.value = new Set()\n deletedKeys.value = new Set()\n submitted.value = false\n }\n\n // --- Tree mutations (delegate to useNestedListEditor) -----------------------\n\n const addItem = (item?: TItem, hint?: NestedPositionHint): void => {\n const data = item ?? options.factory?.()\n if (data === undefined) return // no item + no factory (read-only) → no-op\n tree.addItem(data, hint)\n }\n const addAfter = (afterKey: ListEditorKey, item?: TItem, childrenAllowed = true): void => {\n const data = item ?? options.factory?.()\n if (data === undefined) return\n tree.addItem(data, { afterId: afterKey, childrenAllowed })\n }\n const addChild = (parentKey: ListEditorKey, item?: TItem, childrenAllowed = true): void => {\n const data = item ?? options.factory?.()\n if (data === undefined) return\n tree.addItem(data, { parentId: parentKey, childrenAllowed })\n }\n const updateItem = (key: ListEditorKey, data: TItem, markDirty = true): void => {\n tree.updateItem(key, data, markDirty)\n }\n // Immediate delete: the row is gone on the backend and the editor removes it with its subtree.\n // So neither stays in the saved tree that `reset()` restores.\n const dropFromBaseline = (key: ListEditorKey): void => {\n if (!baselineTree.value) return\n const base = cloneTree(baselineTree.value)\n const detach = (nodes: NestedTreeNode<TItem>[]): NestedTreeNode<TItem> | undefined => {\n for (let i = 0; i < nodes.length; i++) {\n if (keyOf(nodes[i]!.data) === key) return nodes.splice(i, 1)[0]\n const found = nodes[i]!.children?.length ? detach(nodes[i]!.children!) : undefined\n if (found) return found\n }\n return undefined\n }\n const removed = detach(base.children)\n if (!removed) return\n const hashes = new Map(baselineHashes.value)\n const parents = new Map(baselineParents.value)\n walkNodes({ ...base, children: [removed] }, (n) => {\n hashes.delete(keyOf(n.data))\n parents.delete(keyOf(n.data))\n })\n baselineHashes.value = hashes\n baselineParents.value = parents\n baselineTree.value = base\n }\n\n const deleteItem = (key: ListEditorKey, opts?: { trackDeleted?: boolean; renumber?: boolean }): void => {\n // A saved row removed in deferred mode is tombstoned: it counts as unsaved and appears in `getChanges().deleted`.\n // `trackDeleted: false` (immediate, already deleted on the backend) skips this.\n // `treeHasKey` prevents a phantom tombstone when a consumer calls\n // `deleteItem` again for a row the component already removed.\n if (baselineHashes.value.has(key) && opts?.trackDeleted !== false && treeHasKey(key)) {\n deletedKeys.value.add(key)\n } else if (baselineHashes.value.has(key) && treeHasKey(key)) {\n dropFromBaseline(key)\n }\n tree.deleteItem(key, { renumber: opts?.renumber })\n }\n\n const restoreDeleted = (key: ListEditorKey): void => {\n deletedKeys.value.delete(key)\n }\n const moveUp = (key: ListEditorKey): boolean => tree.moveUp(key) !== null\n const moveDown = (key: ListEditorKey): boolean => tree.moveDown(key) !== null\n const moveTop = (key: ListEditorKey): boolean => tree.moveTop(key) !== null\n const moveBottom = (key: ListEditorKey): boolean => tree.moveBottom(key) !== null\n const indent = (key: ListEditorKey): boolean => tree.indent(key) !== null\n const outdent = (key: ListEditorKey): boolean => tree.outdent(key) !== null\n const moveTo = (key: ListEditorKey, targetParentKey: ListEditorKey | null, targetIndex: number): boolean =>\n tree.moveTo(key, targetParentKey, targetIndex) !== null\n const recalculatePositions = (): void => {\n options.set(tree.recalculatePositions(options.get()))\n }\n\n const registerValidity = (key: ListEditorKey, isValid: () => boolean): (() => void) => {\n registeredValidity.set(key, isValid)\n return () => registeredValidity.delete(key)\n }\n\n return {\n items,\n viewItems,\n hasUnsaved,\n unsavedCount,\n hasErrors,\n invalidKeys,\n isUnsaved,\n rowState,\n validateAll,\n getPayload,\n getChanges,\n commit,\n acceptRows,\n reset,\n addItem,\n addAfter,\n addChild,\n updateItem,\n deleteItem,\n restoreDeleted,\n moveUp,\n moveDown,\n moveTop,\n moveBottom,\n indent,\n outdent,\n moveTo,\n recalculatePositions,\n registerValidity,\n findNode: tree.findNode,\n calculateSubtreeDepth: tree.calculateSubtreeDepth,\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"useReorderMode.js","names":["SharedReorderRegistryKey","useReorderMode","applying","ref","applyError","reorderMode","computed","options","movedCount","hasPendingChanges","clonePayload","isEmbedded","watch","newMode","oldMode","payload","err"],"sources":["../../../../src/domains/listEditor/composables/useReorderMode.ts"],"sourcesContent":["import { computed, ref, watch, type ComputedRef, type InjectionKey, type Ref } from 'vue'\nimport type { ListEditorKey } from '@/domains/listEditor/types/listEditorTypes'\n\n// Registry that lets embedded inner editors push their reorder pending-count\n// up to the nearest non-embedded outer editor. The outer's reorder toolbar\n// status (\"N pending changes\") then reflects child moves too — so toggling\n// the order of an answer inside a question increments the outer's counter\n// just like a question move would.\nexport interface SharedReorderRegistry {\n register: (\n id: symbol,\n movedCount: ComputedRef<number>,\n hasPendingChanges: ComputedRef<boolean>,\n validateAll: () => boolean\n ) => void\n unregister: (id: symbol) => void\n}\n\nexport const SharedReorderRegistryKey = Symbol('le.sharedReorderRegistry') as InjectionKey<SharedReorderRegistry>\n\nexport type ReorderModeValue = 'view' | 'reorder'\n\nexport interface UseReorderModeEmit<T> {\n reorderStart: () => void\n reorderCancel: () => void\n reorderApplied: (payload: T) => void\n reorderApplyError: (err: unknown) => void\n reorderEnd: () => void\n}\n\nexport interface UseReorderModeOptions<T> {\n /**\n * v-model-backed mode ref — the composable reads + writes, but the\n * component owns the `defineModel('mode', ...)` so external\n * `v-model:mode` bindings still flow. Passing the ref in avoids\n * duplicating the defineModel contract inside the composable.\n */\n mode: Ref<ReorderModeValue>\n /**\n * Reorder snapshot — cloned on enter, restored on cancel, cleared on\n * apply. Stays at component level (the dirty-baseline needs to read it\n * indirectly too), but the composable owns every assignment.\n */\n snapshot: Ref<T | null>\n /**\n * Keys the user has actively moved this session (drag, arrow buttons,\n * indent/outdent). Cleared on every mode transition. Stays at component\n * level because the per-row decorator reads it for the `moved` flag.\n */\n movedKeys: Ref<Set<ListEditorKey>>\n modelValue: Ref<T>\n /**\n * Deep-clone the model value for snapshotting. Caller-provided because\n * the nested tree shape and flat array shape need different serializer\n * handling (both use `cloneDeep` in practice, but the callsite already\n * imports it).\n */\n cloneModel: (m: T) => T\n applyModel: (m: T) => void\n canEnterReorder: ComputedRef<boolean>\n /**\n * Hook run after mode flips to `reorder` but before emit — nested uses\n * this to expand every branch + init sortable instances, flat uses it\n * (via nothing — the sortable initialises lazily via a watch in the\n * flat variant). Left optional.\n */\n onEnter?: () => void\n /**\n * Hook run after mode flips back to `view` on cancel — nested destroys\n * its sortable instances here. Flat doesn't need it.\n */\n onCancel?: () => void\n /**\n * Hook run after apply succeeds — nested destroys its sortable instances\n * here. Flat doesn't need it.\n */\n onApplyEnd?: () => void\n /**\n * Called from the mode watcher when mode flips externally from `view` to\n * `reorder` (e.g. v-model:mode bound by the parent) — each variant uses\n * this to clear variant-specific caches that `enterReorderMode` itself\n * also clears via its own call-site. The flat variant clears editing +\n * expanded; nested clears editing only (children-expanded stays).\n */\n onExternalEnter?: () => void\n /**\n * Called from the mode watcher when an EMBEDDED editor flips externally from\n * `reorder` back to `view` (its parent's Cancel or Apply). Embedded editors\n * have no own snapshot/apply/cancel, so this is their only exit hook — the\n * flat variant uses it to reconcile immediate (backend) deletes made during\n * the session: on a parent Cancel the parent's snapshot restore resurrects\n * the deleted row, which must be re-removed; on Apply it stayed gone (no-op).\n */\n onEmbeddedExit?: () => void\n /**\n * Async persist callback wired from the parent — identical semantics to\n * the old `props.onReorderApply`. Receives the cloned payload (array for\n * flat, tree for nested); throwing surfaces the error in the header\n * toolbar via `applyError`.\n */\n onReorderApply?: (payload: T) => Promise<void> | void\n /**\n * Optional override for the payload passed to `onReorderApply` + the\n * `reorder-applied` emit — defaults to `cloneModel(modelValue)`. Exists\n * so consumers could send a different shape than their stored snapshot\n * if the need arises; both current callers use the default.\n */\n clonePayload?: (m: T) => T\n /**\n * Embedded mode — the editor follows external mode changes but does NOT\n * own a snapshot or apply/cancel logic. The parent (a non-embedded outer\n * editor) takes a deep snapshot covering this editor's data too, so cancel\n * at the top restores everything. Used for the \"shared reorder\" pattern\n * where a single Reorder button drives multiple stacked editors.\n */\n embedded?: ComputedRef<boolean> | Ref<boolean>\n emit: UseReorderModeEmit<T>\n}\n\nexport interface UseReorderModeApi {\n applying: Ref<boolean>\n applyError: Ref<string | null>\n hasPendingChanges: ComputedRef<boolean>\n movedCount: ComputedRef<number>\n reorderMode: ComputedRef<boolean>\n enterReorderMode: () => void\n cancelReorderMode: () => void\n applyReorder: () => Promise<void>\n}\n\n/**\n * Reorder-mode state machine shared between ASortableListEditor and\n * ANestedSortableListEditor. Owns the `applying` + `applyError` flags, the\n * pending-changes counters, and the enter / cancel / apply transitions —\n * plus the mode watcher that fires when the v-model:mode flips externally.\n *\n * The snapshot and `movedKeys` sets stay at component level because the\n * per-row decorator + dirty-baseline read them directly; the composable\n * takes them as refs so it can still drive the state machine.\n */\nexport function useReorderMode<T>(options: UseReorderModeOptions<T>): UseReorderModeApi {\n const applying = ref(false)\n const applyError = ref<string | null>(null)\n\n const reorderMode = computed(() => options.mode.value === 'reorder')\n const movedCount = computed(() => options.movedKeys.value.size)\n const hasPendingChanges = computed(() => movedCount.value > 0)\n\n const clonePayload = (): T =>\n options.clonePayload ? options.clonePayload(options.modelValue.value) : options.cloneModel(options.modelValue.value)\n\n const isEmbedded = (): boolean => options.embedded?.value === true\n\n const enterReorderMode = () => {\n if (!options.canEnterReorder.value || reorderMode.value) return\n if (!isEmbedded()) {\n options.snapshot.value = options.cloneModel(options.modelValue.value)\n }\n options.movedKeys.value = new Set()\n applyError.value = null\n options.mode.value = 'reorder'\n options.onEnter?.()\n options.emit.reorderStart()\n }\n\n const cancelReorderMode = () => {\n if (!reorderMode.value || applying.value) return\n if (!isEmbedded() && options.snapshot.value) {\n options.applyModel(options.snapshot.value as T)\n }\n options.snapshot.value = null\n options.movedKeys.value = new Set()\n applyError.value = null\n applying.value = false\n options.mode.value = 'view'\n options.onCancel?.()\n options.emit.reorderCancel()\n options.emit.reorderEnd()\n }\n\n const applyReorder = async () => {\n if (!reorderMode.value) return\n const payload = clonePayload()\n applyError.value = null\n if (!isEmbedded() && options.onReorderApply) {\n applying.value = true\n try {\n await options.onReorderApply(payload)\n } catch (err) {\n applying.value = false\n applyError.value = err instanceof Error ? err.message : String(err)\n options.emit.reorderApplyError(err)\n return\n }\n applying.value = false\n }\n // Deliberately keep `movedKeys` populated — consumer still has to persist\n // the new order via their own API call before rows are truly \"saved\"; we\n // let them clear the state via `commit()` on success.\n options.snapshot.value = null\n options.mode.value = 'view'\n options.onApplyEnd?.()\n options.emit.reorderApplied(payload)\n options.emit.reorderEnd()\n }\n\n // Handle external mode flips (v-model:mode from a parent) — mirror the\n // same bookkeeping enterReorderMode / cancelReorderMode do so the state\n // stays consistent whether the transition came from a button click or a\n // parent binding. Embedded editors do NOT take a snapshot; their parent\n // (the outer non-embedded editor) owns one that covers nested data too.\n //\n // The view→reorder→view cleanup path differs between embedded and\n // non-embedded:\n // - non-embedded cancel: snapshot is set → clear state here\n // - non-embedded apply: applyReorder nulls snapshot BEFORE flipping\n // mode, so the snapshot-guarded branch is skipped → movedKeys stays\n // populated until consumer calls commit() (the contract)\n // - embedded: no snapshot ever, clear state on every view transition\n // so the inner editor's movedKeys doesn't outlive a parent\n // cancel/apply (otherwise rows would render as `unsaved` after the\n // parent restores the original data)\n // Immediate: an editor mounted with mode already `reorder` needs the same snapshot, or Cancel keeps the moves.\n watch(\n options.mode,\n (newMode, oldMode) => {\n if (newMode === 'reorder' && oldMode !== 'reorder') {\n if (!isEmbedded() && !options.snapshot.value) {\n options.snapshot.value = options.cloneModel(options.modelValue.value)\n }\n options.movedKeys.value = new Set()\n options.onExternalEnter?.()\n }\n if (newMode === 'view' && oldMode === 'reorder') {\n if (options.snapshot.value) {\n options.snapshot.value = null\n options.movedKeys.value = new Set()\n applyError.value = null\n applying.value = false\n } else if (isEmbedded()) {\n options.movedKeys.value = new Set()\n applyError.value = null\n applying.value = false\n // Reconcile session immediate (backend) deletes: the parent has already flushed both props, so\n // the model reflects a Cancel's snapshot-restore (deleted row resurrected → re-remove) or an\n // Apply (row stayed gone → the re-remove is a no-op). Deferred deletes need nothing here.\n options.onEmbeddedExit?.()\n }\n }\n },\n { immediate: true }\n )\n\n return {\n applying,\n applyError,\n hasPendingChanges,\n movedCount,\n reorderMode,\n enterReorderMode,\n cancelReorderMode,\n applyReorder,\n }\n}\n"],"mappings":";;AAkBA,IAAaA,IAA2B,OAAO,0BAA0B;AA0HzE,SAAgBC,EAAkB,GAAsD;CACtF,IAAMC,IAAWC,EAAI,EAAK,GACpBC,IAAaD,EAAmB,IAAI,GAEpCE,IAAcC,QAAeC,EAAQ,KAAK,UAAU,SAAS,GAC7DC,IAAaF,QAAeC,EAAQ,UAAU,MAAM,IAAI,GACxDE,IAAoBH,QAAeE,EAAW,QAAQ,CAAC,GAEvDE,UACJH,EAAQ,eAAeA,EAAQ,aAAaA,EAAQ,WAAW,KAAK,IAAIA,EAAQ,WAAWA,EAAQ,WAAW,KAAK,GAE/GI,UAA4BJ,EAAQ,UAAU,UAAU;CAsG9D,OA9BAK,EACEL,EAAQ,OACP,GAAS,MAAY;EAQpB,AAPIM,MAAY,aAAaC,MAAY,cACnC,CAACH,EAAW,KAAK,CAACJ,EAAQ,SAAS,UACrC,EAAQ,SAAS,QAAQA,EAAQ,WAAWA,EAAQ,WAAW,KAAK,IAEtE,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClCA,EAAQ,kBAAkB,IAExBM,MAAY,UAAUC,MAAY,cAChCP,EAAQ,SAAS,SACnB,EAAQ,SAAS,QAAQ,MACzB,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAS,QAAQ,MACRI,EAAW,MACpB,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAS,QAAQ,IAIjBJ,EAAQ,iBAAiB;CAG/B,GACA,EAAE,WAAW,GAAK,CACpB,GAEO;EACL;EACA;EACA;EACA;EACA;EACA,wBA1G6B;GAC7B,AAAKA,EAAQ,gBAAgB,SAAS,GAAY,UAC7CI,EAAW,MACd,EAAQ,SAAS,QAAQJ,EAAQ,WAAWA,EAAQ,WAAW,KAAK,IAEtE,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAQ,KAAK,QAAQ,WACrBA,EAAQ,UAAU,GAClBA,EAAQ,KAAK,aAAa;EAC5B;EAiGE,yBA/F8B;GAC9B,AAAKF,EAAY,SAAS,GAAS,UAC/B,CAACM,EAAW,KAAKJ,EAAQ,SAAS,SACpCA,EAAQ,WAAWA,EAAQ,SAAS,KAAU,GAEhD,EAAQ,SAAS,QAAQ,MACzB,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAS,QAAQ,IACjB,EAAQ,KAAK,QAAQ,QACrBA,EAAQ,WAAW,GACnBA,EAAQ,KAAK,cAAc,GAC3BA,EAAQ,KAAK,WAAW;EAC1B;EAmFE,0BAjF+B;GAC/B,IAAI,CAACF,EAAY,OAAO;GACxB,IAAMU,IAAUL,EAAa;GAE7B,IADA,EAAW,QAAQ,MACf,CAACC,EAAW,KAAKJ,EAAQ,gBAAgB;IAC3C,EAAS,QAAQ;IACjB,IAAI;KACF,MAAMA,EAAQ,eAAeQ,CAAO;IACtC,SAASC,GAAK;KAGZ,AAFA,EAAS,QAAQ,IACjB,EAAW,QAAQA,aAAe,QAAQA,EAAI,UAAU,OAAOA,CAAG,GAClET,EAAQ,KAAK,kBAAkBS,CAAG;KAClC;IACF;IACA,EAAS,QAAQ;GACnB;GAQA,AAJA,EAAQ,SAAS,QAAQ,MACzB,EAAQ,KAAK,QAAQ,QACrBT,EAAQ,aAAa,GACrBA,EAAQ,KAAK,eAAeQ,CAAO,GACnCR,EAAQ,KAAK,WAAW;EAC1B;CA0DA;AACF"}
1
+ {"version":3,"file":"useReorderMode.js","names":["SharedReorderRegistryKey","useReorderMode","applying","ref","applyError","reorderMode","computed","options","movedCount","hasPendingChanges","clonePayload","isEmbedded","watch","newMode","oldMode","payload","err"],"sources":["../../../../src/domains/listEditor/composables/useReorderMode.ts"],"sourcesContent":["import { computed, ref, watch, type ComputedRef, type InjectionKey, type Ref } from 'vue'\nimport type { ListEditorKey } from '@/domains/listEditor/types/listEditorTypes'\n\n// Registry that lets embedded inner editors push their reorder pending-count\n// up to the nearest non-embedded outer editor. The outer's reorder toolbar\n// status (\"N pending changes\") then reflects child moves too — so toggling\n// the order of an answer inside a question increments the outer's counter\n// just like a question move would.\nexport interface SharedReorderRegistry {\n register: (\n id: symbol,\n movedCount: ComputedRef<number>,\n hasPendingChanges: ComputedRef<boolean>,\n validateAll: () => boolean\n ) => void\n unregister: (id: symbol) => void\n}\n\nexport const SharedReorderRegistryKey = Symbol('le.sharedReorderRegistry') as InjectionKey<SharedReorderRegistry>\n\nexport type ReorderModeValue = 'view' | 'reorder'\n\nexport interface UseReorderModeEmit<T> {\n reorderStart: () => void\n reorderCancel: () => void\n reorderApplied: (payload: T) => void\n reorderApplyError: (err: unknown) => void\n reorderEnd: () => void\n}\n\nexport interface UseReorderModeOptions<T> {\n /**\n * v-model-backed mode ref — the composable reads + writes, but the\n * component owns the `defineModel('mode', ...)` so external\n * `v-model:mode` bindings still flow. Passing the ref in avoids\n * duplicating the defineModel contract inside the composable.\n */\n mode: Ref<ReorderModeValue>\n /**\n * Reorder snapshot — cloned on enter, restored on cancel, cleared on\n * apply. Stays at component level (the dirty-baseline needs to read it\n * indirectly too), but the composable owns every assignment.\n */\n snapshot: Ref<T | null>\n /**\n * Keys the user has actively moved this session (drag, arrow buttons,\n * indent/outdent). Cleared on every mode transition. Stays at component\n * level because the per-row decorator reads it for the `moved` flag.\n */\n movedKeys: Ref<Set<ListEditorKey>>\n modelValue: Ref<T>\n /**\n * Deep-clone the model value for snapshotting. Caller-provided because\n * the nested tree shape and flat array shape need different serializer\n * handling (both use `cloneDeep` in practice, but the callsite already\n * imports it).\n */\n cloneModel: (m: T) => T\n applyModel: (m: T) => void\n canEnterReorder: ComputedRef<boolean>\n /**\n * Hook run after mode flips to `reorder` but before emit — nested uses\n * this to expand every branch + init sortable instances, flat uses it\n * (via nothing — the sortable initialises lazily via a watch in the\n * flat variant). Left optional.\n */\n onEnter?: () => void\n /**\n * Hook run after mode flips back to `view` on cancel — nested destroys\n * its sortable instances here. Flat doesn't need it.\n */\n onCancel?: () => void\n /**\n * Hook run after apply succeeds — nested destroys its sortable instances\n * here. Flat doesn't need it.\n */\n onApplyEnd?: () => void\n /**\n * Called from the mode watcher when mode flips externally from `view` to\n * `reorder` (e.g. v-model:mode bound by the parent) — each variant uses\n * this to clear variant-specific caches that `enterReorderMode` itself\n * also clears via its own call-site. The flat variant clears editing +\n * expanded; nested clears editing only (children-expanded stays).\n */\n onExternalEnter?: () => void\n /**\n * Called from the mode watcher when an EMBEDDED editor flips externally from\n * `reorder` back to `view` (its parent's Cancel or Apply). Embedded editors\n * have no own snapshot/apply/cancel, so this is their only exit hook — the\n * flat variant uses it to reconcile immediate (backend) deletes made during\n * the session: on a parent Cancel the parent's snapshot restore resurrects\n * the deleted row, which must be re-removed; on Apply it stayed gone (no-op).\n */\n onEmbeddedExit?: () => void\n /**\n * Async persist callback wired from the parent — identical semantics to\n * the old `props.onReorderApply`. Receives the cloned payload (array for\n * flat, tree for nested); throwing surfaces the error in the header\n * toolbar via `applyError`.\n */\n onReorderApply?: (payload: T) => Promise<void> | void\n /**\n * Optional override for the payload passed to `onReorderApply` + the\n * `reorder-applied` emit — defaults to `cloneModel(modelValue)`. Exists\n * so consumers could send a different shape than their stored snapshot\n * if the need arises; both current callers use the default.\n */\n clonePayload?: (m: T) => T\n /**\n * Embedded mode — the editor follows external mode changes but does NOT\n * own a snapshot or apply/cancel logic. The parent (a non-embedded outer\n * editor) takes a deep snapshot covering this editor's data too, so cancel\n * at the top restores everything. Used for the \"shared reorder\" pattern\n * where a single Reorder button drives multiple stacked editors.\n */\n embedded?: ComputedRef<boolean> | Ref<boolean>\n emit: UseReorderModeEmit<T>\n}\n\nexport interface UseReorderModeApi {\n applying: Ref<boolean>\n applyError: Ref<string | null>\n hasPendingChanges: ComputedRef<boolean>\n movedCount: ComputedRef<number>\n reorderMode: ComputedRef<boolean>\n enterReorderMode: () => void\n cancelReorderMode: () => void\n applyReorder: () => Promise<void>\n}\n\n/**\n * Reorder-mode state machine shared between ASortableListEditor and\n * ANestedSortableListEditor. Owns the `applying` + `applyError` flags, the\n * pending-changes counters, and the enter / cancel / apply transitions —\n * plus the mode watcher that fires when the v-model:mode flips externally.\n *\n * The snapshot and `movedKeys` sets stay at component level because the\n * per-row decorator + dirty-baseline read them directly; the composable\n * takes them as refs so it can still drive the state machine.\n */\nexport function useReorderMode<T>(options: UseReorderModeOptions<T>): UseReorderModeApi {\n const applying = ref(false)\n const applyError = ref<string | null>(null)\n\n const reorderMode = computed(() => options.mode.value === 'reorder')\n const movedCount = computed(() => options.movedKeys.value.size)\n const hasPendingChanges = computed(() => movedCount.value > 0)\n\n const clonePayload = (): T =>\n options.clonePayload ? options.clonePayload(options.modelValue.value) : options.cloneModel(options.modelValue.value)\n\n const isEmbedded = (): boolean => options.embedded?.value === true\n\n const enterReorderMode = () => {\n if (!options.canEnterReorder.value || reorderMode.value) return\n if (!isEmbedded()) {\n options.snapshot.value = options.cloneModel(options.modelValue.value)\n }\n options.movedKeys.value = new Set()\n applyError.value = null\n options.mode.value = 'reorder'\n options.onEnter?.()\n options.emit.reorderStart()\n }\n\n const cancelReorderMode = () => {\n if (!reorderMode.value || applying.value) return\n if (!isEmbedded() && options.snapshot.value) {\n options.applyModel(options.snapshot.value as T)\n }\n options.snapshot.value = null\n options.movedKeys.value = new Set()\n applyError.value = null\n applying.value = false\n options.mode.value = 'view'\n options.onCancel?.()\n options.emit.reorderCancel()\n options.emit.reorderEnd()\n }\n\n const applyReorder = async () => {\n if (!reorderMode.value) return\n const payload = clonePayload()\n applyError.value = null\n if (!isEmbedded() && options.onReorderApply) {\n applying.value = true\n try {\n await options.onReorderApply(payload)\n } catch (err) {\n applying.value = false\n applyError.value = err instanceof Error ? err.message : String(err)\n options.emit.reorderApplyError(err)\n return\n }\n applying.value = false\n }\n // Keep `movedKeys` populated. The consumer still has to persist the new order with its own API call.\n // It clears the state via `commit()` on success.\n options.snapshot.value = null\n options.mode.value = 'view'\n options.onApplyEnd?.()\n options.emit.reorderApplied(payload)\n options.emit.reorderEnd()\n }\n\n // Handle mode flips from a parent `v-model:mode` with the same bookkeeping as enterReorderMode / cancelReorderMode.\n // Embedded editors take no snapshot. The outer editor's snapshot covers nested data.\n // Non-embedded: cancel has a snapshot and clears state here. `applyReorder`\n // nulls the snapshot before the flip, so `movedKeys` stays until `commit()`.\n // Embedded: clear state on every view transition, or rows show as `unsaved` after a parent cancel or\n // apply. Immediate: an editor mounted in `reorder` needs the snapshot too, or Cancel keeps the moves.\n watch(\n options.mode,\n (newMode, oldMode) => {\n if (newMode === 'reorder' && oldMode !== 'reorder') {\n if (!isEmbedded() && !options.snapshot.value) {\n options.snapshot.value = options.cloneModel(options.modelValue.value)\n }\n options.movedKeys.value = new Set()\n options.onExternalEnter?.()\n }\n if (newMode === 'view' && oldMode === 'reorder') {\n if (options.snapshot.value) {\n options.snapshot.value = null\n options.movedKeys.value = new Set()\n applyError.value = null\n applying.value = false\n } else if (isEmbedded()) {\n options.movedKeys.value = new Set()\n applyError.value = null\n applying.value = false\n // Reconcile immediate (backend) deletes from this session. The parent has already flushed both props.\n // After Cancel the snapshot restore brings the deleted row back,\n // so it is removed again. After Apply the removal is a no-op.\n // Deferred deletes need nothing here.\n options.onEmbeddedExit?.()\n }\n }\n },\n { immediate: true }\n )\n\n return {\n applying,\n applyError,\n hasPendingChanges,\n movedCount,\n reorderMode,\n enterReorderMode,\n cancelReorderMode,\n applyReorder,\n }\n}\n"],"mappings":";;AAkBA,IAAaA,IAA2B,OAAO,0BAA0B;AA0HzE,SAAgBC,EAAkB,GAAsD;CACtF,IAAMC,IAAWC,EAAI,EAAK,GACpBC,IAAaD,EAAmB,IAAI,GAEpCE,IAAcC,QAAeC,EAAQ,KAAK,UAAU,SAAS,GAC7DC,IAAaF,QAAeC,EAAQ,UAAU,MAAM,IAAI,GACxDE,IAAoBH,QAAeE,EAAW,QAAQ,CAAC,GAEvDE,UACJH,EAAQ,eAAeA,EAAQ,aAAaA,EAAQ,WAAW,KAAK,IAAIA,EAAQ,WAAWA,EAAQ,WAAW,KAAK,GAE/GI,UAA4BJ,EAAQ,UAAU,UAAU;CA2F9D,OA/BAK,EACEL,EAAQ,OACP,GAAS,MAAY;EAQpB,AAPIM,MAAY,aAAaC,MAAY,cACnC,CAACH,EAAW,KAAK,CAACJ,EAAQ,SAAS,UACrC,EAAQ,SAAS,QAAQA,EAAQ,WAAWA,EAAQ,WAAW,KAAK,IAEtE,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClCA,EAAQ,kBAAkB,IAExBM,MAAY,UAAUC,MAAY,cAChCP,EAAQ,SAAS,SACnB,EAAQ,SAAS,QAAQ,MACzB,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAS,QAAQ,MACRI,EAAW,MACpB,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAS,QAAQ,IAKjBJ,EAAQ,iBAAiB;CAG/B,GACA,EAAE,WAAW,GAAK,CACpB,GAEO;EACL;EACA;EACA;EACA;EACA;EACA,wBA/F6B;GAC7B,AAAKA,EAAQ,gBAAgB,SAAS,GAAY,UAC7CI,EAAW,MACd,EAAQ,SAAS,QAAQJ,EAAQ,WAAWA,EAAQ,WAAW,KAAK,IAEtE,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAQ,KAAK,QAAQ,WACrBA,EAAQ,UAAU,GAClBA,EAAQ,KAAK,aAAa;EAC5B;EAsFE,yBApF8B;GAC9B,AAAKF,EAAY,SAAS,GAAS,UAC/B,CAACM,EAAW,KAAKJ,EAAQ,SAAS,SACpCA,EAAQ,WAAWA,EAAQ,SAAS,KAAU,GAEhD,EAAQ,SAAS,QAAQ,MACzB,EAAQ,UAAU,wBAAQ,IAAI,IAAI,GAClC,EAAW,QAAQ,MACnB,EAAS,QAAQ,IACjB,EAAQ,KAAK,QAAQ,QACrBA,EAAQ,WAAW,GACnBA,EAAQ,KAAK,cAAc,GAC3BA,EAAQ,KAAK,WAAW;EAC1B;EAwEE,0BAtE+B;GAC/B,IAAI,CAACF,EAAY,OAAO;GACxB,IAAMU,IAAUL,EAAa;GAE7B,IADA,EAAW,QAAQ,MACf,CAACC,EAAW,KAAKJ,EAAQ,gBAAgB;IAC3C,EAAS,QAAQ;IACjB,IAAI;KACF,MAAMA,EAAQ,eAAeQ,CAAO;IACtC,SAASC,GAAK;KAGZ,AAFA,EAAS,QAAQ,IACjB,EAAW,QAAQA,aAAe,QAAQA,EAAI,UAAU,OAAOA,CAAG,GAClET,EAAQ,KAAK,kBAAkBS,CAAG;KAClC;IACF;IACA,EAAS,QAAQ;GACnB;GAOA,AAJA,EAAQ,SAAS,QAAQ,MACzB,EAAQ,KAAK,QAAQ,QACrBT,EAAQ,aAAa,GACrBA,EAAQ,KAAK,eAAeQ,CAAO,GACnCR,EAAQ,KAAK,WAAW;EAC1B;CAgDA;AACF"}
@@ -35,8 +35,8 @@ export interface NestedPositionHint {
35
35
  childrenAllowed?: boolean;
36
36
  }
37
37
  /**
38
- * A tree node of any record shape with stable keys addressable via configurable fields (keyField,
39
- * positionField, parentField). Admin-cms data types like `LinkedListItemKind` are assignable to this.
38
+ * A tree node of any record shape, addressed via configurable fields (keyField, positionField, parentField).
39
+ * Admin-cms types like `LinkedListItemKind` are assignable to it.
40
40
  */
41
41
  export interface NestedTreeNode<TItem = any> {
42
42
  data: TItem;
@@ -3,10 +3,10 @@ export declare const LIST_EDITOR_LOAD_TIMEOUT = 15000;
3
3
  /** `promise`, or a rejection with `message` once `timeout` ms pass without it settling. */
4
4
  export declare const withTimeout: <T>(promise: Promise<T>, timeout: number, message: string) => Promise<T>;
5
5
  /**
6
- * The list editor the bookmark dialog's manage tab needs, loaded when that tab is opened: it and
7
- * sortablejs under it are most of the dialog, and every list page carries the bookmark button.
8
- * Gives up after `timeout`, so a chunk that never arrives ends in an error the user can retry.
9
- * A retry helps when the chunk was only slow. After a failed fetch it helps only where the browser fetches
10
- * again: Chrome and Firefox kept the failure until the page reloaded, until the 2026 spec change (whatwg/html#10327).
6
+ * Loads the list editor for the bookmark dialog's manage tab when the tab opens. It
7
+ * and sortablejs are most of the dialog, and every list page has the bookmark button.
8
+ * Gives up after `timeout`, so a chunk that never arrives ends in a retryable error.
9
+ * A retry helps when the chunk was only slow. After a failed fetch it helps only where the browser fetches again.
10
+ * Chrome and Firefox kept the failure until reload, until the 2026 spec change (whatwg/html#10327).
11
11
  */
12
12
  export declare const loadListEditor: (timeout?: number) => Promise<Component>;
@@ -1 +1 @@
1
- {"version":3,"file":"listEditorLoader.js","names":["LIST_EDITOR_LOAD_TIMEOUT","withTimeout","timer","reject","message","timeout","resolve","value","error","loadListEditor","module"],"sources":["../../../../src/domains/listEditor/utils/listEditorLoader.ts"],"sourcesContent":["import type { Component } from 'vue'\n\nexport const LIST_EDITOR_LOAD_TIMEOUT = 15_000\n\n/** `promise`, or a rejection with `message` once `timeout` ms pass without it settling. */\nexport const withTimeout = <T>(promise: Promise<T>, timeout: number, message: string): Promise<T> =>\n new Promise((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(message)), timeout)\n promise.then(\n (value) => {\n clearTimeout(timer)\n resolve(value)\n },\n (error) => {\n clearTimeout(timer)\n reject(error)\n }\n )\n })\n\n/**\n * The list editor the bookmark dialog's manage tab needs, loaded when that tab is opened: it and\n * sortablejs under it are most of the dialog, and every list page carries the bookmark button.\n * Gives up after `timeout`, so a chunk that never arrives ends in an error the user can retry.\n * A retry helps when the chunk was only slow. After a failed fetch it helps only where the browser fetches\n * again: Chrome and Firefox kept the failure until the page reloaded, until the 2026 spec change (whatwg/html#10327).\n */\nexport const loadListEditor = (timeout = LIST_EDITOR_LOAD_TIMEOUT): Promise<Component> =>\n withTimeout(\n import('@/domains/listEditor/components/ASortableListEditor.vue').then((module) => module.default),\n timeout,\n `The list editor did not load within ${timeout} ms.`\n )\n"],"mappings":";AAEA,IAAaA,IAA2B,MAG3BC,KAAkB,GAAqB,GAAiB,MACnE,IAAI,SAAS,GAAS,MAAW;CAC/B,IAAMC,IAAQ,iBAAiBC,EAAW,MAAMC,CAAO,CAAC,GAAGC,CAAO;CAClE,EAAQ,MACL,MAAU;EAET,AADA,aAAaH,CAAK,GAClBI,EAAQC,CAAK;CACf,IACC,MAAU;EAET,AADA,aAAaL,CAAK,GAClBC,EAAOK,CAAK;CACd,CACF;AACF,CAAC,GASUC,KAAkB,IAAUT,MACvCC,EACE,OAAO,uCAA0D,CAAC,MAAM,MAAWS,EAAO,OAAO,GACjGL,GACA,uCAAuCA,EAAQ,KACjD"}
1
+ {"version":3,"file":"listEditorLoader.js","names":["LIST_EDITOR_LOAD_TIMEOUT","withTimeout","timer","reject","message","timeout","resolve","value","error","loadListEditor","module"],"sources":["../../../../src/domains/listEditor/utils/listEditorLoader.ts"],"sourcesContent":["import type { Component } from 'vue'\n\nexport const LIST_EDITOR_LOAD_TIMEOUT = 15_000\n\n/** `promise`, or a rejection with `message` once `timeout` ms pass without it settling. */\nexport const withTimeout = <T>(promise: Promise<T>, timeout: number, message: string): Promise<T> =>\n new Promise((resolve, reject) => {\n const timer = setTimeout(() => reject(new Error(message)), timeout)\n promise.then(\n (value) => {\n clearTimeout(timer)\n resolve(value)\n },\n (error) => {\n clearTimeout(timer)\n reject(error)\n }\n )\n })\n\n/**\n * Loads the list editor for the bookmark dialog's manage tab when the tab opens. It\n * and sortablejs are most of the dialog, and every list page has the bookmark button.\n * Gives up after `timeout`, so a chunk that never arrives ends in a retryable error.\n * A retry helps when the chunk was only slow. After a failed fetch it helps only where the browser fetches again.\n * Chrome and Firefox kept the failure until reload, until the 2026 spec change (whatwg/html#10327).\n */\nexport const loadListEditor = (timeout = LIST_EDITOR_LOAD_TIMEOUT): Promise<Component> =>\n withTimeout(\n import('@/domains/listEditor/components/ASortableListEditor.vue').then((module) => module.default),\n timeout,\n `The list editor did not load within ${timeout} ms.`\n )\n"],"mappings":";AAEA,IAAaA,IAA2B,MAG3BC,KAAkB,GAAqB,GAAiB,MACnE,IAAI,SAAS,GAAS,MAAW;CAC/B,IAAMC,IAAQ,iBAAiBC,EAAW,MAAMC,CAAO,CAAC,GAAGC,CAAO;CAClE,EAAQ,MACL,MAAU;EAET,AADA,aAAaH,CAAK,GAClBI,EAAQC,CAAK;CACf,IACC,MAAU;EAET,AADA,aAAaL,CAAK,GAClBC,EAAOK,CAAK;CACd,CACF;AACF,CAAC,GASUC,KAAkB,IAAUT,MACvCC,EACE,OAAO,uCAA0D,CAAC,MAAM,MAAWS,EAAO,OAAO,GACjGL,GACA,uCAAuCA,EAAQ,KACjD"}
@@ -1 +1 @@
1
- {"version":3,"file":"resolveCompactText.js","names":["resolveCompactText","options","v","raw","segment"],"sources":["../../../../src/domains/listEditor/utils/resolveCompactText.ts"],"sourcesContent":["// Compact (collapsed) display text for a list-editor row. Used by every\n// editor variant when the consumer didn't provide an `#item-compact` slot.\n// Consumers must opt in explicitly via `compactField` — there is NO implicit\n// fallback to common field names. Returns empty string otherwise; provide\n// the `#item-compact` slot for anything richer.\nexport function resolveCompactText<TItem extends Record<string, any>>(\n raw: TItem,\n options: { compactField?: string | null }\n): string {\n if (!options.compactField) return ''\n // A dotted path reads through nested objects (`texts.title`), which is how most entities in\n // these admins carry their label. A key without a dot behaves exactly as it always did, and a\n // path that runs into a missing or non-object step yields '' rather than throwing.\n let v: unknown = raw\n for (const segment of options.compactField.split('.')) {\n if (v === null || typeof v !== 'object') return ''\n v = (v as Record<string, unknown>)[segment]\n }\n return v == null || v === '' ? '' : String(v)\n}\n"],"mappings":";AAKA,SAAgBA,EACd,GACA,GACQ;CACR,IAAI,CAACC,EAAQ,cAAc,OAAO;CAIlC,IAAIC,IAAaC;CACjB,KAAK,IAAMC,KAAWH,EAAQ,aAAa,MAAM,GAAG,GAAG;EACrD,IAAkB,OAAOC,KAAM,aAA3BA,GAAqC,OAAO;EAChD,IAAKA,EAA8BE;CACrC;CACA,OAAOF,KAAK,QAAQA,MAAM,KAAK,KAAK,OAAOA,CAAC;AAC9C"}
1
+ {"version":3,"file":"resolveCompactText.js","names":["resolveCompactText","options","v","raw","segment"],"sources":["../../../../src/domains/listEditor/utils/resolveCompactText.ts"],"sourcesContent":["// Compact (collapsed) display text for a list-editor row. Used by every\n// editor variant when the consumer didn't provide an `#item-compact` slot.\n// Consumers must opt in explicitly via `compactField` — there is NO implicit\n// fallback to common field names. Returns empty string otherwise; provide\n// the `#item-compact` slot for anything richer.\nexport function resolveCompactText<TItem extends Record<string, any>>(\n raw: TItem,\n options: { compactField?: string | null }\n): string {\n if (!options.compactField) return ''\n // A dotted path reads through nested objects (`texts.title`), which is how most entities carry their label.\n // A path that hits a missing or non-object step yields '' instead of throwing.\n let v: unknown = raw\n for (const segment of options.compactField.split('.')) {\n if (v === null || typeof v !== 'object') return ''\n v = (v as Record<string, unknown>)[segment]\n }\n return v == null || v === '' ? '' : String(v)\n}\n"],"mappings":";AAKA,SAAgBA,EACd,GACA,GACQ;CACR,IAAI,CAACC,EAAQ,cAAc,OAAO;CAGlC,IAAIC,IAAaC;CACjB,KAAK,IAAMC,KAAWH,EAAQ,aAAa,MAAM,GAAG,GAAG;EACrD,IAAkB,OAAOC,KAAM,aAA3BA,GAAqC,OAAO;EAChD,IAAKA,EAA8BE;CACrC;CACA,OAAOF,KAAK,QAAQA,MAAM,KAAK,KAAK,OAAOA,CAAC;AAC9C"}
@@ -9,9 +9,8 @@ interface LogApiParams {
9
9
  type: LogTypeType;
10
10
  }
11
11
  /**
12
- * The backend and the endpoint both come from the caller, so these cannot be hoisted the way an
13
- * entity fetcher is -- every mount builds its own, which is also what gives each one its own
14
- * abort controller set.
12
+ * The caller provides the backend and the endpoint, so this cannot be hoisted like an entity fetcher.
13
+ * Each mount builds its own, which also gives each its own abort controller set.
15
14
  */
16
15
  export declare const useFetchLogList: ({ client, system, logPaths, type }: LogApiParams) => import('../../api/composables/useApiFetchList').UseApiFetchListReturnType<Log>;
17
16
  export declare const useFetchLog: ({ client, system, logPaths, type }: LogApiParams) => import('../../api/composables/useApiRequest').UseApiRequestReturnType<Log, null>;
@@ -1 +1 @@
1
- {"version":3,"file":"logApi.js","names":["useFetchLogList","useApiFetchList","logPaths","type","useFetchLog","useApiRequest"],"sources":["../../../../src/domains/log/api/logApi.ts"],"sourcesContent":["import type { AxiosClientFn } from '@/domains/api/utils/client'\nimport { useApiFetchList } from '@/domains/api/composables/useApiFetchList'\nimport { useApiRequest } from '@/domains/api/composables/useApiRequest'\nimport type { LogPaths, LogTypeType } from '@/domains/log/composables/logType'\nimport type { Log } from '@/domains/log/types/Log'\n\nexport const LOG_ENTITY = 'log'\n\ninterface LogApiParams {\n client: AxiosClientFn\n system: string\n logPaths: LogPaths\n type: LogTypeType\n}\n\n/**\n * The backend and the endpoint both come from the caller, so these cannot be hoisted the way an\n * entity fetcher is -- every mount builds its own, which is also what gives each one its own\n * abort controller set.\n */\nexport const useFetchLogList = ({ client, system, logPaths, type }: LogApiParams) =>\n useApiFetchList<Log>({\n client,\n system,\n entity: LOG_ENTITY,\n urlTemplate: logPaths[type],\n })\n\nexport const useFetchLog = ({ client, system, logPaths, type }: LogApiParams) =>\n useApiRequest<Log, null>({\n client,\n method: 'GET',\n system,\n entity: LOG_ENTITY,\n urlTemplate: logPaths[type] + '/:id',\n })\n"],"mappings":";;AAoBA,IAAaA,KAAmB,EAAE,WAAQ,WAAQ,aAAU,cAC1DC,EAAqB;CACnB;CACA;CACA,QAAA;CACA,aAAaC,EAASC;AACxB,CAAC,GAEUC,KAAe,EAAE,WAAQ,WAAQ,aAAU,cACtDC,EAAyB;CACvB;CACA,QAAQ;CACR;CACA,QAAA;CACA,aAAaH,EAASC,KAAQ;AAChC,CAAC"}
1
+ {"version":3,"file":"logApi.js","names":["useFetchLogList","useApiFetchList","logPaths","type","useFetchLog","useApiRequest"],"sources":["../../../../src/domains/log/api/logApi.ts"],"sourcesContent":["import type { AxiosClientFn } from '@/domains/api/utils/client'\nimport { useApiFetchList } from '@/domains/api/composables/useApiFetchList'\nimport { useApiRequest } from '@/domains/api/composables/useApiRequest'\nimport type { LogPaths, LogTypeType } from '@/domains/log/composables/logType'\nimport type { Log } from '@/domains/log/types/Log'\n\nexport const LOG_ENTITY = 'log'\n\ninterface LogApiParams {\n client: AxiosClientFn\n system: string\n logPaths: LogPaths\n type: LogTypeType\n}\n\n/**\n * The caller provides the backend and the endpoint, so this cannot be hoisted like an entity fetcher.\n * Each mount builds its own, which also gives each its own abort controller set.\n */\nexport const useFetchLogList = ({ client, system, logPaths, type }: LogApiParams) =>\n useApiFetchList<Log>({\n client,\n system,\n entity: LOG_ENTITY,\n urlTemplate: logPaths[type],\n })\n\nexport const useFetchLog = ({ client, system, logPaths, type }: LogApiParams) =>\n useApiRequest<Log, null>({\n client,\n method: 'GET',\n system,\n entity: LOG_ENTITY,\n urlTemplate: logPaths[type] + '/:id',\n })\n"],"mappings":";;AAmBA,IAAaA,KAAmB,EAAE,WAAQ,WAAQ,aAAU,cAC1DC,EAAqB;CACnB;CACA;CACA,QAAA;CACA,aAAaC,EAASC;AACxB,CAAC,GAEUC,KAAe,EAAE,WAAQ,WAAQ,aAAU,cACtDC,EAAyB;CACvB;CACA,QAAQ;CACR;CACA,QAAA;CACA,aAAaH,EAASC,KAAQ;AAChC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"ALogDatatable.js","names":["_sfc_main","ALogDatatable_vue_vue_type_script_setup_true_lang_default","ALogDatatable_default"],"sources":["../../../../src/domains/log/components/ALogDatatable.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { inject, onMounted, onBeforeUnmount, provide, watch } from 'vue'\nimport type { RouteLocationRaw } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\nimport { useDebounceFn } from '@vueuse/core'\nimport ACopyText from '@/domains/ui/components/ACopyText.vue'\nimport ADatatableConfigButton from '@/domains/filters/datatable/components/ADatatableConfigButton.vue'\nimport ADatetime from '@/domains/ui/datetime/components/ADatetime.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ADatatablePagination from '@/domains/filters/datatable/components/ADatatablePagination.vue'\nimport { createDatatableColumnsConfig } from '@/domains/filters/datatable/composables/createDatatableColumnsConfig'\nimport { DatatablePaginationKey, FilterConfigKey, FilterDataKey } from '@/domains/filters/utils/filterInjectionKeys'\nimport { useFilterHelpers } from '@/domains/filters/composables/filterFactory'\nimport { usePagination } from '@/domains/api/composables/pagination'\nimport { SORT_BY_ID } from '@/domains/filters/datatable/utils/datatableColumns'\nimport { useLogListActions } from '@/domains/log/composables/logActions'\nimport { LOG_ENTITY } from '@/domains/log/api/logApi'\nimport { LogType, type LogPaths, type LogTypeType } from '@/domains/log/composables/logType'\nimport type { Log } from '@/domains/log/types/Log'\nimport { isNull, isUndefined } from '@/shared/utils/common'\nimport { isDevelopment } from '@/shared/utils/development'\n\ntype DatatableItem = Log\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n type: LogTypeType\n logPaths: LogPaths\n /** Same mapper the view uses. Needed here so the actions cell stays a real link. */\n detailRoute: (log: Log) => RouteLocationRaw\n}>()\n\nconst emit = defineEmits<{\n (e: 'rowClick', log: Log): void\n}>()\n\n// The spinner belongs to the card above this table, so the flag is owned there.\nconst loading = defineModel<boolean>('loading', { default: false })\n\nconst filterConfig = inject(FilterConfigKey)\nconst filterData = inject(FilterDataKey)\nif (isUndefined(filterConfig) || isUndefined(filterData)) {\n throw new Error('[ALogDatatable] Incorrect provide/inject config.')\n}\n\n// Read once on purpose. Every one of these is fixed for the lifetime of this instance: the page\n// remounts the whole view through a `:key` when the system or the type changes, precisely because\n// `useApiFetchList` closes over its client and url, and reacting here could not undo that.\n/* eslint-disable vue/no-setup-props-reactivity-loss */\nconst { t } = useI18n()\nconst { fetchList, listItems, datatableHiddenColumns, cancel } = useLogListActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n loading,\n})\n\n// Neither the url hash nor local storage: the filter is kept per view in memory by the registry\n// in `logFilter`, and nothing about a log listing is worth persisting across a reload.\nconst { resetFilter, submitFilter, loadStoredFilters } = useFilterHelpers(filterData, filterConfig, {\n storeFiltersLocalStorage: false,\n populateUrlParams: false,\n})\n\nconst { pagination } = usePagination(SORT_BY_ID)\nprovide(DatatablePaginationKey, pagination)\n\n// Keyed by type, not by system: the sets differ between app and audit, and a column hidden in\n// audit must not disappear from the app table.\nconst { columnsVisible, columnsAll, columnsHidden } = createDatatableColumnsConfig(\n [\n { key: 'id' },\n { key: 'datetime' },\n { key: 'levelName' },\n { key: 'message' },\n { key: 'context.appVersion' },\n { key: 'context.contextId' },\n ...(props.type === LogType.Audit\n ? [{ key: 'context.resourceName' }, { key: 'context.resourceIds' }]\n : [{ key: 'context.httpStatus' }]),\n { key: 'context.userId' },\n { key: 'context.ip' },\n ],\n datatableHiddenColumns,\n 'common',\n LOG_ENTITY,\n { storeColumnsLocalStorage: `table_common_log_${props.type}` }\n)\n/* eslint-enable vue/no-setup-props-reactivity-loss */\n\nconst getList = useDebounceFn(async () => {\n await fetchList(pagination, filterData, filterConfig)\n})\n\nconst onRowClick = (_event: unknown, { item }: { item: DatatableItem }) => {\n if (item.id) emit('rowClick', item)\n}\n\nonMounted(() => {\n // Reads nothing back -- both persistences are off -- but it is what restores the page a user\n // was on when they close a detail, which `AActionCloseButtonHistory` flags for the next list.\n loadStoredFilters(pagination, getList)\n})\n\n// Everything above reads its props once, which is only correct while the page remounts this view\n// through a `:key`. Nothing would otherwise report a page that forgot: the table would keep\n// querying the old endpoint with the old columns under a new url, quietly.\nif (isDevelopment()) {\n watch(\n () => [props.system, props.type],\n () => {\n console.error(\n '[ALogDatatable] `system` or `type` changed in place. This view must be remounted -- ' +\n 'give it :key=\"`${system}/${type}`\". The endpoint and columns are bound at mount.'\n )\n }\n )\n}\n\nonBeforeUnmount(() => {\n // Both, and in this order. `cancel()` only invalidates what is already in flight; a debounce\n // still pending would fire after unmount, bump the generation past that invalidation and start\n // a request the token would then consider current.\n getList.cancel()\n cancel()\n})\n\ndefineExpose({\n refresh: getList,\n resetFilter: () => resetFilter(pagination, getList),\n submitFilter: () => submitFilter(pagination, getList),\n})\n</script>\n\n<template>\n <div>\n <div class=\"d-flex align-center\">\n <VSpacer />\n <ADatatableConfigButton\n v-model:columns-hidden=\"columnsHidden\"\n :columns-all=\"columnsAll\"\n />\n </div>\n <VDataTableServer\n class=\"a-datatable\"\n :headers=\"columnsVisible\"\n :items=\"listItems\"\n :items-length=\"listItems.length\"\n item-value=\"id\"\n @click:row=\"onRowClick\"\n >\n <template #item.datetime=\"{ item }: { item: DatatableItem }\">\n <ADatetime :date-time=\"item.datetime\" />\n </template>\n <template #item.message=\"{ item }: { item: DatatableItem }\">\n <div class=\"a-line-clamp-2\">\n {{ item.message }}\n </div>\n </template>\n <template #item.context.resourceIds=\"{ item }: { item: DatatableItem }\">\n {{ item.context.resourceIds.join(', ') }}\n </template>\n <template #item.context.contextId=\"{ item }: { item: DatatableItem }\">\n <ACopyText :value=\"item.context.contextId\" />\n </template>\n <template #item.context.userId=\"{ item }: { item: DatatableItem }\">\n <ACopyText\n v-if=\"!isNull(item.context.userId)\"\n :value=\"item.context.userId\"\n />\n </template>\n <template #item.actions=\"{ item }: { item: DatatableItem }\">\n <div class=\"d-flex justify-end\">\n <!--\n `:to`, not a click handler: an anchor is what makes middle-click and open-in-new-tab\n work on a list people open several entries from, and it is what the smoke spec scrapes\n to find a row id.\n -->\n <VBtn\n :to=\"detailRoute(item)\"\n class=\"ml-1\"\n icon=\"mdi-information-outline\"\n :aria-label=\"t('common.button.detail')\"\n size=\"x-small\"\n variant=\"text\"\n />\n </div>\n </template>\n <template #bottom>\n <ADatatablePagination @change=\"getList\" />\n </template>\n </VDataTableServer>\n </div>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ALogDatatable.js","names":["_sfc_main","ALogDatatable_vue_vue_type_script_setup_true_lang_default","ALogDatatable_default"],"sources":["../../../../src/domains/log/components/ALogDatatable.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { inject, onMounted, onBeforeUnmount, provide, watch } from 'vue'\nimport type { RouteLocationRaw } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\nimport { useDebounceFn } from '@vueuse/core'\nimport ACopyText from '@/domains/ui/components/ACopyText.vue'\nimport ADatatableConfigButton from '@/domains/filters/datatable/components/ADatatableConfigButton.vue'\nimport ADatetime from '@/domains/ui/datetime/components/ADatetime.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ADatatablePagination from '@/domains/filters/datatable/components/ADatatablePagination.vue'\nimport { createDatatableColumnsConfig } from '@/domains/filters/datatable/composables/createDatatableColumnsConfig'\nimport { DatatablePaginationKey, FilterConfigKey, FilterDataKey } from '@/domains/filters/utils/filterInjectionKeys'\nimport { useFilterHelpers } from '@/domains/filters/composables/filterFactory'\nimport { usePagination } from '@/domains/api/composables/pagination'\nimport { SORT_BY_ID } from '@/domains/filters/datatable/utils/datatableColumns'\nimport { useLogListActions } from '@/domains/log/composables/logActions'\nimport { LOG_ENTITY } from '@/domains/log/api/logApi'\nimport { LogType, type LogPaths, type LogTypeType } from '@/domains/log/composables/logType'\nimport type { Log } from '@/domains/log/types/Log'\nimport { isNull, isUndefined } from '@/shared/utils/common'\nimport { isDevelopment } from '@/shared/utils/development'\n\ntype DatatableItem = Log\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n type: LogTypeType\n logPaths: LogPaths\n /** Same mapper the view uses. Needed here so the actions cell stays a real link. */\n detailRoute: (log: Log) => RouteLocationRaw\n}>()\n\nconst emit = defineEmits<{\n (e: 'rowClick', log: Log): void\n}>()\n\n// The spinner belongs to the card above this table, so the flag is owned there.\nconst loading = defineModel<boolean>('loading', { default: false })\n\nconst filterConfig = inject(FilterConfigKey)\nconst filterData = inject(FilterDataKey)\nif (isUndefined(filterConfig) || isUndefined(filterData)) {\n throw new Error('[ALogDatatable] Incorrect provide/inject config.')\n}\n\n// Read once on purpose. These are fixed for this instance's lifetime.\n// The page remounts the view via `:key` on system or type change,\n// because `useApiFetchList` closes over its client and url.\n/* eslint-disable vue/no-setup-props-reactivity-loss */\nconst { t } = useI18n()\nconst { fetchList, listItems, datatableHiddenColumns, cancel } = useLogListActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n loading,\n})\n\n// No url hash and no local storage. The `logFilter` registry keeps the filter per view in memory.\n// Nothing about a log listing is worth persisting across a reload.\nconst { resetFilter, submitFilter, loadStoredFilters } = useFilterHelpers(filterData, filterConfig, {\n storeFiltersLocalStorage: false,\n populateUrlParams: false,\n})\n\nconst { pagination } = usePagination(SORT_BY_ID)\nprovide(DatatablePaginationKey, pagination)\n\n// Keyed by type, not by system. The column sets differ between app and audit.\n// A column hidden in audit must not disappear from the app table.\nconst { columnsVisible, columnsAll, columnsHidden } = createDatatableColumnsConfig(\n [\n { key: 'id' },\n { key: 'datetime' },\n { key: 'levelName' },\n { key: 'message' },\n { key: 'context.appVersion' },\n { key: 'context.contextId' },\n ...(props.type === LogType.Audit\n ? [{ key: 'context.resourceName' }, { key: 'context.resourceIds' }]\n : [{ key: 'context.httpStatus' }]),\n { key: 'context.userId' },\n { key: 'context.ip' },\n ],\n datatableHiddenColumns,\n 'common',\n LOG_ENTITY,\n { storeColumnsLocalStorage: `table_common_log_${props.type}` }\n)\n/* eslint-enable vue/no-setup-props-reactivity-loss */\n\nconst getList = useDebounceFn(async () => {\n await fetchList(pagination, filterData, filterConfig)\n})\n\nconst onRowClick = (_event: unknown, { item }: { item: DatatableItem }) => {\n if (item.id) emit('rowClick', item)\n}\n\nonMounted(() => {\n // Both persistences are off, so it reads nothing back.\n // It still restores the page a user was on after closing a detail,\n // which `AActionCloseButtonHistory` flags for the next list.\n loadStoredFilters(pagination, getList)\n})\n\n// The code above reads props once, which is only correct while the page remounts this view via `:key`.\n// Otherwise the table would silently keep querying the old endpoint with the old columns.\nif (isDevelopment()) {\n watch(\n () => [props.system, props.type],\n () => {\n console.error(\n '[ALogDatatable] `system` or `type` changed in place. This view must be remounted -- ' +\n 'give it :key=\"`${system}/${type}`\". The endpoint and columns are bound at mount.'\n )\n }\n )\n}\n\nonBeforeUnmount(() => {\n // Both calls, in this order. `cancel()` only invalidates requests already in flight.\n // A pending debounce would fire after unmount, bump the generation past\n // that invalidation and start a request the token treats as current.\n getList.cancel()\n cancel()\n})\n\ndefineExpose({\n refresh: getList,\n resetFilter: () => resetFilter(pagination, getList),\n submitFilter: () => submitFilter(pagination, getList),\n})\n</script>\n\n<template>\n <div>\n <div class=\"d-flex align-center\">\n <VSpacer />\n <ADatatableConfigButton\n v-model:columns-hidden=\"columnsHidden\"\n :columns-all=\"columnsAll\"\n />\n </div>\n <VDataTableServer\n class=\"a-datatable\"\n :headers=\"columnsVisible\"\n :items=\"listItems\"\n :items-length=\"listItems.length\"\n item-value=\"id\"\n @click:row=\"onRowClick\"\n >\n <template #item.datetime=\"{ item }: { item: DatatableItem }\">\n <ADatetime :date-time=\"item.datetime\" />\n </template>\n <template #item.message=\"{ item }: { item: DatatableItem }\">\n <div class=\"a-line-clamp-2\">\n {{ item.message }}\n </div>\n </template>\n <template #item.context.resourceIds=\"{ item }: { item: DatatableItem }\">\n {{ item.context.resourceIds.join(', ') }}\n </template>\n <template #item.context.contextId=\"{ item }: { item: DatatableItem }\">\n <ACopyText :value=\"item.context.contextId\" />\n </template>\n <template #item.context.userId=\"{ item }: { item: DatatableItem }\">\n <ACopyText\n v-if=\"!isNull(item.context.userId)\"\n :value=\"item.context.userId\"\n />\n </template>\n <template #item.actions=\"{ item }: { item: DatatableItem }\">\n <div class=\"d-flex justify-end\">\n <!--\n `:to`, not a click handler. An anchor makes middle-click and open-in-new-tab work.\n The smoke spec also scrapes it to find a row id.\n -->\n <VBtn\n :to=\"detailRoute(item)\"\n class=\"ml-1\"\n icon=\"mdi-information-outline\"\n :aria-label=\"t('common.button.detail')\"\n size=\"x-small\"\n variant=\"text\"\n />\n </div>\n </template>\n <template #bottom>\n <ADatatablePagination @change=\"getList\" />\n </template>\n </VDataTableServer>\n </div>\n</template>\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"ALogDatatable.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_component_VSpacer","ADatatableConfigButton","_unref","_isRef","_component_VDataTableServer","_withCtx","ADatetime","_toDisplayString","_createTextVNode","ACopyText","_createBlock","_createCommentVNode","_component_VBtn","ADatatablePagination","ADatatableConfigButton_default","ADatetime_default","ACopyText_default","ADatatablePagination_default","_hoisted_1","_hoisted_2","_hoisted_3","ALogDatatable_vue_vue_type_script_setup_true_lang_default","\"loading\"","\"loadingModifiers\"","__expose","__emit","props","__props","emit","loading","useModel","filterConfig","inject","FilterConfigKey","filterData","FilterDataKey","isUndefined","useI18n","useLogListActions","useFilterHelpers","usePagination","DatatablePaginationKey","pagination","createDatatableColumnsConfig","LogType","datatableHiddenColumns","getList","useDebounceFn","fetchList","onRowClick","item","onMounted","isDevelopment","watch","onBeforeUnmount","cancel","resetFilter","submitFilter","openBlock","createElementBlock","createElementVNode","createVNode","VSpacer","unref","columnsHidden","_cache","isRef","$event","columnsAll","VDataTableServer","columnsVisible","listItems","withCtx","toDisplayString","createTextVNode","isNull","createCommentVNode","createBlock","VBtn","t"],"sources":["../../../../src/domains/log/components/ALogDatatable.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { inject, onMounted, onBeforeUnmount, provide, watch } from 'vue'\nimport type { RouteLocationRaw } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\nimport { useDebounceFn } from '@vueuse/core'\nimport ACopyText from '@/domains/ui/components/ACopyText.vue'\nimport ADatatableConfigButton from '@/domains/filters/datatable/components/ADatatableConfigButton.vue'\nimport ADatetime from '@/domains/ui/datetime/components/ADatetime.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ADatatablePagination from '@/domains/filters/datatable/components/ADatatablePagination.vue'\nimport { createDatatableColumnsConfig } from '@/domains/filters/datatable/composables/createDatatableColumnsConfig'\nimport { DatatablePaginationKey, FilterConfigKey, FilterDataKey } from '@/domains/filters/utils/filterInjectionKeys'\nimport { useFilterHelpers } from '@/domains/filters/composables/filterFactory'\nimport { usePagination } from '@/domains/api/composables/pagination'\nimport { SORT_BY_ID } from '@/domains/filters/datatable/utils/datatableColumns'\nimport { useLogListActions } from '@/domains/log/composables/logActions'\nimport { LOG_ENTITY } from '@/domains/log/api/logApi'\nimport { LogType, type LogPaths, type LogTypeType } from '@/domains/log/composables/logType'\nimport type { Log } from '@/domains/log/types/Log'\nimport { isNull, isUndefined } from '@/shared/utils/common'\nimport { isDevelopment } from '@/shared/utils/development'\n\ntype DatatableItem = Log\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n type: LogTypeType\n logPaths: LogPaths\n /** Same mapper the view uses. Needed here so the actions cell stays a real link. */\n detailRoute: (log: Log) => RouteLocationRaw\n}>()\n\nconst emit = defineEmits<{\n (e: 'rowClick', log: Log): void\n}>()\n\n// The spinner belongs to the card above this table, so the flag is owned there.\nconst loading = defineModel<boolean>('loading', { default: false })\n\nconst filterConfig = inject(FilterConfigKey)\nconst filterData = inject(FilterDataKey)\nif (isUndefined(filterConfig) || isUndefined(filterData)) {\n throw new Error('[ALogDatatable] Incorrect provide/inject config.')\n}\n\n// Read once on purpose. Every one of these is fixed for the lifetime of this instance: the page\n// remounts the whole view through a `:key` when the system or the type changes, precisely because\n// `useApiFetchList` closes over its client and url, and reacting here could not undo that.\n/* eslint-disable vue/no-setup-props-reactivity-loss */\nconst { t } = useI18n()\nconst { fetchList, listItems, datatableHiddenColumns, cancel } = useLogListActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n loading,\n})\n\n// Neither the url hash nor local storage: the filter is kept per view in memory by the registry\n// in `logFilter`, and nothing about a log listing is worth persisting across a reload.\nconst { resetFilter, submitFilter, loadStoredFilters } = useFilterHelpers(filterData, filterConfig, {\n storeFiltersLocalStorage: false,\n populateUrlParams: false,\n})\n\nconst { pagination } = usePagination(SORT_BY_ID)\nprovide(DatatablePaginationKey, pagination)\n\n// Keyed by type, not by system: the sets differ between app and audit, and a column hidden in\n// audit must not disappear from the app table.\nconst { columnsVisible, columnsAll, columnsHidden } = createDatatableColumnsConfig(\n [\n { key: 'id' },\n { key: 'datetime' },\n { key: 'levelName' },\n { key: 'message' },\n { key: 'context.appVersion' },\n { key: 'context.contextId' },\n ...(props.type === LogType.Audit\n ? [{ key: 'context.resourceName' }, { key: 'context.resourceIds' }]\n : [{ key: 'context.httpStatus' }]),\n { key: 'context.userId' },\n { key: 'context.ip' },\n ],\n datatableHiddenColumns,\n 'common',\n LOG_ENTITY,\n { storeColumnsLocalStorage: `table_common_log_${props.type}` }\n)\n/* eslint-enable vue/no-setup-props-reactivity-loss */\n\nconst getList = useDebounceFn(async () => {\n await fetchList(pagination, filterData, filterConfig)\n})\n\nconst onRowClick = (_event: unknown, { item }: { item: DatatableItem }) => {\n if (item.id) emit('rowClick', item)\n}\n\nonMounted(() => {\n // Reads nothing back -- both persistences are off -- but it is what restores the page a user\n // was on when they close a detail, which `AActionCloseButtonHistory` flags for the next list.\n loadStoredFilters(pagination, getList)\n})\n\n// Everything above reads its props once, which is only correct while the page remounts this view\n// through a `:key`. Nothing would otherwise report a page that forgot: the table would keep\n// querying the old endpoint with the old columns under a new url, quietly.\nif (isDevelopment()) {\n watch(\n () => [props.system, props.type],\n () => {\n console.error(\n '[ALogDatatable] `system` or `type` changed in place. This view must be remounted -- ' +\n 'give it :key=\"`${system}/${type}`\". The endpoint and columns are bound at mount.'\n )\n }\n )\n}\n\nonBeforeUnmount(() => {\n // Both, and in this order. `cancel()` only invalidates what is already in flight; a debounce\n // still pending would fire after unmount, bump the generation past that invalidation and start\n // a request the token would then consider current.\n getList.cancel()\n cancel()\n})\n\ndefineExpose({\n refresh: getList,\n resetFilter: () => resetFilter(pagination, getList),\n submitFilter: () => submitFilter(pagination, getList),\n})\n</script>\n\n<template>\n <div>\n <div class=\"d-flex align-center\">\n <VSpacer />\n <ADatatableConfigButton\n v-model:columns-hidden=\"columnsHidden\"\n :columns-all=\"columnsAll\"\n />\n </div>\n <VDataTableServer\n class=\"a-datatable\"\n :headers=\"columnsVisible\"\n :items=\"listItems\"\n :items-length=\"listItems.length\"\n item-value=\"id\"\n @click:row=\"onRowClick\"\n >\n <template #item.datetime=\"{ item }: { item: DatatableItem }\">\n <ADatetime :date-time=\"item.datetime\" />\n </template>\n <template #item.message=\"{ item }: { item: DatatableItem }\">\n <div class=\"a-line-clamp-2\">\n {{ item.message }}\n </div>\n </template>\n <template #item.context.resourceIds=\"{ item }: { item: DatatableItem }\">\n {{ item.context.resourceIds.join(', ') }}\n </template>\n <template #item.context.contextId=\"{ item }: { item: DatatableItem }\">\n <ACopyText :value=\"item.context.contextId\" />\n </template>\n <template #item.context.userId=\"{ item }: { item: DatatableItem }\">\n <ACopyText\n v-if=\"!isNull(item.context.userId)\"\n :value=\"item.context.userId\"\n />\n </template>\n <template #item.actions=\"{ item }: { item: DatatableItem }\">\n <div class=\"d-flex justify-end\">\n <!--\n `:to`, not a click handler: an anchor is what makes middle-click and open-in-new-tab\n work on a list people open several entries from, and it is what the smoke spec scrapes\n to find a row id.\n -->\n <VBtn\n :to=\"detailRoute(item)\"\n class=\"ml-1\"\n icon=\"mdi-information-outline\"\n :aria-label=\"t('common.button.detail')\"\n size=\"x-small\"\n variant=\"text\"\n />\n </div>\n </template>\n <template #bottom>\n <ADatatablePagination @change=\"getList\" />\n </template>\n </VDataTableServer>\n </div>\n</template>\n"],"mappings":"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"}
1
+ {"version":3,"file":"ALogDatatable.vue_vue_type_script_setup_true_lang.js","names":["_useModel","_openBlock","_createElementBlock","_createElementVNode","_createVNode","_component_VSpacer","ADatatableConfigButton","_unref","_isRef","_component_VDataTableServer","_withCtx","ADatetime","_toDisplayString","_createTextVNode","ACopyText","_createBlock","_createCommentVNode","_component_VBtn","ADatatablePagination","ADatatableConfigButton_default","ADatetime_default","ACopyText_default","ADatatablePagination_default","_hoisted_1","_hoisted_2","_hoisted_3","ALogDatatable_vue_vue_type_script_setup_true_lang_default","\"loading\"","\"loadingModifiers\"","__expose","__emit","props","__props","emit","loading","useModel","filterConfig","inject","FilterConfigKey","filterData","FilterDataKey","isUndefined","useI18n","useLogListActions","useFilterHelpers","usePagination","DatatablePaginationKey","pagination","createDatatableColumnsConfig","LogType","datatableHiddenColumns","getList","useDebounceFn","fetchList","onRowClick","item","onMounted","isDevelopment","watch","onBeforeUnmount","cancel","resetFilter","submitFilter","openBlock","createElementBlock","createElementVNode","createVNode","VSpacer","unref","columnsHidden","_cache","isRef","$event","columnsAll","VDataTableServer","columnsVisible","listItems","withCtx","toDisplayString","createTextVNode","isNull","createCommentVNode","createBlock","VBtn","t"],"sources":["../../../../src/domains/log/components/ALogDatatable.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { inject, onMounted, onBeforeUnmount, provide, watch } from 'vue'\nimport type { RouteLocationRaw } from 'vue-router'\nimport { useI18n } from 'vue-i18n'\nimport { useDebounceFn } from '@vueuse/core'\nimport ACopyText from '@/domains/ui/components/ACopyText.vue'\nimport ADatatableConfigButton from '@/domains/filters/datatable/components/ADatatableConfigButton.vue'\nimport ADatetime from '@/domains/ui/datetime/components/ADatetime.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ADatatablePagination from '@/domains/filters/datatable/components/ADatatablePagination.vue'\nimport { createDatatableColumnsConfig } from '@/domains/filters/datatable/composables/createDatatableColumnsConfig'\nimport { DatatablePaginationKey, FilterConfigKey, FilterDataKey } from '@/domains/filters/utils/filterInjectionKeys'\nimport { useFilterHelpers } from '@/domains/filters/composables/filterFactory'\nimport { usePagination } from '@/domains/api/composables/pagination'\nimport { SORT_BY_ID } from '@/domains/filters/datatable/utils/datatableColumns'\nimport { useLogListActions } from '@/domains/log/composables/logActions'\nimport { LOG_ENTITY } from '@/domains/log/api/logApi'\nimport { LogType, type LogPaths, type LogTypeType } from '@/domains/log/composables/logType'\nimport type { Log } from '@/domains/log/types/Log'\nimport { isNull, isUndefined } from '@/shared/utils/common'\nimport { isDevelopment } from '@/shared/utils/development'\n\ntype DatatableItem = Log\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n type: LogTypeType\n logPaths: LogPaths\n /** Same mapper the view uses. Needed here so the actions cell stays a real link. */\n detailRoute: (log: Log) => RouteLocationRaw\n}>()\n\nconst emit = defineEmits<{\n (e: 'rowClick', log: Log): void\n}>()\n\n// The spinner belongs to the card above this table, so the flag is owned there.\nconst loading = defineModel<boolean>('loading', { default: false })\n\nconst filterConfig = inject(FilterConfigKey)\nconst filterData = inject(FilterDataKey)\nif (isUndefined(filterConfig) || isUndefined(filterData)) {\n throw new Error('[ALogDatatable] Incorrect provide/inject config.')\n}\n\n// Read once on purpose. These are fixed for this instance's lifetime.\n// The page remounts the view via `:key` on system or type change,\n// because `useApiFetchList` closes over its client and url.\n/* eslint-disable vue/no-setup-props-reactivity-loss */\nconst { t } = useI18n()\nconst { fetchList, listItems, datatableHiddenColumns, cancel } = useLogListActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n loading,\n})\n\n// No url hash and no local storage. The `logFilter` registry keeps the filter per view in memory.\n// Nothing about a log listing is worth persisting across a reload.\nconst { resetFilter, submitFilter, loadStoredFilters } = useFilterHelpers(filterData, filterConfig, {\n storeFiltersLocalStorage: false,\n populateUrlParams: false,\n})\n\nconst { pagination } = usePagination(SORT_BY_ID)\nprovide(DatatablePaginationKey, pagination)\n\n// Keyed by type, not by system. The column sets differ between app and audit.\n// A column hidden in audit must not disappear from the app table.\nconst { columnsVisible, columnsAll, columnsHidden } = createDatatableColumnsConfig(\n [\n { key: 'id' },\n { key: 'datetime' },\n { key: 'levelName' },\n { key: 'message' },\n { key: 'context.appVersion' },\n { key: 'context.contextId' },\n ...(props.type === LogType.Audit\n ? [{ key: 'context.resourceName' }, { key: 'context.resourceIds' }]\n : [{ key: 'context.httpStatus' }]),\n { key: 'context.userId' },\n { key: 'context.ip' },\n ],\n datatableHiddenColumns,\n 'common',\n LOG_ENTITY,\n { storeColumnsLocalStorage: `table_common_log_${props.type}` }\n)\n/* eslint-enable vue/no-setup-props-reactivity-loss */\n\nconst getList = useDebounceFn(async () => {\n await fetchList(pagination, filterData, filterConfig)\n})\n\nconst onRowClick = (_event: unknown, { item }: { item: DatatableItem }) => {\n if (item.id) emit('rowClick', item)\n}\n\nonMounted(() => {\n // Both persistences are off, so it reads nothing back.\n // It still restores the page a user was on after closing a detail,\n // which `AActionCloseButtonHistory` flags for the next list.\n loadStoredFilters(pagination, getList)\n})\n\n// The code above reads props once, which is only correct while the page remounts this view via `:key`.\n// Otherwise the table would silently keep querying the old endpoint with the old columns.\nif (isDevelopment()) {\n watch(\n () => [props.system, props.type],\n () => {\n console.error(\n '[ALogDatatable] `system` or `type` changed in place. This view must be remounted -- ' +\n 'give it :key=\"`${system}/${type}`\". The endpoint and columns are bound at mount.'\n )\n }\n )\n}\n\nonBeforeUnmount(() => {\n // Both calls, in this order. `cancel()` only invalidates requests already in flight.\n // A pending debounce would fire after unmount, bump the generation past\n // that invalidation and start a request the token treats as current.\n getList.cancel()\n cancel()\n})\n\ndefineExpose({\n refresh: getList,\n resetFilter: () => resetFilter(pagination, getList),\n submitFilter: () => submitFilter(pagination, getList),\n})\n</script>\n\n<template>\n <div>\n <div class=\"d-flex align-center\">\n <VSpacer />\n <ADatatableConfigButton\n v-model:columns-hidden=\"columnsHidden\"\n :columns-all=\"columnsAll\"\n />\n </div>\n <VDataTableServer\n class=\"a-datatable\"\n :headers=\"columnsVisible\"\n :items=\"listItems\"\n :items-length=\"listItems.length\"\n item-value=\"id\"\n @click:row=\"onRowClick\"\n >\n <template #item.datetime=\"{ item }: { item: DatatableItem }\">\n <ADatetime :date-time=\"item.datetime\" />\n </template>\n <template #item.message=\"{ item }: { item: DatatableItem }\">\n <div class=\"a-line-clamp-2\">\n {{ item.message }}\n </div>\n </template>\n <template #item.context.resourceIds=\"{ item }: { item: DatatableItem }\">\n {{ item.context.resourceIds.join(', ') }}\n </template>\n <template #item.context.contextId=\"{ item }: { item: DatatableItem }\">\n <ACopyText :value=\"item.context.contextId\" />\n </template>\n <template #item.context.userId=\"{ item }: { item: DatatableItem }\">\n <ACopyText\n v-if=\"!isNull(item.context.userId)\"\n :value=\"item.context.userId\"\n />\n </template>\n <template #item.actions=\"{ item }: { item: DatatableItem }\">\n <div class=\"d-flex justify-end\">\n <!--\n `:to`, not a click handler. An anchor makes middle-click and open-in-new-tab work.\n The smoke spec also scrapes it to find a row id.\n -->\n <VBtn\n :to=\"detailRoute(item)\"\n class=\"ml-1\"\n icon=\"mdi-information-outline\"\n :aria-label=\"t('common.button.detail')\"\n size=\"x-small\"\n variant=\"text\"\n />\n </div>\n </template>\n <template #bottom>\n <ADatatablePagination @change=\"getList\" />\n </template>\n </VDataTableServer>\n </div>\n</template>\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"ALogDetailView.js","names":["_sfc_main","ALogDetailView_vue_vue_type_script_setup_true_lang_default","ALogDetailView_default"],"sources":["../../../../src/domains/log/components/ALogDetailView.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { onBeforeUnmount, onMounted } from 'vue'\nimport type { RouteRecordName } from 'vue-router'\nimport ACard from '@/domains/ui/components/ACard.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ALogDetail from '@/domains/log/components/ALogDetail.vue'\nimport { useLogDetailActions } from '@/domains/log/composables/logActions'\nimport { useRecordPage } from '@/domains/system/composables/recordPage'\nimport type { LogPaths, LogTypeType } from '@/domains/log/composables/logType'\nimport { isNull } from '@/shared/utils/common'\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n /** From the route. A log id means nothing without the store it came from. */\n type: LogTypeType\n id: string\n logPaths: LogPaths\n /** Where a log that cannot be loaded leaves to when the history has nowhere: the page's Close fallback. */\n fallbackRouteName?: RouteRecordName\n fallbackRouteParams?: Record<string, any>\n}>()\n\n// Read once: the page keys this view on `${system}/${type}/${id}`, so a change remounts it.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { log, detailLoading, fetchData, cancel } = useLogDetailActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n})\n\n// Without `loading`: the view has no buttons to hide, and a page that gives no fallback would keep\n// the card loading for good once a fresh tab has nowhere to go back to.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { leave } = useRecordPage({\n fallbackRouteName: props.fallbackRouteName,\n fallbackRouteParams: props.fallbackRouteParams,\n})\n\nonMounted(async () => {\n if ((await fetchData(props.id)) === false) await leave()\n})\n\nonBeforeUnmount(() => {\n cancel()\n})\n</script>\n\n<template>\n <ACard :loading=\"detailLoading\">\n <VCardText>\n <ALogDetail\n v-if=\"!isNull(log)\"\n :log=\"log\"\n />\n </VCardText>\n </ACard>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ALogDetailView.js","names":["_sfc_main","ALogDetailView_vue_vue_type_script_setup_true_lang_default","ALogDetailView_default"],"sources":["../../../../src/domains/log/components/ALogDetailView.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { onBeforeUnmount, onMounted } from 'vue'\nimport type { RouteRecordName } from 'vue-router'\nimport ACard from '@/domains/ui/components/ACard.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ALogDetail from '@/domains/log/components/ALogDetail.vue'\nimport { useLogDetailActions } from '@/domains/log/composables/logActions'\nimport { useRecordPage } from '@/domains/system/composables/recordPage'\nimport type { LogPaths, LogTypeType } from '@/domains/log/composables/logType'\nimport { isNull } from '@/shared/utils/common'\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n /** From the route. A log id means nothing without the store it came from. */\n type: LogTypeType\n id: string\n logPaths: LogPaths\n /** Where a log that cannot be loaded leaves to when history is empty. The page's Close fallback. */\n fallbackRouteName?: RouteRecordName\n fallbackRouteParams?: Record<string, any>\n}>()\n\n// Read once: the page keys this view on `${system}/${type}/${id}`, so a change remounts it.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { log, detailLoading, fetchData, cancel } = useLogDetailActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n})\n\n// No `loading`: the view has no buttons to hide.\n// With it, a page without a fallback would keep the card loading forever in a fresh tab.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { leave } = useRecordPage({\n fallbackRouteName: props.fallbackRouteName,\n fallbackRouteParams: props.fallbackRouteParams,\n})\n\nonMounted(async () => {\n if ((await fetchData(props.id)) === false) await leave()\n})\n\nonBeforeUnmount(() => {\n cancel()\n})\n</script>\n\n<template>\n <ACard :loading=\"detailLoading\">\n <VCardText>\n <ALogDetail\n v-if=\"!isNull(log)\"\n :log=\"log\"\n />\n </VCardText>\n </ACard>\n</template>\n"],"mappings":""}
@@ -8,7 +8,7 @@ type __VLS_Props = {
8
8
  type: LogTypeType;
9
9
  id: string;
10
10
  logPaths: LogPaths;
11
- /** Where a log that cannot be loaded leaves to when the history has nowhere: the page's Close fallback. */
11
+ /** Where a log that cannot be loaded leaves to when history is empty. The page's Close fallback. */
12
12
  fallbackRouteName?: RouteRecordName;
13
13
  fallbackRouteParams?: Record<string, any>;
14
14
  };
@@ -1 +1 @@
1
- {"version":3,"file":"ALogDetailView.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","ACard","_unref","_withCtx","_createVNode","_component_VCardText","ALogDetail","_createCommentVNode","ACard_default","ALogDetail_default","ALogDetailView_vue_vue_type_script_setup_true_lang_default","props","__props","useLogDetailActions","useRecordPage","onMounted","fetchData","leave","onBeforeUnmount","openBlock","createBlock","unref","detailLoading","withCtx","createVNode","VCardText","isNull","log","createCommentVNode"],"sources":["../../../../src/domains/log/components/ALogDetailView.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { onBeforeUnmount, onMounted } from 'vue'\nimport type { RouteRecordName } from 'vue-router'\nimport ACard from '@/domains/ui/components/ACard.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ALogDetail from '@/domains/log/components/ALogDetail.vue'\nimport { useLogDetailActions } from '@/domains/log/composables/logActions'\nimport { useRecordPage } from '@/domains/system/composables/recordPage'\nimport type { LogPaths, LogTypeType } from '@/domains/log/composables/logType'\nimport { isNull } from '@/shared/utils/common'\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n /** From the route. A log id means nothing without the store it came from. */\n type: LogTypeType\n id: string\n logPaths: LogPaths\n /** Where a log that cannot be loaded leaves to when the history has nowhere: the page's Close fallback. */\n fallbackRouteName?: RouteRecordName\n fallbackRouteParams?: Record<string, any>\n}>()\n\n// Read once: the page keys this view on `${system}/${type}/${id}`, so a change remounts it.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { log, detailLoading, fetchData, cancel } = useLogDetailActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n})\n\n// Without `loading`: the view has no buttons to hide, and a page that gives no fallback would keep\n// the card loading for good once a fresh tab has nowhere to go back to.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { leave } = useRecordPage({\n fallbackRouteName: props.fallbackRouteName,\n fallbackRouteParams: props.fallbackRouteParams,\n})\n\nonMounted(async () => {\n if ((await fetchData(props.id)) === false) await leave()\n})\n\nonBeforeUnmount(() => {\n cancel()\n})\n</script>\n\n<template>\n <ACard :loading=\"detailLoading\">\n <VCardText>\n <ALogDetail\n v-if=\"!isNull(log)\"\n :log=\"log\"\n />\n </VCardText>\n </ACard>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAWA,IAAMY,IAAQC,GAcR,EAAE,QAAK,kBAAe,cAAW,cAAWC,EAAoB;GACpE,QAAQF,EAAM;GACd,QAAQA,EAAM;GACd,UAAUA,EAAM;GAChB,MAAMA,EAAM;EACd,CAAC,GAKK,EAAE,aAAUG,EAAc;GAC9B,mBAAmBH,EAAM;GACzB,qBAAqBA,EAAM;EAC7B,CAAC;E,OAEDI,EAAU,YAAY;GACpB,AAAK,MAAMC,EAAUL,EAAM,EAAE,MAAO,MAAO,MAAMM,EAAM;EACzD,CAAC,GAEDC,QAAsB;GACpB,EAAO;EACT,CAAC,I,UAICnB,EAAA,GAAAC,EAOQC,GAAA,EAPA,SAASC,EAAAoB,CAAA,EAAa,GAAA;GAC5B,SAAAnB,QAKY,CALZC,EAKYC,GAAA,MAAA;IAJV,SAAAF,QAGE,CAFOD,EAAAwB,CAAA,CAAM,CAACxB,EAAAyB,CAAA,CAAG,I,aADnB5B,EAAA,GAAAC,EAGEM,GAAA;;KADC,KAAKJ,EAAAyB,CAAA"}
1
+ {"version":3,"file":"ALogDetailView.vue_vue_type_script_setup_true_lang.js","names":["_openBlock","_createBlock","ACard","_unref","_withCtx","_createVNode","_component_VCardText","ALogDetail","_createCommentVNode","ACard_default","ALogDetail_default","ALogDetailView_vue_vue_type_script_setup_true_lang_default","props","__props","useLogDetailActions","useRecordPage","onMounted","fetchData","leave","onBeforeUnmount","openBlock","createBlock","unref","detailLoading","withCtx","createVNode","VCardText","isNull","log","createCommentVNode"],"sources":["../../../../src/domains/log/components/ALogDetailView.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { onBeforeUnmount, onMounted } from 'vue'\nimport type { RouteRecordName } from 'vue-router'\nimport ACard from '@/domains/ui/components/ACard.vue'\nimport type { AxiosClientFn } from '@/domains/api/utils/client'\nimport ALogDetail from '@/domains/log/components/ALogDetail.vue'\nimport { useLogDetailActions } from '@/domains/log/composables/logActions'\nimport { useRecordPage } from '@/domains/system/composables/recordPage'\nimport type { LogPaths, LogTypeType } from '@/domains/log/composables/logType'\nimport { isNull } from '@/shared/utils/common'\n\nconst props = defineProps<{\n client: AxiosClientFn\n system: string\n /** From the route. A log id means nothing without the store it came from. */\n type: LogTypeType\n id: string\n logPaths: LogPaths\n /** Where a log that cannot be loaded leaves to when history is empty. The page's Close fallback. */\n fallbackRouteName?: RouteRecordName\n fallbackRouteParams?: Record<string, any>\n}>()\n\n// Read once: the page keys this view on `${system}/${type}/${id}`, so a change remounts it.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { log, detailLoading, fetchData, cancel } = useLogDetailActions({\n client: props.client,\n system: props.system,\n logPaths: props.logPaths,\n type: props.type,\n})\n\n// No `loading`: the view has no buttons to hide.\n// With it, a page without a fallback would keep the card loading forever in a fresh tab.\n// eslint-disable-next-line vue/no-setup-props-reactivity-loss\nconst { leave } = useRecordPage({\n fallbackRouteName: props.fallbackRouteName,\n fallbackRouteParams: props.fallbackRouteParams,\n})\n\nonMounted(async () => {\n if ((await fetchData(props.id)) === false) await leave()\n})\n\nonBeforeUnmount(() => {\n cancel()\n})\n</script>\n\n<template>\n <ACard :loading=\"detailLoading\">\n <VCardText>\n <ALogDetail\n v-if=\"!isNull(log)\"\n :log=\"log\"\n />\n </VCardText>\n </ACard>\n</template>\n"],"mappings":";;;;;;;;;;;;;;;;;;;;EAWA,IAAMY,IAAQC,GAcR,EAAE,QAAK,kBAAe,cAAW,cAAWC,EAAoB;GACpE,QAAQF,EAAM;GACd,QAAQA,EAAM;GACd,UAAUA,EAAM;GAChB,MAAMA,EAAM;EACd,CAAC,GAKK,EAAE,aAAUG,EAAc;GAC9B,mBAAmBH,EAAM;GACzB,qBAAqBA,EAAM;EAC7B,CAAC;E,OAEDI,EAAU,YAAY;GACpB,AAAK,MAAMC,EAAUL,EAAM,EAAE,MAAO,MAAO,MAAMM,EAAM;EACzD,CAAC,GAEDC,QAAsB;GACpB,EAAO;EACT,CAAC,I,UAICnB,EAAA,GAAAC,EAOQC,GAAA,EAPA,SAASC,EAAAoB,CAAA,EAAa,GAAA;GAC5B,SAAAnB,QAKY,CALZC,EAKYC,GAAA,MAAA;IAJV,SAAAF,QAGE,CAFOD,EAAAwB,CAAA,CAAM,CAACxB,EAAAyB,CAAA,CAAG,I,aADnB5B,EAAA,GAAAC,EAGEM,GAAA;;KADC,KAAKJ,EAAAyB,CAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"ALogFilter.js","names":["_sfc_main","ALogFilter_vue_vue_type_script_setup_true_lang_default","ALogFilter_default"],"sources":["../../../../src/domains/log/components/ALogFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useI18n } from 'vue-i18n'\nimport AFilterString from '@/domains/filters/components/AFilterString.vue'\nimport AFilterTimeInterval from '@/domains/filters/components/AFilterTimeInterval.vue'\nimport AFilterValueObjectOptionsSelect from '@/domains/filters/components/AFilterValueObjectOptionsSelect.vue'\nimport AFilterWrapper from '@/domains/filters/components/AFilterWrapper.vue'\nimport type { TimeIntervalToolsValue } from '@/domains/filters/composables/filterTimeIntervalTools'\nimport { type LogTypeType, useLogType } from '@/domains/log/composables/logType'\nimport { useLogLevel } from '@/domains/log/valueObject/LogLevel'\n\ndefineProps<{\n type: LogTypeType\n allowedTimeIntervals?: TimeIntervalToolsValue[] | undefined\n}>()\n\nconst emit = defineEmits<{\n (e: 'submit'): void\n (e: 'reset'): void\n (e: 'changeType', type: LogTypeType): void\n}>()\n\nconst { t } = useI18n()\nconst { logLevelOptions } = useLogLevel()\nconst { logTypeOptions } = useLogType()\n</script>\n\n<template>\n <AFilterWrapper\n enable-top\n @submit=\"emit('submit')\"\n @reset=\"emit('reset')\"\n >\n <template #top>\n <VRow class=\"align-start\">\n <VCol\n class=\"pb-0\"\n cols=\"12\"\n sm=\"4\"\n >\n <!--\n A plain select, not `AFilterValueObjectOptionsSelect`: that one throws unless the name\n it is given is a live filter field, and the type is not one. It picks the endpoint and\n lives in the route, which is also what makes it survive a filter reset.\n -->\n <VSelect\n :model-value=\"type\"\n :items=\"logTypeOptions\"\n :label=\"t('common.log.filter.type')\"\n item-title=\"title\"\n item-value=\"value\"\n density=\"compact\"\n variant=\"outlined\"\n hide-details\n data-cy=\"filter-log-type\"\n @update:model-value=\"emit('changeType', $event)\"\n />\n </VCol>\n </VRow>\n <VDivider class=\"mb-4 mt-4\" />\n </template>\n <template #search>\n <AFilterString\n name=\"contextId\"\n class=\"mr-2\"\n />\n <AFilterString\n name=\"message\"\n class=\"mr-2\"\n />\n <AFilterTimeInterval\n name-from=\"datetimeFrom\"\n name-until=\"datetimeTo\"\n :allowed=\"allowedTimeIntervals\"\n />\n </template>\n <template #item.levelName>\n <AFilterValueObjectOptionsSelect\n name=\"levelName\"\n :items=\"logLevelOptions\"\n />\n </template>\n </AFilterWrapper>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"ALogFilter.js","names":["_sfc_main","ALogFilter_vue_vue_type_script_setup_true_lang_default","ALogFilter_default"],"sources":["../../../../src/domains/log/components/ALogFilter.vue"],"sourcesContent":["<script lang=\"ts\" setup>\nimport { useI18n } from 'vue-i18n'\nimport AFilterString from '@/domains/filters/components/AFilterString.vue'\nimport AFilterTimeInterval from '@/domains/filters/components/AFilterTimeInterval.vue'\nimport AFilterValueObjectOptionsSelect from '@/domains/filters/components/AFilterValueObjectOptionsSelect.vue'\nimport AFilterWrapper from '@/domains/filters/components/AFilterWrapper.vue'\nimport type { TimeIntervalToolsValue } from '@/domains/filters/composables/filterTimeIntervalTools'\nimport { type LogTypeType, useLogType } from '@/domains/log/composables/logType'\nimport { useLogLevel } from '@/domains/log/valueObject/LogLevel'\n\ndefineProps<{\n type: LogTypeType\n allowedTimeIntervals?: TimeIntervalToolsValue[] | undefined\n}>()\n\nconst emit = defineEmits<{\n (e: 'submit'): void\n (e: 'reset'): void\n (e: 'changeType', type: LogTypeType): void\n}>()\n\nconst { t } = useI18n()\nconst { logLevelOptions } = useLogLevel()\nconst { logTypeOptions } = useLogType()\n</script>\n\n<template>\n <AFilterWrapper\n enable-top\n @submit=\"emit('submit')\"\n @reset=\"emit('reset')\"\n >\n <template #top>\n <VRow class=\"align-start\">\n <VCol\n class=\"pb-0\"\n cols=\"12\"\n sm=\"4\"\n >\n <!--\n A plain select, not `AFilterValueObjectOptionsSelect`. That one throws\n unless the name is a live filter field, and the type is not one.\n The type picks the endpoint and lives in the route, so it survives a filter reset.\n -->\n <VSelect\n :model-value=\"type\"\n :items=\"logTypeOptions\"\n :label=\"t('common.log.filter.type')\"\n item-title=\"title\"\n item-value=\"value\"\n density=\"compact\"\n variant=\"outlined\"\n hide-details\n data-cy=\"filter-log-type\"\n @update:model-value=\"emit('changeType', $event)\"\n />\n </VCol>\n </VRow>\n <VDivider class=\"mb-4 mt-4\" />\n </template>\n <template #search>\n <AFilterString\n name=\"contextId\"\n class=\"mr-2\"\n />\n <AFilterString\n name=\"message\"\n class=\"mr-2\"\n />\n <AFilterTimeInterval\n name-from=\"datetimeFrom\"\n name-until=\"datetimeTo\"\n :allowed=\"allowedTimeIntervals\"\n />\n </template>\n <template #item.levelName>\n <AFilterValueObjectOptionsSelect\n name=\"levelName\"\n :items=\"logLevelOptions\"\n />\n </template>\n </AFilterWrapper>\n</template>\n"],"mappings":""}