@printwithsynergy/artwork-pdf-editor 0.1.6 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +62 -0
- package/README.md +63 -2
- package/dist/components/AccessibilityHintsPanel.d.ts +142 -0
- package/dist/components/AccessibilityHintsPanel.d.ts.map +1 -0
- package/dist/components/AccessibilityHintsPanel.js +158 -0
- package/dist/components/AccessibilityHintsPanel.js.map +1 -0
- package/dist/components/AnnotationOverlay.d.ts +142 -0
- package/dist/components/AnnotationOverlay.d.ts.map +1 -0
- package/dist/components/AnnotationOverlay.js +141 -0
- package/dist/components/AnnotationOverlay.js.map +1 -0
- package/dist/components/AnnotationsSidebar.d.ts +98 -0
- package/dist/components/AnnotationsSidebar.d.ts.map +1 -0
- package/dist/components/AnnotationsSidebar.js +100 -0
- package/dist/components/AnnotationsSidebar.js.map +1 -0
- package/dist/components/BarcodeGeneratorPanel.d.ts +58 -0
- package/dist/components/BarcodeGeneratorPanel.d.ts.map +1 -0
- package/dist/components/BarcodeGeneratorPanel.js +91 -0
- package/dist/components/BarcodeGeneratorPanel.js.map +1 -0
- package/dist/components/BraillePanel.d.ts +99 -0
- package/dist/components/BraillePanel.d.ts.map +1 -0
- package/dist/components/BraillePanel.js +221 -0
- package/dist/components/BraillePanel.js.map +1 -0
- package/dist/components/BrandAssetsPanel.d.ts +130 -0
- package/dist/components/BrandAssetsPanel.d.ts.map +1 -0
- package/dist/components/BrandAssetsPanel.js +125 -0
- package/dist/components/BrandAssetsPanel.js.map +1 -0
- package/dist/components/BrandConsistencyPanel.d.ts +140 -0
- package/dist/components/BrandConsistencyPanel.d.ts.map +1 -0
- package/dist/components/BrandConsistencyPanel.js +158 -0
- package/dist/components/BrandConsistencyPanel.js.map +1 -0
- package/dist/components/ComplianceFindingsPanel.d.ts +62 -0
- package/dist/components/ComplianceFindingsPanel.d.ts.map +1 -0
- package/dist/components/ComplianceFindingsPanel.js +118 -0
- package/dist/components/ComplianceFindingsPanel.js.map +1 -0
- package/dist/components/DesignSuggestionsPanel.d.ts +148 -0
- package/dist/components/DesignSuggestionsPanel.d.ts.map +1 -0
- package/dist/components/DesignSuggestionsPanel.js +154 -0
- package/dist/components/DesignSuggestionsPanel.js.map +1 -0
- package/dist/components/DielineParametersPanel.d.ts +62 -0
- package/dist/components/DielineParametersPanel.d.ts.map +1 -0
- package/dist/components/DielineParametersPanel.js +170 -0
- package/dist/components/DielineParametersPanel.js.map +1 -0
- package/dist/components/DielinePreview.d.ts +150 -0
- package/dist/components/DielinePreview.d.ts.map +1 -0
- package/dist/components/DielinePreview.js +146 -0
- package/dist/components/DielinePreview.js.map +1 -0
- package/dist/components/EditorApp.d.ts +39 -5
- package/dist/components/EditorApp.d.ts.map +1 -1
- package/dist/components/EditorApp.js +110 -5
- package/dist/components/EditorApp.js.map +1 -1
- package/dist/components/EditorCanvas.d.ts +51 -2
- package/dist/components/EditorCanvas.d.ts.map +1 -1
- package/dist/components/EditorCanvas.js +117 -48
- package/dist/components/EditorCanvas.js.map +1 -1
- package/dist/components/EmailNotifyPanel.d.ts +165 -0
- package/dist/components/EmailNotifyPanel.d.ts.map +1 -0
- package/dist/components/EmailNotifyPanel.js +211 -0
- package/dist/components/EmailNotifyPanel.js.map +1 -0
- package/dist/components/FileDropZone.d.ts +9 -1
- package/dist/components/FileDropZone.d.ts.map +1 -1
- package/dist/components/FileDropZone.js +53 -5
- package/dist/components/FileDropZone.js.map +1 -1
- package/dist/components/FoldEditorPanel.d.ts +68 -0
- package/dist/components/FoldEditorPanel.d.ts.map +1 -0
- package/dist/components/FoldEditorPanel.js +65 -0
- package/dist/components/FoldEditorPanel.js.map +1 -0
- package/dist/components/FoldPreviewOverlay.d.ts +48 -0
- package/dist/components/FoldPreviewOverlay.d.ts.map +1 -0
- package/dist/components/FoldPreviewOverlay.js +182 -0
- package/dist/components/FoldPreviewOverlay.js.map +1 -0
- package/dist/components/Gs1DigitalLinkPanel.d.ts +103 -0
- package/dist/components/Gs1DigitalLinkPanel.d.ts.map +1 -0
- package/dist/components/Gs1DigitalLinkPanel.js +199 -0
- package/dist/components/Gs1DigitalLinkPanel.js.map +1 -0
- package/dist/components/HistoryPanel.d.ts +39 -0
- package/dist/components/HistoryPanel.d.ts.map +1 -0
- package/dist/components/HistoryPanel.js +72 -0
- package/dist/components/HistoryPanel.js.map +1 -0
- package/dist/components/IccSoftProofOverlay.d.ts +67 -0
- package/dist/components/IccSoftProofOverlay.d.ts.map +1 -0
- package/dist/components/IccSoftProofOverlay.js +119 -0
- package/dist/components/IccSoftProofOverlay.js.map +1 -0
- package/dist/components/ImposePanel.d.ts +71 -0
- package/dist/components/ImposePanel.d.ts.map +1 -0
- package/dist/components/ImposePanel.js +127 -0
- package/dist/components/ImposePanel.js.map +1 -0
- package/dist/components/InksPanel.d.ts +61 -0
- package/dist/components/InksPanel.d.ts.map +1 -0
- package/dist/components/InksPanel.js +84 -0
- package/dist/components/InksPanel.js.map +1 -0
- package/dist/components/JobSetupPanel.d.ts +118 -0
- package/dist/components/JobSetupPanel.d.ts.map +1 -0
- package/dist/components/JobSetupPanel.js +169 -0
- package/dist/components/JobSetupPanel.js.map +1 -0
- package/dist/components/LayersPanel.d.ts.map +1 -1
- package/dist/components/LayersPanel.js +1 -0
- package/dist/components/LayersPanel.js.map +1 -1
- package/dist/components/MarkLibraryPanel.d.ts +131 -0
- package/dist/components/MarkLibraryPanel.d.ts.map +1 -0
- package/dist/components/MarkLibraryPanel.js +184 -0
- package/dist/components/MarkLibraryPanel.js.map +1 -0
- package/dist/components/MisEstimateButton.d.ts +73 -0
- package/dist/components/MisEstimateButton.d.ts.map +1 -0
- package/dist/components/MisEstimateButton.js +57 -0
- package/dist/components/MisEstimateButton.js.map +1 -0
- package/dist/components/NutritionPanel.d.ts +118 -0
- package/dist/components/NutritionPanel.d.ts.map +1 -0
- package/dist/components/NutritionPanel.js +169 -0
- package/dist/components/NutritionPanel.js.map +1 -0
- package/dist/components/PageNavigator.d.ts +26 -0
- package/dist/components/PageNavigator.d.ts.map +1 -0
- package/dist/components/PageNavigator.js +96 -0
- package/dist/components/PageNavigator.js.map +1 -0
- package/dist/components/PaletteManager.d.ts +32 -0
- package/dist/components/PaletteManager.d.ts.map +1 -0
- package/dist/components/PaletteManager.js +89 -0
- package/dist/components/PaletteManager.js.map +1 -0
- package/dist/components/PaletteToSpotPanel.d.ts +122 -0
- package/dist/components/PaletteToSpotPanel.d.ts.map +1 -0
- package/dist/components/PaletteToSpotPanel.js +160 -0
- package/dist/components/PaletteToSpotPanel.js.map +1 -0
- package/dist/components/PreflightAutoFixPanel.d.ts +110 -0
- package/dist/components/PreflightAutoFixPanel.d.ts.map +1 -0
- package/dist/components/PreflightAutoFixPanel.js +119 -0
- package/dist/components/PreflightAutoFixPanel.js.map +1 -0
- package/dist/components/PreflightDiffPanel.d.ts +127 -0
- package/dist/components/PreflightDiffPanel.d.ts.map +1 -0
- package/dist/components/PreflightDiffPanel.js +0 -0
- package/dist/components/PreflightDiffPanel.js.map +1 -0
- package/dist/components/ProcessRulesPanel.d.ts +81 -0
- package/dist/components/ProcessRulesPanel.d.ts.map +1 -0
- package/dist/components/ProcessRulesPanel.js +143 -0
- package/dist/components/ProcessRulesPanel.js.map +1 -0
- package/dist/components/SlackNotifyPanel.d.ts +139 -0
- package/dist/components/SlackNotifyPanel.d.ts.map +1 -0
- package/dist/components/SlackNotifyPanel.js +133 -0
- package/dist/components/SlackNotifyPanel.js.map +1 -0
- package/dist/components/SmartSpotMatchPanel.d.ts +143 -0
- package/dist/components/SmartSpotMatchPanel.d.ts.map +1 -0
- package/dist/components/SmartSpotMatchPanel.js +159 -0
- package/dist/components/SmartSpotMatchPanel.js.map +1 -0
- package/dist/components/SwatchesPicker.d.ts +83 -0
- package/dist/components/SwatchesPicker.d.ts.map +1 -0
- package/dist/components/SwatchesPicker.js +151 -0
- package/dist/components/SwatchesPicker.js.map +1 -0
- package/dist/components/TacOverlay.d.ts +47 -0
- package/dist/components/TacOverlay.d.ts.map +1 -0
- package/dist/components/TacOverlay.js +116 -0
- package/dist/components/TacOverlay.js.map +1 -0
- package/dist/components/TrapEditorPanel.d.ts +52 -0
- package/dist/components/TrapEditorPanel.d.ts.map +1 -0
- package/dist/components/TrapEditorPanel.js +64 -0
- package/dist/components/TrapEditorPanel.js.map +1 -0
- package/dist/components/TrapPreviewOverlay.d.ts +64 -0
- package/dist/components/TrapPreviewOverlay.d.ts.map +1 -0
- package/dist/components/TrapPreviewOverlay.js +120 -0
- package/dist/components/TrapPreviewOverlay.js.map +1 -0
- package/dist/components/VariantMatrixPanel.d.ts +61 -0
- package/dist/components/VariantMatrixPanel.d.ts.map +1 -0
- package/dist/components/VariantMatrixPanel.js +97 -0
- package/dist/components/VariantMatrixPanel.js.map +1 -0
- package/dist/components/VariantMatrixVersionPanel.d.ts +122 -0
- package/dist/components/VariantMatrixVersionPanel.d.ts.map +1 -0
- package/dist/components/VariantMatrixVersionPanel.js +162 -0
- package/dist/components/VariantMatrixVersionPanel.js.map +1 -0
- package/dist/components/WebhookNotifyPanel.d.ts +160 -0
- package/dist/components/WebhookNotifyPanel.d.ts.map +1 -0
- package/dist/components/WebhookNotifyPanel.js +100 -0
- package/dist/components/WebhookNotifyPanel.js.map +1 -0
- package/dist/components/WhiteUnderbasePanel.d.ts +107 -0
- package/dist/components/WhiteUnderbasePanel.d.ts.map +1 -0
- package/dist/components/WhiteUnderbasePanel.js +104 -0
- package/dist/components/WhiteUnderbasePanel.js.map +1 -0
- package/dist/data/dielines.json +35 -0
- package/dist/hooks/useEditorMode.d.ts +25 -5
- package/dist/hooks/useEditorMode.d.ts.map +1 -1
- package/dist/hooks/useEditorMode.js +18 -5
- package/dist/hooks/useEditorMode.js.map +1 -1
- package/dist/index.d.ts +49 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -2
- package/dist/index.js.map +1 -1
- package/dist/lens/dieline-overlay.d.ts +25 -0
- package/dist/lens/dieline-overlay.d.ts.map +1 -0
- package/dist/lens/dieline-overlay.js +50 -0
- package/dist/lens/dieline-overlay.js.map +1 -0
- package/dist/lens/index.d.ts +27 -0
- package/dist/lens/index.d.ts.map +1 -0
- package/dist/lens/index.js +28 -0
- package/dist/lens/index.js.map +1 -0
- package/dist/lens/preflight-findings.d.ts +21 -0
- package/dist/lens/preflight-findings.d.ts.map +1 -0
- package/dist/lens/preflight-findings.js +82 -0
- package/dist/lens/preflight-findings.js.map +1 -0
- package/dist/lib/barcode-scan.d.ts +154 -0
- package/dist/lib/barcode-scan.d.ts.map +1 -0
- package/dist/lib/barcode-scan.js +152 -0
- package/dist/lib/barcode-scan.js.map +1 -0
- package/dist/lib/color-math.d.ts +76 -0
- package/dist/lib/color-math.d.ts.map +1 -0
- package/dist/lib/color-math.js +96 -0
- package/dist/lib/color-math.js.map +1 -0
- package/dist/lib/dieline-template.d.ts +169 -0
- package/dist/lib/dieline-template.d.ts.map +1 -1
- package/dist/lib/dieline-template.js +229 -1
- package/dist/lib/dieline-template.js.map +1 -1
- package/dist/lib/editor-config.d.ts +384 -1
- package/dist/lib/editor-config.d.ts.map +1 -1
- package/dist/lib/editor-config.js +89 -2
- package/dist/lib/editor-config.js.map +1 -1
- package/dist/lib/fold-geometry.d.ts +144 -0
- package/dist/lib/fold-geometry.d.ts.map +1 -0
- package/dist/lib/fold-geometry.js +138 -0
- package/dist/lib/fold-geometry.js.map +1 -0
- package/dist/lib/merge-tokens.d.ts +81 -0
- package/dist/lib/merge-tokens.d.ts.map +1 -0
- package/dist/lib/merge-tokens.js +88 -0
- package/dist/lib/merge-tokens.js.map +1 -0
- package/dist/lib/palette-registry.d.ts +40 -0
- package/dist/lib/palette-registry.d.ts.map +1 -0
- package/dist/lib/palette-registry.js +49 -0
- package/dist/lib/palette-registry.js.map +1 -0
- package/dist/lib/panel-anchor.d.ts +101 -0
- package/dist/lib/panel-anchor.d.ts.map +1 -0
- package/dist/lib/panel-anchor.js +68 -0
- package/dist/lib/panel-anchor.js.map +1 -0
- package/dist/lib/preflight/checks.d.ts.map +1 -1
- package/dist/lib/preflight/checks.js +71 -0
- package/dist/lib/preflight/checks.js.map +1 -1
- package/dist/lib/preflight/types.d.ts.map +1 -1
- package/dist/lib/preflight/types.js +11 -0
- package/dist/lib/preflight/types.js.map +1 -1
- package/dist/lib/rasterize.d.ts +93 -0
- package/dist/lib/rasterize.d.ts.map +1 -0
- package/dist/lib/rasterize.js +117 -0
- package/dist/lib/rasterize.js.map +1 -0
- package/dist/lib/separations-registry.d.ts +99 -0
- package/dist/lib/separations-registry.d.ts.map +1 -0
- package/dist/lib/separations-registry.js +59 -0
- package/dist/lib/separations-registry.js.map +1 -0
- package/dist/lib/unwired.d.ts +29 -0
- package/dist/lib/unwired.d.ts.map +1 -0
- package/dist/lib/unwired.js +58 -0
- package/dist/lib/unwired.js.map +1 -0
- package/package.json +29 -11
- package/dist/components/SeparationsPanel.d.ts +0 -9
- package/dist/components/SeparationsPanel.d.ts.map +0 -1
- package/dist/components/SeparationsPanel.js +0 -168
- package/dist/components/SeparationsPanel.js.map +0 -1
|
@@ -0,0 +1,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":"
|
|
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
|
-
|
|
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
|
|
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:
|
|
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;
|
|
1
|
+
{"version":3,"file":"FileDropZone.js","sourceRoot":"","sources":["../../src/components/FileDropZone.tsx"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;;AACb,OAAO,EAAgB,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACzF,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAatD;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,IAAI,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAC9C,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC5C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,EAAE,MAAM,EAAE,SAAS,EAAS;IACvD,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,MAAM,CAAmB,IAAI,CAAC,CAAC;IAEhD,MAAM,gBAAgB,GAAG,SAAS,KAAK,SAAS,CAAC;IAEjD,MAAM,MAAM,GAAG,WAAW,CACxB,KAAK,EAAE,IAAU,EAAE,EAAE;QACnB,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,8DAA8D;QAC9D,4DAA4D;QAC5D,yDAAyD;QACzD,2DAA2D;QAC3D,mDAAmD;QACnD,MAAM,aAAa,GAAG,gBAAgB,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAC5E,IAAI,aAAa,IAAI,SAAS,EAAE,CAAC;YAC/B,IAAI,CAAC;gBACH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC/B,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC;gBACpC,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oBAC/B,aAAa,CAAC,GAAG,IAAI,CAAC,IAAI,+CAA+C,CAAC,CAAC;oBAC3E,OAAO;gBACT,CAAC;gBACD,SAAS,CAAC,OAAO,CAAC,CAAC;YACrB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC7D,aAAa,CAAC,GAAG,IAAI,CAAC,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC;YACxC,CAAC;YACD,OAAO;QACT,CAAC;QAED,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,EAAE,SAAS,EAAE,gBAAgB,CAAC,CACtC,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,EAAE,gBAAgB,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,cAAc,EAC1E,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,YAEA,gBAAgB,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,wBAAwB,GAC7E,EACP,eAAM,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,YAClE,gBAAgB;oBACf,CAAC,CAAC,uFAAuF;oBACzF,CAAC,CAAC,oEAAoE,GACnE,EACN,UAAU,IAAI,CACb,eACE,IAAI,EAAC,OAAO,eACF,QAAQ,EAClB,KAAK,EAAE;oBACL,OAAO,EAAE,OAAO;oBAChB,KAAK,EAAE,SAAS;oBAChB,SAAS,EAAE,SAAS;oBACpB,QAAQ,EAAE,QAAQ;iBACnB,YAEA,UAAU,GACN,CACR,IACM,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -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"}
|