mesurer 0.0.9 → 0.0.11
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 +15 -0
- package/README.md +28 -7
- package/dist/index.cjs +2440 -539
- package/dist/index.d.cts +136 -2
- package/dist/index.d.ts +136 -2
- package/dist/index.js +2413 -515
- package/dist/styles.css +553 -4
- package/package.json +9 -8
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// measurer.tsx
|
|
2
2
|
import {
|
|
3
|
-
useCallback as
|
|
4
|
-
useEffect as
|
|
3
|
+
useCallback as useCallback8,
|
|
4
|
+
useEffect as useEffect7,
|
|
5
5
|
useMemo as useMemo2,
|
|
6
|
-
useRef as
|
|
7
|
-
useState as
|
|
6
|
+
useRef as useRef12,
|
|
7
|
+
useState as useState11,
|
|
8
8
|
useSyncExternalStore
|
|
9
9
|
} from "react";
|
|
10
10
|
import { createPortal } from "react-dom";
|
|
@@ -24,6 +24,7 @@ var MIN_SINGLE_ELEMENT_COVERAGE = 0.15;
|
|
|
24
24
|
|
|
25
25
|
// runtime/style-inject.ts
|
|
26
26
|
var MESURER_STYLE_ID = "mesurer-styles";
|
|
27
|
+
var injectedTargets = /* @__PURE__ */ new WeakSet();
|
|
27
28
|
var isDocument = (target) => target.nodeType === 9;
|
|
28
29
|
var isShadowRoot = (target) => target.nodeType === 11;
|
|
29
30
|
var getStyleTarget = (target) => {
|
|
@@ -34,12 +35,29 @@ var getStyleTarget = (target) => {
|
|
|
34
35
|
if (rootNode.nodeType === 11) return rootNode;
|
|
35
36
|
return target.ownerDocument ?? document;
|
|
36
37
|
};
|
|
38
|
+
var adoptSheet = (styleTarget, cssText) => {
|
|
39
|
+
const sheet = new CSSStyleSheet();
|
|
40
|
+
sheet.replaceSync(cssText);
|
|
41
|
+
styleTarget.adoptedStyleSheets = [...styleTarget.adoptedStyleSheets, sheet];
|
|
42
|
+
};
|
|
37
43
|
function ensureMeasurerStyles(cssText, target) {
|
|
38
44
|
if (typeof document === "undefined") return;
|
|
39
45
|
if (!cssText) return;
|
|
40
46
|
const styleTarget = getStyleTarget(target);
|
|
41
47
|
if (!styleTarget) return;
|
|
42
|
-
if (
|
|
48
|
+
if (injectedTargets.has(styleTarget)) return;
|
|
49
|
+
if (styleTarget.querySelector(`#${MESURER_STYLE_ID}`)) {
|
|
50
|
+
injectedTargets.add(styleTarget);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (isShadowRoot(styleTarget)) {
|
|
54
|
+
try {
|
|
55
|
+
adoptSheet(styleTarget, cssText);
|
|
56
|
+
injectedTargets.add(styleTarget);
|
|
57
|
+
return;
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
43
61
|
const ownerDocument = isDocument(styleTarget) ? styleTarget : styleTarget.ownerDocument;
|
|
44
62
|
if (!ownerDocument) return;
|
|
45
63
|
const style = ownerDocument.createElement("style");
|
|
@@ -47,22 +65,24 @@ function ensureMeasurerStyles(cssText, target) {
|
|
|
47
65
|
style.textContent = cssText;
|
|
48
66
|
if (isShadowRoot(styleTarget)) {
|
|
49
67
|
styleTarget.appendChild(style);
|
|
50
|
-
|
|
68
|
+
} else {
|
|
69
|
+
ownerDocument.head.appendChild(style);
|
|
51
70
|
}
|
|
52
|
-
|
|
71
|
+
injectedTargets.add(styleTarget);
|
|
53
72
|
}
|
|
54
73
|
|
|
55
74
|
// styles.generated.ts
|
|
56
|
-
var MESURER_STYLES = '/*! tailwindcss v4.2.2 | MIT License | https://tailwindcss.com */\n@layer properties;\n@layer theme, base, components, utilities;\n@layer theme {\n :root, :host {\n --msr-font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",\n "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";\n --msr-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",\n "Courier New", monospace;\n --msr-color-black: #000;\n --msr-color-white: #fff;\n --msr-spacing: 0.25rem;\n --msr-radius-md: 0.375rem;\n --msr-radius-lg: 0.5rem;\n --msr-default-transition-duration: 150ms;\n --msr-default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);\n --msr-default-font-family: var(--msr-font-sans);\n --msr-default-mono-font-family: var(--msr-font-mono);\n --msr-color-ink-50: var(--color-ink-50);\n --msr-color-ink-200: var(--color-ink-200);\n --msr-color-ink-700: var(--color-ink-700);\n --msr-color-ink-900: var(--color-ink-900);\n }\n}\n@layer base {\n *, ::after, ::before, ::backdrop, ::file-selector-button {\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n border: 0 solid;\n }\n html, :host {\n line-height: 1.5;\n -webkit-text-size-adjust: 100%;\n tab-size: 4;\n font-family: var(--msr-default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji");\n font-feature-settings: var(--msr-default-font-feature-settings, normal);\n font-variation-settings: var(--msr-default-font-variation-settings, normal);\n -webkit-tap-highlight-color: transparent;\n }\n hr {\n height: 0;\n color: inherit;\n border-top-width: 1px;\n }\n abbr:where([title]) {\n -webkit-text-decoration: underline dotted;\n text-decoration: underline dotted;\n }\n h1, h2, h3, h4, h5, h6 {\n font-size: inherit;\n font-weight: inherit;\n }\n a {\n color: inherit;\n -webkit-text-decoration: inherit;\n text-decoration: inherit;\n }\n b, strong {\n font-weight: bolder;\n }\n code, kbd, samp, pre {\n font-family: var(--msr-default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);\n font-feature-settings: var(--msr-default-mono-font-feature-settings, normal);\n font-variation-settings: var(--msr-default-mono-font-variation-settings, normal);\n font-size: 1em;\n }\n small {\n font-size: 80%;\n }\n sub, sup {\n font-size: 75%;\n line-height: 0;\n position: relative;\n vertical-align: baseline;\n }\n sub {\n bottom: -0.25em;\n }\n sup {\n top: -0.5em;\n }\n table {\n text-indent: 0;\n border-color: inherit;\n border-collapse: collapse;\n }\n :-moz-focusring {\n outline: auto;\n }\n progress {\n vertical-align: baseline;\n }\n summary {\n display: list-item;\n }\n ol, ul, menu {\n list-style: none;\n }\n img, svg, video, canvas, audio, iframe, embed, object {\n display: block;\n vertical-align: middle;\n }\n img, video {\n max-width: 100%;\n height: auto;\n }\n button, input, select, optgroup, textarea, ::file-selector-button {\n font: inherit;\n font-feature-settings: inherit;\n font-variation-settings: inherit;\n letter-spacing: inherit;\n color: inherit;\n border-radius: 0;\n background-color: transparent;\n opacity: 1;\n }\n :where(select:is([multiple], [size])) optgroup {\n font-weight: bolder;\n }\n :where(select:is([multiple], [size])) optgroup option {\n padding-inline-start: 20px;\n }\n ::file-selector-button {\n margin-inline-end: 4px;\n }\n ::placeholder {\n opacity: 1;\n }\n @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) {\n ::placeholder {\n color: currentcolor;\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, currentcolor 50%, transparent);\n }\n }\n }\n textarea {\n resize: vertical;\n }\n ::-webkit-search-decoration {\n -webkit-appearance: none;\n }\n ::-webkit-date-and-time-value {\n min-height: 1lh;\n text-align: inherit;\n }\n ::-webkit-datetime-edit {\n display: inline-flex;\n }\n ::-webkit-datetime-edit-fields-wrapper {\n padding: 0;\n }\n ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {\n padding-block: 0;\n }\n ::-webkit-calendar-picker-indicator {\n line-height: 1;\n }\n :-moz-ui-invalid {\n box-shadow: none;\n }\n button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {\n appearance: button;\n }\n ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {\n height: auto;\n }\n [hidden]:where(:not([hidden="until-found"])) {\n display: none !important;\n }\n}\n@layer utilities {\n .msr\\:pointer-events-auto {\n pointer-events: auto;\n }\n .msr\\:pointer-events-none {\n pointer-events: none;\n }\n .msr\\:absolute {\n position: absolute;\n }\n .msr\\:fixed {\n position: fixed;\n }\n .msr\\:relative {\n position: relative;\n }\n .msr\\:inset-0 {\n inset: calc(var(--msr-spacing) * 0);\n }\n .msr\\:top-0 {\n top: calc(var(--msr-spacing) * 0);\n }\n .msr\\:top-\\[18px\\] {\n top: 18px;\n }\n .msr\\:top-full {\n top: 100%;\n }\n .msr\\:right-0 {\n right: calc(var(--msr-spacing) * 0);\n }\n .msr\\:bottom-0 {\n bottom: calc(var(--msr-spacing) * 0);\n }\n .msr\\:bottom-full {\n bottom: 100%;\n }\n .msr\\:left-0 {\n left: calc(var(--msr-spacing) * 0);\n }\n .msr\\:left-1\\/2 {\n left: calc(1 / 2 * 100%);\n }\n .msr\\:left-\\[18px\\] {\n left: 18px;\n }\n .msr\\:z-50 {\n z-index: 50;\n }\n .msr\\:z-\\[70\\] {\n z-index: 70;\n }\n .msr\\:z-\\[90\\] {\n z-index: 90;\n }\n .msr\\:mt-2 {\n margin-top: calc(var(--msr-spacing) * 2);\n }\n .msr\\:mb-2 {\n margin-bottom: calc(var(--msr-spacing) * 2);\n }\n .msr\\:-ml-1 {\n margin-left: calc(var(--msr-spacing) * -1);\n }\n .msr\\:block {\n display: block;\n }\n .msr\\:flex {\n display: flex;\n }\n .msr\\:size-8 {\n width: calc(var(--msr-spacing) * 8);\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:size-\\[18px\\] {\n width: 18px;\n height: 18px;\n }\n .msr\\:h-6 {\n height: calc(var(--msr-spacing) * 6);\n }\n .msr\\:h-8 {\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:h-full {\n height: 100%;\n }\n .msr\\:h-px {\n height: 1px;\n }\n .msr\\:w-4 {\n width: calc(var(--msr-spacing) * 4);\n }\n .msr\\:w-6 {\n width: calc(var(--msr-spacing) * 6);\n }\n .msr\\:w-44 {\n width: calc(var(--msr-spacing) * 44);\n }\n .msr\\:w-\\[18px\\] {\n width: 18px;\n }\n .msr\\:w-full {\n width: 100%;\n }\n .msr\\:w-px {\n width: 1px;\n }\n .msr\\:flex-1 {\n flex: 1;\n }\n .msr\\:-translate-x-1\\/2 {\n --tw-translate-x: calc(calc(1 / 2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .msr\\:-translate-y-1\\/2 {\n --tw-translate-y: calc(calc(1 / 2 * 100%) * -1);\n translate: var(--tw-translate-x) var(--tw-translate-y);\n }\n .msr\\:rotate-90 {\n rotate: 90deg;\n }\n .msr\\:rotate-\\[45deg\\] {\n rotate: 45deg;\n }\n .msr\\:rotate-\\[135deg\\] {\n rotate: 135deg;\n }\n .msr\\:cursor-crosshair {\n cursor: crosshair;\n }\n .msr\\:cursor-default {\n cursor: default;\n }\n .msr\\:flex-col {\n flex-direction: column;\n }\n .msr\\:items-center {\n align-items: center;\n }\n .msr\\:items-stretch {\n align-items: stretch;\n }\n .msr\\:justify-center {\n justify-content: center;\n }\n .msr\\:gap-1 {\n gap: calc(var(--msr-spacing) * 1);\n }\n .msr\\:gap-2 {\n gap: calc(var(--msr-spacing) * 2);\n }\n .msr\\:gap-px {\n gap: 1px;\n }\n .msr\\:overflow-hidden {\n overflow: hidden;\n }\n .msr\\:rounded {\n border-radius: 0.25rem;\n }\n .msr\\:rounded-\\[6px\\] {\n border-radius: 6px;\n }\n .msr\\:rounded-\\[8px\\] {\n border-radius: 8px;\n }\n .msr\\:rounded-\\[12px\\] {\n border-radius: 12px;\n }\n .msr\\:rounded-lg {\n border-radius: var(--msr-radius-lg);\n }\n .msr\\:rounded-md {\n border-radius: var(--msr-radius-md);\n }\n .msr\\:border {\n border-style: var(--tw-border-style);\n border-width: 1px;\n }\n .msr\\:border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .msr\\:border-l {\n border-left-style: var(--tw-border-style);\n border-left-width: 1px;\n }\n .msr\\:border-dashed {\n --tw-border-style: dashed;\n border-style: dashed;\n }\n .msr\\:border-\\[\\#2563eb\\]\\/70 {\n border-color: color-mix(in oklab, #2563eb 70%, transparent);\n }\n .msr\\:border-ink-200 {\n border-color: var(--msr-color-ink-200);\n }\n .msr\\:bg-\\[\\#0d99ff\\] {\n background-color: #0d99ff;\n }\n .msr\\:bg-\\[\\#2563eb\\] {\n background-color: #2563eb;\n }\n .msr\\:bg-\\[\\#fff\\] {\n background-color: #fff;\n }\n .msr\\:bg-black {\n background-color: var(--msr-color-black);\n }\n .msr\\:bg-black\\/10 {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n .msr\\:bg-ink-900\\/90 {\n background-color: var(--msr-color-ink-900);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-ink-900) 90%, transparent);\n }\n }\n .msr\\:bg-transparent {\n background-color: transparent;\n }\n .msr\\:bg-white {\n background-color: var(--msr-color-white);\n }\n .msr\\:p-1 {\n padding: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-1 {\n padding-inline: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-2 {\n padding-inline: calc(var(--msr-spacing) * 2);\n }\n .msr\\:py-0\\.5 {\n padding-block: calc(var(--msr-spacing) * 0.5);\n }\n .msr\\:py-1 {\n padding-block: calc(var(--msr-spacing) * 1);\n }\n .msr\\:py-1\\.5 {\n padding-block: calc(var(--msr-spacing) * 1.5);\n }\n .msr\\:text-left {\n text-align: left;\n }\n .msr\\:text-\\[9px\\] {\n font-size: 9px;\n }\n .msr\\:text-\\[10px\\] {\n font-size: 10px;\n }\n .msr\\:text-\\[11px\\] {\n font-size: 11px;\n }\n .msr\\:text-\\[12px\\] {\n font-size: 12px;\n }\n .msr\\:whitespace-nowrap {\n white-space: nowrap;\n }\n .msr\\:text-\\[\\#64748b\\] {\n color: #64748b;\n }\n .msr\\:text-black {\n color: var(--msr-color-black);\n }\n .msr\\:text-ink-50 {\n color: var(--msr-color-ink-50);\n }\n .msr\\:text-ink-700 {\n color: var(--msr-color-ink-700);\n }\n .msr\\:text-white {\n color: var(--msr-color-white);\n }\n .msr\\:text-white\\/60 {\n color: var(--msr-color-white);\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, var(--msr-color-white) 60%, transparent);\n }\n }\n .msr\\:tabular-nums {\n --tw-numeric-spacing: tabular-nums;\n font-variant-numeric: var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,);\n }\n .msr\\:opacity-0 {\n opacity: 0%;\n }\n .msr\\:opacity-100 {\n opacity: 100%;\n }\n .msr\\:outline {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n .msr\\:outline-transparent {\n outline-color: transparent;\n }\n .msr\\:transition-opacity {\n transition-property: opacity;\n transition-timing-function: var(--tw-ease, var(--msr-default-transition-timing-function));\n transition-duration: var(--tw-duration, var(--msr-default-transition-duration));\n }\n .msr\\:transition-none {\n transition-property: none;\n }\n .msr\\:duration-150 {\n --tw-duration: 150ms;\n transition-duration: 150ms;\n }\n .msr\\:outline-none {\n --tw-outline-style: none;\n outline-style: none;\n }\n .msr\\:select-none {\n -webkit-user-select: none;\n user-select: none;\n }\n .msr\\:hover\\:bg-\\[\\#0d99ff\\] {\n &:hover {\n @media (hover: hover) {\n background-color: #0d99ff;\n }\n }\n }\n .msr\\:hover\\:bg-black\\/4 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 4%, transparent);\n }\n }\n }\n }\n .msr\\:hover\\:bg-black\\/10 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n background-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n }\n }\n .msr\\:hover\\:text-white {\n &:hover {\n @media (hover: hover) {\n color: var(--msr-color-white);\n }\n }\n }\n .msr\\:focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n}\n:root, :host {\n --color-ink-50: #f8fafc;\n --color-ink-200: #e2e8f0;\n --color-ink-500: #64748b;\n --color-ink-700: #334155;\n --color-ink-900: #0f172a;\n}\n.mesurer-toolbar-surface {\n box-shadow: 0 0 0.5px rgba(0, 0, 0, 0.18), 0 3px 8px rgba(0, 0, 0, 0.1), 0 1px 3px rgba(0, 0, 0, 0.1);\n}\n.mesurer-menu-surface {\n box-shadow: 0 10px 30px rgba(0, 0, 0, 0.08);\n}\n.mesurer-root {\n --msr-spacing: 4px;\n}\n@property --tw-translate-x {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-y {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-translate-z {\n syntax: "*";\n inherits: false;\n initial-value: 0;\n}\n@property --tw-border-style {\n syntax: "*";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-ordinal {\n syntax: "*";\n inherits: false;\n}\n@property --tw-slashed-zero {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-figure {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-spacing {\n syntax: "*";\n inherits: false;\n}\n@property --tw-numeric-fraction {\n syntax: "*";\n inherits: false;\n}\n@property --tw-outline-style {\n syntax: "*";\n inherits: false;\n initial-value: solid;\n}\n@property --tw-duration {\n syntax: "*";\n inherits: false;\n}\n@layer properties {\n @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) {\n *, ::before, ::after, ::backdrop {\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n --tw-border-style: solid;\n --tw-ordinal: initial;\n --tw-slashed-zero: initial;\n --tw-numeric-figure: initial;\n --tw-numeric-spacing: initial;\n --tw-numeric-fraction: initial;\n --tw-outline-style: solid;\n --tw-duration: initial;\n }\n }\n}\n';
|
|
75
|
+
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-red-50: oklch(97.1% 0.013 17.38);\n --msr-color-red-200: oklch(88.5% 0.062 18.334);\n --msr-color-red-600: oklch(57.7% 0.245 27.325);\n --msr-color-black: #000;\n --msr-color-white: #fff;\n --msr-spacing: 0.25rem;\n --msr-font-weight-normal: 400;\n --msr-font-weight-medium: 500;\n --msr-font-weight-semibold: 600;\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: #f8fafc;\n --msr-color-ink-200: #e2e8f0;\n --msr-color-ink-500: #64748b;\n --msr-color-ink-700: #334155;\n --msr-color-ink-900: #0f172a;\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-1 {\n right: calc(var(--msr-spacing) * -1);\n }\n .msr\\:right-0 {\n right: calc(var(--msr-spacing) * 0);\n }\n .msr\\:right-\\[8px\\] {\n right: 8px;\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-\\[8px\\] {\n left: 8px;\n }\n .msr\\:left-\\[18px\\] {\n left: 18px;\n }\n .msr\\:z-10 {\n z-index: 10;\n }\n .msr\\:z-50 {\n z-index: 50;\n }\n .msr\\:z-\\[70\\] {\n z-index: 70;\n }\n .msr\\:z-\\[80\\] {\n z-index: 80;\n }\n .msr\\:z-\\[90\\] {\n z-index: 90;\n }\n .msr\\:col-span-2 {\n grid-column: span 2 / span 2;\n }\n .msr\\:mt-2 {\n margin-top: calc(var(--msr-spacing) * 2);\n }\n .msr\\:mb-1 {\n margin-bottom: calc(var(--msr-spacing) * 1);\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\\:ml-1 {\n margin-left: calc(var(--msr-spacing) * 1);\n }\n .msr\\:box-border {\n box-sizing: border-box;\n }\n .msr\\:block {\n display: block;\n }\n .msr\\:flex {\n display: flex;\n }\n .msr\\:grid {\n display: grid;\n }\n .msr\\:inline-flex {\n display: inline-flex;\n }\n .msr\\:size-3 {\n width: calc(var(--msr-spacing) * 3);\n height: calc(var(--msr-spacing) * 3);\n }\n .msr\\:size-4 {\n width: calc(var(--msr-spacing) * 4);\n height: calc(var(--msr-spacing) * 4);\n }\n .msr\\:size-8 {\n width: calc(var(--msr-spacing) * 8);\n height: calc(var(--msr-spacing) * 8);\n }\n .msr\\:size-\\[10px\\] {\n width: 10px;\n height: 10px;\n }\n .msr\\:size-\\[18px\\] {\n width: 18px;\n height: 18px;\n }\n .msr\\:size-full {\n width: 100%;\n height: 100%;\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-\\[14px\\] {\n height: 14px;\n }\n .msr\\:h-full {\n height: 100%;\n }\n .msr\\:h-px {\n height: 1px;\n }\n .msr\\:max-h-\\[min\\(70vh\\,34rem\\)\\] {\n max-height: min(70vh, 34rem);\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-9 {\n width: calc(var(--msr-spacing) * 9);\n }\n .msr\\:w-12 {\n width: calc(var(--msr-spacing) * 12);\n }\n .msr\\:w-44 {\n width: calc(var(--msr-spacing) * 44);\n }\n .msr\\:w-\\[18px\\] {\n width: 18px;\n }\n .msr\\:w-\\[26px\\] {\n width: 26px;\n }\n .msr\\:w-\\[272px\\] {\n width: 272px;\n }\n .msr\\:w-full {\n width: 100%;\n }\n .msr\\:w-px {\n width: 1px;\n }\n .msr\\:max-w-\\[calc\\(100vw-16px\\)\\] {\n max-width: calc(100vw - 16px);\n }\n .msr\\:min-w-0 {\n min-width: calc(var(--msr-spacing) * 0);\n }\n .msr\\:min-w-36 {\n min-width: calc(var(--msr-spacing) * 36);\n }\n .msr\\:flex-1 {\n flex: 1;\n }\n .msr\\:shrink-0 {\n flex-shrink: 0;\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\\:cursor-pointer {\n cursor: pointer;\n }\n .msr\\:touch-none {\n touch-action: none;\n }\n .msr\\:appearance-none {\n appearance: none;\n }\n .msr\\:grid-cols-\\[78px_156px\\] {\n grid-template-columns: 78px 156px;\n }\n .msr\\:flex-col {\n flex-direction: column;\n }\n .msr\\:items-center {\n align-items: center;\n }\n .msr\\:items-start {\n align-items: flex-start;\n }\n .msr\\:items-stretch {\n align-items: stretch;\n }\n .msr\\:justify-between {\n justify-content: space-between;\n }\n .msr\\:justify-center {\n justify-content: center;\n }\n .msr\\:justify-end {\n justify-content: flex-end;\n }\n .msr\\:gap-0 {\n gap: calc(var(--msr-spacing) * 0);\n }\n .msr\\:gap-1 {\n gap: calc(var(--msr-spacing) * 1);\n }\n .msr\\:gap-1\\.5 {\n gap: calc(var(--msr-spacing) * 1.5);\n }\n .msr\\:gap-2 {\n gap: calc(var(--msr-spacing) * 2);\n }\n .msr\\:gap-3 {\n gap: calc(var(--msr-spacing) * 3);\n }\n .msr\\:gap-px {\n gap: 1px;\n }\n .msr\\:gap-x-3 {\n column-gap: calc(var(--msr-spacing) * 3);\n }\n .msr\\:gap-y-1 {\n row-gap: calc(var(--msr-spacing) * 1);\n }\n .msr\\:justify-self-end {\n justify-self: flex-end;\n }\n .msr\\:overflow-hidden {\n overflow: hidden;\n }\n .msr\\:overflow-y-auto {\n overflow-y: auto;\n }\n .msr\\:rounded {\n border-radius: 0.25rem;\n }\n .msr\\:rounded-\\[3px\\] {\n border-radius: 3px;\n }\n .msr\\:rounded-\\[5px\\] {\n border-radius: 5px;\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-full {\n border-radius: calc(infinity * 1px);\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-0 {\n border-style: var(--tw-border-style);\n border-width: 0px;\n }\n .msr\\:border-t {\n border-top-style: var(--tw-border-style);\n border-top-width: 1px;\n }\n .msr\\:border-t-2 {\n border-top-style: var(--tw-border-style);\n border-top-width: 2px;\n }\n .msr\\:border-b {\n border-bottom-style: var(--tw-border-style);\n border-bottom-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-dotted {\n --tw-border-style: dotted;\n border-style: dotted;\n }\n .msr\\:border-solid {\n --tw-border-style: solid;\n border-style: solid;\n }\n .msr\\:border-\\[\\#0d99ff\\] {\n border-color: #0d99ff;\n }\n .msr\\:border-\\[\\#2563eb\\]\\/70 {\n border-color: color-mix(in oklab, #2563eb 70%, transparent);\n }\n .msr\\:border-black\\/8 {\n border-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--msr-color-black) 8%, transparent);\n }\n }\n .msr\\:border-black\\/10 {\n border-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--msr-color-black) 10%, transparent);\n }\n }\n .msr\\:border-black\\/15 {\n border-color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n border-color: color-mix(in oklab, var(--msr-color-black) 15%, transparent);\n }\n }\n .msr\\:border-ink-200 {\n border-color: var(--msr-color-ink-200);\n }\n .msr\\:border-ink-700 {\n border-color: var(--msr-color-ink-700);\n }\n .msr\\:border-red-200 {\n border-color: var(--msr-color-red-200);\n }\n .msr\\:border-transparent {\n border-color: transparent;\n }\n .msr\\:bg-\\[\\#0d99ff\\] {\n background-color: #0d99ff;\n }\n .msr\\:bg-\\[\\#0d99ff\\]\\/10 {\n background-color: color-mix(in oklab, #0d99ff 10%, transparent);\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-50 {\n background-color: var(--msr-color-ink-50);\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\\:p-3 {\n padding: calc(var(--msr-spacing) * 3);\n }\n .msr\\:p-px {\n padding: 1px;\n }\n .msr\\:px-1 {\n padding-inline: calc(var(--msr-spacing) * 1);\n }\n .msr\\:px-1\\.5 {\n padding-inline: calc(var(--msr-spacing) * 1.5);\n }\n .msr\\:px-2 {\n padding-inline: calc(var(--msr-spacing) * 2);\n }\n .msr\\:py-0 {\n padding-block: calc(var(--msr-spacing) * 0);\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\\:py-2 {\n padding-block: calc(var(--msr-spacing) * 2);\n }\n .msr\\:pb-1 {\n padding-bottom: calc(var(--msr-spacing) * 1);\n }\n .msr\\:text-center {\n text-align: center;\n }\n .msr\\:text-left {\n text-align: left;\n }\n .msr\\:font-mono {\n font-family: var(--msr-font-mono);\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\\:leading-4 {\n --tw-leading: calc(var(--msr-spacing) * 4);\n line-height: calc(var(--msr-spacing) * 4);\n }\n .msr\\:leading-none {\n --tw-leading: 1;\n line-height: 1;\n }\n .msr\\:font-medium {\n --tw-font-weight: var(--msr-font-weight-medium);\n font-weight: var(--msr-font-weight-medium);\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-black\\/45 {\n color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, var(--msr-color-black) 45%, transparent);\n }\n }\n .msr\\:text-black\\/60 {\n color: var(--msr-color-black);\n @supports (color: color-mix(in lab, red, red)) {\n color: color-mix(in oklab, var(--msr-color-black) 60%, transparent);\n }\n }\n .msr\\:text-ink-50 {\n color: var(--msr-color-ink-50);\n }\n .msr\\:text-ink-500 {\n color: var(--msr-color-ink-500);\n }\n .msr\\:text-ink-700 {\n color: var(--msr-color-ink-700);\n }\n .msr\\:text-ink-900 {\n color: var(--msr-color-ink-900);\n }\n .msr\\:text-red-600 {\n color: var(--msr-color-red-600);\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\\:shadow-\\[0_0_0_1px_rgba\\(15\\,23\\,42\\,0\\.12\\)\\] {\n --tw-shadow: 0 0 0 1px var(--tw-shadow-color, rgba(15,23,42,0.12));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .msr\\:shadow-lg {\n --tw-shadow: 0 10px 15px -3px var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 4px 6px -4px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n .msr\\:shadow-sm {\n --tw-shadow: 0 1px 3px 0 var(--tw-shadow-color, rgb(0 0 0 / 0.1)), 0 1px 2px -1px var(--tw-shadow-color, rgb(0 0 0 / 0.1));\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\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-colors {\n transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;\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-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-shadow {\n transition-property: box-shadow;\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-transform {\n transition-property: transform, translate, scale, rotate;\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\\:group-hover\\:border-ink-200 {\n &:is(:where(.msr\\:group):hover *) {\n @media (hover: hover) {\n border-color: var(--msr-color-ink-200);\n }\n }\n }\n .msr\\:focus-within\\:rounded-l-\\[5px\\] {\n &:focus-within {\n border-top-left-radius: 5px;\n border-bottom-left-radius: 5px;\n }\n }\n .msr\\:focus-within\\:rounded-r-\\[5px\\] {\n &:focus-within {\n border-top-right-radius: 5px;\n border-bottom-right-radius: 5px;\n }\n }\n .msr\\:focus-within\\:outline {\n &:focus-within {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n }\n .msr\\:focus-within\\:outline-1 {\n &:focus-within {\n outline-style: var(--tw-outline-style);\n outline-width: 1px;\n }\n }\n .msr\\:focus-within\\:outline-offset-\\[-1px\\] {\n &:focus-within {\n outline-offset: -1px;\n }\n }\n .msr\\:focus-within\\:outline-\\[\\#0d99ff\\] {\n &:focus-within {\n outline-color: #0d99ff;\n }\n }\n .msr\\:hover\\:border-ink-200 {\n &:hover {\n @media (hover: hover) {\n border-color: var(--msr-color-ink-200);\n }\n }\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\\:bg-ink-50 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-ink-50);\n }\n }\n }\n .msr\\:hover\\:bg-red-50 {\n &:hover {\n @media (hover: hover) {\n background-color: var(--msr-color-red-50);\n }\n }\n }\n .msr\\:hover\\:text-black {\n &:hover {\n @media (hover: hover) {\n color: var(--msr-color-black);\n }\n }\n }\n .msr\\:hover\\:text-ink-700 {\n &:hover {\n @media (hover: hover) {\n color: var(--msr-color-ink-700);\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\\:hover\\:underline {\n &:hover {\n @media (hover: hover) {\n text-decoration-line: underline;\n }\n }\n }\n .msr\\:focus\\:shadow-\\[inset_0_0_0_1px_\\#0d99ff\\] {\n &:focus {\n --tw-shadow: inset 0 0 0 1px var(--tw-shadow-color, #0d99ff);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .msr\\:focus\\:outline-none {\n &:focus {\n --tw-outline-style: none;\n outline-style: none;\n }\n }\n .msr\\:focus-visible\\:shadow-\\[inset_0_0_0_1px_\\#0d99ff\\] {\n &:focus-visible {\n --tw-shadow: inset 0 0 0 1px var(--tw-shadow-color, #0d99ff);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .msr\\:focus-visible\\:shadow-\\[inset_0_0_0_1px_\\#ef4444\\] {\n &:focus-visible {\n --tw-shadow: inset 0 0 0 1px var(--tw-shadow-color, #ef4444);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .msr\\:focus-visible\\:ring-1 {\n &:focus-visible {\n --tw-ring-shadow: var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color, currentcolor);\n box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);\n }\n }\n .msr\\:focus-visible\\:ring-\\[\\#0d99ff\\]\\/25 {\n &:focus-visible {\n --tw-ring-color: color-mix(in oklab, #0d99ff 25%, transparent);\n }\n }\n .msr\\:focus-visible\\:outline-none {\n &:focus-visible {\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:host {\n all: initial;\n display: block;\n color-scheme: light;\n color: #0f172a;\n font-family: ui-sans-serif, system-ui, sans-serif;\n font-size: 16px;\n font-weight: 400;\n line-height: 1.5;\n letter-spacing: normal;\n direction: ltr;\n --msr-spacing: 4px;\n}\n*, *::before, *::after {\n box-sizing: border-box;\n}\n@layer base {\n *, ::before, ::after, ::backdrop {\n --tw-border-style: solid;\n --tw-outline-style: solid;\n --tw-shadow: 0 0 #0000;\n --tw-inset-shadow: 0 0 #0000;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-translate-x: 0;\n --tw-translate-y: 0;\n --tw-translate-z: 0;\n }\n button, input, select, textarea {\n appearance: none;\n background-color: transparent;\n padding: 0;\n font: inherit;\n color: inherit;\n letter-spacing: inherit;\n }\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-color-picker {\n border: 1px solid rgba(0, 0, 0, 0.1);\n box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);\n}\n.mesurer-settings-tabs {\n box-shadow: inset 0 0 0 1px rgba(15, 23, 42, 0.08);\n}\n.mesurer-settings-tab[aria-selected="true"] {\n box-shadow: 0 0 0 1px rgba(15, 23, 42, 0.12);\n}\n.mesurer-switch-track {\n box-sizing: border-box;\n border: 1px solid #e2e8f0;\n}\n.mesurer-switch-track[data-checked="true"] {\n border-color: #0d99ff;\n}\n.mesurer-control-shell {\n border: 1px solid transparent;\n}\n.mesurer-control-shell:hover {\n border-color: #e2e8f0;\n}\n.mesurer-control-focus:focus-within {\n outline: 1px solid #0d99ff;\n outline-offset: -1px;\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-leading {\n syntax: "*";\n inherits: false;\n}\n@property --tw-font-weight {\n syntax: "*";\n inherits: false;\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-shadow {\n syntax: "*";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-shadow-color {\n syntax: "*";\n inherits: false;\n}\n@property --tw-shadow-alpha {\n syntax: "<percentage>";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-inset-shadow {\n syntax: "*";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-shadow-color {\n syntax: "*";\n inherits: false;\n}\n@property --tw-inset-shadow-alpha {\n syntax: "<percentage>";\n inherits: false;\n initial-value: 100%;\n}\n@property --tw-ring-color {\n syntax: "*";\n inherits: false;\n}\n@property --tw-ring-shadow {\n syntax: "*";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-inset-ring-color {\n syntax: "*";\n inherits: false;\n}\n@property --tw-inset-ring-shadow {\n syntax: "*";\n inherits: false;\n initial-value: 0 0 #0000;\n}\n@property --tw-ring-inset {\n syntax: "*";\n inherits: false;\n}\n@property --tw-ring-offset-width {\n syntax: "<length>";\n inherits: false;\n initial-value: 0px;\n}\n@property --tw-ring-offset-color {\n syntax: "*";\n inherits: false;\n initial-value: #fff;\n}\n@property --tw-ring-offset-shadow {\n syntax: "*";\n inherits: false;\n initial-value: 0 0 #0000;\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-leading: initial;\n --tw-font-weight: initial;\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-shadow: 0 0 #0000;\n --tw-shadow-color: initial;\n --tw-shadow-alpha: 100%;\n --tw-inset-shadow: 0 0 #0000;\n --tw-inset-shadow-color: initial;\n --tw-inset-shadow-alpha: 100%;\n --tw-ring-color: initial;\n --tw-ring-shadow: 0 0 #0000;\n --tw-inset-ring-color: initial;\n --tw-inset-ring-shadow: 0 0 #0000;\n --tw-ring-inset: initial;\n --tw-ring-offset-width: 0px;\n --tw-ring-offset-color: #fff;\n --tw-ring-offset-shadow: 0 0 #0000;\n --tw-outline-style: solid;\n --tw-duration: initial;\n }\n }\n}\n';
|
|
57
76
|
|
|
58
77
|
// components/toolbar.tsx
|
|
59
78
|
import {
|
|
60
79
|
forwardRef,
|
|
61
80
|
memo,
|
|
62
|
-
useCallback,
|
|
81
|
+
useCallback as useCallback2,
|
|
82
|
+
useEffect,
|
|
63
83
|
useLayoutEffect,
|
|
64
|
-
useRef,
|
|
65
|
-
useState
|
|
84
|
+
useRef as useRef2,
|
|
85
|
+
useState as useState3
|
|
66
86
|
} from "react";
|
|
67
87
|
|
|
68
88
|
// core/utils.ts
|
|
@@ -70,9 +90,751 @@ var formatValue = (value) => Math.round(value);
|
|
|
70
90
|
var cn = (...inputs) => inputs.filter(Boolean).join(" ");
|
|
71
91
|
var createId = () => typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random()}`;
|
|
72
92
|
|
|
93
|
+
// components/settings-panel.tsx
|
|
94
|
+
import { useState as useState2 } from "react";
|
|
95
|
+
|
|
96
|
+
// package.json
|
|
97
|
+
var package_default = {
|
|
98
|
+
name: "mesurer",
|
|
99
|
+
version: "0.0.11",
|
|
100
|
+
description: "Measure and align elements on any website.",
|
|
101
|
+
license: "MIT",
|
|
102
|
+
author: "Julien Thibeaut",
|
|
103
|
+
type: "module",
|
|
104
|
+
main: "./dist/index.cjs",
|
|
105
|
+
module: "./dist/index.js",
|
|
106
|
+
types: "./dist/index.d.ts",
|
|
107
|
+
exports: {
|
|
108
|
+
".": {
|
|
109
|
+
types: "./dist/index.d.ts",
|
|
110
|
+
import: "./dist/index.js",
|
|
111
|
+
require: "./dist/index.cjs"
|
|
112
|
+
},
|
|
113
|
+
"./styles.css": "./dist/styles.css",
|
|
114
|
+
"./package.json": "./package.json"
|
|
115
|
+
},
|
|
116
|
+
files: [
|
|
117
|
+
"dist",
|
|
118
|
+
"dist/styles.css",
|
|
119
|
+
"CHANGELOG.md",
|
|
120
|
+
"README.md",
|
|
121
|
+
"LICENSE"
|
|
122
|
+
],
|
|
123
|
+
sideEffects: [
|
|
124
|
+
"*.css"
|
|
125
|
+
],
|
|
126
|
+
publishConfig: {
|
|
127
|
+
access: "public"
|
|
128
|
+
},
|
|
129
|
+
homepage: "https://mesurer.dev",
|
|
130
|
+
repository: {
|
|
131
|
+
type: "git",
|
|
132
|
+
url: "https://github.com/ibelick/mesurer.git"
|
|
133
|
+
},
|
|
134
|
+
bugs: {
|
|
135
|
+
url: "https://github.com/ibelick/mesurer/issues"
|
|
136
|
+
},
|
|
137
|
+
scripts: {
|
|
138
|
+
build: "pnpm exec tailwindcss -i styles.css -o styles.generated.css && node scripts/generate-styles.mjs && tsup && pnpm exec tailwindcss -i styles.css -o dist/styles.css",
|
|
139
|
+
dev: "node scripts/dev.mjs",
|
|
140
|
+
typecheck: "tsc --noEmit",
|
|
141
|
+
prepublishOnly: "npm run typecheck && npm run build"
|
|
142
|
+
},
|
|
143
|
+
peerDependencies: {
|
|
144
|
+
react: ">=18.0.0",
|
|
145
|
+
"react-dom": ">=18.0.0"
|
|
146
|
+
},
|
|
147
|
+
devDependencies: {
|
|
148
|
+
"@tailwindcss/cli": "^4.2.2",
|
|
149
|
+
"@types/react": "^19.0.0",
|
|
150
|
+
"@types/react-dom": "^19.0.0",
|
|
151
|
+
react: "^19.0.0",
|
|
152
|
+
"react-dom": "^19.0.0",
|
|
153
|
+
tailwindcss: "^4.2.2",
|
|
154
|
+
tsup: "^8.5.0",
|
|
155
|
+
typescript: "^5.9.2"
|
|
156
|
+
},
|
|
157
|
+
keywords: [
|
|
158
|
+
"measurement",
|
|
159
|
+
"alignment"
|
|
160
|
+
]
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// core/colors.ts
|
|
164
|
+
var clamp = (value, min = 0, max = 1) => Math.min(max, Math.max(min, value));
|
|
165
|
+
var round = (value, digits = 2) => {
|
|
166
|
+
const factor = 10 ** digits;
|
|
167
|
+
return Math.round(value * factor) / factor;
|
|
168
|
+
};
|
|
169
|
+
var parseChannel = (value) => {
|
|
170
|
+
const trimmed = value.trim();
|
|
171
|
+
const numeric = trimmed.endsWith("%") ? trimmed.slice(0, -1).trim() : trimmed;
|
|
172
|
+
if (!/^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i.test(numeric)) return null;
|
|
173
|
+
const parsed = Number.parseFloat(numeric);
|
|
174
|
+
if (!Number.isFinite(parsed)) return null;
|
|
175
|
+
if (trimmed.endsWith("%")) return clamp(parsed / 100) * 255;
|
|
176
|
+
return clamp(parsed / 255) * 255;
|
|
177
|
+
};
|
|
178
|
+
var parseAlpha = (value) => {
|
|
179
|
+
if (!value) return 1;
|
|
180
|
+
const trimmed = value.trim();
|
|
181
|
+
const numeric = trimmed.endsWith("%") ? trimmed.slice(0, -1).trim() : trimmed;
|
|
182
|
+
if (!/^[+-]?(?:\d+\.?\d*|\.\d+)(?:e[+-]?\d+)?$/i.test(numeric)) return null;
|
|
183
|
+
const parsed = Number.parseFloat(numeric);
|
|
184
|
+
if (!Number.isFinite(parsed)) return null;
|
|
185
|
+
return clamp(trimmed.endsWith("%") ? parsed / 100 : parsed);
|
|
186
|
+
};
|
|
187
|
+
var parseCssColor = (value) => {
|
|
188
|
+
const input = value.trim().toLowerCase();
|
|
189
|
+
if (!input || input === "transparent") return null;
|
|
190
|
+
if (input.startsWith("#")) {
|
|
191
|
+
const hex = input.slice(1);
|
|
192
|
+
const expanded = hex.length === 3 || hex.length === 4 ? hex.split("").map((digit) => digit + digit).join("") : hex;
|
|
193
|
+
if (![6, 8].includes(expanded.length) || !/^[\da-f]+$/.test(expanded)) return null;
|
|
194
|
+
return {
|
|
195
|
+
red: Number.parseInt(expanded.slice(0, 2), 16),
|
|
196
|
+
green: Number.parseInt(expanded.slice(2, 4), 16),
|
|
197
|
+
blue: Number.parseInt(expanded.slice(4, 6), 16),
|
|
198
|
+
alpha: expanded.length === 8 ? Number.parseInt(expanded.slice(6, 8), 16) / 255 : 1
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
const match = input.match(/^rgba?\((.*)\)$/);
|
|
202
|
+
if (!match) return null;
|
|
203
|
+
const channels = match[1].replace(/\//g, " ").split(/[ ,]+/).filter(Boolean);
|
|
204
|
+
if (channels.length < 3 || channels.length > 4) return null;
|
|
205
|
+
const red = parseChannel(channels[0]);
|
|
206
|
+
const green = parseChannel(channels[1]);
|
|
207
|
+
const blue = parseChannel(channels[2]);
|
|
208
|
+
const alpha = parseAlpha(channels[3]);
|
|
209
|
+
if (red === null || green === null || blue === null || alpha === null) return null;
|
|
210
|
+
return { red, green, blue, alpha };
|
|
211
|
+
};
|
|
212
|
+
var toByte = (value) => Math.round(clamp(value / 255) * 255);
|
|
213
|
+
var colorToHex = (color) => {
|
|
214
|
+
const hex = [color.red, color.green, color.blue].map((channel) => toByte(channel).toString(16).padStart(2, "0")).join("");
|
|
215
|
+
if (color.alpha >= 0.999) return `#${hex}`;
|
|
216
|
+
return `#${hex}${Math.round(color.alpha * 255).toString(16).padStart(2, "0")}`;
|
|
217
|
+
};
|
|
218
|
+
var colorToRgb = (color) => {
|
|
219
|
+
const channels = `${toByte(color.red)}, ${toByte(color.green)}, ${toByte(color.blue)}`;
|
|
220
|
+
return color.alpha >= 0.999 ? `rgb(${channels})` : `rgba(${channels}, ${round(color.alpha, 3)})`;
|
|
221
|
+
};
|
|
222
|
+
var colorToHsl = (color) => {
|
|
223
|
+
const red = color.red / 255;
|
|
224
|
+
const green = color.green / 255;
|
|
225
|
+
const blue = color.blue / 255;
|
|
226
|
+
const max = Math.max(red, green, blue);
|
|
227
|
+
const min = Math.min(red, green, blue);
|
|
228
|
+
const lightness = (max + min) / 2;
|
|
229
|
+
const delta = max - min;
|
|
230
|
+
let hue = 0;
|
|
231
|
+
let saturation = 0;
|
|
232
|
+
if (delta !== 0) {
|
|
233
|
+
saturation = delta / (1 - Math.abs(2 * lightness - 1));
|
|
234
|
+
if (max === red) hue = (green - blue) / delta % 6;
|
|
235
|
+
else if (max === green) hue = (blue - red) / delta + 2;
|
|
236
|
+
else hue = (red - green) / delta + 4;
|
|
237
|
+
hue *= 60;
|
|
238
|
+
if (hue < 0) hue += 360;
|
|
239
|
+
}
|
|
240
|
+
const result = `hsl(${round(hue, 1)} ${round(saturation * 100, 1)}% ${round(lightness * 100, 1)}%`;
|
|
241
|
+
return color.alpha >= 0.999 ? `${result})` : `${result} / ${round(color.alpha, 3)})`;
|
|
242
|
+
};
|
|
243
|
+
var linearize = (value) => {
|
|
244
|
+
const normalized = value / 255;
|
|
245
|
+
return normalized <= 0.04045 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;
|
|
246
|
+
};
|
|
247
|
+
var colorToOklch = (color) => {
|
|
248
|
+
const red = linearize(color.red);
|
|
249
|
+
const green = linearize(color.green);
|
|
250
|
+
const blue = linearize(color.blue);
|
|
251
|
+
const l = 0.4122214708 * red + 0.5363325363 * green + 0.0514459929 * blue;
|
|
252
|
+
const m = 0.2119034982 * red + 0.6806995451 * green + 0.1073969566 * blue;
|
|
253
|
+
const s = 0.0883024619 * red + 0.2817188376 * green + 0.6299787005 * blue;
|
|
254
|
+
const lRoot = Math.cbrt(l);
|
|
255
|
+
const mRoot = Math.cbrt(m);
|
|
256
|
+
const sRoot = Math.cbrt(s);
|
|
257
|
+
const lightness = 0.2104542553 * lRoot + 0.793617785 * mRoot - 0.0040720468 * sRoot;
|
|
258
|
+
const a = 1.9779984951 * lRoot - 2.428592205 * mRoot + 0.4505937099 * sRoot;
|
|
259
|
+
const b = 0.0259040371 * lRoot + 0.7827717662 * mRoot - 0.808675766 * sRoot;
|
|
260
|
+
const chroma = Math.sqrt(a * a + b * b);
|
|
261
|
+
let hue = Math.atan2(b, a) * 180 / Math.PI;
|
|
262
|
+
if (hue < 0) hue += 360;
|
|
263
|
+
const result = `oklch(${round(lightness, 3)} ${round(chroma, 3)} ${round(hue, 1)}`;
|
|
264
|
+
return color.alpha >= 0.999 ? `${result})` : `${result} / ${round(color.alpha, 3)})`;
|
|
265
|
+
};
|
|
266
|
+
var formatColor = (color, format) => {
|
|
267
|
+
if (format === "hex") return colorToHex(color);
|
|
268
|
+
if (format === "rgb") return colorToRgb(color);
|
|
269
|
+
if (format === "hsl") return colorToHsl(color);
|
|
270
|
+
return colorToOklch(color);
|
|
271
|
+
};
|
|
272
|
+
|
|
273
|
+
// components/tooltip.tsx
|
|
274
|
+
import { useCallback, useRef, useState } from "react";
|
|
275
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
276
|
+
var TOOLTIP_DELAY_MS = 800;
|
|
277
|
+
function Tooltip({
|
|
278
|
+
label,
|
|
279
|
+
shortcut,
|
|
280
|
+
visible,
|
|
281
|
+
instant = false,
|
|
282
|
+
side = "top",
|
|
283
|
+
className
|
|
284
|
+
}) {
|
|
285
|
+
return /* @__PURE__ */ jsxs(
|
|
286
|
+
"span",
|
|
287
|
+
{
|
|
288
|
+
role: "tooltip",
|
|
289
|
+
className: cn(
|
|
290
|
+
"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",
|
|
291
|
+
instant && "msr:transition-none",
|
|
292
|
+
side === "top" ? "msr:bottom-full msr:mb-2" : "msr:top-full msr:mt-2",
|
|
293
|
+
visible === void 0 ? null : visible ? "msr:opacity-100" : "msr:opacity-0",
|
|
294
|
+
className
|
|
295
|
+
),
|
|
296
|
+
children: [
|
|
297
|
+
label,
|
|
298
|
+
shortcut ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
299
|
+
" ",
|
|
300
|
+
/* @__PURE__ */ jsx("kbd", { className: "msr:text-white/60", children: shortcut })
|
|
301
|
+
] }) : null
|
|
302
|
+
]
|
|
303
|
+
}
|
|
304
|
+
);
|
|
305
|
+
}
|
|
306
|
+
function useTooltip() {
|
|
307
|
+
const [visibleTooltipId, setVisibleTooltipId] = useState(null);
|
|
308
|
+
const timerRef = useRef(null);
|
|
309
|
+
const instantRef = useRef(false);
|
|
310
|
+
const [tooltipInstant, setTooltipInstant] = useState(false);
|
|
311
|
+
const clearTimer = useCallback(() => {
|
|
312
|
+
if (timerRef.current === null) return;
|
|
313
|
+
window.clearTimeout(timerRef.current);
|
|
314
|
+
timerRef.current = null;
|
|
315
|
+
}, []);
|
|
316
|
+
const onTooltipEnter = useCallback((id) => {
|
|
317
|
+
clearTimer();
|
|
318
|
+
if (instantRef.current) {
|
|
319
|
+
setTooltipInstant(true);
|
|
320
|
+
setVisibleTooltipId(id);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
setTooltipInstant(false);
|
|
324
|
+
timerRef.current = window.setTimeout(() => {
|
|
325
|
+
setVisibleTooltipId(id);
|
|
326
|
+
instantRef.current = true;
|
|
327
|
+
timerRef.current = null;
|
|
328
|
+
}, TOOLTIP_DELAY_MS);
|
|
329
|
+
}, [clearTimer]);
|
|
330
|
+
const onTooltipLeave = useCallback(() => {
|
|
331
|
+
clearTimer();
|
|
332
|
+
setVisibleTooltipId(null);
|
|
333
|
+
}, [clearTimer]);
|
|
334
|
+
const onTooltipContainerLeave = useCallback(() => {
|
|
335
|
+
clearTimer();
|
|
336
|
+
setVisibleTooltipId(null);
|
|
337
|
+
instantRef.current = false;
|
|
338
|
+
setTooltipInstant(false);
|
|
339
|
+
}, [clearTimer]);
|
|
340
|
+
return {
|
|
341
|
+
visibleTooltipId,
|
|
342
|
+
tooltipInstant,
|
|
343
|
+
onTooltipEnter,
|
|
344
|
+
onTooltipLeave,
|
|
345
|
+
onTooltipContainerLeave
|
|
346
|
+
};
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// components/settings-panel.tsx
|
|
350
|
+
import { Fragment as Fragment2, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
351
|
+
var COLOR_FORMATS = ["hex", "rgb", "hsl", "oklch"];
|
|
352
|
+
var GUIDE_PATTERNS = [
|
|
353
|
+
{ value: "solid", label: "Solid" },
|
|
354
|
+
{ value: "dashed", label: "Dashed" },
|
|
355
|
+
{ value: "dotted", label: "Dotted" }
|
|
356
|
+
];
|
|
357
|
+
function ControlShell({ left, right }) {
|
|
358
|
+
return /* @__PURE__ */ jsxs2(
|
|
359
|
+
"div",
|
|
360
|
+
{
|
|
361
|
+
className: "mesurer-control-shell msr:group msr:flex msr:h-6 msr:w-full msr:min-w-0 msr:items-center msr:overflow-hidden msr:rounded-[5px] msr:border msr:border-transparent msr:bg-ink-50 msr:hover:border-ink-200",
|
|
362
|
+
children: [
|
|
363
|
+
/* @__PURE__ */ jsx2("div", { className: "mesurer-control-focus msr:flex msr:h-full msr:min-w-0 msr:flex-1 msr:items-center msr:focus-within:rounded-l-[5px] msr:focus-within:outline msr:focus-within:outline-1 msr:focus-within:outline-[#0d99ff] msr:focus-within:outline-offset-[-1px]", children: left }),
|
|
364
|
+
/* @__PURE__ */ jsx2("div", { className: "mesurer-control-focus msr:box-border msr:flex msr:h-full msr:w-12 msr:shrink-0 msr:items-center msr:border-l msr:border-transparent msr:group-hover:border-ink-200 msr:focus-within:rounded-r-[5px] msr:focus-within:outline msr:focus-within:outline-1 msr:focus-within:outline-[#0d99ff] msr:focus-within:outline-offset-[-1px]", children: right })
|
|
365
|
+
]
|
|
366
|
+
}
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
function SettingsSwitch({ label, checked, onChange }) {
|
|
370
|
+
return /* @__PURE__ */ jsxs2(
|
|
371
|
+
"button",
|
|
372
|
+
{
|
|
373
|
+
type: "button",
|
|
374
|
+
role: "switch",
|
|
375
|
+
"aria-checked": checked,
|
|
376
|
+
className: "msr:col-span-2 msr:grid msr:h-6 msr:w-full msr:appearance-none msr:grid-cols-[78px_156px] msr:items-center msr:gap-3 msr:text-left msr:text-[12px] msr:leading-none msr:text-ink-700",
|
|
377
|
+
onClick: () => onChange(!checked),
|
|
378
|
+
children: [
|
|
379
|
+
/* @__PURE__ */ jsx2("span", { children: label }),
|
|
380
|
+
/* @__PURE__ */ jsx2(
|
|
381
|
+
"span",
|
|
382
|
+
{
|
|
383
|
+
"aria-hidden": "true",
|
|
384
|
+
style: { justifySelf: "end" },
|
|
385
|
+
"data-checked": checked ? "true" : void 0,
|
|
386
|
+
className: cn(
|
|
387
|
+
"mesurer-switch-track msr:flex msr:h-[14px] msr:w-[26px] msr:shrink-0 msr:items-center msr:rounded-full msr:border msr:p-px msr:transition-colors",
|
|
388
|
+
checked ? "msr:border-[#0d99ff] msr:bg-[#0d99ff]" : "msr:border-ink-200 msr:bg-ink-50"
|
|
389
|
+
),
|
|
390
|
+
children: /* @__PURE__ */ jsx2(
|
|
391
|
+
"span",
|
|
392
|
+
{
|
|
393
|
+
className: "msr:block msr:size-[10px] msr:shrink-0 msr:rounded-full msr:bg-white msr:shadow-sm msr:transition-transform",
|
|
394
|
+
style: { transform: `translateX(${checked ? 12 : 0}px)` }
|
|
395
|
+
}
|
|
396
|
+
)
|
|
397
|
+
}
|
|
398
|
+
)
|
|
399
|
+
]
|
|
400
|
+
}
|
|
401
|
+
);
|
|
402
|
+
}
|
|
403
|
+
function SliderControl({
|
|
404
|
+
label,
|
|
405
|
+
min,
|
|
406
|
+
max,
|
|
407
|
+
step,
|
|
408
|
+
value,
|
|
409
|
+
onChange,
|
|
410
|
+
formatValue: formatValue4 = (currentValue) => String(currentValue),
|
|
411
|
+
parseInput = (input) => Number(input)
|
|
412
|
+
}) {
|
|
413
|
+
const thumbSize = 12;
|
|
414
|
+
const thumbInset = 8;
|
|
415
|
+
const percentage = (value - min) / (max - min) * 100;
|
|
416
|
+
const [draftValue, setDraftValue] = useState2(formatValue4(value));
|
|
417
|
+
const [editing, setEditing] = useState2(false);
|
|
418
|
+
const commitDraft = () => {
|
|
419
|
+
const parsed = parseInput(draftValue);
|
|
420
|
+
if (Number.isFinite(parsed)) {
|
|
421
|
+
onChange(Math.min(max, Math.max(min, parsed)));
|
|
422
|
+
}
|
|
423
|
+
const next = Number.isFinite(parsed) ? Math.min(max, Math.max(min, parsed)) : value;
|
|
424
|
+
setDraftValue(formatValue4(next));
|
|
425
|
+
setEditing(false);
|
|
426
|
+
};
|
|
427
|
+
const updateFromPointer = (event) => {
|
|
428
|
+
event.stopPropagation();
|
|
429
|
+
const rect = event.currentTarget.getBoundingClientRect();
|
|
430
|
+
const usableWidth = Math.max(1, rect.width - thumbInset * 2);
|
|
431
|
+
const ratio = Math.min(1, Math.max(0, (event.clientX - rect.left - thumbInset) / usableWidth));
|
|
432
|
+
const rawValue = min + ratio * (max - min);
|
|
433
|
+
const steppedValue = Math.round((rawValue - min) / step) * step + min;
|
|
434
|
+
onChange(Number(steppedValue.toFixed(4)));
|
|
435
|
+
};
|
|
436
|
+
return /* @__PURE__ */ jsxs2("div", { className: "msr:col-span-2 msr:grid msr:w-full msr:grid-cols-[78px_156px] msr:items-center msr:gap-3", children: [
|
|
437
|
+
/* @__PURE__ */ jsx2("span", { className: "msr:text-[11px] msr:font-medium msr:text-ink-700", children: label }),
|
|
438
|
+
/* @__PURE__ */ jsx2(
|
|
439
|
+
ControlShell,
|
|
440
|
+
{
|
|
441
|
+
left: /* @__PURE__ */ jsxs2(
|
|
442
|
+
"div",
|
|
443
|
+
{
|
|
444
|
+
className: "msr:relative msr:min-w-0 msr:flex-1 msr:touch-none msr:select-none msr:px-2",
|
|
445
|
+
style: { height: 20 },
|
|
446
|
+
"data-slider-container": "true",
|
|
447
|
+
onPointerDown: (event) => {
|
|
448
|
+
event.stopPropagation();
|
|
449
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
450
|
+
updateFromPointer(event);
|
|
451
|
+
},
|
|
452
|
+
onPointerMove: (event) => {
|
|
453
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) updateFromPointer(event);
|
|
454
|
+
},
|
|
455
|
+
onPointerUp: (event) => {
|
|
456
|
+
event.stopPropagation();
|
|
457
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
458
|
+
},
|
|
459
|
+
onPointerCancel: (event) => {
|
|
460
|
+
event.stopPropagation();
|
|
461
|
+
if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);
|
|
462
|
+
},
|
|
463
|
+
onClick: (event) => event.stopPropagation(),
|
|
464
|
+
children: [
|
|
465
|
+
/* @__PURE__ */ jsx2(
|
|
466
|
+
"div",
|
|
467
|
+
{
|
|
468
|
+
className: "msr:absolute msr:left-[8px] msr:right-[8px] msr:rounded-full",
|
|
469
|
+
style: { top: 8, height: 4, backgroundColor: "rgba(15, 23, 42, 0.16)" },
|
|
470
|
+
"aria-hidden": "true"
|
|
471
|
+
}
|
|
472
|
+
),
|
|
473
|
+
/* @__PURE__ */ jsx2(
|
|
474
|
+
"div",
|
|
475
|
+
{
|
|
476
|
+
className: "msr:absolute msr:left-[8px] msr:rounded-full",
|
|
477
|
+
style: { top: 8, width: `calc(${percentage}% - ${percentage * thumbInset * 2 / 100}px)`, height: 4, backgroundColor: "#0d99ff" },
|
|
478
|
+
"aria-hidden": "true"
|
|
479
|
+
}
|
|
480
|
+
),
|
|
481
|
+
/* @__PURE__ */ jsx2(
|
|
482
|
+
"div",
|
|
483
|
+
{
|
|
484
|
+
className: "msr:absolute msr:rounded-[5px] msr:bg-white msr:shadow-sm msr:transition-shadow msr:outline-none msr:focus-visible:ring-1 msr:focus-visible:ring-[#0d99ff]/25",
|
|
485
|
+
style: {
|
|
486
|
+
left: `calc(8px + (100% - 16px) * ${percentage / 100})`,
|
|
487
|
+
top: 4,
|
|
488
|
+
width: thumbSize,
|
|
489
|
+
height: thumbSize,
|
|
490
|
+
border: "0",
|
|
491
|
+
transform: "translateX(-50%)"
|
|
492
|
+
},
|
|
493
|
+
role: "slider",
|
|
494
|
+
tabIndex: 0,
|
|
495
|
+
"aria-label": label,
|
|
496
|
+
"aria-valuemin": min,
|
|
497
|
+
"aria-valuemax": max,
|
|
498
|
+
"aria-valuenow": value,
|
|
499
|
+
"aria-orientation": "horizontal",
|
|
500
|
+
onKeyDown: (event) => {
|
|
501
|
+
event.stopPropagation();
|
|
502
|
+
const direction = event.key === "ArrowRight" || event.key === "ArrowUp" ? 1 : event.key === "ArrowLeft" || event.key === "ArrowDown" ? -1 : 0;
|
|
503
|
+
if (event.key === "Home") onChange(min);
|
|
504
|
+
else if (event.key === "End") onChange(max);
|
|
505
|
+
else if (direction) {
|
|
506
|
+
event.preventDefault();
|
|
507
|
+
onChange(Number(Math.min(max, Math.max(min, value + direction * step)).toFixed(4)));
|
|
508
|
+
} else return;
|
|
509
|
+
event.preventDefault();
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
]
|
|
514
|
+
}
|
|
515
|
+
),
|
|
516
|
+
right: /* @__PURE__ */ jsx2(
|
|
517
|
+
"input",
|
|
518
|
+
{
|
|
519
|
+
type: "text",
|
|
520
|
+
"aria-label": `${label} value`,
|
|
521
|
+
className: "msr:h-full msr:w-full msr:shrink-0 msr:border-0 msr:bg-transparent msr:px-2 msr:text-center msr:font-mono msr:text-[12px] msr:font-medium msr:tabular-nums msr:text-ink-700 msr:outline-none",
|
|
522
|
+
style: { boxSizing: "border-box", borderRadius: "0 5px 5px 0", lineHeight: "1rem" },
|
|
523
|
+
value: editing ? draftValue : formatValue4(value),
|
|
524
|
+
onFocus: () => {
|
|
525
|
+
setDraftValue(formatValue4(value));
|
|
526
|
+
setEditing(true);
|
|
527
|
+
},
|
|
528
|
+
onChange: (event) => {
|
|
529
|
+
const nextDraft = event.target.value;
|
|
530
|
+
setDraftValue(nextDraft);
|
|
531
|
+
const next = parseInput(nextDraft);
|
|
532
|
+
if (Number.isFinite(next)) onChange(Math.min(max, Math.max(min, next)));
|
|
533
|
+
},
|
|
534
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
535
|
+
onClick: (event) => event.stopPropagation(),
|
|
536
|
+
onBlur: () => {
|
|
537
|
+
commitDraft();
|
|
538
|
+
},
|
|
539
|
+
onKeyDown: (event) => {
|
|
540
|
+
event.stopPropagation();
|
|
541
|
+
if (event.key === "ArrowUp" || event.key === "ArrowDown") {
|
|
542
|
+
event.preventDefault();
|
|
543
|
+
const current = parseInput(event.currentTarget.value);
|
|
544
|
+
const direction = event.key === "ArrowUp" ? 1 : -1;
|
|
545
|
+
const next = Number(
|
|
546
|
+
Math.min(max, Math.max(min, (Number.isFinite(current) ? current : value) + direction * step)).toFixed(4)
|
|
547
|
+
);
|
|
548
|
+
setDraftValue(formatValue4(next));
|
|
549
|
+
onChange(next);
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
if (event.key === "Enter") {
|
|
553
|
+
event.preventDefault();
|
|
554
|
+
event.currentTarget.blur();
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
)
|
|
559
|
+
}
|
|
560
|
+
)
|
|
561
|
+
] });
|
|
562
|
+
}
|
|
563
|
+
function ColorField({ label, value, fallback, ownerWindow, onChange }) {
|
|
564
|
+
const parsed = parseCssColor(value);
|
|
565
|
+
const canvas = ownerWindow.document.createElement("canvas");
|
|
566
|
+
const context = canvas.getContext("2d");
|
|
567
|
+
if (context) context.fillStyle = value;
|
|
568
|
+
const serialized = typeof context?.fillStyle === "string" ? context.fillStyle : "";
|
|
569
|
+
const converted = serialized ? parseCssColor(serialized) : null;
|
|
570
|
+
const inputValue = parsed ?? converted ? colorToHex(parsed ?? converted).slice(0, 7) : fallback;
|
|
571
|
+
const sample = parsed ?? converted ?? parseCssColor(fallback);
|
|
572
|
+
const hexValue = sample ? colorToHex({ ...sample, alpha: 1 }).slice(1).toUpperCase() : "000000";
|
|
573
|
+
const alphaValue = sample ? Math.round(sample.alpha * 100) : 100;
|
|
574
|
+
const [hexDraft, setHexDraft] = useState2(hexValue);
|
|
575
|
+
const [alphaDraft, setAlphaDraft] = useState2(String(alphaValue));
|
|
576
|
+
const [hexFocused, setHexFocused] = useState2(false);
|
|
577
|
+
const [alphaFocused, setAlphaFocused] = useState2(false);
|
|
578
|
+
const updateColor = (nextHex, nextAlpha) => {
|
|
579
|
+
if (!/^[\da-f]{6}$/i.test(nextHex)) return;
|
|
580
|
+
const nextSample = parseCssColor(`#${nextHex}`);
|
|
581
|
+
if (!nextSample) return;
|
|
582
|
+
onChange(colorToHex({ ...nextSample, alpha: Math.min(100, Math.max(0, nextAlpha)) / 100 }));
|
|
583
|
+
};
|
|
584
|
+
const swatchColor = ownerWindow.CSS?.supports("color", value) ? value : fallback;
|
|
585
|
+
return /* @__PURE__ */ jsxs2("div", { className: "msr:col-span-2 msr:grid msr:w-full msr:grid-cols-[78px_156px] msr:items-center msr:gap-3 msr:text-[12px] msr:text-ink-700", children: [
|
|
586
|
+
/* @__PURE__ */ jsx2("span", { children: label }),
|
|
587
|
+
/* @__PURE__ */ jsx2(
|
|
588
|
+
ControlShell,
|
|
589
|
+
{
|
|
590
|
+
left: /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
591
|
+
/* @__PURE__ */ jsx2(
|
|
592
|
+
"span",
|
|
593
|
+
{
|
|
594
|
+
className: "msr:relative msr:ml-1 msr:block msr:size-4 msr:shrink-0 msr:overflow-hidden msr:rounded-[3px] msr:border msr:border-black/10",
|
|
595
|
+
style: { backgroundColor: swatchColor },
|
|
596
|
+
children: /* @__PURE__ */ jsx2(
|
|
597
|
+
"input",
|
|
598
|
+
{
|
|
599
|
+
type: "color",
|
|
600
|
+
"aria-label": `${label} color picker`,
|
|
601
|
+
value: inputValue,
|
|
602
|
+
className: "msr:absolute msr:inset-0 msr:size-full msr:cursor-pointer msr:opacity-0",
|
|
603
|
+
onChange: (event) => onChange(event.target.value)
|
|
604
|
+
}
|
|
605
|
+
)
|
|
606
|
+
}
|
|
607
|
+
),
|
|
608
|
+
/* @__PURE__ */ jsx2(
|
|
609
|
+
"input",
|
|
610
|
+
{
|
|
611
|
+
"aria-label": `${label} hex value`,
|
|
612
|
+
type: "text",
|
|
613
|
+
value: hexFocused ? hexDraft : hexValue,
|
|
614
|
+
maxLength: 6,
|
|
615
|
+
className: "msr:min-w-0 msr:flex-1 msr:bg-transparent msr:px-2 msr:font-mono msr:text-[12px] msr:tabular-nums msr:text-ink-700 msr:outline-none",
|
|
616
|
+
onFocus: () => {
|
|
617
|
+
setHexDraft(hexValue);
|
|
618
|
+
setHexFocused(true);
|
|
619
|
+
},
|
|
620
|
+
onBlur: () => setHexFocused(false),
|
|
621
|
+
onChange: (event) => {
|
|
622
|
+
const next = event.target.value.replace(/[^\da-f]/gi, "").slice(0, 6).toUpperCase();
|
|
623
|
+
setHexDraft(next);
|
|
624
|
+
updateColor(next, alphaFocused ? Number(alphaDraft) : alphaValue);
|
|
625
|
+
},
|
|
626
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
627
|
+
onClick: (event) => event.stopPropagation()
|
|
628
|
+
}
|
|
629
|
+
)
|
|
630
|
+
] }),
|
|
631
|
+
right: /* @__PURE__ */ jsx2(
|
|
632
|
+
"input",
|
|
633
|
+
{
|
|
634
|
+
"aria-label": `${label} opacity value`,
|
|
635
|
+
type: "text",
|
|
636
|
+
inputMode: "numeric",
|
|
637
|
+
value: alphaFocused ? alphaDraft ? `${alphaDraft}%` : "" : `${alphaValue}%`,
|
|
638
|
+
maxLength: 4,
|
|
639
|
+
className: "msr:h-full msr:w-full msr:bg-transparent msr:px-1 msr:text-center msr:font-mono msr:text-[12px] msr:tabular-nums msr:text-ink-700 msr:outline-none",
|
|
640
|
+
onFocus: () => {
|
|
641
|
+
setAlphaDraft(String(alphaValue));
|
|
642
|
+
setAlphaFocused(true);
|
|
643
|
+
},
|
|
644
|
+
onBlur: () => setAlphaFocused(false),
|
|
645
|
+
onChange: (event) => {
|
|
646
|
+
const next = event.target.value.replace(/\D/g, "").slice(0, 3);
|
|
647
|
+
setAlphaDraft(next);
|
|
648
|
+
updateColor(hexFocused ? hexDraft : hexValue, Number(next));
|
|
649
|
+
},
|
|
650
|
+
onKeyDown: (event) => {
|
|
651
|
+
if (event.key !== "ArrowUp" && event.key !== "ArrowDown") return;
|
|
652
|
+
event.preventDefault();
|
|
653
|
+
event.stopPropagation();
|
|
654
|
+
const current = Number.parseInt(alphaFocused ? alphaDraft : String(alphaValue), 10);
|
|
655
|
+
const direction = event.key === "ArrowUp" ? 1 : -1;
|
|
656
|
+
const next = Math.min(100, Math.max(0, (Number.isFinite(current) ? current : 0) + direction));
|
|
657
|
+
setAlphaDraft(String(next));
|
|
658
|
+
updateColor(hexFocused ? hexDraft : hexValue, next);
|
|
659
|
+
},
|
|
660
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
661
|
+
onClick: (event) => event.stopPropagation()
|
|
662
|
+
}
|
|
663
|
+
)
|
|
664
|
+
}
|
|
665
|
+
)
|
|
666
|
+
] });
|
|
667
|
+
}
|
|
668
|
+
function SettingsPanel({
|
|
669
|
+
ownerWindow,
|
|
670
|
+
highlightColor,
|
|
671
|
+
setHighlightColor,
|
|
672
|
+
guideColor,
|
|
673
|
+
setGuideColor,
|
|
674
|
+
hoverHighlight,
|
|
675
|
+
setHoverHighlight,
|
|
676
|
+
persistOnReload,
|
|
677
|
+
setPersistOnReload,
|
|
678
|
+
colorFormats,
|
|
679
|
+
setColorFormats,
|
|
680
|
+
colorClickFormat,
|
|
681
|
+
setColorClickFormat,
|
|
682
|
+
snapEnabled,
|
|
683
|
+
setSnapEnabled,
|
|
684
|
+
snapGuidesEnabled,
|
|
685
|
+
setSnapGuidesEnabled,
|
|
686
|
+
selectNewGuideEnabled,
|
|
687
|
+
setSelectNewGuideEnabled,
|
|
688
|
+
multiMeasureEnabled,
|
|
689
|
+
setMultiMeasureEnabled,
|
|
690
|
+
guideStyle,
|
|
691
|
+
setGuideStyle,
|
|
692
|
+
rulerSettings,
|
|
693
|
+
setRulerSettings,
|
|
694
|
+
activeTab,
|
|
695
|
+
onTabChange,
|
|
696
|
+
onResetSettings,
|
|
697
|
+
onClearWorkspace
|
|
698
|
+
}) {
|
|
699
|
+
const toggleFormat = (format) => {
|
|
700
|
+
setColorFormats((previous) => {
|
|
701
|
+
if (previous.includes(format)) {
|
|
702
|
+
if (previous.length === 1) return previous;
|
|
703
|
+
return previous.filter((item) => item !== format);
|
|
704
|
+
}
|
|
705
|
+
return [...previous, format];
|
|
706
|
+
});
|
|
707
|
+
};
|
|
708
|
+
const patternTooltip = useTooltip();
|
|
709
|
+
return /* @__PURE__ */ jsxs2("div", { className: "msr:flex msr:max-h-[min(70vh,34rem)] msr:flex-col msr:gap-2 msr:overflow-y-auto", onPointerDown: (event) => event.stopPropagation(), children: [
|
|
710
|
+
/* @__PURE__ */ jsx2("div", { className: "mesurer-settings-tabs msr:flex msr:h-6 msr:shrink-0 msr:select-none msr:items-stretch msr:gap-0 msr:rounded-[5px] msr:bg-ink-50 msr:p-px", role: "tablist", "aria-label": "Settings sections", children: [
|
|
711
|
+
["guides", "Guides"],
|
|
712
|
+
["select", "Select"],
|
|
713
|
+
["color-picker", "Color"],
|
|
714
|
+
["rulers", "Rulers"],
|
|
715
|
+
["general", "General"]
|
|
716
|
+
].map(([value, label]) => /* @__PURE__ */ jsx2(
|
|
717
|
+
"button",
|
|
718
|
+
{
|
|
719
|
+
type: "button",
|
|
720
|
+
role: "tab",
|
|
721
|
+
"aria-selected": activeTab === value,
|
|
722
|
+
className: cn(
|
|
723
|
+
"mesurer-settings-tab msr:relative msr:flex msr:min-w-0 msr:flex-1 msr:appearance-none msr:items-center msr:justify-center msr:whitespace-nowrap msr:px-1.5 msr:py-0 msr:text-[10px] msr:font-medium msr:transition-colors msr:focus-visible:outline-none msr:focus-visible:shadow-[inset_0_0_0_1px_#0d99ff]",
|
|
724
|
+
activeTab === value ? "msr:rounded-[5px] msr:bg-white msr:text-ink-900 msr:shadow-[0_0_0_1px_rgba(15,23,42,0.12)]" : "msr:rounded-[5px] msr:text-ink-500 msr:hover:text-ink-700"
|
|
725
|
+
),
|
|
726
|
+
onClick: () => onTabChange(value),
|
|
727
|
+
children: label
|
|
728
|
+
},
|
|
729
|
+
value
|
|
730
|
+
)) }),
|
|
731
|
+
activeTab === "guides" ? /* @__PURE__ */ jsxs2("section", { className: "msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-x-3 msr:gap-y-1", "aria-label": "Guide settings", children: [
|
|
732
|
+
/* @__PURE__ */ jsx2(ColorField, { label: "Color", value: guideColor, fallback: "#f97316", ownerWindow, onChange: setGuideColor }),
|
|
733
|
+
/* @__PURE__ */ jsx2(SliderControl, { label: "Weight", min: 1, max: 4, step: 1, value: guideStyle.width, formatValue: (value) => `${value}px`, parseInput: (input) => Number.parseFloat(input), onChange: (value) => setGuideStyle((style) => ({ ...style, width: value })) }),
|
|
734
|
+
/* @__PURE__ */ jsxs2("div", { className: "msr:col-span-2 msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-3", children: [
|
|
735
|
+
/* @__PURE__ */ jsx2("span", { className: "msr:text-[12px] msr:text-ink-700", children: "Pattern" }),
|
|
736
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:flex msr:gap-1", role: "radiogroup", "aria-label": "Guide pattern", onMouseLeave: patternTooltip.onTooltipContainerLeave, children: GUIDE_PATTERNS.map(({ value, label }) => {
|
|
737
|
+
const selected = guideStyle.pattern === value;
|
|
738
|
+
const tooltipId = `guide-pattern-${value}`;
|
|
739
|
+
return /* @__PURE__ */ jsxs2(
|
|
740
|
+
"button",
|
|
741
|
+
{
|
|
742
|
+
type: "button",
|
|
743
|
+
role: "radio",
|
|
744
|
+
"aria-label": `${label} guide pattern`,
|
|
745
|
+
"aria-checked": selected,
|
|
746
|
+
className: cn(
|
|
747
|
+
"msr:relative msr:flex msr:h-6 msr:min-w-0 msr:flex-1 msr:items-center msr:justify-center msr:rounded-[5px] msr:border msr:px-1 msr:focus-visible:outline-none msr:focus-visible:shadow-[inset_0_0_0_1px_#0d99ff]",
|
|
748
|
+
selected ? "msr:border-[#0d99ff] msr:bg-[#0d99ff]/10" : "msr:border-ink-200 msr:bg-ink-50 msr:hover:bg-ink-100"
|
|
749
|
+
),
|
|
750
|
+
onClick: () => setGuideStyle((style) => ({ ...style, pattern: value })),
|
|
751
|
+
onMouseEnter: () => patternTooltip.onTooltipEnter(tooltipId),
|
|
752
|
+
onFocus: () => patternTooltip.onTooltipEnter(tooltipId),
|
|
753
|
+
onBlur: patternTooltip.onTooltipLeave,
|
|
754
|
+
children: [
|
|
755
|
+
/* @__PURE__ */ jsx2("span", { "aria-hidden": "true", className: cn("msr:block msr:w-full msr:border-t-2 msr:border-ink-700", value === "dashed" ? "msr:border-dashed" : value === "dotted" ? "msr:border-dotted" : "msr:border-solid") }),
|
|
756
|
+
/* @__PURE__ */ jsx2(Tooltip, { label, visible: patternTooltip.visibleTooltipId === tooltipId, instant: patternTooltip.tooltipInstant, className: "msr:z-10" })
|
|
757
|
+
]
|
|
758
|
+
},
|
|
759
|
+
value
|
|
760
|
+
);
|
|
761
|
+
}) })
|
|
762
|
+
] }),
|
|
763
|
+
guideStyle.pattern !== "solid" ? /* @__PURE__ */ jsxs2(Fragment2, { children: [
|
|
764
|
+
/* @__PURE__ */ jsx2(SliderControl, { label: "Length", min: 2, max: 24, step: 1, value: guideStyle.dashLength, formatValue: (value) => `${value}px`, parseInput: (input) => Number.parseFloat(input), onChange: (value) => setGuideStyle((style) => ({ ...style, dashLength: value })) }),
|
|
765
|
+
/* @__PURE__ */ jsx2(SliderControl, { label: "Gap", min: 0, max: 24, step: 1, value: guideStyle.gap, formatValue: (value) => `${value}px`, parseInput: (input) => Number.parseFloat(input), onChange: (value) => setGuideStyle((style) => ({ ...style, gap: value })) })
|
|
766
|
+
] }) : null,
|
|
767
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Snap", checked: snapGuidesEnabled, onChange: setSnapGuidesEnabled }) }),
|
|
768
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Highlight", checked: selectNewGuideEnabled, onChange: setSelectNewGuideEnabled }) })
|
|
769
|
+
] }) : null,
|
|
770
|
+
activeTab === "select" ? /* @__PURE__ */ jsxs2("section", { className: "msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-x-3 msr:gap-y-1", "aria-label": "Selection settings", children: [
|
|
771
|
+
/* @__PURE__ */ jsx2(ColorField, { label: "Color", value: highlightColor, fallback: "#0d99ff", ownerWindow, onChange: setHighlightColor }),
|
|
772
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Hover", checked: hoverHighlight, onChange: setHoverHighlight }) }),
|
|
773
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Element snap", checked: snapEnabled, onChange: setSnapEnabled }) }),
|
|
774
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Stack", checked: multiMeasureEnabled, onChange: setMultiMeasureEnabled }) })
|
|
775
|
+
] }) : null,
|
|
776
|
+
activeTab === "color-picker" ? /* @__PURE__ */ jsxs2("section", { className: "msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-x-3 msr:gap-y-1", "aria-label": "Color settings", children: [
|
|
777
|
+
/* @__PURE__ */ jsxs2("div", { className: "msr:col-span-2 msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-3", children: [
|
|
778
|
+
/* @__PURE__ */ jsx2("span", { className: "msr:text-[12px] msr:text-ink-700", children: "Format" }),
|
|
779
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:flex msr:min-w-0 msr:gap-1", children: COLOR_FORMATS.map((format) => /* @__PURE__ */ jsx2(
|
|
780
|
+
"button",
|
|
781
|
+
{
|
|
782
|
+
type: "button",
|
|
783
|
+
"aria-pressed": colorFormats.includes(format),
|
|
784
|
+
className: cn(
|
|
785
|
+
"msr:h-6 msr:min-w-0 msr:flex-1 msr:rounded-[5px] msr:border msr:px-1 msr:text-[11px] msr:focus-visible:outline-none msr:focus-visible:shadow-[inset_0_0_0_1px_#0d99ff]",
|
|
786
|
+
colorFormats.includes(format) ? "msr:border-[#0d99ff] msr:bg-[#0d99ff] msr:text-white" : "msr:border-ink-200 msr:text-ink-500 msr:hover:bg-ink-50"
|
|
787
|
+
),
|
|
788
|
+
onClick: () => toggleFormat(format),
|
|
789
|
+
children: format
|
|
790
|
+
},
|
|
791
|
+
format
|
|
792
|
+
)) })
|
|
793
|
+
] }),
|
|
794
|
+
/* @__PURE__ */ jsxs2("label", { className: "msr:col-span-2 msr:flex msr:items-center msr:justify-between msr:gap-3 msr:text-[12px] msr:text-ink-700", children: [
|
|
795
|
+
"Copy",
|
|
796
|
+
/* @__PURE__ */ jsx2("select", { value: colorClickFormat, className: "msr:rounded-[5px] msr:border msr:border-ink-200 msr:bg-white msr:px-1.5 msr:py-1 msr:text-[11px] msr:outline-none msr:focus:shadow-[inset_0_0_0_1px_#0d99ff]", onChange: (event) => setColorClickFormat(event.target.value), children: COLOR_FORMATS.map((format) => /* @__PURE__ */ jsx2("option", { value: format, children: format }, format)) })
|
|
797
|
+
] })
|
|
798
|
+
] }) : null,
|
|
799
|
+
activeTab === "rulers" ? /* @__PURE__ */ jsxs2("section", { className: "msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-x-3 msr:gap-y-1", "aria-label": "Ruler settings", children: [
|
|
800
|
+
/* @__PURE__ */ jsx2(SliderControl, { label: "Opacity", min: 0.2, max: 1, step: 0.05, value: rulerSettings.opacity, formatValue: (value) => `${Math.round(value * 100)}%`, parseInput: (input) => Number.parseFloat(input) / 100, onChange: (value) => setRulerSettings((settings) => ({ ...settings, opacity: value })) }),
|
|
801
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Edge reveal", checked: rulerSettings.edgeReveal, onChange: (edgeReveal) => setRulerSettings((settings) => ({ ...settings, edgeReveal })) }) })
|
|
802
|
+
] }) : null,
|
|
803
|
+
activeTab === "general" ? /* @__PURE__ */ jsxs2("section", { className: "msr:grid msr:grid-cols-[78px_156px] msr:items-center msr:gap-x-3 msr:gap-y-1", "aria-label": "General settings", children: [
|
|
804
|
+
/* @__PURE__ */ jsx2("div", { className: "msr:col-span-2", children: /* @__PURE__ */ jsx2(SettingsSwitch, { label: "Persist", checked: persistOnReload, onChange: setPersistOnReload }) }),
|
|
805
|
+
/* @__PURE__ */ jsxs2("div", { className: "msr:col-span-2 msr:grid msr:h-6 msr:grid-cols-[78px_156px] msr:items-center msr:gap-3 msr:text-[12px] msr:text-ink-700", children: [
|
|
806
|
+
/* @__PURE__ */ jsx2("span", { children: "Version" }),
|
|
807
|
+
/* @__PURE__ */ jsx2("span", { className: "msr:justify-self-end msr:font-mono msr:text-[11px] msr:tabular-nums msr:text-ink-700", children: package_default.version })
|
|
808
|
+
] }),
|
|
809
|
+
/* @__PURE__ */ jsxs2("div", { className: "msr:col-span-2 msr:flex msr:justify-end msr:gap-1", children: [
|
|
810
|
+
/* @__PURE__ */ jsx2(
|
|
811
|
+
"button",
|
|
812
|
+
{
|
|
813
|
+
type: "button",
|
|
814
|
+
"aria-label": "Reset settings to defaults",
|
|
815
|
+
className: "msr:rounded-[5px] msr:border msr:border-ink-200 msr:px-2 msr:py-1 msr:text-[11px] msr:text-ink-700 msr:hover:bg-ink-50 msr:focus-visible:outline-none msr:focus-visible:shadow-[inset_0_0_0_1px_#0d99ff]",
|
|
816
|
+
onClick: onResetSettings,
|
|
817
|
+
children: "Use defaults"
|
|
818
|
+
}
|
|
819
|
+
),
|
|
820
|
+
/* @__PURE__ */ jsx2(
|
|
821
|
+
"button",
|
|
822
|
+
{
|
|
823
|
+
type: "button",
|
|
824
|
+
"aria-label": "Clear workspace",
|
|
825
|
+
className: "msr:rounded-[5px] msr:border msr:border-red-200 msr:px-2 msr:py-1 msr:text-[11px] msr:text-red-600 msr:hover:bg-red-50 msr:focus-visible:outline-none msr:focus-visible:shadow-[inset_0_0_0_1px_#ef4444]",
|
|
826
|
+
onClick: onClearWorkspace,
|
|
827
|
+
children: "Clear workspace"
|
|
828
|
+
}
|
|
829
|
+
)
|
|
830
|
+
] })
|
|
831
|
+
] }) : null
|
|
832
|
+
] });
|
|
833
|
+
}
|
|
834
|
+
|
|
73
835
|
// components/icons.tsx
|
|
74
|
-
import { jsx } from "react/jsx-runtime";
|
|
75
|
-
var IconBase = ({ size = 24, ...props }) => /* @__PURE__ */
|
|
836
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
837
|
+
var IconBase = ({ size = 24, ...props }) => /* @__PURE__ */ jsx3(
|
|
76
838
|
"svg",
|
|
77
839
|
{
|
|
78
840
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -80,12 +842,14 @@ var IconBase = ({ size = 24, ...props }) => /* @__PURE__ */ jsx(
|
|
|
80
842
|
height: size,
|
|
81
843
|
viewBox: "0 0 256 256",
|
|
82
844
|
fill: "currentColor",
|
|
845
|
+
"aria-hidden": "true",
|
|
846
|
+
onDragStart: (event) => event.preventDefault(),
|
|
83
847
|
...props
|
|
84
848
|
}
|
|
85
849
|
);
|
|
86
|
-
var CursorIcon = ({ size = 20, ...props }) => /* @__PURE__ */
|
|
87
|
-
var RulerIcon = ({ size = 20, ...props }) => /* @__PURE__ */
|
|
88
|
-
var XrayIcon = ({ size = 20, ...props }) => /* @__PURE__ */
|
|
850
|
+
var CursorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3("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" }) });
|
|
851
|
+
var RulerIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3("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" }) });
|
|
852
|
+
var XrayIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3(
|
|
89
853
|
"path",
|
|
90
854
|
{
|
|
91
855
|
fill: "none",
|
|
@@ -97,7 +861,7 @@ var XrayIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(IconBase, { size
|
|
|
97
861
|
d: "M76 48h96a16 16 0 0 1 16 16v96a16 16 0 0 1-16 16H76a16 16 0 0 1-16-16V64a16 16 0 0 1 16-16Zm32 32h96a16 16 0 0 1 16 16v96a16 16 0 0 1-16 16h-96a16 16 0 0 1-16-16V96a16 16 0 0 1 16-16Z"
|
|
98
862
|
}
|
|
99
863
|
) });
|
|
100
|
-
var RulersIcon = ({ size = 20, ...props }) => /* @__PURE__ */
|
|
864
|
+
var RulersIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3(
|
|
101
865
|
"path",
|
|
102
866
|
{
|
|
103
867
|
fill: "none",
|
|
@@ -108,10 +872,10 @@ var RulersIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(IconBase, { si
|
|
|
108
872
|
d: "M48 208V48h160M80 48v24m32-24v24m32-24v24m32-24v24M48 80h24M48 112h24m-24 32h24m-24 32h24"
|
|
109
873
|
}
|
|
110
874
|
) });
|
|
111
|
-
var CaretDownIcon = ({ size = 8, ...props }) => /* @__PURE__ */
|
|
112
|
-
var CheckIcon = ({ size = 12, ...props }) => /* @__PURE__ */
|
|
113
|
-
var MinusIcon = ({ size = 12, ...props }) => /* @__PURE__ */
|
|
114
|
-
var TextInspectorIcon = ({ size = 20, ...props }) => /* @__PURE__ */
|
|
875
|
+
var CaretDownIcon = ({ size = 8, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3("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" }) });
|
|
876
|
+
var CheckIcon = ({ size = 12, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3("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" }) });
|
|
877
|
+
var MinusIcon = ({ size = 12, ...props }) => /* @__PURE__ */ jsx3(IconBase, { size, ...props, children: /* @__PURE__ */ jsx3("path", { d: "M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z" }) });
|
|
878
|
+
var TextInspectorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx3(
|
|
115
879
|
"svg",
|
|
116
880
|
{
|
|
117
881
|
xmlns: "http://www.w3.org/2000/svg",
|
|
@@ -119,8 +883,10 @@ var TextInspectorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(
|
|
|
119
883
|
height: size,
|
|
120
884
|
viewBox: "0 0 256 256",
|
|
121
885
|
fill: "currentColor",
|
|
886
|
+
"aria-hidden": "true",
|
|
887
|
+
onDragStart: (event) => event.preventDefault(),
|
|
122
888
|
...props,
|
|
123
|
-
children: /* @__PURE__ */
|
|
889
|
+
children: /* @__PURE__ */ jsx3(
|
|
124
890
|
"text",
|
|
125
891
|
{
|
|
126
892
|
x: "50%",
|
|
@@ -136,9 +902,54 @@ var TextInspectorIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx(
|
|
|
136
902
|
)
|
|
137
903
|
}
|
|
138
904
|
);
|
|
905
|
+
var ColorPickerIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsx3(
|
|
906
|
+
"svg",
|
|
907
|
+
{
|
|
908
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
909
|
+
width: size,
|
|
910
|
+
height: size,
|
|
911
|
+
viewBox: "0 0 24 24",
|
|
912
|
+
fill: "none",
|
|
913
|
+
...props,
|
|
914
|
+
children: /* @__PURE__ */ jsx3(
|
|
915
|
+
"path",
|
|
916
|
+
{
|
|
917
|
+
fill: "currentColor",
|
|
918
|
+
fillRule: "evenodd",
|
|
919
|
+
transform: "translate(-1.44 -1.44) scale(1.12)",
|
|
920
|
+
d: "M15.16 5.658a2.25 2.25 0 0 1 3.18.001l.155.17a2.25 2.25 0 0 1 0 2.84l-.154.172-1.696 1.692a1.5 1.5 0 0 1 .02 1.913l-.104.114a1.5 1.5 0 0 1-2.007.103l-.02-.018-4.443 4.447a2.24 2.24 0 0 1-1.716.65l-.814.815a1.5 1.5 0 0 1-2.121-2.121l.816-.818a2.25 2.25 0 0 1 .653-1.708l4.443-4.446a1.5 1.5 0 0 1 .088-2.025l.114-.103a1.5 1.5 0 0 1 1.91.015zm-7.544 8.959a1.25 1.25 0 0 0-.358 1.021c.021.197-.014.406-.154.546l-.958.96a.5.5 0 0 0 .708.706l.955-.956c.14-.14.352-.176.55-.153.364.042.745-.077 1.025-.356l4.438-4.442-1.767-1.767zm10.018-8.251a1.25 1.25 0 0 0-1.768 0l-1.782 1.78-.065.06a.87.87 0 0 1-1.165-.06.5.5 0 0 0-.707.707l3 3a.5.5 0 0 0 .628.064l.079-.064a.5.5 0 0 0 0-.707l-.004-.004a.873.873 0 0 1 .004-1.23l1.78-1.778a1.25 1.25 0 0 0 0-1.768",
|
|
921
|
+
clipRule: "evenodd"
|
|
922
|
+
}
|
|
923
|
+
)
|
|
924
|
+
}
|
|
925
|
+
);
|
|
926
|
+
var GearIcon = ({ size = 20, ...props }) => /* @__PURE__ */ jsxs3(
|
|
927
|
+
"svg",
|
|
928
|
+
{
|
|
929
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
930
|
+
width: size,
|
|
931
|
+
height: size,
|
|
932
|
+
viewBox: "0 0 24 24",
|
|
933
|
+
fill: "none",
|
|
934
|
+
...props,
|
|
935
|
+
children: [
|
|
936
|
+
/* @__PURE__ */ jsx3(
|
|
937
|
+
"path",
|
|
938
|
+
{
|
|
939
|
+
d: "M10.6504 5.81117C10.9939 4.39628 13.0061 4.39628 13.3496 5.81117C13.5715 6.72517 14.6187 7.15891 15.4219 6.66952C16.6652 5.91193 18.0881 7.33479 17.3305 8.57815C16.8411 9.38134 17.2748 10.4285 18.1888 10.6504C19.6037 10.9939 19.6037 13.0061 18.1888 13.3496C17.2748 13.5715 16.8411 14.6187 17.3305 15.4219C18.0881 16.6652 16.6652 18.0881 15.4219 17.3305C14.6187 16.8411 13.5715 17.2748 13.3496 18.1888C13.0061 19.6037 10.9939 19.6037 10.6504 18.1888C10.4285 17.2748 9.38135 16.8411 8.57815 17.3305C7.33479 18.0881 5.91193 16.6652 6.66952 15.4219C7.15891 14.6187 6.72517 13.5715 5.81117 13.3496C4.39628 13.0061 4.39628 10.9939 5.81117 10.6504C6.72517 10.4285 7.15891 9.38134 6.66952 8.57815C5.91193 7.33479 7.33479 5.91192 8.57815 6.66952C9.38135 7.15891 10.4285 6.72517 10.6504 5.81117Z",
|
|
940
|
+
stroke: "currentColor",
|
|
941
|
+
strokeWidth: "1",
|
|
942
|
+
strokeLinecap: "round",
|
|
943
|
+
strokeLinejoin: "round"
|
|
944
|
+
}
|
|
945
|
+
),
|
|
946
|
+
/* @__PURE__ */ jsx3("circle", { cx: "12", cy: "12", r: "2.5", stroke: "currentColor", strokeWidth: "1" })
|
|
947
|
+
]
|
|
948
|
+
}
|
|
949
|
+
);
|
|
139
950
|
|
|
140
951
|
// components/toolbar.tsx
|
|
141
|
-
import { jsx as
|
|
952
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
142
953
|
var TOOLBAR_TOOLTIP_DELAY_MS = 800;
|
|
143
954
|
var TOOLBAR_DRAG_SLOP = 6;
|
|
144
955
|
var GUIDE_MENU_WIDTH = 176;
|
|
@@ -156,61 +967,43 @@ function ToolbarButton({
|
|
|
156
967
|
onTooltipLeave,
|
|
157
968
|
children
|
|
158
969
|
}) {
|
|
159
|
-
return /* @__PURE__ */
|
|
970
|
+
return /* @__PURE__ */ jsxs4(
|
|
160
971
|
"div",
|
|
161
972
|
{
|
|
162
973
|
className: "msr:relative",
|
|
163
974
|
onMouseEnter: () => onTooltipEnter(id),
|
|
164
975
|
onMouseLeave: () => onTooltipLeave(id),
|
|
165
976
|
children: [
|
|
166
|
-
/* @__PURE__ */
|
|
977
|
+
/* @__PURE__ */ jsx4(
|
|
167
978
|
"button",
|
|
168
979
|
{
|
|
169
980
|
type: "button",
|
|
170
|
-
"aria-label": `${label} (${shortcut})`,
|
|
171
981
|
"aria-pressed": active,
|
|
172
|
-
|
|
982
|
+
"aria-label": `${label} (${shortcut})`,
|
|
173
983
|
className: cn(
|
|
174
|
-
"msr:flex msr:size-8 msr:items-center msr:justify-center msr:rounded-[8px] msr:outline-none",
|
|
984
|
+
"msr:flex msr:size-8 msr:select-none msr:items-center msr:justify-center msr:rounded-[8px] msr:outline-none",
|
|
175
985
|
active ? "msr:bg-[#0d99ff] msr:text-white" : "msr:bg-transparent msr:text-black msr:hover:bg-black/4"
|
|
176
986
|
),
|
|
177
987
|
onClick,
|
|
178
988
|
children
|
|
179
989
|
}
|
|
180
990
|
),
|
|
181
|
-
/* @__PURE__ */
|
|
182
|
-
"span",
|
|
183
|
-
{
|
|
184
|
-
className: cn(
|
|
185
|
-
cn(
|
|
186
|
-
"msr:pointer-events-none msr:absolute msr:left-1/2 msr:-translate-x-1/2 msr:whitespace-nowrap msr:rounded msr:bg-black msr:px-2 msr:py-1 msr:text-[11px] msr:text-white msr:transition-opacity msr:duration-150 msr:select-none",
|
|
187
|
-
tooltipInstant && "msr:transition-none"
|
|
188
|
-
),
|
|
189
|
-
tooltipSide === "top" ? "msr:bottom-full msr:mb-2" : "msr:top-full msr:mt-2",
|
|
190
|
-
tooltipVisible ? "msr:opacity-100" : "msr:opacity-0"
|
|
191
|
-
),
|
|
192
|
-
children: [
|
|
193
|
-
label,
|
|
194
|
-
" ",
|
|
195
|
-
/* @__PURE__ */ jsx2("kbd", { className: "msr:text-white/60", children: shortcut })
|
|
196
|
-
]
|
|
197
|
-
}
|
|
198
|
-
)
|
|
991
|
+
/* @__PURE__ */ jsx4(Tooltip, { label, shortcut, visible: tooltipVisible, instant: tooltipInstant, side: tooltipSide })
|
|
199
992
|
]
|
|
200
993
|
}
|
|
201
994
|
);
|
|
202
995
|
}
|
|
203
996
|
function useToolbarTooltip() {
|
|
204
|
-
const [visibleTooltipId, setVisibleTooltipId] =
|
|
205
|
-
const timerRef =
|
|
206
|
-
const instantRef =
|
|
207
|
-
const [tooltipInstant, setTooltipInstant] =
|
|
208
|
-
const clearTimer =
|
|
997
|
+
const [visibleTooltipId, setVisibleTooltipId] = useState3(null);
|
|
998
|
+
const timerRef = useRef2(null);
|
|
999
|
+
const instantRef = useRef2(false);
|
|
1000
|
+
const [tooltipInstant, setTooltipInstant] = useState3(false);
|
|
1001
|
+
const clearTimer = useCallback2(() => {
|
|
209
1002
|
if (timerRef.current === null) return;
|
|
210
1003
|
window.clearTimeout(timerRef.current);
|
|
211
1004
|
timerRef.current = null;
|
|
212
1005
|
}, []);
|
|
213
|
-
const onTooltipEnter =
|
|
1006
|
+
const onTooltipEnter = useCallback2(
|
|
214
1007
|
(id) => {
|
|
215
1008
|
clearTimer();
|
|
216
1009
|
if (instantRef.current) {
|
|
@@ -227,14 +1020,14 @@ function useToolbarTooltip() {
|
|
|
227
1020
|
},
|
|
228
1021
|
[clearTimer]
|
|
229
1022
|
);
|
|
230
|
-
const onTooltipLeave =
|
|
1023
|
+
const onTooltipLeave = useCallback2(
|
|
231
1024
|
(id) => {
|
|
232
1025
|
clearTimer();
|
|
233
1026
|
setVisibleTooltipId((prev) => prev === id ? null : prev);
|
|
234
1027
|
},
|
|
235
1028
|
[clearTimer]
|
|
236
1029
|
);
|
|
237
|
-
const onToolbarLeave =
|
|
1030
|
+
const onToolbarLeave = useCallback2(() => {
|
|
238
1031
|
clearTimer();
|
|
239
1032
|
setVisibleTooltipId(null);
|
|
240
1033
|
instantRef.current = false;
|
|
@@ -249,10 +1042,11 @@ function useToolbarTooltip() {
|
|
|
249
1042
|
};
|
|
250
1043
|
}
|
|
251
1044
|
function useToolbarDrag(initialPosition, eventTarget) {
|
|
252
|
-
const [position, setPosition] =
|
|
253
|
-
const suppressClickRef =
|
|
254
|
-
const
|
|
255
|
-
const
|
|
1045
|
+
const [position, setPosition] = useState3(initialPosition);
|
|
1046
|
+
const suppressClickRef = useRef2(false);
|
|
1047
|
+
const previousUserSelectRef = useRef2(null);
|
|
1048
|
+
const detachListenersRef = useRef2(null);
|
|
1049
|
+
const dragRef = useRef2({
|
|
256
1050
|
active: false,
|
|
257
1051
|
didDrag: false,
|
|
258
1052
|
pointerId: -1,
|
|
@@ -263,12 +1057,28 @@ function useToolbarDrag(initialPosition, eventTarget) {
|
|
|
263
1057
|
width: 0,
|
|
264
1058
|
height: 0
|
|
265
1059
|
});
|
|
266
|
-
const
|
|
1060
|
+
const disableTextSelection = useCallback2(() => {
|
|
1061
|
+
if (previousUserSelectRef.current !== null) return;
|
|
1062
|
+
const root = eventTarget.document.documentElement;
|
|
1063
|
+
previousUserSelectRef.current = root.style.userSelect;
|
|
1064
|
+
root.style.setProperty("user-select", "none", "important");
|
|
1065
|
+
}, [eventTarget]);
|
|
1066
|
+
const restoreTextSelection = useCallback2(() => {
|
|
1067
|
+
const previous = previousUserSelectRef.current;
|
|
1068
|
+
if (previous === null) return;
|
|
1069
|
+
const root = eventTarget.document.documentElement;
|
|
1070
|
+
root.style.userSelect = previous;
|
|
1071
|
+
previousUserSelectRef.current = null;
|
|
1072
|
+
}, [eventTarget]);
|
|
1073
|
+
useEffect(() => restoreTextSelection, [restoreTextSelection]);
|
|
1074
|
+
const onPointerDown = useCallback2(
|
|
267
1075
|
(event) => {
|
|
268
1076
|
if (event.button !== 0) return;
|
|
1077
|
+
disableTextSelection();
|
|
269
1078
|
if (detachListenersRef.current) {
|
|
270
1079
|
detachListenersRef.current();
|
|
271
1080
|
detachListenersRef.current = null;
|
|
1081
|
+
restoreTextSelection();
|
|
272
1082
|
}
|
|
273
1083
|
const state = dragRef.current;
|
|
274
1084
|
state.active = false;
|
|
@@ -303,6 +1113,7 @@ function useToolbarDrag(initialPosition, eventTarget) {
|
|
|
303
1113
|
if (current.pointerId !== endEvent.pointerId && current.pointerId !== -1)
|
|
304
1114
|
return;
|
|
305
1115
|
suppressClickRef.current = current.didDrag;
|
|
1116
|
+
restoreTextSelection();
|
|
306
1117
|
current.active = false;
|
|
307
1118
|
current.didDrag = false;
|
|
308
1119
|
current.pointerId = -1;
|
|
@@ -320,9 +1131,9 @@ function useToolbarDrag(initialPosition, eventTarget) {
|
|
|
320
1131
|
eventTarget.removeEventListener("pointercancel", handlePointerEnd);
|
|
321
1132
|
};
|
|
322
1133
|
},
|
|
323
|
-
[eventTarget, position.x, position.y]
|
|
1134
|
+
[disableTextSelection, eventTarget, position.x, position.y, restoreTextSelection]
|
|
324
1135
|
);
|
|
325
|
-
const onClickCapture =
|
|
1136
|
+
const onClickCapture = useCallback2(
|
|
326
1137
|
(event) => {
|
|
327
1138
|
if (!suppressClickRef.current) return;
|
|
328
1139
|
event.preventDefault();
|
|
@@ -337,12 +1148,48 @@ function ToolbarComponent({
|
|
|
337
1148
|
toolMode,
|
|
338
1149
|
setEnabled,
|
|
339
1150
|
setToolMode,
|
|
1151
|
+
xrayVisible,
|
|
1152
|
+
setXrayVisible,
|
|
340
1153
|
rulersVisible,
|
|
341
1154
|
setRulersVisible,
|
|
342
1155
|
guideOrientation,
|
|
343
1156
|
setGuideOrientation,
|
|
344
1157
|
onInteract,
|
|
345
|
-
eventTarget
|
|
1158
|
+
eventTarget,
|
|
1159
|
+
colorPickerActive,
|
|
1160
|
+
setColorPickerActive,
|
|
1161
|
+
onColorPickerClick,
|
|
1162
|
+
settingsOpen,
|
|
1163
|
+
setSettingsOpen,
|
|
1164
|
+
highlightColor,
|
|
1165
|
+
setHighlightColor,
|
|
1166
|
+
guideColor,
|
|
1167
|
+
setGuideColor,
|
|
1168
|
+
hoverHighlight,
|
|
1169
|
+
setHoverHighlight,
|
|
1170
|
+
persistOnReload,
|
|
1171
|
+
setPersistOnReload,
|
|
1172
|
+
colorPickerFormats,
|
|
1173
|
+
setColorPickerFormats,
|
|
1174
|
+
colorPickerClickFormat,
|
|
1175
|
+
setColorPickerClickFormat,
|
|
1176
|
+
snapEnabled,
|
|
1177
|
+
setSnapEnabled,
|
|
1178
|
+
snapGuidesEnabled,
|
|
1179
|
+
setSnapGuidesEnabled,
|
|
1180
|
+
selectNewGuideEnabled,
|
|
1181
|
+
setSelectNewGuideEnabled,
|
|
1182
|
+
multiMeasureEnabled,
|
|
1183
|
+
setMultiMeasureEnabled,
|
|
1184
|
+
guideStyle,
|
|
1185
|
+
setGuideStyle,
|
|
1186
|
+
rulerSettings,
|
|
1187
|
+
setRulerSettings,
|
|
1188
|
+
settingsTab,
|
|
1189
|
+
setSettingsTab,
|
|
1190
|
+
onToggleSettings,
|
|
1191
|
+
onResetSettings,
|
|
1192
|
+
onClearWorkspace
|
|
346
1193
|
}, ref) {
|
|
347
1194
|
const { position, onPointerDown, onClickCapture } = useToolbarDrag({
|
|
348
1195
|
x: 16,
|
|
@@ -355,11 +1202,13 @@ function ToolbarComponent({
|
|
|
355
1202
|
onTooltipLeave,
|
|
356
1203
|
onToolbarLeave
|
|
357
1204
|
} = useToolbarTooltip();
|
|
358
|
-
const [guideMenuOpen, setGuideMenuOpen] =
|
|
359
|
-
const
|
|
360
|
-
const
|
|
361
|
-
const [
|
|
362
|
-
const
|
|
1205
|
+
const [guideMenuOpen, setGuideMenuOpen] = useState3(false);
|
|
1206
|
+
const settingsRef = useRef2(null);
|
|
1207
|
+
const guideMenuRef = useRef2(null);
|
|
1208
|
+
const [activeMenuIndex, setActiveMenuIndex] = useState3(0);
|
|
1209
|
+
const [menuAlign, setMenuAlign] = useState3("right");
|
|
1210
|
+
const tooltipsEnabled = !guideMenuOpen && !settingsOpen;
|
|
1211
|
+
const updateMenuAlign = useCallback2(() => {
|
|
363
1212
|
const anchorRect = guideMenuRef.current?.getBoundingClientRect();
|
|
364
1213
|
if (!anchorRect) return;
|
|
365
1214
|
const rightAlignedLeft = anchorRect.right - GUIDE_MENU_WIDTH;
|
|
@@ -379,34 +1228,50 @@ function ToolbarComponent({
|
|
|
379
1228
|
const nearBottom = viewportHeight > 0 && position.y > viewportHeight - 56;
|
|
380
1229
|
const tooltipSide = nearTop && !nearBottom ? "bottom" : "top";
|
|
381
1230
|
const menuSide = nearBottom ? "top" : "bottom";
|
|
382
|
-
const selectMode =
|
|
1231
|
+
const selectMode = useCallback2(() => {
|
|
383
1232
|
setEnabled(true);
|
|
1233
|
+
setColorPickerActive(false);
|
|
384
1234
|
setToolMode((prev) => prev === "select" ? "none" : "select");
|
|
385
1235
|
onInteract();
|
|
386
|
-
}, [onInteract, setEnabled, setToolMode]);
|
|
387
|
-
const guidesMode =
|
|
1236
|
+
}, [onInteract, setColorPickerActive, setEnabled, setToolMode]);
|
|
1237
|
+
const guidesMode = useCallback2(() => {
|
|
388
1238
|
setEnabled(true);
|
|
1239
|
+
setColorPickerActive(false);
|
|
389
1240
|
setToolMode((prev) => prev === "guides" ? "none" : "guides");
|
|
390
1241
|
onInteract();
|
|
391
|
-
}, [onInteract, setEnabled, setToolMode]);
|
|
392
|
-
const textInspectorMode =
|
|
1242
|
+
}, [onInteract, setColorPickerActive, setEnabled, setToolMode]);
|
|
1243
|
+
const textInspectorMode = useCallback2(() => {
|
|
393
1244
|
setEnabled(true);
|
|
1245
|
+
setColorPickerActive(false);
|
|
394
1246
|
setToolMode(
|
|
395
1247
|
(prev) => prev === "text-inspector" ? "none" : "text-inspector"
|
|
396
1248
|
);
|
|
397
1249
|
onInteract();
|
|
398
|
-
}, [onInteract, setEnabled, setToolMode]);
|
|
399
|
-
const xrayMode =
|
|
1250
|
+
}, [onInteract, setColorPickerActive, setEnabled, setToolMode]);
|
|
1251
|
+
const xrayMode = useCallback2(() => {
|
|
400
1252
|
setEnabled(true);
|
|
401
|
-
|
|
1253
|
+
setColorPickerActive(false);
|
|
1254
|
+
setXrayVisible((prev) => !prev);
|
|
402
1255
|
onInteract();
|
|
403
|
-
}, [onInteract, setEnabled,
|
|
404
|
-
const
|
|
1256
|
+
}, [onInteract, setColorPickerActive, setEnabled, setXrayVisible]);
|
|
1257
|
+
const colorPickerMode = useCallback2(() => {
|
|
405
1258
|
setEnabled(true);
|
|
1259
|
+
setToolMode("none");
|
|
1260
|
+
if (colorPickerActive) {
|
|
1261
|
+
setColorPickerActive(false);
|
|
1262
|
+
} else {
|
|
1263
|
+
setColorPickerActive(true);
|
|
1264
|
+
onColorPickerClick();
|
|
1265
|
+
}
|
|
1266
|
+
onInteract();
|
|
1267
|
+
}, [colorPickerActive, onColorPickerClick, onInteract, setColorPickerActive, setEnabled, setToolMode]);
|
|
1268
|
+
const rulersMode = useCallback2(() => {
|
|
1269
|
+
setEnabled(true);
|
|
1270
|
+
setColorPickerActive(false);
|
|
406
1271
|
setRulersVisible((prev) => !prev);
|
|
407
1272
|
onInteract();
|
|
408
|
-
}, [onInteract, setEnabled, setRulersVisible]);
|
|
409
|
-
const selectGuideOrientation =
|
|
1273
|
+
}, [onInteract, setColorPickerActive, setEnabled, setRulersVisible]);
|
|
1274
|
+
const selectGuideOrientation = useCallback2(
|
|
410
1275
|
(orientation) => {
|
|
411
1276
|
setEnabled(true);
|
|
412
1277
|
setToolMode("guides");
|
|
@@ -417,29 +1282,33 @@ function ToolbarComponent({
|
|
|
417
1282
|
[onInteract, setEnabled, setGuideOrientation, setToolMode]
|
|
418
1283
|
);
|
|
419
1284
|
useLayoutEffect(() => {
|
|
420
|
-
if (!guideMenuOpen) return;
|
|
421
|
-
const frame = eventTarget.requestAnimationFrame(() => {
|
|
1285
|
+
if (!guideMenuOpen && !settingsOpen) return;
|
|
1286
|
+
const frame = guideMenuOpen ? eventTarget.requestAnimationFrame(() => {
|
|
422
1287
|
guideMenuRef.current?.querySelector("[role='menu']")?.focus();
|
|
423
|
-
});
|
|
1288
|
+
}) : 0;
|
|
424
1289
|
const handlePointerDown = (event) => {
|
|
425
|
-
const menu = guideMenuRef.current;
|
|
426
|
-
if (!menu) return;
|
|
427
1290
|
const path = event.composedPath();
|
|
428
|
-
if (
|
|
429
|
-
|
|
1291
|
+
if (guideMenuOpen) {
|
|
1292
|
+
const menu = guideMenuRef.current;
|
|
1293
|
+
if (menu && !path.includes(menu)) setGuideMenuOpen(false);
|
|
1294
|
+
}
|
|
1295
|
+
if (settingsOpen) {
|
|
1296
|
+
const settings = settingsRef.current;
|
|
1297
|
+
if (settings && !path.includes(settings)) setSettingsOpen(false);
|
|
1298
|
+
}
|
|
430
1299
|
};
|
|
431
1300
|
const handleResize = () => {
|
|
432
|
-
updateMenuAlign();
|
|
1301
|
+
if (guideMenuOpen) updateMenuAlign();
|
|
433
1302
|
};
|
|
434
1303
|
eventTarget.addEventListener("pointerdown", handlePointerDown);
|
|
435
|
-
eventTarget.addEventListener("resize", handleResize);
|
|
1304
|
+
if (guideMenuOpen) eventTarget.addEventListener("resize", handleResize);
|
|
436
1305
|
return () => {
|
|
437
|
-
eventTarget.cancelAnimationFrame(frame);
|
|
1306
|
+
if (frame) eventTarget.cancelAnimationFrame(frame);
|
|
438
1307
|
eventTarget.removeEventListener("pointerdown", handlePointerDown);
|
|
439
1308
|
eventTarget.removeEventListener("resize", handleResize);
|
|
440
1309
|
};
|
|
441
|
-
}, [eventTarget, guideMenuOpen, guideOrientation, updateMenuAlign]);
|
|
442
|
-
return /* @__PURE__ */
|
|
1310
|
+
}, [eventTarget, guideMenuOpen, guideOrientation, settingsOpen, updateMenuAlign]);
|
|
1311
|
+
return /* @__PURE__ */ jsxs4(
|
|
443
1312
|
"div",
|
|
444
1313
|
{
|
|
445
1314
|
ref,
|
|
@@ -452,7 +1321,7 @@ function ToolbarComponent({
|
|
|
452
1321
|
onClickCapture,
|
|
453
1322
|
onMouseLeave: onToolbarLeave,
|
|
454
1323
|
children: [
|
|
455
|
-
/* @__PURE__ */
|
|
1324
|
+
/* @__PURE__ */ jsx4(
|
|
456
1325
|
ToolbarButton,
|
|
457
1326
|
{
|
|
458
1327
|
id: "select",
|
|
@@ -460,31 +1329,47 @@ function ToolbarComponent({
|
|
|
460
1329
|
label: "Select",
|
|
461
1330
|
shortcut: "S",
|
|
462
1331
|
onClick: selectMode,
|
|
463
|
-
tooltipVisible: visibleTooltipId === "select",
|
|
1332
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "select",
|
|
464
1333
|
tooltipInstant,
|
|
465
1334
|
tooltipSide,
|
|
466
1335
|
onTooltipEnter,
|
|
467
1336
|
onTooltipLeave,
|
|
468
|
-
children: /* @__PURE__ */
|
|
1337
|
+
children: /* @__PURE__ */ jsx4(CursorIcon, { size: 20 })
|
|
469
1338
|
}
|
|
470
1339
|
),
|
|
471
|
-
/* @__PURE__ */
|
|
1340
|
+
/* @__PURE__ */ jsx4(
|
|
472
1341
|
ToolbarButton,
|
|
473
1342
|
{
|
|
474
1343
|
id: "xray",
|
|
475
|
-
active:
|
|
1344
|
+
active: xrayVisible,
|
|
476
1345
|
label: "X-ray",
|
|
477
1346
|
shortcut: "X",
|
|
478
1347
|
onClick: xrayMode,
|
|
479
|
-
tooltipVisible: visibleTooltipId === "xray",
|
|
1348
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "xray",
|
|
480
1349
|
tooltipInstant,
|
|
481
1350
|
tooltipSide,
|
|
482
1351
|
onTooltipEnter,
|
|
483
1352
|
onTooltipLeave,
|
|
484
|
-
children: /* @__PURE__ */
|
|
1353
|
+
children: /* @__PURE__ */ jsx4(XrayIcon, { size: 20 })
|
|
485
1354
|
}
|
|
486
1355
|
),
|
|
487
|
-
/* @__PURE__ */
|
|
1356
|
+
/* @__PURE__ */ jsx4(
|
|
1357
|
+
ToolbarButton,
|
|
1358
|
+
{
|
|
1359
|
+
id: "color-picker",
|
|
1360
|
+
active: colorPickerActive,
|
|
1361
|
+
label: "Color picker",
|
|
1362
|
+
shortcut: "P",
|
|
1363
|
+
onClick: colorPickerMode,
|
|
1364
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "color-picker",
|
|
1365
|
+
tooltipInstant,
|
|
1366
|
+
tooltipSide,
|
|
1367
|
+
onTooltipEnter,
|
|
1368
|
+
onTooltipLeave,
|
|
1369
|
+
children: /* @__PURE__ */ jsx4(ColorPickerIcon, { size: 20, "aria-hidden": "true" })
|
|
1370
|
+
}
|
|
1371
|
+
),
|
|
1372
|
+
/* @__PURE__ */ jsx4(
|
|
488
1373
|
ToolbarButton,
|
|
489
1374
|
{
|
|
490
1375
|
id: "rulers",
|
|
@@ -492,15 +1377,15 @@ function ToolbarComponent({
|
|
|
492
1377
|
label: "Rulers",
|
|
493
1378
|
shortcut: "R",
|
|
494
1379
|
onClick: rulersMode,
|
|
495
|
-
tooltipVisible: visibleTooltipId === "rulers",
|
|
1380
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "rulers",
|
|
496
1381
|
tooltipInstant,
|
|
497
1382
|
tooltipSide,
|
|
498
1383
|
onTooltipEnter,
|
|
499
1384
|
onTooltipLeave,
|
|
500
|
-
children: /* @__PURE__ */
|
|
1385
|
+
children: /* @__PURE__ */ jsx4(RulersIcon, { size: 20 })
|
|
501
1386
|
}
|
|
502
1387
|
),
|
|
503
|
-
/* @__PURE__ */
|
|
1388
|
+
/* @__PURE__ */ jsx4(
|
|
504
1389
|
ToolbarButton,
|
|
505
1390
|
{
|
|
506
1391
|
id: "text-inspector",
|
|
@@ -508,15 +1393,15 @@ function ToolbarComponent({
|
|
|
508
1393
|
label: "Text inspector",
|
|
509
1394
|
shortcut: "A",
|
|
510
1395
|
onClick: textInspectorMode,
|
|
511
|
-
tooltipVisible: visibleTooltipId === "text-inspector",
|
|
1396
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "text-inspector",
|
|
512
1397
|
tooltipInstant,
|
|
513
1398
|
tooltipSide,
|
|
514
1399
|
onTooltipEnter,
|
|
515
1400
|
onTooltipLeave,
|
|
516
|
-
children: /* @__PURE__ */
|
|
1401
|
+
children: /* @__PURE__ */ jsx4(TextInspectorIcon, { size: 20, "aria-hidden": "true" })
|
|
517
1402
|
}
|
|
518
1403
|
),
|
|
519
|
-
/* @__PURE__ */
|
|
1404
|
+
/* @__PURE__ */ jsx4(
|
|
520
1405
|
ToolbarButton,
|
|
521
1406
|
{
|
|
522
1407
|
id: "guides",
|
|
@@ -524,12 +1409,12 @@ function ToolbarComponent({
|
|
|
524
1409
|
label: "Guides",
|
|
525
1410
|
shortcut: "G",
|
|
526
1411
|
onClick: guidesMode,
|
|
527
|
-
tooltipVisible: visibleTooltipId === "guides",
|
|
1412
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "guides",
|
|
528
1413
|
tooltipInstant,
|
|
529
1414
|
tooltipSide,
|
|
530
1415
|
onTooltipEnter,
|
|
531
1416
|
onTooltipLeave,
|
|
532
|
-
children: /* @__PURE__ */
|
|
1417
|
+
children: /* @__PURE__ */ jsx4(
|
|
533
1418
|
RulerIcon,
|
|
534
1419
|
{
|
|
535
1420
|
size: 20,
|
|
@@ -540,7 +1425,7 @@ function ToolbarComponent({
|
|
|
540
1425
|
)
|
|
541
1426
|
}
|
|
542
1427
|
),
|
|
543
|
-
/* @__PURE__ */
|
|
1428
|
+
/* @__PURE__ */ jsxs4(
|
|
544
1429
|
"div",
|
|
545
1430
|
{
|
|
546
1431
|
className: "msr:group msr:relative msr:-ml-1 msr:flex msr:items-stretch",
|
|
@@ -548,12 +1433,11 @@ function ToolbarComponent({
|
|
|
548
1433
|
onMouseEnter: () => onTooltipEnter("guide-menu"),
|
|
549
1434
|
onMouseLeave: () => onTooltipLeave("guide-menu"),
|
|
550
1435
|
children: [
|
|
551
|
-
/* @__PURE__ */
|
|
1436
|
+
/* @__PURE__ */ jsx4(
|
|
552
1437
|
"button",
|
|
553
1438
|
{
|
|
554
1439
|
type: "button",
|
|
555
1440
|
"aria-label": "Guide orientation menu",
|
|
556
|
-
title: "Guide orientation",
|
|
557
1441
|
className: cn(
|
|
558
1442
|
"msr:flex msr:h-8 msr:w-4 msr:items-center msr:justify-center msr:rounded-[6px] msr:outline-none msr:hover:bg-black/10",
|
|
559
1443
|
guideMenuOpen ? "msr:bg-black/10 msr:text-black" : "msr:text-black"
|
|
@@ -568,21 +1452,21 @@ function ToolbarComponent({
|
|
|
568
1452
|
return !prev;
|
|
569
1453
|
});
|
|
570
1454
|
},
|
|
571
|
-
children: /* @__PURE__ */
|
|
1455
|
+
children: /* @__PURE__ */ jsx4(CaretDownIcon, { size: 8 })
|
|
572
1456
|
}
|
|
573
1457
|
),
|
|
574
|
-
/* @__PURE__ */
|
|
1458
|
+
/* @__PURE__ */ jsx4(
|
|
575
1459
|
"span",
|
|
576
1460
|
{
|
|
577
1461
|
className: cn(
|
|
578
1462
|
"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",
|
|
579
1463
|
tooltipSide === "top" ? "msr:bottom-full msr:mb-2" : "msr:top-full msr:mt-2",
|
|
580
|
-
visibleTooltipId === "guide-menu" &&
|
|
1464
|
+
visibleTooltipId === "guide-menu" && tooltipsEnabled ? "msr:opacity-100" : "msr:opacity-0"
|
|
581
1465
|
),
|
|
582
1466
|
children: "Orientation Guide"
|
|
583
1467
|
}
|
|
584
1468
|
),
|
|
585
|
-
guideMenuOpen ? /* @__PURE__ */
|
|
1469
|
+
guideMenuOpen ? /* @__PURE__ */ jsxs4(
|
|
586
1470
|
"div",
|
|
587
1471
|
{
|
|
588
1472
|
className: cn(
|
|
@@ -623,7 +1507,7 @@ function ToolbarComponent({
|
|
|
623
1507
|
}
|
|
624
1508
|
},
|
|
625
1509
|
children: [
|
|
626
|
-
/* @__PURE__ */
|
|
1510
|
+
/* @__PURE__ */ jsxs4(
|
|
627
1511
|
"button",
|
|
628
1512
|
{
|
|
629
1513
|
type: "button",
|
|
@@ -633,7 +1517,7 @@ function ToolbarComponent({
|
|
|
633
1517
|
),
|
|
634
1518
|
onClick: () => selectGuideOrientation("horizontal"),
|
|
635
1519
|
children: [
|
|
636
|
-
/* @__PURE__ */
|
|
1520
|
+
/* @__PURE__ */ jsx4(
|
|
637
1521
|
CheckIcon,
|
|
638
1522
|
{
|
|
639
1523
|
size: 12,
|
|
@@ -642,13 +1526,13 @@ function ToolbarComponent({
|
|
|
642
1526
|
)
|
|
643
1527
|
}
|
|
644
1528
|
),
|
|
645
|
-
/* @__PURE__ */
|
|
646
|
-
/* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
1529
|
+
/* @__PURE__ */ jsx4(MinusIcon, { size: 12 }),
|
|
1530
|
+
/* @__PURE__ */ jsx4("span", { className: "msr:flex-1", children: "Horizontal" }),
|
|
1531
|
+
/* @__PURE__ */ jsx4("span", { children: "H" })
|
|
648
1532
|
]
|
|
649
1533
|
}
|
|
650
1534
|
),
|
|
651
|
-
/* @__PURE__ */
|
|
1535
|
+
/* @__PURE__ */ jsxs4(
|
|
652
1536
|
"button",
|
|
653
1537
|
{
|
|
654
1538
|
type: "button",
|
|
@@ -658,7 +1542,7 @@ function ToolbarComponent({
|
|
|
658
1542
|
),
|
|
659
1543
|
onClick: () => selectGuideOrientation("vertical"),
|
|
660
1544
|
children: [
|
|
661
|
-
/* @__PURE__ */
|
|
1545
|
+
/* @__PURE__ */ jsx4(
|
|
662
1546
|
CheckIcon,
|
|
663
1547
|
{
|
|
664
1548
|
size: 12,
|
|
@@ -667,9 +1551,9 @@ function ToolbarComponent({
|
|
|
667
1551
|
)
|
|
668
1552
|
}
|
|
669
1553
|
),
|
|
670
|
-
/* @__PURE__ */
|
|
671
|
-
/* @__PURE__ */
|
|
672
|
-
/* @__PURE__ */
|
|
1554
|
+
/* @__PURE__ */ jsx4(MinusIcon, { size: 12, className: "msr:rotate-90" }),
|
|
1555
|
+
/* @__PURE__ */ jsx4("span", { className: "msr:flex-1", children: "Vertical" }),
|
|
1556
|
+
/* @__PURE__ */ jsx4("span", { children: "V" })
|
|
673
1557
|
]
|
|
674
1558
|
}
|
|
675
1559
|
)
|
|
@@ -678,34 +1562,329 @@ function ToolbarComponent({
|
|
|
678
1562
|
) : null
|
|
679
1563
|
]
|
|
680
1564
|
}
|
|
1565
|
+
),
|
|
1566
|
+
/* @__PURE__ */ jsxs4("div", { ref: settingsRef, className: "msr:relative msr:flex", children: [
|
|
1567
|
+
/* @__PURE__ */ jsx4(
|
|
1568
|
+
ToolbarButton,
|
|
1569
|
+
{
|
|
1570
|
+
id: "settings",
|
|
1571
|
+
active: settingsOpen,
|
|
1572
|
+
label: "Settings",
|
|
1573
|
+
shortcut: "\u2318/Ctrl+,",
|
|
1574
|
+
onClick: () => {
|
|
1575
|
+
onInteract();
|
|
1576
|
+
onToggleSettings();
|
|
1577
|
+
},
|
|
1578
|
+
tooltipVisible: tooltipsEnabled && visibleTooltipId === "settings",
|
|
1579
|
+
tooltipInstant,
|
|
1580
|
+
tooltipSide,
|
|
1581
|
+
onTooltipEnter,
|
|
1582
|
+
onTooltipLeave,
|
|
1583
|
+
children: /* @__PURE__ */ jsx4(GearIcon, { size: 20, "aria-hidden": "true" })
|
|
1584
|
+
}
|
|
1585
|
+
),
|
|
1586
|
+
settingsOpen ? /* @__PURE__ */ jsx4(
|
|
1587
|
+
"div",
|
|
1588
|
+
{
|
|
1589
|
+
className: cn(
|
|
1590
|
+
"mesurer-menu-surface msr:absolute msr:-right-1 msr:z-[70] msr:box-border msr:w-[272px] msr:max-w-[calc(100vw-16px)] msr:rounded-lg msr:border msr:border-ink-200 msr:bg-white msr:p-3",
|
|
1591
|
+
menuSide === "bottom" ? "msr:top-full msr:mt-2" : "msr:bottom-full msr:mb-2"
|
|
1592
|
+
),
|
|
1593
|
+
"data-mesurer-inspector-ui": "true",
|
|
1594
|
+
role: "dialog",
|
|
1595
|
+
"aria-label": "Settings",
|
|
1596
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
1597
|
+
onPointerMove: (event) => event.stopPropagation(),
|
|
1598
|
+
onPointerUp: (event) => event.stopPropagation(),
|
|
1599
|
+
onClick: (event) => event.stopPropagation(),
|
|
1600
|
+
children: /* @__PURE__ */ jsx4(
|
|
1601
|
+
SettingsPanel,
|
|
1602
|
+
{
|
|
1603
|
+
ownerWindow: eventTarget,
|
|
1604
|
+
highlightColor,
|
|
1605
|
+
setHighlightColor,
|
|
1606
|
+
guideColor,
|
|
1607
|
+
setGuideColor,
|
|
1608
|
+
hoverHighlight,
|
|
1609
|
+
setHoverHighlight,
|
|
1610
|
+
persistOnReload,
|
|
1611
|
+
setPersistOnReload,
|
|
1612
|
+
colorFormats: colorPickerFormats,
|
|
1613
|
+
setColorFormats: setColorPickerFormats,
|
|
1614
|
+
colorClickFormat: colorPickerClickFormat,
|
|
1615
|
+
setColorClickFormat: setColorPickerClickFormat,
|
|
1616
|
+
snapEnabled,
|
|
1617
|
+
setSnapEnabled,
|
|
1618
|
+
snapGuidesEnabled,
|
|
1619
|
+
setSnapGuidesEnabled,
|
|
1620
|
+
selectNewGuideEnabled,
|
|
1621
|
+
setSelectNewGuideEnabled,
|
|
1622
|
+
multiMeasureEnabled,
|
|
1623
|
+
setMultiMeasureEnabled,
|
|
1624
|
+
guideStyle,
|
|
1625
|
+
setGuideStyle,
|
|
1626
|
+
rulerSettings,
|
|
1627
|
+
setRulerSettings,
|
|
1628
|
+
activeTab: settingsTab,
|
|
1629
|
+
onTabChange: setSettingsTab,
|
|
1630
|
+
onResetSettings,
|
|
1631
|
+
onClearWorkspace
|
|
1632
|
+
}
|
|
1633
|
+
)
|
|
1634
|
+
}
|
|
1635
|
+
) : null
|
|
1636
|
+
] })
|
|
1637
|
+
]
|
|
1638
|
+
}
|
|
1639
|
+
);
|
|
1640
|
+
}
|
|
1641
|
+
var Toolbar = memo(forwardRef(ToolbarComponent));
|
|
1642
|
+
|
|
1643
|
+
// components/color-picker.tsx
|
|
1644
|
+
import { useCallback as useCallback3, useLayoutEffect as useLayoutEffect2, useRef as useRef3, useState as useState4 } from "react";
|
|
1645
|
+
import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
1646
|
+
function CopyableColorValue({
|
|
1647
|
+
id,
|
|
1648
|
+
value,
|
|
1649
|
+
copiedId,
|
|
1650
|
+
onCopy,
|
|
1651
|
+
onTooltipEnter,
|
|
1652
|
+
tooltip,
|
|
1653
|
+
className
|
|
1654
|
+
}) {
|
|
1655
|
+
const copied = copiedId === id;
|
|
1656
|
+
const showTooltip = tooltip.visibleTooltipId === id || copied && tooltip.visibleTooltipId === null;
|
|
1657
|
+
return /* @__PURE__ */ jsxs5(
|
|
1658
|
+
"span",
|
|
1659
|
+
{
|
|
1660
|
+
className: "msr:relative msr:inline-flex",
|
|
1661
|
+
onMouseLeave: tooltip.onTooltipLeave,
|
|
1662
|
+
children: [
|
|
1663
|
+
/* @__PURE__ */ jsx5(
|
|
1664
|
+
"button",
|
|
1665
|
+
{
|
|
1666
|
+
type: "button",
|
|
1667
|
+
className,
|
|
1668
|
+
onMouseEnter: () => onTooltipEnter(id),
|
|
1669
|
+
onFocus: () => onTooltipEnter(id),
|
|
1670
|
+
onBlur: tooltip.onTooltipLeave,
|
|
1671
|
+
onClick: onCopy,
|
|
1672
|
+
children: value
|
|
1673
|
+
}
|
|
1674
|
+
),
|
|
1675
|
+
/* @__PURE__ */ jsx5(
|
|
1676
|
+
Tooltip,
|
|
1677
|
+
{
|
|
1678
|
+
label: copied ? "Copied!" : "Click to copy",
|
|
1679
|
+
visible: showTooltip,
|
|
1680
|
+
instant: copied || tooltip.tooltipInstant,
|
|
1681
|
+
side: "bottom",
|
|
1682
|
+
className: "msr:z-10"
|
|
1683
|
+
}
|
|
681
1684
|
)
|
|
682
1685
|
]
|
|
683
1686
|
}
|
|
684
1687
|
);
|
|
685
1688
|
}
|
|
686
|
-
|
|
1689
|
+
function ColorPicker({
|
|
1690
|
+
active,
|
|
1691
|
+
sample,
|
|
1692
|
+
unsupported,
|
|
1693
|
+
formats,
|
|
1694
|
+
favoriteFormat,
|
|
1695
|
+
ownerWindow,
|
|
1696
|
+
toolbarRef,
|
|
1697
|
+
onClose
|
|
1698
|
+
}) {
|
|
1699
|
+
const panelRef = useRef3(null);
|
|
1700
|
+
const copyTimeoutRef = useRef3(null);
|
|
1701
|
+
const [copiedId, setCopiedId] = useState4(null);
|
|
1702
|
+
const tooltip = useTooltip();
|
|
1703
|
+
const copyValue = useCallback3(
|
|
1704
|
+
(id, value) => {
|
|
1705
|
+
const clipboardWrite = ownerWindow.navigator.clipboard?.writeText(value);
|
|
1706
|
+
void clipboardWrite?.catch(() => void 0);
|
|
1707
|
+
tooltip.onTooltipLeave();
|
|
1708
|
+
setCopiedId(id);
|
|
1709
|
+
if (copyTimeoutRef.current !== null) {
|
|
1710
|
+
ownerWindow.clearTimeout(copyTimeoutRef.current);
|
|
1711
|
+
}
|
|
1712
|
+
copyTimeoutRef.current = ownerWindow.setTimeout(() => {
|
|
1713
|
+
copyTimeoutRef.current = null;
|
|
1714
|
+
setCopiedId(null);
|
|
1715
|
+
}, 1500);
|
|
1716
|
+
},
|
|
1717
|
+
[ownerWindow, tooltip]
|
|
1718
|
+
);
|
|
1719
|
+
const handleTooltipEnter = useCallback3(
|
|
1720
|
+
(id) => {
|
|
1721
|
+
if (copiedId !== null && copiedId !== id) {
|
|
1722
|
+
if (copyTimeoutRef.current !== null) {
|
|
1723
|
+
ownerWindow.clearTimeout(copyTimeoutRef.current);
|
|
1724
|
+
copyTimeoutRef.current = null;
|
|
1725
|
+
}
|
|
1726
|
+
setCopiedId(null);
|
|
1727
|
+
}
|
|
1728
|
+
tooltip.onTooltipEnter(id);
|
|
1729
|
+
},
|
|
1730
|
+
[copiedId, ownerWindow, tooltip]
|
|
1731
|
+
);
|
|
1732
|
+
useLayoutEffect2(() => {
|
|
1733
|
+
if (!active) return;
|
|
1734
|
+
const panel = panelRef.current;
|
|
1735
|
+
const toolbar = toolbarRef.current;
|
|
1736
|
+
if (!panel || !toolbar) return;
|
|
1737
|
+
let frame = 0;
|
|
1738
|
+
const updatePosition = () => {
|
|
1739
|
+
const toolbarRect = toolbar.getBoundingClientRect();
|
|
1740
|
+
const panelRect = panel.getBoundingClientRect();
|
|
1741
|
+
const left = Math.min(
|
|
1742
|
+
Math.max(8, toolbarRect.left),
|
|
1743
|
+
ownerWindow.innerWidth - panelRect.width - 8
|
|
1744
|
+
);
|
|
1745
|
+
const belowTop = toolbarRect.bottom + 8;
|
|
1746
|
+
const aboveTop = toolbarRect.top - panelRect.height - 8;
|
|
1747
|
+
const top = belowTop + panelRect.height <= ownerWindow.innerHeight ? belowTop : Math.max(8, aboveTop);
|
|
1748
|
+
panel.style.left = `${left}px`;
|
|
1749
|
+
panel.style.top = `${top}px`;
|
|
1750
|
+
frame = ownerWindow.requestAnimationFrame(updatePosition);
|
|
1751
|
+
};
|
|
1752
|
+
frame = ownerWindow.requestAnimationFrame(updatePosition);
|
|
1753
|
+
return () => ownerWindow.cancelAnimationFrame(frame);
|
|
1754
|
+
}, [active, ownerWindow, toolbarRef, formats, sample, unsupported, favoriteFormat]);
|
|
1755
|
+
useLayoutEffect2(() => {
|
|
1756
|
+
return () => {
|
|
1757
|
+
if (copyTimeoutRef.current !== null) {
|
|
1758
|
+
ownerWindow.clearTimeout(copyTimeoutRef.current);
|
|
1759
|
+
}
|
|
1760
|
+
};
|
|
1761
|
+
}, [ownerWindow]);
|
|
1762
|
+
if (!active || !sample && !unsupported) return null;
|
|
1763
|
+
const headerFormat = formats.includes(favoriteFormat) ? favoriteFormat : formats[0];
|
|
1764
|
+
const secondaryFormats = headerFormat ? formats.filter((format) => format !== headerFormat) : [];
|
|
1765
|
+
return /* @__PURE__ */ jsx5(
|
|
1766
|
+
"div",
|
|
1767
|
+
{
|
|
1768
|
+
ref: panelRef,
|
|
1769
|
+
className: "mesurer-color-picker msr:pointer-events-auto msr:fixed msr:z-[80] msr:min-w-36 msr:rounded-lg msr:border msr:border-black/10 msr:bg-white msr:px-2 msr:py-2 msr:font-mono msr:text-[10px] msr:leading-4 msr:shadow-lg",
|
|
1770
|
+
role: "dialog",
|
|
1771
|
+
"aria-label": "Selected color values",
|
|
1772
|
+
onMouseLeave: tooltip.onTooltipContainerLeave,
|
|
1773
|
+
children: unsupported ? /* @__PURE__ */ jsxs5("div", { className: "msr:flex msr:items-start msr:gap-2", children: [
|
|
1774
|
+
/* @__PURE__ */ jsx5("span", { className: "msr:text-black/60", children: "Color picker is not supported in this browser." }),
|
|
1775
|
+
/* @__PURE__ */ jsx5(
|
|
1776
|
+
"button",
|
|
1777
|
+
{
|
|
1778
|
+
type: "button",
|
|
1779
|
+
className: "msr:text-black/45 msr:hover:text-black",
|
|
1780
|
+
"aria-label": "Close color picker message",
|
|
1781
|
+
onClick: onClose,
|
|
1782
|
+
children: "x"
|
|
1783
|
+
}
|
|
1784
|
+
)
|
|
1785
|
+
] }) : sample ? /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1786
|
+
headerFormat ? /* @__PURE__ */ jsxs5(
|
|
1787
|
+
"div",
|
|
1788
|
+
{
|
|
1789
|
+
className: secondaryFormats.length > 0 ? "msr:mb-1 msr:flex msr:items-center msr:gap-1.5 msr:border-b msr:border-black/8 msr:pb-1" : "msr:flex msr:items-center msr:gap-1.5",
|
|
1790
|
+
children: [
|
|
1791
|
+
/* @__PURE__ */ jsx5(
|
|
1792
|
+
"span",
|
|
1793
|
+
{
|
|
1794
|
+
className: "msr:size-3 msr:shrink-0 msr:rounded-full msr:border msr:border-black/15",
|
|
1795
|
+
style: { backgroundColor: colorToHex(sample) },
|
|
1796
|
+
"aria-hidden": "true"
|
|
1797
|
+
}
|
|
1798
|
+
),
|
|
1799
|
+
/* @__PURE__ */ jsx5(
|
|
1800
|
+
CopyableColorValue,
|
|
1801
|
+
{
|
|
1802
|
+
id: headerFormat,
|
|
1803
|
+
value: formatColor(sample, headerFormat),
|
|
1804
|
+
copiedId,
|
|
1805
|
+
onCopy: () => copyValue(headerFormat, formatColor(sample, headerFormat)),
|
|
1806
|
+
onTooltipEnter: handleTooltipEnter,
|
|
1807
|
+
tooltip,
|
|
1808
|
+
className: "msr:font-medium msr:tabular-nums msr:text-black msr:hover:underline"
|
|
1809
|
+
}
|
|
1810
|
+
)
|
|
1811
|
+
]
|
|
1812
|
+
}
|
|
1813
|
+
) : /* @__PURE__ */ jsx5("div", { className: "msr:flex msr:items-center", children: /* @__PURE__ */ jsx5(
|
|
1814
|
+
"span",
|
|
1815
|
+
{
|
|
1816
|
+
className: "msr:size-3 msr:shrink-0 msr:rounded-full msr:border msr:border-black/15",
|
|
1817
|
+
style: { backgroundColor: colorToHex(sample) },
|
|
1818
|
+
"aria-hidden": "true"
|
|
1819
|
+
}
|
|
1820
|
+
) }),
|
|
1821
|
+
secondaryFormats.map((format) => {
|
|
1822
|
+
const value = formatColor(sample, format);
|
|
1823
|
+
return /* @__PURE__ */ jsxs5("div", { className: "msr:flex msr:items-center msr:gap-2", children: [
|
|
1824
|
+
/* @__PURE__ */ jsx5("span", { className: "msr:w-9 msr:text-black/45", children: format }),
|
|
1825
|
+
/* @__PURE__ */ jsx5(
|
|
1826
|
+
CopyableColorValue,
|
|
1827
|
+
{
|
|
1828
|
+
id: format,
|
|
1829
|
+
value,
|
|
1830
|
+
copiedId,
|
|
1831
|
+
onCopy: () => copyValue(format, value),
|
|
1832
|
+
onTooltipEnter: handleTooltipEnter,
|
|
1833
|
+
tooltip,
|
|
1834
|
+
className: "msr:tabular-nums msr:text-black msr:hover:underline"
|
|
1835
|
+
}
|
|
1836
|
+
)
|
|
1837
|
+
] }, format);
|
|
1838
|
+
})
|
|
1839
|
+
] }) : null
|
|
1840
|
+
}
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
687
1843
|
|
|
688
1844
|
// components/rulers-overlay.tsx
|
|
689
|
-
import { memo as memo2, useRef as
|
|
690
|
-
import { jsx as
|
|
1845
|
+
import { memo as memo2, useEffect as useEffect2, useRef as useRef4, useState as useState5 } from "react";
|
|
1846
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
691
1847
|
var RULER_SIZE = 18;
|
|
692
1848
|
var RULER_LENGTH = 4e3;
|
|
693
1849
|
var TICK_STEP = 5;
|
|
1850
|
+
var RULER_EDGE_REVEAL_DISTANCE = 32;
|
|
1851
|
+
var RULER_FADE_MS = 100;
|
|
694
1852
|
var ticks = Array.from(
|
|
695
1853
|
{ length: RULER_LENGTH / TICK_STEP + 1 },
|
|
696
1854
|
(_, index) => index * TICK_STEP
|
|
697
1855
|
);
|
|
698
1856
|
var RulersOverlay = memo2(function RulersOverlay2({
|
|
1857
|
+
ownerWindow,
|
|
1858
|
+
settings,
|
|
699
1859
|
onStartGuide,
|
|
700
1860
|
onMoveGuide,
|
|
701
1861
|
onFinishGuide,
|
|
702
1862
|
onCancelGuide,
|
|
703
1863
|
guides,
|
|
704
|
-
selectedGuideIds
|
|
1864
|
+
selectedGuideIds,
|
|
1865
|
+
interactive = true,
|
|
1866
|
+
forceVisible = false
|
|
705
1867
|
}) {
|
|
706
|
-
const [dragPosition, setDragPosition] =
|
|
707
|
-
const [dragOrientation, setDragOrientation] =
|
|
708
|
-
const
|
|
1868
|
+
const [dragPosition, setDragPosition] = useState5(null);
|
|
1869
|
+
const [dragOrientation, setDragOrientation] = useState5(null);
|
|
1870
|
+
const [nearEdge, setNearEdge] = useState5(false);
|
|
1871
|
+
const dragRef = useRef4(null);
|
|
1872
|
+
useEffect2(() => {
|
|
1873
|
+
if (!settings.edgeReveal) return;
|
|
1874
|
+
const handlePointerMove = (event) => {
|
|
1875
|
+
const pointer = event;
|
|
1876
|
+
const nearHorizontalEdge = pointer.clientX <= RULER_EDGE_REVEAL_DISTANCE || pointer.clientX >= ownerWindow.innerWidth - RULER_EDGE_REVEAL_DISTANCE;
|
|
1877
|
+
const nearVerticalEdge = pointer.clientY <= RULER_EDGE_REVEAL_DISTANCE || pointer.clientY >= ownerWindow.innerHeight - RULER_EDGE_REVEAL_DISTANCE;
|
|
1878
|
+
setNearEdge(nearHorizontalEdge || nearVerticalEdge);
|
|
1879
|
+
};
|
|
1880
|
+
ownerWindow.document.addEventListener("pointermove", handlePointerMove, true);
|
|
1881
|
+
ownerWindow.document.addEventListener("mousemove", handlePointerMove, true);
|
|
1882
|
+
return () => {
|
|
1883
|
+
ownerWindow.document.removeEventListener("pointermove", handlePointerMove, true);
|
|
1884
|
+
ownerWindow.document.removeEventListener("mousemove", handlePointerMove, true);
|
|
1885
|
+
};
|
|
1886
|
+
}, [ownerWindow, settings.edgeReveal]);
|
|
1887
|
+
const showRulers = forceVisible || !settings.edgeReveal || nearEdge;
|
|
709
1888
|
const beginGuideDrag = (orientation, event) => {
|
|
710
1889
|
if (event.button !== 0) return;
|
|
711
1890
|
event.stopPropagation();
|
|
@@ -755,13 +1934,18 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
755
1934
|
const selectedHorizontalGuides = guides.filter(
|
|
756
1935
|
(guide) => guide.orientation === "horizontal" && selectedGuideIds.includes(guide.id)
|
|
757
1936
|
);
|
|
758
|
-
return /* @__PURE__ */
|
|
1937
|
+
return /* @__PURE__ */ jsxs6(
|
|
759
1938
|
"div",
|
|
760
1939
|
{
|
|
761
1940
|
"aria-hidden": "true",
|
|
1941
|
+
"data-mesurer-rulers": "true",
|
|
762
1942
|
className: "msr:pointer-events-none msr:absolute msr:inset-0 msr:select-none msr:text-[9px] msr:text-[#64748b]",
|
|
1943
|
+
style: {
|
|
1944
|
+
opacity: showRulers ? settings.opacity : 0,
|
|
1945
|
+
transition: `opacity ${RULER_FADE_MS}ms ease`
|
|
1946
|
+
},
|
|
763
1947
|
children: [
|
|
764
|
-
/* @__PURE__ */
|
|
1948
|
+
/* @__PURE__ */ jsx6(
|
|
765
1949
|
"div",
|
|
766
1950
|
{
|
|
767
1951
|
className: "msr:absolute msr:left-[18px] msr:right-0 msr:top-0 msr:overflow-hidden msr:bg-white",
|
|
@@ -769,13 +1953,13 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
769
1953
|
boxShadow: "0 1px 3px rgba(0, 0, 0, 0.12)",
|
|
770
1954
|
height: RULER_SIZE,
|
|
771
1955
|
cursor: "ns-resize",
|
|
772
|
-
pointerEvents: "auto"
|
|
1956
|
+
pointerEvents: showRulers && interactive ? "auto" : "none"
|
|
773
1957
|
},
|
|
774
1958
|
onPointerDown: (event) => beginGuideDrag("horizontal", event),
|
|
775
1959
|
onPointerMove: moveGuide,
|
|
776
1960
|
onPointerUp: finishGuideDrag,
|
|
777
1961
|
onPointerCancel: cancelGuideDrag,
|
|
778
|
-
children: /* @__PURE__ */
|
|
1962
|
+
children: /* @__PURE__ */ jsxs6(
|
|
779
1963
|
"svg",
|
|
780
1964
|
{
|
|
781
1965
|
className: "msr:block msr:h-6",
|
|
@@ -783,7 +1967,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
783
1967
|
height: RULER_SIZE,
|
|
784
1968
|
viewBox: `0 0 ${RULER_LENGTH} ${RULER_SIZE}`,
|
|
785
1969
|
children: [
|
|
786
|
-
/* @__PURE__ */
|
|
1970
|
+
/* @__PURE__ */ jsx6("defs", { children: /* @__PURE__ */ jsxs6(
|
|
787
1971
|
"linearGradient",
|
|
788
1972
|
{
|
|
789
1973
|
id: "ruler-label-fade-x",
|
|
@@ -791,18 +1975,18 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
791
1975
|
x2: "100%",
|
|
792
1976
|
gradientUnits: "objectBoundingBox",
|
|
793
1977
|
children: [
|
|
794
|
-
/* @__PURE__ */
|
|
795
|
-
/* @__PURE__ */
|
|
796
|
-
/* @__PURE__ */
|
|
797
|
-
/* @__PURE__ */
|
|
1978
|
+
/* @__PURE__ */ jsx6("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
1979
|
+
/* @__PURE__ */ jsx6("stop", { offset: "0.2", stopColor: "white" }),
|
|
1980
|
+
/* @__PURE__ */ jsx6("stop", { offset: "0.8", stopColor: "white" }),
|
|
1981
|
+
/* @__PURE__ */ jsx6("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
|
|
798
1982
|
]
|
|
799
1983
|
}
|
|
800
1984
|
) }),
|
|
801
1985
|
ticks.map((x) => {
|
|
802
1986
|
const major = x % 100 === 0;
|
|
803
1987
|
const medium = x % 50 === 0;
|
|
804
|
-
return /* @__PURE__ */
|
|
805
|
-
/* @__PURE__ */
|
|
1988
|
+
return /* @__PURE__ */ jsxs6("g", { children: [
|
|
1989
|
+
/* @__PURE__ */ jsx6(
|
|
806
1990
|
"line",
|
|
807
1991
|
{
|
|
808
1992
|
x1: x,
|
|
@@ -813,11 +1997,11 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
813
1997
|
strokeWidth: "1"
|
|
814
1998
|
}
|
|
815
1999
|
),
|
|
816
|
-
major ? /* @__PURE__ */
|
|
2000
|
+
major ? /* @__PURE__ */ jsx6("text", { x, y: "8", textAnchor: "middle", fill: "currentColor", children: x }) : null
|
|
817
2001
|
] }, x);
|
|
818
2002
|
}),
|
|
819
|
-
selectedVerticalGuides.map((guide) => /* @__PURE__ */
|
|
820
|
-
/* @__PURE__ */
|
|
2003
|
+
selectedVerticalGuides.map((guide) => /* @__PURE__ */ jsxs6("g", { children: [
|
|
2004
|
+
/* @__PURE__ */ jsx6(
|
|
821
2005
|
"rect",
|
|
822
2006
|
{
|
|
823
2007
|
x: guide.position - RULER_SIZE - 8,
|
|
@@ -827,7 +2011,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
827
2011
|
fill: "url(#ruler-label-fade-x)"
|
|
828
2012
|
}
|
|
829
2013
|
),
|
|
830
|
-
/* @__PURE__ */
|
|
2014
|
+
/* @__PURE__ */ jsx6(
|
|
831
2015
|
"text",
|
|
832
2016
|
{
|
|
833
2017
|
x: guide.position - RULER_SIZE + 16,
|
|
@@ -839,8 +2023,8 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
839
2023
|
}
|
|
840
2024
|
)
|
|
841
2025
|
] }, guide.id)),
|
|
842
|
-
dragOrientation === "vertical" && dragPosition !== null ? /* @__PURE__ */
|
|
843
|
-
/* @__PURE__ */
|
|
2026
|
+
dragOrientation === "vertical" && dragPosition !== null ? /* @__PURE__ */ jsxs6("g", { children: [
|
|
2027
|
+
/* @__PURE__ */ jsx6(
|
|
844
2028
|
"rect",
|
|
845
2029
|
{
|
|
846
2030
|
x: dragPosition - RULER_SIZE - 8,
|
|
@@ -850,7 +2034,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
850
2034
|
fill: "url(#ruler-label-fade-x)"
|
|
851
2035
|
}
|
|
852
2036
|
),
|
|
853
|
-
/* @__PURE__ */
|
|
2037
|
+
/* @__PURE__ */ jsx6(
|
|
854
2038
|
"text",
|
|
855
2039
|
{
|
|
856
2040
|
x: dragPosition - RULER_SIZE + 16,
|
|
@@ -867,7 +2051,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
867
2051
|
)
|
|
868
2052
|
}
|
|
869
2053
|
),
|
|
870
|
-
/* @__PURE__ */
|
|
2054
|
+
/* @__PURE__ */ jsx6(
|
|
871
2055
|
"div",
|
|
872
2056
|
{
|
|
873
2057
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:top-[18px] msr:w-[18px] msr:overflow-hidden msr:bg-white",
|
|
@@ -875,13 +2059,13 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
875
2059
|
boxShadow: "1px 0 3px rgba(0, 0, 0, 0.12)",
|
|
876
2060
|
width: RULER_SIZE,
|
|
877
2061
|
cursor: "ew-resize",
|
|
878
|
-
pointerEvents: "auto"
|
|
2062
|
+
pointerEvents: showRulers && interactive ? "auto" : "none"
|
|
879
2063
|
},
|
|
880
2064
|
onPointerDown: (event) => beginGuideDrag("vertical", event),
|
|
881
2065
|
onPointerMove: moveGuide,
|
|
882
2066
|
onPointerUp: finishGuideDrag,
|
|
883
2067
|
onPointerCancel: cancelGuideDrag,
|
|
884
|
-
children: /* @__PURE__ */
|
|
2068
|
+
children: /* @__PURE__ */ jsxs6(
|
|
885
2069
|
"svg",
|
|
886
2070
|
{
|
|
887
2071
|
className: "msr:block msr:w-6",
|
|
@@ -889,7 +2073,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
889
2073
|
height: RULER_LENGTH,
|
|
890
2074
|
viewBox: `0 0 ${RULER_SIZE} ${RULER_LENGTH}`,
|
|
891
2075
|
children: [
|
|
892
|
-
/* @__PURE__ */
|
|
2076
|
+
/* @__PURE__ */ jsx6("defs", { children: /* @__PURE__ */ jsxs6(
|
|
893
2077
|
"linearGradient",
|
|
894
2078
|
{
|
|
895
2079
|
id: "ruler-label-fade-y",
|
|
@@ -897,18 +2081,18 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
897
2081
|
y2: "100%",
|
|
898
2082
|
gradientUnits: "objectBoundingBox",
|
|
899
2083
|
children: [
|
|
900
|
-
/* @__PURE__ */
|
|
901
|
-
/* @__PURE__ */
|
|
902
|
-
/* @__PURE__ */
|
|
903
|
-
/* @__PURE__ */
|
|
2084
|
+
/* @__PURE__ */ jsx6("stop", { offset: "0", stopColor: "white", stopOpacity: "0" }),
|
|
2085
|
+
/* @__PURE__ */ jsx6("stop", { offset: "0.2", stopColor: "white" }),
|
|
2086
|
+
/* @__PURE__ */ jsx6("stop", { offset: "0.8", stopColor: "white" }),
|
|
2087
|
+
/* @__PURE__ */ jsx6("stop", { offset: "1", stopColor: "white", stopOpacity: "0" })
|
|
904
2088
|
]
|
|
905
2089
|
}
|
|
906
2090
|
) }),
|
|
907
2091
|
ticks.map((y) => {
|
|
908
2092
|
const major = y % 100 === 0;
|
|
909
2093
|
const medium = y % 50 === 0;
|
|
910
|
-
return /* @__PURE__ */
|
|
911
|
-
/* @__PURE__ */
|
|
2094
|
+
return /* @__PURE__ */ jsxs6("g", { children: [
|
|
2095
|
+
/* @__PURE__ */ jsx6(
|
|
912
2096
|
"line",
|
|
913
2097
|
{
|
|
914
2098
|
x1: RULER_SIZE,
|
|
@@ -919,7 +2103,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
919
2103
|
strokeWidth: "1"
|
|
920
2104
|
}
|
|
921
2105
|
),
|
|
922
|
-
major ? /* @__PURE__ */
|
|
2106
|
+
major ? /* @__PURE__ */ jsx6(
|
|
923
2107
|
"text",
|
|
924
2108
|
{
|
|
925
2109
|
x: "8",
|
|
@@ -931,8 +2115,8 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
931
2115
|
) : null
|
|
932
2116
|
] }, y);
|
|
933
2117
|
}),
|
|
934
|
-
selectedHorizontalGuides.map((guide) => /* @__PURE__ */
|
|
935
|
-
/* @__PURE__ */
|
|
2118
|
+
selectedHorizontalGuides.map((guide) => /* @__PURE__ */ jsxs6("g", { children: [
|
|
2119
|
+
/* @__PURE__ */ jsx6(
|
|
936
2120
|
"rect",
|
|
937
2121
|
{
|
|
938
2122
|
x: "-3",
|
|
@@ -942,7 +2126,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
942
2126
|
fill: "url(#ruler-label-fade-y)"
|
|
943
2127
|
}
|
|
944
2128
|
),
|
|
945
|
-
/* @__PURE__ */
|
|
2129
|
+
/* @__PURE__ */ jsx6(
|
|
946
2130
|
"text",
|
|
947
2131
|
{
|
|
948
2132
|
x: "9",
|
|
@@ -955,8 +2139,8 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
955
2139
|
}
|
|
956
2140
|
)
|
|
957
2141
|
] }, guide.id)),
|
|
958
|
-
dragOrientation === "horizontal" && dragPosition !== null ? /* @__PURE__ */
|
|
959
|
-
/* @__PURE__ */
|
|
2142
|
+
dragOrientation === "horizontal" && dragPosition !== null ? /* @__PURE__ */ jsxs6("g", { children: [
|
|
2143
|
+
/* @__PURE__ */ jsx6(
|
|
960
2144
|
"rect",
|
|
961
2145
|
{
|
|
962
2146
|
x: "-3",
|
|
@@ -966,7 +2150,7 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
966
2150
|
fill: "url(#ruler-label-fade-y)"
|
|
967
2151
|
}
|
|
968
2152
|
),
|
|
969
|
-
/* @__PURE__ */
|
|
2153
|
+
/* @__PURE__ */ jsx6(
|
|
970
2154
|
"text",
|
|
971
2155
|
{
|
|
972
2156
|
x: "9",
|
|
@@ -984,34 +2168,34 @@ var RulersOverlay = memo2(function RulersOverlay2({
|
|
|
984
2168
|
)
|
|
985
2169
|
}
|
|
986
2170
|
),
|
|
987
|
-
/* @__PURE__ */
|
|
2171
|
+
/* @__PURE__ */ jsx6("div", { className: "msr:absolute msr:left-0 msr:top-0 msr:size-[18px] msr:bg-white" })
|
|
988
2172
|
]
|
|
989
2173
|
}
|
|
990
2174
|
);
|
|
991
2175
|
});
|
|
992
2176
|
|
|
993
2177
|
// hooks/use-drag-state.ts
|
|
994
|
-
import { useState as
|
|
2178
|
+
import { useState as useState6 } from "react";
|
|
995
2179
|
var useDragState = () => {
|
|
996
|
-
const [start, setStart] =
|
|
997
|
-
const [end, setEnd] =
|
|
998
|
-
const [isDragging, setIsDragging] =
|
|
2180
|
+
const [start, setStart] = useState6(null);
|
|
2181
|
+
const [end, setEnd] = useState6(null);
|
|
2182
|
+
const [isDragging, setIsDragging] = useState6(false);
|
|
999
2183
|
return { start, setStart, end, setEnd, isDragging, setIsDragging };
|
|
1000
2184
|
};
|
|
1001
2185
|
|
|
1002
2186
|
// hooks/use-guide-drag-hold.ts
|
|
1003
|
-
import { useCallback as
|
|
2187
|
+
import { useCallback as useCallback4, useRef as useRef5 } from "react";
|
|
1004
2188
|
var useGuideDragHold = (eventTarget) => {
|
|
1005
|
-
const guideDragHoldTimerRef =
|
|
1006
|
-
const guideDragHoldGuideIdRef =
|
|
1007
|
-
const clearGuideDragHold =
|
|
2189
|
+
const guideDragHoldTimerRef = useRef5(null);
|
|
2190
|
+
const guideDragHoldGuideIdRef = useRef5(null);
|
|
2191
|
+
const clearGuideDragHold = useCallback4(() => {
|
|
1008
2192
|
if (guideDragHoldTimerRef.current !== null) {
|
|
1009
2193
|
eventTarget.clearTimeout(guideDragHoldTimerRef.current);
|
|
1010
2194
|
guideDragHoldTimerRef.current = null;
|
|
1011
2195
|
}
|
|
1012
2196
|
guideDragHoldGuideIdRef.current = null;
|
|
1013
2197
|
}, []);
|
|
1014
|
-
const scheduleGuideDragHold =
|
|
2198
|
+
const scheduleGuideDragHold = useCallback4(
|
|
1015
2199
|
(id, onHold) => {
|
|
1016
2200
|
clearGuideDragHold();
|
|
1017
2201
|
guideDragHoldGuideIdRef.current = id;
|
|
@@ -1030,11 +2214,11 @@ var useGuideDragHold = (eventTarget) => {
|
|
|
1030
2214
|
};
|
|
1031
2215
|
|
|
1032
2216
|
// hooks/use-guide-state.ts
|
|
1033
|
-
import { useState as
|
|
2217
|
+
import { useState as useState7 } from "react";
|
|
1034
2218
|
var useGuideState = (options = {}) => {
|
|
1035
|
-
const [guides, setGuides] =
|
|
1036
|
-
const [draggingGuideId, setDraggingGuideId] =
|
|
1037
|
-
const [selectedGuideIds, setSelectedGuideIds] =
|
|
2219
|
+
const [guides, setGuides] = useState7(options.initialGuides ?? []);
|
|
2220
|
+
const [draggingGuideId, setDraggingGuideId] = useState7(null);
|
|
2221
|
+
const [selectedGuideIds, setSelectedGuideIds] = useState7(
|
|
1038
2222
|
options.initialSelectedGuideIds ?? []
|
|
1039
2223
|
);
|
|
1040
2224
|
return {
|
|
@@ -1048,67 +2232,91 @@ var useGuideState = (options = {}) => {
|
|
|
1048
2232
|
};
|
|
1049
2233
|
|
|
1050
2234
|
// hooks/use-hotkeys.ts
|
|
1051
|
-
import { useEffect } from "react";
|
|
2235
|
+
import { useEffect as useEffect3, useRef as useRef6 } from "react";
|
|
1052
2236
|
var useHotkeys = (options) => {
|
|
1053
|
-
|
|
2237
|
+
const optionsRef = useRef6(options);
|
|
2238
|
+
optionsRef.current = options;
|
|
2239
|
+
useEffect3(() => {
|
|
1054
2240
|
const target = options.eventTarget;
|
|
1055
2241
|
const handleKeyDown = (event) => {
|
|
2242
|
+
const current = optionsRef.current;
|
|
1056
2243
|
if (event.key === "Escape") {
|
|
1057
|
-
|
|
2244
|
+
if (current.isSettingsOpen()) {
|
|
2245
|
+
current.onToggleSettings();
|
|
2246
|
+
return;
|
|
2247
|
+
}
|
|
2248
|
+
if (current.isColorPickerActive()) {
|
|
2249
|
+
current.onCloseColorPicker();
|
|
2250
|
+
return;
|
|
2251
|
+
}
|
|
2252
|
+
current.clearAll();
|
|
1058
2253
|
return;
|
|
1059
2254
|
}
|
|
1060
2255
|
if (event.metaKey || event.ctrlKey) {
|
|
2256
|
+
if (event.key === ",") {
|
|
2257
|
+
event.preventDefault();
|
|
2258
|
+
current.onToggleSettings();
|
|
2259
|
+
current.onInteract();
|
|
2260
|
+
return;
|
|
2261
|
+
}
|
|
1061
2262
|
if (event.key.toLowerCase() !== "z") return;
|
|
1062
2263
|
if (event.shiftKey) {
|
|
1063
2264
|
event.preventDefault();
|
|
1064
|
-
|
|
2265
|
+
current.redo();
|
|
1065
2266
|
return;
|
|
1066
2267
|
}
|
|
1067
2268
|
event.preventDefault();
|
|
1068
|
-
|
|
2269
|
+
current.undo();
|
|
1069
2270
|
return;
|
|
1070
2271
|
}
|
|
1071
2272
|
if (event.key.toLowerCase() === "m") {
|
|
1072
|
-
|
|
2273
|
+
current.setEnabled((prev) => !prev);
|
|
1073
2274
|
}
|
|
1074
2275
|
const key = event.key.toLowerCase();
|
|
1075
|
-
if (
|
|
2276
|
+
if (key === "p") {
|
|
2277
|
+
event.preventDefault();
|
|
2278
|
+
current.onColorPicker();
|
|
2279
|
+
current.onInteract();
|
|
2280
|
+
return;
|
|
2281
|
+
}
|
|
2282
|
+
if (key === "x") {
|
|
2283
|
+
current.onToggleXray();
|
|
2284
|
+
current.onInteract();
|
|
2285
|
+
return;
|
|
2286
|
+
}
|
|
2287
|
+
if (current.isOverlayActive()) {
|
|
1076
2288
|
if (key === "a") {
|
|
1077
|
-
|
|
2289
|
+
current.setToolMode(
|
|
1078
2290
|
(prev) => prev === "text-inspector" ? "none" : "text-inspector"
|
|
1079
2291
|
);
|
|
1080
|
-
|
|
2292
|
+
current.onInteract();
|
|
1081
2293
|
}
|
|
1082
2294
|
if (key === "s") {
|
|
1083
|
-
|
|
1084
|
-
|
|
2295
|
+
current.setToolMode((prev) => prev === "select" ? "none" : "select");
|
|
2296
|
+
current.onInteract();
|
|
1085
2297
|
}
|
|
1086
2298
|
if (key === "g") {
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
}
|
|
1090
|
-
if (key === "x") {
|
|
1091
|
-
options.setToolMode((prev) => prev === "xray" ? "none" : "xray");
|
|
1092
|
-
options.onInteract();
|
|
2299
|
+
current.setToolMode((prev) => prev === "guides" ? "none" : "guides");
|
|
2300
|
+
current.onInteract();
|
|
1093
2301
|
}
|
|
1094
2302
|
if (key === "r") {
|
|
1095
|
-
|
|
1096
|
-
|
|
2303
|
+
current.setRulersVisible((prev) => !prev);
|
|
2304
|
+
current.onInteract();
|
|
1097
2305
|
}
|
|
1098
2306
|
if (key === "h") {
|
|
1099
|
-
|
|
1100
|
-
|
|
2307
|
+
current.setGuideOrientation("horizontal");
|
|
2308
|
+
current.onInteract();
|
|
1101
2309
|
}
|
|
1102
2310
|
if (key === "v") {
|
|
1103
|
-
|
|
1104
|
-
|
|
2311
|
+
current.setGuideOrientation("vertical");
|
|
2312
|
+
current.onInteract();
|
|
1105
2313
|
}
|
|
1106
2314
|
}
|
|
1107
2315
|
if (event.key === "Alt") {
|
|
1108
|
-
|
|
2316
|
+
current.setAltPressed(true);
|
|
1109
2317
|
}
|
|
1110
2318
|
if (event.key === "Backspace" || event.key === "Delete") {
|
|
1111
|
-
const removed =
|
|
2319
|
+
const removed = current.removeSelectedGuides();
|
|
1112
2320
|
if (removed) {
|
|
1113
2321
|
event.preventDefault();
|
|
1114
2322
|
}
|
|
@@ -1116,7 +2324,7 @@ var useHotkeys = (options) => {
|
|
|
1116
2324
|
};
|
|
1117
2325
|
const handleKeyUp = (event) => {
|
|
1118
2326
|
if (event.key === "Alt") {
|
|
1119
|
-
|
|
2327
|
+
optionsRef.current.setAltPressed(false);
|
|
1120
2328
|
}
|
|
1121
2329
|
};
|
|
1122
2330
|
target.addEventListener("keydown", handleKeyDown);
|
|
@@ -1125,11 +2333,11 @@ var useHotkeys = (options) => {
|
|
|
1125
2333
|
target.removeEventListener("keydown", handleKeyDown);
|
|
1126
2334
|
target.removeEventListener("keyup", handleKeyUp);
|
|
1127
2335
|
};
|
|
1128
|
-
}, [options]);
|
|
2336
|
+
}, [options.eventTarget]);
|
|
1129
2337
|
};
|
|
1130
2338
|
|
|
1131
2339
|
// hooks/use-live-element-tracking.ts
|
|
1132
|
-
import { useEffect as
|
|
2340
|
+
import { useEffect as useEffect4, useRef as useRef7 } from "react";
|
|
1133
2341
|
|
|
1134
2342
|
// core/geometry.ts
|
|
1135
2343
|
var getViewportSize = (ownerWindow) => ({
|
|
@@ -1155,7 +2363,7 @@ var getRectFromPoints = (start, end) => {
|
|
|
1155
2363
|
const height = Math.abs(start.y - end.y);
|
|
1156
2364
|
return { left, top, width, height };
|
|
1157
2365
|
};
|
|
1158
|
-
var
|
|
2366
|
+
var clamp2 = (value, min, max) => Math.max(min, Math.min(max, value));
|
|
1159
2367
|
var rectsOverlap = (rectA, rectB) => rectA.left < rectB.left + rectB.width && rectA.left + rectA.width > rectB.left && rectA.top < rectB.top + rectB.height && rectA.top + rectA.height > rectB.top;
|
|
1160
2368
|
var rectArea = (rect) => rect.width * rect.height;
|
|
1161
2369
|
var intersectionArea = (rectA, rectB) => {
|
|
@@ -1219,10 +2427,10 @@ var getDistanceOverlay = (rectA, rectB, elementRefA, elementRefB, ownerWindow =
|
|
|
1219
2427
|
}
|
|
1220
2428
|
}
|
|
1221
2429
|
const normalizedConnectors = connectors.map((segment) => ({
|
|
1222
|
-
x1:
|
|
1223
|
-
y1:
|
|
1224
|
-
x2:
|
|
1225
|
-
y2:
|
|
2430
|
+
x1: clamp2(segment.x1, 0, ownerWindow.innerWidth),
|
|
2431
|
+
y1: clamp2(segment.y1, 0, ownerWindow.innerHeight),
|
|
2432
|
+
x2: clamp2(segment.x2, 0, ownerWindow.innerWidth),
|
|
2433
|
+
y2: clamp2(segment.y2, 0, ownerWindow.innerHeight)
|
|
1226
2434
|
})).filter(
|
|
1227
2435
|
(segment) => Math.abs(segment.x1 - segment.x2) > 0.5 || Math.abs(segment.y1 - segment.y2) > 0.5
|
|
1228
2436
|
);
|
|
@@ -1389,19 +2597,23 @@ var updateMeasurementForResize = (measurement, viewport = getViewportSize(), own
|
|
|
1389
2597
|
|
|
1390
2598
|
// hooks/use-live-element-tracking.ts
|
|
1391
2599
|
var useLiveElementTracking = (params) => {
|
|
1392
|
-
const
|
|
1393
|
-
|
|
2600
|
+
const paramsRef = useRef7(params);
|
|
2601
|
+
paramsRef.current = params;
|
|
2602
|
+
const frameRef = useRef7(null);
|
|
2603
|
+
useEffect4(() => {
|
|
2604
|
+
const ownerWindow = params.window;
|
|
1394
2605
|
if (!params.enabled) {
|
|
1395
2606
|
if (frameRef.current) {
|
|
1396
|
-
|
|
2607
|
+
ownerWindow.cancelAnimationFrame(frameRef.current);
|
|
1397
2608
|
}
|
|
1398
2609
|
frameRef.current = null;
|
|
1399
2610
|
return;
|
|
1400
2611
|
}
|
|
1401
2612
|
const tick = () => {
|
|
1402
|
-
|
|
2613
|
+
const current = paramsRef.current;
|
|
2614
|
+
current.setMeasurements(
|
|
1403
2615
|
(prev) => prev.map((measurement) => {
|
|
1404
|
-
if (!measurement.elementRef || !
|
|
2616
|
+
if (!measurement.elementRef || !current.document.contains(measurement.elementRef)) {
|
|
1405
2617
|
return measurement;
|
|
1406
2618
|
}
|
|
1407
2619
|
const rect = getRectFromDom(measurement.elementRef);
|
|
@@ -1414,8 +2626,8 @@ var useLiveElementTracking = (params) => {
|
|
|
1414
2626
|
};
|
|
1415
2627
|
})
|
|
1416
2628
|
);
|
|
1417
|
-
|
|
1418
|
-
if (!prev?.elementRef || !
|
|
2629
|
+
current.setActiveMeasurement((prev) => {
|
|
2630
|
+
if (!prev?.elementRef || !current.document.contains(prev.elementRef))
|
|
1419
2631
|
return prev;
|
|
1420
2632
|
const rect = getRectFromDom(prev.elementRef);
|
|
1421
2633
|
if (rectAlmostEqual(rect, prev.rect)) return prev;
|
|
@@ -1426,10 +2638,10 @@ var useLiveElementTracking = (params) => {
|
|
|
1426
2638
|
originRect: void 0
|
|
1427
2639
|
};
|
|
1428
2640
|
});
|
|
1429
|
-
|
|
2641
|
+
current.setHeldDistances(
|
|
1430
2642
|
(prev) => prev.map((distance) => {
|
|
1431
|
-
const canTrackA = distance.elementRefA &&
|
|
1432
|
-
const canTrackB = distance.elementRefB &&
|
|
2643
|
+
const canTrackA = distance.elementRefA && current.document.contains(distance.elementRefA);
|
|
2644
|
+
const canTrackB = distance.elementRefB && current.document.contains(distance.elementRefB);
|
|
1433
2645
|
if (!canTrackA && !canTrackB) return distance;
|
|
1434
2646
|
const rectA = canTrackA ? getRectFromDom(distance.elementRefA) : distance.rectA;
|
|
1435
2647
|
const rectB = canTrackB ? getRectFromDom(distance.elementRefB) : distance.rectB;
|
|
@@ -1441,7 +2653,7 @@ var useLiveElementTracking = (params) => {
|
|
|
1441
2653
|
rectB,
|
|
1442
2654
|
distance.elementRefA,
|
|
1443
2655
|
distance.elementRefB,
|
|
1444
|
-
|
|
2656
|
+
ownerWindow
|
|
1445
2657
|
);
|
|
1446
2658
|
return {
|
|
1447
2659
|
...updated,
|
|
@@ -1449,62 +2661,71 @@ var useLiveElementTracking = (params) => {
|
|
|
1449
2661
|
};
|
|
1450
2662
|
})
|
|
1451
2663
|
);
|
|
1452
|
-
const selected =
|
|
1453
|
-
if (selected &&
|
|
1454
|
-
|
|
1455
|
-
const next = getInspectMeasurement(selected,
|
|
2664
|
+
const selected = current.selectedElementRef.current;
|
|
2665
|
+
if (current.selectionEnabled && selected && current.document.contains(selected)) {
|
|
2666
|
+
current.setSelectedMeasurement((prev) => {
|
|
2667
|
+
const next = getInspectMeasurement(selected, ownerWindow);
|
|
1456
2668
|
if (prev && rectAlmostEqual(prev.rect, next.rect)) return prev;
|
|
1457
2669
|
return next;
|
|
1458
2670
|
});
|
|
1459
2671
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
2672
|
+
if (current.selectionEnabled) {
|
|
2673
|
+
current.setSelectedMeasurements(
|
|
2674
|
+
(prev) => prev.map((measurement) => {
|
|
2675
|
+
if (!measurement.elementRef || !current.document.contains(measurement.elementRef)) {
|
|
2676
|
+
return measurement;
|
|
2677
|
+
}
|
|
2678
|
+
const next = getInspectMeasurement(measurement.elementRef, ownerWindow);
|
|
2679
|
+
if (rectAlmostEqual(next.rect, measurement.rect)) return measurement;
|
|
2680
|
+
return {
|
|
2681
|
+
...next,
|
|
2682
|
+
id: measurement.id
|
|
2683
|
+
};
|
|
2684
|
+
})
|
|
2685
|
+
);
|
|
2686
|
+
}
|
|
2687
|
+
const hover = current.hoverElementRef.current;
|
|
2688
|
+
if (current.selectionEnabled && hover && current.document.contains(hover)) {
|
|
1475
2689
|
const rect = getRectFromDom(hover);
|
|
1476
|
-
|
|
2690
|
+
current.setHoverRect(
|
|
1477
2691
|
(prev) => prev && rectAlmostEqual(prev, rect) ? prev : rect
|
|
1478
2692
|
);
|
|
1479
2693
|
}
|
|
1480
|
-
frameRef.current =
|
|
2694
|
+
frameRef.current = ownerWindow.requestAnimationFrame(tick);
|
|
1481
2695
|
};
|
|
1482
|
-
frameRef.current =
|
|
2696
|
+
frameRef.current = ownerWindow.requestAnimationFrame(tick);
|
|
1483
2697
|
return () => {
|
|
1484
2698
|
if (frameRef.current) {
|
|
1485
|
-
|
|
2699
|
+
ownerWindow.cancelAnimationFrame(frameRef.current);
|
|
1486
2700
|
}
|
|
1487
2701
|
frameRef.current = null;
|
|
1488
2702
|
};
|
|
1489
|
-
}, [params]);
|
|
2703
|
+
}, [params.enabled, params.window]);
|
|
1490
2704
|
};
|
|
1491
2705
|
|
|
1492
2706
|
// hooks/use-measure-toggles.ts
|
|
1493
|
-
import { useState as
|
|
2707
|
+
import { useState as useState8 } from "react";
|
|
1494
2708
|
var useMeasureToggles = (options = {}) => {
|
|
1495
|
-
const [enabled, setEnabled] =
|
|
1496
|
-
const [altPressed, setAltPressed] =
|
|
1497
|
-
const [toolMode, setToolMode] =
|
|
2709
|
+
const [enabled, setEnabled] = useState8(options.initialEnabled ?? true);
|
|
2710
|
+
const [altPressed, setAltPressed] = useState8(false);
|
|
2711
|
+
const [toolMode, setToolMode] = useState8(
|
|
1498
2712
|
options.initialToolMode ?? "none"
|
|
1499
2713
|
);
|
|
1500
|
-
const [rulersVisible, setRulersVisible] =
|
|
2714
|
+
const [rulersVisible, setRulersVisible] = useState8(
|
|
1501
2715
|
options.initialRulersVisible ?? false
|
|
1502
2716
|
);
|
|
1503
2717
|
const holdEnabled = false;
|
|
1504
|
-
const multiMeasureEnabled =
|
|
1505
|
-
|
|
2718
|
+
const [multiMeasureEnabled, setMultiMeasureEnabled] = useState8(
|
|
2719
|
+
options.initialMultiMeasureEnabled ?? false
|
|
2720
|
+
);
|
|
2721
|
+
const [snapGuidesEnabled, setSnapGuidesEnabled] = useState8(
|
|
2722
|
+
options.initialSnapGuidesEnabled ?? true
|
|
2723
|
+
);
|
|
2724
|
+
const [selectNewGuideEnabled, setSelectNewGuideEnabled] = useState8(
|
|
2725
|
+
options.initialSelectNewGuideEnabled ?? true
|
|
2726
|
+
);
|
|
1506
2727
|
const guidesEnabled = toolMode === "guides";
|
|
1507
|
-
const snapEnabled = true;
|
|
2728
|
+
const [snapEnabled, setSnapEnabled] = useState8(options.initialSnapEnabled ?? true);
|
|
1508
2729
|
return {
|
|
1509
2730
|
enabled,
|
|
1510
2731
|
setEnabled,
|
|
@@ -1518,21 +2739,26 @@ var useMeasureToggles = (options = {}) => {
|
|
|
1518
2739
|
guidesEnabled,
|
|
1519
2740
|
multiMeasureEnabled,
|
|
1520
2741
|
snapGuidesEnabled,
|
|
1521
|
-
|
|
2742
|
+
setSnapGuidesEnabled,
|
|
2743
|
+
selectNewGuideEnabled,
|
|
2744
|
+
setSelectNewGuideEnabled,
|
|
2745
|
+
snapEnabled,
|
|
2746
|
+
setSnapEnabled,
|
|
2747
|
+
setMultiMeasureEnabled
|
|
1522
2748
|
};
|
|
1523
2749
|
};
|
|
1524
2750
|
|
|
1525
2751
|
// hooks/use-measurement-state.ts
|
|
1526
|
-
import { useState as
|
|
2752
|
+
import { useState as useState9 } from "react";
|
|
1527
2753
|
var useMeasurementState = (options = {}) => {
|
|
1528
|
-
const [activeMeasurement, setActiveMeasurement] =
|
|
1529
|
-
const [measurements, setMeasurements] =
|
|
2754
|
+
const [activeMeasurement, setActiveMeasurement] = useState9(options.initialActiveMeasurement ?? null);
|
|
2755
|
+
const [measurements, setMeasurements] = useState9(
|
|
1530
2756
|
options.initialMeasurements ?? []
|
|
1531
2757
|
);
|
|
1532
|
-
const [selectedMeasurement, setSelectedMeasurement] =
|
|
1533
|
-
const [selectedMeasurements, setSelectedMeasurements] =
|
|
1534
|
-
const [hoverRect, setHoverRect] =
|
|
1535
|
-
const [heldDistances, setHeldDistances] =
|
|
2758
|
+
const [selectedMeasurement, setSelectedMeasurement] = useState9(null);
|
|
2759
|
+
const [selectedMeasurements, setSelectedMeasurements] = useState9([]);
|
|
2760
|
+
const [hoverRect, setHoverRect] = useState9(null);
|
|
2761
|
+
const [heldDistances, setHeldDistances] = useState9(
|
|
1536
2762
|
options.initialHeldDistances ?? []
|
|
1537
2763
|
);
|
|
1538
2764
|
return {
|
|
@@ -2022,7 +3248,7 @@ var useMeasurerDerived = ({
|
|
|
2022
3248
|
};
|
|
2023
3249
|
|
|
2024
3250
|
// hooks/use-measurer-history.ts
|
|
2025
|
-
import { useCallback as
|
|
3251
|
+
import { useCallback as useCallback5, useRef as useRef8 } from "react";
|
|
2026
3252
|
var HISTORY_LIMIT = 50;
|
|
2027
3253
|
var useMeasurerHistory = ({
|
|
2028
3254
|
toggles,
|
|
@@ -2068,10 +3294,10 @@ var useMeasurerHistory = ({
|
|
|
2068
3294
|
setSelectedElement,
|
|
2069
3295
|
clearSelectionRect
|
|
2070
3296
|
} = transient;
|
|
2071
|
-
const historyRef =
|
|
2072
|
-
const futureRef =
|
|
2073
|
-
const historySignatureRef =
|
|
2074
|
-
const captureSnapshot =
|
|
3297
|
+
const historyRef = useRef8([]);
|
|
3298
|
+
const futureRef = useRef8([]);
|
|
3299
|
+
const historySignatureRef = useRef8(null);
|
|
3300
|
+
const captureSnapshot = useCallback5(() => {
|
|
2075
3301
|
return {
|
|
2076
3302
|
enabled,
|
|
2077
3303
|
toolMode,
|
|
@@ -2098,7 +3324,7 @@ var useMeasurerHistory = ({
|
|
|
2098
3324
|
selectedMeasurements,
|
|
2099
3325
|
toolMode
|
|
2100
3326
|
]);
|
|
2101
|
-
const getSnapshotSignature =
|
|
3327
|
+
const getSnapshotSignature = useCallback5((snapshot) => {
|
|
2102
3328
|
const serializeRect = (rect) => `${Math.round(rect.left)}:${Math.round(rect.top)}:${Math.round(rect.width)}:${Math.round(rect.height)}`;
|
|
2103
3329
|
return [
|
|
2104
3330
|
snapshot.enabled ? "1" : "0",
|
|
@@ -2114,7 +3340,7 @@ var useMeasurerHistory = ({
|
|
|
2114
3340
|
snapshot.draggingGuideId ?? ""
|
|
2115
3341
|
].join("|");
|
|
2116
3342
|
}, []);
|
|
2117
|
-
const recordSnapshot =
|
|
3343
|
+
const recordSnapshot = useCallback5(() => {
|
|
2118
3344
|
const snapshot = captureSnapshot();
|
|
2119
3345
|
const signature = getSnapshotSignature(snapshot);
|
|
2120
3346
|
if (historySignatureRef.current === signature) return;
|
|
@@ -2125,7 +3351,7 @@ var useMeasurerHistory = ({
|
|
|
2125
3351
|
historyRef.current.shift();
|
|
2126
3352
|
}
|
|
2127
3353
|
}, [captureSnapshot, getSnapshotSignature]);
|
|
2128
|
-
const restoreSnapshot =
|
|
3354
|
+
const restoreSnapshot = useCallback5(
|
|
2129
3355
|
(snapshot) => {
|
|
2130
3356
|
setEnabled(snapshot.enabled);
|
|
2131
3357
|
setToolMode(snapshot.toolMode);
|
|
@@ -2170,7 +3396,7 @@ var useMeasurerHistory = ({
|
|
|
2170
3396
|
setHoverElement
|
|
2171
3397
|
]
|
|
2172
3398
|
);
|
|
2173
|
-
const undo =
|
|
3399
|
+
const undo = useCallback5(() => {
|
|
2174
3400
|
const previousSnapshot = historyRef.current.pop();
|
|
2175
3401
|
if (!previousSnapshot) return;
|
|
2176
3402
|
const currentSnapshot = captureSnapshot();
|
|
@@ -2181,7 +3407,7 @@ var useMeasurerHistory = ({
|
|
|
2181
3407
|
historySignatureRef.current = null;
|
|
2182
3408
|
restoreSnapshot(previousSnapshot);
|
|
2183
3409
|
}, [captureSnapshot, restoreSnapshot]);
|
|
2184
|
-
const redo =
|
|
3410
|
+
const redo = useCallback5(() => {
|
|
2185
3411
|
const nextSnapshot = futureRef.current.pop();
|
|
2186
3412
|
if (!nextSnapshot) return;
|
|
2187
3413
|
historyRef.current.push(captureSnapshot());
|
|
@@ -2191,7 +3417,7 @@ var useMeasurerHistory = ({
|
|
|
2191
3417
|
historySignatureRef.current = null;
|
|
2192
3418
|
restoreSnapshot(nextSnapshot);
|
|
2193
3419
|
}, [captureSnapshot, restoreSnapshot]);
|
|
2194
|
-
const setToolModeWithHistory =
|
|
3420
|
+
const setToolModeWithHistory = useCallback5(
|
|
2195
3421
|
(value) => {
|
|
2196
3422
|
setToolMode((prev) => {
|
|
2197
3423
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -2202,7 +3428,7 @@ var useMeasurerHistory = ({
|
|
|
2202
3428
|
},
|
|
2203
3429
|
[recordSnapshot, setToolMode]
|
|
2204
3430
|
);
|
|
2205
|
-
const setGuideOrientationWithHistory =
|
|
3431
|
+
const setGuideOrientationWithHistory = useCallback5(
|
|
2206
3432
|
(value) => {
|
|
2207
3433
|
setGuideOrientation((prev) => {
|
|
2208
3434
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -2213,7 +3439,7 @@ var useMeasurerHistory = ({
|
|
|
2213
3439
|
},
|
|
2214
3440
|
[recordSnapshot, setGuideOrientation]
|
|
2215
3441
|
);
|
|
2216
|
-
const setEnabledWithHistory =
|
|
3442
|
+
const setEnabledWithHistory = useCallback5(
|
|
2217
3443
|
(value) => {
|
|
2218
3444
|
setEnabled((prev) => {
|
|
2219
3445
|
const next = typeof value === "function" ? value(prev) : value;
|
|
@@ -2224,7 +3450,7 @@ var useMeasurerHistory = ({
|
|
|
2224
3450
|
},
|
|
2225
3451
|
[recordSnapshot, setEnabled]
|
|
2226
3452
|
);
|
|
2227
|
-
const createActionCommit =
|
|
3453
|
+
const createActionCommit = useCallback5(() => {
|
|
2228
3454
|
let committed = false;
|
|
2229
3455
|
return () => {
|
|
2230
3456
|
if (committed) return;
|
|
@@ -2244,35 +3470,35 @@ var useMeasurerHistory = ({
|
|
|
2244
3470
|
};
|
|
2245
3471
|
|
|
2246
3472
|
// hooks/use-measurer-local-state.ts
|
|
2247
|
-
import { useCallback as
|
|
3473
|
+
import { useCallback as useCallback6, useState as useState10 } from "react";
|
|
2248
3474
|
var useMeasurerLocalState = ({
|
|
2249
3475
|
selectedElementRef,
|
|
2250
3476
|
hoverElementRef,
|
|
2251
3477
|
selectionRectRef
|
|
2252
3478
|
}) => {
|
|
2253
|
-
const [selectionOriginRect, setSelectionOriginRect] =
|
|
3479
|
+
const [selectionOriginRect, setSelectionOriginRect] = useState10(
|
|
2254
3480
|
null
|
|
2255
3481
|
);
|
|
2256
|
-
const [hoverPointer, setHoverPointer] =
|
|
2257
|
-
const [hoverElement, setHoverElementState] =
|
|
3482
|
+
const [hoverPointer, setHoverPointer] = useState10(null);
|
|
3483
|
+
const [hoverElement, setHoverElementState] = useState10(
|
|
2258
3484
|
null
|
|
2259
3485
|
);
|
|
2260
|
-
const [selectedElement, setSelectedElementState] =
|
|
2261
|
-
const setSelectedElement =
|
|
3486
|
+
const [selectedElement, setSelectedElementState] = useState10(null);
|
|
3487
|
+
const setSelectedElement = useCallback6(
|
|
2262
3488
|
(element) => {
|
|
2263
3489
|
selectedElementRef.current = element;
|
|
2264
3490
|
setSelectedElementState(element);
|
|
2265
3491
|
},
|
|
2266
3492
|
[selectedElementRef]
|
|
2267
3493
|
);
|
|
2268
|
-
const setHoverElement =
|
|
3494
|
+
const setHoverElement = useCallback6(
|
|
2269
3495
|
(element) => {
|
|
2270
3496
|
hoverElementRef.current = element;
|
|
2271
3497
|
setHoverElementState(element);
|
|
2272
3498
|
},
|
|
2273
3499
|
[hoverElementRef]
|
|
2274
3500
|
);
|
|
2275
|
-
const clearSelectionRect =
|
|
3501
|
+
const clearSelectionRect = useCallback6(() => {
|
|
2276
3502
|
selectionRectRef.current = null;
|
|
2277
3503
|
setSelectionOriginRect(null);
|
|
2278
3504
|
}, [selectionRectRef]);
|
|
@@ -2290,7 +3516,7 @@ var useMeasurerLocalState = ({
|
|
|
2290
3516
|
};
|
|
2291
3517
|
|
|
2292
3518
|
// hooks/use-measurer-pointer.ts
|
|
2293
|
-
import { useCallback as
|
|
3519
|
+
import { useCallback as useCallback7, useEffect as useEffect5, useRef as useRef9 } from "react";
|
|
2294
3520
|
|
|
2295
3521
|
// core/targets.ts
|
|
2296
3522
|
var pickMultiTargets = (selectionRect, items) => {
|
|
@@ -2493,10 +3719,12 @@ var useMeasurerPointer = ({
|
|
|
2493
3719
|
clearGuideDragHold,
|
|
2494
3720
|
scheduleGuideDragHold,
|
|
2495
3721
|
enabled,
|
|
3722
|
+
settingsOpen,
|
|
2496
3723
|
toolMode,
|
|
2497
3724
|
guidesEnabled,
|
|
2498
3725
|
snapEnabled,
|
|
2499
3726
|
snapGuidesEnabled,
|
|
3727
|
+
selectNewGuideEnabled,
|
|
2500
3728
|
altPressed,
|
|
2501
3729
|
guideOrientation,
|
|
2502
3730
|
hoverHighlightEnabled,
|
|
@@ -2529,24 +3757,24 @@ var useMeasurerPointer = ({
|
|
|
2529
3757
|
setHoverPointer,
|
|
2530
3758
|
clearSelectionRect
|
|
2531
3759
|
}) => {
|
|
2532
|
-
const hoverFrameRef =
|
|
2533
|
-
const hoverPointRef =
|
|
2534
|
-
const selectionCacheRef =
|
|
3760
|
+
const hoverFrameRef = useRef9(null);
|
|
3761
|
+
const hoverPointRef = useRef9(null);
|
|
3762
|
+
const selectionCacheRef = useRef9({
|
|
2535
3763
|
key: "",
|
|
2536
3764
|
entries: [],
|
|
2537
3765
|
overlayNode: null,
|
|
2538
3766
|
frame: -1
|
|
2539
3767
|
});
|
|
2540
|
-
const shiftDragRef =
|
|
2541
|
-
const shiftToggleElementRef =
|
|
2542
|
-
|
|
3768
|
+
const shiftDragRef = useRef9(false);
|
|
3769
|
+
const shiftToggleElementRef = useRef9(null);
|
|
3770
|
+
useEffect5(() => {
|
|
2543
3771
|
return () => {
|
|
2544
3772
|
if (hoverFrameRef.current) {
|
|
2545
3773
|
window2.cancelAnimationFrame(hoverFrameRef.current);
|
|
2546
3774
|
}
|
|
2547
3775
|
};
|
|
2548
3776
|
}, []);
|
|
2549
|
-
const updateHoverTarget =
|
|
3777
|
+
const updateHoverTarget = useCallback7(
|
|
2550
3778
|
(point) => {
|
|
2551
3779
|
const target = getTargetElement(point, overlayRef.current, document2);
|
|
2552
3780
|
if (target) {
|
|
@@ -2565,18 +3793,19 @@ var useMeasurerPointer = ({
|
|
|
2565
3793
|
},
|
|
2566
3794
|
[document2, overlayRef, setHoverElement, setHoverRect]
|
|
2567
3795
|
);
|
|
2568
|
-
const updateHoverElement =
|
|
3796
|
+
const updateHoverElement = useCallback7(
|
|
2569
3797
|
(point) => {
|
|
2570
3798
|
const target = getTargetElement(point, overlayRef.current, document2);
|
|
2571
3799
|
setHoverElement(target);
|
|
2572
3800
|
},
|
|
2573
3801
|
[document2, overlayRef, setHoverElement]
|
|
2574
3802
|
);
|
|
2575
|
-
const handlePointerDown =
|
|
3803
|
+
const handlePointerDown = useCallback7(
|
|
2576
3804
|
(event) => {
|
|
2577
3805
|
const commit = createActionCommit();
|
|
2578
3806
|
const toolbarNode = toolbarRef.current;
|
|
2579
3807
|
if (toolbarNode && toolbarNode.contains(event.target)) return;
|
|
3808
|
+
if (settingsOpen) return;
|
|
2580
3809
|
if (!enabled || event.button !== 0) return;
|
|
2581
3810
|
if (toolMode === "none") return;
|
|
2582
3811
|
clearSelectionRect();
|
|
@@ -2601,7 +3830,11 @@ var useMeasurerPointer = ({
|
|
|
2601
3830
|
return;
|
|
2602
3831
|
}
|
|
2603
3832
|
if (guidesEnabled) {
|
|
3833
|
+
event.preventDefault();
|
|
2604
3834
|
commit();
|
|
3835
|
+
setStart(null);
|
|
3836
|
+
setEnd(null);
|
|
3837
|
+
setIsDragging(false);
|
|
2605
3838
|
const position = getSnapGuidePosition({
|
|
2606
3839
|
orientation: guideOrientation,
|
|
2607
3840
|
point,
|
|
@@ -2612,7 +3845,7 @@ var useMeasurerPointer = ({
|
|
|
2612
3845
|
document: document2
|
|
2613
3846
|
});
|
|
2614
3847
|
const id = createId();
|
|
2615
|
-
setSelectedGuideIds([id]);
|
|
3848
|
+
setSelectedGuideIds(selectNewGuideEnabled ? [id] : []);
|
|
2616
3849
|
setGuides((prev) => [
|
|
2617
3850
|
...prev,
|
|
2618
3851
|
{ id, orientation: guideOrientation, position }
|
|
@@ -2637,12 +3870,14 @@ var useMeasurerPointer = ({
|
|
|
2637
3870
|
draggingGuideId,
|
|
2638
3871
|
document2,
|
|
2639
3872
|
enabled,
|
|
3873
|
+
settingsOpen,
|
|
2640
3874
|
guideOrientation,
|
|
2641
3875
|
guides,
|
|
2642
3876
|
guidesEnabled,
|
|
2643
3877
|
optionPairOverlay,
|
|
2644
3878
|
overlayRef,
|
|
2645
3879
|
scheduleGuideDragHold,
|
|
3880
|
+
selectNewGuideEnabled,
|
|
2646
3881
|
selectedGuideIds.length,
|
|
2647
3882
|
selectedMeasurements,
|
|
2648
3883
|
setDraggingGuideId,
|
|
@@ -2657,10 +3892,11 @@ var useMeasurerPointer = ({
|
|
|
2657
3892
|
toolbarRef
|
|
2658
3893
|
]
|
|
2659
3894
|
);
|
|
2660
|
-
const handlePointerMove =
|
|
3895
|
+
const handlePointerMove = useCallback7(
|
|
2661
3896
|
(event) => {
|
|
2662
3897
|
const toolbarNode = toolbarRef.current;
|
|
2663
3898
|
if (toolbarNode && toolbarNode.contains(event.target)) return;
|
|
3899
|
+
if (settingsOpen) return;
|
|
2664
3900
|
if (!enabled) return;
|
|
2665
3901
|
if (toolMode === "none") {
|
|
2666
3902
|
if (hoverHighlightEnabled) {
|
|
@@ -2679,7 +3915,7 @@ var useMeasurerPointer = ({
|
|
|
2679
3915
|
if (!hoverFrameRef.current) {
|
|
2680
3916
|
hoverFrameRef.current = window2.requestAnimationFrame(() => {
|
|
2681
3917
|
const latest = hoverPointRef.current;
|
|
2682
|
-
if (latest && !draggingGuideId) {
|
|
3918
|
+
if (latest && !draggingGuideId && !guidesEnabled) {
|
|
2683
3919
|
if (hoverHighlightEnabled) {
|
|
2684
3920
|
updateHoverTarget(latest);
|
|
2685
3921
|
} else {
|
|
@@ -2729,6 +3965,7 @@ var useMeasurerPointer = ({
|
|
|
2729
3965
|
)
|
|
2730
3966
|
);
|
|
2731
3967
|
}
|
|
3968
|
+
if (guidesEnabled) return;
|
|
2732
3969
|
if (!start) return;
|
|
2733
3970
|
setEnd(point);
|
|
2734
3971
|
if (!isDragging) {
|
|
@@ -2744,6 +3981,7 @@ var useMeasurerPointer = ({
|
|
|
2744
3981
|
altPressed,
|
|
2745
3982
|
draggingGuideId,
|
|
2746
3983
|
enabled,
|
|
3984
|
+
settingsOpen,
|
|
2747
3985
|
hoverHighlightEnabled,
|
|
2748
3986
|
guides,
|
|
2749
3987
|
guidesEnabled,
|
|
@@ -2766,13 +4004,20 @@ var useMeasurerPointer = ({
|
|
|
2766
4004
|
updateHoverTarget
|
|
2767
4005
|
]
|
|
2768
4006
|
);
|
|
2769
|
-
const handlePointerUp =
|
|
4007
|
+
const handlePointerUp = useCallback7(
|
|
2770
4008
|
(event) => {
|
|
2771
4009
|
const commit = createActionCommit();
|
|
2772
4010
|
const toolbarNode = toolbarRef.current;
|
|
2773
4011
|
if (toolbarNode && toolbarNode.contains(event.target)) return;
|
|
4012
|
+
if (settingsOpen) return;
|
|
2774
4013
|
if (!enabled) return;
|
|
2775
4014
|
clearGuideDragHold();
|
|
4015
|
+
if (guidesEnabled) {
|
|
4016
|
+
setStart(null);
|
|
4017
|
+
setEnd(null);
|
|
4018
|
+
setIsDragging(false);
|
|
4019
|
+
return;
|
|
4020
|
+
}
|
|
2776
4021
|
if (toolMode === "none") {
|
|
2777
4022
|
setStart(null);
|
|
2778
4023
|
setEnd(null);
|
|
@@ -2943,7 +4188,9 @@ var useMeasurerPointer = ({
|
|
|
2943
4188
|
createActionCommit,
|
|
2944
4189
|
draggingGuideId,
|
|
2945
4190
|
enabled,
|
|
4191
|
+
settingsOpen,
|
|
2946
4192
|
end,
|
|
4193
|
+
guidesEnabled,
|
|
2947
4194
|
hoverHighlightEnabled,
|
|
2948
4195
|
isDragging,
|
|
2949
4196
|
overlayRef,
|
|
@@ -2966,7 +4213,7 @@ var useMeasurerPointer = ({
|
|
|
2966
4213
|
toolbarRef
|
|
2967
4214
|
]
|
|
2968
4215
|
);
|
|
2969
|
-
const handlePointerLeave =
|
|
4216
|
+
const handlePointerLeave = useCallback7(() => {
|
|
2970
4217
|
clearGuideDragHold();
|
|
2971
4218
|
setStart(null);
|
|
2972
4219
|
setEnd(null);
|
|
@@ -2990,54 +4237,58 @@ var useMeasurerPointer = ({
|
|
|
2990
4237
|
};
|
|
2991
4238
|
|
|
2992
4239
|
// hooks/use-overlay-refs.ts
|
|
2993
|
-
import { useRef as
|
|
4240
|
+
import { useRef as useRef10 } from "react";
|
|
2994
4241
|
var useOverlayRefs = () => {
|
|
2995
|
-
const overlayRef =
|
|
2996
|
-
const selectedElementRef =
|
|
2997
|
-
const hoverElementRef =
|
|
4242
|
+
const overlayRef = useRef10(null);
|
|
4243
|
+
const selectedElementRef = useRef10(null);
|
|
4244
|
+
const hoverElementRef = useRef10(null);
|
|
2998
4245
|
return { overlayRef, selectedElementRef, hoverElementRef };
|
|
2999
4246
|
};
|
|
3000
4247
|
|
|
3001
4248
|
// hooks/use-resize-sync.ts
|
|
3002
|
-
import { useEffect as
|
|
4249
|
+
import { useEffect as useEffect6, useRef as useRef11 } from "react";
|
|
3003
4250
|
var useResizeSync = (params) => {
|
|
3004
|
-
const
|
|
3005
|
-
|
|
3006
|
-
|
|
4251
|
+
const paramsRef = useRef11(params);
|
|
4252
|
+
paramsRef.current = params;
|
|
4253
|
+
const resizeFrameRef = useRef11(null);
|
|
4254
|
+
const viewportRef = useRef11(getViewportSize(params.window));
|
|
4255
|
+
useEffect6(() => {
|
|
4256
|
+
const ownerWindow = params.window;
|
|
3007
4257
|
const handleResize = () => {
|
|
4258
|
+
const current = paramsRef.current;
|
|
3008
4259
|
if (resizeFrameRef.current) {
|
|
3009
|
-
|
|
4260
|
+
ownerWindow.cancelAnimationFrame(resizeFrameRef.current);
|
|
3010
4261
|
}
|
|
3011
|
-
resizeFrameRef.current =
|
|
3012
|
-
const viewport = getViewportSize(
|
|
4262
|
+
resizeFrameRef.current = ownerWindow.requestAnimationFrame(() => {
|
|
4263
|
+
const viewport = getViewportSize(ownerWindow);
|
|
3013
4264
|
const previousViewport = viewportRef.current;
|
|
3014
|
-
|
|
4265
|
+
current.setMeasurements(
|
|
3015
4266
|
(prev) => prev.map(
|
|
3016
|
-
(measurement) => updateMeasurementForResize(measurement, viewport,
|
|
4267
|
+
(measurement) => updateMeasurementForResize(measurement, viewport, current.document)
|
|
3017
4268
|
)
|
|
3018
4269
|
);
|
|
3019
|
-
|
|
3020
|
-
(prev) => prev ? updateMeasurementForResize(prev, viewport,
|
|
4270
|
+
current.setActiveMeasurement(
|
|
4271
|
+
(prev) => prev ? updateMeasurementForResize(prev, viewport, current.document) : prev
|
|
3021
4272
|
);
|
|
3022
|
-
|
|
4273
|
+
current.setHeldDistances(
|
|
3023
4274
|
(prev) => prev.map(
|
|
3024
4275
|
(distance) => updateDistanceForResize(
|
|
3025
4276
|
distance,
|
|
3026
4277
|
viewport,
|
|
3027
|
-
|
|
3028
|
-
|
|
4278
|
+
current.document,
|
|
4279
|
+
ownerWindow
|
|
3029
4280
|
)
|
|
3030
4281
|
)
|
|
3031
4282
|
);
|
|
3032
|
-
if (
|
|
3033
|
-
|
|
3034
|
-
getInspectMeasurement(
|
|
4283
|
+
if (current.selectedElementRef.current && current.document.contains(current.selectedElementRef.current)) {
|
|
4284
|
+
current.setSelectedMeasurement(
|
|
4285
|
+
getInspectMeasurement(current.selectedElementRef.current, ownerWindow)
|
|
3035
4286
|
);
|
|
3036
4287
|
}
|
|
3037
4288
|
if (previousViewport.width > 0 && previousViewport.height > 0) {
|
|
3038
4289
|
const scaleX = viewport.width / previousViewport.width;
|
|
3039
4290
|
const scaleY = viewport.height / previousViewport.height;
|
|
3040
|
-
|
|
4291
|
+
current.setGuides(
|
|
3041
4292
|
(prev) => prev.map(
|
|
3042
4293
|
(guide) => guide.orientation === "vertical" ? { ...guide, position: guide.position * scaleX } : { ...guide, position: guide.position * scaleY }
|
|
3043
4294
|
)
|
|
@@ -3046,27 +4297,27 @@ var useResizeSync = (params) => {
|
|
|
3046
4297
|
viewportRef.current = viewport;
|
|
3047
4298
|
});
|
|
3048
4299
|
};
|
|
3049
|
-
|
|
4300
|
+
ownerWindow.addEventListener("resize", handleResize);
|
|
3050
4301
|
return () => {
|
|
3051
4302
|
if (resizeFrameRef.current) {
|
|
3052
|
-
|
|
4303
|
+
ownerWindow.cancelAnimationFrame(resizeFrameRef.current);
|
|
3053
4304
|
}
|
|
3054
|
-
|
|
4305
|
+
ownerWindow.removeEventListener("resize", handleResize);
|
|
3055
4306
|
};
|
|
3056
|
-
}, [params]);
|
|
4307
|
+
}, [params.window]);
|
|
3057
4308
|
};
|
|
3058
4309
|
|
|
3059
4310
|
// render/measurer-overlay.tsx
|
|
3060
4311
|
import { memo as memo6 } from "react";
|
|
3061
4312
|
|
|
3062
4313
|
// components/measure-tag.tsx
|
|
3063
|
-
import { jsx as
|
|
4314
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
3064
4315
|
function MeasureTag({
|
|
3065
4316
|
children,
|
|
3066
4317
|
className = "",
|
|
3067
4318
|
style
|
|
3068
4319
|
}) {
|
|
3069
|
-
return /* @__PURE__ */
|
|
4320
|
+
return /* @__PURE__ */ jsx7(
|
|
3070
4321
|
"div",
|
|
3071
4322
|
{
|
|
3072
4323
|
className: cn(
|
|
@@ -3081,20 +4332,20 @@ function MeasureTag({
|
|
|
3081
4332
|
|
|
3082
4333
|
// components/measurement-box.tsx
|
|
3083
4334
|
import { memo as memo3 } from "react";
|
|
3084
|
-
import { jsx as
|
|
4335
|
+
import { jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
3085
4336
|
var formatValue2 = (value) => Math.round(value);
|
|
3086
4337
|
var MeasurementBox = memo3(function MeasurementBox2({
|
|
3087
4338
|
measurement,
|
|
3088
4339
|
transitionMs,
|
|
3089
4340
|
labelOffset,
|
|
3090
|
-
edgeVisibility
|
|
4341
|
+
edgeVisibility,
|
|
4342
|
+
outlineColor,
|
|
4343
|
+
fillColor
|
|
3091
4344
|
}) {
|
|
3092
4345
|
const edges = edgeVisibility ?? { top: true, right: true, bottom: true, left: true };
|
|
3093
4346
|
const displayRect = measurement.rect;
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
return /* @__PURE__ */ jsxs3("div", { className: "msr:pointer-events-none", children: [
|
|
3097
|
-
/* @__PURE__ */ jsxs3(
|
|
4347
|
+
return /* @__PURE__ */ jsxs7("div", { className: "msr:pointer-events-none", children: [
|
|
4348
|
+
/* @__PURE__ */ jsxs7(
|
|
3098
4349
|
"div",
|
|
3099
4350
|
{
|
|
3100
4351
|
className: "msr:absolute",
|
|
@@ -3107,28 +4358,28 @@ var MeasurementBox = memo3(function MeasurementBox2({
|
|
|
3107
4358
|
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease, width ${transitionMs}ms ease, height ${transitionMs}ms ease`
|
|
3108
4359
|
},
|
|
3109
4360
|
children: [
|
|
3110
|
-
edges.top ? /* @__PURE__ */
|
|
4361
|
+
edges.top ? /* @__PURE__ */ jsx8(
|
|
3111
4362
|
"div",
|
|
3112
4363
|
{
|
|
3113
4364
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
3114
4365
|
style: { backgroundColor: outlineColor }
|
|
3115
4366
|
}
|
|
3116
4367
|
) : null,
|
|
3117
|
-
edges.right ? /* @__PURE__ */
|
|
4368
|
+
edges.right ? /* @__PURE__ */ jsx8(
|
|
3118
4369
|
"div",
|
|
3119
4370
|
{
|
|
3120
4371
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
3121
4372
|
style: { backgroundColor: outlineColor }
|
|
3122
4373
|
}
|
|
3123
4374
|
) : null,
|
|
3124
|
-
edges.bottom ? /* @__PURE__ */
|
|
4375
|
+
edges.bottom ? /* @__PURE__ */ jsx8(
|
|
3125
4376
|
"div",
|
|
3126
4377
|
{
|
|
3127
4378
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
3128
4379
|
style: { backgroundColor: outlineColor }
|
|
3129
4380
|
}
|
|
3130
4381
|
) : null,
|
|
3131
|
-
edges.left ? /* @__PURE__ */
|
|
4382
|
+
edges.left ? /* @__PURE__ */ jsx8(
|
|
3132
4383
|
"div",
|
|
3133
4384
|
{
|
|
3134
4385
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -3138,7 +4389,7 @@ var MeasurementBox = memo3(function MeasurementBox2({
|
|
|
3138
4389
|
]
|
|
3139
4390
|
}
|
|
3140
4391
|
),
|
|
3141
|
-
/* @__PURE__ */
|
|
4392
|
+
/* @__PURE__ */ jsxs7(
|
|
3142
4393
|
MeasureTag,
|
|
3143
4394
|
{
|
|
3144
4395
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3159,20 +4410,20 @@ var MeasurementBox = memo3(function MeasurementBox2({
|
|
|
3159
4410
|
|
|
3160
4411
|
// components/selected-measurement-box.tsx
|
|
3161
4412
|
import { memo as memo4 } from "react";
|
|
3162
|
-
import { jsx as
|
|
4413
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
3163
4414
|
var formatValue3 = (value) => Math.round(value);
|
|
3164
4415
|
var SelectedMeasurementBox = memo4(function SelectedMeasurementBox2({
|
|
3165
4416
|
measurement,
|
|
3166
4417
|
transitionMs,
|
|
3167
4418
|
labelOffset,
|
|
3168
|
-
edgeVisibility
|
|
4419
|
+
edgeVisibility,
|
|
4420
|
+
outlineColor,
|
|
4421
|
+
fillColor
|
|
3169
4422
|
}) {
|
|
3170
4423
|
const edges = edgeVisibility ?? { top: true, right: true, bottom: true, left: true };
|
|
3171
4424
|
const displayRect = measurement.rect;
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
return /* @__PURE__ */ jsxs4("div", { className: "msr:pointer-events-none", children: [
|
|
3175
|
-
/* @__PURE__ */ jsxs4(
|
|
4425
|
+
return /* @__PURE__ */ jsxs8("div", { className: "msr:pointer-events-none", "data-mesurer-selected-measurement": "true", children: [
|
|
4426
|
+
/* @__PURE__ */ jsxs8(
|
|
3176
4427
|
"div",
|
|
3177
4428
|
{
|
|
3178
4429
|
className: "msr:absolute",
|
|
@@ -3185,28 +4436,28 @@ var SelectedMeasurementBox = memo4(function SelectedMeasurementBox2({
|
|
|
3185
4436
|
transition: `left ${transitionMs}ms ease, top ${transitionMs}ms ease, width ${transitionMs}ms ease, height ${transitionMs}ms ease`
|
|
3186
4437
|
},
|
|
3187
4438
|
children: [
|
|
3188
|
-
edges.top ? /* @__PURE__ */
|
|
4439
|
+
edges.top ? /* @__PURE__ */ jsx9(
|
|
3189
4440
|
"div",
|
|
3190
4441
|
{
|
|
3191
4442
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
3192
4443
|
style: { backgroundColor: outlineColor }
|
|
3193
4444
|
}
|
|
3194
4445
|
) : null,
|
|
3195
|
-
edges.right ? /* @__PURE__ */
|
|
4446
|
+
edges.right ? /* @__PURE__ */ jsx9(
|
|
3196
4447
|
"div",
|
|
3197
4448
|
{
|
|
3198
4449
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
3199
4450
|
style: { backgroundColor: outlineColor }
|
|
3200
4451
|
}
|
|
3201
4452
|
) : null,
|
|
3202
|
-
edges.bottom ? /* @__PURE__ */
|
|
4453
|
+
edges.bottom ? /* @__PURE__ */ jsx9(
|
|
3203
4454
|
"div",
|
|
3204
4455
|
{
|
|
3205
4456
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
3206
4457
|
style: { backgroundColor: outlineColor }
|
|
3207
4458
|
}
|
|
3208
4459
|
) : null,
|
|
3209
|
-
edges.left ? /* @__PURE__ */
|
|
4460
|
+
edges.left ? /* @__PURE__ */ jsx9(
|
|
3210
4461
|
"div",
|
|
3211
4462
|
{
|
|
3212
4463
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -3216,7 +4467,7 @@ var SelectedMeasurementBox = memo4(function SelectedMeasurementBox2({
|
|
|
3216
4467
|
]
|
|
3217
4468
|
}
|
|
3218
4469
|
),
|
|
3219
|
-
/* @__PURE__ */
|
|
4470
|
+
/* @__PURE__ */ jsxs8(
|
|
3220
4471
|
MeasureTag,
|
|
3221
4472
|
{
|
|
3222
4473
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3237,13 +4488,13 @@ var SelectedMeasurementBox = memo4(function SelectedMeasurementBox2({
|
|
|
3237
4488
|
|
|
3238
4489
|
// render/distance-overlay-item.tsx
|
|
3239
4490
|
import { memo as memo5 } from "react";
|
|
3240
|
-
import { Fragment, jsx as
|
|
4491
|
+
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
3241
4492
|
var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
3242
4493
|
distance,
|
|
3243
4494
|
labelOffset,
|
|
3244
4495
|
onRemove
|
|
3245
4496
|
}) {
|
|
3246
|
-
return /* @__PURE__ */
|
|
4497
|
+
return /* @__PURE__ */ jsxs9(
|
|
3247
4498
|
"div",
|
|
3248
4499
|
{
|
|
3249
4500
|
className: onRemove ? "msr:pointer-events-auto" : "msr:pointer-events-none",
|
|
@@ -3252,7 +4503,7 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3252
4503
|
onRemove(distance.id);
|
|
3253
4504
|
} : void 0,
|
|
3254
4505
|
children: [
|
|
3255
|
-
/* @__PURE__ */
|
|
4506
|
+
/* @__PURE__ */ jsx10(
|
|
3256
4507
|
"div",
|
|
3257
4508
|
{
|
|
3258
4509
|
className: "msr:absolute msr:rounded msr:border msr:border-[#2563eb]/70",
|
|
@@ -3264,7 +4515,7 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3264
4515
|
}
|
|
3265
4516
|
}
|
|
3266
4517
|
),
|
|
3267
|
-
/* @__PURE__ */
|
|
4518
|
+
/* @__PURE__ */ jsx10(
|
|
3268
4519
|
"div",
|
|
3269
4520
|
{
|
|
3270
4521
|
className: "msr:absolute msr:rounded msr:border msr:border-[#2563eb]/70",
|
|
@@ -3277,7 +4528,7 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3277
4528
|
}
|
|
3278
4529
|
),
|
|
3279
4530
|
distance.connectors.map(
|
|
3280
|
-
(connector, index) => Math.abs(connector.x1 - connector.x2) < 1 ? /* @__PURE__ */
|
|
4531
|
+
(connector, index) => Math.abs(connector.x1 - connector.x2) < 1 ? /* @__PURE__ */ jsx10(
|
|
3281
4532
|
"div",
|
|
3282
4533
|
{
|
|
3283
4534
|
className: "msr:absolute msr:border-l msr:border-dashed msr:border-[#2563eb]/70",
|
|
@@ -3288,7 +4539,7 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3288
4539
|
}
|
|
3289
4540
|
},
|
|
3290
4541
|
`${distance.id}-connector-${index}`
|
|
3291
|
-
) : /* @__PURE__ */
|
|
4542
|
+
) : /* @__PURE__ */ jsx10(
|
|
3292
4543
|
"div",
|
|
3293
4544
|
{
|
|
3294
4545
|
className: "msr:absolute msr:border-t msr:border-dashed msr:border-[#2563eb]/70",
|
|
@@ -3301,8 +4552,8 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3301
4552
|
`${distance.id}-connector-${index}`
|
|
3302
4553
|
)
|
|
3303
4554
|
),
|
|
3304
|
-
distance.horizontal && distance.horizontal.value > 0 ? /* @__PURE__ */
|
|
3305
|
-
/* @__PURE__ */
|
|
4555
|
+
distance.horizontal && distance.horizontal.value > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
4556
|
+
/* @__PURE__ */ jsx10(
|
|
3306
4557
|
"div",
|
|
3307
4558
|
{
|
|
3308
4559
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3313,7 +4564,7 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3313
4564
|
}
|
|
3314
4565
|
}
|
|
3315
4566
|
),
|
|
3316
|
-
/* @__PURE__ */
|
|
4567
|
+
/* @__PURE__ */ jsx10(
|
|
3317
4568
|
MeasureTag,
|
|
3318
4569
|
{
|
|
3319
4570
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3325,8 +4576,8 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3325
4576
|
}
|
|
3326
4577
|
)
|
|
3327
4578
|
] }) : null,
|
|
3328
|
-
distance.vertical && distance.vertical.value > 0 ? /* @__PURE__ */
|
|
3329
|
-
/* @__PURE__ */
|
|
4579
|
+
distance.vertical && distance.vertical.value > 0 ? /* @__PURE__ */ jsxs9(Fragment4, { children: [
|
|
4580
|
+
/* @__PURE__ */ jsx10(
|
|
3330
4581
|
"div",
|
|
3331
4582
|
{
|
|
3332
4583
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3337,7 +4588,7 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3337
4588
|
}
|
|
3338
4589
|
}
|
|
3339
4590
|
),
|
|
3340
|
-
/* @__PURE__ */
|
|
4591
|
+
/* @__PURE__ */ jsx10(
|
|
3341
4592
|
MeasureTag,
|
|
3342
4593
|
{
|
|
3343
4594
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3355,9 +4606,10 @@ var DistanceOverlayItem = memo5(function DistanceOverlayItem2({
|
|
|
3355
4606
|
});
|
|
3356
4607
|
|
|
3357
4608
|
// render/measurer-overlay.tsx
|
|
3358
|
-
import { Fragment as
|
|
4609
|
+
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
3359
4610
|
var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
3360
4611
|
enabled,
|
|
4612
|
+
interactive = true,
|
|
3361
4613
|
toolMode,
|
|
3362
4614
|
guidePointerEvents,
|
|
3363
4615
|
guidesEnabled,
|
|
@@ -3387,6 +4639,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3387
4639
|
guideColorActive,
|
|
3388
4640
|
guideColorHover,
|
|
3389
4641
|
guideColorDefault,
|
|
4642
|
+
guideStyle,
|
|
3390
4643
|
onPointerDown,
|
|
3391
4644
|
onPointerMove,
|
|
3392
4645
|
onPointerUp,
|
|
@@ -3397,30 +4650,32 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3397
4650
|
onGuidePointerCancel
|
|
3398
4651
|
}) {
|
|
3399
4652
|
const overlayVisible = enabled;
|
|
3400
|
-
const overlayInteractive = overlayVisible && toolMode !== "none" && toolMode !== "text-inspector" && toolMode !== "xray" && toolMode !== "rulers";
|
|
4653
|
+
const overlayInteractive = interactive && overlayVisible && toolMode !== "none" && toolMode !== "text-inspector" && toolMode !== "xray" && toolMode !== "rulers";
|
|
3401
4654
|
const selectionVisible = toolMode === "select";
|
|
3402
|
-
return /* @__PURE__ */
|
|
4655
|
+
return /* @__PURE__ */ jsxs10(
|
|
3403
4656
|
"div",
|
|
3404
4657
|
{
|
|
3405
|
-
className: `msr:absolute msr:inset-0 ${overlayVisible ? `msr:pointer-events-auto ${guidesEnabled ? hoverGuide || draggingGuideId ? "msr:cursor-default" : "msr:cursor-crosshair" : "msr:cursor-default"} msr:opacity-100` : "msr:pointer-events-none msr:opacity-0"}`,
|
|
4658
|
+
className: `msr:absolute msr:inset-0 msr:select-none ${overlayVisible ? `msr:pointer-events-auto ${guidesEnabled ? hoverGuide || draggingGuideId ? "msr:cursor-default" : "msr:cursor-crosshair" : "msr:cursor-default"} msr:opacity-100` : "msr:pointer-events-none msr:opacity-0"}`,
|
|
3406
4659
|
style: { pointerEvents: overlayInteractive ? "auto" : "none" },
|
|
3407
4660
|
onPointerDown,
|
|
3408
4661
|
onPointerMove,
|
|
3409
4662
|
onPointerUp,
|
|
3410
4663
|
onPointerLeave,
|
|
3411
4664
|
children: [
|
|
3412
|
-
selectionVisible ? displayedMeasurements.map((measurement, index) => /* @__PURE__ */
|
|
4665
|
+
selectionVisible ? displayedMeasurements.map((measurement, index) => /* @__PURE__ */ jsx11(
|
|
3413
4666
|
MeasurementBox,
|
|
3414
4667
|
{
|
|
3415
4668
|
measurement,
|
|
3416
4669
|
transitionMs: MEASURE_TRANSITION_MS,
|
|
3417
4670
|
labelOffset: MEASURE_LABEL_OFFSET,
|
|
3418
|
-
edgeVisibility: measurementEdgeVisibility[index]
|
|
4671
|
+
edgeVisibility: measurementEdgeVisibility[index],
|
|
4672
|
+
outlineColor,
|
|
4673
|
+
fillColor
|
|
3419
4674
|
},
|
|
3420
4675
|
measurement.id
|
|
3421
4676
|
)) : null,
|
|
3422
|
-
selectionVisible && activeRect && isDragging ? /* @__PURE__ */
|
|
3423
|
-
/* @__PURE__ */
|
|
4677
|
+
selectionVisible && activeRect && isDragging ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
4678
|
+
/* @__PURE__ */ jsxs10(
|
|
3424
4679
|
"div",
|
|
3425
4680
|
{
|
|
3426
4681
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -3432,28 +4687,28 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3432
4687
|
backgroundColor: fillColor
|
|
3433
4688
|
},
|
|
3434
4689
|
children: [
|
|
3435
|
-
/* @__PURE__ */
|
|
4690
|
+
/* @__PURE__ */ jsx11(
|
|
3436
4691
|
"div",
|
|
3437
4692
|
{
|
|
3438
4693
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
3439
4694
|
style: { backgroundColor: outlineColor }
|
|
3440
4695
|
}
|
|
3441
4696
|
),
|
|
3442
|
-
/* @__PURE__ */
|
|
4697
|
+
/* @__PURE__ */ jsx11(
|
|
3443
4698
|
"div",
|
|
3444
4699
|
{
|
|
3445
4700
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
3446
4701
|
style: { backgroundColor: outlineColor }
|
|
3447
4702
|
}
|
|
3448
4703
|
),
|
|
3449
|
-
/* @__PURE__ */
|
|
4704
|
+
/* @__PURE__ */ jsx11(
|
|
3450
4705
|
"div",
|
|
3451
4706
|
{
|
|
3452
4707
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
3453
4708
|
style: { backgroundColor: outlineColor }
|
|
3454
4709
|
}
|
|
3455
4710
|
),
|
|
3456
|
-
/* @__PURE__ */
|
|
4711
|
+
/* @__PURE__ */ jsx11(
|
|
3457
4712
|
"div",
|
|
3458
4713
|
{
|
|
3459
4714
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -3463,7 +4718,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3463
4718
|
]
|
|
3464
4719
|
}
|
|
3465
4720
|
),
|
|
3466
|
-
/* @__PURE__ */
|
|
4721
|
+
/* @__PURE__ */ jsxs10(
|
|
3467
4722
|
MeasureTag,
|
|
3468
4723
|
{
|
|
3469
4724
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3479,7 +4734,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3479
4734
|
}
|
|
3480
4735
|
)
|
|
3481
4736
|
] }) : null,
|
|
3482
|
-
selectionVisible && hoverRectToShow ? /* @__PURE__ */
|
|
4737
|
+
selectionVisible && hoverRectToShow ? /* @__PURE__ */ jsxs10(
|
|
3483
4738
|
"div",
|
|
3484
4739
|
{
|
|
3485
4740
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -3491,28 +4746,28 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3491
4746
|
backgroundColor: fillColor
|
|
3492
4747
|
},
|
|
3493
4748
|
children: [
|
|
3494
|
-
hoverEdgeVisibility?.top ? /* @__PURE__ */
|
|
4749
|
+
hoverEdgeVisibility?.top ? /* @__PURE__ */ jsx11(
|
|
3495
4750
|
"div",
|
|
3496
4751
|
{
|
|
3497
4752
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-px msr:w-full",
|
|
3498
4753
|
style: { backgroundColor: outlineColor }
|
|
3499
4754
|
}
|
|
3500
4755
|
) : null,
|
|
3501
|
-
hoverEdgeVisibility?.right ? /* @__PURE__ */
|
|
4756
|
+
hoverEdgeVisibility?.right ? /* @__PURE__ */ jsx11(
|
|
3502
4757
|
"div",
|
|
3503
4758
|
{
|
|
3504
4759
|
className: "msr:absolute msr:right-0 msr:top-0 msr:h-full msr:w-px",
|
|
3505
4760
|
style: { backgroundColor: outlineColor }
|
|
3506
4761
|
}
|
|
3507
4762
|
) : null,
|
|
3508
|
-
hoverEdgeVisibility?.bottom ? /* @__PURE__ */
|
|
4763
|
+
hoverEdgeVisibility?.bottom ? /* @__PURE__ */ jsx11(
|
|
3509
4764
|
"div",
|
|
3510
4765
|
{
|
|
3511
4766
|
className: "msr:absolute msr:bottom-0 msr:left-0 msr:h-px msr:w-full",
|
|
3512
4767
|
style: { backgroundColor: outlineColor }
|
|
3513
4768
|
}
|
|
3514
4769
|
) : null,
|
|
3515
|
-
hoverEdgeVisibility?.left ? /* @__PURE__ */
|
|
4770
|
+
hoverEdgeVisibility?.left ? /* @__PURE__ */ jsx11(
|
|
3516
4771
|
"div",
|
|
3517
4772
|
{
|
|
3518
4773
|
className: "msr:absolute msr:left-0 msr:top-0 msr:h-full msr:w-px",
|
|
@@ -3522,7 +4777,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3522
4777
|
]
|
|
3523
4778
|
}
|
|
3524
4779
|
) : null,
|
|
3525
|
-
guidesEnabled && guidePreview ? /* @__PURE__ */
|
|
4780
|
+
interactive && guidesEnabled && guidePreview ? /* @__PURE__ */ jsx11(
|
|
3526
4781
|
"div",
|
|
3527
4782
|
{
|
|
3528
4783
|
className: "msr:pointer-events-none msr:absolute",
|
|
@@ -3537,7 +4792,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3537
4792
|
height: GUIDE_HITBOX_SIZE,
|
|
3538
4793
|
width: "100%"
|
|
3539
4794
|
},
|
|
3540
|
-
children: /* @__PURE__ */
|
|
4795
|
+
children: /* @__PURE__ */ jsx11(
|
|
3541
4796
|
"div",
|
|
3542
4797
|
{
|
|
3543
4798
|
className: "msr:absolute",
|
|
@@ -3558,17 +4813,19 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3558
4813
|
)
|
|
3559
4814
|
}
|
|
3560
4815
|
) : null,
|
|
3561
|
-
selectionVisible ? displayedSelectedMeasurements.map((measurement, index) => /* @__PURE__ */
|
|
4816
|
+
selectionVisible ? displayedSelectedMeasurements.map((measurement, index) => /* @__PURE__ */ jsx11(
|
|
3562
4817
|
SelectedMeasurementBox,
|
|
3563
4818
|
{
|
|
3564
4819
|
measurement,
|
|
3565
4820
|
transitionMs: MEASURE_TRANSITION_MS,
|
|
3566
4821
|
labelOffset: MEASURE_LABEL_OFFSET,
|
|
3567
|
-
edgeVisibility: selectedEdgeVisibility[index]
|
|
4822
|
+
edgeVisibility: selectedEdgeVisibility[index],
|
|
4823
|
+
outlineColor,
|
|
4824
|
+
fillColor
|
|
3568
4825
|
},
|
|
3569
4826
|
measurement.id
|
|
3570
4827
|
)) : null,
|
|
3571
|
-
heldDistances.map((distance) => /* @__PURE__ */
|
|
4828
|
+
heldDistances.map((distance) => /* @__PURE__ */ jsx11(
|
|
3572
4829
|
DistanceOverlayItem,
|
|
3573
4830
|
{
|
|
3574
4831
|
distance,
|
|
@@ -3577,7 +4834,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3577
4834
|
},
|
|
3578
4835
|
`held-${distance.id}`
|
|
3579
4836
|
)),
|
|
3580
|
-
selectionVisible && altPressed && optionPairOverlay ? /* @__PURE__ */
|
|
4837
|
+
selectionVisible && altPressed && optionPairOverlay ? /* @__PURE__ */ jsx11(
|
|
3581
4838
|
DistanceOverlayItem,
|
|
3582
4839
|
{
|
|
3583
4840
|
distance: optionPairOverlay,
|
|
@@ -3585,7 +4842,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3585
4842
|
},
|
|
3586
4843
|
`option-${optionPairOverlay.id}`
|
|
3587
4844
|
) : null,
|
|
3588
|
-
guidesEnabled && altPressed && guideDistanceOverlay ? /* @__PURE__ */
|
|
4845
|
+
interactive && guidesEnabled && altPressed && guideDistanceOverlay ? /* @__PURE__ */ jsx11(
|
|
3589
4846
|
DistanceOverlayItem,
|
|
3590
4847
|
{
|
|
3591
4848
|
distance: guideDistanceOverlay,
|
|
@@ -3593,9 +4850,9 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3593
4850
|
},
|
|
3594
4851
|
`guide-preview-${guideDistanceOverlay.id}`
|
|
3595
4852
|
) : null,
|
|
3596
|
-
selectionVisible && altPressed && optionContainerLines ? /* @__PURE__ */
|
|
3597
|
-
optionContainerLines.top.value > 0 ? /* @__PURE__ */
|
|
3598
|
-
/* @__PURE__ */
|
|
4853
|
+
selectionVisible && altPressed && optionContainerLines ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
4854
|
+
optionContainerLines.top.value > 0 ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
4855
|
+
/* @__PURE__ */ jsx11(
|
|
3599
4856
|
"div",
|
|
3600
4857
|
{
|
|
3601
4858
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3606,7 +4863,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3606
4863
|
}
|
|
3607
4864
|
}
|
|
3608
4865
|
),
|
|
3609
|
-
/* @__PURE__ */
|
|
4866
|
+
/* @__PURE__ */ jsx11(
|
|
3610
4867
|
MeasureTag,
|
|
3611
4868
|
{
|
|
3612
4869
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3618,8 +4875,8 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3618
4875
|
}
|
|
3619
4876
|
)
|
|
3620
4877
|
] }) : null,
|
|
3621
|
-
optionContainerLines.bottom.value > 0 ? /* @__PURE__ */
|
|
3622
|
-
/* @__PURE__ */
|
|
4878
|
+
optionContainerLines.bottom.value > 0 ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
4879
|
+
/* @__PURE__ */ jsx11(
|
|
3623
4880
|
"div",
|
|
3624
4881
|
{
|
|
3625
4882
|
className: "msr:absolute msr:w-px msr:bg-[#2563eb]",
|
|
@@ -3630,7 +4887,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3630
4887
|
}
|
|
3631
4888
|
}
|
|
3632
4889
|
),
|
|
3633
|
-
/* @__PURE__ */
|
|
4890
|
+
/* @__PURE__ */ jsx11(
|
|
3634
4891
|
MeasureTag,
|
|
3635
4892
|
{
|
|
3636
4893
|
className: "msr:-translate-y-1/2 msr:bg-ink-900/90",
|
|
@@ -3642,8 +4899,8 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3642
4899
|
}
|
|
3643
4900
|
)
|
|
3644
4901
|
] }) : null,
|
|
3645
|
-
optionContainerLines.left.value > 0 ? /* @__PURE__ */
|
|
3646
|
-
/* @__PURE__ */
|
|
4902
|
+
optionContainerLines.left.value > 0 ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
4903
|
+
/* @__PURE__ */ jsx11(
|
|
3647
4904
|
"div",
|
|
3648
4905
|
{
|
|
3649
4906
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3654,7 +4911,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3654
4911
|
}
|
|
3655
4912
|
}
|
|
3656
4913
|
),
|
|
3657
|
-
/* @__PURE__ */
|
|
4914
|
+
/* @__PURE__ */ jsx11(
|
|
3658
4915
|
MeasureTag,
|
|
3659
4916
|
{
|
|
3660
4917
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3666,8 +4923,8 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3666
4923
|
}
|
|
3667
4924
|
)
|
|
3668
4925
|
] }) : null,
|
|
3669
|
-
optionContainerLines.right.value > 0 ? /* @__PURE__ */
|
|
3670
|
-
/* @__PURE__ */
|
|
4926
|
+
optionContainerLines.right.value > 0 ? /* @__PURE__ */ jsxs10(Fragment5, { children: [
|
|
4927
|
+
/* @__PURE__ */ jsx11(
|
|
3671
4928
|
"div",
|
|
3672
4929
|
{
|
|
3673
4930
|
className: "msr:absolute msr:h-px msr:bg-[#2563eb]",
|
|
@@ -3678,7 +4935,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3678
4935
|
}
|
|
3679
4936
|
}
|
|
3680
4937
|
),
|
|
3681
|
-
/* @__PURE__ */
|
|
4938
|
+
/* @__PURE__ */ jsx11(
|
|
3682
4939
|
MeasureTag,
|
|
3683
4940
|
{
|
|
3684
4941
|
className: "msr:-translate-x-1/2 msr:bg-ink-900/90",
|
|
@@ -3694,9 +4951,12 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3694
4951
|
guides.map((guide) => {
|
|
3695
4952
|
const isSelected = selectedGuideIds.includes(guide.id);
|
|
3696
4953
|
const isHovered = hoverGuide?.id === guide.id;
|
|
3697
|
-
const strokeWidth = isSelected || isHovered ? 2 : 1;
|
|
3698
4954
|
const strokeColor = isSelected ? guideColorActive : isHovered ? guideColorHover : guideColorDefault;
|
|
3699
|
-
|
|
4955
|
+
const strokeWidth = Math.max(guideStyle.width, isSelected || isHovered ? 2 : guideStyle.width);
|
|
4956
|
+
const isSolid = guideStyle.pattern === "solid";
|
|
4957
|
+
const backgroundImage = guideStyle.pattern === "solid" ? void 0 : guideStyle.pattern === "dotted" ? `radial-gradient(circle, ${strokeColor} 0 ${strokeWidth / 2}px, transparent ${strokeWidth / 2 + 0.5}px)` : `repeating-linear-gradient(${guide.orientation === "vertical" ? "to bottom" : "to right"}, ${strokeColor} 0 ${guideStyle.dashLength}px, transparent ${guideStyle.dashLength}px ${guideStyle.dashLength + guideStyle.gap}px)`;
|
|
4958
|
+
const backgroundSize = guideStyle.pattern === "dotted" ? guide.orientation === "vertical" ? `${strokeWidth}px ${guideStyle.dashLength + guideStyle.gap}px` : `${guideStyle.dashLength + guideStyle.gap}px ${strokeWidth}px` : void 0;
|
|
4959
|
+
return /* @__PURE__ */ jsx11(
|
|
3700
4960
|
"div",
|
|
3701
4961
|
{
|
|
3702
4962
|
className: "msr:absolute",
|
|
@@ -3717,7 +4977,7 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3717
4977
|
onPointerDown: (event) => onGuidePointerDown(guide, event),
|
|
3718
4978
|
onPointerUp: (event) => onGuidePointerUp(guide, event),
|
|
3719
4979
|
onPointerCancel: (event) => onGuidePointerCancel(guide, event),
|
|
3720
|
-
children: /* @__PURE__ */
|
|
4980
|
+
children: /* @__PURE__ */ jsx11(
|
|
3721
4981
|
"div",
|
|
3722
4982
|
{
|
|
3723
4983
|
className: "msr:absolute",
|
|
@@ -3726,13 +4986,19 @@ var MeasurerOverlay = memo6(function MeasurerOverlay2({
|
|
|
3726
4986
|
top: 0,
|
|
3727
4987
|
width: strokeWidth,
|
|
3728
4988
|
height: "100%",
|
|
3729
|
-
backgroundColor: strokeColor
|
|
4989
|
+
backgroundColor: isSolid ? strokeColor : "transparent",
|
|
4990
|
+
backgroundImage,
|
|
4991
|
+
backgroundSize,
|
|
4992
|
+
opacity: guideStyle.opacity
|
|
3730
4993
|
} : {
|
|
3731
4994
|
top: GUIDE_HITBOX_SIZE / 2 - 1,
|
|
3732
4995
|
left: 0,
|
|
3733
4996
|
height: strokeWidth,
|
|
3734
4997
|
width: "100%",
|
|
3735
|
-
backgroundColor: strokeColor
|
|
4998
|
+
backgroundColor: isSolid ? strokeColor : "transparent",
|
|
4999
|
+
backgroundImage,
|
|
5000
|
+
backgroundSize,
|
|
5001
|
+
opacity: guideStyle.opacity
|
|
3736
5002
|
}
|
|
3737
5003
|
}
|
|
3738
5004
|
)
|
|
@@ -4253,6 +5519,7 @@ var createTextInspector = (options = {}, legacy = false) => {
|
|
|
4253
5519
|
if (!element) return false;
|
|
4254
5520
|
for (let node = element; node; node = node.parentElement) {
|
|
4255
5521
|
if (node.classList.contains("mesurer-toolbar-surface")) return true;
|
|
5522
|
+
if (node.hasAttribute("data-mesurer-inspector-ui")) return true;
|
|
4256
5523
|
}
|
|
4257
5524
|
return false;
|
|
4258
5525
|
};
|
|
@@ -4550,7 +5817,7 @@ var createTextInspector = (options = {}, legacy = false) => {
|
|
|
4550
5817
|
const isInspectorUIEvent = (event) => event.composedPath().some(
|
|
4551
5818
|
(node) => node instanceof HTMLElementConstructor && (() => {
|
|
4552
5819
|
const element = node;
|
|
4553
|
-
return element.id === OVERLAY_ID || element.classList.contains("mesurer-ti-card") || element.classList.contains("mesurer-ti-box") || element.classList.contains("mesurer-ti-close") || element.classList.contains("mesurer-toolbar-surface");
|
|
5820
|
+
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") || element.hasAttribute("data-mesurer-inspector-ui");
|
|
4554
5821
|
})()
|
|
4555
5822
|
);
|
|
4556
5823
|
const onClick = (event) => {
|
|
@@ -4633,8 +5900,226 @@ var createTextInspector = (options = {}, legacy = false) => {
|
|
|
4633
5900
|
};
|
|
4634
5901
|
var TextInspector = createTextInspector({}, true);
|
|
4635
5902
|
|
|
5903
|
+
// core/persistence.ts
|
|
5904
|
+
var MESURER_STORAGE_VERSION = 2;
|
|
5905
|
+
var DEFAULT_GUIDE_STYLE = {
|
|
5906
|
+
opacity: 1,
|
|
5907
|
+
width: 1,
|
|
5908
|
+
pattern: "solid",
|
|
5909
|
+
dashLength: 6,
|
|
5910
|
+
gap: 4
|
|
5911
|
+
};
|
|
5912
|
+
var DEFAULT_RULER_SETTINGS = {
|
|
5913
|
+
opacity: 1,
|
|
5914
|
+
edgeReveal: false
|
|
5915
|
+
};
|
|
5916
|
+
var isFormat = (value) => value === "hex" || value === "rgb" || value === "hsl" || value === "oklch";
|
|
5917
|
+
var normalizeGuideStyle = (value) => {
|
|
5918
|
+
if (!value || typeof value !== "object") return void 0;
|
|
5919
|
+
const input = value;
|
|
5920
|
+
return {
|
|
5921
|
+
opacity: typeof input.opacity === "number" ? Math.min(1, Math.max(0, input.opacity)) : DEFAULT_GUIDE_STYLE.opacity,
|
|
5922
|
+
width: typeof input.width === "number" ? Math.min(4, Math.max(1, input.width)) : DEFAULT_GUIDE_STYLE.width,
|
|
5923
|
+
pattern: input.pattern === "dashed" || input.pattern === "dotted" ? input.pattern : DEFAULT_GUIDE_STYLE.pattern,
|
|
5924
|
+
dashLength: typeof input.dashLength === "number" ? Math.min(24, Math.max(2, input.dashLength)) : DEFAULT_GUIDE_STYLE.dashLength,
|
|
5925
|
+
gap: typeof input.gap === "number" ? Math.min(24, Math.max(0, input.gap)) : DEFAULT_GUIDE_STYLE.gap
|
|
5926
|
+
};
|
|
5927
|
+
};
|
|
5928
|
+
var normalizeRulerSettings = (value) => {
|
|
5929
|
+
if (!value || typeof value !== "object") return void 0;
|
|
5930
|
+
const input = value;
|
|
5931
|
+
return {
|
|
5932
|
+
opacity: typeof input.opacity === "number" ? Math.min(1, Math.max(0.2, input.opacity)) : DEFAULT_RULER_SETTINGS.opacity,
|
|
5933
|
+
edgeReveal: typeof input.edgeReveal === "boolean" ? input.edgeReveal : DEFAULT_RULER_SETTINGS.edgeReveal
|
|
5934
|
+
};
|
|
5935
|
+
};
|
|
5936
|
+
var isFiniteNumber = (value) => typeof value === "number" && Number.isFinite(value);
|
|
5937
|
+
var isRect = (value) => {
|
|
5938
|
+
if (!value || typeof value !== "object") return false;
|
|
5939
|
+
const rect = value;
|
|
5940
|
+
return isFiniteNumber(rect.left) && isFiniteNumber(rect.top) && isFiniteNumber(rect.width) && rect.width >= 0 && isFiniteNumber(rect.height) && rect.height >= 0;
|
|
5941
|
+
};
|
|
5942
|
+
var isNormalizedRect = (value) => isRect(value);
|
|
5943
|
+
var isMeasurement = (value) => {
|
|
5944
|
+
if (!value || typeof value !== "object") return false;
|
|
5945
|
+
const measurement = value;
|
|
5946
|
+
return typeof measurement.id === "string" && isRect(measurement.rect) && isNormalizedRect(measurement.normalizedRect) && isFiniteNumber(measurement.deltaX) && isFiniteNumber(measurement.deltaY) && (measurement.snapped === void 0 || typeof measurement.snapped === "boolean");
|
|
5947
|
+
};
|
|
5948
|
+
var isGuide = (value) => {
|
|
5949
|
+
if (!value || typeof value !== "object") return false;
|
|
5950
|
+
const guide = value;
|
|
5951
|
+
return typeof guide.id === "string" && (guide.orientation === "vertical" || guide.orientation === "horizontal") && isFiniteNumber(guide.position);
|
|
5952
|
+
};
|
|
5953
|
+
var isDistanceOverlay = (value) => {
|
|
5954
|
+
if (!value || typeof value !== "object") return false;
|
|
5955
|
+
const distance = value;
|
|
5956
|
+
const isDistanceLine = (line) => {
|
|
5957
|
+
if (line === null) return true;
|
|
5958
|
+
if (!line || typeof line !== "object") return false;
|
|
5959
|
+
const item = line;
|
|
5960
|
+
return isFiniteNumber(item.x1) && isFiniteNumber(item.x2) && isFiniteNumber(item.y) && isFiniteNumber(item.value);
|
|
5961
|
+
};
|
|
5962
|
+
const isVerticalLine = (line) => {
|
|
5963
|
+
if (line === null) return true;
|
|
5964
|
+
if (!line || typeof line !== "object") return false;
|
|
5965
|
+
const item = line;
|
|
5966
|
+
return isFiniteNumber(item.y1) && isFiniteNumber(item.y2) && isFiniteNumber(item.x) && isFiniteNumber(item.value);
|
|
5967
|
+
};
|
|
5968
|
+
return typeof distance.id === "string" && isRect(distance.rectA) && isRect(distance.rectB) && isNormalizedRect(distance.normalizedRectA) && isNormalizedRect(distance.normalizedRectB) && isDistanceLine(distance.horizontal) && isVerticalLine(distance.vertical) && Array.isArray(distance.connectors) && distance.connectors.every((connector) => {
|
|
5969
|
+
if (!connector || typeof connector !== "object") return false;
|
|
5970
|
+
const item = connector;
|
|
5971
|
+
return isFiniteNumber(item.x1) && isFiniteNumber(item.y1) && isFiniteNumber(item.x2) && isFiniteNumber(item.y2);
|
|
5972
|
+
});
|
|
5973
|
+
};
|
|
5974
|
+
var normalizeStoredSettings = (value) => {
|
|
5975
|
+
if (!value || typeof value !== "object") return {};
|
|
5976
|
+
const input = value;
|
|
5977
|
+
return {
|
|
5978
|
+
...typeof input.highlightColor === "string" ? { highlightColor: input.highlightColor } : {},
|
|
5979
|
+
...typeof input.guideColor === "string" ? { guideColor: input.guideColor } : {},
|
|
5980
|
+
...typeof input.hoverHighlightEnabled === "boolean" ? { hoverHighlightEnabled: input.hoverHighlightEnabled } : {},
|
|
5981
|
+
...Array.isArray(input.colorPickerFormats) && input.colorPickerFormats.some(isFormat) ? { colorPickerFormats: input.colorPickerFormats.filter(isFormat) } : {},
|
|
5982
|
+
...isFormat(input.colorPickerClickFormat) ? { colorPickerClickFormat: input.colorPickerClickFormat } : {},
|
|
5983
|
+
...typeof input.snapEnabled === "boolean" ? { snapEnabled: input.snapEnabled } : {},
|
|
5984
|
+
...typeof input.snapGuidesEnabled === "boolean" ? { snapGuidesEnabled: input.snapGuidesEnabled } : {},
|
|
5985
|
+
...typeof input.selectNewGuideEnabled === "boolean" ? { selectNewGuideEnabled: input.selectNewGuideEnabled } : {},
|
|
5986
|
+
...typeof input.multiMeasureEnabled === "boolean" ? { multiMeasureEnabled: input.multiMeasureEnabled } : {},
|
|
5987
|
+
...typeof input.persistOnReload === "boolean" ? { persistOnReload: input.persistOnReload } : {},
|
|
5988
|
+
...normalizeGuideStyle(input.guideStyle) ? { guideStyle: normalizeGuideStyle(input.guideStyle) } : {},
|
|
5989
|
+
...normalizeRulerSettings(input.rulerSettings) ? { rulerSettings: normalizeRulerSettings(input.rulerSettings) } : {}
|
|
5990
|
+
};
|
|
5991
|
+
};
|
|
5992
|
+
var normalizeStoredWorkspace = (value) => {
|
|
5993
|
+
if (!value || typeof value !== "object") return null;
|
|
5994
|
+
const input = value;
|
|
5995
|
+
if (typeof input.enabled !== "boolean" || input.toolMode !== "none" && input.toolMode !== "select" && input.toolMode !== "guides" && input.toolMode !== "text-inspector" && input.toolMode !== "xray" && input.toolMode !== "rulers" || typeof input.rulersVisible !== "boolean" || input.guideOrientation !== "vertical" && input.guideOrientation !== "horizontal" || !Array.isArray(input.guides) || !Array.isArray(input.selectedGuideIds) || !Array.isArray(input.measurements) || !Array.isArray(input.heldDistances)) return null;
|
|
5996
|
+
return {
|
|
5997
|
+
enabled: input.enabled,
|
|
5998
|
+
xrayVisible: typeof input.xrayVisible === "boolean" ? input.xrayVisible : input.toolMode === "xray",
|
|
5999
|
+
toolMode: input.toolMode,
|
|
6000
|
+
rulersVisible: input.rulersVisible,
|
|
6001
|
+
guideOrientation: input.guideOrientation,
|
|
6002
|
+
guides: input.guides.filter(isGuide),
|
|
6003
|
+
selectedGuideIds: input.selectedGuideIds.filter((id) => typeof id === "string"),
|
|
6004
|
+
measurements: input.measurements.filter(isMeasurement),
|
|
6005
|
+
activeMeasurement: isMeasurement(input.activeMeasurement) ? input.activeMeasurement : null,
|
|
6006
|
+
heldDistances: input.heldDistances.filter(isDistanceOverlay)
|
|
6007
|
+
};
|
|
6008
|
+
};
|
|
6009
|
+
var normalizePersistenceSnapshot = (value) => {
|
|
6010
|
+
if (!value || typeof value !== "object") return null;
|
|
6011
|
+
const record = value;
|
|
6012
|
+
if (record.version !== MESURER_STORAGE_VERSION) return null;
|
|
6013
|
+
return {
|
|
6014
|
+
settings: normalizeStoredSettings(record.settings),
|
|
6015
|
+
workspace: normalizeStoredWorkspace(record.workspace)
|
|
6016
|
+
};
|
|
6017
|
+
};
|
|
6018
|
+
var migrate = (record) => {
|
|
6019
|
+
if (record.version === MESURER_STORAGE_VERSION) {
|
|
6020
|
+
return normalizePersistenceSnapshot(record);
|
|
6021
|
+
}
|
|
6022
|
+
if (record.version !== 1) return null;
|
|
6023
|
+
return {
|
|
6024
|
+
settings: {},
|
|
6025
|
+
workspace: record.enabled === void 0 || !record.toolMode || !record.guideOrientation || !record.guides || !record.selectedGuideIds || !record.measurements || record.activeMeasurement === void 0 || !record.heldDistances ? null : normalizeStoredWorkspace({
|
|
6026
|
+
enabled: record.enabled,
|
|
6027
|
+
xrayVisible: record.toolMode === "xray",
|
|
6028
|
+
toolMode: record.toolMode,
|
|
6029
|
+
rulersVisible: record.rulersVisible ?? record.toolMode === "rulers",
|
|
6030
|
+
guideOrientation: record.guideOrientation,
|
|
6031
|
+
guides: record.guides,
|
|
6032
|
+
selectedGuideIds: record.selectedGuideIds,
|
|
6033
|
+
measurements: record.measurements,
|
|
6034
|
+
activeMeasurement: record.activeMeasurement,
|
|
6035
|
+
heldDistances: record.heldDistances
|
|
6036
|
+
})
|
|
6037
|
+
};
|
|
6038
|
+
};
|
|
6039
|
+
var createLocalStoragePersistence = (ownerWindow, workspaceKey, settingsKey = workspaceKey, legacyKey) => {
|
|
6040
|
+
let errorHandler;
|
|
6041
|
+
const readRecord = (key) => {
|
|
6042
|
+
try {
|
|
6043
|
+
const raw = ownerWindow.localStorage.getItem(key);
|
|
6044
|
+
if (!raw) return null;
|
|
6045
|
+
return migrate(JSON.parse(raw));
|
|
6046
|
+
} catch (error) {
|
|
6047
|
+
errorHandler?.(error);
|
|
6048
|
+
return null;
|
|
6049
|
+
}
|
|
6050
|
+
};
|
|
6051
|
+
const read = () => {
|
|
6052
|
+
const legacy = legacyKey ? readRecord(legacyKey) : null;
|
|
6053
|
+
const settingsRecord = readRecord(settingsKey);
|
|
6054
|
+
const workspaceRecord = readRecord(workspaceKey);
|
|
6055
|
+
if (!settingsRecord && !workspaceRecord && !legacy) return null;
|
|
6056
|
+
return {
|
|
6057
|
+
settings: settingsRecord?.settings ?? legacy?.settings ?? {},
|
|
6058
|
+
workspace: workspaceRecord?.workspace ?? legacy?.workspace ?? null
|
|
6059
|
+
};
|
|
6060
|
+
};
|
|
6061
|
+
const writeRecord = (key, snapshot) => {
|
|
6062
|
+
try {
|
|
6063
|
+
ownerWindow.localStorage.setItem(
|
|
6064
|
+
key,
|
|
6065
|
+
JSON.stringify({ version: MESURER_STORAGE_VERSION, ...snapshot })
|
|
6066
|
+
);
|
|
6067
|
+
} catch (error) {
|
|
6068
|
+
errorHandler?.(error);
|
|
6069
|
+
}
|
|
6070
|
+
};
|
|
6071
|
+
return {
|
|
6072
|
+
load: read,
|
|
6073
|
+
saveSettings: (settings) => {
|
|
6074
|
+
if (settingsKey === workspaceKey) {
|
|
6075
|
+
writeRecord(workspaceKey, { settings, workspace: read()?.workspace ?? null });
|
|
6076
|
+
return;
|
|
6077
|
+
}
|
|
6078
|
+
writeRecord(settingsKey, { settings, workspace: null });
|
|
6079
|
+
},
|
|
6080
|
+
saveWorkspace: (workspace) => {
|
|
6081
|
+
if (settingsKey === workspaceKey) {
|
|
6082
|
+
writeRecord(workspaceKey, { settings: read()?.settings ?? {}, workspace });
|
|
6083
|
+
return;
|
|
6084
|
+
}
|
|
6085
|
+
writeRecord(workspaceKey, { settings: {}, workspace });
|
|
6086
|
+
},
|
|
6087
|
+
clearWorkspace: () => {
|
|
6088
|
+
if (settingsKey === workspaceKey) {
|
|
6089
|
+
const current = read();
|
|
6090
|
+
if (current) writeRecord(workspaceKey, { settings: current.settings, workspace: null });
|
|
6091
|
+
return;
|
|
6092
|
+
}
|
|
6093
|
+
writeRecord(workspaceKey, { settings: {}, workspace: null });
|
|
6094
|
+
},
|
|
6095
|
+
clearSettings: () => {
|
|
6096
|
+
if (settingsKey === workspaceKey) {
|
|
6097
|
+
writeRecord(workspaceKey, { settings: {}, workspace: read()?.workspace ?? null });
|
|
6098
|
+
return;
|
|
6099
|
+
}
|
|
6100
|
+
writeRecord(settingsKey, { settings: {}, workspace: null });
|
|
6101
|
+
},
|
|
6102
|
+
setErrorHandler: (handler) => {
|
|
6103
|
+
errorHandler = handler;
|
|
6104
|
+
},
|
|
6105
|
+
subscribe: (listener) => {
|
|
6106
|
+
const handleStorage = (event) => {
|
|
6107
|
+
if (event.key !== settingsKey && event.key !== workspaceKey && event.key !== legacyKey) return;
|
|
6108
|
+
listener(read(), {
|
|
6109
|
+
settings: event.key === settingsKey || event.key === legacyKey || settingsKey === workspaceKey,
|
|
6110
|
+
workspace: event.key === workspaceKey || event.key === legacyKey || settingsKey === workspaceKey
|
|
6111
|
+
});
|
|
6112
|
+
};
|
|
6113
|
+
ownerWindow.addEventListener("storage", handleStorage);
|
|
6114
|
+
return () => {
|
|
6115
|
+
ownerWindow.removeEventListener("storage", handleStorage);
|
|
6116
|
+
};
|
|
6117
|
+
}
|
|
6118
|
+
};
|
|
6119
|
+
};
|
|
6120
|
+
|
|
4636
6121
|
// measurer.tsx
|
|
4637
|
-
import { jsx as
|
|
6122
|
+
import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
4638
6123
|
var measurerInstanceCount = 0;
|
|
4639
6124
|
var XRAY_STYLE_ID = "mesurer-xray-styles";
|
|
4640
6125
|
var XRAY_STYLES = `
|
|
@@ -4646,7 +6131,11 @@ var XRAY_STYLES = `
|
|
|
4646
6131
|
.xray-mode .mesurer-root,
|
|
4647
6132
|
.xray-mode .mesurer-root *,
|
|
4648
6133
|
.xray-mode .mesurer-toolbar-surface,
|
|
4649
|
-
.xray-mode .mesurer-toolbar-surface
|
|
6134
|
+
.xray-mode .mesurer-toolbar-surface *,
|
|
6135
|
+
.xray-mode .mesurer-ti-box,
|
|
6136
|
+
.xray-mode .mesurer-ti-card,
|
|
6137
|
+
.xray-mode .mesurer-ti-card *,
|
|
6138
|
+
.xray-mode .mesurer-ti-close {
|
|
4650
6139
|
outline: none !important;
|
|
4651
6140
|
}
|
|
4652
6141
|
`;
|
|
@@ -4666,70 +6155,112 @@ var stripDistance = (distance) => ({
|
|
|
4666
6155
|
elementRefA: void 0,
|
|
4667
6156
|
elementRefB: void 0
|
|
4668
6157
|
});
|
|
6158
|
+
var TAB_ID_KEY = "mesurer:tab-id";
|
|
6159
|
+
var SETTINGS_STORAGE_KEY = "mesurer-settings";
|
|
6160
|
+
var LEGACY_STORAGE_KEY = "mesurer-state";
|
|
6161
|
+
var getTabId = (ownerWindow) => {
|
|
6162
|
+
try {
|
|
6163
|
+
const existing = ownerWindow.sessionStorage.getItem(TAB_ID_KEY);
|
|
6164
|
+
if (existing) return existing;
|
|
6165
|
+
const id = ownerWindow.crypto.randomUUID();
|
|
6166
|
+
ownerWindow.sessionStorage.setItem(TAB_ID_KEY, id);
|
|
6167
|
+
return id;
|
|
6168
|
+
} catch {
|
|
6169
|
+
return "session";
|
|
6170
|
+
}
|
|
6171
|
+
};
|
|
6172
|
+
var sanitizeStoredSettings = (ownerWindow, settings) => {
|
|
6173
|
+
const supportsColor = (value) => value !== void 0 && ownerWindow.CSS?.supports("color", value) === true;
|
|
6174
|
+
return {
|
|
6175
|
+
...settings,
|
|
6176
|
+
...supportsColor(settings.highlightColor) ? {} : { highlightColor: void 0 },
|
|
6177
|
+
...supportsColor(settings.guideColor) ? {} : { guideColor: void 0 }
|
|
6178
|
+
};
|
|
6179
|
+
};
|
|
4669
6180
|
function MeasurerClient({
|
|
4670
6181
|
highlightColor,
|
|
4671
6182
|
guideColor,
|
|
4672
6183
|
hoverHighlightEnabled,
|
|
4673
6184
|
persistOnReload,
|
|
4674
6185
|
portalTarget,
|
|
4675
|
-
persistKey
|
|
6186
|
+
persistKey,
|
|
6187
|
+
colorPickerFormats,
|
|
6188
|
+
colorPickerClickFormat,
|
|
6189
|
+
snapEnabled: snapEnabledDefault,
|
|
6190
|
+
snapGuidesEnabled: snapGuidesEnabledDefault,
|
|
6191
|
+
selectNewGuideEnabled: selectNewGuideEnabledDefault,
|
|
6192
|
+
multiMeasureEnabled: multiMeasureEnabledDefault,
|
|
6193
|
+
guideStyle: guideStyleDefault,
|
|
6194
|
+
rulerSettings: rulerSettingsDefault,
|
|
6195
|
+
persistence,
|
|
6196
|
+
onPersistenceError
|
|
4676
6197
|
}) {
|
|
4677
|
-
const instanceIdRef =
|
|
6198
|
+
const instanceIdRef = useRef12(null);
|
|
4678
6199
|
if (instanceIdRef.current === null) {
|
|
4679
6200
|
instanceIdRef.current = ++measurerInstanceCount;
|
|
4680
6201
|
}
|
|
4681
|
-
const storageKey = persistKey ?? (instanceIdRef.current === 1 ? "mesurer-state" : `mesurer-state-${instanceIdRef.current}`);
|
|
4682
6202
|
const ownerDocument = portalTarget.ownerDocument ?? document;
|
|
4683
6203
|
const ownerWindow = ownerDocument.defaultView ?? window;
|
|
4684
|
-
const
|
|
6204
|
+
const tabIdRef = useRef12(null);
|
|
6205
|
+
if (tabIdRef.current === null) tabIdRef.current = getTabId(ownerWindow);
|
|
6206
|
+
const storageKey = persistKey ?? (instanceIdRef.current === 1 ? `mesurer-state:${tabIdRef.current}` : `mesurer-state:${tabIdRef.current}:${instanceIdRef.current}`);
|
|
6207
|
+
const legacyStorageKey = persistKey ? void 0 : LEGACY_STORAGE_KEY;
|
|
6208
|
+
const guideScrollRef = useRef12({
|
|
4685
6209
|
x: ownerWindow.scrollX,
|
|
4686
6210
|
y: ownerWindow.scrollY
|
|
4687
6211
|
});
|
|
4688
|
-
const textInspectorRef =
|
|
6212
|
+
const textInspectorRef = useRef12(null);
|
|
4689
6213
|
if (!textInspectorRef.current) {
|
|
4690
6214
|
textInspectorRef.current = createTextInspector({ portalTarget });
|
|
4691
6215
|
}
|
|
4692
6216
|
const textInspector = textInspectorRef.current;
|
|
4693
|
-
const selectionRectRef =
|
|
4694
|
-
const toolbarRef =
|
|
4695
|
-
const selectionAnimationCleanupTimeoutRef =
|
|
4696
|
-
const guideDragRef =
|
|
4697
|
-
const guideUserSelectRef =
|
|
4698
|
-
const
|
|
4699
|
-
|
|
4700
|
-
|
|
4701
|
-
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4706
|
-
|
|
4707
|
-
|
|
4708
|
-
|
|
4709
|
-
|
|
4710
|
-
const
|
|
4711
|
-
|
|
6217
|
+
const selectionRectRef = useRef12(null);
|
|
6218
|
+
const toolbarRef = useRef12(null);
|
|
6219
|
+
const selectionAnimationCleanupTimeoutRef = useRef12(null);
|
|
6220
|
+
const guideDragRef = useRef12(null);
|
|
6221
|
+
const guideUserSelectRef = useRef12(null);
|
|
6222
|
+
const persistenceErrorHandlerRef = useRef12(onPersistenceError);
|
|
6223
|
+
persistenceErrorHandlerRef.current = onPersistenceError;
|
|
6224
|
+
const activePersistence = useMemo2(() => {
|
|
6225
|
+
const next = persistence ?? createLocalStoragePersistence(ownerWindow, storageKey, SETTINGS_STORAGE_KEY, legacyStorageKey);
|
|
6226
|
+
next.setErrorHandler?.((error) => persistenceErrorHandlerRef.current?.(error));
|
|
6227
|
+
return next;
|
|
6228
|
+
}, [legacyStorageKey, ownerWindow, persistence, storageKey]);
|
|
6229
|
+
const storedState = useMemo2(
|
|
6230
|
+
() => activePersistence.load(),
|
|
6231
|
+
[activePersistence]
|
|
6232
|
+
);
|
|
6233
|
+
const persistedState = persistOnReload || storedState?.settings.persistOnReload ? storedState?.workspace ?? null : null;
|
|
6234
|
+
const persistedSettings = sanitizeStoredSettings(ownerWindow, storedState?.settings ?? {});
|
|
6235
|
+
useEffect7(() => {
|
|
6236
|
+
return () => activePersistence.setErrorHandler?.(void 0);
|
|
6237
|
+
}, [activePersistence]);
|
|
6238
|
+
const enabledRef = useRef12(false);
|
|
6239
|
+
const toolModeRef = useRef12(
|
|
4712
6240
|
persistedState?.toolMode === "rulers" ? "none" : persistedState?.toolMode ?? "none"
|
|
4713
6241
|
);
|
|
4714
|
-
const rulersVisibleRef =
|
|
6242
|
+
const rulersVisibleRef = useRef12(
|
|
4715
6243
|
persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers"
|
|
4716
6244
|
);
|
|
4717
|
-
const
|
|
6245
|
+
const xrayVisibleRef = useRef12(persistedState?.xrayVisible ?? persistedState?.toolMode === "xray");
|
|
6246
|
+
const guideOrientationRef = useRef12(
|
|
4718
6247
|
persistedState?.guideOrientation ?? "vertical"
|
|
4719
6248
|
);
|
|
4720
|
-
const measurementsRef =
|
|
6249
|
+
const measurementsRef = useRef12(
|
|
4721
6250
|
persistedState?.measurements ?? []
|
|
4722
6251
|
);
|
|
4723
|
-
const activeMeasurementRef =
|
|
6252
|
+
const activeMeasurementRef = useRef12(
|
|
4724
6253
|
persistedState?.activeMeasurement ?? null
|
|
4725
6254
|
);
|
|
4726
|
-
const heldDistancesRef =
|
|
6255
|
+
const heldDistancesRef = useRef12(
|
|
4727
6256
|
persistedState?.heldDistances ?? []
|
|
4728
6257
|
);
|
|
4729
|
-
const guidesRef =
|
|
4730
|
-
const selectedGuideIdsRef =
|
|
6258
|
+
const guidesRef = useRef12(persistedState?.guides ?? []);
|
|
6259
|
+
const selectedGuideIdsRef = useRef12(
|
|
4731
6260
|
persistedState?.selectedGuideIds ?? []
|
|
4732
6261
|
);
|
|
6262
|
+
const workspacePersistTimeoutRef = useRef12(null);
|
|
6263
|
+
const applyingExternalPersistenceRef = useRef12(false);
|
|
4733
6264
|
const { overlayRef, selectedElementRef, hoverElementRef } = useOverlayRefs();
|
|
4734
6265
|
const {
|
|
4735
6266
|
selectionOriginRect,
|
|
@@ -4759,11 +6290,20 @@ function MeasurerClient({
|
|
|
4759
6290
|
setRulersVisible,
|
|
4760
6291
|
guidesEnabled,
|
|
4761
6292
|
multiMeasureEnabled,
|
|
4762
|
-
snapGuidesEnabled
|
|
6293
|
+
snapGuidesEnabled,
|
|
6294
|
+
setSnapGuidesEnabled,
|
|
6295
|
+
selectNewGuideEnabled,
|
|
6296
|
+
setSelectNewGuideEnabled,
|
|
6297
|
+
setSnapEnabled,
|
|
6298
|
+
setMultiMeasureEnabled
|
|
4763
6299
|
} = useMeasureToggles({
|
|
4764
6300
|
initialEnabled: persistedState?.enabled,
|
|
4765
6301
|
initialToolMode: persistedState?.toolMode === "rulers" ? "none" : persistedState?.toolMode,
|
|
4766
|
-
initialRulersVisible: persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers"
|
|
6302
|
+
initialRulersVisible: persistedState?.rulersVisible ?? persistedState?.toolMode === "rulers",
|
|
6303
|
+
initialSnapEnabled: persistedSettings.snapEnabled ?? snapEnabledDefault,
|
|
6304
|
+
initialSnapGuidesEnabled: persistedSettings.snapGuidesEnabled ?? snapGuidesEnabledDefault,
|
|
6305
|
+
initialSelectNewGuideEnabled: persistedSettings.selectNewGuideEnabled ?? selectNewGuideEnabledDefault,
|
|
6306
|
+
initialMultiMeasureEnabled: persistedSettings.multiMeasureEnabled ?? multiMeasureEnabledDefault
|
|
4767
6307
|
});
|
|
4768
6308
|
const { start, setStart, end, setEnd, isDragging, setIsDragging } = useDragState();
|
|
4769
6309
|
const {
|
|
@@ -4795,11 +6335,59 @@ function MeasurerClient({
|
|
|
4795
6335
|
initialGuides: persistedState?.guides ?? [],
|
|
4796
6336
|
initialSelectedGuideIds: persistedState?.selectedGuideIds ?? []
|
|
4797
6337
|
});
|
|
4798
|
-
const [toolbarActive, setToolbarActive] =
|
|
6338
|
+
const [toolbarActive, setToolbarActive] = useState11(true);
|
|
6339
|
+
const [colorPickerActive, setColorPickerActive] = useState11(false);
|
|
6340
|
+
const [colorPickerSample, setColorPickerSample] = useState11(null);
|
|
6341
|
+
const [colorPickerUnsupported, setColorPickerUnsupported] = useState11(false);
|
|
6342
|
+
const [settingsOpen, setSettingsOpen] = useState11(false);
|
|
6343
|
+
const [settingsTab, setSettingsTab] = useState11("general");
|
|
6344
|
+
const [settingsHighlightColor, setSettingsHighlightColor] = useState11(
|
|
6345
|
+
persistedSettings.highlightColor ?? highlightColor
|
|
6346
|
+
);
|
|
6347
|
+
const [settingsGuideColor, setSettingsGuideColor] = useState11(
|
|
6348
|
+
persistedSettings.guideColor ?? guideColor
|
|
6349
|
+
);
|
|
6350
|
+
const [settingsHoverHighlight, setSettingsHoverHighlight] = useState11(
|
|
6351
|
+
persistedSettings.hoverHighlightEnabled ?? hoverHighlightEnabled
|
|
6352
|
+
);
|
|
6353
|
+
const [settingsPersistOnReload, setSettingsPersistOnReload] = useState11(
|
|
6354
|
+
persistedSettings.persistOnReload ?? persistOnReload
|
|
6355
|
+
);
|
|
6356
|
+
const [settingsColorFormats, setSettingsColorFormats] = useState11(
|
|
6357
|
+
persistedSettings.colorPickerFormats ?? colorPickerFormats
|
|
6358
|
+
);
|
|
6359
|
+
const [settingsColorClickFormat, setSettingsColorClickFormat] = useState11(
|
|
6360
|
+
persistedSettings.colorPickerClickFormat ?? colorPickerClickFormat
|
|
6361
|
+
);
|
|
6362
|
+
const [settingsGuideStyle, setSettingsGuideStyle] = useState11({
|
|
6363
|
+
...guideStyleDefault,
|
|
6364
|
+
...persistedSettings.guideStyle
|
|
6365
|
+
});
|
|
6366
|
+
const [settingsRulerSettings, setSettingsRulerSettings] = useState11({
|
|
6367
|
+
...rulerSettingsDefault,
|
|
6368
|
+
...persistedSettings.rulerSettings
|
|
6369
|
+
});
|
|
6370
|
+
const [xrayVisible, setXrayVisible] = useState11(xrayVisibleRef.current);
|
|
4799
6371
|
const { clearGuideDragHold, scheduleGuideDragHold } = useGuideDragHold(ownerWindow);
|
|
4800
|
-
const [guidePreview, setGuidePreview] =
|
|
4801
|
-
const
|
|
6372
|
+
const [guidePreview, setGuidePreview] = useState11(null);
|
|
6373
|
+
const resetSettings = () => {
|
|
6374
|
+
setSettingsHighlightColor(highlightColor);
|
|
6375
|
+
setSettingsGuideColor(guideColor);
|
|
6376
|
+
setSettingsHoverHighlight(hoverHighlightEnabled);
|
|
6377
|
+
setSettingsPersistOnReload(persistOnReload);
|
|
6378
|
+
setSettingsColorFormats([...colorPickerFormats]);
|
|
6379
|
+
setSettingsColorClickFormat(colorPickerClickFormat);
|
|
6380
|
+
setSnapEnabled(snapEnabledDefault);
|
|
6381
|
+
setSnapGuidesEnabled(snapGuidesEnabledDefault);
|
|
6382
|
+
setSelectNewGuideEnabled(selectNewGuideEnabledDefault);
|
|
6383
|
+
setMultiMeasureEnabled(multiMeasureEnabledDefault);
|
|
6384
|
+
setSettingsGuideStyle({ ...guideStyleDefault });
|
|
6385
|
+
setSettingsRulerSettings({ ...rulerSettingsDefault });
|
|
6386
|
+
};
|
|
6387
|
+
const initialSettingsTab = colorPickerActive ? "color-picker" : rulersVisible ? "rulers" : toolMode === "guides" ? "guides" : toolMode === "select" || toolMode === "text-inspector" ? "select" : "general";
|
|
6388
|
+
const [guideOrientation, setGuideOrientation] = useState11(persistedState?.guideOrientation ?? "vertical");
|
|
4802
6389
|
enabledRef.current = enabled;
|
|
6390
|
+
xrayVisibleRef.current = xrayVisible;
|
|
4803
6391
|
toolModeRef.current = toolMode;
|
|
4804
6392
|
rulersVisibleRef.current = rulersVisible;
|
|
4805
6393
|
guideOrientationRef.current = guideOrientation;
|
|
@@ -4808,29 +6396,168 @@ function MeasurerClient({
|
|
|
4808
6396
|
heldDistancesRef.current = heldDistances;
|
|
4809
6397
|
guidesRef.current = guides;
|
|
4810
6398
|
selectedGuideIdsRef.current = selectedGuideIds;
|
|
4811
|
-
const
|
|
4812
|
-
if (!
|
|
4813
|
-
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4817
|
-
|
|
4818
|
-
|
|
4819
|
-
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
4825
|
-
|
|
4826
|
-
|
|
4827
|
-
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
6399
|
+
const saveWorkspace = useCallback8(() => {
|
|
6400
|
+
if (!settingsPersistOnReload) return;
|
|
6401
|
+
const workspace = {
|
|
6402
|
+
enabled: enabledRef.current,
|
|
6403
|
+
xrayVisible: xrayVisibleRef.current,
|
|
6404
|
+
toolMode: toolModeRef.current,
|
|
6405
|
+
rulersVisible: rulersVisibleRef.current,
|
|
6406
|
+
guideOrientation: guideOrientationRef.current,
|
|
6407
|
+
guides: guidesRef.current,
|
|
6408
|
+
selectedGuideIds: selectedGuideIdsRef.current,
|
|
6409
|
+
measurements: measurementsRef.current.map(stripMeasurement),
|
|
6410
|
+
activeMeasurement: activeMeasurementRef.current ? stripMeasurement(activeMeasurementRef.current) : null,
|
|
6411
|
+
heldDistances: heldDistancesRef.current.map(stripDistance)
|
|
6412
|
+
};
|
|
6413
|
+
activePersistence.saveWorkspace(workspace);
|
|
6414
|
+
}, [activePersistence, settingsPersistOnReload]);
|
|
6415
|
+
const persistState = useCallback8(() => {
|
|
6416
|
+
if (!settingsPersistOnReload) return;
|
|
6417
|
+
if (workspacePersistTimeoutRef.current !== null) {
|
|
6418
|
+
ownerWindow.clearTimeout(workspacePersistTimeoutRef.current);
|
|
6419
|
+
}
|
|
6420
|
+
workspacePersistTimeoutRef.current = ownerWindow.setTimeout(() => {
|
|
6421
|
+
workspacePersistTimeoutRef.current = null;
|
|
6422
|
+
saveWorkspace();
|
|
6423
|
+
}, 250);
|
|
6424
|
+
}, [ownerWindow, saveWorkspace, settingsPersistOnReload]);
|
|
6425
|
+
const persistSettings = useCallback8(() => {
|
|
6426
|
+
activePersistence.saveSettings({
|
|
6427
|
+
highlightColor: settingsHighlightColor,
|
|
6428
|
+
guideColor: settingsGuideColor,
|
|
6429
|
+
hoverHighlightEnabled: settingsHoverHighlight,
|
|
6430
|
+
colorPickerFormats: settingsColorFormats,
|
|
6431
|
+
colorPickerClickFormat: settingsColorClickFormat,
|
|
6432
|
+
snapEnabled,
|
|
6433
|
+
snapGuidesEnabled,
|
|
6434
|
+
selectNewGuideEnabled,
|
|
6435
|
+
multiMeasureEnabled,
|
|
6436
|
+
persistOnReload: settingsPersistOnReload,
|
|
6437
|
+
guideStyle: settingsGuideStyle,
|
|
6438
|
+
rulerSettings: settingsRulerSettings
|
|
6439
|
+
});
|
|
6440
|
+
}, [
|
|
6441
|
+
multiMeasureEnabled,
|
|
6442
|
+
selectNewGuideEnabled,
|
|
6443
|
+
settingsColorClickFormat,
|
|
6444
|
+
settingsColorFormats,
|
|
6445
|
+
settingsGuideColor,
|
|
6446
|
+
settingsHighlightColor,
|
|
6447
|
+
settingsHoverHighlight,
|
|
6448
|
+
settingsPersistOnReload,
|
|
6449
|
+
snapEnabled,
|
|
6450
|
+
snapGuidesEnabled,
|
|
6451
|
+
activePersistence,
|
|
6452
|
+
settingsGuideStyle,
|
|
6453
|
+
settingsRulerSettings
|
|
6454
|
+
]);
|
|
6455
|
+
useEffect7(() => {
|
|
6456
|
+
if (applyingExternalPersistenceRef.current) {
|
|
6457
|
+
applyingExternalPersistenceRef.current = false;
|
|
6458
|
+
return;
|
|
6459
|
+
}
|
|
6460
|
+
persistSettings();
|
|
6461
|
+
if (settingsPersistOnReload) persistState();
|
|
6462
|
+
}, [persistSettings, persistState, settingsPersistOnReload]);
|
|
6463
|
+
useEffect7(() => {
|
|
6464
|
+
if (!settingsPersistOnReload) return;
|
|
6465
|
+
const handleBeforeUnload = () => saveWorkspace();
|
|
6466
|
+
ownerWindow.addEventListener("beforeunload", handleBeforeUnload);
|
|
6467
|
+
return () => {
|
|
6468
|
+
ownerWindow.removeEventListener("beforeunload", handleBeforeUnload);
|
|
6469
|
+
if (workspacePersistTimeoutRef.current !== null) {
|
|
6470
|
+
ownerWindow.clearTimeout(workspacePersistTimeoutRef.current);
|
|
6471
|
+
workspacePersistTimeoutRef.current = null;
|
|
6472
|
+
saveWorkspace();
|
|
6473
|
+
}
|
|
6474
|
+
};
|
|
6475
|
+
}, [ownerWindow, saveWorkspace, settingsPersistOnReload]);
|
|
6476
|
+
const clearPersistedWorkspace = useCallback8(() => {
|
|
6477
|
+
enabledRef.current = false;
|
|
6478
|
+
toolModeRef.current = "none";
|
|
6479
|
+
rulersVisibleRef.current = false;
|
|
6480
|
+
xrayVisibleRef.current = false;
|
|
6481
|
+
guideOrientationRef.current = "vertical";
|
|
6482
|
+
measurementsRef.current = [];
|
|
6483
|
+
activeMeasurementRef.current = null;
|
|
6484
|
+
heldDistancesRef.current = [];
|
|
6485
|
+
guidesRef.current = [];
|
|
6486
|
+
selectedGuideIdsRef.current = [];
|
|
6487
|
+
setEnabled(false);
|
|
6488
|
+
setToolMode("none");
|
|
6489
|
+
setRulersVisible(false);
|
|
6490
|
+
setXrayVisible(false);
|
|
6491
|
+
setGuideOrientation("vertical");
|
|
6492
|
+
setMeasurements([]);
|
|
6493
|
+
setActiveMeasurement(null);
|
|
6494
|
+
setSelectedMeasurement(null);
|
|
6495
|
+
setSelectedMeasurements([]);
|
|
6496
|
+
setHeldDistances([]);
|
|
6497
|
+
setGuides([]);
|
|
6498
|
+
setSelectedGuideIds([]);
|
|
6499
|
+
}, [setActiveMeasurement, setEnabled, setGuideOrientation, setGuides, setHeldDistances, setMeasurements, setRulersVisible, setSelectedGuideIds, setSelectedMeasurement, setSelectedMeasurements, setToolMode]);
|
|
6500
|
+
const clearWorkspace = useCallback8(() => {
|
|
6501
|
+
clearPersistedWorkspace();
|
|
6502
|
+
activePersistence.clearWorkspace();
|
|
6503
|
+
}, [activePersistence, clearPersistedWorkspace]);
|
|
6504
|
+
const applyPersistedWorkspace = useCallback8((workspace) => {
|
|
6505
|
+
enabledRef.current = workspace.enabled;
|
|
6506
|
+
toolModeRef.current = workspace.toolMode;
|
|
6507
|
+
rulersVisibleRef.current = workspace.rulersVisible;
|
|
6508
|
+
xrayVisibleRef.current = workspace.xrayVisible;
|
|
6509
|
+
guideOrientationRef.current = workspace.guideOrientation;
|
|
6510
|
+
measurementsRef.current = workspace.measurements;
|
|
6511
|
+
activeMeasurementRef.current = workspace.activeMeasurement;
|
|
6512
|
+
heldDistancesRef.current = workspace.heldDistances;
|
|
6513
|
+
guidesRef.current = workspace.guides;
|
|
6514
|
+
selectedGuideIdsRef.current = workspace.selectedGuideIds;
|
|
6515
|
+
setEnabled(workspace.enabled);
|
|
6516
|
+
setToolMode(workspace.toolMode);
|
|
6517
|
+
setRulersVisible(workspace.rulersVisible);
|
|
6518
|
+
setXrayVisible(workspace.xrayVisible);
|
|
6519
|
+
setGuideOrientation(workspace.guideOrientation);
|
|
6520
|
+
setMeasurements(workspace.measurements);
|
|
6521
|
+
setActiveMeasurement(workspace.activeMeasurement);
|
|
6522
|
+
setGuides(workspace.guides);
|
|
6523
|
+
setSelectedGuideIds(workspace.selectedGuideIds);
|
|
6524
|
+
setHeldDistances(workspace.heldDistances);
|
|
6525
|
+
}, [setActiveMeasurement, setEnabled, setGuideOrientation, setGuides, setHeldDistances, setMeasurements, setRulersVisible, setSelectedGuideIds, setToolMode]);
|
|
6526
|
+
const applyPersistenceSnapshot = useCallback8((snapshot, source) => {
|
|
6527
|
+
if (!snapshot) return;
|
|
6528
|
+
applyingExternalPersistenceRef.current = true;
|
|
6529
|
+
const settings = sanitizeStoredSettings(ownerWindow, snapshot.settings);
|
|
6530
|
+
if (settings.highlightColor !== void 0) setSettingsHighlightColor(settings.highlightColor);
|
|
6531
|
+
if (settings.guideColor !== void 0) setSettingsGuideColor(settings.guideColor);
|
|
6532
|
+
if (settings.hoverHighlightEnabled !== void 0) setSettingsHoverHighlight(settings.hoverHighlightEnabled);
|
|
6533
|
+
if (settings.colorPickerFormats !== void 0) setSettingsColorFormats(settings.colorPickerFormats);
|
|
6534
|
+
if (settings.colorPickerClickFormat !== void 0) setSettingsColorClickFormat(settings.colorPickerClickFormat);
|
|
6535
|
+
if (settings.persistOnReload !== void 0) setSettingsPersistOnReload(settings.persistOnReload);
|
|
6536
|
+
if (settings.snapEnabled !== void 0) setSnapEnabled(settings.snapEnabled);
|
|
6537
|
+
if (settings.snapGuidesEnabled !== void 0) setSnapGuidesEnabled(settings.snapGuidesEnabled);
|
|
6538
|
+
if (settings.selectNewGuideEnabled !== void 0) setSelectNewGuideEnabled(settings.selectNewGuideEnabled);
|
|
6539
|
+
if (settings.multiMeasureEnabled !== void 0) setMultiMeasureEnabled(settings.multiMeasureEnabled);
|
|
6540
|
+
if (settings.guideStyle !== void 0) setSettingsGuideStyle({ ...guideStyleDefault, ...settings.guideStyle });
|
|
6541
|
+
if (settings.rulerSettings !== void 0) setSettingsRulerSettings({ ...rulerSettingsDefault, ...settings.rulerSettings });
|
|
6542
|
+
const workspace = snapshot.workspace;
|
|
6543
|
+
if (source?.workspace !== false && workspace && (settings.persistOnReload ?? settingsPersistOnReload)) {
|
|
6544
|
+
applyPersistedWorkspace(workspace);
|
|
4831
6545
|
}
|
|
4832
|
-
|
|
4833
|
-
|
|
6546
|
+
ownerWindow.setTimeout(() => {
|
|
6547
|
+
applyingExternalPersistenceRef.current = false;
|
|
6548
|
+
}, 0);
|
|
6549
|
+
}, [applyPersistedWorkspace, guideStyleDefault, ownerWindow, rulerSettingsDefault, setMultiMeasureEnabled, setSelectNewGuideEnabled, setSettingsColorClickFormat, setSettingsColorFormats, setSettingsGuideColor, setSettingsHighlightColor, setSettingsHoverHighlight, setSettingsPersistOnReload, setSnapEnabled, setSnapGuidesEnabled, settingsPersistOnReload]);
|
|
6550
|
+
const previousPersistenceRef = useRef12(activePersistence);
|
|
6551
|
+
useEffect7(() => {
|
|
6552
|
+
if (previousPersistenceRef.current === activePersistence) return;
|
|
6553
|
+
previousPersistenceRef.current = activePersistence;
|
|
6554
|
+
applyPersistenceSnapshot(storedState);
|
|
6555
|
+
}, [activePersistence, applyPersistenceSnapshot, storedState]);
|
|
6556
|
+
useEffect7(() => {
|
|
6557
|
+
const unsubscribe = activePersistence.subscribe?.(applyPersistenceSnapshot);
|
|
6558
|
+
return unsubscribe;
|
|
6559
|
+
}, [activePersistence, applyPersistenceSnapshot]);
|
|
6560
|
+
const setEnabledPersisted = useCallback8(
|
|
4834
6561
|
(value) => {
|
|
4835
6562
|
const next = typeof value === "function" ? value(enabledRef.current) : value;
|
|
4836
6563
|
if (Object.is(next, enabledRef.current)) return;
|
|
@@ -4840,7 +6567,7 @@ function MeasurerClient({
|
|
|
4840
6567
|
},
|
|
4841
6568
|
[persistState, setEnabled]
|
|
4842
6569
|
);
|
|
4843
|
-
const setRulersVisiblePersisted =
|
|
6570
|
+
const setRulersVisiblePersisted = useCallback8(
|
|
4844
6571
|
(value) => {
|
|
4845
6572
|
const next = typeof value === "function" ? value(rulersVisibleRef.current) : value;
|
|
4846
6573
|
if (Object.is(next, rulersVisibleRef.current)) return;
|
|
@@ -4850,7 +6577,7 @@ function MeasurerClient({
|
|
|
4850
6577
|
},
|
|
4851
6578
|
[persistState, setRulersVisible]
|
|
4852
6579
|
);
|
|
4853
|
-
const setToolModePersisted =
|
|
6580
|
+
const setToolModePersisted = useCallback8(
|
|
4854
6581
|
(value) => {
|
|
4855
6582
|
const next = typeof value === "function" ? value(toolModeRef.current) : value;
|
|
4856
6583
|
if (Object.is(next, toolModeRef.current)) return;
|
|
@@ -4865,7 +6592,7 @@ function MeasurerClient({
|
|
|
4865
6592
|
},
|
|
4866
6593
|
[persistState, setToolMode, textInspector]
|
|
4867
6594
|
);
|
|
4868
|
-
const setGuideOrientationPersisted =
|
|
6595
|
+
const setGuideOrientationPersisted = useCallback8(
|
|
4869
6596
|
(value) => {
|
|
4870
6597
|
const next = typeof value === "function" ? value(guideOrientationRef.current) : value;
|
|
4871
6598
|
if (Object.is(next, guideOrientationRef.current)) return;
|
|
@@ -4875,7 +6602,7 @@ function MeasurerClient({
|
|
|
4875
6602
|
},
|
|
4876
6603
|
[persistState, setGuideOrientation]
|
|
4877
6604
|
);
|
|
4878
|
-
const setMeasurementsPersisted =
|
|
6605
|
+
const setMeasurementsPersisted = useCallback8(
|
|
4879
6606
|
(value) => {
|
|
4880
6607
|
const next = typeof value === "function" ? value(measurementsRef.current) : value;
|
|
4881
6608
|
if (Object.is(next, measurementsRef.current)) return;
|
|
@@ -4885,7 +6612,7 @@ function MeasurerClient({
|
|
|
4885
6612
|
},
|
|
4886
6613
|
[persistState, setMeasurements]
|
|
4887
6614
|
);
|
|
4888
|
-
const setActiveMeasurementPersisted =
|
|
6615
|
+
const setActiveMeasurementPersisted = useCallback8(
|
|
4889
6616
|
(value) => {
|
|
4890
6617
|
const next = typeof value === "function" ? value(activeMeasurementRef.current) : value;
|
|
4891
6618
|
if (Object.is(next, activeMeasurementRef.current)) return;
|
|
@@ -4895,7 +6622,7 @@ function MeasurerClient({
|
|
|
4895
6622
|
},
|
|
4896
6623
|
[persistState, setActiveMeasurement]
|
|
4897
6624
|
);
|
|
4898
|
-
const setHeldDistancesPersisted =
|
|
6625
|
+
const setHeldDistancesPersisted = useCallback8(
|
|
4899
6626
|
(value) => {
|
|
4900
6627
|
const next = typeof value === "function" ? value(heldDistancesRef.current) : value;
|
|
4901
6628
|
if (Object.is(next, heldDistancesRef.current)) return;
|
|
@@ -4905,7 +6632,7 @@ function MeasurerClient({
|
|
|
4905
6632
|
},
|
|
4906
6633
|
[persistState, setHeldDistances]
|
|
4907
6634
|
);
|
|
4908
|
-
const setGuidesPersisted =
|
|
6635
|
+
const setGuidesPersisted = useCallback8(
|
|
4909
6636
|
(value) => {
|
|
4910
6637
|
const next = typeof value === "function" ? value(guidesRef.current) : value;
|
|
4911
6638
|
if (Object.is(next, guidesRef.current)) return;
|
|
@@ -4915,7 +6642,7 @@ function MeasurerClient({
|
|
|
4915
6642
|
},
|
|
4916
6643
|
[persistState, setGuides]
|
|
4917
6644
|
);
|
|
4918
|
-
const setSelectedGuideIdsPersisted =
|
|
6645
|
+
const setSelectedGuideIdsPersisted = useCallback8(
|
|
4919
6646
|
(value) => {
|
|
4920
6647
|
const next = typeof value === "function" ? value(selectedGuideIdsRef.current) : value;
|
|
4921
6648
|
if (Object.is(next, selectedGuideIdsRef.current)) return;
|
|
@@ -4973,15 +6700,15 @@ function MeasurerClient({
|
|
|
4973
6700
|
clearSelectionRect
|
|
4974
6701
|
}
|
|
4975
6702
|
});
|
|
4976
|
-
const undo =
|
|
6703
|
+
const undo = useCallback8(() => {
|
|
4977
6704
|
if (toolMode === "text-inspector" && textInspector.undo()) return;
|
|
4978
6705
|
undoHistory();
|
|
4979
6706
|
}, [textInspector, toolMode, undoHistory]);
|
|
4980
|
-
const redo =
|
|
6707
|
+
const redo = useCallback8(() => {
|
|
4981
6708
|
if (toolMode === "text-inspector" && textInspector.redo()) return;
|
|
4982
6709
|
redoHistory();
|
|
4983
6710
|
}, [redoHistory, textInspector, toolMode]);
|
|
4984
|
-
const clearAll =
|
|
6711
|
+
const clearAll = useCallback8(() => {
|
|
4985
6712
|
if (toolMode === "text-inspector") {
|
|
4986
6713
|
textInspector.clear();
|
|
4987
6714
|
}
|
|
@@ -5021,7 +6748,7 @@ function MeasurerClient({
|
|
|
5021
6748
|
textInspector,
|
|
5022
6749
|
toolMode
|
|
5023
6750
|
]);
|
|
5024
|
-
const removeSelectedGuides =
|
|
6751
|
+
const removeSelectedGuides = useCallback8(() => {
|
|
5025
6752
|
if (selectedGuideIds.length === 0) return false;
|
|
5026
6753
|
recordSnapshot();
|
|
5027
6754
|
setGuidesPersisted(
|
|
@@ -5035,6 +6762,37 @@ function MeasurerClient({
|
|
|
5035
6762
|
setGuidesPersisted,
|
|
5036
6763
|
setSelectedGuideIdsPersisted
|
|
5037
6764
|
]);
|
|
6765
|
+
const openColorPicker = useCallback8(async () => {
|
|
6766
|
+
const EyeDropper = ownerWindow.EyeDropper;
|
|
6767
|
+
setEnabledWithHistory(true);
|
|
6768
|
+
setToolModeWithHistory("none");
|
|
6769
|
+
setColorPickerActive(true);
|
|
6770
|
+
setColorPickerSample(null);
|
|
6771
|
+
setColorPickerUnsupported(!EyeDropper);
|
|
6772
|
+
if (!EyeDropper) return;
|
|
6773
|
+
try {
|
|
6774
|
+
const result = await new EyeDropper().open();
|
|
6775
|
+
const nextSample = parseCssColor(result.sRGBHex);
|
|
6776
|
+
if (!nextSample) return;
|
|
6777
|
+
setColorPickerSample(nextSample);
|
|
6778
|
+
const clipboardWrite = ownerWindow.navigator.clipboard?.writeText(
|
|
6779
|
+
formatColor(nextSample, settingsColorClickFormat)
|
|
6780
|
+
);
|
|
6781
|
+
void clipboardWrite?.catch(() => void 0);
|
|
6782
|
+
} catch (error) {
|
|
6783
|
+
if (error instanceof DOMException && error.name === "AbortError") {
|
|
6784
|
+
setColorPickerActive(false);
|
|
6785
|
+
}
|
|
6786
|
+
}
|
|
6787
|
+
}, [ownerWindow, setEnabledWithHistory, setToolModeWithHistory, settingsColorClickFormat]);
|
|
6788
|
+
const toggleSettings = useCallback8(() => {
|
|
6789
|
+
if (settingsOpen) {
|
|
6790
|
+
setSettingsOpen(false);
|
|
6791
|
+
return;
|
|
6792
|
+
}
|
|
6793
|
+
setSettingsTab(initialSettingsTab);
|
|
6794
|
+
setSettingsOpen(true);
|
|
6795
|
+
}, [initialSettingsTab, settingsOpen]);
|
|
5038
6796
|
useHotkeys({
|
|
5039
6797
|
eventTarget: ownerWindow,
|
|
5040
6798
|
clearAll,
|
|
@@ -5047,7 +6805,13 @@ function MeasurerClient({
|
|
|
5047
6805
|
setAltPressed,
|
|
5048
6806
|
isOverlayActive: () => enabled && (toolMode !== "none" || toolbarActive),
|
|
5049
6807
|
setGuideOrientation: setGuideOrientationWithHistory,
|
|
5050
|
-
onInteract: () => setToolbarActive(true)
|
|
6808
|
+
onInteract: () => setToolbarActive(true),
|
|
6809
|
+
onColorPicker: openColorPicker,
|
|
6810
|
+
onToggleXray: () => setXrayVisible((previous) => !previous),
|
|
6811
|
+
onToggleSettings: toggleSettings,
|
|
6812
|
+
isSettingsOpen: () => settingsOpen,
|
|
6813
|
+
onCloseColorPicker: () => setColorPickerActive(false),
|
|
6814
|
+
isColorPickerActive: () => colorPickerActive
|
|
5051
6815
|
});
|
|
5052
6816
|
useResizeSync({
|
|
5053
6817
|
document: ownerDocument,
|
|
@@ -5059,7 +6823,7 @@ function MeasurerClient({
|
|
|
5059
6823
|
setGuides: setGuidesPersisted,
|
|
5060
6824
|
selectedElementRef
|
|
5061
6825
|
});
|
|
5062
|
-
|
|
6826
|
+
useEffect7(() => {
|
|
5063
6827
|
const handleScroll = () => {
|
|
5064
6828
|
const next = {
|
|
5065
6829
|
x: ownerWindow.scrollX,
|
|
@@ -5083,6 +6847,7 @@ function MeasurerClient({
|
|
|
5083
6847
|
document: ownerDocument,
|
|
5084
6848
|
window: ownerWindow,
|
|
5085
6849
|
enabled,
|
|
6850
|
+
selectionEnabled: toolMode === "select",
|
|
5086
6851
|
selectedElementRef,
|
|
5087
6852
|
hoverElementRef,
|
|
5088
6853
|
setSelectedMeasurement,
|
|
@@ -5092,7 +6857,7 @@ function MeasurerClient({
|
|
|
5092
6857
|
setActiveMeasurement: setActiveMeasurementPersisted,
|
|
5093
6858
|
setHeldDistances: setHeldDistancesPersisted
|
|
5094
6859
|
});
|
|
5095
|
-
|
|
6860
|
+
useEffect7(() => {
|
|
5096
6861
|
if (!toolbarActive || toolMode !== "none") return;
|
|
5097
6862
|
const handlePointerDown2 = (event) => {
|
|
5098
6863
|
const toolbarNode = toolbarRef.current;
|
|
@@ -5104,9 +6869,10 @@ function MeasurerClient({
|
|
|
5104
6869
|
ownerWindow.removeEventListener("pointerdown", handlePointerDown2);
|
|
5105
6870
|
};
|
|
5106
6871
|
}, [ownerWindow, toolbarActive, toolMode]);
|
|
5107
|
-
|
|
6872
|
+
useEffect7(() => {
|
|
5108
6873
|
if (!enabled) return;
|
|
5109
6874
|
const handleGuidePointerDown2 = (event) => {
|
|
6875
|
+
if (settingsOpen) return;
|
|
5110
6876
|
if (toolbarRef.current?.contains(event.target)) return;
|
|
5111
6877
|
const guideTarget = event.composedPath().some(
|
|
5112
6878
|
(target) => target instanceof ownerWindow.Element && target.hasAttribute("data-mesurer-guide")
|
|
@@ -5189,16 +6955,30 @@ function MeasurerClient({
|
|
|
5189
6955
|
ownerWindow,
|
|
5190
6956
|
setGuidesPersisted,
|
|
5191
6957
|
setSelectedGuideIdsPersisted,
|
|
6958
|
+
settingsOpen,
|
|
5192
6959
|
toolMode
|
|
5193
6960
|
]);
|
|
5194
|
-
|
|
6961
|
+
useEffect7(() => {
|
|
5195
6962
|
if (toolMode === "text-inspector") {
|
|
5196
6963
|
textInspector.enable();
|
|
5197
6964
|
} else {
|
|
5198
6965
|
textInspector.disable();
|
|
5199
6966
|
}
|
|
5200
6967
|
}, [textInspector, toolMode]);
|
|
5201
|
-
|
|
6968
|
+
const selectionToolRef = useRef12(toolMode);
|
|
6969
|
+
if (selectionToolRef.current !== toolMode) {
|
|
6970
|
+
selectionToolRef.current = toolMode;
|
|
6971
|
+
if (toolMode !== "select") {
|
|
6972
|
+
setSelectedElement(null);
|
|
6973
|
+
setHoverElement(null);
|
|
6974
|
+
setHoverRect(null);
|
|
6975
|
+
setHoverPointer(null);
|
|
6976
|
+
setSelectedMeasurement(null);
|
|
6977
|
+
setSelectedMeasurements([]);
|
|
6978
|
+
clearSelectionRect();
|
|
6979
|
+
}
|
|
6980
|
+
}
|
|
6981
|
+
useEffect7(() => {
|
|
5202
6982
|
let style = ownerDocument.getElementById(XRAY_STYLE_ID);
|
|
5203
6983
|
if (!style) {
|
|
5204
6984
|
style = ownerDocument.createElement("style");
|
|
@@ -5206,7 +6986,7 @@ function MeasurerClient({
|
|
|
5206
6986
|
style.textContent = XRAY_STYLES;
|
|
5207
6987
|
ownerDocument.head.appendChild(style);
|
|
5208
6988
|
}
|
|
5209
|
-
if (
|
|
6989
|
+
if (xrayVisible) {
|
|
5210
6990
|
ownerDocument.body.classList.add("xray-mode");
|
|
5211
6991
|
} else {
|
|
5212
6992
|
ownerDocument.body.classList.remove("xray-mode");
|
|
@@ -5214,13 +6994,13 @@ function MeasurerClient({
|
|
|
5214
6994
|
return () => {
|
|
5215
6995
|
ownerDocument.body.classList.remove("xray-mode");
|
|
5216
6996
|
};
|
|
5217
|
-
}, [ownerDocument,
|
|
5218
|
-
|
|
6997
|
+
}, [ownerDocument, xrayVisible]);
|
|
6998
|
+
useEffect7(() => {
|
|
5219
6999
|
return () => {
|
|
5220
7000
|
textInspector.destroy();
|
|
5221
7001
|
};
|
|
5222
7002
|
}, [textInspector]);
|
|
5223
|
-
|
|
7003
|
+
useEffect7(() => {
|
|
5224
7004
|
const hasSelectionAnimationState = !!selectionOriginRect || !!selectedMeasurement?.originRect || selectedMeasurements.some((measurement) => !!measurement.originRect);
|
|
5225
7005
|
if (!hasSelectionAnimationState) {
|
|
5226
7006
|
if (selectionAnimationCleanupTimeoutRef.current !== null) {
|
|
@@ -5301,9 +7081,9 @@ function MeasurerClient({
|
|
|
5301
7081
|
guidesEnabled,
|
|
5302
7082
|
guidePreview,
|
|
5303
7083
|
displayedMeasurements,
|
|
5304
|
-
hoverHighlightEnabled,
|
|
5305
|
-
highlightColor,
|
|
5306
|
-
guideColor
|
|
7084
|
+
hoverHighlightEnabled: settingsHoverHighlight,
|
|
7085
|
+
highlightColor: settingsHighlightColor,
|
|
7086
|
+
guideColor: settingsGuideColor
|
|
5307
7087
|
});
|
|
5308
7088
|
const {
|
|
5309
7089
|
handlePointerDown,
|
|
@@ -5320,10 +7100,12 @@ function MeasurerClient({
|
|
|
5320
7100
|
clearGuideDragHold,
|
|
5321
7101
|
scheduleGuideDragHold,
|
|
5322
7102
|
enabled,
|
|
7103
|
+
settingsOpen,
|
|
5323
7104
|
toolMode,
|
|
5324
7105
|
guidesEnabled,
|
|
5325
7106
|
snapEnabled,
|
|
5326
7107
|
snapGuidesEnabled,
|
|
7108
|
+
selectNewGuideEnabled,
|
|
5327
7109
|
altPressed,
|
|
5328
7110
|
guideOrientation,
|
|
5329
7111
|
hoverHighlightEnabled,
|
|
@@ -5356,7 +7138,7 @@ function MeasurerClient({
|
|
|
5356
7138
|
setHoverPointer,
|
|
5357
7139
|
clearSelectionRect
|
|
5358
7140
|
});
|
|
5359
|
-
const removeHeldDistance =
|
|
7141
|
+
const removeHeldDistance = useCallback8(
|
|
5360
7142
|
(id) => {
|
|
5361
7143
|
recordSnapshot();
|
|
5362
7144
|
setHeldDistancesPersisted(
|
|
@@ -5365,42 +7147,62 @@ function MeasurerClient({
|
|
|
5365
7147
|
},
|
|
5366
7148
|
[recordSnapshot, setHeldDistancesPersisted]
|
|
5367
7149
|
);
|
|
5368
|
-
const
|
|
7150
|
+
const snapGuidePosition = useCallback8(
|
|
7151
|
+
(orientation, position, draggingGuideId2 = null) => getSnapGuidePosition({
|
|
7152
|
+
orientation,
|
|
7153
|
+
point: orientation === "vertical" ? { x: position, y: 0 } : { x: 0, y: position },
|
|
7154
|
+
snapGuidesEnabled,
|
|
7155
|
+
overlayNode: overlayRef.current,
|
|
7156
|
+
guides,
|
|
7157
|
+
draggingGuideId: draggingGuideId2,
|
|
7158
|
+
document: ownerDocument
|
|
7159
|
+
}),
|
|
7160
|
+
[guides, ownerDocument, overlayRef, snapGuidesEnabled]
|
|
7161
|
+
);
|
|
7162
|
+
const startGuideFromRuler = useCallback8(
|
|
5369
7163
|
(orientation, position) => {
|
|
5370
7164
|
const id = createId();
|
|
5371
7165
|
const commit = createActionCommit();
|
|
5372
7166
|
commit();
|
|
5373
7167
|
setSelectedGuideIdsPersisted([]);
|
|
5374
|
-
setGuidesPersisted((prev) => [
|
|
7168
|
+
setGuidesPersisted((prev) => [
|
|
7169
|
+
...prev,
|
|
7170
|
+
{ id, orientation, position: snapGuidePosition(orientation, position) }
|
|
7171
|
+
]);
|
|
5375
7172
|
return id;
|
|
5376
7173
|
},
|
|
5377
7174
|
[
|
|
5378
7175
|
createActionCommit,
|
|
5379
7176
|
setGuidesPersisted,
|
|
5380
|
-
setSelectedGuideIdsPersisted
|
|
7177
|
+
setSelectedGuideIdsPersisted,
|
|
7178
|
+
snapGuidePosition
|
|
5381
7179
|
]
|
|
5382
7180
|
);
|
|
5383
|
-
const moveGuideFromRuler =
|
|
7181
|
+
const moveGuideFromRuler = useCallback8(
|
|
5384
7182
|
(id, position) => {
|
|
5385
7183
|
setGuidesPersisted(
|
|
5386
|
-
(prev) => prev.map(
|
|
7184
|
+
(prev) => prev.map(
|
|
7185
|
+
(guide) => guide.id === id ? { ...guide, position: snapGuidePosition(guide.orientation, position, id) } : guide
|
|
7186
|
+
)
|
|
5387
7187
|
);
|
|
5388
7188
|
},
|
|
5389
|
-
[setGuidesPersisted]
|
|
7189
|
+
[setGuidesPersisted, snapGuidePosition]
|
|
5390
7190
|
);
|
|
5391
|
-
const finishGuideFromRuler =
|
|
7191
|
+
const finishGuideFromRuler = useCallback8(
|
|
5392
7192
|
(id) => {
|
|
5393
|
-
|
|
7193
|
+
if (selectNewGuideEnabled) {
|
|
7194
|
+
setSelectedGuideIdsPersisted([id]);
|
|
7195
|
+
}
|
|
5394
7196
|
},
|
|
5395
|
-
[setSelectedGuideIdsPersisted]
|
|
7197
|
+
[selectNewGuideEnabled, setSelectedGuideIdsPersisted]
|
|
5396
7198
|
);
|
|
5397
|
-
const cancelGuideFromRuler =
|
|
7199
|
+
const cancelGuideFromRuler = useCallback8(
|
|
5398
7200
|
(id) => {
|
|
5399
7201
|
setGuidesPersisted((prev) => prev.filter((guide) => guide.id !== id));
|
|
5400
7202
|
},
|
|
5401
7203
|
[setGuidesPersisted]
|
|
5402
7204
|
);
|
|
5403
|
-
const handleGuidePointerDown =
|
|
7205
|
+
const handleGuidePointerDown = useCallback8(
|
|
5404
7206
|
(guide, event) => {
|
|
5405
7207
|
const commit = createActionCommit();
|
|
5406
7208
|
if (!enabled) return;
|
|
@@ -5426,7 +7228,7 @@ function MeasurerClient({
|
|
|
5426
7228
|
setSelectedGuideIdsPersisted
|
|
5427
7229
|
]
|
|
5428
7230
|
);
|
|
5429
|
-
const handleGuidePointerUp =
|
|
7231
|
+
const handleGuidePointerUp = useCallback8(
|
|
5430
7232
|
(guide, event) => {
|
|
5431
7233
|
event.stopPropagation();
|
|
5432
7234
|
clearGuideDragHold();
|
|
@@ -5437,16 +7239,37 @@ function MeasurerClient({
|
|
|
5437
7239
|
},
|
|
5438
7240
|
[clearGuideDragHold, setDraggingGuideId]
|
|
5439
7241
|
);
|
|
7242
|
+
const overlayInteractive = enabled && !settingsOpen;
|
|
7243
|
+
const overlayGuides = useMemo2(() => {
|
|
7244
|
+
if (guides.length > 0) return guides;
|
|
7245
|
+
if (!settingsOpen || settingsTab !== "guides") return guides;
|
|
7246
|
+
return [
|
|
7247
|
+
{
|
|
7248
|
+
id: "__mesurer-preview-vertical",
|
|
7249
|
+
orientation: "vertical",
|
|
7250
|
+
position: ownerWindow.innerWidth / 2
|
|
7251
|
+
},
|
|
7252
|
+
{
|
|
7253
|
+
id: "__mesurer-preview-horizontal",
|
|
7254
|
+
orientation: "horizontal",
|
|
7255
|
+
position: ownerWindow.innerHeight / 2
|
|
7256
|
+
}
|
|
7257
|
+
];
|
|
7258
|
+
}, [guides, ownerWindow, settingsOpen, settingsTab]);
|
|
5440
7259
|
return createPortal(
|
|
5441
|
-
/* @__PURE__ */
|
|
7260
|
+
/* @__PURE__ */ jsxs11(
|
|
5442
7261
|
"div",
|
|
5443
7262
|
{
|
|
5444
7263
|
ref: overlayRef,
|
|
5445
7264
|
className: "mesurer-root msr:pointer-events-none msr:fixed msr:inset-0 msr:z-50",
|
|
5446
7265
|
children: [
|
|
5447
|
-
enabled && rulersVisible ? /* @__PURE__ */
|
|
7266
|
+
enabled && rulersVisible ? /* @__PURE__ */ jsx12(
|
|
5448
7267
|
RulersOverlay,
|
|
5449
7268
|
{
|
|
7269
|
+
ownerWindow,
|
|
7270
|
+
settings: settingsRulerSettings,
|
|
7271
|
+
interactive: !settingsOpen,
|
|
7272
|
+
forceVisible: settingsOpen,
|
|
5450
7273
|
onStartGuide: startGuideFromRuler,
|
|
5451
7274
|
onMoveGuide: moveGuideFromRuler,
|
|
5452
7275
|
onFinishGuide: finishGuideFromRuler,
|
|
@@ -5455,12 +7278,13 @@ function MeasurerClient({
|
|
|
5455
7278
|
selectedGuideIds
|
|
5456
7279
|
}
|
|
5457
7280
|
) : null,
|
|
5458
|
-
/* @__PURE__ */
|
|
7281
|
+
/* @__PURE__ */ jsx12(
|
|
5459
7282
|
MeasurerOverlay,
|
|
5460
7283
|
{
|
|
5461
7284
|
enabled,
|
|
7285
|
+
interactive: overlayInteractive,
|
|
5462
7286
|
toolMode,
|
|
5463
|
-
guidePointerEvents:
|
|
7287
|
+
guidePointerEvents: overlayInteractive && (toolMode !== "none" || rulersVisible),
|
|
5464
7288
|
guidesEnabled,
|
|
5465
7289
|
altPressed,
|
|
5466
7290
|
isDragging,
|
|
@@ -5481,13 +7305,14 @@ function MeasurerClient({
|
|
|
5481
7305
|
optionPairOverlay,
|
|
5482
7306
|
guideDistanceOverlay,
|
|
5483
7307
|
optionContainerLines,
|
|
5484
|
-
guides,
|
|
7308
|
+
guides: overlayGuides,
|
|
5485
7309
|
hoverGuide,
|
|
5486
7310
|
draggingGuideId,
|
|
5487
7311
|
selectedGuideIds,
|
|
5488
7312
|
guideColorActive,
|
|
5489
7313
|
guideColorHover,
|
|
5490
7314
|
guideColorDefault,
|
|
7315
|
+
guideStyle: settingsGuideStyle,
|
|
5491
7316
|
onPointerDown: handlePointerDown,
|
|
5492
7317
|
onPointerMove: handlePointerMove,
|
|
5493
7318
|
onPointerUp: handlePointerUp,
|
|
@@ -5498,7 +7323,20 @@ function MeasurerClient({
|
|
|
5498
7323
|
onGuidePointerCancel: handleGuidePointerUp
|
|
5499
7324
|
}
|
|
5500
7325
|
),
|
|
5501
|
-
/* @__PURE__ */
|
|
7326
|
+
/* @__PURE__ */ jsx12(
|
|
7327
|
+
ColorPicker,
|
|
7328
|
+
{
|
|
7329
|
+
active: colorPickerActive,
|
|
7330
|
+
sample: colorPickerSample,
|
|
7331
|
+
unsupported: colorPickerUnsupported,
|
|
7332
|
+
ownerWindow,
|
|
7333
|
+
toolbarRef,
|
|
7334
|
+
formats: settingsColorFormats,
|
|
7335
|
+
favoriteFormat: settingsColorClickFormat,
|
|
7336
|
+
onClose: () => setColorPickerActive(false)
|
|
7337
|
+
}
|
|
7338
|
+
),
|
|
7339
|
+
/* @__PURE__ */ jsx12(
|
|
5502
7340
|
Toolbar,
|
|
5503
7341
|
{
|
|
5504
7342
|
ref: toolbarRef,
|
|
@@ -5506,11 +7344,47 @@ function MeasurerClient({
|
|
|
5506
7344
|
toolMode,
|
|
5507
7345
|
setEnabled: setEnabledWithHistory,
|
|
5508
7346
|
setToolMode: setToolModeWithHistory,
|
|
7347
|
+
xrayVisible,
|
|
7348
|
+
setXrayVisible,
|
|
5509
7349
|
rulersVisible,
|
|
5510
7350
|
setRulersVisible: setRulersVisiblePersisted,
|
|
5511
7351
|
guideOrientation,
|
|
5512
7352
|
setGuideOrientation: setGuideOrientationWithHistory,
|
|
5513
|
-
onInteract: () => setToolbarActive(true)
|
|
7353
|
+
onInteract: () => setToolbarActive(true),
|
|
7354
|
+
colorPickerActive,
|
|
7355
|
+
setColorPickerActive,
|
|
7356
|
+
onColorPickerClick: openColorPicker,
|
|
7357
|
+
settingsOpen,
|
|
7358
|
+
setSettingsOpen,
|
|
7359
|
+
highlightColor: settingsHighlightColor,
|
|
7360
|
+
setHighlightColor: setSettingsHighlightColor,
|
|
7361
|
+
guideColor: settingsGuideColor,
|
|
7362
|
+
setGuideColor: setSettingsGuideColor,
|
|
7363
|
+
hoverHighlight: settingsHoverHighlight,
|
|
7364
|
+
setHoverHighlight: setSettingsHoverHighlight,
|
|
7365
|
+
persistOnReload: settingsPersistOnReload,
|
|
7366
|
+
setPersistOnReload: setSettingsPersistOnReload,
|
|
7367
|
+
colorPickerFormats: settingsColorFormats,
|
|
7368
|
+
setColorPickerFormats: setSettingsColorFormats,
|
|
7369
|
+
colorPickerClickFormat: settingsColorClickFormat,
|
|
7370
|
+
setColorPickerClickFormat: setSettingsColorClickFormat,
|
|
7371
|
+
snapEnabled,
|
|
7372
|
+
setSnapEnabled,
|
|
7373
|
+
snapGuidesEnabled,
|
|
7374
|
+
setSnapGuidesEnabled,
|
|
7375
|
+
selectNewGuideEnabled,
|
|
7376
|
+
setSelectNewGuideEnabled,
|
|
7377
|
+
multiMeasureEnabled,
|
|
7378
|
+
setMultiMeasureEnabled,
|
|
7379
|
+
guideStyle: settingsGuideStyle,
|
|
7380
|
+
setGuideStyle: setSettingsGuideStyle,
|
|
7381
|
+
rulerSettings: settingsRulerSettings,
|
|
7382
|
+
setRulerSettings: setSettingsRulerSettings,
|
|
7383
|
+
settingsTab,
|
|
7384
|
+
setSettingsTab,
|
|
7385
|
+
onToggleSettings: toggleSettings,
|
|
7386
|
+
onResetSettings: resetSettings,
|
|
7387
|
+
onClearWorkspace: clearWorkspace
|
|
5514
7388
|
}
|
|
5515
7389
|
)
|
|
5516
7390
|
]
|
|
@@ -5525,14 +7399,24 @@ function Measurer({
|
|
|
5525
7399
|
hoverHighlightEnabled = true,
|
|
5526
7400
|
persistOnReload = false,
|
|
5527
7401
|
portalTarget,
|
|
5528
|
-
persistKey
|
|
7402
|
+
persistKey,
|
|
7403
|
+
colorPickerFormats = ["hex", "rgb", "oklch"],
|
|
7404
|
+
colorPickerClickFormat = "hex",
|
|
7405
|
+
snapEnabled = true,
|
|
7406
|
+
snapGuidesEnabled = true,
|
|
7407
|
+
selectNewGuideEnabled = true,
|
|
7408
|
+
multiMeasureEnabled = false,
|
|
7409
|
+
guideStyle,
|
|
7410
|
+
rulerSettings,
|
|
7411
|
+
persistence,
|
|
7412
|
+
onPersistenceError
|
|
5529
7413
|
}) {
|
|
5530
7414
|
if (typeof document !== "undefined") {
|
|
5531
7415
|
ensureMeasurerStyles(MESURER_STYLES, portalTarget);
|
|
5532
7416
|
}
|
|
5533
7417
|
const hydrated = useHydrated();
|
|
5534
7418
|
if (!hydrated) return null;
|
|
5535
|
-
return /* @__PURE__ */
|
|
7419
|
+
return /* @__PURE__ */ jsx12(
|
|
5536
7420
|
MeasurerClient,
|
|
5537
7421
|
{
|
|
5538
7422
|
highlightColor,
|
|
@@ -5540,12 +7424,26 @@ function Measurer({
|
|
|
5540
7424
|
hoverHighlightEnabled,
|
|
5541
7425
|
persistOnReload,
|
|
5542
7426
|
persistKey,
|
|
7427
|
+
colorPickerFormats,
|
|
7428
|
+
colorPickerClickFormat,
|
|
7429
|
+
snapEnabled,
|
|
7430
|
+
snapGuidesEnabled,
|
|
7431
|
+
selectNewGuideEnabled,
|
|
7432
|
+
multiMeasureEnabled,
|
|
7433
|
+
guideStyle: { ...DEFAULT_GUIDE_STYLE, ...guideStyle },
|
|
7434
|
+
rulerSettings: { ...DEFAULT_RULER_SETTINGS, ...rulerSettings },
|
|
7435
|
+
persistence,
|
|
7436
|
+
onPersistenceError,
|
|
5543
7437
|
portalTarget: portalTarget ?? document.body
|
|
5544
7438
|
}
|
|
5545
7439
|
);
|
|
5546
7440
|
}
|
|
5547
7441
|
export {
|
|
7442
|
+
MESURER_STORAGE_VERSION,
|
|
5548
7443
|
Measurer,
|
|
5549
7444
|
TextInspector,
|
|
5550
|
-
|
|
7445
|
+
createLocalStoragePersistence,
|
|
7446
|
+
createTextInspector,
|
|
7447
|
+
normalizeStoredSettings,
|
|
7448
|
+
normalizeStoredWorkspace
|
|
5551
7449
|
};
|