@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.
Files changed (249) hide show
  1. package/LICENSE +62 -0
  2. package/README.md +63 -2
  3. package/dist/components/AccessibilityHintsPanel.d.ts +142 -0
  4. package/dist/components/AccessibilityHintsPanel.d.ts.map +1 -0
  5. package/dist/components/AccessibilityHintsPanel.js +158 -0
  6. package/dist/components/AccessibilityHintsPanel.js.map +1 -0
  7. package/dist/components/AnnotationOverlay.d.ts +142 -0
  8. package/dist/components/AnnotationOverlay.d.ts.map +1 -0
  9. package/dist/components/AnnotationOverlay.js +141 -0
  10. package/dist/components/AnnotationOverlay.js.map +1 -0
  11. package/dist/components/AnnotationsSidebar.d.ts +98 -0
  12. package/dist/components/AnnotationsSidebar.d.ts.map +1 -0
  13. package/dist/components/AnnotationsSidebar.js +100 -0
  14. package/dist/components/AnnotationsSidebar.js.map +1 -0
  15. package/dist/components/BarcodeGeneratorPanel.d.ts +58 -0
  16. package/dist/components/BarcodeGeneratorPanel.d.ts.map +1 -0
  17. package/dist/components/BarcodeGeneratorPanel.js +91 -0
  18. package/dist/components/BarcodeGeneratorPanel.js.map +1 -0
  19. package/dist/components/BraillePanel.d.ts +99 -0
  20. package/dist/components/BraillePanel.d.ts.map +1 -0
  21. package/dist/components/BraillePanel.js +221 -0
  22. package/dist/components/BraillePanel.js.map +1 -0
  23. package/dist/components/BrandAssetsPanel.d.ts +130 -0
  24. package/dist/components/BrandAssetsPanel.d.ts.map +1 -0
  25. package/dist/components/BrandAssetsPanel.js +125 -0
  26. package/dist/components/BrandAssetsPanel.js.map +1 -0
  27. package/dist/components/BrandConsistencyPanel.d.ts +140 -0
  28. package/dist/components/BrandConsistencyPanel.d.ts.map +1 -0
  29. package/dist/components/BrandConsistencyPanel.js +158 -0
  30. package/dist/components/BrandConsistencyPanel.js.map +1 -0
  31. package/dist/components/ComplianceFindingsPanel.d.ts +62 -0
  32. package/dist/components/ComplianceFindingsPanel.d.ts.map +1 -0
  33. package/dist/components/ComplianceFindingsPanel.js +118 -0
  34. package/dist/components/ComplianceFindingsPanel.js.map +1 -0
  35. package/dist/components/DesignSuggestionsPanel.d.ts +148 -0
  36. package/dist/components/DesignSuggestionsPanel.d.ts.map +1 -0
  37. package/dist/components/DesignSuggestionsPanel.js +154 -0
  38. package/dist/components/DesignSuggestionsPanel.js.map +1 -0
  39. package/dist/components/DielineParametersPanel.d.ts +62 -0
  40. package/dist/components/DielineParametersPanel.d.ts.map +1 -0
  41. package/dist/components/DielineParametersPanel.js +170 -0
  42. package/dist/components/DielineParametersPanel.js.map +1 -0
  43. package/dist/components/DielinePreview.d.ts +150 -0
  44. package/dist/components/DielinePreview.d.ts.map +1 -0
  45. package/dist/components/DielinePreview.js +146 -0
  46. package/dist/components/DielinePreview.js.map +1 -0
  47. package/dist/components/EditorApp.d.ts +39 -5
  48. package/dist/components/EditorApp.d.ts.map +1 -1
  49. package/dist/components/EditorApp.js +110 -5
  50. package/dist/components/EditorApp.js.map +1 -1
  51. package/dist/components/EditorCanvas.d.ts +51 -2
  52. package/dist/components/EditorCanvas.d.ts.map +1 -1
  53. package/dist/components/EditorCanvas.js +117 -48
  54. package/dist/components/EditorCanvas.js.map +1 -1
  55. package/dist/components/EmailNotifyPanel.d.ts +165 -0
  56. package/dist/components/EmailNotifyPanel.d.ts.map +1 -0
  57. package/dist/components/EmailNotifyPanel.js +211 -0
  58. package/dist/components/EmailNotifyPanel.js.map +1 -0
  59. package/dist/components/FileDropZone.d.ts +9 -1
  60. package/dist/components/FileDropZone.d.ts.map +1 -1
  61. package/dist/components/FileDropZone.js +53 -5
  62. package/dist/components/FileDropZone.js.map +1 -1
  63. package/dist/components/FoldEditorPanel.d.ts +68 -0
  64. package/dist/components/FoldEditorPanel.d.ts.map +1 -0
  65. package/dist/components/FoldEditorPanel.js +65 -0
  66. package/dist/components/FoldEditorPanel.js.map +1 -0
  67. package/dist/components/FoldPreviewOverlay.d.ts +48 -0
  68. package/dist/components/FoldPreviewOverlay.d.ts.map +1 -0
  69. package/dist/components/FoldPreviewOverlay.js +182 -0
  70. package/dist/components/FoldPreviewOverlay.js.map +1 -0
  71. package/dist/components/Gs1DigitalLinkPanel.d.ts +103 -0
  72. package/dist/components/Gs1DigitalLinkPanel.d.ts.map +1 -0
  73. package/dist/components/Gs1DigitalLinkPanel.js +199 -0
  74. package/dist/components/Gs1DigitalLinkPanel.js.map +1 -0
  75. package/dist/components/HistoryPanel.d.ts +39 -0
  76. package/dist/components/HistoryPanel.d.ts.map +1 -0
  77. package/dist/components/HistoryPanel.js +72 -0
  78. package/dist/components/HistoryPanel.js.map +1 -0
  79. package/dist/components/IccSoftProofOverlay.d.ts +67 -0
  80. package/dist/components/IccSoftProofOverlay.d.ts.map +1 -0
  81. package/dist/components/IccSoftProofOverlay.js +119 -0
  82. package/dist/components/IccSoftProofOverlay.js.map +1 -0
  83. package/dist/components/ImposePanel.d.ts +71 -0
  84. package/dist/components/ImposePanel.d.ts.map +1 -0
  85. package/dist/components/ImposePanel.js +127 -0
  86. package/dist/components/ImposePanel.js.map +1 -0
  87. package/dist/components/InksPanel.d.ts +61 -0
  88. package/dist/components/InksPanel.d.ts.map +1 -0
  89. package/dist/components/InksPanel.js +84 -0
  90. package/dist/components/InksPanel.js.map +1 -0
  91. package/dist/components/JobSetupPanel.d.ts +118 -0
  92. package/dist/components/JobSetupPanel.d.ts.map +1 -0
  93. package/dist/components/JobSetupPanel.js +169 -0
  94. package/dist/components/JobSetupPanel.js.map +1 -0
  95. package/dist/components/LayersPanel.d.ts.map +1 -1
  96. package/dist/components/LayersPanel.js +1 -0
  97. package/dist/components/LayersPanel.js.map +1 -1
  98. package/dist/components/MarkLibraryPanel.d.ts +131 -0
  99. package/dist/components/MarkLibraryPanel.d.ts.map +1 -0
  100. package/dist/components/MarkLibraryPanel.js +184 -0
  101. package/dist/components/MarkLibraryPanel.js.map +1 -0
  102. package/dist/components/MisEstimateButton.d.ts +73 -0
  103. package/dist/components/MisEstimateButton.d.ts.map +1 -0
  104. package/dist/components/MisEstimateButton.js +57 -0
  105. package/dist/components/MisEstimateButton.js.map +1 -0
  106. package/dist/components/NutritionPanel.d.ts +118 -0
  107. package/dist/components/NutritionPanel.d.ts.map +1 -0
  108. package/dist/components/NutritionPanel.js +169 -0
  109. package/dist/components/NutritionPanel.js.map +1 -0
  110. package/dist/components/PageNavigator.d.ts +26 -0
  111. package/dist/components/PageNavigator.d.ts.map +1 -0
  112. package/dist/components/PageNavigator.js +96 -0
  113. package/dist/components/PageNavigator.js.map +1 -0
  114. package/dist/components/PaletteManager.d.ts +32 -0
  115. package/dist/components/PaletteManager.d.ts.map +1 -0
  116. package/dist/components/PaletteManager.js +89 -0
  117. package/dist/components/PaletteManager.js.map +1 -0
  118. package/dist/components/PaletteToSpotPanel.d.ts +122 -0
  119. package/dist/components/PaletteToSpotPanel.d.ts.map +1 -0
  120. package/dist/components/PaletteToSpotPanel.js +160 -0
  121. package/dist/components/PaletteToSpotPanel.js.map +1 -0
  122. package/dist/components/PreflightAutoFixPanel.d.ts +110 -0
  123. package/dist/components/PreflightAutoFixPanel.d.ts.map +1 -0
  124. package/dist/components/PreflightAutoFixPanel.js +119 -0
  125. package/dist/components/PreflightAutoFixPanel.js.map +1 -0
  126. package/dist/components/PreflightDiffPanel.d.ts +127 -0
  127. package/dist/components/PreflightDiffPanel.d.ts.map +1 -0
  128. package/dist/components/PreflightDiffPanel.js +0 -0
  129. package/dist/components/PreflightDiffPanel.js.map +1 -0
  130. package/dist/components/ProcessRulesPanel.d.ts +81 -0
  131. package/dist/components/ProcessRulesPanel.d.ts.map +1 -0
  132. package/dist/components/ProcessRulesPanel.js +143 -0
  133. package/dist/components/ProcessRulesPanel.js.map +1 -0
  134. package/dist/components/SlackNotifyPanel.d.ts +139 -0
  135. package/dist/components/SlackNotifyPanel.d.ts.map +1 -0
  136. package/dist/components/SlackNotifyPanel.js +133 -0
  137. package/dist/components/SlackNotifyPanel.js.map +1 -0
  138. package/dist/components/SmartSpotMatchPanel.d.ts +143 -0
  139. package/dist/components/SmartSpotMatchPanel.d.ts.map +1 -0
  140. package/dist/components/SmartSpotMatchPanel.js +159 -0
  141. package/dist/components/SmartSpotMatchPanel.js.map +1 -0
  142. package/dist/components/SwatchesPicker.d.ts +83 -0
  143. package/dist/components/SwatchesPicker.d.ts.map +1 -0
  144. package/dist/components/SwatchesPicker.js +151 -0
  145. package/dist/components/SwatchesPicker.js.map +1 -0
  146. package/dist/components/TacOverlay.d.ts +47 -0
  147. package/dist/components/TacOverlay.d.ts.map +1 -0
  148. package/dist/components/TacOverlay.js +116 -0
  149. package/dist/components/TacOverlay.js.map +1 -0
  150. package/dist/components/TrapEditorPanel.d.ts +52 -0
  151. package/dist/components/TrapEditorPanel.d.ts.map +1 -0
  152. package/dist/components/TrapEditorPanel.js +64 -0
  153. package/dist/components/TrapEditorPanel.js.map +1 -0
  154. package/dist/components/TrapPreviewOverlay.d.ts +64 -0
  155. package/dist/components/TrapPreviewOverlay.d.ts.map +1 -0
  156. package/dist/components/TrapPreviewOverlay.js +120 -0
  157. package/dist/components/TrapPreviewOverlay.js.map +1 -0
  158. package/dist/components/VariantMatrixPanel.d.ts +61 -0
  159. package/dist/components/VariantMatrixPanel.d.ts.map +1 -0
  160. package/dist/components/VariantMatrixPanel.js +97 -0
  161. package/dist/components/VariantMatrixPanel.js.map +1 -0
  162. package/dist/components/VariantMatrixVersionPanel.d.ts +122 -0
  163. package/dist/components/VariantMatrixVersionPanel.d.ts.map +1 -0
  164. package/dist/components/VariantMatrixVersionPanel.js +162 -0
  165. package/dist/components/VariantMatrixVersionPanel.js.map +1 -0
  166. package/dist/components/WebhookNotifyPanel.d.ts +160 -0
  167. package/dist/components/WebhookNotifyPanel.d.ts.map +1 -0
  168. package/dist/components/WebhookNotifyPanel.js +100 -0
  169. package/dist/components/WebhookNotifyPanel.js.map +1 -0
  170. package/dist/components/WhiteUnderbasePanel.d.ts +107 -0
  171. package/dist/components/WhiteUnderbasePanel.d.ts.map +1 -0
  172. package/dist/components/WhiteUnderbasePanel.js +104 -0
  173. package/dist/components/WhiteUnderbasePanel.js.map +1 -0
  174. package/dist/data/dielines.json +35 -0
  175. package/dist/hooks/useEditorMode.d.ts +25 -5
  176. package/dist/hooks/useEditorMode.d.ts.map +1 -1
  177. package/dist/hooks/useEditorMode.js +18 -5
  178. package/dist/hooks/useEditorMode.js.map +1 -1
  179. package/dist/index.d.ts +49 -2
  180. package/dist/index.d.ts.map +1 -1
  181. package/dist/index.js +49 -2
  182. package/dist/index.js.map +1 -1
  183. package/dist/lens/dieline-overlay.d.ts +25 -0
  184. package/dist/lens/dieline-overlay.d.ts.map +1 -0
  185. package/dist/lens/dieline-overlay.js +50 -0
  186. package/dist/lens/dieline-overlay.js.map +1 -0
  187. package/dist/lens/index.d.ts +27 -0
  188. package/dist/lens/index.d.ts.map +1 -0
  189. package/dist/lens/index.js +28 -0
  190. package/dist/lens/index.js.map +1 -0
  191. package/dist/lens/preflight-findings.d.ts +21 -0
  192. package/dist/lens/preflight-findings.d.ts.map +1 -0
  193. package/dist/lens/preflight-findings.js +82 -0
  194. package/dist/lens/preflight-findings.js.map +1 -0
  195. package/dist/lib/barcode-scan.d.ts +154 -0
  196. package/dist/lib/barcode-scan.d.ts.map +1 -0
  197. package/dist/lib/barcode-scan.js +152 -0
  198. package/dist/lib/barcode-scan.js.map +1 -0
  199. package/dist/lib/color-math.d.ts +76 -0
  200. package/dist/lib/color-math.d.ts.map +1 -0
  201. package/dist/lib/color-math.js +96 -0
  202. package/dist/lib/color-math.js.map +1 -0
  203. package/dist/lib/dieline-template.d.ts +169 -0
  204. package/dist/lib/dieline-template.d.ts.map +1 -1
  205. package/dist/lib/dieline-template.js +229 -1
  206. package/dist/lib/dieline-template.js.map +1 -1
  207. package/dist/lib/editor-config.d.ts +384 -1
  208. package/dist/lib/editor-config.d.ts.map +1 -1
  209. package/dist/lib/editor-config.js +89 -2
  210. package/dist/lib/editor-config.js.map +1 -1
  211. package/dist/lib/fold-geometry.d.ts +144 -0
  212. package/dist/lib/fold-geometry.d.ts.map +1 -0
  213. package/dist/lib/fold-geometry.js +138 -0
  214. package/dist/lib/fold-geometry.js.map +1 -0
  215. package/dist/lib/merge-tokens.d.ts +81 -0
  216. package/dist/lib/merge-tokens.d.ts.map +1 -0
  217. package/dist/lib/merge-tokens.js +88 -0
  218. package/dist/lib/merge-tokens.js.map +1 -0
  219. package/dist/lib/palette-registry.d.ts +40 -0
  220. package/dist/lib/palette-registry.d.ts.map +1 -0
  221. package/dist/lib/palette-registry.js +49 -0
  222. package/dist/lib/palette-registry.js.map +1 -0
  223. package/dist/lib/panel-anchor.d.ts +101 -0
  224. package/dist/lib/panel-anchor.d.ts.map +1 -0
  225. package/dist/lib/panel-anchor.js +68 -0
  226. package/dist/lib/panel-anchor.js.map +1 -0
  227. package/dist/lib/preflight/checks.d.ts.map +1 -1
  228. package/dist/lib/preflight/checks.js +71 -0
  229. package/dist/lib/preflight/checks.js.map +1 -1
  230. package/dist/lib/preflight/types.d.ts.map +1 -1
  231. package/dist/lib/preflight/types.js +11 -0
  232. package/dist/lib/preflight/types.js.map +1 -1
  233. package/dist/lib/rasterize.d.ts +93 -0
  234. package/dist/lib/rasterize.d.ts.map +1 -0
  235. package/dist/lib/rasterize.js +117 -0
  236. package/dist/lib/rasterize.js.map +1 -0
  237. package/dist/lib/separations-registry.d.ts +99 -0
  238. package/dist/lib/separations-registry.d.ts.map +1 -0
  239. package/dist/lib/separations-registry.js +59 -0
  240. package/dist/lib/separations-registry.js.map +1 -0
  241. package/dist/lib/unwired.d.ts +29 -0
  242. package/dist/lib/unwired.d.ts.map +1 -0
  243. package/dist/lib/unwired.js +58 -0
  244. package/dist/lib/unwired.js.map +1 -0
  245. package/package.json +29 -11
  246. package/dist/components/SeparationsPanel.d.ts +0 -9
  247. package/dist/components/SeparationsPanel.d.ts.map +0 -1
  248. package/dist/components/SeparationsPanel.js +0 -168
  249. package/dist/components/SeparationsPanel.js.map +0 -1
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Wave 4 I2 — Email notify panel.
3
+ *
4
+ * Third member of the Wave 4 integration family alongside I3
5
+ * {@link SlackNotifyPanel} (Slack incoming webhooks) and I1
6
+ * {@link WebhookNotifyPanel} (generic outbound webhooks). I2 targets
7
+ * email — typically the longest-lived notification channel for
8
+ * artwork-review workflows (approval pings, preflight blockers,
9
+ * customer-facing job-submitted receipts).
10
+ *
11
+ * The host wires an {@link EmailNotifyFn} adapter (SMTP relay,
12
+ * SendGrid, Postmark, AWS SES, internal Synergy node, etc.). The
13
+ * panel handles event-template selection, recipient + cc + bcc
14
+ * inputs, subject / body composition via {@link composeEmailMessage},
15
+ * and the send-button state machine.
16
+ *
17
+ * Pairs with the synergy `email.notify` workflow node when one is
18
+ * deployed; hosts without a synergy bridge can also POST straight to
19
+ * their tenant SMTP / transactional-email provider — the adapter
20
+ * shape is intentionally agnostic.
21
+ *
22
+ * @public
23
+ */
24
+ import type { ReactElement } from "react";
25
+ /**
26
+ * The set of editor events that map to canonical email templates.
27
+ * Mirrors I3's and I1's vocabulary so a single host-side trigger
28
+ * source can fan out to all three integration panels.
29
+ *
30
+ * @public
31
+ */
32
+ export type EmailNotificationEventKind = "preflight-blocked" | "preflight-cleared" | "job-submitted" | "variant-approved" | "approval-requested" | "custom";
33
+ /**
34
+ * Context passed to {@link composeEmailMessage}. Most fields are
35
+ * optional and only render when the chosen template references them.
36
+ *
37
+ * @public
38
+ */
39
+ export type EmailNotificationContext = {
40
+ /** Human-readable document name surfaced in the subject + body. */
41
+ documentName?: string;
42
+ /** Stable identifier the host uses to link back to the document. */
43
+ documentId?: string;
44
+ /** Optional clickable URL — rendered as a "View artwork" link in
45
+ * the body so reviewers can jump straight into the editor. */
46
+ documentUrl?: string;
47
+ /** Preflight finding count (errors only for `"preflight-blocked"`,
48
+ * total resolved for `"preflight-cleared"`). */
49
+ findingCount?: number;
50
+ /** Variant id for `"variant-approved"`. */
51
+ variantId?: string;
52
+ /** Reviewer / submitter display name — surfaces as the byline in
53
+ * the body. */
54
+ actor?: string;
55
+ /** Free-form additional text appended to the canonical body (or,
56
+ * for `"custom"`, used as the entire body). */
57
+ text?: string;
58
+ };
59
+ /**
60
+ * Composed email payload — the panel emits this through the host
61
+ * adapter. The subject + body split keeps the wire shape consumable
62
+ * by SMTP / transactional-email APIs without further parsing. Plain
63
+ * text only at this version; rich HTML can land in a future iteration
64
+ * once hosts express a need.
65
+ *
66
+ * @public
67
+ */
68
+ export type EmailNotificationPayload = {
69
+ /** Primary recipients. At least one address is required at the
70
+ * panel level — the composer doesn't enforce that so it stays
71
+ * pure. */
72
+ to: readonly string[];
73
+ /** Optional carbon-copy list. */
74
+ cc?: readonly string[];
75
+ /** Optional blind carbon-copy list. */
76
+ bcc?: readonly string[];
77
+ /** Subject line. */
78
+ subject: string;
79
+ /** Plain-text body. */
80
+ body: string;
81
+ };
82
+ /**
83
+ * Pure helper — parses a comma / semicolon / whitespace-separated
84
+ * address list into a deduplicated, trimmed array. Empty input
85
+ * returns an empty array. Pure function; no I/O.
86
+ *
87
+ * @public
88
+ */
89
+ export declare function parseEmailList(raw: string): readonly string[];
90
+ /**
91
+ * Pure helper — composes an {@link EmailNotificationPayload} subject
92
+ * and body from a kind + context + recipient lists. The subject is a
93
+ * single canonical line per template; the body is a short multi-line
94
+ * plaintext block that includes whatever fields the context supplies.
95
+ *
96
+ * `"custom"` uses `context.text` verbatim as the body and falls back
97
+ * to a sensible default when the host left it empty — the helper
98
+ * never silently drops the message.
99
+ *
100
+ * Pure function; no I/O.
101
+ *
102
+ * @public
103
+ */
104
+ export declare function composeEmailMessage(kind: EmailNotificationEventKind, context: EmailNotificationContext, recipients: {
105
+ to: readonly string[];
106
+ cc?: readonly string[];
107
+ bcc?: readonly string[];
108
+ }): EmailNotificationPayload;
109
+ /**
110
+ * Host adapter — POSTs the composed payload to the wired email
111
+ * provider (typically via a server-side proxy or the synergy
112
+ * `email.notify` node). Resolves on accept; rejects on transport /
113
+ * validation errors and the panel surfaces the message inline.
114
+ *
115
+ * @public
116
+ */
117
+ export type EmailNotifyFn = (payload: EmailNotificationPayload) => Promise<void>;
118
+ /**
119
+ * Human-readable labels for each event kind, in the order they
120
+ * appear in the dropdown. Mirrors the I3 and I1 label maps so the
121
+ * three integrations stay in lockstep.
122
+ *
123
+ * @public
124
+ */
125
+ export declare const EMAIL_NOTIFICATION_EVENT_LABELS: Readonly<Record<EmailNotificationEventKind, string>>;
126
+ /**
127
+ * Configuration for the {@link EmailNotifyPanel}. The host always
128
+ * supplies the {@link EmailNotifyFn}; the optional fields seed the
129
+ * recipient + event dropdown defaults so the panel can open
130
+ * prefilled for the common case.
131
+ *
132
+ * @public
133
+ */
134
+ export type EmailNotifyPanelProps = {
135
+ /** Host adapter, see {@link EmailNotifyFn}. */
136
+ notify: EmailNotifyFn;
137
+ /** Context the panel renders into the chosen template. */
138
+ context: EmailNotificationContext;
139
+ /** Optional initial event selection. Defaults to
140
+ * `"approval-requested"` — the most common email trigger. */
141
+ defaultEvent?: EmailNotificationEventKind;
142
+ /** Optional initial recipients (comma-separated for the input). */
143
+ defaultTo?: string;
144
+ /** Optional initial cc list. */
145
+ defaultCc?: string;
146
+ /** Optional initial bcc list. */
147
+ defaultBcc?: string;
148
+ /** Optional mapper that turns a notify error into a user-facing
149
+ * message. The default avoids leaking internal `Error.message`
150
+ * strings. */
151
+ errorMessage?: (err: unknown) => string;
152
+ /** Optional callback fired on successful notify so the host can
153
+ * show a confirmation toast / log analytics. */
154
+ onSuccess?: (payload: EmailNotificationPayload) => void;
155
+ };
156
+ /**
157
+ * Stateful panel — picks an event template, captures recipient
158
+ * lists, lets the user append a custom note, composes the payload
159
+ * via {@link composeEmailMessage}, and POSTs through the host
160
+ * adapter.
161
+ *
162
+ * @public
163
+ */
164
+ export declare function EmailNotifyPanel({ notify, context, defaultEvent, defaultTo, defaultCc, defaultBcc, errorMessage, onSuccess, }: EmailNotifyPanelProps): ReactElement;
165
+ //# sourceMappingURL=EmailNotifyPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmailNotifyPanel.d.ts","sourceRoot":"","sources":["../../src/components/EmailNotifyPanel.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C;;;;;;GAMG;AACH,MAAM,MAAM,0BAA0B,GAClC,mBAAmB,GACnB,mBAAmB,GACnB,eAAe,GACf,kBAAkB,GAClB,oBAAoB,GACpB,QAAQ,CAAC;AAEb;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;mEAC+D;IAC/D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;qDACiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;oBACgB;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;oDACgD;IAChD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC;;gBAEY;IACZ,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IACtB,iCAAiC;IACjC,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvB,uCAAuC;IACvC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACxB,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAIF;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAa7D;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,0BAA0B,EAChC,OAAO,EAAE,wBAAwB,EACjC,UAAU,EAAE;IAAE,EAAE,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,EAAE,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,GAAG,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,GACrF,wBAAwB,CAU1B;AAqED;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjF;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,EAAE,QAAQ,CAAC,MAAM,CAAC,0BAA0B,EAAE,MAAM,CAAC,CAQ9F,CAAC;AAEJ;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG;IAClC,+CAA+C;IAC/C,MAAM,EAAE,aAAa,CAAC;IACtB,0DAA0D;IAC1D,OAAO,EAAE,wBAAwB,CAAC;IAClC;kEAC8D;IAC9D,YAAY,CAAC,EAAE,0BAA0B,CAAC;IAC1C,mEAAmE;IACnE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gCAAgC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iCAAiC;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;mBAEe;IACf,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IACxC;qDACiD;IACjD,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACzD,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,OAAO,EACP,YAAY,EACZ,SAAS,EACT,SAAS,EACT,UAAU,EACV,YAAY,EACZ,SAAS,GACV,EAAE,qBAAqB,GAAG,YAAY,CAiKtC"}
@@ -0,0 +1,211 @@
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 { useState } from "react";
5
+ const EMAIL_LIST_SEPARATOR = /[,;\s]+/;
6
+ /**
7
+ * Pure helper — parses a comma / semicolon / whitespace-separated
8
+ * address list into a deduplicated, trimmed array. Empty input
9
+ * returns an empty array. Pure function; no I/O.
10
+ *
11
+ * @public
12
+ */
13
+ export function parseEmailList(raw) {
14
+ if (!raw.trim())
15
+ return [];
16
+ const seen = new Set();
17
+ const out = [];
18
+ for (const part of raw.split(EMAIL_LIST_SEPARATOR)) {
19
+ const trimmed = part.trim();
20
+ if (!trimmed)
21
+ continue;
22
+ const key = trimmed.toLowerCase();
23
+ if (seen.has(key))
24
+ continue;
25
+ seen.add(key);
26
+ out.push(trimmed);
27
+ }
28
+ return out;
29
+ }
30
+ /**
31
+ * Pure helper — composes an {@link EmailNotificationPayload} subject
32
+ * and body from a kind + context + recipient lists. The subject is a
33
+ * single canonical line per template; the body is a short multi-line
34
+ * plaintext block that includes whatever fields the context supplies.
35
+ *
36
+ * `"custom"` uses `context.text` verbatim as the body and falls back
37
+ * to a sensible default when the host left it empty — the helper
38
+ * never silently drops the message.
39
+ *
40
+ * Pure function; no I/O.
41
+ *
42
+ * @public
43
+ */
44
+ export function composeEmailMessage(kind, context, recipients) {
45
+ const subject = composeSubject(kind, context);
46
+ const body = composeBody(kind, context);
47
+ return {
48
+ to: recipients.to,
49
+ ...(recipients.cc && recipients.cc.length > 0 && { cc: recipients.cc }),
50
+ ...(recipients.bcc && recipients.bcc.length > 0 && { bcc: recipients.bcc }),
51
+ subject,
52
+ body,
53
+ };
54
+ }
55
+ /** Resolve a human-readable document name from the context, falling
56
+ * back to id and then to a generic placeholder. */
57
+ function documentDisplayName(context) {
58
+ return context.documentName ?? context.documentId ?? "an artwork document";
59
+ }
60
+ /** Render the email subject line for one of the canonical templates. */
61
+ function composeSubject(kind, context) {
62
+ const subject = documentDisplayName(context);
63
+ switch (kind) {
64
+ case "preflight-blocked":
65
+ return `Preflight blocked: ${subject}`;
66
+ case "preflight-cleared":
67
+ return `Preflight cleared: ${subject}`;
68
+ case "job-submitted":
69
+ return `Job submitted: ${subject}`;
70
+ case "variant-approved":
71
+ return `Variant approved: ${subject}`;
72
+ case "approval-requested":
73
+ return `Approval requested: ${subject}`;
74
+ case "custom":
75
+ return `Update: ${subject}`;
76
+ }
77
+ }
78
+ /** Render the email body (multi-line plaintext) for one of the
79
+ * canonical templates; `"custom"` uses `context.text` verbatim. */
80
+ function composeBody(kind, context) {
81
+ if (kind === "custom") {
82
+ const trailing = context.text?.trim();
83
+ if (trailing)
84
+ return trailing;
85
+ return `Update on ${documentDisplayName(context)}.`;
86
+ }
87
+ const lines = [];
88
+ const subject = documentDisplayName(context);
89
+ switch (kind) {
90
+ case "preflight-blocked": {
91
+ const n = context.findingCount;
92
+ const findingsFragment = typeof n === "number" ? ` ${n} finding${n === 1 ? "" : "s"} surfaced.` : "";
93
+ lines.push(`Preflight is blocking ${subject}.${findingsFragment}`);
94
+ break;
95
+ }
96
+ case "preflight-cleared":
97
+ lines.push(`Preflight is now clear on ${subject}.`);
98
+ break;
99
+ case "job-submitted":
100
+ lines.push(`A job has been submitted for ${subject}.`);
101
+ break;
102
+ case "variant-approved": {
103
+ const v = context.variantId ? ` (variant ${context.variantId})` : "";
104
+ lines.push(`A variant${v} was approved on ${subject}.`);
105
+ break;
106
+ }
107
+ case "approval-requested":
108
+ lines.push(`Approval is requested on ${subject}.`);
109
+ break;
110
+ }
111
+ if (context.actor)
112
+ lines.push(`By: ${context.actor}`);
113
+ if (context.documentUrl)
114
+ lines.push(`View artwork: ${context.documentUrl}`);
115
+ if (context.text?.trim())
116
+ lines.push("", context.text.trim());
117
+ return lines.join("\n");
118
+ }
119
+ /**
120
+ * Human-readable labels for each event kind, in the order they
121
+ * appear in the dropdown. Mirrors the I3 and I1 label maps so the
122
+ * three integrations stay in lockstep.
123
+ *
124
+ * @public
125
+ */
126
+ export const EMAIL_NOTIFICATION_EVENT_LABELS = {
127
+ "preflight-blocked": "Preflight blocked",
128
+ "preflight-cleared": "Preflight cleared",
129
+ "job-submitted": "Job submitted",
130
+ "variant-approved": "Variant approved",
131
+ "approval-requested": "Approval requested",
132
+ custom: "Custom message",
133
+ };
134
+ /**
135
+ * Stateful panel — picks an event template, captures recipient
136
+ * lists, lets the user append a custom note, composes the payload
137
+ * via {@link composeEmailMessage}, and POSTs through the host
138
+ * adapter.
139
+ *
140
+ * @public
141
+ */
142
+ export function EmailNotifyPanel({ notify, context, defaultEvent, defaultTo, defaultCc, defaultBcc, errorMessage, onSuccess, }) {
143
+ const [event, setEvent] = useState(defaultEvent ?? "approval-requested");
144
+ const [toRaw, setToRaw] = useState(defaultTo ?? "");
145
+ const [ccRaw, setCcRaw] = useState(defaultCc ?? "");
146
+ const [bccRaw, setBccRaw] = useState(defaultBcc ?? "");
147
+ const [note, setNote] = useState("");
148
+ const [state, setState] = useState({ kind: "idle" });
149
+ // Clear the outcome chip on any input edit — a "Sent" indicator
150
+ // sitting next to an unsent payload reads as a lie.
151
+ const resetOutcome = () => {
152
+ setState((prev) => (prev.kind === "ok" || prev.kind === "error" ? { kind: "idle" } : prev));
153
+ };
154
+ const onClick = async () => {
155
+ const to = parseEmailList(toRaw);
156
+ if (to.length === 0) {
157
+ setState({ kind: "error", message: "Add at least one recipient." });
158
+ return;
159
+ }
160
+ setState({ kind: "sending" });
161
+ const payload = composeEmailMessage(event, {
162
+ ...context,
163
+ ...(note.trim() && { text: note }),
164
+ }, {
165
+ to,
166
+ cc: parseEmailList(ccRaw),
167
+ bcc: parseEmailList(bccRaw),
168
+ });
169
+ try {
170
+ await notify(payload);
171
+ setState({ kind: "ok" });
172
+ onSuccess?.(payload);
173
+ }
174
+ catch (err) {
175
+ // Guard against a host-supplied errorMessage that throws or returns
176
+ // a falsy / empty string — either would leave the user staring at a
177
+ // blank error chip with no idea what happened.
178
+ let message = "Couldn't send email notification.";
179
+ if (errorMessage) {
180
+ try {
181
+ const candidate = errorMessage(err);
182
+ if (candidate)
183
+ message = candidate;
184
+ }
185
+ catch {
186
+ // fall back to the default
187
+ }
188
+ }
189
+ setState({ kind: "error", message });
190
+ }
191
+ };
192
+ return (_jsxs("div", { "data-testid": "email-notify-panel", style: { padding: "0.5rem" }, children: [_jsx("header", { style: { marginBottom: "0.5rem" }, children: _jsx("h3", { style: { margin: 0, fontSize: "0.875rem" }, children: "Email notify" }) }), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Event", _jsx("select", { "aria-label": "Event", value: event, onChange: (e) => {
193
+ setEvent(e.target.value);
194
+ resetOutcome();
195
+ }, style: { display: "block", marginTop: "0.125rem", width: "100%" }, children: Object.entries(EMAIL_NOTIFICATION_EVENT_LABELS).map(([k, label]) => (_jsx("option", { value: k, children: label }, k))) })] }), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["To", _jsx("input", { type: "text", "aria-label": "To", placeholder: "reviewer@example.com, \u2026", value: toRaw, onChange: (e) => {
196
+ setToRaw(e.target.value);
197
+ resetOutcome();
198
+ }, style: { display: "block", marginTop: "0.125rem", width: "100%" } })] }), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Cc", _jsx("input", { type: "text", "aria-label": "Cc", placeholder: "optional", value: ccRaw, onChange: (e) => {
199
+ setCcRaw(e.target.value);
200
+ resetOutcome();
201
+ }, style: { display: "block", marginTop: "0.125rem", width: "100%" } })] }), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Bcc", _jsx("input", { type: "text", "aria-label": "Bcc", placeholder: "optional", value: bccRaw, onChange: (e) => {
202
+ setBccRaw(e.target.value);
203
+ resetOutcome();
204
+ }, style: { display: "block", marginTop: "0.125rem", width: "100%" } })] }), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Note", _jsx("textarea", { "aria-label": "Note", placeholder: event === "custom"
205
+ ? "Used as the full body for custom messages"
206
+ : "Optional — appended to the body", value: note, onChange: (e) => {
207
+ setNote(e.target.value);
208
+ resetOutcome();
209
+ }, rows: 2, style: { display: "block", marginTop: "0.125rem", width: "100%" } })] }), _jsxs("div", { style: { display: "flex", gap: "0.5rem", alignItems: "center" }, children: [_jsx("button", { type: "button", onClick: onClick, disabled: state.kind === "sending", "aria-busy": state.kind === "sending", children: state.kind === "sending" ? "Sending…" : "Send email" }), state.kind === "ok" && (_jsx("output", { style: { color: "#080", fontSize: "0.75rem" }, children: "Sent" })), state.kind === "error" && (_jsx("span", { role: "alert", style: { color: "#a00", fontSize: "0.75rem" }, children: state.message }))] })] }));
210
+ }
211
+ //# sourceMappingURL=EmailNotifyPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EmailNotifyPanel.js","sourceRoot":"","sources":["../../src/components/EmailNotifyPanel.tsx"],"names":[],"mappings":"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"}
@@ -1,6 +1,14 @@
1
+ import { type Dieline } from "@artworkpdf/dieline-parser";
1
2
  type Props = {
3
+ /** Called when a PDF or raster image is dropped — the existing
4
+ * preflight → editor flow takes over. */
2
5
  onFile: (file: File) => void;
6
+ /** Called when a structural dieline file (CF2 / DDES / ARD) is
7
+ * dropped. Hosts that want to bypass preflight and seed the
8
+ * canvas directly from the parsed `Dieline` should provide this.
9
+ * Absent → dieline files are rejected. */
10
+ onDieline?: (dieline: Dieline) => void;
3
11
  };
4
- export declare function FileDropZone({ onFile }: Props): import("react/jsx-runtime").JSX.Element;
12
+ export declare function FileDropZone({ onFile, onDieline }: Props): import("react/jsx-runtime").JSX.Element;
5
13
  export {};
6
14
  //# sourceMappingURL=FileDropZone.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileDropZone.d.ts","sourceRoot":"","sources":["../../src/components/FileDropZone.tsx"],"names":[],"mappings":"AAIA,KAAK,KAAK,GAAG;IACX,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAC9B,CAAC;AAEF,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,2CAwE7C"}
1
+ {"version":3,"file":"FileDropZone.d.ts","sourceRoot":"","sources":["../../src/components/FileDropZone.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,OAAO,EAAiC,MAAM,4BAA4B,CAAC;AAGzF,KAAK,KAAK,GAAG;IACX;8CAC0C;IAC1C,MAAM,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC7B;;;+CAG2C;IAC3C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACxC,CAAC;AAeF,wBAAgB,YAAY,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,EAAE,KAAK,2CAkHxD"}
@@ -1,17 +1,58 @@
1
1
  // SPDX-License-Identifier: AGPL-3.0-or-later
2
2
  "use client";
3
3
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { parseARD, parseCF2, parseDDES } from "@artworkpdf/dieline-parser";
4
5
  import { useCallback, useRef, useState } from "react";
5
- export function FileDropZone({ onFile }) {
6
+ /**
7
+ * Detect which dieline-parser to invoke for a given filename.
8
+ * Returns `null` for non-dieline files (caller falls back to the
9
+ * normal PDF / image path).
10
+ */
11
+ function dielineParserFor(name) {
12
+ const lower = name.toLowerCase();
13
+ if (lower.endsWith(".cf2"))
14
+ return parseCF2;
15
+ if (lower.endsWith(".ddes"))
16
+ return parseDDES;
17
+ if (lower.endsWith(".ard"))
18
+ return parseARD;
19
+ return null;
20
+ }
21
+ export function FileDropZone({ onFile, onDieline }) {
6
22
  const [dragging, setDragging] = useState(false);
23
+ const [parseError, setParseError] = useState(null);
7
24
  const inputRef = useRef(null);
8
- const handle = useCallback((file) => {
25
+ const dielineSupported = onDieline !== undefined;
26
+ const handle = useCallback(async (file) => {
27
+ setParseError(null);
28
+ // Try the dieline-parser path first when the host supports it
29
+ // (onDieline provided). PDF / image still flows through the
30
+ // legacy `onFile` → preflight path. When dielines aren't
31
+ // supported, .cf2 / .ddes / .ard files fall through to the
32
+ // PDF/image check below and are silently rejected.
33
+ const dielineParser = dielineSupported ? dielineParserFor(file.name) : null;
34
+ if (dielineParser && onDieline) {
35
+ try {
36
+ const text = await file.text();
37
+ const dieline = dielineParser(text);
38
+ if (dieline.paths.length === 0) {
39
+ setParseError(`${file.name}: no recognizable paths in this dieline file.`);
40
+ return;
41
+ }
42
+ onDieline(dieline);
43
+ }
44
+ catch (err) {
45
+ const msg = err instanceof Error ? err.message : String(err);
46
+ setParseError(`${file.name}: ${msg}`);
47
+ }
48
+ return;
49
+ }
9
50
  if (file.type === "application/pdf" ||
10
51
  file.name.toLowerCase().endsWith(".pdf") ||
11
52
  file.type.startsWith("image/")) {
12
53
  onFile(file);
13
54
  }
14
- }, [onFile]);
55
+ }, [onFile, onDieline, dielineSupported]);
15
56
  return (_jsxs("button", { type: "button", onDragOver: (e) => {
16
57
  e.preventDefault();
17
58
  setDragging(true);
@@ -33,7 +74,7 @@ export function FileDropZone({ onFile }) {
33
74
  width: "100%",
34
75
  fontFamily: "inherit",
35
76
  display: "block",
36
- }, children: [_jsx("input", { ref: inputRef, type: "file", accept: ".pdf,image/*", style: { display: "none" }, onChange: (e) => {
77
+ }, children: [_jsx("input", { ref: inputRef, type: "file", accept: dielineSupported ? ".pdf,.cf2,.ddes,.ard,image/*" : ".pdf,image/*", style: { display: "none" }, onChange: (e) => {
37
78
  const file = e.target.files?.[0];
38
79
  if (file)
39
80
  handle(file);
@@ -43,6 +84,13 @@ export function FileDropZone({ onFile }) {
43
84
  fontWeight: 600,
44
85
  marginBottom: "0.5rem",
45
86
  fontSize: "1rem",
46
- }, children: "Drop artwork file here" }), _jsx("span", { style: { display: "block", color: "#666", fontSize: "0.82rem" }, children: "PDF or raster image \u2014 preflight checks run before the canvas opens" })] }));
87
+ }, children: dielineSupported ? "Drop artwork or dieline file here" : "Drop artwork file here" }), _jsx("span", { style: { display: "block", color: "#666", fontSize: "0.82rem" }, children: dielineSupported
88
+ ? "PDF / raster image (runs preflight) — or CF2 / DDES / ARD (seeds the canvas directly)"
89
+ : "PDF or raster image — preflight checks run before the canvas opens" }), parseError && (_jsx("span", { role: "alert", "aria-live": "polite", style: {
90
+ display: "block",
91
+ color: "#ef4444",
92
+ marginTop: "0.65rem",
93
+ fontSize: "0.8rem",
94
+ }, children: parseError }))] }));
47
95
  }
48
96
  //# sourceMappingURL=FileDropZone.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileDropZone.js","sourceRoot":"","sources":["../../src/components/FileDropZone.tsx"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;;AACb,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAMtD,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAS;IAC5C,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAEhD,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,IAAU,EAAE,EAAE;QACb,IACE,IAAI,CAAC,IAAI,KAAK,iBAAiB;YAC/B,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YACxC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,EAC9B,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,CAAC;QACf,CAAC;IACH,CAAC,EACD,CAAC,MAAM,CAAC,CACT,CAAC;IAEF,OAAO,CACL,kBACE,IAAI,EAAC,QAAQ,EACb,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE;YAChB,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC,EACD,WAAW,EAAE,GAAG,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,EACrC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE;YACZ,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,WAAW,CAAC,KAAK,CAAC,CAAC;YACnB,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACrC,IAAI,IAAI;gBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC,EACD,OAAO,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,EACxC,KAAK,EAAE;YACL,MAAM,EAAE,cAAc,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,EAAE;YACxD,YAAY,EAAE,EAAE;YAChB,OAAO,EAAE,WAAW;YACpB,SAAS,EAAE,QAAQ;YACnB,MAAM,EAAE,SAAS;YACjB,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,aAAa;YAC5D,UAAU,EAAE,sCAAsC;YAClD,QAAQ,EAAE,GAAG;YACb,KAAK,EAAE,MAAM;YACb,UAAU,EAAE,SAAS;YACrB,OAAO,EAAE,OAAO;SACjB,aAED,gBACE,GAAG,EAAE,QAAQ,EACb,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE;oBACd,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;oBACjC,IAAI,IAAI;wBAAE,MAAM,CAAC,IAAI,CAAC,CAAC;gBACzB,CAAC,GACD,EACF,eACE,KAAK,EAAE;oBACL,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,SAAS;oBAChB,UAAU,EAAE,GAAG;oBACf,YAAY,EAAE,QAAQ;oBACtB,QAAQ,EAAE,MAAM;iBACjB,uCAGI,EACP,eAAM,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,wFAE9D,IACA,CACV,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"FileDropZone.js","sourceRoot":"","sources":["../../src/components/FileDropZone.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Wave 2 S4 (PR-4) — interactive fold editor.
3
+ *
4
+ * Surfaces each fold edge in `FoldConfig` as a row with an angle
5
+ * slider, plus an OCG-style "show folded" toggle that hosts wire to
6
+ * the {@link FoldPreviewOverlay}'s active vs. flat view. Editing is
7
+ * controlled (`value` / `onChange`); the panel never owns state.
8
+ *
9
+ * Pairs with PR-3's `FoldPreviewOverlay` — the slider here updates
10
+ * `FoldConfig.edges[*].angleDeg`, and the overlay re-renders the
11
+ * Three.js scene on every commit.
12
+ *
13
+ * Designed to stay consumable without `@artworkpdf/document-model`:
14
+ * the value shape (`FoldEditorPanelValue`) mirrors the document-model
15
+ * `FoldConfig` field-for-field, same convention as
16
+ * `EditorSeparation`, `FoldGeometryPanelMetadata`,
17
+ * `EditorDielinePanel`.
18
+ *
19
+ * @public
20
+ */
21
+ /**
22
+ * One fold edge between two panels.
23
+ *
24
+ * @public
25
+ */
26
+ export type FoldEditorEdge = {
27
+ id: string;
28
+ panelA: string;
29
+ panelB: string;
30
+ angleDeg: number;
31
+ direction?: "mountain" | "valley";
32
+ };
33
+ /**
34
+ * Controlled value — mirrors document-model's `FoldConfig`.
35
+ *
36
+ * @public
37
+ */
38
+ export type FoldEditorPanelValue = {
39
+ edges: FoldEditorEdge[];
40
+ defaultAngleDeg?: number;
41
+ };
42
+ /**
43
+ * @public
44
+ */
45
+ export type FoldEditorPanelProps = {
46
+ /** Current fold configuration. `undefined` means "no panels with
47
+ * fold metadata" — the panel renders a placeholder. */
48
+ value: FoldEditorPanelValue | undefined;
49
+ /** Fires on every slider tick. Hosts debounce externally if the
50
+ * 3D scene rebuild becomes expensive. */
51
+ onChange: (next: FoldEditorPanelValue) => void;
52
+ /** When `true`, the {@link FoldPreviewOverlay} should render the
53
+ * *folded* state; when `false`, the flat unfolded state. Pure UI
54
+ * state — the value-side is unaffected. */
55
+ showFolded?: boolean;
56
+ /** Fires when the user toggles the show-folded switch. Hosts thread
57
+ * this back into a top-level UI flag and pass it to the overlay. */
58
+ onShowFoldedChange?: (next: boolean) => void;
59
+ /** Range bounds on the angle slider, in degrees. Defaults to
60
+ * `[-180, 180]` — the same range `FoldConfig` permits. */
61
+ minAngleDeg?: number;
62
+ maxAngleDeg?: number;
63
+ };
64
+ /**
65
+ * @public
66
+ */
67
+ export declare function FoldEditorPanel({ value, onChange, showFolded, onShowFoldedChange, minAngleDeg, maxAngleDeg, }: FoldEditorPanelProps): import("react/jsx-runtime").JSX.Element;
68
+ //# sourceMappingURL=FoldEditorPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FoldEditorPanel.d.ts","sourceRoot":"","sources":["../../src/components/FoldEditorPanel.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH;;;;GAIG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,UAAU,GAAG,QAAQ,CAAC;CACnC,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC;4DACwD;IACxD,KAAK,EAAE,oBAAoB,GAAG,SAAS,CAAC;IACxC;8CAC0C;IAC1C,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C;;gDAE4C;IAC5C,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;yEACqE;IACrE,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC7C;+DAC2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAKF;;GAEG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,QAAQ,EACR,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,WAAW,GACZ,EAAE,oBAAoB,2CAoHtB"}