@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
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState } from "react";
|
|
4
|
+
/**
|
|
5
|
+
* DielineOverlay — standalone info-icon overlay for dieline
|
|
6
|
+
* regions. Renders one ``i`` chip at the centroid of each
|
|
7
|
+
* extracted region so operators can click to see width/height
|
|
8
|
+
* in mm + inches. Independent of ``BoxOverlay`` so users don't
|
|
9
|
+
* have to flip on the Trim/Bleed Boxes toolbar to see dieline
|
|
10
|
+
* sizes.
|
|
11
|
+
*/
|
|
12
|
+
function boxToPixels(box, page, canvasWidth, canvasHeight) {
|
|
13
|
+
const scaleX = canvasWidth / page.width_pts;
|
|
14
|
+
const scaleY = canvasHeight / page.height_pts;
|
|
15
|
+
const mb = page.media_box;
|
|
16
|
+
return {
|
|
17
|
+
left: (box.x0 - mb.x0) * scaleX,
|
|
18
|
+
top: canvasHeight - (box.y1 - mb.y0) * scaleY,
|
|
19
|
+
width: (box.x1 - box.x0) * scaleX,
|
|
20
|
+
height: (box.y1 - box.y0) * scaleY,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
function ptToInches(pts) {
|
|
24
|
+
return pts / 72;
|
|
25
|
+
}
|
|
26
|
+
function formatSize(widthPts, heightPts) {
|
|
27
|
+
return {
|
|
28
|
+
mm: `${(widthPts * 25.4 / 72).toFixed(2)} × ${(heightPts * 25.4 / 72).toFixed(2)} mm`,
|
|
29
|
+
inches: `${ptToInches(widthPts).toFixed(3)} × ${ptToInches(heightPts).toFixed(3)} in`,
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function DielineOverlay({ page, canvasWidth, canvasHeight, dieline, }) {
|
|
33
|
+
const [openIdx, setOpenIdx] = useState(null);
|
|
34
|
+
const regions = dieline?.regions ?? [];
|
|
35
|
+
if (regions.length === 0)
|
|
36
|
+
return null;
|
|
37
|
+
const color = dieline?.multi_color ? "#ef4444" : "#dc2626";
|
|
38
|
+
return (_jsx("div", { style: { position: "absolute", inset: 0, zIndex: 16 }, children: regions.map((region, idx) => {
|
|
39
|
+
const box = {
|
|
40
|
+
x0: region.x0,
|
|
41
|
+
y0: region.y0,
|
|
42
|
+
x1: region.x1,
|
|
43
|
+
y1: region.y1,
|
|
44
|
+
};
|
|
45
|
+
const px = boxToPixels(box, page, canvasWidth, canvasHeight);
|
|
46
|
+
const cx = px.left + px.width / 2;
|
|
47
|
+
const cy = px.top + px.height / 2;
|
|
48
|
+
const size = formatSize(region.x1 - region.x0, region.y1 - region.y0);
|
|
49
|
+
const isOpen = openIdx === idx;
|
|
50
|
+
const label = regions.length > 1 ? `Dieline ${idx + 1}` : "Dieline";
|
|
51
|
+
return (_jsxs("div", { className: "absolute", style: { left: Math.max(0, cx - 8), top: Math.max(0, cy - 8) }, children: [_jsx("button", { type: "button", "aria-label": `${label} size`, title: `Show ${label.toLowerCase()} size`, onClick: (e) => {
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
setOpenIdx(isOpen ? null : idx);
|
|
54
|
+
}, className: "flex h-5 w-5 items-center justify-center rounded-full text-[11px] font-bold text-white shadow ring-1 ring-black/30", style: { backgroundColor: color }, children: "i" }), isOpen && (_jsxs("div", { className: "absolute left-6 top-0 z-20 w-max rounded-md bg-black/90 px-3 py-2 text-xs text-white shadow-xl", onClick: (e) => e.stopPropagation(), children: [_jsxs("div", { className: "mb-1 flex items-center gap-2 border-b border-white/10 pb-1", children: [_jsx("span", { className: "inline-block h-2 w-2 rounded-sm", style: { backgroundColor: color } }), _jsx("span", { className: "font-semibold", children: label }), dieline?.multi_color && (_jsx("span", { className: "ml-1 rounded bg-red-500/20 px-1 py-0.5 text-[9px] font-semibold text-red-300", children: "multi-colour" }))] }), _jsxs("div", { className: "grid grid-cols-[auto_auto] gap-x-3 gap-y-0.5", children: [_jsx("span", { className: "text-slate-400", children: "Metric" }), _jsx("span", { className: "font-mono", children: size.mm }), _jsx("span", { className: "text-slate-400", children: "Imperial" }), _jsx("span", { className: "font-mono", children: size.inches })] })] }))] }, `die-icon-${idx}`));
|
|
55
|
+
}) }));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=DielineOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DielineOverlay.js","sourceRoot":"","sources":["../../components/DielineOverlay.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Findings sidebar — built-in component for hosts that pass
|
|
3
|
+
* ``items`` (OverlayItems) to LensPDF and want a polished list of
|
|
4
|
+
* findings alongside the canvas.
|
|
5
|
+
*
|
|
6
|
+
* Behaviour out of the box:
|
|
7
|
+
*
|
|
8
|
+
* - Splits items into "Located in viewer" (clickable, drawn on the
|
|
9
|
+
* canvas) and "Informational" (no bbox, surfaced separately) via
|
|
10
|
+
* ``splitFindingsByLocation`` so consumers never have to write
|
|
11
|
+
* the predicate themselves.
|
|
12
|
+
* - Each group has a collapsible header with a count chip.
|
|
13
|
+
* - Severity filter pills (all / error / warning / advisory / info)
|
|
14
|
+
* along the top.
|
|
15
|
+
* - Item buttons fire ``onSelect`` so the host can sync canvas
|
|
16
|
+
* highlight + page jump.
|
|
17
|
+
*
|
|
18
|
+
* The component is intentionally opinionated about layout (vertical
|
|
19
|
+
* sidebar, dark / brand palette honoured via Lens's existing
|
|
20
|
+
* ThemeTokens). Hosts that need a totally different chrome should
|
|
21
|
+
* import the underlying helpers and roll their own.
|
|
22
|
+
*
|
|
23
|
+
* @public
|
|
24
|
+
*/
|
|
25
|
+
import * as React from "react";
|
|
26
|
+
import type { OverlayItem } from "../plugin";
|
|
27
|
+
export interface FindingsSidebarProps {
|
|
28
|
+
/** All findings — both located and informational. Pass the same
|
|
29
|
+
* superset you'd pass to ``<LensPDF items={...}>``. */
|
|
30
|
+
items: readonly OverlayItem[];
|
|
31
|
+
/** Current canvas selection, if any. Drives the highlighted row. */
|
|
32
|
+
selected?: OverlayItem | null;
|
|
33
|
+
/** Fires when the user clicks a located item. Hosts typically
|
|
34
|
+
* forward this to LensPDF's ``selectedItem`` prop so the canvas
|
|
35
|
+
* jumps + tooltips the matching bbox. */
|
|
36
|
+
onSelect?: (item: OverlayItem | null) => void;
|
|
37
|
+
/** Optional title shown in the sidebar header. Default:
|
|
38
|
+
* ``"Preflight findings"`` — adapter authors mapping other
|
|
39
|
+
* engines (callas, PitStop, Acrobat) can override. */
|
|
40
|
+
title?: string;
|
|
41
|
+
/** Optional filename caption rendered under the title. */
|
|
42
|
+
filename?: string;
|
|
43
|
+
/** Width class applied to the aside; defaults to ``w-80``. */
|
|
44
|
+
widthClass?: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Sticky vertical sidebar for the LensPDF viewer.
|
|
48
|
+
*/
|
|
49
|
+
export declare function FindingsSidebar({ items, selected, onSelect, title, filename, widthClass, }: FindingsSidebarProps): React.ReactElement;
|
|
50
|
+
//# sourceMappingURL=FindingsSidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FindingsSidebar.d.ts","sourceRoot":"","sources":["../../components/FindingsSidebar.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAiC7C,MAAM,WAAW,oBAAoB;IACnC;4DACwD;IACxD,KAAK,EAAE,SAAS,WAAW,EAAE,CAAC;IAC9B,oEAAoE;IACpE,QAAQ,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B;;8CAE0C;IAC1C,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAC9C;;2DAEuD;IACvD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAe,EACf,QAAQ,EACR,KAA4B,EAC5B,QAAQ,EACR,UAAmB,GACpB,EAAE,oBAAoB,GAAG,KAAK,CAAC,YAAY,CAiJ3C"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useMemo, useState } from "react";
|
|
4
|
+
import { splitFindingsByLocation } from "../plugin/index.js";
|
|
5
|
+
const TIER_TONE = {
|
|
6
|
+
error: {
|
|
7
|
+
wrap: "border-red-700/60 bg-red-900/30 text-red-200",
|
|
8
|
+
chip: "border-red-700/60 bg-red-900/30 text-red-200",
|
|
9
|
+
},
|
|
10
|
+
warning: {
|
|
11
|
+
wrap: "border-amber-700/60 bg-amber-900/30 text-amber-200",
|
|
12
|
+
chip: "border-amber-700/60 bg-amber-900/30 text-amber-200",
|
|
13
|
+
},
|
|
14
|
+
advisory: {
|
|
15
|
+
wrap: "border-sky-700/60 bg-sky-900/30 text-sky-200",
|
|
16
|
+
chip: "border-sky-700/60 bg-sky-900/30 text-sky-200",
|
|
17
|
+
},
|
|
18
|
+
info: {
|
|
19
|
+
wrap: "border-slate-700 bg-slate-800 text-slate-300",
|
|
20
|
+
chip: "border-slate-700 bg-slate-800 text-slate-300",
|
|
21
|
+
},
|
|
22
|
+
neutral: {
|
|
23
|
+
wrap: "border-slate-700 bg-slate-800 text-slate-400",
|
|
24
|
+
chip: "border-slate-700 bg-slate-800 text-slate-400",
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
function tierLabel(t) {
|
|
28
|
+
return t ?? "info";
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sticky vertical sidebar for the LensPDF viewer.
|
|
32
|
+
*/
|
|
33
|
+
export function FindingsSidebar({ items, selected = null, onSelect, title = "Preflight findings", filename, widthClass = "w-80", }) {
|
|
34
|
+
const [tierFilter, setTierFilter] = useState("all");
|
|
35
|
+
const [locatedOpen, setLocatedOpen] = useState(true);
|
|
36
|
+
const [infoOpen, setInfoOpen] = useState(true);
|
|
37
|
+
const allItems = useMemo(() => Array.from(items ?? []), [items]);
|
|
38
|
+
const tierCounts = useMemo(() => {
|
|
39
|
+
const counts = {};
|
|
40
|
+
for (const it of allItems) {
|
|
41
|
+
const t = tierLabel(it.tier);
|
|
42
|
+
counts[t] = (counts[t] ?? 0) + 1;
|
|
43
|
+
}
|
|
44
|
+
return counts;
|
|
45
|
+
}, [allItems]);
|
|
46
|
+
const visible = useMemo(() => tierFilter === "all"
|
|
47
|
+
? allItems
|
|
48
|
+
: allItems.filter((i) => tierLabel(i.tier) === tierFilter), [allItems, tierFilter]);
|
|
49
|
+
const { located, informational } = useMemo(() => splitFindingsByLocation(visible), [visible]);
|
|
50
|
+
const total = allItems.length;
|
|
51
|
+
const tierOrder = ["all", "error", "warning", "advisory", "info"];
|
|
52
|
+
return (_jsxs("aside", { className: `${widthClass} hidden shrink-0 flex-col border-r border-slate-800 bg-slate-900/60 text-slate-100 md:flex`, children: [_jsxs("div", { className: "border-b border-slate-800 px-4 py-3", children: [_jsx("p", { className: "text-xs font-semibold uppercase tracking-wider text-brand-300", children: title }), filename ? (_jsx("p", { className: "mt-1 truncate text-xs text-slate-500", title: filename, children: filename })) : null, total > 0 ? (_jsx("div", { className: "mt-3 flex flex-wrap gap-1.5", children: tierOrder.map((tier) => {
|
|
53
|
+
const count = tier === "all" ? total : tierCounts[tier] ?? 0;
|
|
54
|
+
if (tier !== "all" && count === 0)
|
|
55
|
+
return null;
|
|
56
|
+
const active = tierFilter === tier;
|
|
57
|
+
return (_jsxs("button", { type: "button", onClick: () => setTierFilter(tier), className: "rounded-full border px-2.5 py-0.5 text-[10px] font-medium transition " +
|
|
58
|
+
(active
|
|
59
|
+
? "border-brand-400 bg-brand-900/40 text-brand-100"
|
|
60
|
+
: "border-slate-700 bg-slate-800 text-slate-400 hover:border-brand-500/60 hover:text-brand-200"), children: [tier === "all" ? "All" : tier, _jsx("span", { className: "ml-1 text-slate-500", children: count })] }, tier));
|
|
61
|
+
}) })) : null] }), _jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto", children: [total === 0 ? (_jsx("p", { className: "px-4 py-6 text-center text-xs text-slate-500", children: "No findings on this PDF." })) : null, located.length > 0 ? (_jsx(SectionHeader, { label: "Located in viewer", count: located.length, tone: "brand", open: locatedOpen, onToggle: () => setLocatedOpen((v) => !v) })) : null, locatedOpen && located.length > 0 ? (_jsx("ul", { className: "divide-y divide-slate-800", children: located.map((item) => {
|
|
62
|
+
const tier = tierLabel(item.tier);
|
|
63
|
+
const isSelected = selected?.id === item.id;
|
|
64
|
+
return (_jsx("li", { children: _jsxs("button", { type: "button", onClick: () => onSelect?.(item), className: "flex w-full flex-col items-start gap-1 px-4 py-3 text-left text-xs transition " +
|
|
65
|
+
(isSelected ? "bg-brand-900/40" : "hover:bg-slate-900/80"), children: [_jsx(FindingRowHeader, { item: item, tier: tier }), _jsx("span", { className: "text-slate-200", children: item.label ?? item.description ?? item.code ?? "Finding" })] }) }, item.id));
|
|
66
|
+
}) })) : null, informational.length > 0 ? (_jsx(SectionHeader, { label: "Informational", count: informational.length, tone: "muted", open: infoOpen, onToggle: () => setInfoOpen((v) => !v) })) : null, infoOpen && informational.length > 0 ? (_jsx("ul", { className: "divide-y divide-slate-800", children: informational.map((item) => {
|
|
67
|
+
const tier = tierLabel(item.tier);
|
|
68
|
+
return (_jsxs("li", { className: "cursor-default px-4 py-3 text-xs", title: "No bounding box on this finding \u2014 not clickable in the viewer.", children: [_jsx(FindingRowHeader, { item: item, tier: tier }), _jsx("span", { className: "mt-1 block text-slate-300", children: item.label ?? item.description ?? item.code ?? "Finding" })] }, item.id));
|
|
69
|
+
}) })) : null] })] }));
|
|
70
|
+
}
|
|
71
|
+
function FindingRowHeader({ item, tier, }) {
|
|
72
|
+
return (_jsxs("div", { className: "flex w-full items-center gap-2", children: [_jsx("span", { className: "rounded-full border px-2 py-0.5 text-[10px] font-medium " + TIER_TONE[tier].chip, children: tier }), item.code ? (_jsx("span", { className: "truncate font-mono text-[11px] text-slate-400", children: item.code })) : null, _jsxs("span", { className: "ml-auto shrink-0 text-[11px] text-slate-500", children: ["p", item.page] })] }));
|
|
73
|
+
}
|
|
74
|
+
function SectionHeader({ label, count, tone, open, onToggle, }) {
|
|
75
|
+
const color = tone === "brand" ? "text-brand-300" : "text-slate-400";
|
|
76
|
+
return (_jsxs("button", { type: "button", onClick: onToggle, "aria-expanded": open, className: `flex w-full items-center gap-2 border-y border-slate-800 bg-slate-900/80 px-4 py-2 text-left text-[10px] font-semibold uppercase tracking-wider transition hover:bg-slate-900 ${color}`, children: [_jsx("span", { "aria-hidden": "true", className: `inline-block w-2 text-center transition-transform ${open ? "rotate-90" : ""}`, children: "\u25B6" }), _jsxs("span", { children: [label, " \u00B7 ", count] })] }));
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=FindingsSidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FindingsSidebar.js","sourceRoot":"","sources":["../../components/FindingsSidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WS-17C — instant layer toggling via per-OCG isolated tiles.
|
|
3
|
+
*
|
|
4
|
+
* The engine renders one PNG per layer with a transparent
|
|
5
|
+
* background (``pngalpha`` device + every other OCG hidden via
|
|
6
|
+
* ``_apply_ocg_overrides``). The browser then composites the active
|
|
7
|
+
* subset locally via ``source-over`` blending. Toggling a layer
|
|
8
|
+
* is just removing it from the draw list and redrawing — no API
|
|
9
|
+
* round-trip after the first warm-up.
|
|
10
|
+
*
|
|
11
|
+
* The first paint of an unseen layer takes ~1-3 s (Ghostscript +
|
|
12
|
+
* cache write). Subsequent toggles of the same layer hit the S3
|
|
13
|
+
* cache and complete in well under 100 ms.
|
|
14
|
+
*
|
|
15
|
+
* Mirrors the public-shape of SeparationCanvas so PdfViewer can
|
|
16
|
+
* swap them in / out by ``viewerMode``.
|
|
17
|
+
*/
|
|
18
|
+
interface LayerCanvasProps {
|
|
19
|
+
jobId: string;
|
|
20
|
+
pageNum: number;
|
|
21
|
+
enabledLayers: Set<number>;
|
|
22
|
+
/** All OCG indices for this page (drawing order). */
|
|
23
|
+
allLayers: number[];
|
|
24
|
+
width: number;
|
|
25
|
+
height: number;
|
|
26
|
+
dpi?: number;
|
|
27
|
+
}
|
|
28
|
+
export declare function LayerCanvas({ jobId: _jobId, pageNum, enabledLayers, allLayers, width, height, dpi, }: LayerCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=LayerCanvas.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayerCanvas.d.ts","sourceRoot":"","sources":["../../components/LayerCanvas.tsx"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AAEH,UAAU,gBAAgB;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,qDAAqD;IACrD,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,WAAW,CAAC,EAC1B,KAAK,EAAE,MAAM,EACb,OAAO,EACP,aAAa,EACb,SAAS,EACT,KAAK,EACL,MAAM,EACN,GAAiB,GAClB,EAAE,gBAAgB,2CA+FlB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
4
|
+
import { DEFAULT_DPI } from "../types/index.js";
|
|
5
|
+
import { useViewerServices } from "../host/index.js";
|
|
6
|
+
export function LayerCanvas({ jobId: _jobId, pageNum, enabledLayers, allLayers, width, height, dpi = DEFAULT_DPI, }) {
|
|
7
|
+
const { layers: layerService } = useViewerServices();
|
|
8
|
+
const canvasRef = useRef(null);
|
|
9
|
+
const [layerImages, setLayerImages] = useState(new Map());
|
|
10
|
+
const [loadingLayers, setLoadingLayers] = useState(new Set());
|
|
11
|
+
// Drop the cache when the page changes — different page = different
|
|
12
|
+
// OCG set, even if indices happen to overlap numerically.
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
setLayerImages(new Map());
|
|
15
|
+
setLoadingLayers(new Set());
|
|
16
|
+
}, [pageNum]);
|
|
17
|
+
const loadLayer = useCallback(async (layerIndex) => {
|
|
18
|
+
if (layerImages.has(layerIndex) || loadingLayers.has(layerIndex)) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
setLoadingLayers((prev) => new Set(prev).add(layerIndex));
|
|
22
|
+
const img = new Image();
|
|
23
|
+
const url = layerService.getLayerImageUrl({ pageNum, layerIndex, dpi });
|
|
24
|
+
await new Promise((resolve) => {
|
|
25
|
+
img.onload = () => {
|
|
26
|
+
setLayerImages((prev) => {
|
|
27
|
+
const next = new Map(prev);
|
|
28
|
+
next.set(layerIndex, img);
|
|
29
|
+
return next;
|
|
30
|
+
});
|
|
31
|
+
setLoadingLayers((prev) => {
|
|
32
|
+
const next = new Set(prev);
|
|
33
|
+
next.delete(layerIndex);
|
|
34
|
+
return next;
|
|
35
|
+
});
|
|
36
|
+
resolve();
|
|
37
|
+
};
|
|
38
|
+
img.onerror = () => {
|
|
39
|
+
// Don't bubble the error — let the canvas show the layers
|
|
40
|
+
// that DID load. Render failures on a single layer are
|
|
41
|
+
// logged server-side; the viewer just shows everything else.
|
|
42
|
+
setLoadingLayers((prev) => {
|
|
43
|
+
const next = new Set(prev);
|
|
44
|
+
next.delete(layerIndex);
|
|
45
|
+
return next;
|
|
46
|
+
});
|
|
47
|
+
resolve();
|
|
48
|
+
};
|
|
49
|
+
img.src = url;
|
|
50
|
+
});
|
|
51
|
+
}, [layerService, pageNum, dpi, layerImages, loadingLayers]);
|
|
52
|
+
// Trigger fetches for any enabled layer we don't have cached yet.
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
for (const idx of enabledLayers) {
|
|
55
|
+
if (!layerImages.has(idx)) {
|
|
56
|
+
void loadLayer(idx);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}, [enabledLayers, layerImages, loadLayer]);
|
|
60
|
+
// Repaint every time the enabled set or the cached images change.
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const canvas = canvasRef.current;
|
|
63
|
+
if (!canvas)
|
|
64
|
+
return;
|
|
65
|
+
const ctx = canvas.getContext("2d");
|
|
66
|
+
if (!ctx)
|
|
67
|
+
return;
|
|
68
|
+
// Start from white paper so hidden layers reveal blank stock,
|
|
69
|
+
// not the slate-900 viewer chrome behind the canvas.
|
|
70
|
+
ctx.fillStyle = "#ffffff";
|
|
71
|
+
ctx.fillRect(0, 0, width, height);
|
|
72
|
+
ctx.globalCompositeOperation = "source-over";
|
|
73
|
+
for (const layerIndex of allLayers) {
|
|
74
|
+
if (!enabledLayers.has(layerIndex))
|
|
75
|
+
continue;
|
|
76
|
+
const img = layerImages.get(layerIndex);
|
|
77
|
+
if (!img)
|
|
78
|
+
continue;
|
|
79
|
+
ctx.drawImage(img, 0, 0, width, height);
|
|
80
|
+
}
|
|
81
|
+
}, [width, height, enabledLayers, layerImages, allLayers]);
|
|
82
|
+
return (_jsx("canvas", { ref: canvasRef, width: width, height: height, style: { position: "absolute", left: 0, top: 0, width, height } }));
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=LayerCanvas.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayerCanvas.js","sourceRoot":"","sources":["../../components/LayerCanvas.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface LayerPanelProps {
|
|
2
|
+
jobId: string;
|
|
3
|
+
enabledLayers: Set<number>;
|
|
4
|
+
onToggleLayer: (ocgIndex: number) => void;
|
|
5
|
+
onSetAllLayers: (enabled: boolean) => void;
|
|
6
|
+
}
|
|
7
|
+
export declare function LayerPanel({ jobId: _jobId, enabledLayers, onToggleLayer, onSetAllLayers, }: LayerPanelProps): import("react/jsx-runtime").JSX.Element | null;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=LayerPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayerPanel.d.ts","sourceRoot":"","sources":["../../components/LayerPanel.tsx"],"names":[],"mappings":"AAYA,UAAU,eAAe;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,aAAa,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,cAAc,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC5C;AAkHD,wBAAgB,UAAU,CAAC,EACzB,KAAK,EAAE,MAAM,EACb,aAAa,EACb,aAAa,EACb,cAAc,GACf,EAAE,eAAe,kDAmGjB"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { useCallback, useEffect, useState } from "react";
|
|
4
|
+
import { logUnwiredHide, useFallbackMode, useViewerHost, useViewerServices, } from "../host/index.js";
|
|
5
|
+
const FLATTENED_LAYER_INDEX = -1;
|
|
6
|
+
const FLATTENED_LAYER = {
|
|
7
|
+
name: "Artwork (flattened PDF)",
|
|
8
|
+
ocg_index: FLATTENED_LAYER_INDEX,
|
|
9
|
+
default_on: true,
|
|
10
|
+
synthetic: true,
|
|
11
|
+
kind: "flattened-artwork",
|
|
12
|
+
};
|
|
13
|
+
const containerStyle = {
|
|
14
|
+
display: "flex",
|
|
15
|
+
flexDirection: "column",
|
|
16
|
+
gap: 10,
|
|
17
|
+
padding: 8,
|
|
18
|
+
fontSize: 12,
|
|
19
|
+
color: "#e2e8f0",
|
|
20
|
+
};
|
|
21
|
+
const headerRowStyle = {
|
|
22
|
+
display: "flex",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
justifyContent: "space-between",
|
|
25
|
+
gap: 8,
|
|
26
|
+
};
|
|
27
|
+
const headerTitleStyle = {
|
|
28
|
+
margin: 0,
|
|
29
|
+
fontSize: 12,
|
|
30
|
+
fontWeight: 600,
|
|
31
|
+
color: "#f8fafc",
|
|
32
|
+
letterSpacing: "0.04em",
|
|
33
|
+
textTransform: "uppercase",
|
|
34
|
+
};
|
|
35
|
+
const headerActionsStyle = {
|
|
36
|
+
display: "flex",
|
|
37
|
+
gap: 6,
|
|
38
|
+
};
|
|
39
|
+
const allButtonStyle = {
|
|
40
|
+
background: "transparent",
|
|
41
|
+
border: "1px solid rgba(255,255,255,0.12)",
|
|
42
|
+
borderRadius: 4,
|
|
43
|
+
color: "#cbd5e1",
|
|
44
|
+
fontSize: 11,
|
|
45
|
+
padding: "2px 6px",
|
|
46
|
+
cursor: "pointer",
|
|
47
|
+
};
|
|
48
|
+
const layerListStyle = {
|
|
49
|
+
display: "flex",
|
|
50
|
+
flexDirection: "column",
|
|
51
|
+
gap: 4,
|
|
52
|
+
};
|
|
53
|
+
const layerRowStyle = {
|
|
54
|
+
display: "flex",
|
|
55
|
+
alignItems: "center",
|
|
56
|
+
gap: 8,
|
|
57
|
+
padding: "4px 6px",
|
|
58
|
+
borderRadius: 4,
|
|
59
|
+
cursor: "pointer",
|
|
60
|
+
color: "#e2e8f0",
|
|
61
|
+
fontSize: 12,
|
|
62
|
+
background: "transparent",
|
|
63
|
+
transition: "background 0.12s ease",
|
|
64
|
+
};
|
|
65
|
+
const layerNameStyle = {
|
|
66
|
+
flex: 1,
|
|
67
|
+
overflow: "hidden",
|
|
68
|
+
textOverflow: "ellipsis",
|
|
69
|
+
whiteSpace: "nowrap",
|
|
70
|
+
};
|
|
71
|
+
const messageStyle = {
|
|
72
|
+
margin: 0,
|
|
73
|
+
padding: "8px 6px",
|
|
74
|
+
fontSize: 12,
|
|
75
|
+
color: "rgba(226,232,240,0.55)",
|
|
76
|
+
fontStyle: "italic",
|
|
77
|
+
};
|
|
78
|
+
const errorStyle = {
|
|
79
|
+
...messageStyle,
|
|
80
|
+
color: "#fca5a5",
|
|
81
|
+
fontStyle: "normal",
|
|
82
|
+
};
|
|
83
|
+
const loadingRowStyle = {
|
|
84
|
+
display: "flex",
|
|
85
|
+
alignItems: "center",
|
|
86
|
+
gap: 8,
|
|
87
|
+
padding: "8px 6px",
|
|
88
|
+
fontSize: 12,
|
|
89
|
+
color: "rgba(226,232,240,0.55)",
|
|
90
|
+
fontStyle: "italic",
|
|
91
|
+
};
|
|
92
|
+
const spinnerStyle = {
|
|
93
|
+
width: 14,
|
|
94
|
+
height: 14,
|
|
95
|
+
borderRadius: "50%",
|
|
96
|
+
border: "2px solid rgba(255,255,255,0.18)",
|
|
97
|
+
borderTopColor: "rgba(255,255,255,0.65)",
|
|
98
|
+
animation: "lens-pdf-layer-spin 0.85s linear infinite",
|
|
99
|
+
};
|
|
100
|
+
const SPINNER_KEYFRAMES = `@keyframes lens-pdf-layer-spin {
|
|
101
|
+
to { transform: rotate(360deg); }
|
|
102
|
+
}`;
|
|
103
|
+
export function LayerPanel({ jobId: _jobId, enabledLayers, onToggleLayer, onSetAllLayers, }) {
|
|
104
|
+
const { layers: layerService } = useViewerServices();
|
|
105
|
+
const { debug, pdfFallback } = useViewerHost();
|
|
106
|
+
const mode = useFallbackMode(layerService);
|
|
107
|
+
const [layers, setLayers] = useState([]);
|
|
108
|
+
const [loading, setLoading] = useState(true);
|
|
109
|
+
const [error, setError] = useState("");
|
|
110
|
+
const displayLayers = layers.length > 0 ? layers : [FLATTENED_LAYER];
|
|
111
|
+
const showingSyntheticFallback = displayLayers.length === 1 && displayLayers[0]?.synthetic === true;
|
|
112
|
+
const fetchLayers = useCallback(async () => {
|
|
113
|
+
try {
|
|
114
|
+
const items = mode === "fallback" && pdfFallback
|
|
115
|
+
? await pdfFallback.listLayers()
|
|
116
|
+
: await layerService.listLayers();
|
|
117
|
+
setLayers([...items]);
|
|
118
|
+
}
|
|
119
|
+
catch (e) {
|
|
120
|
+
setError(e instanceof Error ? e.message : "Failed to load layers");
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
setLoading(false);
|
|
124
|
+
}
|
|
125
|
+
}, [layerService, pdfFallback, mode]);
|
|
126
|
+
useEffect(() => {
|
|
127
|
+
if (mode === "hidden") {
|
|
128
|
+
if (debug)
|
|
129
|
+
logUnwiredHide("LayerPanel", "layers");
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
fetchLayers();
|
|
133
|
+
}, [fetchLayers, mode, debug]);
|
|
134
|
+
if (mode === "hidden")
|
|
135
|
+
return null;
|
|
136
|
+
if (loading) {
|
|
137
|
+
return (_jsxs(_Fragment, { children: [_jsx("style", { children: SPINNER_KEYFRAMES }), _jsxs("div", { style: loadingRowStyle, children: [_jsx("span", { "aria-hidden": true, style: spinnerStyle }), _jsx("span", { children: "Loading layers\u2026" })] })] }));
|
|
138
|
+
}
|
|
139
|
+
if (error) {
|
|
140
|
+
return _jsx("div", { style: errorStyle, children: error });
|
|
141
|
+
}
|
|
142
|
+
return (_jsxs("div", { style: containerStyle, children: [_jsxs("div", { style: headerRowStyle, children: [_jsxs("h3", { style: headerTitleStyle, children: ["Layers (", displayLayers.length, ")"] }), _jsxs("div", { style: headerActionsStyle, children: [_jsx("button", { type: "button", onClick: () => onSetAllLayers(true), style: allButtonStyle, title: "Show every layer", children: "All on" }), _jsx("button", { type: "button", onClick: () => onSetAllLayers(false), style: allButtonStyle, title: "Hide every layer", children: "All off" })] })] }), showingSyntheticFallback && (_jsx("p", { style: messageStyle, children: "No optional-content groups (OCGs) were found, so this row represents the flattened page artwork. Many exported PDFs are flat." })), _jsx("div", { style: layerListStyle, children: displayLayers.map((layer) => (_jsxs("label", { style: layerRowStyle, title: `Toggle "${layer.name}"`, children: [_jsx("input", { type: "checkbox", checked: enabledLayers.has(layer.ocg_index), onChange: () => onToggleLayer(layer.ocg_index) }), _jsx("span", { style: layerNameStyle, children: layer.name })] }, layer.ocg_index))) })] }));
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=LayerPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LayerPanel.js","sourceRoot":"","sources":["../../components/LayerPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `<LensPDF>` — drop-in production viewer.
|
|
3
|
+
*
|
|
4
|
+
* One mount, every viewer-only feature wired by default:
|
|
5
|
+
*
|
|
6
|
+
* ```tsx
|
|
7
|
+
* import { LensPDF } from "@printwithsynergy/lens-pdf";
|
|
8
|
+
* import pdfWorkerSrc from "pdfjs-dist/build/pdf.worker.mjs?url";
|
|
9
|
+
*
|
|
10
|
+
* <LensPDF pdfUrl="/proofs/abc.pdf" workerSrc={pdfWorkerSrc} />
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* Production hosts can plug in their own preflight engine without
|
|
14
|
+
* forking the viewer:
|
|
15
|
+
*
|
|
16
|
+
* ```tsx
|
|
17
|
+
* <LensPDF
|
|
18
|
+
* pdfUrl="/proofs/abc.pdf"
|
|
19
|
+
* workerSrc={pdfWorkerSrc}
|
|
20
|
+
* items={findings} // OverlayItem[] from your engine
|
|
21
|
+
* selectedItem={selected}
|
|
22
|
+
* onItemSelect={setSelected}
|
|
23
|
+
* dieline={dielineForCurrentPage}
|
|
24
|
+
* showBoxOverlays // trim / bleed / crop popovers
|
|
25
|
+
* tools={["color-picker", "annotate", "tac-heatmap", "separations"]}
|
|
26
|
+
* onPageChange={setCurrentPage}
|
|
27
|
+
* tokens={{ accent: "#e50c6a" }}
|
|
28
|
+
* />
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* Identical to {@link LensPDFDemo} except the upload chrome (URL bar,
|
|
32
|
+
* file picker, drag-and-drop, empty state) is hidden — `pdfUrl` is the
|
|
33
|
+
* single required prop, and changing it swaps the loaded document.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
import { type LensPDFDemoProps } from "./LensPDFDemo";
|
|
38
|
+
/**
|
|
39
|
+
* Props for {@link LensPDF}. Identical to {@link LensPDFDemoProps}
|
|
40
|
+
* except `pdfUrl` is required (replaces `initialPdfUrl`) and the
|
|
41
|
+
* upload-chrome props (`maxFileSize`) are hidden.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export interface LensPDFProps extends Omit<LensPDFDemoProps, "embedded" | "initialPdfUrl" | "maxFileSize"> {
|
|
46
|
+
/**
|
|
47
|
+
* URL of the PDF to load. Any URL the browser can fetch — your
|
|
48
|
+
* own CDN, a signed link, a `blob:` URL from a `File` your app
|
|
49
|
+
* uploaded, etc. Changing this swaps the document and resets to
|
|
50
|
+
* `initialPage`.
|
|
51
|
+
*/
|
|
52
|
+
pdfUrl: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Drop-in production viewer. See {@link LensPDFProps} for the full
|
|
56
|
+
* prop surface.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export declare function LensPDF({ pdfUrl, ...rest }: LensPDFProps): import("react/jsx-runtime").JSX.Element;
|
|
61
|
+
//# sourceMappingURL=LensPDF.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LensPDF.d.ts","sourceRoot":"","sources":["../../components/LensPDF.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAe,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,WAAW,YACf,SAAQ,IAAI,CAAC,gBAAgB,EAAE,UAAU,GAAG,eAAe,GAAG,aAAa,CAAC;IAC5E;;;;;OAKG;IACH,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,EAAE,YAAY,2CAExD"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* `<LensPDF>` — drop-in production viewer.
|
|
5
|
+
*
|
|
6
|
+
* One mount, every viewer-only feature wired by default:
|
|
7
|
+
*
|
|
8
|
+
* ```tsx
|
|
9
|
+
* import { LensPDF } from "@printwithsynergy/lens-pdf";
|
|
10
|
+
* import pdfWorkerSrc from "pdfjs-dist/build/pdf.worker.mjs?url";
|
|
11
|
+
*
|
|
12
|
+
* <LensPDF pdfUrl="/proofs/abc.pdf" workerSrc={pdfWorkerSrc} />
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* Production hosts can plug in their own preflight engine without
|
|
16
|
+
* forking the viewer:
|
|
17
|
+
*
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <LensPDF
|
|
20
|
+
* pdfUrl="/proofs/abc.pdf"
|
|
21
|
+
* workerSrc={pdfWorkerSrc}
|
|
22
|
+
* items={findings} // OverlayItem[] from your engine
|
|
23
|
+
* selectedItem={selected}
|
|
24
|
+
* onItemSelect={setSelected}
|
|
25
|
+
* dieline={dielineForCurrentPage}
|
|
26
|
+
* showBoxOverlays // trim / bleed / crop popovers
|
|
27
|
+
* tools={["color-picker", "annotate", "tac-heatmap", "separations"]}
|
|
28
|
+
* onPageChange={setCurrentPage}
|
|
29
|
+
* tokens={{ accent: "#e50c6a" }}
|
|
30
|
+
* />
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* Identical to {@link LensPDFDemo} except the upload chrome (URL bar,
|
|
34
|
+
* file picker, drag-and-drop, empty state) is hidden — `pdfUrl` is the
|
|
35
|
+
* single required prop, and changing it swaps the loaded document.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
import { LensPDFDemo } from "./LensPDFDemo.js";
|
|
40
|
+
/**
|
|
41
|
+
* Drop-in production viewer. See {@link LensPDFProps} for the full
|
|
42
|
+
* prop surface.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export function LensPDF({ pdfUrl, ...rest }) {
|
|
47
|
+
return _jsx(LensPDFDemo, { ...rest, embedded: true, preset: "minimal", initialPdfUrl: pdfUrl });
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=LensPDF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LensPDF.js","sourceRoot":"","sources":["../../components/LensPDF.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAC;;AAEb;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH,OAAO,EAAE,WAAW,EAAyB,MAAM,eAAe,CAAC;AAoBnE;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,EAAgB;IACvD,OAAO,KAAC,WAAW,OAAK,IAAI,EAAE,QAAQ,QAAC,MAAM,EAAC,SAAS,EAAC,aAAa,EAAE,MAAM,GAAI,CAAC;AACpF,CAAC"}
|