@vc-shell/vc-app-skill 2.5.0 → 2.6.0-pr370.de147ea
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.
- package/package.json +1 -1
- package/runtime/VERSION +1 -1
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +28 -1
- package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +1 -1
- package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +8 -8
- package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +11 -0
- package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +2 -0
- package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +15 -4
- package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +22 -18
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +4 -0
- package/runtime/knowledge/docs/core/services/services.docs.md +0 -1
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +1 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +10 -9
- package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +21 -20
- package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +27 -26
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +1 -0
- package/runtime/knowledge/docs/ui/components/molecules/vc-popover/vc-popover.docs.md +3 -2
- package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +16 -11
- package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +1 -0
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +1 -1
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +77 -0
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +20 -19
- package/runtime/knowledge/docs/ui/components/organisms/vc-scheduler/vc-scheduler.docs.md +4 -2
- package/runtime/vc-app.md +4 -2
- package/runtime/knowledge/docs/core/composables/useKeyboardShortcuts/useKeyboardShortcuts.docs.md +0 -219
- package/runtime/knowledge/docs/core/composables/useLatestRequest/useLatestRequest.docs.md +0 -149
- package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +0 -93
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/vc-app-skill",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.6.0-pr370.de147ea",
|
|
4
4
|
"description": "AI coding skill for scaffolding and generating VirtoCommerce Shell applications. Works with Claude Code, OpenCode, Gemini, Codex, Cursor.",
|
|
5
5
|
"bin": "./bin/install.cjs",
|
|
6
6
|
"files": [
|
package/runtime/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.6.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Synced from framework at commit
|
|
1
|
+
Synced from framework at commit 1919c06af on 2026-09-22T14:57:56.467Z
|
|
@@ -44,10 +44,36 @@ The `createBladeStack` / `createBladeMessaging` factories are internal (not re-e
|
|
|
44
44
|
|
|
45
45
|
The blade stack state machine. Manages an ordered array of `BladeDescriptor` objects.
|
|
46
46
|
|
|
47
|
-
### Factory: `createBladeStack(bladeRegistry, hasAccess?)`
|
|
47
|
+
### Factory: `createBladeStack(bladeRegistry, hasAccess?, urlSink?)`
|
|
48
48
|
|
|
49
49
|
Creates a new stack instance. Called once by the navigation plugin.
|
|
50
50
|
|
|
51
|
+
`urlSink` is where the stack writes the address bar. It defaults to a no-op, so a
|
|
52
|
+
stack created without one (Storybook, standalone mounts, unit tests) simply never
|
|
53
|
+
touches the URL. The plugin passes the router-backed sink.
|
|
54
|
+
|
|
55
|
+
### The stack owns the URL
|
|
56
|
+
|
|
57
|
+
Every navigation action syncs the URL itself, with the verb the action implies.
|
|
58
|
+
Callers mutate the stack and nothing else — there is no "and now sync the URL"
|
|
59
|
+
step to forget.
|
|
60
|
+
|
|
61
|
+
| Action | Verb | When |
|
|
62
|
+
| --------------------- | --------- | -------------------------------------- |
|
|
63
|
+
| `openWorkspace` | `push` | the resulting active blade has a `url` |
|
|
64
|
+
| `openBlade` | `push` | the resulting active blade has a `url` |
|
|
65
|
+
| `coverCurrentBlade` | `push` | the resulting active blade has a `url` |
|
|
66
|
+
| `replaceCurrentBlade` | `replace` | the resulting active blade has a `url` |
|
|
67
|
+
| `closeBlade` | `replace` | the close was not prevented by a guard |
|
|
68
|
+
| `closeChildren` | `replace` | always |
|
|
69
|
+
|
|
70
|
+
Everything else — `updateBladeQuery`, `setBladeTitle`, `setBladeError`,
|
|
71
|
+
`_restoreStack` — never writes the URL.
|
|
72
|
+
|
|
73
|
+
The router guard restores the stack **from** the URL, so it suppresses the sink
|
|
74
|
+
for the duration of the navigation (`RouterUrlSink.suppressWhile`): during
|
|
75
|
+
resolution the URL is the source, and writing back would re-enter the guard.
|
|
76
|
+
|
|
51
77
|
### API
|
|
52
78
|
|
|
53
79
|
| Method | Description |
|
|
@@ -162,6 +188,7 @@ The plain data object stored in the stack for each blade:
|
|
|
162
188
|
- Close guards return `true` to PREVENT closing (opposite of the legacy convention where `false` prevented closing). The adapter handles the inversion.
|
|
163
189
|
- `replaceCurrentBlade` destroys the current blade and creates a new one at the same index with the same `parentId`. Use `coverCurrentBlade` to hide instead of destroy — the covering blade's `callParent` reaches the hidden blade's exposed methods.
|
|
164
190
|
- URL sync only updates the address bar for blades that have a `url` segment. Third-level detail panels without URLs leave the previous URL intact.
|
|
191
|
+
- The stack writes the URL, not the caller. `createUrlSync` remains for the two writes that are not stack mutations: the post-restore reconcile in `VcBladeNavigation` and the debounced table-query-state writer.
|
|
165
192
|
- `useBladeNavigation()` requires the navigation plugin to be installed. It throws if called before plugin initialization.
|
|
166
193
|
|
|
167
194
|
## Related
|
|
@@ -790,7 +790,7 @@ if (param.value) {
|
|
|
790
790
|
1. **Plugin setup:** `BladeNavigationPlugin` (plugin-v2) installs a `BladeStack` and `BladeMessaging` singleton and provides them via Vue's dependency injection.
|
|
791
791
|
2. **Inside a blade:** `VcBladeSlot` provides a `BladeDescriptor` ref for each blade instance. `useBlade()` injects this descriptor to access identity, register guards, and set errors.
|
|
792
792
|
3. **Outside a blade:** `useBlade()` falls back to the singleton instances. Only `openBlade` works because it does not need a blade descriptor.
|
|
793
|
-
4. **URL sync:** When blades with a `url` property are opened or closed,
|
|
793
|
+
4. **URL sync:** When blades with a `url` property are opened or closed, the blade stack synchronizes the browser URL itself (push on open, replace on close), enabling deep linking and back/forward navigation. `useBlade()` only mutates the stack.
|
|
794
794
|
|
|
795
795
|
<!-- internal:end -->
|
|
796
796
|
|
package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md
CHANGED
|
@@ -71,13 +71,13 @@ function openMenu() {
|
|
|
71
71
|
|
|
72
72
|
### Parameters (Options Object)
|
|
73
73
|
|
|
74
|
-
| Parameter | Type | Default | Description
|
|
75
|
-
| ------------------- | --------------------------- | ------------------ |
|
|
76
|
-
| `containerSelector` | `string` | `'[role="menu"]'` | CSS selector to auto-find the container on mount. Set to empty string to disable auto-attach.
|
|
77
|
-
| `itemSelector` | `string` | `'[tabindex="0"]'` | CSS selector for focusable items inside the container.
|
|
78
|
-
| `onEnter` | `(el: HTMLElement) => void` | `undefined` | Called when Enter or Space is pressed on a focused item. Falls back to `el.click()` if not provided.
|
|
79
|
-
| `onEscape` | `() => void` | `undefined` | Called when Escape is pressed. Typically used to close the menu or popover.
|
|
80
|
-
| `loop` | `boolean` | `true` | When `true`, pressing ArrowDown on the last item wraps to the first, and ArrowUp on the first wraps to the last.
|
|
74
|
+
| Parameter | Type | Default | Description |
|
|
75
|
+
| ------------------- | --------------------------- | ------------------ | --------------------------------------------------------------------------------------------------------------------- |
|
|
76
|
+
| `containerSelector` | `string` | `'[role="menu"]'` | CSS selector to auto-find the container on mount. Set to empty string to disable auto-attach. |
|
|
77
|
+
| `itemSelector` | `string` | `'[tabindex="0"]'` | CSS selector for focusable items inside the container. |
|
|
78
|
+
| `onEnter` | `(el: HTMLElement) => void` | `undefined` | Called when Enter or Space is pressed on a focused item. Falls back to `el.click()` if not provided. |
|
|
79
|
+
| `onEscape` | `() => void` | `undefined` | Called when Escape is pressed, and makes the composable consume the key. Typically used to close the menu or popover. |
|
|
80
|
+
| `loop` | `boolean` | `true` | When `true`, pressing ArrowDown on the last item wraps to the first, and ArrowUp on the first wraps to the last. |
|
|
81
81
|
|
|
82
82
|
### Returns
|
|
83
83
|
|
|
@@ -101,7 +101,7 @@ The composable listens for `keydown` events on the container element and handles
|
|
|
101
101
|
- **ArrowDown / Tab**: Move focus to the next item (`focusNextElement`)
|
|
102
102
|
- **ArrowUp / Shift+Tab**: Move focus to the previous item (`focusPreviousElement`)
|
|
103
103
|
- **Enter / Space**: Activate the focused item (calls `onEnter` callback, or `el.click()`)
|
|
104
|
-
- **Escape**: Call `onEscape` callback
|
|
104
|
+
- **Escape**: Call `onEscape` callback. When a callback is given the event is consumed (`preventDefault` + `stopPropagation`), so a sidebar or dialog listening on `document` does not also close behind the overlay. With no `onEscape`, the key passes through untouched.
|
|
105
105
|
|
|
106
106
|
On each key event, the composable re-queries the container for matching items (`itemSelector`), so it naturally handles dynamic lists where items are added or removed. The focused index is validated against the current item count before every operation to prevent stale-index bugs.
|
|
107
107
|
|
|
@@ -6,6 +6,17 @@ group: forms
|
|
|
6
6
|
|
|
7
7
|
# useModificationTracker
|
|
8
8
|
|
|
9
|
+
!!! warning "Deprecated — use `useBladeForm`"
|
|
10
|
+
`useBladeForm` owns validation, the dirty flag, the unsaved-changes guard and the
|
|
11
|
+
close prompt together, where this tracks only the dirty flag. It has no callers
|
|
12
|
+
left in the framework or the reference app, and `cli/migrate`'s `use-blade-form`
|
|
13
|
+
transform already flags the `useForm` + `useBeforeUnload` +
|
|
14
|
+
`useModificationTracker` combination for the same move.
|
|
15
|
+
|
|
16
|
+
Its comparator is deliberately not being aligned with `useBladeForm`'s: an
|
|
17
|
+
empty array counts as empty there and not here, and changing that would move
|
|
18
|
+
the dirty flag under anyone still on this composable.
|
|
19
|
+
|
|
9
20
|
Tracks deep changes to a value and reports whether it has been modified compared to its original (pristine) state. This is the core composable behind the "unsaved changes" detection pattern in vc-shell blades. It handles complex nested objects, arrays, and the common API quirk where `null`, `undefined`, and `""` should be treated as equivalent empty values.
|
|
10
21
|
|
|
11
22
|
The composable maintains two copies of the data: the `pristineValue` (the clean baseline) and the `currentValue` (the working copy bound to form fields). Any deep difference between the two sets `isModified` to `true`.
|
|
@@ -110,6 +110,8 @@ The plugin instance is resolved via `inject(PopupPluginKey)`. If called outside
|
|
|
110
110
|
|
|
111
111
|
Multiple popups can be open simultaneously — they stack with the most recent on top.
|
|
112
112
|
|
|
113
|
+
On close, focus returns to the control that opened the popup (WCAG 2.4.3 Focus Order). When that control was never focused, or has since been removed from the page, focus goes to the app workspace instead — never left on `<body>`, which would make the next Tab restart at the top of the document. A popup that deliberately moved focus somewhere else keeps it; this repairs lost focus rather than dictating it.
|
|
114
|
+
|
|
113
115
|
## Recipe: Delete Confirmation with Notification
|
|
114
116
|
|
|
115
117
|
```vue
|
|
@@ -8,8 +8,6 @@ group: ui-state
|
|
|
8
8
|
|
|
9
9
|
Controls the sidebar (left navigation panel) expansion, pinning, hover, and mobile menu state. This composable exposes a unified API for reading and toggling all sidebar states from any component within the VcApp tree. The sidebar has three independent dimensions: **pinned** (user explicitly locked it open, persisted to localStorage), **hover-expanded** (mouse is hovering over the collapsed sidebar on desktop), and **mobile menu** (overlay drawer on small screens). The derived `isExpanded` computed combines pinned and hover states for convenience.
|
|
10
10
|
|
|
11
|
-
Internally, it delegates to `useMenuExpanded()` to share reactive state with other components like `UserDropdownButton` that also need to know the sidebar state.
|
|
12
|
-
|
|
13
11
|
## When to Use
|
|
14
12
|
|
|
15
13
|
- Toggle or read sidebar expanded/collapsed state from any component inside VcApp
|
|
@@ -82,6 +80,20 @@ provideSidebarState();
|
|
|
82
80
|
|
|
83
81
|
<!-- internal:end -->
|
|
84
82
|
|
|
83
|
+
## Storage key
|
|
84
|
+
|
|
85
|
+
The pinned state lives in `localStorage` under an app-scoped key -- the first segment of the URL path, so several vc-shell apps on one domain keep independent sidebars. `sidebarStorageKey()` returns that key, so tests and stories can seed the state before `VcApp` mounts instead of hard-coding the string:
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
import { sidebarStorageKey } from "@vc-shell/framework";
|
|
89
|
+
|
|
90
|
+
// Served from "/operations/catalog" -> "VC_APP_MENU_EXPANDED_operations"
|
|
91
|
+
localStorage.setItem(sidebarStorageKey(), "true");
|
|
92
|
+
|
|
93
|
+
// Or name the app explicitly
|
|
94
|
+
localStorage.setItem(sidebarStorageKey("operations"), "false");
|
|
95
|
+
```
|
|
96
|
+
|
|
85
97
|
## Recipe: Auto-Close Mobile Menu After Navigation
|
|
86
98
|
|
|
87
99
|
```vue
|
|
@@ -138,10 +150,9 @@ const contentClass = computed(() => (isExpanded.value ? "tw-ml-64" : "tw-ml-16")
|
|
|
138
150
|
## Tips
|
|
139
151
|
|
|
140
152
|
- **Hover delay prevents flicker.** The 200ms delay on `setHoverExpanded(true)` means that quickly passing the mouse over the sidebar does not cause it to flash open. Closing is instant so the sidebar feels responsive.
|
|
141
|
-
- **`isPinned` is persisted to localStorage.** If a user pins the sidebar, it stays pinned across page reloads and browser sessions. The key is
|
|
153
|
+
- **`isPinned` is persisted to localStorage.** If a user pins the sidebar, it stays pinned across page reloads and browser sessions. The key is app-scoped -- `sidebarStorageKey()` returns it.
|
|
142
154
|
- **Do not call outside VcApp.** If you call `useSidebarState()` in a component that is not a descendant of VcApp (e.g., in a standalone dialog or a separate Vue app instance), it will throw an error.
|
|
143
155
|
|
|
144
156
|
## Related
|
|
145
157
|
|
|
146
|
-
- `useMenuExpanded` -- lower-level composable that manages pinned/hover state and localStorage persistence
|
|
147
158
|
- `VcApp` -- the root component that calls `provideSidebarState()`
|
|
@@ -7,15 +7,17 @@ internal: true
|
|
|
7
7
|
|
|
8
8
|
# useSlowNetworkDetection
|
|
9
9
|
|
|
10
|
-
Detects slow network conditions and
|
|
10
|
+
Detects slow network conditions and publishes them as the `vc-slow-network` class on `<html>`, which the framework renders as a 2px sweep along the top edge of the viewport. Two detection channels work together: a **proactive** channel reads `navigator.connection.effectiveType` to catch weak connections before any request is made, and a **reactive** channel flags idempotent API requests that have been pending for more than 10 seconds. The class is removed with a 3-second delay after conditions clear, preventing flicker. When the browser goes fully offline, the class is dropped in favor of the offline notification from `useConnectionStatus`.
|
|
11
|
+
|
|
12
|
+
A slow network is a state, not an event, so it is never announced as a toast: a dismissable one reappears on every action that outruns the threshold, and a sticky one sits on the screen for the whole session on a 2g connection (VCST-6045).
|
|
11
13
|
|
|
12
14
|
Like `useConnectionStatus`, this is a module-level singleton — calling it from multiple components shares the same state and listeners.
|
|
13
15
|
|
|
14
16
|
## When to Use
|
|
15
17
|
|
|
16
18
|
- Reactively check `isSlowNetwork` to show skeleton loaders, disable auto-refresh, or display inline warnings
|
|
17
|
-
- The
|
|
18
|
-
- Use `trackRequest` / `untrackRequest` only if you have custom fetch logic outside the standard interceptor (the built-in fetch interceptor already tracks
|
|
19
|
+
- The `vc-slow-network` class is automatic — no extra code needed beyond calling the composable once at app startup (already done in `framework/index.ts`)
|
|
20
|
+
- Use `trackRequest` / `untrackRequest` only if you have custom fetch logic outside the standard interceptor (the built-in fetch interceptor already tracks idempotent `/api/*` requests)
|
|
19
21
|
- When NOT to use: for offline detection (use `useConnectionStatus` instead) or for measuring exact latency/bandwidth
|
|
20
22
|
|
|
21
23
|
## Quick Start
|
|
@@ -61,11 +63,12 @@ const { isSlowNetwork } = useSlowNetworkDetection();
|
|
|
61
63
|
|
|
62
64
|
These are module-private `const` declarations, not exported symbols — do not `import` them. They document the thresholds baked into the composable.
|
|
63
65
|
|
|
64
|
-
| Name | Value | Purpose
|
|
65
|
-
| --------------------------- | ------------------- |
|
|
66
|
-
| `SLOW_REQUEST_THRESHOLD_MS` | `10000` | Time before a pending request is considered slow
|
|
67
|
-
| `DISMISS_DELAY_MS` | `3000` | Delay before
|
|
68
|
-
| `SLOW_EFFECTIVE_TYPES` | `["slow-2g", "2g"]` | Connection types flagged as slow
|
|
66
|
+
| Name | Value | Purpose |
|
|
67
|
+
| --------------------------- | ------------------- | ------------------------------------------------ |
|
|
68
|
+
| `SLOW_REQUEST_THRESHOLD_MS` | `10000` | Time before a pending request is considered slow |
|
|
69
|
+
| `DISMISS_DELAY_MS` | `3000` | Delay before dropping the class after recovery |
|
|
70
|
+
| `SLOW_EFFECTIVE_TYPES` | `["slow-2g", "2g"]` | Connection types flagged as slow |
|
|
71
|
+
| `SLOW_NETWORK_CLASS` | `"vc-slow-network"` | Class the state is published as, on `<html>` |
|
|
69
72
|
|
|
70
73
|
## How It Works
|
|
71
74
|
|
|
@@ -75,15 +78,15 @@ On first call, the composable checks `navigator.connection.effectiveType` (Netwo
|
|
|
75
78
|
|
|
76
79
|
### Channel 2: Request timers (reactive)
|
|
77
80
|
|
|
78
|
-
The fetch interceptor in `framework/core/interceptors/index.ts` calls `trackRequest(id)` before every `/api/*` request and `untrackRequest(id)` in the `finally` block. Each tracked request gets a 10-second timer. If the response arrives in time, the timer is cancelled. If not, `isSlowNetwork` becomes `true` and stays `true` until all slow requests complete.
|
|
81
|
+
The fetch interceptor in `framework/core/interceptors/index.ts` calls `trackRequest(id)` before every idempotent `/api/*` request (GET and HEAD) and `untrackRequest(id)` in the `finally` block. An upload or any other mutation is left out: its duration is the operator's uplink, not a stalled server, and a large file would otherwise claim the network is slow every time. Each tracked request gets a 10-second timer. If the response arrives in time, the timer is cancelled. If not, `isSlowNetwork` becomes `true` and stays `true` until all slow requests complete.
|
|
79
82
|
|
|
80
|
-
###
|
|
83
|
+
### Class lifecycle
|
|
81
84
|
|
|
82
|
-
1. `isSlowNetwork` becomes `true` →
|
|
83
|
-
2. `isSlowNetwork` becomes `false` → start a 3-second
|
|
84
|
-
3. If `isSlowNetwork` goes back to `true` within those 3 seconds → cancel
|
|
85
|
-
4. If the browser goes offline →
|
|
86
|
-
5. If the browser comes back online and `isSlowNetwork` is still `true` →
|
|
85
|
+
1. `isSlowNetwork` becomes `true` → add `vc-slow-network` to `<html>`, and the bar appears
|
|
86
|
+
2. `isSlowNetwork` becomes `false` → start a 3-second removal timer
|
|
87
|
+
3. If `isSlowNetwork` goes back to `true` within those 3 seconds → cancel removal, the class stays
|
|
88
|
+
4. If the browser goes offline → remove the class at once (the offline notification takes over)
|
|
89
|
+
5. If the browser comes back online and `isSlowNetwork` is still `true` → add it again
|
|
87
90
|
<!-- internal:end -->
|
|
88
91
|
|
|
89
92
|
## Recipe: Custom Slow-Network Behavior in a Blade
|
|
@@ -131,8 +134,9 @@ async function fetchFromExternalApi(url: string) {
|
|
|
131
134
|
## Tips
|
|
132
135
|
|
|
133
136
|
- **Singleton by design.** Multiple calls to `useSlowNetworkDetection()` share the same state. No overhead from calling it in many components.
|
|
134
|
-
- **The
|
|
135
|
-
- **The 3-second
|
|
137
|
+
- **The state cannot stack.** A class is present or it is not, so concurrent slow requests read as one state.
|
|
138
|
+
- **The 3-second removal delay prevents flicker.** Without it, a burst of requests completing one-by-one would toggle the class on and off rapidly.
|
|
139
|
+
- **The bar lives in one CSS rule.** `framework/assets/styles/index.scss` draws it next to the `html.vc-offline` rule, so an app can restyle or suppress it without touching the composable. Under `prefers-reduced-motion` it becomes a static line.
|
|
136
140
|
- **`navigator.connection` has limited support.** Only Chromium-based browsers support it. Firefox and Safari users will only get the request-timer channel, which is still effective.
|
|
137
141
|
- **The composable does not block requests.** Unlike the offline guard in the interceptor, slow-network detection is purely informational — it never prevents or delays a fetch.
|
|
138
142
|
|
|
@@ -171,4 +175,4 @@ trackRequest("my-request-2");
|
|
|
171
175
|
|
|
172
176
|
- [`useConnectionStatus`](../useConnectionStatus/useConnectionStatus.docs.md) — offline detection (binary online/offline)
|
|
173
177
|
- [`registerInterceptors`](https://github.com/VirtoCommerce/vc-shell/blob/main/framework/core/interceptors/index.ts) — the fetch wrapper that calls `trackRequest`/`untrackRequest`
|
|
174
|
-
- `
|
|
178
|
+
- `framework/assets/styles/index.scss` — the top-edge sweep this class renders as, alongside the `html.vc-offline` rule
|
|
@@ -350,6 +350,10 @@ function helperFunction() {
|
|
|
350
350
|
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
351
351
|
| `provideToolbarService()` | Creates and provides the toolbar service via Vue injection. Idempotent -- returns existing service if already provided. Cleans up via `onScopeDispose`. |
|
|
352
352
|
|
|
353
|
+
!!! note "When you need it"
|
|
354
|
+
|
|
355
|
+
Inside a shell app the framework install already provides the toolbar service, so `provideToolbarService()` returns the existing instance and you do not need to call it. Use it when bootstrapping an isolated tree (stories, tests) that has not installed the framework, the same way as `provideWidgetService()` and `provideDashboardService()`.
|
|
356
|
+
|
|
353
357
|
### IToolbarItem
|
|
354
358
|
|
|
355
359
|
| Property | Type | Required | Description |
|
|
@@ -41,7 +41,6 @@ Every service follows the same architecture:
|
|
|
41
41
|
| **SettingsMenuService** | `createSettingsMenuService()` | `addSettingsMenuItem()` | `ISettingsMenuItem` |
|
|
42
42
|
| **AppBarWidgetService** | `createAppBarWidgetService()` | `addAppBarWidget()` | `AppBarWidget` |
|
|
43
43
|
| **AppBarMobileButtonsService** | `createAppBarMobileButtonsService()` | (direct API) | `AppBarButtonContent` |
|
|
44
|
-
| **GlobalSearchService** | `createGlobalSearchService()` | (direct API) | per-blade search state |
|
|
45
44
|
| **LanguageService** | `createLanguageService()` | (direct API) | locale strings |
|
|
46
45
|
|
|
47
46
|
## Usage
|
|
@@ -315,6 +315,7 @@ All visual properties are customizable through CSS custom properties. Each varia
|
|
|
315
315
|
- `aria-pressed` reflects the `selected` prop for toggle buttons
|
|
316
316
|
- Icon-only buttons **must** include `ariaLabel` for screen reader users
|
|
317
317
|
- Disabled buttons use `pointer-events: none` and `opacity: 0.5` to prevent interaction
|
|
318
|
+
- A button that becomes disabled **while it holds focus** keeps the focus: it switches to `aria-disabled` instead of the native attribute, since a natively disabled element cannot be focused and focus would fall to `<body>` (WCAG 2.4.3). It stays inert, and the user is still on it when the work finishes. Every other disabled button keeps the native attribute and stays out of the tab order.
|
|
318
319
|
- The `click` event calls `e.preventDefault()` -- use `type="submit"` for form submissions
|
|
319
320
|
|
|
320
321
|
## Related Components
|
package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md
CHANGED
|
@@ -50,15 +50,16 @@ const color = ref<string | null>(null);
|
|
|
50
50
|
|
|
51
51
|
## Key Props
|
|
52
52
|
|
|
53
|
-
| Prop | Type | Default | Description
|
|
54
|
-
| ------------------------ | ---------------------- | ----------- |
|
|
55
|
-
| `modelValue` | `string \| null` | `undefined` | Color value via `v-model` (hex string or CSS color name)
|
|
56
|
-
| `label` | `string` | -- | Label text above the field
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `
|
|
61
|
-
| `
|
|
53
|
+
| Prop | Type | Default | Description |
|
|
54
|
+
| ------------------------ | ---------------------- | ----------- | ---------------------------------------------------------------------- |
|
|
55
|
+
| `modelValue` | `string \| null` | `undefined` | Color value via `v-model` (hex string or CSS color name) |
|
|
56
|
+
| `label` | `string` | -- | Label text above the field |
|
|
57
|
+
| `ariaLabel` | `string` | -- | Accessible name for the text input when no visible `label` is provided |
|
|
58
|
+
| `placeholder` | `string` | -- | Placeholder text |
|
|
59
|
+
| `clearable` | `boolean` | `false` | Shows a clear button when a value is present |
|
|
60
|
+
| `size` | `"default" \| "small"` | `"default"` | Field height variant |
|
|
61
|
+
| `error` / `errorMessage` | `boolean` / `string` | -- | Error styling and validation message |
|
|
62
|
+
| `disabled` | `boolean` | `false` | Disables the input and color picker |
|
|
62
63
|
|
|
63
64
|
## Events
|
|
64
65
|
|
package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md
CHANGED
|
@@ -294,26 +294,27 @@ const date = ref<Date | null>(new Date("2025-01-15"));
|
|
|
294
294
|
|
|
295
295
|
## Props
|
|
296
296
|
|
|
297
|
-
| Prop | Type | Default | Description
|
|
298
|
-
| ------------------- | ---------------------------- | ---------------- |
|
|
299
|
-
| `modelValue` | `Date \| string \| null` | `undefined` | Bound value via `v-model`
|
|
300
|
-
| `type` | `"date" \| "datetime-local"` | `"date"` | Date only or date + time mode
|
|
301
|
-
| `label` | `string` | -- | Label text above the field
|
|
302
|
-
| `
|
|
303
|
-
| `
|
|
304
|
-
| `
|
|
305
|
-
| `
|
|
306
|
-
| `
|
|
307
|
-
| `
|
|
308
|
-
| `
|
|
309
|
-
| `
|
|
310
|
-
| `
|
|
311
|
-
| `
|
|
312
|
-
| `
|
|
313
|
-
| `
|
|
314
|
-
| `
|
|
315
|
-
| `
|
|
316
|
-
| `
|
|
297
|
+
| Prop | Type | Default | Description |
|
|
298
|
+
| ------------------- | ---------------------------- | ---------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
299
|
+
| `modelValue` | `Date \| string \| null` | `undefined` | Bound value via `v-model` |
|
|
300
|
+
| `type` | `"date" \| "datetime-local"` | `"date"` | Date only or date + time mode |
|
|
301
|
+
| `label` | `string` | -- | Label text above the field |
|
|
302
|
+
| `ariaLabel` | `string` | -- | Accessible name for the date input when no visible `label` is provided; applied through the library's `ariaLabels.input` option |
|
|
303
|
+
| `placeholder` | `string` | auto (localized) | Placeholder text; auto-generated from locale if not provided |
|
|
304
|
+
| `hint` | `string` | -- | Helper text below the field |
|
|
305
|
+
| `tooltip` | `string` | -- | Tooltip on the label info icon |
|
|
306
|
+
| `clearable` | `boolean` | `false` | Shows a clear button when a date is selected |
|
|
307
|
+
| `loading` | `boolean` | `false` | Shows a spinning loader icon |
|
|
308
|
+
| `size` | `"default" \| "small"` | `"default"` | Field height variant |
|
|
309
|
+
| `required` | `boolean` | `false` | Shows a required indicator |
|
|
310
|
+
| `error` | `boolean` | `false` | Enables error styling |
|
|
311
|
+
| `errorMessage` | `string` | -- | Error message below the field |
|
|
312
|
+
| `disabled` | `boolean` | `false` | Disables the date picker |
|
|
313
|
+
| `autofocus` | `boolean` | `false` | Focus the field on mount |
|
|
314
|
+
| `name` | `string` | `"Field"` | HTML name attribute |
|
|
315
|
+
| `multilanguage` | `boolean` | `false` | Shows language badge on the label |
|
|
316
|
+
| `currentLanguage` | `string` | -- | Language code for the badge |
|
|
317
|
+
| `datePickerOptions` | `VueDatePickerProps` | -- | Pass-through options to VueDatePicker |
|
|
317
318
|
|
|
318
319
|
## Events
|
|
319
320
|
|
|
@@ -671,32 +671,33 @@ VcInput blocks the minus key for both `number` and `integer` types. If you need
|
|
|
671
671
|
|
|
672
672
|
### Props
|
|
673
673
|
|
|
674
|
-
| Prop | Type | Default | Description
|
|
675
|
-
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
|
676
|
-
| `modelValue` | `string \| number \| Date \| null` | `undefined` | Bound value via `v-model`
|
|
677
|
-
| `type` | `"text" \| "password" \| "email" \| "tel" \| "url" \| "time" \| "number" \| "integer" \| "date" \| "datetime-local" \| "color"` | `"text"` | Input type. `date`/`datetime-local` delegate to VcDatePicker; `color` delegates to VcColorInput
|
|
678
|
-
| `label` | `string` | -- | Label text displayed above the field
|
|
679
|
-
| `placeholder` | `string` | -- | Placeholder text inside the field
|
|
680
|
-
| `hint` | `string` | -- | Help text displayed below the field
|
|
681
|
-
| `tooltip` | `string` | -- | Tooltip text shown on hover next to the label
|
|
682
|
-
| `prefix` | `string` | -- | Static text rendered before the input value
|
|
683
|
-
| `suffix` | `string` | -- | Static text rendered after the input value
|
|
684
|
-
| `name` | `string` | `"Field"` | HTML `name` attribute on the native input
|
|
685
|
-
| `clearable` | `boolean` | `false` | Shows a clear (x) button when the field has a value
|
|
686
|
-
| `disabled` | `boolean` | `false` | Disables the input (also inherits from `VcInputGroup` context)
|
|
687
|
-
| `required` | `boolean` | `false` | Adds a red asterisk to the label (visual only, no validation)
|
|
688
|
-
| `loading` | `boolean` | `false` | Shows a spinning loader icon inside the field
|
|
689
|
-
| `autofocus` | `boolean` | `false` | Auto-focuses the input on mount
|
|
690
|
-
| `autocomplete` | `string` | -- | Autofill hint set on the native input (e.g. `"username"`, `"current-password"`)
|
|
691
|
-
| `
|
|
692
|
-
| `
|
|
693
|
-
| `
|
|
694
|
-
| `
|
|
695
|
-
| `
|
|
696
|
-
| `
|
|
697
|
-
| `
|
|
698
|
-
| `
|
|
699
|
-
| `
|
|
674
|
+
| Prop | Type | Default | Description |
|
|
675
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
676
|
+
| `modelValue` | `string \| number \| Date \| null` | `undefined` | Bound value via `v-model` |
|
|
677
|
+
| `type` | `"text" \| "password" \| "email" \| "tel" \| "url" \| "time" \| "number" \| "integer" \| "date" \| "datetime-local" \| "color"` | `"text"` | Input type. `date`/`datetime-local` delegate to VcDatePicker; `color` delegates to VcColorInput |
|
|
678
|
+
| `label` | `string` | -- | Label text displayed above the field |
|
|
679
|
+
| `placeholder` | `string` | -- | Placeholder text inside the field |
|
|
680
|
+
| `hint` | `string` | -- | Help text displayed below the field |
|
|
681
|
+
| `tooltip` | `string` | -- | Tooltip text shown on hover next to the label |
|
|
682
|
+
| `prefix` | `string` | -- | Static text rendered before the input value |
|
|
683
|
+
| `suffix` | `string` | -- | Static text rendered after the input value |
|
|
684
|
+
| `name` | `string` | `"Field"` | HTML `name` attribute on the native input |
|
|
685
|
+
| `clearable` | `boolean` | `false` | Shows a clear (x) button when the field has a value |
|
|
686
|
+
| `disabled` | `boolean` | `false` | Disables the input (also inherits from `VcInputGroup` context) |
|
|
687
|
+
| `required` | `boolean` | `false` | Adds a red asterisk to the label (visual only, no validation) |
|
|
688
|
+
| `loading` | `boolean` | `false` | Shows a spinning loader icon inside the field |
|
|
689
|
+
| `autofocus` | `boolean` | `false` | Auto-focuses the input on mount |
|
|
690
|
+
| `autocomplete` | `string` | -- | Autofill hint set on the native input (e.g. `"username"`, `"current-password"`) |
|
|
691
|
+
| `ariaLabel` | `string` | -- | Accessible name used when no visible `label` is provided; forwarded to the delegated date picker and color input too |
|
|
692
|
+
| `error` | `boolean` | `false` | Activates error styling (red border and ring) |
|
|
693
|
+
| `errorMessage` | `string` | -- | Error text shown below the field; also activates error styling when truthy |
|
|
694
|
+
| `debounce` | `string \| number` | -- | Delay in ms before emitting model updates |
|
|
695
|
+
| `maxlength` | `string \| number` | `"1024"` | Maximum character length |
|
|
696
|
+
| `step` | `string` | `"1"` | Step granularity for number inputs |
|
|
697
|
+
| `size` | `"default" \| "small"` | `"default"` | Field height variant (36px / 32px) |
|
|
698
|
+
| `multilanguage` | `boolean` | `false` | Shows a language indicator badge on the label |
|
|
699
|
+
| `currentLanguage` | `string` | -- | Language code to display in the multilanguage badge |
|
|
700
|
+
| `datePickerOptions` | `VueDatePickerProps` | -- | Options forwarded to VcDatePicker (only when `type` is `date` or `datetime-local`) |
|
|
700
701
|
|
|
701
702
|
### Events
|
|
702
703
|
|
package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md
CHANGED
|
@@ -268,6 +268,7 @@ Replace the default dropdown toggle with a custom element using the `button` slo
|
|
|
268
268
|
| `name` | `string` | -- | HTML name attribute for the input |
|
|
269
269
|
| `multilanguage` | `boolean` | `false` | Enable multilanguage editing (forwarded to VcSelect) |
|
|
270
270
|
| `currentLanguage` | `string` | -- | Active language for multilanguage mode (forwarded to VcSelect) |
|
|
271
|
+
| `ariaLabel` | `string` | -- | Accessible name for the value input when no visible `label` is provided |
|
|
271
272
|
|
|
272
273
|
## Events
|
|
273
274
|
|
|
@@ -59,6 +59,7 @@ const open = ref(false);
|
|
|
59
59
|
| `contentScrollable` | `boolean` | `true` | Enable scrolling in the content area |
|
|
60
60
|
| `closeOnClickOutside` | `boolean` | `true` | Close when clicking outside |
|
|
61
61
|
| `closeOnEscape` | `boolean` | `true` | Close on Escape key |
|
|
62
|
+
| `inert` | `boolean` | `false` | Hide the panel from assistive technology and keyboard focus while something covers it. The panel is teleported, so it does not inherit `inert` from an ancestor — pass it explicitly |
|
|
62
63
|
|
|
63
64
|
## Events
|
|
64
65
|
|
|
@@ -143,7 +144,7 @@ The panel's z-index comes from the global `--z-critical-floating-panel` token an
|
|
|
143
144
|
- Escape key dismisses the panel (configurable via `closeOnEscape`)
|
|
144
145
|
- Click-outside detection uses `pointerdown` for reliable z-index handling
|
|
145
146
|
- Supports nested panels via an internal anchor registry -- child panel clicks do not close parent panels
|
|
146
|
-
- Exposes `close()`
|
|
147
|
+
- Exposes `close()` and `panelEl` (the teleported panel element) via template ref
|
|
147
148
|
|
|
148
149
|
## Related Components
|
|
149
150
|
|
|
@@ -157,7 +158,7 @@ The panel's z-index comes from the global `--z-critical-floating-panel` token an
|
|
|
157
158
|
- 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.
|
|
158
159
|
- `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.
|
|
159
160
|
- 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.
|
|
160
|
-
- The panel exposes
|
|
161
|
+
- The panel exposes `close()` and `panelEl` via `defineExpose` for use with template refs. `panelEl` is the teleported panel itself — a call site managing focus needs it to answer "is focus still inside?", and cannot reach it any other way.
|
|
161
162
|
- `useTeleportTarget` resolves the teleport destination (typically `body`) respecting any custom portal container.
|
|
162
163
|
|
|
163
164
|
<!-- internal:end -->
|
|
@@ -234,20 +234,23 @@ Use the `"star-and-text"` or `"text"` variant in table cell slots for a compact
|
|
|
234
234
|
|
|
235
235
|
## Props
|
|
236
236
|
|
|
237
|
-
| Prop
|
|
238
|
-
|
|
|
239
|
-
| `modelValue`
|
|
240
|
-
| `max`
|
|
241
|
-
| `variant`
|
|
242
|
-
| `label`
|
|
243
|
-
| `tooltip`
|
|
244
|
-
| `placeholder`
|
|
237
|
+
| Prop | Type | Default | Description |
|
|
238
|
+
| -------------- | -------------------------------------- | --------- | ----------------------------------------------------------------------- |
|
|
239
|
+
| `modelValue` | `number` | -- | Current rating value to display |
|
|
240
|
+
| `max` | `number` | `5` | Maximum rating value (defines the scale) |
|
|
241
|
+
| `variant` | `"stars" \| "star-and-text" \| "text"` | `"stars"` | Display variant |
|
|
242
|
+
| `label` | `string` | -- | Field label text above the rating |
|
|
243
|
+
| `tooltip` | `string` | -- | Tooltip shown on the label |
|
|
244
|
+
| `placeholder` | `string` | -- | Text shown when `modelValue` is falsy |
|
|
245
|
+
| `error` | `boolean` | -- | Marks the field invalid without a message |
|
|
246
|
+
| `errorMessage` | `string` | -- | Validation message shown below the rating; also marks the field invalid |
|
|
245
247
|
|
|
246
248
|
## Slots
|
|
247
249
|
|
|
248
|
-
| Slot | Scope | Description
|
|
249
|
-
| --------- | ----- |
|
|
250
|
-
| `details` | -- | Additional content below the rating (available in `star-and-text` and `text` variants)
|
|
250
|
+
| Slot | Scope | Description |
|
|
251
|
+
| --------- | ----- | --------------------------------------------------------------------------------------------------------------------------------------- |
|
|
252
|
+
| `details` | -- | Additional content below the rating (available in `star-and-text` and `text` variants) |
|
|
253
|
+
| `error` | -- | Replaces the default validation message element. Keep the slotted element's `id`, or the control's `aria-describedby` points at nothing |
|
|
251
254
|
|
|
252
255
|
## CSS Variables
|
|
253
256
|
|
|
@@ -266,6 +269,8 @@ Use the `"star-and-text"` or `"text"` variant in table cell slots for a compact
|
|
|
266
269
|
- When no value is present, the `aria-label` falls back to the placeholder text or "No rating".
|
|
267
270
|
- The label is rendered via `VcLabel` with optional tooltip, maintaining consistent label semantics.
|
|
268
271
|
- Star icons are decorative and do not receive focus since the component is display-only.
|
|
272
|
+
- A validation message is rendered below the rating and referenced from the control through `aria-describedby`, so a screen reader is told what is wrong rather than only that something is.
|
|
273
|
+
- Invalid state comes from `useFormField`, so it reflects a surrounding `VcInputGroup` as well as the component's own `error` / `errorMessage`.
|
|
269
274
|
|
|
270
275
|
## Related Components
|
|
271
276
|
|
|
@@ -251,6 +251,7 @@ const description = ref<string>("");
|
|
|
251
251
|
| `name` | `string` | `"Field"` | Field name used for validation/id generation (not applied as an HTML name attribute on the textarea) |
|
|
252
252
|
| `multilanguage` | `boolean` | `false` | Shows language badge on the label |
|
|
253
253
|
| `currentLanguage` | `string` | -- | Language code displayed in the badge |
|
|
254
|
+
| `ariaLabel` | `string` | -- | Accessible name used when no visible `label` is provided |
|
|
254
255
|
|
|
255
256
|
## Events
|
|
256
257
|
|
|
@@ -79,7 +79,7 @@ VcApp orchestrates several internal systems:
|
|
|
79
79
|
1. **Layout** -- switches between `DesktopLayout` (sidebar) and `MobileLayout` (top bar) based on viewport width. The breakpoint is managed by the framework's responsive detection system.
|
|
80
80
|
2. **Blade Navigation** -- renders `VcBladeNavigation` for the stacked panel workspace. Blades open to the right and scroll horizontally.
|
|
81
81
|
3. **Module Loading** -- consumes `DynamicModulesKey` for runtime module registration; shows error notifications on failure. Modules declare routes, menu items, and services.
|
|
82
|
-
4. **Services** --
|
|
82
|
+
4. **Services** -- provides the shell-scoped services via `useShellBootstrap`: dashboard, app bar mobile buttons, and the AI agent when configured. Menu, toolbar, widget and settings services are provided earlier, by the framework install. All are reachable from child components through provide/inject.
|
|
83
83
|
|
|
84
84
|
<!-- internal:end -->
|
|
85
85
|
|