@reekon-tools/boldr-utils 1.22.0 → 1.24.0
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/annotation/canvas/pdfCanvasPages.d.ts +25 -0
- package/dist/annotation/canvas/pdfCanvasPages.js +255 -0
- package/dist/annotation/data/AnnotationDataProvider.d.ts +6 -0
- package/dist/annotation/data/InMemoryAnnotationProvider.d.ts +6 -0
- package/dist/annotation/data/InMemoryAnnotationProvider.js +25 -0
- package/dist/annotation/data/hooks/usePdfCanvasDoc.d.ts +29 -0
- package/dist/annotation/data/hooks/usePdfCanvasDoc.js +344 -0
- package/dist/export/pdf/annots.d.ts +23 -0
- package/dist/export/pdf/annots.js +135 -0
- package/dist/export/pdf/decrypt.d.ts +21 -0
- package/dist/export/pdf/decrypt.js +121 -0
- package/dist/export/pdf/fonts.d.ts +3 -4
- package/dist/export/pdf/fonts.js +2 -14
- package/dist/export/pdf/index.d.ts +4 -2
- package/dist/export/pdf/index.js +3 -1
- package/dist/export/pdf/marks.d.ts +66 -5
- package/dist/export/pdf/marks.js +150 -7
- package/dist/export/pdf/pageMapping.d.ts +2 -0
- package/dist/export/pdf/pageMapping.js +10 -0
- package/dist/export/pdf/renderCanvasToPdf.d.ts +9 -1
- package/dist/export/pdf/renderCanvasToPdf.js +303 -120
- package/dist/export/pdf/resources.d.ts +35 -0
- package/dist/export/pdf/resources.js +95 -0
- package/dist/export/pdf/tiles.d.ts +5 -9
- package/dist/export/pdf/tiles.js +20 -20
- package/dist/export/pdf/types.d.ts +25 -1
- package/dist/exports.d.ts +3 -0
- package/dist/exports.js +3 -0
- package/dist/server.d.ts +2 -0
- package/dist/server.js +2 -0
- package/dist/types/firestore.d.ts +6 -0
- package/dist/types/firestore.js +5 -0
- package/dist/types/pdfCanvas.d.ts +38 -0
- package/dist/types/pdfCanvas.js +16 -0
- package/package.json +6 -1
package/dist/export/pdf/tiles.js
CHANGED
|
@@ -133,15 +133,15 @@ const valueRowOps = (ctx, value, cx, cy, color, availableWidth, tileWidth) => {
|
|
|
133
133
|
tokens.forEach((t, i) => {
|
|
134
134
|
const w = widths[i];
|
|
135
135
|
if (!t.fraction) {
|
|
136
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
136
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, t.text, fs, color, x, baseline));
|
|
137
137
|
}
|
|
138
138
|
else {
|
|
139
139
|
const stackW = Math.max(ctx.fonts.width(t.fraction.num, fracFs), ctx.fonts.width(t.fraction.den, fracFs));
|
|
140
140
|
const scx = x + stackW / 2;
|
|
141
141
|
// Numerator above the rule, denominator below; rule at the row centre.
|
|
142
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
142
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, t.fraction.num, fracFs, color, scx, cy - fracFs * 0.15, { align: 'center' }), pushGraphicsState(), ...fillStateOps(color), rectangle(x, cy - fracFs * 0.05, stackW, Math.max(fracFs * 0.08, 0.8)), fill(), popGraphicsState(), ...ctx.fonts.textOps(ctx.scope, t.fraction.den, fracFs, color, scx, cy + fracFs * 0.85, { align: 'center' }));
|
|
143
143
|
if (t.fraction.suffix) {
|
|
144
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
144
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, t.fraction.suffix, fs, color, x + stackW, baseline));
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
147
|
x += w + gap;
|
|
@@ -156,7 +156,7 @@ const measurementTileOps = (ctx, c) => {
|
|
|
156
156
|
const white = GeneralColors.white;
|
|
157
157
|
// Header row: position label, bold, top-left.
|
|
158
158
|
if (c.positionLabel) {
|
|
159
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
159
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.positionLabel, 12, white, 6, 14));
|
|
160
160
|
}
|
|
161
161
|
// Value row, centred on the tile, between the two unit slots.
|
|
162
162
|
const hasUnit = !!c.unit;
|
|
@@ -164,7 +164,7 @@ const measurementTileOps = (ctx, c) => {
|
|
|
164
164
|
const valueText = (c.negative ? '-' : '') + c.value;
|
|
165
165
|
ops.push(...valueRowOps(ctx, valueText, SQUARE / 2, 48, white, available, SQUARE));
|
|
166
166
|
if (hasUnit) {
|
|
167
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
167
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.unit, UNIT_FONT, white, SQUARE - UNIT_RESERVE / 2, 52, {
|
|
168
168
|
align: 'center',
|
|
169
169
|
}));
|
|
170
170
|
}
|
|
@@ -175,7 +175,7 @@ const measurementTileOps = (ctx, c) => {
|
|
|
175
175
|
ops.push(...filledRoundedRect(4, SQUARE - 20, SQUARE - 8, 16, 3, FormulaColors.darkPurple), ...strokedRoundedRect(4, SQUARE - 20, SQUARE - 8, 16, 3, FormulaColors.purple, 1));
|
|
176
176
|
}
|
|
177
177
|
const text = truncate(ctx.fonts, c.label, labelSize, SQUARE - 12);
|
|
178
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
178
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, text, labelSize, white, SQUARE / 2, SQUARE - 8, { align: 'center' }));
|
|
179
179
|
}
|
|
180
180
|
return ops;
|
|
181
181
|
};
|
|
@@ -186,9 +186,9 @@ const emptyTileOps = (ctx, c) => {
|
|
|
186
186
|
...strokedRoundedRect(0, 0, SQUARE, SQUARE, CARD_RADIUS, GeneralColors.grey3, 1),
|
|
187
187
|
];
|
|
188
188
|
if (c.topLeftLabel)
|
|
189
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
189
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.topLeftLabel, 10, ink, 8, 18));
|
|
190
190
|
if (c.topRightLabel) {
|
|
191
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
191
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.topRightLabel, 10, ink, SQUARE - 8, 18, {
|
|
192
192
|
align: 'right',
|
|
193
193
|
}));
|
|
194
194
|
}
|
|
@@ -205,7 +205,7 @@ const emptyTileOps = (ctx, c) => {
|
|
|
205
205
|
]), stroke(), popGraphicsState());
|
|
206
206
|
if (c.bottomLabel) {
|
|
207
207
|
const text = truncate(ctx.fonts, c.bottomLabel, 10, SQUARE - 16);
|
|
208
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
208
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, text, 10, ink, cx, SQUARE - 10, {
|
|
209
209
|
align: 'center',
|
|
210
210
|
}));
|
|
211
211
|
}
|
|
@@ -216,17 +216,17 @@ const literalTileOps = (ctx, c) => {
|
|
|
216
216
|
const fillColor = filled ? TileColors.activeBlue : GeneralColors.grey2;
|
|
217
217
|
const ink = filled ? GeneralColors.white : GeneralColors.grey4;
|
|
218
218
|
const ops = filledRoundedRect(0, 0, SQUARE, SQUARE, CARD_RADIUS, fillColor);
|
|
219
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
220
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
219
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.topLeftLabel, 10, ink, 8, 18));
|
|
220
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.topRightLabel, 10, ink, SQUARE - 8, 18, {
|
|
221
221
|
align: 'right',
|
|
222
222
|
}));
|
|
223
223
|
ops.push(...filledRoundedRect(8, 28, SQUARE - 16, 40, 4, filled ? TileColors.activeBlue : GeneralColors.grey3));
|
|
224
224
|
if (filled) {
|
|
225
225
|
const size = ctx.fonts.fitSize(c.value, SQUARE - 24, 16, 6);
|
|
226
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
226
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, c.value, size, ink, SQUARE / 2, 48 + size * 0.35, { align: 'center' }));
|
|
227
227
|
}
|
|
228
228
|
const bottom = truncate(ctx.fonts, c.bottomLabel, 10, SQUARE - 16);
|
|
229
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
229
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, bottom, 10, ink, SQUARE / 2, SQUARE - 10, {
|
|
230
230
|
align: 'center',
|
|
231
231
|
}));
|
|
232
232
|
return ops;
|
|
@@ -273,7 +273,7 @@ const headerTileOps = (ctx, c) => {
|
|
|
273
273
|
ops.push(...globeOps(W / 2, by + S.badgeHeight / 2, S.globeSize, S.globeColor));
|
|
274
274
|
else {
|
|
275
275
|
const text = truncate(ctx.fonts, b.text, S.badgeFontSize, inner - 10);
|
|
276
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
276
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, text, S.badgeFontSize, S.badgeTextColor, W / 2, by + S.badgeHeight / 2 + S.badgeFontSize * 0.35, { align: 'center' }));
|
|
277
277
|
}
|
|
278
278
|
});
|
|
279
279
|
}
|
|
@@ -287,7 +287,7 @@ const headerTileOps = (ctx, c) => {
|
|
|
287
287
|
ops.push(...globeOps(bx + bw / 2, y + S.badgeHeight / 2, S.globeSize, S.globeColor));
|
|
288
288
|
else {
|
|
289
289
|
const text = truncate(ctx.fonts, b.text, S.badgeFontSize, bw - 10);
|
|
290
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
290
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, text, S.badgeFontSize, S.badgeTextColor, bx + bw / 2, y + S.badgeHeight / 2 + S.badgeFontSize * 0.35, { align: 'center' }));
|
|
291
291
|
}
|
|
292
292
|
});
|
|
293
293
|
}
|
|
@@ -295,7 +295,7 @@ const headerTileOps = (ctx, c) => {
|
|
|
295
295
|
}
|
|
296
296
|
if (d.name !== null) {
|
|
297
297
|
const text = truncate(ctx.fonts, d.name, S.nameFontSize, inner);
|
|
298
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
298
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, text, S.nameFontSize, S.nameColor, W / 2, y + S.nameGap + S.nameFontSize * 0.95, { align: 'center' }));
|
|
299
299
|
}
|
|
300
300
|
return ops;
|
|
301
301
|
};
|
|
@@ -311,14 +311,14 @@ const objectTileOps = (ctx, c) => {
|
|
|
311
311
|
if (!thumb) {
|
|
312
312
|
ops.push(...filledRoundedRect(x, y, w, h, CARD_RADIUS, GeneralColors.grey2));
|
|
313
313
|
const name = truncate(ctx.fonts, c.name || 'Object removed', 9, w - 8);
|
|
314
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
314
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, name, 9, GeneralColors.grey4, SQUARE / 2, SQUARE / 2 + 3, { align: 'center' }));
|
|
315
315
|
return ops;
|
|
316
316
|
}
|
|
317
317
|
// Thumbnail, cover-fit and clipped to the rounded card.
|
|
318
318
|
const scale = Math.max(w / thumb.width, h / thumb.height);
|
|
319
319
|
const iw = thumb.width * scale;
|
|
320
320
|
const ih = thumb.height * scale;
|
|
321
|
-
ops.push(pushGraphicsState(), ...roundedRectPathOps(x, y, w, h, CARD_RADIUS), clip(), endPath(), ...imageOps(thumb
|
|
321
|
+
ops.push(pushGraphicsState(), ...roundedRectPathOps(x, y, w, h, CARD_RADIUS), clip(), endPath(), ...imageOps(ctx.scope.imageKey(thumb), x + (w - iw) / 2, y + (h - ih) / 2, iw, ih), popGraphicsState());
|
|
322
322
|
// Footer bar by object type: a layout group gets the magenta bar with white
|
|
323
323
|
// ink, a plain photo/background none, every document a white bar with dark ink.
|
|
324
324
|
const type = c.fileType;
|
|
@@ -330,7 +330,7 @@ const objectTileOps = (ctx, c) => {
|
|
|
330
330
|
if (bar) {
|
|
331
331
|
ops.push(pushGraphicsState(), ...roundedRectPathOps(x, y, w, h, CARD_RADIUS), clip(), endPath(), ...fillStateOps(bar.fill), rectangle(x, y + h - OBJECT_BAR_HEIGHT, w, OBJECT_BAR_HEIGHT), fill(), popGraphicsState());
|
|
332
332
|
const name = truncate(ctx.fonts, c.name, 9, w - 8);
|
|
333
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
333
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, name, 9, bar.ink, SQUARE / 2, y + h - OBJECT_BAR_HEIGHT / 2 + 3, { align: 'center' }));
|
|
334
334
|
}
|
|
335
335
|
return ops;
|
|
336
336
|
};
|
|
@@ -365,7 +365,7 @@ const instructionsTileOps = (ctx, c) => {
|
|
|
365
365
|
const lh = size * 1.25;
|
|
366
366
|
const top = SQUARE / 2 - (lines.length * lh) / 2;
|
|
367
367
|
lines.forEach((line, i) => {
|
|
368
|
-
ops.push(...ctx.fonts.textOps(ctx.
|
|
368
|
+
ops.push(...ctx.fonts.textOps(ctx.scope, truncate(ctx.fonts, line, size, maxW), size, color, SQUARE / 2, top + i * lh + size * 0.9, { align: 'center' }));
|
|
369
369
|
});
|
|
370
370
|
return ops;
|
|
371
371
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { GroupHeaderDescriptor } from '../../annotation/canvas/groupHeaderLayout.js';
|
|
2
2
|
import type { AnnotationCanvasState, PlacedMeasurementRef } from '../../types/annotation.js';
|
|
3
|
+
import type { PdfCanvasData, PdfCanvasPageState } from '../../types/pdfCanvas.js';
|
|
3
4
|
export interface EmbeddedImage {
|
|
4
5
|
bytes: Uint8Array;
|
|
5
6
|
mime: 'image/png' | 'image/jpeg';
|
|
@@ -89,13 +90,36 @@ export interface RenderCanvasToPdfInput {
|
|
|
89
90
|
calibration?: PdfExportCalibration;
|
|
90
91
|
/** TTF/OTF bytes of the primary font (Metropolis Bold in the apps). */
|
|
91
92
|
primaryFont: Uint8Array;
|
|
93
|
+
/**
|
|
94
|
+
* 'annotations' (default): every layer, mark and tile becomes a PDF
|
|
95
|
+
* annotation object — selectable, movable and deletable in Preview /
|
|
96
|
+
* Acrobat, with the element's exact drawing as its appearance. 'flatten':
|
|
97
|
+
* everything is appended to the page content stream and cannot be edited.
|
|
98
|
+
*/
|
|
99
|
+
mode?: 'annotations' | 'flatten';
|
|
100
|
+
}
|
|
101
|
+
export interface RenderPdfCanvasToPdfInput {
|
|
102
|
+
/** The PDF the file was uploaded from (`pdfCanvas.document.storagePath`). */
|
|
103
|
+
sourcePdf: Uint8Array;
|
|
104
|
+
/** The file-level record (`fileData.pdfCanvas`). */
|
|
105
|
+
pdfCanvas: PdfCanvasData;
|
|
106
|
+
/** Page docs by page index; a page without one is exported un-annotated. */
|
|
107
|
+
pageStates: Partial<Record<number, PdfCanvasPageState>>;
|
|
108
|
+
resolveTile: (ref: PlacedMeasurementRef) => ResolvedTileContent | undefined;
|
|
109
|
+
calibration?: PdfExportCalibration;
|
|
110
|
+
primaryFont: Uint8Array;
|
|
111
|
+
mode?: 'annotations' | 'flatten';
|
|
92
112
|
}
|
|
93
113
|
export interface RenderCanvasToPdfResult {
|
|
94
114
|
pdf: Uint8Array;
|
|
95
115
|
pageCount: number;
|
|
116
|
+
/** Annotations written across all pages (0 in flatten mode). */
|
|
117
|
+
annotationCount: number;
|
|
96
118
|
skipped: SkippedItem[];
|
|
97
119
|
}
|
|
98
120
|
export declare class PdfExportError extends Error {
|
|
99
|
-
readonly code: 'no-pdf-document' | 'page-count-mismatch' | 'page-geometry-mismatch'
|
|
121
|
+
readonly code: 'no-pdf-document' | 'page-count-mismatch' | 'page-geometry-mismatch'
|
|
122
|
+
/** The renderer was handed an encrypted PDF — run stripPdfEncryption first. */
|
|
123
|
+
| 'encrypted' | 'password-required' | 'password-incorrect' | 'unsupported' | 'corrupt';
|
|
100
124
|
constructor(code: PdfExportError['code'], message: string);
|
|
101
125
|
}
|
package/dist/exports.d.ts
CHANGED
|
@@ -6,6 +6,7 @@ export { useParseMeasurement } from './utils/useParseMeasurement.js';
|
|
|
6
6
|
export * from './types/firestore.js';
|
|
7
7
|
export * from './types/layout.js';
|
|
8
8
|
export * from './types/annotation.js';
|
|
9
|
+
export * from './types/pdfCanvas.js';
|
|
9
10
|
export { getToleranceColor, calculateDeviationPercentage, isWithinTolerance, generateToleranceGradient, createDefaultToleranceThresholds, DEFAULT_TOLERANCE_COLORS, type ToleranceThreshold, type ToleranceConfig, } from './utils/tolerance.js';
|
|
10
11
|
export { GeneralColors, SecondaryColors, FormColors, TileColors, FormulaColors, YellowColors, RedColors, GreenColors, tailwindColors, } from './theme/colors.js';
|
|
11
12
|
export { DEFAULT_GROUP_INDEX, isDefaultGroup, findDefaultGroup, isFormGroupCompleted, } from './utils/groups.js';
|
|
@@ -25,6 +26,7 @@ export { useAnnotationDoc, type UseAnnotationDocResult, } from './annotation/dat
|
|
|
25
26
|
export { useAnnotationList, type UseAnnotationListResult, } from './annotation/data/hooks/useAnnotationList.js';
|
|
26
27
|
export { useAnnotationMutations, type AnnotationMutations, } from './annotation/data/hooks/useAnnotationMutations.js';
|
|
27
28
|
export { useAnnotationCanvasDoc, type SaveStatus, type UseAnnotationCanvasDocOptions, type UseAnnotationCanvasDocResult, } from './annotation/data/hooks/useAnnotationCanvasDoc.js';
|
|
29
|
+
export { usePdfCanvasDoc, type UsePdfCanvasDocOptions, type UsePdfCanvasDocResult, } from './annotation/data/hooks/usePdfCanvasDoc.js';
|
|
28
30
|
export { hydrateCanvasState } from './annotation/data/canvasPersistence.js';
|
|
29
31
|
export { InMemoryAnnotationProvider } from './annotation/data/InMemoryAnnotationProvider.js';
|
|
30
32
|
export type { AnnotationCanvasHandle } from './annotation/canvas/useAnnotationCanvasState.js';
|
|
@@ -37,6 +39,7 @@ export { STAMP_TILE_SIZE, GROUP_HEADER_TILE_WIDTH, GROUP_HEADER_TILE_HEIGHT, GRO
|
|
|
37
39
|
export { GROUP_HEADER_STYLE, describeGroupHeader, groupHeaderSignature, type GroupHeaderBadge, type GroupHeaderDescriptor, } from './annotation/canvas/groupHeaderLayout.js';
|
|
38
40
|
export { createViewportApi, fitToScreen, fitRectToScreen, imageDocRect, panBy, zoomAt, DEFAULT_VIEWPORT, DEFAULT_ZOOM_LIMITS, type ViewportApi, type ViewportState, type ZoomLimits, } from './annotation/canvas/viewport.js';
|
|
39
41
|
export { DEFAULT_PDF_PAGE_GAP, DEFAULT_MIN_ZOOM, DEFAULT_MAX_ZOOM, makePdfDocumentId, createPdfDocument, pdfPageDocRects, pdfDocumentExtent, pdfFirstPageDocRect, computeZoomFloor, type PdfDocRect, } from './annotation/canvas/pdfDocument.js';
|
|
42
|
+
export { normalizePdfRotation, effectivePageRotation, pdfPageDisplaySize, pdfCanvasPageDocId, emptyPdfCanvasPageState, pdfCanvasPageDocument, pdfCanvasKnobsOf, pdfCanvasKnobsEqual, pageStateToCanvasState, canvasStateToPageState, rotatePointInPage, rotatePageState, rotatePdfCanvasPage, type PdfPageDisplaySize, type PdfRotationDelta, } from './annotation/canvas/pdfCanvasPages.js';
|
|
40
43
|
export { LEGACY_BACKGROUND_LAYER_ID, BACKGROUND_PLACEMENT_GAP_RATIO, backgroundLayersOf, backgroundLayerIsLocked, isBackgroundLayerLocked, defaultBackgroundLayerLocked, backgroundLayerDocRect, backgroundLayersUnionRect, placeNewBackgroundLayer, } from './annotation/canvas/backgroundLayers.js';
|
|
41
44
|
export { fileTileImageSource, expandFileTileToBackground, collapseBackgroundToFileTile, type FileTileImageSource, } from './annotation/canvas/fileTileSwap.js';
|
|
42
45
|
export { createPenTool, type PenToolOptions, } from './annotation/canvas/tools/penTool.js';
|
package/dist/exports.js
CHANGED
|
@@ -10,6 +10,7 @@ export { useParseMeasurement } from './utils/useParseMeasurement.js';
|
|
|
10
10
|
export * from './types/firestore.js';
|
|
11
11
|
export * from './types/layout.js';
|
|
12
12
|
export * from './types/annotation.js';
|
|
13
|
+
export * from './types/pdfCanvas.js';
|
|
13
14
|
export { getToleranceColor, calculateDeviationPercentage, isWithinTolerance, generateToleranceGradient, createDefaultToleranceThresholds, DEFAULT_TOLERANCE_COLORS, } from './utils/tolerance.js';
|
|
14
15
|
// Shared color palette (canonical source for both apps' brand colors).
|
|
15
16
|
export { GeneralColors, SecondaryColors, FormColors, TileColors, FormulaColors, YellowColors, RedColors, GreenColors, tailwindColors, } from './theme/colors.js';
|
|
@@ -37,12 +38,14 @@ export { useAnnotationDoc, } from './annotation/data/hooks/useAnnotationDoc.js';
|
|
|
37
38
|
export { useAnnotationList, } from './annotation/data/hooks/useAnnotationList.js';
|
|
38
39
|
export { useAnnotationMutations, } from './annotation/data/hooks/useAnnotationMutations.js';
|
|
39
40
|
export { useAnnotationCanvasDoc, } from './annotation/data/hooks/useAnnotationCanvasDoc.js';
|
|
41
|
+
export { usePdfCanvasDoc, } from './annotation/data/hooks/usePdfCanvasDoc.js';
|
|
40
42
|
export { hydrateCanvasState } from './annotation/data/canvasPersistence.js';
|
|
41
43
|
export { InMemoryAnnotationProvider } from './annotation/data/InMemoryAnnotationProvider.js';
|
|
42
44
|
export { STAMP_TILE_SIZE, GROUP_HEADER_TILE_WIDTH, GROUP_HEADER_TILE_HEIGHT, GROUP_HEADER_COLLAPSED_WIDTH, GROUP_HEADER_COLLAPSED_HEIGHT, GROUP_HEADER_DESIGN, groupHeaderBaseDims, DEFAULT_TILE_SCALE, TILE_SCALE_MIN, TILE_SCALE_MAX, clampTileScale, resolveTileScaleFactor, resolveHeaderTileScaleFactor, resolveFileTileScaleFactor, tileDocSizeForFactor, tileScaleFromDocSize, stampTileSize, stampTileDims, isUnassociatedStamp, isFileStamp, } from './annotation/canvas/stampLayout.js';
|
|
43
45
|
export { GROUP_HEADER_STYLE, describeGroupHeader, groupHeaderSignature, } from './annotation/canvas/groupHeaderLayout.js';
|
|
44
46
|
export { createViewportApi, fitToScreen, fitRectToScreen, imageDocRect, panBy, zoomAt, DEFAULT_VIEWPORT, DEFAULT_ZOOM_LIMITS, } from './annotation/canvas/viewport.js';
|
|
45
47
|
export { DEFAULT_PDF_PAGE_GAP, DEFAULT_MIN_ZOOM, DEFAULT_MAX_ZOOM, makePdfDocumentId, createPdfDocument, pdfPageDocRects, pdfDocumentExtent, pdfFirstPageDocRect, computeZoomFloor, } from './annotation/canvas/pdfDocument.js';
|
|
48
|
+
export { normalizePdfRotation, effectivePageRotation, pdfPageDisplaySize, pdfCanvasPageDocId, emptyPdfCanvasPageState, pdfCanvasPageDocument, pdfCanvasKnobsOf, pdfCanvasKnobsEqual, pageStateToCanvasState, canvasStateToPageState, rotatePointInPage, rotatePageState, rotatePdfCanvasPage, } from './annotation/canvas/pdfCanvasPages.js';
|
|
46
49
|
export { LEGACY_BACKGROUND_LAYER_ID, BACKGROUND_PLACEMENT_GAP_RATIO, backgroundLayersOf, backgroundLayerIsLocked, isBackgroundLayerLocked, defaultBackgroundLayerLocked, backgroundLayerDocRect, backgroundLayersUnionRect, placeNewBackgroundLayer, } from './annotation/canvas/backgroundLayers.js';
|
|
47
50
|
export { fileTileImageSource, expandFileTileToBackground, collapseBackgroundToFileTile, } from './annotation/canvas/fileTileSwap.js';
|
|
48
51
|
export { createPenTool, } from './annotation/canvas/tools/penTool.js';
|
package/dist/server.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ export { parseMeasurement } from './utils/parseMeasurement.js';
|
|
|
5
5
|
export * from './types/firestore.js';
|
|
6
6
|
export * from './types/layout.js';
|
|
7
7
|
export * from './types/annotation.js';
|
|
8
|
+
export * from './types/pdfCanvas.js';
|
|
9
|
+
export { normalizePdfRotation, effectivePageRotation, pdfPageDisplaySize, pdfCanvasPageDocId, pageStateToCanvasState, rotatePageState, type PdfPageDisplaySize, type PdfRotationDelta, } from './annotation/canvas/pdfCanvasPages.js';
|
|
8
10
|
export { getToleranceColor, getToleranceSecondaryColor, calculateDeviationPercentage, isWithinTolerance, generateToleranceGradient, createDefaultToleranceThresholds, DEFAULT_TOLERANCE_COLORS, DEFAULT_TOLERANCE_SECONDARY_COLORS, type ToleranceThreshold, type ToleranceConfig, } from './utils/tolerance.js';
|
|
9
11
|
export { DEFAULT_GROUP_INDEX, isDefaultGroup, findDefaultGroup, isFormGroupCompleted, } from './utils/groups.js';
|
|
10
12
|
export { ROLE_RANK, EMPTY_GRANTS, normalizeRole, roleAtLeast, effectiveRole, canView, canEdit, canManage, canManageOrg, isGuest, groupGrants, resolveAccess, type MaybeRole, type GroupedGrants, type ResolvedAccess, } from './utils/permissions.js';
|
package/dist/server.js
CHANGED
|
@@ -10,6 +10,8 @@ export { parseMeasurement } from './utils/parseMeasurement.js';
|
|
|
10
10
|
export * from './types/firestore.js';
|
|
11
11
|
export * from './types/layout.js';
|
|
12
12
|
export * from './types/annotation.js';
|
|
13
|
+
export * from './types/pdfCanvas.js';
|
|
14
|
+
export { normalizePdfRotation, effectivePageRotation, pdfPageDisplaySize, pdfCanvasPageDocId, pageStateToCanvasState, rotatePageState, } from './annotation/canvas/pdfCanvasPages.js';
|
|
13
15
|
export { getToleranceColor, getToleranceSecondaryColor, calculateDeviationPercentage, isWithinTolerance, generateToleranceGradient, createDefaultToleranceThresholds, DEFAULT_TOLERANCE_COLORS, DEFAULT_TOLERANCE_SECONDARY_COLORS, } from './utils/tolerance.js';
|
|
14
16
|
export { DEFAULT_GROUP_INDEX, isDefaultGroup, findDefaultGroup, isFormGroupCompleted, } from './utils/groups.js';
|
|
15
17
|
export { ROLE_RANK, EMPTY_GRANTS, normalizeRole, roleAtLeast, effectiveRole, canView, canEdit, canManage, canManageOrg, isGuest, groupGrants, resolveAccess, } from './utils/permissions.js';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { AnnotationCanvasState } from './annotation.js';
|
|
2
|
+
import type { PdfCanvasData } from './pdfCanvas.js';
|
|
2
3
|
import type { CalculatorUnit } from '../calculator/units.js';
|
|
3
4
|
interface FirestoreDoc {
|
|
4
5
|
id: string;
|
|
@@ -170,6 +171,7 @@ export interface SelectedTemplate extends FirestoreDoc {
|
|
|
170
171
|
export declare enum FileUploadType {
|
|
171
172
|
Annotation = "annotation",
|
|
172
173
|
Canvas = "canvas",
|
|
174
|
+
PdfCanvas = "pdfCanvas",
|
|
173
175
|
Template = "template",
|
|
174
176
|
Background = "background",
|
|
175
177
|
LayoutGroup = "layoutGroup",
|
|
@@ -186,6 +188,7 @@ export interface AnnotationFileData {
|
|
|
186
188
|
clientId: string;
|
|
187
189
|
seq: number;
|
|
188
190
|
};
|
|
191
|
+
pdfCanvas?: PdfCanvasData;
|
|
189
192
|
}
|
|
190
193
|
export interface CalculatorFileData {
|
|
191
194
|
templateId: string;
|
|
@@ -242,6 +245,9 @@ export type FileUpload = FileUploadBase & ({
|
|
|
242
245
|
} | {
|
|
243
246
|
type: FileUploadType.Canvas;
|
|
244
247
|
fileData: AnnotationFileData;
|
|
248
|
+
} | {
|
|
249
|
+
type: FileUploadType.PdfCanvas;
|
|
250
|
+
fileData: AnnotationFileData;
|
|
245
251
|
} | {
|
|
246
252
|
type: FileUploadType.Calculator;
|
|
247
253
|
fileData: CalculatorFileData;
|
package/dist/types/firestore.js
CHANGED
|
@@ -52,6 +52,11 @@ export var FileUploadType;
|
|
|
52
52
|
// v2 Skia photo-annotation canvas. Distinct from the legacy PSPDFKit
|
|
53
53
|
// `Annotation` docs so file-open routing sends it to the canvas editor.
|
|
54
54
|
FileUploadType["Canvas"] = "canvas";
|
|
55
|
+
// A PDF annotated one page at a time with the Skia canvas (see
|
|
56
|
+
// types/pdfCanvas.ts). Its PDF sits at `${folderPath}/file` like a legacy
|
|
57
|
+
// `Annotation` upload, so a client that predates the type still opens it in
|
|
58
|
+
// the Nutrient viewer instead of failing.
|
|
59
|
+
FileUploadType["PdfCanvas"] = "pdfCanvas";
|
|
55
60
|
FileUploadType["Template"] = "template";
|
|
56
61
|
FileUploadType["Background"] = "background";
|
|
57
62
|
FileUploadType["LayoutGroup"] = "layoutGroup";
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { AnnotationLayer, AnnotationShape, AnnotationStroke, PlacedMeasurementRef, PlaneCalibration } from './annotation.js';
|
|
2
|
+
export type PdfPageRotation = 0 | 90 | 180 | 270;
|
|
3
|
+
export interface PdfCanvasPage {
|
|
4
|
+
width: number;
|
|
5
|
+
height: number;
|
|
6
|
+
rotation: PdfPageRotation;
|
|
7
|
+
}
|
|
8
|
+
export interface PdfCanvasDocument {
|
|
9
|
+
storagePath: string;
|
|
10
|
+
fileName?: string;
|
|
11
|
+
pageCount: number;
|
|
12
|
+
pages: PdfCanvasPage[];
|
|
13
|
+
}
|
|
14
|
+
export interface PdfCanvasRev {
|
|
15
|
+
clientId: string;
|
|
16
|
+
seq: number;
|
|
17
|
+
}
|
|
18
|
+
export interface PdfCanvasData {
|
|
19
|
+
schemaVersion: 1;
|
|
20
|
+
document: PdfCanvasDocument;
|
|
21
|
+
tileScaleFactor?: number;
|
|
22
|
+
tileScaleFactorMobile?: number;
|
|
23
|
+
headerTileScaleFactor?: number;
|
|
24
|
+
headerTileScaleFactorMobile?: number;
|
|
25
|
+
tileDocSize?: number;
|
|
26
|
+
annotatedPages: number[];
|
|
27
|
+
}
|
|
28
|
+
export interface PdfCanvasPageState {
|
|
29
|
+
schemaVersion: 1;
|
|
30
|
+
pageIndex: number;
|
|
31
|
+
layers: AnnotationLayer[];
|
|
32
|
+
strokes: AnnotationStroke[];
|
|
33
|
+
shapes: AnnotationShape[];
|
|
34
|
+
placedMeasurements: PlacedMeasurementRef[];
|
|
35
|
+
planes?: PlaneCalibration[];
|
|
36
|
+
updatedAt: number;
|
|
37
|
+
rev?: PdfCanvasRev;
|
|
38
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Schema of a PDF CANVAS file (FileUploadType.PdfCanvas): a PDF annotated one
|
|
2
|
+
// page at a time with the Skia canvas. Distinct from a Canvas file carrying a
|
|
3
|
+
// `viewport.pdfDocument` filmstrip — there every page shares one doc space;
|
|
4
|
+
// here EVERY PAGE IS ITS OWN CANVAS whose doc space is that page's displayed
|
|
5
|
+
// extent in PDF points (origin top-left, y down), so the canvas engine needs no
|
|
6
|
+
// page concept at all: the editor mounts the current page's state and swaps it
|
|
7
|
+
// on a page turn.
|
|
8
|
+
//
|
|
9
|
+
// Storage split (see pdfCanvasPages.ts for the mapping helpers):
|
|
10
|
+
// - `fileData.pdfCanvas` on the file doc: the small file-level record —
|
|
11
|
+
// which PDF, page geometry + user rotations, shared tile-scale knobs, and
|
|
12
|
+
// which pages have been annotated.
|
|
13
|
+
// - `files/{fileId}/pages/{pageIndex}`: one doc per annotated page holding
|
|
14
|
+
// that page's elements. Sharded so a heavy set never approaches the 1 MiB
|
|
15
|
+
// doc limit, a save rewrites one page, and a listener watches one page.
|
|
16
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reekon-tools/boldr-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.24.0",
|
|
4
4
|
"description": "Shared utilities for formulas and measurement conversion used in Reekon apps",
|
|
5
5
|
"author": "REEKON Tools",
|
|
6
6
|
"license": "MIT",
|
|
@@ -52,7 +52,9 @@
|
|
|
52
52
|
"pdf-lib": "1.17.1",
|
|
53
53
|
"zod": "^4.4.3"
|
|
54
54
|
},
|
|
55
|
+
"//peerDependencies-embedpdf": "OPTIONAL, server only: `@embedpdf/pdfium` is imported lazily by exactly one module (export/pdf/decrypt.ts, reached through the ./server entry) to strip PDF encryption before pdf-lib appends to a page. The apps never resolve it.",
|
|
55
56
|
"peerDependencies": {
|
|
57
|
+
"@embedpdf/pdfium": ">=2.15.0",
|
|
56
58
|
"@shopify/react-native-skia": ">=2.5.0",
|
|
57
59
|
"react": "^18.0.0 || ^19.0.0",
|
|
58
60
|
"react-native": ">=0.74.0",
|
|
@@ -60,6 +62,9 @@
|
|
|
60
62
|
"react-native-reanimated": ">=3.0.0"
|
|
61
63
|
},
|
|
62
64
|
"peerDependenciesMeta": {
|
|
65
|
+
"@embedpdf/pdfium": {
|
|
66
|
+
"optional": true
|
|
67
|
+
},
|
|
63
68
|
"react-native": {
|
|
64
69
|
"optional": true
|
|
65
70
|
},
|