@cellarnode/ui 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +238 -0
- package/dist/chat/chat-toggle-button.d.ts +6 -3
- package/dist/chat/chat-toggle-button.d.ts.map +1 -1
- package/dist/chat/chat-toggle-button.js +9 -4
- package/dist/chat/chat-toggle-button.js.map +1 -1
- package/dist/chat/messenger-layout.d.ts.map +1 -1
- package/dist/chat/messenger-layout.js +7 -2
- package/dist/chat/messenger-layout.js.map +1 -1
- package/dist/components/stat-card.d.ts +12 -0
- package/dist/components/stat-card.d.ts.map +1 -0
- package/dist/components/stat-card.js +10 -0
- package/dist/components/stat-card.js.map +1 -0
- package/dist/globe/country-coords.d.ts +29 -0
- package/dist/globe/country-coords.d.ts.map +1 -0
- package/dist/globe/country-coords.js +117 -0
- package/dist/globe/country-coords.js.map +1 -0
- package/dist/globe/globe-loading-skeleton.d.ts +10 -0
- package/dist/globe/globe-loading-skeleton.d.ts.map +1 -0
- package/dist/globe/globe-loading-skeleton.js +23 -0
- package/dist/globe/globe-loading-skeleton.js.map +1 -0
- package/dist/globe/index.d.ts +2 -0
- package/dist/globe/index.d.ts.map +1 -1
- package/dist/globe/index.js +2 -0
- package/dist/globe/index.js.map +1 -1
- package/dist/hooks/use-deferred-mount.d.ts +16 -0
- package/dist/hooks/use-deferred-mount.d.ts.map +1 -0
- package/dist/hooks/use-deferred-mount.js +32 -0
- package/dist/hooks/use-deferred-mount.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/nav/app-shell.d.ts +18 -0
- package/dist/nav/app-shell.d.ts.map +1 -0
- package/dist/nav/app-shell.js +9 -0
- package/dist/nav/app-shell.js.map +1 -0
- package/dist/nav/app-sidebar.d.ts +33 -0
- package/dist/nav/app-sidebar.d.ts.map +1 -0
- package/dist/nav/app-sidebar.js +46 -0
- package/dist/nav/app-sidebar.js.map +1 -0
- package/dist/nav/expandable-nav-item.d.ts +11 -0
- package/dist/nav/expandable-nav-item.d.ts.map +1 -0
- package/dist/nav/expandable-nav-item.js +27 -0
- package/dist/nav/expandable-nav-item.js.map +1 -0
- package/dist/nav/index.d.ts +6 -0
- package/dist/nav/index.d.ts.map +1 -0
- package/dist/nav/index.js +5 -0
- package/dist/nav/index.js.map +1 -0
- package/dist/nav/types.d.ts +40 -0
- package/dist/nav/types.d.ts.map +1 -0
- package/dist/nav/types.js +4 -0
- package/dist/nav/types.js.map +1 -0
- package/dist/opportunities/index.d.ts +3 -0
- package/dist/opportunities/index.d.ts.map +1 -0
- package/dist/opportunities/index.js +2 -0
- package/dist/opportunities/index.js.map +1 -0
- package/dist/opportunities/opportunities-table.d.ts +23 -0
- package/dist/opportunities/opportunities-table.d.ts.map +1 -0
- package/dist/opportunities/opportunities-table.js +115 -0
- package/dist/opportunities/opportunities-table.js.map +1 -0
- package/dist/profile/index.d.ts +2 -0
- package/dist/profile/index.d.ts.map +1 -0
- package/dist/profile/index.js +2 -0
- package/dist/profile/index.js.map +1 -0
- package/dist/profile/profile.d.ts +50 -0
- package/dist/profile/profile.d.ts.map +1 -0
- package/dist/profile/profile.js +30 -0
- package/dist/profile/profile.js.map +1 -0
- package/package.json +24 -2
- package/src/theme/tokens.css +6 -0
package/dist/globe/index.js
CHANGED
|
@@ -4,4 +4,6 @@ export { numericToAlpha2, alpha2ToNumeric } from "./map/country-code-map";
|
|
|
4
4
|
export { useElectronEmitter } from "./electron-arc";
|
|
5
5
|
export { GlobeView } from "./globe-view";
|
|
6
6
|
export { addStarfield, addHalo, getVignetteStyle } from "./scene-extras";
|
|
7
|
+
export { GlobeLoadingSkeleton } from "./globe-loading-skeleton";
|
|
8
|
+
export { countryCoords, resolveCountries, COUNTRY_COORDS } from "./country-coords";
|
|
7
9
|
//# sourceMappingURL=index.js.map
|
package/dist/globe/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/globe/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGjG,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/globe/index.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAGjG,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC3F,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAEzE,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Defers mounting of heavy components (e.g. WebGL globe) until the browser is
|
|
3
|
+
* idle, preventing them from blocking the main thread during initial page paint.
|
|
4
|
+
*
|
|
5
|
+
* Uses `requestIdleCallback` with a `setTimeout` fallback for browsers that
|
|
6
|
+
* don't support it (Safari < 18).
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* function GlobeWrapper() {
|
|
10
|
+
* const mounted = useDeferredMount();
|
|
11
|
+
* if (!mounted) return <Skeleton className="h-96 w-full rounded-xl" />;
|
|
12
|
+
* return <Suspense fallback={<Skeleton />}><GlobeView /></Suspense>;
|
|
13
|
+
* }
|
|
14
|
+
*/
|
|
15
|
+
export declare function useDeferredMount(delayMs?: number): boolean;
|
|
16
|
+
//# sourceMappingURL=use-deferred-mount.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-deferred-mount.d.ts","sourceRoot":"","sources":["../../src/hooks/use-deferred-mount.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,SAAK,GAAG,OAAO,CAmBtD"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Defers mounting of heavy components (e.g. WebGL globe) until the browser is
|
|
4
|
+
* idle, preventing them from blocking the main thread during initial page paint.
|
|
5
|
+
*
|
|
6
|
+
* Uses `requestIdleCallback` with a `setTimeout` fallback for browsers that
|
|
7
|
+
* don't support it (Safari < 18).
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* function GlobeWrapper() {
|
|
11
|
+
* const mounted = useDeferredMount();
|
|
12
|
+
* if (!mounted) return <Skeleton className="h-96 w-full rounded-xl" />;
|
|
13
|
+
* return <Suspense fallback={<Skeleton />}><GlobeView /></Suspense>;
|
|
14
|
+
* }
|
|
15
|
+
*/
|
|
16
|
+
export function useDeferredMount(delayMs = 50) {
|
|
17
|
+
const [mounted, setMounted] = useState(false);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let handle;
|
|
20
|
+
if (typeof requestIdleCallback !== "undefined") {
|
|
21
|
+
handle = requestIdleCallback(() => setMounted(true), {
|
|
22
|
+
timeout: delayMs,
|
|
23
|
+
});
|
|
24
|
+
return () => cancelIdleCallback(handle);
|
|
25
|
+
}
|
|
26
|
+
// Safari fallback
|
|
27
|
+
const timer = setTimeout(() => setMounted(true), delayMs);
|
|
28
|
+
return () => clearTimeout(timer);
|
|
29
|
+
}, [delayMs]);
|
|
30
|
+
return mounted;
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=use-deferred-mount.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-deferred-mount.js","sourceRoot":"","sources":["../../src/hooks/use-deferred-mount.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAO,GAAG,EAAE;IAC3C,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAc,CAAC;QAEnB,IAAI,OAAO,mBAAmB,KAAK,WAAW,EAAE,CAAC;YAC/C,MAAM,GAAG,mBAAmB,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE;gBACnD,OAAO,EAAE,OAAO;aACjB,CAAC,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAC1C,CAAC;QAED,kBAAkB;QAClB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;QAC1D,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { toneClass, offerStatusTone, type SemanticTone, } from "./lib/semantic-t
|
|
|
3
3
|
export { COMMON_CURRENCIES, type CurrencyCode } from "./lib/currencies";
|
|
4
4
|
export { useIsMobile } from "./hooks/use-mobile";
|
|
5
5
|
export { useToast, toast as radixToast } from "./hooks/use-toast";
|
|
6
|
+
export { useDeferredMount } from "./hooks/use-deferred-mount";
|
|
6
7
|
export * from "./components/accordion";
|
|
7
8
|
export * from "./components/alert";
|
|
8
9
|
export * from "./components/avatar";
|
|
@@ -57,4 +58,6 @@ export { AnimatedList } from "./components/animated-list";
|
|
|
57
58
|
export type { AnimatedListItem, AnimatedListProps } from "./components/animated-list";
|
|
58
59
|
export { ClassificationSelect } from "./components/classification-select";
|
|
59
60
|
export type { ClassificationSelectProps, CategoryOption } from "./components/classification-select";
|
|
61
|
+
export { StatCard } from "./components/stat-card";
|
|
62
|
+
export type { StatCardProps } from "./components/stat-card";
|
|
60
63
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,SAAS,EACT,eAAe,EACf,KAAK,YAAY,GAClB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAE,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAGxE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { COMMON_CURRENCIES } from "./lib/currencies";
|
|
|
4
4
|
// Hooks
|
|
5
5
|
export { useIsMobile } from "./hooks/use-mobile";
|
|
6
6
|
export { useToast, toast as radixToast } from "./hooks/use-toast";
|
|
7
|
+
export { useDeferredMount } from "./hooks/use-deferred-mount";
|
|
7
8
|
// Components (alphabetical)
|
|
8
9
|
export * from "./components/accordion";
|
|
9
10
|
export * from "./components/alert";
|
|
@@ -66,4 +67,5 @@ export { ShadcnDialog, ShadcnDialogClose, ShadcnDialogContent, ShadcnDialogDescr
|
|
|
66
67
|
export { ShadcnSelect, ShadcnSelectContent, ShadcnSelectGroup, ShadcnSelectItem, ShadcnSelectScrollDownButton, ShadcnSelectScrollUpButton, ShadcnSelectTrigger, ShadcnSelectValue, } from "./components/shadcn-select";
|
|
67
68
|
export { AnimatedList } from "./components/animated-list";
|
|
68
69
|
export { ClassificationSelect } from "./components/classification-select";
|
|
70
|
+
export { StatCard } from "./components/stat-card";
|
|
69
71
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,aAAa,CAAC;AACjC,OAAO,EACL,SAAS,EACT,eAAe,GAEhB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,iBAAiB,EAAqB,MAAM,kBAAkB,CAAC;AAExE,QAAQ;AACR,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,KAAK,IAAI,UAAU,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
interface AppShellProps {
|
|
3
|
+
/** The rendered sidebar content (e.g. <AppSidebar ...props />) */
|
|
4
|
+
sidebar: React.ReactNode;
|
|
5
|
+
/** Main page content */
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
/** Page title for mobile top bar */
|
|
8
|
+
mobileTitle?: string;
|
|
9
|
+
/** Right-side slot for mobile top bar (notifications, avatar, etc.) */
|
|
10
|
+
mobileTray?: React.ReactNode;
|
|
11
|
+
/** Floating overlay (e.g. Chat FAB) rendered outside the scroll area */
|
|
12
|
+
overlay?: React.ReactNode;
|
|
13
|
+
/** Optional extra class on the main content wrapper */
|
|
14
|
+
contentClassName?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function AppShell({ sidebar, children, mobileTitle, mobileTray, overlay, contentClassName, }: AppShellProps): import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=app-shell.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-shell.d.ts","sourceRoot":"","sources":["../../src/nav/app-shell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAIxC,UAAU,aAAa;IACrB,kEAAkE;IAClE,OAAO,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,wBAAwB;IACxB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,uEAAuE;IACvE,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC7B,wEAAwE;IACxE,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,uDAAuD;IACvD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,WAAW,EACX,UAAU,EACV,OAAO,EACP,gBAAgB,GACjB,EAAE,aAAa,2CAgFf"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { Sheet, SheetContent, SheetTitle } from "../components/sheet";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
export function AppShell({ sidebar, children, mobileTitle, mobileTray, overlay, contentClassName, }) {
|
|
6
|
+
const [mobileOpen, setMobileOpen] = useState(false);
|
|
7
|
+
return (_jsxs("div", { className: "min-h-dvh", children: [_jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: _jsxs(SheetContent, { side: "left", className: "w-72 max-w-xs p-0 border-r-0 [&>button]:hidden", "aria-describedby": undefined, children: [_jsx(SheetTitle, { className: "sr-only", children: "Navigation" }), _jsx("div", { className: "flex h-full flex-col", children: sidebar })] }) }), _jsx("div", { className: "hidden lg:fixed lg:inset-y-0 lg:z-50 lg:flex lg:w-72 lg:flex-col", children: sidebar }), _jsxs("div", { className: cn("lg:pl-72 flex flex-col min-h-dvh", contentClassName), children: [_jsxs("div", { className: "sticky top-0 z-40 flex h-16 shrink-0 items-center gap-x-4 border-b border-border bg-card px-4 shadow-xs sm:gap-x-6 sm:px-6 lg:hidden", children: [_jsx("button", { type: "button", onClick: () => setMobileOpen(true), className: "-m-2.5 p-2.5 text-foreground", "aria-label": "Open sidebar", children: _jsx("svg", { className: "size-6", fill: "none", viewBox: "0 0 24 24", strokeWidth: 1.5, stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" }) }) }), _jsx("div", { "aria-hidden": "true", className: "h-6 w-px bg-border" }), _jsxs("div", { className: "flex items-center gap-2 truncate", children: [_jsx("img", { src: "/android-chrome-192x192.png", alt: "", className: "size-4 shrink-0 rounded-xs" }), mobileTitle && (_jsx("span", { className: "text-sm font-semibold font-display text-foreground truncate", children: mobileTitle }))] }), mobileTray && (_jsx("div", { className: "ml-auto flex items-center gap-x-3", children: mobileTray }))] }), _jsx("main", { className: "flex-1 flex flex-col py-8", children: _jsx("div", { className: "flex-1 flex flex-col px-4 sm:px-6 lg:px-8", children: children }) })] }), overlay] }));
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=app-shell.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-shell.js","sourceRoot":"","sources":["../../src/nav/app-shell.tsx"],"names":[],"mappings":";AAAA,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAoB,MAAM,qBAAqB,CAAC;AACxF,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAiBlC,MAAM,UAAU,QAAQ,CAAC,EACvB,OAAO,EACP,QAAQ,EACR,WAAW,EACX,UAAU,EACV,OAAO,EACP,gBAAgB,GACF;IACd,MAAM,CAAC,UAAU,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEpD,OAAO,CACL,eAAK,SAAS,EAAC,WAAW,aAExB,KAAC,KAAK,IAAC,IAAI,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,YAClD,MAAC,YAAY,IACX,IAAI,EAAC,MAAM,EACX,SAAS,EAAC,gDAAgD,sBACxC,SAAS,aAE3B,KAAC,UAAU,IAAC,SAAS,EAAC,SAAS,2BAAwB,EACvD,cAAK,SAAS,EAAC,sBAAsB,YAAE,OAAO,GAAO,IACxC,GACT,EAGR,cAAK,SAAS,EAAC,kEAAkE,YAC9E,OAAO,GACJ,EAGN,eAAK,SAAS,EAAE,EAAE,CAAC,kCAAkC,EAAE,gBAAgB,CAAC,aAEtE,eAAK,SAAS,EAAC,sIAAsI,aACnJ,iBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,EAClC,SAAS,EAAC,8BAA8B,gBAC7B,cAAc,YAEzB,cACE,SAAS,EAAC,QAAQ,EAClB,IAAI,EAAC,MAAM,EACX,OAAO,EAAC,WAAW,EACnB,WAAW,EAAE,GAAG,EAChB,MAAM,EAAC,cAAc,iBACT,MAAM,YAElB,eACE,aAAa,EAAC,OAAO,EACrB,cAAc,EAAC,OAAO,EACtB,CAAC,EAAC,8CAA8C,GAChD,GACE,GACC,EAET,6BAAiB,MAAM,EAAC,SAAS,EAAC,oBAAoB,GAAG,EAEzD,eAAK,SAAS,EAAC,kCAAkC,aAC/C,cACE,GAAG,EAAC,6BAA6B,EACjC,GAAG,EAAC,EAAE,EACN,SAAS,EAAC,4BAA4B,GACtC,EACD,WAAW,IAAI,CACd,eAAM,SAAS,EAAC,6DAA6D,YAC1E,WAAW,GACP,CACR,IACG,EAEL,UAAU,IAAI,CACb,cAAK,SAAS,EAAC,mCAAmC,YAAE,UAAU,GAAO,CACtE,IACG,EAGN,eAAM,SAAS,EAAC,2BAA2B,YACzC,cAAK,SAAS,EAAC,2CAA2C,YACvD,QAAQ,GACL,GACD,IACH,EAGL,OAAO,IACJ,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { type SidebarNavLeafItem, type SidebarNavSection, type SidebarUser, type RenderLinkFn } from "./types";
|
|
3
|
+
interface AppSidebarProps {
|
|
4
|
+
/** "Producer Portal" | "Importer Portal" | any custom label */
|
|
5
|
+
portalLabel: string;
|
|
6
|
+
/** Optional pinned dashboard item shown above nav sections */
|
|
7
|
+
dashboardItem?: SidebarNavLeafItem;
|
|
8
|
+
navSections: SidebarNavSection[];
|
|
9
|
+
/** Current route pathname for active-state determination */
|
|
10
|
+
currentPath: string;
|
|
11
|
+
/** Provide the router-aware Link component */
|
|
12
|
+
renderLink: RenderLinkFn;
|
|
13
|
+
user: SidebarUser | null;
|
|
14
|
+
isDark: boolean;
|
|
15
|
+
onToggleTheme: () => void;
|
|
16
|
+
onSignOut: () => void;
|
|
17
|
+
/** Notification button (e.g. <NotificationPanel />) rendered in footer */
|
|
18
|
+
notificationSlot?: React.ReactNode;
|
|
19
|
+
/** Language switcher rendered in footer */
|
|
20
|
+
languageSwitcherSlot?: React.ReactNode;
|
|
21
|
+
/** Any dashboard-specific controls in the footer (e.g. data-source toggle) */
|
|
22
|
+
extraFooterContent?: React.ReactNode;
|
|
23
|
+
/** i18n overrides */
|
|
24
|
+
labels?: {
|
|
25
|
+
signOut?: string;
|
|
26
|
+
user?: string;
|
|
27
|
+
switchToLight?: string;
|
|
28
|
+
switchToDark?: string;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export declare function AppSidebar({ portalLabel, dashboardItem, navSections, currentPath, renderLink, user, isDark, onToggleTheme, onSignOut, notificationSlot, languageSwitcherSlot, extraFooterContent, labels, }: AppSidebarProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=app-sidebar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-sidebar.d.ts","sourceRoot":"","sources":["../../src/nav/app-sidebar.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAEL,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,YAAY,EAClB,MAAM,SAAS,CAAC;AAIjB,UAAU,eAAe;IACvB,+DAA+D;IAC/D,WAAW,EAAE,MAAM,CAAC;IACpB,8DAA8D;IAC9D,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,WAAW,EAAE,iBAAiB,EAAE,CAAC;IACjC,4DAA4D;IAC5D,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,UAAU,EAAE,YAAY,CAAC;IACzB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,OAAO,CAAC;IAChB,aAAa,EAAE,MAAM,IAAI,CAAC;IAC1B,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACnC,2CAA2C;IAC3C,oBAAoB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvC,8EAA8E;IAC9E,kBAAkB,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACrC,qBAAqB;IACrB,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,YAAY,CAAC,EAAE,MAAM,CAAC;KACvB,CAAC;CACH;AAOD,wBAAgB,UAAU,CAAC,EACzB,WAAW,EACX,aAAa,EACb,WAAW,EACX,WAAW,EACX,UAAU,EACV,IAAI,EACJ,MAAM,EACN,aAAa,EACb,SAAS,EACT,gBAAgB,EAChB,oBAAoB,EACpB,kBAAkB,EAClB,MAAW,GACZ,EAAE,eAAe,2CAkKjB"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { Sun, Moon } from "lucide-react";
|
|
3
|
+
import { cn } from "../lib/utils";
|
|
4
|
+
import { ExpandableNavItem } from "./expandable-nav-item";
|
|
5
|
+
import { isSidebarNavExpandable, } from "./types";
|
|
6
|
+
const BRAND_NAME = "CellarNode";
|
|
7
|
+
function isActive(currentPath, href) {
|
|
8
|
+
if (href === "/" || href === "/dashboard")
|
|
9
|
+
return currentPath === href;
|
|
10
|
+
return currentPath.startsWith(href);
|
|
11
|
+
}
|
|
12
|
+
export function AppSidebar({ portalLabel, dashboardItem, navSections, currentPath, renderLink, user, isDark, onToggleTheme, onSignOut, notificationSlot, languageSwitcherSlot, extraFooterContent, labels = {}, }) {
|
|
13
|
+
const ThemeIcon = isDark ? Sun : Moon;
|
|
14
|
+
const initials = user?.initials
|
|
15
|
+
?? (user?.name
|
|
16
|
+
? user.name
|
|
17
|
+
.split(" ")
|
|
18
|
+
.map((n) => n[0])
|
|
19
|
+
.join("")
|
|
20
|
+
.toUpperCase()
|
|
21
|
+
.slice(0, 2)
|
|
22
|
+
: "?");
|
|
23
|
+
return (_jsxs("div", { className: "relative flex grow flex-col gap-y-5 overflow-y-auto bg-primary px-6 dark:bg-sidebar dark:before:pointer-events-none dark:before:absolute dark:before:inset-0 dark:before:border-r dark:before:border-white/5 dark:before:bg-white/[0.015]", children: [_jsx("div", { className: "relative flex h-16 shrink-0 items-center gap-3", children: renderLink({
|
|
24
|
+
href: dashboardItem?.href ?? "/",
|
|
25
|
+
className: "flex items-center gap-3",
|
|
26
|
+
children: (_jsxs(_Fragment, { children: [_jsx("img", { src: "/android-chrome-192x192.png", alt: BRAND_NAME, className: "size-10 shrink-0 rounded-[1.15rem]" }), _jsxs("div", { className: "flex flex-col leading-none", children: [_jsx("span", { className: "text-sm font-semibold font-display tracking-tight text-white dark:text-sidebar-foreground", children: BRAND_NAME }), _jsx("span", { className: "text-[11px] uppercase tracking-[0.16em] text-white/65 dark:text-sidebar-foreground/65", children: portalLabel })] })] })),
|
|
27
|
+
}) }), _jsx("nav", { className: "relative flex flex-1 flex-col", children: _jsxs("ul", { role: "list", className: "flex flex-1 flex-col gap-y-7", children: [dashboardItem && (_jsx("li", { children: _jsx("ul", { role: "list", className: "-mx-2 mt-2 space-y-1.5", children: _jsx(NavLeafItem, { item: dashboardItem, current: isActive(currentPath, dashboardItem.href), renderLink: renderLink }) }) })), navSections.map((section) => (_jsxs("li", { children: [_jsx("div", { className: "text-[11px] font-semibold uppercase tracking-[0.16em] text-white/50 dark:text-sidebar-foreground/50 mb-2", children: section.label }), _jsx("ul", { role: "list", className: "-mx-2 space-y-1.5", children: section.items.map((item) => isSidebarNavExpandable(item) ? (_jsx(ExpandableNavItem, { name: item.title, icon: item.icon, children: item.children, currentPath: currentPath, renderLink: renderLink }, item.title)) : (_jsx(NavLeafItem, { item: item, current: isActive(currentPath, item.href), renderLink: renderLink }, item.href))) })] }, section.label))), _jsxs("li", { className: "-mx-6 mt-auto", children: [extraFooterContent && (_jsx("div", { className: "px-6 pb-3", children: extraFooterContent })), _jsxs("div", { className: "flex items-center gap-x-4 px-6 py-3", children: [renderLink({
|
|
28
|
+
href: user?.profileHref ?? "/profile",
|
|
29
|
+
className: "flex flex-1 items-center gap-x-4 text-sm/6 font-semibold text-primary-foreground hover:opacity-80 truncate min-w-0",
|
|
30
|
+
children: (_jsxs(_Fragment, { children: [_jsx("span", { className: "inline-grid size-8 shrink-0 select-none place-items-center rounded-full bg-primary/80 text-xs font-semibold text-white outline -outline-offset-1 outline-white/10 dark:bg-white/5", "aria-hidden": "true", children: user?.avatarUrl ? (_jsx("img", { src: user.avatarUrl, alt: user.name, className: "size-full rounded-full object-cover" })) : (initials) }), _jsx("span", { className: "font-display truncate", children: user?.name ?? labels.user ?? "User" })] })),
|
|
31
|
+
}), _jsxs("div", { className: "flex items-center gap-x-2", children: [_jsx("button", { type: "button", onClick: onToggleTheme, "aria-label": isDark
|
|
32
|
+
? (labels.switchToLight ?? "Switch to light theme")
|
|
33
|
+
: (labels.switchToDark ?? "Switch to dark theme"), className: "inline-flex size-9 items-center justify-center rounded-full border border-white/15 bg-white/5 text-white/80 transition-colors hover:bg-white/10 hover:text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-white/20 dark:border-white/10 dark:bg-white/5 dark:text-zinc-200 dark:hover:bg-white/10 dark:hover:text-zinc-50", children: _jsx(ThemeIcon, { className: "size-4.5", "aria-hidden": "true" }) }), notificationSlot] })] }), languageSwitcherSlot && (_jsx("div", { className: "flex items-center justify-between px-6 pb-3", children: languageSwitcherSlot })), _jsx("div", { className: "px-6 pb-4", children: _jsx("button", { type: "button", onClick: onSignOut, className: "w-full rounded-md border border-white/20 px-3 py-2 text-sm font-semibold text-white/80 hover:bg-white/5 hover:text-white dark:border-white/10 dark:text-zinc-200 dark:hover:bg-white/5 dark:hover:text-zinc-50", children: labels.signOut ?? "Sign out" }) })] })] }) })] }));
|
|
34
|
+
}
|
|
35
|
+
function NavLeafItem({ item, current, renderLink, }) {
|
|
36
|
+
return (_jsx("li", { children: renderLink({
|
|
37
|
+
href: item.href,
|
|
38
|
+
className: cn("group relative flex min-h-11 items-center gap-x-3 rounded-md px-3 py-2 text-sm/6 transition-colors ring-1 ring-transparent", current
|
|
39
|
+
? "bg-white/10 text-white font-semibold before:absolute before:left-1.5 before:top-1/2 before:h-5 before:w-0.5 before:-translate-y-1/2 before:rounded-full before:bg-white/85 dark:bg-white/6 dark:text-zinc-50 dark:ring-1 dark:ring-white/10 dark:before:bg-primary/80"
|
|
40
|
+
: "text-white/80 font-medium hover:bg-white/6 hover:text-white dark:text-zinc-300 dark:hover:bg-white/5 dark:hover:text-zinc-100"),
|
|
41
|
+
children: (_jsxs(_Fragment, { children: [_jsx(item.icon, { "aria-hidden": "true", className: cn("size-6 shrink-0 transition-opacity", current ? "opacity-100" : "opacity-80 group-hover:opacity-100") }), _jsx("span", { className: cn("font-display truncate", current ? "tracking-[0.01em]" : ""), children: item.title }), item.badgeCount != null && item.badgeCount > 0 ? (_jsx("span", { "aria-hidden": "true", className: cn("ml-auto w-9 min-w-max rounded-full px-2.5 py-0.5 text-center text-xs/5 font-medium whitespace-nowrap outline-1 -outline-offset-1", current
|
|
42
|
+
? "bg-white/12 text-white outline-white/15 dark:bg-white/8 dark:text-zinc-100 dark:outline-white/10"
|
|
43
|
+
: "bg-white/8 text-white/80 outline-white/10 dark:bg-white/5 dark:text-zinc-300 dark:outline-white/5"), children: item.badgeCount > 99 ? "99+" : item.badgeCount })) : null] })),
|
|
44
|
+
}) }));
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=app-sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app-sidebar.js","sourceRoot":"","sources":["../../src/nav/app-sidebar.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SidebarNavSubItem, IconType, RenderLinkFn } from "./types";
|
|
2
|
+
interface ExpandableNavItemProps {
|
|
3
|
+
name: string;
|
|
4
|
+
icon: IconType;
|
|
5
|
+
children: SidebarNavSubItem[];
|
|
6
|
+
currentPath: string;
|
|
7
|
+
renderLink: RenderLinkFn;
|
|
8
|
+
}
|
|
9
|
+
export declare function ExpandableNavItem({ name, icon: Icon, children, currentPath, renderLink, }: ExpandableNavItemProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=expandable-nav-item.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expandable-nav-item.d.ts","sourceRoot":"","sources":["../../src/nav/expandable-nav-item.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,iBAAiB,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEzE,UAAU,sBAAsB;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,QAAQ,EAAE,iBAAiB,EAAE,CAAC;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,YAAY,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,IAAI,EAAE,IAAI,EACV,QAAQ,EACR,WAAW,EACX,UAAU,GACX,EAAE,sBAAsB,2CAuExB"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect } from "react";
|
|
3
|
+
import { ChevronDown, ChevronUp } from "lucide-react";
|
|
4
|
+
import { cn } from "../lib/utils";
|
|
5
|
+
export function ExpandableNavItem({ name, icon: Icon, children, currentPath, renderLink, }) {
|
|
6
|
+
const isChildActive = children.some((child) => child.href === "/" ? currentPath === "/" : currentPath.startsWith(child.href));
|
|
7
|
+
const [open, setOpen] = useState(isChildActive);
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
if (isChildActive)
|
|
10
|
+
setOpen(true);
|
|
11
|
+
}, [isChildActive]);
|
|
12
|
+
return (_jsxs("li", { children: [_jsxs("button", { type: "button", onClick: () => setOpen((prev) => !prev), className: cn("group relative flex w-full min-h-11 items-center gap-x-3 rounded-md px-3 py-2 text-sm/6 transition-colors ring-1 ring-transparent", isChildActive
|
|
13
|
+
? "text-white font-semibold"
|
|
14
|
+
: "text-white/80 font-medium hover:bg-white/6 hover:text-white dark:text-zinc-300 dark:hover:bg-white/5 dark:hover:text-zinc-100"), children: [_jsx(Icon, { "aria-hidden": "true", className: cn("size-6 shrink-0 transition-opacity", isChildActive ? "opacity-100" : "opacity-80 group-hover:opacity-100") }), _jsx("span", { className: cn("font-display truncate", isChildActive ? "tracking-[0.01em]" : ""), children: name }), open ? (_jsx(ChevronUp, { "aria-hidden": "true", className: "ml-auto size-4 shrink-0 opacity-60 group-hover:opacity-80" })) : (_jsx(ChevronDown, { "aria-hidden": "true", className: "ml-auto size-4 shrink-0 opacity-60 group-hover:opacity-80" }))] }), open && (_jsx("ul", { role: "list", className: "mt-1 space-y-1", children: children.map((child, index) => {
|
|
15
|
+
const current = index === 0
|
|
16
|
+
? currentPath === child.href
|
|
17
|
+
: currentPath === child.href || currentPath.startsWith(child.href + "/");
|
|
18
|
+
return (_jsx("li", { children: renderLink({
|
|
19
|
+
href: child.href,
|
|
20
|
+
className: cn("group relative flex min-h-9 items-center gap-x-3 rounded-md pl-12 pr-3 py-1.5 text-sm/6 transition-colors ring-1 ring-transparent", current
|
|
21
|
+
? "bg-white/10 text-white font-semibold before:absolute before:left-1.5 before:top-1/2 before:h-5 before:w-0.5 before:-translate-y-1/2 before:rounded-full before:bg-white/85 dark:bg-white/6 dark:text-zinc-50 dark:ring-1 dark:ring-white/10 dark:before:bg-primary/80"
|
|
22
|
+
: "text-white/80 font-medium hover:bg-white/6 hover:text-white dark:text-zinc-300 dark:hover:bg-white/5 dark:hover:text-zinc-100"),
|
|
23
|
+
children: (_jsx("span", { className: cn("font-display truncate", current ? "tracking-[0.01em]" : ""), children: child.title })),
|
|
24
|
+
}) }, child.href));
|
|
25
|
+
}) }))] }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=expandable-nav-item.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expandable-nav-item.js","sourceRoot":"","sources":["../../src/nav/expandable-nav-item.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,EAAE,EAAE,MAAM,cAAc,CAAC;AAWlC,MAAM,UAAU,iBAAiB,CAAC,EAChC,IAAI,EACJ,IAAI,EAAE,IAAI,EACV,QAAQ,EACR,WAAW,EACX,UAAU,GACa;IACvB,MAAM,aAAa,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAC5C,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAC9E,CAAC;IAEF,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IAEhD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,aAAa;YAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,OAAO,CACL,yBACE,kBACE,IAAI,EAAC,QAAQ,EACb,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,EACvC,SAAS,EAAE,EAAE,CACX,mIAAmI,EACnI,aAAa;oBACX,CAAC,CAAC,0BAA0B;oBAC5B,CAAC,CAAC,+HAA+H,CACpI,aAED,KAAC,IAAI,mBACS,MAAM,EAClB,SAAS,EAAE,EAAE,CACX,oCAAoC,EACpC,aAAa,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,oCAAoC,CACrE,GACD,EACF,eAAM,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,aAAa,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,YACnF,IAAI,GACA,EACN,IAAI,CAAC,CAAC,CAAC,CACN,KAAC,SAAS,mBAAa,MAAM,EAAC,SAAS,EAAC,2DAA2D,GAAG,CACvG,CAAC,CAAC,CAAC,CACF,KAAC,WAAW,mBAAa,MAAM,EAAC,SAAS,EAAC,2DAA2D,GAAG,CACzG,IACM,EAER,IAAI,IAAI,CACP,aAAI,IAAI,EAAC,MAAM,EAAC,SAAS,EAAC,gBAAgB,YACvC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE;oBAC7B,MAAM,OAAO,GACX,KAAK,KAAK,CAAC;wBACT,CAAC,CAAC,WAAW,KAAK,KAAK,CAAC,IAAI;wBAC5B,CAAC,CAAC,WAAW,KAAK,KAAK,CAAC,IAAI,IAAI,WAAW,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;oBAE7E,OAAO,CACL,uBACG,UAAU,CAAC;4BACV,IAAI,EAAE,KAAK,CAAC,IAAI;4BAChB,SAAS,EAAE,EAAE,CACX,mIAAmI,EACnI,OAAO;gCACL,CAAC,CAAC,uQAAuQ;gCACzQ,CAAC,CAAC,+HAA+H,CACpI;4BACD,QAAQ,EAAE,CACR,eAAM,SAAS,EAAE,EAAE,CAAC,uBAAuB,EAAE,OAAO,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,YAC7E,KAAK,CAAC,KAAK,GACP,CACR;yBACF,CAAC,IAdK,KAAK,CAAC,IAAI,CAed,CACN,CAAC;gBACJ,CAAC,CAAC,GACC,CACN,IACE,CACN,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { AppSidebar } from "./app-sidebar";
|
|
2
|
+
export { AppShell } from "./app-shell";
|
|
3
|
+
export { ExpandableNavItem } from "./expandable-nav-item";
|
|
4
|
+
export type { IconType, RenderLinkFn, SidebarNavLeafItem, SidebarNavExpandableItem, SidebarNavSectionItem, SidebarNavSection, SidebarNavSubItem, SidebarUser, } from "./types";
|
|
5
|
+
export { isSidebarNavExpandable } from "./types";
|
|
6
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nav/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,YAAY,EACV,QAAQ,EACR,YAAY,EACZ,kBAAkB,EAClB,wBAAwB,EACxB,qBAAqB,EACrB,iBAAiB,EACjB,iBAAiB,EACjB,WAAW,GACZ,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nav/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAW1D,OAAO,EAAE,sBAAsB,EAAE,MAAM,SAAS,CAAC"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type React from "react";
|
|
2
|
+
export type IconType = React.ComponentType<{
|
|
3
|
+
className?: string;
|
|
4
|
+
"aria-hidden"?: boolean | "true" | "false";
|
|
5
|
+
}>;
|
|
6
|
+
export type RenderLinkFn = (props: {
|
|
7
|
+
href: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
children: React.ReactNode;
|
|
10
|
+
}) => React.ReactElement;
|
|
11
|
+
export interface SidebarNavSubItem {
|
|
12
|
+
title: string;
|
|
13
|
+
href: string;
|
|
14
|
+
}
|
|
15
|
+
export interface SidebarNavLeafItem {
|
|
16
|
+
title: string;
|
|
17
|
+
href: string;
|
|
18
|
+
icon: IconType;
|
|
19
|
+
badgeCount?: number;
|
|
20
|
+
}
|
|
21
|
+
export interface SidebarNavExpandableItem {
|
|
22
|
+
title: string;
|
|
23
|
+
icon: IconType;
|
|
24
|
+
expandable: true;
|
|
25
|
+
children: SidebarNavSubItem[];
|
|
26
|
+
}
|
|
27
|
+
export type SidebarNavSectionItem = SidebarNavLeafItem | SidebarNavExpandableItem;
|
|
28
|
+
export interface SidebarNavSection {
|
|
29
|
+
label: string;
|
|
30
|
+
items: SidebarNavSectionItem[];
|
|
31
|
+
}
|
|
32
|
+
export interface SidebarUser {
|
|
33
|
+
name: string;
|
|
34
|
+
email?: string;
|
|
35
|
+
initials?: string;
|
|
36
|
+
avatarUrl?: string;
|
|
37
|
+
profileHref: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function isSidebarNavExpandable(item: SidebarNavSectionItem): item is SidebarNavExpandableItem;
|
|
40
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/nav/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,MAAM,MAAM,QAAQ,GAAG,KAAK,CAAC,aAAa,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,OAAO,CAAC;CAC5C,CAAC,CAAC;AAEH,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,KAAK,KAAK,CAAC,YAAY,CAAC;AAEzB,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,QAAQ,CAAC;IACf,UAAU,EAAE,IAAI,CAAC;IACjB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,MAAM,qBAAqB,GAAG,kBAAkB,GAAG,wBAAwB,CAAC;AAElF,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,qBAAqB,EAAE,CAAC;CAChC;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,sBAAsB,CACpC,IAAI,EAAE,qBAAqB,GAC1B,IAAI,IAAI,wBAAwB,CAElC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/nav/types.ts"],"names":[],"mappings":"AA+CA,MAAM,UAAU,sBAAsB,CACpC,IAA2B;IAE3B,OAAO,YAAY,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,KAAK,IAAI,CAAC;AAC1D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/opportunities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,YAAY,EAAE,uBAAuB,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/opportunities/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
export interface OpportunityRow {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
marketIdentifier?: string | null;
|
|
6
|
+
beverageType?: string | null;
|
|
7
|
+
countryOfOrigin?: string | null;
|
|
8
|
+
status: string;
|
|
9
|
+
submissionDeadline?: string | null;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
}
|
|
12
|
+
export interface OpportunitiesTableProps {
|
|
13
|
+
data: OpportunityRow[];
|
|
14
|
+
isLoading?: boolean;
|
|
15
|
+
/** Router-agnostic link renderer */
|
|
16
|
+
renderLink?: (href: string, children: React.ReactNode) => React.ReactNode;
|
|
17
|
+
/** Build href for a row. If not provided, rows are not clickable. */
|
|
18
|
+
getRowHref?: (row: OpportunityRow) => string;
|
|
19
|
+
emptyMessage?: string;
|
|
20
|
+
pageSize?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare function OpportunitiesTable({ data, isLoading, renderLink, getRowHref, emptyMessage, pageSize, }: OpportunitiesTableProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
//# sourceMappingURL=opportunities-table.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opportunities-table.d.ts","sourceRoot":"","sources":["../../src/opportunities/opportunities-table.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AA0B/B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,uBAAuB;IACtC,IAAI,EAAE,cAAc,EAAE,CAAC;IACvB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,oCAAoC;IACpC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,CAAC,SAAS,CAAC;IAC1E,qEAAqE;IACrE,UAAU,CAAC,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,MAAM,CAAC;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AA+QD,wBAAgB,kBAAkB,CAAC,EACjC,IAAI,EACJ,SAAiB,EACjB,UAAU,EACV,UAAU,EACV,YAAwC,EACxC,QAAa,GACd,EAAE,uBAAuB,2CAuHzB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { useReactTable, getCoreRowModel, getFilteredRowModel, getPaginationRowModel, } from "@tanstack/react-table";
|
|
4
|
+
import { AnimatePresence, motion } from "motion/react";
|
|
5
|
+
import { format, formatDistanceToNow, isPast, parseISO } from "date-fns";
|
|
6
|
+
import { Clock, Search, ChevronDown, ChevronLeft, ChevronRight, Rows3, Rows4, } from "lucide-react";
|
|
7
|
+
import { cn } from "../lib/utils";
|
|
8
|
+
import { ShadcnButton } from "../components/shadcn-button";
|
|
9
|
+
import { ShadcnInput } from "../components/shadcn-input";
|
|
10
|
+
import { Skeleton } from "../components/skeleton";
|
|
11
|
+
// ─── Country flags ────────────────────────────────────────────────────────────
|
|
12
|
+
const COUNTRY_FLAGS = {
|
|
13
|
+
AR: "🇦🇷", AU: "🇦🇺", AT: "🇦🇹", BE: "🇧🇪", BR: "🇧🇷",
|
|
14
|
+
CA: "🇨🇦", CL: "🇨🇱", CN: "🇨🇳", HR: "🇭🇷", CZ: "🇨🇿",
|
|
15
|
+
DK: "🇩🇰", FR: "🇫🇷", DE: "🇩🇪", GR: "🇬🇷", HU: "🇭🇺",
|
|
16
|
+
IE: "🇮🇪", IT: "🇮🇹", JP: "🇯🇵", MX: "🇲🇽", NL: "🇳🇱",
|
|
17
|
+
NO: "🇳🇴", PL: "🇵🇱", PT: "🇵🇹", ES: "🇪🇸", SE: "🇸🇪",
|
|
18
|
+
CH: "🇨🇭", TR: "🇹🇷", GB: "🇬🇧", US: "🇺🇸", ZA: "🇿🇦",
|
|
19
|
+
KR: "🇰🇷", NZ: "🇳🇿", SK: "🇸🇰", SI: "🇸🇮", FI: "🇫🇮",
|
|
20
|
+
EE: "🇪🇪", LV: "🇱🇻", LT: "🇱🇹", LU: "🇱🇺", RO: "🇷🇴",
|
|
21
|
+
};
|
|
22
|
+
const COUNTRY_NAME_TO_ISO = {
|
|
23
|
+
"Argentina": "AR", "Australia": "AU", "Austria": "AT", "Belgium": "BE",
|
|
24
|
+
"Brazil": "BR", "Canada": "CA", "Chile": "CL", "China": "CN",
|
|
25
|
+
"Croatia": "HR", "Czech Republic": "CZ", "Czechia": "CZ",
|
|
26
|
+
"Denmark": "DK", "France": "FR", "Germany": "DE", "Greece": "GR",
|
|
27
|
+
"Hungary": "HU", "Ireland": "IE", "Italy": "IT", "Japan": "JP",
|
|
28
|
+
"Mexico": "MX", "Netherlands": "NL", "Norway": "NO", "Poland": "PL",
|
|
29
|
+
"Portugal": "PT", "Spain": "ES", "Sweden": "SE", "Switzerland": "CH",
|
|
30
|
+
"Turkey": "TR", "Türkiye": "TR", "United Kingdom": "GB", "UK": "GB",
|
|
31
|
+
"United States": "US", "USA": "US", "South Africa": "ZA",
|
|
32
|
+
"South Korea": "KR", "New Zealand": "NZ", "Slovakia": "SK",
|
|
33
|
+
"Slovenia": "SI", "Finland": "FI", "Estonia": "EE", "Latvia": "LV",
|
|
34
|
+
"Lithuania": "LT", "Luxembourg": "LU", "Romania": "RO",
|
|
35
|
+
};
|
|
36
|
+
function getFlag(country) {
|
|
37
|
+
if (!country)
|
|
38
|
+
return "🏳️";
|
|
39
|
+
const upper = country.toUpperCase();
|
|
40
|
+
if (COUNTRY_FLAGS[upper])
|
|
41
|
+
return COUNTRY_FLAGS[upper];
|
|
42
|
+
const iso = COUNTRY_NAME_TO_ISO[country];
|
|
43
|
+
return iso ? (COUNTRY_FLAGS[iso] ?? "🏳️") : "🏳️";
|
|
44
|
+
}
|
|
45
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
46
|
+
function StatusBadge({ status }) {
|
|
47
|
+
const normalised = status.toLowerCase();
|
|
48
|
+
return (_jsx("span", { className: cn("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", normalised === "open" &&
|
|
49
|
+
"bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400", normalised === "closed" && "bg-muted text-muted-foreground", normalised === "draft" &&
|
|
50
|
+
"bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400", !["open", "closed", "draft"].includes(normalised) &&
|
|
51
|
+
"bg-muted text-muted-foreground"), children: status }));
|
|
52
|
+
}
|
|
53
|
+
function DeadlineDisplay({ deadline, full = false, }) {
|
|
54
|
+
if (!deadline)
|
|
55
|
+
return _jsx("span", { className: "text-muted-foreground", children: "\u2014" });
|
|
56
|
+
const date = parseISO(deadline);
|
|
57
|
+
const past = isPast(date);
|
|
58
|
+
const daysLeft = Math.ceil((date.getTime() - Date.now()) / (1000 * 60 * 60 * 24));
|
|
59
|
+
return (_jsxs("span", { className: cn("inline-flex items-center gap-1 text-sm", past && "text-destructive", !past && daysLeft <= 7 && "text-amber-600 dark:text-amber-400", !past && daysLeft > 7 && "text-emerald-600 dark:text-emerald-400"), children: [_jsx(Clock, { className: "size-3.5 shrink-0" }), full
|
|
60
|
+
? format(date, "PPP")
|
|
61
|
+
: formatDistanceToNow(date, { addSuffix: true })] }));
|
|
62
|
+
}
|
|
63
|
+
// ─── Skeleton ─────────────────────────────────────────────────────────────────
|
|
64
|
+
function RowSkeleton({ density }) {
|
|
65
|
+
return (_jsxs("li", { className: cn("flex items-center gap-3 px-4", density === "comfortable" ? "py-3.5" : "py-2"), children: [_jsx(Skeleton, { className: "size-7 shrink-0 rounded-md" }), _jsxs("div", { className: "flex flex-1 flex-col gap-1.5", children: [_jsx(Skeleton, { className: "h-3.5 w-48 rounded" }), _jsx(Skeleton, { className: "h-3 w-28 rounded" })] }), _jsx(Skeleton, { className: "h-5 w-16 rounded-full" }), _jsx(Skeleton, { className: "h-5 w-16 rounded-full" }), _jsx(Skeleton, { className: "h-4 w-24 rounded" }), _jsx(Skeleton, { className: "size-5 shrink-0 rounded" })] }));
|
|
66
|
+
}
|
|
67
|
+
// ─── Detail grid ──────────────────────────────────────────────────────────────
|
|
68
|
+
function DetailField({ label, children, }) {
|
|
69
|
+
return (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-xs font-medium text-muted-foreground", children: label }), _jsx("span", { className: "text-sm text-foreground", children: children })] }));
|
|
70
|
+
}
|
|
71
|
+
// ─── Row item ─────────────────────────────────────────────────────────────────
|
|
72
|
+
function OpportunityRowItem({ row, density, renderLink, getRowHref, }) {
|
|
73
|
+
const [expanded, setExpanded] = React.useState(false);
|
|
74
|
+
const href = getRowHref?.(row);
|
|
75
|
+
const flag = getFlag(row.countryOfOrigin);
|
|
76
|
+
const nameContent = (_jsx("span", { className: "text-sm font-semibold text-foreground hover:underline", children: row.name }));
|
|
77
|
+
return (_jsxs("li", { className: "bg-card", children: [_jsxs("div", { className: cn("flex items-center gap-3 px-4", density === "comfortable" ? "py-3.5" : "py-2"), children: [_jsx("span", { className: "shrink-0 text-xl leading-none", role: "img", "aria-label": row.countryOfOrigin ?? "Unknown country", children: flag }), _jsxs("div", { className: "min-w-0 flex-1", children: [href && renderLink ? (renderLink(href, nameContent)) : (nameContent), row.marketIdentifier && (_jsx("p", { className: "truncate text-xs text-muted-foreground", children: row.marketIdentifier }))] }), row.beverageType && (_jsx("span", { className: "hidden shrink-0 rounded-full bg-muted px-2 py-0.5 text-xs text-muted-foreground sm:inline-block", children: row.beverageType })), _jsx(StatusBadge, { status: row.status }), _jsx("span", { className: "hidden shrink-0 md:inline-flex", children: _jsx(DeadlineDisplay, { deadline: row.submissionDeadline }) }), _jsx("button", { type: "button", onClick: () => setExpanded((v) => !v), "aria-expanded": expanded, "aria-label": expanded ? "Collapse details" : "Expand details", className: "shrink-0 rounded-md p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring", children: _jsx(ChevronDown, { className: cn("size-4 transition-transform duration-200", expanded && "rotate-180") }) })] }), _jsx(AnimatePresence, { initial: false, children: expanded && (_jsx(motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeInOut" }, className: "overflow-hidden", children: _jsx("div", { className: "border-t border-border/40 bg-muted/20 px-4 pb-4 pt-3", children: _jsxs("div", { className: "grid grid-cols-2 gap-4 md:grid-cols-3", children: [_jsx(DetailField, { label: "Country of Origin", children: row.countryOfOrigin
|
|
78
|
+
? `${flag} ${row.countryOfOrigin}`
|
|
79
|
+
: "—" }), _jsx(DetailField, { label: "Beverage Type", children: row.beverageType ?? "—" }), _jsx(DetailField, { label: "Submission Deadline", children: _jsx(DeadlineDisplay, { deadline: row.submissionDeadline, full: true }) }), _jsx(DetailField, { label: "Market Identifier", children: row.marketIdentifier ?? "—" }), _jsx(DetailField, { label: "Status", children: _jsx(StatusBadge, { status: row.status }) })] }) }) }, "detail")) })] }));
|
|
80
|
+
}
|
|
81
|
+
// ─── Main component ───────────────────────────────────────────────────────────
|
|
82
|
+
const DUMMY_COLUMNS = [
|
|
83
|
+
{ accessorKey: "name" },
|
|
84
|
+
{ accessorKey: "marketIdentifier" },
|
|
85
|
+
{ accessorKey: "beverageType" },
|
|
86
|
+
{ accessorKey: "countryOfOrigin" },
|
|
87
|
+
{ accessorKey: "status" },
|
|
88
|
+
{ accessorKey: "submissionDeadline" },
|
|
89
|
+
];
|
|
90
|
+
export function OpportunitiesTable({ data, isLoading = false, renderLink, getRowHref, emptyMessage = "No opportunities found.", pageSize = 10, }) {
|
|
91
|
+
const [globalFilter, setGlobalFilter] = React.useState("");
|
|
92
|
+
const [density, setDensity] = React.useState("comfortable");
|
|
93
|
+
const table = useReactTable({
|
|
94
|
+
data,
|
|
95
|
+
columns: DUMMY_COLUMNS,
|
|
96
|
+
state: { globalFilter },
|
|
97
|
+
onGlobalFilterChange: setGlobalFilter,
|
|
98
|
+
globalFilterFn: (row, _columnId, filterValue) => {
|
|
99
|
+
const q = filterValue.toLowerCase();
|
|
100
|
+
return (row.original.name.toLowerCase().includes(q) ||
|
|
101
|
+
(row.original.marketIdentifier?.toLowerCase().includes(q) ?? false) ||
|
|
102
|
+
(row.original.beverageType?.toLowerCase().includes(q) ?? false) ||
|
|
103
|
+
(row.original.countryOfOrigin?.toLowerCase().includes(q) ?? false));
|
|
104
|
+
},
|
|
105
|
+
getCoreRowModel: getCoreRowModel(),
|
|
106
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
107
|
+
getPaginationRowModel: getPaginationRowModel(),
|
|
108
|
+
initialState: { pagination: { pageSize } },
|
|
109
|
+
});
|
|
110
|
+
const { pageIndex } = table.getState().pagination;
|
|
111
|
+
const pageCount = table.getPageCount();
|
|
112
|
+
const filteredCount = table.getFilteredRowModel().rows.length;
|
|
113
|
+
return (_jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [_jsxs("div", { className: "relative flex-1", children: [_jsx(Search, { className: "pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" }), _jsx(ShadcnInput, { value: globalFilter, onChange: (e) => setGlobalFilter(e.target.value), placeholder: "Search name, market, type, country\u2026", className: "pl-9" })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [_jsx(ShadcnButton, { variant: density === "comfortable" ? "secondary" : "ghost", size: "icon-sm", onClick: () => setDensity("comfortable"), title: "Comfortable density", children: _jsx(Rows4, { className: "size-4" }) }), _jsx(ShadcnButton, { variant: density === "compact" ? "secondary" : "ghost", size: "icon-sm", onClick: () => setDensity("compact"), title: "Compact density", children: _jsx(Rows3, { className: "size-4" }) })] }), !isLoading && (_jsxs("span", { className: "shrink-0 text-xs text-muted-foreground", children: [filteredCount, " ", filteredCount === 1 ? "opportunity" : "opportunities"] }))] }), _jsx("ul", { className: "divide-y divide-border/50 overflow-hidden rounded-2xl border border-border/60 bg-card", children: isLoading ? (Array.from({ length: 5 }).map((_, i) => (_jsx(RowSkeleton, { density: density }, i)))) : table.getRowModel().rows.length === 0 ? (_jsx("li", { className: "py-16 text-center text-sm text-muted-foreground", children: emptyMessage })) : (table.getRowModel().rows.map((row) => (_jsx(OpportunityRowItem, { row: row.original, density: density, renderLink: renderLink, getRowHref: getRowHref }, row.id)))) }), !isLoading && pageCount > 1 && (_jsxs("div", { className: "flex items-center justify-between gap-4", children: [_jsxs("p", { className: "text-xs text-muted-foreground", children: ["Page ", pageIndex + 1, " of ", pageCount] }), _jsxs("div", { className: "flex items-center gap-1.5", children: [_jsxs(ShadcnButton, { variant: "outline", size: "sm", onClick: () => table.previousPage(), disabled: !table.getCanPreviousPage(), children: [_jsx(ChevronLeft, { className: "size-4" }), "Previous"] }), _jsxs(ShadcnButton, { variant: "outline", size: "sm", onClick: () => table.nextPage(), disabled: !table.getCanNextPage(), children: ["Next", _jsx(ChevronRight, { className: "size-4" })] })] })] }))] }));
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=opportunities-table.js.map
|