@vc-shell/framework 1.2.3-beta.0 → 1.2.3

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 (244) hide show
  1. package/core/composables/index.ts +0 -2
  2. package/core/composables/useAssets/index.ts +28 -72
  3. package/core/composables/useAsync/index.ts +1 -4
  4. package/core/composables/useBladeRegistry/index.ts +5 -6
  5. package/core/composables/useBreadcrumbs/index.ts +1 -4
  6. package/core/composables/useErrorHandler/index.ts +1 -4
  7. package/core/composables/useFunctions/debounce.ts +1 -0
  8. package/core/composables/useFunctions/delay.ts +1 -0
  9. package/core/composables/useFunctions/index.ts +1 -0
  10. package/core/composables/useFunctions/once.ts +1 -0
  11. package/core/composables/useFunctions/sleep.ts +1 -0
  12. package/core/composables/useFunctions/throttle.ts +1 -0
  13. package/core/composables/useGlobalSearch/index.ts +3 -3
  14. package/core/composables/useMenuService/index.ts +12 -7
  15. package/core/composables/useNotifications/index.ts +2 -5
  16. package/core/composables/useTheme/index.ts +1 -4
  17. package/core/composables/useUser/index.ts +20 -189
  18. package/core/composables/useWidgets/index.ts +2 -5
  19. package/core/constants/index.ts +0 -2
  20. package/core/interceptors/index.ts +2 -5
  21. package/core/plugins/modularity/index.ts +6 -8
  22. package/core/plugins/modularity/loader.ts +33 -36
  23. package/core/plugins/signalR/index.ts +3 -6
  24. package/core/services/app-bar-menu-service.ts +1 -4
  25. package/core/services/dashboard-service.ts +1 -4
  26. package/core/services/global-search-service.ts +36 -0
  27. package/core/services/index.ts +0 -2
  28. package/core/services/menu-service.ts +41 -5
  29. package/core/services/settings-menu-service.ts +1 -4
  30. package/core/services/toolbar-service.ts +3 -18
  31. package/core/services/widget-service.ts +4 -7
  32. package/core/types/index.ts +47 -3
  33. package/core/utilities/index.ts +0 -2
  34. package/dist/core/composables/useAssets/index.d.ts.map +1 -1
  35. package/dist/core/composables/useAsync/index.d.ts.map +1 -1
  36. package/dist/core/composables/useBladeRegistry/index.d.ts.map +1 -1
  37. package/dist/core/composables/useBreadcrumbs/index.d.ts.map +1 -1
  38. package/dist/core/composables/useErrorHandler/index.d.ts.map +1 -1
  39. package/dist/core/composables/useFunctions/debounce.d.ts.map +1 -1
  40. package/dist/core/composables/useFunctions/delay.d.ts.map +1 -1
  41. package/dist/core/composables/useFunctions/index.d.ts.map +1 -1
  42. package/dist/core/composables/useFunctions/once.d.ts.map +1 -1
  43. package/dist/core/composables/useFunctions/sleep.d.ts.map +1 -1
  44. package/dist/core/composables/useFunctions/throttle.d.ts.map +1 -1
  45. package/dist/core/composables/useGlobalSearch/index.d.ts.map +1 -1
  46. package/dist/core/composables/useMenuService/index.d.ts +2 -2
  47. package/dist/core/composables/useMenuService/index.d.ts.map +1 -1
  48. package/dist/core/composables/useNotifications/index.d.ts.map +1 -1
  49. package/dist/core/composables/useTheme/index.d.ts.map +1 -1
  50. package/dist/core/composables/useUser/index.d.ts +0 -8
  51. package/dist/core/composables/useUser/index.d.ts.map +1 -1
  52. package/dist/core/composables/useWidgets/index.d.ts.map +1 -1
  53. package/dist/core/constants/index.d.ts +0 -2
  54. package/dist/core/constants/index.d.ts.map +1 -1
  55. package/dist/core/interceptors/index.d.ts.map +1 -1
  56. package/dist/core/plugins/modularity/index.d.ts.map +1 -1
  57. package/dist/core/plugins/modularity/loader.d.ts.map +1 -1
  58. package/dist/core/plugins/signalR/index.d.ts.map +1 -1
  59. package/dist/core/services/app-bar-menu-service.d.ts.map +1 -1
  60. package/dist/core/services/dashboard-service.d.ts.map +1 -1
  61. package/dist/core/services/global-search-service.d.ts +10 -0
  62. package/dist/core/services/global-search-service.d.ts.map +1 -0
  63. package/dist/core/services/menu-service.d.ts +24 -1
  64. package/dist/core/services/menu-service.d.ts.map +1 -1
  65. package/dist/core/services/settings-menu-service.d.ts.map +1 -1
  66. package/dist/core/services/toolbar-service.d.ts.map +1 -1
  67. package/dist/core/services/widget-service.d.ts.map +1 -1
  68. package/dist/core/types/index.d.ts +34 -0
  69. package/dist/core/types/index.d.ts.map +1 -1
  70. package/dist/core/utilities/index.d.ts +0 -2
  71. package/dist/core/utilities/index.d.ts.map +1 -1
  72. package/dist/framework.js +8664 -9720
  73. package/dist/index.css +1 -1
  74. package/dist/index.d.ts +0 -19
  75. package/dist/index.d.ts.map +1 -1
  76. package/dist/injection-keys.d.ts +6 -21
  77. package/dist/injection-keys.d.ts.map +1 -1
  78. package/dist/shared/components/app-switcher/composables/useAppSwitcher/index.d.ts.map +1 -1
  79. package/dist/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue.d.ts.map +1 -1
  80. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/index.d.ts.map +1 -1
  81. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.d.ts.map +1 -1
  82. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.d.ts.map +1 -1
  83. package/dist/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.d.ts.map +1 -1
  84. package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts.map +1 -1
  85. package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts.map +1 -1
  86. package/dist/shared/components/notifications/composables/useContainer/index.d.ts.map +1 -1
  87. package/dist/shared/components/notifications/composables/useInstance/index.d.ts.map +1 -1
  88. package/dist/shared/components/notifications/core/notification.d.ts.map +1 -1
  89. package/dist/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue.d.ts.map +1 -1
  90. package/dist/shared/components/sign-in/useExternalProvider.d.ts.map +1 -1
  91. package/dist/shared/composables/useExternalWidgets.d.ts.map +1 -1
  92. package/dist/shared/composables/useMenuExpanded.d.ts.map +1 -1
  93. package/dist/shared/composables/useTableSelection.d.ts.map +1 -1
  94. package/dist/shared/composables/useTableSort.d.ts.map +1 -1
  95. package/dist/shared/modules/assets-manager/components/assets-manager/assets-manager.vue.d.ts.map +1 -1
  96. package/dist/shared/pages/LoginPage/components/login/Login.vue.d.ts.map +1 -1
  97. package/dist/shared/utilities/colorUtils.d.ts +6 -0
  98. package/dist/shared/utilities/colorUtils.d.ts.map +1 -1
  99. package/dist/tsconfig.tsbuildinfo +1 -1
  100. package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts +3 -0
  101. package/dist/ui/components/atoms/vc-badge/vc-badge.vue.d.ts.map +1 -1
  102. package/dist/ui/components/atoms/vc-banner/vc-banner.vue.d.ts.map +1 -1
  103. package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts +15 -0
  104. package/dist/ui/components/atoms/vc-button/vc-button.vue.d.ts.map +1 -1
  105. package/dist/ui/components/atoms/vc-container/vc-container.vue.d.ts.map +1 -1
  106. package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts.map +1 -1
  107. package/dist/ui/components/atoms/vc-icon/vc-lucide-icon.vue.d.ts.map +1 -1
  108. package/dist/ui/components/atoms/vc-image/vc-image.vue.d.ts.map +1 -1
  109. package/dist/ui/components/atoms/vc-link/vc-link.vue.d.ts.map +1 -1
  110. package/dist/ui/components/atoms/vc-loading/vc-loading.vue.d.ts.map +1 -1
  111. package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts +5 -0
  112. package/dist/ui/components/atoms/vc-status/vc-status.vue.d.ts.map +1 -1
  113. package/dist/ui/components/atoms/vc-tooltip/vc-tooltip.vue.d.ts.map +1 -1
  114. package/dist/ui/components/atoms/vc-video/vc-video.vue.d.ts.map +1 -1
  115. package/dist/ui/components/atoms/vc-widget/vc-widget.vue.d.ts.map +1 -1
  116. package/dist/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue.d.ts.map +1 -1
  117. package/dist/ui/components/molecules/vc-input/vc-input.vue.d.ts.map +1 -1
  118. package/dist/ui/components/molecules/vc-pagination/vc-pagination.vue.d.ts.map +1 -1
  119. package/dist/ui/components/molecules/vc-toast/vc-toast.vue.d.ts.map +1 -1
  120. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/useBadge.d.ts +18 -0
  121. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/useBadge.d.ts.map +1 -0
  122. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts +4 -1
  123. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue.d.ts.map +1 -1
  124. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts +4 -1
  125. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts.map +1 -1
  126. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue.d.ts.map +1 -1
  127. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
  128. package/dist/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue.d.ts.map +1 -1
  129. package/dist/ui/components/organisms/vc-blade/vc-blade.vue.d.ts.map +1 -1
  130. package/dist/ui/components/organisms/vc-login-form/vc-login-form.vue.d.ts.map +1 -1
  131. package/dist/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue.d.ts.map +1 -1
  132. package/dist/ui/components/organisms/vc-table/composables/useTableActions.d.ts.map +1 -1
  133. package/dist/ui/components/organisms/vc-table/composables/useTableColumnResize.d.ts.map +1 -1
  134. package/dist/ui/components/organisms/vc-table/composables/useTableRowReorder.d.ts.map +1 -1
  135. package/dist/ui/components/organisms/vc-table/composables/useTableSelection.d.ts.map +1 -1
  136. package/dist/ui/components/organisms/vc-table/composables/useTableState.d.ts.map +1 -1
  137. package/dist/{vendor-lodash-es-SgOIjJF8.js → vendor-lodash-es-BqkGj3Jl.js} +0 -2
  138. package/package.json +5 -5
  139. package/shared/components/app-switcher/composables/useAppSwitcher/index.ts +1 -4
  140. package/shared/components/blade-navigation/components/vc-blade-navigation/vc-blade-navigation.vue +4 -67
  141. package/shared/components/blade-navigation/composables/useBladeNavigation/index.ts +10 -13
  142. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeActions.ts +4 -7
  143. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/bladeRouteResolver.ts +1 -4
  144. package/shared/components/blade-navigation/composables/useBladeNavigation/internal/routerUtils.ts +1 -4
  145. package/shared/components/change-password/change-password.vue +1 -1
  146. package/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.ts +5 -14
  147. package/shared/components/draggable-dashboard/composables/useLayoutPersistence.ts +2 -5
  148. package/shared/components/index.ts +0 -2
  149. package/shared/components/notifications/composables/useContainer/index.ts +6 -8
  150. package/shared/components/notifications/composables/useInstance/index.ts +1 -4
  151. package/shared/components/notifications/core/notification.ts +7 -10
  152. package/shared/components/popup-handler/components/vc-popup-container/vc-popup-container.vue +1 -20
  153. package/shared/components/sign-in/useExternalProvider.ts +4 -6
  154. package/shared/composables/useExternalWidgets.ts +4 -7
  155. package/shared/composables/useMenuExpanded.ts +1 -15
  156. package/shared/composables/useTableSelection.ts +0 -6
  157. package/shared/composables/useTableSort.ts +4 -4
  158. package/shared/modules/assets-manager/components/assets-manager/assets-manager.vue +3 -6
  159. package/shared/pages/LoginPage/components/login/Login.vue +1 -4
  160. package/shared/utilities/colorUtils.ts +12 -5
  161. package/ui/components/atoms/vc-badge/vc-badge.vue +59 -0
  162. package/ui/components/atoms/vc-banner/vc-banner.vue +1 -4
  163. package/ui/components/atoms/vc-button/vc-button.vue +25 -2
  164. package/ui/components/atoms/vc-container/vc-container.vue +3 -12
  165. package/ui/components/atoms/vc-icon/vc-icon.vue +10 -0
  166. package/ui/components/atoms/vc-icon/vc-lucide-icon.vue +2 -5
  167. package/ui/components/atoms/vc-image/vc-image.vue +1 -4
  168. package/ui/components/atoms/vc-link/vc-link.vue +54 -59
  169. package/ui/components/atoms/vc-loading/vc-loading.vue +0 -4
  170. package/ui/components/atoms/vc-status/vc-status.vue +5 -0
  171. package/ui/components/atoms/vc-status-icon/vc-status-icon.vue +4 -4
  172. package/ui/components/atoms/vc-tooltip/vc-tooltip.vue +1 -8
  173. package/ui/components/atoms/vc-video/vc-video.vue +2 -4
  174. package/ui/components/atoms/vc-widget/vc-widget.vue +1 -4
  175. package/ui/components/molecules/vc-breadcrumbs/vc-breadcrumbs.vue +2 -7
  176. package/ui/components/molecules/vc-input/vc-input.vue +1 -0
  177. package/ui/components/molecules/vc-pagination/vc-pagination.vue +1 -6
  178. package/ui/components/molecules/vc-rating/vc-rating.vue +1 -1
  179. package/ui/components/molecules/vc-textarea/vc-textarea.vue +1 -1
  180. package/ui/components/molecules/vc-toast/vc-toast.vue +1 -11
  181. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/useBadge.ts +80 -0
  182. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/_internal/vc-app-menu-link.vue +53 -10
  183. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +10 -1
  184. package/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +3 -0
  185. package/ui/components/organisms/vc-app/vc-app.vue +3 -22
  186. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/_internal/vc-blade-toolbar-buttons/_internal/vc-blade-toolbar-button/vc-blade-toolbar-button.vue +1 -4
  187. package/ui/components/organisms/vc-blade/_internal/vc-blade-toolbar/vc-blade-toolbar.vue +14 -14
  188. package/ui/components/organisms/vc-blade/vc-blade.vue +1 -3
  189. package/ui/components/organisms/vc-login-form/vc-login-form.vue +1 -3
  190. package/ui/components/organisms/vc-table/_internal/vc-table-cell/vc-table-cell.vue +2 -34
  191. package/ui/components/organisms/vc-table/composables/useTableActions.ts +10 -7
  192. package/ui/components/organisms/vc-table/composables/useTableColumnResize.ts +1 -4
  193. package/ui/components/organisms/vc-table/composables/useTableRowReorder.ts +2 -5
  194. package/ui/components/organisms/vc-table/composables/useTableSelection.ts +18 -26
  195. package/ui/components/organisms/vc-table/composables/useTableState.ts +1 -4
  196. package/core/constants/defaults.ts +0 -76
  197. package/core/constants/ui.ts +0 -68
  198. package/core/plugins/ai-agent/README.md +0 -336
  199. package/core/plugins/ai-agent/components/VcAiAgentPanel.vue +0 -125
  200. package/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue +0 -182
  201. package/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue +0 -77
  202. package/core/plugins/ai-agent/components/index.ts +0 -1
  203. package/core/plugins/ai-agent/composables/index.ts +0 -4
  204. package/core/plugins/ai-agent/composables/useAiAgent.ts +0 -231
  205. package/core/plugins/ai-agent/composables/useAiAgentContext.ts +0 -280
  206. package/core/plugins/ai-agent/constants.ts +0 -89
  207. package/core/plugins/ai-agent/index.ts +0 -91
  208. package/core/plugins/ai-agent/services/ai-agent-service.ts +0 -598
  209. package/core/plugins/ai-agent/types.ts +0 -310
  210. package/core/types/services.ts +0 -194
  211. package/core/utilities/errorTypes.ts +0 -126
  212. package/core/utilities/logger.ts +0 -120
  213. package/dist/core/constants/defaults.d.ts +0 -63
  214. package/dist/core/constants/defaults.d.ts.map +0 -1
  215. package/dist/core/constants/ui.d.ts +0 -50
  216. package/dist/core/constants/ui.d.ts.map +0 -1
  217. package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts +0 -3
  218. package/dist/core/plugins/ai-agent/components/VcAiAgentPanel.vue.d.ts.map +0 -1
  219. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts +0 -15
  220. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentHeader.vue.d.ts.map +0 -1
  221. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts +0 -10
  222. package/dist/core/plugins/ai-agent/components/_internal/VcAiAgentIframe.vue.d.ts.map +0 -1
  223. package/dist/core/plugins/ai-agent/components/index.d.ts +0 -2
  224. package/dist/core/plugins/ai-agent/components/index.d.ts.map +0 -1
  225. package/dist/core/plugins/ai-agent/composables/index.d.ts +0 -4
  226. package/dist/core/plugins/ai-agent/composables/index.d.ts.map +0 -1
  227. package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts +0 -95
  228. package/dist/core/plugins/ai-agent/composables/useAiAgent.d.ts.map +0 -1
  229. package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts +0 -55
  230. package/dist/core/plugins/ai-agent/composables/useAiAgentContext.d.ts.map +0 -1
  231. package/dist/core/plugins/ai-agent/constants.d.ts +0 -47
  232. package/dist/core/plugins/ai-agent/constants.d.ts.map +0 -1
  233. package/dist/core/plugins/ai-agent/index.d.ts +0 -48
  234. package/dist/core/plugins/ai-agent/index.d.ts.map +0 -1
  235. package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts +0 -45
  236. package/dist/core/plugins/ai-agent/services/ai-agent-service.d.ts.map +0 -1
  237. package/dist/core/plugins/ai-agent/types.d.ts +0 -258
  238. package/dist/core/plugins/ai-agent/types.d.ts.map +0 -1
  239. package/dist/core/types/services.d.ts +0 -169
  240. package/dist/core/types/services.d.ts.map +0 -1
  241. package/dist/core/utilities/errorTypes.d.ts +0 -61
  242. package/dist/core/utilities/errorTypes.d.ts.map +0 -1
  243. package/dist/core/utilities/logger.d.ts +0 -259
  244. package/dist/core/utilities/logger.d.ts.map +0 -1
@@ -0,0 +1,80 @@
1
+ import { computed, unref, isRef, type ComputedRef, type Ref } from "vue";
2
+ import type { MenuItemBadgeConfig, MenuItemBadge } from "./../../../../../../../../../core/types";
3
+ import { getMenuBadges } from "./../../../../../../../../../core/services/menu-service";
4
+
5
+ export interface ResolvedBadge {
6
+ content: string | number | undefined;
7
+ variant: "primary" | "success" | "warning" | "danger" | "info" | "secondary";
8
+ isDot: boolean;
9
+ isVisible: boolean;
10
+ }
11
+
12
+ /**
13
+ * Composable to resolve badge configuration for menu items.
14
+ * Supports direct badge config, routeId lookup, or groupId lookup.
15
+ *
16
+ * @param badgeConfig - Direct badge configuration (takes priority)
17
+ * @param routeId - Route ID to lookup badge from registry
18
+ * @param groupId - Group ID to lookup badge from registry
19
+ */
20
+ export function useBadge(
21
+ badgeConfig: MenuItemBadgeConfig | undefined,
22
+ routeId?: string,
23
+ groupId?: string,
24
+ ): ComputedRef<ResolvedBadge> {
25
+ const menuBadges = getMenuBadges();
26
+
27
+ return computed(() => {
28
+ // Priority: direct badge config > badge from registry by routeId > badge from registry by groupId
29
+ let config: MenuItemBadgeConfig | undefined = badgeConfig;
30
+ if (!config && routeId) {
31
+ config = menuBadges.value.get(routeId);
32
+ }
33
+ if (!config && groupId) {
34
+ config = menuBadges.value.get(groupId);
35
+ }
36
+
37
+ if (!config) {
38
+ return { content: undefined, variant: "primary", isDot: false, isVisible: false };
39
+ }
40
+
41
+ // Normalize shorthand to full config object
42
+ let badge: MenuItemBadge;
43
+ if (typeof config === "object" && !isRef(config) && "content" in config) {
44
+ badge = config as MenuItemBadge;
45
+ } else {
46
+ badge = { content: config as MenuItemBadge["content"] };
47
+ }
48
+
49
+ // Resolve reactive content
50
+ let rawContent: string | number | undefined = undefined;
51
+ if (typeof badge.content === "function") {
52
+ rawContent = badge.content();
53
+ } else if (isRef(badge.content)) {
54
+ rawContent = unref(badge.content as Ref<string | number | undefined>);
55
+ } else {
56
+ rawContent = badge.content;
57
+ }
58
+
59
+ // Truncate values > 99
60
+ let displayContent: string | number | undefined = rawContent;
61
+ if (typeof rawContent === "number" && rawContent > 99) {
62
+ displayContent = "99+";
63
+ } else if (typeof rawContent === "string") {
64
+ const numValue = parseInt(rawContent, 10);
65
+ if (!isNaN(numValue) && numValue > 99) {
66
+ displayContent = "99+";
67
+ }
68
+ }
69
+
70
+ const isDot = badge.isDot ?? false;
71
+ const isVisible = isDot || (displayContent != null && displayContent !== "" && displayContent !== 0);
72
+
73
+ return {
74
+ content: displayContent,
75
+ variant: badge.variant ?? "primary",
76
+ isDot,
77
+ isVisible,
78
+ };
79
+ });
80
+ }
@@ -45,6 +45,15 @@
45
45
  <div class="vc-app-menu-link__title-truncate">
46
46
  {{ $t(title ?? "") }}
47
47
  </div>
48
+ <VcBadge
49
+ v-if="resolvedBadge.isVisible"
50
+ :content="resolvedBadge.isDot ? undefined : resolvedBadge.content"
51
+ :variant="resolvedBadge.variant"
52
+ :is-dot="resolvedBadge.isDot"
53
+ size="s"
54
+ inline
55
+ class="vc-app-menu-link__badge"
56
+ />
48
57
  <div
49
58
  v-if="(!!children?.length && expand) || false"
50
59
  class="vc-app-menu-link__title-icon"
@@ -119,15 +128,28 @@
119
128
  {{ twoLettersTitle(nested.title) }}
120
129
  </div>
121
130
  <Transition name="opacity">
122
- <p
131
+ <div
123
132
  v-show="expand"
124
- class="vc-app-menu-link__child-item-title"
125
- :class="{
126
- 'vc-app-menu-link__child-item-title--no-icon': !nested.icon,
127
- }"
133
+ class="vc-app-menu-link__child-item-content"
128
134
  >
129
- {{ $t(nested.title) }}
130
- </p>
135
+ <p
136
+ class="vc-app-menu-link__child-item-title"
137
+ :class="{
138
+ 'vc-app-menu-link__child-item-title--no-icon': !nested.icon,
139
+ }"
140
+ >
141
+ {{ $t(nested.title) }}
142
+ </p>
143
+ <VcBadge
144
+ v-if="getChildBadge(nested).isVisible"
145
+ :content="getChildBadge(nested).isDot ? undefined : getChildBadge(nested).content"
146
+ :variant="getChildBadge(nested).variant"
147
+ :is-dot="getChildBadge(nested).isDot"
148
+ size="s"
149
+ inline
150
+ class="vc-app-menu-link__badge"
151
+ />
152
+ </div>
131
153
  </Transition>
132
154
  </div>
133
155
  </div>
@@ -139,9 +161,10 @@
139
161
 
140
162
  <script lang="ts" setup>
141
163
  import { ref, watch, computed, onMounted, Component, MaybeRef, unref } from "vue";
142
- import { MenuItem } from "./../../../../../../../../../core/types";
143
- import { VcIcon } from "./../../../../../../../";
164
+ import { MenuItem, MenuItemBadgeConfig } from "./../../../../../../../../../core/types";
165
+ import { VcIcon, VcBadge } from "./../../../../../../../";
144
166
  import { useRoute } from "vue-router";
167
+ import { useBadge } from "./useBadge";
145
168
 
146
169
  export interface Props {
147
170
  children?: MenuItem[];
@@ -151,6 +174,9 @@ export interface Props {
151
174
  url?: string;
152
175
  expand?: boolean;
153
176
  id?: string | number;
177
+ badge?: MenuItemBadgeConfig;
178
+ routeId?: string;
179
+ groupId?: string;
154
180
  }
155
181
 
156
182
  export interface Emits {
@@ -163,6 +189,14 @@ const props = withDefaults(defineProps<Props>(), {
163
189
 
164
190
  const emit = defineEmits<Emits>();
165
191
 
192
+ // Badge resolution for parent menu item
193
+ const resolvedBadge = useBadge(props.badge, props.routeId, props.groupId);
194
+
195
+ // Helper to get resolved badge for child items
196
+ const getChildBadge = (child: MenuItem) => {
197
+ return useBadge(child.badge, child.routeId, child.groupId).value;
198
+ };
199
+
166
200
  const isOpened = ref(false);
167
201
  const route = useRoute();
168
202
  const params = Object.fromEntries(Object.entries(route.params).filter(([key]) => key !== "pathMatch"));
@@ -346,7 +380,7 @@ watch(isOpened, (newValue) => {
346
380
 
347
381
  &__child-item {
348
382
  @apply tw-cursor-pointer tw-min-w-0 tw-flex tw-h-[var(--app-menu-item-height)]
349
- tw-items-center tw-transition-[padding] tw-duration-150 tw-w-full tw-py-2 tw-px-3
383
+ tw-items-center tw-transition-[padding] tw-duration-150 tw-w-full tw-py-2 tw-pl-3 tw-pr-2
350
384
  tw-text-[color:var(--app-menu-item-title-color)] tw-text-sm
351
385
  hover:tw-bg-[var(--app-menu-item-background-color-hover)]
352
386
  hover:tw-text-[color:var(--app-menu-item-title-color-active)] tw-gap-5;
@@ -389,6 +423,15 @@ watch(isOpened, (newValue) => {
389
423
  &__icon-collapsed {
390
424
  @apply tw-p-0 tw-m-0;
391
425
  }
426
+
427
+ // Badge styles for menu items - positioned after text
428
+ &__badge {
429
+ @apply tw-shrink-0 tw-ml-auto;
430
+ }
431
+
432
+ &__child-item-content {
433
+ @apply tw-flex tw-items-center tw-w-full tw-min-w-0;
434
+ }
392
435
  }
393
436
 
394
437
  .opacity-enter-active,
@@ -13,6 +13,9 @@
13
13
  :title="title ?? ''"
14
14
  :url="url"
15
15
  :expand="expand"
16
+ :badge="badge"
17
+ :route-id="routeId"
18
+ :group-id="groupId"
16
19
  @on-click="$emit('click')"
17
20
  />
18
21
  </router-link>
@@ -26,6 +29,9 @@
26
29
  :icon="icon ?? ''"
27
30
  :title="title ?? ''"
28
31
  :expand="expand"
32
+ :badge="badge"
33
+ :route-id="routeId"
34
+ :group-id="groupId"
29
35
  @on-click="$emit('click', $event)"
30
36
  />
31
37
  </template>
@@ -34,7 +40,7 @@
34
40
 
35
41
  <script lang="ts" setup>
36
42
  import VcAppMenuLink from "./_internal/vc-app-menu-link.vue";
37
- import { MenuItem } from "../../../../../../../../core/types";
43
+ import { MenuItem, MenuItemBadgeConfig } from "../../../../../../../../core/types";
38
44
  import type { Component } from "vue";
39
45
  export interface Props {
40
46
  sticky?: boolean;
@@ -45,6 +51,9 @@ export interface Props {
45
51
  children?: MenuItem[];
46
52
  expand?: boolean;
47
53
  id?: string | number;
54
+ badge?: MenuItemBadgeConfig;
55
+ routeId?: string;
56
+ groupId?: string;
48
57
  }
49
58
 
50
59
  export interface Emits {
@@ -36,6 +36,9 @@
36
36
  :title="item.title as string"
37
37
  :children="item.children"
38
38
  :expand="$isDesktop.value ? isExpanded || isHoverExpanded : true"
39
+ :badge="item.badge"
40
+ :route-id="item.routeId"
41
+ :group-id="item.groupId"
39
42
  @click="handleMenuItemClick(item, $event)"
40
43
  />
41
44
  </div>
@@ -30,8 +30,6 @@
30
30
  class="vc-app__workspace"
31
31
  >
32
32
  <VcBladeNavigation />
33
- <!-- AI Agent Panel (shown when plugin is installed) -->
34
- <VcAiAgentPanel v-if="aiAgentConfig?.url" />
35
33
  </div>
36
34
 
37
35
  <!-- Popup container -->
@@ -51,8 +49,6 @@ import {
51
49
  BladeRoutesRecord,
52
50
  } from "./../../../../shared/components";
53
51
  import { useAppSwitcher } from "../../../../shared/components/app-switcher/composables/useAppSwitcher";
54
- import { VcAiAgentPanel, provideAiAgentService } from "../../../../core/plugins/ai-agent";
55
- import type { IAiAgentConfig } from "../../../../core/plugins/ai-agent";
56
52
  import { provideAppBarWidget, useNotifications } from "../../../../core/composables";
57
53
  import { useRoute, useRouter } from "vue-router";
58
54
  import { watchOnce } from "@vueuse/core";
@@ -68,7 +64,6 @@ import { DynamicModulesKey, EMBEDDED_MODE } from "../../../../injection-keys";
68
64
  import { provideMenuService } from "../../../../core/composables/useMenuService";
69
65
  import { provideAppBarMobileButtonsService } from "../../../../core/composables/useAppBarMobileButtons";
70
66
  import { useUserManagement } from "../../../../core/composables/useUserManagement";
71
- import { createLogger } from "../../../../core/utilities";
72
67
 
73
68
  export interface Props {
74
69
  isReady: boolean;
@@ -97,13 +92,10 @@ defineSlots<{
97
92
  const props = defineProps<Props>();
98
93
  const slots = useSlots();
99
94
 
100
- const logger = createLogger("vc-app");
101
- logger.debug("Init vc-app");
95
+ console.debug("vc-app: Init vc-app");
102
96
 
103
97
  const internalRoutes = inject("bladeRoutes") as BladeRoutesRecord[];
104
98
  const dynamicModules = inject(DynamicModulesKey, undefined);
105
- const aiAgentConfig = inject<IAiAgentConfig | undefined>("aiAgentConfig", undefined);
106
- const aiAgentAddGlobalToolbarButton = inject<boolean>("aiAgentAddGlobalToolbarButton", true);
107
99
 
108
100
  const isAppReady = ref(props.isReady);
109
101
 
@@ -171,7 +163,7 @@ registerMobileButton({
171
163
  });
172
164
 
173
165
  const onMenuItemClick = function (item: MenuItem) {
174
- logger.debug("onMenuItemClick() called");
166
+ console.debug(`vc-app#onMenuItemClick() called.`);
175
167
 
176
168
  if (item.routeId) {
177
169
  const bladeComponent = resolveBladeByName(item.routeId);
@@ -183,7 +175,7 @@ const onMenuItemClick = function (item: MenuItem) {
183
175
  true,
184
176
  );
185
177
  } else {
186
- logger.error(`Blade component with routeId '${item.routeId}' not found.`);
178
+ console.error(`Blade component with routeId '${item.routeId}' not found.`);
187
179
  }
188
180
  } else if (!item.routeId && item.url) {
189
181
  const menuRoute = routes.find((r) => {
@@ -226,14 +218,6 @@ provideDashboardService();
226
218
  provideMenuService();
227
219
  provideGlobalSearch();
228
220
  provide(EMBEDDED_MODE, isEmbedded);
229
-
230
- // Provide AI Agent service if config is available (via plugin)
231
- if (aiAgentConfig?.url) {
232
- provideAiAgentService({
233
- config: aiAgentConfig,
234
- addGlobalToolbarButton: aiAgentAddGlobalToolbarButton,
235
- });
236
- }
237
221
  // Provide slots to child components with all necessary props and handlers
238
222
  provideAppSlots(
239
223
  slots,
@@ -261,9 +245,6 @@ onUnmounted(() => {
261
245
  <style lang="scss">
262
246
  :root {
263
247
  --app-background: var(--secondary-200);
264
- // Shared transition timing for synchronized animations
265
- --app-panel-transition-duration: 0.3s;
266
- --app-panel-transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
267
248
  }
268
249
 
269
250
  .vc-app {
@@ -43,9 +43,6 @@
43
43
  <script lang="ts" setup>
44
44
  import { ref } from "vue";
45
45
  import { VcIcon, VcTooltip } from "../../../../../../../../";
46
- import { createLogger } from "../../../../../../../../../../core/utilities";
47
-
48
- const logger = createLogger("vc-blade-toolbar-button");
49
46
 
50
47
  export interface Props {
51
48
  isExpanded: boolean;
@@ -84,7 +81,7 @@ const emit = defineEmits<Emits>();
84
81
  const isWaiting = ref(false);
85
82
 
86
83
  async function onClick(): Promise<void> {
87
- logger.debug("onClick()");
84
+ console.debug("vc-blade-toolbar-item#onClick()");
88
85
 
89
86
  if (!props.disabled && !isWaiting.value) {
90
87
  if (props.clickHandler && typeof props.clickHandler === "function") {
@@ -25,10 +25,10 @@ import { useLocalStorage } from "@vueuse/core";
25
25
  import { usePermissions, useToolbar } from "../../../../../../core/composables";
26
26
  import { IBladeToolbar } from "../../../../../../core/types";
27
27
  import VcBladeToolbarButtons from "./_internal/vc-blade-toolbar-buttons/vc-blade-toolbar-buttons.vue";
28
+ import { BladeInstance } from "../../../../../../injection-keys";
28
29
  import { FALLBACK_BLADE_ID } from "../../../../../../core/constants";
29
30
  import { IBladeInstance } from "../../../../../../shared/components/blade-navigation/types";
30
31
  import { IToolbarItem } from "../../../../../../core/services";
31
- import { useBlade } from "../../../../../../core/composables";
32
32
 
33
33
  export interface Props {
34
34
  items: IBladeToolbar[];
@@ -41,17 +41,21 @@ const props = withDefaults(defineProps<Props>(), {
41
41
  const slots = useSlots();
42
42
  const isExpanded = useLocalStorage("VC_BLADE_TOOLBAR_IS_EXPANDED", true);
43
43
  const { hasAccess } = usePermissions();
44
- const {
45
- registerToolbarItem,
46
- unregisterToolbarItem,
47
- getToolbarItems,
48
- clearBladeToolbarItems,
49
- updateToolbarItem,
50
- registeredToolbarItems,
51
- } = useToolbar();
44
+ const { registerToolbarItem, unregisterToolbarItem, getToolbarItems, clearBladeToolbarItems, updateToolbarItem } =
45
+ useToolbar();
52
46
 
53
47
  // Get the ID of the current blade
54
- const blade = useBlade();
48
+ const blade = inject<ComputedRef<IBladeInstance>>(
49
+ BladeInstance,
50
+ computed(() => ({
51
+ id: FALLBACK_BLADE_ID,
52
+ expandable: false,
53
+ maximized: false,
54
+ error: undefined,
55
+ navigation: undefined,
56
+ breadcrumbs: undefined,
57
+ })),
58
+ );
55
59
 
56
60
  const bladeId = computed(() => (blade.value?.id ?? FALLBACK_BLADE_ID).toLowerCase());
57
61
 
@@ -122,10 +126,6 @@ function clearToolbarItems(): void {
122
126
 
123
127
  // Filter visible items from service
124
128
  const visibleItems = computed(() => {
125
- // Access registeredToolbarItems.length to create reactive dependency
126
- // This ensures computed recalculates when new items are registered
127
- void registeredToolbarItems.length;
128
-
129
129
  return getToolbarItems()
130
130
  .filter(
131
131
  (item) =>
@@ -288,10 +288,8 @@ const openErrorDetails = () => {
288
288
  }
289
289
 
290
290
  .vc-blade {
291
- @apply tw-relative tw-flex tw-shrink-0 tw-flex-col tw-overflow-hidden;
291
+ @apply tw-relative tw-flex tw-shrink-0 tw-flex-col tw-overflow-hidden tw-transition-[width] tw-duration-200;
292
292
  @apply tw-bg-[color:var(--blade-background-color)] tw-border tw-border-solid tw-border-[--blade-border-color];
293
- // Use shared transition timing for synchronized animations with AI panel
294
- transition: width var(--app-panel-transition-duration, 0.3s) var(--app-panel-transition-timing, cubic-bezier(0.4, 0, 0.2, 1));
295
293
 
296
294
  &__back-button {
297
295
  @apply tw-mr-[14px];
@@ -24,7 +24,6 @@
24
24
  <script lang="ts" setup>
25
25
  import { computed } from "vue";
26
26
  import { useRouter } from "vue-router";
27
- import { createLogger } from "../../../../core/utilities";
28
27
 
29
28
  export interface Props {
30
29
  logo?: string;
@@ -58,8 +57,7 @@ const logoImageHandler = computed(() => {
58
57
 
59
58
  const version = router.currentRoute.value.meta?.appVersion;
60
59
 
61
- const logger = createLogger("vc-login-form");
62
- logger.debug("Init vc-login-form");
60
+ console.debug("Init vc-login-form");
63
61
  </script>
64
62
 
65
63
  <style lang="scss">
@@ -290,38 +290,6 @@ import { Field } from "vee-validate";
290
290
  import type { TableItem } from "../../types";
291
291
  import { ITableColumns } from "../../../../../../core/types";
292
292
 
293
- // Cache for sanitized HTML to avoid repeated DOMPurify calls across table cells
294
- const sanitizedHtmlCache = new Map<string, string>();
295
- const MAX_CACHE_SIZE = 500;
296
-
297
- function getSanitizedHtml(html: string): string {
298
- if (sanitizedHtmlCache.has(html)) {
299
- return sanitizedHtmlCache.get(html)!;
300
- }
301
-
302
- const sanitized = DOMPurify.default.sanitize(html, {
303
- ALLOWED_TAGS: [
304
- "p", "br", "strong", "em", "u", "s", "h1", "h2", "h3", "h4", "h5", "h6",
305
- "ul", "ol", "li", "blockquote", "pre", "code", "a", "img", "table",
306
- "thead", "tbody", "tr", "th", "td", "hr", "div", "span",
307
- ],
308
- ALLOWED_ATTR: ["href", "src", "alt", "title", "class", "id", "colspan", "rowspan", "align", "valign"],
309
- FORBID_TAGS: ["script", "object", "embed", "form", "input"],
310
- FORBID_ATTR: ["onerror", "onload", "onclick", "onmouseover", "onfocus", "onblur", "style"],
311
- });
312
-
313
- // Limit cache size to prevent memory leaks
314
- if (sanitizedHtmlCache.size >= MAX_CACHE_SIZE) {
315
- const firstKey = sanitizedHtmlCache.keys().next().value;
316
- if (firstKey !== undefined) {
317
- sanitizedHtmlCache.delete(firstKey);
318
- }
319
- }
320
-
321
- sanitizedHtmlCache.set(html, sanitized);
322
- return sanitized;
323
- }
324
-
325
293
  export interface Props {
326
294
  cell: ITableColumns;
327
295
  item: string | TableItem;
@@ -345,8 +313,8 @@ const value = computed((): any => _.get(props.item, props.cell.field || props.ce
345
313
  const isEditable = computed(() => props.cell.editable && props.editing);
346
314
 
347
315
  const sanitizedHtml = computed(() => {
348
- if (props.cell.type === "html" && value.value) {
349
- return getSanitizedHtml(String(value.value));
316
+ if (props.cell.type === "html") {
317
+ return DOMPurify.default.sanitize(value.value as string, { USE_PROFILES: { html: true } });
350
318
  }
351
319
  return "";
352
320
  });
@@ -20,13 +20,16 @@ export function useTableActions<T extends TableItem | string>(options: UseTableA
20
20
  const builder = unref(itemActionBuilder);
21
21
 
22
22
  if (unref(enableItemActions) && typeof builder === "function") {
23
- // Use Promise.all for parallel execution instead of sequential awaits
24
- const actionPromises = items
25
- .filter((item) => typeof item === "object")
26
- .map((item) => builder(item));
27
-
28
- const results = await Promise.all(actionPromises);
29
- itemActions.value = results.filter((result): result is IActionBuilderResult<T>[] => !!result);
23
+ const populatedItems: IActionBuilderResult<T>[][] = [];
24
+ for (let index = 0; index < items.length; index++) {
25
+ if (typeof items[index] === "object") {
26
+ const elementWithActions = await builder(items[index]);
27
+ if (elementWithActions) {
28
+ populatedItems.push(elementWithActions);
29
+ }
30
+ }
31
+ }
32
+ itemActions.value = populatedItems;
30
33
  } else {
31
34
  itemActions.value = [];
32
35
  }
@@ -1,8 +1,5 @@
1
1
  import { ref, Ref } from "vue";
2
2
  import { TableColPartial } from "../types";
3
- import { createLogger } from "../../../../../core/utilities";
4
-
5
- const logger = createLogger("vc-table-column-resize");
6
3
 
7
4
  export function useTableColumnResize(
8
5
  internalColumns: Ref<TableColPartial[]>,
@@ -38,7 +35,7 @@ export function useTableColumnResize(
38
35
  e.stopImmediatePropagation();
39
36
 
40
37
  if (!item.id) {
41
- logger.warn("Column has no id, cannot resize:", item);
38
+ console.warn("Column has no id, cannot resize:", item);
42
39
  return;
43
40
  }
44
41
 
@@ -1,8 +1,5 @@
1
1
  import { computed, ref, Ref } from "vue";
2
2
  import { TableItem } from "../types";
3
- import { createLogger } from "../../../../../core/utilities";
4
-
5
- const logger = createLogger("vc-table-row-reorder");
6
3
 
7
4
  export function useTableRowReorder<T extends TableItem | string>(
8
5
  items: Ref<T[]>,
@@ -30,7 +27,7 @@ export function useTableRowReorder<T extends TableItem | string>(
30
27
  function onRowMouseDown(event: MouseEvent) {
31
28
  if (event.currentTarget instanceof HTMLElement) {
32
29
  const row = event.currentTarget;
33
- logger.debug("Row mousedown event", row);
30
+ console.log("row", row);
34
31
  const rowRect = row.getBoundingClientRect();
35
32
 
36
33
  dragOffset.value = {
@@ -57,7 +54,7 @@ export function useTableRowReorder<T extends TableItem | string>(
57
54
  }
58
55
 
59
56
  function onRowDragStart(event: DragEvent, item: T) {
60
- logger.debug("Row drag start", { item });
57
+ console.log("onRowDragStart", event, item);
61
58
  rowDragged.value = true;
62
59
  const index = internalItems.value.indexOf(item);
63
60
  draggedRow.value = index;
@@ -1,16 +1,9 @@
1
1
  import { computed, ref, Ref, watch } from "vue";
2
2
  import { TableItem } from "../types";
3
+ import * as _ from "lodash-es";
3
4
 
4
5
  type TableItemType = TableItem | string;
5
6
 
6
- /**
7
- * Gets a unique identifier for a table item
8
- */
9
- function getItemId(item: TableItemType): string {
10
- if (typeof item === "string") return item;
11
- return (item as TableItem).id ?? JSON.stringify(item);
12
- }
13
-
14
7
  export interface UseTableSelectionOptions<T extends TableItemType> {
15
8
  items: Ref<T[]>;
16
9
  disableItemCheckbox?: (item: T) => boolean;
@@ -44,11 +37,8 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
44
37
  return selection.value.length === items.value.length && (options.totalCount || 0) > items.value.length;
45
38
  });
46
39
 
47
- // Use Set for O(1) selection lookups instead of O(n) array search with deep equality
48
- const selectionIds = computed(() => new Set(selection.value.map(getItemId)));
49
-
50
40
  function isSelected(item: T): boolean {
51
- return selectionIds.value.has(getItemId(item));
41
+ return selection.value.some((x) => _.isEqual(x, item));
52
42
  }
53
43
 
54
44
  function handleSelectAll(): void {
@@ -62,15 +52,14 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
62
52
  }
63
53
 
64
54
  function rowCheckbox(item: T): void {
65
- const itemId = getItemId(item);
66
- const disabledIds = new Set(disabledSelection.value.map(getItemId));
67
-
68
- if (disabledIds.has(itemId)) {
55
+ if (disabledSelection.value.includes(item)) {
69
56
  return;
70
57
  }
71
58
 
72
- if (selectionIds.value.has(itemId)) {
73
- selection.value = selection.value.filter((x) => getItemId(x) !== itemId);
59
+ const index = selection.value.findIndex((x) => _.isEqual(x, item));
60
+
61
+ if (index !== -1) {
62
+ selection.value = selection.value.filter((_, i) => i !== index);
74
63
  } else {
75
64
  selection.value = [...selection.value, item];
76
65
  }
@@ -78,11 +67,16 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
78
67
 
79
68
  async function handleMultiselect(items: T[]): Promise<void> {
80
69
  if (disableItemCheckbox && typeof disableItemCheckbox === "function") {
81
- // Use Promise.all for parallel execution instead of sequential awaits
82
- const objectItems = items.filter((item) => typeof item === "object");
83
- const results = await Promise.all(objectItems.map((item) => disableItemCheckbox(item)));
84
-
85
- disabledSelection.value = objectItems.filter((_, index) => results[index]);
70
+ const disabledMultiselect: T[] = [];
71
+ for (const item of items) {
72
+ if (typeof item === "object") {
73
+ const element = await disableItemCheckbox(item);
74
+ if (element) {
75
+ disabledMultiselect.push(item);
76
+ }
77
+ }
78
+ }
79
+ disabledSelection.value = disabledMultiselect;
86
80
  }
87
81
  }
88
82
 
@@ -90,9 +84,7 @@ export function useTableSelection<T extends TableItemType>(options: UseTableSele
90
84
  () => items.value,
91
85
  (newItems) => {
92
86
  handleMultiselect(newItems);
93
- // Use Set for O(1) lookups when filtering selection
94
- const newItemIds = new Set(newItems.map(getItemId));
95
- selection.value = selection.value.filter((item) => newItemIds.has(getItemId(item)));
87
+ selection.value = selection.value.filter((item) => newItems.includes(item));
96
88
  },
97
89
  { deep: true, immediate: true },
98
90
  );
@@ -4,9 +4,6 @@ import { useLocalStorage } from "@vueuse/core";
4
4
  import { cloneDeep, pick, unionBy } from "lodash-es";
5
5
  import { TableColPartial } from "../types";
6
6
  import { ITableColumns } from "../../../../../core/types";
7
- import { createLogger } from "../../../../../core/utilities";
8
-
9
- const logger = createLogger("vc-table-state");
10
7
 
11
8
  export interface UseTableStateOptions {
12
9
  stateKey: Ref<string, string>;
@@ -50,7 +47,7 @@ export function useTableState(options: UseTableStateOptions) {
50
47
  });
51
48
 
52
49
  function saveState() {
53
- logger.debug("Save state");
50
+ console.debug("[@vc-shell/framework#vc-table.vue] - Save state");
54
51
  const colsClone = cloneDeep(internalColumns.value);
55
52
  state.value = colsClone.map((col) => pick(col, "id", "visible", "width", "predefined", "title"));
56
53
  }