@vc-shell/vc-app-skill 2.0.0-alpha.33 → 2.0.0-alpha.34

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 +78 -54
  2. package/README.md +42 -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 +18 -7
  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 +28 -24
  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 +27 -25
  29. package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +15 -15
  30. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +43 -47
  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 +9 -9
  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/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +28 -0
  46. package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +32 -24
  47. package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +32 -11
  48. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +22 -13
  49. package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +7 -7
  50. package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +32 -24
  51. package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +21 -17
  52. package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +24 -24
  53. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +28 -31
  54. package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +43 -24
  55. package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +68 -48
  56. package/runtime/knowledge/docs/core/composables/useWebVitals/useWebVitals.docs.md +19 -19
  57. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +42 -47
  58. package/runtime/knowledge/docs/core/directives/autofocus/autofocus.docs.md +10 -4
  59. package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +35 -20
  60. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +36 -35
  61. package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +38 -38
  62. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +79 -62
  63. package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +10 -10
  64. package/runtime/knowledge/docs/core/plugins/i18n/i18n.docs.md +21 -23
  65. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +91 -83
  66. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +10 -16
  67. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +9 -9
  68. package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +65 -22
  69. package/runtime/knowledge/docs/core/services/services.docs.md +19 -22
  70. package/runtime/knowledge/docs/core/types/types.docs.md +40 -40
  71. package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +27 -27
  72. package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +23 -23
  73. package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +22 -25
  74. package/runtime/knowledge/docs/core/utilities/utilities.docs.md +64 -64
  75. package/runtime/knowledge/docs/injection-keys.docs.md +52 -51
  76. package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +9 -9
  77. package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +23 -43
  78. package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +5 -5
  79. package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +5 -5
  80. package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +8 -7
  81. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +7 -7
  82. package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +8 -7
  83. package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +29 -13
  84. package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +13 -16
  85. package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +1 -7
  86. package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +5 -5
  87. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
  88. package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
  89. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -9
  90. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +11 -17
  91. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +34 -65
  92. package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +16 -26
  93. package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +2 -2
  94. package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +7 -9
  95. package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +30 -40
  96. package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +26 -19
  97. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +15 -12
  98. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +15 -26
  99. package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +21 -19
  100. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +83 -67
  101. package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +100 -59
  102. package/runtime/knowledge/docs/ui/components/atoms/vc-col/vc-col.docs.md +28 -11
  103. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +20 -17
  104. package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +26 -17
  105. package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +30 -32
  106. package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +25 -48
  107. package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +29 -24
  108. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +23 -15
  109. package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +22 -13
  110. package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +33 -18
  111. package/runtime/knowledge/docs/ui/components/atoms/vc-row/vc-row.docs.md +56 -15
  112. package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +28 -15
  113. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +40 -20
  114. package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +25 -14
  115. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +40 -14
  116. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +54 -42
  117. package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +17 -17
  118. package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +21 -21
  119. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +23 -10
  120. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +55 -44
  121. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +23 -20
  122. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +92 -65
  123. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +22 -36
  124. package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +65 -23
  125. package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +52 -73
  126. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +91 -85
  127. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +38 -42
  128. package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +56 -73
  129. package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +61 -27
  130. package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +42 -50
  131. package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +35 -64
  132. package/runtime/knowledge/docs/ui/components/molecules/vc-image-tile/vc-image-tile.docs.md +38 -41
  133. package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +109 -131
  134. package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +47 -88
  135. package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +50 -64
  136. package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +29 -24
  137. package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +32 -28
  138. package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +57 -65
  139. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +28 -26
  140. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +55 -20
  141. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +21 -35
  142. package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +38 -33
  143. package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +72 -83
  144. package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +21 -16
  145. package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +55 -64
  146. package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +51 -70
  147. package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +58 -57
  148. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +49 -26
  149. package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +82 -28
  150. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +90 -75
  151. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +99 -48
  152. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +548 -367
  153. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +35 -52
  154. package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +33 -62
  155. package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +17 -23
  156. package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +109 -68
  157. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +82 -44
  158. package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +8 -8
  159. package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +164 -0
  160. package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +34 -26
  161. package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +48 -40
  162. package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +30 -17
  163. package/runtime/knowledge/docs/ui/types/ui-types.docs.md +40 -29
  164. package/runtime/knowledge/examples/offers-module.md +15 -13
  165. package/runtime/knowledge/examples/team-module.md +82 -119
  166. package/runtime/knowledge/examples/videos-module.md +44 -17
  167. package/runtime/knowledge/index.md +22 -0
  168. package/runtime/knowledge/migration-prompts/blade-form-migration.md +17 -8
  169. package/runtime/knowledge/migration-prompts/blade-props-migration.md +1 -2
  170. package/runtime/knowledge/migration-prompts/datatable-migration.md +801 -0
  171. package/runtime/knowledge/migration-prompts/icon-migration.md +97 -0
  172. package/runtime/knowledge/migration-prompts/manual-migration-audit.md +117 -0
  173. package/runtime/knowledge/migration-prompts/notifications-migration.md +8 -3
  174. package/runtime/knowledge/migration-prompts/nswag-migration.md +25 -29
  175. package/runtime/knowledge/migration-prompts/use-assets-migration.md +164 -0
  176. package/runtime/knowledge/migration-prompts/use-data-table-pagination-migration.md +176 -0
  177. package/runtime/knowledge/migration-prompts/widgets-migration.md +48 -27
  178. package/runtime/knowledge/patterns/assets-management.md +20 -20
  179. package/runtime/knowledge/patterns/blade-navigation.md +7 -14
  180. package/runtime/knowledge/patterns/blade-widget.md +19 -17
  181. package/runtime/knowledge/patterns/child-blade-flow.md +19 -7
  182. package/runtime/knowledge/patterns/composable-details.md +20 -50
  183. package/runtime/knowledge/patterns/composable-list.md +43 -31
  184. package/runtime/knowledge/patterns/dashboard-widget.md +14 -16
  185. package/runtime/knowledge/patterns/datatable-pattern.md +521 -0
  186. package/runtime/knowledge/patterns/details-blade-pattern.md +78 -116
  187. package/runtime/knowledge/patterns/extension-points-usage.md +53 -44
  188. package/runtime/knowledge/patterns/form-validation.md +28 -64
  189. package/runtime/knowledge/patterns/list-blade-pattern.md +33 -21
  190. package/runtime/knowledge/patterns/module-structure.md +7 -1
  191. package/runtime/knowledge/patterns/multilanguage-fields.md +8 -14
  192. package/runtime/knowledge/patterns/notification-template.md +21 -14
  193. package/runtime/knowledge/patterns/signalr-notifications.md +30 -32
  194. package/runtime/knowledge/patterns/toolbar-pattern.md +18 -20
  195. package/runtime/vc-app.md +241 -62
@@ -30,21 +30,21 @@ const { uiSettings, loading } = useSettings();
30
30
 
31
31
  ### Returns
32
32
 
33
- | Property | Type | Description |
34
- |----------|------|-------------|
35
- | `uiSettings` | `Ref<IUISetting>` | Reactive object with current UI customization values |
36
- | `loading` | `ComputedRef<boolean>` | Whether settings are being fetched from the API |
33
+ | Property | Type | Description |
34
+ | --------------- | --------------------------------------------------- | --------------------------------------------------------- |
35
+ | `uiSettings` | `Ref<IUISetting>` | Reactive object with current UI customization values |
36
+ | `loading` | `ComputedRef<boolean>` | Whether settings are being fetched from the API |
37
37
  | `applySettings` | `(args: { logo?, title?, avatar?, role? }) => void` | Override settings with custom values (prevents API fetch) |
38
38
 
39
39
  ### IUISetting
40
40
 
41
- | Property | Type | Description |
42
- |----------|------|-------------|
41
+ | Property | Type | Description |
42
+ | --------------- | --------- | ------------------------------------------ |
43
43
  | `contrast_logo` | `string?` | Logo variant for dark/contrast backgrounds |
44
- | `logo` | `string?` | Primary application logo URL |
45
- | `title` | `string?` | Application title |
46
- | `avatar` | `string?` | Current user avatar URL |
47
- | `role` | `string?` | Current user role display name |
44
+ | `logo` | `string?` | Primary application logo URL |
45
+ | `title` | `string?` | Application title |
46
+ | `avatar` | `string?` | Current user avatar URL |
47
+ | `role` | `string?` | Current user role display name |
48
48
 
49
49
  ## Common Patterns
50
50
 
@@ -58,14 +58,20 @@ const { uiSettings, loading } = useSettings();
58
58
  </script>
59
59
 
60
60
  <template>
61
- <div v-loading="loading" class="tw-min-h-[40px]">
61
+ <div
62
+ v-loading="loading"
63
+ class="tw-min-h-[40px]"
64
+ >
62
65
  <img
63
66
  v-if="uiSettings.logo"
64
67
  :src="uiSettings.logo"
65
68
  :alt="uiSettings.title ?? 'Application Logo'"
66
69
  class="tw-h-10"
67
70
  />
68
- <span v-if="uiSettings.title" class="tw-ml-2 tw-text-lg tw-font-semibold">
71
+ <span
72
+ v-if="uiSettings.title"
73
+ class="tw-ml-2 tw-text-lg tw-font-semibold"
74
+ >
69
75
  {{ uiSettings.title }}
70
76
  </span>
71
77
  </div>
@@ -117,7 +123,10 @@ watch(user, (currentUser) => {
117
123
  alt="User avatar"
118
124
  class="tw-w-8 tw-h-8 tw-rounded-full"
119
125
  />
120
- <span v-if="uiSettings.role" class="tw-text-sm tw-text-gray-500">
126
+ <span
127
+ v-if="uiSettings.role"
128
+ class="tw-text-sm tw-text-gray-500"
129
+ >
121
130
  {{ uiSettings.role }}
122
131
  </span>
123
132
  </div>
@@ -29,16 +29,16 @@ const items = settingsMenu.items.value;
29
29
 
30
30
  ### Returns (`ISettingsMenuService`)
31
31
 
32
- | Property | Type | Description |
33
- |----------|------|-------------|
34
- | `register` | `(options: RegisterSettingsMenuItemOptions) => string` | Register a settings menu item; returns the item ID |
35
- | `unregister` | `(id: string) => void` | Remove a settings menu item by ID |
36
- | `items` | `ComputedRef<ISettingsMenuItem[]>` | Reactive array of all registered settings menu items |
32
+ | Property | Type | Description |
33
+ | ------------ | ------------------------------------------------------ | ---------------------------------------------------- |
34
+ | `register` | `(options: RegisterSettingsMenuItemOptions) => string` | Register a settings menu item; returns the item ID |
35
+ | `unregister` | `(id: string) => void` | Remove a settings menu item by ID |
36
+ | `items` | `ComputedRef<ISettingsMenuItem[]>` | Reactive array of all registered settings menu items |
37
37
 
38
38
  ### Related Exports
39
39
 
40
- | Export | Description |
41
- |--------|-------------|
40
+ | Export | Description |
41
+ | ----------------------- | -------------------------------------------------- |
42
42
  | `provideSettingsMenu()` | Create and provide the service in a root component |
43
43
 
44
44
  ## Common Patterns
@@ -15,7 +15,7 @@ Internally, it delegates to `useMenuExpanded()` to share reactive state with oth
15
15
 
16
16
  ```vue
17
17
  <script setup lang="ts">
18
- import { useSidebarState } from '@vc-shell/framework';
18
+ import { useSidebarState } from "@vc-shell/framework";
19
19
 
20
20
  const { isExpanded, isPinned, togglePin, openMenu, closeMenu } = useSidebarState();
21
21
  </script>
@@ -24,10 +24,17 @@ const { isExpanded, isPinned, togglePin, openMenu, closeMenu } = useSidebarState
24
24
  <div class="tw-flex tw-items-center">
25
25
  <!-- Show full label when expanded, icon-only when collapsed -->
26
26
  <VcIcon icon="fas fa-box" />
27
- <span v-if="isExpanded" class="tw-ml-2">Products</span>
27
+ <span
28
+ v-if="isExpanded"
29
+ class="tw-ml-2"
30
+ >Products</span
31
+ >
28
32
 
29
33
  <!-- Pin/unpin toggle button -->
30
- <button @click="togglePin" class="tw-ml-auto">
34
+ <button
35
+ @click="togglePin"
36
+ class="tw-ml-auto"
37
+ >
31
38
  <VcIcon :icon="isPinned ? 'fas fa-thumbtack' : 'fas fa-thumbtack tw-rotate-45'" />
32
39
  </button>
33
40
  </div>
@@ -38,21 +45,21 @@ const { isExpanded, isPinned, togglePin, openMenu, closeMenu } = useSidebarState
38
45
 
39
46
  ### Returns -- State
40
47
 
41
- | Property | Type | Description |
42
- |---|---|---|
43
- | `isPinned` | `Ref<boolean>` | Sidebar is pinned open by the user. Persisted to localStorage so it survives page reloads. |
44
- | `isHoverExpanded` | `Ref<boolean>` | Sidebar is temporarily expanded because the mouse is hovering over it (desktop only). |
45
- | `isMenuOpen` | `Ref<boolean>` | Mobile menu overlay is visible. |
46
- | `isExpanded` | `ComputedRef<boolean>` | Derived: `isPinned || isHoverExpanded`. Use this when you just need to know if sidebar content is visible. |
48
+ | Property | Type | Description |
49
+ | ----------------- | ---------------------- | ------------------------------------------------------------------------------------------ | --- | ------------------------------------------------------------------------------------ |
50
+ | `isPinned` | `Ref<boolean>` | Sidebar is pinned open by the user. Persisted to localStorage so it survives page reloads. |
51
+ | `isHoverExpanded` | `Ref<boolean>` | Sidebar is temporarily expanded because the mouse is hovering over it (desktop only). |
52
+ | `isMenuOpen` | `Ref<boolean>` | Mobile menu overlay is visible. |
53
+ | `isExpanded` | `ComputedRef<boolean>` | Derived: `isPinned | | isHoverExpanded`. Use this when you just need to know if sidebar content is visible. |
47
54
 
48
55
  ### Returns -- Actions
49
56
 
50
- | Property | Type | Description |
51
- |---|---|---|
52
- | `togglePin` | `() => void` | Toggle pinned state. Persists the new value to localStorage immediately. |
57
+ | Property | Type | Description |
58
+ | ------------------ | -------------------------- | ---------------------------------------------------------------------------------------------------------------- |
59
+ | `togglePin` | `() => void` | Toggle pinned state. Persists the new value to localStorage immediately. |
53
60
  | `setHoverExpanded` | `(value: boolean) => void` | Set hover expansion. Opening has a 200ms delay to prevent flicker from brief mouse passes; closing is immediate. |
54
- | `openMenu` | `() => void` | Show the mobile menu overlay. |
55
- | `closeMenu` | `() => void` | Hide the mobile menu overlay. |
61
+ | `openMenu` | `() => void` | Show the mobile menu overlay. |
62
+ | `closeMenu` | `() => void` | Hide the mobile menu overlay. |
56
63
 
57
64
  ## Setup
58
65
 
@@ -60,7 +67,7 @@ const { isExpanded, isPinned, togglePin, openMenu, closeMenu } = useSidebarState
60
67
 
61
68
  ```typescript
62
69
  // Inside VcApp.vue setup
63
- import { provideSidebarState } from '@vc-shell/framework';
70
+ import { provideSidebarState } from "@vc-shell/framework";
64
71
 
65
72
  provideSidebarState();
66
73
  ```
@@ -69,8 +76,8 @@ provideSidebarState();
69
76
 
70
77
  ```vue
71
78
  <script setup lang="ts">
72
- import { useSidebarState } from '@vc-shell/framework';
73
- import { useBladeContext } from '@vc-shell/framework';
79
+ import { useSidebarState } from "@vc-shell/framework";
80
+ import { useBladeContext } from "@vc-shell/framework";
74
81
 
75
82
  const { closeMenu, isMenuOpen } = useSidebarState();
76
83
  const { openBlade } = useBladeContext();
@@ -83,7 +90,7 @@ async function navigateToProducts() {
83
90
 
84
91
  await openBlade({
85
92
  component: ProductListBlade,
86
- param: { catalogId: 'default' },
93
+ param: { catalogId: "default" },
87
94
  });
88
95
  }
89
96
  </script>
@@ -100,18 +107,19 @@ async function navigateToProducts() {
100
107
 
101
108
  ```vue
102
109
  <script setup lang="ts">
103
- import { useSidebarState } from '@vc-shell/framework';
104
- import { computed } from 'vue';
110
+ import { useSidebarState } from "@vc-shell/framework";
111
+ import { computed } from "vue";
105
112
 
106
113
  const { isExpanded } = useSidebarState();
107
114
 
108
- const contentClass = computed(() =>
109
- isExpanded.value ? 'tw-ml-64' : 'tw-ml-16',
110
- );
115
+ const contentClass = computed(() => (isExpanded.value ? "tw-ml-64" : "tw-ml-16"));
111
116
  </script>
112
117
 
113
118
  <template>
114
- <div :class="contentClass" class="tw-transition-all tw-duration-200">
119
+ <div
120
+ :class="contentClass"
121
+ class="tw-transition-all tw-duration-200"
122
+ >
115
123
  <slot />
116
124
  </div>
117
125
  </template>
@@ -17,14 +17,18 @@ The composable is initialized automatically at app startup. To reactively read t
17
17
 
18
18
  ```vue
19
19
  <script setup lang="ts">
20
- import { useSlowNetworkDetection } from '@vc-shell/framework';
20
+ import { useSlowNetworkDetection } from "@vc-shell/framework";
21
21
 
22
22
  const { isSlowNetwork } = useSlowNetworkDetection();
23
23
  </script>
24
24
 
25
25
  <template>
26
26
  <VcBlade title="Products">
27
- <VcBanner v-if="isSlowNetwork" variant="warning" icon="lucide-wifi">
27
+ <VcBanner
28
+ v-if="isSlowNetwork"
29
+ variant="warning"
30
+ icon="lucide-wifi"
31
+ >
28
32
  <template #title>Slow connection</template>
29
33
  Loading may take longer than usual.
30
34
  </VcBanner>
@@ -38,19 +42,19 @@ const { isSlowNetwork } = useSlowNetworkDetection();
38
42
 
39
43
  ### Returns
40
44
 
41
- | Property | Type | Description |
42
- |---|---|---|
43
- | `isSlowNetwork` | `Readonly<Ref<boolean>>` | `true` when the network is slow (either channel active). Read-only. |
44
- | `trackRequest` | `(id: string) => void` | Start tracking a request. If it isn't untracked within 10 s, it counts as slow. |
45
- | `untrackRequest` | `(id: string) => void` | Stop tracking a request. Cancels the timer or decrements the slow count. |
45
+ | Property | Type | Description |
46
+ | ---------------- | ------------------------ | ------------------------------------------------------------------------------- |
47
+ | `isSlowNetwork` | `Readonly<Ref<boolean>>` | `true` when the network is slow (either channel active). Read-only. |
48
+ | `trackRequest` | `(id: string) => void` | Start tracking a request. If it isn't untracked within 10 s, it counts as slow. |
49
+ | `untrackRequest` | `(id: string) => void` | Stop tracking a request. Cancels the timer or decrements the slow count. |
46
50
 
47
51
  ### Constants
48
52
 
49
- | Name | Value | Purpose |
50
- |---|---|---|
51
- | `SLOW_REQUEST_THRESHOLD_MS` | `10000` | Time before a pending request is considered slow |
52
- | `DISMISS_DELAY_MS` | `3000` | Delay before hiding the notification after recovery |
53
- | `SLOW_EFFECTIVE_TYPES` | `["slow-2g", "2g"]` | Connection types flagged as slow |
53
+ | Name | Value | Purpose |
54
+ | --------------------------- | ------------------- | --------------------------------------------------- |
55
+ | `SLOW_REQUEST_THRESHOLD_MS` | `10000` | Time before a pending request is considered slow |
56
+ | `DISMISS_DELAY_MS` | `3000` | Delay before hiding the notification after recovery |
57
+ | `SLOW_EFFECTIVE_TYPES` | `["slow-2g", "2g"]` | Connection types flagged as slow |
54
58
 
55
59
  ## How It Works
56
60
 
@@ -74,18 +78,18 @@ The fetch interceptor in `framework/core/interceptors/index.ts` calls `trackRequ
74
78
 
75
79
  ```vue
76
80
  <script setup lang="ts">
77
- import { watch } from 'vue';
78
- import { useSlowNetworkDetection } from '@vc-shell/framework';
81
+ import { watch } from "vue";
82
+ import { useSlowNetworkDetection } from "@vc-shell/framework";
79
83
 
80
84
  const { isSlowNetwork } = useSlowNetworkDetection();
81
85
 
82
86
  // Switch to a lightweight polling interval when the network is slow
83
- const pollInterval = computed(() => isSlowNetwork.value ? 30000 : 5000);
87
+ const pollInterval = computed(() => (isSlowNetwork.value ? 30000 : 5000));
84
88
 
85
89
  // Warn before navigating away during slow network + unsaved changes
86
90
  watch(isSlowNetwork, (slow) => {
87
91
  if (slow) {
88
- console.info('Network is slow — consider disabling auto-refresh');
92
+ console.info("Network is slow — consider disabling auto-refresh");
89
93
  }
90
94
  });
91
95
  </script>
@@ -96,7 +100,7 @@ watch(isSlowNetwork, (slow) => {
96
100
  If you bypass the standard fetch interceptor (e.g., direct `XMLHttpRequest` or third-party SDK), you can manually track the request:
97
101
 
98
102
  ```ts
99
- import { useSlowNetworkDetection } from '@vc-shell/framework';
103
+ import { useSlowNetworkDetection } from "@vc-shell/framework";
100
104
 
101
105
  const { trackRequest, untrackRequest } = useSlowNetworkDetection();
102
106
 
@@ -13,15 +13,15 @@ Manages color theme registration, switching, and persistence. Themes are applied
13
13
 
14
14
  ```vue
15
15
  <script setup lang="ts">
16
- import { useTheme } from '@vc-shell/framework';
16
+ import { useTheme } from "@vc-shell/framework";
17
17
 
18
18
  const { themes, currentThemeKey, currentLocalizedName, next, setTheme, register } = useTheme();
19
19
 
20
20
  // Register a dark theme from your module
21
- register({ key: 'dark', localizationKey: 'CORE.THEMES.DARK' });
21
+ register({ key: "dark", localizationKey: "CORE.THEMES.DARK" });
22
22
 
23
23
  // Switch to it explicitly
24
- setTheme('dark');
24
+ setTheme("dark");
25
25
 
26
26
  // Or cycle through all registered themes (light -> dark -> light -> ...)
27
27
  next();
@@ -39,28 +39,28 @@ next();
39
39
 
40
40
  ### Returns
41
41
 
42
- | Property | Type | Description |
43
- |---|---|---|
44
- | `themes` | `ComputedRef<DisplayTheme[]>` | All registered themes with their `key` and localized `name`. Reactive -- updates when themes are registered/unregistered. |
45
- | `currentThemeKey` | `Ref<string>` | Active theme key (e.g., `"light"`, `"dark"`). Two-way reactive -- setting it switches the theme. |
46
- | `currentLocalizedName` | `ComputedRef<string>` | Localized display name of the active theme (e.g., "Light", "Dark"). Falls back to capitalized key. |
47
- | `next` | `() => void` | Cycle to the next registered theme in order. Wraps around at the end. |
48
- | `setTheme` | `(themeKey: string) => void` | Switch to a specific registered theme. Logs a warning if the key is not registered. |
49
- | `register` | `(themes: ThemeDefinition \| ThemeDefinition[]) => void` | Add one or more themes to the global registry. Duplicates (by key) are silently ignored. |
50
- | `unregister` | `(keys: string \| string[]) => void` | Remove themes from the registry by key. |
42
+ | Property | Type | Description |
43
+ | ---------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
44
+ | `themes` | `ComputedRef<DisplayTheme[]>` | All registered themes with their `key` and localized `name`. Reactive -- updates when themes are registered/unregistered. |
45
+ | `currentThemeKey` | `Ref<string>` | Active theme key (e.g., `"light"`, `"dark"`). Two-way reactive -- setting it switches the theme. |
46
+ | `currentLocalizedName` | `ComputedRef<string>` | Localized display name of the active theme (e.g., "Light", "Dark"). Falls back to capitalized key. |
47
+ | `next` | `() => void` | Cycle to the next registered theme in order. Wraps around at the end. |
48
+ | `setTheme` | `(themeKey: string) => void` | Switch to a specific registered theme. Logs a warning if the key is not registered. |
49
+ | `register` | `(themes: ThemeDefinition \| ThemeDefinition[]) => void` | Add one or more themes to the global registry. Duplicates (by key) are silently ignored. |
50
+ | `unregister` | `(keys: string \| string[]) => void` | Remove themes from the registry by key. |
51
51
 
52
52
  ### ThemeDefinition
53
53
 
54
- | Field | Type | Required | Description |
55
- |---|---|---|---|
56
- | `key` | `string` | Yes | Unique theme identifier. Used as the `data-theme` attribute value on `<html>` and as the localStorage persistence key. |
57
- | `localizationKey` | `string` | No | i18n key for the display name (e.g., `"CORE.THEMES.DARK"`). Falls back to the capitalized `key` (e.g., `"Dark"`). |
54
+ | Field | Type | Required | Description |
55
+ | ----------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
56
+ | `key` | `string` | Yes | Unique theme identifier. Used as the `data-theme` attribute value on `<html>` and as the localStorage persistence key. |
57
+ | `localizationKey` | `string` | No | i18n key for the display name (e.g., `"CORE.THEMES.DARK"`). Falls back to the capitalized `key` (e.g., `"Dark"`). |
58
58
 
59
59
  ### DisplayTheme
60
60
 
61
- | Field | Type | Description |
62
- |---|---|---|
63
- | `key` | `string` | Theme identifier |
61
+ | Field | Type | Description |
62
+ | ------ | -------- | ---------------------------------------------------------------------------- |
63
+ | `key` | `string` | Theme identifier |
64
64
  | `name` | `string` | Localized display name, resolved from `localizationKey` or capitalized `key` |
65
65
 
66
66
  ## How It Works
@@ -77,16 +77,16 @@ next();
77
77
 
78
78
  ```typescript
79
79
  // my-module/index.ts
80
- import type { App } from 'vue';
81
- import { useTheme } from '@vc-shell/framework';
80
+ import type { App } from "vue";
81
+ import { useTheme } from "@vc-shell/framework";
82
82
 
83
83
  export default {
84
84
  install(app: App) {
85
85
  const { register } = useTheme();
86
86
 
87
87
  register([
88
- { key: 'ocean', localizationKey: 'MY_MODULE.THEMES.OCEAN' },
89
- { key: 'forest', localizationKey: 'MY_MODULE.THEMES.FOREST' },
88
+ { key: "ocean", localizationKey: "MY_MODULE.THEMES.OCEAN" },
89
+ { key: "forest", localizationKey: "MY_MODULE.THEMES.FOREST" },
90
90
  ]);
91
91
  },
92
92
  };
@@ -113,7 +113,7 @@ Then define your theme's CSS variables scoped by the `data-theme` attribute:
113
113
 
114
114
  ```vue
115
115
  <script setup lang="ts">
116
- import { useTheme } from '@vc-shell/framework';
116
+ import { useTheme } from "@vc-shell/framework";
117
117
 
118
118
  const { themes, currentThemeKey, setTheme } = useTheme();
119
119
  </script>
@@ -170,10 +170,7 @@ By default, all methods operate on the current blade. Pass an explicit `targetBl
170
170
 
171
171
  ```typescript
172
172
  // Register a button on a specific child blade
173
- registerToolbarItem(
174
- { id: "child-action", title: "Action", clickHandler: () => {} },
175
- "ChildBlade",
176
- );
173
+ registerToolbarItem({ id: "child-action", title: "Action", clickHandler: () => {} }, "ChildBlade");
177
174
 
178
175
  // Clear another blade's toolbar
179
176
  clearBladeToolbarItems("ChildBlade");
@@ -325,42 +322,42 @@ function helperFunction() {
325
322
 
326
323
  ### Parameters
327
324
 
328
- | Parameter | Type | Required | Default | Description |
329
- |-----------|------|----------|---------|-------------|
330
- | `options` | `UseToolbarOptions` | No | `{}` | Configuration options |
325
+ | Parameter | Type | Required | Default | Description |
326
+ | --------- | ------------------- | -------- | ------- | --------------------- |
327
+ | `options` | `UseToolbarOptions` | No | `{}` | Configuration options |
331
328
 
332
329
  #### UseToolbarOptions
333
330
 
334
- | Option | Type | Default | Description |
335
- |--------|------|---------|-------------|
336
- | `autoCleanup` | `boolean` | `true` | Clear all toolbar items for the current blade on component unmount |
331
+ | Option | Type | Default | Description |
332
+ | ------------- | --------- | ------- | ------------------------------------------------------------------ |
333
+ | `autoCleanup` | `boolean` | `true` | Clear all toolbar items for the current blade on component unmount |
337
334
 
338
335
  ### Returns: `UseToolbarReturn`
339
336
 
340
- | Property | Type | Description |
341
- |----------|------|-------------|
342
- | `registerToolbarItem` | `(item: IToolbarItem, targetBladeId?: string) => void` | Register a toolbar button (scoped to current blade by default) |
343
- | `unregisterToolbarItem` | `(id: string, targetBladeId?: string) => void` | Remove a toolbar button by ID |
344
- | `updateToolbarItem` | `(id: string, partial: Partial<IToolbarItem>, targetBladeId?: string) => void` | Update properties of an existing toolbar button |
345
- | `getToolbarItems` | `(targetBladeId?: string) => IToolbarItem[]` | Get all toolbar items for a blade |
346
- | `clearBladeToolbarItems` | `(targetBladeId?: string) => void` | Remove all toolbar items for a blade |
347
- | `isToolbarItemRegistered` | `(id: string) => boolean` | Check if a toolbar item with the given ID exists |
348
- | `registeredToolbarItems` | `IToolbarRegistration[]` | All registered toolbar items across all blades |
337
+ | Property | Type | Description |
338
+ | ------------------------- | ------------------------------------------------------------------------------ | -------------------------------------------------------------- |
339
+ | `registerToolbarItem` | `(item: IToolbarItem, targetBladeId?: string) => void` | Register a toolbar button (scoped to current blade by default) |
340
+ | `unregisterToolbarItem` | `(id: string, targetBladeId?: string) => void` | Remove a toolbar button by ID |
341
+ | `updateToolbarItem` | `(id: string, partial: Partial<IToolbarItem>, targetBladeId?: string) => void` | Update properties of an existing toolbar button |
342
+ | `getToolbarItems` | `(targetBladeId?: string) => IToolbarItem[]` | Get all toolbar items for a blade |
343
+ | `clearBladeToolbarItems` | `(targetBladeId?: string) => void` | Remove all toolbar items for a blade |
344
+ | `isToolbarItemRegistered` | `(id: string) => boolean` | Check if a toolbar item with the given ID exists |
345
+ | `registeredToolbarItems` | `IToolbarRegistration[]` | All registered toolbar items across all blades |
349
346
 
350
347
  ### IToolbarItem
351
348
 
352
- | Property | Type | Required | Description |
353
- |----------|------|----------|-------------|
354
- | `id` | `string` | Yes | Unique identifier for the button |
355
- | `title` | `string \| Ref<string> \| ComputedRef<string>` | No | Button label (supports reactive values) |
356
- | `icon` | `string \| (() => string)` | No | Icon class (e.g., `"fas fa-save"`) or a function returning one |
357
- | `clickHandler` | `(app?) => void` | No | Click callback |
358
- | `disabled` | `boolean \| ComputedRef<boolean>` | No | Whether the button is disabled |
359
- | `isVisible` | `boolean \| Ref<boolean> \| ComputedRef<boolean> \| ((blade?) => boolean)` | No | Controls button visibility |
360
- | `priority` | `number` | No | Sort order (higher = displayed first, default `0`) |
361
- | `separator` | `"left" \| "right" \| "both"` | No | Adds a visual divider next to the button |
362
- | `permissions` | `string \| string[]` | No | Required permission(s) to display the button |
363
- | `bladeId` | `string` | No | Target blade ID (auto-resolved from context) |
349
+ | Property | Type | Required | Description |
350
+ | -------------- | -------------------------------------------------------------------------- | -------- | -------------------------------------------------------------- |
351
+ | `id` | `string` | Yes | Unique identifier for the button |
352
+ | `title` | `string \| Ref<string> \| ComputedRef<string>` | No | Button label (supports reactive values) |
353
+ | `icon` | `string \| (() => string)` | No | Icon class (e.g., `"fas fa-save"`) or a function returning one |
354
+ | `clickHandler` | `(app?) => void` | No | Click callback |
355
+ | `disabled` | `boolean \| ComputedRef<boolean>` | No | Whether the button is disabled |
356
+ | `isVisible` | `boolean \| Ref<boolean> \| ComputedRef<boolean> \| ((blade?) => boolean)` | No | Controls button visibility |
357
+ | `priority` | `number` | No | Sort order (higher = displayed first, default `0`) |
358
+ | `separator` | `"left" \| "right" \| "both"` | No | Adds a visual divider next to the button |
359
+ | `permissions` | `string \| string[]` | No | Required permission(s) to display the button |
360
+ | `bladeId` | `string` | No | Target blade ID (auto-resolved from context) |
364
361
 
365
362
  ## Related
366
363
 
@@ -16,17 +16,26 @@ Uses `createSharedComposable` from VueUse, so all callers across the entire appl
16
16
 
17
17
  ```vue
18
18
  <script setup lang="ts">
19
- import { useUser } from '@vc-shell/framework';
19
+ import { useUser } from "@vc-shell/framework";
20
20
 
21
21
  const { user, isAuthenticated, isAdministrator, loading } = useUser();
22
22
  </script>
23
23
 
24
24
  <template>
25
- <div v-if="loading" class="tw-animate-pulse">Loading user...</div>
25
+ <div
26
+ v-if="loading"
27
+ class="tw-animate-pulse"
28
+ >
29
+ Loading user...
30
+ </div>
26
31
 
27
32
  <div v-else-if="isAuthenticated">
28
33
  <p>Welcome, {{ user?.userName }}</p>
29
- <span v-if="isAdministrator" class="tw-badge tw-badge-primary">Admin</span>
34
+ <span
35
+ v-if="isAdministrator"
36
+ class="tw-badge tw-badge-primary"
37
+ >Admin</span
38
+ >
30
39
  </div>
31
40
 
32
41
  <div v-else>
@@ -43,15 +52,15 @@ None.
43
52
 
44
53
  ### Returns
45
54
 
46
- | Property | Type | Description |
47
- |----------|------|-------------|
48
- | `user` | `ComputedRef<UserDetail \| undefined>` | Current user details (userName, email, id, etc.), or `undefined` if not authenticated. |
49
- | `loading` | `ComputedRef<boolean>` | Whether a user operation (loadUser, signOut) is in progress. |
50
- | `isAuthenticated` | `ComputedRef<boolean>` | Whether a user session is active. Derived from `user.userName != null`. |
51
- | `isAdministrator` | `ComputedRef<boolean \| undefined>` | Whether the current user has admin privileges. `undefined` if user is not loaded. |
52
- | `loadUser` | `() => Promise<UserDetail>` | Loads/reloads user info from the server. Deduplicates concurrent calls -- if two components call `loadUser()` at the same time, only one API request is made. |
53
- | `signOut` | `() => Promise<void>` | Signs out the current user, clears auth data from localStorage, and resets the user state. Handles both standard and external (SSO) sign-out flows. |
54
- | `getAccessToken` | `() => Promise<string \| null>` | Returns the current OAuth access token. Automatically refreshes using the refresh token if the access token has expired or will expire within 60 seconds. Returns `null` if no auth data exists. |
55
+ | Property | Type | Description |
56
+ | ----------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
57
+ | `user` | `ComputedRef<UserDetail \| undefined>` | Current user details (userName, email, id, etc.), or `undefined` if not authenticated. |
58
+ | `loading` | `ComputedRef<boolean>` | Whether a user operation (loadUser, signOut) is in progress. |
59
+ | `isAuthenticated` | `ComputedRef<boolean>` | Whether a user session is active. Derived from `user.userName != null`. |
60
+ | `isAdministrator` | `ComputedRef<boolean \| undefined>` | Whether the current user has admin privileges. `undefined` if user is not loaded. |
61
+ | `loadUser` | `() => Promise<UserDetail>` | Loads/reloads user info from the server. Deduplicates concurrent calls -- if two components call `loadUser()` at the same time, only one API request is made. |
62
+ | `signOut` | `() => Promise<void>` | Signs out the current user, clears auth data from localStorage, and resets the user state. Handles both standard and external (SSO) sign-out flows. |
63
+ | `getAccessToken` | `() => Promise<string \| null>` | Returns the current OAuth access token. Automatically refreshes using the refresh token if the access token has expired or will expire within 60 seconds. Returns `null` if no auth data exists. |
55
64
 
56
65
  ## How It Works
57
66
 
@@ -63,14 +72,16 @@ The composable delegates to `_createInternalUserLogic()`, which manages:
63
72
 
64
73
  3. **Token refresh**: `getAccessToken()` checks the expiration time with a 60-second buffer. If the token is expired or about to expire and a refresh token is available, it makes a `POST /connect/token` request with `grant_type: refresh_token`.
65
74
 
66
- 4. **Shared state**: `createSharedComposable` from VueUse ensures all calls to `useUser()` return the same reactive refs. The underlying `user` ref is module-level, so it persists across component lifecycles.
75
+ 4. **Shared state**: `createSharedComposable` from VueUse wraps `_createInternalUserLogic` so every call to `useUser()` or `useUserManagement()` reads from the same singleton internal logic. The `user` ref lives inside that singleton. App bootstrap registers `useUserManagement()` outside any component scope, which pins the singleton for the app lifetime — transient component mount/unmount cycles don't discard it.
67
76
 
68
77
  ## Recipe: Route Guard Based on Authentication
69
78
 
70
79
  ```typescript
71
- import { useUser } from '@vc-shell/framework';
80
+ import { useUser } from "@vc-shell/framework";
72
81
 
73
- const router = createRouter({ /* ... */ });
82
+ const router = createRouter({
83
+ /* ... */
84
+ });
74
85
 
75
86
  router.beforeEach(async (to) => {
76
87
  const { isAuthenticated, loadUser } = useUser();
@@ -85,7 +96,7 @@ router.beforeEach(async (to) => {
85
96
  }
86
97
 
87
98
  if (to.meta.requiresAuth && !isAuthenticated.value) {
88
- return { name: 'SignIn' };
99
+ return { name: "SignIn" };
89
100
  }
90
101
  });
91
102
  ```
@@ -95,25 +106,33 @@ router.beforeEach(async (to) => {
95
106
  ```vue
96
107
  <template>
97
108
  <div class="tw-flex tw-items-center tw-gap-2">
98
- <VcAvatar :name="user?.userName" size="sm" />
109
+ <VcAvatar
110
+ :name="user?.userName"
111
+ size="sm"
112
+ />
99
113
  <div>
100
114
  <p class="tw-text-sm tw-font-medium">{{ user?.userName }}</p>
101
115
  <p class="tw-text-xs tw-text-gray-500">{{ user?.email }}</p>
102
116
  </div>
103
- <VcButton size="sm" variant="ghost" @click="handleSignOut">Sign Out</VcButton>
117
+ <VcButton
118
+ size="sm"
119
+ variant="ghost"
120
+ @click="handleSignOut"
121
+ >Sign Out</VcButton
122
+ >
104
123
  </div>
105
124
  </template>
106
125
 
107
126
  <script setup lang="ts">
108
- import { useUser } from '@vc-shell/framework';
109
- import { useRouter } from 'vue-router';
127
+ import { useUser } from "@vc-shell/framework";
128
+ import { useRouter } from "vue-router";
110
129
 
111
130
  const { user, signOut } = useUser();
112
131
  const router = useRouter();
113
132
 
114
133
  async function handleSignOut() {
115
134
  await signOut();
116
- router.push({ name: 'SignIn' });
135
+ router.push({ name: "SignIn" });
117
136
  }
118
137
  </script>
119
138
  ```
@@ -121,7 +140,7 @@ async function handleSignOut() {
121
140
  ## Recipe: Adding Access Token to Custom API Calls
122
141
 
123
142
  ```typescript
124
- import { useUser } from '@vc-shell/framework';
143
+ import { useUser } from "@vc-shell/framework";
125
144
 
126
145
  const { getAccessToken } = useUser();
127
146
 
@@ -130,7 +149,7 @@ async function fetchCustomEndpoint(url: string) {
130
149
 
131
150
  const response = await fetch(url, {
132
151
  headers: {
133
- Authorization: token ? `Bearer ${token}` : '',
152
+ Authorization: token ? `Bearer ${token}` : "",
134
153
  },
135
154
  });
136
155
 
@@ -140,7 +159,7 @@ async function fetchCustomEndpoint(url: string) {
140
159
 
141
160
  ## Tips
142
161
 
143
- - **`loadUser` deduplicates concurrent calls.** If your app loads multiple blades simultaneously and each calls `loadUser()`, only one API request is made. All calls resolve with the same result.
162
+ - **`loadUser` deduplicates concurrent calls across composables.** If multiple blades call `loadUser()` simultaneously or if `useUser()` and `useUserManagement()` are both used in the same flow — only one API request is made. `useUser` and `useUserManagement` share the singleton internal logic, so request deduplication works across both.
144
163
  - **Token refresh is transparent.** `getAccessToken()` handles expiration checking and refresh internally. You never need to manually check token expiration or call a refresh endpoint.
145
164
  - **`isAuthenticated` checks `userName`, not the token.** A user is considered authenticated if `user.value?.userName` is not null. This means the user could have an expired token but still appear "authenticated" until the next API call fails.
146
165
  - **`signOut` clears localStorage.** After sign-out, the `vc_auth_data` key is removed from localStorage. Any cached tokens are gone permanently.