@almadar/ui 4.51.14 → 4.51.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/avl/index.cjs +807 -154
- package/dist/avl/index.js +807 -154
- package/dist/components/atoms/Sparkline.d.ts +30 -0
- package/dist/components/atoms/index.d.ts +1 -0
- package/dist/components/index.cjs +797 -153
- package/dist/components/index.js +798 -154
- package/dist/components/molecules/DateRangePicker.d.ts +56 -0
- package/dist/components/molecules/FilterGroup.d.ts +3 -3
- package/dist/components/molecules/StatDisplay.d.ts +9 -1
- package/dist/components/molecules/index.d.ts +1 -0
- package/dist/components/organisms/Chart.d.ts +32 -12
- package/dist/providers/index.cjs +795 -153
- package/dist/providers/index.js +795 -153
- package/dist/runtime/index.cjs +795 -153
- package/dist/runtime/index.js +795 -153
- package/package.json +1 -1
package/dist/avl/index.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 })
|
|
@@ -24984,7 +25441,6 @@ function useDataDnd(args) {
|
|
|
24984
25441
|
const raw = it[dndItemIdField];
|
|
24985
25442
|
return raw ?? `__idx_${idx}`;
|
|
24986
25443
|
}),
|
|
24987
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
24988
25444
|
[itemIdsSignature]
|
|
24989
25445
|
);
|
|
24990
25446
|
const itemsContentSig = items.map((it, idx) => String(it[dndItemIdField] ?? `__${idx}`)).join("|");
|
|
@@ -26578,7 +27034,16 @@ var init_FilterGroup = __esm({
|
|
|
26578
27034
|
onClear: () => handleFilterSelect(`${filter.field}_to`, null)
|
|
26579
27035
|
}
|
|
26580
27036
|
)
|
|
26581
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
27037
|
+
] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
27038
|
+
Input,
|
|
27039
|
+
{
|
|
27040
|
+
value: selectedValues[filter.field] || "",
|
|
27041
|
+
onChange: (e) => handleFilterSelect(filter.field, e.target.value || null),
|
|
27042
|
+
placeholder: filter.label,
|
|
27043
|
+
clearable: true,
|
|
27044
|
+
onClear: () => handleFilterSelect(filter.field, null)
|
|
27045
|
+
}
|
|
27046
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
26582
27047
|
Select,
|
|
26583
27048
|
{
|
|
26584
27049
|
value: selectedValues[filter.field] || "all",
|
|
@@ -26645,7 +27110,17 @@ var init_FilterGroup = __esm({
|
|
|
26645
27110
|
className: "text-sm min-w-[100px]"
|
|
26646
27111
|
}
|
|
26647
27112
|
)
|
|
26648
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
27113
|
+
] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
27114
|
+
Input,
|
|
27115
|
+
{
|
|
27116
|
+
value: selectedValues[filter.field] || "",
|
|
27117
|
+
onChange: (e) => handleFilterSelect(filter.field, e.target.value || null),
|
|
27118
|
+
placeholder: filter.label,
|
|
27119
|
+
clearable: true,
|
|
27120
|
+
onClear: () => handleFilterSelect(filter.field, null),
|
|
27121
|
+
className: "text-sm"
|
|
27122
|
+
}
|
|
27123
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
26649
27124
|
Select,
|
|
26650
27125
|
{
|
|
26651
27126
|
value: selectedValues[filter.field] || "all",
|
|
@@ -26750,7 +27225,17 @@ var init_FilterGroup = __esm({
|
|
|
26750
27225
|
className: "min-w-[130px]"
|
|
26751
27226
|
}
|
|
26752
27227
|
)
|
|
26753
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
27228
|
+
] }) : resolveFilterType(filter) === "text" ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
27229
|
+
Input,
|
|
27230
|
+
{
|
|
27231
|
+
value: selectedValues[filter.field] || "",
|
|
27232
|
+
onChange: (e) => handleFilterSelect(filter.field, e.target.value || null),
|
|
27233
|
+
placeholder: filter.label,
|
|
27234
|
+
clearable: true,
|
|
27235
|
+
onClear: () => handleFilterSelect(filter.field, null),
|
|
27236
|
+
className: "min-w-[160px]"
|
|
27237
|
+
}
|
|
27238
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
26754
27239
|
Select,
|
|
26755
27240
|
{
|
|
26756
27241
|
value: selectedValues[filter.field] || "all",
|
|
@@ -28039,6 +28524,151 @@ var init_FlipCard = __esm({
|
|
|
28039
28524
|
FlipCard.displayName = "FlipCard";
|
|
28040
28525
|
}
|
|
28041
28526
|
});
|
|
28527
|
+
function toISODate(d) {
|
|
28528
|
+
return d.toISOString().slice(0, 10);
|
|
28529
|
+
}
|
|
28530
|
+
function startOfMonth(d) {
|
|
28531
|
+
return new Date(d.getFullYear(), d.getMonth(), 1);
|
|
28532
|
+
}
|
|
28533
|
+
function startOfQuarter(d) {
|
|
28534
|
+
return new Date(d.getFullYear(), Math.floor(d.getMonth() / 3) * 3, 1);
|
|
28535
|
+
}
|
|
28536
|
+
function startOfYear(d) {
|
|
28537
|
+
return new Date(d.getFullYear(), 0, 1);
|
|
28538
|
+
}
|
|
28539
|
+
function daysAgo(n) {
|
|
28540
|
+
const d = /* @__PURE__ */ new Date();
|
|
28541
|
+
d.setDate(d.getDate() - n);
|
|
28542
|
+
return d;
|
|
28543
|
+
}
|
|
28544
|
+
var DEFAULT_PRESETS, DateRangePicker;
|
|
28545
|
+
var init_DateRangePicker = __esm({
|
|
28546
|
+
"components/molecules/DateRangePicker.tsx"() {
|
|
28547
|
+
"use client";
|
|
28548
|
+
init_cn();
|
|
28549
|
+
init_Button();
|
|
28550
|
+
init_Input();
|
|
28551
|
+
init_Stack();
|
|
28552
|
+
init_Typography();
|
|
28553
|
+
init_useEventBus();
|
|
28554
|
+
DEFAULT_PRESETS = [
|
|
28555
|
+
{
|
|
28556
|
+
label: "Last 7 days",
|
|
28557
|
+
value: "7d",
|
|
28558
|
+
range: () => ({ from: toISODate(daysAgo(7)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28559
|
+
},
|
|
28560
|
+
{
|
|
28561
|
+
label: "Last 30 days",
|
|
28562
|
+
value: "30d",
|
|
28563
|
+
range: () => ({ from: toISODate(daysAgo(30)), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28564
|
+
},
|
|
28565
|
+
{
|
|
28566
|
+
label: "This Month",
|
|
28567
|
+
value: "month",
|
|
28568
|
+
range: () => ({ from: toISODate(startOfMonth(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28569
|
+
},
|
|
28570
|
+
{
|
|
28571
|
+
label: "This Quarter",
|
|
28572
|
+
value: "quarter",
|
|
28573
|
+
range: () => ({ from: toISODate(startOfQuarter(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28574
|
+
},
|
|
28575
|
+
{
|
|
28576
|
+
label: "YTD",
|
|
28577
|
+
value: "ytd",
|
|
28578
|
+
range: () => ({ from: toISODate(startOfYear(/* @__PURE__ */ new Date())), to: toISODate(/* @__PURE__ */ new Date()) })
|
|
28579
|
+
}
|
|
28580
|
+
];
|
|
28581
|
+
DateRangePicker = ({
|
|
28582
|
+
from: fromProp,
|
|
28583
|
+
to: toProp,
|
|
28584
|
+
event,
|
|
28585
|
+
onChange,
|
|
28586
|
+
presets = DEFAULT_PRESETS,
|
|
28587
|
+
fromLabel = "From",
|
|
28588
|
+
toLabel = "To",
|
|
28589
|
+
className
|
|
28590
|
+
}) => {
|
|
28591
|
+
const eventBus = useEventBus();
|
|
28592
|
+
const [from, setFrom] = React93.useState(fromProp ?? "");
|
|
28593
|
+
const [to, setTo] = React93.useState(toProp ?? "");
|
|
28594
|
+
const [activePreset, setActivePreset] = React93.useState(null);
|
|
28595
|
+
const emit = React93.useCallback(
|
|
28596
|
+
(range) => {
|
|
28597
|
+
onChange?.(range);
|
|
28598
|
+
if (event) eventBus.emit(`UI:${event}`, range);
|
|
28599
|
+
},
|
|
28600
|
+
[onChange, event, eventBus]
|
|
28601
|
+
);
|
|
28602
|
+
const handleFromChange = React93.useCallback(
|
|
28603
|
+
(next) => {
|
|
28604
|
+
setFrom(next);
|
|
28605
|
+
setActivePreset(null);
|
|
28606
|
+
emit({ from: next, to });
|
|
28607
|
+
},
|
|
28608
|
+
[to, emit]
|
|
28609
|
+
);
|
|
28610
|
+
const handleToChange = React93.useCallback(
|
|
28611
|
+
(next) => {
|
|
28612
|
+
setTo(next);
|
|
28613
|
+
setActivePreset(null);
|
|
28614
|
+
emit({ from, to: next });
|
|
28615
|
+
},
|
|
28616
|
+
[from, emit]
|
|
28617
|
+
);
|
|
28618
|
+
const handlePreset = React93.useCallback(
|
|
28619
|
+
(preset) => {
|
|
28620
|
+
const range = preset.range();
|
|
28621
|
+
setFrom(range.from);
|
|
28622
|
+
setTo(range.to);
|
|
28623
|
+
setActivePreset(preset.value);
|
|
28624
|
+
emit(range);
|
|
28625
|
+
},
|
|
28626
|
+
[emit]
|
|
28627
|
+
);
|
|
28628
|
+
const presetButtons = React93.useMemo(
|
|
28629
|
+
() => presets.map((preset) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
28630
|
+
Button,
|
|
28631
|
+
{
|
|
28632
|
+
variant: activePreset === preset.value ? "primary" : "ghost",
|
|
28633
|
+
size: "sm",
|
|
28634
|
+
onClick: () => handlePreset(preset),
|
|
28635
|
+
children: preset.label
|
|
28636
|
+
},
|
|
28637
|
+
preset.value
|
|
28638
|
+
)),
|
|
28639
|
+
[presets, activePreset, handlePreset]
|
|
28640
|
+
);
|
|
28641
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "sm", className: cn(className), children: [
|
|
28642
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "md", align: "end", children: [
|
|
28643
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
28644
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: fromLabel }),
|
|
28645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28646
|
+
Input,
|
|
28647
|
+
{
|
|
28648
|
+
type: "date",
|
|
28649
|
+
value: from,
|
|
28650
|
+
onChange: (e) => handleFromChange(e.target.value)
|
|
28651
|
+
}
|
|
28652
|
+
)
|
|
28653
|
+
] }),
|
|
28654
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", children: [
|
|
28655
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: toLabel }),
|
|
28656
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
28657
|
+
Input,
|
|
28658
|
+
{
|
|
28659
|
+
type: "date",
|
|
28660
|
+
value: to,
|
|
28661
|
+
onChange: (e) => handleToChange(e.target.value)
|
|
28662
|
+
}
|
|
28663
|
+
)
|
|
28664
|
+
] })
|
|
28665
|
+
] }),
|
|
28666
|
+
presets.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(HStack, { gap: "xs", wrap: true, children: presetButtons })
|
|
28667
|
+
] });
|
|
28668
|
+
};
|
|
28669
|
+
DateRangePicker.displayName = "DateRangePicker";
|
|
28670
|
+
}
|
|
28671
|
+
});
|
|
28042
28672
|
var DEFAULT_OPTIONS, DateRangeSelector;
|
|
28043
28673
|
var init_DateRangeSelector = __esm({
|
|
28044
28674
|
"components/molecules/DateRangeSelector.tsx"() {
|
|
@@ -31010,7 +31640,9 @@ var init_StatDisplay = __esm({
|
|
|
31010
31640
|
init_Typography();
|
|
31011
31641
|
init_Box();
|
|
31012
31642
|
init_Stack();
|
|
31643
|
+
init_Sparkline();
|
|
31013
31644
|
init_Icon();
|
|
31645
|
+
init_useEventBus();
|
|
31014
31646
|
variantColor = {
|
|
31015
31647
|
default: "text-foreground",
|
|
31016
31648
|
primary: "text-primary",
|
|
@@ -31025,6 +31657,10 @@ var init_StatDisplay = __esm({
|
|
|
31025
31657
|
max,
|
|
31026
31658
|
target,
|
|
31027
31659
|
trend,
|
|
31660
|
+
trendPolarity = "higher-is-better",
|
|
31661
|
+
trendFormat = "absolute",
|
|
31662
|
+
sparklineData,
|
|
31663
|
+
clickEvent,
|
|
31028
31664
|
prefix,
|
|
31029
31665
|
suffix,
|
|
31030
31666
|
icon: iconProp,
|
|
@@ -31038,6 +31674,10 @@ var init_StatDisplay = __esm({
|
|
|
31038
31674
|
isLoading = false,
|
|
31039
31675
|
error = null
|
|
31040
31676
|
}) => {
|
|
31677
|
+
const eventBus = useEventBus();
|
|
31678
|
+
const handleClick = React93.useCallback(() => {
|
|
31679
|
+
if (clickEvent) eventBus.emit(`UI:${clickEvent}`, { metricLabel: label });
|
|
31680
|
+
}, [clickEvent, eventBus, label]);
|
|
31041
31681
|
const ResolvedIcon = typeof iconProp === "string" ? resolveIcon(iconProp) : null;
|
|
31042
31682
|
const iconSizes3 = { sm: "h-4 w-4", md: "h-5 w-5", lg: "h-6 w-6" };
|
|
31043
31683
|
const valueSizes = { sm: "text-lg", md: "text-2xl", lg: "text-3xl" };
|
|
@@ -31048,7 +31688,10 @@ var init_StatDisplay = __esm({
|
|
|
31048
31688
|
const targetPct = showTarget ? Math.max(0, Math.min(100, numericValue / target * 100)) : 0;
|
|
31049
31689
|
const showTrend = typeof trend === "number" && trend !== 0 && Number.isFinite(trend);
|
|
31050
31690
|
const trendUp = showTrend && trend > 0;
|
|
31051
|
-
const
|
|
31691
|
+
const trendIsGood = trendPolarity === "lower-is-better" ? !trendUp : trendUp;
|
|
31692
|
+
const trendMagnitude = Math.abs(trend);
|
|
31693
|
+
const trendSuffix = trendFormat === "percent" ? "%" : "";
|
|
31694
|
+
const trendLabel = showTrend ? `${trendUp ? "\u2191" : "\u2193"} ${trendMagnitude}${trendSuffix}` : "";
|
|
31052
31695
|
if (error) {
|
|
31053
31696
|
return /* @__PURE__ */ jsxRuntime.jsx(Card, { className: cn(padSizes[size], className), children: /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", color: "error", children: error.message }) });
|
|
31054
31697
|
}
|
|
@@ -31059,38 +31702,57 @@ var init_StatDisplay = __esm({
|
|
|
31059
31702
|
] }) });
|
|
31060
31703
|
}
|
|
31061
31704
|
if (compact) {
|
|
31062
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
31063
|
-
|
|
31064
|
-
|
|
31065
|
-
|
|
31066
|
-
|
|
31067
|
-
|
|
31068
|
-
|
|
31705
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
31706
|
+
HStack,
|
|
31707
|
+
{
|
|
31708
|
+
gap: "sm",
|
|
31709
|
+
className: cn("items-center", clickEvent && "cursor-pointer hover:opacity-80", className),
|
|
31710
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31711
|
+
children: [
|
|
31712
|
+
ResolvedIcon && /* @__PURE__ */ jsxRuntime.jsx(ResolvedIcon, { className: cn(iconSizes3[size], iconColor) }),
|
|
31713
|
+
typeof iconProp !== "string" && iconProp,
|
|
31714
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", color: "secondary", children: label }),
|
|
31715
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31716
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "caption", className: cn("font-semibold", trendIsGood ? "text-success" : "text-error"), children: trendLabel }),
|
|
31717
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto", width: 60, height: 20 })
|
|
31718
|
+
]
|
|
31719
|
+
}
|
|
31720
|
+
);
|
|
31069
31721
|
}
|
|
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
|
-
|
|
31722
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
31723
|
+
Card,
|
|
31724
|
+
{
|
|
31725
|
+
className: cn(padSizes[size], clickEvent && "cursor-pointer hover:shadow-md transition-shadow", className),
|
|
31726
|
+
onClick: clickEvent ? handleClick : void 0,
|
|
31727
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(HStack, { align: "start", justify: "between", children: [
|
|
31728
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "none", className: "space-y-1 flex-1", children: [
|
|
31729
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "overline", color: "secondary", children: label }),
|
|
31730
|
+
/* @__PURE__ */ jsxRuntime.jsxs(HStack, { gap: "sm", align: "end", children: [
|
|
31731
|
+
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "h4", className: cn("font-bold", valueSizes[size], variantColor[variant]), children: displayValue }),
|
|
31732
|
+
showTrend && /* @__PURE__ */ jsxRuntime.jsx(
|
|
31733
|
+
Typography,
|
|
31734
|
+
{
|
|
31735
|
+
variant: "caption",
|
|
31736
|
+
className: cn("font-semibold pb-1", trendIsGood ? "text-success" : "text-error"),
|
|
31737
|
+
children: trendLabel
|
|
31738
|
+
}
|
|
31739
|
+
)
|
|
31740
|
+
] }),
|
|
31741
|
+
showTarget && /* @__PURE__ */ jsxRuntime.jsx(Box, { className: "mt-2 h-1.5 w-full bg-muted rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
31742
|
+
Box,
|
|
31743
|
+
{
|
|
31744
|
+
className: cn("h-full rounded-full transition-all", `bg-${variant === "default" ? "primary" : variant}`),
|
|
31745
|
+
style: { width: `${targetPct}%` }
|
|
31746
|
+
}
|
|
31747
|
+
) })
|
|
31748
|
+
] }),
|
|
31749
|
+
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
31750
|
+
(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 }),
|
|
31751
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
31752
|
+
] })
|
|
31753
|
+
] })
|
|
31754
|
+
}
|
|
31755
|
+
);
|
|
31094
31756
|
};
|
|
31095
31757
|
StatDisplay.displayName = "StatDisplay";
|
|
31096
31758
|
}
|
|
@@ -45169,6 +45831,7 @@ var init_StatCard = __esm({
|
|
|
45169
45831
|
init_Box();
|
|
45170
45832
|
init_Stack();
|
|
45171
45833
|
init_Button();
|
|
45834
|
+
init_Sparkline();
|
|
45172
45835
|
init_useEventBus();
|
|
45173
45836
|
init_useTranslate();
|
|
45174
45837
|
init_Icon();
|
|
@@ -45338,32 +46001,7 @@ var init_StatCard = __esm({
|
|
|
45338
46001
|
] }),
|
|
45339
46002
|
/* @__PURE__ */ jsxRuntime.jsxs(VStack, { gap: "xs", align: "end", children: [
|
|
45340
46003
|
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
|
-
})()
|
|
46004
|
+
sparklineData && sparklineData.length > 1 && /* @__PURE__ */ jsxRuntime.jsx(Sparkline, { data: sparklineData, color: "auto" })
|
|
45367
46005
|
] })
|
|
45368
46006
|
] }),
|
|
45369
46007
|
action && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -52733,6 +53371,7 @@ var init_component_registry_generated = __esm({
|
|
|
52733
53371
|
init_DataGrid();
|
|
52734
53372
|
init_DataList();
|
|
52735
53373
|
init_DataTable();
|
|
53374
|
+
init_DateRangePicker();
|
|
52736
53375
|
init_DateRangeSelector();
|
|
52737
53376
|
init_DayCell();
|
|
52738
53377
|
init_DebuggerBoard();
|
|
@@ -52865,6 +53504,7 @@ var init_component_registry_generated = __esm({
|
|
|
52865
53504
|
init_Skeleton();
|
|
52866
53505
|
init_SocialProof();
|
|
52867
53506
|
init_SortableList();
|
|
53507
|
+
init_Sparkline();
|
|
52868
53508
|
init_Split();
|
|
52869
53509
|
init_SplitPane();
|
|
52870
53510
|
init_SplitSection();
|
|
@@ -53013,6 +53653,7 @@ var init_component_registry_generated = __esm({
|
|
|
53013
53653
|
"DataGrid": DataGrid,
|
|
53014
53654
|
"DataList": DataList,
|
|
53015
53655
|
"DataTable": DataTable,
|
|
53656
|
+
"DateRangePicker": DateRangePicker,
|
|
53016
53657
|
"DateRangeSelector": DateRangeSelector,
|
|
53017
53658
|
"DayCell": DayCell,
|
|
53018
53659
|
"DebuggerBoard": DebuggerBoard,
|
|
@@ -53174,6 +53815,7 @@ var init_component_registry_generated = __esm({
|
|
|
53174
53815
|
"SortableList": SortableList,
|
|
53175
53816
|
"Spacer": SpacerPattern,
|
|
53176
53817
|
"SpacerPattern": SpacerPattern,
|
|
53818
|
+
"Sparkline": Sparkline,
|
|
53177
53819
|
"Spinner": SpinnerPattern,
|
|
53178
53820
|
"SpinnerPattern": SpinnerPattern,
|
|
53179
53821
|
"Split": Split,
|
|
@@ -60480,8 +61122,19 @@ function OrbInspector({ node, schema, editable = false, userType = "builder", th
|
|
|
60480
61122
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "text-muted-foreground text-[10px] uppercase tracking-wider mb-2", children: t("Props") }),
|
|
60481
61123
|
/* @__PURE__ */ jsxRuntime.jsx(Box, { className: "flex flex-col gap-1.5", children: Object.entries(patternDef.propsSchema).slice(0, 12).map(([propName, propSchema]) => {
|
|
60482
61124
|
const ps = propSchema;
|
|
60483
|
-
const
|
|
61125
|
+
const explicitValue = patternConfig ? patternConfig[propName] : void 0;
|
|
61126
|
+
const defaultValue = ps.default;
|
|
61127
|
+
const isImplicit = explicitValue === void 0 && defaultValue !== void 0;
|
|
61128
|
+
const currentValue = explicitValue !== void 0 ? explicitValue : defaultValue;
|
|
60484
61129
|
const displayValue = currentValue !== void 0 ? typeof currentValue === "object" ? JSON.stringify(currentValue) : String(currentValue) : "";
|
|
61130
|
+
inspectorLog.debug("prop-row", () => ({
|
|
61131
|
+
patternType: patternDef.type,
|
|
61132
|
+
patternId: selectedPattern?.patternId ?? "",
|
|
61133
|
+
propName,
|
|
61134
|
+
explicitValue: explicitValue === void 0 ? "<unset>" : JSON.stringify(explicitValue),
|
|
61135
|
+
defaultValue: defaultValue === void 0 ? "<unset>" : JSON.stringify(defaultValue),
|
|
61136
|
+
isImplicit: String(isImplicit)
|
|
61137
|
+
}));
|
|
60485
61138
|
return /* @__PURE__ */ jsxRuntime.jsxs(Box, { className: "flex items-center gap-2", children: [
|
|
60486
61139
|
/* @__PURE__ */ jsxRuntime.jsx(Typography, { variant: "small", className: "text-muted-foreground text-[11px] w-20 shrink-0 font-mono", children: propName }),
|
|
60487
61140
|
editable ? /* @__PURE__ */ jsxRuntime.jsx(
|