@vc-shell/framework 1.1.0-alpha.4 → 1.1.0-alpha.6

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 (119) hide show
  1. package/core/composables/useMenuService/index.ts +20 -110
  2. package/core/composables/useWidgets/index.ts +2 -1
  3. package/core/plugins/modularity/index.ts +3 -3
  4. package/core/services/menu-service.ts +195 -0
  5. package/core/services/widget-service.ts +20 -0
  6. package/core/types/index.ts +1 -1
  7. package/dist/core/composables/useMenuService/index.d.ts +4 -10
  8. package/dist/core/composables/useMenuService/index.d.ts.map +1 -1
  9. package/dist/core/composables/useWidgets/index.d.ts +2 -1
  10. package/dist/core/composables/useWidgets/index.d.ts.map +1 -1
  11. package/dist/core/plugins/modularity/index.d.ts.map +1 -1
  12. package/dist/core/services/menu-service.d.ts +17 -0
  13. package/dist/core/services/menu-service.d.ts.map +1 -0
  14. package/dist/core/services/widget-service.d.ts +4 -0
  15. package/dist/core/services/widget-service.d.ts.map +1 -1
  16. package/dist/core/types/index.d.ts +1 -1
  17. package/dist/core/types/index.d.ts.map +1 -1
  18. package/dist/framework.js +220 -210
  19. package/dist/{index-CrxFDC2b.js → index-3ySdd-mG.js} +1 -1
  20. package/dist/{index-B1YR_MYV.js → index-B-nvqNbp.js} +1 -1
  21. package/dist/{index-xLYzNPa7.js → index-BQF2-UMe.js} +1 -1
  22. package/dist/{index-BBYyHeYA.js → index-BXlxP2d2.js} +1 -1
  23. package/dist/{index-Cf9Tz1ql.js → index-C7P-aBjd.js} +1 -1
  24. package/dist/{index-8LELHzw9.js → index-CO_2IshF.js} +1 -1
  25. package/dist/{index-BA98L1jI.js → index-CfyFpaKq.js} +1 -1
  26. package/dist/{index-DVljTjbf.js → index-Ci23AX3j.js} +1 -1
  27. package/dist/{index-D1JchciU.js → index-CyuFXG83.js} +1 -1
  28. package/dist/{index-CWKrD2Cd.js → index-D1rpRTKf.js} +1 -1
  29. package/dist/{index-BAeTsi-X.js → index-DLxTAT7x.js} +1 -1
  30. package/dist/{index-BuO5ByG9.js → index-DOVhosAY.js} +1 -1
  31. package/dist/{index-DLtsQ_PJ.js → index-DZAq0B3U.js} +23780 -23339
  32. package/dist/{index-BrUitdDo.js → index-DtkJ7xTB.js} +1 -1
  33. package/dist/{index-9lJxZE5w.js → index-DvGVm1rK.js} +1 -1
  34. package/dist/{index-RwX3kiZh.js → index-EDF1MDtU.js} +1 -1
  35. package/dist/{index-CJ5I7vTn.js → index-LjqdX6jw.js} +1 -1
  36. package/dist/index.css +1 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/injection-keys.d.ts +2 -0
  39. package/dist/injection-keys.d.ts.map +1 -1
  40. package/dist/shared/components/draggable-dashboard/DraggableDashboard.vue.d.ts +2 -0
  41. package/dist/shared/components/draggable-dashboard/DraggableDashboard.vue.d.ts.map +1 -1
  42. package/dist/shared/components/draggable-dashboard/composables/useCellSizeCalculator.d.ts +25 -0
  43. package/dist/shared/components/draggable-dashboard/composables/useCellSizeCalculator.d.ts.map +1 -0
  44. package/dist/shared/components/draggable-dashboard/composables/useCollisionDetection.d.ts +27 -0
  45. package/dist/shared/components/draggable-dashboard/composables/useCollisionDetection.d.ts.map +1 -0
  46. package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts +22 -0
  47. package/dist/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.d.ts.map +1 -1
  48. package/dist/shared/components/draggable-dashboard/composables/useDashboardGrid.d.ts +12 -4
  49. package/dist/shared/components/draggable-dashboard/composables/useDashboardGrid.d.ts.map +1 -1
  50. package/dist/shared/components/draggable-dashboard/composables/useDragClone.d.ts +15 -0
  51. package/dist/shared/components/draggable-dashboard/composables/useDragClone.d.ts.map +1 -0
  52. package/dist/shared/components/draggable-dashboard/composables/useEventCoordinates.d.ts +33 -0
  53. package/dist/shared/components/draggable-dashboard/composables/useEventCoordinates.d.ts.map +1 -0
  54. package/dist/shared/components/draggable-dashboard/composables/useGridPosition.d.ts +57 -0
  55. package/dist/shared/components/draggable-dashboard/composables/useGridPosition.d.ts.map +1 -0
  56. package/dist/shared/components/draggable-dashboard/composables/useGridSystem.d.ts +22 -0
  57. package/dist/shared/components/draggable-dashboard/composables/useGridSystem.d.ts.map +1 -0
  58. package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts +19 -0
  59. package/dist/shared/components/draggable-dashboard/composables/useLayoutPersistence.d.ts.map +1 -0
  60. package/dist/shared/components/draggable-dashboard/composables/useResizeObserver.d.ts +18 -0
  61. package/dist/shared/components/draggable-dashboard/composables/useResizeObserver.d.ts.map +1 -0
  62. package/dist/shared/components/draggable-dashboard/composables/useWidgetLayout.d.ts +14 -0
  63. package/dist/shared/components/draggable-dashboard/composables/useWidgetLayout.d.ts.map +1 -0
  64. package/dist/shared/components/draggable-dashboard/composables/useWidgetStyles.d.ts +21 -0
  65. package/dist/shared/components/draggable-dashboard/composables/useWidgetStyles.d.ts.map +1 -0
  66. package/dist/shared/components/draggable-dashboard/types.d.ts +5 -1
  67. package/dist/shared/components/draggable-dashboard/types.d.ts.map +1 -1
  68. package/dist/tsconfig.tsbuildinfo +1 -1
  69. package/dist/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue.d.ts +18 -0
  70. package/dist/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue.d.ts.map +1 -0
  71. package/dist/ui/components/atoms/vc-icon/icons/OffersIcon.vue.d.ts +18 -0
  72. package/dist/ui/components/atoms/vc-icon/icons/OffersIcon.vue.d.ts.map +1 -0
  73. package/dist/ui/components/atoms/vc-icon/icons/OrdersIcon.vue.d.ts +18 -0
  74. package/dist/ui/components/atoms/vc-icon/icons/OrdersIcon.vue.d.ts.map +1 -0
  75. package/dist/ui/components/atoms/vc-icon/icons/PeopleIcon.vue.d.ts +18 -0
  76. package/dist/ui/components/atoms/vc-icon/icons/PeopleIcon.vue.d.ts.map +1 -0
  77. package/dist/ui/components/atoms/vc-icon/icons/ProductsIcon.vue.d.ts +18 -0
  78. package/dist/ui/components/atoms/vc-icon/icons/ProductsIcon.vue.d.ts.map +1 -0
  79. package/dist/ui/components/atoms/vc-icon/icons/ProfileIcon.vue.d.ts +18 -0
  80. package/dist/ui/components/atoms/vc-icon/icons/ProfileIcon.vue.d.ts.map +1 -0
  81. package/dist/ui/components/atoms/vc-icon/icons/index.d.ts +6 -0
  82. package/dist/ui/components/atoms/vc-icon/icons/index.d.ts.map +1 -1
  83. package/dist/ui/components/atoms/vc-icon/vc-icon.vue.d.ts.map +1 -1
  84. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/components/app-bar-button/app-bar-button.vue.d.ts +1 -0
  85. package/dist/ui/components/organisms/vc-app/_internal/vc-app-bar/components/app-bar-button/app-bar-button.vue.d.ts.map +1 -1
  86. package/dist/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue.d.ts +2 -1
  87. 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
  88. package/dist/ui/components/organisms/vc-app/vc-app.vue.d.ts.map +1 -1
  89. package/dist/ui/components/organisms/vc-table/vc-table.vue.d.ts.map +1 -1
  90. package/package.json +4 -4
  91. package/shared/components/draggable-dashboard/DraggableDashboard.vue +114 -148
  92. package/shared/components/draggable-dashboard/composables/useCellSizeCalculator.ts +121 -0
  93. package/shared/components/draggable-dashboard/composables/useCollisionDetection.ts +219 -0
  94. package/shared/components/draggable-dashboard/composables/useDashboardDragAndDrop.ts +126 -331
  95. package/shared/components/draggable-dashboard/composables/useDashboardGrid.ts +74 -220
  96. package/shared/components/draggable-dashboard/composables/useDragClone.ts +97 -0
  97. package/shared/components/draggable-dashboard/composables/useEventCoordinates.ts +91 -0
  98. package/shared/components/draggable-dashboard/composables/useGridPosition.ts +150 -0
  99. package/shared/components/draggable-dashboard/composables/useGridSystem.ts +169 -0
  100. package/shared/components/draggable-dashboard/composables/useLayoutPersistence.ts +89 -0
  101. package/shared/components/draggable-dashboard/composables/useResizeObserver.ts +105 -0
  102. package/shared/components/draggable-dashboard/composables/useWidgetLayout.ts +264 -0
  103. package/shared/components/draggable-dashboard/composables/useWidgetStyles.ts +120 -0
  104. package/shared/components/draggable-dashboard/types.ts +6 -1
  105. package/shared/components/notification-dropdown/notification-dropdown.vue +1 -0
  106. package/ui/components/atoms/vc-icon/icons/FulfillmentCentersIcon.vue +27 -0
  107. package/ui/components/atoms/vc-icon/icons/OffersIcon.vue +23 -0
  108. package/ui/components/atoms/vc-icon/icons/OrdersIcon.vue +19 -0
  109. package/ui/components/atoms/vc-icon/icons/PeopleIcon.vue +21 -0
  110. package/ui/components/atoms/vc-icon/icons/ProductsIcon.vue +23 -0
  111. package/ui/components/atoms/vc-icon/icons/ProfileIcon.vue +18 -0
  112. package/ui/components/atoms/vc-icon/icons/index.ts +6 -0
  113. package/ui/components/atoms/vc-icon/vc-icon.vue +101 -82
  114. package/ui/components/organisms/vc-app/_internal/vc-app-bar/components/app-bar-button/app-bar-button.vue +10 -3
  115. package/ui/components/organisms/vc-app/_internal/vc-app-bar/vc-app-bar.vue +3 -4
  116. package/ui/components/organisms/vc-app/_internal/vc-app-menu/_internal/vc-app-menu-item/vc-app-menu-item.vue +2 -2
  117. package/ui/components/organisms/vc-app/_internal/vc-app-menu/vc-app-menu.vue +1 -0
  118. package/ui/components/organisms/vc-app/vc-app.vue +2 -3
  119. package/ui/components/organisms/vc-table/vc-table.vue +4 -1
@@ -0,0 +1,121 @@
1
+ import { ref, type Ref } from "vue";
2
+
3
+ /**
4
+ * Size of the cell
5
+ */
6
+ export interface CellSize {
7
+ width: number;
8
+ height: number;
9
+ }
10
+
11
+ /**
12
+ * Constants for calculations
13
+ */
14
+ const CELL_HEIGHT = 80; // Height of the cell, corresponds to the CSS variable --dashboard-cell-height
15
+ const HORIZONTAL_PADDING = 18; // Horizontal padding, corresponds to --dashboard-cell-gap-horizontal
16
+
17
+ /**
18
+ * Hook for calculating the sizes of dashboard cells
19
+ *
20
+ * Provides functions for calculating the sizes of cells with respect to the container size
21
+ * and caching for performance optimization
22
+ *
23
+ * @param gridColumns The number of columns in the grid
24
+ * @returns An object with functions for working with cell sizes
25
+ */
26
+ export function useCellSizeCalculator(gridColumns: number) {
27
+ // Cache for cell sizes for performance optimization
28
+ const cellSizeCache = ref<CellSize | null>(null);
29
+
30
+ // Previous container width for performance optimization
31
+ const previousContainerWidth = ref<number>(0);
32
+
33
+ /**
34
+ * Calculates the sizes of a cell based on the container size
35
+ *
36
+ * @param container The container element for calculating the sizes
37
+ * @param useCache Use cache for optimization (default is true)
38
+ * @returns The sizes of the cell
39
+ */
40
+ const calculateCellSize = (container: HTMLElement | null, useCache: boolean = true): CellSize => {
41
+ // If we use cache and it is not empty - return the cached value
42
+ if (useCache && cellSizeCache.value) return cellSizeCache.value;
43
+
44
+ // If the container is not defined, return zero sizes
45
+ if (!container) return { width: 0, height: CELL_HEIGHT };
46
+
47
+ // Get the sizes of the container
48
+ const rect = container.getBoundingClientRect();
49
+
50
+ // Calculate the available width taking into account the padding
51
+ const availableWidth = rect.width - 2 * HORIZONTAL_PADDING;
52
+
53
+ // Calculate the width of the cell
54
+ const cellWidth = availableWidth / gridColumns;
55
+
56
+ // Create an object with sizes
57
+ const size: CellSize = {
58
+ width: Math.max(cellWidth, 0), // Protection against negative values
59
+ height: CELL_HEIGHT,
60
+ };
61
+
62
+ // Update the cache
63
+ cellSizeCache.value = size;
64
+ previousContainerWidth.value = rect.width;
65
+
66
+ return size;
67
+ };
68
+
69
+ /**
70
+ * Clears the cache of cell sizes
71
+ */
72
+ const clearCache = (): void => {
73
+ cellSizeCache.value = null;
74
+ };
75
+
76
+ /**
77
+ * Checks if the sizes need to be recalculated based on the width change
78
+ *
79
+ * @param newWidth The new width of the container
80
+ * @returns true if recalculation is needed, false otherwise
81
+ */
82
+ const shouldRecalculate = (newWidth: number): boolean => {
83
+ if (previousContainerWidth.value === 0) return true;
84
+
85
+ const widthChange = Math.abs(newWidth - previousContainerWidth.value);
86
+ const widthChangePercent = (widthChange / previousContainerWidth.value) * 100;
87
+
88
+ // Recalculate if the change is greater than 5% or 50px
89
+ return widthChangePercent > 5 || widthChange > 50;
90
+ };
91
+
92
+ /**
93
+ * Handles the change of the container size
94
+ *
95
+ * @param container The container element
96
+ */
97
+ const handleContainerResize = (container: HTMLElement): void => {
98
+ if (!container) return;
99
+
100
+ const newWidth = container.getBoundingClientRect().width;
101
+
102
+ // Clear the cache for forced recalculation
103
+ clearCache();
104
+
105
+ // If the width has changed significantly, recalculate
106
+ if (shouldRecalculate(newWidth)) {
107
+ calculateCellSize(container, false);
108
+ }
109
+
110
+ // Update the previous width
111
+ previousContainerWidth.value = newWidth;
112
+ };
113
+
114
+ return {
115
+ calculateCellSize,
116
+ clearCache,
117
+ shouldRecalculate,
118
+ handleContainerResize,
119
+ previousContainerWidth,
120
+ };
121
+ }
@@ -0,0 +1,219 @@
1
+ import { ref } from "vue";
2
+ import type { IDashboardWidget, DashboardWidgetPosition } from "../types";
3
+
4
+ /**
5
+ * Composables for detecting and handling collisions between widgets
6
+ *
7
+ * Provides functions for checking widget intersections and calculating
8
+ * new positions for displaced widgets
9
+ *
10
+ * @returns An object with functions for working with collisions
11
+ */
12
+ export function useCollisionDetection() {
13
+ // Map of displaced widgets: widget id -> new position
14
+ const displacedWidgets = ref<Map<string, DashboardWidgetPosition>>(new Map());
15
+
16
+ /**
17
+ * Checks the intersection of two widgets
18
+ *
19
+ * @param widgetA The first widget
20
+ * @param posA The position of the first widget
21
+ * @param widgetB The second widget
22
+ * @param posB The position of the second widget
23
+ * @returns true if the widgets intersect
24
+ */
25
+ const intersect = (
26
+ widgetA: IDashboardWidget,
27
+ posA: DashboardWidgetPosition,
28
+ widgetB: IDashboardWidget,
29
+ posB: DashboardWidgetPosition,
30
+ ): boolean => {
31
+ // Early check by Y axis (if the difference is greater than the sum of heights, there is no intersection)
32
+ const verticalDistance = Math.abs(posA.y - posB.y);
33
+ if (verticalDistance > widgetA.size.height + widgetB.size.height) {
34
+ return false;
35
+ }
36
+
37
+ // Early check by X axis (if the difference is greater than the sum of widths, there is no intersection)
38
+ const horizontalDistance = Math.abs(posA.x - posB.x);
39
+ if (horizontalDistance > widgetA.size.width + widgetB.size.width) {
40
+ return false;
41
+ }
42
+
43
+ // Standard intersection check
44
+ const aLeft = posA.x;
45
+ const aRight = posA.x + widgetA.size.width;
46
+ const aTop = posA.y;
47
+ const aBottom = posA.y + widgetA.size.height;
48
+
49
+ const bLeft = posB.x;
50
+ const bRight = posB.x + widgetB.size.width;
51
+ const bTop = posB.y;
52
+ const bBottom = posB.y + widgetB.size.height;
53
+
54
+ return !(aRight <= bLeft || aLeft >= bRight || aBottom <= bTop || aTop >= bBottom);
55
+ };
56
+
57
+ /**
58
+ * Updates the list of displaced widgets based on the current position of the dragged widget
59
+ *
60
+ * @param draggedWidget The dragged widget
61
+ * @param previewPosition The current position of the dragged widget
62
+ * @param widgets All widgets on the dashboard
63
+ * @param layout The current dashboard layout (widget id -> position map)
64
+ */
65
+ const updateDisplacedWidgets = (
66
+ draggedWidget: IDashboardWidget | null,
67
+ previewPosition: DashboardWidgetPosition | null,
68
+ widgets: IDashboardWidget[],
69
+ layout: Map<string, DashboardWidgetPosition>,
70
+ ) => {
71
+ if (!draggedWidget || !previewPosition) {
72
+ displacedWidgets.value.clear();
73
+ return;
74
+ }
75
+
76
+ const newDisplacements = new Map<string, DashboardWidgetPosition>();
77
+ const processedWidgets = new Set<string>();
78
+
79
+ // Cache for initial collision checks
80
+ const directCollisionWidgets = new Set<string>();
81
+
82
+ // Check collisions with other widgets
83
+ for (const widget of widgets) {
84
+ if (widget.id === draggedWidget.id) continue;
85
+
86
+ const pos = layout.get(widget.id);
87
+ if (!pos) continue;
88
+
89
+ if (intersect(draggedWidget, previewPosition, widget, pos)) {
90
+ directCollisionWidgets.add(widget.id);
91
+ }
92
+ }
93
+
94
+ // If there are no direct collisions, skip additional calculations
95
+ if (directCollisionWidgets.size === 0) {
96
+ displacedWidgets.value = newDisplacements;
97
+ return;
98
+ }
99
+
100
+ // Sort widgets from top to bottom for more natural rearrangement
101
+ const sortedWidgets = [...widgets]
102
+ .filter((w) => w.id !== draggedWidget.id)
103
+ .sort((a, b) => {
104
+ const posA = layout.get(a.id);
105
+ const posB = layout.get(b.id);
106
+ if (!posA || !posB) return 0;
107
+ // Sort first by Y, then by X for more stable results
108
+ return posA.y === posB.y ? posA.x - posB.x : posA.y - posB.y;
109
+ });
110
+
111
+ // Function for checking collisions with caching
112
+ const collisionCache = new Map<string, boolean>();
113
+
114
+ const checkCollision = (widget: IDashboardWidget, position: DashboardWidgetPosition) => {
115
+ const cacheKey = `${widget.id}_${position.x}_${position.y}`;
116
+
117
+ if (collisionCache.has(cacheKey)) {
118
+ return collisionCache.get(cacheKey);
119
+ }
120
+
121
+ // Check intersection with the dragged widget
122
+ let hasCollision = intersect(draggedWidget, previewPosition, widget, position);
123
+
124
+ // Check intersections with already displaced widgets, if there is no collision with the dragged widget
125
+ if (!hasCollision) {
126
+ for (const [id, pos] of newDisplacements) {
127
+ const w = widgets.find((w) => w.id === id);
128
+ if (w && intersect(widget, position, w, pos)) {
129
+ hasCollision = true;
130
+ break;
131
+ }
132
+ }
133
+ }
134
+
135
+ collisionCache.set(cacheKey, hasCollision);
136
+ return hasCollision;
137
+ };
138
+
139
+ // First process widgets with direct collisions
140
+ for (const widget of sortedWidgets) {
141
+ if (processedWidgets.has(widget.id)) continue;
142
+
143
+ const currentPos = layout.get(widget.id);
144
+ if (!currentPos) continue;
145
+
146
+ // First focus on widgets with direct collisions
147
+ if (!directCollisionWidgets.has(widget.id) && newDisplacements.size === 0) continue;
148
+
149
+ // Check collisions in the current position
150
+ const hasCollision = checkCollision(widget, currentPos);
151
+
152
+ if (hasCollision) {
153
+ // Find a new position below the dragged widget
154
+ const newY = Math.max(previewPosition.y + draggedWidget.size.height, currentPos.y + 1);
155
+ let finalY = newY;
156
+
157
+ // Find the nearest position without collisions
158
+ const maxIterations = 50; // Protection against infinite loop
159
+ let iterations = 0;
160
+
161
+ while (checkCollision(widget, { x: currentPos.x, y: finalY }) && iterations < maxIterations) {
162
+ finalY++;
163
+ iterations++;
164
+ }
165
+
166
+ newDisplacements.set(widget.id, { x: currentPos.x, y: finalY });
167
+ processedWidgets.add(widget.id);
168
+
169
+ // If we have displaced a widget with a direct collision, check if we have created new collisions
170
+ for (const w of sortedWidgets) {
171
+ if (w.id !== widget.id && !processedWidgets.has(w.id)) {
172
+ const pos = layout.get(w.id);
173
+ if (pos && intersect(widget, { x: currentPos.x, y: finalY }, w, pos)) {
174
+ directCollisionWidgets.add(w.id);
175
+ }
176
+ }
177
+ }
178
+ }
179
+ }
180
+
181
+ displacedWidgets.value = newDisplacements;
182
+ };
183
+
184
+ /**
185
+ * Clears the list of displaced widgets
186
+ */
187
+ const clearDisplacedWidgets = () => {
188
+ displacedWidgets.value.clear();
189
+ };
190
+
191
+ /**
192
+ * Checks if the widget is displaced
193
+ *
194
+ * @param widgetId The ID of the widget
195
+ * @returns true if the widget is displaced
196
+ */
197
+ const isWidgetDisplaced = (widgetId: string) => {
198
+ return displacedWidgets.value.has(widgetId);
199
+ };
200
+
201
+ /**
202
+ * Gets the new position for the displaced widget
203
+ *
204
+ * @param widgetId The ID of the widget
205
+ * @returns The new position or undefined if the widget is not displaced
206
+ */
207
+ const getDisplacedPosition = (widgetId: string) => {
208
+ return displacedWidgets.value.get(widgetId);
209
+ };
210
+
211
+ return {
212
+ displacedWidgets,
213
+ intersect,
214
+ updateDisplacedWidgets,
215
+ clearDisplacedWidgets,
216
+ isWidgetDisplaced,
217
+ getDisplacedPosition,
218
+ };
219
+ }