@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.
- package/dist/admin/admin/src/components/DragLayer.js +67 -0
- package/dist/admin/admin/src/components/DragLayer.js.map +1 -0
- package/dist/admin/admin/src/components/DragLayer.mjs +64 -0
- package/dist/admin/admin/src/components/DragLayer.mjs.map +1 -0
- package/dist/admin/admin/src/components/FormInputs/Json.js +1 -1
- package/dist/admin/admin/src/components/FormInputs/Json.js.map +1 -1
- package/dist/admin/admin/src/components/FormInputs/Json.mjs +1 -1
- package/dist/admin/admin/src/components/FormInputs/Json.mjs.map +1 -1
- package/dist/admin/admin/src/components/GapDropZone.js +292 -0
- package/dist/admin/admin/src/components/GapDropZone.js.map +1 -0
- package/dist/admin/admin/src/components/GapDropZone.mjs +268 -0
- package/dist/admin/admin/src/components/GapDropZone.mjs.map +1 -0
- package/dist/admin/admin/src/components/ResizeIndicator.js +353 -0
- package/dist/admin/admin/src/components/ResizeIndicator.js.map +1 -0
- package/dist/admin/admin/src/components/ResizeIndicator.mjs +332 -0
- package/dist/admin/admin/src/components/ResizeIndicator.mjs.map +1 -0
- package/dist/admin/admin/src/components/SubNav.js +9 -2
- package/dist/admin/admin/src/components/SubNav.js.map +1 -1
- package/dist/admin/admin/src/components/SubNav.mjs +9 -2
- package/dist/admin/admin/src/components/SubNav.mjs.map +1 -1
- package/dist/admin/admin/src/components/WidgetRoot.js +216 -0
- package/dist/admin/admin/src/components/WidgetRoot.js.map +1 -0
- package/dist/admin/admin/src/components/WidgetRoot.mjs +195 -0
- package/dist/admin/admin/src/components/WidgetRoot.mjs.map +1 -0
- package/dist/admin/admin/src/features/Tracking.js.map +1 -1
- package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
- package/dist/admin/admin/src/features/Widgets.js +276 -0
- package/dist/admin/admin/src/features/Widgets.js.map +1 -0
- package/dist/admin/admin/src/features/Widgets.mjs +255 -0
- package/dist/admin/admin/src/features/Widgets.mjs.map +1 -0
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.js +1 -1
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.js.map +1 -1
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs +1 -1
- package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.js +160 -91
- package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
- package/dist/admin/admin/src/pages/Home/HomePage.mjs +162 -93
- package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js +189 -0
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js.map +1 -0
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs +168 -0
- package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs.map +1 -0
- package/dist/admin/admin/src/services/homepage.js +11 -4
- package/dist/admin/admin/src/services/homepage.js.map +1 -1
- package/dist/admin/admin/src/services/homepage.mjs +11 -4
- package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
- package/dist/admin/admin/src/translations/en.json.js +8 -1
- package/dist/admin/admin/src/translations/en.json.js.map +1 -1
- package/dist/admin/admin/src/translations/en.json.mjs +8 -1
- package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
- package/dist/admin/admin/src/translations/uk.json.js +9 -9
- package/dist/admin/admin/src/translations/uk.json.mjs +9 -9
- package/dist/admin/admin/src/utils/resizeHandlers.js +109 -0
- package/dist/admin/admin/src/utils/resizeHandlers.js.map +1 -0
- package/dist/admin/admin/src/utils/resizeHandlers.mjs +100 -0
- package/dist/admin/admin/src/utils/resizeHandlers.mjs.map +1 -0
- package/dist/admin/admin/src/utils/widgetLayout.js +293 -0
- package/dist/admin/admin/src/utils/widgetLayout.js.map +1 -0
- package/dist/admin/admin/src/utils/widgetLayout.mjs +273 -0
- package/dist/admin/admin/src/utils/widgetLayout.mjs.map +1 -0
- package/dist/admin/src/components/DragLayer.d.ts +8 -4
- package/dist/admin/src/components/GapDropZone.d.ts +36 -0
- package/dist/admin/src/components/ResizeIndicator.d.ts +12 -0
- package/dist/admin/src/components/SubNav.d.ts +1 -1
- package/dist/admin/src/components/WidgetRoot.d.ts +14 -0
- package/dist/admin/src/features/Tracking.d.ts +1 -1
- package/dist/admin/src/features/Widgets.d.ts +29 -0
- package/dist/admin/src/pages/Home/HomePage.d.ts +4 -5
- package/dist/admin/src/pages/Home/components/AddWidgetModal.d.ts +10 -0
- package/dist/admin/src/services/homepage.d.ts +3 -3
- package/dist/admin/src/utils/resizeHandlers.d.ts +58 -0
- package/dist/admin/src/utils/widgetLayout.d.ts +78 -0
- package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +4 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +4 -2
- package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
- package/dist/server/server/src/bootstrap.js +5 -0
- package/dist/server/server/src/bootstrap.js.map +1 -1
- package/dist/server/server/src/bootstrap.mjs +5 -0
- package/dist/server/server/src/bootstrap.mjs.map +1 -1
- package/dist/server/server/src/controllers/authentication.js +6 -6
- package/dist/server/server/src/controllers/authentication.js.map +1 -1
- package/dist/server/server/src/controllers/authentication.mjs +6 -6
- package/dist/server/server/src/controllers/authentication.mjs.map +1 -1
- package/dist/server/server/src/register.js +2 -1
- package/dist/server/server/src/register.js.map +1 -1
- package/dist/server/server/src/register.mjs +2 -1
- package/dist/server/server/src/register.mjs.map +1 -1
- package/dist/server/shared/utils/session-auth.js +14 -5
- package/dist/server/shared/utils/session-auth.js.map +1 -1
- package/dist/server/shared/utils/session-auth.mjs +14 -5
- package/dist/server/shared/utils/session-auth.mjs.map +1 -1
- package/dist/server/src/bootstrap.d.ts.map +1 -1
- package/dist/server/src/controllers/authentication.d.ts.map +1 -1
- package/dist/server/src/register.d.ts.map +1 -1
- package/dist/shared/contracts/homepage.d.ts +8 -4
- package/dist/shared/contracts/homepage.d.ts.map +1 -1
- package/dist/shared/utils/session-auth.d.ts +2 -2
- package/dist/shared/utils/session-auth.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var widgetLayout = require('./widgetLayout.js');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Snaps a width value to the nearest discrete size
|
|
7
|
+
*/ const snapToDiscreteSize = (width)=>{
|
|
8
|
+
return widgetLayout.WIDGET_SIZING.DISCRETE_SIZES.reduce((prev, curr)=>Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev);
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Ensures two widths sum to exactly 12 columns by adjusting the right width
|
|
12
|
+
*/ const adjustToTotalColumns = (leftWidth, rightWidth)=>{
|
|
13
|
+
const totalWidth = leftWidth + rightWidth;
|
|
14
|
+
if (totalWidth !== widgetLayout.WIDGET_SIZING.TOTAL_COLUMNS) {
|
|
15
|
+
const difference = widgetLayout.WIDGET_SIZING.TOTAL_COLUMNS - totalWidth;
|
|
16
|
+
rightWidth += difference;
|
|
17
|
+
}
|
|
18
|
+
return {
|
|
19
|
+
leftWidth,
|
|
20
|
+
rightWidth
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Validates if two widget widths together are valid (sum to 12 columns)
|
|
25
|
+
*/ const isValidResize = (leftWidth, rightWidth)=>{
|
|
26
|
+
return leftWidth >= widgetLayout.WIDGET_SIZING.MIN_WIDGET_WIDTH && rightWidth >= widgetLayout.WIDGET_SIZING.MIN_WIDGET_WIDTH && leftWidth + rightWidth === widgetLayout.WIDGET_SIZING.TOTAL_COLUMNS;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Get bounding rects for all elements
|
|
30
|
+
*/ const getElementRects = (leftElement, rightElement, containerElement)=>{
|
|
31
|
+
if (!leftElement || !rightElement || !containerElement) {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
leftRect: leftElement.getBoundingClientRect(),
|
|
36
|
+
rightRect: rightElement.getBoundingClientRect(),
|
|
37
|
+
containerRect: containerElement.getBoundingClientRect()
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
/**
|
|
41
|
+
* Calculate resize handle position from DOM elements
|
|
42
|
+
*/ const calculateResizeHandlePosition = (leftElement, rightElement, containerElement)=>{
|
|
43
|
+
const rects = getElementRects(leftElement, rightElement, containerElement);
|
|
44
|
+
if (!rects) {
|
|
45
|
+
return {
|
|
46
|
+
left: 0,
|
|
47
|
+
top: 0,
|
|
48
|
+
height: 0
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
const { leftRect, rightRect, containerRect } = rects;
|
|
52
|
+
const left = leftRect.right - containerRect.left;
|
|
53
|
+
const top = leftRect.top - containerRect.top;
|
|
54
|
+
const height = Math.max(leftRect.height, rightRect.height);
|
|
55
|
+
return {
|
|
56
|
+
left,
|
|
57
|
+
top,
|
|
58
|
+
height
|
|
59
|
+
};
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Calculate row bounds for resize indicator from DOM elements
|
|
63
|
+
*/ const calculateRowBounds = (leftElement, rightElement, containerElement)=>{
|
|
64
|
+
const rects = getElementRects(leftElement, rightElement, containerElement);
|
|
65
|
+
if (!rects) {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
const { leftRect, rightRect, containerRect } = rects;
|
|
69
|
+
const rowLeft = Math.min(leftRect.left, rightRect.left) - containerRect.left;
|
|
70
|
+
const rowTop = leftRect.top - containerRect.top;
|
|
71
|
+
const rowWidth = Math.max(leftRect.right, rightRect.right) - Math.min(leftRect.left, rightRect.left);
|
|
72
|
+
const rowHeight = Math.max(leftRect.height, rightRect.height);
|
|
73
|
+
return {
|
|
74
|
+
left: rowLeft,
|
|
75
|
+
top: rowTop,
|
|
76
|
+
width: rowWidth,
|
|
77
|
+
height: rowHeight
|
|
78
|
+
};
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Calculates target widths for a resize operation based on delta movement
|
|
82
|
+
*/ const calculateTargetWidths = (deltaColumns, startLeftWidth, startRightWidth)=>{
|
|
83
|
+
let targetLeftWidth = startLeftWidth + deltaColumns;
|
|
84
|
+
let targetRightWidth = startRightWidth - deltaColumns;
|
|
85
|
+
targetLeftWidth = snapToDiscreteSize(targetLeftWidth);
|
|
86
|
+
targetRightWidth = snapToDiscreteSize(targetRightWidth);
|
|
87
|
+
// Adjust to maintain total columns constraint
|
|
88
|
+
const adjusted = adjustToTotalColumns(targetLeftWidth, targetRightWidth);
|
|
89
|
+
return {
|
|
90
|
+
targetLeftWidth: adjusted.leftWidth,
|
|
91
|
+
targetRightWidth: adjusted.rightWidth
|
|
92
|
+
};
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Determines if a resize operation should trigger based on value changes
|
|
96
|
+
* Used for performance optimization to prevent unnecessary updates
|
|
97
|
+
*/ const shouldTriggerResize = (leftWidth, rightWidth, lastResizeValues)=>{
|
|
98
|
+
return leftWidth !== lastResizeValues.leftWidth || rightWidth !== lastResizeValues.rightWidth;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
exports.adjustToTotalColumns = adjustToTotalColumns;
|
|
102
|
+
exports.calculateResizeHandlePosition = calculateResizeHandlePosition;
|
|
103
|
+
exports.calculateRowBounds = calculateRowBounds;
|
|
104
|
+
exports.calculateTargetWidths = calculateTargetWidths;
|
|
105
|
+
exports.getElementRects = getElementRects;
|
|
106
|
+
exports.isValidResize = isValidResize;
|
|
107
|
+
exports.shouldTriggerResize = shouldTriggerResize;
|
|
108
|
+
exports.snapToDiscreteSize = snapToDiscreteSize;
|
|
109
|
+
//# sourceMappingURL=resizeHandlers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resizeHandlers.js","sources":["../../../../../admin/src/utils/resizeHandlers.ts"],"sourcesContent":["/**\n * These functions handle DOM element positioning, bounding rect calculations, and resize-specific logic.\n */\n\nimport { WIDGET_SIZING } from './widgetLayout';\n\n/**\n * Snaps a width value to the nearest discrete size\n */\nexport const snapToDiscreteSize = (width: number): number => {\n return WIDGET_SIZING.DISCRETE_SIZES.reduce((prev, curr) =>\n Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev\n );\n};\n\n/**\n * Ensures two widths sum to exactly 12 columns by adjusting the right width\n */\nexport const adjustToTotalColumns = (\n leftWidth: number,\n rightWidth: number\n): { leftWidth: number; rightWidth: number } => {\n const totalWidth = leftWidth + rightWidth;\n if (totalWidth !== WIDGET_SIZING.TOTAL_COLUMNS) {\n const difference = WIDGET_SIZING.TOTAL_COLUMNS - totalWidth;\n rightWidth += difference;\n }\n return { leftWidth, rightWidth };\n};\n\n/**\n * Validates if two widget widths together are valid (sum to 12 columns)\n */\nexport const isValidResize = (leftWidth: number, rightWidth: number): boolean => {\n return (\n leftWidth >= WIDGET_SIZING.MIN_WIDGET_WIDTH &&\n rightWidth >= WIDGET_SIZING.MIN_WIDGET_WIDTH &&\n leftWidth + rightWidth === WIDGET_SIZING.TOTAL_COLUMNS\n );\n};\n\n/**\n * Get bounding rects for all elements\n */\nexport const getElementRects = (\n leftElement: Element | null,\n rightElement: Element | null,\n containerElement: Element | null\n) => {\n if (!leftElement || !rightElement || !containerElement) {\n return null;\n }\n\n return {\n leftRect: leftElement.getBoundingClientRect(),\n rightRect: rightElement.getBoundingClientRect(),\n containerRect: containerElement.getBoundingClientRect(),\n };\n};\n\n/**\n * Calculate resize handle position from DOM elements\n */\nexport const calculateResizeHandlePosition = (\n leftElement: Element | null,\n rightElement: Element | null,\n containerElement: Element | null\n) => {\n const rects = getElementRects(leftElement, rightElement, containerElement);\n if (!rects) {\n return { left: 0, top: 0, height: 0 };\n }\n\n const { leftRect, rightRect, containerRect } = rects;\n\n const left = leftRect.right - containerRect.left;\n const top = leftRect.top - containerRect.top;\n const height = Math.max(leftRect.height, rightRect.height);\n\n return { left, top, height };\n};\n\n/**\n * Calculate row bounds for resize indicator from DOM elements\n */\nexport const calculateRowBounds = (\n leftElement: Element | null,\n rightElement: Element | null,\n containerElement: Element | null\n) => {\n const rects = getElementRects(leftElement, rightElement, containerElement);\n if (!rects) {\n return null;\n }\n\n const { leftRect, rightRect, containerRect } = rects;\n\n const rowLeft = Math.min(leftRect.left, rightRect.left) - containerRect.left;\n const rowTop = leftRect.top - containerRect.top;\n const rowWidth =\n Math.max(leftRect.right, rightRect.right) - Math.min(leftRect.left, rightRect.left);\n const rowHeight = Math.max(leftRect.height, rightRect.height);\n\n return { left: rowLeft, top: rowTop, width: rowWidth, height: rowHeight };\n};\n\n/**\n * Calculates target widths for a resize operation based on delta movement\n */\nexport const calculateTargetWidths = (\n deltaColumns: number,\n startLeftWidth: number,\n startRightWidth: number\n): { targetLeftWidth: number; targetRightWidth: number } => {\n let targetLeftWidth = startLeftWidth + deltaColumns;\n let targetRightWidth = startRightWidth - deltaColumns;\n\n targetLeftWidth = snapToDiscreteSize(targetLeftWidth);\n targetRightWidth = snapToDiscreteSize(targetRightWidth);\n\n // Adjust to maintain total columns constraint\n const adjusted = adjustToTotalColumns(targetLeftWidth, targetRightWidth);\n return { targetLeftWidth: adjusted.leftWidth, targetRightWidth: adjusted.rightWidth };\n};\n\n/**\n * Determines if a resize operation should trigger based on value changes\n * Used for performance optimization to prevent unnecessary updates\n */\nexport const shouldTriggerResize = (\n leftWidth: number,\n rightWidth: number,\n lastResizeValues: { leftWidth: number; rightWidth: number }\n): boolean => {\n return leftWidth !== lastResizeValues.leftWidth || rightWidth !== lastResizeValues.rightWidth;\n};\n"],"names":["snapToDiscreteSize","width","WIDGET_SIZING","DISCRETE_SIZES","reduce","prev","curr","Math","abs","adjustToTotalColumns","leftWidth","rightWidth","totalWidth","TOTAL_COLUMNS","difference","isValidResize","MIN_WIDGET_WIDTH","getElementRects","leftElement","rightElement","containerElement","leftRect","getBoundingClientRect","rightRect","containerRect","calculateResizeHandlePosition","rects","left","top","height","right","max","calculateRowBounds","rowLeft","min","rowTop","rowWidth","rowHeight","calculateTargetWidths","deltaColumns","startLeftWidth","startRightWidth","targetLeftWidth","targetRightWidth","adjusted","shouldTriggerResize","lastResizeValues"],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { WIDGET_SIZING } from './widgetLayout.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Snaps a width value to the nearest discrete size
|
|
5
|
+
*/ const snapToDiscreteSize = (width)=>{
|
|
6
|
+
return WIDGET_SIZING.DISCRETE_SIZES.reduce((prev, curr)=>Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev);
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Ensures two widths sum to exactly 12 columns by adjusting the right width
|
|
10
|
+
*/ const adjustToTotalColumns = (leftWidth, rightWidth)=>{
|
|
11
|
+
const totalWidth = leftWidth + rightWidth;
|
|
12
|
+
if (totalWidth !== WIDGET_SIZING.TOTAL_COLUMNS) {
|
|
13
|
+
const difference = WIDGET_SIZING.TOTAL_COLUMNS - totalWidth;
|
|
14
|
+
rightWidth += difference;
|
|
15
|
+
}
|
|
16
|
+
return {
|
|
17
|
+
leftWidth,
|
|
18
|
+
rightWidth
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Validates if two widget widths together are valid (sum to 12 columns)
|
|
23
|
+
*/ const isValidResize = (leftWidth, rightWidth)=>{
|
|
24
|
+
return leftWidth >= WIDGET_SIZING.MIN_WIDGET_WIDTH && rightWidth >= WIDGET_SIZING.MIN_WIDGET_WIDTH && leftWidth + rightWidth === WIDGET_SIZING.TOTAL_COLUMNS;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Get bounding rects for all elements
|
|
28
|
+
*/ const getElementRects = (leftElement, rightElement, containerElement)=>{
|
|
29
|
+
if (!leftElement || !rightElement || !containerElement) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
leftRect: leftElement.getBoundingClientRect(),
|
|
34
|
+
rightRect: rightElement.getBoundingClientRect(),
|
|
35
|
+
containerRect: containerElement.getBoundingClientRect()
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Calculate resize handle position from DOM elements
|
|
40
|
+
*/ const calculateResizeHandlePosition = (leftElement, rightElement, containerElement)=>{
|
|
41
|
+
const rects = getElementRects(leftElement, rightElement, containerElement);
|
|
42
|
+
if (!rects) {
|
|
43
|
+
return {
|
|
44
|
+
left: 0,
|
|
45
|
+
top: 0,
|
|
46
|
+
height: 0
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
const { leftRect, rightRect, containerRect } = rects;
|
|
50
|
+
const left = leftRect.right - containerRect.left;
|
|
51
|
+
const top = leftRect.top - containerRect.top;
|
|
52
|
+
const height = Math.max(leftRect.height, rightRect.height);
|
|
53
|
+
return {
|
|
54
|
+
left,
|
|
55
|
+
top,
|
|
56
|
+
height
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Calculate row bounds for resize indicator from DOM elements
|
|
61
|
+
*/ const calculateRowBounds = (leftElement, rightElement, containerElement)=>{
|
|
62
|
+
const rects = getElementRects(leftElement, rightElement, containerElement);
|
|
63
|
+
if (!rects) {
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
const { leftRect, rightRect, containerRect } = rects;
|
|
67
|
+
const rowLeft = Math.min(leftRect.left, rightRect.left) - containerRect.left;
|
|
68
|
+
const rowTop = leftRect.top - containerRect.top;
|
|
69
|
+
const rowWidth = Math.max(leftRect.right, rightRect.right) - Math.min(leftRect.left, rightRect.left);
|
|
70
|
+
const rowHeight = Math.max(leftRect.height, rightRect.height);
|
|
71
|
+
return {
|
|
72
|
+
left: rowLeft,
|
|
73
|
+
top: rowTop,
|
|
74
|
+
width: rowWidth,
|
|
75
|
+
height: rowHeight
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
/**
|
|
79
|
+
* Calculates target widths for a resize operation based on delta movement
|
|
80
|
+
*/ const calculateTargetWidths = (deltaColumns, startLeftWidth, startRightWidth)=>{
|
|
81
|
+
let targetLeftWidth = startLeftWidth + deltaColumns;
|
|
82
|
+
let targetRightWidth = startRightWidth - deltaColumns;
|
|
83
|
+
targetLeftWidth = snapToDiscreteSize(targetLeftWidth);
|
|
84
|
+
targetRightWidth = snapToDiscreteSize(targetRightWidth);
|
|
85
|
+
// Adjust to maintain total columns constraint
|
|
86
|
+
const adjusted = adjustToTotalColumns(targetLeftWidth, targetRightWidth);
|
|
87
|
+
return {
|
|
88
|
+
targetLeftWidth: adjusted.leftWidth,
|
|
89
|
+
targetRightWidth: adjusted.rightWidth
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
/**
|
|
93
|
+
* Determines if a resize operation should trigger based on value changes
|
|
94
|
+
* Used for performance optimization to prevent unnecessary updates
|
|
95
|
+
*/ const shouldTriggerResize = (leftWidth, rightWidth, lastResizeValues)=>{
|
|
96
|
+
return leftWidth !== lastResizeValues.leftWidth || rightWidth !== lastResizeValues.rightWidth;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export { adjustToTotalColumns, calculateResizeHandlePosition, calculateRowBounds, calculateTargetWidths, getElementRects, isValidResize, shouldTriggerResize, snapToDiscreteSize };
|
|
100
|
+
//# sourceMappingURL=resizeHandlers.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resizeHandlers.mjs","sources":["../../../../../admin/src/utils/resizeHandlers.ts"],"sourcesContent":["/**\n * These functions handle DOM element positioning, bounding rect calculations, and resize-specific logic.\n */\n\nimport { WIDGET_SIZING } from './widgetLayout';\n\n/**\n * Snaps a width value to the nearest discrete size\n */\nexport const snapToDiscreteSize = (width: number): number => {\n return WIDGET_SIZING.DISCRETE_SIZES.reduce((prev, curr) =>\n Math.abs(curr - width) < Math.abs(prev - width) ? curr : prev\n );\n};\n\n/**\n * Ensures two widths sum to exactly 12 columns by adjusting the right width\n */\nexport const adjustToTotalColumns = (\n leftWidth: number,\n rightWidth: number\n): { leftWidth: number; rightWidth: number } => {\n const totalWidth = leftWidth + rightWidth;\n if (totalWidth !== WIDGET_SIZING.TOTAL_COLUMNS) {\n const difference = WIDGET_SIZING.TOTAL_COLUMNS - totalWidth;\n rightWidth += difference;\n }\n return { leftWidth, rightWidth };\n};\n\n/**\n * Validates if two widget widths together are valid (sum to 12 columns)\n */\nexport const isValidResize = (leftWidth: number, rightWidth: number): boolean => {\n return (\n leftWidth >= WIDGET_SIZING.MIN_WIDGET_WIDTH &&\n rightWidth >= WIDGET_SIZING.MIN_WIDGET_WIDTH &&\n leftWidth + rightWidth === WIDGET_SIZING.TOTAL_COLUMNS\n );\n};\n\n/**\n * Get bounding rects for all elements\n */\nexport const getElementRects = (\n leftElement: Element | null,\n rightElement: Element | null,\n containerElement: Element | null\n) => {\n if (!leftElement || !rightElement || !containerElement) {\n return null;\n }\n\n return {\n leftRect: leftElement.getBoundingClientRect(),\n rightRect: rightElement.getBoundingClientRect(),\n containerRect: containerElement.getBoundingClientRect(),\n };\n};\n\n/**\n * Calculate resize handle position from DOM elements\n */\nexport const calculateResizeHandlePosition = (\n leftElement: Element | null,\n rightElement: Element | null,\n containerElement: Element | null\n) => {\n const rects = getElementRects(leftElement, rightElement, containerElement);\n if (!rects) {\n return { left: 0, top: 0, height: 0 };\n }\n\n const { leftRect, rightRect, containerRect } = rects;\n\n const left = leftRect.right - containerRect.left;\n const top = leftRect.top - containerRect.top;\n const height = Math.max(leftRect.height, rightRect.height);\n\n return { left, top, height };\n};\n\n/**\n * Calculate row bounds for resize indicator from DOM elements\n */\nexport const calculateRowBounds = (\n leftElement: Element | null,\n rightElement: Element | null,\n containerElement: Element | null\n) => {\n const rects = getElementRects(leftElement, rightElement, containerElement);\n if (!rects) {\n return null;\n }\n\n const { leftRect, rightRect, containerRect } = rects;\n\n const rowLeft = Math.min(leftRect.left, rightRect.left) - containerRect.left;\n const rowTop = leftRect.top - containerRect.top;\n const rowWidth =\n Math.max(leftRect.right, rightRect.right) - Math.min(leftRect.left, rightRect.left);\n const rowHeight = Math.max(leftRect.height, rightRect.height);\n\n return { left: rowLeft, top: rowTop, width: rowWidth, height: rowHeight };\n};\n\n/**\n * Calculates target widths for a resize operation based on delta movement\n */\nexport const calculateTargetWidths = (\n deltaColumns: number,\n startLeftWidth: number,\n startRightWidth: number\n): { targetLeftWidth: number; targetRightWidth: number } => {\n let targetLeftWidth = startLeftWidth + deltaColumns;\n let targetRightWidth = startRightWidth - deltaColumns;\n\n targetLeftWidth = snapToDiscreteSize(targetLeftWidth);\n targetRightWidth = snapToDiscreteSize(targetRightWidth);\n\n // Adjust to maintain total columns constraint\n const adjusted = adjustToTotalColumns(targetLeftWidth, targetRightWidth);\n return { targetLeftWidth: adjusted.leftWidth, targetRightWidth: adjusted.rightWidth };\n};\n\n/**\n * Determines if a resize operation should trigger based on value changes\n * Used for performance optimization to prevent unnecessary updates\n */\nexport const shouldTriggerResize = (\n leftWidth: number,\n rightWidth: number,\n lastResizeValues: { leftWidth: number; rightWidth: number }\n): boolean => {\n return leftWidth !== lastResizeValues.leftWidth || rightWidth !== lastResizeValues.rightWidth;\n};\n"],"names":["snapToDiscreteSize","width","WIDGET_SIZING","DISCRETE_SIZES","reduce","prev","curr","Math","abs","adjustToTotalColumns","leftWidth","rightWidth","totalWidth","TOTAL_COLUMNS","difference","isValidResize","MIN_WIDGET_WIDTH","getElementRects","leftElement","rightElement","containerElement","leftRect","getBoundingClientRect","rightRect","containerRect","calculateResizeHandlePosition","rects","left","top","height","right","max","calculateRowBounds","rowLeft","min","rowTop","rowWidth","rowHeight","calculateTargetWidths","deltaColumns","startLeftWidth","startRightWidth","targetLeftWidth","targetRightWidth","adjusted","shouldTriggerResize","lastResizeValues"],"mappings":"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"}
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* Comprehensive utilities for widget layout operations including sizing, positioning, and layout calculations.
|
|
6
|
+
*
|
|
7
|
+
* Constraints:
|
|
8
|
+
* - Maximum 3 widgets per row (since minimum widget width is 4 columns)
|
|
9
|
+
* - Widget widths are snapped to discrete values: 4 (1/3), 6 (1/2), 8 (2/3), 12 (3/3)
|
|
10
|
+
*/ const WIDGET_SIZING = {
|
|
11
|
+
TOTAL_COLUMNS: 12,
|
|
12
|
+
MIN_WIDGET_WIDTH: 4,
|
|
13
|
+
DISCRETE_SIZES: [
|
|
14
|
+
4,
|
|
15
|
+
6,
|
|
16
|
+
8,
|
|
17
|
+
12
|
|
18
|
+
]
|
|
19
|
+
};
|
|
20
|
+
const WIDGET_DATA_ATTRIBUTES = {
|
|
21
|
+
WIDGET_ID: 'data-strapi-widget-id',
|
|
22
|
+
GRID_CONTAINER: 'data-strapi-grid-container'
|
|
23
|
+
};
|
|
24
|
+
const getWidgetElement = (uid)=>{
|
|
25
|
+
return document.querySelector(`[${WIDGET_DATA_ATTRIBUTES.WIDGET_ID}="${uid}"]`);
|
|
26
|
+
};
|
|
27
|
+
const getWidgetGridContainer = ()=>{
|
|
28
|
+
return document.querySelector(`[${WIDGET_DATA_ATTRIBUTES.GRID_CONTAINER}]`);
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Validates if a widget width is valid (within constraints)
|
|
32
|
+
*/ const isValidWidgetWidth = (width)=>{
|
|
33
|
+
return width >= WIDGET_SIZING.MIN_WIDGET_WIDTH && width <= WIDGET_SIZING.TOTAL_COLUMNS;
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* Validates if a resize operation is allowed between two widgets
|
|
37
|
+
*/ const isValidResizeOperation = (leftWidth, rightWidth)=>{
|
|
38
|
+
// Check minimum size constraints
|
|
39
|
+
if (!isValidWidgetWidth(leftWidth) || !isValidWidgetWidth(rightWidth)) {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
// Check if the total doesn't exceed row capacity
|
|
43
|
+
if (leftWidth + rightWidth > WIDGET_SIZING.TOTAL_COLUMNS) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
return true;
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Gets widget width with fallback to default value
|
|
50
|
+
*/ const getWidgetWidth = (columnWidths, widgetId, defaultWidth = 6)=>{
|
|
51
|
+
return widgetId ? columnWidths[widgetId] || defaultWidth : defaultWidth;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Calculates the current row structure from widgets and their widths
|
|
55
|
+
*/ const calculateWidgetRows = (widgets, columnWidths)=>{
|
|
56
|
+
const rows = [];
|
|
57
|
+
let currentRow = [];
|
|
58
|
+
let currentRowWidth = 0;
|
|
59
|
+
let startIndex = 0;
|
|
60
|
+
widgets.forEach((widget, index)=>{
|
|
61
|
+
const widgetWidth = getWidgetWidth(columnWidths, widget.uid);
|
|
62
|
+
// If adding this widget would exceed 12 columns, start a new row
|
|
63
|
+
if (currentRowWidth + widgetWidth > WIDGET_SIZING.TOTAL_COLUMNS) {
|
|
64
|
+
if (currentRow.length > 0) {
|
|
65
|
+
rows.push({
|
|
66
|
+
widgets: currentRow,
|
|
67
|
+
totalWidth: currentRowWidth,
|
|
68
|
+
startIndex,
|
|
69
|
+
endIndex: startIndex + currentRow.length - 1
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
currentRow = [
|
|
73
|
+
widget
|
|
74
|
+
];
|
|
75
|
+
currentRowWidth = widgetWidth;
|
|
76
|
+
startIndex = index;
|
|
77
|
+
} else {
|
|
78
|
+
currentRow.push(widget);
|
|
79
|
+
currentRowWidth += widgetWidth;
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
// Add the last row if it has widgets
|
|
83
|
+
if (currentRow.length > 0) {
|
|
84
|
+
rows.push({
|
|
85
|
+
widgets: currentRow,
|
|
86
|
+
totalWidth: currentRowWidth,
|
|
87
|
+
startIndex,
|
|
88
|
+
endIndex: startIndex + currentRow.length - 1
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
return rows;
|
|
92
|
+
};
|
|
93
|
+
/**
|
|
94
|
+
* Calculates optimal layout for a specific row based on widget count
|
|
95
|
+
* Only enforces constraints when necessary:
|
|
96
|
+
* - 1 widget in row: must be 3/3 (12 columns)
|
|
97
|
+
* - 3 widgets in row: must be 1/3+1/3+1/3 (4+4+4 columns)
|
|
98
|
+
* - 2 widgets in row: preserves existing proportions or uses 1/2+1/2
|
|
99
|
+
*/ const calculateOptimalLayoutForRow = (widgetsInRow, currentColumnWidths)=>{
|
|
100
|
+
const newWidths = {
|
|
101
|
+
...currentColumnWidths
|
|
102
|
+
};
|
|
103
|
+
const widgetCount = widgetsInRow.length;
|
|
104
|
+
if (widgetCount === 1) {
|
|
105
|
+
// Single widget must take full width (12)
|
|
106
|
+
newWidths[widgetsInRow[0].uid] = 12;
|
|
107
|
+
} else if (widgetCount === 3) {
|
|
108
|
+
// Three widgets must be equal (4 + 4 + 4)
|
|
109
|
+
widgetsInRow.forEach((widget)=>{
|
|
110
|
+
newWidths[widget.uid] = 4;
|
|
111
|
+
});
|
|
112
|
+
} else if (widgetCount === 2) {
|
|
113
|
+
// Two widgets can be flexible - preserve existing proportions or use 6 + 6
|
|
114
|
+
const currentWidths = widgetsInRow.map((widget)=>getWidgetWidth(currentColumnWidths, widget.uid));
|
|
115
|
+
const totalWidth = currentWidths.reduce((sum, width)=>sum + width, 0);
|
|
116
|
+
if (totalWidth === 12) {
|
|
117
|
+
// Row is already properly sized, preserve proportions
|
|
118
|
+
widgetsInRow.forEach((widget, index)=>{
|
|
119
|
+
newWidths[widget.uid] = currentWidths[index];
|
|
120
|
+
});
|
|
121
|
+
} else {
|
|
122
|
+
// Row needs adjustment, use equal split
|
|
123
|
+
widgetsInRow.forEach((widget)=>{
|
|
124
|
+
newWidths[widget.uid] = 6;
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return newWidths;
|
|
129
|
+
};
|
|
130
|
+
const moveWidgetInArray = (widgets, widgetId, insertIndex)=>{
|
|
131
|
+
const currentIndex = widgets.findIndex((w)=>w.uid === widgetId);
|
|
132
|
+
if (currentIndex === -1) return widgets;
|
|
133
|
+
// Remove widget from current position
|
|
134
|
+
const widgetsWithoutMoved = widgets.filter((w)=>w.uid !== widgetId);
|
|
135
|
+
// Insert at new position (adjust index if moving forward)
|
|
136
|
+
const adjustedInsertIndex = insertIndex > currentIndex ? insertIndex - 1 : insertIndex;
|
|
137
|
+
const newWidgets = [
|
|
138
|
+
...widgetsWithoutMoved
|
|
139
|
+
];
|
|
140
|
+
newWidgets.splice(adjustedInsertIndex, 0, widgets[currentIndex]);
|
|
141
|
+
return newWidgets;
|
|
142
|
+
};
|
|
143
|
+
const findRowContainingWidget = (widgetRows, widgetId, widgets)=>{
|
|
144
|
+
const widgetIndex = widgets.findIndex((w)=>w.uid === widgetId);
|
|
145
|
+
if (widgetIndex === -1) return undefined;
|
|
146
|
+
return widgetRows.find((row)=>widgetIndex >= row.startIndex && widgetIndex <= row.endIndex);
|
|
147
|
+
};
|
|
148
|
+
const resizeRowAfterRemoval = (row, removedWidgetId, currentWidths)=>{
|
|
149
|
+
if (!row) return currentWidths;
|
|
150
|
+
const remainingWidgets = row.widgets.filter((w)=>w.uid !== removedWidgetId);
|
|
151
|
+
return calculateOptimalLayoutForRow(remainingWidgets, currentWidths);
|
|
152
|
+
};
|
|
153
|
+
const resizeRowAfterAddition = (row, addedWidget, insertIndex, currentWidths)=>{
|
|
154
|
+
if (!row) return currentWidths;
|
|
155
|
+
// Calculate the new widget arrangement for the target row
|
|
156
|
+
const targetRowWidgets = [
|
|
157
|
+
...row.widgets
|
|
158
|
+
];
|
|
159
|
+
const existingIndex = targetRowWidgets.findIndex((w)=>w.uid === addedWidget.uid);
|
|
160
|
+
if (existingIndex !== -1) {
|
|
161
|
+
// Widget was already in this row, just reorder
|
|
162
|
+
targetRowWidgets.splice(existingIndex, 1);
|
|
163
|
+
}
|
|
164
|
+
// Insert at the new position within the row
|
|
165
|
+
let insertPosition = insertIndex - row.startIndex;
|
|
166
|
+
// If insertIndex is at the end of the row (row.endIndex + 1),
|
|
167
|
+
// insert at the end of the row instead of beyond it
|
|
168
|
+
if (insertIndex === row.endIndex + 1) {
|
|
169
|
+
insertPosition = row.widgets.length;
|
|
170
|
+
}
|
|
171
|
+
targetRowWidgets.splice(insertPosition, 0, addedWidget);
|
|
172
|
+
return calculateOptimalLayoutForRow(targetRowWidgets, currentWidths);
|
|
173
|
+
};
|
|
174
|
+
const isLastWidgetInRow = (widgetIndex, widgets, columnWidths)=>{
|
|
175
|
+
if (widgetIndex >= widgets.length - 1) {
|
|
176
|
+
return true; // Last widget overall
|
|
177
|
+
}
|
|
178
|
+
let currentRowWidth = 0;
|
|
179
|
+
// Calculate the current row width by going through widgets from the start
|
|
180
|
+
for(let i = 0; i <= widgetIndex; i++){
|
|
181
|
+
const widgetWidth = getWidgetWidth(columnWidths, widgets[i]?.uid);
|
|
182
|
+
if (currentRowWidth + widgetWidth > WIDGET_SIZING.TOTAL_COLUMNS) {
|
|
183
|
+
// This widget starts a new row, so the previous widget was the last in its row
|
|
184
|
+
currentRowWidth = widgetWidth;
|
|
185
|
+
} else {
|
|
186
|
+
currentRowWidth += widgetWidth;
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
// Check if the next widget would fit in the current row
|
|
190
|
+
const nextWidgetWidth = getWidgetWidth(columnWidths, widgets[widgetIndex + 1]?.uid);
|
|
191
|
+
return currentRowWidth + nextWidgetWidth > WIDGET_SIZING.TOTAL_COLUMNS;
|
|
192
|
+
};
|
|
193
|
+
const canResizeBetweenWidgets = (leftWidgetId, rightWidgetId, columnWidths, widgets)=>{
|
|
194
|
+
const leftWidth = getWidgetWidth(columnWidths, leftWidgetId);
|
|
195
|
+
const rightWidth = getWidgetWidth(columnWidths, rightWidgetId);
|
|
196
|
+
// First check if the widgets are actually adjacent in the same row
|
|
197
|
+
const leftIndex = widgets.findIndex((w)=>w.uid === leftWidgetId);
|
|
198
|
+
const rightIndex = widgets.findIndex((w)=>w.uid === rightWidgetId);
|
|
199
|
+
// Widgets must be consecutive in the array and in the same row
|
|
200
|
+
if (rightIndex !== leftIndex + 1) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
// Check if they're in the same row by verifying the right widget isn't the first in a new row
|
|
204
|
+
if (isLastWidgetInRow(leftIndex, widgets, columnWidths)) {
|
|
205
|
+
return false; // Left widget is last in its row, so right widget starts a new row
|
|
206
|
+
}
|
|
207
|
+
// Check if either widget can be made smaller (must be > 4 columns)
|
|
208
|
+
// or if either widget can be made bigger (must be < 12 columns)
|
|
209
|
+
const canLeftShrink = leftWidth > WIDGET_SIZING.MIN_WIDGET_WIDTH;
|
|
210
|
+
const canRightShrink = rightWidth > WIDGET_SIZING.MIN_WIDGET_WIDTH;
|
|
211
|
+
const canLeftGrow = leftWidth < WIDGET_SIZING.TOTAL_COLUMNS;
|
|
212
|
+
const canRightGrow = rightWidth < WIDGET_SIZING.TOTAL_COLUMNS;
|
|
213
|
+
// Resizing is possible if either widget can shrink AND the other can grow
|
|
214
|
+
return canLeftShrink && canRightGrow || canRightShrink && canLeftGrow;
|
|
215
|
+
};
|
|
216
|
+
/**
|
|
217
|
+
* Filters widgets to only include those present in the homepage layout
|
|
218
|
+
*/ const filterWidgetsByHomepageLayout = (widgets, homepageLayout)=>{
|
|
219
|
+
const createHomepageWidgetUidsSet = (homepageLayout)=>new Set(homepageLayout.widgets.map((w)=>w.uid));
|
|
220
|
+
const homepageWidgetUids = createHomepageWidgetUidsSet(homepageLayout);
|
|
221
|
+
return widgets.filter((widget)=>homepageWidgetUids.has(widget.uid));
|
|
222
|
+
};
|
|
223
|
+
/**
|
|
224
|
+
* Sorts widgets according to the homepage layout order
|
|
225
|
+
*/ const sortWidgetsByHomepageLayout = (widgets, homepageLayout)=>{
|
|
226
|
+
const widgetOrderMap = new Map(homepageLayout.widgets.map((widget, index)=>[
|
|
227
|
+
widget.uid,
|
|
228
|
+
index
|
|
229
|
+
]));
|
|
230
|
+
return [
|
|
231
|
+
...widgets
|
|
232
|
+
].sort((a, b)=>{
|
|
233
|
+
const aIndex = widgetOrderMap.get(a.uid) ?? Number.MAX_SAFE_INTEGER;
|
|
234
|
+
const bIndex = widgetOrderMap.get(b.uid) ?? Number.MAX_SAFE_INTEGER;
|
|
235
|
+
return aIndex - bIndex;
|
|
236
|
+
});
|
|
237
|
+
};
|
|
238
|
+
/**
|
|
239
|
+
* Applies homepage layout to widgets (filters, sorts, and extracts widths)
|
|
240
|
+
*/ const applyHomepageLayout = (authorizedWidgets, homepageLayout)=>{
|
|
241
|
+
const layoutWidgets = filterWidgetsByHomepageLayout(authorizedWidgets, homepageLayout);
|
|
242
|
+
const sortedWidgets = sortWidgetsByHomepageLayout(layoutWidgets, homepageLayout);
|
|
243
|
+
// Extract widths from homepage layout
|
|
244
|
+
const widths = {};
|
|
245
|
+
homepageLayout.widgets.forEach(({ uid, width })=>{
|
|
246
|
+
widths[uid] = width;
|
|
247
|
+
});
|
|
248
|
+
return {
|
|
249
|
+
filteredWidgets: sortedWidgets,
|
|
250
|
+
widths
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
/**
|
|
254
|
+
* Creates default widget widths based on widget count
|
|
255
|
+
* Even count: all widgets get width 6
|
|
256
|
+
* Odd count: all widgets get width 6 except the last one which gets width 12
|
|
257
|
+
*/ const createDefaultWidgetWidths = (widgets)=>{
|
|
258
|
+
const defaultWidths = {};
|
|
259
|
+
const widgetCount = widgets.length;
|
|
260
|
+
if (widgetCount > 0) {
|
|
261
|
+
if (widgetCount % 2 === 0) {
|
|
262
|
+
widgets.forEach((widget)=>{
|
|
263
|
+
defaultWidths[widget.uid] = 6;
|
|
264
|
+
});
|
|
265
|
+
} else {
|
|
266
|
+
widgets.forEach((widget, index)=>{
|
|
267
|
+
defaultWidths[widget.uid] = index === widgetCount - 1 ? 12 : 6;
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
return defaultWidths;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
exports.WIDGET_DATA_ATTRIBUTES = WIDGET_DATA_ATTRIBUTES;
|
|
275
|
+
exports.WIDGET_SIZING = WIDGET_SIZING;
|
|
276
|
+
exports.applyHomepageLayout = applyHomepageLayout;
|
|
277
|
+
exports.calculateOptimalLayoutForRow = calculateOptimalLayoutForRow;
|
|
278
|
+
exports.calculateWidgetRows = calculateWidgetRows;
|
|
279
|
+
exports.canResizeBetweenWidgets = canResizeBetweenWidgets;
|
|
280
|
+
exports.createDefaultWidgetWidths = createDefaultWidgetWidths;
|
|
281
|
+
exports.filterWidgetsByHomepageLayout = filterWidgetsByHomepageLayout;
|
|
282
|
+
exports.findRowContainingWidget = findRowContainingWidget;
|
|
283
|
+
exports.getWidgetElement = getWidgetElement;
|
|
284
|
+
exports.getWidgetGridContainer = getWidgetGridContainer;
|
|
285
|
+
exports.getWidgetWidth = getWidgetWidth;
|
|
286
|
+
exports.isLastWidgetInRow = isLastWidgetInRow;
|
|
287
|
+
exports.isValidResizeOperation = isValidResizeOperation;
|
|
288
|
+
exports.isValidWidgetWidth = isValidWidgetWidth;
|
|
289
|
+
exports.moveWidgetInArray = moveWidgetInArray;
|
|
290
|
+
exports.resizeRowAfterAddition = resizeRowAfterAddition;
|
|
291
|
+
exports.resizeRowAfterRemoval = resizeRowAfterRemoval;
|
|
292
|
+
exports.sortWidgetsByHomepageLayout = sortWidgetsByHomepageLayout;
|
|
293
|
+
//# sourceMappingURL=widgetLayout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"widgetLayout.js","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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"}
|