@aznabee/freehand-ui 0.1.7 → 0.2.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/react.cjs CHANGED
@@ -317,6 +317,10 @@ var DEFAULT_OPTIONS = {
317
317
  */
318
318
  zIndex: null
319
319
  };
320
+ var OVERLAY_CLASS = "doodle-ui-overlay";
321
+ function isOverlayNode(node) {
322
+ return node?.classList?.contains(OVERLAY_CLASS) ?? false;
323
+ }
320
324
  function resolveElement(target) {
321
325
  if (!target) return null;
322
326
  if (typeof target === "string") {
@@ -422,45 +426,21 @@ function resolveOverlayZIndex(element, override) {
422
426
  }
423
427
  return null;
424
428
  }
425
- var ITEM_PLACEMENT_PROPERTIES = [
426
- "order",
427
- "flexGrow",
428
- "flexShrink",
429
- "flexBasis",
430
- "alignSelf",
431
- "justifySelf",
432
- "gridColumn",
433
- "gridRow",
434
- "gridArea"
435
- ];
436
- function isInlineDisplay(computed) {
437
- return computed.display.startsWith("inline");
438
- }
439
429
  function insertOverlaySvg(svg, element) {
440
- const parent = element.parentNode;
441
- if (!parent) {
442
- document.body.appendChild(svg);
443
- return null;
444
- }
445
- const wrapper = document.createElement("div");
446
- wrapper.style.position = "relative";
447
- const computed = getComputedStyle(element);
448
- wrapper.style.display = isInlineDisplay(computed) ? "inline-block" : "block";
449
- for (const property of ITEM_PLACEMENT_PROPERTIES) {
450
- const value = computed[property];
451
- if (value) wrapper.style[property] = value;
452
- }
453
- parent.replaceChild(wrapper, element);
454
- wrapper.appendChild(element);
455
- wrapper.appendChild(svg);
456
- return wrapper;
457
- }
458
- function removeOverlaySvg(svg, wrapper, element) {
430
+ const setPosition = getComputedStyle(element).position === "static";
431
+ if (setPosition) {
432
+ element.style.position = "relative";
433
+ }
434
+ element.appendChild(svg);
435
+ return setPosition;
436
+ }
437
+ function removeOverlaySvg(svg, element, clearPosition) {
459
438
  if (svg.parentNode) {
460
439
  svg.parentNode.removeChild(svg);
461
440
  }
462
- if (!wrapper || !wrapper.parentNode) return;
463
- wrapper.parentNode.replaceChild(element, wrapper);
441
+ if (clearPosition) {
442
+ element.style.position = "";
443
+ }
464
444
  }
465
445
  function syncOverlayStacking(svg, element, zIndexOverride) {
466
446
  const zIndex = resolveOverlayZIndex(element, zIndexOverride);
@@ -487,7 +467,10 @@ function averageCornerRadius(element) {
487
467
  function detectBorderRadius(element) {
488
468
  const own = averageCornerRadius(element);
489
469
  if (own > 0) return own;
490
- const child = element.children.length === 1 ? element.firstElementChild : null;
470
+ const content = Array.from(element.children).filter(
471
+ (node) => !isOverlayNode(node)
472
+ );
473
+ const child = content.length === 1 ? content[0] : null;
491
474
  if (!child) return 0;
492
475
  const outer = element.getBoundingClientRect();
493
476
  const inner = child.getBoundingClientRect();
@@ -518,22 +501,6 @@ function relativeRect(outer, inner) {
518
501
  radius: inner.radius
519
502
  };
520
503
  }
521
- function unionRects(rects, margin = 0) {
522
- if (rects.length === 0) {
523
- return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
524
- }
525
- const minX = Math.min(...rects.map((r) => r.x)) - margin;
526
- const minY = Math.min(...rects.map((r) => r.y)) - margin;
527
- const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
528
- const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
529
- return {
530
- x: minX,
531
- y: minY,
532
- width: maxX - minX,
533
- height: maxY - minY,
534
- radius: 0
535
- };
536
- }
537
504
  function inflateRect(rect, amount) {
538
505
  return {
539
506
  x: rect.x - amount,
@@ -615,8 +582,13 @@ function annotationAnchor(position, rect, offset = 12) {
615
582
  return point;
616
583
  }
617
584
 
618
- // src/renderer.js
585
+ // src/svg-dom.js
619
586
  var SVG_NS = "http://www.w3.org/2000/svg";
587
+ function createSvgElement(tag) {
588
+ return document.createElementNS(SVG_NS, tag);
589
+ }
590
+
591
+ // src/renderer.js
620
592
  var XML_NS = "http://www.w3.org/XML/1998/namespace";
621
593
  var HANDWRITTEN_FONT = '"Caveat", "Kalam", "Patrick Hand", "Bradley Hand", "Segoe Script", "Comic Sans MS", cursive';
622
594
  var NOTE_FONT_SIZE = 19;
@@ -840,7 +812,7 @@ function createBorderBreaks(perimeter, config, random) {
840
812
  return breaks;
841
813
  }
842
814
  function createGroup(parent, x, y, rotation = 0) {
843
- const group = document.createElementNS(SVG_NS, "g");
815
+ const group = createSvgElement("g");
844
816
  group.setAttribute(
845
817
  "transform",
846
818
  `translate(${fmt(x)} ${fmt(y)}) rotate(${rotation.toFixed(1)})`
@@ -849,7 +821,7 @@ function createGroup(parent, x, y, rotation = 0) {
849
821
  return group;
850
822
  }
851
823
  function appendPath(svg, d, style) {
852
- const path = document.createElementNS(SVG_NS, "path");
824
+ const path = createSvgElement("path");
853
825
  path.setAttribute("d", d);
854
826
  path.setAttribute("fill", style.fill ?? "none");
855
827
  path.setAttribute("stroke", style.color);
@@ -864,7 +836,7 @@ function appendPath(svg, d, style) {
864
836
  return path;
865
837
  }
866
838
  function appendGlow(svg, radius, style) {
867
- const circle = document.createElementNS(SVG_NS, "circle");
839
+ const circle = createSvgElement("circle");
868
840
  circle.setAttribute("r", fmt(radius));
869
841
  circle.setAttribute("fill", style.color);
870
842
  circle.setAttribute("opacity", String(style.opacity));
@@ -1168,7 +1140,7 @@ function drawArrow(svg, rect, arrowOptions, style, seed, origin = null, context
1168
1140
  tipAngle = Math.atan2(end.y - c2y, end.x - c2x);
1169
1141
  }
1170
1142
  }
1171
- const group = document.createElementNS(SVG_NS, "g");
1143
+ const group = createSvgElement("g");
1172
1144
  svg.appendChild(group);
1173
1145
  const shaftPaths = [];
1174
1146
  if (ghost) {
@@ -1258,8 +1230,8 @@ function createNoteText(svg, text, style, options = {}) {
1258
1230
  const lines = wrapWords(text, options.wordsPerLine ?? DEFAULT_WORDS_PER_LINE);
1259
1231
  const lineHeight = fontSize * 1.05;
1260
1232
  const rtl = options.rtl ?? isRtlText(text);
1261
- const group = document.createElementNS(SVG_NS, "g");
1262
- const textEl = document.createElementNS(SVG_NS, "text");
1233
+ const group = createSvgElement("g");
1234
+ const textEl = createSvgElement("text");
1263
1235
  textEl.setAttribute("x", "0");
1264
1236
  textEl.setAttribute("y", "0");
1265
1237
  textEl.setAttribute("fill", style.color);
@@ -1278,7 +1250,7 @@ function createNoteText(svg, text, style, options = {}) {
1278
1250
  textEl.setAttributeNS(XML_NS, "xml:lang", options.locale);
1279
1251
  }
1280
1252
  const tspans = lines.map((line, index) => {
1281
- const tspan = document.createElementNS(SVG_NS, "tspan");
1253
+ const tspan = createSvgElement("tspan");
1282
1254
  tspan.textContent = line;
1283
1255
  tspan.setAttribute("x", "0");
1284
1256
  tspan.setAttribute("dy", index === 0 ? "0" : String(lineHeight));
@@ -1342,8 +1314,8 @@ function placeNoteText(note, box, style, seed, options = {}) {
1342
1314
  return note.group;
1343
1315
  }
1344
1316
  function createOverlaySvg(left, top, width, height) {
1345
- const svg = document.createElementNS(SVG_NS, "svg");
1346
- svg.setAttribute("class", "doodle-ui-overlay");
1317
+ const svg = createSvgElement("svg");
1318
+ svg.setAttribute("class", OVERLAY_CLASS);
1347
1319
  svg.setAttribute("xmlns", SVG_NS);
1348
1320
  svg.setAttribute("width", String(width));
1349
1321
  svg.setAttribute("height", String(height));
@@ -1885,13 +1857,27 @@ var instances = /* @__PURE__ */ new WeakMap();
1885
1857
  function now() {
1886
1858
  return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1887
1859
  }
1888
- function localBand(overlayRect, inset = 8) {
1860
+ function localBand(originLeft, inset = 8) {
1889
1861
  const width = window.innerWidth || document.documentElement.clientWidth || 0;
1890
1862
  return {
1891
- x: -overlayRect.x + inset,
1863
+ x: -originLeft + inset,
1892
1864
  width: Math.max(0, width - inset * 2)
1893
1865
  };
1894
1866
  }
1867
+ function paddingBox(element) {
1868
+ const rect = element.getBoundingClientRect();
1869
+ const style = getComputedStyle(element);
1870
+ const left = parseFloat(style.borderLeftWidth) || 0;
1871
+ const top = parseFloat(style.borderTopWidth) || 0;
1872
+ const right = parseFloat(style.borderRightWidth) || 0;
1873
+ const bottom = parseFloat(style.borderBottomWidth) || 0;
1874
+ return {
1875
+ left: rect.left + left,
1876
+ top: rect.top + top,
1877
+ width: Math.max(0, rect.width - left - right),
1878
+ height: Math.max(0, rect.height - top - bottom)
1879
+ };
1880
+ }
1895
1881
  var DoodleOverlay = class {
1896
1882
  /**
1897
1883
  * @param {Element} element
@@ -1903,7 +1889,7 @@ var DoodleOverlay = class {
1903
1889
  this.seed = Math.floor(Math.random() * 1e9);
1904
1890
  this.startedAt = now();
1905
1891
  this.svg = null;
1906
- this.wrapper = null;
1892
+ this.setPosition = false;
1907
1893
  this.resizeObserver = null;
1908
1894
  this.mutationObserver = null;
1909
1895
  this.pendingFrame = null;
@@ -1915,14 +1901,17 @@ var DoodleOverlay = class {
1915
1901
  }
1916
1902
  mount() {
1917
1903
  this.svg = createOverlaySvg(0, 0, 0, 0);
1918
- this.wrapper = insertOverlaySvg(this.svg, this.element);
1904
+ this.setPosition = insertOverlaySvg(this.svg, this.element);
1919
1905
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1920
1906
  this.resizeObserver = new ResizeObserver(this.onResize);
1921
1907
  this.resizeObserver.observe(this.element);
1922
1908
  if (this.options.children) {
1923
1909
  this.observeChildren();
1924
1910
  }
1925
- this.mutationObserver = new MutationObserver(this.scheduleUpdate.bind(this));
1911
+ this.mutationObserver = new MutationObserver((records) => {
1912
+ const relevant = records.some((record) => !this.svg.contains(record.target));
1913
+ if (relevant) this.scheduleUpdate();
1914
+ });
1926
1915
  this.mutationObserver.observe(this.element, {
1927
1916
  childList: true,
1928
1917
  subtree: true,
@@ -1974,22 +1963,23 @@ var DoodleOverlay = class {
1974
1963
  if (!this.svg || !this.element.isConnected) return;
1975
1964
  const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
1976
1965
  const targets = this.getTargets();
1977
- const margin = this.overlayMargin();
1978
1966
  const elapsed = now() - this.startedAt;
1979
1967
  const absoluteRects = targets.map(
1980
1968
  (target) => getElementBounds(target, padding, radius)
1981
1969
  );
1982
- const overlayRect = unionRects(absoluteRects, margin);
1983
1970
  clearSvg(this.svg);
1984
1971
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1985
- const origin = this.wrapper ? this.wrapper.getBoundingClientRect() : { left: 0, top: 0 };
1986
- this.svg.setAttribute("width", String(overlayRect.width));
1987
- this.svg.setAttribute("height", String(overlayRect.height));
1988
- this.svg.setAttribute("viewBox", `0 0 ${overlayRect.width} ${overlayRect.height}`);
1989
- this.svg.style.left = `${overlayRect.x - origin.left}px`;
1990
- this.svg.style.top = `${overlayRect.y - origin.top}px`;
1991
- this.svg.style.width = `${overlayRect.width}px`;
1992
- this.svg.style.height = `${overlayRect.height}px`;
1972
+ const box = paddingBox(this.element);
1973
+ const width = Math.max(1, box.width);
1974
+ const height = Math.max(1, box.height);
1975
+ const origin = { x: box.left, y: box.top };
1976
+ this.svg.setAttribute("width", String(width));
1977
+ this.svg.setAttribute("height", String(height));
1978
+ this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
1979
+ this.svg.style.left = "0px";
1980
+ this.svg.style.top = "0px";
1981
+ this.svg.style.width = `${width}px`;
1982
+ this.svg.style.height = `${height}px`;
1993
1983
  const strokeStyle = { color, strokeWidth, roughness, opacity };
1994
1984
  const noteStyle = {
1995
1985
  color,
@@ -2000,12 +1990,12 @@ var DoodleOverlay = class {
2000
1990
  };
2001
1991
  const noteGroups = [];
2002
1992
  const noteLayout = {
2003
- band: localBand(overlayRect),
1993
+ band: localBand(origin.x),
2004
1994
  gap: this.options.arrow ? 40 : 14
2005
1995
  };
2006
1996
  targets.forEach((target, index) => {
2007
1997
  const absolute = absoluteRects[index];
2008
- const local = relativeRect(overlayRect, absolute);
1998
+ const local = relativeRect(origin, absolute);
2009
1999
  const seed = this.seed + index * 31;
2010
2000
  const note = this.options.note && index === 0 ? renderAnnotation(
2011
2001
  this.svg,
@@ -2051,15 +2041,6 @@ var DoodleOverlay = class {
2051
2041
  this.svg.appendChild(group);
2052
2042
  }
2053
2043
  }
2054
- /**
2055
- * Room the overlay needs beyond the element for notes, arrows and decorations.
2056
- */
2057
- overlayMargin() {
2058
- const { note, arrow, decorations } = this.options;
2059
- if (!note && !arrow && !decorations) return 48;
2060
- const { text } = resolveLocalizedText(note?.text, note?.locale);
2061
- return Math.max(96, Math.min(240, 80 + text.length * 8));
2062
- }
2063
2044
  destroy() {
2064
2045
  if (this.pendingFrame != null) {
2065
2046
  cancelFrame(this.pendingFrame);
@@ -2082,10 +2063,9 @@ var DoodleOverlay = class {
2082
2063
  }
2083
2064
  this.listeners = [];
2084
2065
  if (this.svg) {
2085
- removeOverlaySvg(this.svg, this.wrapper, this.element);
2066
+ removeOverlaySvg(this.svg, this.element, this.setPosition);
2086
2067
  }
2087
2068
  this.svg = null;
2088
- this.wrapper = null;
2089
2069
  instances.delete(this.element);
2090
2070
  }
2091
2071
  };
package/dist/react.js CHANGED
@@ -300,6 +300,10 @@ var DEFAULT_OPTIONS = {
300
300
  */
301
301
  zIndex: null
302
302
  };
303
+ var OVERLAY_CLASS = "doodle-ui-overlay";
304
+ function isOverlayNode(node) {
305
+ return node?.classList?.contains(OVERLAY_CLASS) ?? false;
306
+ }
303
307
  function resolveElement(target) {
304
308
  if (!target) return null;
305
309
  if (typeof target === "string") {
@@ -405,45 +409,21 @@ function resolveOverlayZIndex(element, override) {
405
409
  }
406
410
  return null;
407
411
  }
408
- var ITEM_PLACEMENT_PROPERTIES = [
409
- "order",
410
- "flexGrow",
411
- "flexShrink",
412
- "flexBasis",
413
- "alignSelf",
414
- "justifySelf",
415
- "gridColumn",
416
- "gridRow",
417
- "gridArea"
418
- ];
419
- function isInlineDisplay(computed) {
420
- return computed.display.startsWith("inline");
421
- }
422
412
  function insertOverlaySvg(svg, element) {
423
- const parent = element.parentNode;
424
- if (!parent) {
425
- document.body.appendChild(svg);
426
- return null;
427
- }
428
- const wrapper = document.createElement("div");
429
- wrapper.style.position = "relative";
430
- const computed = getComputedStyle(element);
431
- wrapper.style.display = isInlineDisplay(computed) ? "inline-block" : "block";
432
- for (const property of ITEM_PLACEMENT_PROPERTIES) {
433
- const value = computed[property];
434
- if (value) wrapper.style[property] = value;
435
- }
436
- parent.replaceChild(wrapper, element);
437
- wrapper.appendChild(element);
438
- wrapper.appendChild(svg);
439
- return wrapper;
440
- }
441
- function removeOverlaySvg(svg, wrapper, element) {
413
+ const setPosition = getComputedStyle(element).position === "static";
414
+ if (setPosition) {
415
+ element.style.position = "relative";
416
+ }
417
+ element.appendChild(svg);
418
+ return setPosition;
419
+ }
420
+ function removeOverlaySvg(svg, element, clearPosition) {
442
421
  if (svg.parentNode) {
443
422
  svg.parentNode.removeChild(svg);
444
423
  }
445
- if (!wrapper || !wrapper.parentNode) return;
446
- wrapper.parentNode.replaceChild(element, wrapper);
424
+ if (clearPosition) {
425
+ element.style.position = "";
426
+ }
447
427
  }
448
428
  function syncOverlayStacking(svg, element, zIndexOverride) {
449
429
  const zIndex = resolveOverlayZIndex(element, zIndexOverride);
@@ -470,7 +450,10 @@ function averageCornerRadius(element) {
470
450
  function detectBorderRadius(element) {
471
451
  const own = averageCornerRadius(element);
472
452
  if (own > 0) return own;
473
- const child = element.children.length === 1 ? element.firstElementChild : null;
453
+ const content = Array.from(element.children).filter(
454
+ (node) => !isOverlayNode(node)
455
+ );
456
+ const child = content.length === 1 ? content[0] : null;
474
457
  if (!child) return 0;
475
458
  const outer = element.getBoundingClientRect();
476
459
  const inner = child.getBoundingClientRect();
@@ -501,22 +484,6 @@ function relativeRect(outer, inner) {
501
484
  radius: inner.radius
502
485
  };
503
486
  }
504
- function unionRects(rects, margin = 0) {
505
- if (rects.length === 0) {
506
- return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
507
- }
508
- const minX = Math.min(...rects.map((r) => r.x)) - margin;
509
- const minY = Math.min(...rects.map((r) => r.y)) - margin;
510
- const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
511
- const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
512
- return {
513
- x: minX,
514
- y: minY,
515
- width: maxX - minX,
516
- height: maxY - minY,
517
- radius: 0
518
- };
519
- }
520
487
  function inflateRect(rect, amount) {
521
488
  return {
522
489
  x: rect.x - amount,
@@ -598,8 +565,13 @@ function annotationAnchor(position, rect, offset = 12) {
598
565
  return point;
599
566
  }
600
567
 
601
- // src/renderer.js
568
+ // src/svg-dom.js
602
569
  var SVG_NS = "http://www.w3.org/2000/svg";
570
+ function createSvgElement(tag) {
571
+ return document.createElementNS(SVG_NS, tag);
572
+ }
573
+
574
+ // src/renderer.js
603
575
  var XML_NS = "http://www.w3.org/XML/1998/namespace";
604
576
  var HANDWRITTEN_FONT = '"Caveat", "Kalam", "Patrick Hand", "Bradley Hand", "Segoe Script", "Comic Sans MS", cursive';
605
577
  var NOTE_FONT_SIZE = 19;
@@ -823,7 +795,7 @@ function createBorderBreaks(perimeter, config, random) {
823
795
  return breaks;
824
796
  }
825
797
  function createGroup(parent, x, y, rotation = 0) {
826
- const group = document.createElementNS(SVG_NS, "g");
798
+ const group = createSvgElement("g");
827
799
  group.setAttribute(
828
800
  "transform",
829
801
  `translate(${fmt(x)} ${fmt(y)}) rotate(${rotation.toFixed(1)})`
@@ -832,7 +804,7 @@ function createGroup(parent, x, y, rotation = 0) {
832
804
  return group;
833
805
  }
834
806
  function appendPath(svg, d, style) {
835
- const path = document.createElementNS(SVG_NS, "path");
807
+ const path = createSvgElement("path");
836
808
  path.setAttribute("d", d);
837
809
  path.setAttribute("fill", style.fill ?? "none");
838
810
  path.setAttribute("stroke", style.color);
@@ -847,7 +819,7 @@ function appendPath(svg, d, style) {
847
819
  return path;
848
820
  }
849
821
  function appendGlow(svg, radius, style) {
850
- const circle = document.createElementNS(SVG_NS, "circle");
822
+ const circle = createSvgElement("circle");
851
823
  circle.setAttribute("r", fmt(radius));
852
824
  circle.setAttribute("fill", style.color);
853
825
  circle.setAttribute("opacity", String(style.opacity));
@@ -1151,7 +1123,7 @@ function drawArrow(svg, rect, arrowOptions, style, seed, origin = null, context
1151
1123
  tipAngle = Math.atan2(end.y - c2y, end.x - c2x);
1152
1124
  }
1153
1125
  }
1154
- const group = document.createElementNS(SVG_NS, "g");
1126
+ const group = createSvgElement("g");
1155
1127
  svg.appendChild(group);
1156
1128
  const shaftPaths = [];
1157
1129
  if (ghost) {
@@ -1241,8 +1213,8 @@ function createNoteText(svg, text, style, options = {}) {
1241
1213
  const lines = wrapWords(text, options.wordsPerLine ?? DEFAULT_WORDS_PER_LINE);
1242
1214
  const lineHeight = fontSize * 1.05;
1243
1215
  const rtl = options.rtl ?? isRtlText(text);
1244
- const group = document.createElementNS(SVG_NS, "g");
1245
- const textEl = document.createElementNS(SVG_NS, "text");
1216
+ const group = createSvgElement("g");
1217
+ const textEl = createSvgElement("text");
1246
1218
  textEl.setAttribute("x", "0");
1247
1219
  textEl.setAttribute("y", "0");
1248
1220
  textEl.setAttribute("fill", style.color);
@@ -1261,7 +1233,7 @@ function createNoteText(svg, text, style, options = {}) {
1261
1233
  textEl.setAttributeNS(XML_NS, "xml:lang", options.locale);
1262
1234
  }
1263
1235
  const tspans = lines.map((line, index) => {
1264
- const tspan = document.createElementNS(SVG_NS, "tspan");
1236
+ const tspan = createSvgElement("tspan");
1265
1237
  tspan.textContent = line;
1266
1238
  tspan.setAttribute("x", "0");
1267
1239
  tspan.setAttribute("dy", index === 0 ? "0" : String(lineHeight));
@@ -1325,8 +1297,8 @@ function placeNoteText(note, box, style, seed, options = {}) {
1325
1297
  return note.group;
1326
1298
  }
1327
1299
  function createOverlaySvg(left, top, width, height) {
1328
- const svg = document.createElementNS(SVG_NS, "svg");
1329
- svg.setAttribute("class", "doodle-ui-overlay");
1300
+ const svg = createSvgElement("svg");
1301
+ svg.setAttribute("class", OVERLAY_CLASS);
1330
1302
  svg.setAttribute("xmlns", SVG_NS);
1331
1303
  svg.setAttribute("width", String(width));
1332
1304
  svg.setAttribute("height", String(height));
@@ -1868,13 +1840,27 @@ var instances = /* @__PURE__ */ new WeakMap();
1868
1840
  function now() {
1869
1841
  return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1870
1842
  }
1871
- function localBand(overlayRect, inset = 8) {
1843
+ function localBand(originLeft, inset = 8) {
1872
1844
  const width = window.innerWidth || document.documentElement.clientWidth || 0;
1873
1845
  return {
1874
- x: -overlayRect.x + inset,
1846
+ x: -originLeft + inset,
1875
1847
  width: Math.max(0, width - inset * 2)
1876
1848
  };
1877
1849
  }
1850
+ function paddingBox(element) {
1851
+ const rect = element.getBoundingClientRect();
1852
+ const style = getComputedStyle(element);
1853
+ const left = parseFloat(style.borderLeftWidth) || 0;
1854
+ const top = parseFloat(style.borderTopWidth) || 0;
1855
+ const right = parseFloat(style.borderRightWidth) || 0;
1856
+ const bottom = parseFloat(style.borderBottomWidth) || 0;
1857
+ return {
1858
+ left: rect.left + left,
1859
+ top: rect.top + top,
1860
+ width: Math.max(0, rect.width - left - right),
1861
+ height: Math.max(0, rect.height - top - bottom)
1862
+ };
1863
+ }
1878
1864
  var DoodleOverlay = class {
1879
1865
  /**
1880
1866
  * @param {Element} element
@@ -1886,7 +1872,7 @@ var DoodleOverlay = class {
1886
1872
  this.seed = Math.floor(Math.random() * 1e9);
1887
1873
  this.startedAt = now();
1888
1874
  this.svg = null;
1889
- this.wrapper = null;
1875
+ this.setPosition = false;
1890
1876
  this.resizeObserver = null;
1891
1877
  this.mutationObserver = null;
1892
1878
  this.pendingFrame = null;
@@ -1898,14 +1884,17 @@ var DoodleOverlay = class {
1898
1884
  }
1899
1885
  mount() {
1900
1886
  this.svg = createOverlaySvg(0, 0, 0, 0);
1901
- this.wrapper = insertOverlaySvg(this.svg, this.element);
1887
+ this.setPosition = insertOverlaySvg(this.svg, this.element);
1902
1888
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1903
1889
  this.resizeObserver = new ResizeObserver(this.onResize);
1904
1890
  this.resizeObserver.observe(this.element);
1905
1891
  if (this.options.children) {
1906
1892
  this.observeChildren();
1907
1893
  }
1908
- this.mutationObserver = new MutationObserver(this.scheduleUpdate.bind(this));
1894
+ this.mutationObserver = new MutationObserver((records) => {
1895
+ const relevant = records.some((record) => !this.svg.contains(record.target));
1896
+ if (relevant) this.scheduleUpdate();
1897
+ });
1909
1898
  this.mutationObserver.observe(this.element, {
1910
1899
  childList: true,
1911
1900
  subtree: true,
@@ -1957,22 +1946,23 @@ var DoodleOverlay = class {
1957
1946
  if (!this.svg || !this.element.isConnected) return;
1958
1947
  const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
1959
1948
  const targets = this.getTargets();
1960
- const margin = this.overlayMargin();
1961
1949
  const elapsed = now() - this.startedAt;
1962
1950
  const absoluteRects = targets.map(
1963
1951
  (target) => getElementBounds(target, padding, radius)
1964
1952
  );
1965
- const overlayRect = unionRects(absoluteRects, margin);
1966
1953
  clearSvg(this.svg);
1967
1954
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1968
- const origin = this.wrapper ? this.wrapper.getBoundingClientRect() : { left: 0, top: 0 };
1969
- this.svg.setAttribute("width", String(overlayRect.width));
1970
- this.svg.setAttribute("height", String(overlayRect.height));
1971
- this.svg.setAttribute("viewBox", `0 0 ${overlayRect.width} ${overlayRect.height}`);
1972
- this.svg.style.left = `${overlayRect.x - origin.left}px`;
1973
- this.svg.style.top = `${overlayRect.y - origin.top}px`;
1974
- this.svg.style.width = `${overlayRect.width}px`;
1975
- this.svg.style.height = `${overlayRect.height}px`;
1955
+ const box = paddingBox(this.element);
1956
+ const width = Math.max(1, box.width);
1957
+ const height = Math.max(1, box.height);
1958
+ const origin = { x: box.left, y: box.top };
1959
+ this.svg.setAttribute("width", String(width));
1960
+ this.svg.setAttribute("height", String(height));
1961
+ this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
1962
+ this.svg.style.left = "0px";
1963
+ this.svg.style.top = "0px";
1964
+ this.svg.style.width = `${width}px`;
1965
+ this.svg.style.height = `${height}px`;
1976
1966
  const strokeStyle = { color, strokeWidth, roughness, opacity };
1977
1967
  const noteStyle = {
1978
1968
  color,
@@ -1983,12 +1973,12 @@ var DoodleOverlay = class {
1983
1973
  };
1984
1974
  const noteGroups = [];
1985
1975
  const noteLayout = {
1986
- band: localBand(overlayRect),
1976
+ band: localBand(origin.x),
1987
1977
  gap: this.options.arrow ? 40 : 14
1988
1978
  };
1989
1979
  targets.forEach((target, index) => {
1990
1980
  const absolute = absoluteRects[index];
1991
- const local = relativeRect(overlayRect, absolute);
1981
+ const local = relativeRect(origin, absolute);
1992
1982
  const seed = this.seed + index * 31;
1993
1983
  const note = this.options.note && index === 0 ? renderAnnotation(
1994
1984
  this.svg,
@@ -2034,15 +2024,6 @@ var DoodleOverlay = class {
2034
2024
  this.svg.appendChild(group);
2035
2025
  }
2036
2026
  }
2037
- /**
2038
- * Room the overlay needs beyond the element for notes, arrows and decorations.
2039
- */
2040
- overlayMargin() {
2041
- const { note, arrow, decorations } = this.options;
2042
- if (!note && !arrow && !decorations) return 48;
2043
- const { text } = resolveLocalizedText(note?.text, note?.locale);
2044
- return Math.max(96, Math.min(240, 80 + text.length * 8));
2045
- }
2046
2027
  destroy() {
2047
2028
  if (this.pendingFrame != null) {
2048
2029
  cancelFrame(this.pendingFrame);
@@ -2065,10 +2046,9 @@ var DoodleOverlay = class {
2065
2046
  }
2066
2047
  this.listeners = [];
2067
2048
  if (this.svg) {
2068
- removeOverlaySvg(this.svg, this.wrapper, this.element);
2049
+ removeOverlaySvg(this.svg, this.element, this.setPosition);
2069
2050
  }
2070
2051
  this.svg = null;
2071
- this.wrapper = null;
2072
2052
  instances.delete(this.element);
2073
2053
  }
2074
2054
  };
@@ -0,0 +1,7 @@
1
+ {
2
+ "name": "@aznabee/freehand-ui-native",
3
+ "private": true,
4
+ "main": "../dist/native.cjs",
5
+ "module": "../dist/native.js",
6
+ "types": "../dist/native.d.ts"
7
+ }