@printwithsynergy/artwork-pdf-editor 0.2.0 → 0.4.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/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 +18 -3
- package/dist/components/EditorApp.d.ts.map +1 -1
- package/dist/components/EditorApp.js +42 -7
- package/dist/components/EditorApp.js.map +1 -1
- package/dist/components/EditorCanvas.d.ts +31 -2
- package/dist/components/EditorCanvas.d.ts.map +1 -1
- package/dist/components/EditorCanvas.js +97 -16
- 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.map +1 -1
- package/dist/components/PageNavigator.js +6 -1
- package/dist/components/PageNavigator.js.map +1 -1
- 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/StreamingRenderProgress.d.ts +60 -0
- package/dist/components/StreamingRenderProgress.d.ts.map +1 -0
- package/dist/components/StreamingRenderProgress.js +99 -0
- package/dist/components/StreamingRenderProgress.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/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 +51 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +51 -2
- package/dist/index.js.map +1 -1
- package/dist/lens/preflight-findings.d.ts.map +1 -1
- package/dist/lens/preflight-findings.js.map +1 -1
- 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 +87 -0
- package/dist/lib/dieline-template.d.ts.map +1 -1
- package/dist/lib/dieline-template.js +163 -0
- package/dist/lib/dieline-template.js.map +1 -1
- package/dist/lib/editor-config.d.ts +390 -0
- package/dist/lib/editor-config.d.ts.map +1 -1
- package/dist/lib/editor-config.js +90 -0
- 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 +50 -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/streaming-render.d.ts +100 -0
- package/dist/lib/streaming-render.d.ts.map +1 -0
- package/dist/lib/streaming-render.js +132 -0
- package/dist/lib/streaming-render.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 +20 -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,154 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* G2v — barcode detection + validation for the live editor and the
|
|
3
|
+
* file-upload preflight pass.
|
|
4
|
+
*
|
|
5
|
+
* Two responsibilities, intentionally separated:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Validation** ({@link validateEAN13}, {@link validateUPCA},
|
|
8
|
+
* {@link validateGS1128}, {@link validateBarcode}) — pure
|
|
9
|
+
* check-digit / structural validators against the canonical
|
|
10
|
+
* specifications. No third-party dep; the standard mod-10 and
|
|
11
|
+
* AI-parsing algorithms are short and well-defined. These are
|
|
12
|
+
* what the `barcode_validation` preflight rule consults to flag
|
|
13
|
+
* malformed codes the user has already declared on the canvas
|
|
14
|
+
* (or that future G2g (Wave 3) will generate).
|
|
15
|
+
*
|
|
16
|
+
* 2. **Detection** ({@link scanBarcodes}) — visual scanning of a
|
|
17
|
+
* rasterized canvas / image to find barcodes the user pasted in
|
|
18
|
+
* or imported from artwork PDFs. The detector is currently a
|
|
19
|
+
* stub that always resolves to an empty array; a follow-up will
|
|
20
|
+
* add `jsqr` for QR codes (smallest footprint ~40 kB minified)
|
|
21
|
+
* and either `quagga2` (~200 kB, mature, EAN-13/UPC-A/Code-128)
|
|
22
|
+
* or `@undecaf/zbar-wasm` (~600 kB, more accurate) for linear
|
|
23
|
+
* barcodes after a perf+accuracy bake-off. Until then this
|
|
24
|
+
* module ships the type contract and validator surface so the
|
|
25
|
+
* preflight switch + rule defaults can land cleanly without
|
|
26
|
+
* pulling in a heavyweight dep on day one.
|
|
27
|
+
*/
|
|
28
|
+
/**
|
|
29
|
+
* Barcode symbology / format. Listed are the formats covered by the
|
|
30
|
+
* `barcode_validation` rule. Other formats (Data Matrix, ITF-14,
|
|
31
|
+
* Code 39, …) can be added incrementally; each gets its own
|
|
32
|
+
* validator + entry in {@link validateBarcode}.
|
|
33
|
+
*
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export type BarcodeFormat = "EAN-13" | "UPC-A" | "GS1-128" | "QR";
|
|
37
|
+
/**
|
|
38
|
+
* Canonical list of every {@link BarcodeFormat} the module supports.
|
|
39
|
+
* Exported so UI surfaces ({@link import("../components/BarcodeGeneratorPanel").BarcodeGeneratorPanel}
|
|
40
|
+
* default dropdown, host-supplied filters, contract tests) don't have
|
|
41
|
+
* to redeclare the list and drift out of sync when a new format is
|
|
42
|
+
* added to the union.
|
|
43
|
+
*
|
|
44
|
+
* @public
|
|
45
|
+
*/
|
|
46
|
+
export declare const ALL_BARCODE_FORMATS: readonly BarcodeFormat[];
|
|
47
|
+
/**
|
|
48
|
+
* Result of detecting one barcode on a rasterized image.
|
|
49
|
+
*
|
|
50
|
+
* `bounds` and `confidence` are optional because different detectors
|
|
51
|
+
* surface them with different fidelity (jsQR returns a 4-corner
|
|
52
|
+
* polygon, zbar returns a rect, quagga returns both); callers should
|
|
53
|
+
* defensively check for `undefined`.
|
|
54
|
+
*
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
export type BarcodeDetection = {
|
|
58
|
+
/** The decoded payload, e.g. `"4006381333931"` for an EAN-13 or a
|
|
59
|
+
* URL for a QR code. */
|
|
60
|
+
code: string;
|
|
61
|
+
/** Detected symbology. */
|
|
62
|
+
format: BarcodeFormat;
|
|
63
|
+
/** Pixel-space bounding box on the source ImageData, if the
|
|
64
|
+
* detector reported one. */
|
|
65
|
+
bounds?: {
|
|
66
|
+
x: number;
|
|
67
|
+
y: number;
|
|
68
|
+
width: number;
|
|
69
|
+
height: number;
|
|
70
|
+
};
|
|
71
|
+
/** Detector confidence in `[0, 1]`, if reported. */
|
|
72
|
+
confidence?: number;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Result of validating one barcode against its format-specific spec.
|
|
76
|
+
*
|
|
77
|
+
* `reason` is populated only when `valid` is `false` — a short
|
|
78
|
+
* human-readable explanation suitable for surfacing in the
|
|
79
|
+
* preflight panel.
|
|
80
|
+
*
|
|
81
|
+
* @public
|
|
82
|
+
*/
|
|
83
|
+
export type BarcodeValidation = {
|
|
84
|
+
valid: boolean;
|
|
85
|
+
reason?: string;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* EAN-13 check-digit validation.
|
|
89
|
+
*
|
|
90
|
+
* EAN-13 is 13 digits; the 13th is a mod-10 checksum over the first
|
|
91
|
+
* 12 with alternating weights (1, 3, 1, 3, …). Returns `true` iff the
|
|
92
|
+
* input is exactly 13 ASCII digits and the checksum matches.
|
|
93
|
+
*
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
export declare function validateEAN13(code: string): boolean;
|
|
97
|
+
/**
|
|
98
|
+
* UPC-A check-digit validation.
|
|
99
|
+
*
|
|
100
|
+
* UPC-A is 12 digits; the 12th is a mod-10 checksum over the first
|
|
101
|
+
* 11 with weights (3, 1, 3, 1, …). Returns `true` iff the input is
|
|
102
|
+
* exactly 12 ASCII digits and the checksum matches.
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
export declare function validateUPCA(code: string): boolean;
|
|
107
|
+
/**
|
|
108
|
+
* GS1-128 structural validation.
|
|
109
|
+
*
|
|
110
|
+
* GS1-128 (formerly UCC/EAN-128) encodes structured data using
|
|
111
|
+
* Application Identifiers — each AI is 2–4 digits followed by a
|
|
112
|
+
* data field of AI-dependent length. A full validator would require
|
|
113
|
+
* the AI table; the shippable approximation here checks that:
|
|
114
|
+
*
|
|
115
|
+
* - The payload contains only printable ASCII (no control chars
|
|
116
|
+
* other than the `<GS>` `0x1D` separator used between
|
|
117
|
+
* variable-length data fields).
|
|
118
|
+
* - The payload starts with at least two digits (the first AI).
|
|
119
|
+
* - The payload is non-empty and ≤ 48 chars (real-world
|
|
120
|
+
* GS1-128 codes rarely exceed this).
|
|
121
|
+
*
|
|
122
|
+
* Returns `true` for plausibly-structured payloads. False positives
|
|
123
|
+
* are intentional — preflight is a sanity check, not a parser.
|
|
124
|
+
*
|
|
125
|
+
* @public
|
|
126
|
+
*/
|
|
127
|
+
export declare function validateGS1128(code: string): boolean;
|
|
128
|
+
/**
|
|
129
|
+
* Format-aware validator that dispatches to the right per-format
|
|
130
|
+
* check. QR codes pass when the payload is non-empty (the symbol
|
|
131
|
+
* itself carries a Reed-Solomon checksum the detector already
|
|
132
|
+
* verified before emitting the {@link BarcodeDetection}).
|
|
133
|
+
*
|
|
134
|
+
* @public
|
|
135
|
+
*/
|
|
136
|
+
export declare function validateBarcode(detection: BarcodeDetection): BarcodeValidation;
|
|
137
|
+
/**
|
|
138
|
+
* Visual barcode detection from a rasterized image.
|
|
139
|
+
*
|
|
140
|
+
* Currently a stub: returns an empty array regardless of input. The
|
|
141
|
+
* real implementation lands in a follow-up that adds a barcode
|
|
142
|
+
* detection library (likely `jsqr` for QR + `quagga2` for linear).
|
|
143
|
+
* Until then, callers see no false positives, and the
|
|
144
|
+
* {@link validateBarcode} surface stays usable for codes the user
|
|
145
|
+
* (or G2g, Wave 3) declares directly on the canvas.
|
|
146
|
+
*
|
|
147
|
+
* The async signature is forward-compatible — most barcode
|
|
148
|
+
* detectors are async (decoder workers, WASM init), so callers
|
|
149
|
+
* don't need to refactor when the real detector lands.
|
|
150
|
+
*
|
|
151
|
+
* @public
|
|
152
|
+
*/
|
|
153
|
+
export declare function scanBarcodes(_imageData: ImageData): Promise<BarcodeDetection[]>;
|
|
154
|
+
//# sourceMappingURL=barcode-scan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barcode-scan.d.ts","sourceRoot":"","sources":["../../src/lib/barcode-scan.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,OAAO,GAAG,SAAS,GAAG,IAAI,CAAC;AAElE;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,EAAE,SAAS,aAAa,EAK9C,CAAC;AAEX;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B;6BACyB;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,MAAM,EAAE,aAAa,CAAC;IACtB;iCAC6B;IAC7B,MAAM,CAAC,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IACjE,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAAE,KAAK,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpE;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAUnD;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWlD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAWpD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,gBAAgB,GAAG,iBAAiB,CA2B9E;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,YAAY,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAGrF"}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/**
|
|
3
|
+
* Canonical list of every {@link BarcodeFormat} the module supports.
|
|
4
|
+
* Exported so UI surfaces ({@link import("../components/BarcodeGeneratorPanel").BarcodeGeneratorPanel}
|
|
5
|
+
* default dropdown, host-supplied filters, contract tests) don't have
|
|
6
|
+
* to redeclare the list and drift out of sync when a new format is
|
|
7
|
+
* added to the union.
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export const ALL_BARCODE_FORMATS = [
|
|
12
|
+
"EAN-13",
|
|
13
|
+
"UPC-A",
|
|
14
|
+
"GS1-128",
|
|
15
|
+
"QR",
|
|
16
|
+
];
|
|
17
|
+
/**
|
|
18
|
+
* EAN-13 check-digit validation.
|
|
19
|
+
*
|
|
20
|
+
* EAN-13 is 13 digits; the 13th is a mod-10 checksum over the first
|
|
21
|
+
* 12 with alternating weights (1, 3, 1, 3, …). Returns `true` iff the
|
|
22
|
+
* input is exactly 13 ASCII digits and the checksum matches.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
25
|
+
*/
|
|
26
|
+
export function validateEAN13(code) {
|
|
27
|
+
if (!/^[0-9]{13}$/.test(code))
|
|
28
|
+
return false;
|
|
29
|
+
let sum = 0;
|
|
30
|
+
for (let i = 0; i < 12; i++) {
|
|
31
|
+
const d = code.charCodeAt(i) - 48;
|
|
32
|
+
// Odd-positioned digits (1-indexed) get weight 1; even get 3.
|
|
33
|
+
sum += i % 2 === 0 ? d : d * 3;
|
|
34
|
+
}
|
|
35
|
+
const check = (10 - (sum % 10)) % 10;
|
|
36
|
+
return check === code.charCodeAt(12) - 48;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* UPC-A check-digit validation.
|
|
40
|
+
*
|
|
41
|
+
* UPC-A is 12 digits; the 12th is a mod-10 checksum over the first
|
|
42
|
+
* 11 with weights (3, 1, 3, 1, …). Returns `true` iff the input is
|
|
43
|
+
* exactly 12 ASCII digits and the checksum matches.
|
|
44
|
+
*
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
export function validateUPCA(code) {
|
|
48
|
+
if (!/^[0-9]{12}$/.test(code))
|
|
49
|
+
return false;
|
|
50
|
+
let sum = 0;
|
|
51
|
+
for (let i = 0; i < 11; i++) {
|
|
52
|
+
const d = code.charCodeAt(i) - 48;
|
|
53
|
+
// Odd-positioned digits (1-indexed) get weight 3; even get 1 —
|
|
54
|
+
// mirror image of EAN-13's weight pattern.
|
|
55
|
+
sum += i % 2 === 0 ? d * 3 : d;
|
|
56
|
+
}
|
|
57
|
+
const check = (10 - (sum % 10)) % 10;
|
|
58
|
+
return check === code.charCodeAt(11) - 48;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* GS1-128 structural validation.
|
|
62
|
+
*
|
|
63
|
+
* GS1-128 (formerly UCC/EAN-128) encodes structured data using
|
|
64
|
+
* Application Identifiers — each AI is 2–4 digits followed by a
|
|
65
|
+
* data field of AI-dependent length. A full validator would require
|
|
66
|
+
* the AI table; the shippable approximation here checks that:
|
|
67
|
+
*
|
|
68
|
+
* - The payload contains only printable ASCII (no control chars
|
|
69
|
+
* other than the `<GS>` `0x1D` separator used between
|
|
70
|
+
* variable-length data fields).
|
|
71
|
+
* - The payload starts with at least two digits (the first AI).
|
|
72
|
+
* - The payload is non-empty and ≤ 48 chars (real-world
|
|
73
|
+
* GS1-128 codes rarely exceed this).
|
|
74
|
+
*
|
|
75
|
+
* Returns `true` for plausibly-structured payloads. False positives
|
|
76
|
+
* are intentional — preflight is a sanity check, not a parser.
|
|
77
|
+
*
|
|
78
|
+
* @public
|
|
79
|
+
*/
|
|
80
|
+
export function validateGS1128(code) {
|
|
81
|
+
if (code.length === 0 || code.length > 48)
|
|
82
|
+
return false;
|
|
83
|
+
if (!/^[0-9]{2}/.test(code))
|
|
84
|
+
return false;
|
|
85
|
+
// 0x1D is the GS separator GS1-128 uses; everything else must be
|
|
86
|
+
// printable ASCII so we don't accept binary garbage.
|
|
87
|
+
for (let i = 0; i < code.length; i++) {
|
|
88
|
+
const c = code.charCodeAt(i);
|
|
89
|
+
if (c === 0x1d)
|
|
90
|
+
continue;
|
|
91
|
+
if (c < 0x20 || c > 0x7e)
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Format-aware validator that dispatches to the right per-format
|
|
98
|
+
* check. QR codes pass when the payload is non-empty (the symbol
|
|
99
|
+
* itself carries a Reed-Solomon checksum the detector already
|
|
100
|
+
* verified before emitting the {@link BarcodeDetection}).
|
|
101
|
+
*
|
|
102
|
+
* @public
|
|
103
|
+
*/
|
|
104
|
+
export function validateBarcode(detection) {
|
|
105
|
+
switch (detection.format) {
|
|
106
|
+
case "EAN-13":
|
|
107
|
+
return validateEAN13(detection.code)
|
|
108
|
+
? { valid: true }
|
|
109
|
+
: { valid: false, reason: "EAN-13 check digit failed or wrong length (need 13 digits)" };
|
|
110
|
+
case "UPC-A":
|
|
111
|
+
return validateUPCA(detection.code)
|
|
112
|
+
? { valid: true }
|
|
113
|
+
: { valid: false, reason: "UPC-A check digit failed or wrong length (need 12 digits)" };
|
|
114
|
+
case "GS1-128":
|
|
115
|
+
return validateGS1128(detection.code)
|
|
116
|
+
? { valid: true }
|
|
117
|
+
: {
|
|
118
|
+
valid: false,
|
|
119
|
+
reason: "GS1-128 payload is empty, too long, or contains non-printable chars",
|
|
120
|
+
};
|
|
121
|
+
case "QR":
|
|
122
|
+
return detection.code.length > 0
|
|
123
|
+
? { valid: true }
|
|
124
|
+
: { valid: false, reason: "QR payload is empty" };
|
|
125
|
+
default:
|
|
126
|
+
// Defensive: detectors that return formats outside our union
|
|
127
|
+
// (e.g. a future library reporting "Code128" before we add it
|
|
128
|
+
// to BarcodeFormat) would otherwise return undefined.
|
|
129
|
+
return { valid: false, reason: "Unsupported barcode format" };
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Visual barcode detection from a rasterized image.
|
|
134
|
+
*
|
|
135
|
+
* Currently a stub: returns an empty array regardless of input. The
|
|
136
|
+
* real implementation lands in a follow-up that adds a barcode
|
|
137
|
+
* detection library (likely `jsqr` for QR + `quagga2` for linear).
|
|
138
|
+
* Until then, callers see no false positives, and the
|
|
139
|
+
* {@link validateBarcode} surface stays usable for codes the user
|
|
140
|
+
* (or G2g, Wave 3) declares directly on the canvas.
|
|
141
|
+
*
|
|
142
|
+
* The async signature is forward-compatible — most barcode
|
|
143
|
+
* detectors are async (decoder workers, WASM init), so callers
|
|
144
|
+
* don't need to refactor when the real detector lands.
|
|
145
|
+
*
|
|
146
|
+
* @public
|
|
147
|
+
*/
|
|
148
|
+
export async function scanBarcodes(_imageData) {
|
|
149
|
+
// TODO(wave-1 follow-up): integrate jsqr + a linear scanner.
|
|
150
|
+
return [];
|
|
151
|
+
}
|
|
152
|
+
//# sourceMappingURL=barcode-scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"barcode-scan.js","sourceRoot":"","sources":["../../src/lib/barcode-scan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny color-math helpers used by the C4 live-TAC sampler.
|
|
3
|
+
*
|
|
4
|
+
* Intentionally simple — the editor's TAC heatmap is a sanity check,
|
|
5
|
+
* not a colorimetric proof. Production color management lives
|
|
6
|
+
* server-side in compile-pdf (`codex_pdf.color`'s ICC-profile-aware
|
|
7
|
+
* conversion). These helpers do the cheap browser-side math so the
|
|
8
|
+
* editor can flag obviously over-inked regions without round-tripping
|
|
9
|
+
* to the server.
|
|
10
|
+
*
|
|
11
|
+
* Lab → CMYK is **not** here on purpose — that conversion is profile-
|
|
12
|
+
* dependent and codex owns it. The editor's spots (`EditorSeparation`)
|
|
13
|
+
* carry an optional `lab` for display, but TAC sampling uses the hex
|
|
14
|
+
* source color (via {@link hexToCmyk}) for browser-side speed.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Subtractive RGB → CMYK with auto black extraction (the "K" channel
|
|
18
|
+
* is the minimum of the inverted RGB values; C/M/Y rescale once K is
|
|
19
|
+
* pulled).
|
|
20
|
+
*
|
|
21
|
+
* Each output channel is in the `[0, 1]` range — multiply by 100 for
|
|
22
|
+
* a percentage. Inputs that fall outside `0..1` are clamped (defensive
|
|
23
|
+
* against bad string parsing).
|
|
24
|
+
*
|
|
25
|
+
* @public
|
|
26
|
+
*/
|
|
27
|
+
export declare function rgbToCmyk(r: number, g: number, b: number): {
|
|
28
|
+
c: number;
|
|
29
|
+
m: number;
|
|
30
|
+
y: number;
|
|
31
|
+
k: number;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Parse a `#rrggbb` (or `rrggbb`) hex string into `[r, g, b]` floats
|
|
35
|
+
* in the `[0, 1]` range. Returns `null` for malformed input — callers
|
|
36
|
+
* fall back to whatever default they prefer.
|
|
37
|
+
*
|
|
38
|
+
* Accepts a leading `#` or not; case-insensitive. Short-form `#rgb`
|
|
39
|
+
* is **not** supported — the editor canonicalizes to long form at
|
|
40
|
+
* registration time (see `separations-registry.ts`'s lowercase
|
|
41
|
+
* normalization).
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export declare function parseHex(hex: string): [number, number, number] | null;
|
|
46
|
+
/**
|
|
47
|
+
* Convert a `#rrggbb` hex string into CMYK fractions.
|
|
48
|
+
*
|
|
49
|
+
* Returns `null` for malformed input (delegates parsing to
|
|
50
|
+
* {@link parseHex}). Use the `.c + .m + .y + .k` sum × 100 for a
|
|
51
|
+
* total-area-coverage estimate on the pixel.
|
|
52
|
+
*
|
|
53
|
+
* @public
|
|
54
|
+
*/
|
|
55
|
+
export declare function hexToCmyk(hex: string): {
|
|
56
|
+
c: number;
|
|
57
|
+
m: number;
|
|
58
|
+
y: number;
|
|
59
|
+
k: number;
|
|
60
|
+
} | null;
|
|
61
|
+
/**
|
|
62
|
+
* Total area coverage of a single CMYK quadruple, in percent (0-400).
|
|
63
|
+
*
|
|
64
|
+
* Sum of all four ink channels — the standard print-industry TAC
|
|
65
|
+
* metric. The TAC limit on coated stock is usually 280-320%; on
|
|
66
|
+
* newsprint, 240%. The editor's preflight default is 300%.
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
export declare function tacPercent(cmyk: {
|
|
71
|
+
c: number;
|
|
72
|
+
m: number;
|
|
73
|
+
y: number;
|
|
74
|
+
k: number;
|
|
75
|
+
}): number;
|
|
76
|
+
//# sourceMappingURL=color-math.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-math.d.ts","sourceRoot":"","sources":["../../src/lib/color-math.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CACvB,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,EACT,CAAC,EAAE,MAAM,GACR;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,CAgBhD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CASrE;AAED;;;;;;;;GAQG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI5F;AAED;;;;;;;;GAQG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE;IAAE,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEvF"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
/**
|
|
3
|
+
* Tiny color-math helpers used by the C4 live-TAC sampler.
|
|
4
|
+
*
|
|
5
|
+
* Intentionally simple — the editor's TAC heatmap is a sanity check,
|
|
6
|
+
* not a colorimetric proof. Production color management lives
|
|
7
|
+
* server-side in compile-pdf (`codex_pdf.color`'s ICC-profile-aware
|
|
8
|
+
* conversion). These helpers do the cheap browser-side math so the
|
|
9
|
+
* editor can flag obviously over-inked regions without round-tripping
|
|
10
|
+
* to the server.
|
|
11
|
+
*
|
|
12
|
+
* Lab → CMYK is **not** here on purpose — that conversion is profile-
|
|
13
|
+
* dependent and codex owns it. The editor's spots (`EditorSeparation`)
|
|
14
|
+
* carry an optional `lab` for display, but TAC sampling uses the hex
|
|
15
|
+
* source color (via {@link hexToCmyk}) for browser-side speed.
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Subtractive RGB → CMYK with auto black extraction (the "K" channel
|
|
19
|
+
* is the minimum of the inverted RGB values; C/M/Y rescale once K is
|
|
20
|
+
* pulled).
|
|
21
|
+
*
|
|
22
|
+
* Each output channel is in the `[0, 1]` range — multiply by 100 for
|
|
23
|
+
* a percentage. Inputs that fall outside `0..1` are clamped (defensive
|
|
24
|
+
* against bad string parsing).
|
|
25
|
+
*
|
|
26
|
+
* @public
|
|
27
|
+
*/
|
|
28
|
+
export function rgbToCmyk(r, g, b) {
|
|
29
|
+
const R = Math.max(0, Math.min(1, r));
|
|
30
|
+
const G = Math.max(0, Math.min(1, g));
|
|
31
|
+
const B = Math.max(0, Math.min(1, b));
|
|
32
|
+
const k = 1 - Math.max(R, G, B);
|
|
33
|
+
if (k >= 1) {
|
|
34
|
+
// Pure black — no chroma channels, all ink in K.
|
|
35
|
+
return { c: 0, m: 0, y: 0, k: 1 };
|
|
36
|
+
}
|
|
37
|
+
const scale = 1 - k;
|
|
38
|
+
return {
|
|
39
|
+
c: (1 - R - k) / scale,
|
|
40
|
+
m: (1 - G - k) / scale,
|
|
41
|
+
y: (1 - B - k) / scale,
|
|
42
|
+
k,
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse a `#rrggbb` (or `rrggbb`) hex string into `[r, g, b]` floats
|
|
47
|
+
* in the `[0, 1]` range. Returns `null` for malformed input — callers
|
|
48
|
+
* fall back to whatever default they prefer.
|
|
49
|
+
*
|
|
50
|
+
* Accepts a leading `#` or not; case-insensitive. Short-form `#rgb`
|
|
51
|
+
* is **not** supported — the editor canonicalizes to long form at
|
|
52
|
+
* registration time (see `separations-registry.ts`'s lowercase
|
|
53
|
+
* normalization).
|
|
54
|
+
*
|
|
55
|
+
* @public
|
|
56
|
+
*/
|
|
57
|
+
export function parseHex(hex) {
|
|
58
|
+
const trimmed = hex.trim();
|
|
59
|
+
const body = trimmed.startsWith("#") ? trimmed.slice(1) : trimmed;
|
|
60
|
+
if (body.length !== 6)
|
|
61
|
+
return null;
|
|
62
|
+
if (!/^[0-9a-fA-F]{6}$/.test(body))
|
|
63
|
+
return null;
|
|
64
|
+
const r = Number.parseInt(body.slice(0, 2), 16) / 255;
|
|
65
|
+
const g = Number.parseInt(body.slice(2, 4), 16) / 255;
|
|
66
|
+
const b = Number.parseInt(body.slice(4, 6), 16) / 255;
|
|
67
|
+
return [r, g, b];
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Convert a `#rrggbb` hex string into CMYK fractions.
|
|
71
|
+
*
|
|
72
|
+
* Returns `null` for malformed input (delegates parsing to
|
|
73
|
+
* {@link parseHex}). Use the `.c + .m + .y + .k` sum × 100 for a
|
|
74
|
+
* total-area-coverage estimate on the pixel.
|
|
75
|
+
*
|
|
76
|
+
* @public
|
|
77
|
+
*/
|
|
78
|
+
export function hexToCmyk(hex) {
|
|
79
|
+
const rgb = parseHex(hex);
|
|
80
|
+
if (rgb === null)
|
|
81
|
+
return null;
|
|
82
|
+
return rgbToCmyk(rgb[0], rgb[1], rgb[2]);
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Total area coverage of a single CMYK quadruple, in percent (0-400).
|
|
86
|
+
*
|
|
87
|
+
* Sum of all four ink channels — the standard print-industry TAC
|
|
88
|
+
* metric. The TAC limit on coated stock is usually 280-320%; on
|
|
89
|
+
* newsprint, 240%. The editor's preflight default is 300%.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
export function tacPercent(cmyk) {
|
|
94
|
+
return (cmyk.c + cmyk.m + cmyk.y + cmyk.k) * 100;
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=color-math.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"color-math.js","sourceRoot":"","sources":["../../src/lib/color-math.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,21 @@
|
|
|
1
|
+
import type { Dieline } from "@artworkpdf/dieline-parser";
|
|
1
2
|
import type { CanvasObj } from "../components/EditorCanvas";
|
|
3
|
+
import type { EditorSeparation } from "./separations-registry";
|
|
4
|
+
/**
|
|
5
|
+
* One packaging structure — geometry + metadata for a known dieline
|
|
6
|
+
* (pouch, bottle wrap, carton, etc.).
|
|
7
|
+
*
|
|
8
|
+
* `dimensions` is the *trim* size in mm; `bleedMm` is the per-side
|
|
9
|
+
* bleed extension; `trimBox` is the trim rect in mm relative to the
|
|
10
|
+
* full bleed-included page. `previewSvg` is an inline string suitable
|
|
11
|
+
* for thumbnail rendering in the template-picker UI.
|
|
12
|
+
*
|
|
13
|
+
* Distinct from `@artworkpdf/document-model`'s `DielineTemplate`: the
|
|
14
|
+
* shape here is a published, self-contained type so the editor
|
|
15
|
+
* package doesn't force the document-model dep on hosts.
|
|
16
|
+
*
|
|
17
|
+
* @public
|
|
18
|
+
*/
|
|
2
19
|
export type DielineTemplate = {
|
|
3
20
|
id: string;
|
|
4
21
|
name: string;
|
|
@@ -44,6 +61,15 @@ export type TemplateSet = {
|
|
|
44
61
|
tags: string[];
|
|
45
62
|
isDefault?: boolean;
|
|
46
63
|
};
|
|
64
|
+
/**
|
|
65
|
+
* All bundled dieline templates, in library declaration order.
|
|
66
|
+
*
|
|
67
|
+
* Mirrors the shape of `data/dielines.json`. Hosts that want a
|
|
68
|
+
* filtered or ordered subset should derive from this array rather
|
|
69
|
+
* than reloading the JSON file.
|
|
70
|
+
*
|
|
71
|
+
* @public
|
|
72
|
+
*/
|
|
47
73
|
export declare const TEMPLATES: DielineTemplate[];
|
|
48
74
|
/**
|
|
49
75
|
* Bundled multi-page template sets (e.g. carton front + back). Empty if
|
|
@@ -52,7 +78,20 @@ export declare const TEMPLATES: DielineTemplate[];
|
|
|
52
78
|
* @public
|
|
53
79
|
*/
|
|
54
80
|
export declare const TEMPLATE_SETS: TemplateSet[];
|
|
81
|
+
/**
|
|
82
|
+
* Return the library's default template (`isDefault: true`), falling
|
|
83
|
+
* back to the first entry. Throws if the library is empty — that
|
|
84
|
+
* would indicate a packaging defect, not a runtime condition.
|
|
85
|
+
*
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
55
88
|
export declare function getDefaultTemplate(): DielineTemplate;
|
|
89
|
+
/**
|
|
90
|
+
* Lookup by template id. Returns `undefined` (not throws) for
|
|
91
|
+
* unknown or missing ids so callers can fall back to a default.
|
|
92
|
+
*
|
|
93
|
+
* @public
|
|
94
|
+
*/
|
|
56
95
|
export declare function getTemplateById(id: string | undefined): DielineTemplate | undefined;
|
|
57
96
|
/**
|
|
58
97
|
* Lookup a multi-page template set by id (e.g. `"carton-6x4x2-set"`).
|
|
@@ -90,6 +129,11 @@ export type Page = {
|
|
|
90
129
|
templateId?: string;
|
|
91
130
|
/** Human label shown in the page navigator (e.g. "Front", "Back"). */
|
|
92
131
|
name?: string;
|
|
132
|
+
/** AI4 separations registry — spot inks the user has registered
|
|
133
|
+
* on this page. Threads through to compile-pdf via the
|
|
134
|
+
* job request's `separationsOverride`. Absent → no overrides;
|
|
135
|
+
* empty array → explicit composite-only render. */
|
|
136
|
+
separations?: EditorSeparation[];
|
|
93
137
|
};
|
|
94
138
|
/**
|
|
95
139
|
* Build a {@link Page} from a {@link DielineTemplate}. Mirrors the
|
|
@@ -110,6 +154,22 @@ export declare function templatesToPages(entries: ReadonlyArray<{
|
|
|
110
154
|
template: DielineTemplate;
|
|
111
155
|
name?: string;
|
|
112
156
|
}>, bleedMmOverride?: number): Page[];
|
|
157
|
+
/**
|
|
158
|
+
* Build the initial canvas state for a single template — the dieline
|
|
159
|
+
* trim rect (locked, non-interactive) plus the page size including
|
|
160
|
+
* bleed on all sides.
|
|
161
|
+
*
|
|
162
|
+
* Pass `bleedMmOverride` to use a host-supplied bleed instead of the
|
|
163
|
+
* template's bundled value (e.g. when the user picks a custom bleed
|
|
164
|
+
* in the URL or UI). Returned coordinates are in PDF points
|
|
165
|
+
* (1 mm = 2.83465 pt).
|
|
166
|
+
*
|
|
167
|
+
* Use this for single-page seeds; for multi-page documents use
|
|
168
|
+
* {@link templateToPage} or {@link templatesToPages} which wrap the
|
|
169
|
+
* result in a {@link Page}.
|
|
170
|
+
*
|
|
171
|
+
* @public
|
|
172
|
+
*/
|
|
113
173
|
export declare function templateToInitialState(template: DielineTemplate, bleedMmOverride?: number): {
|
|
114
174
|
objects: CanvasObj[];
|
|
115
175
|
pageSize: {
|
|
@@ -117,4 +177,31 @@ export declare function templateToInitialState(template: DielineTemplate, bleedM
|
|
|
117
177
|
height: number;
|
|
118
178
|
};
|
|
119
179
|
};
|
|
180
|
+
/**
|
|
181
|
+
* Build a {@link Page} from a parsed {@link Dieline} (CF2 / DDES /
|
|
182
|
+
* ARD import).
|
|
183
|
+
*
|
|
184
|
+
* Each `DielinePath` becomes one locked `CanvasObj` of type `"path"`
|
|
185
|
+
* rendered as a Konva `Path` (the `Path` import was added to
|
|
186
|
+
* `EditorCanvas` for this case). Type-specific stroke colors come
|
|
187
|
+
* from {@link DIELINE_PATH_STROKES}. The whole page is locked so
|
|
188
|
+
* users can't accidentally drag the structural reference geometry —
|
|
189
|
+
* same invariant as the bundled-template dieline rect.
|
|
190
|
+
*
|
|
191
|
+
* Coordinate units: the parser emits SVG path `d` strings in
|
|
192
|
+
* **dieline-native millimeters** (Y-down). We position each path
|
|
193
|
+
* object at `(bleedMm * MM_TO_PT, bleedMm * MM_TO_PT)` so the dieline
|
|
194
|
+
* trim sits inside the bleed margin. The path data itself is in
|
|
195
|
+
* mm — Konva renders it without further conversion because the
|
|
196
|
+
* containing Stage is configured in points and the relative offsets
|
|
197
|
+
* align (the Stage's own scale handles the mm→pt for display).
|
|
198
|
+
*
|
|
199
|
+
* `bleedMmOverride`: pass a host-supplied bleed (URL param, UI
|
|
200
|
+
* input) instead of the default. Defaults to 0 for parsed dielines —
|
|
201
|
+
* the source files don't carry their own bleed convention and the
|
|
202
|
+
* caller is the right place to decide.
|
|
203
|
+
*
|
|
204
|
+
* @public
|
|
205
|
+
*/
|
|
206
|
+
export declare function dielineToPage(dieline: Dieline, bleedMmOverride?: number): Page;
|
|
120
207
|
//# sourceMappingURL=dieline-template.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dieline-template.d.ts","sourceRoot":"","sources":["../../src/lib/dieline-template.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"dieline-template.d.ts","sourceRoot":"","sources":["../../src/lib/dieline-template.ts"],"names":[],"mappings":"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"}
|