made-refine 0.1.1-beta.1 → 0.1.1
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 +7 -5
- package/dist/index.d.ts +7 -5
- package/dist/index.js +197 -112
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +197 -112
- package/dist/index.mjs.map +1 -1
- package/dist/{utils-DNTIJ83m.d.mts → utils-DyR599SI.d.mts} +15 -1
- package/dist/{utils-DNTIJ83m.d.ts → utils-DyR599SI.d.ts} +15 -1
- package/dist/utils.d.mts +1 -1
- package/dist/utils.d.ts +1 -1
- package/dist/utils.js +129 -0
- package/dist/utils.js.map +1 -1
- package/dist/utils.mjs +123 -0
- package/dist/utils.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { D as DragState, a as DropIndicator, b as DirectEditState, S as SpacingPropertyKey, C as CSSPropertyValue, B as BorderRadiusPropertyKey, c as BorderPropertyKey, d as BorderProperties, F as FlexPropertyKey, e as SizingPropertyKey, f as SizingValue, g as ColorPropertyKey, h as ColorValue, T as TypographyPropertyKey, A as ActiveTool, i as Theme, j as SessionEdit, k as TypographyProperties, M as MeasurementLine, G as Guideline, l as Comment } from './utils-
|
|
4
|
-
export { m as BorderRadiusProperties, n as BorderStyle, o as ColorProperties, p as CommentReply, q as DomSourceLocation, r as DropTarget, E as ElementInfo, s as ElementLocator, t as FlexProperties, u as MeasurementState, R as ReactComponentFrame, v as SizingMode, w as SizingProperties, x as SpacingProperties, U as UndoEditEntry, y as UndoEntry, z as UndoMoveEntry, H as UndoSelectionEntry, I as buildCommentExport, J as buildSessionExport, K as calculateDropPosition, L as calculateElementMeasurements, N as calculateGuidelineMeasurements, O as calculateParentMeasurements, P as colorToTailwind, Q as elementFromPointWithoutOverlays, V as findContainerAtPoint, W as formatPropertyValue, X as getComputedBorderStyles, Y as getComputedColorStyles, Z as getComputedStyles, _ as getDimensionDisplay, $ as getElementInfo, a0 as getElementLocator, a1 as getFlexDirection, a2 as isFlexContainer, a3 as parseColorValue, a4 as parsePropertyValue, a5 as stylesToTailwind } from './utils-
|
|
3
|
+
import { D as DragState, a as DropIndicator, b as DirectEditState, S as SpacingPropertyKey, C as CSSPropertyValue, B as BorderRadiusPropertyKey, c as BorderPropertyKey, d as BorderProperties, F as FlexPropertyKey, e as SizingPropertyKey, f as SizingValue, g as ColorPropertyKey, h as ColorValue, T as TypographyPropertyKey, A as ActiveTool, i as Theme, j as SessionEdit, k as TypographyProperties, M as MeasurementLine, G as Guideline, l as Comment } from './utils-DyR599SI.mjs';
|
|
4
|
+
export { m as BorderRadiusProperties, n as BorderStyle, o as ColorProperties, p as CommentReply, q as DomSourceLocation, r as DropTarget, E as ElementInfo, s as ElementLocator, t as FlexProperties, u as MeasurementState, R as ReactComponentFrame, v as SizingMode, w as SizingProperties, x as SpacingProperties, U as UndoEditEntry, y as UndoEntry, z as UndoMoveEntry, H as UndoSelectionEntry, I as buildCommentExport, J as buildSessionExport, K as calculateDropPosition, L as calculateElementMeasurements, N as calculateGuidelineMeasurements, O as calculateParentMeasurements, P as colorToTailwind, Q as elementFromPointWithoutOverlays, V as findContainerAtPoint, W as formatPropertyValue, X as getComputedBorderStyles, Y as getComputedColorStyles, Z as getComputedStyles, _ as getDimensionDisplay, $ as getElementInfo, a0 as getElementLocator, a1 as getFlexDirection, a2 as isFlexContainer, a3 as parseColorValue, a4 as parsePropertyValue, a5 as stylesToTailwind } from './utils-DyR599SI.mjs';
|
|
5
5
|
|
|
6
6
|
declare function DirectEdit(): react_jsx_runtime.JSX.Element;
|
|
7
7
|
|
|
@@ -190,9 +190,11 @@ interface SelectionOverlayProps {
|
|
|
190
190
|
};
|
|
191
191
|
onMoveStart: (e: React.PointerEvent) => void;
|
|
192
192
|
isTextEditing?: boolean;
|
|
193
|
-
onDoubleClick?: () => void;
|
|
193
|
+
onDoubleClick?: (clientX: number, clientY: number) => void;
|
|
194
|
+
onHoverElement?: (element: HTMLElement | null) => void;
|
|
195
|
+
onClickThrough?: (clientX: number, clientY: number) => void;
|
|
194
196
|
}
|
|
195
|
-
declare function SelectionOverlay({ selectedElement, isDragging, ghostPosition, onMoveStart, isTextEditing, onDoubleClick, }: SelectionOverlayProps): react_jsx_runtime.JSX.Element;
|
|
197
|
+
declare function SelectionOverlay({ selectedElement, isDragging, ghostPosition, onMoveStart, isTextEditing, onDoubleClick, onHoverElement, onClickThrough, }: SelectionOverlayProps): react_jsx_runtime.JSX.Element;
|
|
196
198
|
|
|
197
199
|
interface MoveOverlayProps {
|
|
198
200
|
dropIndicator: DropIndicator | null;
|
|
@@ -220,7 +222,7 @@ interface UseGuidelinesResult {
|
|
|
220
222
|
clearAll: () => void;
|
|
221
223
|
}
|
|
222
224
|
declare function getStoredGuidelines(): Guideline[];
|
|
223
|
-
declare function useGuidelines(enabled: boolean): UseGuidelinesResult;
|
|
225
|
+
declare function useGuidelines(enabled: boolean, hostElement?: HTMLElement | null): UseGuidelinesResult;
|
|
224
226
|
|
|
225
227
|
interface CommentOverlayProps {
|
|
226
228
|
comments: Comment[];
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { D as DragState, a as DropIndicator, b as DirectEditState, S as SpacingPropertyKey, C as CSSPropertyValue, B as BorderRadiusPropertyKey, c as BorderPropertyKey, d as BorderProperties, F as FlexPropertyKey, e as SizingPropertyKey, f as SizingValue, g as ColorPropertyKey, h as ColorValue, T as TypographyPropertyKey, A as ActiveTool, i as Theme, j as SessionEdit, k as TypographyProperties, M as MeasurementLine, G as Guideline, l as Comment } from './utils-
|
|
4
|
-
export { m as BorderRadiusProperties, n as BorderStyle, o as ColorProperties, p as CommentReply, q as DomSourceLocation, r as DropTarget, E as ElementInfo, s as ElementLocator, t as FlexProperties, u as MeasurementState, R as ReactComponentFrame, v as SizingMode, w as SizingProperties, x as SpacingProperties, U as UndoEditEntry, y as UndoEntry, z as UndoMoveEntry, H as UndoSelectionEntry, I as buildCommentExport, J as buildSessionExport, K as calculateDropPosition, L as calculateElementMeasurements, N as calculateGuidelineMeasurements, O as calculateParentMeasurements, P as colorToTailwind, Q as elementFromPointWithoutOverlays, V as findContainerAtPoint, W as formatPropertyValue, X as getComputedBorderStyles, Y as getComputedColorStyles, Z as getComputedStyles, _ as getDimensionDisplay, $ as getElementInfo, a0 as getElementLocator, a1 as getFlexDirection, a2 as isFlexContainer, a3 as parseColorValue, a4 as parsePropertyValue, a5 as stylesToTailwind } from './utils-
|
|
3
|
+
import { D as DragState, a as DropIndicator, b as DirectEditState, S as SpacingPropertyKey, C as CSSPropertyValue, B as BorderRadiusPropertyKey, c as BorderPropertyKey, d as BorderProperties, F as FlexPropertyKey, e as SizingPropertyKey, f as SizingValue, g as ColorPropertyKey, h as ColorValue, T as TypographyPropertyKey, A as ActiveTool, i as Theme, j as SessionEdit, k as TypographyProperties, M as MeasurementLine, G as Guideline, l as Comment } from './utils-DyR599SI.js';
|
|
4
|
+
export { m as BorderRadiusProperties, n as BorderStyle, o as ColorProperties, p as CommentReply, q as DomSourceLocation, r as DropTarget, E as ElementInfo, s as ElementLocator, t as FlexProperties, u as MeasurementState, R as ReactComponentFrame, v as SizingMode, w as SizingProperties, x as SpacingProperties, U as UndoEditEntry, y as UndoEntry, z as UndoMoveEntry, H as UndoSelectionEntry, I as buildCommentExport, J as buildSessionExport, K as calculateDropPosition, L as calculateElementMeasurements, N as calculateGuidelineMeasurements, O as calculateParentMeasurements, P as colorToTailwind, Q as elementFromPointWithoutOverlays, V as findContainerAtPoint, W as formatPropertyValue, X as getComputedBorderStyles, Y as getComputedColorStyles, Z as getComputedStyles, _ as getDimensionDisplay, $ as getElementInfo, a0 as getElementLocator, a1 as getFlexDirection, a2 as isFlexContainer, a3 as parseColorValue, a4 as parsePropertyValue, a5 as stylesToTailwind } from './utils-DyR599SI.js';
|
|
5
5
|
|
|
6
6
|
declare function DirectEdit(): react_jsx_runtime.JSX.Element;
|
|
7
7
|
|
|
@@ -190,9 +190,11 @@ interface SelectionOverlayProps {
|
|
|
190
190
|
};
|
|
191
191
|
onMoveStart: (e: React.PointerEvent) => void;
|
|
192
192
|
isTextEditing?: boolean;
|
|
193
|
-
onDoubleClick?: () => void;
|
|
193
|
+
onDoubleClick?: (clientX: number, clientY: number) => void;
|
|
194
|
+
onHoverElement?: (element: HTMLElement | null) => void;
|
|
195
|
+
onClickThrough?: (clientX: number, clientY: number) => void;
|
|
194
196
|
}
|
|
195
|
-
declare function SelectionOverlay({ selectedElement, isDragging, ghostPosition, onMoveStart, isTextEditing, onDoubleClick, }: SelectionOverlayProps): react_jsx_runtime.JSX.Element;
|
|
197
|
+
declare function SelectionOverlay({ selectedElement, isDragging, ghostPosition, onMoveStart, isTextEditing, onDoubleClick, onHoverElement, onClickThrough, }: SelectionOverlayProps): react_jsx_runtime.JSX.Element;
|
|
196
198
|
|
|
197
199
|
interface MoveOverlayProps {
|
|
198
200
|
dropIndicator: DropIndicator | null;
|
|
@@ -220,7 +222,7 @@ interface UseGuidelinesResult {
|
|
|
220
222
|
clearAll: () => void;
|
|
221
223
|
}
|
|
222
224
|
declare function getStoredGuidelines(): Guideline[];
|
|
223
|
-
declare function useGuidelines(enabled: boolean): UseGuidelinesResult;
|
|
225
|
+
declare function useGuidelines(enabled: boolean, hostElement?: HTMLElement | null): UseGuidelinesResult;
|
|
224
226
|
|
|
225
227
|
interface CommentOverlayProps {
|
|
226
228
|
comments: Comment[];
|
package/dist/index.js
CHANGED
|
@@ -590,11 +590,19 @@ var TEXT_ELEMENT_TAGS = /* @__PURE__ */ new Set([
|
|
|
590
590
|
"code",
|
|
591
591
|
"pre"
|
|
592
592
|
]);
|
|
593
|
+
function hasDirectNonWhitespaceText(element) {
|
|
594
|
+
return Array.from(element.childNodes).some(
|
|
595
|
+
(node) => node.nodeType === Node.TEXT_NODE && Boolean(node.textContent?.trim())
|
|
596
|
+
);
|
|
597
|
+
}
|
|
593
598
|
function isTextElement(element) {
|
|
594
599
|
const tagName = element.tagName.toLowerCase();
|
|
595
600
|
if (TEXT_ELEMENT_TAGS.has(tagName)) {
|
|
596
601
|
return true;
|
|
597
602
|
}
|
|
603
|
+
if (hasDirectNonWhitespaceText(element)) {
|
|
604
|
+
return true;
|
|
605
|
+
}
|
|
598
606
|
if (element.children.length === 0 && element.textContent?.trim()) {
|
|
599
607
|
return true;
|
|
600
608
|
}
|
|
@@ -1139,6 +1147,57 @@ function detectChildrenDirection(container, exclude) {
|
|
|
1139
1147
|
}
|
|
1140
1148
|
return { axis: "vertical", reversed: second.bottom < first.top };
|
|
1141
1149
|
}
|
|
1150
|
+
function htmlChildren(el) {
|
|
1151
|
+
return Array.from(el.children).filter(
|
|
1152
|
+
(child) => child instanceof HTMLElement
|
|
1153
|
+
);
|
|
1154
|
+
}
|
|
1155
|
+
function findFlexAncestor(element, boundary) {
|
|
1156
|
+
let current = element;
|
|
1157
|
+
while (current && current !== document.body) {
|
|
1158
|
+
const parent = current.parentElement;
|
|
1159
|
+
if (!parent) break;
|
|
1160
|
+
const display = getComputedStyle(parent).display;
|
|
1161
|
+
if (display === "flex" || display === "inline-flex") {
|
|
1162
|
+
return { flexParent: parent, child: current };
|
|
1163
|
+
}
|
|
1164
|
+
if (boundary && parent === boundary) break;
|
|
1165
|
+
current = parent;
|
|
1166
|
+
}
|
|
1167
|
+
return null;
|
|
1168
|
+
}
|
|
1169
|
+
function computeHoverHighlight(elementUnder, selectedElement) {
|
|
1170
|
+
if (!elementUnder || elementUnder === document.body || elementUnder === document.documentElement || elementUnder.closest("[data-direct-edit]") || elementUnder.closest("[data-direct-edit-host]") || elementUnder === selectedElement) {
|
|
1171
|
+
return null;
|
|
1172
|
+
}
|
|
1173
|
+
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1174
|
+
const ownDisplay = getComputedStyle(elementUnder).display;
|
|
1175
|
+
if (ownDisplay === "flex" || ownDisplay === "inline-flex") {
|
|
1176
|
+
return { flexContainer: elementUnder, children: htmlChildren(elementUnder) };
|
|
1177
|
+
}
|
|
1178
|
+
const found = findFlexAncestor(elementUnder, boundary);
|
|
1179
|
+
if (found) {
|
|
1180
|
+
return { flexContainer: found.flexParent, children: htmlChildren(found.flexParent) };
|
|
1181
|
+
}
|
|
1182
|
+
return { flexContainer: elementUnder, children: [] };
|
|
1183
|
+
}
|
|
1184
|
+
function resolveElementTarget(elementUnder, selectedElement) {
|
|
1185
|
+
const boundary = selectedElement?.contains(elementUnder) ? selectedElement : null;
|
|
1186
|
+
const found = findFlexAncestor(elementUnder, boundary);
|
|
1187
|
+
if (found && found.flexParent === boundary) return elementUnder;
|
|
1188
|
+
return found?.child ?? elementUnder;
|
|
1189
|
+
}
|
|
1190
|
+
function findChildAtPoint(parent, clientX, clientY) {
|
|
1191
|
+
const children = htmlChildren(parent);
|
|
1192
|
+
if (children.length === 0) return null;
|
|
1193
|
+
const hit = children.find((child) => {
|
|
1194
|
+
const r = child.getBoundingClientRect();
|
|
1195
|
+
return clientX >= r.left && clientX <= r.right && clientY >= r.top && clientY <= r.bottom;
|
|
1196
|
+
});
|
|
1197
|
+
if (hit) return hit;
|
|
1198
|
+
if (children.length === 1 && !hasDirectNonWhitespaceText(parent)) return children[0];
|
|
1199
|
+
return null;
|
|
1200
|
+
}
|
|
1142
1201
|
function elementFromPointWithoutOverlays(x, y) {
|
|
1143
1202
|
const host = document.querySelector("[data-direct-edit-host]");
|
|
1144
1203
|
if (host) host.style.display = "none";
|
|
@@ -2050,6 +2109,8 @@ ${context}`).catch(() => {
|
|
|
2050
2109
|
const previousText = existing?.textEdit?.newText ?? originalText;
|
|
2051
2110
|
editingElement.removeAttribute("contenteditable");
|
|
2052
2111
|
editingElement.removeAttribute("data-direct-edit-original-text");
|
|
2112
|
+
editingElement.style.outline = "";
|
|
2113
|
+
editingElement.style.outlineOffset = "";
|
|
2053
2114
|
editingElement.blur();
|
|
2054
2115
|
if (newText !== previousText) {
|
|
2055
2116
|
pushUndo({ type: "textEdit", element: editingElement, originalText, previousText });
|
|
@@ -2674,6 +2735,8 @@ ${exportMarkdown}`);
|
|
|
2674
2735
|
const originalText = existing?.textEdit?.originalText ?? (element.textContent ?? "");
|
|
2675
2736
|
element.setAttribute("data-direct-edit-original-text", originalText);
|
|
2676
2737
|
element.setAttribute("contenteditable", "true");
|
|
2738
|
+
element.style.outline = "1px solid #0D99FF";
|
|
2739
|
+
element.style.outlineOffset = "0px";
|
|
2677
2740
|
element.focus();
|
|
2678
2741
|
const selection = window.getSelection();
|
|
2679
2742
|
if (selection) {
|
|
@@ -3900,27 +3963,42 @@ function generateId() {
|
|
|
3900
3963
|
return `gl-${Date.now()}-${idCounter++}`;
|
|
3901
3964
|
}
|
|
3902
3965
|
var RULER_SIZE = 20;
|
|
3903
|
-
function
|
|
3904
|
-
|
|
3966
|
+
function viewportToCssCoord(hostElement, value, axis) {
|
|
3967
|
+
if (!hostElement) return value;
|
|
3968
|
+
const rect = hostElement.getBoundingClientRect();
|
|
3969
|
+
const origin = axis === "x" ? rect.left : rect.top;
|
|
3970
|
+
const size = axis === "x" ? rect.width : rect.height;
|
|
3971
|
+
const cssSize = axis === "x" ? hostElement.offsetWidth : hostElement.offsetHeight;
|
|
3972
|
+
if (size === 0) return value;
|
|
3973
|
+
return (value - origin) * (cssSize / size);
|
|
3974
|
+
}
|
|
3975
|
+
function useGuidelines(enabled, hostElement) {
|
|
3976
|
+
const [guidelines, setGuidelines] = React11.useState([]);
|
|
3977
|
+
const [hydrated, setHydrated] = React11.useState(false);
|
|
3905
3978
|
const [activeGuidelineId, setActiveGuidelineId] = React11.useState(null);
|
|
3906
3979
|
const [dragPosition, setDragPosition] = React11.useState(null);
|
|
3907
3980
|
const [isCreating, setIsCreating] = React11.useState(false);
|
|
3908
|
-
const [scrollOffset, setScrollOffset] = React11.useState({
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
});
|
|
3981
|
+
const [scrollOffset, setScrollOffset] = React11.useState({ x: 0, y: 0 });
|
|
3982
|
+
const hostRef = React11.useRef(hostElement ?? null);
|
|
3983
|
+
hostRef.current = hostElement ?? null;
|
|
3912
3984
|
const [dragging, setDragging] = React11.useState(false);
|
|
3913
3985
|
const guidelinesRef = React11.useRef(guidelines);
|
|
3914
3986
|
guidelinesRef.current = guidelines;
|
|
3915
3987
|
const dragInfoRef = React11.useRef(null);
|
|
3916
3988
|
React11.useEffect(() => {
|
|
3989
|
+
setGuidelines(loadGuidelines());
|
|
3990
|
+
setHydrated(true);
|
|
3991
|
+
}, []);
|
|
3992
|
+
React11.useEffect(() => {
|
|
3993
|
+
if (!hydrated) return;
|
|
3917
3994
|
saveGuidelines(guidelines);
|
|
3918
|
-
}, [guidelines]);
|
|
3995
|
+
}, [guidelines, hydrated]);
|
|
3919
3996
|
React11.useEffect(() => {
|
|
3920
3997
|
if (!enabled) return;
|
|
3921
3998
|
function update() {
|
|
3922
3999
|
setScrollOffset({ x: window.scrollX, y: window.scrollY });
|
|
3923
4000
|
}
|
|
4001
|
+
update();
|
|
3924
4002
|
window.addEventListener("scroll", update, true);
|
|
3925
4003
|
window.addEventListener("resize", update);
|
|
3926
4004
|
return () => {
|
|
@@ -3941,8 +4019,13 @@ function useGuidelines(enabled) {
|
|
|
3941
4019
|
const info = dragInfoRef.current;
|
|
3942
4020
|
if (!info) return;
|
|
3943
4021
|
const { guidelineId, orientation } = info;
|
|
4022
|
+
const axis = orientation === "horizontal" ? "y" : "x";
|
|
4023
|
+
function pointerToPos(e) {
|
|
4024
|
+
const raw = orientation === "horizontal" ? e.clientY : e.clientX;
|
|
4025
|
+
return viewportToCssCoord(hostRef.current, raw, axis);
|
|
4026
|
+
}
|
|
3944
4027
|
function onPointerMove(e) {
|
|
3945
|
-
const pos =
|
|
4028
|
+
const pos = pointerToPos(e);
|
|
3946
4029
|
setDragPosition(pos);
|
|
3947
4030
|
const currentScroll = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
3948
4031
|
setGuidelines(
|
|
@@ -3950,7 +4033,7 @@ function useGuidelines(enabled) {
|
|
|
3950
4033
|
);
|
|
3951
4034
|
}
|
|
3952
4035
|
function onPointerUp(e) {
|
|
3953
|
-
const pos =
|
|
4036
|
+
const pos = pointerToPos(e);
|
|
3954
4037
|
if (pos <= RULER_SIZE) {
|
|
3955
4038
|
setGuidelines((prev) => prev.filter((g) => g.id !== guidelineId));
|
|
3956
4039
|
}
|
|
@@ -3974,12 +4057,14 @@ function useGuidelines(enabled) {
|
|
|
3974
4057
|
);
|
|
3975
4058
|
const startCreate = React11.useCallback(
|
|
3976
4059
|
(orientation, viewportPosition) => {
|
|
4060
|
+
const axis = orientation === "horizontal" ? "y" : "x";
|
|
4061
|
+
const pos = viewportToCssCoord(hostRef.current, viewportPosition, axis);
|
|
3977
4062
|
const scrollPos = orientation === "horizontal" ? window.scrollY : window.scrollX;
|
|
3978
4063
|
const id = generateId();
|
|
3979
|
-
const newGuideline = { id, orientation, position:
|
|
4064
|
+
const newGuideline = { id, orientation, position: pos + scrollPos };
|
|
3980
4065
|
setGuidelines((prev) => [...prev, newGuideline]);
|
|
3981
4066
|
setActiveGuidelineId(id);
|
|
3982
|
-
setDragPosition(
|
|
4067
|
+
setDragPosition(pos);
|
|
3983
4068
|
setIsCreating(true);
|
|
3984
4069
|
dragInfoRef.current = { guidelineId: id, orientation, isCreating: true };
|
|
3985
4070
|
setDragging(true);
|
|
@@ -4052,16 +4137,20 @@ var React12 = __toESM(require("react"));
|
|
|
4052
4137
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
4053
4138
|
var BLUE3 = "#0D99FF";
|
|
4054
4139
|
var DRAG_THRESHOLD = 4;
|
|
4140
|
+
var DBLCLICK_DELAY = 300;
|
|
4055
4141
|
function SelectionOverlay({
|
|
4056
4142
|
selectedElement,
|
|
4057
4143
|
isDragging,
|
|
4058
4144
|
ghostPosition,
|
|
4059
4145
|
onMoveStart,
|
|
4060
4146
|
isTextEditing,
|
|
4061
|
-
onDoubleClick
|
|
4147
|
+
onDoubleClick,
|
|
4148
|
+
onHoverElement,
|
|
4149
|
+
onClickThrough
|
|
4062
4150
|
}) {
|
|
4063
4151
|
const [rect, setRect] = React12.useState(() => selectedElement.getBoundingClientRect());
|
|
4064
4152
|
const cleanupRef = React12.useRef(null);
|
|
4153
|
+
const clickThroughTimerRef = React12.useRef(null);
|
|
4065
4154
|
React12.useEffect(() => {
|
|
4066
4155
|
function updateRect() {
|
|
4067
4156
|
setRect(selectedElement.getBoundingClientRect());
|
|
@@ -4084,11 +4173,17 @@ function SelectionOverlay({
|
|
|
4084
4173
|
React12.useEffect(() => {
|
|
4085
4174
|
return () => {
|
|
4086
4175
|
cleanupRef.current?.();
|
|
4176
|
+
if (clickThroughTimerRef.current) clearTimeout(clickThroughTimerRef.current);
|
|
4087
4177
|
};
|
|
4088
4178
|
}, []);
|
|
4089
4179
|
const handlePointerDown = (e) => {
|
|
4180
|
+
if (e.button !== 0) return;
|
|
4090
4181
|
e.stopPropagation();
|
|
4091
4182
|
cleanupRef.current?.();
|
|
4183
|
+
if (clickThroughTimerRef.current) {
|
|
4184
|
+
clearTimeout(clickThroughTimerRef.current);
|
|
4185
|
+
clickThroughTimerRef.current = null;
|
|
4186
|
+
}
|
|
4092
4187
|
const origin = { x: e.clientX, y: e.clientY };
|
|
4093
4188
|
const savedEvent = e;
|
|
4094
4189
|
const onMove = (moveEvent) => {
|
|
@@ -4099,8 +4194,15 @@ function SelectionOverlay({
|
|
|
4099
4194
|
onMoveStart(savedEvent);
|
|
4100
4195
|
}
|
|
4101
4196
|
};
|
|
4102
|
-
const onUp = () => {
|
|
4197
|
+
const onUp = (upEvent) => {
|
|
4103
4198
|
cleanup();
|
|
4199
|
+
if (onClickThrough) {
|
|
4200
|
+
const { clientX, clientY } = upEvent;
|
|
4201
|
+
clickThroughTimerRef.current = setTimeout(() => {
|
|
4202
|
+
clickThroughTimerRef.current = null;
|
|
4203
|
+
onClickThrough(clientX, clientY);
|
|
4204
|
+
}, DBLCLICK_DELAY);
|
|
4205
|
+
}
|
|
4104
4206
|
};
|
|
4105
4207
|
const cleanup = () => {
|
|
4106
4208
|
window.removeEventListener("pointermove", onMove);
|
|
@@ -4115,7 +4217,19 @@ function SelectionOverlay({
|
|
|
4115
4217
|
e.preventDefault();
|
|
4116
4218
|
e.stopPropagation();
|
|
4117
4219
|
cleanupRef.current?.();
|
|
4118
|
-
|
|
4220
|
+
if (clickThroughTimerRef.current) {
|
|
4221
|
+
clearTimeout(clickThroughTimerRef.current);
|
|
4222
|
+
clickThroughTimerRef.current = null;
|
|
4223
|
+
}
|
|
4224
|
+
onDoubleClick?.(e.clientX, e.clientY);
|
|
4225
|
+
};
|
|
4226
|
+
const handleMouseMove = (e) => {
|
|
4227
|
+
if (!onHoverElement) return;
|
|
4228
|
+
const elementUnder = elementFromPointWithoutOverlays(e.clientX, e.clientY);
|
|
4229
|
+
onHoverElement(elementUnder);
|
|
4230
|
+
};
|
|
4231
|
+
const handleMouseLeave = () => {
|
|
4232
|
+
onHoverElement?.(null);
|
|
4119
4233
|
};
|
|
4120
4234
|
const displayX = isDragging && ghostPosition ? ghostPosition.x : rect.left;
|
|
4121
4235
|
const displayY = isDragging && ghostPosition ? ghostPosition.y : rect.top;
|
|
@@ -4132,7 +4246,7 @@ function SelectionOverlay({
|
|
|
4132
4246
|
pointerEvents: "none",
|
|
4133
4247
|
zIndex: 99996
|
|
4134
4248
|
},
|
|
4135
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4249
|
+
children: !isTextEditing && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
4136
4250
|
"rect",
|
|
4137
4251
|
{
|
|
4138
4252
|
x: displayX,
|
|
@@ -4141,7 +4255,7 @@ function SelectionOverlay({
|
|
|
4141
4255
|
height: rect.height,
|
|
4142
4256
|
fill: "transparent",
|
|
4143
4257
|
stroke: BLUE3,
|
|
4144
|
-
strokeWidth:
|
|
4258
|
+
strokeWidth: 1
|
|
4145
4259
|
}
|
|
4146
4260
|
)
|
|
4147
4261
|
}
|
|
@@ -4161,7 +4275,9 @@ function SelectionOverlay({
|
|
|
4161
4275
|
pointerEvents: "auto"
|
|
4162
4276
|
},
|
|
4163
4277
|
onPointerDown: handlePointerDown,
|
|
4164
|
-
onDoubleClick: handleDoubleClick
|
|
4278
|
+
onDoubleClick: handleDoubleClick,
|
|
4279
|
+
onMouseMove: handleMouseMove,
|
|
4280
|
+
onMouseLeave: handleMouseLeave
|
|
4165
4281
|
}
|
|
4166
4282
|
)
|
|
4167
4283
|
] });
|
|
@@ -6145,69 +6261,18 @@ function DirectEditPanelContent() {
|
|
|
6145
6261
|
onDoubleClick: (e) => {
|
|
6146
6262
|
e.preventDefault();
|
|
6147
6263
|
if (activeTool !== "select") return;
|
|
6148
|
-
const
|
|
6149
|
-
el.style.pointerEvents = "none";
|
|
6150
|
-
const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
|
|
6151
|
-
el.style.pointerEvents = textEditingElement ? "none" : "auto";
|
|
6264
|
+
const elementUnder = elementFromPointWithoutOverlays(e.clientX, e.clientY);
|
|
6152
6265
|
if (elementUnder && elementUnder !== document.body && elementUnder !== document.documentElement) {
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
if (parent) {
|
|
6158
|
-
const display = getComputedStyle(parent).display;
|
|
6159
|
-
if (display === "flex" || display === "inline-flex") {
|
|
6160
|
-
resolvedElement = current;
|
|
6161
|
-
break;
|
|
6162
|
-
}
|
|
6163
|
-
}
|
|
6164
|
-
current = parent;
|
|
6165
|
-
}
|
|
6166
|
-
if (isTextElement(resolvedElement)) {
|
|
6167
|
-
if (selectedElement !== resolvedElement) {
|
|
6168
|
-
selectElement(resolvedElement);
|
|
6169
|
-
}
|
|
6170
|
-
startTextEditing(resolvedElement);
|
|
6266
|
+
const resolved = resolveElementTarget(elementUnder, selectedElement);
|
|
6267
|
+
if (isTextElement(resolved)) {
|
|
6268
|
+
if (selectedElement !== resolved) selectElement(resolved);
|
|
6269
|
+
startTextEditing(resolved);
|
|
6171
6270
|
}
|
|
6172
6271
|
}
|
|
6173
6272
|
},
|
|
6174
6273
|
onMouseMove: (e) => {
|
|
6175
|
-
const
|
|
6176
|
-
|
|
6177
|
-
const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
|
|
6178
|
-
el.style.pointerEvents = "auto";
|
|
6179
|
-
if (elementUnder && elementUnder !== document.body && elementUnder !== document.documentElement && !elementUnder.closest("[data-direct-edit]") && !elementUnder.closest("[data-direct-edit-host]") && elementUnder !== selectedElement) {
|
|
6180
|
-
const ownDisplay = getComputedStyle(elementUnder).display;
|
|
6181
|
-
if (ownDisplay === "flex" || ownDisplay === "inline-flex") {
|
|
6182
|
-
setHoverHighlight({
|
|
6183
|
-
flexContainer: elementUnder,
|
|
6184
|
-
children: Array.from(elementUnder.children).filter(
|
|
6185
|
-
(child) => child instanceof HTMLElement
|
|
6186
|
-
)
|
|
6187
|
-
});
|
|
6188
|
-
return;
|
|
6189
|
-
}
|
|
6190
|
-
let current = elementUnder;
|
|
6191
|
-
while (current && current !== document.body) {
|
|
6192
|
-
const parent = current.parentElement;
|
|
6193
|
-
if (parent) {
|
|
6194
|
-
const display = getComputedStyle(parent).display;
|
|
6195
|
-
if (display === "flex" || display === "inline-flex") {
|
|
6196
|
-
setHoverHighlight({
|
|
6197
|
-
flexContainer: parent,
|
|
6198
|
-
children: Array.from(parent.children).filter(
|
|
6199
|
-
(child) => child instanceof HTMLElement
|
|
6200
|
-
)
|
|
6201
|
-
});
|
|
6202
|
-
return;
|
|
6203
|
-
}
|
|
6204
|
-
}
|
|
6205
|
-
current = parent;
|
|
6206
|
-
}
|
|
6207
|
-
setHoverHighlight({ flexContainer: elementUnder, children: [] });
|
|
6208
|
-
} else {
|
|
6209
|
-
setHoverHighlight(null);
|
|
6210
|
-
}
|
|
6274
|
+
const elementUnder = elementFromPointWithoutOverlays(e.clientX, e.clientY);
|
|
6275
|
+
setHoverHighlight(computeHoverHighlight(elementUnder, selectedElement));
|
|
6211
6276
|
},
|
|
6212
6277
|
onMouseLeave: () => setHoverHighlight(null),
|
|
6213
6278
|
onClick: (e) => {
|
|
@@ -6217,29 +6282,11 @@ function DirectEditPanelContent() {
|
|
|
6217
6282
|
setActiveCommentId(null);
|
|
6218
6283
|
return;
|
|
6219
6284
|
}
|
|
6220
|
-
const
|
|
6221
|
-
el.style.pointerEvents = "none";
|
|
6222
|
-
const elementUnder = document.elementFromPoint(e.clientX, e.clientY);
|
|
6223
|
-
el.style.pointerEvents = "auto";
|
|
6285
|
+
const elementUnder = elementFromPointWithoutOverlays(e.clientX, e.clientY);
|
|
6224
6286
|
if (elementUnder && elementUnder !== document.body && elementUnder !== document.documentElement) {
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
const parent = current.parentElement;
|
|
6229
|
-
if (parent) {
|
|
6230
|
-
const display = getComputedStyle(parent).display;
|
|
6231
|
-
if (display === "flex" || display === "inline-flex") {
|
|
6232
|
-
resolvedElement = current;
|
|
6233
|
-
break;
|
|
6234
|
-
}
|
|
6235
|
-
}
|
|
6236
|
-
current = parent;
|
|
6237
|
-
}
|
|
6238
|
-
if (activeTool === "comment") {
|
|
6239
|
-
addComment(resolvedElement, { x: e.clientX, y: e.clientY });
|
|
6240
|
-
} else {
|
|
6241
|
-
selectElement(resolvedElement);
|
|
6242
|
-
}
|
|
6287
|
+
const resolved = resolveElementTarget(elementUnder, selectedElement);
|
|
6288
|
+
if (activeTool === "comment") addComment(resolved, { x: e.clientX, y: e.clientY });
|
|
6289
|
+
else selectElement(resolved);
|
|
6243
6290
|
}
|
|
6244
6291
|
}
|
|
6245
6292
|
}
|
|
@@ -6328,9 +6375,36 @@ function DirectEditPanelContent() {
|
|
|
6328
6375
|
ghostPosition: dragState.ghostPosition,
|
|
6329
6376
|
onMoveStart: handleMoveStart,
|
|
6330
6377
|
isTextEditing: Boolean(textEditingElement),
|
|
6331
|
-
onDoubleClick: () => {
|
|
6332
|
-
if (selectedElement)
|
|
6378
|
+
onDoubleClick: (clientX, clientY) => {
|
|
6379
|
+
if (!selectedElement) return;
|
|
6380
|
+
if (isTextElement(selectedElement)) {
|
|
6333
6381
|
startTextEditing(selectedElement);
|
|
6382
|
+
return;
|
|
6383
|
+
}
|
|
6384
|
+
const elementUnder = elementFromPointWithoutOverlays(clientX, clientY);
|
|
6385
|
+
if (elementUnder && elementUnder !== selectedElement && selectedElement.contains(elementUnder)) {
|
|
6386
|
+
const resolved = resolveElementTarget(elementUnder, selectedElement);
|
|
6387
|
+
if (isTextElement(resolved)) {
|
|
6388
|
+
selectElement(resolved);
|
|
6389
|
+
startTextEditing(resolved);
|
|
6390
|
+
}
|
|
6391
|
+
}
|
|
6392
|
+
},
|
|
6393
|
+
onHoverElement: (element) => {
|
|
6394
|
+
setHoverHighlight(computeHoverHighlight(element, selectedElement));
|
|
6395
|
+
},
|
|
6396
|
+
onClickThrough: (clientX, clientY) => {
|
|
6397
|
+
if (!selectedElement) return;
|
|
6398
|
+
const elementUnder = elementFromPointWithoutOverlays(clientX, clientY);
|
|
6399
|
+
if (!elementUnder) return;
|
|
6400
|
+
if (elementUnder !== selectedElement && selectedElement.contains(elementUnder)) {
|
|
6401
|
+
const resolved = resolveElementTarget(elementUnder, selectedElement);
|
|
6402
|
+
selectElement(resolved);
|
|
6403
|
+
return;
|
|
6404
|
+
}
|
|
6405
|
+
const child = findChildAtPoint(selectedElement, clientX, clientY);
|
|
6406
|
+
if (child) {
|
|
6407
|
+
selectElement(child);
|
|
6334
6408
|
}
|
|
6335
6409
|
}
|
|
6336
6410
|
}
|
|
@@ -6414,11 +6488,10 @@ var RULER_SIZE2 = 20;
|
|
|
6414
6488
|
var GUIDELINE_COLOR = "#FF6B6B";
|
|
6415
6489
|
var HIT_ZONE = 9;
|
|
6416
6490
|
function useRulerColors() {
|
|
6417
|
-
const [dark, setDark] = React15.useState(
|
|
6418
|
-
() => typeof window !== "undefined" && window.matchMedia("(prefers-color-scheme: dark)").matches
|
|
6419
|
-
);
|
|
6491
|
+
const [dark, setDark] = React15.useState(false);
|
|
6420
6492
|
React15.useEffect(() => {
|
|
6421
6493
|
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
6494
|
+
setDark(mq.matches);
|
|
6422
6495
|
const handler = (e) => setDark(e.matches);
|
|
6423
6496
|
mq.addEventListener("change", handler);
|
|
6424
6497
|
return () => mq.removeEventListener("change", handler);
|
|
@@ -6451,12 +6524,13 @@ function HorizontalRuler({
|
|
|
6451
6524
|
const canvas = canvasRef.current;
|
|
6452
6525
|
if (!canvas) return;
|
|
6453
6526
|
const dpr = window.devicePixelRatio || 1;
|
|
6454
|
-
const width = viewportWidth - RULER_SIZE2;
|
|
6527
|
+
const width = Math.max(0, viewportWidth - RULER_SIZE2);
|
|
6455
6528
|
const height = RULER_SIZE2;
|
|
6456
6529
|
canvas.width = width * dpr;
|
|
6457
6530
|
canvas.height = height * dpr;
|
|
6458
6531
|
canvas.style.width = `${width}px`;
|
|
6459
6532
|
canvas.style.height = `${height}px`;
|
|
6533
|
+
if (width === 0) return;
|
|
6460
6534
|
const ctx = canvas.getContext("2d");
|
|
6461
6535
|
if (!ctx) return;
|
|
6462
6536
|
ctx.scale(dpr, dpr);
|
|
@@ -6515,11 +6589,12 @@ function VerticalRuler({
|
|
|
6515
6589
|
if (!canvas) return;
|
|
6516
6590
|
const dpr = window.devicePixelRatio || 1;
|
|
6517
6591
|
const width = RULER_SIZE2;
|
|
6518
|
-
const height = viewportHeight - RULER_SIZE2;
|
|
6592
|
+
const height = Math.max(0, viewportHeight - RULER_SIZE2);
|
|
6519
6593
|
canvas.width = width * dpr;
|
|
6520
6594
|
canvas.height = height * dpr;
|
|
6521
6595
|
canvas.style.width = `${width}px`;
|
|
6522
6596
|
canvas.style.height = `${height}px`;
|
|
6597
|
+
if (height === 0) return;
|
|
6523
6598
|
const ctx = canvas.getContext("2d");
|
|
6524
6599
|
if (!ctx) return;
|
|
6525
6600
|
ctx.scale(dpr, dpr);
|
|
@@ -6723,8 +6798,9 @@ function GuidelineLine({
|
|
|
6723
6798
|
] });
|
|
6724
6799
|
}
|
|
6725
6800
|
function useViewportWidth() {
|
|
6726
|
-
const [width, setWidth] = React15.useState(
|
|
6801
|
+
const [width, setWidth] = React15.useState(0);
|
|
6727
6802
|
React15.useEffect(() => {
|
|
6803
|
+
setWidth(window.innerWidth);
|
|
6728
6804
|
const onResize = () => setWidth(window.innerWidth);
|
|
6729
6805
|
window.addEventListener("resize", onResize);
|
|
6730
6806
|
return () => window.removeEventListener("resize", onResize);
|
|
@@ -6732,8 +6808,9 @@ function useViewportWidth() {
|
|
|
6732
6808
|
return width;
|
|
6733
6809
|
}
|
|
6734
6810
|
function useViewportHeight() {
|
|
6735
|
-
const [height, setHeight] = React15.useState(
|
|
6811
|
+
const [height, setHeight] = React15.useState(0);
|
|
6736
6812
|
React15.useEffect(() => {
|
|
6813
|
+
setHeight(window.innerHeight);
|
|
6737
6814
|
const onResize = () => setHeight(window.innerHeight);
|
|
6738
6815
|
window.addEventListener("resize", onResize);
|
|
6739
6816
|
return () => window.removeEventListener("resize", onResize);
|
|
@@ -6742,6 +6819,12 @@ function useViewportHeight() {
|
|
|
6742
6819
|
}
|
|
6743
6820
|
function RulersOverlay({ enabled }) {
|
|
6744
6821
|
const container = usePortalContainer();
|
|
6822
|
+
const hostElement = React15.useMemo(() => {
|
|
6823
|
+
if (!container) return null;
|
|
6824
|
+
const root = container.getRootNode();
|
|
6825
|
+
if (root instanceof ShadowRoot) return root.host;
|
|
6826
|
+
return null;
|
|
6827
|
+
}, [container]);
|
|
6745
6828
|
const {
|
|
6746
6829
|
guidelines,
|
|
6747
6830
|
activeGuideline,
|
|
@@ -6750,7 +6833,7 @@ function RulersOverlay({ enabled }) {
|
|
|
6750
6833
|
startCreate,
|
|
6751
6834
|
startDrag,
|
|
6752
6835
|
deleteGuideline
|
|
6753
|
-
} = useGuidelines(enabled);
|
|
6836
|
+
} = useGuidelines(enabled, hostElement);
|
|
6754
6837
|
if (!enabled || !container) return null;
|
|
6755
6838
|
const handleHorizontalPointerDown = (e) => {
|
|
6756
6839
|
e.preventDefault();
|
|
@@ -6784,14 +6867,13 @@ function RulersOverlay({ enabled }) {
|
|
|
6784
6867
|
var RULERS_VISIBLE_KEY = "direct-edit-rulers-visible";
|
|
6785
6868
|
var RULERS_TOGGLE_EVENT = "direct-edit-rulers-toggle";
|
|
6786
6869
|
function useRulersVisible() {
|
|
6787
|
-
const [visible, setVisible] = React15.useState(
|
|
6788
|
-
|
|
6870
|
+
const [visible, setVisible] = React15.useState(true);
|
|
6871
|
+
React15.useEffect(() => {
|
|
6789
6872
|
try {
|
|
6790
|
-
|
|
6873
|
+
if (localStorage.getItem(RULERS_VISIBLE_KEY) === "false") setVisible(false);
|
|
6791
6874
|
} catch {
|
|
6792
|
-
return true;
|
|
6793
6875
|
}
|
|
6794
|
-
});
|
|
6876
|
+
}, []);
|
|
6795
6877
|
React15.useEffect(() => {
|
|
6796
6878
|
function handler(e) {
|
|
6797
6879
|
setVisible(e.detail);
|
|
@@ -6819,6 +6901,9 @@ function Rulers() {
|
|
|
6819
6901
|
if (!editModeActive) return;
|
|
6820
6902
|
function handleKeyDown(e) {
|
|
6821
6903
|
if (e.shiftKey && e.key === "R" && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
|
6904
|
+
const active = document.activeElement;
|
|
6905
|
+
const isInput = active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement || active instanceof HTMLElement && active.isContentEditable;
|
|
6906
|
+
if (isInput) return;
|
|
6822
6907
|
e.preventDefault();
|
|
6823
6908
|
toggleRulers();
|
|
6824
6909
|
}
|