mesurer-solid 0.1.0-beta.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/dist/core.js ADDED
@@ -0,0 +1,226 @@
1
+ //#region ../mesurer-core/dist/domain.js
2
+ var e = {
3
+ opacity: 1,
4
+ width: 1,
5
+ pattern: "solid",
6
+ dashLength: 6,
7
+ gap: 4
8
+ }, t = {
9
+ opacity: 1,
10
+ edgeReveal: !1
11
+ };
12
+ //#endregion
13
+ //#region ../mesurer-core/dist/events.js
14
+ function n() {
15
+ let e = /* @__PURE__ */ new Map();
16
+ return {
17
+ on(t, n) {
18
+ let r = e.get(t) ?? /* @__PURE__ */ new Set();
19
+ return r.add(n), e.set(t, r), () => {
20
+ r.delete(n), r.size === 0 && e.delete(t);
21
+ };
22
+ },
23
+ async emit(t, n) {
24
+ for (let r of [...e.get(t) ?? []]) await r(n);
25
+ },
26
+ clear() {
27
+ e.clear();
28
+ }
29
+ };
30
+ }
31
+ ({ ...e }), { ...t };
32
+ //#endregion
33
+ //#region ../mesurer-core/dist/plugins.js
34
+ var r = 50;
35
+ function i() {
36
+ let e = 1, t = 0, i = n(), a = /* @__PURE__ */ new Map(), o = /* @__PURE__ */ new Map(), s = /* @__PURE__ */ new Map(), c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Map(), p = /* @__PURE__ */ new Map(), m = [], h = [], g = (e, t) => {
37
+ i.emit("changed", {
38
+ pluginId: e,
39
+ reason: t
40
+ });
41
+ }, _ = (t, n, r) => {
42
+ let i = e++;
43
+ t.set(i, {
44
+ ...r,
45
+ pluginId: n,
46
+ registrationId: i
47
+ });
48
+ let a = !1;
49
+ return { dispose() {
50
+ a || (a = !0, t.delete(i), g(n, "registration"));
51
+ } };
52
+ }, v = (e, t) => {
53
+ let n = !1;
54
+ return { dispose() {
55
+ if (!n) {
56
+ n = !0;
57
+ try {
58
+ t();
59
+ } finally {
60
+ g(e, "registration");
61
+ }
62
+ }
63
+ } };
64
+ }, y = (e, t) => t === "all" || (t === "history" ? e.history === !0 : e.persist === !0), b = (e = "all") => {
65
+ let t = {};
66
+ for (let n of f.values()) !y(n, e) || !p.has(n.id) || (t[n.id] = p.get(n.id));
67
+ return t;
68
+ }, x = (e, t = "all") => {
69
+ let n = new Set([...f.values()].filter((e) => y(e, t)).map((e) => e.id));
70
+ for (let [t, r] of Object.entries(e)) n.has(t) && p.set(t, r);
71
+ g(void 0, "state");
72
+ }, S = (e, t) => {
73
+ let n = Object.keys(e), r = Object.keys(t);
74
+ return n.length === r.length && n.every((n) => Object.prototype.hasOwnProperty.call(t, n) && Object.is(e[n], t[n]));
75
+ }, C = () => {
76
+ m.length = 0, h.length = 0;
77
+ }, w = async (e, n, a) => {
78
+ let o = [...l.values()].reverse().find((t) => t.id === e);
79
+ if (!o) throw Error(`Unknown Mesurer command: ${e}`);
80
+ let s = t === 0, c = s ? b("history") : null;
81
+ t += 1;
82
+ try {
83
+ await o.handler(n, { source: a }), await i.emit("command", {
84
+ id: e,
85
+ args: n
86
+ });
87
+ } finally {
88
+ --t;
89
+ }
90
+ if (s && c) {
91
+ let e = b("history");
92
+ S(c, e) || (m.push(c), m.length > r && m.shift(), h.length = 0);
93
+ }
94
+ }, T = () => {
95
+ let e = m.pop();
96
+ return e ? (h.push(b("history")), h.length > r && h.shift(), x(e, "history"), g(void 0, "history"), !0) : !1;
97
+ }, E = () => {
98
+ let e = h.pop();
99
+ return e ? (m.push(b("history")), m.length > r && m.shift(), x(e, "history"), g(void 0, "history"), !0) : !1;
100
+ }, D = async (e, t) => {
101
+ for (let n of [...u.values()].filter((t) => t.name === e)) await n.handler(t);
102
+ }, O = (e) => [...d.values()].reverse().find((t) => t.id === e)?.value, k = {
103
+ get: (e) => p.get(e),
104
+ update(e, t) {
105
+ if (!p.has(e)) throw Error(`Unknown Mesurer state slice: ${e}`);
106
+ p.set(e, t(p.get(e))), g(void 0, "state");
107
+ },
108
+ serialize: b,
109
+ restore: x
110
+ }, A = (e, t) => {
111
+ let n = (e) => (t.push(e), e);
112
+ return {
113
+ state: {
114
+ register(t) {
115
+ let r = n(_(f, e, t));
116
+ return p.has(t.id) || p.set(t.id, t.initial), r;
117
+ },
118
+ get: k.get,
119
+ update: k.update
120
+ },
121
+ tool: { register: (t) => n(_(o, e, t)) },
122
+ settings: { register: (t) => n(_(s, e, t)) },
123
+ overlay: { register: (t) => n(_(c, e, t)) },
124
+ command: {
125
+ register: (t, r) => n(_(l, e, {
126
+ id: t,
127
+ handler: r
128
+ })),
129
+ execute: w
130
+ },
131
+ hook: {
132
+ on: (t, r) => n(_(u, e, {
133
+ name: t,
134
+ handler: r
135
+ })),
136
+ emit: D
137
+ },
138
+ service: {
139
+ provide: (t, r) => n(_(d, e, {
140
+ id: t,
141
+ value: r
142
+ })),
143
+ get: O
144
+ },
145
+ lifecycle: { onDispose: (t) => n(v(e, t)) }
146
+ };
147
+ }, j = () => {
148
+ let e = new Set([...f.values()].map((e) => e.id));
149
+ for (let t of [...p.keys()]) e.has(t) || p.delete(t);
150
+ }, M = (e) => {
151
+ let t = a.get(e);
152
+ if (!t) return !1;
153
+ for (let e of [...t.registrations].reverse()) e.dispose();
154
+ return a.delete(e), j(), C(), g(e, "remove"), !0;
155
+ }, N = async (e) => {
156
+ let t = a.has(e.id);
157
+ t && M(e.id);
158
+ let n = (e.requires ?? []).filter((e) => ![...a.values()].some(({ plugin: t }) => t.provides?.includes(e)));
159
+ if (n.length) throw Error(`Plugin ${e.id} requires missing capabilities: ${n.join(", ")}`);
160
+ let r = [];
161
+ try {
162
+ await e.setup(A(e.id, r)), a.set(e.id, {
163
+ plugin: e,
164
+ registrations: r
165
+ }), C(), g(e.id, t ? "replace" : "load");
166
+ } catch (e) {
167
+ for (let e of r.reverse()) e.dispose();
168
+ throw j(), e;
169
+ }
170
+ }, P = (e) => [...e].sort((e, t) => (e.order ?? 0) - (t.order ?? 0)), F = ({ pluginId: e, registrationId: t, ...n }) => n, I = {
171
+ load: N,
172
+ remove: M,
173
+ replace: N,
174
+ has: (e) => a.has(e),
175
+ plugin: (e) => a.get(e)?.plugin,
176
+ listPlugins: () => [...a.values()].map((e) => e.plugin),
177
+ tools: () => P(o.values()).map(F),
178
+ settings: () => P(s.values()).map(F),
179
+ overlays: () => P(c.values()).map(F),
180
+ state: k,
181
+ service: { get: O },
182
+ command: { execute: w },
183
+ hook: { emit: D },
184
+ undo: T,
185
+ redo: E,
186
+ canUndo: () => m.length > 0,
187
+ canRedo: () => h.length > 0,
188
+ subscribe: (e) => i.on("changed", e),
189
+ describe() {
190
+ return {
191
+ plugins: [...a.values()].map(({ plugin: e }) => ({
192
+ id: e.id,
193
+ version: e.version,
194
+ requires: e.requires ?? [],
195
+ provides: e.provides ?? []
196
+ })),
197
+ tools: I.tools().map(({ active: e, disabled: t, icon: n, ...r }) => r),
198
+ settings: I.settings(),
199
+ overlays: I.overlays(),
200
+ state: [...f.values()].map(({ id: e, history: t, persist: n }) => ({
201
+ id: e,
202
+ history: t ?? !1,
203
+ persist: n ?? !1
204
+ })),
205
+ commands: [...new Set([...l.values()].map((e) => e.id))],
206
+ hooks: [...new Set([...u.values()].map((e) => e.name))],
207
+ services: [...new Set([...d.values()].map((e) => e.id))]
208
+ };
209
+ },
210
+ dispose() {
211
+ for (let e of [...a.keys()].reverse()) M(e);
212
+ i.clear(), p.clear(), C();
213
+ }
214
+ };
215
+ return I;
216
+ }
217
+ //#endregion
218
+ //#region src/core.ts
219
+ var a = (e) => e, o = i;
220
+ async function s(e = {}) {
221
+ let t = o();
222
+ for (let n of e.plugins ?? []) await t.load(n);
223
+ return t;
224
+ }
225
+ //#endregion
226
+ export { o as createMesurerPluginHost, s as createMesurerRuntime, a as defineMesurerPlugin };
@@ -0,0 +1,24 @@
1
+ export type MesurerHostLayerMode = "top-layer" | "fixed";
2
+ export type MesurerHostLayer = {
3
+ mode: MesurerHostLayerMode;
4
+ bringToFront(): void;
5
+ dispose(): void;
6
+ };
7
+ /**
8
+ * Mount Mesurer's outer host using browser top-layer primitives when available.
9
+ *
10
+ * Shadow DOM isolates Mesurer's internals from host CSS, but it does not by
11
+ * itself protect the shadow host from page stacking contexts, clipping, or
12
+ * author styles. A manual popover escapes ordinary document stacking and
13
+ * ancestor clipping. The fixed/max-z-index host is the compatibility fallback.
14
+ *
15
+ * The protected host itself is intentionally zero-sized with visible overflow.
16
+ * This lets Mesurer's fixed-position descendants receive pointer input without
17
+ * turning the protection layer into a viewport-sized click blocker for the app.
18
+ *
19
+ * Modal dialogs are special: the platform makes every node outside the active
20
+ * modal inert. When an observable modal opens, Mesurer temporarily reparents
21
+ * its host into that dialog so the toolbar stays interactive, then restores the
22
+ * original parent when the modal closes.
23
+ */
24
+ export declare function mountMesurerHost(container: HTMLDivElement, target: HTMLElement | ShadowRoot, preferTopLayer?: boolean): MesurerHostLayer;
@@ -0,0 +1,210 @@
1
+ import { type MesurerAgentHarness } from "./agent";
2
+ import type { MesurerAnnotation, MesurerCapturePlanV1, MesurerContextRequest, MesurerContextV1, MesurerReviewV1 } from "./context";
3
+ import type { MesurerPlugin, MesurerPluginDescription, MesurerPluginHost } from "./core";
4
+ import { type MesurerHostLayerMode } from "./host-layer";
5
+ export type ColorPickerFormat = "hex" | "rgb" | "hsl" | "oklch";
6
+ export type MesurerBuiltinPluginId = "select" | "xray" | "color-picker" | "rulers" | "text-inspector" | "guides" | "distance" | "settings";
7
+ export type LinePattern = "solid" | "dashed" | "dotted";
8
+ export type LineStyle = {
9
+ opacity: number;
10
+ width: number;
11
+ pattern: LinePattern;
12
+ dashLength: number;
13
+ gap: number;
14
+ };
15
+ export type GuidePattern = LinePattern;
16
+ export type GuideStyle = LineStyle;
17
+ export type SelectionSpacingStyle = LineStyle & {
18
+ enabled: boolean;
19
+ color: string;
20
+ };
21
+ export type RulerSettings = {
22
+ opacity: number;
23
+ edgeReveal: boolean;
24
+ };
25
+ export type MesurerRect = {
26
+ left: number;
27
+ top: number;
28
+ width: number;
29
+ height: number;
30
+ };
31
+ export type MesurerMeasurement = {
32
+ id: string;
33
+ rect: MesurerRect;
34
+ normalizedRect: MesurerRect;
35
+ deltaX: number;
36
+ deltaY: number;
37
+ snapped?: boolean;
38
+ };
39
+ export type MesurerGuide = {
40
+ id: string;
41
+ orientation: "vertical" | "horizontal";
42
+ position: number;
43
+ };
44
+ export type MesurerDistance = {
45
+ id: string;
46
+ rectA: MesurerRect;
47
+ rectB: MesurerRect;
48
+ normalizedRectA: MesurerRect;
49
+ normalizedRectB: MesurerRect;
50
+ horizontal: {
51
+ x1: number;
52
+ x2: number;
53
+ y: number;
54
+ value: number;
55
+ } | null;
56
+ vertical: {
57
+ y1: number;
58
+ y2: number;
59
+ x: number;
60
+ value: number;
61
+ } | null;
62
+ connectors: Array<{
63
+ x1: number;
64
+ y1: number;
65
+ x2: number;
66
+ y2: number;
67
+ }>;
68
+ };
69
+ export type MesurerStoredSettings = {
70
+ highlightColor?: string;
71
+ guideColor?: string;
72
+ hoverHighlightEnabled?: boolean;
73
+ colorPickerFormats?: ColorPickerFormat[];
74
+ colorPickerClickFormat?: ColorPickerFormat;
75
+ snapEnabled?: boolean;
76
+ snapGuidesEnabled?: boolean;
77
+ selectNewGuideEnabled?: boolean;
78
+ multiMeasureEnabled?: boolean;
79
+ persistOnReload?: boolean;
80
+ guideStyle?: Partial<GuideStyle>;
81
+ selectionSpacingStyle?: Partial<SelectionSpacingStyle>;
82
+ rulerSettings?: Partial<RulerSettings>;
83
+ };
84
+ export type MesurerStoredWorkspace = {
85
+ enabled: boolean;
86
+ xrayVisible: boolean;
87
+ toolMode: "none" | "select" | "guides" | "text-inspector" | "xray" | "rulers";
88
+ rulersVisible: boolean;
89
+ guideOrientation: "vertical" | "horizontal";
90
+ guides: MesurerGuide[];
91
+ selectedGuideIds: string[];
92
+ measurements: MesurerMeasurement[];
93
+ activeMeasurement: MesurerMeasurement | null;
94
+ heldDistances: MesurerDistance[];
95
+ };
96
+ export type MesurerPersistenceSnapshot = {
97
+ settings: MesurerStoredSettings;
98
+ workspace: MesurerStoredWorkspace | null;
99
+ };
100
+ export type MesurerPersistence = {
101
+ load(): MesurerPersistenceSnapshot | null;
102
+ saveSettings(settings: MesurerStoredSettings): void;
103
+ saveWorkspace(workspace: MesurerStoredWorkspace): void;
104
+ clearWorkspace(): void;
105
+ clearSettings(): void;
106
+ subscribe?: (listener: (snapshot: MesurerPersistenceSnapshot | null, source?: {
107
+ settings?: boolean;
108
+ workspace?: boolean;
109
+ }) => void) => () => void;
110
+ setErrorHandler?: (handler: ((error: unknown) => void) | undefined) => void;
111
+ };
112
+ export type AgentBridgeOptions = {
113
+ globalName?: string;
114
+ root?: ParentNode;
115
+ };
116
+ export type MesurerOptions = {
117
+ highlightColor?: string;
118
+ guideColor?: string;
119
+ hoverHighlightEnabled?: boolean;
120
+ persistOnReload?: boolean;
121
+ persistKey?: string;
122
+ persistence?: MesurerPersistence;
123
+ onPersistenceError?: (error: unknown) => void;
124
+ colorPickerFormats?: ColorPickerFormat[];
125
+ colorPickerClickFormat?: ColorPickerFormat;
126
+ snapEnabled?: boolean;
127
+ snapGuidesEnabled?: boolean;
128
+ selectNewGuideEnabled?: boolean;
129
+ multiMeasureEnabled?: boolean;
130
+ guideStyle?: Partial<GuideStyle>;
131
+ selectionSpacingStyle?: Partial<SelectionSpacingStyle>;
132
+ rulerSettings?: Partial<RulerSettings>;
133
+ plugins?: MesurerPlugin[];
134
+ excludePlugins?: MesurerBuiltinPluginId[];
135
+ pluginHost?: MesurerPluginHost;
136
+ onPluginHost?: (host: MesurerPluginHost) => void;
137
+ onPluginsReady?: (host: MesurerPluginHost) => void;
138
+ onPluginError?: (error: unknown, pluginId: string) => void;
139
+ };
140
+ export type MountMeasurerOptions = MesurerOptions & {
141
+ target?: HTMLElement | ShadowRoot;
142
+ isolate?: boolean;
143
+ shadowMode?: ShadowRootMode;
144
+ topLayer?: boolean;
145
+ agent?: boolean | AgentBridgeOptions;
146
+ };
147
+ export type MesurerAgentCapabilities = {
148
+ protocol: "mesurer.agent/v1";
149
+ contextSchema: "mesurer.context/v1";
150
+ capabilities: {
151
+ context: boolean;
152
+ annotations: boolean;
153
+ review: boolean;
154
+ capturePlan: boolean;
155
+ screenshots: boolean;
156
+ send: boolean;
157
+ };
158
+ };
159
+ export type MesurerContextHarness = {
160
+ capabilities(): MesurerAgentCapabilities;
161
+ context(request?: MesurerContextRequest): Promise<MesurerContextV1>;
162
+ contextText(request?: MesurerContextRequest): Promise<string>;
163
+ annotations(): Promise<MesurerAnnotation[]>;
164
+ review(annotationId?: string): Promise<MesurerReviewV1 | MesurerReviewV1[]>;
165
+ capturePlan(request?: MesurerContextRequest): Promise<MesurerCapturePlanV1>;
166
+ prepareCapture(): Promise<void>;
167
+ finishCapture(): Promise<void>;
168
+ sendContext(request?: MesurerContextRequest): Promise<void>;
169
+ };
170
+ export type MesurerBrowserAgent = MesurerAgentHarness & MesurerContextHarness;
171
+ export type MountedMeasurer = {
172
+ element: HTMLDivElement;
173
+ root: HTMLDivElement | ShadowRoot;
174
+ readonly hostLayer: MesurerHostLayerMode;
175
+ readonly pluginHost: MesurerPluginHost | undefined;
176
+ readonly ready: Promise<void>;
177
+ readonly agent: MesurerBrowserAgent;
178
+ context(request?: MesurerContextRequest): Promise<MesurerContextV1>;
179
+ contextText(request?: MesurerContextRequest): Promise<string>;
180
+ copyContext(request?: MesurerContextRequest): Promise<void>;
181
+ annotations(): Promise<MesurerAnnotation[]>;
182
+ review(annotationId?: string): Promise<MesurerReviewV1 | MesurerReviewV1[]>;
183
+ capturePlan(request?: MesurerContextRequest): Promise<MesurerCapturePlanV1>;
184
+ prepareCapture(): Promise<void>;
185
+ finishCapture(): Promise<void>;
186
+ sendContext(request?: MesurerContextRequest): Promise<void>;
187
+ bringToFront(): void;
188
+ describe(): MesurerPluginDescription | undefined;
189
+ dispose(): void;
190
+ };
191
+ export declare function mountMeasurer(options?: MountMeasurerOptions): MountedMeasurer;
192
+ export { createMesurerAgentHarness } from "./agent";
193
+ export type { AgentDistance, AgentEdges, AgentElementInspection, AgentFeedbackSnapshot, AgentRect, AgentViewportSnapshot, CreateMesurerAgentHarnessOptions, MesurerAgentHarness, } from "./agent";
194
+ export { captureMesurerContext, copyTextToClipboard, createMesurerCapturePlan, formatMesurerContext, reviewMesurerAnnotation, toAcpContentBlocks, } from "./context";
195
+ export type { AcpImageContentBlock, AcpTextContentBlock, MesurerAcpContentBlock, MesurerAnnotation, MesurerAnnotationBaseline, MesurerAnnotationTarget, MesurerCapturePlanV1, MesurerContextDelivery, MesurerContextDistance, MesurerContextEdges, MesurerContextGuide, MesurerContextMeasurement, MesurerContextRect, MesurerContextRequest, MesurerContextSender, MesurerContextTarget, MesurerContextV1, MesurerElementFingerprint, MesurerElementInspection, MesurerEvidenceImage, MesurerEvidenceProvider, MesurerReviewChange, MesurerReviewMetricChange, MesurerReviewPresenceChange, MesurerReviewV1, } from "./context";
196
+ export { contextPlugin, MESURER_CONTEXT_PLUGIN_ID, MESURER_CONTEXT_SERVICE_ID, } from "./context-plugin";
197
+ export type { MesurerContextPluginOptions, MesurerContextService, } from "./context-plugin";
198
+ export { createMesurerPluginHost, createMesurerRuntime, defineMesurerPlugin } from "./core";
199
+ export type { CommandHandler as MesurerCommandHandler, MesurerPlugin, MesurerPluginContext, MesurerPluginDescription, MesurerPluginHost, OverlayContribution, Registration as MesurerRegistration, SettingsContribution, StateSliceDefinition, ToolContribution, } from "./core";
200
+ export type { MesurerHostLayerMode } from "./host-layer";
201
+ export declare const selectPlugin: () => MesurerPlugin;
202
+ export declare const xrayPlugin: () => MesurerPlugin;
203
+ export declare const colorPickerPlugin: () => MesurerPlugin;
204
+ export declare const rulersPlugin: () => MesurerPlugin;
205
+ export declare const textInspectorPlugin: () => MesurerPlugin;
206
+ export declare const guidesPlugin: () => MesurerPlugin;
207
+ export declare const distancePlugin: () => MesurerPlugin;
208
+ export declare const settingsPlugin: () => MesurerPlugin;
209
+ export declare const defaultMesurerPlugins: () => MesurerPlugin[];
210
+ export declare const composeMesurerPlugins: (plugins?: MesurerPlugin[], exclude?: MesurerBuiltinPluginId[]) => MesurerPlugin[];