@archie/devtools 0.0.44 → 0.0.45
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/client/client.js +291 -189
- package/dist/client/client.mjs +291 -189
- package/package.json +1 -1
package/dist/client/client.mjs
CHANGED
|
@@ -581,44 +581,6 @@ function getFirstCollision(collisions, property) {
|
|
|
581
581
|
const [firstCollision] = collisions;
|
|
582
582
|
return property ? firstCollision[property] : firstCollision;
|
|
583
583
|
}
|
|
584
|
-
function centerOfRectangle(rect, left, top) {
|
|
585
|
-
if (left === void 0) {
|
|
586
|
-
left = rect.left;
|
|
587
|
-
}
|
|
588
|
-
if (top === void 0) {
|
|
589
|
-
top = rect.top;
|
|
590
|
-
}
|
|
591
|
-
return {
|
|
592
|
-
x: left + rect.width * 0.5,
|
|
593
|
-
y: top + rect.height * 0.5
|
|
594
|
-
};
|
|
595
|
-
}
|
|
596
|
-
var closestCenter = (_ref) => {
|
|
597
|
-
let {
|
|
598
|
-
collisionRect,
|
|
599
|
-
droppableRects,
|
|
600
|
-
droppableContainers
|
|
601
|
-
} = _ref;
|
|
602
|
-
const centerRect = centerOfRectangle(collisionRect, collisionRect.left, collisionRect.top);
|
|
603
|
-
const collisions = [];
|
|
604
|
-
for (const droppableContainer of droppableContainers) {
|
|
605
|
-
const {
|
|
606
|
-
id
|
|
607
|
-
} = droppableContainer;
|
|
608
|
-
const rect = droppableRects.get(id);
|
|
609
|
-
if (rect) {
|
|
610
|
-
const distBetween = distanceBetween(centerOfRectangle(rect), centerRect);
|
|
611
|
-
collisions.push({
|
|
612
|
-
id,
|
|
613
|
-
data: {
|
|
614
|
-
droppableContainer,
|
|
615
|
-
value: distBetween
|
|
616
|
-
}
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
}
|
|
620
|
-
return collisions.sort(sortCollisionsAsc);
|
|
621
|
-
};
|
|
622
584
|
var closestCorners = (_ref) => {
|
|
623
585
|
let {
|
|
624
586
|
collisionRect,
|
|
@@ -5547,6 +5509,7 @@ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
|
5547
5509
|
var HANDLES = ["nw", "n", "ne", "e", "se", "s", "sw", "w"];
|
|
5548
5510
|
var HANDLE_HIT_SIZE = 24;
|
|
5549
5511
|
var HANDLE_KNOB_SIZE = 8;
|
|
5512
|
+
var EMPTY_SCROLL_DELTA = { x: NaN, y: NaN };
|
|
5550
5513
|
var OVERLAY_ROOT_STYLE = {
|
|
5551
5514
|
position: "fixed",
|
|
5552
5515
|
inset: 0,
|
|
@@ -5620,17 +5583,39 @@ function handlePosition(dir) {
|
|
|
5620
5583
|
};
|
|
5621
5584
|
return positions[dir];
|
|
5622
5585
|
}
|
|
5623
|
-
function
|
|
5586
|
+
function getSelectedOutlineStyle(rect, inspectorTheme) {
|
|
5624
5587
|
return {
|
|
5625
5588
|
...OUTLINE_BASE_STYLE,
|
|
5626
5589
|
left: rect.left,
|
|
5627
5590
|
top: rect.top,
|
|
5628
5591
|
width: rect.width,
|
|
5629
5592
|
height: rect.height,
|
|
5630
|
-
border:
|
|
5631
|
-
backgroundColor:
|
|
5593
|
+
border: `2px solid ${inspectorTheme.accent}`,
|
|
5594
|
+
backgroundColor: inspectorTheme.accentSoft
|
|
5632
5595
|
};
|
|
5633
5596
|
}
|
|
5597
|
+
function getGuideOutlineStyle(rect, tier, inspectorTheme) {
|
|
5598
|
+
const base = {
|
|
5599
|
+
...OUTLINE_BASE_STYLE,
|
|
5600
|
+
left: rect.left,
|
|
5601
|
+
top: rect.top,
|
|
5602
|
+
width: rect.width,
|
|
5603
|
+
height: rect.height
|
|
5604
|
+
};
|
|
5605
|
+
switch (tier) {
|
|
5606
|
+
case "candidate":
|
|
5607
|
+
return { ...base, border: `1px solid ${inspectorTheme.accent}`, opacity: 0.2 };
|
|
5608
|
+
case "lane-child":
|
|
5609
|
+
return { ...base, border: `1px dashed ${inspectorTheme.accent}`, opacity: 0.45 };
|
|
5610
|
+
case "lane":
|
|
5611
|
+
return {
|
|
5612
|
+
...base,
|
|
5613
|
+
border: `1.5px solid ${inspectorTheme.accent}`,
|
|
5614
|
+
backgroundColor: inspectorTheme.accentSoft,
|
|
5615
|
+
opacity: 0.75
|
|
5616
|
+
};
|
|
5617
|
+
}
|
|
5618
|
+
}
|
|
5634
5619
|
function getResizeHandleStyle(position) {
|
|
5635
5620
|
return {
|
|
5636
5621
|
...RESIZE_HANDLE_BASE_STYLE,
|
|
@@ -5653,40 +5638,58 @@ function getLabelStyle(labelLeft, labelTop, labelColor) {
|
|
|
5653
5638
|
backgroundColor: labelColor
|
|
5654
5639
|
};
|
|
5655
5640
|
}
|
|
5641
|
+
function projectDragRect(dragGuide, nodeId, sdx, sdy) {
|
|
5642
|
+
const r = dragGuide.rects.get(nodeId);
|
|
5643
|
+
if (!r) return null;
|
|
5644
|
+
return { left: r.left - sdx, top: r.top - sdy, width: r.width, height: r.height };
|
|
5645
|
+
}
|
|
5656
5646
|
function ElementHighlight({
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
activeEl,
|
|
5660
|
-
arrangeSelectedNodeId,
|
|
5647
|
+
selected,
|
|
5648
|
+
dragGuide,
|
|
5661
5649
|
externalDragActive,
|
|
5662
5650
|
onResizeHandlePointerDown
|
|
5663
5651
|
}) {
|
|
5664
5652
|
const inspectorTheme = useDesignModeStore((s) => s.inspectorTheme);
|
|
5665
|
-
const internalDragInProgress = draggingNodeId !== null;
|
|
5666
|
-
const overlayVisible = arrangeSelectedNodeId !== null || internalDragInProgress;
|
|
5667
5653
|
const containerRef = useRef5(null);
|
|
5668
5654
|
const rafRef = useRef5(0);
|
|
5655
|
+
const lastScrollDeltaRef = useRef5(EMPTY_SCROLL_DELTA);
|
|
5669
5656
|
const syncPositions = useCallback5(() => {
|
|
5670
5657
|
const container = containerRef.current;
|
|
5671
5658
|
if (!container) return;
|
|
5672
|
-
|
|
5673
|
-
|
|
5674
|
-
const
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
const
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
label.style.left = `${rect.left}px`;
|
|
5685
|
-
label.style.top = `${rect.top}px`;
|
|
5659
|
+
if (dragGuide) {
|
|
5660
|
+
const sdx = window.scrollX - dragGuide.startScroll.x;
|
|
5661
|
+
const sdy = window.scrollY - dragGuide.startScroll.y;
|
|
5662
|
+
if (sdx === lastScrollDeltaRef.current.x && sdy === lastScrollDeltaRef.current.y) return;
|
|
5663
|
+
lastScrollDeltaRef.current = { x: sdx, y: sdy };
|
|
5664
|
+
const outlines = container.querySelectorAll("[data-guide-for]");
|
|
5665
|
+
for (const outline2 of outlines) {
|
|
5666
|
+
const nodeId = outline2.getAttribute("data-guide-for");
|
|
5667
|
+
const r = dragGuide.rects.get(nodeId);
|
|
5668
|
+
if (!r) continue;
|
|
5669
|
+
outline2.style.left = `${r.left - sdx}px`;
|
|
5670
|
+
outline2.style.top = `${r.top - sdy}px`;
|
|
5686
5671
|
}
|
|
5672
|
+
return;
|
|
5687
5673
|
}
|
|
5688
|
-
|
|
5674
|
+
if (!selected) return;
|
|
5675
|
+
const rect2 = selected.element.getBoundingClientRect();
|
|
5676
|
+
const outline = container.querySelector("[data-outline-for]");
|
|
5677
|
+
if (outline) {
|
|
5678
|
+
outline.style.left = `${rect2.left}px`;
|
|
5679
|
+
outline.style.top = `${rect2.top}px`;
|
|
5680
|
+
outline.style.width = `${rect2.width}px`;
|
|
5681
|
+
outline.style.height = `${rect2.height}px`;
|
|
5682
|
+
}
|
|
5683
|
+
const label = container.querySelector("[data-drag-handle]");
|
|
5684
|
+
if (label) {
|
|
5685
|
+
label.style.left = `${rect2.left + 12}px`;
|
|
5686
|
+
label.style.top = `${Math.max(0, rect2.top - 20)}px`;
|
|
5687
|
+
}
|
|
5688
|
+
}, [dragGuide, selected]);
|
|
5689
|
+
const loopActive = !externalDragActive && (dragGuide !== null || selected !== null);
|
|
5689
5690
|
useEffect5(() => {
|
|
5691
|
+
if (!loopActive) return;
|
|
5692
|
+
lastScrollDeltaRef.current = EMPTY_SCROLL_DELTA;
|
|
5690
5693
|
let running = true;
|
|
5691
5694
|
const loop = () => {
|
|
5692
5695
|
if (!running) return;
|
|
@@ -5698,81 +5701,113 @@ function ElementHighlight({
|
|
|
5698
5701
|
running = false;
|
|
5699
5702
|
cancelAnimationFrame(rafRef.current);
|
|
5700
5703
|
};
|
|
5701
|
-
}, [syncPositions]);
|
|
5702
|
-
if (!
|
|
5703
|
-
if (
|
|
5704
|
-
|
|
5705
|
-
|
|
5706
|
-
{
|
|
5707
|
-
|
|
5708
|
-
|
|
5709
|
-
|
|
5710
|
-
|
|
5711
|
-
if (
|
|
5712
|
-
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5739
|
-
|
|
5740
|
-
|
|
5741
|
-
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5704
|
+
}, [loopActive, syncPositions]);
|
|
5705
|
+
if (!loopActive) return null;
|
|
5706
|
+
if (dragGuide) {
|
|
5707
|
+
const sdx = window.scrollX - dragGuide.startScroll.x;
|
|
5708
|
+
const sdy = window.scrollY - dragGuide.startScroll.y;
|
|
5709
|
+
const { candidateContainerIds, activeContainerId, activeChildIds, draggingNodeId } = dragGuide;
|
|
5710
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, "data-design-mode-ui": true, style: OVERLAY_ROOT_STYLE, children: [
|
|
5711
|
+
[...candidateContainerIds].map((id) => {
|
|
5712
|
+
if (id === activeContainerId || id === draggingNodeId) return null;
|
|
5713
|
+
const rect2 = projectDragRect(dragGuide, id, sdx, sdy);
|
|
5714
|
+
if (!rect2) return null;
|
|
5715
|
+
return /* @__PURE__ */ jsx2(
|
|
5716
|
+
"div",
|
|
5717
|
+
{
|
|
5718
|
+
"data-guide-for": id,
|
|
5719
|
+
"data-guide-tier": "candidate",
|
|
5720
|
+
"data-design-mode-ui": true,
|
|
5721
|
+
style: getGuideOutlineStyle(rect2, "candidate", inspectorTheme)
|
|
5722
|
+
},
|
|
5723
|
+
`candidate:${id}`
|
|
5724
|
+
);
|
|
5725
|
+
}),
|
|
5726
|
+
activeContainerId !== null && activeChildIds.map((id) => {
|
|
5727
|
+
if (id === draggingNodeId) return null;
|
|
5728
|
+
const rect2 = projectDragRect(dragGuide, id, sdx, sdy);
|
|
5729
|
+
if (!rect2) return null;
|
|
5730
|
+
return /* @__PURE__ */ jsx2(
|
|
5731
|
+
"div",
|
|
5732
|
+
{
|
|
5733
|
+
"data-guide-for": id,
|
|
5734
|
+
"data-guide-tier": "lane-child",
|
|
5735
|
+
"data-design-mode-ui": true,
|
|
5736
|
+
style: getGuideOutlineStyle(rect2, "lane-child", inspectorTheme)
|
|
5737
|
+
},
|
|
5738
|
+
`lane-child:${id}`
|
|
5739
|
+
);
|
|
5740
|
+
}),
|
|
5741
|
+
activeContainerId !== null && activeContainerId !== draggingNodeId && (() => {
|
|
5742
|
+
const rect2 = projectDragRect(dragGuide, activeContainerId, sdx, sdy);
|
|
5743
|
+
if (!rect2) return null;
|
|
5744
|
+
return /* @__PURE__ */ jsx2(
|
|
5745
|
+
"div",
|
|
5746
|
+
{
|
|
5747
|
+
"data-guide-for": activeContainerId,
|
|
5748
|
+
"data-guide-tier": "lane",
|
|
5749
|
+
"data-design-mode-ui": true,
|
|
5750
|
+
style: getGuideOutlineStyle(rect2, "lane", inspectorTheme)
|
|
5751
|
+
},
|
|
5752
|
+
`lane:${activeContainerId}`
|
|
5753
|
+
);
|
|
5754
|
+
})()
|
|
5755
|
+
] });
|
|
5756
|
+
}
|
|
5757
|
+
if (!selected) return null;
|
|
5758
|
+
const rect = selected.element.getBoundingClientRect();
|
|
5759
|
+
const labelTop = Math.max(0, rect.top - 20);
|
|
5760
|
+
const labelLeft = rect.left + 12;
|
|
5761
|
+
return /* @__PURE__ */ jsxs("div", { ref: containerRef, "data-design-mode-ui": true, style: OVERLAY_ROOT_STYLE, children: [
|
|
5762
|
+
/* @__PURE__ */ jsx2(
|
|
5763
|
+
"div",
|
|
5764
|
+
{
|
|
5765
|
+
"data-outline-for": selected.nodeId,
|
|
5766
|
+
"data-design-mode-ui": true,
|
|
5767
|
+
style: getSelectedOutlineStyle(rect, inspectorTheme),
|
|
5768
|
+
children: selected.draggable && HANDLES.map((dir) => {
|
|
5769
|
+
const pos = handlePosition(dir);
|
|
5770
|
+
return /* @__PURE__ */ jsx2(
|
|
5752
5771
|
"div",
|
|
5753
5772
|
{
|
|
5754
5773
|
"data-design-mode-ui": true,
|
|
5755
|
-
"data-
|
|
5756
|
-
|
|
5757
|
-
|
|
5758
|
-
|
|
5759
|
-
|
|
5760
|
-
),
|
|
5761
|
-
children:
|
|
5762
|
-
|
|
5763
|
-
|
|
5764
|
-
|
|
5765
|
-
|
|
5766
|
-
|
|
5767
|
-
|
|
5768
|
-
|
|
5769
|
-
|
|
5770
|
-
|
|
5771
|
-
|
|
5772
|
-
|
|
5773
|
-
|
|
5774
|
-
|
|
5775
|
-
|
|
5774
|
+
"data-resize-handle": dir,
|
|
5775
|
+
onPointerDown: (e) => {
|
|
5776
|
+
e.stopPropagation();
|
|
5777
|
+
onResizeHandlePointerDown?.(e, selected.nodeId, dir);
|
|
5778
|
+
},
|
|
5779
|
+
style: getResizeHandleStyle(pos),
|
|
5780
|
+
children: /* @__PURE__ */ jsx2(
|
|
5781
|
+
"span",
|
|
5782
|
+
{
|
|
5783
|
+
"data-design-mode-ui": true,
|
|
5784
|
+
style: getResizeKnobStyle(inspectorTheme.accent)
|
|
5785
|
+
}
|
|
5786
|
+
)
|
|
5787
|
+
},
|
|
5788
|
+
dir
|
|
5789
|
+
);
|
|
5790
|
+
})
|
|
5791
|
+
}
|
|
5792
|
+
),
|
|
5793
|
+
/* @__PURE__ */ jsxs(
|
|
5794
|
+
"div",
|
|
5795
|
+
{
|
|
5796
|
+
"data-design-mode-ui": true,
|
|
5797
|
+
"data-drag-handle": selected.nodeId,
|
|
5798
|
+
style: getLabelStyle(labelLeft, labelTop, inspectorTheme.accent),
|
|
5799
|
+
children: [
|
|
5800
|
+
/* @__PURE__ */ jsx2("span", { style: LABEL_ICON_STYLE, children: "\u283F" }),
|
|
5801
|
+
selected.label,
|
|
5802
|
+
/* @__PURE__ */ jsxs("span", { style: LABEL_DIMENSIONS_STYLE, children: [
|
|
5803
|
+
Math.round(rect.width),
|
|
5804
|
+
"\xD7",
|
|
5805
|
+
Math.round(rect.height)
|
|
5806
|
+
] })
|
|
5807
|
+
]
|
|
5808
|
+
}
|
|
5809
|
+
)
|
|
5810
|
+
] });
|
|
5776
5811
|
}
|
|
5777
5812
|
|
|
5778
5813
|
// src/client/dnd/design-mode/projection.ts
|
|
@@ -6566,30 +6601,6 @@ function applyDndCommandPlacement(command, direction, resolveNodeElement) {
|
|
|
6566
6601
|
return true;
|
|
6567
6602
|
}
|
|
6568
6603
|
|
|
6569
|
-
// src/client/dnd/design-mode/design-mode-collision.ts
|
|
6570
|
-
function filterDroppables(droppableContainers, blockedContainerIds) {
|
|
6571
|
-
if (!blockedContainerIds || blockedContainerIds.size === 0) return droppableContainers;
|
|
6572
|
-
return droppableContainers.filter((container) => !blockedContainerIds.has(String(container.id)));
|
|
6573
|
-
}
|
|
6574
|
-
function getCollisions(detector, args) {
|
|
6575
|
-
return detector(args);
|
|
6576
|
-
}
|
|
6577
|
-
function createDesignModeCollisionDetection(blockedContainerIds) {
|
|
6578
|
-
return (args) => {
|
|
6579
|
-
const droppableContainers = filterDroppables(args.droppableContainers, blockedContainerIds);
|
|
6580
|
-
if (droppableContainers.length === 0) return [];
|
|
6581
|
-
const scopedArgs = {
|
|
6582
|
-
...args,
|
|
6583
|
-
droppableContainers
|
|
6584
|
-
};
|
|
6585
|
-
const pointerHits = getCollisions(pointerWithin, scopedArgs);
|
|
6586
|
-
if (pointerHits.length > 0) return pointerHits;
|
|
6587
|
-
const cornerHits = getCollisions(closestCorners, scopedArgs);
|
|
6588
|
-
if (cornerHits.length > 0) return cornerHits;
|
|
6589
|
-
return getCollisions(closestCenter, scopedArgs);
|
|
6590
|
-
};
|
|
6591
|
-
}
|
|
6592
|
-
|
|
6593
6604
|
// src/client/dnd/design-mode/arrange-session.ts
|
|
6594
6605
|
function serializeArrangeChange(event, index) {
|
|
6595
6606
|
return {
|
|
@@ -6868,9 +6879,9 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
|
|
|
6868
6879
|
const lastIntentRef = useRef8(null);
|
|
6869
6880
|
const visualIntentRef = useRef8(null);
|
|
6870
6881
|
const sourceContainerIdRef = useRef8(null);
|
|
6882
|
+
const activeLaneContainerIdRef = useRef8(null);
|
|
6871
6883
|
const rowLockedRef = useRef8(false);
|
|
6872
6884
|
const dragSessionAnchorRef = useRef8(null);
|
|
6873
|
-
const lockRef = useRef8({ containerId: null, isCrossUnlocked: false, exitSince: null, unlockUntilTs: null });
|
|
6874
6885
|
const targetPlaneRef = useRef8("lane");
|
|
6875
6886
|
const nestCandidateRef = useRef8(null);
|
|
6876
6887
|
const nestTargetRef = useRef8(null);
|
|
@@ -6880,7 +6891,6 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
|
|
|
6880
6891
|
const sourceCommitLaneRef = useRef8(null);
|
|
6881
6892
|
const commitLaneCacheRef = useRef8(/* @__PURE__ */ new Map());
|
|
6882
6893
|
const safeZoneRef = useRef8(null);
|
|
6883
|
-
const blockedContainerIdsRef = useRef8(/* @__PURE__ */ new Set());
|
|
6884
6894
|
const historyRef = useRef8(new DndCommandHistory());
|
|
6885
6895
|
const processedUndoIdRef = useRef8(undoRequestId);
|
|
6886
6896
|
const processedRedoIdRef = useRef8(redoRequestId);
|
|
@@ -6900,9 +6910,9 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
|
|
|
6900
6910
|
lastIntentRef,
|
|
6901
6911
|
visualIntentRef,
|
|
6902
6912
|
sourceContainerIdRef,
|
|
6913
|
+
activeLaneContainerIdRef,
|
|
6903
6914
|
rowLockedRef,
|
|
6904
6915
|
dragSessionAnchorRef,
|
|
6905
|
-
lockRef,
|
|
6906
6916
|
targetPlaneRef,
|
|
6907
6917
|
nestCandidateRef,
|
|
6908
6918
|
nestTargetRef,
|
|
@@ -6912,7 +6922,6 @@ function useOverlayRefs(undoRequestId, redoRequestId) {
|
|
|
6912
6922
|
sourceCommitLaneRef,
|
|
6913
6923
|
commitLaneCacheRef,
|
|
6914
6924
|
safeZoneRef,
|
|
6915
|
-
blockedContainerIdsRef,
|
|
6916
6925
|
historyRef,
|
|
6917
6926
|
processedUndoIdRef,
|
|
6918
6927
|
processedRedoIdRef,
|
|
@@ -7180,6 +7189,11 @@ function pointInRect(px, py, r) {
|
|
|
7180
7189
|
function pointInExpandedRect(px, py, r, inset) {
|
|
7181
7190
|
return px >= r.left - inset && px <= r.right + inset && py >= r.top - inset && py <= r.bottom + inset;
|
|
7182
7191
|
}
|
|
7192
|
+
function isInNestZone(px, py, rect) {
|
|
7193
|
+
const relX = (px - rect.left) / rect.width;
|
|
7194
|
+
const relY = (py - rect.top) / rect.height;
|
|
7195
|
+
return relX > NEST_EDGE_FRACTION && relX < 1 - NEST_EDGE_FRACTION && relY > NEST_EDGE_FRACTION && relY < 1 - NEST_EDGE_FRACTION;
|
|
7196
|
+
}
|
|
7183
7197
|
function buildSlotQuadtree(slotIndex) {
|
|
7184
7198
|
const rects = /* @__PURE__ */ new Map();
|
|
7185
7199
|
for (const [id, slot] of slotIndex) {
|
|
@@ -7222,6 +7236,11 @@ var DragIntentEngine = class {
|
|
|
7222
7236
|
__publicField(this, "laneAllowedContainers");
|
|
7223
7237
|
__publicField(this, "blockedContainerIds");
|
|
7224
7238
|
__publicField(this, "targetPlane", "lane");
|
|
7239
|
+
// Memoized result of getValidDropContainerIds(). Safe to cache because every
|
|
7240
|
+
// input it reads (containerIndex, slotIndex, activeId, laneAllowedContainers,
|
|
7241
|
+
// blockedContainerIds) is fixed in the constructor and never mutated during
|
|
7242
|
+
// a drag.
|
|
7243
|
+
__publicField(this, "validDropContainerIds", null);
|
|
7225
7244
|
this.projectionTree = projection.projectionTree;
|
|
7226
7245
|
this.containerIndex = projection.containerIndex;
|
|
7227
7246
|
this.slotIndex = projection.slotIndex;
|
|
@@ -7258,6 +7277,44 @@ var DragIntentEngine = class {
|
|
|
7258
7277
|
getContainerChildren(containerId) {
|
|
7259
7278
|
return this.containerIndex.get(containerId)?.children ?? [];
|
|
7260
7279
|
}
|
|
7280
|
+
/**
|
|
7281
|
+
* Every container id this engine would accept as a drop target for the
|
|
7282
|
+
* active node, at the current pointer position or any other — i.e. the
|
|
7283
|
+
* full set `resolvePointerContainer` draws from, not a snapshot of one
|
|
7284
|
+
* resolve() call. Intended for the visual layer to draw a guide that
|
|
7285
|
+
* matches exactly what the engine can land on, without re-deriving the
|
|
7286
|
+
* eligibility rule itself.
|
|
7287
|
+
*
|
|
7288
|
+
* Always queries with `laneLock: true`. That is not an approximation of
|
|
7289
|
+
* the "real" default — it IS the real answer for every reachable caller:
|
|
7290
|
+
*
|
|
7291
|
+
* - With a row lock active (`laneAllowedContainers` set), `isLaneContainer`
|
|
7292
|
+
* restricts eligibility to that set, so this returns exactly
|
|
7293
|
+
* `{srcContainerId}` — the ARCH-1071 lock, reproduced faithfully.
|
|
7294
|
+
* - Without a row lock, `laneAllowedContainers` is null and
|
|
7295
|
+
* `isLaneContainer` returns true unconditionally, so `laneLock`'s value
|
|
7296
|
+
* makes no difference — passing `true` costs nothing here.
|
|
7297
|
+
* - The engine's own 'nest' plane does call `isEligibleDropContainer` with
|
|
7298
|
+
* `laneLock: false` (see `peekNestIntent` → `resolvePointerContainer`),
|
|
7299
|
+
* but that plane is unreachable for a locked drag: `computeAllowNest`
|
|
7300
|
+
* (useDragVisualLoop.ts) short-circuits `rowLocked` drags before
|
|
7301
|
+
* `setTargetPlane('nest')` is ever called, so `targetPlane` stays
|
|
7302
|
+
* 'lane' for the drag's whole lifetime. If that guard is ever removed,
|
|
7303
|
+
* this method will under-report nest-only targets for locked drags —
|
|
7304
|
+
* keep the two in sync.
|
|
7305
|
+
*
|
|
7306
|
+
* Cached after the first call: every input (containerIndex, slotIndex,
|
|
7307
|
+
* activeId, laneAllowedContainers, blockedContainerIds) is fixed at
|
|
7308
|
+
* construction and never changes for the life of a drag.
|
|
7309
|
+
*/
|
|
7310
|
+
getValidDropContainerIds() {
|
|
7311
|
+
if (this.validDropContainerIds) return this.validDropContainerIds;
|
|
7312
|
+
const ids2 = /* @__PURE__ */ new Set();
|
|
7313
|
+
for (const id of this.containerIndex.keys()) {
|
|
7314
|
+
if (this.isEligibleDropContainer(id, true)) ids2.add(id);
|
|
7315
|
+
}
|
|
7316
|
+
return this.validDropContainerIds = ids2;
|
|
7317
|
+
}
|
|
7261
7318
|
setTargetPlane(plane) {
|
|
7262
7319
|
this.targetPlane = plane;
|
|
7263
7320
|
}
|
|
@@ -7276,6 +7333,17 @@ var DragIntentEngine = class {
|
|
|
7276
7333
|
isInvalidDropContainer(containerId) {
|
|
7277
7334
|
return containerId === this.activeId || this.isContainerDescendantOf(containerId, this.activeId);
|
|
7278
7335
|
}
|
|
7336
|
+
/**
|
|
7337
|
+
* The full "can this container accept the active node this drag" predicate.
|
|
7338
|
+
* SINGLE definition — every caller routes through it so no two parts of the
|
|
7339
|
+
* system can disagree about which containers are droppable.
|
|
7340
|
+
*/
|
|
7341
|
+
isEligibleDropContainer(containerId, laneLock) {
|
|
7342
|
+
if (this.isInvalidDropContainer(containerId)) return false;
|
|
7343
|
+
if (this.isBlockedContainer(containerId)) return false;
|
|
7344
|
+
if (laneLock && !this.isLaneContainer(containerId)) return false;
|
|
7345
|
+
return this.hasUsableSlots(containerId);
|
|
7346
|
+
}
|
|
7279
7347
|
/**
|
|
7280
7348
|
* Resolve the drag intent from the current pointer position.
|
|
7281
7349
|
*
|
|
@@ -7363,9 +7431,7 @@ var DragIntentEngine = class {
|
|
|
7363
7431
|
const childNode = this.getNodeRect(childId);
|
|
7364
7432
|
if (!childNode) continue;
|
|
7365
7433
|
if (!pointInRect(px, py, childNode)) continue;
|
|
7366
|
-
|
|
7367
|
-
const relY = (py - childNode.top) / childNode.height;
|
|
7368
|
-
if (relX > NEST_EDGE_FRACTION && relX < 1 - NEST_EDGE_FRACTION && relY > NEST_EDGE_FRACTION && relY < 1 - NEST_EDGE_FRACTION) {
|
|
7434
|
+
if (isInNestZone(px, py, childNode)) {
|
|
7369
7435
|
return {
|
|
7370
7436
|
containerId: pointerContainerId,
|
|
7371
7437
|
index: container.children.indexOf(childId),
|
|
@@ -7379,11 +7445,8 @@ var DragIntentEngine = class {
|
|
|
7379
7445
|
resolvePointerContainer(px, py, laneLock) {
|
|
7380
7446
|
const pointerContainers = [];
|
|
7381
7447
|
for (const [id, node] of this.containerIndex) {
|
|
7382
|
-
if (this.isInvalidDropContainer(id)) continue;
|
|
7383
|
-
if (this.isBlockedContainer(id)) continue;
|
|
7384
|
-
if (laneLock && !this.isLaneContainer(id)) continue;
|
|
7385
7448
|
if (!pointInRect(px, py, node.rect)) continue;
|
|
7386
|
-
if (this.
|
|
7449
|
+
if (!this.isEligibleDropContainer(id, laneLock)) continue;
|
|
7387
7450
|
const r = node.rect;
|
|
7388
7451
|
const edgeDistX = Math.min(px - r.left, r.right - px);
|
|
7389
7452
|
const edgeDistY = Math.min(py - r.top, r.bottom - py);
|
|
@@ -7400,11 +7463,11 @@ var DragIntentEngine = class {
|
|
|
7400
7463
|
let pointerContainerId = pointerContainers[0]?.id ?? null;
|
|
7401
7464
|
if (!pointerContainerId && this.lastIntent?.mode === "reorder") {
|
|
7402
7465
|
const lastContainer = this.containerIndex.get(this.lastIntent.containerId);
|
|
7403
|
-
if (lastContainer &&
|
|
7466
|
+
if (lastContainer && this.isEligibleDropContainer(lastContainer.id, laneLock) && pointInExpandedRect(px, py, lastContainer.rect, LAST_CONTAINER_REENTRY_SLOP_PX)) {
|
|
7404
7467
|
pointerContainerId = lastContainer.id;
|
|
7405
7468
|
}
|
|
7406
7469
|
}
|
|
7407
|
-
if (this.originContainerId && this.originContainerId !== pointerContainerId &&
|
|
7470
|
+
if (this.originContainerId && this.originContainerId !== pointerContainerId && this.isEligibleDropContainer(this.originContainerId, laneLock)) {
|
|
7408
7471
|
const originNode = this.containerIndex.get(this.originContainerId);
|
|
7409
7472
|
const currentNode = pointerContainerId ? this.containerIndex.get(pointerContainerId) : null;
|
|
7410
7473
|
const originIsDeeper = originNode && (!currentNode || originNode.depth >= currentNode.depth);
|
|
@@ -7817,7 +7880,8 @@ function useDragVisualLoop({
|
|
|
7817
7880
|
refs,
|
|
7818
7881
|
getCommitLaneSnapshot,
|
|
7819
7882
|
setInsideRect,
|
|
7820
|
-
setDropLine
|
|
7883
|
+
setDropLine,
|
|
7884
|
+
setActiveLaneContainerId
|
|
7821
7885
|
}) {
|
|
7822
7886
|
useEffect8(() => {
|
|
7823
7887
|
const engine = refs.engineRef.current;
|
|
@@ -7825,6 +7889,11 @@ function useDragVisualLoop({
|
|
|
7825
7889
|
if (!activeDrag || !engine || !snapshot) return;
|
|
7826
7890
|
let rafId;
|
|
7827
7891
|
const animator = refs.animatorRef.current;
|
|
7892
|
+
const publishActiveLane = (containerId) => {
|
|
7893
|
+
if (refs.activeLaneContainerIdRef.current === containerId) return;
|
|
7894
|
+
refs.activeLaneContainerIdRef.current = containerId;
|
|
7895
|
+
setActiveLaneContainerId(containerId);
|
|
7896
|
+
};
|
|
7828
7897
|
const setTargetPlane = (nextPlane) => {
|
|
7829
7898
|
const prevPlane = refs.targetPlaneRef.current;
|
|
7830
7899
|
if (prevPlane === nextPlane) return;
|
|
@@ -7843,6 +7912,7 @@ function useDragVisualLoop({
|
|
|
7843
7912
|
const safeZone = refs.safeZoneRef.current;
|
|
7844
7913
|
if (isPointerBlocked(px, py, safeZone)) {
|
|
7845
7914
|
setTargetPlane("lane");
|
|
7915
|
+
publishActiveLane(null);
|
|
7846
7916
|
refs.lastIntentRef.current = null;
|
|
7847
7917
|
refs.visualIntentRef.current = null;
|
|
7848
7918
|
refs.nestCandidateRef.current = null;
|
|
@@ -7884,6 +7954,7 @@ function useDragVisualLoop({
|
|
|
7884
7954
|
let intent = engine.resolve(px, py, window.scrollX, window.scrollY, snapshot.scroll.x, snapshot.scroll.y);
|
|
7885
7955
|
if (!intent) {
|
|
7886
7956
|
setTargetPlane("lane");
|
|
7957
|
+
publishActiveLane(null);
|
|
7887
7958
|
refs.lastIntentRef.current = null;
|
|
7888
7959
|
refs.visualIntentRef.current = null;
|
|
7889
7960
|
refs.nestCandidateRef.current = null;
|
|
@@ -7909,6 +7980,7 @@ function useDragVisualLoop({
|
|
|
7909
7980
|
const targetId = intent.slotId.split("::nest::")[1] ?? "";
|
|
7910
7981
|
if (!targetId) {
|
|
7911
7982
|
setTargetPlane("lane");
|
|
7983
|
+
publishActiveLane(null);
|
|
7912
7984
|
rafId = requestAnimationFrame(tick);
|
|
7913
7985
|
return;
|
|
7914
7986
|
}
|
|
@@ -7930,12 +8002,14 @@ function useDragVisualLoop({
|
|
|
7930
8002
|
};
|
|
7931
8003
|
refs.visualIntentRef.current = intent;
|
|
7932
8004
|
refs.lastIntentRef.current = intent;
|
|
8005
|
+
publishActiveLane(intent.containerId);
|
|
7933
8006
|
} else {
|
|
7934
8007
|
setTargetPlane("lane");
|
|
7935
8008
|
refs.nestCandidateRef.current = null;
|
|
7936
8009
|
refs.nestTargetRef.current = null;
|
|
7937
8010
|
refs.lastIntentRef.current = intent;
|
|
7938
8011
|
refs.visualIntentRef.current = intent;
|
|
8012
|
+
publishActiveLane(intent.containerId);
|
|
7939
8013
|
setInsideRect(null);
|
|
7940
8014
|
const proj = refs.projectionRef.current;
|
|
7941
8015
|
const slot = proj.slotIndex.get(intent.slotId);
|
|
@@ -8242,7 +8316,8 @@ function useDragLifecycle({
|
|
|
8242
8316
|
syncHistoryAvailability,
|
|
8243
8317
|
resolveNodeElement,
|
|
8244
8318
|
setInsideRect,
|
|
8245
|
-
setDropLine
|
|
8319
|
+
setDropLine,
|
|
8320
|
+
setActiveLaneContainerId
|
|
8246
8321
|
}) {
|
|
8247
8322
|
const [activeDrag, setActiveDrag] = useState5(null);
|
|
8248
8323
|
const clearDragState = useCallback6(() => {
|
|
@@ -8253,13 +8328,12 @@ function useDragLifecycle({
|
|
|
8253
8328
|
refs.snapshotRef.current = null;
|
|
8254
8329
|
refs.projectionRef.current = EMPTY_PROJECTION;
|
|
8255
8330
|
refs.engineRef.current = null;
|
|
8256
|
-
refs.blockedContainerIdsRef.current = /* @__PURE__ */ new Set();
|
|
8257
8331
|
refs.lastIntentRef.current = null;
|
|
8258
8332
|
refs.visualIntentRef.current = null;
|
|
8259
8333
|
refs.sourceContainerIdRef.current = null;
|
|
8334
|
+
refs.activeLaneContainerIdRef.current = null;
|
|
8260
8335
|
refs.rowLockedRef.current = false;
|
|
8261
8336
|
refs.dragSessionAnchorRef.current = null;
|
|
8262
|
-
refs.lockRef.current = { containerId: null, isCrossUnlocked: false, exitSince: null, unlockUntilTs: null };
|
|
8263
8337
|
refs.targetPlaneRef.current = "lane";
|
|
8264
8338
|
refs.nestCandidateRef.current = null;
|
|
8265
8339
|
refs.nestTargetRef.current = null;
|
|
@@ -8270,6 +8344,7 @@ function useDragLifecycle({
|
|
|
8270
8344
|
refs.safeZoneRef.current = null;
|
|
8271
8345
|
setInsideRect(null);
|
|
8272
8346
|
setDropLine(null);
|
|
8347
|
+
setActiveLaneContainerId(null);
|
|
8273
8348
|
setActiveDrag(null);
|
|
8274
8349
|
resume();
|
|
8275
8350
|
}, [clearCommitLaneCache, resume]);
|
|
@@ -8327,7 +8402,6 @@ function useDragLifecycle({
|
|
|
8327
8402
|
const sourceCommitLane = getCommitLaneSnapshot(srcContainerId);
|
|
8328
8403
|
const startPosition = getCurrentCommitPlacement(anchorNodeId, srcContainerId);
|
|
8329
8404
|
const blockedContainerIds = buildBlockedStructuralContainerIds(proj, refs.nodeMapRef.current, srcContainerId);
|
|
8330
|
-
refs.blockedContainerIdsRef.current = blockedContainerIds;
|
|
8331
8405
|
const engineOptions = buildDragIntentEngineOptions(anchorScanned.element, srcContainerId, blockedContainerIds);
|
|
8332
8406
|
refs.rowLockedRef.current = !!engineOptions.laneAllowedContainers;
|
|
8333
8407
|
refs.engineRef.current = createDragIntentEngine(proj, anchorNodeId, engineOptions);
|
|
@@ -8336,7 +8410,6 @@ function useDragLifecycle({
|
|
|
8336
8410
|
refs.sourceContainerIdRef.current = srcContainerId;
|
|
8337
8411
|
refs.sourceCommitLaneRef.current = sourceCommitLane;
|
|
8338
8412
|
refs.dragSessionAnchorRef.current = anchor;
|
|
8339
|
-
refs.lockRef.current = { containerId: srcContainerId, isCrossUnlocked: true, exitSince: null, unlockUntilTs: null };
|
|
8340
8413
|
refs.dragStartPositionRef.current = startPosition;
|
|
8341
8414
|
refs.safeZoneRef.current = resolveSafeZoneRect();
|
|
8342
8415
|
pause();
|
|
@@ -8895,6 +8968,7 @@ function commitExternalDrop(x, y, engine, component, refs, resolveNodeElement, s
|
|
|
8895
8968
|
// src/client/dnd/design-mode/DesignModeOverlay.tsx
|
|
8896
8969
|
import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
8897
8970
|
var DROP_ANIMATION = { duration: DURATION_MS, easing: EASING };
|
|
8971
|
+
var EMPTY_CONTAINER_ID_SET = /* @__PURE__ */ new Set();
|
|
8898
8972
|
function resizeCursorFromHandle(handle) {
|
|
8899
8973
|
switch (handle) {
|
|
8900
8974
|
case "n":
|
|
@@ -9182,13 +9256,9 @@ function DesignModeOverlay() {
|
|
|
9182
9256
|
const sensors = useSensors(
|
|
9183
9257
|
useSensor(PointerSensor, { activationConstraint: { distance: 8 } })
|
|
9184
9258
|
);
|
|
9185
|
-
const collisionDetection = useCallback8(
|
|
9186
|
-
(args) => createDesignModeCollisionDetection(refs.blockedContainerIdsRef.current)(args),
|
|
9187
|
-
[]
|
|
9188
|
-
// eslint-disable-line react-hooks/exhaustive-deps -- refs are stable
|
|
9189
|
-
);
|
|
9190
9259
|
const [insideRect, setInsideRect] = useState6(null);
|
|
9191
9260
|
const [dropLine, setDropLine] = useState6(null);
|
|
9261
|
+
const [activeLaneContainerId, setActiveLaneContainerId] = useState6(null);
|
|
9192
9262
|
useEffect11(() => {
|
|
9193
9263
|
if (!enabled) return;
|
|
9194
9264
|
const fn = (e) => {
|
|
@@ -9224,8 +9294,43 @@ function DesignModeOverlay() {
|
|
|
9224
9294
|
syncHistoryAvailability,
|
|
9225
9295
|
resolveNodeElement,
|
|
9226
9296
|
setInsideRect,
|
|
9227
|
-
setDropLine
|
|
9297
|
+
setDropLine,
|
|
9298
|
+
setActiveLaneContainerId
|
|
9228
9299
|
});
|
|
9300
|
+
const dropCandidateContainerIds = useMemo6(
|
|
9301
|
+
() => activeDrag ? refs.engineRef.current?.getValidDropContainerIds() ?? null : null,
|
|
9302
|
+
[activeDrag]
|
|
9303
|
+
// eslint-disable-line react-hooks/exhaustive-deps -- refs are stable
|
|
9304
|
+
);
|
|
9305
|
+
const visibleCandidateContainerIds = useMemo6(() => {
|
|
9306
|
+
if (!dropCandidateContainerIds) return null;
|
|
9307
|
+
const rects = refs.snapshotRef.current?.rects;
|
|
9308
|
+
if (!rects) return dropCandidateContainerIds;
|
|
9309
|
+
const vw = window.innerWidth;
|
|
9310
|
+
const vh = window.innerHeight;
|
|
9311
|
+
const visible = /* @__PURE__ */ new Set();
|
|
9312
|
+
for (const id of dropCandidateContainerIds) {
|
|
9313
|
+
const r = rects.get(id);
|
|
9314
|
+
if (!r) continue;
|
|
9315
|
+
if (r.right < 0 || r.bottom < 0 || r.left > vw || r.top > vh) continue;
|
|
9316
|
+
visible.add(id);
|
|
9317
|
+
}
|
|
9318
|
+
return visible;
|
|
9319
|
+
}, [dropCandidateContainerIds]);
|
|
9320
|
+
const dragGuide = useMemo6(() => {
|
|
9321
|
+
if (!activeDrag) return null;
|
|
9322
|
+
const snapshot = refs.snapshotRef.current;
|
|
9323
|
+
if (!snapshot) return null;
|
|
9324
|
+
const activeChildIds = activeLaneContainerId ? refs.engineRef.current?.getContainerChildren(activeLaneContainerId) ?? [] : [];
|
|
9325
|
+
return {
|
|
9326
|
+
rects: snapshot.rects,
|
|
9327
|
+
startScroll: snapshot.scroll,
|
|
9328
|
+
candidateContainerIds: visibleCandidateContainerIds ?? EMPTY_CONTAINER_ID_SET,
|
|
9329
|
+
activeContainerId: activeLaneContainerId,
|
|
9330
|
+
activeChildIds,
|
|
9331
|
+
draggingNodeId: activeDrag.nodeId
|
|
9332
|
+
};
|
|
9333
|
+
}, [activeDrag, activeLaneContainerId, visibleCandidateContainerIds]);
|
|
9229
9334
|
useEffect11(() => {
|
|
9230
9335
|
if (!enabled || activeDrag) return;
|
|
9231
9336
|
if (undoRequestId === refs.processedUndoIdRef.current) return;
|
|
@@ -9288,7 +9393,7 @@ function DesignModeOverlay() {
|
|
|
9288
9393
|
safeZoneRef: refs.safeZoneRef,
|
|
9289
9394
|
autoScrollStateRef: refs.autoScrollStateRef
|
|
9290
9395
|
});
|
|
9291
|
-
useDragVisualLoop({ activeDrag, refs, getCommitLaneSnapshot, setInsideRect, setDropLine });
|
|
9396
|
+
useDragVisualLoop({ activeDrag, refs, getCommitLaneSnapshot, setInsideRect, setDropLine, setActiveLaneContainerId });
|
|
9292
9397
|
useExternalDragLoop({
|
|
9293
9398
|
externalDrag,
|
|
9294
9399
|
refs,
|
|
@@ -9308,7 +9413,6 @@ function DesignModeOverlay() {
|
|
|
9308
9413
|
DndContext,
|
|
9309
9414
|
{
|
|
9310
9415
|
sensors,
|
|
9311
|
-
collisionDetection,
|
|
9312
9416
|
autoScroll: false,
|
|
9313
9417
|
onDragStart: handleDragStart,
|
|
9314
9418
|
onDragEnd: handleDragEnd,
|
|
@@ -9317,10 +9421,8 @@ function DesignModeOverlay() {
|
|
|
9317
9421
|
/* @__PURE__ */ jsx4(
|
|
9318
9422
|
ElementHighlight,
|
|
9319
9423
|
{
|
|
9320
|
-
|
|
9321
|
-
|
|
9322
|
-
activeEl: refs.activeElRef.current,
|
|
9323
|
-
arrangeSelectedNodeId,
|
|
9424
|
+
selected: arrangeSelectedNodeId ? nodeMap.get(arrangeSelectedNodeId) ?? null : null,
|
|
9425
|
+
dragGuide,
|
|
9324
9426
|
externalDragActive: externalDrag !== null,
|
|
9325
9427
|
onResizeHandlePointerDown: handleResizeHandlePointerDown
|
|
9326
9428
|
}
|