@vc-shell/vc-app-skill 2.0.5 → 2.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +7 -7
  3. package/package.json +1 -1
  4. package/runtime/VERSION +1 -1
  5. package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
  6. package/runtime/knowledge/docs/core/api/platform.docs.md +6 -6
  7. package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +1 -1
  8. package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +2 -2
  9. package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +67 -42
  10. package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +2 -2
  11. package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +15 -13
  12. package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +11 -11
  13. package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +17 -14
  14. package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +4 -2
  15. package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +31 -23
  16. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +46 -26
  17. package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +1 -0
  18. package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +1 -1
  19. package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +1 -1
  20. package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +1 -0
  21. package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +20 -6
  22. package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +2 -1
  23. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +2 -2
  24. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +109 -133
  25. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +1 -2
  26. package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +184 -0
  27. package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +117 -0
  28. package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md +150 -0
  29. package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +113 -0
  30. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +12 -15
  31. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +1 -1
  32. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +54 -116
  33. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +12 -3
  34. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +20 -20
  35. package/runtime/knowledge/docs/injection-keys.docs.md +1 -1
  36. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +1 -1
  37. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
  38. package/runtime/knowledge/docs/shell/components/notification-dropdown/notification-dropdown.docs.md +1 -1
  39. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +1 -1
  40. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +7 -7
  41. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +2 -2
  42. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +1 -1
  43. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +4 -4
  44. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +1 -1
  45. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +21 -1
  46. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +22 -6
  47. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +2 -2
  48. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +32 -26
  49. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +3 -3
  50. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +1 -1
  51. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +1 -1
  52. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +1 -1
  53. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +13 -13
  54. package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +1 -1
  55. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +1 -1
  56. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +4 -4
  57. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +39 -37
  58. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +17 -17
  59. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +16 -7
  60. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +1 -1
@@ -37,8 +37,8 @@ If you are building anything in vc-shell -- a new page, a CRUD flow, a dashboard
37
37
  - [Registering Notification Types](#registering-notification-types)
38
38
  - [Adding Locales](#adding-locales)
39
39
  - [Registering Dashboard Widgets](#registering-dashboard-widgets)
40
- - [Module Version Compatibility](#module-version-compatibility)
41
- - [Remote Modules (Module Federation)](#remote-modules-module-federation)
40
+ - [Plugin Compatibility](#plugin-compatibility)
41
+ - [Plugin Loading (Module Federation)](#plugin-loading-module-federation)
42
42
  - [Recipes](#recipes)
43
43
  - [Minimal Module (Blades Only)](#minimal-module-blades-only)
44
44
  - [Module with CRUD Blades (List + Details)](#module-with-crud-blades-list--details)
@@ -69,24 +69,15 @@ export default defineAppModule({
69
69
  ```vue
70
70
  <!-- modules/my-feature/pages/MyFeatureList.vue -->
71
71
  <template>
72
- <VcBlade
73
- title="My Feature"
74
- :closable="closable"
75
- @close="$emit('close:blade')"
76
- >
72
+ <VcBlade title="My Feature">
77
73
  <p>Hello from my first module!</p>
78
74
  </VcBlade>
79
75
  </template>
80
76
 
81
77
  <script setup lang="ts">
82
- import { VcBlade } from "@vc-shell/framework";
78
+ import { VcBlade } from "@vc-shell/framework/ui";
83
79
 
84
- defineProps<{ closable?: boolean }>();
85
- defineEmits(["close:blade"]);
86
- </script>
87
-
88
- <script lang="ts">
89
- defineOptions({
80
+ defineBlade({
90
81
  name: "MyFeatureList",
91
82
  url: "/my-feature",
92
83
  isWorkspace: true,
@@ -99,6 +90,8 @@ defineOptions({
99
90
  </script>
100
91
  ```
101
92
 
93
+ `VcBlade` reads `expanded` and `closable` directly from the blade descriptor and emits its own close action — blade pages no longer declare those as props or wire up `@close` / `@expand` / `@collapse` emits.
94
+
102
95
  ```json
103
96
  // modules/my-feature/locales/en.json
104
97
  {
@@ -153,31 +146,12 @@ my-feature-module/
153
146
 
154
147
  When the host application calls `app.use(module)`, the `install()` function runs the following steps **synchronously and in order**:
155
148
 
156
- ```
157
- app.use(module)
158
- |
159
- v
160
- 1. BLADE REGISTRATION
161
- For each entry in `blades`:
162
- - Register in BladeRegistry (name, component, route, permissions)
163
- - If blade has `url` + `menuItem` --> register sidebar menu entry
164
- |
165
- v
166
- 2. NOTIFICATION REGISTRATION (new API)
167
- For each entry in `notifications`:
168
- - Register type + config in NotificationStore
169
- |
170
- v
171
- 3. LEGACY NOTIFICATION COMPAT (deprecated)
172
- If `notifications` is NOT provided but `notificationTemplates` is:
173
- - Register templates with notifyType in NotificationStore
174
- If any blade has `notifyType`:
175
- - Create automatic toast subscription (with deprecation warning)
176
- |
177
- v
178
- 4. LOCALE MERGE
179
- For each entry in `locales`:
180
- - mergeLocaleMessage(langCode, messages) into vue-i18n
149
+ ```mermaid
150
+ flowchart TD
151
+ Entry["app.use(module)"] --> S1["1. BLADE REGISTRATION<br/>For each entry in <code>blades</code>:<br/>• Register in BladeRegistry (name, component, route, permissions)<br/>• If blade has <code>url</code> + <code>menuItem</code> → register sidebar menu entry"]
152
+ S1 --> S2["2. NOTIFICATION REGISTRATION<br/>For each entry in <code>notifications</code>:<br/>• Register type + config in NotificationStore"]
153
+ S2 --> S3["3. LEGACY NOTIFICATION COMPAT (deprecated)<br/>If <code>notifications</code> is NOT provided but <code>notificationTemplates</code> is:<br/>• Register templates with notifyType<br/>If any blade has <code>notifyType</code>:<br/>• Create automatic toast subscription (with deprecation warning)"]
154
+ S3 --> S4["4. LOCALE MERGE<br/>For each entry in <code>locales</code>:<br/>• mergeLocaleMessage(langCode, messages) into vue-i18n"]
181
155
  ```
182
156
 
183
157
  > **Why this order matters:** Blades must be registered before anything references them (e.g., menu items link to blade routes). Notifications are independent. Locales come last because they are purely additive.
@@ -274,15 +248,15 @@ Each blade is registered in the `BladeRegistry` with:
274
248
  | `routable` | `component.routable` | `true` = gets a Vue Router route (default: `true`) |
275
249
  | `permissions` | `component.permissions` | Required permissions to access the blade |
276
250
 
277
- > **Tip:** The export key (e.g., `ProductsList` in `{ ProductsList }`) is used as a fallback name when `component.name` is not defined. Always set `defineOptions({ name: "..." })` for clarity.
251
+ > **Tip:** The export key (e.g., `ProductsList` in `{ ProductsList }`) is used as a fallback name when `defineBlade` does not set a name. Always set `defineBlade({ name: "..." })` explicitly.
278
252
 
279
253
  ### Blade Static Properties
280
254
 
281
- Blades declare their routing, permissions, and menu behavior through **static properties** set via `defineOptions`:
255
+ Blades declare their routing, permissions, and menu behavior through `defineBlade`:
282
256
 
283
257
  ```vue
284
- <script lang="ts">
285
- defineOptions({
258
+ <script setup lang="ts">
259
+ defineBlade({
286
260
  // REQUIRED: Unique name for the blade (used in BladeRegistry)
287
261
  name: "OrdersList",
288
262
 
@@ -310,13 +284,13 @@ defineOptions({
310
284
  </script>
311
285
  ```
312
286
 
313
- > **Note:** `defineOptions` is a Vue 3.3+ compiler macro. Static properties like `url`, `isWorkspace`, and `menuItem` are vc-shell conventions -- they are read by `defineAppModule` during the install phase, not by Vue itself.
287
+ > **Note:** `defineBlade` is compiled by the VC-Shell Vite plugin. It emits Vue component options and registers blade metadata before module installation.
314
288
 
315
289
  **Child blades** (detail pages opened from a list) typically do NOT need `url`, `isWorkspace`, or `menuItem`:
316
290
 
317
291
  ```vue
318
- <script lang="ts">
319
- defineOptions({
292
+ <script setup lang="ts">
293
+ defineBlade({
320
294
  name: "OrderDetails",
321
295
  // No url, no menuItem -- this blade is opened programmatically via openBlade()
322
296
  });
@@ -328,8 +302,8 @@ defineOptions({
328
302
  Menu items are created **automatically** when a blade has both `url` and `menuItem` static properties. You do not call any menu API yourself.
329
303
 
330
304
  ```vue
331
- <script lang="ts">
332
- defineOptions({
305
+ <script setup lang="ts">
306
+ defineBlade({
333
307
  name: "ProductsList",
334
308
  url: "/products",
335
309
  isWorkspace: true,
@@ -509,64 +483,31 @@ export default defineAppModule({ blades: pages, locales });
509
483
  | `permissions` | `string[]` | Required permissions (optional) |
510
484
  | `props` | `Record<string, unknown>` | Props passed to the component (optional) |
511
485
 
512
- ### Module Version Compatibility
513
-
514
- Remote modules loaded via Module Federation can declare framework compatibility using semver ranges. The host checks these ranges at load time and skips incompatible modules:
515
-
516
- ```json
517
- // Remote module's manifest (served by the backend)
518
- {
519
- "id": "my-remote-module",
520
- "entry": "https://cdn.example.com/my-module/remoteEntry.js",
521
- "version": "1.2.0",
522
- "compatibleWith": {
523
- "dependencies": {
524
- "@vc-shell/framework": ">=2.0.0 <3.0.0"
525
- }
526
- }
527
- }
528
- ```
529
-
530
- At startup, the host:
486
+ ### Plugin Compatibility
531
487
 
532
- 1. Reads the current `@vc-shell/framework` version from `package.json`
533
- 2. Checks each remote module's `compatibleWith.dependencies["@vc-shell/framework"]` range
534
- 3. Skips modules that fail the semver check (with a console warning)
535
- 4. Loads and installs compatible modules
488
+ Plugin compatibility is settled on the Platform side, not in the browser. The Platform validates each plugin's `<dependency>` declarations in **module.manifest** at .NET module install time and refuses incompatible installs. By the time a plugin appears in the manifest endpoint, the dependency graph has already approved it — there is no client-side semver filter.
536
489
 
537
- This ensures that a framework major version upgrade does not break deployed remote modules.
490
+ Upgrading the host's framework does not silently drop older plugins; if a plugin becomes incompatible, the Platform admin sees an install-time error first.
538
491
 
539
- ### Remote Modules (Module Federation)
492
+ ### Plugin Loading (Module Federation)
540
493
 
541
- vc-shell supports loading modules from remote servers at runtime using Module Federation. This is the primary deployment model for production applications where modules are developed and deployed independently.
494
+ vc-shell loads plugin extensions at runtime via Module Federation. A plugin remote is built by a .NET module's Vue subpackage and discovered by the Platform from the dependency graph. The host fetches a manifest of plugins for its `appId` at boot and installs each as a Vue plugin.
542
495
 
543
496
  The loading sequence:
544
497
 
498
+ ```mermaid
499
+ flowchart TD
500
+ A["App Start (host main.ts)"] --> N1["1. Fetch plugin manifest<br/>GET /api/apps/{appId}/manifest"]
501
+ N1 --> N2["2. Initialize MF runtime<br/>with shared deps from @vc-shell/mf-config"]
502
+ N2 --> N3["3. Load each plugin's remoteEntry.js<br/>(Promise.allSettled in parallel)"]
503
+ N3 --> N4["4. Resolve Vue plugins from each remote's default export"]
504
+ N4 --> N5["5. app.use(plugin, { router }) for each<br/>→ triggers defineAppModule's install()"]
505
+ N5 --> N6["6. provide(ModulesReadyKey, true)<br/>→ app.mount('#app')"]
545
506
  ```
546
- App Start
547
- |
548
- v
549
- 1. Fetch module registry from /api/frontend-modules
550
- |
551
- v
552
- 2. Filter by framework version compatibility (semver check)
553
- |
554
- v
555
- 3. Initialize Module Federation runtime with shared deps
556
- (vue, vue-router, vue-i18n, @vc-shell/framework, etc.)
557
- |
558
- v
559
- 4. Load all compatible remote modules in parallel
560
- |
561
- v
562
- 5. Resolve Vue plugins from each module's exports
563
- |
564
- v
565
- 6. app.use(plugin) for each module --> triggers defineAppModule's install()
566
- |
567
- v
568
- 7. Set modulesReady = true --> app renders
569
- ```
507
+
508
+ Non-OK manifest responses (401 / 403 / 404 / 5xx) are treated as "no plugins" — the host logs a `console.warn`, sets `modulesReady=true`, and mounts without extensions. Only network or parse failures set `modulesLoadError=true`.
509
+
510
+ See the [Module Federation guide](../guides/module-federation/index.md) for the full plugin-author + host-app walkthrough.
570
511
 
571
512
  The host shares singleton instances of core dependencies (Vue, Vue Router, vue-i18n, @vc-shell/framework) so that remote modules use the same runtime. This is critical for reactivity, routing, and DI to work across module boundaries.
572
513
 
@@ -626,8 +567,12 @@ The list blade (workspace):
626
567
 
627
568
  ```vue
628
569
  <!-- pages/ProductsList.vue -->
629
- <script lang="ts">
630
- defineOptions({
570
+ <script setup lang="ts">
571
+ import { useBlade } from "@vc-shell/framework";
572
+ import { VcBlade, VcDataTable, VcColumn } from "@vc-shell/framework/ui";
573
+ import useProducts from "../composables/useProducts";
574
+
575
+ defineBlade({
631
576
  name: "ProductsList",
632
577
  url: "/products",
633
578
  isWorkspace: true,
@@ -638,11 +583,6 @@ defineOptions({
638
583
  priority: 10,
639
584
  },
640
585
  });
641
- </script>
642
-
643
- <script setup lang="ts">
644
- import { useBlade, VcBlade, VcDataTable, VcColumn } from "@vc-shell/framework";
645
- import useProducts from "../composables/useProducts";
646
586
 
647
587
  const { openBlade } = useBlade();
648
588
  const { items, loading, totalCount, load } = useProducts();
@@ -660,15 +600,13 @@ The details blade (child):
660
600
 
661
601
  ```vue
662
602
  <!-- pages/ProductDetails.vue -->
663
- <script lang="ts">
664
- defineOptions({
603
+ <script setup lang="ts">
604
+ import { VcBlade } from "@vc-shell/framework/ui";
605
+
606
+ defineBlade({
665
607
  name: "ProductDetails",
666
608
  // No url, no menuItem -- opened programmatically
667
609
  });
668
- </script>
669
-
670
- <script setup lang="ts">
671
- import { VcBlade } from "@vc-shell/framework";
672
610
 
673
611
  const props = defineProps<{
674
612
  param?: { productId: string };
@@ -758,7 +696,7 @@ import { ExtensionPoint } from "@vc-shell/framework";
758
696
 
759
697
  ## Common Mistakes
760
698
 
761
- ### Forgetting `defineOptions` on a blade
699
+ ### Forgetting `defineBlade` on a blade
762
700
 
763
701
  ```typescript
764
702
  // module/index.ts
@@ -770,11 +708,11 @@ export default defineAppModule({
770
708
  ```vue
771
709
  <!-- MyBlade.vue -->
772
710
  <script setup lang="ts">
773
- // No defineOptions!
711
+ // No defineBlade!
774
712
  </script>
775
713
  ```
776
714
 
777
- The blade will be registered with the export key (`"MyBlade"`) as its name, but it will have **no route and no menu entry**. Always add `defineOptions` with at least a `name`.
715
+ The blade will be registered with the export key (`"MyBlade"`) as its name, but it will have **no route and no menu entry** because `defineBlade` is what writes routing, permissions, and menu config into the blade config registry. Always call `defineBlade({ name, url?, menuItem?, ... })` at the top of `<script setup>`.
778
716
 
779
717
  ### Using `createAppModule` with the new notifications API
780
718
 
@@ -821,11 +759,11 @@ export default defineAppModule({
821
759
 
822
760
  // Module B
823
761
  export default defineAppModule({
824
- blades: { Dashboard: DashboardB }, // Overwrites Module A's Dashboard!
762
+ blades: { Dashboard: DashboardB }, // Throws at install time!
825
763
  });
826
764
  ```
827
765
 
828
- Blade names must be globally unique. Use descriptive, module-prefixed names: `OrdersDashboard`, `ProductsDashboard`.
766
+ `BladeRegistry` throws when a name is registered twice: `Blade 'Dashboard' is already registered`. The error halts module installation, so duplicate names are caught at startup rather than silently shadowing each other. Use descriptive, module-prefixed names: `OrdersDashboard`, `ProductsDashboard`.
829
767
 
830
768
  ### Locale key collisions
831
769
 
@@ -122,10 +122,14 @@ export default defineAppModule({
122
122
 
123
123
  ### Toolbar Button Visibility
124
124
 
125
- Toolbar buttons support a `permissions` property that works the same way:
125
+ Toolbar items are declared as an `IBladeToolbar[]` array and bound to `<VcBlade :toolbar-items>`. The `permissions` property on each entry is filtered out before render when the user lacks the listed permission(s):
126
126
 
127
- ```typescript
128
- const toolbar = useToolbar([
127
+ ```vue
128
+ <script setup lang="ts">
129
+ import { ref } from "vue";
130
+ import { VcBlade, type IBladeToolbar } from "@vc-shell/framework";
131
+
132
+ const bladeToolbar = ref<IBladeToolbar[]>([
129
133
  {
130
134
  id: "save",
131
135
  title: "Save",
@@ -141,6 +145,11 @@ const toolbar = useToolbar([
141
145
  clickHandler: () => deleteOrder(),
142
146
  },
143
147
  ]);
148
+ </script>
149
+
150
+ <template>
151
+ <VcBlade :toolbar-items="bladeToolbar" />
152
+ </template>
144
153
  ```
145
154
 
146
155
  ## Tip: Permission Naming Convention
@@ -67,26 +67,26 @@ Module developers do not install this plugin. It is registered once by the frame
67
67
 
68
68
  ## Connection Lifecycle
69
69
 
70
- ```
71
- User logs in (isAuthenticated = true)
72
- |
73
- v
74
- connection.start() ------> /pushNotificationHub (WebSocket)
75
- | |
76
- | <--- "Send" messages -------+
77
- | <--- "SendSystemEvents" ----+ (filtered by creator)
78
- | |
79
- v |
80
- store.ingest(message) |
81
- | |
82
- +--- toast notification |
83
- +--- subscriber callbacks |
84
- +--- history update |
85
- | |
86
- User logs out |
87
- | |
88
- v |
89
- connection.stop() ------------>-+
70
+ ```mermaid
71
+ sequenceDiagram
72
+ participant U as User
73
+ participant C as SignalR client
74
+ participant Hub as /pushNotificationHub
75
+ participant Store as NotificationStore
76
+
77
+ U->>C: log in (isAuthenticated = true)
78
+ C->>Hub: connection.start() (WebSocket)
79
+ Note over C,Hub: connection open
80
+
81
+ Hub-->>C: "Send" (targeted)
82
+ C->>Store: ingest(message)
83
+ Hub-->>C: "SendSystemEvents" (broadcast, filtered by creator)
84
+ C->>Store: ingest(message, { broadcast: true })
85
+
86
+ Store->>Store: toast • subscriber callbacks • history update
87
+
88
+ U->>C: log out
89
+ C->>Hub: connection.stop()
90
90
  ```
91
91
 
92
92
  ### Reconnection Behavior
@@ -49,7 +49,7 @@ This centralized approach has several advantages:
49
49
  | `DashboardServiceKey` | `IDashboardService` | Dashboard widget management |
50
50
  | `MenuServiceKey` | `MenuService` | Main navigation menu |
51
51
  | `SettingsMenuServiceKey` | `ISettingsMenuService` | Settings sidebar menu |
52
- | `AppBarWidgetServiceKey` | `IAppBarWidgetService` | App bar widget slots |
52
+ | `AppBarWidgetServiceKey` | `IAppBarWidgetService` | App hub widget registry |
53
53
  | `AppBarMobileButtonsServiceKey` | `IAppBarMobileButtonsService` | Mobile app bar buttons |
54
54
  | `LanguageServiceKey` | `ILanguageService` | Localization service |
55
55
  | `ToolbarServiceKey` | `IToolbarService` | Blade toolbar actions |
@@ -61,7 +61,7 @@ const routes = [
61
61
  component: Login,
62
62
  meta: { public: true },
63
63
  props: {
64
- title: "Vendor Portal",
64
+ title: "Operations Console",
65
65
  subtitle: "Sign in to manage your store",
66
66
  logo: "/assets/vendor-logo.svg",
67
67
  },
@@ -102,4 +102,4 @@ async function onLogin(user) {
102
102
  - [SettingsMenu](../settings-menu/settings-menu.docs.md) -- parent container
103
103
  - [SettingsMenuItem](../settings-menu-item/settings-menu-item.docs.md) -- base menu item used internally
104
104
  - [ThemeSelector](../theme-selector/theme-selector.docs.md) -- sibling preference entry
105
- - [MultilanguageSelector](../multilanguage-selector/multilanguage-selector.docs.md) -- content language picker (different purpose)
105
+ - [MultilanguageSelector](../../../ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md) -- content language picker (different purpose)
@@ -123,4 +123,4 @@ When a notification's `notifyType` matches a registered template key, that compo
123
123
  ## Related Components
124
124
 
125
125
  - [NotificationTemplate](../notification-template/notification-template.docs.md) -- base template for each notification row
126
- - [Notifications](../notifications/notifications.docs.md) -- toast notification system (different from push notifications)
126
+ - [Notifications](../../../core/notifications/notifications.docs.md) -- push notification system (store, registration, blade-scoped subscriptions)
@@ -175,4 +175,4 @@ const isRunning = computed(() => (notification.value as any).isRunning ?? false)
175
175
  ## Related Components
176
176
 
177
177
  - [NotificationDropdown](../notification-dropdown/notification-dropdown.docs.md) -- parent dropdown container
178
- - [Notifications](../notifications/notifications.docs.md) -- toast notification system (different from push notifications)
178
+ - [Notifications](../../../core/notifications/notifications.docs.md) -- push notification system (store, registration, blade-scoped subscriptions)
@@ -53,7 +53,7 @@ This component has no props. All content is driven by the settings menu service
53
53
  A typical module registers all its settings entries during the module install phase:
54
54
 
55
55
  ```ts
56
- // vendor-portal-module/index.ts
56
+ // settings-module/index.ts
57
57
  import { markRaw } from "vue";
58
58
  import { useSettingsMenu, ThemeSelector, LanguageSelector, ChangePasswordButton, LogoutButton } from "@vc-shell/framework";
59
59
 
@@ -98,12 +98,12 @@ export default {
98
98
 
99
99
  ### Registration options
100
100
 
101
- | Option | Type | Required | Description |
102
- | ----------- | ----------- | -------- | ---------------------------------------------------------- |
103
- | `id` | `string` | Yes | Unique identifier for the entry |
104
- | `group` | `string` | Yes | Group name (entries are grouped and separated by dividers) |
105
- | `order` | `number` | Yes | Sort order within the group (lower = higher position) |
106
- | `component` | `Component` | Yes | Vue component to render as the menu item |
101
+ | Option | Type | Required | Description |
102
+ | ----------- | ----------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
103
+ | `id` | `string` | No | Unique identifier for the entry. Auto-generated when omitted. |
104
+ | `group` | `string` | No | Group name (entries are grouped and separated by dividers). Defaults to `"general"`. |
105
+ | `order` | `number` | No | Sort order within the group (lower = higher position). Defaults to the current registry size at registration time, preserving insertion order. |
106
+ | `component` | `Component` | Yes | Vue component to render as the menu item. |
107
107
 
108
108
  ### Group rendering
109
109
 
@@ -201,5 +201,5 @@ Do not set `triggerAction="none"` and then rely on `@trigger:click` -- the event
201
201
  - [SettingsMenu](../settings-menu/settings-menu.docs.md) -- parent container
202
202
  - [ThemeSelector](../theme-selector/theme-selector.docs.md) -- uses SettingsMenuItem with submenu slot
203
203
  - [LanguageSelector](../language-selector/language-selector.docs.md) -- uses SettingsMenuItem with submenu slot
204
- - [VcDropdownPanel](../../ui/components/molecules/vc-dropdown-panel/) -- used internally for desktop sub-menus
205
- - [VcDropdownItem](../../ui/components/molecules/vc-dropdown/) -- recommended for sub-menu option rows
204
+ - [VcDropdownPanel](../../../ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md) -- used internally for desktop sub-menus
205
+ - [VcDropdown](../../../ui/components/molecules/vc-dropdown/vc-dropdown.docs.md) -- recommended for sub-menu option rows
@@ -11,7 +11,7 @@ Gridstack.js-powered dashboard container that renders registered widgets in a dr
11
11
 
12
12
  ## When to Use
13
13
 
14
- - Use as the main dashboard view for the shell or vendor portal
14
+ - Use as the main dashboard view for a shell application
15
15
  - When you need a customizable widget grid with drag-and-drop rearrangement
16
16
  - Do NOT use for static, non-rearrangeable layouts (use a regular grid/flex layout instead)
17
17
 
@@ -85,12 +85,12 @@ A small indicator component for displaying counts, status dots, or short text la
85
85
  ## Recipe: Status Tags in a Table Cell
86
86
 
87
87
  ```vue
88
- <VcColumn id="status" header="Status" :width="120">
89
- <template #default="{ row }">
88
+ <VcColumn id="status" title="Status" width="120px">
89
+ <template #body="{ data }">
90
90
  <VcBadge
91
91
  inline
92
- :content="row.status"
93
- :variant="statusVariantMap[row.status]"
92
+ :content="data.status"
93
+ :variant="statusVariantMap[data.status]"
94
94
  size="s"
95
95
  />
96
96
  </template>
@@ -328,5 +328,5 @@ All visual properties are customizable through CSS custom properties. Each varia
328
328
 
329
329
  - VcButton calls `e.preventDefault()` on click to support `link` variant pattern. Form submit buttons must use `type="submit"` to bypass this.
330
330
  - `VcButtonGroup` integration is via provide/inject (`vcButtonGroupSize` injection key in `framework/injection-keys.ts`).
331
- - Size aliases `xs`/`base` are kept for vendor-portal backward compatibility — slated for removal in v3.
331
+ - Size aliases `xs`/`base` are kept for backward compatibility — slated for removal in v3.
332
332
  <!-- internal:end -->
@@ -19,11 +19,31 @@ A scrollable content wrapper that fills its parent, provides configurable paddin
19
19
 
20
20
  ## Basic Usage
21
21
 
22
+ The most common form is a bare `<VcContainer>` wrapping the blade's body — it fills the parent, scrolls when content overflows, and applies a 16px default padding.
23
+
24
+ ```vue
25
+ <VcContainer>
26
+ <p>Scrollable content goes here...</p>
27
+ </VcContainer>
28
+ ```
29
+
30
+ When the contained child already manages its own padding (a `VcDataTable`, for example), set `:no-padding="true"` so the wrapper does not stack extra space around it:
31
+
32
+ ```vue
33
+ <VcContainer :no-padding="true">
34
+ <VcDataTable :items="items">
35
+ <VcColumn id="name" title="Name" />
36
+ </VcDataTable>
37
+ </VcContainer>
38
+ ```
39
+
40
+ The `shadow` prop adds an inset shadow as a scroll cue. Use it for content that genuinely overflows by a long way (long forms, free-text editors); the default no-shadow rendering is preferable everywhere else.
41
+
22
42
  ::storybook id="layout-vccontainer--with-shadow" height="300"
23
43
 
24
44
  ```vue
25
45
  <VcContainer shadow>
26
- <p>Scrollable content goes here...</p>
46
+ <p>Long-form content that benefits from a scroll cue...</p>
27
47
  </VcContainer>
28
48
  ```
29
49
 
@@ -72,13 +72,29 @@ function openDetails() {
72
72
 
73
73
  ### Inline Action in a Table Cell
74
74
 
75
+ For row actions in a `VcDataTable`, the framework's `:row-actions` builder is the recommended path — it renders a consistent action menu per row without an extra column declaration:
76
+
77
+ ```vue
78
+ <VcDataTable :items="items" :row-actions="actionBuilder" row-actions-position="column" />
79
+
80
+ <script setup lang="ts">
81
+ import type { TableAction } from "@vc-shell/framework";
82
+
83
+ function actionBuilder(item: Item): TableAction[] {
84
+ return [
85
+ { icon: "lucide-pencil", title: "Edit", clickHandler: () => editItem(item) },
86
+ { icon: "lucide-copy", title: "Copy", clickHandler: () => duplicateItem(item) },
87
+ ];
88
+ }
89
+ </script>
90
+ ```
91
+
92
+ Inline `VcLink` in a cell still fits non-action navigation (open another blade from a name, jump to a docs URL):
93
+
75
94
  ```vue
76
- <VcColumn id="actions" header="Actions" :width="120">
77
- <template #default="{ row }">
78
- <div class="tw-flex tw-gap-3">
79
- <VcLink @click="editItem(row)">Edit</VcLink>
80
- <VcLink @click="duplicateItem(row)">Copy</VcLink>
81
- </div>
95
+ <VcColumn id="name" title="Name">
96
+ <template #body="{ data }">
97
+ <VcLink @click="openItem(data.id)">{{ data.name }}</VcLink>
82
98
  </template>
83
99
  </VcColumn>
84
100
  ```
@@ -52,7 +52,7 @@ The last row automatically renders at 60% width for a natural paragraph feel.
52
52
  ### Avatar Placeholder
53
53
 
54
54
  ```vue
55
- <VcSkeleton variant="circle" :width="48" :height="48" />
55
+ <VcSkeleton variant="circle" width="48px" :height="48" />
56
56
  ```
57
57
 
58
58
  ::storybook id="layout-vcskeleton--card-skeleton" height="450"
@@ -93,7 +93,7 @@ The last row automatically renders at 60% width for a natural paragraph feel.
93
93
  >
94
94
  <VcSkeleton
95
95
  variant="circle"
96
- :width="40"
96
+ width="40px"
97
97
  :height="40"
98
98
  />
99
99
  <div class="tw-flex-1">