dnd-block-tree 1.2.0 → 1.3.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/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +167 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +167 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -793,13 +793,15 @@ interface BlockTreeDevToolsProps<T extends BaseBlock = BaseBlock> {
|
|
|
793
793
|
buttonStyle?: React.CSSProperties;
|
|
794
794
|
/** Custom inline styles for the card panel */
|
|
795
795
|
panelStyle?: React.CSSProperties;
|
|
796
|
+
/** Force mount in production (default: false). DevTools renders nothing in production unless this is true. */
|
|
797
|
+
forceMount?: boolean;
|
|
796
798
|
}
|
|
797
799
|
declare function useDevToolsCallbacks<T extends BaseBlock = BaseBlock>(): {
|
|
798
800
|
callbacks: DevToolsCallbacks<T>;
|
|
799
801
|
events: DevToolsEventEntry[];
|
|
800
802
|
clearEvents: () => void;
|
|
801
803
|
};
|
|
802
|
-
declare function BlockTreeDevTools<T extends BaseBlock = BaseBlock>({ blocks, containerTypes, events, onClearEvents, getLabel, initialOpen, position, buttonStyle, panelStyle, }: BlockTreeDevToolsProps<T>): react_jsx_runtime.JSX.Element;
|
|
804
|
+
declare function BlockTreeDevTools<T extends BaseBlock = BaseBlock>({ blocks, containerTypes, events, onClearEvents, getLabel, initialOpen, position, buttonStyle, panelStyle, forceMount, }: BlockTreeDevToolsProps<T>): react_jsx_runtime.JSX.Element | null;
|
|
803
805
|
|
|
804
806
|
/**
|
|
805
807
|
* A nested/tree representation of a block.
|
package/dist/index.d.ts
CHANGED
|
@@ -793,13 +793,15 @@ interface BlockTreeDevToolsProps<T extends BaseBlock = BaseBlock> {
|
|
|
793
793
|
buttonStyle?: React.CSSProperties;
|
|
794
794
|
/** Custom inline styles for the card panel */
|
|
795
795
|
panelStyle?: React.CSSProperties;
|
|
796
|
+
/** Force mount in production (default: false). DevTools renders nothing in production unless this is true. */
|
|
797
|
+
forceMount?: boolean;
|
|
796
798
|
}
|
|
797
799
|
declare function useDevToolsCallbacks<T extends BaseBlock = BaseBlock>(): {
|
|
798
800
|
callbacks: DevToolsCallbacks<T>;
|
|
799
801
|
events: DevToolsEventEntry[];
|
|
800
802
|
clearEvents: () => void;
|
|
801
803
|
};
|
|
802
|
-
declare function BlockTreeDevTools<T extends BaseBlock = BaseBlock>({ blocks, containerTypes, events, onClearEvents, getLabel, initialOpen, position, buttonStyle, panelStyle, }: BlockTreeDevToolsProps<T>): react_jsx_runtime.JSX.Element;
|
|
804
|
+
declare function BlockTreeDevTools<T extends BaseBlock = BaseBlock>({ blocks, containerTypes, events, onClearEvents, getLabel, initialOpen, position, buttonStyle, panelStyle, forceMount, }: BlockTreeDevToolsProps<T>): react_jsx_runtime.JSX.Element | null;
|
|
803
805
|
|
|
804
806
|
/**
|
|
805
807
|
* A nested/tree representation of a block.
|
package/dist/index.js
CHANGED
|
@@ -2061,33 +2061,78 @@ var DEFAULT_HEIGHT = 420;
|
|
|
2061
2061
|
var DIFF_EXTRA_WIDTH = 300;
|
|
2062
2062
|
var MIN_WIDTH = 280;
|
|
2063
2063
|
var MIN_HEIGHT = 200;
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2064
|
+
var BTN_SIZE = 40;
|
|
2065
|
+
var BTN_MARGIN = 16;
|
|
2066
|
+
var STORAGE_KEY = "dnd-devtools-position";
|
|
2067
|
+
var BTN_DRAG_THRESHOLD = 5;
|
|
2068
|
+
function cornerToXY(corner) {
|
|
2069
|
+
const vw = typeof window !== "undefined" ? window.innerWidth : 1024;
|
|
2070
|
+
const vh = typeof window !== "undefined" ? window.innerHeight : 768;
|
|
2071
|
+
switch (corner) {
|
|
2068
2072
|
case "top-left":
|
|
2069
|
-
return {
|
|
2073
|
+
return { x: BTN_MARGIN, y: BTN_MARGIN };
|
|
2070
2074
|
case "top-right":
|
|
2071
|
-
return {
|
|
2075
|
+
return { x: vw - BTN_MARGIN - BTN_SIZE, y: BTN_MARGIN };
|
|
2076
|
+
case "bottom-right":
|
|
2077
|
+
return { x: vw - BTN_MARGIN - BTN_SIZE, y: vh - BTN_MARGIN - BTN_SIZE };
|
|
2072
2078
|
case "bottom-left":
|
|
2073
2079
|
default:
|
|
2074
|
-
return {
|
|
2080
|
+
return { x: BTN_MARGIN, y: vh - BTN_MARGIN - BTN_SIZE };
|
|
2081
|
+
}
|
|
2082
|
+
}
|
|
2083
|
+
function xyToCorner(x, y) {
|
|
2084
|
+
const vw = typeof window !== "undefined" ? window.innerWidth : 1024;
|
|
2085
|
+
const vh = typeof window !== "undefined" ? window.innerHeight : 768;
|
|
2086
|
+
const isLeft = x + BTN_SIZE / 2 < vw / 2;
|
|
2087
|
+
const isTop = y + BTN_SIZE / 2 < vh / 2;
|
|
2088
|
+
if (isTop && isLeft) return "top-left";
|
|
2089
|
+
if (isTop) return "top-right";
|
|
2090
|
+
if (isLeft) return "bottom-left";
|
|
2091
|
+
return "bottom-right";
|
|
2092
|
+
}
|
|
2093
|
+
function loadStoredPosition() {
|
|
2094
|
+
if (typeof window === "undefined") return null;
|
|
2095
|
+
try {
|
|
2096
|
+
const v = localStorage.getItem(STORAGE_KEY);
|
|
2097
|
+
if (v === "bottom-left" || v === "bottom-right" || v === "top-left" || v === "top-right") return v;
|
|
2098
|
+
} catch {
|
|
2099
|
+
}
|
|
2100
|
+
return null;
|
|
2101
|
+
}
|
|
2102
|
+
function savePosition(corner) {
|
|
2103
|
+
try {
|
|
2104
|
+
localStorage.setItem(STORAGE_KEY, corner);
|
|
2105
|
+
} catch {
|
|
2075
2106
|
}
|
|
2076
2107
|
}
|
|
2077
|
-
function computeCardOrigin(
|
|
2108
|
+
function computeCardOrigin(corner, width, height) {
|
|
2078
2109
|
const vw = typeof window !== "undefined" ? window.innerWidth : 1024;
|
|
2079
2110
|
const vh = typeof window !== "undefined" ? window.innerHeight : 768;
|
|
2080
|
-
|
|
2111
|
+
let x;
|
|
2112
|
+
let y;
|
|
2113
|
+
switch (corner) {
|
|
2081
2114
|
case "bottom-right":
|
|
2082
|
-
|
|
2115
|
+
x = vw - BTN_MARGIN - width;
|
|
2116
|
+
y = vh - BTN_MARGIN - height - BTN_SIZE - 8;
|
|
2117
|
+
break;
|
|
2083
2118
|
case "top-left":
|
|
2084
|
-
|
|
2119
|
+
x = BTN_MARGIN;
|
|
2120
|
+
y = BTN_MARGIN + BTN_SIZE + 8;
|
|
2121
|
+
break;
|
|
2085
2122
|
case "top-right":
|
|
2086
|
-
|
|
2123
|
+
x = vw - BTN_MARGIN - width;
|
|
2124
|
+
y = BTN_MARGIN + BTN_SIZE + 8;
|
|
2125
|
+
break;
|
|
2087
2126
|
case "bottom-left":
|
|
2088
2127
|
default:
|
|
2089
|
-
|
|
2128
|
+
x = BTN_MARGIN;
|
|
2129
|
+
y = vh - BTN_MARGIN - height - BTN_SIZE - 8;
|
|
2130
|
+
break;
|
|
2090
2131
|
}
|
|
2132
|
+
return {
|
|
2133
|
+
x: Math.max(0, Math.min(x, vw - width)),
|
|
2134
|
+
y: Math.max(0, Math.min(y, vh - height))
|
|
2135
|
+
};
|
|
2091
2136
|
}
|
|
2092
2137
|
function BlockTreeDevTools({
|
|
2093
2138
|
blocks,
|
|
@@ -2098,13 +2143,89 @@ function BlockTreeDevTools({
|
|
|
2098
2143
|
initialOpen = false,
|
|
2099
2144
|
position = "bottom-left",
|
|
2100
2145
|
buttonStyle,
|
|
2101
|
-
panelStyle
|
|
2146
|
+
panelStyle,
|
|
2147
|
+
forceMount = false
|
|
2102
2148
|
}) {
|
|
2149
|
+
if (typeof process !== "undefined" && process.env?.NODE_ENV === "production" && !forceMount) {
|
|
2150
|
+
return null;
|
|
2151
|
+
}
|
|
2103
2152
|
const [isOpen, setIsOpen] = react.useState(initialOpen);
|
|
2104
2153
|
const [showDiff, setShowDiff] = react.useState(false);
|
|
2105
2154
|
const [cardPos, setCardPos] = react.useState(null);
|
|
2106
2155
|
const [cardSize, setCardSize] = react.useState({ w: DEFAULT_WIDTH, h: DEFAULT_HEIGHT });
|
|
2107
2156
|
const [showTooltip, setShowTooltip] = react.useState(false);
|
|
2157
|
+
const [activeCorner, setActiveCorner] = react.useState(() => loadStoredPosition() ?? position);
|
|
2158
|
+
const [btnPos, setBtnPos] = react.useState(() => cornerToXY(loadStoredPosition() ?? position));
|
|
2159
|
+
const [btnDragging, setBtnDragging] = react.useState(false);
|
|
2160
|
+
const [btnTransition, setBtnTransition] = react.useState(false);
|
|
2161
|
+
const btnDragRef = react.useRef({
|
|
2162
|
+
active: false,
|
|
2163
|
+
startX: 0,
|
|
2164
|
+
startY: 0,
|
|
2165
|
+
origX: 0,
|
|
2166
|
+
origY: 0,
|
|
2167
|
+
moved: false
|
|
2168
|
+
});
|
|
2169
|
+
react.useEffect(() => {
|
|
2170
|
+
if (!btnDragging) {
|
|
2171
|
+
setBtnPos(cornerToXY(activeCorner));
|
|
2172
|
+
}
|
|
2173
|
+
}, [activeCorner, btnDragging]);
|
|
2174
|
+
react.useEffect(() => {
|
|
2175
|
+
const onResize = () => {
|
|
2176
|
+
if (!btnDragRef.current.active) {
|
|
2177
|
+
setBtnPos(cornerToXY(activeCorner));
|
|
2178
|
+
}
|
|
2179
|
+
};
|
|
2180
|
+
window.addEventListener("resize", onResize);
|
|
2181
|
+
return () => window.removeEventListener("resize", onResize);
|
|
2182
|
+
}, [activeCorner]);
|
|
2183
|
+
const handleBtnPointerDown = react.useCallback((e) => {
|
|
2184
|
+
btnDragRef.current = {
|
|
2185
|
+
active: true,
|
|
2186
|
+
startX: e.clientX,
|
|
2187
|
+
startY: e.clientY,
|
|
2188
|
+
origX: btnPos.x,
|
|
2189
|
+
origY: btnPos.y,
|
|
2190
|
+
moved: false
|
|
2191
|
+
};
|
|
2192
|
+
e.target.setPointerCapture(e.pointerId);
|
|
2193
|
+
}, [btnPos]);
|
|
2194
|
+
const handleBtnPointerMove = react.useCallback((e) => {
|
|
2195
|
+
const r = btnDragRef.current;
|
|
2196
|
+
if (!r.active) return;
|
|
2197
|
+
const dx = e.clientX - r.startX;
|
|
2198
|
+
const dy = e.clientY - r.startY;
|
|
2199
|
+
if (!r.moved && Math.abs(dx) < BTN_DRAG_THRESHOLD && Math.abs(dy) < BTN_DRAG_THRESHOLD) return;
|
|
2200
|
+
r.moved = true;
|
|
2201
|
+
setBtnDragging(true);
|
|
2202
|
+
const newX = r.origX + dx;
|
|
2203
|
+
const newY = r.origY + dy;
|
|
2204
|
+
const maxX = window.innerWidth - BTN_SIZE;
|
|
2205
|
+
const maxY = window.innerHeight - BTN_SIZE;
|
|
2206
|
+
setBtnPos({
|
|
2207
|
+
x: Math.max(0, Math.min(newX, maxX)),
|
|
2208
|
+
y: Math.max(0, Math.min(newY, maxY))
|
|
2209
|
+
});
|
|
2210
|
+
}, []);
|
|
2211
|
+
const handleBtnPointerUp = react.useCallback(() => {
|
|
2212
|
+
const wasMoved = btnDragRef.current.moved;
|
|
2213
|
+
btnDragRef.current.active = false;
|
|
2214
|
+
if (wasMoved) {
|
|
2215
|
+
const newCorner = xyToCorner(btnPos.x, btnPos.y);
|
|
2216
|
+
setActiveCorner(newCorner);
|
|
2217
|
+
savePosition(newCorner);
|
|
2218
|
+
setBtnTransition(true);
|
|
2219
|
+
setBtnPos(cornerToXY(newCorner));
|
|
2220
|
+
setTimeout(() => {
|
|
2221
|
+
setBtnTransition(false);
|
|
2222
|
+
setBtnDragging(false);
|
|
2223
|
+
}, 300);
|
|
2224
|
+
} else {
|
|
2225
|
+
setBtnDragging(false);
|
|
2226
|
+
setIsOpen((prev) => !prev);
|
|
2227
|
+
}
|
|
2228
|
+
}, [btnPos]);
|
|
2108
2229
|
const dragRef = react.useRef({
|
|
2109
2230
|
dragging: false,
|
|
2110
2231
|
startX: 0,
|
|
@@ -2133,18 +2254,28 @@ function BlockTreeDevTools({
|
|
|
2133
2254
|
const targetW = showDiff ? DEFAULT_WIDTH + DIFF_EXTRA_WIDTH : DEFAULT_WIDTH;
|
|
2134
2255
|
const wasDefault = Math.abs(prev.w - DEFAULT_WIDTH) < 20;
|
|
2135
2256
|
const wasExpanded = Math.abs(prev.w - (DEFAULT_WIDTH + DIFF_EXTRA_WIDTH)) < 20;
|
|
2257
|
+
let newW = prev.w;
|
|
2136
2258
|
if (showDiff && (wasDefault || prev.w < targetW)) {
|
|
2137
|
-
|
|
2259
|
+
newW = targetW;
|
|
2260
|
+
} else if (!showDiff && wasExpanded) {
|
|
2261
|
+
newW = DEFAULT_WIDTH;
|
|
2138
2262
|
}
|
|
2139
|
-
if (
|
|
2140
|
-
|
|
2263
|
+
if (newW !== prev.w) {
|
|
2264
|
+
setCardPos((cp) => {
|
|
2265
|
+
if (!cp) return cp;
|
|
2266
|
+
const vw = typeof window !== "undefined" ? window.innerWidth : 1024;
|
|
2267
|
+
const maxX = Math.max(0, vw - newW);
|
|
2268
|
+
if (cp.x > maxX) return { ...cp, x: maxX };
|
|
2269
|
+
return cp;
|
|
2270
|
+
});
|
|
2271
|
+
return { ...prev, w: newW };
|
|
2141
2272
|
}
|
|
2142
2273
|
return prev;
|
|
2143
2274
|
});
|
|
2144
2275
|
}, [showDiff]);
|
|
2145
2276
|
const getDefaultCardPos = react.useCallback(() => {
|
|
2146
|
-
return computeCardOrigin(
|
|
2147
|
-
}, [
|
|
2277
|
+
return computeCardOrigin(activeCorner, cardSize.w, cardSize.h);
|
|
2278
|
+
}, [activeCorner, cardSize.w, cardSize.h]);
|
|
2148
2279
|
react.useEffect(() => {
|
|
2149
2280
|
if (isOpen && !cardPos) {
|
|
2150
2281
|
setCardPos(getDefaultCardPos());
|
|
@@ -2253,23 +2384,27 @@ function BlockTreeDevTools({
|
|
|
2253
2384
|
const d = new Date(ts);
|
|
2254
2385
|
return `${d.getHours().toString().padStart(2, "0")}:${d.getMinutes().toString().padStart(2, "0")}:${d.getSeconds().toString().padStart(2, "0")}`;
|
|
2255
2386
|
};
|
|
2256
|
-
const
|
|
2387
|
+
const isBottom = activeCorner.startsWith("bottom");
|
|
2388
|
+
const isLeft = activeCorner.endsWith("left");
|
|
2257
2389
|
const triggerBtnStyle = {
|
|
2258
2390
|
position: "fixed",
|
|
2259
|
-
|
|
2391
|
+
left: btnPos.x,
|
|
2392
|
+
top: btnPos.y,
|
|
2260
2393
|
zIndex: 99998,
|
|
2261
|
-
width:
|
|
2262
|
-
height:
|
|
2394
|
+
width: BTN_SIZE,
|
|
2395
|
+
height: BTN_SIZE,
|
|
2263
2396
|
borderRadius: "50%",
|
|
2264
2397
|
border: "none",
|
|
2265
2398
|
background: isOpen ? "rgba(59, 130, 246, 0.9)" : "rgba(30, 30, 30, 0.85)",
|
|
2266
2399
|
color: "#fff",
|
|
2267
|
-
cursor: "pointer",
|
|
2400
|
+
cursor: btnDragging ? "grabbing" : "pointer",
|
|
2268
2401
|
display: "flex",
|
|
2269
2402
|
alignItems: "center",
|
|
2270
2403
|
justifyContent: "center",
|
|
2271
2404
|
boxShadow: "0 2px 8px rgba(0,0,0,0.3)",
|
|
2272
|
-
transition: "background 0.15s
|
|
2405
|
+
transition: btnTransition ? "left 0.3s cubic-bezier(0.4, 0, 0.2, 1), top 0.3s cubic-bezier(0.4, 0, 0.2, 1), background 0.15s" : "background 0.15s",
|
|
2406
|
+
touchAction: "none",
|
|
2407
|
+
userSelect: "none",
|
|
2273
2408
|
...buttonStyle
|
|
2274
2409
|
};
|
|
2275
2410
|
const tooltipStyle = {
|
|
@@ -2283,9 +2418,8 @@ function BlockTreeDevTools({
|
|
|
2283
2418
|
color: "#ccc",
|
|
2284
2419
|
boxShadow: "0 2px 8px rgba(0,0,0,0.3)",
|
|
2285
2420
|
pointerEvents: "none",
|
|
2286
|
-
|
|
2287
|
-
...
|
|
2288
|
-
...anchor.left !== void 0 ? { left: 0 } : { right: 0 }
|
|
2421
|
+
...isBottom ? { bottom: "100%", marginBottom: 8 } : { top: "100%", marginTop: 8 },
|
|
2422
|
+
...isLeft ? { left: 0 } : { right: 0 }
|
|
2289
2423
|
};
|
|
2290
2424
|
const cardStyle = {
|
|
2291
2425
|
position: "fixed",
|
|
@@ -2476,11 +2610,13 @@ function BlockTreeDevTools({
|
|
|
2476
2610
|
return { color: "rgba(200,200,200,0.5)" };
|
|
2477
2611
|
};
|
|
2478
2612
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2479
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "fixed",
|
|
2613
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { style: { position: "fixed", left: btnPos.x, top: btnPos.y, zIndex: 99998 }, children: [
|
|
2480
2614
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2481
2615
|
"button",
|
|
2482
2616
|
{
|
|
2483
|
-
|
|
2617
|
+
onPointerDown: handleBtnPointerDown,
|
|
2618
|
+
onPointerMove: handleBtnPointerMove,
|
|
2619
|
+
onPointerUp: handleBtnPointerUp,
|
|
2484
2620
|
onMouseEnter: () => setShowTooltip(true),
|
|
2485
2621
|
onMouseLeave: () => setShowTooltip(false),
|
|
2486
2622
|
style: triggerBtnStyle,
|
|
@@ -2488,7 +2624,7 @@ function BlockTreeDevTools({
|
|
|
2488
2624
|
children: /* @__PURE__ */ jsxRuntime.jsx(DevToolsLogo, { size: 20 })
|
|
2489
2625
|
}
|
|
2490
2626
|
),
|
|
2491
|
-
showTooltip && !isOpen && /* @__PURE__ */ jsxRuntime.jsx("div", { style: tooltipStyle, children: "dnd-block-tree DevTools" })
|
|
2627
|
+
showTooltip && !isOpen && !btnDragging && /* @__PURE__ */ jsxRuntime.jsx("div", { style: tooltipStyle, children: "dnd-block-tree DevTools" })
|
|
2492
2628
|
] }),
|
|
2493
2629
|
isOpen && cardPos && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2494
2630
|
"div",
|