@burdenoff/microfe-theglobalfuel 2026.705.3 → 2026.705.4
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/theglobalfuel/TheGlobalFuelRoot.js +54 -46
- package/dist/theglobalfuel/TheGlobalFuelRoot.js.map +1 -1
- package/dist/theglobalfuel/TheGlobalFuelRoutes.js +10 -6
- package/dist/theglobalfuel/TheGlobalFuelRoutes.js.map +1 -1
- package/dist/theglobalfuel/components/DataTable.js +126 -58
- package/dist/theglobalfuel/components/DataTable.js.map +1 -1
- package/dist/theglobalfuel/components/EmptyState.js +4 -4
- package/dist/theglobalfuel/components/EmptyState.js.map +1 -1
- package/dist/theglobalfuel/components/MetricsCard.js +2 -2
- package/dist/theglobalfuel/components/MetricsCard.js.map +1 -1
- package/dist/theglobalfuel/components/WorldMap.js +115 -0
- package/dist/theglobalfuel/components/WorldMap.js.map +1 -0
- package/dist/theglobalfuel/components/index.js +9 -0
- package/dist/theglobalfuel/components/viz/AllocationBar.js +68 -0
- package/dist/theglobalfuel/components/viz/AllocationBar.js.map +1 -0
- package/dist/theglobalfuel/components/viz/AreaChart.js +102 -0
- package/dist/theglobalfuel/components/viz/AreaChart.js.map +1 -0
- package/dist/theglobalfuel/components/viz/AvatarStack.js +2 -0
- package/dist/theglobalfuel/components/viz/BarChart.js +4 -0
- package/dist/theglobalfuel/components/viz/CertificateCard.js +4 -0
- package/dist/theglobalfuel/components/viz/DonutChart.js +109 -0
- package/dist/theglobalfuel/components/viz/DonutChart.js.map +1 -0
- package/dist/theglobalfuel/components/viz/HBarFunnel.js +3 -0
- package/dist/theglobalfuel/components/viz/Heatmap.js +3 -0
- package/dist/theglobalfuel/components/viz/KanbanBoard.js +2 -0
- package/dist/theglobalfuel/components/viz/LineChart.js +4 -0
- package/dist/theglobalfuel/components/viz/OrgTree.js +2 -0
- package/dist/theglobalfuel/components/viz/PathSteps.js +68 -0
- package/dist/theglobalfuel/components/viz/PathSteps.js.map +1 -0
- package/dist/theglobalfuel/components/viz/ProgressRing.js +6 -0
- package/dist/theglobalfuel/components/viz/ProgressRing.js.map +1 -0
- package/dist/theglobalfuel/components/viz/RatingStars.js +3 -0
- package/dist/theglobalfuel/components/viz/SegmentedTabs.js +3 -0
- package/dist/theglobalfuel/components/viz/SkillBar.js +3 -0
- package/dist/theglobalfuel/components/viz/Sparkline.js +74 -0
- package/dist/theglobalfuel/components/viz/Sparkline.js.map +1 -0
- package/dist/theglobalfuel/components/viz/StatCard.js +3 -0
- package/dist/theglobalfuel/components/viz/StepProgress.js +64 -0
- package/dist/theglobalfuel/components/viz/StepProgress.js.map +1 -0
- package/dist/theglobalfuel/components/viz/Timeline.js +66 -0
- package/dist/theglobalfuel/components/viz/Timeline.js.map +1 -0
- package/dist/theglobalfuel/components/viz/index.js +23 -0
- package/dist/theglobalfuel/components/viz/lib/Avatar.js +1 -0
- package/dist/theglobalfuel/components/viz/lib/CartesianFrame.js +119 -0
- package/dist/theglobalfuel/components/viz/lib/CartesianFrame.js.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/ResponsiveSvg.js +35 -0
- package/dist/theglobalfuel/components/viz/lib/ResponsiveSvg.js.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/format.js +17 -0
- package/dist/theglobalfuel/components/viz/lib/format.js.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/geometry.js +61 -0
- package/dist/theglobalfuel/components/viz/lib/geometry.js.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/hooks.js +39 -0
- package/dist/theglobalfuel/components/viz/lib/hooks.js.map +1 -0
- package/dist/theglobalfuel/components/viz/lib/palette.js +27 -0
- package/dist/theglobalfuel/components/viz/lib/palette.js.map +1 -0
- package/dist/theglobalfuel/pages/assets/AssetDetailPage.js +431 -316
- package/dist/theglobalfuel/pages/assets/AssetDetailPage.js.map +1 -1
- package/dist/theglobalfuel/pages/dashboard/DashboardPage.js +525 -227
- package/dist/theglobalfuel/pages/dashboard/DashboardPage.js.map +1 -1
- package/dist/theglobalfuel/pages/emissions/EmissionsPage.js +255 -206
- package/dist/theglobalfuel/pages/emissions/EmissionsPage.js.map +1 -1
- package/dist/theglobalfuel/pages/provenance/ProvenancePage.js +465 -0
- package/dist/theglobalfuel/pages/provenance/ProvenancePage.js.map +1 -0
- package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js +356 -227
- package/dist/theglobalfuel/pages/shipments/ShipmentsPage.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,119 +5,127 @@ import { useCallback as r, useEffect as i } from "react";
|
|
|
5
5
|
import { QueryClient as a, QueryClientProvider as o } from "@tanstack/react-query";
|
|
6
6
|
import { FeatureFlagProvider as s } from "@burdenoff/fe-libs/shared/feature-flags";
|
|
7
7
|
import { useI18n as c } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
8
|
-
import { Boxes as l, Factory as u, FileText as d, Gauge as f, Layers as p, LayoutDashboard as m, Leaf as h, ShieldCheck as g, Truck as _ } from "lucide-react";
|
|
9
|
-
import { jsx as
|
|
8
|
+
import { Boxes as l, Factory as u, FileText as d, Gauge as f, Layers as p, LayoutDashboard as m, Leaf as h, ShieldCheck as g, Truck as _, Waypoints as v } from "lucide-react";
|
|
9
|
+
import { jsx as y } from "react/jsx-runtime";
|
|
10
10
|
//#region src/theglobalfuel/TheGlobalFuelRoot.tsx
|
|
11
|
-
var
|
|
11
|
+
var b = new a({ defaultOptions: { queries: {
|
|
12
12
|
staleTime: 300 * 1e3,
|
|
13
13
|
retry: 1,
|
|
14
14
|
refetchOnWindowFocus: !1
|
|
15
|
-
} } }),
|
|
16
|
-
let { registerNavItems:
|
|
17
|
-
let n =
|
|
15
|
+
} } }), x = (a) => {
|
|
16
|
+
let { registerNavItems: x, registerFooterItems: S, basePath: C = "/" } = a, { t: w } = c(), T = r((e, t) => {
|
|
17
|
+
let n = w(e);
|
|
18
18
|
return n === e ? t : n;
|
|
19
|
-
}, [
|
|
19
|
+
}, [w]);
|
|
20
20
|
return i(() => {
|
|
21
|
-
if (
|
|
21
|
+
if (x) return x([
|
|
22
22
|
{
|
|
23
23
|
id: "theglobalfuel-dashboard",
|
|
24
|
-
label:
|
|
25
|
-
path: e(
|
|
26
|
-
icon: /* @__PURE__ */
|
|
24
|
+
label: T("theglobalfuel.nav.dashboard", "Dashboard"),
|
|
25
|
+
path: e(C, ""),
|
|
26
|
+
icon: /* @__PURE__ */ y(m, { size: 20 }),
|
|
27
27
|
order: 0,
|
|
28
28
|
group: "products"
|
|
29
29
|
},
|
|
30
30
|
{
|
|
31
31
|
id: "theglobalfuel-assets",
|
|
32
|
-
label:
|
|
33
|
-
path: e(
|
|
34
|
-
icon: /* @__PURE__ */
|
|
32
|
+
label: T("theglobalfuel.nav.assets", "Assets"),
|
|
33
|
+
path: e(C, "assets"),
|
|
34
|
+
icon: /* @__PURE__ */ y(u, { size: 20 }),
|
|
35
35
|
order: 1,
|
|
36
36
|
group: "products"
|
|
37
37
|
},
|
|
38
38
|
{
|
|
39
39
|
id: "theglobalfuel-production",
|
|
40
|
-
label:
|
|
41
|
-
path: e(
|
|
42
|
-
icon: /* @__PURE__ */
|
|
40
|
+
label: T("theglobalfuel.nav.production", "Production"),
|
|
41
|
+
path: e(C, "production"),
|
|
42
|
+
icon: /* @__PURE__ */ y(f, { size: 20 }),
|
|
43
43
|
order: 2,
|
|
44
44
|
group: "products"
|
|
45
45
|
},
|
|
46
46
|
{
|
|
47
47
|
id: "theglobalfuel-reserves",
|
|
48
|
-
label:
|
|
49
|
-
path: e(
|
|
50
|
-
icon: /* @__PURE__ */
|
|
48
|
+
label: T("theglobalfuel.nav.reserves", "Reserves"),
|
|
49
|
+
path: e(C, "reserves"),
|
|
50
|
+
icon: /* @__PURE__ */ y(p, { size: 20 }),
|
|
51
51
|
order: 3,
|
|
52
52
|
group: "products"
|
|
53
53
|
},
|
|
54
54
|
{
|
|
55
55
|
id: "theglobalfuel-contracts",
|
|
56
|
-
label:
|
|
57
|
-
path: e(
|
|
58
|
-
icon: /* @__PURE__ */
|
|
56
|
+
label: T("theglobalfuel.nav.contracts", "Offtake Contracts"),
|
|
57
|
+
path: e(C, "contracts"),
|
|
58
|
+
icon: /* @__PURE__ */ y(d, { size: 20 }),
|
|
59
59
|
order: 4,
|
|
60
60
|
group: "products"
|
|
61
61
|
},
|
|
62
62
|
{
|
|
63
63
|
id: "theglobalfuel-shipments",
|
|
64
|
-
label:
|
|
65
|
-
path: e(
|
|
66
|
-
icon: /* @__PURE__ */
|
|
64
|
+
label: T("theglobalfuel.nav.shipments", "Shipments"),
|
|
65
|
+
path: e(C, "shipments"),
|
|
66
|
+
icon: /* @__PURE__ */ y(_, { size: 20 }),
|
|
67
67
|
order: 5,
|
|
68
68
|
group: "products"
|
|
69
69
|
},
|
|
70
70
|
{
|
|
71
71
|
id: "theglobalfuel-inventory",
|
|
72
|
-
label:
|
|
73
|
-
path: e(
|
|
74
|
-
icon: /* @__PURE__ */
|
|
72
|
+
label: T("theglobalfuel.nav.inventory", "Inventory"),
|
|
73
|
+
path: e(C, "inventory"),
|
|
74
|
+
icon: /* @__PURE__ */ y(l, { size: 20 }),
|
|
75
75
|
order: 6,
|
|
76
76
|
group: "products"
|
|
77
77
|
},
|
|
78
78
|
{
|
|
79
79
|
id: "theglobalfuel-emissions",
|
|
80
|
-
label:
|
|
81
|
-
path: e(
|
|
82
|
-
icon: /* @__PURE__ */
|
|
80
|
+
label: T("theglobalfuel.nav.emissions", "Emissions"),
|
|
81
|
+
path: e(C, "emissions"),
|
|
82
|
+
icon: /* @__PURE__ */ y(h, { size: 20 }),
|
|
83
83
|
order: 7,
|
|
84
84
|
group: "products"
|
|
85
85
|
},
|
|
86
86
|
{
|
|
87
87
|
id: "theglobalfuel-compliance",
|
|
88
|
-
label:
|
|
89
|
-
path: e(
|
|
90
|
-
icon: /* @__PURE__ */
|
|
88
|
+
label: T("theglobalfuel.nav.compliance", "Compliance"),
|
|
89
|
+
path: e(C, "compliance"),
|
|
90
|
+
icon: /* @__PURE__ */ y(g, { size: 20 }),
|
|
91
91
|
order: 8,
|
|
92
92
|
group: "products"
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: "theglobalfuel-provenance",
|
|
96
|
+
label: T("theglobalfuel.nav.provenance", "Provenance"),
|
|
97
|
+
path: e(C, "provenance"),
|
|
98
|
+
icon: /* @__PURE__ */ y(v, { size: 20 }),
|
|
99
|
+
order: 9,
|
|
100
|
+
group: "products"
|
|
93
101
|
}
|
|
94
102
|
]);
|
|
95
103
|
}, [
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
104
|
+
x,
|
|
105
|
+
C,
|
|
106
|
+
T
|
|
99
107
|
]), i(() => {
|
|
100
|
-
if (
|
|
108
|
+
if (S) return S([{
|
|
101
109
|
id: "theglobalfuel-status",
|
|
102
|
-
label:
|
|
110
|
+
label: T("theglobalfuel.footer.ready", "TheGlobalFuel Ready"),
|
|
103
111
|
type: "status",
|
|
104
112
|
section: "left",
|
|
105
113
|
order: 10
|
|
106
114
|
}]);
|
|
107
|
-
}, [
|
|
108
|
-
client:
|
|
109
|
-
children: /* @__PURE__ */
|
|
115
|
+
}, [S, T]), /* @__PURE__ */ y(o, {
|
|
116
|
+
client: b,
|
|
117
|
+
children: /* @__PURE__ */ y(s, {
|
|
110
118
|
workspaceId: null,
|
|
111
119
|
gateway: "global",
|
|
112
120
|
defaultEnabled: !0,
|
|
113
|
-
children: /* @__PURE__ */
|
|
121
|
+
children: /* @__PURE__ */ y(t, {
|
|
114
122
|
...a,
|
|
115
|
-
children: /* @__PURE__ */
|
|
123
|
+
children: /* @__PURE__ */ y(n, {})
|
|
116
124
|
})
|
|
117
125
|
})
|
|
118
126
|
});
|
|
119
127
|
};
|
|
120
128
|
//#endregion
|
|
121
|
-
export {
|
|
129
|
+
export { x as TheGlobalFuelRoot };
|
|
122
130
|
|
|
123
131
|
//# sourceMappingURL=TheGlobalFuelRoot.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TheGlobalFuelRoot.js","names":[],"sources":["../../src/theglobalfuel/TheGlobalFuelRoot.tsx"],"sourcesContent":["/**\n * TheGlobalFuel Root Component\n * @module theglobalfuel\n *\n * Host-contract entry point. Registers the product's sidebar nav (nine sections\n * that map 1:1 to the wspace-theglobalfuel-svc `the*` backend) and mounts the\n * routed pages inside the shared QueryClient + FeatureFlag providers.\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n LayoutDashboard,\n Factory,\n Gauge,\n Layers,\n FileText,\n Truck,\n Boxes,\n Leaf,\n ShieldCheck,\n} from 'lucide-react';\nimport { TheGlobalFuelProvider } from './context/TheGlobalFuelContext';\nimport { TheGlobalFuelRoutes } from './TheGlobalFuelRoutes';\nimport { joinPath } from './utils/navigation';\nimport type { TheGlobalFuelRootProps, NavItem } from './types';\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n },\n});\n\nexport const TheGlobalFuelRoot: FC<TheGlobalFuelRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n // Register navigation items with the shell on mount. Ids/paths/orders match\n // the app-shell static NavRegistration block so the two are a single,\n // consistent source of truth.\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'theglobalfuel-dashboard',\n label: t('theglobalfuel.nav.dashboard', 'Dashboard'),\n path: joinPath(basePath, ''),\n icon: <LayoutDashboard size={20} />,\n order: 0,\n group: 'products',\n },\n {\n id: 'theglobalfuel-assets',\n label: t('theglobalfuel.nav.assets', 'Assets'),\n path: joinPath(basePath, 'assets'),\n icon: <Factory size={20} />,\n order: 1,\n group: 'products',\n },\n {\n id: 'theglobalfuel-production',\n label: t('theglobalfuel.nav.production', 'Production'),\n path: joinPath(basePath, 'production'),\n icon: <Gauge size={20} />,\n order: 2,\n group: 'products',\n },\n {\n id: 'theglobalfuel-reserves',\n label: t('theglobalfuel.nav.reserves', 'Reserves'),\n path: joinPath(basePath, 'reserves'),\n icon: <Layers size={20} />,\n order: 3,\n group: 'products',\n },\n {\n id: 'theglobalfuel-contracts',\n label: t('theglobalfuel.nav.contracts', 'Offtake Contracts'),\n path: joinPath(basePath, 'contracts'),\n icon: <FileText size={20} />,\n order: 4,\n group: 'products',\n },\n {\n id: 'theglobalfuel-shipments',\n label: t('theglobalfuel.nav.shipments', 'Shipments'),\n path: joinPath(basePath, 'shipments'),\n icon: <Truck size={20} />,\n order: 5,\n group: 'products',\n },\n {\n id: 'theglobalfuel-inventory',\n label: t('theglobalfuel.nav.inventory', 'Inventory'),\n path: joinPath(basePath, 'inventory'),\n icon: <Boxes size={20} />,\n order: 6,\n group: 'products',\n },\n {\n id: 'theglobalfuel-emissions',\n label: t('theglobalfuel.nav.emissions', 'Emissions'),\n path: joinPath(basePath, 'emissions'),\n icon: <Leaf size={20} />,\n order: 7,\n group: 'products',\n },\n {\n id: 'theglobalfuel-compliance',\n label: t('theglobalfuel.nav.compliance', 'Compliance'),\n path: joinPath(basePath, 'compliance'),\n icon: <ShieldCheck size={20} />,\n order: 8,\n group: 'products',\n },\n ];\n\n return registerNavItems(navItems);\n }, [registerNavItems, basePath, t]);\n\n useEffect(() => {\n if (!registerFooterItems) return;\n return registerFooterItems([\n {\n id: 'theglobalfuel-status',\n label: t('theglobalfuel.footer.ready', 'TheGlobalFuel Ready'),\n type: 'status',\n section: 'left',\n order: 10,\n },\n ]);\n }, [registerFooterItems, t]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <TheGlobalFuelProvider {...props}>\n <TheGlobalFuelRoutes />\n </TheGlobalFuelProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n"],"mappings":";;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"TheGlobalFuelRoot.js","names":[],"sources":["../../src/theglobalfuel/TheGlobalFuelRoot.tsx"],"sourcesContent":["/**\n * TheGlobalFuel Root Component\n * @module theglobalfuel\n *\n * Host-contract entry point. Registers the product's sidebar nav (nine sections\n * that map 1:1 to the wspace-theglobalfuel-svc `the*` backend) and mounts the\n * routed pages inside the shared QueryClient + FeatureFlag providers.\n */\n\nimport type { FC } from 'react';\nimport { useCallback, useEffect } from 'react';\nimport { QueryClient, QueryClientProvider } from '@tanstack/react-query';\nimport { FeatureFlagProvider } from '@burdenoff/fe-libs/shared/feature-flags';\nimport { useI18n } from '@burdenoff/fe-libs/shared/providers/shell/I18nProvider';\nimport {\n LayoutDashboard,\n Factory,\n Gauge,\n Layers,\n FileText,\n Truck,\n Boxes,\n Leaf,\n ShieldCheck,\n Waypoints,\n} from 'lucide-react';\nimport { TheGlobalFuelProvider } from './context/TheGlobalFuelContext';\nimport { TheGlobalFuelRoutes } from './TheGlobalFuelRoutes';\nimport { joinPath } from './utils/navigation';\nimport type { TheGlobalFuelRootProps, NavItem } from './types';\n\nconst queryClient = new QueryClient({\n defaultOptions: {\n queries: {\n staleTime: 5 * 60 * 1000,\n retry: 1,\n refetchOnWindowFocus: false,\n },\n },\n});\n\nexport const TheGlobalFuelRoot: FC<TheGlobalFuelRootProps> = (props) => {\n const { registerNavItems, registerFooterItems, basePath = '/' } = props;\n const { t: translate } = useI18n();\n const t = useCallback(\n (key: string, fallback: string): string => {\n const value = translate(key);\n return value === key ? fallback : value;\n },\n [translate]\n );\n\n // Register navigation items with the shell on mount. Ids/paths/orders match\n // the app-shell static NavRegistration block so the two are a single,\n // consistent source of truth.\n useEffect(() => {\n if (!registerNavItems) return;\n\n const navItems: NavItem[] = [\n {\n id: 'theglobalfuel-dashboard',\n label: t('theglobalfuel.nav.dashboard', 'Dashboard'),\n path: joinPath(basePath, ''),\n icon: <LayoutDashboard size={20} />,\n order: 0,\n group: 'products',\n },\n {\n id: 'theglobalfuel-assets',\n label: t('theglobalfuel.nav.assets', 'Assets'),\n path: joinPath(basePath, 'assets'),\n icon: <Factory size={20} />,\n order: 1,\n group: 'products',\n },\n {\n id: 'theglobalfuel-production',\n label: t('theglobalfuel.nav.production', 'Production'),\n path: joinPath(basePath, 'production'),\n icon: <Gauge size={20} />,\n order: 2,\n group: 'products',\n },\n {\n id: 'theglobalfuel-reserves',\n label: t('theglobalfuel.nav.reserves', 'Reserves'),\n path: joinPath(basePath, 'reserves'),\n icon: <Layers size={20} />,\n order: 3,\n group: 'products',\n },\n {\n id: 'theglobalfuel-contracts',\n label: t('theglobalfuel.nav.contracts', 'Offtake Contracts'),\n path: joinPath(basePath, 'contracts'),\n icon: <FileText size={20} />,\n order: 4,\n group: 'products',\n },\n {\n id: 'theglobalfuel-shipments',\n label: t('theglobalfuel.nav.shipments', 'Shipments'),\n path: joinPath(basePath, 'shipments'),\n icon: <Truck size={20} />,\n order: 5,\n group: 'products',\n },\n {\n id: 'theglobalfuel-inventory',\n label: t('theglobalfuel.nav.inventory', 'Inventory'),\n path: joinPath(basePath, 'inventory'),\n icon: <Boxes size={20} />,\n order: 6,\n group: 'products',\n },\n {\n id: 'theglobalfuel-emissions',\n label: t('theglobalfuel.nav.emissions', 'Emissions'),\n path: joinPath(basePath, 'emissions'),\n icon: <Leaf size={20} />,\n order: 7,\n group: 'products',\n },\n {\n id: 'theglobalfuel-compliance',\n label: t('theglobalfuel.nav.compliance', 'Compliance'),\n path: joinPath(basePath, 'compliance'),\n icon: <ShieldCheck size={20} />,\n order: 8,\n group: 'products',\n },\n {\n id: 'theglobalfuel-provenance',\n label: t('theglobalfuel.nav.provenance', 'Provenance'),\n path: joinPath(basePath, 'provenance'),\n icon: <Waypoints size={20} />,\n order: 9,\n group: 'products',\n },\n ];\n\n return registerNavItems(navItems);\n }, [registerNavItems, basePath, t]);\n\n useEffect(() => {\n if (!registerFooterItems) return;\n return registerFooterItems([\n {\n id: 'theglobalfuel-status',\n label: t('theglobalfuel.footer.ready', 'TheGlobalFuel Ready'),\n type: 'status',\n section: 'left',\n order: 10,\n },\n ]);\n }, [registerFooterItems, t]);\n\n return (\n <QueryClientProvider client={queryClient}>\n <FeatureFlagProvider workspaceId={null} gateway=\"global\" defaultEnabled={true}>\n <TheGlobalFuelProvider {...props}>\n <TheGlobalFuelRoutes />\n </TheGlobalFuelProvider>\n </FeatureFlagProvider>\n </QueryClientProvider>\n );\n};\n"],"mappings":"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"}
|
|
@@ -5,15 +5,15 @@ import { Navigate as i, Route as a, Routes as o, useLocation as s } from "react-
|
|
|
5
5
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
6
6
|
import { Spinner as u } from "@burdenoff/fe-libs/ui";
|
|
7
7
|
//#region src/theglobalfuel/TheGlobalFuelRoutes.tsx
|
|
8
|
-
var d = r(() => import("./pages/assets/AssetsPage.js").then((e) => ({ default: e.AssetsPage }))), f = r(() => import("./pages/assets/AssetDetailPage.js").then((e) => ({ default: e.AssetDetailPage }))), p = r(() => import("./pages/production/ProductionPage.js").then((e) => ({ default: e.ProductionPage }))), m = r(() => import("./pages/reserves/ReservesPage.js").then((e) => ({ default: e.ReservesPage }))), h = r(() => import("./pages/contracts/ContractsPage.js").then((e) => ({ default: e.ContractsPage }))), g = r(() => import("./pages/contracts/ContractDetailPage.js").then((e) => ({ default: e.ContractDetailPage }))), _ = r(() => import("./pages/shipments/ShipmentsPage.js").then((e) => ({ default: e.ShipmentsPage }))), v = r(() => import("./pages/inventory/InventoryPage.js").then((e) => ({ default: e.InventoryPage }))), y = r(() => import("./pages/emissions/EmissionsPage.js").then((e) => ({ default: e.EmissionsPage }))), b = r(() => import("./pages/compliance/CompliancePage.js").then((e) => ({ default: e.CompliancePage }))), x = () => /* @__PURE__ */ c("div", {
|
|
8
|
+
var d = r(() => import("./pages/assets/AssetsPage.js").then((e) => ({ default: e.AssetsPage }))), f = r(() => import("./pages/assets/AssetDetailPage.js").then((e) => ({ default: e.AssetDetailPage }))), p = r(() => import("./pages/production/ProductionPage.js").then((e) => ({ default: e.ProductionPage }))), m = r(() => import("./pages/reserves/ReservesPage.js").then((e) => ({ default: e.ReservesPage }))), h = r(() => import("./pages/contracts/ContractsPage.js").then((e) => ({ default: e.ContractsPage }))), g = r(() => import("./pages/contracts/ContractDetailPage.js").then((e) => ({ default: e.ContractDetailPage }))), _ = r(() => import("./pages/shipments/ShipmentsPage.js").then((e) => ({ default: e.ShipmentsPage }))), v = r(() => import("./pages/inventory/InventoryPage.js").then((e) => ({ default: e.InventoryPage }))), y = r(() => import("./pages/emissions/EmissionsPage.js").then((e) => ({ default: e.EmissionsPage }))), b = r(() => import("./pages/compliance/CompliancePage.js").then((e) => ({ default: e.CompliancePage }))), x = r(() => import("./pages/provenance/ProvenancePage.js").then((e) => ({ default: e.ProvenancePage }))), S = () => /* @__PURE__ */ c("div", {
|
|
9
9
|
className: "flex min-h-[400px] items-center justify-center",
|
|
10
10
|
children: /* @__PURE__ */ c(u, { size: "lg" })
|
|
11
|
-
}),
|
|
12
|
-
let { basePath: r, isStandalone: u } = e(),
|
|
13
|
-
return
|
|
11
|
+
}), C = () => {
|
|
12
|
+
let { basePath: r, isStandalone: u } = e(), C = s(), w = r === "/" ? "" : (r ?? "").replace(/\/$/, "");
|
|
13
|
+
return w && !u && !(C.pathname === w || C.pathname.startsWith(w + "/")) ? null : /* @__PURE__ */ c("div", {
|
|
14
14
|
className: "flex min-h-full flex-col",
|
|
15
15
|
children: /* @__PURE__ */ c(n, {
|
|
16
|
-
fallback: /* @__PURE__ */ c(
|
|
16
|
+
fallback: /* @__PURE__ */ c(S, {}),
|
|
17
17
|
children: /* @__PURE__ */ l(o, { children: [
|
|
18
18
|
/* @__PURE__ */ c(a, {
|
|
19
19
|
index: !0,
|
|
@@ -59,6 +59,10 @@ var d = r(() => import("./pages/assets/AssetsPage.js").then((e) => ({ default: e
|
|
|
59
59
|
path: "compliance",
|
|
60
60
|
element: /* @__PURE__ */ c(b, {})
|
|
61
61
|
}),
|
|
62
|
+
/* @__PURE__ */ c(a, {
|
|
63
|
+
path: "provenance",
|
|
64
|
+
element: /* @__PURE__ */ c(x, {})
|
|
65
|
+
}),
|
|
62
66
|
/* @__PURE__ */ c(a, {
|
|
63
67
|
path: "*",
|
|
64
68
|
element: /* @__PURE__ */ c(i, {
|
|
@@ -71,6 +75,6 @@ var d = r(() => import("./pages/assets/AssetsPage.js").then((e) => ({ default: e
|
|
|
71
75
|
});
|
|
72
76
|
};
|
|
73
77
|
//#endregion
|
|
74
|
-
export {
|
|
78
|
+
export { C as TheGlobalFuelRoutes };
|
|
75
79
|
|
|
76
80
|
//# sourceMappingURL=TheGlobalFuelRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TheGlobalFuelRoutes.js","names":[],"sources":["../../src/theglobalfuel/TheGlobalFuelRoutes.tsx"],"sourcesContent":["/**\n * TheGlobalFuel Routes\n * @module theglobalfuel\n *\n * Domain routes. The dashboard is eager-loaded (primary landing); all other\n * pages are lazy-loaded. Every route maps to a real `the*` backend capability.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router-dom';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useTheGlobalFuel } from './context/TheGlobalFuelContext';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/dashboard/DashboardPage';\n\n// Registry — Assets, Production, Reserves\nconst AssetsPage = lazy(() =>\n import('./pages/assets/AssetsPage').then((m) => ({ default: m.AssetsPage }))\n);\nconst AssetDetailPage = lazy(() =>\n import('./pages/assets/AssetDetailPage').then((m) => ({ default: m.AssetDetailPage }))\n);\nconst ProductionPage = lazy(() =>\n import('./pages/production/ProductionPage').then((m) => ({ default: m.ProductionPage }))\n);\nconst ReservesPage = lazy(() =>\n import('./pages/reserves/ReservesPage').then((m) => ({ default: m.ReservesPage }))\n);\n\n// Commerce — Offtake Contracts, Shipments, Inventory\nconst ContractsPage = lazy(() =>\n import('./pages/contracts/ContractsPage').then((m) => ({ default: m.ContractsPage }))\n);\nconst ContractDetailPage = lazy(() =>\n import('./pages/contracts/ContractDetailPage').then((m) => ({ default: m.ContractDetailPage }))\n);\nconst ShipmentsPage = lazy(() =>\n import('./pages/shipments/ShipmentsPage').then((m) => ({ default: m.ShipmentsPage }))\n);\nconst InventoryPage = lazy(() =>\n import('./pages/inventory/InventoryPage').then((m) => ({ default: m.InventoryPage }))\n);\n\n// Sustainability — Emissions, Compliance\nconst EmissionsPage = lazy(() =>\n import('./pages/emissions/EmissionsPage').then((m) => ({ default: m.EmissionsPage }))\n);\nconst CompliancePage = lazy(() =>\n import('./pages/compliance/CompliancePage').then((m) => ({ default: m.CompliancePage }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const TheGlobalFuelRoutes: FC = () => {\n const { basePath, isStandalone } = useTheGlobalFuel();\n const location = useLocation();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={<DashboardPage />} />\n\n <Route path=\"assets\" element={<AssetsPage />} />\n <Route path=\"assets/:id\" element={<AssetDetailPage />} />\n\n <Route path=\"production\" element={<ProductionPage />} />\n\n <Route path=\"reserves\" element={<ReservesPage />} />\n\n <Route path=\"contracts\" element={<ContractsPage />} />\n <Route path=\"contracts/:id\" element={<ContractDetailPage />} />\n\n <Route path=\"shipments\" element={<ShipmentsPage />} />\n\n <Route path=\"inventory\" element={<InventoryPage />} />\n\n <Route path=\"emissions\" element={<EmissionsPage />} />\n\n <Route path=\"compliance\" element={<CompliancePage />} />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":";;;;;;;AAiBA,IAAM,IAAa,QACjB,OAAO,gCAA6B,MAAM,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAC7E,EACK,IAAkB,QACtB,OAAO,qCAAkC,MAAM,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,CACvF,EACK,IAAiB,QACrB,OAAO,wCAAqC,MAAM,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,CACzF,EACK,IAAe,QACnB,OAAO,oCAAiC,MAAM,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,CACnF,EAGK,IAAgB,QACpB,OAAO,sCAAmC,MAAM,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CACtF,EACK,IAAqB,QACzB,OAAO,2CAAwC,MAAM,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,CAChG,EACK,IAAgB,QACpB,OAAO,sCAAmC,MAAM,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CACtF,EACK,IAAgB,QACpB,OAAO,sCAAmC,MAAM,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CACtF,EAGK,IAAgB,QACpB,OAAO,sCAAmC,MAAM,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,CACtF,EACK,IAAiB,QACrB,OAAO,wCAAqC,MAAM,OAAO,EAAE,SAAS,EAAE,gBAAgB,EAAE,CACzF,EAEK,UACJ,kBAAC,OAAD;CAAK,WAAU;WACb,kBAAC,GAAD,EAAS,MAAK,MAAO,CAAA;CACjB,CAAA,EAGK,UAAgC;CAC3C,IAAM,EAAE,aAAU,oBAAiB,GAAkB,EAC/C,IAAW,GAAa,EAExB,IAAqB,MAAa,MAAM,MAAM,KAAY,IAAI,QAAQ,OAAO,GAAG;AAYtF,QATI,KAAsB,CAAC,KAIrB,EAFF,EAAS,aAAa,KACtB,EAAS,SAAS,WAAW,IAAqB,IAAI,IAE/C,OAKT,kBAAC,OAAD;EAAK,WAAU;YACb,kBAAC,GAAD;GAAU,UAAU,kBAAC,GAAD,EAAc,CAAA;aAChC,kBAAC,GAAD,EAAA,UAAA;IACE,kBAAC,GAAD;KAAO,OAAA;KAAM,SAAS,kBAAC,GAAD,EAAiB,CAAA;KAAI,CAAA;IAE3C,kBAAC,GAAD;KAAO,MAAK;KAAS,SAAS,kBAAC,GAAD,EAAc,CAAA;KAAI,CAAA;IAChD,kBAAC,GAAD;KAAO,MAAK;KAAa,SAAS,kBAAC,GAAD,EAAmB,CAAA;KAAI,CAAA;IAEzD,kBAAC,GAAD;KAAO,MAAK;KAAa,SAAS,kBAAC,GAAD,EAAkB,CAAA;KAAI,CAAA;IAExD,kBAAC,GAAD;KAAO,MAAK;KAAW,SAAS,kBAAC,GAAD,EAAgB,CAAA;KAAI,CAAA;IAEpD,kBAAC,GAAD;KAAO,MAAK;KAAY,SAAS,kBAAC,GAAD,EAAiB,CAAA;KAAI,CAAA;IACtD,kBAAC,GAAD;KAAO,MAAK;KAAgB,SAAS,kBAAC,GAAD,EAAsB,CAAA;KAAI,CAAA;IAE/D,kBAAC,GAAD;KAAO,MAAK;KAAY,SAAS,kBAAC,GAAD,EAAiB,CAAA;KAAI,CAAA;IAEtD,kBAAC,GAAD;KAAO,MAAK;KAAY,SAAS,kBAAC,GAAD,EAAiB,CAAA;KAAI,CAAA;IAEtD,kBAAC,GAAD;KAAO,MAAK;KAAY,SAAS,kBAAC,GAAD,EAAiB,CAAA;KAAI,CAAA;IAEtD,kBAAC,GAAD;KAAO,MAAK;KAAa,SAAS,kBAAC,GAAD,EAAkB,CAAA;KAAI,CAAA;IAExD,kBAAC,GAAD;KAAO,MAAK;KAAI,SAAS,kBAAC,GAAD;MAAU,IAAG;MAAG,SAAA;MAAU,CAAA;KAAI,CAAA;IAChD,EAAA,CAAA;GACA,CAAA;EACP,CAAA"}
|
|
1
|
+
{"version":3,"file":"TheGlobalFuelRoutes.js","names":[],"sources":["../../src/theglobalfuel/TheGlobalFuelRoutes.tsx"],"sourcesContent":["/**\n * TheGlobalFuel Routes\n * @module theglobalfuel\n *\n * Domain routes. The dashboard is eager-loaded (primary landing); all other\n * pages are lazy-loaded. Every route maps to a real `the*` backend capability.\n */\n\nimport { type FC, lazy, Suspense } from 'react';\nimport { Routes, Route, Navigate, useLocation } from 'react-router-dom';\nimport { Spinner } from '@burdenoff/fe-libs/ui';\nimport { useTheGlobalFuel } from './context/TheGlobalFuelContext';\n\n// Eager — primary landing\nimport { DashboardPage } from './pages/dashboard/DashboardPage';\n\n// Registry — Assets, Production, Reserves\nconst AssetsPage = lazy(() =>\n import('./pages/assets/AssetsPage').then((m) => ({ default: m.AssetsPage }))\n);\nconst AssetDetailPage = lazy(() =>\n import('./pages/assets/AssetDetailPage').then((m) => ({ default: m.AssetDetailPage }))\n);\nconst ProductionPage = lazy(() =>\n import('./pages/production/ProductionPage').then((m) => ({ default: m.ProductionPage }))\n);\nconst ReservesPage = lazy(() =>\n import('./pages/reserves/ReservesPage').then((m) => ({ default: m.ReservesPage }))\n);\n\n// Commerce — Offtake Contracts, Shipments, Inventory\nconst ContractsPage = lazy(() =>\n import('./pages/contracts/ContractsPage').then((m) => ({ default: m.ContractsPage }))\n);\nconst ContractDetailPage = lazy(() =>\n import('./pages/contracts/ContractDetailPage').then((m) => ({ default: m.ContractDetailPage }))\n);\nconst ShipmentsPage = lazy(() =>\n import('./pages/shipments/ShipmentsPage').then((m) => ({ default: m.ShipmentsPage }))\n);\nconst InventoryPage = lazy(() =>\n import('./pages/inventory/InventoryPage').then((m) => ({ default: m.InventoryPage }))\n);\n\n// Sustainability — Emissions, Compliance\nconst EmissionsPage = lazy(() =>\n import('./pages/emissions/EmissionsPage').then((m) => ({ default: m.EmissionsPage }))\n);\nconst CompliancePage = lazy(() =>\n import('./pages/compliance/CompliancePage').then((m) => ({ default: m.CompliancePage }))\n);\nconst ProvenancePage = lazy(() =>\n import('./pages/provenance/ProvenancePage').then((m) => ({ default: m.ProvenancePage }))\n);\n\nconst PageLoader: FC = () => (\n <div className=\"flex min-h-[400px] items-center justify-center\">\n <Spinner size=\"lg\" />\n </div>\n);\n\nexport const TheGlobalFuelRoutes: FC = () => {\n const { basePath, isStandalone } = useTheGlobalFuel();\n const location = useLocation();\n\n const normalizedBasePath = basePath === '/' ? '' : (basePath ?? '').replace(/\\/$/, '');\n\n // Guard: only render if the current path matches basePath (integrated mode).\n if (normalizedBasePath && !isStandalone) {\n const pathMatches =\n location.pathname === normalizedBasePath ||\n location.pathname.startsWith(normalizedBasePath + '/');\n if (!pathMatches) {\n return null;\n }\n }\n\n return (\n <div className=\"flex min-h-full flex-col\">\n <Suspense fallback={<PageLoader />}>\n <Routes>\n <Route index element={<DashboardPage />} />\n\n <Route path=\"assets\" element={<AssetsPage />} />\n <Route path=\"assets/:id\" element={<AssetDetailPage />} />\n\n <Route path=\"production\" element={<ProductionPage />} />\n\n <Route path=\"reserves\" element={<ReservesPage />} />\n\n <Route path=\"contracts\" element={<ContractsPage />} />\n <Route path=\"contracts/:id\" element={<ContractDetailPage />} />\n\n <Route path=\"shipments\" element={<ShipmentsPage />} />\n\n <Route path=\"inventory\" element={<InventoryPage />} />\n\n <Route path=\"emissions\" element={<EmissionsPage />} />\n\n <Route path=\"compliance\" element={<CompliancePage />} />\n\n <Route path=\"provenance\" element={<ProvenancePage />} />\n\n <Route path=\"*\" element={<Navigate to=\"\" replace />} />\n </Routes>\n </Suspense>\n </div>\n );\n};\n"],"mappings":"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"}
|
|
@@ -1,81 +1,149 @@
|
|
|
1
1
|
import { cn as e } from "../utils/cn.js";
|
|
2
|
-
import {
|
|
3
|
-
import { ChevronDown as
|
|
4
|
-
import { jsx as
|
|
5
|
-
import { GlassCard as
|
|
2
|
+
import { useId as t, useMemo as n, useState as r } from "react";
|
|
3
|
+
import { ChevronDown as i, ChevronRight as a, ChevronUp as o, ChevronsUpDown as s } from "lucide-react";
|
|
4
|
+
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
5
|
+
import { GlassCard as u } from "@burdenoff/fe-libs/ui";
|
|
6
6
|
//#region src/theglobalfuel/components/DataTable.tsx
|
|
7
|
-
var
|
|
7
|
+
var d = (e, t) => {
|
|
8
8
|
e.target === e.currentTarget && (e.key === "Enter" || e.key === " ") && (e.preventDefault(), t());
|
|
9
|
-
},
|
|
9
|
+
}, f = {
|
|
10
10
|
left: "text-left",
|
|
11
11
|
right: "text-right",
|
|
12
12
|
center: "text-center"
|
|
13
13
|
};
|
|
14
|
-
function
|
|
15
|
-
let [
|
|
16
|
-
if (!
|
|
17
|
-
let e =
|
|
18
|
-
if (!e?.sortValue) return
|
|
19
|
-
let t =
|
|
20
|
-
return [...
|
|
14
|
+
function p({ columns: p, rows: m, rowKey: h, onRowClick: g, rowLabel: _, className: v, defaultSort: y }) {
|
|
15
|
+
let [b, x] = r(y ?? null), S = t(), C = n(() => {
|
|
16
|
+
if (!b) return m;
|
|
17
|
+
let e = p.find((e) => e.key === b.key);
|
|
18
|
+
if (!e?.sortValue) return m;
|
|
19
|
+
let t = b.dir === "asc" ? 1 : -1;
|
|
20
|
+
return [...m].sort((n, r) => {
|
|
21
21
|
let i = e.sortValue(n), a = e.sortValue(r);
|
|
22
22
|
return i < a ? -1 * t : i > a ? 1 * t : 0;
|
|
23
23
|
});
|
|
24
24
|
}, [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
]),
|
|
29
|
-
|
|
25
|
+
m,
|
|
26
|
+
b,
|
|
27
|
+
p
|
|
28
|
+
]), w = (e) => {
|
|
29
|
+
x((t) => t?.key === e ? {
|
|
30
30
|
key: e,
|
|
31
31
|
dir: t.dir === "asc" ? "desc" : "asc"
|
|
32
32
|
} : {
|
|
33
33
|
key: e,
|
|
34
34
|
dir: "asc"
|
|
35
35
|
});
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
36
|
+
}, T = () => x((e) => e && {
|
|
37
|
+
key: e.key,
|
|
38
|
+
dir: e.dir === "asc" ? "desc" : "asc"
|
|
39
|
+
}), E = n(() => p.filter((e) => e.sortValue), [p]), D = (e) => g ? {
|
|
40
|
+
role: "button",
|
|
41
|
+
tabIndex: 0,
|
|
42
|
+
"aria-label": _?.(e),
|
|
43
|
+
onClick: () => g(e),
|
|
44
|
+
onKeyDown: (t) => d(t, () => g(e))
|
|
45
|
+
} : {}, [O, ...k] = p;
|
|
46
|
+
return /* @__PURE__ */ l("div", {
|
|
47
|
+
className: v,
|
|
48
|
+
children: [/* @__PURE__ */ c(u, {
|
|
49
|
+
treatment: "plain",
|
|
50
|
+
className: "hidden overflow-hidden md:block",
|
|
51
|
+
children: /* @__PURE__ */ c("div", {
|
|
52
|
+
className: "overflow-x-auto",
|
|
53
|
+
children: /* @__PURE__ */ l("table", {
|
|
54
|
+
className: "w-full border-collapse text-sm",
|
|
55
|
+
children: [/* @__PURE__ */ c("thead", { children: /* @__PURE__ */ c("tr", {
|
|
56
|
+
className: "border-b border-border-seam",
|
|
57
|
+
children: p.map((t) => {
|
|
58
|
+
let n = !!t.sortValue, r = b?.key === t.key;
|
|
59
|
+
return /* @__PURE__ */ c("th", {
|
|
60
|
+
scope: "col",
|
|
61
|
+
role: n ? "button" : void 0,
|
|
62
|
+
tabIndex: n ? 0 : void 0,
|
|
63
|
+
onClick: n ? () => w(t.key) : void 0,
|
|
64
|
+
onKeyDown: n ? (e) => d(e, () => w(t.key)) : void 0,
|
|
65
|
+
"aria-sort": r ? b?.dir === "asc" ? "ascending" : "descending" : void 0,
|
|
66
|
+
className: e("px-4 py-3 font-medium text-text-secondary whitespace-nowrap", f[t.align ?? "left"], t.hideOnMobile && "hidden md:table-cell", n && "cursor-pointer select-none hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]"),
|
|
67
|
+
children: /* @__PURE__ */ l("span", {
|
|
68
|
+
className: e("inline-flex items-center gap-1", t.align === "right" && "flex-row-reverse"),
|
|
69
|
+
children: [t.header, n && (r ? b?.dir === "asc" ? /* @__PURE__ */ c(o, { className: "h-3.5 w-3.5 text-accent" }) : /* @__PURE__ */ c(i, { className: "h-3.5 w-3.5 text-accent" }) : /* @__PURE__ */ c(s, { className: "h-3.5 w-3.5 opacity-40" }))]
|
|
70
|
+
})
|
|
71
|
+
}, t.key);
|
|
72
|
+
})
|
|
73
|
+
}) }), /* @__PURE__ */ c("tbody", { children: C.map((t) => /* @__PURE__ */ c("tr", {
|
|
74
|
+
...D(t),
|
|
75
|
+
className: e("group border-b border-border-seam/60 last:border-0", g && "cursor-pointer transition-colors hover:bg-bg-sunken/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--color-focus-ring)]"),
|
|
76
|
+
children: p.map((n) => /* @__PURE__ */ c("td", {
|
|
77
|
+
className: e("px-4 py-3 text-text-primary align-middle", f[n.align ?? "left"], n.hideOnMobile && "hidden md:table-cell", n.className),
|
|
78
|
+
children: n.render(t)
|
|
79
|
+
}, n.key))
|
|
80
|
+
}, h(t))) })]
|
|
81
|
+
})
|
|
74
82
|
})
|
|
75
|
-
})
|
|
83
|
+
}), /* @__PURE__ */ l("div", {
|
|
84
|
+
className: "space-y-2.5 md:hidden",
|
|
85
|
+
children: [E.length > 0 && /* @__PURE__ */ l("div", {
|
|
86
|
+
className: "flex items-center justify-end gap-1.5 px-0.5",
|
|
87
|
+
children: [
|
|
88
|
+
/* @__PURE__ */ c("label", {
|
|
89
|
+
htmlFor: S,
|
|
90
|
+
className: "text-xs text-text-tertiary",
|
|
91
|
+
children: "Sort"
|
|
92
|
+
}),
|
|
93
|
+
/* @__PURE__ */ l("select", {
|
|
94
|
+
id: S,
|
|
95
|
+
value: b?.key ?? "",
|
|
96
|
+
onChange: (e) => x(e.target.value ? {
|
|
97
|
+
key: e.target.value,
|
|
98
|
+
dir: b?.dir ?? "asc"
|
|
99
|
+
} : null),
|
|
100
|
+
className: "rounded-md border border-border-subtle bg-bg-surface px-2 py-1 text-xs text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
|
|
101
|
+
children: [/* @__PURE__ */ c("option", {
|
|
102
|
+
value: "",
|
|
103
|
+
children: "Default order"
|
|
104
|
+
}), E.map((e) => /* @__PURE__ */ c("option", {
|
|
105
|
+
value: e.key,
|
|
106
|
+
children: typeof e.header == "string" ? e.header : e.key
|
|
107
|
+
}, e.key))]
|
|
108
|
+
}),
|
|
109
|
+
b && /* @__PURE__ */ c("button", {
|
|
110
|
+
type: "button",
|
|
111
|
+
onClick: T,
|
|
112
|
+
"aria-label": b.dir === "asc" ? "Sort ascending" : "Sort descending",
|
|
113
|
+
className: "inline-flex h-7 w-7 items-center justify-center rounded-md border border-border-subtle bg-bg-surface text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]",
|
|
114
|
+
children: b.dir === "asc" ? /* @__PURE__ */ c(o, { className: "h-4 w-4" }) : /* @__PURE__ */ c(i, { className: "h-4 w-4" })
|
|
115
|
+
})
|
|
116
|
+
]
|
|
117
|
+
}), C.map((t) => /* @__PURE__ */ l("div", {
|
|
118
|
+
...D(t),
|
|
119
|
+
className: e("rounded-xl border border-border-subtle bg-bg-surface p-4", g && "cursor-pointer transition-colors hover:bg-bg-sunken/40 active:bg-bg-sunken/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]"),
|
|
120
|
+
children: [O && /* @__PURE__ */ l("div", {
|
|
121
|
+
className: "flex items-start justify-between gap-3",
|
|
122
|
+
children: [/* @__PURE__ */ c("div", {
|
|
123
|
+
className: "min-w-0 flex-1",
|
|
124
|
+
children: O.render(t)
|
|
125
|
+
}), g && /* @__PURE__ */ c(a, {
|
|
126
|
+
className: "mt-0.5 h-4 w-4 shrink-0 text-text-tertiary",
|
|
127
|
+
"aria-hidden": !0
|
|
128
|
+
})]
|
|
129
|
+
}), k.length > 0 && /* @__PURE__ */ c("dl", {
|
|
130
|
+
className: "mt-3 grid grid-cols-2 gap-x-4 gap-y-2.5 border-t border-border-subtle/70 pt-3",
|
|
131
|
+
children: k.map((e) => /* @__PURE__ */ l("div", {
|
|
132
|
+
className: "min-w-0",
|
|
133
|
+
children: [/* @__PURE__ */ c("dt", {
|
|
134
|
+
className: "text-[11px] uppercase tracking-wide text-text-tertiary",
|
|
135
|
+
children: e.header
|
|
136
|
+
}), /* @__PURE__ */ c("dd", {
|
|
137
|
+
className: "mt-0.5 text-sm text-text-primary break-words",
|
|
138
|
+
children: e.render(t)
|
|
139
|
+
})]
|
|
140
|
+
}, e.key))
|
|
141
|
+
})]
|
|
142
|
+
}, h(t)))]
|
|
143
|
+
})]
|
|
76
144
|
});
|
|
77
145
|
}
|
|
78
146
|
//#endregion
|
|
79
|
-
export {
|
|
147
|
+
export { p as DataTable };
|
|
80
148
|
|
|
81
149
|
//# sourceMappingURL=DataTable.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataTable.js","names":[],"sources":["../../../src/theglobalfuel/components/DataTable.tsx"],"sourcesContent":["/**\n * DataTable — a lightweight, semantic-token table for list pages.\n * @module theglobalfuel/components\n *\n * Deliberately minimal (no external table lib). Renders a responsive,\n * horizontally-scrollable table wrapped in a GlassCard. Columns declare a\n * header, a render fn, optional alignment, and optionally a `sortValue` to make\n * the column click-sortable.\n */\n\nimport { useMemo, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { ChevronUp, ChevronDown, ChevronsUpDown } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\nexport interface Column<T> {\n key: string;\n header: ReactNode;\n render: (row: T) => ReactNode;\n align?: 'left' | 'right' | 'center';\n className?: string;\n /** Hide below the `md` breakpoint for a mobile-friendly layout. */\n hideOnMobile?: boolean;\n /** Provide to make this column click-sortable (returns a comparable value). */\n sortValue?: (row: T) => string | number;\n}\n\ninterface DataTableProps<T> {\n columns: Column<T>[];\n rows: T[];\n rowKey: (row: T) => string;\n onRowClick?: (row: T) => void;\n /** Accessible label for a clickable row (e.g. `(a) => `Open ${a.name}``). */\n rowLabel?: (row: T) => string;\n className?: string;\n /** Default sort: a column key + direction. */\n defaultSort?: { key: string; dir: 'asc' | 'desc' };\n}\n\n/** Enter/Space activate — only when the event originates on the element itself\n * (not on an interactive descendant like a Select or Button inside a cell). */\nconst activateOnKey = (e: KeyboardEvent, fn: () => void) => {\n if (e.target !== e.currentTarget) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n fn();\n }\n};\n\nconst alignClass = {\n left: 'text-left',\n right: 'text-right',\n center: 'text-center',\n} as const;\n\nexport function DataTable<T>({\n columns,\n rows,\n rowKey,\n onRowClick,\n rowLabel,\n className,\n defaultSort,\n}: DataTableProps<T>) {\n const [sort, setSort] = useState<{ key: string; dir: 'asc' | 'desc' } | null>(\n defaultSort ?? null\n );\n\n const sortedRows = useMemo(() => {\n if (!sort) return rows;\n const col = columns.find((c) => c.key === sort.key);\n if (!col?.sortValue) return rows;\n const dir = sort.dir === 'asc' ? 1 : -1;\n return [...rows].sort((a, b) => {\n const va = col.sortValue!(a);\n const vb = col.sortValue!(b);\n if (va < vb) return -1 * dir;\n if (va > vb) return 1 * dir;\n return 0;\n });\n }, [rows, sort, columns]);\n\n const toggleSort = (key: string) => {\n setSort((prev) =>\n prev?.key === key ? { key, dir: prev.dir === 'asc' ? 'desc' : 'asc' } : { key, dir: 'asc' }\n );\n };\n\n return (\n <GlassCard treatment=\"plain\" className={cn('overflow-hidden', className)}>\n <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam\">\n {columns.map((col) => {\n const sortable = Boolean(col.sortValue);\n const active = sort?.key === col.key;\n return (\n <th\n key={col.key}\n scope=\"col\"\n role={sortable ? 'button' : undefined}\n tabIndex={sortable ? 0 : undefined}\n onClick={sortable ? () => toggleSort(col.key) : undefined}\n onKeyDown={\n sortable ? (e) => activateOnKey(e, () => toggleSort(col.key)) : undefined\n }\n aria-sort={\n active ? (sort?.dir === 'asc' ? 'ascending' : 'descending') : undefined\n }\n className={cn(\n 'px-4 py-3 font-medium text-text-secondary whitespace-nowrap',\n alignClass[col.align ?? 'left'],\n col.hideOnMobile && 'hidden md:table-cell',\n sortable &&\n 'cursor-pointer select-none hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]'\n )}\n >\n <span\n className={cn(\n 'inline-flex items-center gap-1',\n col.align === 'right' && 'flex-row-reverse'\n )}\n >\n {col.header}\n {sortable &&\n (active ? (\n sort?.dir === 'asc' ? (\n <ChevronUp className=\"h-3.5 w-3.5 text-accent\" />\n ) : (\n <ChevronDown className=\"h-3.5 w-3.5 text-accent\" />\n )\n ) : (\n <ChevronsUpDown className=\"h-3.5 w-3.5 opacity-40\" />\n ))}\n </span>\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {sortedRows.map((row) => (\n <tr\n key={rowKey(row)}\n onClick={onRowClick ? () => onRowClick(row) : undefined}\n onKeyDown={onRowClick ? (e) => activateOnKey(e, () => onRowClick(row)) : undefined}\n role={onRowClick ? 'button' : undefined}\n tabIndex={onRowClick ? 0 : undefined}\n aria-label={onRowClick ? rowLabel?.(row) : undefined}\n className={cn(\n 'group border-b border-border-seam/60 last:border-0',\n onRowClick &&\n 'cursor-pointer transition-colors hover:bg-bg-sunken/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--color-focus-ring)]'\n )}\n >\n {columns.map((col) => (\n <td\n key={col.key}\n className={cn(\n 'px-4 py-3 text-text-primary align-middle',\n alignClass[col.align ?? 'left'],\n col.hideOnMobile && 'hidden md:table-cell',\n col.className\n )}\n >\n {col.render(row)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </GlassCard>\n );\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataTable.js","names":[],"sources":["../../../src/theglobalfuel/components/DataTable.tsx"],"sourcesContent":["/**\n * DataTable — a lightweight, semantic-token table for list pages.\n * @module theglobalfuel/components\n *\n * Deliberately minimal (no external table lib). Columns declare a header, a\n * render fn, optional alignment, and optionally a `sortValue` to make the column\n * click-sortable.\n *\n * Responsive strategy:\n * - At `md` and up it renders a horizontally-scrollable table wrapped in a\n * GlassCard (the classic desktop layout).\n * - Below `md` it renders each row as a native-feeling, stacked \"card\": the\n * first column becomes the card's headline (with a chevron affordance when\n * the row is clickable) and the remaining columns render as label→value\n * pairs. Sort + click behavior carry over, so every list page is usable on\n * mobile with zero page-level changes.\n */\n\nimport { useId, useMemo, useState, type KeyboardEvent, type ReactNode } from 'react';\nimport { ChevronUp, ChevronDown, ChevronsUpDown, ChevronRight } from 'lucide-react';\nimport { GlassCard } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\nexport interface Column<T> {\n key: string;\n header: ReactNode;\n render: (row: T) => ReactNode;\n align?: 'left' | 'right' | 'center';\n className?: string;\n /** Hide below the `md` breakpoint for a mobile-friendly layout. */\n hideOnMobile?: boolean;\n /** Provide to make this column click-sortable (returns a comparable value). */\n sortValue?: (row: T) => string | number;\n}\n\ninterface DataTableProps<T> {\n columns: Column<T>[];\n rows: T[];\n rowKey: (row: T) => string;\n onRowClick?: (row: T) => void;\n /** Accessible label for a clickable row (e.g. `(a) => `Open ${a.name}``). */\n rowLabel?: (row: T) => string;\n className?: string;\n /** Default sort: a column key + direction. */\n defaultSort?: { key: string; dir: 'asc' | 'desc' };\n}\n\n/** Enter/Space activate — only when the event originates on the element itself\n * (not on an interactive descendant like a Select or Button inside a cell). */\nconst activateOnKey = (e: KeyboardEvent, fn: () => void) => {\n if (e.target !== e.currentTarget) return;\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n fn();\n }\n};\n\nconst alignClass = {\n left: 'text-left',\n right: 'text-right',\n center: 'text-center',\n} as const;\n\ntype Sort = { key: string; dir: 'asc' | 'desc' };\n\nexport function DataTable<T>({\n columns,\n rows,\n rowKey,\n onRowClick,\n rowLabel,\n className,\n defaultSort,\n}: DataTableProps<T>) {\n const [sort, setSort] = useState<Sort | null>(defaultSort ?? null);\n const sortSelectId = useId();\n\n const sortedRows = useMemo(() => {\n if (!sort) return rows;\n const col = columns.find((c) => c.key === sort.key);\n if (!col?.sortValue) return rows;\n const dir = sort.dir === 'asc' ? 1 : -1;\n return [...rows].sort((a, b) => {\n const va = col.sortValue!(a);\n const vb = col.sortValue!(b);\n if (va < vb) return -1 * dir;\n if (va > vb) return 1 * dir;\n return 0;\n });\n }, [rows, sort, columns]);\n\n const toggleSort = (key: string) => {\n setSort((prev) =>\n prev?.key === key ? { key, dir: prev.dir === 'asc' ? 'desc' : 'asc' } : { key, dir: 'asc' }\n );\n };\n\n const flipDir = () =>\n setSort((prev) => (prev ? { key: prev.key, dir: prev.dir === 'asc' ? 'desc' : 'asc' } : prev));\n\n const sortableColumns = useMemo(() => columns.filter((c) => c.sortValue), [columns]);\n\n const rowInteractive = (row: T) =>\n onRowClick\n ? {\n role: 'button' as const,\n tabIndex: 0,\n 'aria-label': rowLabel?.(row),\n onClick: () => onRowClick(row),\n onKeyDown: (e: KeyboardEvent) => activateOnKey(e, () => onRowClick(row)),\n }\n : {};\n\n const [headCol, ...restCols] = columns;\n\n return (\n <div className={className}>\n {/* ── md and up: full table ─────────────────────────────────────── */}\n <GlassCard treatment=\"plain\" className=\"hidden overflow-hidden md:block\">\n <div className=\"overflow-x-auto\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"border-b border-border-seam\">\n {columns.map((col) => {\n const sortable = Boolean(col.sortValue);\n const active = sort?.key === col.key;\n return (\n <th\n key={col.key}\n scope=\"col\"\n role={sortable ? 'button' : undefined}\n tabIndex={sortable ? 0 : undefined}\n onClick={sortable ? () => toggleSort(col.key) : undefined}\n onKeyDown={\n sortable ? (e) => activateOnKey(e, () => toggleSort(col.key)) : undefined\n }\n aria-sort={\n active ? (sort?.dir === 'asc' ? 'ascending' : 'descending') : undefined\n }\n className={cn(\n 'px-4 py-3 font-medium text-text-secondary whitespace-nowrap',\n alignClass[col.align ?? 'left'],\n col.hideOnMobile && 'hidden md:table-cell',\n sortable &&\n 'cursor-pointer select-none hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]'\n )}\n >\n <span\n className={cn(\n 'inline-flex items-center gap-1',\n col.align === 'right' && 'flex-row-reverse'\n )}\n >\n {col.header}\n {sortable &&\n (active ? (\n sort?.dir === 'asc' ? (\n <ChevronUp className=\"h-3.5 w-3.5 text-accent\" />\n ) : (\n <ChevronDown className=\"h-3.5 w-3.5 text-accent\" />\n )\n ) : (\n <ChevronsUpDown className=\"h-3.5 w-3.5 opacity-40\" />\n ))}\n </span>\n </th>\n );\n })}\n </tr>\n </thead>\n <tbody>\n {sortedRows.map((row) => (\n <tr\n key={rowKey(row)}\n {...rowInteractive(row)}\n className={cn(\n 'group border-b border-border-seam/60 last:border-0',\n onRowClick &&\n 'cursor-pointer transition-colors hover:bg-bg-sunken/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-[var(--color-focus-ring)]'\n )}\n >\n {columns.map((col) => (\n <td\n key={col.key}\n className={cn(\n 'px-4 py-3 text-text-primary align-middle',\n alignClass[col.align ?? 'left'],\n col.hideOnMobile && 'hidden md:table-cell',\n col.className\n )}\n >\n {col.render(row)}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </GlassCard>\n\n {/* ── below md: stacked cards ───────────────────────────────────── */}\n <div className=\"space-y-2.5 md:hidden\">\n {sortableColumns.length > 0 && (\n <div className=\"flex items-center justify-end gap-1.5 px-0.5\">\n <label htmlFor={sortSelectId} className=\"text-xs text-text-tertiary\">\n Sort\n </label>\n <select\n id={sortSelectId}\n value={sort?.key ?? ''}\n onChange={(e) =>\n setSort(\n e.target.value ? { key: e.target.value, dir: sort?.dir ?? 'asc' } : null\n )\n }\n className=\"rounded-md border border-border-subtle bg-bg-surface px-2 py-1 text-xs text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n <option value=\"\">Default order</option>\n {sortableColumns.map((col) => (\n <option key={col.key} value={col.key}>\n {typeof col.header === 'string' ? col.header : col.key}\n </option>\n ))}\n </select>\n {sort && (\n <button\n type=\"button\"\n onClick={flipDir}\n aria-label={sort.dir === 'asc' ? 'Sort ascending' : 'Sort descending'}\n className=\"inline-flex h-7 w-7 items-center justify-center rounded-md border border-border-subtle bg-bg-surface text-text-secondary transition-colors hover:text-text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]\"\n >\n {sort.dir === 'asc' ? (\n <ChevronUp className=\"h-4 w-4\" />\n ) : (\n <ChevronDown className=\"h-4 w-4\" />\n )}\n </button>\n )}\n </div>\n )}\n\n {sortedRows.map((row) => (\n <div\n key={rowKey(row)}\n {...rowInteractive(row)}\n className={cn(\n 'rounded-xl border border-border-subtle bg-bg-surface p-4',\n onRowClick &&\n 'cursor-pointer transition-colors hover:bg-bg-sunken/40 active:bg-bg-sunken/60 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)]'\n )}\n >\n {headCol && (\n <div className=\"flex items-start justify-between gap-3\">\n <div className=\"min-w-0 flex-1\">{headCol.render(row)}</div>\n {onRowClick && (\n <ChevronRight\n className=\"mt-0.5 h-4 w-4 shrink-0 text-text-tertiary\"\n aria-hidden\n />\n )}\n </div>\n )}\n {restCols.length > 0 && (\n <dl className=\"mt-3 grid grid-cols-2 gap-x-4 gap-y-2.5 border-t border-border-subtle/70 pt-3\">\n {restCols.map((col) => (\n <div key={col.key} className=\"min-w-0\">\n <dt className=\"text-[11px] uppercase tracking-wide text-text-tertiary\">\n {col.header}\n </dt>\n <dd className=\"mt-0.5 text-sm text-text-primary break-words\">\n {col.render(row)}\n </dd>\n </div>\n ))}\n </dl>\n )}\n </div>\n ))}\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;AAiDA,IAAM,KAAiB,GAAkB,MAAmB;AACtD,GAAE,WAAW,EAAE,kBACf,EAAE,QAAQ,WAAW,EAAE,QAAQ,SACjC,EAAE,gBAAgB,EAClB,GAAI;GAIF,IAAa;CACjB,MAAM;CACN,OAAO;CACP,QAAQ;CACT;AAID,SAAgB,EAAa,EAC3B,YACA,SACA,WACA,eACA,aACA,cACA,kBACoB;CACpB,IAAM,CAAC,GAAM,KAAW,EAAsB,KAAe,KAAK,EAC5D,IAAe,GAAO,EAEtB,IAAa,QAAc;AAC/B,MAAI,CAAC,EAAM,QAAO;EAClB,IAAM,IAAM,EAAQ,MAAM,MAAM,EAAE,QAAQ,EAAK,IAAI;AACnD,MAAI,CAAC,GAAK,UAAW,QAAO;EAC5B,IAAM,IAAM,EAAK,QAAQ,QAAQ,IAAI;AACrC,SAAO,CAAC,GAAG,EAAK,CAAC,MAAM,GAAG,MAAM;GAC9B,IAAM,IAAK,EAAI,UAAW,EAAE,EACtB,IAAK,EAAI,UAAW,EAAE;AAG5B,UAFI,IAAK,IAAW,KAAK,IACrB,IAAK,IAAW,IAAI,IACjB;IACP;IACD;EAAC;EAAM;EAAM;EAAQ,CAAC,EAEnB,KAAc,MAAgB;AAClC,KAAS,MACP,GAAM,QAAQ,IAAM;GAAE;GAAK,KAAK,EAAK,QAAQ,QAAQ,SAAS;GAAO,GAAG;GAAE;GAAK,KAAK;GAAO,CAC5F;IAGG,UACJ,GAAS,MAAU,KAAO;EAAE,KAAK,EAAK;EAAK,KAAK,EAAK,QAAQ,QAAQ,SAAS;EAAO,CAAS,EAE1F,IAAkB,QAAc,EAAQ,QAAQ,MAAM,EAAE,UAAU,EAAE,CAAC,EAAQ,CAAC,EAE9E,KAAkB,MACtB,IACI;EACE,MAAM;EACN,UAAU;EACV,cAAc,IAAW,EAAI;EAC7B,eAAe,EAAW,EAAI;EAC9B,YAAY,MAAqB,EAAc,SAAS,EAAW,EAAI,CAAC;EACzE,GACD,EAAE,EAEF,CAAC,GAAS,GAAG,KAAY;AAE/B,QACE,kBAAC,OAAD;EAAgB;YAAhB,CAEE,kBAAC,GAAD;GAAW,WAAU;GAAQ,WAAU;aACrC,kBAAC,OAAD;IAAK,WAAU;cACb,kBAAC,SAAD;KAAO,WAAU;eAAjB,CACE,kBAAC,SAAD,EAAA,UACE,kBAAC,MAAD;MAAI,WAAU;gBACX,EAAQ,KAAK,MAAQ;OACpB,IAAM,IAAW,EAAQ,EAAI,WACvB,IAAS,GAAM,QAAQ,EAAI;AACjC,cACE,kBAAC,MAAD;QAEE,OAAM;QACN,MAAM,IAAW,WAAW,KAAA;QAC5B,UAAU,IAAW,IAAI,KAAA;QACzB,SAAS,UAAiB,EAAW,EAAI,IAAI,GAAG,KAAA;QAChD,WACE,KAAY,MAAM,EAAc,SAAS,EAAW,EAAI,IAAI,CAAC,GAAG,KAAA;QAElE,aACE,IAAU,GAAM,QAAQ,QAAQ,cAAc,eAAgB,KAAA;QAEhE,WAAW,EACT,+DACA,EAAW,EAAI,SAAS,SACxB,EAAI,gBAAgB,wBACpB,KACE,kJACH;kBAED,kBAAC,QAAD;SACE,WAAW,EACT,kCACA,EAAI,UAAU,WAAW,mBAC1B;mBAJH,CAMG,EAAI,QACJ,MACE,IACC,GAAM,QAAQ,QACZ,kBAAC,GAAD,EAAW,WAAU,2BAA4B,CAAA,GAEjD,kBAAC,GAAD,EAAa,WAAU,2BAA4B,CAAA,GAGrD,kBAAC,GAAD,EAAgB,WAAU,0BAA2B,CAAA,EAEpD;;QACJ,EArCE,EAAI,IAqCN;QAEP;MACC,CAAA,EACC,CAAA,EACR,kBAAC,SAAD,EAAA,UACG,EAAW,KAAK,MACf,kBAAC,MAAD;MAEE,GAAI,EAAe,EAAI;MACvB,WAAW,EACT,sDACA,KACE,+KACH;gBAEA,EAAQ,KAAK,MACZ,kBAAC,MAAD;OAEE,WAAW,EACT,4CACA,EAAW,EAAI,SAAS,SACxB,EAAI,gBAAgB,wBACpB,EAAI,UACL;iBAEA,EAAI,OAAO,EAAI;OACb,EATE,EAAI,IASN,CACL;MACC,EArBE,EAAO,EAAI,CAqBb,CACL,EACI,CAAA,CACF;;IACJ,CAAA;GACI,CAAA,EAGZ,kBAAC,OAAD;GAAK,WAAU;aAAf,CACG,EAAgB,SAAS,KACxB,kBAAC,OAAD;IAAK,WAAU;cAAf;KACE,kBAAC,SAAD;MAAO,SAAS;MAAc,WAAU;gBAA6B;MAE7D,CAAA;KACR,kBAAC,UAAD;MACE,IAAI;MACJ,OAAO,GAAM,OAAO;MACpB,WAAW,MACT,EACE,EAAE,OAAO,QAAQ;OAAE,KAAK,EAAE,OAAO;OAAO,KAAK,GAAM,OAAO;OAAO,GAAG,KACrE;MAEH,WAAU;gBARZ,CAUE,kBAAC,UAAD;OAAQ,OAAM;iBAAG;OAAsB,CAAA,EACtC,EAAgB,KAAK,MACpB,kBAAC,UAAD;OAAsB,OAAO,EAAI;iBAC9B,OAAO,EAAI,UAAW,WAAW,EAAI,SAAS,EAAI;OAC5C,EAFI,EAAI,IAER,CACT,CACK;;KACR,KACC,kBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,cAAY,EAAK,QAAQ,QAAQ,mBAAmB;MACpD,WAAU;gBAET,EAAK,QAAQ,QACZ,kBAAC,GAAD,EAAW,WAAU,WAAY,CAAA,GAEjC,kBAAC,GAAD,EAAa,WAAU,WAAY,CAAA;MAE9B,CAAA;KAEP;OAGP,EAAW,KAAK,MACf,kBAAC,OAAD;IAEE,GAAI,EAAe,EAAI;IACvB,WAAW,EACT,4DACA,KACE,6KACH;cAPH,CASG,KACC,kBAAC,OAAD;KAAK,WAAU;eAAf,CACE,kBAAC,OAAD;MAAK,WAAU;gBAAkB,EAAQ,OAAO,EAAI;MAAO,CAAA,EAC1D,KACC,kBAAC,GAAD;MACE,WAAU;MACV,eAAA;MACA,CAAA,CAEA;QAEP,EAAS,SAAS,KACjB,kBAAC,MAAD;KAAI,WAAU;eACX,EAAS,KAAK,MACb,kBAAC,OAAD;MAAmB,WAAU;gBAA7B,CACE,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAI;OACF,CAAA,EACL,kBAAC,MAAD;OAAI,WAAU;iBACX,EAAI,OAAO,EAAI;OACb,CAAA,CACD;QAPI,EAAI,IAOR,CACN;KACC,CAAA,CAEH;MAjCC,EAAO,EAAI,CAiCZ,CACN,CACE;KACF"}
|
|
@@ -9,18 +9,18 @@ var i = ({ icon: i, illustration: a, title: o, description: s, action: c, classN
|
|
|
9
9
|
action: c,
|
|
10
10
|
className: l
|
|
11
11
|
}) : /* @__PURE__ */ n("div", {
|
|
12
|
-
className: e("flex flex-col items-center justify-center
|
|
12
|
+
className: e("flex flex-col items-center justify-center px-4 py-14 text-center", l),
|
|
13
13
|
children: [
|
|
14
14
|
i && /* @__PURE__ */ t("div", {
|
|
15
|
-
className: "mb-
|
|
15
|
+
className: "mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-bg-sunken text-text-tertiary ring-1 ring-border-subtle",
|
|
16
16
|
children: i
|
|
17
17
|
}),
|
|
18
18
|
/* @__PURE__ */ t("h3", {
|
|
19
|
-
className: "text-lg font-
|
|
19
|
+
className: "text-lg font-semibold text-text-primary",
|
|
20
20
|
children: o
|
|
21
21
|
}),
|
|
22
22
|
s && /* @__PURE__ */ t("p", {
|
|
23
|
-
className: "mt-2 text-sm text-text-secondary
|
|
23
|
+
className: "mt-2 max-w-sm text-sm leading-relaxed text-text-secondary",
|
|
24
24
|
children: s
|
|
25
25
|
}),
|
|
26
26
|
c && /* @__PURE__ */ t("div", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/theglobalfuel/components/EmptyState.tsx"],"sourcesContent":["/**\n * Empty State Component\n * @module theglobalfuel/components\n *\n * Boff UI 2.0 zero-state. When an `illustration` name is provided it renders the\n * fe-libs {@link IllustratedEmptyState} (on-brand glass illustration); otherwise\n * it falls back to the icon-based layout.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface EmptyStateProps {\n icon?: ReactNode;\n /**\n * On-brand illustration name → `/illustrations/<name>.webp`. Standard names:\n * empty-data, empty-search, empty-files, empty-people, empty-notifications,\n * onboarding, empty-generic.\n */\n illustration?: string;\n title: string;\n description?: string;\n action?: ReactNode;\n className?: string;\n}\n\nexport const EmptyState: FC<EmptyStateProps> = ({\n icon,\n illustration,\n title,\n description,\n action,\n className,\n}) => {\n if (illustration) {\n return (\n <IllustratedEmptyState\n illustration={illustration}\n title={title}\n description={description}\n action={action}\n className={className}\n />\n );\n }\n\n return (\n <div\n className={cn('flex flex-col items-center justify-center
|
|
1
|
+
{"version":3,"file":"EmptyState.js","names":[],"sources":["../../../src/theglobalfuel/components/EmptyState.tsx"],"sourcesContent":["/**\n * Empty State Component\n * @module theglobalfuel/components\n *\n * Boff UI 2.0 zero-state. When an `illustration` name is provided it renders the\n * fe-libs {@link IllustratedEmptyState} (on-brand glass illustration); otherwise\n * it falls back to the icon-based layout.\n */\n\nimport type { FC, ReactNode } from 'react';\nimport { IllustratedEmptyState } from '@burdenoff/fe-libs/ui';\nimport { cn } from '../utils/cn';\n\ninterface EmptyStateProps {\n icon?: ReactNode;\n /**\n * On-brand illustration name → `/illustrations/<name>.webp`. Standard names:\n * empty-data, empty-search, empty-files, empty-people, empty-notifications,\n * onboarding, empty-generic.\n */\n illustration?: string;\n title: string;\n description?: string;\n action?: ReactNode;\n className?: string;\n}\n\nexport const EmptyState: FC<EmptyStateProps> = ({\n icon,\n illustration,\n title,\n description,\n action,\n className,\n}) => {\n if (illustration) {\n return (\n <IllustratedEmptyState\n illustration={illustration}\n title={title}\n description={description}\n action={action}\n className={className}\n />\n );\n }\n\n return (\n <div\n className={cn('flex flex-col items-center justify-center px-4 py-14 text-center', className)}\n >\n {icon && (\n <div className=\"mb-5 flex h-16 w-16 items-center justify-center rounded-full bg-bg-sunken text-text-tertiary ring-1 ring-border-subtle\">\n {icon}\n </div>\n )}\n <h3 className=\"text-lg font-semibold text-text-primary\">{title}</h3>\n {description && (\n <p className=\"mt-2 max-w-sm text-sm leading-relaxed text-text-secondary\">{description}</p>\n )}\n {action && <div className=\"mt-6\">{action}</div>}\n </div>\n );\n};\n"],"mappings":";;;;AA2BA,IAAa,KAAmC,EAC9C,SACA,iBACA,UACA,gBACA,WACA,mBAEI,IAEA,kBAAC,GAAD;CACgB;CACP;CACM;CACL;CACG;CACX,CAAA,GAKJ,kBAAC,OAAD;CACE,WAAW,EAAG,oEAAoE,EAAU;WAD9F;EAGG,KACC,kBAAC,OAAD;GAAK,WAAU;aACZ;GACG,CAAA;EAER,kBAAC,MAAD;GAAI,WAAU;aAA2C;GAAW,CAAA;EACnE,KACC,kBAAC,KAAD;GAAG,WAAU;aAA6D;GAAgB,CAAA;EAE3F,KAAU,kBAAC,OAAD;GAAK,WAAU;aAAQ;GAAa,CAAA;EAC3C"}
|