@vc-shell/vc-app-skill 2.0.0-alpha.32 → 2.0.0-alpha.33-pr220.455e322

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 (195) hide show
  1. package/CHANGELOG.md +59 -47
  2. package/README.md +18 -12
  3. package/package.json +4 -4
  4. package/runtime/VERSION +1 -1
  5. package/runtime/agents/api-analyzer.md +31 -16
  6. package/runtime/agents/blade-enhancer.md +15 -9
  7. package/runtime/agents/details-blade-generator.md +47 -31
  8. package/runtime/agents/list-blade-generator.md +21 -37
  9. package/runtime/agents/locales-generator.md +3 -0
  10. package/runtime/agents/migration-agent.md +94 -0
  11. package/runtime/agents/module-analyzer.md +2 -0
  12. package/runtime/agents/module-assembler.md +15 -0
  13. package/runtime/agents/promote-agent.md +15 -4
  14. package/runtime/agents/type-checker.md +11 -0
  15. package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
  16. package/runtime/knowledge/docs/core/api/platform.docs.md +30 -30
  17. package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +41 -41
  18. package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +12 -10
  19. package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +11 -14
  20. package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +35 -35
  21. package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +35 -35
  22. package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +15 -15
  23. package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +21 -18
  24. package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +31 -27
  25. package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +90 -61
  26. package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +19 -18
  27. package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +89 -68
  28. package/runtime/knowledge/docs/core/composables/useBladeForm/useBladeForm.docs.md +75 -19
  29. package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +15 -15
  30. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +74 -78
  31. package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +11 -11
  32. package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +27 -15
  33. package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +30 -30
  34. package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +34 -36
  35. package/runtime/knowledge/docs/core/composables/useErrorHandler/useErrorHandler.docs.md +44 -23
  36. package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +14 -11
  37. package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +47 -38
  38. package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +37 -28
  39. package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +23 -17
  40. package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +10 -10
  41. package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +42 -42
  42. package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +22 -12
  43. package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +33 -41
  44. package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +16 -16
  45. package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +32 -24
  46. package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +32 -11
  47. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +24 -15
  48. package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +7 -7
  49. package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +32 -24
  50. package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +21 -17
  51. package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +24 -24
  52. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +28 -31
  53. package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +43 -24
  54. package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +68 -48
  55. package/runtime/knowledge/docs/core/composables/useWebVitals/useWebVitals.docs.md +19 -19
  56. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +42 -47
  57. package/runtime/knowledge/docs/core/directives/autofocus/autofocus.docs.md +10 -4
  58. package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +35 -20
  59. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +36 -35
  60. package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +38 -38
  61. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +107 -91
  62. package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +10 -10
  63. package/runtime/knowledge/docs/core/plugins/i18n/i18n.docs.md +21 -23
  64. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +98 -90
  65. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +10 -16
  66. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +9 -9
  67. package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +65 -22
  68. package/runtime/knowledge/docs/core/services/services.docs.md +19 -22
  69. package/runtime/knowledge/docs/core/types/types.docs.md +40 -40
  70. package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +27 -27
  71. package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +23 -23
  72. package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +22 -25
  73. package/runtime/knowledge/docs/core/utilities/utilities.docs.md +64 -64
  74. package/runtime/knowledge/docs/injection-keys.docs.md +52 -51
  75. package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +9 -9
  76. package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +23 -43
  77. package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +102 -0
  78. package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +5 -5
  79. package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +8 -7
  80. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +7 -7
  81. package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +8 -7
  82. package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +29 -13
  83. package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +13 -16
  84. package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +1 -7
  85. package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +5 -5
  86. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
  87. package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
  88. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -9
  89. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +12 -18
  90. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +34 -65
  91. package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +16 -26
  92. package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +2 -2
  93. package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +7 -9
  94. package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +30 -40
  95. package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +26 -19
  96. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +15 -12
  97. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +15 -26
  98. package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +21 -19
  99. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +83 -67
  100. package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +104 -59
  101. package/runtime/knowledge/docs/ui/components/atoms/vc-col/vc-col.docs.md +28 -11
  102. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +20 -17
  103. package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +26 -17
  104. package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +30 -32
  105. package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +25 -48
  106. package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +29 -24
  107. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +23 -15
  108. package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +22 -13
  109. package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +33 -18
  110. package/runtime/knowledge/docs/ui/components/atoms/vc-row/vc-row.docs.md +56 -15
  111. package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +28 -15
  112. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +40 -20
  113. package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +25 -14
  114. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +40 -14
  115. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +54 -42
  116. package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +17 -17
  117. package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +21 -21
  118. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +23 -10
  119. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +59 -44
  120. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +23 -20
  121. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +96 -64
  122. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +26 -35
  123. package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +69 -22
  124. package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +58 -72
  125. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +91 -85
  126. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +38 -42
  127. package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +60 -72
  128. package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +65 -26
  129. package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +46 -49
  130. package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +35 -64
  131. package/runtime/knowledge/docs/ui/components/molecules/vc-image-tile/vc-image-tile.docs.md +38 -41
  132. package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +115 -130
  133. package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +53 -87
  134. package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +56 -63
  135. package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +29 -24
  136. package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +32 -28
  137. package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +63 -64
  138. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +28 -26
  139. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +59 -19
  140. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +25 -34
  141. package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +42 -32
  142. package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +78 -82
  143. package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +25 -15
  144. package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +59 -63
  145. package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +57 -69
  146. package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +58 -57
  147. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +49 -26
  148. package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +82 -28
  149. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +120 -75
  150. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +30 -44
  151. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +536 -365
  152. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +35 -52
  153. package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +33 -62
  154. package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +17 -23
  155. package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +109 -68
  156. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +82 -44
  157. package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +8 -8
  158. package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +164 -0
  159. package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +34 -26
  160. package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +48 -40
  161. package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +30 -17
  162. package/runtime/knowledge/docs/ui/types/ui-types.docs.md +40 -29
  163. package/runtime/knowledge/examples/offers-module.md +15 -13
  164. package/runtime/knowledge/examples/team-module.md +82 -119
  165. package/runtime/knowledge/examples/videos-module.md +44 -17
  166. package/runtime/knowledge/index.md +22 -0
  167. package/runtime/knowledge/migration-prompts/blade-form-migration.md +255 -0
  168. package/runtime/knowledge/migration-prompts/blade-props-migration.md +194 -0
  169. package/runtime/knowledge/migration-prompts/datatable-migration.md +801 -0
  170. package/runtime/knowledge/migration-prompts/icon-migration.md +97 -0
  171. package/runtime/knowledge/migration-prompts/manual-migration-audit.md +117 -0
  172. package/runtime/knowledge/migration-prompts/notifications-migration.md +223 -0
  173. package/runtime/knowledge/migration-prompts/nswag-migration.md +244 -0
  174. package/runtime/knowledge/migration-prompts/use-assets-migration.md +164 -0
  175. package/runtime/knowledge/migration-prompts/use-data-table-pagination-migration.md +176 -0
  176. package/runtime/knowledge/migration-prompts/widgets-migration.md +178 -0
  177. package/runtime/knowledge/patterns/assets-management.md +20 -20
  178. package/runtime/knowledge/patterns/blade-navigation.md +7 -14
  179. package/runtime/knowledge/patterns/blade-widget.md +19 -17
  180. package/runtime/knowledge/patterns/child-blade-flow.md +19 -7
  181. package/runtime/knowledge/patterns/composable-details.md +20 -50
  182. package/runtime/knowledge/patterns/composable-list.md +43 -31
  183. package/runtime/knowledge/patterns/dashboard-widget.md +14 -16
  184. package/runtime/knowledge/patterns/datatable-pattern.md +521 -0
  185. package/runtime/knowledge/patterns/details-blade-pattern.md +78 -116
  186. package/runtime/knowledge/patterns/extension-points-usage.md +53 -44
  187. package/runtime/knowledge/patterns/form-validation.md +28 -64
  188. package/runtime/knowledge/patterns/list-blade-pattern.md +33 -21
  189. package/runtime/knowledge/patterns/module-structure.md +7 -1
  190. package/runtime/knowledge/patterns/multilanguage-fields.md +8 -14
  191. package/runtime/knowledge/patterns/notification-template.md +21 -14
  192. package/runtime/knowledge/patterns/signalr-notifications.md +30 -32
  193. package/runtime/knowledge/patterns/toolbar-pattern.md +18 -20
  194. package/runtime/vc-app.md +354 -49
  195. package/runtime/knowledge/docs/core/constants/constants.docs.md +0 -185
@@ -0,0 +1,164 @@
1
+ ---
2
+ name: use-assets-migration
3
+ description: AI transformation rules for useAssets()/AssetsHandler migration to useAssetsManager().
4
+ ---
5
+
6
+ # Assets Migration: useAssets -> useAssetsManager
7
+
8
+ Migrate legacy assets handling (`useAssets`, `AssetsHandler`, ad-hoc upload/remove/edit callbacks) to `useAssetsManager`.
9
+
10
+ ## RULE 1: Replace `useAssets()` with `useAssetsManager()`
11
+
12
+ **BEFORE:**
13
+
14
+ ```typescript
15
+ import { useAssets } from "@vc-shell/framework";
16
+
17
+ const { upload, remove, edit, loading } = useAssets(imagesRef, uploadPath);
18
+ ```
19
+
20
+ **AFTER:**
21
+
22
+ ```typescript
23
+ import { useAssetsManager } from "@vc-shell/framework";
24
+
25
+ const assetsManager = useAssetsManager(imagesRef, {
26
+ uploadPath: () => uploadPath.value,
27
+ confirmRemove: () => showConfirmation(t("MY_MODULE.ALERTS.DELETE_CONFIRMATION")),
28
+ });
29
+
30
+ // assetsManager.items, assetsManager.upload, assetsManager.remove,
31
+ // assetsManager.removeMany, assetsManager.reorder, assetsManager.updateItem, assetsManager.loading
32
+ ```
33
+
34
+ Notes:
35
+
36
+ - `uploadPath` must be a function (`() => string`), not a static string.
37
+ - If no confirmation is needed, omit `confirmRemove`.
38
+
39
+ ## RULE 2: Replace `ICommonAsset` with `AssetLike`
40
+
41
+ **BEFORE:**
42
+
43
+ ```typescript
44
+ import type { ICommonAsset } from "@vc-shell/framework";
45
+ ```
46
+
47
+ **AFTER:**
48
+
49
+ ```typescript
50
+ import type { AssetLike } from "@vc-shell/framework";
51
+ ```
52
+
53
+ Also update all type annotations in the file.
54
+
55
+ ## RULE 3: Single-image fields must be wrapped in writable computed array
56
+
57
+ For fields like `iconUrl`, `logo`, `photo`, convert single value <-> array bridge.
58
+
59
+ **BEFORE:**
60
+
61
+ ```typescript
62
+ const { upload, remove } = useAssets(photoRef, () => `users/${item.value?.id}`);
63
+ ```
64
+
65
+ **AFTER:**
66
+
67
+ ```typescript
68
+ const photoAssets = computed({
69
+ get: () => (item.value?.iconUrl ? [{ url: item.value.iconUrl }] : []),
70
+ set: (val) => {
71
+ if (item.value) item.value.iconUrl = val[0]?.url;
72
+ },
73
+ });
74
+
75
+ const photoManager = useAssetsManager(photoAssets, {
76
+ uploadPath: () => `users/${item.value?.id ?? "new"}`,
77
+ });
78
+ ```
79
+
80
+ ## RULE 4: `AssetsHandler` and raw handler props -> manager object
81
+
82
+ If the component receives or creates handler bundles (`assetsUploadHandler`, `assetsEditHandler`, `assetsRemoveHandler`, `AssetsHandler<T>`), replace with a manager instance.
83
+
84
+ **BEFORE:**
85
+
86
+ ```typescript
87
+ interface Props {
88
+ imageHandlers?: AssetsHandler<MyImage>;
89
+ }
90
+
91
+ const defaultHandlers = { upload, remove, edit, loading };
92
+ const handlers = props.imageHandlers ?? defaultHandlers;
93
+ ```
94
+
95
+ **AFTER:**
96
+
97
+ ```typescript
98
+ interface Props {
99
+ manager?: ReturnType<typeof useAssetsManager>;
100
+ }
101
+
102
+ const defaultManager = useAssetsManager(imagesRef, {
103
+ uploadPath: () => `products/${item.value?.id}`,
104
+ });
105
+
106
+ const manager = computed(() => props.manager ?? defaultManager);
107
+ ```
108
+
109
+ ## RULE 5: `openBlade("AssetsManager")` must pass `manager: markRaw(...)`
110
+
111
+ **BEFORE:**
112
+
113
+ ```typescript
114
+ openBlade({
115
+ name: "AssetsManager",
116
+ options: {
117
+ assets: item.value?.assets,
118
+ assetsUploadHandler: upload,
119
+ assetsEditHandler: edit,
120
+ assetsRemoveHandler: remove,
121
+ loading,
122
+ },
123
+ });
124
+ ```
125
+
126
+ **AFTER:**
127
+
128
+ ```typescript
129
+ import { markRaw } from "vue";
130
+
131
+ openBlade({
132
+ name: "AssetsManager",
133
+ options: {
134
+ manager: markRaw(assetsManager),
135
+ disabled: disabled.value,
136
+ },
137
+ });
138
+ ```
139
+
140
+ If `manager` is already passed but not wrapped, add `markRaw()`.
141
+
142
+ ## RULE 6: Keep `AssetsDetails` callbacks wired to manager methods
143
+
144
+ If opening `AssetsDetails`, connect handlers to manager methods (`updateItem`, `remove`) and keep asset type as `AssetLike`.
145
+
146
+ ```typescript
147
+ openBlade({
148
+ name: "AssetsDetails",
149
+ options: {
150
+ asset,
151
+ assetEditHandler: (updated: AssetLike) => assetsManager.updateItem(updated),
152
+ assetRemoveHandler: (toRemove: AssetLike) => assetsManager.remove(toRemove),
153
+ },
154
+ });
155
+ ```
156
+
157
+ ## Verification
158
+
159
+ After migration:
160
+
161
+ 1. Search for stale API: `useAssets(`, `AssetsHandler`, `ICommonAsset`, `assetsUploadHandler`, `assetsEditHandler`, `assetsRemoveHandler`.
162
+ 2. Confirm `AssetsManager` blade calls pass `manager: markRaw(...)`.
163
+ 3. Run `npx vue-tsc --noEmit`.
164
+ 4. Validate runtime flow: upload, remove, reorder, edit metadata.
@@ -0,0 +1,176 @@
1
+ # useDataTablePagination Migration
2
+
3
+ Replace the manual `totalCount` / `pages` / `currentPage` computed triple plus hand-written `onPaginationClick` handler with a single `useDataTablePagination()` call.
4
+
5
+ ## Rule 1: Update the data composable
6
+
7
+ For each list composable file:
8
+
9
+ ### 1a. Add import
10
+
11
+ Add to the `@vc-shell/framework` import (merge, don't duplicate):
12
+
13
+ ```ts
14
+ import { useDataTablePagination, type UseDataTablePaginationReturn } from "@vc-shell/framework";
15
+ ```
16
+
17
+ ### 1b. Create `pagination` before the return
18
+
19
+ Declare, before the return block:
20
+
21
+ ```ts
22
+ const pagination = useDataTablePagination({
23
+ pageSize,
24
+ totalCount: computed(() => searchResult.value?.totalCount ?? 0),
25
+ onPageChange: ({ skip }) => loadItems({ ...searchQuery.value, skip }),
26
+ });
27
+ ```
28
+
29
+ - Use the same `pageSize` the composable already accepts as option (default 20).
30
+ - Pass `totalCount` as a computed (not a plain number).
31
+ - Use the composable's own loader name for `onPageChange` (`loadItems`, `loadMessages`, `searchXxx` — whatever already exists).
32
+
33
+ ### 1c. Replace the three computed in the return
34
+
35
+ **Before:**
36
+
37
+ ```ts
38
+ return {
39
+ totalCount: computed(() => searchResult.value?.totalCount || 0),
40
+ pages: computed(() => Math.ceil((searchResult.value?.totalCount || 1) / pageSize)),
41
+ currentPage: computed(() => Math.ceil((searchQuery.value?.skip || 0) / pageSize + 1)),
42
+ // ...other returns
43
+ };
44
+ ```
45
+
46
+ **After:**
47
+
48
+ ```ts
49
+ return {
50
+ pagination,
51
+ // ...other returns (unchanged)
52
+ };
53
+ ```
54
+
55
+ ### 1d. Update the return type interface (if present)
56
+
57
+ **Before:**
58
+
59
+ ```ts
60
+ export interface IUseList {
61
+ totalCount: ComputedRef<number>;
62
+ pages: ComputedRef<number>;
63
+ currentPage: ComputedRef<number>;
64
+ // ...
65
+ }
66
+ ```
67
+
68
+ **After:**
69
+
70
+ ```ts
71
+ export interface IUseList {
72
+ pagination: UseDataTablePaginationReturn;
73
+ // ...
74
+ }
75
+ ```
76
+
77
+ ## Rule 2: Update the blade page template
78
+
79
+ ### 2a. Replace VcDataTable pagination bindings
80
+
81
+ **Before:**
82
+
83
+ ```vue
84
+ <VcDataTable :total-count="totalCount" :pagination="{ currentPage, pages }" @pagination-click="onPaginationClick" />
85
+ ```
86
+
87
+ **After:**
88
+
89
+ ```vue
90
+ <VcDataTable :total-count="pagination.totalCount" :pagination="pagination" @pagination-click="pagination.goToPage" />
91
+ ```
92
+
93
+ ### 2b. Update the composable destructure
94
+
95
+ **Before:**
96
+
97
+ ```ts
98
+ const { items, totalCount, pages, currentPage, searchQuery, loadItems } = useList();
99
+ ```
100
+
101
+ **After:**
102
+
103
+ ```ts
104
+ const { items, pagination, searchQuery, loadItems } = useList();
105
+ ```
106
+
107
+ ### 2c. Delete the manual `onPaginationClick` handler
108
+
109
+ Remove the entire function — it's redundant; `pagination.goToPage` fires the composable's `onPageChange`.
110
+
111
+ **Delete:**
112
+
113
+ ```ts
114
+ async function onPaginationClick(page: number) {
115
+ await loadItems({
116
+ ...searchQuery.value,
117
+ skip: (page - 1) * (searchQuery.value.take ?? 20),
118
+ });
119
+ }
120
+ ```
121
+
122
+ ### 2d. Rewrite `reload()` helper (if present)
123
+
124
+ If the blade has a `reload()` helper that recomputes skip from currentPage, use `pagination.skip`:
125
+
126
+ **Before:**
127
+
128
+ ```ts
129
+ const reload = async () => {
130
+ await loadItems({
131
+ ...searchQuery.value,
132
+ skip: (currentPage.value - 1) * (searchQuery.value.take ?? 10),
133
+ sort: sortExpression.value,
134
+ });
135
+ };
136
+ ```
137
+
138
+ **After:**
139
+
140
+ ```ts
141
+ const reload = async () => {
142
+ await loadItems({
143
+ ...searchQuery.value,
144
+ skip: pagination.skip,
145
+ sort: sortExpression.value,
146
+ });
147
+ };
148
+ ```
149
+
150
+ ## Rule 3: VcTable / VcTableAdapter — skip that file (not the whole topic)
151
+
152
+ Per-file check. If a specific blade page still uses `<VcTable>` (legacy adapter, with `:pages` + `:current-page` scalar props), SKIP that file — migrating pagination against a different table API would break the bindings. But:
153
+
154
+ - **Still migrate the composable** if other callers (pages with `<VcDataTable>`) exist — the composable change is independent of any single consumer.
155
+ - **Still migrate other pages** in the same `affectedFiles` list that DO use `<VcDataTable>`.
156
+ - In your report, mark the skipped file(s) as `needs vctable-audit first` so the user knows why.
157
+
158
+ Do not skip the entire topic just because one file is out of scope.
159
+
160
+ ## Rule 4: Infinite-scroll tables — skip that file
161
+
162
+ If a specific VcDataTable uses `:infinite-scroll="true"`, pagination is not used — skip that file. Same per-file rule as Rule 3.
163
+
164
+ ## Behavioral notes
165
+
166
+ - `pagination` is a `reactive()` object — access properties directly (`pagination.totalCount`), never `.value`.
167
+ - Do NOT destructure `pagination` — destructuring loses reactivity.
168
+ - `pagination.reset()` sets currentPage to 1 silently (no onPageChange fire). Use when resetting filters.
169
+
170
+ ## Self-check after migration
171
+
172
+ - [ ] `totalCount`, `pages`, `currentPage` no longer appear in the composable's return.
173
+ - [ ] `onPaginationClick` function is deleted from the blade page.
174
+ - [ ] Template uses `pagination.goToPage` not a handwritten callback.
175
+ - [ ] No `.value` access on `pagination.*` properties.
176
+ - [ ] `useDataTablePagination` import is present in the composable.
@@ -0,0 +1,178 @@
1
+ ---
2
+ name: widgets-migration
3
+ description: AI transformation rules for useWidgets→useBladeWidgets migration.
4
+ ---
5
+
6
+ # Widget Migration: useWidgets → useBladeWidgets
7
+
8
+ Migrate blade widgets from the imperative `useWidgets()` + `registerWidget()` API to the declarative `useBladeWidgets()` composable. The new API eliminates manual registration/cleanup and removes the need for per-widget `.vue` components when they only render a standard sidebar item.
9
+
10
+ ## RULE 1: Create Widget Composable
11
+
12
+ For each blade that calls `registerWidget()`, create a `widgets/useXxxWidgets.ts` composable.
13
+
14
+ **BEFORE:**
15
+
16
+ ```typescript
17
+ // In XxxDetails.vue <script setup>
18
+ import { useWidgets, useBlade } from "@vc-shell/framework";
19
+ import type { BladeInstance } from "@vc-shell/framework";
20
+ import { onMounted, onUnmounted } from "vue";
21
+ import ChildListWidget from "../widgets/ChildListWidget.vue";
22
+
23
+ const { registerWidget, clearBladeWidgets } = useWidgets();
24
+ const { openBlade } = useBlade();
25
+
26
+ onMounted(() => {
27
+ registerWidget(
28
+ {
29
+ id: "ChildListWidget",
30
+ component: ChildListWidget,
31
+ props: {
32
+ count: childCount,
33
+ onClick: () => openBlade({ name: "ChildEntityList", options: { entityId: entity.value.id } }),
34
+ },
35
+ },
36
+ bladeContext.id,
37
+ );
38
+ });
39
+
40
+ onUnmounted(() => {
41
+ clearBladeWidgets(bladeContext.id);
42
+ });
43
+ ```
44
+
45
+ **AFTER:**
46
+
47
+ ```typescript
48
+ // widgets/useEntityWidgets.ts
49
+ import { useBladeWidgets, useBlade } from "@vc-shell/framework";
50
+ import type { UseBladeWidgetsReturn } from "@vc-shell/framework";
51
+ import { computed, type Ref } from "vue";
52
+
53
+ interface UseEntityWidgetsOptions {
54
+ item: Ref<Entity | undefined>;
55
+ isVisible: Ref<boolean> | boolean;
56
+ childCount: Ref<number>;
57
+ }
58
+
59
+ export function useEntityWidgets(options: UseEntityWidgetsOptions): UseBladeWidgetsReturn {
60
+ const { item, isVisible, childCount } = options;
61
+ const { openBlade } = useBlade();
62
+
63
+ return useBladeWidgets([
64
+ {
65
+ id: "ChildListWidget",
66
+ icon: "lucide-tag",
67
+ title: "MODULE.WIDGETS.CHILD_LIST.TITLE",
68
+ badge: computed(() => childCount.value),
69
+ isVisible,
70
+ onClick: () =>
71
+ openBlade({
72
+ name: "ChildEntityList",
73
+ options: { entityId: item.value?.id },
74
+ }),
75
+ onRefresh: async () => {
76
+ // load child count logic here
77
+ },
78
+ },
79
+ ]);
80
+ }
81
+ ```
82
+
83
+ ## RULE 2: Replace Usage in Blade Page
84
+
85
+ Import the new composable and destructure `{ refreshAll }`.
86
+
87
+ **BEFORE:**
88
+
89
+ ```typescript
90
+ // XxxDetails.vue <script setup>
91
+ import { useWidgets } from "@vc-shell/framework";
92
+ import ChildListWidget from "../widgets/ChildListWidget.vue";
93
+ import RelatedItemsWidget from "../widgets/RelatedItemsWidget.vue";
94
+
95
+ const { registerWidget, clearBladeWidgets } = useWidgets();
96
+
97
+ onMounted(() => {
98
+ registerWidget({ id: "ChildListWidget", component: ChildListWidget, props: { ... } }, bladeId);
99
+ registerWidget({ id: "RelatedItemsWidget", component: RelatedItemsWidget, props: { ... } }, bladeId);
100
+ });
101
+
102
+ onUnmounted(() => {
103
+ clearBladeWidgets(bladeId);
104
+ });
105
+ ```
106
+
107
+ **AFTER:**
108
+
109
+ ```typescript
110
+ // XxxDetails.vue <script setup>
111
+ import { useEntityWidgets } from "../widgets/useEntityWidgets";
112
+
113
+ const isExisting = computed(() => !!param.value);
114
+
115
+ const { refreshAll } = useEntityWidgets({
116
+ item: entity,
117
+ isVisible: isExisting,
118
+ childCount,
119
+ });
120
+ ```
121
+
122
+ If the old code used `updateActiveWidget()`, replace it with `refreshAll()` from the widget composable return:
123
+
124
+ ```typescript
125
+ // BEFORE
126
+ const { updateActiveWidget } = useWidgets();
127
+ updateActiveWidget();
128
+
129
+ // AFTER
130
+ const { refreshAll } = useEntityWidgets({ item: entity, isVisible: isExisting, childCount });
131
+ refreshAll();
132
+ ```
133
+
134
+ ## RULE 3: Remove Widget .vue Components
135
+
136
+ Delete widget `.vue` files that only render a standard sidebar item (icon + title + badge + click handler). These are replaced by the declarative config in `useBladeWidgets()`.
137
+
138
+ **Keep** the `.vue` component only if it has custom rendering beyond the standard widget layout.
139
+
140
+ **Delete:**
141
+
142
+ - `widgets/ChildListWidget.vue` (if it only shows icon, title, badge, click)
143
+ - `widgets/RelatedItemsWidget.vue` (same)
144
+
145
+ **Keep:**
146
+
147
+ - `widgets/CustomChartWidget.vue` (has custom chart rendering)
148
+
149
+ ## RULE 4: Remove Old Imports
150
+
151
+ Remove these imports that are no longer needed:
152
+
153
+ ```typescript
154
+ // REMOVE all of these:
155
+ import { useWidgets } from "@vc-shell/framework";
156
+ import type { BladeInstance } from "@vc-shell/framework"; // if only used for widgets
157
+ import { registerWidget, unregisterWidget, clearBladeWidgets } from "...";
158
+ import { onUnmounted } from "vue"; // if only used for widget cleanup
159
+ import ChildListWidget from "../widgets/ChildListWidget.vue"; // deleted component
160
+ ```
161
+
162
+ ## RULE 5: `defineBladeContext` only for external widgets
163
+
164
+ Do not add `defineBladeContext()` by default in this migration.
165
+
166
+ Add it only if the blade hosts external widget components that use `injectBladeContext()`.
167
+
168
+ ## Verification
169
+
170
+ After migration:
171
+
172
+ 1. Run `npx tsc --noEmit` to verify no TypeScript errors
173
+ 2. Confirm widgets appear in the blade sidebar
174
+ 3. Confirm badge counts update reactively
175
+ 4. Confirm clicking a widget opens the correct child blade
176
+ 5. Confirm widgets are hidden when `isVisible` is false (e.g., on "create new" blades)
177
+ 6. Confirm no console errors about widget registration/cleanup on blade close
178
+ 7. Confirm `updateActiveWidget()` calls are removed and replaced with `refreshAll()` from `useEntityWidgets` return
@@ -68,7 +68,9 @@ const { showConfirmation } = usePopup();
68
68
 
69
69
  const images = computed({
70
70
  get: () => item.value?.images ?? [],
71
- set: (val) => { if (item.value) item.value.images = val; },
71
+ set: (val) => {
72
+ if (item.value) item.value.images = val;
73
+ },
72
74
  });
73
75
 
74
76
  const assets = useAssetsManager(images, {
@@ -101,13 +103,7 @@ Use when assets are a secondary concern shown as a widget badge. Clicking the wi
101
103
  ```ts
102
104
  // widgets/useEntityWidgets.ts
103
105
  import { computed, markRaw, type Ref, type ComputedRef } from "vue";
104
- import {
105
- useBlade,
106
- useBladeWidgets,
107
- useAssetsManager,
108
- usePopup,
109
- type UseBladeWidgetsReturn,
110
- } from "@vc-shell/framework";
106
+ import { useBlade, useBladeWidgets, useAssetsManager, usePopup, type UseBladeWidgetsReturn } from "@vc-shell/framework";
111
107
 
112
108
  interface Options {
113
109
  item: Ref<Entity | undefined>;
@@ -145,7 +141,7 @@ export function useEntityWidgets({ item, disabled, isVisible }: Options): UseBla
145
141
  openBlade({
146
142
  name: "AssetsManager",
147
143
  options: {
148
- manager: markRaw(assetsManager), // markRaw prevents Vue from making it reactive
144
+ manager: markRaw(assetsManager), // markRaw prevents Vue from making it reactive
149
145
  disabled: disabled.value,
150
146
  },
151
147
  }),
@@ -186,14 +182,18 @@ Each manager operates on a different writable computed pointing to a different a
186
182
  // Gallery assets (images)
187
183
  const productImages = computed({
188
184
  get: () => item.value.productData?.images ?? [],
189
- set: (val) => { if (item.value.productData) item.value.productData.images = val; },
185
+ set: (val) => {
186
+ if (item.value.productData) item.value.productData.images = val;
187
+ },
190
188
  });
191
189
  const imageAssets = useAssetsManager(productImages, { uploadPath: () => `/catalog/${item.value.id}` });
192
190
 
193
191
  // Widget assets (files)
194
192
  const productFiles = computed({
195
193
  get: () => (item.value?.productData?.assets ?? []) as Asset[],
196
- set: (val) => { if (item.value?.productData) item.value.productData.assets = val; },
194
+ set: (val) => {
195
+ if (item.value?.productData) item.value.productData.assets = val;
196
+ },
197
197
  });
198
198
  const fileAssets = useAssetsManager(productFiles, { uploadPath: () => `/catalog/${item.value.id}` });
199
199
  ```
@@ -202,12 +202,12 @@ const fileAssets = useAssetsManager(productFiles, { uploadPath: () => `/catalog/
202
202
 
203
203
  ## Key Points
204
204
 
205
- | Concern | Approach |
206
- |---|---|
207
- | Binding to entity | Writable `computed` — getter reads nested array, setter writes it back |
208
- | Upload path | Callback `() => string` — resolved at upload time, so entity ID is available |
209
- | Remove confirmation | Pass `confirmRemove` returning `Promise<boolean>` via `usePopup().showConfirmation` |
210
- | Passing to AssetsManager blade | Wrap with `markRaw()` — prevents Vue from making the manager deeply reactive |
211
- | Multiple asset types | Create separate `useAssetsManager` instances per array (images vs files) |
212
- | Gallery edit | Open `AssetsDetails` blade, pass `assetEditHandler` and `assetRemoveHandler` callbacks |
213
- | Widget visibility | Use `isVisible: computed(() => !!param.value)` to hide on "create new" mode |
205
+ | Concern | Approach |
206
+ | ------------------------------ | -------------------------------------------------------------------------------------- |
207
+ | Binding to entity | Writable `computed` — getter reads nested array, setter writes it back |
208
+ | Upload path | Callback `() => string` — resolved at upload time, so entity ID is available |
209
+ | Remove confirmation | Pass `confirmRemove` returning `Promise<boolean>` via `usePopup().showConfirmation` |
210
+ | Passing to AssetsManager blade | Wrap with `markRaw()` — prevents Vue from making the manager deeply reactive |
211
+ | Multiple asset types | Create separate `useAssetsManager` instances per array (images vs files) |
212
+ | Gallery edit | Open `AssetsDetails` blade, pass `assetEditHandler` and `assetRemoveHandler` callbacks |
213
+ | Widget visibility | Use `isVisible: computed(() => !!param.value)` to hide on "create new" mode |
@@ -9,15 +9,7 @@ Blades are stacked panels rendered by `VcBladeNavigation`. Navigation between bl
9
9
  ```ts
10
10
  import { useBlade } from "@vc-shell/framework";
11
11
 
12
- const {
13
- openBlade,
14
- closeSelf,
15
- callParent,
16
- exposeToChildren,
17
- onBeforeClose,
18
- param,
19
- options,
20
- } = useBlade<OptionsType>();
12
+ const { openBlade, closeSelf, callParent, exposeToChildren, onBeforeClose, param, options } = useBlade<OptionsType>();
21
13
  ```
22
14
 
23
15
  `useBlade()` must be called inside `<script setup>` of a blade component. It uses provide/inject to wire the blade hierarchy.
@@ -58,6 +50,7 @@ entity.value.name = options.value?.prefilledName ?? "";
58
50
  ## `openBlade()` — Open a child blade
59
51
 
60
52
  Full signature:
53
+
61
54
  ```ts
62
55
  openBlade({
63
56
  name: string, // defineBlade name of the target blade
@@ -133,7 +126,7 @@ const { callParent } = useBlade();
133
126
 
134
127
  // In details blade after save:
135
128
  await updateXxx(entity.value);
136
- callParent("reload"); // calls parent's reload() function
129
+ callParent("reload"); // calls parent's reload() function
137
130
  closeSelf();
138
131
  ```
139
132
 
@@ -170,19 +163,19 @@ const { showConfirmation } = usePopup();
170
163
  onBeforeClose(async () => {
171
164
  if (modified.value) {
172
165
  // returns true to BLOCK close, false to ALLOW close
173
- return !(await showConfirmation(
174
- unref(computed(() => t("MODULE.PAGES.ALERTS.CLOSE_CONFIRMATION"))),
175
- ));
166
+ return !(await showConfirmation(unref(computed(() => t("MODULE.PAGES.ALERTS.CLOSE_CONFIRMATION")))));
176
167
  }
177
- return false; // no unsaved changes — allow close
168
+ return false; // no unsaved changes — allow close
178
169
  });
179
170
  ```
180
171
 
181
172
  Return value semantics:
173
+
182
174
  - `false` → close is allowed
183
175
  - `true` → close is blocked (user stays on the blade)
184
176
 
185
177
  The pattern `!(await showConfirmation(...))` works as:
178
+
186
179
  - User clicks "Confirm" → `showConfirmation` returns `true` → `!true` = `false` → close allowed
187
180
  - User clicks "Cancel" → `showConfirmation` returns `false` → `!false` = `true` → close blocked
188
181