@almadar/ui 4.51.14 → 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 +775 -150
- package/dist/avl/index.js +775 -150
- 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
package/dist/avl/index.js
CHANGED
|
@@ -8418,6 +8418,67 @@ var init_Radio = __esm({
|
|
|
8418
8418
|
Radio.displayName = "Radio";
|
|
8419
8419
|
}
|
|
8420
8420
|
});
|
|
8421
|
+
var COLOR_VAR, Sparkline;
|
|
8422
|
+
var init_Sparkline = __esm({
|
|
8423
|
+
"components/atoms/Sparkline.tsx"() {
|
|
8424
|
+
init_cn();
|
|
8425
|
+
COLOR_VAR = {
|
|
8426
|
+
primary: "var(--color-primary)",
|
|
8427
|
+
success: "var(--color-success)",
|
|
8428
|
+
warning: "var(--color-warning)",
|
|
8429
|
+
error: "var(--color-error)",
|
|
8430
|
+
info: "var(--color-info)",
|
|
8431
|
+
muted: "var(--color-muted-foreground)"
|
|
8432
|
+
};
|
|
8433
|
+
Sparkline = ({
|
|
8434
|
+
data,
|
|
8435
|
+
color = "auto",
|
|
8436
|
+
width = 80,
|
|
8437
|
+
height = 32,
|
|
8438
|
+
strokeWidth = 2,
|
|
8439
|
+
fill = false,
|
|
8440
|
+
className
|
|
8441
|
+
}) => {
|
|
8442
|
+
if (data.length < 2) return null;
|
|
8443
|
+
const pad = 2;
|
|
8444
|
+
const min = Math.min(...data);
|
|
8445
|
+
const max = Math.max(...data);
|
|
8446
|
+
const range = max - min || 1;
|
|
8447
|
+
const points = data.map((v, i) => {
|
|
8448
|
+
const x = pad + i / (data.length - 1) * (width - pad * 2);
|
|
8449
|
+
const y = pad + (1 - (v - min) / range) * (height - pad * 2);
|
|
8450
|
+
return `${x},${y}`;
|
|
8451
|
+
}).join(" ");
|
|
8452
|
+
const resolvedColor = color === "auto" ? data[data.length - 1] >= data[0] ? COLOR_VAR.success : COLOR_VAR.error : COLOR_VAR[color];
|
|
8453
|
+
const areaPath = fill ? `M ${pad},${height - pad} L ${points.split(" ").join(" L ")} L ${width - pad},${height - pad} Z` : null;
|
|
8454
|
+
return /* @__PURE__ */ jsxs(
|
|
8455
|
+
"svg",
|
|
8456
|
+
{
|
|
8457
|
+
width,
|
|
8458
|
+
height,
|
|
8459
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
8460
|
+
className: cn("flex-shrink-0", className),
|
|
8461
|
+
"aria-hidden": "true",
|
|
8462
|
+
children: [
|
|
8463
|
+
areaPath && /* @__PURE__ */ jsx("path", { d: areaPath, fill: resolvedColor, opacity: 0.15 }),
|
|
8464
|
+
/* @__PURE__ */ jsx(
|
|
8465
|
+
"polyline",
|
|
8466
|
+
{
|
|
8467
|
+
fill: "none",
|
|
8468
|
+
stroke: resolvedColor,
|
|
8469
|
+
strokeWidth,
|
|
8470
|
+
strokeLinecap: "round",
|
|
8471
|
+
strokeLinejoin: "round",
|
|
8472
|
+
points
|
|
8473
|
+
}
|
|
8474
|
+
)
|
|
8475
|
+
]
|
|
8476
|
+
}
|
|
8477
|
+
);
|
|
8478
|
+
};
|
|
8479
|
+
Sparkline.displayName = "Sparkline";
|
|
8480
|
+
}
|
|
8481
|
+
});
|
|
8421
8482
|
var Switch;
|
|
8422
8483
|
var init_Switch = __esm({
|
|
8423
8484
|
"components/atoms/Switch.tsx"() {
|
|
@@ -13651,7 +13712,7 @@ var init_MapView = __esm({
|
|
|
13651
13712
|
shadowSize: [41, 41]
|
|
13652
13713
|
});
|
|
13653
13714
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
13654
|
-
const { useEffect: useEffect87, useRef: useRef88, useCallback:
|
|
13715
|
+
const { useEffect: useEffect87, useRef: useRef88, useCallback: useCallback128, useState: useState121 } = React93__default;
|
|
13655
13716
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
13656
13717
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
13657
13718
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -13696,8 +13757,8 @@ var init_MapView = __esm({
|
|
|
13696
13757
|
showAttribution = true
|
|
13697
13758
|
}) {
|
|
13698
13759
|
const eventBus = useEventBus3();
|
|
13699
|
-
const [clickedPosition, setClickedPosition] =
|
|
13700
|
-
const handleMapClick =
|
|
13760
|
+
const [clickedPosition, setClickedPosition] = useState121(null);
|
|
13761
|
+
const handleMapClick = useCallback128((lat, lng) => {
|
|
13701
13762
|
if (showClickedPin) {
|
|
13702
13763
|
setClickedPosition({ lat, lng });
|
|
13703
13764
|
}
|
|
@@ -13706,7 +13767,7 @@ var init_MapView = __esm({
|
|
|
13706
13767
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
13707
13768
|
}
|
|
13708
13769
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
13709
|
-
const handleMarkerClick =
|
|
13770
|
+
const handleMarkerClick = useCallback128((marker) => {
|
|
13710
13771
|
onMarkerClick?.(marker);
|
|
13711
13772
|
if (markerClickEvent) {
|
|
13712
13773
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -22819,7 +22880,7 @@ var init_CastleTemplate = __esm({
|
|
|
22819
22880
|
CastleTemplate.displayName = "CastleTemplate";
|
|
22820
22881
|
}
|
|
22821
22882
|
});
|
|
22822
|
-
var CHART_COLORS, BarChart, PieChart, LineChart, Chart;
|
|
22883
|
+
var CHART_COLORS, seriesColor, monthFormatter, formatTimeLabel, BarChart, PieChart, LineChart, ScatterChart, Chart;
|
|
22823
22884
|
var init_Chart = __esm({
|
|
22824
22885
|
"components/organisms/Chart.tsx"() {
|
|
22825
22886
|
"use client";
|
|
@@ -22839,38 +22900,159 @@ var init_Chart = __esm({
|
|
|
22839
22900
|
"var(--color-info)",
|
|
22840
22901
|
"var(--color-accent)"
|
|
22841
22902
|
];
|
|
22842
|
-
|
|
22843
|
-
|
|
22844
|
-
|
|
22845
|
-
|
|
22846
|
-
|
|
22847
|
-
|
|
22848
|
-
|
|
22849
|
-
|
|
22850
|
-
|
|
22851
|
-
|
|
22852
|
-
|
|
22853
|
-
|
|
22854
|
-
|
|
22855
|
-
|
|
22856
|
-
|
|
22857
|
-
|
|
22858
|
-
|
|
22903
|
+
seriesColor = (series, idx) => series.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
22904
|
+
monthFormatter = new Intl.DateTimeFormat(void 0, {
|
|
22905
|
+
month: "short",
|
|
22906
|
+
year: "2-digit"
|
|
22907
|
+
});
|
|
22908
|
+
formatTimeLabel = (raw) => {
|
|
22909
|
+
const parsed = new Date(raw);
|
|
22910
|
+
if (Number.isNaN(parsed.getTime())) return raw;
|
|
22911
|
+
return monthFormatter.format(parsed);
|
|
22912
|
+
};
|
|
22913
|
+
BarChart = ({ series, height, showValues, stack, timeAxis, histogram = false, onPointClick }) => {
|
|
22914
|
+
const categories = useMemo(() => {
|
|
22915
|
+
const set = [];
|
|
22916
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22917
|
+
for (const s of series) {
|
|
22918
|
+
for (const p2 of s.data) {
|
|
22919
|
+
if (!seen.has(p2.label)) {
|
|
22920
|
+
seen.add(p2.label);
|
|
22921
|
+
set.push(p2.label);
|
|
22859
22922
|
}
|
|
22860
|
-
|
|
22861
|
-
|
|
22862
|
-
|
|
22863
|
-
|
|
22864
|
-
|
|
22865
|
-
|
|
22866
|
-
|
|
22867
|
-
|
|
22923
|
+
}
|
|
22924
|
+
}
|
|
22925
|
+
return set;
|
|
22926
|
+
}, [series]);
|
|
22927
|
+
const valueAt = useCallback(
|
|
22928
|
+
(s, label) => {
|
|
22929
|
+
const p2 = s.data.find((d) => d.label === label);
|
|
22930
|
+
return p2 ? p2.value : 0;
|
|
22931
|
+
},
|
|
22932
|
+
[]
|
|
22933
|
+
);
|
|
22934
|
+
const columnTotals = useMemo(() => {
|
|
22935
|
+
if (stack === "none") return null;
|
|
22936
|
+
return categories.map(
|
|
22937
|
+
(label) => series.reduce((sum, s) => sum + valueAt(s, label), 0)
|
|
22938
|
+
);
|
|
22939
|
+
}, [categories, series, stack, valueAt]);
|
|
22940
|
+
const maxValue = useMemo(() => {
|
|
22941
|
+
if (stack === "normalize") return 100;
|
|
22942
|
+
if (stack === "stack" && columnTotals) {
|
|
22943
|
+
return Math.max(...columnTotals, 1);
|
|
22944
|
+
}
|
|
22945
|
+
let m = 1;
|
|
22946
|
+
for (const s of series) {
|
|
22947
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
22948
|
+
}
|
|
22949
|
+
return m;
|
|
22950
|
+
}, [series, stack, columnTotals]);
|
|
22951
|
+
return /* @__PURE__ */ jsx(
|
|
22952
|
+
HStack,
|
|
22953
|
+
{
|
|
22954
|
+
gap: histogram ? "none" : "xs",
|
|
22955
|
+
align: "end",
|
|
22956
|
+
className: "w-full",
|
|
22957
|
+
style: { height },
|
|
22958
|
+
children: categories.map((label, catIdx) => {
|
|
22959
|
+
const displayLabel = timeAxis ? formatTimeLabel(label) : label;
|
|
22960
|
+
if (stack === "none") {
|
|
22961
|
+
return /* @__PURE__ */ jsxs(
|
|
22962
|
+
VStack,
|
|
22963
|
+
{
|
|
22964
|
+
gap: "xs",
|
|
22965
|
+
align: "center",
|
|
22966
|
+
flex: true,
|
|
22967
|
+
className: "min-w-0",
|
|
22968
|
+
children: [
|
|
22969
|
+
/* @__PURE__ */ jsx(HStack, { gap: histogram ? "none" : "xs", align: "end", className: "w-full", style: { height: "100%" }, children: series.map((s, sIdx) => {
|
|
22970
|
+
const value = valueAt(s, label);
|
|
22971
|
+
const barHeight = value / maxValue * 100;
|
|
22972
|
+
const color = seriesColor(s, sIdx);
|
|
22973
|
+
return /* @__PURE__ */ jsx(
|
|
22974
|
+
Box,
|
|
22975
|
+
{
|
|
22976
|
+
className: cn(
|
|
22977
|
+
"rounded-t-sm transition-all duration-500 ease-out min-h-[4px] cursor-pointer hover:opacity-80",
|
|
22978
|
+
histogram ? "flex-1 mx-0" : "flex-1"
|
|
22979
|
+
),
|
|
22980
|
+
style: {
|
|
22981
|
+
height: `${barHeight}%`,
|
|
22982
|
+
backgroundColor: color
|
|
22983
|
+
},
|
|
22984
|
+
onClick: () => onPointClick?.(
|
|
22985
|
+
{ label, value, color },
|
|
22986
|
+
s.name
|
|
22987
|
+
),
|
|
22988
|
+
title: `${s.name}: ${value}`
|
|
22989
|
+
},
|
|
22990
|
+
s.name
|
|
22991
|
+
);
|
|
22992
|
+
}) }),
|
|
22993
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", className: "tabular-nums", children: valueAt(series[0], label) }),
|
|
22994
|
+
/* @__PURE__ */ jsx(
|
|
22995
|
+
Typography,
|
|
22996
|
+
{
|
|
22997
|
+
variant: "caption",
|
|
22998
|
+
color: "secondary",
|
|
22999
|
+
className: "truncate w-full text-center",
|
|
23000
|
+
children: displayLabel
|
|
23001
|
+
}
|
|
23002
|
+
)
|
|
23003
|
+
]
|
|
23004
|
+
},
|
|
23005
|
+
label
|
|
23006
|
+
);
|
|
22868
23007
|
}
|
|
22869
|
-
|
|
22870
|
-
|
|
22871
|
-
|
|
23008
|
+
const total = columnTotals?.[catIdx] ?? 1;
|
|
23009
|
+
return /* @__PURE__ */ jsxs(
|
|
23010
|
+
VStack,
|
|
23011
|
+
{
|
|
23012
|
+
gap: "xs",
|
|
23013
|
+
align: "center",
|
|
23014
|
+
flex: true,
|
|
23015
|
+
className: "min-w-0",
|
|
23016
|
+
children: [
|
|
23017
|
+
/* @__PURE__ */ jsx(VStack, { gap: "none", className: "w-full", style: { height: "100%" }, justify: "end", children: series.map((s, sIdx) => {
|
|
23018
|
+
const value = valueAt(s, label);
|
|
23019
|
+
const ratio = stack === "normalize" ? total === 0 ? 0 : value / total * 100 : value / maxValue * 100;
|
|
23020
|
+
const color = seriesColor(s, sIdx);
|
|
23021
|
+
return /* @__PURE__ */ jsx(
|
|
23022
|
+
Box,
|
|
23023
|
+
{
|
|
23024
|
+
className: "w-full transition-all duration-500 ease-out cursor-pointer hover:opacity-80",
|
|
23025
|
+
style: {
|
|
23026
|
+
height: `${ratio}%`,
|
|
23027
|
+
backgroundColor: color
|
|
23028
|
+
},
|
|
23029
|
+
onClick: () => onPointClick?.(
|
|
23030
|
+
{ label, value, color },
|
|
23031
|
+
s.name
|
|
23032
|
+
),
|
|
23033
|
+
title: `${s.name}: ${value}`
|
|
23034
|
+
},
|
|
23035
|
+
s.name
|
|
23036
|
+
);
|
|
23037
|
+
}) }),
|
|
23038
|
+
/* @__PURE__ */ jsx(
|
|
23039
|
+
Typography,
|
|
23040
|
+
{
|
|
23041
|
+
variant: "caption",
|
|
23042
|
+
color: "secondary",
|
|
23043
|
+
className: "truncate w-full text-center",
|
|
23044
|
+
children: displayLabel
|
|
23045
|
+
}
|
|
23046
|
+
)
|
|
23047
|
+
]
|
|
23048
|
+
},
|
|
23049
|
+
label
|
|
23050
|
+
);
|
|
23051
|
+
})
|
|
23052
|
+
}
|
|
23053
|
+
);
|
|
22872
23054
|
};
|
|
22873
|
-
PieChart = ({ data, height, showValues, donut = false }) => {
|
|
23055
|
+
PieChart = ({ data, height, showValues, donut = false, onPointClick }) => {
|
|
22874
23056
|
const total = data.reduce((sum, d) => sum + d.value, 0);
|
|
22875
23057
|
const size = Math.min(height, 200);
|
|
22876
23058
|
const radius = size / 2 - 8;
|
|
@@ -22916,7 +23098,11 @@ var init_Chart = __esm({
|
|
|
22916
23098
|
fill: seg.color,
|
|
22917
23099
|
stroke: "var(--color-card)",
|
|
22918
23100
|
strokeWidth: "2",
|
|
22919
|
-
className: "transition-opacity duration-200 hover:opacity-80"
|
|
23101
|
+
className: "transition-opacity duration-200 hover:opacity-80 cursor-pointer",
|
|
23102
|
+
onClick: () => onPointClick?.(
|
|
23103
|
+
{ label: seg.label, value: seg.value, color: seg.color },
|
|
23104
|
+
"default"
|
|
23105
|
+
)
|
|
22920
23106
|
},
|
|
22921
23107
|
idx
|
|
22922
23108
|
)),
|
|
@@ -22951,56 +23137,243 @@ var init_Chart = __esm({
|
|
|
22951
23137
|
] }, idx)) })
|
|
22952
23138
|
] });
|
|
22953
23139
|
};
|
|
22954
|
-
LineChart = ({
|
|
22955
|
-
const maxValue = Math.max(...data.map((d) => d.value), 1);
|
|
23140
|
+
LineChart = ({ series, height, showValues, fill = false, timeAxis, onPointClick }) => {
|
|
22956
23141
|
const width = 400;
|
|
22957
23142
|
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
22958
23143
|
const chartWidth = width - padding.left - padding.right;
|
|
22959
23144
|
const chartHeight = height - padding.top - padding.bottom;
|
|
22960
|
-
const
|
|
22961
|
-
|
|
22962
|
-
|
|
22963
|
-
|
|
22964
|
-
|
|
22965
|
-
|
|
22966
|
-
|
|
22967
|
-
|
|
22968
|
-
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
22969
|
-
return /* @__PURE__ */ jsxs("svg", { width: "100%", height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", children: [
|
|
22970
|
-
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
22971
|
-
const y = padding.top + chartHeight * (1 - frac);
|
|
22972
|
-
return /* @__PURE__ */ jsx(
|
|
22973
|
-
"line",
|
|
22974
|
-
{
|
|
22975
|
-
x1: padding.left,
|
|
22976
|
-
y1: y,
|
|
22977
|
-
x2: width - padding.right,
|
|
22978
|
-
y2: y,
|
|
22979
|
-
stroke: "var(--color-border)",
|
|
22980
|
-
strokeDasharray: "4 4",
|
|
22981
|
-
opacity: 0.5
|
|
22982
|
-
},
|
|
22983
|
-
frac
|
|
22984
|
-
);
|
|
22985
|
-
}),
|
|
22986
|
-
fill && /* @__PURE__ */ jsx("path", { d: areaPath, fill: "var(--color-primary)", opacity: 0.1 }),
|
|
22987
|
-
/* @__PURE__ */ jsx("path", { d: linePath, fill: "none", stroke: "var(--color-primary)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
22988
|
-
points.map((p2, idx) => /* @__PURE__ */ jsxs("g", { children: [
|
|
22989
|
-
/* @__PURE__ */ jsx("circle", { cx: p2.x, cy: p2.y, r: "4", fill: "var(--color-card)", stroke: "var(--color-primary)", strokeWidth: "2" }),
|
|
22990
|
-
showValues && /* @__PURE__ */ jsx("text", { x: p2.x, y: p2.y - 10, textAnchor: "middle", fill: "var(--color-foreground)", fontSize: "10", fontWeight: "500", children: p2.value }),
|
|
22991
|
-
/* @__PURE__ */ jsx(
|
|
22992
|
-
"text",
|
|
22993
|
-
{
|
|
22994
|
-
x: p2.x,
|
|
22995
|
-
y: height - 8,
|
|
22996
|
-
textAnchor: "middle",
|
|
22997
|
-
fill: "var(--color-muted-foreground)",
|
|
22998
|
-
fontSize: "9",
|
|
22999
|
-
children: p2.label
|
|
23145
|
+
const labels = useMemo(() => {
|
|
23146
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23147
|
+
const out = [];
|
|
23148
|
+
for (const s of series) {
|
|
23149
|
+
for (const p2 of s.data) {
|
|
23150
|
+
if (!seen.has(p2.label)) {
|
|
23151
|
+
seen.add(p2.label);
|
|
23152
|
+
out.push(p2.label);
|
|
23000
23153
|
}
|
|
23001
|
-
|
|
23002
|
-
|
|
23003
|
-
|
|
23154
|
+
}
|
|
23155
|
+
}
|
|
23156
|
+
return out;
|
|
23157
|
+
}, [series]);
|
|
23158
|
+
const maxValue = useMemo(() => {
|
|
23159
|
+
let m = 1;
|
|
23160
|
+
for (const s of series) {
|
|
23161
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
23162
|
+
}
|
|
23163
|
+
return m;
|
|
23164
|
+
}, [series]);
|
|
23165
|
+
const xFor = useCallback(
|
|
23166
|
+
(idx) => padding.left + idx / Math.max(labels.length - 1, 1) * chartWidth,
|
|
23167
|
+
[labels.length, chartWidth, padding.left]
|
|
23168
|
+
);
|
|
23169
|
+
const yFor = useCallback(
|
|
23170
|
+
(value) => padding.top + chartHeight - value / maxValue * chartHeight,
|
|
23171
|
+
[maxValue, chartHeight, padding.top]
|
|
23172
|
+
);
|
|
23173
|
+
return /* @__PURE__ */ jsxs(
|
|
23174
|
+
"svg",
|
|
23175
|
+
{
|
|
23176
|
+
width: "100%",
|
|
23177
|
+
height,
|
|
23178
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
23179
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
23180
|
+
children: [
|
|
23181
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
23182
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
23183
|
+
return /* @__PURE__ */ jsx(
|
|
23184
|
+
"line",
|
|
23185
|
+
{
|
|
23186
|
+
x1: padding.left,
|
|
23187
|
+
y1: y,
|
|
23188
|
+
x2: width - padding.right,
|
|
23189
|
+
y2: y,
|
|
23190
|
+
stroke: "var(--color-border)",
|
|
23191
|
+
strokeDasharray: "4 4",
|
|
23192
|
+
opacity: 0.5
|
|
23193
|
+
},
|
|
23194
|
+
frac
|
|
23195
|
+
);
|
|
23196
|
+
}),
|
|
23197
|
+
series.map((s, sIdx) => {
|
|
23198
|
+
const color = seriesColor(s, sIdx);
|
|
23199
|
+
const points = labels.map((label, idx) => {
|
|
23200
|
+
const point = s.data.find((d) => d.label === label);
|
|
23201
|
+
return {
|
|
23202
|
+
x: xFor(idx),
|
|
23203
|
+
y: yFor(point ? point.value : 0),
|
|
23204
|
+
value: point ? point.value : 0,
|
|
23205
|
+
label
|
|
23206
|
+
};
|
|
23207
|
+
});
|
|
23208
|
+
const linePath = points.map((p2, i) => `${i === 0 ? "M" : "L"} ${p2.x} ${p2.y}`).join(" ");
|
|
23209
|
+
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
23210
|
+
return /* @__PURE__ */ jsxs("g", { children: [
|
|
23211
|
+
fill && /* @__PURE__ */ jsx(
|
|
23212
|
+
"path",
|
|
23213
|
+
{
|
|
23214
|
+
d: areaPath,
|
|
23215
|
+
fill: color,
|
|
23216
|
+
opacity: series.length > 1 ? 0.08 : 0.1
|
|
23217
|
+
}
|
|
23218
|
+
),
|
|
23219
|
+
/* @__PURE__ */ jsx(
|
|
23220
|
+
"path",
|
|
23221
|
+
{
|
|
23222
|
+
d: linePath,
|
|
23223
|
+
fill: "none",
|
|
23224
|
+
stroke: color,
|
|
23225
|
+
strokeWidth: "2",
|
|
23226
|
+
strokeLinecap: "round",
|
|
23227
|
+
strokeLinejoin: "round",
|
|
23228
|
+
strokeDasharray: s.dashed ? "6 4" : void 0
|
|
23229
|
+
}
|
|
23230
|
+
),
|
|
23231
|
+
points.map((p2, idx) => /* @__PURE__ */ jsxs("g", { children: [
|
|
23232
|
+
/* @__PURE__ */ jsx(
|
|
23233
|
+
"circle",
|
|
23234
|
+
{
|
|
23235
|
+
cx: p2.x,
|
|
23236
|
+
cy: p2.y,
|
|
23237
|
+
r: "4",
|
|
23238
|
+
fill: "var(--color-card)",
|
|
23239
|
+
stroke: color,
|
|
23240
|
+
strokeWidth: "2",
|
|
23241
|
+
className: "cursor-pointer",
|
|
23242
|
+
onClick: () => onPointClick?.(
|
|
23243
|
+
{ label: p2.label, value: p2.value, color },
|
|
23244
|
+
s.name
|
|
23245
|
+
)
|
|
23246
|
+
}
|
|
23247
|
+
),
|
|
23248
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsx(
|
|
23249
|
+
"text",
|
|
23250
|
+
{
|
|
23251
|
+
x: p2.x,
|
|
23252
|
+
y: p2.y - 10,
|
|
23253
|
+
textAnchor: "middle",
|
|
23254
|
+
fill: "var(--color-foreground)",
|
|
23255
|
+
fontSize: "10",
|
|
23256
|
+
fontWeight: "500",
|
|
23257
|
+
children: p2.value
|
|
23258
|
+
}
|
|
23259
|
+
)
|
|
23260
|
+
] }, idx))
|
|
23261
|
+
] }, s.name);
|
|
23262
|
+
}),
|
|
23263
|
+
labels.map((label, idx) => /* @__PURE__ */ jsx(
|
|
23264
|
+
"text",
|
|
23265
|
+
{
|
|
23266
|
+
x: xFor(idx),
|
|
23267
|
+
y: height - 8,
|
|
23268
|
+
textAnchor: "middle",
|
|
23269
|
+
fill: "var(--color-muted-foreground)",
|
|
23270
|
+
fontSize: "9",
|
|
23271
|
+
children: timeAxis ? formatTimeLabel(label) : label
|
|
23272
|
+
},
|
|
23273
|
+
label
|
|
23274
|
+
))
|
|
23275
|
+
]
|
|
23276
|
+
}
|
|
23277
|
+
);
|
|
23278
|
+
};
|
|
23279
|
+
ScatterChart = ({ data, height, onPointClick }) => {
|
|
23280
|
+
const width = 400;
|
|
23281
|
+
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
23282
|
+
const chartWidth = width - padding.left - padding.right;
|
|
23283
|
+
const chartHeight = height - padding.top - padding.bottom;
|
|
23284
|
+
const { minX, maxX, minY, maxY } = useMemo(() => {
|
|
23285
|
+
if (data.length === 0) {
|
|
23286
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
23287
|
+
}
|
|
23288
|
+
let mnX = data[0].x;
|
|
23289
|
+
let mxX = data[0].x;
|
|
23290
|
+
let mnY = data[0].y;
|
|
23291
|
+
let mxY = data[0].y;
|
|
23292
|
+
for (const p2 of data) {
|
|
23293
|
+
if (p2.x < mnX) mnX = p2.x;
|
|
23294
|
+
if (p2.x > mxX) mxX = p2.x;
|
|
23295
|
+
if (p2.y < mnY) mnY = p2.y;
|
|
23296
|
+
if (p2.y > mxY) mxY = p2.y;
|
|
23297
|
+
}
|
|
23298
|
+
return { minX: mnX, maxX: mxX, minY: mnY, maxY: mxY };
|
|
23299
|
+
}, [data]);
|
|
23300
|
+
const rangeX = maxX - minX || 1;
|
|
23301
|
+
const rangeY = maxY - minY || 1;
|
|
23302
|
+
return /* @__PURE__ */ jsxs(
|
|
23303
|
+
"svg",
|
|
23304
|
+
{
|
|
23305
|
+
width: "100%",
|
|
23306
|
+
height,
|
|
23307
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
23308
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
23309
|
+
children: [
|
|
23310
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
23311
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
23312
|
+
return /* @__PURE__ */ jsx(
|
|
23313
|
+
"line",
|
|
23314
|
+
{
|
|
23315
|
+
x1: padding.left,
|
|
23316
|
+
y1: y,
|
|
23317
|
+
x2: width - padding.right,
|
|
23318
|
+
y2: y,
|
|
23319
|
+
stroke: "var(--color-border)",
|
|
23320
|
+
strokeDasharray: "4 4",
|
|
23321
|
+
opacity: 0.5
|
|
23322
|
+
},
|
|
23323
|
+
frac
|
|
23324
|
+
);
|
|
23325
|
+
}),
|
|
23326
|
+
data.map((p2, idx) => {
|
|
23327
|
+
const cx = padding.left + (p2.x - minX) / rangeX * chartWidth;
|
|
23328
|
+
const cy = padding.top + chartHeight - (p2.y - minY) / rangeY * chartHeight;
|
|
23329
|
+
const r2 = p2.size ?? 5;
|
|
23330
|
+
const color = p2.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
23331
|
+
return /* @__PURE__ */ jsx(
|
|
23332
|
+
"circle",
|
|
23333
|
+
{
|
|
23334
|
+
cx,
|
|
23335
|
+
cy,
|
|
23336
|
+
r: r2,
|
|
23337
|
+
fill: color,
|
|
23338
|
+
opacity: 0.7,
|
|
23339
|
+
className: "cursor-pointer hover:opacity-100",
|
|
23340
|
+
onClick: () => onPointClick?.(
|
|
23341
|
+
{
|
|
23342
|
+
label: p2.label ?? `(${p2.x}, ${p2.y})`,
|
|
23343
|
+
value: p2.y,
|
|
23344
|
+
color
|
|
23345
|
+
},
|
|
23346
|
+
"default"
|
|
23347
|
+
),
|
|
23348
|
+
children: /* @__PURE__ */ jsx("title", { children: p2.label ?? `(${p2.x}, ${p2.y})` })
|
|
23349
|
+
},
|
|
23350
|
+
idx
|
|
23351
|
+
);
|
|
23352
|
+
}),
|
|
23353
|
+
/* @__PURE__ */ jsx(
|
|
23354
|
+
"text",
|
|
23355
|
+
{
|
|
23356
|
+
x: padding.left,
|
|
23357
|
+
y: height - 8,
|
|
23358
|
+
fill: "var(--color-muted-foreground)",
|
|
23359
|
+
fontSize: "9",
|
|
23360
|
+
children: minX.toFixed(1)
|
|
23361
|
+
}
|
|
23362
|
+
),
|
|
23363
|
+
/* @__PURE__ */ jsx(
|
|
23364
|
+
"text",
|
|
23365
|
+
{
|
|
23366
|
+
x: width - padding.right,
|
|
23367
|
+
y: height - 8,
|
|
23368
|
+
textAnchor: "end",
|
|
23369
|
+
fill: "var(--color-muted-foreground)",
|
|
23370
|
+
fontSize: "9",
|
|
23371
|
+
children: maxX.toFixed(1)
|
|
23372
|
+
}
|
|
23373
|
+
)
|
|
23374
|
+
]
|
|
23375
|
+
}
|
|
23376
|
+
);
|
|
23004
23377
|
};
|
|
23005
23378
|
Chart = ({
|
|
23006
23379
|
title,
|
|
@@ -23008,9 +23381,13 @@ var init_Chart = __esm({
|
|
|
23008
23381
|
chartType = "bar",
|
|
23009
23382
|
series,
|
|
23010
23383
|
data: simpleData,
|
|
23384
|
+
scatterData,
|
|
23011
23385
|
height = 200,
|
|
23012
23386
|
showLegend = true,
|
|
23013
23387
|
showValues = false,
|
|
23388
|
+
stack = "none",
|
|
23389
|
+
timeAxis = false,
|
|
23390
|
+
drillEvent,
|
|
23014
23391
|
actions,
|
|
23015
23392
|
entity,
|
|
23016
23393
|
isLoading = false,
|
|
@@ -23027,11 +23404,25 @@ var init_Chart = __esm({
|
|
|
23027
23404
|
},
|
|
23028
23405
|
[eventBus]
|
|
23029
23406
|
);
|
|
23030
|
-
const
|
|
23031
|
-
|
|
23032
|
-
|
|
23407
|
+
const handlePointClick = useCallback(
|
|
23408
|
+
(point, seriesName) => {
|
|
23409
|
+
if (drillEvent) {
|
|
23410
|
+
eventBus.emit(`UI:${drillEvent}`, {
|
|
23411
|
+
label: point.label,
|
|
23412
|
+
value: point.value,
|
|
23413
|
+
seriesLabel: seriesName === "default" ? void 0 : seriesName
|
|
23414
|
+
});
|
|
23415
|
+
}
|
|
23416
|
+
},
|
|
23417
|
+
[drillEvent, eventBus]
|
|
23418
|
+
);
|
|
23419
|
+
const normalizedSeries = useMemo(() => {
|
|
23420
|
+
if (series && series.length > 0) return series;
|
|
23421
|
+
if (simpleData) return [{ name: "default", data: simpleData }];
|
|
23033
23422
|
return [];
|
|
23034
23423
|
}, [simpleData, series]);
|
|
23424
|
+
const firstSeriesData = normalizedSeries[0]?.data ?? [];
|
|
23425
|
+
const hasContent = chartType === "scatter" ? (scatterData?.length ?? 0) > 0 : normalizedSeries.some((s) => s.data.length > 0);
|
|
23035
23426
|
if (isLoading) {
|
|
23036
23427
|
return /* @__PURE__ */ jsx(LoadingState, { message: "Loading chart...", className });
|
|
23037
23428
|
}
|
|
@@ -23045,7 +23436,7 @@ var init_Chart = __esm({
|
|
|
23045
23436
|
}
|
|
23046
23437
|
);
|
|
23047
23438
|
}
|
|
23048
|
-
if (
|
|
23439
|
+
if (!hasContent) {
|
|
23049
23440
|
return /* @__PURE__ */ jsx(EmptyState, { title: t("empty.noData"), description: t("empty.noData"), className });
|
|
23050
23441
|
}
|
|
23051
23442
|
return /* @__PURE__ */ jsx(Card, { className: cn("p-6", className), children: /* @__PURE__ */ jsxs(VStack, { gap: "md", children: [
|
|
@@ -23066,18 +23457,84 @@ var init_Chart = __esm({
|
|
|
23066
23457
|
)) })
|
|
23067
23458
|
] }),
|
|
23068
23459
|
/* @__PURE__ */ jsxs(Box, { className: "w-full", children: [
|
|
23069
|
-
chartType === "bar" && /* @__PURE__ */ jsx(
|
|
23070
|
-
|
|
23071
|
-
|
|
23072
|
-
|
|
23073
|
-
|
|
23460
|
+
chartType === "bar" && /* @__PURE__ */ jsx(
|
|
23461
|
+
BarChart,
|
|
23462
|
+
{
|
|
23463
|
+
series: normalizedSeries,
|
|
23464
|
+
height,
|
|
23465
|
+
showValues,
|
|
23466
|
+
stack,
|
|
23467
|
+
timeAxis,
|
|
23468
|
+
onPointClick: handlePointClick
|
|
23469
|
+
}
|
|
23470
|
+
),
|
|
23471
|
+
chartType === "histogram" && /* @__PURE__ */ jsx(
|
|
23472
|
+
BarChart,
|
|
23473
|
+
{
|
|
23474
|
+
series: normalizedSeries,
|
|
23475
|
+
height,
|
|
23476
|
+
showValues,
|
|
23477
|
+
stack: "none",
|
|
23478
|
+
timeAxis: false,
|
|
23479
|
+
histogram: true,
|
|
23480
|
+
onPointClick: handlePointClick
|
|
23481
|
+
}
|
|
23482
|
+
),
|
|
23483
|
+
chartType === "line" && /* @__PURE__ */ jsx(
|
|
23484
|
+
LineChart,
|
|
23485
|
+
{
|
|
23486
|
+
series: normalizedSeries,
|
|
23487
|
+
height,
|
|
23488
|
+
showValues,
|
|
23489
|
+
timeAxis,
|
|
23490
|
+
onPointClick: handlePointClick
|
|
23491
|
+
}
|
|
23492
|
+
),
|
|
23493
|
+
chartType === "area" && /* @__PURE__ */ jsx(
|
|
23494
|
+
LineChart,
|
|
23495
|
+
{
|
|
23496
|
+
series: normalizedSeries,
|
|
23497
|
+
height,
|
|
23498
|
+
showValues,
|
|
23499
|
+
timeAxis,
|
|
23500
|
+
fill: true,
|
|
23501
|
+
onPointClick: handlePointClick
|
|
23502
|
+
}
|
|
23503
|
+
),
|
|
23504
|
+
chartType === "pie" && /* @__PURE__ */ jsx(
|
|
23505
|
+
PieChart,
|
|
23506
|
+
{
|
|
23507
|
+
data: firstSeriesData,
|
|
23508
|
+
height,
|
|
23509
|
+
showValues: showLegend,
|
|
23510
|
+
onPointClick: handlePointClick
|
|
23511
|
+
}
|
|
23512
|
+
),
|
|
23513
|
+
chartType === "donut" && /* @__PURE__ */ jsx(
|
|
23514
|
+
PieChart,
|
|
23515
|
+
{
|
|
23516
|
+
data: firstSeriesData,
|
|
23517
|
+
height,
|
|
23518
|
+
showValues: showLegend,
|
|
23519
|
+
donut: true,
|
|
23520
|
+
onPointClick: handlePointClick
|
|
23521
|
+
}
|
|
23522
|
+
),
|
|
23523
|
+
chartType === "scatter" && /* @__PURE__ */ jsx(
|
|
23524
|
+
ScatterChart,
|
|
23525
|
+
{
|
|
23526
|
+
data: scatterData ?? [],
|
|
23527
|
+
height,
|
|
23528
|
+
onPointClick: handlePointClick
|
|
23529
|
+
}
|
|
23530
|
+
)
|
|
23074
23531
|
] }),
|
|
23075
|
-
showLegend &&
|
|
23532
|
+
showLegend && normalizedSeries.length > 1 && /* @__PURE__ */ jsx(HStack, { gap: "md", justify: "center", wrap: true, children: normalizedSeries.map((s, idx) => /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
23076
23533
|
/* @__PURE__ */ jsx(
|
|
23077
23534
|
Box,
|
|
23078
23535
|
{
|
|
23079
23536
|
className: "w-3 h-3 rounded-full flex-shrink-0",
|
|
23080
|
-
style: { backgroundColor: s
|
|
23537
|
+
style: { backgroundColor: seriesColor(s, idx) }
|
|
23081
23538
|
}
|
|
23082
23539
|
),
|
|
23083
23540
|
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: s.name })
|
|
@@ -27993,6 +28450,151 @@ var init_FlipCard = __esm({
|
|
|
27993
28450
|
FlipCard.displayName = "FlipCard";
|
|
27994
28451
|
}
|
|
27995
28452
|
});
|
|
28453
|
+
function toISODate(d) {
|
|
28454
|
+
return d.toISOString().slice(0, 10);
|
|
28455
|
+
}
|
|
28456
|
+
function startOfMonth(d) {
|
|
28457
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
28458
|
+
}
|
|
28459
|
+
function startOfQuarter(d) {
|
|
28460
|
+
return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
|
|
28461
|
+
}
|
|
28462
|
+
function startOfYear(d) {
|
|
28463
|
+
return new Date(d.getFullYear(), 0, 1);
|
|
28464
|
+
}
|
|
28465
|
+
function daysAgo(n) {
|
|
28466
|
+
const d = /* @__PURE__ */ new Date();
|
|
28467
|
+
d.setDate(d.getDate() - n);
|
|
28468
|
+
return d;
|
|
28469
|
+
}
|
|
28470
|
+
var DEFAULT_PRESETS, DateRangePicker;
|
|
28471
|
+
var init_DateRangePicker = __esm({
|
|
28472
|
+
"components/molecules/DateRangePicker.tsx"() {
|
|
28473
|
+
"use client";
|
|
28474
|
+
init_cn();
|
|
28475
|
+
init_Button();
|
|
28476
|
+
init_Input();
|
|
28477
|
+
init_Stack();
|
|
28478
|
+
init_Typography();
|
|
28479
|
+
init_useEventBus();
|
|
28480
|
+
DEFAULT_PRESETS = [
|
|
28481
|
+
{
|
|
28482
|
+
label: "Last 7 days",
|
|
28483
|
+
value: "7d",
|
|
28484
|
+
range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28485
|
+
},
|
|
28486
|
+
{
|
|
28487
|
+
label: "Last 30 days",
|
|
28488
|
+
value: "30d",
|
|
28489
|
+
range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28490
|
+
},
|
|
28491
|
+
{
|
|
28492
|
+
label: "This Month",
|
|
28493
|
+
value: "month",
|
|
28494
|
+
range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28495
|
+
},
|
|
28496
|
+
{
|
|
28497
|
+
label: "This Quarter",
|
|
28498
|
+
value: "quarter",
|
|
28499
|
+
range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28500
|
+
},
|
|
28501
|
+
{
|
|
28502
|
+
label: "YTD",
|
|
28503
|
+
value: "ytd",
|
|
28504
|
+
range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28505
|
+
}
|
|
28506
|
+
];
|
|
28507
|
+
DateRangePicker = ({
|
|
28508
|
+
from: fromProp,
|
|
28509
|
+
to: toProp,
|
|
28510
|
+
event,
|
|
28511
|
+
onChange,
|
|
28512
|
+
presets = DEFAULT_PRESETS,
|
|
28513
|
+
fromLabel = "From",
|
|
28514
|
+
toLabel = "To",
|
|
28515
|
+
className
|
|
28516
|
+
}) => {
|
|
28517
|
+
const eventBus = useEventBus();
|
|
28518
|
+
const [from, setFrom] = useState(fromProp ?? "");
|
|
28519
|
+
const [to, setTo] = useState(toProp ?? "");
|
|
28520
|
+
const [activePreset, setActivePreset] = useState(null);
|
|
28521
|
+
const emit = useCallback(
|
|
28522
|
+
(range) => {
|
|
28523
|
+
onChange?.(range);
|
|
28524
|
+
if (event) eventBus.emit(`UI:${event}`, range);
|
|
28525
|
+
},
|
|
28526
|
+
[onChange, event, eventBus]
|
|
28527
|
+
);
|
|
28528
|
+
const handleFromChange = useCallback(
|
|
28529
|
+
(next) => {
|
|
28530
|
+
setFrom(next);
|
|
28531
|
+
setActivePreset(null);
|
|
28532
|
+
emit({ from: next, to });
|
|
28533
|
+
},
|
|
28534
|
+
[to, emit]
|
|
28535
|
+
);
|
|
28536
|
+
const handleToChange = useCallback(
|
|
28537
|
+
(next) => {
|
|
28538
|
+
setTo(next);
|
|
28539
|
+
setActivePreset(null);
|
|
28540
|
+
emit({ from, to: next });
|
|
28541
|
+
},
|
|
28542
|
+
[from, emit]
|
|
28543
|
+
);
|
|
28544
|
+
const handlePreset = useCallback(
|
|
28545
|
+
(preset) => {
|
|
28546
|
+
const range = preset.range();
|
|
28547
|
+
setFrom(range.from);
|
|
28548
|
+
setTo(range.to);
|
|
28549
|
+
setActivePreset(preset.value);
|
|
28550
|
+
emit(range);
|
|
28551
|
+
},
|
|
28552
|
+
[emit]
|
|
28553
|
+
);
|
|
28554
|
+
const presetButtons = useMemo(
|
|
28555
|
+
() => presets.map((preset) => /* @__PURE__ */ jsx(
|
|
28556
|
+
Button,
|
|
28557
|
+
{
|
|
28558
|
+
variant: activePreset === preset.value ? "primary" : "ghost",
|
|
28559
|
+
size: "sm",
|
|
28560
|
+
onClick: () => handlePreset(preset),
|
|
28561
|
+
children: preset.label
|
|
28562
|
+
},
|
|
28563
|
+
preset.value
|
|
28564
|
+
)),
|
|
28565
|
+
[presets, activePreset, handlePreset]
|
|
28566
|
+
);
|
|
28567
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn(className), children: [
|
|
28568
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "md", align: "end", children: [
|
|
28569
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
28570
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: fromLabel }),
|
|
28571
|
+
/* @__PURE__ */ jsx(
|
|
28572
|
+
Input,
|
|
28573
|
+
{
|
|
28574
|
+
type: "date",
|
|
28575
|
+
value: from,
|
|
28576
|
+
onChange: (e) => handleFromChange(e.target.value)
|
|
28577
|
+
}
|
|
28578
|
+
)
|
|
28579
|
+
] }),
|
|
28580
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
28581
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: toLabel }),
|
|
28582
|
+
/* @__PURE__ */ jsx(
|
|
28583
|
+
Input,
|
|
28584
|
+
{
|
|
28585
|
+
type: "date",
|
|
28586
|
+
value: to,
|
|
28587
|
+
onChange: (e) => handleToChange(e.target.value)
|
|
28588
|
+
}
|
|
28589
|
+
)
|
|
28590
|
+
] })
|
|
28591
|
+
] }),
|
|
28592
|
+
presets.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
|
|
28593
|
+
] });
|
|
28594
|
+
};
|
|
28595
|
+
DateRangePicker.displayName = "DateRangePicker";
|
|
28596
|
+
}
|
|
28597
|
+
});
|
|
27996
28598
|
var DEFAULT_OPTIONS, DateRangeSelector;
|
|
27997
28599
|
var init_DateRangeSelector = __esm({
|
|
27998
28600
|
"components/molecules/DateRangeSelector.tsx"() {
|
|
@@ -30964,7 +31566,9 @@ var init_StatDisplay = __esm({
|
|
|
30964
31566
|
init_Typography();
|
|
30965
31567
|
init_Box();
|
|
30966
31568
|
init_Stack();
|
|
31569
|
+
init_Sparkline();
|
|
30967
31570
|
init_Icon();
|
|
31571
|
+
init_useEventBus();
|
|
30968
31572
|
variantColor = {
|
|
30969
31573
|
default: "text-foreground",
|
|
30970
31574
|
primary: "text-primary",
|
|
@@ -30979,6 +31583,10 @@ var init_StatDisplay = __esm({
|
|
|
30979
31583
|
max,
|
|
30980
31584
|
target,
|
|
30981
31585
|
trend,
|
|
31586
|
+
trendPolarity = "higher-is-better",
|
|
31587
|
+
trendFormat = "absolute",
|
|
31588
|
+
sparklineData,
|
|
31589
|
+
clickEvent,
|
|
30982
31590
|
prefix,
|
|
30983
31591
|
suffix,
|
|
30984
31592
|
icon: iconProp,
|
|
@@ -30992,6 +31600,10 @@ var init_StatDisplay = __esm({
|
|
|
30992
31600
|
isLoading = false,
|
|
30993
31601
|
error = null
|
|
30994
31602
|
}) => {
|
|
31603
|
+
const eventBus = useEventBus();
|
|
31604
|
+
const handleClick = useCallback(() => {
|
|
31605
|
+
if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
|
|
31606
|
+
}, [clickEvent, eventBus, label]);
|
|
30995
31607
|
const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
|
|
30996
31608
|
const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
|
|
30997
31609
|
const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
|
|
@@ -31002,7 +31614,10 @@ var init_StatDisplay = __esm({
|
|
|
31002
31614
|
const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
|
|
31003
31615
|
const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
|
|
31004
31616
|
const trendUp = showTrend && trend > 0;
|
|
31005
|
-
const
|
|
31617
|
+
const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
|
|
31618
|
+
const trendMagnitude = Math.abs(trend);
|
|
31619
|
+
const trendSuffix = trendFormat === "percent" ? "%" : "";
|
|
31620
|
+
const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
|
|
31006
31621
|
if (error) {
|
|
31007
31622
|
return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "error", children: error.message }) });
|
|
31008
31623
|
}
|
|
@@ -31013,38 +31628,57 @@ var init_StatDisplay = __esm({
|
|
|
31013
31628
|
] }) });
|
|
31014
31629
|
}
|
|
31015
31630
|
if (compact) {
|
|
31016
|
-
return /* @__PURE__ */ jsxs(
|
|
31017
|
-
|
|
31018
|
-
|
|
31019
|
-
|
|
31020
|
-
|
|
31021
|
-
|
|
31022
|
-
|
|
31631
|
+
return /* @__PURE__ */ jsxs(
|
|
31632
|
+
HStack,
|
|
31633
|
+
{
|
|
31634
|
+
gap: "sm",
|
|
31635
|
+
className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
|
|
31636
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31637
|
+
children: [
|
|
31638
|
+
ResolvedIcon && /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
|
|
31639
|
+
typeof iconProp !== "string" && iconProp,
|
|
31640
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: label }),
|
|
31641
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31642
|
+
showTrend && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
|
|
31643
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
|
|
31644
|
+
]
|
|
31645
|
+
}
|
|
31646
|
+
);
|
|
31023
31647
|
}
|
|
31024
|
-
return /* @__PURE__ */ jsx(
|
|
31025
|
-
|
|
31026
|
-
|
|
31027
|
-
|
|
31028
|
-
|
|
31029
|
-
|
|
31030
|
-
|
|
31031
|
-
{
|
|
31032
|
-
|
|
31033
|
-
className: cn("font-
|
|
31034
|
-
|
|
31035
|
-
|
|
31036
|
-
|
|
31037
|
-
|
|
31038
|
-
|
|
31039
|
-
|
|
31040
|
-
|
|
31041
|
-
|
|
31042
|
-
|
|
31043
|
-
|
|
31044
|
-
|
|
31045
|
-
|
|
31046
|
-
|
|
31047
|
-
|
|
31648
|
+
return /* @__PURE__ */ jsx(
|
|
31649
|
+
Card,
|
|
31650
|
+
{
|
|
31651
|
+
className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
|
|
31652
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31653
|
+
children: /* @__PURE__ */ jsxs(HStack, { align: "start", justify: "between", children: [
|
|
31654
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
|
|
31655
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", children: label }),
|
|
31656
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "end", children: [
|
|
31657
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31658
|
+
showTrend && /* @__PURE__ */ jsx(
|
|
31659
|
+
Typography,
|
|
31660
|
+
{
|
|
31661
|
+
variant: "caption",
|
|
31662
|
+
className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
|
|
31663
|
+
children: trendLabel
|
|
31664
|
+
}
|
|
31665
|
+
)
|
|
31666
|
+
] }),
|
|
31667
|
+
showTarget && /* @__PURE__ */ jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
31668
|
+
Box,
|
|
31669
|
+
{
|
|
31670
|
+
className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
|
|
31671
|
+
style: { width: `${targetPct}%` }
|
|
31672
|
+
}
|
|
31673
|
+
) })
|
|
31674
|
+
] }),
|
|
31675
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
31676
|
+
(ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }) : iconProp }),
|
|
31677
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
31678
|
+
] })
|
|
31679
|
+
] })
|
|
31680
|
+
}
|
|
31681
|
+
);
|
|
31048
31682
|
};
|
|
31049
31683
|
StatDisplay.displayName = "StatDisplay";
|
|
31050
31684
|
}
|
|
@@ -45123,6 +45757,7 @@ var init_StatCard = __esm({
|
|
|
45123
45757
|
init_Box();
|
|
45124
45758
|
init_Stack();
|
|
45125
45759
|
init_Button();
|
|
45760
|
+
init_Sparkline();
|
|
45126
45761
|
init_useEventBus();
|
|
45127
45762
|
init_useTranslate();
|
|
45128
45763
|
init_Icon();
|
|
@@ -45292,32 +45927,7 @@ var init_StatCard = __esm({
|
|
|
45292
45927
|
] }),
|
|
45293
45928
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
45294
45929
|
Icon3 && /* @__PURE__ */ jsx(Box, { className: cn("p-3", iconBg), children: /* @__PURE__ */ jsx(Icon3, { className: cn("h-6 w-6", iconColor) }) }),
|
|
45295
|
-
sparklineData && sparklineData.length > 1 && (
|
|
45296
|
-
const w = 80;
|
|
45297
|
-
const h = 32;
|
|
45298
|
-
const pad = 2;
|
|
45299
|
-
const min = Math.min(...sparklineData);
|
|
45300
|
-
const max = Math.max(...sparklineData);
|
|
45301
|
-
const range = max - min || 1;
|
|
45302
|
-
const points = sparklineData.map((v, i) => {
|
|
45303
|
-
const x = pad + i / (sparklineData.length - 1) * (w - pad * 2);
|
|
45304
|
-
const y = pad + (1 - (v - min) / range) * (h - pad * 2);
|
|
45305
|
-
return `${x},${y}`;
|
|
45306
|
-
}).join(" ");
|
|
45307
|
-
const trending = sparklineData[sparklineData.length - 1] >= sparklineData[0];
|
|
45308
|
-
const strokeColor = trending ? "var(--color-success)" : "var(--color-error)";
|
|
45309
|
-
return /* @__PURE__ */ jsx("svg", { width: w, height: h, viewBox: `0 0 ${w} ${h}`, className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
|
|
45310
|
-
"polyline",
|
|
45311
|
-
{
|
|
45312
|
-
fill: "none",
|
|
45313
|
-
stroke: strokeColor,
|
|
45314
|
-
strokeWidth: "2",
|
|
45315
|
-
strokeLinecap: "round",
|
|
45316
|
-
strokeLinejoin: "round",
|
|
45317
|
-
points
|
|
45318
|
-
}
|
|
45319
|
-
) });
|
|
45320
|
-
})()
|
|
45930
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
45321
45931
|
] })
|
|
45322
45932
|
] }),
|
|
45323
45933
|
action && /* @__PURE__ */ jsxs(
|
|
@@ -52687,6 +53297,7 @@ var init_component_registry_generated = __esm({
|
|
|
52687
53297
|
init_DataGrid();
|
|
52688
53298
|
init_DataList();
|
|
52689
53299
|
init_DataTable();
|
|
53300
|
+
init_DateRangePicker();
|
|
52690
53301
|
init_DateRangeSelector();
|
|
52691
53302
|
init_DayCell();
|
|
52692
53303
|
init_DebuggerBoard();
|
|
@@ -52819,6 +53430,7 @@ var init_component_registry_generated = __esm({
|
|
|
52819
53430
|
init_Skeleton();
|
|
52820
53431
|
init_SocialProof();
|
|
52821
53432
|
init_SortableList();
|
|
53433
|
+
init_Sparkline();
|
|
52822
53434
|
init_Split();
|
|
52823
53435
|
init_SplitPane();
|
|
52824
53436
|
init_SplitSection();
|
|
@@ -52967,6 +53579,7 @@ var init_component_registry_generated = __esm({
|
|
|
52967
53579
|
"DataGrid": DataGrid,
|
|
52968
53580
|
"DataList": DataList,
|
|
52969
53581
|
"DataTable": DataTable,
|
|
53582
|
+
"DateRangePicker": DateRangePicker,
|
|
52970
53583
|
"DateRangeSelector": DateRangeSelector,
|
|
52971
53584
|
"DayCell": DayCell,
|
|
52972
53585
|
"DebuggerBoard": DebuggerBoard,
|
|
@@ -53128,6 +53741,7 @@ var init_component_registry_generated = __esm({
|
|
|
53128
53741
|
"SortableList": SortableList,
|
|
53129
53742
|
"Spacer": SpacerPattern,
|
|
53130
53743
|
"SpacerPattern": SpacerPattern,
|
|
53744
|
+
"Sparkline": Sparkline,
|
|
53131
53745
|
"Spinner": SpinnerPattern,
|
|
53132
53746
|
"SpinnerPattern": SpinnerPattern,
|
|
53133
53747
|
"Split": Split,
|
|
@@ -60434,8 +61048,19 @@ function OrbInspector({ node, schema, editable = false, userType = "builder", th
|
|
|
60434
61048
|
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] uppercase tracking-wider mb-2", children: t("Props") }),
|
|
60435
61049
|
/* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-1.5", children: Object.entries(patternDef.propsSchema).slice(0, 12).map(([propName, propSchema]) => {
|
|
60436
61050
|
const ps = propSchema;
|
|
60437
|
-
const
|
|
61051
|
+
const explicitValue = patternConfig ? patternConfig[propName] : void 0;
|
|
61052
|
+
const defaultValue = ps.default;
|
|
61053
|
+
const isImplicit = explicitValue === void 0 && defaultValue !== void 0;
|
|
61054
|
+
const currentValue = explicitValue !== void 0 ? explicitValue : defaultValue;
|
|
60438
61055
|
const displayValue = currentValue !== void 0 ? typeof currentValue === "object" ? JSON.stringify(currentValue) : String(currentValue) : "";
|
|
61056
|
+
inspectorLog.debug("prop-row", () => ({
|
|
61057
|
+
patternType: patternDef.type,
|
|
61058
|
+
patternId: selectedPattern?.patternId ?? "",
|
|
61059
|
+
propName,
|
|
61060
|
+
explicitValue: explicitValue === void 0 ? "<unset>" : JSON.stringify(explicitValue),
|
|
61061
|
+
defaultValue: defaultValue === void 0 ? "<unset>" : JSON.stringify(defaultValue),
|
|
61062
|
+
isImplicit: String(isImplicit)
|
|
61063
|
+
}));
|
|
60439
61064
|
return /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2", children: [
|
|
60440
61065
|
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[11px] w-20 shrink-0 font-mono", children: propName }),
|
|
60441
61066
|
editable ? /* @__PURE__ */ jsx(
|