@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
@@ -39,15 +39,30 @@ import { VcStatusIcon } from "@vc-shell/framework";
39
39
 
40
40
  ### Boolean Column in a Table
41
41
 
42
+ For a simple yes/no indicator, declare the column with `type="status-icon"` — `VcDataTable` renders the icon based on the boolean cell value, no slot needed:
43
+
44
+ ```vue
45
+ <template>
46
+ <VcColumn
47
+ id="isActive"
48
+ title="Active"
49
+ type="status-icon"
50
+ width="80px"
51
+ />
52
+ </template>
53
+ ```
54
+
55
+ Reach for the `#body` slot only when you need a custom predicate or a non-boolean source:
56
+
42
57
  ```vue
43
58
  <template>
44
59
  <VcColumn
45
60
  id="isActive"
46
- header="Active"
47
- :width="80"
61
+ title="Active"
62
+ width="80px"
48
63
  >
49
- <template #default="{ row }">
50
- <VcStatusIcon :status="row.isActive" />
64
+ <template #body="{ data }">
65
+ <VcStatusIcon :status="data.isActive && data.confirmed" />
51
66
  </template>
52
67
  </VcColumn>
53
68
  </template>
@@ -57,35 +72,26 @@ import { VcStatusIcon } from "@vc-shell/framework";
57
72
 
58
73
  ```vue
59
74
  <template>
60
- <VcDataTable
61
- :columns="columns"
62
- :items="users"
63
- >
75
+ <VcDataTable :items="users">
64
76
  <VcColumn
65
77
  id="emailVerified"
66
- header="Email"
67
- :width="70"
68
- >
69
- <template #default="{ row }">
70
- <VcStatusIcon :status="row.emailVerified" />
71
- </template>
72
- </VcColumn>
78
+ title="Email"
79
+ type="status-icon"
80
+ width="70px"
81
+ />
73
82
  <VcColumn
74
83
  id="isActive"
75
- header="Active"
76
- :width="70"
77
- >
78
- <template #default="{ row }">
79
- <VcStatusIcon :status="row.isActive" />
80
- </template>
81
- </VcColumn>
84
+ title="Active"
85
+ type="status-icon"
86
+ width="70px"
87
+ />
82
88
  <VcColumn
83
89
  id="hasAvatar"
84
- header="Avatar"
85
- :width="70"
90
+ title="Avatar"
91
+ width="70px"
86
92
  >
87
- <template #default="{ row }">
88
- <VcStatusIcon :status="!!row.avatarUrl" />
93
+ <template #body="{ data }">
94
+ <VcStatusIcon :status="!!data.avatarUrl" />
89
95
  </template>
90
96
  </VcColumn>
91
97
  </VcDataTable>
@@ -143,7 +143,7 @@ Set a maximum width to prevent wide tooltips from stretching across the screen:
143
143
  <VcTooltip>...</VcTooltip>
144
144
 
145
145
  <!-- Wider tooltip for long content -->
146
- <VcTooltip :max-width="400">...</VcTooltip>
146
+ <VcTooltip max-width="400px">...</VcTooltip>
147
147
 
148
148
  <!-- CSS string value -->
149
149
  <VcTooltip max-width="50vw">...</VcTooltip>
@@ -165,7 +165,7 @@ Suppress the tooltip dynamically without removing it from the template:
165
165
  The `#tooltip` slot accepts any HTML or Vue components, not just text:
166
166
 
167
167
  ```vue
168
- <VcTooltip placement="top" :max-width="320">
168
+ <VcTooltip placement="top" max-width="320px">
169
169
  <span class="tw-underline tw-decoration-dotted tw-cursor-help">
170
170
  Fulfillment status
171
171
  </span>
@@ -225,7 +225,7 @@ const actions = [
225
225
  <template>
226
226
  <VcTooltip
227
227
  placement="top"
228
- :max-width="400"
228
+ max-width="400px"
229
229
  >
230
230
  <span class="tw-truncate tw-max-w-[200px] tw-block">
231
231
  {{ longProductName }}
@@ -144,4 +144,4 @@ onMounted(async () => {
144
144
 
145
145
  ## Related Components
146
146
 
147
- - [LanguageSelector](../language-selector/language-selector.docs.md) -- settings menu entry for UI locale switching (different purpose)
147
+ - **LanguageSelector** -- shell-internal settings menu entry for UI locale switching (different purpose)
@@ -275,7 +275,7 @@ interface AccordionItem {
275
275
 
276
276
  ## Related Components
277
277
 
278
- - [VcAccordionItem](./_internal/vc-accordion-item/) -- individual accordion panel (used internally and available via the default slot)
278
+ - **VcAccordionItem** -- internal sub-component for individual accordion panels (used internally and available via the default slot)
279
279
 
280
280
  ::storybook id="action-vcaccordion--skeleton"
281
281
 
@@ -288,7 +288,7 @@ clickHandler: () => { navigate(); return true; }
288
288
  ## Related Components
289
289
 
290
290
  - [VcDropdown](../vc-dropdown/) -- Used internally to render the overflow menu
291
- - [VcBreadcrumbsItem](./_internal/vc-breadcrumbs-item/) -- Internal sub-component for individual breadcrumb rendering
291
+ - **VcBreadcrumbsItem** -- internal sub-component for individual breadcrumb rendering
292
292
  - [VcButton](../../atoms/vc-button/) -- Can be used inside the `trigger` slot for a styled overflow button
293
293
 
294
294
  <!-- internal:start -->
@@ -49,18 +49,18 @@ const open = ref(false);
49
49
 
50
50
  ## Key Props
51
51
 
52
- | Prop | Type | Default | Description |
53
- | --------------------- | --------------------- | ---------------- | ------------------------------------------------------------------ |
54
- | `show` | `boolean` | — | Panel visibility (v-model:show) |
55
- | `anchorRef` | `HTMLElement \| null` | `null` | Anchor element for floating positioning |
56
- | `title` | `string` | `""` | Header title text (header hidden when empty and no `#header` slot) |
57
- | `placement` | `Placement` | `"bottom-start"` | Floating UI placement relative to anchor |
58
- | `width` | `string` | `"280px"` | Panel min-width |
59
- | `maxWidth` | `string` | `"400px"` | Panel max-width |
60
- | `maxHeight` | `number` | `350` | Max height in pixels (clamped by viewport) |
61
- | `contentScrollable` | `boolean` | `true` | Enable scrolling in the content area |
62
- | `closeOnClickOutside` | `boolean` | `true` | Close when clicking outside |
63
- | `closeOnEscape` | `boolean` | `true` | Close on Escape key |
52
+ | Prop | Type | Default | Description |
53
+ | --------------------- | -------------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
54
+ | `show` | `boolean` | — | Panel visibility (v-model:show) |
55
+ | `anchorRef` | `ReferenceElement \| null` | `null` | Anchor for floating positioning — accepts an `HTMLElement` or a floating-ui `VirtualElement` (`{ getBoundingClientRect, contextElement? }`). Use a `VirtualElement` when the underlying DOM root can swap dynamically — e.g. wrapping a component whose root changes via internal `v-if` — so `getBoundingClientRect` is resolved fresh on every update instead of caching a stale `$el`. |
56
+ | `title` | `string` | `""` | Header title text (header hidden when empty and no `#header` slot) |
57
+ | `placement` | `Placement` | `"bottom-start"` | Floating UI placement relative to anchor |
58
+ | `width` | `string` | `"280px"` | Panel min-width |
59
+ | `maxWidth` | `string` | `"400px"` | Panel max-width |
60
+ | `maxHeight` | `number` | `350` | Max height in pixels (clamped by viewport) |
61
+ | `contentScrollable` | `boolean` | `true` | Enable scrolling in the content area |
62
+ | `closeOnClickOutside` | `boolean` | `true` | Close when clicking outside |
63
+ | `closeOnEscape` | `boolean` | `true` | Close on Escape key |
64
64
 
65
65
  ## Events
66
66
 
@@ -158,7 +158,7 @@ const open = ref(false);
158
158
  ## Architecture Notes
159
159
 
160
160
  - Click-outside detection uses a `pointerdown` listener on `document` rather than a backdrop overlay. This ensures clicks on high-z-index siblings (sidebar, other teleported panels) are still caught.
161
- - `panelAnchorRegistry` (`panel-anchor-registry.ts`) is a `WeakMap<Element, HTMLElement | null>` that maps each open panel's DOM element to its anchor. This is used to distinguish child panels (whose anchor lives inside this panel) from sibling/parent panels when deciding whether to close on outside click.
161
+ - `panelAnchorRegistry` (`panel-anchor-registry.ts`) is a `WeakMap<Element, Element | null>` that maps each open panel's DOM element to its anchor element. When `anchorRef` is a floating-ui `VirtualElement`, the registry stores its `contextElement` (the live DOM element backing the virtual reference). This is used to distinguish child panels (whose anchor lives inside this panel) from sibling/parent panels when deciding whether to close on outside click.
162
162
  - Nested VcSelect dropdowns teleported to `<body>` are exempt from click-outside via an ARIA `aria-controls` check: if the clicked `.vc-select__dropdown` has an `id` that matches an `aria-controls` attribute inside this panel, the close is suppressed.
163
163
  - The panel exposes a `close()` method via `defineExpose` for use with template refs.
164
164
  - `useTeleportTarget` resolves the teleport destination (typically `body`) respecting any custom portal container.
@@ -538,6 +538,6 @@ disabled: computed(() => !modified.value),
538
538
  - **[VcCheckbox](../vc-checkbox/)** -- checkbox input
539
539
  - **[VcRow](../../atoms/vc-row/)** -- horizontal flex row for form layout
540
540
  - **[VcCol](../../atoms/vc-col/)** -- column within a VcRow
541
- - **[VcCard](../vc-card/)** -- collapsible card for grouping form sections
541
+ - **[VcCard](../../atoms/vc-card/vc-card.docs.md)** -- collapsible card for grouping form sections
542
542
  - **[VcBlade](../../organisms/vc-blade/)** -- blade container that hosts the form
543
543
  - **[VcPopup](../../organisms/vc-popup/)** -- modal dialog, often used for inline forms
@@ -301,7 +301,7 @@ currentPage.value = Math.min(currentPage.value, totalPages.value);
301
301
 
302
302
  ## Related Components
303
303
 
304
- - [VcDataTable](../../organisms/vc-table) -- Data table that commonly pairs with pagination for large datasets
304
+ - [VcDataTable](../../organisms/vc-data-table/vc-data-table.docs.md) -- Data table that commonly pairs with pagination for large datasets
305
305
  - [VcSelect](../vc-select/) -- Can be used alongside pagination for a "rows per page" selector
306
306
 
307
307
  <!-- internal:start -->
@@ -38,7 +38,7 @@ import { VcApp } from "@vc-shell/framework";
38
38
 
39
39
  const isReady = ref(true);
40
40
  const logoUrl = "/logo.svg";
41
- const appTitle = "Vendor Portal";
41
+ const appTitle = "Operations Console";
42
42
  const user = reactive({ name: "John", role: "Admin" });
43
43
  </script>
44
44
  ```
@@ -146,8 +146,8 @@ Modules registered via `useDynamicModules()` are loaded at runtime. Each module
146
146
 
147
147
  The App Hub is a popover panel (desktop) or a swipeable tab (mobile) that combines two sections:
148
148
 
149
- - **Applications** — tile grid of registered apps (e.g., Vendor Portal, Marketplace Admin). Clicking an app switches context without a full page reload. This section can be hidden with `disableAppHub` or customized via the `app-hub` slot. The list is searchable via a built-in search input inside the hub.
150
- - **Widgets** — registered app bar widgets (notifications, background tasks, etc.). Clicking a widget expands its content inline (desktop) or navigates to its panel (mobile). Widgets are registered via `useAppBarWidget()` and can display badges for unread counts.
149
+ - **Applications** — tile grid of registered apps (for example, Operations Console or Marketplace Admin). Clicking an app switches context without a full page reload. This section can be hidden with `disableAppHub` or customized via the `app-hub` slot. The list is searchable via a built-in search input inside the hub.
150
+ - **Widgets** — cross-app widgets registered through `useAppBarWidget()` (sync status, background tasks, language picker, and the like). Clicking a widget either runs its `onClick` (for action widgets) or expands its component inline inside the popover with a back-arrow to return (for component widgets). On mobile, the content flies out below the panel. Widgets can display badges for unread counts.
151
151
 
152
152
  On desktop, the App Hub opens from the sidebar header menu button (`AppHubPopover`). On mobile, it appears as a second tab ("Hub") in the slide-out navigation panel — users can swipe between Menu and Hub tabs.
153
153
 
@@ -225,7 +225,7 @@ Replace the default user info section with a custom footer:
225
225
  - The `disableMenu` prop is useful for single-purpose apps that do not need sidebar navigation (e.g., a standalone settings page or an embedded widget).
226
226
  - Use the `layout` slot only as a last resort for completely custom layouts. For most customizations, the more specific slots (`menu`, `sidebar-header`, `sidebar-footer`) are sufficient.
227
227
  - The `version` prop is informational and can be displayed in the sidebar footer or a settings page. It does not affect any runtime behavior.
228
- - VcApp provides shell services via Vue's provide/inject system. Child components access them through composables like `useMenuService()`, `useToolbarService()`, etc.
228
+ - VcApp provides shell services via Vue's provide/inject system. Child components access them through composables like `useMenuService()`, `useToolbar()`, `useAppBarWidget()`, `useSettingsMenu()`, and `useDashboard()`.
229
229
 
230
230
  ## Accessibility
231
231
 
@@ -12,16 +12,18 @@ The foundational container component of the VirtoCommerce admin shell. Blades ar
12
12
 
13
13
  Traditional admin panels use page-based routing: click a link, the entire viewport changes. Context is lost. Blades solve this by **stacking panels horizontally**. When a user clicks an item in a list, a details blade slides in from the right while the list remains visible. This preserves context, enables comparison, and supports deep drill-down workflows without losing your place.
14
14
 
15
- ```
16
- +----------------+-------------------+---------------------+
17
- | | | |
18
- | Products | Product Details | Edit Variant |
19
- | (workspace) | (child blade) | (grandchild blade) |
20
- | | | |
21
- | [list...] | Name: Widget | Color: Red |
22
- | [list...] | SKU: WDG-001 | Size: Large |
23
- | | | |
24
- +----------------+-------------------+---------------------+
15
+ ```mermaid
16
+ flowchart LR
17
+ subgraph WS["Products (workspace)"]
18
+ L1["[list...]<br/>[list...]"]
19
+ end
20
+ subgraph CH["Product Details (child blade)"]
21
+ L2["Name: Widget<br/>SKU: WDG-001"]
22
+ end
23
+ subgraph GC["Edit Variant (grandchild blade)"]
24
+ L3["Color: Red<br/>Size: Large"]
25
+ end
26
+ WS --> CH --> GC
25
27
  ```
26
28
 
27
29
  | Aspect | Pages/Routes | Blades |
@@ -33,12 +35,12 @@ Traditional admin panels use page-based routing: click a link, the entire viewpo
33
35
 
34
36
  ## When to Use
35
37
 
36
- | Scenario | Component |
37
- | ------------------------------------------------- | -------------------------------------------- |
38
- | Stacked panel with toolbar, header, and lifecycle | **VcBlade** |
39
- | One-off confirmation or input dialog | [VcPopup](../../molecules/vc-popup/) |
40
- | Full-page route without blade stack | Vue Router view |
41
- | Scrollable content section inside a blade | [VcContainer](../../molecules/vc-container/) |
38
+ | Scenario | Component |
39
+ | ------------------------------------------------- | ------------------------------------------------------------ |
40
+ | Stacked panel with toolbar, header, and lifecycle | **VcBlade** |
41
+ | One-off confirmation or input dialog | [VcPopup](../vc-popup/vc-popup.docs.md) |
42
+ | Full-page route without blade stack | Vue Router view |
43
+ | Scrollable content section inside a blade | [VcContainer](../../atoms/vc-container/vc-container.docs.md) |
42
44
 
43
45
  ::storybook id="navigation-vcblade--default"
44
46
 
@@ -58,12 +60,12 @@ Use VcBlade for every screen in a vc-shell application -- it is the standard con
58
60
  </template>
59
61
 
60
62
  <script setup lang="ts">
61
- defineOptions({ name: "MyFirstBlade", url: "/my-first-blade" });
63
+ defineBlade({ name: "MyFirstBlade", url: "/my-first-blade" });
62
64
  </script>
63
65
  ```
64
66
 
65
67
  !!! tip "Every blade needs a name"
66
- Every blade must define a `name` in `defineOptions`. This is how other blades reference it: `openBlade({ name: "MyFirstBlade" })`. The `url` is optional and controls the URL segment.
68
+ Every blade must define a `name` in `defineBlade`. This is how other blades reference it: `openBlade({ name: "MyFirstBlade" })`. The `url` is optional and controls the URL segment.
67
69
 
68
70
  ## Blade Anatomy
69
71
 
@@ -87,7 +89,7 @@ A blade has four visual zones, rendered top-to-bottom:
87
89
 
88
90
  **Toolbar** -- Action buttons from the `toolbarItems` prop. Overflow items automatically collapse into a "More" dropdown (via `ResizeObserver`).
89
91
 
90
- **Status Banners** -- Unified, priority-sorted banner area. System banners: yellow when `modified` is `true`, red when the blade has an error (via `setError()`). Custom banners can be added programmatically via `useBlade().addBanner()` — see [useBlade docs](../../../core/composables/useBlade/useBlade.docs.md#banner-management).
92
+ **Status Banners** -- Unified, priority-sorted banner area. System banners: yellow when `modified` is `true`, red when the blade has an error (via `setError()`). Custom banners can be added programmatically via `useBlade().addBanner()` — see [useBlade docs](../../../../core/composables/useBlade/useBlade.docs.md#banner-management).
91
93
 
92
94
  **Content Area** -- The `default` slot. Scrolls independently of header and toolbar.
93
95
 
@@ -117,7 +119,7 @@ import { computed, ref } from "vue";
117
119
  import { useBlade, type IBladeToolbar } from "@vc-shell/framework";
118
120
 
119
121
  // Registration metadata
120
- defineOptions({
122
+ defineBlade({
121
123
  name: "OfferDetails", // Required: unique blade name
122
124
  url: "/offer", // Optional: URL segment
123
125
  routable: false, // Optional: exclude from direct URL access
@@ -447,12 +449,12 @@ addBanner({
447
449
  </script>
448
450
  ```
449
451
 
450
- Four variants are available: `danger`, `warning`, `info`, `success`. System banners (error and unsaved changes) are always present and cannot be removed by `clearBanners()`. For the full API reference, see [useBlade — Banner Management](../../../core/composables/useBlade/useBlade.docs.md#banner-management).
452
+ Four variants are available: `danger`, `warning`, `info`, `success`. System banners (error and unsaved changes) are always present and cannot be removed by `clearBanners()`. For the full API reference, see [useBlade — Banner Management](../../../../core/composables/useBlade/useBlade.docs.md#banner-management).
451
453
 
452
454
  ## Blade Width Control
453
455
 
454
456
  ```vue
455
- <VcBlade :width="350"> <!-- Pixels (number) -->
457
+ <VcBlade width="350px"> <!-- Pixels (number) -->
456
458
  <VcBlade width="50%"> <!-- CSS value (string) -->
457
459
  <VcBlade> <!-- Default: "30%" -->
458
460
  ```
@@ -463,12 +465,12 @@ On mobile, width is forced to `100%`. When `expanded` is `true`, the blade fills
463
465
 
464
466
  ### Master-Detail (List + Details)
465
467
 
466
- The most common vc-shell pattern. Key points from real-world usage (see `offers-list.vue` and `offers-details.vue`):
468
+ The most common vc-shell pattern. Key points:
467
469
 
468
470
  **List blade** -- Opens a details blade on row click, tracks selected item:
469
471
 
470
472
  ```ts
471
- defineOptions({ name: "Offers", url: "/offers", isWorkspace: true });
473
+ defineBlade({ name: "Offers", url: "/offers", isWorkspace: true });
472
474
 
473
475
  const { openBlade } = useBlade();
474
476
  const selectedItemId = ref<string>();
@@ -493,7 +495,7 @@ defineExpose({ title: bladeTitle, reload });
493
495
  **Details blade** -- Loads entity, saves, notifies parent, replaces self on create:
494
496
 
495
497
  ```ts
496
- defineOptions({ name: "Offer", url: "/offer", routable: false });
498
+ defineBlade({ name: "Offer", url: "/offer", routable: false });
497
499
 
498
500
  const { callParent, replaceWith, onBeforeClose } = useBlade();
499
501
 
@@ -577,7 +579,7 @@ const toolbar = ref([
577
579
  defineOptions({});
578
580
 
579
581
  // CORRECT
580
- defineOptions({ name: "ProductDetails", url: "/product" });
582
+ defineBlade({ name: "ProductDetails", url: "/product" });
581
583
  ```
582
584
 
583
585
  ### Forgetting to expose the title
@@ -624,17 +626,17 @@ openBlade({ name: "ProductsList" });
624
626
 
625
627
  ## Props
626
628
 
627
- | Prop | Type | Default | Description |
628
- | -------------- | ------------------ | ----------- | ------------------------------------------------------------ |
629
- | `title` | `string` | `undefined` | Title text in the blade header. |
630
- | `subtitle` | `string` | `undefined` | Secondary text below the title. |
631
- | `icon` | `string` | `undefined` | Icon name (e.g., `"lucide-box"`) displayed before the title. |
632
- | `width` | `number \| string` | `"30%"` | Blade width. Numbers are pixels; strings are CSS values. |
633
- | `expanded` | `boolean` | `false` | Whether the blade fills all available width. |
634
- | `closable` | `boolean` | `true` | Whether the close button is shown. |
635
- | `toolbarItems` | `IBladeToolbar[]` | `[]` | Action buttons in the toolbar zone. |
636
- | `modified` | `boolean` | `undefined` | Shows unsaved changes indicator and banner. |
637
- | `loading` | `boolean` | `false` | Shows skeleton placeholders for all blade zones. |
629
+ | Prop | Type | Default | Description |
630
+ | -------------- | ------------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
631
+ | `title` | `string` | `undefined` | Title text in the blade header. |
632
+ | `subtitle` | `string` | `undefined` | Secondary text below the title. |
633
+ | `icon` | `string` | `undefined` | Icon name (e.g., `"lucide-box"`) displayed before the title. |
634
+ | `width` | `number \| string` | `"30%"` | Blade width. Numbers are pixels; strings are CSS values. |
635
+ | `expanded` | `boolean` | `undefined` | Whether the blade fills all available width. Inside a blade-navigation context this prop is overridden by the active blade's expanded state; in standalone use the prop is read directly. |
636
+ | `closable` | `boolean` | `true` | Whether the close button is shown. |
637
+ | `toolbarItems` | `IBladeToolbar[]` | `[]` | Action buttons in the toolbar zone. |
638
+ | `modified` | `boolean` | `undefined` | Shows unsaved changes indicator and banner. |
639
+ | `loading` | `boolean` | `undefined` | Shows skeleton placeholders for all blade zones. |
638
640
 
639
641
  ## Events
640
642
 
@@ -167,7 +167,7 @@ Formats as currency. Reads the currency code from each row's `currency` field by
167
167
  ### Image
168
168
 
169
169
  ```vue
170
- <VcColumn id="thumbnail" field="imgSrc" title="Image" type="image" :width="60" />
170
+ <VcColumn id="thumbnail" field="imgSrc" title="Image" type="image" width="60px" />
171
171
  ```
172
172
 
173
173
  Renders a small thumbnail from the field's URL value.
@@ -351,7 +351,7 @@ For explicit control over checkbox column placement:
351
351
 
352
352
  ```vue
353
353
  <VcDataTable :items="products" v-model:selection="selected">
354
- <VcColumn id="select" selection-mode="multiple" :width="40" />
354
+ <VcColumn id="select" selection-mode="multiple" width="40px" />
355
355
  <VcColumn id="name" field="name" title="Name" />
356
356
  </VcDataTable>
357
357
  ```
@@ -485,7 +485,7 @@ A row enters edit mode when the user clicks the edit button. All editable cells
485
485
  <VcColumn id="name" field="name" title="Name" editable />
486
486
  <VcColumn id="price" field="price" title="Price" type="money" editable />
487
487
  <VcColumn id="stock" field="stock" title="Stock" type="number" editable />
488
- <VcColumn id="actions" :row-editor="true" title="" :width="80" />
488
+ <VcColumn id="actions" :row-editor="true" title="" width="80px" />
489
489
  </VcDataTable>
490
490
  ```
491
491
 
@@ -550,7 +550,7 @@ Columns are resizable by default. Drag the right border of any column header to
550
550
  Set per-column min/max constraints:
551
551
 
552
552
  ```vue
553
- <VcColumn id="name" field="name" title="Name" :min-width="100" :max-width="400" />
553
+ <VcColumn id="name" field="name" title="Name" min-width="100px" max-width="400px" />
554
554
  ```
555
555
 
556
556
  ### Reorder
@@ -583,11 +583,11 @@ VcDataTable uses a **weight-based engine** to compute exact pixel widths for eve
583
583
 
584
584
  **Width prop contract:**
585
585
 
586
- | Declaration | Meaning |
587
- | ------------------------------- | ------------------------------------------------------------ |
588
- | `width="200"` or `:width="200"` | Initial 200 px hint |
589
- | `width="20%"` | Initial hint based on 20% of available width |
590
- | `width` omitted | Auto — splits remaining space equally among all auto columns |
586
+ | Declaration | Meaning |
587
+ | -------------------------------- | ------------------------------------------------------------ |
588
+ | `width="200"` or `width="200px"` | Initial 200 px hint |
589
+ | `width="20%"` | Initial hint based on 20% of available width |
590
+ | `width` omitted | Auto — splits remaining space equally among all auto columns |
591
591
 
592
592
  After initialization the column lives in the weight model. Container resizes recompute px values without changing weights.
593
593
 
@@ -628,7 +628,7 @@ When a blade narrows (e.g., a second blade opens), only `alwaysVisible` columns
628
628
 
629
629
  ```vue
630
630
  <VcDataTable :items="products" :show-all-columns="!isBladeNarrow">
631
- <VcColumn id="image" field="imgSrc" type="image" :width="60" :always-visible="true" />
631
+ <VcColumn id="image" field="imgSrc" type="image" width="60px" :always-visible="true" />
632
632
  <VcColumn id="name" field="name" title="Name" :always-visible="true" />
633
633
  <VcColumn id="price" field="price" title="Price" type="money" />
634
634
  <VcColumn id="stock" field="stock" title="Stock" type="number" />
@@ -653,7 +653,7 @@ Enable drag-and-drop row reordering with a drag handle column:
653
653
  <VcColumn
654
654
  id="drag"
655
655
  :row-reorder="true"
656
- :width="40"
656
+ width="40px"
657
657
  />
658
658
  <VcColumn
659
659
  id="name"
@@ -695,7 +695,7 @@ Show additional detail below a row when the user clicks the expand toggle:
695
695
  <VcColumn
696
696
  id="expand"
697
697
  :expander="true"
698
- :width="40"
698
+ width="40px"
699
699
  />
700
700
  <VcColumn
701
701
  id="orderNumber"
@@ -752,7 +752,7 @@ Use `isRowExpandable` to control which rows show the expand toggle. Rows that fa
752
752
  <VcColumn
753
753
  id="expand"
754
754
  :expander="true"
755
- :width="40"
755
+ width="40px"
756
756
  />
757
757
  <VcColumn
758
758
  id="orderNumber"
@@ -1028,9 +1028,9 @@ async function loadNextPage() {
1028
1028
  ## State Persistence
1029
1029
 
1030
1030
  !!! tip "Use unique state keys"
1031
- Every table in your application must have a distinct `state-key`. Two tables sharing the same key will silently overwrite each other's persisted column widths, order, and sort state.
1031
+ Every table in your application must have a distinct `state-key`. Two tables sharing the same key will silently overwrite each other's persisted column widths, order, and hidden/shown column lists.
1032
1032
 
1033
- Persist column widths, column order, hidden columns, sort, and filters across page reloads:
1033
+ Persist column widths, column order, and column visibility across page reloads. Sort, filters, pagination, selection, and search input are session-scoped — they are deliberately excluded from the persisted state so the blade owns them through its own URL or store:
1034
1034
 
1035
1035
  ```vue
1036
1036
  <VcDataTable :items="products" state-key="product-list">
@@ -1135,7 +1135,7 @@ On mobile screens, VcDataTable automatically switches from a table to a card lay
1135
1135
 
1136
1136
  ```vue
1137
1137
  <VcDataTable :items="products">
1138
- <VcColumn id="image" field="imgSrc" type="image" mobile-role="image" :width="60" />
1138
+ <VcColumn id="image" field="imgSrc" type="image" mobile-role="image" width="60px" />
1139
1139
  <VcColumn id="name" field="name" title="Name" mobile-role="title" />
1140
1140
  <VcColumn id="price" field="price" title="Price" type="money" mobile-role="field" />
1141
1141
  <VcColumn id="stock" field="stock" title="Stock" type="number" mobile-role="field" />
@@ -1589,7 +1589,7 @@ function onRowRemove(event: { data: Product; index: number; cancel: () => void }
1589
1589
 
1590
1590
  ### Recipe 1: Products List Blade
1591
1591
 
1592
- A typical list blade with search, pagination, row actions, and empty states -- modeled after real vendor-portal usage.
1592
+ A typical list blade with search, pagination, row actions, and empty states.
1593
1593
 
1594
1594
  ```vue
1595
1595
  <template>
@@ -22,19 +22,28 @@ Renders a VirtoCommerce platform dynamic property as the appropriate form contro
22
22
  ```vue
23
23
  <template>
24
24
  <VcDynamicProperty
25
- :property="dynamicProperty"
26
- :model-value="propertyValue"
27
- :value-type="dynamicProperty.valueType"
28
- :name="dynamicProperty.name"
29
- :required="dynamicProperty.isRequired"
30
- :dictionary="dynamicProperty.isDictionary"
31
- :multivalue="dynamicProperty.isMultivalue"
25
+ :property="property"
26
+ :model-value="property.value"
27
+ :value-type="property.valueType ?? ''"
28
+ :name="property.name"
29
+ :required="property.required"
30
+ :dictionary="property.dictionary"
31
+ :multivalue="property.multivalue"
32
+ :multilanguage="property.multilanguage"
33
+ :current-language="currentLocale"
34
+ :rules="{
35
+ min: property.validationRule?.charCountMin,
36
+ max: property.validationRule?.charCountMax,
37
+ regex: property.validationRule?.regExp,
38
+ }"
32
39
  :options-getter="loadDictionaryOptions"
33
40
  @update:model-value="handlePropertyUpdate"
34
41
  />
35
42
  </template>
36
43
  ```
37
44
 
45
+ The prop names match the `DynamicObjectProperty` shape returned by the platform — pass `property.dictionary`, `property.multivalue`, `property.required` directly without renaming. Always pass `valueType` with a string fallback because the API can return `undefined` for newly-created properties. The `:multilanguage` and `:current-language` props are required when the property supports localized values; the `:rules` object maps the property's `validationRule` to the form-validation engine.
46
+
38
47
  ## Key Props
39
48
 
40
49
  | Prop | Type | Default | Description |
@@ -126,7 +126,7 @@ Override with the `width` or `height` prop for custom dimensions.
126
126
  ### Elevated Variant with Custom Width
127
127
 
128
128
  ```vue
129
- <VcSidebar v-model="open" variant="elevated" :width="480" title="Details">
129
+ <VcSidebar v-model="open" variant="elevated" width="480px" title="Details">
130
130
  <div class="tw-p-5">Content</div>
131
131
  </VcSidebar>
132
132
  ```