@almadar/ui 4.51.13 → 4.51.15
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/avl/index.cjs +777 -151
- package/dist/avl/index.js +777 -151
- package/dist/components/atoms/Sparkline.d.ts +30 -0
- package/dist/components/atoms/index.d.ts +1 -0
- package/dist/components/index.cjs +765 -149
- package/dist/components/index.js +766 -150
- package/dist/components/molecules/DateRangePicker.d.ts +56 -0
- package/dist/components/molecules/FilterGroup.d.ts +3 -3
- package/dist/components/molecules/StatDisplay.d.ts +9 -1
- package/dist/components/molecules/index.d.ts +1 -0
- package/dist/components/organisms/Chart.d.ts +32 -12
- package/dist/providers/index.cjs +763 -149
- package/dist/providers/index.js +763 -149
- package/dist/runtime/index.cjs +763 -149
- package/dist/runtime/index.js +763 -149
- package/package.json +1 -1
|
@@ -2681,6 +2681,67 @@ var init_Radio = __esm({
|
|
|
2681
2681
|
exports.Radio.displayName = "Radio";
|
|
2682
2682
|
}
|
|
2683
2683
|
});
|
|
2684
|
+
var COLOR_VAR; exports.Sparkline = void 0;
|
|
2685
|
+
var init_Sparkline = __esm({
|
|
2686
|
+
"components/atoms/Sparkline.tsx"() {
|
|
2687
|
+
init_cn();
|
|
2688
|
+
COLOR_VAR = {
|
|
2689
|
+
primary: "var(--color-primary)",
|
|
2690
|
+
success: "var(--color-success)",
|
|
2691
|
+
warning: "var(--color-warning)",
|
|
2692
|
+
error: "var(--color-error)",
|
|
2693
|
+
info: "var(--color-info)",
|
|
2694
|
+
muted: "var(--color-muted-foreground)"
|
|
2695
|
+
};
|
|
2696
|
+
exports.Sparkline = ({
|
|
2697
|
+
data,
|
|
2698
|
+
color = "auto",
|
|
2699
|
+
width = 80,
|
|
2700
|
+
height = 32,
|
|
2701
|
+
strokeWidth = 2,
|
|
2702
|
+
fill = false,
|
|
2703
|
+
className
|
|
2704
|
+
}) => {
|
|
2705
|
+
if (data.length < 2) return null;
|
|
2706
|
+
const pad = 2;
|
|
2707
|
+
const min = Math.min(...data);
|
|
2708
|
+
const max = Math.max(...data);
|
|
2709
|
+
const range = max - min || 1;
|
|
2710
|
+
const points = data.map((v, i) => {
|
|
2711
|
+
const x = pad + i / (data.length - 1) * (width - pad * 2);
|
|
2712
|
+
const y = pad + (1 - (v - min) / range) * (height - pad * 2);
|
|
2713
|
+
return `${x},${y}`;
|
|
2714
|
+
}).join(" ");
|
|
2715
|
+
const resolvedColor = color === "auto" ? data[data.length - 1] >= data[0] ? COLOR_VAR.success : COLOR_VAR.error : COLOR_VAR[color];
|
|
2716
|
+
const areaPath = fill ? `M ${pad},${height - pad} L ${points.split(" ").join(" L ")} L ${width - pad},${height - pad} Z` : null;
|
|
2717
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2718
|
+
"svg",
|
|
2719
|
+
{
|
|
2720
|
+
width,
|
|
2721
|
+
height,
|
|
2722
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
2723
|
+
className: cn("flex-shrink-0", className),
|
|
2724
|
+
"aria-hidden": "true",
|
|
2725
|
+
children: [
|
|
2726
|
+
areaPath && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: resolvedColor, opacity: 0.15 }),
|
|
2727
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2728
|
+
"polyline",
|
|
2729
|
+
{
|
|
2730
|
+
fill: "none",
|
|
2731
|
+
stroke: resolvedColor,
|
|
2732
|
+
strokeWidth,
|
|
2733
|
+
strokeLinecap: "round",
|
|
2734
|
+
strokeLinejoin: "round",
|
|
2735
|
+
points
|
|
2736
|
+
}
|
|
2737
|
+
)
|
|
2738
|
+
]
|
|
2739
|
+
}
|
|
2740
|
+
);
|
|
2741
|
+
};
|
|
2742
|
+
exports.Sparkline.displayName = "Sparkline";
|
|
2743
|
+
}
|
|
2744
|
+
});
|
|
2684
2745
|
exports.Switch = void 0;
|
|
2685
2746
|
var init_Switch = __esm({
|
|
2686
2747
|
"components/atoms/Switch.tsx"() {
|
|
@@ -7754,7 +7815,7 @@ var init_MapView = __esm({
|
|
|
7754
7815
|
shadowSize: [41, 41]
|
|
7755
7816
|
});
|
|
7756
7817
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
7757
|
-
const { useEffect: useEffect70, useRef: useRef66, useCallback:
|
|
7818
|
+
const { useEffect: useEffect70, useRef: useRef66, useCallback: useCallback126, useState: useState107 } = React75__namespace.default;
|
|
7758
7819
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
7759
7820
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
7760
7821
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -7799,8 +7860,8 @@ var init_MapView = __esm({
|
|
|
7799
7860
|
showAttribution = true
|
|
7800
7861
|
}) {
|
|
7801
7862
|
const eventBus = useEventBus2();
|
|
7802
|
-
const [clickedPosition, setClickedPosition] =
|
|
7803
|
-
const handleMapClick =
|
|
7863
|
+
const [clickedPosition, setClickedPosition] = useState107(null);
|
|
7864
|
+
const handleMapClick = useCallback126((lat, lng) => {
|
|
7804
7865
|
if (showClickedPin) {
|
|
7805
7866
|
setClickedPosition({ lat, lng });
|
|
7806
7867
|
}
|
|
@@ -7809,7 +7870,7 @@ var init_MapView = __esm({
|
|
|
7809
7870
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
7810
7871
|
}
|
|
7811
7872
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
7812
|
-
const handleMarkerClick =
|
|
7873
|
+
const handleMarkerClick = useCallback126((marker) => {
|
|
7813
7874
|
onMarkerClick?.(marker);
|
|
7814
7875
|
if (markerClickEvent) {
|
|
7815
7876
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -17801,7 +17862,7 @@ var init_CastleTemplate = __esm({
|
|
|
17801
17862
|
CastleTemplate.displayName = "CastleTemplate";
|
|
17802
17863
|
}
|
|
17803
17864
|
});
|
|
17804
|
-
var CHART_COLORS, BarChart, PieChart, LineChart; exports.Chart = void 0;
|
|
17865
|
+
var CHART_COLORS, seriesColor, monthFormatter, formatTimeLabel, BarChart, PieChart, LineChart, ScatterChart; exports.Chart = void 0;
|
|
17805
17866
|
var init_Chart = __esm({
|
|
17806
17867
|
"components/organisms/Chart.tsx"() {
|
|
17807
17868
|
"use client";
|
|
@@ -17821,38 +17882,159 @@ var init_Chart = __esm({
|
|
|
17821
17882
|
"var(--color-info)",
|
|
17822
17883
|
"var(--color-accent)"
|
|
17823
17884
|
];
|
|
17824
|
-
|
|
17825
|
-
|
|
17826
|
-
|
|
17827
|
-
|
|
17828
|
-
|
|
17829
|
-
|
|
17830
|
-
|
|
17831
|
-
|
|
17832
|
-
|
|
17833
|
-
|
|
17834
|
-
|
|
17835
|
-
|
|
17836
|
-
|
|
17837
|
-
|
|
17838
|
-
|
|
17839
|
-
|
|
17840
|
-
|
|
17885
|
+
seriesColor = (series, idx) => series.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
17886
|
+
monthFormatter = new Intl.DateTimeFormat(void 0, {
|
|
17887
|
+
month: "short",
|
|
17888
|
+
year: "2-digit"
|
|
17889
|
+
});
|
|
17890
|
+
formatTimeLabel = (raw) => {
|
|
17891
|
+
const parsed = new Date(raw);
|
|
17892
|
+
if (Number.isNaN(parsed.getTime())) return raw;
|
|
17893
|
+
return monthFormatter.format(parsed);
|
|
17894
|
+
};
|
|
17895
|
+
BarChart = ({ series, height, showValues, stack, timeAxis, histogram = false, onPointClick }) => {
|
|
17896
|
+
const categories = React75.useMemo(() => {
|
|
17897
|
+
const set = [];
|
|
17898
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17899
|
+
for (const s of series) {
|
|
17900
|
+
for (const p2 of s.data) {
|
|
17901
|
+
if (!seen.has(p2.label)) {
|
|
17902
|
+
seen.add(p2.label);
|
|
17903
|
+
set.push(p2.label);
|
|
17841
17904
|
}
|
|
17842
|
-
|
|
17843
|
-
|
|
17844
|
-
|
|
17845
|
-
|
|
17846
|
-
|
|
17847
|
-
|
|
17848
|
-
|
|
17849
|
-
|
|
17905
|
+
}
|
|
17906
|
+
}
|
|
17907
|
+
return set;
|
|
17908
|
+
}, [series]);
|
|
17909
|
+
const valueAt = React75.useCallback(
|
|
17910
|
+
(s, label) => {
|
|
17911
|
+
const p2 = s.data.find((d) => d.label === label);
|
|
17912
|
+
return p2 ? p2.value : 0;
|
|
17913
|
+
},
|
|
17914
|
+
[]
|
|
17915
|
+
);
|
|
17916
|
+
const columnTotals = React75.useMemo(() => {
|
|
17917
|
+
if (stack === "none") return null;
|
|
17918
|
+
return categories.map(
|
|
17919
|
+
(label) => series.reduce((sum, s) => sum + valueAt(s, label), 0)
|
|
17920
|
+
);
|
|
17921
|
+
}, [categories, series, stack, valueAt]);
|
|
17922
|
+
const maxValue = React75.useMemo(() => {
|
|
17923
|
+
if (stack === "normalize") return 100;
|
|
17924
|
+
if (stack === "stack" && columnTotals) {
|
|
17925
|
+
return Math.max(...columnTotals, 1);
|
|
17926
|
+
}
|
|
17927
|
+
let m = 1;
|
|
17928
|
+
for (const s of series) {
|
|
17929
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
17930
|
+
}
|
|
17931
|
+
return m;
|
|
17932
|
+
}, [series, stack, columnTotals]);
|
|
17933
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17934
|
+
exports.HStack,
|
|
17935
|
+
{
|
|
17936
|
+
gap: histogram ? "none" : "xs",
|
|
17937
|
+
align: "end",
|
|
17938
|
+
className: "w-full",
|
|
17939
|
+
style: { height },
|
|
17940
|
+
children: categories.map((label, catIdx) => {
|
|
17941
|
+
const displayLabel = timeAxis ? formatTimeLabel(label) : label;
|
|
17942
|
+
if (stack === "none") {
|
|
17943
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17944
|
+
exports.VStack,
|
|
17945
|
+
{
|
|
17946
|
+
gap: "xs",
|
|
17947
|
+
align: "center",
|
|
17948
|
+
flex: true,
|
|
17949
|
+
className: "min-w-0",
|
|
17950
|
+
children: [
|
|
17951
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: histogram ? "none" : "xs", align: "end", className: "w-full", style: { height: "100%" }, children: series.map((s, sIdx) => {
|
|
17952
|
+
const value = valueAt(s, label);
|
|
17953
|
+
const barHeight = value / maxValue * 100;
|
|
17954
|
+
const color = seriesColor(s, sIdx);
|
|
17955
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17956
|
+
exports.Box,
|
|
17957
|
+
{
|
|
17958
|
+
className: cn(
|
|
17959
|
+
"rounded-t-sm transition-all duration-500 ease-out min-h-[4px] cursor-pointer hover:opacity-80",
|
|
17960
|
+
histogram ? "flex-1 mx-0" : "flex-1"
|
|
17961
|
+
),
|
|
17962
|
+
style: {
|
|
17963
|
+
height: `${barHeight}%`,
|
|
17964
|
+
backgroundColor: color
|
|
17965
|
+
},
|
|
17966
|
+
onClick: () => onPointClick?.(
|
|
17967
|
+
{ label, value, color },
|
|
17968
|
+
s.name
|
|
17969
|
+
),
|
|
17970
|
+
title: `${s.name}: ${value}`
|
|
17971
|
+
},
|
|
17972
|
+
s.name
|
|
17973
|
+
);
|
|
17974
|
+
}) }),
|
|
17975
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", className: "tabular-nums", children: valueAt(series[0], label) }),
|
|
17976
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17977
|
+
exports.Typography,
|
|
17978
|
+
{
|
|
17979
|
+
variant: "caption",
|
|
17980
|
+
color: "secondary",
|
|
17981
|
+
className: "truncate w-full text-center",
|
|
17982
|
+
children: displayLabel
|
|
17983
|
+
}
|
|
17984
|
+
)
|
|
17985
|
+
]
|
|
17986
|
+
},
|
|
17987
|
+
label
|
|
17988
|
+
);
|
|
17850
17989
|
}
|
|
17851
|
-
|
|
17852
|
-
|
|
17853
|
-
|
|
17990
|
+
const total = columnTotals?.[catIdx] ?? 1;
|
|
17991
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
17992
|
+
exports.VStack,
|
|
17993
|
+
{
|
|
17994
|
+
gap: "xs",
|
|
17995
|
+
align: "center",
|
|
17996
|
+
flex: true,
|
|
17997
|
+
className: "min-w-0",
|
|
17998
|
+
children: [
|
|
17999
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.VStack, { gap: "none", className: "w-full", style: { height: "100%" }, justify: "end", children: series.map((s, sIdx) => {
|
|
18000
|
+
const value = valueAt(s, label);
|
|
18001
|
+
const ratio = stack === "normalize" ? total === 0 ? 0 : value / total * 100 : value / maxValue * 100;
|
|
18002
|
+
const color = seriesColor(s, sIdx);
|
|
18003
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18004
|
+
exports.Box,
|
|
18005
|
+
{
|
|
18006
|
+
className: "w-full transition-all duration-500 ease-out cursor-pointer hover:opacity-80",
|
|
18007
|
+
style: {
|
|
18008
|
+
height: `${ratio}%`,
|
|
18009
|
+
backgroundColor: color
|
|
18010
|
+
},
|
|
18011
|
+
onClick: () => onPointClick?.(
|
|
18012
|
+
{ label, value, color },
|
|
18013
|
+
s.name
|
|
18014
|
+
),
|
|
18015
|
+
title: `${s.name}: ${value}`
|
|
18016
|
+
},
|
|
18017
|
+
s.name
|
|
18018
|
+
);
|
|
18019
|
+
}) }),
|
|
18020
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18021
|
+
exports.Typography,
|
|
18022
|
+
{
|
|
18023
|
+
variant: "caption",
|
|
18024
|
+
color: "secondary",
|
|
18025
|
+
className: "truncate w-full text-center",
|
|
18026
|
+
children: displayLabel
|
|
18027
|
+
}
|
|
18028
|
+
)
|
|
18029
|
+
]
|
|
18030
|
+
},
|
|
18031
|
+
label
|
|
18032
|
+
);
|
|
18033
|
+
})
|
|
18034
|
+
}
|
|
18035
|
+
);
|
|
17854
18036
|
};
|
|
17855
|
-
PieChart = ({ data, height, showValues, donut = false }) => {
|
|
18037
|
+
PieChart = ({ data, height, showValues, donut = false, onPointClick }) => {
|
|
17856
18038
|
const total = data.reduce((sum, d) => sum + d.value, 0);
|
|
17857
18039
|
const size = Math.min(height, 200);
|
|
17858
18040
|
const radius = size / 2 - 8;
|
|
@@ -17898,7 +18080,11 @@ var init_Chart = __esm({
|
|
|
17898
18080
|
fill: seg.color,
|
|
17899
18081
|
stroke: "var(--color-card)",
|
|
17900
18082
|
strokeWidth: "2",
|
|
17901
|
-
className: "transition-opacity duration-200 hover:opacity-80"
|
|
18083
|
+
className: "transition-opacity duration-200 hover:opacity-80 cursor-pointer",
|
|
18084
|
+
onClick: () => onPointClick?.(
|
|
18085
|
+
{ label: seg.label, value: seg.value, color: seg.color },
|
|
18086
|
+
"default"
|
|
18087
|
+
)
|
|
17902
18088
|
},
|
|
17903
18089
|
idx
|
|
17904
18090
|
)),
|
|
@@ -17933,56 +18119,243 @@ var init_Chart = __esm({
|
|
|
17933
18119
|
] }, idx)) })
|
|
17934
18120
|
] });
|
|
17935
18121
|
};
|
|
17936
|
-
LineChart = ({
|
|
17937
|
-
const maxValue = Math.max(...data.map((d) => d.value), 1);
|
|
18122
|
+
LineChart = ({ series, height, showValues, fill = false, timeAxis, onPointClick }) => {
|
|
17938
18123
|
const width = 400;
|
|
17939
18124
|
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
17940
18125
|
const chartWidth = width - padding.left - padding.right;
|
|
17941
18126
|
const chartHeight = height - padding.top - padding.bottom;
|
|
17942
|
-
const
|
|
17943
|
-
|
|
17944
|
-
|
|
17945
|
-
|
|
17946
|
-
|
|
17947
|
-
|
|
17948
|
-
|
|
17949
|
-
|
|
17950
|
-
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
17951
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "100%", height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", children: [
|
|
17952
|
-
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
17953
|
-
const y = padding.top + chartHeight * (1 - frac);
|
|
17954
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
17955
|
-
"line",
|
|
17956
|
-
{
|
|
17957
|
-
x1: padding.left,
|
|
17958
|
-
y1: y,
|
|
17959
|
-
x2: width - padding.right,
|
|
17960
|
-
y2: y,
|
|
17961
|
-
stroke: "var(--color-border)",
|
|
17962
|
-
strokeDasharray: "4 4",
|
|
17963
|
-
opacity: 0.5
|
|
17964
|
-
},
|
|
17965
|
-
frac
|
|
17966
|
-
);
|
|
17967
|
-
}),
|
|
17968
|
-
fill && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: "var(--color-primary)", opacity: 0.1 }),
|
|
17969
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: linePath, fill: "none", stroke: "var(--color-primary)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
17970
|
-
points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
17971
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: p2.x, cy: p2.y, r: "4", fill: "var(--color-card)", stroke: "var(--color-primary)", strokeWidth: "2" }),
|
|
17972
|
-
showValues && /* @__PURE__ */ jsxRuntime.jsx("text", { x: p2.x, y: p2.y - 10, textAnchor: "middle", fill: "var(--color-foreground)", fontSize: "10", fontWeight: "500", children: p2.value }),
|
|
17973
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
17974
|
-
"text",
|
|
17975
|
-
{
|
|
17976
|
-
x: p2.x,
|
|
17977
|
-
y: height - 8,
|
|
17978
|
-
textAnchor: "middle",
|
|
17979
|
-
fill: "var(--color-muted-foreground)",
|
|
17980
|
-
fontSize: "9",
|
|
17981
|
-
children: p2.label
|
|
18127
|
+
const labels = React75.useMemo(() => {
|
|
18128
|
+
const seen = /* @__PURE__ */ new Set();
|
|
18129
|
+
const out = [];
|
|
18130
|
+
for (const s of series) {
|
|
18131
|
+
for (const p2 of s.data) {
|
|
18132
|
+
if (!seen.has(p2.label)) {
|
|
18133
|
+
seen.add(p2.label);
|
|
18134
|
+
out.push(p2.label);
|
|
17982
18135
|
}
|
|
17983
|
-
|
|
17984
|
-
|
|
17985
|
-
|
|
18136
|
+
}
|
|
18137
|
+
}
|
|
18138
|
+
return out;
|
|
18139
|
+
}, [series]);
|
|
18140
|
+
const maxValue = React75.useMemo(() => {
|
|
18141
|
+
let m = 1;
|
|
18142
|
+
for (const s of series) {
|
|
18143
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
18144
|
+
}
|
|
18145
|
+
return m;
|
|
18146
|
+
}, [series]);
|
|
18147
|
+
const xFor = React75.useCallback(
|
|
18148
|
+
(idx) => padding.left + idx / Math.max(labels.length - 1, 1) * chartWidth,
|
|
18149
|
+
[labels.length, chartWidth, padding.left]
|
|
18150
|
+
);
|
|
18151
|
+
const yFor = React75.useCallback(
|
|
18152
|
+
(value) => padding.top + chartHeight - value / maxValue * chartHeight,
|
|
18153
|
+
[maxValue, chartHeight, padding.top]
|
|
18154
|
+
);
|
|
18155
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18156
|
+
"svg",
|
|
18157
|
+
{
|
|
18158
|
+
width: "100%",
|
|
18159
|
+
height,
|
|
18160
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
18161
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
18162
|
+
children: [
|
|
18163
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
18164
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
18165
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18166
|
+
"line",
|
|
18167
|
+
{
|
|
18168
|
+
x1: padding.left,
|
|
18169
|
+
y1: y,
|
|
18170
|
+
x2: width - padding.right,
|
|
18171
|
+
y2: y,
|
|
18172
|
+
stroke: "var(--color-border)",
|
|
18173
|
+
strokeDasharray: "4 4",
|
|
18174
|
+
opacity: 0.5
|
|
18175
|
+
},
|
|
18176
|
+
frac
|
|
18177
|
+
);
|
|
18178
|
+
}),
|
|
18179
|
+
series.map((s, sIdx) => {
|
|
18180
|
+
const color = seriesColor(s, sIdx);
|
|
18181
|
+
const points = labels.map((label, idx) => {
|
|
18182
|
+
const point = s.data.find((d) => d.label === label);
|
|
18183
|
+
return {
|
|
18184
|
+
x: xFor(idx),
|
|
18185
|
+
y: yFor(point ? point.value : 0),
|
|
18186
|
+
value: point ? point.value : 0,
|
|
18187
|
+
label
|
|
18188
|
+
};
|
|
18189
|
+
});
|
|
18190
|
+
const linePath = points.map((p2, i) => `${i === 0 ? "M" : "L"} ${p2.x} ${p2.y}`).join(" ");
|
|
18191
|
+
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
18192
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
18193
|
+
fill && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18194
|
+
"path",
|
|
18195
|
+
{
|
|
18196
|
+
d: areaPath,
|
|
18197
|
+
fill: color,
|
|
18198
|
+
opacity: series.length > 1 ? 0.08 : 0.1
|
|
18199
|
+
}
|
|
18200
|
+
),
|
|
18201
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18202
|
+
"path",
|
|
18203
|
+
{
|
|
18204
|
+
d: linePath,
|
|
18205
|
+
fill: "none",
|
|
18206
|
+
stroke: color,
|
|
18207
|
+
strokeWidth: "2",
|
|
18208
|
+
strokeLinecap: "round",
|
|
18209
|
+
strokeLinejoin: "round",
|
|
18210
|
+
strokeDasharray: s.dashed ? "6 4" : void 0
|
|
18211
|
+
}
|
|
18212
|
+
),
|
|
18213
|
+
points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
18214
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18215
|
+
"circle",
|
|
18216
|
+
{
|
|
18217
|
+
cx: p2.x,
|
|
18218
|
+
cy: p2.y,
|
|
18219
|
+
r: "4",
|
|
18220
|
+
fill: "var(--color-card)",
|
|
18221
|
+
stroke: color,
|
|
18222
|
+
strokeWidth: "2",
|
|
18223
|
+
className: "cursor-pointer",
|
|
18224
|
+
onClick: () => onPointClick?.(
|
|
18225
|
+
{ label: p2.label, value: p2.value, color },
|
|
18226
|
+
s.name
|
|
18227
|
+
)
|
|
18228
|
+
}
|
|
18229
|
+
),
|
|
18230
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18231
|
+
"text",
|
|
18232
|
+
{
|
|
18233
|
+
x: p2.x,
|
|
18234
|
+
y: p2.y - 10,
|
|
18235
|
+
textAnchor: "middle",
|
|
18236
|
+
fill: "var(--color-foreground)",
|
|
18237
|
+
fontSize: "10",
|
|
18238
|
+
fontWeight: "500",
|
|
18239
|
+
children: p2.value
|
|
18240
|
+
}
|
|
18241
|
+
)
|
|
18242
|
+
] }, idx))
|
|
18243
|
+
] }, s.name);
|
|
18244
|
+
}),
|
|
18245
|
+
labels.map((label, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
18246
|
+
"text",
|
|
18247
|
+
{
|
|
18248
|
+
x: xFor(idx),
|
|
18249
|
+
y: height - 8,
|
|
18250
|
+
textAnchor: "middle",
|
|
18251
|
+
fill: "var(--color-muted-foreground)",
|
|
18252
|
+
fontSize: "9",
|
|
18253
|
+
children: timeAxis ? formatTimeLabel(label) : label
|
|
18254
|
+
},
|
|
18255
|
+
label
|
|
18256
|
+
))
|
|
18257
|
+
]
|
|
18258
|
+
}
|
|
18259
|
+
);
|
|
18260
|
+
};
|
|
18261
|
+
ScatterChart = ({ data, height, onPointClick }) => {
|
|
18262
|
+
const width = 400;
|
|
18263
|
+
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
18264
|
+
const chartWidth = width - padding.left - padding.right;
|
|
18265
|
+
const chartHeight = height - padding.top - padding.bottom;
|
|
18266
|
+
const { minX, maxX, minY, maxY } = React75.useMemo(() => {
|
|
18267
|
+
if (data.length === 0) {
|
|
18268
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
18269
|
+
}
|
|
18270
|
+
let mnX = data[0].x;
|
|
18271
|
+
let mxX = data[0].x;
|
|
18272
|
+
let mnY = data[0].y;
|
|
18273
|
+
let mxY = data[0].y;
|
|
18274
|
+
for (const p2 of data) {
|
|
18275
|
+
if (p2.x < mnX) mnX = p2.x;
|
|
18276
|
+
if (p2.x > mxX) mxX = p2.x;
|
|
18277
|
+
if (p2.y < mnY) mnY = p2.y;
|
|
18278
|
+
if (p2.y > mxY) mxY = p2.y;
|
|
18279
|
+
}
|
|
18280
|
+
return { minX: mnX, maxX: mxX, minY: mnY, maxY: mxY };
|
|
18281
|
+
}, [data]);
|
|
18282
|
+
const rangeX = maxX - minX || 1;
|
|
18283
|
+
const rangeY = maxY - minY || 1;
|
|
18284
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
18285
|
+
"svg",
|
|
18286
|
+
{
|
|
18287
|
+
width: "100%",
|
|
18288
|
+
height,
|
|
18289
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
18290
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
18291
|
+
children: [
|
|
18292
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
18293
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
18294
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18295
|
+
"line",
|
|
18296
|
+
{
|
|
18297
|
+
x1: padding.left,
|
|
18298
|
+
y1: y,
|
|
18299
|
+
x2: width - padding.right,
|
|
18300
|
+
y2: y,
|
|
18301
|
+
stroke: "var(--color-border)",
|
|
18302
|
+
strokeDasharray: "4 4",
|
|
18303
|
+
opacity: 0.5
|
|
18304
|
+
},
|
|
18305
|
+
frac
|
|
18306
|
+
);
|
|
18307
|
+
}),
|
|
18308
|
+
data.map((p2, idx) => {
|
|
18309
|
+
const cx = padding.left + (p2.x - minX) / rangeX * chartWidth;
|
|
18310
|
+
const cy = padding.top + chartHeight - (p2.y - minY) / rangeY * chartHeight;
|
|
18311
|
+
const r = p2.size ?? 5;
|
|
18312
|
+
const color = p2.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
18313
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
18314
|
+
"circle",
|
|
18315
|
+
{
|
|
18316
|
+
cx,
|
|
18317
|
+
cy,
|
|
18318
|
+
r,
|
|
18319
|
+
fill: color,
|
|
18320
|
+
opacity: 0.7,
|
|
18321
|
+
className: "cursor-pointer hover:opacity-100",
|
|
18322
|
+
onClick: () => onPointClick?.(
|
|
18323
|
+
{
|
|
18324
|
+
label: p2.label ?? `(${p2.x}, ${p2.y})`,
|
|
18325
|
+
value: p2.y,
|
|
18326
|
+
color
|
|
18327
|
+
},
|
|
18328
|
+
"default"
|
|
18329
|
+
),
|
|
18330
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: p2.label ?? `(${p2.x}, ${p2.y})` })
|
|
18331
|
+
},
|
|
18332
|
+
idx
|
|
18333
|
+
);
|
|
18334
|
+
}),
|
|
18335
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18336
|
+
"text",
|
|
18337
|
+
{
|
|
18338
|
+
x: padding.left,
|
|
18339
|
+
y: height - 8,
|
|
18340
|
+
fill: "var(--color-muted-foreground)",
|
|
18341
|
+
fontSize: "9",
|
|
18342
|
+
children: minX.toFixed(1)
|
|
18343
|
+
}
|
|
18344
|
+
),
|
|
18345
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18346
|
+
"text",
|
|
18347
|
+
{
|
|
18348
|
+
x: width - padding.right,
|
|
18349
|
+
y: height - 8,
|
|
18350
|
+
textAnchor: "end",
|
|
18351
|
+
fill: "var(--color-muted-foreground)",
|
|
18352
|
+
fontSize: "9",
|
|
18353
|
+
children: maxX.toFixed(1)
|
|
18354
|
+
}
|
|
18355
|
+
)
|
|
18356
|
+
]
|
|
18357
|
+
}
|
|
18358
|
+
);
|
|
17986
18359
|
};
|
|
17987
18360
|
exports.Chart = ({
|
|
17988
18361
|
title,
|
|
@@ -17990,9 +18363,13 @@ var init_Chart = __esm({
|
|
|
17990
18363
|
chartType = "bar",
|
|
17991
18364
|
series,
|
|
17992
18365
|
data: simpleData,
|
|
18366
|
+
scatterData,
|
|
17993
18367
|
height = 200,
|
|
17994
18368
|
showLegend = true,
|
|
17995
18369
|
showValues = false,
|
|
18370
|
+
stack = "none",
|
|
18371
|
+
timeAxis = false,
|
|
18372
|
+
drillEvent,
|
|
17996
18373
|
actions,
|
|
17997
18374
|
entity,
|
|
17998
18375
|
isLoading = false,
|
|
@@ -18009,11 +18386,25 @@ var init_Chart = __esm({
|
|
|
18009
18386
|
},
|
|
18010
18387
|
[eventBus]
|
|
18011
18388
|
);
|
|
18012
|
-
const
|
|
18013
|
-
|
|
18014
|
-
|
|
18389
|
+
const handlePointClick = React75.useCallback(
|
|
18390
|
+
(point, seriesName) => {
|
|
18391
|
+
if (drillEvent) {
|
|
18392
|
+
eventBus.emit(`UI:${drillEvent}`, {
|
|
18393
|
+
label: point.label,
|
|
18394
|
+
value: point.value,
|
|
18395
|
+
seriesLabel: seriesName === "default" ? void 0 : seriesName
|
|
18396
|
+
});
|
|
18397
|
+
}
|
|
18398
|
+
},
|
|
18399
|
+
[drillEvent, eventBus]
|
|
18400
|
+
);
|
|
18401
|
+
const normalizedSeries = React75.useMemo(() => {
|
|
18402
|
+
if (series && series.length > 0) return series;
|
|
18403
|
+
if (simpleData) return [{ name: "default", data: simpleData }];
|
|
18015
18404
|
return [];
|
|
18016
18405
|
}, [simpleData, series]);
|
|
18406
|
+
const firstSeriesData = normalizedSeries[0]?.data ?? [];
|
|
18407
|
+
const hasContent = chartType === "scatter" ? (scatterData?.length ?? 0) > 0 : normalizedSeries.some((s) => s.data.length > 0);
|
|
18017
18408
|
if (isLoading) {
|
|
18018
18409
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.LoadingState, { message: "Loading chart...", className });
|
|
18019
18410
|
}
|
|
@@ -18027,7 +18418,7 @@ var init_Chart = __esm({
|
|
|
18027
18418
|
}
|
|
18028
18419
|
);
|
|
18029
18420
|
}
|
|
18030
|
-
if (
|
|
18421
|
+
if (!hasContent) {
|
|
18031
18422
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.EmptyState, { title: t("empty.noData"), description: t("empty.noData"), className });
|
|
18032
18423
|
}
|
|
18033
18424
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className: cn("p-6", className), children: /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "md", children: [
|
|
@@ -18048,18 +18439,84 @@ var init_Chart = __esm({
|
|
|
18048
18439
|
)) })
|
|
18049
18440
|
] }),
|
|
18050
18441
|
/* @__PURE__ */ jsxRuntime.jsxs(exports.Box, { className: "w-full", children: [
|
|
18051
|
-
chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18052
|
-
|
|
18053
|
-
|
|
18054
|
-
|
|
18055
|
-
|
|
18442
|
+
chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18443
|
+
BarChart,
|
|
18444
|
+
{
|
|
18445
|
+
series: normalizedSeries,
|
|
18446
|
+
height,
|
|
18447
|
+
showValues,
|
|
18448
|
+
stack,
|
|
18449
|
+
timeAxis,
|
|
18450
|
+
onPointClick: handlePointClick
|
|
18451
|
+
}
|
|
18452
|
+
),
|
|
18453
|
+
chartType === "histogram" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18454
|
+
BarChart,
|
|
18455
|
+
{
|
|
18456
|
+
series: normalizedSeries,
|
|
18457
|
+
height,
|
|
18458
|
+
showValues,
|
|
18459
|
+
stack: "none",
|
|
18460
|
+
timeAxis: false,
|
|
18461
|
+
histogram: true,
|
|
18462
|
+
onPointClick: handlePointClick
|
|
18463
|
+
}
|
|
18464
|
+
),
|
|
18465
|
+
chartType === "line" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18466
|
+
LineChart,
|
|
18467
|
+
{
|
|
18468
|
+
series: normalizedSeries,
|
|
18469
|
+
height,
|
|
18470
|
+
showValues,
|
|
18471
|
+
timeAxis,
|
|
18472
|
+
onPointClick: handlePointClick
|
|
18473
|
+
}
|
|
18474
|
+
),
|
|
18475
|
+
chartType === "area" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18476
|
+
LineChart,
|
|
18477
|
+
{
|
|
18478
|
+
series: normalizedSeries,
|
|
18479
|
+
height,
|
|
18480
|
+
showValues,
|
|
18481
|
+
timeAxis,
|
|
18482
|
+
fill: true,
|
|
18483
|
+
onPointClick: handlePointClick
|
|
18484
|
+
}
|
|
18485
|
+
),
|
|
18486
|
+
chartType === "pie" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18487
|
+
PieChart,
|
|
18488
|
+
{
|
|
18489
|
+
data: firstSeriesData,
|
|
18490
|
+
height,
|
|
18491
|
+
showValues: showLegend,
|
|
18492
|
+
onPointClick: handlePointClick
|
|
18493
|
+
}
|
|
18494
|
+
),
|
|
18495
|
+
chartType === "donut" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18496
|
+
PieChart,
|
|
18497
|
+
{
|
|
18498
|
+
data: firstSeriesData,
|
|
18499
|
+
height,
|
|
18500
|
+
showValues: showLegend,
|
|
18501
|
+
donut: true,
|
|
18502
|
+
onPointClick: handlePointClick
|
|
18503
|
+
}
|
|
18504
|
+
),
|
|
18505
|
+
chartType === "scatter" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
18506
|
+
ScatterChart,
|
|
18507
|
+
{
|
|
18508
|
+
data: scatterData ?? [],
|
|
18509
|
+
height,
|
|
18510
|
+
onPointClick: handlePointClick
|
|
18511
|
+
}
|
|
18512
|
+
)
|
|
18056
18513
|
] }),
|
|
18057
|
-
showLegend &&
|
|
18514
|
+
showLegend && normalizedSeries.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "md", justify: "center", wrap: true, children: normalizedSeries.map((s, idx) => /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "xs", align: "center", children: [
|
|
18058
18515
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
18059
18516
|
exports.Box,
|
|
18060
18517
|
{
|
|
18061
18518
|
className: "w-3 h-3 rounded-full flex-shrink-0",
|
|
18062
|
-
style: { backgroundColor: s
|
|
18519
|
+
style: { backgroundColor: seriesColor(s, idx) }
|
|
18063
18520
|
}
|
|
18064
18521
|
),
|
|
18065
18522
|
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: s.name })
|
|
@@ -23214,6 +23671,151 @@ var init_FlipCard = __esm({
|
|
|
23214
23671
|
exports.FlipCard.displayName = "FlipCard";
|
|
23215
23672
|
}
|
|
23216
23673
|
});
|
|
23674
|
+
function toISODate(d) {
|
|
23675
|
+
return d.toISOString().slice(0, 10);
|
|
23676
|
+
}
|
|
23677
|
+
function startOfMonth(d) {
|
|
23678
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
23679
|
+
}
|
|
23680
|
+
function startOfQuarter(d) {
|
|
23681
|
+
return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
|
|
23682
|
+
}
|
|
23683
|
+
function startOfYear(d) {
|
|
23684
|
+
return new Date(d.getFullYear(), 0, 1);
|
|
23685
|
+
}
|
|
23686
|
+
function daysAgo(n) {
|
|
23687
|
+
const d = /* @__PURE__ */ new Date();
|
|
23688
|
+
d.setDate(d.getDate() - n);
|
|
23689
|
+
return d;
|
|
23690
|
+
}
|
|
23691
|
+
var DEFAULT_PRESETS; exports.DateRangePicker = void 0;
|
|
23692
|
+
var init_DateRangePicker = __esm({
|
|
23693
|
+
"components/molecules/DateRangePicker.tsx"() {
|
|
23694
|
+
"use client";
|
|
23695
|
+
init_cn();
|
|
23696
|
+
init_Button();
|
|
23697
|
+
init_Input();
|
|
23698
|
+
init_Stack();
|
|
23699
|
+
init_Typography();
|
|
23700
|
+
init_useEventBus();
|
|
23701
|
+
DEFAULT_PRESETS = [
|
|
23702
|
+
{
|
|
23703
|
+
label: "Last 7 days",
|
|
23704
|
+
value: "7d",
|
|
23705
|
+
range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
23706
|
+
},
|
|
23707
|
+
{
|
|
23708
|
+
label: "Last 30 days",
|
|
23709
|
+
value: "30d",
|
|
23710
|
+
range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
23711
|
+
},
|
|
23712
|
+
{
|
|
23713
|
+
label: "This Month",
|
|
23714
|
+
value: "month",
|
|
23715
|
+
range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
23716
|
+
},
|
|
23717
|
+
{
|
|
23718
|
+
label: "This Quarter",
|
|
23719
|
+
value: "quarter",
|
|
23720
|
+
range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
23721
|
+
},
|
|
23722
|
+
{
|
|
23723
|
+
label: "YTD",
|
|
23724
|
+
value: "ytd",
|
|
23725
|
+
range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
23726
|
+
}
|
|
23727
|
+
];
|
|
23728
|
+
exports.DateRangePicker = ({
|
|
23729
|
+
from: fromProp,
|
|
23730
|
+
to: toProp,
|
|
23731
|
+
event,
|
|
23732
|
+
onChange,
|
|
23733
|
+
presets = DEFAULT_PRESETS,
|
|
23734
|
+
fromLabel = "From",
|
|
23735
|
+
toLabel = "To",
|
|
23736
|
+
className
|
|
23737
|
+
}) => {
|
|
23738
|
+
const eventBus = useEventBus();
|
|
23739
|
+
const [from, setFrom] = React75.useState(fromProp ?? "");
|
|
23740
|
+
const [to, setTo] = React75.useState(toProp ?? "");
|
|
23741
|
+
const [activePreset, setActivePreset] = React75.useState(null);
|
|
23742
|
+
const emit = React75.useCallback(
|
|
23743
|
+
(range) => {
|
|
23744
|
+
onChange?.(range);
|
|
23745
|
+
if (event) eventBus.emit(`UI:${event}`, range);
|
|
23746
|
+
},
|
|
23747
|
+
[onChange, event, eventBus]
|
|
23748
|
+
);
|
|
23749
|
+
const handleFromChange = React75.useCallback(
|
|
23750
|
+
(next) => {
|
|
23751
|
+
setFrom(next);
|
|
23752
|
+
setActivePreset(null);
|
|
23753
|
+
emit({ from: next, to });
|
|
23754
|
+
},
|
|
23755
|
+
[to, emit]
|
|
23756
|
+
);
|
|
23757
|
+
const handleToChange = React75.useCallback(
|
|
23758
|
+
(next) => {
|
|
23759
|
+
setTo(next);
|
|
23760
|
+
setActivePreset(null);
|
|
23761
|
+
emit({ from, to: next });
|
|
23762
|
+
},
|
|
23763
|
+
[from, emit]
|
|
23764
|
+
);
|
|
23765
|
+
const handlePreset = React75.useCallback(
|
|
23766
|
+
(preset) => {
|
|
23767
|
+
const range = preset.range();
|
|
23768
|
+
setFrom(range.from);
|
|
23769
|
+
setTo(range.to);
|
|
23770
|
+
setActivePreset(preset.value);
|
|
23771
|
+
emit(range);
|
|
23772
|
+
},
|
|
23773
|
+
[emit]
|
|
23774
|
+
);
|
|
23775
|
+
const presetButtons = React75.useMemo(
|
|
23776
|
+
() => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23777
|
+
exports.Button,
|
|
23778
|
+
{
|
|
23779
|
+
variant: activePreset === preset.value ? "primary" : "ghost",
|
|
23780
|
+
size: "sm",
|
|
23781
|
+
onClick: () => handlePreset(preset),
|
|
23782
|
+
children: preset.label
|
|
23783
|
+
},
|
|
23784
|
+
preset.value
|
|
23785
|
+
)),
|
|
23786
|
+
[presets, activePreset, handlePreset]
|
|
23787
|
+
);
|
|
23788
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "sm", className: cn(className), children: [
|
|
23789
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "md", align: "end", children: [
|
|
23790
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", children: [
|
|
23791
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: fromLabel }),
|
|
23792
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23793
|
+
exports.Input,
|
|
23794
|
+
{
|
|
23795
|
+
type: "date",
|
|
23796
|
+
value: from,
|
|
23797
|
+
onChange: (e) => handleFromChange(e.target.value)
|
|
23798
|
+
}
|
|
23799
|
+
)
|
|
23800
|
+
] }),
|
|
23801
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", children: [
|
|
23802
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: toLabel }),
|
|
23803
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23804
|
+
exports.Input,
|
|
23805
|
+
{
|
|
23806
|
+
type: "date",
|
|
23807
|
+
value: to,
|
|
23808
|
+
onChange: (e) => handleToChange(e.target.value)
|
|
23809
|
+
}
|
|
23810
|
+
)
|
|
23811
|
+
] })
|
|
23812
|
+
] }),
|
|
23813
|
+
presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(exports.HStack, { gap: "xs", wrap: true, children: presetButtons })
|
|
23814
|
+
] });
|
|
23815
|
+
};
|
|
23816
|
+
exports.DateRangePicker.displayName = "DateRangePicker";
|
|
23817
|
+
}
|
|
23818
|
+
});
|
|
23217
23819
|
var DEFAULT_OPTIONS; exports.DateRangeSelector = void 0;
|
|
23218
23820
|
var init_DateRangeSelector = __esm({
|
|
23219
23821
|
"components/molecules/DateRangeSelector.tsx"() {
|
|
@@ -26469,7 +27071,9 @@ var init_StatDisplay = __esm({
|
|
|
26469
27071
|
init_Typography();
|
|
26470
27072
|
init_Box();
|
|
26471
27073
|
init_Stack();
|
|
27074
|
+
init_Sparkline();
|
|
26472
27075
|
init_Icon();
|
|
27076
|
+
init_useEventBus();
|
|
26473
27077
|
variantColor = {
|
|
26474
27078
|
default: "text-foreground",
|
|
26475
27079
|
primary: "text-primary",
|
|
@@ -26484,6 +27088,10 @@ var init_StatDisplay = __esm({
|
|
|
26484
27088
|
max,
|
|
26485
27089
|
target,
|
|
26486
27090
|
trend,
|
|
27091
|
+
trendPolarity = "higher-is-better",
|
|
27092
|
+
trendFormat = "absolute",
|
|
27093
|
+
sparklineData,
|
|
27094
|
+
clickEvent,
|
|
26487
27095
|
prefix,
|
|
26488
27096
|
suffix,
|
|
26489
27097
|
icon: iconProp,
|
|
@@ -26497,6 +27105,10 @@ var init_StatDisplay = __esm({
|
|
|
26497
27105
|
isLoading = false,
|
|
26498
27106
|
error = null
|
|
26499
27107
|
}) => {
|
|
27108
|
+
const eventBus = useEventBus();
|
|
27109
|
+
const handleClick = React75.useCallback(() => {
|
|
27110
|
+
if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
|
|
27111
|
+
}, [clickEvent, eventBus, label]);
|
|
26500
27112
|
const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
|
|
26501
27113
|
const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
|
|
26502
27114
|
const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
|
|
@@ -26507,7 +27119,10 @@ var init_StatDisplay = __esm({
|
|
|
26507
27119
|
const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
|
|
26508
27120
|
const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
|
|
26509
27121
|
const trendUp = showTrend && trend > 0;
|
|
26510
|
-
const
|
|
27122
|
+
const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
|
|
27123
|
+
const trendMagnitude = Math.abs(trend);
|
|
27124
|
+
const trendSuffix = trendFormat === "percent" ? "%" : "";
|
|
27125
|
+
const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
|
|
26511
27126
|
if (error) {
|
|
26512
27127
|
return /* @__PURE__ */ jsxRuntime.jsx(exports.Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "small", color: "error", children: error.message }) });
|
|
26513
27128
|
}
|
|
@@ -26518,38 +27133,57 @@ var init_StatDisplay = __esm({
|
|
|
26518
27133
|
] }) });
|
|
26519
27134
|
}
|
|
26520
27135
|
if (compact) {
|
|
26521
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
26522
|
-
|
|
26523
|
-
|
|
26524
|
-
|
|
26525
|
-
|
|
26526
|
-
|
|
26527
|
-
|
|
27136
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
27137
|
+
exports.HStack,
|
|
27138
|
+
{
|
|
27139
|
+
gap: "sm",
|
|
27140
|
+
className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
|
|
27141
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
27142
|
+
children: [
|
|
27143
|
+
ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
|
|
27144
|
+
typeof iconProp !== "string" && iconProp,
|
|
27145
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", color: "secondary", children: label }),
|
|
27146
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
27147
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
|
|
27148
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(exports.Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
|
|
27149
|
+
]
|
|
27150
|
+
}
|
|
27151
|
+
);
|
|
26528
27152
|
}
|
|
26529
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
26530
|
-
|
|
26531
|
-
|
|
26532
|
-
|
|
26533
|
-
|
|
26534
|
-
|
|
26535
|
-
|
|
26536
|
-
{
|
|
26537
|
-
|
|
26538
|
-
className: cn("font-
|
|
26539
|
-
|
|
26540
|
-
|
|
26541
|
-
|
|
26542
|
-
|
|
26543
|
-
|
|
26544
|
-
|
|
26545
|
-
|
|
26546
|
-
|
|
26547
|
-
|
|
26548
|
-
|
|
26549
|
-
|
|
26550
|
-
|
|
26551
|
-
|
|
26552
|
-
|
|
27153
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27154
|
+
exports.Card,
|
|
27155
|
+
{
|
|
27156
|
+
className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
|
|
27157
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
27158
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { align: "start", justify: "between", children: [
|
|
27159
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "none", className: "space-y-1 flex-1", children: [
|
|
27160
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "overline", color: "secondary", children: label }),
|
|
27161
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.HStack, { gap: "sm", align: "end", children: [
|
|
27162
|
+
/* @__PURE__ */ jsxRuntime.jsx(exports.Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
27163
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(
|
|
27164
|
+
exports.Typography,
|
|
27165
|
+
{
|
|
27166
|
+
variant: "caption",
|
|
27167
|
+
className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
|
|
27168
|
+
children: trendLabel
|
|
27169
|
+
}
|
|
27170
|
+
)
|
|
27171
|
+
] }),
|
|
27172
|
+
showTarget && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
27173
|
+
exports.Box,
|
|
27174
|
+
{
|
|
27175
|
+
className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
|
|
27176
|
+
style: { width: `${targetPct}%` }
|
|
27177
|
+
}
|
|
27178
|
+
) })
|
|
27179
|
+
] }),
|
|
27180
|
+
/* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", align: "end", children: [
|
|
27181
|
+
(ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }) : iconProp }),
|
|
27182
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(exports.Sparkline, { data: sparklineData, color: "auto" })
|
|
27183
|
+
] })
|
|
27184
|
+
] })
|
|
27185
|
+
}
|
|
27186
|
+
);
|
|
26553
27187
|
};
|
|
26554
27188
|
exports.StatDisplay.displayName = "StatDisplay";
|
|
26555
27189
|
}
|
|
@@ -31898,6 +32532,7 @@ var init_molecules = __esm({
|
|
|
31898
32532
|
init_ViolationAlert();
|
|
31899
32533
|
init_FormSectionHeader();
|
|
31900
32534
|
init_FlipCard();
|
|
32535
|
+
init_DateRangePicker();
|
|
31901
32536
|
init_DateRangeSelector();
|
|
31902
32537
|
init_ChartLegend();
|
|
31903
32538
|
init_LineChart();
|
|
@@ -41454,6 +42089,7 @@ var init_StatCard = __esm({
|
|
|
41454
42089
|
init_Box();
|
|
41455
42090
|
init_Stack();
|
|
41456
42091
|
init_Button();
|
|
42092
|
+
init_Sparkline();
|
|
41457
42093
|
init_useEventBus();
|
|
41458
42094
|
init_useTranslate();
|
|
41459
42095
|
init_Icon();
|
|
@@ -41623,32 +42259,7 @@ var init_StatCard = __esm({
|
|
|
41623
42259
|
] }),
|
|
41624
42260
|
/* @__PURE__ */ jsxRuntime.jsxs(exports.VStack, { gap: "xs", align: "end", children: [
|
|
41625
42261
|
Icon3 && /* @__PURE__ */ jsxRuntime.jsx(exports.Box, { className: cn("p-3", iconBg), children: /* @__PURE__ */ jsxRuntime.jsx(Icon3, { className: cn("h-6 w-6", iconColor) }) }),
|
|
41626
|
-
sparklineData && sparklineData.length > 1 && (
|
|
41627
|
-
const w = 80;
|
|
41628
|
-
const h = 32;
|
|
41629
|
-
const pad = 2;
|
|
41630
|
-
const min = Math.min(...sparklineData);
|
|
41631
|
-
const max = Math.max(...sparklineData);
|
|
41632
|
-
const range = max - min || 1;
|
|
41633
|
-
const points = sparklineData.map((v, i) => {
|
|
41634
|
-
const x = pad + i / (sparklineData.length - 1) * (w - pad * 2);
|
|
41635
|
-
const y = pad + (1 - (v - min) / range) * (h - pad * 2);
|
|
41636
|
-
return `${x},${y}`;
|
|
41637
|
-
}).join(" ");
|
|
41638
|
-
const trending = sparklineData[sparklineData.length - 1] >= sparklineData[0];
|
|
41639
|
-
const strokeColor = trending ? "var(--color-success)" : "var(--color-error)";
|
|
41640
|
-
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w, height: h, viewBox: `0 0 ${w} ${h}`, className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
41641
|
-
"polyline",
|
|
41642
|
-
{
|
|
41643
|
-
fill: "none",
|
|
41644
|
-
stroke: strokeColor,
|
|
41645
|
-
strokeWidth: "2",
|
|
41646
|
-
strokeLinecap: "round",
|
|
41647
|
-
strokeLinejoin: "round",
|
|
41648
|
-
points
|
|
41649
|
-
}
|
|
41650
|
-
) });
|
|
41651
|
-
})()
|
|
42262
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(exports.Sparkline, { data: sparklineData, color: "auto" })
|
|
41652
42263
|
] })
|
|
41653
42264
|
] }),
|
|
41654
42265
|
action && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -43735,6 +44346,7 @@ var init_component_registry_generated = __esm({
|
|
|
43735
44346
|
init_DataGrid();
|
|
43736
44347
|
init_DataList();
|
|
43737
44348
|
init_DataTable();
|
|
44349
|
+
init_DateRangePicker();
|
|
43738
44350
|
init_DateRangeSelector();
|
|
43739
44351
|
init_DayCell();
|
|
43740
44352
|
init_DebuggerBoard();
|
|
@@ -43867,6 +44479,7 @@ var init_component_registry_generated = __esm({
|
|
|
43867
44479
|
init_Skeleton();
|
|
43868
44480
|
init_SocialProof();
|
|
43869
44481
|
init_SortableList();
|
|
44482
|
+
init_Sparkline();
|
|
43870
44483
|
init_Split();
|
|
43871
44484
|
init_SplitPane();
|
|
43872
44485
|
init_SplitSection();
|
|
@@ -44015,6 +44628,7 @@ var init_component_registry_generated = __esm({
|
|
|
44015
44628
|
"DataGrid": DataGrid,
|
|
44016
44629
|
"DataList": DataList,
|
|
44017
44630
|
"DataTable": DataTable,
|
|
44631
|
+
"DateRangePicker": exports.DateRangePicker,
|
|
44018
44632
|
"DateRangeSelector": exports.DateRangeSelector,
|
|
44019
44633
|
"DayCell": DayCell,
|
|
44020
44634
|
"DebuggerBoard": DebuggerBoard,
|
|
@@ -44176,6 +44790,7 @@ var init_component_registry_generated = __esm({
|
|
|
44176
44790
|
"SortableList": exports.SortableList,
|
|
44177
44791
|
"Spacer": SpacerPattern,
|
|
44178
44792
|
"SpacerPattern": SpacerPattern,
|
|
44793
|
+
"Sparkline": exports.Sparkline,
|
|
44179
44794
|
"Spinner": SpinnerPattern,
|
|
44180
44795
|
"SpinnerPattern": SpinnerPattern,
|
|
44181
44796
|
"Split": exports.Split,
|
|
@@ -45180,6 +45795,7 @@ var init_atoms = __esm({
|
|
|
45180
45795
|
init_Icon();
|
|
45181
45796
|
init_ProgressBar();
|
|
45182
45797
|
init_Radio();
|
|
45798
|
+
init_Sparkline();
|
|
45183
45799
|
init_Switch();
|
|
45184
45800
|
init_Spacer();
|
|
45185
45801
|
init_Stack();
|