@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,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wave 4 I1 — Generic webhook notify panel.
|
|
3
|
+
*
|
|
4
|
+
* Companion to the I3 {@link SlackNotifyPanel} (Wave 4 PR-11). Where
|
|
5
|
+
* I3 targets a single integration (Slack incoming webhooks) with a
|
|
6
|
+
* canned message template per event, I1 is the generic catch-all —
|
|
7
|
+
* the host wires any outbound HTTP integration (Zapier, n8n, GitHub
|
|
8
|
+
* Actions repository_dispatch, internal worker queues, custom tenant
|
|
9
|
+
* endpoints) by supplying a {@link WebhookNotifyFn} adapter and the
|
|
10
|
+
* panel emits a typed {@link WebhookNotificationEvent} payload.
|
|
11
|
+
*
|
|
12
|
+
* The wire shape is intentionally structured rather than free-form
|
|
13
|
+
* text: downstream consumers can pattern-match on `kind` and read
|
|
14
|
+
* typed fields off `context`, rather than parsing English. Hosts that
|
|
15
|
+
* want a human-readable rendering on top of the structured payload
|
|
16
|
+
* wrap their own adapter.
|
|
17
|
+
*
|
|
18
|
+
* Pairs with the synergy `webhook.notify` workflow node when one is
|
|
19
|
+
* deployed; hosts running purely client-side `fetch()` calls wire a
|
|
20
|
+
* local adapter in the meantime.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
import type { ReactElement } from "react";
|
|
25
|
+
/**
|
|
26
|
+
* The set of editor events the panel can emit. Mirrors
|
|
27
|
+
* {@link SlackNotificationEventKind} for cross-integration parity —
|
|
28
|
+
* the two panels respond to the same event vocabulary so a host can
|
|
29
|
+
* wire I1 + I3 against the same trigger list.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export type WebhookNotificationEventKind = "preflight-blocked" | "preflight-cleared" | "job-submitted" | "variant-approved" | "approval-requested" | "custom";
|
|
34
|
+
/**
|
|
35
|
+
* Context the host passes in alongside the chosen event. Mirrors
|
|
36
|
+
* {@link SlackNotificationContext} so a single host-side state object
|
|
37
|
+
* can feed both panels; the webhook payload preserves the structured
|
|
38
|
+
* fields rather than rendering them into a single text line.
|
|
39
|
+
*
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
export type WebhookNotificationContext = {
|
|
43
|
+
/** Human-readable document name. */
|
|
44
|
+
documentName?: string;
|
|
45
|
+
/** Stable identifier the host uses to link back to the document. */
|
|
46
|
+
documentId?: string;
|
|
47
|
+
/** Optional clickable URL the downstream consumer can use to jump
|
|
48
|
+
* straight into the editor. */
|
|
49
|
+
documentUrl?: string;
|
|
50
|
+
/** Preflight finding count (errors only for `"preflight-blocked"`,
|
|
51
|
+
* total resolved for `"preflight-cleared"`). */
|
|
52
|
+
findingCount?: number;
|
|
53
|
+
/** Variant id for `"variant-approved"`. */
|
|
54
|
+
variantId?: string;
|
|
55
|
+
/** Reviewer / submitter display name. */
|
|
56
|
+
actor?: string;
|
|
57
|
+
/** Free-form additional text — the panel surfaces an optional note
|
|
58
|
+
* input that populates this; downstream consumers may render it as
|
|
59
|
+
* a description / commit message / etc. */
|
|
60
|
+
text?: string;
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Canonical structured payload the panel POSTs to the host adapter.
|
|
64
|
+
* The `kind` + `context` split keeps the wire shape pattern-matchable
|
|
65
|
+
* (no English-parsing required on the receiver) while leaving the
|
|
66
|
+
* envelope (`integration`, `sentAt`) free for routing.
|
|
67
|
+
*
|
|
68
|
+
* @public
|
|
69
|
+
*/
|
|
70
|
+
export type WebhookNotificationEvent = {
|
|
71
|
+
/** Schema version — bump on breaking shape changes. */
|
|
72
|
+
schemaVersion: 1;
|
|
73
|
+
/** Event kind from {@link WebhookNotificationEventKind}. */
|
|
74
|
+
kind: WebhookNotificationEventKind;
|
|
75
|
+
/** Structured context — see {@link WebhookNotificationContext}. */
|
|
76
|
+
context: WebhookNotificationContext;
|
|
77
|
+
/** Optional integration identifier the host can use to route the
|
|
78
|
+
* event to one of many wired endpoints (e.g. `"zapier-main"`,
|
|
79
|
+
* `"github-actions-staging"`). When absent, the host adapter
|
|
80
|
+
* decides the default destination. */
|
|
81
|
+
integration?: string;
|
|
82
|
+
/** ISO 8601 timestamp the panel stamps at send time. */
|
|
83
|
+
sentAt: string;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* Pure helper — composes a {@link WebhookNotificationEvent} from a
|
|
87
|
+
* kind + context + optional integration. Stamps `sentAt` to the
|
|
88
|
+
* passed-in `now()` so tests can pin the timestamp. Pure function;
|
|
89
|
+
* no I/O.
|
|
90
|
+
*
|
|
91
|
+
* @public
|
|
92
|
+
*/
|
|
93
|
+
export declare function composeWebhookEvent(kind: WebhookNotificationEventKind, context: WebhookNotificationContext, options?: {
|
|
94
|
+
integration?: string;
|
|
95
|
+
now?: () => Date;
|
|
96
|
+
}): WebhookNotificationEvent;
|
|
97
|
+
/**
|
|
98
|
+
* Host adapter — POSTs the composed payload to the wired endpoint
|
|
99
|
+
* (typically via a server-side proxy or the synergy `webhook.notify`
|
|
100
|
+
* node). Resolves on accept; rejects on transport / validation
|
|
101
|
+
* errors and the panel surfaces the message inline.
|
|
102
|
+
*
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
export type WebhookNotifyFn = (event: WebhookNotificationEvent) => Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Human-readable labels for each event kind, in the order they appear
|
|
108
|
+
* in the dropdown. Mirrors {@link SlackNotifyPanel}'s label map so the
|
|
109
|
+
* two panels stay in lockstep.
|
|
110
|
+
*
|
|
111
|
+
* @public
|
|
112
|
+
*/
|
|
113
|
+
export declare const WEBHOOK_NOTIFICATION_EVENT_LABELS: Readonly<Record<WebhookNotificationEventKind, string>>;
|
|
114
|
+
/**
|
|
115
|
+
* Configuration for the {@link WebhookNotifyPanel}.
|
|
116
|
+
*
|
|
117
|
+
* The host supplies the {@link WebhookNotifyFn} adapter, the typed
|
|
118
|
+
* {@link WebhookNotificationContext}, and (optionally) a list of
|
|
119
|
+
* integration ids that populate the panel's "Integration" dropdown.
|
|
120
|
+
* The panel handles event-kind selection, the optional free-form
|
|
121
|
+
* note, the send button state machine, and surfaces success / error
|
|
122
|
+
* inline.
|
|
123
|
+
*
|
|
124
|
+
* @public
|
|
125
|
+
*/
|
|
126
|
+
export type WebhookNotifyPanelProps = {
|
|
127
|
+
/** Host adapter — see {@link WebhookNotifyFn}. */
|
|
128
|
+
notify: WebhookNotifyFn;
|
|
129
|
+
/** Typed context to bundle into the outgoing event. The host
|
|
130
|
+
* typically wires this from the active document. */
|
|
131
|
+
context: WebhookNotificationContext;
|
|
132
|
+
/** Optional initial event selection. Defaults to
|
|
133
|
+
* `"job-submitted"` — the most common webhook trigger across
|
|
134
|
+
* CI / queue / chat integrations. */
|
|
135
|
+
defaultEvent?: WebhookNotificationEventKind;
|
|
136
|
+
/** Optional list of integration ids the host has wired. Surfaces as
|
|
137
|
+
* a dropdown; when absent the panel omits the picker and the
|
|
138
|
+
* outgoing event has no `integration` field set. */
|
|
139
|
+
integrations?: readonly string[];
|
|
140
|
+
/** Optional initial integration selection. Must match one of
|
|
141
|
+
* `integrations`; when absent the first entry is selected. */
|
|
142
|
+
defaultIntegration?: string;
|
|
143
|
+
/** Optional mapper that turns a notify error into a user-facing
|
|
144
|
+
* message. The default avoids leaking internal `Error.message`
|
|
145
|
+
* strings; hosts that want richer surfaces pass their own mapper.
|
|
146
|
+
* The original error is still passed in so hosts can log it. */
|
|
147
|
+
errorMessage?: (err: unknown) => string;
|
|
148
|
+
/** Optional callback fired on successful notify so the host can
|
|
149
|
+
* show a confirmation toast / log analytics. */
|
|
150
|
+
onSuccess?: (event: WebhookNotificationEvent) => void;
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Stateful panel — picks an event template + integration, lets the
|
|
154
|
+
* user append a custom note, composes the typed event via
|
|
155
|
+
* {@link composeWebhookEvent}, and POSTs through the host adapter.
|
|
156
|
+
*
|
|
157
|
+
* @public
|
|
158
|
+
*/
|
|
159
|
+
export declare function WebhookNotifyPanel({ notify, context, defaultEvent, integrations, defaultIntegration, errorMessage, onSuccess, }: WebhookNotifyPanelProps): ReactElement;
|
|
160
|
+
//# sourceMappingURL=WebhookNotifyPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebhookNotifyPanel.d.ts","sourceRoot":"","sources":["../../src/components/WebhookNotifyPanel.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C;;;;;;;GAOG;AACH,MAAM,MAAM,4BAA4B,GACpC,mBAAmB,GACnB,mBAAmB,GACnB,eAAe,GACf,kBAAkB,GAClB,oBAAoB,GACpB,QAAQ,CAAC;AAEb;;;;;;;GAOG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,oEAAoE;IACpE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;oCACgC;IAChC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;qDACiD;IACjD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;gDAE4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,uDAAuD;IACvD,aAAa,EAAE,CAAC,CAAC;IACjB,4DAA4D;IAC5D,IAAI,EAAE,4BAA4B,CAAC;IACnC,mEAAmE;IACnE,OAAO,EAAE,0BAA0B,CAAC;IACpC;;;2CAGuC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,wDAAwD;IACxD,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,4BAA4B,EAClC,OAAO,EAAE,0BAA0B,EACnC,OAAO,CAAC,EAAE;IAAE,WAAW,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,IAAI,CAAA;CAAE,GACnD,wBAAwB,CAS1B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,wBAAwB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjF;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,EAAE,QAAQ,CACtD,MAAM,CAAC,4BAA4B,EAAE,MAAM,CAAC,CAQ7C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,uBAAuB,GAAG;IACpC,kDAAkD;IAClD,MAAM,EAAE,eAAe,CAAC;IACxB;yDACqD;IACrD,OAAO,EAAE,0BAA0B,CAAC;IACpC;;0CAEsC;IACtC,YAAY,CAAC,EAAE,4BAA4B,CAAC;IAC5C;;yDAEqD;IACrD,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC;mEAC+D;IAC/D,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;qEAGiE;IACjE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;IACxC;qDACiD;IACjD,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,wBAAwB,KAAK,IAAI,CAAC;CACvD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,MAAM,EACN,OAAO,EACP,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,SAAS,GACV,EAAE,uBAAuB,GAAG,YAAY,CAgIxC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
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
|
+
/**
|
|
6
|
+
* Pure helper — composes a {@link WebhookNotificationEvent} from a
|
|
7
|
+
* kind + context + optional integration. Stamps `sentAt` to the
|
|
8
|
+
* passed-in `now()` so tests can pin the timestamp. Pure function;
|
|
9
|
+
* no I/O.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export function composeWebhookEvent(kind, context, options) {
|
|
14
|
+
const now = options?.now ?? (() => new Date());
|
|
15
|
+
return {
|
|
16
|
+
schemaVersion: 1,
|
|
17
|
+
kind,
|
|
18
|
+
context,
|
|
19
|
+
...(options?.integration && { integration: options.integration }),
|
|
20
|
+
sentAt: now().toISOString(),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Human-readable labels for each event kind, in the order they appear
|
|
25
|
+
* in the dropdown. Mirrors {@link SlackNotifyPanel}'s label map so the
|
|
26
|
+
* two panels stay in lockstep.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export const WEBHOOK_NOTIFICATION_EVENT_LABELS = {
|
|
31
|
+
"preflight-blocked": "Preflight blocked",
|
|
32
|
+
"preflight-cleared": "Preflight cleared",
|
|
33
|
+
"job-submitted": "Job submitted",
|
|
34
|
+
"variant-approved": "Variant approved",
|
|
35
|
+
"approval-requested": "Approval requested",
|
|
36
|
+
custom: "Custom event",
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* Stateful panel — picks an event template + integration, lets the
|
|
40
|
+
* user append a custom note, composes the typed event via
|
|
41
|
+
* {@link composeWebhookEvent}, and POSTs through the host adapter.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export function WebhookNotifyPanel({ notify, context, defaultEvent, integrations, defaultIntegration, errorMessage, onSuccess, }) {
|
|
46
|
+
const [event, setEvent] = useState(defaultEvent ?? "job-submitted");
|
|
47
|
+
// Validate `defaultIntegration` against the wired list — a host-supplied
|
|
48
|
+
// default that isn't in `integrations` would otherwise quietly ship as
|
|
49
|
+
// the outgoing event's `integration` field even though the user can't
|
|
50
|
+
// see / change it in the dropdown.
|
|
51
|
+
const [integration, setIntegration] = useState(() => {
|
|
52
|
+
if (defaultIntegration && integrations?.includes(defaultIntegration)) {
|
|
53
|
+
return defaultIntegration;
|
|
54
|
+
}
|
|
55
|
+
return integrations?.[0] ?? "";
|
|
56
|
+
});
|
|
57
|
+
const [note, setNote] = useState("");
|
|
58
|
+
const [state, setState] = useState({ kind: "idle" });
|
|
59
|
+
// Clear the success / error chip when the user edits any input —
|
|
60
|
+
// a "Sent" indicator next to an unsent payload reads as a lie.
|
|
61
|
+
const resetOutcome = () => {
|
|
62
|
+
setState((prev) => (prev.kind === "ok" || prev.kind === "error" ? { kind: "idle" } : prev));
|
|
63
|
+
};
|
|
64
|
+
const onClick = async () => {
|
|
65
|
+
setState({ kind: "sending" });
|
|
66
|
+
const payload = composeWebhookEvent(event, {
|
|
67
|
+
...context,
|
|
68
|
+
...(note.trim() && { text: note }),
|
|
69
|
+
}, integration ? { integration } : undefined);
|
|
70
|
+
try {
|
|
71
|
+
await notify(payload);
|
|
72
|
+
setState({ kind: "ok" });
|
|
73
|
+
onSuccess?.(payload);
|
|
74
|
+
}
|
|
75
|
+
catch (err) {
|
|
76
|
+
// Guard against a host-supplied errorMessage that throws.
|
|
77
|
+
let message = "Couldn't send webhook notification.";
|
|
78
|
+
if (errorMessage) {
|
|
79
|
+
try {
|
|
80
|
+
message = errorMessage(err);
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// fall back to the default
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
setState({ kind: "error", message });
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
return (_jsxs("div", { "data-testid": "webhook-notify-panel", style: { padding: "0.5rem" }, children: [_jsx("header", { style: { marginBottom: "0.5rem" }, children: _jsx("h3", { style: { margin: 0, fontSize: "0.875rem" }, children: "Webhook notify" }) }), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Event", _jsx("select", { "aria-label": "Event", value: event, onChange: (e) => {
|
|
90
|
+
setEvent(e.target.value);
|
|
91
|
+
resetOutcome();
|
|
92
|
+
}, style: { display: "block", marginTop: "0.125rem", width: "100%" }, children: Object.entries(WEBHOOK_NOTIFICATION_EVENT_LABELS).map(([k, label]) => (_jsx("option", { value: k, children: label }, k))) })] }), integrations && integrations.length > 0 && (_jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Integration", _jsx("select", { "aria-label": "Integration", value: integration, onChange: (e) => {
|
|
93
|
+
setIntegration(e.target.value);
|
|
94
|
+
resetOutcome();
|
|
95
|
+
}, style: { display: "block", marginTop: "0.125rem", width: "100%" }, children: integrations.map((id) => (_jsx("option", { value: id, children: id }, id))) })] })), _jsxs("label", { style: { display: "block", fontSize: "0.75rem", marginBottom: "0.5rem" }, children: ["Note", _jsx("textarea", { "aria-label": "Note", placeholder: "Optional \u2014 included as context.text", value: note, onChange: (e) => {
|
|
96
|
+
setNote(e.target.value);
|
|
97
|
+
resetOutcome();
|
|
98
|
+
}, 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 webhook" }), 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 }))] })] }));
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=WebhookNotifyPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WebhookNotifyPanel.js","sourceRoot":"","sources":["../../src/components/WebhookNotifyPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wave 3 C2 — White / underbase auto-generation panel.
|
|
3
|
+
*
|
|
4
|
+
* Many packaging substrates (foils, dark plastics, kraft) require an
|
|
5
|
+
* opaque white layer printed *under* the CMYK / spots so the
|
|
6
|
+
* subsequent ink lays down with the colour the designer specified
|
|
7
|
+
* rather than being tinted by the substrate. Manually authoring this
|
|
8
|
+
* separation is tedious and error-prone — C2 asks compile-pdf's
|
|
9
|
+
* `white_underbase` producer to compute the union of CMYK fill
|
|
10
|
+
* coverage on the page and emit a new `White` separation matching
|
|
11
|
+
* that union, optionally choked inward by a small amount so the
|
|
12
|
+
* white doesn't peek out from underneath the chromatic ink.
|
|
13
|
+
*
|
|
14
|
+
* Pure-adapter design (same shape as the rest of the AI / I family
|
|
15
|
+
* panels): the host wires a {@link WhiteUnderbaseGeneratorFn} that
|
|
16
|
+
* fronts the producer; the panel owns config inputs and lifecycle
|
|
17
|
+
* state.
|
|
18
|
+
*
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
import type { ReactElement } from "react";
|
|
22
|
+
/**
|
|
23
|
+
* Spec for one underbase-generation request. Mirrors the
|
|
24
|
+
* `WhiteUnderbaseOptions` shape on compile-pdf's
|
|
25
|
+
* `/v1/white-underbase/apply` endpoint so a host can pass the value
|
|
26
|
+
* straight through.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export type WhiteUnderbaseSpec = {
|
|
31
|
+
/** Name to assign the new separation. Default `"White"`. */
|
|
32
|
+
separationName: string;
|
|
33
|
+
/** Opacity of the underbase (0..1). 1 = solid white. */
|
|
34
|
+
opacity: number;
|
|
35
|
+
/** Distance (in mm) to choke the white inward from the chromatic
|
|
36
|
+
* ink edges. Prevents the white from peeking out around the
|
|
37
|
+
* printed colour. 0 = no choke. */
|
|
38
|
+
chokeMm: number;
|
|
39
|
+
/** How the underbase relates to overlapping chromatic ink:
|
|
40
|
+
* - `solid` — white covers the entire chromatic region (default)
|
|
41
|
+
* - `subtract-cmyk` — white opacity is scaled down where CMYK
|
|
42
|
+
* coverage approaches 100% (lighter inks need less underbase) */
|
|
43
|
+
knockoutMode: "solid" | "subtract-cmyk";
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* Default spec values — sensible for the most common case
|
|
47
|
+
* (white-ink underbase on dark substrate, no choke).
|
|
48
|
+
*
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export declare const DEFAULT_WHITE_UNDERBASE_SPEC: WhiteUnderbaseSpec;
|
|
52
|
+
/**
|
|
53
|
+
* Result returned by the host generator. The host typically wires
|
|
54
|
+
* this to `CompilePdfClient.whiteUnderbase()` which calls
|
|
55
|
+
* `/v1/white-underbase/apply` and returns the producer's
|
|
56
|
+
* `separation_name` + `coverage_pct` fields.
|
|
57
|
+
*
|
|
58
|
+
* @public
|
|
59
|
+
*/
|
|
60
|
+
export type WhiteUnderbaseResult = {
|
|
61
|
+
separationName: string;
|
|
62
|
+
/** Percentage of the page area covered by the new underbase
|
|
63
|
+
* separation. Useful as a sanity check (e.g. > 95 % suggests the
|
|
64
|
+
* page is mostly chromatic — review the choke). */
|
|
65
|
+
coveragePct: number;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Host adapter — generates the white underbase for the active
|
|
69
|
+
* document. Rejects on transport / validation errors and the panel
|
|
70
|
+
* surfaces the message inline.
|
|
71
|
+
*
|
|
72
|
+
* @public
|
|
73
|
+
*/
|
|
74
|
+
export type WhiteUnderbaseGeneratorFn = (spec: WhiteUnderbaseSpec) => Promise<WhiteUnderbaseResult>;
|
|
75
|
+
/**
|
|
76
|
+
* Pure helper — validates a spec. Returns the first error message
|
|
77
|
+
* encountered or `null` when the spec is valid. Hosts can call this
|
|
78
|
+
* to disable the "Generate" button preemptively. Pure function.
|
|
79
|
+
*
|
|
80
|
+
* @public
|
|
81
|
+
*/
|
|
82
|
+
export declare function validateWhiteUnderbaseSpec(spec: WhiteUnderbaseSpec): string | null;
|
|
83
|
+
/**
|
|
84
|
+
* Configuration for the {@link WhiteUnderbasePanel}.
|
|
85
|
+
*
|
|
86
|
+
* @public
|
|
87
|
+
*/
|
|
88
|
+
export type WhiteUnderbasePanelProps = {
|
|
89
|
+
/** Initial spec values — `DEFAULT_WHITE_UNDERBASE_SPEC` if absent. */
|
|
90
|
+
initialSpec?: Partial<WhiteUnderbaseSpec>;
|
|
91
|
+
/** Generator adapter — when absent, the panel renders in
|
|
92
|
+
* read-only mode (config inputs disabled). Useful when the host
|
|
93
|
+
* wants to surface the controls but defer the network wire. */
|
|
94
|
+
generator?: WhiteUnderbaseGeneratorFn;
|
|
95
|
+
/** Fired after a successful generation — typically used to refresh
|
|
96
|
+
* the editor's separations registry / inks panel. */
|
|
97
|
+
onGenerated?: (result: WhiteUnderbaseResult) => void;
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* Stateful panel — exposes inputs for every {@link WhiteUnderbaseSpec}
|
|
101
|
+
* field, dispatches the generator, and surfaces the result chip /
|
|
102
|
+
* inline error. Handles loading, validation, and success states.
|
|
103
|
+
*
|
|
104
|
+
* @public
|
|
105
|
+
*/
|
|
106
|
+
export declare function WhiteUnderbasePanel({ initialSpec, generator, onGenerated, }: WhiteUnderbasePanelProps): ReactElement;
|
|
107
|
+
//# sourceMappingURL=WhiteUnderbasePanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WhiteUnderbasePanel.d.ts","sourceRoot":"","sources":["../../src/components/WhiteUnderbasePanel.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,4DAA4D;IAC5D,cAAc,EAAE,MAAM,CAAC;IACvB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB;;wCAEoC;IACpC,OAAO,EAAE,MAAM,CAAC;IAChB;;;wEAGoE;IACpE,YAAY,EAAE,OAAO,GAAG,eAAe,CAAC;CACzC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,EAAE,kBAK1C,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB;;wDAEoD;IACpD,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,yBAAyB,GAAG,CACtC,IAAI,EAAE,kBAAkB,KACrB,OAAO,CAAC,oBAAoB,CAAC,CAAC;AAEnC;;;;;;GAMG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,GAAG,IAAI,CAalF;AAED;;;;GAIG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAC,kBAAkB,CAAC,CAAC;IAC1C;;oEAEgE;IAChE,SAAS,CAAC,EAAE,yBAAyB,CAAC;IACtC;0DACsD;IACtD,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,CAAC;CACtD,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,SAAS,EACT,WAAW,GACZ,EAAE,wBAAwB,GAAG,YAAY,CAyIzC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
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 { useCallback, useState } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Default spec values — sensible for the most common case
|
|
7
|
+
* (white-ink underbase on dark substrate, no choke).
|
|
8
|
+
*
|
|
9
|
+
* @public
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_WHITE_UNDERBASE_SPEC = {
|
|
12
|
+
separationName: "White",
|
|
13
|
+
opacity: 1,
|
|
14
|
+
chokeMm: 0,
|
|
15
|
+
knockoutMode: "solid",
|
|
16
|
+
};
|
|
17
|
+
/**
|
|
18
|
+
* Pure helper — validates a spec. Returns the first error message
|
|
19
|
+
* encountered or `null` when the spec is valid. Hosts can call this
|
|
20
|
+
* to disable the "Generate" button preemptively. Pure function.
|
|
21
|
+
*
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export function validateWhiteUnderbaseSpec(spec) {
|
|
25
|
+
// Defensive against partial-spec merges that leave fields undefined
|
|
26
|
+
// (Partial<WhiteUnderbaseSpec> lets a host pass `{ separationName:
|
|
27
|
+
// undefined }`, which would otherwise throw on `.trim()`).
|
|
28
|
+
const name = spec.separationName ?? "";
|
|
29
|
+
if (!name.trim())
|
|
30
|
+
return "Separation name is required.";
|
|
31
|
+
if (!Number.isFinite(spec.opacity) || spec.opacity < 0 || spec.opacity > 1) {
|
|
32
|
+
return "Opacity must be between 0 and 1.";
|
|
33
|
+
}
|
|
34
|
+
if (!Number.isFinite(spec.chokeMm))
|
|
35
|
+
return "Choke must be a number.";
|
|
36
|
+
if (spec.chokeMm < 0)
|
|
37
|
+
return "Choke can't be negative.";
|
|
38
|
+
if (spec.chokeMm > 5)
|
|
39
|
+
return "Choke above 5 mm is implausibly large; double-check.";
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Stateful panel — exposes inputs for every {@link WhiteUnderbaseSpec}
|
|
44
|
+
* field, dispatches the generator, and surfaces the result chip /
|
|
45
|
+
* inline error. Handles loading, validation, and success states.
|
|
46
|
+
*
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
export function WhiteUnderbasePanel({ initialSpec, generator, onGenerated, }) {
|
|
50
|
+
const [spec, setSpec] = useState(() => {
|
|
51
|
+
// Field-wise merge — skip undefined values in initialSpec so hosts
|
|
52
|
+
// passing `{ separationName: undefined }` don't clobber the
|
|
53
|
+
// defaults and leave required fields unset.
|
|
54
|
+
const merged = { ...DEFAULT_WHITE_UNDERBASE_SPEC };
|
|
55
|
+
if (!initialSpec)
|
|
56
|
+
return merged;
|
|
57
|
+
for (const key of Object.keys(initialSpec)) {
|
|
58
|
+
const value = initialSpec[key];
|
|
59
|
+
if (value !== undefined) {
|
|
60
|
+
// biome-ignore lint/suspicious/noExplicitAny: dynamic keyed assignment
|
|
61
|
+
merged[key] = value;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return merged;
|
|
65
|
+
});
|
|
66
|
+
const [status, setStatus] = useState("idle");
|
|
67
|
+
const [result, setResult] = useState(null);
|
|
68
|
+
const [errorMsg, setErrorMsg] = useState(null);
|
|
69
|
+
const validationError = validateWhiteUnderbaseSpec(spec);
|
|
70
|
+
const canGenerate = !!generator && status !== "loading" && !validationError;
|
|
71
|
+
const generate = useCallback(async () => {
|
|
72
|
+
if (!generator)
|
|
73
|
+
return;
|
|
74
|
+
setStatus("loading");
|
|
75
|
+
setErrorMsg(null);
|
|
76
|
+
try {
|
|
77
|
+
const next = await generator(spec);
|
|
78
|
+
setResult(next);
|
|
79
|
+
setStatus("done");
|
|
80
|
+
onGenerated?.(next);
|
|
81
|
+
}
|
|
82
|
+
catch (err) {
|
|
83
|
+
const msg = err instanceof Error ? err.message : "Generation failed.";
|
|
84
|
+
setErrorMsg(msg);
|
|
85
|
+
setStatus("error");
|
|
86
|
+
}
|
|
87
|
+
}, [generator, spec, onGenerated]);
|
|
88
|
+
const update = (key, value) => {
|
|
89
|
+
setSpec((prev) => ({ ...prev, [key]: value }));
|
|
90
|
+
};
|
|
91
|
+
return (_jsxs("div", { "data-testid": "white-underbase-panel", style: { padding: "0.5rem" }, children: [_jsx("header", { style: { marginBottom: "0.5rem" }, children: _jsx("h3", { style: { margin: 0, fontSize: "0.875rem" }, children: "White underbase" }) }), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.375rem" }, children: [_jsxs("label", { style: { fontSize: "0.75rem", display: "flex", flexDirection: "column" }, children: [_jsx("span", { style: { color: "#595959", marginBottom: "0.125rem" }, children: "Separation name" }), _jsx("input", { type: "text", value: spec.separationName, onChange: (e) => update("separationName", e.target.value), disabled: !generator, style: { fontSize: "0.8125rem", padding: "0.25rem 0.375rem" } })] }), _jsxs("label", { style: { fontSize: "0.75rem", display: "flex", flexDirection: "column" }, children: [_jsxs("span", { style: { color: "#595959", marginBottom: "0.125rem" }, children: ["Opacity (", spec.opacity.toFixed(2), ")"] }), _jsx("input", { type: "range", min: 0, max: 1, step: 0.05, value: spec.opacity, onChange: (e) => {
|
|
92
|
+
const next = Number(e.target.value);
|
|
93
|
+
if (Number.isFinite(next))
|
|
94
|
+
update("opacity", next);
|
|
95
|
+
}, disabled: !generator })] }), _jsxs("label", { style: { fontSize: "0.75rem", display: "flex", flexDirection: "column" }, children: [_jsx("span", { style: { color: "#595959", marginBottom: "0.125rem" }, children: "Choke (mm)" }), _jsx("input", { type: "number", min: 0, max: 5, step: 0.05, value: spec.chokeMm, onChange: (e) => {
|
|
96
|
+
// Empty number input → "" → NaN, which would bypass
|
|
97
|
+
// validation and slip through to the generator. Treat a
|
|
98
|
+
// cleared field as 0 (the no-choke default).
|
|
99
|
+
const next = e.target.value === "" ? 0 : Number(e.target.value);
|
|
100
|
+
if (Number.isFinite(next))
|
|
101
|
+
update("chokeMm", next);
|
|
102
|
+
}, disabled: !generator, style: { fontSize: "0.8125rem", padding: "0.25rem 0.375rem" } })] }), _jsxs("label", { style: { fontSize: "0.75rem", display: "flex", flexDirection: "column" }, children: [_jsx("span", { style: { color: "#595959", marginBottom: "0.125rem" }, children: "Knockout mode" }), _jsxs("select", { value: spec.knockoutMode, onChange: (e) => update("knockoutMode", e.target.value), disabled: !generator, style: { fontSize: "0.8125rem", padding: "0.25rem 0.375rem" }, children: [_jsx("option", { value: "solid", children: "solid \u2014 full coverage" }), _jsx("option", { value: "subtract-cmyk", children: "subtract-cmyk \u2014 scale by ink density" })] })] })] }), validationError && (_jsx("div", { role: "alert", style: { marginTop: "0.5rem", fontSize: "0.75rem", color: "#a60" }, children: validationError })), _jsxs("div", { style: { marginTop: "0.5rem", display: "flex", alignItems: "center", gap: "0.5rem" }, children: [_jsx("button", { type: "button", onClick: generate, disabled: !canGenerate, style: { fontSize: "0.75rem", padding: "0.25rem 0.625rem" }, children: status === "loading" ? "Generating…" : "Generate" }), status === "done" && result && (_jsxs("span", { style: { fontSize: "0.75rem", color: "#595959" }, children: [result.separationName, " \u00B7 ", result.coveragePct.toFixed(1), "% coverage"] })), status === "error" && errorMsg && (_jsx("span", { role: "alert", style: { fontSize: "0.75rem", color: "#a00" }, children: errorMsg }))] })] }));
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=WhiteUnderbasePanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WhiteUnderbasePanel.js","sourceRoot":"","sources":["../../src/components/WhiteUnderbasePanel.tsx"],"names":[],"mappings":"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"}
|
package/dist/data/dielines.json
CHANGED
|
@@ -182,5 +182,40 @@
|
|
|
182
182
|
"previewSvg": "<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 54.8 80.2'><rect x='2' y='2' width='50.8' height='76.2' fill='none' stroke='#333' stroke-width='0.5' rx='3'/><line x1='2' y1='12' x2='52.8' y2='12' stroke='#666' stroke-width='0.3'/><text x='27.4' y='47' text-anchor='middle' font-size='6' fill='#666'>Sachet</text><text x='27.4' y='56' text-anchor='middle' font-size='4' fill='#999'>2×3″</text></svg>",
|
|
183
183
|
"tags": ["sachet", "single-serve", "condiment", "sample", "hotel"]
|
|
184
184
|
}
|
|
185
|
+
],
|
|
186
|
+
"templateSets": [
|
|
187
|
+
{
|
|
188
|
+
"id": "carton-6x4x2-set",
|
|
189
|
+
"name": "Carton 6×4×2 (front + back)",
|
|
190
|
+
"description": "Two-sided dieline for a 6×4×2 straight-tuck carton. Front and back share the same trim.",
|
|
191
|
+
"category": "carton-set",
|
|
192
|
+
"pages": [
|
|
193
|
+
{ "templateId": "carton-6x4x2", "name": "Front" },
|
|
194
|
+
{ "templateId": "carton-6x4x2", "name": "Back" }
|
|
195
|
+
],
|
|
196
|
+
"tags": ["carton", "box", "multi-page", "front-back"]
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "carton-8x6x3-set",
|
|
200
|
+
"name": "Carton 8×6×3 (front + back)",
|
|
201
|
+
"description": "Two-sided dieline for an 8×6×3 straight-tuck carton.",
|
|
202
|
+
"category": "carton-set",
|
|
203
|
+
"pages": [
|
|
204
|
+
{ "templateId": "carton-8x6x3", "name": "Front" },
|
|
205
|
+
{ "templateId": "carton-8x6x3", "name": "Back" }
|
|
206
|
+
],
|
|
207
|
+
"tags": ["carton", "box", "multi-page", "front-back"]
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "standup-pouch-4x6-set",
|
|
211
|
+
"name": "Stand-Up Pouch 4×6 (front + back)",
|
|
212
|
+
"description": "Two-sided dieline for a 4×6 stand-up pouch — front graphic + back panel.",
|
|
213
|
+
"category": "pouch-set",
|
|
214
|
+
"pages": [
|
|
215
|
+
{ "templateId": "standup-pouch-4x6", "name": "Front" },
|
|
216
|
+
{ "templateId": "standup-pouch-4x6", "name": "Back" }
|
|
217
|
+
],
|
|
218
|
+
"tags": ["pouch", "stand-up", "multi-page", "front-back"]
|
|
219
|
+
}
|
|
185
220
|
]
|
|
186
221
|
}
|
|
@@ -1,11 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Editor UI complexity tier. `"basic"` strips advanced controls and
|
|
3
|
+
* is the touch/mobile default; `"pro"` shows the full toolset.
|
|
4
|
+
* Resolved via {@link useEditorMode}.
|
|
5
|
+
*
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
1
8
|
export type EditorMode = "basic" | "pro";
|
|
2
9
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
10
|
+
* Resolve the active editor mode and expose a setter that persists
|
|
11
|
+
* the choice across reloads.
|
|
12
|
+
*
|
|
13
|
+
* Precedence (later wins):
|
|
14
|
+
*
|
|
15
|
+
* 1. Explicit user choice persisted in `localStorage`
|
|
16
|
+
* (`"artworkpdf:editor-mode"`)
|
|
17
|
+
* 2. The `prefer` arg (typically threaded from the host page —
|
|
18
|
+
* `/demo` passes `"auto"` so the viewport heuristic picks)
|
|
19
|
+
* 3. Viewport heuristic: `"pro"` on wider viewports, `"basic"`
|
|
20
|
+
* on narrower ones
|
|
21
|
+
*
|
|
22
|
+
* `setMode(null)` clears the persisted preference and falls back to
|
|
23
|
+
* the heuristic; `isAuto` is true while no explicit choice is saved.
|
|
24
|
+
*
|
|
25
|
+
* SSR-safe: returns the resolved fallback until hydration completes,
|
|
26
|
+
* so the server render matches the first client paint.
|
|
7
27
|
*
|
|
8
|
-
*
|
|
28
|
+
* @public
|
|
9
29
|
*/
|
|
10
30
|
export declare function useEditorMode(prefer?: EditorMode | "auto"): {
|
|
11
31
|
mode: EditorMode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditorMode.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorMode.ts"],"names":[],"mappings":"AAIA,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;AAIzC
|
|
1
|
+
{"version":3,"file":"useEditorMode.d.ts","sourceRoot":"","sources":["../../src/hooks/useEditorMode.ts"],"names":[],"mappings":"AAIA;;;;;;GAMG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,CAAC;AAIzC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAAC,MAAM,GAAE,UAAU,GAAG,MAAe,GAAG;IACnE,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3C,MAAM,EAAE,OAAO,CAAC;CACjB,CAqCA"}
|
|
@@ -3,12 +3,25 @@
|
|
|
3
3
|
import { useCallback, useEffect, useState } from "react";
|
|
4
4
|
const STORAGE_KEY = "artworkpdf:editor-mode";
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
* 2. `prefer` prop (set by the page — e.g. demo passes "auto")
|
|
9
|
-
* 3. Viewport heuristic: pro on >= 900 CSS px, basic otherwise
|
|
6
|
+
* Resolve the active editor mode and expose a setter that persists
|
|
7
|
+
* the choice across reloads.
|
|
10
8
|
*
|
|
11
|
-
*
|
|
9
|
+
* Precedence (later wins):
|
|
10
|
+
*
|
|
11
|
+
* 1. Explicit user choice persisted in `localStorage`
|
|
12
|
+
* (`"artworkpdf:editor-mode"`)
|
|
13
|
+
* 2. The `prefer` arg (typically threaded from the host page —
|
|
14
|
+
* `/demo` passes `"auto"` so the viewport heuristic picks)
|
|
15
|
+
* 3. Viewport heuristic: `"pro"` on wider viewports, `"basic"`
|
|
16
|
+
* on narrower ones
|
|
17
|
+
*
|
|
18
|
+
* `setMode(null)` clears the persisted preference and falls back to
|
|
19
|
+
* the heuristic; `isAuto` is true while no explicit choice is saved.
|
|
20
|
+
*
|
|
21
|
+
* SSR-safe: returns the resolved fallback until hydration completes,
|
|
22
|
+
* so the server render matches the first client paint.
|
|
23
|
+
*
|
|
24
|
+
* @public
|
|
12
25
|
*/
|
|
13
26
|
export function useEditorMode(prefer = "auto") {
|
|
14
27
|
const [stored, setStored] = useState(null);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useEditorMode.js","sourceRoot":"","sources":["../../src/hooks/useEditorMode.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;AACb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"useEditorMode.js","sourceRoot":"","sources":["../../src/hooks/useEditorMode.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;AACb,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAWzD,MAAM,WAAW,GAAG,wBAAwB,CAAC;AAE7C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,UAAU,aAAa,CAAC,SAA8B,MAAM;IAKhE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAoB,IAAI,CAAC,CAAC;IAC9D,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAU,KAAK,CAAC,CAAC;IAC/D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YACrD,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,KAAK;gBAAE,SAAS,CAAC,GAAG,CAAC,CAAC;QACvD,CAAC;QAAC,MAAM,CAAC;YACP,8DAA8D;QAChE,CAAC;QAED,MAAM,EAAE,GAAG,MAAM,CAAC,UAAU,CAAC,oBAAoB,CAAC,CAAC;QACnD,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC;QAC9C,IAAI,EAAE,CAAC;QACP,EAAE,CAAC,gBAAgB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;QACpC,WAAW,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtD,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,MAAM,OAAO,GAAG,WAAW,CAAC,CAAC,IAAuB,EAAE,EAAE;QACtD,SAAS,CAAC,IAAI,CAAC,CAAC;QAChB,IAAI,CAAC;YACH,IAAI,IAAI,KAAK,IAAI;gBAAE,MAAM,CAAC,YAAY,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;;gBAC1D,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,oEAAoE;IACpE,MAAM,IAAI,GAAe,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC;IACvD,MAAM,QAAQ,GAAe,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;IAC/D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;IAEpD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,EAAE,CAAC;AACpD,CAAC"}
|