@vc-shell/vc-app-skill 2.1.0-pr255.87acc71 → 2.1.0-pr256.0fe3abb

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 (139) hide show
  1. package/package.json +1 -1
  2. package/runtime/knowledge/docs/core/api/platform.docs.md +20 -18
  3. package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +43 -34
  4. package/runtime/knowledge/docs/core/blade-navigation/table-query-state/useTableQueryState.docs.md +95 -0
  5. package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +5 -3
  6. package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +12 -10
  7. package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +7 -5
  8. package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +8 -6
  9. package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +3 -1
  10. package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +1 -1
  11. package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +8 -5
  12. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +12 -12
  13. package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +3 -3
  14. package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +4 -3
  15. package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -0
  16. package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +3 -3
  17. package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +5 -4
  18. package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +3 -3
  19. package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +2 -0
  20. package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +1 -2
  21. package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +1 -1
  22. package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +3 -3
  23. package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +35 -0
  24. package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +1 -1
  25. package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +2 -2
  26. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -1
  27. package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +18 -18
  28. package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +3 -3
  29. package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +10 -7
  30. package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +7 -7
  31. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +18 -12
  32. package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +2 -2
  33. package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +20 -20
  34. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +15 -24
  35. package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +2 -2
  36. package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +183 -0
  37. package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +117 -0
  38. package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md +150 -0
  39. package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +114 -0
  40. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +50 -30
  41. package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +30 -11
  42. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
  43. package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +2 -3
  44. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +26 -26
  45. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +2 -3
  46. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +11 -50
  47. package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +9 -6
  48. package/runtime/knowledge/docs/core/services/services.docs.md +15 -13
  49. package/runtime/knowledge/docs/core/types/types.docs.md +37 -40
  50. package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +1 -2
  51. package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +21 -30
  52. package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +2 -2
  53. package/runtime/knowledge/docs/core/utilities/utilities.docs.md +9 -8
  54. package/runtime/knowledge/docs/injection-keys.docs.md +6 -11
  55. package/runtime/knowledge/docs/modules/assets/assets-details.docs.md +123 -0
  56. package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +1 -1
  57. package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +20 -12
  58. package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +10 -10
  59. package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +6 -6
  60. package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +4 -4
  61. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +16 -14
  62. package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +1 -1
  63. package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +12 -11
  64. package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +10 -3
  65. package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +3 -3
  66. package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +9 -2
  67. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +4 -2
  68. package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
  69. package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +35 -31
  70. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -11
  71. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +8 -7
  72. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +23 -21
  73. package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +5 -3
  74. package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +7 -7
  75. package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +11 -11
  76. package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +28 -16
  77. package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +17 -19
  78. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/dashboard-widget-skeleton.docs.md +33 -0
  79. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +21 -0
  80. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +2 -1
  81. package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +2 -2
  82. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +15 -14
  83. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +9 -6
  84. package/runtime/knowledge/docs/ui/components/atoms/vc-environment-banner/vc-environment-banner.docs.md +42 -0
  85. package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +1 -1
  86. package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +10 -9
  87. package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +19 -4
  88. package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +2 -2
  89. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +5 -4
  90. package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +5 -4
  91. package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +9 -8
  92. package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +7 -0
  93. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +1 -1
  94. package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +2 -2
  95. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +1 -1
  96. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +11 -10
  97. package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +28 -8
  98. package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +22 -19
  99. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +8 -8
  100. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +16 -6
  101. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +9 -8
  102. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +42 -34
  103. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +1 -1
  104. package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +14 -1
  105. package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +3 -1
  106. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +34 -33
  107. package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +26 -24
  108. package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +12 -14
  109. package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +30 -30
  110. package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +2 -2
  111. package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +1 -1
  112. package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +34 -31
  113. package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +14 -12
  114. package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +1 -1
  115. package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +36 -27
  116. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +5 -1
  117. package/runtime/knowledge/docs/ui/components/molecules/{vc-dropdown-panel/vc-dropdown-panel.docs.md → vc-popover/vc-popover.docs.md} +26 -25
  118. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +10 -9
  119. package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +44 -19
  120. package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +11 -11
  121. package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +15 -14
  122. package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +15 -15
  123. package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +15 -13
  124. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +5 -1
  125. package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +18 -0
  126. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +48 -78
  127. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +9 -11
  128. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +71 -43
  129. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +27 -20
  130. package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +2 -2
  131. package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +12 -12
  132. package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +33 -24
  133. package/runtime/knowledge/docs/ui/components/organisms/vc-scheduler/vc-scheduler.docs.md +412 -0
  134. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +43 -26
  135. package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +15 -9
  136. package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +8 -6
  137. package/runtime/knowledge/docs/ui/composables/useTableSearch.docs.md +130 -0
  138. package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +4 -4
  139. package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +2 -3
@@ -2,6 +2,7 @@
2
2
  title: useConnectionStatus
3
3
  category: composables
4
4
  group: ui-state
5
+ internal: true
5
6
  ---
6
7
 
7
8
  # useConnectionStatus
@@ -18,7 +19,7 @@ Monitors the browser's network connectivity and shows a persistent notification
18
19
 
19
20
  ```vue
20
21
  <script setup lang="ts">
21
- import { useConnectionStatus } from "@vc-shell/framework";
22
+ import { useConnectionStatus } from "@core/composables/useConnectionStatus";
22
23
 
23
24
  const { isOnline } = useConnectionStatus();
24
25
  </script>
@@ -69,7 +70,7 @@ When connectivity is restored, the notification is removed, the CSS class is cle
69
70
 
70
71
  ```vue
71
72
  <script setup lang="ts">
72
- import { useConnectionStatus } from "@vc-shell/framework";
73
+ import { useConnectionStatus } from "@core/composables/useConnectionStatus";
73
74
  import { watch, ref } from "vue";
74
75
 
75
76
  const { isOnline } = useConnectionStatus();
@@ -125,4 +126,4 @@ html.vc-offline {
125
126
  ## Related
126
127
 
127
128
  - `@vueuse/core` `useNetwork` -- underlying browser API wrapper
128
- - `notification` from `@shared/components/notifications` -- the notification system used to display the offline warning
129
+ - `notification` from `@core/notifications/notification` -- the notification system used to display the offline warning
@@ -55,6 +55,7 @@ const { getPropertyValue, setPropertyValue, loadDictionaries, loadMeasurements,
55
55
  | `value` | `string \| IBasePropertyValue[] \| (IBasePropertyDictionaryItem & { value: string })[]` | The new value. Type depends on property configuration. |
56
56
  | `dictionary` | `IBasePropertyDictionaryItem[]?` | Dictionary items. Required when setting a dictionary value. |
57
57
  | `locale` | `string?` | Current locale for multilanguage properties. |
58
+ | `initialProp` | `IBaseProperty?` | Original property snapshot, used to reconcile prior values. |
58
59
  | `unitOfMeasureId` | `string?` | Unit of measure ID for measure-type properties. |
59
60
  | `colorCode` | `string?` | Color hex code for color-type properties. |
60
61
 
@@ -59,9 +59,9 @@ initOnce(); // still returns cached result
59
59
  ## How They Work
60
60
 
61
61
  - **debounce**: Uses `setTimeout` / `clearTimeout` internally. Each call clears the previous timeout and starts a new one. The function only fires when there is a pause of at least `delay` ms between calls.
62
- - **throttle**: Uses a `Date.now()` timestamp check. The first call fires immediately and records the timestamp. Subsequent calls are silently dropped until enough time has passed.
62
+ - **throttle**: Uses a `wasThrottled` boolean flag. The first call fires immediately and sets the flag; a `setTimeout` clears the flag after `delay` ms. Calls within that window are silently dropped.
63
63
  - **delay**: A simple wrapper around `setTimeout`. Useful for readability when you want to express "do X after Y ms" without creating a raw timeout.
64
- - **once**: Wraps the function with a boolean guard. After the first call, the result is cached and the original function reference is never called again.
64
+ - **once**: Caches the result in a module-level `WeakMap` keyed by the wrapped function. The first call invokes the function and stores its result; every later call returns the stored value via the map and never re-invokes.
65
65
 
66
66
  ## Recipe: Debounced Search in a Blade Toolbar
67
67
 
@@ -111,7 +111,7 @@ function onSearchInput(value: string) {
111
111
 
112
112
  - **No cancellation API.** Unlike `@vueuse/core`'s `useDebounceFn`, the `debounce` here does not return a cancel method. If you need to cancel a pending debounce on component unmount, use VueUse instead or manually clear the timeout.
113
113
  - **Throttle uses leading-edge firing.** The first call always executes immediately. If you need trailing-edge throttle (fire after the window closes), this implementation does not support it -- use lodash `throttle` with `{ trailing: true }` instead.
114
- - **`once` caches even `undefined` results.** If the wrapped function returns `undefined`, subsequent calls still skip execution and return `undefined`. The guard is based on "has it been called", not "did it return a truthy value".
114
+ - **`once` caches even `undefined` results.** If the wrapped function returns `undefined`, subsequent calls still skip execution and return `undefined`. Caching is based on the WeakMap having an entry for the function ("has it been called"), not on whether the result was truthy.
115
115
  - **`delay(fn, 0)` is not the same as `nextTick`.** `delay` uses `setTimeout(fn, 0)`, which defers to the next macrotask. Vue's `nextTick` defers to the next microtask, which fires sooner. Use `nextTick` for DOM update timing.
116
116
 
117
117
  ## Related
@@ -2,6 +2,7 @@
2
2
  title: useKeyboardNavigation
3
3
  category: composables
4
4
  group: ui-state
5
+ internal: true
5
6
  ---
6
7
 
7
8
  # useKeyboardNavigation
@@ -20,8 +21,8 @@ The composable supports two attachment modes: **auto-attach** on mount via a CSS
20
21
 
21
22
  ```vue
22
23
  <script setup lang="ts">
23
- import { useKeyboardNavigation } from "@vc-shell/framework";
24
- import { ref } from "vue";
24
+ import { useKeyboardNavigation } from "@core/composables/useKeyboardNavigation";
25
+ import { ref, nextTick } from "vue";
25
26
 
26
27
  const menuRef = ref<HTMLElement | null>(null);
27
28
  const items = ref(["Dashboard", "Products", "Orders", "Settings"]);
@@ -112,7 +113,7 @@ Auto-attach happens in `onMounted`: if `containerSelector` is set and a matching
112
113
 
113
114
  ```vue
114
115
  <script setup lang="ts">
115
- import { useKeyboardNavigation } from "@vc-shell/framework";
116
+ import { useKeyboardNavigation } from "@core/composables/useKeyboardNavigation";
116
117
  import { ref, watch, nextTick } from "vue";
117
118
 
118
119
  const dropdownRef = ref<HTMLElement | null>(null);
@@ -180,7 +181,7 @@ function selectSuggestion(value: string) {
180
181
  - **Items are re-queried on every key press.** This means dynamically added or removed items are picked up automatically. You do not need to re-initialize after the list changes.
181
182
  - **`loop: false` stops at boundaries.** When looping is disabled, pressing ArrowDown on the last item or ArrowUp on the first item does nothing. This is appropriate for linear navigation patterns.
182
183
  - **Clean up if you manually init.** While auto-attached listeners are cleaned up on `onBeforeUnmount`, if you call `initKeyboardNavigation` on a dynamic element, call `cleanupKeyboardNavigation` when that element is removed.
183
- - **Tab key is intercepted.** The composable handles Tab/Shift+Tab within the container, moving focus between items rather than leaving the container. This follows the WAI-ARIA composite widget pattern.
184
+ - **Tab moves the focused index but is not trapped.** Tab/Shift+Tab advances the composable's focused item, but it does not call `preventDefault`, so the browser's native Tab behavior still applies and focus can leave the container. This follows the WAI-ARIA composite widget pattern.
184
185
 
185
186
  ## Related
186
187
 
@@ -67,9 +67,9 @@ None.
67
67
  | `currentLocale` | `ComputedRef<string>` | The currently active locale code (e.g., `"en-US"`, `"de-DE"`). |
68
68
  | `setLocale` | `(locale: string) => void` | Switches the application locale. This updates `vue-i18n`'s locale and triggers re-rendering of all translated text. |
69
69
  | `getLocaleByTag` | `(localeTag: string) => string \| undefined` | Resolves a locale tag to its native display name. Regional tags stay distinct (e.g., `"en-US"` → `"American English"`, `"en-GB"` → `"British English"`); plain codes resolve to the base native name (`"fr"` → `"Français"`). Returns `undefined` if the tag is not recognized. |
70
- | `resolveCamelCaseLocale` | `(locale: string) => string` | Converts a locale code to camelCase format (e.g., `"en-US"` to `"enUs"`). Useful for dynamic property access on objects keyed by locale. |
70
+ | `resolveCamelCaseLocale` | `(locale: string) => string` | Normalizes and validates a locale code to a supported hyphenated lowercase locale (e.g., `"enUS"` to `"en-us"`), falling back to `"en"` if the locale is not supported. Delegates to `resolveSupportedLocale`. |
71
71
  | `getFlag` | `(language: string) => Promise<string>` | Fetches a flag image URL for the given language/locale. Returns a promise because flags may be loaded lazily. |
72
- | `getCountryCode` | `(language: string) => string` | Extracts the country code from a language tag (e.g., `"en-US"` to `"US"`, `"de-DE"` to `"DE"`). |
72
+ | `getCountryCode` | `(language: string) => string` | Extracts the lowercase country code from a language tag (e.g., `"en-US"` to `"us"`, `"de-DE"` to `"de"`). Falls back to `"xx"` for unknown languages. |
73
73
 
74
74
  ### Additional Exports
75
75
 
@@ -149,7 +149,7 @@ const displayValue = computed(() => getPropertyValue(property.value, currentLoca
149
149
  - **`setLocale` triggers a full re-render of translated text.** This is expected behavior from Vue I18n. If your app has many translated strings, the switch may cause a brief layout recalculation. There is no way to avoid this.
150
150
  - **`getFlag` is async.** Flag images may be loaded from a CDN or bundled as lazy imports. Always await the result before using it in templates.
151
151
  - **Fallback singleton is not reactive to injection changes.** If `provideLanguages()` is called after `useLanguages()` was already invoked outside an injection context, the fallback instance is not replaced. This is rarely an issue in practice since `provideLanguages()` runs before module installation.
152
- - **`resolveCamelCaseLocale` is useful for object property access.** Platform API responses sometimes key multilanguage data by camelCase locale (e.g., `{ enUs: "Hello", deDe: "Hallo" }`).
152
+ - **`resolveCamelCaseLocale` normalizes locale codes.** It returns a supported hyphenated lowercase locale (e.g., `"enUS"` -> `"en-us"`), or `"en"` when the locale is not supported. Despite the name, it does not produce camelCase output.
153
153
 
154
154
  ## Related
155
155
 
@@ -37,6 +37,8 @@ const combinedLoading = useLoading(loadingA, loadingB, loadingC);
37
37
  | ---------------------- | ------------------------------------------------------------------------------------------------------ |
38
38
  | `ComputedRef<boolean>` | `true` if any of the input refs is `true`, `false` otherwise. Re-evaluates whenever any input changes. |
39
39
 
40
+ The module also exports a shape-helper interface `HasLoading` (`{ loading: Readonly<Ref<boolean>> }`), for typing objects that expose a readonly `loading` ref. It is not part of `useLoading`'s call signature.
41
+
40
42
  <!-- internal:start -->
41
43
 
42
44
  ## How It Works
@@ -58,8 +58,7 @@ resetModificationState(); // currentValue becomes the new pristine baseline
58
58
  ```vue
59
59
  <script setup lang="ts">
60
60
  import { ref, watch } from "vue";
61
- import { useModificationTracker } from "@vc-shell/framework";
62
- import { useBeforeUnload } from "@vueuse/core";
61
+ import { useModificationTracker, useBeforeUnload } from "@vc-shell/framework";
63
62
 
64
63
  // Simulate API data loaded into a ref
65
64
  const apiData = ref({ name: "Widget A", price: 19.99, tags: ["sale"] });
@@ -78,7 +78,7 @@ For the canonical blade-side example and the registration of notification types
78
78
 
79
79
  4. **Module notifications**: The `moduleNotifications` computed filters the store's real-time queue for items that are new (`isNew: true`) and match the subscribed types.
80
80
 
81
- 5. **History**: `loadFromHistory` delegates to the store, which fetches from the platform API and merges into the local history.
81
+ 5. **History**: `loadFromHistory` delegates to `store.loadHistory`, which fetches a page from the platform API and replaces the local history with the result (`take` controls page size, default 10). It does not merge with or page onto existing entries.
82
82
 
83
83
  ## Recipe: Notification Panel with Real-Time Updates
84
84
 
@@ -130,13 +130,13 @@ Use `hasAccess` in a blade component to redirect users who lack the required per
130
130
 
131
131
  ```typescript
132
132
  <script setup lang="ts">
133
- import { usePermissions, useBladeContext } from "@vc-shell/framework";
133
+ import { usePermissions, useBlade } from "@vc-shell/framework";
134
134
 
135
135
  const { hasAccess } = usePermissions();
136
- const { closeSelf } = useBladeContext();
136
+ const { closeSelf } = useBlade();
137
137
 
138
138
  if (!hasAccess("order:read")) {
139
- closeSelf();
139
+ await closeSelf(); // returns Promise<boolean>
140
140
  return;
141
141
  }
142
142
  </script>
@@ -0,0 +1,35 @@
1
+ ---
2
+ title: usePlatformLocaleSync
3
+ category: composables
4
+ group: user
5
+ internal: true
6
+ ---
7
+
8
+ # usePlatformLocaleSync
9
+
10
+ One-way reactive bridge from the VirtoCommerce platform's locale storage key (`NG_TRANSLATE_LANG_KEY`, set by AngularJS + angular-translate) to the shell's language service.
11
+
12
+ Call this composable only when the shell runs embedded inside the platform — `useShellBootstrap` invokes it automatically when `options.isEmbedded === true`. In standalone mode the shell owns its own locale via `VC_LANGUAGE_SETTINGS`, and this composable should not be used.
13
+
14
+ ## When to Use
15
+
16
+ - Never call directly from feature code. This is a framework-internal sync primitive.
17
+ - It is invoked once per `VcApp` mount from `useShellBootstrap`.
18
+
19
+ ## Behaviour
20
+
21
+ - Reads `localStorage["NG_TRANSLATE_LANG_KEY"]` via VueUse's `useLocalStorage`, which subscribes to `storage` events for cross-tab reactivity.
22
+ - On setup, if the value is non-empty, calls `LanguageService.setLocale(value)`. `setLocale` normalises the value (e.g. `en-US` → `en-us`), falls back to `en` for unsupported locales, updates `vue-i18n`, reconfigures `vee-validate`, and persists to `VC_LANGUAGE_SETTINGS`.
23
+ - On subsequent changes of the platform key, re-applies the value.
24
+ - Skips empty strings (platform clearing the key does not blank the shell locale).
25
+ - Skips values equal to `currentLocale` to avoid redundant re-configuration.
26
+
27
+ ## How It Works
28
+
29
+ `useLocalStorage("NG_TRANSLATE_LANG_KEY", "")` returns a `Ref<string>` that VueUse keeps in sync with `localStorage` and the DOM `storage` event (which fires in tabs other than the writer). The composable applies the current ref value once synchronously and then registers a `watch` on it; any cross-tab mutation flows through the ref into `setLocale`.
30
+
31
+ The watcher is bound to the active effect scope (typically `VcApp`'s setup). When `VcApp` unmounts, the watcher stops; `useLocalStorage` cleans up its own `storage` listener.
32
+
33
+ ## Relationship to `VC_LANGUAGE_SETTINGS`
34
+
35
+ The sync is strictly one-directional. `setLocale` writes to `VC_LANGUAGE_SETTINGS` as a side effect, but this composable never writes to `NG_TRANSLATE_LANG_KEY`. In embedded mode the in-shell `LanguageSelector` is unreachable (it lives inside `UserDropdownButton`, which is hidden when `isEmbedded` is `true`), so there is no competing writer from the shell side.
@@ -62,7 +62,7 @@ async function deleteProduct(id: string) {
62
62
 
63
63
  | Field | Type | Required | Description |
64
64
  | ----------- | --------------------------------------------- | -------- | ------------------------------------------------------------------------- |
65
- | `component` | `ComponentPublicInstanceConstructor` | Yes | The popup component to render |
65
+ | `component` | `T` (`extends Component`) | Yes | The popup component to render |
66
66
  | `props` | `RawProps<T>` | No | Props to pass to the component (typed from the component's `defineProps`) |
67
67
  | `emits` | `RawEmits<T>` | No | Event handlers (typed from the component's `defineEmits`) |
68
68
  | `slots` | `Record<string, string \| Component \| Slot>` | No | Named slots — strings render as text, components render as VNodes |
@@ -50,12 +50,12 @@ None. The composable reads breakpoint state from the framework's provide/inject
50
50
  | Property | Type | Default | Description |
51
51
  | ----------- | -------------- | ------- | --------------------------------------------------------------------- |
52
52
  | `isMobile` | `Ref<boolean>` | `false` | `true` when viewport width < 1024px |
53
- | `isDesktop` | `Ref<boolean>` | `true` | `true` when viewport width >= 1024px |
53
+ | `isDesktop` | `Ref<boolean>` | `true` | `true` when viewport width > 1024px |
54
54
  | `isPhone` | `Ref<boolean>` | `false` | `true` when viewport width < 480px |
55
55
  | `isTablet` | `Ref<boolean>` | `false` | `true` when 480px <= viewport width < 1024px |
56
56
  | `isTouch` | `boolean` | `false` | `true` on touch-capable devices (not reactive — set once at app init) |
57
57
 
58
- Breakpoint thresholds: phone < 480px, tablet 480–1023px, desktop >= 1024px. These match the framework's `setupBreakpoints()` configuration.
58
+ Breakpoint thresholds: phone < 480px, tablet 480–1023px, desktop > 1024px (bound to `bp.greater("desktop")`, strictly greater than 1024px). These match the framework's `setupBreakpoints()` configuration.
59
59
 
60
60
  Note: `isMobile` is the union of `isPhone` and `isTablet` — it covers all viewports below the desktop threshold.
61
61
 
@@ -104,10 +104,11 @@ applySettings({
104
104
 
105
105
  ```vue
106
106
  <script setup lang="ts">
107
+ import { watch } from "vue";
107
108
  import { useSettings } from "@vc-shell/framework";
108
109
  import { useUserManagement } from "@vc-shell/framework";
109
110
 
110
- const { uiSettings } = useSettings();
111
+ const { uiSettings, applySettings } = useSettings();
111
112
  const { user } = useUserManagement();
112
113
 
113
114
  // Apply user-specific settings after login
@@ -41,6 +41,18 @@ const items = settingsMenu.items.value;
41
41
  | `unregister` | `(id: string) => void` | Remove a settings menu item by ID |
42
42
  | `items` | `ComputedRef<ISettingsMenuItem[]>` | Reactive array of all registered settings menu items |
43
43
 
44
+ ### RegisterSettingsMenuItemOptions
45
+
46
+ | Field | Type | Required | Description |
47
+ | ----------- | ------------------------- | -------- | ------------------------------------------------------------------------ |
48
+ | `id` | `string` | No | Item ID. If omitted, a UUID is generated and returned from `register()`. |
49
+ | `order` | `number` | No | Sort order. Defaults to the current registry size (appended at the end). |
50
+ | `group` | `string` | No | Group key used to cluster related items. |
51
+ | `component` | `Component` | Yes | Component rendered for this item. Wrapped in `markRaw()` internally. |
52
+ | `props` | `Record<string, unknown>` | No | Props passed to the component. |
53
+
54
+ There is no `title` or `icon` field; the registered component is responsible for rendering its own label and icon.
55
+
44
56
  ### Related Exports
45
57
 
46
58
  | Export | Description |
@@ -58,11 +70,9 @@ const settingsMenu = useSettingsMenu();
58
70
 
59
71
  const itemId = settingsMenu.register({
60
72
  id: "notification-preferences",
61
- title: "Notifications",
62
- icon: "fas fa-bell",
63
73
  component: NotificationSettingsPage,
64
74
  group: "General",
65
- priority: 10,
75
+ order: 10,
66
76
  });
67
77
  ```
68
78
 
@@ -77,29 +87,23 @@ const settingsMenu = useSettingsMenu();
77
87
  // Group related settings under a common section
78
88
  settingsMenu.register({
79
89
  id: "catalog-general",
80
- title: "General",
81
- icon: "lucide-settings",
82
90
  component: markRaw(CatalogGeneralSettings),
83
91
  group: "Catalog",
84
- priority: 1,
92
+ order: 1,
85
93
  });
86
94
 
87
95
  settingsMenu.register({
88
96
  id: "catalog-seo",
89
- title: "SEO Settings",
90
- icon: "lucide-search",
91
97
  component: markRaw(CatalogSeoSettings),
92
98
  group: "Catalog",
93
- priority: 2,
99
+ order: 2,
94
100
  });
95
101
 
96
102
  settingsMenu.register({
97
103
  id: "catalog-import-export",
98
- title: "Import / Export",
99
- icon: "lucide-arrow-left-right",
100
104
  component: markRaw(CatalogImportExportSettings),
101
105
  group: "Catalog",
102
- priority: 3,
106
+ order: 3,
103
107
  });
104
108
  ```
105
109
 
@@ -112,11 +116,9 @@ import { onBeforeUnmount } from "vue";
112
116
  const settingsMenu = useSettingsMenu();
113
117
  const itemId = settingsMenu.register({
114
118
  id: "my-settings",
115
- title: "My Module Settings",
116
- icon: "lucide-wrench",
117
119
  component: markRaw(MySettingsPage),
118
120
  group: "Modules",
119
- priority: 10,
121
+ order: 10,
120
122
  });
121
123
 
122
124
  onBeforeUnmount(() => {
@@ -136,11 +138,9 @@ const { hasAccess } = usePermissions();
136
138
  if (hasAccess("catalog:manage")) {
137
139
  settingsMenu.register({
138
140
  id: "catalog-advanced",
139
- title: "Advanced Catalog Settings",
140
- icon: "lucide-settings-2",
141
141
  component: markRaw(AdvancedCatalogSettings),
142
142
  group: "Catalog",
143
- priority: 99,
143
+ order: 99,
144
144
  });
145
145
  }
146
146
  ```
@@ -87,10 +87,10 @@ provideSidebarState();
87
87
  ```vue
88
88
  <script setup lang="ts">
89
89
  import { useSidebarState } from "@vc-shell/framework";
90
- import { useBladeContext } from "@vc-shell/framework";
90
+ import { useBlade } from "@vc-shell/framework";
91
91
 
92
92
  const { closeMenu, isMenuOpen } = useSidebarState();
93
- const { openBlade } = useBladeContext();
93
+ const { openBlade } = useBlade();
94
94
 
95
95
  async function navigateToProducts() {
96
96
  // Close the mobile menu first so it does not overlay the new blade
@@ -99,7 +99,7 @@ async function navigateToProducts() {
99
99
  }
100
100
 
101
101
  await openBlade({
102
- component: ProductListBlade,
102
+ name: "ProductList",
103
103
  param: { catalogId: "default" },
104
104
  });
105
105
  }
@@ -2,6 +2,7 @@
2
2
  title: useSlowNetworkDetection
3
3
  category: composables
4
4
  group: ui-state
5
+ internal: true
5
6
  ---
6
7
 
7
8
  # useSlowNetworkDetection
@@ -23,7 +24,7 @@ The composable is initialized automatically at app startup. To reactively read t
23
24
 
24
25
  ```vue
25
26
  <script setup lang="ts">
26
- import { useSlowNetworkDetection } from "@vc-shell/framework";
27
+ import { useSlowNetworkDetection } from "@core/composables/useSlowNetworkDetection";
27
28
 
28
29
  const { isSlowNetwork } = useSlowNetworkDetection();
29
30
  </script>
@@ -54,7 +55,11 @@ const { isSlowNetwork } = useSlowNetworkDetection();
54
55
  | `trackRequest` | `(id: string) => void` | Start tracking a request. If it isn't untracked within 10 s, it counts as slow. |
55
56
  | `untrackRequest` | `(id: string) => void` | Stop tracking a request. Cancels the timer or decrements the slow count. |
56
57
 
57
- ### Constants
58
+ <!-- internal:start -->
59
+
60
+ ### Internal Constants
61
+
62
+ These are module-private `const` declarations, not exported symbols — do not `import` them. They document the thresholds baked into the composable.
58
63
 
59
64
  | Name | Value | Purpose |
60
65
  | --------------------------- | ------------------- | --------------------------------------------------- |
@@ -62,8 +67,6 @@ const { isSlowNetwork } = useSlowNetworkDetection();
62
67
  | `DISMISS_DELAY_MS` | `3000` | Delay before hiding the notification after recovery |
63
68
  | `SLOW_EFFECTIVE_TYPES` | `["slow-2g", "2g"]` | Connection types flagged as slow |
64
69
 
65
- <!-- internal:start -->
66
-
67
70
  ## How It Works
68
71
 
69
72
  ### Channel 1: effectiveType (proactive)
@@ -88,7 +91,7 @@ The fetch interceptor in `framework/core/interceptors/index.ts` calls `trackRequ
88
91
  ```vue
89
92
  <script setup lang="ts">
90
93
  import { watch } from "vue";
91
- import { useSlowNetworkDetection } from "@vc-shell/framework";
94
+ import { useSlowNetworkDetection } from "@core/composables/useSlowNetworkDetection";
92
95
 
93
96
  const { isSlowNetwork } = useSlowNetworkDetection();
94
97
 
@@ -109,7 +112,7 @@ watch(isSlowNetwork, (slow) => {
109
112
  If you bypass the standard fetch interceptor (e.g., direct `XMLHttpRequest` or third-party SDK), you can manually track the request:
110
113
 
111
114
  ```ts
112
- import { useSlowNetworkDetection } from "@vc-shell/framework";
115
+ import { useSlowNetworkDetection } from "@core/composables/useSlowNetworkDetection";
113
116
 
114
117
  const { trackRequest, untrackRequest } = useSlowNetworkDetection();
115
118
 
@@ -168,4 +171,4 @@ trackRequest("my-request-2");
168
171
 
169
172
  - [`useConnectionStatus`](../useConnectionStatus/useConnectionStatus.docs.md) — offline detection (binary online/offline)
170
173
  - [`registerInterceptors`](https://github.com/VirtoCommerce/vc-shell/blob/main/framework/core/interceptors/index.ts) — the fetch wrapper that calls `trackRequest`/`untrackRequest`
171
- - `notification` from `@shared/components/notifications` — the notification system used to display the warning
174
+ - `notification` from `@core/notifications/notification` — the notification system used to display the warning
@@ -6,7 +6,7 @@ group: ui-state
6
6
 
7
7
  # useTheme
8
8
 
9
- Manages color theme registration, switching, and persistence. Themes are applied via a `data-theme` attribute on `<html>`, and the active theme key is persisted to localStorage via `@vueuse/core`'s `useColorMode`. The composable maintains a global registry of theme definitions, supports runtime registration/unregistration from modules, and provides both explicit (`setTheme`) and sequential (`next`) theme switching. A default `"light"` theme is always registered out of the box.
9
+ Manages color theme registration, switching, and persistence. Themes are applied via a `data-theme` attribute on `<html>`, and the active theme key is persisted to localStorage via `@vueuse/core`'s `useColorMode`. The composable maintains a global registry of theme definitions, supports runtime registration/unregistration from modules, and provides both explicit (`setTheme`) and sequential (`next`) theme switching. Both `"light"` and `"dark"` themes are registered out of the box.
10
10
 
11
11
  ## When to Use
12
12
 
@@ -23,13 +23,13 @@ import { useTheme } from "@vc-shell/framework";
23
23
 
24
24
  const { themes, currentThemeKey, currentLocalizedName, next, setTheme, register } = useTheme();
25
25
 
26
- // Register a dark theme from your module
27
- register({ key: "dark", localizationKey: "CORE.THEMES.DARK" });
26
+ // light and dark are registered by default; register a custom theme from your module
27
+ register({ key: "ocean", localizationKey: "MY_MODULE.THEMES.OCEAN" });
28
28
 
29
29
  // Switch to it explicitly
30
- setTheme("dark");
30
+ setTheme("ocean");
31
31
 
32
- // Or cycle through all registered themes (light -> dark -> light -> ...)
32
+ // Or cycle through all registered themes (light -> dark -> ocean -> light -> ...)
33
33
  next();
34
34
  </script>
35
35
 
@@ -47,9 +47,9 @@ next();
47
47
 
48
48
  | Property | Type | Description |
49
49
  | ---------------------- | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
50
- | `themes` | `ComputedRef<DisplayTheme[]>` | All registered themes with their `key` and localized `name`. Reactive -- updates when themes are registered/unregistered. |
50
+ | `themes` | `Ref<DisplayTheme[]>` | All registered themes with their `key` and localized `name`. Reactive -- updates when themes are registered/unregistered. |
51
51
  | `currentThemeKey` | `Ref<string>` | Active theme key (e.g., `"light"`, `"dark"`). Two-way reactive -- setting it switches the theme. |
52
- | `currentLocalizedName` | `ComputedRef<string>` | Localized display name of the active theme (e.g., "Light", "Dark"). Falls back to capitalized key. |
52
+ | `currentLocalizedName` | `Ref<string>` | Localized display name of the active theme (e.g., "Light", "Dark"). Falls back to capitalized key. |
53
53
  | `next` | `() => void` | Cycle to the next registered theme in order. Wraps around at the end. |
54
54
  | `setTheme` | `(themeKey: string) => void` | Switch to a specific registered theme. Logs a warning if the key is not registered. |
55
55
  | `register` | `(themes: ThemeDefinition \| ThemeDefinition[]) => void` | Add one or more themes to the global registry. Duplicates (by key) are silently ignored. |
@@ -326,20 +326,26 @@ function helperFunction() {
326
326
  | `isToolbarItemRegistered` | `(id: string) => boolean` | Check if a toolbar item with the given ID exists |
327
327
  | `registeredToolbarItems` | `IToolbarRegistration[]` | All registered toolbar items across all blades |
328
328
 
329
+ ### Additional Exports
330
+
331
+ | Export | Description |
332
+ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
333
+ | `provideToolbarService()` | Creates and provides the toolbar service via Vue injection. Idempotent -- returns existing service if already provided. Cleans up via `onScopeDispose`. |
334
+
329
335
  ### IToolbarItem
330
336
 
331
- | Property | Type | Required | Description |
332
- | -------------- | -------------------------------------------------------------------------- | -------- | -------------------------------------------------------------- |
333
- | `id` | `string` | Yes | Unique identifier for the button |
334
- | `title` | `string \| Ref<string> \| ComputedRef<string>` | No | Button label (supports reactive values) |
335
- | `icon` | `string \| (() => string)` | No | Icon class (e.g., `"fas fa-save"`) or a function returning one |
336
- | `clickHandler` | `(app?) => void` | No | Click callback |
337
- | `disabled` | `boolean \| ComputedRef<boolean>` | No | Whether the button is disabled |
338
- | `isVisible` | `boolean \| Ref<boolean> \| ComputedRef<boolean> \| ((blade?) => boolean)` | No | Controls button visibility |
339
- | `priority` | `number` | No | Sort order (higher = displayed first, default `0`) |
340
- | `separator` | `"left" \| "right" \| "both"` | No | Adds a visual divider next to the button |
341
- | `permissions` | `string \| string[]` | No | Required permission(s) to display the button |
342
- | `bladeId` | `string` | No | Target blade ID (auto-resolved from context) |
337
+ | Property | Type | Required | Description |
338
+ | -------------- | ----------------------------------------------------------------------------------------------------------------- | -------- | -------------------------------------------------------------- |
339
+ | `id` | `string` | Yes | Unique identifier for the button |
340
+ | `title` | `string \| Ref<string> \| ComputedRef<string>` | No | Button label (supports reactive values) |
341
+ | `icon` | `string \| (() => string)` | No | Icon class (e.g., `"fas fa-save"`) or a function returning one |
342
+ | `clickHandler` | `(app?) => void` | No | Click callback |
343
+ | `disabled` | `boolean \| ComputedRef<boolean \| undefined>` | No | Whether the button is disabled |
344
+ | `isVisible` | `boolean \| Ref<boolean \| undefined> \| ComputedRef<boolean \| undefined> \| ((blade?) => boolean \| undefined)` | No | Controls button visibility |
345
+ | `priority` | `number` | No | Sort order (higher = displayed first, default `0`) |
346
+ | `separator` | `"left" \| "right" \| "both"` | No | Adds a visual divider next to the button |
347
+ | `permissions` | `string \| string[]` | No | Required permission(s) to display the button |
348
+ | `bladeId` | `string` | No | Target blade ID (auto-resolved from context) |
343
349
 
344
350
  `IToolbarItem` is the shape consumed by `ToolbarService`. The blade-level array binding uses `IBladeToolbar` (see [Core types](../../types/)), a near-identical shape that the framework normalizes into `IToolbarItem` before render.
345
351
 
@@ -60,7 +60,7 @@ None.
60
60
 
61
61
  | Property | Type | Description |
62
62
  | ----------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
63
- | `user` | `ComputedRef<UserDetail \| undefined>` | Current user details (userName, email, id, etc.), or `undefined` if not authenticated. |
63
+ | `user` | `ComputedRef<UserDetail \| undefined>` | Current user details (userName, id, permissions, isAdministrator, etc.), or `undefined` if not authenticated. |
64
64
  | `loading` | `ComputedRef<boolean>` | Whether a user operation (loadUser, signOut) is in progress. |
65
65
  | `isAuthenticated` | `ComputedRef<boolean>` | Whether a user session is active. Derived from `user.userName != null`. |
66
66
  | `isAdministrator` | `ComputedRef<boolean \| undefined>` | Whether the current user has admin privileges. `undefined` if user is not loaded. |
@@ -118,7 +118,7 @@ router.beforeEach(async (to) => {
118
118
  />
119
119
  <div>
120
120
  <p class="tw-text-sm tw-font-medium">{{ user?.userName }}</p>
121
- <p class="tw-text-xs tw-text-gray-500">{{ user?.email }}</p>
121
+ <p class="tw-text-xs tw-text-gray-500">{{ user?.id }}</p>
122
122
  </div>
123
123
  <VcButton
124
124
  size="sm"