@sybilion/uilib 1.2.26 → 1.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/dist/esm/components/ui/Chart/Chart.js +5 -0
- package/dist/esm/components/ui/Chart/components/BaseChartWrapper.js +7 -32
- package/dist/esm/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.js +21 -0
- package/dist/esm/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.styl.js +7 -0
- package/dist/esm/components/ui/Chart/lightweight/LightweightForecastChart.js +460 -0
- package/dist/esm/components/ui/Chart/lightweight/LightweightForecastChart.styl.js +7 -0
- package/dist/esm/components/ui/Chart/lightweight/chartTime.js +16 -0
- package/dist/esm/components/ui/Chart/lightweight/lightweightForecastChart.helpers.js +114 -0
- package/dist/esm/components/ui/Chart/lightweight/quantileBandCustomSeries.js +147 -0
- package/dist/esm/components/ui/Chart/quantileBandConeChartData.js +131 -0
- package/dist/esm/components/ui/Chart/tools/chartPlotGeometry.js +65 -0
- package/dist/esm/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.js +37 -1
- package/dist/esm/components/ui/ChartAreaInteractive/ChartAreaInteractive.js +5 -2
- package/dist/esm/components/ui/ChartAreaInteractive/TimeRangeBrushLayer.js +205 -0
- package/dist/esm/components/ui/ChartAreaInteractive/TimeRangeBrushLayer.styl.js +7 -0
- package/dist/esm/components/ui/ChartAreaInteractive/TimeRangeBrushLayout.helpers.js +37 -0
- package/dist/esm/components/ui/ChartAreaInteractive/overlays/IntervalsOverlay/IntervalsOverlay.hooks.js +1 -0
- package/dist/esm/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.js +7 -60
- package/dist/esm/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.styl.js +2 -2
- package/dist/esm/components/ui/ChartAreaInteractive/overlays/ThresholdsOverlay/ThresholdsOverlay.hooks.js +1 -0
- package/dist/esm/components/ui/ChartAreaInteractive/overlays/useChartYRange.js +2 -4
- package/dist/esm/components/ui/ChartAreaInteractive/overlays/useQuantileBands.js +4 -102
- package/dist/esm/components/ui/TimeRangeControls/TimeRangeControls.js +7 -2
- package/dist/esm/components/ui/WorldMap/WorldMap.js +11 -0
- package/dist/esm/components/ui/WorldMap/WorldMap.styl.js +7 -0
- package/dist/esm/components/widgets/DriverCard/DriverCard.js +89 -0
- package/dist/esm/components/widgets/DriverCard/DriverCard.styl.js +7 -0
- package/dist/esm/components/widgets/DriverCard/DriverPerformanceChart.js +83 -0
- package/dist/esm/components/widgets/DriverCard/DriverPerformanceChart.styl.js +7 -0
- package/dist/esm/components/widgets/DriverCard/driverPerformanceChartData.js +50 -0
- package/dist/esm/components/widgets/DriverMap/DriverMap.js +2 -2
- package/dist/esm/components/widgets/DriverMap/DriverMap.styl.js +2 -2
- package/dist/esm/index.js +4 -2
- package/dist/esm/types/src/components/ui/Chart/Chart.d.ts +2 -0
- package/dist/esm/types/src/components/ui/Chart/components/BaseChartWrapper.d.ts +2 -1
- package/dist/esm/types/src/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.d.ts +14 -0
- package/dist/esm/types/src/components/ui/Chart/lightweight/LightweightForecastChart.d.ts +26 -0
- package/dist/esm/types/src/components/ui/Chart/lightweight/chartTime.d.ts +5 -0
- package/dist/esm/types/src/components/ui/Chart/lightweight/lightweightForecastChart.helpers.d.ts +13 -0
- package/dist/esm/types/src/components/ui/Chart/lightweight/quantileBandCustomSeries.d.ts +24 -0
- package/dist/esm/types/src/components/ui/Chart/quantileBandConeChartData.d.ts +7 -0
- package/dist/esm/types/src/components/ui/Chart/tools/chartPlotGeometry.d.ts +30 -0
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.d.ts +1 -1
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.d.ts +11 -2
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.types.d.ts +2 -2
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/TimeRangeBrushLayer.d.ts +15 -0
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/TimeRangeBrushLayout.helpers.d.ts +14 -0
- package/dist/esm/types/src/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Page/PageColumns/PageColumns.d.ts +1 -1
- package/dist/esm/types/src/components/ui/TimeRangeControls/TimeRangeControls.d.ts +5 -7
- package/dist/esm/types/src/components/ui/WorldMap/WorldMap.d.ts +4 -0
- package/dist/esm/types/src/components/ui/WorldMap/index.d.ts +2 -0
- package/dist/esm/types/src/components/widgets/DriverCard/DriverCard.d.ts +9 -0
- package/dist/esm/types/src/components/widgets/DriverCard/DriverPerformanceChart.d.ts +5 -0
- package/dist/esm/types/src/components/widgets/DriverCard/driverPerformanceChartData.d.ts +7 -0
- package/dist/esm/types/src/components/widgets/DriverCard/index.d.ts +1 -0
- package/dist/esm/types/src/components/widgets/DriverMap/index.d.ts +0 -2
- package/dist/esm/types/src/docs/pages/LightweightChartPage.d.ts +1 -0
- package/dist/esm/types/src/docs/pages/PageColumnsPage.d.ts +1 -0
- package/dist/esm/types/src/docs/pages/WorldMapPage.d.ts +1 -0
- package/dist/esm/types/src/index.d.ts +2 -0
- package/package.json +3 -2
- package/src/components/ui/Chart/Chart.tsx +9 -0
- package/src/components/ui/Chart/components/BaseChartWrapper.tsx +8 -41
- package/src/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.styl +60 -0
- package/src/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.styl.d.ts +15 -0
- package/src/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.tsx +66 -0
- package/src/components/ui/Chart/lightweight/LightweightForecastChart.styl +25 -0
- package/src/components/ui/Chart/lightweight/LightweightForecastChart.styl.d.ts +11 -0
- package/src/components/ui/Chart/lightweight/LightweightForecastChart.tsx +721 -0
- package/src/components/ui/Chart/lightweight/chartTime.ts +18 -0
- package/src/components/ui/Chart/lightweight/lightweightForecastChart.helpers.ts +141 -0
- package/src/components/ui/Chart/lightweight/quantileBandCustomSeries.ts +215 -0
- package/src/components/ui/Chart/quantileBandConeChartData.ts +171 -0
- package/src/components/ui/Chart/tools/chartPlotGeometry.ts +89 -0
- package/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.ts +44 -2
- package/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.tsx +14 -1
- package/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.types.ts +2 -3
- package/src/components/ui/ChartAreaInteractive/TimeRangeBrushLayer.styl +21 -0
- package/src/components/{widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl.d.ts → ui/ChartAreaInteractive/TimeRangeBrushLayer.styl.d.ts} +3 -3
- package/src/components/ui/ChartAreaInteractive/TimeRangeBrushLayer.tsx +285 -0
- package/src/components/ui/ChartAreaInteractive/TimeRangeBrushLayout.helpers.ts +55 -0
- package/src/components/ui/ChartAreaInteractive/overlays/IntervalsOverlay/IntervalsOverlay.hooks.ts +1 -0
- package/src/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.styl +2 -7
- package/src/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.styl.d.ts +0 -1
- package/src/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.tsx +7 -71
- package/src/components/ui/ChartAreaInteractive/overlays/ThresholdsOverlay/ThresholdsOverlay.hooks.ts +1 -0
- package/src/components/ui/ChartAreaInteractive/overlays/useChartYRange.ts +2 -3
- package/src/components/ui/ChartAreaInteractive/overlays/useQuantileBands.ts +5 -131
- package/src/components/ui/Page/PageColumns/PageColumns.tsx +1 -1
- package/src/components/ui/TimeRangeControls/TimeRangeControls.tsx +16 -17
- package/src/components/{widgets/DriverMap/MapBackground/MapBackground.styl → ui/WorldMap/WorldMap.styl} +1 -3
- package/src/components/{widgets/DriverMap/MapBackground/MapBackground.styl.d.ts → ui/WorldMap/WorldMap.styl.d.ts} +1 -1
- package/src/components/ui/WorldMap/WorldMap.tsx +22 -0
- package/src/components/ui/WorldMap/index.ts +2 -0
- package/src/components/widgets/DriverCard/DriverCard.styl +169 -0
- package/src/components/widgets/DriverCard/DriverCard.styl.d.ts +40 -0
- package/src/components/widgets/DriverCard/DriverCard.tsx +219 -0
- package/src/components/widgets/DriverCard/DriverPerformanceChart.styl +43 -0
- package/src/components/widgets/DriverCard/DriverPerformanceChart.styl.d.ts +13 -0
- package/src/components/widgets/DriverCard/DriverPerformanceChart.tsx +150 -0
- package/src/components/widgets/DriverCard/driverPerformanceChartData.ts +64 -0
- package/src/components/widgets/DriverCard/index.ts +1 -0
- package/src/components/widgets/DriverMap/DriverIcon/DriverIcon.tsx +0 -2
- package/src/components/widgets/DriverMap/DriverMap.styl +6 -1
- package/src/components/widgets/DriverMap/DriverMap.styl.d.ts +1 -0
- package/src/components/widgets/DriverMap/DriverMap.tsx +2 -4
- package/src/components/widgets/DriverMap/driverCategoryIcon.tsx +0 -2
- package/src/components/widgets/DriverMap/index.ts +0 -2
- package/src/declarations.d.ts +2 -0
- package/src/docs/config/webpack.config.js +26 -3
- package/src/docs/index.tsx +1 -1
- package/src/docs/pages/ChartAreaInteractivePage.tsx +2 -3
- package/src/docs/pages/DriverMapPage.tsx +214 -60
- package/src/docs/pages/LightweightChartPage.styl +18 -0
- package/src/docs/pages/LightweightChartPage.styl.d.ts +10 -0
- package/src/docs/pages/LightweightChartPage.tsx +195 -0
- package/src/docs/pages/PageColumnsPage.tsx +92 -0
- package/src/docs/pages/TimeRangeControlsPage.tsx +2 -3
- package/src/docs/pages/WorldMapPage.styl +14 -0
- package/src/docs/pages/WorldMapPage.styl.d.ts +8 -0
- package/src/docs/pages/WorldMapPage.tsx +26 -0
- package/src/docs/registry.ts +19 -1
- package/src/index.ts +2 -0
- package/dist/esm/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.js +0 -8
- package/dist/esm/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl.js +0 -7
- package/dist/esm/components/widgets/DriverMap/MapBackground/MapBackground.js +0 -10
- package/dist/esm/components/widgets/DriverMap/MapBackground/MapBackground.styl.js +0 -7
- package/dist/esm/types/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.d.ts +0 -1
- package/dist/esm/types/src/components/widgets/DriverMap/MapBackground/MapBackground.d.ts +0 -1
- package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.styl +0 -24
- package/src/components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.tsx +0 -11
- package/src/components/widgets/DriverMap/MapBackground/MapBackground.tsx +0 -18
- /package/dist/esm/components/{widgets/DriverMap/MapBackground → ui/WorldMap}/map.svg.js +0 -0
- /package/src/components/{widgets/DriverMap/MapBackground → ui/WorldMap}/map.svg +0 -0
- /package/src/components/{widgets/DriverMap/MapBackground → ui/WorldMap}/mapAspect.mixin.styl +0 -0
- /package/src/components/{widgets/DriverMap/MapBackground → ui/WorldMap}/mapAspect.mixin.styl.d.ts +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
2
|
+
import React__default, { useMemo } from 'react';
|
|
3
|
+
import { CoffeeIcon, TrendUpIcon, TrendDownIcon } from '@phosphor-icons/react';
|
|
4
|
+
import { Badge } from '../../ui/Badge/Badge.js';
|
|
5
|
+
import { Card, CardContent } from '../../ui/Card/Card.js';
|
|
6
|
+
import { LabelWithId } from '../../ui/LabelWithId/LabelWithId.js';
|
|
7
|
+
import { Skeleton } from '../../ui/Skeleton/Skeleton.js';
|
|
8
|
+
import { Tooltip, TooltipTrigger, TooltipContent } from '../../ui/Tooltip/Tooltip.js';
|
|
9
|
+
import { getCategoryIcon } from '../DriverMap/driverCategoryIcon.js';
|
|
10
|
+
import S from './DriverCard.styl.js';
|
|
11
|
+
import { DriverPerformanceChart } from './DriverPerformanceChart.js';
|
|
12
|
+
|
|
13
|
+
function DriverCard({ selectedDriver, isLoading, inQueue = false, driverSelector, }) {
|
|
14
|
+
const importanceDisplay = useMemo(() => {
|
|
15
|
+
if (!selectedDriver)
|
|
16
|
+
return '';
|
|
17
|
+
let importance = 0;
|
|
18
|
+
if (selectedDriver.rawImportance &&
|
|
19
|
+
typeof selectedDriver.rawImportance === 'object') {
|
|
20
|
+
const importanceObj = selectedDriver.rawImportance;
|
|
21
|
+
if (importanceObj.overall && typeof importanceObj.overall === 'object') {
|
|
22
|
+
const overall = importanceObj.overall;
|
|
23
|
+
if (typeof overall.mean === 'number') {
|
|
24
|
+
importance = Math.round(overall.mean);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return importance > 0
|
|
29
|
+
? `${importance}%`
|
|
30
|
+
: `${selectedDriver.importance.toFixed(1)}%`;
|
|
31
|
+
}, [selectedDriver]);
|
|
32
|
+
const regionDisplay = React__default.useMemo(() => {
|
|
33
|
+
if (!selectedDriver)
|
|
34
|
+
return '';
|
|
35
|
+
// Check for src_region and tgt_region properties first
|
|
36
|
+
const driver = selectedDriver;
|
|
37
|
+
const srcRegion = driver.src_region;
|
|
38
|
+
const tgtRegion = driver.tgt_region;
|
|
39
|
+
const srcName = srcRegion?.name;
|
|
40
|
+
const tgtName = tgtRegion?.name;
|
|
41
|
+
// If both src_region and tgt_region have valid names
|
|
42
|
+
if (srcName && tgtName) {
|
|
43
|
+
// If source and target are the same, just show one
|
|
44
|
+
if (srcName === tgtName) {
|
|
45
|
+
return srcName;
|
|
46
|
+
}
|
|
47
|
+
return `${srcName} → ${tgtName}`;
|
|
48
|
+
}
|
|
49
|
+
// If only src_region has a valid name
|
|
50
|
+
if (srcName) {
|
|
51
|
+
if (srcName === 'World') {
|
|
52
|
+
return 'World';
|
|
53
|
+
}
|
|
54
|
+
return `${srcName} → World`;
|
|
55
|
+
}
|
|
56
|
+
// If only tgt_region has a valid name
|
|
57
|
+
if (tgtName) {
|
|
58
|
+
if (tgtName === 'World') {
|
|
59
|
+
return 'World';
|
|
60
|
+
}
|
|
61
|
+
return `World → ${tgtName}`;
|
|
62
|
+
}
|
|
63
|
+
if (selectedDriver.region.length === 1)
|
|
64
|
+
return selectedDriver.region[0];
|
|
65
|
+
if (selectedDriver.region.length > 1) {
|
|
66
|
+
return (selectedDriver.region
|
|
67
|
+
// .filter(region => region !== 'World')
|
|
68
|
+
.join(' → '));
|
|
69
|
+
}
|
|
70
|
+
// Fallback to "World" when no region information is available
|
|
71
|
+
return 'World';
|
|
72
|
+
}, [selectedDriver]);
|
|
73
|
+
if (inQueue) {
|
|
74
|
+
return (jsx(Card, { className: S.root, children: jsx(CardContent, { centered: true, fullHeight: true, noScroll: true, children: jsxs("div", { className: S.queueMessage, children: [jsx(CoffeeIcon, { size: 24, weight: "regular" }), jsxs("div", { children: [jsx("p", { children: "Retrieving drivers data." }), jsx("p", { children: "This may take a while." })] })] }) }) }));
|
|
75
|
+
}
|
|
76
|
+
if (isLoading) {
|
|
77
|
+
return (jsx(Card, { className: S.root, children: jsx(CardContent, { noScroll: true, children: jsxs("div", { className: S.skeletonContainer, children: [jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.w75}` }), jsx(Skeleton, { className: `${S.skeletonItem} ${S.hm} ${S.w50}` }), jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.w33}` }), jsxs("div", { className: S.skeletonGroup, children: [jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.wFull}` }), jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.w75}` }), jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.w50}` })] }), jsx(Skeleton, { className: `${S.skeletonItem} ${S.hl} ${S.wFull}` }), jsxs("div", { className: S.skeletonGroup, children: [jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.wFull}` }), jsx(Skeleton, { className: `${S.skeletonItem} ${S.hs} ${S.w75}` })] })] }) }) }));
|
|
78
|
+
}
|
|
79
|
+
if (!selectedDriver) {
|
|
80
|
+
return (jsx(Card, { className: S.root, children: jsx(CardContent, { centered: true, fullHeight: true, noScroll: true, children: jsx("span", { className: S.noDriverSelected, children: "No driver selected" }) }) }));
|
|
81
|
+
}
|
|
82
|
+
const { id, name, category, direction, lag, summary } = selectedDriver;
|
|
83
|
+
const directionText = direction > 0 ? 'Positive' : 'Negative';
|
|
84
|
+
const DirectionIcon = direction > 0 ? TrendUpIcon : TrendDownIcon;
|
|
85
|
+
const nameElem = (jsx("h4", { className: `${S.driverTitle} ${S.truncated}`, children: name }));
|
|
86
|
+
return (jsx(Card, { className: S.root, paddingSize: "l", children: jsx(CardContent, { noScroll: true, children: jsxs("div", { className: S.cardContent, children: [jsx("div", { className: S.driverHeader, children: jsxs("div", { className: S.headerContent, children: [jsxs("div", { className: S.topHeader, children: [jsxs("p", { className: S.categoryInfo, children: [jsx("span", { className: S.categoryIcon, children: getCategoryIcon(category) }), jsx("span", { className: S.categoryText, children: category })] }), driverSelector] }), name.length > 60 ? (jsxs(Tooltip, { children: [jsx(LabelWithId, { id: id, label: jsx(TooltipTrigger, { asChild: true, children: nameElem }) }), jsx(TooltipContent, { side: "left", className: S.tooltipContent, children: jsx("div", { className: S.tooltipTitle, children: name }) })] })) : (jsx(LabelWithId, { id: id, label: nameElem })), jsx("p", { className: S.regionDisplay, children: regionDisplay })] }) }), jsx("div", { className: S.metricsSection, children: jsx("div", { className: S.importanceScore, children: importanceDisplay }) }), jsxs("div", { className: S.directionLagSection, children: [jsxs(Badge, { variant: direction > 0 ? 'green' : 'red', className: S.directionBadge, children: [jsx(DirectionIcon, { className: S.trendIcon }), directionText, " correlation"] }), jsxs("span", { className: S.lagInfo, children: ["Lag: ", lag] })] }), jsx(DriverPerformanceChart, { driver: selectedDriver }), jsx("p", { className: S.description, children: summary ?? '' })] }) }) }));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export { DriverCard };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
|
|
3
|
+
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.DriverCard_root__Kr5Xz{height:auto;min-height:500px;width:100%}@media (min-width:640px){.DriverCard_root__Kr5Xz{min-height:25rem}}@media (min-width:768px){.DriverCard_root__Kr5Xz{min-height:31.25rem}}.DriverCard_cardContent__zB8UV{display:flex;flex-direction:column;gap:.5rem}.DriverCard_noDriverSelected__-mVm-{color:var(--muted-foreground)}.DriverCard_driverHeader__0aeJ-{align-items:flex-start;display:flex;flex-direction:column;gap:.75rem;padding-bottom:.25rem}.DriverCard_headerContent__YNqtK{display:flex;flex-direction:column;flex-grow:1;gap:.5rem;width:100%}.DriverCard_topHeader__sUDUc{align-items:center;display:flex;justify-content:space-between;margin-top:-12px;min-height:36px}.DriverCard_categoryInfo__8Dhqn{align-items:center;color:var(--muted-foreground);display:flex;font-size:.75rem;gap:.25rem}.DriverCard_categoryIcon__lSIM8{color:var(--muted-foreground);height:.75rem;width:.75rem}.DriverCard_categoryText__DuifF{display:-webkit-box;-webkit-line-clamp:1;-webkit-box-orient:vertical;overflow:hidden;text-transform:lowercase}.DriverCard_categoryText__DuifF:first-letter{text-transform:uppercase}.DriverCard_driverTitle__tYQO1{color:var(--foreground);font-size:1.1rem;font-weight:500;line-height:1.4;-webkit-user-select:text;-moz-user-select:text;user-select:text}.DriverCard_driverTitle__tYQO1.DriverCard_truncated__RIn6f{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;cursor:help;overflow:hidden}.DriverCard_regionDisplay__QYVWx{color:var(--muted-foreground);font-size:.75rem}.DriverCard_metricsSection__uZViQ{margin-bottom:.5rem;text-align:left}.DriverCard_importanceScore__RGh5Y{align-items:center;color:var(--foreground);display:flex;font-size:2.25rem;font-weight:400;height:auto;line-height:1;-webkit-user-select:text;-moz-user-select:text;user-select:text}.DriverCard_directionLagSection__Mh-ep{align-items:center;display:flex;justify-content:space-between}.DriverCard_directionBadge__7EAHe{align-items:center;display:flex;gap:.5rem}.DriverCard_trendIcon__GtkDe{height:.75rem;width:.75rem}.DriverCard_lagInfo__enbxl{color:var(--muted-foreground);font-size:.75rem}.DriverCard_description__fNR4e{font-size:.875rem;line-height:1.625;-webkit-user-select:text;-moz-user-select:text;user-select:text}.DriverCard_skeletonContainer__AE9MP{display:flex;flex-direction:column;gap:1rem}.DriverCard_skeletonGroup__lQXls{display:flex;flex-direction:column;gap:.5rem}.DriverCard_skeletonItem__pmx4S.DriverCard_hxs__taJow{height:.75rem}.DriverCard_skeletonItem__pmx4S.DriverCard_hs__PlDPB{height:1rem}.DriverCard_skeletonItem__pmx4S.DriverCard_hm__oFwUK{height:2rem}.DriverCard_skeletonItem__pmx4S.DriverCard_hl__McKZn{height:8rem}.DriverCard_skeletonItem__pmx4S.DriverCard_w33__cI-vq{width:33.333333%}.DriverCard_skeletonItem__pmx4S.DriverCard_w50__DcUSo{width:50%}.DriverCard_skeletonItem__pmx4S.DriverCard_w75__To5oR{width:75%}.DriverCard_skeletonItem__pmx4S.DriverCard_w80__y8wQl{width:80%}.DriverCard_skeletonItem__pmx4S.DriverCard_wFull__TnaxF{width:100%}.DriverCard_tooltipContent__F6DUH{font-size:.75rem;max-width:20rem}.DriverCard_tooltipTitle__NieWB{font-family:var(--font-family-body);font-weight:400}.DriverCard_queueMessage__4hQxI{align-items:center;color:var(--muted-foreground);display:flex;flex-direction:column;font-size:.875rem;gap:var(--p-4);line-height:1.5;padding:var(--p-8) var(--p-4);text-align:center}.DriverCard_queueMessage__4hQxI svg{color:var(--muted-foreground);flex-shrink:0;opacity:.8}";
|
|
4
|
+
var S = {"root":"DriverCard_root__Kr5Xz","cardContent":"DriverCard_cardContent__zB8UV","noDriverSelected":"DriverCard_noDriverSelected__-mVm-","driverHeader":"DriverCard_driverHeader__0aeJ-","headerContent":"DriverCard_headerContent__YNqtK","topHeader":"DriverCard_topHeader__sUDUc","categoryInfo":"DriverCard_categoryInfo__8Dhqn","categoryIcon":"DriverCard_categoryIcon__lSIM8","categoryText":"DriverCard_categoryText__DuifF","driverTitle":"DriverCard_driverTitle__tYQO1","truncated":"DriverCard_truncated__RIn6f","regionDisplay":"DriverCard_regionDisplay__QYVWx","metricsSection":"DriverCard_metricsSection__uZViQ","importanceScore":"DriverCard_importanceScore__RGh5Y","directionLagSection":"DriverCard_directionLagSection__Mh-ep","directionBadge":"DriverCard_directionBadge__7EAHe","trendIcon":"DriverCard_trendIcon__GtkDe","lagInfo":"DriverCard_lagInfo__enbxl","description":"DriverCard_description__fNR4e","skeletonContainer":"DriverCard_skeletonContainer__AE9MP","skeletonGroup":"DriverCard_skeletonGroup__lQXls","skeletonItem":"DriverCard_skeletonItem__pmx4S","hxs":"DriverCard_hxs__taJow","hs":"DriverCard_hs__PlDPB","hm":"DriverCard_hm__oFwUK","hl":"DriverCard_hl__McKZn","w33":"DriverCard_w33__cI-vq","w50":"DriverCard_w50__DcUSo","w75":"DriverCard_w75__To5oR","w80":"DriverCard_w80__y8wQl","wFull":"DriverCard_wFull__TnaxF","tooltipContent":"DriverCard_tooltipContent__F6DUH","tooltipTitle":"DriverCard_tooltipTitle__NieWB","queueMessage":"DriverCard_queueMessage__4hQxI"};
|
|
5
|
+
styleInject(css_248z);
|
|
6
|
+
|
|
7
|
+
export { S as default };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { useMemo } from 'react';
|
|
4
|
+
import { LineChart, CartesianGrid, XAxis, YAxis, Tooltip, Line } from 'recharts';
|
|
5
|
+
import '../../ui/Chart/components/BaseChartWrapper.js';
|
|
6
|
+
import { ChartContainer } from '../../ui/Chart/components/ChartContainer.js';
|
|
7
|
+
import '../../ui/Chart/Chart.context.js';
|
|
8
|
+
import '../../ui/Chart/Chart.styl.js';
|
|
9
|
+
import '../../ui/AnalysisLineIcon/AnalysisLineIcon.styl.js';
|
|
10
|
+
import '@radix-ui/react-slot';
|
|
11
|
+
import '../../ui/Badge/Badge.styl.js';
|
|
12
|
+
import '../../ui/LabelWithId/LabelWithId.styl.js';
|
|
13
|
+
import '@radix-ui/react-select';
|
|
14
|
+
import 'lucide-react';
|
|
15
|
+
import '../../ui/Select/Select.styl.js';
|
|
16
|
+
import '../../ui/TextShimmer/TextShimmer.js';
|
|
17
|
+
import '@phosphor-icons/react';
|
|
18
|
+
import '../../ui/AnalysesSelector/AnalysesSelector.styl.js';
|
|
19
|
+
import '../../ui/Chart/components/CustomChartLegend/CustomChartLegend.styl.js';
|
|
20
|
+
import '../../ui/ChartAreaInteractive/ChartLines.js';
|
|
21
|
+
import '../../ui/Skeleton/Skeleton.styl.js';
|
|
22
|
+
import 'lightweight-charts';
|
|
23
|
+
import '../../ui/Chart/lightweight/LightweightForecastChart.styl.js';
|
|
24
|
+
import { ChartEmptyState } from '../../ui/Chart/components/ChartEmptyState/ChartEmptyState.js';
|
|
25
|
+
import S from './DriverPerformanceChart.styl.js';
|
|
26
|
+
import { generateDriverChartData } from './driverPerformanceChartData.js';
|
|
27
|
+
|
|
28
|
+
const driverChartConfig = {
|
|
29
|
+
value: {
|
|
30
|
+
label: 'Performance',
|
|
31
|
+
color: 'var(--primary)',
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
function DriverPerformanceChart({ driver, }) {
|
|
35
|
+
const precision = useMemo(() => {
|
|
36
|
+
if (!driver.normalized_series)
|
|
37
|
+
return 7;
|
|
38
|
+
const values = Object.values(driver.normalized_series).filter((v) => typeof v === 'number' && v !== null);
|
|
39
|
+
if (values.length === 0)
|
|
40
|
+
return 7;
|
|
41
|
+
const absoluteValues = values.map(Math.abs).filter(v => v > 0);
|
|
42
|
+
if (absoluteValues.length === 0)
|
|
43
|
+
return 7;
|
|
44
|
+
const minAbs = Math.min(...absoluteValues);
|
|
45
|
+
if (minAbs < 0.0001)
|
|
46
|
+
return 7;
|
|
47
|
+
if (minAbs < 0.001)
|
|
48
|
+
return 6;
|
|
49
|
+
if (minAbs < 0.01)
|
|
50
|
+
return 5;
|
|
51
|
+
if (minAbs < 0.1)
|
|
52
|
+
return 4;
|
|
53
|
+
if (minAbs < 1)
|
|
54
|
+
return 3;
|
|
55
|
+
return 2;
|
|
56
|
+
}, [driver.normalized_series]);
|
|
57
|
+
const chartData = useMemo(() => generateDriverChartData(driver, precision), [driver, precision]);
|
|
58
|
+
const noSeriesData = useMemo(() => {
|
|
59
|
+
if (!driver.normalized_series)
|
|
60
|
+
return false;
|
|
61
|
+
return Object.values(driver.normalized_series).every(value => value === null);
|
|
62
|
+
}, [driver.normalized_series]);
|
|
63
|
+
const renderTooltipContent = ({ active, payload, }) => {
|
|
64
|
+
if (active && payload?.length) {
|
|
65
|
+
const dataPoint = payload[0];
|
|
66
|
+
const row = dataPoint?.payload;
|
|
67
|
+
const date = row?.date;
|
|
68
|
+
const value = dataPoint?.value;
|
|
69
|
+
return (jsxs("div", { className: S.chartTooltip, children: [jsx("div", { className: S.tooltipDate, children: date instanceof Date
|
|
70
|
+
? date.toLocaleDateString('en-US', {
|
|
71
|
+
month: 'long',
|
|
72
|
+
year: 'numeric',
|
|
73
|
+
})
|
|
74
|
+
: 'Unknown Date' }), jsxs("div", { className: S.tooltipPerformance, children: ["Performance:", ' ', typeof value === 'number'
|
|
75
|
+
? value.toFixed(precision)
|
|
76
|
+
: String(value ?? '')] })] }));
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
};
|
|
80
|
+
return (jsxs("div", { className: S.driverChartContainer, children: [jsx(ChartContainer, { config: driverChartConfig, className: cn(S.chartContainer, noSeriesData && S.chartContainerDisabled), children: jsxs(LineChart, { data: chartData, margin: { left: 8, right: 8, top: 8, bottom: -20 }, children: [jsx(CartesianGrid, { vertical: false }), jsx(XAxis, { dataKey: "date", tickLine: false, axisLine: false, tick: false, tickMargin: 0, minTickGap: 0 }), jsx(YAxis, { tickLine: false, axisLine: false, tick: false, tickMargin: 0, minTickGap: 0, width: 0, domain: ['dataMin', 'dataMax'] }), jsx(Tooltip, { cursor: false, content: renderTooltipContent }), jsx(Line, { dataKey: "value", type: "natural", stroke: "var(--color-value)" })] }) }), noSeriesData && (jsx(ChartEmptyState, { variant: "inline", align: "center", status: "No series data", className: S.noDataMessage }))] }));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export { DriverPerformanceChart };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import styleInject from 'style-inject';
|
|
2
|
+
|
|
3
|
+
var css_248z = ".DriverPerformanceChart_driverChartContainer__27xZ-{position:relative;width:100%}.DriverPerformanceChart_driverChartContainer__27xZ- svg{overflow:visible}.DriverPerformanceChart_chartContainer__--rGL{height:214px;margin-left:-.5rem;padding:var(--p-4) 0;width:100%}.DriverPerformanceChart_chartContainerDisabled__ndtPZ{opacity:.1}.DriverPerformanceChart_noDataMessage__RO3u1{color:var(--foreground);font-size:.875rem;font-weight:500;left:50%;pointer-events:none;position:absolute;top:50%;transform:translate(-50%,-50%);z-index:10}.DriverPerformanceChart_chartTooltip__cpaQw{background-color:var(--popover);border:1px solid var(--border);border-radius:.5rem;box-shadow:0 10px 15px -3px rgba(0,0,0,.1);padding:.75rem}.DriverPerformanceChart_tooltipDate__B2aeP{color:var(--popover-foreground);font-size:.875rem;font-weight:500}.DriverPerformanceChart_tooltipPerformance__3hfgE{color:var(--muted-foreground);font-size:.875rem}";
|
|
4
|
+
var S = {"driverChartContainer":"DriverPerformanceChart_driverChartContainer__27xZ-","chartContainer":"DriverPerformanceChart_chartContainer__--rGL","chartContainerDisabled":"DriverPerformanceChart_chartContainerDisabled__ndtPZ","noDataMessage":"DriverPerformanceChart_noDataMessage__RO3u1","chartTooltip":"DriverPerformanceChart_chartTooltip__cpaQw","tooltipDate":"DriverPerformanceChart_tooltipDate__B2aeP","tooltipPerformance":"DriverPerformanceChart_tooltipPerformance__3hfgE"};
|
|
5
|
+
styleInject(css_248z);
|
|
6
|
+
|
|
7
|
+
export { S as default };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/** Last non-null points from `normalized_series`, or deterministic fallback sample. */
|
|
2
|
+
function generateDriverChartData(driver, precision = 7) {
|
|
3
|
+
if (driver.normalized_series) {
|
|
4
|
+
const entries = Object.entries(driver.normalized_series);
|
|
5
|
+
const seriesData = entries
|
|
6
|
+
.filter(([, value]) => value !== null)
|
|
7
|
+
.map(([date, value]) => {
|
|
8
|
+
let parsedDate;
|
|
9
|
+
try {
|
|
10
|
+
const dateStr = date.toString();
|
|
11
|
+
if (dateStr.includes('-')) {
|
|
12
|
+
parsedDate = new Date(`${dateStr}T00:00:00`);
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
parsedDate = new Date(dateStr);
|
|
16
|
+
}
|
|
17
|
+
if (Number.isNaN(parsedDate.getTime())) {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
const numericValue = parseFloat(value.toFixed(precision));
|
|
25
|
+
return {
|
|
26
|
+
date: parsedDate,
|
|
27
|
+
value: numericValue,
|
|
28
|
+
};
|
|
29
|
+
})
|
|
30
|
+
.filter((item) => item !== null)
|
|
31
|
+
.sort((a, b) => a.date.getTime() - b.date.getTime())
|
|
32
|
+
.slice(-24);
|
|
33
|
+
if (seriesData.length > 0) {
|
|
34
|
+
return seriesData;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const data = [];
|
|
38
|
+
const baseValue = driver.importance / 100;
|
|
39
|
+
for (let i = 0; i < 12; i++) {
|
|
40
|
+
const randomVariation = (Math.random() - 0.5) * 0.2;
|
|
41
|
+
const value = Math.max(0, Math.min(1, baseValue + randomVariation));
|
|
42
|
+
data.push({
|
|
43
|
+
date: new Date(2023, i, 1),
|
|
44
|
+
value: parseFloat(value.toFixed(precision)),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
return data;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { generateDriverChartData };
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import { useRef, useState, useMemo, useEffect, useCallback } from 'react';
|
|
4
|
+
import { WorldMap } from '../../ui/WorldMap/WorldMap.js';
|
|
4
5
|
import useEvent from '../../../hooks/useEvent.js';
|
|
5
6
|
import { Shimmer } from '@homecode/ui';
|
|
6
7
|
import { DriverIcon } from './DriverIcon/DriverIcon.js';
|
|
7
8
|
import constants from './DriverIcon/DriverIcon.constants.json.js';
|
|
8
9
|
import { findMostSpecificRegion, getDriverCoordinates, hasValidCoords, calculateBadgeSizes } from './DriverMap.helpers.js';
|
|
9
10
|
import S from './DriverMap.styl.js';
|
|
10
|
-
import { MapBackground } from './MapBackground/MapBackground.js';
|
|
11
11
|
import { getHighestImportanceDriver } from './driverMapSelection.js';
|
|
12
12
|
|
|
13
13
|
const delay = (ms) => new Promise(r => setTimeout(r, ms));
|
|
@@ -113,7 +113,7 @@ function DriverMap({ drivers, isLoading, setSelectedDriver, selectedDriver, }) {
|
|
|
113
113
|
callback: handleKeyDown,
|
|
114
114
|
isCapture: true,
|
|
115
115
|
});
|
|
116
|
-
return (jsxs("div", { className: cn(S.root, isTransitioning && S.inTransition), children: [jsxs("div", { className: S.mapInner, children: [jsx(
|
|
116
|
+
return (jsxs("div", { className: cn(S.root, isTransitioning && S.inTransition), children: [jsxs("div", { className: S.mapInner, children: [jsx(WorldMap, { className: S.mapWorld }), isLoading && jsx(Shimmer, { className: S.shimmerOverlay, size: "l" }), otherDrivers.map(driver => (jsx(DriverIcon, { isLoading: isLoading, isVisible: isVisible, driver: driver, size: badgeSizes[driver.id] || 's', isSelected: selectedDriver?.id === driver.id, onClick: () => setSelectedDriver(driver) }, driver.id)))] }), jsx("div", { className: S.worldDrivers, children: worldDrivers.map(driver => {
|
|
117
117
|
const driverWithCoords = {
|
|
118
118
|
...driver,
|
|
119
119
|
coordinates: driver.coordinates || {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.DriverMap_root__JszhG{aspect-ratio:623.2/341.276;max-width:100%;overflow:hidden;padding:0;position:relative;width:100%}@media (min-width:768px){.DriverMap_root__JszhG{flex:1;height:35rem;width:-moz-fit-content;width:fit-content}}.DriverMap_mapInner__E7rZR{aspect-ratio:623.2/341.276;border-radius:var(--p-4);margin:0 auto;max-height:100%;max-width:100%;overflow:hidden;position:relative}.DriverMap_shimmerOverlay__UH2qz{z-index:20}.DriverMap_inTransition__lvYwJ{pointer-events:none}.DriverMap_worldDrivers__sZOIW{align-items:center;bottom:0;display:flex;gap:.5rem;padding:.5rem;position:absolute}.DriverMap_worldDrivers__sZOIW button{position:static!important;transform:none!important}.DriverMap_worldDrivers__sZOIW button>span{opacity:1!important;transform:none!important}";
|
|
4
|
-
var S = {"root":"DriverMap_root__JszhG","mapInner":"DriverMap_mapInner__E7rZR","shimmerOverlay":"DriverMap_shimmerOverlay__UH2qz","inTransition":"DriverMap_inTransition__lvYwJ","worldDrivers":"DriverMap_worldDrivers__sZOIW"};
|
|
3
|
+
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.DriverMap_root__JszhG{aspect-ratio:623.2/341.276;max-width:100%;overflow:hidden;padding:0;position:relative;width:100%}@media (min-width:768px){.DriverMap_root__JszhG{flex:1;height:35rem;width:-moz-fit-content;width:fit-content}}.DriverMap_mapInner__E7rZR{aspect-ratio:623.2/341.276;border-radius:var(--p-4);margin:0 auto;max-height:100%;max-width:100%;overflow:hidden;position:relative}.DriverMap_mapWorld__vmPp-{box-sizing:border-box;inset:0;position:absolute}.DriverMap_shimmerOverlay__UH2qz{z-index:20}.DriverMap_inTransition__lvYwJ{pointer-events:none}.DriverMap_worldDrivers__sZOIW{align-items:center;bottom:0;display:flex;gap:.5rem;padding:.5rem;position:absolute}.DriverMap_worldDrivers__sZOIW button{position:static!important;transform:none!important}.DriverMap_worldDrivers__sZOIW button>span{opacity:1!important;transform:none!important}";
|
|
4
|
+
var S = {"root":"DriverMap_root__JszhG","mapInner":"DriverMap_mapInner__E7rZR","mapWorld":"DriverMap_mapWorld__vmPp-","shimmerOverlay":"DriverMap_shimmerOverlay__UH2qz","inTransition":"DriverMap_inTransition__lvYwJ","worldDrivers":"DriverMap_worldDrivers__sZOIW"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
7
7
|
export { S as default };
|
package/dist/esm/index.js
CHANGED
|
@@ -81,6 +81,7 @@ export { Toggle } from './components/ui/Toggle/Toggle.js';
|
|
|
81
81
|
export { ToggleGroup, ToggleGroupItem } from './components/ui/ToggleGroup/ToggleGroup.js';
|
|
82
82
|
export { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './components/ui/Tooltip/Tooltip.js';
|
|
83
83
|
export { VimeoEmbed } from './components/ui/VimeoEmbed/VimeoEmbed.js';
|
|
84
|
+
export { WorldMap } from './components/ui/WorldMap/WorldMap.js';
|
|
84
85
|
export { WorkspaceAppSwitcher } from './components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.js';
|
|
85
86
|
export { WORKSPACE_APP_SLUG_BASE_PATH } from './components/ui/WorkspaceAppSwitcher/workspaceApp.types.js';
|
|
86
87
|
export { WORKSPACE_APPS_LS_KEY } from './components/ui/WorkspaceAppSwitcher/workspaceAppsConstants.js';
|
|
@@ -89,12 +90,11 @@ export { WORKSPACE_APP_ICONS, isWorkspaceAppIconKey } from './components/ui/Work
|
|
|
89
90
|
export { findWorkspaceAppByPathname, workspaceAppSlugPath } from './components/ui/WorkspaceAppSwitcher/workspaceAppPaths.js';
|
|
90
91
|
export { SidebarDatasetsItemsGrouped } from './components/widgets/SidebarDatasetsItemsGrouped/SidebarDatasetsItemsGrouped.js';
|
|
91
92
|
export { groupSidebarDatasets } from './components/widgets/SidebarDatasetsItemsGrouped/groupSidebarDatasets.js';
|
|
93
|
+
export { DriverCard } from './components/widgets/DriverCard/DriverCard.js';
|
|
92
94
|
export { DriverMap } from './components/widgets/DriverMap/DriverMap.js';
|
|
93
95
|
export { getCategoryIcon } from './components/widgets/DriverMap/driverCategoryIcon.js';
|
|
94
96
|
export { getDriverImportance, getHighestImportanceDriver } from './components/widgets/DriverMap/driverMapSelection.js';
|
|
95
97
|
export { geographicCoordinates, geographicToSVG, getContinentFromRegion, getPreciseCoordinates, getResponsiveCoordinates, svgToPercentage } from './components/widgets/DriverMap/driverMapGeography.js';
|
|
96
|
-
export { MapBackground } from './components/widgets/DriverMap/MapBackground/MapBackground.js';
|
|
97
|
-
export { LoadingSpinner } from './components/widgets/DriverMap/LoadingSpinner/LoadingSpinner.js';
|
|
98
98
|
export { SybilionAppHeader } from './components/widgets/SybilionAppHeader/SybilionAppHeader.js';
|
|
99
99
|
export { SybilionAuthLayout } from './components/widgets/SybilionAuthLayout/SybilionAuthLayout.js';
|
|
100
100
|
export { SybilionAuthHeadline } from './components/widgets/SybilionAuthLayout/SybilionAuthHeadline.js';
|
|
@@ -103,6 +103,8 @@ export { SignInPage } from './components/widgets/SignInPage/SignInPage.js';
|
|
|
103
103
|
export { ChartTooltipItem } from './components/ui/Chart/components/ChartTooltipItem.js';
|
|
104
104
|
export { ChartLegendItem } from './components/ui/Chart/components/ChartLegendItem.js';
|
|
105
105
|
export { CustomChartLegend } from './components/ui/Chart/components/CustomChartLegend/CustomChartLegend.js';
|
|
106
|
+
export { LightweightForecastChart } from './components/ui/Chart/lightweight/LightweightForecastChart.js';
|
|
107
|
+
export { ChartEmptyState } from './components/ui/Chart/components/ChartEmptyState/ChartEmptyState.js';
|
|
106
108
|
export { ChartContainer, ChartStyle } from './components/ui/Chart/components/ChartContainer.js';
|
|
107
109
|
export { ChartTooltipContent } from './components/ui/Chart/components/ChartTooltipContent.js';
|
|
108
110
|
export { ChartLegendContent } from './components/ui/Chart/components/ChartLegendContent.js';
|
|
@@ -10,3 +10,5 @@ export { ChartTooltipItem } from './components/ChartTooltipItem';
|
|
|
10
10
|
export { ChartLegendItem } from './components/ChartLegendItem';
|
|
11
11
|
export { CustomChartLegend } from './components/CustomChartLegend/CustomChartLegend';
|
|
12
12
|
export { ChartContainer, ChartTooltip, ChartTooltipContent, ChartLegend, ChartLegendContent, ChartStyle, BaseChartWrapper, };
|
|
13
|
+
export { LightweightForecastChart, type LightweightForecastChartProps, } from './lightweight/LightweightForecastChart';
|
|
14
|
+
export { ChartEmptyState, type ChartEmptyStateProps, type ChartEmptyStatusTone, } from './components/ChartEmptyState/ChartEmptyState';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { ComponentProps, ReactNode } from 'react';
|
|
2
|
-
import { ChartConfig, ChartContainer } from '#uilib/components/ui/Chart/Chart';
|
|
3
2
|
import type { QuantileBandConfig } from '#uilib/components/ui/Chart/chartForecastVisualization.types';
|
|
4
3
|
import { ChartDataPoint } from '#uilib/components/ui/ChartAreaInteractive/ChartAreaInteractive.types';
|
|
5
4
|
import { ForecastItemData } from '#uilib/components/ui/ChartAreaInteractive/ChartLines';
|
|
5
|
+
import type { ChartConfig } from '../Chart.types';
|
|
6
|
+
import { ChartContainer } from './ChartContainer';
|
|
6
7
|
import { LegendPayload } from 'recharts/types/component/DefaultLegendContent';
|
|
7
8
|
export interface BaseChartWrapperProps {
|
|
8
9
|
renderId?: string;
|
package/dist/esm/types/src/components/ui/Chart/components/ChartEmptyState/ChartEmptyState.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
export type ChartEmptyStatusTone = 'muted' | 'destructive';
|
|
3
|
+
export interface ChartEmptyStateProps {
|
|
4
|
+
className?: string;
|
|
5
|
+
/** Primary guidance (muted). */
|
|
6
|
+
hint?: ReactNode;
|
|
7
|
+
/** Status / technical detail. */
|
|
8
|
+
status?: ReactNode;
|
|
9
|
+
statusTone?: ChartEmptyStatusTone;
|
|
10
|
+
/** `panel`: chart-sized block with light fill. `inline`: text only (e.g. above chart). */
|
|
11
|
+
variant?: 'panel' | 'inline';
|
|
12
|
+
align?: 'center' | 'start';
|
|
13
|
+
}
|
|
14
|
+
export declare function ChartEmptyState({ className, hint, status, statusTone, variant, align, }: ChartEmptyStateProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { ChartConfig } from '#uilib/components/ui/Chart/Chart.types';
|
|
2
|
+
import type { QuantileBandConfig } from '#uilib/components/ui/Chart/chartForecastVisualization.types';
|
|
3
|
+
import type { ChartDataPoint } from '#uilib/components/ui/ChartAreaInteractive/ChartAreaInteractive.types';
|
|
4
|
+
import { ForecastItemData } from '#uilib/components/ui/ChartAreaInteractive/ChartLines';
|
|
5
|
+
export interface LightweightForecastChartProps {
|
|
6
|
+
chartData: ChartDataPoint[];
|
|
7
|
+
forecastData?: ForecastItemData[];
|
|
8
|
+
quantileBands?: QuantileBandConfig[];
|
|
9
|
+
chartConfig?: ChartConfig;
|
|
10
|
+
historicalLineColor?: string;
|
|
11
|
+
isDarkTheme: boolean;
|
|
12
|
+
height?: number;
|
|
13
|
+
className?: string;
|
|
14
|
+
hiddenSeries?: Set<string>;
|
|
15
|
+
onLegendClick?: (data: unknown, index: number, event: unknown) => void;
|
|
16
|
+
disableForecastHistoricalBridge?: boolean;
|
|
17
|
+
forecastLineStyle?: 'dashed' | 'solid';
|
|
18
|
+
formatDate?: (value: string, detailed?: boolean) => string;
|
|
19
|
+
formatNumber?: (value: number) => string;
|
|
20
|
+
loading?: boolean;
|
|
21
|
+
error?: string | null;
|
|
22
|
+
noDataMessage?: string;
|
|
23
|
+
showLegend?: boolean;
|
|
24
|
+
showTooltip?: boolean;
|
|
25
|
+
}
|
|
26
|
+
export declare function LightweightForecastChart(props: LightweightForecastChartProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/esm/types/src/components/ui/Chart/lightweight/lightweightForecastChart.helpers.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { ChartDataPoint } from '#uilib/components/ui/ChartAreaInteractive/ChartAreaInteractive.types';
|
|
2
|
+
import type { ChartOptions, DeepPartial, LineData, UTCTimestamp } from 'lightweight-charts';
|
|
3
|
+
import type { QuantileBandCustomData } from './quantileBandCustomSeries';
|
|
4
|
+
export declare function buildLightweightChartOptions(args: {
|
|
5
|
+
isDarkTheme: boolean;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
autoSize?: boolean;
|
|
9
|
+
}): DeepPartial<ChartOptions>;
|
|
10
|
+
export declare function buildHistoricalLineData(rows: ChartDataPoint[]): LineData<UTCTimestamp>[];
|
|
11
|
+
export declare function buildForecastLineData(rows: ChartDataPoint[], forecastKey: string): LineData<UTCTimestamp>[];
|
|
12
|
+
export declare function buildQuantileBandCustomData(rows: ChartDataPoint[], bandKey: string): QuantileBandCustomData[];
|
|
13
|
+
export declare function findNearestChartRow(rows: ChartDataPoint[], time: UTCTimestamp): ChartDataPoint | null;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { CustomData, CustomSeriesOptions, CustomSeriesWhitespaceData, ICustomSeriesPaneRenderer, ICustomSeriesPaneView, PaneRendererCustomData, UTCTimestamp } from 'lightweight-charts';
|
|
2
|
+
export interface QuantileBandCustomData extends CustomData<UTCTimestamp> {
|
|
3
|
+
lower: number;
|
|
4
|
+
upper: number;
|
|
5
|
+
}
|
|
6
|
+
export type QuantileBandStyle = {
|
|
7
|
+
fill: string;
|
|
8
|
+
stroke?: string;
|
|
9
|
+
strokeWidth: number;
|
|
10
|
+
strokeDasharray?: string;
|
|
11
|
+
strokeOpacity?: number;
|
|
12
|
+
};
|
|
13
|
+
export declare class QuantileBandPaneView implements ICustomSeriesPaneView<UTCTimestamp, QuantileBandCustomData, CustomSeriesOptions> {
|
|
14
|
+
private _paneData;
|
|
15
|
+
private _style;
|
|
16
|
+
constructor(initialStyle: QuantileBandStyle);
|
|
17
|
+
updateStyle(style: QuantileBandStyle): void;
|
|
18
|
+
renderer(): ICustomSeriesPaneRenderer;
|
|
19
|
+
update(paneData: PaneRendererCustomData<UTCTimestamp, QuantileBandCustomData>, seriesOptions: CustomSeriesOptions): void;
|
|
20
|
+
priceValueBuilder(plotRow: QuantileBandCustomData): number[];
|
|
21
|
+
isWhitespace(data: QuantileBandCustomData | CustomSeriesWhitespaceData<UTCTimestamp>): data is CustomSeriesWhitespaceData<UTCTimestamp>;
|
|
22
|
+
defaultOptions(): CustomSeriesOptions;
|
|
23
|
+
destroy(): void;
|
|
24
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ChartDataPoint } from '#uilib/components/ui/ChartAreaInteractive/ChartAreaInteractive.types';
|
|
2
|
+
/**
|
|
3
|
+
* Matches ChartAreaInteractive `mode="intervals"`: cone / fan chart hand-off — collapse the
|
|
4
|
+
* interval to a point at the historical→forecast boundary, then expand along forecast anchors.
|
|
5
|
+
* (Same rules as `useQuantileBands`, without requiring `ForecastData` — reads tuples from each row.)
|
|
6
|
+
*/
|
|
7
|
+
export declare function applyQuantileBandConeToChartData(chartData: ChartDataPoint[], bandKey: string): ChartDataPoint[];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared Recharts plot / margin math (DOM-agnostic except measurement entry points).
|
|
3
|
+
* Keeps BaseChartWrapper tooltip clamp and ChartAreaInteractive brush in sync.
|
|
4
|
+
*/
|
|
5
|
+
export type ChartMargin = {
|
|
6
|
+
top: number;
|
|
7
|
+
right: number;
|
|
8
|
+
bottom: number;
|
|
9
|
+
left: number;
|
|
10
|
+
};
|
|
11
|
+
export declare const DEFAULT_CHART_MARGIN: ChartMargin;
|
|
12
|
+
export declare function resolveChartMargin(margin: Partial<ChartMargin> | undefined): ChartMargin;
|
|
13
|
+
/** Plot box inside `.recharts-wrapper` (Recharts cartesian convention). */
|
|
14
|
+
export declare function getPlotViewBox(wrapper: HTMLElement, m: ChartMargin): {
|
|
15
|
+
x: number;
|
|
16
|
+
y: number;
|
|
17
|
+
width: number;
|
|
18
|
+
height: number;
|
|
19
|
+
};
|
|
20
|
+
export type PlotRect = {
|
|
21
|
+
left: number;
|
|
22
|
+
top: number;
|
|
23
|
+
width: number;
|
|
24
|
+
height: number;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Plot area in `host` local px: prefer painted `.recharts-cartesian-grid`, else
|
|
28
|
+
* last `.recharts-wrapper` + margins. One `hostRect` read; grid/wrapper rects as needed.
|
|
29
|
+
*/
|
|
30
|
+
export declare function measureHostRelativePlotRect(host: HTMLElement, margin: ChartMargin): PlotRect | null;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ChartAreaInteractiveProps } from './ChartAreaInteractive.types';
|
|
2
2
|
export declare const chartConfig: {};
|
|
3
|
-
export declare function ChartAreaInteractive({ className, chartContainerClassName, legendClassName, xAxisClassName, yAxisClassName, timeRange, onTimeRangeChange, pinMonth, onPinMonthChange, onPreviewMonthChange, chartData, forecastData, error, loading, isDarkTheme, footerActions, mode, selectedForecast, upperQuantiles, lowerQuantiles, selectedLowerQuantile, selectedUpperQuantile, onLowerQuantileChange, onUpperQuantileChange, lowerThreshold, upperThreshold, onLowerThresholdChange, onUpperThresholdChange, discreteThresholdValues, headerActions, excludeLegendIds, loadingAnalyses, onLegendClick, onAnalysisSelect, disableTimeRangeSelector, forecastLineStyle, selectedAnalysisId, chartRenderId, toggleLegendSeries, ensureAnalysisSeriesVisible, overlayForecastData, hiddenSeries, disableForecastHistoricalBridge, ...restProps }: ChartAreaInteractiveProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
export declare function ChartAreaInteractive({ className, chartContainerClassName, legendClassName, xAxisClassName, yAxisClassName, timeRange, onTimeRangeChange, pinMonth, onPinMonthChange, onPreviewMonthChange, chartData, forecastData, error, loading, isDarkTheme, footerActions, mode, selectedForecast, upperQuantiles, lowerQuantiles, selectedLowerQuantile, selectedUpperQuantile, onLowerQuantileChange, onUpperQuantileChange, lowerThreshold, upperThreshold, onLowerThresholdChange, onUpperThresholdChange, discreteThresholdValues, headerActions, excludeLegendIds, loadingAnalyses, onLegendClick, onAnalysisSelect, disableTimeRangeSelector, forecastLineStyle, selectedAnalysisId, chartRenderId, toggleLegendSeries, ensureAnalysisSeriesVisible, overlayForecastData, hiddenSeries, disableForecastHistoricalBridge, overlayElements: overlayElementsProp, ...restProps }: ChartAreaInteractiveProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/esm/types/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.helpers.d.ts
CHANGED
|
@@ -8,13 +8,22 @@ declare const timeRangeToMonths: {
|
|
|
8
8
|
readonly '5y': 60;
|
|
9
9
|
readonly All: 12;
|
|
10
10
|
};
|
|
11
|
-
export type
|
|
11
|
+
export type TimeRangePreset = keyof typeof timeRangeToMonths;
|
|
12
|
+
/** @deprecated Use `TimeRangePreset` or `string` for brush-encoded ranges. */
|
|
13
|
+
export type TimeRange = TimeRangePreset;
|
|
14
|
+
export declare const DRAG_TIME_RANGE_PREFIX: "__drag:";
|
|
15
|
+
export declare function encodeDragTimeRange(a: Date, b: Date): string;
|
|
16
|
+
export declare function parseDragTimeRange(s: string): {
|
|
17
|
+
start: Date;
|
|
18
|
+
end: Date;
|
|
19
|
+
} | null;
|
|
20
|
+
export declare function isTimeRangePreset(s: string): s is TimeRangePreset;
|
|
12
21
|
export type FilterDataForTimeRangeOptions = {
|
|
13
22
|
/** When set (e.g. selected forecast on Forecast tab), the window ends at the
|
|
14
23
|
* latest point that has shared historical or that analysis — not at another run. */
|
|
15
24
|
endDateAnchorAnalysisId?: number | null;
|
|
16
25
|
};
|
|
17
|
-
export declare const filterDataForTimeRange: (data: ChartDataPoint[], currentTimeRange:
|
|
26
|
+
export declare const filterDataForTimeRange: (data: ChartDataPoint[], currentTimeRange: string, options?: FilterDataForTimeRangeOptions) => ChartDataPoint[];
|
|
18
27
|
export declare const shortDateFormatter: (value: string) => string;
|
|
19
28
|
export declare const longDateFormatter: (value: string) => string;
|
|
20
29
|
/**
|
package/dist/esm/types/src/components/ui/ChartAreaInteractive/ChartAreaInteractive.types.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { BaseChartWrapperProps } from '#uilib/components/ui/Chart/components/BaseChartWrapper';
|
|
2
2
|
import type { ForecastData } from '#uilib/types/forecast-data';
|
|
3
3
|
import { LegendPayload } from 'recharts';
|
|
4
|
-
import { TimeRange } from './ChartAreaInteractive.helpers';
|
|
5
4
|
export type OverlayMode = 'pin' | 'intervals' | 'thresholds';
|
|
6
5
|
export interface ChartDataPoint {
|
|
7
6
|
date: string;
|
|
@@ -22,7 +21,8 @@ export interface Analysis {
|
|
|
22
21
|
}
|
|
23
22
|
export interface ChartAreaInteractiveProps extends BaseChartWrapperProps {
|
|
24
23
|
chartContainerClassName?: string;
|
|
25
|
-
|
|
24
|
+
/** Preset (`6m`, `1y`, …, `All`) or `__drag:startMs,endMs` from chart brush. */
|
|
25
|
+
timeRange: string;
|
|
26
26
|
onTimeRangeChange: (range: string) => void;
|
|
27
27
|
pinMonth: string | undefined;
|
|
28
28
|
onPinMonthChange: (month: string | undefined) => void;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
import type { ChartDataPoint } from '#uilib/components/ui/ChartAreaInteractive/ChartAreaInteractive.types';
|
|
3
|
+
export interface TimeRangeBrushHostProps {
|
|
4
|
+
chartData: ChartDataPoint[];
|
|
5
|
+
onTimeRangeChange: (range: string) => void;
|
|
6
|
+
enabled: boolean;
|
|
7
|
+
/** Bumps layout sync when chart remounts (e.g. dataset / render id). */
|
|
8
|
+
layoutKey?: string | number | null;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Wraps chart; pointerdown on SVG starts horizontal brush. Plot box tracks the
|
|
13
|
+
* painted grid / Recharts plot (see TimeRangeBrushLayout.helpers).
|
|
14
|
+
*/
|
|
15
|
+
export declare function TimeRangeBrushHost({ chartData, onTimeRangeChange, enabled, layoutKey, children, }: TimeRangeBrushHostProps): import("react/jsx-runtime").JSX.Element;
|
package/dist/esm/types/src/components/ui/ChartAreaInteractive/TimeRangeBrushLayout.helpers.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type ChartMargin, type PlotRect, measureHostRelativePlotRect, resolveChartMargin } from '#uilib/components/ui/Chart/tools/chartPlotGeometry';
|
|
2
|
+
import type { ChartDataPoint } from '#uilib/components/ui/ChartAreaInteractive/ChartAreaInteractive.types';
|
|
3
|
+
/** Debounce for `window` resize only (RO uses rAF-coalesced sync). */
|
|
4
|
+
export declare const BRUSH_LAYOUT_RESIZE_DEBOUNCE_MS = 500;
|
|
5
|
+
export declare const BRUSH_MIN_DRAG_PX = 8;
|
|
6
|
+
export declare const BRUSH_DOUBLE_TAP_MS = 300;
|
|
7
|
+
export declare const BRUSH_DOUBLE_TAP_MAX_DIST_PX = 24;
|
|
8
|
+
export type { ChartMargin };
|
|
9
|
+
export { resolveChartMargin };
|
|
10
|
+
export type BrushPlotLayout = PlotRect;
|
|
11
|
+
/** Host-relative plot rect (grid-first, then wrapper + margins). */
|
|
12
|
+
export declare const measureBrushPlotLayout: typeof measureHostRelativePlotRect;
|
|
13
|
+
export declare function brushPlotLayoutsEqual(a: BrushPlotLayout | null, b: BrushPlotLayout | null): boolean;
|
|
14
|
+
export declare function brushClientXToDate(clientX: number, plotRect: DOMRect, chartData: ChartDataPoint[]): Date | null;
|
package/dist/esm/types/src/components/ui/ChartAreaInteractive/overlays/PinOverlay/PinOverlay.d.ts
CHANGED
|
@@ -6,5 +6,5 @@ interface PinOverlayProps {
|
|
|
6
6
|
onPreviewMonthChange?: (month: string | undefined) => void;
|
|
7
7
|
className?: string;
|
|
8
8
|
}
|
|
9
|
-
export declare function PinOverlay({ baseChartProps, pinMonth, onPinMonthChange, onPreviewMonthChange, className, }: PinOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function PinOverlay({ baseChartProps, pinMonth, onPinMonthChange, onPreviewMonthChange: _onPreviewMonthChange, className, }: PinOverlayProps): import("react/jsx-runtime").JSX.Element;
|
|
10
10
|
export {};
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
timeRange: TimeRange;
|
|
1
|
+
export type TimeRangeControlsProps = {
|
|
2
|
+
timeRange: string;
|
|
4
3
|
onTimeRangeChange: (range: string) => void;
|
|
5
4
|
loading?: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare const
|
|
8
|
-
|
|
9
|
-
onTimeRangeChange: (range: string) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare const TimeRangeControls: import("react").MemoExoticComponent<({ timeRange, onTimeRangeChange, loading }: TimeRangeControlsProps) => import("react/jsx-runtime").JSX.Element>;
|
|
7
|
+
export declare const TimeRangeSelect: import("react").MemoExoticComponent<({ timeRange, onTimeRangeChange, loading, }: TimeRangeControlsProps & {
|
|
10
8
|
loading: boolean;
|
|
11
9
|
}) => import("react/jsx-runtime").JSX.Element>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { DriverData } from '../DriverMap/driverMapGeography';
|
|
3
|
+
export interface DriverCardProps {
|
|
4
|
+
selectedDriver: DriverData | null;
|
|
5
|
+
isLoading: boolean;
|
|
6
|
+
inQueue?: boolean;
|
|
7
|
+
driverSelector?: React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export declare function DriverCard({ selectedDriver, isLoading, inQueue, driverSelector, }: DriverCardProps): import("react/jsx-runtime").JSX.Element;
|