@cellarnode/ui 0.190.0 → 0.192.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/components/country-flag.d.ts +19 -1
- package/dist/components/country-flag.d.ts.map +1 -1
- package/dist/components/country-flag.js +66 -11
- package/dist/components/country-flag.js.map +1 -1
- package/dist/markets/deadline.d.ts +35 -0
- package/dist/markets/deadline.d.ts.map +1 -0
- package/dist/markets/deadline.js +58 -0
- package/dist/markets/deadline.js.map +1 -0
- package/dist/markets/index.d.ts +4 -0
- package/dist/markets/index.d.ts.map +1 -0
- package/dist/markets/index.js +4 -0
- package/dist/markets/index.js.map +1 -0
- package/dist/markets/market-list-item.d.ts +41 -0
- package/dist/markets/market-list-item.d.ts.map +1 -0
- package/dist/markets/market-list-item.js +25 -0
- package/dist/markets/market-list-item.js.map +1 -0
- package/dist/markets/market-opportunities-table.d.ts +137 -0
- package/dist/markets/market-opportunities-table.d.ts.map +1 -0
- package/dist/markets/market-opportunities-table.js +282 -0
- package/dist/markets/market-opportunities-table.js.map +1 -0
- package/dist/markets/market-workspace-header.d.ts +53 -0
- package/dist/markets/market-workspace-header.d.ts.map +1 -0
- package/dist/markets/market-workspace-header.js +34 -0
- package/dist/markets/market-workspace-header.js.map +1 -0
- package/dist/opportunities/opportunities-table.d.ts +3 -1
- package/dist/opportunities/opportunities-table.d.ts.map +1 -1
- package/dist/opportunities/opportunities-table.js +24 -56
- package/dist/opportunities/opportunities-table.js.map +1 -1
- package/dist/opportunities/opportunity-detail-panel.d.ts +7 -0
- package/dist/opportunities/opportunity-detail-panel.d.ts.map +1 -1
- package/dist/opportunities/opportunity-detail-panel.js +2 -2
- package/dist/opportunities/opportunity-detail-panel.js.map +1 -1
- package/dist/opportunity-facts/edit-labels.d.ts +56 -0
- package/dist/opportunity-facts/edit-labels.d.ts.map +1 -0
- package/dist/opportunity-facts/edit-labels.js +37 -0
- package/dist/opportunity-facts/edit-labels.js.map +1 -0
- package/dist/opportunity-facts/editable-section.d.ts +119 -0
- package/dist/opportunity-facts/editable-section.d.ts.map +1 -0
- package/dist/opportunity-facts/editable-section.js +267 -0
- package/dist/opportunity-facts/editable-section.js.map +1 -0
- package/dist/opportunity-facts/index.d.ts +2 -0
- package/dist/opportunity-facts/index.d.ts.map +1 -1
- package/dist/opportunity-facts/index.js +1 -0
- package/dist/opportunity-facts/index.js.map +1 -1
- package/dist/opportunity-facts/opportunity-fact-sheet.d.ts +39 -1
- package/dist/opportunity-facts/opportunity-fact-sheet.d.ts.map +1 -1
- package/dist/opportunity-facts/opportunity-fact-sheet.js +285 -13
- package/dist/opportunity-facts/opportunity-fact-sheet.js.map +1 -1
- package/package.json +6 -1
|
@@ -1,6 +1,24 @@
|
|
|
1
1
|
export interface CountryFlagProps {
|
|
2
2
|
code: string;
|
|
3
3
|
className?: string;
|
|
4
|
+
/**
|
|
5
|
+
* Localised accessible name. Overrides the built-in English country name
|
|
6
|
+
* (and the "Unknown country" fallback).
|
|
7
|
+
*/
|
|
8
|
+
label?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Hide from assistive tech. Use when the country name is already visible as
|
|
11
|
+
* text next to the flag, so it is not announced twice.
|
|
12
|
+
*/
|
|
13
|
+
decorative?: boolean;
|
|
4
14
|
}
|
|
5
|
-
|
|
15
|
+
/** Test seam: forget the memoised flag set. */
|
|
16
|
+
export declare function __resetCountryFlagCacheForTests(): void;
|
|
17
|
+
/**
|
|
18
|
+
* CEL-2135 — renders real SVG flags (country-flag-icons, 3x2) rather than regional-indicator
|
|
19
|
+
* emoji, which Windows shows as two letters. The flag set is one lazy chunk (~49 KB gzip, fetched on first
|
|
20
|
+
* render); until it arrives the box is neutral, if it fails or the code is unknown the Globe shows,
|
|
21
|
+
* never letters.
|
|
22
|
+
*/
|
|
23
|
+
export declare function CountryFlag({ code, className, label, decorative }: CountryFlagProps): import("react/jsx-runtime").JSX.Element;
|
|
6
24
|
//# sourceMappingURL=country-flag.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"country-flag.d.ts","sourceRoot":"","sources":["../../src/components/country-flag.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"country-flag.d.ts","sourceRoot":"","sources":["../../src/components/country-flag.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAmED,+CAA+C;AAC/C,wBAAgB,+BAA+B,IAAI,IAAI,CAGtD;AAYD;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,gBAAgB,2CA6BnF"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
2
3
|
import { Globe } from "lucide-react";
|
|
3
4
|
import { COUNTRY_NAMES } from "../lib/country-registry.js";
|
|
4
5
|
import { cn } from "../lib/utils.js";
|
|
@@ -13,20 +14,74 @@ function countryName(code) {
|
|
|
13
14
|
const canonical = COUNTRY_ALIASES[code] ?? code;
|
|
14
15
|
return COUNTRY_NAMES[canonical];
|
|
15
16
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
/**
|
|
18
|
+
* The 3x2 flag set loads as ONE lazy chunk (the per-flag entry points all re-export the shared
|
|
19
|
+
* module, so splitting per flag would still download the whole set on the first flag). It is
|
|
20
|
+
* fetched only when a flag first renders and memoised so it is fetched once. A rejected load
|
|
21
|
+
* clears the memo so the next mount retries.
|
|
22
|
+
*/
|
|
23
|
+
let flagSet;
|
|
24
|
+
let flagSetPromise;
|
|
25
|
+
function loadFlagSet() {
|
|
26
|
+
flagSetPromise ??= import("country-flag-icons/react/3x2").then((m) => (flagSet = m), (error) => {
|
|
27
|
+
flagSetPromise = undefined;
|
|
28
|
+
throw error;
|
|
29
|
+
});
|
|
30
|
+
return flagSetPromise;
|
|
31
|
+
}
|
|
32
|
+
function useFlagStatus(code) {
|
|
33
|
+
const [failed, setFailed] = React.useState(false);
|
|
34
|
+
const [, rerender] = React.useReducer((n) => n + 1, 0);
|
|
35
|
+
const needsLoad = Boolean(code) && flagSet === undefined;
|
|
36
|
+
React.useEffect(() => {
|
|
37
|
+
if (!needsLoad)
|
|
38
|
+
return;
|
|
39
|
+
let live = true;
|
|
40
|
+
loadFlagSet().then(() => {
|
|
41
|
+
if (live)
|
|
42
|
+
rerender();
|
|
43
|
+
}, () => {
|
|
44
|
+
if (live)
|
|
45
|
+
setFailed(true); // chunk failed: show the Globe, never letters
|
|
46
|
+
});
|
|
47
|
+
return () => {
|
|
48
|
+
live = false;
|
|
49
|
+
};
|
|
50
|
+
}, [needsLoad]);
|
|
51
|
+
if (code && flagSet?.[code])
|
|
52
|
+
return "ready";
|
|
53
|
+
return failed || flagSet ? "failed" : "pending";
|
|
54
|
+
}
|
|
55
|
+
/** Test seam: forget the memoised flag set. */
|
|
56
|
+
export function __resetCountryFlagCacheForTests() {
|
|
57
|
+
flagSet = undefined;
|
|
58
|
+
flagSetPromise = undefined;
|
|
23
59
|
}
|
|
24
|
-
|
|
60
|
+
function renderFlag(code, className) {
|
|
61
|
+
const Flag = flagSet?.[code];
|
|
62
|
+
return Flag
|
|
63
|
+
? React.createElement(Flag, { "aria-hidden": true, focusable: false, className })
|
|
64
|
+
: null;
|
|
65
|
+
}
|
|
66
|
+
/** Same footprint the emoji had: one em tall, inline with the text, 3:2 like the SVG flags. */
|
|
67
|
+
const FLAG_BOX = "inline-block h-[1em] w-[1.5em] shrink-0 align-[-0.125em] rounded-xs";
|
|
68
|
+
/**
|
|
69
|
+
* CEL-2135 — renders real SVG flags (country-flag-icons, 3x2) rather than regional-indicator
|
|
70
|
+
* emoji, which Windows shows as two letters. The flag set is one lazy chunk (~49 KB gzip, fetched on first
|
|
71
|
+
* render); until it arrives the box is neutral, if it fails or the code is unknown the Globe shows,
|
|
72
|
+
* never letters.
|
|
73
|
+
*/
|
|
74
|
+
export function CountryFlag({ code, className, label, decorative }) {
|
|
25
75
|
const up = code?.toUpperCase() ?? "";
|
|
26
76
|
const name = countryName(up);
|
|
27
|
-
|
|
28
|
-
|
|
77
|
+
const canonical = name ? (COUNTRY_ALIASES[up] ?? up) : undefined;
|
|
78
|
+
const status = useFlagStatus(canonical);
|
|
79
|
+
if (!name || status === "failed") {
|
|
80
|
+
return (_jsx("span", { ...(decorative
|
|
81
|
+
? { "aria-hidden": true }
|
|
82
|
+
: { role: "img", "aria-label": label ?? name ?? "Unknown country" }), className: cn("inline-flex items-center text-muted-foreground", className), children: _jsx(Globe, { "aria-hidden": true, className: "size-4" }) }));
|
|
29
83
|
}
|
|
30
|
-
return (_jsx("span", { role: "img", "aria-label": name, className: cn("inline-block", className), children:
|
|
84
|
+
return (_jsx("span", { ...(decorative ? { "aria-hidden": true } : { role: "img", "aria-label": label ?? name }), className: cn("inline-block", className), children: (canonical &&
|
|
85
|
+
renderFlag(canonical, cn(FLAG_BOX, "ring-1 ring-foreground/10 ring-inset"))) || (_jsx("span", { "aria-hidden": true, className: cn(FLAG_BOX, "bg-muted") })) }));
|
|
31
86
|
}
|
|
32
87
|
//# sourceMappingURL=country-flag.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"country-flag.js","sourceRoot":"","sources":["../../src/components/country-flag.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"country-flag.js","sourceRoot":"","sources":["../../src/components/country-flag.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export type DeadlineInput = Date | string | null | undefined;
|
|
2
|
+
export declare function toDate(value: DeadlineInput): Date | null;
|
|
3
|
+
export interface DeadlineFormatting {
|
|
4
|
+
/** BCP 47 locale for the absolute date. Default `"en"`. */
|
|
5
|
+
locale?: string;
|
|
6
|
+
/** Override the relative text ("in 3 days"). Receives the reference `now`. */
|
|
7
|
+
formatRelative?: (date: Date, now: Date) => string;
|
|
8
|
+
/** Override the absolute text ("12 Oct 2026"). */
|
|
9
|
+
formatAbsolute?: (date: Date) => string;
|
|
10
|
+
}
|
|
11
|
+
export declare function formatAbsoluteDate(date: Date, f: DeadlineFormatting): string;
|
|
12
|
+
/**
|
|
13
|
+
* Relative text computed against the injected `now` (never the wall clock) and
|
|
14
|
+
* localised through `Intl.RelativeTimeFormat` with `numeric: "auto"`, so the
|
|
15
|
+
* text always agrees with the urgency icon and honours `locale`.
|
|
16
|
+
*/
|
|
17
|
+
export declare function formatRelativeDate(date: Date, now: Date, f: DeadlineFormatting): string;
|
|
18
|
+
export interface DeadlineValueProps extends DeadlineFormatting {
|
|
19
|
+
deadline: DeadlineInput;
|
|
20
|
+
now: Date;
|
|
21
|
+
/** When false (closed / expired / draft) no urgency emphasis is applied. */
|
|
22
|
+
emphasise?: boolean;
|
|
23
|
+
/** Text when there is no deadline. */
|
|
24
|
+
emptyLabel: string;
|
|
25
|
+
/** Stack relative over absolute (default) or inline them. */
|
|
26
|
+
layout?: "stacked" | "inline";
|
|
27
|
+
className?: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Relative + absolute deadline. Urgency is carried by icon AND text (never
|
|
31
|
+
* colour alone): past = calendar-x, within 7 days = clock in the warning tone,
|
|
32
|
+
* otherwise a calendar-clock in the default ink.
|
|
33
|
+
*/
|
|
34
|
+
export declare function DeadlineValue({ deadline, now, emphasise, emptyLabel, layout, className, locale, formatRelative, formatAbsolute, }: DeadlineValueProps): import("react/jsx-runtime").JSX.Element;
|
|
35
|
+
//# sourceMappingURL=deadline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deadline.d.ts","sourceRoot":"","sources":["../../src/markets/deadline.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,aAAa,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;AAE7D,wBAAgB,MAAM,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI,GAAG,IAAI,CAIxD;AAED,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,KAAK,MAAM,CAAC;IACnD,kDAAkD;IAClD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,MAAM,CAAC;CACzC;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAG5E;AAMD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,kBAAkB,GAAG,MAAM,CAWvF;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,QAAQ,EAAE,aAAa,CAAC;IACxB,GAAG,EAAE,IAAI,CAAC;IACV,4EAA4E;IAC5E,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,MAAM,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,EAC5B,QAAQ,EACR,GAAG,EACH,SAAgB,EAChB,UAAU,EACV,MAAkB,EAClB,SAAS,EACT,MAAM,EACN,cAAc,EACd,cAAc,GACf,EAAE,kBAAkB,2CA6CpB"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { CalendarClock, CalendarX, Clock } from "lucide-react";
|
|
3
|
+
import { cn } from "../lib/utils.js";
|
|
4
|
+
export function toDate(value) {
|
|
5
|
+
if (value == null || value === "")
|
|
6
|
+
return null;
|
|
7
|
+
const d = value instanceof Date ? value : new Date(value);
|
|
8
|
+
return Number.isNaN(d.getTime()) ? null : d;
|
|
9
|
+
}
|
|
10
|
+
export function formatAbsoluteDate(date, f) {
|
|
11
|
+
if (f.formatAbsolute)
|
|
12
|
+
return f.formatAbsolute(date);
|
|
13
|
+
return new Intl.DateTimeFormat(f.locale ?? "en", { dateStyle: "medium" }).format(date);
|
|
14
|
+
}
|
|
15
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
16
|
+
const MINUTE_MS = 60 * 1000;
|
|
17
|
+
const HOUR_MS = 60 * MINUTE_MS;
|
|
18
|
+
/**
|
|
19
|
+
* Relative text computed against the injected `now` (never the wall clock) and
|
|
20
|
+
* localised through `Intl.RelativeTimeFormat` with `numeric: "auto"`, so the
|
|
21
|
+
* text always agrees with the urgency icon and honours `locale`.
|
|
22
|
+
*/
|
|
23
|
+
export function formatRelativeDate(date, now, f) {
|
|
24
|
+
if (f.formatRelative)
|
|
25
|
+
return f.formatRelative(date, now);
|
|
26
|
+
const rtf = new Intl.RelativeTimeFormat(f.locale ?? "en", { numeric: "auto" });
|
|
27
|
+
const diff = date.getTime() - now.getTime();
|
|
28
|
+
const abs = Math.abs(diff);
|
|
29
|
+
if (abs < MINUTE_MS)
|
|
30
|
+
return rtf.format(0, "second");
|
|
31
|
+
if (abs < HOUR_MS)
|
|
32
|
+
return rtf.format(Math.trunc(diff / MINUTE_MS), "minute");
|
|
33
|
+
if (abs < DAY_MS)
|
|
34
|
+
return rtf.format(Math.trunc(diff / HOUR_MS), "hour");
|
|
35
|
+
if (abs < 30 * DAY_MS)
|
|
36
|
+
return rtf.format(Math.trunc(diff / DAY_MS), "day");
|
|
37
|
+
if (abs < 365 * DAY_MS)
|
|
38
|
+
return rtf.format(Math.trunc(diff / (30 * DAY_MS)), "month");
|
|
39
|
+
return rtf.format(Math.trunc(diff / (365 * DAY_MS)), "year");
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Relative + absolute deadline. Urgency is carried by icon AND text (never
|
|
43
|
+
* colour alone): past = calendar-x, within 7 days = clock in the warning tone,
|
|
44
|
+
* otherwise a calendar-clock in the default ink.
|
|
45
|
+
*/
|
|
46
|
+
export function DeadlineValue({ deadline, now, emphasise = true, emptyLabel, layout = "stacked", className, locale, formatRelative, formatAbsolute, }) {
|
|
47
|
+
const date = toDate(deadline);
|
|
48
|
+
if (!date) {
|
|
49
|
+
return _jsx("span", { className: cn("text-sm text-muted-foreground", className), children: emptyLabel });
|
|
50
|
+
}
|
|
51
|
+
const f = { locale, formatRelative, formatAbsolute };
|
|
52
|
+
const diff = date.getTime() - now.getTime();
|
|
53
|
+
const past = diff < 0;
|
|
54
|
+
const soon = !past && diff <= 7 * DAY_MS;
|
|
55
|
+
const Icon = past ? CalendarX : soon ? Clock : CalendarClock;
|
|
56
|
+
return (_jsxs("time", { dateTime: date.toISOString(), "data-urgency": emphasise ? (past ? "past" : soon ? "soon" : "later") : "none", className: cn("inline-flex items-start gap-1.5 text-sm", layout === "inline" && "items-center", className), children: [_jsx(Icon, { "aria-hidden": true, className: cn("mt-0.5 size-4 shrink-0", layout === "inline" && "mt-0", emphasise && soon ? "text-[var(--tone-warning-fg)]" : "text-muted-foreground") }), _jsxs("span", { className: cn("flex min-w-0 gap-x-1.5", layout === "stacked" ? "flex-col" : "flex-wrap"), children: [_jsx("span", { className: cn("font-medium", emphasise && soon ? "text-[var(--tone-warning-fg)]" : "text-foreground"), children: formatRelativeDate(date, now, f) }), _jsx("span", { className: "font-tabular text-xs text-muted-foreground", children: formatAbsoluteDate(date, f) })] })] }));
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=deadline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deadline.js","sourceRoot":"","sources":["../../src/markets/deadline.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { MarketWorkspaceHeader, defaultMarketWorkspaceHeaderLabels, type MarketOperationalMarket, type MarketWorkspaceHeaderLabels, type MarketWorkspaceHeaderProps, } from "./market-workspace-header.js";
|
|
2
|
+
export { MarketOpportunitiesTable, defaultMarketOpportunitiesTableLabels, defaultMarketStatusOptions, defaultMarketDeadlineOptions, defaultMarketSortOptions, defaultMarketSortColumns, type MarketSortableColumn, type MarketFilterOption, type MarketOpportunitiesTableLabels, type MarketOpportunitiesTableProps, type MarketOpportunityRow, } from "./market-opportunities-table.js";
|
|
3
|
+
export { MarketListItem, defaultMarketListItemLabels, type MarketListItemLabels, type MarketListItemLinkProps, type MarketListItemProps, } from "./market-list-item.js";
|
|
4
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/markets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,kCAAkC,EAClC,KAAK,uBAAuB,EAC5B,KAAK,2BAA2B,EAChC,KAAK,0BAA0B,GAChC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,EACxB,qCAAqC,EACrC,0BAA0B,EAC1B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,EACxB,KAAK,oBAAoB,EACzB,KAAK,kBAAkB,EACvB,KAAK,8BAA8B,EACnC,KAAK,6BAA6B,EAClC,KAAK,oBAAoB,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,cAAc,EACd,2BAA2B,EAC3B,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { MarketWorkspaceHeader, defaultMarketWorkspaceHeaderLabels, } from "./market-workspace-header.js";
|
|
2
|
+
export { MarketOpportunitiesTable, defaultMarketOpportunitiesTableLabels, defaultMarketStatusOptions, defaultMarketDeadlineOptions, defaultMarketSortOptions, defaultMarketSortColumns, } from "./market-opportunities-table.js";
|
|
3
|
+
export { MarketListItem, defaultMarketListItemLabels, } from "./market-list-item.js";
|
|
4
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/markets/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,kCAAkC,GAInC,MAAM,2BAA2B,CAAC;AACnC,OAAO,EACL,wBAAwB,EACxB,qCAAqC,EACrC,0BAA0B,EAC1B,4BAA4B,EAC5B,wBAAwB,EACxB,wBAAwB,GAMzB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,cAAc,EACd,2BAA2B,GAI5B,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type DeadlineFormatting, type DeadlineInput } from "./deadline.js";
|
|
3
|
+
export interface MarketListItemLabels {
|
|
4
|
+
/** "{n} open opportunities" style text. Receives the count. */
|
|
5
|
+
openOpportunities: (count: number) => string;
|
|
6
|
+
/** Screen-reader prefix for the next deadline, punctuation included, e.g. "Next deadline:". */
|
|
7
|
+
nextDeadline: string;
|
|
8
|
+
}
|
|
9
|
+
export declare const defaultMarketListItemLabels: MarketListItemLabels;
|
|
10
|
+
export interface MarketListItemLinkProps {
|
|
11
|
+
href: string;
|
|
12
|
+
className: string;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export interface MarketListItemProps extends DeadlineFormatting {
|
|
16
|
+
name: string;
|
|
17
|
+
/** ISO-3166 alpha-2 code. */
|
|
18
|
+
countryCode: string;
|
|
19
|
+
/** Localised country name used as the flag's accessible name. Defaults to the English ISO name. */
|
|
20
|
+
countryName?: string;
|
|
21
|
+
/** Already-localised market type label. */
|
|
22
|
+
marketType?: string | null;
|
|
23
|
+
/** Rendered only when a number (0 is a value). */
|
|
24
|
+
openOpportunityCount?: number | null;
|
|
25
|
+
/** Rendered only when present. */
|
|
26
|
+
nextDeadline?: DeadlineInput;
|
|
27
|
+
href: string;
|
|
28
|
+
/** Router-agnostic link: render the consumer's `<Link>` with the given props. Defaults to `<a>`. */
|
|
29
|
+
renderLink?: (props: MarketListItemLinkProps) => React.ReactNode;
|
|
30
|
+
/** Reference time for the relative deadline (tests, SSR). Default: render time. */
|
|
31
|
+
now?: Date;
|
|
32
|
+
labels?: Partial<MarketListItemLabels>;
|
|
33
|
+
className?: string;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* One row of the `/market` list (CEL-2135). The whole row is a single link.
|
|
37
|
+
* Renders an `<li>`: place it inside a `<ul>`. The open count and next
|
|
38
|
+
* deadline appear only when the backend supplied them.
|
|
39
|
+
*/
|
|
40
|
+
export declare function MarketListItem({ name, countryCode, countryName, marketType, openOpportunityCount, nextDeadline, href, renderLink, now, labels: labelsProp, className, locale, formatRelative, formatAbsolute, }: MarketListItemProps): import("react/jsx-runtime").JSX.Element;
|
|
41
|
+
//# sourceMappingURL=market-list-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"market-list-item.d.ts","sourceRoot":"","sources":["../../src/markets/market-list-item.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,OAAO,EAAyB,KAAK,kBAAkB,EAAE,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhG,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,iBAAiB,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C,+FAA+F;IAC/F,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,2BAA2B,EAAE,oBAGzC,CAAC;AAEF,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAoB,SAAQ,kBAAkB;IAC7D,IAAI,EAAE,MAAM,CAAC;IACb,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,mGAAmG;IACnG,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2CAA2C;IAC3C,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kDAAkD;IAClD,oBAAoB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,kCAAkC;IAClC,YAAY,CAAC,EAAE,aAAa,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,oGAAoG;IACpG,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,KAAK,CAAC,SAAS,CAAC;IACjE,mFAAmF;IACnF,GAAG,CAAC,EAAE,IAAI,CAAC;IACX,MAAM,CAAC,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,EAC7B,IAAI,EACJ,WAAW,EACX,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EACT,MAAM,EACN,cAAc,EACd,cAAc,GACf,EAAE,mBAAmB,2CA8DrB"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { CalendarClock, ChevronRight } from "lucide-react";
|
|
4
|
+
import { CountryFlag } from "../components/country-flag.js";
|
|
5
|
+
import { cn } from "../lib/utils.js";
|
|
6
|
+
import { DeadlineValue, toDate } from "./deadline.js";
|
|
7
|
+
export const defaultMarketListItemLabels = {
|
|
8
|
+
openOpportunities: (n) => `${n} open ${n === 1 ? "opportunity" : "opportunities"}`,
|
|
9
|
+
nextDeadline: "Next deadline:",
|
|
10
|
+
};
|
|
11
|
+
/**
|
|
12
|
+
* One row of the `/market` list (CEL-2135). The whole row is a single link.
|
|
13
|
+
* Renders an `<li>`: place it inside a `<ul>`. The open count and next
|
|
14
|
+
* deadline appear only when the backend supplied them.
|
|
15
|
+
*/
|
|
16
|
+
export function MarketListItem({ name, countryCode, countryName, marketType, openOpportunityCount, nextDeadline, href, renderLink, now, labels: labelsProp, className, locale, formatRelative, formatAbsolute, }) {
|
|
17
|
+
const labels = { ...defaultMarketListItemLabels, ...labelsProp };
|
|
18
|
+
const [fallbackNow] = React.useState(() => new Date());
|
|
19
|
+
const hasCount = typeof openOpportunityCount === "number";
|
|
20
|
+
const deadline = toDate(nextDeadline);
|
|
21
|
+
const linkClass = cn("group flex items-center gap-4 rounded-lg px-4 py-4 outline-hidden transition-colors duration-[var(--duration-micro)] hover:bg-muted/60 focus-visible:ring-3 focus-visible:ring-ring/70 focus-visible:ring-inset");
|
|
22
|
+
const content = (_jsxs(_Fragment, { children: [_jsx(CountryFlag, { code: countryCode, label: countryName, className: "shrink-0 text-2xl/6" }), _jsxs("span", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [_jsx("span", { className: "truncate text-base font-semibold text-foreground", children: name }), marketType ? (_jsx("span", { className: "truncate text-sm text-muted-foreground", children: marketType })) : null] }), hasCount || deadline ? (_jsxs("span", { className: "flex shrink-0 flex-col items-end gap-1 text-right", children: [hasCount ? (_jsx("span", { className: "font-tabular text-sm font-medium text-foreground", children: labels.openOpportunities(openOpportunityCount) })) : null, deadline ? (_jsxs("span", { className: "inline-flex items-center gap-1.5 text-xs text-muted-foreground", children: [_jsx(CalendarClock, { "aria-hidden": true, className: "size-3.5" }), _jsxs("span", { className: "sr-only", children: [labels.nextDeadline, " "] }), _jsx(DeadlineValue, { deadline: deadline, now: now ?? fallbackNow, emptyLabel: "", layout: "inline", emphasise: false, locale: locale, formatRelative: formatRelative, formatAbsolute: formatAbsolute, className: "text-xs [&>svg]:hidden" })] })) : null] })) : null, _jsx(ChevronRight, { "aria-hidden": true, className: "size-4 shrink-0 text-muted-foreground transition-transform duration-[var(--duration-micro)] group-hover:translate-x-0.5 motion-reduce:transition-none" })] }));
|
|
23
|
+
return (_jsx("li", { "data-slot": "market-list-item", className: cn("list-none", className), children: renderLink ? (renderLink({ href, className: linkClass, children: content })) : (_jsx("a", { href: href, className: linkClass, children: content })) }));
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=market-list-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"market-list-item.js","sourceRoot":"","sources":["../../src/markets/market-list-item.tsx"],"names":[],"mappings":";AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAC;AACzD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAClC,OAAO,EAAE,aAAa,EAAE,MAAM,EAA+C,MAAM,YAAY,CAAC;AAShG,MAAM,CAAC,MAAM,2BAA2B,GAAyB;IAC/D,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,eAAe,EAAE;IAClF,YAAY,EAAE,gBAAgB;CAC/B,CAAC;AA6BF;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,IAAI,EACJ,WAAW,EACX,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,YAAY,EACZ,IAAI,EACJ,UAAU,EACV,GAAG,EACH,MAAM,EAAE,UAAU,EAClB,SAAS,EACT,MAAM,EACN,cAAc,EACd,cAAc,GACM;IACpB,MAAM,MAAM,GAAG,EAAE,GAAG,2BAA2B,EAAE,GAAG,UAAU,EAAE,CAAC;IACjE,MAAM,CAAC,WAAW,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,OAAO,oBAAoB,KAAK,QAAQ,CAAC;IAC1D,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAG,EAAE,CAClB,iNAAiN,CAClN,CAAC;IACF,MAAM,OAAO,GAAG,CACd,8BACE,KAAC,WAAW,IAAC,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAC,qBAAqB,GAAG,EACtF,gBAAM,SAAS,EAAC,oCAAoC,aAClD,eAAM,SAAS,EAAC,kDAAkD,YAAE,IAAI,GAAQ,EAC/E,UAAU,CAAC,CAAC,CAAC,CACZ,eAAM,SAAS,EAAC,wCAAwC,YAAE,UAAU,GAAQ,CAC7E,CAAC,CAAC,CAAC,IAAI,IACH,EACN,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CACtB,gBAAM,SAAS,EAAC,mDAAmD,aAChE,QAAQ,CAAC,CAAC,CAAC,CACV,eAAM,SAAS,EAAC,kDAAkD,YAC/D,MAAM,CAAC,iBAAiB,CAAC,oBAAoB,CAAC,GAC1C,CACR,CAAC,CAAC,CAAC,IAAI,EACP,QAAQ,CAAC,CAAC,CAAC,CACV,gBAAM,SAAS,EAAC,gEAAgE,aAC9E,KAAC,aAAa,yBAAa,SAAS,EAAC,UAAU,GAAG,EAClD,gBAAM,SAAS,EAAC,SAAS,aAAE,MAAM,CAAC,YAAY,SAAS,EACvD,KAAC,aAAa,IACZ,QAAQ,EAAE,QAAQ,EAClB,GAAG,EAAE,GAAG,IAAI,WAAW,EACvB,UAAU,EAAC,EAAE,EACb,MAAM,EAAC,QAAQ,EACf,SAAS,EAAE,KAAK,EAChB,MAAM,EAAE,MAAM,EACd,cAAc,EAAE,cAAc,EAC9B,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAC,wBAAwB,GAClC,IACG,CACR,CAAC,CAAC,CAAC,IAAI,IACH,CACR,CAAC,CAAC,CAAC,IAAI,EACR,KAAC,YAAY,yBAEX,SAAS,EAAC,uJAAuJ,GACjK,IACD,CACJ,CAAC;IAEF,OAAO,CACL,0BAAc,kBAAkB,EAAC,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,YACnE,UAAU,CAAC,CAAC,CAAC,CACZ,UAAU,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAC9D,CAAC,CAAC,CAAC,CACF,YAAG,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,SAAS,YAChC,OAAO,GACN,CACL,GACE,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import type { OpportunityChannelType, OpportunityLifecycleStatus } from "../opportunities/types.js";
|
|
3
|
+
import { type DeadlineFormatting, type DeadlineInput } from "./deadline.js";
|
|
4
|
+
export interface MarketOpportunityRow {
|
|
5
|
+
id: string;
|
|
6
|
+
name: string;
|
|
7
|
+
deadline?: DeadlineInput;
|
|
8
|
+
status: OpportunityLifecycleStatus;
|
|
9
|
+
/** Already-formatted volume ("12,000 L"); the table does not format units. */
|
|
10
|
+
volumeLabel?: string | null;
|
|
11
|
+
channel?: OpportunityChannelType | null;
|
|
12
|
+
/** For an importer-channel row: the creating org, shown as "Direct from {name}". */
|
|
13
|
+
creatorOrgName?: string | null;
|
|
14
|
+
/** Offers THIS viewer can see. `null` / `undefined` renders "not set"; `0` renders 0 with no link. */
|
|
15
|
+
offersReceivedCount?: number | null;
|
|
16
|
+
}
|
|
17
|
+
export interface MarketFilterOption {
|
|
18
|
+
value: string;
|
|
19
|
+
label: string;
|
|
20
|
+
}
|
|
21
|
+
export interface MarketOpportunitiesTableLabels {
|
|
22
|
+
tableCaption: string;
|
|
23
|
+
searchLabel: string;
|
|
24
|
+
searchPlaceholder: string;
|
|
25
|
+
statusFilterLabel: string;
|
|
26
|
+
deadlineFilterLabel: string;
|
|
27
|
+
sortLabel: string;
|
|
28
|
+
filterAndSort: string;
|
|
29
|
+
/** Collapsed toggle when filters are active: "Filter and sort (2)". */
|
|
30
|
+
filterAndSortWithCount: (count: number) => string;
|
|
31
|
+
columnName: string;
|
|
32
|
+
columnDeadline: string;
|
|
33
|
+
columnStatus: string;
|
|
34
|
+
columnVolume: string;
|
|
35
|
+
columnChannel: string;
|
|
36
|
+
columnOffers: string;
|
|
37
|
+
expandRow: (name: string) => string;
|
|
38
|
+
collapseRow: (name: string) => string;
|
|
39
|
+
detailsRegion: (name: string) => string;
|
|
40
|
+
notSet: string;
|
|
41
|
+
noDeadline: string;
|
|
42
|
+
offersCount: (count: number) => string;
|
|
43
|
+
/** Shown instead of a count when there are no offers. */
|
|
44
|
+
noOffers: string;
|
|
45
|
+
resultCount: (total: number) => string;
|
|
46
|
+
loading: string;
|
|
47
|
+
emptyHeadline: string;
|
|
48
|
+
emptyDescription: string;
|
|
49
|
+
filteredEmptyHeadline: string;
|
|
50
|
+
filteredEmptyDescription: string;
|
|
51
|
+
clearFilters: string;
|
|
52
|
+
errorHeadline: string;
|
|
53
|
+
errorDescription: string;
|
|
54
|
+
retry: string;
|
|
55
|
+
paginationLabel: string;
|
|
56
|
+
previousPage: string;
|
|
57
|
+
nextPage: string;
|
|
58
|
+
showingRange: (from: number, to: number, total: number) => string;
|
|
59
|
+
statusLabels: Record<OpportunityLifecycleStatus, string>;
|
|
60
|
+
}
|
|
61
|
+
export declare const defaultMarketOpportunitiesTableLabels: MarketOpportunitiesTableLabels;
|
|
62
|
+
export declare const defaultMarketStatusOptions: readonly MarketFilterOption[];
|
|
63
|
+
export declare const defaultMarketDeadlineOptions: readonly MarketFilterOption[];
|
|
64
|
+
export declare const defaultMarketSortOptions: readonly MarketFilterOption[];
|
|
65
|
+
export type MarketSortableColumn = "name" | "deadline";
|
|
66
|
+
/** Sort values a sortable column header toggles between. Must exist in `sortOptions`. */
|
|
67
|
+
export declare const defaultMarketSortColumns: Readonly<Record<MarketSortableColumn, {
|
|
68
|
+
asc: string;
|
|
69
|
+
desc: string;
|
|
70
|
+
}>>;
|
|
71
|
+
export interface MarketOpportunitiesTableProps extends DeadlineFormatting {
|
|
72
|
+
rows: readonly MarketOpportunityRow[];
|
|
73
|
+
/** Total matching rows across all pages (for the count and pagination). Defaults to `rows.length`. */
|
|
74
|
+
total?: number;
|
|
75
|
+
search: string;
|
|
76
|
+
onSearchChange: (value: string) => void;
|
|
77
|
+
status: string;
|
|
78
|
+
onStatusChange: (value: string) => void;
|
|
79
|
+
deadline: string;
|
|
80
|
+
onDeadlineChange: (value: string) => void;
|
|
81
|
+
sort: string;
|
|
82
|
+
onSortChange: (value: string) => void;
|
|
83
|
+
statusOptions?: readonly MarketFilterOption[];
|
|
84
|
+
deadlineOptions?: readonly MarketFilterOption[];
|
|
85
|
+
sortOptions?: readonly MarketFilterOption[];
|
|
86
|
+
/**
|
|
87
|
+
* Sortable column headers (table layout). Clicking an inactive header selects
|
|
88
|
+
* its `asc` value; clicking the active one flips asc and desc. Stays in sync
|
|
89
|
+
* with `sort` and the sort select. Omit a column to make it non-sortable.
|
|
90
|
+
*/
|
|
91
|
+
sortColumns?: Partial<Record<MarketSortableColumn, {
|
|
92
|
+
asc: string;
|
|
93
|
+
desc: string;
|
|
94
|
+
}>>;
|
|
95
|
+
/** Number of active filters, shown on the collapsed narrow-layout toggle. */
|
|
96
|
+
activeFilterCount?: number;
|
|
97
|
+
/** True when anything differs from the consumer's default view. Drives the filtered-empty state. */
|
|
98
|
+
hasActiveFilters?: boolean;
|
|
99
|
+
onClearFilters?: () => void;
|
|
100
|
+
isLoading?: boolean;
|
|
101
|
+
isError?: boolean;
|
|
102
|
+
onRetry?: () => void;
|
|
103
|
+
/** Offset pagination (1-based page). Chrome renders only when `total > pageSize`. */
|
|
104
|
+
page?: number;
|
|
105
|
+
pageSize?: number;
|
|
106
|
+
onPageChange?: (page: number) => void;
|
|
107
|
+
/** Slot for a page-size control, rendered in the pagination footer. */
|
|
108
|
+
pageSizeSlot?: React.ReactNode;
|
|
109
|
+
/** In-place expansion. One row at a time. */
|
|
110
|
+
renderExpanded?: (row: MarketOpportunityRow) => React.ReactNode;
|
|
111
|
+
/** Optional controlled expansion. Omit for internal state. */
|
|
112
|
+
expandedId?: string | null;
|
|
113
|
+
onExpandedChange?: (id: string | null) => void;
|
|
114
|
+
/** Wrap the offers count in a consumer link. Called only when the count is above zero. */
|
|
115
|
+
renderOffersLink?: (row: MarketOpportunityRow, children: React.ReactNode) => React.ReactNode;
|
|
116
|
+
/** Per-channel label override for i18n ("Direct from {name}" is passed already resolved). */
|
|
117
|
+
channelLabel?: (row: MarketOpportunityRow) => string | undefined;
|
|
118
|
+
/**
|
|
119
|
+
* `auto` (default) switches on the width of the component itself (a container
|
|
120
|
+
* check, not the viewport): table at 720px and wider, cards below.
|
|
121
|
+
*/
|
|
122
|
+
layout?: "auto" | "table" | "cards";
|
|
123
|
+
/** Reference time for relative deadlines (tests, SSR). Default: render time. */
|
|
124
|
+
now?: Date;
|
|
125
|
+
labels?: Partial<MarketOpportunitiesTableLabels>;
|
|
126
|
+
className?: string;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Opportunities of one assigned market (CEL-2135): a desktop table that becomes
|
|
130
|
+
* a card list on narrow containers. Fully controlled toolbar (search, status,
|
|
131
|
+
* deadline, sort), in-place row expansion through `renderExpanded` (one row at
|
|
132
|
+
* a time, `aria-expanded`, Escape closes), and loading / empty / filtered-empty
|
|
133
|
+
* / error / offset-pagination states. Router-agnostic: the offers count links
|
|
134
|
+
* through `renderOffersLink`.
|
|
135
|
+
*/
|
|
136
|
+
export declare function MarketOpportunitiesTable(props: MarketOpportunitiesTableProps): import("react/jsx-runtime").JSX.Element;
|
|
137
|
+
//# sourceMappingURL=market-opportunities-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"market-opportunities-table.d.ts","sourceRoot":"","sources":["../../src/markets/market-opportunities-table.tsx"],"names":[],"mappings":"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"}
|