@embedpdf/plugin-measurement 3.0.0-next.14

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/index.cjs ADDED
@@ -0,0 +1,471 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ const require_contract = require("./contract-Dy7X9nSj.cjs");
3
+ let _embedpdf_core = require("@embedpdf/core");
4
+ let _embedpdf_plugin_annotation_contract_host = require("@embedpdf/plugin-annotation/contract/host");
5
+ let _embedpdf_plugin_interaction_contract = require("@embedpdf/plugin-interaction/contract");
6
+ let _embedpdf_plugin_annotation_contract = require("@embedpdf/plugin-annotation/contract");
7
+ let _embedpdf_engine_core_runtime = require("@embedpdf/engine-core/runtime");
8
+ //#region src/scale.ts
9
+ const DEFAULT_PRESETS = [
10
+ ...[
11
+ 1,
12
+ 10,
13
+ 20,
14
+ 50,
15
+ 100,
16
+ 200
17
+ ].map((real) => ({
18
+ id: `metric-${real}`,
19
+ label: `1:${real}`,
20
+ paper: 1,
21
+ real,
22
+ unit: "m"
23
+ })),
24
+ {
25
+ id: "imperial-quarter",
26
+ label: "1/4 in = 1 ft",
27
+ paper: 1,
28
+ real: 48,
29
+ unit: "ft"
30
+ },
31
+ {
32
+ id: "imperial-eighth",
33
+ label: "1/8 in = 1 ft",
34
+ paper: 1,
35
+ real: 96,
36
+ unit: "ft"
37
+ }
38
+ ];
39
+ const defaultMeasure = (config, userUnit = 1) => typeof config.defaultScale === "object" ? config.defaultScale : (0, _embedpdf_engine_core_runtime.measureFromRatio)(1, 1, config.defaultScale === "imperial" ? "ft" : "m", userUnit);
40
+ function selectPageScale(viewports, crop, fallback, persistent) {
41
+ const selected = viewports.find((v) => v.owned) ?? (0, _embedpdf_engine_core_runtime.viewportForPoint)(viewports, {
42
+ x: (crop.left + crop.right) / 2,
43
+ y: (crop.top + crop.bottom) / 2
44
+ });
45
+ return {
46
+ measure: selected ? selected.measure ?? null : fallback,
47
+ source: selected ? selected.owned ? "owned" : "foreign" : "default",
48
+ ready: true,
49
+ persistent
50
+ };
51
+ }
52
+ function withUnit(m, unit, area = (0, _embedpdf_engine_core_runtime.squareOf)(unit)) {
53
+ const basis = m.x[0]?.unit.trim();
54
+ if (!(basis in _embedpdf_engine_core_runtime.METRES)) throw new RangeError("This scale has an unknown base unit; calibrate it first");
55
+ const previous = m.distance[m.distance.length - 1];
56
+ const precision = previous?.fraction === "fraction" ? 100 : previous?.precision ?? 100;
57
+ return {
58
+ ...m,
59
+ distance: [{
60
+ unit,
61
+ conversion: _embedpdf_engine_core_runtime.METRES[basis] / _embedpdf_engine_core_runtime.METRES[unit],
62
+ precision,
63
+ fraction: "decimal"
64
+ }],
65
+ area: [{
66
+ unit: (0, _embedpdf_engine_core_runtime.areaUnitLabel)(area),
67
+ conversion: _embedpdf_engine_core_runtime.METRES[basis] ** 2 / (0, _embedpdf_engine_core_runtime.squareMetres)(area),
68
+ precision,
69
+ fraction: "decimal"
70
+ }]
71
+ };
72
+ }
73
+ function withPrecision(m, precision) {
74
+ if (!Number.isInteger(Math.log10(precision)) || precision < 1 || precision > 1e9) throw new RangeError("Invalid decimal precision");
75
+ const update = (formats) => formats.map((f, i) => i === formats.length - 1 ? {
76
+ ...f,
77
+ precision,
78
+ fraction: "decimal"
79
+ } : f);
80
+ return {
81
+ ...m,
82
+ distance: update(m.distance),
83
+ area: update(m.area)
84
+ };
85
+ }
86
+ /** Change the area display unit while preserving imported distance formatting. */
87
+ function withAreaUnit(measure, unit) {
88
+ const basis = measure.x[0]?.unit.trim();
89
+ if (!(basis in _embedpdf_engine_core_runtime.METRES)) throw new RangeError("This scale has an unknown base unit; calibrate it first");
90
+ const previous = measure.area[measure.area.length - 1];
91
+ const precision = previous?.fraction === "fraction" ? 100 : previous?.precision ?? 100;
92
+ return {
93
+ ...measure,
94
+ area: [{
95
+ unit: (0, _embedpdf_engine_core_runtime.areaUnitLabel)(unit),
96
+ conversion: _embedpdf_engine_core_runtime.METRES[basis] ** 2 / (0, _embedpdf_engine_core_runtime.squareMetres)(unit),
97
+ precision,
98
+ fraction: "decimal"
99
+ }]
100
+ };
101
+ }
102
+ //#endregion
103
+ //#region src/capability.ts
104
+ const LOADING = {
105
+ measure: null,
106
+ source: "default",
107
+ ready: false,
108
+ persistent: false
109
+ };
110
+ const UNITS = Object.keys(_embedpdf_engine_core_runtime.METRES);
111
+ function createMeasurementCapability(ctx, config, effects) {
112
+ const anno = ctx.get(_embedpdf_plugin_annotation_contract.AnnotationToken);
113
+ const interaction = ctx.get(_embedpdf_plugin_interaction_contract.InteractionToken);
114
+ const canCalibrate = () => ctx.doc?.security.allows("doc.annotate.modify") ?? false;
115
+ const pons = (pon, opts) => pon === "all" || opts?.allPages ? (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber) : [pon];
116
+ const scaleOf = (pon) => {
117
+ const scale = ctx.getState().pages[pon]?.scale.measure;
118
+ if (!scale || scale.subtype !== "RL") throw new RangeError("Calibrate this page before changing its units or precision");
119
+ return scale;
120
+ };
121
+ const presets = config.presets ?? DEFAULT_PRESETS;
122
+ return {
123
+ canCalibrate,
124
+ canMeasure: (pon) => anno.canCreate() && !!ctx.getState().pages[pon]?.scale.ready,
125
+ pageScale: (pon) => ctx.getState().pages[pon]?.scale ?? LOADING,
126
+ isBusy: () => ctx.getState().pending > 0,
127
+ lastReports: () => ctx.getState().reports,
128
+ prepare: effects.prepare,
129
+ setPageScale: (pon, measure, opts = {}) => effects.change(pons(pon, opts), () => measure, opts),
130
+ calibrate: (pon, from, to, real, opts = {}) => {
131
+ const a = (0, _embedpdf_engine_core_runtime.measurementPoint)(from);
132
+ const b = (0, _embedpdf_engine_core_runtime.measurementPoint)(to);
133
+ const scale = (0, _embedpdf_engine_core_runtime.measureFromKnownLength)(Math.hypot(b.x - a.x, b.y - a.y), real);
134
+ return effects.change(pons(pon, opts), () => scale, opts);
135
+ },
136
+ setUnit: (pon, unit, areaUnit, opts = {}) => effects.change(pons(pon, opts), (p) => withUnit(scaleOf(p), unit, areaUnit), {
137
+ ...opts,
138
+ allPages: pon === "all" || opts.allPages
139
+ }),
140
+ setPrecision: (pon, precision, opts = {}) => effects.change(pons(pon, opts), (p) => withPrecision(scaleOf(p), precision), {
141
+ ...opts,
142
+ allPages: pon === "all" || opts.allPages
143
+ }),
144
+ setPreset: (pon, id, opts = {}) => {
145
+ const preset = presets.find((p) => p.id === id);
146
+ if (!preset) return Promise.reject(/* @__PURE__ */ new RangeError("Unknown scale preset"));
147
+ return effects.change(pons(pon, opts), (p) => (0, _embedpdf_engine_core_runtime.measureFromRatio)(preset.paper, preset.real, preset.unit, ctx.document()?.pages.find((page) => page.pageObjectNumber === p)?.userUnit ?? 1), opts);
148
+ },
149
+ presets: () => presets,
150
+ units: () => UNITS,
151
+ areaUnits: () => [
152
+ ...UNITS.map(_embedpdf_engine_core_runtime.squareOf),
153
+ "ha",
154
+ "acre"
155
+ ],
156
+ setAreaUnit: (pon, unit, opts = {}) => effects.change(pons(pon, opts), (p) => withAreaUnit(scaleOf(p), unit), opts),
157
+ readout: (ref) => {
158
+ const dto = anno.get(ref);
159
+ return dto ? (0, _embedpdf_engine_core_runtime.measurementReadout)(dto) : { unavailable: "not-dimension" };
160
+ },
161
+ startCalibration: () => {
162
+ if (canCalibrate()) {
163
+ ctx.dispatch({
164
+ type: "CALIBRATION",
165
+ request: null
166
+ });
167
+ interaction.activateTool("calibrate");
168
+ }
169
+ },
170
+ calibrationRequest: () => ctx.getState().calibration,
171
+ dismissCalibration: () => ctx.dispatch({
172
+ type: "CALIBRATION",
173
+ request: null
174
+ }),
175
+ onCalibrationRequested: (cb) => {
176
+ effects.calibrationListeners.add(cb);
177
+ return () => {
178
+ effects.calibrationListeners.delete(cb);
179
+ };
180
+ },
181
+ onScaleChanged: (cb) => {
182
+ effects.scaleListeners.add(cb);
183
+ return () => {
184
+ effects.scaleListeners.delete(cb);
185
+ };
186
+ }
187
+ };
188
+ }
189
+ //#endregion
190
+ //#region src/effects.ts
191
+ /** All engine IO and cross-plugin lifecycle work lives here. Calls serialize
192
+ * per page; refresh epochs prevent an old read from replacing a newer scale. */
193
+ function createMeasurementEffects(ctx, config) {
194
+ const anno = ctx.get(_embedpdf_plugin_annotation_contract_host.AnnotationToken);
195
+ const interaction = ctx.get(_embedpdf_plugin_interaction_contract.InteractionToken);
196
+ let disposed = false;
197
+ const epochs = /* @__PURE__ */ new Map();
198
+ const reading = /* @__PURE__ */ new Map();
199
+ const queues = /* @__PURE__ */ new Map();
200
+ const calibrationListeners = /* @__PURE__ */ new Set();
201
+ const scaleListeners = /* @__PURE__ */ new Set();
202
+ const meta = (pon) => ctx.document()?.pages.find((p) => p.pageObjectNumber === pon);
203
+ const live = () => {
204
+ if (disposed || !ctx.doc) throw new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.DocNotOpen);
205
+ };
206
+ const assertAllowed = () => {
207
+ live();
208
+ if (!ctx.doc.security.allows("doc.annotate.modify")) throw new _embedpdf_engine_core_runtime.PermissionDenied("doc.annotate.modify", "measurement");
209
+ };
210
+ const publish = (pon, viewports) => {
211
+ if (disposed) return;
212
+ const page = meta(pon);
213
+ if (!page) return;
214
+ const fallback = defaultMeasure(config, page.userUnit);
215
+ anno.setPageViewports(pon, viewports, fallback);
216
+ ctx.dispatch({
217
+ type: "PAGE_SCALE",
218
+ pon,
219
+ viewports,
220
+ scale: selectPageScale(viewports, page.boxes.crop, fallback, !!ctx.doc?.page(pon).measure)
221
+ });
222
+ };
223
+ const refresh = (pon) => {
224
+ live();
225
+ const page = meta(pon);
226
+ if (!page) return Promise.reject(new _embedpdf_engine_core_runtime.EngineError(_embedpdf_engine_core_runtime.EngineErrorCode.NotFound, "Page not found"));
227
+ const epoch = (epochs.get(pon) ?? 0) + 1;
228
+ epochs.set(pon, epoch);
229
+ anno.setPageViewports(pon, void 0, defaultMeasure(config, page.userUnit));
230
+ const previous = ctx.getState().pages[pon];
231
+ ctx.dispatch({
232
+ type: "PAGE_SCALE",
233
+ pon,
234
+ viewports: previous?.viewports ?? [],
235
+ scale: {
236
+ ...previous?.scale ?? {
237
+ measure: null,
238
+ source: "default",
239
+ persistent: !!ctx.doc.page(pon).measure
240
+ },
241
+ ready: false
242
+ }
243
+ });
244
+ const service = ctx.doc.page(pon).measure;
245
+ const request = (async () => {
246
+ try {
247
+ const viewports = service ? await service.viewports() : ctx.getState().pages[pon]?.viewports ?? [];
248
+ if (!disposed && epochs.get(pon) === epoch) publish(pon, viewports);
249
+ } catch (error) {
250
+ if (!disposed && epochs.get(pon) === epoch) ctx.dispatch({
251
+ type: "PAGE_SCALE",
252
+ pon,
253
+ viewports: [],
254
+ scale: {
255
+ measure: null,
256
+ source: "default",
257
+ ready: false,
258
+ persistent: !!service,
259
+ error: (0, _embedpdf_engine_core_runtime.serializeError)(error)
260
+ }
261
+ });
262
+ throw error;
263
+ } finally {
264
+ if (epochs.get(pon) === epoch) reading.delete(pon);
265
+ }
266
+ })();
267
+ reading.set(pon, request);
268
+ return request;
269
+ };
270
+ const prepare = (pon) => reading.get(pon) ?? (ctx.getState().pages[pon]?.scale.ready ? Promise.resolve() : refresh(pon));
271
+ const enqueue = (pon, action) => {
272
+ const result = (queues.get(pon) ?? Promise.resolve()).catch(() => {}).then(action);
273
+ queues.set(pon, result);
274
+ result.finally(() => {
275
+ if (queues.get(pon) === result) queues.delete(pon);
276
+ }).catch(() => {});
277
+ return result;
278
+ };
279
+ const save = async (pon, scale, opts) => {
280
+ assertAllowed();
281
+ await prepare(pon);
282
+ assertAllowed();
283
+ const service = ctx.doc.page(pon).measure;
284
+ if (service) {
285
+ await service.setScale(scale);
286
+ live();
287
+ await refresh(pon);
288
+ } else {
289
+ const page = meta(pon);
290
+ const old = ctx.getState().pages[pon]?.viewports ?? [];
291
+ publish(pon, [...old.filter((v) => !v.owned), {
292
+ bbox: page.boxes.crop,
293
+ name: "EmbedPDF",
294
+ owned: true,
295
+ measure: scale
296
+ }]);
297
+ }
298
+ live();
299
+ const report = opts.recalculate === false ? {
300
+ pon,
301
+ scale,
302
+ updated: [],
303
+ skipped: [],
304
+ failed: []
305
+ } : await anno.remeasurePage(pon, scale);
306
+ live();
307
+ for (const cb of scaleListeners) try {
308
+ cb({
309
+ pon,
310
+ report
311
+ });
312
+ } catch {}
313
+ return report;
314
+ };
315
+ const change = async (pons, measure, opts = {}) => {
316
+ assertAllowed();
317
+ ctx.dispatch({
318
+ type: "PENDING",
319
+ delta: 1
320
+ });
321
+ try {
322
+ const reports = await Promise.all(pons.map((pon) => enqueue(pon, async () => {
323
+ try {
324
+ await prepare(pon);
325
+ const scale = measure(pon);
326
+ (0, _embedpdf_engine_core_runtime.assertWritableMeasure)(scale);
327
+ return await save(pon, scale, opts);
328
+ } catch (error) {
329
+ if (!opts.allPages) throw error;
330
+ return {
331
+ pon,
332
+ updated: [],
333
+ skipped: [],
334
+ failed: [],
335
+ scaleError: (0, _embedpdf_engine_core_runtime.serializeError)(error)
336
+ };
337
+ }
338
+ })));
339
+ live();
340
+ ctx.dispatch({
341
+ type: "REPORTS",
342
+ reports
343
+ });
344
+ return reports;
345
+ } finally {
346
+ if (!disposed) ctx.dispatch({
347
+ type: "PENDING",
348
+ delta: -1
349
+ });
350
+ }
351
+ };
352
+ const start = () => {
353
+ const doc = ctx.doc;
354
+ if (!doc) return;
355
+ ctx.cleanup(() => {
356
+ disposed = true;
357
+ epochs.clear();
358
+ queues.clear();
359
+ calibrationListeners.clear();
360
+ scaleListeners.clear();
361
+ });
362
+ ctx.cleanup(anno.onDraftCaptured((draft) => {
363
+ if (draft.tool !== "calibrate" || !doc.security.allows("doc.annotate.modify")) return;
364
+ const a = (0, _embedpdf_engine_core_runtime.measurementPoint)(draft.from);
365
+ const b = (0, _embedpdf_engine_core_runtime.measurementPoint)(draft.to);
366
+ const userSpaceLength = Math.hypot(b.x - a.x, b.y - a.y);
367
+ if (!(userSpaceLength > 0)) return;
368
+ const request = {
369
+ pon: draft.pon,
370
+ from: a,
371
+ to: b,
372
+ userSpaceLength
373
+ };
374
+ interaction.activateTool("pointer");
375
+ ctx.dispatch({
376
+ type: "CALIBRATION",
377
+ request
378
+ });
379
+ for (const cb of calibrationListeners) try {
380
+ cb(request);
381
+ } catch {}
382
+ }));
383
+ const hydrate = () => {
384
+ for (const page of ctx.document()?.pages ?? []) refresh(page.pageObjectNumber).catch(() => {});
385
+ };
386
+ ctx.cleanup(doc.events.subscribe((event) => {
387
+ if (event.type === "page.viewportsChanged") refresh(event.pageObjectNumber).catch(() => {});
388
+ else if (event.type === "stream.desynced" || event.type === "document.versioned") hydrate();
389
+ }));
390
+ let pages = "";
391
+ const reconcile = () => {
392
+ const next = (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber).join(",");
393
+ if (next === pages) return;
394
+ pages = next;
395
+ for (const page of ctx.document()?.pages ?? []) if (!ctx.getState().pages[page.pageObjectNumber]) prepare(page.pageObjectNumber).catch(() => {});
396
+ };
397
+ ctx.cleanup(ctx.subscribe(reconcile));
398
+ reconcile();
399
+ };
400
+ return {
401
+ start,
402
+ prepare,
403
+ change,
404
+ calibrationListeners,
405
+ scaleListeners
406
+ };
407
+ }
408
+ //#endregion
409
+ //#region src/reducer.ts
410
+ const initialMeasurementState = {
411
+ pages: {},
412
+ pending: 0,
413
+ calibration: null,
414
+ reports: []
415
+ };
416
+ function measurementReducer(s, a) {
417
+ switch (a.type) {
418
+ case "PAGE_SCALE": return {
419
+ ...s,
420
+ pages: {
421
+ ...s.pages,
422
+ [a.pon]: {
423
+ viewports: a.viewports,
424
+ scale: a.scale
425
+ }
426
+ }
427
+ };
428
+ case "PENDING": return {
429
+ ...s,
430
+ pending: Math.max(0, s.pending + a.delta)
431
+ };
432
+ case "CALIBRATION": return {
433
+ ...s,
434
+ calibration: a.request
435
+ };
436
+ case "REPORTS": return {
437
+ ...s,
438
+ reports: a.reports
439
+ };
440
+ }
441
+ }
442
+ //#endregion
443
+ //#region src/measurement.plugin.ts
444
+ const measurementPlugin = (config = {}) => {
445
+ const drivers = /* @__PURE__ */ new Map();
446
+ return (0, _embedpdf_core.definePlugin)({
447
+ id: "measurement",
448
+ scope: "document",
449
+ token: require_contract.MeasurementToken,
450
+ requires: [_embedpdf_plugin_annotation_contract_host.AnnotationToken, _embedpdf_plugin_interaction_contract.InteractionToken],
451
+ initialState: initialMeasurementState,
452
+ reduce: measurementReducer,
453
+ capability: (ctx) => {
454
+ const effects = createMeasurementEffects(ctx, config);
455
+ drivers.set(ctx.documentId, effects);
456
+ ctx.cleanup(() => {
457
+ drivers.delete(ctx.documentId);
458
+ });
459
+ return createMeasurementCapability(ctx, config, effects);
460
+ },
461
+ effects: (ctx) => {
462
+ ctx.get(require_contract.MeasurementToken);
463
+ drivers.get(ctx.documentId).start();
464
+ }
465
+ });
466
+ };
467
+ //#endregion
468
+ exports.MeasurementToken = require_contract.MeasurementToken;
469
+ exports.measurementPlugin = measurementPlugin;
470
+
471
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":["METRES","METRES","AnnotationToken","InteractionToken","squareOf","AnnotationToken","InteractionToken","EngineError","EngineErrorCode","PermissionDenied","MeasurementToken","AnnotationToken","InteractionToken"],"sources":["../src/scale.ts","../src/capability.ts","../src/effects.ts","../src/reducer.ts","../src/measurement.plugin.ts"],"sourcesContent":["import {\n areaUnitLabel,\n measureFromRatio,\n METRES,\n squareMetres,\n squareOf,\n viewportForPoint,\n} from '@embedpdf/engine-core/runtime';\nimport type {\n AreaUnit,\n LengthUnit,\n PageMeasurementViewport,\n PdfMeasure,\n PdfRect,\n} from '@embedpdf/engine-core/runtime';\nimport type { MeasurementConfig, PageScale, ScalePreset } from './types';\n\nexport const DEFAULT_PRESETS: ScalePreset[] = [\n ...[1, 10, 20, 50, 100, 200].map((real) => ({\n id: `metric-${real}`,\n label: `1:${real}`,\n paper: 1,\n real,\n unit: 'm' as const,\n })),\n { id: 'imperial-quarter', label: '1/4 in = 1 ft', paper: 1, real: 48, unit: 'ft' },\n { id: 'imperial-eighth', label: '1/8 in = 1 ft', paper: 1, real: 96, unit: 'ft' },\n];\n\nexport const defaultMeasure = (config: MeasurementConfig, userUnit = 1): PdfMeasure =>\n typeof config.defaultScale === 'object'\n ? config.defaultScale\n : measureFromRatio(1, 1, config.defaultScale === 'imperial' ? 'ft' : 'm', userUnit);\n\nexport function selectPageScale(\n viewports: PageMeasurementViewport[],\n crop: PdfRect,\n fallback: PdfMeasure,\n persistent: boolean,\n): PageScale {\n const selected =\n viewports.find((v) => v.owned) ??\n viewportForPoint(viewports, {\n x: (crop.left + crop.right) / 2,\n y: (crop.top + crop.bottom) / 2,\n });\n return {\n measure: selected ? (selected.measure ?? null) : fallback,\n source: selected ? (selected.owned ? 'owned' : 'foreign') : 'default',\n ready: true,\n persistent,\n };\n}\n\nexport function withUnit(\n m: PdfMeasure,\n unit: LengthUnit,\n area: AreaUnit = squareOf(unit),\n): PdfMeasure {\n const basis = m.x[0]?.unit.trim() as LengthUnit;\n if (!(basis in METRES)) {\n throw new RangeError('This scale has an unknown base unit; calibrate it first');\n }\n const previous = m.distance[m.distance.length - 1];\n const precision = previous?.fraction === 'fraction' ? 100 : (previous?.precision ?? 100);\n return {\n ...m,\n distance: [{ unit, conversion: METRES[basis] / METRES[unit], precision, fraction: 'decimal' }],\n area: [\n {\n unit: areaUnitLabel(area),\n conversion: METRES[basis] ** 2 / squareMetres(area),\n precision,\n fraction: 'decimal',\n },\n ],\n };\n}\n\nexport function withPrecision(m: PdfMeasure, precision: number): PdfMeasure {\n if (!Number.isInteger(Math.log10(precision)) || precision < 1 || precision > 1e9) {\n throw new RangeError('Invalid decimal precision');\n }\n const update = (formats: PdfMeasure['distance']) =>\n formats.map((f, i) =>\n i === formats.length - 1 ? { ...f, precision, fraction: 'decimal' as const } : f,\n );\n return { ...m, distance: update(m.distance), area: update(m.area) };\n}\n\n/** Change the area display unit while preserving imported distance formatting. */\nexport function withAreaUnit(measure: PdfMeasure, unit: AreaUnit): PdfMeasure {\n const basis = measure.x[0]?.unit.trim() as LengthUnit;\n if (!(basis in METRES)) {\n throw new RangeError('This scale has an unknown base unit; calibrate it first');\n }\n const previous = measure.area[measure.area.length - 1];\n const precision = previous?.fraction === 'fraction' ? 100 : (previous?.precision ?? 100);\n return {\n ...measure,\n area: [\n {\n unit: areaUnitLabel(unit),\n conversion: METRES[basis] ** 2 / squareMetres(unit),\n precision,\n fraction: 'decimal',\n },\n ],\n };\n}\n","import type { PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport {\n measureFromKnownLength,\n measureFromRatio,\n measurementPoint,\n measurementReadout,\n METRES,\n squareOf,\n} from '@embedpdf/engine-core/runtime';\nimport type { PdfMeasure } from '@embedpdf/engine-core/runtime';\nimport type { MeasurementEffects } from './effects';\nimport { DEFAULT_PRESETS, withAreaUnit, withPrecision, withUnit } from './scale';\nimport type {\n MeasurementAction,\n MeasurementCapability,\n MeasurementConfig,\n MeasurementState,\n PageScale,\n SetScaleOptions,\n} from './types';\n\nconst LOADING: PageScale = { measure: null, source: 'default', ready: false, persistent: false };\nconst UNITS = Object.keys(METRES) as Array<keyof typeof METRES>;\n\nexport function createMeasurementCapability(\n ctx: PluginContext<MeasurementState, MeasurementAction>,\n config: MeasurementConfig,\n effects: MeasurementEffects,\n): MeasurementCapability {\n const anno = ctx.get(AnnotationToken);\n const interaction = ctx.get(InteractionToken);\n const canCalibrate = () => ctx.doc?.security.allows('doc.annotate.modify') ?? false;\n const pons = (pon: number | 'all', opts?: SetScaleOptions) =>\n pon === 'all' || opts?.allPages\n ? (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber)\n : [pon];\n const scaleOf = (pon: number): PdfMeasure => {\n const scale = ctx.getState().pages[pon]?.scale.measure;\n if (!scale || scale.subtype !== 'RL') {\n throw new RangeError('Calibrate this page before changing its units or precision');\n }\n return scale;\n };\n const presets = config.presets ?? DEFAULT_PRESETS;\n return {\n canCalibrate,\n canMeasure: (pon) => anno.canCreate() && !!ctx.getState().pages[pon]?.scale.ready,\n pageScale: (pon) => ctx.getState().pages[pon]?.scale ?? LOADING,\n isBusy: () => ctx.getState().pending > 0,\n lastReports: () => ctx.getState().reports,\n prepare: effects.prepare,\n setPageScale: (pon, measure, opts = {}) => effects.change(pons(pon, opts), () => measure, opts),\n calibrate: (pon, from, to, real, opts = {}) => {\n const a = measurementPoint(from);\n const b = measurementPoint(to);\n const scale = measureFromKnownLength(Math.hypot(b.x - a.x, b.y - a.y), real);\n return effects.change(pons(pon, opts), () => scale, opts);\n },\n setUnit: (pon, unit, areaUnit, opts = {}) =>\n effects.change(pons(pon, opts), (p) => withUnit(scaleOf(p), unit, areaUnit), {\n ...opts,\n allPages: pon === 'all' || opts.allPages,\n }),\n setPrecision: (pon, precision, opts = {}) =>\n effects.change(pons(pon, opts), (p) => withPrecision(scaleOf(p), precision), {\n ...opts,\n allPages: pon === 'all' || opts.allPages,\n }),\n setPreset: (pon, id, opts = {}) => {\n const preset = presets.find((p) => p.id === id);\n if (!preset) {\n return Promise.reject(new RangeError('Unknown scale preset'));\n }\n return effects.change(\n pons(pon, opts),\n (p) =>\n measureFromRatio(\n preset.paper,\n preset.real,\n preset.unit,\n ctx.document()?.pages.find((page) => page.pageObjectNumber === p)?.userUnit ?? 1,\n ),\n opts,\n );\n },\n presets: () => presets,\n units: () => UNITS,\n areaUnits: () => [...UNITS.map(squareOf), 'ha', 'acre'],\n setAreaUnit: (pon, unit, opts = {}) =>\n effects.change(pons(pon, opts), (p) => withAreaUnit(scaleOf(p), unit), opts),\n readout: (ref) => {\n const dto = anno.get(ref);\n return dto ? measurementReadout(dto) : { unavailable: 'not-dimension' };\n },\n startCalibration: () => {\n if (canCalibrate()) {\n ctx.dispatch({ type: 'CALIBRATION', request: null });\n interaction.activateTool('calibrate');\n }\n },\n calibrationRequest: () => ctx.getState().calibration,\n dismissCalibration: () => ctx.dispatch({ type: 'CALIBRATION', request: null }),\n onCalibrationRequested: (cb) => {\n effects.calibrationListeners.add(cb);\n return () => {\n effects.calibrationListeners.delete(cb);\n };\n },\n onScaleChanged: (cb) => {\n effects.scaleListeners.add(cb);\n return () => {\n effects.scaleListeners.delete(cb);\n };\n },\n };\n}\n","import type { PluginContext } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport {\n assertWritableMeasure,\n EngineError,\n EngineErrorCode,\n PermissionDenied,\n measurementPoint,\n serializeError,\n} from '@embedpdf/engine-core/runtime';\nimport type { PdfMeasure, PageMeasurementViewport } from '@embedpdf/engine-core/runtime';\nimport { defaultMeasure, selectPageScale } from './scale';\nimport type {\n CalibrationRequest,\n MeasurementAction,\n MeasurementConfig,\n MeasurementState,\n ScaleChangeReport,\n SetScaleOptions,\n} from './types';\n\ntype Context = PluginContext<MeasurementState, MeasurementAction>;\n/** All engine IO and cross-plugin lifecycle work lives here. Calls serialize\n * per page; refresh epochs prevent an old read from replacing a newer scale. */\nexport function createMeasurementEffects(ctx: Context, config: MeasurementConfig) {\n const anno = ctx.get(AnnotationToken);\n const interaction = ctx.get(InteractionToken);\n let disposed = false;\n const epochs = new Map<number, number>();\n const reading = new Map<number, Promise<void>>();\n const queues = new Map<number, Promise<unknown>>();\n const calibrationListeners = new Set<(r: CalibrationRequest) => void>();\n const scaleListeners = new Set<(e: { pon: number; report: ScaleChangeReport }) => void>();\n const meta = (pon: number) => ctx.document()?.pages.find((p) => p.pageObjectNumber === pon);\n const live = () => {\n if (disposed || !ctx.doc) {\n throw new EngineError(EngineErrorCode.DocNotOpen);\n }\n };\n const assertAllowed = () => {\n live();\n if (!ctx.doc!.security.allows('doc.annotate.modify')) {\n throw new PermissionDenied('doc.annotate.modify', 'measurement');\n }\n };\n const publish = (pon: number, viewports: PageMeasurementViewport[]) => {\n if (disposed) {\n return;\n }\n const page = meta(pon);\n if (!page) {\n return;\n }\n const fallback = defaultMeasure(config, page.userUnit);\n anno.setPageViewports(pon, viewports, fallback);\n ctx.dispatch({\n type: 'PAGE_SCALE',\n pon,\n viewports,\n scale: selectPageScale(viewports, page.boxes.crop, fallback, !!ctx.doc?.page(pon).measure),\n });\n };\n const refresh = (pon: number): Promise<void> => {\n live();\n const page = meta(pon);\n if (!page) {\n return Promise.reject(new EngineError(EngineErrorCode.NotFound, 'Page not found'));\n }\n const epoch = (epochs.get(pon) ?? 0) + 1;\n epochs.set(pon, epoch);\n // Disable creation until calibration is known; never race a default into an imported viewport.\n anno.setPageViewports(pon, undefined, defaultMeasure(config, page.userUnit));\n const previous = ctx.getState().pages[pon];\n ctx.dispatch({\n type: 'PAGE_SCALE',\n pon,\n viewports: previous?.viewports ?? [],\n scale: {\n ...(previous?.scale ?? {\n measure: null,\n source: 'default',\n persistent: !!ctx.doc!.page(pon).measure,\n }),\n ready: false,\n },\n });\n const service = ctx.doc!.page(pon).measure;\n const request = (async () => {\n try {\n const viewports = service\n ? await service.viewports()\n : (ctx.getState().pages[pon]?.viewports ?? []);\n if (!disposed && epochs.get(pon) === epoch) {\n publish(pon, viewports);\n }\n } catch (error) {\n if (!disposed && epochs.get(pon) === epoch) {\n ctx.dispatch({\n type: 'PAGE_SCALE',\n pon,\n viewports: [],\n scale: {\n measure: null,\n source: 'default',\n ready: false,\n persistent: !!service,\n error: serializeError(error),\n },\n });\n }\n throw error;\n } finally {\n if (epochs.get(pon) === epoch) {\n reading.delete(pon);\n }\n }\n })();\n reading.set(pon, request);\n return request;\n };\n const prepare = (pon: number) =>\n reading.get(pon) ?? (ctx.getState().pages[pon]?.scale.ready ? Promise.resolve() : refresh(pon));\n const enqueue = (\n pon: number,\n action: () => Promise<ScaleChangeReport>,\n ): Promise<ScaleChangeReport> => {\n const result = (queues.get(pon) ?? Promise.resolve()).catch(() => {}).then(action);\n queues.set(pon, result);\n void result\n .finally(() => {\n if (queues.get(pon) === result) {\n queues.delete(pon);\n }\n })\n .catch(() => {});\n return result;\n };\n const save = async (\n pon: number,\n scale: PdfMeasure,\n opts: SetScaleOptions,\n ): Promise<ScaleChangeReport> => {\n assertAllowed();\n await prepare(pon);\n assertAllowed();\n const service = ctx.doc!.page(pon).measure;\n if (service) {\n await service.setScale(scale);\n live();\n await refresh(pon);\n } else {\n const page = meta(pon)!;\n const old = ctx.getState().pages[pon]?.viewports ?? [];\n publish(pon, [\n ...old.filter((v) => !v.owned),\n { bbox: page.boxes.crop, name: 'EmbedPDF', owned: true, measure: scale },\n ]);\n }\n live();\n const report =\n opts.recalculate === false\n ? { pon, scale, updated: [], skipped: [], failed: [] }\n : await anno.remeasurePage(pon, scale);\n live();\n for (const cb of scaleListeners) {\n try {\n cb({ pon, report });\n } catch {\n /* observers do not roll back a committed scale */\n }\n }\n return report;\n };\n const change = async (\n pons: number[],\n measure: (pon: number) => PdfMeasure,\n opts: SetScaleOptions = {},\n ): Promise<ScaleChangeReport[]> => {\n assertAllowed();\n ctx.dispatch({ type: 'PENDING', delta: 1 });\n try {\n const reports = await Promise.all(\n pons.map((pon) =>\n enqueue(pon, async () => {\n try {\n await prepare(pon);\n const scale = measure(pon);\n assertWritableMeasure(scale);\n return await save(pon, scale, opts);\n } catch (error) {\n if (!opts.allPages) {\n throw error;\n }\n return {\n pon,\n updated: [],\n skipped: [],\n failed: [],\n scaleError: serializeError(error),\n };\n }\n }),\n ),\n );\n live();\n ctx.dispatch({ type: 'REPORTS', reports });\n return reports;\n } finally {\n if (!disposed) {\n ctx.dispatch({ type: 'PENDING', delta: -1 });\n }\n }\n };\n const start = () => {\n const doc = ctx.doc;\n if (!doc) {\n return;\n }\n ctx.cleanup(() => {\n disposed = true;\n epochs.clear();\n queues.clear();\n calibrationListeners.clear();\n scaleListeners.clear();\n });\n ctx.cleanup(\n anno.onDraftCaptured((draft) => {\n if (draft.tool !== 'calibrate' || !doc.security.allows('doc.annotate.modify')) {\n return;\n }\n const a = measurementPoint(draft.from);\n const b = measurementPoint(draft.to);\n const userSpaceLength = Math.hypot(b.x - a.x, b.y - a.y);\n if (!(userSpaceLength > 0)) {\n return;\n }\n const request = { pon: draft.pon, from: a, to: b, userSpaceLength };\n interaction.activateTool('pointer');\n ctx.dispatch({ type: 'CALIBRATION', request });\n for (const cb of calibrationListeners) {\n try {\n cb(request);\n } catch {\n /* observers */\n }\n }\n }),\n );\n const hydrate = () => {\n for (const page of ctx.document()?.pages ?? []) {\n void refresh(page.pageObjectNumber).catch(() => {});\n }\n };\n ctx.cleanup(\n doc.events.subscribe((event) => {\n if (event.type === 'page.viewportsChanged') {\n void refresh(event.pageObjectNumber).catch(() => {});\n } else if (event.type === 'stream.desynced' || event.type === 'document.versioned') {\n hydrate();\n }\n }),\n );\n // Covers pages inserted after this document-scoped instance was created.\n let pages = '';\n const reconcile = () => {\n const next = (ctx.document()?.pages ?? []).map((p) => p.pageObjectNumber).join(',');\n if (next === pages) {\n return;\n }\n pages = next;\n for (const page of ctx.document()?.pages ?? [])\n if (!ctx.getState().pages[page.pageObjectNumber]) {\n void prepare(page.pageObjectNumber).catch(() => {});\n }\n };\n ctx.cleanup(ctx.subscribe(reconcile));\n reconcile();\n };\n return { start, prepare, change, calibrationListeners, scaleListeners };\n}\n\nexport type MeasurementEffects = ReturnType<typeof createMeasurementEffects>;\n","import type { MeasurementAction, MeasurementState } from './types';\n\nexport const initialMeasurementState: MeasurementState = {\n pages: {},\n pending: 0,\n calibration: null,\n reports: [],\n};\n\nexport function measurementReducer(s: MeasurementState, a: MeasurementAction): MeasurementState {\n switch (a.type) {\n case 'PAGE_SCALE':\n return { ...s, pages: { ...s.pages, [a.pon]: { viewports: a.viewports, scale: a.scale } } };\n case 'PENDING':\n return { ...s, pending: Math.max(0, s.pending + a.delta) };\n case 'CALIBRATION':\n return { ...s, calibration: a.request };\n case 'REPORTS':\n return { ...s, reports: a.reports };\n }\n}\n","import { definePlugin } from '@embedpdf/core';\nimport { AnnotationToken } from '@embedpdf/plugin-annotation/contract/host';\nimport { InteractionToken } from '@embedpdf/plugin-interaction/contract';\nimport { createMeasurementCapability } from './capability';\nimport { createMeasurementEffects, type MeasurementEffects } from './effects';\nimport { initialMeasurementState, measurementReducer } from './reducer';\nimport { MeasurementToken } from './types';\nimport type {\n MeasurementAction,\n MeasurementCapability,\n MeasurementConfig,\n MeasurementState,\n} from './types';\n\nexport const measurementPlugin = (config: MeasurementConfig = {}) => {\n // A plugin definition is reused across documents. Drivers are keyed by the\n // bound instance, never one mutable closure shared between document tabs.\n const drivers = new Map<string, MeasurementEffects>();\n return definePlugin<MeasurementState, MeasurementAction, MeasurementCapability>({\n id: 'measurement',\n scope: 'document',\n token: MeasurementToken,\n requires: [AnnotationToken, InteractionToken],\n initialState: initialMeasurementState,\n reduce: measurementReducer,\n capability: (ctx) => {\n const effects = createMeasurementEffects(ctx, config);\n drivers.set(ctx.documentId!, effects);\n ctx.cleanup(() => {\n drivers.delete(ctx.documentId!);\n });\n return createMeasurementCapability(ctx, config, effects);\n },\n effects: (ctx) => {\n ctx.get(MeasurementToken); // Capabilities are lazy; construct this document's driver first.\n drivers.get(ctx.documentId!)!.start();\n },\n });\n};\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import { _ as SetScaleOptions, a as MeasurementAction, c as MeasurementReadout, d as MeasurementUnavailable, f as PageScale, g as ScalePreset, h as ScaleChangeReport, i as LengthUnit, l as MeasurementState, m as RecalibrationReport, n as AreaUnit, o as MeasurementCapability, p as PdfMeasure, r as CalibrationRequest, s as MeasurementConfig, t as AnnotationRef, u as MeasurementToken } from "./contract-BnLRuw-Z.cjs";
2
+ //#region src/measurement.plugin.d.ts
3
+ declare const measurementPlugin: (config?: MeasurementConfig) => import("@embedpdf/core").PluginDef<MeasurementState, MeasurementAction, MeasurementCapability>;
4
+ //#endregion
5
+ export { type AnnotationRef, type AreaUnit, type CalibrationRequest, type LengthUnit, type MeasurementAction, type MeasurementCapability, type MeasurementConfig, type MeasurementReadout, type MeasurementState, MeasurementToken, type MeasurementUnavailable, type PageScale, type PdfMeasure, type RecalibrationReport, type ScaleChangeReport, type ScalePreset, type SetScaleOptions, measurementPlugin };
6
+ //# sourceMappingURL=index.d.cts.map
@@ -0,0 +1,6 @@
1
+ import { _ as SetScaleOptions, a as MeasurementAction, c as MeasurementReadout, d as MeasurementUnavailable, f as PageScale, g as ScalePreset, h as ScaleChangeReport, i as LengthUnit, l as MeasurementState, m as RecalibrationReport, n as AreaUnit, o as MeasurementCapability, p as PdfMeasure, r as CalibrationRequest, s as MeasurementConfig, t as AnnotationRef, u as MeasurementToken } from "./contract-C_ugpRGJ.js";
2
+ //#region src/measurement.plugin.d.ts
3
+ declare const measurementPlugin: (config?: MeasurementConfig) => import("@embedpdf/core").PluginDef<MeasurementState, MeasurementAction, MeasurementCapability>;
4
+ //#endregion
5
+ export { type AnnotationRef, type AreaUnit, type CalibrationRequest, type LengthUnit, type MeasurementAction, type MeasurementCapability, type MeasurementConfig, type MeasurementReadout, type MeasurementState, MeasurementToken, type MeasurementUnavailable, type PageScale, type PdfMeasure, type RecalibrationReport, type ScaleChangeReport, type ScalePreset, type SetScaleOptions, measurementPlugin };
6
+ //# sourceMappingURL=index.d.ts.map