@cellarnode/ui 0.8.6 → 0.8.8

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 (59) hide show
  1. package/dist/components/attachment-row.d.ts +23 -0
  2. package/dist/components/attachment-row.d.ts.map +1 -0
  3. package/dist/components/attachment-row.js +61 -0
  4. package/dist/components/attachment-row.js.map +1 -0
  5. package/dist/components/attachment-row.stories.d.ts +9 -0
  6. package/dist/components/attachment-row.stories.d.ts.map +1 -0
  7. package/dist/components/attachment-row.stories.js +65 -0
  8. package/dist/components/attachment-row.stories.js.map +1 -0
  9. package/dist/components/certification-upload-card.d.ts +19 -0
  10. package/dist/components/certification-upload-card.d.ts.map +1 -0
  11. package/dist/components/certification-upload-card.js +74 -0
  12. package/dist/components/certification-upload-card.js.map +1 -0
  13. package/dist/components/certification-upload-card.stories.d.ts +9 -0
  14. package/dist/components/certification-upload-card.stories.d.ts.map +1 -0
  15. package/dist/components/certification-upload-card.stories.js +44 -0
  16. package/dist/components/certification-upload-card.stories.js.map +1 -0
  17. package/dist/components/confirmation-dialog.d.ts.map +1 -1
  18. package/dist/components/confirmation-dialog.js +1 -0
  19. package/dist/components/confirmation-dialog.js.map +1 -1
  20. package/dist/components/contact-person-select.d.ts +16 -0
  21. package/dist/components/contact-person-select.d.ts.map +1 -0
  22. package/dist/components/contact-person-select.js +19 -0
  23. package/dist/components/contact-person-select.js.map +1 -0
  24. package/dist/components/contact-person-select.stories.d.ts +16 -0
  25. package/dist/components/contact-person-select.stories.d.ts.map +1 -0
  26. package/dist/components/contact-person-select.stories.js +56 -0
  27. package/dist/components/contact-person-select.stories.js.map +1 -0
  28. package/dist/components/price-comparison.d.ts +13 -0
  29. package/dist/components/price-comparison.d.ts.map +1 -0
  30. package/dist/components/price-comparison.js +60 -0
  31. package/dist/components/price-comparison.js.map +1 -0
  32. package/dist/components/price-comparison.stories.d.ts +11 -0
  33. package/dist/components/price-comparison.stories.d.ts.map +1 -0
  34. package/dist/components/price-comparison.stories.js +56 -0
  35. package/dist/components/price-comparison.stories.js.map +1 -0
  36. package/dist/components/stat-card.js +1 -1
  37. package/dist/components/stat-card.js.map +1 -1
  38. package/dist/components/variant-picker-dialog.d.ts.map +1 -1
  39. package/dist/components/variant-picker-dialog.js +1 -0
  40. package/dist/components/variant-picker-dialog.js.map +1 -1
  41. package/dist/globe/globe-canvas.d.ts.map +1 -1
  42. package/dist/globe/globe-canvas.js +1 -0
  43. package/dist/globe/globe-canvas.js.map +1 -1
  44. package/dist/globe/globe-tooltip.d.ts.map +1 -1
  45. package/dist/globe/globe-tooltip.js +58 -18
  46. package/dist/globe/globe-tooltip.js.map +1 -1
  47. package/dist/globe/globe-types.d.ts +4 -0
  48. package/dist/globe/globe-types.d.ts.map +1 -1
  49. package/dist/globe/globe-view.d.ts.map +1 -1
  50. package/dist/globe/globe-view.js +29 -13
  51. package/dist/globe/globe-view.js.map +1 -1
  52. package/dist/index.d.ts +8 -0
  53. package/dist/index.d.ts.map +1 -1
  54. package/dist/index.js +4 -0
  55. package/dist/index.js.map +1 -1
  56. package/dist/org/invite-member-dialog.d.ts.map +1 -1
  57. package/dist/org/invite-member-dialog.js +2 -0
  58. package/dist/org/invite-member-dialog.js.map +1 -1
  59. package/package.json +1 -1
@@ -0,0 +1,23 @@
1
+ export interface AttachmentRowFile {
2
+ id: string;
3
+ fileName: string;
4
+ name?: string | null;
5
+ mimeType: string;
6
+ fileSize: number;
7
+ type?: string;
8
+ }
9
+ export interface AttachmentRowProps {
10
+ file: AttachmentRowFile;
11
+ typeOptions: Array<{
12
+ value: string;
13
+ label: string;
14
+ }>;
15
+ autoAttached?: boolean;
16
+ onRename?: (id: string, newName: string) => void;
17
+ onTypeChange?: (id: string, newType: string) => void;
18
+ onRemove?: (id: string) => void;
19
+ onDownload?: (id: string) => void;
20
+ className?: string;
21
+ }
22
+ export declare function AttachmentRow({ file, typeOptions, autoAttached, onRename, onTypeChange, onRemove, onDownload, className, }: AttachmentRowProps): import("react/jsx-runtime").JSX.Element;
23
+ //# sourceMappingURL=attachment-row.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-row.d.ts","sourceRoot":"","sources":["../../src/components/attachment-row.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,iBAAiB,CAAC;IACxB,WAAW,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjD,YAAY,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAkBD,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,WAAW,EACX,YAAY,EACZ,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,UAAU,EACV,SAAS,GACV,EAAE,kBAAkB,2CA2HpB"}
@@ -0,0 +1,61 @@
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
+ function formatFileSize(bytes) {
5
+ if (bytes < 1024)
6
+ return `${bytes} B`;
7
+ if (bytes < 1024 * 1024)
8
+ return `${Math.round(bytes / 1024)} KB`;
9
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
10
+ }
11
+ function getFileIcon(mimeType) {
12
+ if (mimeType === "application/pdf") {
13
+ return { label: "PDF", bgClass: "bg-red-500/15 text-red-600 dark:bg-red-500/20 dark:text-red-400" };
14
+ }
15
+ if (mimeType.startsWith("image/")) {
16
+ return { label: "IMG", bgClass: "bg-sky-500/15 text-sky-600 dark:bg-sky-500/20 dark:text-sky-400" };
17
+ }
18
+ return { label: "FILE", bgClass: "bg-muted text-muted-foreground" };
19
+ }
20
+ export function AttachmentRow({ file, typeOptions, autoAttached, onRename, onTypeChange, onRemove, onDownload, className, }) {
21
+ const [editing, setEditing] = React.useState(false);
22
+ const [editValue, setEditValue] = React.useState("");
23
+ const inputRef = React.useRef(null);
24
+ const displayName = file.name ?? file.fileName;
25
+ const icon = getFileIcon(file.mimeType);
26
+ React.useEffect(() => {
27
+ if (editing && inputRef.current) {
28
+ inputRef.current.focus();
29
+ inputRef.current.select();
30
+ }
31
+ }, [editing]);
32
+ function startEditing() {
33
+ if (!onRename)
34
+ return;
35
+ setEditValue(displayName);
36
+ setEditing(true);
37
+ }
38
+ function commitEdit() {
39
+ const trimmed = editValue.trim();
40
+ if (trimmed && trimmed !== displayName) {
41
+ onRename?.(file.id, trimmed);
42
+ }
43
+ setEditing(false);
44
+ }
45
+ function cancelEdit() {
46
+ setEditing(false);
47
+ }
48
+ function handleKeyDown(e) {
49
+ if (e.key === "Enter") {
50
+ e.preventDefault();
51
+ commitEdit();
52
+ }
53
+ else if (e.key === "Escape") {
54
+ e.preventDefault();
55
+ cancelEdit();
56
+ }
57
+ }
58
+ return (_jsxs("div", { className: cn("flex items-center gap-3 rounded-xl border border-border bg-background px-3.5 py-2.5", className), children: [_jsx("div", { className: cn("flex size-9 shrink-0 items-center justify-center rounded-lg text-xs font-bold", icon.bgClass), children: icon.label }), _jsxs("div", { className: "min-w-0 flex-1", children: [editing ? (_jsx("input", { ref: inputRef, type: "text", value: editValue, onChange: (e) => setEditValue(e.target.value), onBlur: commitEdit, onKeyDown: handleKeyDown, className: "w-full border-b border-dashed border-primary bg-transparent text-sm font-medium text-foreground outline-none" })) : (_jsx("button", { type: "button", onClick: onRename ? startEditing : onDownload ? () => onDownload(file.id) : undefined, className: cn("truncate text-left text-sm font-medium text-foreground", onRename &&
59
+ "cursor-text border-b border-dashed border-transparent hover:border-primary/40", !onRename && onDownload && "cursor-pointer hover:underline", !onRename && !onDownload && "cursor-default"), children: displayName })), _jsxs("p", { className: "text-[10px] text-muted-foreground", children: [formatFileSize(file.fileSize), autoAttached && (_jsx("span", { className: "ml-1.5", children: "\u00B7 Auto-attached from portfolio" }))] })] }), _jsx("select", { value: file.type ?? "generic", onChange: (e) => onTypeChange?.(file.id, e.target.value), className: "shrink-0 rounded-lg border border-border bg-background px-2 py-1 text-[11px] text-foreground", children: typeOptions.map((opt) => (_jsx("option", { value: opt.value, children: opt.label }, opt.value))) }), onRemove && (_jsx("button", { type: "button", onClick: () => onRemove(file.id), className: "shrink-0 text-sm text-muted-foreground transition-colors hover:text-red-500", "aria-label": "Remove attachment", children: "\u00D7" }))] }));
60
+ }
61
+ //# sourceMappingURL=attachment-row.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-row.js","sourceRoot":"","sources":["../../src/components/attachment-row.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { AttachmentRow } from "./attachment-row";
3
+ declare const meta: Meta<typeof AttachmentRow>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const AutoAttached: Story;
8
+ export declare const WithEditableName: Story;
9
+ //# sourceMappingURL=attachment-row.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-row.stories.d.ts","sourceRoot":"","sources":["../../src/components/attachment-row.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAQjD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,aAAa,CAOpC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAcrB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAe1B,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,KAgB9B,CAAC"}
@@ -0,0 +1,65 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { AttachmentRow } from "./attachment-row";
3
+ const typeOptions = [
4
+ { value: "product_image", label: "Product Image" },
5
+ { value: "technical_sheet", label: "Technical Sheet" },
6
+ { value: "generic", label: "Other Document" },
7
+ ];
8
+ const meta = {
9
+ title: "Components/AttachmentRow",
10
+ component: AttachmentRow,
11
+ tags: ["autodocs"],
12
+ parameters: { layout: "padded" },
13
+ args: { typeOptions },
14
+ decorators: [(Story) => _jsx("div", { className: "max-w-lg", children: _jsx(Story, {}) })],
15
+ };
16
+ export default meta;
17
+ export const Default = {
18
+ args: {
19
+ file: {
20
+ id: "1",
21
+ fileName: "product-spec-2026.pdf",
22
+ mimeType: "application/pdf",
23
+ fileSize: 245_760,
24
+ type: "technical_sheet",
25
+ },
26
+ /* eslint-disable no-console */
27
+ onRemove: (id) => console.log("remove", id),
28
+ onTypeChange: (id, type) => console.log("type change", id, type),
29
+ /* eslint-enable no-console */
30
+ },
31
+ };
32
+ export const AutoAttached = {
33
+ args: {
34
+ file: {
35
+ id: "2",
36
+ fileName: "chateau-reserve-front.jpg",
37
+ mimeType: "image/jpeg",
38
+ fileSize: 1_832_960,
39
+ type: "product_image",
40
+ },
41
+ autoAttached: true,
42
+ /* eslint-disable no-console */
43
+ onRemove: (id) => console.log("remove", id),
44
+ onTypeChange: (id, type) => console.log("type change", id, type),
45
+ /* eslint-enable no-console */
46
+ },
47
+ };
48
+ export const WithEditableName = {
49
+ args: {
50
+ file: {
51
+ id: "3",
52
+ fileName: "compliance-report-final.pdf",
53
+ name: "Compliance Report",
54
+ mimeType: "application/pdf",
55
+ fileSize: 524_288,
56
+ type: "generic",
57
+ },
58
+ /* eslint-disable no-console */
59
+ onRename: (id, name) => console.log("rename", id, name),
60
+ onRemove: (id) => console.log("remove", id),
61
+ onTypeChange: (id, type) => console.log("type change", id, type),
62
+ /* eslint-enable no-console */
63
+ },
64
+ };
65
+ //# sourceMappingURL=attachment-row.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attachment-row.stories.js","sourceRoot":"","sources":["../../src/components/attachment-row.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEjD,MAAM,WAAW,GAAG;IAClB,EAAE,KAAK,EAAE,eAAe,EAAE,KAAK,EAAE,eAAe,EAAE;IAClD,EAAE,KAAK,EAAE,iBAAiB,EAAE,KAAK,EAAE,iBAAiB,EAAE;IACtD,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,gBAAgB,EAAE;CAC9C,CAAC;AAEF,MAAM,IAAI,GAA+B;IACvC,KAAK,EAAE,0BAA0B;IACjC,SAAS,EAAE,aAAa;IACxB,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChC,IAAI,EAAE,EAAE,WAAW,EAAE;IACrB,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAK,SAAS,EAAC,UAAU,YAAC,KAAC,KAAK,KAAG,GAAM,CAAC;CACnE,CAAC;AAEF,eAAe,IAAI,CAAC;AAGpB,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,uBAAuB;YACjC,QAAQ,EAAE,iBAAiB;YAC3B,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,iBAAiB;SACxB;QACD,+BAA+B;QAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3C,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;QAChE,8BAA8B;KAC/B;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,2BAA2B;YACrC,QAAQ,EAAE,YAAY;YACtB,QAAQ,EAAE,SAAS;YACnB,IAAI,EAAE,eAAe;SACtB;QACD,YAAY,EAAE,IAAI;QAClB,+BAA+B;QAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3C,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;QAChE,8BAA8B;KAC/B;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAU;IACrC,IAAI,EAAE;QACJ,IAAI,EAAE;YACJ,EAAE,EAAE,GAAG;YACP,QAAQ,EAAE,6BAA6B;YACvC,IAAI,EAAE,mBAAmB;YACzB,QAAQ,EAAE,iBAAiB;YAC3B,QAAQ,EAAE,OAAO;YACjB,IAAI,EAAE,SAAS;SAChB;QACD,+BAA+B;QAC/B,QAAQ,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,EAAE,IAAI,CAAC;QACvD,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC;QAC3C,YAAY,EAAE,CAAC,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,EAAE,IAAI,CAAC;QAChE,8BAA8B;KAC/B;CACF,CAAC"}
@@ -0,0 +1,19 @@
1
+ import * as React from "react";
2
+ export type CertStatus = "required" | "filled" | "optional";
3
+ export interface CertificationUploadCardProps {
4
+ type: string;
5
+ label: string;
6
+ icon: React.ReactNode;
7
+ status: CertStatus;
8
+ file?: {
9
+ name: string;
10
+ size?: number;
11
+ } | null;
12
+ autoAttached?: boolean;
13
+ onUpload: (file: File) => void;
14
+ onRemove?: () => void;
15
+ onReplace?: () => void;
16
+ className?: string;
17
+ }
18
+ export declare function CertificationUploadCard({ label, icon, status, file, autoAttached, onUpload, onRemove, onReplace, className, }: CertificationUploadCardProps): import("react/jsx-runtime").JSX.Element;
19
+ //# sourceMappingURL=certification-upload-card.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certification-upload-card.d.ts","sourceRoot":"","sources":["../../src/components/certification-upload-card.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,MAAM,MAAM,UAAU,GAAG,UAAU,GAAG,QAAQ,GAAG,UAAU,CAAC;AAE5D,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,KAAK,CAAC,SAAS,CAAC;IACtB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAC9C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAuCD,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,YAAY,EACZ,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,SAAS,GACV,EAAE,4BAA4B,2CA4J9B"}
@@ -0,0 +1,74 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../lib/utils";
4
+ const ACCEPTED_TYPES = ".pdf,.jpg,.jpeg,.png,.webp";
5
+ const containerStyles = {
6
+ filled: "border border-emerald-200 bg-emerald-50/60 dark:border-emerald-500/20 dark:bg-emerald-950/20",
7
+ required: "border border-dashed border-amber-300 bg-amber-50/40 dark:border-amber-500/20 dark:bg-amber-950/20",
8
+ optional: "border border-dashed border-border/60 bg-muted/30 opacity-70",
9
+ };
10
+ const iconStyles = {
11
+ filled: "bg-emerald-100 text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-300",
12
+ required: "bg-amber-100 text-amber-700 dark:bg-amber-900/40 dark:text-amber-300",
13
+ optional: "bg-muted text-muted-foreground",
14
+ };
15
+ const labelStyles = {
16
+ filled: "text-emerald-700 dark:text-emerald-300",
17
+ required: "text-amber-700 dark:text-amber-300",
18
+ optional: "text-muted-foreground",
19
+ };
20
+ const dropZoneBorderStyles = {
21
+ required: "border-amber-300 text-amber-700 hover:bg-amber-50 dark:border-amber-500/30 dark:text-amber-300 dark:hover:bg-amber-950/30",
22
+ optional: "border-border/60 text-muted-foreground hover:bg-muted/40 dark:hover:bg-muted/20",
23
+ };
24
+ function formatFileSize(bytes) {
25
+ if (bytes < 1024)
26
+ return `${bytes} B`;
27
+ if (bytes < 1024 * 1024)
28
+ return `${(bytes / 1024).toFixed(1)} KB`;
29
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
30
+ }
31
+ export function CertificationUploadCard({ label, icon, status, file, autoAttached, onUpload, onRemove, onReplace, className, }) {
32
+ const inputRef = React.useRef(null);
33
+ const [dragOver, setDragOver] = React.useState(false);
34
+ const handleFileChange = (e) => {
35
+ const selected = e.target.files?.[0];
36
+ if (selected) {
37
+ onUpload(selected);
38
+ // Reset input so the same file can be re-selected
39
+ e.target.value = "";
40
+ }
41
+ };
42
+ const handleDragOver = (e) => {
43
+ e.preventDefault();
44
+ e.stopPropagation();
45
+ setDragOver(true);
46
+ };
47
+ const handleDragLeave = (e) => {
48
+ e.preventDefault();
49
+ e.stopPropagation();
50
+ setDragOver(false);
51
+ };
52
+ const handleDrop = (e) => {
53
+ e.preventDefault();
54
+ e.stopPropagation();
55
+ setDragOver(false);
56
+ const droppedFile = e.dataTransfer.files[0];
57
+ if (droppedFile) {
58
+ onUpload(droppedFile);
59
+ }
60
+ };
61
+ const handleDropZoneClick = () => {
62
+ inputRef.current?.click();
63
+ };
64
+ const handleReplaceClick = () => {
65
+ if (onReplace) {
66
+ onReplace();
67
+ }
68
+ else {
69
+ inputRef.current?.click();
70
+ }
71
+ };
72
+ return (_jsxs("div", { className: cn("relative flex flex-col items-center rounded-xl p-4 text-center transition-all", containerStyles[status], dragOver && "ring-2 ring-primary/40", className), onDragOver: handleDragOver, onDragLeave: handleDragLeave, onDrop: handleDrop, children: [status === "filled" && autoAttached && (_jsx("span", { className: "absolute -top-2 right-2 rounded-full bg-emerald-600 px-2 py-0.5 text-[9px] font-bold text-white", children: "AUTO" })), _jsx("div", { className: cn("mb-2 flex size-9 items-center justify-center rounded-lg", iconStyles[status]), children: icon }), _jsx("span", { className: cn("text-[11px] font-bold uppercase tracking-[0.06em]", labelStyles[status]), children: label }), status === "filled" && file ? (_jsxs("div", { className: "mt-2 w-full", children: [_jsxs("div", { className: "inline-flex items-center gap-1.5 rounded-full bg-emerald-100/80 px-2.5 py-1 dark:bg-emerald-900/30", children: [_jsx("span", { className: "max-w-[120px] truncate text-[11px] font-medium text-emerald-800 dark:text-emerald-200", children: file.name }), file.size != null && (_jsx("span", { className: "text-[10px] text-emerald-600 dark:text-emerald-400", children: formatFileSize(file.size) }))] }), _jsxs("div", { className: "mt-1.5 flex items-center justify-center gap-2", children: [_jsx("button", { type: "button", onClick: handleReplaceClick, className: "text-[10px] font-medium text-emerald-700 underline-offset-2 hover:underline dark:text-emerald-300", children: "Replace" }), onRemove && (_jsxs(_Fragment, { children: [_jsx("span", { className: "text-emerald-300 dark:text-emerald-700", children: "|" }), _jsx("button", { type: "button", onClick: onRemove, className: "text-[10px] font-medium text-red-600 underline-offset-2 hover:underline dark:text-red-400", children: "Remove" })] }))] })] })) : (_jsxs("div", { className: "mt-2 w-full", children: [status === "required" && (_jsx("p", { className: "mb-1.5 text-[10px] text-amber-600 dark:text-amber-400", children: "Required \u00B7 Not uploaded" })), _jsx("button", { type: "button", onClick: handleDropZoneClick, className: cn("w-full cursor-pointer rounded-lg border border-dashed px-3 py-1.5 text-[11px] font-medium transition-colors", dropZoneBorderStyles[status === "required" ? "required" : "optional"]), children: "Drop file or click" })] })), _jsx("input", { ref: inputRef, type: "file", accept: ACCEPTED_TYPES, className: "hidden", onChange: handleFileChange, tabIndex: -1 })] }));
73
+ }
74
+ //# sourceMappingURL=certification-upload-card.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certification-upload-card.js","sourceRoot":"","sources":["../../src/components/certification-upload-card.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { Meta, StoryObj } from "@storybook/react-vite";
2
+ import { CertificationUploadCard } from "./certification-upload-card";
3
+ declare const meta: Meta<typeof CertificationUploadCard>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Required: Story;
7
+ export declare const Filled: Story;
8
+ export declare const Optional: Story;
9
+ //# sourceMappingURL=certification-upload-card.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certification-upload-card.stories.d.ts","sourceRoot":"","sources":["../../src/components/certification-upload-card.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,uBAAuB,CAM9C,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAmBnC,eAAO,MAAM,QAAQ,EAAE,KAQtB,CAAC;AAEF,eAAO,MAAM,MAAM,EAAE,KAYpB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAQtB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { CertificationUploadCard } from "./certification-upload-card";
3
+ const meta = {
4
+ title: "Components/CertificationUploadCard",
5
+ component: CertificationUploadCard,
6
+ tags: ["autodocs"],
7
+ parameters: { layout: "padded" },
8
+ decorators: [(Story) => _jsx("div", { className: "w-48", children: _jsx(Story, {}) })],
9
+ };
10
+ export default meta;
11
+ /** Inline leaf icon — avoids importing lucide into the ui package */
12
+ const LeafIcon = () => (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", className: "size-5", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 1.5, strokeLinecap: "round", strokeLinejoin: "round", children: [_jsx("path", { d: "M11 20A7 7 0 0 1 9.8 6.9C15.5 4.9 17 3.5 19 2c1 2 2 4.5 2 8 0 5.5-4.78 10-10 10Z" }), _jsx("path", { d: "M2 21c0-3 1.85-5.36 5.08-6C9.5 14.52 12 13 13 12" })] }));
13
+ export const Required = {
14
+ args: {
15
+ type: "organic",
16
+ label: "Organic",
17
+ icon: _jsx(LeafIcon, {}),
18
+ status: "required",
19
+ onUpload: (file) => console.warn("Upload:", file.name),
20
+ },
21
+ };
22
+ export const Filled = {
23
+ args: {
24
+ type: "organic",
25
+ label: "Organic",
26
+ icon: _jsx(LeafIcon, {}),
27
+ status: "filled",
28
+ file: { name: "organic-cert-2026.pdf", size: 245_000 },
29
+ autoAttached: true,
30
+ onUpload: (file) => console.warn("Upload:", file.name),
31
+ onRemove: () => console.warn("Remove"),
32
+ onReplace: () => console.warn("Replace"),
33
+ },
34
+ };
35
+ export const Optional = {
36
+ args: {
37
+ type: "sustainable",
38
+ label: "Sustainable",
39
+ icon: _jsx(LeafIcon, {}),
40
+ status: "optional",
41
+ onUpload: (file) => console.warn("Upload:", file.name),
42
+ },
43
+ };
44
+ //# sourceMappingURL=certification-upload-card.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"certification-upload-card.stories.js","sourceRoot":"","sources":["../../src/components/certification-upload-card.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAEtE,MAAM,IAAI,GAAyC;IACjD,KAAK,EAAE,oCAAoC;IAC3C,SAAS,EAAE,uBAAuB;IAClC,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE;IAChC,UAAU,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,cAAK,SAAS,EAAC,MAAM,YAAC,KAAC,KAAK,KAAG,GAAM,CAAC;CAC/D,CAAC;AAEF,eAAe,IAAI,CAAC;AAGpB,qEAAqE;AACrE,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,CACrB,eACE,KAAK,EAAC,4BAA4B,EAClC,SAAS,EAAC,QAAQ,EAClB,OAAO,EAAC,WAAW,EACnB,IAAI,EAAC,MAAM,EACX,MAAM,EAAC,cAAc,EACrB,WAAW,EAAE,GAAG,EAChB,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,aAEtB,eAAM,CAAC,EAAC,kFAAkF,GAAG,EAC7F,eAAM,CAAC,EAAC,kDAAkD,GAAG,IACzD,CACP,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAU;IAC7B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,KAAC,QAAQ,KAAG;QAClB,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;KAC7D;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,MAAM,GAAU;IAC3B,IAAI,EAAE;QACJ,IAAI,EAAE,SAAS;QACf,KAAK,EAAE,SAAS;QAChB,IAAI,EAAE,KAAC,QAAQ,KAAG;QAClB,MAAM,EAAE,QAAQ;QAChB,IAAI,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,OAAO,EAAE;QACtD,YAAY,EAAE,IAAI;QAClB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;QAC5D,QAAQ,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC;QACtC,SAAS,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC;KACzC;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,QAAQ,GAAU;IAC7B,IAAI,EAAE;QACJ,IAAI,EAAE,aAAa;QACnB,KAAK,EAAE,aAAa;QACpB,IAAI,EAAE,KAAC,QAAQ,KAAG;QAClB,MAAM,EAAE,UAAU;QAClB,QAAQ,EAAE,CAAC,IAAU,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,IAAI,CAAC;KAC7D;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"confirmation-dialog.d.ts","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2FAA2F;IAC3F,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,wFAAwF;IACxF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AA8FD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,OAAO,EACP,IAAe,EACf,IAAI,EACJ,YAAwB,EACxB,WAAsB,EACtB,SAAS,EAAE,eAAuB,EAClC,QAAQ,GACT,EAAE,uBAAuB,2CAuEzB"}
1
+ {"version":3,"file":"confirmation-dialog.d.ts","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAQ/B,MAAM,MAAM,sBAAsB,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAC;AAEnE,MAAM,WAAW,uBAAuB;IACtC,kCAAkC;IAClC,IAAI,EAAE,OAAO,CAAC;IACd,0EAA0E;IAC1E,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,2FAA2F;IAC3F,SAAS,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEtC,uCAAuC;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,sBAAsB,CAAC;IAC9B,wFAAwF;IACxF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,uDAAuD;IACvD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,qDAAqD;IACrD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,uFAAuF;IACvF,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B;AA8FD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,OAAO,EACP,SAAS,EACT,KAAK,EACL,WAAW,EACX,OAAO,EACP,IAAe,EACf,IAAI,EACJ,YAAwB,EACxB,WAAsB,EACtB,SAAS,EAAE,eAAuB,EAClC,QAAQ,GACT,EAAE,uBAAuB,2CAwEzB"}
@@ -62,6 +62,7 @@ export function ConfirmationDialog({ open, onClose, onConfirm, title, descriptio
62
62
  };
63
63
  // Reset submitting state when dialog closes
64
64
  React.useEffect(() => {
65
+ // eslint-disable-next-line @eslint-react/set-state-in-effect -- intentional reset on prop change
65
66
  if (!open)
66
67
  setSubmitting(false);
67
68
  }, [open]);
@@ -1 +1 @@
1
- {"version":3,"file":"confirmation-dialog.js","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"confirmation-dialog.js","sourceRoot":"","sources":["../../src/components/confirmation-dialog.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ export interface ContactPerson {
2
+ id: string;
3
+ name?: string | null;
4
+ email?: string | null;
5
+ role?: string | null;
6
+ }
7
+ export interface ContactPersonSelectProps {
8
+ members: ContactPerson[];
9
+ selectedId: string | null;
10
+ onSelect: (id: string) => void;
11
+ label?: string;
12
+ placeholder?: string;
13
+ className?: string;
14
+ }
15
+ export declare function ContactPersonSelect({ members, selectedId, onSelect, label, placeholder, className, }: ContactPersonSelectProps): import("react/jsx-runtime").JSX.Element;
16
+ //# sourceMappingURL=contact-person-select.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-person-select.d.ts","sourceRoot":"","sources":["../../src/components/contact-person-select.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,aAAa,EAAE,CAAC;IACzB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,UAAU,EACV,QAAQ,EACR,KAAwB,EACxB,WAAmC,EACnC,SAAS,GACV,EAAE,wBAAwB,2CA2F1B"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { cn } from "../lib/utils";
3
+ function getInitials(name, email) {
4
+ if (name) {
5
+ const parts = name.split(/\s+/).filter(Boolean);
6
+ if (parts.length >= 2)
7
+ return `${parts[0][0]}${parts[1][0]}`.toUpperCase();
8
+ return parts[0]?.[0]?.toUpperCase() ?? "?";
9
+ }
10
+ return email?.[0]?.toUpperCase() ?? "?";
11
+ }
12
+ export function ContactPersonSelect({ members, selectedId, onSelect, label = "Contact Person", placeholder = "Select a contact...", className, }) {
13
+ const selected = members.find((m) => m.id === selectedId) ?? null;
14
+ function handleChange(e) {
15
+ onSelect(e.target.value);
16
+ }
17
+ return (_jsxs("div", { className: cn("relative", className), children: [_jsxs("span", { className: "mb-1.5 block text-[11px] font-semibold text-foreground", children: [label, _jsx("span", { className: "ml-0.5 text-red-500", children: "*" })] }), _jsxs("div", { className: "relative", children: [_jsxs("select", { value: selectedId ?? "", onChange: handleChange, className: "peer absolute inset-0 cursor-pointer opacity-0", "aria-label": label, children: [_jsx("option", { value: "", disabled: true, children: placeholder }), members.map((m) => (_jsxs("option", { value: m.id, children: [m.name ?? m.email ?? m.id, m.role ? ` - ${m.role}` : ""] }, m.id)))] }), _jsxs("div", { className: cn("flex items-center gap-2.5 rounded-xl border border-border bg-background px-3.5 py-2.5", "pointer-events-none peer-focus:ring-2 peer-focus:ring-ring peer-focus:ring-offset-1"), children: [_jsx("div", { className: "flex size-8 shrink-0 items-center justify-center rounded-lg bg-primary/10 text-xs font-bold text-primary", children: selected ? getInitials(selected.name, selected.email) : "?" }), _jsx("div", { className: "min-w-0 flex-1", children: selected ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "truncate text-sm font-semibold text-foreground", children: selected.name ?? selected.email ?? selected.id }), selected.role && (_jsx("div", { className: "truncate text-[11px] text-muted-foreground", children: selected.role }))] })) : (_jsx("div", { className: "truncate text-sm text-muted-foreground", children: placeholder })) }), _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 20 20", fill: "currentColor", className: "size-4 shrink-0 text-muted-foreground", children: _jsx("path", { fillRule: "evenodd", d: "M5.22 8.22a.75.75 0 0 1 1.06 0L10 11.94l3.72-3.72a.75.75 0 1 1 1.06 1.06l-4.25 4.25a.75.75 0 0 1-1.06 0L5.22 9.28a.75.75 0 0 1 0-1.06Z", clipRule: "evenodd" }) })] })] }), selected?.email && (_jsx("p", { className: "mt-1 text-[10px] text-muted-foreground", children: selected.email }))] }));
18
+ }
19
+ //# sourceMappingURL=contact-person-select.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-person-select.js","sourceRoot":"","sources":["../../src/components/contact-person-select.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { StoryObj } from "@storybook/react-vite";
2
+ import { ContactPersonSelect } from "./contact-person-select";
3
+ declare const meta: {
4
+ title: string;
5
+ component: typeof ContactPersonSelect;
6
+ tags: string[];
7
+ parameters: {
8
+ layout: string;
9
+ };
10
+ };
11
+ export default meta;
12
+ type Story = StoryObj<typeof meta>;
13
+ export declare const Default: Story;
14
+ export declare const WithNoRole: Story;
15
+ export declare const EmptyMembers: Story;
16
+ //# sourceMappingURL=contact-person-select.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-person-select.stories.d.ts","sourceRoot":"","sources":["../../src/components/contact-person-select.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EACL,mBAAmB,EAEpB,MAAM,yBAAyB,CAAC;AAuBjC,QAAA,MAAM,IAAI;;;;;;;CAKkC,CAAC;AAE7C,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAsBnC,eAAO,MAAM,OAAO,EAAE,KAGrB,CAAC;AAgBF,eAAO,MAAM,UAAU,EAAE,KAGxB,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAW1B,CAAC"}
@@ -0,0 +1,56 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { ContactPersonSelect, } from "./contact-person-select";
4
+ const MOCK_MEMBERS = [
5
+ {
6
+ id: "1",
7
+ name: "Marcus Lindgren",
8
+ email: "marcus@marcuswines.se",
9
+ role: "Export Manager",
10
+ },
11
+ {
12
+ id: "2",
13
+ name: "Sofia Andersson",
14
+ email: "sofia@marcuswines.se",
15
+ role: "Sales Director",
16
+ },
17
+ {
18
+ id: "3",
19
+ name: "Erik Johansson",
20
+ email: "erik@marcuswines.se",
21
+ role: null,
22
+ },
23
+ ];
24
+ const meta = {
25
+ title: "Components/ContactPersonSelect",
26
+ component: ContactPersonSelect,
27
+ tags: ["autodocs"],
28
+ parameters: { layout: "centered" },
29
+ };
30
+ export default meta;
31
+ const stubArgs = {
32
+ members: MOCK_MEMBERS,
33
+ selectedId: null,
34
+ onSelect: () => { },
35
+ };
36
+ function DefaultRender() {
37
+ const [selectedId, setSelectedId] = useState("1");
38
+ return (_jsx("div", { className: "w-full max-w-xs", children: _jsx(ContactPersonSelect, { members: MOCK_MEMBERS, selectedId: selectedId, onSelect: setSelectedId }) }));
39
+ }
40
+ export const Default = {
41
+ args: stubArgs,
42
+ render: () => _jsx(DefaultRender, {}),
43
+ };
44
+ function WithNoRoleRender() {
45
+ const [selectedId, setSelectedId] = useState("3");
46
+ return (_jsx("div", { className: "w-full max-w-xs", children: _jsx(ContactPersonSelect, { members: MOCK_MEMBERS, selectedId: selectedId, onSelect: setSelectedId }) }));
47
+ }
48
+ export const WithNoRole = {
49
+ args: stubArgs,
50
+ render: () => _jsx(WithNoRoleRender, {}),
51
+ };
52
+ export const EmptyMembers = {
53
+ args: stubArgs,
54
+ render: () => (_jsx("div", { className: "w-full max-w-xs", children: _jsx(ContactPersonSelect, { members: [], selectedId: null, onSelect: () => { } }) })),
55
+ };
56
+ //# sourceMappingURL=contact-person-select.stories.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contact-person-select.stories.js","sourceRoot":"","sources":["../../src/components/contact-person-select.stories.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EACL,mBAAmB,GAEpB,MAAM,yBAAyB,CAAC;AAEjC,MAAM,YAAY,GAAoB;IACpC;QACE,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,uBAAuB;QAC9B,IAAI,EAAE,gBAAgB;KACvB;IACD;QACE,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,sBAAsB;QAC7B,IAAI,EAAE,gBAAgB;KACvB;IACD;QACE,EAAE,EAAE,GAAG;QACP,IAAI,EAAE,gBAAgB;QACtB,KAAK,EAAE,qBAAqB;QAC5B,IAAI,EAAE,IAAI;KACX;CACF,CAAC;AAEF,MAAM,IAAI,GAAG;IACX,KAAK,EAAE,gCAAgC;IACvC,SAAS,EAAE,mBAAmB;IAC9B,IAAI,EAAE,CAAC,UAAU,CAAC;IAClB,UAAU,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE;CACQ,CAAC;AAE7C,eAAe,IAAI,CAAC;AAGpB,MAAM,QAAQ,GAAG;IACf,OAAO,EAAE,YAAY;IACrB,UAAU,EAAE,IAAI;IAChB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC;CACnB,CAAC;AAEF,SAAS,aAAa;IACpB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,GAAG,CAAC,CAAC;IAEjE,OAAO,CACL,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,mBAAmB,IAClB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,GACvB,GACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,OAAO,GAAU;IAC5B,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,KAAC,aAAa,KAAG;CAChC,CAAC;AAEF,SAAS,gBAAgB;IACvB,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAgB,GAAG,CAAC,CAAC;IAEjE,OAAO,CACL,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,mBAAmB,IAClB,OAAO,EAAE,YAAY,EACrB,UAAU,EAAE,UAAU,EACtB,QAAQ,EAAE,aAAa,GACvB,GACE,CACP,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,UAAU,GAAU;IAC/B,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,KAAC,gBAAgB,KAAG;CACnC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAU;IACjC,IAAI,EAAE,QAAQ;IACd,MAAM,EAAE,GAAG,EAAE,CAAC,CACZ,cAAK,SAAS,EAAC,iBAAiB,YAC9B,KAAC,mBAAmB,IAClB,OAAO,EAAE,EAAE,EACX,UAAU,EAAE,IAAI,EAChB,QAAQ,EAAE,GAAG,EAAE,GAAE,CAAC,GAClB,GACE,CACP;CACF,CAAC"}
@@ -0,0 +1,13 @@
1
+ export interface PriceComparisonProps {
2
+ targetPrice: number | string | null;
3
+ targetLabel?: string;
4
+ targetSubLabel?: string;
5
+ currency?: string;
6
+ offeredPrice: string;
7
+ onPriceChange: (value: string) => void;
8
+ offeredLabel?: string;
9
+ offeredHint?: string;
10
+ className?: string;
11
+ }
12
+ export declare function PriceComparison({ targetPrice, targetLabel, targetSubLabel, currency, offeredPrice, onPriceChange, offeredLabel, offeredHint, className, }: PriceComparisonProps): import("react/jsx-runtime").JSX.Element;
13
+ //# sourceMappingURL=price-comparison.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"price-comparison.d.ts","sourceRoot":"","sources":["../../src/components/price-comparison.tsx"],"names":[],"mappings":"AAGA,MAAM,WAAW,oBAAoB;IACnC,WAAW,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA8DD,wBAAgB,eAAe,CAAC,EAC9B,WAAW,EACX,WAAoC,EACpC,cAAc,EACd,QAAgB,EAChB,YAAY,EACZ,aAAa,EACb,YAAmC,EACnC,WAA8C,EAC9C,SAAS,GACV,EAAE,oBAAoB,2CAoEtB"}
@@ -0,0 +1,60 @@
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
+ function formatPrice(value, currency) {
5
+ return `${value.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${currency}`;
6
+ }
7
+ function computeDelta(target, offered, currency) {
8
+ if (target === 0)
9
+ return null;
10
+ const diff = offered - target;
11
+ const pct = Math.abs((diff / target) * 100);
12
+ const absDiff = Math.abs(diff).toFixed(2);
13
+ if (diff === 0) {
14
+ return { diff: 0, pct: 0, tone: "emerald", label: "At target price" };
15
+ }
16
+ if (diff < 0) {
17
+ return {
18
+ diff,
19
+ pct,
20
+ tone: "emerald",
21
+ label: `▼ ${absDiff} ${currency} below target (${pct.toFixed(0)}%) — Competitive`,
22
+ };
23
+ }
24
+ if (pct > 15) {
25
+ return {
26
+ diff,
27
+ pct,
28
+ tone: "red",
29
+ label: `▲ ${absDiff} ${currency} above target (${pct.toFixed(0)}%) — Above range`,
30
+ };
31
+ }
32
+ return {
33
+ diff,
34
+ pct,
35
+ tone: "amber",
36
+ label: `▲ ${absDiff} ${currency} above target (${pct.toFixed(0)}%)`,
37
+ };
38
+ }
39
+ const deltaClasses = {
40
+ emerald: "border-emerald-200 bg-emerald-50/60 text-emerald-700 dark:border-emerald-500/25 dark:bg-emerald-950/30 dark:text-emerald-300",
41
+ amber: "border-amber-200 bg-amber-50/60 text-amber-700 dark:border-amber-500/25 dark:bg-amber-950/30 dark:text-amber-300",
42
+ red: "border-red-200 bg-red-50/60 text-red-700 dark:border-red-500/25 dark:bg-red-950/30 dark:text-red-300",
43
+ };
44
+ export function PriceComparison({ targetPrice, targetLabel = "Buyer's Target Price", targetSubLabel, currency = "SEK", offeredPrice, onPriceChange, offeredLabel = "Your Offered Price", offeredHint = "Price you're offering per unit", className, }) {
45
+ const parsedTarget = targetPrice !== null ? Number(targetPrice) : null;
46
+ const parsedOffered = Number(offeredPrice);
47
+ const delta = React.useMemo(() => {
48
+ if (parsedTarget === null ||
49
+ Number.isNaN(parsedTarget) ||
50
+ Number.isNaN(parsedOffered) ||
51
+ offeredPrice.trim() === "") {
52
+ return null;
53
+ }
54
+ return computeDelta(parsedTarget, parsedOffered, currency);
55
+ }, [parsedTarget, parsedOffered, currency, offeredPrice]);
56
+ return (_jsxs("div", { className: cn("grid grid-cols-2 gap-3", className), children: [_jsxs("div", { className: "rounded-xl border border-sky-200/60 bg-sky-50/50 px-4 py-3.5 text-right dark:border-sky-500/15 dark:bg-sky-950/20", children: [_jsx("p", { className: "text-[10px] font-semibold uppercase tracking-[0.08em] text-sky-700 dark:text-sky-300", children: targetLabel }), targetSubLabel && (_jsx("p", { className: "mt-0.5 text-[11px] text-sky-600/70 dark:text-sky-400/60", children: targetSubLabel })), _jsx("p", { className: "mt-1.5 text-2xl font-bold tabular-nums text-sky-800 dark:text-sky-200", children: parsedTarget !== null && !Number.isNaN(parsedTarget)
57
+ ? formatPrice(parsedTarget, currency)
58
+ : "—" })] }), _jsxs("div", { children: [_jsxs("label", { className: "mb-1 block text-[11px] font-semibold text-foreground", children: [offeredLabel, _jsx("span", { className: "ml-0.5 text-red-500", "aria-hidden": "true", children: "*" })] }), _jsx("input", { type: "text", inputMode: "decimal", value: offeredPrice, onChange: (e) => onPriceChange(e.target.value), className: "w-full rounded-lg border border-border bg-background px-3 py-2.5 text-lg font-semibold tabular-nums text-foreground outline-hidden transition-shadow focus:ring-2 focus:ring-ring", "aria-label": offeredLabel }), _jsx("p", { className: "mt-1 text-[10px] text-muted-foreground", children: offeredHint })] }), delta && (_jsx("div", { className: cn("col-span-2 rounded-lg border px-3 py-1.5 text-center text-[11px] font-semibold", deltaClasses[delta.tone]), children: delta.label }))] }));
59
+ }
60
+ //# sourceMappingURL=price-comparison.js.map