@vc-shell/vc-app-skill 2.0.0-alpha.32 → 2.0.0-alpha.33-pr220.455e322
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 +59 -47
- package/README.md +18 -12
- package/package.json +4 -4
- package/runtime/VERSION +1 -1
- package/runtime/agents/api-analyzer.md +31 -16
- package/runtime/agents/blade-enhancer.md +15 -9
- package/runtime/agents/details-blade-generator.md +47 -31
- package/runtime/agents/list-blade-generator.md +21 -37
- package/runtime/agents/locales-generator.md +3 -0
- package/runtime/agents/migration-agent.md +94 -0
- package/runtime/agents/module-analyzer.md +2 -0
- package/runtime/agents/module-assembler.md +15 -0
- package/runtime/agents/promote-agent.md +15 -4
- package/runtime/agents/type-checker.md +11 -0
- package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
- package/runtime/knowledge/docs/core/api/platform.docs.md +30 -30
- package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +41 -41
- package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +12 -10
- package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +11 -14
- package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +35 -35
- package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +35 -35
- package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +15 -15
- package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +21 -18
- package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +31 -27
- package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +90 -61
- package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +19 -18
- package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +89 -68
- package/runtime/knowledge/docs/core/composables/useBladeForm/useBladeForm.docs.md +75 -19
- package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +15 -15
- package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +74 -78
- package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +11 -11
- package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +27 -15
- package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +30 -30
- package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +34 -36
- package/runtime/knowledge/docs/core/composables/useErrorHandler/useErrorHandler.docs.md +44 -23
- package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +14 -11
- package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +47 -38
- package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +37 -28
- package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +23 -17
- package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +10 -10
- package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +42 -42
- package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +22 -12
- package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +33 -41
- package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +16 -16
- package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +32 -24
- package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +32 -11
- package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +24 -15
- package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +7 -7
- package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +32 -24
- package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +21 -17
- package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +24 -24
- package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +28 -31
- package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +43 -24
- package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +68 -48
- package/runtime/knowledge/docs/core/composables/useWebVitals/useWebVitals.docs.md +19 -19
- package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +42 -47
- package/runtime/knowledge/docs/core/directives/autofocus/autofocus.docs.md +10 -4
- package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +35 -20
- package/runtime/knowledge/docs/core/notifications/notifications.docs.md +36 -35
- package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +38 -38
- package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +107 -91
- package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +10 -10
- package/runtime/knowledge/docs/core/plugins/i18n/i18n.docs.md +21 -23
- package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +98 -90
- package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +10 -16
- package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +9 -9
- package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +65 -22
- package/runtime/knowledge/docs/core/services/services.docs.md +19 -22
- package/runtime/knowledge/docs/core/types/types.docs.md +40 -40
- package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +27 -27
- package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +23 -23
- package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +22 -25
- package/runtime/knowledge/docs/core/utilities/utilities.docs.md +64 -64
- package/runtime/knowledge/docs/injection-keys.docs.md +52 -51
- package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +9 -9
- package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +23 -43
- package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +102 -0
- package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +5 -5
- package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +8 -7
- package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +7 -7
- package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +8 -7
- package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +29 -13
- package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +13 -16
- package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +1 -7
- package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +5 -5
- package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
- package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -9
- package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +12 -18
- package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +34 -65
- package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +16 -26
- package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +2 -2
- package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +7 -9
- package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +30 -40
- package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +26 -19
- package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +15 -12
- package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +15 -26
- package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +21 -19
- package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +83 -67
- package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +104 -59
- package/runtime/knowledge/docs/ui/components/atoms/vc-col/vc-col.docs.md +28 -11
- package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +20 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +26 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +30 -32
- package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +25 -48
- package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +29 -24
- package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +23 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +22 -13
- package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +33 -18
- package/runtime/knowledge/docs/ui/components/atoms/vc-row/vc-row.docs.md +56 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +28 -15
- package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +40 -20
- package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +25 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +40 -14
- package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +54 -42
- package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +17 -17
- package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +21 -21
- package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +23 -10
- package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +59 -44
- package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +23 -20
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +96 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +26 -35
- package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +69 -22
- package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +58 -72
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +91 -85
- package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +38 -42
- package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +60 -72
- package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +65 -26
- package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +46 -49
- package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +35 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-image-tile/vc-image-tile.docs.md +38 -41
- package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +115 -130
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +53 -87
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +56 -63
- package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +29 -24
- package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +32 -28
- package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +63 -64
- package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +28 -26
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +59 -19
- package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +25 -34
- package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +42 -32
- package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +78 -82
- package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +25 -15
- package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +59 -63
- package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +57 -69
- package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +58 -57
- package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +49 -26
- package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +82 -28
- package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +120 -75
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +30 -44
- package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +536 -365
- package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +35 -52
- package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +33 -62
- package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +17 -23
- package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +109 -68
- package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +82 -44
- package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +8 -8
- package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +164 -0
- package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +34 -26
- package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +48 -40
- package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +30 -17
- package/runtime/knowledge/docs/ui/types/ui-types.docs.md +40 -29
- package/runtime/knowledge/examples/offers-module.md +15 -13
- package/runtime/knowledge/examples/team-module.md +82 -119
- package/runtime/knowledge/examples/videos-module.md +44 -17
- package/runtime/knowledge/index.md +22 -0
- package/runtime/knowledge/migration-prompts/blade-form-migration.md +255 -0
- package/runtime/knowledge/migration-prompts/blade-props-migration.md +194 -0
- package/runtime/knowledge/migration-prompts/datatable-migration.md +801 -0
- package/runtime/knowledge/migration-prompts/icon-migration.md +97 -0
- package/runtime/knowledge/migration-prompts/manual-migration-audit.md +117 -0
- package/runtime/knowledge/migration-prompts/notifications-migration.md +223 -0
- package/runtime/knowledge/migration-prompts/nswag-migration.md +244 -0
- package/runtime/knowledge/migration-prompts/use-assets-migration.md +164 -0
- package/runtime/knowledge/migration-prompts/use-data-table-pagination-migration.md +176 -0
- package/runtime/knowledge/migration-prompts/widgets-migration.md +178 -0
- package/runtime/knowledge/patterns/assets-management.md +20 -20
- package/runtime/knowledge/patterns/blade-navigation.md +7 -14
- package/runtime/knowledge/patterns/blade-widget.md +19 -17
- package/runtime/knowledge/patterns/child-blade-flow.md +19 -7
- package/runtime/knowledge/patterns/composable-details.md +20 -50
- package/runtime/knowledge/patterns/composable-list.md +43 -31
- package/runtime/knowledge/patterns/dashboard-widget.md +14 -16
- package/runtime/knowledge/patterns/datatable-pattern.md +521 -0
- package/runtime/knowledge/patterns/details-blade-pattern.md +78 -116
- package/runtime/knowledge/patterns/extension-points-usage.md +53 -44
- package/runtime/knowledge/patterns/form-validation.md +28 -64
- package/runtime/knowledge/patterns/list-blade-pattern.md +33 -21
- package/runtime/knowledge/patterns/module-structure.md +7 -1
- package/runtime/knowledge/patterns/multilanguage-fields.md +8 -14
- package/runtime/knowledge/patterns/notification-template.md +21 -14
- package/runtime/knowledge/patterns/signalr-notifications.md +30 -32
- package/runtime/knowledge/patterns/toolbar-pattern.md +18 -20
- package/runtime/vc-app.md +354 -49
- package/runtime/knowledge/docs/core/constants/constants.docs.md +0 -185
|
@@ -11,7 +11,7 @@ Aggregates multiple reactive boolean loading refs into a single computed that is
|
|
|
11
11
|
## Quick Start
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { useLoading } from
|
|
14
|
+
import { useLoading } from "@vc-shell/framework";
|
|
15
15
|
|
|
16
16
|
const combinedLoading = useLoading(loadingA, loadingB, loadingC);
|
|
17
17
|
// combinedLoading.value === true when ANY of the three is true
|
|
@@ -21,14 +21,14 @@ const combinedLoading = useLoading(loadingA, loadingB, loadingC);
|
|
|
21
21
|
|
|
22
22
|
### Parameters
|
|
23
23
|
|
|
24
|
-
| Parameter | Type
|
|
25
|
-
|
|
26
|
-
| `...args` | `Readonly<Ref<boolean>>[]` | Yes
|
|
24
|
+
| Parameter | Type | Required | Description |
|
|
25
|
+
| --------- | -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
26
|
+
| `...args` | `Readonly<Ref<boolean>>[]` | Yes | One or more reactive boolean refs to aggregate. Accepts `Ref<boolean>`, `ComputedRef<boolean>`, or any `Readonly<Ref<boolean>>`. |
|
|
27
27
|
|
|
28
28
|
### Returns
|
|
29
29
|
|
|
30
|
-
| Type
|
|
31
|
-
|
|
30
|
+
| Type | Description |
|
|
31
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
32
32
|
| `ComputedRef<boolean>` | `true` if any of the input refs is `true`, `false` otherwise. Re-evaluates whenever any input changes. |
|
|
33
33
|
|
|
34
34
|
## How It Works
|
|
@@ -36,7 +36,7 @@ const combinedLoading = useLoading(loadingA, loadingB, loadingC);
|
|
|
36
36
|
The implementation is a single `computed` that calls `Array.some()` on the input refs:
|
|
37
37
|
|
|
38
38
|
```typescript
|
|
39
|
-
computed(() => args.some((item) => item.value))
|
|
39
|
+
computed(() => args.some((item) => item.value));
|
|
40
40
|
```
|
|
41
41
|
|
|
42
42
|
Because `computed` tracks all `.value` accesses, Vue knows to re-evaluate whenever any of the input refs changes. The `some()` short-circuits on the first `true`, so it is efficient even with many inputs.
|
|
@@ -45,7 +45,10 @@ Because `computed` tracks all `.value` accesses, Vue knows to re-evaluate whenev
|
|
|
45
45
|
|
|
46
46
|
```vue
|
|
47
47
|
<template>
|
|
48
|
-
<VcBlade
|
|
48
|
+
<VcBlade
|
|
49
|
+
title="Order Details"
|
|
50
|
+
:loading="isLoading"
|
|
51
|
+
>
|
|
49
52
|
<div class="tw-grid tw-grid-cols-2 tw-gap-4">
|
|
50
53
|
<VcCard title="Order Info">
|
|
51
54
|
<p>{{ order?.number }}</p>
|
|
@@ -54,15 +57,18 @@ Because `computed` tracks all `.value` accesses, Vue knows to re-evaluate whenev
|
|
|
54
57
|
<p>{{ customer?.name }}</p>
|
|
55
58
|
</VcCard>
|
|
56
59
|
</div>
|
|
57
|
-
<VcDataTable
|
|
60
|
+
<VcDataTable
|
|
61
|
+
:items="lineItems"
|
|
62
|
+
:columns="columns"
|
|
63
|
+
/>
|
|
58
64
|
</VcBlade>
|
|
59
65
|
</template>
|
|
60
66
|
|
|
61
67
|
<script setup lang="ts">
|
|
62
|
-
import { useLoading } from
|
|
63
|
-
import { useOrder } from
|
|
64
|
-
import { useCustomer } from
|
|
65
|
-
import { useLineItems } from
|
|
68
|
+
import { useLoading } from "@vc-shell/framework";
|
|
69
|
+
import { useOrder } from "../composables/useOrder";
|
|
70
|
+
import { useCustomer } from "../composables/useCustomer";
|
|
71
|
+
import { useLineItems } from "../composables/useLineItems";
|
|
66
72
|
|
|
67
73
|
const { order, loading: orderLoading } = useOrder(props.orderId);
|
|
68
74
|
const { customer, loading: customerLoading } = useCustomer(props.customerId);
|
|
@@ -76,8 +82,8 @@ const isLoading = useLoading(orderLoading, customerLoading, lineItemsLoading);
|
|
|
76
82
|
## Recipe: Combining with useAsync
|
|
77
83
|
|
|
78
84
|
```typescript
|
|
79
|
-
import { useLoading } from
|
|
80
|
-
import { useAsync } from
|
|
85
|
+
import { useLoading } from "@vc-shell/framework";
|
|
86
|
+
import { useAsync } from "@vc-shell/framework";
|
|
81
87
|
|
|
82
88
|
const { loading: saveLoading, action: save } = useAsync(saveItem);
|
|
83
89
|
const { loading: deleteLoading, action: remove } = useAsync(deleteItem);
|
|
@@ -92,8 +98,8 @@ const isBusy = useLoading(saveLoading, deleteLoading, validateLoading);
|
|
|
92
98
|
If you have a variable number of loading sources (e.g., loaded from a plugin system), collect them into an array and spread:
|
|
93
99
|
|
|
94
100
|
```typescript
|
|
95
|
-
import { useLoading } from
|
|
96
|
-
import { Ref } from
|
|
101
|
+
import { useLoading } from "@vc-shell/framework";
|
|
102
|
+
import { Ref } from "vue";
|
|
97
103
|
|
|
98
104
|
const loadingRefs: Ref<boolean>[] = [];
|
|
99
105
|
|
|
@@ -11,7 +11,7 @@ Manages the sidebar menu expanded/collapsed and hover-expanded state with localS
|
|
|
11
11
|
## Basic Usage
|
|
12
12
|
|
|
13
13
|
```typescript
|
|
14
|
-
import { useMenuExpanded } from
|
|
14
|
+
import { useMenuExpanded } from "@vc-shell/framework";
|
|
15
15
|
|
|
16
16
|
const { isExpanded, toggleExpanded, isHoverExpanded, toggleHoverExpanded } = useMenuExpanded();
|
|
17
17
|
|
|
@@ -19,19 +19,19 @@ const { isExpanded, toggleExpanded, isHoverExpanded, toggleHoverExpanded } = use
|
|
|
19
19
|
toggleExpanded();
|
|
20
20
|
|
|
21
21
|
// Hover expand with 200ms delay
|
|
22
|
-
toggleHoverExpanded(true);
|
|
23
|
-
toggleHoverExpanded(false);
|
|
22
|
+
toggleHoverExpanded(true); // opens after delay
|
|
23
|
+
toggleHoverExpanded(false); // closes immediately
|
|
24
24
|
```
|
|
25
25
|
|
|
26
26
|
## API
|
|
27
27
|
|
|
28
28
|
### Returns
|
|
29
29
|
|
|
30
|
-
| Property
|
|
31
|
-
|
|
32
|
-
| `isExpanded`
|
|
33
|
-
| `toggleExpanded`
|
|
34
|
-
| `isHoverExpanded`
|
|
30
|
+
| Property | Type | Description |
|
|
31
|
+
| --------------------- | ---------------------------------- | ---------------------------------------------------------------- |
|
|
32
|
+
| `isExpanded` | `Ref<boolean>` | Pinned state, persisted via `useLocalStorage` |
|
|
33
|
+
| `toggleExpanded` | `() => void` | Toggle the pinned state |
|
|
34
|
+
| `isHoverExpanded` | `Ref<boolean>` | Temporary hover expansion (not persisted) |
|
|
35
35
|
| `toggleHoverExpanded` | `(shouldExpand?: boolean) => void` | Set hover state; opening has a 200ms delay, closing is immediate |
|
|
36
36
|
|
|
37
37
|
## Recipe: Custom Sidebar with Hover Expand
|
|
@@ -59,7 +59,7 @@ const isVisuallyExpanded = computed(() => isExpanded.value || isHoverExpanded.va
|
|
|
59
59
|
<!-- menu items -->
|
|
60
60
|
</nav>
|
|
61
61
|
<button @click="toggleExpanded">
|
|
62
|
-
{{ isExpanded ?
|
|
62
|
+
{{ isExpanded ? "Unpin" : "Pin" }}
|
|
63
63
|
</button>
|
|
64
64
|
</aside>
|
|
65
65
|
</template>
|
|
@@ -67,7 +67,7 @@ const isVisuallyExpanded = computed(() => isExpanded.value || isHoverExpanded.va
|
|
|
67
67
|
|
|
68
68
|
## Details
|
|
69
69
|
|
|
70
|
-
- **Storage key scoping**: The key is scoped per application using the first URL path segment: `VC_APP_MENU_EXPANDED_{appName}`. For example, if the app is hosted at `/
|
|
70
|
+
- **Storage key scoping**: The key is scoped per application using the first URL path segment: `VC_APP_MENU_EXPANDED_{appName}`. For example, if the app is hosted at `/my-app/`, the key is `VC_APP_MENU_EXPANDED_my-app`. This allows multiple vc-shell apps on the same domain to maintain independent sidebar states.
|
|
71
71
|
- **Hover delay**: Opening uses a 200ms debounce to prevent accidental expansion when the cursor briefly passes over the sidebar. Closing is immediate to feel responsive.
|
|
72
72
|
- **Cleanup**: Pending hover timeouts are cleaned up via `onScopeDispose` to prevent memory leaks when the composable's effect scope is destroyed.
|
|
73
73
|
- **Default state**: The sidebar starts pinned open (`true`) on first visit, which is the most user-friendly default for new users.
|
|
@@ -277,63 +277,63 @@ Returns the injected `MenuService` instance. Throws `InjectionError` if the serv
|
|
|
277
277
|
|
|
278
278
|
#### MenuService Interface
|
|
279
279
|
|
|
280
|
-
| Property
|
|
281
|
-
|
|
282
|
-
| `addMenuItem`
|
|
283
|
-
| `removeMenuItem` | `(item: MenuItem) => void`
|
|
284
|
-
| `menuItems`
|
|
285
|
-
| `menuBadges`
|
|
280
|
+
| Property | Type | Description |
|
|
281
|
+
| ---------------- | --------------------------------------- | ---------------------------------------------------------------- |
|
|
282
|
+
| `addMenuItem` | `(item: MenuItem) => void` | Add a menu item (deduplicates by identity) |
|
|
283
|
+
| `removeMenuItem` | `(item: MenuItem) => void` | Remove a menu item |
|
|
284
|
+
| `menuItems` | `Ref<MenuItem[]>` | Reactive array of all registered menu items (grouped and sorted) |
|
|
285
|
+
| `menuBadges` | `Ref<Map<string, MenuItemBadgeConfig>>` | Reactive map of badge configs keyed by routeId or groupId |
|
|
286
286
|
|
|
287
287
|
### Standalone Exports
|
|
288
288
|
|
|
289
|
-
| Function
|
|
290
|
-
|
|
291
|
-
| `addMenuItem(item)`
|
|
289
|
+
| Function | Description |
|
|
290
|
+
| -------------------------------- | ------------------------------------------------------------------ |
|
|
291
|
+
| `addMenuItem(item)` | Pre-register a menu item before the service is initialized |
|
|
292
292
|
| `removeRegisteredMenuItem(item)` | Remove a pre-registered item (works before and after service init) |
|
|
293
|
-
| `setMenuBadge(id, config)`
|
|
294
|
-
| `getMenuBadge(id)`
|
|
295
|
-
| `removeMenuBadge(id)`
|
|
296
|
-
| `getMenuBadges()`
|
|
297
|
-
| `provideMenuService()`
|
|
293
|
+
| `setMenuBadge(id, config)` | Set a badge on a menu item by routeId or groupId |
|
|
294
|
+
| `getMenuBadge(id)` | Get badge config for a menu item |
|
|
295
|
+
| `removeMenuBadge(id)` | Remove a badge from a menu item |
|
|
296
|
+
| `getMenuBadges()` | Get the reactive badge registry map |
|
|
297
|
+
| `provideMenuService()` | Create and provide the service in a root component |
|
|
298
298
|
|
|
299
299
|
### MenuItem Properties
|
|
300
300
|
|
|
301
|
-
| Property
|
|
302
|
-
|
|
303
|
-
| `title`
|
|
304
|
-
| `icon`
|
|
305
|
-
| `priority`
|
|
306
|
-
| `routeId`
|
|
307
|
-
| `url`
|
|
308
|
-
| `id`
|
|
309
|
-
| `permissions`
|
|
310
|
-
| `group`
|
|
311
|
-
| `groupIcon`
|
|
312
|
-
| `groupConfig`
|
|
313
|
-
| `inGroupPriority` | `number`
|
|
314
|
-
| `badge`
|
|
315
|
-
| `children`
|
|
301
|
+
| Property | Type | Required | Description |
|
|
302
|
+
| ----------------- | --------------------- | -------- | ----------------------------------------------------------------------------- |
|
|
303
|
+
| `title` | `string` | Yes | Display text |
|
|
304
|
+
| `icon` | `string` | Yes | Icon class (e.g., `"fas fa-shopping-cart"`) |
|
|
305
|
+
| `priority` | `number` | Yes | Sort order (lower = higher in the list) |
|
|
306
|
+
| `routeId` | `string` | No | Blade route name (also used as identity key) |
|
|
307
|
+
| `url` | `string` | No | External URL |
|
|
308
|
+
| `id` | `string \| number` | No | Explicit identity key |
|
|
309
|
+
| `permissions` | `string \| string[]` | No | Required permissions for visibility |
|
|
310
|
+
| `group` | `string` | No | Group name (deprecated, use `groupConfig`) |
|
|
311
|
+
| `groupIcon` | `string` | No | Group icon (deprecated, use `groupConfig`) |
|
|
312
|
+
| `groupConfig` | `object` | No | Group configuration: `{ id, title?, icon?, priority?, permissions?, badge? }` |
|
|
313
|
+
| `inGroupPriority` | `number` | No | Sort order within a group (deprecated, use item's `priority`) |
|
|
314
|
+
| `badge` | `MenuItemBadgeConfig` | No | Inline badge configuration |
|
|
315
|
+
| `children` | `MenuItem[]` | No | Child items (populated automatically for groups) |
|
|
316
316
|
|
|
317
317
|
### MenuItemBadgeConfig
|
|
318
318
|
|
|
319
319
|
Accepts a full object or shorthand values:
|
|
320
320
|
|
|
321
|
-
| Form
|
|
322
|
-
|
|
323
|
-
| `number`
|
|
324
|
-
| `string`
|
|
325
|
-
| `Ref<number \| string>`
|
|
326
|
-
| `ComputedRef<number \| string>` | `computed(() => count.value)`
|
|
327
|
-
| `() => number \| string`
|
|
328
|
-
| `MenuItemBadge`
|
|
321
|
+
| Form | Example | Description |
|
|
322
|
+
| ------------------------------- | ------------------------------------------------- | ------------------ |
|
|
323
|
+
| `number` | `5` | Numeric count |
|
|
324
|
+
| `string` | `"New"` | Text label |
|
|
325
|
+
| `Ref<number \| string>` | `ref(3)` | Reactive value |
|
|
326
|
+
| `ComputedRef<number \| string>` | `computed(() => count.value)` | Computed value |
|
|
327
|
+
| `() => number \| string` | `() => items.length` | Getter function |
|
|
328
|
+
| `MenuItemBadge` | `{ content: 5, variant: "danger", isDot: false }` | Full config object |
|
|
329
329
|
|
|
330
330
|
#### MenuItemBadge Properties
|
|
331
331
|
|
|
332
|
-
| Property
|
|
333
|
-
|
|
334
|
-
| `content` | `string \| number \| Ref \| ComputedRef \| Function`
|
|
335
|
-
| `variant` | `"primary" \| "success" \| "warning" \| "danger" \| "info" \| "secondary"` | `"primary"` | Color variant
|
|
336
|
-
| `isDot`
|
|
332
|
+
| Property | Type | Default | Description |
|
|
333
|
+
| --------- | -------------------------------------------------------------------------- | ----------- | -------------------------------------------- |
|
|
334
|
+
| `content` | `string \| number \| Ref \| ComputedRef \| Function` | -- | Badge content |
|
|
335
|
+
| `variant` | `"primary" \| "success" \| "warning" \| "danger" \| "info" \| "secondary"` | `"primary"` | Color variant |
|
|
336
|
+
| `isDot` | `boolean` | `false` | Show as dot indicator only (ignores content) |
|
|
337
337
|
|
|
338
338
|
## Related
|
|
339
339
|
|
|
@@ -14,10 +14,10 @@ The composable maintains two copies of the data: the `pristineValue` (the clean
|
|
|
14
14
|
## Basic Usage
|
|
15
15
|
|
|
16
16
|
```typescript
|
|
17
|
-
import { useModificationTracker } from
|
|
17
|
+
import { useModificationTracker } from "@vc-shell/framework";
|
|
18
18
|
|
|
19
19
|
// With a static initial value
|
|
20
|
-
const { currentValue, isModified, resetModificationState } = useModificationTracker({ name:
|
|
20
|
+
const { currentValue, isModified, resetModificationState } = useModificationTracker({ name: "", price: 0 });
|
|
21
21
|
|
|
22
22
|
// With a reactive source (e.g., data loaded from API)
|
|
23
23
|
const { currentValue, isModified, resetModificationState } = useModificationTracker(apiData);
|
|
@@ -34,17 +34,17 @@ resetModificationState(); // currentValue becomes the new pristine baseline
|
|
|
34
34
|
|
|
35
35
|
### Parameters
|
|
36
36
|
|
|
37
|
-
| Parameter
|
|
38
|
-
|
|
39
|
-
| `initialValueProp` | `T \| Ref<T>` | Yes
|
|
37
|
+
| Parameter | Type | Required | Description |
|
|
38
|
+
| ------------------ | ------------- | -------- | -------------------------------------- |
|
|
39
|
+
| `initialValueProp` | `T \| Ref<T>` | Yes | Initial value or reactive ref to track |
|
|
40
40
|
|
|
41
41
|
### Returns
|
|
42
42
|
|
|
43
|
-
| Property
|
|
44
|
-
|
|
45
|
-
| `currentValue`
|
|
46
|
-
| `pristineValue`
|
|
47
|
-
| `isModified`
|
|
43
|
+
| Property | Type | Description |
|
|
44
|
+
| ------------------------ | ------------------------------------- | ---------------------------------------------------------- |
|
|
45
|
+
| `currentValue` | `Ref<T>` | The working value (bind to v-model) |
|
|
46
|
+
| `pristineValue` | `Ref<T>` | The "clean" baseline value |
|
|
47
|
+
| `isModified` | `DeepReadonly<Ref<boolean>>` | `true` when `currentValue` differs from `pristineValue` |
|
|
48
48
|
| `resetModificationState` | `(newBaseline?: T \| Ref<T>) => void` | Reset modification tracking; optionally set a new baseline |
|
|
49
49
|
|
|
50
50
|
## Recipe: Blade with Save/Discard and Unsaved Changes Guard
|
|
@@ -81,8 +81,18 @@ function discard() {
|
|
|
81
81
|
<input v-model.number="currentValue.price" />
|
|
82
82
|
|
|
83
83
|
<div class="tw-flex tw-gap-2">
|
|
84
|
-
<button
|
|
85
|
-
|
|
84
|
+
<button
|
|
85
|
+
:disabled="!isModified"
|
|
86
|
+
@click="save"
|
|
87
|
+
>
|
|
88
|
+
Save
|
|
89
|
+
</button>
|
|
90
|
+
<button
|
|
91
|
+
:disabled="!isModified"
|
|
92
|
+
@click="discard"
|
|
93
|
+
>
|
|
94
|
+
Discard
|
|
95
|
+
</button>
|
|
86
96
|
</div>
|
|
87
97
|
</VcBlade>
|
|
88
98
|
</template>
|
|
@@ -13,21 +13,14 @@ Provides access to the push-notification system: reading notification history, f
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
15
15
|
```typescript
|
|
16
|
-
import { useNotifications } from
|
|
16
|
+
import { useNotifications } from "@vc-shell/framework";
|
|
17
17
|
|
|
18
18
|
// Subscribe to specific notification types
|
|
19
|
-
const {
|
|
20
|
-
notifications,
|
|
21
|
-
moduleNotifications,
|
|
22
|
-
loadFromHistory,
|
|
23
|
-
markAsRead,
|
|
24
|
-
markAllAsRead,
|
|
25
|
-
setNotificationHandler,
|
|
26
|
-
} = useNotifications('OrderStatusChanged');
|
|
19
|
+
const { notifications, moduleNotifications, loadFromHistory, markAsRead, markAllAsRead, setNotificationHandler } = useNotifications("OrderStatusChanged");
|
|
27
20
|
|
|
28
21
|
// Register a handler for real-time notifications
|
|
29
22
|
setNotificationHandler((notification) => {
|
|
30
|
-
console.log(
|
|
23
|
+
console.log("Order status changed:", notification);
|
|
31
24
|
refreshOrderList();
|
|
32
25
|
});
|
|
33
26
|
|
|
@@ -39,20 +32,20 @@ onMounted(() => loadFromHistory(50));
|
|
|
39
32
|
|
|
40
33
|
### Parameters
|
|
41
34
|
|
|
42
|
-
| Parameter
|
|
43
|
-
|
|
44
|
-
| `notifyType` | `string \| string[]` | No
|
|
35
|
+
| Parameter | Type | Required | Description |
|
|
36
|
+
| ------------ | -------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
37
|
+
| `notifyType` | `string \| string[]` | No | Notification type(s) to subscribe to (e.g., `'OrderStatusChanged'` or `['OrderCreated', 'OrderCancelled']`). Omit to receive all notifications. |
|
|
45
38
|
|
|
46
39
|
### Returns
|
|
47
40
|
|
|
48
|
-
| Property
|
|
49
|
-
|
|
50
|
-
| `notifications`
|
|
51
|
-
| `moduleNotifications`
|
|
52
|
-
| `loadFromHistory`
|
|
53
|
-
| `addNotification`
|
|
54
|
-
| `markAsRead`
|
|
55
|
-
| `markAllAsRead`
|
|
41
|
+
| Property | Type | Description |
|
|
42
|
+
| ------------------------ | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
43
|
+
| `notifications` | `ComputedRef<PushNotification[]>` | All notification history, sorted newest first. Includes both read and unread. |
|
|
44
|
+
| `moduleNotifications` | `ComputedRef<PushNotification[]>` | New real-time notifications matching the subscribed types. Only includes items where `isNew` is `true`. |
|
|
45
|
+
| `loadFromHistory` | `(take?: number) => Promise<void>` | Loads notification history from the server. `take` controls how many to fetch. |
|
|
46
|
+
| `addNotification` | `(message: PushNotification) => void` | Manually ingests a notification into the store (e.g., for testing or synthetic events). |
|
|
47
|
+
| `markAsRead` | `(message: PushNotification) => void` | Marks a single notification as read. |
|
|
48
|
+
| `markAllAsRead` | `() => void` | Marks all notifications as read. |
|
|
56
49
|
| `setNotificationHandler` | `(handler: (notification: PushNotification) => void) => void` | Registers a callback for incoming real-time notifications matching subscribed types. Only one handler per composable instance. |
|
|
57
50
|
|
|
58
51
|
## How It Works
|
|
@@ -71,21 +64,14 @@ onMounted(() => loadFromHistory(50));
|
|
|
71
64
|
|
|
72
65
|
```vue
|
|
73
66
|
<script setup lang="ts">
|
|
74
|
-
import { useNotifications } from
|
|
75
|
-
import { onMounted } from
|
|
76
|
-
|
|
77
|
-
const {
|
|
78
|
-
notifications,
|
|
79
|
-
moduleNotifications,
|
|
80
|
-
loadFromHistory,
|
|
81
|
-
markAsRead,
|
|
82
|
-
markAllAsRead,
|
|
83
|
-
setNotificationHandler,
|
|
84
|
-
} = useNotifications(['OrderCreated', 'OrderStatusChanged', 'OrderCancelled']);
|
|
67
|
+
import { useNotifications } from "@vc-shell/framework";
|
|
68
|
+
import { onMounted } from "vue";
|
|
69
|
+
|
|
70
|
+
const { notifications, moduleNotifications, loadFromHistory, markAsRead, markAllAsRead, setNotificationHandler } = useNotifications(["OrderCreated", "OrderStatusChanged", "OrderCancelled"]);
|
|
85
71
|
|
|
86
72
|
// Play a sound on new notifications
|
|
87
73
|
setNotificationHandler((notification) => {
|
|
88
|
-
const audio = new Audio(
|
|
74
|
+
const audio = new Audio("/sounds/notification.mp3");
|
|
89
75
|
audio.play().catch(() => {});
|
|
90
76
|
});
|
|
91
77
|
|
|
@@ -95,15 +81,21 @@ onMounted(() => loadFromHistory(100));
|
|
|
95
81
|
<template>
|
|
96
82
|
<div class="notification-panel">
|
|
97
83
|
<div class="tw-flex tw-justify-between tw-items-center tw-p-2">
|
|
98
|
-
<span class="tw-font-semibold">
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
84
|
+
<span class="tw-font-semibold"> Notifications ({{ moduleNotifications.length }} new) </span>
|
|
85
|
+
<VcButton
|
|
86
|
+
size="sm"
|
|
87
|
+
variant="ghost"
|
|
88
|
+
@click="markAllAsRead"
|
|
89
|
+
>
|
|
102
90
|
Mark all read
|
|
103
91
|
</VcButton>
|
|
104
92
|
</div>
|
|
105
93
|
|
|
106
|
-
<div
|
|
94
|
+
<div
|
|
95
|
+
v-for="item in notifications"
|
|
96
|
+
:key="item.id"
|
|
97
|
+
class="tw-p-2 tw-border-b"
|
|
98
|
+
>
|
|
107
99
|
<div class="tw-flex tw-justify-between">
|
|
108
100
|
<span :class="{ 'tw-font-bold': item.isNew }">
|
|
109
101
|
{{ item.title }}
|
|
@@ -127,10 +119,10 @@ onMounted(() => loadFromHistory(100));
|
|
|
127
119
|
|
|
128
120
|
```vue
|
|
129
121
|
<script setup lang="ts">
|
|
130
|
-
import { useNotifications } from
|
|
131
|
-
import { onMounted } from
|
|
122
|
+
import { useNotifications } from "@vc-shell/framework";
|
|
123
|
+
import { onMounted } from "vue";
|
|
132
124
|
|
|
133
|
-
const { setNotificationHandler } = useNotifications(
|
|
125
|
+
const { setNotificationHandler } = useNotifications("InventoryChanged");
|
|
134
126
|
|
|
135
127
|
const items = ref<InventoryItem[]>([]);
|
|
136
128
|
|
|
@@ -26,21 +26,21 @@ if (hasAccess("order:update")) {
|
|
|
26
26
|
|
|
27
27
|
The `hasAccess` function evaluates permissions from the current user object (loaded via `useUserManagement`). The behavior depends on the input type and the user's role.
|
|
28
28
|
|
|
29
|
-
| Input
|
|
30
|
-
|
|
31
|
-
| `undefined`
|
|
32
|
-
| `"order:read"`
|
|
29
|
+
| Input | Result |
|
|
30
|
+
| -------------------------------- | ------------------------------------------------------------------- |
|
|
31
|
+
| `undefined` | `true` -- no permission required, everyone has access |
|
|
32
|
+
| `"order:read"` | `true` if the user has this exact permission string |
|
|
33
33
|
| `["order:read", "order:update"]` | `true` if the user has **any** of the listed permissions (OR logic) |
|
|
34
|
-
| Any value, administrator user
|
|
34
|
+
| Any value, administrator user | Always `true` -- administrators bypass all checks |
|
|
35
35
|
|
|
36
36
|
Permission strings follow the VirtoCommerce platform format: `"module:action"`. Common examples:
|
|
37
37
|
|
|
38
|
-
| Permission
|
|
39
|
-
|
|
40
|
-
| `"order:read"`
|
|
41
|
-
| `"order:update"`
|
|
42
|
-
| `"order:delete"`
|
|
43
|
-
| `"catalog:create"`
|
|
38
|
+
| Permission | Meaning |
|
|
39
|
+
| ------------------- | ------------------------ |
|
|
40
|
+
| `"order:read"` | View orders |
|
|
41
|
+
| `"order:update"` | Edit orders |
|
|
42
|
+
| `"order:delete"` | Delete orders |
|
|
43
|
+
| `"catalog:create"` | Create catalog items |
|
|
44
44
|
| `"customer:manage"` | Full customer management |
|
|
45
45
|
|
|
46
46
|
## Conditional Rendering in Templates
|
|
@@ -255,15 +255,15 @@ if (hasAccess("order:delete")) {
|
|
|
255
255
|
|
|
256
256
|
### Returns: `UsePermissionsReturn`
|
|
257
257
|
|
|
258
|
-
| Property
|
|
259
|
-
|
|
258
|
+
| Property | Type | Description |
|
|
259
|
+
| ----------- | ----------------------------------------------------------- | -------------------------------------------------------- |
|
|
260
260
|
| `hasAccess` | `(permissions: string \| string[] \| undefined) => boolean` | Check if the current user has the required permission(s) |
|
|
261
261
|
|
|
262
262
|
### hasAccess Parameters
|
|
263
263
|
|
|
264
|
-
| Parameter
|
|
265
|
-
|
|
266
|
-
| `permissions` | `string \| string[] \| undefined` | No
|
|
264
|
+
| Parameter | Type | Required | Description |
|
|
265
|
+
| ------------- | --------------------------------- | -------- | ---------------------------------------------------------------------------- |
|
|
266
|
+
| `permissions` | `string \| string[] \| undefined` | No | Permission string, array of strings (OR logic), or `undefined` (always true) |
|
|
267
267
|
|
|
268
268
|
### Internal Behavior
|
|
269
269
|
|
|
@@ -18,9 +18,7 @@ import { usePopup } from "@vc-shell/framework";
|
|
|
18
18
|
const { showConfirmation, showError } = usePopup();
|
|
19
19
|
|
|
20
20
|
async function deleteProduct(id: string) {
|
|
21
|
-
const confirmed = await showConfirmation(
|
|
22
|
-
"Are you sure you want to delete this product?"
|
|
23
|
-
);
|
|
21
|
+
const confirmed = await showConfirmation("Are you sure you want to delete this product?");
|
|
24
22
|
if (!confirmed) return;
|
|
25
23
|
|
|
26
24
|
try {
|
|
@@ -33,7 +31,10 @@ async function deleteProduct(id: string) {
|
|
|
33
31
|
|
|
34
32
|
<template>
|
|
35
33
|
<VcBlade title="Product">
|
|
36
|
-
<VcButton
|
|
34
|
+
<VcButton
|
|
35
|
+
variant="danger"
|
|
36
|
+
@click="deleteProduct(product.id)"
|
|
37
|
+
>
|
|
37
38
|
Delete
|
|
38
39
|
</VcButton>
|
|
39
40
|
</VcBlade>
|
|
@@ -44,28 +45,28 @@ async function deleteProduct(id: string) {
|
|
|
44
45
|
|
|
45
46
|
### Parameters
|
|
46
47
|
|
|
47
|
-
| Parameter | Type
|
|
48
|
-
|
|
49
|
-
| `options` | `MaybeRef<UsePopupProps<T>>` | No
|
|
48
|
+
| Parameter | Type | Required | Description |
|
|
49
|
+
| --------- | ---------------------------- | -------- | --------------------------------------------------------------------------- |
|
|
50
|
+
| `options` | `MaybeRef<UsePopupProps<T>>` | No | Configuration for a custom popup component. Omit for built-in dialogs only. |
|
|
50
51
|
|
|
51
52
|
#### `UsePopupProps<T>`
|
|
52
53
|
|
|
53
|
-
| Field
|
|
54
|
-
|
|
55
|
-
| `component` | `ComponentPublicInstanceConstructor`
|
|
56
|
-
| `props`
|
|
57
|
-
| `emits`
|
|
58
|
-
| `slots`
|
|
54
|
+
| Field | Type | Required | Description |
|
|
55
|
+
| ----------- | --------------------------------------------- | -------- | ------------------------------------------------------------------------- |
|
|
56
|
+
| `component` | `ComponentPublicInstanceConstructor` | Yes | The popup component to render |
|
|
57
|
+
| `props` | `RawProps<T>` | No | Props to pass to the component (typed from the component's `defineProps`) |
|
|
58
|
+
| `emits` | `RawEmits<T>` | No | Event handlers (typed from the component's `defineEmits`) |
|
|
59
|
+
| `slots` | `Record<string, string \| Component \| Slot>` | No | Named slots — strings render as text, components render as VNodes |
|
|
59
60
|
|
|
60
61
|
### Returns (`IUsePopup`)
|
|
61
62
|
|
|
62
|
-
| Method
|
|
63
|
-
|
|
64
|
-
| `open`
|
|
65
|
-
| `close`
|
|
63
|
+
| Method | Signature | Description |
|
|
64
|
+
| ------------------ | ------------------------------------------------------ | --------------------------------------------------------------------------------------------------- |
|
|
65
|
+
| `open` | `() => void` | Push the popup onto the stack and render it |
|
|
66
|
+
| `close` | `() => void` | Remove the popup from the stack |
|
|
66
67
|
| `showConfirmation` | `(message: string \| Ref<string>) => Promise<boolean>` | Warning dialog with Confirm/Cancel buttons. Resolves `true` on confirm, `false` on cancel or close. |
|
|
67
|
-
| `showError`
|
|
68
|
-
| `showInfo`
|
|
68
|
+
| `showError` | `(message: string \| Ref<string>) => void` | Error-styled popup with a close button |
|
|
69
|
+
| `showInfo` | `(message: string \| Ref<string>) => void` | Info-styled popup with a close button |
|
|
69
70
|
|
|
70
71
|
## How It Works
|
|
71
72
|
|
|
@@ -86,9 +87,7 @@ const { showConfirmation, showError } = usePopup();
|
|
|
86
87
|
const { closeSelf } = useBlade();
|
|
87
88
|
|
|
88
89
|
async function deleteOrder(id: string) {
|
|
89
|
-
const confirmed = await showConfirmation(
|
|
90
|
-
"Are you sure you want to delete this order? This action cannot be undone."
|
|
91
|
-
);
|
|
90
|
+
const confirmed = await showConfirmation("Are you sure you want to delete this order? This action cannot be undone.");
|
|
92
91
|
if (!confirmed) return;
|
|
93
92
|
|
|
94
93
|
try {
|
|
@@ -139,14 +138,20 @@ const { open, close } = usePopup(
|
|
|
139
138
|
computed(() => ({
|
|
140
139
|
component: ConfirmPopup,
|
|
141
140
|
props: { message: `Delete ${selectedCount.value} items?` },
|
|
142
|
-
emits: {
|
|
143
|
-
|
|
141
|
+
emits: {
|
|
142
|
+
onConfirm: () => {
|
|
143
|
+
performDelete();
|
|
144
|
+
close();
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
})),
|
|
144
148
|
);
|
|
145
149
|
```
|
|
146
150
|
|
|
147
151
|
## Common Mistakes
|
|
148
152
|
|
|
149
153
|
**Wrong: not awaiting showConfirmation**
|
|
154
|
+
|
|
150
155
|
```ts
|
|
151
156
|
// The delete runs immediately — confirmation is ignored
|
|
152
157
|
showConfirmation("Delete?");
|
|
@@ -154,6 +159,7 @@ await api.deleteProduct(id); // runs before user clicks!
|
|
|
154
159
|
```
|
|
155
160
|
|
|
156
161
|
**Correct: await the result**
|
|
162
|
+
|
|
157
163
|
```ts
|
|
158
164
|
const confirmed = await showConfirmation("Delete?");
|
|
159
165
|
if (!confirmed) return;
|
|
@@ -163,6 +169,7 @@ await api.deleteProduct(id);
|
|
|
163
169
|
---
|
|
164
170
|
|
|
165
171
|
**Wrong: nesting many popups**
|
|
172
|
+
|
|
166
173
|
```ts
|
|
167
174
|
// 3+ deep popup stacks confuse users
|
|
168
175
|
const a = await showConfirmation("Step 1?");
|
|
@@ -175,6 +182,7 @@ if (a) {
|
|
|
175
182
|
```
|
|
176
183
|
|
|
177
184
|
**Correct: use a blade for multi-step workflows**
|
|
185
|
+
|
|
178
186
|
```ts
|
|
179
187
|
// Complex flows belong in blades, not popups
|
|
180
188
|
openBlade({ name: "WizardBlade", options: { step: 1 } });
|