@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.cjs
CHANGED
|
@@ -8464,6 +8464,67 @@ var init_Radio = __esm({
|
|
|
8464
8464
|
Radio.displayName = "Radio";
|
|
8465
8465
|
}
|
|
8466
8466
|
});
|
|
8467
|
+
var COLOR_VAR, Sparkline;
|
|
8468
|
+
var init_Sparkline = __esm({
|
|
8469
|
+
"components/atoms/Sparkline.tsx"() {
|
|
8470
|
+
init_cn();
|
|
8471
|
+
COLOR_VAR = {
|
|
8472
|
+
primary: "var(--color-primary)",
|
|
8473
|
+
success: "var(--color-success)",
|
|
8474
|
+
warning: "var(--color-warning)",
|
|
8475
|
+
error: "var(--color-error)",
|
|
8476
|
+
info: "var(--color-info)",
|
|
8477
|
+
muted: "var(--color-muted-foreground)"
|
|
8478
|
+
};
|
|
8479
|
+
Sparkline = ({
|
|
8480
|
+
data,
|
|
8481
|
+
color = "auto",
|
|
8482
|
+
width = 80,
|
|
8483
|
+
height = 32,
|
|
8484
|
+
strokeWidth = 2,
|
|
8485
|
+
fill = false,
|
|
8486
|
+
className
|
|
8487
|
+
}) => {
|
|
8488
|
+
if (data.length < 2) return null;
|
|
8489
|
+
const pad = 2;
|
|
8490
|
+
const min = Math.min(...data);
|
|
8491
|
+
const max = Math.max(...data);
|
|
8492
|
+
const range = max - min || 1;
|
|
8493
|
+
const points = data.map((v, i) => {
|
|
8494
|
+
const x = pad + i / (data.length - 1) * (width - pad * 2);
|
|
8495
|
+
const y = pad + (1 - (v - min) / range) * (height - pad * 2);
|
|
8496
|
+
return `${x},${y}`;
|
|
8497
|
+
}).join(" ");
|
|
8498
|
+
const resolvedColor = color === "auto" ? data[data.length - 1] >= data[0] ? COLOR_VAR.success : COLOR_VAR.error : COLOR_VAR[color];
|
|
8499
|
+
const areaPath = fill ? `M ${pad},${height - pad} L ${points.split(" ").join(" L ")} L ${width - pad},${height - pad} Z` : null;
|
|
8500
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8501
|
+
"svg",
|
|
8502
|
+
{
|
|
8503
|
+
width,
|
|
8504
|
+
height,
|
|
8505
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
8506
|
+
className: cn("flex-shrink-0", className),
|
|
8507
|
+
"aria-hidden": "true",
|
|
8508
|
+
children: [
|
|
8509
|
+
areaPath && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: resolvedColor, opacity: 0.15 }),
|
|
8510
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8511
|
+
"polyline",
|
|
8512
|
+
{
|
|
8513
|
+
fill: "none",
|
|
8514
|
+
stroke: resolvedColor,
|
|
8515
|
+
strokeWidth,
|
|
8516
|
+
strokeLinecap: "round",
|
|
8517
|
+
strokeLinejoin: "round",
|
|
8518
|
+
points
|
|
8519
|
+
}
|
|
8520
|
+
)
|
|
8521
|
+
]
|
|
8522
|
+
}
|
|
8523
|
+
);
|
|
8524
|
+
};
|
|
8525
|
+
Sparkline.displayName = "Sparkline";
|
|
8526
|
+
}
|
|
8527
|
+
});
|
|
8467
8528
|
var Switch;
|
|
8468
8529
|
var init_Switch = __esm({
|
|
8469
8530
|
"components/atoms/Switch.tsx"() {
|
|
@@ -13697,7 +13758,7 @@ var init_MapView = __esm({
|
|
|
13697
13758
|
shadowSize: [41, 41]
|
|
13698
13759
|
});
|
|
13699
13760
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
13700
|
-
const { useEffect: useEffect87, useRef: useRef88, useCallback:
|
|
13761
|
+
const { useEffect: useEffect87, useRef: useRef88, useCallback: useCallback128, useState: useState121 } = React93__namespace.default;
|
|
13701
13762
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
13702
13763
|
const { useEventBus: useEventBus3 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
13703
13764
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -13742,8 +13803,8 @@ var init_MapView = __esm({
|
|
|
13742
13803
|
showAttribution = true
|
|
13743
13804
|
}) {
|
|
13744
13805
|
const eventBus = useEventBus3();
|
|
13745
|
-
const [clickedPosition, setClickedPosition] =
|
|
13746
|
-
const handleMapClick =
|
|
13806
|
+
const [clickedPosition, setClickedPosition] = useState121(null);
|
|
13807
|
+
const handleMapClick = useCallback128((lat, lng) => {
|
|
13747
13808
|
if (showClickedPin) {
|
|
13748
13809
|
setClickedPosition({ lat, lng });
|
|
13749
13810
|
}
|
|
@@ -13752,7 +13813,7 @@ var init_MapView = __esm({
|
|
|
13752
13813
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
13753
13814
|
}
|
|
13754
13815
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
13755
|
-
const handleMarkerClick =
|
|
13816
|
+
const handleMarkerClick = useCallback128((marker) => {
|
|
13756
13817
|
onMarkerClick?.(marker);
|
|
13757
13818
|
if (markerClickEvent) {
|
|
13758
13819
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -22865,7 +22926,7 @@ var init_CastleTemplate = __esm({
|
|
|
22865
22926
|
CastleTemplate.displayName = "CastleTemplate";
|
|
22866
22927
|
}
|
|
22867
22928
|
});
|
|
22868
|
-
var CHART_COLORS, BarChart, PieChart, LineChart, Chart;
|
|
22929
|
+
var CHART_COLORS, seriesColor, monthFormatter, formatTimeLabel, BarChart, PieChart, LineChart, ScatterChart, Chart;
|
|
22869
22930
|
var init_Chart = __esm({
|
|
22870
22931
|
"components/organisms/Chart.tsx"() {
|
|
22871
22932
|
"use client";
|
|
@@ -22885,38 +22946,159 @@ var init_Chart = __esm({
|
|
|
22885
22946
|
"var(--color-info)",
|
|
22886
22947
|
"var(--color-accent)"
|
|
22887
22948
|
];
|
|
22888
|
-
|
|
22889
|
-
|
|
22890
|
-
|
|
22891
|
-
|
|
22892
|
-
|
|
22893
|
-
|
|
22894
|
-
|
|
22895
|
-
|
|
22896
|
-
|
|
22897
|
-
|
|
22898
|
-
|
|
22899
|
-
|
|
22900
|
-
|
|
22901
|
-
|
|
22902
|
-
|
|
22903
|
-
|
|
22904
|
-
|
|
22949
|
+
seriesColor = (series, idx) => series.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
22950
|
+
monthFormatter = new Intl.DateTimeFormat(void 0, {
|
|
22951
|
+
month: "short",
|
|
22952
|
+
year: "2-digit"
|
|
22953
|
+
});
|
|
22954
|
+
formatTimeLabel = (raw) => {
|
|
22955
|
+
const parsed = new Date(raw);
|
|
22956
|
+
if (Number.isNaN(parsed.getTime())) return raw;
|
|
22957
|
+
return monthFormatter.format(parsed);
|
|
22958
|
+
};
|
|
22959
|
+
BarChart = ({ series, height, showValues, stack, timeAxis, histogram = false, onPointClick }) => {
|
|
22960
|
+
const categories = React93.useMemo(() => {
|
|
22961
|
+
const set = [];
|
|
22962
|
+
const seen = /* @__PURE__ */ new Set();
|
|
22963
|
+
for (const s of series) {
|
|
22964
|
+
for (const p2 of s.data) {
|
|
22965
|
+
if (!seen.has(p2.label)) {
|
|
22966
|
+
seen.add(p2.label);
|
|
22967
|
+
set.push(p2.label);
|
|
22905
22968
|
}
|
|
22906
|
-
|
|
22907
|
-
|
|
22908
|
-
|
|
22909
|
-
|
|
22910
|
-
|
|
22911
|
-
|
|
22912
|
-
|
|
22913
|
-
|
|
22969
|
+
}
|
|
22970
|
+
}
|
|
22971
|
+
return set;
|
|
22972
|
+
}, [series]);
|
|
22973
|
+
const valueAt = React93.useCallback(
|
|
22974
|
+
(s, label) => {
|
|
22975
|
+
const p2 = s.data.find((d) => d.label === label);
|
|
22976
|
+
return p2 ? p2.value : 0;
|
|
22977
|
+
},
|
|
22978
|
+
[]
|
|
22979
|
+
);
|
|
22980
|
+
const columnTotals = React93.useMemo(() => {
|
|
22981
|
+
if (stack === "none") return null;
|
|
22982
|
+
return categories.map(
|
|
22983
|
+
(label) => series.reduce((sum, s) => sum + valueAt(s, label), 0)
|
|
22984
|
+
);
|
|
22985
|
+
}, [categories, series, stack, valueAt]);
|
|
22986
|
+
const maxValue = React93.useMemo(() => {
|
|
22987
|
+
if (stack === "normalize") return 100;
|
|
22988
|
+
if (stack === "stack" && columnTotals) {
|
|
22989
|
+
return Math.max(...columnTotals, 1);
|
|
22990
|
+
}
|
|
22991
|
+
let m = 1;
|
|
22992
|
+
for (const s of series) {
|
|
22993
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
22994
|
+
}
|
|
22995
|
+
return m;
|
|
22996
|
+
}, [series, stack, columnTotals]);
|
|
22997
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
22998
|
+
HStack,
|
|
22999
|
+
{
|
|
23000
|
+
gap: histogram ? "none" : "xs",
|
|
23001
|
+
align: "end",
|
|
23002
|
+
className: "w-full",
|
|
23003
|
+
style: { height },
|
|
23004
|
+
children: categories.map((label, catIdx) => {
|
|
23005
|
+
const displayLabel = timeAxis ? formatTimeLabel(label) : label;
|
|
23006
|
+
if (stack === "none") {
|
|
23007
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
23008
|
+
VStack,
|
|
23009
|
+
{
|
|
23010
|
+
gap: "xs",
|
|
23011
|
+
align: "center",
|
|
23012
|
+
flex: true,
|
|
23013
|
+
className: "min-w-0",
|
|
23014
|
+
children: [
|
|
23015
|
+
/* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: histogram ? "none" : "xs", align: "end", className: "w-full", style: { height: "100%" }, children: series.map((s, sIdx) => {
|
|
23016
|
+
const value = valueAt(s, label);
|
|
23017
|
+
const barHeight = value / maxValue * 100;
|
|
23018
|
+
const color = seriesColor(s, sIdx);
|
|
23019
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23020
|
+
Box,
|
|
23021
|
+
{
|
|
23022
|
+
className: cn(
|
|
23023
|
+
"rounded-t-sm transition-all duration-500 ease-out min-h-[4px] cursor-pointer hover:opacity-80",
|
|
23024
|
+
histogram ? "flex-1 mx-0" : "flex-1"
|
|
23025
|
+
),
|
|
23026
|
+
style: {
|
|
23027
|
+
height: `${barHeight}%`,
|
|
23028
|
+
backgroundColor: color
|
|
23029
|
+
},
|
|
23030
|
+
onClick: () => onPointClick?.(
|
|
23031
|
+
{ label, value, color },
|
|
23032
|
+
s.name
|
|
23033
|
+
),
|
|
23034
|
+
title: `${s.name}: ${value}`
|
|
23035
|
+
},
|
|
23036
|
+
s.name
|
|
23037
|
+
);
|
|
23038
|
+
}) }),
|
|
23039
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "tabular-nums", children: valueAt(series[0], label) }),
|
|
23040
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23041
|
+
Typography,
|
|
23042
|
+
{
|
|
23043
|
+
variant: "caption",
|
|
23044
|
+
color: "secondary",
|
|
23045
|
+
className: "truncate w-full text-center",
|
|
23046
|
+
children: displayLabel
|
|
23047
|
+
}
|
|
23048
|
+
)
|
|
23049
|
+
]
|
|
23050
|
+
},
|
|
23051
|
+
label
|
|
23052
|
+
);
|
|
22914
23053
|
}
|
|
22915
|
-
|
|
22916
|
-
|
|
22917
|
-
|
|
23054
|
+
const total = columnTotals?.[catIdx] ?? 1;
|
|
23055
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
23056
|
+
VStack,
|
|
23057
|
+
{
|
|
23058
|
+
gap: "xs",
|
|
23059
|
+
align: "center",
|
|
23060
|
+
flex: true,
|
|
23061
|
+
className: "min-w-0",
|
|
23062
|
+
children: [
|
|
23063
|
+
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", className: "w-full", style: { height: "100%" }, justify: "end", children: series.map((s, sIdx) => {
|
|
23064
|
+
const value = valueAt(s, label);
|
|
23065
|
+
const ratio = stack === "normalize" ? total === 0 ? 0 : value / total * 100 : value / maxValue * 100;
|
|
23066
|
+
const color = seriesColor(s, sIdx);
|
|
23067
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23068
|
+
Box,
|
|
23069
|
+
{
|
|
23070
|
+
className: "w-full transition-all duration-500 ease-out cursor-pointer hover:opacity-80",
|
|
23071
|
+
style: {
|
|
23072
|
+
height: `${ratio}%`,
|
|
23073
|
+
backgroundColor: color
|
|
23074
|
+
},
|
|
23075
|
+
onClick: () => onPointClick?.(
|
|
23076
|
+
{ label, value, color },
|
|
23077
|
+
s.name
|
|
23078
|
+
),
|
|
23079
|
+
title: `${s.name}: ${value}`
|
|
23080
|
+
},
|
|
23081
|
+
s.name
|
|
23082
|
+
);
|
|
23083
|
+
}) }),
|
|
23084
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23085
|
+
Typography,
|
|
23086
|
+
{
|
|
23087
|
+
variant: "caption",
|
|
23088
|
+
color: "secondary",
|
|
23089
|
+
className: "truncate w-full text-center",
|
|
23090
|
+
children: displayLabel
|
|
23091
|
+
}
|
|
23092
|
+
)
|
|
23093
|
+
]
|
|
23094
|
+
},
|
|
23095
|
+
label
|
|
23096
|
+
);
|
|
23097
|
+
})
|
|
23098
|
+
}
|
|
23099
|
+
);
|
|
22918
23100
|
};
|
|
22919
|
-
PieChart = ({ data, height, showValues, donut = false }) => {
|
|
23101
|
+
PieChart = ({ data, height, showValues, donut = false, onPointClick }) => {
|
|
22920
23102
|
const total = data.reduce((sum, d) => sum + d.value, 0);
|
|
22921
23103
|
const size = Math.min(height, 200);
|
|
22922
23104
|
const radius = size / 2 - 8;
|
|
@@ -22962,7 +23144,11 @@ var init_Chart = __esm({
|
|
|
22962
23144
|
fill: seg.color,
|
|
22963
23145
|
stroke: "var(--color-card)",
|
|
22964
23146
|
strokeWidth: "2",
|
|
22965
|
-
className: "transition-opacity duration-200 hover:opacity-80"
|
|
23147
|
+
className: "transition-opacity duration-200 hover:opacity-80 cursor-pointer",
|
|
23148
|
+
onClick: () => onPointClick?.(
|
|
23149
|
+
{ label: seg.label, value: seg.value, color: seg.color },
|
|
23150
|
+
"default"
|
|
23151
|
+
)
|
|
22966
23152
|
},
|
|
22967
23153
|
idx
|
|
22968
23154
|
)),
|
|
@@ -22997,56 +23183,243 @@ var init_Chart = __esm({
|
|
|
22997
23183
|
] }, idx)) })
|
|
22998
23184
|
] });
|
|
22999
23185
|
};
|
|
23000
|
-
LineChart = ({
|
|
23001
|
-
const maxValue = Math.max(...data.map((d) => d.value), 1);
|
|
23186
|
+
LineChart = ({ series, height, showValues, fill = false, timeAxis, onPointClick }) => {
|
|
23002
23187
|
const width = 400;
|
|
23003
23188
|
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
23004
23189
|
const chartWidth = width - padding.left - padding.right;
|
|
23005
23190
|
const chartHeight = height - padding.top - padding.bottom;
|
|
23006
|
-
const
|
|
23007
|
-
|
|
23008
|
-
|
|
23009
|
-
|
|
23010
|
-
|
|
23011
|
-
|
|
23012
|
-
|
|
23013
|
-
|
|
23014
|
-
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
23015
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "100%", height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", children: [
|
|
23016
|
-
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
23017
|
-
const y = padding.top + chartHeight * (1 - frac);
|
|
23018
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23019
|
-
"line",
|
|
23020
|
-
{
|
|
23021
|
-
x1: padding.left,
|
|
23022
|
-
y1: y,
|
|
23023
|
-
x2: width - padding.right,
|
|
23024
|
-
y2: y,
|
|
23025
|
-
stroke: "var(--color-border)",
|
|
23026
|
-
strokeDasharray: "4 4",
|
|
23027
|
-
opacity: 0.5
|
|
23028
|
-
},
|
|
23029
|
-
frac
|
|
23030
|
-
);
|
|
23031
|
-
}),
|
|
23032
|
-
fill && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: "var(--color-primary)", opacity: 0.1 }),
|
|
23033
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: linePath, fill: "none", stroke: "var(--color-primary)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
23034
|
-
points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
23035
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: p2.x, cy: p2.y, r: "4", fill: "var(--color-card)", stroke: "var(--color-primary)", strokeWidth: "2" }),
|
|
23036
|
-
showValues && /* @__PURE__ */ jsxRuntime.jsx("text", { x: p2.x, y: p2.y - 10, textAnchor: "middle", fill: "var(--color-foreground)", fontSize: "10", fontWeight: "500", children: p2.value }),
|
|
23037
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23038
|
-
"text",
|
|
23039
|
-
{
|
|
23040
|
-
x: p2.x,
|
|
23041
|
-
y: height - 8,
|
|
23042
|
-
textAnchor: "middle",
|
|
23043
|
-
fill: "var(--color-muted-foreground)",
|
|
23044
|
-
fontSize: "9",
|
|
23045
|
-
children: p2.label
|
|
23191
|
+
const labels = React93.useMemo(() => {
|
|
23192
|
+
const seen = /* @__PURE__ */ new Set();
|
|
23193
|
+
const out = [];
|
|
23194
|
+
for (const s of series) {
|
|
23195
|
+
for (const p2 of s.data) {
|
|
23196
|
+
if (!seen.has(p2.label)) {
|
|
23197
|
+
seen.add(p2.label);
|
|
23198
|
+
out.push(p2.label);
|
|
23046
23199
|
}
|
|
23047
|
-
|
|
23048
|
-
|
|
23049
|
-
|
|
23200
|
+
}
|
|
23201
|
+
}
|
|
23202
|
+
return out;
|
|
23203
|
+
}, [series]);
|
|
23204
|
+
const maxValue = React93.useMemo(() => {
|
|
23205
|
+
let m = 1;
|
|
23206
|
+
for (const s of series) {
|
|
23207
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
23208
|
+
}
|
|
23209
|
+
return m;
|
|
23210
|
+
}, [series]);
|
|
23211
|
+
const xFor = React93.useCallback(
|
|
23212
|
+
(idx) => padding.left + idx / Math.max(labels.length - 1, 1) * chartWidth,
|
|
23213
|
+
[labels.length, chartWidth, padding.left]
|
|
23214
|
+
);
|
|
23215
|
+
const yFor = React93.useCallback(
|
|
23216
|
+
(value) => padding.top + chartHeight - value / maxValue * chartHeight,
|
|
23217
|
+
[maxValue, chartHeight, padding.top]
|
|
23218
|
+
);
|
|
23219
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
23220
|
+
"svg",
|
|
23221
|
+
{
|
|
23222
|
+
width: "100%",
|
|
23223
|
+
height,
|
|
23224
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
23225
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
23226
|
+
children: [
|
|
23227
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
23228
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
23229
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23230
|
+
"line",
|
|
23231
|
+
{
|
|
23232
|
+
x1: padding.left,
|
|
23233
|
+
y1: y,
|
|
23234
|
+
x2: width - padding.right,
|
|
23235
|
+
y2: y,
|
|
23236
|
+
stroke: "var(--color-border)",
|
|
23237
|
+
strokeDasharray: "4 4",
|
|
23238
|
+
opacity: 0.5
|
|
23239
|
+
},
|
|
23240
|
+
frac
|
|
23241
|
+
);
|
|
23242
|
+
}),
|
|
23243
|
+
series.map((s, sIdx) => {
|
|
23244
|
+
const color = seriesColor(s, sIdx);
|
|
23245
|
+
const points = labels.map((label, idx) => {
|
|
23246
|
+
const point = s.data.find((d) => d.label === label);
|
|
23247
|
+
return {
|
|
23248
|
+
x: xFor(idx),
|
|
23249
|
+
y: yFor(point ? point.value : 0),
|
|
23250
|
+
value: point ? point.value : 0,
|
|
23251
|
+
label
|
|
23252
|
+
};
|
|
23253
|
+
});
|
|
23254
|
+
const linePath = points.map((p2, i) => `${i === 0 ? "M" : "L"} ${p2.x} ${p2.y}`).join(" ");
|
|
23255
|
+
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
23256
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
23257
|
+
fill && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23258
|
+
"path",
|
|
23259
|
+
{
|
|
23260
|
+
d: areaPath,
|
|
23261
|
+
fill: color,
|
|
23262
|
+
opacity: series.length > 1 ? 0.08 : 0.1
|
|
23263
|
+
}
|
|
23264
|
+
),
|
|
23265
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23266
|
+
"path",
|
|
23267
|
+
{
|
|
23268
|
+
d: linePath,
|
|
23269
|
+
fill: "none",
|
|
23270
|
+
stroke: color,
|
|
23271
|
+
strokeWidth: "2",
|
|
23272
|
+
strokeLinecap: "round",
|
|
23273
|
+
strokeLinejoin: "round",
|
|
23274
|
+
strokeDasharray: s.dashed ? "6 4" : void 0
|
|
23275
|
+
}
|
|
23276
|
+
),
|
|
23277
|
+
points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
23278
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23279
|
+
"circle",
|
|
23280
|
+
{
|
|
23281
|
+
cx: p2.x,
|
|
23282
|
+
cy: p2.y,
|
|
23283
|
+
r: "4",
|
|
23284
|
+
fill: "var(--color-card)",
|
|
23285
|
+
stroke: color,
|
|
23286
|
+
strokeWidth: "2",
|
|
23287
|
+
className: "cursor-pointer",
|
|
23288
|
+
onClick: () => onPointClick?.(
|
|
23289
|
+
{ label: p2.label, value: p2.value, color },
|
|
23290
|
+
s.name
|
|
23291
|
+
)
|
|
23292
|
+
}
|
|
23293
|
+
),
|
|
23294
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23295
|
+
"text",
|
|
23296
|
+
{
|
|
23297
|
+
x: p2.x,
|
|
23298
|
+
y: p2.y - 10,
|
|
23299
|
+
textAnchor: "middle",
|
|
23300
|
+
fill: "var(--color-foreground)",
|
|
23301
|
+
fontSize: "10",
|
|
23302
|
+
fontWeight: "500",
|
|
23303
|
+
children: p2.value
|
|
23304
|
+
}
|
|
23305
|
+
)
|
|
23306
|
+
] }, idx))
|
|
23307
|
+
] }, s.name);
|
|
23308
|
+
}),
|
|
23309
|
+
labels.map((label, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
23310
|
+
"text",
|
|
23311
|
+
{
|
|
23312
|
+
x: xFor(idx),
|
|
23313
|
+
y: height - 8,
|
|
23314
|
+
textAnchor: "middle",
|
|
23315
|
+
fill: "var(--color-muted-foreground)",
|
|
23316
|
+
fontSize: "9",
|
|
23317
|
+
children: timeAxis ? formatTimeLabel(label) : label
|
|
23318
|
+
},
|
|
23319
|
+
label
|
|
23320
|
+
))
|
|
23321
|
+
]
|
|
23322
|
+
}
|
|
23323
|
+
);
|
|
23324
|
+
};
|
|
23325
|
+
ScatterChart = ({ data, height, onPointClick }) => {
|
|
23326
|
+
const width = 400;
|
|
23327
|
+
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
23328
|
+
const chartWidth = width - padding.left - padding.right;
|
|
23329
|
+
const chartHeight = height - padding.top - padding.bottom;
|
|
23330
|
+
const { minX, maxX, minY, maxY } = React93.useMemo(() => {
|
|
23331
|
+
if (data.length === 0) {
|
|
23332
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
23333
|
+
}
|
|
23334
|
+
let mnX = data[0].x;
|
|
23335
|
+
let mxX = data[0].x;
|
|
23336
|
+
let mnY = data[0].y;
|
|
23337
|
+
let mxY = data[0].y;
|
|
23338
|
+
for (const p2 of data) {
|
|
23339
|
+
if (p2.x < mnX) mnX = p2.x;
|
|
23340
|
+
if (p2.x > mxX) mxX = p2.x;
|
|
23341
|
+
if (p2.y < mnY) mnY = p2.y;
|
|
23342
|
+
if (p2.y > mxY) mxY = p2.y;
|
|
23343
|
+
}
|
|
23344
|
+
return { minX: mnX, maxX: mxX, minY: mnY, maxY: mxY };
|
|
23345
|
+
}, [data]);
|
|
23346
|
+
const rangeX = maxX - minX || 1;
|
|
23347
|
+
const rangeY = maxY - minY || 1;
|
|
23348
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
23349
|
+
"svg",
|
|
23350
|
+
{
|
|
23351
|
+
width: "100%",
|
|
23352
|
+
height,
|
|
23353
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
23354
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
23355
|
+
children: [
|
|
23356
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
23357
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
23358
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23359
|
+
"line",
|
|
23360
|
+
{
|
|
23361
|
+
x1: padding.left,
|
|
23362
|
+
y1: y,
|
|
23363
|
+
x2: width - padding.right,
|
|
23364
|
+
y2: y,
|
|
23365
|
+
stroke: "var(--color-border)",
|
|
23366
|
+
strokeDasharray: "4 4",
|
|
23367
|
+
opacity: 0.5
|
|
23368
|
+
},
|
|
23369
|
+
frac
|
|
23370
|
+
);
|
|
23371
|
+
}),
|
|
23372
|
+
data.map((p2, idx) => {
|
|
23373
|
+
const cx = padding.left + (p2.x - minX) / rangeX * chartWidth;
|
|
23374
|
+
const cy = padding.top + chartHeight - (p2.y - minY) / rangeY * chartHeight;
|
|
23375
|
+
const r2 = p2.size ?? 5;
|
|
23376
|
+
const color = p2.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
23377
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
23378
|
+
"circle",
|
|
23379
|
+
{
|
|
23380
|
+
cx,
|
|
23381
|
+
cy,
|
|
23382
|
+
r: r2,
|
|
23383
|
+
fill: color,
|
|
23384
|
+
opacity: 0.7,
|
|
23385
|
+
className: "cursor-pointer hover:opacity-100",
|
|
23386
|
+
onClick: () => onPointClick?.(
|
|
23387
|
+
{
|
|
23388
|
+
label: p2.label ?? `(${p2.x}, ${p2.y})`,
|
|
23389
|
+
value: p2.y,
|
|
23390
|
+
color
|
|
23391
|
+
},
|
|
23392
|
+
"default"
|
|
23393
|
+
),
|
|
23394
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: p2.label ?? `(${p2.x}, ${p2.y})` })
|
|
23395
|
+
},
|
|
23396
|
+
idx
|
|
23397
|
+
);
|
|
23398
|
+
}),
|
|
23399
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23400
|
+
"text",
|
|
23401
|
+
{
|
|
23402
|
+
x: padding.left,
|
|
23403
|
+
y: height - 8,
|
|
23404
|
+
fill: "var(--color-muted-foreground)",
|
|
23405
|
+
fontSize: "9",
|
|
23406
|
+
children: minX.toFixed(1)
|
|
23407
|
+
}
|
|
23408
|
+
),
|
|
23409
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23410
|
+
"text",
|
|
23411
|
+
{
|
|
23412
|
+
x: width - padding.right,
|
|
23413
|
+
y: height - 8,
|
|
23414
|
+
textAnchor: "end",
|
|
23415
|
+
fill: "var(--color-muted-foreground)",
|
|
23416
|
+
fontSize: "9",
|
|
23417
|
+
children: maxX.toFixed(1)
|
|
23418
|
+
}
|
|
23419
|
+
)
|
|
23420
|
+
]
|
|
23421
|
+
}
|
|
23422
|
+
);
|
|
23050
23423
|
};
|
|
23051
23424
|
Chart = ({
|
|
23052
23425
|
title,
|
|
@@ -23054,9 +23427,13 @@ var init_Chart = __esm({
|
|
|
23054
23427
|
chartType = "bar",
|
|
23055
23428
|
series,
|
|
23056
23429
|
data: simpleData,
|
|
23430
|
+
scatterData,
|
|
23057
23431
|
height = 200,
|
|
23058
23432
|
showLegend = true,
|
|
23059
23433
|
showValues = false,
|
|
23434
|
+
stack = "none",
|
|
23435
|
+
timeAxis = false,
|
|
23436
|
+
drillEvent,
|
|
23060
23437
|
actions,
|
|
23061
23438
|
entity,
|
|
23062
23439
|
isLoading = false,
|
|
@@ -23073,11 +23450,25 @@ var init_Chart = __esm({
|
|
|
23073
23450
|
},
|
|
23074
23451
|
[eventBus]
|
|
23075
23452
|
);
|
|
23076
|
-
const
|
|
23077
|
-
|
|
23078
|
-
|
|
23453
|
+
const handlePointClick = React93.useCallback(
|
|
23454
|
+
(point, seriesName) => {
|
|
23455
|
+
if (drillEvent) {
|
|
23456
|
+
eventBus.emit(`UI:${drillEvent}`, {
|
|
23457
|
+
label: point.label,
|
|
23458
|
+
value: point.value,
|
|
23459
|
+
seriesLabel: seriesName === "default" ? void 0 : seriesName
|
|
23460
|
+
});
|
|
23461
|
+
}
|
|
23462
|
+
},
|
|
23463
|
+
[drillEvent, eventBus]
|
|
23464
|
+
);
|
|
23465
|
+
const normalizedSeries = React93.useMemo(() => {
|
|
23466
|
+
if (series && series.length > 0) return series;
|
|
23467
|
+
if (simpleData) return [{ name: "default", data: simpleData }];
|
|
23079
23468
|
return [];
|
|
23080
23469
|
}, [simpleData, series]);
|
|
23470
|
+
const firstSeriesData = normalizedSeries[0]?.data ?? [];
|
|
23471
|
+
const hasContent = chartType === "scatter" ? (scatterData?.length ?? 0) > 0 : normalizedSeries.some((s) => s.data.length > 0);
|
|
23081
23472
|
if (isLoading) {
|
|
23082
23473
|
return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: "Loading chart...", className });
|
|
23083
23474
|
}
|
|
@@ -23091,7 +23482,7 @@ var init_Chart = __esm({
|
|
|
23091
23482
|
}
|
|
23092
23483
|
);
|
|
23093
23484
|
}
|
|
23094
|
-
if (
|
|
23485
|
+
if (!hasContent) {
|
|
23095
23486
|
return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { title: t("empty.noData"), description: t("empty.noData"), className });
|
|
23096
23487
|
}
|
|
23097
23488
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn("p-6", className), children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", children: [
|
|
@@ -23112,18 +23503,84 @@ var init_Chart = __esm({
|
|
|
23112
23503
|
)) })
|
|
23113
23504
|
] }),
|
|
23114
23505
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "w-full", children: [
|
|
23115
|
-
chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23116
|
-
|
|
23117
|
-
|
|
23118
|
-
|
|
23119
|
-
|
|
23506
|
+
chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23507
|
+
BarChart,
|
|
23508
|
+
{
|
|
23509
|
+
series: normalizedSeries,
|
|
23510
|
+
height,
|
|
23511
|
+
showValues,
|
|
23512
|
+
stack,
|
|
23513
|
+
timeAxis,
|
|
23514
|
+
onPointClick: handlePointClick
|
|
23515
|
+
}
|
|
23516
|
+
),
|
|
23517
|
+
chartType === "histogram" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23518
|
+
BarChart,
|
|
23519
|
+
{
|
|
23520
|
+
series: normalizedSeries,
|
|
23521
|
+
height,
|
|
23522
|
+
showValues,
|
|
23523
|
+
stack: "none",
|
|
23524
|
+
timeAxis: false,
|
|
23525
|
+
histogram: true,
|
|
23526
|
+
onPointClick: handlePointClick
|
|
23527
|
+
}
|
|
23528
|
+
),
|
|
23529
|
+
chartType === "line" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23530
|
+
LineChart,
|
|
23531
|
+
{
|
|
23532
|
+
series: normalizedSeries,
|
|
23533
|
+
height,
|
|
23534
|
+
showValues,
|
|
23535
|
+
timeAxis,
|
|
23536
|
+
onPointClick: handlePointClick
|
|
23537
|
+
}
|
|
23538
|
+
),
|
|
23539
|
+
chartType === "area" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23540
|
+
LineChart,
|
|
23541
|
+
{
|
|
23542
|
+
series: normalizedSeries,
|
|
23543
|
+
height,
|
|
23544
|
+
showValues,
|
|
23545
|
+
timeAxis,
|
|
23546
|
+
fill: true,
|
|
23547
|
+
onPointClick: handlePointClick
|
|
23548
|
+
}
|
|
23549
|
+
),
|
|
23550
|
+
chartType === "pie" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23551
|
+
PieChart,
|
|
23552
|
+
{
|
|
23553
|
+
data: firstSeriesData,
|
|
23554
|
+
height,
|
|
23555
|
+
showValues: showLegend,
|
|
23556
|
+
onPointClick: handlePointClick
|
|
23557
|
+
}
|
|
23558
|
+
),
|
|
23559
|
+
chartType === "donut" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23560
|
+
PieChart,
|
|
23561
|
+
{
|
|
23562
|
+
data: firstSeriesData,
|
|
23563
|
+
height,
|
|
23564
|
+
showValues: showLegend,
|
|
23565
|
+
donut: true,
|
|
23566
|
+
onPointClick: handlePointClick
|
|
23567
|
+
}
|
|
23568
|
+
),
|
|
23569
|
+
chartType === "scatter" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
23570
|
+
ScatterChart,
|
|
23571
|
+
{
|
|
23572
|
+
data: scatterData ?? [],
|
|
23573
|
+
height,
|
|
23574
|
+
onPointClick: handlePointClick
|
|
23575
|
+
}
|
|
23576
|
+
)
|
|
23120
23577
|
] }),
|
|
23121
|
-
showLegend &&
|
|
23578
|
+
showLegend && normalizedSeries.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "md", justify: "center", wrap: true, children: normalizedSeries.map((s, idx) => /* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "xs", align: "center", children: [
|
|
23122
23579
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
23123
23580
|
Box,
|
|
23124
23581
|
{
|
|
23125
23582
|
className: "w-3 h-3 rounded-full flex-shrink-0",
|
|
23126
|
-
style: { backgroundColor: s
|
|
23583
|
+
style: { backgroundColor: seriesColor(s, idx) }
|
|
23127
23584
|
}
|
|
23128
23585
|
),
|
|
23129
23586
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: s.name })
|
|
@@ -28039,6 +28496,151 @@ var init_FlipCard = __esm({
|
|
|
28039
28496
|
FlipCard.displayName = "FlipCard";
|
|
28040
28497
|
}
|
|
28041
28498
|
});
|
|
28499
|
+
function toISODate(d) {
|
|
28500
|
+
return d.toISOString().slice(0, 10);
|
|
28501
|
+
}
|
|
28502
|
+
function startOfMonth(d) {
|
|
28503
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
28504
|
+
}
|
|
28505
|
+
function startOfQuarter(d) {
|
|
28506
|
+
return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
|
|
28507
|
+
}
|
|
28508
|
+
function startOfYear(d) {
|
|
28509
|
+
return new Date(d.getFullYear(), 0, 1);
|
|
28510
|
+
}
|
|
28511
|
+
function daysAgo(n) {
|
|
28512
|
+
const d = /* @__PURE__ */ new Date();
|
|
28513
|
+
d.setDate(d.getDate() - n);
|
|
28514
|
+
return d;
|
|
28515
|
+
}
|
|
28516
|
+
var DEFAULT_PRESETS, DateRangePicker;
|
|
28517
|
+
var init_DateRangePicker = __esm({
|
|
28518
|
+
"components/molecules/DateRangePicker.tsx"() {
|
|
28519
|
+
"use client";
|
|
28520
|
+
init_cn();
|
|
28521
|
+
init_Button();
|
|
28522
|
+
init_Input();
|
|
28523
|
+
init_Stack();
|
|
28524
|
+
init_Typography();
|
|
28525
|
+
init_useEventBus();
|
|
28526
|
+
DEFAULT_PRESETS = [
|
|
28527
|
+
{
|
|
28528
|
+
label: "Last 7 days",
|
|
28529
|
+
value: "7d",
|
|
28530
|
+
range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28531
|
+
},
|
|
28532
|
+
{
|
|
28533
|
+
label: "Last 30 days",
|
|
28534
|
+
value: "30d",
|
|
28535
|
+
range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28536
|
+
},
|
|
28537
|
+
{
|
|
28538
|
+
label: "This Month",
|
|
28539
|
+
value: "month",
|
|
28540
|
+
range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28541
|
+
},
|
|
28542
|
+
{
|
|
28543
|
+
label: "This Quarter",
|
|
28544
|
+
value: "quarter",
|
|
28545
|
+
range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28546
|
+
},
|
|
28547
|
+
{
|
|
28548
|
+
label: "YTD",
|
|
28549
|
+
value: "ytd",
|
|
28550
|
+
range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28551
|
+
}
|
|
28552
|
+
];
|
|
28553
|
+
DateRangePicker = ({
|
|
28554
|
+
from: fromProp,
|
|
28555
|
+
to: toProp,
|
|
28556
|
+
event,
|
|
28557
|
+
onChange,
|
|
28558
|
+
presets = DEFAULT_PRESETS,
|
|
28559
|
+
fromLabel = "From",
|
|
28560
|
+
toLabel = "To",
|
|
28561
|
+
className
|
|
28562
|
+
}) => {
|
|
28563
|
+
const eventBus = useEventBus();
|
|
28564
|
+
const [from, setFrom] = React93.useState(fromProp ?? "");
|
|
28565
|
+
const [to, setTo] = React93.useState(toProp ?? "");
|
|
28566
|
+
const [activePreset, setActivePreset] = React93.useState(null);
|
|
28567
|
+
const emit = React93.useCallback(
|
|
28568
|
+
(range) => {
|
|
28569
|
+
onChange?.(range);
|
|
28570
|
+
if (event) eventBus.emit(`UI:${event}`, range);
|
|
28571
|
+
},
|
|
28572
|
+
[onChange, event, eventBus]
|
|
28573
|
+
);
|
|
28574
|
+
const handleFromChange = React93.useCallback(
|
|
28575
|
+
(next) => {
|
|
28576
|
+
setFrom(next);
|
|
28577
|
+
setActivePreset(null);
|
|
28578
|
+
emit({ from: next, to });
|
|
28579
|
+
},
|
|
28580
|
+
[to, emit]
|
|
28581
|
+
);
|
|
28582
|
+
const handleToChange = React93.useCallback(
|
|
28583
|
+
(next) => {
|
|
28584
|
+
setTo(next);
|
|
28585
|
+
setActivePreset(null);
|
|
28586
|
+
emit({ from, to: next });
|
|
28587
|
+
},
|
|
28588
|
+
[from, emit]
|
|
28589
|
+
);
|
|
28590
|
+
const handlePreset = React93.useCallback(
|
|
28591
|
+
(preset) => {
|
|
28592
|
+
const range = preset.range();
|
|
28593
|
+
setFrom(range.from);
|
|
28594
|
+
setTo(range.to);
|
|
28595
|
+
setActivePreset(preset.value);
|
|
28596
|
+
emit(range);
|
|
28597
|
+
},
|
|
28598
|
+
[emit]
|
|
28599
|
+
);
|
|
28600
|
+
const presetButtons = React93.useMemo(
|
|
28601
|
+
() => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
28602
|
+
Button,
|
|
28603
|
+
{
|
|
28604
|
+
variant: activePreset === preset.value ? "primary" : "ghost",
|
|
28605
|
+
size: "sm",
|
|
28606
|
+
onClick: () => handlePreset(preset),
|
|
28607
|
+
children: preset.label
|
|
28608
|
+
},
|
|
28609
|
+
preset.value
|
|
28610
|
+
)),
|
|
28611
|
+
[presets, activePreset, handlePreset]
|
|
28612
|
+
);
|
|
28613
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: cn(className), children: [
|
|
28614
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "end", children: [
|
|
28615
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
28616
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: fromLabel }),
|
|
28617
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28618
|
+
Input,
|
|
28619
|
+
{
|
|
28620
|
+
type: "date",
|
|
28621
|
+
value: from,
|
|
28622
|
+
onChange: (e) => handleFromChange(e.target.value)
|
|
28623
|
+
}
|
|
28624
|
+
)
|
|
28625
|
+
] }),
|
|
28626
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
28627
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: toLabel }),
|
|
28628
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28629
|
+
Input,
|
|
28630
|
+
{
|
|
28631
|
+
type: "date",
|
|
28632
|
+
value: to,
|
|
28633
|
+
onChange: (e) => handleToChange(e.target.value)
|
|
28634
|
+
}
|
|
28635
|
+
)
|
|
28636
|
+
] })
|
|
28637
|
+
] }),
|
|
28638
|
+
presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
|
|
28639
|
+
] });
|
|
28640
|
+
};
|
|
28641
|
+
DateRangePicker.displayName = "DateRangePicker";
|
|
28642
|
+
}
|
|
28643
|
+
});
|
|
28042
28644
|
var DEFAULT_OPTIONS, DateRangeSelector;
|
|
28043
28645
|
var init_DateRangeSelector = __esm({
|
|
28044
28646
|
"components/molecules/DateRangeSelector.tsx"() {
|
|
@@ -31010,7 +31612,9 @@ var init_StatDisplay = __esm({
|
|
|
31010
31612
|
init_Typography();
|
|
31011
31613
|
init_Box();
|
|
31012
31614
|
init_Stack();
|
|
31615
|
+
init_Sparkline();
|
|
31013
31616
|
init_Icon();
|
|
31617
|
+
init_useEventBus();
|
|
31014
31618
|
variantColor = {
|
|
31015
31619
|
default: "text-foreground",
|
|
31016
31620
|
primary: "text-primary",
|
|
@@ -31025,6 +31629,10 @@ var init_StatDisplay = __esm({
|
|
|
31025
31629
|
max,
|
|
31026
31630
|
target,
|
|
31027
31631
|
trend,
|
|
31632
|
+
trendPolarity = "higher-is-better",
|
|
31633
|
+
trendFormat = "absolute",
|
|
31634
|
+
sparklineData,
|
|
31635
|
+
clickEvent,
|
|
31028
31636
|
prefix,
|
|
31029
31637
|
suffix,
|
|
31030
31638
|
icon: iconProp,
|
|
@@ -31038,6 +31646,10 @@ var init_StatDisplay = __esm({
|
|
|
31038
31646
|
isLoading = false,
|
|
31039
31647
|
error = null
|
|
31040
31648
|
}) => {
|
|
31649
|
+
const eventBus = useEventBus();
|
|
31650
|
+
const handleClick = React93.useCallback(() => {
|
|
31651
|
+
if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
|
|
31652
|
+
}, [clickEvent, eventBus, label]);
|
|
31041
31653
|
const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
|
|
31042
31654
|
const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
|
|
31043
31655
|
const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
|
|
@@ -31048,7 +31660,10 @@ var init_StatDisplay = __esm({
|
|
|
31048
31660
|
const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
|
|
31049
31661
|
const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
|
|
31050
31662
|
const trendUp = showTrend && trend > 0;
|
|
31051
|
-
const
|
|
31663
|
+
const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
|
|
31664
|
+
const trendMagnitude = Math.abs(trend);
|
|
31665
|
+
const trendSuffix = trendFormat === "percent" ? "%" : "";
|
|
31666
|
+
const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
|
|
31052
31667
|
if (error) {
|
|
31053
31668
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
|
|
31054
31669
|
}
|
|
@@ -31059,38 +31674,57 @@ var init_StatDisplay = __esm({
|
|
|
31059
31674
|
] }) });
|
|
31060
31675
|
}
|
|
31061
31676
|
if (compact) {
|
|
31062
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
31063
|
-
|
|
31064
|
-
|
|
31065
|
-
|
|
31066
|
-
|
|
31067
|
-
|
|
31068
|
-
|
|
31677
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
31678
|
+
HStack,
|
|
31679
|
+
{
|
|
31680
|
+
gap: "sm",
|
|
31681
|
+
className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
|
|
31682
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31683
|
+
children: [
|
|
31684
|
+
ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
|
|
31685
|
+
typeof iconProp !== "string" && iconProp,
|
|
31686
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
|
|
31687
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31688
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
|
|
31689
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
|
|
31690
|
+
]
|
|
31691
|
+
}
|
|
31692
|
+
);
|
|
31069
31693
|
}
|
|
31070
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
31071
|
-
|
|
31072
|
-
|
|
31073
|
-
|
|
31074
|
-
|
|
31075
|
-
|
|
31076
|
-
|
|
31077
|
-
{
|
|
31078
|
-
|
|
31079
|
-
className: cn("font-
|
|
31080
|
-
|
|
31081
|
-
|
|
31082
|
-
|
|
31083
|
-
|
|
31084
|
-
|
|
31085
|
-
|
|
31086
|
-
|
|
31087
|
-
|
|
31088
|
-
|
|
31089
|
-
|
|
31090
|
-
|
|
31091
|
-
|
|
31092
|
-
|
|
31093
|
-
|
|
31694
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
31695
|
+
Card,
|
|
31696
|
+
{
|
|
31697
|
+
className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
|
|
31698
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31699
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
|
|
31700
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
|
|
31701
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
|
|
31702
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
|
|
31703
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31704
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(
|
|
31705
|
+
Typography,
|
|
31706
|
+
{
|
|
31707
|
+
variant: "caption",
|
|
31708
|
+
className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
|
|
31709
|
+
children: trendLabel
|
|
31710
|
+
}
|
|
31711
|
+
)
|
|
31712
|
+
] }),
|
|
31713
|
+
showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
31714
|
+
Box,
|
|
31715
|
+
{
|
|
31716
|
+
className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
|
|
31717
|
+
style: { width: `${targetPct}%` }
|
|
31718
|
+
}
|
|
31719
|
+
) })
|
|
31720
|
+
] }),
|
|
31721
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
31722
|
+
(ResolvedIcon || typeof iconProp !== "string" && iconProp) && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3 rounded-md", iconBg), children: ResolvedIcon ? /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }) : iconProp }),
|
|
31723
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
31724
|
+
] })
|
|
31725
|
+
] })
|
|
31726
|
+
}
|
|
31727
|
+
);
|
|
31094
31728
|
};
|
|
31095
31729
|
StatDisplay.displayName = "StatDisplay";
|
|
31096
31730
|
}
|
|
@@ -45169,6 +45803,7 @@ var init_StatCard = __esm({
|
|
|
45169
45803
|
init_Box();
|
|
45170
45804
|
init_Stack();
|
|
45171
45805
|
init_Button();
|
|
45806
|
+
init_Sparkline();
|
|
45172
45807
|
init_useEventBus();
|
|
45173
45808
|
init_useTranslate();
|
|
45174
45809
|
init_Icon();
|
|
@@ -45338,32 +45973,7 @@ var init_StatCard = __esm({
|
|
|
45338
45973
|
] }),
|
|
45339
45974
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
45340
45975
|
Icon3 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3", iconBg), children: /* @__PURE__ */ jsxRuntime.jsx(Icon3, { className: cn("h-6 w-6", iconColor) }) }),
|
|
45341
|
-
sparklineData && sparklineData.length > 1 && (
|
|
45342
|
-
const w = 80;
|
|
45343
|
-
const h = 32;
|
|
45344
|
-
const pad = 2;
|
|
45345
|
-
const min = Math.min(...sparklineData);
|
|
45346
|
-
const max = Math.max(...sparklineData);
|
|
45347
|
-
const range = max - min || 1;
|
|
45348
|
-
const points = sparklineData.map((v, i) => {
|
|
45349
|
-
const x = pad + i / (sparklineData.length - 1) * (w - pad * 2);
|
|
45350
|
-
const y = pad + (1 - (v - min) / range) * (h - pad * 2);
|
|
45351
|
-
return `${x},${y}`;
|
|
45352
|
-
}).join(" ");
|
|
45353
|
-
const trending = sparklineData[sparklineData.length - 1] >= sparklineData[0];
|
|
45354
|
-
const strokeColor = trending ? "var(--color-success)" : "var(--color-error)";
|
|
45355
|
-
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w, height: h, viewBox: `0 0 ${w} ${h}`, className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
45356
|
-
"polyline",
|
|
45357
|
-
{
|
|
45358
|
-
fill: "none",
|
|
45359
|
-
stroke: strokeColor,
|
|
45360
|
-
strokeWidth: "2",
|
|
45361
|
-
strokeLinecap: "round",
|
|
45362
|
-
strokeLinejoin: "round",
|
|
45363
|
-
points
|
|
45364
|
-
}
|
|
45365
|
-
) });
|
|
45366
|
-
})()
|
|
45976
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
45367
45977
|
] })
|
|
45368
45978
|
] }),
|
|
45369
45979
|
action && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -52733,6 +53343,7 @@ var init_component_registry_generated = __esm({
|
|
|
52733
53343
|
init_DataGrid();
|
|
52734
53344
|
init_DataList();
|
|
52735
53345
|
init_DataTable();
|
|
53346
|
+
init_DateRangePicker();
|
|
52736
53347
|
init_DateRangeSelector();
|
|
52737
53348
|
init_DayCell();
|
|
52738
53349
|
init_DebuggerBoard();
|
|
@@ -52865,6 +53476,7 @@ var init_component_registry_generated = __esm({
|
|
|
52865
53476
|
init_Skeleton();
|
|
52866
53477
|
init_SocialProof();
|
|
52867
53478
|
init_SortableList();
|
|
53479
|
+
init_Sparkline();
|
|
52868
53480
|
init_Split();
|
|
52869
53481
|
init_SplitPane();
|
|
52870
53482
|
init_SplitSection();
|
|
@@ -53013,6 +53625,7 @@ var init_component_registry_generated = __esm({
|
|
|
53013
53625
|
"DataGrid": DataGrid,
|
|
53014
53626
|
"DataList": DataList,
|
|
53015
53627
|
"DataTable": DataTable,
|
|
53628
|
+
"DateRangePicker": DateRangePicker,
|
|
53016
53629
|
"DateRangeSelector": DateRangeSelector,
|
|
53017
53630
|
"DayCell": DayCell,
|
|
53018
53631
|
"DebuggerBoard": DebuggerBoard,
|
|
@@ -53174,6 +53787,7 @@ var init_component_registry_generated = __esm({
|
|
|
53174
53787
|
"SortableList": SortableList,
|
|
53175
53788
|
"Spacer": SpacerPattern,
|
|
53176
53789
|
"SpacerPattern": SpacerPattern,
|
|
53790
|
+
"Sparkline": Sparkline,
|
|
53177
53791
|
"Spinner": SpinnerPattern,
|
|
53178
53792
|
"SpinnerPattern": SpinnerPattern,
|
|
53179
53793
|
"Split": Split,
|
|
@@ -60480,8 +61094,19 @@ function OrbInspector({ node, schema, editable = false, userType = "builder", th
|
|
|
60480
61094
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] uppercase tracking-wider mb-2", children: t("Props") }),
|
|
60481
61095
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-1.5", children: Object.entries(patternDef.propsSchema).slice(0, 12).map(([propName, propSchema]) => {
|
|
60482
61096
|
const ps = propSchema;
|
|
60483
|
-
const
|
|
61097
|
+
const explicitValue = patternConfig ? patternConfig[propName] : void 0;
|
|
61098
|
+
const defaultValue = ps.default;
|
|
61099
|
+
const isImplicit = explicitValue === void 0 && defaultValue !== void 0;
|
|
61100
|
+
const currentValue = explicitValue !== void 0 ? explicitValue : defaultValue;
|
|
60484
61101
|
const displayValue = currentValue !== void 0 ? typeof currentValue === "object" ? JSON.stringify(currentValue) : String(currentValue) : "";
|
|
61102
|
+
inspectorLog.debug("prop-row", () => ({
|
|
61103
|
+
patternType: patternDef.type,
|
|
61104
|
+
patternId: selectedPattern?.patternId ?? "",
|
|
61105
|
+
propName,
|
|
61106
|
+
explicitValue: explicitValue === void 0 ? "<unset>" : JSON.stringify(explicitValue),
|
|
61107
|
+
defaultValue: defaultValue === void 0 ? "<unset>" : JSON.stringify(defaultValue),
|
|
61108
|
+
isImplicit: String(isImplicit)
|
|
61109
|
+
}));
|
|
60485
61110
|
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2", children: [
|
|
60486
61111
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "text-muted-foreground text-[11px] w-20 shrink-0 font-mono", children: propName }),
|
|
60487
61112
|
editable ? /* @__PURE__ */ jsxRuntime.jsx(
|