mesurer 0.0.7 → 0.0.9
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/CHANGELOG.md +18 -0
- package/README.md +4 -0
- package/dist/index.cjs +2308 -540
- package/dist/index.d.cts +39 -2
- package/dist/index.d.ts +39 -2
- package/dist/index.js +2291 -526
- package/dist/styles.css +37 -0
- package/package.json +11 -10
package/dist/index.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
// measurer.tsx
|
|
2
2
|
import {
|
|
3
3
|
useCallback as useCallback6,
|
|
4
|
-
useEffect as
|
|
4
|
+
useEffect as useEffect5,
|
|
5
5
|
useMemo as useMemo2,
|
|
6
|
-
useRef as
|
|
7
|
-
useState as
|
|
6
|
+
useRef as useRef9,
|
|
7
|
+
useState as useState8,
|
|
8
8
|
useSyncExternalStore
|
|
9
9
|
} from "react";
|
|
10
10
|
import { createPortal } from "react-dom";
|
|
11
11
|
|
|
12
|
-
// constants.ts
|
|
12
|
+
// core/constants.ts
|
|
13
13
|
var MEASURE_LABEL_OFFSET = 2;
|
|
14
14
|
var GUIDE_SNAP_DISTANCE = 10;
|
|
15
15
|
var GUIDE_HITBOX_SIZE = 14;
|
|
@@ -22,15 +22,17 @@ var ANCESTOR_KEEP_COVERAGE = 0.92;
|
|
|
22
22
|
var MIN_SINGLE_TARGET_SIZE = 8;
|
|
23
23
|
var MIN_SINGLE_ELEMENT_COVERAGE = 0.15;
|
|
24
24
|
|
|
25
|
-
// style-inject.ts
|
|
25
|
+
// runtime/style-inject.ts
|
|
26
26
|
var MESURER_STYLE_ID = "mesurer-styles";
|
|
27
|
+
var isDocument = (target) => target.nodeType === 9;
|
|
28
|
+
var isShadowRoot = (target) => target.nodeType === 11;
|
|
27
29
|
var getStyleTarget = (target) => {
|
|
28
30
|
if (typeof document === "undefined") return null;
|
|
29
31
|
if (!target) return document;
|
|
30
|
-
if (target
|
|
32
|
+
if (isShadowRoot(target)) return target;
|
|
31
33
|
const rootNode = target.getRootNode();
|
|
32
|
-
if (rootNode
|
|
33
|
-
return document;
|
|
34
|
+
if (rootNode.nodeType === 11) return rootNode;
|
|
35
|
+
return target.ownerDocument ?? document;
|
|
34
36
|
};
|
|
35
37
|
function ensureMeasurerStyles(cssText, target) {
|
|
36
38
|
if (typeof document === "undefined") return;
|
|
@@ -38,31 +40,32 @@ function ensureMeasurerStyles(cssText, target) {
|
|
|
38
40
|
const styleTarget = getStyleTarget(target);
|
|
39
41
|
if (!styleTarget) return;
|
|
40
42
|
if (styleTarget.querySelector(`#${MESURER_STYLE_ID}`)) return;
|
|
41
|
-
const
|
|
43
|
+
const ownerDocument = isDocument(styleTarget) ? styleTarget : styleTarget.ownerDocument;
|
|
44
|
+
if (!ownerDocument) return;
|
|
45
|
+
const style = ownerDocument.createElement("style");
|
|
42
46
|
style.id = MESURER_STYLE_ID;
|
|
43
47
|
style.textContent = cssText;
|
|
44
|
-
if (styleTarget
|
|
48
|
+
if (isShadowRoot(styleTarget)) {
|
|
45
49
|
styleTarget.appendChild(style);
|
|
46
50
|
return;
|
|
47
51
|
}
|
|
48
|
-
|
|
52
|
+
ownerDocument.head.appendChild(style);
|
|
49
53
|
}
|
|
50
54
|
|
|
51
55
|
// styles.generated.ts
|
|
52
|
-
var MESURER_STYLES = '/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --msr-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",\n "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n --msr-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",\n "Courier New", monospace;\n --msr-color-black: #000;\n --msr-color-white: #fff;\n --msr-spacing: 0.25rem;\n --msr-radius-md: 0.375rem;\n --msr-radius-lg: 0.5rem;\n --msr-default-transition-duration: 150ms;\n --msr-default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --msr-default-font-family: var(--msr-font-sans);\n --msr-default-mono-font-family: var(--msr-font-mono);\n --msr-color-ink-50: var(--color-ink-50);\n --msr-color-ink-200: var(--color-ink-200);\n --msr-color-ink-700: var(--color-ink-700);\n --msr-color-ink-900: var(--color-ink-900);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--msr-default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--msr-default-font-feature-settings, normal);\n font-variation-settings: var(--msr-default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--msr-default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--msr-default-mono-font-feature-settings, normal);\n font-variation-settings: var(--msr-default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden="until-found"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .msr\\:pointer-events-auto {\n pointer-events: auto;\n }\n .msr\\:pointer-events-none {\n pointer-events: none;\n }\n .msr\\:absolute {\n position: absolute;\n }\n .msr\\:fixed {\n position: fixed;\n }\n .msr\\:relative {\n position: relative;\n }\n .msr\\:inset-0 {\n inset: calc(var(--msr-spacing) * 0);\n }\n .msr\\:top-0 {\n top: calc(var(--msr-spacing) * 0);\n }\n .msr\\:top-full {\n top: 100%;\n }\n .msr\\:right-0 {\n right: calc(var(--msr-spacing) * 0);\n }\n .msr\\:bottom-0 {\n bottom: calc(var(--msr-spacing) * 0);\n }\n .msr\\:bottom-full {\n bottom: 100%;\n }\n .msr\\:left-0 {\n left: calc(var(--msr-spacing) * 0);\n }\n .msr\\:left-1\\/2 {\n left: calc(1 / 2 * 100%);\n }\n .msr\\:z-50 {\n z-index: 50;\n }\n .msr\\:z-\\[70\\] {\n z-index: 70;\n }\n .msr\\:z-\\[90\\] {\n z-index: 90;\n }\n .msr\\:mt-2 {\n margin-top: calc(var(--msr-spacing) * 2);\n }\n .msr\\:mb-2 {\n margin-bottom: calc(var(--msr-spacing) * 2);\n }\n .msr\\:-ml-1 {\n margin-left: calc(var(--msr-spacing) * -1);\n }\n .msr\\:flex {\n display: flex;\n }\n .msr\\:size-8 {\n width: calc(var(--msr-spacing) * 8);\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:h-8 {\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:h-full {\n height: 100%;\n }\n .msr\\:h-px {\n height: 1px;\n }\n .msr\\:w-4 {\n width: calc(var(--msr-spacing) * 4);\n }\n .msr\\:w-44 {\n width: calc(var(--msr-spacing) * 44);\n }\n .msr\\:w-full {\n width: 100%;\n }\n .msr\\:w-px {\n width: 1px;\n }\n .msr\\:flex-1 {\n flex: 1;\n }\n .msr\\:-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1 / 2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .msr\\:-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1 / 2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .msr\\:rotate-90 {\n rotate: 90deg;\n }\n .msr\\:rotate-\\[45deg\\] {\n rotate: 45deg;\n }\n .msr\\:rotate-\\[135deg\\] {\n rotate: 135deg;\n }\n .msr\\:cursor-crosshair {\n cursor: crosshair;\n }\n .msr\\:cursor-default {\n cursor: default;\n }\n .msr\\:flex-col {\n flex-direction: column;\n }\n .msr\\:items-center {\n align-items: center;\n }\n .msr\\:items-stretch {\n align-items: stretch;\n }\n .msr\\:justify-center {\n justify-content: center;\n }\n .msr\\:gap-1 {\n gap: calc(var(--msr-spacing) * 1);\n }\n .msr\\:gap-2 {\n gap: calc(var(--msr-spacing) * 2);\n }\n .msr\\:gap-px {\n gap: 1px;\n }\n .msr\\:rounded {\n border-radius: 0.25rem;\n }\n .msr\\:rounded-\\[6px\\] {\n border-radius: 6px;\n }\n .msr\\:rounded-\\[8px\\] {\n border-radius: 8px;\n }\n .msr\\:rounded-\\[12px\\] {\n border-radius: 12px;\n }\n .msr\\:rounded-lg {\n border-radius: var(--msr-radius-lg);\n }\n .msr\\:rounded-md {\n border-radius: var(--msr-radius-md);\n }\n .msr\\:border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .msr\\:border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .msr\\:border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .msr\\:border-dashed {\n --tw-border-style: dashed;\n border-style: dashed;\n }\n .msr\\:border-\\[\\#2563eb\\]\\/70 {\n border-color: color-mix(in oklab, #2563eb 70%, transparent);\n }\n .msr\\:border-ink-200 {\n border-color: var(--msr-color-ink-200);\n }\n .msr\\:bg-\\[\\#0d99ff\\] {\n background-color: #0d99ff;\n }\n .msr\\:bg-\\[\\#2563eb\\] {\n background-color: #2563eb;\n }\n .msr\\:bg-\\[\\#fff\\] {\n background-color: #fff;\n }\n .msr\\:bg-black {\n background-color: var(--msr-color-black);\n }\n .msr\\:bg-black\\/10 {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n .msr\\:bg-ink-900\\/90 {\n background-color: var(--msr-color-ink-900);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-ink-900) 90%, transparent);\n }\n }\n .msr\\:bg-transparent {\n background-color: transparent;\n }\n .msr\\:bg-white {\n background-color: var(--msr-color-white);\n }\n .msr\\:p-1 {\n padding: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-1 {\n padding-inline: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-2 {\n padding-inline: calc(var(--msr-spacing) * 2);\n }\n .msr\\:py-0\\.5 {\n padding-block: calc(var(--msr-spacing) * 0.5);\n }\n .msr\\:py-1 {\n padding-block: calc(var(--msr-spacing) * 1);\n }\n .msr\\:py-1\\.5 {\n padding-block: calc(var(--msr-spacing) * 1.5);\n }\n .msr\\:text-left {\n text-align: left;\n }\n .msr\\:text-\\[10px\\] {\n font-size: 10px;\n }\n .msr\\:text-\\[11px\\] {\n font-size: 11px;\n }\n .msr\\:text-\\[12px\\] {\n font-size: 12px;\n }\n .msr\\:whitespace-nowrap {\n white-space: nowrap;\n }\n .msr\\:text-black {\n color: var(--msr-color-black);\n }\n .msr\\:text-ink-50 {\n color: var(--msr-color-ink-50);\n }\n .msr\\:text-ink-700 {\n color: var(--msr-color-ink-700);\n }\n .msr\\:text-white {\n color: var(--msr-color-white);\n }\n .msr\\:text-white\\/60 {\n color: var(--msr-color-white);\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, var(--msr-color-white) 60%, transparent);\n }\n }\n .msr\\:tabular-nums {\n --tw-numeric-spacing: tabular-nums;\n font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);\n }\n .msr\\:opacity-0 {\n opacity: 0%;\n }\n .msr\\:opacity-100 {\n opacity: 100%;\n }\n .msr\\:outline {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n .msr\\:outline-transparent {\n outline-color: transparent;\n }\n .msr\\:transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--msr-default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--msr-default-transition-duration));\n }\n .msr\\:duration-150 {\n --tw-duration: 150ms;\n transition-duration: 150ms;\n }\n .msr\\:outline-none {\n --tw-outline-style: none;\n outline-style: none;\n }\n .msr\\:select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .msr\\:hover\\:bg-\\[\\#0d99ff\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #0d99ff;\n }\n }\n }\n .msr\\:hover\\:bg-black\\/4 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 4%, transparent);\n }\n }\n }\n }\n .msr\\:hover\\:bg-black\\/10 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n }\n }\n .msr\\:hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--msr-color-white);\n }\n }\n }\n .msr\\:focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n}\n:root, :host {\n --color-ink-50: #f8fafc;\n --color-ink-200: #e2e8f0;\n --color-ink-500: #64748b;\n --color-ink-700: #334155;\n --color-ink-900: #0f172a;\n}\n.mesurer-toolbar-surface {\n box-shadow: 0 0 0.5px rgba(0, 0, 0, 0.18), 0 3px 8px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.mesurer-menu-surface {\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);\n}\n@property --tw-translate-x {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: "*";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-ordinal {\n syntax: "*";\n inherits: false;\n}\n@property --tw-slashed-zero {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-figure {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-spacing {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-fraction {\n syntax: "*";\n inherits: false;\n}\n@property --tw-outline-style {\n syntax: "*";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-duration {\n syntax: "*";\n inherits: false;\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-border-style: solid;\n --tw-ordinal: initial;\n --tw-slashed-zero: initial;\n --tw-numeric-figure: initial;\n --tw-numeric-spacing: initial;\n --tw-numeric-fraction: initial;\n --tw-outline-style: solid;\n --tw-duration: initial;\n }\n }\n}\n';
|
|
56
|
+
var MESURER_STYLES = '/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --msr-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",\n "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n --msr-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",\n "Courier New", monospace;\n --msr-color-black: #000;\n --msr-color-white: #fff;\n --msr-spacing: 0.25rem;\n --msr-radius-md: 0.375rem;\n --msr-radius-lg: 0.5rem;\n --msr-default-transition-duration: 150ms;\n --msr-default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --msr-default-font-family: var(--msr-font-sans);\n --msr-default-mono-font-family: var(--msr-font-mono);\n --msr-color-ink-50: var(--color-ink-50);\n --msr-color-ink-200: var(--color-ink-200);\n --msr-color-ink-700: var(--color-ink-700);\n --msr-color-ink-900: var(--color-ink-900);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--msr-default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--msr-default-font-feature-settings, normal);\n font-variation-settings: var(--msr-default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--msr-default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--msr-default-mono-font-feature-settings, normal);\n font-variation-settings: var(--msr-default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden="until-found"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .msr\\:pointer-events-auto {\n pointer-events: auto;\n }\n .msr\\:pointer-events-none {\n pointer-events: none;\n }\n .msr\\:absolute {\n position: absolute;\n }\n .msr\\:fixed {\n position: fixed;\n }\n .msr\\:relative {\n position: relative;\n }\n .msr\\:inset-0 {\n inset: calc(var(--msr-spacing) * 0);\n }\n .msr\\:top-0 {\n top: calc(var(--msr-spacing) * 0);\n }\n .msr\\:top-\\[18px\\] {\n top: 18px;\n }\n .msr\\:top-full {\n top: 100%;\n }\n .msr\\:right-0 {\n right: calc(var(--msr-spacing) * 0);\n }\n .msr\\:bottom-0 {\n bottom: calc(var(--msr-spacing) * 0);\n }\n .msr\\:bottom-full {\n bottom: 100%;\n }\n .msr\\:left-0 {\n left: calc(var(--msr-spacing) * 0);\n }\n .msr\\:left-1\\/2 {\n left: calc(1 / 2 * 100%);\n }\n .msr\\:left-\\[18px\\] {\n left: 18px;\n }\n .msr\\:z-50 {\n z-index: 50;\n }\n .msr\\:z-\\[70\\] {\n z-index: 70;\n }\n .msr\\:z-\\[90\\] {\n z-index: 90;\n }\n .msr\\:mt-2 {\n margin-top: calc(var(--msr-spacing) * 2);\n }\n .msr\\:mb-2 {\n margin-bottom: calc(var(--msr-spacing) * 2);\n }\n .msr\\:-ml-1 {\n margin-left: calc(var(--msr-spacing) * -1);\n }\n .msr\\:block {\n display: block;\n }\n .msr\\:flex {\n display: flex;\n }\n .msr\\:size-8 {\n width: calc(var(--msr-spacing) * 8);\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:size-\\[18px\\] {\n width: 18px;\n height: 18px;\n }\n .msr\\:h-6 {\n height: calc(var(--msr-spacing) * 6);\n }\n .msr\\:h-8 {\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:h-full {\n height: 100%;\n }\n .msr\\:h-px {\n height: 1px;\n }\n .msr\\:w-4 {\n width: calc(var(--msr-spacing) * 4);\n }\n .msr\\:w-6 {\n width: calc(var(--msr-spacing) * 6);\n }\n .msr\\:w-44 {\n width: calc(var(--msr-spacing) * 44);\n }\n .msr\\:w-\\[18px\\] {\n width: 18px;\n }\n .msr\\:w-full {\n width: 100%;\n }\n .msr\\:w-px {\n width: 1px;\n }\n .msr\\:flex-1 {\n flex: 1;\n }\n .msr\\:-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1 / 2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .msr\\:-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1 / 2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .msr\\:rotate-90 {\n rotate: 90deg;\n }\n .msr\\:rotate-\\[45deg\\] {\n rotate: 45deg;\n }\n .msr\\:rotate-\\[135deg\\] {\n rotate: 135deg;\n }\n .msr\\:cursor-crosshair {\n cursor: crosshair;\n }\n .msr\\:cursor-default {\n cursor: default;\n }\n .msr\\:flex-col {\n flex-direction: column;\n }\n .msr\\:items-center {\n align-items: center;\n }\n .msr\\:items-stretch {\n align-items: stretch;\n }\n .msr\\:justify-center {\n justify-content: center;\n }\n .msr\\:gap-1 {\n gap: calc(var(--msr-spacing) * 1);\n }\n .msr\\:gap-2 {\n gap: calc(var(--msr-spacing) * 2);\n }\n .msr\\:gap-px {\n gap: 1px;\n }\n .msr\\:overflow-hidden {\n overflow: hidden;\n }\n .msr\\:rounded {\n border-radius: 0.25rem;\n }\n .msr\\:rounded-\\[6px\\] {\n border-radius: 6px;\n }\n .msr\\:rounded-\\[8px\\] {\n border-radius: 8px;\n }\n .msr\\:rounded-\\[12px\\] {\n border-radius: 12px;\n }\n .msr\\:rounded-lg {\n border-radius: var(--msr-radius-lg);\n }\n .msr\\:rounded-md {\n border-radius: var(--msr-radius-md);\n }\n .msr\\:border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .msr\\:border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .msr\\:border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .msr\\:border-dashed {\n --tw-border-style: dashed;\n border-style: dashed;\n }\n .msr\\:border-\\[\\#2563eb\\]\\/70 {\n border-color: color-mix(in oklab, #2563eb 70%, transparent);\n }\n .msr\\:border-ink-200 {\n border-color: var(--msr-color-ink-200);\n }\n .msr\\:bg-\\[\\#0d99ff\\] {\n background-color: #0d99ff;\n }\n .msr\\:bg-\\[\\#2563eb\\] {\n background-color: #2563eb;\n }\n .msr\\:bg-\\[\\#fff\\] {\n background-color: #fff;\n }\n .msr\\:bg-black {\n background-color: var(--msr-color-black);\n }\n .msr\\:bg-black\\/10 {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n .msr\\:bg-ink-900\\/90 {\n background-color: var(--msr-color-ink-900);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-ink-900) 90%, transparent);\n }\n }\n .msr\\:bg-transparent {\n background-color: transparent;\n }\n .msr\\:bg-white {\n background-color: var(--msr-color-white);\n }\n .msr\\:p-1 {\n padding: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-1 {\n padding-inline: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-2 {\n padding-inline: calc(var(--msr-spacing) * 2);\n }\n .msr\\:py-0\\.5 {\n padding-block: calc(var(--msr-spacing) * 0.5);\n }\n .msr\\:py-1 {\n padding-block: calc(var(--msr-spacing) * 1);\n }\n .msr\\:py-1\\.5 {\n padding-block: calc(var(--msr-spacing) * 1.5);\n }\n .msr\\:text-left {\n text-align: left;\n }\n .msr\\:text-\\[9px\\] {\n font-size: 9px;\n }\n .msr\\:text-\\[10px\\] {\n font-size: 10px;\n }\n .msr\\:text-\\[11px\\] {\n font-size: 11px;\n }\n .msr\\:text-\\[12px\\] {\n font-size: 12px;\n }\n .msr\\:whitespace-nowrap {\n white-space: nowrap;\n }\n .msr\\:text-\\[\\#64748b\\] {\n color: #64748b;\n }\n .msr\\:text-black {\n color: var(--msr-color-black);\n }\n .msr\\:text-ink-50 {\n color: var(--msr-color-ink-50);\n }\n .msr\\:text-ink-700 {\n color: var(--msr-color-ink-700);\n }\n .msr\\:text-white {\n color: var(--msr-color-white);\n }\n .msr\\:text-white\\/60 {\n color: var(--msr-color-white);\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, var(--msr-color-white) 60%, transparent);\n }\n }\n .msr\\:tabular-nums {\n --tw-numeric-spacing: tabular-nums;\n font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);\n }\n .msr\\:opacity-0 {\n opacity: 0%;\n }\n .msr\\:opacity-100 {\n opacity: 100%;\n }\n .msr\\:outline {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n .msr\\:outline-transparent {\n outline-color: transparent;\n }\n .msr\\:transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--msr-default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--msr-default-transition-duration));\n }\n .msr\\:transition-none {\n transition-property: none;\n }\n .msr\\:duration-150 {\n --tw-duration: 150ms;\n transition-duration: 150ms;\n }\n .msr\\:outline-none {\n --tw-outline-style: none;\n outline-style: none;\n }\n .msr\\:select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .msr\\:hover\\:bg-\\[\\#0d99ff\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #0d99ff;\n }\n }\n }\n .msr\\:hover\\:bg-black\\/4 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 4%, transparent);\n }\n }\n }\n }\n .msr\\:hover\\:bg-black\\/10 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n }\n }\n .msr\\:hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--msr-color-white);\n }\n }\n }\n .msr\\:focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n}\n:root, :host {\n --color-ink-50: #f8fafc;\n --color-ink-200: #e2e8f0;\n --color-ink-500: #64748b;\n --color-ink-700: #334155;\n --color-ink-900: #0f172a;\n}\n.mesurer-toolbar-surface {\n box-shadow: 0 0 0.5px rgba(0, 0, 0, 0.18), 0 3px 8px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.mesurer-menu-surface {\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);\n}\n.mesurer-root {\n --msr-spacing: 4px;\n}\n@property --tw-translate-x {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: "*";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-ordinal {\n syntax: "*";\n inherits: false;\n}\n@property --tw-slashed-zero {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-figure {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-spacing {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-fraction {\n syntax: "*";\n inherits: false;\n}\n@property --tw-outline-style {\n syntax: "*";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-duration {\n syntax: "*";\n inherits: false;\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-border-style: solid;\n --tw-ordinal: initial;\n --tw-slashed-zero: initial;\n --tw-numeric-figure: initial;\n --tw-numeric-spacing: initial;\n --tw-numeric-fraction: initial;\n --tw-outline-style: solid;\n --tw-duration: initial;\n }\n }\n}\n';
|
|
53
57
|
|
|
54
58
|
// components/toolbar.tsx
|
|
55
59
|
import {
|
|
56
60
|
forwardRef,
|
|
57
61
|
memo,
|
|
58
62
|
useCallback,
|
|
59
|
-
useEffect,
|
|
60
63
|
useLayoutEffect,
|
|
61
64
|
useRef,
|
|
62
65
|
useState
|
|
63
66
|
} from "react";
|
|
64
67
|
|
|
65
|
-
// utils.ts
|
|
68
|
+
// core/utils.ts
|
|
66
69
|
var formatValue = (value) => Math.round(value);
|
|
67
70
|
var cn = (...inputs) => inputs.filter(Boolean).join(" ");
|
|
68
71
|
var createId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`;
|
|
@@ -82,9 +85,57 @@ var IconBase = ({ size = 24, ...props }) => /* @__PURE__ */ jsx(
|
|
|
82
85
|
);
|
|
83
86
|
var CursorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx("path", { d: "M166.59,134.1a1.91,1.91,0,0,1-.55-1.79,2,2,0,0,1,1.08-1.42l46.25-17.76.24-.1A14,14,0,0,0,212.38,87L52.29,34.7A13.95,13.95,0,0,0,34.7,52.29L87,212.38a13.82,13.82,0,0,0,12.6,9.6c.23,0,.46,0,.69,0A13.84,13.84,0,0,0,113,213.61a2.44,2.44,0,0,0,.1-.24l17.76-46.25a2,2,0,0,1,3.21-.53l51.31,51.31a14,14,0,0,0,19.8,0l12.69-12.69a14,14,0,0,0,0-19.8Zm42.82,62.63-12.68,12.68a2,2,0,0,1-2.83,0L142.59,158.1a14,14,0,0,0-22.74,4.32,2.44,2.44,0,0,0-.1.24L102,208.91a2,2,0,0,1-3.61-.26L46.11,48.57a1.87,1.87,0,0,1,.47-2A1.92,1.92,0,0,1,47.93,46a2.22,2.22,0,0,1,.64.1L208.65,98.38a2,2,0,0,1,.26,3.61l-46.25,17.76-.24.1a14,14,0,0,0-4.32,22.74h0l51.31,51.31A2,2,0,0,1,209.41,196.73Z" }) });
|
|
84
87
|
var RulerIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx("path", { d: "M233.91,74.79,181.22,22.1a14,14,0,0,0-19.8,0L22.09,161.41a14,14,0,0,0,0,19.8L74.78,233.9a14,14,0,0,0,19.8,0L233.91,94.59A14,14,0,0,0,233.91,74.79ZM225.42,86.1,86.1,225.41h0a2,2,0,0,1-2.83,0L30.58,172.73a2,2,0,0,1,0-2.83L64,136.48l27.76,27.76a6,6,0,1,0,8.48-8.48L72.48,128,96,104.48l27.76,27.76a6,6,0,0,0,8.48-8.48L104.48,96,128,72.49l27.76,27.75a6,6,0,0,0,8.48-8.48L136.49,64,169.9,30.59a2,2,0,0,1,2.83,0l52.69,52.68A2,2,0,0,1,225.42,86.1Z" }) });
|
|
88
|
+
var XrayIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx(
|
|
89
|
+
"path",
|
|
90
|
+
{
|
|
91
|
+
fill: "none",
|
|
92
|
+
stroke: "currentColor",
|
|
93
|
+
strokeLinecap: "round",
|
|
94
|
+
strokeLinejoin: "round",
|
|
95
|
+
strokeWidth: "12",
|
|
96
|
+
strokeOpacity: "0.78",
|
|
97
|
+
d: "M76 48h96a16 16 0 0 1 16 16v96a16 16 0 0 1-16 16H76a16 16 0 0 1-16-16V64a16 16 0 0 1 16-16Zm32 32h96a16 16 0 0 1 16 16v96a16 16 0 0 1-16 16h-96a16 16 0 0 1-16-16V96a16 16 0 0 1 16-16Z"
|
|
98
|
+
}
|
|
99
|
+
) });
|
|
100
|
+
var RulersIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx(
|
|
101
|
+
"path",
|
|
102
|
+
{
|
|
103
|
+
fill: "none",
|
|
104
|
+
stroke: "currentColor",
|
|
105
|
+
strokeLinecap: "round",
|
|
106
|
+
strokeLinejoin: "round",
|
|
107
|
+
strokeWidth: "12",
|
|
108
|
+
d: "M48 208V48h160M80 48v24m32-24v24m32-24v24m32-24v24M48 80h24M48 112h24m-24 32h24m-24 32h24"
|
|
109
|
+
}
|
|
110
|
+
) });
|
|
85
111
|
var CaretDownIcon = ({ size = 8, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx("path", { d: "M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z" }) });
|
|
86
112
|
var CheckIcon = ({ size = 12, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx("path", { d: "M232.49,80.49l-128,128a12,12,0,0,1-17,0l-56-56a12,12,0,1,1,17-17L96,183,215.51,63.51a12,12,0,0,1,17,17Z" }) });
|
|
87
113
|
var MinusIcon = ({ size = 12, ...props }) => /* @__PURE__ */ jsx(IconBase, { size, ...props, children: /* @__PURE__ */ jsx("path", { d: "M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z" }) });
|
|
114
|
+
var TextInspectorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(
|
|
115
|
+
"svg",
|
|
116
|
+
{
|
|
117
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
118
|
+
width: size,
|
|
119
|
+
height: size,
|
|
120
|
+
viewBox: "0 0 256 256",
|
|
121
|
+
fill: "currentColor",
|
|
122
|
+
...props,
|
|
123
|
+
children: /* @__PURE__ */ jsx(
|
|
124
|
+
"text",
|
|
125
|
+
{
|
|
126
|
+
x: "50%",
|
|
127
|
+
y: "60%",
|
|
128
|
+
textAnchor: "middle",
|
|
129
|
+
dominantBaseline: "middle",
|
|
130
|
+
fill: "currentColor",
|
|
131
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif",
|
|
132
|
+
fontWeight: 300,
|
|
133
|
+
fontSize: 220,
|
|
134
|
+
children: "Aa"
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
);
|
|
88
139
|
|
|
89
140
|
// components/toolbar.tsx
|
|
90
141
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
@@ -99,6 +150,7 @@ function ToolbarButton({
|
|
|
99
150
|
shortcut,
|
|
100
151
|
onClick,
|
|
101
152
|
tooltipVisible,
|
|
153
|
+
tooltipInstant,
|
|
102
154
|
tooltipSide,
|
|
103
155
|
onTooltipEnter,
|
|
104
156
|
onTooltipLeave,
|
|
@@ -116,6 +168,7 @@ function ToolbarButton({
|
|
|
116
168
|
{
|
|
117
169
|
type: "button",
|
|
118
170
|
"aria-label": `${label} (${shortcut})`,
|
|
171
|
+
"aria-pressed": active,
|
|
119
172
|
title: `${label} (${shortcut})`,
|
|
120
173
|
className: cn(
|
|
121
174
|
"msr:flex msr:size-8 msr:items-center msr:justify-center msr:rounded-[8px] msr:outline-none",
|
|
@@ -129,7 +182,10 @@ function ToolbarButton({
|
|
|
129
182
|
"span",
|
|
130
183
|
{
|
|
131
184
|
className: cn(
|
|
132
|
-
|
|
185
|
+
cn(
|
|
186
|
+
"msr:pointer-events-none msr:absolute msr:left-1/2 msr:-translate-x-1/2 msr:whitespace-nowrap msr:rounded msr:bg-black msr:px-2 msr:py-1 msr:text-[11px] msr:text-white msr:transition-opacity msr:duration-150 msr:select-none",
|
|
187
|
+
tooltipInstant && "msr:transition-none"
|
|
188
|
+
),
|
|
133
189
|
tooltipSide === "top" ? "msr:bottom-full msr:mb-2" : "msr:top-full msr:mt-2",
|
|
134
190
|
tooltipVisible ? "msr:opacity-100" : "msr:opacity-0"
|
|
135
191
|
),
|
|
@@ -148,6 +204,7 @@ function useToolbarTooltip() {
|
|
|
148
204
|
const [visibleTooltipId, setVisibleTooltipId] = useState(null);
|
|
149
205
|
const timerRef = useRef(null);
|
|
150
206
|
const instantRef = useRef(false);
|
|
207
|
+
const [tooltipInstant, setTooltipInstant] = useState(false);
|
|
151
208
|
const clearTimer = useCallback(() => {
|
|
152
209
|
if (timerRef.current === null) return;
|
|
153
210
|
window.clearTimeout(timerRef.current);
|
|
@@ -157,9 +214,11 @@ function useToolbarTooltip() {
|
|
|
157
214
|
(id) => {
|
|
158
215
|
clearTimer();
|
|
159
216
|
if (instantRef.current) {
|
|
217
|
+
setTooltipInstant(true);
|
|
160
218
|
setVisibleTooltipId(id);
|
|
161
219
|
return;
|
|
162
220
|
}
|
|
221
|
+
setTooltipInstant(false);
|
|
163
222
|
timerRef.current = window.setTimeout(() => {
|
|
164
223
|
setVisibleTooltipId(id);
|
|
165
224
|
instantRef.current = true;
|
|
@@ -179,15 +238,17 @@ function useToolbarTooltip() {
|
|
|
179
238
|
clearTimer();
|
|
180
239
|
setVisibleTooltipId(null);
|
|
181
240
|
instantRef.current = false;
|
|
241
|
+
setTooltipInstant(false);
|
|
182
242
|
}, [clearTimer]);
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
243
|
+
return {
|
|
244
|
+
visibleTooltipId,
|
|
245
|
+
tooltipInstant,
|
|
246
|
+
onTooltipEnter,
|
|
247
|
+
onTooltipLeave,
|
|
248
|
+
onToolbarLeave
|
|
249
|
+
};
|
|
189
250
|
}
|
|
190
|
-
function useToolbarDrag(initialPosition) {
|
|
251
|
+
function useToolbarDrag(initialPosition, eventTarget) {
|
|
191
252
|
const [position, setPosition] = useState(initialPosition);
|
|
192
253
|
const suppressClickRef = useRef(false);
|
|
193
254
|
const detachListenersRef = useRef(null);
|
|
@@ -230,8 +291,8 @@ function useToolbarDrag(initialPosition) {
|
|
|
230
291
|
}
|
|
231
292
|
if (!current.active) return;
|
|
232
293
|
current.didDrag = true;
|
|
233
|
-
const maxX = Math.max(8,
|
|
234
|
-
const maxY = Math.max(8,
|
|
294
|
+
const maxX = Math.max(8, eventTarget.innerWidth - current.width - 8);
|
|
295
|
+
const maxY = Math.max(8, eventTarget.innerHeight - current.height - 8);
|
|
235
296
|
setPosition({
|
|
236
297
|
x: Math.min(maxX, Math.max(8, current.originX + dx)),
|
|
237
298
|
y: Math.min(maxY, Math.max(8, current.originY + dy))
|
|
@@ -245,21 +306,21 @@ function useToolbarDrag(initialPosition) {
|
|
|
245
306
|
current.active = false;
|
|
246
307
|
current.didDrag = false;
|
|
247
308
|
current.pointerId = -1;
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
309
|
+
eventTarget.removeEventListener("pointermove", handlePointerMove);
|
|
310
|
+
eventTarget.removeEventListener("pointerup", handlePointerEnd);
|
|
311
|
+
eventTarget.removeEventListener("pointercancel", handlePointerEnd);
|
|
251
312
|
detachListenersRef.current = null;
|
|
252
313
|
};
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
314
|
+
eventTarget.addEventListener("pointermove", handlePointerMove);
|
|
315
|
+
eventTarget.addEventListener("pointerup", handlePointerEnd);
|
|
316
|
+
eventTarget.addEventListener("pointercancel", handlePointerEnd);
|
|
256
317
|
detachListenersRef.current = () => {
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
318
|
+
eventTarget.removeEventListener("pointermove", handlePointerMove);
|
|
319
|
+
eventTarget.removeEventListener("pointerup", handlePointerEnd);
|
|
320
|
+
eventTarget.removeEventListener("pointercancel", handlePointerEnd);
|
|
260
321
|
};
|
|
261
322
|
},
|
|
262
|
-
[position.x, position.y]
|
|
323
|
+
[eventTarget, position.x, position.y]
|
|
263
324
|
);
|
|
264
325
|
const onClickCapture = useCallback(
|
|
265
326
|
(event) => {
|
|
@@ -276,15 +337,24 @@ function ToolbarComponent({
|
|
|
276
337
|
toolMode,
|
|
277
338
|
setEnabled,
|
|
278
339
|
setToolMode,
|
|
340
|
+
rulersVisible,
|
|
341
|
+
setRulersVisible,
|
|
279
342
|
guideOrientation,
|
|
280
343
|
setGuideOrientation,
|
|
281
|
-
onInteract
|
|
344
|
+
onInteract,
|
|
345
|
+
eventTarget
|
|
282
346
|
}, ref) {
|
|
283
347
|
const { position, onPointerDown, onClickCapture } = useToolbarDrag({
|
|
284
348
|
x: 16,
|
|
285
349
|
y: 16
|
|
286
|
-
});
|
|
287
|
-
const {
|
|
350
|
+
}, eventTarget);
|
|
351
|
+
const {
|
|
352
|
+
visibleTooltipId,
|
|
353
|
+
tooltipInstant,
|
|
354
|
+
onTooltipEnter,
|
|
355
|
+
onTooltipLeave,
|
|
356
|
+
onToolbarLeave
|
|
357
|
+
} = useToolbarTooltip();
|
|
288
358
|
const [guideMenuOpen, setGuideMenuOpen] = useState(false);
|
|
289
359
|
const guideMenuRef = useRef(null);
|
|
290
360
|
const [activeMenuIndex, setActiveMenuIndex] = useState(0);
|
|
@@ -298,13 +368,13 @@ function ToolbarComponent({
|
|
|
298
368
|
setMenuAlign("left");
|
|
299
369
|
return;
|
|
300
370
|
}
|
|
301
|
-
if (leftAlignedRight >
|
|
371
|
+
if (leftAlignedRight > eventTarget.innerWidth - VIEWPORT_PADDING) {
|
|
302
372
|
setMenuAlign("right");
|
|
303
373
|
return;
|
|
304
374
|
}
|
|
305
375
|
setMenuAlign("right");
|
|
306
|
-
}, []);
|
|
307
|
-
const viewportHeight =
|
|
376
|
+
}, [eventTarget]);
|
|
377
|
+
const viewportHeight = eventTarget.innerHeight || 0;
|
|
308
378
|
const nearTop = position.y < 56;
|
|
309
379
|
const nearBottom = viewportHeight > 0 && position.y > viewportHeight - 56;
|
|
310
380
|
const tooltipSide = nearTop && !nearBottom ? "bottom" : "top";
|
|
@@ -319,6 +389,23 @@ function ToolbarComponent({
|
|
|
319
389
|
setToolMode((prev) => prev === "guides" ? "none" : "guides");
|
|
320
390
|
onInteract();
|
|
321
391
|
}, [onInteract, setEnabled, setToolMode]);
|
|
392
|
+
const textInspectorMode = useCallback(() => {
|
|
393
|
+
setEnabled(true);
|
|
394
|
+
setToolMode(
|
|
395
|
+
(prev) => prev === "text-inspector" ? "none" : "text-inspector"
|
|
396
|
+
);
|
|
397
|
+
onInteract();
|
|
398
|
+
}, [onInteract, setEnabled, setToolMode]);
|
|
399
|
+
const xrayMode = useCallback(() => {
|
|
400
|
+
setEnabled(true);
|
|
401
|
+
setToolMode((prev) => prev === "xray" ? "none" : "xray");
|
|
402
|
+
onInteract();
|
|
403
|
+
}, [onInteract, setEnabled, setToolMode]);
|
|
404
|
+
const rulersMode = useCallback(() => {
|
|
405
|
+
setEnabled(true);
|
|
406
|
+
setRulersVisible((prev) => !prev);
|
|
407
|
+
onInteract();
|
|
408
|
+
}, [onInteract, setEnabled, setRulersVisible]);
|
|
322
409
|
const selectGuideOrientation = useCallback(
|
|
323
410
|
(orientation) => {
|
|
324
411
|
setEnabled(true);
|
|
@@ -331,7 +418,7 @@ function ToolbarComponent({
|
|
|
331
418
|
);
|
|
332
419
|
useLayoutEffect(() => {
|
|
333
420
|
if (!guideMenuOpen) return;
|
|
334
|
-
const frame = requestAnimationFrame(() => {
|
|
421
|
+
const frame = eventTarget.requestAnimationFrame(() => {
|
|
335
422
|
guideMenuRef.current?.querySelector("[role='menu']")?.focus();
|
|
336
423
|
});
|
|
337
424
|
const handlePointerDown = (event) => {
|
|
@@ -344,14 +431,14 @@ function ToolbarComponent({
|
|
|
344
431
|
const handleResize = () => {
|
|
345
432
|
updateMenuAlign();
|
|
346
433
|
};
|
|
347
|
-
|
|
348
|
-
|
|
434
|
+
eventTarget.addEventListener("pointerdown", handlePointerDown);
|
|
435
|
+
eventTarget.addEventListener("resize", handleResize);
|
|
349
436
|
return () => {
|
|
350
|
-
cancelAnimationFrame(frame);
|
|
351
|
-
|
|
352
|
-
|
|
437
|
+
eventTarget.cancelAnimationFrame(frame);
|
|
438
|
+
eventTarget.removeEventListener("pointerdown", handlePointerDown);
|
|
439
|
+
eventTarget.removeEventListener("resize", handleResize);
|
|
353
440
|
};
|
|
354
|
-
}, [guideMenuOpen, guideOrientation, updateMenuAlign]);
|
|
441
|
+
}, [eventTarget, guideMenuOpen, guideOrientation, updateMenuAlign]);
|
|
355
442
|
return /* @__PURE__ */ jsxs(
|
|
356
443
|
"div",
|
|
357
444
|
{
|
|
@@ -374,12 +461,61 @@ function ToolbarComponent({
|
|
|
374
461
|
shortcut: "S",
|
|
375
462
|
onClick: selectMode,
|
|
376
463
|
tooltipVisible: visibleTooltipId === "select",
|
|
464
|
+
tooltipInstant,
|
|
377
465
|
tooltipSide,
|
|
378
466
|
onTooltipEnter,
|
|
379
467
|
onTooltipLeave,
|
|
380
468
|
children: /* @__PURE__ */ jsx2(CursorIcon, { size: 20 })
|
|
381
469
|
}
|
|
382
470
|
),
|
|
471
|
+
/* @__PURE__ */ jsx2(
|
|
472
|
+
ToolbarButton,
|
|
473
|
+
{
|
|
474
|
+
id: "xray",
|
|
475
|
+
active: toolMode === "xray",
|
|
476
|
+
label: "X-ray",
|
|
477
|
+
shortcut: "X",
|
|
478
|
+
onClick: xrayMode,
|
|
479
|
+
tooltipVisible: visibleTooltipId === "xray",
|
|
480
|
+
tooltipInstant,
|
|
481
|
+
tooltipSide,
|
|
482
|
+
onTooltipEnter,
|
|
483
|
+
onTooltipLeave,
|
|
484
|
+
children: /* @__PURE__ */ jsx2(XrayIcon, { size: 20 })
|
|
485
|
+
}
|
|
486
|
+
),
|
|
487
|
+
/* @__PURE__ */ jsx2(
|
|
488
|
+
ToolbarButton,
|
|
489
|
+
{
|
|
490
|
+
id: "rulers",
|
|
491
|
+
active: rulersVisible,
|
|
492
|
+
label: "Rulers",
|
|
493
|
+
shortcut: "R",
|
|
494
|
+
onClick: rulersMode,
|
|
495
|
+
tooltipVisible: visibleTooltipId === "rulers",
|
|
496
|
+
tooltipInstant,
|
|
497
|
+
tooltipSide,
|
|
498
|
+
onTooltipEnter,
|
|
499
|
+
onTooltipLeave,
|
|
500
|
+
children: /* @__PURE__ */ jsx2(RulersIcon, { size: 20 })
|
|
501
|
+
}
|
|
502
|
+
),
|
|
503
|
+
/* @__PURE__ */ jsx2(
|
|
504
|
+
ToolbarButton,
|
|
505
|
+
{
|
|
506
|
+
id: "text-inspector",
|
|
507
|
+
active: toolMode === "text-inspector",
|
|
508
|
+
label: "Text inspector",
|
|
509
|
+
shortcut: "A",
|
|
510
|
+
onClick: textInspectorMode,
|
|
511
|
+
tooltipVisible: visibleTooltipId === "text-inspector",
|
|
512
|
+
tooltipInstant,
|
|
513
|
+
tooltipSide,
|
|
514
|
+
onTooltipEnter,
|
|
515
|
+
onTooltipLeave,
|
|
516
|
+
children: /* @__PURE__ */ jsx2(TextInspectorIcon, { size: 20, "aria-hidden": "true" })
|
|
517
|
+
}
|
|
518
|
+
),
|
|
383
519
|
/* @__PURE__ */ jsx2(
|
|
384
520
|
ToolbarButton,
|
|
385
521
|
{
|
|
@@ -389,6 +525,7 @@ function ToolbarComponent({
|
|
|
389
525
|
shortcut: "G",
|
|
390
526
|
onClick: guidesMode,
|
|
391
527
|
tooltipVisible: visibleTooltipId === "guides",
|
|
528
|
+
tooltipInstant,
|
|
392
529
|
tooltipSide,
|
|
393
530
|
onTooltipEnter,
|
|
394
531
|
onTooltipLeave,
|
|
@@ -548,23 +685,328 @@ function ToolbarComponent({
|
|
|
548
685
|
}
|
|
549
686
|
var Toolbar = memo(forwardRef(ToolbarComponent));
|
|
550
687
|
|
|
688
|
+
// components/rulers-overlay.tsx
|
|
689
|
+
import { memo as memo2, useRef as useRef2, useState as useState2 } from "react";
|
|
690
|
+
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
691
|
+
var RULER_SIZE = 18;
|
|
692
|
+
var RULER_LENGTH = 4e3;
|
|
693
|
+
var TICK_STEP = 5;
|
|
694
|
+
var ticks = Array.from(
|
|
695
|
+
{ length: RULER_LENGTH / TICK_STEP + 1 },
|
|
696
|
+
(_, index) => index * TICK_STEP
|
|
697
|
+
);
|
|
698
|
+
var RulersOverlay = memo2(function RulersOverlay2({
|
|
699
|
+
onStartGuide,
|
|
700
|
+
onMoveGuide,
|
|
701
|
+
onFinishGuide,
|
|
702
|
+
onCancelGuide,
|
|
703
|
+
guides,
|
|
704
|
+
selectedGuideIds
|
|
705
|
+
}) {
|
|
706
|
+
const [dragPosition, setDragPosition] = useState2(null);
|
|
707
|
+
const [dragOrientation, setDragOrientation] = useState2(null);
|
|
708
|
+
const dragRef = useRef2(null);
|
|
709
|
+
const beginGuideDrag = (orientation, event) => {
|
|
710
|
+
if (event.button !== 0) return;
|
|
711
|
+
event.stopPropagation();
|
|
712
|
+
const position = orientation === "horizontal" ? event.clientY : event.clientX;
|
|
713
|
+
setDragPosition(position);
|
|
714
|
+
setDragOrientation(orientation);
|
|
715
|
+
dragRef.current = {
|
|
716
|
+
orientation,
|
|
717
|
+
pointerId: event.pointerId,
|
|
718
|
+
id: onStartGuide(orientation, position)
|
|
719
|
+
};
|
|
720
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
721
|
+
};
|
|
722
|
+
const moveGuide = (event) => {
|
|
723
|
+
const drag = dragRef.current;
|
|
724
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
725
|
+
event.stopPropagation();
|
|
726
|
+
const position = drag.orientation === "horizontal" ? event.clientY : event.clientX;
|
|
727
|
+
setDragPosition(position);
|
|
728
|
+
onMoveGuide(drag.id, position);
|
|
729
|
+
};
|
|
730
|
+
const finishGuideDrag = (event) => {
|
|
731
|
+
const drag = dragRef.current;
|
|
732
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
733
|
+
event.stopPropagation();
|
|
734
|
+
const position = drag.orientation === "horizontal" ? event.clientY : event.clientX;
|
|
735
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
736
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
737
|
+
}
|
|
738
|
+
dragRef.current = null;
|
|
739
|
+
setDragPosition(null);
|
|
740
|
+
setDragOrientation(null);
|
|
741
|
+
onMoveGuide(drag.id, position);
|
|
742
|
+
onFinishGuide(drag.id);
|
|
743
|
+
};
|
|
744
|
+
const cancelGuideDrag = (event) => {
|
|
745
|
+
const drag = dragRef.current;
|
|
746
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
747
|
+
dragRef.current = null;
|
|
748
|
+
setDragPosition(null);
|
|
749
|
+
setDragOrientation(null);
|
|
750
|
+
onCancelGuide(drag.id);
|
|
751
|
+
};
|
|
752
|
+
const selectedVerticalGuides = guides.filter(
|
|
753
|
+
(guide) => guide.orientation === "vertical" && selectedGuideIds.includes(guide.id)
|
|
754
|
+
);
|
|
755
|
+
const selectedHorizontalGuides = guides.filter(
|
|
756
|
+
(guide) => guide.orientation === "horizontal" && selectedGuideIds.includes(guide.id)
|
|
757
|
+
);
|
|
758
|
+
return /* @__PURE__ */ jsxs2(
|
|
759
|
+
"div",
|
|
760
|
+
{
|
|
761
|
+
"aria-hidden": "true",
|
|
762
|
+
className: "msr:pointer-events-none msr:absolute msr:inset-0 msr:select-none msr:text-[9px] msr:text-[#64748b]",
|
|
763
|
+
children: [
|
|
764
|
+
/* @__PURE__ */ jsx3(
|
|
765
|
+
"div",
|
|
766
|
+
{
|
|
767
|
+
className: "msr:absolute msr:left-[18px] msr:right-0 msr:top-0 msr:overflow-hidden msr:bg-white",
|
|
768
|
+
style: {
|
|
769
|
+
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.12)",
|
|
770
|
+
height: RULER_SIZE,
|
|
771
|
+
cursor: "ns-resize",
|
|
772
|
+
pointerEvents: "auto"
|
|
773
|
+
},
|
|
774
|
+
onPointerDown: (event) => beginGuideDrag("horizontal", event),
|
|
775
|
+
onPointerMove: moveGuide,
|
|
776
|
+
onPointerUp: finishGuideDrag,
|
|
777
|
+
onPointerCancel: cancelGuideDrag,
|
|
778
|
+
children: /* @__PURE__ */ jsxs2(
|
|
779
|
+
"svg",
|
|
780
|
+
{
|
|
781
|
+
className: "msr:block msr:h-6",
|
|
782
|
+
width: RULER_LENGTH,
|
|
783
|
+
height: RULER_SIZE,
|
|
784
|
+
viewBox: `0 0 ${RULER_LENGTH} ${RULER_SIZE}`,
|
|
785
|
+
children: [
|
|
786
|
+
/* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsxs2(
|
|
787
|
+
"linearGradient",
|
|
788
|
+
{
|
|
789
|
+
id: "ruler-label-fade-x",
|
|
790
|
+
x1: "0%",
|
|
791
|
+
x2: "100%",
|
|
792
|
+
gradientUnits: "objectBoundingBox",
|
|
793
|
+
children: [
|
|
794
|
+
/* @__PURE__ */ jsx3("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
795
|
+
/* @__PURE__ */ jsx3("stop", { offset: "0.2", stopColor: "white" }),
|
|
796
|
+
/* @__PURE__ */ jsx3("stop", { offset: "0.8", stopColor: "white" }),
|
|
797
|
+
/* @__PURE__ */ jsx3("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
|
|
798
|
+
]
|
|
799
|
+
}
|
|
800
|
+
) }),
|
|
801
|
+
ticks.map((x) => {
|
|
802
|
+
const major = x % 100 === 0;
|
|
803
|
+
const medium = x % 50 === 0;
|
|
804
|
+
return /* @__PURE__ */ jsxs2("g", { children: [
|
|
805
|
+
/* @__PURE__ */ jsx3(
|
|
806
|
+
"line",
|
|
807
|
+
{
|
|
808
|
+
x1: x,
|
|
809
|
+
y1: RULER_SIZE,
|
|
810
|
+
x2: x,
|
|
811
|
+
y2: major ? 8 : medium ? 13 : 17,
|
|
812
|
+
stroke: "currentColor",
|
|
813
|
+
strokeWidth: "1"
|
|
814
|
+
}
|
|
815
|
+
),
|
|
816
|
+
major ? /* @__PURE__ */ jsx3("text", { x, y: "8", textAnchor: "middle", fill: "currentColor", children: x }) : null
|
|
817
|
+
] }, x);
|
|
818
|
+
}),
|
|
819
|
+
selectedVerticalGuides.map((guide) => /* @__PURE__ */ jsxs2("g", { children: [
|
|
820
|
+
/* @__PURE__ */ jsx3(
|
|
821
|
+
"rect",
|
|
822
|
+
{
|
|
823
|
+
x: guide.position - RULER_SIZE - 8,
|
|
824
|
+
y: "-1",
|
|
825
|
+
width: "48",
|
|
826
|
+
height: "12",
|
|
827
|
+
fill: "url(#ruler-label-fade-x)"
|
|
828
|
+
}
|
|
829
|
+
),
|
|
830
|
+
/* @__PURE__ */ jsx3(
|
|
831
|
+
"text",
|
|
832
|
+
{
|
|
833
|
+
x: guide.position - RULER_SIZE + 16,
|
|
834
|
+
y: "8",
|
|
835
|
+
textAnchor: "middle",
|
|
836
|
+
fill: "#ef4444",
|
|
837
|
+
fontWeight: "600",
|
|
838
|
+
children: Math.round(guide.position - RULER_SIZE)
|
|
839
|
+
}
|
|
840
|
+
)
|
|
841
|
+
] }, guide.id)),
|
|
842
|
+
dragOrientation === "vertical" && dragPosition !== null ? /* @__PURE__ */ jsxs2("g", { children: [
|
|
843
|
+
/* @__PURE__ */ jsx3(
|
|
844
|
+
"rect",
|
|
845
|
+
{
|
|
846
|
+
x: dragPosition - RULER_SIZE - 8,
|
|
847
|
+
y: "-1",
|
|
848
|
+
width: "48",
|
|
849
|
+
height: "12",
|
|
850
|
+
fill: "url(#ruler-label-fade-x)"
|
|
851
|
+
}
|
|
852
|
+
),
|
|
853
|
+
/* @__PURE__ */ jsx3(
|
|
854
|
+
"text",
|
|
855
|
+
{
|
|
856
|
+
x: dragPosition - RULER_SIZE + 16,
|
|
857
|
+
y: "8",
|
|
858
|
+
textAnchor: "middle",
|
|
859
|
+
fill: "#ef4444",
|
|
860
|
+
fontWeight: "600",
|
|
861
|
+
children: Math.round(dragPosition - RULER_SIZE)
|
|
862
|
+
}
|
|
863
|
+
)
|
|
864
|
+
] }) : null
|
|
865
|
+
]
|
|
866
|
+
}
|
|
867
|
+
)
|
|
868
|
+
}
|
|
869
|
+
),
|
|
870
|
+
/* @__PURE__ */ jsx3(
|
|
871
|
+
"div",
|
|
872
|
+
{
|
|
873
|
+
className: "msr:absolute msr:bottom-0 msr:left-0 msr:top-[18px] msr:w-[18px] msr:overflow-hidden msr:bg-white",
|
|
874
|
+
style: {
|
|
875
|
+
boxShadow: "1px 0 3px rgba(0, 0, 0, 0.12)",
|
|
876
|
+
width: RULER_SIZE,
|
|
877
|
+
cursor: "ew-resize",
|
|
878
|
+
pointerEvents: "auto"
|
|
879
|
+
},
|
|
880
|
+
onPointerDown: (event) => beginGuideDrag("vertical", event),
|
|
881
|
+
onPointerMove: moveGuide,
|
|
882
|
+
onPointerUp: finishGuideDrag,
|
|
883
|
+
onPointerCancel: cancelGuideDrag,
|
|
884
|
+
children: /* @__PURE__ */ jsxs2(
|
|
885
|
+
"svg",
|
|
886
|
+
{
|
|
887
|
+
className: "msr:block msr:w-6",
|
|
888
|
+
width: RULER_SIZE,
|
|
889
|
+
height: RULER_LENGTH,
|
|
890
|
+
viewBox: `0 0 ${RULER_SIZE} ${RULER_LENGTH}`,
|
|
891
|
+
children: [
|
|
892
|
+
/* @__PURE__ */ jsx3("defs", { children: /* @__PURE__ */ jsxs2(
|
|
893
|
+
"linearGradient",
|
|
894
|
+
{
|
|
895
|
+
id: "ruler-label-fade-y",
|
|
896
|
+
y1: "0%",
|
|
897
|
+
y2: "100%",
|
|
898
|
+
gradientUnits: "objectBoundingBox",
|
|
899
|
+
children: [
|
|
900
|
+
/* @__PURE__ */ jsx3("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
901
|
+
/* @__PURE__ */ jsx3("stop", { offset: "0.2", stopColor: "white" }),
|
|
902
|
+
/* @__PURE__ */ jsx3("stop", { offset: "0.8", stopColor: "white" }),
|
|
903
|
+
/* @__PURE__ */ jsx3("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
|
|
904
|
+
]
|
|
905
|
+
}
|
|
906
|
+
) }),
|
|
907
|
+
ticks.map((y) => {
|
|
908
|
+
const major = y % 100 === 0;
|
|
909
|
+
const medium = y % 50 === 0;
|
|
910
|
+
return /* @__PURE__ */ jsxs2("g", { children: [
|
|
911
|
+
/* @__PURE__ */ jsx3(
|
|
912
|
+
"line",
|
|
913
|
+
{
|
|
914
|
+
x1: RULER_SIZE,
|
|
915
|
+
y1: y,
|
|
916
|
+
x2: major ? 8 : medium ? 13 : 17,
|
|
917
|
+
y2: y,
|
|
918
|
+
stroke: "currentColor",
|
|
919
|
+
strokeWidth: "1"
|
|
920
|
+
}
|
|
921
|
+
),
|
|
922
|
+
major ? /* @__PURE__ */ jsx3(
|
|
923
|
+
"text",
|
|
924
|
+
{
|
|
925
|
+
x: "8",
|
|
926
|
+
y: y + 10,
|
|
927
|
+
fill: "currentColor",
|
|
928
|
+
transform: `rotate(-90 8 ${y + 10})`,
|
|
929
|
+
children: y
|
|
930
|
+
}
|
|
931
|
+
) : null
|
|
932
|
+
] }, y);
|
|
933
|
+
}),
|
|
934
|
+
selectedHorizontalGuides.map((guide) => /* @__PURE__ */ jsxs2("g", { children: [
|
|
935
|
+
/* @__PURE__ */ jsx3(
|
|
936
|
+
"rect",
|
|
937
|
+
{
|
|
938
|
+
x: "-3",
|
|
939
|
+
y: guide.position - RULER_SIZE - 38,
|
|
940
|
+
width: "24",
|
|
941
|
+
height: "48",
|
|
942
|
+
fill: "url(#ruler-label-fade-y)"
|
|
943
|
+
}
|
|
944
|
+
),
|
|
945
|
+
/* @__PURE__ */ jsx3(
|
|
946
|
+
"text",
|
|
947
|
+
{
|
|
948
|
+
x: "9",
|
|
949
|
+
y: guide.position - RULER_SIZE - 16,
|
|
950
|
+
textAnchor: "middle",
|
|
951
|
+
fill: "#ef4444",
|
|
952
|
+
fontWeight: "600",
|
|
953
|
+
transform: `rotate(-90 9 ${guide.position - RULER_SIZE - 16})`,
|
|
954
|
+
children: Math.round(guide.position - RULER_SIZE)
|
|
955
|
+
}
|
|
956
|
+
)
|
|
957
|
+
] }, guide.id)),
|
|
958
|
+
dragOrientation === "horizontal" && dragPosition !== null ? /* @__PURE__ */ jsxs2("g", { children: [
|
|
959
|
+
/* @__PURE__ */ jsx3(
|
|
960
|
+
"rect",
|
|
961
|
+
{
|
|
962
|
+
x: "-3",
|
|
963
|
+
y: dragPosition - RULER_SIZE - 38,
|
|
964
|
+
width: "24",
|
|
965
|
+
height: "48",
|
|
966
|
+
fill: "url(#ruler-label-fade-y)"
|
|
967
|
+
}
|
|
968
|
+
),
|
|
969
|
+
/* @__PURE__ */ jsx3(
|
|
970
|
+
"text",
|
|
971
|
+
{
|
|
972
|
+
x: "9",
|
|
973
|
+
y: dragPosition - RULER_SIZE - 16,
|
|
974
|
+
textAnchor: "middle",
|
|
975
|
+
fill: "#ef4444",
|
|
976
|
+
fontWeight: "600",
|
|
977
|
+
transform: `rotate(-90 9 ${dragPosition - RULER_SIZE - 16})`,
|
|
978
|
+
children: Math.round(dragPosition - RULER_SIZE)
|
|
979
|
+
}
|
|
980
|
+
)
|
|
981
|
+
] }) : null
|
|
982
|
+
]
|
|
983
|
+
}
|
|
984
|
+
)
|
|
985
|
+
}
|
|
986
|
+
),
|
|
987
|
+
/* @__PURE__ */ jsx3("div", { className: "msr:absolute msr:left-0 msr:top-0 msr:size-[18px] msr:bg-white" })
|
|
988
|
+
]
|
|
989
|
+
}
|
|
990
|
+
);
|
|
991
|
+
});
|
|
992
|
+
|
|
551
993
|
// hooks/use-drag-state.ts
|
|
552
|
-
import { useState as
|
|
994
|
+
import { useState as useState3 } from "react";
|
|
553
995
|
var useDragState = () => {
|
|
554
|
-
const [start, setStart] =
|
|
555
|
-
const [end, setEnd] =
|
|
556
|
-
const [isDragging, setIsDragging] =
|
|
996
|
+
const [start, setStart] = useState3(null);
|
|
997
|
+
const [end, setEnd] = useState3(null);
|
|
998
|
+
const [isDragging, setIsDragging] = useState3(false);
|
|
557
999
|
return { start, setStart, end, setEnd, isDragging, setIsDragging };
|
|
558
1000
|
};
|
|
559
1001
|
|
|
560
1002
|
// hooks/use-guide-drag-hold.ts
|
|
561
|
-
import { useCallback as useCallback2, useRef as
|
|
562
|
-
var useGuideDragHold = () => {
|
|
563
|
-
const guideDragHoldTimerRef =
|
|
564
|
-
const guideDragHoldGuideIdRef =
|
|
1003
|
+
import { useCallback as useCallback2, useRef as useRef3 } from "react";
|
|
1004
|
+
var useGuideDragHold = (eventTarget) => {
|
|
1005
|
+
const guideDragHoldTimerRef = useRef3(null);
|
|
1006
|
+
const guideDragHoldGuideIdRef = useRef3(null);
|
|
565
1007
|
const clearGuideDragHold = useCallback2(() => {
|
|
566
1008
|
if (guideDragHoldTimerRef.current !== null) {
|
|
567
|
-
|
|
1009
|
+
eventTarget.clearTimeout(guideDragHoldTimerRef.current);
|
|
568
1010
|
guideDragHoldTimerRef.current = null;
|
|
569
1011
|
}
|
|
570
1012
|
guideDragHoldGuideIdRef.current = null;
|
|
@@ -573,7 +1015,7 @@ var useGuideDragHold = () => {
|
|
|
573
1015
|
(id, onHold) => {
|
|
574
1016
|
clearGuideDragHold();
|
|
575
1017
|
guideDragHoldGuideIdRef.current = id;
|
|
576
|
-
guideDragHoldTimerRef.current =
|
|
1018
|
+
guideDragHoldTimerRef.current = eventTarget.setTimeout(() => {
|
|
577
1019
|
if (guideDragHoldGuideIdRef.current === id) {
|
|
578
1020
|
onHold(id);
|
|
579
1021
|
}
|
|
@@ -588,11 +1030,11 @@ var useGuideDragHold = () => {
|
|
|
588
1030
|
};
|
|
589
1031
|
|
|
590
1032
|
// hooks/use-guide-state.ts
|
|
591
|
-
import { useState as
|
|
1033
|
+
import { useState as useState4 } from "react";
|
|
592
1034
|
var useGuideState = (options = {}) => {
|
|
593
|
-
const [guides, setGuides] =
|
|
594
|
-
const [draggingGuideId, setDraggingGuideId] =
|
|
595
|
-
const [selectedGuideIds, setSelectedGuideIds] =
|
|
1035
|
+
const [guides, setGuides] = useState4(options.initialGuides ?? []);
|
|
1036
|
+
const [draggingGuideId, setDraggingGuideId] = useState4(null);
|
|
1037
|
+
const [selectedGuideIds, setSelectedGuideIds] = useState4(
|
|
596
1038
|
options.initialSelectedGuideIds ?? []
|
|
597
1039
|
);
|
|
598
1040
|
return {
|
|
@@ -606,19 +1048,37 @@ var useGuideState = (options = {}) => {
|
|
|
606
1048
|
};
|
|
607
1049
|
|
|
608
1050
|
// hooks/use-hotkeys.ts
|
|
609
|
-
import { useEffect
|
|
1051
|
+
import { useEffect } from "react";
|
|
610
1052
|
var useHotkeys = (options) => {
|
|
611
|
-
|
|
1053
|
+
useEffect(() => {
|
|
1054
|
+
const target = options.eventTarget;
|
|
612
1055
|
const handleKeyDown = (event) => {
|
|
613
1056
|
if (event.key === "Escape") {
|
|
614
1057
|
options.clearAll();
|
|
615
1058
|
return;
|
|
616
1059
|
}
|
|
1060
|
+
if (event.metaKey || event.ctrlKey) {
|
|
1061
|
+
if (event.key.toLowerCase() !== "z") return;
|
|
1062
|
+
if (event.shiftKey) {
|
|
1063
|
+
event.preventDefault();
|
|
1064
|
+
options.redo();
|
|
1065
|
+
return;
|
|
1066
|
+
}
|
|
1067
|
+
event.preventDefault();
|
|
1068
|
+
options.undo();
|
|
1069
|
+
return;
|
|
1070
|
+
}
|
|
617
1071
|
if (event.key.toLowerCase() === "m") {
|
|
618
1072
|
options.setEnabled((prev) => !prev);
|
|
619
1073
|
}
|
|
620
1074
|
const key = event.key.toLowerCase();
|
|
621
1075
|
if (options.isOverlayActive()) {
|
|
1076
|
+
if (key === "a") {
|
|
1077
|
+
options.setToolMode(
|
|
1078
|
+
(prev) => prev === "text-inspector" ? "none" : "text-inspector"
|
|
1079
|
+
);
|
|
1080
|
+
options.onInteract();
|
|
1081
|
+
}
|
|
622
1082
|
if (key === "s") {
|
|
623
1083
|
options.setToolMode((prev) => prev === "select" ? "none" : "select");
|
|
624
1084
|
options.onInteract();
|
|
@@ -627,6 +1087,14 @@ var useHotkeys = (options) => {
|
|
|
627
1087
|
options.setToolMode((prev) => prev === "guides" ? "none" : "guides");
|
|
628
1088
|
options.onInteract();
|
|
629
1089
|
}
|
|
1090
|
+
if (key === "x") {
|
|
1091
|
+
options.setToolMode((prev) => prev === "xray" ? "none" : "xray");
|
|
1092
|
+
options.onInteract();
|
|
1093
|
+
}
|
|
1094
|
+
if (key === "r") {
|
|
1095
|
+
options.setRulersVisible((prev) => !prev);
|
|
1096
|
+
options.onInteract();
|
|
1097
|
+
}
|
|
630
1098
|
if (key === "h") {
|
|
631
1099
|
options.setGuideOrientation("horizontal");
|
|
632
1100
|
options.onInteract();
|
|
@@ -651,22 +1119,22 @@ var useHotkeys = (options) => {
|
|
|
651
1119
|
options.setAltPressed(false);
|
|
652
1120
|
}
|
|
653
1121
|
};
|
|
654
|
-
|
|
655
|
-
|
|
1122
|
+
target.addEventListener("keydown", handleKeyDown);
|
|
1123
|
+
target.addEventListener("keyup", handleKeyUp);
|
|
656
1124
|
return () => {
|
|
657
|
-
|
|
658
|
-
|
|
1125
|
+
target.removeEventListener("keydown", handleKeyDown);
|
|
1126
|
+
target.removeEventListener("keyup", handleKeyUp);
|
|
659
1127
|
};
|
|
660
1128
|
}, [options]);
|
|
661
1129
|
};
|
|
662
1130
|
|
|
663
1131
|
// hooks/use-live-element-tracking.ts
|
|
664
|
-
import { useEffect as
|
|
1132
|
+
import { useEffect as useEffect2, useRef as useRef4 } from "react";
|
|
665
1133
|
|
|
666
|
-
// geometry.ts
|
|
667
|
-
var getViewportSize = () => ({
|
|
668
|
-
width: typeof window === "undefined" ? 1 : window.innerWidth || 1,
|
|
669
|
-
height: typeof window === "undefined" ? 1 : window.innerHeight || 1
|
|
1134
|
+
// core/geometry.ts
|
|
1135
|
+
var getViewportSize = (ownerWindow) => ({
|
|
1136
|
+
width: ownerWindow?.innerWidth || (typeof window === "undefined" ? 1 : window.innerWidth) || 1,
|
|
1137
|
+
height: ownerWindow?.innerHeight || (typeof window === "undefined" ? 1 : window.innerHeight) || 1
|
|
670
1138
|
});
|
|
671
1139
|
var normalizeRect = (rect, viewport = getViewportSize()) => ({
|
|
672
1140
|
left: rect.left / viewport.width,
|
|
@@ -708,9 +1176,9 @@ var getDistanceToRect = (point, rect) => {
|
|
|
708
1176
|
return Math.hypot(dx, dy);
|
|
709
1177
|
};
|
|
710
1178
|
|
|
711
|
-
// distances.ts
|
|
712
|
-
var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB) => {
|
|
713
|
-
const viewport = getViewportSize();
|
|
1179
|
+
// core/distances.ts
|
|
1180
|
+
var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB, ownerWindow = window) => {
|
|
1181
|
+
const viewport = getViewportSize(ownerWindow);
|
|
714
1182
|
const normalizedRectA = normalizeRect(rectA, viewport);
|
|
715
1183
|
const normalizedRectB = normalizeRect(rectB, viewport);
|
|
716
1184
|
const rightA = rectA.left + rectA.width;
|
|
@@ -751,10 +1219,10 @@ var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB) => {
|
|
|
751
1219
|
}
|
|
752
1220
|
}
|
|
753
1221
|
const normalizedConnectors = connectors.map((segment) => ({
|
|
754
|
-
x1: clamp(segment.x1, 0,
|
|
755
|
-
y1: clamp(segment.y1, 0,
|
|
756
|
-
x2: clamp(segment.x2, 0,
|
|
757
|
-
y2: clamp(segment.y2, 0,
|
|
1222
|
+
x1: clamp(segment.x1, 0, ownerWindow.innerWidth),
|
|
1223
|
+
y1: clamp(segment.y1, 0, ownerWindow.innerHeight),
|
|
1224
|
+
x2: clamp(segment.x2, 0, ownerWindow.innerWidth),
|
|
1225
|
+
y2: clamp(segment.y2, 0, ownerWindow.innerHeight)
|
|
758
1226
|
})).filter(
|
|
759
1227
|
(segment) => Math.abs(segment.x1 - segment.x2) > 0.5 || Math.abs(segment.y1 - segment.y2) > 0.5
|
|
760
1228
|
);
|
|
@@ -771,17 +1239,17 @@ var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB) => {
|
|
|
771
1239
|
connectors: normalizedConnectors
|
|
772
1240
|
};
|
|
773
1241
|
};
|
|
774
|
-
var updateDistanceForResize = (distance, viewport = getViewportSize()) => {
|
|
775
|
-
const normalizedRectA = distance.normalizedRectA ?? normalizeRect(distance.rectA);
|
|
776
|
-
const normalizedRectB = distance.normalizedRectB ?? normalizeRect(distance.rectB);
|
|
1242
|
+
var updateDistanceForResize = (distance, viewport = getViewportSize(), ownerDocument = document, ownerWindow = window) => {
|
|
1243
|
+
const normalizedRectA = distance.normalizedRectA ?? normalizeRect(distance.rectA, viewport);
|
|
1244
|
+
const normalizedRectB = distance.normalizedRectB ?? normalizeRect(distance.rectB, viewport);
|
|
777
1245
|
let rectA = distance.rectA;
|
|
778
1246
|
let rectB = distance.rectB;
|
|
779
|
-
if (distance.elementRefA &&
|
|
1247
|
+
if (distance.elementRefA && ownerDocument.contains(distance.elementRefA)) {
|
|
780
1248
|
rectA = distance.elementRefA.getBoundingClientRect();
|
|
781
1249
|
} else {
|
|
782
1250
|
rectA = denormalizeRect(normalizedRectA, viewport);
|
|
783
1251
|
}
|
|
784
|
-
if (distance.elementRefB &&
|
|
1252
|
+
if (distance.elementRefB && ownerDocument.contains(distance.elementRefB)) {
|
|
785
1253
|
rectB = distance.elementRefB.getBoundingClientRect();
|
|
786
1254
|
} else {
|
|
787
1255
|
rectB = denormalizeRect(normalizedRectB, viewport);
|
|
@@ -790,7 +1258,8 @@ var updateDistanceForResize = (distance, viewport = getViewportSize()) => {
|
|
|
790
1258
|
rectA,
|
|
791
1259
|
rectB,
|
|
792
1260
|
distance.elementRefA,
|
|
793
|
-
distance.elementRefB
|
|
1261
|
+
distance.elementRefB,
|
|
1262
|
+
ownerWindow
|
|
794
1263
|
);
|
|
795
1264
|
return {
|
|
796
1265
|
...updated,
|
|
@@ -798,7 +1267,7 @@ var updateDistanceForResize = (distance, viewport = getViewportSize()) => {
|
|
|
798
1267
|
};
|
|
799
1268
|
};
|
|
800
1269
|
|
|
801
|
-
// dom.ts
|
|
1270
|
+
// core/dom.ts
|
|
802
1271
|
var getElementLabel = (element) => {
|
|
803
1272
|
const tag = element.tagName.toLowerCase();
|
|
804
1273
|
const id = element.id ? `#${element.id}` : "";
|
|
@@ -831,24 +1300,38 @@ var getRectFromDomCached = (element) => {
|
|
|
831
1300
|
};
|
|
832
1301
|
var cachedElements = [];
|
|
833
1302
|
var cachedFrame = -1;
|
|
1303
|
+
var cachedDocument = null;
|
|
834
1304
|
var getFrameToken = () => {
|
|
835
1305
|
if (typeof performance === "undefined") return 0;
|
|
836
1306
|
return Math.floor(performance.now() / 16);
|
|
837
1307
|
};
|
|
838
|
-
var getBodyElementsCached = () => {
|
|
1308
|
+
var getBodyElementsCached = (ownerDocument = document) => {
|
|
839
1309
|
const frame = getFrameToken();
|
|
840
|
-
if (frame === cachedFrame && cachedElements.length > 0) {
|
|
1310
|
+
if (frame === cachedFrame && cachedDocument === ownerDocument && cachedElements.length > 0) {
|
|
841
1311
|
return cachedElements;
|
|
842
1312
|
}
|
|
843
1313
|
cachedFrame = frame;
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
1314
|
+
cachedDocument = ownerDocument;
|
|
1315
|
+
const elements = [];
|
|
1316
|
+
const HTMLElementConstructor = ownerDocument.defaultView?.HTMLElement ?? HTMLElement;
|
|
1317
|
+
const visit = (root) => {
|
|
1318
|
+
const walker = ownerDocument.createTreeWalker(root, 1);
|
|
1319
|
+
let node = walker.nextNode();
|
|
1320
|
+
while (node) {
|
|
1321
|
+
if (node instanceof HTMLElementConstructor) {
|
|
1322
|
+
elements.push(node);
|
|
1323
|
+
if (node.shadowRoot) visit(node.shadowRoot);
|
|
1324
|
+
}
|
|
1325
|
+
node = walker.nextNode();
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
if (ownerDocument.body) visit(ownerDocument.body);
|
|
1329
|
+
cachedElements = elements;
|
|
847
1330
|
return cachedElements;
|
|
848
1331
|
};
|
|
849
|
-
var getInspectMeasurement = (element) => {
|
|
1332
|
+
var getInspectMeasurement = (element, ownerWindow = window) => {
|
|
850
1333
|
const rect = element.getBoundingClientRect();
|
|
851
|
-
const style =
|
|
1334
|
+
const style = ownerWindow.getComputedStyle(element);
|
|
852
1335
|
const padding = {
|
|
853
1336
|
top: parseEdge(style.paddingTop),
|
|
854
1337
|
right: parseEdge(style.paddingRight),
|
|
@@ -889,9 +1372,9 @@ var getInspectMeasurement = (element) => {
|
|
|
889
1372
|
elementRef: element
|
|
890
1373
|
};
|
|
891
1374
|
};
|
|
892
|
-
var updateMeasurementForResize = (measurement, viewport = getViewportSize()) => {
|
|
1375
|
+
var updateMeasurementForResize = (measurement, viewport = getViewportSize(), ownerDocument = document) => {
|
|
893
1376
|
let rect = measurement.rect;
|
|
894
|
-
if (measurement.elementRef &&
|
|
1377
|
+
if (measurement.elementRef && ownerDocument.contains(measurement.elementRef)) {
|
|
895
1378
|
rect = getRectFromDom(measurement.elementRef);
|
|
896
1379
|
} else if (measurement.normalizedRect) {
|
|
897
1380
|
rect = denormalizeRect(measurement.normalizedRect, viewport);
|
|
@@ -906,11 +1389,11 @@ var updateMeasurementForResize = (measurement, viewport = getViewportSize()) =>
|
|
|
906
1389
|
|
|
907
1390
|
// hooks/use-live-element-tracking.ts
|
|
908
1391
|
var useLiveElementTracking = (params) => {
|
|
909
|
-
const frameRef =
|
|
910
|
-
|
|
1392
|
+
const frameRef = useRef4(null);
|
|
1393
|
+
useEffect2(() => {
|
|
911
1394
|
if (!params.enabled) {
|
|
912
1395
|
if (frameRef.current) {
|
|
913
|
-
cancelAnimationFrame(frameRef.current);
|
|
1396
|
+
params.window.cancelAnimationFrame(frameRef.current);
|
|
914
1397
|
}
|
|
915
1398
|
frameRef.current = null;
|
|
916
1399
|
return;
|
|
@@ -918,7 +1401,7 @@ var useLiveElementTracking = (params) => {
|
|
|
918
1401
|
const tick = () => {
|
|
919
1402
|
params.setMeasurements(
|
|
920
1403
|
(prev) => prev.map((measurement) => {
|
|
921
|
-
if (!measurement.elementRef || !document.contains(measurement.elementRef)) {
|
|
1404
|
+
if (!measurement.elementRef || !params.document.contains(measurement.elementRef)) {
|
|
922
1405
|
return measurement;
|
|
923
1406
|
}
|
|
924
1407
|
const rect = getRectFromDom(measurement.elementRef);
|
|
@@ -932,7 +1415,7 @@ var useLiveElementTracking = (params) => {
|
|
|
932
1415
|
})
|
|
933
1416
|
);
|
|
934
1417
|
params.setActiveMeasurement((prev) => {
|
|
935
|
-
if (!prev?.elementRef || !document.contains(prev.elementRef))
|
|
1418
|
+
if (!prev?.elementRef || !params.document.contains(prev.elementRef))
|
|
936
1419
|
return prev;
|
|
937
1420
|
const rect = getRectFromDom(prev.elementRef);
|
|
938
1421
|
if (rectAlmostEqual(rect, prev.rect)) return prev;
|
|
@@ -945,8 +1428,8 @@ var useLiveElementTracking = (params) => {
|
|
|
945
1428
|
});
|
|
946
1429
|
params.setHeldDistances(
|
|
947
1430
|
(prev) => prev.map((distance) => {
|
|
948
|
-
const canTrackA = distance.elementRefA && document.contains(distance.elementRefA);
|
|
949
|
-
const canTrackB = distance.elementRefB && document.contains(distance.elementRefB);
|
|
1431
|
+
const canTrackA = distance.elementRefA && params.document.contains(distance.elementRefA);
|
|
1432
|
+
const canTrackB = distance.elementRefB && params.document.contains(distance.elementRefB);
|
|
950
1433
|
if (!canTrackA && !canTrackB) return distance;
|
|
951
1434
|
const rectA = canTrackA ? getRectFromDom(distance.elementRefA) : distance.rectA;
|
|
952
1435
|
const rectB = canTrackB ? getRectFromDom(distance.elementRefB) : distance.rectB;
|
|
@@ -957,7 +1440,8 @@ var useLiveElementTracking = (params) => {
|
|
|
957
1440
|
rectA,
|
|
958
1441
|
rectB,
|
|
959
1442
|
distance.elementRefA,
|
|
960
|
-
distance.elementRefB
|
|
1443
|
+
distance.elementRefB,
|
|
1444
|
+
params.window
|
|
961
1445
|
);
|
|
962
1446
|
return {
|
|
963
1447
|
...updated,
|
|
@@ -966,19 +1450,19 @@ var useLiveElementTracking = (params) => {
|
|
|
966
1450
|
})
|
|
967
1451
|
);
|
|
968
1452
|
const selected = params.selectedElementRef.current;
|
|
969
|
-
if (selected && document.contains(selected)) {
|
|
1453
|
+
if (selected && params.document.contains(selected)) {
|
|
970
1454
|
params.setSelectedMeasurement((prev) => {
|
|
971
|
-
const next = getInspectMeasurement(selected);
|
|
1455
|
+
const next = getInspectMeasurement(selected, params.window);
|
|
972
1456
|
if (prev && rectAlmostEqual(prev.rect, next.rect)) return prev;
|
|
973
1457
|
return next;
|
|
974
1458
|
});
|
|
975
1459
|
}
|
|
976
1460
|
params.setSelectedMeasurements(
|
|
977
1461
|
(prev) => prev.map((measurement) => {
|
|
978
|
-
if (!measurement.elementRef || !document.contains(measurement.elementRef)) {
|
|
1462
|
+
if (!measurement.elementRef || !params.document.contains(measurement.elementRef)) {
|
|
979
1463
|
return measurement;
|
|
980
1464
|
}
|
|
981
|
-
const next = getInspectMeasurement(measurement.elementRef);
|
|
1465
|
+
const next = getInspectMeasurement(measurement.elementRef, params.window);
|
|
982
1466
|
if (rectAlmostEqual(next.rect, measurement.rect)) return measurement;
|
|
983
1467
|
return {
|
|
984
1468
|
...next,
|
|
@@ -987,18 +1471,18 @@ var useLiveElementTracking = (params) => {
|
|
|
987
1471
|
})
|
|
988
1472
|
);
|
|
989
1473
|
const hover = params.hoverElementRef.current;
|
|
990
|
-
if (hover && document.contains(hover)) {
|
|
1474
|
+
if (hover && params.document.contains(hover)) {
|
|
991
1475
|
const rect = getRectFromDom(hover);
|
|
992
1476
|
params.setHoverRect(
|
|
993
1477
|
(prev) => prev && rectAlmostEqual(prev, rect) ? prev : rect
|
|
994
1478
|
);
|
|
995
1479
|
}
|
|
996
|
-
frameRef.current = requestAnimationFrame(tick);
|
|
1480
|
+
frameRef.current = params.window.requestAnimationFrame(tick);
|
|
997
1481
|
};
|
|
998
|
-
frameRef.current = requestAnimationFrame(tick);
|
|
1482
|
+
frameRef.current = params.window.requestAnimationFrame(tick);
|
|
999
1483
|
return () => {
|
|
1000
1484
|
if (frameRef.current) {
|
|
1001
|
-
cancelAnimationFrame(frameRef.current);
|
|
1485
|
+
params.window.cancelAnimationFrame(frameRef.current);
|
|
1002
1486
|
}
|
|
1003
1487
|
frameRef.current = null;
|
|
1004
1488
|
};
|
|
@@ -1006,13 +1490,16 @@ var useLiveElementTracking = (params) => {
|
|
|
1006
1490
|
};
|
|
1007
1491
|
|
|
1008
1492
|
// hooks/use-measure-toggles.ts
|
|
1009
|
-
import { useState as
|
|
1493
|
+
import { useState as useState5 } from "react";
|
|
1010
1494
|
var useMeasureToggles = (options = {}) => {
|
|
1011
|
-
const [enabled, setEnabled] =
|
|
1012
|
-
const [altPressed, setAltPressed] =
|
|
1013
|
-
const [toolMode, setToolMode] =
|
|
1495
|
+
const [enabled, setEnabled] = useState5(options.initialEnabled ?? true);
|
|
1496
|
+
const [altPressed, setAltPressed] = useState5(false);
|
|
1497
|
+
const [toolMode, setToolMode] = useState5(
|
|
1014
1498
|
options.initialToolMode ?? "none"
|
|
1015
1499
|
);
|
|
1500
|
+
const [rulersVisible, setRulersVisible] = useState5(
|
|
1501
|
+
options.initialRulersVisible ?? false
|
|
1502
|
+
);
|
|
1016
1503
|
const holdEnabled = false;
|
|
1017
1504
|
const multiMeasureEnabled = false;
|
|
1018
1505
|
const snapGuidesEnabled = true;
|
|
@@ -1026,6 +1513,8 @@ var useMeasureToggles = (options = {}) => {
|
|
|
1026
1513
|
setAltPressed,
|
|
1027
1514
|
toolMode,
|
|
1028
1515
|
setToolMode,
|
|
1516
|
+
rulersVisible,
|
|
1517
|
+
setRulersVisible,
|
|
1029
1518
|
guidesEnabled,
|
|
1030
1519
|
multiMeasureEnabled,
|
|
1031
1520
|
snapGuidesEnabled,
|
|
@@ -1034,16 +1523,16 @@ var useMeasureToggles = (options = {}) => {
|
|
|
1034
1523
|
};
|
|
1035
1524
|
|
|
1036
1525
|
// hooks/use-measurement-state.ts
|
|
1037
|
-
import { useState as
|
|
1526
|
+
import { useState as useState6 } from "react";
|
|
1038
1527
|
var useMeasurementState = (options = {}) => {
|
|
1039
|
-
const [activeMeasurement, setActiveMeasurement] =
|
|
1040
|
-
const [measurements, setMeasurements] =
|
|
1528
|
+
const [activeMeasurement, setActiveMeasurement] = useState6(options.initialActiveMeasurement ?? null);
|
|
1529
|
+
const [measurements, setMeasurements] = useState6(
|
|
1041
1530
|
options.initialMeasurements ?? []
|
|
1042
1531
|
);
|
|
1043
|
-
const [selectedMeasurement, setSelectedMeasurement] =
|
|
1044
|
-
const [selectedMeasurements, setSelectedMeasurements] =
|
|
1045
|
-
const [hoverRect, setHoverRect] =
|
|
1046
|
-
const [heldDistances, setHeldDistances] =
|
|
1532
|
+
const [selectedMeasurement, setSelectedMeasurement] = useState6(null);
|
|
1533
|
+
const [selectedMeasurements, setSelectedMeasurements] = useState6([]);
|
|
1534
|
+
const [hoverRect, setHoverRect] = useState6(null);
|
|
1535
|
+
const [heldDistances, setHeldDistances] = useState6(
|
|
1047
1536
|
options.initialHeldDistances ?? []
|
|
1048
1537
|
);
|
|
1049
1538
|
return {
|
|
@@ -1065,7 +1554,7 @@ var useMeasurementState = (options = {}) => {
|
|
|
1065
1554
|
// hooks/use-measurer-derived.ts
|
|
1066
1555
|
import { useMemo } from "react";
|
|
1067
1556
|
|
|
1068
|
-
// edge-visibility.ts
|
|
1557
|
+
// core/edge-visibility.ts
|
|
1069
1558
|
var rangesOverlap = (a1, a2, b1, b2) => Math.min(a2, b2) - Math.max(a1, b1) > 0;
|
|
1070
1559
|
var getEdgeVisibilityForRects = (rects, epsilon = 1) => {
|
|
1071
1560
|
const visibility = rects.map(() => ({
|
|
@@ -1105,24 +1594,25 @@ var getEdgeVisibilityForRects = (rects, epsilon = 1) => {
|
|
|
1105
1594
|
return visibility;
|
|
1106
1595
|
};
|
|
1107
1596
|
|
|
1108
|
-
// guides.ts
|
|
1109
|
-
var getGuideRect = (guide) => {
|
|
1110
|
-
const viewport = getViewportSize();
|
|
1597
|
+
// core/guides.ts
|
|
1598
|
+
var getGuideRect = (guide, ownerWindow = window) => {
|
|
1599
|
+
const viewport = getViewportSize(ownerWindow);
|
|
1111
1600
|
return guide.orientation === "vertical" ? { left: guide.position, top: 0, width: 1, height: viewport.height } : { left: 0, top: guide.position, width: viewport.width, height: 1 };
|
|
1112
1601
|
};
|
|
1113
1602
|
var getGuideDistance = (guide, point) => guide.orientation === "vertical" ? Math.abs(guide.position - point.x) : Math.abs(guide.position - point.y);
|
|
1114
1603
|
var getSnapGuidePosition = (params) => {
|
|
1604
|
+
const ownerDocument = params.document ?? document;
|
|
1115
1605
|
const { orientation, point, snapGuidesEnabled, overlayNode, guides } = params;
|
|
1116
1606
|
if (!snapGuidesEnabled) {
|
|
1117
1607
|
return orientation === "vertical" ? point.x : point.y;
|
|
1118
1608
|
}
|
|
1119
|
-
const elements = getBodyElementsCached();
|
|
1609
|
+
const elements = getBodyElementsCached(ownerDocument);
|
|
1120
1610
|
let bestValue = orientation === "vertical" ? point.x : point.y;
|
|
1121
1611
|
let bestDistance = GUIDE_SNAP_DISTANCE + 1;
|
|
1122
1612
|
for (const element of elements) {
|
|
1123
|
-
if (!(element instanceof HTMLElement)) continue;
|
|
1613
|
+
if (!(element instanceof (ownerDocument.defaultView?.HTMLElement ?? HTMLElement))) continue;
|
|
1124
1614
|
if (overlayNode && overlayNode.contains(element)) continue;
|
|
1125
|
-
if (element ===
|
|
1615
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1126
1616
|
continue;
|
|
1127
1617
|
const rect = getRectFromDomCached(element);
|
|
1128
1618
|
if (rect.width <= 2 || rect.height <= 2) continue;
|
|
@@ -1158,7 +1648,7 @@ var getSnapGuidePosition = (params) => {
|
|
|
1158
1648
|
return bestDistance <= GUIDE_SNAP_DISTANCE ? bestValue : orientation === "vertical" ? point.x : point.y;
|
|
1159
1649
|
};
|
|
1160
1650
|
|
|
1161
|
-
// option-measurements.ts
|
|
1651
|
+
// core/option-measurements.ts
|
|
1162
1652
|
var getHoveredGuide = (point, guides) => {
|
|
1163
1653
|
if (!point || guides.length === 0) return null;
|
|
1164
1654
|
let closest = null;
|
|
@@ -1179,6 +1669,8 @@ var getSelectedGuide = (guides, selectedGuideIds) => {
|
|
|
1179
1669
|
return guides.find((guide) => guide.id === lastId) ?? null;
|
|
1180
1670
|
};
|
|
1181
1671
|
var getOptionPairOverlay = (params) => {
|
|
1672
|
+
const ownerDocument = params.document ?? document;
|
|
1673
|
+
const ownerWindow = params.window ?? window;
|
|
1182
1674
|
if (!params.altPressed) return null;
|
|
1183
1675
|
if (!params.selectedGuide && !params.primarySelectedMeasurement) return null;
|
|
1184
1676
|
const primary = params.primarySelectedMeasurement;
|
|
@@ -1207,10 +1699,13 @@ var getOptionPairOverlay = (params) => {
|
|
|
1207
1699
|
selectedTarget.rect,
|
|
1208
1700
|
hoverTarget.rect,
|
|
1209
1701
|
selectedTarget.element ?? null,
|
|
1210
|
-
hoverTarget.element ?? null
|
|
1702
|
+
hoverTarget.element ?? null,
|
|
1703
|
+
ownerWindow
|
|
1211
1704
|
);
|
|
1212
1705
|
};
|
|
1213
1706
|
var getOptionContainerLines = (params) => {
|
|
1707
|
+
const ownerDocument = params.document ?? document;
|
|
1708
|
+
const ownerWindow = params.window ?? window;
|
|
1214
1709
|
if (!params.altPressed || !params.primarySelectedMeasurement || params.optionPairOverlay)
|
|
1215
1710
|
return null;
|
|
1216
1711
|
if (params.selectedGuideIds.length > 0) return null;
|
|
@@ -1218,11 +1713,11 @@ var getOptionContainerLines = (params) => {
|
|
|
1218
1713
|
if (params.selectedElement && params.hoverElement && params.hoverElement !== params.selectedElement && params.hoverElement.contains(params.selectedElement)) {
|
|
1219
1714
|
containerElement = params.hoverElement;
|
|
1220
1715
|
}
|
|
1221
|
-
const containerRect = containerElement && containerElement !==
|
|
1716
|
+
const containerRect = containerElement && containerElement !== ownerDocument.body && containerElement !== ownerDocument.documentElement ? getRectFromDom(containerElement) : {
|
|
1222
1717
|
left: 0,
|
|
1223
1718
|
top: 0,
|
|
1224
|
-
width:
|
|
1225
|
-
height:
|
|
1719
|
+
width: ownerWindow.innerWidth,
|
|
1720
|
+
height: ownerWindow.innerHeight
|
|
1226
1721
|
};
|
|
1227
1722
|
const rect = params.primarySelectedMeasurement.rect;
|
|
1228
1723
|
const right = rect.left + rect.width;
|
|
@@ -1261,12 +1756,20 @@ var getOptionContainerLines = (params) => {
|
|
|
1261
1756
|
};
|
|
1262
1757
|
};
|
|
1263
1758
|
|
|
1264
|
-
// selection-helpers.ts
|
|
1759
|
+
// core/selection-helpers.ts
|
|
1760
|
+
var getOverlayHost = (overlayNode) => {
|
|
1761
|
+
if (!overlayNode) return null;
|
|
1762
|
+
const rootNode = overlayNode.getRootNode();
|
|
1763
|
+
return rootNode.nodeType === 11 ? rootNode.host : null;
|
|
1764
|
+
};
|
|
1265
1765
|
var getPrimarySelectedMeasurement = (selectedMeasurements, selectedMeasurement) => selectedMeasurements.length > 0 ? selectedMeasurements[selectedMeasurements.length - 1] : selectedMeasurement;
|
|
1266
1766
|
var getSelectedMeasurementHit = (params) => {
|
|
1767
|
+
const ownerDocument = params.document ?? document;
|
|
1768
|
+
const HTMLElementConstructor = ownerDocument.defaultView?.HTMLElement ?? HTMLElement;
|
|
1769
|
+
const overlayHost = getOverlayHost(params.overlayNode);
|
|
1267
1770
|
const candidates = params.selectedMeasurements.map((measurement) => {
|
|
1268
1771
|
const element = measurement.elementRef;
|
|
1269
|
-
if (!element || !
|
|
1772
|
+
if (!element || !ownerDocument.contains(element)) return null;
|
|
1270
1773
|
const rect = getRectFromDom(element);
|
|
1271
1774
|
return {
|
|
1272
1775
|
measurement,
|
|
@@ -1276,10 +1779,11 @@ var getSelectedMeasurementHit = (params) => {
|
|
|
1276
1779
|
};
|
|
1277
1780
|
}).filter((item) => item !== null).sort((a, b) => a.area - b.area);
|
|
1278
1781
|
if (candidates.length === 0) return null;
|
|
1279
|
-
const stack =
|
|
1782
|
+
const stack = ownerDocument.elementsFromPoint(params.point.x, params.point.y);
|
|
1280
1783
|
for (const element of stack) {
|
|
1281
|
-
if (!(element instanceof
|
|
1784
|
+
if (!(element instanceof HTMLElementConstructor)) continue;
|
|
1282
1785
|
if (params.overlayNode && params.overlayNode.contains(element)) continue;
|
|
1786
|
+
if (overlayHost && element === overlayHost) continue;
|
|
1283
1787
|
for (const candidate of candidates) {
|
|
1284
1788
|
if (candidate.element === element || candidate.element.contains(element)) {
|
|
1285
1789
|
return candidate.measurement;
|
|
@@ -1296,6 +1800,8 @@ var getSelectedMeasurementHit = (params) => {
|
|
|
1296
1800
|
|
|
1297
1801
|
// hooks/use-measurer-derived.ts
|
|
1298
1802
|
var useMeasurerDerived = ({
|
|
1803
|
+
document: document2,
|
|
1804
|
+
window: window2,
|
|
1299
1805
|
start,
|
|
1300
1806
|
end,
|
|
1301
1807
|
selectedMeasurements,
|
|
@@ -1380,7 +1886,9 @@ var useMeasurerDerived = ({
|
|
|
1380
1886
|
selectedGuide,
|
|
1381
1887
|
hoverGuide,
|
|
1382
1888
|
hoverElement,
|
|
1383
|
-
selectedElementRef: selectedElement
|
|
1889
|
+
selectedElementRef: selectedElement,
|
|
1890
|
+
document: document2,
|
|
1891
|
+
window: window2
|
|
1384
1892
|
});
|
|
1385
1893
|
}, [
|
|
1386
1894
|
altPressed,
|
|
@@ -1397,7 +1905,9 @@ var useMeasurerDerived = ({
|
|
|
1397
1905
|
optionPairOverlay,
|
|
1398
1906
|
selectedGuideIds,
|
|
1399
1907
|
selectedElement,
|
|
1400
|
-
hoverElement
|
|
1908
|
+
hoverElement,
|
|
1909
|
+
document: document2,
|
|
1910
|
+
window: window2
|
|
1401
1911
|
});
|
|
1402
1912
|
}, [
|
|
1403
1913
|
altPressed,
|
|
@@ -1411,8 +1921,11 @@ var useMeasurerDerived = ({
|
|
|
1411
1921
|
if (!altPressed || !guidesEnabled) return null;
|
|
1412
1922
|
if (selectedGuide && hoverGuide && selectedGuide.id !== hoverGuide.id) {
|
|
1413
1923
|
return getDistanceOverlay(
|
|
1414
|
-
getGuideRect(selectedGuide),
|
|
1415
|
-
getGuideRect(hoverGuide)
|
|
1924
|
+
getGuideRect(selectedGuide, window2),
|
|
1925
|
+
getGuideRect(hoverGuide, window2),
|
|
1926
|
+
null,
|
|
1927
|
+
null,
|
|
1928
|
+
window2
|
|
1416
1929
|
);
|
|
1417
1930
|
}
|
|
1418
1931
|
if (!guidePreview) return null;
|
|
@@ -1435,8 +1948,11 @@ var useMeasurerDerived = ({
|
|
|
1435
1948
|
);
|
|
1436
1949
|
if (!nearest) return null;
|
|
1437
1950
|
return getDistanceOverlay(
|
|
1438
|
-
getGuideRect(previewGuide),
|
|
1439
|
-
getGuideRect(nearest.guide)
|
|
1951
|
+
getGuideRect(previewGuide, window2),
|
|
1952
|
+
getGuideRect(nearest.guide, window2),
|
|
1953
|
+
null,
|
|
1954
|
+
null,
|
|
1955
|
+
window2
|
|
1440
1956
|
);
|
|
1441
1957
|
}, [
|
|
1442
1958
|
altPressed,
|
|
@@ -1506,7 +2022,7 @@ var useMeasurerDerived = ({
|
|
|
1506
2022
|
};
|
|
1507
2023
|
|
|
1508
2024
|
// hooks/use-measurer-history.ts
|
|
1509
|
-
import { useCallback as useCallback3,
|
|
2025
|
+
import { useCallback as useCallback3, useRef as useRef5 } from "react";
|
|
1510
2026
|
var HISTORY_LIMIT = 50;
|
|
1511
2027
|
var useMeasurerHistory = ({
|
|
1512
2028
|
toggles,
|
|
@@ -1552,9 +2068,9 @@ var useMeasurerHistory = ({
|
|
|
1552
2068
|
setSelectedElement,
|
|
1553
2069
|
clearSelectionRect
|
|
1554
2070
|
} = transient;
|
|
1555
|
-
const historyRef =
|
|
1556
|
-
const futureRef =
|
|
1557
|
-
const historySignatureRef =
|
|
2071
|
+
const historyRef = useRef5([]);
|
|
2072
|
+
const futureRef = useRef5([]);
|
|
2073
|
+
const historySignatureRef = useRef5(null);
|
|
1558
2074
|
const captureSnapshot = useCallback3(() => {
|
|
1559
2075
|
return {
|
|
1560
2076
|
enabled,
|
|
@@ -1716,49 +2232,32 @@ var useMeasurerHistory = ({
|
|
|
1716
2232
|
committed = true;
|
|
1717
2233
|
};
|
|
1718
2234
|
}, [recordSnapshot]);
|
|
1719
|
-
useEffect4(() => {
|
|
1720
|
-
const handleKeyDown = (event) => {
|
|
1721
|
-
if (!(event.metaKey || event.ctrlKey)) return;
|
|
1722
|
-
if (event.key.toLowerCase() !== "z") return;
|
|
1723
|
-
if (event.shiftKey) {
|
|
1724
|
-
if (futureRef.current.length === 0) return;
|
|
1725
|
-
event.preventDefault();
|
|
1726
|
-
redo();
|
|
1727
|
-
return;
|
|
1728
|
-
}
|
|
1729
|
-
if (historyRef.current.length === 0) return;
|
|
1730
|
-
event.preventDefault();
|
|
1731
|
-
undo();
|
|
1732
|
-
};
|
|
1733
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
1734
|
-
return () => {
|
|
1735
|
-
window.removeEventListener("keydown", handleKeyDown);
|
|
1736
|
-
};
|
|
1737
|
-
}, [redo, undo]);
|
|
1738
2235
|
return {
|
|
1739
2236
|
recordSnapshot,
|
|
1740
2237
|
createActionCommit,
|
|
1741
2238
|
setToolModeWithHistory,
|
|
1742
2239
|
setGuideOrientationWithHistory,
|
|
1743
|
-
setEnabledWithHistory
|
|
2240
|
+
setEnabledWithHistory,
|
|
2241
|
+
undo,
|
|
2242
|
+
redo
|
|
1744
2243
|
};
|
|
1745
2244
|
};
|
|
1746
2245
|
|
|
1747
2246
|
// hooks/use-measurer-local-state.ts
|
|
1748
|
-
import { useCallback as useCallback4, useState as
|
|
2247
|
+
import { useCallback as useCallback4, useState as useState7 } from "react";
|
|
1749
2248
|
var useMeasurerLocalState = ({
|
|
1750
2249
|
selectedElementRef,
|
|
1751
2250
|
hoverElementRef,
|
|
1752
2251
|
selectionRectRef
|
|
1753
2252
|
}) => {
|
|
1754
|
-
const [selectionOriginRect, setSelectionOriginRect] =
|
|
2253
|
+
const [selectionOriginRect, setSelectionOriginRect] = useState7(
|
|
1755
2254
|
null
|
|
1756
2255
|
);
|
|
1757
|
-
const [hoverPointer, setHoverPointer] =
|
|
1758
|
-
const [hoverElement, setHoverElementState] =
|
|
2256
|
+
const [hoverPointer, setHoverPointer] = useState7(null);
|
|
2257
|
+
const [hoverElement, setHoverElementState] = useState7(
|
|
1759
2258
|
null
|
|
1760
2259
|
);
|
|
1761
|
-
const [selectedElement, setSelectedElementState] =
|
|
2260
|
+
const [selectedElement, setSelectedElementState] = useState7(null);
|
|
1762
2261
|
const setSelectedElement = useCallback4(
|
|
1763
2262
|
(element) => {
|
|
1764
2263
|
selectedElementRef.current = element;
|
|
@@ -1791,9 +2290,9 @@ var useMeasurerLocalState = ({
|
|
|
1791
2290
|
};
|
|
1792
2291
|
|
|
1793
2292
|
// hooks/use-measurer-pointer.ts
|
|
1794
|
-
import { useCallback as useCallback5, useEffect as
|
|
2293
|
+
import { useCallback as useCallback5, useEffect as useEffect3, useRef as useRef6 } from "react";
|
|
1795
2294
|
|
|
1796
|
-
// targets.ts
|
|
2295
|
+
// core/targets.ts
|
|
1797
2296
|
var pickMultiTargets = (selectionRect, items) => {
|
|
1798
2297
|
const candidates = items.map(({ element, rect }) => {
|
|
1799
2298
|
const overlapArea = intersectionArea(selectionRect, rect);
|
|
@@ -1858,17 +2357,39 @@ var pickPointTarget = (point, items) => {
|
|
|
1858
2357
|
return scored[0].element;
|
|
1859
2358
|
};
|
|
1860
2359
|
|
|
1861
|
-
// selection.ts
|
|
1862
|
-
var
|
|
2360
|
+
// core/selection.ts
|
|
2361
|
+
var getOverlayHost2 = (overlayNode) => {
|
|
2362
|
+
if (!overlayNode) return null;
|
|
2363
|
+
const rootNode = overlayNode.getRootNode();
|
|
2364
|
+
return rootNode.nodeType === 11 ? rootNode.host : null;
|
|
2365
|
+
};
|
|
2366
|
+
var isOverlayElement = (element, overlayNode, overlayHost) => {
|
|
2367
|
+
if (overlayNode && overlayNode.contains(element)) return true;
|
|
2368
|
+
if (overlayHost && element === overlayHost) return true;
|
|
2369
|
+
return false;
|
|
2370
|
+
};
|
|
2371
|
+
var getDeepestElementAt = (element, point) => {
|
|
2372
|
+
let current = element;
|
|
2373
|
+
const HTMLElementConstructor = element.ownerDocument.defaultView?.HTMLElement ?? HTMLElement;
|
|
2374
|
+
while (current instanceof HTMLElementConstructor && current.shadowRoot) {
|
|
2375
|
+
const nested = current.shadowRoot.elementFromPoint(point.x, point.y);
|
|
2376
|
+
if (!nested || nested === current) break;
|
|
2377
|
+
current = nested;
|
|
2378
|
+
}
|
|
2379
|
+
return current;
|
|
2380
|
+
};
|
|
2381
|
+
var getTargetElement = (point, overlayNode, ownerDocument = document) => {
|
|
2382
|
+
const overlayHost = getOverlayHost2(overlayNode);
|
|
1863
2383
|
if (overlayNode) {
|
|
1864
2384
|
const previous = overlayNode.style.pointerEvents;
|
|
1865
2385
|
overlayNode.style.pointerEvents = "none";
|
|
1866
|
-
const elements2 =
|
|
2386
|
+
const elements2 = ownerDocument.elementsFromPoint(point.x, point.y);
|
|
1867
2387
|
overlayNode.style.pointerEvents = previous;
|
|
1868
|
-
for (const
|
|
1869
|
-
|
|
1870
|
-
if (
|
|
1871
|
-
if (element
|
|
2388
|
+
for (const rawElement of elements2) {
|
|
2389
|
+
const element = getDeepestElementAt(rawElement, point);
|
|
2390
|
+
if (!(element instanceof (ownerDocument.defaultView?.HTMLElement ?? HTMLElement))) continue;
|
|
2391
|
+
if (isOverlayElement(element, overlayNode, overlayHost)) continue;
|
|
2392
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1872
2393
|
continue;
|
|
1873
2394
|
const rect = element.getBoundingClientRect();
|
|
1874
2395
|
if (rect.width <= 2 || rect.height <= 2) continue;
|
|
@@ -1876,10 +2397,12 @@ var getTargetElement = (point, overlayNode) => {
|
|
|
1876
2397
|
}
|
|
1877
2398
|
return null;
|
|
1878
2399
|
}
|
|
1879
|
-
const elements =
|
|
1880
|
-
for (const
|
|
1881
|
-
|
|
1882
|
-
if (element
|
|
2400
|
+
const elements = ownerDocument.elementsFromPoint(point.x, point.y);
|
|
2401
|
+
for (const rawElement of elements) {
|
|
2402
|
+
const element = getDeepestElementAt(rawElement, point);
|
|
2403
|
+
if (!(element instanceof (ownerDocument.defaultView?.HTMLElement ?? HTMLElement))) continue;
|
|
2404
|
+
if (isOverlayElement(element, overlayNode, overlayHost)) continue;
|
|
2405
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1883
2406
|
continue;
|
|
1884
2407
|
const rect = element.getBoundingClientRect();
|
|
1885
2408
|
if (rect.width <= 2 || rect.height <= 2) continue;
|
|
@@ -1887,33 +2410,34 @@ var getTargetElement = (point, overlayNode) => {
|
|
|
1887
2410
|
}
|
|
1888
2411
|
return null;
|
|
1889
2412
|
};
|
|
1890
|
-
var getSnappedClickTarget = (point, overlayNode, snapEnabled) => {
|
|
1891
|
-
if (!snapEnabled) return getTargetElement(point, overlayNode);
|
|
2413
|
+
var getSnappedClickTarget = (point, overlayNode, snapEnabled, ownerDocument = document) => {
|
|
2414
|
+
if (!snapEnabled) return getTargetElement(point, overlayNode, ownerDocument);
|
|
1892
2415
|
const probeRect = {
|
|
1893
2416
|
left: point.x - 20,
|
|
1894
2417
|
top: point.y - 20,
|
|
1895
2418
|
width: 40,
|
|
1896
2419
|
height: 40
|
|
1897
2420
|
};
|
|
1898
|
-
const entries = getSelectionEntries(probeRect, overlayNode);
|
|
1899
|
-
return pickPointTarget(point, entries) ?? pickSingleTarget(probeRect, point, entries) ?? getTargetElement(point, overlayNode);
|
|
2421
|
+
const entries = getSelectionEntries(probeRect, overlayNode, ownerDocument);
|
|
2422
|
+
return pickPointTarget(point, entries) ?? pickSingleTarget(probeRect, point, entries) ?? getTargetElement(point, overlayNode, ownerDocument);
|
|
1900
2423
|
};
|
|
1901
|
-
var getSelectionEntries = (rect, overlayNode) => {
|
|
2424
|
+
var getSelectionEntries = (rect, overlayNode, ownerDocument = document) => {
|
|
2425
|
+
const overlayHost = getOverlayHost2(overlayNode);
|
|
1902
2426
|
const frame = getFrameToken();
|
|
1903
2427
|
const key = `${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(
|
|
1904
2428
|
rect.width
|
|
1905
2429
|
)}:${Math.round(rect.height)}`;
|
|
1906
|
-
if (frame === cachedSelectionFrame && cachedSelectionKey === key && cachedOverlayNode === overlayNode) {
|
|
2430
|
+
if (frame === cachedSelectionFrame && cachedSelectionKey === key && cachedOverlayNode === overlayNode && cachedSelectionDocument === ownerDocument) {
|
|
1907
2431
|
return cachedSelectionEntries;
|
|
1908
2432
|
}
|
|
1909
2433
|
const minLeft = rect.left - 1;
|
|
1910
2434
|
const minTop = rect.top - 1;
|
|
1911
2435
|
const maxRight = rect.left + rect.width + 1;
|
|
1912
2436
|
const maxBottom = rect.top + rect.height + 1;
|
|
1913
|
-
const elements = getBodyElementsCached();
|
|
2437
|
+
const elements = getBodyElementsCached(ownerDocument);
|
|
1914
2438
|
const entries = elements.map((element) => ({ element, rect: getRectFromDomCached(element) })).filter(({ element, rect: elementRect }) => {
|
|
1915
|
-
if (overlayNode
|
|
1916
|
-
if (element ===
|
|
2439
|
+
if (isOverlayElement(element, overlayNode, overlayHost)) return false;
|
|
2440
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1917
2441
|
return false;
|
|
1918
2442
|
if (elementRect.width < MIN_MULTI_TARGET_SIZE || elementRect.height < MIN_MULTI_TARGET_SIZE) {
|
|
1919
2443
|
return false;
|
|
@@ -1927,6 +2451,7 @@ var getSelectionEntries = (rect, overlayNode) => {
|
|
|
1927
2451
|
cachedSelectionFrame = frame;
|
|
1928
2452
|
cachedSelectionKey = key;
|
|
1929
2453
|
cachedOverlayNode = overlayNode;
|
|
2454
|
+
cachedSelectionDocument = ownerDocument;
|
|
1930
2455
|
cachedSelectionEntries = entries;
|
|
1931
2456
|
return entries;
|
|
1932
2457
|
};
|
|
@@ -1934,30 +2459,33 @@ var cachedSelectionFrame = -1;
|
|
|
1934
2459
|
var cachedSelectionKey = "";
|
|
1935
2460
|
var cachedSelectionEntries = [];
|
|
1936
2461
|
var cachedOverlayNode = null;
|
|
2462
|
+
var cachedSelectionDocument = null;
|
|
1937
2463
|
var getSelectionCacheKey = (rect) => `${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(
|
|
1938
2464
|
rect.width
|
|
1939
2465
|
)}:${Math.round(rect.height)}`;
|
|
1940
|
-
var getSelectionEntriesCached = (rect, overlayNode, cache) => {
|
|
2466
|
+
var getSelectionEntriesCached = (rect, overlayNode, cache, ownerDocument = document) => {
|
|
1941
2467
|
const frame = getFrameToken();
|
|
1942
2468
|
const key = getSelectionCacheKey(rect);
|
|
1943
2469
|
if (cache.key === key && cache.overlayNode === overlayNode && cache.frame === frame) {
|
|
1944
2470
|
return cache.entries;
|
|
1945
2471
|
}
|
|
1946
|
-
const entries = getSelectionEntries(rect, overlayNode);
|
|
2472
|
+
const entries = getSelectionEntries(rect, overlayNode, ownerDocument);
|
|
1947
2473
|
cache.key = key;
|
|
1948
2474
|
cache.overlayNode = overlayNode;
|
|
1949
2475
|
cache.frame = frame;
|
|
1950
2476
|
cache.entries = entries;
|
|
1951
2477
|
return entries;
|
|
1952
2478
|
};
|
|
1953
|
-
var getElementsInRectCached = (rect, overlayNode, cache) => {
|
|
1954
|
-
const entries = getSelectionEntriesCached(rect, overlayNode, cache);
|
|
2479
|
+
var getElementsInRectCached = (rect, overlayNode, cache, ownerDocument = document) => {
|
|
2480
|
+
const entries = getSelectionEntriesCached(rect, overlayNode, cache, ownerDocument);
|
|
1955
2481
|
if (entries.length === 0) return [];
|
|
1956
2482
|
return pickMultiTargets(rect, entries);
|
|
1957
2483
|
};
|
|
1958
2484
|
|
|
1959
2485
|
// hooks/use-measurer-pointer.ts
|
|
1960
2486
|
var useMeasurerPointer = ({
|
|
2487
|
+
document: document2,
|
|
2488
|
+
window: window2,
|
|
1961
2489
|
toolbarRef,
|
|
1962
2490
|
overlayRef,
|
|
1963
2491
|
selectionRectRef,
|
|
@@ -2001,46 +2529,26 @@ var useMeasurerPointer = ({
|
|
|
2001
2529
|
setHoverPointer,
|
|
2002
2530
|
clearSelectionRect
|
|
2003
2531
|
}) => {
|
|
2004
|
-
const hoverFrameRef =
|
|
2005
|
-
const hoverPointRef =
|
|
2006
|
-
const selectionCacheRef =
|
|
2532
|
+
const hoverFrameRef = useRef6(null);
|
|
2533
|
+
const hoverPointRef = useRef6(null);
|
|
2534
|
+
const selectionCacheRef = useRef6({
|
|
2007
2535
|
key: "",
|
|
2008
2536
|
entries: [],
|
|
2009
2537
|
overlayNode: null,
|
|
2010
2538
|
frame: -1
|
|
2011
2539
|
});
|
|
2012
|
-
const shiftDragRef =
|
|
2013
|
-
const shiftToggleElementRef =
|
|
2014
|
-
|
|
2015
|
-
const guidesRef = useRef5(guides);
|
|
2016
|
-
const snapGuidesEnabledRef = useRef5(snapGuidesEnabled);
|
|
2017
|
-
const draggingGuideIdRef = useRef5(draggingGuideId);
|
|
2018
|
-
const guideOrientationRef = useRef5(guideOrientation);
|
|
2019
|
-
useEffect5(() => {
|
|
2540
|
+
const shiftDragRef = useRef6(false);
|
|
2541
|
+
const shiftToggleElementRef = useRef6(null);
|
|
2542
|
+
useEffect3(() => {
|
|
2020
2543
|
return () => {
|
|
2021
2544
|
if (hoverFrameRef.current) {
|
|
2022
|
-
cancelAnimationFrame(hoverFrameRef.current);
|
|
2545
|
+
window2.cancelAnimationFrame(hoverFrameRef.current);
|
|
2023
2546
|
}
|
|
2024
2547
|
};
|
|
2025
2548
|
}, []);
|
|
2026
|
-
useEffect5(() => {
|
|
2027
|
-
guidesEnabledRef.current = guidesEnabled;
|
|
2028
|
-
}, [guidesEnabled]);
|
|
2029
|
-
useEffect5(() => {
|
|
2030
|
-
guidesRef.current = guides;
|
|
2031
|
-
}, [guides]);
|
|
2032
|
-
useEffect5(() => {
|
|
2033
|
-
snapGuidesEnabledRef.current = snapGuidesEnabled;
|
|
2034
|
-
}, [snapGuidesEnabled]);
|
|
2035
|
-
useEffect5(() => {
|
|
2036
|
-
guideOrientationRef.current = guideOrientation;
|
|
2037
|
-
}, [guideOrientation]);
|
|
2038
|
-
useEffect5(() => {
|
|
2039
|
-
draggingGuideIdRef.current = draggingGuideId;
|
|
2040
|
-
}, [draggingGuideId]);
|
|
2041
2549
|
const updateHoverTarget = useCallback5(
|
|
2042
2550
|
(point) => {
|
|
2043
|
-
const target = getTargetElement(point, overlayRef.current);
|
|
2551
|
+
const target = getTargetElement(point, overlayRef.current, document2);
|
|
2044
2552
|
if (target) {
|
|
2045
2553
|
const rect = target.getBoundingClientRect();
|
|
2046
2554
|
setHoverRect({
|
|
@@ -2055,14 +2563,14 @@ var useMeasurerPointer = ({
|
|
|
2055
2563
|
setHoverElement(null);
|
|
2056
2564
|
}
|
|
2057
2565
|
},
|
|
2058
|
-
[overlayRef, setHoverElement, setHoverRect]
|
|
2566
|
+
[document2, overlayRef, setHoverElement, setHoverRect]
|
|
2059
2567
|
);
|
|
2060
2568
|
const updateHoverElement = useCallback5(
|
|
2061
2569
|
(point) => {
|
|
2062
|
-
const target = getTargetElement(point, overlayRef.current);
|
|
2570
|
+
const target = getTargetElement(point, overlayRef.current, document2);
|
|
2063
2571
|
setHoverElement(target);
|
|
2064
2572
|
},
|
|
2065
|
-
[overlayRef, setHoverElement]
|
|
2573
|
+
[document2, overlayRef, setHoverElement]
|
|
2066
2574
|
);
|
|
2067
2575
|
const handlePointerDown = useCallback5(
|
|
2068
2576
|
(event) => {
|
|
@@ -2077,7 +2585,8 @@ var useMeasurerPointer = ({
|
|
|
2077
2585
|
shiftToggleElementRef.current = event.shiftKey ? getSelectedMeasurementHit({
|
|
2078
2586
|
point,
|
|
2079
2587
|
selectedMeasurements,
|
|
2080
|
-
overlayNode: overlayRef.current
|
|
2588
|
+
overlayNode: overlayRef.current,
|
|
2589
|
+
document: document2
|
|
2081
2590
|
})?.elementRef ?? null : null;
|
|
2082
2591
|
selectionCacheRef.current.key = "";
|
|
2083
2592
|
if (altPressed && optionPairOverlay) {
|
|
@@ -2099,10 +2608,11 @@ var useMeasurerPointer = ({
|
|
|
2099
2608
|
snapGuidesEnabled,
|
|
2100
2609
|
overlayNode: overlayRef.current,
|
|
2101
2610
|
guides,
|
|
2102
|
-
draggingGuideId
|
|
2611
|
+
draggingGuideId,
|
|
2612
|
+
document: document2
|
|
2103
2613
|
});
|
|
2104
2614
|
const id = createId();
|
|
2105
|
-
setSelectedGuideIds([]);
|
|
2615
|
+
setSelectedGuideIds([id]);
|
|
2106
2616
|
setGuides((prev) => [
|
|
2107
2617
|
...prev,
|
|
2108
2618
|
{ id, orientation: guideOrientation, position }
|
|
@@ -2125,6 +2635,7 @@ var useMeasurerPointer = ({
|
|
|
2125
2635
|
clearSelectionRect,
|
|
2126
2636
|
createActionCommit,
|
|
2127
2637
|
draggingGuideId,
|
|
2638
|
+
document2,
|
|
2128
2639
|
enabled,
|
|
2129
2640
|
guideOrientation,
|
|
2130
2641
|
guides,
|
|
@@ -2166,31 +2677,32 @@ var useMeasurerPointer = ({
|
|
|
2166
2677
|
}
|
|
2167
2678
|
hoverPointRef.current = point;
|
|
2168
2679
|
if (!hoverFrameRef.current) {
|
|
2169
|
-
hoverFrameRef.current = requestAnimationFrame(() => {
|
|
2680
|
+
hoverFrameRef.current = window2.requestAnimationFrame(() => {
|
|
2170
2681
|
const latest = hoverPointRef.current;
|
|
2171
|
-
if (latest && !
|
|
2682
|
+
if (latest && !draggingGuideId) {
|
|
2172
2683
|
if (hoverHighlightEnabled) {
|
|
2173
2684
|
updateHoverTarget(latest);
|
|
2174
2685
|
} else {
|
|
2175
2686
|
updateHoverElement(latest);
|
|
2176
2687
|
}
|
|
2177
2688
|
}
|
|
2178
|
-
if (latest &&
|
|
2689
|
+
if (latest && guides.length > 0) {
|
|
2179
2690
|
setHoverPointer(latest);
|
|
2180
2691
|
} else {
|
|
2181
2692
|
setHoverPointer(null);
|
|
2182
2693
|
}
|
|
2183
|
-
if (
|
|
2694
|
+
if (guidesEnabled && latest && !draggingGuideId) {
|
|
2184
2695
|
const position = getSnapGuidePosition({
|
|
2185
|
-
orientation:
|
|
2696
|
+
orientation: guideOrientation,
|
|
2186
2697
|
point: latest,
|
|
2187
|
-
snapGuidesEnabled
|
|
2698
|
+
snapGuidesEnabled,
|
|
2188
2699
|
overlayNode: overlayRef.current,
|
|
2189
|
-
guides
|
|
2190
|
-
draggingGuideId
|
|
2700
|
+
guides,
|
|
2701
|
+
draggingGuideId,
|
|
2702
|
+
document: document2
|
|
2191
2703
|
});
|
|
2192
2704
|
setGuidePreview({
|
|
2193
|
-
orientation:
|
|
2705
|
+
orientation: guideOrientation,
|
|
2194
2706
|
position
|
|
2195
2707
|
});
|
|
2196
2708
|
} else {
|
|
@@ -2207,10 +2719,11 @@ var useMeasurerPointer = ({
|
|
|
2207
2719
|
position: getSnapGuidePosition({
|
|
2208
2720
|
orientation: guide.orientation,
|
|
2209
2721
|
point,
|
|
2210
|
-
snapGuidesEnabled
|
|
2722
|
+
snapGuidesEnabled,
|
|
2211
2723
|
overlayNode: overlayRef.current,
|
|
2212
|
-
guides
|
|
2213
|
-
draggingGuideId
|
|
2724
|
+
guides,
|
|
2725
|
+
draggingGuideId,
|
|
2726
|
+
document: document2
|
|
2214
2727
|
})
|
|
2215
2728
|
} : guide
|
|
2216
2729
|
)
|
|
@@ -2232,8 +2745,11 @@ var useMeasurerPointer = ({
|
|
|
2232
2745
|
draggingGuideId,
|
|
2233
2746
|
enabled,
|
|
2234
2747
|
hoverHighlightEnabled,
|
|
2748
|
+
guides,
|
|
2749
|
+
guidesEnabled,
|
|
2235
2750
|
isDragging,
|
|
2236
2751
|
overlayRef,
|
|
2752
|
+
guideOrientation,
|
|
2237
2753
|
setAltPressed,
|
|
2238
2754
|
setEnd,
|
|
2239
2755
|
setGuidePreview,
|
|
@@ -2242,6 +2758,7 @@ var useMeasurerPointer = ({
|
|
|
2242
2758
|
setHoverPointer,
|
|
2243
2759
|
setHoverRect,
|
|
2244
2760
|
setIsDragging,
|
|
2761
|
+
snapGuidesEnabled,
|
|
2245
2762
|
start,
|
|
2246
2763
|
toolMode,
|
|
2247
2764
|
toolbarRef,
|
|
@@ -2295,7 +2812,8 @@ var useMeasurerPointer = ({
|
|
|
2295
2812
|
const elements = getElementsInRectCached(
|
|
2296
2813
|
selectionRect,
|
|
2297
2814
|
overlayRef.current,
|
|
2298
|
-
selectionCacheRef.current
|
|
2815
|
+
selectionCacheRef.current,
|
|
2816
|
+
document2
|
|
2299
2817
|
);
|
|
2300
2818
|
const hasSameSelection = elements.length === selectedMeasurements.length && elements.every(
|
|
2301
2819
|
(element, index) => selectedMeasurements[index]?.elementRef === element
|
|
@@ -2306,7 +2824,7 @@ var useMeasurerPointer = ({
|
|
|
2306
2824
|
if (!hasSameSelection) {
|
|
2307
2825
|
commit();
|
|
2308
2826
|
const nextMeasurements = elements.map((element) => ({
|
|
2309
|
-
...getInspectMeasurement(element),
|
|
2827
|
+
...getInspectMeasurement(element, window2),
|
|
2310
2828
|
originRect: selectionRect
|
|
2311
2829
|
}));
|
|
2312
2830
|
setSelectedMeasurements(nextMeasurements);
|
|
@@ -2340,7 +2858,8 @@ var useMeasurerPointer = ({
|
|
|
2340
2858
|
) ?? null : getSelectedMeasurementHit({
|
|
2341
2859
|
point,
|
|
2342
2860
|
selectedMeasurements,
|
|
2343
|
-
overlayNode: overlayRef.current
|
|
2861
|
+
overlayNode: overlayRef.current,
|
|
2862
|
+
document: document2
|
|
2344
2863
|
});
|
|
2345
2864
|
if (event.shiftKey && selectedHit) {
|
|
2346
2865
|
commit();
|
|
@@ -2370,9 +2889,9 @@ var useMeasurerPointer = ({
|
|
|
2370
2889
|
resetDragState();
|
|
2371
2890
|
return;
|
|
2372
2891
|
}
|
|
2373
|
-
const target = event.shiftKey ? getTargetElement(point, overlayRef.current) ?? getSnappedClickTarget(point, overlayRef.current, snapEnabled) : getSnappedClickTarget(point, overlayRef.current, snapEnabled);
|
|
2892
|
+
const target = event.shiftKey ? getTargetElement(point, overlayRef.current, document2) ?? getSnappedClickTarget(point, overlayRef.current, snapEnabled, document2) : getSnappedClickTarget(point, overlayRef.current, snapEnabled, document2);
|
|
2374
2893
|
if (target) {
|
|
2375
|
-
const inspectMeasurement = getInspectMeasurement(target);
|
|
2894
|
+
const inspectMeasurement = getInspectMeasurement(target, window2);
|
|
2376
2895
|
clearTransientMeasurements();
|
|
2377
2896
|
if (event.shiftKey) {
|
|
2378
2897
|
const alreadySelected = selectedMeasurements.some(
|
|
@@ -2471,41 +2990,48 @@ var useMeasurerPointer = ({
|
|
|
2471
2990
|
};
|
|
2472
2991
|
|
|
2473
2992
|
// hooks/use-overlay-refs.ts
|
|
2474
|
-
import { useRef as
|
|
2993
|
+
import { useRef as useRef7 } from "react";
|
|
2475
2994
|
var useOverlayRefs = () => {
|
|
2476
|
-
const overlayRef =
|
|
2477
|
-
const selectedElementRef =
|
|
2478
|
-
const hoverElementRef =
|
|
2995
|
+
const overlayRef = useRef7(null);
|
|
2996
|
+
const selectedElementRef = useRef7(null);
|
|
2997
|
+
const hoverElementRef = useRef7(null);
|
|
2479
2998
|
return { overlayRef, selectedElementRef, hoverElementRef };
|
|
2480
2999
|
};
|
|
2481
3000
|
|
|
2482
3001
|
// hooks/use-resize-sync.ts
|
|
2483
|
-
import { useEffect as
|
|
3002
|
+
import { useEffect as useEffect4, useRef as useRef8 } from "react";
|
|
2484
3003
|
var useResizeSync = (params) => {
|
|
2485
|
-
const resizeFrameRef =
|
|
2486
|
-
const viewportRef =
|
|
2487
|
-
|
|
3004
|
+
const resizeFrameRef = useRef8(null);
|
|
3005
|
+
const viewportRef = useRef8(getViewportSize(params.window));
|
|
3006
|
+
useEffect4(() => {
|
|
2488
3007
|
const handleResize = () => {
|
|
2489
3008
|
if (resizeFrameRef.current) {
|
|
2490
|
-
cancelAnimationFrame(resizeFrameRef.current);
|
|
3009
|
+
params.window.cancelAnimationFrame(resizeFrameRef.current);
|
|
2491
3010
|
}
|
|
2492
|
-
resizeFrameRef.current = requestAnimationFrame(() => {
|
|
2493
|
-
const viewport = getViewportSize();
|
|
3011
|
+
resizeFrameRef.current = params.window.requestAnimationFrame(() => {
|
|
3012
|
+
const viewport = getViewportSize(params.window);
|
|
2494
3013
|
const previousViewport = viewportRef.current;
|
|
2495
3014
|
params.setMeasurements(
|
|
2496
3015
|
(prev) => prev.map(
|
|
2497
|
-
(measurement) => updateMeasurementForResize(measurement, viewport)
|
|
3016
|
+
(measurement) => updateMeasurementForResize(measurement, viewport, params.document)
|
|
2498
3017
|
)
|
|
2499
3018
|
);
|
|
2500
3019
|
params.setActiveMeasurement(
|
|
2501
|
-
(prev) => prev ? updateMeasurementForResize(prev, viewport) : prev
|
|
3020
|
+
(prev) => prev ? updateMeasurementForResize(prev, viewport, params.document) : prev
|
|
2502
3021
|
);
|
|
2503
3022
|
params.setHeldDistances(
|
|
2504
|
-
(prev) => prev.map(
|
|
3023
|
+
(prev) => prev.map(
|
|
3024
|
+
(distance) => updateDistanceForResize(
|
|
3025
|
+
distance,
|
|
3026
|
+
viewport,
|
|
3027
|
+
params.document,
|
|
3028
|
+
params.window
|
|
3029
|
+
)
|
|
3030
|
+
)
|
|
2505
3031
|
);
|
|
2506
|
-
if (params.selectedElementRef.current) {
|
|
3032
|
+
if (params.selectedElementRef.current && params.document.contains(params.selectedElementRef.current)) {
|
|
2507
3033
|
params.setSelectedMeasurement(
|
|
2508
|
-
getInspectMeasurement(params.selectedElementRef.current)
|
|
3034
|
+
getInspectMeasurement(params.selectedElementRef.current, params.window)
|
|
2509
3035
|
);
|
|
2510
3036
|
}
|
|
2511
3037
|
if (previousViewport.width > 0 && previousViewport.height > 0) {
|
|
@@ -2520,27 +3046,27 @@ var useResizeSync = (params) => {
|
|
|
2520
3046
|
viewportRef.current = viewport;
|
|
2521
3047
|
});
|
|
2522
3048
|
};
|
|
2523
|
-
window.addEventListener("resize", handleResize);
|
|
3049
|
+
params.window.addEventListener("resize", handleResize);
|
|
2524
3050
|
return () => {
|
|
2525
3051
|
if (resizeFrameRef.current) {
|
|
2526
|
-
cancelAnimationFrame(resizeFrameRef.current);
|
|
3052
|
+
params.window.cancelAnimationFrame(resizeFrameRef.current);
|
|
2527
3053
|
}
|
|
2528
|
-
window.removeEventListener("resize", handleResize);
|
|
3054
|
+
params.window.removeEventListener("resize", handleResize);
|
|
2529
3055
|
};
|
|
2530
3056
|
}, [params]);
|
|
2531
3057
|
};
|
|
2532
3058
|
|
|
2533
3059
|
// render/measurer-overlay.tsx
|
|
2534
|
-
import { memo as
|
|
3060
|
+
import { memo as memo6 } from "react";
|
|
2535
3061
|
|
|
2536
3062
|
// components/measure-tag.tsx
|
|
2537
|
-
import { jsx as
|
|
3063
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
2538
3064
|
function MeasureTag({
|
|
2539
3065
|
children,
|
|
2540
3066
|
className = "",
|
|
2541
3067
|
style
|
|
2542
3068
|
}) {
|
|
2543
|
-
return /* @__PURE__ */
|
|
3069
|
+
return /* @__PURE__ */ jsx4(
|
|
2544
3070
|
"div",
|
|
2545
3071
|
{
|
|
2546
3072
|
className: cn(
|
|
@@ -2554,31 +3080,21 @@ function MeasureTag({
|
|
|
2554
3080
|
}
|
|
2555
3081
|
|
|
2556
3082
|
// components/measurement-box.tsx
|
|
2557
|
-
import { memo as
|
|
2558
|
-
import { jsx as
|
|
3083
|
+
import { memo as memo3 } from "react";
|
|
3084
|
+
import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
2559
3085
|
var formatValue2 = (value) => Math.round(value);
|
|
2560
|
-
var MeasurementBox =
|
|
3086
|
+
var MeasurementBox = memo3(function MeasurementBox2({
|
|
2561
3087
|
measurement,
|
|
2562
3088
|
transitionMs,
|
|
2563
3089
|
labelOffset,
|
|
2564
3090
|
edgeVisibility
|
|
2565
3091
|
}) {
|
|
2566
|
-
const [rect, setRect] = useState7(
|
|
2567
|
-
measurement.originRect ?? measurement.rect
|
|
2568
|
-
);
|
|
2569
|
-
useEffect7(() => {
|
|
2570
|
-
if (!measurement.originRect) return;
|
|
2571
|
-
const frame = requestAnimationFrame(() => {
|
|
2572
|
-
setRect(measurement.rect);
|
|
2573
|
-
});
|
|
2574
|
-
return () => cancelAnimationFrame(frame);
|
|
2575
|
-
}, [measurement]);
|
|
2576
3092
|
const edges = edgeVisibility ?? { top: true, right: true, bottom: true, left: true };
|
|
2577
|
-
const displayRect = measurement.
|
|
3093
|
+
const displayRect = measurement.rect;
|
|
2578
3094
|
const outlineColor = "color-mix(in oklch, oklch(0.62 0.18 255) 80%, transparent)";
|
|
2579
3095
|
const fillColor = "color-mix(in oklch, oklch(0.62 0.18 255) 8%, transparent)";
|
|
2580
|
-
return /* @__PURE__ */
|
|
2581
|
-
/* @__PURE__ */
|
|
3096
|
+
return /* @__PURE__ */ jsxs3("div", { className: "msr:pointer-events-none", children: [
|
|
3097
|
+
/* @__PURE__ */ jsxs3(
|
|
2582
3098
|
"div",
|
|
2583
3099
|
{
|
|
2584
3100
|
className: "msr:absolute",
|
|
@@ -2588,31 +3104,31 @@ var MeasurementBox = memo2(function MeasurementBox2({
|
|
|
2588
3104
|
width: displayRect.width,
|
|
2589
3105
|
height: displayRect.height,
|
|
2590
3106
|
backgroundColor: fillColor,
|
|
2591
|
-
transition:
|
|
3107
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease, width ${transitionMs}ms ease, height ${transitionMs}ms ease`
|
|
2592
3108
|
},
|
|
2593
3109
|
children: [
|
|
2594
|
-
edges.top ? /* @__PURE__ */
|
|
3110
|
+
edges.top ? /* @__PURE__ */ jsx5(
|
|
2595
3111
|
"div",
|
|
2596
3112
|
{
|
|
2597
3113
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2598
3114
|
style: { backgroundColor: outlineColor }
|
|
2599
3115
|
}
|
|
2600
3116
|
) : null,
|
|
2601
|
-
edges.right ? /* @__PURE__ */
|
|
3117
|
+
edges.right ? /* @__PURE__ */ jsx5(
|
|
2602
3118
|
"div",
|
|
2603
3119
|
{
|
|
2604
3120
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2605
3121
|
style: { backgroundColor: outlineColor }
|
|
2606
3122
|
}
|
|
2607
3123
|
) : null,
|
|
2608
|
-
edges.bottom ? /* @__PURE__ */
|
|
3124
|
+
edges.bottom ? /* @__PURE__ */ jsx5(
|
|
2609
3125
|
"div",
|
|
2610
3126
|
{
|
|
2611
3127
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
2612
3128
|
style: { backgroundColor: outlineColor }
|
|
2613
3129
|
}
|
|
2614
3130
|
) : null,
|
|
2615
|
-
edges.left ? /* @__PURE__ */
|
|
3131
|
+
edges.left ? /* @__PURE__ */ jsx5(
|
|
2616
3132
|
"div",
|
|
2617
3133
|
{
|
|
2618
3134
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -2622,14 +3138,14 @@ var MeasurementBox = memo2(function MeasurementBox2({
|
|
|
2622
3138
|
]
|
|
2623
3139
|
}
|
|
2624
3140
|
),
|
|
2625
|
-
/* @__PURE__ */
|
|
3141
|
+
/* @__PURE__ */ jsxs3(
|
|
2626
3142
|
MeasureTag,
|
|
2627
3143
|
{
|
|
2628
3144
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
2629
3145
|
style: {
|
|
2630
3146
|
left: displayRect.left + displayRect.width / 2,
|
|
2631
3147
|
top: displayRect.top + displayRect.height + labelOffset,
|
|
2632
|
-
transition:
|
|
3148
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease`
|
|
2633
3149
|
},
|
|
2634
3150
|
children: [
|
|
2635
3151
|
formatValue2(displayRect.width),
|
|
@@ -2642,31 +3158,21 @@ var MeasurementBox = memo2(function MeasurementBox2({
|
|
|
2642
3158
|
});
|
|
2643
3159
|
|
|
2644
3160
|
// components/selected-measurement-box.tsx
|
|
2645
|
-
import { memo as
|
|
2646
|
-
import { jsx as
|
|
3161
|
+
import { memo as memo4 } from "react";
|
|
3162
|
+
import { jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
2647
3163
|
var formatValue3 = (value) => Math.round(value);
|
|
2648
|
-
var SelectedMeasurementBox =
|
|
3164
|
+
var SelectedMeasurementBox = memo4(function SelectedMeasurementBox2({
|
|
2649
3165
|
measurement,
|
|
2650
3166
|
transitionMs,
|
|
2651
3167
|
labelOffset,
|
|
2652
3168
|
edgeVisibility
|
|
2653
3169
|
}) {
|
|
2654
|
-
const [rect, setRect] = useState8(
|
|
2655
|
-
measurement.originRect ?? measurement.rect
|
|
2656
|
-
);
|
|
2657
|
-
useEffect8(() => {
|
|
2658
|
-
if (!measurement.originRect) return;
|
|
2659
|
-
const frame = requestAnimationFrame(() => {
|
|
2660
|
-
setRect(measurement.rect);
|
|
2661
|
-
});
|
|
2662
|
-
return () => cancelAnimationFrame(frame);
|
|
2663
|
-
}, [measurement]);
|
|
2664
3170
|
const edges = edgeVisibility ?? { top: true, right: true, bottom: true, left: true };
|
|
2665
|
-
const displayRect = measurement.
|
|
3171
|
+
const displayRect = measurement.rect;
|
|
2666
3172
|
const outlineColor = "color-mix(in oklch, oklch(0.62 0.18 255) 80%, transparent)";
|
|
2667
3173
|
const fillColor = "color-mix(in oklch, oklch(0.62 0.18 255) 8%, transparent)";
|
|
2668
|
-
return /* @__PURE__ */
|
|
2669
|
-
/* @__PURE__ */
|
|
3174
|
+
return /* @__PURE__ */ jsxs4("div", { className: "msr:pointer-events-none", children: [
|
|
3175
|
+
/* @__PURE__ */ jsxs4(
|
|
2670
3176
|
"div",
|
|
2671
3177
|
{
|
|
2672
3178
|
className: "msr:absolute",
|
|
@@ -2676,31 +3182,31 @@ var SelectedMeasurementBox = memo3(function SelectedMeasurementBox2({
|
|
|
2676
3182
|
width: displayRect.width,
|
|
2677
3183
|
height: displayRect.height,
|
|
2678
3184
|
backgroundColor: fillColor,
|
|
2679
|
-
transition:
|
|
3185
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease, width ${transitionMs}ms ease, height ${transitionMs}ms ease`
|
|
2680
3186
|
},
|
|
2681
3187
|
children: [
|
|
2682
|
-
edges.top ? /* @__PURE__ */
|
|
3188
|
+
edges.top ? /* @__PURE__ */ jsx6(
|
|
2683
3189
|
"div",
|
|
2684
3190
|
{
|
|
2685
3191
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2686
3192
|
style: { backgroundColor: outlineColor }
|
|
2687
3193
|
}
|
|
2688
3194
|
) : null,
|
|
2689
|
-
edges.right ? /* @__PURE__ */
|
|
3195
|
+
edges.right ? /* @__PURE__ */ jsx6(
|
|
2690
3196
|
"div",
|
|
2691
3197
|
{
|
|
2692
3198
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2693
3199
|
style: { backgroundColor: outlineColor }
|
|
2694
3200
|
}
|
|
2695
3201
|
) : null,
|
|
2696
|
-
edges.bottom ? /* @__PURE__ */
|
|
3202
|
+
edges.bottom ? /* @__PURE__ */ jsx6(
|
|
2697
3203
|
"div",
|
|
2698
3204
|
{
|
|
2699
3205
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
2700
3206
|
style: { backgroundColor: outlineColor }
|
|
2701
3207
|
}
|
|
2702
3208
|
) : null,
|
|
2703
|
-
edges.left ? /* @__PURE__ */
|
|
3209
|
+
edges.left ? /* @__PURE__ */ jsx6(
|
|
2704
3210
|
"div",
|
|
2705
3211
|
{
|
|
2706
3212
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -2710,14 +3216,14 @@ var SelectedMeasurementBox = memo3(function SelectedMeasurementBox2({
|
|
|
2710
3216
|
]
|
|
2711
3217
|
}
|
|
2712
3218
|
),
|
|
2713
|
-
/* @__PURE__ */
|
|
3219
|
+
/* @__PURE__ */ jsxs4(
|
|
2714
3220
|
MeasureTag,
|
|
2715
3221
|
{
|
|
2716
3222
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
2717
3223
|
style: {
|
|
2718
3224
|
left: displayRect.left + displayRect.width / 2,
|
|
2719
3225
|
top: displayRect.top + displayRect.height + labelOffset,
|
|
2720
|
-
transition:
|
|
3226
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease`
|
|
2721
3227
|
},
|
|
2722
3228
|
children: [
|
|
2723
3229
|
formatValue3(displayRect.width),
|
|
@@ -2730,14 +3236,14 @@ var SelectedMeasurementBox = memo3(function SelectedMeasurementBox2({
|
|
|
2730
3236
|
});
|
|
2731
3237
|
|
|
2732
3238
|
// render/distance-overlay-item.tsx
|
|
2733
|
-
import { memo as
|
|
2734
|
-
import { Fragment, jsx as
|
|
2735
|
-
var DistanceOverlayItem =
|
|
3239
|
+
import { memo as memo5 } from "react";
|
|
3240
|
+
import { Fragment, jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
3241
|
+
var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
2736
3242
|
distance,
|
|
2737
3243
|
labelOffset,
|
|
2738
3244
|
onRemove
|
|
2739
3245
|
}) {
|
|
2740
|
-
return /* @__PURE__ */
|
|
3246
|
+
return /* @__PURE__ */ jsxs5(
|
|
2741
3247
|
"div",
|
|
2742
3248
|
{
|
|
2743
3249
|
className: onRemove ? "msr:pointer-events-auto" : "msr:pointer-events-none",
|
|
@@ -2746,7 +3252,7 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2746
3252
|
onRemove(distance.id);
|
|
2747
3253
|
} : void 0,
|
|
2748
3254
|
children: [
|
|
2749
|
-
/* @__PURE__ */
|
|
3255
|
+
/* @__PURE__ */ jsx7(
|
|
2750
3256
|
"div",
|
|
2751
3257
|
{
|
|
2752
3258
|
className: "msr:absolute msr:rounded msr:border msr:border-[#2563eb]/70",
|
|
@@ -2758,7 +3264,7 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2758
3264
|
}
|
|
2759
3265
|
}
|
|
2760
3266
|
),
|
|
2761
|
-
/* @__PURE__ */
|
|
3267
|
+
/* @__PURE__ */ jsx7(
|
|
2762
3268
|
"div",
|
|
2763
3269
|
{
|
|
2764
3270
|
className: "msr:absolute msr:rounded msr:border msr:border-[#2563eb]/70",
|
|
@@ -2771,7 +3277,7 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2771
3277
|
}
|
|
2772
3278
|
),
|
|
2773
3279
|
distance.connectors.map(
|
|
2774
|
-
(connector, index) => Math.abs(connector.x1 - connector.x2) < 1 ? /* @__PURE__ */
|
|
3280
|
+
(connector, index) => Math.abs(connector.x1 - connector.x2) < 1 ? /* @__PURE__ */ jsx7(
|
|
2775
3281
|
"div",
|
|
2776
3282
|
{
|
|
2777
3283
|
className: "msr:absolute msr:border-l msr:border-dashed msr:border-[#2563eb]/70",
|
|
@@ -2782,7 +3288,7 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2782
3288
|
}
|
|
2783
3289
|
},
|
|
2784
3290
|
`${distance.id}-connector-${index}`
|
|
2785
|
-
) : /* @__PURE__ */
|
|
3291
|
+
) : /* @__PURE__ */ jsx7(
|
|
2786
3292
|
"div",
|
|
2787
3293
|
{
|
|
2788
3294
|
className: "msr:absolute msr:border-t msr:border-dashed msr:border-[#2563eb]/70",
|
|
@@ -2795,8 +3301,8 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2795
3301
|
`${distance.id}-connector-${index}`
|
|
2796
3302
|
)
|
|
2797
3303
|
),
|
|
2798
|
-
distance.horizontal && distance.horizontal.value > 0 ? /* @__PURE__ */
|
|
2799
|
-
/* @__PURE__ */
|
|
3304
|
+
distance.horizontal && distance.horizontal.value > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
3305
|
+
/* @__PURE__ */ jsx7(
|
|
2800
3306
|
"div",
|
|
2801
3307
|
{
|
|
2802
3308
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -2807,7 +3313,7 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2807
3313
|
}
|
|
2808
3314
|
}
|
|
2809
3315
|
),
|
|
2810
|
-
/* @__PURE__ */
|
|
3316
|
+
/* @__PURE__ */ jsx7(
|
|
2811
3317
|
MeasureTag,
|
|
2812
3318
|
{
|
|
2813
3319
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -2819,8 +3325,8 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2819
3325
|
}
|
|
2820
3326
|
)
|
|
2821
3327
|
] }) : null,
|
|
2822
|
-
distance.vertical && distance.vertical.value > 0 ? /* @__PURE__ */
|
|
2823
|
-
/* @__PURE__ */
|
|
3328
|
+
distance.vertical && distance.vertical.value > 0 ? /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
3329
|
+
/* @__PURE__ */ jsx7(
|
|
2824
3330
|
"div",
|
|
2825
3331
|
{
|
|
2826
3332
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -2831,7 +3337,7 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2831
3337
|
}
|
|
2832
3338
|
}
|
|
2833
3339
|
),
|
|
2834
|
-
/* @__PURE__ */
|
|
3340
|
+
/* @__PURE__ */ jsx7(
|
|
2835
3341
|
MeasureTag,
|
|
2836
3342
|
{
|
|
2837
3343
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -2849,10 +3355,11 @@ var DistanceOverlayItem = memo4(function DistanceOverlayItem2({
|
|
|
2849
3355
|
});
|
|
2850
3356
|
|
|
2851
3357
|
// render/measurer-overlay.tsx
|
|
2852
|
-
import { Fragment as Fragment2, jsx as
|
|
2853
|
-
var MeasurerOverlay =
|
|
3358
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
3359
|
+
var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
2854
3360
|
enabled,
|
|
2855
3361
|
toolMode,
|
|
3362
|
+
guidePointerEvents,
|
|
2856
3363
|
guidesEnabled,
|
|
2857
3364
|
altPressed,
|
|
2858
3365
|
isDragging,
|
|
@@ -2889,16 +3396,20 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
2889
3396
|
onGuidePointerUp,
|
|
2890
3397
|
onGuidePointerCancel
|
|
2891
3398
|
}) {
|
|
2892
|
-
|
|
3399
|
+
const overlayVisible = enabled;
|
|
3400
|
+
const overlayInteractive = overlayVisible && toolMode !== "none" && toolMode !== "text-inspector" && toolMode !== "xray" && toolMode !== "rulers";
|
|
3401
|
+
const selectionVisible = toolMode === "select";
|
|
3402
|
+
return /* @__PURE__ */ jsxs6(
|
|
2893
3403
|
"div",
|
|
2894
3404
|
{
|
|
2895
|
-
className: `msr:absolute msr:inset-0 ${
|
|
3405
|
+
className: `msr:absolute msr:inset-0 ${overlayVisible ? `msr:pointer-events-auto ${guidesEnabled ? hoverGuide || draggingGuideId ? "msr:cursor-default" : "msr:cursor-crosshair" : "msr:cursor-default"} msr:opacity-100` : "msr:pointer-events-none msr:opacity-0"}`,
|
|
3406
|
+
style: { pointerEvents: overlayInteractive ? "auto" : "none" },
|
|
2896
3407
|
onPointerDown,
|
|
2897
3408
|
onPointerMove,
|
|
2898
3409
|
onPointerUp,
|
|
2899
3410
|
onPointerLeave,
|
|
2900
3411
|
children: [
|
|
2901
|
-
|
|
3412
|
+
selectionVisible ? displayedMeasurements.map((measurement, index) => /* @__PURE__ */ jsx8(
|
|
2902
3413
|
MeasurementBox,
|
|
2903
3414
|
{
|
|
2904
3415
|
measurement,
|
|
@@ -2908,8 +3419,8 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
2908
3419
|
},
|
|
2909
3420
|
measurement.id
|
|
2910
3421
|
)) : null,
|
|
2911
|
-
|
|
2912
|
-
/* @__PURE__ */
|
|
3422
|
+
selectionVisible && activeRect && isDragging ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3423
|
+
/* @__PURE__ */ jsxs6(
|
|
2913
3424
|
"div",
|
|
2914
3425
|
{
|
|
2915
3426
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -2921,28 +3432,28 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
2921
3432
|
backgroundColor: fillColor
|
|
2922
3433
|
},
|
|
2923
3434
|
children: [
|
|
2924
|
-
/* @__PURE__ */
|
|
3435
|
+
/* @__PURE__ */ jsx8(
|
|
2925
3436
|
"div",
|
|
2926
3437
|
{
|
|
2927
3438
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2928
3439
|
style: { backgroundColor: outlineColor }
|
|
2929
3440
|
}
|
|
2930
3441
|
),
|
|
2931
|
-
/* @__PURE__ */
|
|
3442
|
+
/* @__PURE__ */ jsx8(
|
|
2932
3443
|
"div",
|
|
2933
3444
|
{
|
|
2934
3445
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2935
3446
|
style: { backgroundColor: outlineColor }
|
|
2936
3447
|
}
|
|
2937
3448
|
),
|
|
2938
|
-
/* @__PURE__ */
|
|
3449
|
+
/* @__PURE__ */ jsx8(
|
|
2939
3450
|
"div",
|
|
2940
3451
|
{
|
|
2941
3452
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
2942
3453
|
style: { backgroundColor: outlineColor }
|
|
2943
3454
|
}
|
|
2944
3455
|
),
|
|
2945
|
-
/* @__PURE__ */
|
|
3456
|
+
/* @__PURE__ */ jsx8(
|
|
2946
3457
|
"div",
|
|
2947
3458
|
{
|
|
2948
3459
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -2952,7 +3463,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
2952
3463
|
]
|
|
2953
3464
|
}
|
|
2954
3465
|
),
|
|
2955
|
-
/* @__PURE__ */
|
|
3466
|
+
/* @__PURE__ */ jsxs6(
|
|
2956
3467
|
MeasureTag,
|
|
2957
3468
|
{
|
|
2958
3469
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -2968,7 +3479,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
2968
3479
|
}
|
|
2969
3480
|
)
|
|
2970
3481
|
] }) : null,
|
|
2971
|
-
|
|
3482
|
+
selectionVisible && hoverRectToShow ? /* @__PURE__ */ jsxs6(
|
|
2972
3483
|
"div",
|
|
2973
3484
|
{
|
|
2974
3485
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -2980,28 +3491,28 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
2980
3491
|
backgroundColor: fillColor
|
|
2981
3492
|
},
|
|
2982
3493
|
children: [
|
|
2983
|
-
hoverEdgeVisibility?.top ? /* @__PURE__ */
|
|
3494
|
+
hoverEdgeVisibility?.top ? /* @__PURE__ */ jsx8(
|
|
2984
3495
|
"div",
|
|
2985
3496
|
{
|
|
2986
3497
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2987
3498
|
style: { backgroundColor: outlineColor }
|
|
2988
3499
|
}
|
|
2989
3500
|
) : null,
|
|
2990
|
-
hoverEdgeVisibility?.right ? /* @__PURE__ */
|
|
3501
|
+
hoverEdgeVisibility?.right ? /* @__PURE__ */ jsx8(
|
|
2991
3502
|
"div",
|
|
2992
3503
|
{
|
|
2993
3504
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2994
3505
|
style: { backgroundColor: outlineColor }
|
|
2995
3506
|
}
|
|
2996
3507
|
) : null,
|
|
2997
|
-
hoverEdgeVisibility?.bottom ? /* @__PURE__ */
|
|
3508
|
+
hoverEdgeVisibility?.bottom ? /* @__PURE__ */ jsx8(
|
|
2998
3509
|
"div",
|
|
2999
3510
|
{
|
|
3000
3511
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
3001
3512
|
style: { backgroundColor: outlineColor }
|
|
3002
3513
|
}
|
|
3003
3514
|
) : null,
|
|
3004
|
-
hoverEdgeVisibility?.left ? /* @__PURE__ */
|
|
3515
|
+
hoverEdgeVisibility?.left ? /* @__PURE__ */ jsx8(
|
|
3005
3516
|
"div",
|
|
3006
3517
|
{
|
|
3007
3518
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -3011,7 +3522,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3011
3522
|
]
|
|
3012
3523
|
}
|
|
3013
3524
|
) : null,
|
|
3014
|
-
guidesEnabled && guidePreview ? /* @__PURE__ */
|
|
3525
|
+
guidesEnabled && guidePreview ? /* @__PURE__ */ jsx8(
|
|
3015
3526
|
"div",
|
|
3016
3527
|
{
|
|
3017
3528
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -3026,7 +3537,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3026
3537
|
height: GUIDE_HITBOX_SIZE,
|
|
3027
3538
|
width: "100%"
|
|
3028
3539
|
},
|
|
3029
|
-
children: /* @__PURE__ */
|
|
3540
|
+
children: /* @__PURE__ */ jsx8(
|
|
3030
3541
|
"div",
|
|
3031
3542
|
{
|
|
3032
3543
|
className: "msr:absolute",
|
|
@@ -3047,7 +3558,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3047
3558
|
)
|
|
3048
3559
|
}
|
|
3049
3560
|
) : null,
|
|
3050
|
-
|
|
3561
|
+
selectionVisible ? displayedSelectedMeasurements.map((measurement, index) => /* @__PURE__ */ jsx8(
|
|
3051
3562
|
SelectedMeasurementBox,
|
|
3052
3563
|
{
|
|
3053
3564
|
measurement,
|
|
@@ -3057,7 +3568,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3057
3568
|
},
|
|
3058
3569
|
measurement.id
|
|
3059
3570
|
)) : null,
|
|
3060
|
-
heldDistances.map((distance) => /* @__PURE__ */
|
|
3571
|
+
heldDistances.map((distance) => /* @__PURE__ */ jsx8(
|
|
3061
3572
|
DistanceOverlayItem,
|
|
3062
3573
|
{
|
|
3063
3574
|
distance,
|
|
@@ -3066,7 +3577,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3066
3577
|
},
|
|
3067
3578
|
`held-${distance.id}`
|
|
3068
3579
|
)),
|
|
3069
|
-
|
|
3580
|
+
selectionVisible && altPressed && optionPairOverlay ? /* @__PURE__ */ jsx8(
|
|
3070
3581
|
DistanceOverlayItem,
|
|
3071
3582
|
{
|
|
3072
3583
|
distance: optionPairOverlay,
|
|
@@ -3074,7 +3585,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3074
3585
|
},
|
|
3075
3586
|
`option-${optionPairOverlay.id}`
|
|
3076
3587
|
) : null,
|
|
3077
|
-
guidesEnabled && altPressed && guideDistanceOverlay ? /* @__PURE__ */
|
|
3588
|
+
guidesEnabled && altPressed && guideDistanceOverlay ? /* @__PURE__ */ jsx8(
|
|
3078
3589
|
DistanceOverlayItem,
|
|
3079
3590
|
{
|
|
3080
3591
|
distance: guideDistanceOverlay,
|
|
@@ -3082,9 +3593,9 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3082
3593
|
},
|
|
3083
3594
|
`guide-preview-${guideDistanceOverlay.id}`
|
|
3084
3595
|
) : null,
|
|
3085
|
-
|
|
3086
|
-
optionContainerLines.top.value > 0 ? /* @__PURE__ */
|
|
3087
|
-
/* @__PURE__ */
|
|
3596
|
+
selectionVisible && altPressed && optionContainerLines ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3597
|
+
optionContainerLines.top.value > 0 ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3598
|
+
/* @__PURE__ */ jsx8(
|
|
3088
3599
|
"div",
|
|
3089
3600
|
{
|
|
3090
3601
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3095,7 +3606,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3095
3606
|
}
|
|
3096
3607
|
}
|
|
3097
3608
|
),
|
|
3098
|
-
/* @__PURE__ */
|
|
3609
|
+
/* @__PURE__ */ jsx8(
|
|
3099
3610
|
MeasureTag,
|
|
3100
3611
|
{
|
|
3101
3612
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3107,8 +3618,8 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3107
3618
|
}
|
|
3108
3619
|
)
|
|
3109
3620
|
] }) : null,
|
|
3110
|
-
optionContainerLines.bottom.value > 0 ? /* @__PURE__ */
|
|
3111
|
-
/* @__PURE__ */
|
|
3621
|
+
optionContainerLines.bottom.value > 0 ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3622
|
+
/* @__PURE__ */ jsx8(
|
|
3112
3623
|
"div",
|
|
3113
3624
|
{
|
|
3114
3625
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3119,7 +3630,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3119
3630
|
}
|
|
3120
3631
|
}
|
|
3121
3632
|
),
|
|
3122
|
-
/* @__PURE__ */
|
|
3633
|
+
/* @__PURE__ */ jsx8(
|
|
3123
3634
|
MeasureTag,
|
|
3124
3635
|
{
|
|
3125
3636
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3131,8 +3642,8 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3131
3642
|
}
|
|
3132
3643
|
)
|
|
3133
3644
|
] }) : null,
|
|
3134
|
-
optionContainerLines.left.value > 0 ? /* @__PURE__ */
|
|
3135
|
-
/* @__PURE__ */
|
|
3645
|
+
optionContainerLines.left.value > 0 ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3646
|
+
/* @__PURE__ */ jsx8(
|
|
3136
3647
|
"div",
|
|
3137
3648
|
{
|
|
3138
3649
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3143,7 +3654,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3143
3654
|
}
|
|
3144
3655
|
}
|
|
3145
3656
|
),
|
|
3146
|
-
/* @__PURE__ */
|
|
3657
|
+
/* @__PURE__ */ jsx8(
|
|
3147
3658
|
MeasureTag,
|
|
3148
3659
|
{
|
|
3149
3660
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3155,8 +3666,8 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3155
3666
|
}
|
|
3156
3667
|
)
|
|
3157
3668
|
] }) : null,
|
|
3158
|
-
optionContainerLines.right.value > 0 ? /* @__PURE__ */
|
|
3159
|
-
/* @__PURE__ */
|
|
3669
|
+
optionContainerLines.right.value > 0 ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
|
|
3670
|
+
/* @__PURE__ */ jsx8(
|
|
3160
3671
|
"div",
|
|
3161
3672
|
{
|
|
3162
3673
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3167,7 +3678,7 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3167
3678
|
}
|
|
3168
3679
|
}
|
|
3169
3680
|
),
|
|
3170
|
-
/* @__PURE__ */
|
|
3681
|
+
/* @__PURE__ */ jsx8(
|
|
3171
3682
|
MeasureTag,
|
|
3172
3683
|
{
|
|
3173
3684
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3185,25 +3696,28 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3185
3696
|
const isHovered = hoverGuide?.id === guide.id;
|
|
3186
3697
|
const strokeWidth = isSelected || isHovered ? 2 : 1;
|
|
3187
3698
|
const strokeColor = isSelected ? guideColorActive : isHovered ? guideColorHover : guideColorDefault;
|
|
3188
|
-
return /* @__PURE__ */
|
|
3699
|
+
return /* @__PURE__ */ jsx8(
|
|
3189
3700
|
"div",
|
|
3190
3701
|
{
|
|
3191
3702
|
className: "msr:absolute",
|
|
3703
|
+
"data-mesurer-guide": "true",
|
|
3192
3704
|
style: guide.orientation === "vertical" ? {
|
|
3193
3705
|
left: guide.position - GUIDE_HITBOX_SIZE / 2,
|
|
3194
3706
|
top: 0,
|
|
3195
3707
|
width: GUIDE_HITBOX_SIZE,
|
|
3196
|
-
height: "100%"
|
|
3708
|
+
height: "100%",
|
|
3709
|
+
pointerEvents: guidePointerEvents ? "auto" : "none"
|
|
3197
3710
|
} : {
|
|
3198
3711
|
top: guide.position - GUIDE_HITBOX_SIZE / 2,
|
|
3199
3712
|
left: 0,
|
|
3200
3713
|
height: GUIDE_HITBOX_SIZE,
|
|
3201
|
-
width: "100%"
|
|
3714
|
+
width: "100%",
|
|
3715
|
+
pointerEvents: guidePointerEvents ? "auto" : "none"
|
|
3202
3716
|
},
|
|
3203
3717
|
onPointerDown: (event) => onGuidePointerDown(guide, event),
|
|
3204
3718
|
onPointerUp: (event) => onGuidePointerUp(guide, event),
|
|
3205
3719
|
onPointerCancel: (event) => onGuidePointerCancel(guide, event),
|
|
3206
|
-
children: /* @__PURE__ */
|
|
3720
|
+
children: /* @__PURE__ */ jsx8(
|
|
3207
3721
|
"div",
|
|
3208
3722
|
{
|
|
3209
3723
|
className: "msr:absolute",
|
|
@@ -3231,57 +3745,1002 @@ var MeasurerOverlay = memo5(function MeasurerOverlay2({
|
|
|
3231
3745
|
);
|
|
3232
3746
|
});
|
|
3233
3747
|
|
|
3234
|
-
//
|
|
3235
|
-
|
|
3236
|
-
var
|
|
3748
|
+
// runtime/text-inspector-dom.ts
|
|
3749
|
+
var INK_50 = "#f8fafc";
|
|
3750
|
+
var INK_200 = "#e2e8f0";
|
|
3751
|
+
var INK_500 = "#64748b";
|
|
3752
|
+
var INK_900 = "#0f172a";
|
|
3753
|
+
var makeEdge = (document2, side, color) => {
|
|
3754
|
+
const edge = document2.createElement("div");
|
|
3755
|
+
Object.assign(edge.style, {
|
|
3756
|
+
position: "absolute",
|
|
3757
|
+
backgroundColor: color,
|
|
3758
|
+
...side === "top" || side === "bottom" ? { left: "0", [side]: "0", width: "100%", height: "1px" } : { top: "0", [side]: "0", width: "1px", height: "100%" }
|
|
3759
|
+
});
|
|
3760
|
+
return edge;
|
|
3237
3761
|
};
|
|
3238
|
-
var
|
|
3239
|
-
|
|
3240
|
-
(
|
|
3241
|
-
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3246
|
-
});
|
|
3247
|
-
|
|
3248
|
-
|
|
3249
|
-
|
|
3250
|
-
|
|
3251
|
-
}
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
|
|
3263
|
-
|
|
3264
|
-
|
|
3265
|
-
|
|
3266
|
-
|
|
3267
|
-
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3762
|
+
var makeBox = (document2, fill, outline) => {
|
|
3763
|
+
const box = document2.createElement("div");
|
|
3764
|
+
Object.assign(box.style, {
|
|
3765
|
+
position: "fixed",
|
|
3766
|
+
zIndex: "0",
|
|
3767
|
+
pointerEvents: "none",
|
|
3768
|
+
backgroundColor: fill,
|
|
3769
|
+
boxSizing: "border-box"
|
|
3770
|
+
});
|
|
3771
|
+
box.className = "mesurer-ti-box";
|
|
3772
|
+
box.dataset.state = "hidden";
|
|
3773
|
+
for (const side of ["top", "right", "bottom", "left"]) {
|
|
3774
|
+
box.appendChild(makeEdge(document2, side, outline));
|
|
3775
|
+
}
|
|
3776
|
+
return box;
|
|
3777
|
+
};
|
|
3778
|
+
var positionBox = (box, rect) => {
|
|
3779
|
+
Object.assign(box.style, {
|
|
3780
|
+
left: `${rect.left}px`,
|
|
3781
|
+
top: `${rect.top}px`,
|
|
3782
|
+
width: `${rect.width}px`,
|
|
3783
|
+
height: `${rect.height}px`
|
|
3784
|
+
});
|
|
3785
|
+
};
|
|
3786
|
+
var makeCard = (document2, pinned) => {
|
|
3787
|
+
const card = document2.createElement("div");
|
|
3788
|
+
Object.assign(card.style, {
|
|
3789
|
+
position: "fixed",
|
|
3790
|
+
zIndex: "1",
|
|
3791
|
+
pointerEvents: pinned ? "auto" : "none",
|
|
3792
|
+
background: "#ffffff",
|
|
3793
|
+
color: INK_900,
|
|
3794
|
+
borderRadius: "13px",
|
|
3795
|
+
padding: "10px 12px",
|
|
3796
|
+
fontSize: "11px",
|
|
3797
|
+
lineHeight: "1.5",
|
|
3798
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif",
|
|
3799
|
+
fontVariantNumeric: "tabular-nums",
|
|
3800
|
+
userSelect: "none",
|
|
3801
|
+
whiteSpace: "nowrap",
|
|
3802
|
+
width: "320px",
|
|
3803
|
+
minWidth: "320px",
|
|
3804
|
+
maxWidth: "320px",
|
|
3805
|
+
boxSizing: "border-box",
|
|
3806
|
+
boxShadow: "0px 0px 0.5px rgba(0, 0, 0, 0.18), 0px 3px 8px rgba(0, 0, 0, 0.1), 0px 1px 3px rgba(0, 0, 0, 0.1)"
|
|
3807
|
+
});
|
|
3808
|
+
card.className = pinned ? "mesurer-ti-card mesurer-ti-card--pinned" : "mesurer-ti-card";
|
|
3809
|
+
card.dataset.state = "hidden";
|
|
3810
|
+
return card;
|
|
3811
|
+
};
|
|
3812
|
+
var populateCard = (document2, card, info, pinned) => {
|
|
3813
|
+
card.replaceChildren();
|
|
3814
|
+
const header = document2.createElement("div");
|
|
3815
|
+
Object.assign(header.style, {
|
|
3816
|
+
display: "flex",
|
|
3817
|
+
alignItems: "center",
|
|
3818
|
+
gap: "8px",
|
|
3819
|
+
marginBottom: "8px",
|
|
3820
|
+
paddingBottom: "6px"
|
|
3821
|
+
});
|
|
3822
|
+
const tag = document2.createElement("span");
|
|
3823
|
+
Object.assign(tag.style, {
|
|
3824
|
+
color: INK_50,
|
|
3825
|
+
background: INK_900,
|
|
3826
|
+
borderRadius: "4px",
|
|
3827
|
+
padding: "1px 5px",
|
|
3828
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
3829
|
+
fontSize: "10px",
|
|
3830
|
+
fontWeight: "500"
|
|
3831
|
+
});
|
|
3832
|
+
tag.textContent = info.tagName;
|
|
3833
|
+
header.appendChild(tag);
|
|
3834
|
+
if (info.textSnippet) {
|
|
3835
|
+
const snippet = document2.createElement("span");
|
|
3836
|
+
Object.assign(snippet.style, {
|
|
3837
|
+
color: INK_500,
|
|
3838
|
+
overflow: "hidden",
|
|
3839
|
+
textOverflow: "ellipsis",
|
|
3840
|
+
whiteSpace: "nowrap",
|
|
3841
|
+
flex: "1",
|
|
3842
|
+
minWidth: "0",
|
|
3843
|
+
fontSize: "10px"
|
|
3844
|
+
});
|
|
3845
|
+
snippet.textContent = info.textSnippet;
|
|
3846
|
+
header.appendChild(snippet);
|
|
3847
|
+
}
|
|
3848
|
+
if (pinned) {
|
|
3849
|
+
const close = document2.createElement("button");
|
|
3850
|
+
close.type = "button";
|
|
3851
|
+
close.className = "mesurer-ti-close";
|
|
3852
|
+
close.setAttribute("aria-label", "Close");
|
|
3853
|
+
close.textContent = "\xD7";
|
|
3854
|
+
Object.assign(close.style, {
|
|
3855
|
+
all: "unset",
|
|
3856
|
+
marginLeft: info.textSnippet ? "0" : "auto",
|
|
3857
|
+
flex: "0 0 auto",
|
|
3858
|
+
width: "16px",
|
|
3859
|
+
height: "16px",
|
|
3860
|
+
lineHeight: "14px",
|
|
3861
|
+
textAlign: "center",
|
|
3862
|
+
borderRadius: "4px",
|
|
3863
|
+
color: INK_500,
|
|
3864
|
+
fontSize: "14px"
|
|
3865
|
+
});
|
|
3866
|
+
header.appendChild(close);
|
|
3867
|
+
}
|
|
3868
|
+
card.appendChild(header);
|
|
3869
|
+
const grid = document2.createElement("div");
|
|
3870
|
+
Object.assign(grid.style, {
|
|
3871
|
+
display: "grid",
|
|
3872
|
+
gridTemplateColumns: "auto 1fr",
|
|
3873
|
+
columnGap: "12px",
|
|
3874
|
+
rowGap: "3px",
|
|
3875
|
+
alignItems: "baseline"
|
|
3876
|
+
});
|
|
3877
|
+
for (const row of info.rows) {
|
|
3878
|
+
const label = document2.createElement("span");
|
|
3879
|
+
label.style.color = INK_500;
|
|
3880
|
+
label.style.fontSize = "11px";
|
|
3881
|
+
label.textContent = row.label;
|
|
3882
|
+
const value = document2.createElement("span");
|
|
3883
|
+
Object.assign(value.style, {
|
|
3884
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
3885
|
+
fontSize: "11px",
|
|
3886
|
+
color: INK_900,
|
|
3887
|
+
overflow: "hidden",
|
|
3888
|
+
textOverflow: "ellipsis",
|
|
3889
|
+
whiteSpace: "nowrap"
|
|
3890
|
+
});
|
|
3891
|
+
if (!row.varName) {
|
|
3892
|
+
value.textContent = row.value;
|
|
3893
|
+
} else {
|
|
3894
|
+
const variable = document2.createElement("span");
|
|
3895
|
+
variable.textContent = row.value;
|
|
3896
|
+
const separator = document2.createElement("span");
|
|
3897
|
+
separator.style.color = INK_200;
|
|
3898
|
+
separator.style.margin = "0 6px";
|
|
3899
|
+
separator.textContent = "\xB7";
|
|
3900
|
+
const name = document2.createElement("span");
|
|
3901
|
+
name.style.color = "#0369a1";
|
|
3902
|
+
name.textContent = row.varName;
|
|
3903
|
+
value.append(variable, separator, name);
|
|
3904
|
+
}
|
|
3905
|
+
grid.append(label, value);
|
|
3906
|
+
}
|
|
3907
|
+
card.appendChild(grid);
|
|
3908
|
+
};
|
|
3909
|
+
var positionCard = (window2, card, rect, offsetX = 0, offsetY = 0) => {
|
|
3910
|
+
const center = rect.left + rect.width / 2 + offsetX;
|
|
3911
|
+
card.style.left = `${center}px`;
|
|
3912
|
+
const size = card.getBoundingClientRect();
|
|
3913
|
+
let top = rect.bottom + 4 + offsetY;
|
|
3914
|
+
if (top + size.height > window2.innerHeight - 8) {
|
|
3915
|
+
top = rect.top - size.height - 4 + offsetY;
|
|
3916
|
+
}
|
|
3917
|
+
card.style.top = `${Math.max(8, top)}px`;
|
|
3918
|
+
const half = size.width / 2;
|
|
3919
|
+
card.style.left = `${Math.min(
|
|
3920
|
+
Math.max(center, 8 + half),
|
|
3921
|
+
window2.innerWidth - 8 - half
|
|
3922
|
+
)}px`;
|
|
3923
|
+
};
|
|
3924
|
+
|
|
3925
|
+
// runtime/text-inspector-typography.ts
|
|
3926
|
+
var FONT_WEIGHT_KEYWORD = {
|
|
3927
|
+
"100": "thin",
|
|
3928
|
+
"200": "extralight",
|
|
3929
|
+
"300": "light",
|
|
3930
|
+
"400": "normal",
|
|
3931
|
+
"500": "medium",
|
|
3932
|
+
"600": "semibold",
|
|
3933
|
+
"700": "bold",
|
|
3934
|
+
"800": "extrabold",
|
|
3935
|
+
"900": "black"
|
|
3936
|
+
};
|
|
3937
|
+
var TYPO_PROPS = [
|
|
3938
|
+
"font-family",
|
|
3939
|
+
"font-size",
|
|
3940
|
+
"font-weight",
|
|
3941
|
+
"line-height",
|
|
3942
|
+
"letter-spacing"
|
|
3943
|
+
];
|
|
3944
|
+
var TYPO_LABELS = {
|
|
3945
|
+
Family: "font-family",
|
|
3946
|
+
Size: "font-size",
|
|
3947
|
+
Weight: "font-weight",
|
|
3948
|
+
Line: "line-height",
|
|
3949
|
+
Tracking: "letter-spacing"
|
|
3950
|
+
};
|
|
3951
|
+
var formatPx = (raw) => {
|
|
3952
|
+
if (!raw || raw === "normal") return raw || "normal";
|
|
3953
|
+
const match = /^(-?[\d.]+)px$/.exec(raw);
|
|
3954
|
+
if (!match) return raw;
|
|
3955
|
+
return `${Math.round(Number(match[1]) * 10) / 10}px`;
|
|
3956
|
+
};
|
|
3957
|
+
var firstFontFamily = (families) => (families.split(",")[0] ?? "").trim().replace(/^['"]|['"]$/g, "");
|
|
3958
|
+
var weightWithKeyword = (weight) => {
|
|
3959
|
+
const keyword = FONT_WEIGHT_KEYWORD[weight];
|
|
3960
|
+
return keyword ? `${weight} / ${keyword}` : weight;
|
|
3961
|
+
};
|
|
3962
|
+
var extractVarName = (value) => {
|
|
3963
|
+
if (!value) return null;
|
|
3964
|
+
return /var\(\s*(--[a-zA-Z0-9_-]+)/.exec(value)?.[1] ?? null;
|
|
3965
|
+
};
|
|
3966
|
+
var selectorSpecificity = (selector) => {
|
|
3967
|
+
const ids = (selector.match(/#[\w-]+/g) ?? []).length;
|
|
3968
|
+
const classes = (selector.match(/\.[\w-]+|\[[^\]]+\]|:[\w-]+/g) ?? []).length;
|
|
3969
|
+
const elements = (selector.match(/(?:^|[ >+~])([a-zA-Z][\w-]*)/g) ?? []).length;
|
|
3970
|
+
return ids * 1e4 + classes * 100 + elements;
|
|
3971
|
+
};
|
|
3972
|
+
var wins = (next, previous) => {
|
|
3973
|
+
if (!previous) return true;
|
|
3974
|
+
if (next.important !== previous.important) return next.important;
|
|
3975
|
+
if (next.specificity !== previous.specificity) {
|
|
3976
|
+
return next.specificity > previous.specificity;
|
|
3977
|
+
}
|
|
3978
|
+
return next.order > previous.order;
|
|
3979
|
+
};
|
|
3980
|
+
var TypographyInspector = class {
|
|
3981
|
+
constructor(document2, window2) {
|
|
3982
|
+
this.document = document2;
|
|
3983
|
+
this.window = window2;
|
|
3984
|
+
}
|
|
3985
|
+
collectRules(rules, output, mediaOk, order) {
|
|
3986
|
+
for (let i = 0; i < rules.length; i++) {
|
|
3987
|
+
const rule = rules[i];
|
|
3988
|
+
const currentOrder = order.value++;
|
|
3989
|
+
if (rule.type === 4) {
|
|
3990
|
+
const mediaRule = rule;
|
|
3991
|
+
let matches = mediaOk;
|
|
3992
|
+
try {
|
|
3993
|
+
matches = mediaOk && this.window.matchMedia(mediaRule.media.mediaText).matches;
|
|
3994
|
+
} catch {
|
|
3995
|
+
matches = false;
|
|
3996
|
+
}
|
|
3997
|
+
this.collectRules(mediaRule.cssRules, output, matches, order);
|
|
3998
|
+
} else if (rule.type === 12) {
|
|
3999
|
+
this.collectRules(rule.cssRules, output, mediaOk, order);
|
|
4000
|
+
} else if (rule.type === 1) {
|
|
4001
|
+
output.push({
|
|
4002
|
+
rule,
|
|
4003
|
+
mediaOk,
|
|
4004
|
+
order: currentOrder
|
|
4005
|
+
});
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
}
|
|
4009
|
+
getRules() {
|
|
4010
|
+
const rules = [];
|
|
4011
|
+
const order = { value: 0 };
|
|
4012
|
+
for (const sheet of Array.from(this.document.styleSheets)) {
|
|
4013
|
+
try {
|
|
4014
|
+
this.collectRules(sheet.cssRules, rules, true, order);
|
|
4015
|
+
} catch {
|
|
4016
|
+
continue;
|
|
4017
|
+
}
|
|
4018
|
+
}
|
|
4019
|
+
return rules;
|
|
4020
|
+
}
|
|
4021
|
+
findVarReferences(el) {
|
|
4022
|
+
const result = Object.fromEntries(
|
|
4023
|
+
TYPO_PROPS.map((prop) => [prop, null])
|
|
4024
|
+
);
|
|
4025
|
+
const rules = this.getRules();
|
|
4026
|
+
for (const prop of TYPO_PROPS) {
|
|
4027
|
+
let node = el;
|
|
4028
|
+
while (node && result[prop] === null) {
|
|
4029
|
+
let winner;
|
|
4030
|
+
const inlineValue = node.style.getPropertyValue(prop);
|
|
4031
|
+
const inlineName = extractVarName(inlineValue);
|
|
4032
|
+
if (inlineName) {
|
|
4033
|
+
winner = {
|
|
4034
|
+
name: inlineName,
|
|
4035
|
+
specificity: Number.MAX_SAFE_INTEGER,
|
|
4036
|
+
order: Number.MAX_SAFE_INTEGER,
|
|
4037
|
+
important: node.style.getPropertyPriority(prop) === "important"
|
|
4038
|
+
};
|
|
4039
|
+
}
|
|
4040
|
+
for (const { rule, mediaOk, order } of rules) {
|
|
4041
|
+
if (!mediaOk) continue;
|
|
4042
|
+
let matches = false;
|
|
4043
|
+
try {
|
|
4044
|
+
matches = node.matches(rule.selectorText);
|
|
4045
|
+
} catch {
|
|
4046
|
+
continue;
|
|
4047
|
+
}
|
|
4048
|
+
if (!matches) continue;
|
|
4049
|
+
const name = extractVarName(rule.style.getPropertyValue(prop));
|
|
4050
|
+
if (!name) continue;
|
|
4051
|
+
const candidate = {
|
|
4052
|
+
name,
|
|
4053
|
+
specificity: selectorSpecificity(rule.selectorText),
|
|
4054
|
+
order,
|
|
4055
|
+
important: rule.style.getPropertyPriority(prop) === "important"
|
|
4056
|
+
};
|
|
4057
|
+
if (wins(candidate, winner)) winner = candidate;
|
|
4058
|
+
}
|
|
4059
|
+
if (winner) result[prop] = winner.name;
|
|
4060
|
+
node = node.parentElement;
|
|
4061
|
+
}
|
|
4062
|
+
}
|
|
4063
|
+
return result;
|
|
4064
|
+
}
|
|
4065
|
+
getFast(el) {
|
|
4066
|
+
const styles = this.window.getComputedStyle(el);
|
|
4067
|
+
const rows = [
|
|
4068
|
+
{ label: "Family", value: firstFontFamily(styles.fontFamily), varName: null },
|
|
4069
|
+
{ label: "Size", value: formatPx(styles.fontSize), varName: null },
|
|
4070
|
+
{
|
|
4071
|
+
label: "Weight",
|
|
4072
|
+
value: weightWithKeyword(styles.fontWeight),
|
|
4073
|
+
varName: null
|
|
4074
|
+
},
|
|
4075
|
+
{
|
|
4076
|
+
label: "Line",
|
|
4077
|
+
value: styles.lineHeight === "normal" ? "normal" : formatPx(styles.lineHeight),
|
|
4078
|
+
varName: null
|
|
4079
|
+
},
|
|
4080
|
+
{
|
|
4081
|
+
label: "Tracking",
|
|
4082
|
+
value: styles.letterSpacing === "normal" ? "normal" : formatPx(styles.letterSpacing),
|
|
4083
|
+
varName: null
|
|
4084
|
+
}
|
|
4085
|
+
];
|
|
4086
|
+
const directText = Array.from(el.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE).map((node) => node.nodeValue?.trim() ?? "").filter(Boolean).join(" ").replace(/\s+/g, " ");
|
|
4087
|
+
return {
|
|
4088
|
+
rows,
|
|
4089
|
+
tagName: el.tagName.toLowerCase(),
|
|
4090
|
+
textSnippet: directText.length > 40 ? `${directText.slice(0, 40)}\u2026` : directText
|
|
4091
|
+
};
|
|
4092
|
+
}
|
|
4093
|
+
getFull(el, base = this.getFast(el)) {
|
|
4094
|
+
const vars = this.findVarReferences(el);
|
|
4095
|
+
return {
|
|
4096
|
+
...base,
|
|
4097
|
+
rows: base.rows.map((row) => ({
|
|
4098
|
+
...row,
|
|
4099
|
+
varName: vars[TYPO_LABELS[row.label]]
|
|
4100
|
+
}))
|
|
4101
|
+
};
|
|
4102
|
+
}
|
|
4103
|
+
};
|
|
4104
|
+
|
|
4105
|
+
// runtime/text-inspector.ts
|
|
4106
|
+
var DEFAULT_EXTENSION_HOST_ID = "mesurer-extension-host";
|
|
4107
|
+
var DEFAULT_OVERLAY_ID = "mesurer-text-inspector-overlay";
|
|
4108
|
+
var DEFAULT_STYLE_ID = "mesurer-text-inspector-styles";
|
|
4109
|
+
var DEFAULT_BODY_MODE_CLASS = "mesurer-text-inspect-mode";
|
|
4110
|
+
var inspectorInstanceCount = 0;
|
|
4111
|
+
var FILL_HOVER = "color-mix(in oklch, oklch(0.62 0.18 255) 8%, transparent)";
|
|
4112
|
+
var OUTLINE_HOVER = "color-mix(in oklch, oklch(0.62 0.18 255) 80%, transparent)";
|
|
4113
|
+
var FILL_PINNED = "color-mix(in oklch, oklch(0.62 0.18 255) 4%, transparent)";
|
|
4114
|
+
var OUTLINE_PINNED = "color-mix(in oklch, oklch(0.62 0.18 255) 35%, transparent)";
|
|
4115
|
+
var DEFAULT_SKIP_TAGS = [
|
|
4116
|
+
"HTML",
|
|
4117
|
+
"BODY",
|
|
4118
|
+
"SCRIPT",
|
|
4119
|
+
"STYLE",
|
|
4120
|
+
"META",
|
|
4121
|
+
"LINK",
|
|
4122
|
+
"NOSCRIPT",
|
|
4123
|
+
"IMG",
|
|
4124
|
+
"VIDEO",
|
|
4125
|
+
"AUDIO",
|
|
4126
|
+
"IFRAME"
|
|
4127
|
+
];
|
|
4128
|
+
var createInspectorStyles = (extensionHostId, overlayId, bodyModeClass) => `
|
|
4129
|
+
.${bodyModeClass},
|
|
4130
|
+
.${bodyModeClass} * {
|
|
4131
|
+
cursor: help !important;
|
|
4132
|
+
}
|
|
4133
|
+
.${bodyModeClass} #${extensionHostId},
|
|
4134
|
+
.${bodyModeClass} #${extensionHostId} * {
|
|
4135
|
+
cursor: auto !important;
|
|
4136
|
+
}
|
|
4137
|
+
#${overlayId} .mesurer-ti-card--pinned {
|
|
4138
|
+
cursor: grab;
|
|
4139
|
+
}
|
|
4140
|
+
#${overlayId} .mesurer-ti-card--pinned:active {
|
|
4141
|
+
cursor: grabbing;
|
|
4142
|
+
}
|
|
4143
|
+
#${overlayId} .mesurer-ti-close {
|
|
4144
|
+
cursor: pointer;
|
|
4145
|
+
}
|
|
4146
|
+
#${overlayId} .mesurer-ti-close:hover {
|
|
4147
|
+
background: rgba(15, 23, 42, 0.06);
|
|
4148
|
+
color: #0f172a;
|
|
4149
|
+
}
|
|
4150
|
+
#${overlayId} .mesurer-ti-box,
|
|
4151
|
+
#${overlayId} .mesurer-ti-card {
|
|
4152
|
+
opacity: 1;
|
|
4153
|
+
}
|
|
4154
|
+
#${overlayId} .mesurer-ti-box[data-state="hidden"],
|
|
4155
|
+
#${overlayId} .mesurer-ti-card[data-state="hidden"] {
|
|
4156
|
+
opacity: 0;
|
|
4157
|
+
}
|
|
4158
|
+
#${overlayId} .mesurer-ti-card {
|
|
4159
|
+
transform: translateX(-50%);
|
|
4160
|
+
}
|
|
4161
|
+
`;
|
|
4162
|
+
var createIdleScheduler = (window2) => {
|
|
4163
|
+
const browser = window2;
|
|
4164
|
+
if (browser.requestIdleCallback) {
|
|
4165
|
+
return {
|
|
4166
|
+
request: (callback) => browser.requestIdleCallback(
|
|
4167
|
+
() => callback(),
|
|
4168
|
+
{ timeout: 250 }
|
|
4169
|
+
),
|
|
4170
|
+
cancel: (id) => browser.cancelIdleCallback?.(id)
|
|
4171
|
+
};
|
|
4172
|
+
}
|
|
4173
|
+
return {
|
|
4174
|
+
request: (callback) => window2.setTimeout(callback, 32),
|
|
4175
|
+
cancel: (id) => window2.clearTimeout(id)
|
|
4176
|
+
};
|
|
4177
|
+
};
|
|
4178
|
+
var createTextInspector = (options = {}, legacy = false) => {
|
|
4179
|
+
const portalDocument = options.portalTarget?.ownerDocument;
|
|
4180
|
+
const availableDocument = portalDocument ?? (typeof globalThis.document === "undefined" ? null : globalThis.document);
|
|
4181
|
+
const availableWindow = availableDocument?.defaultView ?? (typeof globalThis.window === "undefined" ? null : globalThis.window);
|
|
4182
|
+
const document2 = availableDocument;
|
|
4183
|
+
const window2 = availableWindow;
|
|
4184
|
+
const realm = availableWindow;
|
|
4185
|
+
const HTMLElementConstructor = realm?.HTMLElement ?? globalThis.HTMLElement;
|
|
4186
|
+
const SVGElementConstructor = realm?.SVGElement ?? globalThis.SVGElement;
|
|
4187
|
+
const extensionHostId = DEFAULT_EXTENSION_HOST_ID;
|
|
4188
|
+
const instanceId = (options.id ?? (legacy ? DEFAULT_OVERLAY_ID : `mesurer-text-inspector-${++inspectorInstanceCount}`)).replace(
|
|
4189
|
+
/[^a-zA-Z0-9_-]/g,
|
|
4190
|
+
"-"
|
|
4191
|
+
);
|
|
4192
|
+
const overlayId = legacy ? DEFAULT_OVERLAY_ID : `${instanceId}-overlay`;
|
|
4193
|
+
const styleId = legacy ? DEFAULT_STYLE_ID : `${instanceId}-styles`;
|
|
4194
|
+
const bodyModeClass = legacy ? DEFAULT_BODY_MODE_CLASS : `${instanceId}-mode`;
|
|
4195
|
+
const skipTags = new Set(
|
|
4196
|
+
(options.ignoredTags ?? DEFAULT_SKIP_TAGS).map((tag) => tag.toUpperCase())
|
|
4197
|
+
);
|
|
4198
|
+
const maxPinned = Number.isFinite(options.maxPinned) ? Math.max(1, Math.floor(options.maxPinned)) : Infinity;
|
|
4199
|
+
const inspectorStyles = createInspectorStyles(
|
|
4200
|
+
extensionHostId,
|
|
4201
|
+
overlayId,
|
|
4202
|
+
bodyModeClass
|
|
4203
|
+
);
|
|
4204
|
+
const EXTENSION_HOST_ID = extensionHostId;
|
|
4205
|
+
const OVERLAY_ID = overlayId;
|
|
4206
|
+
const STYLE_ID = styleId;
|
|
4207
|
+
const BODY_MODE_CLASS = bodyModeClass;
|
|
4208
|
+
const SKIP_TAGS = skipTags;
|
|
4209
|
+
const INSPECTOR_STYLES = inspectorStyles;
|
|
4210
|
+
const portalIsShadowRoot = options.portalTarget?.nodeType === 11;
|
|
4211
|
+
const typography = new TypographyInspector(document2, window2);
|
|
4212
|
+
const pinned = [];
|
|
4213
|
+
const history = [];
|
|
4214
|
+
const future = [];
|
|
4215
|
+
let enabled = false;
|
|
4216
|
+
let overlay = null;
|
|
4217
|
+
let hoverBox = null;
|
|
4218
|
+
let hoverCard = null;
|
|
4219
|
+
let hoveredEl = null;
|
|
4220
|
+
let pointerX = 0;
|
|
4221
|
+
let pointerY = 0;
|
|
4222
|
+
let frameScheduled = false;
|
|
4223
|
+
let pendingElement = null;
|
|
4224
|
+
let pendingIdleId = -1;
|
|
4225
|
+
let idleScheduler = null;
|
|
4226
|
+
const getIdleScheduler = () => {
|
|
4227
|
+
idleScheduler ?? (idleScheduler = createIdleScheduler(window2));
|
|
4228
|
+
return idleScheduler;
|
|
4229
|
+
};
|
|
4230
|
+
const hasDirectText = (el) => Array.from(el.childNodes).some(
|
|
4231
|
+
(node) => node.nodeType === Node.TEXT_NODE && !!node.nodeValue?.trim()
|
|
4232
|
+
);
|
|
4233
|
+
const isInspectable = (el) => !!el && el instanceof HTMLElementConstructor && !SKIP_TAGS.has(el.tagName) && !(el instanceof SVGElementConstructor) && hasDirectText(el);
|
|
4234
|
+
const isOverlayNode = (node) => {
|
|
4235
|
+
for (let current = node; current; current = current.parentNode) {
|
|
4236
|
+
if (current instanceof HTMLElementConstructor) {
|
|
4237
|
+
const element = current;
|
|
4238
|
+
if (element.id === OVERLAY_ID || element.id === EXTENSION_HOST_ID) {
|
|
4239
|
+
return true;
|
|
4240
|
+
}
|
|
4241
|
+
}
|
|
4242
|
+
}
|
|
4243
|
+
return false;
|
|
4244
|
+
};
|
|
4245
|
+
const pickElementAt = (x, y) => {
|
|
4246
|
+
return document2.elementsFromPoint(x, y).find(
|
|
4247
|
+
(el) => !isOverlayNode(el) && isInspectable(el)
|
|
4248
|
+
) ?? null;
|
|
4249
|
+
};
|
|
4250
|
+
const pointerOverToolbar = (x, y) => {
|
|
4251
|
+
const shadow = document2.getElementById(EXTENSION_HOST_ID)?.shadowRoot;
|
|
4252
|
+
const element = shadow?.elementFromPoint(x, y);
|
|
4253
|
+
if (!element) return false;
|
|
4254
|
+
for (let node = element; node; node = node.parentElement) {
|
|
4255
|
+
if (node.classList.contains("mesurer-toolbar-surface")) return true;
|
|
4256
|
+
}
|
|
4257
|
+
return false;
|
|
4258
|
+
};
|
|
4259
|
+
const ensureStyles = () => {
|
|
4260
|
+
const append = (root) => {
|
|
4261
|
+
if (root.querySelector(`#${STYLE_ID}`)) return;
|
|
4262
|
+
const style = document2.createElement("style");
|
|
4263
|
+
style.id = STYLE_ID;
|
|
4264
|
+
style.textContent = INSPECTOR_STYLES;
|
|
4265
|
+
root.nodeType === 9 ? root.head.appendChild(style) : root.appendChild(style);
|
|
4266
|
+
};
|
|
4267
|
+
append(document2);
|
|
4268
|
+
if (portalIsShadowRoot) append(options.portalTarget);
|
|
4269
|
+
};
|
|
4270
|
+
const ensureOverlay = () => {
|
|
4271
|
+
if (overlay?.isConnected) return overlay;
|
|
4272
|
+
overlay = document2.createElement("div");
|
|
4273
|
+
overlay.id = OVERLAY_ID;
|
|
4274
|
+
Object.assign(overlay.style, {
|
|
4275
|
+
position: "fixed",
|
|
4276
|
+
inset: "0",
|
|
4277
|
+
pointerEvents: "none",
|
|
4278
|
+
zIndex: "2147483646"
|
|
4279
|
+
});
|
|
4280
|
+
(options.portalTarget ?? document2.body).appendChild(overlay);
|
|
4281
|
+
return overlay;
|
|
4282
|
+
};
|
|
4283
|
+
const setState = (element, visible) => {
|
|
4284
|
+
element.dataset.state = visible ? "visible" : "hidden";
|
|
4285
|
+
};
|
|
4286
|
+
const ensureHover = () => {
|
|
4287
|
+
const root = ensureOverlay();
|
|
4288
|
+
hoverBox ?? (hoverBox = makeBox(document2, FILL_HOVER, OUTLINE_HOVER));
|
|
4289
|
+
hoverCard ?? (hoverCard = makeCard(document2, false));
|
|
4290
|
+
if (!hoverBox.parentNode) root.appendChild(hoverBox);
|
|
4291
|
+
if (!hoverCard.parentNode) root.appendChild(hoverCard);
|
|
4292
|
+
};
|
|
4293
|
+
const scheduleEnrichment = (element, fast) => {
|
|
4294
|
+
if (pendingElement === element) return;
|
|
4295
|
+
if (pendingIdleId !== -1) getIdleScheduler().cancel(pendingIdleId);
|
|
4296
|
+
pendingElement = element;
|
|
4297
|
+
pendingIdleId = getIdleScheduler().request(() => {
|
|
4298
|
+
pendingIdleId = -1;
|
|
4299
|
+
pendingElement = null;
|
|
4300
|
+
if (!enabled) return;
|
|
4301
|
+
const full = typography.getFull(element, fast);
|
|
4302
|
+
if (hoveredEl !== element || !hoverCard) return;
|
|
4303
|
+
populateCard(document2, hoverCard, full, false);
|
|
4304
|
+
positionCard(window2, hoverCard, element.getBoundingClientRect());
|
|
4305
|
+
options.onInspect?.(element, full);
|
|
4306
|
+
});
|
|
4307
|
+
};
|
|
4308
|
+
const inspect = (element) => {
|
|
4309
|
+
if (!enabled || !isInspectable(element)) return false;
|
|
4310
|
+
ensureHover();
|
|
4311
|
+
const rect = element.getBoundingClientRect();
|
|
4312
|
+
hoveredEl = element;
|
|
4313
|
+
const fast = typography.getFast(element);
|
|
4314
|
+
populateCard(document2, hoverCard, fast, false);
|
|
4315
|
+
scheduleEnrichment(element, fast);
|
|
4316
|
+
positionBox(hoverBox, rect);
|
|
4317
|
+
positionCard(window2, hoverCard, rect);
|
|
4318
|
+
setState(hoverBox, true);
|
|
4319
|
+
setState(hoverCard, true);
|
|
4320
|
+
return true;
|
|
4321
|
+
};
|
|
4322
|
+
const updateHover = () => {
|
|
4323
|
+
if (!enabled || pointerOverToolbar(pointerX, pointerY)) {
|
|
4324
|
+
hideHover();
|
|
4325
|
+
return;
|
|
4326
|
+
}
|
|
4327
|
+
const element = pickElementAt(pointerX, pointerY);
|
|
4328
|
+
if (!element) {
|
|
4329
|
+
hideHover();
|
|
4330
|
+
return;
|
|
4331
|
+
}
|
|
4332
|
+
if (element !== hoveredEl) inspect(element);
|
|
4333
|
+
else {
|
|
4334
|
+
positionBox(hoverBox, element.getBoundingClientRect());
|
|
4335
|
+
positionCard(window2, hoverCard, element.getBoundingClientRect());
|
|
4336
|
+
}
|
|
4337
|
+
};
|
|
4338
|
+
const hideHover = () => {
|
|
4339
|
+
hoveredEl = null;
|
|
4340
|
+
if (hoverBox) setState(hoverBox, false);
|
|
4341
|
+
if (hoverCard) setState(hoverCard, false);
|
|
4342
|
+
};
|
|
4343
|
+
const snapshotPins = () => pinned.map((pin) => {
|
|
4344
|
+
const rect = pin.card.getBoundingClientRect();
|
|
4345
|
+
return {
|
|
4346
|
+
sourceEl: pin.sourceEl,
|
|
4347
|
+
left: pin.userPlaced ? rect.left + rect.width / 2 : 0,
|
|
4348
|
+
top: pin.userPlaced ? rect.top : 0,
|
|
4349
|
+
userPlaced: pin.userPlaced
|
|
4350
|
+
};
|
|
4351
|
+
});
|
|
4352
|
+
const recordPinState = () => {
|
|
4353
|
+
history.push(snapshotPins());
|
|
4354
|
+
future.length = 0;
|
|
4355
|
+
};
|
|
4356
|
+
const removePin = (pin, record = true, notify = record) => {
|
|
4357
|
+
const index = pinned.indexOf(pin);
|
|
4358
|
+
if (index === -1) return;
|
|
4359
|
+
if (record) recordPinState();
|
|
4360
|
+
pinned.splice(index, 1);
|
|
4361
|
+
pin.detach();
|
|
4362
|
+
pin.box.remove();
|
|
4363
|
+
pin.card.remove();
|
|
4364
|
+
if (notify) options.onUnpin?.(pin.sourceEl);
|
|
4365
|
+
};
|
|
4366
|
+
const clearPins = (notify = false) => {
|
|
4367
|
+
while (pinned.length) {
|
|
4368
|
+
removePin(pinned[pinned.length - 1], false, notify);
|
|
4369
|
+
}
|
|
4370
|
+
};
|
|
4371
|
+
const attachDrag = (pin) => {
|
|
4372
|
+
let pointerId = -1;
|
|
4373
|
+
let startX = 0;
|
|
4374
|
+
let startY = 0;
|
|
4375
|
+
let originLeft = 0;
|
|
4376
|
+
let originTop = 0;
|
|
4377
|
+
let active = false;
|
|
4378
|
+
let dragged = false;
|
|
4379
|
+
let historyRecorded = false;
|
|
4380
|
+
const slop = 6;
|
|
4381
|
+
const onMove = (event) => {
|
|
4382
|
+
if (event.pointerId !== pointerId) return;
|
|
4383
|
+
const dx = event.clientX - startX;
|
|
4384
|
+
const dy = event.clientY - startY;
|
|
4385
|
+
if (!active) active = Math.abs(dx) > slop || Math.abs(dy) > slop;
|
|
4386
|
+
if (!active) return;
|
|
4387
|
+
if (!historyRecorded) {
|
|
4388
|
+
recordPinState();
|
|
4389
|
+
historyRecorded = true;
|
|
4390
|
+
}
|
|
4391
|
+
dragged = true;
|
|
4392
|
+
pin.card.style.left = `${Math.min(
|
|
4393
|
+
window2.innerWidth - 8,
|
|
4394
|
+
Math.max(8, originLeft + dx)
|
|
4395
|
+
)}px`;
|
|
4396
|
+
pin.card.style.top = `${Math.min(
|
|
4397
|
+
window2.innerHeight - 8,
|
|
4398
|
+
Math.max(8, originTop + dy)
|
|
4399
|
+
)}px`;
|
|
4400
|
+
pin.userPlaced = true;
|
|
4401
|
+
};
|
|
4402
|
+
const onEnd = (event) => {
|
|
4403
|
+
if (event.pointerId !== pointerId && pointerId !== -1) return;
|
|
4404
|
+
window2.removeEventListener("pointermove", onMove);
|
|
4405
|
+
window2.removeEventListener("pointerup", onEnd);
|
|
4406
|
+
window2.removeEventListener("pointercancel", onEnd);
|
|
4407
|
+
pointerId = -1;
|
|
4408
|
+
active = false;
|
|
4409
|
+
historyRecorded = false;
|
|
4410
|
+
if (dragged) {
|
|
4411
|
+
const swallow = (click) => {
|
|
4412
|
+
click.preventDefault();
|
|
4413
|
+
click.stopPropagation();
|
|
4414
|
+
window2.removeEventListener("click", swallow, true);
|
|
4415
|
+
};
|
|
4416
|
+
window2.addEventListener("click", swallow, true);
|
|
4417
|
+
}
|
|
4418
|
+
dragged = false;
|
|
4419
|
+
};
|
|
4420
|
+
const onDown = (event) => {
|
|
4421
|
+
if (event.button !== 0) return;
|
|
4422
|
+
if (event.target?.classList.contains("mesurer-ti-close")) {
|
|
4423
|
+
return;
|
|
4424
|
+
}
|
|
4425
|
+
const rect = pin.card.getBoundingClientRect();
|
|
4426
|
+
originLeft = rect.left + rect.width / 2;
|
|
4427
|
+
originTop = rect.top;
|
|
4428
|
+
startX = event.clientX;
|
|
4429
|
+
startY = event.clientY;
|
|
4430
|
+
pointerId = event.pointerId;
|
|
4431
|
+
active = false;
|
|
4432
|
+
dragged = false;
|
|
4433
|
+
window2.addEventListener("pointermove", onMove);
|
|
4434
|
+
window2.addEventListener("pointerup", onEnd);
|
|
4435
|
+
window2.addEventListener("pointercancel", onEnd);
|
|
4436
|
+
};
|
|
4437
|
+
pin.card.addEventListener("pointerdown", onDown);
|
|
4438
|
+
return () => {
|
|
4439
|
+
pin.card.removeEventListener("pointerdown", onDown);
|
|
4440
|
+
window2.removeEventListener("pointermove", onMove);
|
|
4441
|
+
window2.removeEventListener("pointerup", onEnd);
|
|
4442
|
+
window2.removeEventListener("pointercancel", onEnd);
|
|
4443
|
+
};
|
|
4444
|
+
};
|
|
4445
|
+
const createPin = (sourceEl, state, record = true, notify = record) => {
|
|
4446
|
+
const existing = pinned.find((pin2) => pin2.sourceEl === sourceEl);
|
|
4447
|
+
if (existing) {
|
|
4448
|
+
const root2 = ensureOverlay();
|
|
4449
|
+
root2.append(existing.box, existing.card);
|
|
4450
|
+
return;
|
|
4451
|
+
}
|
|
4452
|
+
if (record) {
|
|
4453
|
+
recordPinState();
|
|
4454
|
+
if (pinned.length >= maxPinned) removePin(pinned[0], false, true);
|
|
4455
|
+
}
|
|
4456
|
+
const root = ensureOverlay();
|
|
4457
|
+
const box = makeBox(document2, FILL_PINNED, OUTLINE_PINNED);
|
|
4458
|
+
const card = makeCard(document2, true);
|
|
4459
|
+
const info = typography.getFull(sourceEl);
|
|
4460
|
+
populateCard(document2, card, info, true);
|
|
4461
|
+
root.append(box, card);
|
|
4462
|
+
const pin = {
|
|
4463
|
+
sourceEl,
|
|
4464
|
+
box,
|
|
4465
|
+
card,
|
|
4466
|
+
userPlaced: state?.userPlaced ?? false,
|
|
4467
|
+
detach: () => {
|
|
4468
|
+
}
|
|
4469
|
+
};
|
|
4470
|
+
const rect = sourceEl.getBoundingClientRect();
|
|
4471
|
+
positionBox(box, rect);
|
|
4472
|
+
positionCard(window2, card, rect);
|
|
4473
|
+
if (state?.userPlaced) {
|
|
4474
|
+
card.style.left = `${state.left}px`;
|
|
4475
|
+
card.style.top = `${state.top}px`;
|
|
4476
|
+
}
|
|
4477
|
+
setState(box, true);
|
|
4478
|
+
setState(card, true);
|
|
4479
|
+
pinned.push(pin);
|
|
4480
|
+
card.querySelector(".mesurer-ti-close")?.addEventListener(
|
|
4481
|
+
"click",
|
|
4482
|
+
(event) => {
|
|
4483
|
+
event.preventDefault();
|
|
4484
|
+
event.stopPropagation();
|
|
4485
|
+
removePin(pin);
|
|
4486
|
+
}
|
|
4487
|
+
);
|
|
4488
|
+
pin.detach = attachDrag(pin);
|
|
4489
|
+
if (notify) options.onPin?.(sourceEl, info);
|
|
4490
|
+
};
|
|
4491
|
+
const restorePins = (states) => {
|
|
4492
|
+
clearPins(false);
|
|
4493
|
+
for (const state of states) {
|
|
4494
|
+
if (state.sourceEl.isConnected) createPin(state.sourceEl, state, false, false);
|
|
4495
|
+
}
|
|
4496
|
+
};
|
|
4497
|
+
const undo = () => {
|
|
4498
|
+
const previous = history.pop();
|
|
4499
|
+
if (!previous) return false;
|
|
4500
|
+
future.push(snapshotPins());
|
|
4501
|
+
restorePins(previous);
|
|
4502
|
+
return true;
|
|
4503
|
+
};
|
|
4504
|
+
const redo = () => {
|
|
4505
|
+
const next = future.pop();
|
|
4506
|
+
if (!next) return false;
|
|
4507
|
+
history.push(snapshotPins());
|
|
4508
|
+
restorePins(next);
|
|
4509
|
+
return true;
|
|
4510
|
+
};
|
|
4511
|
+
const clear = () => {
|
|
4512
|
+
if (!pinned.length) return;
|
|
4513
|
+
recordPinState();
|
|
4514
|
+
clearPins(true);
|
|
4515
|
+
};
|
|
4516
|
+
const syncPins = () => {
|
|
4517
|
+
for (const pin of [...pinned]) {
|
|
4518
|
+
if (!pin.sourceEl.isConnected) {
|
|
4519
|
+
removePin(pin, false);
|
|
4520
|
+
continue;
|
|
4521
|
+
}
|
|
4522
|
+
const rect = pin.sourceEl.getBoundingClientRect();
|
|
4523
|
+
positionBox(pin.box, rect);
|
|
4524
|
+
if (!pin.userPlaced) positionCard(window2, pin.card, rect);
|
|
4525
|
+
const visible = rect.bottom >= 0 && rect.right >= 0 && rect.left <= window2.innerWidth && rect.top <= window2.innerHeight;
|
|
4526
|
+
setState(pin.box, visible);
|
|
4527
|
+
setState(pin.card, visible);
|
|
4528
|
+
pin.card.style.pointerEvents = visible ? "auto" : "none";
|
|
4529
|
+
}
|
|
4530
|
+
};
|
|
4531
|
+
const scheduleFrame = () => {
|
|
4532
|
+
if (frameScheduled) return;
|
|
4533
|
+
frameScheduled = true;
|
|
4534
|
+
requestAnimationFrame(() => {
|
|
4535
|
+
frameScheduled = false;
|
|
4536
|
+
if (!enabled) return;
|
|
4537
|
+
updateHover();
|
|
4538
|
+
syncPins();
|
|
4539
|
+
});
|
|
4540
|
+
};
|
|
4541
|
+
const onMouseMove = (event) => {
|
|
4542
|
+
pointerX = event.clientX;
|
|
4543
|
+
pointerY = event.clientY;
|
|
4544
|
+
scheduleFrame();
|
|
4545
|
+
};
|
|
4546
|
+
const onMouseOut = (event) => {
|
|
4547
|
+
if (!event.relatedTarget) hideHover();
|
|
4548
|
+
};
|
|
4549
|
+
const onScrollOrResize = () => scheduleFrame();
|
|
4550
|
+
const isInspectorUIEvent = (event) => event.composedPath().some(
|
|
4551
|
+
(node) => node instanceof HTMLElementConstructor && (() => {
|
|
4552
|
+
const element = node;
|
|
4553
|
+
return element.id === OVERLAY_ID || element.classList.contains("mesurer-ti-card") || element.classList.contains("mesurer-ti-box") || element.classList.contains("mesurer-ti-close") || element.classList.contains("mesurer-toolbar-surface");
|
|
4554
|
+
})()
|
|
4555
|
+
);
|
|
4556
|
+
const onClick = (event) => {
|
|
4557
|
+
if (isInspectorUIEvent(event) || pointerOverToolbar(event.clientX, event.clientY)) {
|
|
4558
|
+
return;
|
|
4559
|
+
}
|
|
4560
|
+
event.preventDefault();
|
|
4561
|
+
event.stopImmediatePropagation();
|
|
4562
|
+
if (event.button === 0) {
|
|
4563
|
+
const source = pickElementAt(event.clientX, event.clientY);
|
|
4564
|
+
if (source) createPin(source);
|
|
4565
|
+
}
|
|
4566
|
+
};
|
|
4567
|
+
const onAuxClick = (event) => {
|
|
4568
|
+
if (isInspectorUIEvent(event) || pointerOverToolbar(event.clientX, event.clientY)) {
|
|
4569
|
+
return;
|
|
4570
|
+
}
|
|
4571
|
+
event.preventDefault();
|
|
4572
|
+
event.stopImmediatePropagation();
|
|
4573
|
+
};
|
|
4574
|
+
const enable = () => {
|
|
4575
|
+
if (enabled || !availableDocument || !availableWindow) return;
|
|
4576
|
+
enabled = true;
|
|
4577
|
+
ensureStyles();
|
|
4578
|
+
ensureOverlay();
|
|
4579
|
+
document2.body.classList.add(BODY_MODE_CLASS);
|
|
4580
|
+
window2.addEventListener("mousemove", onMouseMove, true);
|
|
4581
|
+
window2.addEventListener("mouseout", onMouseOut, true);
|
|
4582
|
+
window2.addEventListener("click", onClick, true);
|
|
4583
|
+
window2.addEventListener("auxclick", onAuxClick, true);
|
|
4584
|
+
window2.addEventListener("scroll", onScrollOrResize, true);
|
|
4585
|
+
window2.addEventListener("resize", onScrollOrResize, true);
|
|
4586
|
+
};
|
|
4587
|
+
const disable = () => {
|
|
4588
|
+
if (!enabled) return;
|
|
4589
|
+
enabled = false;
|
|
4590
|
+
if (pendingIdleId !== -1) getIdleScheduler().cancel(pendingIdleId);
|
|
4591
|
+
pendingIdleId = -1;
|
|
4592
|
+
pendingElement = null;
|
|
4593
|
+
history.length = 0;
|
|
4594
|
+
future.length = 0;
|
|
4595
|
+
window2.removeEventListener("mousemove", onMouseMove, true);
|
|
4596
|
+
window2.removeEventListener("mouseout", onMouseOut, true);
|
|
4597
|
+
window2.removeEventListener("click", onClick, true);
|
|
4598
|
+
window2.removeEventListener("auxclick", onAuxClick, true);
|
|
4599
|
+
window2.removeEventListener("scroll", onScrollOrResize, true);
|
|
4600
|
+
window2.removeEventListener("resize", onScrollOrResize, true);
|
|
4601
|
+
hideHover();
|
|
4602
|
+
hoverBox?.remove();
|
|
4603
|
+
hoverCard?.remove();
|
|
4604
|
+
hoverBox = null;
|
|
4605
|
+
hoverCard = null;
|
|
4606
|
+
clearPins();
|
|
4607
|
+
document2.body.classList.remove(BODY_MODE_CLASS);
|
|
4608
|
+
};
|
|
4609
|
+
const cleanup = () => {
|
|
4610
|
+
disable();
|
|
4611
|
+
overlay?.remove();
|
|
4612
|
+
overlay = null;
|
|
4613
|
+
if (typeof document2 !== "undefined") {
|
|
4614
|
+
document2.getElementById(STYLE_ID)?.remove();
|
|
4615
|
+
if (portalIsShadowRoot) {
|
|
4616
|
+
options.portalTarget.querySelector(`#${STYLE_ID}`)?.remove();
|
|
4617
|
+
}
|
|
4618
|
+
}
|
|
4619
|
+
};
|
|
4620
|
+
return {
|
|
4621
|
+
enable,
|
|
4622
|
+
disable,
|
|
4623
|
+
undo,
|
|
4624
|
+
redo,
|
|
4625
|
+
canUndo: () => history.length > 0,
|
|
4626
|
+
canRedo: () => future.length > 0,
|
|
4627
|
+
clear,
|
|
4628
|
+
inspect,
|
|
4629
|
+
isEnabled: () => enabled,
|
|
4630
|
+
cleanup,
|
|
4631
|
+
destroy: cleanup
|
|
4632
|
+
};
|
|
4633
|
+
};
|
|
4634
|
+
var TextInspector = createTextInspector({}, true);
|
|
4635
|
+
|
|
4636
|
+
// measurer.tsx
|
|
4637
|
+
import { jsx as jsx9, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
4638
|
+
var measurerInstanceCount = 0;
|
|
4639
|
+
var XRAY_STYLE_ID = "mesurer-xray-styles";
|
|
4640
|
+
var XRAY_STYLES = `
|
|
4641
|
+
.xray-mode * {
|
|
4642
|
+
outline: solid 1px blue !important;
|
|
4643
|
+
}
|
|
4644
|
+
.xray-mode #mesurer-extension-host,
|
|
4645
|
+
.xray-mode #mesurer-extension-host *,
|
|
4646
|
+
.xray-mode .mesurer-root,
|
|
4647
|
+
.xray-mode .mesurer-root *,
|
|
4648
|
+
.xray-mode .mesurer-toolbar-surface,
|
|
4649
|
+
.xray-mode .mesurer-toolbar-surface * {
|
|
4650
|
+
outline: none !important;
|
|
4651
|
+
}
|
|
4652
|
+
`;
|
|
4653
|
+
var subscribeHydration = () => () => {
|
|
4654
|
+
};
|
|
4655
|
+
var useHydrated = () => useSyncExternalStore(
|
|
4656
|
+
subscribeHydration,
|
|
4657
|
+
() => true,
|
|
4658
|
+
() => false
|
|
4659
|
+
);
|
|
4660
|
+
var stripMeasurement = (measurement) => ({
|
|
4661
|
+
...measurement,
|
|
4662
|
+
elementRef: void 0
|
|
4663
|
+
});
|
|
4664
|
+
var stripDistance = (distance) => ({
|
|
4665
|
+
...distance,
|
|
4666
|
+
elementRefA: void 0,
|
|
4667
|
+
elementRefB: void 0
|
|
4668
|
+
});
|
|
4669
|
+
function MeasurerClient({
|
|
4670
|
+
highlightColor,
|
|
4671
|
+
guideColor,
|
|
4672
|
+
hoverHighlightEnabled,
|
|
4673
|
+
persistOnReload,
|
|
4674
|
+
portalTarget,
|
|
4675
|
+
persistKey
|
|
4676
|
+
}) {
|
|
4677
|
+
const instanceIdRef = useRef9(null);
|
|
4678
|
+
if (instanceIdRef.current === null) {
|
|
4679
|
+
instanceIdRef.current = ++measurerInstanceCount;
|
|
4680
|
+
}
|
|
4681
|
+
const storageKey = persistKey ?? (instanceIdRef.current === 1 ? "mesurer-state" : `mesurer-state-${instanceIdRef.current}`);
|
|
4682
|
+
const ownerDocument = portalTarget.ownerDocument ?? document;
|
|
4683
|
+
const ownerWindow = ownerDocument.defaultView ?? window;
|
|
4684
|
+
const guideScrollRef = useRef9({
|
|
4685
|
+
x: ownerWindow.scrollX,
|
|
4686
|
+
y: ownerWindow.scrollY
|
|
4687
|
+
});
|
|
4688
|
+
const textInspectorRef = useRef9(null);
|
|
4689
|
+
if (!textInspectorRef.current) {
|
|
4690
|
+
textInspectorRef.current = createTextInspector({ portalTarget });
|
|
4691
|
+
}
|
|
4692
|
+
const textInspector = textInspectorRef.current;
|
|
4693
|
+
const selectionRectRef = useRef9(null);
|
|
4694
|
+
const toolbarRef = useRef9(null);
|
|
4695
|
+
const selectionAnimationCleanupTimeoutRef = useRef9(null);
|
|
4696
|
+
const guideDragRef = useRef9(null);
|
|
4697
|
+
const guideUserSelectRef = useRef9(null);
|
|
4698
|
+
const persistedState = useMemo2(() => {
|
|
4699
|
+
if (!persistOnReload) return null;
|
|
4700
|
+
try {
|
|
4701
|
+
const stored = window.localStorage.getItem(storageKey);
|
|
4702
|
+
if (!stored) return null;
|
|
4703
|
+
const parsed = JSON.parse(stored);
|
|
4704
|
+
if (!parsed || parsed.version !== 1) return null;
|
|
4705
|
+
return parsed;
|
|
4706
|
+
} catch {
|
|
4707
|
+
return null;
|
|
4708
|
+
}
|
|
4709
|
+
}, [persistOnReload, storageKey]);
|
|
4710
|
+
const enabledRef = useRef9(false);
|
|
4711
|
+
const toolModeRef = useRef9(
|
|
4712
|
+
persistedState?.toolMode === "rulers" ? "none" : persistedState?.toolMode ?? "none"
|
|
4713
|
+
);
|
|
4714
|
+
const rulersVisibleRef = useRef9(
|
|
4715
|
+
persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers"
|
|
4716
|
+
);
|
|
4717
|
+
const guideOrientationRef = useRef9(
|
|
4718
|
+
persistedState?.guideOrientation ?? "vertical"
|
|
4719
|
+
);
|
|
4720
|
+
const measurementsRef = useRef9(
|
|
4721
|
+
persistedState?.measurements ?? []
|
|
4722
|
+
);
|
|
4723
|
+
const activeMeasurementRef = useRef9(
|
|
4724
|
+
persistedState?.activeMeasurement ?? null
|
|
4725
|
+
);
|
|
4726
|
+
const heldDistancesRef = useRef9(
|
|
4727
|
+
persistedState?.heldDistances ?? []
|
|
4728
|
+
);
|
|
4729
|
+
const guidesRef = useRef9(persistedState?.guides ?? []);
|
|
4730
|
+
const selectedGuideIdsRef = useRef9(
|
|
4731
|
+
persistedState?.selectedGuideIds ?? []
|
|
4732
|
+
);
|
|
4733
|
+
const { overlayRef, selectedElementRef, hoverElementRef } = useOverlayRefs();
|
|
4734
|
+
const {
|
|
4735
|
+
selectionOriginRect,
|
|
4736
|
+
setSelectionOriginRect,
|
|
4737
|
+
hoverPointer,
|
|
4738
|
+
setHoverPointer,
|
|
4739
|
+
hoverElement,
|
|
4740
|
+
setHoverElement,
|
|
4741
|
+
selectedElement,
|
|
4742
|
+
setSelectedElement,
|
|
4743
|
+
clearSelectionRect
|
|
3285
4744
|
} = useMeasurerLocalState({
|
|
3286
4745
|
selectedElementRef,
|
|
3287
4746
|
hoverElementRef,
|
|
@@ -3296,12 +4755,15 @@ function MeasurerClient({
|
|
|
3296
4755
|
setAltPressed,
|
|
3297
4756
|
toolMode,
|
|
3298
4757
|
setToolMode,
|
|
4758
|
+
rulersVisible,
|
|
4759
|
+
setRulersVisible,
|
|
3299
4760
|
guidesEnabled,
|
|
3300
4761
|
multiMeasureEnabled,
|
|
3301
4762
|
snapGuidesEnabled
|
|
3302
4763
|
} = useMeasureToggles({
|
|
3303
4764
|
initialEnabled: persistedState?.enabled,
|
|
3304
|
-
initialToolMode: persistedState?.toolMode
|
|
4765
|
+
initialToolMode: persistedState?.toolMode === "rulers" ? "none" : persistedState?.toolMode,
|
|
4766
|
+
initialRulersVisible: persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers"
|
|
3305
4767
|
});
|
|
3306
4768
|
const { start, setStart, end, setEnd, isDragging, setIsDragging } = useDragState();
|
|
3307
4769
|
const {
|
|
@@ -3333,85 +4795,170 @@ function MeasurerClient({
|
|
|
3333
4795
|
initialGuides: persistedState?.guides ?? [],
|
|
3334
4796
|
initialSelectedGuideIds: persistedState?.selectedGuideIds ?? []
|
|
3335
4797
|
});
|
|
3336
|
-
const [toolbarActive, setToolbarActive] =
|
|
3337
|
-
const { clearGuideDragHold, scheduleGuideDragHold } = useGuideDragHold();
|
|
3338
|
-
const [guidePreview, setGuidePreview] =
|
|
3339
|
-
const [guideOrientation, setGuideOrientation] =
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
activeMeasurement: activeMeasurement ? stripMeasurement(activeMeasurement) : null,
|
|
3351
|
-
heldDistances: heldDistances.map(stripDistance)
|
|
3352
|
-
});
|
|
3353
|
-
}, [
|
|
3354
|
-
activeMeasurement,
|
|
3355
|
-
enabled,
|
|
3356
|
-
guideOrientation,
|
|
3357
|
-
guides,
|
|
3358
|
-
heldDistances,
|
|
3359
|
-
measurements,
|
|
3360
|
-
persistOnReload,
|
|
3361
|
-
selectedGuideIds,
|
|
3362
|
-
toolMode
|
|
3363
|
-
]);
|
|
3364
|
-
useEffect9(() => {
|
|
4798
|
+
const [toolbarActive, setToolbarActive] = useState8(true);
|
|
4799
|
+
const { clearGuideDragHold, scheduleGuideDragHold } = useGuideDragHold(ownerWindow);
|
|
4800
|
+
const [guidePreview, setGuidePreview] = useState8(null);
|
|
4801
|
+
const [guideOrientation, setGuideOrientation] = useState8(persistedState?.guideOrientation ?? "vertical");
|
|
4802
|
+
enabledRef.current = enabled;
|
|
4803
|
+
toolModeRef.current = toolMode;
|
|
4804
|
+
rulersVisibleRef.current = rulersVisible;
|
|
4805
|
+
guideOrientationRef.current = guideOrientation;
|
|
4806
|
+
measurementsRef.current = measurements;
|
|
4807
|
+
activeMeasurementRef.current = activeMeasurement;
|
|
4808
|
+
heldDistancesRef.current = heldDistances;
|
|
4809
|
+
guidesRef.current = guides;
|
|
4810
|
+
selectedGuideIdsRef.current = selectedGuideIds;
|
|
4811
|
+
const persistState = useCallback6(() => {
|
|
3365
4812
|
if (!persistOnReload) return;
|
|
3366
4813
|
if (typeof window === "undefined") return;
|
|
3367
|
-
if (!persistPayload) return;
|
|
3368
4814
|
try {
|
|
3369
|
-
window.localStorage.setItem(
|
|
4815
|
+
window.localStorage.setItem(
|
|
4816
|
+
storageKey,
|
|
4817
|
+
JSON.stringify({
|
|
4818
|
+
version: 1,
|
|
4819
|
+
enabled: enabledRef.current,
|
|
4820
|
+
toolMode: toolModeRef.current,
|
|
4821
|
+
rulersVisible: rulersVisibleRef.current,
|
|
4822
|
+
guideOrientation: guideOrientationRef.current,
|
|
4823
|
+
guides: guidesRef.current,
|
|
4824
|
+
selectedGuideIds: selectedGuideIdsRef.current,
|
|
4825
|
+
measurements: measurementsRef.current.map(stripMeasurement),
|
|
4826
|
+
activeMeasurement: activeMeasurementRef.current ? stripMeasurement(activeMeasurementRef.current) : null,
|
|
4827
|
+
heldDistances: heldDistancesRef.current.map(stripDistance)
|
|
4828
|
+
})
|
|
4829
|
+
);
|
|
3370
4830
|
} catch {
|
|
3371
4831
|
}
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
4832
|
+
}, [persistOnReload, storageKey]);
|
|
4833
|
+
const setEnabledPersisted = useCallback6(
|
|
4834
|
+
(value) => {
|
|
4835
|
+
const next = typeof value === "function" ? value(enabledRef.current) : value;
|
|
4836
|
+
if (Object.is(next, enabledRef.current)) return;
|
|
4837
|
+
enabledRef.current = next;
|
|
4838
|
+
setEnabled(next);
|
|
4839
|
+
persistState();
|
|
4840
|
+
},
|
|
4841
|
+
[persistState, setEnabled]
|
|
4842
|
+
);
|
|
4843
|
+
const setRulersVisiblePersisted = useCallback6(
|
|
4844
|
+
(value) => {
|
|
4845
|
+
const next = typeof value === "function" ? value(rulersVisibleRef.current) : value;
|
|
4846
|
+
if (Object.is(next, rulersVisibleRef.current)) return;
|
|
4847
|
+
rulersVisibleRef.current = next;
|
|
4848
|
+
setRulersVisible(next);
|
|
4849
|
+
persistState();
|
|
4850
|
+
},
|
|
4851
|
+
[persistState, setRulersVisible]
|
|
4852
|
+
);
|
|
4853
|
+
const setToolModePersisted = useCallback6(
|
|
4854
|
+
(value) => {
|
|
4855
|
+
const next = typeof value === "function" ? value(toolModeRef.current) : value;
|
|
4856
|
+
if (Object.is(next, toolModeRef.current)) return;
|
|
4857
|
+
toolModeRef.current = next;
|
|
4858
|
+
setToolMode(next);
|
|
4859
|
+
if (next === "text-inspector") {
|
|
4860
|
+
textInspector.enable();
|
|
4861
|
+
} else {
|
|
4862
|
+
textInspector.disable();
|
|
3376
4863
|
}
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
4864
|
+
persistState();
|
|
4865
|
+
},
|
|
4866
|
+
[persistState, setToolMode, textInspector]
|
|
4867
|
+
);
|
|
4868
|
+
const setGuideOrientationPersisted = useCallback6(
|
|
4869
|
+
(value) => {
|
|
4870
|
+
const next = typeof value === "function" ? value(guideOrientationRef.current) : value;
|
|
4871
|
+
if (Object.is(next, guideOrientationRef.current)) return;
|
|
4872
|
+
guideOrientationRef.current = next;
|
|
4873
|
+
setGuideOrientation(next);
|
|
4874
|
+
persistState();
|
|
4875
|
+
},
|
|
4876
|
+
[persistState, setGuideOrientation]
|
|
4877
|
+
);
|
|
4878
|
+
const setMeasurementsPersisted = useCallback6(
|
|
4879
|
+
(value) => {
|
|
4880
|
+
const next = typeof value === "function" ? value(measurementsRef.current) : value;
|
|
4881
|
+
if (Object.is(next, measurementsRef.current)) return;
|
|
4882
|
+
measurementsRef.current = next;
|
|
4883
|
+
setMeasurements(next);
|
|
4884
|
+
persistState();
|
|
4885
|
+
},
|
|
4886
|
+
[persistState, setMeasurements]
|
|
4887
|
+
);
|
|
4888
|
+
const setActiveMeasurementPersisted = useCallback6(
|
|
4889
|
+
(value) => {
|
|
4890
|
+
const next = typeof value === "function" ? value(activeMeasurementRef.current) : value;
|
|
4891
|
+
if (Object.is(next, activeMeasurementRef.current)) return;
|
|
4892
|
+
activeMeasurementRef.current = next;
|
|
4893
|
+
setActiveMeasurement(next);
|
|
4894
|
+
persistState();
|
|
4895
|
+
},
|
|
4896
|
+
[persistState, setActiveMeasurement]
|
|
4897
|
+
);
|
|
4898
|
+
const setHeldDistancesPersisted = useCallback6(
|
|
4899
|
+
(value) => {
|
|
4900
|
+
const next = typeof value === "function" ? value(heldDistancesRef.current) : value;
|
|
4901
|
+
if (Object.is(next, heldDistancesRef.current)) return;
|
|
4902
|
+
heldDistancesRef.current = next;
|
|
4903
|
+
setHeldDistances(next);
|
|
4904
|
+
persistState();
|
|
4905
|
+
},
|
|
4906
|
+
[persistState, setHeldDistances]
|
|
4907
|
+
);
|
|
4908
|
+
const setGuidesPersisted = useCallback6(
|
|
4909
|
+
(value) => {
|
|
4910
|
+
const next = typeof value === "function" ? value(guidesRef.current) : value;
|
|
4911
|
+
if (Object.is(next, guidesRef.current)) return;
|
|
4912
|
+
guidesRef.current = next;
|
|
4913
|
+
setGuides(next);
|
|
4914
|
+
persistState();
|
|
4915
|
+
},
|
|
4916
|
+
[persistState, setGuides]
|
|
4917
|
+
);
|
|
4918
|
+
const setSelectedGuideIdsPersisted = useCallback6(
|
|
4919
|
+
(value) => {
|
|
4920
|
+
const next = typeof value === "function" ? value(selectedGuideIdsRef.current) : value;
|
|
4921
|
+
if (Object.is(next, selectedGuideIdsRef.current)) return;
|
|
4922
|
+
selectedGuideIdsRef.current = next;
|
|
4923
|
+
setSelectedGuideIds(next);
|
|
4924
|
+
persistState();
|
|
4925
|
+
},
|
|
4926
|
+
[persistState, setSelectedGuideIds]
|
|
4927
|
+
);
|
|
3383
4928
|
const {
|
|
3384
4929
|
recordSnapshot,
|
|
3385
4930
|
createActionCommit,
|
|
3386
4931
|
setToolModeWithHistory,
|
|
3387
4932
|
setGuideOrientationWithHistory,
|
|
3388
|
-
setEnabledWithHistory
|
|
4933
|
+
setEnabledWithHistory,
|
|
4934
|
+
undo: undoHistory,
|
|
4935
|
+
redo: redoHistory
|
|
3389
4936
|
} = useMeasurerHistory({
|
|
3390
4937
|
toggles: {
|
|
3391
4938
|
enabled,
|
|
3392
|
-
setEnabled,
|
|
4939
|
+
setEnabled: setEnabledPersisted,
|
|
3393
4940
|
toolMode,
|
|
3394
|
-
setToolMode,
|
|
4941
|
+
setToolMode: setToolModePersisted,
|
|
3395
4942
|
guideOrientation,
|
|
3396
|
-
setGuideOrientation
|
|
4943
|
+
setGuideOrientation: setGuideOrientationPersisted
|
|
3397
4944
|
},
|
|
3398
4945
|
measurements: {
|
|
3399
4946
|
measurements,
|
|
3400
|
-
setMeasurements,
|
|
4947
|
+
setMeasurements: setMeasurementsPersisted,
|
|
3401
4948
|
activeMeasurement,
|
|
3402
|
-
setActiveMeasurement,
|
|
4949
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
3403
4950
|
selectedMeasurements,
|
|
3404
4951
|
setSelectedMeasurements,
|
|
3405
4952
|
selectedMeasurement,
|
|
3406
4953
|
setSelectedMeasurement,
|
|
3407
4954
|
heldDistances,
|
|
3408
|
-
setHeldDistances
|
|
4955
|
+
setHeldDistances: setHeldDistancesPersisted
|
|
3409
4956
|
},
|
|
3410
4957
|
guides: {
|
|
3411
4958
|
guides,
|
|
3412
|
-
setGuides,
|
|
4959
|
+
setGuides: setGuidesPersisted,
|
|
3413
4960
|
selectedGuideIds,
|
|
3414
|
-
setSelectedGuideIds,
|
|
4961
|
+
setSelectedGuideIds: setSelectedGuideIdsPersisted,
|
|
3415
4962
|
draggingGuideId,
|
|
3416
4963
|
setDraggingGuideId
|
|
3417
4964
|
},
|
|
@@ -3426,96 +4973,254 @@ function MeasurerClient({
|
|
|
3426
4973
|
clearSelectionRect
|
|
3427
4974
|
}
|
|
3428
4975
|
});
|
|
4976
|
+
const undo = useCallback6(() => {
|
|
4977
|
+
if (toolMode === "text-inspector" && textInspector.undo()) return;
|
|
4978
|
+
undoHistory();
|
|
4979
|
+
}, [textInspector, toolMode, undoHistory]);
|
|
4980
|
+
const redo = useCallback6(() => {
|
|
4981
|
+
if (toolMode === "text-inspector" && textInspector.redo()) return;
|
|
4982
|
+
redoHistory();
|
|
4983
|
+
}, [redoHistory, textInspector, toolMode]);
|
|
3429
4984
|
const clearAll = useCallback6(() => {
|
|
4985
|
+
if (toolMode === "text-inspector") {
|
|
4986
|
+
textInspector.clear();
|
|
4987
|
+
}
|
|
3430
4988
|
recordSnapshot();
|
|
3431
4989
|
clearGuideDragHold();
|
|
3432
4990
|
setStart(null);
|
|
3433
4991
|
setEnd(null);
|
|
3434
4992
|
setIsDragging(false);
|
|
3435
|
-
|
|
3436
|
-
|
|
4993
|
+
setActiveMeasurementPersisted(null);
|
|
4994
|
+
setMeasurementsPersisted([]);
|
|
3437
4995
|
setSelectedMeasurement(null);
|
|
3438
4996
|
setSelectedMeasurements([]);
|
|
3439
4997
|
clearSelectionRect();
|
|
3440
4998
|
setSelectedElement(null);
|
|
3441
4999
|
setHoverRect(null);
|
|
3442
5000
|
setHoverElement(null);
|
|
3443
|
-
|
|
3444
|
-
|
|
3445
|
-
|
|
5001
|
+
setGuidesPersisted([]);
|
|
5002
|
+
setSelectedGuideIdsPersisted([]);
|
|
5003
|
+
setHeldDistancesPersisted([]);
|
|
3446
5004
|
}, [
|
|
3447
5005
|
clearGuideDragHold,
|
|
3448
5006
|
clearSelectionRect,
|
|
3449
5007
|
recordSnapshot,
|
|
3450
|
-
|
|
5008
|
+
setActiveMeasurementPersisted,
|
|
3451
5009
|
setEnd,
|
|
3452
|
-
|
|
3453
|
-
|
|
5010
|
+
setGuidesPersisted,
|
|
5011
|
+
setHeldDistancesPersisted,
|
|
3454
5012
|
setHoverElement,
|
|
3455
5013
|
setHoverRect,
|
|
3456
5014
|
setIsDragging,
|
|
3457
|
-
|
|
5015
|
+
setMeasurementsPersisted,
|
|
3458
5016
|
setSelectedElement,
|
|
3459
|
-
|
|
5017
|
+
setSelectedGuideIdsPersisted,
|
|
3460
5018
|
setSelectedMeasurement,
|
|
3461
5019
|
setSelectedMeasurements,
|
|
3462
|
-
setStart
|
|
5020
|
+
setStart,
|
|
5021
|
+
textInspector,
|
|
5022
|
+
toolMode
|
|
3463
5023
|
]);
|
|
3464
5024
|
const removeSelectedGuides = useCallback6(() => {
|
|
3465
5025
|
if (selectedGuideIds.length === 0) return false;
|
|
3466
5026
|
recordSnapshot();
|
|
3467
|
-
|
|
5027
|
+
setGuidesPersisted(
|
|
3468
5028
|
(prev) => prev.filter((guide) => !selectedGuideIds.includes(guide.id))
|
|
3469
5029
|
);
|
|
3470
|
-
|
|
5030
|
+
setSelectedGuideIdsPersisted([]);
|
|
3471
5031
|
return true;
|
|
3472
|
-
}, [
|
|
5032
|
+
}, [
|
|
5033
|
+
recordSnapshot,
|
|
5034
|
+
selectedGuideIds,
|
|
5035
|
+
setGuidesPersisted,
|
|
5036
|
+
setSelectedGuideIdsPersisted
|
|
5037
|
+
]);
|
|
3473
5038
|
useHotkeys({
|
|
5039
|
+
eventTarget: ownerWindow,
|
|
3474
5040
|
clearAll,
|
|
5041
|
+
undo,
|
|
5042
|
+
redo,
|
|
3475
5043
|
removeSelectedGuides,
|
|
3476
5044
|
setEnabled: setEnabledWithHistory,
|
|
3477
5045
|
setToolMode: setToolModeWithHistory,
|
|
5046
|
+
setRulersVisible: setRulersVisiblePersisted,
|
|
3478
5047
|
setAltPressed,
|
|
3479
5048
|
isOverlayActive: () => enabled && (toolMode !== "none" || toolbarActive),
|
|
3480
5049
|
setGuideOrientation: setGuideOrientationWithHistory,
|
|
3481
5050
|
onInteract: () => setToolbarActive(true)
|
|
3482
5051
|
});
|
|
3483
5052
|
useResizeSync({
|
|
3484
|
-
|
|
3485
|
-
|
|
3486
|
-
|
|
5053
|
+
document: ownerDocument,
|
|
5054
|
+
window: ownerWindow,
|
|
5055
|
+
setMeasurements: setMeasurementsPersisted,
|
|
5056
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5057
|
+
setHeldDistances: setHeldDistancesPersisted,
|
|
3487
5058
|
setSelectedMeasurement,
|
|
3488
|
-
setGuides,
|
|
5059
|
+
setGuides: setGuidesPersisted,
|
|
3489
5060
|
selectedElementRef
|
|
3490
5061
|
});
|
|
5062
|
+
useEffect5(() => {
|
|
5063
|
+
const handleScroll = () => {
|
|
5064
|
+
const next = {
|
|
5065
|
+
x: ownerWindow.scrollX,
|
|
5066
|
+
y: ownerWindow.scrollY
|
|
5067
|
+
};
|
|
5068
|
+
const deltaX = next.x - guideScrollRef.current.x;
|
|
5069
|
+
const deltaY = next.y - guideScrollRef.current.y;
|
|
5070
|
+
guideScrollRef.current = next;
|
|
5071
|
+
if (deltaX === 0 && deltaY === 0) return;
|
|
5072
|
+
setGuidesPersisted(
|
|
5073
|
+
(prev) => prev.map((guide) => ({
|
|
5074
|
+
...guide,
|
|
5075
|
+
position: guide.position - (guide.orientation === "vertical" ? deltaX : deltaY)
|
|
5076
|
+
}))
|
|
5077
|
+
);
|
|
5078
|
+
};
|
|
5079
|
+
ownerWindow.addEventListener("scroll", handleScroll, true);
|
|
5080
|
+
return () => ownerWindow.removeEventListener("scroll", handleScroll, true);
|
|
5081
|
+
}, [ownerWindow, setGuidesPersisted]);
|
|
3491
5082
|
useLiveElementTracking({
|
|
5083
|
+
document: ownerDocument,
|
|
5084
|
+
window: ownerWindow,
|
|
3492
5085
|
enabled,
|
|
3493
5086
|
selectedElementRef,
|
|
3494
5087
|
hoverElementRef,
|
|
3495
5088
|
setSelectedMeasurement,
|
|
3496
5089
|
setSelectedMeasurements,
|
|
3497
5090
|
setHoverRect,
|
|
3498
|
-
setMeasurements,
|
|
3499
|
-
setActiveMeasurement,
|
|
3500
|
-
setHeldDistances
|
|
5091
|
+
setMeasurements: setMeasurementsPersisted,
|
|
5092
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5093
|
+
setHeldDistances: setHeldDistancesPersisted
|
|
3501
5094
|
});
|
|
3502
|
-
|
|
5095
|
+
useEffect5(() => {
|
|
3503
5096
|
if (!toolbarActive || toolMode !== "none") return;
|
|
3504
5097
|
const handlePointerDown2 = (event) => {
|
|
3505
5098
|
const toolbarNode = toolbarRef.current;
|
|
3506
5099
|
if (toolbarNode && toolbarNode.contains(event.target)) return;
|
|
3507
5100
|
setToolbarActive(false);
|
|
3508
5101
|
};
|
|
3509
|
-
|
|
5102
|
+
ownerWindow.addEventListener("pointerdown", handlePointerDown2);
|
|
3510
5103
|
return () => {
|
|
3511
|
-
|
|
5104
|
+
ownerWindow.removeEventListener("pointerdown", handlePointerDown2);
|
|
3512
5105
|
};
|
|
3513
|
-
}, [toolbarActive, toolMode]);
|
|
3514
|
-
|
|
3515
|
-
if (
|
|
3516
|
-
|
|
3517
|
-
|
|
3518
|
-
|
|
5106
|
+
}, [ownerWindow, toolbarActive, toolMode]);
|
|
5107
|
+
useEffect5(() => {
|
|
5108
|
+
if (!enabled) return;
|
|
5109
|
+
const handleGuidePointerDown2 = (event) => {
|
|
5110
|
+
if (toolbarRef.current?.contains(event.target)) return;
|
|
5111
|
+
const guideTarget = event.composedPath().some(
|
|
5112
|
+
(target) => target instanceof ownerWindow.Element && target.hasAttribute("data-mesurer-guide")
|
|
5113
|
+
);
|
|
5114
|
+
if (guideTarget && toolMode !== "none") return;
|
|
5115
|
+
const point = { x: event.clientX, y: event.clientY };
|
|
5116
|
+
const guide = guides.find((candidate) => {
|
|
5117
|
+
const distance = candidate.orientation === "vertical" ? Math.abs(candidate.position - point.x) : Math.abs(candidate.position - point.y);
|
|
5118
|
+
return distance <= GUIDE_HITBOX_SIZE / 2;
|
|
5119
|
+
});
|
|
5120
|
+
if (!guide) return;
|
|
5121
|
+
if (event.button === 0 && !event.shiftKey && toolMode === "none") {
|
|
5122
|
+
guideDragRef.current = {
|
|
5123
|
+
id: guide.id,
|
|
5124
|
+
orientation: guide.orientation,
|
|
5125
|
+
pointerId: event.pointerId,
|
|
5126
|
+
commit: createActionCommit(),
|
|
5127
|
+
committed: false
|
|
5128
|
+
};
|
|
5129
|
+
}
|
|
5130
|
+
setSelectedGuideIdsPersisted(
|
|
5131
|
+
(prev) => event.shiftKey ? prev.includes(guide.id) ? prev.filter((id) => id !== guide.id) : [...prev, guide.id] : [guide.id]
|
|
5132
|
+
);
|
|
5133
|
+
};
|
|
5134
|
+
const handleGuidePointerMove = (event) => {
|
|
5135
|
+
const drag = guideDragRef.current;
|
|
5136
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
5137
|
+
const position = drag.orientation === "vertical" ? event.clientX : event.clientY;
|
|
5138
|
+
if (!drag.committed) {
|
|
5139
|
+
event.preventDefault();
|
|
5140
|
+
if (guideUserSelectRef.current === null) {
|
|
5141
|
+
guideUserSelectRef.current = ownerDocument.documentElement.style.userSelect;
|
|
5142
|
+
ownerDocument.documentElement.style.userSelect = "none";
|
|
5143
|
+
}
|
|
5144
|
+
ownerWindow.getSelection()?.removeAllRanges();
|
|
5145
|
+
drag.commit();
|
|
5146
|
+
drag.committed = true;
|
|
5147
|
+
}
|
|
5148
|
+
setGuidesPersisted(
|
|
5149
|
+
(prev) => prev.map(
|
|
5150
|
+
(guide) => guide.id === drag.id ? { ...guide, position } : guide
|
|
5151
|
+
)
|
|
5152
|
+
);
|
|
5153
|
+
};
|
|
5154
|
+
const handleGuidePointerEnd = (event) => {
|
|
5155
|
+
if (guideDragRef.current?.pointerId === event.pointerId) {
|
|
5156
|
+
guideDragRef.current = null;
|
|
5157
|
+
if (guideUserSelectRef.current !== null) {
|
|
5158
|
+
ownerDocument.documentElement.style.userSelect = guideUserSelectRef.current;
|
|
5159
|
+
guideUserSelectRef.current = null;
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
};
|
|
5163
|
+
ownerWindow.addEventListener("pointerdown", handleGuidePointerDown2, true);
|
|
5164
|
+
ownerWindow.addEventListener("pointermove", handleGuidePointerMove, true);
|
|
5165
|
+
ownerWindow.addEventListener("pointerup", handleGuidePointerEnd, true);
|
|
5166
|
+
ownerWindow.addEventListener("pointercancel", handleGuidePointerEnd, true);
|
|
5167
|
+
return () => {
|
|
5168
|
+
ownerWindow.removeEventListener(
|
|
5169
|
+
"pointerdown",
|
|
5170
|
+
handleGuidePointerDown2,
|
|
5171
|
+
true
|
|
5172
|
+
);
|
|
5173
|
+
ownerWindow.removeEventListener("pointermove", handleGuidePointerMove, true);
|
|
5174
|
+
ownerWindow.removeEventListener("pointerup", handleGuidePointerEnd, true);
|
|
5175
|
+
ownerWindow.removeEventListener(
|
|
5176
|
+
"pointercancel",
|
|
5177
|
+
handleGuidePointerEnd,
|
|
5178
|
+
true
|
|
5179
|
+
);
|
|
5180
|
+
if (guideUserSelectRef.current !== null) {
|
|
5181
|
+
ownerDocument.documentElement.style.userSelect = guideUserSelectRef.current;
|
|
5182
|
+
guideUserSelectRef.current = null;
|
|
5183
|
+
}
|
|
5184
|
+
};
|
|
5185
|
+
}, [
|
|
5186
|
+
createActionCommit,
|
|
5187
|
+
enabled,
|
|
5188
|
+
guides,
|
|
5189
|
+
ownerWindow,
|
|
5190
|
+
setGuidesPersisted,
|
|
5191
|
+
setSelectedGuideIdsPersisted,
|
|
5192
|
+
toolMode
|
|
5193
|
+
]);
|
|
5194
|
+
useEffect5(() => {
|
|
5195
|
+
if (toolMode === "text-inspector") {
|
|
5196
|
+
textInspector.enable();
|
|
5197
|
+
} else {
|
|
5198
|
+
textInspector.disable();
|
|
5199
|
+
}
|
|
5200
|
+
}, [textInspector, toolMode]);
|
|
5201
|
+
useEffect5(() => {
|
|
5202
|
+
let style = ownerDocument.getElementById(XRAY_STYLE_ID);
|
|
5203
|
+
if (!style) {
|
|
5204
|
+
style = ownerDocument.createElement("style");
|
|
5205
|
+
style.id = XRAY_STYLE_ID;
|
|
5206
|
+
style.textContent = XRAY_STYLES;
|
|
5207
|
+
ownerDocument.head.appendChild(style);
|
|
5208
|
+
}
|
|
5209
|
+
if (toolMode === "xray") {
|
|
5210
|
+
ownerDocument.body.classList.add("xray-mode");
|
|
5211
|
+
} else {
|
|
5212
|
+
ownerDocument.body.classList.remove("xray-mode");
|
|
5213
|
+
}
|
|
5214
|
+
return () => {
|
|
5215
|
+
ownerDocument.body.classList.remove("xray-mode");
|
|
5216
|
+
};
|
|
5217
|
+
}, [ownerDocument, toolMode]);
|
|
5218
|
+
useEffect5(() => {
|
|
5219
|
+
return () => {
|
|
5220
|
+
textInspector.destroy();
|
|
5221
|
+
};
|
|
5222
|
+
}, [textInspector]);
|
|
5223
|
+
useEffect5(() => {
|
|
3519
5224
|
const hasSelectionAnimationState = !!selectionOriginRect || !!selectedMeasurement?.originRect || selectedMeasurements.some((measurement) => !!measurement.originRect);
|
|
3520
5225
|
if (!hasSelectionAnimationState) {
|
|
3521
5226
|
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
@@ -3544,6 +5249,12 @@ function MeasurerClient({
|
|
|
3544
5249
|
return changed ? next : prev;
|
|
3545
5250
|
});
|
|
3546
5251
|
}, MEASURE_TRANSITION_MS);
|
|
5252
|
+
return () => {
|
|
5253
|
+
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
5254
|
+
window.clearTimeout(selectionAnimationCleanupTimeoutRef.current);
|
|
5255
|
+
selectionAnimationCleanupTimeoutRef.current = null;
|
|
5256
|
+
}
|
|
5257
|
+
};
|
|
3547
5258
|
}, [
|
|
3548
5259
|
selectionOriginRect,
|
|
3549
5260
|
selectedMeasurement,
|
|
@@ -3552,13 +5263,6 @@ function MeasurerClient({
|
|
|
3552
5263
|
setSelectedMeasurements,
|
|
3553
5264
|
setSelectionOriginRect
|
|
3554
5265
|
]);
|
|
3555
|
-
useEffect9(() => {
|
|
3556
|
-
return () => {
|
|
3557
|
-
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
3558
|
-
window.clearTimeout(selectionAnimationCleanupTimeoutRef.current);
|
|
3559
|
-
}
|
|
3560
|
-
};
|
|
3561
|
-
}, []);
|
|
3562
5266
|
const displayedMeasurements = holdEnabled ? measurements : multiMeasureEnabled && measurements.length > 0 ? measurements : activeMeasurement ? [activeMeasurement] : [];
|
|
3563
5267
|
const {
|
|
3564
5268
|
activeRect,
|
|
@@ -3580,6 +5284,8 @@ function MeasurerClient({
|
|
|
3580
5284
|
hoverEdgeVisibility,
|
|
3581
5285
|
measurementEdgeVisibility
|
|
3582
5286
|
} = useMeasurerDerived({
|
|
5287
|
+
document: ownerDocument,
|
|
5288
|
+
window: ownerWindow,
|
|
3583
5289
|
start,
|
|
3584
5290
|
end,
|
|
3585
5291
|
selectedMeasurements,
|
|
@@ -3605,6 +5311,8 @@ function MeasurerClient({
|
|
|
3605
5311
|
handlePointerUp,
|
|
3606
5312
|
handlePointerLeave
|
|
3607
5313
|
} = useMeasurerPointer({
|
|
5314
|
+
document: ownerDocument,
|
|
5315
|
+
window: ownerWindow,
|
|
3608
5316
|
toolbarRef,
|
|
3609
5317
|
overlayRef,
|
|
3610
5318
|
selectionRectRef,
|
|
@@ -3630,15 +5338,15 @@ function MeasurerClient({
|
|
|
3630
5338
|
optionPairOverlay,
|
|
3631
5339
|
setAltPressed,
|
|
3632
5340
|
setGuidePreview,
|
|
3633
|
-
setSelectedGuideIds,
|
|
3634
|
-
setGuides,
|
|
5341
|
+
setSelectedGuideIds: setSelectedGuideIdsPersisted,
|
|
5342
|
+
setGuides: setGuidesPersisted,
|
|
3635
5343
|
setStart,
|
|
3636
5344
|
setEnd,
|
|
3637
5345
|
setIsDragging,
|
|
3638
|
-
setHeldDistances,
|
|
5346
|
+
setHeldDistances: setHeldDistancesPersisted,
|
|
3639
5347
|
setDraggingGuideId,
|
|
3640
|
-
setActiveMeasurement,
|
|
3641
|
-
setMeasurements,
|
|
5348
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5349
|
+
setMeasurements: setMeasurementsPersisted,
|
|
3642
5350
|
setSelectedMeasurements,
|
|
3643
5351
|
setSelectedMeasurement,
|
|
3644
5352
|
setSelectionOriginRect,
|
|
@@ -3651,24 +5359,62 @@ function MeasurerClient({
|
|
|
3651
5359
|
const removeHeldDistance = useCallback6(
|
|
3652
5360
|
(id) => {
|
|
3653
5361
|
recordSnapshot();
|
|
3654
|
-
|
|
5362
|
+
setHeldDistancesPersisted(
|
|
5363
|
+
(prev) => prev.filter((distance) => distance.id !== id)
|
|
5364
|
+
);
|
|
5365
|
+
},
|
|
5366
|
+
[recordSnapshot, setHeldDistancesPersisted]
|
|
5367
|
+
);
|
|
5368
|
+
const startGuideFromRuler = useCallback6(
|
|
5369
|
+
(orientation, position) => {
|
|
5370
|
+
const id = createId();
|
|
5371
|
+
const commit = createActionCommit();
|
|
5372
|
+
commit();
|
|
5373
|
+
setSelectedGuideIdsPersisted([]);
|
|
5374
|
+
setGuidesPersisted((prev) => [...prev, { id, orientation, position }]);
|
|
5375
|
+
return id;
|
|
5376
|
+
},
|
|
5377
|
+
[
|
|
5378
|
+
createActionCommit,
|
|
5379
|
+
setGuidesPersisted,
|
|
5380
|
+
setSelectedGuideIdsPersisted
|
|
5381
|
+
]
|
|
5382
|
+
);
|
|
5383
|
+
const moveGuideFromRuler = useCallback6(
|
|
5384
|
+
(id, position) => {
|
|
5385
|
+
setGuidesPersisted(
|
|
5386
|
+
(prev) => prev.map((guide) => guide.id === id ? { ...guide, position } : guide)
|
|
5387
|
+
);
|
|
5388
|
+
},
|
|
5389
|
+
[setGuidesPersisted]
|
|
5390
|
+
);
|
|
5391
|
+
const finishGuideFromRuler = useCallback6(
|
|
5392
|
+
(id) => {
|
|
5393
|
+
setSelectedGuideIdsPersisted([id]);
|
|
5394
|
+
},
|
|
5395
|
+
[setSelectedGuideIdsPersisted]
|
|
5396
|
+
);
|
|
5397
|
+
const cancelGuideFromRuler = useCallback6(
|
|
5398
|
+
(id) => {
|
|
5399
|
+
setGuidesPersisted((prev) => prev.filter((guide) => guide.id !== id));
|
|
3655
5400
|
},
|
|
3656
|
-
[
|
|
5401
|
+
[setGuidesPersisted]
|
|
3657
5402
|
);
|
|
3658
5403
|
const handleGuidePointerDown = useCallback6(
|
|
3659
5404
|
(guide, event) => {
|
|
3660
5405
|
const commit = createActionCommit();
|
|
3661
5406
|
if (!enabled) return;
|
|
3662
5407
|
event.stopPropagation();
|
|
5408
|
+
event.preventDefault();
|
|
3663
5409
|
if (event.shiftKey) {
|
|
3664
5410
|
commit();
|
|
3665
|
-
|
|
5411
|
+
setSelectedGuideIdsPersisted(
|
|
3666
5412
|
(prev) => prev.includes(guide.id) ? prev.filter((id) => id !== guide.id) : [...prev, guide.id]
|
|
3667
5413
|
);
|
|
3668
5414
|
return;
|
|
3669
5415
|
}
|
|
3670
5416
|
commit();
|
|
3671
|
-
|
|
5417
|
+
setSelectedGuideIdsPersisted([guide.id]);
|
|
3672
5418
|
scheduleGuideDragHold(guide.id, setDraggingGuideId);
|
|
3673
5419
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
3674
5420
|
},
|
|
@@ -3677,7 +5423,7 @@ function MeasurerClient({
|
|
|
3677
5423
|
enabled,
|
|
3678
5424
|
scheduleGuideDragHold,
|
|
3679
5425
|
setDraggingGuideId,
|
|
3680
|
-
|
|
5426
|
+
setSelectedGuideIdsPersisted
|
|
3681
5427
|
]
|
|
3682
5428
|
);
|
|
3683
5429
|
const handleGuidePointerUp = useCallback6(
|
|
@@ -3692,17 +5438,29 @@ function MeasurerClient({
|
|
|
3692
5438
|
[clearGuideDragHold, setDraggingGuideId]
|
|
3693
5439
|
);
|
|
3694
5440
|
return createPortal(
|
|
3695
|
-
/* @__PURE__ */
|
|
5441
|
+
/* @__PURE__ */ jsxs7(
|
|
3696
5442
|
"div",
|
|
3697
5443
|
{
|
|
3698
5444
|
ref: overlayRef,
|
|
3699
5445
|
className: "mesurer-root msr:pointer-events-none msr:fixed msr:inset-0 msr:z-50",
|
|
3700
5446
|
children: [
|
|
3701
|
-
/* @__PURE__ */
|
|
5447
|
+
enabled && rulersVisible ? /* @__PURE__ */ jsx9(
|
|
5448
|
+
RulersOverlay,
|
|
5449
|
+
{
|
|
5450
|
+
onStartGuide: startGuideFromRuler,
|
|
5451
|
+
onMoveGuide: moveGuideFromRuler,
|
|
5452
|
+
onFinishGuide: finishGuideFromRuler,
|
|
5453
|
+
onCancelGuide: cancelGuideFromRuler,
|
|
5454
|
+
guides,
|
|
5455
|
+
selectedGuideIds
|
|
5456
|
+
}
|
|
5457
|
+
) : null,
|
|
5458
|
+
/* @__PURE__ */ jsx9(
|
|
3702
5459
|
MeasurerOverlay,
|
|
3703
5460
|
{
|
|
3704
5461
|
enabled,
|
|
3705
5462
|
toolMode,
|
|
5463
|
+
guidePointerEvents: enabled && (toolMode !== "none" || rulersVisible),
|
|
3706
5464
|
guidesEnabled,
|
|
3707
5465
|
altPressed,
|
|
3708
5466
|
isDragging,
|
|
@@ -3740,13 +5498,16 @@ function MeasurerClient({
|
|
|
3740
5498
|
onGuidePointerCancel: handleGuidePointerUp
|
|
3741
5499
|
}
|
|
3742
5500
|
),
|
|
3743
|
-
/* @__PURE__ */
|
|
5501
|
+
/* @__PURE__ */ jsx9(
|
|
3744
5502
|
Toolbar,
|
|
3745
5503
|
{
|
|
3746
5504
|
ref: toolbarRef,
|
|
5505
|
+
eventTarget: ownerWindow,
|
|
3747
5506
|
toolMode,
|
|
3748
5507
|
setEnabled: setEnabledWithHistory,
|
|
3749
5508
|
setToolMode: setToolModeWithHistory,
|
|
5509
|
+
rulersVisible,
|
|
5510
|
+
setRulersVisible: setRulersVisiblePersisted,
|
|
3750
5511
|
guideOrientation,
|
|
3751
5512
|
setGuideOrientation: setGuideOrientationWithHistory,
|
|
3752
5513
|
onInteract: () => setToolbarActive(true)
|
|
@@ -3763,24 +5524,28 @@ function Measurer({
|
|
|
3763
5524
|
guideColor = "oklch(0.63 0.26 29.23)",
|
|
3764
5525
|
hoverHighlightEnabled = true,
|
|
3765
5526
|
persistOnReload = false,
|
|
3766
|
-
portalTarget
|
|
5527
|
+
portalTarget,
|
|
5528
|
+
persistKey
|
|
3767
5529
|
}) {
|
|
3768
5530
|
if (typeof document !== "undefined") {
|
|
3769
5531
|
ensureMeasurerStyles(MESURER_STYLES, portalTarget);
|
|
3770
5532
|
}
|
|
3771
5533
|
const hydrated = useHydrated();
|
|
3772
5534
|
if (!hydrated) return null;
|
|
3773
|
-
return /* @__PURE__ */
|
|
5535
|
+
return /* @__PURE__ */ jsx9(
|
|
3774
5536
|
MeasurerClient,
|
|
3775
5537
|
{
|
|
3776
5538
|
highlightColor,
|
|
3777
5539
|
guideColor,
|
|
3778
5540
|
hoverHighlightEnabled,
|
|
3779
5541
|
persistOnReload,
|
|
5542
|
+
persistKey,
|
|
3780
5543
|
portalTarget: portalTarget ?? document.body
|
|
3781
5544
|
}
|
|
3782
5545
|
);
|
|
3783
5546
|
}
|
|
3784
5547
|
export {
|
|
3785
|
-
Measurer
|
|
5548
|
+
Measurer,
|
|
5549
|
+
TextInspector,
|
|
5550
|
+
createTextInspector
|
|
3786
5551
|
};
|