@almadar/ui 4.51.14 → 4.51.16
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 +807 -154
- package/dist/avl/index.js +807 -154
- package/dist/components/atoms/Sparkline.d.ts +30 -0
- package/dist/components/atoms/index.d.ts +1 -0
- package/dist/components/index.cjs +797 -153
- package/dist/components/index.js +798 -154
- 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 +795 -153
- package/dist/providers/index.js +795 -153
- package/dist/runtime/index.cjs +795 -153
- package/dist/runtime/index.js +795 -153
- 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 })
|
|
@@ -24938,7 +25395,6 @@ function useDataDnd(args) {
|
|
|
24938
25395
|
const raw = it[dndItemIdField];
|
|
24939
25396
|
return raw ?? `__idx_${idx}`;
|
|
24940
25397
|
}),
|
|
24941
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24942
25398
|
[itemIdsSignature]
|
|
24943
25399
|
);
|
|
24944
25400
|
const itemsContentSig = items.map((it, idx) => String(it[dndItemIdField] ?? `__${idx}`)).join("|");
|
|
@@ -26532,7 +26988,16 @@ var init_FilterGroup = __esm({
|
|
|
26532
26988
|
onClear: () => handleFilterSelect(`${filter.field}_to`, null)
|
|
26533
26989
|
}
|
|
26534
26990
|
)
|
|
26535
|
-
] }) : /* @__PURE__ */ jsx(
|
|
26991
|
+
] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsx(
|
|
26992
|
+
Input,
|
|
26993
|
+
{
|
|
26994
|
+
value: selectedValues[filter.field] || "",
|
|
26995
|
+
onChange: (e) => handleFilterSelect(filter.field, e.target.value || null),
|
|
26996
|
+
placeholder: filter.label,
|
|
26997
|
+
clearable: true,
|
|
26998
|
+
onClear: () => handleFilterSelect(filter.field, null)
|
|
26999
|
+
}
|
|
27000
|
+
) : /* @__PURE__ */ jsx(
|
|
26536
27001
|
Select,
|
|
26537
27002
|
{
|
|
26538
27003
|
value: selectedValues[filter.field] || "all",
|
|
@@ -26599,7 +27064,17 @@ var init_FilterGroup = __esm({
|
|
|
26599
27064
|
className: "text-sm min-w-[100px]"
|
|
26600
27065
|
}
|
|
26601
27066
|
)
|
|
26602
|
-
] }) : /* @__PURE__ */ jsx(
|
|
27067
|
+
] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsx(
|
|
27068
|
+
Input,
|
|
27069
|
+
{
|
|
27070
|
+
value: selectedValues[filter.field] || "",
|
|
27071
|
+
onChange: (e) => handleFilterSelect(filter.field, e.target.value || null),
|
|
27072
|
+
placeholder: filter.label,
|
|
27073
|
+
clearable: true,
|
|
27074
|
+
onClear: () => handleFilterSelect(filter.field, null),
|
|
27075
|
+
className: "text-sm"
|
|
27076
|
+
}
|
|
27077
|
+
) : /* @__PURE__ */ jsx(
|
|
26603
27078
|
Select,
|
|
26604
27079
|
{
|
|
26605
27080
|
value: selectedValues[filter.field] || "all",
|
|
@@ -26704,7 +27179,17 @@ var init_FilterGroup = __esm({
|
|
|
26704
27179
|
className: "min-w-[130px]"
|
|
26705
27180
|
}
|
|
26706
27181
|
)
|
|
26707
|
-
] }) : /* @__PURE__ */ jsx(
|
|
27182
|
+
] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsx(
|
|
27183
|
+
Input,
|
|
27184
|
+
{
|
|
27185
|
+
value: selectedValues[filter.field] || "",
|
|
27186
|
+
onChange: (e) => handleFilterSelect(filter.field, e.target.value || null),
|
|
27187
|
+
placeholder: filter.label,
|
|
27188
|
+
clearable: true,
|
|
27189
|
+
onClear: () => handleFilterSelect(filter.field, null),
|
|
27190
|
+
className: "min-w-[160px]"
|
|
27191
|
+
}
|
|
27192
|
+
) : /* @__PURE__ */ jsx(
|
|
26708
27193
|
Select,
|
|
26709
27194
|
{
|
|
26710
27195
|
value: selectedValues[filter.field] || "all",
|
|
@@ -27993,6 +28478,151 @@ var init_FlipCard = __esm({
|
|
|
27993
28478
|
FlipCard.displayName = "FlipCard";
|
|
27994
28479
|
}
|
|
27995
28480
|
});
|
|
28481
|
+
function toISODate(d) {
|
|
28482
|
+
return d.toISOString().slice(0, 10);
|
|
28483
|
+
}
|
|
28484
|
+
function startOfMonth(d) {
|
|
28485
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
28486
|
+
}
|
|
28487
|
+
function startOfQuarter(d) {
|
|
28488
|
+
return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
|
|
28489
|
+
}
|
|
28490
|
+
function startOfYear(d) {
|
|
28491
|
+
return new Date(d.getFullYear(), 0, 1);
|
|
28492
|
+
}
|
|
28493
|
+
function daysAgo(n) {
|
|
28494
|
+
const d = /* @__PURE__ */ new Date();
|
|
28495
|
+
d.setDate(d.getDate() - n);
|
|
28496
|
+
return d;
|
|
28497
|
+
}
|
|
28498
|
+
var DEFAULT_PRESETS, DateRangePicker;
|
|
28499
|
+
var init_DateRangePicker = __esm({
|
|
28500
|
+
"components/molecules/DateRangePicker.tsx"() {
|
|
28501
|
+
"use client";
|
|
28502
|
+
init_cn();
|
|
28503
|
+
init_Button();
|
|
28504
|
+
init_Input();
|
|
28505
|
+
init_Stack();
|
|
28506
|
+
init_Typography();
|
|
28507
|
+
init_useEventBus();
|
|
28508
|
+
DEFAULT_PRESETS = [
|
|
28509
|
+
{
|
|
28510
|
+
label: "Last 7 days",
|
|
28511
|
+
value: "7d",
|
|
28512
|
+
range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28513
|
+
},
|
|
28514
|
+
{
|
|
28515
|
+
label: "Last 30 days",
|
|
28516
|
+
value: "30d",
|
|
28517
|
+
range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28518
|
+
},
|
|
28519
|
+
{
|
|
28520
|
+
label: "This Month",
|
|
28521
|
+
value: "month",
|
|
28522
|
+
range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28523
|
+
},
|
|
28524
|
+
{
|
|
28525
|
+
label: "This Quarter",
|
|
28526
|
+
value: "quarter",
|
|
28527
|
+
range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28528
|
+
},
|
|
28529
|
+
{
|
|
28530
|
+
label: "YTD",
|
|
28531
|
+
value: "ytd",
|
|
28532
|
+
range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28533
|
+
}
|
|
28534
|
+
];
|
|
28535
|
+
DateRangePicker = ({
|
|
28536
|
+
from: fromProp,
|
|
28537
|
+
to: toProp,
|
|
28538
|
+
event,
|
|
28539
|
+
onChange,
|
|
28540
|
+
presets = DEFAULT_PRESETS,
|
|
28541
|
+
fromLabel = "From",
|
|
28542
|
+
toLabel = "To",
|
|
28543
|
+
className
|
|
28544
|
+
}) => {
|
|
28545
|
+
const eventBus = useEventBus();
|
|
28546
|
+
const [from, setFrom] = useState(fromProp ?? "");
|
|
28547
|
+
const [to, setTo] = useState(toProp ?? "");
|
|
28548
|
+
const [activePreset, setActivePreset] = useState(null);
|
|
28549
|
+
const emit = useCallback(
|
|
28550
|
+
(range) => {
|
|
28551
|
+
onChange?.(range);
|
|
28552
|
+
if (event) eventBus.emit(`UI:${event}`, range);
|
|
28553
|
+
},
|
|
28554
|
+
[onChange, event, eventBus]
|
|
28555
|
+
);
|
|
28556
|
+
const handleFromChange = useCallback(
|
|
28557
|
+
(next) => {
|
|
28558
|
+
setFrom(next);
|
|
28559
|
+
setActivePreset(null);
|
|
28560
|
+
emit({ from: next, to });
|
|
28561
|
+
},
|
|
28562
|
+
[to, emit]
|
|
28563
|
+
);
|
|
28564
|
+
const handleToChange = useCallback(
|
|
28565
|
+
(next) => {
|
|
28566
|
+
setTo(next);
|
|
28567
|
+
setActivePreset(null);
|
|
28568
|
+
emit({ from, to: next });
|
|
28569
|
+
},
|
|
28570
|
+
[from, emit]
|
|
28571
|
+
);
|
|
28572
|
+
const handlePreset = useCallback(
|
|
28573
|
+
(preset) => {
|
|
28574
|
+
const range = preset.range();
|
|
28575
|
+
setFrom(range.from);
|
|
28576
|
+
setTo(range.to);
|
|
28577
|
+
setActivePreset(preset.value);
|
|
28578
|
+
emit(range);
|
|
28579
|
+
},
|
|
28580
|
+
[emit]
|
|
28581
|
+
);
|
|
28582
|
+
const presetButtons = useMemo(
|
|
28583
|
+
() => presets.map((preset) => /* @__PURE__ */ jsx(
|
|
28584
|
+
Button,
|
|
28585
|
+
{
|
|
28586
|
+
variant: activePreset === preset.value ? "primary" : "ghost",
|
|
28587
|
+
size: "sm",
|
|
28588
|
+
onClick: () => handlePreset(preset),
|
|
28589
|
+
children: preset.label
|
|
28590
|
+
},
|
|
28591
|
+
preset.value
|
|
28592
|
+
)),
|
|
28593
|
+
[presets, activePreset, handlePreset]
|
|
28594
|
+
);
|
|
28595
|
+
return /* @__PURE__ */ jsxs(VStack, { gap: "sm", className: cn(className), children: [
|
|
28596
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "md", align: "end", children: [
|
|
28597
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
28598
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: fromLabel }),
|
|
28599
|
+
/* @__PURE__ */ jsx(
|
|
28600
|
+
Input,
|
|
28601
|
+
{
|
|
28602
|
+
type: "date",
|
|
28603
|
+
value: from,
|
|
28604
|
+
onChange: (e) => handleFromChange(e.target.value)
|
|
28605
|
+
}
|
|
28606
|
+
)
|
|
28607
|
+
] }),
|
|
28608
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
|
|
28609
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: toLabel }),
|
|
28610
|
+
/* @__PURE__ */ jsx(
|
|
28611
|
+
Input,
|
|
28612
|
+
{
|
|
28613
|
+
type: "date",
|
|
28614
|
+
value: to,
|
|
28615
|
+
onChange: (e) => handleToChange(e.target.value)
|
|
28616
|
+
}
|
|
28617
|
+
)
|
|
28618
|
+
] })
|
|
28619
|
+
] }),
|
|
28620
|
+
presets.length > 0 && /* @__PURE__ */ jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
|
|
28621
|
+
] });
|
|
28622
|
+
};
|
|
28623
|
+
DateRangePicker.displayName = "DateRangePicker";
|
|
28624
|
+
}
|
|
28625
|
+
});
|
|
27996
28626
|
var DEFAULT_OPTIONS, DateRangeSelector;
|
|
27997
28627
|
var init_DateRangeSelector = __esm({
|
|
27998
28628
|
"components/molecules/DateRangeSelector.tsx"() {
|
|
@@ -30964,7 +31594,9 @@ var init_StatDisplay = __esm({
|
|
|
30964
31594
|
init_Typography();
|
|
30965
31595
|
init_Box();
|
|
30966
31596
|
init_Stack();
|
|
31597
|
+
init_Sparkline();
|
|
30967
31598
|
init_Icon();
|
|
31599
|
+
init_useEventBus();
|
|
30968
31600
|
variantColor = {
|
|
30969
31601
|
default: "text-foreground",
|
|
30970
31602
|
primary: "text-primary",
|
|
@@ -30979,6 +31611,10 @@ var init_StatDisplay = __esm({
|
|
|
30979
31611
|
max,
|
|
30980
31612
|
target,
|
|
30981
31613
|
trend,
|
|
31614
|
+
trendPolarity = "higher-is-better",
|
|
31615
|
+
trendFormat = "absolute",
|
|
31616
|
+
sparklineData,
|
|
31617
|
+
clickEvent,
|
|
30982
31618
|
prefix,
|
|
30983
31619
|
suffix,
|
|
30984
31620
|
icon: iconProp,
|
|
@@ -30992,6 +31628,10 @@ var init_StatDisplay = __esm({
|
|
|
30992
31628
|
isLoading = false,
|
|
30993
31629
|
error = null
|
|
30994
31630
|
}) => {
|
|
31631
|
+
const eventBus = useEventBus();
|
|
31632
|
+
const handleClick = useCallback(() => {
|
|
31633
|
+
if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
|
|
31634
|
+
}, [clickEvent, eventBus, label]);
|
|
30995
31635
|
const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
|
|
30996
31636
|
const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
|
|
30997
31637
|
const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
|
|
@@ -31002,7 +31642,10 @@ var init_StatDisplay = __esm({
|
|
|
31002
31642
|
const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
|
|
31003
31643
|
const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
|
|
31004
31644
|
const trendUp = showTrend && trend > 0;
|
|
31005
|
-
const
|
|
31645
|
+
const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
|
|
31646
|
+
const trendMagnitude = Math.abs(trend);
|
|
31647
|
+
const trendSuffix = trendFormat === "percent" ? "%" : "";
|
|
31648
|
+
const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
|
|
31006
31649
|
if (error) {
|
|
31007
31650
|
return /* @__PURE__ */ jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsx(Typography, { variant: "small", color: "error", children: error.message }) });
|
|
31008
31651
|
}
|
|
@@ -31013,38 +31656,57 @@ var init_StatDisplay = __esm({
|
|
|
31013
31656
|
] }) });
|
|
31014
31657
|
}
|
|
31015
31658
|
if (compact) {
|
|
31016
|
-
return /* @__PURE__ */ jsxs(
|
|
31017
|
-
|
|
31018
|
-
|
|
31019
|
-
|
|
31020
|
-
|
|
31021
|
-
|
|
31022
|
-
|
|
31659
|
+
return /* @__PURE__ */ jsxs(
|
|
31660
|
+
HStack,
|
|
31661
|
+
{
|
|
31662
|
+
gap: "sm",
|
|
31663
|
+
className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
|
|
31664
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31665
|
+
children: [
|
|
31666
|
+
ResolvedIcon && /* @__PURE__ */ jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
|
|
31667
|
+
typeof iconProp !== "string" && iconProp,
|
|
31668
|
+
/* @__PURE__ */ jsx(Typography, { variant: "caption", color: "secondary", children: label }),
|
|
31669
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31670
|
+
showTrend && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
|
|
31671
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
|
|
31672
|
+
]
|
|
31673
|
+
}
|
|
31674
|
+
);
|
|
31023
31675
|
}
|
|
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
|
-
|
|
31676
|
+
return /* @__PURE__ */ jsx(
|
|
31677
|
+
Card,
|
|
31678
|
+
{
|
|
31679
|
+
className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
|
|
31680
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31681
|
+
children: /* @__PURE__ */ jsxs(HStack, { align: "start", justify: "between", children: [
|
|
31682
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
|
|
31683
|
+
/* @__PURE__ */ jsx(Typography, { variant: "overline", color: "secondary", children: label }),
|
|
31684
|
+
/* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "end", children: [
|
|
31685
|
+
/* @__PURE__ */ jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31686
|
+
showTrend && /* @__PURE__ */ jsx(
|
|
31687
|
+
Typography,
|
|
31688
|
+
{
|
|
31689
|
+
variant: "caption",
|
|
31690
|
+
className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
|
|
31691
|
+
children: trendLabel
|
|
31692
|
+
}
|
|
31693
|
+
)
|
|
31694
|
+
] }),
|
|
31695
|
+
showTarget && /* @__PURE__ */ jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsx(
|
|
31696
|
+
Box,
|
|
31697
|
+
{
|
|
31698
|
+
className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
|
|
31699
|
+
style: { width: `${targetPct}%` }
|
|
31700
|
+
}
|
|
31701
|
+
) })
|
|
31702
|
+
] }),
|
|
31703
|
+
/* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
31704
|
+
(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 }),
|
|
31705
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
31706
|
+
] })
|
|
31707
|
+
] })
|
|
31708
|
+
}
|
|
31709
|
+
);
|
|
31048
31710
|
};
|
|
31049
31711
|
StatDisplay.displayName = "StatDisplay";
|
|
31050
31712
|
}
|
|
@@ -45123,6 +45785,7 @@ var init_StatCard = __esm({
|
|
|
45123
45785
|
init_Box();
|
|
45124
45786
|
init_Stack();
|
|
45125
45787
|
init_Button();
|
|
45788
|
+
init_Sparkline();
|
|
45126
45789
|
init_useEventBus();
|
|
45127
45790
|
init_useTranslate();
|
|
45128
45791
|
init_Icon();
|
|
@@ -45292,32 +45955,7 @@ var init_StatCard = __esm({
|
|
|
45292
45955
|
] }),
|
|
45293
45956
|
/* @__PURE__ */ jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
45294
45957
|
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
|
-
})()
|
|
45958
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
45321
45959
|
] })
|
|
45322
45960
|
] }),
|
|
45323
45961
|
action && /* @__PURE__ */ jsxs(
|
|
@@ -52687,6 +53325,7 @@ var init_component_registry_generated = __esm({
|
|
|
52687
53325
|
init_DataGrid();
|
|
52688
53326
|
init_DataList();
|
|
52689
53327
|
init_DataTable();
|
|
53328
|
+
init_DateRangePicker();
|
|
52690
53329
|
init_DateRangeSelector();
|
|
52691
53330
|
init_DayCell();
|
|
52692
53331
|
init_DebuggerBoard();
|
|
@@ -52819,6 +53458,7 @@ var init_component_registry_generated = __esm({
|
|
|
52819
53458
|
init_Skeleton();
|
|
52820
53459
|
init_SocialProof();
|
|
52821
53460
|
init_SortableList();
|
|
53461
|
+
init_Sparkline();
|
|
52822
53462
|
init_Split();
|
|
52823
53463
|
init_SplitPane();
|
|
52824
53464
|
init_SplitSection();
|
|
@@ -52967,6 +53607,7 @@ var init_component_registry_generated = __esm({
|
|
|
52967
53607
|
"DataGrid": DataGrid,
|
|
52968
53608
|
"DataList": DataList,
|
|
52969
53609
|
"DataTable": DataTable,
|
|
53610
|
+
"DateRangePicker": DateRangePicker,
|
|
52970
53611
|
"DateRangeSelector": DateRangeSelector,
|
|
52971
53612
|
"DayCell": DayCell,
|
|
52972
53613
|
"DebuggerBoard": DebuggerBoard,
|
|
@@ -53128,6 +53769,7 @@ var init_component_registry_generated = __esm({
|
|
|
53128
53769
|
"SortableList": SortableList,
|
|
53129
53770
|
"Spacer": SpacerPattern,
|
|
53130
53771
|
"SpacerPattern": SpacerPattern,
|
|
53772
|
+
"Sparkline": Sparkline,
|
|
53131
53773
|
"Spinner": SpinnerPattern,
|
|
53132
53774
|
"SpinnerPattern": SpinnerPattern,
|
|
53133
53775
|
"Split": Split,
|
|
@@ -60434,8 +61076,19 @@ function OrbInspector({ node, schema, editable = false, userType = "builder", th
|
|
|
60434
61076
|
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] uppercase tracking-wider mb-2", children: t("Props") }),
|
|
60435
61077
|
/* @__PURE__ */ jsx(Box, { className: "flex flex-col gap-1.5", children: Object.entries(patternDef.propsSchema).slice(0, 12).map(([propName, propSchema]) => {
|
|
60436
61078
|
const ps = propSchema;
|
|
60437
|
-
const
|
|
61079
|
+
const explicitValue = patternConfig ? patternConfig[propName] : void 0;
|
|
61080
|
+
const defaultValue = ps.default;
|
|
61081
|
+
const isImplicit = explicitValue === void 0 && defaultValue !== void 0;
|
|
61082
|
+
const currentValue = explicitValue !== void 0 ? explicitValue : defaultValue;
|
|
60438
61083
|
const displayValue = currentValue !== void 0 ? typeof currentValue === "object" ? JSON.stringify(currentValue) : String(currentValue) : "";
|
|
61084
|
+
inspectorLog.debug("prop-row", () => ({
|
|
61085
|
+
patternType: patternDef.type,
|
|
61086
|
+
patternId: selectedPattern?.patternId ?? "",
|
|
61087
|
+
propName,
|
|
61088
|
+
explicitValue: explicitValue === void 0 ? "<unset>" : JSON.stringify(explicitValue),
|
|
61089
|
+
defaultValue: defaultValue === void 0 ? "<unset>" : JSON.stringify(defaultValue),
|
|
61090
|
+
isImplicit: String(isImplicit)
|
|
61091
|
+
}));
|
|
60439
61092
|
return /* @__PURE__ */ jsxs(Box, { className: "flex items-center gap-2", children: [
|
|
60440
61093
|
/* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-muted-foreground text-[11px] w-20 shrink-0 font-mono", children: propName }),
|
|
60441
61094
|
editable ? /* @__PURE__ */ jsx(
|