@aznabee/freehand-ui 0.1.6 → 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/dist/freehand-ui.cjs +60 -118
- package/dist/freehand-ui.js +60 -118
- package/dist/react.cjs +60 -118
- package/dist/react.js +60 -118
- package/package.json +1 -1
package/dist/freehand-ui.cjs
CHANGED
|
@@ -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") {
|
|
@@ -399,20 +403,6 @@ function isValidPosition(position) {
|
|
|
399
403
|
"center"
|
|
400
404
|
].includes(position);
|
|
401
405
|
}
|
|
402
|
-
function getScrollableAncestors(element) {
|
|
403
|
-
const ancestors = [];
|
|
404
|
-
let node = element.parentElement;
|
|
405
|
-
while (node && node !== document.documentElement) {
|
|
406
|
-
const style = getComputedStyle(node);
|
|
407
|
-
const overflow = style.overflow + style.overflowY + style.overflowX;
|
|
408
|
-
if (/(auto|scroll|overlay)/.test(overflow)) {
|
|
409
|
-
ancestors.push(node);
|
|
410
|
-
}
|
|
411
|
-
node = node.parentElement;
|
|
412
|
-
}
|
|
413
|
-
ancestors.push(window);
|
|
414
|
-
return ancestors;
|
|
415
|
-
}
|
|
416
406
|
function resolveOverlayZIndex(element, override) {
|
|
417
407
|
if (override != null) return override;
|
|
418
408
|
const { zIndex, position } = getComputedStyle(element);
|
|
@@ -432,12 +422,20 @@ function resolveOverlayZIndex(element, override) {
|
|
|
432
422
|
return null;
|
|
433
423
|
}
|
|
434
424
|
function insertOverlaySvg(svg, element) {
|
|
435
|
-
const
|
|
436
|
-
if (
|
|
437
|
-
|
|
438
|
-
|
|
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) {
|
|
433
|
+
if (svg.parentNode) {
|
|
434
|
+
svg.parentNode.removeChild(svg);
|
|
435
|
+
}
|
|
436
|
+
if (clearPosition) {
|
|
437
|
+
element.style.position = "";
|
|
439
438
|
}
|
|
440
|
-
parent.insertBefore(svg, element.nextSibling);
|
|
441
439
|
}
|
|
442
440
|
function syncOverlayStacking(svg, element, zIndexOverride) {
|
|
443
441
|
const zIndex = resolveOverlayZIndex(element, zIndexOverride);
|
|
@@ -464,7 +462,10 @@ function averageCornerRadius(element) {
|
|
|
464
462
|
function detectBorderRadius(element) {
|
|
465
463
|
const own = averageCornerRadius(element);
|
|
466
464
|
if (own > 0) return own;
|
|
467
|
-
const
|
|
465
|
+
const content = Array.from(element.children).filter(
|
|
466
|
+
(node) => !isOverlayNode(node)
|
|
467
|
+
);
|
|
468
|
+
const child = content.length === 1 ? content[0] : null;
|
|
468
469
|
if (!child) return 0;
|
|
469
470
|
const outer = element.getBoundingClientRect();
|
|
470
471
|
const inner = child.getBoundingClientRect();
|
|
@@ -495,22 +496,6 @@ function relativeRect(outer, inner) {
|
|
|
495
496
|
radius: inner.radius
|
|
496
497
|
};
|
|
497
498
|
}
|
|
498
|
-
function unionRects(rects, margin = 0) {
|
|
499
|
-
if (rects.length === 0) {
|
|
500
|
-
return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
|
|
501
|
-
}
|
|
502
|
-
const minX = Math.min(...rects.map((r) => r.x)) - margin;
|
|
503
|
-
const minY = Math.min(...rects.map((r) => r.y)) - margin;
|
|
504
|
-
const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
|
|
505
|
-
const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
|
|
506
|
-
return {
|
|
507
|
-
x: minX,
|
|
508
|
-
y: minY,
|
|
509
|
-
width: maxX - minX,
|
|
510
|
-
height: maxY - minY,
|
|
511
|
-
radius: 0
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
499
|
function inflateRect(rect, amount) {
|
|
515
500
|
return {
|
|
516
501
|
x: rect.x - amount,
|
|
@@ -1320,19 +1305,18 @@ function placeNoteText(note, box, style, seed, options = {}) {
|
|
|
1320
1305
|
}
|
|
1321
1306
|
function createOverlaySvg(left, top, width, height) {
|
|
1322
1307
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1323
|
-
svg.setAttribute("class",
|
|
1308
|
+
svg.setAttribute("class", OVERLAY_CLASS);
|
|
1324
1309
|
svg.setAttribute("xmlns", SVG_NS);
|
|
1325
1310
|
svg.setAttribute("width", String(width));
|
|
1326
1311
|
svg.setAttribute("height", String(height));
|
|
1327
1312
|
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
1328
|
-
svg.style.position = "
|
|
1313
|
+
svg.style.position = "absolute";
|
|
1329
1314
|
svg.style.left = `${left}px`;
|
|
1330
1315
|
svg.style.top = `${top}px`;
|
|
1331
1316
|
svg.style.width = `${width}px`;
|
|
1332
1317
|
svg.style.height = `${height}px`;
|
|
1333
1318
|
svg.style.pointerEvents = "none";
|
|
1334
1319
|
svg.style.overflow = "visible";
|
|
1335
|
-
svg.style.willChange = "transform";
|
|
1336
1320
|
return svg;
|
|
1337
1321
|
}
|
|
1338
1322
|
|
|
@@ -1863,13 +1847,27 @@ var instances = /* @__PURE__ */ new WeakMap();
|
|
|
1863
1847
|
function now() {
|
|
1864
1848
|
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
1865
1849
|
}
|
|
1866
|
-
function localBand(
|
|
1850
|
+
function localBand(originLeft, inset = 8) {
|
|
1867
1851
|
const width = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
1868
1852
|
return {
|
|
1869
|
-
x: -
|
|
1853
|
+
x: -originLeft + inset,
|
|
1870
1854
|
width: Math.max(0, width - inset * 2)
|
|
1871
1855
|
};
|
|
1872
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
|
+
}
|
|
1873
1871
|
var DoodleOverlay = class {
|
|
1874
1872
|
/**
|
|
1875
1873
|
* @param {Element} element
|
|
@@ -1881,13 +1879,11 @@ var DoodleOverlay = class {
|
|
|
1881
1879
|
this.seed = Math.floor(Math.random() * 1e9);
|
|
1882
1880
|
this.startedAt = now();
|
|
1883
1881
|
this.svg = null;
|
|
1882
|
+
this.setPosition = false;
|
|
1884
1883
|
this.resizeObserver = null;
|
|
1885
1884
|
this.mutationObserver = null;
|
|
1886
1885
|
this.pendingFrame = null;
|
|
1887
|
-
this.pendingRepositionFrame = null;
|
|
1888
|
-
this.basePosition = { x: 0, y: 0 };
|
|
1889
1886
|
this.listeners = [];
|
|
1890
|
-
this.onScroll = this.scheduleReposition.bind(this);
|
|
1891
1887
|
this.onResize = this.scheduleUpdate.bind(this);
|
|
1892
1888
|
this.onLanguageChange = this.scheduleUpdate.bind(this);
|
|
1893
1889
|
this.childElements = [];
|
|
@@ -1895,23 +1891,22 @@ var DoodleOverlay = class {
|
|
|
1895
1891
|
}
|
|
1896
1892
|
mount() {
|
|
1897
1893
|
this.svg = createOverlaySvg(0, 0, 0, 0);
|
|
1898
|
-
insertOverlaySvg(this.svg, this.element);
|
|
1894
|
+
this.setPosition = insertOverlaySvg(this.svg, this.element);
|
|
1899
1895
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
1900
1896
|
this.resizeObserver = new ResizeObserver(this.onResize);
|
|
1901
1897
|
this.resizeObserver.observe(this.element);
|
|
1902
1898
|
if (this.options.children) {
|
|
1903
1899
|
this.observeChildren();
|
|
1904
1900
|
}
|
|
1905
|
-
this.mutationObserver = new MutationObserver(
|
|
1901
|
+
this.mutationObserver = new MutationObserver((records) => {
|
|
1902
|
+
const relevant = records.some((record) => !this.svg.contains(record.target));
|
|
1903
|
+
if (relevant) this.scheduleUpdate();
|
|
1904
|
+
});
|
|
1906
1905
|
this.mutationObserver.observe(this.element, {
|
|
1907
1906
|
childList: true,
|
|
1908
1907
|
subtree: true,
|
|
1909
1908
|
attributes: true
|
|
1910
1909
|
});
|
|
1911
|
-
for (const target of getScrollableAncestors(this.element)) {
|
|
1912
|
-
target.addEventListener("scroll", this.onScroll, { passive: true });
|
|
1913
|
-
this.listeners.push({ target, type: "scroll", handler: this.onScroll });
|
|
1914
|
-
}
|
|
1915
1910
|
window.addEventListener("resize", this.onResize, { passive: true });
|
|
1916
1911
|
this.listeners.push({
|
|
1917
1912
|
target: window,
|
|
@@ -1947,46 +1942,6 @@ var DoodleOverlay = class {
|
|
|
1947
1942
|
this.update();
|
|
1948
1943
|
});
|
|
1949
1944
|
}
|
|
1950
|
-
scheduleReposition() {
|
|
1951
|
-
if (this.pendingFrame != null || this.pendingRepositionFrame != null) {
|
|
1952
|
-
return;
|
|
1953
|
-
}
|
|
1954
|
-
this.pendingRepositionFrame = scheduleFrame(() => {
|
|
1955
|
-
this.pendingRepositionFrame = null;
|
|
1956
|
-
this.reposition();
|
|
1957
|
-
});
|
|
1958
|
-
}
|
|
1959
|
-
/**
|
|
1960
|
-
* Cheap scroll-driven path: slide the overlay to the element's new
|
|
1961
|
-
* viewport position without touching its contents. Scrolling can't change
|
|
1962
|
-
* an element's size, so the rects, viewBox and every hand-drawn stroke
|
|
1963
|
-
* inside them are still valid - only the overlay's position needs to move.
|
|
1964
|
-
*
|
|
1965
|
-
* That move is a `transform`, not `left`/`top`. `left`/`top` sit in the
|
|
1966
|
-
* same box-geometry pass as layout, so the browser re-checks layout on
|
|
1967
|
-
* every write; `transform` is composited, so the scroll path never
|
|
1968
|
-
* touches layout at all.
|
|
1969
|
-
*/
|
|
1970
|
-
reposition() {
|
|
1971
|
-
if (!this.svg || !this.element.isConnected) return;
|
|
1972
|
-
const { padding, radius } = this.options;
|
|
1973
|
-
const targets = this.getTargets();
|
|
1974
|
-
const margin = this.overlayMargin();
|
|
1975
|
-
const absoluteRects = targets.map(
|
|
1976
|
-
(target) => getElementBounds(target, padding, radius)
|
|
1977
|
-
);
|
|
1978
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
1979
|
-
const currentWidth = parseFloat(this.svg.style.width) || 0;
|
|
1980
|
-
const currentHeight = parseFloat(this.svg.style.height) || 0;
|
|
1981
|
-
const resized = Math.abs(overlayRect.width - currentWidth) > 0.5 || Math.abs(overlayRect.height - currentHeight) > 0.5;
|
|
1982
|
-
if (resized) {
|
|
1983
|
-
this.update();
|
|
1984
|
-
return;
|
|
1985
|
-
}
|
|
1986
|
-
const dx = overlayRect.x - this.basePosition.x;
|
|
1987
|
-
const dy = overlayRect.y - this.basePosition.y;
|
|
1988
|
-
this.svg.style.transform = `translate3d(${dx}px, ${dy}px, 0)`;
|
|
1989
|
-
}
|
|
1990
1945
|
getTargets() {
|
|
1991
1946
|
if (this.options.children) {
|
|
1992
1947
|
const nodes = this.element.querySelectorAll(this.options.children);
|
|
@@ -1998,23 +1953,23 @@ var DoodleOverlay = class {
|
|
|
1998
1953
|
if (!this.svg || !this.element.isConnected) return;
|
|
1999
1954
|
const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
|
|
2000
1955
|
const targets = this.getTargets();
|
|
2001
|
-
const margin = this.overlayMargin();
|
|
2002
1956
|
const elapsed = now() - this.startedAt;
|
|
2003
1957
|
const absoluteRects = targets.map(
|
|
2004
1958
|
(target) => getElementBounds(target, padding, radius)
|
|
2005
1959
|
);
|
|
2006
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
2007
1960
|
clearSvg(this.svg);
|
|
2008
1961
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
this.svg.
|
|
2014
|
-
this.svg.
|
|
2015
|
-
this.svg.
|
|
2016
|
-
this.svg.style.
|
|
2017
|
-
this.
|
|
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`;
|
|
2018
1973
|
const strokeStyle = { color, strokeWidth, roughness, opacity };
|
|
2019
1974
|
const noteStyle = {
|
|
2020
1975
|
color,
|
|
@@ -2025,12 +1980,12 @@ var DoodleOverlay = class {
|
|
|
2025
1980
|
};
|
|
2026
1981
|
const noteGroups = [];
|
|
2027
1982
|
const noteLayout = {
|
|
2028
|
-
band: localBand(
|
|
1983
|
+
band: localBand(origin.x),
|
|
2029
1984
|
gap: this.options.arrow ? 40 : 14
|
|
2030
1985
|
};
|
|
2031
1986
|
targets.forEach((target, index) => {
|
|
2032
1987
|
const absolute = absoluteRects[index];
|
|
2033
|
-
const local = relativeRect(
|
|
1988
|
+
const local = relativeRect(origin, absolute);
|
|
2034
1989
|
const seed = this.seed + index * 31;
|
|
2035
1990
|
const note = this.options.note && index === 0 ? renderAnnotation(
|
|
2036
1991
|
this.svg,
|
|
@@ -2076,24 +2031,11 @@ var DoodleOverlay = class {
|
|
|
2076
2031
|
this.svg.appendChild(group);
|
|
2077
2032
|
}
|
|
2078
2033
|
}
|
|
2079
|
-
/**
|
|
2080
|
-
* Room the overlay needs beyond the element for notes, arrows and decorations.
|
|
2081
|
-
*/
|
|
2082
|
-
overlayMargin() {
|
|
2083
|
-
const { note, arrow, decorations } = this.options;
|
|
2084
|
-
if (!note && !arrow && !decorations) return 48;
|
|
2085
|
-
const { text } = resolveLocalizedText(note?.text, note?.locale);
|
|
2086
|
-
return Math.max(96, Math.min(240, 80 + text.length * 8));
|
|
2087
|
-
}
|
|
2088
2034
|
destroy() {
|
|
2089
2035
|
if (this.pendingFrame != null) {
|
|
2090
2036
|
cancelFrame(this.pendingFrame);
|
|
2091
2037
|
this.pendingFrame = null;
|
|
2092
2038
|
}
|
|
2093
|
-
if (this.pendingRepositionFrame != null) {
|
|
2094
|
-
cancelFrame(this.pendingRepositionFrame);
|
|
2095
|
-
this.pendingRepositionFrame = null;
|
|
2096
|
-
}
|
|
2097
2039
|
if (this.resizeObserver) {
|
|
2098
2040
|
this.resizeObserver.disconnect();
|
|
2099
2041
|
this.resizeObserver = null;
|
|
@@ -2110,8 +2052,8 @@ var DoodleOverlay = class {
|
|
|
2110
2052
|
target.removeEventListener(type, handler);
|
|
2111
2053
|
}
|
|
2112
2054
|
this.listeners = [];
|
|
2113
|
-
if (this.svg
|
|
2114
|
-
this.svg.
|
|
2055
|
+
if (this.svg) {
|
|
2056
|
+
removeOverlaySvg(this.svg, this.element, this.setPosition);
|
|
2115
2057
|
}
|
|
2116
2058
|
this.svg = null;
|
|
2117
2059
|
instances.delete(this.element);
|
package/dist/freehand-ui.js
CHANGED
|
@@ -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") {
|
|
@@ -374,20 +378,6 @@ function isValidPosition(position) {
|
|
|
374
378
|
"center"
|
|
375
379
|
].includes(position);
|
|
376
380
|
}
|
|
377
|
-
function getScrollableAncestors(element) {
|
|
378
|
-
const ancestors = [];
|
|
379
|
-
let node = element.parentElement;
|
|
380
|
-
while (node && node !== document.documentElement) {
|
|
381
|
-
const style = getComputedStyle(node);
|
|
382
|
-
const overflow = style.overflow + style.overflowY + style.overflowX;
|
|
383
|
-
if (/(auto|scroll|overlay)/.test(overflow)) {
|
|
384
|
-
ancestors.push(node);
|
|
385
|
-
}
|
|
386
|
-
node = node.parentElement;
|
|
387
|
-
}
|
|
388
|
-
ancestors.push(window);
|
|
389
|
-
return ancestors;
|
|
390
|
-
}
|
|
391
381
|
function resolveOverlayZIndex(element, override) {
|
|
392
382
|
if (override != null) return override;
|
|
393
383
|
const { zIndex, position } = getComputedStyle(element);
|
|
@@ -407,12 +397,20 @@ function resolveOverlayZIndex(element, override) {
|
|
|
407
397
|
return null;
|
|
408
398
|
}
|
|
409
399
|
function insertOverlaySvg(svg, element) {
|
|
410
|
-
const
|
|
411
|
-
if (
|
|
412
|
-
|
|
413
|
-
|
|
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) {
|
|
408
|
+
if (svg.parentNode) {
|
|
409
|
+
svg.parentNode.removeChild(svg);
|
|
410
|
+
}
|
|
411
|
+
if (clearPosition) {
|
|
412
|
+
element.style.position = "";
|
|
414
413
|
}
|
|
415
|
-
parent.insertBefore(svg, element.nextSibling);
|
|
416
414
|
}
|
|
417
415
|
function syncOverlayStacking(svg, element, zIndexOverride) {
|
|
418
416
|
const zIndex = resolveOverlayZIndex(element, zIndexOverride);
|
|
@@ -439,7 +437,10 @@ function averageCornerRadius(element) {
|
|
|
439
437
|
function detectBorderRadius(element) {
|
|
440
438
|
const own = averageCornerRadius(element);
|
|
441
439
|
if (own > 0) return own;
|
|
442
|
-
const
|
|
440
|
+
const content = Array.from(element.children).filter(
|
|
441
|
+
(node) => !isOverlayNode(node)
|
|
442
|
+
);
|
|
443
|
+
const child = content.length === 1 ? content[0] : null;
|
|
443
444
|
if (!child) return 0;
|
|
444
445
|
const outer = element.getBoundingClientRect();
|
|
445
446
|
const inner = child.getBoundingClientRect();
|
|
@@ -470,22 +471,6 @@ function relativeRect(outer, inner) {
|
|
|
470
471
|
radius: inner.radius
|
|
471
472
|
};
|
|
472
473
|
}
|
|
473
|
-
function unionRects(rects, margin = 0) {
|
|
474
|
-
if (rects.length === 0) {
|
|
475
|
-
return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
|
|
476
|
-
}
|
|
477
|
-
const minX = Math.min(...rects.map((r) => r.x)) - margin;
|
|
478
|
-
const minY = Math.min(...rects.map((r) => r.y)) - margin;
|
|
479
|
-
const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
|
|
480
|
-
const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
|
|
481
|
-
return {
|
|
482
|
-
x: minX,
|
|
483
|
-
y: minY,
|
|
484
|
-
width: maxX - minX,
|
|
485
|
-
height: maxY - minY,
|
|
486
|
-
radius: 0
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
474
|
function inflateRect(rect, amount) {
|
|
490
475
|
return {
|
|
491
476
|
x: rect.x - amount,
|
|
@@ -1295,19 +1280,18 @@ function placeNoteText(note, box, style, seed, options = {}) {
|
|
|
1295
1280
|
}
|
|
1296
1281
|
function createOverlaySvg(left, top, width, height) {
|
|
1297
1282
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1298
|
-
svg.setAttribute("class",
|
|
1283
|
+
svg.setAttribute("class", OVERLAY_CLASS);
|
|
1299
1284
|
svg.setAttribute("xmlns", SVG_NS);
|
|
1300
1285
|
svg.setAttribute("width", String(width));
|
|
1301
1286
|
svg.setAttribute("height", String(height));
|
|
1302
1287
|
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
1303
|
-
svg.style.position = "
|
|
1288
|
+
svg.style.position = "absolute";
|
|
1304
1289
|
svg.style.left = `${left}px`;
|
|
1305
1290
|
svg.style.top = `${top}px`;
|
|
1306
1291
|
svg.style.width = `${width}px`;
|
|
1307
1292
|
svg.style.height = `${height}px`;
|
|
1308
1293
|
svg.style.pointerEvents = "none";
|
|
1309
1294
|
svg.style.overflow = "visible";
|
|
1310
|
-
svg.style.willChange = "transform";
|
|
1311
1295
|
return svg;
|
|
1312
1296
|
}
|
|
1313
1297
|
|
|
@@ -1838,13 +1822,27 @@ var instances = /* @__PURE__ */ new WeakMap();
|
|
|
1838
1822
|
function now() {
|
|
1839
1823
|
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
1840
1824
|
}
|
|
1841
|
-
function localBand(
|
|
1825
|
+
function localBand(originLeft, inset = 8) {
|
|
1842
1826
|
const width = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
1843
1827
|
return {
|
|
1844
|
-
x: -
|
|
1828
|
+
x: -originLeft + inset,
|
|
1845
1829
|
width: Math.max(0, width - inset * 2)
|
|
1846
1830
|
};
|
|
1847
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
|
+
}
|
|
1848
1846
|
var DoodleOverlay = class {
|
|
1849
1847
|
/**
|
|
1850
1848
|
* @param {Element} element
|
|
@@ -1856,13 +1854,11 @@ var DoodleOverlay = class {
|
|
|
1856
1854
|
this.seed = Math.floor(Math.random() * 1e9);
|
|
1857
1855
|
this.startedAt = now();
|
|
1858
1856
|
this.svg = null;
|
|
1857
|
+
this.setPosition = false;
|
|
1859
1858
|
this.resizeObserver = null;
|
|
1860
1859
|
this.mutationObserver = null;
|
|
1861
1860
|
this.pendingFrame = null;
|
|
1862
|
-
this.pendingRepositionFrame = null;
|
|
1863
|
-
this.basePosition = { x: 0, y: 0 };
|
|
1864
1861
|
this.listeners = [];
|
|
1865
|
-
this.onScroll = this.scheduleReposition.bind(this);
|
|
1866
1862
|
this.onResize = this.scheduleUpdate.bind(this);
|
|
1867
1863
|
this.onLanguageChange = this.scheduleUpdate.bind(this);
|
|
1868
1864
|
this.childElements = [];
|
|
@@ -1870,23 +1866,22 @@ var DoodleOverlay = class {
|
|
|
1870
1866
|
}
|
|
1871
1867
|
mount() {
|
|
1872
1868
|
this.svg = createOverlaySvg(0, 0, 0, 0);
|
|
1873
|
-
insertOverlaySvg(this.svg, this.element);
|
|
1869
|
+
this.setPosition = insertOverlaySvg(this.svg, this.element);
|
|
1874
1870
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
1875
1871
|
this.resizeObserver = new ResizeObserver(this.onResize);
|
|
1876
1872
|
this.resizeObserver.observe(this.element);
|
|
1877
1873
|
if (this.options.children) {
|
|
1878
1874
|
this.observeChildren();
|
|
1879
1875
|
}
|
|
1880
|
-
this.mutationObserver = new MutationObserver(
|
|
1876
|
+
this.mutationObserver = new MutationObserver((records) => {
|
|
1877
|
+
const relevant = records.some((record) => !this.svg.contains(record.target));
|
|
1878
|
+
if (relevant) this.scheduleUpdate();
|
|
1879
|
+
});
|
|
1881
1880
|
this.mutationObserver.observe(this.element, {
|
|
1882
1881
|
childList: true,
|
|
1883
1882
|
subtree: true,
|
|
1884
1883
|
attributes: true
|
|
1885
1884
|
});
|
|
1886
|
-
for (const target of getScrollableAncestors(this.element)) {
|
|
1887
|
-
target.addEventListener("scroll", this.onScroll, { passive: true });
|
|
1888
|
-
this.listeners.push({ target, type: "scroll", handler: this.onScroll });
|
|
1889
|
-
}
|
|
1890
1885
|
window.addEventListener("resize", this.onResize, { passive: true });
|
|
1891
1886
|
this.listeners.push({
|
|
1892
1887
|
target: window,
|
|
@@ -1922,46 +1917,6 @@ var DoodleOverlay = class {
|
|
|
1922
1917
|
this.update();
|
|
1923
1918
|
});
|
|
1924
1919
|
}
|
|
1925
|
-
scheduleReposition() {
|
|
1926
|
-
if (this.pendingFrame != null || this.pendingRepositionFrame != null) {
|
|
1927
|
-
return;
|
|
1928
|
-
}
|
|
1929
|
-
this.pendingRepositionFrame = scheduleFrame(() => {
|
|
1930
|
-
this.pendingRepositionFrame = null;
|
|
1931
|
-
this.reposition();
|
|
1932
|
-
});
|
|
1933
|
-
}
|
|
1934
|
-
/**
|
|
1935
|
-
* Cheap scroll-driven path: slide the overlay to the element's new
|
|
1936
|
-
* viewport position without touching its contents. Scrolling can't change
|
|
1937
|
-
* an element's size, so the rects, viewBox and every hand-drawn stroke
|
|
1938
|
-
* inside them are still valid - only the overlay's position needs to move.
|
|
1939
|
-
*
|
|
1940
|
-
* That move is a `transform`, not `left`/`top`. `left`/`top` sit in the
|
|
1941
|
-
* same box-geometry pass as layout, so the browser re-checks layout on
|
|
1942
|
-
* every write; `transform` is composited, so the scroll path never
|
|
1943
|
-
* touches layout at all.
|
|
1944
|
-
*/
|
|
1945
|
-
reposition() {
|
|
1946
|
-
if (!this.svg || !this.element.isConnected) return;
|
|
1947
|
-
const { padding, radius } = this.options;
|
|
1948
|
-
const targets = this.getTargets();
|
|
1949
|
-
const margin = this.overlayMargin();
|
|
1950
|
-
const absoluteRects = targets.map(
|
|
1951
|
-
(target) => getElementBounds(target, padding, radius)
|
|
1952
|
-
);
|
|
1953
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
1954
|
-
const currentWidth = parseFloat(this.svg.style.width) || 0;
|
|
1955
|
-
const currentHeight = parseFloat(this.svg.style.height) || 0;
|
|
1956
|
-
const resized = Math.abs(overlayRect.width - currentWidth) > 0.5 || Math.abs(overlayRect.height - currentHeight) > 0.5;
|
|
1957
|
-
if (resized) {
|
|
1958
|
-
this.update();
|
|
1959
|
-
return;
|
|
1960
|
-
}
|
|
1961
|
-
const dx = overlayRect.x - this.basePosition.x;
|
|
1962
|
-
const dy = overlayRect.y - this.basePosition.y;
|
|
1963
|
-
this.svg.style.transform = `translate3d(${dx}px, ${dy}px, 0)`;
|
|
1964
|
-
}
|
|
1965
1920
|
getTargets() {
|
|
1966
1921
|
if (this.options.children) {
|
|
1967
1922
|
const nodes = this.element.querySelectorAll(this.options.children);
|
|
@@ -1973,23 +1928,23 @@ var DoodleOverlay = class {
|
|
|
1973
1928
|
if (!this.svg || !this.element.isConnected) return;
|
|
1974
1929
|
const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
|
|
1975
1930
|
const targets = this.getTargets();
|
|
1976
|
-
const margin = this.overlayMargin();
|
|
1977
1931
|
const elapsed = now() - this.startedAt;
|
|
1978
1932
|
const absoluteRects = targets.map(
|
|
1979
1933
|
(target) => getElementBounds(target, padding, radius)
|
|
1980
1934
|
);
|
|
1981
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
1982
1935
|
clearSvg(this.svg);
|
|
1983
1936
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
this.svg.
|
|
1989
|
-
this.svg.
|
|
1990
|
-
this.svg.
|
|
1991
|
-
this.svg.style.
|
|
1992
|
-
this.
|
|
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`;
|
|
1993
1948
|
const strokeStyle = { color, strokeWidth, roughness, opacity };
|
|
1994
1949
|
const noteStyle = {
|
|
1995
1950
|
color,
|
|
@@ -2000,12 +1955,12 @@ var DoodleOverlay = class {
|
|
|
2000
1955
|
};
|
|
2001
1956
|
const noteGroups = [];
|
|
2002
1957
|
const noteLayout = {
|
|
2003
|
-
band: localBand(
|
|
1958
|
+
band: localBand(origin.x),
|
|
2004
1959
|
gap: this.options.arrow ? 40 : 14
|
|
2005
1960
|
};
|
|
2006
1961
|
targets.forEach((target, index) => {
|
|
2007
1962
|
const absolute = absoluteRects[index];
|
|
2008
|
-
const local = relativeRect(
|
|
1963
|
+
const local = relativeRect(origin, absolute);
|
|
2009
1964
|
const seed = this.seed + index * 31;
|
|
2010
1965
|
const note = this.options.note && index === 0 ? renderAnnotation(
|
|
2011
1966
|
this.svg,
|
|
@@ -2051,24 +2006,11 @@ var DoodleOverlay = class {
|
|
|
2051
2006
|
this.svg.appendChild(group);
|
|
2052
2007
|
}
|
|
2053
2008
|
}
|
|
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
2009
|
destroy() {
|
|
2064
2010
|
if (this.pendingFrame != null) {
|
|
2065
2011
|
cancelFrame(this.pendingFrame);
|
|
2066
2012
|
this.pendingFrame = null;
|
|
2067
2013
|
}
|
|
2068
|
-
if (this.pendingRepositionFrame != null) {
|
|
2069
|
-
cancelFrame(this.pendingRepositionFrame);
|
|
2070
|
-
this.pendingRepositionFrame = null;
|
|
2071
|
-
}
|
|
2072
2014
|
if (this.resizeObserver) {
|
|
2073
2015
|
this.resizeObserver.disconnect();
|
|
2074
2016
|
this.resizeObserver = null;
|
|
@@ -2085,8 +2027,8 @@ var DoodleOverlay = class {
|
|
|
2085
2027
|
target.removeEventListener(type, handler);
|
|
2086
2028
|
}
|
|
2087
2029
|
this.listeners = [];
|
|
2088
|
-
if (this.svg
|
|
2089
|
-
this.svg.
|
|
2030
|
+
if (this.svg) {
|
|
2031
|
+
removeOverlaySvg(this.svg, this.element, this.setPosition);
|
|
2090
2032
|
}
|
|
2091
2033
|
this.svg = null;
|
|
2092
2034
|
instances.delete(this.element);
|
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") {
|
|
@@ -404,20 +408,6 @@ function isValidPosition(position) {
|
|
|
404
408
|
"center"
|
|
405
409
|
].includes(position);
|
|
406
410
|
}
|
|
407
|
-
function getScrollableAncestors(element) {
|
|
408
|
-
const ancestors = [];
|
|
409
|
-
let node = element.parentElement;
|
|
410
|
-
while (node && node !== document.documentElement) {
|
|
411
|
-
const style = getComputedStyle(node);
|
|
412
|
-
const overflow = style.overflow + style.overflowY + style.overflowX;
|
|
413
|
-
if (/(auto|scroll|overlay)/.test(overflow)) {
|
|
414
|
-
ancestors.push(node);
|
|
415
|
-
}
|
|
416
|
-
node = node.parentElement;
|
|
417
|
-
}
|
|
418
|
-
ancestors.push(window);
|
|
419
|
-
return ancestors;
|
|
420
|
-
}
|
|
421
411
|
function resolveOverlayZIndex(element, override) {
|
|
422
412
|
if (override != null) return override;
|
|
423
413
|
const { zIndex, position } = getComputedStyle(element);
|
|
@@ -437,12 +427,20 @@ function resolveOverlayZIndex(element, override) {
|
|
|
437
427
|
return null;
|
|
438
428
|
}
|
|
439
429
|
function insertOverlaySvg(svg, element) {
|
|
440
|
-
const
|
|
441
|
-
if (
|
|
442
|
-
|
|
443
|
-
|
|
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) {
|
|
438
|
+
if (svg.parentNode) {
|
|
439
|
+
svg.parentNode.removeChild(svg);
|
|
440
|
+
}
|
|
441
|
+
if (clearPosition) {
|
|
442
|
+
element.style.position = "";
|
|
444
443
|
}
|
|
445
|
-
parent.insertBefore(svg, element.nextSibling);
|
|
446
444
|
}
|
|
447
445
|
function syncOverlayStacking(svg, element, zIndexOverride) {
|
|
448
446
|
const zIndex = resolveOverlayZIndex(element, zIndexOverride);
|
|
@@ -469,7 +467,10 @@ function averageCornerRadius(element) {
|
|
|
469
467
|
function detectBorderRadius(element) {
|
|
470
468
|
const own = averageCornerRadius(element);
|
|
471
469
|
if (own > 0) return own;
|
|
472
|
-
const
|
|
470
|
+
const content = Array.from(element.children).filter(
|
|
471
|
+
(node) => !isOverlayNode(node)
|
|
472
|
+
);
|
|
473
|
+
const child = content.length === 1 ? content[0] : null;
|
|
473
474
|
if (!child) return 0;
|
|
474
475
|
const outer = element.getBoundingClientRect();
|
|
475
476
|
const inner = child.getBoundingClientRect();
|
|
@@ -500,22 +501,6 @@ function relativeRect(outer, inner) {
|
|
|
500
501
|
radius: inner.radius
|
|
501
502
|
};
|
|
502
503
|
}
|
|
503
|
-
function unionRects(rects, margin = 0) {
|
|
504
|
-
if (rects.length === 0) {
|
|
505
|
-
return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
|
|
506
|
-
}
|
|
507
|
-
const minX = Math.min(...rects.map((r) => r.x)) - margin;
|
|
508
|
-
const minY = Math.min(...rects.map((r) => r.y)) - margin;
|
|
509
|
-
const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
|
|
510
|
-
const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
|
|
511
|
-
return {
|
|
512
|
-
x: minX,
|
|
513
|
-
y: minY,
|
|
514
|
-
width: maxX - minX,
|
|
515
|
-
height: maxY - minY,
|
|
516
|
-
radius: 0
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
504
|
function inflateRect(rect, amount) {
|
|
520
505
|
return {
|
|
521
506
|
x: rect.x - amount,
|
|
@@ -1325,19 +1310,18 @@ function placeNoteText(note, box, style, seed, options = {}) {
|
|
|
1325
1310
|
}
|
|
1326
1311
|
function createOverlaySvg(left, top, width, height) {
|
|
1327
1312
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1328
|
-
svg.setAttribute("class",
|
|
1313
|
+
svg.setAttribute("class", OVERLAY_CLASS);
|
|
1329
1314
|
svg.setAttribute("xmlns", SVG_NS);
|
|
1330
1315
|
svg.setAttribute("width", String(width));
|
|
1331
1316
|
svg.setAttribute("height", String(height));
|
|
1332
1317
|
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
1333
|
-
svg.style.position = "
|
|
1318
|
+
svg.style.position = "absolute";
|
|
1334
1319
|
svg.style.left = `${left}px`;
|
|
1335
1320
|
svg.style.top = `${top}px`;
|
|
1336
1321
|
svg.style.width = `${width}px`;
|
|
1337
1322
|
svg.style.height = `${height}px`;
|
|
1338
1323
|
svg.style.pointerEvents = "none";
|
|
1339
1324
|
svg.style.overflow = "visible";
|
|
1340
|
-
svg.style.willChange = "transform";
|
|
1341
1325
|
return svg;
|
|
1342
1326
|
}
|
|
1343
1327
|
|
|
@@ -1868,13 +1852,27 @@ var instances = /* @__PURE__ */ new WeakMap();
|
|
|
1868
1852
|
function now() {
|
|
1869
1853
|
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
1870
1854
|
}
|
|
1871
|
-
function localBand(
|
|
1855
|
+
function localBand(originLeft, inset = 8) {
|
|
1872
1856
|
const width = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
1873
1857
|
return {
|
|
1874
|
-
x: -
|
|
1858
|
+
x: -originLeft + inset,
|
|
1875
1859
|
width: Math.max(0, width - inset * 2)
|
|
1876
1860
|
};
|
|
1877
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
|
+
}
|
|
1878
1876
|
var DoodleOverlay = class {
|
|
1879
1877
|
/**
|
|
1880
1878
|
* @param {Element} element
|
|
@@ -1886,13 +1884,11 @@ var DoodleOverlay = class {
|
|
|
1886
1884
|
this.seed = Math.floor(Math.random() * 1e9);
|
|
1887
1885
|
this.startedAt = now();
|
|
1888
1886
|
this.svg = null;
|
|
1887
|
+
this.setPosition = false;
|
|
1889
1888
|
this.resizeObserver = null;
|
|
1890
1889
|
this.mutationObserver = null;
|
|
1891
1890
|
this.pendingFrame = null;
|
|
1892
|
-
this.pendingRepositionFrame = null;
|
|
1893
|
-
this.basePosition = { x: 0, y: 0 };
|
|
1894
1891
|
this.listeners = [];
|
|
1895
|
-
this.onScroll = this.scheduleReposition.bind(this);
|
|
1896
1892
|
this.onResize = this.scheduleUpdate.bind(this);
|
|
1897
1893
|
this.onLanguageChange = this.scheduleUpdate.bind(this);
|
|
1898
1894
|
this.childElements = [];
|
|
@@ -1900,23 +1896,22 @@ var DoodleOverlay = class {
|
|
|
1900
1896
|
}
|
|
1901
1897
|
mount() {
|
|
1902
1898
|
this.svg = createOverlaySvg(0, 0, 0, 0);
|
|
1903
|
-
insertOverlaySvg(this.svg, this.element);
|
|
1899
|
+
this.setPosition = insertOverlaySvg(this.svg, this.element);
|
|
1904
1900
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
1905
1901
|
this.resizeObserver = new ResizeObserver(this.onResize);
|
|
1906
1902
|
this.resizeObserver.observe(this.element);
|
|
1907
1903
|
if (this.options.children) {
|
|
1908
1904
|
this.observeChildren();
|
|
1909
1905
|
}
|
|
1910
|
-
this.mutationObserver = new MutationObserver(
|
|
1906
|
+
this.mutationObserver = new MutationObserver((records) => {
|
|
1907
|
+
const relevant = records.some((record) => !this.svg.contains(record.target));
|
|
1908
|
+
if (relevant) this.scheduleUpdate();
|
|
1909
|
+
});
|
|
1911
1910
|
this.mutationObserver.observe(this.element, {
|
|
1912
1911
|
childList: true,
|
|
1913
1912
|
subtree: true,
|
|
1914
1913
|
attributes: true
|
|
1915
1914
|
});
|
|
1916
|
-
for (const target of getScrollableAncestors(this.element)) {
|
|
1917
|
-
target.addEventListener("scroll", this.onScroll, { passive: true });
|
|
1918
|
-
this.listeners.push({ target, type: "scroll", handler: this.onScroll });
|
|
1919
|
-
}
|
|
1920
1915
|
window.addEventListener("resize", this.onResize, { passive: true });
|
|
1921
1916
|
this.listeners.push({
|
|
1922
1917
|
target: window,
|
|
@@ -1952,46 +1947,6 @@ var DoodleOverlay = class {
|
|
|
1952
1947
|
this.update();
|
|
1953
1948
|
});
|
|
1954
1949
|
}
|
|
1955
|
-
scheduleReposition() {
|
|
1956
|
-
if (this.pendingFrame != null || this.pendingRepositionFrame != null) {
|
|
1957
|
-
return;
|
|
1958
|
-
}
|
|
1959
|
-
this.pendingRepositionFrame = scheduleFrame(() => {
|
|
1960
|
-
this.pendingRepositionFrame = null;
|
|
1961
|
-
this.reposition();
|
|
1962
|
-
});
|
|
1963
|
-
}
|
|
1964
|
-
/**
|
|
1965
|
-
* Cheap scroll-driven path: slide the overlay to the element's new
|
|
1966
|
-
* viewport position without touching its contents. Scrolling can't change
|
|
1967
|
-
* an element's size, so the rects, viewBox and every hand-drawn stroke
|
|
1968
|
-
* inside them are still valid - only the overlay's position needs to move.
|
|
1969
|
-
*
|
|
1970
|
-
* That move is a `transform`, not `left`/`top`. `left`/`top` sit in the
|
|
1971
|
-
* same box-geometry pass as layout, so the browser re-checks layout on
|
|
1972
|
-
* every write; `transform` is composited, so the scroll path never
|
|
1973
|
-
* touches layout at all.
|
|
1974
|
-
*/
|
|
1975
|
-
reposition() {
|
|
1976
|
-
if (!this.svg || !this.element.isConnected) return;
|
|
1977
|
-
const { padding, radius } = this.options;
|
|
1978
|
-
const targets = this.getTargets();
|
|
1979
|
-
const margin = this.overlayMargin();
|
|
1980
|
-
const absoluteRects = targets.map(
|
|
1981
|
-
(target) => getElementBounds(target, padding, radius)
|
|
1982
|
-
);
|
|
1983
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
1984
|
-
const currentWidth = parseFloat(this.svg.style.width) || 0;
|
|
1985
|
-
const currentHeight = parseFloat(this.svg.style.height) || 0;
|
|
1986
|
-
const resized = Math.abs(overlayRect.width - currentWidth) > 0.5 || Math.abs(overlayRect.height - currentHeight) > 0.5;
|
|
1987
|
-
if (resized) {
|
|
1988
|
-
this.update();
|
|
1989
|
-
return;
|
|
1990
|
-
}
|
|
1991
|
-
const dx = overlayRect.x - this.basePosition.x;
|
|
1992
|
-
const dy = overlayRect.y - this.basePosition.y;
|
|
1993
|
-
this.svg.style.transform = `translate3d(${dx}px, ${dy}px, 0)`;
|
|
1994
|
-
}
|
|
1995
1950
|
getTargets() {
|
|
1996
1951
|
if (this.options.children) {
|
|
1997
1952
|
const nodes = this.element.querySelectorAll(this.options.children);
|
|
@@ -2003,23 +1958,23 @@ var DoodleOverlay = class {
|
|
|
2003
1958
|
if (!this.svg || !this.element.isConnected) return;
|
|
2004
1959
|
const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
|
|
2005
1960
|
const targets = this.getTargets();
|
|
2006
|
-
const margin = this.overlayMargin();
|
|
2007
1961
|
const elapsed = now() - this.startedAt;
|
|
2008
1962
|
const absoluteRects = targets.map(
|
|
2009
1963
|
(target) => getElementBounds(target, padding, radius)
|
|
2010
1964
|
);
|
|
2011
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
2012
1965
|
clearSvg(this.svg);
|
|
2013
1966
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
this.svg.
|
|
2019
|
-
this.svg.
|
|
2020
|
-
this.svg.
|
|
2021
|
-
this.svg.style.
|
|
2022
|
-
this.
|
|
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`;
|
|
2023
1978
|
const strokeStyle = { color, strokeWidth, roughness, opacity };
|
|
2024
1979
|
const noteStyle = {
|
|
2025
1980
|
color,
|
|
@@ -2030,12 +1985,12 @@ var DoodleOverlay = class {
|
|
|
2030
1985
|
};
|
|
2031
1986
|
const noteGroups = [];
|
|
2032
1987
|
const noteLayout = {
|
|
2033
|
-
band: localBand(
|
|
1988
|
+
band: localBand(origin.x),
|
|
2034
1989
|
gap: this.options.arrow ? 40 : 14
|
|
2035
1990
|
};
|
|
2036
1991
|
targets.forEach((target, index) => {
|
|
2037
1992
|
const absolute = absoluteRects[index];
|
|
2038
|
-
const local = relativeRect(
|
|
1993
|
+
const local = relativeRect(origin, absolute);
|
|
2039
1994
|
const seed = this.seed + index * 31;
|
|
2040
1995
|
const note = this.options.note && index === 0 ? renderAnnotation(
|
|
2041
1996
|
this.svg,
|
|
@@ -2081,24 +2036,11 @@ var DoodleOverlay = class {
|
|
|
2081
2036
|
this.svg.appendChild(group);
|
|
2082
2037
|
}
|
|
2083
2038
|
}
|
|
2084
|
-
/**
|
|
2085
|
-
* Room the overlay needs beyond the element for notes, arrows and decorations.
|
|
2086
|
-
*/
|
|
2087
|
-
overlayMargin() {
|
|
2088
|
-
const { note, arrow, decorations } = this.options;
|
|
2089
|
-
if (!note && !arrow && !decorations) return 48;
|
|
2090
|
-
const { text } = resolveLocalizedText(note?.text, note?.locale);
|
|
2091
|
-
return Math.max(96, Math.min(240, 80 + text.length * 8));
|
|
2092
|
-
}
|
|
2093
2039
|
destroy() {
|
|
2094
2040
|
if (this.pendingFrame != null) {
|
|
2095
2041
|
cancelFrame(this.pendingFrame);
|
|
2096
2042
|
this.pendingFrame = null;
|
|
2097
2043
|
}
|
|
2098
|
-
if (this.pendingRepositionFrame != null) {
|
|
2099
|
-
cancelFrame(this.pendingRepositionFrame);
|
|
2100
|
-
this.pendingRepositionFrame = null;
|
|
2101
|
-
}
|
|
2102
2044
|
if (this.resizeObserver) {
|
|
2103
2045
|
this.resizeObserver.disconnect();
|
|
2104
2046
|
this.resizeObserver = null;
|
|
@@ -2115,8 +2057,8 @@ var DoodleOverlay = class {
|
|
|
2115
2057
|
target.removeEventListener(type, handler);
|
|
2116
2058
|
}
|
|
2117
2059
|
this.listeners = [];
|
|
2118
|
-
if (this.svg
|
|
2119
|
-
this.svg.
|
|
2060
|
+
if (this.svg) {
|
|
2061
|
+
removeOverlaySvg(this.svg, this.element, this.setPosition);
|
|
2120
2062
|
}
|
|
2121
2063
|
this.svg = null;
|
|
2122
2064
|
instances.delete(this.element);
|
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") {
|
|
@@ -387,20 +391,6 @@ function isValidPosition(position) {
|
|
|
387
391
|
"center"
|
|
388
392
|
].includes(position);
|
|
389
393
|
}
|
|
390
|
-
function getScrollableAncestors(element) {
|
|
391
|
-
const ancestors = [];
|
|
392
|
-
let node = element.parentElement;
|
|
393
|
-
while (node && node !== document.documentElement) {
|
|
394
|
-
const style = getComputedStyle(node);
|
|
395
|
-
const overflow = style.overflow + style.overflowY + style.overflowX;
|
|
396
|
-
if (/(auto|scroll|overlay)/.test(overflow)) {
|
|
397
|
-
ancestors.push(node);
|
|
398
|
-
}
|
|
399
|
-
node = node.parentElement;
|
|
400
|
-
}
|
|
401
|
-
ancestors.push(window);
|
|
402
|
-
return ancestors;
|
|
403
|
-
}
|
|
404
394
|
function resolveOverlayZIndex(element, override) {
|
|
405
395
|
if (override != null) return override;
|
|
406
396
|
const { zIndex, position } = getComputedStyle(element);
|
|
@@ -420,12 +410,20 @@ function resolveOverlayZIndex(element, override) {
|
|
|
420
410
|
return null;
|
|
421
411
|
}
|
|
422
412
|
function insertOverlaySvg(svg, element) {
|
|
423
|
-
const
|
|
424
|
-
if (
|
|
425
|
-
|
|
426
|
-
|
|
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) {
|
|
421
|
+
if (svg.parentNode) {
|
|
422
|
+
svg.parentNode.removeChild(svg);
|
|
423
|
+
}
|
|
424
|
+
if (clearPosition) {
|
|
425
|
+
element.style.position = "";
|
|
427
426
|
}
|
|
428
|
-
parent.insertBefore(svg, element.nextSibling);
|
|
429
427
|
}
|
|
430
428
|
function syncOverlayStacking(svg, element, zIndexOverride) {
|
|
431
429
|
const zIndex = resolveOverlayZIndex(element, zIndexOverride);
|
|
@@ -452,7 +450,10 @@ function averageCornerRadius(element) {
|
|
|
452
450
|
function detectBorderRadius(element) {
|
|
453
451
|
const own = averageCornerRadius(element);
|
|
454
452
|
if (own > 0) return own;
|
|
455
|
-
const
|
|
453
|
+
const content = Array.from(element.children).filter(
|
|
454
|
+
(node) => !isOverlayNode(node)
|
|
455
|
+
);
|
|
456
|
+
const child = content.length === 1 ? content[0] : null;
|
|
456
457
|
if (!child) return 0;
|
|
457
458
|
const outer = element.getBoundingClientRect();
|
|
458
459
|
const inner = child.getBoundingClientRect();
|
|
@@ -483,22 +484,6 @@ function relativeRect(outer, inner) {
|
|
|
483
484
|
radius: inner.radius
|
|
484
485
|
};
|
|
485
486
|
}
|
|
486
|
-
function unionRects(rects, margin = 0) {
|
|
487
|
-
if (rects.length === 0) {
|
|
488
|
-
return { x: 0, y: 0, width: 0, height: 0, radius: 0 };
|
|
489
|
-
}
|
|
490
|
-
const minX = Math.min(...rects.map((r) => r.x)) - margin;
|
|
491
|
-
const minY = Math.min(...rects.map((r) => r.y)) - margin;
|
|
492
|
-
const maxX = Math.max(...rects.map((r) => r.x + r.width)) + margin;
|
|
493
|
-
const maxY = Math.max(...rects.map((r) => r.y + r.height)) + margin;
|
|
494
|
-
return {
|
|
495
|
-
x: minX,
|
|
496
|
-
y: minY,
|
|
497
|
-
width: maxX - minX,
|
|
498
|
-
height: maxY - minY,
|
|
499
|
-
radius: 0
|
|
500
|
-
};
|
|
501
|
-
}
|
|
502
487
|
function inflateRect(rect, amount) {
|
|
503
488
|
return {
|
|
504
489
|
x: rect.x - amount,
|
|
@@ -1308,19 +1293,18 @@ function placeNoteText(note, box, style, seed, options = {}) {
|
|
|
1308
1293
|
}
|
|
1309
1294
|
function createOverlaySvg(left, top, width, height) {
|
|
1310
1295
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
1311
|
-
svg.setAttribute("class",
|
|
1296
|
+
svg.setAttribute("class", OVERLAY_CLASS);
|
|
1312
1297
|
svg.setAttribute("xmlns", SVG_NS);
|
|
1313
1298
|
svg.setAttribute("width", String(width));
|
|
1314
1299
|
svg.setAttribute("height", String(height));
|
|
1315
1300
|
svg.setAttribute("viewBox", `0 0 ${width} ${height}`);
|
|
1316
|
-
svg.style.position = "
|
|
1301
|
+
svg.style.position = "absolute";
|
|
1317
1302
|
svg.style.left = `${left}px`;
|
|
1318
1303
|
svg.style.top = `${top}px`;
|
|
1319
1304
|
svg.style.width = `${width}px`;
|
|
1320
1305
|
svg.style.height = `${height}px`;
|
|
1321
1306
|
svg.style.pointerEvents = "none";
|
|
1322
1307
|
svg.style.overflow = "visible";
|
|
1323
|
-
svg.style.willChange = "transform";
|
|
1324
1308
|
return svg;
|
|
1325
1309
|
}
|
|
1326
1310
|
|
|
@@ -1851,13 +1835,27 @@ var instances = /* @__PURE__ */ new WeakMap();
|
|
|
1851
1835
|
function now() {
|
|
1852
1836
|
return typeof performance !== "undefined" && performance.now ? performance.now() : Date.now();
|
|
1853
1837
|
}
|
|
1854
|
-
function localBand(
|
|
1838
|
+
function localBand(originLeft, inset = 8) {
|
|
1855
1839
|
const width = window.innerWidth || document.documentElement.clientWidth || 0;
|
|
1856
1840
|
return {
|
|
1857
|
-
x: -
|
|
1841
|
+
x: -originLeft + inset,
|
|
1858
1842
|
width: Math.max(0, width - inset * 2)
|
|
1859
1843
|
};
|
|
1860
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
|
+
}
|
|
1861
1859
|
var DoodleOverlay = class {
|
|
1862
1860
|
/**
|
|
1863
1861
|
* @param {Element} element
|
|
@@ -1869,13 +1867,11 @@ var DoodleOverlay = class {
|
|
|
1869
1867
|
this.seed = Math.floor(Math.random() * 1e9);
|
|
1870
1868
|
this.startedAt = now();
|
|
1871
1869
|
this.svg = null;
|
|
1870
|
+
this.setPosition = false;
|
|
1872
1871
|
this.resizeObserver = null;
|
|
1873
1872
|
this.mutationObserver = null;
|
|
1874
1873
|
this.pendingFrame = null;
|
|
1875
|
-
this.pendingRepositionFrame = null;
|
|
1876
|
-
this.basePosition = { x: 0, y: 0 };
|
|
1877
1874
|
this.listeners = [];
|
|
1878
|
-
this.onScroll = this.scheduleReposition.bind(this);
|
|
1879
1875
|
this.onResize = this.scheduleUpdate.bind(this);
|
|
1880
1876
|
this.onLanguageChange = this.scheduleUpdate.bind(this);
|
|
1881
1877
|
this.childElements = [];
|
|
@@ -1883,23 +1879,22 @@ var DoodleOverlay = class {
|
|
|
1883
1879
|
}
|
|
1884
1880
|
mount() {
|
|
1885
1881
|
this.svg = createOverlaySvg(0, 0, 0, 0);
|
|
1886
|
-
insertOverlaySvg(this.svg, this.element);
|
|
1882
|
+
this.setPosition = insertOverlaySvg(this.svg, this.element);
|
|
1887
1883
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
1888
1884
|
this.resizeObserver = new ResizeObserver(this.onResize);
|
|
1889
1885
|
this.resizeObserver.observe(this.element);
|
|
1890
1886
|
if (this.options.children) {
|
|
1891
1887
|
this.observeChildren();
|
|
1892
1888
|
}
|
|
1893
|
-
this.mutationObserver = new MutationObserver(
|
|
1889
|
+
this.mutationObserver = new MutationObserver((records) => {
|
|
1890
|
+
const relevant = records.some((record) => !this.svg.contains(record.target));
|
|
1891
|
+
if (relevant) this.scheduleUpdate();
|
|
1892
|
+
});
|
|
1894
1893
|
this.mutationObserver.observe(this.element, {
|
|
1895
1894
|
childList: true,
|
|
1896
1895
|
subtree: true,
|
|
1897
1896
|
attributes: true
|
|
1898
1897
|
});
|
|
1899
|
-
for (const target of getScrollableAncestors(this.element)) {
|
|
1900
|
-
target.addEventListener("scroll", this.onScroll, { passive: true });
|
|
1901
|
-
this.listeners.push({ target, type: "scroll", handler: this.onScroll });
|
|
1902
|
-
}
|
|
1903
1898
|
window.addEventListener("resize", this.onResize, { passive: true });
|
|
1904
1899
|
this.listeners.push({
|
|
1905
1900
|
target: window,
|
|
@@ -1935,46 +1930,6 @@ var DoodleOverlay = class {
|
|
|
1935
1930
|
this.update();
|
|
1936
1931
|
});
|
|
1937
1932
|
}
|
|
1938
|
-
scheduleReposition() {
|
|
1939
|
-
if (this.pendingFrame != null || this.pendingRepositionFrame != null) {
|
|
1940
|
-
return;
|
|
1941
|
-
}
|
|
1942
|
-
this.pendingRepositionFrame = scheduleFrame(() => {
|
|
1943
|
-
this.pendingRepositionFrame = null;
|
|
1944
|
-
this.reposition();
|
|
1945
|
-
});
|
|
1946
|
-
}
|
|
1947
|
-
/**
|
|
1948
|
-
* Cheap scroll-driven path: slide the overlay to the element's new
|
|
1949
|
-
* viewport position without touching its contents. Scrolling can't change
|
|
1950
|
-
* an element's size, so the rects, viewBox and every hand-drawn stroke
|
|
1951
|
-
* inside them are still valid - only the overlay's position needs to move.
|
|
1952
|
-
*
|
|
1953
|
-
* That move is a `transform`, not `left`/`top`. `left`/`top` sit in the
|
|
1954
|
-
* same box-geometry pass as layout, so the browser re-checks layout on
|
|
1955
|
-
* every write; `transform` is composited, so the scroll path never
|
|
1956
|
-
* touches layout at all.
|
|
1957
|
-
*/
|
|
1958
|
-
reposition() {
|
|
1959
|
-
if (!this.svg || !this.element.isConnected) return;
|
|
1960
|
-
const { padding, radius } = this.options;
|
|
1961
|
-
const targets = this.getTargets();
|
|
1962
|
-
const margin = this.overlayMargin();
|
|
1963
|
-
const absoluteRects = targets.map(
|
|
1964
|
-
(target) => getElementBounds(target, padding, radius)
|
|
1965
|
-
);
|
|
1966
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
1967
|
-
const currentWidth = parseFloat(this.svg.style.width) || 0;
|
|
1968
|
-
const currentHeight = parseFloat(this.svg.style.height) || 0;
|
|
1969
|
-
const resized = Math.abs(overlayRect.width - currentWidth) > 0.5 || Math.abs(overlayRect.height - currentHeight) > 0.5;
|
|
1970
|
-
if (resized) {
|
|
1971
|
-
this.update();
|
|
1972
|
-
return;
|
|
1973
|
-
}
|
|
1974
|
-
const dx = overlayRect.x - this.basePosition.x;
|
|
1975
|
-
const dy = overlayRect.y - this.basePosition.y;
|
|
1976
|
-
this.svg.style.transform = `translate3d(${dx}px, ${dy}px, 0)`;
|
|
1977
|
-
}
|
|
1978
1933
|
getTargets() {
|
|
1979
1934
|
if (this.options.children) {
|
|
1980
1935
|
const nodes = this.element.querySelectorAll(this.options.children);
|
|
@@ -1986,23 +1941,23 @@ var DoodleOverlay = class {
|
|
|
1986
1941
|
if (!this.svg || !this.element.isConnected) return;
|
|
1987
1942
|
const { padding, radius, color, strokeWidth, roughness, opacity } = this.options;
|
|
1988
1943
|
const targets = this.getTargets();
|
|
1989
|
-
const margin = this.overlayMargin();
|
|
1990
1944
|
const elapsed = now() - this.startedAt;
|
|
1991
1945
|
const absoluteRects = targets.map(
|
|
1992
1946
|
(target) => getElementBounds(target, padding, radius)
|
|
1993
1947
|
);
|
|
1994
|
-
const overlayRect = unionRects(absoluteRects, margin);
|
|
1995
1948
|
clearSvg(this.svg);
|
|
1996
1949
|
syncOverlayStacking(this.svg, this.element, this.options.zIndex);
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
this.svg.
|
|
2002
|
-
this.svg.
|
|
2003
|
-
this.svg.
|
|
2004
|
-
this.svg.style.
|
|
2005
|
-
this.
|
|
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`;
|
|
2006
1961
|
const strokeStyle = { color, strokeWidth, roughness, opacity };
|
|
2007
1962
|
const noteStyle = {
|
|
2008
1963
|
color,
|
|
@@ -2013,12 +1968,12 @@ var DoodleOverlay = class {
|
|
|
2013
1968
|
};
|
|
2014
1969
|
const noteGroups = [];
|
|
2015
1970
|
const noteLayout = {
|
|
2016
|
-
band: localBand(
|
|
1971
|
+
band: localBand(origin.x),
|
|
2017
1972
|
gap: this.options.arrow ? 40 : 14
|
|
2018
1973
|
};
|
|
2019
1974
|
targets.forEach((target, index) => {
|
|
2020
1975
|
const absolute = absoluteRects[index];
|
|
2021
|
-
const local = relativeRect(
|
|
1976
|
+
const local = relativeRect(origin, absolute);
|
|
2022
1977
|
const seed = this.seed + index * 31;
|
|
2023
1978
|
const note = this.options.note && index === 0 ? renderAnnotation(
|
|
2024
1979
|
this.svg,
|
|
@@ -2064,24 +2019,11 @@ var DoodleOverlay = class {
|
|
|
2064
2019
|
this.svg.appendChild(group);
|
|
2065
2020
|
}
|
|
2066
2021
|
}
|
|
2067
|
-
/**
|
|
2068
|
-
* Room the overlay needs beyond the element for notes, arrows and decorations.
|
|
2069
|
-
*/
|
|
2070
|
-
overlayMargin() {
|
|
2071
|
-
const { note, arrow, decorations } = this.options;
|
|
2072
|
-
if (!note && !arrow && !decorations) return 48;
|
|
2073
|
-
const { text } = resolveLocalizedText(note?.text, note?.locale);
|
|
2074
|
-
return Math.max(96, Math.min(240, 80 + text.length * 8));
|
|
2075
|
-
}
|
|
2076
2022
|
destroy() {
|
|
2077
2023
|
if (this.pendingFrame != null) {
|
|
2078
2024
|
cancelFrame(this.pendingFrame);
|
|
2079
2025
|
this.pendingFrame = null;
|
|
2080
2026
|
}
|
|
2081
|
-
if (this.pendingRepositionFrame != null) {
|
|
2082
|
-
cancelFrame(this.pendingRepositionFrame);
|
|
2083
|
-
this.pendingRepositionFrame = null;
|
|
2084
|
-
}
|
|
2085
2027
|
if (this.resizeObserver) {
|
|
2086
2028
|
this.resizeObserver.disconnect();
|
|
2087
2029
|
this.resizeObserver = null;
|
|
@@ -2098,8 +2040,8 @@ var DoodleOverlay = class {
|
|
|
2098
2040
|
target.removeEventListener(type, handler);
|
|
2099
2041
|
}
|
|
2100
2042
|
this.listeners = [];
|
|
2101
|
-
if (this.svg
|
|
2102
|
-
this.svg.
|
|
2043
|
+
if (this.svg) {
|
|
2044
|
+
removeOverlaySvg(this.svg, this.element, this.setPosition);
|
|
2103
2045
|
}
|
|
2104
2046
|
this.svg = null;
|
|
2105
2047
|
instances.delete(this.element);
|
package/package.json
CHANGED