@printwithsynergy/artwork-pdf-editor 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (236) hide show
  1. package/LICENSE +62 -0
  2. package/dist/components/AccessibilityHintsPanel.d.ts +142 -0
  3. package/dist/components/AccessibilityHintsPanel.d.ts.map +1 -0
  4. package/dist/components/AccessibilityHintsPanel.js +158 -0
  5. package/dist/components/AccessibilityHintsPanel.js.map +1 -0
  6. package/dist/components/AnnotationOverlay.d.ts +142 -0
  7. package/dist/components/AnnotationOverlay.d.ts.map +1 -0
  8. package/dist/components/AnnotationOverlay.js +141 -0
  9. package/dist/components/AnnotationOverlay.js.map +1 -0
  10. package/dist/components/AnnotationsSidebar.d.ts +98 -0
  11. package/dist/components/AnnotationsSidebar.d.ts.map +1 -0
  12. package/dist/components/AnnotationsSidebar.js +100 -0
  13. package/dist/components/AnnotationsSidebar.js.map +1 -0
  14. package/dist/components/BarcodeGeneratorPanel.d.ts +58 -0
  15. package/dist/components/BarcodeGeneratorPanel.d.ts.map +1 -0
  16. package/dist/components/BarcodeGeneratorPanel.js +91 -0
  17. package/dist/components/BarcodeGeneratorPanel.js.map +1 -0
  18. package/dist/components/BraillePanel.d.ts +99 -0
  19. package/dist/components/BraillePanel.d.ts.map +1 -0
  20. package/dist/components/BraillePanel.js +221 -0
  21. package/dist/components/BraillePanel.js.map +1 -0
  22. package/dist/components/BrandAssetsPanel.d.ts +130 -0
  23. package/dist/components/BrandAssetsPanel.d.ts.map +1 -0
  24. package/dist/components/BrandAssetsPanel.js +125 -0
  25. package/dist/components/BrandAssetsPanel.js.map +1 -0
  26. package/dist/components/BrandConsistencyPanel.d.ts +140 -0
  27. package/dist/components/BrandConsistencyPanel.d.ts.map +1 -0
  28. package/dist/components/BrandConsistencyPanel.js +158 -0
  29. package/dist/components/BrandConsistencyPanel.js.map +1 -0
  30. package/dist/components/ComplianceFindingsPanel.d.ts +62 -0
  31. package/dist/components/ComplianceFindingsPanel.d.ts.map +1 -0
  32. package/dist/components/ComplianceFindingsPanel.js +118 -0
  33. package/dist/components/ComplianceFindingsPanel.js.map +1 -0
  34. package/dist/components/DesignSuggestionsPanel.d.ts +148 -0
  35. package/dist/components/DesignSuggestionsPanel.d.ts.map +1 -0
  36. package/dist/components/DesignSuggestionsPanel.js +154 -0
  37. package/dist/components/DesignSuggestionsPanel.js.map +1 -0
  38. package/dist/components/DielineParametersPanel.d.ts +62 -0
  39. package/dist/components/DielineParametersPanel.d.ts.map +1 -0
  40. package/dist/components/DielineParametersPanel.js +170 -0
  41. package/dist/components/DielineParametersPanel.js.map +1 -0
  42. package/dist/components/DielinePreview.d.ts +150 -0
  43. package/dist/components/DielinePreview.d.ts.map +1 -0
  44. package/dist/components/DielinePreview.js +146 -0
  45. package/dist/components/DielinePreview.js.map +1 -0
  46. package/dist/components/EditorApp.d.ts +18 -3
  47. package/dist/components/EditorApp.d.ts.map +1 -1
  48. package/dist/components/EditorApp.js +42 -7
  49. package/dist/components/EditorApp.js.map +1 -1
  50. package/dist/components/EditorCanvas.d.ts +31 -2
  51. package/dist/components/EditorCanvas.d.ts.map +1 -1
  52. package/dist/components/EditorCanvas.js +97 -16
  53. package/dist/components/EditorCanvas.js.map +1 -1
  54. package/dist/components/EmailNotifyPanel.d.ts +165 -0
  55. package/dist/components/EmailNotifyPanel.d.ts.map +1 -0
  56. package/dist/components/EmailNotifyPanel.js +211 -0
  57. package/dist/components/EmailNotifyPanel.js.map +1 -0
  58. package/dist/components/FileDropZone.d.ts +9 -1
  59. package/dist/components/FileDropZone.d.ts.map +1 -1
  60. package/dist/components/FileDropZone.js +53 -5
  61. package/dist/components/FileDropZone.js.map +1 -1
  62. package/dist/components/FoldEditorPanel.d.ts +68 -0
  63. package/dist/components/FoldEditorPanel.d.ts.map +1 -0
  64. package/dist/components/FoldEditorPanel.js +65 -0
  65. package/dist/components/FoldEditorPanel.js.map +1 -0
  66. package/dist/components/FoldPreviewOverlay.d.ts +48 -0
  67. package/dist/components/FoldPreviewOverlay.d.ts.map +1 -0
  68. package/dist/components/FoldPreviewOverlay.js +182 -0
  69. package/dist/components/FoldPreviewOverlay.js.map +1 -0
  70. package/dist/components/Gs1DigitalLinkPanel.d.ts +103 -0
  71. package/dist/components/Gs1DigitalLinkPanel.d.ts.map +1 -0
  72. package/dist/components/Gs1DigitalLinkPanel.js +199 -0
  73. package/dist/components/Gs1DigitalLinkPanel.js.map +1 -0
  74. package/dist/components/HistoryPanel.d.ts +39 -0
  75. package/dist/components/HistoryPanel.d.ts.map +1 -0
  76. package/dist/components/HistoryPanel.js +72 -0
  77. package/dist/components/HistoryPanel.js.map +1 -0
  78. package/dist/components/IccSoftProofOverlay.d.ts +67 -0
  79. package/dist/components/IccSoftProofOverlay.d.ts.map +1 -0
  80. package/dist/components/IccSoftProofOverlay.js +119 -0
  81. package/dist/components/IccSoftProofOverlay.js.map +1 -0
  82. package/dist/components/ImposePanel.d.ts +71 -0
  83. package/dist/components/ImposePanel.d.ts.map +1 -0
  84. package/dist/components/ImposePanel.js +127 -0
  85. package/dist/components/ImposePanel.js.map +1 -0
  86. package/dist/components/InksPanel.d.ts +61 -0
  87. package/dist/components/InksPanel.d.ts.map +1 -0
  88. package/dist/components/InksPanel.js +84 -0
  89. package/dist/components/InksPanel.js.map +1 -0
  90. package/dist/components/JobSetupPanel.d.ts +118 -0
  91. package/dist/components/JobSetupPanel.d.ts.map +1 -0
  92. package/dist/components/JobSetupPanel.js +169 -0
  93. package/dist/components/JobSetupPanel.js.map +1 -0
  94. package/dist/components/LayersPanel.d.ts.map +1 -1
  95. package/dist/components/LayersPanel.js +1 -0
  96. package/dist/components/LayersPanel.js.map +1 -1
  97. package/dist/components/MarkLibraryPanel.d.ts +131 -0
  98. package/dist/components/MarkLibraryPanel.d.ts.map +1 -0
  99. package/dist/components/MarkLibraryPanel.js +184 -0
  100. package/dist/components/MarkLibraryPanel.js.map +1 -0
  101. package/dist/components/MisEstimateButton.d.ts +73 -0
  102. package/dist/components/MisEstimateButton.d.ts.map +1 -0
  103. package/dist/components/MisEstimateButton.js +57 -0
  104. package/dist/components/MisEstimateButton.js.map +1 -0
  105. package/dist/components/NutritionPanel.d.ts +118 -0
  106. package/dist/components/NutritionPanel.d.ts.map +1 -0
  107. package/dist/components/NutritionPanel.js +169 -0
  108. package/dist/components/NutritionPanel.js.map +1 -0
  109. package/dist/components/PageNavigator.d.ts.map +1 -1
  110. package/dist/components/PageNavigator.js +6 -1
  111. package/dist/components/PageNavigator.js.map +1 -1
  112. package/dist/components/PaletteManager.d.ts +32 -0
  113. package/dist/components/PaletteManager.d.ts.map +1 -0
  114. package/dist/components/PaletteManager.js +89 -0
  115. package/dist/components/PaletteManager.js.map +1 -0
  116. package/dist/components/PaletteToSpotPanel.d.ts +122 -0
  117. package/dist/components/PaletteToSpotPanel.d.ts.map +1 -0
  118. package/dist/components/PaletteToSpotPanel.js +160 -0
  119. package/dist/components/PaletteToSpotPanel.js.map +1 -0
  120. package/dist/components/PreflightAutoFixPanel.d.ts +110 -0
  121. package/dist/components/PreflightAutoFixPanel.d.ts.map +1 -0
  122. package/dist/components/PreflightAutoFixPanel.js +119 -0
  123. package/dist/components/PreflightAutoFixPanel.js.map +1 -0
  124. package/dist/components/PreflightDiffPanel.d.ts +127 -0
  125. package/dist/components/PreflightDiffPanel.d.ts.map +1 -0
  126. package/dist/components/PreflightDiffPanel.js +0 -0
  127. package/dist/components/PreflightDiffPanel.js.map +1 -0
  128. package/dist/components/ProcessRulesPanel.d.ts +81 -0
  129. package/dist/components/ProcessRulesPanel.d.ts.map +1 -0
  130. package/dist/components/ProcessRulesPanel.js +143 -0
  131. package/dist/components/ProcessRulesPanel.js.map +1 -0
  132. package/dist/components/SlackNotifyPanel.d.ts +139 -0
  133. package/dist/components/SlackNotifyPanel.d.ts.map +1 -0
  134. package/dist/components/SlackNotifyPanel.js +133 -0
  135. package/dist/components/SlackNotifyPanel.js.map +1 -0
  136. package/dist/components/SmartSpotMatchPanel.d.ts +143 -0
  137. package/dist/components/SmartSpotMatchPanel.d.ts.map +1 -0
  138. package/dist/components/SmartSpotMatchPanel.js +159 -0
  139. package/dist/components/SmartSpotMatchPanel.js.map +1 -0
  140. package/dist/components/SwatchesPicker.d.ts +83 -0
  141. package/dist/components/SwatchesPicker.d.ts.map +1 -0
  142. package/dist/components/SwatchesPicker.js +151 -0
  143. package/dist/components/SwatchesPicker.js.map +1 -0
  144. package/dist/components/TacOverlay.d.ts +47 -0
  145. package/dist/components/TacOverlay.d.ts.map +1 -0
  146. package/dist/components/TacOverlay.js +116 -0
  147. package/dist/components/TacOverlay.js.map +1 -0
  148. package/dist/components/TrapEditorPanel.d.ts +52 -0
  149. package/dist/components/TrapEditorPanel.d.ts.map +1 -0
  150. package/dist/components/TrapEditorPanel.js +64 -0
  151. package/dist/components/TrapEditorPanel.js.map +1 -0
  152. package/dist/components/TrapPreviewOverlay.d.ts +64 -0
  153. package/dist/components/TrapPreviewOverlay.d.ts.map +1 -0
  154. package/dist/components/TrapPreviewOverlay.js +120 -0
  155. package/dist/components/TrapPreviewOverlay.js.map +1 -0
  156. package/dist/components/VariantMatrixPanel.d.ts +61 -0
  157. package/dist/components/VariantMatrixPanel.d.ts.map +1 -0
  158. package/dist/components/VariantMatrixPanel.js +97 -0
  159. package/dist/components/VariantMatrixPanel.js.map +1 -0
  160. package/dist/components/VariantMatrixVersionPanel.d.ts +122 -0
  161. package/dist/components/VariantMatrixVersionPanel.d.ts.map +1 -0
  162. package/dist/components/VariantMatrixVersionPanel.js +162 -0
  163. package/dist/components/VariantMatrixVersionPanel.js.map +1 -0
  164. package/dist/components/WebhookNotifyPanel.d.ts +160 -0
  165. package/dist/components/WebhookNotifyPanel.d.ts.map +1 -0
  166. package/dist/components/WebhookNotifyPanel.js +100 -0
  167. package/dist/components/WebhookNotifyPanel.js.map +1 -0
  168. package/dist/components/WhiteUnderbasePanel.d.ts +107 -0
  169. package/dist/components/WhiteUnderbasePanel.d.ts.map +1 -0
  170. package/dist/components/WhiteUnderbasePanel.js +104 -0
  171. package/dist/components/WhiteUnderbasePanel.js.map +1 -0
  172. package/dist/hooks/useEditorMode.d.ts +25 -5
  173. package/dist/hooks/useEditorMode.d.ts.map +1 -1
  174. package/dist/hooks/useEditorMode.js +18 -5
  175. package/dist/hooks/useEditorMode.js.map +1 -1
  176. package/dist/index.d.ts +49 -2
  177. package/dist/index.d.ts.map +1 -1
  178. package/dist/index.js +49 -2
  179. package/dist/index.js.map +1 -1
  180. package/dist/lens/preflight-findings.d.ts.map +1 -1
  181. package/dist/lens/preflight-findings.js.map +1 -1
  182. package/dist/lib/barcode-scan.d.ts +154 -0
  183. package/dist/lib/barcode-scan.d.ts.map +1 -0
  184. package/dist/lib/barcode-scan.js +152 -0
  185. package/dist/lib/barcode-scan.js.map +1 -0
  186. package/dist/lib/color-math.d.ts +76 -0
  187. package/dist/lib/color-math.d.ts.map +1 -0
  188. package/dist/lib/color-math.js +96 -0
  189. package/dist/lib/color-math.js.map +1 -0
  190. package/dist/lib/dieline-template.d.ts +87 -0
  191. package/dist/lib/dieline-template.d.ts.map +1 -1
  192. package/dist/lib/dieline-template.js +163 -0
  193. package/dist/lib/dieline-template.js.map +1 -1
  194. package/dist/lib/editor-config.d.ts +384 -0
  195. package/dist/lib/editor-config.d.ts.map +1 -1
  196. package/dist/lib/editor-config.js +89 -0
  197. package/dist/lib/editor-config.js.map +1 -1
  198. package/dist/lib/fold-geometry.d.ts +144 -0
  199. package/dist/lib/fold-geometry.d.ts.map +1 -0
  200. package/dist/lib/fold-geometry.js +138 -0
  201. package/dist/lib/fold-geometry.js.map +1 -0
  202. package/dist/lib/merge-tokens.d.ts +81 -0
  203. package/dist/lib/merge-tokens.d.ts.map +1 -0
  204. package/dist/lib/merge-tokens.js +88 -0
  205. package/dist/lib/merge-tokens.js.map +1 -0
  206. package/dist/lib/palette-registry.d.ts +40 -0
  207. package/dist/lib/palette-registry.d.ts.map +1 -0
  208. package/dist/lib/palette-registry.js +49 -0
  209. package/dist/lib/palette-registry.js.map +1 -0
  210. package/dist/lib/panel-anchor.d.ts +101 -0
  211. package/dist/lib/panel-anchor.d.ts.map +1 -0
  212. package/dist/lib/panel-anchor.js +68 -0
  213. package/dist/lib/panel-anchor.js.map +1 -0
  214. package/dist/lib/preflight/checks.d.ts.map +1 -1
  215. package/dist/lib/preflight/checks.js +71 -0
  216. package/dist/lib/preflight/checks.js.map +1 -1
  217. package/dist/lib/preflight/types.d.ts.map +1 -1
  218. package/dist/lib/preflight/types.js +11 -0
  219. package/dist/lib/preflight/types.js.map +1 -1
  220. package/dist/lib/rasterize.d.ts +93 -0
  221. package/dist/lib/rasterize.d.ts.map +1 -0
  222. package/dist/lib/rasterize.js +117 -0
  223. package/dist/lib/rasterize.js.map +1 -0
  224. package/dist/lib/separations-registry.d.ts +99 -0
  225. package/dist/lib/separations-registry.d.ts.map +1 -0
  226. package/dist/lib/separations-registry.js +59 -0
  227. package/dist/lib/separations-registry.js.map +1 -0
  228. package/dist/lib/unwired.d.ts +29 -0
  229. package/dist/lib/unwired.d.ts.map +1 -0
  230. package/dist/lib/unwired.js +58 -0
  231. package/dist/lib/unwired.js.map +1 -0
  232. package/package.json +20 -11
  233. package/dist/components/SeparationsPanel.d.ts +0 -9
  234. package/dist/components/SeparationsPanel.d.ts.map +0 -1
  235. package/dist/components/SeparationsPanel.js +0 -168
  236. package/dist/components/SeparationsPanel.js.map +0 -1
@@ -0,0 +1,154 @@
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 { useEffect, useMemo, useState } from "react";
5
+ /**
6
+ * Canonical category order — typography is the first thing a human
7
+ * eye lands on; "other" is the escape hatch at the tail.
8
+ *
9
+ * @public
10
+ */
11
+ export const DESIGN_SUGGESTION_CATEGORY_ORDER = [
12
+ "typography",
13
+ "color",
14
+ "contrast",
15
+ "layout",
16
+ "imagery",
17
+ "other",
18
+ ];
19
+ const CATEGORY_LABELS = {
20
+ typography: "Typography",
21
+ color: "Color",
22
+ contrast: "Contrast",
23
+ layout: "Layout",
24
+ imagery: "Imagery",
25
+ other: "Other",
26
+ };
27
+ /**
28
+ * Pure helper — filters suggestions by category / minConfidence.
29
+ * Returns a new array; preserves input order. Pure function.
30
+ *
31
+ * @public
32
+ */
33
+ export function filterDesignSuggestions(suggestions, filter) {
34
+ const min = filter.minConfidence ?? 0;
35
+ return suggestions.filter((s) => {
36
+ if (filter.category && s.category !== filter.category)
37
+ return false;
38
+ if (min > 0) {
39
+ if (typeof s.confidence !== "number" || s.confidence < min)
40
+ return false;
41
+ }
42
+ return true;
43
+ });
44
+ }
45
+ /**
46
+ * Pure helper — groups suggestions by category in
47
+ * {@link DESIGN_SUGGESTION_CATEGORY_ORDER}. Returns a stable
48
+ * six-bucket shape so renderers iterate without absent-key checks.
49
+ * Unknown runtime categories fall into "other" rather than being
50
+ * dropped (defensive against forward-compat catalogue extensions).
51
+ *
52
+ * Pure function.
53
+ *
54
+ * @public
55
+ */
56
+ export function groupDesignSuggestionsByCategory(suggestions) {
57
+ const buckets = new Map(DESIGN_SUGGESTION_CATEGORY_ORDER.map((c) => [c, []]));
58
+ for (const s of suggestions) {
59
+ const bucket = buckets.get(s.category) ?? buckets.get("other");
60
+ bucket?.push(s);
61
+ }
62
+ return DESIGN_SUGGESTION_CATEGORY_ORDER.map((category) => ({
63
+ category,
64
+ suggestions: buckets.get(category) ?? [],
65
+ }));
66
+ }
67
+ /**
68
+ * Stateful panel — loads the suggestion stream on mount, exposes a
69
+ * category filter + min-confidence slider, and emits `onApply` /
70
+ * `onDismiss`. Handles loading / error / empty states inline.
71
+ *
72
+ * @public
73
+ */
74
+ export function DesignSuggestionsPanel({ loader, defaultMinConfidence, onApply, onDismiss, }) {
75
+ const [suggestions, setSuggestions] = useState(null);
76
+ const [error, setError] = useState(null);
77
+ const [loading, setLoading] = useState(true);
78
+ const [category, setCategory] = useState("all");
79
+ const [minConfidence, setMinConfidence] = useState(defaultMinConfidence ?? 0);
80
+ useEffect(() => {
81
+ let disposed = false;
82
+ setLoading(true);
83
+ setError(null);
84
+ setSuggestions(null);
85
+ void (async () => {
86
+ try {
87
+ const next = await loader();
88
+ if (disposed)
89
+ return;
90
+ setSuggestions(next);
91
+ }
92
+ catch (err) {
93
+ if (disposed)
94
+ return;
95
+ setError(err instanceof Error ? err.message : String(err));
96
+ }
97
+ finally {
98
+ if (!disposed)
99
+ setLoading(false);
100
+ }
101
+ })();
102
+ return () => {
103
+ disposed = true;
104
+ };
105
+ }, [loader]);
106
+ const visibleGroups = useMemo(() => {
107
+ if (!suggestions)
108
+ return null;
109
+ const filtered = filterDesignSuggestions(suggestions, {
110
+ ...(category !== "all" && { category }),
111
+ minConfidence,
112
+ });
113
+ return groupDesignSuggestionsByCategory(filtered);
114
+ }, [suggestions, category, minConfidence]);
115
+ if (loading) {
116
+ return (_jsx("div", { "data-testid": "design-suggestions-panel", style: { padding: "0.5rem", opacity: 0.6 }, children: "Loading suggestions\u2026" }));
117
+ }
118
+ if (error) {
119
+ return (_jsxs("div", { "data-testid": "design-suggestions-panel", role: "alert", style: { padding: "0.5rem", color: "#a00" }, children: ["Couldn't load design suggestions: ", error] }));
120
+ }
121
+ if (!visibleGroups)
122
+ return _jsx("div", { "data-testid": "design-suggestions-panel" });
123
+ const totalVisible = visibleGroups.reduce((s, g) => s + g.suggestions.length, 0);
124
+ return (_jsxs("div", { "data-testid": "design-suggestions-panel", style: { padding: "0.5rem" }, children: [_jsxs("header", { style: { marginBottom: "0.5rem" }, children: [_jsxs("h3", { style: { margin: 0, fontSize: "0.875rem" }, children: ["Design suggestions (", totalVisible, ")"] }), _jsxs("div", { style: { display: "flex", gap: "0.5rem", marginTop: "0.25rem", alignItems: "center" }, children: [_jsxs("label", { style: { fontSize: "0.75rem" }, children: ["Category", _jsxs("select", { "aria-label": "Category", value: category, onChange: (e) => setCategory(e.target.value), style: { marginLeft: "0.25rem", fontSize: "0.75rem" }, children: [_jsx("option", { value: "all", children: "All" }), DESIGN_SUGGESTION_CATEGORY_ORDER.map((c) => (_jsx("option", { value: c, children: CATEGORY_LABELS[c] }, c)))] })] }), _jsxs("label", { style: { fontSize: "0.75rem", flex: 1 }, children: ["Min confidence: ", minConfidence.toFixed(2), _jsx("input", { type: "range", "aria-label": "Min confidence", min: 0, max: 1, step: 0.05, value: minConfidence, onChange: (e) => setMinConfidence(Number(e.target.value)), style: { display: "block", width: "100%" } })] })] })] }), totalVisible === 0 && (_jsx("div", { "data-testid": "design-suggestions-panel-empty", style: { opacity: 0.6, fontSize: "0.875rem" }, children: "No suggestions match the current filter." })), visibleGroups.map((group) => {
125
+ if (group.suggestions.length === 0)
126
+ return null;
127
+ return (_jsxs("section", { "data-testid": `design-suggestions-group-${group.category}`, style: { marginBottom: "0.75rem" }, children: [_jsxs("h4", { style: {
128
+ margin: "0 0 0.25rem 0",
129
+ fontSize: "0.75rem",
130
+ color: "#666",
131
+ textTransform: "uppercase",
132
+ letterSpacing: "0.05em",
133
+ }, children: [CATEGORY_LABELS[group.category], " (", group.suggestions.length, ")"] }), _jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: group.suggestions.map((s) => (_jsx(DesignSuggestionRow, { suggestion: s, onApply: onApply, onDismiss: onDismiss }, s.id))) })] }, group.category));
134
+ })] }));
135
+ }
136
+ /**
137
+ * Renders one suggestion row inside a category group. Intra-package
138
+ * helper — the row's surface is intentionally minimal (summary +
139
+ * optional description + optional confidence chip + apply / dismiss
140
+ * buttons) so {@link DesignSuggestionsPanel} can swap it without
141
+ * downstream consumers depending on the shape.
142
+ */
143
+ function DesignSuggestionRow({ suggestion, onApply, onDismiss, }) {
144
+ return (_jsxs("li", { style: {
145
+ display: "flex",
146
+ gap: "0.5rem",
147
+ alignItems: "flex-start",
148
+ padding: "0.375rem 0.5rem",
149
+ border: "1px solid #ddd",
150
+ borderRadius: 4,
151
+ marginBottom: "0.25rem",
152
+ }, children: [_jsxs("div", { style: { flex: 1 }, children: [_jsx("div", { style: { fontSize: "0.8125rem", fontWeight: 500 }, children: suggestion.summary }), suggestion.description && (_jsx("div", { style: { fontSize: "0.75rem", color: "#666", marginTop: "0.125rem" }, children: suggestion.description })), typeof suggestion.confidence === "number" && (_jsxs("div", { style: { fontSize: "0.6875rem", color: "#595959", marginTop: "0.125rem" }, children: ["confidence ", suggestion.confidence.toFixed(2)] }))] }), _jsxs("div", { style: { display: "flex", flexDirection: "column", gap: "0.125rem" }, children: [onApply && (_jsx("button", { type: "button", onClick: () => onApply(suggestion), style: { fontSize: "0.75rem", padding: "0.125rem 0.5rem" }, children: "Apply" })), onDismiss && (_jsx("button", { type: "button", onClick: () => onDismiss(suggestion), style: { fontSize: "0.75rem", padding: "0.125rem 0.5rem" }, children: "Dismiss" }))] })] }));
153
+ }
154
+ //# sourceMappingURL=DesignSuggestionsPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DesignSuggestionsPanel.js","sourceRoot":"","sources":["../../src/components/DesignSuggestionsPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Editable dieline parameters. All values are in **mm**; the
3
+ * conversion to PDF points happens at the regen step. `depthMm` is
4
+ * optional because flat dielines (labels, postcards) don't carry a
5
+ * third dimension.
6
+ *
7
+ * @public
8
+ */
9
+ export type DielineParameters = {
10
+ widthMm: number;
11
+ heightMm: number;
12
+ depthMm?: number;
13
+ bleedMm: number;
14
+ };
15
+ /**
16
+ * @public
17
+ */
18
+ export type DielineParametersPanelProps = {
19
+ /** Current parameters. `undefined` means "no parametric template
20
+ * loaded" — the panel shows a placeholder. */
21
+ value: DielineParameters | undefined;
22
+ /** Fires on every committed change. Hosts debounce externally if
23
+ * the regen step is expensive. */
24
+ onChange: (next: DielineParameters) => void;
25
+ /** Fires when the user *finishes* editing a field (input blur or
26
+ * Enter key). Distinct from `onChange` which fires on every
27
+ * keystroke. Hosts wire this into their undo stack so a 50→500
28
+ * width drag commits as one history entry rather than 451. */
29
+ onCommit?: (next: DielineParameters) => void;
30
+ /** Optional inclusive bounds for the numeric inputs. Defaults are
31
+ * conservative (1 - 2000 mm); hosts that ship a stricter
32
+ * parametric generator pass tighter bounds so the input clamps
33
+ * before reaching the generator. */
34
+ minWidthMm?: number;
35
+ maxWidthMm?: number;
36
+ minHeightMm?: number;
37
+ maxHeightMm?: number;
38
+ minDepthMm?: number;
39
+ maxDepthMm?: number;
40
+ /** When `true`, hides the depth input even if `value.depthMm` is
41
+ * set. Useful for flat-only contexts (labels, postcards). */
42
+ hideDepth?: boolean;
43
+ /** When `true`, hides the live preview thumbnail. Useful for
44
+ * tight UI surfaces or when the host already renders its own
45
+ * preview elsewhere. */
46
+ hidePreview?: boolean;
47
+ };
48
+ /**
49
+ * Compute validation warnings for a set of dieline parameters.
50
+ *
51
+ * Exported so hosts that want to mirror the panel's validation
52
+ * surface (e.g. a sticky banner above the canvas) can call the
53
+ * same check function without re-implementing the rules.
54
+ *
55
+ * @public
56
+ */
57
+ export declare function validateDielineParameters(value: DielineParameters): string[];
58
+ /**
59
+ * @public
60
+ */
61
+ export declare function DielineParametersPanel({ value, onChange, onCommit, minWidthMm, maxWidthMm, minHeightMm, maxHeightMm, minDepthMm, maxDepthMm, hideDepth, hidePreview, }: DielineParametersPanelProps): import("react/jsx-runtime").JSX.Element;
62
+ //# sourceMappingURL=DielineParametersPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DielineParametersPanel.d.ts","sourceRoot":"","sources":["../../src/components/DielineParametersPanel.tsx"],"names":[],"mappings":"AAyBA;;;;;;;GAOG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC;mDAC+C;IAC/C,KAAK,EAAE,iBAAiB,GAAG,SAAS,CAAC;IACrC;uCACmC;IACnC,QAAQ,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC5C;;;mEAG+D;IAC/D,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,iBAAiB,KAAK,IAAI,CAAC;IAC7C;;;yCAGqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;kEAC8D;IAC9D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;6BAEyB;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB,CAAC;AAcF;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE,iBAAiB,GAAG,MAAM,EAAE,CAkB5E;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,UAAU,EACV,WAAW,EACX,WAAW,EACX,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,GACZ,EAAE,2BAA2B,2CAmL7B"}
@@ -0,0 +1,170 @@
1
+ // SPDX-License-Identifier: AGPL-3.0-or-later
2
+ "use client";
3
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
4
+ import { useMemo, useRef } from "react";
5
+ const DEFAULT_MIN_MM = 1;
6
+ const DEFAULT_MAX_MM = 2000;
7
+ const MAX_BLEED_MM = 20;
8
+ /** When bleed exceeds this fraction of the shorter trim dimension,
9
+ * the panel surfaces a warning — at 50% the bleed ring is bigger
10
+ * than the trim and most parametric generators reject it. */
11
+ const BLEED_WARN_FRACTION = 0.5;
12
+ /** SVG preview canvas size in CSS pixels. The dieline scales to
13
+ * fit; the size is fixed so the panel layout stays stable as the
14
+ * user changes dimensions. */
15
+ const PREVIEW_SIZE_PX = 120;
16
+ /**
17
+ * Compute validation warnings for a set of dieline parameters.
18
+ *
19
+ * Exported so hosts that want to mirror the panel's validation
20
+ * surface (e.g. a sticky banner above the canvas) can call the
21
+ * same check function without re-implementing the rules.
22
+ *
23
+ * @public
24
+ */
25
+ export function validateDielineParameters(value) {
26
+ const warnings = [];
27
+ const minTrim = Math.min(value.widthMm, value.heightMm);
28
+ // Both checks guard on `minTrim > 0` so partial mid-edit values
29
+ // (e.g. user clears a field momentarily) don't flash spurious
30
+ // warnings. Once both width and height are populated, the
31
+ // guard releases and validation fires normally.
32
+ if (minTrim > 0 && value.bleedMm > minTrim * BLEED_WARN_FRACTION) {
33
+ warnings.push(`Bleed ${value.bleedMm} mm exceeds ${(BLEED_WARN_FRACTION * 100).toFixed(0)}% of the shorter trim (${minTrim} mm) — most parametric generators will reject this.`);
34
+ }
35
+ if (minTrim > 0 && value.depthMm !== undefined && value.depthMm > minTrim) {
36
+ warnings.push(`Depth ${value.depthMm} mm exceeds the shorter trim ${minTrim} mm — the carton would not close.`);
37
+ }
38
+ return warnings;
39
+ }
40
+ /**
41
+ * @public
42
+ */
43
+ export function DielineParametersPanel({ value, onChange, onCommit, minWidthMm, maxWidthMm, minHeightMm, maxHeightMm, minDepthMm, maxDepthMm, hideDepth, hidePreview, }) {
44
+ const bounds = useMemo(() => ({
45
+ width: {
46
+ min: minWidthMm ?? DEFAULT_MIN_MM,
47
+ max: maxWidthMm ?? DEFAULT_MAX_MM,
48
+ },
49
+ height: {
50
+ min: minHeightMm ?? DEFAULT_MIN_MM,
51
+ max: maxHeightMm ?? DEFAULT_MAX_MM,
52
+ },
53
+ depth: {
54
+ min: minDepthMm ?? DEFAULT_MIN_MM,
55
+ max: maxDepthMm ?? DEFAULT_MAX_MM,
56
+ },
57
+ }), [minWidthMm, maxWidthMm, minHeightMm, maxHeightMm, minDepthMm, maxDepthMm]);
58
+ // `warnings` recomputes only when `value` changes — the validation
59
+ // rules don't depend on bounds so we don't pull them into the dep
60
+ // array. Computing here (not inside the JSX) lets the empty case
61
+ // fast-path the no-warning render.
62
+ const warnings = useMemo(() => (value ? validateDielineParameters(value) : []), [value]);
63
+ // Track the value as of the last commit so blur on an untouched
64
+ // field doesn't push a duplicate history entry to the host.
65
+ // `value` is recreated by `onChange` on every keystroke (via the
66
+ // spread in `set`), so a reference compare is sufficient.
67
+ const lastCommittedRef = useRef(value);
68
+ if (!value) {
69
+ return (_jsx("div", { "data-testid": "dieline-parameters-panel", style: { padding: "0.5rem", opacity: 0.6 }, children: "Load a parametric dieline to edit its dimensions." }));
70
+ }
71
+ const set = (patch) => {
72
+ onChange({ ...value, ...patch });
73
+ };
74
+ const commit = () => {
75
+ // Skip if the value hasn't changed since the last commit —
76
+ // blur on an untouched field shouldn't fire an undo-stack
77
+ // entry. Reference compare is safe because `set` recreates
78
+ // the object on every keystroke.
79
+ if (value === lastCommittedRef.current)
80
+ return;
81
+ lastCommittedRef.current = value;
82
+ onCommit?.(value);
83
+ };
84
+ // Enter inside a numeric input should commit the same way blur
85
+ // does — matches the contract documented on `onCommit` and keeps
86
+ // keyboard-only users from being stuck in a "no commit ever
87
+ // fires" state when they tab through fields with `Enter`.
88
+ const commitOnEnter = (e) => {
89
+ if (e.key === "Enter")
90
+ commit();
91
+ };
92
+ // Parse a numeric input, clamping to [min, max]. Empty / `NaN`
93
+ // returns `null` so callers can decide what to do — width/height/
94
+ // bleed treat that as a no-op (host keeps the last good value
95
+ // while the user is mid-edit), so `Number("")` no longer leaks
96
+ // `NaN` through `onChange`.
97
+ const parseClamped = (raw, min, max) => {
98
+ if (raw === "")
99
+ return null;
100
+ const n = Number(raw);
101
+ if (!Number.isFinite(n))
102
+ return null;
103
+ return Math.min(Math.max(n, min), max);
104
+ };
105
+ return (_jsxs("div", { "data-testid": "dieline-parameters-panel", style: { padding: "0.5rem" }, children: [_jsx("h3", { style: { margin: "0 0 0.5rem 0" }, children: "Dieline parameters" }), _jsxs("div", { style: { display: "grid", gridTemplateColumns: "auto 1fr", gap: "0.25rem 0.5rem" }, children: [_jsx("label", { htmlFor: "dieline-width", children: "Width (mm)" }), _jsx("input", { id: "dieline-width", type: "number", step: "0.1", min: bounds.width.min, max: bounds.width.max, value: value.widthMm, onChange: (e) => {
106
+ const next = parseClamped(e.target.value, bounds.width.min, bounds.width.max);
107
+ if (next !== null)
108
+ set({ widthMm: next });
109
+ }, onBlur: commit, onKeyDown: commitOnEnter, "aria-label": "Width in millimetres" }), _jsx("label", { htmlFor: "dieline-height", children: "Height (mm)" }), _jsx("input", { id: "dieline-height", type: "number", step: "0.1", min: bounds.height.min, max: bounds.height.max, value: value.heightMm, onChange: (e) => {
110
+ const next = parseClamped(e.target.value, bounds.height.min, bounds.height.max);
111
+ if (next !== null)
112
+ set({ heightMm: next });
113
+ }, onBlur: commit, onKeyDown: commitOnEnter, "aria-label": "Height in millimetres" }), !hideDepth && (_jsxs(_Fragment, { children: [_jsx("label", { htmlFor: "dieline-depth", children: "Depth (mm)" }), _jsx("input", { id: "dieline-depth", type: "number", step: "0.1", min: bounds.depth.min, max: bounds.depth.max, value: value.depthMm ?? "", onChange: (e) => {
114
+ const raw = e.target.value;
115
+ if (raw === "") {
116
+ // Empty input clears the depth — surfaces as
117
+ // `undefined` to the host so flat dielines stay flat.
118
+ const { depthMm: _omit, ...rest } = value;
119
+ onChange(rest);
120
+ return;
121
+ }
122
+ const next = parseClamped(raw, bounds.depth.min, bounds.depth.max);
123
+ if (next !== null)
124
+ set({ depthMm: next });
125
+ }, onBlur: commit, onKeyDown: commitOnEnter, "aria-label": "Depth in millimetres", placeholder: "\u2014" })] })), _jsx("label", { htmlFor: "dieline-bleed", children: "Bleed (mm)" }), _jsx("input", { id: "dieline-bleed", type: "number", step: "0.1", min: 0, max: MAX_BLEED_MM, value: value.bleedMm, onChange: (e) => {
126
+ const next = parseClamped(e.target.value, 0, MAX_BLEED_MM);
127
+ if (next !== null)
128
+ set({ bleedMm: next });
129
+ }, onBlur: commit, onKeyDown: commitOnEnter, "aria-label": "Bleed in millimetres" })] }), warnings.length > 0 && (_jsx("ul", { "data-testid": "dieline-parameters-warnings", role: "alert", style: {
130
+ margin: "0.5rem 0 0 0",
131
+ padding: "0.4rem 0.6rem 0.4rem 1.2rem",
132
+ background: "#fff8e1",
133
+ border: "1px solid #f0c419",
134
+ borderRadius: 4,
135
+ color: "#8a6d00",
136
+ fontSize: "0.85rem",
137
+ }, children: warnings.map((w) => (_jsx("li", { children: w }, w))) })), !hidePreview && _jsx(DielineParametersPreview, { value: value, sizePx: PREVIEW_SIZE_PX })] }));
138
+ }
139
+ /**
140
+ * Live preview thumbnail rendered as inline SVG.
141
+ *
142
+ * Shows the trim box (black outline) and the bleed margin (dashed
143
+ * red outline) scaled to fit `sizePx`. When `depthMm` is set, a
144
+ * proportional side panel renders to the right of the trim so users
145
+ * can see the 3D aspect at a glance. SVG (not Konva) keeps the
146
+ * preview lightweight, screenreader-accessible, and renderable in
147
+ * SSR contexts where a Konva Stage would need a browser canvas.
148
+ */
149
+ function DielineParametersPreview({ value, sizePx, }) {
150
+ // Compute scale-to-fit so the longest outer dimension (trim +
151
+ // bleed on both sides, plus the depth flap if present) maps to
152
+ // `sizePx - 8` (leaving an 8px gutter for the preview frame).
153
+ const outerWidth = value.widthMm + 2 * value.bleedMm + (value.depthMm ?? 0);
154
+ const outerHeight = value.heightMm + 2 * value.bleedMm;
155
+ const longestMm = Math.max(outerWidth, outerHeight, 1);
156
+ const scale = (sizePx - 8) / longestMm;
157
+ const trimX = 4 + value.bleedMm * scale;
158
+ const trimY = 4 + value.bleedMm * scale;
159
+ const trimW = value.widthMm * scale;
160
+ const trimH = value.heightMm * scale;
161
+ const bleedX = 4;
162
+ const bleedY = 4;
163
+ const bleedW = (value.widthMm + 2 * value.bleedMm) * scale;
164
+ const bleedH = (value.heightMm + 2 * value.bleedMm) * scale;
165
+ const depthW = (value.depthMm ?? 0) * scale;
166
+ return (_jsx("div", { style: { marginTop: "0.5rem" }, children: _jsxs("svg", { "data-testid": "dieline-parameters-preview", width: sizePx, height: sizePx, viewBox: `0 0 ${sizePx} ${sizePx}`, role: "img", "aria-label": value.depthMm !== undefined
167
+ ? `Dieline preview: ${value.widthMm} × ${value.heightMm} × ${value.depthMm} mm with ${value.bleedMm} mm bleed`
168
+ : `Dieline preview: ${value.widthMm} × ${value.heightMm} mm with ${value.bleedMm} mm bleed`, style: { border: "1px solid #ddd", background: "#fafafa", borderRadius: 4 }, children: [value.bleedMm > 0 && (_jsx("rect", { x: bleedX, y: bleedY, width: bleedW, height: bleedH, fill: "none", stroke: "#d33", strokeDasharray: "2 2", strokeWidth: 1 })), _jsx("rect", { x: trimX, y: trimY, width: trimW, height: trimH, fill: "#fff", stroke: "#222", strokeWidth: 1 }), value.depthMm !== undefined && value.depthMm > 0 && (_jsx("rect", { x: trimX + trimW, y: trimY, width: depthW, height: trimH, fill: "#fff", stroke: "#222", strokeDasharray: "3 2", strokeWidth: 1 }))] }) }));
169
+ }
170
+ //# sourceMappingURL=DielineParametersPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DielineParametersPanel.js","sourceRoot":"","sources":["../../src/components/DielineParametersPanel.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,150 @@
1
+ /**
2
+ * Wave 4 S6 — lightweight dieline preview panel.
3
+ *
4
+ * Renders a small 2D thumbnail of the active page's dieline: every
5
+ * panel from `panelMetadata` is drawn as a rect (bbox-derived), and
6
+ * every fold edge from `foldConfig` is overlaid as a colored segment
7
+ * (mountain = blue, valley = red).
8
+ *
9
+ * Distinct from {@link FoldPreviewOverlay}, which spins up a Three.js
10
+ * WebGL scene for full 3D viewing. S6 is the cheap always-on chrome
11
+ * companion: SVG-only, no GPU, SSR-safe, ~zero bundle cost. Hosts
12
+ * typically dock it in the right rail next to {@link DielineParametersPanel}
13
+ * so a parametric edit + this preview update side-by-side.
14
+ *
15
+ * The component is fully controlled and props-driven — no internal
16
+ * state, no fold-angle math, no hover side effects. The host owns
17
+ * `activePanelId`; the preview just renders it. This keeps the panel
18
+ * useful in both Wave 4 contexts (host-driven hover affordance) and
19
+ * Wave 5+ contexts (host-driven panel-anchored object selection).
20
+ *
21
+ * @public
22
+ */
23
+ import type { ReactElement } from "react";
24
+ /**
25
+ * One panel of the dieline registry, structurally compatible with
26
+ * `@artworkpdf/document-model`'s `DielinePanel` and editor-side
27
+ * {@link FoldGeometryPanel}. The fields below are the subset we need
28
+ * for the 2D preview — `pathData` is intentionally omitted; the
29
+ * preview uses the axis-aligned `bbox` for speed and SSR-safety.
30
+ *
31
+ * @public
32
+ */
33
+ export type DielinePreviewPanel = {
34
+ id: string;
35
+ name?: string;
36
+ bbox: {
37
+ x: number;
38
+ y: number;
39
+ width: number;
40
+ height: number;
41
+ };
42
+ role?: string;
43
+ };
44
+ /**
45
+ * Panel registry input — structurally compatible with `PanelMetadata`
46
+ * on `@artworkpdf/document-model`'s `PageV3`.
47
+ *
48
+ * @public
49
+ */
50
+ export type DielinePreviewPanelMetadata = {
51
+ panels: DielinePreviewPanel[];
52
+ };
53
+ /**
54
+ * One fold edge between two panels (Wave 2 S4 wire shape).
55
+ * Structurally compatible with `@artworkpdf/document-model`'s
56
+ * `FoldEdge`.
57
+ *
58
+ * @public
59
+ */
60
+ export type DielinePreviewFoldEdge = {
61
+ id: string;
62
+ panelA: string;
63
+ panelB: string;
64
+ angleDeg: number;
65
+ direction?: "mountain" | "valley";
66
+ };
67
+ /**
68
+ * Fold-edge registry input — structurally compatible with `FoldConfig`
69
+ * on `@artworkpdf/document-model`'s `PageV3`.
70
+ *
71
+ * @public
72
+ */
73
+ export type DielinePreviewFoldConfig = {
74
+ edges: DielinePreviewFoldEdge[];
75
+ defaultAngleDeg?: number;
76
+ };
77
+ /**
78
+ * @public
79
+ */
80
+ export type DielinePreviewProps = {
81
+ /** Panel registry for the active page. `undefined` renders the
82
+ * "no dieline loaded" empty state. */
83
+ panelMetadata: DielinePreviewPanelMetadata | undefined;
84
+ /** Fold-edge registry for the active page. `undefined` is fine —
85
+ * panels render alone, no hinge lines appear. */
86
+ foldConfig?: DielinePreviewFoldConfig;
87
+ /** Optional template id surfaced in the panel header. Hosts that
88
+ * carry `PageV3.dielineTemplateId` pass it here as a label hint. */
89
+ templateId?: string;
90
+ /** Preview viewport size in CSS pixels (square). Defaults to 160. */
91
+ sizePx?: number;
92
+ /** Id of a panel to render in the "active" style (host-controlled
93
+ * hover / selection affordance). Absent → no highlight. */
94
+ activePanelId?: string;
95
+ };
96
+ /**
97
+ * Internal layout shape produced by {@link computeDielinePreviewLayout}.
98
+ *
99
+ * Exposed only via the helper's return type so tests can assert
100
+ * geometry without driving the SVG renderer.
101
+ */
102
+ export type DielinePreviewLayout = {
103
+ panels: DielinePreviewLaidOutPanel[];
104
+ hinges: DielinePreviewLaidOutHinge[];
105
+ scale: number;
106
+ };
107
+ /**
108
+ * One panel projected into the preview viewport.
109
+ *
110
+ * @public
111
+ */
112
+ export type DielinePreviewLaidOutPanel = {
113
+ id: string;
114
+ name?: string;
115
+ role?: string;
116
+ x: number;
117
+ y: number;
118
+ width: number;
119
+ height: number;
120
+ };
121
+ /**
122
+ * One hinge segment projected into the preview viewport.
123
+ *
124
+ * @public
125
+ */
126
+ export type DielinePreviewLaidOutHinge = {
127
+ id: string;
128
+ x1: number;
129
+ y1: number;
130
+ x2: number;
131
+ y2: number;
132
+ direction: "mountain" | "valley";
133
+ };
134
+ /**
135
+ * Pure geometry helper — projects the panel registry + fold config
136
+ * into the preview viewport at `sizePx` square. Exposed for tests
137
+ * and for hosts that want to drive their own SVG / canvas renderer
138
+ * over the same numbers.
139
+ *
140
+ * Returns an empty layout when `panels` is empty; collapses to a
141
+ * unit scale when every panel has zero extent (mid-edit guard).
142
+ *
143
+ * @public
144
+ */
145
+ export declare function computeDielinePreviewLayout(panelMetadata: DielinePreviewPanelMetadata, foldConfig: DielinePreviewFoldConfig | undefined, sizePx: number): DielinePreviewLayout;
146
+ /**
147
+ * @public
148
+ */
149
+ export declare function DielinePreview({ panelMetadata, foldConfig, templateId, sizePx, activePanelId, }: DielinePreviewProps): ReactElement;
150
+ //# sourceMappingURL=DielinePreview.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DielinePreview.d.ts","sourceRoot":"","sources":["../../src/components/DielinePreview.tsx"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAE1C;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE;QAAE,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,2BAA2B,GAAG;IACxC,MAAM,EAAE,mBAAmB,EAAE,CAAC;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,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;;;;;GAKG;AACH,MAAM,MAAM,wBAAwB,GAAG;IACrC,KAAK,EAAE,sBAAsB,EAAE,CAAC;IAChC,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;2CACuC;IACvC,aAAa,EAAE,2BAA2B,GAAG,SAAS,CAAC;IACvD;sDACkD;IAClD,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC;yEACqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qEAAqE;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;gEAC4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAgBF;;;;;GAKG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,0BAA0B,EAAE,CAAC;IACrC,MAAM,EAAE,0BAA0B,EAAE,CAAC;IACrC,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;IACV,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,0BAA0B,GAAG;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,UAAU,GAAG,QAAQ,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,2BAA2B,CACzC,aAAa,EAAE,2BAA2B,EAC1C,UAAU,EAAE,wBAAwB,GAAG,SAAS,EAChD,MAAM,EAAE,MAAM,GACb,oBAAoB,CAuDtB;AA4CD;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,aAAa,EACb,UAAU,EACV,UAAU,EACV,MAAwB,EACxB,aAAa,GACd,EAAE,mBAAmB,GAAG,YAAY,CAwFpC"}