@aznabee/freehand-ui 0.1.7 → 0.1.8

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/README.md CHANGED
@@ -6,7 +6,7 @@ Wrap any existing web element with a beautiful, responsive, hand-drawn doodle la
6
6
 
7
7
  ## What it does
8
8
 
9
- `freehand-ui` adds a subtle SVG overlay on top of your UI - thin pen strokes, handwritten notes, arrows, and small decorations. It does not change your element's own styling and never blocks clicks (`pointer-events: none`).
9
+ `freehand-ui` adds a subtle SVG overlay on top of your UI - thin pen strokes, handwritten notes, arrows, and small decorations. It does **not** change your HTML layout or block clicks (`pointer-events: none`).
10
10
 
11
11
  **Good for:** call-to-action buttons, feature cards, onboarding hints, playful marketing UI.
12
12
 
@@ -19,8 +19,6 @@ Wrap any existing web element with a beautiful, responsive, hand-drawn doodle la
19
19
  | **Localised** | Notes in the visitor's own language, right-to-left included |
20
20
  | **Responsive** | Stays aligned on resize, scroll, and reflow |
21
21
 
22
- **DOM note:** the element is wrapped in a plain positioning `<div>` so the overlay can be mounted beside it (last child, so it paints on top) - the wrapped element keeps its own display and, in a flex/grid parent, its own placement, but a selector depending on it being a *direct* child of its original parent (`.parent > .card`, `:nth-child`) will no longer match. The overlay is also clipped by an `overflow: hidden` ancestor, since it no longer escapes the page via `position: fixed`.
23
-
24
22
  **Live on [Aznabee.com](https://aznabee.com)** - see it in production on the real product.
25
23
 
26
24
  ## ![Basic hand-drawn border around a card](docs/images/basic.png)
@@ -257,7 +255,7 @@ A `dotted` arrow spends its dash pattern on the dots, and one pattern cannot bot
257
255
  Notes:
258
256
 
259
257
  - **`prefers-reduced-motion: reduce` turns both gestures off** and leaves the arrow fully drawn.
260
- - The overlay moves with the element for free through ordinary layout - scrolling, a sibling loading in above it - and is only rebuilt when the element's own size actually changes. Animations are placed by how long the overlay has been on the page rather than restarted, so repositioning never replays a draw or jolts a lean mid-cycle.
258
+ - The overlay is rebuilt on every scroll and resize. Animations are placed by how long the overlay has been on the page rather than restarted, so scrolling never replays a draw or jolts a lean mid-cycle.
261
259
 
262
260
  ### Decorations
263
261
 
@@ -456,7 +454,7 @@ Then open:
456
454
  - **Framework agnostic** - plain JavaScript at the core; React is an optional entry point
457
455
  - **SVG based** - hand-drawn paths, not CSS borders
458
456
  - **Non-invasive** - `pointer-events: none`, no layout changes
459
- - **Responsive** - absolutely positioned beside the element, so it tracks scroll and layout shifts for free; `ResizeObserver` covers the rest
457
+ - **Responsive** - `ResizeObserver`, scroll listeners, and `requestAnimationFrame`
460
458
  - **Lightweight** - zero runtime dependencies
461
459
 
462
460
  ---
@@ -312,6 +312,10 @@ var DEFAULT_OPTIONS = {
312
312
  */
313
313
  zIndex: null
314
314
  };
315
+ var OVERLAY_CLASS = "doodle-ui-overlay";
316
+ function isOverlayNode(node) {
317
+ return node?.classList?.contains(OVERLAY_CLASS) ?? false;
318
+ }
315
319
  function resolveElement(target) {
316
320
  if (!target) return null;
317
321
  if (typeof target === "string") {
@@ -417,45 +421,21 @@ function resolveOverlayZIndex(element, override) {
417
421
  }
418
422
  return null;
419
423
  }
420
- var ITEM_PLACEMENT_PROPERTIES = [
421
- "order",
422
- "flexGrow",
423
- "flexShrink",
424
- "flexBasis",
425
- "alignSelf",
426
- "justifySelf",
427
- "gridColumn",
428
- "gridRow",
429
- "gridArea"
430
- ];
431
- function isInlineDisplay(computed) {
432
- return computed.display.startsWith("inline");
433
- }
434
424
  function insertOverlaySvg(svg, element) {
435
- const parent = element.parentNode;
436
- if (!parent) {
437
- document.body.appendChild(svg);
438
- return null;
439
- }
440
- const wrapper = document.createElement("div");
441
- wrapper.style.position = "relative";
442
- const computed = getComputedStyle(element);
443
- wrapper.style.display = isInlineDisplay(computed) ? "inline-block" : "block";
444
- for (const property of ITEM_PLACEMENT_PROPERTIES) {
445
- const value = computed[property];
446
- if (value) wrapper.style[property] = value;
447
- }
448
- parent.replaceChild(wrapper, element);
449
- wrapper.appendChild(element);
450
- wrapper.appendChild(svg);
451
- return wrapper;
452
- }
453
- function removeOverlaySvg(svg, wrapper, element) {
425
+ const setPosition = getComputedStyle(element).position === "static";
426
+ if (setPosition) {
427
+ element.style.position = "relative";
428
+ }
429
+ element.appendChild(svg);
430
+ return setPosition;
431
+ }
432
+ function removeOverlaySvg(svg, element, clearPosition) {
454
433
  if (svg.parentNode) {
455
434
  svg.parentNode.removeChild(svg);
456
435
  }
457
- if (!wrapper || !wrapper.parentNode) return;
458
- wrapper.parentNode.replaceChild(element, wrapper);
436
+ if (clearPosition) {
437
+ element.style.position = "";
438
+ }
459
439
  }
460
440
  function syncOverlayStacking(svg, element, zIndexOverride) {
461
441
  const zIndex = resolveOverlayZIndex(element, zIndexOverride);
@@ -482,7 +462,10 @@ function averageCornerRadius(element) {
482
462
  function detectBorderRadius(element) {
483
463
  const own = averageCornerRadius(element);
484
464
  if (own > 0) return own;
485
- const child = element.children.length === 1 ? element.firstElementChild : null;
465
+ const content = Array.from(element.children).filter(
466
+ (node) => !isOverlayNode(node)
467
+ );
468
+ const child = content.length === 1 ? content[0] : null;
486
469
  if (!child) return 0;
487
470
  const outer = element.getBoundingClientRect();
488
471
  const inner = child.getBoundingClientRect();
@@ -513,22 +496,6 @@ function relativeRect(outer, inner) {
513
496
  radius: inner.radius
514
497
  };
515
498
  }
516
- function unionRects(rects, margin = 0) {
517
- if (rects.length === 0) {
518
- return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
519
- }
520
- const minX = Math.min(...rects.map((r) => r.x)) - margin;
521
- const minY = Math.min(...rects.map((r) => r.y)) - margin;
522
- const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
523
- const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
524
- return {
525
- x: minX,
526
- y: minY,
527
- width: maxX - minX,
528
- height: maxY - minY,
529
- radius: 0
530
- };
531
- }
532
499
  function inflateRect(rect, amount) {
533
500
  return {
534
501
  x: rect.x - amount,
@@ -1338,7 +1305,7 @@ function placeNoteText(note, box, style, seed, options = {}) {
1338
1305
  }
1339
1306
  function createOverlaySvg(left, top, width, height) {
1340
1307
  const svg = document.createElementNS(SVG_NS, "svg");
1341
- svg.setAttribute("class", "doodle-ui-overlay");
1308
+ svg.setAttribute("class", OVERLAY_CLASS);
1342
1309
  svg.setAttribute("xmlns", SVG_NS);
1343
1310
  svg.setAttribute("width", String(width));
1344
1311
  svg.setAttribute("height", String(height));
@@ -1880,13 +1847,27 @@ var instances = /* @__PURE__ */ new WeakMap();
1880
1847
  function now() {
1881
1848
  return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1882
1849
  }
1883
- function localBand(overlayRect, inset = 8) {
1850
+ function localBand(originLeft, inset = 8) {
1884
1851
  const width = window.innerWidth || document.documentElement.clientWidth || 0;
1885
1852
  return {
1886
- x: -overlayRect.x + inset,
1853
+ x: -originLeft + inset,
1887
1854
  width: Math.max(0, width - inset * 2)
1888
1855
  };
1889
1856
  }
1857
+ function paddingBox(element) {
1858
+ const rect = element.getBoundingClientRect();
1859
+ const style = getComputedStyle(element);
1860
+ const left = parseFloat(style.borderLeftWidth) || 0;
1861
+ const top = parseFloat(style.borderTopWidth) || 0;
1862
+ const right = parseFloat(style.borderRightWidth) || 0;
1863
+ const bottom = parseFloat(style.borderBottomWidth) || 0;
1864
+ return {
1865
+ left: rect.left + left,
1866
+ top: rect.top + top,
1867
+ width: Math.max(0, rect.width - left - right),
1868
+ height: Math.max(0, rect.height - top - bottom)
1869
+ };
1870
+ }
1890
1871
  var DoodleOverlay = class {
1891
1872
  /**
1892
1873
  * @param {Element} element
@@ -1898,7 +1879,7 @@ var DoodleOverlay = class {
1898
1879
  this.seed = Math.floor(Math.random() * 1e9);
1899
1880
  this.startedAt = now();
1900
1881
  this.svg = null;
1901
- this.wrapper = null;
1882
+ this.setPosition = false;
1902
1883
  this.resizeObserver = null;
1903
1884
  this.mutationObserver = null;
1904
1885
  this.pendingFrame = null;
@@ -1910,14 +1891,17 @@ var DoodleOverlay = class {
1910
1891
  }
1911
1892
  mount() {
1912
1893
  this.svg = createOverlaySvg(0, 0, 0, 0);
1913
- this.wrapper = insertOverlaySvg(this.svg, this.element);
1894
+ this.setPosition = insertOverlaySvg(this.svg, this.element);
1914
1895
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1915
1896
  this.resizeObserver = new ResizeObserver(this.onResize);
1916
1897
  this.resizeObserver.observe(this.element);
1917
1898
  if (this.options.children) {
1918
1899
  this.observeChildren();
1919
1900
  }
1920
- this.mutationObserver = new MutationObserver(this.scheduleUpdate.bind(this));
1901
+ this.mutationObserver = new MutationObserver((records) => {
1902
+ const relevant = records.some((record) => !this.svg.contains(record.target));
1903
+ if (relevant) this.scheduleUpdate();
1904
+ });
1921
1905
  this.mutationObserver.observe(this.element, {
1922
1906
  childList: true,
1923
1907
  subtree: true,
@@ -1969,22 +1953,23 @@ var DoodleOverlay = class {
1969
1953
  if (!this.svg || !this.element.isConnected) return;
1970
1954
  const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
1971
1955
  const targets = this.getTargets();
1972
- const margin = this.overlayMargin();
1973
1956
  const elapsed = now() - this.startedAt;
1974
1957
  const absoluteRects = targets.map(
1975
1958
  (target) => getElementBounds(target, padding, radius)
1976
1959
  );
1977
- const overlayRect = unionRects(absoluteRects, margin);
1978
1960
  clearSvg(this.svg);
1979
1961
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1980
- const origin = this.wrapper ? this.wrapper.getBoundingClientRect() : { left: 0, top: 0 };
1981
- this.svg.setAttribute("width", String(overlayRect.width));
1982
- this.svg.setAttribute("height", String(overlayRect.height));
1983
- this.svg.setAttribute("viewBox", `0 0 ${overlayRect.width} ${overlayRect.height}`);
1984
- this.svg.style.left = `${overlayRect.x - origin.left}px`;
1985
- this.svg.style.top = `${overlayRect.y - origin.top}px`;
1986
- this.svg.style.width = `${overlayRect.width}px`;
1987
- this.svg.style.height = `${overlayRect.height}px`;
1962
+ const box = paddingBox(this.element);
1963
+ const width = Math.max(1, box.width);
1964
+ const height = Math.max(1, box.height);
1965
+ const origin = { x: box.left, y: box.top };
1966
+ this.svg.setAttribute("width", String(width));
1967
+ this.svg.setAttribute("height", String(height));
1968
+ this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
1969
+ this.svg.style.left = "0px";
1970
+ this.svg.style.top = "0px";
1971
+ this.svg.style.width = `${width}px`;
1972
+ this.svg.style.height = `${height}px`;
1988
1973
  const strokeStyle = { color, strokeWidth, roughness, opacity };
1989
1974
  const noteStyle = {
1990
1975
  color,
@@ -1995,12 +1980,12 @@ var DoodleOverlay = class {
1995
1980
  };
1996
1981
  const noteGroups = [];
1997
1982
  const noteLayout = {
1998
- band: localBand(overlayRect),
1983
+ band: localBand(origin.x),
1999
1984
  gap: this.options.arrow ? 40 : 14
2000
1985
  };
2001
1986
  targets.forEach((target, index) => {
2002
1987
  const absolute = absoluteRects[index];
2003
- const local = relativeRect(overlayRect, absolute);
1988
+ const local = relativeRect(origin, absolute);
2004
1989
  const seed = this.seed + index * 31;
2005
1990
  const note = this.options.note && index === 0 ? renderAnnotation(
2006
1991
  this.svg,
@@ -2046,15 +2031,6 @@ var DoodleOverlay = class {
2046
2031
  this.svg.appendChild(group);
2047
2032
  }
2048
2033
  }
2049
- /**
2050
- * Room the overlay needs beyond the element for notes, arrows and decorations.
2051
- */
2052
- overlayMargin() {
2053
- const { note, arrow, decorations } = this.options;
2054
- if (!note && !arrow && !decorations) return 48;
2055
- const { text } = resolveLocalizedText(note?.text, note?.locale);
2056
- return Math.max(96, Math.min(240, 80 + text.length * 8));
2057
- }
2058
2034
  destroy() {
2059
2035
  if (this.pendingFrame != null) {
2060
2036
  cancelFrame(this.pendingFrame);
@@ -2077,10 +2053,9 @@ var DoodleOverlay = class {
2077
2053
  }
2078
2054
  this.listeners = [];
2079
2055
  if (this.svg) {
2080
- removeOverlaySvg(this.svg, this.wrapper, this.element);
2056
+ removeOverlaySvg(this.svg, this.element, this.setPosition);
2081
2057
  }
2082
2058
  this.svg = null;
2083
- this.wrapper = null;
2084
2059
  instances.delete(this.element);
2085
2060
  }
2086
2061
  };
@@ -287,6 +287,10 @@ var DEFAULT_OPTIONS = {
287
287
  */
288
288
  zIndex: null
289
289
  };
290
+ var OVERLAY_CLASS = "doodle-ui-overlay";
291
+ function isOverlayNode(node) {
292
+ return node?.classList?.contains(OVERLAY_CLASS) ?? false;
293
+ }
290
294
  function resolveElement(target) {
291
295
  if (!target) return null;
292
296
  if (typeof target === "string") {
@@ -392,45 +396,21 @@ function resolveOverlayZIndex(element, override) {
392
396
  }
393
397
  return null;
394
398
  }
395
- var ITEM_PLACEMENT_PROPERTIES = [
396
- "order",
397
- "flexGrow",
398
- "flexShrink",
399
- "flexBasis",
400
- "alignSelf",
401
- "justifySelf",
402
- "gridColumn",
403
- "gridRow",
404
- "gridArea"
405
- ];
406
- function isInlineDisplay(computed) {
407
- return computed.display.startsWith("inline");
408
- }
409
399
  function insertOverlaySvg(svg, element) {
410
- const parent = element.parentNode;
411
- if (!parent) {
412
- document.body.appendChild(svg);
413
- return null;
414
- }
415
- const wrapper = document.createElement("div");
416
- wrapper.style.position = "relative";
417
- const computed = getComputedStyle(element);
418
- wrapper.style.display = isInlineDisplay(computed) ? "inline-block" : "block";
419
- for (const property of ITEM_PLACEMENT_PROPERTIES) {
420
- const value = computed[property];
421
- if (value) wrapper.style[property] = value;
422
- }
423
- parent.replaceChild(wrapper, element);
424
- wrapper.appendChild(element);
425
- wrapper.appendChild(svg);
426
- return wrapper;
427
- }
428
- function removeOverlaySvg(svg, wrapper, element) {
400
+ const setPosition = getComputedStyle(element).position === "static";
401
+ if (setPosition) {
402
+ element.style.position = "relative";
403
+ }
404
+ element.appendChild(svg);
405
+ return setPosition;
406
+ }
407
+ function removeOverlaySvg(svg, element, clearPosition) {
429
408
  if (svg.parentNode) {
430
409
  svg.parentNode.removeChild(svg);
431
410
  }
432
- if (!wrapper || !wrapper.parentNode) return;
433
- wrapper.parentNode.replaceChild(element, wrapper);
411
+ if (clearPosition) {
412
+ element.style.position = "";
413
+ }
434
414
  }
435
415
  function syncOverlayStacking(svg, element, zIndexOverride) {
436
416
  const zIndex = resolveOverlayZIndex(element, zIndexOverride);
@@ -457,7 +437,10 @@ function averageCornerRadius(element) {
457
437
  function detectBorderRadius(element) {
458
438
  const own = averageCornerRadius(element);
459
439
  if (own > 0) return own;
460
- const child = element.children.length === 1 ? element.firstElementChild : null;
440
+ const content = Array.from(element.children).filter(
441
+ (node) => !isOverlayNode(node)
442
+ );
443
+ const child = content.length === 1 ? content[0] : null;
461
444
  if (!child) return 0;
462
445
  const outer = element.getBoundingClientRect();
463
446
  const inner = child.getBoundingClientRect();
@@ -488,22 +471,6 @@ function relativeRect(outer, inner) {
488
471
  radius: inner.radius
489
472
  };
490
473
  }
491
- function unionRects(rects, margin = 0) {
492
- if (rects.length === 0) {
493
- return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
494
- }
495
- const minX = Math.min(...rects.map((r) => r.x)) - margin;
496
- const minY = Math.min(...rects.map((r) => r.y)) - margin;
497
- const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
498
- const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
499
- return {
500
- x: minX,
501
- y: minY,
502
- width: maxX - minX,
503
- height: maxY - minY,
504
- radius: 0
505
- };
506
- }
507
474
  function inflateRect(rect, amount) {
508
475
  return {
509
476
  x: rect.x - amount,
@@ -1313,7 +1280,7 @@ function placeNoteText(note, box, style, seed, options = {}) {
1313
1280
  }
1314
1281
  function createOverlaySvg(left, top, width, height) {
1315
1282
  const svg = document.createElementNS(SVG_NS, "svg");
1316
- svg.setAttribute("class", "doodle-ui-overlay");
1283
+ svg.setAttribute("class", OVERLAY_CLASS);
1317
1284
  svg.setAttribute("xmlns", SVG_NS);
1318
1285
  svg.setAttribute("width", String(width));
1319
1286
  svg.setAttribute("height", String(height));
@@ -1855,13 +1822,27 @@ var instances = /* @__PURE__ */ new WeakMap();
1855
1822
  function now() {
1856
1823
  return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1857
1824
  }
1858
- function localBand(overlayRect, inset = 8) {
1825
+ function localBand(originLeft, inset = 8) {
1859
1826
  const width = window.innerWidth || document.documentElement.clientWidth || 0;
1860
1827
  return {
1861
- x: -overlayRect.x + inset,
1828
+ x: -originLeft + inset,
1862
1829
  width: Math.max(0, width - inset * 2)
1863
1830
  };
1864
1831
  }
1832
+ function paddingBox(element) {
1833
+ const rect = element.getBoundingClientRect();
1834
+ const style = getComputedStyle(element);
1835
+ const left = parseFloat(style.borderLeftWidth) || 0;
1836
+ const top = parseFloat(style.borderTopWidth) || 0;
1837
+ const right = parseFloat(style.borderRightWidth) || 0;
1838
+ const bottom = parseFloat(style.borderBottomWidth) || 0;
1839
+ return {
1840
+ left: rect.left + left,
1841
+ top: rect.top + top,
1842
+ width: Math.max(0, rect.width - left - right),
1843
+ height: Math.max(0, rect.height - top - bottom)
1844
+ };
1845
+ }
1865
1846
  var DoodleOverlay = class {
1866
1847
  /**
1867
1848
  * @param {Element} element
@@ -1873,7 +1854,7 @@ var DoodleOverlay = class {
1873
1854
  this.seed = Math.floor(Math.random() * 1e9);
1874
1855
  this.startedAt = now();
1875
1856
  this.svg = null;
1876
- this.wrapper = null;
1857
+ this.setPosition = false;
1877
1858
  this.resizeObserver = null;
1878
1859
  this.mutationObserver = null;
1879
1860
  this.pendingFrame = null;
@@ -1885,14 +1866,17 @@ var DoodleOverlay = class {
1885
1866
  }
1886
1867
  mount() {
1887
1868
  this.svg = createOverlaySvg(0, 0, 0, 0);
1888
- this.wrapper = insertOverlaySvg(this.svg, this.element);
1869
+ this.setPosition = insertOverlaySvg(this.svg, this.element);
1889
1870
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1890
1871
  this.resizeObserver = new ResizeObserver(this.onResize);
1891
1872
  this.resizeObserver.observe(this.element);
1892
1873
  if (this.options.children) {
1893
1874
  this.observeChildren();
1894
1875
  }
1895
- this.mutationObserver = new MutationObserver(this.scheduleUpdate.bind(this));
1876
+ this.mutationObserver = new MutationObserver((records) => {
1877
+ const relevant = records.some((record) => !this.svg.contains(record.target));
1878
+ if (relevant) this.scheduleUpdate();
1879
+ });
1896
1880
  this.mutationObserver.observe(this.element, {
1897
1881
  childList: true,
1898
1882
  subtree: true,
@@ -1944,22 +1928,23 @@ var DoodleOverlay = class {
1944
1928
  if (!this.svg || !this.element.isConnected) return;
1945
1929
  const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
1946
1930
  const targets = this.getTargets();
1947
- const margin = this.overlayMargin();
1948
1931
  const elapsed = now() - this.startedAt;
1949
1932
  const absoluteRects = targets.map(
1950
1933
  (target) => getElementBounds(target, padding, radius)
1951
1934
  );
1952
- const overlayRect = unionRects(absoluteRects, margin);
1953
1935
  clearSvg(this.svg);
1954
1936
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1955
- const origin = this.wrapper ? this.wrapper.getBoundingClientRect() : { left: 0, top: 0 };
1956
- this.svg.setAttribute("width", String(overlayRect.width));
1957
- this.svg.setAttribute("height", String(overlayRect.height));
1958
- this.svg.setAttribute("viewBox", `0 0 ${overlayRect.width} ${overlayRect.height}`);
1959
- this.svg.style.left = `${overlayRect.x - origin.left}px`;
1960
- this.svg.style.top = `${overlayRect.y - origin.top}px`;
1961
- this.svg.style.width = `${overlayRect.width}px`;
1962
- this.svg.style.height = `${overlayRect.height}px`;
1937
+ const box = paddingBox(this.element);
1938
+ const width = Math.max(1, box.width);
1939
+ const height = Math.max(1, box.height);
1940
+ const origin = { x: box.left, y: box.top };
1941
+ this.svg.setAttribute("width", String(width));
1942
+ this.svg.setAttribute("height", String(height));
1943
+ this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
1944
+ this.svg.style.left = "0px";
1945
+ this.svg.style.top = "0px";
1946
+ this.svg.style.width = `${width}px`;
1947
+ this.svg.style.height = `${height}px`;
1963
1948
  const strokeStyle = { color, strokeWidth, roughness, opacity };
1964
1949
  const noteStyle = {
1965
1950
  color,
@@ -1970,12 +1955,12 @@ var DoodleOverlay = class {
1970
1955
  };
1971
1956
  const noteGroups = [];
1972
1957
  const noteLayout = {
1973
- band: localBand(overlayRect),
1958
+ band: localBand(origin.x),
1974
1959
  gap: this.options.arrow ? 40 : 14
1975
1960
  };
1976
1961
  targets.forEach((target, index) => {
1977
1962
  const absolute = absoluteRects[index];
1978
- const local = relativeRect(overlayRect, absolute);
1963
+ const local = relativeRect(origin, absolute);
1979
1964
  const seed = this.seed + index * 31;
1980
1965
  const note = this.options.note && index === 0 ? renderAnnotation(
1981
1966
  this.svg,
@@ -2021,15 +2006,6 @@ var DoodleOverlay = class {
2021
2006
  this.svg.appendChild(group);
2022
2007
  }
2023
2008
  }
2024
- /**
2025
- * Room the overlay needs beyond the element for notes, arrows and decorations.
2026
- */
2027
- overlayMargin() {
2028
- const { note, arrow, decorations } = this.options;
2029
- if (!note && !arrow && !decorations) return 48;
2030
- const { text } = resolveLocalizedText(note?.text, note?.locale);
2031
- return Math.max(96, Math.min(240, 80 + text.length * 8));
2032
- }
2033
2009
  destroy() {
2034
2010
  if (this.pendingFrame != null) {
2035
2011
  cancelFrame(this.pendingFrame);
@@ -2052,10 +2028,9 @@ var DoodleOverlay = class {
2052
2028
  }
2053
2029
  this.listeners = [];
2054
2030
  if (this.svg) {
2055
- removeOverlaySvg(this.svg, this.wrapper, this.element);
2031
+ removeOverlaySvg(this.svg, this.element, this.setPosition);
2056
2032
  }
2057
2033
  this.svg = null;
2058
- this.wrapper = null;
2059
2034
  instances.delete(this.element);
2060
2035
  }
2061
2036
  };
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,
@@ -1343,7 +1310,7 @@ function placeNoteText(note, box, style, seed, options = {}) {
1343
1310
  }
1344
1311
  function createOverlaySvg(left, top, width, height) {
1345
1312
  const svg = document.createElementNS(SVG_NS, "svg");
1346
- svg.setAttribute("class", "doodle-ui-overlay");
1313
+ svg.setAttribute("class", OVERLAY_CLASS);
1347
1314
  svg.setAttribute("xmlns", SVG_NS);
1348
1315
  svg.setAttribute("width", String(width));
1349
1316
  svg.setAttribute("height", String(height));
@@ -1885,13 +1852,27 @@ var instances = /* @__PURE__ */ new WeakMap();
1885
1852
  function now() {
1886
1853
  return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1887
1854
  }
1888
- function localBand(overlayRect, inset = 8) {
1855
+ function localBand(originLeft, inset = 8) {
1889
1856
  const width = window.innerWidth || document.documentElement.clientWidth || 0;
1890
1857
  return {
1891
- x: -overlayRect.x + inset,
1858
+ x: -originLeft + inset,
1892
1859
  width: Math.max(0, width - inset * 2)
1893
1860
  };
1894
1861
  }
1862
+ function paddingBox(element) {
1863
+ const rect = element.getBoundingClientRect();
1864
+ const style = getComputedStyle(element);
1865
+ const left = parseFloat(style.borderLeftWidth) || 0;
1866
+ const top = parseFloat(style.borderTopWidth) || 0;
1867
+ const right = parseFloat(style.borderRightWidth) || 0;
1868
+ const bottom = parseFloat(style.borderBottomWidth) || 0;
1869
+ return {
1870
+ left: rect.left + left,
1871
+ top: rect.top + top,
1872
+ width: Math.max(0, rect.width - left - right),
1873
+ height: Math.max(0, rect.height - top - bottom)
1874
+ };
1875
+ }
1895
1876
  var DoodleOverlay = class {
1896
1877
  /**
1897
1878
  * @param {Element} element
@@ -1903,7 +1884,7 @@ var DoodleOverlay = class {
1903
1884
  this.seed = Math.floor(Math.random() * 1e9);
1904
1885
  this.startedAt = now();
1905
1886
  this.svg = null;
1906
- this.wrapper = null;
1887
+ this.setPosition = false;
1907
1888
  this.resizeObserver = null;
1908
1889
  this.mutationObserver = null;
1909
1890
  this.pendingFrame = null;
@@ -1915,14 +1896,17 @@ var DoodleOverlay = class {
1915
1896
  }
1916
1897
  mount() {
1917
1898
  this.svg = createOverlaySvg(0, 0, 0, 0);
1918
- this.wrapper = insertOverlaySvg(this.svg, this.element);
1899
+ this.setPosition = insertOverlaySvg(this.svg, this.element);
1919
1900
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1920
1901
  this.resizeObserver = new ResizeObserver(this.onResize);
1921
1902
  this.resizeObserver.observe(this.element);
1922
1903
  if (this.options.children) {
1923
1904
  this.observeChildren();
1924
1905
  }
1925
- this.mutationObserver = new MutationObserver(this.scheduleUpdate.bind(this));
1906
+ this.mutationObserver = new MutationObserver((records) => {
1907
+ const relevant = records.some((record) => !this.svg.contains(record.target));
1908
+ if (relevant) this.scheduleUpdate();
1909
+ });
1926
1910
  this.mutationObserver.observe(this.element, {
1927
1911
  childList: true,
1928
1912
  subtree: true,
@@ -1974,22 +1958,23 @@ var DoodleOverlay = class {
1974
1958
  if (!this.svg || !this.element.isConnected) return;
1975
1959
  const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
1976
1960
  const targets = this.getTargets();
1977
- const margin = this.overlayMargin();
1978
1961
  const elapsed = now() - this.startedAt;
1979
1962
  const absoluteRects = targets.map(
1980
1963
  (target) => getElementBounds(target, padding, radius)
1981
1964
  );
1982
- const overlayRect = unionRects(absoluteRects, margin);
1983
1965
  clearSvg(this.svg);
1984
1966
  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`;
1967
+ const box = paddingBox(this.element);
1968
+ const width = Math.max(1, box.width);
1969
+ const height = Math.max(1, box.height);
1970
+ const origin = { x: box.left, y: box.top };
1971
+ this.svg.setAttribute("width", String(width));
1972
+ this.svg.setAttribute("height", String(height));
1973
+ this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
1974
+ this.svg.style.left = "0px";
1975
+ this.svg.style.top = "0px";
1976
+ this.svg.style.width = `${width}px`;
1977
+ this.svg.style.height = `${height}px`;
1993
1978
  const strokeStyle = { color, strokeWidth, roughness, opacity };
1994
1979
  const noteStyle = {
1995
1980
  color,
@@ -2000,12 +1985,12 @@ var DoodleOverlay = class {
2000
1985
  };
2001
1986
  const noteGroups = [];
2002
1987
  const noteLayout = {
2003
- band: localBand(overlayRect),
1988
+ band: localBand(origin.x),
2004
1989
  gap: this.options.arrow ? 40 : 14
2005
1990
  };
2006
1991
  targets.forEach((target, index) => {
2007
1992
  const absolute = absoluteRects[index];
2008
- const local = relativeRect(overlayRect, absolute);
1993
+ const local = relativeRect(origin, absolute);
2009
1994
  const seed = this.seed + index * 31;
2010
1995
  const note = this.options.note && index === 0 ? renderAnnotation(
2011
1996
  this.svg,
@@ -2051,15 +2036,6 @@ var DoodleOverlay = class {
2051
2036
  this.svg.appendChild(group);
2052
2037
  }
2053
2038
  }
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
2039
  destroy() {
2064
2040
  if (this.pendingFrame != null) {
2065
2041
  cancelFrame(this.pendingFrame);
@@ -2082,10 +2058,9 @@ var DoodleOverlay = class {
2082
2058
  }
2083
2059
  this.listeners = [];
2084
2060
  if (this.svg) {
2085
- removeOverlaySvg(this.svg, this.wrapper, this.element);
2061
+ removeOverlaySvg(this.svg, this.element, this.setPosition);
2086
2062
  }
2087
2063
  this.svg = null;
2088
- this.wrapper = null;
2089
2064
  instances.delete(this.element);
2090
2065
  }
2091
2066
  };
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,
@@ -1326,7 +1293,7 @@ function placeNoteText(note, box, style, seed, options = {}) {
1326
1293
  }
1327
1294
  function createOverlaySvg(left, top, width, height) {
1328
1295
  const svg = document.createElementNS(SVG_NS, "svg");
1329
- svg.setAttribute("class", "doodle-ui-overlay");
1296
+ svg.setAttribute("class", OVERLAY_CLASS);
1330
1297
  svg.setAttribute("xmlns", SVG_NS);
1331
1298
  svg.setAttribute("width", String(width));
1332
1299
  svg.setAttribute("height", String(height));
@@ -1868,13 +1835,27 @@ var instances = /* @__PURE__ */ new WeakMap();
1868
1835
  function now() {
1869
1836
  return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
1870
1837
  }
1871
- function localBand(overlayRect, inset = 8) {
1838
+ function localBand(originLeft, inset = 8) {
1872
1839
  const width = window.innerWidth || document.documentElement.clientWidth || 0;
1873
1840
  return {
1874
- x: -overlayRect.x + inset,
1841
+ x: -originLeft + inset,
1875
1842
  width: Math.max(0, width - inset * 2)
1876
1843
  };
1877
1844
  }
1845
+ function paddingBox(element) {
1846
+ const rect = element.getBoundingClientRect();
1847
+ const style = getComputedStyle(element);
1848
+ const left = parseFloat(style.borderLeftWidth) || 0;
1849
+ const top = parseFloat(style.borderTopWidth) || 0;
1850
+ const right = parseFloat(style.borderRightWidth) || 0;
1851
+ const bottom = parseFloat(style.borderBottomWidth) || 0;
1852
+ return {
1853
+ left: rect.left + left,
1854
+ top: rect.top + top,
1855
+ width: Math.max(0, rect.width - left - right),
1856
+ height: Math.max(0, rect.height - top - bottom)
1857
+ };
1858
+ }
1878
1859
  var DoodleOverlay = class {
1879
1860
  /**
1880
1861
  * @param {Element} element
@@ -1886,7 +1867,7 @@ var DoodleOverlay = class {
1886
1867
  this.seed = Math.floor(Math.random() * 1e9);
1887
1868
  this.startedAt = now();
1888
1869
  this.svg = null;
1889
- this.wrapper = null;
1870
+ this.setPosition = false;
1890
1871
  this.resizeObserver = null;
1891
1872
  this.mutationObserver = null;
1892
1873
  this.pendingFrame = null;
@@ -1898,14 +1879,17 @@ var DoodleOverlay = class {
1898
1879
  }
1899
1880
  mount() {
1900
1881
  this.svg = createOverlaySvg(0, 0, 0, 0);
1901
- this.wrapper = insertOverlaySvg(this.svg, this.element);
1882
+ this.setPosition = insertOverlaySvg(this.svg, this.element);
1902
1883
  syncOverlayStacking(this.svg, this.element, this.options.zIndex);
1903
1884
  this.resizeObserver = new ResizeObserver(this.onResize);
1904
1885
  this.resizeObserver.observe(this.element);
1905
1886
  if (this.options.children) {
1906
1887
  this.observeChildren();
1907
1888
  }
1908
- this.mutationObserver = new MutationObserver(this.scheduleUpdate.bind(this));
1889
+ this.mutationObserver = new MutationObserver((records) => {
1890
+ const relevant = records.some((record) => !this.svg.contains(record.target));
1891
+ if (relevant) this.scheduleUpdate();
1892
+ });
1909
1893
  this.mutationObserver.observe(this.element, {
1910
1894
  childList: true,
1911
1895
  subtree: true,
@@ -1957,22 +1941,23 @@ var DoodleOverlay = class {
1957
1941
  if (!this.svg || !this.element.isConnected) return;
1958
1942
  const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
1959
1943
  const targets = this.getTargets();
1960
- const margin = this.overlayMargin();
1961
1944
  const elapsed = now() - this.startedAt;
1962
1945
  const absoluteRects = targets.map(
1963
1946
  (target) => getElementBounds(target, padding, radius)
1964
1947
  );
1965
- const overlayRect = unionRects(absoluteRects, margin);
1966
1948
  clearSvg(this.svg);
1967
1949
  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`;
1950
+ const box = paddingBox(this.element);
1951
+ const width = Math.max(1, box.width);
1952
+ const height = Math.max(1, box.height);
1953
+ const origin = { x: box.left, y: box.top };
1954
+ this.svg.setAttribute("width", String(width));
1955
+ this.svg.setAttribute("height", String(height));
1956
+ this.svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
1957
+ this.svg.style.left = "0px";
1958
+ this.svg.style.top = "0px";
1959
+ this.svg.style.width = `${width}px`;
1960
+ this.svg.style.height = `${height}px`;
1976
1961
  const strokeStyle = { color, strokeWidth, roughness, opacity };
1977
1962
  const noteStyle = {
1978
1963
  color,
@@ -1983,12 +1968,12 @@ var DoodleOverlay = class {
1983
1968
  };
1984
1969
  const noteGroups = [];
1985
1970
  const noteLayout = {
1986
- band: localBand(overlayRect),
1971
+ band: localBand(origin.x),
1987
1972
  gap: this.options.arrow ? 40 : 14
1988
1973
  };
1989
1974
  targets.forEach((target, index) => {
1990
1975
  const absolute = absoluteRects[index];
1991
- const local = relativeRect(overlayRect, absolute);
1976
+ const local = relativeRect(origin, absolute);
1992
1977
  const seed = this.seed + index * 31;
1993
1978
  const note = this.options.note && index === 0 ? renderAnnotation(
1994
1979
  this.svg,
@@ -2034,15 +2019,6 @@ var DoodleOverlay = class {
2034
2019
  this.svg.appendChild(group);
2035
2020
  }
2036
2021
  }
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
2022
  destroy() {
2047
2023
  if (this.pendingFrame != null) {
2048
2024
  cancelFrame(this.pendingFrame);
@@ -2065,10 +2041,9 @@ var DoodleOverlay = class {
2065
2041
  }
2066
2042
  this.listeners = [];
2067
2043
  if (this.svg) {
2068
- removeOverlaySvg(this.svg, this.wrapper, this.element);
2044
+ removeOverlaySvg(this.svg, this.element, this.setPosition);
2069
2045
  }
2070
2046
  this.svg = null;
2071
- this.wrapper = null;
2072
2047
  instances.delete(this.element);
2073
2048
  }
2074
2049
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aznabee/freehand-ui",
3
- "version": "0.1.7",
3
+ "version": "0.1.8",
4
4
  "description": "Wrap any existing web element with a beautiful, responsive, hand-drawn doodle layer",
5
5
  "type": "module",
6
6
  "main": "./dist/freehand-ui.cjs",