@printwithsynergy/lens-pdf 0.3.0-beta.81
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/LICENSE +661 -0
- package/README.md +344 -0
- package/dist/browser/codexOverlay.d.ts +109 -0
- package/dist/browser/codexOverlay.d.ts.map +1 -0
- package/dist/browser/codexOverlay.js +256 -0
- package/dist/browser/codexOverlay.js.map +1 -0
- package/dist/browser/constants.d.ts +13 -0
- package/dist/browser/constants.d.ts.map +1 -0
- package/dist/browser/constants.js +13 -0
- package/dist/browser/constants.js.map +1 -0
- package/dist/browser/index.d.ts +211 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +1190 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/browser/pantone-gold.d.ts +59 -0
- package/dist/browser/pantone-gold.d.ts.map +1 -0
- package/dist/browser/pantone-gold.js +237 -0
- package/dist/browser/pantone-gold.js.map +1 -0
- package/dist/components/AnnotationCanvas.d.ts +27 -0
- package/dist/components/AnnotationCanvas.d.ts.map +1 -0
- package/dist/components/AnnotationCanvas.js +401 -0
- package/dist/components/AnnotationCanvas.js.map +1 -0
- package/dist/components/AnnotationNotesPanel.d.ts +15 -0
- package/dist/components/AnnotationNotesPanel.d.ts.map +1 -0
- package/dist/components/AnnotationNotesPanel.js +235 -0
- package/dist/components/AnnotationNotesPanel.js.map +1 -0
- package/dist/components/AnnotationThread.d.ts +18 -0
- package/dist/components/AnnotationThread.d.ts.map +1 -0
- package/dist/components/AnnotationThread.js +163 -0
- package/dist/components/AnnotationThread.js.map +1 -0
- package/dist/components/AnnotationToolbar.d.ts +39 -0
- package/dist/components/AnnotationToolbar.d.ts.map +1 -0
- package/dist/components/AnnotationToolbar.js +258 -0
- package/dist/components/AnnotationToolbar.js.map +1 -0
- package/dist/components/BoxOverlay.d.ts +20 -0
- package/dist/components/BoxOverlay.d.ts.map +1 -0
- package/dist/components/BoxOverlay.js +107 -0
- package/dist/components/BoxOverlay.js.map +1 -0
- package/dist/components/ColorPickerTool.d.ts +11 -0
- package/dist/components/ColorPickerTool.d.ts.map +1 -0
- package/dist/components/ColorPickerTool.js +220 -0
- package/dist/components/ColorPickerTool.js.map +1 -0
- package/dist/components/DensitometerTool.d.ts +25 -0
- package/dist/components/DensitometerTool.d.ts.map +1 -0
- package/dist/components/DensitometerTool.js +246 -0
- package/dist/components/DensitometerTool.js.map +1 -0
- package/dist/components/DielineInfoPanel.d.ts +27 -0
- package/dist/components/DielineInfoPanel.d.ts.map +1 -0
- package/dist/components/DielineInfoPanel.js +23 -0
- package/dist/components/DielineInfoPanel.js.map +1 -0
- package/dist/components/DielineOverlay.d.ts +10 -0
- package/dist/components/DielineOverlay.d.ts.map +1 -0
- package/dist/components/DielineOverlay.js +57 -0
- package/dist/components/DielineOverlay.js.map +1 -0
- package/dist/components/FindingsSidebar.d.ts +50 -0
- package/dist/components/FindingsSidebar.d.ts.map +1 -0
- package/dist/components/FindingsSidebar.js +78 -0
- package/dist/components/FindingsSidebar.js.map +1 -0
- package/dist/components/LayerCanvas.d.ts +30 -0
- package/dist/components/LayerCanvas.d.ts.map +1 -0
- package/dist/components/LayerCanvas.js +84 -0
- package/dist/components/LayerCanvas.js.map +1 -0
- package/dist/components/LayerPanel.d.ts +9 -0
- package/dist/components/LayerPanel.d.ts.map +1 -0
- package/dist/components/LayerPanel.js +144 -0
- package/dist/components/LayerPanel.js.map +1 -0
- package/dist/components/LensPDF.d.ts +61 -0
- package/dist/components/LensPDF.d.ts.map +1 -0
- package/dist/components/LensPDF.js +49 -0
- package/dist/components/LensPDF.js.map +1 -0
- package/dist/components/LensPDFDemo.d.ts +160 -0
- package/dist/components/LensPDFDemo.d.ts.map +1 -0
- package/dist/components/LensPDFDemo.js +1060 -0
- package/dist/components/LensPDFDemo.js.map +1 -0
- package/dist/components/LensPDFDemo.styles.d.ts +38 -0
- package/dist/components/LensPDFDemo.styles.d.ts.map +1 -0
- package/dist/components/LensPDFDemo.styles.js +282 -0
- package/dist/components/LensPDFDemo.styles.js.map +1 -0
- package/dist/components/LensPDFViewer.d.ts +79 -0
- package/dist/components/LensPDFViewer.d.ts.map +1 -0
- package/dist/components/LensPDFViewer.js +254 -0
- package/dist/components/LensPDFViewer.js.map +1 -0
- package/dist/components/MeasureTool.d.ts +16 -0
- package/dist/components/MeasureTool.d.ts.map +1 -0
- package/dist/components/MeasureTool.js +137 -0
- package/dist/components/MeasureTool.js.map +1 -0
- package/dist/components/MobileBottomSheet.d.ts +12 -0
- package/dist/components/MobileBottomSheet.d.ts.map +1 -0
- package/dist/components/MobileBottomSheet.js +113 -0
- package/dist/components/MobileBottomSheet.js.map +1 -0
- package/dist/components/MobileDrawer.d.ts +31 -0
- package/dist/components/MobileDrawer.d.ts.map +1 -0
- package/dist/components/MobileDrawer.js +67 -0
- package/dist/components/MobileDrawer.js.map +1 -0
- package/dist/components/PageCanvas.d.ts +33 -0
- package/dist/components/PageCanvas.d.ts.map +1 -0
- package/dist/components/PageCanvas.js +385 -0
- package/dist/components/PageCanvas.js.map +1 -0
- package/dist/components/PageNavigator.d.ts +18 -0
- package/dist/components/PageNavigator.d.ts.map +1 -0
- package/dist/components/PageNavigator.js +44 -0
- package/dist/components/PageNavigator.js.map +1 -0
- package/dist/components/SeparationCanvas.d.ts +12 -0
- package/dist/components/SeparationCanvas.d.ts.map +1 -0
- package/dist/components/SeparationCanvas.js +174 -0
- package/dist/components/SeparationCanvas.js.map +1 -0
- package/dist/components/TACHeatmapOverlay.d.ts +17 -0
- package/dist/components/TACHeatmapOverlay.d.ts.map +1 -0
- package/dist/components/TACHeatmapOverlay.js +119 -0
- package/dist/components/TACHeatmapOverlay.js.map +1 -0
- package/dist/components/ZoomControls.d.ts +11 -0
- package/dist/components/ZoomControls.d.ts.map +1 -0
- package/dist/components/ZoomControls.js +26 -0
- package/dist/components/ZoomControls.js.map +1 -0
- package/dist/components/defaultShellPlugins.d.ts +3 -0
- package/dist/components/defaultShellPlugins.d.ts.map +1 -0
- package/dist/components/defaultShellPlugins.js +273 -0
- package/dist/components/defaultShellPlugins.js.map +1 -0
- package/dist/components/index.d.ts +32 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +32 -0
- package/dist/components/index.js.map +1 -0
- package/dist/components/presets.d.ts +8 -0
- package/dist/components/presets.d.ts.map +1 -0
- package/dist/components/presets.js +14 -0
- package/dist/components/presets.js.map +1 -0
- package/dist/components/shellPlugins.d.ts +105 -0
- package/dist/components/shellPlugins.d.ts.map +1 -0
- package/dist/components/shellPlugins.js +52 -0
- package/dist/components/shellPlugins.js.map +1 -0
- package/dist/components/useIsMobile.d.ts +16 -0
- package/dist/components/useIsMobile.d.ts.map +1 -0
- package/dist/components/useIsMobile.js +30 -0
- package/dist/components/useIsMobile.js.map +1 -0
- package/dist/fallback-pdfjs/index.d.ts +60 -0
- package/dist/fallback-pdfjs/index.d.ts.map +1 -0
- package/dist/fallback-pdfjs/index.js +163 -0
- package/dist/fallback-pdfjs/index.js.map +1 -0
- package/dist/host/LensPDFProvider.d.ts +36 -0
- package/dist/host/LensPDFProvider.d.ts.map +1 -0
- package/dist/host/LensPDFProvider.js +12 -0
- package/dist/host/LensPDFProvider.js.map +1 -0
- package/dist/host/index.d.ts +167 -0
- package/dist/host/index.d.ts.map +1 -0
- package/dist/host/index.js +173 -0
- package/dist/host/index.js.map +1 -0
- package/dist/host/pdfFallback.d.ts +50 -0
- package/dist/host/pdfFallback.d.ts.map +1 -0
- package/dist/host/pdfFallback.js +171 -0
- package/dist/host/pdfFallback.js.map +1 -0
- package/dist/host/pdfValidation.d.ts +45 -0
- package/dist/host/pdfValidation.d.ts.map +1 -0
- package/dist/host/pdfValidation.js +78 -0
- package/dist/host/pdfValidation.js.map +1 -0
- package/dist/host/shareLink.d.ts +80 -0
- package/dist/host/shareLink.d.ts.map +1 -0
- package/dist/host/shareLink.js +114 -0
- package/dist/host/shareLink.js.map +1 -0
- package/dist/host/useLensPDF.d.ts +73 -0
- package/dist/host/useLensPDF.d.ts.map +1 -0
- package/dist/host/useLensPDF.js +213 -0
- package/dist/host/useLensPDF.js.map +1 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/plugin/context.d.ts +70 -0
- package/dist/plugin/context.d.ts.map +1 -0
- package/dist/plugin/context.js +16 -0
- package/dist/plugin/context.js.map +1 -0
- package/dist/plugin/findings-location.d.ts +53 -0
- package/dist/plugin/findings-location.d.ts.map +1 -0
- package/dist/plugin/findings-location.js +72 -0
- package/dist/plugin/findings-location.js.map +1 -0
- package/dist/plugin/index.d.ts +19 -0
- package/dist/plugin/index.d.ts.map +1 -0
- package/dist/plugin/index.js +16 -0
- package/dist/plugin/index.js.map +1 -0
- package/dist/plugin/registry.d.ts +61 -0
- package/dist/plugin/registry.d.ts.map +1 -0
- package/dist/plugin/registry.js +102 -0
- package/dist/plugin/registry.js.map +1 -0
- package/dist/plugin/services.d.ts +380 -0
- package/dist/plugin/services.d.ts.map +1 -0
- package/dist/plugin/services.js +104 -0
- package/dist/plugin/services.js.map +1 -0
- package/dist/plugin/types.d.ts +198 -0
- package/dist/plugin/types.d.ts.map +1 -0
- package/dist/plugin/types.js +24 -0
- package/dist/plugin/types.js.map +1 -0
- package/dist/types/index.d.ts +191 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +95 -0
- package/dist/types/index.js.map +1 -0
- package/dist/units/index.d.ts +64 -0
- package/dist/units/index.d.ts.map +1 -0
- package/dist/units/index.js +98 -0
- package/dist/units/index.js.map +1 -0
- package/docs/architecture.md +90 -0
- package/docs/components.md +569 -0
- package/docs/contributing.md +78 -0
- package/docs/fallback.md +174 -0
- package/docs/lens-pdf-viewer.md +128 -0
- package/docs/licensing.md +78 -0
- package/docs/measurement-units.md +87 -0
- package/docs/plugins.md +256 -0
- package/docs/security.md +69 -0
- package/docs/server.md +212 -0
- package/docs/services.md +210 -0
- package/docs/share-links.md +111 -0
- package/docs/theming.md +164 -0
- package/docs/validation.md +83 -0
- package/package.json +139 -0
package/README.md
ADDED
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: "Overview"
|
|
3
|
+
description: "Host-agnostic OSS PDF viewer core for React 19. A plugin-driven canvas viewer with overlay, panel, and toolbar slots. AGPL-3.0-or-later."
|
|
4
|
+
group: "Getting started"
|
|
5
|
+
order: 1
|
|
6
|
+
slug: "overview"
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# LensPDF
|
|
10
|
+
|
|
11
|
+
[](https://github.com/Printwithsynergy/lens-pdf/actions/workflows/ci.yml)
|
|
12
|
+
[](./LICENSE)
|
|
13
|
+
[](https://react.dev/)
|
|
14
|
+
|
|
15
|
+
OSS PDF viewer core. A plugin-driven canvas viewer with overlay, panel, and
|
|
16
|
+
toolbar slots, built around React 19. Host-agnostic: the viewer never
|
|
17
|
+
imports a SaaS, never hardcodes a backend route, and self-hides any tool
|
|
18
|
+
whose backing service the host hasn't wired. AGPL-3.0-or-later.
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
LensPDF is published to the public **npm registry** under the
|
|
23
|
+
`@printwithsynergy` scope.
|
|
24
|
+
|
|
25
|
+
```sh
|
|
26
|
+
# stable
|
|
27
|
+
npm install @printwithsynergy/lens-pdf
|
|
28
|
+
|
|
29
|
+
# pre-release (current)
|
|
30
|
+
npm install @printwithsynergy/lens-pdf@beta
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Peer dependencies you provide in your host app:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
npm install react react-dom
|
|
37
|
+
# Optional — only if you mount AnnotationCanvas / AnnotationThread:
|
|
38
|
+
npm install fabric
|
|
39
|
+
# Optional — only if you pass a `codex` client for Ghostscript-accurate
|
|
40
|
+
# separations / TAC / layers:
|
|
41
|
+
npm install @printwithsynergy/codex-client
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Requires `react@^19` and `react-dom@^19`. `fabric@^7` is an optional peer
|
|
45
|
+
used by the annotation components. `@printwithsynergy/codex-client@^1.8.1`
|
|
46
|
+
is an optional peer used by the codex accuracy overlay — hosts that
|
|
47
|
+
never pass the `codex` prop don't need to install it. `pdfjs-dist@^4`
|
|
48
|
+
is a regular dependency — it comes along automatically and powers the
|
|
49
|
+
`createBrowserViewerServices` factory exposed at `/browser`. The package
|
|
50
|
+
ships ESM only.
|
|
51
|
+
|
|
52
|
+
## Quick start — pick your tier
|
|
53
|
+
|
|
54
|
+
LensPDF ships five integration levels. Start with Tier 1 and drop
|
|
55
|
+
down only when you need more control.
|
|
56
|
+
|
|
57
|
+
### Tier 1 — Drop-in production viewer (~3 lines)
|
|
58
|
+
|
|
59
|
+
`<LensPDF>` is the recommended single-component entry point. One
|
|
60
|
+
mount, every viewer-only feature wired to pdf.js out of the box:
|
|
61
|
+
|
|
62
|
+
- **Page raster** with a multi-DPI tile cache so zoom never
|
|
63
|
+
degrades the image.
|
|
64
|
+
- **Color picker** — RGB readout plus a per-ink breakdown (CMYK
|
|
65
|
+
+ any spot inks the PDF declares).
|
|
66
|
+
- **Densitometer** — per-channel coverage and TAC limit.
|
|
67
|
+
- **TAC heatmap** — process CMYK plus every detected spot ink
|
|
68
|
+
summed and visualised.
|
|
69
|
+
- **Per-ink separations** — toggle CMYK and any spot plates
|
|
70
|
+
on / off (defaults to all-on like Output Preview).
|
|
71
|
+
- **Layers** — OCG list with per-layer visibility.
|
|
72
|
+
- **Annotation toolbar / canvas / thread** — pen, arrow, rect,
|
|
73
|
+
ellipse, text, highlight, sticky note, all in-memory.
|
|
74
|
+
- **Mobile** — tools collapse into a left-anchored slide-in
|
|
75
|
+
drawer; readouts swap to bottom sheets so they stay legible.
|
|
76
|
+
|
|
77
|
+
```tsx
|
|
78
|
+
import { LensPDF } from "@printwithsynergy/lens-pdf";
|
|
79
|
+
import pdfWorkerSrc from "pdfjs-dist/build/pdf.worker.mjs?url";
|
|
80
|
+
|
|
81
|
+
export function ProofPage() {
|
|
82
|
+
return <LensPDF pdfUrl="/proofs/abc.pdf" workerSrc={pdfWorkerSrc} />;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
Hosts with a preflight engine plug findings + dieline + box overlays
|
|
87
|
+
in directly:
|
|
88
|
+
|
|
89
|
+
```tsx
|
|
90
|
+
<LensPDF
|
|
91
|
+
pdfUrl="/proofs/abc.pdf"
|
|
92
|
+
workerSrc={pdfWorkerSrc}
|
|
93
|
+
items={findings} // OverlayItem[] — error / warning / advisory bboxes
|
|
94
|
+
selectedItem={selected}
|
|
95
|
+
onItemSelect={setSelected}
|
|
96
|
+
dieline={dielineForCurrentPage}
|
|
97
|
+
showBoxOverlays // trim / bleed / crop popovers
|
|
98
|
+
cropToTrim // clip the canvas to TrimBox
|
|
99
|
+
tools={["color-picker", "densitometer", "annotate", "tac-heatmap"]}
|
|
100
|
+
onPageChange={setCurrentPage}
|
|
101
|
+
tokens={{ accent: "#e50c6a" }}
|
|
102
|
+
brand="MyApp"
|
|
103
|
+
brandLogoUrl="/logo.svg"
|
|
104
|
+
/>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
No backend required for the viewer side. Server-only features (HTML /
|
|
108
|
+
PDF report exports, ICC-correct preflight separations, server-
|
|
109
|
+
persisted annotations) self-hide because their dedicated services are
|
|
110
|
+
intentionally `markUnwired`. Hosts with a backend pass `services` to
|
|
111
|
+
override the in-browser ones.
|
|
112
|
+
|
|
113
|
+
### Tier 1b — Demo / showcase viewer
|
|
114
|
+
|
|
115
|
+
Same component, with an upload bar + drag-drop + URL paste — useful
|
|
116
|
+
for marketing pages and internal sandboxes where users bring their
|
|
117
|
+
own files.
|
|
118
|
+
|
|
119
|
+
```tsx
|
|
120
|
+
import { LensPDFDemo } from "@printwithsynergy/lens-pdf";
|
|
121
|
+
|
|
122
|
+
export function DemoPage() {
|
|
123
|
+
return <LensPDFDemo brand="MyApp" brandLogoUrl="/logo.svg" />;
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Tier 2 — One-liner viewer (~5 lines)
|
|
128
|
+
|
|
129
|
+
`<LensPDFViewer>` auto-discovers pages, layers, dimensions. Ships
|
|
130
|
+
a responsive toolbar with zoom, layers, color picker, and measure.
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { LensPDFViewer } from "@printwithsynergy/lens-pdf/components";
|
|
134
|
+
|
|
135
|
+
export function MyViewer() {
|
|
136
|
+
return <LensPDFViewer pdfUrl="https://cdn.example.com/proof.pdf" />;
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
Slot props (`header`, `sidebar`, `footer`) let you replace regions
|
|
141
|
+
without losing the rest of the viewer:
|
|
142
|
+
|
|
143
|
+
```tsx
|
|
144
|
+
<LensPDFViewer
|
|
145
|
+
pdfUrl={url}
|
|
146
|
+
header={(state) => <MyToolbar zoom={state.zoom} setZoom={state.setZoom} />}
|
|
147
|
+
footer={<p>Custom footer</p>}
|
|
148
|
+
/>
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Tier 3 — Hook + Provider (~20 lines)
|
|
152
|
+
|
|
153
|
+
`useLensPDF()` manages all state; `<LensPDFProvider>` mounts both
|
|
154
|
+
contexts. Build any layout you want on top.
|
|
155
|
+
|
|
156
|
+
```tsx
|
|
157
|
+
import { useLensPDF, LensPDFProvider } from "@printwithsynergy/lens-pdf/host";
|
|
158
|
+
import { PageCanvas } from "@printwithsynergy/lens-pdf/components";
|
|
159
|
+
|
|
160
|
+
export function CustomViewer({ url }: { url: string }) {
|
|
161
|
+
const viewer = useLensPDF(url, { tokens: { accent: "#e50c6a" } });
|
|
162
|
+
|
|
163
|
+
return (
|
|
164
|
+
<LensPDFProvider value={viewer}>
|
|
165
|
+
<PageCanvas jobId="demo" page={viewer.currentPageInfo} zoom={viewer.zoom} items={[]} selectedItem={null} onItemClick={() => {}} />
|
|
166
|
+
</LensPDFProvider>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Tier 4 — Full custom composition
|
|
172
|
+
|
|
173
|
+
Wire `ViewerHostContext` + `ViewerServicesContext` yourself. Every
|
|
174
|
+
component (`PageCanvas`, `LayerPanel`, `MeasureTool`, etc.) is
|
|
175
|
+
exported and unchanged.
|
|
176
|
+
|
|
177
|
+
### Shareable links
|
|
178
|
+
|
|
179
|
+
Generate URLs that open the viewer with a specific PDF and settings:
|
|
180
|
+
|
|
181
|
+
```ts
|
|
182
|
+
import { generateShareLink, parseShareParams } from "@printwithsynergy/lens-pdf/host";
|
|
183
|
+
|
|
184
|
+
const link = generateShareLink({
|
|
185
|
+
baseUrl: "https://lenspdf.com/demo",
|
|
186
|
+
pdfUrl: "https://cdn.example.com/proof.pdf",
|
|
187
|
+
fullscreen: true,
|
|
188
|
+
zoom: 150,
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// On the demo page:
|
|
192
|
+
const params = parseShareParams(new URLSearchParams(window.location.search));
|
|
193
|
+
// → { pdfUrl: "https://...", fullscreen: true, zoom: 150 }
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
### PDF validation
|
|
197
|
+
|
|
198
|
+
Client-side checks (magic bytes, MIME, size) are built in:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
import { validatePdfFile, validatePdfUrl } from "@printwithsynergy/lens-pdf/host";
|
|
202
|
+
|
|
203
|
+
const result = await validatePdfFile(file); // { valid: true } or { valid: false, error: "..." }
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Browser-only services (full feature surface, no backend)
|
|
207
|
+
|
|
208
|
+
`createBrowserViewerServices` returns a complete `ViewerServices`
|
|
209
|
+
backed by pdf.js — every viewer-only feature works on any PDF the
|
|
210
|
+
browser can fetch:
|
|
211
|
+
|
|
212
|
+
```tsx
|
|
213
|
+
import { createBrowserViewerServices } from "@printwithsynergy/lens-pdf/browser";
|
|
214
|
+
import { ViewerServicesContext, ViewerHostContext } from "@printwithsynergy/lens-pdf/host";
|
|
215
|
+
|
|
216
|
+
const services = createBrowserViewerServices({ pdfUrl: "/proof.pdf" });
|
|
217
|
+
|
|
218
|
+
<ViewerHostContext.Provider value={{ apiBase: "", jobApiBase: "", readOnly: false }}>
|
|
219
|
+
<ViewerServicesContext.Provider value={services}>
|
|
220
|
+
<PageCanvas ... />
|
|
221
|
+
<SeparationCanvas ... />
|
|
222
|
+
<TACHeatmapOverlay ... />
|
|
223
|
+
{/* etc. */}
|
|
224
|
+
</ViewerServicesContext.Provider>
|
|
225
|
+
</ViewerHostContext.Provider>;
|
|
226
|
+
|
|
227
|
+
services.dispose(); // free blob URLs / pdf.js doc on unmount
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
CMYK / TAC are RGB-derived approximations when no backend is wired.
|
|
231
|
+
Spot inks are detected by scanning raw PDF bytes for `/Separation`
|
|
232
|
+
and `/DeviceN` colour spaces; each detected spot's coverage is
|
|
233
|
+
estimated from its alternate-RGB direction. Good for visual
|
|
234
|
+
showcase and casual review, **not** press-grade. For ICC-correct
|
|
235
|
+
readings deploy the optional reference server below and pass its
|
|
236
|
+
`services` overrides — the components automatically swap from the
|
|
237
|
+
browser approximation to ICC-derived data with no markup change.
|
|
238
|
+
|
|
239
|
+
## Findings + dieline (0.3.0-beta.71 +)
|
|
240
|
+
|
|
241
|
+
Two built-in components for adapter authors (lint-pdf, callas
|
|
242
|
+
pdfToolbox, PitStop, Acrobat, custom rule engines) mapping their
|
|
243
|
+
preflight findings into Lens overlays:
|
|
244
|
+
|
|
245
|
+
- **`FindingsSidebar`** — vertical sidebar that splits items into
|
|
246
|
+
collapsible **Located in viewer** (clickable, draws boxes/numbers
|
|
247
|
+
on the canvas) and **Informational** (no bbox, surfaced as static
|
|
248
|
+
rows). Severity-filter pills along the top.
|
|
249
|
+
- **`DielineInfoPanel`** — info card showing source / spot name /
|
|
250
|
+
confidence + per-region size (mm + inches) from a
|
|
251
|
+
`DielineResult`. Pairs with the canvas-side dieline bbox that
|
|
252
|
+
`BoxOverlay` now draws automatically when the same prop is
|
|
253
|
+
passed to `<LensPDF dieline={...}>`.
|
|
254
|
+
|
|
255
|
+
Plus two helpers exported from `@printwithsynergy/lens-pdf/plugin`:
|
|
256
|
+
|
|
257
|
+
- **`hasViewerLocation(item)`** — true when the item has a bbox /
|
|
258
|
+
point / regions. Same predicate the canvas uses internally.
|
|
259
|
+
- **`splitFindingsByLocation(items)`** — returns
|
|
260
|
+
`{located, informational}` preserving order in each bucket.
|
|
261
|
+
|
|
262
|
+
```tsx
|
|
263
|
+
import {
|
|
264
|
+
LensPDF,
|
|
265
|
+
FindingsSidebar,
|
|
266
|
+
DielineInfoPanel,
|
|
267
|
+
} from "@printwithsynergy/lens-pdf";
|
|
268
|
+
|
|
269
|
+
<div className="flex h-full w-full">
|
|
270
|
+
<FindingsSidebar items={overlayItems} onSelect={setSelected} />
|
|
271
|
+
<LensPDF
|
|
272
|
+
items={overlayItems}
|
|
273
|
+
selectedItem={selected}
|
|
274
|
+
onItemSelect={setSelected}
|
|
275
|
+
dieline={dielineResult}
|
|
276
|
+
/>
|
|
277
|
+
<DielineInfoPanel dieline={dielineResult} />
|
|
278
|
+
</div>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
`FindingsSidebar` + `DielineInfoPanel` are no-ops when their data
|
|
282
|
+
prop is empty/null so hosts mount them unconditionally — they only
|
|
283
|
+
render once real data arrives. Theming honours Lens's brand-* /
|
|
284
|
+
slate-* tokens.
|
|
285
|
+
|
|
286
|
+
## Demo
|
|
287
|
+
|
|
288
|
+
Want to see the hide-on-unwired contract in action without setting up your own
|
|
289
|
+
host? `demo/` is a tiny Vite app that flips between empty / pdf.js-fallback /
|
|
290
|
+
fully-mocked contexts:
|
|
291
|
+
|
|
292
|
+
```sh
|
|
293
|
+
cd demo && npm install && npm run dev
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
See [demo/README.md](./demo/README.md) for the smoke-check checklist.
|
|
297
|
+
|
|
298
|
+
## Optional reference server
|
|
299
|
+
|
|
300
|
+
For **press-grade ICC-correct** ink separations, densitometer readings,
|
|
301
|
+
and TAC heatmap (the browser services use an RGB→CMYK approximation —
|
|
302
|
+
fine for showcase, not for prepress sign-off), deploy the small
|
|
303
|
+
Node + Ghostscript service in [`server/`](./server). Wire its
|
|
304
|
+
endpoints into your `ViewerServices` and the corresponding components
|
|
305
|
+
swap from the browser approximation to ICC-derived data.
|
|
306
|
+
|
|
307
|
+
```sh
|
|
308
|
+
cd server && docker build -t lens-pdf-server .
|
|
309
|
+
docker run -p 3000:3000 -v lens-jobs:/var/lib/lens-pdf/jobs lens-pdf-server
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
See [docs/server.md](./docs/server.md) for the HTTP contract,
|
|
313
|
+
deployment notes, and security caveats.
|
|
314
|
+
|
|
315
|
+
## Documentation
|
|
316
|
+
|
|
317
|
+
| Topic | Doc |
|
|
318
|
+
| --- | --- |
|
|
319
|
+
| The one-line `<LensPDFViewer>` composition | [docs/lens-pdf-viewer.md](./docs/lens-pdf-viewer.md) |
|
|
320
|
+
| How the contexts, components, and plugins fit together | [docs/architecture.md](./docs/architecture.md) |
|
|
321
|
+
| Wiring `ViewerServices` (page images, layers, separations, TAC, color, densitometer, annotations, reports) | [docs/services.md](./docs/services.md) |
|
|
322
|
+
| Capability detection, debug logging, and the in-browser PDF fallback | [docs/fallback.md](./docs/fallback.md) |
|
|
323
|
+
| Optional Node + Ghostscript backend for preflight-grade tools | [docs/server.md](./docs/server.md) |
|
|
324
|
+
| Per-component props and usage | [docs/components.md](./docs/components.md) |
|
|
325
|
+
| Plugin slots, registration, and the `replaces` mechanism | [docs/plugins.md](./docs/plugins.md) |
|
|
326
|
+
| Built-in `MeasurementUnit`s + custom-unit Protocol | [docs/measurement-units.md](./docs/measurement-units.md) |
|
|
327
|
+
| Theme tokens, i18n, telemetry, read-only mode | [docs/theming.md](./docs/theming.md) |
|
|
328
|
+
| Shareable viewer links (`generateShareLink`, `parseShareParams`) | [docs/share-links.md](./docs/share-links.md) |
|
|
329
|
+
| Client-side PDF validation (`validatePdfFile`, `validatePdfUrl`) | [docs/validation.md](./docs/validation.md) |
|
|
330
|
+
| Boundary rule, provenance, contributing | [docs/contributing.md](./docs/contributing.md) |
|
|
331
|
+
|
|
332
|
+
## Community
|
|
333
|
+
|
|
334
|
+
- [CHANGELOG](./CHANGELOG.md) — release notes (Keep-a-Changelog format).
|
|
335
|
+
- [CONTRIBUTING](./CONTRIBUTING.md) — quick-start; the full guide is in [docs/contributing.md](./docs/contributing.md).
|
|
336
|
+
- [CODE_OF_CONDUCT](./CODE_OF_CONDUCT.md) — Contributor Covenant 2.1.
|
|
337
|
+
- [SECURITY](./SECURITY.md) — vulnerability disclosure process. **Don't open public issues for security problems.**
|
|
338
|
+
|
|
339
|
+
## License
|
|
340
|
+
|
|
341
|
+
LensPDF is licensed under the GNU Affero General Public License v3.0 or
|
|
342
|
+
later (AGPL-3.0-or-later). See [`LICENSE`](./LICENSE) for the full text.
|
|
343
|
+
|
|
344
|
+
Copyright (C) 2026 Think Neverland LLC.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Codex accuracy overlay for `<LensPDFDemo>`.
|
|
3
|
+
*
|
|
4
|
+
* When a host passes a `codex` client, `LensPDFDemo` fires
|
|
5
|
+
* `extractStream` in the background. This module wraps the codex
|
|
6
|
+
* render APIs (renderSeparations, renderHeatmap, renderLayer) into
|
|
7
|
+
* the `ViewerServices` slot interface so the viewer can swap in
|
|
8
|
+
* Ghostscript-accurate renders silently once they arrive.
|
|
9
|
+
*
|
|
10
|
+
* This module has **no import of `@printwithsynergy/codex-client`**.
|
|
11
|
+
* It defines a minimal structural interface — any object whose shape
|
|
12
|
+
* matches `MinimalCodexClient` (including `HttpClient` from
|
|
13
|
+
* `@printwithsynergy/codex-client`) satisfies it.
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
import type { SeparationService, LayerService, TACHeatmapService } from "../plugin/services";
|
|
18
|
+
import type { DetectedInk } from "./index";
|
|
19
|
+
/**
|
|
20
|
+
* Minimal subset of `@printwithsynergy/codex-client`'s `HttpClient`
|
|
21
|
+
* that `LensPDFDemo` uses for the accuracy overlay. Any object
|
|
22
|
+
* implementing this interface (including `HttpClient`) is accepted.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export interface MinimalCodexClient {
|
|
27
|
+
extractStream(pdf: ArrayBuffer | Uint8Array, callbacks: {
|
|
28
|
+
granular?: boolean;
|
|
29
|
+
onColorWorld?: (data: Record<string, unknown>) => void;
|
|
30
|
+
onOcgs?: (data: Record<string, unknown>) => void;
|
|
31
|
+
onPhase2?: (doc: {
|
|
32
|
+
pdf_sha256: string;
|
|
33
|
+
[key: string]: unknown;
|
|
34
|
+
}) => void;
|
|
35
|
+
}): Promise<{
|
|
36
|
+
pdf_sha256: string;
|
|
37
|
+
[key: string]: unknown;
|
|
38
|
+
}>;
|
|
39
|
+
renderSeparations(pdf: {
|
|
40
|
+
sha256: string;
|
|
41
|
+
}, opts?: {
|
|
42
|
+
page?: number;
|
|
43
|
+
dpi?: number;
|
|
44
|
+
}): Promise<{
|
|
45
|
+
channels: Array<{
|
|
46
|
+
name: string;
|
|
47
|
+
type: string;
|
|
48
|
+
png_b64: string;
|
|
49
|
+
}>;
|
|
50
|
+
}>;
|
|
51
|
+
renderHeatmap(pdf: {
|
|
52
|
+
sha256: string;
|
|
53
|
+
}, opts?: {
|
|
54
|
+
page?: number;
|
|
55
|
+
dpi?: number;
|
|
56
|
+
tacLimit?: number;
|
|
57
|
+
}): Promise<{
|
|
58
|
+
png: Uint8Array;
|
|
59
|
+
}>;
|
|
60
|
+
renderLayer(pdf: {
|
|
61
|
+
sha256: string;
|
|
62
|
+
}, opts: {
|
|
63
|
+
page?: number;
|
|
64
|
+
layerIndex: number;
|
|
65
|
+
allLayerIndices: number[];
|
|
66
|
+
dpi?: number;
|
|
67
|
+
}): Promise<Uint8Array>;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Extract a `DetectedInk[]` from the `color_world` SSE event payload.
|
|
71
|
+
* Returns the 4 CMYK process channels plus any spot colorants the
|
|
72
|
+
* PDF declares (accurate — from pikepdf, not regex scanning).
|
|
73
|
+
*
|
|
74
|
+
* @public
|
|
75
|
+
*/
|
|
76
|
+
export declare function extractInksFromColorWorld(colorWorld: Record<string, unknown>): DetectedInk[];
|
|
77
|
+
/**
|
|
78
|
+
* Extract a layer list from the `ocgs` SSE event payload.
|
|
79
|
+
*
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
export declare function extractLayersFromOcgs(ocgs: Record<string, unknown>): Array<{
|
|
83
|
+
name: string;
|
|
84
|
+
ocg_index: number;
|
|
85
|
+
default_on: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
export interface CodexOverlayServices {
|
|
88
|
+
separations: SeparationService;
|
|
89
|
+
tacHeatmap: TACHeatmapService;
|
|
90
|
+
layers: LayerService;
|
|
91
|
+
subscribe(listener: () => void): () => void;
|
|
92
|
+
dispose(): void;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Build `separations`, `tacHeatmap`, and `layers` service slots backed
|
|
96
|
+
* by the codex render APIs. Lazy: each page's renders are fetched the
|
|
97
|
+
* first time they're requested, then cached as blob URLs.
|
|
98
|
+
*
|
|
99
|
+
* Hosts swap these into `ViewerServices` after `phase2_complete` fires
|
|
100
|
+
* so pdfjs approximations are replaced by Ghostscript renders.
|
|
101
|
+
*
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
export declare function createCodexOverlayServices(client: MinimalCodexClient, sha256: string, tacLimit: number, layerData: ReadonlyArray<{
|
|
105
|
+
name: string;
|
|
106
|
+
ocg_index: number;
|
|
107
|
+
default_on: boolean;
|
|
108
|
+
}>): CodexOverlayServices;
|
|
109
|
+
//# sourceMappingURL=codexOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"codexOverlay.d.ts","sourceRoot":"","sources":["../../browser/codexOverlay.ts"],"names":[],"mappings":"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"}
|