@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.
Files changed (244) hide show
  1. package/LICENSE +62 -0
  2. package/dist/components/AccessibilityHintsPanel.d.ts +142 -0
  3. package/dist/components/AccessibilityHintsPanel.d.ts.map +1 -0
  4. package/dist/components/AccessibilityHintsPanel.js +158 -0
  5. package/dist/components/AccessibilityHintsPanel.js.map +1 -0
  6. package/dist/components/AnnotationOverlay.d.ts +142 -0
  7. package/dist/components/AnnotationOverlay.d.ts.map +1 -0
  8. package/dist/components/AnnotationOverlay.js +141 -0
  9. package/dist/components/AnnotationOverlay.js.map +1 -0
  10. package/dist/components/AnnotationsSidebar.d.ts +98 -0
  11. package/dist/components/AnnotationsSidebar.d.ts.map +1 -0
  12. package/dist/components/AnnotationsSidebar.js +100 -0
  13. package/dist/components/AnnotationsSidebar.js.map +1 -0
  14. package/dist/components/BarcodeGeneratorPanel.d.ts +58 -0
  15. package/dist/components/BarcodeGeneratorPanel.d.ts.map +1 -0
  16. package/dist/components/BarcodeGeneratorPanel.js +91 -0
  17. package/dist/components/BarcodeGeneratorPanel.js.map +1 -0
  18. package/dist/components/BraillePanel.d.ts +99 -0
  19. package/dist/components/BraillePanel.d.ts.map +1 -0
  20. package/dist/components/BraillePanel.js +221 -0
  21. package/dist/components/BraillePanel.js.map +1 -0
  22. package/dist/components/BrandAssetsPanel.d.ts +130 -0
  23. package/dist/components/BrandAssetsPanel.d.ts.map +1 -0
  24. package/dist/components/BrandAssetsPanel.js +125 -0
  25. package/dist/components/BrandAssetsPanel.js.map +1 -0
  26. package/dist/components/BrandConsistencyPanel.d.ts +140 -0
  27. package/dist/components/BrandConsistencyPanel.d.ts.map +1 -0
  28. package/dist/components/BrandConsistencyPanel.js +158 -0
  29. package/dist/components/BrandConsistencyPanel.js.map +1 -0
  30. package/dist/components/ComplianceFindingsPanel.d.ts +62 -0
  31. package/dist/components/ComplianceFindingsPanel.d.ts.map +1 -0
  32. package/dist/components/ComplianceFindingsPanel.js +118 -0
  33. package/dist/components/ComplianceFindingsPanel.js.map +1 -0
  34. package/dist/components/DesignSuggestionsPanel.d.ts +148 -0
  35. package/dist/components/DesignSuggestionsPanel.d.ts.map +1 -0
  36. package/dist/components/DesignSuggestionsPanel.js +154 -0
  37. package/dist/components/DesignSuggestionsPanel.js.map +1 -0
  38. package/dist/components/DielineParametersPanel.d.ts +62 -0
  39. package/dist/components/DielineParametersPanel.d.ts.map +1 -0
  40. package/dist/components/DielineParametersPanel.js +170 -0
  41. package/dist/components/DielineParametersPanel.js.map +1 -0
  42. package/dist/components/DielinePreview.d.ts +150 -0
  43. package/dist/components/DielinePreview.d.ts.map +1 -0
  44. package/dist/components/DielinePreview.js +146 -0
  45. package/dist/components/DielinePreview.js.map +1 -0
  46. package/dist/components/EditorApp.d.ts +18 -3
  47. package/dist/components/EditorApp.d.ts.map +1 -1
  48. package/dist/components/EditorApp.js +42 -7
  49. package/dist/components/EditorApp.js.map +1 -1
  50. package/dist/components/EditorCanvas.d.ts +31 -2
  51. package/dist/components/EditorCanvas.d.ts.map +1 -1
  52. package/dist/components/EditorCanvas.js +97 -16
  53. package/dist/components/EditorCanvas.js.map +1 -1
  54. package/dist/components/EmailNotifyPanel.d.ts +165 -0
  55. package/dist/components/EmailNotifyPanel.d.ts.map +1 -0
  56. package/dist/components/EmailNotifyPanel.js +211 -0
  57. package/dist/components/EmailNotifyPanel.js.map +1 -0
  58. package/dist/components/FileDropZone.d.ts +9 -1
  59. package/dist/components/FileDropZone.d.ts.map +1 -1
  60. package/dist/components/FileDropZone.js +53 -5
  61. package/dist/components/FileDropZone.js.map +1 -1
  62. package/dist/components/FoldEditorPanel.d.ts +68 -0
  63. package/dist/components/FoldEditorPanel.d.ts.map +1 -0
  64. package/dist/components/FoldEditorPanel.js +65 -0
  65. package/dist/components/FoldEditorPanel.js.map +1 -0
  66. package/dist/components/FoldPreviewOverlay.d.ts +48 -0
  67. package/dist/components/FoldPreviewOverlay.d.ts.map +1 -0
  68. package/dist/components/FoldPreviewOverlay.js +182 -0
  69. package/dist/components/FoldPreviewOverlay.js.map +1 -0
  70. package/dist/components/Gs1DigitalLinkPanel.d.ts +103 -0
  71. package/dist/components/Gs1DigitalLinkPanel.d.ts.map +1 -0
  72. package/dist/components/Gs1DigitalLinkPanel.js +199 -0
  73. package/dist/components/Gs1DigitalLinkPanel.js.map +1 -0
  74. package/dist/components/HistoryPanel.d.ts +39 -0
  75. package/dist/components/HistoryPanel.d.ts.map +1 -0
  76. package/dist/components/HistoryPanel.js +72 -0
  77. package/dist/components/HistoryPanel.js.map +1 -0
  78. package/dist/components/IccSoftProofOverlay.d.ts +67 -0
  79. package/dist/components/IccSoftProofOverlay.d.ts.map +1 -0
  80. package/dist/components/IccSoftProofOverlay.js +119 -0
  81. package/dist/components/IccSoftProofOverlay.js.map +1 -0
  82. package/dist/components/ImposePanel.d.ts +71 -0
  83. package/dist/components/ImposePanel.d.ts.map +1 -0
  84. package/dist/components/ImposePanel.js +127 -0
  85. package/dist/components/ImposePanel.js.map +1 -0
  86. package/dist/components/InksPanel.d.ts +61 -0
  87. package/dist/components/InksPanel.d.ts.map +1 -0
  88. package/dist/components/InksPanel.js +84 -0
  89. package/dist/components/InksPanel.js.map +1 -0
  90. package/dist/components/JobSetupPanel.d.ts +118 -0
  91. package/dist/components/JobSetupPanel.d.ts.map +1 -0
  92. package/dist/components/JobSetupPanel.js +169 -0
  93. package/dist/components/JobSetupPanel.js.map +1 -0
  94. package/dist/components/LayersPanel.d.ts.map +1 -1
  95. package/dist/components/LayersPanel.js +1 -0
  96. package/dist/components/LayersPanel.js.map +1 -1
  97. package/dist/components/MarkLibraryPanel.d.ts +131 -0
  98. package/dist/components/MarkLibraryPanel.d.ts.map +1 -0
  99. package/dist/components/MarkLibraryPanel.js +184 -0
  100. package/dist/components/MarkLibraryPanel.js.map +1 -0
  101. package/dist/components/MisEstimateButton.d.ts +73 -0
  102. package/dist/components/MisEstimateButton.d.ts.map +1 -0
  103. package/dist/components/MisEstimateButton.js +57 -0
  104. package/dist/components/MisEstimateButton.js.map +1 -0
  105. package/dist/components/NutritionPanel.d.ts +118 -0
  106. package/dist/components/NutritionPanel.d.ts.map +1 -0
  107. package/dist/components/NutritionPanel.js +169 -0
  108. package/dist/components/NutritionPanel.js.map +1 -0
  109. package/dist/components/PageNavigator.d.ts.map +1 -1
  110. package/dist/components/PageNavigator.js +6 -1
  111. package/dist/components/PageNavigator.js.map +1 -1
  112. package/dist/components/PaletteManager.d.ts +32 -0
  113. package/dist/components/PaletteManager.d.ts.map +1 -0
  114. package/dist/components/PaletteManager.js +89 -0
  115. package/dist/components/PaletteManager.js.map +1 -0
  116. package/dist/components/PaletteToSpotPanel.d.ts +122 -0
  117. package/dist/components/PaletteToSpotPanel.d.ts.map +1 -0
  118. package/dist/components/PaletteToSpotPanel.js +160 -0
  119. package/dist/components/PaletteToSpotPanel.js.map +1 -0
  120. package/dist/components/PreflightAutoFixPanel.d.ts +110 -0
  121. package/dist/components/PreflightAutoFixPanel.d.ts.map +1 -0
  122. package/dist/components/PreflightAutoFixPanel.js +119 -0
  123. package/dist/components/PreflightAutoFixPanel.js.map +1 -0
  124. package/dist/components/PreflightDiffPanel.d.ts +127 -0
  125. package/dist/components/PreflightDiffPanel.d.ts.map +1 -0
  126. package/dist/components/PreflightDiffPanel.js +0 -0
  127. package/dist/components/PreflightDiffPanel.js.map +1 -0
  128. package/dist/components/ProcessRulesPanel.d.ts +81 -0
  129. package/dist/components/ProcessRulesPanel.d.ts.map +1 -0
  130. package/dist/components/ProcessRulesPanel.js +143 -0
  131. package/dist/components/ProcessRulesPanel.js.map +1 -0
  132. package/dist/components/SlackNotifyPanel.d.ts +139 -0
  133. package/dist/components/SlackNotifyPanel.d.ts.map +1 -0
  134. package/dist/components/SlackNotifyPanel.js +133 -0
  135. package/dist/components/SlackNotifyPanel.js.map +1 -0
  136. package/dist/components/SmartSpotMatchPanel.d.ts +143 -0
  137. package/dist/components/SmartSpotMatchPanel.d.ts.map +1 -0
  138. package/dist/components/SmartSpotMatchPanel.js +159 -0
  139. package/dist/components/SmartSpotMatchPanel.js.map +1 -0
  140. package/dist/components/StreamingRenderProgress.d.ts +60 -0
  141. package/dist/components/StreamingRenderProgress.d.ts.map +1 -0
  142. package/dist/components/StreamingRenderProgress.js +99 -0
  143. package/dist/components/StreamingRenderProgress.js.map +1 -0
  144. package/dist/components/SwatchesPicker.d.ts +83 -0
  145. package/dist/components/SwatchesPicker.d.ts.map +1 -0
  146. package/dist/components/SwatchesPicker.js +151 -0
  147. package/dist/components/SwatchesPicker.js.map +1 -0
  148. package/dist/components/TacOverlay.d.ts +47 -0
  149. package/dist/components/TacOverlay.d.ts.map +1 -0
  150. package/dist/components/TacOverlay.js +116 -0
  151. package/dist/components/TacOverlay.js.map +1 -0
  152. package/dist/components/TrapEditorPanel.d.ts +52 -0
  153. package/dist/components/TrapEditorPanel.d.ts.map +1 -0
  154. package/dist/components/TrapEditorPanel.js +64 -0
  155. package/dist/components/TrapEditorPanel.js.map +1 -0
  156. package/dist/components/TrapPreviewOverlay.d.ts +64 -0
  157. package/dist/components/TrapPreviewOverlay.d.ts.map +1 -0
  158. package/dist/components/TrapPreviewOverlay.js +120 -0
  159. package/dist/components/TrapPreviewOverlay.js.map +1 -0
  160. package/dist/components/VariantMatrixPanel.d.ts +61 -0
  161. package/dist/components/VariantMatrixPanel.d.ts.map +1 -0
  162. package/dist/components/VariantMatrixPanel.js +97 -0
  163. package/dist/components/VariantMatrixPanel.js.map +1 -0
  164. package/dist/components/VariantMatrixVersionPanel.d.ts +122 -0
  165. package/dist/components/VariantMatrixVersionPanel.d.ts.map +1 -0
  166. package/dist/components/VariantMatrixVersionPanel.js +162 -0
  167. package/dist/components/VariantMatrixVersionPanel.js.map +1 -0
  168. package/dist/components/WebhookNotifyPanel.d.ts +160 -0
  169. package/dist/components/WebhookNotifyPanel.d.ts.map +1 -0
  170. package/dist/components/WebhookNotifyPanel.js +100 -0
  171. package/dist/components/WebhookNotifyPanel.js.map +1 -0
  172. package/dist/components/WhiteUnderbasePanel.d.ts +107 -0
  173. package/dist/components/WhiteUnderbasePanel.d.ts.map +1 -0
  174. package/dist/components/WhiteUnderbasePanel.js +104 -0
  175. package/dist/components/WhiteUnderbasePanel.js.map +1 -0
  176. package/dist/hooks/useEditorMode.d.ts +25 -5
  177. package/dist/hooks/useEditorMode.d.ts.map +1 -1
  178. package/dist/hooks/useEditorMode.js +18 -5
  179. package/dist/hooks/useEditorMode.js.map +1 -1
  180. package/dist/index.d.ts +51 -2
  181. package/dist/index.d.ts.map +1 -1
  182. package/dist/index.js +51 -2
  183. package/dist/index.js.map +1 -1
  184. package/dist/lens/preflight-findings.d.ts.map +1 -1
  185. package/dist/lens/preflight-findings.js.map +1 -1
  186. package/dist/lib/barcode-scan.d.ts +154 -0
  187. package/dist/lib/barcode-scan.d.ts.map +1 -0
  188. package/dist/lib/barcode-scan.js +152 -0
  189. package/dist/lib/barcode-scan.js.map +1 -0
  190. package/dist/lib/color-math.d.ts +76 -0
  191. package/dist/lib/color-math.d.ts.map +1 -0
  192. package/dist/lib/color-math.js +96 -0
  193. package/dist/lib/color-math.js.map +1 -0
  194. package/dist/lib/dieline-template.d.ts +87 -0
  195. package/dist/lib/dieline-template.d.ts.map +1 -1
  196. package/dist/lib/dieline-template.js +163 -0
  197. package/dist/lib/dieline-template.js.map +1 -1
  198. package/dist/lib/editor-config.d.ts +390 -0
  199. package/dist/lib/editor-config.d.ts.map +1 -1
  200. package/dist/lib/editor-config.js +90 -0
  201. package/dist/lib/editor-config.js.map +1 -1
  202. package/dist/lib/fold-geometry.d.ts +144 -0
  203. package/dist/lib/fold-geometry.d.ts.map +1 -0
  204. package/dist/lib/fold-geometry.js +138 -0
  205. package/dist/lib/fold-geometry.js.map +1 -0
  206. package/dist/lib/merge-tokens.d.ts +81 -0
  207. package/dist/lib/merge-tokens.d.ts.map +1 -0
  208. package/dist/lib/merge-tokens.js +88 -0
  209. package/dist/lib/merge-tokens.js.map +1 -0
  210. package/dist/lib/palette-registry.d.ts +40 -0
  211. package/dist/lib/palette-registry.d.ts.map +1 -0
  212. package/dist/lib/palette-registry.js +50 -0
  213. package/dist/lib/palette-registry.js.map +1 -0
  214. package/dist/lib/panel-anchor.d.ts +101 -0
  215. package/dist/lib/panel-anchor.d.ts.map +1 -0
  216. package/dist/lib/panel-anchor.js +68 -0
  217. package/dist/lib/panel-anchor.js.map +1 -0
  218. package/dist/lib/preflight/checks.d.ts.map +1 -1
  219. package/dist/lib/preflight/checks.js +71 -0
  220. package/dist/lib/preflight/checks.js.map +1 -1
  221. package/dist/lib/preflight/types.d.ts.map +1 -1
  222. package/dist/lib/preflight/types.js +11 -0
  223. package/dist/lib/preflight/types.js.map +1 -1
  224. package/dist/lib/rasterize.d.ts +93 -0
  225. package/dist/lib/rasterize.d.ts.map +1 -0
  226. package/dist/lib/rasterize.js +117 -0
  227. package/dist/lib/rasterize.js.map +1 -0
  228. package/dist/lib/separations-registry.d.ts +99 -0
  229. package/dist/lib/separations-registry.d.ts.map +1 -0
  230. package/dist/lib/separations-registry.js +59 -0
  231. package/dist/lib/separations-registry.js.map +1 -0
  232. package/dist/lib/streaming-render.d.ts +100 -0
  233. package/dist/lib/streaming-render.d.ts.map +1 -0
  234. package/dist/lib/streaming-render.js +132 -0
  235. package/dist/lib/streaming-render.js.map +1 -0
  236. package/dist/lib/unwired.d.ts +29 -0
  237. package/dist/lib/unwired.d.ts.map +1 -0
  238. package/dist/lib/unwired.js +58 -0
  239. package/dist/lib/unwired.js.map +1 -0
  240. package/package.json +20 -11
  241. package/dist/components/SeparationsPanel.d.ts +0 -9
  242. package/dist/components/SeparationsPanel.d.ts.map +0 -1
  243. package/dist/components/SeparationsPanel.js +0 -168
  244. package/dist/components/SeparationsPanel.js.map +0 -1
@@ -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":"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"}
@@ -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"}
@@ -0,0 +1,120 @@
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
+ /**
6
+ * D1 background trap-preview overlay.
7
+ *
8
+ * Sits as an absolutely-positioned `<canvas>` on top of the Konva
9
+ * Stage, debouncing calls to a host-supplied
10
+ * {@link TrapPreviewFn} on every change to the `trigger` prop. Paints
11
+ * a translucent cyan band over each predicted trap region from the
12
+ * server's trap-diff so users see where ink spreading / choking will
13
+ * happen before submitting a full render.
14
+ *
15
+ * Approximate preview — uses the metadata-only `/v1/trap/preview`
16
+ * endpoint (compile-pdf PR #38) which runs the same trap analysis as
17
+ * `/trap/apply` but skips the PDF write. Users wanting bit-exact
18
+ * preview must still run a full job.
19
+ *
20
+ * @public
21
+ */
22
+ /** Wipes any previously drawn trap rectangles. Called from every
23
+ * "no overlay should be visible right now" branch so the canvas
24
+ * doesn't keep stale visuals after the user disables the feature
25
+ * or the preview request fails. */
26
+ function clearOverlayCanvas(canvas) {
27
+ if (!canvas)
28
+ return;
29
+ const ctx = canvas.getContext("2d");
30
+ if (!ctx)
31
+ return;
32
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
33
+ }
34
+ export function TrapPreviewOverlay({ width, height, pageIndex, pointsToPx, trigger, previewFn, debounceMs = 500, }) {
35
+ const canvasRef = useRef(null);
36
+ const [opsCount, setOpsCount] = useState(null);
37
+ const reqIdRef = useRef(0);
38
+ useEffect(() => {
39
+ // `trigger` is intentionally read here (no-op `void` cast) so the
40
+ // exhaustive-deps lint sees it as used; the actual value is never
41
+ // consumed — only its identity change is meaningful.
42
+ void trigger;
43
+ if (!previewFn || width <= 0 || height <= 0) {
44
+ // Reset BOTH state and canvas — otherwise the previously drawn
45
+ // trap bands stay visible after the user disables the feature
46
+ // via `enable_trap_preview` or the container collapses to 0×0.
47
+ setOpsCount(null);
48
+ clearOverlayCanvas(canvasRef.current);
49
+ return;
50
+ }
51
+ reqIdRef.current += 1;
52
+ const myReqId = reqIdRef.current;
53
+ const handle = setTimeout(async () => {
54
+ let result;
55
+ try {
56
+ result = await previewFn();
57
+ }
58
+ catch {
59
+ // Network / server failure — clear the overlay and stop. We
60
+ // don't surface the error because trap preview is advisory;
61
+ // failures shouldn't block editing.
62
+ if (myReqId === reqIdRef.current) {
63
+ setOpsCount(null);
64
+ clearOverlayCanvas(canvasRef.current);
65
+ }
66
+ return;
67
+ }
68
+ // Stale-response guard: a newer request fired while this one
69
+ // was in-flight; drop the result.
70
+ if (myReqId !== reqIdRef.current)
71
+ return;
72
+ // The server emits 0-indexed `page_index` (compile-pdf's
73
+ // `TrapZone.page_index: NonNegativeInt`); our prop is 1-indexed
74
+ // to match PDF user-facing page numbers. Convert at the boundary.
75
+ const pageOps = result.operations.filter((o) => o.page_index === pageIndex - 1);
76
+ setOpsCount(pageOps.length);
77
+ const canvas = canvasRef.current;
78
+ if (!canvas)
79
+ return;
80
+ canvas.width = Math.round(width);
81
+ canvas.height = Math.round(height);
82
+ const ctx = canvas.getContext("2d");
83
+ if (!ctx)
84
+ return;
85
+ ctx.clearRect(0, 0, canvas.width, canvas.height);
86
+ ctx.fillStyle = "rgba(14, 165, 233, 0.45)";
87
+ for (const op of pageOps) {
88
+ const [llx, lly, urx, ury] = op.rect_pt;
89
+ const x = llx * pointsToPx;
90
+ // PDF coords are y-up from bottom; canvas coords are y-down
91
+ // from top. Mirror against the container height so traps land
92
+ // where the user sees them on screen.
93
+ const y = canvas.height - ury * pointsToPx;
94
+ const w = (urx - llx) * pointsToPx;
95
+ const h = (ury - lly) * pointsToPx;
96
+ ctx.fillRect(x, y, w, h);
97
+ }
98
+ }, debounceMs);
99
+ return () => clearTimeout(handle);
100
+ }, [width, height, pageIndex, pointsToPx, trigger, previewFn, debounceMs]);
101
+ return (_jsxs(_Fragment, { children: [_jsx("canvas", { ref: canvasRef, style: {
102
+ position: "absolute",
103
+ inset: 0,
104
+ width: `${width}px`,
105
+ height: `${height}px`,
106
+ pointerEvents: "none",
107
+ } }), opsCount !== null && opsCount > 0 && (_jsxs("output", { "aria-label": "Trap preview operations", style: {
108
+ position: "absolute",
109
+ bottom: 8,
110
+ right: 8,
111
+ padding: "0.25rem 0.5rem",
112
+ background: "rgba(14, 116, 144, 0.85)",
113
+ color: "#f0f9ff",
114
+ fontSize: "0.7rem",
115
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
116
+ borderRadius: 4,
117
+ pointerEvents: "none",
118
+ }, children: [opsCount, " trap", opsCount === 1 ? "" : "s"] }))] }));
119
+ }
120
+ //# sourceMappingURL=TrapPreviewOverlay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TrapPreviewOverlay.js","sourceRoot":"","sources":["../../src/components/TrapPreviewOverlay.tsx"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;;AAEb,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAmEpD;;;;;;;;;;;;;;;;GAgBG;AACH;;;oCAGoC;AACpC,SAAS,kBAAkB,CAAC,MAAgC;IAC1D,IAAI,CAAC,MAAM;QAAE,OAAO;IACpB,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IACpC,IAAI,CAAC,GAAG;QAAE,OAAO;IACjB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EACjC,KAAK,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,OAAO,EACP,SAAS,EACT,UAAU,GAAG,GAAG,GACQ;IACxB,MAAM,SAAS,GAAG,MAAM,CAAoB,IAAI,CAAC,CAAC;IAClD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC9D,MAAM,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAE3B,SAAS,CAAC,GAAG,EAAE;QACb,kEAAkE;QAClE,kEAAkE;QAClE,qDAAqD;QACrD,KAAK,OAAO,CAAC;QACb,IAAI,CAAC,SAAS,IAAI,KAAK,IAAI,CAAC,IAAI,MAAM,IAAI,CAAC,EAAE,CAAC;YAC5C,+DAA+D;YAC/D,8DAA8D;YAC9D,+DAA+D;YAC/D,WAAW,CAAC,IAAI,CAAC,CAAC;YAClB,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACtC,OAAO;QACT,CAAC;QACD,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;QACtB,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC;QACjC,MAAM,MAAM,GAAG,UAAU,CAAC,KAAK,IAAI,EAAE;YACnC,IAAI,MAA0C,CAAC;YAC/C,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;YAC7B,CAAC;YAAC,MAAM,CAAC;gBACP,4DAA4D;gBAC5D,4DAA4D;gBAC5D,oCAAoC;gBACpC,IAAI,OAAO,KAAK,QAAQ,CAAC,OAAO,EAAE,CAAC;oBACjC,WAAW,CAAC,IAAI,CAAC,CAAC;oBAClB,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;gBACxC,CAAC;gBACD,OAAO;YACT,CAAC;YACD,6DAA6D;YAC7D,kCAAkC;YAClC,IAAI,OAAO,KAAK,QAAQ,CAAC,OAAO;gBAAE,OAAO;YAEzC,yDAAyD;YACzD,gEAAgE;YAChE,kEAAkE;YAClE,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,GAAG,CAAC,CAAC,CAAC;YAChF,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YAE5B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC;YACjC,IAAI,CAAC,MAAM;gBAAE,OAAO;YACpB,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACjC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACnC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,GAAG;gBAAE,OAAO;YACjB,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;YACjD,GAAG,CAAC,SAAS,GAAG,0BAA0B,CAAC;YAC3C,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;gBACzB,MAAM,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC;gBACxC,MAAM,CAAC,GAAG,GAAG,GAAG,UAAU,CAAC;gBAC3B,4DAA4D;gBAC5D,8DAA8D;gBAC9D,sCAAsC;gBACtC,MAAM,CAAC,GAAG,MAAM,CAAC,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC;gBAC3C,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;gBACnC,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,UAAU,CAAC;gBACnC,GAAG,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,EAAE,UAAU,CAAC,CAAC;QACf,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;IACpC,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC;IAE3E,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,QAAQ,KAAK,IAAI,IAAI,QAAQ,GAAG,CAAC,IAAI,CACpC,gCACa,yBAAyB,EACpC,KAAK,EAAE;oBACL,QAAQ,EAAE,UAAU;oBACpB,MAAM,EAAE,CAAC;oBACT,KAAK,EAAE,CAAC;oBACR,OAAO,EAAE,gBAAgB;oBACzB,UAAU,EAAE,0BAA0B;oBACtC,KAAK,EAAE,SAAS;oBAChB,QAAQ,EAAE,QAAQ;oBAClB,UAAU,EAAE,gDAAgD;oBAC5D,YAAY,EAAE,CAAC;oBACf,aAAa,EAAE,MAAM;iBACtB,aAEA,QAAQ,WAAO,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,IAClC,CACV,IACA,CACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Wave 2 V2 — variant matrix UI for variable-data overrides.
3
+ *
4
+ * One row per {@link Variant}; one editable column per token in
5
+ * `tokenKeys`. The token columns mirror the document-level
6
+ * `variableData` token keys; each `Variant.overrides` maps a subset
7
+ * of those keys to variant-specific values. Absent keys inherit the
8
+ * document's defaults at merge time (Wave 3 V1).
9
+ *
10
+ * Structurally mirrors `@artworkpdf/document-model`'s `VariantMatrix`
11
+ * — inlined here so the editor stays consumable without
12
+ * document-model (same pattern as `EditorSeparation`,
13
+ * `FoldGeometryPanelMetadata`).
14
+ *
15
+ * Controlled component: pass `value` + `onChange`, panel reflects
16
+ * mutations back to the host on every keystroke. Hosts that need
17
+ * batched commits should debounce externally.
18
+ *
19
+ * @public
20
+ */
21
+ /**
22
+ * One row of a {@link VariantMatrixPanelValue}.
23
+ *
24
+ * @public
25
+ */
26
+ export type VariantMatrixPanelVariant = {
27
+ id: string;
28
+ name: string;
29
+ overrides: Record<string, string>;
30
+ };
31
+ /**
32
+ * Controlled value for the panel — the cross-product of variants
33
+ * (rows) × token keys (columns).
34
+ *
35
+ * @public
36
+ */
37
+ export type VariantMatrixPanelValue = {
38
+ tokenKeys: string[];
39
+ variants: VariantMatrixPanelVariant[];
40
+ };
41
+ /**
42
+ * @public
43
+ */
44
+ export type VariantMatrixPanelProps = {
45
+ /** Current matrix. `undefined` means "no variants configured" —
46
+ * the panel offers an empty matrix with the document's token
47
+ * keys as columns. */
48
+ value: VariantMatrixPanelValue | undefined;
49
+ /** Fires on every change to a variant row, a token cell, or a
50
+ * token key. Hosts thread this into `document.variants`. */
51
+ onChange: (next: VariantMatrixPanelValue) => void;
52
+ /** Optional initial token keys to surface when `value` is
53
+ * `undefined` — typically the document-level `variableData`
54
+ * keys, so the matrix immediately reflects the merge surface. */
55
+ initialTokenKeys?: readonly string[];
56
+ };
57
+ /**
58
+ * @public
59
+ */
60
+ export declare function VariantMatrixPanel({ value, onChange, initialTokenKeys }: VariantMatrixPanelProps): import("react/jsx-runtime").JSX.Element;
61
+ //# sourceMappingURL=VariantMatrixPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantMatrixPanel.d.ts","sourceRoot":"","sources":["../../src/components/VariantMatrixPanel.tsx"],"names":[],"mappings":"AAKA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;GAIG;AACH,MAAM,MAAM,yBAAyB,GAAG;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACnC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,QAAQ,EAAE,yBAAyB,EAAE,CAAC;CACvC,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC;;2BAEuB;IACvB,KAAK,EAAE,uBAAuB,GAAG,SAAS,CAAC;IAC3C;iEAC6D;IAC7D,QAAQ,EAAE,CAAC,IAAI,EAAE,uBAAuB,KAAK,IAAI,CAAC;IAClD;;sEAEkE;IAClE,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACtC,CAAC;AAEF;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,gBAAgB,EAAE,EAAE,uBAAuB,2CAsJhG"}
@@ -0,0 +1,97 @@
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 { useMemo, useRef } from "react";
5
+ /**
6
+ * @public
7
+ */
8
+ export function VariantMatrixPanel({ value, onChange, initialTokenKeys }) {
9
+ const effective = useMemo(() => {
10
+ if (value)
11
+ return value;
12
+ return {
13
+ tokenKeys: initialTokenKeys ? [...initialTokenKeys] : [],
14
+ variants: [],
15
+ };
16
+ }, [value, initialTokenKeys]);
17
+ // Monotonic counter to keep variant IDs stable across delete-then-add
18
+ // cycles. Length-derived ids (`v-${length + 1}`) collide whenever a
19
+ // middle row is removed and a new one added, which produces duplicate
20
+ // React keys and mis-targets row-level updates.
21
+ const nextVariantSuffix = useRef(1);
22
+ const addVariant = () => {
23
+ const used = new Set(effective.variants.map((v) => v.id));
24
+ let n = nextVariantSuffix.current;
25
+ let id = `v-${n}`;
26
+ while (used.has(id)) {
27
+ n += 1;
28
+ id = `v-${n}`;
29
+ }
30
+ nextVariantSuffix.current = n + 1;
31
+ onChange({
32
+ ...effective,
33
+ variants: [...effective.variants, { id, name: `Variant ${n}`, overrides: {} }],
34
+ });
35
+ };
36
+ const removeVariant = (id) => {
37
+ onChange({
38
+ ...effective,
39
+ variants: effective.variants.filter((v) => v.id !== id),
40
+ });
41
+ };
42
+ const renameVariant = (id, name) => {
43
+ onChange({
44
+ ...effective,
45
+ variants: effective.variants.map((v) => (v.id === id ? { ...v, name } : v)),
46
+ });
47
+ };
48
+ const setOverride = (id, key, val) => {
49
+ onChange({
50
+ ...effective,
51
+ variants: effective.variants.map((v) => {
52
+ if (v.id !== id)
53
+ return v;
54
+ // Empty string means "clear the override" — drop the key so the
55
+ // variant falls back to the document-level default at merge
56
+ // time. Storing `""` would pin the override to an empty string,
57
+ // which is a different (and surprising) semantic.
58
+ if (val === "") {
59
+ const { [key]: _removed, ...rest } = v.overrides;
60
+ return { ...v, overrides: rest };
61
+ }
62
+ return { ...v, overrides: { ...v.overrides, [key]: val } };
63
+ }),
64
+ });
65
+ };
66
+ const addTokenKey = (key) => {
67
+ const trimmed = key.trim();
68
+ if (!trimmed || effective.tokenKeys.includes(trimmed))
69
+ return;
70
+ onChange({ ...effective, tokenKeys: [...effective.tokenKeys, trimmed] });
71
+ };
72
+ const removeTokenKey = (key) => {
73
+ onChange({
74
+ ...effective,
75
+ tokenKeys: effective.tokenKeys.filter((k) => k !== key),
76
+ variants: effective.variants.map((v) => {
77
+ if (!(key in v.overrides))
78
+ return v;
79
+ const { [key]: _removed, ...rest } = v.overrides;
80
+ return { ...v, overrides: rest };
81
+ }),
82
+ });
83
+ };
84
+ return (_jsxs("div", { "data-testid": "variant-matrix-panel", style: { padding: "0.5rem" }, children: [_jsxs("header", { style: { display: "flex", gap: "0.5rem", alignItems: "baseline" }, children: [_jsx("h3", { style: { margin: 0 }, children: "Variants" }), _jsx("button", { type: "button", onClick: addVariant, "aria-label": "Add variant", children: "+ variant" }), _jsx(TokenKeyAdder, { onAdd: addTokenKey })] }), effective.variants.length === 0 ? (_jsxs("p", { style: { opacity: 0.6 }, children: ["No variants yet. Click ", _jsx("strong", { children: "+ variant" }), " to add the first row."] })) : (_jsxs("table", { style: { borderCollapse: "collapse", marginTop: "0.5rem" }, children: [_jsx("thead", { children: _jsxs("tr", { children: [_jsx("th", { children: "Name" }), effective.tokenKeys.map((k) => (_jsxs("th", { children: [k, " ", _jsx("button", { type: "button", onClick: () => removeTokenKey(k), "aria-label": `Remove token ${k}`, title: `Remove token ${k}`, children: "\u00D7" })] }, k))), _jsx("th", {})] }) }), _jsx("tbody", { children: effective.variants.map((v) => (_jsxs("tr", { children: [_jsx("td", { children: _jsx("input", { value: v.name, onChange: (e) => renameVariant(v.id, e.target.value), "aria-label": `Variant name for ${v.id}` }) }), effective.tokenKeys.map((k) => (_jsx("td", { children: _jsx("input", { value: v.overrides[k] ?? "", onChange: (e) => setOverride(v.id, k, e.target.value), "aria-label": `${v.name} override for ${k}`, placeholder: "\u2014" }) }, k))), _jsx("td", { children: _jsx("button", { type: "button", onClick: () => removeVariant(v.id), "aria-label": `Remove variant ${v.name}`, children: "\u00D7" }) })] }, v.id))) })] }))] }));
85
+ }
86
+ function TokenKeyAdder({ onAdd }) {
87
+ return (_jsxs("form", { style: { display: "inline-flex", gap: "0.25rem" }, onSubmit: (e) => {
88
+ e.preventDefault();
89
+ const form = e.currentTarget;
90
+ const input = form.elements.namedItem("token");
91
+ if (input?.value) {
92
+ onAdd(input.value);
93
+ input.value = "";
94
+ }
95
+ }, children: [_jsx("input", { name: "token", placeholder: "+ token key", "aria-label": "New token key" }), _jsx("button", { type: "submit", children: "add" })] }));
96
+ }
97
+ //# sourceMappingURL=VariantMatrixPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VariantMatrixPanel.js","sourceRoot":"","sources":["../../src/components/VariantMatrixPanel.tsx"],"names":[],"mappings":"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"}