@cellarnode/ui 0.13.0 → 0.15.1

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 (60) hide show
  1. package/dist/components/bottle-extract-dialog.d.ts +25 -0
  2. package/dist/components/bottle-extract-dialog.d.ts.map +1 -0
  3. package/dist/components/bottle-extract-dialog.js +87 -0
  4. package/dist/components/bottle-extract-dialog.js.map +1 -0
  5. package/dist/components/bottle-extract-dialog.stories.d.ts +17 -0
  6. package/dist/components/bottle-extract-dialog.stories.d.ts.map +1 -0
  7. package/dist/components/bottle-extract-dialog.stories.js +54 -0
  8. package/dist/components/bottle-extract-dialog.stories.js.map +1 -0
  9. package/dist/components/bottle-extraction-inline-progress.d.ts +14 -0
  10. package/dist/components/bottle-extraction-inline-progress.d.ts.map +1 -0
  11. package/dist/components/bottle-extraction-inline-progress.js +28 -0
  12. package/dist/components/bottle-extraction-inline-progress.js.map +1 -0
  13. package/dist/components/bottle-extraction-inline-progress.stories.d.ts +17 -0
  14. package/dist/components/bottle-extraction-inline-progress.stories.d.ts.map +1 -0
  15. package/dist/components/bottle-extraction-inline-progress.stories.js +35 -0
  16. package/dist/components/bottle-extraction-inline-progress.stories.js.map +1 -0
  17. package/dist/components/extraction-phase-stepper.d.ts +19 -0
  18. package/dist/components/extraction-phase-stepper.d.ts.map +1 -0
  19. package/dist/components/extraction-phase-stepper.js +26 -0
  20. package/dist/components/extraction-phase-stepper.js.map +1 -0
  21. package/dist/components/extraction-phase-stepper.stories.d.ts +18 -0
  22. package/dist/components/extraction-phase-stepper.stories.d.ts.map +1 -0
  23. package/dist/components/extraction-phase-stepper.stories.js +31 -0
  24. package/dist/components/extraction-phase-stepper.stories.js.map +1 -0
  25. package/dist/components/flagged-field-editor.d.ts +23 -0
  26. package/dist/components/flagged-field-editor.d.ts.map +1 -0
  27. package/dist/components/flagged-field-editor.js +16 -0
  28. package/dist/components/flagged-field-editor.js.map +1 -0
  29. package/dist/components/flagged-field-editor.stories.d.ts +27 -0
  30. package/dist/components/flagged-field-editor.stories.d.ts.map +1 -0
  31. package/dist/components/flagged-field-editor.stories.js +60 -0
  32. package/dist/components/flagged-field-editor.stories.js.map +1 -0
  33. package/dist/components/picker-empty-guidance.js +1 -1
  34. package/dist/components/picker-empty-guidance.js.map +1 -1
  35. package/dist/components/preflight-verdict-sheet.d.ts +20 -0
  36. package/dist/components/preflight-verdict-sheet.d.ts.map +1 -0
  37. package/dist/components/preflight-verdict-sheet.js +23 -0
  38. package/dist/components/preflight-verdict-sheet.js.map +1 -0
  39. package/dist/components/preflight-verdict-sheet.stories.d.ts +29 -0
  40. package/dist/components/preflight-verdict-sheet.stories.d.ts.map +1 -0
  41. package/dist/components/preflight-verdict-sheet.stories.js +48 -0
  42. package/dist/components/preflight-verdict-sheet.stories.js.map +1 -0
  43. package/dist/components/reason-pill.d.ts.map +1 -1
  44. package/dist/components/reason-pill.js +5 -2
  45. package/dist/components/reason-pill.js.map +1 -1
  46. package/dist/components/score-chip.js +1 -1
  47. package/dist/components/score-chip.js.map +1 -1
  48. package/dist/components/variant-picker-dialog.d.ts +30 -2
  49. package/dist/components/variant-picker-dialog.d.ts.map +1 -1
  50. package/dist/components/variant-picker-dialog.js +31 -18
  51. package/dist/components/variant-picker-dialog.js.map +1 -1
  52. package/dist/components/variant-picker-dialog.test.d.ts +2 -0
  53. package/dist/components/variant-picker-dialog.test.d.ts.map +1 -0
  54. package/dist/components/variant-picker-dialog.test.js +140 -0
  55. package/dist/components/variant-picker-dialog.test.js.map +1 -0
  56. package/dist/index.d.ts +6 -1
  57. package/dist/index.d.ts.map +1 -1
  58. package/dist/index.js +7 -0
  59. package/dist/index.js.map +1 -1
  60. package/package.json +1 -1
@@ -0,0 +1,25 @@
1
+ export type BottleExtractDialogContext = {
2
+ kind: "beverage_gallery";
3
+ beverageId: string;
4
+ beverageName: string;
5
+ } | {
6
+ kind: "variant_carousel";
7
+ beverageId: string;
8
+ variantId: string;
9
+ variantName: string;
10
+ beverageName: string;
11
+ };
12
+ export interface BottleExtractDialogProps {
13
+ open: boolean;
14
+ context: BottleExtractDialogContext;
15
+ onClose: () => void;
16
+ onSubmit: (input: {
17
+ file: File;
18
+ aiExtract: boolean;
19
+ makePrimary: boolean;
20
+ }) => Promise<void>;
21
+ /** i18n lookup — producer-dashboard passes react-i18next's `t` */
22
+ t: (key: string, opts?: Record<string, unknown>) => string;
23
+ }
24
+ export declare function BottleExtractDialog({ open, context, onClose, onSubmit, t, }: BottleExtractDialogProps): import("react/jsx-runtime").JSX.Element;
25
+ //# sourceMappingURL=bottle-extract-dialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extract-dialog.d.ts","sourceRoot":"","sources":["../../src/components/bottle-extract-dialog.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,0BAA0B,GAClC;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GACtE;IACE,IAAI,EAAE,kBAAkB,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;CACtB,CAAC;AAEN,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,0BAA0B,CAAC;IACpC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,IAAI,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7F,kEAAkE;IAClE,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;CAC5D;AAOD,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,OAAO,EACP,QAAQ,EACR,CAAC,GACF,EAAE,wBAAwB,2CAkK1B"}
@@ -0,0 +1,87 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as Dialog from "@radix-ui/react-dialog";
3
+ import * as React from "react";
4
+ import { cn } from "../lib/utils";
5
+ export function BottleExtractDialog({ open, context, onClose, onSubmit, t, }) {
6
+ const [file, setFile] = React.useState(null);
7
+ const [mode, setMode] = React.useState("extract");
8
+ const [makePrimary, setMakePrimary] = React.useState(false);
9
+ const [state, setState] = React.useState({ kind: "idle" });
10
+ const fileInputRef = React.useRef(null);
11
+ const targetName = context.kind === "beverage_gallery" ? context.beverageName : context.variantName;
12
+ const titleId = React.useId();
13
+ const validate = (f) => {
14
+ if (f.name.toLowerCase().endsWith(".heic") ||
15
+ f.type === "image/heic" ||
16
+ f.type === "image/heif") {
17
+ return t("dialog.heic_error");
18
+ }
19
+ if (f.type === "image/webp")
20
+ return t("dialog.webp_error");
21
+ if (!["image/jpeg", "image/png"].includes(f.type)) {
22
+ return t("dialog.heic_error");
23
+ }
24
+ if (f.size > 10 * 1024 * 1024)
25
+ return "File is larger than 10MB.";
26
+ return null;
27
+ };
28
+ const handleFileChange = (files) => {
29
+ if (!files || files.length === 0)
30
+ return;
31
+ const first = files[0];
32
+ if (!first)
33
+ return;
34
+ const err = validate(first);
35
+ if (err) {
36
+ setState({ kind: "error", message: err });
37
+ return;
38
+ }
39
+ setFile(first);
40
+ setState({ kind: "idle" });
41
+ };
42
+ const handleSubmit = async (e) => {
43
+ e.preventDefault();
44
+ if (!file) {
45
+ setState({ kind: "error", message: "Please choose a file first." });
46
+ return;
47
+ }
48
+ setState({ kind: "submitting" });
49
+ try {
50
+ await onSubmit({
51
+ file,
52
+ aiExtract: mode === "extract",
53
+ makePrimary: mode === "extract" && makePrimary,
54
+ });
55
+ setFile(null);
56
+ setMakePrimary(false);
57
+ setMode("extract");
58
+ setState({ kind: "idle" });
59
+ onClose();
60
+ }
61
+ catch (err) {
62
+ setState({ kind: "error", message: err.message });
63
+ }
64
+ };
65
+ return (_jsx(Dialog.Root, { open: open, onOpenChange: (nextOpen) => !nextOpen && onClose(), children: _jsxs(Dialog.Portal, { children: [_jsx(Dialog.Overlay, { className: "fixed inset-0 z-50 bg-foreground/20 backdrop-blur-xs" }), _jsxs(Dialog.Content, { "aria-labelledby": titleId, className: cn("fixed left-1/2 top-1/2 z-50 w-[calc(100%-2rem)] max-w-lg -translate-x-1/2 -translate-y-1/2", "rounded-2xl border border-border bg-card p-6 shadow-xl"), children: [_jsx(Dialog.Title, { id: titleId, className: "text-base/6 font-semibold text-foreground", children: t("dialog.title") }), _jsxs("form", { onSubmit: handleSubmit, className: "mt-4 flex flex-col gap-4", children: [_jsx(DropZone, { ref: fileInputRef, file: file, onFileChange: handleFileChange, t: t }), _jsxs("fieldset", { className: "flex flex-col gap-2", children: [_jsx("legend", { className: "sr-only", children: "Upload mode" }), _jsxs("label", { className: "flex cursor-pointer items-start gap-3", children: [_jsx("input", { type: "radio", name: "mode", value: "as_is", checked: mode === "as_is", onChange: () => setMode("as_is"), className: "mt-1" }), _jsxs("span", { children: [_jsx("span", { className: "font-medium text-foreground", children: t("dialog.mode_as_is") }), _jsx("span", { className: "block text-sm text-muted-foreground", children: t("dialog.mode_as_is_help", { name: targetName }) })] })] }), _jsxs("label", { className: "flex cursor-pointer items-start gap-3", children: [_jsx("input", { type: "radio", name: "mode", value: "extract", checked: mode === "extract", onChange: () => setMode("extract"), className: "mt-1" }), _jsxs("span", { children: [_jsx("span", { className: "font-medium text-foreground", children: t("dialog.mode_extract") }), _jsx("span", { className: "block text-sm text-muted-foreground", children: t("dialog.mode_extract_help", { name: targetName }) })] })] })] }), mode === "extract" && (_jsxs("label", { className: "flex cursor-pointer items-center gap-2 text-foreground", children: [_jsx("input", { type: "checkbox", checked: makePrimary, onChange: (e) => setMakePrimary(e.target.checked) }), _jsx("span", { children: t("dialog.make_primary") })] })), state.kind === "error" && (_jsx("div", { role: "alert", className: "rounded-lg border border-red-300 bg-red-50 p-2 text-sm text-red-900 dark:border-red-800 dark:bg-red-950 dark:text-red-100", children: state.message })), _jsx("div", { "aria-live": "polite", className: "sr-only", children: state.kind === "submitting" ? t("dialog.uploading") : "" }), _jsxs("div", { className: "mt-2 flex justify-end gap-2", children: [_jsx("button", { type: "button", onClick: onClose, className: "rounded-md px-4 py-2 text-foreground hover:bg-muted/50 focus:outline-hidden focus-visible:ring-2 focus-visible:ring-primary/50", children: t("dialog.cancel") }), _jsx("button", { type: "submit", disabled: !file || state.kind === "submitting", className: "rounded-md bg-emerald-600 px-4 py-2 text-white hover:bg-emerald-700 focus:outline-hidden focus-visible:ring-2 focus-visible:ring-emerald-500 disabled:opacity-50", children: state.kind === "submitting" ? t("dialog.uploading") : t("dialog.submit") })] })] }), _jsx(Dialog.Close, { className: "absolute right-4 top-4 text-muted-foreground hover:text-foreground focus:outline-hidden focus-visible:ring-2 focus-visible:ring-primary/50", "aria-label": "Close", children: "\u00D7" })] })] }) }));
66
+ }
67
+ const DropZone = React.forwardRef(({ file, onFileChange, t }, ref) => {
68
+ const [hover, setHover] = React.useState(false);
69
+ const labelId = React.useId();
70
+ return (_jsxs("div", { role: "button", tabIndex: 0, "aria-labelledby": labelId, onClick: () => ref.current?.click(), onKeyDown: (e) => {
71
+ if (e.key === "Enter" || e.key === " ") {
72
+ e.preventDefault();
73
+ ref.current?.click();
74
+ }
75
+ }, onDragOver: (e) => {
76
+ e.preventDefault();
77
+ setHover(true);
78
+ }, onDragLeave: () => setHover(false), onDrop: (e) => {
79
+ e.preventDefault();
80
+ setHover(false);
81
+ onFileChange(e.dataTransfer.files);
82
+ }, className: cn("cursor-pointer rounded-lg border-2 border-dashed p-6 text-center focus:outline-hidden focus-visible:ring-2 focus-visible:ring-emerald-500", hover
83
+ ? "border-emerald-500 bg-emerald-50 dark:bg-emerald-950/30"
84
+ : "border-border bg-muted/20"), children: [_jsx("input", { ref: ref, type: "file", accept: "image/jpeg,image/png", className: "hidden", onChange: (e) => onFileChange(e.target.files) }), _jsx("p", { id: labelId, className: "text-sm text-foreground", children: file ? file.name : t("dialog.drop_zone") })] }));
85
+ });
86
+ DropZone.displayName = "DropZone";
87
+ //# sourceMappingURL=bottle-extract-dialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extract-dialog.js","sourceRoot":"","sources":["../../src/components/bottle-extract-dialog.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { StoryObj } from "@storybook/react-vite";
2
+ import { BottleExtractDialog } from "./bottle-extract-dialog";
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof BottleExtractDialog;
6
+ tags: string[];
7
+ parameters: {
8
+ a11y: {
9
+ test: string;
10
+ };
11
+ };
12
+ };
13
+ export default meta;
14
+ type Story = StoryObj<typeof meta>;
15
+ export declare const BeverageGallery: Story;
16
+ export declare const VariantCarousel: Story;
17
+ //# sourceMappingURL=bottle-extract-dialog.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extract-dialog.stories.d.ts","sourceRoot":"","sources":["../../src/components/bottle-extract-dialog.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAsB9D,QAAA,MAAM,IAAI;;;;;;;;;CAKkC,CAAC;AAE7C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,eAAe,EAAE,KAY7B,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAc7B,CAAC"}
@@ -0,0 +1,54 @@
1
+ import { BottleExtractDialog } from "./bottle-extract-dialog";
2
+ const t = (key, opts) => {
3
+ const strings = {
4
+ "dialog.title": "Add bottle photo",
5
+ "dialog.drop_zone": "Drop an image here, or click to browse (JPEG or PNG, up to 10MB)",
6
+ "dialog.mode_as_is": "Upload as-is",
7
+ "dialog.mode_as_is_help": `Add this photo to ${opts?.name}'s gallery without AI processing.`,
8
+ "dialog.mode_extract": "Upload + AI extract bottle",
9
+ "dialog.mode_extract_help": `We'll send this image to our bottle-extraction AI to isolate the bottle. Takes ~10 seconds. Result will be added to ${opts?.name}'s gallery.`,
10
+ "dialog.make_primary": "Make the cutout the primary photo",
11
+ "dialog.submit": "Upload",
12
+ "dialog.cancel": "Cancel",
13
+ "dialog.uploading": "Uploading…",
14
+ "dialog.heic_error": "HEIC isn't supported yet. Please convert to JPEG.",
15
+ "dialog.webp_error": "WebP isn't supported yet. Please convert to JPEG or PNG.",
16
+ };
17
+ return strings[key] ?? key;
18
+ };
19
+ const meta = {
20
+ title: "Extraction/BottleExtractDialog",
21
+ component: BottleExtractDialog,
22
+ tags: ["autodocs"],
23
+ parameters: { a11y: { test: "error" } },
24
+ };
25
+ export default meta;
26
+ export const BeverageGallery = {
27
+ args: {
28
+ open: true,
29
+ context: {
30
+ kind: "beverage_gallery",
31
+ beverageId: "b1",
32
+ beverageName: "Tenuta Sample Reserve",
33
+ },
34
+ onClose: () => { },
35
+ onSubmit: async () => new Promise((resolve) => setTimeout(resolve, 600)),
36
+ t,
37
+ },
38
+ };
39
+ export const VariantCarousel = {
40
+ args: {
41
+ open: true,
42
+ context: {
43
+ kind: "variant_carousel",
44
+ beverageId: "b1",
45
+ variantId: "v1",
46
+ variantName: "Tenuta Sample Reserve 2021",
47
+ beverageName: "Tenuta Sample Reserve",
48
+ },
49
+ onClose: () => { },
50
+ onSubmit: async () => new Promise((resolve) => setTimeout(resolve, 600)),
51
+ t,
52
+ },
53
+ };
54
+ //# sourceMappingURL=bottle-extract-dialog.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extract-dialog.stories.js","sourceRoot":"","sources":["../../src/components/bottle-extract-dialog.stories.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,IAA8B,EAAE,EAAE;IACxD,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,kBAAkB,EAChB,kEAAkE;QACpE,mBAAmB,EAAE,cAAc;QACnC,wBAAwB,EAAE,qBAAqB,IAAI,EAAE,IAAI,mCAAmC;QAC5F,qBAAqB,EAAE,4BAA4B;QACnD,0BAA0B,EAAE,uHAAuH,IAAI,EAAE,IAAI,aAAa;QAC1K,qBAAqB,EAAE,mCAAmC;QAC1D,eAAe,EAAE,QAAQ;QACzB,eAAe,EAAE,QAAQ;QACzB,kBAAkB,EAAE,YAAY;QAChC,mBAAmB,EAAE,mDAAmD;QACxE,mBAAmB,EACjB,0DAA0D;KAC7D,CAAC;IACF,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,gCAAgC;IACvC,SAAS,EAAE,mBAAmB;IAC9B,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;CACG,CAAC;AAE7C,eAAe,IAAI,CAAC;AAGpB,MAAM,CAAC,MAAM,eAAe,GAAU;IACpC,IAAI,EAAE;QACJ,IAAI,EAAE,IAAI;QACV,OAAO,EAAE;YACP,IAAI,EAAE,kBAAkB;YACxB,UAAU,EAAE,IAAI;YAChB,YAAY,EAAE,uBAAuB;SACtC;QACD,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;QACjB,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAU;IACpC,IAAI,EAAE;QACJ,IAAI,EAAE,IAAI;QACV,OAAO,EAAE;YACP,IAAI,EAAE,kBAAkB;YACxB,UAAU,EAAE,IAAI;YAChB,SAAS,EAAE,IAAI;YACf,WAAW,EAAE,4BAA4B;YACzC,YAAY,EAAE,uBAAuB;SACtC;QACD,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC;QACjB,QAAQ,EAAE,KAAK,IAAI,EAAE,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACxE,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,14 @@
1
+ export interface BottleExtractionInlineProgressProps {
2
+ jobId: string;
3
+ progress: {
4
+ processed: number;
5
+ total: number;
6
+ currentProductIndex?: number;
7
+ message?: string;
8
+ } | null;
9
+ status: "pending" | "processing" | "completed" | "failed" | "abandoned" | "awaiting_producer";
10
+ onCancel?: () => void;
11
+ t: (key: string, opts?: Record<string, unknown>) => string;
12
+ }
13
+ export declare function BottleExtractionInlineProgress(props: BottleExtractionInlineProgressProps): import("react/jsx-runtime").JSX.Element | null;
14
+ //# sourceMappingURL=bottle-extraction-inline-progress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extraction-inline-progress.d.ts","sourceRoot":"","sources":["../../src/components/bottle-extraction-inline-progress.tsx"],"names":[],"mappings":"AAEA,MAAM,WAAW,mCAAmC;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,IAAI,CAAC;IACT,MAAM,EAAE,SAAS,GAAG,YAAY,GAAG,WAAW,GAAG,QAAQ,GAAG,WAAW,GAAG,mBAAmB,CAAC;IAC9F,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;CAC5D;AAED,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,mCAAmC,kDAmDxF"}
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ export function BottleExtractionInlineProgress(props) {
4
+ const { progress, status, onCancel, t } = props;
5
+ const [startedAt] = React.useState(() => Date.now());
6
+ const [now, setNow] = React.useState(() => Date.now());
7
+ React.useEffect(() => {
8
+ if (status === "completed" || status === "failed" || status === "abandoned")
9
+ return;
10
+ const tick = setInterval(() => setNow(Date.now()), 1000);
11
+ return () => clearInterval(tick);
12
+ }, [status]);
13
+ const elapsedSeconds = Math.round((now - startedAt) / 1000);
14
+ const coldStartHint = elapsedSeconds >= 60 ? "slow_60s" : elapsedSeconds >= 20 ? "slow_20s" : null;
15
+ if (status === "completed")
16
+ return null;
17
+ const label = progress && progress.total > 1
18
+ ? t("progress.running_with_counts", {
19
+ processed: progress.processed,
20
+ total: progress.total,
21
+ })
22
+ : t("progress.running");
23
+ return (_jsxs("div", { role: "status", "aria-live": "polite", className: "flex items-center gap-3 rounded-lg border border-emerald-200 bg-emerald-50 p-3 dark:border-emerald-800 dark:bg-emerald-950/30", children: [_jsx(Spinner, {}), _jsxs("div", { className: "flex-1", children: [_jsx("p", { className: "text-sm font-medium text-foreground", children: label }), coldStartHint && (_jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: t(`progress.${coldStartHint}`) }))] }), elapsedSeconds >= 60 && onCancel && (_jsx("button", { type: "button", onClick: onCancel, className: "rounded-md text-sm text-red-600 hover:underline focus:outline-hidden focus-visible:ring-2 focus-visible:ring-red-500", children: t("progress.cancel") }))] }));
24
+ }
25
+ function Spinner() {
26
+ return (_jsx("span", { "aria-hidden": "true", className: "inline-block size-4 animate-spin rounded-full border-2 border-emerald-600 border-t-transparent" }));
27
+ }
28
+ //# sourceMappingURL=bottle-extraction-inline-progress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extraction-inline-progress.js","sourceRoot":"","sources":["../../src/components/bottle-extraction-inline-progress.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,MAAM,UAAU,8BAA8B,CAAC,KAA0C;IACvF,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC;IAChD,MAAM,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACrD,MAAM,CAAC,GAAG,EAAE,MAAM,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IAEvD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,WAAW;YAAE,OAAO;QACpF,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC;QACzD,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5D,MAAM,aAAa,GACjB,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;IAE/E,IAAI,MAAM,KAAK,WAAW;QAAE,OAAO,IAAI,CAAC;IAExC,MAAM,KAAK,GACT,QAAQ,IAAI,QAAQ,CAAC,KAAK,GAAG,CAAC;QAC5B,CAAC,CAAC,CAAC,CAAC,8BAA8B,EAAE;YAChC,SAAS,EAAE,QAAQ,CAAC,SAAS;YAC7B,KAAK,EAAE,QAAQ,CAAC,KAAK;SACtB,CAAC;QACJ,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAE5B,OAAO,CACL,eACE,IAAI,EAAC,QAAQ,eACH,QAAQ,EAClB,SAAS,EAAC,+HAA+H,aAEzI,KAAC,OAAO,KAAG,EACX,eAAK,SAAS,EAAC,QAAQ,aACrB,YAAG,SAAS,EAAC,qCAAqC,YAAE,KAAK,GAAK,EAC7D,aAAa,IAAI,CAChB,YAAG,SAAS,EAAC,oCAAoC,YAC9C,CAAC,CAAC,YAAY,aAAa,EAAE,CAAC,GAC7B,CACL,IACG,EACL,cAAc,IAAI,EAAE,IAAI,QAAQ,IAAI,CACnC,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,QAAQ,EACjB,SAAS,EAAC,sHAAsH,YAE/H,CAAC,CAAC,iBAAiB,CAAC,GACd,CACV,IACG,CACP,CAAC;AACJ,CAAC;AAED,SAAS,OAAO;IACd,OAAO,CACL,8BACc,MAAM,EAClB,SAAS,EAAC,gGAAgG,GAC1G,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { StoryObj } from "@storybook/react-vite";
2
+ import { BottleExtractionInlineProgress } from "./bottle-extraction-inline-progress";
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof BottleExtractionInlineProgress;
6
+ tags: string[];
7
+ parameters: {
8
+ a11y: {
9
+ test: string;
10
+ };
11
+ };
12
+ };
13
+ export default meta;
14
+ type Story = StoryObj<typeof meta>;
15
+ export declare const SingleRunning: Story;
16
+ export declare const CatalogMidway: Story;
17
+ //# sourceMappingURL=bottle-extraction-inline-progress.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extraction-inline-progress.stories.d.ts","sourceRoot":"","sources":["../../src/components/bottle-extraction-inline-progress.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAerF,QAAA,MAAM,IAAI;;;;;;;;;CAK6C,CAAC;AAExD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,aAAa,EAAE,KAO3B,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAO3B,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { BottleExtractionInlineProgress } from "./bottle-extraction-inline-progress";
2
+ const t = (key, opts) => {
3
+ const strings = {
4
+ "progress.running": "Extracting bottle photo…",
5
+ "progress.running_with_counts": `Extracting bottle photo… (${opts?.processed} of ${opts?.total} processed)`,
6
+ "progress.slow_20s": "This is taking a moment longer than usual — we're warming up the AI service.",
7
+ "progress.slow_60s": "Still working — bottle extraction can take 1–2 minutes on first run.",
8
+ "progress.cancel": "Cancel",
9
+ };
10
+ return strings[key] ?? key;
11
+ };
12
+ const meta = {
13
+ title: "Extraction/BottleExtractionInlineProgress",
14
+ component: BottleExtractionInlineProgress,
15
+ tags: ["autodocs"],
16
+ parameters: { a11y: { test: "error" } },
17
+ };
18
+ export default meta;
19
+ export const SingleRunning = {
20
+ args: {
21
+ jobId: "j1",
22
+ status: "processing",
23
+ progress: { processed: 0, total: 1 },
24
+ t,
25
+ },
26
+ };
27
+ export const CatalogMidway = {
28
+ args: {
29
+ jobId: "j2",
30
+ status: "processing",
31
+ progress: { processed: 4, total: 12 },
32
+ t,
33
+ },
34
+ };
35
+ //# sourceMappingURL=bottle-extraction-inline-progress.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bottle-extraction-inline-progress.stories.js","sourceRoot":"","sources":["../../src/components/bottle-extraction-inline-progress.stories.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,8BAA8B,EAAE,MAAM,qCAAqC,CAAC;AAErF,MAAM,CAAC,GAAG,CAAC,GAAW,EAAE,IAA8B,EAAE,EAAE;IACxD,MAAM,OAAO,GAA2B;QACtC,kBAAkB,EAAE,0BAA0B;QAC9C,8BAA8B,EAAE,6BAA6B,IAAI,EAAE,SAAS,OAAO,IAAI,EAAE,KAAK,aAAa;QAC3G,mBAAmB,EACjB,8EAA8E;QAChF,mBAAmB,EACjB,sEAAsE;QACxE,iBAAiB,EAAE,QAAQ;KAC5B,CAAC;IACF,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;AAC7B,CAAC,CAAC;AAEF,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,2CAA2C;IAClD,SAAS,EAAE,8BAA8B;IACzC,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;CACc,CAAC;AAExD,eAAe,IAAI,CAAC;AAGpB,MAAM,CAAC,MAAM,aAAa,GAAU;IAClC,IAAI,EAAE;QACJ,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;QACpC,CAAC;KACF;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAU;IAClC,IAAI,EAAE;QACJ,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,YAAY;QACpB,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE;QACrC,CAAC;KACF;CACF,CAAC"}
@@ -0,0 +1,19 @@
1
+ export interface StepperStep {
2
+ key: string;
3
+ label: string;
4
+ conditional?: boolean;
5
+ visible?: boolean;
6
+ }
7
+ export interface ExtractionPhaseStepperProps {
8
+ steps: StepperStep[];
9
+ currentPhaseKey: string;
10
+ reviewCount?: number;
11
+ className?: string;
12
+ }
13
+ /**
14
+ * Horizontal phase stepper for the multi-phase extraction workflow.
15
+ * Hides conditional steps (e.g. "Needs review") unless `visible` is true.
16
+ * Announces review count changes via an `aria-live="polite"` region.
17
+ */
18
+ export declare function ExtractionPhaseStepper(props: ExtractionPhaseStepperProps): import("react/jsx-runtime").JSX.Element;
19
+ //# sourceMappingURL=extraction-phase-stepper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-phase-stepper.d.ts","sourceRoot":"","sources":["../../src/components/extraction-phase-stepper.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,2BAA2B;IAC1C,KAAK,EAAE,WAAW,EAAE,CAAC;IACrB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,2BAA2B,2CA+CxE"}
@@ -0,0 +1,26 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../lib/utils";
4
+ /**
5
+ * Horizontal phase stepper for the multi-phase extraction workflow.
6
+ * Hides conditional steps (e.g. "Needs review") unless `visible` is true.
7
+ * Announces review count changes via an `aria-live="polite"` region.
8
+ */
9
+ export function ExtractionPhaseStepper(props) {
10
+ const { steps, currentPhaseKey, reviewCount, className } = props;
11
+ const visible = steps.filter((s) => !s.conditional || s.visible);
12
+ const currentIdx = visible.findIndex((s) => s.key === currentPhaseKey);
13
+ const [lastReviewCount, setLastReviewCount] = React.useState(reviewCount ?? 0);
14
+ const announceRef = React.useRef(null);
15
+ React.useEffect(() => {
16
+ if ((reviewCount ?? 0) > lastReviewCount && announceRef.current) {
17
+ announceRef.current.textContent = `${reviewCount} products need your review`;
18
+ }
19
+ setLastReviewCount(reviewCount ?? 0);
20
+ }, [reviewCount, lastReviewCount]);
21
+ return (_jsxs("ol", { role: "list", "aria-label": "Extraction progress", className: cn("flex flex-wrap gap-2", className), children: [visible.map((s, i) => {
22
+ const state = i < currentIdx ? "done" : i === currentIdx ? "current" : "pending";
23
+ return (_jsx("li", { "aria-current": state === "current" ? "step" : undefined, className: cn("rounded px-3 py-1 text-xs font-semibold", state === "done" && "bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-100", state === "current" && "bg-indigo-600 text-white dark:bg-indigo-500", state === "pending" && "bg-gray-100 text-gray-500 dark:bg-gray-800 dark:text-gray-400"), children: s.label }, s.key));
24
+ }), _jsx("span", { ref: announceRef, className: "sr-only", "aria-live": "polite", "aria-atomic": "true" })] }));
25
+ }
26
+ //# sourceMappingURL=extraction-phase-stepper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-phase-stepper.js","sourceRoot":"","sources":["../../src/components/extraction-phase-stepper.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAgBlC;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAkC;IACvE,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAEjE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,eAAe,CAAC,CAAC;IAEvE,MAAM,CAAC,eAAe,EAAE,kBAAkB,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IAC/E,MAAM,WAAW,GAAG,KAAK,CAAC,MAAM,CAAkB,IAAI,CAAC,CAAC;IAExD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACnB,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC,GAAG,eAAe,IAAI,WAAW,CAAC,OAAO,EAAE,CAAC;YAChE,WAAW,CAAC,OAAO,CAAC,WAAW,GAAG,GAAG,WAAW,4BAA4B,CAAC;QAC/E,CAAC;QACD,kBAAkB,CAAC,WAAW,IAAI,CAAC,CAAC,CAAC;IACvC,CAAC,EAAE,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC,CAAC;IAEnC,OAAO,CACL,cACE,IAAI,EAAC,MAAM,gBACA,qBAAqB,EAChC,SAAS,EAAE,EAAE,CAAC,sBAAsB,EAAE,SAAS,CAAC,aAE/C,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;gBACpB,MAAM,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;gBACjF,OAAO,CACL,6BAEgB,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,EACtD,SAAS,EAAE,EAAE,CACX,yCAAyC,EACzC,KAAK,KAAK,MAAM,IAAI,8EAA8E,EAClG,KAAK,KAAK,SAAS,IAAI,6CAA6C,EACpE,KAAK,KAAK,SAAS,IAAI,+DAA+D,CACvF,YAEA,CAAC,CAAC,KAAK,IATH,CAAC,CAAC,GAAG,CAUP,CACN,CAAC;YACJ,CAAC,CAAC,EACF,eACE,GAAG,EAAE,WAAW,EAChB,SAAS,EAAC,SAAS,eACT,QAAQ,iBACN,MAAM,GAClB,IACC,CACN,CAAC;AACJ,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { StoryObj } from "@storybook/react-vite";
2
+ import { ExtractionPhaseStepper } from "./extraction-phase-stepper";
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof ExtractionPhaseStepper;
6
+ tags: string[];
7
+ parameters: {
8
+ a11y: {
9
+ test: string;
10
+ };
11
+ };
12
+ };
13
+ export default meta;
14
+ type Story = StoryObj<typeof meta>;
15
+ export declare const Running: Story;
16
+ export declare const WithReview: Story;
17
+ export declare const Completed: Story;
18
+ //# sourceMappingURL=extraction-phase-stepper.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-phase-stepper.stories.d.ts","sourceRoot":"","sources":["../../src/components/extraction-phase-stepper.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,QAAA,MAAM,IAAI;;;;;;;;;CAKqC,CAAC;AAEhD,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAYnC,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAMxB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAEvB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import { ExtractionPhaseStepper } from "./extraction-phase-stepper";
2
+ const meta = {
3
+ title: "Extraction/ExtractionPhaseStepper",
4
+ component: ExtractionPhaseStepper,
5
+ tags: ["autodocs"],
6
+ parameters: { a11y: { test: "error" } },
7
+ };
8
+ export default meta;
9
+ const baseSteps = [
10
+ { key: "preflight", label: "Checking file" },
11
+ { key: "classifying", label: "Finding products" },
12
+ { key: "extracting", label: "Extracting details" },
13
+ { key: "verifying", label: "Verifying" },
14
+ { key: "review", label: "Needs review · 3", conditional: true, visible: false },
15
+ { key: "persisting", label: "Saving" },
16
+ { key: "completed", label: "Done" },
17
+ ];
18
+ export const Running = {
19
+ args: { steps: baseSteps, currentPhaseKey: "extracting" },
20
+ };
21
+ export const WithReview = {
22
+ args: {
23
+ steps: baseSteps.map((s) => (s.key === "review" ? { ...s, visible: true } : s)),
24
+ currentPhaseKey: "verifying",
25
+ reviewCount: 3,
26
+ },
27
+ };
28
+ export const Completed = {
29
+ args: { steps: baseSteps, currentPhaseKey: "completed" },
30
+ };
31
+ //# sourceMappingURL=extraction-phase-stepper.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"extraction-phase-stepper.stories.js","sourceRoot":"","sources":["../../src/components/extraction-phase-stepper.stories.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AAEpE,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,mCAAmC;IAC1C,SAAS,EAAE,sBAAsB;IACjC,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;CACM,CAAC;AAEhD,eAAe,IAAI,CAAC;AAGpB,MAAM,SAAS,GAAG;IAChB,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,eAAe,EAAE;IAC5C,EAAE,GAAG,EAAE,aAAa,EAAE,KAAK,EAAE,kBAAkB,EAAE;IACjD,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,oBAAoB,EAAE;IAClD,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE;IACxC,EAAE,GAAG,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,EAAE,WAAW,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE;IAC/E,EAAE,GAAG,EAAE,YAAY,EAAE,KAAK,EAAE,QAAQ,EAAE;IACtC,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE;CACpC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,YAAY,EAAE;CAC1D,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAU;IAC/B,IAAI,EAAE;QACJ,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/E,eAAe,EAAE,WAAW;QAC5B,WAAW,EAAE,CAAC;KACf;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,IAAI,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE;CACzD,CAAC"}
@@ -0,0 +1,23 @@
1
+ export type FlaggedFieldKind = "string" | "number" | "enum" | "boolean";
2
+ export interface FlaggedFieldEditorOption {
3
+ id: string;
4
+ label: string;
5
+ }
6
+ export interface FlaggedFieldEditorProps {
7
+ label: string;
8
+ kind: FlaggedFieldKind;
9
+ extractedAs?: unknown;
10
+ reason: string;
11
+ options?: FlaggedFieldEditorOption[];
12
+ onConfirm: (value: unknown) => void;
13
+ onSkip: () => void;
14
+ className?: string;
15
+ }
16
+ /**
17
+ * Inline editor for a flagged extraction field (validation issue surfaced
18
+ * by the extraction pipeline). Renders a kind-appropriate input alongside
19
+ * the reason and confirm/skip controls. Styled with amber tones to signal
20
+ * attention.
21
+ */
22
+ export declare function FlaggedFieldEditor(props: FlaggedFieldEditorProps): import("react/jsx-runtime").JSX.Element;
23
+ //# sourceMappingURL=flagged-field-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flagged-field-editor.d.ts","sourceRoot":"","sources":["../../src/components/flagged-field-editor.tsx"],"names":[],"mappings":"AAGA,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,QAAQ,GAAG,MAAM,GAAG,SAAS,CAAC;AAExE,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,gBAAgB,CAAC;IACvB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,wBAAwB,EAAE,CAAC;IACrC,SAAS,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACpC,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,2CAkFhE"}
@@ -0,0 +1,16 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../lib/utils";
4
+ /**
5
+ * Inline editor for a flagged extraction field (validation issue surfaced
6
+ * by the extraction pipeline). Renders a kind-appropriate input alongside
7
+ * the reason and confirm/skip controls. Styled with amber tones to signal
8
+ * attention.
9
+ */
10
+ export function FlaggedFieldEditor(props) {
11
+ const { label, kind, extractedAs, reason, options, onConfirm, onSkip, className, } = props;
12
+ const [value, setValue] = React.useState(extractedAs ?? "");
13
+ const fieldId = React.useId();
14
+ return (_jsxs("div", { className: cn("rounded border border-amber-300 bg-amber-50 p-3 dark:border-amber-800 dark:bg-amber-950/40", className), children: [_jsxs("label", { className: "block text-xs font-semibold text-amber-900 dark:text-amber-100", htmlFor: fieldId, children: [label, " \u00B7 ", reason] }), kind === "enum" && options ? (_jsxs("select", { id: fieldId, value: String(value ?? ""), onChange: (e) => setValue(e.target.value), className: "mt-1 w-full rounded border border-gray-300 bg-white px-2 py-1 text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100", children: [_jsx("option", { value: "", children: "Pick one\u2026" }), options.map((o) => (_jsx("option", { value: o.id, children: o.label }, o.id)))] })) : kind === "boolean" ? (_jsxs("select", { id: fieldId, value: String(value), onChange: (e) => setValue(e.target.value === "true"), className: "mt-1 w-full rounded border border-gray-300 bg-white px-2 py-1 text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100", children: [_jsx("option", { value: "", children: "\u2014" }), _jsx("option", { value: "true", children: "Yes" }), _jsx("option", { value: "false", children: "No" })] })) : (_jsx("input", { id: fieldId, type: kind === "number" ? "number" : "text", value: String(value ?? ""), onChange: (e) => setValue(kind === "number" ? Number(e.target.value) : e.target.value), className: "mt-1 w-full rounded border border-gray-300 bg-white px-2 py-1 text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100" })), _jsxs("div", { className: "mt-2 flex gap-2", children: [_jsx("button", { type: "button", onClick: () => onConfirm(value), className: "rounded bg-indigo-600 px-3 py-1 text-xs font-semibold text-white hover:bg-indigo-700 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-indigo-400", children: "Confirm" }), _jsx("button", { type: "button", onClick: onSkip, className: "rounded bg-transparent px-3 py-1 text-xs font-semibold text-gray-700 hover:bg-gray-100 focus:outline focus:outline-2 focus:outline-offset-2 focus:outline-gray-400 dark:text-gray-300 dark:hover:bg-gray-800", children: "Skip for now" })] })] }));
15
+ }
16
+ //# sourceMappingURL=flagged-field-editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flagged-field-editor.js","sourceRoot":"","sources":["../../src/components/flagged-field-editor.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAoBlC;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAA8B;IAC/D,MAAM,EACJ,KAAK,EACL,IAAI,EACJ,WAAW,EACX,MAAM,EACN,OAAO,EACP,SAAS,EACT,MAAM,EACN,SAAS,GACV,GAAG,KAAK,CAAC;IAEV,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAU,WAAW,IAAI,EAAE,CAAC,CAAC;IACrE,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;IAE9B,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,4FAA4F,EAC5F,SAAS,CACV,aAED,iBACE,SAAS,EAAC,gEAAgE,EAC1E,OAAO,EAAE,OAAO,aAEf,KAAK,cAAK,MAAM,IACX,EACP,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAC5B,kBACE,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EACzC,SAAS,EAAC,8IAA8I,aAExJ,iBAAQ,KAAK,EAAC,EAAE,+BAAmB,EAClC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAClB,iBAAmB,KAAK,EAAE,CAAC,CAAC,EAAE,YAC3B,CAAC,CAAC,KAAK,IADG,CAAC,CAAC,EAAE,CAER,CACV,CAAC,IACK,CACV,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CACvB,kBACE,EAAE,EAAE,OAAO,EACX,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,EACpB,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,MAAM,CAAC,EACpD,SAAS,EAAC,8IAA8I,aAExJ,iBAAQ,KAAK,EAAC,EAAE,uBAAW,EAC3B,iBAAQ,KAAK,EAAC,MAAM,oBAAa,EACjC,iBAAQ,KAAK,EAAC,OAAO,mBAAY,IAC1B,CACV,CAAC,CAAC,CAAC,CACF,gBACE,EAAE,EAAE,OAAO,EACX,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,EAC3C,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAC1B,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CACd,QAAQ,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAEvE,SAAS,EAAC,8IAA8I,GACxJ,CACH,EACD,eAAK,SAAS,EAAC,iBAAiB,aAC9B,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAC/B,SAAS,EAAC,oKAAoK,wBAGvK,EACT,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,MAAM,EACf,SAAS,EAAC,8MAA8M,6BAGjN,IACL,IACF,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,27 @@
1
+ import type { StoryObj } from "@storybook/react-vite";
2
+ import { FlaggedFieldEditor } from "./flagged-field-editor";
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof FlaggedFieldEditor;
6
+ tags: string[];
7
+ parameters: {
8
+ a11y: {
9
+ test: string;
10
+ };
11
+ };
12
+ argTypes: {
13
+ onConfirm: {
14
+ action: string;
15
+ };
16
+ onSkip: {
17
+ action: string;
18
+ };
19
+ };
20
+ };
21
+ export default meta;
22
+ type Story = StoryObj<typeof meta>;
23
+ export declare const StringField: Story;
24
+ export declare const NumberField: Story;
25
+ export declare const EnumField: Story;
26
+ export declare const BooleanField: Story;
27
+ //# sourceMappingURL=flagged-field-editor.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flagged-field-editor.stories.d.ts","sourceRoot":"","sources":["../../src/components/flagged-field-editor.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAI5D,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;CASiC,CAAC;AAE5C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,WAAW,EAAE,KASzB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KASzB,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAevB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAS1B,CAAC"}
@@ -0,0 +1,60 @@
1
+ import { FlaggedFieldEditor } from "./flagged-field-editor";
2
+ const noop = () => { };
3
+ const meta = {
4
+ title: "Extraction/FlaggedFieldEditor",
5
+ component: FlaggedFieldEditor,
6
+ tags: ["autodocs"],
7
+ parameters: { a11y: { test: "error" } },
8
+ argTypes: {
9
+ onConfirm: { action: "confirm" },
10
+ onSkip: { action: "skip" },
11
+ },
12
+ };
13
+ export default meta;
14
+ export const StringField = {
15
+ args: {
16
+ label: "Producer",
17
+ kind: "string",
18
+ reason: "Low confidence",
19
+ extractedAs: "Tenuta Sample",
20
+ onConfirm: noop,
21
+ onSkip: noop,
22
+ },
23
+ };
24
+ export const NumberField = {
25
+ args: {
26
+ label: "ABV",
27
+ kind: "number",
28
+ reason: "Outside expected range",
29
+ extractedAs: 14.5,
30
+ onConfirm: noop,
31
+ onSkip: noop,
32
+ },
33
+ };
34
+ export const EnumField = {
35
+ args: {
36
+ label: "Category",
37
+ kind: "enum",
38
+ reason: "Ambiguous category",
39
+ extractedAs: "",
40
+ options: [
41
+ { id: "wine", label: "Wine" },
42
+ { id: "beer", label: "Beer" },
43
+ { id: "spirits", label: "Spirits" },
44
+ { id: "cider", label: "Cider" },
45
+ ],
46
+ onConfirm: noop,
47
+ onSkip: noop,
48
+ },
49
+ };
50
+ export const BooleanField = {
51
+ args: {
52
+ label: "Organic",
53
+ kind: "boolean",
54
+ reason: "Not detected clearly in source",
55
+ extractedAs: false,
56
+ onConfirm: noop,
57
+ onSkip: noop,
58
+ },
59
+ };
60
+ //# sourceMappingURL=flagged-field-editor.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flagged-field-editor.stories.js","sourceRoot":"","sources":["../../src/components/flagged-field-editor.stories.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAC;AAEtB,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,+BAA+B;IACtC,SAAS,EAAE,kBAAkB;IAC7B,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE;IACvC,QAAQ,EAAE;QACR,SAAS,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE;QAChC,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;KAC3B;CACwC,CAAC;AAE5C,eAAe,IAAI,CAAC;AAGpB,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,IAAI,EAAE;QACJ,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,gBAAgB;QACxB,WAAW,EAAE,eAAe;QAC5B,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAU;IAChC,IAAI,EAAE;QACJ,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,QAAQ;QACd,MAAM,EAAE,wBAAwB;QAChC,WAAW,EAAE,IAAI;QACjB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAU;IAC9B,IAAI,EAAE;QACJ,KAAK,EAAE,UAAU;QACjB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,oBAAoB;QAC5B,WAAW,EAAE,EAAE;QACf,OAAO,EAAE;YACP,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC7B,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE;YAC7B,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,SAAS,EAAE;YACnC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;SAChC;QACD,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,IAAI,EAAE;QACJ,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,gCAAgC;QACxC,WAAW,EAAE,KAAK;QAClB,SAAS,EAAE,IAAI;QACf,MAAM,EAAE,IAAI;KACb;CACF,CAAC"}