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 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-DNTIJ83m.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-DNTIJ83m.mjs';
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-DNTIJ83m.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-DNTIJ83m.js';
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 useGuidelines(enabled) {
3904
- const [guidelines, setGuidelines] = React11.useState(loadGuidelines);
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
- x: typeof window !== "undefined" ? window.scrollX : 0,
3910
- y: typeof window !== "undefined" ? window.scrollY : 0
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 = orientation === "horizontal" ? e.clientY : e.clientX;
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 = orientation === "horizontal" ? e.clientY : e.clientX;
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: viewportPosition + scrollPos };
4064
+ const newGuideline = { id, orientation, position: pos + scrollPos };
3980
4065
  setGuidelines((prev) => [...prev, newGuideline]);
3981
4066
  setActiveGuidelineId(id);
3982
- setDragPosition(viewportPosition);
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
- onDoubleClick?.();
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: 2
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 el = e.currentTarget;
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
- let resolvedElement = elementUnder;
6154
- let current = elementUnder;
6155
- while (current && current !== document.body) {
6156
- const parent = current.parentElement;
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 el = e.currentTarget;
6176
- el.style.pointerEvents = "none";
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 el = e.currentTarget;
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
- let resolvedElement = elementUnder;
6226
- let current = elementUnder;
6227
- while (current && current !== document.body) {
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(typeof window !== "undefined" ? window.innerWidth : 0);
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(typeof window !== "undefined" ? window.innerHeight : 0);
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
- if (typeof window === "undefined") return true;
6870
+ const [visible, setVisible] = React15.useState(true);
6871
+ React15.useEffect(() => {
6789
6872
  try {
6790
- return localStorage.getItem(RULERS_VISIBLE_KEY) !== "false";
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
  }