@strapi/admin 5.27.0 → 5.28.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 (81) 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/GapDropZone.js +292 -0
  6. package/dist/admin/admin/src/components/GapDropZone.js.map +1 -0
  7. package/dist/admin/admin/src/components/GapDropZone.mjs +268 -0
  8. package/dist/admin/admin/src/components/GapDropZone.mjs.map +1 -0
  9. package/dist/admin/admin/src/components/ResizeIndicator.js +353 -0
  10. package/dist/admin/admin/src/components/ResizeIndicator.js.map +1 -0
  11. package/dist/admin/admin/src/components/ResizeIndicator.mjs +332 -0
  12. package/dist/admin/admin/src/components/ResizeIndicator.mjs.map +1 -0
  13. package/dist/admin/admin/src/components/WidgetRoot.js +216 -0
  14. package/dist/admin/admin/src/components/WidgetRoot.js.map +1 -0
  15. package/dist/admin/admin/src/components/WidgetRoot.mjs +195 -0
  16. package/dist/admin/admin/src/components/WidgetRoot.mjs.map +1 -0
  17. package/dist/admin/admin/src/features/Tracking.js.map +1 -1
  18. package/dist/admin/admin/src/features/Tracking.mjs.map +1 -1
  19. package/dist/admin/admin/src/features/Widgets.js +276 -0
  20. package/dist/admin/admin/src/features/Widgets.js.map +1 -0
  21. package/dist/admin/admin/src/features/Widgets.mjs +255 -0
  22. package/dist/admin/admin/src/features/Widgets.mjs.map +1 -0
  23. package/dist/admin/admin/src/hooks/useAPIErrorHandler.js +1 -1
  24. package/dist/admin/admin/src/hooks/useAPIErrorHandler.js.map +1 -1
  25. package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs +1 -1
  26. package/dist/admin/admin/src/hooks/useAPIErrorHandler.mjs.map +1 -1
  27. package/dist/admin/admin/src/pages/Home/HomePage.js +160 -91
  28. package/dist/admin/admin/src/pages/Home/HomePage.js.map +1 -1
  29. package/dist/admin/admin/src/pages/Home/HomePage.mjs +162 -93
  30. package/dist/admin/admin/src/pages/Home/HomePage.mjs.map +1 -1
  31. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js +189 -0
  32. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.js.map +1 -0
  33. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs +168 -0
  34. package/dist/admin/admin/src/pages/Home/components/AddWidgetModal.mjs.map +1 -0
  35. package/dist/admin/admin/src/services/homepage.js +11 -4
  36. package/dist/admin/admin/src/services/homepage.js.map +1 -1
  37. package/dist/admin/admin/src/services/homepage.mjs +11 -4
  38. package/dist/admin/admin/src/services/homepage.mjs.map +1 -1
  39. package/dist/admin/admin/src/translations/en.json.js +6 -1
  40. package/dist/admin/admin/src/translations/en.json.js.map +1 -1
  41. package/dist/admin/admin/src/translations/en.json.mjs +6 -1
  42. package/dist/admin/admin/src/translations/en.json.mjs.map +1 -1
  43. package/dist/admin/admin/src/translations/uk.json.js +9 -9
  44. package/dist/admin/admin/src/translations/uk.json.mjs +9 -9
  45. package/dist/admin/admin/src/utils/resizeHandlers.js +109 -0
  46. package/dist/admin/admin/src/utils/resizeHandlers.js.map +1 -0
  47. package/dist/admin/admin/src/utils/resizeHandlers.mjs +100 -0
  48. package/dist/admin/admin/src/utils/resizeHandlers.mjs.map +1 -0
  49. package/dist/admin/admin/src/utils/widgetLayout.js +293 -0
  50. package/dist/admin/admin/src/utils/widgetLayout.js.map +1 -0
  51. package/dist/admin/admin/src/utils/widgetLayout.mjs +273 -0
  52. package/dist/admin/admin/src/utils/widgetLayout.mjs.map +1 -0
  53. package/dist/admin/src/components/DragLayer.d.ts +8 -4
  54. package/dist/admin/src/components/GapDropZone.d.ts +36 -0
  55. package/dist/admin/src/components/ResizeIndicator.d.ts +12 -0
  56. package/dist/admin/src/components/WidgetRoot.d.ts +14 -0
  57. package/dist/admin/src/features/Tracking.d.ts +1 -1
  58. package/dist/admin/src/features/Widgets.d.ts +29 -0
  59. package/dist/admin/src/pages/Home/HomePage.d.ts +4 -5
  60. package/dist/admin/src/pages/Home/components/AddWidgetModal.d.ts +10 -0
  61. package/dist/admin/src/services/homepage.d.ts +3 -3
  62. package/dist/admin/src/utils/resizeHandlers.d.ts +58 -0
  63. package/dist/admin/src/utils/widgetLayout.d.ts +78 -0
  64. package/dist/ee/server/src/controllers/authentication-utils/middlewares.d.ts.map +1 -1
  65. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js +4 -2
  66. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.js.map +1 -1
  67. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs +4 -2
  68. package/dist/server/ee/server/src/controllers/authentication-utils/middlewares.mjs.map +1 -1
  69. package/dist/server/server/src/bootstrap.js +5 -0
  70. package/dist/server/server/src/bootstrap.js.map +1 -1
  71. package/dist/server/server/src/bootstrap.mjs +5 -0
  72. package/dist/server/server/src/bootstrap.mjs.map +1 -1
  73. package/dist/server/shared/utils/session-auth.js +4 -2
  74. package/dist/server/shared/utils/session-auth.js.map +1 -1
  75. package/dist/server/shared/utils/session-auth.mjs +4 -2
  76. package/dist/server/shared/utils/session-auth.mjs.map +1 -1
  77. package/dist/server/src/bootstrap.d.ts.map +1 -1
  78. package/dist/shared/contracts/homepage.d.ts +8 -4
  79. package/dist/shared/contracts/homepage.d.ts.map +1 -1
  80. package/dist/shared/utils/session-auth.d.ts.map +1 -1
  81. package/package.json +7 -7
@@ -0,0 +1,67 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ require('react');
5
+ var designSystem = require('@strapi/design-system');
6
+ var reactDnd = require('react-dnd');
7
+ var widgetLayout = require('../utils/widgetLayout.js');
8
+
9
+ function isWidgetDragItem(item) {
10
+ return typeof item === 'object' && item !== null && 'id' in item && typeof item.id === 'string' && 'originalIndex' in item && typeof item.originalIndex === 'number' && 'title' in item && 'component' in item;
11
+ }
12
+ function getStyle(initialOffset, currentOffset, mouseOffset, item) {
13
+ if (!initialOffset || !currentOffset || !mouseOffset) {
14
+ return {
15
+ display: 'none'
16
+ };
17
+ }
18
+ const { x, y } = mouseOffset;
19
+ // Only apply custom offset for widget drags
20
+ if (isWidgetDragItem(item)) {
21
+ // Calculate dynamic offset based on widget position and width
22
+ const widgetElement = widgetLayout.getWidgetElement(item.id);
23
+ const previewWidth = widgetElement?.clientWidth;
24
+ const offsetX = previewWidth ? -previewWidth + 20 : 0;
25
+ const offsetY = 20;
26
+ return {
27
+ transform: `translate(${x + offsetX}px, ${y + offsetY}px)`
28
+ };
29
+ }
30
+ // Default positioning for non-widget drags
31
+ return {
32
+ transform: `translate(${x}px, ${y}px)`
33
+ };
34
+ }
35
+ const DragLayer = ({ renderItem })=>{
36
+ const { itemType, isDragging, item, initialOffset, currentOffset, mouseOffset } = reactDnd.useDragLayer((monitor)=>({
37
+ item: monitor.getItem(),
38
+ itemType: monitor.getItemType(),
39
+ initialOffset: monitor.getInitialSourceClientOffset(),
40
+ currentOffset: monitor.getSourceClientOffset(),
41
+ isDragging: monitor.isDragging(),
42
+ mouseOffset: monitor.getClientOffset()
43
+ }));
44
+ if (!isDragging) {
45
+ return null;
46
+ }
47
+ return /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
48
+ height: "100%",
49
+ left: 0,
50
+ position: "fixed",
51
+ pointerEvents: "none",
52
+ top: 0,
53
+ zIndex: 100,
54
+ width: "100%",
55
+ children: /*#__PURE__*/ jsxRuntime.jsx(designSystem.Box, {
56
+ style: getStyle(initialOffset, currentOffset, mouseOffset, item),
57
+ children: renderItem({
58
+ type: itemType,
59
+ item
60
+ })
61
+ })
62
+ });
63
+ };
64
+
65
+ exports.DragLayer = DragLayer;
66
+ exports.isWidgetDragItem = isWidgetDragItem;
67
+ //# sourceMappingURL=DragLayer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DragLayer.js","sources":["../../../../../admin/src/components/DragLayer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box } from '@strapi/design-system';\nimport { DragLayerMonitor, XYCoord, useDragLayer } from 'react-dnd';\n\nimport { getWidgetElement } from '../utils/widgetLayout';\n\nimport type { WidgetArgs } from '../core/apis/Widgets';\n\nexport interface WidgetDragItem extends Pick<WidgetArgs, 'title' | 'icon' | 'link' | 'component'> {\n type: 'widget';\n id: string;\n originalIndex: number;\n}\n\nexport function isWidgetDragItem(item: unknown): item is WidgetDragItem {\n return (\n typeof item === 'object' &&\n item !== null &&\n 'id' in item &&\n typeof item.id === 'string' &&\n 'originalIndex' in item &&\n typeof item.originalIndex === 'number' &&\n 'title' in item &&\n 'component' in item\n );\n}\n\nfunction getStyle(\n initialOffset: XYCoord | null,\n currentOffset: XYCoord | null,\n mouseOffset: XYCoord | null,\n item?: unknown\n) {\n if (!initialOffset || !currentOffset || !mouseOffset) {\n return { display: 'none' };\n }\n\n const { x, y } = mouseOffset;\n\n // Only apply custom offset for widget drags\n if (isWidgetDragItem(item)) {\n // Calculate dynamic offset based on widget position and width\n const widgetElement = getWidgetElement(item.id);\n const previewWidth = widgetElement?.clientWidth;\n const offsetX = previewWidth ? -previewWidth + 20 : 0;\n const offsetY = 20;\n\n return {\n transform: `translate(${x + offsetX}px, ${y + offsetY}px)`,\n };\n }\n\n // Default positioning for non-widget drags\n return {\n transform: `translate(${x}px, ${y}px)`,\n };\n}\n\nexport interface DragLayerProps {\n renderItem: (item: {\n item: unknown;\n type: ReturnType<DragLayerMonitor['getItemType']>;\n }) => React.ReactNode;\n}\n\nconst DragLayer = ({ renderItem }: DragLayerProps) => {\n const { itemType, isDragging, item, initialOffset, currentOffset, mouseOffset } = useDragLayer(\n (monitor) => ({\n item: monitor.getItem(),\n itemType: monitor.getItemType(),\n initialOffset: monitor.getInitialSourceClientOffset(),\n currentOffset: monitor.getSourceClientOffset(),\n isDragging: monitor.isDragging(),\n mouseOffset: monitor.getClientOffset(),\n })\n );\n\n if (!isDragging) {\n return null;\n }\n\n return (\n <Box\n height=\"100%\"\n left={0}\n position=\"fixed\"\n pointerEvents=\"none\"\n top={0}\n zIndex={100}\n width=\"100%\"\n >\n <Box style={getStyle(initialOffset, currentOffset, mouseOffset, item)}>\n {renderItem({ type: itemType, item })}\n </Box>\n </Box>\n );\n};\n\nexport { DragLayer };\n"],"names":["isWidgetDragItem","item","id","originalIndex","getStyle","initialOffset","currentOffset","mouseOffset","display","x","y","widgetElement","getWidgetElement","previewWidth","clientWidth","offsetX","offsetY","transform","DragLayer","renderItem","itemType","isDragging","useDragLayer","monitor","getItem","getItemType","getInitialSourceClientOffset","getSourceClientOffset","getClientOffset","_jsx","Box","height","left","position","pointerEvents","top","zIndex","width","style","type"],"mappings":";;;;;;;;AAeO,SAASA,iBAAiBC,IAAa,EAAA;IAC5C,OACE,OAAOA,SAAS,QAChBA,IAAAA,IAAAA,KAAS,QACT,IAAQA,IAAAA,IAAAA,IACR,OAAOA,IAAKC,CAAAA,EAAE,KAAK,QACnB,IAAA,eAAA,IAAmBD,QACnB,OAAOA,IAAAA,CAAKE,aAAa,KAAK,QAAA,IAC9B,OAAWF,IAAAA,IAAAA,IACX,WAAeA,IAAAA,IAAAA;AAEnB;AAEA,SAASG,SACPC,aAA6B,EAC7BC,aAA6B,EAC7BC,WAA2B,EAC3BN,IAAc,EAAA;AAEd,IAAA,IAAI,CAACI,aAAAA,IAAiB,CAACC,aAAAA,IAAiB,CAACC,WAAa,EAAA;QACpD,OAAO;YAAEC,OAAS,EAAA;AAAO,SAAA;AAC3B;AAEA,IAAA,MAAM,EAAEC,CAAC,EAAEC,CAAC,EAAE,GAAGH,WAAAA;;AAGjB,IAAA,IAAIP,iBAAiBC,IAAO,CAAA,EAAA;;QAE1B,MAAMU,aAAAA,GAAgBC,6BAAiBX,CAAAA,IAAAA,CAAKC,EAAE,CAAA;AAC9C,QAAA,MAAMW,eAAeF,aAAeG,EAAAA,WAAAA;AACpC,QAAA,MAAMC,OAAUF,GAAAA,YAAAA,GAAe,CAACA,YAAAA,GAAe,EAAK,GAAA,CAAA;AACpD,QAAA,MAAMG,OAAU,GAAA,EAAA;QAEhB,OAAO;YACLC,SAAW,EAAA,CAAC,UAAU,EAAER,CAAIM,GAAAA,OAAAA,CAAQ,IAAI,EAAEL,CAAAA,GAAIM,OAAQ,CAAA,GAAG;AAC3D,SAAA;AACF;;IAGA,OAAO;QACLC,SAAW,EAAA,CAAC,UAAU,EAAER,CAAAA,CAAE,IAAI,EAAEC,CAAAA,CAAE,GAAG;AACvC,KAAA;AACF;AASA,MAAMQ,SAAY,GAAA,CAAC,EAAEC,UAAU,EAAkB,GAAA;AAC/C,IAAA,MAAM,EAAEC,QAAQ,EAAEC,UAAU,EAAEpB,IAAI,EAAEI,aAAa,EAAEC,aAAa,EAAEC,WAAW,EAAE,GAAGe,qBAChF,CAAA,CAACC,WAAa;AACZtB,YAAAA,IAAAA,EAAMsB,QAAQC,OAAO,EAAA;AACrBJ,YAAAA,QAAAA,EAAUG,QAAQE,WAAW,EAAA;AAC7BpB,YAAAA,aAAAA,EAAekB,QAAQG,4BAA4B,EAAA;AACnDpB,YAAAA,aAAAA,EAAeiB,QAAQI,qBAAqB,EAAA;AAC5CN,YAAAA,UAAAA,EAAYE,QAAQF,UAAU,EAAA;AAC9Bd,YAAAA,WAAAA,EAAagB,QAAQK,eAAe;SACtC,CAAA,CAAA;AAGF,IAAA,IAAI,CAACP,UAAY,EAAA;QACf,OAAO,IAAA;AACT;AAEA,IAAA,qBACEQ,cAACC,CAAAA,gBAAAA,EAAAA;QACCC,MAAO,EAAA,MAAA;QACPC,IAAM,EAAA,CAAA;QACNC,QAAS,EAAA,OAAA;QACTC,aAAc,EAAA,MAAA;QACdC,GAAK,EAAA,CAAA;QACLC,MAAQ,EAAA,GAAA;QACRC,KAAM,EAAA,MAAA;AAEN,QAAA,QAAA,gBAAAR,cAACC,CAAAA,gBAAAA,EAAAA;YAAIQ,KAAOlC,EAAAA,QAAAA,CAASC,aAAeC,EAAAA,aAAAA,EAAeC,WAAaN,EAAAA,IAAAA,CAAAA;sBAC7DkB,UAAW,CAAA;gBAAEoB,IAAMnB,EAAAA,QAAAA;AAAUnB,gBAAAA;AAAK,aAAA;;;AAI3C;;;;;"}
@@ -0,0 +1,64 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import 'react';
3
+ import { Box } from '@strapi/design-system';
4
+ import { useDragLayer } from 'react-dnd';
5
+ import { getWidgetElement } from '../utils/widgetLayout.mjs';
6
+
7
+ function isWidgetDragItem(item) {
8
+ return typeof item === 'object' && item !== null && 'id' in item && typeof item.id === 'string' && 'originalIndex' in item && typeof item.originalIndex === 'number' && 'title' in item && 'component' in item;
9
+ }
10
+ function getStyle(initialOffset, currentOffset, mouseOffset, item) {
11
+ if (!initialOffset || !currentOffset || !mouseOffset) {
12
+ return {
13
+ display: 'none'
14
+ };
15
+ }
16
+ const { x, y } = mouseOffset;
17
+ // Only apply custom offset for widget drags
18
+ if (isWidgetDragItem(item)) {
19
+ // Calculate dynamic offset based on widget position and width
20
+ const widgetElement = getWidgetElement(item.id);
21
+ const previewWidth = widgetElement?.clientWidth;
22
+ const offsetX = previewWidth ? -previewWidth + 20 : 0;
23
+ const offsetY = 20;
24
+ return {
25
+ transform: `translate(${x + offsetX}px, ${y + offsetY}px)`
26
+ };
27
+ }
28
+ // Default positioning for non-widget drags
29
+ return {
30
+ transform: `translate(${x}px, ${y}px)`
31
+ };
32
+ }
33
+ const DragLayer = ({ renderItem })=>{
34
+ const { itemType, isDragging, item, initialOffset, currentOffset, mouseOffset } = useDragLayer((monitor)=>({
35
+ item: monitor.getItem(),
36
+ itemType: monitor.getItemType(),
37
+ initialOffset: monitor.getInitialSourceClientOffset(),
38
+ currentOffset: monitor.getSourceClientOffset(),
39
+ isDragging: monitor.isDragging(),
40
+ mouseOffset: monitor.getClientOffset()
41
+ }));
42
+ if (!isDragging) {
43
+ return null;
44
+ }
45
+ return /*#__PURE__*/ jsx(Box, {
46
+ height: "100%",
47
+ left: 0,
48
+ position: "fixed",
49
+ pointerEvents: "none",
50
+ top: 0,
51
+ zIndex: 100,
52
+ width: "100%",
53
+ children: /*#__PURE__*/ jsx(Box, {
54
+ style: getStyle(initialOffset, currentOffset, mouseOffset, item),
55
+ children: renderItem({
56
+ type: itemType,
57
+ item
58
+ })
59
+ })
60
+ });
61
+ };
62
+
63
+ export { DragLayer, isWidgetDragItem };
64
+ //# sourceMappingURL=DragLayer.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DragLayer.mjs","sources":["../../../../../admin/src/components/DragLayer.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box } from '@strapi/design-system';\nimport { DragLayerMonitor, XYCoord, useDragLayer } from 'react-dnd';\n\nimport { getWidgetElement } from '../utils/widgetLayout';\n\nimport type { WidgetArgs } from '../core/apis/Widgets';\n\nexport interface WidgetDragItem extends Pick<WidgetArgs, 'title' | 'icon' | 'link' | 'component'> {\n type: 'widget';\n id: string;\n originalIndex: number;\n}\n\nexport function isWidgetDragItem(item: unknown): item is WidgetDragItem {\n return (\n typeof item === 'object' &&\n item !== null &&\n 'id' in item &&\n typeof item.id === 'string' &&\n 'originalIndex' in item &&\n typeof item.originalIndex === 'number' &&\n 'title' in item &&\n 'component' in item\n );\n}\n\nfunction getStyle(\n initialOffset: XYCoord | null,\n currentOffset: XYCoord | null,\n mouseOffset: XYCoord | null,\n item?: unknown\n) {\n if (!initialOffset || !currentOffset || !mouseOffset) {\n return { display: 'none' };\n }\n\n const { x, y } = mouseOffset;\n\n // Only apply custom offset for widget drags\n if (isWidgetDragItem(item)) {\n // Calculate dynamic offset based on widget position and width\n const widgetElement = getWidgetElement(item.id);\n const previewWidth = widgetElement?.clientWidth;\n const offsetX = previewWidth ? -previewWidth + 20 : 0;\n const offsetY = 20;\n\n return {\n transform: `translate(${x + offsetX}px, ${y + offsetY}px)`,\n };\n }\n\n // Default positioning for non-widget drags\n return {\n transform: `translate(${x}px, ${y}px)`,\n };\n}\n\nexport interface DragLayerProps {\n renderItem: (item: {\n item: unknown;\n type: ReturnType<DragLayerMonitor['getItemType']>;\n }) => React.ReactNode;\n}\n\nconst DragLayer = ({ renderItem }: DragLayerProps) => {\n const { itemType, isDragging, item, initialOffset, currentOffset, mouseOffset } = useDragLayer(\n (monitor) => ({\n item: monitor.getItem(),\n itemType: monitor.getItemType(),\n initialOffset: monitor.getInitialSourceClientOffset(),\n currentOffset: monitor.getSourceClientOffset(),\n isDragging: monitor.isDragging(),\n mouseOffset: monitor.getClientOffset(),\n })\n );\n\n if (!isDragging) {\n return null;\n }\n\n return (\n <Box\n height=\"100%\"\n left={0}\n position=\"fixed\"\n pointerEvents=\"none\"\n top={0}\n zIndex={100}\n width=\"100%\"\n >\n <Box style={getStyle(initialOffset, currentOffset, mouseOffset, item)}>\n {renderItem({ type: itemType, item })}\n </Box>\n </Box>\n );\n};\n\nexport { DragLayer };\n"],"names":["isWidgetDragItem","item","id","originalIndex","getStyle","initialOffset","currentOffset","mouseOffset","display","x","y","widgetElement","getWidgetElement","previewWidth","clientWidth","offsetX","offsetY","transform","DragLayer","renderItem","itemType","isDragging","useDragLayer","monitor","getItem","getItemType","getInitialSourceClientOffset","getSourceClientOffset","getClientOffset","_jsx","Box","height","left","position","pointerEvents","top","zIndex","width","style","type"],"mappings":";;;;;;AAeO,SAASA,iBAAiBC,IAAa,EAAA;IAC5C,OACE,OAAOA,SAAS,QAChBA,IAAAA,IAAAA,KAAS,QACT,IAAQA,IAAAA,IAAAA,IACR,OAAOA,IAAKC,CAAAA,EAAE,KAAK,QACnB,IAAA,eAAA,IAAmBD,QACnB,OAAOA,IAAAA,CAAKE,aAAa,KAAK,QAAA,IAC9B,OAAWF,IAAAA,IAAAA,IACX,WAAeA,IAAAA,IAAAA;AAEnB;AAEA,SAASG,SACPC,aAA6B,EAC7BC,aAA6B,EAC7BC,WAA2B,EAC3BN,IAAc,EAAA;AAEd,IAAA,IAAI,CAACI,aAAAA,IAAiB,CAACC,aAAAA,IAAiB,CAACC,WAAa,EAAA;QACpD,OAAO;YAAEC,OAAS,EAAA;AAAO,SAAA;AAC3B;AAEA,IAAA,MAAM,EAAEC,CAAC,EAAEC,CAAC,EAAE,GAAGH,WAAAA;;AAGjB,IAAA,IAAIP,iBAAiBC,IAAO,CAAA,EAAA;;QAE1B,MAAMU,aAAAA,GAAgBC,gBAAiBX,CAAAA,IAAAA,CAAKC,EAAE,CAAA;AAC9C,QAAA,MAAMW,eAAeF,aAAeG,EAAAA,WAAAA;AACpC,QAAA,MAAMC,OAAUF,GAAAA,YAAAA,GAAe,CAACA,YAAAA,GAAe,EAAK,GAAA,CAAA;AACpD,QAAA,MAAMG,OAAU,GAAA,EAAA;QAEhB,OAAO;YACLC,SAAW,EAAA,CAAC,UAAU,EAAER,CAAIM,GAAAA,OAAAA,CAAQ,IAAI,EAAEL,CAAAA,GAAIM,OAAQ,CAAA,GAAG;AAC3D,SAAA;AACF;;IAGA,OAAO;QACLC,SAAW,EAAA,CAAC,UAAU,EAAER,CAAAA,CAAE,IAAI,EAAEC,CAAAA,CAAE,GAAG;AACvC,KAAA;AACF;AASA,MAAMQ,SAAY,GAAA,CAAC,EAAEC,UAAU,EAAkB,GAAA;AAC/C,IAAA,MAAM,EAAEC,QAAQ,EAAEC,UAAU,EAAEpB,IAAI,EAAEI,aAAa,EAAEC,aAAa,EAAEC,WAAW,EAAE,GAAGe,YAChF,CAAA,CAACC,WAAa;AACZtB,YAAAA,IAAAA,EAAMsB,QAAQC,OAAO,EAAA;AACrBJ,YAAAA,QAAAA,EAAUG,QAAQE,WAAW,EAAA;AAC7BpB,YAAAA,aAAAA,EAAekB,QAAQG,4BAA4B,EAAA;AACnDpB,YAAAA,aAAAA,EAAeiB,QAAQI,qBAAqB,EAAA;AAC5CN,YAAAA,UAAAA,EAAYE,QAAQF,UAAU,EAAA;AAC9Bd,YAAAA,WAAAA,EAAagB,QAAQK,eAAe;SACtC,CAAA,CAAA;AAGF,IAAA,IAAI,CAACP,UAAY,EAAA;QACf,OAAO,IAAA;AACT;AAEA,IAAA,qBACEQ,GAACC,CAAAA,GAAAA,EAAAA;QACCC,MAAO,EAAA,MAAA;QACPC,IAAM,EAAA,CAAA;QACNC,QAAS,EAAA,OAAA;QACTC,aAAc,EAAA,MAAA;QACdC,GAAK,EAAA,CAAA;QACLC,MAAQ,EAAA,GAAA;QACRC,KAAM,EAAA,MAAA;AAEN,QAAA,QAAA,gBAAAR,GAACC,CAAAA,GAAAA,EAAAA;YAAIQ,KAAOlC,EAAAA,QAAAA,CAASC,aAAeC,EAAAA,aAAAA,EAAeC,WAAaN,EAAAA,IAAAA,CAAAA;sBAC7DkB,UAAW,CAAA;gBAAEoB,IAAMnB,EAAAA,QAAAA;AAAUnB,gBAAAA;AAAK,aAAA;;;AAI3C;;;;"}
@@ -0,0 +1,292 @@
1
+ 'use strict';
2
+
3
+ var jsxRuntime = require('react/jsx-runtime');
4
+ var React = require('react');
5
+ var designSystem = require('@strapi/design-system');
6
+ var reactDnd = require('react-dnd');
7
+ var styled = require('styled-components');
8
+ var widgetLayout = require('../utils/widgetLayout.js');
9
+
10
+ function _interopNamespaceDefault(e) {
11
+ var n = Object.create(null);
12
+ if (e) {
13
+ Object.keys(e).forEach(function (k) {
14
+ if (k !== 'default') {
15
+ var d = Object.getOwnPropertyDescriptor(e, k);
16
+ Object.defineProperty(n, k, d.get ? d : {
17
+ enumerable: true,
18
+ get: function () { return e[k]; }
19
+ });
20
+ }
21
+ });
22
+ }
23
+ n.default = e;
24
+ return Object.freeze(n);
25
+ }
26
+
27
+ var React__namespace = /*#__PURE__*/_interopNamespaceDefault(React);
28
+
29
+ const DROP_ZONE_SIZE = 20;
30
+ const getRowInfo = (row)=>{
31
+ const firstWidgetElement = widgetLayout.getWidgetElement(row.widgets[0].uid);
32
+ const lastWidgetElement = widgetLayout.getWidgetElement(row.widgets[row.widgets.length - 1].uid);
33
+ const containerElement = widgetLayout.getWidgetGridContainer();
34
+ if (!firstWidgetElement || !lastWidgetElement || !containerElement) {
35
+ return null;
36
+ }
37
+ const firstRect = firstWidgetElement.getBoundingClientRect();
38
+ const lastRect = lastWidgetElement.getBoundingClientRect();
39
+ const containerRect = containerElement.getBoundingClientRect();
40
+ return {
41
+ firstWidgetElement,
42
+ lastWidgetElement,
43
+ containerElement,
44
+ firstRect,
45
+ lastRect,
46
+ containerRect,
47
+ rowHeight: Math.max(firstRect.height, lastRect.height),
48
+ rowTop: firstRect.top - containerRect.top
49
+ };
50
+ };
51
+ const addVerticalDropZones = (row, rowInfo, rowIndex)=>{
52
+ if (!rowInfo) return [];
53
+ const { containerRect, rowTop, rowHeight } = rowInfo;
54
+ const widgetCount = row.widgets.length;
55
+ // Get widget positions relative to container
56
+ const widgetPositions = row.widgets.map((widget)=>{
57
+ const element = widgetLayout.getWidgetElement(widget.uid);
58
+ if (!element) return null;
59
+ const rect = element.getBoundingClientRect();
60
+ return {
61
+ left: rect.left - containerRect.left,
62
+ width: rect.width
63
+ };
64
+ }).filter((pos)=>pos !== null);
65
+ if (widgetPositions.length !== widgetCount) return [];
66
+ const gapDropZones = [];
67
+ // Always add drop zone before the first widget
68
+ gapDropZones.push({
69
+ insertIndex: row.startIndex,
70
+ position: {
71
+ left: widgetPositions[0].left - DROP_ZONE_SIZE,
72
+ top: rowTop,
73
+ height: rowHeight,
74
+ width: DROP_ZONE_SIZE
75
+ },
76
+ isVisible: true,
77
+ type: 'vertical',
78
+ targetRowIndex: rowIndex
79
+ });
80
+ // Add drop zones between widgets
81
+ widgetPositions.slice(0, -1).forEach((currentWidget, i)=>{
82
+ gapDropZones.push({
83
+ insertIndex: row.startIndex + i + 1,
84
+ position: {
85
+ left: currentWidget.left + currentWidget.width,
86
+ top: rowTop,
87
+ height: rowHeight,
88
+ width: DROP_ZONE_SIZE
89
+ },
90
+ isVisible: true,
91
+ type: 'vertical',
92
+ targetRowIndex: rowIndex
93
+ });
94
+ });
95
+ // Always add drop zone after the last widget
96
+ const lastWidget = widgetPositions[widgetCount - 1];
97
+ gapDropZones.push({
98
+ insertIndex: row.endIndex + 1,
99
+ position: {
100
+ left: lastWidget.left + lastWidget.width,
101
+ top: rowTop,
102
+ height: rowHeight,
103
+ width: DROP_ZONE_SIZE
104
+ },
105
+ isVisible: true,
106
+ type: 'vertical',
107
+ targetRowIndex: rowIndex
108
+ });
109
+ return gapDropZones;
110
+ };
111
+ const addHorizontalDropZones = (row, rowIndex, rowInfo, widgetRows, filteredWidgets)=>{
112
+ if (!rowInfo) return [];
113
+ // Don't show horizontal drop zones if there's only one row with one widget
114
+ if (widgetRows.length === 1 && row.widgets.length === 1) return [];
115
+ const { containerRect } = rowInfo;
116
+ const containerWidth = containerRect.width;
117
+ const horizontalDropZoneHeight = DROP_ZONE_SIZE;
118
+ const gapDropZones = [];
119
+ // Add horizontal drop zone above the first row
120
+ if (rowIndex === 0) {
121
+ const firstRowRect = rowInfo.firstRect;
122
+ const firstRowTop = firstRowRect.top - containerRect.top;
123
+ gapDropZones.push({
124
+ insertIndex: 0,
125
+ position: {
126
+ left: 0,
127
+ top: firstRowTop - horizontalDropZoneHeight,
128
+ height: horizontalDropZoneHeight,
129
+ width: containerWidth
130
+ },
131
+ isVisible: true,
132
+ type: 'horizontal',
133
+ isHorizontalDrop: true
134
+ });
135
+ }
136
+ // Add horizontal drop zone below the current row (between rows or after last row)
137
+ if (rowIndex < widgetRows.length - 1) {
138
+ // Between rows: position above the next row
139
+ const nextRow = widgetRows[rowIndex + 1];
140
+ const nextRowFirstWidgetElement = widgetLayout.getWidgetElement(nextRow.widgets[0].uid);
141
+ if (nextRowFirstWidgetElement) {
142
+ const nextRowRect = nextRowFirstWidgetElement.getBoundingClientRect();
143
+ const nextRowTop = nextRowRect.top - containerRect.top;
144
+ gapDropZones.push({
145
+ insertIndex: row.endIndex + 1,
146
+ position: {
147
+ left: 0,
148
+ top: nextRowTop - horizontalDropZoneHeight,
149
+ height: horizontalDropZoneHeight,
150
+ width: containerWidth
151
+ },
152
+ isVisible: true,
153
+ type: 'horizontal',
154
+ isHorizontalDrop: true
155
+ });
156
+ }
157
+ } else {
158
+ // After the last row: position below the current row
159
+ const lastRowRect = rowInfo.lastRect;
160
+ const lastRowBottom = lastRowRect.bottom - containerRect.top;
161
+ gapDropZones.push({
162
+ insertIndex: filteredWidgets.length,
163
+ position: {
164
+ left: 0,
165
+ top: lastRowBottom,
166
+ height: horizontalDropZoneHeight,
167
+ width: containerWidth
168
+ },
169
+ isVisible: true,
170
+ type: 'horizontal',
171
+ isHorizontalDrop: true
172
+ });
173
+ }
174
+ return gapDropZones;
175
+ };
176
+ const GapDropZoneManager = ({ filteredWidgets, columnWidths, draggedWidgetId, moveWidget })=>{
177
+ const [positions, setPositions] = React__namespace.useState([]);
178
+ // Calculate widget rows
179
+ const widgetRows = React__namespace.useMemo(()=>{
180
+ return widgetLayout.calculateWidgetRows(filteredWidgets, columnWidths);
181
+ }, [
182
+ filteredWidgets,
183
+ columnWidths
184
+ ]);
185
+ // Main function to calculate GapDropZone positions
186
+ const calculateGapDropZonePositions = React__namespace.useCallback(()=>{
187
+ const gapDropZones = [];
188
+ // Find which row the dragged widget is from
189
+ const draggedWidgetRow = draggedWidgetId ? widgetRows.find((row)=>row.widgets.some((widget)=>widget.uid === draggedWidgetId)) : null;
190
+ widgetRows.forEach((row, rowIndex)=>{
191
+ const rowInfo = getRowInfo(row);
192
+ if (!rowInfo) return;
193
+ const widgetCount = row.widgets.length;
194
+ // Determine if we should show vertical drop zones for this row
195
+ const isDraggingFromThisRow = draggedWidgetRow && draggedWidgetRow === row;
196
+ const isDraggingFromAnotherRow = draggedWidgetRow && draggedWidgetRow !== row;
197
+ const canAcceptMoreWidgets = widgetCount < 3;
198
+ const shouldShowVerticalDropZones = isDraggingFromThisRow || isDraggingFromAnotherRow && canAcceptMoreWidgets;
199
+ // Add vertical drop zones based on widget count
200
+ if (shouldShowVerticalDropZones) {
201
+ const verticalDropZones = addVerticalDropZones(row, rowInfo, rowIndex);
202
+ gapDropZones.push(...verticalDropZones);
203
+ }
204
+ // Add horizontal drop zones
205
+ const horizontalDropZones = addHorizontalDropZones(row, rowIndex, rowInfo, widgetRows, filteredWidgets);
206
+ gapDropZones.push(...horizontalDropZones);
207
+ });
208
+ return gapDropZones;
209
+ }, [
210
+ widgetRows,
211
+ draggedWidgetId,
212
+ filteredWidgets
213
+ ]);
214
+ React__namespace.useLayoutEffect(()=>{
215
+ const updatePositions = ()=>{
216
+ const newPositions = calculateGapDropZonePositions();
217
+ setPositions(newPositions);
218
+ };
219
+ updatePositions();
220
+ // Update positions on container resize using ResizeObserver
221
+ const containerElement = widgetLayout.getWidgetGridContainer();
222
+ if (!containerElement) return;
223
+ const resizeObserver = new ResizeObserver(()=>{
224
+ updatePositions();
225
+ });
226
+ resizeObserver.observe(containerElement);
227
+ return ()=>{
228
+ resizeObserver.disconnect();
229
+ };
230
+ }, [
231
+ calculateGapDropZonePositions
232
+ ]);
233
+ return positions.map((gapDropZone)=>/*#__PURE__*/ jsxRuntime.jsx(GapDropZone, {
234
+ insertIndex: gapDropZone.insertIndex,
235
+ position: gapDropZone.position,
236
+ isVisible: gapDropZone.isVisible,
237
+ type: gapDropZone.type,
238
+ moveWidget: moveWidget,
239
+ targetRowIndex: gapDropZone.targetRowIndex
240
+ }, `gap-drop-zone-${gapDropZone.type}-${gapDropZone.insertIndex}-${gapDropZone.targetRowIndex ?? 'no-row'}`));
241
+ };
242
+ const GapDropZoneContainer = styled.styled(designSystem.Box)`
243
+ background-color: ${({ $isOver, theme })=>$isOver ? `${theme.colors.primary100}` : 'transparent'};
244
+ border: ${({ $isOver, theme })=>$isOver ? `2px solid ${theme.colors.primary500}` : '2px solid transparent'};
245
+ opacity: ${({ $isOver })=>$isOver ? 1 : 0.6};
246
+ transition: all 0.2s ease-in-out;
247
+ cursor: pointer;
248
+ border-radius: ${({ theme })=>theme.borderRadius};
249
+ display: flex;
250
+ align-items: center;
251
+ justify-content: center;
252
+ position: absolute;
253
+ top: 0;
254
+ bottom: 0;
255
+ width: ${DROP_ZONE_SIZE}px;
256
+ z-index: 1;
257
+ `;
258
+ const GapDropZone = ({ insertIndex, position, isVisible, type, moveWidget, targetRowIndex })=>{
259
+ const isHorizontalDrop = type === 'horizontal';
260
+ const [{ isOver }, drop] = reactDnd.useDrop(()=>({
261
+ accept: 'widget',
262
+ drop: (item)=>{
263
+ moveWidget(item.id, insertIndex, targetRowIndex, isHorizontalDrop);
264
+ },
265
+ collect: (monitor)=>({
266
+ isOver: monitor.isOver()
267
+ })
268
+ }), [
269
+ insertIndex,
270
+ isHorizontalDrop,
271
+ moveWidget,
272
+ targetRowIndex
273
+ ]);
274
+ if (!isVisible) {
275
+ return null;
276
+ }
277
+ return /*#__PURE__*/ jsxRuntime.jsx(GapDropZoneContainer, {
278
+ ref: drop,
279
+ $isOver: isOver,
280
+ style: {
281
+ transform: `translate(${position.left}px, ${position.top}px)`,
282
+ height: `${position.height}px`,
283
+ width: `${position.width}px`
284
+ }
285
+ });
286
+ };
287
+
288
+ exports.DROP_ZONE_SIZE = DROP_ZONE_SIZE;
289
+ exports.GapDropZoneManager = GapDropZoneManager;
290
+ exports.addHorizontalDropZones = addHorizontalDropZones;
291
+ exports.addVerticalDropZones = addVerticalDropZones;
292
+ //# sourceMappingURL=GapDropZone.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GapDropZone.js","sources":["../../../../../admin/src/components/GapDropZone.tsx"],"sourcesContent":["import * as React from 'react';\n\nimport { Box } from '@strapi/design-system';\n// TODO: use @dnd-kit/core instead\nimport { useDrop } from 'react-dnd';\nimport { styled } from 'styled-components';\n\nimport {\n calculateWidgetRows,\n type WidgetRow,\n getWidgetElement,\n getWidgetGridContainer,\n} from '../utils/widgetLayout';\n\nimport type { WidgetWithUID } from '../core/apis/Widgets';\n\nexport const DROP_ZONE_SIZE = 20;\n\nexport interface GapDropZonePosition {\n insertIndex: number;\n position: { left: number; top: number; height: number; width: number };\n isVisible: boolean;\n type: 'vertical' | 'horizontal';\n isHorizontalDrop?: boolean;\n targetRowIndex?: number;\n}\n\ninterface GapDropZoneManagerProps {\n filteredWidgets: WidgetWithUID[];\n columnWidths: Record<string, number>;\n draggedWidgetId?: string;\n moveWidget: (id: string, to: number, targetRowIndex?: number, isHorizontalDrop?: boolean) => void;\n}\n\nconst getRowInfo = (row: WidgetRow) => {\n const firstWidgetElement = getWidgetElement(row.widgets[0].uid);\n const lastWidgetElement = getWidgetElement(row.widgets[row.widgets.length - 1].uid);\n const containerElement = getWidgetGridContainer();\n\n if (!firstWidgetElement || !lastWidgetElement || !containerElement) {\n return null;\n }\n\n const firstRect = firstWidgetElement.getBoundingClientRect();\n const lastRect = lastWidgetElement.getBoundingClientRect();\n const containerRect = containerElement.getBoundingClientRect();\n\n return {\n firstWidgetElement,\n lastWidgetElement,\n containerElement,\n firstRect,\n lastRect,\n containerRect,\n rowHeight: Math.max(firstRect.height, lastRect.height),\n rowTop: firstRect.top - containerRect.top,\n };\n};\n\nexport const addVerticalDropZones = (\n row: WidgetRow,\n rowInfo: ReturnType<typeof getRowInfo>,\n rowIndex: number\n): GapDropZonePosition[] => {\n if (!rowInfo) return [];\n\n const { containerRect, rowTop, rowHeight } = rowInfo;\n const widgetCount = row.widgets.length;\n\n // Get widget positions relative to container\n const widgetPositions = row.widgets\n .map((widget) => {\n const element = getWidgetElement(widget.uid);\n if (!element) return null;\n\n const rect = element.getBoundingClientRect();\n return {\n left: rect.left - containerRect.left,\n width: rect.width,\n };\n })\n .filter((pos): pos is NonNullable<typeof pos> => pos !== null);\n\n if (widgetPositions.length !== widgetCount) return [];\n\n const gapDropZones: GapDropZonePosition[] = [];\n\n // Always add drop zone before the first widget\n gapDropZones.push({\n insertIndex: row.startIndex,\n position: {\n left: widgetPositions[0].left - DROP_ZONE_SIZE,\n top: rowTop,\n height: rowHeight,\n width: DROP_ZONE_SIZE,\n },\n isVisible: true,\n type: 'vertical',\n targetRowIndex: rowIndex,\n });\n\n // Add drop zones between widgets\n widgetPositions.slice(0, -1).forEach((currentWidget, i) => {\n gapDropZones.push({\n insertIndex: row.startIndex + i + 1,\n position: {\n left: currentWidget.left + currentWidget.width,\n top: rowTop,\n height: rowHeight,\n width: DROP_ZONE_SIZE,\n },\n isVisible: true,\n type: 'vertical',\n targetRowIndex: rowIndex,\n });\n });\n\n // Always add drop zone after the last widget\n const lastWidget = widgetPositions[widgetCount - 1];\n gapDropZones.push({\n insertIndex: row.endIndex + 1,\n position: {\n left: lastWidget.left + lastWidget.width,\n top: rowTop,\n height: rowHeight,\n width: DROP_ZONE_SIZE,\n },\n isVisible: true,\n type: 'vertical',\n targetRowIndex: rowIndex,\n });\n\n return gapDropZones;\n};\n\nexport const addHorizontalDropZones = (\n row: WidgetRow,\n rowIndex: number,\n rowInfo: ReturnType<typeof getRowInfo>,\n widgetRows: WidgetRow[],\n filteredWidgets: WidgetWithUID[]\n): GapDropZonePosition[] => {\n if (!rowInfo) return [];\n\n // Don't show horizontal drop zones if there's only one row with one widget\n if (widgetRows.length === 1 && row.widgets.length === 1) return [];\n\n const { containerRect } = rowInfo;\n const containerWidth = containerRect.width;\n const horizontalDropZoneHeight = DROP_ZONE_SIZE;\n\n const gapDropZones: GapDropZonePosition[] = [];\n\n // Add horizontal drop zone above the first row\n if (rowIndex === 0) {\n const firstRowRect = rowInfo.firstRect;\n const firstRowTop = firstRowRect.top - containerRect.top;\n\n gapDropZones.push({\n insertIndex: 0,\n position: {\n left: 0,\n top: firstRowTop - horizontalDropZoneHeight,\n height: horizontalDropZoneHeight,\n width: containerWidth,\n },\n isVisible: true,\n type: 'horizontal',\n isHorizontalDrop: true,\n });\n }\n\n // Add horizontal drop zone below the current row (between rows or after last row)\n if (rowIndex < widgetRows.length - 1) {\n // Between rows: position above the next row\n const nextRow = widgetRows[rowIndex + 1];\n const nextRowFirstWidgetElement = getWidgetElement(nextRow.widgets[0].uid);\n\n if (nextRowFirstWidgetElement) {\n const nextRowRect = nextRowFirstWidgetElement.getBoundingClientRect();\n const nextRowTop = nextRowRect.top - containerRect.top;\n\n gapDropZones.push({\n insertIndex: row.endIndex + 1,\n position: {\n left: 0,\n top: nextRowTop - horizontalDropZoneHeight,\n height: horizontalDropZoneHeight,\n width: containerWidth,\n },\n isVisible: true,\n type: 'horizontal',\n isHorizontalDrop: true,\n });\n }\n } else {\n // After the last row: position below the current row\n const lastRowRect = rowInfo.lastRect;\n const lastRowBottom = lastRowRect.bottom - containerRect.top;\n\n gapDropZones.push({\n insertIndex: filteredWidgets.length,\n position: {\n left: 0,\n top: lastRowBottom,\n height: horizontalDropZoneHeight,\n width: containerWidth,\n },\n isVisible: true,\n type: 'horizontal',\n isHorizontalDrop: true,\n });\n }\n\n return gapDropZones;\n};\n\nexport const GapDropZoneManager = ({\n filteredWidgets,\n columnWidths,\n draggedWidgetId,\n moveWidget,\n}: GapDropZoneManagerProps) => {\n const [positions, setPositions] = React.useState<GapDropZonePosition[]>([]);\n\n // Calculate widget rows\n const widgetRows = React.useMemo(() => {\n return calculateWidgetRows(filteredWidgets, columnWidths);\n }, [filteredWidgets, columnWidths]);\n\n // Main function to calculate GapDropZone positions\n const calculateGapDropZonePositions = React.useCallback(() => {\n const gapDropZones: GapDropZonePosition[] = [];\n\n // Find which row the dragged widget is from\n const draggedWidgetRow = draggedWidgetId\n ? widgetRows.find((row) => row.widgets.some((widget) => widget.uid === draggedWidgetId))\n : null;\n\n widgetRows.forEach((row, rowIndex) => {\n const rowInfo = getRowInfo(row);\n if (!rowInfo) return;\n\n const widgetCount = row.widgets.length;\n\n // Determine if we should show vertical drop zones for this row\n const isDraggingFromThisRow = draggedWidgetRow && draggedWidgetRow === row;\n const isDraggingFromAnotherRow = draggedWidgetRow && draggedWidgetRow !== row;\n const canAcceptMoreWidgets = widgetCount < 3;\n\n const shouldShowVerticalDropZones =\n isDraggingFromThisRow || (isDraggingFromAnotherRow && canAcceptMoreWidgets);\n\n // Add vertical drop zones based on widget count\n if (shouldShowVerticalDropZones) {\n const verticalDropZones = addVerticalDropZones(row, rowInfo, rowIndex);\n gapDropZones.push(...verticalDropZones);\n }\n\n // Add horizontal drop zones\n const horizontalDropZones = addHorizontalDropZones(\n row,\n rowIndex,\n rowInfo,\n widgetRows,\n filteredWidgets\n );\n gapDropZones.push(...horizontalDropZones);\n });\n\n return gapDropZones;\n }, [widgetRows, draggedWidgetId, filteredWidgets]);\n\n React.useLayoutEffect(() => {\n const updatePositions = () => {\n const newPositions = calculateGapDropZonePositions();\n setPositions(newPositions);\n };\n\n updatePositions();\n\n // Update positions on container resize using ResizeObserver\n const containerElement = getWidgetGridContainer();\n if (!containerElement) return;\n\n const resizeObserver = new ResizeObserver(() => {\n updatePositions();\n });\n\n resizeObserver.observe(containerElement);\n\n return () => {\n resizeObserver.disconnect();\n };\n }, [calculateGapDropZonePositions]);\n\n return positions.map((gapDropZone) => (\n <GapDropZone\n key={`gap-drop-zone-${gapDropZone.type}-${gapDropZone.insertIndex}-${gapDropZone.targetRowIndex ?? 'no-row'}`}\n insertIndex={gapDropZone.insertIndex}\n position={gapDropZone.position}\n isVisible={gapDropZone.isVisible}\n type={gapDropZone.type}\n moveWidget={moveWidget}\n targetRowIndex={gapDropZone.targetRowIndex}\n />\n ));\n};\n\ninterface GapDropZoneProps {\n insertIndex: number;\n position: { left: number; top: number; height: number; width: number };\n isVisible: boolean;\n type: 'vertical' | 'horizontal';\n moveWidget: (id: string, to: number, targetRowIndex?: number, isHorizontalDrop?: boolean) => void;\n targetRowIndex?: number;\n}\n\nconst GapDropZoneContainer = styled(Box)<{\n $isOver: boolean;\n}>`\n background-color: ${({ $isOver, theme }) =>\n $isOver ? `${theme.colors.primary100}` : 'transparent'};\n border: ${({ $isOver, theme }) =>\n $isOver ? `2px solid ${theme.colors.primary500}` : '2px solid transparent'};\n opacity: ${({ $isOver }) => ($isOver ? 1 : 0.6)};\n transition: all 0.2s ease-in-out;\n cursor: pointer;\n border-radius: ${({ theme }) => theme.borderRadius};\n display: flex;\n align-items: center;\n justify-content: center;\n position: absolute;\n top: 0;\n bottom: 0;\n width: ${DROP_ZONE_SIZE}px;\n z-index: 1;\n`;\n\nconst GapDropZone = ({\n insertIndex,\n position,\n isVisible,\n type,\n moveWidget,\n targetRowIndex,\n}: GapDropZoneProps) => {\n const isHorizontalDrop = type === 'horizontal';\n\n const [{ isOver }, drop] = useDrop(\n () => ({\n accept: 'widget',\n drop: (item: { id: string }) => {\n moveWidget(item.id, insertIndex, targetRowIndex, isHorizontalDrop);\n },\n collect: (monitor) => ({\n isOver: monitor.isOver(),\n }),\n }),\n [insertIndex, isHorizontalDrop, moveWidget, targetRowIndex]\n );\n\n if (!isVisible) {\n return null;\n }\n\n return (\n <GapDropZoneContainer\n ref={drop}\n $isOver={isOver}\n style={{\n transform: `translate(${position.left}px, ${position.top}px)`,\n height: `${position.height}px`,\n width: `${position.width}px`,\n }}\n />\n );\n};\n"],"names":["DROP_ZONE_SIZE","getRowInfo","row","firstWidgetElement","getWidgetElement","widgets","uid","lastWidgetElement","length","containerElement","getWidgetGridContainer","firstRect","getBoundingClientRect","lastRect","containerRect","rowHeight","Math","max","height","rowTop","top","addVerticalDropZones","rowInfo","rowIndex","widgetCount","widgetPositions","map","widget","element","rect","left","width","filter","pos","gapDropZones","push","insertIndex","startIndex","position","isVisible","type","targetRowIndex","slice","forEach","currentWidget","i","lastWidget","endIndex","addHorizontalDropZones","widgetRows","filteredWidgets","containerWidth","horizontalDropZoneHeight","firstRowRect","firstRowTop","isHorizontalDrop","nextRow","nextRowFirstWidgetElement","nextRowRect","nextRowTop","lastRowRect","lastRowBottom","bottom","GapDropZoneManager","columnWidths","draggedWidgetId","moveWidget","positions","setPositions","React","useState","useMemo","calculateWidgetRows","calculateGapDropZonePositions","useCallback","draggedWidgetRow","find","some","isDraggingFromThisRow","isDraggingFromAnotherRow","canAcceptMoreWidgets","shouldShowVerticalDropZones","verticalDropZones","horizontalDropZones","useLayoutEffect","updatePositions","newPositions","resizeObserver","ResizeObserver","observe","disconnect","gapDropZone","_jsx","GapDropZone","GapDropZoneContainer","styled","Box","$isOver","theme","colors","primary100","primary500","borderRadius","isOver","drop","useDrop","accept","item","id","collect","monitor","ref","style","transform"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgBO,MAAMA,iBAAiB;AAkB9B,MAAMC,aAAa,CAACC,GAAAA,GAAAA;AAClB,IAAA,MAAMC,qBAAqBC,6BAAiBF,CAAAA,GAAAA,CAAIG,OAAO,CAAC,CAAA,CAAE,CAACC,GAAG,CAAA;AAC9D,IAAA,MAAMC,iBAAoBH,GAAAA,6BAAAA,CAAiBF,GAAIG,CAAAA,OAAO,CAACH,GAAAA,CAAIG,OAAO,CAACG,MAAM,GAAG,CAAE,CAAA,CAACF,GAAG,CAAA;AAClF,IAAA,MAAMG,gBAAmBC,GAAAA,mCAAAA,EAAAA;AAEzB,IAAA,IAAI,CAACP,kBAAAA,IAAsB,CAACI,iBAAAA,IAAqB,CAACE,gBAAkB,EAAA;QAClE,OAAO,IAAA;AACT;IAEA,MAAME,SAAAA,GAAYR,mBAAmBS,qBAAqB,EAAA;IAC1D,MAAMC,QAAAA,GAAWN,kBAAkBK,qBAAqB,EAAA;IACxD,MAAME,aAAAA,GAAgBL,iBAAiBG,qBAAqB,EAAA;IAE5D,OAAO;AACLT,QAAAA,kBAAAA;AACAI,QAAAA,iBAAAA;AACAE,QAAAA,gBAAAA;AACAE,QAAAA,SAAAA;AACAE,QAAAA,QAAAA;AACAC,QAAAA,aAAAA;AACAC,QAAAA,SAAAA,EAAWC,KAAKC,GAAG,CAACN,UAAUO,MAAM,EAAEL,SAASK,MAAM,CAAA;AACrDC,QAAAA,MAAAA,EAAQR,SAAUS,CAAAA,GAAG,GAAGN,aAAAA,CAAcM;AACxC,KAAA;AACF,CAAA;AAEaC,MAAAA,oBAAAA,GAAuB,CAClCnB,GAAAA,EACAoB,OACAC,EAAAA,QAAAA,GAAAA;IAEA,IAAI,CAACD,OAAS,EAAA,OAAO,EAAE;AAEvB,IAAA,MAAM,EAAER,aAAa,EAAEK,MAAM,EAAEJ,SAAS,EAAE,GAAGO,OAAAA;AAC7C,IAAA,MAAME,WAActB,GAAAA,GAAAA,CAAIG,OAAO,CAACG,MAAM;;AAGtC,IAAA,MAAMiB,kBAAkBvB,GAAIG,CAAAA,OAAO,CAChCqB,GAAG,CAAC,CAACC,MAAAA,GAAAA;QACJ,MAAMC,OAAAA,GAAUxB,6BAAiBuB,CAAAA,MAAAA,CAAOrB,GAAG,CAAA;QAC3C,IAAI,CAACsB,SAAS,OAAO,IAAA;QAErB,MAAMC,IAAAA,GAAOD,QAAQhB,qBAAqB,EAAA;QAC1C,OAAO;AACLkB,YAAAA,IAAAA,EAAMD,IAAKC,CAAAA,IAAI,GAAGhB,aAAAA,CAAcgB,IAAI;AACpCC,YAAAA,KAAAA,EAAOF,KAAKE;AACd,SAAA;AACF,KAAA,CAAA,CACCC,MAAM,CAAC,CAACC,GAAAA,GAAwCA,GAAQ,KAAA,IAAA,CAAA;AAE3D,IAAA,IAAIR,eAAgBjB,CAAAA,MAAM,KAAKgB,WAAAA,EAAa,OAAO,EAAE;AAErD,IAAA,MAAMU,eAAsC,EAAE;;AAG9CA,IAAAA,YAAAA,CAAaC,IAAI,CAAC;AAChBC,QAAAA,WAAAA,EAAalC,IAAImC,UAAU;QAC3BC,QAAU,EAAA;AACRR,YAAAA,IAAAA,EAAML,eAAe,CAAC,CAAE,CAAA,CAACK,IAAI,GAAG9B,cAAAA;YAChCoB,GAAKD,EAAAA,MAAAA;YACLD,MAAQH,EAAAA,SAAAA;YACRgB,KAAO/B,EAAAA;AACT,SAAA;QACAuC,SAAW,EAAA,IAAA;QACXC,IAAM,EAAA,UAAA;QACNC,cAAgBlB,EAAAA;AAClB,KAAA,CAAA;;IAGAE,eAAgBiB,CAAAA,KAAK,CAAC,CAAG,EAAA,CAAC,GAAGC,OAAO,CAAC,CAACC,aAAeC,EAAAA,CAAAA,GAAAA;AACnDX,QAAAA,YAAAA,CAAaC,IAAI,CAAC;YAChBC,WAAalC,EAAAA,GAAAA,CAAImC,UAAU,GAAGQ,CAAI,GAAA,CAAA;YAClCP,QAAU,EAAA;AACRR,gBAAAA,IAAAA,EAAMc,aAAcd,CAAAA,IAAI,GAAGc,aAAAA,CAAcb,KAAK;gBAC9CX,GAAKD,EAAAA,MAAAA;gBACLD,MAAQH,EAAAA,SAAAA;gBACRgB,KAAO/B,EAAAA;AACT,aAAA;YACAuC,SAAW,EAAA,IAAA;YACXC,IAAM,EAAA,UAAA;YACNC,cAAgBlB,EAAAA;AAClB,SAAA,CAAA;AACF,KAAA,CAAA;;AAGA,IAAA,MAAMuB,UAAarB,GAAAA,eAAe,CAACD,WAAAA,GAAc,CAAE,CAAA;AACnDU,IAAAA,YAAAA,CAAaC,IAAI,CAAC;QAChBC,WAAalC,EAAAA,GAAAA,CAAI6C,QAAQ,GAAG,CAAA;QAC5BT,QAAU,EAAA;AACRR,YAAAA,IAAAA,EAAMgB,UAAWhB,CAAAA,IAAI,GAAGgB,UAAAA,CAAWf,KAAK;YACxCX,GAAKD,EAAAA,MAAAA;YACLD,MAAQH,EAAAA,SAAAA;YACRgB,KAAO/B,EAAAA;AACT,SAAA;QACAuC,SAAW,EAAA,IAAA;QACXC,IAAM,EAAA,UAAA;QACNC,cAAgBlB,EAAAA;AAClB,KAAA,CAAA;IAEA,OAAOW,YAAAA;AACT;MAEac,sBAAyB,GAAA,CACpC9C,GACAqB,EAAAA,QAAAA,EACAD,SACA2B,UACAC,EAAAA,eAAAA,GAAAA;IAEA,IAAI,CAAC5B,OAAS,EAAA,OAAO,EAAE;;IAGvB,IAAI2B,UAAAA,CAAWzC,MAAM,KAAK,CAAKN,IAAAA,GAAAA,CAAIG,OAAO,CAACG,MAAM,KAAK,CAAG,EAAA,OAAO,EAAE;IAElE,MAAM,EAAEM,aAAa,EAAE,GAAGQ,OAAAA;IAC1B,MAAM6B,cAAAA,GAAiBrC,cAAciB,KAAK;AAC1C,IAAA,MAAMqB,wBAA2BpD,GAAAA,cAAAA;AAEjC,IAAA,MAAMkC,eAAsC,EAAE;;AAG9C,IAAA,IAAIX,aAAa,CAAG,EAAA;QAClB,MAAM8B,YAAAA,GAAe/B,QAAQX,SAAS;AACtC,QAAA,MAAM2C,WAAcD,GAAAA,YAAAA,CAAajC,GAAG,GAAGN,cAAcM,GAAG;AAExDc,QAAAA,YAAAA,CAAaC,IAAI,CAAC;YAChBC,WAAa,EAAA,CAAA;YACbE,QAAU,EAAA;gBACRR,IAAM,EAAA,CAAA;AACNV,gBAAAA,GAAAA,EAAKkC,WAAcF,GAAAA,wBAAAA;gBACnBlC,MAAQkC,EAAAA,wBAAAA;gBACRrB,KAAOoB,EAAAA;AACT,aAAA;YACAZ,SAAW,EAAA,IAAA;YACXC,IAAM,EAAA,YAAA;YACNe,gBAAkB,EAAA;AACpB,SAAA,CAAA;AACF;;AAGA,IAAA,IAAIhC,QAAW0B,GAAAA,UAAAA,CAAWzC,MAAM,GAAG,CAAG,EAAA;;AAEpC,QAAA,MAAMgD,OAAUP,GAAAA,UAAU,CAAC1B,QAAAA,GAAW,CAAE,CAAA;AACxC,QAAA,MAAMkC,4BAA4BrD,6BAAiBoD,CAAAA,OAAAA,CAAQnD,OAAO,CAAC,CAAA,CAAE,CAACC,GAAG,CAAA;AAEzE,QAAA,IAAImD,yBAA2B,EAAA;YAC7B,MAAMC,WAAAA,GAAcD,0BAA0B7C,qBAAqB,EAAA;AACnE,YAAA,MAAM+C,UAAaD,GAAAA,WAAAA,CAAYtC,GAAG,GAAGN,cAAcM,GAAG;AAEtDc,YAAAA,YAAAA,CAAaC,IAAI,CAAC;gBAChBC,WAAalC,EAAAA,GAAAA,CAAI6C,QAAQ,GAAG,CAAA;gBAC5BT,QAAU,EAAA;oBACRR,IAAM,EAAA,CAAA;AACNV,oBAAAA,GAAAA,EAAKuC,UAAaP,GAAAA,wBAAAA;oBAClBlC,MAAQkC,EAAAA,wBAAAA;oBACRrB,KAAOoB,EAAAA;AACT,iBAAA;gBACAZ,SAAW,EAAA,IAAA;gBACXC,IAAM,EAAA,YAAA;gBACNe,gBAAkB,EAAA;AACpB,aAAA,CAAA;AACF;KACK,MAAA;;QAEL,MAAMK,WAAAA,GAActC,QAAQT,QAAQ;AACpC,QAAA,MAAMgD,aAAgBD,GAAAA,WAAAA,CAAYE,MAAM,GAAGhD,cAAcM,GAAG;AAE5Dc,QAAAA,YAAAA,CAAaC,IAAI,CAAC;AAChBC,YAAAA,WAAAA,EAAac,gBAAgB1C,MAAM;YACnC8B,QAAU,EAAA;gBACRR,IAAM,EAAA,CAAA;gBACNV,GAAKyC,EAAAA,aAAAA;gBACL3C,MAAQkC,EAAAA,wBAAAA;gBACRrB,KAAOoB,EAAAA;AACT,aAAA;YACAZ,SAAW,EAAA,IAAA;YACXC,IAAM,EAAA,YAAA;YACNe,gBAAkB,EAAA;AACpB,SAAA,CAAA;AACF;IAEA,OAAOrB,YAAAA;AACT;AAEO,MAAM6B,kBAAqB,GAAA,CAAC,EACjCb,eAAe,EACfc,YAAY,EACZC,eAAe,EACfC,UAAU,EACc,GAAA;AACxB,IAAA,MAAM,CAACC,SAAWC,EAAAA,YAAAA,CAAa,GAAGC,gBAAMC,CAAAA,QAAQ,CAAwB,EAAE,CAAA;;IAG1E,MAAMrB,UAAAA,GAAaoB,gBAAME,CAAAA,OAAO,CAAC,IAAA;AAC/B,QAAA,OAAOC,iCAAoBtB,eAAiBc,EAAAA,YAAAA,CAAAA;KAC3C,EAAA;AAACd,QAAAA,eAAAA;AAAiBc,QAAAA;AAAa,KAAA,CAAA;;IAGlC,MAAMS,6BAAAA,GAAgCJ,gBAAMK,CAAAA,WAAW,CAAC,IAAA;AACtD,QAAA,MAAMxC,eAAsC,EAAE;;AAG9C,QAAA,MAAMyC,mBAAmBV,eACrBhB,GAAAA,UAAAA,CAAW2B,IAAI,CAAC,CAAC1E,GAAQA,GAAAA,GAAAA,CAAIG,OAAO,CAACwE,IAAI,CAAC,CAAClD,SAAWA,MAAOrB,CAAAA,GAAG,KAAK2D,eACrE,CAAA,CAAA,GAAA,IAAA;QAEJhB,UAAWN,CAAAA,OAAO,CAAC,CAACzC,GAAKqB,EAAAA,QAAAA,GAAAA;AACvB,YAAA,MAAMD,UAAUrB,UAAWC,CAAAA,GAAAA,CAAAA;AAC3B,YAAA,IAAI,CAACoB,OAAS,EAAA;AAEd,YAAA,MAAME,WAActB,GAAAA,GAAAA,CAAIG,OAAO,CAACG,MAAM;;YAGtC,MAAMsE,qBAAAA,GAAwBH,oBAAoBA,gBAAqBzE,KAAAA,GAAAA;YACvE,MAAM6E,wBAAAA,GAA2BJ,oBAAoBA,gBAAqBzE,KAAAA,GAAAA;AAC1E,YAAA,MAAM8E,uBAAuBxD,WAAc,GAAA,CAAA;YAE3C,MAAMyD,2BAAAA,GACJH,yBAA0BC,wBAA4BC,IAAAA,oBAAAA;;AAGxD,YAAA,IAAIC,2BAA6B,EAAA;gBAC/B,MAAMC,iBAAAA,GAAoB7D,oBAAqBnB,CAAAA,GAAAA,EAAKoB,OAASC,EAAAA,QAAAA,CAAAA;AAC7DW,gBAAAA,YAAAA,CAAaC,IAAI,CAAI+C,GAAAA,iBAAAA,CAAAA;AACvB;;AAGA,YAAA,MAAMC,mBAAsBnC,GAAAA,sBAAAA,CAC1B9C,GACAqB,EAAAA,QAAAA,EACAD,SACA2B,UACAC,EAAAA,eAAAA,CAAAA;AAEFhB,YAAAA,YAAAA,CAAaC,IAAI,CAAIgD,GAAAA,mBAAAA,CAAAA;AACvB,SAAA,CAAA;QAEA,OAAOjD,YAAAA;KACN,EAAA;AAACe,QAAAA,UAAAA;AAAYgB,QAAAA,eAAAA;AAAiBf,QAAAA;AAAgB,KAAA,CAAA;AAEjDmB,IAAAA,gBAAAA,CAAMe,eAAe,CAAC,IAAA;AACpB,QAAA,MAAMC,eAAkB,GAAA,IAAA;AACtB,YAAA,MAAMC,YAAeb,GAAAA,6BAAAA,EAAAA;YACrBL,YAAakB,CAAAA,YAAAA,CAAAA;AACf,SAAA;AAEAD,QAAAA,eAAAA,EAAAA;;AAGA,QAAA,MAAM5E,gBAAmBC,GAAAA,mCAAAA,EAAAA;AACzB,QAAA,IAAI,CAACD,gBAAkB,EAAA;QAEvB,MAAM8E,cAAAA,GAAiB,IAAIC,cAAe,CAAA,IAAA;AACxCH,YAAAA,eAAAA,EAAAA;AACF,SAAA,CAAA;AAEAE,QAAAA,cAAAA,CAAeE,OAAO,CAAChF,gBAAAA,CAAAA;QAEvB,OAAO,IAAA;AACL8E,YAAAA,cAAAA,CAAeG,UAAU,EAAA;AAC3B,SAAA;KACC,EAAA;AAACjB,QAAAA;AAA8B,KAAA,CAAA;AAElC,IAAA,OAAON,SAAUzC,CAAAA,GAAG,CAAC,CAACiE,4BACpBC,cAACC,CAAAA,WAAAA,EAAAA;AAECzD,YAAAA,WAAAA,EAAauD,YAAYvD,WAAW;AACpCE,YAAAA,QAAAA,EAAUqD,YAAYrD,QAAQ;AAC9BC,YAAAA,SAAAA,EAAWoD,YAAYpD,SAAS;AAChCC,YAAAA,IAAAA,EAAMmD,YAAYnD,IAAI;YACtB0B,UAAYA,EAAAA,UAAAA;AACZzB,YAAAA,cAAAA,EAAgBkD,YAAYlD;AANvB,SAAA,EAAA,CAAC,cAAc,EAAEkD,WAAAA,CAAYnD,IAAI,CAAC,CAAC,EAAEmD,WAAAA,CAAYvD,WAAW,CAAC,CAAC,EAAEuD,WAAAA,CAAYlD,cAAc,IAAI,SAAS,CAAC,CAAA,CAAA;AASnH;AAWA,MAAMqD,oBAAAA,GAAuBC,aAAOC,CAAAA,gBAAAA,CAElC;AACkB,oBAAA,EAAE,CAAC,EAAEC,OAAO,EAAEC,KAAK,EAAE,GACrCD,OAAAA,GAAU,CAAC,EAAEC,MAAMC,MAAM,CAACC,UAAU,CAAC,CAAC,GAAG,aAAc,CAAA;AACjD,UAAA,EAAE,CAAC,EAAEH,OAAO,EAAEC,KAAK,EAAE,GAC3BD,OAAU,GAAA,CAAC,UAAU,EAAEC,MAAMC,MAAM,CAACE,UAAU,CAAC,CAAC,GAAG,uBAAwB,CAAA;AACpE,WAAA,EAAE,CAAC,EAAEJ,OAAO,EAAE,GAAMA,OAAAA,GAAU,IAAI,GAAK,CAAA;;;AAGjC,iBAAA,EAAE,CAAC,EAAEC,KAAK,EAAE,GAAKA,KAAAA,CAAMI,YAAY,CAAC;;;;;;;AAO5C,SAAA,EAAEtG,cAAe,CAAA;;AAE1B,CAAC;AAED,MAAM6F,WAAc,GAAA,CAAC,EACnBzD,WAAW,EACXE,QAAQ,EACRC,SAAS,EACTC,IAAI,EACJ0B,UAAU,EACVzB,cAAc,EACG,GAAA;AACjB,IAAA,MAAMc,mBAAmBf,IAAS,KAAA,YAAA;IAElC,MAAM,CAAC,EAAE+D,MAAM,EAAE,EAAEC,IAAK,CAAA,GAAGC,gBACzB,CAAA,KAAO;YACLC,MAAQ,EAAA,QAAA;AACRF,YAAAA,IAAAA,EAAM,CAACG,IAAAA,GAAAA;AACLzC,gBAAAA,UAAAA,CAAWyC,IAAKC,CAAAA,EAAE,EAAExE,WAAAA,EAAaK,cAAgBc,EAAAA,gBAAAA,CAAAA;AACnD,aAAA;YACAsD,OAAS,EAAA,CAACC,WAAa;AACrBP,oBAAAA,MAAAA,EAAQO,QAAQP,MAAM;iBACxB;AACF,SAAA,CACA,EAAA;AAACnE,QAAAA,WAAAA;AAAamB,QAAAA,gBAAAA;AAAkBW,QAAAA,UAAAA;AAAYzB,QAAAA;AAAe,KAAA,CAAA;AAG7D,IAAA,IAAI,CAACF,SAAW,EAAA;QACd,OAAO,IAAA;AACT;AAEA,IAAA,qBACEqD,cAACE,CAAAA,oBAAAA,EAAAA;QACCiB,GAAKP,EAAAA,IAAAA;QACLP,OAASM,EAAAA,MAAAA;QACTS,KAAO,EAAA;AACLC,YAAAA,SAAAA,EAAW,CAAC,UAAU,EAAE3E,QAAAA,CAASR,IAAI,CAAC,IAAI,EAAEQ,QAASlB,CAAAA,GAAG,CAAC,GAAG,CAAC;AAC7DF,YAAAA,MAAAA,EAAQ,CAAC,EAAEoB,QAAAA,CAASpB,MAAM,CAAC,EAAE,CAAC;AAC9Ba,YAAAA,KAAAA,EAAO,CAAC,EAAEO,QAAAA,CAASP,KAAK,CAAC,EAAE;AAC7B;;AAGN,CAAA;;;;;;;"}