@almadar/ui 4.51.13 → 4.51.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +777 -151
- package/dist/avl/index.js +777 -151
- package/dist/components/atoms/Sparkline.d.ts +30 -0
- package/dist/components/atoms/index.d.ts +1 -0
- package/dist/components/index.cjs +765 -149
- package/dist/components/index.js +766 -150
- package/dist/components/molecules/DateRangePicker.d.ts +56 -0
- package/dist/components/molecules/FilterGroup.d.ts +3 -3
- package/dist/components/molecules/StatDisplay.d.ts +9 -1
- package/dist/components/molecules/index.d.ts +1 -0
- package/dist/components/organisms/Chart.d.ts +32 -12
- package/dist/providers/index.cjs +763 -149
- package/dist/providers/index.js +763 -149
- package/dist/runtime/index.cjs +763 -149
- package/dist/runtime/index.js +763 -149
- package/package.json +1 -1
package/dist/providers/index.cjs
CHANGED
|
@@ -3649,6 +3649,67 @@ var init_Radio = __esm({
|
|
|
3649
3649
|
Radio.displayName = "Radio";
|
|
3650
3650
|
}
|
|
3651
3651
|
});
|
|
3652
|
+
var COLOR_VAR, Sparkline;
|
|
3653
|
+
var init_Sparkline = __esm({
|
|
3654
|
+
"components/atoms/Sparkline.tsx"() {
|
|
3655
|
+
init_cn();
|
|
3656
|
+
COLOR_VAR = {
|
|
3657
|
+
primary: "var(--color-primary)",
|
|
3658
|
+
success: "var(--color-success)",
|
|
3659
|
+
warning: "var(--color-warning)",
|
|
3660
|
+
error: "var(--color-error)",
|
|
3661
|
+
info: "var(--color-info)",
|
|
3662
|
+
muted: "var(--color-muted-foreground)"
|
|
3663
|
+
};
|
|
3664
|
+
Sparkline = ({
|
|
3665
|
+
data,
|
|
3666
|
+
color = "auto",
|
|
3667
|
+
width = 80,
|
|
3668
|
+
height = 32,
|
|
3669
|
+
strokeWidth = 2,
|
|
3670
|
+
fill = false,
|
|
3671
|
+
className
|
|
3672
|
+
}) => {
|
|
3673
|
+
if (data.length < 2) return null;
|
|
3674
|
+
const pad = 2;
|
|
3675
|
+
const min = Math.min(...data);
|
|
3676
|
+
const max = Math.max(...data);
|
|
3677
|
+
const range = max - min || 1;
|
|
3678
|
+
const points = data.map((v, i) => {
|
|
3679
|
+
const x = pad + i / (data.length - 1) * (width - pad * 2);
|
|
3680
|
+
const y = pad + (1 - (v - min) / range) * (height - pad * 2);
|
|
3681
|
+
return `${x},${y}`;
|
|
3682
|
+
}).join(" ");
|
|
3683
|
+
const resolvedColor = color === "auto" ? data[data.length - 1] >= data[0] ? COLOR_VAR.success : COLOR_VAR.error : COLOR_VAR[color];
|
|
3684
|
+
const areaPath = fill ? `M ${pad},${height - pad} L ${points.split(" ").join(" L ")} L ${width - pad},${height - pad} Z` : null;
|
|
3685
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3686
|
+
"svg",
|
|
3687
|
+
{
|
|
3688
|
+
width,
|
|
3689
|
+
height,
|
|
3690
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
3691
|
+
className: cn("flex-shrink-0", className),
|
|
3692
|
+
"aria-hidden": "true",
|
|
3693
|
+
children: [
|
|
3694
|
+
areaPath && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: resolvedColor, opacity: 0.15 }),
|
|
3695
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3696
|
+
"polyline",
|
|
3697
|
+
{
|
|
3698
|
+
fill: "none",
|
|
3699
|
+
stroke: resolvedColor,
|
|
3700
|
+
strokeWidth,
|
|
3701
|
+
strokeLinecap: "round",
|
|
3702
|
+
strokeLinejoin: "round",
|
|
3703
|
+
points
|
|
3704
|
+
}
|
|
3705
|
+
)
|
|
3706
|
+
]
|
|
3707
|
+
}
|
|
3708
|
+
);
|
|
3709
|
+
};
|
|
3710
|
+
Sparkline.displayName = "Sparkline";
|
|
3711
|
+
}
|
|
3712
|
+
});
|
|
3652
3713
|
var Switch;
|
|
3653
3714
|
var init_Switch = __esm({
|
|
3654
3715
|
"components/atoms/Switch.tsx"() {
|
|
@@ -9322,7 +9383,7 @@ var init_MapView = __esm({
|
|
|
9322
9383
|
shadowSize: [41, 41]
|
|
9323
9384
|
});
|
|
9324
9385
|
L.Marker.prototype.options.icon = defaultIcon;
|
|
9325
|
-
const { useEffect: useEffect67, useRef: useRef65, useCallback:
|
|
9386
|
+
const { useEffect: useEffect67, useRef: useRef65, useCallback: useCallback112, useState: useState96 } = React81__namespace.default;
|
|
9326
9387
|
const { Typography: Typography2 } = await Promise.resolve().then(() => (init_Typography(), Typography_exports));
|
|
9327
9388
|
const { useEventBus: useEventBus2 } = await Promise.resolve().then(() => (init_useEventBus(), useEventBus_exports));
|
|
9328
9389
|
function MapUpdater({ centerLat, centerLng, zoom }) {
|
|
@@ -9367,8 +9428,8 @@ var init_MapView = __esm({
|
|
|
9367
9428
|
showAttribution = true
|
|
9368
9429
|
}) {
|
|
9369
9430
|
const eventBus = useEventBus2();
|
|
9370
|
-
const [clickedPosition, setClickedPosition] =
|
|
9371
|
-
const handleMapClick =
|
|
9431
|
+
const [clickedPosition, setClickedPosition] = useState96(null);
|
|
9432
|
+
const handleMapClick = useCallback112((lat, lng) => {
|
|
9372
9433
|
if (showClickedPin) {
|
|
9373
9434
|
setClickedPosition({ lat, lng });
|
|
9374
9435
|
}
|
|
@@ -9377,7 +9438,7 @@ var init_MapView = __esm({
|
|
|
9377
9438
|
eventBus.emit(`UI:${mapClickEvent}`, { latitude: lat, longitude: lng });
|
|
9378
9439
|
}
|
|
9379
9440
|
}, [onMapClick, mapClickEvent, eventBus, showClickedPin]);
|
|
9380
|
-
const handleMarkerClick =
|
|
9441
|
+
const handleMarkerClick = useCallback112((marker) => {
|
|
9381
9442
|
onMarkerClick?.(marker);
|
|
9382
9443
|
if (markerClickEvent) {
|
|
9383
9444
|
eventBus.emit(`UI:${markerClickEvent}`, { ...marker });
|
|
@@ -19277,7 +19338,7 @@ var init_CastleTemplate = __esm({
|
|
|
19277
19338
|
CastleTemplate.displayName = "CastleTemplate";
|
|
19278
19339
|
}
|
|
19279
19340
|
});
|
|
19280
|
-
var CHART_COLORS, BarChart, PieChart, LineChart, Chart;
|
|
19341
|
+
var CHART_COLORS, seriesColor, monthFormatter, formatTimeLabel, BarChart, PieChart, LineChart, ScatterChart, Chart;
|
|
19281
19342
|
var init_Chart = __esm({
|
|
19282
19343
|
"components/organisms/Chart.tsx"() {
|
|
19283
19344
|
"use client";
|
|
@@ -19297,38 +19358,159 @@ var init_Chart = __esm({
|
|
|
19297
19358
|
"var(--color-info)",
|
|
19298
19359
|
"var(--color-accent)"
|
|
19299
19360
|
];
|
|
19300
|
-
|
|
19301
|
-
|
|
19302
|
-
|
|
19303
|
-
|
|
19304
|
-
|
|
19305
|
-
|
|
19306
|
-
|
|
19307
|
-
|
|
19308
|
-
|
|
19309
|
-
|
|
19310
|
-
|
|
19311
|
-
|
|
19312
|
-
|
|
19313
|
-
|
|
19314
|
-
|
|
19315
|
-
|
|
19316
|
-
|
|
19361
|
+
seriesColor = (series, idx) => series.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
19362
|
+
monthFormatter = new Intl.DateTimeFormat(void 0, {
|
|
19363
|
+
month: "short",
|
|
19364
|
+
year: "2-digit"
|
|
19365
|
+
});
|
|
19366
|
+
formatTimeLabel = (raw) => {
|
|
19367
|
+
const parsed = new Date(raw);
|
|
19368
|
+
if (Number.isNaN(parsed.getTime())) return raw;
|
|
19369
|
+
return monthFormatter.format(parsed);
|
|
19370
|
+
};
|
|
19371
|
+
BarChart = ({ series, height, showValues, stack, timeAxis, histogram = false, onPointClick }) => {
|
|
19372
|
+
const categories = React81.useMemo(() => {
|
|
19373
|
+
const set = [];
|
|
19374
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19375
|
+
for (const s of series) {
|
|
19376
|
+
for (const p2 of s.data) {
|
|
19377
|
+
if (!seen.has(p2.label)) {
|
|
19378
|
+
seen.add(p2.label);
|
|
19379
|
+
set.push(p2.label);
|
|
19317
19380
|
}
|
|
19318
|
-
|
|
19319
|
-
|
|
19320
|
-
|
|
19321
|
-
|
|
19322
|
-
|
|
19323
|
-
|
|
19324
|
-
|
|
19325
|
-
|
|
19381
|
+
}
|
|
19382
|
+
}
|
|
19383
|
+
return set;
|
|
19384
|
+
}, [series]);
|
|
19385
|
+
const valueAt = React81.useCallback(
|
|
19386
|
+
(s, label) => {
|
|
19387
|
+
const p2 = s.data.find((d) => d.label === label);
|
|
19388
|
+
return p2 ? p2.value : 0;
|
|
19389
|
+
},
|
|
19390
|
+
[]
|
|
19391
|
+
);
|
|
19392
|
+
const columnTotals = React81.useMemo(() => {
|
|
19393
|
+
if (stack === "none") return null;
|
|
19394
|
+
return categories.map(
|
|
19395
|
+
(label) => series.reduce((sum, s) => sum + valueAt(s, label), 0)
|
|
19396
|
+
);
|
|
19397
|
+
}, [categories, series, stack, valueAt]);
|
|
19398
|
+
const maxValue = React81.useMemo(() => {
|
|
19399
|
+
if (stack === "normalize") return 100;
|
|
19400
|
+
if (stack === "stack" && columnTotals) {
|
|
19401
|
+
return Math.max(...columnTotals, 1);
|
|
19402
|
+
}
|
|
19403
|
+
let m = 1;
|
|
19404
|
+
for (const s of series) {
|
|
19405
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
19406
|
+
}
|
|
19407
|
+
return m;
|
|
19408
|
+
}, [series, stack, columnTotals]);
|
|
19409
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19410
|
+
HStack,
|
|
19411
|
+
{
|
|
19412
|
+
gap: histogram ? "none" : "xs",
|
|
19413
|
+
align: "end",
|
|
19414
|
+
className: "w-full",
|
|
19415
|
+
style: { height },
|
|
19416
|
+
children: categories.map((label, catIdx) => {
|
|
19417
|
+
const displayLabel = timeAxis ? formatTimeLabel(label) : label;
|
|
19418
|
+
if (stack === "none") {
|
|
19419
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19420
|
+
VStack,
|
|
19421
|
+
{
|
|
19422
|
+
gap: "xs",
|
|
19423
|
+
align: "center",
|
|
19424
|
+
flex: true,
|
|
19425
|
+
className: "min-w-0",
|
|
19426
|
+
children: [
|
|
19427
|
+
/* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: histogram ? "none" : "xs", align: "end", className: "w-full", style: { height: "100%" }, children: series.map((s, sIdx) => {
|
|
19428
|
+
const value = valueAt(s, label);
|
|
19429
|
+
const barHeight = value / maxValue * 100;
|
|
19430
|
+
const color = seriesColor(s, sIdx);
|
|
19431
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19432
|
+
Box,
|
|
19433
|
+
{
|
|
19434
|
+
className: cn(
|
|
19435
|
+
"rounded-t-sm transition-all duration-500 ease-out min-h-[4px] cursor-pointer hover:opacity-80",
|
|
19436
|
+
histogram ? "flex-1 mx-0" : "flex-1"
|
|
19437
|
+
),
|
|
19438
|
+
style: {
|
|
19439
|
+
height: `${barHeight}%`,
|
|
19440
|
+
backgroundColor: color
|
|
19441
|
+
},
|
|
19442
|
+
onClick: () => onPointClick?.(
|
|
19443
|
+
{ label, value, color },
|
|
19444
|
+
s.name
|
|
19445
|
+
),
|
|
19446
|
+
title: `${s.name}: ${value}`
|
|
19447
|
+
},
|
|
19448
|
+
s.name
|
|
19449
|
+
);
|
|
19450
|
+
}) }),
|
|
19451
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", className: "tabular-nums", children: valueAt(series[0], label) }),
|
|
19452
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19453
|
+
Typography,
|
|
19454
|
+
{
|
|
19455
|
+
variant: "caption",
|
|
19456
|
+
color: "secondary",
|
|
19457
|
+
className: "truncate w-full text-center",
|
|
19458
|
+
children: displayLabel
|
|
19459
|
+
}
|
|
19460
|
+
)
|
|
19461
|
+
]
|
|
19462
|
+
},
|
|
19463
|
+
label
|
|
19464
|
+
);
|
|
19326
19465
|
}
|
|
19327
|
-
|
|
19328
|
-
|
|
19329
|
-
|
|
19466
|
+
const total = columnTotals?.[catIdx] ?? 1;
|
|
19467
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19468
|
+
VStack,
|
|
19469
|
+
{
|
|
19470
|
+
gap: "xs",
|
|
19471
|
+
align: "center",
|
|
19472
|
+
flex: true,
|
|
19473
|
+
className: "min-w-0",
|
|
19474
|
+
children: [
|
|
19475
|
+
/* @__PURE__ */ jsxRuntime.jsx(VStack, { gap: "none", className: "w-full", style: { height: "100%" }, justify: "end", children: series.map((s, sIdx) => {
|
|
19476
|
+
const value = valueAt(s, label);
|
|
19477
|
+
const ratio = stack === "normalize" ? total === 0 ? 0 : value / total * 100 : value / maxValue * 100;
|
|
19478
|
+
const color = seriesColor(s, sIdx);
|
|
19479
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19480
|
+
Box,
|
|
19481
|
+
{
|
|
19482
|
+
className: "w-full transition-all duration-500 ease-out cursor-pointer hover:opacity-80",
|
|
19483
|
+
style: {
|
|
19484
|
+
height: `${ratio}%`,
|
|
19485
|
+
backgroundColor: color
|
|
19486
|
+
},
|
|
19487
|
+
onClick: () => onPointClick?.(
|
|
19488
|
+
{ label, value, color },
|
|
19489
|
+
s.name
|
|
19490
|
+
),
|
|
19491
|
+
title: `${s.name}: ${value}`
|
|
19492
|
+
},
|
|
19493
|
+
s.name
|
|
19494
|
+
);
|
|
19495
|
+
}) }),
|
|
19496
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19497
|
+
Typography,
|
|
19498
|
+
{
|
|
19499
|
+
variant: "caption",
|
|
19500
|
+
color: "secondary",
|
|
19501
|
+
className: "truncate w-full text-center",
|
|
19502
|
+
children: displayLabel
|
|
19503
|
+
}
|
|
19504
|
+
)
|
|
19505
|
+
]
|
|
19506
|
+
},
|
|
19507
|
+
label
|
|
19508
|
+
);
|
|
19509
|
+
})
|
|
19510
|
+
}
|
|
19511
|
+
);
|
|
19330
19512
|
};
|
|
19331
|
-
PieChart = ({ data, height, showValues, donut = false }) => {
|
|
19513
|
+
PieChart = ({ data, height, showValues, donut = false, onPointClick }) => {
|
|
19332
19514
|
const total = data.reduce((sum, d) => sum + d.value, 0);
|
|
19333
19515
|
const size = Math.min(height, 200);
|
|
19334
19516
|
const radius = size / 2 - 8;
|
|
@@ -19374,7 +19556,11 @@ var init_Chart = __esm({
|
|
|
19374
19556
|
fill: seg.color,
|
|
19375
19557
|
stroke: "var(--color-card)",
|
|
19376
19558
|
strokeWidth: "2",
|
|
19377
|
-
className: "transition-opacity duration-200 hover:opacity-80"
|
|
19559
|
+
className: "transition-opacity duration-200 hover:opacity-80 cursor-pointer",
|
|
19560
|
+
onClick: () => onPointClick?.(
|
|
19561
|
+
{ label: seg.label, value: seg.value, color: seg.color },
|
|
19562
|
+
"default"
|
|
19563
|
+
)
|
|
19378
19564
|
},
|
|
19379
19565
|
idx
|
|
19380
19566
|
)),
|
|
@@ -19409,56 +19595,243 @@ var init_Chart = __esm({
|
|
|
19409
19595
|
] }, idx)) })
|
|
19410
19596
|
] });
|
|
19411
19597
|
};
|
|
19412
|
-
LineChart = ({
|
|
19413
|
-
const maxValue = Math.max(...data.map((d) => d.value), 1);
|
|
19598
|
+
LineChart = ({ series, height, showValues, fill = false, timeAxis, onPointClick }) => {
|
|
19414
19599
|
const width = 400;
|
|
19415
19600
|
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
19416
19601
|
const chartWidth = width - padding.left - padding.right;
|
|
19417
19602
|
const chartHeight = height - padding.top - padding.bottom;
|
|
19418
|
-
const
|
|
19419
|
-
|
|
19420
|
-
|
|
19421
|
-
|
|
19422
|
-
|
|
19423
|
-
|
|
19424
|
-
|
|
19425
|
-
|
|
19426
|
-
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
19427
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "100%", height, viewBox: `0 0 ${width} ${height}`, preserveAspectRatio: "xMidYMid meet", children: [
|
|
19428
|
-
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
19429
|
-
const y = padding.top + chartHeight * (1 - frac);
|
|
19430
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19431
|
-
"line",
|
|
19432
|
-
{
|
|
19433
|
-
x1: padding.left,
|
|
19434
|
-
y1: y,
|
|
19435
|
-
x2: width - padding.right,
|
|
19436
|
-
y2: y,
|
|
19437
|
-
stroke: "var(--color-border)",
|
|
19438
|
-
strokeDasharray: "4 4",
|
|
19439
|
-
opacity: 0.5
|
|
19440
|
-
},
|
|
19441
|
-
frac
|
|
19442
|
-
);
|
|
19443
|
-
}),
|
|
19444
|
-
fill && /* @__PURE__ */ jsxRuntime.jsx("path", { d: areaPath, fill: "var(--color-primary)", opacity: 0.1 }),
|
|
19445
|
-
/* @__PURE__ */ jsxRuntime.jsx("path", { d: linePath, fill: "none", stroke: "var(--color-primary)", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" }),
|
|
19446
|
-
points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
19447
|
-
/* @__PURE__ */ jsxRuntime.jsx("circle", { cx: p2.x, cy: p2.y, r: "4", fill: "var(--color-card)", stroke: "var(--color-primary)", strokeWidth: "2" }),
|
|
19448
|
-
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 }),
|
|
19449
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19450
|
-
"text",
|
|
19451
|
-
{
|
|
19452
|
-
x: p2.x,
|
|
19453
|
-
y: height - 8,
|
|
19454
|
-
textAnchor: "middle",
|
|
19455
|
-
fill: "var(--color-muted-foreground)",
|
|
19456
|
-
fontSize: "9",
|
|
19457
|
-
children: p2.label
|
|
19603
|
+
const labels = React81.useMemo(() => {
|
|
19604
|
+
const seen = /* @__PURE__ */ new Set();
|
|
19605
|
+
const out = [];
|
|
19606
|
+
for (const s of series) {
|
|
19607
|
+
for (const p2 of s.data) {
|
|
19608
|
+
if (!seen.has(p2.label)) {
|
|
19609
|
+
seen.add(p2.label);
|
|
19610
|
+
out.push(p2.label);
|
|
19458
19611
|
}
|
|
19459
|
-
|
|
19460
|
-
|
|
19461
|
-
|
|
19612
|
+
}
|
|
19613
|
+
}
|
|
19614
|
+
return out;
|
|
19615
|
+
}, [series]);
|
|
19616
|
+
const maxValue = React81.useMemo(() => {
|
|
19617
|
+
let m = 1;
|
|
19618
|
+
for (const s of series) {
|
|
19619
|
+
for (const p2 of s.data) if (p2.value > m) m = p2.value;
|
|
19620
|
+
}
|
|
19621
|
+
return m;
|
|
19622
|
+
}, [series]);
|
|
19623
|
+
const xFor = React81.useCallback(
|
|
19624
|
+
(idx) => padding.left + idx / Math.max(labels.length - 1, 1) * chartWidth,
|
|
19625
|
+
[labels.length, chartWidth, padding.left]
|
|
19626
|
+
);
|
|
19627
|
+
const yFor = React81.useCallback(
|
|
19628
|
+
(value) => padding.top + chartHeight - value / maxValue * chartHeight,
|
|
19629
|
+
[maxValue, chartHeight, padding.top]
|
|
19630
|
+
);
|
|
19631
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19632
|
+
"svg",
|
|
19633
|
+
{
|
|
19634
|
+
width: "100%",
|
|
19635
|
+
height,
|
|
19636
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
19637
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
19638
|
+
children: [
|
|
19639
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
19640
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
19641
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19642
|
+
"line",
|
|
19643
|
+
{
|
|
19644
|
+
x1: padding.left,
|
|
19645
|
+
y1: y,
|
|
19646
|
+
x2: width - padding.right,
|
|
19647
|
+
y2: y,
|
|
19648
|
+
stroke: "var(--color-border)",
|
|
19649
|
+
strokeDasharray: "4 4",
|
|
19650
|
+
opacity: 0.5
|
|
19651
|
+
},
|
|
19652
|
+
frac
|
|
19653
|
+
);
|
|
19654
|
+
}),
|
|
19655
|
+
series.map((s, sIdx) => {
|
|
19656
|
+
const color = seriesColor(s, sIdx);
|
|
19657
|
+
const points = labels.map((label, idx) => {
|
|
19658
|
+
const point = s.data.find((d) => d.label === label);
|
|
19659
|
+
return {
|
|
19660
|
+
x: xFor(idx),
|
|
19661
|
+
y: yFor(point ? point.value : 0),
|
|
19662
|
+
value: point ? point.value : 0,
|
|
19663
|
+
label
|
|
19664
|
+
};
|
|
19665
|
+
});
|
|
19666
|
+
const linePath = points.map((p2, i) => `${i === 0 ? "M" : "L"} ${p2.x} ${p2.y}`).join(" ");
|
|
19667
|
+
const areaPath = `${linePath} L ${points[points.length - 1]?.x ?? 0} ${padding.top + chartHeight} L ${padding.left} ${padding.top + chartHeight} Z`;
|
|
19668
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
19669
|
+
fill && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19670
|
+
"path",
|
|
19671
|
+
{
|
|
19672
|
+
d: areaPath,
|
|
19673
|
+
fill: color,
|
|
19674
|
+
opacity: series.length > 1 ? 0.08 : 0.1
|
|
19675
|
+
}
|
|
19676
|
+
),
|
|
19677
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19678
|
+
"path",
|
|
19679
|
+
{
|
|
19680
|
+
d: linePath,
|
|
19681
|
+
fill: "none",
|
|
19682
|
+
stroke: color,
|
|
19683
|
+
strokeWidth: "2",
|
|
19684
|
+
strokeLinecap: "round",
|
|
19685
|
+
strokeLinejoin: "round",
|
|
19686
|
+
strokeDasharray: s.dashed ? "6 4" : void 0
|
|
19687
|
+
}
|
|
19688
|
+
),
|
|
19689
|
+
points.map((p2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("g", { children: [
|
|
19690
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19691
|
+
"circle",
|
|
19692
|
+
{
|
|
19693
|
+
cx: p2.x,
|
|
19694
|
+
cy: p2.y,
|
|
19695
|
+
r: "4",
|
|
19696
|
+
fill: "var(--color-card)",
|
|
19697
|
+
stroke: color,
|
|
19698
|
+
strokeWidth: "2",
|
|
19699
|
+
className: "cursor-pointer",
|
|
19700
|
+
onClick: () => onPointClick?.(
|
|
19701
|
+
{ label: p2.label, value: p2.value, color },
|
|
19702
|
+
s.name
|
|
19703
|
+
)
|
|
19704
|
+
}
|
|
19705
|
+
),
|
|
19706
|
+
showValues && series.length === 1 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19707
|
+
"text",
|
|
19708
|
+
{
|
|
19709
|
+
x: p2.x,
|
|
19710
|
+
y: p2.y - 10,
|
|
19711
|
+
textAnchor: "middle",
|
|
19712
|
+
fill: "var(--color-foreground)",
|
|
19713
|
+
fontSize: "10",
|
|
19714
|
+
fontWeight: "500",
|
|
19715
|
+
children: p2.value
|
|
19716
|
+
}
|
|
19717
|
+
)
|
|
19718
|
+
] }, idx))
|
|
19719
|
+
] }, s.name);
|
|
19720
|
+
}),
|
|
19721
|
+
labels.map((label, idx) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
19722
|
+
"text",
|
|
19723
|
+
{
|
|
19724
|
+
x: xFor(idx),
|
|
19725
|
+
y: height - 8,
|
|
19726
|
+
textAnchor: "middle",
|
|
19727
|
+
fill: "var(--color-muted-foreground)",
|
|
19728
|
+
fontSize: "9",
|
|
19729
|
+
children: timeAxis ? formatTimeLabel(label) : label
|
|
19730
|
+
},
|
|
19731
|
+
label
|
|
19732
|
+
))
|
|
19733
|
+
]
|
|
19734
|
+
}
|
|
19735
|
+
);
|
|
19736
|
+
};
|
|
19737
|
+
ScatterChart = ({ data, height, onPointClick }) => {
|
|
19738
|
+
const width = 400;
|
|
19739
|
+
const padding = { top: 20, right: 20, bottom: 30, left: 40 };
|
|
19740
|
+
const chartWidth = width - padding.left - padding.right;
|
|
19741
|
+
const chartHeight = height - padding.top - padding.bottom;
|
|
19742
|
+
const { minX, maxX, minY, maxY } = React81.useMemo(() => {
|
|
19743
|
+
if (data.length === 0) {
|
|
19744
|
+
return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
|
|
19745
|
+
}
|
|
19746
|
+
let mnX = data[0].x;
|
|
19747
|
+
let mxX = data[0].x;
|
|
19748
|
+
let mnY = data[0].y;
|
|
19749
|
+
let mxY = data[0].y;
|
|
19750
|
+
for (const p2 of data) {
|
|
19751
|
+
if (p2.x < mnX) mnX = p2.x;
|
|
19752
|
+
if (p2.x > mxX) mxX = p2.x;
|
|
19753
|
+
if (p2.y < mnY) mnY = p2.y;
|
|
19754
|
+
if (p2.y > mxY) mxY = p2.y;
|
|
19755
|
+
}
|
|
19756
|
+
return { minX: mnX, maxX: mxX, minY: mnY, maxY: mxY };
|
|
19757
|
+
}, [data]);
|
|
19758
|
+
const rangeX = maxX - minX || 1;
|
|
19759
|
+
const rangeY = maxY - minY || 1;
|
|
19760
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
19761
|
+
"svg",
|
|
19762
|
+
{
|
|
19763
|
+
width: "100%",
|
|
19764
|
+
height,
|
|
19765
|
+
viewBox: `0 0 ${width} ${height}`,
|
|
19766
|
+
preserveAspectRatio: "xMidYMid meet",
|
|
19767
|
+
children: [
|
|
19768
|
+
[0, 0.25, 0.5, 0.75, 1].map((frac) => {
|
|
19769
|
+
const y = padding.top + chartHeight * (1 - frac);
|
|
19770
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19771
|
+
"line",
|
|
19772
|
+
{
|
|
19773
|
+
x1: padding.left,
|
|
19774
|
+
y1: y,
|
|
19775
|
+
x2: width - padding.right,
|
|
19776
|
+
y2: y,
|
|
19777
|
+
stroke: "var(--color-border)",
|
|
19778
|
+
strokeDasharray: "4 4",
|
|
19779
|
+
opacity: 0.5
|
|
19780
|
+
},
|
|
19781
|
+
frac
|
|
19782
|
+
);
|
|
19783
|
+
}),
|
|
19784
|
+
data.map((p2, idx) => {
|
|
19785
|
+
const cx = padding.left + (p2.x - minX) / rangeX * chartWidth;
|
|
19786
|
+
const cy = padding.top + chartHeight - (p2.y - minY) / rangeY * chartHeight;
|
|
19787
|
+
const r = p2.size ?? 5;
|
|
19788
|
+
const color = p2.color ?? CHART_COLORS[idx % CHART_COLORS.length];
|
|
19789
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
19790
|
+
"circle",
|
|
19791
|
+
{
|
|
19792
|
+
cx,
|
|
19793
|
+
cy,
|
|
19794
|
+
r,
|
|
19795
|
+
fill: color,
|
|
19796
|
+
opacity: 0.7,
|
|
19797
|
+
className: "cursor-pointer hover:opacity-100",
|
|
19798
|
+
onClick: () => onPointClick?.(
|
|
19799
|
+
{
|
|
19800
|
+
label: p2.label ?? `(${p2.x}, ${p2.y})`,
|
|
19801
|
+
value: p2.y,
|
|
19802
|
+
color
|
|
19803
|
+
},
|
|
19804
|
+
"default"
|
|
19805
|
+
),
|
|
19806
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("title", { children: p2.label ?? `(${p2.x}, ${p2.y})` })
|
|
19807
|
+
},
|
|
19808
|
+
idx
|
|
19809
|
+
);
|
|
19810
|
+
}),
|
|
19811
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19812
|
+
"text",
|
|
19813
|
+
{
|
|
19814
|
+
x: padding.left,
|
|
19815
|
+
y: height - 8,
|
|
19816
|
+
fill: "var(--color-muted-foreground)",
|
|
19817
|
+
fontSize: "9",
|
|
19818
|
+
children: minX.toFixed(1)
|
|
19819
|
+
}
|
|
19820
|
+
),
|
|
19821
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19822
|
+
"text",
|
|
19823
|
+
{
|
|
19824
|
+
x: width - padding.right,
|
|
19825
|
+
y: height - 8,
|
|
19826
|
+
textAnchor: "end",
|
|
19827
|
+
fill: "var(--color-muted-foreground)",
|
|
19828
|
+
fontSize: "9",
|
|
19829
|
+
children: maxX.toFixed(1)
|
|
19830
|
+
}
|
|
19831
|
+
)
|
|
19832
|
+
]
|
|
19833
|
+
}
|
|
19834
|
+
);
|
|
19462
19835
|
};
|
|
19463
19836
|
Chart = ({
|
|
19464
19837
|
title,
|
|
@@ -19466,9 +19839,13 @@ var init_Chart = __esm({
|
|
|
19466
19839
|
chartType = "bar",
|
|
19467
19840
|
series,
|
|
19468
19841
|
data: simpleData,
|
|
19842
|
+
scatterData,
|
|
19469
19843
|
height = 200,
|
|
19470
19844
|
showLegend = true,
|
|
19471
19845
|
showValues = false,
|
|
19846
|
+
stack = "none",
|
|
19847
|
+
timeAxis = false,
|
|
19848
|
+
drillEvent,
|
|
19472
19849
|
actions,
|
|
19473
19850
|
entity,
|
|
19474
19851
|
isLoading = false,
|
|
@@ -19485,11 +19862,25 @@ var init_Chart = __esm({
|
|
|
19485
19862
|
},
|
|
19486
19863
|
[eventBus]
|
|
19487
19864
|
);
|
|
19488
|
-
const
|
|
19489
|
-
|
|
19490
|
-
|
|
19865
|
+
const handlePointClick = React81.useCallback(
|
|
19866
|
+
(point, seriesName) => {
|
|
19867
|
+
if (drillEvent) {
|
|
19868
|
+
eventBus.emit(`UI:${drillEvent}`, {
|
|
19869
|
+
label: point.label,
|
|
19870
|
+
value: point.value,
|
|
19871
|
+
seriesLabel: seriesName === "default" ? void 0 : seriesName
|
|
19872
|
+
});
|
|
19873
|
+
}
|
|
19874
|
+
},
|
|
19875
|
+
[drillEvent, eventBus]
|
|
19876
|
+
);
|
|
19877
|
+
const normalizedSeries = React81.useMemo(() => {
|
|
19878
|
+
if (series && series.length > 0) return series;
|
|
19879
|
+
if (simpleData) return [{ name: "default", data: simpleData }];
|
|
19491
19880
|
return [];
|
|
19492
19881
|
}, [simpleData, series]);
|
|
19882
|
+
const firstSeriesData = normalizedSeries[0]?.data ?? [];
|
|
19883
|
+
const hasContent = chartType === "scatter" ? (scatterData?.length ?? 0) > 0 : normalizedSeries.some((s) => s.data.length > 0);
|
|
19493
19884
|
if (isLoading) {
|
|
19494
19885
|
return /* @__PURE__ */ jsxRuntime.jsx(LoadingState, { message: "Loading chart...", className });
|
|
19495
19886
|
}
|
|
@@ -19503,7 +19894,7 @@ var init_Chart = __esm({
|
|
|
19503
19894
|
}
|
|
19504
19895
|
);
|
|
19505
19896
|
}
|
|
19506
|
-
if (
|
|
19897
|
+
if (!hasContent) {
|
|
19507
19898
|
return /* @__PURE__ */ jsxRuntime.jsx(EmptyState, { title: t("empty.noData"), description: t("empty.noData"), className });
|
|
19508
19899
|
}
|
|
19509
19900
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn("p-6", className), children: /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "md", children: [
|
|
@@ -19524,18 +19915,84 @@ var init_Chart = __esm({
|
|
|
19524
19915
|
)) })
|
|
19525
19916
|
] }),
|
|
19526
19917
|
/* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "w-full", children: [
|
|
19527
|
-
chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19528
|
-
|
|
19529
|
-
|
|
19530
|
-
|
|
19531
|
-
|
|
19918
|
+
chartType === "bar" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19919
|
+
BarChart,
|
|
19920
|
+
{
|
|
19921
|
+
series: normalizedSeries,
|
|
19922
|
+
height,
|
|
19923
|
+
showValues,
|
|
19924
|
+
stack,
|
|
19925
|
+
timeAxis,
|
|
19926
|
+
onPointClick: handlePointClick
|
|
19927
|
+
}
|
|
19928
|
+
),
|
|
19929
|
+
chartType === "histogram" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19930
|
+
BarChart,
|
|
19931
|
+
{
|
|
19932
|
+
series: normalizedSeries,
|
|
19933
|
+
height,
|
|
19934
|
+
showValues,
|
|
19935
|
+
stack: "none",
|
|
19936
|
+
timeAxis: false,
|
|
19937
|
+
histogram: true,
|
|
19938
|
+
onPointClick: handlePointClick
|
|
19939
|
+
}
|
|
19940
|
+
),
|
|
19941
|
+
chartType === "line" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19942
|
+
LineChart,
|
|
19943
|
+
{
|
|
19944
|
+
series: normalizedSeries,
|
|
19945
|
+
height,
|
|
19946
|
+
showValues,
|
|
19947
|
+
timeAxis,
|
|
19948
|
+
onPointClick: handlePointClick
|
|
19949
|
+
}
|
|
19950
|
+
),
|
|
19951
|
+
chartType === "area" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19952
|
+
LineChart,
|
|
19953
|
+
{
|
|
19954
|
+
series: normalizedSeries,
|
|
19955
|
+
height,
|
|
19956
|
+
showValues,
|
|
19957
|
+
timeAxis,
|
|
19958
|
+
fill: true,
|
|
19959
|
+
onPointClick: handlePointClick
|
|
19960
|
+
}
|
|
19961
|
+
),
|
|
19962
|
+
chartType === "pie" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19963
|
+
PieChart,
|
|
19964
|
+
{
|
|
19965
|
+
data: firstSeriesData,
|
|
19966
|
+
height,
|
|
19967
|
+
showValues: showLegend,
|
|
19968
|
+
onPointClick: handlePointClick
|
|
19969
|
+
}
|
|
19970
|
+
),
|
|
19971
|
+
chartType === "donut" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19972
|
+
PieChart,
|
|
19973
|
+
{
|
|
19974
|
+
data: firstSeriesData,
|
|
19975
|
+
height,
|
|
19976
|
+
showValues: showLegend,
|
|
19977
|
+
donut: true,
|
|
19978
|
+
onPointClick: handlePointClick
|
|
19979
|
+
}
|
|
19980
|
+
),
|
|
19981
|
+
chartType === "scatter" && /* @__PURE__ */ jsxRuntime.jsx(
|
|
19982
|
+
ScatterChart,
|
|
19983
|
+
{
|
|
19984
|
+
data: scatterData ?? [],
|
|
19985
|
+
height,
|
|
19986
|
+
onPointClick: handlePointClick
|
|
19987
|
+
}
|
|
19988
|
+
)
|
|
19532
19989
|
] }),
|
|
19533
|
-
showLegend &&
|
|
19990
|
+
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: [
|
|
19534
19991
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
19535
19992
|
Box,
|
|
19536
19993
|
{
|
|
19537
19994
|
className: "w-3 h-3 rounded-full flex-shrink-0",
|
|
19538
|
-
style: { backgroundColor: s
|
|
19995
|
+
style: { backgroundColor: seriesColor(s, idx) }
|
|
19539
19996
|
}
|
|
19540
19997
|
),
|
|
19541
19998
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: s.name })
|
|
@@ -24451,6 +24908,151 @@ var init_FlipCard = __esm({
|
|
|
24451
24908
|
FlipCard.displayName = "FlipCard";
|
|
24452
24909
|
}
|
|
24453
24910
|
});
|
|
24911
|
+
function toISODate(d) {
|
|
24912
|
+
return d.toISOString().slice(0, 10);
|
|
24913
|
+
}
|
|
24914
|
+
function startOfMonth(d) {
|
|
24915
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
24916
|
+
}
|
|
24917
|
+
function startOfQuarter(d) {
|
|
24918
|
+
return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
|
|
24919
|
+
}
|
|
24920
|
+
function startOfYear(d) {
|
|
24921
|
+
return new Date(d.getFullYear(), 0, 1);
|
|
24922
|
+
}
|
|
24923
|
+
function daysAgo(n) {
|
|
24924
|
+
const d = /* @__PURE__ */ new Date();
|
|
24925
|
+
d.setDate(d.getDate() - n);
|
|
24926
|
+
return d;
|
|
24927
|
+
}
|
|
24928
|
+
var DEFAULT_PRESETS, DateRangePicker;
|
|
24929
|
+
var init_DateRangePicker = __esm({
|
|
24930
|
+
"components/molecules/DateRangePicker.tsx"() {
|
|
24931
|
+
"use client";
|
|
24932
|
+
init_cn();
|
|
24933
|
+
init_Button();
|
|
24934
|
+
init_Input();
|
|
24935
|
+
init_Stack();
|
|
24936
|
+
init_Typography();
|
|
24937
|
+
init_useEventBus();
|
|
24938
|
+
DEFAULT_PRESETS = [
|
|
24939
|
+
{
|
|
24940
|
+
label: "Last 7 days",
|
|
24941
|
+
value: "7d",
|
|
24942
|
+
range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
24943
|
+
},
|
|
24944
|
+
{
|
|
24945
|
+
label: "Last 30 days",
|
|
24946
|
+
value: "30d",
|
|
24947
|
+
range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
24948
|
+
},
|
|
24949
|
+
{
|
|
24950
|
+
label: "This Month",
|
|
24951
|
+
value: "month",
|
|
24952
|
+
range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
24953
|
+
},
|
|
24954
|
+
{
|
|
24955
|
+
label: "This Quarter",
|
|
24956
|
+
value: "quarter",
|
|
24957
|
+
range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
24958
|
+
},
|
|
24959
|
+
{
|
|
24960
|
+
label: "YTD",
|
|
24961
|
+
value: "ytd",
|
|
24962
|
+
range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
24963
|
+
}
|
|
24964
|
+
];
|
|
24965
|
+
DateRangePicker = ({
|
|
24966
|
+
from: fromProp,
|
|
24967
|
+
to: toProp,
|
|
24968
|
+
event,
|
|
24969
|
+
onChange,
|
|
24970
|
+
presets = DEFAULT_PRESETS,
|
|
24971
|
+
fromLabel = "From",
|
|
24972
|
+
toLabel = "To",
|
|
24973
|
+
className
|
|
24974
|
+
}) => {
|
|
24975
|
+
const eventBus = useEventBus();
|
|
24976
|
+
const [from, setFrom] = React81.useState(fromProp ?? "");
|
|
24977
|
+
const [to, setTo] = React81.useState(toProp ?? "");
|
|
24978
|
+
const [activePreset, setActivePreset] = React81.useState(null);
|
|
24979
|
+
const emit = React81.useCallback(
|
|
24980
|
+
(range) => {
|
|
24981
|
+
onChange?.(range);
|
|
24982
|
+
if (event) eventBus.emit(`UI:${event}`, range);
|
|
24983
|
+
},
|
|
24984
|
+
[onChange, event, eventBus]
|
|
24985
|
+
);
|
|
24986
|
+
const handleFromChange = React81.useCallback(
|
|
24987
|
+
(next) => {
|
|
24988
|
+
setFrom(next);
|
|
24989
|
+
setActivePreset(null);
|
|
24990
|
+
emit({ from: next, to });
|
|
24991
|
+
},
|
|
24992
|
+
[to, emit]
|
|
24993
|
+
);
|
|
24994
|
+
const handleToChange = React81.useCallback(
|
|
24995
|
+
(next) => {
|
|
24996
|
+
setTo(next);
|
|
24997
|
+
setActivePreset(null);
|
|
24998
|
+
emit({ from, to: next });
|
|
24999
|
+
},
|
|
25000
|
+
[from, emit]
|
|
25001
|
+
);
|
|
25002
|
+
const handlePreset = React81.useCallback(
|
|
25003
|
+
(preset) => {
|
|
25004
|
+
const range = preset.range();
|
|
25005
|
+
setFrom(range.from);
|
|
25006
|
+
setTo(range.to);
|
|
25007
|
+
setActivePreset(preset.value);
|
|
25008
|
+
emit(range);
|
|
25009
|
+
},
|
|
25010
|
+
[emit]
|
|
25011
|
+
);
|
|
25012
|
+
const presetButtons = React81.useMemo(
|
|
25013
|
+
() => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
25014
|
+
Button,
|
|
25015
|
+
{
|
|
25016
|
+
variant: activePreset === preset.value ? "primary" : "ghost",
|
|
25017
|
+
size: "sm",
|
|
25018
|
+
onClick: () => handlePreset(preset),
|
|
25019
|
+
children: preset.label
|
|
25020
|
+
},
|
|
25021
|
+
preset.value
|
|
25022
|
+
)),
|
|
25023
|
+
[presets, activePreset, handlePreset]
|
|
25024
|
+
);
|
|
25025
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: cn(className), children: [
|
|
25026
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "end", children: [
|
|
25027
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
25028
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: fromLabel }),
|
|
25029
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25030
|
+
Input,
|
|
25031
|
+
{
|
|
25032
|
+
type: "date",
|
|
25033
|
+
value: from,
|
|
25034
|
+
onChange: (e) => handleFromChange(e.target.value)
|
|
25035
|
+
}
|
|
25036
|
+
)
|
|
25037
|
+
] }),
|
|
25038
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
25039
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: toLabel }),
|
|
25040
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
25041
|
+
Input,
|
|
25042
|
+
{
|
|
25043
|
+
type: "date",
|
|
25044
|
+
value: to,
|
|
25045
|
+
onChange: (e) => handleToChange(e.target.value)
|
|
25046
|
+
}
|
|
25047
|
+
)
|
|
25048
|
+
] })
|
|
25049
|
+
] }),
|
|
25050
|
+
presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
|
|
25051
|
+
] });
|
|
25052
|
+
};
|
|
25053
|
+
DateRangePicker.displayName = "DateRangePicker";
|
|
25054
|
+
}
|
|
25055
|
+
});
|
|
24454
25056
|
var DEFAULT_OPTIONS, DateRangeSelector;
|
|
24455
25057
|
var init_DateRangeSelector = __esm({
|
|
24456
25058
|
"components/molecules/DateRangeSelector.tsx"() {
|
|
@@ -27422,7 +28024,9 @@ var init_StatDisplay = __esm({
|
|
|
27422
28024
|
init_Typography();
|
|
27423
28025
|
init_Box();
|
|
27424
28026
|
init_Stack();
|
|
28027
|
+
init_Sparkline();
|
|
27425
28028
|
init_Icon();
|
|
28029
|
+
init_useEventBus();
|
|
27426
28030
|
variantColor = {
|
|
27427
28031
|
default: "text-foreground",
|
|
27428
28032
|
primary: "text-primary",
|
|
@@ -27437,6 +28041,10 @@ var init_StatDisplay = __esm({
|
|
|
27437
28041
|
max,
|
|
27438
28042
|
target,
|
|
27439
28043
|
trend,
|
|
28044
|
+
trendPolarity = "higher-is-better",
|
|
28045
|
+
trendFormat = "absolute",
|
|
28046
|
+
sparklineData,
|
|
28047
|
+
clickEvent,
|
|
27440
28048
|
prefix,
|
|
27441
28049
|
suffix,
|
|
27442
28050
|
icon: iconProp,
|
|
@@ -27450,6 +28058,10 @@ var init_StatDisplay = __esm({
|
|
|
27450
28058
|
isLoading = false,
|
|
27451
28059
|
error = null
|
|
27452
28060
|
}) => {
|
|
28061
|
+
const eventBus = useEventBus();
|
|
28062
|
+
const handleClick = React81.useCallback(() => {
|
|
28063
|
+
if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
|
|
28064
|
+
}, [clickEvent, eventBus, label]);
|
|
27453
28065
|
const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
|
|
27454
28066
|
const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
|
|
27455
28067
|
const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
|
|
@@ -27460,7 +28072,10 @@ var init_StatDisplay = __esm({
|
|
|
27460
28072
|
const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
|
|
27461
28073
|
const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
|
|
27462
28074
|
const trendUp = showTrend && trend > 0;
|
|
27463
|
-
const
|
|
28075
|
+
const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
|
|
28076
|
+
const trendMagnitude = Math.abs(trend);
|
|
28077
|
+
const trendSuffix = trendFormat === "percent" ? "%" : "";
|
|
28078
|
+
const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
|
|
27464
28079
|
if (error) {
|
|
27465
28080
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
|
|
27466
28081
|
}
|
|
@@ -27471,38 +28086,57 @@ var init_StatDisplay = __esm({
|
|
|
27471
28086
|
] }) });
|
|
27472
28087
|
}
|
|
27473
28088
|
if (compact) {
|
|
27474
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
27475
|
-
|
|
27476
|
-
|
|
27477
|
-
|
|
27478
|
-
|
|
27479
|
-
|
|
27480
|
-
|
|
28089
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
28090
|
+
HStack,
|
|
28091
|
+
{
|
|
28092
|
+
gap: "sm",
|
|
28093
|
+
className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
|
|
28094
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
28095
|
+
children: [
|
|
28096
|
+
ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
|
|
28097
|
+
typeof iconProp !== "string" && iconProp,
|
|
28098
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
|
|
28099
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
28100
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
|
|
28101
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
|
|
28102
|
+
]
|
|
28103
|
+
}
|
|
28104
|
+
);
|
|
27481
28105
|
}
|
|
27482
|
-
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
27483
|
-
|
|
27484
|
-
|
|
27485
|
-
|
|
27486
|
-
|
|
27487
|
-
|
|
27488
|
-
|
|
27489
|
-
{
|
|
27490
|
-
|
|
27491
|
-
className: cn("font-
|
|
27492
|
-
|
|
27493
|
-
|
|
27494
|
-
|
|
27495
|
-
|
|
27496
|
-
|
|
27497
|
-
|
|
27498
|
-
|
|
27499
|
-
|
|
27500
|
-
|
|
27501
|
-
|
|
27502
|
-
|
|
27503
|
-
|
|
27504
|
-
|
|
27505
|
-
|
|
28106
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
28107
|
+
Card,
|
|
28108
|
+
{
|
|
28109
|
+
className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
|
|
28110
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
28111
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
|
|
28112
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
|
|
28113
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
|
|
28114
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
|
|
28115
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
28116
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(
|
|
28117
|
+
Typography,
|
|
28118
|
+
{
|
|
28119
|
+
variant: "caption",
|
|
28120
|
+
className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
|
|
28121
|
+
children: trendLabel
|
|
28122
|
+
}
|
|
28123
|
+
)
|
|
28124
|
+
] }),
|
|
28125
|
+
showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
28126
|
+
Box,
|
|
28127
|
+
{
|
|
28128
|
+
className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
|
|
28129
|
+
style: { width: `${targetPct}%` }
|
|
28130
|
+
}
|
|
28131
|
+
) })
|
|
28132
|
+
] }),
|
|
28133
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
28134
|
+
(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 }),
|
|
28135
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
28136
|
+
] })
|
|
28137
|
+
] })
|
|
28138
|
+
}
|
|
28139
|
+
);
|
|
27506
28140
|
};
|
|
27507
28141
|
StatDisplay.displayName = "StatDisplay";
|
|
27508
28142
|
}
|
|
@@ -41965,6 +42599,7 @@ var init_StatCard = __esm({
|
|
|
41965
42599
|
init_Box();
|
|
41966
42600
|
init_Stack();
|
|
41967
42601
|
init_Button();
|
|
42602
|
+
init_Sparkline();
|
|
41968
42603
|
init_useEventBus();
|
|
41969
42604
|
init_useTranslate();
|
|
41970
42605
|
init_Icon();
|
|
@@ -42134,32 +42769,7 @@ var init_StatCard = __esm({
|
|
|
42134
42769
|
] }),
|
|
42135
42770
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
42136
42771
|
Icon3 && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: cn("p-3", iconBg), children: /* @__PURE__ */ jsxRuntime.jsx(Icon3, { className: cn("h-6 w-6", iconColor) }) }),
|
|
42137
|
-
sparklineData && sparklineData.length > 1 && (
|
|
42138
|
-
const w = 80;
|
|
42139
|
-
const h = 32;
|
|
42140
|
-
const pad = 2;
|
|
42141
|
-
const min = Math.min(...sparklineData);
|
|
42142
|
-
const max = Math.max(...sparklineData);
|
|
42143
|
-
const range = max - min || 1;
|
|
42144
|
-
const points = sparklineData.map((v, i) => {
|
|
42145
|
-
const x = pad + i / (sparklineData.length - 1) * (w - pad * 2);
|
|
42146
|
-
const y = pad + (1 - (v - min) / range) * (h - pad * 2);
|
|
42147
|
-
return `${x},${y}`;
|
|
42148
|
-
}).join(" ");
|
|
42149
|
-
const trending = sparklineData[sparklineData.length - 1] >= sparklineData[0];
|
|
42150
|
-
const strokeColor = trending ? "var(--color-success)" : "var(--color-error)";
|
|
42151
|
-
return /* @__PURE__ */ jsxRuntime.jsx("svg", { width: w, height: h, viewBox: `0 0 ${w} ${h}`, className: "flex-shrink-0", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
42152
|
-
"polyline",
|
|
42153
|
-
{
|
|
42154
|
-
fill: "none",
|
|
42155
|
-
stroke: strokeColor,
|
|
42156
|
-
strokeWidth: "2",
|
|
42157
|
-
strokeLinecap: "round",
|
|
42158
|
-
strokeLinejoin: "round",
|
|
42159
|
-
points
|
|
42160
|
-
}
|
|
42161
|
-
) });
|
|
42162
|
-
})()
|
|
42772
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
42163
42773
|
] })
|
|
42164
42774
|
] }),
|
|
42165
42775
|
action && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -44057,6 +44667,7 @@ var init_component_registry_generated = __esm({
|
|
|
44057
44667
|
init_DataGrid();
|
|
44058
44668
|
init_DataList();
|
|
44059
44669
|
init_DataTable();
|
|
44670
|
+
init_DateRangePicker();
|
|
44060
44671
|
init_DateRangeSelector();
|
|
44061
44672
|
init_DayCell();
|
|
44062
44673
|
init_DebuggerBoard();
|
|
@@ -44189,6 +44800,7 @@ var init_component_registry_generated = __esm({
|
|
|
44189
44800
|
init_Skeleton();
|
|
44190
44801
|
init_SocialProof();
|
|
44191
44802
|
init_SortableList();
|
|
44803
|
+
init_Sparkline();
|
|
44192
44804
|
init_Split();
|
|
44193
44805
|
init_SplitPane();
|
|
44194
44806
|
init_SplitSection();
|
|
@@ -44337,6 +44949,7 @@ var init_component_registry_generated = __esm({
|
|
|
44337
44949
|
"DataGrid": DataGrid,
|
|
44338
44950
|
"DataList": DataList,
|
|
44339
44951
|
"DataTable": DataTable,
|
|
44952
|
+
"DateRangePicker": DateRangePicker,
|
|
44340
44953
|
"DateRangeSelector": DateRangeSelector,
|
|
44341
44954
|
"DayCell": DayCell,
|
|
44342
44955
|
"DebuggerBoard": DebuggerBoard,
|
|
@@ -44498,6 +45111,7 @@ var init_component_registry_generated = __esm({
|
|
|
44498
45111
|
"SortableList": SortableList,
|
|
44499
45112
|
"Spacer": SpacerPattern,
|
|
44500
45113
|
"SpacerPattern": SpacerPattern,
|
|
45114
|
+
"Sparkline": Sparkline,
|
|
44501
45115
|
"Spinner": SpinnerPattern,
|
|
44502
45116
|
"SpinnerPattern": SpinnerPattern,
|
|
44503
45117
|
"Split": Split,
|