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.cjs
CHANGED
|
@@ -20,15 +20,17 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
-
Measurer: () => Measurer
|
|
23
|
+
Measurer: () => Measurer,
|
|
24
|
+
TextInspector: () => TextInspector,
|
|
25
|
+
createTextInspector: () => createTextInspector
|
|
24
26
|
});
|
|
25
27
|
module.exports = __toCommonJS(index_exports);
|
|
26
28
|
|
|
27
29
|
// measurer.tsx
|
|
28
|
-
var
|
|
30
|
+
var import_react20 = require("react");
|
|
29
31
|
var import_react_dom = require("react-dom");
|
|
30
32
|
|
|
31
|
-
// constants.ts
|
|
33
|
+
// core/constants.ts
|
|
32
34
|
var MEASURE_LABEL_OFFSET = 2;
|
|
33
35
|
var GUIDE_SNAP_DISTANCE = 10;
|
|
34
36
|
var GUIDE_HITBOX_SIZE = 14;
|
|
@@ -41,15 +43,17 @@ var ANCESTOR_KEEP_COVERAGE = 0.92;
|
|
|
41
43
|
var MIN_SINGLE_TARGET_SIZE = 8;
|
|
42
44
|
var MIN_SINGLE_ELEMENT_COVERAGE = 0.15;
|
|
43
45
|
|
|
44
|
-
// style-inject.ts
|
|
46
|
+
// runtime/style-inject.ts
|
|
45
47
|
var MESURER_STYLE_ID = "mesurer-styles";
|
|
48
|
+
var isDocument = (target) => target.nodeType === 9;
|
|
49
|
+
var isShadowRoot = (target) => target.nodeType === 11;
|
|
46
50
|
var getStyleTarget = (target) => {
|
|
47
51
|
if (typeof document === "undefined") return null;
|
|
48
52
|
if (!target) return document;
|
|
49
|
-
if (target
|
|
53
|
+
if (isShadowRoot(target)) return target;
|
|
50
54
|
const rootNode = target.getRootNode();
|
|
51
|
-
if (rootNode
|
|
52
|
-
return document;
|
|
55
|
+
if (rootNode.nodeType === 11) return rootNode;
|
|
56
|
+
return target.ownerDocument ?? document;
|
|
53
57
|
};
|
|
54
58
|
function ensureMeasurerStyles(cssText, target) {
|
|
55
59
|
if (typeof document === "undefined") return;
|
|
@@ -57,23 +61,25 @@ function ensureMeasurerStyles(cssText, target) {
|
|
|
57
61
|
const styleTarget = getStyleTarget(target);
|
|
58
62
|
if (!styleTarget) return;
|
|
59
63
|
if (styleTarget.querySelector(`#${MESURER_STYLE_ID}`)) return;
|
|
60
|
-
const
|
|
64
|
+
const ownerDocument = isDocument(styleTarget) ? styleTarget : styleTarget.ownerDocument;
|
|
65
|
+
if (!ownerDocument) return;
|
|
66
|
+
const style = ownerDocument.createElement("style");
|
|
61
67
|
style.id = MESURER_STYLE_ID;
|
|
62
68
|
style.textContent = cssText;
|
|
63
|
-
if (styleTarget
|
|
69
|
+
if (isShadowRoot(styleTarget)) {
|
|
64
70
|
styleTarget.appendChild(style);
|
|
65
71
|
return;
|
|
66
72
|
}
|
|
67
|
-
|
|
73
|
+
ownerDocument.head.appendChild(style);
|
|
68
74
|
}
|
|
69
75
|
|
|
70
76
|
// styles.generated.ts
|
|
71
|
-
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';
|
|
77
|
+
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';
|
|
72
78
|
|
|
73
79
|
// components/toolbar.tsx
|
|
74
80
|
var import_react = require("react");
|
|
75
81
|
|
|
76
|
-
// utils.ts
|
|
82
|
+
// core/utils.ts
|
|
77
83
|
var formatValue = (value) => Math.round(value);
|
|
78
84
|
var cn = (...inputs) => inputs.filter(Boolean).join(" ");
|
|
79
85
|
var createId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`;
|
|
@@ -93,9 +99,57 @@ var IconBase = ({ size = 24, ...props }) => /* @__PURE__ */ (0, import_jsx_runti
|
|
|
93
99
|
);
|
|
94
100
|
var CursorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) });
|
|
95
101
|
var RulerIcon = ({ size = 20, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) });
|
|
102
|
+
var XrayIcon = ({ size = 20, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
103
|
+
"path",
|
|
104
|
+
{
|
|
105
|
+
fill: "none",
|
|
106
|
+
stroke: "currentColor",
|
|
107
|
+
strokeLinecap: "round",
|
|
108
|
+
strokeLinejoin: "round",
|
|
109
|
+
strokeWidth: "12",
|
|
110
|
+
strokeOpacity: "0.78",
|
|
111
|
+
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"
|
|
112
|
+
}
|
|
113
|
+
) });
|
|
114
|
+
var RulersIcon = ({ size = 20, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
115
|
+
"path",
|
|
116
|
+
{
|
|
117
|
+
fill: "none",
|
|
118
|
+
stroke: "currentColor",
|
|
119
|
+
strokeLinecap: "round",
|
|
120
|
+
strokeLinejoin: "round",
|
|
121
|
+
strokeWidth: "12",
|
|
122
|
+
d: "M48 208V48h160M80 48v24m32-24v24m32-24v24m32-24v24M48 80h24M48 112h24m-24 32h24m-24 32h24"
|
|
123
|
+
}
|
|
124
|
+
) });
|
|
96
125
|
var CaretDownIcon = ({ size = 8, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) });
|
|
97
126
|
var CheckIcon = ({ size = 12, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.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" }) });
|
|
98
127
|
var MinusIcon = ({ size = 12, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(IconBase, { size, ...props, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z" }) });
|
|
128
|
+
var TextInspectorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
129
|
+
"svg",
|
|
130
|
+
{
|
|
131
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
132
|
+
width: size,
|
|
133
|
+
height: size,
|
|
134
|
+
viewBox: "0 0 256 256",
|
|
135
|
+
fill: "currentColor",
|
|
136
|
+
...props,
|
|
137
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
138
|
+
"text",
|
|
139
|
+
{
|
|
140
|
+
x: "50%",
|
|
141
|
+
y: "60%",
|
|
142
|
+
textAnchor: "middle",
|
|
143
|
+
dominantBaseline: "middle",
|
|
144
|
+
fill: "currentColor",
|
|
145
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif",
|
|
146
|
+
fontWeight: 300,
|
|
147
|
+
fontSize: 220,
|
|
148
|
+
children: "Aa"
|
|
149
|
+
}
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
);
|
|
99
153
|
|
|
100
154
|
// components/toolbar.tsx
|
|
101
155
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
@@ -110,6 +164,7 @@ function ToolbarButton({
|
|
|
110
164
|
shortcut,
|
|
111
165
|
onClick,
|
|
112
166
|
tooltipVisible,
|
|
167
|
+
tooltipInstant,
|
|
113
168
|
tooltipSide,
|
|
114
169
|
onTooltipEnter,
|
|
115
170
|
onTooltipLeave,
|
|
@@ -127,6 +182,7 @@ function ToolbarButton({
|
|
|
127
182
|
{
|
|
128
183
|
type: "button",
|
|
129
184
|
"aria-label": `${label} (${shortcut})`,
|
|
185
|
+
"aria-pressed": active,
|
|
130
186
|
title: `${label} (${shortcut})`,
|
|
131
187
|
className: cn(
|
|
132
188
|
"msr:flex msr:size-8 msr:items-center msr:justify-center msr:rounded-[8px] msr:outline-none",
|
|
@@ -140,7 +196,10 @@ function ToolbarButton({
|
|
|
140
196
|
"span",
|
|
141
197
|
{
|
|
142
198
|
className: cn(
|
|
143
|
-
|
|
199
|
+
cn(
|
|
200
|
+
"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",
|
|
201
|
+
tooltipInstant && "msr:transition-none"
|
|
202
|
+
),
|
|
144
203
|
tooltipSide === "top" ? "msr:bottom-full msr:mb-2" : "msr:top-full msr:mt-2",
|
|
145
204
|
tooltipVisible ? "msr:opacity-100" : "msr:opacity-0"
|
|
146
205
|
),
|
|
@@ -159,6 +218,7 @@ function useToolbarTooltip() {
|
|
|
159
218
|
const [visibleTooltipId, setVisibleTooltipId] = (0, import_react.useState)(null);
|
|
160
219
|
const timerRef = (0, import_react.useRef)(null);
|
|
161
220
|
const instantRef = (0, import_react.useRef)(false);
|
|
221
|
+
const [tooltipInstant, setTooltipInstant] = (0, import_react.useState)(false);
|
|
162
222
|
const clearTimer = (0, import_react.useCallback)(() => {
|
|
163
223
|
if (timerRef.current === null) return;
|
|
164
224
|
window.clearTimeout(timerRef.current);
|
|
@@ -168,9 +228,11 @@ function useToolbarTooltip() {
|
|
|
168
228
|
(id) => {
|
|
169
229
|
clearTimer();
|
|
170
230
|
if (instantRef.current) {
|
|
231
|
+
setTooltipInstant(true);
|
|
171
232
|
setVisibleTooltipId(id);
|
|
172
233
|
return;
|
|
173
234
|
}
|
|
235
|
+
setTooltipInstant(false);
|
|
174
236
|
timerRef.current = window.setTimeout(() => {
|
|
175
237
|
setVisibleTooltipId(id);
|
|
176
238
|
instantRef.current = true;
|
|
@@ -190,15 +252,17 @@ function useToolbarTooltip() {
|
|
|
190
252
|
clearTimer();
|
|
191
253
|
setVisibleTooltipId(null);
|
|
192
254
|
instantRef.current = false;
|
|
255
|
+
setTooltipInstant(false);
|
|
193
256
|
}, [clearTimer]);
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
257
|
+
return {
|
|
258
|
+
visibleTooltipId,
|
|
259
|
+
tooltipInstant,
|
|
260
|
+
onTooltipEnter,
|
|
261
|
+
onTooltipLeave,
|
|
262
|
+
onToolbarLeave
|
|
263
|
+
};
|
|
200
264
|
}
|
|
201
|
-
function useToolbarDrag(initialPosition) {
|
|
265
|
+
function useToolbarDrag(initialPosition, eventTarget) {
|
|
202
266
|
const [position, setPosition] = (0, import_react.useState)(initialPosition);
|
|
203
267
|
const suppressClickRef = (0, import_react.useRef)(false);
|
|
204
268
|
const detachListenersRef = (0, import_react.useRef)(null);
|
|
@@ -241,8 +305,8 @@ function useToolbarDrag(initialPosition) {
|
|
|
241
305
|
}
|
|
242
306
|
if (!current.active) return;
|
|
243
307
|
current.didDrag = true;
|
|
244
|
-
const maxX = Math.max(8,
|
|
245
|
-
const maxY = Math.max(8,
|
|
308
|
+
const maxX = Math.max(8, eventTarget.innerWidth - current.width - 8);
|
|
309
|
+
const maxY = Math.max(8, eventTarget.innerHeight - current.height - 8);
|
|
246
310
|
setPosition({
|
|
247
311
|
x: Math.min(maxX, Math.max(8, current.originX + dx)),
|
|
248
312
|
y: Math.min(maxY, Math.max(8, current.originY + dy))
|
|
@@ -256,21 +320,21 @@ function useToolbarDrag(initialPosition) {
|
|
|
256
320
|
current.active = false;
|
|
257
321
|
current.didDrag = false;
|
|
258
322
|
current.pointerId = -1;
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
323
|
+
eventTarget.removeEventListener("pointermove", handlePointerMove);
|
|
324
|
+
eventTarget.removeEventListener("pointerup", handlePointerEnd);
|
|
325
|
+
eventTarget.removeEventListener("pointercancel", handlePointerEnd);
|
|
262
326
|
detachListenersRef.current = null;
|
|
263
327
|
};
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
328
|
+
eventTarget.addEventListener("pointermove", handlePointerMove);
|
|
329
|
+
eventTarget.addEventListener("pointerup", handlePointerEnd);
|
|
330
|
+
eventTarget.addEventListener("pointercancel", handlePointerEnd);
|
|
267
331
|
detachListenersRef.current = () => {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
332
|
+
eventTarget.removeEventListener("pointermove", handlePointerMove);
|
|
333
|
+
eventTarget.removeEventListener("pointerup", handlePointerEnd);
|
|
334
|
+
eventTarget.removeEventListener("pointercancel", handlePointerEnd);
|
|
271
335
|
};
|
|
272
336
|
},
|
|
273
|
-
[position.x, position.y]
|
|
337
|
+
[eventTarget, position.x, position.y]
|
|
274
338
|
);
|
|
275
339
|
const onClickCapture = (0, import_react.useCallback)(
|
|
276
340
|
(event) => {
|
|
@@ -287,15 +351,24 @@ function ToolbarComponent({
|
|
|
287
351
|
toolMode,
|
|
288
352
|
setEnabled,
|
|
289
353
|
setToolMode,
|
|
354
|
+
rulersVisible,
|
|
355
|
+
setRulersVisible,
|
|
290
356
|
guideOrientation,
|
|
291
357
|
setGuideOrientation,
|
|
292
|
-
onInteract
|
|
358
|
+
onInteract,
|
|
359
|
+
eventTarget
|
|
293
360
|
}, ref) {
|
|
294
361
|
const { position, onPointerDown, onClickCapture } = useToolbarDrag({
|
|
295
362
|
x: 16,
|
|
296
363
|
y: 16
|
|
297
|
-
});
|
|
298
|
-
const {
|
|
364
|
+
}, eventTarget);
|
|
365
|
+
const {
|
|
366
|
+
visibleTooltipId,
|
|
367
|
+
tooltipInstant,
|
|
368
|
+
onTooltipEnter,
|
|
369
|
+
onTooltipLeave,
|
|
370
|
+
onToolbarLeave
|
|
371
|
+
} = useToolbarTooltip();
|
|
299
372
|
const [guideMenuOpen, setGuideMenuOpen] = (0, import_react.useState)(false);
|
|
300
373
|
const guideMenuRef = (0, import_react.useRef)(null);
|
|
301
374
|
const [activeMenuIndex, setActiveMenuIndex] = (0, import_react.useState)(0);
|
|
@@ -309,13 +382,13 @@ function ToolbarComponent({
|
|
|
309
382
|
setMenuAlign("left");
|
|
310
383
|
return;
|
|
311
384
|
}
|
|
312
|
-
if (leftAlignedRight >
|
|
385
|
+
if (leftAlignedRight > eventTarget.innerWidth - VIEWPORT_PADDING) {
|
|
313
386
|
setMenuAlign("right");
|
|
314
387
|
return;
|
|
315
388
|
}
|
|
316
389
|
setMenuAlign("right");
|
|
317
|
-
}, []);
|
|
318
|
-
const viewportHeight =
|
|
390
|
+
}, [eventTarget]);
|
|
391
|
+
const viewportHeight = eventTarget.innerHeight || 0;
|
|
319
392
|
const nearTop = position.y < 56;
|
|
320
393
|
const nearBottom = viewportHeight > 0 && position.y > viewportHeight - 56;
|
|
321
394
|
const tooltipSide = nearTop && !nearBottom ? "bottom" : "top";
|
|
@@ -330,6 +403,23 @@ function ToolbarComponent({
|
|
|
330
403
|
setToolMode((prev) => prev === "guides" ? "none" : "guides");
|
|
331
404
|
onInteract();
|
|
332
405
|
}, [onInteract, setEnabled, setToolMode]);
|
|
406
|
+
const textInspectorMode = (0, import_react.useCallback)(() => {
|
|
407
|
+
setEnabled(true);
|
|
408
|
+
setToolMode(
|
|
409
|
+
(prev) => prev === "text-inspector" ? "none" : "text-inspector"
|
|
410
|
+
);
|
|
411
|
+
onInteract();
|
|
412
|
+
}, [onInteract, setEnabled, setToolMode]);
|
|
413
|
+
const xrayMode = (0, import_react.useCallback)(() => {
|
|
414
|
+
setEnabled(true);
|
|
415
|
+
setToolMode((prev) => prev === "xray" ? "none" : "xray");
|
|
416
|
+
onInteract();
|
|
417
|
+
}, [onInteract, setEnabled, setToolMode]);
|
|
418
|
+
const rulersMode = (0, import_react.useCallback)(() => {
|
|
419
|
+
setEnabled(true);
|
|
420
|
+
setRulersVisible((prev) => !prev);
|
|
421
|
+
onInteract();
|
|
422
|
+
}, [onInteract, setEnabled, setRulersVisible]);
|
|
333
423
|
const selectGuideOrientation = (0, import_react.useCallback)(
|
|
334
424
|
(orientation) => {
|
|
335
425
|
setEnabled(true);
|
|
@@ -342,7 +432,7 @@ function ToolbarComponent({
|
|
|
342
432
|
);
|
|
343
433
|
(0, import_react.useLayoutEffect)(() => {
|
|
344
434
|
if (!guideMenuOpen) return;
|
|
345
|
-
const frame = requestAnimationFrame(() => {
|
|
435
|
+
const frame = eventTarget.requestAnimationFrame(() => {
|
|
346
436
|
guideMenuRef.current?.querySelector("[role='menu']")?.focus();
|
|
347
437
|
});
|
|
348
438
|
const handlePointerDown = (event) => {
|
|
@@ -355,14 +445,14 @@ function ToolbarComponent({
|
|
|
355
445
|
const handleResize = () => {
|
|
356
446
|
updateMenuAlign();
|
|
357
447
|
};
|
|
358
|
-
|
|
359
|
-
|
|
448
|
+
eventTarget.addEventListener("pointerdown", handlePointerDown);
|
|
449
|
+
eventTarget.addEventListener("resize", handleResize);
|
|
360
450
|
return () => {
|
|
361
|
-
cancelAnimationFrame(frame);
|
|
362
|
-
|
|
363
|
-
|
|
451
|
+
eventTarget.cancelAnimationFrame(frame);
|
|
452
|
+
eventTarget.removeEventListener("pointerdown", handlePointerDown);
|
|
453
|
+
eventTarget.removeEventListener("resize", handleResize);
|
|
364
454
|
};
|
|
365
|
-
}, [guideMenuOpen, guideOrientation, updateMenuAlign]);
|
|
455
|
+
}, [eventTarget, guideMenuOpen, guideOrientation, updateMenuAlign]);
|
|
366
456
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
367
457
|
"div",
|
|
368
458
|
{
|
|
@@ -385,12 +475,61 @@ function ToolbarComponent({
|
|
|
385
475
|
shortcut: "S",
|
|
386
476
|
onClick: selectMode,
|
|
387
477
|
tooltipVisible: visibleTooltipId === "select",
|
|
478
|
+
tooltipInstant,
|
|
388
479
|
tooltipSide,
|
|
389
480
|
onTooltipEnter,
|
|
390
481
|
onTooltipLeave,
|
|
391
482
|
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(CursorIcon, { size: 20 })
|
|
392
483
|
}
|
|
393
484
|
),
|
|
485
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
486
|
+
ToolbarButton,
|
|
487
|
+
{
|
|
488
|
+
id: "xray",
|
|
489
|
+
active: toolMode === "xray",
|
|
490
|
+
label: "X-ray",
|
|
491
|
+
shortcut: "X",
|
|
492
|
+
onClick: xrayMode,
|
|
493
|
+
tooltipVisible: visibleTooltipId === "xray",
|
|
494
|
+
tooltipInstant,
|
|
495
|
+
tooltipSide,
|
|
496
|
+
onTooltipEnter,
|
|
497
|
+
onTooltipLeave,
|
|
498
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(XrayIcon, { size: 20 })
|
|
499
|
+
}
|
|
500
|
+
),
|
|
501
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
502
|
+
ToolbarButton,
|
|
503
|
+
{
|
|
504
|
+
id: "rulers",
|
|
505
|
+
active: rulersVisible,
|
|
506
|
+
label: "Rulers",
|
|
507
|
+
shortcut: "R",
|
|
508
|
+
onClick: rulersMode,
|
|
509
|
+
tooltipVisible: visibleTooltipId === "rulers",
|
|
510
|
+
tooltipInstant,
|
|
511
|
+
tooltipSide,
|
|
512
|
+
onTooltipEnter,
|
|
513
|
+
onTooltipLeave,
|
|
514
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(RulersIcon, { size: 20 })
|
|
515
|
+
}
|
|
516
|
+
),
|
|
517
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
518
|
+
ToolbarButton,
|
|
519
|
+
{
|
|
520
|
+
id: "text-inspector",
|
|
521
|
+
active: toolMode === "text-inspector",
|
|
522
|
+
label: "Text inspector",
|
|
523
|
+
shortcut: "A",
|
|
524
|
+
onClick: textInspectorMode,
|
|
525
|
+
tooltipVisible: visibleTooltipId === "text-inspector",
|
|
526
|
+
tooltipInstant,
|
|
527
|
+
tooltipSide,
|
|
528
|
+
onTooltipEnter,
|
|
529
|
+
onTooltipLeave,
|
|
530
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(TextInspectorIcon, { size: 20, "aria-hidden": "true" })
|
|
531
|
+
}
|
|
532
|
+
),
|
|
394
533
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
395
534
|
ToolbarButton,
|
|
396
535
|
{
|
|
@@ -400,6 +539,7 @@ function ToolbarComponent({
|
|
|
400
539
|
shortcut: "G",
|
|
401
540
|
onClick: guidesMode,
|
|
402
541
|
tooltipVisible: visibleTooltipId === "guides",
|
|
542
|
+
tooltipInstant,
|
|
403
543
|
tooltipSide,
|
|
404
544
|
onTooltipEnter,
|
|
405
545
|
onTooltipLeave,
|
|
@@ -559,32 +699,337 @@ function ToolbarComponent({
|
|
|
559
699
|
}
|
|
560
700
|
var Toolbar = (0, import_react.memo)((0, import_react.forwardRef)(ToolbarComponent));
|
|
561
701
|
|
|
562
|
-
//
|
|
702
|
+
// components/rulers-overlay.tsx
|
|
563
703
|
var import_react2 = require("react");
|
|
704
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
705
|
+
var RULER_SIZE = 18;
|
|
706
|
+
var RULER_LENGTH = 4e3;
|
|
707
|
+
var TICK_STEP = 5;
|
|
708
|
+
var ticks = Array.from(
|
|
709
|
+
{ length: RULER_LENGTH / TICK_STEP + 1 },
|
|
710
|
+
(_, index) => index * TICK_STEP
|
|
711
|
+
);
|
|
712
|
+
var RulersOverlay = (0, import_react2.memo)(function RulersOverlay2({
|
|
713
|
+
onStartGuide,
|
|
714
|
+
onMoveGuide,
|
|
715
|
+
onFinishGuide,
|
|
716
|
+
onCancelGuide,
|
|
717
|
+
guides,
|
|
718
|
+
selectedGuideIds
|
|
719
|
+
}) {
|
|
720
|
+
const [dragPosition, setDragPosition] = (0, import_react2.useState)(null);
|
|
721
|
+
const [dragOrientation, setDragOrientation] = (0, import_react2.useState)(null);
|
|
722
|
+
const dragRef = (0, import_react2.useRef)(null);
|
|
723
|
+
const beginGuideDrag = (orientation, event) => {
|
|
724
|
+
if (event.button !== 0) return;
|
|
725
|
+
event.stopPropagation();
|
|
726
|
+
const position = orientation === "horizontal" ? event.clientY : event.clientX;
|
|
727
|
+
setDragPosition(position);
|
|
728
|
+
setDragOrientation(orientation);
|
|
729
|
+
dragRef.current = {
|
|
730
|
+
orientation,
|
|
731
|
+
pointerId: event.pointerId,
|
|
732
|
+
id: onStartGuide(orientation, position)
|
|
733
|
+
};
|
|
734
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
735
|
+
};
|
|
736
|
+
const moveGuide = (event) => {
|
|
737
|
+
const drag = dragRef.current;
|
|
738
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
739
|
+
event.stopPropagation();
|
|
740
|
+
const position = drag.orientation === "horizontal" ? event.clientY : event.clientX;
|
|
741
|
+
setDragPosition(position);
|
|
742
|
+
onMoveGuide(drag.id, position);
|
|
743
|
+
};
|
|
744
|
+
const finishGuideDrag = (event) => {
|
|
745
|
+
const drag = dragRef.current;
|
|
746
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
747
|
+
event.stopPropagation();
|
|
748
|
+
const position = drag.orientation === "horizontal" ? event.clientY : event.clientX;
|
|
749
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) {
|
|
750
|
+
event.currentTarget.releasePointerCapture(event.pointerId);
|
|
751
|
+
}
|
|
752
|
+
dragRef.current = null;
|
|
753
|
+
setDragPosition(null);
|
|
754
|
+
setDragOrientation(null);
|
|
755
|
+
onMoveGuide(drag.id, position);
|
|
756
|
+
onFinishGuide(drag.id);
|
|
757
|
+
};
|
|
758
|
+
const cancelGuideDrag = (event) => {
|
|
759
|
+
const drag = dragRef.current;
|
|
760
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
761
|
+
dragRef.current = null;
|
|
762
|
+
setDragPosition(null);
|
|
763
|
+
setDragOrientation(null);
|
|
764
|
+
onCancelGuide(drag.id);
|
|
765
|
+
};
|
|
766
|
+
const selectedVerticalGuides = guides.filter(
|
|
767
|
+
(guide) => guide.orientation === "vertical" && selectedGuideIds.includes(guide.id)
|
|
768
|
+
);
|
|
769
|
+
const selectedHorizontalGuides = guides.filter(
|
|
770
|
+
(guide) => guide.orientation === "horizontal" && selectedGuideIds.includes(guide.id)
|
|
771
|
+
);
|
|
772
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
773
|
+
"div",
|
|
774
|
+
{
|
|
775
|
+
"aria-hidden": "true",
|
|
776
|
+
className: "msr:pointer-events-none msr:absolute msr:inset-0 msr:select-none msr:text-[9px] msr:text-[#64748b]",
|
|
777
|
+
children: [
|
|
778
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
779
|
+
"div",
|
|
780
|
+
{
|
|
781
|
+
className: "msr:absolute msr:left-[18px] msr:right-0 msr:top-0 msr:overflow-hidden msr:bg-white",
|
|
782
|
+
style: {
|
|
783
|
+
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.12)",
|
|
784
|
+
height: RULER_SIZE,
|
|
785
|
+
cursor: "ns-resize",
|
|
786
|
+
pointerEvents: "auto"
|
|
787
|
+
},
|
|
788
|
+
onPointerDown: (event) => beginGuideDrag("horizontal", event),
|
|
789
|
+
onPointerMove: moveGuide,
|
|
790
|
+
onPointerUp: finishGuideDrag,
|
|
791
|
+
onPointerCancel: cancelGuideDrag,
|
|
792
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
793
|
+
"svg",
|
|
794
|
+
{
|
|
795
|
+
className: "msr:block msr:h-6",
|
|
796
|
+
width: RULER_LENGTH,
|
|
797
|
+
height: RULER_SIZE,
|
|
798
|
+
viewBox: `0 0 ${RULER_LENGTH} ${RULER_SIZE}`,
|
|
799
|
+
children: [
|
|
800
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
801
|
+
"linearGradient",
|
|
802
|
+
{
|
|
803
|
+
id: "ruler-label-fade-x",
|
|
804
|
+
x1: "0%",
|
|
805
|
+
x2: "100%",
|
|
806
|
+
gradientUnits: "objectBoundingBox",
|
|
807
|
+
children: [
|
|
808
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
809
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "0.2", stopColor: "white" }),
|
|
810
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "0.8", stopColor: "white" }),
|
|
811
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
|
|
812
|
+
]
|
|
813
|
+
}
|
|
814
|
+
) }),
|
|
815
|
+
ticks.map((x) => {
|
|
816
|
+
const major = x % 100 === 0;
|
|
817
|
+
const medium = x % 50 === 0;
|
|
818
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
|
|
819
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
820
|
+
"line",
|
|
821
|
+
{
|
|
822
|
+
x1: x,
|
|
823
|
+
y1: RULER_SIZE,
|
|
824
|
+
x2: x,
|
|
825
|
+
y2: major ? 8 : medium ? 13 : 17,
|
|
826
|
+
stroke: "currentColor",
|
|
827
|
+
strokeWidth: "1"
|
|
828
|
+
}
|
|
829
|
+
),
|
|
830
|
+
major ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("text", { x, y: "8", textAnchor: "middle", fill: "currentColor", children: x }) : null
|
|
831
|
+
] }, x);
|
|
832
|
+
}),
|
|
833
|
+
selectedVerticalGuides.map((guide) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
|
|
834
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
835
|
+
"rect",
|
|
836
|
+
{
|
|
837
|
+
x: guide.position - RULER_SIZE - 8,
|
|
838
|
+
y: "-1",
|
|
839
|
+
width: "48",
|
|
840
|
+
height: "12",
|
|
841
|
+
fill: "url(#ruler-label-fade-x)"
|
|
842
|
+
}
|
|
843
|
+
),
|
|
844
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
845
|
+
"text",
|
|
846
|
+
{
|
|
847
|
+
x: guide.position - RULER_SIZE + 16,
|
|
848
|
+
y: "8",
|
|
849
|
+
textAnchor: "middle",
|
|
850
|
+
fill: "#ef4444",
|
|
851
|
+
fontWeight: "600",
|
|
852
|
+
children: Math.round(guide.position - RULER_SIZE)
|
|
853
|
+
}
|
|
854
|
+
)
|
|
855
|
+
] }, guide.id)),
|
|
856
|
+
dragOrientation === "vertical" && dragPosition !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
|
|
857
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
858
|
+
"rect",
|
|
859
|
+
{
|
|
860
|
+
x: dragPosition - RULER_SIZE - 8,
|
|
861
|
+
y: "-1",
|
|
862
|
+
width: "48",
|
|
863
|
+
height: "12",
|
|
864
|
+
fill: "url(#ruler-label-fade-x)"
|
|
865
|
+
}
|
|
866
|
+
),
|
|
867
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
868
|
+
"text",
|
|
869
|
+
{
|
|
870
|
+
x: dragPosition - RULER_SIZE + 16,
|
|
871
|
+
y: "8",
|
|
872
|
+
textAnchor: "middle",
|
|
873
|
+
fill: "#ef4444",
|
|
874
|
+
fontWeight: "600",
|
|
875
|
+
children: Math.round(dragPosition - RULER_SIZE)
|
|
876
|
+
}
|
|
877
|
+
)
|
|
878
|
+
] }) : null
|
|
879
|
+
]
|
|
880
|
+
}
|
|
881
|
+
)
|
|
882
|
+
}
|
|
883
|
+
),
|
|
884
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
885
|
+
"div",
|
|
886
|
+
{
|
|
887
|
+
className: "msr:absolute msr:bottom-0 msr:left-0 msr:top-[18px] msr:w-[18px] msr:overflow-hidden msr:bg-white",
|
|
888
|
+
style: {
|
|
889
|
+
boxShadow: "1px 0 3px rgba(0, 0, 0, 0.12)",
|
|
890
|
+
width: RULER_SIZE,
|
|
891
|
+
cursor: "ew-resize",
|
|
892
|
+
pointerEvents: "auto"
|
|
893
|
+
},
|
|
894
|
+
onPointerDown: (event) => beginGuideDrag("vertical", event),
|
|
895
|
+
onPointerMove: moveGuide,
|
|
896
|
+
onPointerUp: finishGuideDrag,
|
|
897
|
+
onPointerCancel: cancelGuideDrag,
|
|
898
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
899
|
+
"svg",
|
|
900
|
+
{
|
|
901
|
+
className: "msr:block msr:w-6",
|
|
902
|
+
width: RULER_SIZE,
|
|
903
|
+
height: RULER_LENGTH,
|
|
904
|
+
viewBox: `0 0 ${RULER_SIZE} ${RULER_LENGTH}`,
|
|
905
|
+
children: [
|
|
906
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("defs", { children: /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
907
|
+
"linearGradient",
|
|
908
|
+
{
|
|
909
|
+
id: "ruler-label-fade-y",
|
|
910
|
+
y1: "0%",
|
|
911
|
+
y2: "100%",
|
|
912
|
+
gradientUnits: "objectBoundingBox",
|
|
913
|
+
children: [
|
|
914
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
915
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "0.2", stopColor: "white" }),
|
|
916
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "0.8", stopColor: "white" }),
|
|
917
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
|
|
918
|
+
]
|
|
919
|
+
}
|
|
920
|
+
) }),
|
|
921
|
+
ticks.map((y) => {
|
|
922
|
+
const major = y % 100 === 0;
|
|
923
|
+
const medium = y % 50 === 0;
|
|
924
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
|
|
925
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
926
|
+
"line",
|
|
927
|
+
{
|
|
928
|
+
x1: RULER_SIZE,
|
|
929
|
+
y1: y,
|
|
930
|
+
x2: major ? 8 : medium ? 13 : 17,
|
|
931
|
+
y2: y,
|
|
932
|
+
stroke: "currentColor",
|
|
933
|
+
strokeWidth: "1"
|
|
934
|
+
}
|
|
935
|
+
),
|
|
936
|
+
major ? /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
937
|
+
"text",
|
|
938
|
+
{
|
|
939
|
+
x: "8",
|
|
940
|
+
y: y + 10,
|
|
941
|
+
fill: "currentColor",
|
|
942
|
+
transform: `rotate(-90 8 ${y + 10})`,
|
|
943
|
+
children: y
|
|
944
|
+
}
|
|
945
|
+
) : null
|
|
946
|
+
] }, y);
|
|
947
|
+
}),
|
|
948
|
+
selectedHorizontalGuides.map((guide) => /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
|
|
949
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
950
|
+
"rect",
|
|
951
|
+
{
|
|
952
|
+
x: "-3",
|
|
953
|
+
y: guide.position - RULER_SIZE - 38,
|
|
954
|
+
width: "24",
|
|
955
|
+
height: "48",
|
|
956
|
+
fill: "url(#ruler-label-fade-y)"
|
|
957
|
+
}
|
|
958
|
+
),
|
|
959
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
960
|
+
"text",
|
|
961
|
+
{
|
|
962
|
+
x: "9",
|
|
963
|
+
y: guide.position - RULER_SIZE - 16,
|
|
964
|
+
textAnchor: "middle",
|
|
965
|
+
fill: "#ef4444",
|
|
966
|
+
fontWeight: "600",
|
|
967
|
+
transform: `rotate(-90 9 ${guide.position - RULER_SIZE - 16})`,
|
|
968
|
+
children: Math.round(guide.position - RULER_SIZE)
|
|
969
|
+
}
|
|
970
|
+
)
|
|
971
|
+
] }, guide.id)),
|
|
972
|
+
dragOrientation === "horizontal" && dragPosition !== null ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("g", { children: [
|
|
973
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
974
|
+
"rect",
|
|
975
|
+
{
|
|
976
|
+
x: "-3",
|
|
977
|
+
y: dragPosition - RULER_SIZE - 38,
|
|
978
|
+
width: "24",
|
|
979
|
+
height: "48",
|
|
980
|
+
fill: "url(#ruler-label-fade-y)"
|
|
981
|
+
}
|
|
982
|
+
),
|
|
983
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
984
|
+
"text",
|
|
985
|
+
{
|
|
986
|
+
x: "9",
|
|
987
|
+
y: dragPosition - RULER_SIZE - 16,
|
|
988
|
+
textAnchor: "middle",
|
|
989
|
+
fill: "#ef4444",
|
|
990
|
+
fontWeight: "600",
|
|
991
|
+
transform: `rotate(-90 9 ${dragPosition - RULER_SIZE - 16})`,
|
|
992
|
+
children: Math.round(dragPosition - RULER_SIZE)
|
|
993
|
+
}
|
|
994
|
+
)
|
|
995
|
+
] }) : null
|
|
996
|
+
]
|
|
997
|
+
}
|
|
998
|
+
)
|
|
999
|
+
}
|
|
1000
|
+
),
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "msr:absolute msr:left-0 msr:top-0 msr:size-[18px] msr:bg-white" })
|
|
1002
|
+
]
|
|
1003
|
+
}
|
|
1004
|
+
);
|
|
1005
|
+
});
|
|
1006
|
+
|
|
1007
|
+
// hooks/use-drag-state.ts
|
|
1008
|
+
var import_react3 = require("react");
|
|
564
1009
|
var useDragState = () => {
|
|
565
|
-
const [start, setStart] = (0,
|
|
566
|
-
const [end, setEnd] = (0,
|
|
567
|
-
const [isDragging, setIsDragging] = (0,
|
|
1010
|
+
const [start, setStart] = (0, import_react3.useState)(null);
|
|
1011
|
+
const [end, setEnd] = (0, import_react3.useState)(null);
|
|
1012
|
+
const [isDragging, setIsDragging] = (0, import_react3.useState)(false);
|
|
568
1013
|
return { start, setStart, end, setEnd, isDragging, setIsDragging };
|
|
569
1014
|
};
|
|
570
1015
|
|
|
571
1016
|
// hooks/use-guide-drag-hold.ts
|
|
572
|
-
var
|
|
573
|
-
var useGuideDragHold = () => {
|
|
574
|
-
const guideDragHoldTimerRef = (0,
|
|
575
|
-
const guideDragHoldGuideIdRef = (0,
|
|
576
|
-
const clearGuideDragHold = (0,
|
|
1017
|
+
var import_react4 = require("react");
|
|
1018
|
+
var useGuideDragHold = (eventTarget) => {
|
|
1019
|
+
const guideDragHoldTimerRef = (0, import_react4.useRef)(null);
|
|
1020
|
+
const guideDragHoldGuideIdRef = (0, import_react4.useRef)(null);
|
|
1021
|
+
const clearGuideDragHold = (0, import_react4.useCallback)(() => {
|
|
577
1022
|
if (guideDragHoldTimerRef.current !== null) {
|
|
578
|
-
|
|
1023
|
+
eventTarget.clearTimeout(guideDragHoldTimerRef.current);
|
|
579
1024
|
guideDragHoldTimerRef.current = null;
|
|
580
1025
|
}
|
|
581
1026
|
guideDragHoldGuideIdRef.current = null;
|
|
582
1027
|
}, []);
|
|
583
|
-
const scheduleGuideDragHold = (0,
|
|
1028
|
+
const scheduleGuideDragHold = (0, import_react4.useCallback)(
|
|
584
1029
|
(id, onHold) => {
|
|
585
1030
|
clearGuideDragHold();
|
|
586
1031
|
guideDragHoldGuideIdRef.current = id;
|
|
587
|
-
guideDragHoldTimerRef.current =
|
|
1032
|
+
guideDragHoldTimerRef.current = eventTarget.setTimeout(() => {
|
|
588
1033
|
if (guideDragHoldGuideIdRef.current === id) {
|
|
589
1034
|
onHold(id);
|
|
590
1035
|
}
|
|
@@ -599,11 +1044,11 @@ var useGuideDragHold = () => {
|
|
|
599
1044
|
};
|
|
600
1045
|
|
|
601
1046
|
// hooks/use-guide-state.ts
|
|
602
|
-
var
|
|
1047
|
+
var import_react5 = require("react");
|
|
603
1048
|
var useGuideState = (options = {}) => {
|
|
604
|
-
const [guides, setGuides] = (0,
|
|
605
|
-
const [draggingGuideId, setDraggingGuideId] = (0,
|
|
606
|
-
const [selectedGuideIds, setSelectedGuideIds] = (0,
|
|
1049
|
+
const [guides, setGuides] = (0, import_react5.useState)(options.initialGuides ?? []);
|
|
1050
|
+
const [draggingGuideId, setDraggingGuideId] = (0, import_react5.useState)(null);
|
|
1051
|
+
const [selectedGuideIds, setSelectedGuideIds] = (0, import_react5.useState)(
|
|
607
1052
|
options.initialSelectedGuideIds ?? []
|
|
608
1053
|
);
|
|
609
1054
|
return {
|
|
@@ -617,19 +1062,37 @@ var useGuideState = (options = {}) => {
|
|
|
617
1062
|
};
|
|
618
1063
|
|
|
619
1064
|
// hooks/use-hotkeys.ts
|
|
620
|
-
var
|
|
1065
|
+
var import_react6 = require("react");
|
|
621
1066
|
var useHotkeys = (options) => {
|
|
622
|
-
(0,
|
|
1067
|
+
(0, import_react6.useEffect)(() => {
|
|
1068
|
+
const target = options.eventTarget;
|
|
623
1069
|
const handleKeyDown = (event) => {
|
|
624
1070
|
if (event.key === "Escape") {
|
|
625
1071
|
options.clearAll();
|
|
626
1072
|
return;
|
|
627
1073
|
}
|
|
1074
|
+
if (event.metaKey || event.ctrlKey) {
|
|
1075
|
+
if (event.key.toLowerCase() !== "z") return;
|
|
1076
|
+
if (event.shiftKey) {
|
|
1077
|
+
event.preventDefault();
|
|
1078
|
+
options.redo();
|
|
1079
|
+
return;
|
|
1080
|
+
}
|
|
1081
|
+
event.preventDefault();
|
|
1082
|
+
options.undo();
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
628
1085
|
if (event.key.toLowerCase() === "m") {
|
|
629
1086
|
options.setEnabled((prev) => !prev);
|
|
630
1087
|
}
|
|
631
1088
|
const key = event.key.toLowerCase();
|
|
632
1089
|
if (options.isOverlayActive()) {
|
|
1090
|
+
if (key === "a") {
|
|
1091
|
+
options.setToolMode(
|
|
1092
|
+
(prev) => prev === "text-inspector" ? "none" : "text-inspector"
|
|
1093
|
+
);
|
|
1094
|
+
options.onInteract();
|
|
1095
|
+
}
|
|
633
1096
|
if (key === "s") {
|
|
634
1097
|
options.setToolMode((prev) => prev === "select" ? "none" : "select");
|
|
635
1098
|
options.onInteract();
|
|
@@ -638,6 +1101,14 @@ var useHotkeys = (options) => {
|
|
|
638
1101
|
options.setToolMode((prev) => prev === "guides" ? "none" : "guides");
|
|
639
1102
|
options.onInteract();
|
|
640
1103
|
}
|
|
1104
|
+
if (key === "x") {
|
|
1105
|
+
options.setToolMode((prev) => prev === "xray" ? "none" : "xray");
|
|
1106
|
+
options.onInteract();
|
|
1107
|
+
}
|
|
1108
|
+
if (key === "r") {
|
|
1109
|
+
options.setRulersVisible((prev) => !prev);
|
|
1110
|
+
options.onInteract();
|
|
1111
|
+
}
|
|
641
1112
|
if (key === "h") {
|
|
642
1113
|
options.setGuideOrientation("horizontal");
|
|
643
1114
|
options.onInteract();
|
|
@@ -662,22 +1133,22 @@ var useHotkeys = (options) => {
|
|
|
662
1133
|
options.setAltPressed(false);
|
|
663
1134
|
}
|
|
664
1135
|
};
|
|
665
|
-
|
|
666
|
-
|
|
1136
|
+
target.addEventListener("keydown", handleKeyDown);
|
|
1137
|
+
target.addEventListener("keyup", handleKeyUp);
|
|
667
1138
|
return () => {
|
|
668
|
-
|
|
669
|
-
|
|
1139
|
+
target.removeEventListener("keydown", handleKeyDown);
|
|
1140
|
+
target.removeEventListener("keyup", handleKeyUp);
|
|
670
1141
|
};
|
|
671
1142
|
}, [options]);
|
|
672
1143
|
};
|
|
673
1144
|
|
|
674
1145
|
// hooks/use-live-element-tracking.ts
|
|
675
|
-
var
|
|
1146
|
+
var import_react7 = require("react");
|
|
676
1147
|
|
|
677
|
-
// geometry.ts
|
|
678
|
-
var getViewportSize = () => ({
|
|
679
|
-
width: typeof window === "undefined" ? 1 : window.innerWidth || 1,
|
|
680
|
-
height: typeof window === "undefined" ? 1 : window.innerHeight || 1
|
|
1148
|
+
// core/geometry.ts
|
|
1149
|
+
var getViewportSize = (ownerWindow) => ({
|
|
1150
|
+
width: ownerWindow?.innerWidth || (typeof window === "undefined" ? 1 : window.innerWidth) || 1,
|
|
1151
|
+
height: ownerWindow?.innerHeight || (typeof window === "undefined" ? 1 : window.innerHeight) || 1
|
|
681
1152
|
});
|
|
682
1153
|
var normalizeRect = (rect, viewport = getViewportSize()) => ({
|
|
683
1154
|
left: rect.left / viewport.width,
|
|
@@ -719,9 +1190,9 @@ var getDistanceToRect = (point, rect) => {
|
|
|
719
1190
|
return Math.hypot(dx, dy);
|
|
720
1191
|
};
|
|
721
1192
|
|
|
722
|
-
// distances.ts
|
|
723
|
-
var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB) => {
|
|
724
|
-
const viewport = getViewportSize();
|
|
1193
|
+
// core/distances.ts
|
|
1194
|
+
var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB, ownerWindow = window) => {
|
|
1195
|
+
const viewport = getViewportSize(ownerWindow);
|
|
725
1196
|
const normalizedRectA = normalizeRect(rectA, viewport);
|
|
726
1197
|
const normalizedRectB = normalizeRect(rectB, viewport);
|
|
727
1198
|
const rightA = rectA.left + rectA.width;
|
|
@@ -762,10 +1233,10 @@ var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB) => {
|
|
|
762
1233
|
}
|
|
763
1234
|
}
|
|
764
1235
|
const normalizedConnectors = connectors.map((segment) => ({
|
|
765
|
-
x1: clamp(segment.x1, 0,
|
|
766
|
-
y1: clamp(segment.y1, 0,
|
|
767
|
-
x2: clamp(segment.x2, 0,
|
|
768
|
-
y2: clamp(segment.y2, 0,
|
|
1236
|
+
x1: clamp(segment.x1, 0, ownerWindow.innerWidth),
|
|
1237
|
+
y1: clamp(segment.y1, 0, ownerWindow.innerHeight),
|
|
1238
|
+
x2: clamp(segment.x2, 0, ownerWindow.innerWidth),
|
|
1239
|
+
y2: clamp(segment.y2, 0, ownerWindow.innerHeight)
|
|
769
1240
|
})).filter(
|
|
770
1241
|
(segment) => Math.abs(segment.x1 - segment.x2) > 0.5 || Math.abs(segment.y1 - segment.y2) > 0.5
|
|
771
1242
|
);
|
|
@@ -782,17 +1253,17 @@ var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB) => {
|
|
|
782
1253
|
connectors: normalizedConnectors
|
|
783
1254
|
};
|
|
784
1255
|
};
|
|
785
|
-
var updateDistanceForResize = (distance, viewport = getViewportSize()) => {
|
|
786
|
-
const normalizedRectA = distance.normalizedRectA ?? normalizeRect(distance.rectA);
|
|
787
|
-
const normalizedRectB = distance.normalizedRectB ?? normalizeRect(distance.rectB);
|
|
1256
|
+
var updateDistanceForResize = (distance, viewport = getViewportSize(), ownerDocument = document, ownerWindow = window) => {
|
|
1257
|
+
const normalizedRectA = distance.normalizedRectA ?? normalizeRect(distance.rectA, viewport);
|
|
1258
|
+
const normalizedRectB = distance.normalizedRectB ?? normalizeRect(distance.rectB, viewport);
|
|
788
1259
|
let rectA = distance.rectA;
|
|
789
1260
|
let rectB = distance.rectB;
|
|
790
|
-
if (distance.elementRefA &&
|
|
1261
|
+
if (distance.elementRefA && ownerDocument.contains(distance.elementRefA)) {
|
|
791
1262
|
rectA = distance.elementRefA.getBoundingClientRect();
|
|
792
1263
|
} else {
|
|
793
1264
|
rectA = denormalizeRect(normalizedRectA, viewport);
|
|
794
1265
|
}
|
|
795
|
-
if (distance.elementRefB &&
|
|
1266
|
+
if (distance.elementRefB && ownerDocument.contains(distance.elementRefB)) {
|
|
796
1267
|
rectB = distance.elementRefB.getBoundingClientRect();
|
|
797
1268
|
} else {
|
|
798
1269
|
rectB = denormalizeRect(normalizedRectB, viewport);
|
|
@@ -801,7 +1272,8 @@ var updateDistanceForResize = (distance, viewport = getViewportSize()) => {
|
|
|
801
1272
|
rectA,
|
|
802
1273
|
rectB,
|
|
803
1274
|
distance.elementRefA,
|
|
804
|
-
distance.elementRefB
|
|
1275
|
+
distance.elementRefB,
|
|
1276
|
+
ownerWindow
|
|
805
1277
|
);
|
|
806
1278
|
return {
|
|
807
1279
|
...updated,
|
|
@@ -809,7 +1281,7 @@ var updateDistanceForResize = (distance, viewport = getViewportSize()) => {
|
|
|
809
1281
|
};
|
|
810
1282
|
};
|
|
811
1283
|
|
|
812
|
-
// dom.ts
|
|
1284
|
+
// core/dom.ts
|
|
813
1285
|
var getElementLabel = (element) => {
|
|
814
1286
|
const tag = element.tagName.toLowerCase();
|
|
815
1287
|
const id = element.id ? `#${element.id}` : "";
|
|
@@ -842,24 +1314,38 @@ var getRectFromDomCached = (element) => {
|
|
|
842
1314
|
};
|
|
843
1315
|
var cachedElements = [];
|
|
844
1316
|
var cachedFrame = -1;
|
|
1317
|
+
var cachedDocument = null;
|
|
845
1318
|
var getFrameToken = () => {
|
|
846
1319
|
if (typeof performance === "undefined") return 0;
|
|
847
1320
|
return Math.floor(performance.now() / 16);
|
|
848
1321
|
};
|
|
849
|
-
var getBodyElementsCached = () => {
|
|
1322
|
+
var getBodyElementsCached = (ownerDocument = document) => {
|
|
850
1323
|
const frame = getFrameToken();
|
|
851
|
-
if (frame === cachedFrame && cachedElements.length > 0) {
|
|
1324
|
+
if (frame === cachedFrame && cachedDocument === ownerDocument && cachedElements.length > 0) {
|
|
852
1325
|
return cachedElements;
|
|
853
1326
|
}
|
|
854
1327
|
cachedFrame = frame;
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
1328
|
+
cachedDocument = ownerDocument;
|
|
1329
|
+
const elements = [];
|
|
1330
|
+
const HTMLElementConstructor = ownerDocument.defaultView?.HTMLElement ?? HTMLElement;
|
|
1331
|
+
const visit = (root) => {
|
|
1332
|
+
const walker = ownerDocument.createTreeWalker(root, 1);
|
|
1333
|
+
let node = walker.nextNode();
|
|
1334
|
+
while (node) {
|
|
1335
|
+
if (node instanceof HTMLElementConstructor) {
|
|
1336
|
+
elements.push(node);
|
|
1337
|
+
if (node.shadowRoot) visit(node.shadowRoot);
|
|
1338
|
+
}
|
|
1339
|
+
node = walker.nextNode();
|
|
1340
|
+
}
|
|
1341
|
+
};
|
|
1342
|
+
if (ownerDocument.body) visit(ownerDocument.body);
|
|
1343
|
+
cachedElements = elements;
|
|
858
1344
|
return cachedElements;
|
|
859
1345
|
};
|
|
860
|
-
var getInspectMeasurement = (element) => {
|
|
1346
|
+
var getInspectMeasurement = (element, ownerWindow = window) => {
|
|
861
1347
|
const rect = element.getBoundingClientRect();
|
|
862
|
-
const style =
|
|
1348
|
+
const style = ownerWindow.getComputedStyle(element);
|
|
863
1349
|
const padding = {
|
|
864
1350
|
top: parseEdge(style.paddingTop),
|
|
865
1351
|
right: parseEdge(style.paddingRight),
|
|
@@ -900,9 +1386,9 @@ var getInspectMeasurement = (element) => {
|
|
|
900
1386
|
elementRef: element
|
|
901
1387
|
};
|
|
902
1388
|
};
|
|
903
|
-
var updateMeasurementForResize = (measurement, viewport = getViewportSize()) => {
|
|
1389
|
+
var updateMeasurementForResize = (measurement, viewport = getViewportSize(), ownerDocument = document) => {
|
|
904
1390
|
let rect = measurement.rect;
|
|
905
|
-
if (measurement.elementRef &&
|
|
1391
|
+
if (measurement.elementRef && ownerDocument.contains(measurement.elementRef)) {
|
|
906
1392
|
rect = getRectFromDom(measurement.elementRef);
|
|
907
1393
|
} else if (measurement.normalizedRect) {
|
|
908
1394
|
rect = denormalizeRect(measurement.normalizedRect, viewport);
|
|
@@ -917,11 +1403,11 @@ var updateMeasurementForResize = (measurement, viewport = getViewportSize()) =>
|
|
|
917
1403
|
|
|
918
1404
|
// hooks/use-live-element-tracking.ts
|
|
919
1405
|
var useLiveElementTracking = (params) => {
|
|
920
|
-
const frameRef = (0,
|
|
921
|
-
(0,
|
|
1406
|
+
const frameRef = (0, import_react7.useRef)(null);
|
|
1407
|
+
(0, import_react7.useEffect)(() => {
|
|
922
1408
|
if (!params.enabled) {
|
|
923
1409
|
if (frameRef.current) {
|
|
924
|
-
cancelAnimationFrame(frameRef.current);
|
|
1410
|
+
params.window.cancelAnimationFrame(frameRef.current);
|
|
925
1411
|
}
|
|
926
1412
|
frameRef.current = null;
|
|
927
1413
|
return;
|
|
@@ -929,7 +1415,7 @@ var useLiveElementTracking = (params) => {
|
|
|
929
1415
|
const tick = () => {
|
|
930
1416
|
params.setMeasurements(
|
|
931
1417
|
(prev) => prev.map((measurement) => {
|
|
932
|
-
if (!measurement.elementRef || !document.contains(measurement.elementRef)) {
|
|
1418
|
+
if (!measurement.elementRef || !params.document.contains(measurement.elementRef)) {
|
|
933
1419
|
return measurement;
|
|
934
1420
|
}
|
|
935
1421
|
const rect = getRectFromDom(measurement.elementRef);
|
|
@@ -943,7 +1429,7 @@ var useLiveElementTracking = (params) => {
|
|
|
943
1429
|
})
|
|
944
1430
|
);
|
|
945
1431
|
params.setActiveMeasurement((prev) => {
|
|
946
|
-
if (!prev?.elementRef || !document.contains(prev.elementRef))
|
|
1432
|
+
if (!prev?.elementRef || !params.document.contains(prev.elementRef))
|
|
947
1433
|
return prev;
|
|
948
1434
|
const rect = getRectFromDom(prev.elementRef);
|
|
949
1435
|
if (rectAlmostEqual(rect, prev.rect)) return prev;
|
|
@@ -956,8 +1442,8 @@ var useLiveElementTracking = (params) => {
|
|
|
956
1442
|
});
|
|
957
1443
|
params.setHeldDistances(
|
|
958
1444
|
(prev) => prev.map((distance) => {
|
|
959
|
-
const canTrackA = distance.elementRefA && document.contains(distance.elementRefA);
|
|
960
|
-
const canTrackB = distance.elementRefB && document.contains(distance.elementRefB);
|
|
1445
|
+
const canTrackA = distance.elementRefA && params.document.contains(distance.elementRefA);
|
|
1446
|
+
const canTrackB = distance.elementRefB && params.document.contains(distance.elementRefB);
|
|
961
1447
|
if (!canTrackA && !canTrackB) return distance;
|
|
962
1448
|
const rectA = canTrackA ? getRectFromDom(distance.elementRefA) : distance.rectA;
|
|
963
1449
|
const rectB = canTrackB ? getRectFromDom(distance.elementRefB) : distance.rectB;
|
|
@@ -968,7 +1454,8 @@ var useLiveElementTracking = (params) => {
|
|
|
968
1454
|
rectA,
|
|
969
1455
|
rectB,
|
|
970
1456
|
distance.elementRefA,
|
|
971
|
-
distance.elementRefB
|
|
1457
|
+
distance.elementRefB,
|
|
1458
|
+
params.window
|
|
972
1459
|
);
|
|
973
1460
|
return {
|
|
974
1461
|
...updated,
|
|
@@ -977,19 +1464,19 @@ var useLiveElementTracking = (params) => {
|
|
|
977
1464
|
})
|
|
978
1465
|
);
|
|
979
1466
|
const selected = params.selectedElementRef.current;
|
|
980
|
-
if (selected && document.contains(selected)) {
|
|
1467
|
+
if (selected && params.document.contains(selected)) {
|
|
981
1468
|
params.setSelectedMeasurement((prev) => {
|
|
982
|
-
const next = getInspectMeasurement(selected);
|
|
1469
|
+
const next = getInspectMeasurement(selected, params.window);
|
|
983
1470
|
if (prev && rectAlmostEqual(prev.rect, next.rect)) return prev;
|
|
984
1471
|
return next;
|
|
985
1472
|
});
|
|
986
1473
|
}
|
|
987
1474
|
params.setSelectedMeasurements(
|
|
988
1475
|
(prev) => prev.map((measurement) => {
|
|
989
|
-
if (!measurement.elementRef || !document.contains(measurement.elementRef)) {
|
|
1476
|
+
if (!measurement.elementRef || !params.document.contains(measurement.elementRef)) {
|
|
990
1477
|
return measurement;
|
|
991
1478
|
}
|
|
992
|
-
const next = getInspectMeasurement(measurement.elementRef);
|
|
1479
|
+
const next = getInspectMeasurement(measurement.elementRef, params.window);
|
|
993
1480
|
if (rectAlmostEqual(next.rect, measurement.rect)) return measurement;
|
|
994
1481
|
return {
|
|
995
1482
|
...next,
|
|
@@ -998,18 +1485,18 @@ var useLiveElementTracking = (params) => {
|
|
|
998
1485
|
})
|
|
999
1486
|
);
|
|
1000
1487
|
const hover = params.hoverElementRef.current;
|
|
1001
|
-
if (hover && document.contains(hover)) {
|
|
1488
|
+
if (hover && params.document.contains(hover)) {
|
|
1002
1489
|
const rect = getRectFromDom(hover);
|
|
1003
1490
|
params.setHoverRect(
|
|
1004
1491
|
(prev) => prev && rectAlmostEqual(prev, rect) ? prev : rect
|
|
1005
1492
|
);
|
|
1006
1493
|
}
|
|
1007
|
-
frameRef.current = requestAnimationFrame(tick);
|
|
1494
|
+
frameRef.current = params.window.requestAnimationFrame(tick);
|
|
1008
1495
|
};
|
|
1009
|
-
frameRef.current = requestAnimationFrame(tick);
|
|
1496
|
+
frameRef.current = params.window.requestAnimationFrame(tick);
|
|
1010
1497
|
return () => {
|
|
1011
1498
|
if (frameRef.current) {
|
|
1012
|
-
cancelAnimationFrame(frameRef.current);
|
|
1499
|
+
params.window.cancelAnimationFrame(frameRef.current);
|
|
1013
1500
|
}
|
|
1014
1501
|
frameRef.current = null;
|
|
1015
1502
|
};
|
|
@@ -1017,13 +1504,16 @@ var useLiveElementTracking = (params) => {
|
|
|
1017
1504
|
};
|
|
1018
1505
|
|
|
1019
1506
|
// hooks/use-measure-toggles.ts
|
|
1020
|
-
var
|
|
1507
|
+
var import_react8 = require("react");
|
|
1021
1508
|
var useMeasureToggles = (options = {}) => {
|
|
1022
|
-
const [enabled, setEnabled] = (0,
|
|
1023
|
-
const [altPressed, setAltPressed] = (0,
|
|
1024
|
-
const [toolMode, setToolMode] = (0,
|
|
1509
|
+
const [enabled, setEnabled] = (0, import_react8.useState)(options.initialEnabled ?? true);
|
|
1510
|
+
const [altPressed, setAltPressed] = (0, import_react8.useState)(false);
|
|
1511
|
+
const [toolMode, setToolMode] = (0, import_react8.useState)(
|
|
1025
1512
|
options.initialToolMode ?? "none"
|
|
1026
1513
|
);
|
|
1514
|
+
const [rulersVisible, setRulersVisible] = (0, import_react8.useState)(
|
|
1515
|
+
options.initialRulersVisible ?? false
|
|
1516
|
+
);
|
|
1027
1517
|
const holdEnabled = false;
|
|
1028
1518
|
const multiMeasureEnabled = false;
|
|
1029
1519
|
const snapGuidesEnabled = true;
|
|
@@ -1037,6 +1527,8 @@ var useMeasureToggles = (options = {}) => {
|
|
|
1037
1527
|
setAltPressed,
|
|
1038
1528
|
toolMode,
|
|
1039
1529
|
setToolMode,
|
|
1530
|
+
rulersVisible,
|
|
1531
|
+
setRulersVisible,
|
|
1040
1532
|
guidesEnabled,
|
|
1041
1533
|
multiMeasureEnabled,
|
|
1042
1534
|
snapGuidesEnabled,
|
|
@@ -1045,16 +1537,16 @@ var useMeasureToggles = (options = {}) => {
|
|
|
1045
1537
|
};
|
|
1046
1538
|
|
|
1047
1539
|
// hooks/use-measurement-state.ts
|
|
1048
|
-
var
|
|
1540
|
+
var import_react9 = require("react");
|
|
1049
1541
|
var useMeasurementState = (options = {}) => {
|
|
1050
|
-
const [activeMeasurement, setActiveMeasurement] = (0,
|
|
1051
|
-
const [measurements, setMeasurements] = (0,
|
|
1542
|
+
const [activeMeasurement, setActiveMeasurement] = (0, import_react9.useState)(options.initialActiveMeasurement ?? null);
|
|
1543
|
+
const [measurements, setMeasurements] = (0, import_react9.useState)(
|
|
1052
1544
|
options.initialMeasurements ?? []
|
|
1053
1545
|
);
|
|
1054
|
-
const [selectedMeasurement, setSelectedMeasurement] = (0,
|
|
1055
|
-
const [selectedMeasurements, setSelectedMeasurements] = (0,
|
|
1056
|
-
const [hoverRect, setHoverRect] = (0,
|
|
1057
|
-
const [heldDistances, setHeldDistances] = (0,
|
|
1546
|
+
const [selectedMeasurement, setSelectedMeasurement] = (0, import_react9.useState)(null);
|
|
1547
|
+
const [selectedMeasurements, setSelectedMeasurements] = (0, import_react9.useState)([]);
|
|
1548
|
+
const [hoverRect, setHoverRect] = (0, import_react9.useState)(null);
|
|
1549
|
+
const [heldDistances, setHeldDistances] = (0, import_react9.useState)(
|
|
1058
1550
|
options.initialHeldDistances ?? []
|
|
1059
1551
|
);
|
|
1060
1552
|
return {
|
|
@@ -1074,9 +1566,9 @@ var useMeasurementState = (options = {}) => {
|
|
|
1074
1566
|
};
|
|
1075
1567
|
|
|
1076
1568
|
// hooks/use-measurer-derived.ts
|
|
1077
|
-
var
|
|
1569
|
+
var import_react10 = require("react");
|
|
1078
1570
|
|
|
1079
|
-
// edge-visibility.ts
|
|
1571
|
+
// core/edge-visibility.ts
|
|
1080
1572
|
var rangesOverlap = (a1, a2, b1, b2) => Math.min(a2, b2) - Math.max(a1, b1) > 0;
|
|
1081
1573
|
var getEdgeVisibilityForRects = (rects, epsilon = 1) => {
|
|
1082
1574
|
const visibility = rects.map(() => ({
|
|
@@ -1116,24 +1608,25 @@ var getEdgeVisibilityForRects = (rects, epsilon = 1) => {
|
|
|
1116
1608
|
return visibility;
|
|
1117
1609
|
};
|
|
1118
1610
|
|
|
1119
|
-
// guides.ts
|
|
1120
|
-
var getGuideRect = (guide) => {
|
|
1121
|
-
const viewport = getViewportSize();
|
|
1611
|
+
// core/guides.ts
|
|
1612
|
+
var getGuideRect = (guide, ownerWindow = window) => {
|
|
1613
|
+
const viewport = getViewportSize(ownerWindow);
|
|
1122
1614
|
return guide.orientation === "vertical" ? { left: guide.position, top: 0, width: 1, height: viewport.height } : { left: 0, top: guide.position, width: viewport.width, height: 1 };
|
|
1123
1615
|
};
|
|
1124
1616
|
var getGuideDistance = (guide, point) => guide.orientation === "vertical" ? Math.abs(guide.position - point.x) : Math.abs(guide.position - point.y);
|
|
1125
1617
|
var getSnapGuidePosition = (params) => {
|
|
1618
|
+
const ownerDocument = params.document ?? document;
|
|
1126
1619
|
const { orientation, point, snapGuidesEnabled, overlayNode, guides } = params;
|
|
1127
1620
|
if (!snapGuidesEnabled) {
|
|
1128
1621
|
return orientation === "vertical" ? point.x : point.y;
|
|
1129
1622
|
}
|
|
1130
|
-
const elements = getBodyElementsCached();
|
|
1623
|
+
const elements = getBodyElementsCached(ownerDocument);
|
|
1131
1624
|
let bestValue = orientation === "vertical" ? point.x : point.y;
|
|
1132
1625
|
let bestDistance = GUIDE_SNAP_DISTANCE + 1;
|
|
1133
1626
|
for (const element of elements) {
|
|
1134
|
-
if (!(element instanceof HTMLElement)) continue;
|
|
1627
|
+
if (!(element instanceof (ownerDocument.defaultView?.HTMLElement ?? HTMLElement))) continue;
|
|
1135
1628
|
if (overlayNode && overlayNode.contains(element)) continue;
|
|
1136
|
-
if (element ===
|
|
1629
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1137
1630
|
continue;
|
|
1138
1631
|
const rect = getRectFromDomCached(element);
|
|
1139
1632
|
if (rect.width <= 2 || rect.height <= 2) continue;
|
|
@@ -1169,7 +1662,7 @@ var getSnapGuidePosition = (params) => {
|
|
|
1169
1662
|
return bestDistance <= GUIDE_SNAP_DISTANCE ? bestValue : orientation === "vertical" ? point.x : point.y;
|
|
1170
1663
|
};
|
|
1171
1664
|
|
|
1172
|
-
// option-measurements.ts
|
|
1665
|
+
// core/option-measurements.ts
|
|
1173
1666
|
var getHoveredGuide = (point, guides) => {
|
|
1174
1667
|
if (!point || guides.length === 0) return null;
|
|
1175
1668
|
let closest = null;
|
|
@@ -1190,6 +1683,8 @@ var getSelectedGuide = (guides, selectedGuideIds) => {
|
|
|
1190
1683
|
return guides.find((guide) => guide.id === lastId) ?? null;
|
|
1191
1684
|
};
|
|
1192
1685
|
var getOptionPairOverlay = (params) => {
|
|
1686
|
+
const ownerDocument = params.document ?? document;
|
|
1687
|
+
const ownerWindow = params.window ?? window;
|
|
1193
1688
|
if (!params.altPressed) return null;
|
|
1194
1689
|
if (!params.selectedGuide && !params.primarySelectedMeasurement) return null;
|
|
1195
1690
|
const primary = params.primarySelectedMeasurement;
|
|
@@ -1218,10 +1713,13 @@ var getOptionPairOverlay = (params) => {
|
|
|
1218
1713
|
selectedTarget.rect,
|
|
1219
1714
|
hoverTarget.rect,
|
|
1220
1715
|
selectedTarget.element ?? null,
|
|
1221
|
-
hoverTarget.element ?? null
|
|
1716
|
+
hoverTarget.element ?? null,
|
|
1717
|
+
ownerWindow
|
|
1222
1718
|
);
|
|
1223
1719
|
};
|
|
1224
1720
|
var getOptionContainerLines = (params) => {
|
|
1721
|
+
const ownerDocument = params.document ?? document;
|
|
1722
|
+
const ownerWindow = params.window ?? window;
|
|
1225
1723
|
if (!params.altPressed || !params.primarySelectedMeasurement || params.optionPairOverlay)
|
|
1226
1724
|
return null;
|
|
1227
1725
|
if (params.selectedGuideIds.length > 0) return null;
|
|
@@ -1229,11 +1727,11 @@ var getOptionContainerLines = (params) => {
|
|
|
1229
1727
|
if (params.selectedElement && params.hoverElement && params.hoverElement !== params.selectedElement && params.hoverElement.contains(params.selectedElement)) {
|
|
1230
1728
|
containerElement = params.hoverElement;
|
|
1231
1729
|
}
|
|
1232
|
-
const containerRect = containerElement && containerElement !==
|
|
1730
|
+
const containerRect = containerElement && containerElement !== ownerDocument.body && containerElement !== ownerDocument.documentElement ? getRectFromDom(containerElement) : {
|
|
1233
1731
|
left: 0,
|
|
1234
1732
|
top: 0,
|
|
1235
|
-
width:
|
|
1236
|
-
height:
|
|
1733
|
+
width: ownerWindow.innerWidth,
|
|
1734
|
+
height: ownerWindow.innerHeight
|
|
1237
1735
|
};
|
|
1238
1736
|
const rect = params.primarySelectedMeasurement.rect;
|
|
1239
1737
|
const right = rect.left + rect.width;
|
|
@@ -1272,12 +1770,20 @@ var getOptionContainerLines = (params) => {
|
|
|
1272
1770
|
};
|
|
1273
1771
|
};
|
|
1274
1772
|
|
|
1275
|
-
// selection-helpers.ts
|
|
1773
|
+
// core/selection-helpers.ts
|
|
1774
|
+
var getOverlayHost = (overlayNode) => {
|
|
1775
|
+
if (!overlayNode) return null;
|
|
1776
|
+
const rootNode = overlayNode.getRootNode();
|
|
1777
|
+
return rootNode.nodeType === 11 ? rootNode.host : null;
|
|
1778
|
+
};
|
|
1276
1779
|
var getPrimarySelectedMeasurement = (selectedMeasurements, selectedMeasurement) => selectedMeasurements.length > 0 ? selectedMeasurements[selectedMeasurements.length - 1] : selectedMeasurement;
|
|
1277
1780
|
var getSelectedMeasurementHit = (params) => {
|
|
1781
|
+
const ownerDocument = params.document ?? document;
|
|
1782
|
+
const HTMLElementConstructor = ownerDocument.defaultView?.HTMLElement ?? HTMLElement;
|
|
1783
|
+
const overlayHost = getOverlayHost(params.overlayNode);
|
|
1278
1784
|
const candidates = params.selectedMeasurements.map((measurement) => {
|
|
1279
1785
|
const element = measurement.elementRef;
|
|
1280
|
-
if (!element || !
|
|
1786
|
+
if (!element || !ownerDocument.contains(element)) return null;
|
|
1281
1787
|
const rect = getRectFromDom(element);
|
|
1282
1788
|
return {
|
|
1283
1789
|
measurement,
|
|
@@ -1287,10 +1793,11 @@ var getSelectedMeasurementHit = (params) => {
|
|
|
1287
1793
|
};
|
|
1288
1794
|
}).filter((item) => item !== null).sort((a, b) => a.area - b.area);
|
|
1289
1795
|
if (candidates.length === 0) return null;
|
|
1290
|
-
const stack =
|
|
1796
|
+
const stack = ownerDocument.elementsFromPoint(params.point.x, params.point.y);
|
|
1291
1797
|
for (const element of stack) {
|
|
1292
|
-
if (!(element instanceof
|
|
1798
|
+
if (!(element instanceof HTMLElementConstructor)) continue;
|
|
1293
1799
|
if (params.overlayNode && params.overlayNode.contains(element)) continue;
|
|
1800
|
+
if (overlayHost && element === overlayHost) continue;
|
|
1294
1801
|
for (const candidate of candidates) {
|
|
1295
1802
|
if (candidate.element === element || candidate.element.contains(element)) {
|
|
1296
1803
|
return candidate.measurement;
|
|
@@ -1307,6 +1814,8 @@ var getSelectedMeasurementHit = (params) => {
|
|
|
1307
1814
|
|
|
1308
1815
|
// hooks/use-measurer-derived.ts
|
|
1309
1816
|
var useMeasurerDerived = ({
|
|
1817
|
+
document: document2,
|
|
1818
|
+
window: window2,
|
|
1310
1819
|
start,
|
|
1311
1820
|
end,
|
|
1312
1821
|
selectedMeasurements,
|
|
@@ -1326,7 +1835,7 @@ var useMeasurerDerived = ({
|
|
|
1326
1835
|
highlightColor,
|
|
1327
1836
|
guideColor
|
|
1328
1837
|
}) => {
|
|
1329
|
-
const activeRect = (0,
|
|
1838
|
+
const activeRect = (0, import_react10.useMemo)(() => {
|
|
1330
1839
|
if (!start || !end) return null;
|
|
1331
1840
|
return {
|
|
1332
1841
|
left: Math.min(start.x, end.x),
|
|
@@ -1337,7 +1846,7 @@ var useMeasurerDerived = ({
|
|
|
1337
1846
|
}, [end, start]);
|
|
1338
1847
|
const activeWidth = activeRect ? formatValue(activeRect.width) : 0;
|
|
1339
1848
|
const activeHeight = activeRect ? formatValue(activeRect.height) : 0;
|
|
1340
|
-
const groupedSelection = (0,
|
|
1849
|
+
const groupedSelection = (0, import_react10.useMemo)(() => {
|
|
1341
1850
|
if (selectedMeasurements.length <= 1) return null;
|
|
1342
1851
|
const selectionKey = selectedMeasurements.map((measurement) => measurement.id).join("|");
|
|
1343
1852
|
const rects = selectedMeasurements.map((measurement) => measurement.rect);
|
|
@@ -1367,31 +1876,33 @@ var useMeasurerDerived = ({
|
|
|
1367
1876
|
originRect: selectionOriginRect ?? void 0
|
|
1368
1877
|
};
|
|
1369
1878
|
}, [selectedMeasurements, selectionOriginRect]);
|
|
1370
|
-
const displayedSelectedMeasurements = (0,
|
|
1879
|
+
const displayedSelectedMeasurements = (0, import_react10.useMemo)(
|
|
1371
1880
|
() => groupedSelection ? [groupedSelection] : selectedMeasurements.length > 0 ? selectedMeasurements : selectedMeasurement ? [selectedMeasurement] : [],
|
|
1372
1881
|
[groupedSelection, selectedMeasurement, selectedMeasurements]
|
|
1373
1882
|
);
|
|
1374
|
-
const selectedGuide = (0,
|
|
1883
|
+
const selectedGuide = (0, import_react10.useMemo)(
|
|
1375
1884
|
() => getSelectedGuide(guides, selectedGuideIds),
|
|
1376
1885
|
[guides, selectedGuideIds]
|
|
1377
1886
|
);
|
|
1378
|
-
const hoverGuide = (0,
|
|
1887
|
+
const hoverGuide = (0, import_react10.useMemo)(
|
|
1379
1888
|
() => getHoveredGuide(hoverPointer, guides),
|
|
1380
1889
|
[guides, hoverPointer]
|
|
1381
1890
|
);
|
|
1382
|
-
const primarySelectedMeasurement = (0,
|
|
1891
|
+
const primarySelectedMeasurement = (0, import_react10.useMemo)(
|
|
1383
1892
|
() => getPrimarySelectedMeasurement(selectedMeasurements, selectedMeasurement),
|
|
1384
1893
|
[selectedMeasurement, selectedMeasurements]
|
|
1385
1894
|
);
|
|
1386
1895
|
const effectivePrimarySelected = groupedSelection ?? primarySelectedMeasurement;
|
|
1387
|
-
const optionPairOverlay = (0,
|
|
1896
|
+
const optionPairOverlay = (0, import_react10.useMemo)(() => {
|
|
1388
1897
|
return getOptionPairOverlay({
|
|
1389
1898
|
altPressed,
|
|
1390
1899
|
primarySelectedMeasurement: effectivePrimarySelected,
|
|
1391
1900
|
selectedGuide,
|
|
1392
1901
|
hoverGuide,
|
|
1393
1902
|
hoverElement,
|
|
1394
|
-
selectedElementRef: selectedElement
|
|
1903
|
+
selectedElementRef: selectedElement,
|
|
1904
|
+
document: document2,
|
|
1905
|
+
window: window2
|
|
1395
1906
|
});
|
|
1396
1907
|
}, [
|
|
1397
1908
|
altPressed,
|
|
@@ -1401,14 +1912,16 @@ var useMeasurerDerived = ({
|
|
|
1401
1912
|
selectedElement,
|
|
1402
1913
|
selectedGuide
|
|
1403
1914
|
]);
|
|
1404
|
-
const optionContainerLines = (0,
|
|
1915
|
+
const optionContainerLines = (0, import_react10.useMemo)(() => {
|
|
1405
1916
|
return getOptionContainerLines({
|
|
1406
1917
|
altPressed,
|
|
1407
1918
|
primarySelectedMeasurement: effectivePrimarySelected,
|
|
1408
1919
|
optionPairOverlay,
|
|
1409
1920
|
selectedGuideIds,
|
|
1410
1921
|
selectedElement,
|
|
1411
|
-
hoverElement
|
|
1922
|
+
hoverElement,
|
|
1923
|
+
document: document2,
|
|
1924
|
+
window: window2
|
|
1412
1925
|
});
|
|
1413
1926
|
}, [
|
|
1414
1927
|
altPressed,
|
|
@@ -1418,12 +1931,15 @@ var useMeasurerDerived = ({
|
|
|
1418
1931
|
selectedElement,
|
|
1419
1932
|
selectedGuideIds
|
|
1420
1933
|
]);
|
|
1421
|
-
const guideDistanceOverlay = (0,
|
|
1934
|
+
const guideDistanceOverlay = (0, import_react10.useMemo)(() => {
|
|
1422
1935
|
if (!altPressed || !guidesEnabled) return null;
|
|
1423
1936
|
if (selectedGuide && hoverGuide && selectedGuide.id !== hoverGuide.id) {
|
|
1424
1937
|
return getDistanceOverlay(
|
|
1425
|
-
getGuideRect(selectedGuide),
|
|
1426
|
-
getGuideRect(hoverGuide)
|
|
1938
|
+
getGuideRect(selectedGuide, window2),
|
|
1939
|
+
getGuideRect(hoverGuide, window2),
|
|
1940
|
+
null,
|
|
1941
|
+
null,
|
|
1942
|
+
window2
|
|
1427
1943
|
);
|
|
1428
1944
|
}
|
|
1429
1945
|
if (!guidePreview) return null;
|
|
@@ -1446,8 +1962,11 @@ var useMeasurerDerived = ({
|
|
|
1446
1962
|
);
|
|
1447
1963
|
if (!nearest) return null;
|
|
1448
1964
|
return getDistanceOverlay(
|
|
1449
|
-
getGuideRect(previewGuide),
|
|
1450
|
-
getGuideRect(nearest.guide)
|
|
1965
|
+
getGuideRect(previewGuide, window2),
|
|
1966
|
+
getGuideRect(nearest.guide, window2),
|
|
1967
|
+
null,
|
|
1968
|
+
null,
|
|
1969
|
+
window2
|
|
1451
1970
|
);
|
|
1452
1971
|
}, [
|
|
1453
1972
|
altPressed,
|
|
@@ -1464,7 +1983,7 @@ var useMeasurerDerived = ({
|
|
|
1464
1983
|
guideColorHover,
|
|
1465
1984
|
guideColorDefault,
|
|
1466
1985
|
guideColorPreview
|
|
1467
|
-
} = (0,
|
|
1986
|
+
} = (0, import_react10.useMemo)(
|
|
1468
1987
|
() => ({
|
|
1469
1988
|
outlineColor: `color-mix(in oklch, ${highlightColor} 80%, transparent)`,
|
|
1470
1989
|
fillColor: `color-mix(in oklch, ${highlightColor} 8%, transparent)`,
|
|
@@ -1475,12 +1994,12 @@ var useMeasurerDerived = ({
|
|
|
1475
1994
|
}),
|
|
1476
1995
|
[guideColor, highlightColor]
|
|
1477
1996
|
);
|
|
1478
|
-
const selectedRects = (0,
|
|
1997
|
+
const selectedRects = (0, import_react10.useMemo)(
|
|
1479
1998
|
() => displayedSelectedMeasurements.map((measurement) => measurement.rect),
|
|
1480
1999
|
[displayedSelectedMeasurements]
|
|
1481
2000
|
);
|
|
1482
2001
|
const hoverRectToShow = hoverHighlightEnabled && hoverRect && selectedMeasurements.length <= 1 ? hoverRect : null;
|
|
1483
|
-
const selectionEdgeVisibility = (0,
|
|
2002
|
+
const selectionEdgeVisibility = (0, import_react10.useMemo)(
|
|
1484
2003
|
() => getEdgeVisibilityForRects(selectedRects),
|
|
1485
2004
|
[selectedRects]
|
|
1486
2005
|
);
|
|
@@ -1489,7 +2008,7 @@ var useMeasurerDerived = ({
|
|
|
1489
2008
|
selectedRects.length
|
|
1490
2009
|
);
|
|
1491
2010
|
const hoverEdgeVisibility = hoverRectToShow ? { top: true, right: true, bottom: true, left: true } : null;
|
|
1492
|
-
const measurementEdgeVisibility = (0,
|
|
2011
|
+
const measurementEdgeVisibility = (0, import_react10.useMemo)(
|
|
1493
2012
|
() => getEdgeVisibilityForRects(displayedMeasurements.map((m) => m.rect)),
|
|
1494
2013
|
[displayedMeasurements]
|
|
1495
2014
|
);
|
|
@@ -1517,7 +2036,7 @@ var useMeasurerDerived = ({
|
|
|
1517
2036
|
};
|
|
1518
2037
|
|
|
1519
2038
|
// hooks/use-measurer-history.ts
|
|
1520
|
-
var
|
|
2039
|
+
var import_react11 = require("react");
|
|
1521
2040
|
var HISTORY_LIMIT = 50;
|
|
1522
2041
|
var useMeasurerHistory = ({
|
|
1523
2042
|
toggles,
|
|
@@ -1563,10 +2082,10 @@ var useMeasurerHistory = ({
|
|
|
1563
2082
|
setSelectedElement,
|
|
1564
2083
|
clearSelectionRect
|
|
1565
2084
|
} = transient;
|
|
1566
|
-
const historyRef = (0,
|
|
1567
|
-
const futureRef = (0,
|
|
1568
|
-
const historySignatureRef = (0,
|
|
1569
|
-
const captureSnapshot = (0,
|
|
2085
|
+
const historyRef = (0, import_react11.useRef)([]);
|
|
2086
|
+
const futureRef = (0, import_react11.useRef)([]);
|
|
2087
|
+
const historySignatureRef = (0, import_react11.useRef)(null);
|
|
2088
|
+
const captureSnapshot = (0, import_react11.useCallback)(() => {
|
|
1570
2089
|
return {
|
|
1571
2090
|
enabled,
|
|
1572
2091
|
toolMode,
|
|
@@ -1593,7 +2112,7 @@ var useMeasurerHistory = ({
|
|
|
1593
2112
|
selectedMeasurements,
|
|
1594
2113
|
toolMode
|
|
1595
2114
|
]);
|
|
1596
|
-
const getSnapshotSignature = (0,
|
|
2115
|
+
const getSnapshotSignature = (0, import_react11.useCallback)((snapshot) => {
|
|
1597
2116
|
const serializeRect = (rect) => `${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`;
|
|
1598
2117
|
return [
|
|
1599
2118
|
snapshot.enabled ? "1" : "0",
|
|
@@ -1609,7 +2128,7 @@ var useMeasurerHistory = ({
|
|
|
1609
2128
|
snapshot.draggingGuideId ?? ""
|
|
1610
2129
|
].join("|");
|
|
1611
2130
|
}, []);
|
|
1612
|
-
const recordSnapshot = (0,
|
|
2131
|
+
const recordSnapshot = (0, import_react11.useCallback)(() => {
|
|
1613
2132
|
const snapshot = captureSnapshot();
|
|
1614
2133
|
const signature = getSnapshotSignature(snapshot);
|
|
1615
2134
|
if (historySignatureRef.current === signature) return;
|
|
@@ -1620,7 +2139,7 @@ var useMeasurerHistory = ({
|
|
|
1620
2139
|
historyRef.current.shift();
|
|
1621
2140
|
}
|
|
1622
2141
|
}, [captureSnapshot, getSnapshotSignature]);
|
|
1623
|
-
const restoreSnapshot = (0,
|
|
2142
|
+
const restoreSnapshot = (0, import_react11.useCallback)(
|
|
1624
2143
|
(snapshot) => {
|
|
1625
2144
|
setEnabled(snapshot.enabled);
|
|
1626
2145
|
setToolMode(snapshot.toolMode);
|
|
@@ -1665,7 +2184,7 @@ var useMeasurerHistory = ({
|
|
|
1665
2184
|
setHoverElement
|
|
1666
2185
|
]
|
|
1667
2186
|
);
|
|
1668
|
-
const undo = (0,
|
|
2187
|
+
const undo = (0, import_react11.useCallback)(() => {
|
|
1669
2188
|
const previousSnapshot = historyRef.current.pop();
|
|
1670
2189
|
if (!previousSnapshot) return;
|
|
1671
2190
|
const currentSnapshot = captureSnapshot();
|
|
@@ -1676,7 +2195,7 @@ var useMeasurerHistory = ({
|
|
|
1676
2195
|
historySignatureRef.current = null;
|
|
1677
2196
|
restoreSnapshot(previousSnapshot);
|
|
1678
2197
|
}, [captureSnapshot, restoreSnapshot]);
|
|
1679
|
-
const redo = (0,
|
|
2198
|
+
const redo = (0, import_react11.useCallback)(() => {
|
|
1680
2199
|
const nextSnapshot = futureRef.current.pop();
|
|
1681
2200
|
if (!nextSnapshot) return;
|
|
1682
2201
|
historyRef.current.push(captureSnapshot());
|
|
@@ -1686,7 +2205,7 @@ var useMeasurerHistory = ({
|
|
|
1686
2205
|
historySignatureRef.current = null;
|
|
1687
2206
|
restoreSnapshot(nextSnapshot);
|
|
1688
2207
|
}, [captureSnapshot, restoreSnapshot]);
|
|
1689
|
-
const setToolModeWithHistory = (0,
|
|
2208
|
+
const setToolModeWithHistory = (0, import_react11.useCallback)(
|
|
1690
2209
|
(value) => {
|
|
1691
2210
|
setToolMode((prev) => {
|
|
1692
2211
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -1697,7 +2216,7 @@ var useMeasurerHistory = ({
|
|
|
1697
2216
|
},
|
|
1698
2217
|
[recordSnapshot, setToolMode]
|
|
1699
2218
|
);
|
|
1700
|
-
const setGuideOrientationWithHistory = (0,
|
|
2219
|
+
const setGuideOrientationWithHistory = (0, import_react11.useCallback)(
|
|
1701
2220
|
(value) => {
|
|
1702
2221
|
setGuideOrientation((prev) => {
|
|
1703
2222
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -1708,7 +2227,7 @@ var useMeasurerHistory = ({
|
|
|
1708
2227
|
},
|
|
1709
2228
|
[recordSnapshot, setGuideOrientation]
|
|
1710
2229
|
);
|
|
1711
|
-
const setEnabledWithHistory = (0,
|
|
2230
|
+
const setEnabledWithHistory = (0, import_react11.useCallback)(
|
|
1712
2231
|
(value) => {
|
|
1713
2232
|
setEnabled((prev) => {
|
|
1714
2233
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -1719,7 +2238,7 @@ var useMeasurerHistory = ({
|
|
|
1719
2238
|
},
|
|
1720
2239
|
[recordSnapshot, setEnabled]
|
|
1721
2240
|
);
|
|
1722
|
-
const createActionCommit = (0,
|
|
2241
|
+
const createActionCommit = (0, import_react11.useCallback)(() => {
|
|
1723
2242
|
let committed = false;
|
|
1724
2243
|
return () => {
|
|
1725
2244
|
if (committed) return;
|
|
@@ -1727,64 +2246,47 @@ var useMeasurerHistory = ({
|
|
|
1727
2246
|
committed = true;
|
|
1728
2247
|
};
|
|
1729
2248
|
}, [recordSnapshot]);
|
|
1730
|
-
(0, import_react10.useEffect)(() => {
|
|
1731
|
-
const handleKeyDown = (event) => {
|
|
1732
|
-
if (!(event.metaKey || event.ctrlKey)) return;
|
|
1733
|
-
if (event.key.toLowerCase() !== "z") return;
|
|
1734
|
-
if (event.shiftKey) {
|
|
1735
|
-
if (futureRef.current.length === 0) return;
|
|
1736
|
-
event.preventDefault();
|
|
1737
|
-
redo();
|
|
1738
|
-
return;
|
|
1739
|
-
}
|
|
1740
|
-
if (historyRef.current.length === 0) return;
|
|
1741
|
-
event.preventDefault();
|
|
1742
|
-
undo();
|
|
1743
|
-
};
|
|
1744
|
-
window.addEventListener("keydown", handleKeyDown);
|
|
1745
|
-
return () => {
|
|
1746
|
-
window.removeEventListener("keydown", handleKeyDown);
|
|
1747
|
-
};
|
|
1748
|
-
}, [redo, undo]);
|
|
1749
2249
|
return {
|
|
1750
2250
|
recordSnapshot,
|
|
1751
2251
|
createActionCommit,
|
|
1752
2252
|
setToolModeWithHistory,
|
|
1753
2253
|
setGuideOrientationWithHistory,
|
|
1754
|
-
setEnabledWithHistory
|
|
2254
|
+
setEnabledWithHistory,
|
|
2255
|
+
undo,
|
|
2256
|
+
redo
|
|
1755
2257
|
};
|
|
1756
2258
|
};
|
|
1757
2259
|
|
|
1758
2260
|
// hooks/use-measurer-local-state.ts
|
|
1759
|
-
var
|
|
2261
|
+
var import_react12 = require("react");
|
|
1760
2262
|
var useMeasurerLocalState = ({
|
|
1761
2263
|
selectedElementRef,
|
|
1762
2264
|
hoverElementRef,
|
|
1763
2265
|
selectionRectRef
|
|
1764
2266
|
}) => {
|
|
1765
|
-
const [selectionOriginRect, setSelectionOriginRect] = (0,
|
|
2267
|
+
const [selectionOriginRect, setSelectionOriginRect] = (0, import_react12.useState)(
|
|
1766
2268
|
null
|
|
1767
2269
|
);
|
|
1768
|
-
const [hoverPointer, setHoverPointer] = (0,
|
|
1769
|
-
const [hoverElement, setHoverElementState] = (0,
|
|
2270
|
+
const [hoverPointer, setHoverPointer] = (0, import_react12.useState)(null);
|
|
2271
|
+
const [hoverElement, setHoverElementState] = (0, import_react12.useState)(
|
|
1770
2272
|
null
|
|
1771
2273
|
);
|
|
1772
|
-
const [selectedElement, setSelectedElementState] = (0,
|
|
1773
|
-
const setSelectedElement = (0,
|
|
2274
|
+
const [selectedElement, setSelectedElementState] = (0, import_react12.useState)(null);
|
|
2275
|
+
const setSelectedElement = (0, import_react12.useCallback)(
|
|
1774
2276
|
(element) => {
|
|
1775
2277
|
selectedElementRef.current = element;
|
|
1776
2278
|
setSelectedElementState(element);
|
|
1777
2279
|
},
|
|
1778
2280
|
[selectedElementRef]
|
|
1779
2281
|
);
|
|
1780
|
-
const setHoverElement = (0,
|
|
2282
|
+
const setHoverElement = (0, import_react12.useCallback)(
|
|
1781
2283
|
(element) => {
|
|
1782
2284
|
hoverElementRef.current = element;
|
|
1783
2285
|
setHoverElementState(element);
|
|
1784
2286
|
},
|
|
1785
2287
|
[hoverElementRef]
|
|
1786
2288
|
);
|
|
1787
|
-
const clearSelectionRect = (0,
|
|
2289
|
+
const clearSelectionRect = (0, import_react12.useCallback)(() => {
|
|
1788
2290
|
selectionRectRef.current = null;
|
|
1789
2291
|
setSelectionOriginRect(null);
|
|
1790
2292
|
}, [selectionRectRef]);
|
|
@@ -1802,9 +2304,9 @@ var useMeasurerLocalState = ({
|
|
|
1802
2304
|
};
|
|
1803
2305
|
|
|
1804
2306
|
// hooks/use-measurer-pointer.ts
|
|
1805
|
-
var
|
|
2307
|
+
var import_react13 = require("react");
|
|
1806
2308
|
|
|
1807
|
-
// targets.ts
|
|
2309
|
+
// core/targets.ts
|
|
1808
2310
|
var pickMultiTargets = (selectionRect, items) => {
|
|
1809
2311
|
const candidates = items.map(({ element, rect }) => {
|
|
1810
2312
|
const overlapArea = intersectionArea(selectionRect, rect);
|
|
@@ -1869,17 +2371,39 @@ var pickPointTarget = (point, items) => {
|
|
|
1869
2371
|
return scored[0].element;
|
|
1870
2372
|
};
|
|
1871
2373
|
|
|
1872
|
-
// selection.ts
|
|
1873
|
-
var
|
|
2374
|
+
// core/selection.ts
|
|
2375
|
+
var getOverlayHost2 = (overlayNode) => {
|
|
2376
|
+
if (!overlayNode) return null;
|
|
2377
|
+
const rootNode = overlayNode.getRootNode();
|
|
2378
|
+
return rootNode.nodeType === 11 ? rootNode.host : null;
|
|
2379
|
+
};
|
|
2380
|
+
var isOverlayElement = (element, overlayNode, overlayHost) => {
|
|
2381
|
+
if (overlayNode && overlayNode.contains(element)) return true;
|
|
2382
|
+
if (overlayHost && element === overlayHost) return true;
|
|
2383
|
+
return false;
|
|
2384
|
+
};
|
|
2385
|
+
var getDeepestElementAt = (element, point) => {
|
|
2386
|
+
let current = element;
|
|
2387
|
+
const HTMLElementConstructor = element.ownerDocument.defaultView?.HTMLElement ?? HTMLElement;
|
|
2388
|
+
while (current instanceof HTMLElementConstructor && current.shadowRoot) {
|
|
2389
|
+
const nested = current.shadowRoot.elementFromPoint(point.x, point.y);
|
|
2390
|
+
if (!nested || nested === current) break;
|
|
2391
|
+
current = nested;
|
|
2392
|
+
}
|
|
2393
|
+
return current;
|
|
2394
|
+
};
|
|
2395
|
+
var getTargetElement = (point, overlayNode, ownerDocument = document) => {
|
|
2396
|
+
const overlayHost = getOverlayHost2(overlayNode);
|
|
1874
2397
|
if (overlayNode) {
|
|
1875
2398
|
const previous = overlayNode.style.pointerEvents;
|
|
1876
2399
|
overlayNode.style.pointerEvents = "none";
|
|
1877
|
-
const elements2 =
|
|
2400
|
+
const elements2 = ownerDocument.elementsFromPoint(point.x, point.y);
|
|
1878
2401
|
overlayNode.style.pointerEvents = previous;
|
|
1879
|
-
for (const
|
|
1880
|
-
|
|
1881
|
-
if (
|
|
1882
|
-
if (element
|
|
2402
|
+
for (const rawElement of elements2) {
|
|
2403
|
+
const element = getDeepestElementAt(rawElement, point);
|
|
2404
|
+
if (!(element instanceof (ownerDocument.defaultView?.HTMLElement ?? HTMLElement))) continue;
|
|
2405
|
+
if (isOverlayElement(element, overlayNode, overlayHost)) continue;
|
|
2406
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1883
2407
|
continue;
|
|
1884
2408
|
const rect = element.getBoundingClientRect();
|
|
1885
2409
|
if (rect.width <= 2 || rect.height <= 2) continue;
|
|
@@ -1887,10 +2411,12 @@ var getTargetElement = (point, overlayNode) => {
|
|
|
1887
2411
|
}
|
|
1888
2412
|
return null;
|
|
1889
2413
|
}
|
|
1890
|
-
const elements =
|
|
1891
|
-
for (const
|
|
1892
|
-
|
|
1893
|
-
if (element
|
|
2414
|
+
const elements = ownerDocument.elementsFromPoint(point.x, point.y);
|
|
2415
|
+
for (const rawElement of elements) {
|
|
2416
|
+
const element = getDeepestElementAt(rawElement, point);
|
|
2417
|
+
if (!(element instanceof (ownerDocument.defaultView?.HTMLElement ?? HTMLElement))) continue;
|
|
2418
|
+
if (isOverlayElement(element, overlayNode, overlayHost)) continue;
|
|
2419
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1894
2420
|
continue;
|
|
1895
2421
|
const rect = element.getBoundingClientRect();
|
|
1896
2422
|
if (rect.width <= 2 || rect.height <= 2) continue;
|
|
@@ -1898,33 +2424,34 @@ var getTargetElement = (point, overlayNode) => {
|
|
|
1898
2424
|
}
|
|
1899
2425
|
return null;
|
|
1900
2426
|
};
|
|
1901
|
-
var getSnappedClickTarget = (point, overlayNode, snapEnabled) => {
|
|
1902
|
-
if (!snapEnabled) return getTargetElement(point, overlayNode);
|
|
2427
|
+
var getSnappedClickTarget = (point, overlayNode, snapEnabled, ownerDocument = document) => {
|
|
2428
|
+
if (!snapEnabled) return getTargetElement(point, overlayNode, ownerDocument);
|
|
1903
2429
|
const probeRect = {
|
|
1904
2430
|
left: point.x - 20,
|
|
1905
2431
|
top: point.y - 20,
|
|
1906
2432
|
width: 40,
|
|
1907
2433
|
height: 40
|
|
1908
2434
|
};
|
|
1909
|
-
const entries = getSelectionEntries(probeRect, overlayNode);
|
|
1910
|
-
return pickPointTarget(point, entries) ?? pickSingleTarget(probeRect, point, entries) ?? getTargetElement(point, overlayNode);
|
|
2435
|
+
const entries = getSelectionEntries(probeRect, overlayNode, ownerDocument);
|
|
2436
|
+
return pickPointTarget(point, entries) ?? pickSingleTarget(probeRect, point, entries) ?? getTargetElement(point, overlayNode, ownerDocument);
|
|
1911
2437
|
};
|
|
1912
|
-
var getSelectionEntries = (rect, overlayNode) => {
|
|
2438
|
+
var getSelectionEntries = (rect, overlayNode, ownerDocument = document) => {
|
|
2439
|
+
const overlayHost = getOverlayHost2(overlayNode);
|
|
1913
2440
|
const frame = getFrameToken();
|
|
1914
2441
|
const key = `${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(
|
|
1915
2442
|
rect.width
|
|
1916
2443
|
)}:${Math.round(rect.height)}`;
|
|
1917
|
-
if (frame === cachedSelectionFrame && cachedSelectionKey === key && cachedOverlayNode === overlayNode) {
|
|
2444
|
+
if (frame === cachedSelectionFrame && cachedSelectionKey === key && cachedOverlayNode === overlayNode && cachedSelectionDocument === ownerDocument) {
|
|
1918
2445
|
return cachedSelectionEntries;
|
|
1919
2446
|
}
|
|
1920
2447
|
const minLeft = rect.left - 1;
|
|
1921
2448
|
const minTop = rect.top - 1;
|
|
1922
2449
|
const maxRight = rect.left + rect.width + 1;
|
|
1923
2450
|
const maxBottom = rect.top + rect.height + 1;
|
|
1924
|
-
const elements = getBodyElementsCached();
|
|
2451
|
+
const elements = getBodyElementsCached(ownerDocument);
|
|
1925
2452
|
const entries = elements.map((element) => ({ element, rect: getRectFromDomCached(element) })).filter(({ element, rect: elementRect }) => {
|
|
1926
|
-
if (overlayNode
|
|
1927
|
-
if (element ===
|
|
2453
|
+
if (isOverlayElement(element, overlayNode, overlayHost)) return false;
|
|
2454
|
+
if (element === ownerDocument.body || element === ownerDocument.documentElement)
|
|
1928
2455
|
return false;
|
|
1929
2456
|
if (elementRect.width < MIN_MULTI_TARGET_SIZE || elementRect.height < MIN_MULTI_TARGET_SIZE) {
|
|
1930
2457
|
return false;
|
|
@@ -1938,6 +2465,7 @@ var getSelectionEntries = (rect, overlayNode) => {
|
|
|
1938
2465
|
cachedSelectionFrame = frame;
|
|
1939
2466
|
cachedSelectionKey = key;
|
|
1940
2467
|
cachedOverlayNode = overlayNode;
|
|
2468
|
+
cachedSelectionDocument = ownerDocument;
|
|
1941
2469
|
cachedSelectionEntries = entries;
|
|
1942
2470
|
return entries;
|
|
1943
2471
|
};
|
|
@@ -1945,30 +2473,33 @@ var cachedSelectionFrame = -1;
|
|
|
1945
2473
|
var cachedSelectionKey = "";
|
|
1946
2474
|
var cachedSelectionEntries = [];
|
|
1947
2475
|
var cachedOverlayNode = null;
|
|
2476
|
+
var cachedSelectionDocument = null;
|
|
1948
2477
|
var getSelectionCacheKey = (rect) => `${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(
|
|
1949
2478
|
rect.width
|
|
1950
2479
|
)}:${Math.round(rect.height)}`;
|
|
1951
|
-
var getSelectionEntriesCached = (rect, overlayNode, cache) => {
|
|
2480
|
+
var getSelectionEntriesCached = (rect, overlayNode, cache, ownerDocument = document) => {
|
|
1952
2481
|
const frame = getFrameToken();
|
|
1953
2482
|
const key = getSelectionCacheKey(rect);
|
|
1954
2483
|
if (cache.key === key && cache.overlayNode === overlayNode && cache.frame === frame) {
|
|
1955
2484
|
return cache.entries;
|
|
1956
2485
|
}
|
|
1957
|
-
const entries = getSelectionEntries(rect, overlayNode);
|
|
2486
|
+
const entries = getSelectionEntries(rect, overlayNode, ownerDocument);
|
|
1958
2487
|
cache.key = key;
|
|
1959
2488
|
cache.overlayNode = overlayNode;
|
|
1960
2489
|
cache.frame = frame;
|
|
1961
2490
|
cache.entries = entries;
|
|
1962
2491
|
return entries;
|
|
1963
2492
|
};
|
|
1964
|
-
var getElementsInRectCached = (rect, overlayNode, cache) => {
|
|
1965
|
-
const entries = getSelectionEntriesCached(rect, overlayNode, cache);
|
|
2493
|
+
var getElementsInRectCached = (rect, overlayNode, cache, ownerDocument = document) => {
|
|
2494
|
+
const entries = getSelectionEntriesCached(rect, overlayNode, cache, ownerDocument);
|
|
1966
2495
|
if (entries.length === 0) return [];
|
|
1967
2496
|
return pickMultiTargets(rect, entries);
|
|
1968
2497
|
};
|
|
1969
2498
|
|
|
1970
2499
|
// hooks/use-measurer-pointer.ts
|
|
1971
2500
|
var useMeasurerPointer = ({
|
|
2501
|
+
document: document2,
|
|
2502
|
+
window: window2,
|
|
1972
2503
|
toolbarRef,
|
|
1973
2504
|
overlayRef,
|
|
1974
2505
|
selectionRectRef,
|
|
@@ -2012,46 +2543,26 @@ var useMeasurerPointer = ({
|
|
|
2012
2543
|
setHoverPointer,
|
|
2013
2544
|
clearSelectionRect
|
|
2014
2545
|
}) => {
|
|
2015
|
-
const hoverFrameRef = (0,
|
|
2016
|
-
const hoverPointRef = (0,
|
|
2017
|
-
const selectionCacheRef = (0,
|
|
2546
|
+
const hoverFrameRef = (0, import_react13.useRef)(null);
|
|
2547
|
+
const hoverPointRef = (0, import_react13.useRef)(null);
|
|
2548
|
+
const selectionCacheRef = (0, import_react13.useRef)({
|
|
2018
2549
|
key: "",
|
|
2019
2550
|
entries: [],
|
|
2020
2551
|
overlayNode: null,
|
|
2021
2552
|
frame: -1
|
|
2022
2553
|
});
|
|
2023
|
-
const shiftDragRef = (0,
|
|
2024
|
-
const shiftToggleElementRef = (0,
|
|
2025
|
-
|
|
2026
|
-
const guidesRef = (0, import_react12.useRef)(guides);
|
|
2027
|
-
const snapGuidesEnabledRef = (0, import_react12.useRef)(snapGuidesEnabled);
|
|
2028
|
-
const draggingGuideIdRef = (0, import_react12.useRef)(draggingGuideId);
|
|
2029
|
-
const guideOrientationRef = (0, import_react12.useRef)(guideOrientation);
|
|
2030
|
-
(0, import_react12.useEffect)(() => {
|
|
2554
|
+
const shiftDragRef = (0, import_react13.useRef)(false);
|
|
2555
|
+
const shiftToggleElementRef = (0, import_react13.useRef)(null);
|
|
2556
|
+
(0, import_react13.useEffect)(() => {
|
|
2031
2557
|
return () => {
|
|
2032
2558
|
if (hoverFrameRef.current) {
|
|
2033
|
-
cancelAnimationFrame(hoverFrameRef.current);
|
|
2559
|
+
window2.cancelAnimationFrame(hoverFrameRef.current);
|
|
2034
2560
|
}
|
|
2035
2561
|
};
|
|
2036
2562
|
}, []);
|
|
2037
|
-
(0,
|
|
2038
|
-
guidesEnabledRef.current = guidesEnabled;
|
|
2039
|
-
}, [guidesEnabled]);
|
|
2040
|
-
(0, import_react12.useEffect)(() => {
|
|
2041
|
-
guidesRef.current = guides;
|
|
2042
|
-
}, [guides]);
|
|
2043
|
-
(0, import_react12.useEffect)(() => {
|
|
2044
|
-
snapGuidesEnabledRef.current = snapGuidesEnabled;
|
|
2045
|
-
}, [snapGuidesEnabled]);
|
|
2046
|
-
(0, import_react12.useEffect)(() => {
|
|
2047
|
-
guideOrientationRef.current = guideOrientation;
|
|
2048
|
-
}, [guideOrientation]);
|
|
2049
|
-
(0, import_react12.useEffect)(() => {
|
|
2050
|
-
draggingGuideIdRef.current = draggingGuideId;
|
|
2051
|
-
}, [draggingGuideId]);
|
|
2052
|
-
const updateHoverTarget = (0, import_react12.useCallback)(
|
|
2563
|
+
const updateHoverTarget = (0, import_react13.useCallback)(
|
|
2053
2564
|
(point) => {
|
|
2054
|
-
const target = getTargetElement(point, overlayRef.current);
|
|
2565
|
+
const target = getTargetElement(point, overlayRef.current, document2);
|
|
2055
2566
|
if (target) {
|
|
2056
2567
|
const rect = target.getBoundingClientRect();
|
|
2057
2568
|
setHoverRect({
|
|
@@ -2066,16 +2577,16 @@ var useMeasurerPointer = ({
|
|
|
2066
2577
|
setHoverElement(null);
|
|
2067
2578
|
}
|
|
2068
2579
|
},
|
|
2069
|
-
[overlayRef, setHoverElement, setHoverRect]
|
|
2580
|
+
[document2, overlayRef, setHoverElement, setHoverRect]
|
|
2070
2581
|
);
|
|
2071
|
-
const updateHoverElement = (0,
|
|
2582
|
+
const updateHoverElement = (0, import_react13.useCallback)(
|
|
2072
2583
|
(point) => {
|
|
2073
|
-
const target = getTargetElement(point, overlayRef.current);
|
|
2584
|
+
const target = getTargetElement(point, overlayRef.current, document2);
|
|
2074
2585
|
setHoverElement(target);
|
|
2075
2586
|
},
|
|
2076
|
-
[overlayRef, setHoverElement]
|
|
2587
|
+
[document2, overlayRef, setHoverElement]
|
|
2077
2588
|
);
|
|
2078
|
-
const handlePointerDown = (0,
|
|
2589
|
+
const handlePointerDown = (0, import_react13.useCallback)(
|
|
2079
2590
|
(event) => {
|
|
2080
2591
|
const commit = createActionCommit();
|
|
2081
2592
|
const toolbarNode = toolbarRef.current;
|
|
@@ -2088,7 +2599,8 @@ var useMeasurerPointer = ({
|
|
|
2088
2599
|
shiftToggleElementRef.current = event.shiftKey ? getSelectedMeasurementHit({
|
|
2089
2600
|
point,
|
|
2090
2601
|
selectedMeasurements,
|
|
2091
|
-
overlayNode: overlayRef.current
|
|
2602
|
+
overlayNode: overlayRef.current,
|
|
2603
|
+
document: document2
|
|
2092
2604
|
})?.elementRef ?? null : null;
|
|
2093
2605
|
selectionCacheRef.current.key = "";
|
|
2094
2606
|
if (altPressed && optionPairOverlay) {
|
|
@@ -2110,10 +2622,11 @@ var useMeasurerPointer = ({
|
|
|
2110
2622
|
snapGuidesEnabled,
|
|
2111
2623
|
overlayNode: overlayRef.current,
|
|
2112
2624
|
guides,
|
|
2113
|
-
draggingGuideId
|
|
2625
|
+
draggingGuideId,
|
|
2626
|
+
document: document2
|
|
2114
2627
|
});
|
|
2115
2628
|
const id = createId();
|
|
2116
|
-
setSelectedGuideIds([]);
|
|
2629
|
+
setSelectedGuideIds([id]);
|
|
2117
2630
|
setGuides((prev) => [
|
|
2118
2631
|
...prev,
|
|
2119
2632
|
{ id, orientation: guideOrientation, position }
|
|
@@ -2136,6 +2649,7 @@ var useMeasurerPointer = ({
|
|
|
2136
2649
|
clearSelectionRect,
|
|
2137
2650
|
createActionCommit,
|
|
2138
2651
|
draggingGuideId,
|
|
2652
|
+
document2,
|
|
2139
2653
|
enabled,
|
|
2140
2654
|
guideOrientation,
|
|
2141
2655
|
guides,
|
|
@@ -2157,7 +2671,7 @@ var useMeasurerPointer = ({
|
|
|
2157
2671
|
toolbarRef
|
|
2158
2672
|
]
|
|
2159
2673
|
);
|
|
2160
|
-
const handlePointerMove = (0,
|
|
2674
|
+
const handlePointerMove = (0, import_react13.useCallback)(
|
|
2161
2675
|
(event) => {
|
|
2162
2676
|
const toolbarNode = toolbarRef.current;
|
|
2163
2677
|
if (toolbarNode && toolbarNode.contains(event.target)) return;
|
|
@@ -2177,31 +2691,32 @@ var useMeasurerPointer = ({
|
|
|
2177
2691
|
}
|
|
2178
2692
|
hoverPointRef.current = point;
|
|
2179
2693
|
if (!hoverFrameRef.current) {
|
|
2180
|
-
hoverFrameRef.current = requestAnimationFrame(() => {
|
|
2694
|
+
hoverFrameRef.current = window2.requestAnimationFrame(() => {
|
|
2181
2695
|
const latest = hoverPointRef.current;
|
|
2182
|
-
if (latest && !
|
|
2696
|
+
if (latest && !draggingGuideId) {
|
|
2183
2697
|
if (hoverHighlightEnabled) {
|
|
2184
2698
|
updateHoverTarget(latest);
|
|
2185
2699
|
} else {
|
|
2186
2700
|
updateHoverElement(latest);
|
|
2187
2701
|
}
|
|
2188
2702
|
}
|
|
2189
|
-
if (latest &&
|
|
2703
|
+
if (latest && guides.length > 0) {
|
|
2190
2704
|
setHoverPointer(latest);
|
|
2191
2705
|
} else {
|
|
2192
2706
|
setHoverPointer(null);
|
|
2193
2707
|
}
|
|
2194
|
-
if (
|
|
2708
|
+
if (guidesEnabled && latest && !draggingGuideId) {
|
|
2195
2709
|
const position = getSnapGuidePosition({
|
|
2196
|
-
orientation:
|
|
2710
|
+
orientation: guideOrientation,
|
|
2197
2711
|
point: latest,
|
|
2198
|
-
snapGuidesEnabled
|
|
2712
|
+
snapGuidesEnabled,
|
|
2199
2713
|
overlayNode: overlayRef.current,
|
|
2200
|
-
guides
|
|
2201
|
-
draggingGuideId
|
|
2714
|
+
guides,
|
|
2715
|
+
draggingGuideId,
|
|
2716
|
+
document: document2
|
|
2202
2717
|
});
|
|
2203
2718
|
setGuidePreview({
|
|
2204
|
-
orientation:
|
|
2719
|
+
orientation: guideOrientation,
|
|
2205
2720
|
position
|
|
2206
2721
|
});
|
|
2207
2722
|
} else {
|
|
@@ -2218,10 +2733,11 @@ var useMeasurerPointer = ({
|
|
|
2218
2733
|
position: getSnapGuidePosition({
|
|
2219
2734
|
orientation: guide.orientation,
|
|
2220
2735
|
point,
|
|
2221
|
-
snapGuidesEnabled
|
|
2736
|
+
snapGuidesEnabled,
|
|
2222
2737
|
overlayNode: overlayRef.current,
|
|
2223
|
-
guides
|
|
2224
|
-
draggingGuideId
|
|
2738
|
+
guides,
|
|
2739
|
+
draggingGuideId,
|
|
2740
|
+
document: document2
|
|
2225
2741
|
})
|
|
2226
2742
|
} : guide
|
|
2227
2743
|
)
|
|
@@ -2243,8 +2759,11 @@ var useMeasurerPointer = ({
|
|
|
2243
2759
|
draggingGuideId,
|
|
2244
2760
|
enabled,
|
|
2245
2761
|
hoverHighlightEnabled,
|
|
2762
|
+
guides,
|
|
2763
|
+
guidesEnabled,
|
|
2246
2764
|
isDragging,
|
|
2247
2765
|
overlayRef,
|
|
2766
|
+
guideOrientation,
|
|
2248
2767
|
setAltPressed,
|
|
2249
2768
|
setEnd,
|
|
2250
2769
|
setGuidePreview,
|
|
@@ -2253,6 +2772,7 @@ var useMeasurerPointer = ({
|
|
|
2253
2772
|
setHoverPointer,
|
|
2254
2773
|
setHoverRect,
|
|
2255
2774
|
setIsDragging,
|
|
2775
|
+
snapGuidesEnabled,
|
|
2256
2776
|
start,
|
|
2257
2777
|
toolMode,
|
|
2258
2778
|
toolbarRef,
|
|
@@ -2260,7 +2780,7 @@ var useMeasurerPointer = ({
|
|
|
2260
2780
|
updateHoverTarget
|
|
2261
2781
|
]
|
|
2262
2782
|
);
|
|
2263
|
-
const handlePointerUp = (0,
|
|
2783
|
+
const handlePointerUp = (0, import_react13.useCallback)(
|
|
2264
2784
|
(event) => {
|
|
2265
2785
|
const commit = createActionCommit();
|
|
2266
2786
|
const toolbarNode = toolbarRef.current;
|
|
@@ -2306,7 +2826,8 @@ var useMeasurerPointer = ({
|
|
|
2306
2826
|
const elements = getElementsInRectCached(
|
|
2307
2827
|
selectionRect,
|
|
2308
2828
|
overlayRef.current,
|
|
2309
|
-
selectionCacheRef.current
|
|
2829
|
+
selectionCacheRef.current,
|
|
2830
|
+
document2
|
|
2310
2831
|
);
|
|
2311
2832
|
const hasSameSelection = elements.length === selectedMeasurements.length && elements.every(
|
|
2312
2833
|
(element, index) => selectedMeasurements[index]?.elementRef === element
|
|
@@ -2317,7 +2838,7 @@ var useMeasurerPointer = ({
|
|
|
2317
2838
|
if (!hasSameSelection) {
|
|
2318
2839
|
commit();
|
|
2319
2840
|
const nextMeasurements = elements.map((element) => ({
|
|
2320
|
-
...getInspectMeasurement(element),
|
|
2841
|
+
...getInspectMeasurement(element, window2),
|
|
2321
2842
|
originRect: selectionRect
|
|
2322
2843
|
}));
|
|
2323
2844
|
setSelectedMeasurements(nextMeasurements);
|
|
@@ -2351,7 +2872,8 @@ var useMeasurerPointer = ({
|
|
|
2351
2872
|
) ?? null : getSelectedMeasurementHit({
|
|
2352
2873
|
point,
|
|
2353
2874
|
selectedMeasurements,
|
|
2354
|
-
overlayNode: overlayRef.current
|
|
2875
|
+
overlayNode: overlayRef.current,
|
|
2876
|
+
document: document2
|
|
2355
2877
|
});
|
|
2356
2878
|
if (event.shiftKey && selectedHit) {
|
|
2357
2879
|
commit();
|
|
@@ -2381,9 +2903,9 @@ var useMeasurerPointer = ({
|
|
|
2381
2903
|
resetDragState();
|
|
2382
2904
|
return;
|
|
2383
2905
|
}
|
|
2384
|
-
const target = event.shiftKey ? getTargetElement(point, overlayRef.current) ?? getSnappedClickTarget(point, overlayRef.current, snapEnabled) : getSnappedClickTarget(point, overlayRef.current, snapEnabled);
|
|
2906
|
+
const target = event.shiftKey ? getTargetElement(point, overlayRef.current, document2) ?? getSnappedClickTarget(point, overlayRef.current, snapEnabled, document2) : getSnappedClickTarget(point, overlayRef.current, snapEnabled, document2);
|
|
2385
2907
|
if (target) {
|
|
2386
|
-
const inspectMeasurement = getInspectMeasurement(target);
|
|
2908
|
+
const inspectMeasurement = getInspectMeasurement(target, window2);
|
|
2387
2909
|
clearTransientMeasurements();
|
|
2388
2910
|
if (event.shiftKey) {
|
|
2389
2911
|
const alreadySelected = selectedMeasurements.some(
|
|
@@ -2458,7 +2980,7 @@ var useMeasurerPointer = ({
|
|
|
2458
2980
|
toolbarRef
|
|
2459
2981
|
]
|
|
2460
2982
|
);
|
|
2461
|
-
const handlePointerLeave = (0,
|
|
2983
|
+
const handlePointerLeave = (0, import_react13.useCallback)(() => {
|
|
2462
2984
|
clearGuideDragHold();
|
|
2463
2985
|
setStart(null);
|
|
2464
2986
|
setEnd(null);
|
|
@@ -2482,41 +3004,48 @@ var useMeasurerPointer = ({
|
|
|
2482
3004
|
};
|
|
2483
3005
|
|
|
2484
3006
|
// hooks/use-overlay-refs.ts
|
|
2485
|
-
var
|
|
3007
|
+
var import_react14 = require("react");
|
|
2486
3008
|
var useOverlayRefs = () => {
|
|
2487
|
-
const overlayRef = (0,
|
|
2488
|
-
const selectedElementRef = (0,
|
|
2489
|
-
const hoverElementRef = (0,
|
|
3009
|
+
const overlayRef = (0, import_react14.useRef)(null);
|
|
3010
|
+
const selectedElementRef = (0, import_react14.useRef)(null);
|
|
3011
|
+
const hoverElementRef = (0, import_react14.useRef)(null);
|
|
2490
3012
|
return { overlayRef, selectedElementRef, hoverElementRef };
|
|
2491
3013
|
};
|
|
2492
3014
|
|
|
2493
3015
|
// hooks/use-resize-sync.ts
|
|
2494
|
-
var
|
|
3016
|
+
var import_react15 = require("react");
|
|
2495
3017
|
var useResizeSync = (params) => {
|
|
2496
|
-
const resizeFrameRef = (0,
|
|
2497
|
-
const viewportRef = (0,
|
|
2498
|
-
(0,
|
|
3018
|
+
const resizeFrameRef = (0, import_react15.useRef)(null);
|
|
3019
|
+
const viewportRef = (0, import_react15.useRef)(getViewportSize(params.window));
|
|
3020
|
+
(0, import_react15.useEffect)(() => {
|
|
2499
3021
|
const handleResize = () => {
|
|
2500
3022
|
if (resizeFrameRef.current) {
|
|
2501
|
-
cancelAnimationFrame(resizeFrameRef.current);
|
|
3023
|
+
params.window.cancelAnimationFrame(resizeFrameRef.current);
|
|
2502
3024
|
}
|
|
2503
|
-
resizeFrameRef.current = requestAnimationFrame(() => {
|
|
2504
|
-
const viewport = getViewportSize();
|
|
3025
|
+
resizeFrameRef.current = params.window.requestAnimationFrame(() => {
|
|
3026
|
+
const viewport = getViewportSize(params.window);
|
|
2505
3027
|
const previousViewport = viewportRef.current;
|
|
2506
3028
|
params.setMeasurements(
|
|
2507
3029
|
(prev) => prev.map(
|
|
2508
|
-
(measurement) => updateMeasurementForResize(measurement, viewport)
|
|
3030
|
+
(measurement) => updateMeasurementForResize(measurement, viewport, params.document)
|
|
2509
3031
|
)
|
|
2510
3032
|
);
|
|
2511
3033
|
params.setActiveMeasurement(
|
|
2512
|
-
(prev) => prev ? updateMeasurementForResize(prev, viewport) : prev
|
|
3034
|
+
(prev) => prev ? updateMeasurementForResize(prev, viewport, params.document) : prev
|
|
2513
3035
|
);
|
|
2514
3036
|
params.setHeldDistances(
|
|
2515
|
-
(prev) => prev.map(
|
|
3037
|
+
(prev) => prev.map(
|
|
3038
|
+
(distance) => updateDistanceForResize(
|
|
3039
|
+
distance,
|
|
3040
|
+
viewport,
|
|
3041
|
+
params.document,
|
|
3042
|
+
params.window
|
|
3043
|
+
)
|
|
3044
|
+
)
|
|
2516
3045
|
);
|
|
2517
|
-
if (params.selectedElementRef.current) {
|
|
3046
|
+
if (params.selectedElementRef.current && params.document.contains(params.selectedElementRef.current)) {
|
|
2518
3047
|
params.setSelectedMeasurement(
|
|
2519
|
-
getInspectMeasurement(params.selectedElementRef.current)
|
|
3048
|
+
getInspectMeasurement(params.selectedElementRef.current, params.window)
|
|
2520
3049
|
);
|
|
2521
3050
|
}
|
|
2522
3051
|
if (previousViewport.width > 0 && previousViewport.height > 0) {
|
|
@@ -2531,27 +3060,27 @@ var useResizeSync = (params) => {
|
|
|
2531
3060
|
viewportRef.current = viewport;
|
|
2532
3061
|
});
|
|
2533
3062
|
};
|
|
2534
|
-
window.addEventListener("resize", handleResize);
|
|
3063
|
+
params.window.addEventListener("resize", handleResize);
|
|
2535
3064
|
return () => {
|
|
2536
3065
|
if (resizeFrameRef.current) {
|
|
2537
|
-
cancelAnimationFrame(resizeFrameRef.current);
|
|
3066
|
+
params.window.cancelAnimationFrame(resizeFrameRef.current);
|
|
2538
3067
|
}
|
|
2539
|
-
window.removeEventListener("resize", handleResize);
|
|
3068
|
+
params.window.removeEventListener("resize", handleResize);
|
|
2540
3069
|
};
|
|
2541
3070
|
}, [params]);
|
|
2542
3071
|
};
|
|
2543
3072
|
|
|
2544
3073
|
// render/measurer-overlay.tsx
|
|
2545
|
-
var
|
|
3074
|
+
var import_react19 = require("react");
|
|
2546
3075
|
|
|
2547
3076
|
// components/measure-tag.tsx
|
|
2548
|
-
var
|
|
3077
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
2549
3078
|
function MeasureTag({
|
|
2550
3079
|
children,
|
|
2551
3080
|
className = "",
|
|
2552
3081
|
style
|
|
2553
3082
|
}) {
|
|
2554
|
-
return /* @__PURE__ */ (0,
|
|
3083
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2555
3084
|
"div",
|
|
2556
3085
|
{
|
|
2557
3086
|
className: cn(
|
|
@@ -2565,31 +3094,21 @@ function MeasureTag({
|
|
|
2565
3094
|
}
|
|
2566
3095
|
|
|
2567
3096
|
// components/measurement-box.tsx
|
|
2568
|
-
var
|
|
2569
|
-
var
|
|
3097
|
+
var import_react16 = require("react");
|
|
3098
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2570
3099
|
var formatValue2 = (value) => Math.round(value);
|
|
2571
|
-
var MeasurementBox = (0,
|
|
3100
|
+
var MeasurementBox = (0, import_react16.memo)(function MeasurementBox2({
|
|
2572
3101
|
measurement,
|
|
2573
3102
|
transitionMs,
|
|
2574
3103
|
labelOffset,
|
|
2575
3104
|
edgeVisibility
|
|
2576
3105
|
}) {
|
|
2577
|
-
const [rect, setRect] = (0, import_react15.useState)(
|
|
2578
|
-
measurement.originRect ?? measurement.rect
|
|
2579
|
-
);
|
|
2580
|
-
(0, import_react15.useEffect)(() => {
|
|
2581
|
-
if (!measurement.originRect) return;
|
|
2582
|
-
const frame = requestAnimationFrame(() => {
|
|
2583
|
-
setRect(measurement.rect);
|
|
2584
|
-
});
|
|
2585
|
-
return () => cancelAnimationFrame(frame);
|
|
2586
|
-
}, [measurement]);
|
|
2587
3106
|
const edges = edgeVisibility ?? { top: true, right: true, bottom: true, left: true };
|
|
2588
|
-
const displayRect = measurement.
|
|
3107
|
+
const displayRect = measurement.rect;
|
|
2589
3108
|
const outlineColor = "color-mix(in oklch, oklch(0.62 0.18 255) 80%, transparent)";
|
|
2590
3109
|
const fillColor = "color-mix(in oklch, oklch(0.62 0.18 255) 8%, transparent)";
|
|
2591
|
-
return /* @__PURE__ */ (0,
|
|
2592
|
-
/* @__PURE__ */ (0,
|
|
3110
|
+
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "msr:pointer-events-none", children: [
|
|
3111
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2593
3112
|
"div",
|
|
2594
3113
|
{
|
|
2595
3114
|
className: "msr:absolute",
|
|
@@ -2599,31 +3118,31 @@ var MeasurementBox = (0, import_react15.memo)(function MeasurementBox2({
|
|
|
2599
3118
|
width: displayRect.width,
|
|
2600
3119
|
height: displayRect.height,
|
|
2601
3120
|
backgroundColor: fillColor,
|
|
2602
|
-
transition:
|
|
3121
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease, width ${transitionMs}ms ease, height ${transitionMs}ms ease`
|
|
2603
3122
|
},
|
|
2604
3123
|
children: [
|
|
2605
|
-
edges.top ? /* @__PURE__ */ (0,
|
|
3124
|
+
edges.top ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2606
3125
|
"div",
|
|
2607
3126
|
{
|
|
2608
3127
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2609
3128
|
style: { backgroundColor: outlineColor }
|
|
2610
3129
|
}
|
|
2611
3130
|
) : null,
|
|
2612
|
-
edges.right ? /* @__PURE__ */ (0,
|
|
3131
|
+
edges.right ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2613
3132
|
"div",
|
|
2614
3133
|
{
|
|
2615
3134
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2616
3135
|
style: { backgroundColor: outlineColor }
|
|
2617
3136
|
}
|
|
2618
3137
|
) : null,
|
|
2619
|
-
edges.bottom ? /* @__PURE__ */ (0,
|
|
3138
|
+
edges.bottom ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2620
3139
|
"div",
|
|
2621
3140
|
{
|
|
2622
3141
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
2623
3142
|
style: { backgroundColor: outlineColor }
|
|
2624
3143
|
}
|
|
2625
3144
|
) : null,
|
|
2626
|
-
edges.left ? /* @__PURE__ */ (0,
|
|
3145
|
+
edges.left ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2627
3146
|
"div",
|
|
2628
3147
|
{
|
|
2629
3148
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -2633,14 +3152,14 @@ var MeasurementBox = (0, import_react15.memo)(function MeasurementBox2({
|
|
|
2633
3152
|
]
|
|
2634
3153
|
}
|
|
2635
3154
|
),
|
|
2636
|
-
/* @__PURE__ */ (0,
|
|
3155
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
|
|
2637
3156
|
MeasureTag,
|
|
2638
3157
|
{
|
|
2639
3158
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
2640
3159
|
style: {
|
|
2641
3160
|
left: displayRect.left + displayRect.width / 2,
|
|
2642
3161
|
top: displayRect.top + displayRect.height + labelOffset,
|
|
2643
|
-
transition:
|
|
3162
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease`
|
|
2644
3163
|
},
|
|
2645
3164
|
children: [
|
|
2646
3165
|
formatValue2(displayRect.width),
|
|
@@ -2653,31 +3172,21 @@ var MeasurementBox = (0, import_react15.memo)(function MeasurementBox2({
|
|
|
2653
3172
|
});
|
|
2654
3173
|
|
|
2655
3174
|
// components/selected-measurement-box.tsx
|
|
2656
|
-
var
|
|
2657
|
-
var
|
|
3175
|
+
var import_react17 = require("react");
|
|
3176
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
2658
3177
|
var formatValue3 = (value) => Math.round(value);
|
|
2659
|
-
var SelectedMeasurementBox = (0,
|
|
3178
|
+
var SelectedMeasurementBox = (0, import_react17.memo)(function SelectedMeasurementBox2({
|
|
2660
3179
|
measurement,
|
|
2661
3180
|
transitionMs,
|
|
2662
3181
|
labelOffset,
|
|
2663
3182
|
edgeVisibility
|
|
2664
3183
|
}) {
|
|
2665
|
-
const [rect, setRect] = (0, import_react16.useState)(
|
|
2666
|
-
measurement.originRect ?? measurement.rect
|
|
2667
|
-
);
|
|
2668
|
-
(0, import_react16.useEffect)(() => {
|
|
2669
|
-
if (!measurement.originRect) return;
|
|
2670
|
-
const frame = requestAnimationFrame(() => {
|
|
2671
|
-
setRect(measurement.rect);
|
|
2672
|
-
});
|
|
2673
|
-
return () => cancelAnimationFrame(frame);
|
|
2674
|
-
}, [measurement]);
|
|
2675
3184
|
const edges = edgeVisibility ?? { top: true, right: true, bottom: true, left: true };
|
|
2676
|
-
const displayRect = measurement.
|
|
3185
|
+
const displayRect = measurement.rect;
|
|
2677
3186
|
const outlineColor = "color-mix(in oklch, oklch(0.62 0.18 255) 80%, transparent)";
|
|
2678
3187
|
const fillColor = "color-mix(in oklch, oklch(0.62 0.18 255) 8%, transparent)";
|
|
2679
|
-
return /* @__PURE__ */ (0,
|
|
2680
|
-
/* @__PURE__ */ (0,
|
|
3188
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "msr:pointer-events-none", children: [
|
|
3189
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2681
3190
|
"div",
|
|
2682
3191
|
{
|
|
2683
3192
|
className: "msr:absolute",
|
|
@@ -2687,31 +3196,31 @@ var SelectedMeasurementBox = (0, import_react16.memo)(function SelectedMeasureme
|
|
|
2687
3196
|
width: displayRect.width,
|
|
2688
3197
|
height: displayRect.height,
|
|
2689
3198
|
backgroundColor: fillColor,
|
|
2690
|
-
transition:
|
|
3199
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease, width ${transitionMs}ms ease, height ${transitionMs}ms ease`
|
|
2691
3200
|
},
|
|
2692
3201
|
children: [
|
|
2693
|
-
edges.top ? /* @__PURE__ */ (0,
|
|
3202
|
+
edges.top ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2694
3203
|
"div",
|
|
2695
3204
|
{
|
|
2696
3205
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2697
3206
|
style: { backgroundColor: outlineColor }
|
|
2698
3207
|
}
|
|
2699
3208
|
) : null,
|
|
2700
|
-
edges.right ? /* @__PURE__ */ (0,
|
|
3209
|
+
edges.right ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2701
3210
|
"div",
|
|
2702
3211
|
{
|
|
2703
3212
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2704
3213
|
style: { backgroundColor: outlineColor }
|
|
2705
3214
|
}
|
|
2706
3215
|
) : null,
|
|
2707
|
-
edges.bottom ? /* @__PURE__ */ (0,
|
|
3216
|
+
edges.bottom ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2708
3217
|
"div",
|
|
2709
3218
|
{
|
|
2710
3219
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
2711
3220
|
style: { backgroundColor: outlineColor }
|
|
2712
3221
|
}
|
|
2713
3222
|
) : null,
|
|
2714
|
-
edges.left ? /* @__PURE__ */ (0,
|
|
3223
|
+
edges.left ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
2715
3224
|
"div",
|
|
2716
3225
|
{
|
|
2717
3226
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -2721,14 +3230,14 @@ var SelectedMeasurementBox = (0, import_react16.memo)(function SelectedMeasureme
|
|
|
2721
3230
|
]
|
|
2722
3231
|
}
|
|
2723
3232
|
),
|
|
2724
|
-
/* @__PURE__ */ (0,
|
|
3233
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2725
3234
|
MeasureTag,
|
|
2726
3235
|
{
|
|
2727
3236
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
2728
3237
|
style: {
|
|
2729
3238
|
left: displayRect.left + displayRect.width / 2,
|
|
2730
3239
|
top: displayRect.top + displayRect.height + labelOffset,
|
|
2731
|
-
transition:
|
|
3240
|
+
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease`
|
|
2732
3241
|
},
|
|
2733
3242
|
children: [
|
|
2734
3243
|
formatValue3(displayRect.width),
|
|
@@ -2741,14 +3250,14 @@ var SelectedMeasurementBox = (0, import_react16.memo)(function SelectedMeasureme
|
|
|
2741
3250
|
});
|
|
2742
3251
|
|
|
2743
3252
|
// render/distance-overlay-item.tsx
|
|
2744
|
-
var
|
|
2745
|
-
var
|
|
2746
|
-
var DistanceOverlayItem = (0,
|
|
3253
|
+
var import_react18 = require("react");
|
|
3254
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
3255
|
+
var DistanceOverlayItem = (0, import_react18.memo)(function DistanceOverlayItem2({
|
|
2747
3256
|
distance,
|
|
2748
3257
|
labelOffset,
|
|
2749
3258
|
onRemove
|
|
2750
3259
|
}) {
|
|
2751
|
-
return /* @__PURE__ */ (0,
|
|
3260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
2752
3261
|
"div",
|
|
2753
3262
|
{
|
|
2754
3263
|
className: onRemove ? "msr:pointer-events-auto" : "msr:pointer-events-none",
|
|
@@ -2757,7 +3266,7 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2757
3266
|
onRemove(distance.id);
|
|
2758
3267
|
} : void 0,
|
|
2759
3268
|
children: [
|
|
2760
|
-
/* @__PURE__ */ (0,
|
|
3269
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2761
3270
|
"div",
|
|
2762
3271
|
{
|
|
2763
3272
|
className: "msr:absolute msr:rounded msr:border msr:border-[#2563eb]/70",
|
|
@@ -2769,7 +3278,7 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2769
3278
|
}
|
|
2770
3279
|
}
|
|
2771
3280
|
),
|
|
2772
|
-
/* @__PURE__ */ (0,
|
|
3281
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2773
3282
|
"div",
|
|
2774
3283
|
{
|
|
2775
3284
|
className: "msr:absolute msr:rounded msr:border msr:border-[#2563eb]/70",
|
|
@@ -2782,7 +3291,7 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2782
3291
|
}
|
|
2783
3292
|
),
|
|
2784
3293
|
distance.connectors.map(
|
|
2785
|
-
(connector, index) => Math.abs(connector.x1 - connector.x2) < 1 ? /* @__PURE__ */ (0,
|
|
3294
|
+
(connector, index) => Math.abs(connector.x1 - connector.x2) < 1 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2786
3295
|
"div",
|
|
2787
3296
|
{
|
|
2788
3297
|
className: "msr:absolute msr:border-l msr:border-dashed msr:border-[#2563eb]/70",
|
|
@@ -2793,7 +3302,7 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2793
3302
|
}
|
|
2794
3303
|
},
|
|
2795
3304
|
`${distance.id}-connector-${index}`
|
|
2796
|
-
) : /* @__PURE__ */ (0,
|
|
3305
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2797
3306
|
"div",
|
|
2798
3307
|
{
|
|
2799
3308
|
className: "msr:absolute msr:border-t msr:border-dashed msr:border-[#2563eb]/70",
|
|
@@ -2806,8 +3315,8 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2806
3315
|
`${distance.id}-connector-${index}`
|
|
2807
3316
|
)
|
|
2808
3317
|
),
|
|
2809
|
-
distance.horizontal && distance.horizontal.value > 0 ? /* @__PURE__ */ (0,
|
|
2810
|
-
/* @__PURE__ */ (0,
|
|
3318
|
+
distance.horizontal && distance.horizontal.value > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3319
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2811
3320
|
"div",
|
|
2812
3321
|
{
|
|
2813
3322
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -2818,7 +3327,7 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2818
3327
|
}
|
|
2819
3328
|
}
|
|
2820
3329
|
),
|
|
2821
|
-
/* @__PURE__ */ (0,
|
|
3330
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2822
3331
|
MeasureTag,
|
|
2823
3332
|
{
|
|
2824
3333
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -2830,8 +3339,8 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2830
3339
|
}
|
|
2831
3340
|
)
|
|
2832
3341
|
] }) : null,
|
|
2833
|
-
distance.vertical && distance.vertical.value > 0 ? /* @__PURE__ */ (0,
|
|
2834
|
-
/* @__PURE__ */ (0,
|
|
3342
|
+
distance.vertical && distance.vertical.value > 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
3343
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2835
3344
|
"div",
|
|
2836
3345
|
{
|
|
2837
3346
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -2842,7 +3351,7 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2842
3351
|
}
|
|
2843
3352
|
}
|
|
2844
3353
|
),
|
|
2845
|
-
/* @__PURE__ */ (0,
|
|
3354
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
2846
3355
|
MeasureTag,
|
|
2847
3356
|
{
|
|
2848
3357
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -2860,10 +3369,11 @@ var DistanceOverlayItem = (0, import_react17.memo)(function DistanceOverlayItem2
|
|
|
2860
3369
|
});
|
|
2861
3370
|
|
|
2862
3371
|
// render/measurer-overlay.tsx
|
|
2863
|
-
var
|
|
2864
|
-
var MeasurerOverlay = (0,
|
|
3372
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
3373
|
+
var MeasurerOverlay = (0, import_react19.memo)(function MeasurerOverlay2({
|
|
2865
3374
|
enabled,
|
|
2866
3375
|
toolMode,
|
|
3376
|
+
guidePointerEvents,
|
|
2867
3377
|
guidesEnabled,
|
|
2868
3378
|
altPressed,
|
|
2869
3379
|
isDragging,
|
|
@@ -2900,16 +3410,20 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
2900
3410
|
onGuidePointerUp,
|
|
2901
3411
|
onGuidePointerCancel
|
|
2902
3412
|
}) {
|
|
2903
|
-
|
|
3413
|
+
const overlayVisible = enabled;
|
|
3414
|
+
const overlayInteractive = overlayVisible && toolMode !== "none" && toolMode !== "text-inspector" && toolMode !== "xray" && toolMode !== "rulers";
|
|
3415
|
+
const selectionVisible = toolMode === "select";
|
|
3416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2904
3417
|
"div",
|
|
2905
3418
|
{
|
|
2906
|
-
className: `msr:absolute msr:inset-0 ${
|
|
3419
|
+
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"}`,
|
|
3420
|
+
style: { pointerEvents: overlayInteractive ? "auto" : "none" },
|
|
2907
3421
|
onPointerDown,
|
|
2908
3422
|
onPointerMove,
|
|
2909
3423
|
onPointerUp,
|
|
2910
3424
|
onPointerLeave,
|
|
2911
3425
|
children: [
|
|
2912
|
-
|
|
3426
|
+
selectionVisible ? displayedMeasurements.map((measurement, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2913
3427
|
MeasurementBox,
|
|
2914
3428
|
{
|
|
2915
3429
|
measurement,
|
|
@@ -2919,8 +3433,8 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
2919
3433
|
},
|
|
2920
3434
|
measurement.id
|
|
2921
3435
|
)) : null,
|
|
2922
|
-
|
|
2923
|
-
/* @__PURE__ */ (0,
|
|
3436
|
+
selectionVisible && activeRect && isDragging ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3437
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2924
3438
|
"div",
|
|
2925
3439
|
{
|
|
2926
3440
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -2932,28 +3446,28 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
2932
3446
|
backgroundColor: fillColor
|
|
2933
3447
|
},
|
|
2934
3448
|
children: [
|
|
2935
|
-
/* @__PURE__ */ (0,
|
|
3449
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2936
3450
|
"div",
|
|
2937
3451
|
{
|
|
2938
3452
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2939
3453
|
style: { backgroundColor: outlineColor }
|
|
2940
3454
|
}
|
|
2941
3455
|
),
|
|
2942
|
-
/* @__PURE__ */ (0,
|
|
3456
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2943
3457
|
"div",
|
|
2944
3458
|
{
|
|
2945
3459
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
2946
3460
|
style: { backgroundColor: outlineColor }
|
|
2947
3461
|
}
|
|
2948
3462
|
),
|
|
2949
|
-
/* @__PURE__ */ (0,
|
|
3463
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2950
3464
|
"div",
|
|
2951
3465
|
{
|
|
2952
3466
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
2953
3467
|
style: { backgroundColor: outlineColor }
|
|
2954
3468
|
}
|
|
2955
3469
|
),
|
|
2956
|
-
/* @__PURE__ */ (0,
|
|
3470
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2957
3471
|
"div",
|
|
2958
3472
|
{
|
|
2959
3473
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -2963,7 +3477,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
2963
3477
|
]
|
|
2964
3478
|
}
|
|
2965
3479
|
),
|
|
2966
|
-
/* @__PURE__ */ (0,
|
|
3480
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2967
3481
|
MeasureTag,
|
|
2968
3482
|
{
|
|
2969
3483
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -2979,7 +3493,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
2979
3493
|
}
|
|
2980
3494
|
)
|
|
2981
3495
|
] }) : null,
|
|
2982
|
-
|
|
3496
|
+
selectionVisible && hoverRectToShow ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
|
|
2983
3497
|
"div",
|
|
2984
3498
|
{
|
|
2985
3499
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -2991,28 +3505,28 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
2991
3505
|
backgroundColor: fillColor
|
|
2992
3506
|
},
|
|
2993
3507
|
children: [
|
|
2994
|
-
hoverEdgeVisibility?.top ? /* @__PURE__ */ (0,
|
|
3508
|
+
hoverEdgeVisibility?.top ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
2995
3509
|
"div",
|
|
2996
3510
|
{
|
|
2997
3511
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
2998
3512
|
style: { backgroundColor: outlineColor }
|
|
2999
3513
|
}
|
|
3000
3514
|
) : null,
|
|
3001
|
-
hoverEdgeVisibility?.right ? /* @__PURE__ */ (0,
|
|
3515
|
+
hoverEdgeVisibility?.right ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3002
3516
|
"div",
|
|
3003
3517
|
{
|
|
3004
3518
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
3005
3519
|
style: { backgroundColor: outlineColor }
|
|
3006
3520
|
}
|
|
3007
3521
|
) : null,
|
|
3008
|
-
hoverEdgeVisibility?.bottom ? /* @__PURE__ */ (0,
|
|
3522
|
+
hoverEdgeVisibility?.bottom ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3009
3523
|
"div",
|
|
3010
3524
|
{
|
|
3011
3525
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
3012
3526
|
style: { backgroundColor: outlineColor }
|
|
3013
3527
|
}
|
|
3014
3528
|
) : null,
|
|
3015
|
-
hoverEdgeVisibility?.left ? /* @__PURE__ */ (0,
|
|
3529
|
+
hoverEdgeVisibility?.left ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3016
3530
|
"div",
|
|
3017
3531
|
{
|
|
3018
3532
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -3022,7 +3536,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3022
3536
|
]
|
|
3023
3537
|
}
|
|
3024
3538
|
) : null,
|
|
3025
|
-
guidesEnabled && guidePreview ? /* @__PURE__ */ (0,
|
|
3539
|
+
guidesEnabled && guidePreview ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3026
3540
|
"div",
|
|
3027
3541
|
{
|
|
3028
3542
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -3037,7 +3551,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3037
3551
|
height: GUIDE_HITBOX_SIZE,
|
|
3038
3552
|
width: "100%"
|
|
3039
3553
|
},
|
|
3040
|
-
children: /* @__PURE__ */ (0,
|
|
3554
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3041
3555
|
"div",
|
|
3042
3556
|
{
|
|
3043
3557
|
className: "msr:absolute",
|
|
@@ -3058,7 +3572,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3058
3572
|
)
|
|
3059
3573
|
}
|
|
3060
3574
|
) : null,
|
|
3061
|
-
|
|
3575
|
+
selectionVisible ? displayedSelectedMeasurements.map((measurement, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3062
3576
|
SelectedMeasurementBox,
|
|
3063
3577
|
{
|
|
3064
3578
|
measurement,
|
|
@@ -3068,7 +3582,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3068
3582
|
},
|
|
3069
3583
|
measurement.id
|
|
3070
3584
|
)) : null,
|
|
3071
|
-
heldDistances.map((distance) => /* @__PURE__ */ (0,
|
|
3585
|
+
heldDistances.map((distance) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3072
3586
|
DistanceOverlayItem,
|
|
3073
3587
|
{
|
|
3074
3588
|
distance,
|
|
@@ -3077,7 +3591,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3077
3591
|
},
|
|
3078
3592
|
`held-${distance.id}`
|
|
3079
3593
|
)),
|
|
3080
|
-
|
|
3594
|
+
selectionVisible && altPressed && optionPairOverlay ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3081
3595
|
DistanceOverlayItem,
|
|
3082
3596
|
{
|
|
3083
3597
|
distance: optionPairOverlay,
|
|
@@ -3085,7 +3599,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3085
3599
|
},
|
|
3086
3600
|
`option-${optionPairOverlay.id}`
|
|
3087
3601
|
) : null,
|
|
3088
|
-
guidesEnabled && altPressed && guideDistanceOverlay ? /* @__PURE__ */ (0,
|
|
3602
|
+
guidesEnabled && altPressed && guideDistanceOverlay ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3089
3603
|
DistanceOverlayItem,
|
|
3090
3604
|
{
|
|
3091
3605
|
distance: guideDistanceOverlay,
|
|
@@ -3093,9 +3607,9 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3093
3607
|
},
|
|
3094
3608
|
`guide-preview-${guideDistanceOverlay.id}`
|
|
3095
3609
|
) : null,
|
|
3096
|
-
|
|
3097
|
-
optionContainerLines.top.value > 0 ? /* @__PURE__ */ (0,
|
|
3098
|
-
/* @__PURE__ */ (0,
|
|
3610
|
+
selectionVisible && altPressed && optionContainerLines ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3611
|
+
optionContainerLines.top.value > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3612
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3099
3613
|
"div",
|
|
3100
3614
|
{
|
|
3101
3615
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3106,7 +3620,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3106
3620
|
}
|
|
3107
3621
|
}
|
|
3108
3622
|
),
|
|
3109
|
-
/* @__PURE__ */ (0,
|
|
3623
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3110
3624
|
MeasureTag,
|
|
3111
3625
|
{
|
|
3112
3626
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3118,8 +3632,8 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3118
3632
|
}
|
|
3119
3633
|
)
|
|
3120
3634
|
] }) : null,
|
|
3121
|
-
optionContainerLines.bottom.value > 0 ? /* @__PURE__ */ (0,
|
|
3122
|
-
/* @__PURE__ */ (0,
|
|
3635
|
+
optionContainerLines.bottom.value > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3636
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3123
3637
|
"div",
|
|
3124
3638
|
{
|
|
3125
3639
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3130,7 +3644,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3130
3644
|
}
|
|
3131
3645
|
}
|
|
3132
3646
|
),
|
|
3133
|
-
/* @__PURE__ */ (0,
|
|
3647
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3134
3648
|
MeasureTag,
|
|
3135
3649
|
{
|
|
3136
3650
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3142,8 +3656,8 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3142
3656
|
}
|
|
3143
3657
|
)
|
|
3144
3658
|
] }) : null,
|
|
3145
|
-
optionContainerLines.left.value > 0 ? /* @__PURE__ */ (0,
|
|
3146
|
-
/* @__PURE__ */ (0,
|
|
3659
|
+
optionContainerLines.left.value > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3660
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3147
3661
|
"div",
|
|
3148
3662
|
{
|
|
3149
3663
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3154,7 +3668,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3154
3668
|
}
|
|
3155
3669
|
}
|
|
3156
3670
|
),
|
|
3157
|
-
/* @__PURE__ */ (0,
|
|
3671
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3158
3672
|
MeasureTag,
|
|
3159
3673
|
{
|
|
3160
3674
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3166,8 +3680,8 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3166
3680
|
}
|
|
3167
3681
|
)
|
|
3168
3682
|
] }) : null,
|
|
3169
|
-
optionContainerLines.right.value > 0 ? /* @__PURE__ */ (0,
|
|
3170
|
-
/* @__PURE__ */ (0,
|
|
3683
|
+
optionContainerLines.right.value > 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(import_jsx_runtime8.Fragment, { children: [
|
|
3684
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3171
3685
|
"div",
|
|
3172
3686
|
{
|
|
3173
3687
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3178,7 +3692,7 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3178
3692
|
}
|
|
3179
3693
|
}
|
|
3180
3694
|
),
|
|
3181
|
-
/* @__PURE__ */ (0,
|
|
3695
|
+
/* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3182
3696
|
MeasureTag,
|
|
3183
3697
|
{
|
|
3184
3698
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3196,25 +3710,28 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3196
3710
|
const isHovered = hoverGuide?.id === guide.id;
|
|
3197
3711
|
const strokeWidth = isSelected || isHovered ? 2 : 1;
|
|
3198
3712
|
const strokeColor = isSelected ? guideColorActive : isHovered ? guideColorHover : guideColorDefault;
|
|
3199
|
-
return /* @__PURE__ */ (0,
|
|
3713
|
+
return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3200
3714
|
"div",
|
|
3201
3715
|
{
|
|
3202
3716
|
className: "msr:absolute",
|
|
3717
|
+
"data-mesurer-guide": "true",
|
|
3203
3718
|
style: guide.orientation === "vertical" ? {
|
|
3204
3719
|
left: guide.position - GUIDE_HITBOX_SIZE / 2,
|
|
3205
3720
|
top: 0,
|
|
3206
3721
|
width: GUIDE_HITBOX_SIZE,
|
|
3207
|
-
height: "100%"
|
|
3722
|
+
height: "100%",
|
|
3723
|
+
pointerEvents: guidePointerEvents ? "auto" : "none"
|
|
3208
3724
|
} : {
|
|
3209
3725
|
top: guide.position - GUIDE_HITBOX_SIZE / 2,
|
|
3210
3726
|
left: 0,
|
|
3211
3727
|
height: GUIDE_HITBOX_SIZE,
|
|
3212
|
-
width: "100%"
|
|
3728
|
+
width: "100%",
|
|
3729
|
+
pointerEvents: guidePointerEvents ? "auto" : "none"
|
|
3213
3730
|
},
|
|
3214
3731
|
onPointerDown: (event) => onGuidePointerDown(guide, event),
|
|
3215
3732
|
onPointerUp: (event) => onGuidePointerUp(guide, event),
|
|
3216
3733
|
onPointerCancel: (event) => onGuidePointerCancel(guide, event),
|
|
3217
|
-
children: /* @__PURE__ */ (0,
|
|
3734
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
3218
3735
|
"div",
|
|
3219
3736
|
{
|
|
3220
3737
|
className: "msr:absolute",
|
|
@@ -3242,46 +3759,991 @@ var MeasurerOverlay = (0, import_react18.memo)(function MeasurerOverlay2({
|
|
|
3242
3759
|
);
|
|
3243
3760
|
});
|
|
3244
3761
|
|
|
3245
|
-
//
|
|
3246
|
-
var
|
|
3247
|
-
var
|
|
3762
|
+
// runtime/text-inspector-dom.ts
|
|
3763
|
+
var INK_50 = "#f8fafc";
|
|
3764
|
+
var INK_200 = "#e2e8f0";
|
|
3765
|
+
var INK_500 = "#64748b";
|
|
3766
|
+
var INK_900 = "#0f172a";
|
|
3767
|
+
var makeEdge = (document2, side, color) => {
|
|
3768
|
+
const edge = document2.createElement("div");
|
|
3769
|
+
Object.assign(edge.style, {
|
|
3770
|
+
position: "absolute",
|
|
3771
|
+
backgroundColor: color,
|
|
3772
|
+
...side === "top" || side === "bottom" ? { left: "0", [side]: "0", width: "100%", height: "1px" } : { top: "0", [side]: "0", width: "1px", height: "100%" }
|
|
3773
|
+
});
|
|
3774
|
+
return edge;
|
|
3248
3775
|
};
|
|
3249
|
-
var
|
|
3250
|
-
|
|
3251
|
-
(
|
|
3252
|
-
|
|
3253
|
-
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
|
|
3257
|
-
});
|
|
3258
|
-
|
|
3259
|
-
|
|
3260
|
-
|
|
3261
|
-
|
|
3262
|
-
}
|
|
3263
|
-
|
|
3776
|
+
var makeBox = (document2, fill, outline) => {
|
|
3777
|
+
const box = document2.createElement("div");
|
|
3778
|
+
Object.assign(box.style, {
|
|
3779
|
+
position: "fixed",
|
|
3780
|
+
zIndex: "0",
|
|
3781
|
+
pointerEvents: "none",
|
|
3782
|
+
backgroundColor: fill,
|
|
3783
|
+
boxSizing: "border-box"
|
|
3784
|
+
});
|
|
3785
|
+
box.className = "mesurer-ti-box";
|
|
3786
|
+
box.dataset.state = "hidden";
|
|
3787
|
+
for (const side of ["top", "right", "bottom", "left"]) {
|
|
3788
|
+
box.appendChild(makeEdge(document2, side, outline));
|
|
3789
|
+
}
|
|
3790
|
+
return box;
|
|
3791
|
+
};
|
|
3792
|
+
var positionBox = (box, rect) => {
|
|
3793
|
+
Object.assign(box.style, {
|
|
3794
|
+
left: `${rect.left}px`,
|
|
3795
|
+
top: `${rect.top}px`,
|
|
3796
|
+
width: `${rect.width}px`,
|
|
3797
|
+
height: `${rect.height}px`
|
|
3798
|
+
});
|
|
3799
|
+
};
|
|
3800
|
+
var makeCard = (document2, pinned) => {
|
|
3801
|
+
const card = document2.createElement("div");
|
|
3802
|
+
Object.assign(card.style, {
|
|
3803
|
+
position: "fixed",
|
|
3804
|
+
zIndex: "1",
|
|
3805
|
+
pointerEvents: pinned ? "auto" : "none",
|
|
3806
|
+
background: "#ffffff",
|
|
3807
|
+
color: INK_900,
|
|
3808
|
+
borderRadius: "13px",
|
|
3809
|
+
padding: "10px 12px",
|
|
3810
|
+
fontSize: "11px",
|
|
3811
|
+
lineHeight: "1.5",
|
|
3812
|
+
fontFamily: "ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, sans-serif",
|
|
3813
|
+
fontVariantNumeric: "tabular-nums",
|
|
3814
|
+
userSelect: "none",
|
|
3815
|
+
whiteSpace: "nowrap",
|
|
3816
|
+
width: "320px",
|
|
3817
|
+
minWidth: "320px",
|
|
3818
|
+
maxWidth: "320px",
|
|
3819
|
+
boxSizing: "border-box",
|
|
3820
|
+
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)"
|
|
3821
|
+
});
|
|
3822
|
+
card.className = pinned ? "mesurer-ti-card mesurer-ti-card--pinned" : "mesurer-ti-card";
|
|
3823
|
+
card.dataset.state = "hidden";
|
|
3824
|
+
return card;
|
|
3825
|
+
};
|
|
3826
|
+
var populateCard = (document2, card, info, pinned) => {
|
|
3827
|
+
card.replaceChildren();
|
|
3828
|
+
const header = document2.createElement("div");
|
|
3829
|
+
Object.assign(header.style, {
|
|
3830
|
+
display: "flex",
|
|
3831
|
+
alignItems: "center",
|
|
3832
|
+
gap: "8px",
|
|
3833
|
+
marginBottom: "8px",
|
|
3834
|
+
paddingBottom: "6px"
|
|
3835
|
+
});
|
|
3836
|
+
const tag = document2.createElement("span");
|
|
3837
|
+
Object.assign(tag.style, {
|
|
3838
|
+
color: INK_50,
|
|
3839
|
+
background: INK_900,
|
|
3840
|
+
borderRadius: "4px",
|
|
3841
|
+
padding: "1px 5px",
|
|
3842
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
3843
|
+
fontSize: "10px",
|
|
3844
|
+
fontWeight: "500"
|
|
3845
|
+
});
|
|
3846
|
+
tag.textContent = info.tagName;
|
|
3847
|
+
header.appendChild(tag);
|
|
3848
|
+
if (info.textSnippet) {
|
|
3849
|
+
const snippet = document2.createElement("span");
|
|
3850
|
+
Object.assign(snippet.style, {
|
|
3851
|
+
color: INK_500,
|
|
3852
|
+
overflow: "hidden",
|
|
3853
|
+
textOverflow: "ellipsis",
|
|
3854
|
+
whiteSpace: "nowrap",
|
|
3855
|
+
flex: "1",
|
|
3856
|
+
minWidth: "0",
|
|
3857
|
+
fontSize: "10px"
|
|
3858
|
+
});
|
|
3859
|
+
snippet.textContent = info.textSnippet;
|
|
3860
|
+
header.appendChild(snippet);
|
|
3861
|
+
}
|
|
3862
|
+
if (pinned) {
|
|
3863
|
+
const close = document2.createElement("button");
|
|
3864
|
+
close.type = "button";
|
|
3865
|
+
close.className = "mesurer-ti-close";
|
|
3866
|
+
close.setAttribute("aria-label", "Close");
|
|
3867
|
+
close.textContent = "\xD7";
|
|
3868
|
+
Object.assign(close.style, {
|
|
3869
|
+
all: "unset",
|
|
3870
|
+
marginLeft: info.textSnippet ? "0" : "auto",
|
|
3871
|
+
flex: "0 0 auto",
|
|
3872
|
+
width: "16px",
|
|
3873
|
+
height: "16px",
|
|
3874
|
+
lineHeight: "14px",
|
|
3875
|
+
textAlign: "center",
|
|
3876
|
+
borderRadius: "4px",
|
|
3877
|
+
color: INK_500,
|
|
3878
|
+
fontSize: "14px"
|
|
3879
|
+
});
|
|
3880
|
+
header.appendChild(close);
|
|
3881
|
+
}
|
|
3882
|
+
card.appendChild(header);
|
|
3883
|
+
const grid = document2.createElement("div");
|
|
3884
|
+
Object.assign(grid.style, {
|
|
3885
|
+
display: "grid",
|
|
3886
|
+
gridTemplateColumns: "auto 1fr",
|
|
3887
|
+
columnGap: "12px",
|
|
3888
|
+
rowGap: "3px",
|
|
3889
|
+
alignItems: "baseline"
|
|
3890
|
+
});
|
|
3891
|
+
for (const row of info.rows) {
|
|
3892
|
+
const label = document2.createElement("span");
|
|
3893
|
+
label.style.color = INK_500;
|
|
3894
|
+
label.style.fontSize = "11px";
|
|
3895
|
+
label.textContent = row.label;
|
|
3896
|
+
const value = document2.createElement("span");
|
|
3897
|
+
Object.assign(value.style, {
|
|
3898
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
3899
|
+
fontSize: "11px",
|
|
3900
|
+
color: INK_900,
|
|
3901
|
+
overflow: "hidden",
|
|
3902
|
+
textOverflow: "ellipsis",
|
|
3903
|
+
whiteSpace: "nowrap"
|
|
3904
|
+
});
|
|
3905
|
+
if (!row.varName) {
|
|
3906
|
+
value.textContent = row.value;
|
|
3907
|
+
} else {
|
|
3908
|
+
const variable = document2.createElement("span");
|
|
3909
|
+
variable.textContent = row.value;
|
|
3910
|
+
const separator = document2.createElement("span");
|
|
3911
|
+
separator.style.color = INK_200;
|
|
3912
|
+
separator.style.margin = "0 6px";
|
|
3913
|
+
separator.textContent = "\xB7";
|
|
3914
|
+
const name = document2.createElement("span");
|
|
3915
|
+
name.style.color = "#0369a1";
|
|
3916
|
+
name.textContent = row.varName;
|
|
3917
|
+
value.append(variable, separator, name);
|
|
3918
|
+
}
|
|
3919
|
+
grid.append(label, value);
|
|
3920
|
+
}
|
|
3921
|
+
card.appendChild(grid);
|
|
3922
|
+
};
|
|
3923
|
+
var positionCard = (window2, card, rect, offsetX = 0, offsetY = 0) => {
|
|
3924
|
+
const center = rect.left + rect.width / 2 + offsetX;
|
|
3925
|
+
card.style.left = `${center}px`;
|
|
3926
|
+
const size = card.getBoundingClientRect();
|
|
3927
|
+
let top = rect.bottom + 4 + offsetY;
|
|
3928
|
+
if (top + size.height > window2.innerHeight - 8) {
|
|
3929
|
+
top = rect.top - size.height - 4 + offsetY;
|
|
3930
|
+
}
|
|
3931
|
+
card.style.top = `${Math.max(8, top)}px`;
|
|
3932
|
+
const half = size.width / 2;
|
|
3933
|
+
card.style.left = `${Math.min(
|
|
3934
|
+
Math.max(center, 8 + half),
|
|
3935
|
+
window2.innerWidth - 8 - half
|
|
3936
|
+
)}px`;
|
|
3937
|
+
};
|
|
3938
|
+
|
|
3939
|
+
// runtime/text-inspector-typography.ts
|
|
3940
|
+
var FONT_WEIGHT_KEYWORD = {
|
|
3941
|
+
"100": "thin",
|
|
3942
|
+
"200": "extralight",
|
|
3943
|
+
"300": "light",
|
|
3944
|
+
"400": "normal",
|
|
3945
|
+
"500": "medium",
|
|
3946
|
+
"600": "semibold",
|
|
3947
|
+
"700": "bold",
|
|
3948
|
+
"800": "extrabold",
|
|
3949
|
+
"900": "black"
|
|
3950
|
+
};
|
|
3951
|
+
var TYPO_PROPS = [
|
|
3952
|
+
"font-family",
|
|
3953
|
+
"font-size",
|
|
3954
|
+
"font-weight",
|
|
3955
|
+
"line-height",
|
|
3956
|
+
"letter-spacing"
|
|
3957
|
+
];
|
|
3958
|
+
var TYPO_LABELS = {
|
|
3959
|
+
Family: "font-family",
|
|
3960
|
+
Size: "font-size",
|
|
3961
|
+
Weight: "font-weight",
|
|
3962
|
+
Line: "line-height",
|
|
3963
|
+
Tracking: "letter-spacing"
|
|
3964
|
+
};
|
|
3965
|
+
var formatPx = (raw) => {
|
|
3966
|
+
if (!raw || raw === "normal") return raw || "normal";
|
|
3967
|
+
const match = /^(-?[\d.]+)px$/.exec(raw);
|
|
3968
|
+
if (!match) return raw;
|
|
3969
|
+
return `${Math.round(Number(match[1]) * 10) / 10}px`;
|
|
3970
|
+
};
|
|
3971
|
+
var firstFontFamily = (families) => (families.split(",")[0] ?? "").trim().replace(/^['"]|['"]$/g, "");
|
|
3972
|
+
var weightWithKeyword = (weight) => {
|
|
3973
|
+
const keyword = FONT_WEIGHT_KEYWORD[weight];
|
|
3974
|
+
return keyword ? `${weight} / ${keyword}` : weight;
|
|
3975
|
+
};
|
|
3976
|
+
var extractVarName = (value) => {
|
|
3977
|
+
if (!value) return null;
|
|
3978
|
+
return /var\(\s*(--[a-zA-Z0-9_-]+)/.exec(value)?.[1] ?? null;
|
|
3979
|
+
};
|
|
3980
|
+
var selectorSpecificity = (selector) => {
|
|
3981
|
+
const ids = (selector.match(/#[\w-]+/g) ?? []).length;
|
|
3982
|
+
const classes = (selector.match(/\.[\w-]+|\[[^\]]+\]|:[\w-]+/g) ?? []).length;
|
|
3983
|
+
const elements = (selector.match(/(?:^|[ >+~])([a-zA-Z][\w-]*)/g) ?? []).length;
|
|
3984
|
+
return ids * 1e4 + classes * 100 + elements;
|
|
3985
|
+
};
|
|
3986
|
+
var wins = (next, previous) => {
|
|
3987
|
+
if (!previous) return true;
|
|
3988
|
+
if (next.important !== previous.important) return next.important;
|
|
3989
|
+
if (next.specificity !== previous.specificity) {
|
|
3990
|
+
return next.specificity > previous.specificity;
|
|
3991
|
+
}
|
|
3992
|
+
return next.order > previous.order;
|
|
3993
|
+
};
|
|
3994
|
+
var TypographyInspector = class {
|
|
3995
|
+
constructor(document2, window2) {
|
|
3996
|
+
this.document = document2;
|
|
3997
|
+
this.window = window2;
|
|
3998
|
+
}
|
|
3999
|
+
collectRules(rules, output, mediaOk, order) {
|
|
4000
|
+
for (let i = 0; i < rules.length; i++) {
|
|
4001
|
+
const rule = rules[i];
|
|
4002
|
+
const currentOrder = order.value++;
|
|
4003
|
+
if (rule.type === 4) {
|
|
4004
|
+
const mediaRule = rule;
|
|
4005
|
+
let matches = mediaOk;
|
|
4006
|
+
try {
|
|
4007
|
+
matches = mediaOk && this.window.matchMedia(mediaRule.media.mediaText).matches;
|
|
4008
|
+
} catch {
|
|
4009
|
+
matches = false;
|
|
4010
|
+
}
|
|
4011
|
+
this.collectRules(mediaRule.cssRules, output, matches, order);
|
|
4012
|
+
} else if (rule.type === 12) {
|
|
4013
|
+
this.collectRules(rule.cssRules, output, mediaOk, order);
|
|
4014
|
+
} else if (rule.type === 1) {
|
|
4015
|
+
output.push({
|
|
4016
|
+
rule,
|
|
4017
|
+
mediaOk,
|
|
4018
|
+
order: currentOrder
|
|
4019
|
+
});
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
}
|
|
4023
|
+
getRules() {
|
|
4024
|
+
const rules = [];
|
|
4025
|
+
const order = { value: 0 };
|
|
4026
|
+
for (const sheet of Array.from(this.document.styleSheets)) {
|
|
4027
|
+
try {
|
|
4028
|
+
this.collectRules(sheet.cssRules, rules, true, order);
|
|
4029
|
+
} catch {
|
|
4030
|
+
continue;
|
|
4031
|
+
}
|
|
4032
|
+
}
|
|
4033
|
+
return rules;
|
|
4034
|
+
}
|
|
4035
|
+
findVarReferences(el) {
|
|
4036
|
+
const result = Object.fromEntries(
|
|
4037
|
+
TYPO_PROPS.map((prop) => [prop, null])
|
|
4038
|
+
);
|
|
4039
|
+
const rules = this.getRules();
|
|
4040
|
+
for (const prop of TYPO_PROPS) {
|
|
4041
|
+
let node = el;
|
|
4042
|
+
while (node && result[prop] === null) {
|
|
4043
|
+
let winner;
|
|
4044
|
+
const inlineValue = node.style.getPropertyValue(prop);
|
|
4045
|
+
const inlineName = extractVarName(inlineValue);
|
|
4046
|
+
if (inlineName) {
|
|
4047
|
+
winner = {
|
|
4048
|
+
name: inlineName,
|
|
4049
|
+
specificity: Number.MAX_SAFE_INTEGER,
|
|
4050
|
+
order: Number.MAX_SAFE_INTEGER,
|
|
4051
|
+
important: node.style.getPropertyPriority(prop) === "important"
|
|
4052
|
+
};
|
|
4053
|
+
}
|
|
4054
|
+
for (const { rule, mediaOk, order } of rules) {
|
|
4055
|
+
if (!mediaOk) continue;
|
|
4056
|
+
let matches = false;
|
|
4057
|
+
try {
|
|
4058
|
+
matches = node.matches(rule.selectorText);
|
|
4059
|
+
} catch {
|
|
4060
|
+
continue;
|
|
4061
|
+
}
|
|
4062
|
+
if (!matches) continue;
|
|
4063
|
+
const name = extractVarName(rule.style.getPropertyValue(prop));
|
|
4064
|
+
if (!name) continue;
|
|
4065
|
+
const candidate = {
|
|
4066
|
+
name,
|
|
4067
|
+
specificity: selectorSpecificity(rule.selectorText),
|
|
4068
|
+
order,
|
|
4069
|
+
important: rule.style.getPropertyPriority(prop) === "important"
|
|
4070
|
+
};
|
|
4071
|
+
if (wins(candidate, winner)) winner = candidate;
|
|
4072
|
+
}
|
|
4073
|
+
if (winner) result[prop] = winner.name;
|
|
4074
|
+
node = node.parentElement;
|
|
4075
|
+
}
|
|
4076
|
+
}
|
|
4077
|
+
return result;
|
|
4078
|
+
}
|
|
4079
|
+
getFast(el) {
|
|
4080
|
+
const styles = this.window.getComputedStyle(el);
|
|
4081
|
+
const rows = [
|
|
4082
|
+
{ label: "Family", value: firstFontFamily(styles.fontFamily), varName: null },
|
|
4083
|
+
{ label: "Size", value: formatPx(styles.fontSize), varName: null },
|
|
4084
|
+
{
|
|
4085
|
+
label: "Weight",
|
|
4086
|
+
value: weightWithKeyword(styles.fontWeight),
|
|
4087
|
+
varName: null
|
|
4088
|
+
},
|
|
4089
|
+
{
|
|
4090
|
+
label: "Line",
|
|
4091
|
+
value: styles.lineHeight === "normal" ? "normal" : formatPx(styles.lineHeight),
|
|
4092
|
+
varName: null
|
|
4093
|
+
},
|
|
4094
|
+
{
|
|
4095
|
+
label: "Tracking",
|
|
4096
|
+
value: styles.letterSpacing === "normal" ? "normal" : formatPx(styles.letterSpacing),
|
|
4097
|
+
varName: null
|
|
4098
|
+
}
|
|
4099
|
+
];
|
|
4100
|
+
const directText = Array.from(el.childNodes).filter((node) => node.nodeType === Node.TEXT_NODE).map((node) => node.nodeValue?.trim() ?? "").filter(Boolean).join(" ").replace(/\s+/g, " ");
|
|
4101
|
+
return {
|
|
4102
|
+
rows,
|
|
4103
|
+
tagName: el.tagName.toLowerCase(),
|
|
4104
|
+
textSnippet: directText.length > 40 ? `${directText.slice(0, 40)}\u2026` : directText
|
|
4105
|
+
};
|
|
4106
|
+
}
|
|
4107
|
+
getFull(el, base = this.getFast(el)) {
|
|
4108
|
+
const vars = this.findVarReferences(el);
|
|
4109
|
+
return {
|
|
4110
|
+
...base,
|
|
4111
|
+
rows: base.rows.map((row) => ({
|
|
4112
|
+
...row,
|
|
4113
|
+
varName: vars[TYPO_LABELS[row.label]]
|
|
4114
|
+
}))
|
|
4115
|
+
};
|
|
4116
|
+
}
|
|
4117
|
+
};
|
|
4118
|
+
|
|
4119
|
+
// runtime/text-inspector.ts
|
|
4120
|
+
var DEFAULT_EXTENSION_HOST_ID = "mesurer-extension-host";
|
|
4121
|
+
var DEFAULT_OVERLAY_ID = "mesurer-text-inspector-overlay";
|
|
4122
|
+
var DEFAULT_STYLE_ID = "mesurer-text-inspector-styles";
|
|
4123
|
+
var DEFAULT_BODY_MODE_CLASS = "mesurer-text-inspect-mode";
|
|
4124
|
+
var inspectorInstanceCount = 0;
|
|
4125
|
+
var FILL_HOVER = "color-mix(in oklch, oklch(0.62 0.18 255) 8%, transparent)";
|
|
4126
|
+
var OUTLINE_HOVER = "color-mix(in oklch, oklch(0.62 0.18 255) 80%, transparent)";
|
|
4127
|
+
var FILL_PINNED = "color-mix(in oklch, oklch(0.62 0.18 255) 4%, transparent)";
|
|
4128
|
+
var OUTLINE_PINNED = "color-mix(in oklch, oklch(0.62 0.18 255) 35%, transparent)";
|
|
4129
|
+
var DEFAULT_SKIP_TAGS = [
|
|
4130
|
+
"HTML",
|
|
4131
|
+
"BODY",
|
|
4132
|
+
"SCRIPT",
|
|
4133
|
+
"STYLE",
|
|
4134
|
+
"META",
|
|
4135
|
+
"LINK",
|
|
4136
|
+
"NOSCRIPT",
|
|
4137
|
+
"IMG",
|
|
4138
|
+
"VIDEO",
|
|
4139
|
+
"AUDIO",
|
|
4140
|
+
"IFRAME"
|
|
4141
|
+
];
|
|
4142
|
+
var createInspectorStyles = (extensionHostId, overlayId, bodyModeClass) => `
|
|
4143
|
+
.${bodyModeClass},
|
|
4144
|
+
.${bodyModeClass} * {
|
|
4145
|
+
cursor: help !important;
|
|
4146
|
+
}
|
|
4147
|
+
.${bodyModeClass} #${extensionHostId},
|
|
4148
|
+
.${bodyModeClass} #${extensionHostId} * {
|
|
4149
|
+
cursor: auto !important;
|
|
4150
|
+
}
|
|
4151
|
+
#${overlayId} .mesurer-ti-card--pinned {
|
|
4152
|
+
cursor: grab;
|
|
4153
|
+
}
|
|
4154
|
+
#${overlayId} .mesurer-ti-card--pinned:active {
|
|
4155
|
+
cursor: grabbing;
|
|
4156
|
+
}
|
|
4157
|
+
#${overlayId} .mesurer-ti-close {
|
|
4158
|
+
cursor: pointer;
|
|
4159
|
+
}
|
|
4160
|
+
#${overlayId} .mesurer-ti-close:hover {
|
|
4161
|
+
background: rgba(15, 23, 42, 0.06);
|
|
4162
|
+
color: #0f172a;
|
|
4163
|
+
}
|
|
4164
|
+
#${overlayId} .mesurer-ti-box,
|
|
4165
|
+
#${overlayId} .mesurer-ti-card {
|
|
4166
|
+
opacity: 1;
|
|
4167
|
+
}
|
|
4168
|
+
#${overlayId} .mesurer-ti-box[data-state="hidden"],
|
|
4169
|
+
#${overlayId} .mesurer-ti-card[data-state="hidden"] {
|
|
4170
|
+
opacity: 0;
|
|
4171
|
+
}
|
|
4172
|
+
#${overlayId} .mesurer-ti-card {
|
|
4173
|
+
transform: translateX(-50%);
|
|
4174
|
+
}
|
|
4175
|
+
`;
|
|
4176
|
+
var createIdleScheduler = (window2) => {
|
|
4177
|
+
const browser = window2;
|
|
4178
|
+
if (browser.requestIdleCallback) {
|
|
4179
|
+
return {
|
|
4180
|
+
request: (callback) => browser.requestIdleCallback(
|
|
4181
|
+
() => callback(),
|
|
4182
|
+
{ timeout: 250 }
|
|
4183
|
+
),
|
|
4184
|
+
cancel: (id) => browser.cancelIdleCallback?.(id)
|
|
4185
|
+
};
|
|
4186
|
+
}
|
|
4187
|
+
return {
|
|
4188
|
+
request: (callback) => window2.setTimeout(callback, 32),
|
|
4189
|
+
cancel: (id) => window2.clearTimeout(id)
|
|
4190
|
+
};
|
|
4191
|
+
};
|
|
4192
|
+
var createTextInspector = (options = {}, legacy = false) => {
|
|
4193
|
+
const portalDocument = options.portalTarget?.ownerDocument;
|
|
4194
|
+
const availableDocument = portalDocument ?? (typeof globalThis.document === "undefined" ? null : globalThis.document);
|
|
4195
|
+
const availableWindow = availableDocument?.defaultView ?? (typeof globalThis.window === "undefined" ? null : globalThis.window);
|
|
4196
|
+
const document2 = availableDocument;
|
|
4197
|
+
const window2 = availableWindow;
|
|
4198
|
+
const realm = availableWindow;
|
|
4199
|
+
const HTMLElementConstructor = realm?.HTMLElement ?? globalThis.HTMLElement;
|
|
4200
|
+
const SVGElementConstructor = realm?.SVGElement ?? globalThis.SVGElement;
|
|
4201
|
+
const extensionHostId = DEFAULT_EXTENSION_HOST_ID;
|
|
4202
|
+
const instanceId = (options.id ?? (legacy ? DEFAULT_OVERLAY_ID : `mesurer-text-inspector-${++inspectorInstanceCount}`)).replace(
|
|
4203
|
+
/[^a-zA-Z0-9_-]/g,
|
|
4204
|
+
"-"
|
|
4205
|
+
);
|
|
4206
|
+
const overlayId = legacy ? DEFAULT_OVERLAY_ID : `${instanceId}-overlay`;
|
|
4207
|
+
const styleId = legacy ? DEFAULT_STYLE_ID : `${instanceId}-styles`;
|
|
4208
|
+
const bodyModeClass = legacy ? DEFAULT_BODY_MODE_CLASS : `${instanceId}-mode`;
|
|
4209
|
+
const skipTags = new Set(
|
|
4210
|
+
(options.ignoredTags ?? DEFAULT_SKIP_TAGS).map((tag) => tag.toUpperCase())
|
|
4211
|
+
);
|
|
4212
|
+
const maxPinned = Number.isFinite(options.maxPinned) ? Math.max(1, Math.floor(options.maxPinned)) : Infinity;
|
|
4213
|
+
const inspectorStyles = createInspectorStyles(
|
|
4214
|
+
extensionHostId,
|
|
4215
|
+
overlayId,
|
|
4216
|
+
bodyModeClass
|
|
4217
|
+
);
|
|
4218
|
+
const EXTENSION_HOST_ID = extensionHostId;
|
|
4219
|
+
const OVERLAY_ID = overlayId;
|
|
4220
|
+
const STYLE_ID = styleId;
|
|
4221
|
+
const BODY_MODE_CLASS = bodyModeClass;
|
|
4222
|
+
const SKIP_TAGS = skipTags;
|
|
4223
|
+
const INSPECTOR_STYLES = inspectorStyles;
|
|
4224
|
+
const portalIsShadowRoot = options.portalTarget?.nodeType === 11;
|
|
4225
|
+
const typography = new TypographyInspector(document2, window2);
|
|
4226
|
+
const pinned = [];
|
|
4227
|
+
const history = [];
|
|
4228
|
+
const future = [];
|
|
4229
|
+
let enabled = false;
|
|
4230
|
+
let overlay = null;
|
|
4231
|
+
let hoverBox = null;
|
|
4232
|
+
let hoverCard = null;
|
|
4233
|
+
let hoveredEl = null;
|
|
4234
|
+
let pointerX = 0;
|
|
4235
|
+
let pointerY = 0;
|
|
4236
|
+
let frameScheduled = false;
|
|
4237
|
+
let pendingElement = null;
|
|
4238
|
+
let pendingIdleId = -1;
|
|
4239
|
+
let idleScheduler = null;
|
|
4240
|
+
const getIdleScheduler = () => {
|
|
4241
|
+
idleScheduler ?? (idleScheduler = createIdleScheduler(window2));
|
|
4242
|
+
return idleScheduler;
|
|
4243
|
+
};
|
|
4244
|
+
const hasDirectText = (el) => Array.from(el.childNodes).some(
|
|
4245
|
+
(node) => node.nodeType === Node.TEXT_NODE && !!node.nodeValue?.trim()
|
|
4246
|
+
);
|
|
4247
|
+
const isInspectable = (el) => !!el && el instanceof HTMLElementConstructor && !SKIP_TAGS.has(el.tagName) && !(el instanceof SVGElementConstructor) && hasDirectText(el);
|
|
4248
|
+
const isOverlayNode = (node) => {
|
|
4249
|
+
for (let current = node; current; current = current.parentNode) {
|
|
4250
|
+
if (current instanceof HTMLElementConstructor) {
|
|
4251
|
+
const element = current;
|
|
4252
|
+
if (element.id === OVERLAY_ID || element.id === EXTENSION_HOST_ID) {
|
|
4253
|
+
return true;
|
|
4254
|
+
}
|
|
4255
|
+
}
|
|
4256
|
+
}
|
|
4257
|
+
return false;
|
|
4258
|
+
};
|
|
4259
|
+
const pickElementAt = (x, y) => {
|
|
4260
|
+
return document2.elementsFromPoint(x, y).find(
|
|
4261
|
+
(el) => !isOverlayNode(el) && isInspectable(el)
|
|
4262
|
+
) ?? null;
|
|
4263
|
+
};
|
|
4264
|
+
const pointerOverToolbar = (x, y) => {
|
|
4265
|
+
const shadow = document2.getElementById(EXTENSION_HOST_ID)?.shadowRoot;
|
|
4266
|
+
const element = shadow?.elementFromPoint(x, y);
|
|
4267
|
+
if (!element) return false;
|
|
4268
|
+
for (let node = element; node; node = node.parentElement) {
|
|
4269
|
+
if (node.classList.contains("mesurer-toolbar-surface")) return true;
|
|
4270
|
+
}
|
|
4271
|
+
return false;
|
|
4272
|
+
};
|
|
4273
|
+
const ensureStyles = () => {
|
|
4274
|
+
const append = (root) => {
|
|
4275
|
+
if (root.querySelector(`#${STYLE_ID}`)) return;
|
|
4276
|
+
const style = document2.createElement("style");
|
|
4277
|
+
style.id = STYLE_ID;
|
|
4278
|
+
style.textContent = INSPECTOR_STYLES;
|
|
4279
|
+
root.nodeType === 9 ? root.head.appendChild(style) : root.appendChild(style);
|
|
4280
|
+
};
|
|
4281
|
+
append(document2);
|
|
4282
|
+
if (portalIsShadowRoot) append(options.portalTarget);
|
|
4283
|
+
};
|
|
4284
|
+
const ensureOverlay = () => {
|
|
4285
|
+
if (overlay?.isConnected) return overlay;
|
|
4286
|
+
overlay = document2.createElement("div");
|
|
4287
|
+
overlay.id = OVERLAY_ID;
|
|
4288
|
+
Object.assign(overlay.style, {
|
|
4289
|
+
position: "fixed",
|
|
4290
|
+
inset: "0",
|
|
4291
|
+
pointerEvents: "none",
|
|
4292
|
+
zIndex: "2147483646"
|
|
4293
|
+
});
|
|
4294
|
+
(options.portalTarget ?? document2.body).appendChild(overlay);
|
|
4295
|
+
return overlay;
|
|
4296
|
+
};
|
|
4297
|
+
const setState = (element, visible) => {
|
|
4298
|
+
element.dataset.state = visible ? "visible" : "hidden";
|
|
4299
|
+
};
|
|
4300
|
+
const ensureHover = () => {
|
|
4301
|
+
const root = ensureOverlay();
|
|
4302
|
+
hoverBox ?? (hoverBox = makeBox(document2, FILL_HOVER, OUTLINE_HOVER));
|
|
4303
|
+
hoverCard ?? (hoverCard = makeCard(document2, false));
|
|
4304
|
+
if (!hoverBox.parentNode) root.appendChild(hoverBox);
|
|
4305
|
+
if (!hoverCard.parentNode) root.appendChild(hoverCard);
|
|
4306
|
+
};
|
|
4307
|
+
const scheduleEnrichment = (element, fast) => {
|
|
4308
|
+
if (pendingElement === element) return;
|
|
4309
|
+
if (pendingIdleId !== -1) getIdleScheduler().cancel(pendingIdleId);
|
|
4310
|
+
pendingElement = element;
|
|
4311
|
+
pendingIdleId = getIdleScheduler().request(() => {
|
|
4312
|
+
pendingIdleId = -1;
|
|
4313
|
+
pendingElement = null;
|
|
4314
|
+
if (!enabled) return;
|
|
4315
|
+
const full = typography.getFull(element, fast);
|
|
4316
|
+
if (hoveredEl !== element || !hoverCard) return;
|
|
4317
|
+
populateCard(document2, hoverCard, full, false);
|
|
4318
|
+
positionCard(window2, hoverCard, element.getBoundingClientRect());
|
|
4319
|
+
options.onInspect?.(element, full);
|
|
4320
|
+
});
|
|
4321
|
+
};
|
|
4322
|
+
const inspect = (element) => {
|
|
4323
|
+
if (!enabled || !isInspectable(element)) return false;
|
|
4324
|
+
ensureHover();
|
|
4325
|
+
const rect = element.getBoundingClientRect();
|
|
4326
|
+
hoveredEl = element;
|
|
4327
|
+
const fast = typography.getFast(element);
|
|
4328
|
+
populateCard(document2, hoverCard, fast, false);
|
|
4329
|
+
scheduleEnrichment(element, fast);
|
|
4330
|
+
positionBox(hoverBox, rect);
|
|
4331
|
+
positionCard(window2, hoverCard, rect);
|
|
4332
|
+
setState(hoverBox, true);
|
|
4333
|
+
setState(hoverCard, true);
|
|
4334
|
+
return true;
|
|
4335
|
+
};
|
|
4336
|
+
const updateHover = () => {
|
|
4337
|
+
if (!enabled || pointerOverToolbar(pointerX, pointerY)) {
|
|
4338
|
+
hideHover();
|
|
4339
|
+
return;
|
|
4340
|
+
}
|
|
4341
|
+
const element = pickElementAt(pointerX, pointerY);
|
|
4342
|
+
if (!element) {
|
|
4343
|
+
hideHover();
|
|
4344
|
+
return;
|
|
4345
|
+
}
|
|
4346
|
+
if (element !== hoveredEl) inspect(element);
|
|
4347
|
+
else {
|
|
4348
|
+
positionBox(hoverBox, element.getBoundingClientRect());
|
|
4349
|
+
positionCard(window2, hoverCard, element.getBoundingClientRect());
|
|
4350
|
+
}
|
|
4351
|
+
};
|
|
4352
|
+
const hideHover = () => {
|
|
4353
|
+
hoveredEl = null;
|
|
4354
|
+
if (hoverBox) setState(hoverBox, false);
|
|
4355
|
+
if (hoverCard) setState(hoverCard, false);
|
|
4356
|
+
};
|
|
4357
|
+
const snapshotPins = () => pinned.map((pin) => {
|
|
4358
|
+
const rect = pin.card.getBoundingClientRect();
|
|
4359
|
+
return {
|
|
4360
|
+
sourceEl: pin.sourceEl,
|
|
4361
|
+
left: pin.userPlaced ? rect.left + rect.width / 2 : 0,
|
|
4362
|
+
top: pin.userPlaced ? rect.top : 0,
|
|
4363
|
+
userPlaced: pin.userPlaced
|
|
4364
|
+
};
|
|
4365
|
+
});
|
|
4366
|
+
const recordPinState = () => {
|
|
4367
|
+
history.push(snapshotPins());
|
|
4368
|
+
future.length = 0;
|
|
4369
|
+
};
|
|
4370
|
+
const removePin = (pin, record = true, notify = record) => {
|
|
4371
|
+
const index = pinned.indexOf(pin);
|
|
4372
|
+
if (index === -1) return;
|
|
4373
|
+
if (record) recordPinState();
|
|
4374
|
+
pinned.splice(index, 1);
|
|
4375
|
+
pin.detach();
|
|
4376
|
+
pin.box.remove();
|
|
4377
|
+
pin.card.remove();
|
|
4378
|
+
if (notify) options.onUnpin?.(pin.sourceEl);
|
|
4379
|
+
};
|
|
4380
|
+
const clearPins = (notify = false) => {
|
|
4381
|
+
while (pinned.length) {
|
|
4382
|
+
removePin(pinned[pinned.length - 1], false, notify);
|
|
4383
|
+
}
|
|
4384
|
+
};
|
|
4385
|
+
const attachDrag = (pin) => {
|
|
4386
|
+
let pointerId = -1;
|
|
4387
|
+
let startX = 0;
|
|
4388
|
+
let startY = 0;
|
|
4389
|
+
let originLeft = 0;
|
|
4390
|
+
let originTop = 0;
|
|
4391
|
+
let active = false;
|
|
4392
|
+
let dragged = false;
|
|
4393
|
+
let historyRecorded = false;
|
|
4394
|
+
const slop = 6;
|
|
4395
|
+
const onMove = (event) => {
|
|
4396
|
+
if (event.pointerId !== pointerId) return;
|
|
4397
|
+
const dx = event.clientX - startX;
|
|
4398
|
+
const dy = event.clientY - startY;
|
|
4399
|
+
if (!active) active = Math.abs(dx) > slop || Math.abs(dy) > slop;
|
|
4400
|
+
if (!active) return;
|
|
4401
|
+
if (!historyRecorded) {
|
|
4402
|
+
recordPinState();
|
|
4403
|
+
historyRecorded = true;
|
|
4404
|
+
}
|
|
4405
|
+
dragged = true;
|
|
4406
|
+
pin.card.style.left = `${Math.min(
|
|
4407
|
+
window2.innerWidth - 8,
|
|
4408
|
+
Math.max(8, originLeft + dx)
|
|
4409
|
+
)}px`;
|
|
4410
|
+
pin.card.style.top = `${Math.min(
|
|
4411
|
+
window2.innerHeight - 8,
|
|
4412
|
+
Math.max(8, originTop + dy)
|
|
4413
|
+
)}px`;
|
|
4414
|
+
pin.userPlaced = true;
|
|
4415
|
+
};
|
|
4416
|
+
const onEnd = (event) => {
|
|
4417
|
+
if (event.pointerId !== pointerId && pointerId !== -1) return;
|
|
4418
|
+
window2.removeEventListener("pointermove", onMove);
|
|
4419
|
+
window2.removeEventListener("pointerup", onEnd);
|
|
4420
|
+
window2.removeEventListener("pointercancel", onEnd);
|
|
4421
|
+
pointerId = -1;
|
|
4422
|
+
active = false;
|
|
4423
|
+
historyRecorded = false;
|
|
4424
|
+
if (dragged) {
|
|
4425
|
+
const swallow = (click) => {
|
|
4426
|
+
click.preventDefault();
|
|
4427
|
+
click.stopPropagation();
|
|
4428
|
+
window2.removeEventListener("click", swallow, true);
|
|
4429
|
+
};
|
|
4430
|
+
window2.addEventListener("click", swallow, true);
|
|
4431
|
+
}
|
|
4432
|
+
dragged = false;
|
|
4433
|
+
};
|
|
4434
|
+
const onDown = (event) => {
|
|
4435
|
+
if (event.button !== 0) return;
|
|
4436
|
+
if (event.target?.classList.contains("mesurer-ti-close")) {
|
|
4437
|
+
return;
|
|
4438
|
+
}
|
|
4439
|
+
const rect = pin.card.getBoundingClientRect();
|
|
4440
|
+
originLeft = rect.left + rect.width / 2;
|
|
4441
|
+
originTop = rect.top;
|
|
4442
|
+
startX = event.clientX;
|
|
4443
|
+
startY = event.clientY;
|
|
4444
|
+
pointerId = event.pointerId;
|
|
4445
|
+
active = false;
|
|
4446
|
+
dragged = false;
|
|
4447
|
+
window2.addEventListener("pointermove", onMove);
|
|
4448
|
+
window2.addEventListener("pointerup", onEnd);
|
|
4449
|
+
window2.addEventListener("pointercancel", onEnd);
|
|
4450
|
+
};
|
|
4451
|
+
pin.card.addEventListener("pointerdown", onDown);
|
|
4452
|
+
return () => {
|
|
4453
|
+
pin.card.removeEventListener("pointerdown", onDown);
|
|
4454
|
+
window2.removeEventListener("pointermove", onMove);
|
|
4455
|
+
window2.removeEventListener("pointerup", onEnd);
|
|
4456
|
+
window2.removeEventListener("pointercancel", onEnd);
|
|
4457
|
+
};
|
|
4458
|
+
};
|
|
4459
|
+
const createPin = (sourceEl, state, record = true, notify = record) => {
|
|
4460
|
+
const existing = pinned.find((pin2) => pin2.sourceEl === sourceEl);
|
|
4461
|
+
if (existing) {
|
|
4462
|
+
const root2 = ensureOverlay();
|
|
4463
|
+
root2.append(existing.box, existing.card);
|
|
4464
|
+
return;
|
|
4465
|
+
}
|
|
4466
|
+
if (record) {
|
|
4467
|
+
recordPinState();
|
|
4468
|
+
if (pinned.length >= maxPinned) removePin(pinned[0], false, true);
|
|
4469
|
+
}
|
|
4470
|
+
const root = ensureOverlay();
|
|
4471
|
+
const box = makeBox(document2, FILL_PINNED, OUTLINE_PINNED);
|
|
4472
|
+
const card = makeCard(document2, true);
|
|
4473
|
+
const info = typography.getFull(sourceEl);
|
|
4474
|
+
populateCard(document2, card, info, true);
|
|
4475
|
+
root.append(box, card);
|
|
4476
|
+
const pin = {
|
|
4477
|
+
sourceEl,
|
|
4478
|
+
box,
|
|
4479
|
+
card,
|
|
4480
|
+
userPlaced: state?.userPlaced ?? false,
|
|
4481
|
+
detach: () => {
|
|
4482
|
+
}
|
|
4483
|
+
};
|
|
4484
|
+
const rect = sourceEl.getBoundingClientRect();
|
|
4485
|
+
positionBox(box, rect);
|
|
4486
|
+
positionCard(window2, card, rect);
|
|
4487
|
+
if (state?.userPlaced) {
|
|
4488
|
+
card.style.left = `${state.left}px`;
|
|
4489
|
+
card.style.top = `${state.top}px`;
|
|
4490
|
+
}
|
|
4491
|
+
setState(box, true);
|
|
4492
|
+
setState(card, true);
|
|
4493
|
+
pinned.push(pin);
|
|
4494
|
+
card.querySelector(".mesurer-ti-close")?.addEventListener(
|
|
4495
|
+
"click",
|
|
4496
|
+
(event) => {
|
|
4497
|
+
event.preventDefault();
|
|
4498
|
+
event.stopPropagation();
|
|
4499
|
+
removePin(pin);
|
|
4500
|
+
}
|
|
4501
|
+
);
|
|
4502
|
+
pin.detach = attachDrag(pin);
|
|
4503
|
+
if (notify) options.onPin?.(sourceEl, info);
|
|
4504
|
+
};
|
|
4505
|
+
const restorePins = (states) => {
|
|
4506
|
+
clearPins(false);
|
|
4507
|
+
for (const state of states) {
|
|
4508
|
+
if (state.sourceEl.isConnected) createPin(state.sourceEl, state, false, false);
|
|
4509
|
+
}
|
|
4510
|
+
};
|
|
4511
|
+
const undo = () => {
|
|
4512
|
+
const previous = history.pop();
|
|
4513
|
+
if (!previous) return false;
|
|
4514
|
+
future.push(snapshotPins());
|
|
4515
|
+
restorePins(previous);
|
|
4516
|
+
return true;
|
|
4517
|
+
};
|
|
4518
|
+
const redo = () => {
|
|
4519
|
+
const next = future.pop();
|
|
4520
|
+
if (!next) return false;
|
|
4521
|
+
history.push(snapshotPins());
|
|
4522
|
+
restorePins(next);
|
|
4523
|
+
return true;
|
|
4524
|
+
};
|
|
4525
|
+
const clear = () => {
|
|
4526
|
+
if (!pinned.length) return;
|
|
4527
|
+
recordPinState();
|
|
4528
|
+
clearPins(true);
|
|
4529
|
+
};
|
|
4530
|
+
const syncPins = () => {
|
|
4531
|
+
for (const pin of [...pinned]) {
|
|
4532
|
+
if (!pin.sourceEl.isConnected) {
|
|
4533
|
+
removePin(pin, false);
|
|
4534
|
+
continue;
|
|
4535
|
+
}
|
|
4536
|
+
const rect = pin.sourceEl.getBoundingClientRect();
|
|
4537
|
+
positionBox(pin.box, rect);
|
|
4538
|
+
if (!pin.userPlaced) positionCard(window2, pin.card, rect);
|
|
4539
|
+
const visible = rect.bottom >= 0 && rect.right >= 0 && rect.left <= window2.innerWidth && rect.top <= window2.innerHeight;
|
|
4540
|
+
setState(pin.box, visible);
|
|
4541
|
+
setState(pin.card, visible);
|
|
4542
|
+
pin.card.style.pointerEvents = visible ? "auto" : "none";
|
|
4543
|
+
}
|
|
4544
|
+
};
|
|
4545
|
+
const scheduleFrame = () => {
|
|
4546
|
+
if (frameScheduled) return;
|
|
4547
|
+
frameScheduled = true;
|
|
4548
|
+
requestAnimationFrame(() => {
|
|
4549
|
+
frameScheduled = false;
|
|
4550
|
+
if (!enabled) return;
|
|
4551
|
+
updateHover();
|
|
4552
|
+
syncPins();
|
|
4553
|
+
});
|
|
4554
|
+
};
|
|
4555
|
+
const onMouseMove = (event) => {
|
|
4556
|
+
pointerX = event.clientX;
|
|
4557
|
+
pointerY = event.clientY;
|
|
4558
|
+
scheduleFrame();
|
|
4559
|
+
};
|
|
4560
|
+
const onMouseOut = (event) => {
|
|
4561
|
+
if (!event.relatedTarget) hideHover();
|
|
4562
|
+
};
|
|
4563
|
+
const onScrollOrResize = () => scheduleFrame();
|
|
4564
|
+
const isInspectorUIEvent = (event) => event.composedPath().some(
|
|
4565
|
+
(node) => node instanceof HTMLElementConstructor && (() => {
|
|
4566
|
+
const element = node;
|
|
4567
|
+
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");
|
|
4568
|
+
})()
|
|
4569
|
+
);
|
|
4570
|
+
const onClick = (event) => {
|
|
4571
|
+
if (isInspectorUIEvent(event) || pointerOverToolbar(event.clientX, event.clientY)) {
|
|
4572
|
+
return;
|
|
4573
|
+
}
|
|
4574
|
+
event.preventDefault();
|
|
4575
|
+
event.stopImmediatePropagation();
|
|
4576
|
+
if (event.button === 0) {
|
|
4577
|
+
const source = pickElementAt(event.clientX, event.clientY);
|
|
4578
|
+
if (source) createPin(source);
|
|
4579
|
+
}
|
|
4580
|
+
};
|
|
4581
|
+
const onAuxClick = (event) => {
|
|
4582
|
+
if (isInspectorUIEvent(event) || pointerOverToolbar(event.clientX, event.clientY)) {
|
|
4583
|
+
return;
|
|
4584
|
+
}
|
|
4585
|
+
event.preventDefault();
|
|
4586
|
+
event.stopImmediatePropagation();
|
|
4587
|
+
};
|
|
4588
|
+
const enable = () => {
|
|
4589
|
+
if (enabled || !availableDocument || !availableWindow) return;
|
|
4590
|
+
enabled = true;
|
|
4591
|
+
ensureStyles();
|
|
4592
|
+
ensureOverlay();
|
|
4593
|
+
document2.body.classList.add(BODY_MODE_CLASS);
|
|
4594
|
+
window2.addEventListener("mousemove", onMouseMove, true);
|
|
4595
|
+
window2.addEventListener("mouseout", onMouseOut, true);
|
|
4596
|
+
window2.addEventListener("click", onClick, true);
|
|
4597
|
+
window2.addEventListener("auxclick", onAuxClick, true);
|
|
4598
|
+
window2.addEventListener("scroll", onScrollOrResize, true);
|
|
4599
|
+
window2.addEventListener("resize", onScrollOrResize, true);
|
|
4600
|
+
};
|
|
4601
|
+
const disable = () => {
|
|
4602
|
+
if (!enabled) return;
|
|
4603
|
+
enabled = false;
|
|
4604
|
+
if (pendingIdleId !== -1) getIdleScheduler().cancel(pendingIdleId);
|
|
4605
|
+
pendingIdleId = -1;
|
|
4606
|
+
pendingElement = null;
|
|
4607
|
+
history.length = 0;
|
|
4608
|
+
future.length = 0;
|
|
4609
|
+
window2.removeEventListener("mousemove", onMouseMove, true);
|
|
4610
|
+
window2.removeEventListener("mouseout", onMouseOut, true);
|
|
4611
|
+
window2.removeEventListener("click", onClick, true);
|
|
4612
|
+
window2.removeEventListener("auxclick", onAuxClick, true);
|
|
4613
|
+
window2.removeEventListener("scroll", onScrollOrResize, true);
|
|
4614
|
+
window2.removeEventListener("resize", onScrollOrResize, true);
|
|
4615
|
+
hideHover();
|
|
4616
|
+
hoverBox?.remove();
|
|
4617
|
+
hoverCard?.remove();
|
|
4618
|
+
hoverBox = null;
|
|
4619
|
+
hoverCard = null;
|
|
4620
|
+
clearPins();
|
|
4621
|
+
document2.body.classList.remove(BODY_MODE_CLASS);
|
|
4622
|
+
};
|
|
4623
|
+
const cleanup = () => {
|
|
4624
|
+
disable();
|
|
4625
|
+
overlay?.remove();
|
|
4626
|
+
overlay = null;
|
|
4627
|
+
if (typeof document2 !== "undefined") {
|
|
4628
|
+
document2.getElementById(STYLE_ID)?.remove();
|
|
4629
|
+
if (portalIsShadowRoot) {
|
|
4630
|
+
options.portalTarget.querySelector(`#${STYLE_ID}`)?.remove();
|
|
4631
|
+
}
|
|
4632
|
+
}
|
|
4633
|
+
};
|
|
4634
|
+
return {
|
|
4635
|
+
enable,
|
|
4636
|
+
disable,
|
|
4637
|
+
undo,
|
|
4638
|
+
redo,
|
|
4639
|
+
canUndo: () => history.length > 0,
|
|
4640
|
+
canRedo: () => future.length > 0,
|
|
4641
|
+
clear,
|
|
4642
|
+
inspect,
|
|
4643
|
+
isEnabled: () => enabled,
|
|
4644
|
+
cleanup,
|
|
4645
|
+
destroy: cleanup
|
|
4646
|
+
};
|
|
4647
|
+
};
|
|
4648
|
+
var TextInspector = createTextInspector({}, true);
|
|
4649
|
+
|
|
4650
|
+
// measurer.tsx
|
|
4651
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
4652
|
+
var measurerInstanceCount = 0;
|
|
4653
|
+
var XRAY_STYLE_ID = "mesurer-xray-styles";
|
|
4654
|
+
var XRAY_STYLES = `
|
|
4655
|
+
.xray-mode * {
|
|
4656
|
+
outline: solid 1px blue !important;
|
|
4657
|
+
}
|
|
4658
|
+
.xray-mode #mesurer-extension-host,
|
|
4659
|
+
.xray-mode #mesurer-extension-host *,
|
|
4660
|
+
.xray-mode .mesurer-root,
|
|
4661
|
+
.xray-mode .mesurer-root *,
|
|
4662
|
+
.xray-mode .mesurer-toolbar-surface,
|
|
4663
|
+
.xray-mode .mesurer-toolbar-surface * {
|
|
4664
|
+
outline: none !important;
|
|
4665
|
+
}
|
|
4666
|
+
`;
|
|
4667
|
+
var subscribeHydration = () => () => {
|
|
4668
|
+
};
|
|
4669
|
+
var useHydrated = () => (0, import_react20.useSyncExternalStore)(
|
|
4670
|
+
subscribeHydration,
|
|
4671
|
+
() => true,
|
|
4672
|
+
() => false
|
|
4673
|
+
);
|
|
4674
|
+
var stripMeasurement = (measurement) => ({
|
|
4675
|
+
...measurement,
|
|
4676
|
+
elementRef: void 0
|
|
4677
|
+
});
|
|
4678
|
+
var stripDistance = (distance) => ({
|
|
4679
|
+
...distance,
|
|
4680
|
+
elementRefA: void 0,
|
|
4681
|
+
elementRefB: void 0
|
|
4682
|
+
});
|
|
4683
|
+
function MeasurerClient({
|
|
3264
4684
|
highlightColor,
|
|
3265
4685
|
guideColor,
|
|
3266
4686
|
hoverHighlightEnabled,
|
|
3267
4687
|
persistOnReload,
|
|
3268
|
-
portalTarget
|
|
4688
|
+
portalTarget,
|
|
4689
|
+
persistKey
|
|
3269
4690
|
}) {
|
|
3270
|
-
const
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
4691
|
+
const instanceIdRef = (0, import_react20.useRef)(null);
|
|
4692
|
+
if (instanceIdRef.current === null) {
|
|
4693
|
+
instanceIdRef.current = ++measurerInstanceCount;
|
|
4694
|
+
}
|
|
4695
|
+
const storageKey = persistKey ?? (instanceIdRef.current === 1 ? "mesurer-state" : `mesurer-state-${instanceIdRef.current}`);
|
|
4696
|
+
const ownerDocument = portalTarget.ownerDocument ?? document;
|
|
4697
|
+
const ownerWindow = ownerDocument.defaultView ?? window;
|
|
4698
|
+
const guideScrollRef = (0, import_react20.useRef)({
|
|
4699
|
+
x: ownerWindow.scrollX,
|
|
4700
|
+
y: ownerWindow.scrollY
|
|
4701
|
+
});
|
|
4702
|
+
const textInspectorRef = (0, import_react20.useRef)(null);
|
|
4703
|
+
if (!textInspectorRef.current) {
|
|
4704
|
+
textInspectorRef.current = createTextInspector({ portalTarget });
|
|
4705
|
+
}
|
|
4706
|
+
const textInspector = textInspectorRef.current;
|
|
4707
|
+
const selectionRectRef = (0, import_react20.useRef)(null);
|
|
4708
|
+
const toolbarRef = (0, import_react20.useRef)(null);
|
|
4709
|
+
const selectionAnimationCleanupTimeoutRef = (0, import_react20.useRef)(null);
|
|
4710
|
+
const guideDragRef = (0, import_react20.useRef)(null);
|
|
4711
|
+
const guideUserSelectRef = (0, import_react20.useRef)(null);
|
|
4712
|
+
const persistedState = (0, import_react20.useMemo)(() => {
|
|
3274
4713
|
if (!persistOnReload) return null;
|
|
3275
|
-
const stored = window.localStorage.getItem("mesurer-state");
|
|
3276
|
-
if (!stored) return null;
|
|
3277
4714
|
try {
|
|
4715
|
+
const stored = window.localStorage.getItem(storageKey);
|
|
4716
|
+
if (!stored) return null;
|
|
3278
4717
|
const parsed = JSON.parse(stored);
|
|
3279
4718
|
if (!parsed || parsed.version !== 1) return null;
|
|
3280
4719
|
return parsed;
|
|
3281
4720
|
} catch {
|
|
3282
4721
|
return null;
|
|
3283
4722
|
}
|
|
3284
|
-
}, [persistOnReload]);
|
|
4723
|
+
}, [persistOnReload, storageKey]);
|
|
4724
|
+
const enabledRef = (0, import_react20.useRef)(false);
|
|
4725
|
+
const toolModeRef = (0, import_react20.useRef)(
|
|
4726
|
+
persistedState?.toolMode === "rulers" ? "none" : persistedState?.toolMode ?? "none"
|
|
4727
|
+
);
|
|
4728
|
+
const rulersVisibleRef = (0, import_react20.useRef)(
|
|
4729
|
+
persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers"
|
|
4730
|
+
);
|
|
4731
|
+
const guideOrientationRef = (0, import_react20.useRef)(
|
|
4732
|
+
persistedState?.guideOrientation ?? "vertical"
|
|
4733
|
+
);
|
|
4734
|
+
const measurementsRef = (0, import_react20.useRef)(
|
|
4735
|
+
persistedState?.measurements ?? []
|
|
4736
|
+
);
|
|
4737
|
+
const activeMeasurementRef = (0, import_react20.useRef)(
|
|
4738
|
+
persistedState?.activeMeasurement ?? null
|
|
4739
|
+
);
|
|
4740
|
+
const heldDistancesRef = (0, import_react20.useRef)(
|
|
4741
|
+
persistedState?.heldDistances ?? []
|
|
4742
|
+
);
|
|
4743
|
+
const guidesRef = (0, import_react20.useRef)(persistedState?.guides ?? []);
|
|
4744
|
+
const selectedGuideIdsRef = (0, import_react20.useRef)(
|
|
4745
|
+
persistedState?.selectedGuideIds ?? []
|
|
4746
|
+
);
|
|
3285
4747
|
const { overlayRef, selectedElementRef, hoverElementRef } = useOverlayRefs();
|
|
3286
4748
|
const {
|
|
3287
4749
|
selectionOriginRect,
|
|
@@ -3307,12 +4769,15 @@ function MeasurerClient({
|
|
|
3307
4769
|
setAltPressed,
|
|
3308
4770
|
toolMode,
|
|
3309
4771
|
setToolMode,
|
|
4772
|
+
rulersVisible,
|
|
4773
|
+
setRulersVisible,
|
|
3310
4774
|
guidesEnabled,
|
|
3311
4775
|
multiMeasureEnabled,
|
|
3312
4776
|
snapGuidesEnabled
|
|
3313
4777
|
} = useMeasureToggles({
|
|
3314
4778
|
initialEnabled: persistedState?.enabled,
|
|
3315
|
-
initialToolMode: persistedState?.toolMode
|
|
4779
|
+
initialToolMode: persistedState?.toolMode === "rulers" ? "none" : persistedState?.toolMode,
|
|
4780
|
+
initialRulersVisible: persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers"
|
|
3316
4781
|
});
|
|
3317
4782
|
const { start, setStart, end, setEnd, isDragging, setIsDragging } = useDragState();
|
|
3318
4783
|
const {
|
|
@@ -3344,85 +4809,170 @@ function MeasurerClient({
|
|
|
3344
4809
|
initialGuides: persistedState?.guides ?? [],
|
|
3345
4810
|
initialSelectedGuideIds: persistedState?.selectedGuideIds ?? []
|
|
3346
4811
|
});
|
|
3347
|
-
const [toolbarActive, setToolbarActive] = (0,
|
|
3348
|
-
const { clearGuideDragHold, scheduleGuideDragHold } = useGuideDragHold();
|
|
3349
|
-
const [guidePreview, setGuidePreview] = (0,
|
|
3350
|
-
const [guideOrientation, setGuideOrientation] = (0,
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
activeMeasurement: activeMeasurement ? stripMeasurement(activeMeasurement) : null,
|
|
3362
|
-
heldDistances: heldDistances.map(stripDistance)
|
|
3363
|
-
});
|
|
3364
|
-
}, [
|
|
3365
|
-
activeMeasurement,
|
|
3366
|
-
enabled,
|
|
3367
|
-
guideOrientation,
|
|
3368
|
-
guides,
|
|
3369
|
-
heldDistances,
|
|
3370
|
-
measurements,
|
|
3371
|
-
persistOnReload,
|
|
3372
|
-
selectedGuideIds,
|
|
3373
|
-
toolMode
|
|
3374
|
-
]);
|
|
3375
|
-
(0, import_react19.useEffect)(() => {
|
|
4812
|
+
const [toolbarActive, setToolbarActive] = (0, import_react20.useState)(true);
|
|
4813
|
+
const { clearGuideDragHold, scheduleGuideDragHold } = useGuideDragHold(ownerWindow);
|
|
4814
|
+
const [guidePreview, setGuidePreview] = (0, import_react20.useState)(null);
|
|
4815
|
+
const [guideOrientation, setGuideOrientation] = (0, import_react20.useState)(persistedState?.guideOrientation ?? "vertical");
|
|
4816
|
+
enabledRef.current = enabled;
|
|
4817
|
+
toolModeRef.current = toolMode;
|
|
4818
|
+
rulersVisibleRef.current = rulersVisible;
|
|
4819
|
+
guideOrientationRef.current = guideOrientation;
|
|
4820
|
+
measurementsRef.current = measurements;
|
|
4821
|
+
activeMeasurementRef.current = activeMeasurement;
|
|
4822
|
+
heldDistancesRef.current = heldDistances;
|
|
4823
|
+
guidesRef.current = guides;
|
|
4824
|
+
selectedGuideIdsRef.current = selectedGuideIds;
|
|
4825
|
+
const persistState = (0, import_react20.useCallback)(() => {
|
|
3376
4826
|
if (!persistOnReload) return;
|
|
3377
4827
|
if (typeof window === "undefined") return;
|
|
3378
|
-
if (!persistPayload) return;
|
|
3379
4828
|
try {
|
|
3380
|
-
window.localStorage.setItem(
|
|
4829
|
+
window.localStorage.setItem(
|
|
4830
|
+
storageKey,
|
|
4831
|
+
JSON.stringify({
|
|
4832
|
+
version: 1,
|
|
4833
|
+
enabled: enabledRef.current,
|
|
4834
|
+
toolMode: toolModeRef.current,
|
|
4835
|
+
rulersVisible: rulersVisibleRef.current,
|
|
4836
|
+
guideOrientation: guideOrientationRef.current,
|
|
4837
|
+
guides: guidesRef.current,
|
|
4838
|
+
selectedGuideIds: selectedGuideIdsRef.current,
|
|
4839
|
+
measurements: measurementsRef.current.map(stripMeasurement),
|
|
4840
|
+
activeMeasurement: activeMeasurementRef.current ? stripMeasurement(activeMeasurementRef.current) : null,
|
|
4841
|
+
heldDistances: heldDistancesRef.current.map(stripDistance)
|
|
4842
|
+
})
|
|
4843
|
+
);
|
|
3381
4844
|
} catch {
|
|
3382
4845
|
}
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
4846
|
+
}, [persistOnReload, storageKey]);
|
|
4847
|
+
const setEnabledPersisted = (0, import_react20.useCallback)(
|
|
4848
|
+
(value) => {
|
|
4849
|
+
const next = typeof value === "function" ? value(enabledRef.current) : value;
|
|
4850
|
+
if (Object.is(next, enabledRef.current)) return;
|
|
4851
|
+
enabledRef.current = next;
|
|
4852
|
+
setEnabled(next);
|
|
4853
|
+
persistState();
|
|
4854
|
+
},
|
|
4855
|
+
[persistState, setEnabled]
|
|
4856
|
+
);
|
|
4857
|
+
const setRulersVisiblePersisted = (0, import_react20.useCallback)(
|
|
4858
|
+
(value) => {
|
|
4859
|
+
const next = typeof value === "function" ? value(rulersVisibleRef.current) : value;
|
|
4860
|
+
if (Object.is(next, rulersVisibleRef.current)) return;
|
|
4861
|
+
rulersVisibleRef.current = next;
|
|
4862
|
+
setRulersVisible(next);
|
|
4863
|
+
persistState();
|
|
4864
|
+
},
|
|
4865
|
+
[persistState, setRulersVisible]
|
|
4866
|
+
);
|
|
4867
|
+
const setToolModePersisted = (0, import_react20.useCallback)(
|
|
4868
|
+
(value) => {
|
|
4869
|
+
const next = typeof value === "function" ? value(toolModeRef.current) : value;
|
|
4870
|
+
if (Object.is(next, toolModeRef.current)) return;
|
|
4871
|
+
toolModeRef.current = next;
|
|
4872
|
+
setToolMode(next);
|
|
4873
|
+
if (next === "text-inspector") {
|
|
4874
|
+
textInspector.enable();
|
|
4875
|
+
} else {
|
|
4876
|
+
textInspector.disable();
|
|
3387
4877
|
}
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
4878
|
+
persistState();
|
|
4879
|
+
},
|
|
4880
|
+
[persistState, setToolMode, textInspector]
|
|
4881
|
+
);
|
|
4882
|
+
const setGuideOrientationPersisted = (0, import_react20.useCallback)(
|
|
4883
|
+
(value) => {
|
|
4884
|
+
const next = typeof value === "function" ? value(guideOrientationRef.current) : value;
|
|
4885
|
+
if (Object.is(next, guideOrientationRef.current)) return;
|
|
4886
|
+
guideOrientationRef.current = next;
|
|
4887
|
+
setGuideOrientation(next);
|
|
4888
|
+
persistState();
|
|
4889
|
+
},
|
|
4890
|
+
[persistState, setGuideOrientation]
|
|
4891
|
+
);
|
|
4892
|
+
const setMeasurementsPersisted = (0, import_react20.useCallback)(
|
|
4893
|
+
(value) => {
|
|
4894
|
+
const next = typeof value === "function" ? value(measurementsRef.current) : value;
|
|
4895
|
+
if (Object.is(next, measurementsRef.current)) return;
|
|
4896
|
+
measurementsRef.current = next;
|
|
4897
|
+
setMeasurements(next);
|
|
4898
|
+
persistState();
|
|
4899
|
+
},
|
|
4900
|
+
[persistState, setMeasurements]
|
|
4901
|
+
);
|
|
4902
|
+
const setActiveMeasurementPersisted = (0, import_react20.useCallback)(
|
|
4903
|
+
(value) => {
|
|
4904
|
+
const next = typeof value === "function" ? value(activeMeasurementRef.current) : value;
|
|
4905
|
+
if (Object.is(next, activeMeasurementRef.current)) return;
|
|
4906
|
+
activeMeasurementRef.current = next;
|
|
4907
|
+
setActiveMeasurement(next);
|
|
4908
|
+
persistState();
|
|
4909
|
+
},
|
|
4910
|
+
[persistState, setActiveMeasurement]
|
|
4911
|
+
);
|
|
4912
|
+
const setHeldDistancesPersisted = (0, import_react20.useCallback)(
|
|
4913
|
+
(value) => {
|
|
4914
|
+
const next = typeof value === "function" ? value(heldDistancesRef.current) : value;
|
|
4915
|
+
if (Object.is(next, heldDistancesRef.current)) return;
|
|
4916
|
+
heldDistancesRef.current = next;
|
|
4917
|
+
setHeldDistances(next);
|
|
4918
|
+
persistState();
|
|
4919
|
+
},
|
|
4920
|
+
[persistState, setHeldDistances]
|
|
4921
|
+
);
|
|
4922
|
+
const setGuidesPersisted = (0, import_react20.useCallback)(
|
|
4923
|
+
(value) => {
|
|
4924
|
+
const next = typeof value === "function" ? value(guidesRef.current) : value;
|
|
4925
|
+
if (Object.is(next, guidesRef.current)) return;
|
|
4926
|
+
guidesRef.current = next;
|
|
4927
|
+
setGuides(next);
|
|
4928
|
+
persistState();
|
|
4929
|
+
},
|
|
4930
|
+
[persistState, setGuides]
|
|
4931
|
+
);
|
|
4932
|
+
const setSelectedGuideIdsPersisted = (0, import_react20.useCallback)(
|
|
4933
|
+
(value) => {
|
|
4934
|
+
const next = typeof value === "function" ? value(selectedGuideIdsRef.current) : value;
|
|
4935
|
+
if (Object.is(next, selectedGuideIdsRef.current)) return;
|
|
4936
|
+
selectedGuideIdsRef.current = next;
|
|
4937
|
+
setSelectedGuideIds(next);
|
|
4938
|
+
persistState();
|
|
4939
|
+
},
|
|
4940
|
+
[persistState, setSelectedGuideIds]
|
|
4941
|
+
);
|
|
3394
4942
|
const {
|
|
3395
4943
|
recordSnapshot,
|
|
3396
4944
|
createActionCommit,
|
|
3397
4945
|
setToolModeWithHistory,
|
|
3398
4946
|
setGuideOrientationWithHistory,
|
|
3399
|
-
setEnabledWithHistory
|
|
4947
|
+
setEnabledWithHistory,
|
|
4948
|
+
undo: undoHistory,
|
|
4949
|
+
redo: redoHistory
|
|
3400
4950
|
} = useMeasurerHistory({
|
|
3401
4951
|
toggles: {
|
|
3402
4952
|
enabled,
|
|
3403
|
-
setEnabled,
|
|
4953
|
+
setEnabled: setEnabledPersisted,
|
|
3404
4954
|
toolMode,
|
|
3405
|
-
setToolMode,
|
|
4955
|
+
setToolMode: setToolModePersisted,
|
|
3406
4956
|
guideOrientation,
|
|
3407
|
-
setGuideOrientation
|
|
4957
|
+
setGuideOrientation: setGuideOrientationPersisted
|
|
3408
4958
|
},
|
|
3409
4959
|
measurements: {
|
|
3410
4960
|
measurements,
|
|
3411
|
-
setMeasurements,
|
|
4961
|
+
setMeasurements: setMeasurementsPersisted,
|
|
3412
4962
|
activeMeasurement,
|
|
3413
|
-
setActiveMeasurement,
|
|
4963
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
3414
4964
|
selectedMeasurements,
|
|
3415
4965
|
setSelectedMeasurements,
|
|
3416
4966
|
selectedMeasurement,
|
|
3417
4967
|
setSelectedMeasurement,
|
|
3418
4968
|
heldDistances,
|
|
3419
|
-
setHeldDistances
|
|
4969
|
+
setHeldDistances: setHeldDistancesPersisted
|
|
3420
4970
|
},
|
|
3421
4971
|
guides: {
|
|
3422
4972
|
guides,
|
|
3423
|
-
setGuides,
|
|
4973
|
+
setGuides: setGuidesPersisted,
|
|
3424
4974
|
selectedGuideIds,
|
|
3425
|
-
setSelectedGuideIds,
|
|
4975
|
+
setSelectedGuideIds: setSelectedGuideIdsPersisted,
|
|
3426
4976
|
draggingGuideId,
|
|
3427
4977
|
setDraggingGuideId
|
|
3428
4978
|
},
|
|
@@ -3437,96 +4987,254 @@ function MeasurerClient({
|
|
|
3437
4987
|
clearSelectionRect
|
|
3438
4988
|
}
|
|
3439
4989
|
});
|
|
3440
|
-
const
|
|
4990
|
+
const undo = (0, import_react20.useCallback)(() => {
|
|
4991
|
+
if (toolMode === "text-inspector" && textInspector.undo()) return;
|
|
4992
|
+
undoHistory();
|
|
4993
|
+
}, [textInspector, toolMode, undoHistory]);
|
|
4994
|
+
const redo = (0, import_react20.useCallback)(() => {
|
|
4995
|
+
if (toolMode === "text-inspector" && textInspector.redo()) return;
|
|
4996
|
+
redoHistory();
|
|
4997
|
+
}, [redoHistory, textInspector, toolMode]);
|
|
4998
|
+
const clearAll = (0, import_react20.useCallback)(() => {
|
|
4999
|
+
if (toolMode === "text-inspector") {
|
|
5000
|
+
textInspector.clear();
|
|
5001
|
+
}
|
|
3441
5002
|
recordSnapshot();
|
|
3442
5003
|
clearGuideDragHold();
|
|
3443
5004
|
setStart(null);
|
|
3444
5005
|
setEnd(null);
|
|
3445
5006
|
setIsDragging(false);
|
|
3446
|
-
|
|
3447
|
-
|
|
5007
|
+
setActiveMeasurementPersisted(null);
|
|
5008
|
+
setMeasurementsPersisted([]);
|
|
3448
5009
|
setSelectedMeasurement(null);
|
|
3449
5010
|
setSelectedMeasurements([]);
|
|
3450
5011
|
clearSelectionRect();
|
|
3451
5012
|
setSelectedElement(null);
|
|
3452
5013
|
setHoverRect(null);
|
|
3453
5014
|
setHoverElement(null);
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
5015
|
+
setGuidesPersisted([]);
|
|
5016
|
+
setSelectedGuideIdsPersisted([]);
|
|
5017
|
+
setHeldDistancesPersisted([]);
|
|
3457
5018
|
}, [
|
|
3458
5019
|
clearGuideDragHold,
|
|
3459
5020
|
clearSelectionRect,
|
|
3460
5021
|
recordSnapshot,
|
|
3461
|
-
|
|
5022
|
+
setActiveMeasurementPersisted,
|
|
3462
5023
|
setEnd,
|
|
3463
|
-
|
|
3464
|
-
|
|
5024
|
+
setGuidesPersisted,
|
|
5025
|
+
setHeldDistancesPersisted,
|
|
3465
5026
|
setHoverElement,
|
|
3466
5027
|
setHoverRect,
|
|
3467
5028
|
setIsDragging,
|
|
3468
|
-
|
|
5029
|
+
setMeasurementsPersisted,
|
|
3469
5030
|
setSelectedElement,
|
|
3470
|
-
|
|
5031
|
+
setSelectedGuideIdsPersisted,
|
|
3471
5032
|
setSelectedMeasurement,
|
|
3472
5033
|
setSelectedMeasurements,
|
|
3473
|
-
setStart
|
|
5034
|
+
setStart,
|
|
5035
|
+
textInspector,
|
|
5036
|
+
toolMode
|
|
3474
5037
|
]);
|
|
3475
|
-
const removeSelectedGuides = (0,
|
|
5038
|
+
const removeSelectedGuides = (0, import_react20.useCallback)(() => {
|
|
3476
5039
|
if (selectedGuideIds.length === 0) return false;
|
|
3477
5040
|
recordSnapshot();
|
|
3478
|
-
|
|
5041
|
+
setGuidesPersisted(
|
|
3479
5042
|
(prev) => prev.filter((guide) => !selectedGuideIds.includes(guide.id))
|
|
3480
5043
|
);
|
|
3481
|
-
|
|
5044
|
+
setSelectedGuideIdsPersisted([]);
|
|
3482
5045
|
return true;
|
|
3483
|
-
}, [
|
|
5046
|
+
}, [
|
|
5047
|
+
recordSnapshot,
|
|
5048
|
+
selectedGuideIds,
|
|
5049
|
+
setGuidesPersisted,
|
|
5050
|
+
setSelectedGuideIdsPersisted
|
|
5051
|
+
]);
|
|
3484
5052
|
useHotkeys({
|
|
5053
|
+
eventTarget: ownerWindow,
|
|
3485
5054
|
clearAll,
|
|
5055
|
+
undo,
|
|
5056
|
+
redo,
|
|
3486
5057
|
removeSelectedGuides,
|
|
3487
5058
|
setEnabled: setEnabledWithHistory,
|
|
3488
5059
|
setToolMode: setToolModeWithHistory,
|
|
5060
|
+
setRulersVisible: setRulersVisiblePersisted,
|
|
3489
5061
|
setAltPressed,
|
|
3490
5062
|
isOverlayActive: () => enabled && (toolMode !== "none" || toolbarActive),
|
|
3491
5063
|
setGuideOrientation: setGuideOrientationWithHistory,
|
|
3492
5064
|
onInteract: () => setToolbarActive(true)
|
|
3493
5065
|
});
|
|
3494
5066
|
useResizeSync({
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
5067
|
+
document: ownerDocument,
|
|
5068
|
+
window: ownerWindow,
|
|
5069
|
+
setMeasurements: setMeasurementsPersisted,
|
|
5070
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5071
|
+
setHeldDistances: setHeldDistancesPersisted,
|
|
3498
5072
|
setSelectedMeasurement,
|
|
3499
|
-
setGuides,
|
|
5073
|
+
setGuides: setGuidesPersisted,
|
|
3500
5074
|
selectedElementRef
|
|
3501
5075
|
});
|
|
5076
|
+
(0, import_react20.useEffect)(() => {
|
|
5077
|
+
const handleScroll = () => {
|
|
5078
|
+
const next = {
|
|
5079
|
+
x: ownerWindow.scrollX,
|
|
5080
|
+
y: ownerWindow.scrollY
|
|
5081
|
+
};
|
|
5082
|
+
const deltaX = next.x - guideScrollRef.current.x;
|
|
5083
|
+
const deltaY = next.y - guideScrollRef.current.y;
|
|
5084
|
+
guideScrollRef.current = next;
|
|
5085
|
+
if (deltaX === 0 && deltaY === 0) return;
|
|
5086
|
+
setGuidesPersisted(
|
|
5087
|
+
(prev) => prev.map((guide) => ({
|
|
5088
|
+
...guide,
|
|
5089
|
+
position: guide.position - (guide.orientation === "vertical" ? deltaX : deltaY)
|
|
5090
|
+
}))
|
|
5091
|
+
);
|
|
5092
|
+
};
|
|
5093
|
+
ownerWindow.addEventListener("scroll", handleScroll, true);
|
|
5094
|
+
return () => ownerWindow.removeEventListener("scroll", handleScroll, true);
|
|
5095
|
+
}, [ownerWindow, setGuidesPersisted]);
|
|
3502
5096
|
useLiveElementTracking({
|
|
5097
|
+
document: ownerDocument,
|
|
5098
|
+
window: ownerWindow,
|
|
3503
5099
|
enabled,
|
|
3504
5100
|
selectedElementRef,
|
|
3505
5101
|
hoverElementRef,
|
|
3506
5102
|
setSelectedMeasurement,
|
|
3507
5103
|
setSelectedMeasurements,
|
|
3508
5104
|
setHoverRect,
|
|
3509
|
-
setMeasurements,
|
|
3510
|
-
setActiveMeasurement,
|
|
3511
|
-
setHeldDistances
|
|
5105
|
+
setMeasurements: setMeasurementsPersisted,
|
|
5106
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5107
|
+
setHeldDistances: setHeldDistancesPersisted
|
|
3512
5108
|
});
|
|
3513
|
-
(0,
|
|
5109
|
+
(0, import_react20.useEffect)(() => {
|
|
3514
5110
|
if (!toolbarActive || toolMode !== "none") return;
|
|
3515
5111
|
const handlePointerDown2 = (event) => {
|
|
3516
5112
|
const toolbarNode = toolbarRef.current;
|
|
3517
5113
|
if (toolbarNode && toolbarNode.contains(event.target)) return;
|
|
3518
5114
|
setToolbarActive(false);
|
|
3519
5115
|
};
|
|
3520
|
-
|
|
5116
|
+
ownerWindow.addEventListener("pointerdown", handlePointerDown2);
|
|
3521
5117
|
return () => {
|
|
3522
|
-
|
|
5118
|
+
ownerWindow.removeEventListener("pointerdown", handlePointerDown2);
|
|
3523
5119
|
};
|
|
3524
|
-
}, [toolbarActive, toolMode]);
|
|
3525
|
-
(0,
|
|
3526
|
-
if (
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
5120
|
+
}, [ownerWindow, toolbarActive, toolMode]);
|
|
5121
|
+
(0, import_react20.useEffect)(() => {
|
|
5122
|
+
if (!enabled) return;
|
|
5123
|
+
const handleGuidePointerDown2 = (event) => {
|
|
5124
|
+
if (toolbarRef.current?.contains(event.target)) return;
|
|
5125
|
+
const guideTarget = event.composedPath().some(
|
|
5126
|
+
(target) => target instanceof ownerWindow.Element && target.hasAttribute("data-mesurer-guide")
|
|
5127
|
+
);
|
|
5128
|
+
if (guideTarget && toolMode !== "none") return;
|
|
5129
|
+
const point = { x: event.clientX, y: event.clientY };
|
|
5130
|
+
const guide = guides.find((candidate) => {
|
|
5131
|
+
const distance = candidate.orientation === "vertical" ? Math.abs(candidate.position - point.x) : Math.abs(candidate.position - point.y);
|
|
5132
|
+
return distance <= GUIDE_HITBOX_SIZE / 2;
|
|
5133
|
+
});
|
|
5134
|
+
if (!guide) return;
|
|
5135
|
+
if (event.button === 0 && !event.shiftKey && toolMode === "none") {
|
|
5136
|
+
guideDragRef.current = {
|
|
5137
|
+
id: guide.id,
|
|
5138
|
+
orientation: guide.orientation,
|
|
5139
|
+
pointerId: event.pointerId,
|
|
5140
|
+
commit: createActionCommit(),
|
|
5141
|
+
committed: false
|
|
5142
|
+
};
|
|
5143
|
+
}
|
|
5144
|
+
setSelectedGuideIdsPersisted(
|
|
5145
|
+
(prev) => event.shiftKey ? prev.includes(guide.id) ? prev.filter((id) => id !== guide.id) : [...prev, guide.id] : [guide.id]
|
|
5146
|
+
);
|
|
5147
|
+
};
|
|
5148
|
+
const handleGuidePointerMove = (event) => {
|
|
5149
|
+
const drag = guideDragRef.current;
|
|
5150
|
+
if (!drag || drag.pointerId !== event.pointerId) return;
|
|
5151
|
+
const position = drag.orientation === "vertical" ? event.clientX : event.clientY;
|
|
5152
|
+
if (!drag.committed) {
|
|
5153
|
+
event.preventDefault();
|
|
5154
|
+
if (guideUserSelectRef.current === null) {
|
|
5155
|
+
guideUserSelectRef.current = ownerDocument.documentElement.style.userSelect;
|
|
5156
|
+
ownerDocument.documentElement.style.userSelect = "none";
|
|
5157
|
+
}
|
|
5158
|
+
ownerWindow.getSelection()?.removeAllRanges();
|
|
5159
|
+
drag.commit();
|
|
5160
|
+
drag.committed = true;
|
|
5161
|
+
}
|
|
5162
|
+
setGuidesPersisted(
|
|
5163
|
+
(prev) => prev.map(
|
|
5164
|
+
(guide) => guide.id === drag.id ? { ...guide, position } : guide
|
|
5165
|
+
)
|
|
5166
|
+
);
|
|
5167
|
+
};
|
|
5168
|
+
const handleGuidePointerEnd = (event) => {
|
|
5169
|
+
if (guideDragRef.current?.pointerId === event.pointerId) {
|
|
5170
|
+
guideDragRef.current = null;
|
|
5171
|
+
if (guideUserSelectRef.current !== null) {
|
|
5172
|
+
ownerDocument.documentElement.style.userSelect = guideUserSelectRef.current;
|
|
5173
|
+
guideUserSelectRef.current = null;
|
|
5174
|
+
}
|
|
5175
|
+
}
|
|
5176
|
+
};
|
|
5177
|
+
ownerWindow.addEventListener("pointerdown", handleGuidePointerDown2, true);
|
|
5178
|
+
ownerWindow.addEventListener("pointermove", handleGuidePointerMove, true);
|
|
5179
|
+
ownerWindow.addEventListener("pointerup", handleGuidePointerEnd, true);
|
|
5180
|
+
ownerWindow.addEventListener("pointercancel", handleGuidePointerEnd, true);
|
|
5181
|
+
return () => {
|
|
5182
|
+
ownerWindow.removeEventListener(
|
|
5183
|
+
"pointerdown",
|
|
5184
|
+
handleGuidePointerDown2,
|
|
5185
|
+
true
|
|
5186
|
+
);
|
|
5187
|
+
ownerWindow.removeEventListener("pointermove", handleGuidePointerMove, true);
|
|
5188
|
+
ownerWindow.removeEventListener("pointerup", handleGuidePointerEnd, true);
|
|
5189
|
+
ownerWindow.removeEventListener(
|
|
5190
|
+
"pointercancel",
|
|
5191
|
+
handleGuidePointerEnd,
|
|
5192
|
+
true
|
|
5193
|
+
);
|
|
5194
|
+
if (guideUserSelectRef.current !== null) {
|
|
5195
|
+
ownerDocument.documentElement.style.userSelect = guideUserSelectRef.current;
|
|
5196
|
+
guideUserSelectRef.current = null;
|
|
5197
|
+
}
|
|
5198
|
+
};
|
|
5199
|
+
}, [
|
|
5200
|
+
createActionCommit,
|
|
5201
|
+
enabled,
|
|
5202
|
+
guides,
|
|
5203
|
+
ownerWindow,
|
|
5204
|
+
setGuidesPersisted,
|
|
5205
|
+
setSelectedGuideIdsPersisted,
|
|
5206
|
+
toolMode
|
|
5207
|
+
]);
|
|
5208
|
+
(0, import_react20.useEffect)(() => {
|
|
5209
|
+
if (toolMode === "text-inspector") {
|
|
5210
|
+
textInspector.enable();
|
|
5211
|
+
} else {
|
|
5212
|
+
textInspector.disable();
|
|
5213
|
+
}
|
|
5214
|
+
}, [textInspector, toolMode]);
|
|
5215
|
+
(0, import_react20.useEffect)(() => {
|
|
5216
|
+
let style = ownerDocument.getElementById(XRAY_STYLE_ID);
|
|
5217
|
+
if (!style) {
|
|
5218
|
+
style = ownerDocument.createElement("style");
|
|
5219
|
+
style.id = XRAY_STYLE_ID;
|
|
5220
|
+
style.textContent = XRAY_STYLES;
|
|
5221
|
+
ownerDocument.head.appendChild(style);
|
|
5222
|
+
}
|
|
5223
|
+
if (toolMode === "xray") {
|
|
5224
|
+
ownerDocument.body.classList.add("xray-mode");
|
|
5225
|
+
} else {
|
|
5226
|
+
ownerDocument.body.classList.remove("xray-mode");
|
|
5227
|
+
}
|
|
5228
|
+
return () => {
|
|
5229
|
+
ownerDocument.body.classList.remove("xray-mode");
|
|
5230
|
+
};
|
|
5231
|
+
}, [ownerDocument, toolMode]);
|
|
5232
|
+
(0, import_react20.useEffect)(() => {
|
|
5233
|
+
return () => {
|
|
5234
|
+
textInspector.destroy();
|
|
5235
|
+
};
|
|
5236
|
+
}, [textInspector]);
|
|
5237
|
+
(0, import_react20.useEffect)(() => {
|
|
3530
5238
|
const hasSelectionAnimationState = !!selectionOriginRect || !!selectedMeasurement?.originRect || selectedMeasurements.some((measurement) => !!measurement.originRect);
|
|
3531
5239
|
if (!hasSelectionAnimationState) {
|
|
3532
5240
|
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
@@ -3555,6 +5263,12 @@ function MeasurerClient({
|
|
|
3555
5263
|
return changed ? next : prev;
|
|
3556
5264
|
});
|
|
3557
5265
|
}, MEASURE_TRANSITION_MS);
|
|
5266
|
+
return () => {
|
|
5267
|
+
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
5268
|
+
window.clearTimeout(selectionAnimationCleanupTimeoutRef.current);
|
|
5269
|
+
selectionAnimationCleanupTimeoutRef.current = null;
|
|
5270
|
+
}
|
|
5271
|
+
};
|
|
3558
5272
|
}, [
|
|
3559
5273
|
selectionOriginRect,
|
|
3560
5274
|
selectedMeasurement,
|
|
@@ -3563,13 +5277,6 @@ function MeasurerClient({
|
|
|
3563
5277
|
setSelectedMeasurements,
|
|
3564
5278
|
setSelectionOriginRect
|
|
3565
5279
|
]);
|
|
3566
|
-
(0, import_react19.useEffect)(() => {
|
|
3567
|
-
return () => {
|
|
3568
|
-
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
3569
|
-
window.clearTimeout(selectionAnimationCleanupTimeoutRef.current);
|
|
3570
|
-
}
|
|
3571
|
-
};
|
|
3572
|
-
}, []);
|
|
3573
5280
|
const displayedMeasurements = holdEnabled ? measurements : multiMeasureEnabled && measurements.length > 0 ? measurements : activeMeasurement ? [activeMeasurement] : [];
|
|
3574
5281
|
const {
|
|
3575
5282
|
activeRect,
|
|
@@ -3591,6 +5298,8 @@ function MeasurerClient({
|
|
|
3591
5298
|
hoverEdgeVisibility,
|
|
3592
5299
|
measurementEdgeVisibility
|
|
3593
5300
|
} = useMeasurerDerived({
|
|
5301
|
+
document: ownerDocument,
|
|
5302
|
+
window: ownerWindow,
|
|
3594
5303
|
start,
|
|
3595
5304
|
end,
|
|
3596
5305
|
selectedMeasurements,
|
|
@@ -3616,6 +5325,8 @@ function MeasurerClient({
|
|
|
3616
5325
|
handlePointerUp,
|
|
3617
5326
|
handlePointerLeave
|
|
3618
5327
|
} = useMeasurerPointer({
|
|
5328
|
+
document: ownerDocument,
|
|
5329
|
+
window: ownerWindow,
|
|
3619
5330
|
toolbarRef,
|
|
3620
5331
|
overlayRef,
|
|
3621
5332
|
selectionRectRef,
|
|
@@ -3641,15 +5352,15 @@ function MeasurerClient({
|
|
|
3641
5352
|
optionPairOverlay,
|
|
3642
5353
|
setAltPressed,
|
|
3643
5354
|
setGuidePreview,
|
|
3644
|
-
setSelectedGuideIds,
|
|
3645
|
-
setGuides,
|
|
5355
|
+
setSelectedGuideIds: setSelectedGuideIdsPersisted,
|
|
5356
|
+
setGuides: setGuidesPersisted,
|
|
3646
5357
|
setStart,
|
|
3647
5358
|
setEnd,
|
|
3648
5359
|
setIsDragging,
|
|
3649
|
-
setHeldDistances,
|
|
5360
|
+
setHeldDistances: setHeldDistancesPersisted,
|
|
3650
5361
|
setDraggingGuideId,
|
|
3651
|
-
setActiveMeasurement,
|
|
3652
|
-
setMeasurements,
|
|
5362
|
+
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5363
|
+
setMeasurements: setMeasurementsPersisted,
|
|
3653
5364
|
setSelectedMeasurements,
|
|
3654
5365
|
setSelectedMeasurement,
|
|
3655
5366
|
setSelectionOriginRect,
|
|
@@ -3659,27 +5370,65 @@ function MeasurerClient({
|
|
|
3659
5370
|
setHoverPointer,
|
|
3660
5371
|
clearSelectionRect
|
|
3661
5372
|
});
|
|
3662
|
-
const removeHeldDistance = (0,
|
|
5373
|
+
const removeHeldDistance = (0, import_react20.useCallback)(
|
|
3663
5374
|
(id) => {
|
|
3664
5375
|
recordSnapshot();
|
|
3665
|
-
|
|
5376
|
+
setHeldDistancesPersisted(
|
|
5377
|
+
(prev) => prev.filter((distance) => distance.id !== id)
|
|
5378
|
+
);
|
|
5379
|
+
},
|
|
5380
|
+
[recordSnapshot, setHeldDistancesPersisted]
|
|
5381
|
+
);
|
|
5382
|
+
const startGuideFromRuler = (0, import_react20.useCallback)(
|
|
5383
|
+
(orientation, position) => {
|
|
5384
|
+
const id = createId();
|
|
5385
|
+
const commit = createActionCommit();
|
|
5386
|
+
commit();
|
|
5387
|
+
setSelectedGuideIdsPersisted([]);
|
|
5388
|
+
setGuidesPersisted((prev) => [...prev, { id, orientation, position }]);
|
|
5389
|
+
return id;
|
|
5390
|
+
},
|
|
5391
|
+
[
|
|
5392
|
+
createActionCommit,
|
|
5393
|
+
setGuidesPersisted,
|
|
5394
|
+
setSelectedGuideIdsPersisted
|
|
5395
|
+
]
|
|
5396
|
+
);
|
|
5397
|
+
const moveGuideFromRuler = (0, import_react20.useCallback)(
|
|
5398
|
+
(id, position) => {
|
|
5399
|
+
setGuidesPersisted(
|
|
5400
|
+
(prev) => prev.map((guide) => guide.id === id ? { ...guide, position } : guide)
|
|
5401
|
+
);
|
|
3666
5402
|
},
|
|
3667
|
-
[
|
|
5403
|
+
[setGuidesPersisted]
|
|
3668
5404
|
);
|
|
3669
|
-
const
|
|
5405
|
+
const finishGuideFromRuler = (0, import_react20.useCallback)(
|
|
5406
|
+
(id) => {
|
|
5407
|
+
setSelectedGuideIdsPersisted([id]);
|
|
5408
|
+
},
|
|
5409
|
+
[setSelectedGuideIdsPersisted]
|
|
5410
|
+
);
|
|
5411
|
+
const cancelGuideFromRuler = (0, import_react20.useCallback)(
|
|
5412
|
+
(id) => {
|
|
5413
|
+
setGuidesPersisted((prev) => prev.filter((guide) => guide.id !== id));
|
|
5414
|
+
},
|
|
5415
|
+
[setGuidesPersisted]
|
|
5416
|
+
);
|
|
5417
|
+
const handleGuidePointerDown = (0, import_react20.useCallback)(
|
|
3670
5418
|
(guide, event) => {
|
|
3671
5419
|
const commit = createActionCommit();
|
|
3672
5420
|
if (!enabled) return;
|
|
3673
5421
|
event.stopPropagation();
|
|
5422
|
+
event.preventDefault();
|
|
3674
5423
|
if (event.shiftKey) {
|
|
3675
5424
|
commit();
|
|
3676
|
-
|
|
5425
|
+
setSelectedGuideIdsPersisted(
|
|
3677
5426
|
(prev) => prev.includes(guide.id) ? prev.filter((id) => id !== guide.id) : [...prev, guide.id]
|
|
3678
5427
|
);
|
|
3679
5428
|
return;
|
|
3680
5429
|
}
|
|
3681
5430
|
commit();
|
|
3682
|
-
|
|
5431
|
+
setSelectedGuideIdsPersisted([guide.id]);
|
|
3683
5432
|
scheduleGuideDragHold(guide.id, setDraggingGuideId);
|
|
3684
5433
|
event.currentTarget.setPointerCapture(event.pointerId);
|
|
3685
5434
|
},
|
|
@@ -3688,10 +5437,10 @@ function MeasurerClient({
|
|
|
3688
5437
|
enabled,
|
|
3689
5438
|
scheduleGuideDragHold,
|
|
3690
5439
|
setDraggingGuideId,
|
|
3691
|
-
|
|
5440
|
+
setSelectedGuideIdsPersisted
|
|
3692
5441
|
]
|
|
3693
5442
|
);
|
|
3694
|
-
const handleGuidePointerUp = (0,
|
|
5443
|
+
const handleGuidePointerUp = (0, import_react20.useCallback)(
|
|
3695
5444
|
(guide, event) => {
|
|
3696
5445
|
event.stopPropagation();
|
|
3697
5446
|
clearGuideDragHold();
|
|
@@ -3703,17 +5452,29 @@ function MeasurerClient({
|
|
|
3703
5452
|
[clearGuideDragHold, setDraggingGuideId]
|
|
3704
5453
|
);
|
|
3705
5454
|
return (0, import_react_dom.createPortal)(
|
|
3706
|
-
/* @__PURE__ */ (0,
|
|
5455
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
|
|
3707
5456
|
"div",
|
|
3708
5457
|
{
|
|
3709
5458
|
ref: overlayRef,
|
|
3710
5459
|
className: "mesurer-root msr:pointer-events-none msr:fixed msr:inset-0 msr:z-50",
|
|
3711
5460
|
children: [
|
|
3712
|
-
/* @__PURE__ */ (0,
|
|
5461
|
+
enabled && rulersVisible ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
5462
|
+
RulersOverlay,
|
|
5463
|
+
{
|
|
5464
|
+
onStartGuide: startGuideFromRuler,
|
|
5465
|
+
onMoveGuide: moveGuideFromRuler,
|
|
5466
|
+
onFinishGuide: finishGuideFromRuler,
|
|
5467
|
+
onCancelGuide: cancelGuideFromRuler,
|
|
5468
|
+
guides,
|
|
5469
|
+
selectedGuideIds
|
|
5470
|
+
}
|
|
5471
|
+
) : null,
|
|
5472
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3713
5473
|
MeasurerOverlay,
|
|
3714
5474
|
{
|
|
3715
5475
|
enabled,
|
|
3716
5476
|
toolMode,
|
|
5477
|
+
guidePointerEvents: enabled && (toolMode !== "none" || rulersVisible),
|
|
3717
5478
|
guidesEnabled,
|
|
3718
5479
|
altPressed,
|
|
3719
5480
|
isDragging,
|
|
@@ -3751,13 +5512,16 @@ function MeasurerClient({
|
|
|
3751
5512
|
onGuidePointerCancel: handleGuidePointerUp
|
|
3752
5513
|
}
|
|
3753
5514
|
),
|
|
3754
|
-
/* @__PURE__ */ (0,
|
|
5515
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3755
5516
|
Toolbar,
|
|
3756
5517
|
{
|
|
3757
5518
|
ref: toolbarRef,
|
|
5519
|
+
eventTarget: ownerWindow,
|
|
3758
5520
|
toolMode,
|
|
3759
5521
|
setEnabled: setEnabledWithHistory,
|
|
3760
5522
|
setToolMode: setToolModeWithHistory,
|
|
5523
|
+
rulersVisible,
|
|
5524
|
+
setRulersVisible: setRulersVisiblePersisted,
|
|
3761
5525
|
guideOrientation,
|
|
3762
5526
|
setGuideOrientation: setGuideOrientationWithHistory,
|
|
3763
5527
|
onInteract: () => setToolbarActive(true)
|
|
@@ -3774,25 +5538,29 @@ function Measurer({
|
|
|
3774
5538
|
guideColor = "oklch(0.63 0.26 29.23)",
|
|
3775
5539
|
hoverHighlightEnabled = true,
|
|
3776
5540
|
persistOnReload = false,
|
|
3777
|
-
portalTarget
|
|
5541
|
+
portalTarget,
|
|
5542
|
+
persistKey
|
|
3778
5543
|
}) {
|
|
3779
5544
|
if (typeof document !== "undefined") {
|
|
3780
5545
|
ensureMeasurerStyles(MESURER_STYLES, portalTarget);
|
|
3781
5546
|
}
|
|
3782
5547
|
const hydrated = useHydrated();
|
|
3783
5548
|
if (!hydrated) return null;
|
|
3784
|
-
return /* @__PURE__ */ (0,
|
|
5549
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
3785
5550
|
MeasurerClient,
|
|
3786
5551
|
{
|
|
3787
5552
|
highlightColor,
|
|
3788
5553
|
guideColor,
|
|
3789
5554
|
hoverHighlightEnabled,
|
|
3790
5555
|
persistOnReload,
|
|
5556
|
+
persistKey,
|
|
3791
5557
|
portalTarget: portalTarget ?? document.body
|
|
3792
5558
|
}
|
|
3793
5559
|
);
|
|
3794
5560
|
}
|
|
3795
5561
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3796
5562
|
0 && (module.exports = {
|
|
3797
|
-
Measurer
|
|
5563
|
+
Measurer,
|
|
5564
|
+
TextInspector,
|
|
5565
|
+
createTextInspector
|
|
3798
5566
|
});
|