@vc-shell/vc-app-skill 2.0.0-alpha.33 → 2.0.0-alpha.34

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.
Files changed (195) hide show
  1. package/CHANGELOG.md +78 -54
  2. package/README.md +42 -12
  3. package/package.json +4 -4
  4. package/runtime/VERSION +1 -1
  5. package/runtime/agents/api-analyzer.md +31 -16
  6. package/runtime/agents/blade-enhancer.md +15 -9
  7. package/runtime/agents/details-blade-generator.md +47 -31
  8. package/runtime/agents/list-blade-generator.md +21 -37
  9. package/runtime/agents/locales-generator.md +3 -0
  10. package/runtime/agents/migration-agent.md +18 -7
  11. package/runtime/agents/module-analyzer.md +2 -0
  12. package/runtime/agents/module-assembler.md +15 -0
  13. package/runtime/agents/promote-agent.md +15 -4
  14. package/runtime/agents/type-checker.md +11 -0
  15. package/runtime/knowledge/docs/_BUILD_HASH.md +1 -1
  16. package/runtime/knowledge/docs/core/api/platform.docs.md +30 -30
  17. package/runtime/knowledge/docs/core/blade-navigation/blade-nav-composables.docs.md +41 -41
  18. package/runtime/knowledge/docs/core/composables/bladeContext/index.docs.md +12 -10
  19. package/runtime/knowledge/docs/core/composables/useApiClient/useApiClient.docs.md +11 -14
  20. package/runtime/knowledge/docs/core/composables/useAppBarMobileButtons/useAppBarMobileButtons.docs.md +35 -35
  21. package/runtime/knowledge/docs/core/composables/useAppBarWidget/useAppBarWidget.docs.md +35 -35
  22. package/runtime/knowledge/docs/core/composables/useAppInsights/useAppInsights.docs.md +15 -15
  23. package/runtime/knowledge/docs/core/composables/useAssets/useAssets.docs.md +21 -18
  24. package/runtime/knowledge/docs/core/composables/useAssetsManager/useAssetsManager.docs.md +28 -24
  25. package/runtime/knowledge/docs/core/composables/useAsync/useAsync.docs.md +90 -61
  26. package/runtime/knowledge/docs/core/composables/useBeforeUnload/useBeforeUnload.docs.md +19 -18
  27. package/runtime/knowledge/docs/core/composables/useBlade/useBlade.docs.md +89 -68
  28. package/runtime/knowledge/docs/core/composables/useBladeForm/useBladeForm.docs.md +27 -25
  29. package/runtime/knowledge/docs/core/composables/useBladeRegistry/useBladeRegistry.docs.md +15 -15
  30. package/runtime/knowledge/docs/core/composables/useBladeWidgets/index.docs.md +43 -47
  31. package/runtime/knowledge/docs/core/composables/useBreadcrumbs/useBreadcrumbs.docs.md +11 -11
  32. package/runtime/knowledge/docs/core/composables/useConnectionStatus/useConnectionStatus.docs.md +27 -15
  33. package/runtime/knowledge/docs/core/composables/useDashboard/useDashboard.docs.md +30 -30
  34. package/runtime/knowledge/docs/core/composables/useDynamicProperties/useDynamicProperties.docs.md +34 -36
  35. package/runtime/knowledge/docs/core/composables/useErrorHandler/useErrorHandler.docs.md +44 -23
  36. package/runtime/knowledge/docs/core/composables/useFunctions/useFunctions.docs.md +14 -11
  37. package/runtime/knowledge/docs/core/composables/useKeyboardNavigation/useKeyboardNavigation.docs.md +47 -38
  38. package/runtime/knowledge/docs/core/composables/useLanguages/useLanguages.docs.md +37 -28
  39. package/runtime/knowledge/docs/core/composables/useLoading/useLoading.docs.md +23 -17
  40. package/runtime/knowledge/docs/core/composables/useMenuExpanded/index.docs.md +9 -9
  41. package/runtime/knowledge/docs/core/composables/useMenuService/useMenuService.docs.md +42 -42
  42. package/runtime/knowledge/docs/core/composables/useModificationTracker/useModificationTracker.docs.md +22 -12
  43. package/runtime/knowledge/docs/core/composables/useNotifications/useNotifications.docs.md +33 -41
  44. package/runtime/knowledge/docs/core/composables/usePermissions/usePermissions.docs.md +16 -16
  45. package/runtime/knowledge/docs/core/composables/usePlatformLocaleSync/usePlatformLocaleSync.docs.md +28 -0
  46. package/runtime/knowledge/docs/core/composables/usePopup/usePopup.docs.md +32 -24
  47. package/runtime/knowledge/docs/core/composables/useResponsive/useResponsive.docs.md +32 -11
  48. package/runtime/knowledge/docs/core/composables/useSettings/useSettings.docs.md +22 -13
  49. package/runtime/knowledge/docs/core/composables/useSettingsMenu/useSettingsMenu.docs.md +7 -7
  50. package/runtime/knowledge/docs/core/composables/useSidebarState/useSidebarState.docs.md +32 -24
  51. package/runtime/knowledge/docs/core/composables/useSlowNetworkDetection/useSlowNetworkDetection.docs.md +21 -17
  52. package/runtime/knowledge/docs/core/composables/useTheme/useTheme.docs.md +24 -24
  53. package/runtime/knowledge/docs/core/composables/useToolbar/useToolbar.docs.md +28 -31
  54. package/runtime/knowledge/docs/core/composables/useUser/useUser.docs.md +43 -24
  55. package/runtime/knowledge/docs/core/composables/useUserManagement/useUserManagement.docs.md +68 -48
  56. package/runtime/knowledge/docs/core/composables/useWebVitals/useWebVitals.docs.md +19 -19
  57. package/runtime/knowledge/docs/core/composables/useWidgets/useWidgets.docs.md +42 -47
  58. package/runtime/knowledge/docs/core/directives/autofocus/autofocus.docs.md +10 -4
  59. package/runtime/knowledge/docs/core/directives/loading/loading.docs.md +35 -20
  60. package/runtime/knowledge/docs/core/notifications/notifications.docs.md +36 -35
  61. package/runtime/knowledge/docs/core/plugins/ai-agent/ai-agent.docs.md +38 -38
  62. package/runtime/knowledge/docs/core/plugins/extension-points/extension-points.docs.md +79 -62
  63. package/runtime/knowledge/docs/core/plugins/global-error-handler/global-error-handler.docs.md +10 -10
  64. package/runtime/knowledge/docs/core/plugins/i18n/i18n.docs.md +21 -23
  65. package/runtime/knowledge/docs/core/plugins/modularity/modularity.docs.md +91 -83
  66. package/runtime/knowledge/docs/core/plugins/permissions/permissions.docs.md +10 -16
  67. package/runtime/knowledge/docs/core/plugins/signalR/signalR.docs.md +9 -9
  68. package/runtime/knowledge/docs/core/plugins/validation/validation.docs.md +65 -22
  69. package/runtime/knowledge/docs/core/services/services.docs.md +19 -22
  70. package/runtime/knowledge/docs/core/types/types.docs.md +40 -40
  71. package/runtime/knowledge/docs/core/utilities/date/date-utilities.docs.md +27 -27
  72. package/runtime/knowledge/docs/core/utilities/shared-utilities.docs.md +23 -23
  73. package/runtime/knowledge/docs/core/utilities/thumbnail/thumbnail.docs.md +22 -25
  74. package/runtime/knowledge/docs/core/utilities/utilities.docs.md +64 -64
  75. package/runtime/knowledge/docs/injection-keys.docs.md +52 -51
  76. package/runtime/knowledge/docs/modules/assets-manager/assets-manager.docs.md +9 -9
  77. package/runtime/knowledge/docs/shell/_internal/popup/common/popup-common.docs.md +23 -43
  78. package/runtime/knowledge/docs/shell/auth/ChangePasswordPage/change-password-page.docs.md +5 -5
  79. package/runtime/knowledge/docs/shell/auth/ForgotPasswordPage/forgot-password-page.docs.md +5 -5
  80. package/runtime/knowledge/docs/shell/auth/InvitePage/invite-page.docs.md +8 -7
  81. package/runtime/knowledge/docs/shell/auth/LoginPage/login-page.docs.md +7 -7
  82. package/runtime/knowledge/docs/shell/auth/ResetPasswordPage/reset-password-page.docs.md +8 -7
  83. package/runtime/knowledge/docs/shell/auth/sign-in/sign-in.docs.md +29 -13
  84. package/runtime/knowledge/docs/shell/components/change-password/change-password.docs.md +13 -16
  85. package/runtime/knowledge/docs/shell/components/change-password-button/change-password-button.docs.md +1 -7
  86. package/runtime/knowledge/docs/shell/components/error-interceptor/error-interceptor.docs.md +5 -5
  87. package/runtime/knowledge/docs/shell/components/language-selector/language-selector.docs.md +1 -1
  88. package/runtime/knowledge/docs/shell/components/logout-button/logout-button.docs.md +1 -1
  89. package/runtime/knowledge/docs/shell/components/notification-template/notification-template.docs.md +17 -9
  90. package/runtime/knowledge/docs/shell/components/settings-menu/settings-menu.docs.md +11 -17
  91. package/runtime/knowledge/docs/shell/components/settings-menu-item/settings-menu-item.docs.md +34 -65
  92. package/runtime/knowledge/docs/shell/components/sidebar/sidebar.docs.md +16 -26
  93. package/runtime/knowledge/docs/shell/components/theme-selector/theme-selector.docs.md +2 -2
  94. package/runtime/knowledge/docs/shell/components/user-dropdown-button/user-dropdown-button.docs.md +7 -9
  95. package/runtime/knowledge/docs/shell/dashboard/dashboard-charts/dashboard-charts.docs.md +30 -40
  96. package/runtime/knowledge/docs/shell/dashboard/dashboard-widget-card/dashboard-widget-card.docs.md +26 -19
  97. package/runtime/knowledge/docs/shell/dashboard/draggable-dashboard/draggable-dashboard.docs.md +15 -12
  98. package/runtime/knowledge/docs/ui/components/atoms/vc-badge/vc-badge.docs.md +15 -26
  99. package/runtime/knowledge/docs/ui/components/atoms/vc-banner/vc-banner.docs.md +21 -19
  100. package/runtime/knowledge/docs/ui/components/atoms/vc-button/vc-button.docs.md +83 -67
  101. package/runtime/knowledge/docs/ui/components/atoms/vc-card/vc-card.docs.md +100 -59
  102. package/runtime/knowledge/docs/ui/components/atoms/vc-col/vc-col.docs.md +28 -11
  103. package/runtime/knowledge/docs/ui/components/atoms/vc-container/vc-container.docs.md +20 -17
  104. package/runtime/knowledge/docs/ui/components/atoms/vc-hint/vc-hint.docs.md +26 -17
  105. package/runtime/knowledge/docs/ui/components/atoms/vc-icon/vc-icon.docs.md +30 -32
  106. package/runtime/knowledge/docs/ui/components/atoms/vc-image/vc-image.docs.md +25 -48
  107. package/runtime/knowledge/docs/ui/components/atoms/vc-label/vc-label.docs.md +29 -24
  108. package/runtime/knowledge/docs/ui/components/atoms/vc-link/vc-link.docs.md +23 -15
  109. package/runtime/knowledge/docs/ui/components/atoms/vc-loading/vc-loading.docs.md +22 -13
  110. package/runtime/knowledge/docs/ui/components/atoms/vc-progress/vc-progress.docs.md +33 -18
  111. package/runtime/knowledge/docs/ui/components/atoms/vc-row/vc-row.docs.md +56 -15
  112. package/runtime/knowledge/docs/ui/components/atoms/vc-scrollable-container/vc-scrollable-container.docs.md +28 -15
  113. package/runtime/knowledge/docs/ui/components/atoms/vc-skeleton/vc-skeleton.docs.md +40 -20
  114. package/runtime/knowledge/docs/ui/components/atoms/vc-status/vc-status.docs.md +25 -14
  115. package/runtime/knowledge/docs/ui/components/atoms/vc-status-icon/vc-status-icon.docs.md +40 -14
  116. package/runtime/knowledge/docs/ui/components/atoms/vc-tooltip/vc-tooltip.docs.md +54 -42
  117. package/runtime/knowledge/docs/ui/components/atoms/vc-video/vc-video.docs.md +17 -17
  118. package/runtime/knowledge/docs/ui/components/atoms/vc-widget/vc-widget.docs.md +21 -21
  119. package/runtime/knowledge/docs/ui/components/molecules/multilanguage-selector/multilanguage-selector.docs.md +23 -10
  120. package/runtime/knowledge/docs/ui/components/molecules/vc-accordion/vc-accordion.docs.md +55 -44
  121. package/runtime/knowledge/docs/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.docs.md +23 -20
  122. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox/vc-checkbox.docs.md +92 -65
  123. package/runtime/knowledge/docs/ui/components/molecules/vc-checkbox-group/vc-checkbox-group.docs.md +22 -36
  124. package/runtime/knowledge/docs/ui/components/molecules/vc-color-input/vc-color-input.docs.md +65 -23
  125. package/runtime/knowledge/docs/ui/components/molecules/vc-date-picker/vc-date-picker.docs.md +52 -73
  126. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown/vc-dropdown.docs.md +91 -85
  127. package/runtime/knowledge/docs/ui/components/molecules/vc-dropdown-panel/vc-dropdown-panel.docs.md +38 -42
  128. package/runtime/knowledge/docs/ui/components/molecules/vc-editor/vc-editor.docs.md +56 -73
  129. package/runtime/knowledge/docs/ui/components/molecules/vc-field/vc-field.docs.md +61 -27
  130. package/runtime/knowledge/docs/ui/components/molecules/vc-file-upload/vc-file-upload.docs.md +42 -50
  131. package/runtime/knowledge/docs/ui/components/molecules/vc-form/vc-form.docs.md +35 -64
  132. package/runtime/knowledge/docs/ui/components/molecules/vc-image-tile/vc-image-tile.docs.md +38 -41
  133. package/runtime/knowledge/docs/ui/components/molecules/vc-input/vc-input.docs.md +109 -131
  134. package/runtime/knowledge/docs/ui/components/molecules/vc-input-currency/vc-input-currency.docs.md +47 -88
  135. package/runtime/knowledge/docs/ui/components/molecules/vc-input-dropdown/vc-input-dropdown.docs.md +50 -64
  136. package/runtime/knowledge/docs/ui/components/molecules/vc-input-group/vc-input-group.docs.md +29 -24
  137. package/runtime/knowledge/docs/ui/components/molecules/vc-menu/vc-menu.docs.md +32 -28
  138. package/runtime/knowledge/docs/ui/components/molecules/vc-multivalue/vc-multivalue.docs.md +57 -65
  139. package/runtime/knowledge/docs/ui/components/molecules/vc-pagination/vc-pagination.docs.md +28 -26
  140. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-button/vc-radio-button.docs.md +55 -20
  141. package/runtime/knowledge/docs/ui/components/molecules/vc-radio-group/vc-radio-group.docs.md +21 -35
  142. package/runtime/knowledge/docs/ui/components/molecules/vc-rating/vc-rating.docs.md +38 -33
  143. package/runtime/knowledge/docs/ui/components/molecules/vc-select/vc-select.docs.md +72 -83
  144. package/runtime/knowledge/docs/ui/components/molecules/vc-slider/vc-slider.docs.md +21 -16
  145. package/runtime/knowledge/docs/ui/components/molecules/vc-switch/vc-switch.docs.md +55 -64
  146. package/runtime/knowledge/docs/ui/components/molecules/vc-textarea/vc-textarea.docs.md +51 -70
  147. package/runtime/knowledge/docs/ui/components/molecules/vc-toast/vc-toast.docs.md +58 -57
  148. package/runtime/knowledge/docs/ui/components/organisms/vc-app/vc-app.docs.md +49 -26
  149. package/runtime/knowledge/docs/ui/components/organisms/vc-auth-layout/vc-auth-layout.docs.md +82 -28
  150. package/runtime/knowledge/docs/ui/components/organisms/vc-blade/vc-blade.docs.md +90 -75
  151. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/composables/table-composables.docs.md +99 -48
  152. package/runtime/knowledge/docs/ui/components/organisms/vc-data-table/vc-data-table.docs.md +548 -367
  153. package/runtime/knowledge/docs/ui/components/organisms/vc-dynamic-property/vc-dynamic-property.docs.md +35 -52
  154. package/runtime/knowledge/docs/ui/components/organisms/vc-gallery/vc-gallery.docs.md +33 -62
  155. package/runtime/knowledge/docs/ui/components/organisms/vc-image-upload/vc-image-upload.docs.md +17 -23
  156. package/runtime/knowledge/docs/ui/components/organisms/vc-popup/vc-popup.docs.md +109 -68
  157. package/runtime/knowledge/docs/ui/components/organisms/vc-sidebar/vc-sidebar.docs.md +82 -44
  158. package/runtime/knowledge/docs/ui/composables/ui-composables.docs.md +8 -8
  159. package/runtime/knowledge/docs/ui/composables/useDataTablePagination.docs.md +164 -0
  160. package/runtime/knowledge/docs/ui/composables/useDataTableSort.docs.md +34 -26
  161. package/runtime/knowledge/docs/ui/composables/useTableSelection.docs.md +48 -40
  162. package/runtime/knowledge/docs/ui/composables/useTableSort.docs.md +30 -17
  163. package/runtime/knowledge/docs/ui/types/ui-types.docs.md +40 -29
  164. package/runtime/knowledge/examples/offers-module.md +15 -13
  165. package/runtime/knowledge/examples/team-module.md +82 -119
  166. package/runtime/knowledge/examples/videos-module.md +44 -17
  167. package/runtime/knowledge/index.md +22 -0
  168. package/runtime/knowledge/migration-prompts/blade-form-migration.md +17 -8
  169. package/runtime/knowledge/migration-prompts/blade-props-migration.md +1 -2
  170. package/runtime/knowledge/migration-prompts/datatable-migration.md +801 -0
  171. package/runtime/knowledge/migration-prompts/icon-migration.md +97 -0
  172. package/runtime/knowledge/migration-prompts/manual-migration-audit.md +117 -0
  173. package/runtime/knowledge/migration-prompts/notifications-migration.md +8 -3
  174. package/runtime/knowledge/migration-prompts/nswag-migration.md +25 -29
  175. package/runtime/knowledge/migration-prompts/use-assets-migration.md +164 -0
  176. package/runtime/knowledge/migration-prompts/use-data-table-pagination-migration.md +176 -0
  177. package/runtime/knowledge/migration-prompts/widgets-migration.md +48 -27
  178. package/runtime/knowledge/patterns/assets-management.md +20 -20
  179. package/runtime/knowledge/patterns/blade-navigation.md +7 -14
  180. package/runtime/knowledge/patterns/blade-widget.md +19 -17
  181. package/runtime/knowledge/patterns/child-blade-flow.md +19 -7
  182. package/runtime/knowledge/patterns/composable-details.md +20 -50
  183. package/runtime/knowledge/patterns/composable-list.md +43 -31
  184. package/runtime/knowledge/patterns/dashboard-widget.md +14 -16
  185. package/runtime/knowledge/patterns/datatable-pattern.md +521 -0
  186. package/runtime/knowledge/patterns/details-blade-pattern.md +78 -116
  187. package/runtime/knowledge/patterns/extension-points-usage.md +53 -44
  188. package/runtime/knowledge/patterns/form-validation.md +28 -64
  189. package/runtime/knowledge/patterns/list-blade-pattern.md +33 -21
  190. package/runtime/knowledge/patterns/module-structure.md +7 -1
  191. package/runtime/knowledge/patterns/multilanguage-fields.md +8 -14
  192. package/runtime/knowledge/patterns/notification-template.md +21 -14
  193. package/runtime/knowledge/patterns/signalr-notifications.md +30 -32
  194. package/runtime/knowledge/patterns/toolbar-pattern.md +18 -20
  195. package/runtime/vc-app.md +241 -62
@@ -0,0 +1,521 @@
1
+ # Data Table Pattern
2
+
3
+ List blades use `VcDataTable` with declarative `<VcColumn>` children to render paginated, sortable, searchable data grids with optional row selection and global filters.
4
+
5
+ ---
6
+
7
+ ## 1. Quick Start
8
+
9
+ Minimal list blade with three columns, sort, search, and pagination. No filters, no selection.
10
+
11
+ ### Template
12
+
13
+ ```vue
14
+ <template>
15
+ <VcBlade
16
+ :title="title"
17
+ :toolbar-items="bladeToolbar"
18
+ width="50%"
19
+ >
20
+ <VcDataTable
21
+ class="tw-grow tw-basis-0"
22
+ :loading="loading"
23
+ :items="items"
24
+ :total-count="pagination.totalCount"
25
+ :pagination="pagination"
26
+ v-model:active-item-id="selectedItemId"
27
+ v-model:sort-field="sortField"
28
+ v-model:sort-order="sortOrder"
29
+ state-key="entity_list"
30
+ :searchable="true"
31
+ @row-click="onItemClick"
32
+ @pagination-click="pagination.goToPage"
33
+ @search="onSearch"
34
+ >
35
+ <VcColumn
36
+ id="name"
37
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.NAME')"
38
+ :sortable="true"
39
+ :always-visible="true"
40
+ mobile-position="top-left"
41
+ />
42
+ <VcColumn
43
+ id="status"
44
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.STATUS')"
45
+ :sortable="true"
46
+ type="status"
47
+ mobile-role="status"
48
+ />
49
+ <VcColumn
50
+ id="createdDate"
51
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.CREATED_DATE')"
52
+ :sortable="true"
53
+ type="date-ago"
54
+ mobile-position="bottom-right"
55
+ />
56
+ </VcDataTable>
57
+ </VcBlade>
58
+ </template>
59
+ ```
60
+
61
+ ### Script
62
+
63
+ ```vue
64
+ <script lang="ts" setup>
65
+ import { ref, computed, watch, onMounted } from "vue";
66
+ import { IBladeToolbar, useBlade, useDataTableSort } from "@vc-shell/framework";
67
+ import { useI18n } from "vue-i18n";
68
+ import useEntities from "../composables/useEntities";
69
+
70
+ const { openBlade, exposeToChildren, param } = useBlade();
71
+ const { t } = useI18n({ useScope: "global" });
72
+ const { getEntities, searchQuery, loading, items, pagination } = useEntities();
73
+ const { sortField, sortOrder, sortExpression } = useDataTableSort({
74
+ initialField: "createdDate",
75
+ initialDirection: "DESC",
76
+ });
77
+
78
+ const selectedItemId = ref<string>();
79
+ const title = computed(() => t("MODULE.PAGES.LIST.TITLE"));
80
+ const bladeToolbar = ref<IBladeToolbar[]>([
81
+ {
82
+ id: "refresh",
83
+ icon: "lucide-refresh-cw",
84
+ title: computed(() => t("MODULE.PAGES.LIST.TOOLBAR.REFRESH")),
85
+ async clickHandler() {
86
+ await reload();
87
+ },
88
+ },
89
+ ]);
90
+
91
+ watch(sortExpression, async (val) => {
92
+ await getEntities({ ...searchQuery.value, sort: val });
93
+ });
94
+ onMounted(async () => {
95
+ await reload();
96
+ });
97
+
98
+ const reload = async () => {
99
+ await getEntities({ ...searchQuery.value, skip: pagination.skip, sort: sortExpression.value });
100
+ };
101
+ const onSearch = async (keyword: string | undefined) => {
102
+ await getEntities({ ...searchQuery.value, keyword, skip: 0, sort: sortExpression.value });
103
+ };
104
+ const onItemClick = (event: { data: { id?: string } }) => {
105
+ openBlade({
106
+ name: "EntityDetails",
107
+ param: event.data.id,
108
+ onOpen() {
109
+ selectedItemId.value = event.data.id;
110
+ },
111
+ onClose() {
112
+ selectedItemId.value = undefined;
113
+ },
114
+ });
115
+ };
116
+
117
+ exposeToChildren({ reload });
118
+ </script>
119
+ ```
120
+
121
+ ---
122
+
123
+ ## 2. Full Example
124
+
125
+ Demonstrates all major VcDataTable features: selection, global filters, pull-to-refresh, empty state, custom column body slots, and search header actions.
126
+
127
+ ### Template
128
+
129
+ ```vue
130
+ <template>
131
+ <VcBlade
132
+ :title="title"
133
+ :toolbar-items="toolbarItems"
134
+ width="50%"
135
+ >
136
+ <VcDataTable
137
+ v-model:active-item-id="selectedItemId"
138
+ v-model:sort-field="sortField"
139
+ v-model:sort-order="sortOrder"
140
+ v-model:selection="localSelection"
141
+ class="tw-grow tw-basis-0"
142
+ :loading="loading"
143
+ :items="items"
144
+ :total-count="pagination.totalCount"
145
+ :pagination="pagination"
146
+ :state-key="stateKey"
147
+ :searchable="true"
148
+ :selection-mode="multiselect ? 'multiple' : undefined"
149
+ :global-filters="computedGlobalFilters"
150
+ :pull-to-refresh="true"
151
+ :empty-state="{
152
+ icon: 'lucide-package-open',
153
+ title: $t('MODULE.PAGES.LIST.EMPTY.NO_ITEMS'),
154
+ actionLabel: $t('MODULE.PAGES.LIST.EMPTY.ADD'),
155
+ actionHandler: onAddItem,
156
+ }"
157
+ @row-click="onItemClick"
158
+ @pagination-click="pagination.goToPage"
159
+ @search="onSearch"
160
+ @filter="onFilter"
161
+ @pull-refresh="reload"
162
+ >
163
+ <!-- Slot for custom actions next to the search bar -->
164
+ <template #search-header-actions>
165
+ <VcButton
166
+ icon="lucide-sliders-horizontal"
167
+ variant="outline"
168
+ size="sm"
169
+ @click="toggleAdvancedView"
170
+ >
171
+ {{ $t("MODULE.PAGES.LIST.ACTIONS.TOGGLE_VIEW") }}
172
+ </VcButton>
173
+ </template>
174
+
175
+ <!-- Image column -->
176
+ <VcColumn
177
+ id="img"
178
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.IMAGE')"
179
+ :always-visible="true"
180
+ mobile-role="image"
181
+ type="image"
182
+ >
183
+ <template #body="{ data }">
184
+ <img
185
+ :src="data.imgSrc || '/placeholder.png'"
186
+ class="tw-w-10 tw-h-10 tw-rounded tw-object-cover"
187
+ />
188
+ </template>
189
+ </VcColumn>
190
+
191
+ <!-- Status column with custom body -->
192
+ <VcColumn
193
+ id="status"
194
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.STATUS')"
195
+ :sortable="true"
196
+ :always-visible="true"
197
+ mobile-role="status"
198
+ type="status"
199
+ >
200
+ <template #body="{ data }">
201
+ <VcStatus :variant="statusVariant(data.status)">
202
+ {{ data.status }}
203
+ </VcStatus>
204
+ </template>
205
+ </VcColumn>
206
+
207
+ <!-- Name column -->
208
+ <VcColumn
209
+ id="name"
210
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.NAME')"
211
+ :sortable="true"
212
+ :always-visible="true"
213
+ mobile-position="top-left"
214
+ />
215
+
216
+ <!-- Date column (built-in date-ago rendering) -->
217
+ <VcColumn
218
+ id="createdDate"
219
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.CREATED_DATE')"
220
+ :sortable="true"
221
+ type="date-ago"
222
+ />
223
+
224
+ <!-- Plain text column -->
225
+ <VcColumn
226
+ id="sku"
227
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.SKU')"
228
+ :always-visible="true"
229
+ mobile-position="bottom-left"
230
+ />
231
+
232
+ <!-- Boolean status-icon column -->
233
+ <VcColumn
234
+ id="isPublished"
235
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.PUBLISHED')"
236
+ :sortable="true"
237
+ mobile-position="bottom-right"
238
+ type="status-icon"
239
+ />
240
+
241
+ <!-- Nested property via :field dot-path -->
242
+ <VcColumn
243
+ id="category"
244
+ :field="'metadata.category'"
245
+ :title="t('MODULE.PAGES.LIST.TABLE.HEADER.CATEGORY')"
246
+ />
247
+ </VcDataTable>
248
+ </VcBlade>
249
+ </template>
250
+ ```
251
+
252
+ ### Script
253
+
254
+ ```vue
255
+ <script lang="ts" setup>
256
+ import { computed, ref, watch, onMounted } from "vue";
257
+ import { useI18n } from "vue-i18n";
258
+ import { IBladeToolbar, useBlade, usePopup, useDataTableSort } from "@vc-shell/framework";
259
+ import useEntities from "../composables/useEntities";
260
+
261
+ const { openBlade, exposeToChildren, param } = useBlade();
262
+ const { t } = useI18n({ useScope: "global" });
263
+ const { showConfirmation } = usePopup();
264
+ const { getEntities, deleteEntities, searchQuery, loading, items, pagination } = useEntities();
265
+
266
+ // Sort state
267
+ const { sortField, sortOrder, sortExpression } = useDataTableSort({
268
+ initialField: "createdDate",
269
+ initialDirection: "DESC",
270
+ });
271
+
272
+ const selectedItemId = ref<string>();
273
+ const multiselect = true;
274
+ const stateKey = "entity_list";
275
+
276
+ // Selection binding — syncs v-model:selection with local ref
277
+ const localSelection = ref<Record<string, unknown>[]>([]);
278
+
279
+ watch(
280
+ localSelection,
281
+ (newSelection) => {
282
+ // Process selection changes (e.g., update toolbar state)
283
+ },
284
+ { deep: true },
285
+ );
286
+
287
+ // Global filters configuration
288
+ const computedGlobalFilters = computed(() => {
289
+ return [
290
+ {
291
+ id: "status",
292
+ label: t("MODULE.PAGES.LIST.FILTERS.STATUS"),
293
+ filter: {
294
+ options: [
295
+ { value: "Active", label: t("MODULE.STATUSES.ACTIVE") },
296
+ { value: "Draft", label: t("MODULE.STATUSES.DRAFT") },
297
+ { value: "Archived", label: t("MODULE.STATUSES.ARCHIVED") },
298
+ ],
299
+ multiple: true,
300
+ },
301
+ },
302
+ ];
303
+ });
304
+
305
+ // Status variant mapping
306
+ const statusVariant = (status: string | undefined) => {
307
+ const map: Record<string, string> = {
308
+ Active: "success",
309
+ Published: "success",
310
+ Draft: "warning",
311
+ Pending: "warning",
312
+ Archived: "danger",
313
+ Cancelled: "danger",
314
+ };
315
+ return map[status ?? ""] ?? "info";
316
+ };
317
+
318
+ // Toolbar (computed to react to selection changes)
319
+ const toolbarItems = computed((): IBladeToolbar[] => {
320
+ const items: IBladeToolbar[] = [];
321
+
322
+ items.push({
323
+ id: "add",
324
+ icon: "lucide-plus",
325
+ title: t("MODULE.PAGES.LIST.TOOLBAR.ADD"),
326
+ clickHandler: () => onAddItem(),
327
+ });
328
+
329
+ items.push({
330
+ id: "refresh",
331
+ icon: "lucide-refresh-cw",
332
+ title: t("MODULE.PAGES.LIST.TOOLBAR.REFRESH"),
333
+ clickHandler: async () => await reload(),
334
+ });
335
+
336
+ items.push({
337
+ id: "deleteSelected",
338
+ icon: "lucide-trash-2",
339
+ title: t("MODULE.PAGES.LIST.TOOLBAR.DELETE"),
340
+ disabled: localSelection.value.length === 0,
341
+ clickHandler: async () => {
342
+ if (await showConfirmation(t("MODULE.ALERTS.DELETE_SELECTED"))) {
343
+ const ids = localSelection.value.map((item) => item.id as string);
344
+ await deleteEntities({ ids });
345
+ localSelection.value = [];
346
+ await reload();
347
+ }
348
+ },
349
+ });
350
+
351
+ return items;
352
+ });
353
+
354
+ // Sort reactivity
355
+ watch(sortExpression, async (val) => {
356
+ await getEntities({ ...searchQuery.value, sort: val });
357
+ });
358
+
359
+ // Track selected row when param changes
360
+ watch(
361
+ () => param.value,
362
+ (newVal) => {
363
+ selectedItemId.value = newVal;
364
+ },
365
+ { immediate: true, deep: true },
366
+ );
367
+
368
+ onMounted(async () => {
369
+ await getEntities({ sort: sortExpression.value });
370
+ });
371
+
372
+ const reload = async () => {
373
+ await getEntities({
374
+ ...searchQuery.value,
375
+ skip: pagination.skip,
376
+ sort: sortExpression.value,
377
+ });
378
+ };
379
+ // No manual onPaginationClick — pagination.goToPage handles it via useDataTablePagination
380
+
381
+ const onSearch = async (keyword: string | undefined) => {
382
+ await getEntities({ ...searchQuery.value, keyword, skip: 0, sort: sortExpression.value });
383
+ };
384
+
385
+ // Row click handler — event wraps row data in { data }
386
+ const onItemClick = (event: { data: { id?: string } }) => {
387
+ selectedItemId.value = event.data.id;
388
+ openBlade({
389
+ name: "EntityDetails",
390
+ param: event.data.id,
391
+ onOpen() {
392
+ selectedItemId.value = event.data.id;
393
+ },
394
+ onClose() {
395
+ selectedItemId.value = undefined;
396
+ },
397
+ });
398
+ };
399
+
400
+ async function onFilter(event: { filters: Record<string, unknown> }) {
401
+ const statusFilter = event.filters.status as string[] | undefined;
402
+ await getEntities({
403
+ ...searchQuery.value,
404
+ status: statusFilter ?? [],
405
+ skip: 0,
406
+ sort: sortExpression.value,
407
+ });
408
+ }
409
+
410
+ function onAddItem() {
411
+ openBlade({ name: "EntityDetails" });
412
+ }
413
+
414
+ function toggleAdvancedView() {
415
+ // Custom view toggle logic
416
+ }
417
+
418
+ // Expose methods to child blades (without title)
419
+ exposeToChildren({
420
+ reload,
421
+ onItemClick,
422
+ });
423
+ </script>
424
+ ```
425
+
426
+ ---
427
+
428
+ ## 3. VcColumn Props Reference
429
+
430
+ | Prop | Type | Description |
431
+ | ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- |
432
+ | `id` | `string` | Column identifier. Matches the item property name used to extract cell value. |
433
+ | `title` | `string` | Column header text. Accepts an i18n key or plain string. |
434
+ | `sortable` | `boolean` | Enable sorting on this column. Default `false`. |
435
+ | `always-visible` | `boolean` | Column cannot be hidden by the user via column settings. Default `false`. |
436
+ | `type` | `string` | Built-in cell renderer: `"date-ago"`, `"date-time"`, `"image"`, `"status"`, `"status-icon"`, `"money"`, `"number"`, `"date"`, `"datetime"`. |
437
+ | `width` | `string` | CSS width value (e.g., `"60px"`, `"120px"`, `"20%"`). |
438
+ | `visible` | `boolean` | Initial column visibility. Default `true`. Set `false` to hide by default (user can show via column settings). |
439
+ | `field` | `string` | Dot-path to nested property on the row item (e.g., `"metadata.category"`, `"productData.productType"`). Use when `id` alone cannot resolve the value. |
440
+ | `mobile-position` | `string` | Position in mobile card layout: `"top-left"`, `"top-right"`, `"bottom-left"`, `"bottom-right"`. |
441
+ | `mobile-role` | `string` | Special mobile rendering role: `"image"`, `"status"`, `"title"`, `"field"`. |
442
+
443
+ ### VcColumn Slots
444
+
445
+ | Slot | Scope | Description |
446
+ | ------- | ---------- | ----------------------------------------------------- |
447
+ | `#body` | `{ data }` | Custom cell body. `data` is the full row item object. |
448
+
449
+ ---
450
+
451
+ ## 4. VcDataTable Props Reference
452
+
453
+ | Prop | Type | Default | Description |
454
+ | ------------------------ | ----------------------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- |
455
+ | `items` | `unknown[]` | `[]` | Array of row items to display. |
456
+ | `total-count` | `number` | `0` | Total number of items (for pagination display). |
457
+ | `loading` | `boolean` | `false` | Shows loading indicator overlay. |
458
+ | `pagination` | `UseDataTablePaginationReturn` | -- | Pagination state from `useDataTablePagination()`. Contains `currentPage`, `pages`, `totalCount`, `skip`, `goToPage()`. |
459
+ | `v-model:active-item-id` | `string \| undefined` | -- | Two-way binding for the highlighted/active row id. |
460
+ | `v-model:sort-field` | `string` | -- | Two-way binding for the currently sorted column id. |
461
+ | `v-model:sort-order` | `0 \| 1 \| -1` | -- | Two-way binding for sort order (1=ASC, -1=DESC, 0=none). Use `useDataTableSort()` which manages this internally. |
462
+ | `v-model:selection` | `unknown[]` | -- | Two-way binding for selected row items. |
463
+ | `state-key` | `string` | -- | Unique key for persisting column widths/order/visibility to localStorage. Use snake_case (e.g., `"entity_list"`). |
464
+ | `searchable` | `boolean` | `false` | Shows the search input above the table. |
465
+ | `selection-mode` | `"multiple" \| undefined` | `undefined` | Enables row checkboxes for multi-select. Set to `"multiple"` to enable, `undefined` to disable. |
466
+ | `is-row-selectable` | `(item: unknown) => boolean` | -- | Predicate to control which rows can be selected. |
467
+ | `global-filters` | `GlobalFilter[] \| undefined` | `undefined` | Array of filter definitions shown above the table. |
468
+ | `pull-to-refresh` | `boolean` | `false` | Enables mobile pull-to-refresh gesture. |
469
+ | `empty-state` | `{ icon: string; title: string; actionLabel?: string; actionHandler?: () => void }` | -- | Configuration for empty state display when no items. |
470
+
471
+ ---
472
+
473
+ ## 5. Events Reference
474
+
475
+ | Event | Payload | Description |
476
+ | ------------------- | -------------------------------------- | ----------------------------------------------------------------------------------------------------------- |
477
+ | `@row-click` | `{ data: RowItem }` | Emitted when a row is clicked. The row item is wrapped in `{ data }`. |
478
+ | `@pagination-click` | `number` | Emitted when a pagination page button is clicked. Payload is the target page number (1-based). |
479
+ | `@search` | `string \| undefined` | Emitted when the user types in the search input. Payload is the search keyword or `undefined` when cleared. |
480
+ | `@filter` | `{ filters: Record<string, unknown> }` | Emitted when a global filter is applied. `filters` is a map of filter id to selected values. |
481
+ | `@pull-refresh` | -- | Emitted when the user triggers pull-to-refresh on mobile. |
482
+
483
+ ---
484
+
485
+ ## 6. Key Rules
486
+
487
+ 1. **Declare columns explicitly, NOT with `v-for`.** Each `<VcColumn>` must be a direct child in the template. This enables custom `#body` slots, per-column `mobile-role`/`mobile-position` attributes, and readable templates.
488
+
489
+ 2. **Row click event wraps data in `{ data }`.** The `@row-click` handler receives `{ data: RowItem }`, not the raw item. Always destructure: `const onItemClick = (event: { data: { id?: string } }) => { ... }`.
490
+
491
+ 3. **Use `useDataTableSort` for sort state.** It returns `sortField`, `sortOrder` (for v-model bindings), and `sortExpression` (computed `"field:DIR"` string for the API). Watch `sortExpression` to reload data when sort changes.
492
+
493
+ 4. **Selection requires a local ref.** Bind `v-model:selection` to a `localSelection` ref, then watch it to sync with external selection state or toolbar actions:
494
+
495
+ ```ts
496
+ const localSelection = ref<Item[]>([]);
497
+ watch(
498
+ localSelection,
499
+ (newSelection) => {
500
+ // Update toolbar state, selection handler, etc.
501
+ },
502
+ { deep: true },
503
+ );
504
+ ```
505
+
506
+ 5. **`state-key` must be unique across all modules.** Use snake_case naming: `"entity_list"`, `"another_list"`, `"team_members"`.
507
+
508
+ 6. **`exposeToChildren` should not include `title`.** Expose only callable methods like `reload` and `onItemClick`. The title is blade metadata, not a child-callable method.
509
+
510
+ 7. **Global filters structure:** Each filter is an object with `id`, `label`, and a `filter` object containing `options` (array of `{ value, label }`) and `multiple` (boolean). Return `undefined` from the computed to hide filters entirely.
511
+
512
+ 8. **Empty state requires all four properties** when you want an action button: `icon` (Lucide icon name), `title` (i18n string), `actionLabel` (button text), `actionHandler` (callback function). Omit `actionLabel` and `actionHandler` for a passive empty state.
513
+
514
+ 9. **Column `type` selection rules:**
515
+ - Date fields: use `"date-ago"` in list blades (relative time), not `"date-time"`
516
+ - Boolean fields (is*, has*, can\*): use `"status-icon"`
517
+ - Status/state enums: use `"status"` with a custom `#body` slot containing `VcStatus`
518
+ - Image URLs: use `"image"` with `mobile-role="image"`
519
+ - Currency fields: use `"money"`
520
+
521
+ 10. **`#search-header-actions` slot** renders custom buttons/controls adjacent to the search input. Use for view toggles, breadcrumbs, or additional action buttons that relate to the list as a whole.