@btst/stack 1.10.0 → 1.11.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/packages/ui/src/components/minimal-tiptap/utils.cjs +15 -11
- package/dist/packages/ui/src/components/minimal-tiptap/utils.mjs +15 -11
- package/dist/packages/ui/src/components/ui-builder/index.cjs +9 -7
- package/dist/packages/ui/src/components/ui-builder/index.mjs +9 -7
- package/dist/packages/ui/src/components/ui-builder/internal/canvas/auto-frame.cjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/canvas/auto-frame.mjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/components/add-component-popover.cjs +228 -48
- package/dist/packages/ui/src/components/ui-builder/internal/components/add-component-popover.mjs +228 -48
- package/dist/packages/ui/src/components/ui-builder/internal/components/element-selector.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/components/element-selector.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/components/error-fallback.cjs +4 -2
- package/dist/packages/ui/src/components/ui-builder/internal/components/error-fallback.mjs +4 -2
- package/dist/packages/ui/src/components/ui-builder/internal/components/multi-select.cjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/components/multi-select.mjs +6 -3
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/draggable-new-component.cjs +67 -0
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/draggable-new-component.mjs +62 -0
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/drop-zone.cjs +181 -37
- package/dist/packages/ui/src/components/ui-builder/internal/dnd/drop-zone.mjs +181 -38
- package/dist/packages/ui/src/components/ui-builder/internal/editor-panel.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/editor-panel.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-group-control.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-group-control.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-item-control.cjs +9 -2
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/classname-control/classname-item-control.mjs +9 -2
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/iconname-field.cjs +3 -2
- package/dist/packages/ui/src/components/ui-builder/internal/form-fields/iconname-field.mjs +3 -2
- package/dist/packages/ui/src/components/ui-builder/internal/layers-panel.cjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/layers-panel.mjs +1 -1
- package/dist/packages/ui/src/components/ui-builder/internal/props-panel.cjs +17 -5
- package/dist/packages/ui/src/components/ui-builder/internal/props-panel.mjs +17 -5
- package/dist/packages/ui/src/components/ui-builder/internal/utils/render-utils.cjs +70 -16
- package/dist/packages/ui/src/components/ui-builder/internal/utils/render-utils.mjs +73 -20
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context-colission-utils.cjs +14 -9
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context-colission-utils.mjs +14 -9
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context.cjs +38 -10
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-context.mjs +35 -11
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-contexts.cjs +1 -0
- package/dist/packages/ui/src/lib/ui-builder/context/dnd-contexts.mjs +1 -0
- package/dist/packages/ui/src/lib/ui-builder/context/drag-overlay.cjs +7 -4
- package/dist/packages/ui/src/lib/ui-builder/context/drag-overlay.mjs +7 -4
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-auto-scroll.cjs +4 -4
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-auto-scroll.mjs +4 -4
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-dnd-event-handlers.cjs +53 -16
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-dnd-event-handlers.mjs +53 -16
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-drop-validation.cjs +23 -7
- package/dist/packages/ui/src/lib/ui-builder/hooks/use-drop-validation.mjs +23 -7
- package/dist/packages/ui/src/lib/ui-builder/registry/form-field-overrides.cjs +110 -11
- package/dist/packages/ui/src/lib/ui-builder/registry/form-field-overrides.mjs +111 -13
- package/dist/packages/ui/src/lib/ui-builder/store/editor-store.cjs +3 -2
- package/dist/packages/ui/src/lib/ui-builder/store/editor-store.mjs +3 -2
- package/dist/packages/ui/src/lib/ui-builder/store/layer-store.cjs +53 -7
- package/dist/packages/ui/src/lib/ui-builder/store/layer-store.mjs +54 -8
- package/dist/packages/ui/src/lib/ui-builder/store/layer-utils.cjs +4 -3
- package/dist/packages/ui/src/lib/ui-builder/store/layer-utils.mjs +4 -3
- package/dist/packages/ui/src/lib/ui-builder/utils/variable-resolver.cjs +12 -0
- package/dist/packages/ui/src/lib/ui-builder/utils/variable-resolver.mjs +12 -1
- package/dist/plugins/ui-builder/client/components/index.d.cts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.mts +1 -1
- package/dist/plugins/ui-builder/client/components/index.d.ts +1 -1
- package/dist/plugins/ui-builder/client/hooks/index.d.cts +2 -2
- package/dist/plugins/ui-builder/client/hooks/index.d.mts +2 -2
- package/dist/plugins/ui-builder/client/hooks/index.d.ts +2 -2
- package/dist/plugins/ui-builder/client/index.d.cts +17 -7
- package/dist/plugins/ui-builder/client/index.d.mts +17 -7
- package/dist/plugins/ui-builder/client/index.d.ts +17 -7
- package/dist/plugins/ui-builder/index.d.cts +2 -2
- package/dist/plugins/ui-builder/index.d.mts +2 -2
- package/dist/plugins/ui-builder/index.d.ts +2 -2
- package/dist/shared/{stack.BSM2cgoq.d.cts → stack.BYysGdHl.d.cts} +1 -1
- package/dist/shared/{stack.CqfZWfjJ.d.cts → stack.BdJFrdyt.d.cts} +8 -2
- package/dist/shared/{stack.e1FN86dE.d.mts → stack.ChVuHi5e.d.mts} +8 -2
- package/dist/shared/{stack.CLtOoAqF.d.mts → stack.DYCFcnkL.d.mts} +1 -1
- package/dist/shared/{stack.MMntCVZZ.d.ts → stack.EhM4pmtN.d.ts} +8 -2
- package/dist/shared/{stack.BD1m-4yB.d.ts → stack.kFbDspnF.d.ts} +1 -1
- package/package.json +1 -1
|
@@ -23,6 +23,8 @@ const DROP_INDICATOR_HOVER = "before:bg-blue-500 before:shadow-xl";
|
|
|
23
23
|
const DROP_INDICATOR_DEFAULT = "before:bg-blue-400/50";
|
|
24
24
|
const DROP_INDICATOR_INLINE_HOVER = "before:bg-blue-500 before:shadow-lg";
|
|
25
25
|
const DROP_INDICATOR_INLINE_DEFAULT = "before:bg-blue-400/40";
|
|
26
|
+
const DROP_INDICATOR_DISABLED = "before:bg-gray-400/30";
|
|
27
|
+
const DROP_INDICATOR_DISABLED_HOVER = "before:bg-gray-500/40";
|
|
26
28
|
function getLayoutType(element) {
|
|
27
29
|
const styles = window.getComputedStyle(element);
|
|
28
30
|
const display = styles.display;
|
|
@@ -59,6 +61,11 @@ const DropPlaceholder = ({
|
|
|
59
61
|
isActive = false,
|
|
60
62
|
style
|
|
61
63
|
}) => {
|
|
64
|
+
const [layoutType, setLayoutType] = React__default.useState("block");
|
|
65
|
+
const [calculatedStyle, setCalculatedStyle] = React__default.useState(null);
|
|
66
|
+
const [element, setElement] = React__default.useState(null);
|
|
67
|
+
const dndContext = dndContexts.useDndContext();
|
|
68
|
+
const isDropValid = dndContext.canDropOnLayer(parentId);
|
|
62
69
|
const {
|
|
63
70
|
isOver,
|
|
64
71
|
setNodeRef
|
|
@@ -68,31 +75,113 @@ const DropPlaceholder = ({
|
|
|
68
75
|
type: "drop-zone",
|
|
69
76
|
parentId,
|
|
70
77
|
position
|
|
71
|
-
}
|
|
78
|
+
},
|
|
79
|
+
// Disable the droppable when drop is not valid (e.g., childOf constraint violation)
|
|
80
|
+
disabled: !isDropValid
|
|
72
81
|
});
|
|
73
|
-
const [layoutType, setLayoutType] = React__default.useState("block");
|
|
74
|
-
const [element, setElement] = React__default.useState(null);
|
|
75
|
-
const dndContext = dndContexts.useDndContext();
|
|
76
82
|
React__default.useLayoutEffect(() => {
|
|
77
83
|
if (!isActive || !element) return;
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
84
|
+
const parentContainer = element.closest(`[data-layer-id="${parentId}"]`);
|
|
85
|
+
if (!parentContainer) return;
|
|
86
|
+
let detectedLayout = getLayoutType(parentContainer);
|
|
87
|
+
if (dndContext?.activeLayerId) {
|
|
88
|
+
const draggedElement = document.querySelector(`[data-layer-id="${dndContext.activeLayerId}"]`);
|
|
89
|
+
if (draggedElement) {
|
|
90
|
+
const draggedTagName = draggedElement.tagName.toLowerCase();
|
|
91
|
+
const draggedDisplay = window.getComputedStyle(draggedElement).display;
|
|
92
|
+
const isInlineElement = draggedDisplay === "inline" || draggedDisplay === "inline-block" || ["span", "a", "strong", "em", "code", "small", "mark", "del", "ins", "sub", "sup"].includes(draggedTagName);
|
|
93
|
+
if (isInlineElement && detectedLayout === "block") {
|
|
94
|
+
detectedLayout = "inline";
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
setLayoutType(detectedLayout);
|
|
99
|
+
const nextSibling = element.nextElementSibling;
|
|
100
|
+
let siblingElement = null;
|
|
101
|
+
if (nextSibling) {
|
|
102
|
+
if (nextSibling.hasAttribute("data-layer-id")) {
|
|
103
|
+
siblingElement = nextSibling;
|
|
104
|
+
} else {
|
|
105
|
+
siblingElement = nextSibling.querySelector("[data-layer-id]");
|
|
106
|
+
}
|
|
81
107
|
}
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
108
|
+
const parentRect = parentContainer.getBoundingClientRect();
|
|
109
|
+
if (siblingElement) {
|
|
110
|
+
const siblingRect = siblingElement.getBoundingClientRect();
|
|
111
|
+
const positionStyle = {
|
|
112
|
+
position: "absolute",
|
|
113
|
+
pointerEvents: "auto",
|
|
114
|
+
zIndex: 999
|
|
115
|
+
};
|
|
116
|
+
if (detectedLayout === "flex-row") {
|
|
117
|
+
positionStyle.left = siblingRect.left - parentRect.left - 4;
|
|
118
|
+
positionStyle.top = siblingRect.top - parentRect.top;
|
|
119
|
+
positionStyle.width = 8;
|
|
120
|
+
positionStyle.height = siblingRect.height;
|
|
121
|
+
} else if (detectedLayout === "inline") {
|
|
122
|
+
positionStyle.left = siblingRect.left - parentRect.left - 3;
|
|
123
|
+
positionStyle.top = siblingRect.top - parentRect.top;
|
|
124
|
+
positionStyle.width = 6;
|
|
125
|
+
positionStyle.height = siblingRect.height;
|
|
126
|
+
} else if (detectedLayout === "grid") {
|
|
127
|
+
positionStyle.left = siblingRect.left - parentRect.left - 4;
|
|
128
|
+
positionStyle.top = siblingRect.top - parentRect.top - 4;
|
|
129
|
+
positionStyle.width = 8;
|
|
130
|
+
positionStyle.height = 8;
|
|
131
|
+
} else {
|
|
132
|
+
positionStyle.left = siblingRect.left - parentRect.left;
|
|
133
|
+
positionStyle.top = siblingRect.top - parentRect.top - 4;
|
|
134
|
+
positionStyle.width = siblingRect.width;
|
|
135
|
+
positionStyle.height = 8;
|
|
136
|
+
}
|
|
137
|
+
setCalculatedStyle(positionStyle);
|
|
138
|
+
} else {
|
|
139
|
+
const childLayers = parentContainer.querySelectorAll("[data-layer-id]");
|
|
140
|
+
const directChildLayers = Array.from(childLayers).filter((el) => {
|
|
141
|
+
const closestLayerParent = el.parentElement?.closest("[data-layer-id]");
|
|
142
|
+
return closestLayerParent === parentContainer || closestLayerParent === null;
|
|
143
|
+
});
|
|
144
|
+
const lastChild = directChildLayers[directChildLayers.length - 1];
|
|
145
|
+
if (lastChild) {
|
|
146
|
+
const lastChildRect = lastChild.getBoundingClientRect();
|
|
147
|
+
const positionStyle = {
|
|
148
|
+
position: "absolute",
|
|
149
|
+
pointerEvents: "auto",
|
|
150
|
+
zIndex: 999
|
|
151
|
+
};
|
|
152
|
+
if (detectedLayout === "flex-row") {
|
|
153
|
+
positionStyle.left = lastChildRect.right - parentRect.left - 4;
|
|
154
|
+
positionStyle.top = lastChildRect.top - parentRect.top;
|
|
155
|
+
positionStyle.width = 8;
|
|
156
|
+
positionStyle.height = lastChildRect.height;
|
|
157
|
+
} else if (detectedLayout === "inline") {
|
|
158
|
+
positionStyle.left = lastChildRect.right - parentRect.left - 3;
|
|
159
|
+
positionStyle.top = lastChildRect.top - parentRect.top;
|
|
160
|
+
positionStyle.width = 6;
|
|
161
|
+
positionStyle.height = lastChildRect.height;
|
|
162
|
+
} else if (detectedLayout === "grid") {
|
|
163
|
+
positionStyle.left = lastChildRect.right - parentRect.left - 4;
|
|
164
|
+
positionStyle.top = lastChildRect.top - parentRect.top - 4;
|
|
165
|
+
positionStyle.width = 8;
|
|
166
|
+
positionStyle.height = 8;
|
|
167
|
+
} else {
|
|
168
|
+
positionStyle.left = lastChildRect.left - parentRect.left;
|
|
169
|
+
positionStyle.top = lastChildRect.bottom - parentRect.top - 4;
|
|
170
|
+
positionStyle.width = lastChildRect.width;
|
|
171
|
+
positionStyle.height = 8;
|
|
93
172
|
}
|
|
173
|
+
setCalculatedStyle(positionStyle);
|
|
174
|
+
} else {
|
|
175
|
+
setCalculatedStyle({
|
|
176
|
+
position: "absolute",
|
|
177
|
+
pointerEvents: "auto",
|
|
178
|
+
zIndex: 999,
|
|
179
|
+
left: 0,
|
|
180
|
+
top: 0,
|
|
181
|
+
right: 0,
|
|
182
|
+
height: 8
|
|
183
|
+
});
|
|
94
184
|
}
|
|
95
|
-
setLayoutType(detectedLayout);
|
|
96
185
|
}
|
|
97
186
|
}, [isActive, element, parentId, position, dndContext?.activeLayerId]);
|
|
98
187
|
const combinedRef = React__default.useCallback((node) => {
|
|
@@ -100,57 +189,112 @@ const DropPlaceholder = ({
|
|
|
100
189
|
setNodeRef(node);
|
|
101
190
|
}, [setNodeRef]);
|
|
102
191
|
if (!isActive) return null;
|
|
192
|
+
const useCalculatedPositioning = calculatedStyle !== null;
|
|
193
|
+
const getIndicatorStyles = (baseHover, baseDefault) => {
|
|
194
|
+
if (!isDropValid) {
|
|
195
|
+
return isOver ? DROP_INDICATOR_DISABLED_HOVER : DROP_INDICATOR_DISABLED;
|
|
196
|
+
}
|
|
197
|
+
return isOver ? baseHover : baseDefault;
|
|
198
|
+
};
|
|
103
199
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
104
200
|
"div",
|
|
105
201
|
{
|
|
106
202
|
ref: combinedRef,
|
|
107
203
|
className: utils.cn(
|
|
204
|
+
// Always apply absolute positioning base classes
|
|
108
205
|
"absolute pointer-events-auto z-[999]",
|
|
109
206
|
"before:content-[''] before:absolute",
|
|
110
207
|
BEFORE_TRANSITION,
|
|
111
208
|
"before:pointer-events-none",
|
|
112
|
-
//
|
|
113
|
-
!
|
|
114
|
-
|
|
209
|
+
// Disabled state visual cue
|
|
210
|
+
!isDropValid && "opacity-60 cursor-not-allowed",
|
|
211
|
+
// Fallback positioning classes when calculatedStyle is not available
|
|
212
|
+
!useCalculatedPositioning && !style && [
|
|
213
|
+
// Flex-row layout: vertical lines on left edge
|
|
115
214
|
layoutType === "flex-row" && [
|
|
116
|
-
"-left-
|
|
215
|
+
"-left-1 top-0 bottom-0 w-2",
|
|
117
216
|
BEFORE_CENTER_TRANSFORM,
|
|
118
217
|
"before:w-1 before:h-8",
|
|
119
|
-
|
|
218
|
+
getIndicatorStyles(
|
|
219
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:w-2 before:h-16`,
|
|
220
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:w-1 before:h-6`
|
|
221
|
+
)
|
|
120
222
|
],
|
|
121
|
-
// Inline layout: subtle vertical indicators
|
|
223
|
+
// Inline layout: subtle vertical indicators
|
|
122
224
|
layoutType === "inline" && [
|
|
123
|
-
"-left-
|
|
225
|
+
"-left-1 top-0 bottom-0 w-2",
|
|
124
226
|
BEFORE_CENTER_TRANSFORM,
|
|
125
227
|
"before:w-0.5 before:h-4",
|
|
126
|
-
|
|
228
|
+
getIndicatorStyles(
|
|
229
|
+
`${DROP_INDICATOR_INLINE_HOVER} ${BEFORE_ROUNDED_HOVER} before:w-1 before:h-8`,
|
|
230
|
+
`${DROP_INDICATOR_INLINE_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:w-0.5 before:h-3`
|
|
231
|
+
)
|
|
127
232
|
],
|
|
128
|
-
// Vertical layout (flex-col, block): horizontal lines on
|
|
233
|
+
// Vertical layout (flex-col, block): horizontal lines on top edge
|
|
129
234
|
(layoutType === "flex-col" || layoutType === "block") && [
|
|
130
|
-
"left-0 right-0 -top-
|
|
235
|
+
"left-0 right-0 -top-1 h-2",
|
|
131
236
|
BEFORE_CENTER_TRANSFORM,
|
|
132
237
|
"before:h-1 before:w-8",
|
|
133
|
-
|
|
238
|
+
getIndicatorStyles(
|
|
239
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:h-2 before:w-16`,
|
|
240
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:h-1 before:w-6`
|
|
241
|
+
)
|
|
134
242
|
],
|
|
135
243
|
// Grid layout: corner indicator
|
|
136
244
|
layoutType === "grid" && [
|
|
137
|
-
"-left-
|
|
245
|
+
"-left-1 -top-1 w-2 h-2",
|
|
138
246
|
BEFORE_CENTER_TRANSFORM,
|
|
139
247
|
"before:h-2 before:w-2",
|
|
140
|
-
|
|
248
|
+
getIndicatorStyles(
|
|
249
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:h-4 before:w-4`,
|
|
250
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:h-2 before:w-2`
|
|
251
|
+
)
|
|
252
|
+
]
|
|
253
|
+
],
|
|
254
|
+
// When using calculated positioning, only apply visual indicator classes
|
|
255
|
+
useCalculatedPositioning && [
|
|
256
|
+
BEFORE_CENTER_TRANSFORM,
|
|
257
|
+
layoutType === "flex-row" && [
|
|
258
|
+
"before:w-1 before:h-8",
|
|
259
|
+
getIndicatorStyles(
|
|
260
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:w-2 before:h-16`,
|
|
261
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
262
|
+
)
|
|
263
|
+
],
|
|
264
|
+
layoutType === "inline" && [
|
|
265
|
+
"before:w-0.5 before:h-4",
|
|
266
|
+
getIndicatorStyles(
|
|
267
|
+
`${DROP_INDICATOR_INLINE_HOVER} ${BEFORE_ROUNDED_HOVER}`,
|
|
268
|
+
`${DROP_INDICATOR_INLINE_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
269
|
+
)
|
|
270
|
+
],
|
|
271
|
+
(layoutType === "flex-col" || layoutType === "block") && [
|
|
272
|
+
"before:h-1 before:w-8",
|
|
273
|
+
getIndicatorStyles(
|
|
274
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:h-2 before:w-16`,
|
|
275
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
276
|
+
)
|
|
277
|
+
],
|
|
278
|
+
layoutType === "grid" && [
|
|
279
|
+
"before:h-2 before:w-2",
|
|
280
|
+
getIndicatorStyles(
|
|
281
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER}`,
|
|
282
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
283
|
+
)
|
|
141
284
|
]
|
|
142
285
|
],
|
|
143
|
-
// Custom style overrides
|
|
286
|
+
// Custom style overrides
|
|
144
287
|
style && [
|
|
145
|
-
"before:bg-blue-500/60 before:rounded-sm",
|
|
146
|
-
isOver && "before:bg-blue-600 before:shadow-md"
|
|
288
|
+
isDropValid ? ["before:bg-blue-500/60 before:rounded-sm", isOver && "before:bg-blue-600 before:shadow-md"] : ["before:bg-gray-400/30 before:rounded-sm", isOver && "before:bg-gray-500/40"]
|
|
147
289
|
]
|
|
148
290
|
),
|
|
149
|
-
style,
|
|
291
|
+
style: useCalculatedPositioning ? calculatedStyle : style,
|
|
150
292
|
"data-testid": `drop-placeholder-${parentId}-${position}`,
|
|
151
|
-
"data-drop-indicator": true
|
|
293
|
+
"data-drop-indicator": true,
|
|
294
|
+
"data-drop-valid": isDropValid
|
|
152
295
|
}
|
|
153
296
|
);
|
|
154
297
|
};
|
|
155
298
|
|
|
156
299
|
exports.DropPlaceholder = DropPlaceholder;
|
|
300
|
+
exports.getLayoutType = getLayoutType;
|
|
@@ -17,6 +17,8 @@ const DROP_INDICATOR_HOVER = "before:bg-blue-500 before:shadow-xl";
|
|
|
17
17
|
const DROP_INDICATOR_DEFAULT = "before:bg-blue-400/50";
|
|
18
18
|
const DROP_INDICATOR_INLINE_HOVER = "before:bg-blue-500 before:shadow-lg";
|
|
19
19
|
const DROP_INDICATOR_INLINE_DEFAULT = "before:bg-blue-400/40";
|
|
20
|
+
const DROP_INDICATOR_DISABLED = "before:bg-gray-400/30";
|
|
21
|
+
const DROP_INDICATOR_DISABLED_HOVER = "before:bg-gray-500/40";
|
|
20
22
|
function getLayoutType(element) {
|
|
21
23
|
const styles = window.getComputedStyle(element);
|
|
22
24
|
const display = styles.display;
|
|
@@ -53,6 +55,11 @@ const DropPlaceholder = ({
|
|
|
53
55
|
isActive = false,
|
|
54
56
|
style
|
|
55
57
|
}) => {
|
|
58
|
+
const [layoutType, setLayoutType] = React__default.useState("block");
|
|
59
|
+
const [calculatedStyle, setCalculatedStyle] = React__default.useState(null);
|
|
60
|
+
const [element, setElement] = React__default.useState(null);
|
|
61
|
+
const dndContext = useDndContext();
|
|
62
|
+
const isDropValid = dndContext.canDropOnLayer(parentId);
|
|
56
63
|
const {
|
|
57
64
|
isOver,
|
|
58
65
|
setNodeRef
|
|
@@ -62,31 +69,113 @@ const DropPlaceholder = ({
|
|
|
62
69
|
type: "drop-zone",
|
|
63
70
|
parentId,
|
|
64
71
|
position
|
|
65
|
-
}
|
|
72
|
+
},
|
|
73
|
+
// Disable the droppable when drop is not valid (e.g., childOf constraint violation)
|
|
74
|
+
disabled: !isDropValid
|
|
66
75
|
});
|
|
67
|
-
const [layoutType, setLayoutType] = React__default.useState("block");
|
|
68
|
-
const [element, setElement] = React__default.useState(null);
|
|
69
|
-
const dndContext = useDndContext();
|
|
70
76
|
React__default.useLayoutEffect(() => {
|
|
71
77
|
if (!isActive || !element) return;
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
78
|
+
const parentContainer = element.closest(`[data-layer-id="${parentId}"]`);
|
|
79
|
+
if (!parentContainer) return;
|
|
80
|
+
let detectedLayout = getLayoutType(parentContainer);
|
|
81
|
+
if (dndContext?.activeLayerId) {
|
|
82
|
+
const draggedElement = document.querySelector(`[data-layer-id="${dndContext.activeLayerId}"]`);
|
|
83
|
+
if (draggedElement) {
|
|
84
|
+
const draggedTagName = draggedElement.tagName.toLowerCase();
|
|
85
|
+
const draggedDisplay = window.getComputedStyle(draggedElement).display;
|
|
86
|
+
const isInlineElement = draggedDisplay === "inline" || draggedDisplay === "inline-block" || ["span", "a", "strong", "em", "code", "small", "mark", "del", "ins", "sub", "sup"].includes(draggedTagName);
|
|
87
|
+
if (isInlineElement && detectedLayout === "block") {
|
|
88
|
+
detectedLayout = "inline";
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
setLayoutType(detectedLayout);
|
|
93
|
+
const nextSibling = element.nextElementSibling;
|
|
94
|
+
let siblingElement = null;
|
|
95
|
+
if (nextSibling) {
|
|
96
|
+
if (nextSibling.hasAttribute("data-layer-id")) {
|
|
97
|
+
siblingElement = nextSibling;
|
|
98
|
+
} else {
|
|
99
|
+
siblingElement = nextSibling.querySelector("[data-layer-id]");
|
|
100
|
+
}
|
|
75
101
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
102
|
+
const parentRect = parentContainer.getBoundingClientRect();
|
|
103
|
+
if (siblingElement) {
|
|
104
|
+
const siblingRect = siblingElement.getBoundingClientRect();
|
|
105
|
+
const positionStyle = {
|
|
106
|
+
position: "absolute",
|
|
107
|
+
pointerEvents: "auto",
|
|
108
|
+
zIndex: 999
|
|
109
|
+
};
|
|
110
|
+
if (detectedLayout === "flex-row") {
|
|
111
|
+
positionStyle.left = siblingRect.left - parentRect.left - 4;
|
|
112
|
+
positionStyle.top = siblingRect.top - parentRect.top;
|
|
113
|
+
positionStyle.width = 8;
|
|
114
|
+
positionStyle.height = siblingRect.height;
|
|
115
|
+
} else if (detectedLayout === "inline") {
|
|
116
|
+
positionStyle.left = siblingRect.left - parentRect.left - 3;
|
|
117
|
+
positionStyle.top = siblingRect.top - parentRect.top;
|
|
118
|
+
positionStyle.width = 6;
|
|
119
|
+
positionStyle.height = siblingRect.height;
|
|
120
|
+
} else if (detectedLayout === "grid") {
|
|
121
|
+
positionStyle.left = siblingRect.left - parentRect.left - 4;
|
|
122
|
+
positionStyle.top = siblingRect.top - parentRect.top - 4;
|
|
123
|
+
positionStyle.width = 8;
|
|
124
|
+
positionStyle.height = 8;
|
|
125
|
+
} else {
|
|
126
|
+
positionStyle.left = siblingRect.left - parentRect.left;
|
|
127
|
+
positionStyle.top = siblingRect.top - parentRect.top - 4;
|
|
128
|
+
positionStyle.width = siblingRect.width;
|
|
129
|
+
positionStyle.height = 8;
|
|
130
|
+
}
|
|
131
|
+
setCalculatedStyle(positionStyle);
|
|
132
|
+
} else {
|
|
133
|
+
const childLayers = parentContainer.querySelectorAll("[data-layer-id]");
|
|
134
|
+
const directChildLayers = Array.from(childLayers).filter((el) => {
|
|
135
|
+
const closestLayerParent = el.parentElement?.closest("[data-layer-id]");
|
|
136
|
+
return closestLayerParent === parentContainer || closestLayerParent === null;
|
|
137
|
+
});
|
|
138
|
+
const lastChild = directChildLayers[directChildLayers.length - 1];
|
|
139
|
+
if (lastChild) {
|
|
140
|
+
const lastChildRect = lastChild.getBoundingClientRect();
|
|
141
|
+
const positionStyle = {
|
|
142
|
+
position: "absolute",
|
|
143
|
+
pointerEvents: "auto",
|
|
144
|
+
zIndex: 999
|
|
145
|
+
};
|
|
146
|
+
if (detectedLayout === "flex-row") {
|
|
147
|
+
positionStyle.left = lastChildRect.right - parentRect.left - 4;
|
|
148
|
+
positionStyle.top = lastChildRect.top - parentRect.top;
|
|
149
|
+
positionStyle.width = 8;
|
|
150
|
+
positionStyle.height = lastChildRect.height;
|
|
151
|
+
} else if (detectedLayout === "inline") {
|
|
152
|
+
positionStyle.left = lastChildRect.right - parentRect.left - 3;
|
|
153
|
+
positionStyle.top = lastChildRect.top - parentRect.top;
|
|
154
|
+
positionStyle.width = 6;
|
|
155
|
+
positionStyle.height = lastChildRect.height;
|
|
156
|
+
} else if (detectedLayout === "grid") {
|
|
157
|
+
positionStyle.left = lastChildRect.right - parentRect.left - 4;
|
|
158
|
+
positionStyle.top = lastChildRect.top - parentRect.top - 4;
|
|
159
|
+
positionStyle.width = 8;
|
|
160
|
+
positionStyle.height = 8;
|
|
161
|
+
} else {
|
|
162
|
+
positionStyle.left = lastChildRect.left - parentRect.left;
|
|
163
|
+
positionStyle.top = lastChildRect.bottom - parentRect.top - 4;
|
|
164
|
+
positionStyle.width = lastChildRect.width;
|
|
165
|
+
positionStyle.height = 8;
|
|
87
166
|
}
|
|
167
|
+
setCalculatedStyle(positionStyle);
|
|
168
|
+
} else {
|
|
169
|
+
setCalculatedStyle({
|
|
170
|
+
position: "absolute",
|
|
171
|
+
pointerEvents: "auto",
|
|
172
|
+
zIndex: 999,
|
|
173
|
+
left: 0,
|
|
174
|
+
top: 0,
|
|
175
|
+
right: 0,
|
|
176
|
+
height: 8
|
|
177
|
+
});
|
|
88
178
|
}
|
|
89
|
-
setLayoutType(detectedLayout);
|
|
90
179
|
}
|
|
91
180
|
}, [isActive, element, parentId, position, dndContext?.activeLayerId]);
|
|
92
181
|
const combinedRef = React__default.useCallback((node) => {
|
|
@@ -94,57 +183,111 @@ const DropPlaceholder = ({
|
|
|
94
183
|
setNodeRef(node);
|
|
95
184
|
}, [setNodeRef]);
|
|
96
185
|
if (!isActive) return null;
|
|
186
|
+
const useCalculatedPositioning = calculatedStyle !== null;
|
|
187
|
+
const getIndicatorStyles = (baseHover, baseDefault) => {
|
|
188
|
+
if (!isDropValid) {
|
|
189
|
+
return isOver ? DROP_INDICATOR_DISABLED_HOVER : DROP_INDICATOR_DISABLED;
|
|
190
|
+
}
|
|
191
|
+
return isOver ? baseHover : baseDefault;
|
|
192
|
+
};
|
|
97
193
|
return /* @__PURE__ */ jsx(
|
|
98
194
|
"div",
|
|
99
195
|
{
|
|
100
196
|
ref: combinedRef,
|
|
101
197
|
className: cn(
|
|
198
|
+
// Always apply absolute positioning base classes
|
|
102
199
|
"absolute pointer-events-auto z-[999]",
|
|
103
200
|
"before:content-[''] before:absolute",
|
|
104
201
|
BEFORE_TRANSITION,
|
|
105
202
|
"before:pointer-events-none",
|
|
106
|
-
//
|
|
107
|
-
!
|
|
108
|
-
|
|
203
|
+
// Disabled state visual cue
|
|
204
|
+
!isDropValid && "opacity-60 cursor-not-allowed",
|
|
205
|
+
// Fallback positioning classes when calculatedStyle is not available
|
|
206
|
+
!useCalculatedPositioning && !style && [
|
|
207
|
+
// Flex-row layout: vertical lines on left edge
|
|
109
208
|
layoutType === "flex-row" && [
|
|
110
|
-
"-left-
|
|
209
|
+
"-left-1 top-0 bottom-0 w-2",
|
|
111
210
|
BEFORE_CENTER_TRANSFORM,
|
|
112
211
|
"before:w-1 before:h-8",
|
|
113
|
-
|
|
212
|
+
getIndicatorStyles(
|
|
213
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:w-2 before:h-16`,
|
|
214
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:w-1 before:h-6`
|
|
215
|
+
)
|
|
114
216
|
],
|
|
115
|
-
// Inline layout: subtle vertical indicators
|
|
217
|
+
// Inline layout: subtle vertical indicators
|
|
116
218
|
layoutType === "inline" && [
|
|
117
|
-
"-left-
|
|
219
|
+
"-left-1 top-0 bottom-0 w-2",
|
|
118
220
|
BEFORE_CENTER_TRANSFORM,
|
|
119
221
|
"before:w-0.5 before:h-4",
|
|
120
|
-
|
|
222
|
+
getIndicatorStyles(
|
|
223
|
+
`${DROP_INDICATOR_INLINE_HOVER} ${BEFORE_ROUNDED_HOVER} before:w-1 before:h-8`,
|
|
224
|
+
`${DROP_INDICATOR_INLINE_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:w-0.5 before:h-3`
|
|
225
|
+
)
|
|
121
226
|
],
|
|
122
|
-
// Vertical layout (flex-col, block): horizontal lines on
|
|
227
|
+
// Vertical layout (flex-col, block): horizontal lines on top edge
|
|
123
228
|
(layoutType === "flex-col" || layoutType === "block") && [
|
|
124
|
-
"left-0 right-0 -top-
|
|
229
|
+
"left-0 right-0 -top-1 h-2",
|
|
125
230
|
BEFORE_CENTER_TRANSFORM,
|
|
126
231
|
"before:h-1 before:w-8",
|
|
127
|
-
|
|
232
|
+
getIndicatorStyles(
|
|
233
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:h-2 before:w-16`,
|
|
234
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:h-1 before:w-6`
|
|
235
|
+
)
|
|
128
236
|
],
|
|
129
237
|
// Grid layout: corner indicator
|
|
130
238
|
layoutType === "grid" && [
|
|
131
|
-
"-left-
|
|
239
|
+
"-left-1 -top-1 w-2 h-2",
|
|
132
240
|
BEFORE_CENTER_TRANSFORM,
|
|
133
241
|
"before:h-2 before:w-2",
|
|
134
|
-
|
|
242
|
+
getIndicatorStyles(
|
|
243
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:h-4 before:w-4`,
|
|
244
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT} before:h-2 before:w-2`
|
|
245
|
+
)
|
|
246
|
+
]
|
|
247
|
+
],
|
|
248
|
+
// When using calculated positioning, only apply visual indicator classes
|
|
249
|
+
useCalculatedPositioning && [
|
|
250
|
+
BEFORE_CENTER_TRANSFORM,
|
|
251
|
+
layoutType === "flex-row" && [
|
|
252
|
+
"before:w-1 before:h-8",
|
|
253
|
+
getIndicatorStyles(
|
|
254
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:w-2 before:h-16`,
|
|
255
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
256
|
+
)
|
|
257
|
+
],
|
|
258
|
+
layoutType === "inline" && [
|
|
259
|
+
"before:w-0.5 before:h-4",
|
|
260
|
+
getIndicatorStyles(
|
|
261
|
+
`${DROP_INDICATOR_INLINE_HOVER} ${BEFORE_ROUNDED_HOVER}`,
|
|
262
|
+
`${DROP_INDICATOR_INLINE_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
263
|
+
)
|
|
264
|
+
],
|
|
265
|
+
(layoutType === "flex-col" || layoutType === "block") && [
|
|
266
|
+
"before:h-1 before:w-8",
|
|
267
|
+
getIndicatorStyles(
|
|
268
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER} before:h-2 before:w-16`,
|
|
269
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
270
|
+
)
|
|
271
|
+
],
|
|
272
|
+
layoutType === "grid" && [
|
|
273
|
+
"before:h-2 before:w-2",
|
|
274
|
+
getIndicatorStyles(
|
|
275
|
+
`${DROP_INDICATOR_HOVER} ${BEFORE_ROUNDED_HOVER}`,
|
|
276
|
+
`${DROP_INDICATOR_DEFAULT} ${BEFORE_ROUNDED_DEFAULT}`
|
|
277
|
+
)
|
|
135
278
|
]
|
|
136
279
|
],
|
|
137
|
-
// Custom style overrides
|
|
280
|
+
// Custom style overrides
|
|
138
281
|
style && [
|
|
139
|
-
"before:bg-blue-500/60 before:rounded-sm",
|
|
140
|
-
isOver && "before:bg-blue-600 before:shadow-md"
|
|
282
|
+
isDropValid ? ["before:bg-blue-500/60 before:rounded-sm", isOver && "before:bg-blue-600 before:shadow-md"] : ["before:bg-gray-400/30 before:rounded-sm", isOver && "before:bg-gray-500/40"]
|
|
141
283
|
]
|
|
142
284
|
),
|
|
143
|
-
style,
|
|
285
|
+
style: useCalculatedPositioning ? calculatedStyle : style,
|
|
144
286
|
"data-testid": `drop-placeholder-${parentId}-${position}`,
|
|
145
|
-
"data-drop-indicator": true
|
|
287
|
+
"data-drop-indicator": true,
|
|
288
|
+
"data-drop-valid": isDropValid
|
|
146
289
|
}
|
|
147
290
|
);
|
|
148
291
|
};
|
|
149
292
|
|
|
150
|
-
export { DropPlaceholder };
|
|
293
|
+
export { DropPlaceholder, getLayoutType };
|
|
@@ -338,7 +338,7 @@ const EditorPanelContent = ({
|
|
|
338
338
|
]
|
|
339
339
|
}
|
|
340
340
|
),
|
|
341
|
-
/* @__PURE__ */ jsxRuntime.jsx(addComponentPopover.AddComponentsPopover, { parentLayerId: selectedPageId, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
341
|
+
/* @__PURE__ */ jsxRuntime.jsx(addComponentPopover.AddComponentsPopover, { parentLayerId: selectedPageId, enableDragToCanvas: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
342
342
|
button.Button,
|
|
343
343
|
{
|
|
344
344
|
variant: "secondary",
|
|
@@ -336,7 +336,7 @@ const EditorPanelContent = ({
|
|
|
336
336
|
]
|
|
337
337
|
}
|
|
338
338
|
),
|
|
339
|
-
/* @__PURE__ */ jsx(AddComponentsPopover, { parentLayerId: selectedPageId, children: /* @__PURE__ */ jsx(
|
|
339
|
+
/* @__PURE__ */ jsx(AddComponentsPopover, { parentLayerId: selectedPageId, enableDragToCanvas: true, children: /* @__PURE__ */ jsx(
|
|
340
340
|
Button,
|
|
341
341
|
{
|
|
342
342
|
variant: "secondary",
|
|
@@ -48,7 +48,7 @@ function ClassNameGroupControl({
|
|
|
48
48
|
{
|
|
49
49
|
onClick: handleDropdownClick(String(key)),
|
|
50
50
|
className: selectedKey === String(key) ? "bg-secondary-foreground/10" : "",
|
|
51
|
-
children: config.CONFIG[String(key)]
|
|
51
|
+
children: config.CONFIG[String(key)]?.label || String(key)
|
|
52
52
|
},
|
|
53
53
|
String(key)
|
|
54
54
|
)) })
|
|
@@ -46,7 +46,7 @@ function ClassNameGroupControl({
|
|
|
46
46
|
{
|
|
47
47
|
onClick: handleDropdownClick(String(key)),
|
|
48
48
|
className: selectedKey === String(key) ? "bg-secondary-foreground/10" : "",
|
|
49
|
-
children: CONFIG[String(key)]
|
|
49
|
+
children: CONFIG[String(key)]?.label || String(key)
|
|
50
50
|
},
|
|
51
51
|
String(key)
|
|
52
52
|
)) })
|
|
@@ -34,7 +34,9 @@ function ClassNameItemControl({ value, onChange }) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
});
|
|
37
|
-
if (!found
|
|
37
|
+
if (!found && group.keys[0]) {
|
|
38
|
+
initialSelected[group.label] = group.keys[0];
|
|
39
|
+
}
|
|
38
40
|
});
|
|
39
41
|
const handledTokens = new Set(
|
|
40
42
|
Object.values(parsedState).flatMap(
|
|
@@ -52,7 +54,9 @@ function ClassNameItemControl({ value, onChange }) {
|
|
|
52
54
|
} else {
|
|
53
55
|
const initialSelected = {};
|
|
54
56
|
config.LAYOUT_GROUPS.forEach((group) => {
|
|
55
|
-
|
|
57
|
+
if (group.keys[0]) {
|
|
58
|
+
initialSelected[group.label] = group.keys[0];
|
|
59
|
+
}
|
|
56
60
|
});
|
|
57
61
|
return {
|
|
58
62
|
parsedState: {},
|
|
@@ -174,7 +178,9 @@ function ClassNameItemControl({ value, onChange }) {
|
|
|
174
178
|
const keys = group.keys.map(String);
|
|
175
179
|
const selectedKey = selectedKeys[group.label] || keys[0];
|
|
176
180
|
if (entry.isVisible && !entry.isVisible(state)) return null;
|
|
181
|
+
if (!selectedKey) return null;
|
|
177
182
|
const groupConfig = config.CONFIG[selectedKey];
|
|
183
|
+
if (!groupConfig) return null;
|
|
178
184
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils.cn("w-full", entry.className), "data-testid": `group-${group.label.toLowerCase().replace(/\s+/g, "-")}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
179
185
|
classnameGroupControl.ClassNameGroupControl,
|
|
180
186
|
{
|
|
@@ -190,6 +196,7 @@ function ClassNameItemControl({ value, onChange }) {
|
|
|
190
196
|
if (entry.isVisible && !entry.isVisible(state)) return null;
|
|
191
197
|
const configKey = entry.key;
|
|
192
198
|
const ungroupedConfig = config.CONFIG[configKey];
|
|
199
|
+
if (!ungroupedConfig) return null;
|
|
193
200
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: utils.cn("w-full", entry.className), "data-testid": `item-${configKey}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
194
201
|
ungroupedConfig.component,
|
|
195
202
|
{
|