@vc-shell/vc-app-skill 2.6.0-rc.1-pr368.9a75b13 → 2.6.1-pr374.43f2115
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/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +8 -8
- package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +2 -2
- package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +22 -18
- package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +16 -11
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vc-shell/vc-app-skill",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.1-pr374.43f2115",
|
|
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.6.
|
|
1
|
+
2.6.1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
Synced from framework at commit
|
|
1
|
+
Synced from framework at commit ce2647528 on 2026-09-29T10:57:40.943Z
|
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
|
|
|
@@ -50,12 +50,12 @@ None. The composable reads breakpoint state from the framework's provide/inject
|
|
|
50
50
|
| Property | Type | Default | Description |
|
|
51
51
|
| ----------- | -------------- | ------- | --------------------------------------------------------------------- |
|
|
52
52
|
| `isMobile` | `Ref<boolean>` | `false` | `true` when viewport width < 1024px |
|
|
53
|
-
| `isDesktop` | `Ref<boolean>` | `true` | `true` when viewport width
|
|
53
|
+
| `isDesktop` | `Ref<boolean>` | `true` | `true` when viewport width >= 1024px |
|
|
54
54
|
| `isPhone` | `Ref<boolean>` | `false` | `true` when viewport width < 480px |
|
|
55
55
|
| `isTablet` | `Ref<boolean>` | `false` | `true` when 480px <= viewport width < 1024px |
|
|
56
56
|
| `isTouch` | `boolean` | `false` | `true` on touch-capable devices (not reactive — set once at app init) |
|
|
57
57
|
|
|
58
|
-
Breakpoint thresholds: phone < 480px, tablet 480–1023px, desktop
|
|
58
|
+
Breakpoint thresholds: phone < 480px, tablet 480–1023px, desktop >= 1024px (bound to `bp.greaterOrEqual("desktop")`, so exactly 1024px is desktop). These match the framework's `setupBreakpoints()` configuration.
|
|
59
59
|
|
|
60
60
|
Note: `isMobile` is the union of `isPhone` and `isTablet` — it covers all viewports below the desktop threshold.
|
|
61
61
|
|
|
@@ -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
|
|
@@ -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
|
|