import type { Dispatch, ReactNode, SetStateAction } from "react"; import type { ThemeTokens, ViewerServices } from "../plugin/services"; import type { AnnotationTool } from "./AnnotationToolbar"; import type { LensPDFDemoTool } from "./LensPDFDemo"; export type ViewerMode = "page" | "separation" | "layer" | "findings"; export type PointerTool = "none" | "color-picker" | "densitometer" | "measure" | "annotate"; export interface LensPDFFeatureAvailability { colorPicker: boolean; densitometer: boolean; measure: boolean; annotate: boolean; tacHeatmap: boolean; separations: boolean; layers: boolean; } export interface LensPDFFeatureInputs { tools: ReadonlyArray; services: ViewerServices | null; detectedInkCount: number; layerCount: number; isUnwired: (service: object | null | undefined) => boolean; } export declare function computeFeatureAvailability({ tools, services, detectedInkCount, layerCount, isUnwired, }: LensPDFFeatureInputs): LensPDFFeatureAvailability; export interface LensPDFShellPluginContext { tokens: ThemeTokens; isMobile: boolean; pdfUrl: string; servicesVersion: number; currentPage: number; setCurrentPage: Dispatch>; viewerMode: ViewerMode; setViewerMode: Dispatch>; activeTool: PointerTool; setActiveTool: Dispatch>; showHeatmap: boolean; setShowHeatmap: Dispatch>; /** Manual dieline overlay toggle. Independent of viewerMode — when * `true` the dieline draws on top of any canvas mode. When `false`, * dieline only renders in Inspection mode (`viewerMode === "findings"`). */ showDieline: boolean; setShowDieline: Dispatch>; /** Manual finding-overlay toggle (bbox highlights + F-number badges * on the canvas). Same gating logic as `showDieline`. */ showFindings: boolean; setShowFindings: Dispatch>; enabledChannels: Set; setEnabledChannels: Dispatch>>; detectedInks: Array<{ name: string; type: "process" | "spot"; /** Synthetic alternate sRGB triplet for the ink. For spots it's * parsed from the PDF's tint transform when available, otherwise * hash-derived. The separations panel uses this as the third * link in the swatch resolution chain after ``spotPalette`` and * the Pantone Gold library. */ altRgb: [number, number, number]; }>; /** Page-average ink coverage % per ink, keyed by ink name (0–100). * `null` while it loads or when the separation service can't compute * it. The separations panel renders it next to each ink and hides any * plate measured at ~0% (an unused / phantom plate). Recomputed on * page change only. */ channelCoverage?: Record | null; /** Host-provided spot-color palette — keyed by spot name (case * insensitive). Takes priority over both the Pantone Gold library * and the PDF's ``altRgb``. Hosts that have a richer source of * truth (codex's ``summary.spot_colors.colors[].swatch_hex``, a * callas/PitStop preflight report, an internal swatch DB) pass * values here so the separations panel renders accurate swatches. */ spotPalette?: Record; /** Preflight findings to surface inside the viewer's Inspection * view. Same superset hosts pass to ````; * the built-in Tools panel renders the filtered/grouped list inline * when the user activates Inspection mode and lets them click a row * to focus the matching bbox on the canvas. */ items?: ReadonlyArray; /** The effective dieline for the loaded document (explicit `dieline` * prop, `dataConfig.codexSummary`-derived, or codex-client-derived). * Carries codex's multi-imprint breakdown in `regions[]` when present. * `null` when no dieline was detected. Lets shell plugins render a * dieline / imprints summary without re-deriving it. */ dieline?: import("../types").DielineResult | null; /** Currently-selected finding, if any. */ selectedItem?: import("../plugin").OverlayItem | null; /** Fires when the user clicks a finding row in the Inspection panel. */ onItemSelect?: (item: import("../plugin").OverlayItem | null) => void; /** Selects a finding (or clears with ``null``) and jumps to its page. * Works in both controlled and uncontrolled modes. Prefer this over * calling onItemSelect directly in shell plugins so the page navigation * is always handled. */ onSelectItem?: (item: import("../plugin").OverlayItem | null) => void; /** When true, render the Inspection panel even with no ``items`` * (panel shows a "no findings yet" empty state). Useful for hosts * that want a stable layout while a preflight call is in-flight, * or for demos that always advertise the panel slot. Default false * — hosts without preflight don't see an empty section. */ forceInspectionPanel?: boolean; enabledLayers: Set; setEnabledLayers: Dispatch>>; allLayerIndices: number[]; annotationTool: AnnotationTool; setAnnotationTool: Dispatch>; strokeColor: string; setStrokeColor: Dispatch>; savingAnnotation: boolean; canUndo: boolean; canRedo: boolean; triggerUndo: () => void; triggerRedo: () => void; indexedAnnotations: Array<{ number: number; pageNum: number; objectType: string; centerX: number; centerY: number; }>; selectedAnnotationId: string | null; setSelectedAnnotationId: Dispatch>; availability: LensPDFFeatureAvailability; /** Stable F1…FN number for every finding, keyed by item.id. * Separate from hand-drawn annotation numbering (#1, #2, …). */ findingNumbers: ReadonlyMap; /** Called when the user clicks an F# badge to open a linked note. */ onFindingNoteRequest?: (id: string) => void; /** When non-null, the Notes panel should select this target and * auto-create a blank linked note focused for typing. */ pendingNoteTarget?: string | null; /** Called by the Notes panel once it has consumed pendingNoteTarget. */ onPendingNoteConsumed?: () => void; /** Active decisions keyed by finding id (from lint-pdf decisions API). */ decisions?: Record; /** Fires when the user approves / waives / rejects a finding. */ onDecide?: (item: import("../plugin").OverlayItem, type: import("../plugin/types").DecisionType, notes?: string) => void; /** When true, spell-check findings are hidden from the Inspection panel. */ hideSpelling?: boolean; /** Toggles spell-check visibility. */ onToggleSpelling?: () => void; /** Set of finding ids whose canvas overlays + badges are hidden. * The Inspection panel reads/writes this via {@link setHiddenFindings} * to support per-finding visibility toggles + Show all / Hide all * bulk controls. Hidden findings still appear in the panel list * (greyed out) so the user can re-enable them. */ hiddenFindings: ReadonlySet; /** Setter for {@link hiddenFindings}. */ setHiddenFindings: Dispatch>>; } export type LensPDFShellSlot = "panel.left" | "overlay.toolbar" | "topbar"; /** * Declarative action button rendered inside the LensPDF tools menu * (the hamburger drawer on mobile / the persistent left sidebar on * desktop), pinned at the top above the plugin panels. * * Hosts pass an array of these via the `menuActions` prop on * `` to add navigation / utility buttons like * "Download PDF", "Back to demo", etc. without authoring a full * shell plugin. For richer needs (custom React, real-time state) * target the `panel.left` shell-plugin slot instead. */ export interface LensMenuAction { /** Stable identifier. Doubles as the React key. */ id: string; /** Visible text on the button. */ label: string; /** When set, renders as ``. One of `href` / `onClick` is required. */ href?: string; /** When set, renders as `