@strapi/admin 5.27.0 → 5.29.0

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 (101) hide show
  1. package/dist/admin/admin/src/components/DragLayer.js +67 -0
  2. package/dist/admin/admin/src/components/DragLayer.js.map +1 -0
  3. package/dist/admin/admin/src/components/DragLayer.mjs +64 -0
  4. package/dist/admin/admin/src/components/DragLayer.mjs.map +1 -0
  5. package/dist/admin/admin/src/components/FormInputs/Json.js +1 -1
  6. package/dist/admin/admin/src/components/FormInputs/Json.js.map +1 -1
  7. package/dist/admin/admin/src/components/FormInputs/Json.mjs +1 -1
  8. package/dist/admin/admin/src/components/FormInputs/Json.mjs.map +1 -1
  9. package/dist/admin/admin/src/components/GapDropZone.js +292 -0
  10. package/dist/admin/admin/src/components/GapDropZone.js.map +1 -0
  11. package/dist/admin/admin/src/components/GapDropZone.mjs +268 -0
  12. package/dist/admin/admin/src/components/GapDropZone.mjs.map +1 -0
  13. package/dist/admin/admin/src/components/ResizeIndicator.js +353 -0
  14. package/dist/admin/admin/src/components/ResizeIndicator.js.map +1 -0
  15. package/dist/admin/admin/src/components/ResizeIndicator.mjs +332 -0
  16. package/dist/admin/admin/src/components/ResizeIndicator.mjs.map +1 -0
  17. package/dist/admin/admin/src/components/SubNav.js +9 -2
  18. package/dist/admin/admin/src/components/SubNav.js.map +1 -1
  19. package/dist/admin/admin/src/components/SubNav.mjs +9 -2
  20. package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
  21. package/dist/admin/admin/src/components/WidgetRoot.js +216 -0
  22. package/dist/admin/admin/src/components/WidgetRoot.js.map +1 -0
  23. package/dist/admin/admin/src/components/WidgetRoot.mjs +195 -0
  24. package/dist/admin/admin/src/components/WidgetRoot.mjs.map +1 -0
  25. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  26. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  27. package/dist/admin/admin/src/features/Widgets.js +276 -0
  28. package/dist/admin/admin/src/features/Widgets.js.map +1 -0
  29. package/dist/admin/admin/src/features/Widgets.mjs +255 -0
  30. package/dist/admin/admin/src/features/Widgets.mjs.map +1 -0
  31. package/dist/admin/admin/src/hooks/useAPIErrorHandler.js +1 -1
  32. package/dist/admin/admin/src/hooks/useAPIErrorHandler.js.map +1 -1
  33. package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs +1 -1
  34. package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs.map +1 -1
  35. package/dist/admin/admin/src/pages/Home/HomePage.js +160 -91
  36. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  37. package/dist/admin/admin/src/pages/Home/HomePage.mjs +162 -93
  38. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  39. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js +189 -0
  40. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js.map +1 -0
  41. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs +168 -0
  42. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs.map +1 -0
  43. package/dist/admin/admin/src/services/homepage.js +11 -4
  44. package/dist/admin/admin/src/services/homepage.js.map +1 -1
  45. package/dist/admin/admin/src/services/homepage.mjs +11 -4
  46. package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
  47. package/dist/admin/admin/src/translations/en.json.js +8 -1
  48. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  49. package/dist/admin/admin/src/translations/en.json.mjs +8 -1
  50. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  51. package/dist/admin/admin/src/translations/uk.json.js +9 -9
  52. package/dist/admin/admin/src/translations/uk.json.mjs +9 -9
  53. package/dist/admin/admin/src/utils/resizeHandlers.js +109 -0
  54. package/dist/admin/admin/src/utils/resizeHandlers.js.map +1 -0
  55. package/dist/admin/admin/src/utils/resizeHandlers.mjs +100 -0
  56. package/dist/admin/admin/src/utils/resizeHandlers.mjs.map +1 -0
  57. package/dist/admin/admin/src/utils/widgetLayout.js +293 -0
  58. package/dist/admin/admin/src/utils/widgetLayout.js.map +1 -0
  59. package/dist/admin/admin/src/utils/widgetLayout.mjs +273 -0
  60. package/dist/admin/admin/src/utils/widgetLayout.mjs.map +1 -0
  61. package/dist/admin/src/components/DragLayer.d.ts +8 -4
  62. package/dist/admin/src/components/GapDropZone.d.ts +36 -0
  63. package/dist/admin/src/components/ResizeIndicator.d.ts +12 -0
  64. package/dist/admin/src/components/SubNav.d.ts +1 -1
  65. package/dist/admin/src/components/WidgetRoot.d.ts +14 -0
  66. package/dist/admin/src/features/Tracking.d.ts +1 -1
  67. package/dist/admin/src/features/Widgets.d.ts +29 -0
  68. package/dist/admin/src/pages/Home/HomePage.d.ts +4 -5
  69. package/dist/admin/src/pages/Home/components/AddWidgetModal.d.ts +10 -0
  70. package/dist/admin/src/services/homepage.d.ts +3 -3
  71. package/dist/admin/src/utils/resizeHandlers.d.ts +58 -0
  72. package/dist/admin/src/utils/widgetLayout.d.ts +78 -0
  73. package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
  74. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +4 -2
  75. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
  76. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +4 -2
  77. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
  78. package/dist/server/server/src/bootstrap.js +5 -0
  79. package/dist/server/server/src/bootstrap.js.map +1 -1
  80. package/dist/server/server/src/bootstrap.mjs +5 -0
  81. package/dist/server/server/src/bootstrap.mjs.map +1 -1
  82. package/dist/server/server/src/controllers/authentication.js +6 -6
  83. package/dist/server/server/src/controllers/authentication.js.map +1 -1
  84. package/dist/server/server/src/controllers/authentication.mjs +6 -6
  85. package/dist/server/server/src/controllers/authentication.mjs.map +1 -1
  86. package/dist/server/server/src/register.js +2 -1
  87. package/dist/server/server/src/register.js.map +1 -1
  88. package/dist/server/server/src/register.mjs +2 -1
  89. package/dist/server/server/src/register.mjs.map +1 -1
  90. package/dist/server/shared/utils/session-auth.js +14 -5
  91. package/dist/server/shared/utils/session-auth.js.map +1 -1
  92. package/dist/server/shared/utils/session-auth.mjs +14 -5
  93. package/dist/server/shared/utils/session-auth.mjs.map +1 -1
  94. package/dist/server/src/bootstrap.d.ts.map +1 -1
  95. package/dist/server/src/controllers/authentication.d.ts.map +1 -1
  96. package/dist/server/src/register.d.ts.map +1 -1
  97. package/dist/shared/contracts/homepage.d.ts +8 -4
  98. package/dist/shared/contracts/homepage.d.ts.map +1 -1
  99. package/dist/shared/utils/session-auth.d.ts +2 -2
  100. package/dist/shared/utils/session-auth.d.ts.map +1 -1
  101. package/package.json +7 -7
@@ -0,0 +1,273 @@
1
+ /**
2
+ *
3
+ * Comprehensive utilities for widget layout operations including sizing, positioning, and layout calculations.
4
+ *
5
+ * Constraints:
6
+ * - Maximum 3 widgets per row (since minimum widget width is 4 columns)
7
+ * - Widget widths are snapped to discrete values: 4 (1/3), 6 (1/2), 8 (2/3), 12 (3/3)
8
+ */ const WIDGET_SIZING = {
9
+ TOTAL_COLUMNS: 12,
10
+ MIN_WIDGET_WIDTH: 4,
11
+ DISCRETE_SIZES: [
12
+ 4,
13
+ 6,
14
+ 8,
15
+ 12
16
+ ]
17
+ };
18
+ const WIDGET_DATA_ATTRIBUTES = {
19
+ WIDGET_ID: 'data-strapi-widget-id',
20
+ GRID_CONTAINER: 'data-strapi-grid-container'
21
+ };
22
+ const getWidgetElement = (uid)=>{
23
+ return document.querySelector(`[${WIDGET_DATA_ATTRIBUTES.WIDGET_ID}="${uid}"]`);
24
+ };
25
+ const getWidgetGridContainer = ()=>{
26
+ return document.querySelector(`[${WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER}]`);
27
+ };
28
+ /**
29
+ * Validates if a widget width is valid (within constraints)
30
+ */ const isValidWidgetWidth = (width)=>{
31
+ return width >= WIDGET_SIZING.MIN_WIDGET_WIDTH && width <= WIDGET_SIZING.TOTAL_COLUMNS;
32
+ };
33
+ /**
34
+ * Validates if a resize operation is allowed between two widgets
35
+ */ const isValidResizeOperation = (leftWidth, rightWidth)=>{
36
+ // Check minimum size constraints
37
+ if (!isValidWidgetWidth(leftWidth) || !isValidWidgetWidth(rightWidth)) {
38
+ return false;
39
+ }
40
+ // Check if the total doesn't exceed row capacity
41
+ if (leftWidth + rightWidth > WIDGET_SIZING.TOTAL_COLUMNS) {
42
+ return false;
43
+ }
44
+ return true;
45
+ };
46
+ /**
47
+ * Gets widget width with fallback to default value
48
+ */ const getWidgetWidth = (columnWidths, widgetId, defaultWidth = 6)=>{
49
+ return widgetId ? columnWidths[widgetId] || defaultWidth : defaultWidth;
50
+ };
51
+ /**
52
+ * Calculates the current row structure from widgets and their widths
53
+ */ const calculateWidgetRows = (widgets, columnWidths)=>{
54
+ const rows = [];
55
+ let currentRow = [];
56
+ let currentRowWidth = 0;
57
+ let startIndex = 0;
58
+ widgets.forEach((widget, index)=>{
59
+ const widgetWidth = getWidgetWidth(columnWidths, widget.uid);
60
+ // If adding this widget would exceed 12 columns, start a new row
61
+ if (currentRowWidth + widgetWidth > WIDGET_SIZING.TOTAL_COLUMNS) {
62
+ if (currentRow.length > 0) {
63
+ rows.push({
64
+ widgets: currentRow,
65
+ totalWidth: currentRowWidth,
66
+ startIndex,
67
+ endIndex: startIndex + currentRow.length - 1
68
+ });
69
+ }
70
+ currentRow = [
71
+ widget
72
+ ];
73
+ currentRowWidth = widgetWidth;
74
+ startIndex = index;
75
+ } else {
76
+ currentRow.push(widget);
77
+ currentRowWidth += widgetWidth;
78
+ }
79
+ });
80
+ // Add the last row if it has widgets
81
+ if (currentRow.length > 0) {
82
+ rows.push({
83
+ widgets: currentRow,
84
+ totalWidth: currentRowWidth,
85
+ startIndex,
86
+ endIndex: startIndex + currentRow.length - 1
87
+ });
88
+ }
89
+ return rows;
90
+ };
91
+ /**
92
+ * Calculates optimal layout for a specific row based on widget count
93
+ * Only enforces constraints when necessary:
94
+ * - 1 widget in row: must be 3/3 (12 columns)
95
+ * - 3 widgets in row: must be 1/3+1/3+1/3 (4+4+4 columns)
96
+ * - 2 widgets in row: preserves existing proportions or uses 1/2+1/2
97
+ */ const calculateOptimalLayoutForRow = (widgetsInRow, currentColumnWidths)=>{
98
+ const newWidths = {
99
+ ...currentColumnWidths
100
+ };
101
+ const widgetCount = widgetsInRow.length;
102
+ if (widgetCount === 1) {
103
+ // Single widget must take full width (12)
104
+ newWidths[widgetsInRow[0].uid] = 12;
105
+ } else if (widgetCount === 3) {
106
+ // Three widgets must be equal (4 + 4 + 4)
107
+ widgetsInRow.forEach((widget)=>{
108
+ newWidths[widget.uid] = 4;
109
+ });
110
+ } else if (widgetCount === 2) {
111
+ // Two widgets can be flexible - preserve existing proportions or use 6 + 6
112
+ const currentWidths = widgetsInRow.map((widget)=>getWidgetWidth(currentColumnWidths, widget.uid));
113
+ const totalWidth = currentWidths.reduce((sum, width)=>sum + width, 0);
114
+ if (totalWidth === 12) {
115
+ // Row is already properly sized, preserve proportions
116
+ widgetsInRow.forEach((widget, index)=>{
117
+ newWidths[widget.uid] = currentWidths[index];
118
+ });
119
+ } else {
120
+ // Row needs adjustment, use equal split
121
+ widgetsInRow.forEach((widget)=>{
122
+ newWidths[widget.uid] = 6;
123
+ });
124
+ }
125
+ }
126
+ return newWidths;
127
+ };
128
+ const moveWidgetInArray = (widgets, widgetId, insertIndex)=>{
129
+ const currentIndex = widgets.findIndex((w)=>w.uid === widgetId);
130
+ if (currentIndex === -1) return widgets;
131
+ // Remove widget from current position
132
+ const widgetsWithoutMoved = widgets.filter((w)=>w.uid !== widgetId);
133
+ // Insert at new position (adjust index if moving forward)
134
+ const adjustedInsertIndex = insertIndex > currentIndex ? insertIndex - 1 : insertIndex;
135
+ const newWidgets = [
136
+ ...widgetsWithoutMoved
137
+ ];
138
+ newWidgets.splice(adjustedInsertIndex, 0, widgets[currentIndex]);
139
+ return newWidgets;
140
+ };
141
+ const findRowContainingWidget = (widgetRows, widgetId, widgets)=>{
142
+ const widgetIndex = widgets.findIndex((w)=>w.uid === widgetId);
143
+ if (widgetIndex === -1) return undefined;
144
+ return widgetRows.find((row)=>widgetIndex >= row.startIndex && widgetIndex <= row.endIndex);
145
+ };
146
+ const resizeRowAfterRemoval = (row, removedWidgetId, currentWidths)=>{
147
+ if (!row) return currentWidths;
148
+ const remainingWidgets = row.widgets.filter((w)=>w.uid !== removedWidgetId);
149
+ return calculateOptimalLayoutForRow(remainingWidgets, currentWidths);
150
+ };
151
+ const resizeRowAfterAddition = (row, addedWidget, insertIndex, currentWidths)=>{
152
+ if (!row) return currentWidths;
153
+ // Calculate the new widget arrangement for the target row
154
+ const targetRowWidgets = [
155
+ ...row.widgets
156
+ ];
157
+ const existingIndex = targetRowWidgets.findIndex((w)=>w.uid === addedWidget.uid);
158
+ if (existingIndex !== -1) {
159
+ // Widget was already in this row, just reorder
160
+ targetRowWidgets.splice(existingIndex, 1);
161
+ }
162
+ // Insert at the new position within the row
163
+ let insertPosition = insertIndex - row.startIndex;
164
+ // If insertIndex is at the end of the row (row.endIndex + 1),
165
+ // insert at the end of the row instead of beyond it
166
+ if (insertIndex === row.endIndex + 1) {
167
+ insertPosition = row.widgets.length;
168
+ }
169
+ targetRowWidgets.splice(insertPosition, 0, addedWidget);
170
+ return calculateOptimalLayoutForRow(targetRowWidgets, currentWidths);
171
+ };
172
+ const isLastWidgetInRow = (widgetIndex, widgets, columnWidths)=>{
173
+ if (widgetIndex >= widgets.length - 1) {
174
+ return true; // Last widget overall
175
+ }
176
+ let currentRowWidth = 0;
177
+ // Calculate the current row width by going through widgets from the start
178
+ for(let i = 0; i <= widgetIndex; i++){
179
+ const widgetWidth = getWidgetWidth(columnWidths, widgets[i]?.uid);
180
+ if (currentRowWidth + widgetWidth > WIDGET_SIZING.TOTAL_COLUMNS) {
181
+ // This widget starts a new row, so the previous widget was the last in its row
182
+ currentRowWidth = widgetWidth;
183
+ } else {
184
+ currentRowWidth += widgetWidth;
185
+ }
186
+ }
187
+ // Check if the next widget would fit in the current row
188
+ const nextWidgetWidth = getWidgetWidth(columnWidths, widgets[widgetIndex + 1]?.uid);
189
+ return currentRowWidth + nextWidgetWidth > WIDGET_SIZING.TOTAL_COLUMNS;
190
+ };
191
+ const canResizeBetweenWidgets = (leftWidgetId, rightWidgetId, columnWidths, widgets)=>{
192
+ const leftWidth = getWidgetWidth(columnWidths, leftWidgetId);
193
+ const rightWidth = getWidgetWidth(columnWidths, rightWidgetId);
194
+ // First check if the widgets are actually adjacent in the same row
195
+ const leftIndex = widgets.findIndex((w)=>w.uid === leftWidgetId);
196
+ const rightIndex = widgets.findIndex((w)=>w.uid === rightWidgetId);
197
+ // Widgets must be consecutive in the array and in the same row
198
+ if (rightIndex !== leftIndex + 1) {
199
+ return false;
200
+ }
201
+ // Check if they're in the same row by verifying the right widget isn't the first in a new row
202
+ if (isLastWidgetInRow(leftIndex, widgets, columnWidths)) {
203
+ return false; // Left widget is last in its row, so right widget starts a new row
204
+ }
205
+ // Check if either widget can be made smaller (must be > 4 columns)
206
+ // or if either widget can be made bigger (must be < 12 columns)
207
+ const canLeftShrink = leftWidth > WIDGET_SIZING.MIN_WIDGET_WIDTH;
208
+ const canRightShrink = rightWidth > WIDGET_SIZING.MIN_WIDGET_WIDTH;
209
+ const canLeftGrow = leftWidth < WIDGET_SIZING.TOTAL_COLUMNS;
210
+ const canRightGrow = rightWidth < WIDGET_SIZING.TOTAL_COLUMNS;
211
+ // Resizing is possible if either widget can shrink AND the other can grow
212
+ return canLeftShrink && canRightGrow || canRightShrink && canLeftGrow;
213
+ };
214
+ /**
215
+ * Filters widgets to only include those present in the homepage layout
216
+ */ const filterWidgetsByHomepageLayout = (widgets, homepageLayout)=>{
217
+ const createHomepageWidgetUidsSet = (homepageLayout)=>new Set(homepageLayout.widgets.map((w)=>w.uid));
218
+ const homepageWidgetUids = createHomepageWidgetUidsSet(homepageLayout);
219
+ return widgets.filter((widget)=>homepageWidgetUids.has(widget.uid));
220
+ };
221
+ /**
222
+ * Sorts widgets according to the homepage layout order
223
+ */ const sortWidgetsByHomepageLayout = (widgets, homepageLayout)=>{
224
+ const widgetOrderMap = new Map(homepageLayout.widgets.map((widget, index)=>[
225
+ widget.uid,
226
+ index
227
+ ]));
228
+ return [
229
+ ...widgets
230
+ ].sort((a, b)=>{
231
+ const aIndex = widgetOrderMap.get(a.uid) ?? Number.MAX_SAFE_INTEGER;
232
+ const bIndex = widgetOrderMap.get(b.uid) ?? Number.MAX_SAFE_INTEGER;
233
+ return aIndex - bIndex;
234
+ });
235
+ };
236
+ /**
237
+ * Applies homepage layout to widgets (filters, sorts, and extracts widths)
238
+ */ const applyHomepageLayout = (authorizedWidgets, homepageLayout)=>{
239
+ const layoutWidgets = filterWidgetsByHomepageLayout(authorizedWidgets, homepageLayout);
240
+ const sortedWidgets = sortWidgetsByHomepageLayout(layoutWidgets, homepageLayout);
241
+ // Extract widths from homepage layout
242
+ const widths = {};
243
+ homepageLayout.widgets.forEach(({ uid, width })=>{
244
+ widths[uid] = width;
245
+ });
246
+ return {
247
+ filteredWidgets: sortedWidgets,
248
+ widths
249
+ };
250
+ };
251
+ /**
252
+ * Creates default widget widths based on widget count
253
+ * Even count: all widgets get width 6
254
+ * Odd count: all widgets get width 6 except the last one which gets width 12
255
+ */ const createDefaultWidgetWidths = (widgets)=>{
256
+ const defaultWidths = {};
257
+ const widgetCount = widgets.length;
258
+ if (widgetCount > 0) {
259
+ if (widgetCount % 2 === 0) {
260
+ widgets.forEach((widget)=>{
261
+ defaultWidths[widget.uid] = 6;
262
+ });
263
+ } else {
264
+ widgets.forEach((widget, index)=>{
265
+ defaultWidths[widget.uid] = index === widgetCount - 1 ? 12 : 6;
266
+ });
267
+ }
268
+ }
269
+ return defaultWidths;
270
+ };
271
+
272
+ export { WIDGET_DATA_ATTRIBUTES, WIDGET_SIZING, applyHomepageLayout, calculateOptimalLayoutForRow, calculateWidgetRows, canResizeBetweenWidgets, createDefaultWidgetWidths, filterWidgetsByHomepageLayout, findRowContainingWidget, getWidgetElement, getWidgetGridContainer, getWidgetWidth, isLastWidgetInRow, isValidResizeOperation, isValidWidgetWidth, moveWidgetInArray, resizeRowAfterAddition, resizeRowAfterRemoval, sortWidgetsByHomepageLayout };
273
+ //# sourceMappingURL=widgetLayout.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"widgetLayout.mjs","sources":["../../../../../admin/src/utils/widgetLayout.ts"],"sourcesContent":["/**\n *\n * Comprehensive utilities for widget layout operations including sizing, positioning, and layout calculations.\n *\n * Constraints:\n * - Maximum 3 widgets per row (since minimum widget width is 4 columns)\n * - Widget widths are snapped to discrete values: 4 (1/3), 6 (1/2), 8 (2/3), 12 (3/3)\n */\n\nimport type { Homepage } from '../../../shared/contracts/homepage';\nimport type { WidgetWithUID } from '../core/apis/Widgets';\n\nexport const WIDGET_SIZING = {\n TOTAL_COLUMNS: 12,\n MIN_WIDGET_WIDTH: 4,\n DISCRETE_SIZES: [4, 6, 8, 12] as const,\n} as const;\n\nexport const WIDGET_DATA_ATTRIBUTES = {\n WIDGET_ID: 'data-strapi-widget-id',\n GRID_CONTAINER: 'data-strapi-grid-container',\n} as const;\n\nexport const getWidgetElement = (uid: string): HTMLElement | null => {\n return document.querySelector(`[${WIDGET_DATA_ATTRIBUTES.WIDGET_ID}=\"${uid}\"]`);\n};\n\nexport const getWidgetGridContainer = (): HTMLElement | null => {\n return document.querySelector(`[${WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER}]`);\n};\n\nexport interface WidgetRow {\n widgets: WidgetWithUID[];\n totalWidth: number;\n startIndex: number;\n endIndex: number;\n}\n\n/**\n * Validates if a widget width is valid (within constraints)\n */\nexport const isValidWidgetWidth = (width: number): boolean => {\n return width >= WIDGET_SIZING.MIN_WIDGET_WIDTH && width <= WIDGET_SIZING.TOTAL_COLUMNS;\n};\n\n/**\n * Validates if a resize operation is allowed between two widgets\n */\nexport const isValidResizeOperation = (leftWidth: number, rightWidth: number): boolean => {\n // Check minimum size constraints\n if (!isValidWidgetWidth(leftWidth) || !isValidWidgetWidth(rightWidth)) {\n return false;\n }\n\n // Check if the total doesn't exceed row capacity\n if (leftWidth + rightWidth > WIDGET_SIZING.TOTAL_COLUMNS) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Gets widget width with fallback to default value\n */\nexport const getWidgetWidth = (\n columnWidths: Record<string, number>,\n widgetId: string | undefined,\n defaultWidth: number = 6\n): number => {\n return widgetId ? columnWidths[widgetId] || defaultWidth : defaultWidth;\n};\n\n/**\n * Calculates the current row structure from widgets and their widths\n */\nexport const calculateWidgetRows = (\n widgets: WidgetWithUID[],\n columnWidths: Record<string, number>\n): WidgetRow[] => {\n const rows: WidgetRow[] = [];\n let currentRow: WidgetWithUID[] = [];\n let currentRowWidth = 0;\n let startIndex = 0;\n\n widgets.forEach((widget, index) => {\n const widgetWidth = getWidgetWidth(columnWidths, widget.uid);\n\n // If adding this widget would exceed 12 columns, start a new row\n if (currentRowWidth + widgetWidth > WIDGET_SIZING.TOTAL_COLUMNS) {\n if (currentRow.length > 0) {\n rows.push({\n widgets: currentRow,\n totalWidth: currentRowWidth,\n startIndex,\n endIndex: startIndex + currentRow.length - 1,\n });\n }\n currentRow = [widget];\n currentRowWidth = widgetWidth;\n startIndex = index;\n } else {\n currentRow.push(widget);\n currentRowWidth += widgetWidth;\n }\n });\n\n // Add the last row if it has widgets\n if (currentRow.length > 0) {\n rows.push({\n widgets: currentRow,\n totalWidth: currentRowWidth,\n startIndex,\n endIndex: startIndex + currentRow.length - 1,\n });\n }\n\n return rows;\n};\n\n/**\n * Calculates optimal layout for a specific row based on widget count\n * Only enforces constraints when necessary:\n * - 1 widget in row: must be 3/3 (12 columns)\n * - 3 widgets in row: must be 1/3+1/3+1/3 (4+4+4 columns)\n * - 2 widgets in row: preserves existing proportions or uses 1/2+1/2\n */\nexport const calculateOptimalLayoutForRow = (\n widgetsInRow: WidgetWithUID[],\n currentColumnWidths: Record<string, number>\n): Record<string, number> => {\n const newWidths = { ...currentColumnWidths };\n const widgetCount = widgetsInRow.length;\n\n if (widgetCount === 1) {\n // Single widget must take full width (12)\n newWidths[widgetsInRow[0].uid] = 12;\n } else if (widgetCount === 3) {\n // Three widgets must be equal (4 + 4 + 4)\n widgetsInRow.forEach((widget) => {\n newWidths[widget.uid] = 4;\n });\n } else if (widgetCount === 2) {\n // Two widgets can be flexible - preserve existing proportions or use 6 + 6\n const currentWidths = widgetsInRow.map((widget) =>\n getWidgetWidth(currentColumnWidths, widget.uid)\n );\n const totalWidth = currentWidths.reduce((sum, width) => sum + width, 0);\n\n if (totalWidth === 12) {\n // Row is already properly sized, preserve proportions\n widgetsInRow.forEach((widget, index) => {\n newWidths[widget.uid] = currentWidths[index];\n });\n } else {\n // Row needs adjustment, use equal split\n widgetsInRow.forEach((widget) => {\n newWidths[widget.uid] = 6;\n });\n }\n }\n\n return newWidths;\n};\n\nexport const moveWidgetInArray = (\n widgets: WidgetWithUID[],\n widgetId: string,\n insertIndex: number\n): WidgetWithUID[] => {\n const currentIndex = widgets.findIndex((w) => w.uid === widgetId);\n if (currentIndex === -1) return widgets;\n\n // Remove widget from current position\n const widgetsWithoutMoved = widgets.filter((w) => w.uid !== widgetId);\n\n // Insert at new position (adjust index if moving forward)\n const adjustedInsertIndex = insertIndex > currentIndex ? insertIndex - 1 : insertIndex;\n const newWidgets = [...widgetsWithoutMoved];\n newWidgets.splice(adjustedInsertIndex, 0, widgets[currentIndex]);\n\n return newWidgets;\n};\n\nexport const findRowContainingWidget = (\n widgetRows: WidgetRow[],\n widgetId: string,\n widgets: WidgetWithUID[]\n): WidgetRow | undefined => {\n const widgetIndex = widgets.findIndex((w) => w.uid === widgetId);\n if (widgetIndex === -1) return undefined;\n\n return widgetRows.find((row) => widgetIndex >= row.startIndex && widgetIndex <= row.endIndex);\n};\n\nexport const resizeRowAfterRemoval = (\n row: WidgetRow | undefined,\n removedWidgetId: string,\n currentWidths: Record<string, number>\n): Record<string, number> => {\n if (!row) return currentWidths;\n\n const remainingWidgets = row.widgets.filter((w) => w.uid !== removedWidgetId);\n return calculateOptimalLayoutForRow(remainingWidgets, currentWidths);\n};\n\nexport const resizeRowAfterAddition = (\n row: WidgetRow | undefined,\n addedWidget: WidgetWithUID,\n insertIndex: number,\n currentWidths: Record<string, number>\n): Record<string, number> => {\n if (!row) return currentWidths;\n\n // Calculate the new widget arrangement for the target row\n const targetRowWidgets = [...row.widgets];\n const existingIndex = targetRowWidgets.findIndex((w) => w.uid === addedWidget.uid);\n\n if (existingIndex !== -1) {\n // Widget was already in this row, just reorder\n targetRowWidgets.splice(existingIndex, 1);\n }\n\n // Insert at the new position within the row\n let insertPosition = insertIndex - row.startIndex;\n\n // If insertIndex is at the end of the row (row.endIndex + 1),\n // insert at the end of the row instead of beyond it\n if (insertIndex === row.endIndex + 1) {\n insertPosition = row.widgets.length;\n }\n\n targetRowWidgets.splice(insertPosition, 0, addedWidget);\n\n return calculateOptimalLayoutForRow(targetRowWidgets, currentWidths);\n};\n\nexport const isLastWidgetInRow = (\n widgetIndex: number,\n widgets: WidgetWithUID[],\n columnWidths: Record<string, number>\n): boolean => {\n if (widgetIndex >= widgets.length - 1) {\n return true; // Last widget overall\n }\n\n let currentRowWidth = 0;\n\n // Calculate the current row width by going through widgets from the start\n for (let i = 0; i <= widgetIndex; i++) {\n const widgetWidth = getWidgetWidth(columnWidths, widgets[i]?.uid);\n if (currentRowWidth + widgetWidth > WIDGET_SIZING.TOTAL_COLUMNS) {\n // This widget starts a new row, so the previous widget was the last in its row\n currentRowWidth = widgetWidth;\n } else {\n currentRowWidth += widgetWidth;\n }\n }\n\n // Check if the next widget would fit in the current row\n const nextWidgetWidth = getWidgetWidth(columnWidths, widgets[widgetIndex + 1]?.uid);\n return currentRowWidth + nextWidgetWidth > WIDGET_SIZING.TOTAL_COLUMNS;\n};\n\nexport const canResizeBetweenWidgets = (\n leftWidgetId: string,\n rightWidgetId: string,\n columnWidths: Record<string, number>,\n widgets: WidgetWithUID[]\n): boolean => {\n const leftWidth = getWidgetWidth(columnWidths, leftWidgetId);\n const rightWidth = getWidgetWidth(columnWidths, rightWidgetId);\n\n // First check if the widgets are actually adjacent in the same row\n const leftIndex = widgets.findIndex((w) => w.uid === leftWidgetId);\n const rightIndex = widgets.findIndex((w) => w.uid === rightWidgetId);\n\n // Widgets must be consecutive in the array and in the same row\n if (rightIndex !== leftIndex + 1) {\n return false;\n }\n\n // Check if they're in the same row by verifying the right widget isn't the first in a new row\n if (isLastWidgetInRow(leftIndex, widgets, columnWidths)) {\n return false; // Left widget is last in its row, so right widget starts a new row\n }\n\n // Check if either widget can be made smaller (must be > 4 columns)\n // or if either widget can be made bigger (must be < 12 columns)\n const canLeftShrink = leftWidth > WIDGET_SIZING.MIN_WIDGET_WIDTH;\n const canRightShrink = rightWidth > WIDGET_SIZING.MIN_WIDGET_WIDTH;\n const canLeftGrow = leftWidth < WIDGET_SIZING.TOTAL_COLUMNS;\n const canRightGrow = rightWidth < WIDGET_SIZING.TOTAL_COLUMNS;\n\n // Resizing is possible if either widget can shrink AND the other can grow\n return (canLeftShrink && canRightGrow) || (canRightShrink && canLeftGrow);\n};\n\n/**\n * Filters widgets to only include those present in the homepage layout\n */\nexport const filterWidgetsByHomepageLayout = (\n widgets: WidgetWithUID[],\n homepageLayout: Homepage.Layout\n): WidgetWithUID[] => {\n const createHomepageWidgetUidsSet = (homepageLayout: Homepage.Layout): Set<string> =>\n new Set(homepageLayout.widgets.map((w) => w.uid));\n const homepageWidgetUids = createHomepageWidgetUidsSet(homepageLayout);\n return widgets.filter((widget) => homepageWidgetUids.has(widget.uid));\n};\n\n/**\n * Sorts widgets according to the homepage layout order\n */\nexport const sortWidgetsByHomepageLayout = (\n widgets: WidgetWithUID[],\n homepageLayout: Homepage.Layout\n): WidgetWithUID[] => {\n const widgetOrderMap = new Map(\n homepageLayout.widgets.map((widget, index) => [widget.uid, index])\n );\n\n return [...widgets].sort((a, b) => {\n const aIndex = widgetOrderMap.get(a.uid) ?? Number.MAX_SAFE_INTEGER;\n const bIndex = widgetOrderMap.get(b.uid) ?? Number.MAX_SAFE_INTEGER;\n return aIndex - bIndex;\n });\n};\n\n/**\n * Applies homepage layout to widgets (filters, sorts, and extracts widths)\n */\nexport const applyHomepageLayout = (\n authorizedWidgets: WidgetWithUID[],\n homepageLayout: Homepage.Layout\n): {\n filteredWidgets: WidgetWithUID[];\n widths: Record<string, number>;\n} => {\n const layoutWidgets = filterWidgetsByHomepageLayout(authorizedWidgets, homepageLayout);\n const sortedWidgets = sortWidgetsByHomepageLayout(layoutWidgets, homepageLayout);\n\n // Extract widths from homepage layout\n const widths: Record<string, number> = {};\n homepageLayout.widgets.forEach(({ uid, width }) => {\n widths[uid] = width;\n });\n\n return {\n filteredWidgets: sortedWidgets,\n widths,\n };\n};\n\n/**\n * Creates default widget widths based on widget count\n * Even count: all widgets get width 6\n * Odd count: all widgets get width 6 except the last one which gets width 12\n */\nexport const createDefaultWidgetWidths = (widgets: WidgetWithUID[]): Record<string, number> => {\n const defaultWidths: Record<string, number> = {};\n const widgetCount = widgets.length;\n\n if (widgetCount > 0) {\n if (widgetCount % 2 === 0) {\n widgets.forEach((widget) => {\n defaultWidths[widget.uid] = 6;\n });\n } else {\n widgets.forEach((widget, index) => {\n defaultWidths[widget.uid] = index === widgetCount - 1 ? 12 : 6;\n });\n }\n }\n\n return defaultWidths;\n};\n"],"names":["WIDGET_SIZING","TOTAL_COLUMNS","MIN_WIDGET_WIDTH","DISCRETE_SIZES","WIDGET_DATA_ATTRIBUTES","WIDGET_ID","GRID_CONTAINER","getWidgetElement","uid","document","querySelector","getWidgetGridContainer","isValidWidgetWidth","width","isValidResizeOperation","leftWidth","rightWidth","getWidgetWidth","columnWidths","widgetId","defaultWidth","calculateWidgetRows","widgets","rows","currentRow","currentRowWidth","startIndex","forEach","widget","index","widgetWidth","length","push","totalWidth","endIndex","calculateOptimalLayoutForRow","widgetsInRow","currentColumnWidths","newWidths","widgetCount","currentWidths","map","reduce","sum","moveWidgetInArray","insertIndex","currentIndex","findIndex","w","widgetsWithoutMoved","filter","adjustedInsertIndex","newWidgets","splice","findRowContainingWidget","widgetRows","widgetIndex","undefined","find","row","resizeRowAfterRemoval","removedWidgetId","remainingWidgets","resizeRowAfterAddition","addedWidget","targetRowWidgets","existingIndex","insertPosition","isLastWidgetInRow","i","nextWidgetWidth","canResizeBetweenWidgets","leftWidgetId","rightWidgetId","leftIndex","rightIndex","canLeftShrink","canRightShrink","canLeftGrow","canRightGrow","filterWidgetsByHomepageLayout","homepageLayout","createHomepageWidgetUidsSet","Set","homepageWidgetUids","has","sortWidgetsByHomepageLayout","widgetOrderMap","Map","sort","a","b","aIndex","get","Number","MAX_SAFE_INTEGER","bIndex","applyHomepageLayout","authorizedWidgets","layoutWidgets","sortedWidgets","widths","filteredWidgets","createDefaultWidgetWidths","defaultWidths"],"mappings":"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"}
@@ -1,11 +1,15 @@
1
1
  import * as React from 'react';
2
2
  import { DragLayerMonitor } from 'react-dnd';
3
+ import type { WidgetArgs } from '../core/apis/Widgets';
4
+ export interface WidgetDragItem extends Pick<WidgetArgs, 'title' | 'icon' | 'link' | 'component'> {
5
+ type: 'widget';
6
+ id: string;
7
+ originalIndex: number;
8
+ }
9
+ export declare function isWidgetDragItem(item: unknown): item is WidgetDragItem;
3
10
  export interface DragLayerProps {
4
11
  renderItem: (item: {
5
- /**
6
- * TODO: it'd be great if we could make this a union where the type infers the item.
7
- */
8
- item: any;
12
+ item: unknown;
9
13
  type: ReturnType<DragLayerMonitor['getItemType']>;
10
14
  }) => React.ReactNode;
11
15
  }
@@ -0,0 +1,36 @@
1
+ import { type WidgetRow } from '../utils/widgetLayout';
2
+ import type { WidgetWithUID } from '../core/apis/Widgets';
3
+ export declare const DROP_ZONE_SIZE = 20;
4
+ export interface GapDropZonePosition {
5
+ insertIndex: number;
6
+ position: {
7
+ left: number;
8
+ top: number;
9
+ height: number;
10
+ width: number;
11
+ };
12
+ isVisible: boolean;
13
+ type: 'vertical' | 'horizontal';
14
+ isHorizontalDrop?: boolean;
15
+ targetRowIndex?: number;
16
+ }
17
+ interface GapDropZoneManagerProps {
18
+ filteredWidgets: WidgetWithUID[];
19
+ columnWidths: Record<string, number>;
20
+ draggedWidgetId?: string;
21
+ moveWidget: (id: string, to: number, targetRowIndex?: number, isHorizontalDrop?: boolean) => void;
22
+ }
23
+ declare const getRowInfo: (row: WidgetRow) => {
24
+ firstWidgetElement: HTMLElement;
25
+ lastWidgetElement: HTMLElement;
26
+ containerElement: HTMLElement;
27
+ firstRect: DOMRect;
28
+ lastRect: DOMRect;
29
+ containerRect: DOMRect;
30
+ rowHeight: number;
31
+ rowTop: number;
32
+ } | null;
33
+ export declare const addVerticalDropZones: (row: WidgetRow, rowInfo: ReturnType<typeof getRowInfo>, rowIndex: number) => GapDropZonePosition[];
34
+ export declare const addHorizontalDropZones: (row: WidgetRow, rowIndex: number, rowInfo: ReturnType<typeof getRowInfo>, widgetRows: WidgetRow[], filteredWidgets: WidgetWithUID[]) => GapDropZonePosition[];
35
+ export declare const GapDropZoneManager: ({ filteredWidgets, columnWidths, draggedWidgetId, moveWidget, }: GapDropZoneManagerProps) => import("react/jsx-runtime").JSX.Element[];
36
+ export {};
@@ -0,0 +1,12 @@
1
+ import type { WidgetWithUID } from '../core/apis/Widgets';
2
+ interface WidgetResizeHandleProps {
3
+ leftWidgetId: string;
4
+ rightWidgetId: string;
5
+ leftWidgetWidth: number;
6
+ rightWidgetWidth: number;
7
+ onResize: (leftWidgetId: string, rightWidgetId: string, newLeftWidth: number, newRightWidth: number) => void;
8
+ saveLayout: () => void;
9
+ filteredWidgets?: WidgetWithUID[];
10
+ }
11
+ export declare const WidgetResizeHandle: ({ leftWidgetId, rightWidgetId, leftWidgetWidth, rightWidgetWidth, onResize, saveLayout, }: WidgetResizeHandleProps) => import("react/jsx-runtime").JSX.Element;
12
+ export {};
@@ -20,7 +20,7 @@ export declare const SubNav: {
20
20
  }) => import("react/jsx-runtime").JSX.Element;
21
21
  Sections: ({ children, ...props }: {
22
22
  children: React.ReactNode[];
23
- [key: string]: any;
23
+ [key: string]: unknown;
24
24
  }) => import("react/jsx-runtime").JSX.Element;
25
25
  Section: ({ label, children, link, sectionId, badgeLabel, }: {
26
26
  label: string;
@@ -0,0 +1,14 @@
1
+ import * as React from 'react';
2
+ import type { FindWidgetFunction, WidgetIdFunction, DragEndFunction } from '../features/Widgets';
3
+ import type { WidgetType } from '@strapi/admin/strapi-admin';
4
+ export interface BaseWidgetProps extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {
5
+ findWidget?: FindWidgetFunction;
6
+ deleteWidget?: WidgetIdFunction;
7
+ onDragStart?: WidgetIdFunction;
8
+ onDragEnd?: DragEndFunction;
9
+ }
10
+ export interface WidgetRootProps extends BaseWidgetProps {
11
+ children: React.ReactNode;
12
+ component?: () => Promise<React.ComponentType>;
13
+ }
14
+ export declare const WidgetRoot: ({ title, icon, children, link, uid, findWidget, deleteWidget, onDragStart, onDragEnd, component, }: WidgetRootProps) => import("react/jsx-runtime").JSX.Element;
@@ -26,7 +26,7 @@ declare const TrackingProvider: ({ children }: TrackingProviderProps) => import(
26
26
  * event so understanding which properties go with which event is very helpful.
27
27
  */
28
28
  export interface EventWithoutProperties {
29
- name: 'changeComponentsOrder' | 'didAddComponentToDynamicZone' | 'didBulkDeleteEntries' | 'didNotBulkDeleteEntries' | 'didChangeDisplayedFields' | 'didCheckDraftRelations' | 'didClickGuidedTourHomepageApiTokens' | 'didClickGuidedTourHomepageContentManager' | 'didClickGuidedTourHomepageContentTypeBuilder' | 'didClickGuidedTourStep1CollectionType' | 'didClickGuidedTourStep2ContentManager' | 'didClickGuidedTourStep3ApiTokens' | 'didClickonBlogSection' | 'didClickonCodeExampleSection' | 'didClickonReadTheDocumentationSection' | 'didClickOnTryStrapiCloudSection' | 'didClickonTutorialSection' | 'didCreateGuidedTourCollectionType' | 'didCreateGuidedTourEntry' | 'didCreateNewRole' | 'didCreateRole' | 'didDeleteToken' | 'didDuplicateRole' | 'didEditEditSettings' | 'didEditEmailTemplates' | 'didEditFieldNameOnContentType' | 'didEditListSettings' | 'didEditMediaLibraryConfig' | 'didEditNameOfContentType' | 'didGenerateGuidedTourApiTokens' | 'didGoToMarketplace' | 'didLaunchGuidedtour' | 'didMissMarketplacePlugin' | 'didNotCreateFirstAdmin' | 'didNotSaveComponent' | 'didPluginLearnMore' | 'didBulkPublishEntries' | 'didNotBulkPublishEntries' | 'didUnpublishEntry' | 'didBulkUnpublishEntries' | 'didNotBulkUnpublishEntries' | 'didSaveComponent' | 'didSaveContentType' | 'didSearch' | 'didSkipGuidedtour' | 'didSubmitPlugin' | 'didSubmitProvider' | 'didUpdateConditions' | 'didSelectAllMediaLibraryElements' | 'didSelectContentTypeFieldSettings' | 'didSelectContentTypeSettings' | 'didEditAuthenticationProvider' | 'didRestoreHistoryVersion' | 'hasClickedCTBAddFieldBanner' | 'removeComponentFromDynamicZone' | 'willAddMoreFieldToContentType' | 'willBulkDeleteEntries' | 'willBulkPublishEntries' | 'willBulkUnpublishEntries' | 'willChangeNumberOfEntriesPerPage' | 'willCheckDraftRelations' | 'willCreateComponent' | 'willCreateComponentFromAttributesModal' | 'willCreateContentType' | 'willCreateFirstAdmin' | 'willCreateNewRole' | 'willCreateRole' | 'willCreateSingleType' | 'willCreateStage' | 'willCreateWorkflow' | 'willDeleteEntryFromList' | 'willDeleteFieldOfContentType' | 'willDuplicateRole' | 'willEditEditLayout' | 'willEditEmailTemplates' | 'willEditEntryFromButton' | 'willEditEntryFromList' | 'willEditReleaseFromHome' | 'willEditFieldOfContentType' | 'willEditMediaLibraryConfig' | 'willEditNameOfContentType' | 'willEditNameOfSingleType' | 'willEditAuthenticationProvider' | 'willEditFieldNameOnContentType' | 'willEditStage' | 'willFilterEntries' | 'willInstallPlugin' | 'willOpenAuditLogDetailsFromHome' | 'willUnpublishEntry' | 'willSaveComponent' | 'willSaveContentType' | 'willSaveContentTypeLayout' | 'didEditFieldNameOnContentType' | 'didCreateRelease' | 'didStartNewChat' | 'didLaunchGuidedtour';
29
+ name: 'changeComponentsOrder' | 'didAddComponentToDynamicZone' | 'didBulkDeleteEntries' | 'didNotBulkDeleteEntries' | 'didChangeDisplayedFields' | 'didCheckDraftRelations' | 'didClickGuidedTourHomepageApiTokens' | 'didClickGuidedTourHomepageContentManager' | 'didClickGuidedTourHomepageContentTypeBuilder' | 'didClickGuidedTourStep1CollectionType' | 'didClickGuidedTourStep2ContentManager' | 'didClickGuidedTourStep3ApiTokens' | 'didClickonBlogSection' | 'didClickonCodeExampleSection' | 'didClickonReadTheDocumentationSection' | 'didClickOnTryStrapiCloudSection' | 'didClickonTutorialSection' | 'didCreateGuidedTourCollectionType' | 'didCreateGuidedTourEntry' | 'didCreateNewRole' | 'didCreateRole' | 'didDeleteToken' | 'didDuplicateRole' | 'didEditEditSettings' | 'didEditEmailTemplates' | 'didEditFieldNameOnContentType' | 'didEditListSettings' | 'didEditMediaLibraryConfig' | 'didEditNameOfContentType' | 'didGenerateGuidedTourApiTokens' | 'didGoToMarketplace' | 'didLaunchGuidedtour' | 'didMissMarketplacePlugin' | 'didNotCreateFirstAdmin' | 'didNotSaveComponent' | 'didPluginLearnMore' | 'didBulkPublishEntries' | 'didNotBulkPublishEntries' | 'didUnpublishEntry' | 'didBulkUnpublishEntries' | 'didNotBulkUnpublishEntries' | 'didSaveComponent' | 'didSaveContentType' | 'didSearch' | 'didSkipGuidedtour' | 'didSubmitPlugin' | 'didSubmitProvider' | 'didUpdateConditions' | 'didSelectAllMediaLibraryElements' | 'didSelectContentTypeFieldSettings' | 'didSelectContentTypeSettings' | 'didEditAuthenticationProvider' | 'didRestoreHistoryVersion' | 'hasClickedCTBAddFieldBanner' | 'removeComponentFromDynamicZone' | 'willAddMoreFieldToContentType' | 'willBulkDeleteEntries' | 'willBulkPublishEntries' | 'willBulkUnpublishEntries' | 'willChangeNumberOfEntriesPerPage' | 'willCheckDraftRelations' | 'willCreateComponent' | 'willCreateComponentFromAttributesModal' | 'willCreateContentType' | 'willCreateFirstAdmin' | 'willCreateNewRole' | 'willCreateRole' | 'willCreateSingleType' | 'willCreateStage' | 'willCreateWorkflow' | 'willDeleteEntryFromList' | 'willDeleteFieldOfContentType' | 'willDuplicateRole' | 'willEditEditLayout' | 'willEditEmailTemplates' | 'willEditEntryFromButton' | 'willEditEntryFromList' | 'willEditReleaseFromHome' | 'willEditFieldOfContentType' | 'willEditMediaLibraryConfig' | 'willEditNameOfContentType' | 'willEditNameOfSingleType' | 'willEditAuthenticationProvider' | 'willEditFieldNameOnContentType' | 'willEditStage' | 'willFilterEntries' | 'willInstallPlugin' | 'willOpenAuditLogDetailsFromHome' | 'willUnpublishEntry' | 'willSaveComponent' | 'willSaveContentType' | 'willSaveContentTypeLayout' | 'didEditFieldNameOnContentType' | 'didCreateRelease' | 'didStartNewChat' | 'didLaunchGuidedtour' | 'didEditAICaption' | 'didEditAIAlternativeText';
30
30
  properties?: never;
31
31
  }
32
32
  interface DidAccessAuthenticatedAdministrationEvent {
@@ -0,0 +1,29 @@
1
+ import * as React from 'react';
2
+ import type { WidgetWithUID } from '../core/apis/Widgets';
3
+ import type { WidgetType } from '@strapi/admin/strapi-admin';
4
+ export interface WidgetInfo {
5
+ widget: WidgetType | undefined;
6
+ index: number;
7
+ }
8
+ export type FindWidgetFunction = (id: string) => WidgetInfo;
9
+ export type WidgetIdFunction = (id: string) => void;
10
+ export type DragEndFunction = () => void;
11
+ interface UseWidgetsOptions {
12
+ filteredWidgets: WidgetWithUID[];
13
+ setFilteredWidgets: (widgets: WidgetWithUID[] | ((prev: WidgetWithUID[]) => WidgetWithUID[])) => void;
14
+ }
15
+ export declare const useWidgets: ({ filteredWidgets, setFilteredWidgets }: UseWidgetsOptions) => {
16
+ findWidget: FindWidgetFunction;
17
+ deleteWidget: WidgetIdFunction;
18
+ addWidget: (widget: WidgetWithUID) => void;
19
+ moveWidget: (widgetId: string, insertIndex: number, targetRowIndex?: number, isHorizontalDrop?: boolean) => void;
20
+ columnWidths: Record<string, number>;
21
+ setColumnWidths: React.Dispatch<React.SetStateAction<Record<string, number>>>;
22
+ handleWidgetResize: (leftWidgetId: string, rightWidgetId: string, newLeftWidth: number, newRightWidth: number) => void;
23
+ saveLayout: () => void;
24
+ isDraggingWidget: boolean;
25
+ draggedWidgetId: string | undefined;
26
+ handleDragStart: WidgetIdFunction;
27
+ handleDragEnd: DragEndFunction;
28
+ };
29
+ export {};
@@ -1,9 +1,8 @@
1
1
  import * as React from 'react';
2
- import type { WidgetType } from '@strapi/admin/strapi-admin';
3
- interface WidgetRootProps extends Pick<WidgetType, 'title' | 'icon' | 'permissions' | 'link' | 'uid'> {
4
- children: React.ReactNode;
5
- }
6
- export declare const WidgetRoot: ({ title, icon, children, link, uid }: WidgetRootProps) => import("react/jsx-runtime").JSX.Element;
2
+ export declare const WidgetComponent: ({ component, columnWidth, }: {
3
+ component: () => Promise<React.ComponentType>;
4
+ columnWidth: number;
5
+ }) => import("react/jsx-runtime").JSX.Element;
7
6
  declare const HomePageCE: () => import("react/jsx-runtime").JSX.Element;
8
7
  declare const HomePage: () => import("react/jsx-runtime").JSX.Element | null;
9
8
  export { HomePage, HomePageCE };
@@ -0,0 +1,10 @@
1
+ import type { WidgetWithUID } from '../../../core/apis/Widgets';
2
+ interface AddWidgetModalProps {
3
+ isOpen: boolean;
4
+ onClose: () => void;
5
+ onAddWidget: (widget: WidgetWithUID) => void;
6
+ currentWidgets: WidgetWithUID[];
7
+ availableWidgets: WidgetWithUID[];
8
+ }
9
+ export declare const AddWidgetModal: ({ isOpen, onClose, onAddWidget, currentWidgets, availableWidgets, }: AddWidgetModalProps) => import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -1,5 +1,5 @@
1
1
  import * as Homepage from '../../../shared/contracts/homepage';
2
- declare const useGetKeyStatisticsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments", {
2
+ declare const useGetKeyStatisticsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments" | "HomepageLayout", {
3
3
  assets: number;
4
4
  contentTypes: number;
5
5
  components: number;
@@ -7,9 +7,9 @@ declare const useGetKeyStatisticsQuery: import("@reduxjs/toolkit/dist/query/reac
7
7
  admins: number;
8
8
  webhooks: number;
9
9
  apiTokens: number;
10
- }, "adminApi">>, useGetCountDocumentsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments", {
10
+ }, "adminApi">>, useGetCountDocumentsQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments" | "HomepageLayout", {
11
11
  draft: number;
12
12
  published: number;
13
13
  modified: number;
14
- }, "adminApi">>, useGetHomepageLayoutQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments", Homepage.Homepage.Layout, "adminApi">>, useUpdateHomepageLayoutMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Homepage.Homepage.LayoutWrite, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments", Homepage.Homepage.Layout, "adminApi">>;
14
+ }, "adminApi">>, useGetHomepageLayoutQuery: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseQuery<import("@reduxjs/toolkit/query").QueryDefinition<void, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments" | "HomepageLayout", Homepage.Homepage.Layout, "adminApi">>, useUpdateHomepageLayoutMutation: import("@reduxjs/toolkit/dist/query/react/buildHooks").UseMutation<import("@reduxjs/toolkit/query").MutationDefinition<Homepage.Homepage.LayoutWrite, import("@reduxjs/toolkit/query").BaseQueryFn<string | import("..").QueryArguments, unknown, import("..").BaseQueryError>, "GuidedTourMeta" | "HomepageKeyStatistics" | "AIUsage" | "CountDocuments" | "HomepageLayout", Homepage.Homepage.Layout, "adminApi">>;
15
15
  export { useGetKeyStatisticsQuery, useGetCountDocumentsQuery, useGetHomepageLayoutQuery, useUpdateHomepageLayoutMutation, };
@@ -0,0 +1,58 @@
1
+ /**
2
+ * These functions handle DOM element positioning, bounding rect calculations, and resize-specific logic.
3
+ */
4
+ /**
5
+ * Snaps a width value to the nearest discrete size
6
+ */
7
+ export declare const snapToDiscreteSize: (width: number) => number;
8
+ /**
9
+ * Ensures two widths sum to exactly 12 columns by adjusting the right width
10
+ */
11
+ export declare const adjustToTotalColumns: (leftWidth: number, rightWidth: number) => {
12
+ leftWidth: number;
13
+ rightWidth: number;
14
+ };
15
+ /**
16
+ * Validates if two widget widths together are valid (sum to 12 columns)
17
+ */
18
+ export declare const isValidResize: (leftWidth: number, rightWidth: number) => boolean;
19
+ /**
20
+ * Get bounding rects for all elements
21
+ */
22
+ export declare const getElementRects: (leftElement: Element | null, rightElement: Element | null, containerElement: Element | null) => {
23
+ leftRect: DOMRect;
24
+ rightRect: DOMRect;
25
+ containerRect: DOMRect;
26
+ } | null;
27
+ /**
28
+ * Calculate resize handle position from DOM elements
29
+ */
30
+ export declare const calculateResizeHandlePosition: (leftElement: Element | null, rightElement: Element | null, containerElement: Element | null) => {
31
+ left: number;
32
+ top: number;
33
+ height: number;
34
+ };
35
+ /**
36
+ * Calculate row bounds for resize indicator from DOM elements
37
+ */
38
+ export declare const calculateRowBounds: (leftElement: Element | null, rightElement: Element | null, containerElement: Element | null) => {
39
+ left: number;
40
+ top: number;
41
+ width: number;
42
+ height: number;
43
+ } | null;
44
+ /**
45
+ * Calculates target widths for a resize operation based on delta movement
46
+ */
47
+ export declare const calculateTargetWidths: (deltaColumns: number, startLeftWidth: number, startRightWidth: number) => {
48
+ targetLeftWidth: number;
49
+ targetRightWidth: number;
50
+ };
51
+ /**
52
+ * Determines if a resize operation should trigger based on value changes
53
+ * Used for performance optimization to prevent unnecessary updates
54
+ */
55
+ export declare const shouldTriggerResize: (leftWidth: number, rightWidth: number, lastResizeValues: {
56
+ leftWidth: number;
57
+ rightWidth: number;
58
+ }) => boolean;