@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
@@ -1,6 +1,6 @@
1
1
  # Blade Widget Pattern
2
2
 
3
- Blade widgets are sidebar items displayed alongside a details blade. They allow navigation to related child blades (e.g., "Offers for this product", "Associated items"). Each widget shows an icon, a title, and an optional reactive badge count.
3
+ Blade widgets are sidebar items displayed alongside a details blade. They allow navigation to related child blades (e.g., "Children of this entity", "Associated items"). Each widget shows an icon, a title, and an optional reactive badge count.
4
4
 
5
5
  Blade widgets use `useBladeWidgets()` — the headless widget API. No `.vue` component is needed per widget; the framework renders a standard `<VcWidget>` from the config object.
6
6
 
@@ -17,18 +17,18 @@ import { useBladeWidgets, useBlade } from "@vc-shell/framework";
17
17
  import { computed } from "vue";
18
18
 
19
19
  const { openBlade } = useBlade();
20
- const offersCount = ref(0);
20
+ const childCount = ref(0);
21
21
 
22
22
  useBladeWidgets([
23
23
  {
24
- id: "OffersWidget",
24
+ id: "ChildListWidget",
25
25
  icon: "lucide-tag",
26
- title: "PRODUCTS.WIDGETS.OFFERS.TITLE",
27
- badge: computed(() => offersCount.value),
28
- isVisible: computed(() => !!param.value), // hide on "create new"
29
- onClick: () => openBlade({ name: "OffersList", options: { productId: entity.value.id } }),
26
+ title: "MODULE.WIDGETS.CHILD_LIST.TITLE",
27
+ badge: computed(() => childCount.value),
28
+ isVisible: computed(() => !!param.value), // hide on "create new"
29
+ onClick: () => openBlade({ name: "ChildEntityList", options: { entityId: entity.value.id } }),
30
30
  onRefresh: async () => {
31
- offersCount.value = await loadOffersCount(entity.value.id);
31
+ childCount.value = await loadChildCount(entity.value.id);
32
32
  },
33
33
  },
34
34
  ]);
@@ -66,10 +66,11 @@ export function useXxxWidgets(options: UseXxxWidgetsOptions): UseBladeWidgetsRet
66
66
  title: "XXX.WIDGETS.RELATED_ITEMS.TITLE",
67
67
  badge: relatedCount,
68
68
  isVisible,
69
- onClick: () => openBlade({
70
- name: "RelatedItemsList",
71
- options: { parentId: item.value?.id },
72
- }),
69
+ onClick: () =>
70
+ openBlade({
71
+ name: "RelatedItemsList",
72
+ options: { parentId: item.value?.id },
73
+ }),
73
74
  },
74
75
  ]);
75
76
  }
@@ -96,9 +97,9 @@ const { refreshAll } = useXxxWidgets({
96
97
 
97
98
  ```ts
98
99
  interface HeadlessWidgetDeclaration {
99
- id: string; // unique within the blade
100
- icon: string; // lucide icon name
101
- title: string; // i18n key or plain string
100
+ id: string; // unique within the blade
101
+ icon: string; // lucide icon name
102
+ title: string; // i18n key or plain string
102
103
  badge?: Ref<number | string> | ComputedRef<number | string>;
103
104
  loading?: Ref<boolean> | ComputedRef<boolean>;
104
105
  disabled?: Ref<boolean> | ComputedRef<boolean> | boolean;
@@ -112,8 +113,8 @@ interface HeadlessWidgetDeclaration {
112
113
 
113
114
  ```ts
114
115
  interface UseBladeWidgetsReturn {
115
- refresh: (widgetId: string) => void; // trigger onRefresh for one widget
116
- refreshAll: () => void; // trigger onRefresh for all widgets
116
+ refresh: (widgetId: string) => void; // trigger onRefresh for one widget
117
+ refreshAll: () => void; // trigger onRefresh for all widgets
117
118
  }
118
119
  ```
119
120
 
@@ -124,6 +125,7 @@ Call `refreshAll()` from `onMounted` or after data loads to populate badge count
124
125
  ## Lifecycle
125
126
 
126
127
  `useBladeWidgets()` automatically:
128
+
127
129
  - Registers all widgets with the `WidgetService` on `onMounted`
128
130
  - Unregisters all widgets from the `WidgetService` on `onUnmounted`
129
131
 
@@ -13,10 +13,14 @@ const { openBlade } = useBlade();
13
13
 
14
14
  openBlade({
15
15
  name: "ProductDetails",
16
- param: product.id, // string — entity ID, appears in URL
17
- options: { mode: "edit", origin: "catalog" }, // object — runtime-only, not in URL
18
- onOpen() { selectedItemId.value = product.id; },
19
- onClose() { selectedItemId.value = undefined; },
16
+ param: product.id, // string — entity ID, appears in URL
17
+ options: { mode: "edit", origin: "catalog" }, // object — runtime-only, not in URL
18
+ onOpen() {
19
+ selectedItemId.value = product.id;
20
+ },
21
+ onClose() {
22
+ selectedItemId.value = undefined;
23
+ },
20
24
  });
21
25
  ```
22
26
 
@@ -93,10 +97,12 @@ onBeforeClose(async () => {
93
97
  ```
94
98
 
95
99
  Return value semantics:
100
+
96
101
  - `false` — close is **allowed**
97
102
  - `true` — close is **blocked** (user stays on the blade)
98
103
 
99
104
  The `!(await showConfirmation(...))` idiom:
105
+
100
106
  - User clicks "Confirm" (discard) -> `true` -> `!true` = `false` -> close allowed
101
107
  - User clicks "Cancel" (stay) -> `false` -> `!false` = `true` -> close blocked
102
108
 
@@ -187,8 +193,12 @@ function onItemClick(event: { data: { id?: string } }) {
187
193
  openBlade({
188
194
  name: "ProductDetails",
189
195
  param: event.data.id,
190
- onOpen() { selectedItemId.value = event.data.id; },
191
- onClose() { selectedItemId.value = undefined; },
196
+ onOpen() {
197
+ selectedItemId.value = event.data.id;
198
+ },
199
+ onClose() {
200
+ selectedItemId.value = undefined;
201
+ },
192
202
  });
193
203
  }
194
204
 
@@ -250,7 +260,9 @@ A "middle" blade acts as both child (calls its parent) and parent (exposes metho
250
260
  const { openBlade, callParent, exposeToChildren, closeSelf } = useBlade();
251
261
 
252
262
  // As a parent — expose reload for child blades
253
- async function reload() { await loadOrder(param.value!); }
263
+ async function reload() {
264
+ await loadOrder(param.value!);
265
+ }
254
266
  exposeToChildren({ reload });
255
267
 
256
268
  // As a child — open sub-details blade
@@ -1,6 +1,6 @@
1
1
  # Details Composable Pattern (`use<Entity>`)
2
2
 
3
- Reference source: `apps/vendor-portal/src/modules/team/composables/useTeamMember/index.ts`
3
+ Generic worked example for the canonical `useTeamMember` / `useEntity` composable shape.
4
4
 
5
5
  ## Overview
6
6
 
@@ -13,19 +13,9 @@ Naming convention: `use<Entity>` (singular) for details, `use<Entity>s` (plural)
13
13
  ## Full Code Skeleton
14
14
 
15
15
  ```ts
16
- import {
17
- useModificationTracker,
18
- useApiClient,
19
- useAsync,
20
- useLoading,
21
- } from "@vc-shell/framework";
16
+ import { useModificationTracker, useApiClient, useAsync, useLoading } from "@vc-shell/framework";
22
17
  import type { AsyncAction } from "@vc-shell/framework";
23
- import {
24
- XxxClient,
25
- XxxType,
26
- CreateXxxCommand,
27
- UpdateXxxCommand,
28
- } from "../../api_client/xxx-client";
18
+ import { XxxClient, XxxType, CreateXxxCommand, UpdateXxxCommand } from "../../api_client/xxx-client";
29
19
  import { computed, ComputedRef, Ref, ref } from "vue";
30
20
 
31
21
  // NOTE: useI18n is NOT imported here. Translations belong in blade components.
@@ -50,15 +40,11 @@ export default (): IUseXxx => {
50
40
  // --- Entity ref and modification tracker ---
51
41
  // entityRef is internal; currentValue is exposed as `entity`
52
42
  const entityRef = ref({} as XxxType) as Ref<XxxType>;
53
- const { currentValue, pristineValue, resetModificationState, isModified } =
54
- useModificationTracker(entityRef);
43
+ const { currentValue, pristineValue, resetModificationState, isModified } = useModificationTracker(entityRef);
55
44
 
56
45
  // --- CRUD operations (each has its own loading ref) ---
57
46
 
58
- const { action: getXxx, loading: getXxxLoading } = useAsync<
59
- { id: string },
60
- void
61
- >(async (args) => {
47
+ const { action: getXxx, loading: getXxxLoading } = useAsync<{ id: string }, void>(async (args) => {
62
48
  if (!args?.id) {
63
49
  throw new Error("Id is required");
64
50
  }
@@ -74,10 +60,7 @@ export default (): IUseXxx => {
74
60
  resetModificationState();
75
61
  });
76
62
 
77
- const { action: createXxx, loading: createXxxLoading } = useAsync<
78
- XxxType,
79
- void
80
- >(async (details) => {
63
+ const { action: createXxx, loading: createXxxLoading } = useAsync<XxxType, void>(async (details) => {
81
64
  const client = await getApiClient();
82
65
 
83
66
  const command = {
@@ -93,10 +76,7 @@ export default (): IUseXxx => {
93
76
  resetModificationState();
94
77
  });
95
78
 
96
- const { action: updateXxx, loading: updateXxxLoading } = useAsync<
97
- XxxType,
98
- void
99
- >(async (details) => {
79
+ const { action: updateXxx, loading: updateXxxLoading } = useAsync<XxxType, void>(async (details) => {
100
80
  if (!details?.id) {
101
81
  throw new Error("Id is required");
102
82
  }
@@ -116,10 +96,7 @@ export default (): IUseXxx => {
116
96
  resetModificationState();
117
97
  });
118
98
 
119
- const { action: deleteXxx, loading: deleteXxxLoading } = useAsync<
120
- { id: string },
121
- void
122
- >(async (args) => {
99
+ const { action: deleteXxx, loading: deleteXxxLoading } = useAsync<{ id: string }, void>(async (args) => {
123
100
  if (!args?.id) {
124
101
  throw new Error("Id is required");
125
102
  }
@@ -138,12 +115,7 @@ export default (): IUseXxx => {
138
115
  // --- Return ---
139
116
  return {
140
117
  // Aggregate all async loading refs into a single computed boolean
141
- loading: useLoading(
142
- getXxxLoading,
143
- createXxxLoading,
144
- updateXxxLoading,
145
- deleteXxxLoading,
146
- ),
118
+ loading: useLoading(getXxxLoading, createXxxLoading, updateXxxLoading, deleteXxxLoading),
147
119
  // currentValue is the reactive entity — alias as `entity` for the blade
148
120
  entity: currentValue,
149
121
  modified: computed(() => isModified.value),
@@ -263,9 +235,9 @@ export default (): IUseXxx => {
263
235
 
264
236
  ---
265
237
 
266
- ## Route Params (when entity scope requires sellerId / tenantId)
238
+ ## Route Params (when entity scope requires a parent ownerId / tenantId)
267
239
 
268
- Some API calls require a scope parameter (e.g., `sellerId`) extracted from the route. Use `useRoute()`:
240
+ Some API calls require a scope parameter (e.g., `ownerId`) extracted from the route. Use `useRoute()`:
269
241
 
270
242
  ```ts
271
243
  import { useRoute } from "vue-router";
@@ -274,20 +246,18 @@ export default (): IUseXxx => {
274
246
  const route = useRoute();
275
247
  const { getApiClient } = useApiClient(XxxClient);
276
248
 
277
- async function getSellerId(): Promise<string> {
278
- return route?.params?.sellerId as string;
249
+ async function getOwnerId(): Promise<string> {
250
+ return route?.params?.ownerId as string;
279
251
  }
280
252
 
281
- const { action: getXxx, loading: getXxxLoading } = useAsync<{ id: string }>(
282
- async (args) => {
283
- const client = await getApiClient();
284
- const sellerId = await getSellerId();
253
+ const { action: getXxx, loading: getXxxLoading } = useAsync<{ id: string }>(async (args) => {
254
+ const client = await getApiClient();
255
+ const ownerId = await getOwnerId();
285
256
 
286
- const result = await client.getXxx(args.id, sellerId);
287
- currentValue.value = result;
288
- resetModificationState();
289
- },
290
- );
257
+ const result = await client.getXxx(args.id, ownerId);
258
+ currentValue.value = result;
259
+ resetModificationState();
260
+ });
291
261
 
292
262
  // ...
293
263
  };
@@ -2,7 +2,7 @@
2
2
 
3
3
  Describes the plural composable that handles search, pagination, and sort for a list blade. Named with the **plural** entity name: `useTeamMembers`, `useCatalogItems`, `useOrders`.
4
4
 
5
- Source: extracted from `apps/vendor-portal/src/modules/team/composables/useTeamMembers/index.ts`.
5
+ Generic worked example for the plural list composable shape.
6
6
 
7
7
  ---
8
8
 
@@ -10,12 +10,7 @@ Source: extracted from `apps/vendor-portal/src/modules/team/composables/useTeamM
10
10
 
11
11
  ```ts
12
12
  import { useApiClient, useAsync, useLoading } from "@vc-shell/framework";
13
- import {
14
- SearchXxxQuery,
15
- SearchXxxResult,
16
- XxxType,
17
- XxxClient,
18
- } from "../../../../api_client/<module-client-file>";
13
+ import { SearchXxxQuery, SearchXxxResult, XxxType, XxxClient } from "../../../../api_client/<module-client-file>";
19
14
  import type { SearchXxxQuery as ISearchXxxQuery } from "../../../../api_client/<module-client-file>";
20
15
  import { computed, Ref, ref } from "vue";
21
16
  import { useRoute } from "vue-router";
@@ -39,7 +34,7 @@ interface IUseXxxsOptions {
39
34
 
40
35
  export default (options?: IUseXxxsOptions): IUseXxxs => {
41
36
  const { getApiClient } = useApiClient(XxxClient);
42
- const route = useRoute(); // for extracting route params (e.g., sellerId, parentId)
37
+ const route = useRoute(); // for extracting route params (e.g., ownerId, parentId)
43
38
 
44
39
  const pageSize = options?.pageSize || 20;
45
40
 
@@ -90,24 +85,19 @@ export default (options?: IUseXxxsOptions): IUseXxxs => {
90
85
 
91
86
  ```ts
92
87
  import { useApiClient, useAsync, useLoading } from "@vc-shell/framework";
93
- import {
94
- SearchSellerUsersQuery,
95
- SearchSellerUsersResult,
96
- SellerUser,
97
- VcmpSellerSecurityClient,
98
- } from "../../../../api_client/virtocommerce.marketplacevendor";
99
- import type { SearchSellerUsersQuery as ISearchSellerUsersQuery } from "../../../../api_client/virtocommerce.marketplacevendor";
88
+ import { SearchUsersQuery, SearchUsersResult, User, UserSecurityClient } from "../../../../api_client/virtocommerce.mymodule";
89
+ import type { SearchUsersQuery as ISearchUsersQuery } from "../../../../api_client/virtocommerce.mymodule";
100
90
  import { computed, Ref, ref } from "vue";
101
91
  import { useRoute } from "vue-router";
102
92
 
103
93
  interface IUseTeamMembers {
104
94
  readonly loading: Ref<boolean>;
105
- readonly membersList: Ref<SellerUser[]>;
95
+ readonly membersList: Ref<User[]>;
106
96
  readonly totalCount: Ref<number>;
107
97
  readonly pages: Ref<number>;
108
98
  currentPage: Ref<number>;
109
- searchQuery: Ref<ISearchSellerUsersQuery>;
110
- getTeamMembers: (query?: ISearchSellerUsersQuery) => Promise<void>;
99
+ searchQuery: Ref<ISearchUsersQuery>;
100
+ getTeamMembers: (query?: ISearchUsersQuery) => Promise<void>;
111
101
  }
112
102
 
113
103
  interface IUseTeamMembersOptions {
@@ -116,29 +106,29 @@ interface IUseTeamMembersOptions {
116
106
  }
117
107
 
118
108
  export default (options?: IUseTeamMembersOptions): IUseTeamMembers => {
119
- const { getApiClient } = useApiClient(VcmpSellerSecurityClient);
109
+ const { getApiClient } = useApiClient(UserSecurityClient);
120
110
  const route = useRoute();
121
111
 
122
112
  const pageSize = options?.pageSize || 20;
123
- const searchQuery = ref<ISearchSellerUsersQuery>({
113
+ const searchQuery = ref<ISearchUsersQuery>({
124
114
  take: pageSize,
125
115
  sort: options?.sort,
126
116
  });
127
117
 
128
- const searchResult = ref<SearchSellerUsersResult>();
118
+ const searchResult = ref<SearchUsersResult>();
129
119
 
130
- async function GetSellerId(): Promise<string> {
131
- const result = route?.params?.sellerId as string;
120
+ async function GetOwnerId(): Promise<string> {
121
+ const result = route?.params?.ownerId as string;
132
122
  return result;
133
123
  }
134
124
 
135
- const { action: getTeamMembers, loading: getTeamMembersLoading } = useAsync<ISearchSellerUsersQuery>(async (query) => {
125
+ const { action: getTeamMembers, loading: getTeamMembersLoading } = useAsync<ISearchUsersQuery>(async (query) => {
136
126
  const client = await getApiClient();
137
- const sellerId = await GetSellerId();
127
+ const ownerId = await GetOwnerId();
138
128
  searchQuery.value = { ...searchQuery.value, ...query };
139
129
 
140
- const command = { ...searchQuery.value, sellerId } as SearchSellerUsersQuery;
141
- searchResult.value = await client.searchSellerUsers(command);
130
+ const command = { ...searchQuery.value, ownerId } as SearchUsersQuery;
131
+ searchResult.value = await client.searchUsers(command);
142
132
  });
143
133
 
144
134
  return {
@@ -158,7 +148,9 @@ export default (options?: IUseTeamMembersOptions): IUseTeamMembers => {
158
148
  ## Key Rules
159
149
 
160
150
  ### File location
151
+
161
152
  Each composable lives in its own subdirectory with an `index.ts`:
153
+
162
154
  ```
163
155
  composables/
164
156
  ├── useXxxs/
@@ -167,39 +159,52 @@ composables/
167
159
  ```
168
160
 
169
161
  ### Default export (not named)
162
+
170
163
  The composable is a **default export** (a factory function). Named exports are the interfaces only. The barrel (`composables/index.ts`) wraps it with a named export:
164
+
171
165
  ```ts
172
166
  export { default as useXxxs } from "./useXxxs";
173
167
  ```
174
168
 
175
169
  ### Type aliasing
170
+
176
171
  NSwag generates classes with the same name as their interfaces. Import the class for runtime use, and import the interface type separately with an alias:
172
+
177
173
  ```ts
178
- import { SearchXxxQuery, XxxClient } from "..."; // class (runtime)
174
+ import { SearchXxxQuery, XxxClient } from "..."; // class (runtime)
179
175
  import type { SearchXxxQuery as ISearchXxxQuery } from "..."; // interface (type-only)
180
176
  ```
181
177
 
182
178
  ### `useAsync` signature
179
+
183
180
  `useAsync<TArg>(fn)` — generic `TArg` is the type of the argument passed to the action:
181
+
184
182
  ```ts
185
183
  const { action: getXxxs, loading: getXxxsLoading } = useAsync<ISearchXxxQuery>(async (query) => {
186
184
  // query is typed as ISearchXxxQuery | undefined
187
185
  });
188
186
  ```
187
+
189
188
  `action` is the callable — invoke it as `getXxxs(query)`.
190
189
 
191
190
  ### `useLoading`
191
+
192
192
  Wrap loading refs with `useLoading` for consistent boolean ref behavior:
193
+
193
194
  ```ts
194
195
  loading: useLoading(getXxxsLoading),
195
196
  ```
197
+
196
198
  If there are multiple async operations (e.g., search + delete), pass all loading refs:
199
+
197
200
  ```ts
198
201
  loading: useLoading(getXxxsLoading, deleteXxxLoading),
199
202
  ```
200
203
 
201
204
  ### Route params
202
- Use `useRoute()` to access route params when the API requires a parent entity ID (e.g., `sellerId`, `orderId`). Access inside the async function, not at module scope:
205
+
206
+ Use `useRoute()` to access route params when the API requires a parent entity ID (e.g., `ownerId`, `orderId`). Access inside the async function, not at module scope:
207
+
203
208
  ```ts
204
209
  const route = useRoute();
205
210
  // inside useAsync callback:
@@ -207,15 +212,18 @@ const parentId = route?.params?.parentId as string;
207
212
  ```
208
213
 
209
214
  ### No `useI18n` in composables
215
+
210
216
  i18n belongs in blade components only. Composables must not import or use `useI18n`.
211
217
 
212
218
  ### `searchQuery` is mutable
219
+
213
220
  The `searchQuery` ref is returned with `Ref<ISearchXxxQuery>` (not `readonly`) because the blade reads it to construct reload/pagination calls:
221
+
214
222
  ```ts
215
223
  // In blade:
216
224
  const reload = async () => {
217
225
  await getXxxs({
218
- ...searchQuery.value, // preserve existing params
226
+ ...searchQuery.value, // preserve existing params
219
227
  skip: (currentPage.value - 1) * (searchQuery.value?.take ?? 20),
220
228
  sort: sortExpression.value,
221
229
  });
@@ -223,22 +231,26 @@ const reload = async () => {
223
231
  ```
224
232
 
225
233
  ### `currentPage` computation
234
+
226
235
  ```ts
227
236
  currentPage: computed(() => Math.floor((searchQuery.value.skip || 0) / pageSize) + 1),
228
237
  ```
238
+
229
239
  Derived from `skip` — no separate state needed.
230
240
 
231
241
  ### `pages` computation
242
+
232
243
  ```ts
233
244
  pages: computed(() => Math.ceil((searchResult.value?.totalCount || 0) / pageSize)),
234
245
  ```
246
+
235
247
  Total number of pages for pagination component.
236
248
 
237
249
  ---
238
250
 
239
251
  ## Composable Without Route Params
240
252
 
241
- When the API doesn't need a parent ID (module is not nested under a seller/store/etc.):
253
+ When the API doesn't need a parent ID (module is not nested under an owner/store/etc.):
242
254
 
243
255
  ```ts
244
256
  const { action: getXxxs, loading: getXxxsLoading } = useAsync<ISearchXxxQuery>(async (query) => {
@@ -34,13 +34,13 @@ export * from "./composables";
34
34
 
35
35
  ```ts
36
36
  interface DashboardWidget {
37
- id: string; // unique across all registered widgets
38
- name: string; // display name
39
- component: Component; // widget Vue component, wrapped in markRaw()
40
- size: { width: number; height: number }; // grid units
37
+ id: string; // unique across all registered widgets
38
+ name: string; // display name
39
+ component: Component; // widget Vue component, wrapped in markRaw()
40
+ size: { width: number; height: number }; // grid units
41
41
  position?: { x: number; y: number }; // optional initial grid position
42
- permissions?: string[]; // optional: restrict visibility by permission
43
- props?: Record<string, unknown>; // optional: static props passed to component
42
+ permissions?: string[]; // optional: restrict visibility by permission
43
+ props?: Record<string, unknown>; // optional: static props passed to component
44
44
  }
45
45
  ```
46
46
 
@@ -66,28 +66,25 @@ The widget component is a plain Vue SFC placed in `src/modules/xxx/components/`:
66
66
  </template>
67
67
 
68
68
  <script lang="ts" setup>
69
- import {
70
- DashboardWidgetCard,
71
- DashboardStatItem,
72
- } from "@vc-shell/framework";
69
+ import { DashboardWidgetCard, DashboardStatItem } from "@vc-shell/framework";
73
70
  import { ref, onMounted } from "vue";
74
71
  import useXxxs from "../composables/useXxxs";
75
72
 
76
73
  const { getXxxs, totalCount, loading } = useXxxs();
77
74
 
78
75
  onMounted(async () => {
79
- await getXxxs({ take: 0 }); // fetch count only
76
+ await getXxxs({ take: 0 }); // fetch count only
80
77
  });
81
78
  </script>
82
79
  ```
83
80
 
84
81
  ### Available dashboard sub-components from `@vc-shell/framework`
85
82
 
86
- | Component | Description |
87
- |-----------------------|---------------------------------------------|
88
- | `DashboardWidgetCard` | Card wrapper with title slot |
89
- | `DashboardStatItem` | Single stat row: label + value + loading |
90
- | `DashboardBarChart` | Horizontal bar chart for breakdown stats |
83
+ | Component | Description |
84
+ | --------------------- | ---------------------------------------- |
85
+ | `DashboardWidgetCard` | Card wrapper with title slot |
86
+ | `DashboardStatItem` | Single stat row: label + value + loading |
87
+ | `DashboardBarChart` | Horizontal bar chart for breakdown stats |
91
88
 
92
89
  ---
93
90
 
@@ -101,6 +98,7 @@ src/modules/xxx/
101
98
  ```
102
99
 
103
100
  `components/index.ts` barrel:
101
+
104
102
  ```ts
105
103
  export { default as XxxDashboardCard } from "./XxxDashboardCard.vue";
106
104
  ```