@vc-shell/vc-app-skill 2.0.11 → 2.1.0-pr248.6401a93
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/ui/components/organisms/vc-data-table/vc-data-table.docs.md +56 -36
- package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +44 -54
- package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +16 -21
- package/runtime/knowledge/migration-prompts/datatable-migration.md +27 -18
- package/runtime/knowledge/patterns/list-blade-pattern.md +85 -41
- package/runtime/knowledge/docs/core/blade-navigation/table-query-state/useTableQueryState.docs.md +0 -95
- package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +0 -34
- package/runtime/knowledge/docs/core/notifications/composables/useBladeNotifications.docs.md +0 -184
- package/runtime/knowledge/docs/core/notifications/composables/useBroadcastFilter.docs.md +0 -117
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md +0 -150
- package/runtime/knowledge/docs/core/notifications/composables/useNotificationStore.docs.md +0 -113
- package/runtime/knowledge/docs/modules/assets/assets-details.docs.md +0 -123
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/dashboard-widget-skeleton.docs.md +0 -33
package/runtime/knowledge/docs/core/notifications/composables/useNotificationContext.docs.md
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: useNotificationContext
|
|
3
|
-
category: composables
|
|
4
|
-
group: notifications
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# useNotificationContext
|
|
8
|
-
|
|
9
|
-
Reads the current `PushNotification` payload inside a custom notification template. The framework provides the message via Vue's `inject()` from the dropdown or toast surface that hosts the template — the composable returns a reactive `ComputedRef` over it.
|
|
10
|
-
|
|
11
|
-
This is the one piece you write when a notification type registered with `defineAppModule({ notifications: { Type: { template } } })` needs a richer rendering than the default `NotificationTemplate` chrome — for example, formatting a domain-specific status, deriving a colored accent, or wiring a click handler that opens the relevant blade.
|
|
12
|
-
|
|
13
|
-
## When to use
|
|
14
|
-
|
|
15
|
-
- Implementing the `template` component for a notification type registered through `defineAppModule({ notifications })`.
|
|
16
|
-
- Reading typed payload fields (status, entity name, job id) to drive the template's layout, color, or actions.
|
|
17
|
-
- When NOT to use: anywhere outside a notification template. The composable throws if the inject context is not present.
|
|
18
|
-
|
|
19
|
-
## Quick Start
|
|
20
|
-
|
|
21
|
-
```vue
|
|
22
|
-
<script lang="ts" setup>
|
|
23
|
-
import { PushNotification, NotificationTemplate, useNotificationContext } from "@vc-shell/framework";
|
|
24
|
-
import { computed } from "vue";
|
|
25
|
-
|
|
26
|
-
interface IOrderPushNotification extends PushNotification {
|
|
27
|
-
orderId: string;
|
|
28
|
-
total: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const notificationRef = useNotificationContext<IOrderPushNotification>();
|
|
32
|
-
const notification = computed(() => notificationRef.value);
|
|
33
|
-
</script>
|
|
34
|
-
|
|
35
|
-
<template>
|
|
36
|
-
<NotificationTemplate
|
|
37
|
-
:title="notification.title ?? ''"
|
|
38
|
-
:notification="notification"
|
|
39
|
-
>
|
|
40
|
-
<p>Order {{ notification.orderId }} — ${{ notification.total }}</p>
|
|
41
|
-
</NotificationTemplate>
|
|
42
|
-
</template>
|
|
43
|
-
```
|
|
44
|
-
|
|
45
|
-
## API
|
|
46
|
-
|
|
47
|
-
### Parameters
|
|
48
|
-
|
|
49
|
-
None. The composable is always called without arguments. Generic type parameter narrows the payload shape:
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
function useNotificationContext<T extends PushNotification = PushNotification>(): ComputedRef<T>;
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### Returns
|
|
56
|
-
|
|
57
|
-
`ComputedRef<T>` — reactive reference to the current `PushNotification` (or your extended subtype via the generic). Update reactively if the same template instance is reused for a refreshed payload (for example, when a progress message is updated through `notification.update`).
|
|
58
|
-
|
|
59
|
-
## Common patterns
|
|
60
|
-
|
|
61
|
-
### Compute display strings from payload fields
|
|
62
|
-
|
|
63
|
-
```vue
|
|
64
|
-
<script lang="ts" setup>
|
|
65
|
-
import { PushNotification, useNotificationContext, NotificationTemplate } from "@vc-shell/framework";
|
|
66
|
-
import { computed } from "vue";
|
|
67
|
-
import { useI18n } from "vue-i18n";
|
|
68
|
-
|
|
69
|
-
interface IProductPush extends PushNotification {
|
|
70
|
-
productName?: string;
|
|
71
|
-
newStatus?: string;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const ctx = useNotificationContext<IProductPush>();
|
|
75
|
-
const notification = computed(() => ctx.value);
|
|
76
|
-
const { t } = useI18n({ useScope: "global" });
|
|
77
|
-
|
|
78
|
-
const title = computed(() => (notification.value.productName ? `${t("PRODUCTS.PUSH.PRODUCT")} "${notification.value.productName}" ${t("PRODUCTS.PUSH.UPDATE")}` : (notification.value.title ?? "")));
|
|
79
|
-
</script>
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
### Open a blade on click
|
|
83
|
-
|
|
84
|
-
```vue
|
|
85
|
-
<script lang="ts" setup>
|
|
86
|
-
import { useBlade, useNotificationContext, NotificationTemplate } from "@vc-shell/framework";
|
|
87
|
-
import { computed } from "vue";
|
|
88
|
-
|
|
89
|
-
const { openBlade } = useBlade();
|
|
90
|
-
const ctx = useNotificationContext<IOrderPush>();
|
|
91
|
-
const notification = computed(() => ctx.value);
|
|
92
|
-
|
|
93
|
-
function onClick() {
|
|
94
|
-
if (!notification.value.orderId) return;
|
|
95
|
-
openBlade({ name: "OrderDetails", param: notification.value.orderId });
|
|
96
|
-
}
|
|
97
|
-
</script>
|
|
98
|
-
|
|
99
|
-
<template>
|
|
100
|
-
<NotificationTemplate
|
|
101
|
-
:title="notification.title ?? ''"
|
|
102
|
-
:notification="notification"
|
|
103
|
-
@click="onClick"
|
|
104
|
-
>
|
|
105
|
-
<p>{{ notification.description }}</p>
|
|
106
|
-
</NotificationTemplate>
|
|
107
|
-
</template>
|
|
108
|
-
```
|
|
109
|
-
|
|
110
|
-
`NotificationTemplate` re-emits the click event so the host (dropdown row, toast) can close itself before your handler runs.
|
|
111
|
-
|
|
112
|
-
### Color the template by status
|
|
113
|
-
|
|
114
|
-
```ts
|
|
115
|
-
const notificationStyle = computed(() => {
|
|
116
|
-
switch (notification.value.newStatus) {
|
|
117
|
-
case "Approved":
|
|
118
|
-
return { color: "var(--success-400)", icon: "lucide-check-circle" };
|
|
119
|
-
case "RequestChanges":
|
|
120
|
-
return { color: "var(--danger-400)", icon: "lucide-alert-circle" };
|
|
121
|
-
case "WaitForApproval":
|
|
122
|
-
return { color: "var(--warning-600)", icon: "lucide-clock" };
|
|
123
|
-
default:
|
|
124
|
-
return { color: "var(--primary-400)", icon: "lucide-bell" };
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
`NotificationTemplate` accepts `:color` and `:icon` props that line up with these computeds — the dropdown row and the toast use the same template, so the styling stays consistent across surfaces.
|
|
130
|
-
|
|
131
|
-
## Where the template runs
|
|
132
|
-
|
|
133
|
-
Notification templates render in two places:
|
|
134
|
-
|
|
135
|
-
- **In the bell dropdown**, as one row in the history list.
|
|
136
|
-
- **As a toast**, when the type's `toast.mode` is `"auto"` or `"progress"` (set the mode to `"silent"` to render only in the dropdown).
|
|
137
|
-
|
|
138
|
-
The template component must be **the same** in both — register it once on `defineAppModule({ notifications })` and the framework reuses it everywhere.
|
|
139
|
-
|
|
140
|
-
## Tips
|
|
141
|
-
|
|
142
|
-
- **Always type the generic.** `useNotificationContext<MyPushType>()` enables autocompletion on payload fields. Without it everything degrades to `PushNotification`.
|
|
143
|
-
- **`computed(() => ctx.value)` is idiomatic** in the example apps because consumers want a regular `Ref` shape to pass into child components and template bindings. Direct access via `ctx.value` is fine too.
|
|
144
|
-
- **Do not subscribe inside a template.** The template renders one message; if you need to react to other notifications, do that in a blade with `useBladeNotifications`.
|
|
145
|
-
|
|
146
|
-
## Related
|
|
147
|
-
|
|
148
|
-
- [useBladeNotifications](./useBladeNotifications.md) — subscribe to types inside a blade.
|
|
149
|
-
- [useNotificationStore](./useNotificationStore.md) — access the underlying store.
|
|
150
|
-
- [Notifications concept page.](../../concepts/notifications.md)
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: useNotificationStore
|
|
3
|
-
category: composables
|
|
4
|
-
group: notifications
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
# useNotificationStore
|
|
8
|
-
|
|
9
|
-
!!! warning "Advanced — most apps do not need this"
|
|
10
|
-
Reach for [useBladeNotifications](./useBladeNotifications.md), [useBroadcastFilter](./useBroadcastFilter.md), and the `notifications` option on `defineAppModule` first. The bell dropdown, unread badge, and toast pipeline are already wired by the shell. This composable is an **escape hatch** for the small set of cases where those facades do not fit.
|
|
11
|
-
|
|
12
|
-
Returns the singleton store that backs the framework's notification system. Direct access exposes the full reactive state plus low-level actions: subscribing, ingesting synthetic messages, controlling the broadcast filter, paging history.
|
|
13
|
-
|
|
14
|
-
## When to use
|
|
15
|
-
|
|
16
|
-
There are only two cases where this composable belongs in app code:
|
|
17
|
-
|
|
18
|
-
- **A test or scripted harness** that needs to push synthetic messages through the same pipeline SignalR uses, via `ingest`. Real-time production code never calls `ingest` directly.
|
|
19
|
-
- **A custom shell** that replaces the framework's bell dropdown entirely — typically a module-federation host with its own chrome — and therefore needs to bind to `history`, `unreadCount`, and `markAllAsRead` outside the default surface. Apps that use the standard `VcApp` shell do not need this; the dropdown is already there.
|
|
20
|
-
|
|
21
|
-
For everything else — reacting in a blade, gating broadcasts, registering types, displaying a toast — use the facades. Direct store mutations can bypass invariants the facades enforce (broadcast filter, scope-aware cleanup, type validation).
|
|
22
|
-
|
|
23
|
-
## Quick Start
|
|
24
|
-
|
|
25
|
-
```ts
|
|
26
|
-
import { useNotificationStore } from "@vc-shell/framework";
|
|
27
|
-
|
|
28
|
-
const store = useNotificationStore();
|
|
29
|
-
|
|
30
|
-
await store.loadHistory(50);
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## API
|
|
34
|
-
|
|
35
|
-
The store exposes the full reactive state plus actions. The shape is summarized below; the underlying types live in `core/notifications/store.ts` and `core/notifications/types.ts`.
|
|
36
|
-
|
|
37
|
-
| Member | Type | Description |
|
|
38
|
-
| ------------------------ | ------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
39
|
-
| `registry` | `Map<string, NotificationTypeConfig>` | Notification types registered through `defineAppModule({ notifications })`. |
|
|
40
|
-
| `history` | `Ref<PushNotification[]>` | Full history (server-loaded plus ingested), newest first. |
|
|
41
|
-
| `realtime` | `Ref<PushNotification[]>` | Session-only realtime queue from the SignalR hub. Drives `messages` in `useBladeNotifications`. |
|
|
42
|
-
| `unreadCount` | `ComputedRef<number>` | Count of unread items in `history`. Drives the bell badge. |
|
|
43
|
-
| `hasUnread` | `ComputedRef<boolean>` | Convenience boolean over `unreadCount`. |
|
|
44
|
-
| `registerType(t, cfg)` | `(string, NotificationTypeConfig) => void` | Register a type. Called by the framework when `defineAppModule({ notifications })` runs — rarely needed manually. |
|
|
45
|
-
| `ingest(msg, opts?)` | `(PushNotification, { broadcast?: boolean }?) => void` | Push a message through the same pipeline SignalR uses. Broadcasts pass through the active broadcast filter. |
|
|
46
|
-
| `setBroadcastFilter(fn)` | `((PushNotification) => boolean) => void` | Install a filter for broadcast messages. Prefer [useBroadcastFilter](./useBroadcastFilter.md) — same method. |
|
|
47
|
-
| `clearBroadcastFilter()` | `() => void` | Remove the broadcast filter. |
|
|
48
|
-
| `markAsRead(msg)` | `(PushNotification) => void` | Mark one message as read. Mirrors to the server. |
|
|
49
|
-
| `markAllAsRead()` | `() => Promise<void>` | Optimistic mark-all with rollback on failure. |
|
|
50
|
-
| `loadHistory(take?)` | `(number?) => Promise<void>` | Fetch history from the platform. Default page size is 10. The shell already calls this at bootstrap. |
|
|
51
|
-
| `subscribe(opts)` | `({ types, filter?, handler? }) => () => void` | Low-level pub/sub. Returns an `unsub` function. Inside blades use [useBladeNotifications](./useBladeNotifications.md) — it wraps this and registers cleanup automatically. |
|
|
52
|
-
| `getByType(type)` | `(string) => PushNotification[]` | Filter `history` by `notifyType`. |
|
|
53
|
-
|
|
54
|
-
## Escape-hatch patterns
|
|
55
|
-
|
|
56
|
-
### Manually ingest a message (tests, scripted replay)
|
|
57
|
-
|
|
58
|
-
```ts
|
|
59
|
-
const store = useNotificationStore();
|
|
60
|
-
|
|
61
|
-
store.ingest({
|
|
62
|
-
id: "test-1",
|
|
63
|
-
notifyType: "OrderCreatedDomainEvent",
|
|
64
|
-
title: "Test order",
|
|
65
|
-
isNew: true,
|
|
66
|
-
created: new Date().toISOString(),
|
|
67
|
-
} as PushNotification);
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
The ingest pipeline runs the configured toast logic and notifies subscribers exactly like a real SignalR message would, so you can verify the end-to-end behavior of `defineAppModule({ notifications })` + `useBladeNotifications` without a live hub.
|
|
71
|
-
|
|
72
|
-
`ingest` with `{ broadcast: true }` simulates `SendSystemEvents` and runs the broadcast filter; without it the message is treated as targeted and bypasses the filter.
|
|
73
|
-
|
|
74
|
-
### Custom shell surface (replace the bell dropdown)
|
|
75
|
-
|
|
76
|
-
When you are building a shell variant that omits the framework's bell dropdown — for example, a module-federation host that renders its own header — bind to the store directly:
|
|
77
|
-
|
|
78
|
-
```ts
|
|
79
|
-
import { useNotificationStore } from "@vc-shell/framework";
|
|
80
|
-
import { onMounted } from "vue";
|
|
81
|
-
|
|
82
|
-
const store = useNotificationStore();
|
|
83
|
-
|
|
84
|
-
onMounted(() => store.loadHistory(100));
|
|
85
|
-
// Use store.history, store.unreadCount, store.markAllAsRead in your own components.
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
If you are using `VcApp` (the default shell), do **not** do this — the dropdown is already mounted and binding to the same store, so a second surface duplicates what is already on screen.
|
|
89
|
-
|
|
90
|
-
## Resolution
|
|
91
|
-
|
|
92
|
-
`useNotificationStore()` resolves in this order:
|
|
93
|
-
|
|
94
|
-
1. If called inside a Vue component's `setup` (or `app.runWithContext()`), it uses `inject(NotificationStoreKey)`.
|
|
95
|
-
2. Otherwise it returns a module-level singleton created on first call.
|
|
96
|
-
|
|
97
|
-
The fallback exists so module-federation remotes and standalone scripts see the same store the host app uses.
|
|
98
|
-
|
|
99
|
-
## Tips
|
|
100
|
-
|
|
101
|
-
- **Prefer facades.** Every time you find yourself writing `store.subscribe(...)` inside a blade, you want `useBladeNotifications`. Every time you write `store.setBroadcastFilter(...)`, you want `useBroadcastFilter`. The facades exist to keep cleanup, typing, and invariants in one place.
|
|
102
|
-
- **Do not iterate `realtime` for unread counts inside a blade.** That is what `useBladeNotifications` does correctly. Touching `realtime` directly couples your component to shell internals.
|
|
103
|
-
- **`loadHistory` replaces, then merges.** Calling it again pages in more entries and merges them with the existing history.
|
|
104
|
-
- **`markAllAsRead` is optimistic.** The local state flips immediately; if the server call fails the change is rolled back and an error toast surfaces.
|
|
105
|
-
- **Direct store mutations can bypass invariants.** The broadcast filter only runs through `ingest({ broadcast: true })`. Pushing arrays around `history.value` directly is not supported.
|
|
106
|
-
|
|
107
|
-
## Related
|
|
108
|
-
|
|
109
|
-
- [useBladeNotifications](./useBladeNotifications.md) — recommended scope-aware subscription. **Start here.**
|
|
110
|
-
- [useBroadcastFilter](./useBroadcastFilter.md) — broadcast acceptance gate.
|
|
111
|
-
- [useNotificationContext](./useNotificationContext.md) — payload access inside templates.
|
|
112
|
-
- [Notifications concept page.](../../concepts/notifications.md)
|
|
113
|
-
- [Notifications plugin reference.](../../plugins/notifications.md)
|
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Assets Module
|
|
3
|
-
category: reference
|
|
4
|
-
group: modules
|
|
5
|
-
slug: assets
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# Assets Details Module
|
|
9
|
-
|
|
10
|
-
A built-in child blade for editing a single asset's metadata: display name, alt text (images only), and description. Opened by `AssetsManager` when the user clicks a table row, but also usable standalone from any parent blade that needs single-asset editing.
|
|
11
|
-
|
|
12
|
-
## Overview
|
|
13
|
-
|
|
14
|
-
The blade reads an `AssetLike` instance from `options.asset`, exposes a form pre-populated from it, and delegates persistence back to the caller through two callbacks (`assetEditHandler`, `assetRemoveHandler`). The blade itself never mutates the original asset and never talks to the network — the caller decides what saving and removing means.
|
|
15
|
-
|
|
16
|
-
The module is registered as `AssetsDetailsModule` and exposes the `AssetsDetails` blade (registered globally under the name `"AssetsDetails"`).
|
|
17
|
-
|
|
18
|
-
## Module Registration
|
|
19
|
-
|
|
20
|
-
```typescript
|
|
21
|
-
import { AssetsDetailsModule } from "@vc-shell/framework";
|
|
22
|
-
|
|
23
|
-
// Registered automatically when the framework loads
|
|
24
|
-
// Exposes: AssetsDetails blade component
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Options (via `useBlade`)
|
|
28
|
-
|
|
29
|
-
The blade reads its configuration from `options` via `useBlade<AssetsDetailsOptions>()` (not props):
|
|
30
|
-
|
|
31
|
-
| Option | Type | Description |
|
|
32
|
-
| -------------------- | --------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
33
|
-
| `asset` | `AssetLike` | The asset to edit. The blade clones it into local state — the source object is never mutated until `assetEditHandler` is called. |
|
|
34
|
-
| `disabled` | `boolean?` | When true, every input is read-only and the toolbar Save/Delete buttons are disabled. |
|
|
35
|
-
| `hiddenFields` | `string[]?` | Field names to hide. Supported values: `"name"`, `"altText"`, `"description"`. The header (preview, size, created date, URL) is always shown. |
|
|
36
|
-
| `assetEditHandler` | `(asset: AssetLike) => void \| Promise<void>` | Called by the toolbar Save button with the edited copy. The blade closes itself after the handler resolves. |
|
|
37
|
-
| `assetRemoveHandler` | `(asset: AssetLike) => Promise<void>` | Called by the toolbar Delete button. The blade closes itself after the handler resolves. |
|
|
38
|
-
|
|
39
|
-
## Usage
|
|
40
|
-
|
|
41
|
-
### Direct invocation
|
|
42
|
-
|
|
43
|
-
```typescript
|
|
44
|
-
import { useBlade } from "@vc-shell/framework";
|
|
45
|
-
|
|
46
|
-
const { openBlade } = useBlade();
|
|
47
|
-
|
|
48
|
-
openBlade({
|
|
49
|
-
name: "AssetsDetails",
|
|
50
|
-
options: {
|
|
51
|
-
asset: selectedAsset,
|
|
52
|
-
disabled: !canEdit.value,
|
|
53
|
-
hiddenFields: ["altText"],
|
|
54
|
-
assetEditHandler: async (edited) => {
|
|
55
|
-
await api.updateAsset(edited);
|
|
56
|
-
},
|
|
57
|
-
assetRemoveHandler: async (asset) => {
|
|
58
|
-
await api.deleteAsset(asset.id);
|
|
59
|
-
},
|
|
60
|
-
},
|
|
61
|
-
});
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
### Used by AssetsManager
|
|
65
|
-
|
|
66
|
-
When `AssetsManager` opens this blade on row click, it wires the manager's mutation methods into the handlers automatically:
|
|
67
|
-
|
|
68
|
-
```typescript
|
|
69
|
-
// inside AssetsManager
|
|
70
|
-
openBlade({
|
|
71
|
-
name: "AssetsDetails",
|
|
72
|
-
options: {
|
|
73
|
-
asset,
|
|
74
|
-
disabled: readonly.value,
|
|
75
|
-
hiddenFields: options.value?.hiddenFields,
|
|
76
|
-
assetEditHandler: (asset) => manager.updateItem(asset),
|
|
77
|
-
assetRemoveHandler: (asset) => manager.remove(asset),
|
|
78
|
-
},
|
|
79
|
-
});
|
|
80
|
-
```
|
|
81
|
-
|
|
82
|
-
## Header
|
|
83
|
-
|
|
84
|
-
The header is always rendered above the editable form and is not configurable through `hiddenFields`:
|
|
85
|
-
|
|
86
|
-
| Element | Source |
|
|
87
|
-
| ------------ | -------------------------------------------------------------------------------------------------- |
|
|
88
|
-
| Preview | `VcImage` thumbnail for image extensions (png/jpg/jpeg/svg/gif), colored extension badge otherwise |
|
|
89
|
-
| Size | `readableSize(asset.size)` — formatted as `KB`/`MB`/`GB` |
|
|
90
|
-
| Created date | `asset.createdDate` rendered with `type="date-ago"` |
|
|
91
|
-
| URL | `asset.url` displayed as a copyable link with `asset.name` as the visible label |
|
|
92
|
-
|
|
93
|
-
## Form fields
|
|
94
|
-
|
|
95
|
-
All fields are bound to a local clone of `asset`. They can be hidden individually via `hiddenFields`.
|
|
96
|
-
|
|
97
|
-
| Field | Visibility | Notes |
|
|
98
|
-
| ------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
99
|
-
| `name` | Hidden if `hiddenFields` includes `"name"` | Required. Edits the **base name only** — the original extension is preserved on save (e.g. editing `report.pdf` keeps `.pdf`). |
|
|
100
|
-
| `altText` | Image assets only; hide via `"altText"` | Plain string. Shown only when `asset.typeId === "Image"`. |
|
|
101
|
-
| `description` | Hidden if `hiddenFields` includes `"description"` | Multiline textarea. |
|
|
102
|
-
|
|
103
|
-
## Toolbar
|
|
104
|
-
|
|
105
|
-
| Button | Disabled condition | Action |
|
|
106
|
-
| ------ | ------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------- |
|
|
107
|
-
| Save | `disabled === true`, the form is invalid, or the form is not dirty (vee-validate `useIsFormValid`/`useIsFormDirty`) | `await assetEditHandler(editedAsset)`, then `closeSelf()` |
|
|
108
|
-
| Delete | `disabled === true` | `await assetRemoveHandler(editedAsset)`, then `closeSelf()` |
|
|
109
|
-
|
|
110
|
-
## Tips
|
|
111
|
-
|
|
112
|
-
- **Extension is locked.** The `name` input only edits the base name; the original extension is reattached on save. Renaming `photo.png` to `cover` produces `cover.png`.
|
|
113
|
-
- **Required name validation** uses vee-validate's `required` rule. The Save button stays disabled until validation passes.
|
|
114
|
-
- **`assetEditHandler`** is invoked with the edited clone — the original `options.asset` reference is never mutated. Callers should treat the argument as the new state.
|
|
115
|
-
- **`disabled` makes the blade fully read-only:** inputs are disabled and toolbar Save/Delete are disabled regardless of dirtiness.
|
|
116
|
-
- **`hiddenFields` does not enforce required-ness.** Hiding `"name"` skips the validated `<Field>`, so the Save button only depends on form dirtiness.
|
|
117
|
-
|
|
118
|
-
## Related
|
|
119
|
-
|
|
120
|
-
- `framework/modules/assets-manager/` -- parent `AssetsManager` blade that opens `AssetsDetails` on row click
|
|
121
|
-
- `framework/core/composables/useAssetsManager/` -- `AssetLike` type definition
|
|
122
|
-
- `framework/core/utilities/assets.ts` -- `isImage`, `readableSize`, `getExtensionColor`, `getExtensionLabel`
|
|
123
|
-
- `framework/ui/components/molecules/vc-field/` -- `VcField` used by the header for size/date/url
|
package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/dashboard-widget-skeleton.docs.md
DELETED
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: DashboardWidgetSkeleton
|
|
3
|
-
category: composables
|
|
4
|
-
group: utilities
|
|
5
|
-
internal: true
|
|
6
|
-
---
|
|
7
|
-
|
|
8
|
-
# DashboardWidgetSkeleton
|
|
9
|
-
|
|
10
|
-
Internal placeholder card used by `GridstackDashboard` while remote modules are still loading. Mimics the shape of `DashboardWidgetCard` (header with icon + title, stats row, content lines) with a shimmer animation. Not exported from `@vc-shell/framework` — consumed only inside the dashboard organism.
|
|
11
|
-
|
|
12
|
-
## When to Use
|
|
13
|
-
|
|
14
|
-
- You won't use this directly. `GridstackDashboard` renders one per `SkeletonItem` while `ModulesReadyKey` resolves to `false`.
|
|
15
|
-
- If you build a custom dashboard layout and want the same loading aesthetic, copy this file rather than importing it — the component is intentionally internal so the dashboard team can change its markup at any time.
|
|
16
|
-
|
|
17
|
-
## Layout Contract
|
|
18
|
-
|
|
19
|
-
The skeleton has no props. Its parent positions it via inline `style` (`grid-column` / `grid-row`) inside a 12-column CSS grid. Card height/width is fully determined by the grid cell it occupies, so the skeleton stretches to fill its slot.
|
|
20
|
-
|
|
21
|
-
## Accessibility
|
|
22
|
-
|
|
23
|
-
- The wrapper has `aria-hidden="true"` so screen readers ignore the visual placeholders. The parent grid carries `role="status"` + `aria-busy="true"` to announce loading state once.
|
|
24
|
-
- Shimmer animation is disabled when the user prefers reduced motion.
|
|
25
|
-
|
|
26
|
-
## Design Tokens
|
|
27
|
-
|
|
28
|
-
Skeleton inherits dashboard card tokens where possible (`--dashboard-widget-card-background`, `--dashboard-widget-card-border-color`, `--dashboard-widget-card-border-radius`, `--dashboard-widget-card-shadow`) so its silhouette matches the real card. Shimmer colors are read from `--neutrals-100` / `--neutrals-200`.
|
|
29
|
-
|
|
30
|
-
## Related
|
|
31
|
-
|
|
32
|
-
- [DraggableDashboard](./draggable-dashboard.docs.md) — owns the skeleton grid and decides when to render placeholders.
|
|
33
|
-
- [DashboardWidgetCard](../dashboard-widget-card/dashboard-widget-card.docs.md) — the real card whose shape skeletons imitate.
|