@vc-shell/vc-app-skill 2.0.0-alpha.28 → 2.0.0-alpha.29

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/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # [2.0.0-alpha.29](https://github.com/VirtoCommerce/vc-shell/compare/v2.0.0-alpha.28...v2.0.0-alpha.29) (2026-03-26)
2
+
3
+ **Note:** Version bump only for package @vc-shell/vc-app-skill
4
+
1
5
  # [2.0.0-alpha.28](https://github.com/VirtoCommerce/vc-shell/compare/v2.0.0-alpha.27...v2.0.0-alpha.28) (2026-03-26)
2
6
 
3
7
  **Note:** Version bump only for package @vc-shell/vc-app-skill
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vc-shell/vc-app-skill",
3
- "version": "2.0.0-alpha.28",
3
+ "version": "2.0.0-alpha.29",
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.0.0-alpha.28
1
+ 2.0.0-alpha.29
@@ -1 +1 @@
1
- Synced from framework at commit 8bc5a83cc on 2026-03-26T07:20:52.461Z
1
+ Synced from framework at commit d863d7620 on 2026-03-26T14:29:54.970Z
@@ -17,7 +17,7 @@ The pattern follows a "define once, inject anywhere" approach: the blade compone
17
17
  // In a blade's <script setup>
18
18
  import { defineBladeContext, injectBladeContext } from '@vc-shell/framework';
19
19
 
20
- // Provide context (blade component)
20
+ // Provide context refs/computeds are auto-unwrapped for consumers
21
21
  defineBladeContext({ item, disabled, loading });
22
22
 
23
23
  // Or with a computed for selective exposure
@@ -29,7 +29,9 @@ defineBladeContext(computed(() => ({ id: item.value?.id })));
29
29
  import { injectBladeContext } from '@vc-shell/framework';
30
30
 
31
31
  const ctx = injectBladeContext();
32
+ // Refs are already unwrapped — access values directly, no .value needed
32
33
  const entityId = computed(() => ctx.value.id as string);
34
+ const item = computed(() => ctx.value.item as { id: string; name: string });
33
35
  ```
34
36
 
35
37
  ## API
@@ -90,6 +92,7 @@ defineBladeContext(computed(() => ({
90
92
 
91
93
  ## Details
92
94
 
95
+ - **Automatic ref unwrapping**: `defineBladeContext` shallow-unwraps all ref/computed values in the provided object. Consumers get plain values directly (`ctx.value.item` instead of `ctx.value.item.value`). This works reactively — when the source ref changes, the context updates automatically.
93
96
  - **Reactivity**: The provided context is always wrapped in a `computed`, so consumers receive a `ComputedRef` regardless of whether the provider passed a plain object, a ref, or a getter. Changes propagate automatically.
94
97
  - **Injection key**: Uses `BladeContextKey` from `framework/injection-keys.ts`. This is a framework-level Symbol, so there is no risk of key collision with application code.
95
98
  - **Error handling**: `injectBladeContext` throws an `InjectionError` with a descriptive message if called outside a blade component tree. This fails fast during development rather than silently returning `undefined`.
@@ -112,7 +112,7 @@ A complete example of an external widget that shows an unread message count and
112
112
  **1. Register the external widget (module index.ts):**
113
113
 
114
114
  ```typescript
115
- import { createAppModule, registerExternalWidget, IBladeInstance } from "@vc-shell/framework";
115
+ import { createAppModule, registerExternalWidget, BladeDescriptor } from "@vc-shell/framework";
116
116
  import { markRaw } from "vue";
117
117
  import { MessageWidget } from "./components/widgets";
118
118
 
@@ -120,7 +120,7 @@ registerExternalWidget({
120
120
  id: "MessageWidget",
121
121
  component: markRaw(MessageWidget),
122
122
  targetBlades: ["ProductDetails", "OrderDetails"],
123
- isVisible: (blade?: IBladeInstance) => !!blade?.param,
123
+ isVisible: (blade?: BladeDescriptor) => !!blade?.param,
124
124
  });
125
125
  ```
126
126
 
@@ -21,7 +21,7 @@ This centralized approach has several advantages:
21
21
  | Key | Type | Description |
22
22
  |-----|------|-------------|
23
23
  | `NavigationViewLocationKey` | `BladeVNode` | Current blade VNode location in navigation |
24
- | `BladeInstanceKey` | `ComputedRef<IBladeInstance>` | Current blade instance metadata |
24
+ | `BladeDescriptorKey` | `ComputedRef<BladeDescriptor>` | Current blade descriptor metadata |
25
25
  | `BladeBackButtonKey` | `Component \| undefined` | Custom back button component for a blade |
26
26
  | `BladeDataKey` | *(from blade-navigation types)* | Data passed between parent/child blades |
27
27
  | `BladeContextKey` | `ComputedRef<Record<string, unknown>>` | Blade-exposed context for widgets/extensions |
@@ -83,7 +83,7 @@ This centralized approach has several advantages:
83
83
  | Deprecated | Use Instead |
84
84
  |------------|-------------|
85
85
  | `navigationViewLocation` | `NavigationViewLocationKey` |
86
- | `BladeInstance` | `BladeInstanceKey` |
86
+ | `BladeDescriptor` | `BladeDescriptorKey` |
87
87
  | `NotificationTemplatesSymbol` | `NotificationTemplatesKey` |
88
88
  | `BLADE_BACK_BUTTON` | `BladeBackButtonKey` |
89
89
  | `TOOLBAR_SERVICE` | `ToolbarServiceKey` |
@@ -355,7 +355,7 @@ interface IBladeToolbar {
355
355
  clickHandler?(): void;
356
356
  disabled?: boolean | ComputedRef<boolean>;
357
357
  isVisible?: boolean | Ref<boolean> | ComputedRef<boolean>
358
- | ((blade?: IBladeInstance) => boolean);
358
+ | ((blade?: BladeDescriptor) => boolean);
359
359
  separator?: "left" | "right" | "both";
360
360
  }
361
361
  ```
@@ -1,135 +0,0 @@
1
- # PopupHandler
2
-
3
- A global popup management system that renders modal dialogs on demand. Installed as a Vue plugin (`VcPopupHandler`), it provides the `usePopup` composable for programmatic popup control. Popups are rendered in a dedicated container at the app root level, ensuring they overlay all other content including blades and sidebars.
4
-
5
- The system supports both built-in dialog types (confirmation, error, info) and fully custom popup components with typed props and emits.
6
-
7
- ## When to Use
8
-
9
- - To show confirmation dialogs before destructive actions (delete, discard, bulk operations)
10
- - To display error or info messages in a modal overlay
11
- - To open custom popup components with typed props and emits
12
- - Do NOT use for passive feedback (use `notification()` toast instead)
13
- - Do NOT use for navigation (use blade navigation instead)
14
-
15
- ## Basic Usage
16
-
17
- ```ts
18
- import { usePopup } from "@vc-shell/framework";
19
-
20
- const { showConfirmation, showError, showInfo } = usePopup();
21
-
22
- // Confirmation dialog (returns Promise<boolean>)
23
- const confirmed = await showConfirmation("Delete this item?");
24
-
25
- // Error popup
26
- showError("Something went wrong.");
27
-
28
- // Info popup
29
- showInfo("Operation completed successfully.");
30
- ```
31
-
32
- ### Custom Popup Component
33
-
34
- ```ts
35
- import { usePopup } from "@vc-shell/framework";
36
- import MyDialog from "./MyDialog.vue";
37
-
38
- const { open, close } = usePopup({
39
- component: MyDialog,
40
- props: { title: "Custom Dialog" },
41
- emits: { onConfirm: () => close() },
42
- });
43
-
44
- open();
45
- ```
46
-
47
- ## API (`usePopup`)
48
-
49
- | Method | Signature | Description |
50
- |--------|-----------|-------------|
51
- | `open` | `() => void` | Push the popup onto the stack and render it |
52
- | `close` | `() => void` | Remove the popup from the stack |
53
- | `showConfirmation` | `(message: string \| Ref<string>) => Promise<boolean>` | Warning dialog with confirm/cancel |
54
- | `showError` | `(message: string \| Ref<string>) => void` | Error-styled popup |
55
- | `showInfo` | `(message: string \| Ref<string>) => void` | Info-styled popup |
56
-
57
- ## Recipe: Delete Confirmation Before API Call
58
-
59
- The most common popup pattern is asking for confirmation before a destructive action:
60
-
61
- ```vue
62
- <script setup lang="ts">
63
- import { usePopup, notification } from "@vc-shell/framework";
64
-
65
- const { showConfirmation } = usePopup();
66
-
67
- async function deleteProduct(id: string) {
68
- const confirmed = await showConfirmation(
69
- "Are you sure you want to delete this product? This action cannot be undone."
70
- );
71
-
72
- if (!confirmed) return;
73
-
74
- try {
75
- await api.deleteProduct(id);
76
- notification("Product deleted.", { type: "success" });
77
- closeSelf();
78
- } catch (error) {
79
- showError(error.message || "Failed to delete product.");
80
- }
81
- }
82
- </script>
83
- ```
84
-
85
- ## Recipe: Custom Popup with Form
86
-
87
- Create a custom popup component for complex interactions:
88
-
89
- ```ts
90
- // Using a custom popup component
91
- import { usePopup } from "@vc-shell/framework";
92
- import AddNotePopup from "./AddNotePopup.vue";
93
-
94
- const { open, close } = usePopup({
95
- component: AddNotePopup,
96
- props: { entityId: "prod-1" },
97
- emits: {
98
- onConfirm: async (note: string) => {
99
- await api.addNote(entityId, note);
100
- close();
101
- notification("Note added.", { type: "success" });
102
- },
103
- onCancel: () => close(),
104
- },
105
- });
106
-
107
- open();
108
- ```
109
-
110
- ## Key Parts
111
-
112
- | Export | Description |
113
- |--------|-------------|
114
- | `VcPopupHandler` | Vue plugin that installs the popup registry |
115
- | `VcPopupContainer` | Renders all active popups (placed once in the app root) |
116
- | `usePopup` | Composable for opening/closing popups |
117
-
118
- ## Details
119
-
120
- - **Popup stack**: Multiple popups can be open simultaneously, stacking with the most recent on top.
121
- - **Promise-based confirmation**: `showConfirmation` returns a `Promise<boolean>` that resolves to `true` on confirm, `false` on cancel.
122
- - **Plugin requirement**: `VcPopupHandler` must be installed as a Vue plugin, and `VcPopupContainer` must be mounted in the component tree. Both are automatically set up in the standard vc-shell app shell.
123
-
124
- ## Tips
125
-
126
- - Always `await` the result of `showConfirmation` before proceeding with the destructive action.
127
- - For simple yes/no questions, use `showConfirmation`. For forms or complex interactions, create a custom popup component.
128
- - The `usePopup` composable can be called without arguments (for built-in dialogs) or with a component config (for custom popups).
129
- - Avoid nesting popups more than 2 levels deep. Consider blades for complex multi-step workflows.
130
-
131
- ## Related Components
132
-
133
- - **VcPopup** - The default popup shell component (header, content, actions)
134
- - **VcBlade** - For panel-based UI; use popups for modal interruptions
135
- - **notification()** - For passive, non-blocking feedback