@printwithsynergy/artwork-pdf-editor 0.1.6 → 0.3.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/LICENSE +62 -0
- package/README.md +63 -2
- package/dist/components/AccessibilityHintsPanel.d.ts +142 -0
- package/dist/components/AccessibilityHintsPanel.d.ts.map +1 -0
- package/dist/components/AccessibilityHintsPanel.js +158 -0
- package/dist/components/AccessibilityHintsPanel.js.map +1 -0
- package/dist/components/AnnotationOverlay.d.ts +142 -0
- package/dist/components/AnnotationOverlay.d.ts.map +1 -0
- package/dist/components/AnnotationOverlay.js +141 -0
- package/dist/components/AnnotationOverlay.js.map +1 -0
- package/dist/components/AnnotationsSidebar.d.ts +98 -0
- package/dist/components/AnnotationsSidebar.d.ts.map +1 -0
- package/dist/components/AnnotationsSidebar.js +100 -0
- package/dist/components/AnnotationsSidebar.js.map +1 -0
- package/dist/components/BarcodeGeneratorPanel.d.ts +58 -0
- package/dist/components/BarcodeGeneratorPanel.d.ts.map +1 -0
- package/dist/components/BarcodeGeneratorPanel.js +91 -0
- package/dist/components/BarcodeGeneratorPanel.js.map +1 -0
- package/dist/components/BraillePanel.d.ts +99 -0
- package/dist/components/BraillePanel.d.ts.map +1 -0
- package/dist/components/BraillePanel.js +221 -0
- package/dist/components/BraillePanel.js.map +1 -0
- package/dist/components/BrandAssetsPanel.d.ts +130 -0
- package/dist/components/BrandAssetsPanel.d.ts.map +1 -0
- package/dist/components/BrandAssetsPanel.js +125 -0
- package/dist/components/BrandAssetsPanel.js.map +1 -0
- package/dist/components/BrandConsistencyPanel.d.ts +140 -0
- package/dist/components/BrandConsistencyPanel.d.ts.map +1 -0
- package/dist/components/BrandConsistencyPanel.js +158 -0
- package/dist/components/BrandConsistencyPanel.js.map +1 -0
- package/dist/components/ComplianceFindingsPanel.d.ts +62 -0
- package/dist/components/ComplianceFindingsPanel.d.ts.map +1 -0
- package/dist/components/ComplianceFindingsPanel.js +118 -0
- package/dist/components/ComplianceFindingsPanel.js.map +1 -0
- package/dist/components/DesignSuggestionsPanel.d.ts +148 -0
- package/dist/components/DesignSuggestionsPanel.d.ts.map +1 -0
- package/dist/components/DesignSuggestionsPanel.js +154 -0
- package/dist/components/DesignSuggestionsPanel.js.map +1 -0
- package/dist/components/DielineParametersPanel.d.ts +62 -0
- package/dist/components/DielineParametersPanel.d.ts.map +1 -0
- package/dist/components/DielineParametersPanel.js +170 -0
- package/dist/components/DielineParametersPanel.js.map +1 -0
- package/dist/components/DielinePreview.d.ts +150 -0
- package/dist/components/DielinePreview.d.ts.map +1 -0
- package/dist/components/DielinePreview.js +146 -0
- package/dist/components/DielinePreview.js.map +1 -0
- package/dist/components/EditorApp.d.ts +39 -5
- package/dist/components/EditorApp.d.ts.map +1 -1
- package/dist/components/EditorApp.js +110 -5
- package/dist/components/EditorApp.js.map +1 -1
- package/dist/components/EditorCanvas.d.ts +51 -2
- package/dist/components/EditorCanvas.d.ts.map +1 -1
- package/dist/components/EditorCanvas.js +117 -48
- package/dist/components/EditorCanvas.js.map +1 -1
- package/dist/components/EmailNotifyPanel.d.ts +165 -0
- package/dist/components/EmailNotifyPanel.d.ts.map +1 -0
- package/dist/components/EmailNotifyPanel.js +211 -0
- package/dist/components/EmailNotifyPanel.js.map +1 -0
- package/dist/components/FileDropZone.d.ts +9 -1
- package/dist/components/FileDropZone.d.ts.map +1 -1
- package/dist/components/FileDropZone.js +53 -5
- package/dist/components/FileDropZone.js.map +1 -1
- package/dist/components/FoldEditorPanel.d.ts +68 -0
- package/dist/components/FoldEditorPanel.d.ts.map +1 -0
- package/dist/components/FoldEditorPanel.js +65 -0
- package/dist/components/FoldEditorPanel.js.map +1 -0
- package/dist/components/FoldPreviewOverlay.d.ts +48 -0
- package/dist/components/FoldPreviewOverlay.d.ts.map +1 -0
- package/dist/components/FoldPreviewOverlay.js +182 -0
- package/dist/components/FoldPreviewOverlay.js.map +1 -0
- package/dist/components/Gs1DigitalLinkPanel.d.ts +103 -0
- package/dist/components/Gs1DigitalLinkPanel.d.ts.map +1 -0
- package/dist/components/Gs1DigitalLinkPanel.js +199 -0
- package/dist/components/Gs1DigitalLinkPanel.js.map +1 -0
- package/dist/components/HistoryPanel.d.ts +39 -0
- package/dist/components/HistoryPanel.d.ts.map +1 -0
- package/dist/components/HistoryPanel.js +72 -0
- package/dist/components/HistoryPanel.js.map +1 -0
- package/dist/components/IccSoftProofOverlay.d.ts +67 -0
- package/dist/components/IccSoftProofOverlay.d.ts.map +1 -0
- package/dist/components/IccSoftProofOverlay.js +119 -0
- package/dist/components/IccSoftProofOverlay.js.map +1 -0
- package/dist/components/ImposePanel.d.ts +71 -0
- package/dist/components/ImposePanel.d.ts.map +1 -0
- package/dist/components/ImposePanel.js +127 -0
- package/dist/components/ImposePanel.js.map +1 -0
- package/dist/components/InksPanel.d.ts +61 -0
- package/dist/components/InksPanel.d.ts.map +1 -0
- package/dist/components/InksPanel.js +84 -0
- package/dist/components/InksPanel.js.map +1 -0
- package/dist/components/JobSetupPanel.d.ts +118 -0
- package/dist/components/JobSetupPanel.d.ts.map +1 -0
- package/dist/components/JobSetupPanel.js +169 -0
- package/dist/components/JobSetupPanel.js.map +1 -0
- package/dist/components/LayersPanel.d.ts.map +1 -1
- package/dist/components/LayersPanel.js +1 -0
- package/dist/components/LayersPanel.js.map +1 -1
- package/dist/components/MarkLibraryPanel.d.ts +131 -0
- package/dist/components/MarkLibraryPanel.d.ts.map +1 -0
- package/dist/components/MarkLibraryPanel.js +184 -0
- package/dist/components/MarkLibraryPanel.js.map +1 -0
- package/dist/components/MisEstimateButton.d.ts +73 -0
- package/dist/components/MisEstimateButton.d.ts.map +1 -0
- package/dist/components/MisEstimateButton.js +57 -0
- package/dist/components/MisEstimateButton.js.map +1 -0
- package/dist/components/NutritionPanel.d.ts +118 -0
- package/dist/components/NutritionPanel.d.ts.map +1 -0
- package/dist/components/NutritionPanel.js +169 -0
- package/dist/components/NutritionPanel.js.map +1 -0
- package/dist/components/PageNavigator.d.ts +26 -0
- package/dist/components/PageNavigator.d.ts.map +1 -0
- package/dist/components/PageNavigator.js +96 -0
- package/dist/components/PageNavigator.js.map +1 -0
- package/dist/components/PaletteManager.d.ts +32 -0
- package/dist/components/PaletteManager.d.ts.map +1 -0
- package/dist/components/PaletteManager.js +89 -0
- package/dist/components/PaletteManager.js.map +1 -0
- package/dist/components/PaletteToSpotPanel.d.ts +122 -0
- package/dist/components/PaletteToSpotPanel.d.ts.map +1 -0
- package/dist/components/PaletteToSpotPanel.js +160 -0
- package/dist/components/PaletteToSpotPanel.js.map +1 -0
- package/dist/components/PreflightAutoFixPanel.d.ts +110 -0
- package/dist/components/PreflightAutoFixPanel.d.ts.map +1 -0
- package/dist/components/PreflightAutoFixPanel.js +119 -0
- package/dist/components/PreflightAutoFixPanel.js.map +1 -0
- package/dist/components/PreflightDiffPanel.d.ts +127 -0
- package/dist/components/PreflightDiffPanel.d.ts.map +1 -0
- package/dist/components/PreflightDiffPanel.js +0 -0
- package/dist/components/PreflightDiffPanel.js.map +1 -0
- package/dist/components/ProcessRulesPanel.d.ts +81 -0
- package/dist/components/ProcessRulesPanel.d.ts.map +1 -0
- package/dist/components/ProcessRulesPanel.js +143 -0
- package/dist/components/ProcessRulesPanel.js.map +1 -0
- package/dist/components/SlackNotifyPanel.d.ts +139 -0
- package/dist/components/SlackNotifyPanel.d.ts.map +1 -0
- package/dist/components/SlackNotifyPanel.js +133 -0
- package/dist/components/SlackNotifyPanel.js.map +1 -0
- package/dist/components/SmartSpotMatchPanel.d.ts +143 -0
- package/dist/components/SmartSpotMatchPanel.d.ts.map +1 -0
- package/dist/components/SmartSpotMatchPanel.js +159 -0
- package/dist/components/SmartSpotMatchPanel.js.map +1 -0
- package/dist/components/SwatchesPicker.d.ts +83 -0
- package/dist/components/SwatchesPicker.d.ts.map +1 -0
- package/dist/components/SwatchesPicker.js +151 -0
- package/dist/components/SwatchesPicker.js.map +1 -0
- package/dist/components/TacOverlay.d.ts +47 -0
- package/dist/components/TacOverlay.d.ts.map +1 -0
- package/dist/components/TacOverlay.js +116 -0
- package/dist/components/TacOverlay.js.map +1 -0
- package/dist/components/TrapEditorPanel.d.ts +52 -0
- package/dist/components/TrapEditorPanel.d.ts.map +1 -0
- package/dist/components/TrapEditorPanel.js +64 -0
- package/dist/components/TrapEditorPanel.js.map +1 -0
- package/dist/components/TrapPreviewOverlay.d.ts +64 -0
- package/dist/components/TrapPreviewOverlay.d.ts.map +1 -0
- package/dist/components/TrapPreviewOverlay.js +120 -0
- package/dist/components/TrapPreviewOverlay.js.map +1 -0
- package/dist/components/VariantMatrixPanel.d.ts +61 -0
- package/dist/components/VariantMatrixPanel.d.ts.map +1 -0
- package/dist/components/VariantMatrixPanel.js +97 -0
- package/dist/components/VariantMatrixPanel.js.map +1 -0
- package/dist/components/VariantMatrixVersionPanel.d.ts +122 -0
- package/dist/components/VariantMatrixVersionPanel.d.ts.map +1 -0
- package/dist/components/VariantMatrixVersionPanel.js +162 -0
- package/dist/components/VariantMatrixVersionPanel.js.map +1 -0
- package/dist/components/WebhookNotifyPanel.d.ts +160 -0
- package/dist/components/WebhookNotifyPanel.d.ts.map +1 -0
- package/dist/components/WebhookNotifyPanel.js +100 -0
- package/dist/components/WebhookNotifyPanel.js.map +1 -0
- package/dist/components/WhiteUnderbasePanel.d.ts +107 -0
- package/dist/components/WhiteUnderbasePanel.d.ts.map +1 -0
- package/dist/components/WhiteUnderbasePanel.js +104 -0
- package/dist/components/WhiteUnderbasePanel.js.map +1 -0
- package/dist/data/dielines.json +35 -0
- package/dist/hooks/useEditorMode.d.ts +25 -5
- package/dist/hooks/useEditorMode.d.ts.map +1 -1
- package/dist/hooks/useEditorMode.js +18 -5
- package/dist/hooks/useEditorMode.js.map +1 -1
- package/dist/index.d.ts +49 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -2
- package/dist/index.js.map +1 -1
- package/dist/lens/dieline-overlay.d.ts +25 -0
- package/dist/lens/dieline-overlay.d.ts.map +1 -0
- package/dist/lens/dieline-overlay.js +50 -0
- package/dist/lens/dieline-overlay.js.map +1 -0
- package/dist/lens/index.d.ts +27 -0
- package/dist/lens/index.d.ts.map +1 -0
- package/dist/lens/index.js +28 -0
- package/dist/lens/index.js.map +1 -0
- package/dist/lens/preflight-findings.d.ts +21 -0
- package/dist/lens/preflight-findings.d.ts.map +1 -0
- package/dist/lens/preflight-findings.js +82 -0
- package/dist/lens/preflight-findings.js.map +1 -0
- package/dist/lib/barcode-scan.d.ts +154 -0
- package/dist/lib/barcode-scan.d.ts.map +1 -0
- package/dist/lib/barcode-scan.js +152 -0
- package/dist/lib/barcode-scan.js.map +1 -0
- package/dist/lib/color-math.d.ts +76 -0
- package/dist/lib/color-math.d.ts.map +1 -0
- package/dist/lib/color-math.js +96 -0
- package/dist/lib/color-math.js.map +1 -0
- package/dist/lib/dieline-template.d.ts +169 -0
- package/dist/lib/dieline-template.d.ts.map +1 -1
- package/dist/lib/dieline-template.js +229 -1
- package/dist/lib/dieline-template.js.map +1 -1
- package/dist/lib/editor-config.d.ts +384 -1
- package/dist/lib/editor-config.d.ts.map +1 -1
- package/dist/lib/editor-config.js +89 -2
- package/dist/lib/editor-config.js.map +1 -1
- package/dist/lib/fold-geometry.d.ts +144 -0
- package/dist/lib/fold-geometry.d.ts.map +1 -0
- package/dist/lib/fold-geometry.js +138 -0
- package/dist/lib/fold-geometry.js.map +1 -0
- package/dist/lib/merge-tokens.d.ts +81 -0
- package/dist/lib/merge-tokens.d.ts.map +1 -0
- package/dist/lib/merge-tokens.js +88 -0
- package/dist/lib/merge-tokens.js.map +1 -0
- package/dist/lib/palette-registry.d.ts +40 -0
- package/dist/lib/palette-registry.d.ts.map +1 -0
- package/dist/lib/palette-registry.js +49 -0
- package/dist/lib/palette-registry.js.map +1 -0
- package/dist/lib/panel-anchor.d.ts +101 -0
- package/dist/lib/panel-anchor.d.ts.map +1 -0
- package/dist/lib/panel-anchor.js +68 -0
- package/dist/lib/panel-anchor.js.map +1 -0
- package/dist/lib/preflight/checks.d.ts.map +1 -1
- package/dist/lib/preflight/checks.js +71 -0
- package/dist/lib/preflight/checks.js.map +1 -1
- package/dist/lib/preflight/types.d.ts.map +1 -1
- package/dist/lib/preflight/types.js +11 -0
- package/dist/lib/preflight/types.js.map +1 -1
- package/dist/lib/rasterize.d.ts +93 -0
- package/dist/lib/rasterize.d.ts.map +1 -0
- package/dist/lib/rasterize.js +117 -0
- package/dist/lib/rasterize.js.map +1 -0
- package/dist/lib/separations-registry.d.ts +99 -0
- package/dist/lib/separations-registry.d.ts.map +1 -0
- package/dist/lib/separations-registry.js +59 -0
- package/dist/lib/separations-registry.js.map +1 -0
- package/dist/lib/unwired.d.ts +29 -0
- package/dist/lib/unwired.d.ts.map +1 -0
- package/dist/lib/unwired.js +58 -0
- package/dist/lib/unwired.js.map +1 -0
- package/package.json +29 -11
- package/dist/components/SeparationsPanel.d.ts +0 -9
- package/dist/components/SeparationsPanel.d.ts.map +0 -1
- package/dist/components/SeparationsPanel.js +0 -168
- package/dist/components/SeparationsPanel.js.map +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One PANTONE catalogue entry from compile-pdf's `/v1/spots/*`
|
|
3
|
+
* endpoints. Mirrors `SpotEntry` on the apps/service
|
|
4
|
+
* `CompilePdfClient`, kept structural here so editor-app stays
|
|
5
|
+
* apps/service-dep-free.
|
|
6
|
+
*
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export type Spot = {
|
|
10
|
+
name: string;
|
|
11
|
+
library?: string | null;
|
|
12
|
+
lab?: [number, number, number] | null;
|
|
13
|
+
cmyk_bridge?: [number, number, number, number] | null;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Search adapter — the editor passes in a function that fronts
|
|
17
|
+
* `CompilePdfClient.spotSearch()`. Threading the search via a prop
|
|
18
|
+
* (rather than calling fetch directly) keeps SwatchesPicker
|
|
19
|
+
* decoupled from the network — tests pass a stub, the demo can
|
|
20
|
+
* preload an in-memory fixture, etc.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export type SpotSearchFn = (opts: {
|
|
25
|
+
q?: string;
|
|
26
|
+
library?: string;
|
|
27
|
+
limit?: number;
|
|
28
|
+
}) => Promise<{
|
|
29
|
+
results: Spot[];
|
|
30
|
+
total: number;
|
|
31
|
+
limit: number;
|
|
32
|
+
}>;
|
|
33
|
+
/**
|
|
34
|
+
* Library descriptor — matches the wire shape of one entry in
|
|
35
|
+
* `/v1/spots/libraries`.
|
|
36
|
+
*
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export type SpotLibrary = {
|
|
40
|
+
id: string;
|
|
41
|
+
count: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* Props for the C3 SwatchesPicker palette.
|
|
45
|
+
*
|
|
46
|
+
* `search` is the only required prop; library filter + initial
|
|
47
|
+
* query are optional. `onSelect` fires when the user clicks a
|
|
48
|
+
* swatch — typically wired to AI4's `registerSpot` in the host.
|
|
49
|
+
*
|
|
50
|
+
* `enable_palettes: false` collapses the entire palette system off;
|
|
51
|
+
* hosts mount this component only when `isPanelVisible(config,
|
|
52
|
+
* "swatches")` returns true.
|
|
53
|
+
*
|
|
54
|
+
* @public
|
|
55
|
+
*/
|
|
56
|
+
export type SwatchesPickerProps = {
|
|
57
|
+
search: SpotSearchFn;
|
|
58
|
+
/** Initial libraries-filter dropdown values. Hosts that already
|
|
59
|
+
* fetched `spotLibraries()` thread the result here. */
|
|
60
|
+
libraries?: SpotLibrary[];
|
|
61
|
+
/** Optional initial query. */
|
|
62
|
+
initialQuery?: string;
|
|
63
|
+
/** Click callback. Receives the full Spot row. */
|
|
64
|
+
onSelect: (spot: Spot) => void;
|
|
65
|
+
};
|
|
66
|
+
/**
|
|
67
|
+
* Right-rail palette for browsing compile-pdf's PANTONE catalogue
|
|
68
|
+
* (codex-pdf's public-domain reference set).
|
|
69
|
+
*
|
|
70
|
+
* UX:
|
|
71
|
+
* - Search input → debounced (250 ms) call to `search()`.
|
|
72
|
+
* - Optional library dropdown (when `libraries` is supplied).
|
|
73
|
+
* - Result list as colored chips with the canonical name; click
|
|
74
|
+
* fires `onSelect`.
|
|
75
|
+
* - Footer disclaimer ("public-domain reference, not licensed
|
|
76
|
+
* PANTONE data") — present per the trademark stance.
|
|
77
|
+
*
|
|
78
|
+
* @returns An `<aside>` element with search input, library filter,
|
|
79
|
+
* results list, and the trademark disclaimer footer.
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
export declare function SwatchesPicker({ search, libraries, initialQuery, onSelect, }: SwatchesPickerProps): import("react/jsx-runtime").JSX.Element;
|
|
83
|
+
//# sourceMappingURL=SwatchesPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwatchesPicker.d.ts","sourceRoot":"","sources":["../../src/components/SwatchesPicker.tsx"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,MAAM,MAAM,IAAI,GAAG;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;IACtC,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CAAC;CACvD,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE;IAChC,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,KAAK,OAAO,CAAC;IAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,MAAM,EAAE,YAAY,CAAC;IACrB;4DACwD;IACxD,SAAS,CAAC,EAAE,WAAW,EAAE,CAAC;IAC1B,8BAA8B;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kDAAkD;IAClD,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChC,CAAC;AAoBF;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAAC,EAC7B,MAAM,EACN,SAAS,EACT,YAAiB,EACjB,QAAQ,GACT,EAAE,mBAAmB,2CAuKrB"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
|
+
const PANEL_BG = "#1a0f08";
|
|
6
|
+
const BORDER = "#3d1a00";
|
|
7
|
+
const BRAND = "#fc5102";
|
|
8
|
+
const TEXT = "#f4ece6";
|
|
9
|
+
const MUTED = "#888";
|
|
10
|
+
const DEBOUNCE_MS = 250;
|
|
11
|
+
const inputStyle = {
|
|
12
|
+
flex: 1,
|
|
13
|
+
padding: "0.4rem 0.6rem",
|
|
14
|
+
background: "#0f0a05",
|
|
15
|
+
border: `1px solid ${BORDER}`,
|
|
16
|
+
borderRadius: 4,
|
|
17
|
+
color: TEXT,
|
|
18
|
+
fontSize: "0.8rem",
|
|
19
|
+
fontFamily: "inherit",
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Right-rail palette for browsing compile-pdf's PANTONE catalogue
|
|
23
|
+
* (codex-pdf's public-domain reference set).
|
|
24
|
+
*
|
|
25
|
+
* UX:
|
|
26
|
+
* - Search input → debounced (250 ms) call to `search()`.
|
|
27
|
+
* - Optional library dropdown (when `libraries` is supplied).
|
|
28
|
+
* - Result list as colored chips with the canonical name; click
|
|
29
|
+
* fires `onSelect`.
|
|
30
|
+
* - Footer disclaimer ("public-domain reference, not licensed
|
|
31
|
+
* PANTONE data") — present per the trademark stance.
|
|
32
|
+
*
|
|
33
|
+
* @returns An `<aside>` element with search input, library filter,
|
|
34
|
+
* results list, and the trademark disclaimer footer.
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export function SwatchesPicker({ search, libraries, initialQuery = "", onSelect, }) {
|
|
38
|
+
const [query, setQuery] = useState(initialQuery);
|
|
39
|
+
const [library, setLibrary] = useState("");
|
|
40
|
+
const [results, setResults] = useState([]);
|
|
41
|
+
const [loading, setLoading] = useState(false);
|
|
42
|
+
const [error, setError] = useState(null);
|
|
43
|
+
const reqIdRef = useRef(0);
|
|
44
|
+
useEffect(() => {
|
|
45
|
+
// Debounce — bump the request id and only commit results from
|
|
46
|
+
// the latest call. Prevents stale results overriding fresh ones
|
|
47
|
+
// when the user types quickly.
|
|
48
|
+
const id = ++reqIdRef.current;
|
|
49
|
+
const handle = setTimeout(() => {
|
|
50
|
+
setLoading(true);
|
|
51
|
+
setError(null);
|
|
52
|
+
const opts = { limit: 50 };
|
|
53
|
+
if (query)
|
|
54
|
+
opts.q = query;
|
|
55
|
+
if (library)
|
|
56
|
+
opts.library = library;
|
|
57
|
+
search(opts)
|
|
58
|
+
.then((res) => {
|
|
59
|
+
if (id !== reqIdRef.current)
|
|
60
|
+
return; // stale
|
|
61
|
+
setResults(res.results);
|
|
62
|
+
setLoading(false);
|
|
63
|
+
})
|
|
64
|
+
.catch((err) => {
|
|
65
|
+
if (id !== reqIdRef.current)
|
|
66
|
+
return;
|
|
67
|
+
const msg = err instanceof Error ? err.message : "spots search failed";
|
|
68
|
+
setError(msg);
|
|
69
|
+
setLoading(false);
|
|
70
|
+
});
|
|
71
|
+
}, DEBOUNCE_MS);
|
|
72
|
+
return () => clearTimeout(handle);
|
|
73
|
+
}, [query, library, search]);
|
|
74
|
+
return (_jsxs("aside", { style: {
|
|
75
|
+
width: 240,
|
|
76
|
+
background: PANEL_BG,
|
|
77
|
+
borderLeft: `1px solid ${BORDER}`,
|
|
78
|
+
color: TEXT,
|
|
79
|
+
display: "flex",
|
|
80
|
+
flexDirection: "column",
|
|
81
|
+
overflow: "hidden",
|
|
82
|
+
flexShrink: 0,
|
|
83
|
+
}, children: [_jsx("div", { style: {
|
|
84
|
+
fontSize: "0.7rem",
|
|
85
|
+
letterSpacing: "0.08em",
|
|
86
|
+
textTransform: "uppercase",
|
|
87
|
+
color: MUTED,
|
|
88
|
+
padding: "0.55rem 0.85rem",
|
|
89
|
+
borderBottom: `1px solid ${BORDER}`,
|
|
90
|
+
}, children: "Swatches" }), _jsx("div", { style: { padding: "0.55rem 0.65rem", display: "flex", gap: "0.4rem" }, children: _jsx("input", { value: query, onChange: (e) => setQuery(e.target.value), placeholder: "Search PANTONE\u2026", "aria-label": "Search PANTONE catalogue", style: inputStyle }) }), libraries && libraries.length > 0 && (_jsx("div", { style: { padding: "0 0.65rem 0.55rem" }, children: _jsxs("select", { value: library, onChange: (e) => setLibrary(e.target.value), "aria-label": "Filter by library", style: { ...inputStyle, width: "100%" }, children: [_jsx("option", { value: "", children: "All libraries" }), libraries.map((lib) => (_jsxs("option", { value: lib.id, children: [lib.id, " (", lib.count, ")"] }, lib.id)))] }) })), _jsxs("div", { style: { flex: 1, overflow: "auto" }, children: [loading && (_jsx("div", { style: { padding: "0.55rem 0.85rem", color: MUTED, fontSize: "0.78rem" }, children: "Loading\u2026" })), error && !loading && (_jsx("div", { role: "alert", style: { padding: "0.55rem 0.85rem", color: "#ef4444", fontSize: "0.78rem" }, children: error })), !loading && !error && results.length === 0 && (_jsx("div", { style: { padding: "0.55rem 0.85rem", color: MUTED, fontSize: "0.78rem" }, children: "No matches." })), !loading &&
|
|
91
|
+
!error &&
|
|
92
|
+
results.map((spot) => {
|
|
93
|
+
const swatchColor = labToCssApprox(spot.lab) ?? "#666";
|
|
94
|
+
return (_jsxs("button", { type: "button", onClick: () => onSelect(spot), style: {
|
|
95
|
+
display: "flex",
|
|
96
|
+
alignItems: "center",
|
|
97
|
+
gap: "0.55rem",
|
|
98
|
+
width: "100%",
|
|
99
|
+
padding: "0.35rem 0.85rem",
|
|
100
|
+
background: "transparent",
|
|
101
|
+
border: "none",
|
|
102
|
+
borderLeft: "2px solid transparent",
|
|
103
|
+
cursor: "pointer",
|
|
104
|
+
color: TEXT,
|
|
105
|
+
fontSize: "0.78rem",
|
|
106
|
+
fontFamily: "inherit",
|
|
107
|
+
textAlign: "left",
|
|
108
|
+
}, onMouseEnter: (e) => {
|
|
109
|
+
e.currentTarget.style.borderLeftColor = BRAND;
|
|
110
|
+
}, onMouseLeave: (e) => {
|
|
111
|
+
e.currentTarget.style.borderLeftColor = "transparent";
|
|
112
|
+
}, children: [_jsx("span", { style: {
|
|
113
|
+
display: "inline-block",
|
|
114
|
+
width: 16,
|
|
115
|
+
height: 16,
|
|
116
|
+
borderRadius: 3,
|
|
117
|
+
background: swatchColor,
|
|
118
|
+
border: `1px solid ${BORDER}`,
|
|
119
|
+
flexShrink: 0,
|
|
120
|
+
} }), _jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: spot.name })] }, spot.name));
|
|
121
|
+
})] }), _jsx("div", { style: {
|
|
122
|
+
padding: "0.45rem 0.85rem",
|
|
123
|
+
borderTop: `1px solid ${BORDER}`,
|
|
124
|
+
color: MUTED,
|
|
125
|
+
fontSize: "0.65rem",
|
|
126
|
+
lineHeight: 1.35,
|
|
127
|
+
}, children: "Public-domain colour-science reference. Not licensed PANTONE data." })] }));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Crude Lab → CSS-color approximation for the swatch chips. Not a
|
|
131
|
+
* colorimetric conversion — just enough to give each row a
|
|
132
|
+
* recognizable tint in the picker. Returns `undefined` for entries
|
|
133
|
+
* without a Lab triplet (the chip falls back to a neutral grey).
|
|
134
|
+
*
|
|
135
|
+
* Lab L is 0-100 (perceptual lightness); we map directly to sRGB
|
|
136
|
+
* grey then shift slightly toward a/b axes. Future: replace with a
|
|
137
|
+
* proper Lab→sRGB conversion via culori or chroma-js if perceptual
|
|
138
|
+
* accuracy matters for the picker.
|
|
139
|
+
*/
|
|
140
|
+
function labToCssApprox(lab) {
|
|
141
|
+
if (!lab)
|
|
142
|
+
return undefined;
|
|
143
|
+
const [L, a, b] = lab;
|
|
144
|
+
// Very rough — clamps to a tinted grey based on a/b sign.
|
|
145
|
+
const lum = Math.max(0, Math.min(255, Math.round((L / 100) * 255)));
|
|
146
|
+
const r = Math.max(0, Math.min(255, lum + Math.round(a * 1.5)));
|
|
147
|
+
const g = Math.max(0, Math.min(255, lum - Math.round(Math.abs(a) * 0.5)));
|
|
148
|
+
const bl = Math.max(0, Math.min(255, lum - Math.round(b * 1.5)));
|
|
149
|
+
return `rgb(${r}, ${g}, ${bl})`;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=SwatchesPicker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SwatchesPicker.js","sourceRoot":"","sources":["../../src/components/SwatchesPicker.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type Konva from "konva";
|
|
2
|
+
/**
|
|
3
|
+
* C4 live total-area-coverage overlay.
|
|
4
|
+
*
|
|
5
|
+
* Sits as an absolutely-positioned `<canvas>` on top of the Konva
|
|
6
|
+
* Stage, debouncing a rasterize-and-sample pass on every change to
|
|
7
|
+
* the watched objects array. Paints pixels whose TAC exceeds the
|
|
8
|
+
* configured threshold (default 300%) in translucent red — a "where
|
|
9
|
+
* the ink is going to pool" hint — and shows a `max / avg` chip in
|
|
10
|
+
* the bottom-left.
|
|
11
|
+
*
|
|
12
|
+
* Browser-side sanity check, not a colorimetric proof: the same
|
|
13
|
+
* caveats as {@link import("../lib/rasterize").sampleTACFromImageData}
|
|
14
|
+
* apply (subtractive sRGB → CMYK with K-extraction, alpha composited
|
|
15
|
+
* onto an opaque white background). Production TAC enforcement lives
|
|
16
|
+
* server-side in compile-pdf's `total_ink_coverage` preflight rule.
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
export type TacOverlayProps = {
|
|
21
|
+
/** Live Konva Stage. The overlay no-ops while this is `null` (the
|
|
22
|
+
* ref starts null on first render). */
|
|
23
|
+
stage: Konva.Stage | null;
|
|
24
|
+
/** Container width/height in CSS pixels — the overlay canvas
|
|
25
|
+
* matches these so it lines up with the Stage. */
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
/** Re-sample trigger. Any change to this value (by reference for
|
|
29
|
+
* arrays, by equality for primitives) debounces a new rasterize
|
|
30
|
+
* pass. The value itself isn't read — it just lets React's effect
|
|
31
|
+
* diffing detect editor changes. Pass `objects` (the canvas
|
|
32
|
+
* contents array) so every commit re-samples. */
|
|
33
|
+
trigger: unknown;
|
|
34
|
+
/** TAC threshold in percent (0-400). Pixels at or above the
|
|
35
|
+
* threshold are painted; pixels below are transparent. Defaults to
|
|
36
|
+
* 300% — the standard coated-stock preflight ceiling. */
|
|
37
|
+
thresholdPct?: number;
|
|
38
|
+
/** Debounce window in milliseconds before a new sample fires.
|
|
39
|
+
* Defaults to 250 ms — fast enough to feel live, slow enough that
|
|
40
|
+
* click-drag operations don't thrash the rasterizer. */
|
|
41
|
+
debounceMs?: number;
|
|
42
|
+
};
|
|
43
|
+
/**
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare function TacOverlay({ stage, width, height, trigger, thresholdPct, debounceMs, }: TacOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
//# sourceMappingURL=TacOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TacOverlay.d.ts","sourceRoot":"","sources":["../../src/components/TacOverlay.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B;4CACwC;IACxC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;IAC1B;uDACmD;IACnD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf;;;;sDAIkD;IAClD,OAAO,EAAE,OAAO,CAAC;IACjB;;8DAE0D;IAC1D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;6DAEyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;GAEG;AACH,wBAAgB,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,YAAkB,EAClB,UAAgB,GACjB,EAAE,eAAe,2CA0HjB"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
4
|
+
import { useEffect, useRef, useState } from "react";
|
|
5
|
+
import { rasterizeStage } from "../lib/rasterize";
|
|
6
|
+
/**
|
|
7
|
+
* @public
|
|
8
|
+
*/
|
|
9
|
+
export function TacOverlay({ stage, width, height, trigger, thresholdPct = 300, debounceMs = 250, }) {
|
|
10
|
+
const canvasRef = useRef(null);
|
|
11
|
+
const [readout, setReadout] = useState(null);
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
// `trigger` is intentionally read here (no-op `void` cast) so the
|
|
14
|
+
// exhaustive-deps lint sees it as used; the actual value is never
|
|
15
|
+
// consumed — only its identity change is meaningful.
|
|
16
|
+
void trigger;
|
|
17
|
+
if (!stage || width <= 0 || height <= 0) {
|
|
18
|
+
setReadout(null);
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
const handle = setTimeout(() => {
|
|
22
|
+
let image;
|
|
23
|
+
try {
|
|
24
|
+
image = rasterizeStage(stage);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
// Stage's 2d context occasionally fails to acquire during
|
|
28
|
+
// teardown (unmount race); silently skip — next change will
|
|
29
|
+
// try again.
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
const canvas = canvasRef.current;
|
|
33
|
+
if (!canvas)
|
|
34
|
+
return;
|
|
35
|
+
// Match the source image so writes are 1:1 — the canvas CSS
|
|
36
|
+
// size is what scales it back to the displayed Stage area.
|
|
37
|
+
canvas.width = image.width;
|
|
38
|
+
canvas.height = image.height;
|
|
39
|
+
const ctx = canvas.getContext("2d");
|
|
40
|
+
if (!ctx)
|
|
41
|
+
return;
|
|
42
|
+
// One fused pass: sample TAC per pixel inline AND paint the
|
|
43
|
+
// overlay where TAC crosses the threshold. We can't reuse the
|
|
44
|
+
// shared sampler's `perPixelPct` for the threshold check
|
|
45
|
+
// because that array clamps the 0-400 % range to a byte
|
|
46
|
+
// (255 = ≥255 %), which collapses every pixel above the
|
|
47
|
+
// default 300 % threshold to a single bucket; honest threshold
|
|
48
|
+
// checks need the un-truncated percentage here.
|
|
49
|
+
const src = image.data;
|
|
50
|
+
const overlay = ctx.createImageData(image.width, image.height);
|
|
51
|
+
const dst = overlay.data;
|
|
52
|
+
const pixelCount = image.width * image.height;
|
|
53
|
+
let maxPct = 0;
|
|
54
|
+
let sumPct = 0;
|
|
55
|
+
for (let p = 0, i = 0; p < src.length; p += 4, i++) {
|
|
56
|
+
// Pre-multiply with opaque white background so semi-
|
|
57
|
+
// transparent pixels reflect printable ink. Mirrors the
|
|
58
|
+
// canonical sampler's composite step.
|
|
59
|
+
const a = (src[p + 3] ?? 255) / 255;
|
|
60
|
+
const inv = 1 - a;
|
|
61
|
+
const r = ((src[p] ?? 0) * a + 255 * inv) / 255;
|
|
62
|
+
const g = ((src[p + 1] ?? 0) * a + 255 * inv) / 255;
|
|
63
|
+
const b = ((src[p + 2] ?? 0) * a + 255 * inv) / 255;
|
|
64
|
+
const k = 1 - Math.max(r, g, b);
|
|
65
|
+
let c = 0;
|
|
66
|
+
let m = 0;
|
|
67
|
+
let y = 0;
|
|
68
|
+
if (k < 1) {
|
|
69
|
+
const scale = 1 - k;
|
|
70
|
+
c = (1 - r - k) / scale;
|
|
71
|
+
m = (1 - g - k) / scale;
|
|
72
|
+
y = (1 - b - k) / scale;
|
|
73
|
+
}
|
|
74
|
+
const tac = (c + m + y + k) * 100;
|
|
75
|
+
if (tac > maxPct)
|
|
76
|
+
maxPct = tac;
|
|
77
|
+
sumPct += tac;
|
|
78
|
+
if (tac >= thresholdPct) {
|
|
79
|
+
const j = i * 4;
|
|
80
|
+
dst[j] = 220; // R
|
|
81
|
+
dst[j + 1] = 38; // G
|
|
82
|
+
dst[j + 2] = 38; // B
|
|
83
|
+
// Alpha scales linearly from 64 at threshold to 192 at
|
|
84
|
+
// (threshold + 100 %), so a 305 % pixel barely glows but
|
|
85
|
+
// a 400 % pixel screams. Clamped to keep the red readable
|
|
86
|
+
// over busy artwork.
|
|
87
|
+
const intensity = Math.min(192, 64 + (tac - thresholdPct) * 1.28);
|
|
88
|
+
dst[j + 3] = intensity;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
ctx.putImageData(overlay, 0, 0);
|
|
92
|
+
setReadout({ maxPct, avgPct: pixelCount > 0 ? sumPct / pixelCount : 0 });
|
|
93
|
+
}, debounceMs);
|
|
94
|
+
return () => clearTimeout(handle);
|
|
95
|
+
}, [stage, width, height, trigger, thresholdPct, debounceMs]);
|
|
96
|
+
return (_jsxs(_Fragment, { children: [_jsx("canvas", { ref: canvasRef, style: {
|
|
97
|
+
position: "absolute",
|
|
98
|
+
inset: 0,
|
|
99
|
+
width: `${width}px`,
|
|
100
|
+
height: `${height}px`,
|
|
101
|
+
pointerEvents: "none",
|
|
102
|
+
} }), readout !== null && (_jsxs("output", { "aria-label": "Total area coverage", style: {
|
|
103
|
+
position: "absolute",
|
|
104
|
+
bottom: 8,
|
|
105
|
+
left: 8,
|
|
106
|
+
padding: "0.25rem 0.5rem",
|
|
107
|
+
background: "rgba(15, 23, 42, 0.78)",
|
|
108
|
+
color: "#f8fafc",
|
|
109
|
+
fontSize: "0.7rem",
|
|
110
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
111
|
+
borderRadius: 4,
|
|
112
|
+
pointerEvents: "none",
|
|
113
|
+
lineHeight: 1.3,
|
|
114
|
+
}, children: [_jsxs("div", { children: ["TAC max ", readout.maxPct.toFixed(0), "%"] }), _jsxs("div", { style: { opacity: 0.75 }, children: ["avg ", readout.avgPct.toFixed(0), "%"] })] }))] }));
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=TacOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TacOverlay.js","sourceRoot":"","sources":["../../src/components/TacOverlay.tsx"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;;AAGb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AA4ClD;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,EACzB,KAAK,EACL,KAAK,EACL,MAAM,EACN,OAAO,EACP,YAAY,GAAG,GAAG,EAClB,UAAU,GAAG,GAAG,GACA;IAChB,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAA4C,IAAI,CAAC,CAAC;IAExF,SAAS,CAAC,GAAG,EAAE;QACb,kEAAkE;QAClE,kEAAkE;QAClE,qDAAqD;QACrD,KAAK,OAAO,CAAC;QACb,IAAI,CAAC,KAAK,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YACxC,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,OAAO;QACT,CAAC;QACD,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,IAAI,KAAgB,CAAC;YACrB,IAAI,CAAC;gBACH,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,0DAA0D;gBAC1D,4DAA4D;gBAC5D,aAAa;gBACb,OAAO;YACT,CAAC;YAED,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;YACjC,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,4DAA4D;YAC5D,2DAA2D;YAC3D,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;YAC3B,MAAM,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG;gBAAE,OAAO;YAEjB,4DAA4D;YAC5D,8DAA8D;YAC9D,yDAAyD;YACzD,wDAAwD;YACxD,wDAAwD;YACxD,+DAA+D;YAC/D,gDAAgD;YAChD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC;YACvB,MAAM,OAAO,GAAG,GAAG,CAAC,eAAe,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YAC/D,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;YACzB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;YAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBACnD,qDAAqD;gBACrD,wDAAwD;gBACxD,sCAAsC;gBACtC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,CAAC;gBACpC,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;gBAClB,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;gBAChD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;gBACpD,MAAM,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;gBACpD,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChC,IAAI,CAAC,GAAG,CAAC,CAAC;gBACV,IAAI,CAAC,GAAG,CAAC,CAAC;gBACV,IAAI,CAAC,GAAG,CAAC,CAAC;gBACV,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;oBACV,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC;oBACpB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;oBACxB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;oBACxB,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;gBAC1B,CAAC;gBACD,MAAM,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC;gBAClC,IAAI,GAAG,GAAG,MAAM;oBAAE,MAAM,GAAG,GAAG,CAAC;gBAC/B,MAAM,IAAI,GAAG,CAAC;gBACd,IAAI,GAAG,IAAI,YAAY,EAAE,CAAC;oBACxB,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;oBAChB,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI;oBAClB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI;oBACrB,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI;oBACrB,uDAAuD;oBACvD,yDAAyD;oBACzD,0DAA0D;oBAC1D,qBAAqB;oBACrB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,GAAG,GAAG,YAAY,CAAC,GAAG,IAAI,CAAC,CAAC;oBAClE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,SAAS,CAAC;gBACzB,CAAC;YACH,CAAC;YACD,GAAG,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAChC,UAAU,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC,CAAC;IAE9D,OAAO,CACL,8BACE,iBACE,GAAG,EAAE,SAAS,EACd,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,KAAK,EAAE,CAAC;oBACR,KAAK,EAAE,GAAG,KAAK,IAAI;oBACnB,MAAM,EAAE,GAAG,MAAM,IAAI;oBACrB,aAAa,EAAE,MAAM;iBACtB,GACD,EACD,OAAO,KAAK,IAAI,IAAI,CACnB,gCACa,qBAAqB,EAChC,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,MAAM,EAAE,CAAC;oBACT,IAAI,EAAE,CAAC;oBACP,OAAO,EAAE,gBAAgB;oBACzB,UAAU,EAAE,wBAAwB;oBACpC,KAAK,EAAE,SAAS;oBAChB,QAAQ,EAAE,QAAQ;oBAClB,UAAU,EAAE,gDAAgD;oBAC5D,YAAY,EAAE,CAAC;oBACf,aAAa,EAAE,MAAM;oBACrB,UAAU,EAAE,GAAG;iBAChB,aAED,sCAAc,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAQ,EAC/C,eAAK,KAAK,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,qBAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAQ,IAC9D,CACV,IACA,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Controlled trap-policy shape consumed by the editor. Mirrors
|
|
3
|
+
* `@artworkpdf/document-model`'s `TrapPolicy` minus the runtime dep
|
|
4
|
+
* (the published editor package can't pull in document-model). Keep
|
|
5
|
+
* these in sync; the future structural-dedup follow-up will move both
|
|
6
|
+
* into a shared types module.
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export type TrapEditorValue = {
|
|
11
|
+
widthMm: number;
|
|
12
|
+
mode?: "auto" | "spread" | "choke";
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export type TrapEditorPanelProps = {
|
|
18
|
+
/** Current policy. `undefined` means "no trap policy set" — the
|
|
19
|
+
* panel renders empty defaults the user can fill in. */
|
|
20
|
+
value: TrapEditorValue | undefined;
|
|
21
|
+
/** Fires on every committed change (slider release, select change).
|
|
22
|
+
* Hosts wire this to `document.pages[activeIdx].trapConfig` so the
|
|
23
|
+
* D1 preview overlay (PR-12) updates live as the user adjusts. */
|
|
24
|
+
onChange: (next: TrapEditorValue) => void;
|
|
25
|
+
/** Min width in mm. Defaults to 0 (no trap). */
|
|
26
|
+
minMm?: number;
|
|
27
|
+
/** Max width in mm. Defaults to 1.0 — typical maximum for press
|
|
28
|
+
* trapping. Hosts can raise for specialty work. */
|
|
29
|
+
maxMm?: number;
|
|
30
|
+
/** Step in mm. Defaults to 0.01 mm (one hundredth-millimeter) so
|
|
31
|
+
* fine-grain edits feel natural. */
|
|
32
|
+
stepMm?: number;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* D2 interactive trap-policy editor.
|
|
36
|
+
*
|
|
37
|
+
* Controlled component: takes the current `TrapEditorValue` and emits
|
|
38
|
+
* the next one on every committed change. Surfaces the two fields the
|
|
39
|
+
* Wave 1 `TrapPolicy` shape supports today — `widthMm` (0–1 mm) and
|
|
40
|
+
* `mode` (`auto` / `spread` / `choke`). Per-edge (top/right/bottom/
|
|
41
|
+
* left) and per-color-pair tables are wired in a follow-up once the
|
|
42
|
+
* compile-pdf trap producer exposes them; the panel layout reserves
|
|
43
|
+
* space for those without committing to their final shape.
|
|
44
|
+
*
|
|
45
|
+
* Renders no chrome of its own — hosts wrap it in whatever modal /
|
|
46
|
+
* drawer / right-rail container fits their layout (matches
|
|
47
|
+
* `JobSetupPanel`'s embedding convention).
|
|
48
|
+
*
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare function TrapEditorPanel({ value, onChange, minMm, maxMm, stepMm, }: TrapEditorPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
52
|
+
//# sourceMappingURL=TrapEditorPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrapEditorPanel.d.ts","sourceRoot":"","sources":["../../src/components/TrapEditorPanel.tsx"],"names":[],"mappings":"AAKA;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,OAAO,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;6DACyD;IACzD,KAAK,EAAE,eAAe,GAAG,SAAS,CAAC;IACnC;;uEAEmE;IACnE,QAAQ,EAAE,CAAC,IAAI,EAAE,eAAe,KAAK,IAAI,CAAC;IAC1C,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;wDACoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;yCACqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,KAAS,EACT,KAAS,EACT,MAAa,GACd,EAAE,oBAAoB,2CA0FtB"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useId } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* D2 interactive trap-policy editor.
|
|
7
|
+
*
|
|
8
|
+
* Controlled component: takes the current `TrapEditorValue` and emits
|
|
9
|
+
* the next one on every committed change. Surfaces the two fields the
|
|
10
|
+
* Wave 1 `TrapPolicy` shape supports today — `widthMm` (0–1 mm) and
|
|
11
|
+
* `mode` (`auto` / `spread` / `choke`). Per-edge (top/right/bottom/
|
|
12
|
+
* left) and per-color-pair tables are wired in a follow-up once the
|
|
13
|
+
* compile-pdf trap producer exposes them; the panel layout reserves
|
|
14
|
+
* space for those without committing to their final shape.
|
|
15
|
+
*
|
|
16
|
+
* Renders no chrome of its own — hosts wrap it in whatever modal /
|
|
17
|
+
* drawer / right-rail container fits their layout (matches
|
|
18
|
+
* `JobSetupPanel`'s embedding convention).
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export function TrapEditorPanel({ value, onChange, minMm = 0, maxMm = 1, stepMm = 0.01, }) {
|
|
23
|
+
const widthId = useId();
|
|
24
|
+
const modeId = useId();
|
|
25
|
+
const current = value ?? { widthMm: 0.144, mode: "auto" };
|
|
26
|
+
const updateWidth = (next) => {
|
|
27
|
+
// Clamp to the configured range so a stray pointer-up at the
|
|
28
|
+
// slider edges doesn't propagate an out-of-range value.
|
|
29
|
+
const clamped = Math.max(minMm, Math.min(maxMm, next));
|
|
30
|
+
onChange({ ...current, widthMm: clamped });
|
|
31
|
+
};
|
|
32
|
+
const updateMode = (next) => {
|
|
33
|
+
onChange({ ...current, mode: next });
|
|
34
|
+
};
|
|
35
|
+
return (_jsxs("div", { style: {
|
|
36
|
+
display: "flex",
|
|
37
|
+
flexDirection: "column",
|
|
38
|
+
gap: "0.75rem",
|
|
39
|
+
padding: "0.75rem",
|
|
40
|
+
fontSize: "0.85rem",
|
|
41
|
+
color: "#1f2937",
|
|
42
|
+
background: "#ffffff",
|
|
43
|
+
border: "1px solid #e5e7eb",
|
|
44
|
+
borderRadius: 6,
|
|
45
|
+
minWidth: 240,
|
|
46
|
+
}, children: [_jsxs("label", { htmlFor: widthId, style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [_jsx("span", { style: { fontWeight: 600 }, children: "Trap width" }), _jsxs("div", { style: { display: "flex", alignItems: "center", gap: "0.5rem" }, children: [_jsx("input", { id: widthId, type: "range", min: minMm, max: maxMm, step: stepMm, value: current.widthMm, onChange: (e) => updateWidth(Number.parseFloat(e.target.value)), style: { flex: 1 } }), _jsxs("span", { style: {
|
|
47
|
+
minWidth: "3.5rem",
|
|
48
|
+
textAlign: "right",
|
|
49
|
+
fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
|
|
50
|
+
fontSize: "0.75rem",
|
|
51
|
+
}, children: [current.widthMm.toFixed(3), " mm"] })] })] }), _jsxs("label", { htmlFor: modeId, style: { display: "flex", flexDirection: "column", gap: "0.25rem" }, children: [_jsx("span", { style: { fontWeight: 600 }, children: "Mode" }), _jsxs("select", { id: modeId, value: current.mode ?? "auto", onChange: (e) => updateMode(e.target.value), style: {
|
|
52
|
+
padding: "0.25rem 0.5rem",
|
|
53
|
+
fontSize: "0.8rem",
|
|
54
|
+
border: "1px solid #d1d5db",
|
|
55
|
+
borderRadius: 4,
|
|
56
|
+
background: "#ffffff",
|
|
57
|
+
}, children: [_jsx("option", { value: "auto", children: "Auto (density-based)" }), _jsx("option", { value: "spread", children: "Spread (lighter into darker)" }), _jsx("option", { value: "choke", children: "Choke (darker into lighter)" })] })] }), _jsx("p", { style: {
|
|
58
|
+
margin: 0,
|
|
59
|
+
fontSize: "0.7rem",
|
|
60
|
+
color: "#6b7280",
|
|
61
|
+
lineHeight: 1.4,
|
|
62
|
+
}, children: "Per-edge and per-color-pair overrides land in a future revision once the compile-pdf trap producer exposes them." })] }));
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=TrapEditorPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrapEditorPanel.js","sourceRoot":"","sources":["../../src/components/TrapEditorPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One trap operation as predicted by the D1 preview pass. Pixel-space
|
|
3
|
+
* rectangle in PDF points (1 pt = 1/72 in) plus the source/destination
|
|
4
|
+
* ink names.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors compile-pdf's `trap_diff.operations[i]` shape (see
|
|
7
|
+
* `apps/service/src/compile-pdf-client.ts`'s `TrapOperation`). Kept
|
|
8
|
+
* inline here so the published editor package has no runtime dep on
|
|
9
|
+
* apps/service — a future refactor may centralize this shape in
|
|
10
|
+
* `@artworkpdf/document-model` to remove the structural duplication.
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export type TrapPreviewOperation = {
|
|
15
|
+
/** Server-side page index — **0-indexed**, matching compile-pdf's
|
|
16
|
+
* `TrapZone.page_index: NonNegativeInt`. Note the distinct
|
|
17
|
+
* convention from the overlay's prop, which uses **1-indexed**
|
|
18
|
+
* `pageIndex` to match PDF user-facing page numbers; the overlay
|
|
19
|
+
* converts internally. */
|
|
20
|
+
page_index: number;
|
|
21
|
+
rect_pt: [number, number, number, number];
|
|
22
|
+
from_ink: string;
|
|
23
|
+
to_ink: string;
|
|
24
|
+
width_pt?: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Pluggable preview fetcher. Hosts inject this so the editor never
|
|
28
|
+
* imports `CompilePdfClient` directly — matches the
|
|
29
|
+
* {@link import("./SwatchesPicker").SpotSearchFn} adapter pattern.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export type TrapPreviewFn = () => Promise<{
|
|
34
|
+
operations: TrapPreviewOperation[];
|
|
35
|
+
}>;
|
|
36
|
+
/**
|
|
37
|
+
* @public
|
|
38
|
+
*/
|
|
39
|
+
export type TrapPreviewOverlayProps = {
|
|
40
|
+
/** Container width / height in CSS pixels — the overlay canvas
|
|
41
|
+
* matches these so it aligns with the Konva Stage underneath. */
|
|
42
|
+
width: number;
|
|
43
|
+
height: number;
|
|
44
|
+
/** 1-indexed page number to render. The trap-diff payload may carry
|
|
45
|
+
* operations for many pages; the overlay only draws this page. */
|
|
46
|
+
pageIndex: number;
|
|
47
|
+
/** Stage scale × DPR-equivalent factor: how many CSS pixels one PDF
|
|
48
|
+
* point occupies. The component multiplies `rect_pt` by this to
|
|
49
|
+
* position each trap rectangle on the overlay. */
|
|
50
|
+
pointsToPx: number;
|
|
51
|
+
/** Re-fetch trigger — change this value to debounce a new preview
|
|
52
|
+
* pass. The value itself isn't read. Pass the editor's `objects`
|
|
53
|
+
* array or a policy-version counter. */
|
|
54
|
+
trigger: unknown;
|
|
55
|
+
/** Async fetcher returning the trap operations for the current
|
|
56
|
+
* document + policy. Hosts wire this to
|
|
57
|
+
* `CompilePdfClient.trapPreview()` and a serialized canvas PDF. */
|
|
58
|
+
previewFn: TrapPreviewFn | null;
|
|
59
|
+
/** Debounce window in milliseconds. Defaults to 500 — slower than
|
|
60
|
+
* C4's 250 ms because the trap preview is a server round trip. */
|
|
61
|
+
debounceMs?: number;
|
|
62
|
+
};
|
|
63
|
+
export declare function TrapPreviewOverlay({ width, height, pageIndex, pointsToPx, trigger, previewFn, debounceMs, }: TrapPreviewOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
64
|
+
//# sourceMappingURL=TrapPreviewOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TrapPreviewOverlay.d.ts","sourceRoot":"","sources":["../../src/components/TrapPreviewOverlay.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;;;;+BAI2B;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC;IACxC,UAAU,EAAE,oBAAoB,EAAE,CAAC;CACpC,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;sEACkE;IAClE,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf;uEACmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB;;uDAEmD;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB;;6CAEyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB;;wEAEoE;IACpE,SAAS,EAAE,aAAa,GAAG,IAAI,CAAC;IAChC;uEACmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AA8BF,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,OAAO,EACP,SAAS,EACT,UAAgB,GACjB,EAAE,uBAAuB,2CAoGzB"}
|