@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,184 @@
|
|
|
1
|
+
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
2
|
+
"use client";
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
4
|
+
import { useEffect, useMemo, useState } from "react";
|
|
5
|
+
/**
|
|
6
|
+
* Canonical order mark categories render in. Crop is the
|
|
7
|
+
* highest-priority press concern; "other" is the escape hatch at
|
|
8
|
+
* the end.
|
|
9
|
+
*
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export const MARK_CATEGORY_ORDER = [
|
|
13
|
+
"crop",
|
|
14
|
+
"registration",
|
|
15
|
+
"color-bar",
|
|
16
|
+
"slug",
|
|
17
|
+
"other",
|
|
18
|
+
];
|
|
19
|
+
const CATEGORY_LABELS = {
|
|
20
|
+
crop: "Crop marks",
|
|
21
|
+
registration: "Registration",
|
|
22
|
+
"color-bar": "Color bars",
|
|
23
|
+
slug: "Slug info",
|
|
24
|
+
other: "Other",
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Group marks by category in {@link MARK_CATEGORY_ORDER}. Returns a
|
|
28
|
+
* stable five-bucket shape so renderers iterate without absent-key
|
|
29
|
+
* checks. Unknown runtime categories fall into "other" rather than
|
|
30
|
+
* being dropped (defensive against forward-compat catalogue
|
|
31
|
+
* extensions).
|
|
32
|
+
*
|
|
33
|
+
* Pure function.
|
|
34
|
+
*
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
export function groupMarksByCategory(marks) {
|
|
38
|
+
const buckets = new Map(MARK_CATEGORY_ORDER.map((c) => [c, []]));
|
|
39
|
+
for (const m of marks) {
|
|
40
|
+
const bucket = buckets.get(m.category) ?? buckets.get("other");
|
|
41
|
+
bucket?.push(m);
|
|
42
|
+
}
|
|
43
|
+
return MARK_CATEGORY_ORDER.map((category) => ({
|
|
44
|
+
category,
|
|
45
|
+
marks: buckets.get(category) ?? [],
|
|
46
|
+
}));
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Filter marks by category / name substring. Returns a new array;
|
|
50
|
+
* preserves input order. Pure function.
|
|
51
|
+
*
|
|
52
|
+
* @public
|
|
53
|
+
*/
|
|
54
|
+
export function filterMarks(marks, filter) {
|
|
55
|
+
const trimmedQuery = filter.query?.trim().toLowerCase() ?? "";
|
|
56
|
+
return marks.filter((m) => {
|
|
57
|
+
if (filter.category && m.category !== filter.category)
|
|
58
|
+
return false;
|
|
59
|
+
if (trimmedQuery && !m.name.toLowerCase().includes(trimmedQuery))
|
|
60
|
+
return false;
|
|
61
|
+
return true;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Stateful picker that loads the host-supplied catalogue, exposes a
|
|
66
|
+
* live name search, and emits the selected entry. Handles loading /
|
|
67
|
+
* error / empty states inline (matches `ComplianceFindingsPanel`'s
|
|
68
|
+
* adapter pattern).
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export function MarkLibraryPanel({ loader, filterCategory, activeMarkId, onSelect, }) {
|
|
73
|
+
const [marks, setMarks] = useState(null);
|
|
74
|
+
const [error, setError] = useState(null);
|
|
75
|
+
const [loading, setLoading] = useState(false);
|
|
76
|
+
const [query, setQuery] = useState("");
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
let disposed = false;
|
|
79
|
+
setLoading(true);
|
|
80
|
+
setError(null);
|
|
81
|
+
setMarks(null);
|
|
82
|
+
void (async () => {
|
|
83
|
+
try {
|
|
84
|
+
const next = await loader();
|
|
85
|
+
if (disposed)
|
|
86
|
+
return;
|
|
87
|
+
setMarks(next);
|
|
88
|
+
}
|
|
89
|
+
catch (err) {
|
|
90
|
+
if (disposed)
|
|
91
|
+
return;
|
|
92
|
+
setError(err instanceof Error ? err.message : String(err));
|
|
93
|
+
}
|
|
94
|
+
finally {
|
|
95
|
+
if (!disposed)
|
|
96
|
+
setLoading(false);
|
|
97
|
+
}
|
|
98
|
+
})();
|
|
99
|
+
return () => {
|
|
100
|
+
disposed = true;
|
|
101
|
+
};
|
|
102
|
+
}, [loader]);
|
|
103
|
+
const visibleGroups = useMemo(() => {
|
|
104
|
+
if (!marks)
|
|
105
|
+
return null;
|
|
106
|
+
const filtered = filterMarks(marks, {
|
|
107
|
+
...(filterCategory && { category: filterCategory }),
|
|
108
|
+
query,
|
|
109
|
+
});
|
|
110
|
+
return groupMarksByCategory(filtered);
|
|
111
|
+
}, [marks, filterCategory, query]);
|
|
112
|
+
if (loading) {
|
|
113
|
+
return (_jsx("div", { "data-testid": "mark-library-panel", style: { padding: "0.5rem", opacity: 0.6 }, children: "Loading mark library\u2026" }));
|
|
114
|
+
}
|
|
115
|
+
if (error) {
|
|
116
|
+
return (_jsxs("div", { "data-testid": "mark-library-panel", role: "alert", style: { padding: "0.5rem", color: "#a00" }, children: ["Couldn't load mark library: ", error] }));
|
|
117
|
+
}
|
|
118
|
+
if (!visibleGroups)
|
|
119
|
+
return _jsx("div", { "data-testid": "mark-library-panel" });
|
|
120
|
+
const totalVisible = visibleGroups.reduce((s, g) => s + g.marks.length, 0);
|
|
121
|
+
return (_jsxs("div", { "data-testid": "mark-library-panel", style: { padding: "0.5rem" }, children: [_jsxs("header", { style: { display: "flex", gap: "0.5rem", marginBottom: "0.5rem" }, children: [_jsxs("h3", { style: { margin: 0, fontSize: "0.875rem", flex: 1 }, children: ["Marks (", totalVisible, ")"] }), _jsx("input", { type: "search", placeholder: "Search marks", value: query, onChange: (e) => setQuery(e.target.value), "aria-label": "Search marks", style: { fontSize: "0.75rem", padding: "0.125rem 0.25rem" } })] }), totalVisible === 0 && (_jsx("div", { "data-testid": "mark-library-panel-empty", style: { opacity: 0.6, fontSize: "0.875rem" }, children: "No marks match the current filter." })), visibleGroups.map((group) => {
|
|
122
|
+
if (group.marks.length === 0)
|
|
123
|
+
return null;
|
|
124
|
+
return (_jsxs("section", { "data-testid": `mark-library-group-${group.category}`, style: { marginBottom: "0.75rem" }, children: [_jsxs("h4", { style: {
|
|
125
|
+
margin: "0 0 0.25rem 0",
|
|
126
|
+
fontSize: "0.75rem",
|
|
127
|
+
color: "#666",
|
|
128
|
+
textTransform: "uppercase",
|
|
129
|
+
letterSpacing: "0.05em",
|
|
130
|
+
}, children: [CATEGORY_LABELS[group.category], " (", group.marks.length, ")"] }), _jsx("ul", { style: { listStyle: "none", padding: 0, margin: 0 }, children: group.marks.map((mark) => (_jsx(MarkLibraryRow, { mark: mark, isActive: mark.id === activeMarkId, onSelect: onSelect }, mark.id))) })] }, group.category));
|
|
131
|
+
})] }));
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Renders one mark row. Switches between a `<button>` (when
|
|
135
|
+
* `onSelect` is wired) and a static `<div>` so screen readers don't
|
|
136
|
+
* announce a non-functional control. The thumbnail, when present, is
|
|
137
|
+
* `aria-hidden` because the row's `aria-label` already names the
|
|
138
|
+
* mark.
|
|
139
|
+
*
|
|
140
|
+
* Intra-package helper.
|
|
141
|
+
*/
|
|
142
|
+
function MarkLibraryRow({ mark, isActive, onSelect, }) {
|
|
143
|
+
const rowStyle = {
|
|
144
|
+
display: "flex",
|
|
145
|
+
alignItems: "center",
|
|
146
|
+
gap: "0.5rem",
|
|
147
|
+
width: "100%",
|
|
148
|
+
padding: "0.25rem 0.5rem",
|
|
149
|
+
background: isActive ? "#e0ecff" : "transparent",
|
|
150
|
+
border: isActive ? "1px solid #2563eb" : "1px solid transparent",
|
|
151
|
+
borderRadius: 4,
|
|
152
|
+
};
|
|
153
|
+
const contents = (_jsxs(_Fragment, { children: [mark.thumbnailDataUrl && (_jsx("img", { src: mark.thumbnailDataUrl, alt: "", "aria-hidden": "true", style: {
|
|
154
|
+
width: 24,
|
|
155
|
+
height: 24,
|
|
156
|
+
objectFit: "contain",
|
|
157
|
+
background: "#fff",
|
|
158
|
+
border: "1px solid #ddd",
|
|
159
|
+
borderRadius: 2,
|
|
160
|
+
flexShrink: 0,
|
|
161
|
+
} })), _jsx("span", { style: { flex: 1, fontSize: "0.8125rem" }, children: mark.name })] }));
|
|
162
|
+
// Visually-hidden description, referenced by `aria-describedby` so
|
|
163
|
+
// screen readers announce the mark's name first and the longer
|
|
164
|
+
// description as a separate supporting detail (rather than fused
|
|
165
|
+
// into a single mash-up label). Hosts that disable verbose
|
|
166
|
+
// announcements then still get a short button name.
|
|
167
|
+
const describedById = mark.description ? `mark-${mark.id}-description` : undefined;
|
|
168
|
+
return (_jsx("li", { children: onSelect ? (_jsxs("button", { type: "button", onClick: () => onSelect(mark), "aria-label": mark.name, "aria-describedby": describedById, title: mark.description, style: {
|
|
169
|
+
...rowStyle,
|
|
170
|
+
cursor: "pointer",
|
|
171
|
+
textAlign: "left",
|
|
172
|
+
}, children: [contents, mark.description && (_jsx("span", { id: describedById, style: {
|
|
173
|
+
position: "absolute",
|
|
174
|
+
width: 1,
|
|
175
|
+
height: 1,
|
|
176
|
+
padding: 0,
|
|
177
|
+
margin: -1,
|
|
178
|
+
overflow: "hidden",
|
|
179
|
+
clip: "rect(0 0 0 0)",
|
|
180
|
+
whiteSpace: "nowrap",
|
|
181
|
+
border: 0,
|
|
182
|
+
}, children: mark.description }))] })) : (_jsx("div", { style: rowStyle, title: mark.description, children: contents })) }));
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=MarkLibraryPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MarkLibraryPanel.js","sourceRoot":"","sources":["../../src/components/MarkLibraryPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { PrintProcess } from "./JobSetupPanel";
|
|
2
|
+
/**
|
|
3
|
+
* Manifest payload — the shape the synergy `mis.estimate` node
|
|
4
|
+
* consumes. All fields except `documentId` and `processClass` are
|
|
5
|
+
* optional so partial submissions still validate (hosts that don't
|
|
6
|
+
* yet collect a due date can omit it).
|
|
7
|
+
*
|
|
8
|
+
* @public
|
|
9
|
+
*/
|
|
10
|
+
export type MisEstimateManifest = {
|
|
11
|
+
/** Stable identifier the host uses to correlate this submission
|
|
12
|
+
* with the underlying document (e.g. a CMS row id). */
|
|
13
|
+
documentId: string;
|
|
14
|
+
/** Matches `PrintContext.process` from the document-model (re-using
|
|
15
|
+
* `JobSetupPanel`'s `PrintProcess` to keep the two in lockstep) so
|
|
16
|
+
* the MIS can route to the right press cell. */
|
|
17
|
+
processClass: PrintProcess;
|
|
18
|
+
/** Ordered ink list at submission time — typically the live ink
|
|
19
|
+
* list from PR-5's InksPanel. Names mirror the wire shape, not
|
|
20
|
+
* the human display string. */
|
|
21
|
+
separations?: ReadonlyArray<{
|
|
22
|
+
name: string;
|
|
23
|
+
colorSpace: "Separation" | "DeviceN";
|
|
24
|
+
}>;
|
|
25
|
+
/** Substrate / coverage hints the MIS uses to estimate
|
|
26
|
+
* consumables. Free shape — different MIS vendors collect
|
|
27
|
+
* different fields. */
|
|
28
|
+
materialEstimate?: Record<string, unknown>;
|
|
29
|
+
/** ISO 8601 (date-only) string. Hosts that surface a date picker
|
|
30
|
+
* pass `value.toISOString().slice(0, 10)`. */
|
|
31
|
+
dueDate?: string;
|
|
32
|
+
/** Tenant-specific extras (`po_number`, `cost_center`, …). The
|
|
33
|
+
* synergy node copies the bag verbatim into the workflow
|
|
34
|
+
* payload. */
|
|
35
|
+
extras?: Record<string, unknown>;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Host adapter — POSTs the manifest to the synergy queue (or
|
|
39
|
+
* whatever MIS bridge the host runs). Resolves with the workflow
|
|
40
|
+
* id the synergy node assigned; rejects on transport / validation
|
|
41
|
+
* errors and the button surfaces the message inline.
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export type MisSubmitFn = (manifest: MisEstimateManifest) => Promise<{
|
|
46
|
+
workflowId: string;
|
|
47
|
+
}>;
|
|
48
|
+
/**
|
|
49
|
+
* @public
|
|
50
|
+
*/
|
|
51
|
+
export type MisEstimateButtonProps = {
|
|
52
|
+
/** The current manifest. When `undefined` the button is disabled
|
|
53
|
+
* — hosts wire this to "we have enough data to submit". */
|
|
54
|
+
manifest: MisEstimateManifest | undefined;
|
|
55
|
+
/** Host adapter, see {@link MisSubmitFn}. */
|
|
56
|
+
submit: MisSubmitFn;
|
|
57
|
+
/** Optional button label override. Defaults to "Send to MIS". */
|
|
58
|
+
label?: string;
|
|
59
|
+
/** Optional callback fired on successful submission with the
|
|
60
|
+
* workflow id so the host can show a confirmation / link. */
|
|
61
|
+
onSuccess?: (workflowId: string) => void;
|
|
62
|
+
/** Optional mapper that turns a submit error into a user-facing
|
|
63
|
+
* message. The default (`"Couldn't send to MIS."`) avoids leaking
|
|
64
|
+
* internal `Error.message` strings; hosts that want richer
|
|
65
|
+
* surfaces (e.g. validation-error toasts) pass their own mapper.
|
|
66
|
+
* The original error is still passed in so hosts can log it. */
|
|
67
|
+
errorMessage?: (err: unknown) => string;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
export declare function MisEstimateButton({ manifest, submit, label, onSuccess, errorMessage, }: MisEstimateButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
73
|
+
//# sourceMappingURL=MisEstimateButton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MisEstimateButton.d.ts","sourceRoot":"","sources":["../../src/components/MisEstimateButton.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD;;;;;;;GAOG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;4DACwD;IACxD,UAAU,EAAE,MAAM,CAAC;IACnB;;qDAEiD;IACjD,YAAY,EAAE,YAAY,CAAC;IAC3B;;oCAEgC;IAChC,WAAW,CAAC,EAAE,aAAa,CAAC;QAC1B,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,YAAY,GAAG,SAAS,CAAC;KACtC,CAAC,CAAC;IACH;;4BAEwB;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3C;mDAC+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;mBAEe;IACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,mBAAmB,KAAK,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE7F;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC;gEAC4D;IAC5D,QAAQ,EAAE,mBAAmB,GAAG,SAAS,CAAC;IAC1C,6CAA6C;IAC7C,MAAM,EAAE,WAAW,CAAC;IACpB,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;kEAC8D;IAC9D,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;;;qEAIiE;IACjE,YAAY,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,MAAM,CAAC;CACzC,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,YAAY,GACb,EAAE,sBAAsB,2CAgExB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Wave 2 O2 — Send-to-MIS manifest emitter.
|
|
6
|
+
*
|
|
7
|
+
* A small button that gathers the current document's print-relevant
|
|
8
|
+
* metadata (separations, material estimate, process class, due date)
|
|
9
|
+
* into a structured manifest and hands it to a host-supplied
|
|
10
|
+
* submitter. The host wires the submitter to the synergy queue's
|
|
11
|
+
* `mis.estimate` node (`POST /synergy/workflows/<id>/submit` in the
|
|
12
|
+
* canonical deploy); the editor stays runtime-free of the synergy
|
|
13
|
+
* client.
|
|
14
|
+
*
|
|
15
|
+
* Designed around the host-adapter pattern that the rest of the
|
|
16
|
+
* editor uses (see `SpotSearchFn`, `TrapPreviewFn`, `InksLoaderFn`).
|
|
17
|
+
*
|
|
18
|
+
* @public
|
|
19
|
+
*/
|
|
20
|
+
import { useEffect, useRef, useState } from "react";
|
|
21
|
+
/**
|
|
22
|
+
* @public
|
|
23
|
+
*/
|
|
24
|
+
export function MisEstimateButton({ manifest, submit, label, onSuccess, errorMessage, }) {
|
|
25
|
+
const [state, setState] = useState({ kind: "idle" });
|
|
26
|
+
// Clear any lingering success/error chip when the host swaps in a
|
|
27
|
+
// new manifest — the previous submission's outcome doesn't apply to
|
|
28
|
+
// a different payload. Identity comparison only; hosts that mutate
|
|
29
|
+
// the same object reference get the chip preserved (rare; almost
|
|
30
|
+
// every host returns a new object on each edit).
|
|
31
|
+
const lastManifestRef = useRef(manifest);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (lastManifestRef.current !== manifest) {
|
|
34
|
+
lastManifestRef.current = manifest;
|
|
35
|
+
setState((prev) => (prev.kind === "submitting" ? prev : { kind: "idle" }));
|
|
36
|
+
}
|
|
37
|
+
}, [manifest]);
|
|
38
|
+
const disabled = !manifest || state.kind === "submitting";
|
|
39
|
+
const onClick = async () => {
|
|
40
|
+
if (!manifest)
|
|
41
|
+
return;
|
|
42
|
+
setState({ kind: "submitting" });
|
|
43
|
+
try {
|
|
44
|
+
const { workflowId } = await submit(manifest);
|
|
45
|
+
setState({ kind: "ok", workflowId });
|
|
46
|
+
onSuccess?.(workflowId);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
setState({
|
|
50
|
+
kind: "error",
|
|
51
|
+
message: errorMessage ? errorMessage(err) : "Couldn't send to MIS.",
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
return (_jsxs("div", { "data-testid": "mis-estimate-button", style: { display: "inline-flex", gap: "0.5rem", alignItems: "center" }, children: [_jsx("button", { type: "button", onClick: onClick, disabled: disabled, "aria-busy": state.kind === "submitting", "aria-label": label ?? "Send to MIS", children: state.kind === "submitting" ? "Sending…" : (label ?? "Send to MIS") }), state.kind === "ok" && (_jsxs("small", { style: { color: "#080", opacity: 0.8 }, role: "status", children: ["Submitted (", state.workflowId, ")"] })), state.kind === "error" && (_jsx("small", { style: { color: "#a00", opacity: 0.8 }, role: "alert", children: state.message }))] }));
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=MisEstimateButton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MisEstimateButton.js","sourceRoot":"","sources":["../../src/components/MisEstimateButton.tsx"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,YAAY,CAAC;;AAEb;;;;;;;;;;;;;;;GAeG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAuEpD;;GAEG;AACH,MAAM,UAAU,iBAAiB,CAAC,EAChC,QAAQ,EACR,MAAM,EACN,KAAK,EACL,SAAS,EACT,YAAY,GACW;IACvB,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAKhC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAEpB,kEAAkE;IAClE,oEAAoE;IACpE,mEAAmE;IACnE,iEAAiE;IACjE,iDAAiD;IACjD,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzC,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,eAAe,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;YACzC,eAAe,CAAC,OAAO,GAAG,QAAQ,CAAC;YACnC,QAAQ,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,MAAM,QAAQ,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC;IAE1D,MAAM,OAAO,GAAG,KAAK,IAAI,EAAE;QACzB,IAAI,CAAC,QAAQ;YAAE,OAAO;QACtB,QAAQ,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC,CAAC;QACjC,IAAI,CAAC;YACH,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC9C,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;YACrC,SAAS,EAAE,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,QAAQ,CAAC;gBACP,IAAI,EAAE,OAAO;gBACb,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,uBAAuB;aACpE,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,OAAO,CACL,8BACc,qBAAqB,EACjC,KAAK,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,aAEtE,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,QAAQ,eACP,KAAK,CAAC,IAAI,KAAK,YAAY,gBAC1B,KAAK,IAAI,aAAa,YAEjC,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,KAAK,IAAI,aAAa,CAAC,GAC7D,EACR,KAAK,CAAC,IAAI,KAAK,IAAI,IAAI,CACtB,iBAAO,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,EAAC,QAAQ,4BAC9C,KAAK,CAAC,UAAU,SACtB,CACT,EACA,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,CACzB,gBAAO,KAAK,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,IAAI,EAAC,OAAO,YACxD,KAAK,CAAC,OAAO,GACR,CACT,IACG,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typed Nutrition Facts data. All fields are per serving except
|
|
3
|
+
* `servingSize` (human-readable, e.g. `"2/3 cup (55g)"`) and
|
|
4
|
+
* `servingsPerContainer`. Numeric fields are in the units the FDA
|
|
5
|
+
* panel declares (grams for macronutrients, milligrams for sodium /
|
|
6
|
+
* cholesterol, micrograms for vitamin D).
|
|
7
|
+
*
|
|
8
|
+
* Optional fields are omitted from the rendered output entirely
|
|
9
|
+
* (different from `0`, which renders as "0g" / "0%").
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export type NutritionFacts = {
|
|
14
|
+
servingSize: string;
|
|
15
|
+
servingsPerContainer: number;
|
|
16
|
+
calories: number;
|
|
17
|
+
totalFatG: number;
|
|
18
|
+
saturatedFatG: number;
|
|
19
|
+
transFatG: number;
|
|
20
|
+
cholesterolMg: number;
|
|
21
|
+
sodiumMg: number;
|
|
22
|
+
totalCarbohydrateG: number;
|
|
23
|
+
dietaryFiberG: number;
|
|
24
|
+
totalSugarsG: number;
|
|
25
|
+
addedSugarsG?: number;
|
|
26
|
+
proteinG: number;
|
|
27
|
+
vitaminDMcg?: number;
|
|
28
|
+
calciumMg?: number;
|
|
29
|
+
ironMg?: number;
|
|
30
|
+
potassiumMg?: number;
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* 2016 FDA Daily Reference Values (DRV) and Reference Daily Intakes
|
|
34
|
+
* (RDI) used to compute the % Daily Value column. Public-domain
|
|
35
|
+
* regulatory data — re-exported so server renderers can use the
|
|
36
|
+
* same constants and stay in sync.
|
|
37
|
+
*
|
|
38
|
+
* @public
|
|
39
|
+
*/
|
|
40
|
+
export declare const FDA_DAILY_VALUES: {
|
|
41
|
+
readonly totalFatG: 78;
|
|
42
|
+
readonly saturatedFatG: 20;
|
|
43
|
+
readonly cholesterolMg: 300;
|
|
44
|
+
readonly sodiumMg: 2300;
|
|
45
|
+
readonly totalCarbohydrateG: 275;
|
|
46
|
+
readonly dietaryFiberG: 28;
|
|
47
|
+
readonly addedSugarsG: 50;
|
|
48
|
+
readonly vitaminDMcg: 20;
|
|
49
|
+
readonly calciumMg: 1300;
|
|
50
|
+
readonly ironMg: 18;
|
|
51
|
+
readonly potassiumMg: 4700;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* One row in the composed nutrition panel spec. `indent` ≥ 1 means
|
|
55
|
+
* the row is a sub-nutrient (e.g. saturated fat under total fat) —
|
|
56
|
+
* hosts typically render indented and not bold. `bold` matches the
|
|
57
|
+
* FDA layout: panel header, "Calories", and section-leading nutrient
|
|
58
|
+
* names are bold.
|
|
59
|
+
*
|
|
60
|
+
* @public
|
|
61
|
+
*/
|
|
62
|
+
export type NutritionRow = {
|
|
63
|
+
label: string;
|
|
64
|
+
amount: string;
|
|
65
|
+
dvPct?: number;
|
|
66
|
+
indent: 0 | 1;
|
|
67
|
+
bold: boolean;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Output of {@link composeNutritionFacts}. `rows` is the ordered
|
|
71
|
+
* list the host renders top-to-bottom; `caloriesLine` is surfaced
|
|
72
|
+
* separately because the FDA layout sets calories at ~22 pt while
|
|
73
|
+
* everything else is at body-text size.
|
|
74
|
+
*
|
|
75
|
+
* @public
|
|
76
|
+
*/
|
|
77
|
+
export type NutritionPanelSpec = {
|
|
78
|
+
servingSize: string;
|
|
79
|
+
servingsLine: string;
|
|
80
|
+
caloriesLine: string;
|
|
81
|
+
rows: NutritionRow[];
|
|
82
|
+
};
|
|
83
|
+
/**
|
|
84
|
+
* Compose the ordered row list for an FDA-style Nutrition Facts
|
|
85
|
+
* panel from a {@link NutritionFacts} record. Pure function —
|
|
86
|
+
* exported so RSC / Astro-frontmatter callers can pre-compute the
|
|
87
|
+
* spec without bundling the panel.
|
|
88
|
+
*
|
|
89
|
+
* Row order matches §101.9(c) exactly: Total Fat, Saturated Fat,
|
|
90
|
+
* Trans Fat, Cholesterol, Sodium, Total Carbohydrate, Dietary
|
|
91
|
+
* Fiber, Total Sugars, Added Sugars, Protein, then the
|
|
92
|
+
* micronutrient block (Vitamin D, Calcium, Iron, Potassium).
|
|
93
|
+
*
|
|
94
|
+
* @public
|
|
95
|
+
*/
|
|
96
|
+
export declare function composeNutritionFacts(facts: NutritionFacts): NutritionPanelSpec;
|
|
97
|
+
/**
|
|
98
|
+
* @public
|
|
99
|
+
*/
|
|
100
|
+
export type NutritionPanelProps = {
|
|
101
|
+
/** Initial values seeded into the form. Defaults to the
|
|
102
|
+
* illustrative FDA-example values. */
|
|
103
|
+
initialFacts?: Partial<NutritionFacts>;
|
|
104
|
+
/** Fired when the user clicks "Compose" with the spec built from
|
|
105
|
+
* the current form state. The host places it on the canvas as a
|
|
106
|
+
* text block. */
|
|
107
|
+
onCompose: (spec: NutritionPanelSpec) => void;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Nutrition Facts data-entry panel. Surfaces the FDA panel's
|
|
111
|
+
* mandatory fields (serving size, servings, calories, macros) plus
|
|
112
|
+
* the optional micronutrient block. Click **Compose** and the host
|
|
113
|
+
* receives the resolved {@link NutritionPanelSpec} via `onCompose`.
|
|
114
|
+
*
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
export declare function NutritionPanel({ initialFacts, onCompose }: NutritionPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
118
|
+
//# sourceMappingURL=NutritionPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NutritionPanel.d.ts","sourceRoot":"","sources":["../../src/components/NutritionPanel.tsx"],"names":[],"mappings":"AAwBA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;CAYnB,CAAC;AAEX;;;;;;;;GAQG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,kBAAkB,GAAG;IAC/B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,YAAY,EAAE,CAAC;CACtB,CAAC;AA0BF;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,GAAG,kBAAkB,CAiG/E;AA8BD;;GAEG;AACH,MAAM,MAAM,mBAAmB,GAAG;IAChC;2CACuC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACvC;;sBAEkB;IAClB,SAAS,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAC/C,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,EAAE,mBAAmB,2CA8E9E"}
|
|
@@ -0,0 +1,169 @@
|
|
|
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
|
+
/**
|
|
5
|
+
* Wave 3 G1 — Nutrition Facts label generator.
|
|
6
|
+
*
|
|
7
|
+
* The FDA Nutrition Facts label (21 CFR §101.9, 2016 revision) has a
|
|
8
|
+
* highly-regulated layout: serving size + servings per container at
|
|
9
|
+
* the top, Calories in 22-pt bold, then a fixed-order list of
|
|
10
|
+
* nutrients with their amounts + % Daily Value. The panel handles
|
|
11
|
+
* data entry; the {@link composeNutritionFacts} helper turns the
|
|
12
|
+
* typed data into an ordered list of rows the host renders into the
|
|
13
|
+
* canvas (text + bold flags + indentation level) — keeping the
|
|
14
|
+
* editor free of any specific PDF text-layout backend and letting
|
|
15
|
+
* server renderers (compile-pdf, codex-pdf) own the canonical typesetting.
|
|
16
|
+
*
|
|
17
|
+
* Daily Value % is computed from the 2016 FDA Reference Daily Intake
|
|
18
|
+
* (RDI) / Daily Reference Value (DRV) tables; values are widely
|
|
19
|
+
* published and trademark-free.
|
|
20
|
+
*
|
|
21
|
+
* @public
|
|
22
|
+
*/
|
|
23
|
+
import { useState } from "react";
|
|
24
|
+
/**
|
|
25
|
+
* 2016 FDA Daily Reference Values (DRV) and Reference Daily Intakes
|
|
26
|
+
* (RDI) used to compute the % Daily Value column. Public-domain
|
|
27
|
+
* regulatory data — re-exported so server renderers can use the
|
|
28
|
+
* same constants and stay in sync.
|
|
29
|
+
*
|
|
30
|
+
* @public
|
|
31
|
+
*/
|
|
32
|
+
export const FDA_DAILY_VALUES = {
|
|
33
|
+
totalFatG: 78,
|
|
34
|
+
saturatedFatG: 20,
|
|
35
|
+
cholesterolMg: 300,
|
|
36
|
+
sodiumMg: 2300,
|
|
37
|
+
totalCarbohydrateG: 275,
|
|
38
|
+
dietaryFiberG: 28,
|
|
39
|
+
addedSugarsG: 50,
|
|
40
|
+
vitaminDMcg: 20,
|
|
41
|
+
calciumMg: 1300,
|
|
42
|
+
ironMg: 18,
|
|
43
|
+
potassiumMg: 4700,
|
|
44
|
+
};
|
|
45
|
+
function dvPct(amount, dv) {
|
|
46
|
+
if (dv === undefined || dv <= 0)
|
|
47
|
+
return undefined;
|
|
48
|
+
return Math.round((amount / dv) * 100);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Build a {@link NutritionRow}, omitting the `dvPct` key entirely
|
|
52
|
+
* when no DV is defined. Required because `dvPct` is declared as an
|
|
53
|
+
* optional property under `exactOptionalPropertyTypes`; assigning
|
|
54
|
+
* `dvPct: undefined` does not satisfy the type, so the helper
|
|
55
|
+
* branches the object shape.
|
|
56
|
+
*/
|
|
57
|
+
function row(label, amount, pct, indent, bold) {
|
|
58
|
+
return pct !== undefined
|
|
59
|
+
? { label, amount, dvPct: pct, indent, bold }
|
|
60
|
+
: { label, amount, indent, bold };
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Compose the ordered row list for an FDA-style Nutrition Facts
|
|
64
|
+
* panel from a {@link NutritionFacts} record. Pure function —
|
|
65
|
+
* exported so RSC / Astro-frontmatter callers can pre-compute the
|
|
66
|
+
* spec without bundling the panel.
|
|
67
|
+
*
|
|
68
|
+
* Row order matches §101.9(c) exactly: Total Fat, Saturated Fat,
|
|
69
|
+
* Trans Fat, Cholesterol, Sodium, Total Carbohydrate, Dietary
|
|
70
|
+
* Fiber, Total Sugars, Added Sugars, Protein, then the
|
|
71
|
+
* micronutrient block (Vitamin D, Calcium, Iron, Potassium).
|
|
72
|
+
*
|
|
73
|
+
* @public
|
|
74
|
+
*/
|
|
75
|
+
export function composeNutritionFacts(facts) {
|
|
76
|
+
const rows = [
|
|
77
|
+
row("Total Fat", `${facts.totalFatG}g`, dvPct(facts.totalFatG, FDA_DAILY_VALUES.totalFatG), 0, true),
|
|
78
|
+
row("Saturated Fat", `${facts.saturatedFatG}g`, dvPct(facts.saturatedFatG, FDA_DAILY_VALUES.saturatedFatG), 1, false),
|
|
79
|
+
row("Trans Fat", `${facts.transFatG}g`, undefined, 1, false),
|
|
80
|
+
row("Cholesterol", `${facts.cholesterolMg}mg`, dvPct(facts.cholesterolMg, FDA_DAILY_VALUES.cholesterolMg), 0, true),
|
|
81
|
+
row("Sodium", `${facts.sodiumMg}mg`, dvPct(facts.sodiumMg, FDA_DAILY_VALUES.sodiumMg), 0, true),
|
|
82
|
+
row("Total Carbohydrate", `${facts.totalCarbohydrateG}g`, dvPct(facts.totalCarbohydrateG, FDA_DAILY_VALUES.totalCarbohydrateG), 0, true),
|
|
83
|
+
row("Dietary Fiber", `${facts.dietaryFiberG}g`, dvPct(facts.dietaryFiberG, FDA_DAILY_VALUES.dietaryFiberG), 1, false),
|
|
84
|
+
row("Total Sugars", `${facts.totalSugarsG}g`, undefined, 1, false),
|
|
85
|
+
];
|
|
86
|
+
if (facts.addedSugarsG !== undefined) {
|
|
87
|
+
rows.push(row("Includes Added Sugars", `${facts.addedSugarsG}g`, dvPct(facts.addedSugarsG, FDA_DAILY_VALUES.addedSugarsG), 1, false));
|
|
88
|
+
}
|
|
89
|
+
rows.push(row("Protein", `${facts.proteinG}g`, undefined, 0, true));
|
|
90
|
+
if (facts.vitaminDMcg !== undefined) {
|
|
91
|
+
rows.push(row("Vitamin D", `${facts.vitaminDMcg}mcg`, dvPct(facts.vitaminDMcg, FDA_DAILY_VALUES.vitaminDMcg), 0, false));
|
|
92
|
+
}
|
|
93
|
+
if (facts.calciumMg !== undefined) {
|
|
94
|
+
rows.push(row("Calcium", `${facts.calciumMg}mg`, dvPct(facts.calciumMg, FDA_DAILY_VALUES.calciumMg), 0, false));
|
|
95
|
+
}
|
|
96
|
+
if (facts.ironMg !== undefined) {
|
|
97
|
+
rows.push(row("Iron", `${facts.ironMg}mg`, dvPct(facts.ironMg, FDA_DAILY_VALUES.ironMg), 0, false));
|
|
98
|
+
}
|
|
99
|
+
if (facts.potassiumMg !== undefined) {
|
|
100
|
+
rows.push(row("Potassium", `${facts.potassiumMg}mg`, dvPct(facts.potassiumMg, FDA_DAILY_VALUES.potassiumMg), 0, false));
|
|
101
|
+
}
|
|
102
|
+
return {
|
|
103
|
+
servingSize: facts.servingSize,
|
|
104
|
+
servingsLine: `${facts.servingsPerContainer} servings per container`,
|
|
105
|
+
caloriesLine: `Calories ${facts.calories}`,
|
|
106
|
+
rows,
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
// Required-field defaults only. Optional nutrients (Added Sugars,
|
|
110
|
+
// Vitamin D, Calcium, Iron, Potassium) are intentionally left absent
|
|
111
|
+
// so hosts that don't want those rows aren't forced to pass
|
|
112
|
+
// `undefined` overrides — `composeNutritionFacts` already omits any
|
|
113
|
+
// optional field that's not set.
|
|
114
|
+
const DEFAULT_FACTS = {
|
|
115
|
+
servingSize: "1 cup (240g)",
|
|
116
|
+
servingsPerContainer: 4,
|
|
117
|
+
calories: 230,
|
|
118
|
+
totalFatG: 8,
|
|
119
|
+
saturatedFatG: 1,
|
|
120
|
+
transFatG: 0,
|
|
121
|
+
cholesterolMg: 0,
|
|
122
|
+
sodiumMg: 160,
|
|
123
|
+
totalCarbohydrateG: 37,
|
|
124
|
+
dietaryFiberG: 4,
|
|
125
|
+
totalSugarsG: 12,
|
|
126
|
+
proteinG: 3,
|
|
127
|
+
};
|
|
128
|
+
const OPTIONAL_NUTRITION_KEYS = new Set([
|
|
129
|
+
"addedSugarsG",
|
|
130
|
+
"vitaminDMcg",
|
|
131
|
+
"calciumMg",
|
|
132
|
+
"ironMg",
|
|
133
|
+
"potassiumMg",
|
|
134
|
+
]);
|
|
135
|
+
/**
|
|
136
|
+
* Nutrition Facts data-entry panel. Surfaces the FDA panel's
|
|
137
|
+
* mandatory fields (serving size, servings, calories, macros) plus
|
|
138
|
+
* the optional micronutrient block. Click **Compose** and the host
|
|
139
|
+
* receives the resolved {@link NutritionPanelSpec} via `onCompose`.
|
|
140
|
+
*
|
|
141
|
+
* @public
|
|
142
|
+
*/
|
|
143
|
+
export function NutritionPanel({ initialFacts, onCompose }) {
|
|
144
|
+
const [facts, setFacts] = useState({ ...DEFAULT_FACTS, ...initialFacts });
|
|
145
|
+
function setNum(key, value) {
|
|
146
|
+
setFacts((f) => ({ ...f, [key]: value }));
|
|
147
|
+
}
|
|
148
|
+
function clearOptional(key) {
|
|
149
|
+
setFacts((f) => {
|
|
150
|
+
const { [key]: _dropped, ...rest } = f;
|
|
151
|
+
return rest;
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function numInput(label, key, unit) {
|
|
155
|
+
const isOptional = OPTIONAL_NUTRITION_KEYS.has(key);
|
|
156
|
+
const current = facts[key];
|
|
157
|
+
return (_jsxs("label", { style: { display: "block", marginBottom: "0.25rem" }, children: [label, _jsx("input", { type: "number", value: current ?? "", onChange: (e) => {
|
|
158
|
+
const raw = e.target.value;
|
|
159
|
+
if (isOptional && raw === "") {
|
|
160
|
+
clearOptional(key);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
const v = Number(raw);
|
|
164
|
+
setNum(key, (Number.isNaN(v) ? 0 : v));
|
|
165
|
+
}, "aria-label": label, style: { marginLeft: "0.5rem", width: "5em" } }), " ", unit] }));
|
|
166
|
+
}
|
|
167
|
+
return (_jsxs("div", { "data-testid": "nutrition-panel", style: { padding: "0.5rem", maxWidth: "24em" }, children: [_jsx("h3", { style: { margin: "0 0 0.5rem 0" }, children: "Nutrition Facts" }), _jsxs("label", { style: { display: "block", marginBottom: "0.5rem" }, children: ["Serving size", _jsx("input", { type: "text", value: facts.servingSize, onChange: (e) => setFacts((f) => ({ ...f, servingSize: e.target.value })), "aria-label": "Serving size", style: { marginLeft: "0.5rem", width: "14em" } })] }), numInput("Servings per container", "servingsPerContainer", ""), numInput("Calories", "calories", "kcal"), numInput("Total Fat", "totalFatG", "g"), numInput("Saturated Fat", "saturatedFatG", "g"), numInput("Trans Fat", "transFatG", "g"), numInput("Cholesterol", "cholesterolMg", "mg"), numInput("Sodium", "sodiumMg", "mg"), numInput("Total Carbohydrate", "totalCarbohydrateG", "g"), numInput("Dietary Fiber", "dietaryFiberG", "g"), numInput("Total Sugars", "totalSugarsG", "g"), numInput("Added Sugars (optional, leave blank to omit)", "addedSugarsG", "g"), numInput("Protein", "proteinG", "g"), numInput("Vitamin D (optional)", "vitaminDMcg", "mcg"), numInput("Calcium (optional)", "calciumMg", "mg"), numInput("Iron (optional)", "ironMg", "mg"), numInput("Potassium (optional)", "potassiumMg", "mg"), _jsx("button", { type: "button", onClick: () => onCompose(composeNutritionFacts(facts)), style: { padding: "0.4rem 0.8rem", marginTop: "0.5rem" }, children: "Compose" })] }));
|
|
168
|
+
}
|
|
169
|
+
//# sourceMappingURL=NutritionPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NutritionPanel.js","sourceRoot":"","sources":["../../src/components/NutritionPanel.tsx"],"names":[],"mappings":"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"}
|