@cellarnode/ui 0.199.1 → 0.201.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/dist/invite-confirm/client.d.ts +10 -0
- package/dist/invite-confirm/client.d.ts.map +1 -0
- package/dist/invite-confirm/client.js +69 -0
- package/dist/invite-confirm/client.js.map +1 -0
- package/dist/invite-confirm/copy.d.ts +42 -0
- package/dist/invite-confirm/copy.d.ts.map +1 -0
- package/dist/invite-confirm/copy.js +42 -0
- package/dist/invite-confirm/copy.js.map +1 -0
- package/dist/invite-confirm/fixtures.d.ts +13 -0
- package/dist/invite-confirm/fixtures.d.ts.map +1 -0
- package/dist/invite-confirm/fixtures.js +30 -0
- package/dist/invite-confirm/fixtures.js.map +1 -0
- package/dist/invite-confirm/index.d.ts +8 -0
- package/dist/invite-confirm/index.d.ts.map +1 -0
- package/dist/invite-confirm/index.js +8 -0
- package/dist/invite-confirm/index.js.map +1 -0
- package/dist/invite-confirm/invite-confirm-page.d.ts +27 -0
- package/dist/invite-confirm/invite-confirm-page.d.ts.map +1 -0
- package/dist/invite-confirm/invite-confirm-page.js +152 -0
- package/dist/invite-confirm/invite-confirm-page.js.map +1 -0
- package/dist/invite-confirm/token.d.ts +20 -0
- package/dist/invite-confirm/token.d.ts.map +1 -0
- package/dist/invite-confirm/token.js +59 -0
- package/dist/invite-confirm/token.js.map +1 -0
- package/dist/invite-confirm/types.d.ts +28 -0
- package/dist/invite-confirm/types.d.ts.map +1 -0
- package/dist/invite-confirm/types.js +11 -0
- package/dist/invite-confirm/types.js.map +1 -0
- package/dist/invite-confirm/use-invite-confirm.d.ts +33 -0
- package/dist/invite-confirm/use-invite-confirm.d.ts.map +1 -0
- package/dist/invite-confirm/use-invite-confirm.js +110 -0
- package/dist/invite-confirm/use-invite-confirm.js.map +1 -0
- package/dist/portfolio/include-in-matching-toggle.d.ts +30 -0
- package/dist/portfolio/include-in-matching-toggle.d.ts.map +1 -0
- package/dist/portfolio/include-in-matching-toggle.js +39 -0
- package/dist/portfolio/include-in-matching-toggle.js.map +1 -0
- package/dist/portfolio/index.d.ts +4 -0
- package/dist/portfolio/index.d.ts.map +1 -1
- package/dist/portfolio/index.js +2 -0
- package/dist/portfolio/index.js.map +1 -1
- package/dist/portfolio/not-matching-badge.d.ts +15 -0
- package/dist/portfolio/not-matching-badge.d.ts.map +1 -0
- package/dist/portfolio/not-matching-badge.js +13 -0
- package/dist/portfolio/not-matching-badge.js.map +1 -0
- package/dist/portfolio/product-grid-section.d.ts.map +1 -1
- package/dist/portfolio/product-grid-section.js +6 -4
- package/dist/portfolio/product-grid-section.js.map +1 -1
- package/dist/portfolio/product-list-section.d.ts.map +1 -1
- package/dist/portfolio/product-list-section.js +11 -5
- package/dist/portfolio/product-list-section.js.map +1 -1
- package/dist/portfolio/types.d.ts +6 -0
- package/dist/portfolio/types.d.ts.map +1 -1
- package/dist/product-editor/tabs/product-status-tab.d.ts.map +1 -1
- package/dist/product-editor/tabs/product-status-tab.js +22 -9
- package/dist/product-editor/tabs/product-status-tab.js.map +1 -1
- package/dist/product-editor/types.d.ts +14 -0
- package/dist/product-editor/types.d.ts.map +1 -1
- package/dist/upload-link/client.d.ts +21 -0
- package/dist/upload-link/client.d.ts.map +1 -0
- package/dist/upload-link/client.js +141 -0
- package/dist/upload-link/client.js.map +1 -0
- package/dist/upload-link/copy.d.ts +83 -0
- package/dist/upload-link/copy.d.ts.map +1 -0
- package/dist/upload-link/copy.js +132 -0
- package/dist/upload-link/copy.js.map +1 -0
- package/dist/upload-link/fixtures.d.ts +17 -0
- package/dist/upload-link/fixtures.d.ts.map +1 -0
- package/dist/upload-link/fixtures.js +63 -0
- package/dist/upload-link/fixtures.js.map +1 -0
- package/dist/upload-link/flow.d.ts +79 -0
- package/dist/upload-link/flow.d.ts.map +1 -0
- package/dist/upload-link/flow.js +107 -0
- package/dist/upload-link/flow.js.map +1 -0
- package/dist/upload-link/index.d.ts +10 -0
- package/dist/upload-link/index.d.ts.map +1 -0
- package/dist/upload-link/index.js +10 -0
- package/dist/upload-link/index.js.map +1 -0
- package/dist/upload-link/types.d.ts +58 -0
- package/dist/upload-link/types.d.ts.map +1 -0
- package/dist/upload-link/types.js +17 -0
- package/dist/upload-link/types.js.map +1 -0
- package/dist/upload-link/upload-link-page.d.ts +41 -0
- package/dist/upload-link/upload-link-page.d.ts.map +1 -0
- package/dist/upload-link/upload-link-page.js +184 -0
- package/dist/upload-link/upload-link-page.js.map +1 -0
- package/dist/upload-link/use-upload-link.d.ts +28 -0
- package/dist/upload-link/use-upload-link.d.ts.map +1 -0
- package/dist/upload-link/use-upload-link.js +155 -0
- package/dist/upload-link/use-upload-link.js.map +1 -0
- package/package.json +9 -1
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { InviteConfirmApiError, type InviteConfirmAuthState, type InviteConfirmClient, type InviteConfirmPreview, type InviteConfirmResult } from "./types.js";
|
|
2
|
+
export type FailureKind = "signed-out" | "wrong-account" | "expired" | "used" | "not-found" | "seat-limit" | "duplicate" | "network" | "other";
|
|
3
|
+
export type Phase = {
|
|
4
|
+
kind: "loading";
|
|
5
|
+
} | {
|
|
6
|
+
kind: "sign-in";
|
|
7
|
+
} | {
|
|
8
|
+
kind: "missing";
|
|
9
|
+
} | {
|
|
10
|
+
kind: "ready";
|
|
11
|
+
preview: InviteConfirmPreview;
|
|
12
|
+
sending: boolean;
|
|
13
|
+
error: FailureKind | null;
|
|
14
|
+
} | {
|
|
15
|
+
kind: "done";
|
|
16
|
+
preview: InviteConfirmPreview;
|
|
17
|
+
result: InviteConfirmResult;
|
|
18
|
+
} | {
|
|
19
|
+
kind: "failed";
|
|
20
|
+
reason: FailureKind;
|
|
21
|
+
};
|
|
22
|
+
/** Backend error -> the failure the page shows. Never the server's own sentence. */
|
|
23
|
+
export declare function failureOf(error: InviteConfirmApiError): FailureKind;
|
|
24
|
+
export declare function useInviteConfirm(options: {
|
|
25
|
+
token: string | null;
|
|
26
|
+
client: InviteConfirmClient;
|
|
27
|
+
auth: InviteConfirmAuthState;
|
|
28
|
+
}): {
|
|
29
|
+
phase: Phase;
|
|
30
|
+
confirm: () => Promise<void>;
|
|
31
|
+
retry: () => void;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=use-invite-confirm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-invite-confirm.d.ts","sourceRoot":"","sources":["../../src/invite-confirm/use-invite-confirm.ts"],"names":[],"mappings":"AACA,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACzB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,eAAe,GACf,SAAS,GACT,MAAM,GACN,WAAW,GACX,YAAY,GACZ,WAAW,GACX,SAAS,GACT,OAAO,CAAC;AAEZ,MAAM,MAAM,KAAK,GACb;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,SAAS,CAAA;CAAE,GACnB;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,GAC7F;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,oBAAoB,CAAC;IAAC,MAAM,EAAE,mBAAmB,CAAA;CAAE,GAC5E;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,WAAW,CAAA;CAAE,CAAC;AAE5C,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,KAAK,EAAE,qBAAqB,GAAG,WAAW,CAYnE;AAOD,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,IAAI,EAAE,sBAAsB,CAAC;CAC9B;;;;EAgFA"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { InviteConfirmApiError, } from "./types.js";
|
|
3
|
+
/** Backend error -> the failure the page shows. Never the server's own sentence. */
|
|
4
|
+
export function failureOf(error) {
|
|
5
|
+
const { status, code } = error;
|
|
6
|
+
if (status === 0)
|
|
7
|
+
return "network";
|
|
8
|
+
// The session ended or never existed: ask for sign-in again (the stashed token survives the round trip). Not "wrong account".
|
|
9
|
+
if (status === 401)
|
|
10
|
+
return "signed-out";
|
|
11
|
+
if (status === 403)
|
|
12
|
+
return "wrong-account";
|
|
13
|
+
if (status === 404)
|
|
14
|
+
return "not-found";
|
|
15
|
+
if (status === 410 || code === "INVITE_CONFIRMATION_EXPIRED")
|
|
16
|
+
return "expired";
|
|
17
|
+
if (status === 402 || code === "ORG_SEAT_LIMIT")
|
|
18
|
+
return "seat-limit";
|
|
19
|
+
if (code === "ORG_DUPLICATE_MEMBER" || code === "ORG_USER_ALREADY_IN_ORG")
|
|
20
|
+
return "duplicate";
|
|
21
|
+
if (status === 409)
|
|
22
|
+
return "used";
|
|
23
|
+
return "other";
|
|
24
|
+
}
|
|
25
|
+
const asApiError = (e) => e instanceof InviteConfirmApiError
|
|
26
|
+
? e
|
|
27
|
+
: new InviteConfirmApiError(0, "NETWORK", "The connection failed.");
|
|
28
|
+
export function useInviteConfirm(options) {
|
|
29
|
+
const { token, client, auth } = options;
|
|
30
|
+
const [attempt, setAttempt] = React.useState(0);
|
|
31
|
+
// What the server answered, tagged with the (token, attempt) it answered for, so a stale answer is simply ignored and no state
|
|
32
|
+
// is set synchronously in an effect.
|
|
33
|
+
const key = `${token ?? ""}|${attempt}`;
|
|
34
|
+
const [answer, setAnswer] = React.useState(null);
|
|
35
|
+
const sendingRef = React.useRef(false);
|
|
36
|
+
// Leaving the page cancels a send still in flight (the request on the server is unaffected: it stays pending until it expires).
|
|
37
|
+
const sendController = React.useRef(null);
|
|
38
|
+
React.useEffect(() => () => sendController.current?.abort(), []);
|
|
39
|
+
const ready = auth === "signed-in" && token !== null && token !== "";
|
|
40
|
+
React.useEffect(() => {
|
|
41
|
+
if (!ready || token === null)
|
|
42
|
+
return;
|
|
43
|
+
const controller = new AbortController();
|
|
44
|
+
client
|
|
45
|
+
.preview(token, controller.signal)
|
|
46
|
+
.then((preview) => {
|
|
47
|
+
if (controller.signal.aborted)
|
|
48
|
+
return;
|
|
49
|
+
// An already-confirmed request reads as used without offering the button again.
|
|
50
|
+
setAnswer({
|
|
51
|
+
key,
|
|
52
|
+
phase: preview.status === "confirmed"
|
|
53
|
+
? { kind: "failed", reason: "used" }
|
|
54
|
+
: { kind: "ready", preview, sending: false, error: null },
|
|
55
|
+
});
|
|
56
|
+
})
|
|
57
|
+
.catch((e) => {
|
|
58
|
+
if (controller.signal.aborted)
|
|
59
|
+
return;
|
|
60
|
+
setAnswer({ key, phase: { kind: "failed", reason: failureOf(asApiError(e)) } });
|
|
61
|
+
});
|
|
62
|
+
return () => controller.abort();
|
|
63
|
+
}, [ready, client, token, key]);
|
|
64
|
+
const phase = auth === "signed-out"
|
|
65
|
+
? { kind: "sign-in" }
|
|
66
|
+
: auth === "checking"
|
|
67
|
+
? { kind: "loading" }
|
|
68
|
+
: token === null || token === ""
|
|
69
|
+
? { kind: "missing" }
|
|
70
|
+
: answer?.key === key
|
|
71
|
+
? answer.phase
|
|
72
|
+
: { kind: "loading" };
|
|
73
|
+
const confirm = React.useCallback(async () => {
|
|
74
|
+
if (phase.kind !== "ready" || sendingRef.current || token === null)
|
|
75
|
+
return;
|
|
76
|
+
sendingRef.current = true;
|
|
77
|
+
const { preview } = phase;
|
|
78
|
+
const controller = new AbortController();
|
|
79
|
+
sendController.current = controller;
|
|
80
|
+
setAnswer({ key, phase: { kind: "ready", preview, sending: true, error: null } });
|
|
81
|
+
try {
|
|
82
|
+
const result = await client.confirm(token, controller.signal);
|
|
83
|
+
if (controller.signal.aborted)
|
|
84
|
+
return;
|
|
85
|
+
setAnswer({ key, phase: { kind: "done", preview, result } });
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
if (controller.signal.aborted)
|
|
89
|
+
return;
|
|
90
|
+
const reason = failureOf(asApiError(e));
|
|
91
|
+
// A refused SEND (seat limit, duplicate) or a dropped connection keeps the request alive on the server: stay on the page
|
|
92
|
+
// with the reason so the owner can fix it and retry. Anything final replaces the page.
|
|
93
|
+
const stay = reason === "network" ||
|
|
94
|
+
reason === "seat-limit" ||
|
|
95
|
+
reason === "duplicate" ||
|
|
96
|
+
reason === "other";
|
|
97
|
+
setAnswer({
|
|
98
|
+
key,
|
|
99
|
+
phase: stay
|
|
100
|
+
? { kind: "ready", preview, sending: false, error: reason }
|
|
101
|
+
: { kind: "failed", reason },
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
finally {
|
|
105
|
+
sendingRef.current = false;
|
|
106
|
+
}
|
|
107
|
+
}, [client, key, phase, token]);
|
|
108
|
+
return { phase, confirm, retry: () => setAttempt((n) => n + 1) };
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=use-invite-confirm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-invite-confirm.js","sourceRoot":"","sources":["../../src/invite-confirm/use-invite-confirm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/** English defaults; consumers override through `copy` (or their own i18n). */
|
|
3
|
+
export declare const DEFAULT_INCLUDE_IN_MATCHING_COPY: {
|
|
4
|
+
readonly label: "Include in matching";
|
|
5
|
+
readonly included: "This product is matched with opportunities.";
|
|
6
|
+
readonly excluded: "Excluded products are not matched with opportunities; existing matches are hidden.";
|
|
7
|
+
readonly error: "Could not update matching. Your change was undone.";
|
|
8
|
+
};
|
|
9
|
+
export type IncludeInMatchingCopy = {
|
|
10
|
+
readonly [K in keyof typeof DEFAULT_INCLUDE_IN_MATCHING_COPY]?: string;
|
|
11
|
+
};
|
|
12
|
+
export interface IncludeInMatchingToggleProps {
|
|
13
|
+
/** Whether the product takes part in matching (the portfolio item's `matchingEnabled`). */
|
|
14
|
+
readonly checked: boolean;
|
|
15
|
+
readonly onChange: (next: boolean) => void;
|
|
16
|
+
/** "pending" disables the switch (aria-busy); "error" shows the error line (role=alert). */
|
|
17
|
+
readonly status?: "pending" | "error";
|
|
18
|
+
readonly copy?: IncludeInMatchingCopy;
|
|
19
|
+
/** Extra content under the state line, e.g. a "needs approval first" note. */
|
|
20
|
+
readonly hint?: ReactNode;
|
|
21
|
+
readonly className?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The one "Include in matching" control for producer and e-label (CEL-1809).
|
|
25
|
+
* A labelled switch with an always-visible state line. The switch always shows
|
|
26
|
+
* the caller's value, so an optimistic update that rolls back is visible
|
|
27
|
+
* without this component owning mutation state.
|
|
28
|
+
*/
|
|
29
|
+
export declare function IncludeInMatchingToggle({ checked, onChange, status, copy, hint, className, }: IncludeInMatchingToggleProps): import("react/jsx-runtime").JSX.Element;
|
|
30
|
+
//# sourceMappingURL=include-in-matching-toggle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-in-matching-toggle.d.ts","sourceRoot":"","sources":["../../src/portfolio/include-in-matching-toggle.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAqB,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAI1D,+EAA+E;AAC/E,eAAO,MAAM,gCAAgC;;;;;CAKnC,CAAC;AAEX,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,CAAC,IAAI,MAAM,OAAO,gCAAgC,CAAC,CAAC,EAAE,MAAM;CACvE,CAAC;AAEF,MAAM,WAAW,4BAA4B;IAC3C,2FAA2F;IAC3F,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC3C,4FAA4F;IAC5F,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC;IACtC,QAAQ,CAAC,IAAI,CAAC,EAAE,qBAAqB,CAAC;IACtC,8EAA8E;IAC9E,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,OAAO,EACP,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,SAAS,GACV,EAAE,4BAA4B,2CA4C9B"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import clsx from "clsx";
|
|
3
|
+
import { Description, Field, Label } from "@headlessui/react";
|
|
4
|
+
import { useEffect, useRef } from "react";
|
|
5
|
+
import { Switch } from "../components/switch.js";
|
|
6
|
+
/** English defaults; consumers override through `copy` (or their own i18n). */
|
|
7
|
+
export const DEFAULT_INCLUDE_IN_MATCHING_COPY = {
|
|
8
|
+
label: "Include in matching",
|
|
9
|
+
included: "This product is matched with opportunities.",
|
|
10
|
+
excluded: "Excluded products are not matched with opportunities; existing matches are hidden.",
|
|
11
|
+
error: "Could not update matching. Your change was undone.",
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* The one "Include in matching" control for producer and e-label (CEL-1809).
|
|
15
|
+
* A labelled switch with an always-visible state line. The switch always shows
|
|
16
|
+
* the caller's value, so an optimistic update that rolls back is visible
|
|
17
|
+
* without this component owning mutation state.
|
|
18
|
+
*/
|
|
19
|
+
export function IncludeInMatchingToggle({ checked, onChange, status, copy, hint, className, }) {
|
|
20
|
+
const text = { ...DEFAULT_INCLUDE_IN_MATCHING_COPY, ...copy };
|
|
21
|
+
const pending = status === "pending";
|
|
22
|
+
// In-flight guard: a second click before the caller has reacted (flipped
|
|
23
|
+
// `checked` or set a status) is ignored, so a double click sends ONE change
|
|
24
|
+
// rather than two competing writes. Released when `checked` or `status` moves.
|
|
25
|
+
const inFlight = useRef(false);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
inFlight.current = false;
|
|
28
|
+
}, [checked, status]);
|
|
29
|
+
const handleChange = (next) => {
|
|
30
|
+
if (inFlight.current)
|
|
31
|
+
return;
|
|
32
|
+
inFlight.current = true;
|
|
33
|
+
onChange(next);
|
|
34
|
+
};
|
|
35
|
+
// Headless Field wires the label and every Description to the switch
|
|
36
|
+
// (aria-labelledby / aria-describedby).
|
|
37
|
+
return (_jsxs(Field, { "data-slot": "include-in-matching-toggle", "data-state": checked ? "included" : "excluded", className: clsx("flex flex-col gap-1.5 rounded-xl bg-muted/40 p-4", className), children: [_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsx(Label, { className: "min-w-0 break-words text-sm/5 font-medium text-foreground", children: text.label }), _jsx(Switch, { checked: checked, disabled: pending, onChange: handleChange, "aria-busy": pending })] }), _jsx(Description, { className: "text-xs/5 text-muted-foreground", children: checked ? text.included : text.excluded }), hint ? (_jsx(Description, { "data-slot": "hint", className: "text-xs/5 text-muted-foreground", children: hint })) : null, status === "error" ? (_jsx("p", { role: "alert", className: "text-xs/5 text-[var(--tone-danger-fg)]", children: text.error })) : null] }));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=include-in-matching-toggle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"include-in-matching-toggle.js","sourceRoot":"","sources":["../../src/portfolio/include-in-matching-toggle.tsx"],"names":[],"mappings":";AAAA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAkB,MAAM,OAAO,CAAC;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAE9C,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC9C,KAAK,EAAE,qBAAqB;IAC5B,QAAQ,EAAE,6CAA6C;IACvD,QAAQ,EAAE,oFAAoF;IAC9F,KAAK,EAAE,oDAAoD;CACnD,CAAC;AAkBX;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,OAAO,EACP,QAAQ,EACR,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,SAAS,GACoB;IAC7B,MAAM,IAAI,GAAG,EAAE,GAAG,gCAAgC,EAAE,GAAG,IAAI,EAAE,CAAC;IAC9D,MAAM,OAAO,GAAG,MAAM,KAAK,SAAS,CAAC;IACrC,yEAAyE;IACzE,4EAA4E;IAC5E,+EAA+E;IAC/E,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/B,SAAS,CAAC,GAAG,EAAE;QACb,QAAQ,CAAC,OAAO,GAAG,KAAK,CAAC;IAC3B,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IACtB,MAAM,YAAY,GAAG,CAAC,IAAa,EAAE,EAAE;QACrC,IAAI,QAAQ,CAAC,OAAO;YAAE,OAAO;QAC7B,QAAQ,CAAC,OAAO,GAAG,IAAI,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,CAAC;IACjB,CAAC,CAAC;IACF,qEAAqE;IACrE,wCAAwC;IACxC,OAAO,CACL,MAAC,KAAK,iBACM,4BAA4B,gBAC1B,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,EAC7C,SAAS,EAAE,IAAI,CAAC,kDAAkD,EAAE,SAAS,CAAC,aAE9E,eAAK,SAAS,EAAC,yCAAyC,aACtD,KAAC,KAAK,IAAC,SAAS,EAAC,2DAA2D,YACzE,IAAI,CAAC,KAAK,GACL,EACR,KAAC,MAAM,IAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,eAAa,OAAO,GAAI,IACvF,EACN,KAAC,WAAW,IAAC,SAAS,EAAC,iCAAiC,YACrD,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAC5B,EACb,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,WAAW,iBAAW,MAAM,EAAC,SAAS,EAAC,iCAAiC,YACtE,IAAI,GACO,CACf,CAAC,CAAC,CAAC,IAAI,EACP,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,CACpB,YAAG,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,wCAAwC,YAC/D,IAAI,CAAC,KAAK,GACT,CACL,CAAC,CAAC,CAAC,IAAI,IACF,CACT,CAAC;AACJ,CAAC"}
|
|
@@ -12,6 +12,10 @@ export { VersionRail, VersionRailRow } from "./version-rail.js";
|
|
|
12
12
|
export type { VersionRailProps, VersionRailRowProps } from "./version-rail.js";
|
|
13
13
|
export { MoveToPortfolioDialog } from "./move-to-portfolio-dialog.js";
|
|
14
14
|
export type { MoveToPortfolioDialogProps } from "./move-to-portfolio-dialog.js";
|
|
15
|
+
export { NotMatchingBadge } from "./not-matching-badge.js";
|
|
16
|
+
export type { NotMatchingBadgeProps } from "./not-matching-badge.js";
|
|
17
|
+
export { DEFAULT_INCLUDE_IN_MATCHING_COPY, IncludeInMatchingToggle, } from "./include-in-matching-toggle.js";
|
|
18
|
+
export type { IncludeInMatchingCopy, IncludeInMatchingToggleProps, } from "./include-in-matching-toggle.js";
|
|
15
19
|
export { SearchInput } from "./search-input.js";
|
|
16
20
|
export type { SearchInputProps } from "./search-input.js";
|
|
17
21
|
export { StatsRow } from "./stats-row.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/portfolio/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/portfolio/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,wBAAwB,EACxB,qBAAqB,EACrB,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,EAClB,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACZ,WAAW,GACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,YAAY,EAAE,sBAAsB,EAAE,MAAM,uBAAuB,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAC5D,YAAY,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7D,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,YAAY,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,YAAY,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAClE,OAAO,EACL,gCAAgC,EAChC,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AACtC,YAAY,EACV,qBAAqB,EACrB,4BAA4B,GAC7B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,YAAY,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,YAAY,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,YAAY,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC"}
|
package/dist/portfolio/index.js
CHANGED
|
@@ -9,6 +9,8 @@ export { ProductGridSection } from "./product-grid-section.js";
|
|
|
9
9
|
export { ProductListSection } from "./product-list-section.js";
|
|
10
10
|
export { VersionRail, VersionRailRow } from "./version-rail.js";
|
|
11
11
|
export { MoveToPortfolioDialog } from "./move-to-portfolio-dialog.js";
|
|
12
|
+
export { NotMatchingBadge } from "./not-matching-badge.js";
|
|
13
|
+
export { DEFAULT_INCLUDE_IN_MATCHING_COPY, IncludeInMatchingToggle, } from "./include-in-matching-toggle.js";
|
|
12
14
|
export { SearchInput } from "./search-input.js";
|
|
13
15
|
export { StatsRow } from "./stats-row.js";
|
|
14
16
|
export { AnimatedCounter } from "./animated-counter.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/portfolio/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAmB/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/portfolio/index.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,6EAA6E;AAC7E,6EAA6E;AAC7E,+EAA+E;AAmB/E,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AAEnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,OAAO,EACL,gCAAgC,EAChC,uBAAuB,GACxB,MAAM,8BAA8B,CAAC;AAKtC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAE9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TranslateFn } from "./types.js";
|
|
2
|
+
export interface NotMatchingBadgeProps {
|
|
3
|
+
/** Overrides the label directly (wins over `t`). */
|
|
4
|
+
label?: string;
|
|
5
|
+
/** Translation adapter; receives (`status.notMatching`, English fallback). */
|
|
6
|
+
t?: TranslateFn;
|
|
7
|
+
className?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* "Not matching" badge for portfolio rows and cards whose product is excluded
|
|
11
|
+
* from matching (CEL-1809). Carries an icon as well as text so the state never
|
|
12
|
+
* rests on colour alone.
|
|
13
|
+
*/
|
|
14
|
+
export declare function NotMatchingBadge({ label, t, className }: NotMatchingBadgeProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
//# sourceMappingURL=not-matching-badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-matching-badge.d.ts","sourceRoot":"","sources":["../../src/portfolio/not-matching-badge.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,WAAW,qBAAqB;IACpC,oDAAoD;IACpD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8EAA8E;IAC9E,CAAC,CAAC,EAAE,WAAW,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,EAAE,qBAAqB,2CAc9E"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { EyeOff } from "lucide-react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
/**
|
|
5
|
+
* "Not matching" badge for portfolio rows and cards whose product is excluded
|
|
6
|
+
* from matching (CEL-1809). Carries an icon as well as text so the state never
|
|
7
|
+
* rests on colour alone.
|
|
8
|
+
*/
|
|
9
|
+
export function NotMatchingBadge({ label, t, className }) {
|
|
10
|
+
const text = label ?? (t ? t("status.notMatching", "Not matching") : "Not matching");
|
|
11
|
+
return (_jsxs("span", { "data-slot": "not-matching-badge", className: cn("inline-flex items-center gap-1 whitespace-nowrap rounded-full bg-[var(--tone-neutral-soft)] px-2.5 py-0.5 text-xs/5 font-medium text-[var(--tone-neutral-fg)] ring-1 ring-border", className), children: [_jsx(EyeOff, { "aria-hidden": "true", className: "size-3" }), text] }));
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=not-matching-badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"not-matching-badge.js","sourceRoot":"","sources":["../../src/portfolio/not-matching-badge.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAEtC,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAWlC;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAyB;IAC7E,MAAM,IAAI,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC;IACrF,OAAO,CACL,6BACY,oBAAoB,EAC9B,SAAS,EAAE,EAAE,CACX,kLAAkL,EAClL,SAAS,CACV,aAED,KAAC,MAAM,mBAAa,MAAM,EAAC,SAAS,EAAC,QAAQ,GAAG,EAC/C,IAAI,IACA,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-grid-section.d.ts","sourceRoot":"","sources":["../../src/portfolio/product-grid-section.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"product-grid-section.d.ts","sourceRoot":"","sources":["../../src/portfolio/product-grid-section.tsx"],"names":[],"mappings":"AAcA,OAAO,KAAK,EACV,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,MAAM,WAAW,uBAAuB;IACtC,iFAAiF;IACjF,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,0EAA0E;IAC1E,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,sEAAsE;IACtE,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,0EAA0E;IAC1E,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,uEAAuE;IACvE,CAAC,CAAC,EAAE,WAAW,CAAC;IAChB,qFAAqF;IACrF,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC5C;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,MAAM,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AA0DD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,CAAC,EACD,eAAe,EACf,cAAc,EACd,SAAS,GACV,EAAE,uBAAuB,2CAgHzB"}
|
|
@@ -8,7 +8,9 @@ import { groupVariantsByBeverage } from "./group-variants-by-beverage.js";
|
|
|
8
8
|
import { ProductStatusPill, ProductStatusDotText, statusKindForValidation, } from "./product-status-pill.js";
|
|
9
9
|
import { VersionRail, VersionRailRow } from "./version-rail.js";
|
|
10
10
|
import { interpolate } from "./interpolate.js";
|
|
11
|
-
|
|
11
|
+
import { NotMatchingBadge } from "./not-matching-badge.js";
|
|
12
|
+
function renderCard(item, { onProductClick, renderKebab, formatDisplayName, formatSubtitle, t, }) {
|
|
13
|
+
const variant = item.variant;
|
|
12
14
|
const displayName = formatDisplayName(variant);
|
|
13
15
|
const subtitle = formatSubtitle ? formatSubtitle(variant) : (variant.beverage?.producer ?? "");
|
|
14
16
|
const rawImage = variant.primaryShowcaseImage;
|
|
@@ -26,7 +28,7 @@ function renderCard(variant, { onProductClick, renderKebab, formatDisplayName, f
|
|
|
26
28
|
// useful than "price on request").
|
|
27
29
|
const volume = variant.containerVolume ? `${variant.containerVolume}ml` : null;
|
|
28
30
|
const footerDetail = [variant.packaging, volume].filter(Boolean).join(" · ") || null;
|
|
29
|
-
return (_jsx(ProductCard, { image: image, placeholder: _jsx(PortfolioCoverPlaceholder, { entityId: variant.id, name: displayName }), statusSlot: _jsx(ProductStatusPill, { kind: statusKindForValidation(variant.validation), t: t }), kebabSlot: renderKebab?.(variant), title: displayName, subtitle: subtitle || undefined, footerSlot: footerDetail ? _jsx("span", { className: "text-xs text-muted-foreground", children: footerDetail }) : null, onClick: () => onProductClick(variant.id), ariaLabel: displayName }));
|
|
31
|
+
return (_jsx(ProductCard, { image: image, placeholder: _jsx(PortfolioCoverPlaceholder, { entityId: variant.id, name: displayName }), statusSlot: _jsxs("div", { className: "flex flex-wrap items-center gap-1.5", children: [_jsx(ProductStatusPill, { kind: statusKindForValidation(variant.validation), t: t }), item.matchingEnabled === false ? _jsx(NotMatchingBadge, { t: t }) : null] }), kebabSlot: renderKebab?.(variant), title: displayName, subtitle: subtitle || undefined, footerSlot: footerDetail ? _jsx("span", { className: "text-xs text-muted-foreground", children: footerDetail }) : null, onClick: () => onProductClick(variant.id), ariaLabel: displayName }));
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
32
34
|
* Product grid for a portfolio detail page — one card per product (beverage),
|
|
@@ -60,14 +62,14 @@ export function ProductGridSection({ items, onProductClick, renderKebab, formatD
|
|
|
60
62
|
? (stackBadgeLabel?.(siblingCount) ?? `+${siblingCount} versions`)
|
|
61
63
|
: undefined, onStackClick: siblingCount > 0
|
|
62
64
|
? () => setExpandedBeverageId(isExpanded ? null : group.beverageId)
|
|
63
|
-
: undefined, children: renderCard(group.primary
|
|
65
|
+
: undefined, children: renderCard(group.primary, cardProps) }) }), isExpanded && siblingCount > 0 && (_jsx("div", { className: "col-span-full grid animate-fade-in-up grid-rows-[1fr] motion-reduce:animate-none", children: _jsx("div", { className: "overflow-hidden", children: _jsx(VersionRail, { caption: caption, children: [group.primary, ...group.siblings].map((item, itemIndex) => {
|
|
64
66
|
const v = item.variant;
|
|
65
67
|
const vDisplayName = formatDisplayName(v);
|
|
66
68
|
const volume = v.containerVolume ? `${v.containerVolume}ml` : null;
|
|
67
69
|
const secondary = [v.packaging, volume].filter(Boolean).join(" · ") || undefined;
|
|
68
70
|
const rawImage = v.primaryShowcaseImage;
|
|
69
71
|
const thumbnail = rawImage ? (_jsx("img", { src: rawImage.url, alt: rawImage.altText ?? vDisplayName, className: "size-full object-contain", loading: "lazy" })) : (_jsx(PortfolioCoverPlaceholder, { entityId: v.id, name: vDisplayName }));
|
|
70
|
-
return (_jsx("div", { className: "animate-scale-fade-in motion-reduce:animate-none", style: { animationDelay: `${itemIndex * 30}ms` }, children: _jsx(VersionRailRow, { thumbnail: thumbnail, primaryLabel: vDisplayName, secondaryLabel: secondary, statusSlot: _jsx(ProductStatusDotText, { kind: statusKindForValidation(v.validation), copy: statusCopy }), kebabSlot: renderKebab?.(v), onClick: () => onProductClick(v.id) }) }, v.id));
|
|
72
|
+
return (_jsx("div", { className: "animate-scale-fade-in motion-reduce:animate-none", style: { animationDelay: `${itemIndex * 30}ms` }, children: _jsx(VersionRailRow, { thumbnail: thumbnail, primaryLabel: vDisplayName, secondaryLabel: secondary, statusSlot: _jsxs("div", { className: "flex items-center gap-2", children: [_jsx(ProductStatusDotText, { kind: statusKindForValidation(v.validation), copy: statusCopy }), item.matchingEnabled === false ? _jsx(NotMatchingBadge, { t: t }) : null] }), kebabSlot: renderKebab?.(v), onClick: () => onProductClick(v.id) }) }, v.id));
|
|
71
73
|
}) }) }) }))] }, group.beverageId));
|
|
72
74
|
}) }));
|
|
73
75
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-grid-section.js","sourceRoot":"","sources":["../../src/portfolio/product-grid-section.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AACrD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAC7D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AA+
|
|
1
|
+
{"version":3,"file":"product-grid-section.js","sourceRoot":"","sources":["../../src/portfolio/product-grid-section.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-list-section.d.ts","sourceRoot":"","sources":["../../src/portfolio/product-list-section.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"product-list-section.d.ts","sourceRoot":"","sources":["../../src/portfolio/product-list-section.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EACV,wBAAwB,EACxB,oBAAoB,EACpB,uBAAuB,EACvB,kBAAkB,EAClB,qBAAqB,EACrB,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,uBAAuB;IACtC,2EAA2E;IAC3E,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,oEAAoE;IACpE,cAAc,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,oEAAoE;IACpE,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC;;;OAGG;IACH,cAAc,CAAC,EAAE,qBAAqB,CAAC;IACvC,yDAAyD;IACzD,iBAAiB,EAAE,wBAAwB,CAAC;IAC5C,iEAAiE;IACjE,cAAc,CAAC,EAAE,CAAC,OAAO,EAAE,uBAAuB,KAAK,MAAM,CAAC;IAC9D,2EAA2E;IAC3E,CAAC,CAAC,EAAE,WAAW,CAAC;IAChB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAWD,wBAAgB,kBAAkB,CAAC,EACjC,KAAK,EACL,cAAc,EACd,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,CAAC,EACD,OAAY,EACZ,SAAS,GACV,EAAE,uBAAuB,2CA2GzB"}
|
|
@@ -6,6 +6,7 @@ import { cn } from "../lib/utils.js";
|
|
|
6
6
|
import { groupVariantsByBeverage } from "./group-variants-by-beverage.js";
|
|
7
7
|
import { ProductStatusPill, ProductStatusDotText, statusKindForValidation, } from "./product-status-pill.js";
|
|
8
8
|
import { interpolate } from "./interpolate.js";
|
|
9
|
+
import { NotMatchingBadge } from "./not-matching-badge.js";
|
|
9
10
|
export function ProductListSection({ items, onProductClick, renderKebab, renderTrailing, formatDisplayName, formatSubtitle, t, maxRows = 10, className, }) {
|
|
10
11
|
const translate = t ?? ((_k, fb) => fb ?? _k);
|
|
11
12
|
const groups = groupVariantsByBeverage(items);
|
|
@@ -14,28 +15,33 @@ export function ProductListSection({ items, onProductClick, renderKebab, renderT
|
|
|
14
15
|
const flatRows = groups.flatMap((group) => [
|
|
15
16
|
{
|
|
16
17
|
variant: group.primary.variant,
|
|
18
|
+
matchingEnabled: group.primary.matchingEnabled,
|
|
17
19
|
indent: false,
|
|
18
20
|
versionCount: group.siblings.length > 0 ? group.siblings.length + 1 : undefined,
|
|
19
21
|
},
|
|
20
|
-
...group.siblings.map((sibling) => ({
|
|
22
|
+
...group.siblings.map((sibling) => ({
|
|
23
|
+
variant: sibling.variant,
|
|
24
|
+
matchingEnabled: sibling.matchingEnabled,
|
|
25
|
+
indent: true,
|
|
26
|
+
})),
|
|
21
27
|
]);
|
|
22
28
|
const statusCopy = {
|
|
23
29
|
active: translate("status.active", "Active"),
|
|
24
30
|
needsReview: translate("status.needsReview", "Needs Review"),
|
|
25
31
|
draft: translate("status.draft", "Draft"),
|
|
26
32
|
};
|
|
27
|
-
const buildRow = (variant, indent, versionCount) => {
|
|
33
|
+
const buildRow = (variant, indent, versionCount, matchingEnabled) => {
|
|
28
34
|
const displayName = formatDisplayName(variant);
|
|
29
35
|
// API returns `matchCount` as `string | number` (Elysia t.Integer quirk).
|
|
30
36
|
const matchCountNum = Number(variant.matchCount ?? 0);
|
|
31
37
|
const trailing = renderTrailing?.(variant);
|
|
32
|
-
return (_jsx(ProductListRow, { indent: indent, versionCount: versionCount, image: variant.primaryShowcaseImage ?? null, placeholder: _jsx(PortfolioCoverPlaceholder, { entityId: variant.id, name: displayName }), statusSlot: indent ? (_jsx(ProductStatusDotText, { kind: statusKindForValidation(variant.validation), copy: statusCopy })) : (_jsx(ProductStatusPill, { kind: statusKindForValidation(variant.validation), copy: statusCopy })), title: displayName, subtitle: formatSubtitle?.(variant), trailingSlot: trailing != null || matchCountNum > 0 ? (_jsxs("div", { className: "flex items-center gap-3", children: [trailing, matchCountNum > 0 && (_jsx("span", { className: "rounded-full bg-primary/10 px-2.5 py-1 text-xs font-semibold text-primary", children: interpolate(translate("detail.matchesCount", "{{count}} matches"), {
|
|
38
|
+
return (_jsx(ProductListRow, { indent: indent, versionCount: versionCount, image: variant.primaryShowcaseImage ?? null, placeholder: _jsx(PortfolioCoverPlaceholder, { entityId: variant.id, name: displayName }), statusSlot: _jsxs("div", { className: "flex items-center gap-2", children: [indent ? (_jsx(ProductStatusDotText, { kind: statusKindForValidation(variant.validation), copy: statusCopy })) : (_jsx(ProductStatusPill, { kind: statusKindForValidation(variant.validation), copy: statusCopy })), matchingEnabled === false ? _jsx(NotMatchingBadge, { t: t }) : null] }), title: displayName, subtitle: formatSubtitle?.(variant), trailingSlot: trailing != null || matchCountNum > 0 ? (_jsxs("div", { className: "flex items-center gap-3", children: [trailing, matchCountNum > 0 && (_jsx("span", { className: "rounded-full bg-primary/10 px-2.5 py-1 text-xs font-semibold text-primary", children: interpolate(translate("detail.matchesCount", "{{count}} matches"), {
|
|
33
39
|
count: matchCountNum,
|
|
34
40
|
}) }))] })) : undefined, kebabSlot: renderKebab?.(variant), onClick: () => onProductClick(variant.id) }));
|
|
35
41
|
};
|
|
36
|
-
return (_jsx("div", { className: cn(className), children: _jsx(CappedList, { items: flatRows, max: maxRows, as: "ul", moreLabel: (hiddenCount) => interpolate(translate("list.moreVariants", "+{{count}} more"), { count: hiddenCount }), lessLabel: translate("list.showLess", "Show less"), getKey: (row) => row.variant.id, className: "flex flex-col gap-3", renderItem: ({ variant, indent, versionCount }, index) => {
|
|
42
|
+
return (_jsx("div", { className: cn(className), children: _jsx(CappedList, { items: flatRows, max: maxRows, as: "ul", moreLabel: (hiddenCount) => interpolate(translate("list.moreVariants", "+{{count}} more"), { count: hiddenCount }), lessLabel: translate("list.showLess", "Show less"), getKey: (row) => row.variant.id, className: "flex flex-col gap-3", renderItem: ({ variant, indent, versionCount, matchingEnabled }, index) => {
|
|
37
43
|
const rowDelay = Math.min(160 + index * 35, 480);
|
|
38
|
-
return (_jsx("li", { className: "animate-scale-fade-in motion-reduce:animate-none", style: { animationDelay: `${rowDelay}ms` }, children: buildRow(variant, indent, versionCount) }));
|
|
44
|
+
return (_jsx("li", { className: "animate-scale-fade-in motion-reduce:animate-none", style: { animationDelay: `${rowDelay}ms` }, children: buildRow(variant, indent, versionCount, matchingEnabled) }));
|
|
39
45
|
} }) }));
|
|
40
46
|
}
|
|
41
47
|
//# sourceMappingURL=product-list-section.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-list-section.js","sourceRoot":"","sources":["../../src/portfolio/product-list-section.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"product-list-section.js","sourceRoot":"","sources":["../../src/portfolio/product-list-section.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AACvD,OAAO,EAAE,yBAAyB,EAAE,MAAM,2CAA2C,CAAC;AACtF,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AACvE,OAAO,EACL,iBAAiB,EACjB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AA0DxD,MAAM,UAAU,kBAAkB,CAAC,EACjC,KAAK,EACL,cAAc,EACd,WAAW,EACX,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,CAAC,EACD,OAAO,GAAG,EAAE,EACZ,SAAS,GACe;IACxB,MAAM,SAAS,GAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3D,MAAM,MAAM,GAAG,uBAAuB,CAAC,KAAK,CAAC,CAAC;IAE9C,4EAA4E;IAC5E,2EAA2E;IAC3E,MAAM,QAAQ,GAAc,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QACpD;YACE,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO;YAC9B,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,eAAe;YAC9C,MAAM,EAAE,KAAK;YACb,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS;SAChF;QACD,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YAClC,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,MAAM,EAAE,IAAI;SACb,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG;QACjB,MAAM,EAAE,SAAS,CAAC,eAAe,EAAE,QAAQ,CAAC;QAC5C,WAAW,EAAE,SAAS,CAAC,oBAAoB,EAAE,cAAc,CAAC;QAC5D,KAAK,EAAE,SAAS,CAAC,cAAc,EAAE,OAAO,CAAC;KAC1C,CAAC;IAEF,MAAM,QAAQ,GAAG,CACf,OAAgC,EAChC,MAAe,EACf,YAAqB,EACrB,eAAyB,EACR,EAAE;QACnB,MAAM,WAAW,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC/C,0EAA0E;QAC1E,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC;QACtD,MAAM,QAAQ,GAAG,cAAc,EAAE,CAAC,OAAO,CAAC,CAAC;QAE3C,OAAO,CACL,KAAC,cAAc,IACb,MAAM,EAAE,MAAM,EACd,YAAY,EAAE,YAAY,EAC1B,KAAK,EAAE,OAAO,CAAC,oBAAoB,IAAI,IAAI,EAC3C,WAAW,EAAE,KAAC,yBAAyB,IAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,WAAW,GAAI,EACnF,UAAU,EACR,eAAK,SAAS,EAAC,yBAAyB,aACrC,MAAM,CAAC,CAAC,CAAC,CACR,KAAC,oBAAoB,IACnB,IAAI,EAAE,uBAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,EACjD,IAAI,EAAE,UAAU,GAChB,CACH,CAAC,CAAC,CAAC,CACF,KAAC,iBAAiB,IAChB,IAAI,EAAE,uBAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,EACjD,IAAI,EAAE,UAAU,GAChB,CACH,EACA,eAAe,KAAK,KAAK,CAAC,CAAC,CAAC,KAAC,gBAAgB,IAAC,CAAC,EAAE,CAAC,GAAI,CAAC,CAAC,CAAC,IAAI,IAC1D,EAER,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,cAAc,EAAE,CAAC,OAAO,CAAC,EACnC,YAAY,EACV,QAAQ,IAAI,IAAI,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,CACtC,eAAK,SAAS,EAAC,yBAAyB,aACrC,QAAQ,EACR,aAAa,GAAG,CAAC,IAAI,CACpB,eAAM,SAAS,EAAC,2EAA2E,YACxF,WAAW,CAAC,SAAS,CAAC,qBAAqB,EAAE,mBAAmB,CAAC,EAAE;4BAClE,KAAK,EAAE,aAAa;yBACrB,CAAC,GACG,CACR,IACG,CACP,CAAC,CAAC,CAAC,SAAS,EAEf,SAAS,EAAE,WAAW,EAAE,CAAC,OAAO,CAAC,EACjC,OAAO,EAAE,GAAG,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,GACzC,CACH,CAAC;IACJ,CAAC,CAAC;IAEF,OAAO,CACL,cAAK,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,YAC3B,KAAC,UAAU,IACT,KAAK,EAAE,QAAQ,EACf,GAAG,EAAE,OAAO,EACZ,EAAE,EAAC,IAAI,EACP,SAAS,EAAE,CAAC,WAAW,EAAE,EAAE,CACzB,WAAW,CAAC,SAAS,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,EAAE,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAExF,SAAS,EAAE,SAAS,CAAC,eAAe,EAAE,WAAW,CAAC,EAClD,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAC/B,SAAS,EAAC,qBAAqB,EAC/B,UAAU,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,EAAE,EAAE,KAAK,EAAE,EAAE;gBACxE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,GAAG,KAAK,GAAG,EAAE,EAAE,GAAG,CAAC,CAAC;gBACjD,OAAO,CACL,aACE,SAAS,EAAC,kDAAkD,EAC5D,KAAK,EAAE,EAAE,cAAc,EAAE,GAAG,QAAQ,IAAI,EAAE,YAEzC,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,eAAe,CAAC,GACtD,CACN,CAAC;YACJ,CAAC,GACD,GACE,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -63,6 +63,12 @@ export interface PortfolioProductVariant {
|
|
|
63
63
|
export interface PortfolioProductItem {
|
|
64
64
|
id: string;
|
|
65
65
|
variant: PortfolioProductVariant;
|
|
66
|
+
/**
|
|
67
|
+
* The portfolio item's matching opt-in (CEL-1809). Only an explicit `false`
|
|
68
|
+
* renders the "Not matching" badge; absent keeps the row unbadged so older
|
|
69
|
+
* consumers are unaffected.
|
|
70
|
+
*/
|
|
71
|
+
matchingEnabled?: boolean;
|
|
66
72
|
}
|
|
67
73
|
/** One card per product: primary variant + sibling versions (grouped by beverage). */
|
|
68
74
|
export interface ProductGroup<Item extends PortfolioProductItem = PortfolioProductItem> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/portfolio/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,CAAC;AAIpC,wFAAwF;AACxF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,8HAA8H;IAC9H,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kFAAkF;IAClF,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACrC,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;CAClC;AAED,gDAAgD;AAChD,MAAM,MAAM,qBAAqB,GAC7B,MAAM,GACN,aAAa,GACb,gBAAgB,GAChB,QAAQ,GACR,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC;AAIlB,iEAAiE;AACjE,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,YAAY,CAAC,EAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,IAAI,CAAC;CAC7E;AAED,uEAAuE;AACvE,MAAM,WAAW,uBAAuB;IACtC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACzC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;IACpC,4EAA4E;IAC5E,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;IACjC,oBAAoB,CAAC,EAAE;QACrB,GAAG,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,+IAA+I;QAC/I,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;QAC/B,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;KACjC,GAAG,IAAI,CAAC;IACT,QAAQ,CAAC,EAAE,wBAAwB,GAAG,IAAI,CAAC;CAC5C;AAED,sEAAsE;AACtE,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/portfolio/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"product-status-tab.d.ts","sourceRoot":"","sources":["../../../src/product-editor/tabs/product-status-tab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"product-status-tab.d.ts","sourceRoot":"","sources":["../../../src/product-editor/tabs/product-status-tab.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAqB,qBAAqB,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAC;AAI9F,MAAM,WAAW,qBAAqB;IACpC,MAAM,CAAC,EAAE,mBAAmB,CAAC;IAC7B,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;CAChD;AA4HD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAe,EAAE,CAAC,EAAE,EAAE,qBAAqB,2CAsV/F"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { ArrowUpRight, CheckCircle2 } from "lucide-react";
|
|
4
|
+
import { IncludeInMatchingToggle } from "../../portfolio/include-in-matching-toggle.js";
|
|
4
5
|
// ─── Helpers ─────────────────────────────────────────────────────────────────
|
|
5
6
|
/**
|
|
6
7
|
* Humanise a flagged-field path into a producer-facing label. We map known
|
|
@@ -134,12 +135,13 @@ export function ProductStatusTab({ status, features, isDirty = false, t }) {
|
|
|
134
135
|
if (!status) {
|
|
135
136
|
return (_jsx("div", { className: "rounded-xl border border-border/60 bg-muted/30 p-6 text-sm text-muted-foreground", children: tr("variantEdit.status.unavailable", "Status will appear after the product is saved.") }));
|
|
136
137
|
}
|
|
137
|
-
const { validationState: serverStatus, matchCount, flaggedFields, matchReadiness, onApprove, isApproving, extractedBy, reviewedBy, reviewedAt, citations, professionalSummary, } = status;
|
|
138
|
+
const { validationState: serverStatus, matchCount, flaggedFields, matchReadiness, onApprove, isApproving, matching, extractedBy, reviewedBy, reviewedAt, citations, professionalSummary, } = status;
|
|
138
139
|
// Server status is authoritative. The earlier CEL-576 timing optimization
|
|
139
140
|
// could apply an old request's completion after direct consumers reused this
|
|
140
141
|
// component for another product; consumers now publish the returned status.
|
|
141
142
|
const validationState = serverStatus;
|
|
142
|
-
const
|
|
143
|
+
const excludedFromMatching = matching?.enabled === false;
|
|
144
|
+
const isDiscoverable = validationState === "approved" && !excludedFromMatching;
|
|
143
145
|
const isPendingReview = serverStatus === "pending_review";
|
|
144
146
|
const hasCitations = Array.isArray(citations) && citations.length > 0;
|
|
145
147
|
// CEL-1830 — the backend's `canApprove` folds `blockers` AND
|
|
@@ -172,13 +174,24 @@ export function ProductStatusTab({ status, features, isDirty = false, t }) {
|
|
|
172
174
|
? "success"
|
|
173
175
|
: validationState === "pending_review"
|
|
174
176
|
? "warning"
|
|
175
|
-
: "neutral" }), _jsx(StatusCard, { label: tr("variantEdit.status.discoverability", "Discoverability"), value:
|
|
176
|
-
? tr("variantEdit.status.
|
|
177
|
-
:
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
:
|
|
177
|
+
: "neutral" }), _jsx(StatusCard, { label: tr("variantEdit.status.discoverability", "Discoverability"), value: excludedFromMatching
|
|
178
|
+
? tr("variantEdit.status.excluded", "Excluded from matching")
|
|
179
|
+
: isDiscoverable
|
|
180
|
+
? tr("variantEdit.status.discoverable", "Ready for matching")
|
|
181
|
+
: tr("variantEdit.status.notDiscoverable", "Not yet discoverable"), tone: isDiscoverable ? "success" : "neutral", helper: excludedFromMatching
|
|
182
|
+
? tr("variantEdit.status.excludedHelper", "This product is excluded from matching. Turn matching back on below to make it discoverable.")
|
|
183
|
+
: isDiscoverable
|
|
184
|
+
? (matchCount ?? 0) > 0
|
|
185
|
+
? tr("variantEdit.status.discoverableHelper", `Your product is discoverable. ${matchCount ?? 0} matches found so far.`)
|
|
186
|
+
: tr("variantEdit.status.discoverableNoMatchesHelper", "Your product is discoverable. No matches yet.")
|
|
187
|
+
: tr("variantEdit.status.notDiscoverableHelper", "Your product will become discoverable to importers once it's been reviewed and approved.") })] }), matching && (_jsx(IncludeInMatchingToggle, { checked: matching.enabled, onChange: (next) => {
|
|
188
|
+
void matching.onChange(next);
|
|
189
|
+
}, status: matching.isPending ? "pending" : matching.error ? "error" : undefined, copy: {
|
|
190
|
+
label: tr("variantEdit.status.matching.label", "Include in matching"),
|
|
191
|
+
included: tr("variantEdit.status.matching.included", "This product is matched with opportunities."),
|
|
192
|
+
excluded: tr("variantEdit.status.matching.excluded", "Excluded products are not matched with opportunities; existing matches are hidden."),
|
|
193
|
+
error: tr("variantEdit.status.matching.error", "Could not update matching. Your change was undone."),
|
|
194
|
+
} })), matchReadiness && (_jsxs("div", { className: "rounded-xl border border-border/60 bg-card p-5", children: [_jsxs("div", { className: "mb-4 flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsx("h4", { className: "text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: tr("matchReadiness.heading", "Match Readiness") }), _jsxs("span", { className: "text-sm font-medium text-foreground", children: [matchReadiness.completed, " / ", matchReadiness.total] })] }), _jsx("div", { role: "progressbar", "aria-label": tr("matchReadiness.heading", "Match Readiness"), "aria-valuenow": Math.round(matchReadiness.percent), "aria-valuemin": 0, "aria-valuemax": 100, "aria-valuetext": tr("matchReadiness.progressValueText", `${matchReadiness.completed} of ${matchReadiness.total} fields complete`), className: "h-2 w-full overflow-hidden rounded-full bg-muted", children: _jsx("div", { className: `h-full ${matchReadiness.percent === 100 ? "bg-[var(--tone-success-solid)]" : "bg-[var(--tone-warning-fg)]"} transition-[width,background-color] duration-500`, style: { width: `${Math.round(matchReadiness.percent)}%` } }) })] }), _jsxs("div", { className: "flex flex-col gap-5", children: [matchReadiness.blockers.length > 0 && (_jsxs("div", { children: [_jsx("h5", { className: "mb-3 text-xs font-semibold uppercase tracking-[0.14em] text-[var(--tone-warning-fg)]", children: tr("matchReadiness.blockersHeading", "Required before approval") }), _jsx("ul", { className: "flex flex-col gap-2", children: matchReadiness.blockers.map((entry) => (_jsxs("li", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-xl border border-[var(--tone-warning-border)]/40 bg-[var(--tone-warning-soft)] px-4 py-3", children: [_jsx("span", { className: "text-sm font-medium text-[var(--tone-warning-fg)]", children: tr(entry.labelKey, fieldLabel(entry.path, tr)) }), _jsx("span", { className: "inline-flex items-center rounded-full bg-[var(--tone-warning-fg)]/10 px-2.5 py-0.5 text-xs font-medium text-[var(--tone-warning-fg)]", children: readinessReasonLabel(entry.reason, tr) })] }, `blocker-${entry.path}`))) })] })), matchReadiness.recommendations.length > 0 && (_jsxs("div", { children: [_jsx("h5", { className: "mb-3 text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: tr("matchReadiness.recommendationsHeading", "Recommended before matching") }), _jsx("ul", { className: "flex flex-col gap-2", children: matchReadiness.recommendations.map((entry) => (_jsxs("li", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-xl border border-border/60 bg-muted/30 px-4 py-3", children: [_jsx("span", { className: "text-sm font-medium text-foreground", children: tr(entry.labelKey, fieldLabel(entry.path, tr)) }), _jsx("span", { className: "inline-flex items-center rounded-full bg-muted/60 px-2.5 py-0.5 text-xs font-medium text-muted-foreground", children: readinessReasonLabel(entry.reason, tr) })] }, `rec-${entry.path}`))) })] })), matchReadiness.acknowledgementsRequired.length > 0 && (_jsxs("div", { children: [_jsx("h5", { className: "mb-3 text-xs font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: tr("matchReadiness.acknowledgementsHeading", "Please confirm") }), _jsx("ul", { className: "flex flex-col gap-2", children: matchReadiness.acknowledgementsRequired.map((entry) => (_jsxs("li", { className: "flex flex-wrap items-center gap-x-3 gap-y-1.5 rounded-xl border border-border/60 bg-muted/30 px-4 py-3", children: [_jsx("span", { className: "text-sm font-medium text-foreground", children: tr(entry.labelKey, fieldLabel(entry.path, tr)) }), _jsx("span", { className: "inline-flex items-center rounded-full bg-[var(--tone-warning-soft)] px-2.5 py-0.5 text-xs font-medium text-[var(--tone-warning-fg)]", children: readinessReasonLabel(entry.reason, tr) })] }, `ack-${entry.path}`))) })] })), matchReadiness.blockers.length === 0 &&
|
|
182
195
|
matchReadiness.canApprove &&
|
|
183
196
|
matchReadiness.recommendations.length === 0 &&
|
|
184
197
|
matchReadiness.acknowledgementsRequired.length === 0 && (_jsxs("div", { className: "flex items-center gap-2 rounded-xl border border-[var(--tone-success-border)]/30 bg-[var(--tone-success-soft)]/30 px-4 py-3 text-sm text-[var(--tone-success-fg)]", children: [_jsx(CheckCircle2, { className: "size-4 shrink-0", "aria-hidden": "true" }), _jsx("span", { children: tr("matchReadiness.allComplete", "All required fields are complete.") })] }))] })] })), features?.approvalWorkflow && isPendingReview && onApprove && (_jsx(ApprovePanel, { hasUnsavedEdits: isDirty, isApproving: isApproving ?? false, readinessBlocked: readinessBlocked, needsAcknowledgement: needsAcknowledgement, onApprove: handleApprove, flaggedFields: flaggedFields ?? null, fieldLabelOf: (p) => fieldLabel(p, tr), reasonLabelOf: (r) => reasonLabel(r, tr), confidenceLabelOf: (c) => confidenceLabel(c, tr), tr: tr })), (extractedBy || reviewedBy || reviewedAt) && (_jsx(StatusCard, { label: tr("variantEdit.status.provenance", "Provenance"), value: extractedBy
|