@anuma/sdk 11.2.0 → 11.3.0
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/react/index.cjs +169 -154
- package/dist/react/index.mjs +169 -154
- package/dist/tools/index.cjs +157 -0
- package/dist/tools/index.d.mts +41 -1
- package/dist/tools/index.d.ts +41 -1
- package/dist/tools/index.mjs +154 -0
- package/package.json +1 -1
package/dist/react/index.mjs
CHANGED
|
@@ -34529,6 +34529,159 @@ import {
|
|
|
34529
34529
|
XAxis,
|
|
34530
34530
|
YAxis
|
|
34531
34531
|
} from "recharts";
|
|
34532
|
+
|
|
34533
|
+
// src/tools/chartModel.ts
|
|
34534
|
+
var DOT_LIMIT = 12;
|
|
34535
|
+
var MAX_TICKS = 8;
|
|
34536
|
+
var MINUS = "\u2212";
|
|
34537
|
+
function chartCellText(value) {
|
|
34538
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : "";
|
|
34539
|
+
}
|
|
34540
|
+
function tickDigits(ticks) {
|
|
34541
|
+
if (!ticks || ticks.length < 2) return 3;
|
|
34542
|
+
const step = ticks[1] - ticks[0];
|
|
34543
|
+
const magnitude = Math.max(...ticks.map(Math.abs));
|
|
34544
|
+
if (step <= 0 || magnitude === 0) return 3;
|
|
34545
|
+
const needed = Math.floor(Math.log10(magnitude)) - Math.floor(Math.log10(step)) + 1;
|
|
34546
|
+
return Math.min(21, Math.max(3, needed));
|
|
34547
|
+
}
|
|
34548
|
+
function keepSmall(options) {
|
|
34549
|
+
const small = new Intl.NumberFormat(void 0, { ...options, maximumSignificantDigits: 3 });
|
|
34550
|
+
const regular = new Intl.NumberFormat(void 0, { ...options, maximumFractionDigits: 2 });
|
|
34551
|
+
return (n, format) => format(n !== 0 && Math.abs(n) < 1 ? small : regular, n);
|
|
34552
|
+
}
|
|
34553
|
+
function buildFormatters(format, currency, ticks) {
|
|
34554
|
+
const digits = tickDigits(ticks);
|
|
34555
|
+
if (format === "currency") {
|
|
34556
|
+
const money = (options) => new Intl.NumberFormat(void 0, {
|
|
34557
|
+
style: "currency",
|
|
34558
|
+
currency: currency ?? "USD",
|
|
34559
|
+
...options
|
|
34560
|
+
});
|
|
34561
|
+
const compact2 = money({ notation: "compact", maximumSignificantDigits: 3 });
|
|
34562
|
+
const tick2 = money({ notation: "compact", maximumSignificantDigits: digits });
|
|
34563
|
+
const small2 = money({ maximumSignificantDigits: 4 });
|
|
34564
|
+
const cents = money({ minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
34565
|
+
const value2 = (n) => Math.abs(n) >= 1e6 ? compact2.format(n) : n !== 0 && Math.abs(n) < 1 ? small2.format(n) : cents.format(n);
|
|
34566
|
+
return { tick: (n) => tick2.format(n), value: value2, change: (d) => value2(Math.abs(d)) };
|
|
34567
|
+
}
|
|
34568
|
+
if (format === "percent") {
|
|
34569
|
+
const percent = keepSmall({ style: "percent" });
|
|
34570
|
+
const points = keepSmall({});
|
|
34571
|
+
const tick2 = new Intl.NumberFormat(void 0, {
|
|
34572
|
+
style: "percent",
|
|
34573
|
+
maximumSignificantDigits: digits
|
|
34574
|
+
});
|
|
34575
|
+
return {
|
|
34576
|
+
tick: (n) => tick2.format(n / 100),
|
|
34577
|
+
value: (n) => percent(n, (formatter) => formatter.format(n / 100)),
|
|
34578
|
+
change: (d) => `${points(Math.abs(d), (formatter, n) => formatter.format(n))} pts`
|
|
34579
|
+
};
|
|
34580
|
+
}
|
|
34581
|
+
const tick = new Intl.NumberFormat(void 0, {
|
|
34582
|
+
notation: "compact",
|
|
34583
|
+
maximumSignificantDigits: digits
|
|
34584
|
+
});
|
|
34585
|
+
const compact = new Intl.NumberFormat(void 0, {
|
|
34586
|
+
notation: "compact",
|
|
34587
|
+
maximumSignificantDigits: 3
|
|
34588
|
+
});
|
|
34589
|
+
const small = new Intl.NumberFormat(void 0, { maximumSignificantDigits: 4 });
|
|
34590
|
+
const plain2 = new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 });
|
|
34591
|
+
const value = (n) => Math.abs(n) >= 1e6 ? compact.format(n) : n !== 0 && Math.abs(n) < 1 ? small.format(n) : plain2.format(n);
|
|
34592
|
+
return { tick: (n) => tick.format(n), value, change: (d) => value(Math.abs(d)) };
|
|
34593
|
+
}
|
|
34594
|
+
function seriesValues(points, keys) {
|
|
34595
|
+
return points.flatMap(
|
|
34596
|
+
(point) => keys.map((key3) => point[key3]).filter((v) => typeof v === "number")
|
|
34597
|
+
);
|
|
34598
|
+
}
|
|
34599
|
+
function niceStep(rough) {
|
|
34600
|
+
const exponent = Math.floor(Math.log10(rough));
|
|
34601
|
+
const base = 10 ** exponent;
|
|
34602
|
+
const fraction = rough / base;
|
|
34603
|
+
const nice = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;
|
|
34604
|
+
return nice * base;
|
|
34605
|
+
}
|
|
34606
|
+
function niceTicks(values) {
|
|
34607
|
+
if (values.length === 0) return void 0;
|
|
34608
|
+
const min = Math.min(...values);
|
|
34609
|
+
const max = Math.max(...values);
|
|
34610
|
+
const span = max - min || Math.abs(max) * 0.02 || 1;
|
|
34611
|
+
const low = min - span * 0.1;
|
|
34612
|
+
const high = max + span * 0.1;
|
|
34613
|
+
const step = niceStep((high - low) / 3);
|
|
34614
|
+
const start = min >= 0 ? Math.max(0, Math.floor(low / step) * step) : Math.floor(low / step) * step;
|
|
34615
|
+
const ticks = [];
|
|
34616
|
+
for (let index = 0; index <= MAX_TICKS; index++) {
|
|
34617
|
+
const tick = Number((start + index * step).toPrecision(15));
|
|
34618
|
+
if (ticks.length > 0 && tick <= ticks[ticks.length - 1]) break;
|
|
34619
|
+
ticks.push(tick);
|
|
34620
|
+
if (tick >= high) break;
|
|
34621
|
+
}
|
|
34622
|
+
return ticks.length >= 2 ? ticks : void 0;
|
|
34623
|
+
}
|
|
34624
|
+
function buildTrend(values, format, formatters) {
|
|
34625
|
+
if (values.length < 2) return void 0;
|
|
34626
|
+
const first = values[0];
|
|
34627
|
+
const last = values[values.length - 1];
|
|
34628
|
+
const difference = last - first;
|
|
34629
|
+
const direction = difference > 0 ? "up" : difference < 0 ? "down" : "flat";
|
|
34630
|
+
const sign = direction === "up" ? "+" : direction === "down" ? MINUS : "";
|
|
34631
|
+
const percent = format !== "percent" && first !== 0 ? ` (${sign}${new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 }).format(
|
|
34632
|
+
Math.abs(difference / Math.abs(first) * 100)
|
|
34633
|
+
)}%)` : "";
|
|
34634
|
+
return {
|
|
34635
|
+
value: formatters.value(last),
|
|
34636
|
+
change: `${sign}${formatters.change(difference)}${percent}`,
|
|
34637
|
+
direction
|
|
34638
|
+
};
|
|
34639
|
+
}
|
|
34640
|
+
function lastValueIndex(points, key3) {
|
|
34641
|
+
for (let index = points.length - 1; index >= 0; index--) {
|
|
34642
|
+
if (typeof points[index][key3] === "number") return index;
|
|
34643
|
+
}
|
|
34644
|
+
return -1;
|
|
34645
|
+
}
|
|
34646
|
+
function chartSeriesLabel(key3) {
|
|
34647
|
+
return key3.charAt(0).toUpperCase() + key3.slice(1);
|
|
34648
|
+
}
|
|
34649
|
+
function buildChartModel(spec) {
|
|
34650
|
+
const { chartType, title, data, dataKeys, xAxisKey, valueFormat, currency } = spec;
|
|
34651
|
+
const isTrendChart = chartType === "line" || chartType === "area";
|
|
34652
|
+
const plottedKeys = chartType === "pie" ? dataKeys.slice(0, 1) : dataKeys;
|
|
34653
|
+
const values = seriesValues(data, plottedKeys);
|
|
34654
|
+
const yTicks = isTrendChart ? niceTicks(values) : void 0;
|
|
34655
|
+
const yDomain = yTicks ? [yTicks[0], yTicks[yTicks.length - 1]] : void 0;
|
|
34656
|
+
const formatters = buildFormatters(valueFormat, currency, yTicks);
|
|
34657
|
+
const seriesLabels = Object.fromEntries(dataKeys.map((key3) => [key3, chartSeriesLabel(key3)]));
|
|
34658
|
+
const trendBase = isTrendChart && dataKeys.length === 1 ? buildTrend(values, valueFormat, formatters) : void 0;
|
|
34659
|
+
const trendRows = trendBase ? data.filter((point) => typeof point[dataKeys[0]] === "number") : [];
|
|
34660
|
+
const range = trendBase && xAxisKey ? [trendRows[0], trendRows[trendRows.length - 1]].map((point) => chartCellText(point[xAxisKey])).filter(Boolean).join(" \u2013 ") || void 0 : void 0;
|
|
34661
|
+
const trend = trendBase ? { ...trendBase, range } : void 0;
|
|
34662
|
+
const tickSamples = [...yDomain ?? [], ...values].map((value) => formatters.tick(value));
|
|
34663
|
+
const showDots = data.length <= DOT_LIMIT;
|
|
34664
|
+
return {
|
|
34665
|
+
isTrendChart,
|
|
34666
|
+
plottedKeys,
|
|
34667
|
+
seriesLabels,
|
|
34668
|
+
labelKey: chartType === "pie" ? xAxisKey || "name" : xAxisKey,
|
|
34669
|
+
values,
|
|
34670
|
+
yTicks,
|
|
34671
|
+
yDomain,
|
|
34672
|
+
formatters,
|
|
34673
|
+
trend,
|
|
34674
|
+
title: title ?? (trend ? seriesLabels[dataKeys[0]] : void 0),
|
|
34675
|
+
showDots,
|
|
34676
|
+
endIndexes: Object.fromEntries(plottedKeys.map((key3) => [key3, lastValueIndex(data, key3)])),
|
|
34677
|
+
curve: showDots ? "linear" : "monotone",
|
|
34678
|
+
hasNegative: values.some((value) => value < 0),
|
|
34679
|
+
longestTickLength: tickSamples.reduce((max, label) => Math.max(max, label.length), 0),
|
|
34680
|
+
total: values.reduce((sum, value) => sum + value, 0)
|
|
34681
|
+
};
|
|
34682
|
+
}
|
|
34683
|
+
|
|
34684
|
+
// src/react/chart.tsx
|
|
34532
34685
|
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
34533
34686
|
function cx(...classes) {
|
|
34534
34687
|
return classes.filter(Boolean).join(" ");
|
|
@@ -34725,7 +34878,7 @@ function ChartLegendContent({
|
|
|
34725
34878
|
style: { backgroundColor: item.color }
|
|
34726
34879
|
}
|
|
34727
34880
|
),
|
|
34728
|
-
itemConfig?.label ??
|
|
34881
|
+
itemConfig?.label ?? chartCellText(item.value)
|
|
34729
34882
|
]
|
|
34730
34883
|
},
|
|
34731
34884
|
String(item.value)
|
|
@@ -34753,15 +34906,9 @@ var DEFAULT_COLORS = [
|
|
|
34753
34906
|
"var(--chart-5)"
|
|
34754
34907
|
];
|
|
34755
34908
|
var SURFACE = "var(--chart-surface)";
|
|
34756
|
-
var DOT_LIMIT = 12;
|
|
34757
|
-
var MAX_TICKS = 8;
|
|
34758
|
-
var MINUS = "\u2212";
|
|
34759
34909
|
function paletteColor(index) {
|
|
34760
34910
|
return index < DEFAULT_COLORS.length ? DEFAULT_COLORS[index] : `hsl(${Math.round(index * 137.508 % 360)} 65% 55%)`;
|
|
34761
34911
|
}
|
|
34762
|
-
function cellText(value) {
|
|
34763
|
-
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : "";
|
|
34764
|
-
}
|
|
34765
34912
|
var VISUALLY_HIDDEN = {
|
|
34766
34913
|
position: "absolute",
|
|
34767
34914
|
width: 1,
|
|
@@ -34773,107 +34920,17 @@ var VISUALLY_HIDDEN = {
|
|
|
34773
34920
|
whiteSpace: "nowrap",
|
|
34774
34921
|
border: 0
|
|
34775
34922
|
};
|
|
34776
|
-
function
|
|
34777
|
-
if (!ticks || ticks.length < 2) return 3;
|
|
34778
|
-
const step = ticks[1] - ticks[0];
|
|
34779
|
-
const magnitude = Math.max(...ticks.map(Math.abs));
|
|
34780
|
-
if (step <= 0 || magnitude === 0) return 3;
|
|
34781
|
-
const needed = Math.floor(Math.log10(magnitude)) - Math.floor(Math.log10(step)) + 1;
|
|
34782
|
-
return Math.min(21, Math.max(3, needed));
|
|
34783
|
-
}
|
|
34784
|
-
function keepSmall(options) {
|
|
34785
|
-
const small = new Intl.NumberFormat(void 0, { ...options, maximumSignificantDigits: 3 });
|
|
34786
|
-
const regular = new Intl.NumberFormat(void 0, { ...options, maximumFractionDigits: 2 });
|
|
34787
|
-
return (n, format) => format(n !== 0 && Math.abs(n) < 1 ? small : regular, n);
|
|
34788
|
-
}
|
|
34789
|
-
function buildFormatters(format, currency, ticks) {
|
|
34790
|
-
const digits = tickDigits(ticks);
|
|
34791
|
-
if (format === "currency") {
|
|
34792
|
-
const money = (options) => new Intl.NumberFormat(void 0, {
|
|
34793
|
-
style: "currency",
|
|
34794
|
-
currency: currency ?? "USD",
|
|
34795
|
-
...options
|
|
34796
|
-
});
|
|
34797
|
-
const compact2 = money({ notation: "compact", maximumSignificantDigits: 3 });
|
|
34798
|
-
const tick2 = money({ notation: "compact", maximumSignificantDigits: digits });
|
|
34799
|
-
const small2 = money({ maximumSignificantDigits: 4 });
|
|
34800
|
-
const cents = money({ minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
34801
|
-
const value2 = (n) => Math.abs(n) >= 1e6 ? compact2.format(n) : n !== 0 && Math.abs(n) < 1 ? small2.format(n) : cents.format(n);
|
|
34802
|
-
return { tick: (n) => tick2.format(n), value: value2, change: (d) => value2(Math.abs(d)) };
|
|
34803
|
-
}
|
|
34804
|
-
if (format === "percent") {
|
|
34805
|
-
const percent = keepSmall({ style: "percent" });
|
|
34806
|
-
const points = keepSmall({});
|
|
34807
|
-
const tick2 = new Intl.NumberFormat(void 0, {
|
|
34808
|
-
style: "percent",
|
|
34809
|
-
maximumSignificantDigits: digits
|
|
34810
|
-
});
|
|
34811
|
-
return {
|
|
34812
|
-
tick: (n) => tick2.format(n / 100),
|
|
34813
|
-
value: (n) => percent(n, (formatter) => formatter.format(n / 100)),
|
|
34814
|
-
change: (d) => `${points(Math.abs(d), (formatter, n) => formatter.format(n))} pts`
|
|
34815
|
-
};
|
|
34816
|
-
}
|
|
34817
|
-
const tick = new Intl.NumberFormat(void 0, {
|
|
34818
|
-
notation: "compact",
|
|
34819
|
-
maximumSignificantDigits: digits
|
|
34820
|
-
});
|
|
34821
|
-
const compact = new Intl.NumberFormat(void 0, {
|
|
34822
|
-
notation: "compact",
|
|
34823
|
-
maximumSignificantDigits: 3
|
|
34824
|
-
});
|
|
34825
|
-
const small = new Intl.NumberFormat(void 0, { maximumSignificantDigits: 4 });
|
|
34826
|
-
const plain2 = new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 });
|
|
34827
|
-
const value = (n) => Math.abs(n) >= 1e6 ? compact.format(n) : n !== 0 && Math.abs(n) < 1 ? small.format(n) : plain2.format(n);
|
|
34828
|
-
return { tick: (n) => tick.format(n), value, change: (d) => value(Math.abs(d)) };
|
|
34829
|
-
}
|
|
34830
|
-
function seriesValues(points, keys) {
|
|
34831
|
-
return points.flatMap(
|
|
34832
|
-
(point) => keys.map((key3) => point[key3]).filter((v) => typeof v === "number")
|
|
34833
|
-
);
|
|
34834
|
-
}
|
|
34835
|
-
function niceStep(rough) {
|
|
34836
|
-
const exponent = Math.floor(Math.log10(rough));
|
|
34837
|
-
const base = 10 ** exponent;
|
|
34838
|
-
const fraction = rough / base;
|
|
34839
|
-
const nice = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;
|
|
34840
|
-
return nice * base;
|
|
34841
|
-
}
|
|
34842
|
-
function niceTicks(values) {
|
|
34843
|
-
if (values.length === 0) return void 0;
|
|
34844
|
-
const min = Math.min(...values);
|
|
34845
|
-
const max = Math.max(...values);
|
|
34846
|
-
const span = max - min || Math.abs(max) * 0.02 || 1;
|
|
34847
|
-
const low = min - span * 0.1;
|
|
34848
|
-
const high = max + span * 0.1;
|
|
34849
|
-
const step = niceStep((high - low) / 3);
|
|
34850
|
-
const start = min >= 0 ? Math.max(0, Math.floor(low / step) * step) : Math.floor(low / step) * step;
|
|
34851
|
-
const ticks = [];
|
|
34852
|
-
for (let index = 0; index <= MAX_TICKS; index++) {
|
|
34853
|
-
const tick = Number((start + index * step).toPrecision(15));
|
|
34854
|
-
if (ticks.length > 0 && tick <= ticks[ticks.length - 1]) break;
|
|
34855
|
-
ticks.push(tick);
|
|
34856
|
-
if (tick >= high) break;
|
|
34857
|
-
}
|
|
34858
|
-
return ticks.length >= 2 ? ticks : void 0;
|
|
34859
|
-
}
|
|
34860
|
-
function buildChartConfig(dataKeys, colors) {
|
|
34923
|
+
function buildChartConfig(dataKeys, labels, colors) {
|
|
34861
34924
|
const config = {};
|
|
34862
34925
|
dataKeys.forEach((key3, i) => {
|
|
34863
34926
|
const custom = colors?.[key3];
|
|
34864
34927
|
config[key3] = {
|
|
34865
|
-
label: key3
|
|
34928
|
+
label: labels[key3],
|
|
34866
34929
|
color: isSafeCssColor(custom) ? custom : paletteColor(i)
|
|
34867
34930
|
};
|
|
34868
34931
|
});
|
|
34869
34932
|
return config;
|
|
34870
34933
|
}
|
|
34871
|
-
function lastValueIndex(points, key3) {
|
|
34872
|
-
for (let index = points.length - 1; index >= 0; index--) {
|
|
34873
|
-
if (typeof points[index][key3] === "number") return index;
|
|
34874
|
-
}
|
|
34875
|
-
return -1;
|
|
34876
|
-
}
|
|
34877
34934
|
function usePrefersReducedMotion() {
|
|
34878
34935
|
const [reduced, setReduced] = React2.useState(false);
|
|
34879
34936
|
React2.useEffect(() => {
|
|
@@ -34886,33 +34943,13 @@ function usePrefersReducedMotion() {
|
|
|
34886
34943
|
}, []);
|
|
34887
34944
|
return reduced;
|
|
34888
34945
|
}
|
|
34889
|
-
function buildTrend(values, format, formatters) {
|
|
34890
|
-
if (values.length < 2) return void 0;
|
|
34891
|
-
const first = values[0];
|
|
34892
|
-
const last = values[values.length - 1];
|
|
34893
|
-
const difference = last - first;
|
|
34894
|
-
const direction = difference > 0 ? "up" : difference < 0 ? "down" : "flat";
|
|
34895
|
-
const sign = direction === "up" ? "+" : direction === "down" ? MINUS : "";
|
|
34896
|
-
const percent = format !== "percent" && first !== 0 ? ` (${sign}${new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 }).format(
|
|
34897
|
-
Math.abs(difference / Math.abs(first) * 100)
|
|
34898
|
-
)}%)` : "";
|
|
34899
|
-
return {
|
|
34900
|
-
value: formatters.value(last),
|
|
34901
|
-
change: `${sign}${formatters.change(difference)}${percent}`,
|
|
34902
|
-
direction
|
|
34903
|
-
};
|
|
34904
|
-
}
|
|
34905
34946
|
var TREND_CLASS = {
|
|
34906
34947
|
up: "text-emerald-600 dark:text-emerald-400",
|
|
34907
34948
|
down: "text-red-600 dark:text-red-400",
|
|
34908
34949
|
flat: "text-muted-foreground"
|
|
34909
34950
|
};
|
|
34910
34951
|
var TREND_ARROW = { up: "\u25B2", down: "\u25BC", flat: "" };
|
|
34911
|
-
function ChartHeader({
|
|
34912
|
-
title,
|
|
34913
|
-
trend,
|
|
34914
|
-
range
|
|
34915
|
-
}) {
|
|
34952
|
+
function ChartHeader({ title, trend }) {
|
|
34916
34953
|
if (!trend) {
|
|
34917
34954
|
return title ? /* @__PURE__ */ jsx2("p", { className: "mb-3 text-sm font-medium", children: title }) : null;
|
|
34918
34955
|
}
|
|
@@ -34924,7 +34961,7 @@ function ChartHeader({
|
|
|
34924
34961
|
TREND_ARROW[trend.direction] && /* @__PURE__ */ jsx2("span", { "aria-hidden": "true", className: "mr-1 text-[0.6rem]", children: TREND_ARROW[trend.direction] }),
|
|
34925
34962
|
trend.change
|
|
34926
34963
|
] }),
|
|
34927
|
-
range && /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: range })
|
|
34964
|
+
trend.range && /* @__PURE__ */ jsx2("span", { className: "text-muted-foreground", children: trend.range })
|
|
34928
34965
|
] })
|
|
34929
34966
|
] });
|
|
34930
34967
|
}
|
|
@@ -34940,34 +34977,13 @@ function ChartCard({ data }) {
|
|
|
34940
34977
|
if ("error" in data) {
|
|
34941
34978
|
return /* @__PURE__ */ jsx2("div", { className: "my-4 max-w-lg", children: /* @__PURE__ */ jsx2("div", { className: "rounded-xl bg-sidebar dark:bg-card px-4 py-3", children: /* @__PURE__ */ jsx2("p", { className: "text-sm text-muted-foreground", children: "Couldn't display this chart." }) }) });
|
|
34942
34979
|
}
|
|
34943
|
-
const {
|
|
34944
|
-
|
|
34945
|
-
|
|
34946
|
-
|
|
34947
|
-
dataKeys,
|
|
34948
|
-
xAxisKey,
|
|
34949
|
-
colors,
|
|
34950
|
-
valueFormat,
|
|
34951
|
-
currency
|
|
34952
|
-
} = data;
|
|
34953
|
-
const chartConfig = buildChartConfig(dataKeys, colors);
|
|
34980
|
+
const { chartType, title, data: chartData, dataKeys, xAxisKey, colors } = data;
|
|
34981
|
+
const model = buildChartModel(data);
|
|
34982
|
+
const { plottedKeys, yTicks, yDomain, formatters, trend, isTrendChart } = model;
|
|
34983
|
+
const chartConfig = buildChartConfig(dataKeys, model.seriesLabels, colors);
|
|
34954
34984
|
const seriesColor = (key3) => chartConfig[key3]?.color;
|
|
34955
|
-
const isTrendChart = chartType === "line" || chartType === "area";
|
|
34956
|
-
const plottedKeys = chartType === "pie" ? dataKeys.slice(0, 1) : dataKeys;
|
|
34957
|
-
const values = seriesValues(chartData, plottedKeys);
|
|
34958
|
-
const yTicks = isTrendChart ? niceTicks(values) : void 0;
|
|
34959
|
-
const yDomain = yTicks ? [yTicks[0], yTicks[yTicks.length - 1]] : void 0;
|
|
34960
|
-
const formatters = buildFormatters(valueFormat, currency, yTicks);
|
|
34961
|
-
const trend = isTrendChart && dataKeys.length === 1 ? buildTrend(values, valueFormat, formatters) : void 0;
|
|
34962
|
-
const trendRows = trend ? chartData.filter((point) => typeof point[dataKeys[0]] === "number") : [];
|
|
34963
|
-
const range = trend && xAxisKey ? [trendRows[0], trendRows[trendRows.length - 1]].map((point) => cellText(point[xAxisKey])).filter(Boolean).join(" \u2013 ") : void 0;
|
|
34964
|
-
const headerTitle = title ?? (trend ? chartConfig[dataKeys[0]]?.label : void 0);
|
|
34965
|
-
const tickSamples = [...yDomain ?? [], ...values].map((value) => formatters.tick(value));
|
|
34966
|
-
const longestTick = tickSamples.reduce((max, label) => Math.max(max, label.length), 0);
|
|
34967
34985
|
const animate = !reducedMotion;
|
|
34968
|
-
const showDots
|
|
34969
|
-
const curve = showDots ? "linear" : "monotone";
|
|
34970
|
-
const hasNegative = values.some((value) => value < 0);
|
|
34986
|
+
const { showDots, curve, hasNegative, endIndexes } = model;
|
|
34971
34987
|
const margin = { top: 8, right: 8, bottom: 0, left: 0 };
|
|
34972
34988
|
const xAxis = xAxisKey && /* @__PURE__ */ jsx2(
|
|
34973
34989
|
XAxis,
|
|
@@ -34992,7 +35008,7 @@ function ChartCard({ data }) {
|
|
|
34992
35008
|
tickFormatter: formatters.tick,
|
|
34993
35009
|
domain: yDomain,
|
|
34994
35010
|
allowDataOverflow: false,
|
|
34995
|
-
width: Math.min(120, Math.max(36,
|
|
35011
|
+
width: Math.min(120, Math.max(36, model.longestTickLength * 7 + 12))
|
|
34996
35012
|
}
|
|
34997
35013
|
);
|
|
34998
35014
|
const tooltip = /* @__PURE__ */ jsx2(
|
|
@@ -35015,9 +35031,8 @@ function ChartCard({ data }) {
|
|
|
35015
35031
|
stroke: SURFACE,
|
|
35016
35032
|
strokeWidth: 2
|
|
35017
35033
|
});
|
|
35018
|
-
const lineDot = (key3) => showDots ? marker(key3, 4) : (props) => props.index ===
|
|
35019
|
-
const
|
|
35020
|
-
const tableColumns = labelKey ? [labelKey, ...plottedKeys] : plottedKeys;
|
|
35034
|
+
const lineDot = (key3) => showDots ? marker(key3, 4) : (props) => props.index === endIndexes[key3] && typeof props.cx === "number" && typeof props.cy === "number" ? /* @__PURE__ */ jsx2("circle", { cx: props.cx, cy: props.cy, ...marker(key3, 4) }, `end-${key3}`) : /* @__PURE__ */ jsx2("g", {}, `dot-${key3}-${props.index}`);
|
|
35035
|
+
const tableColumns = model.labelKey ? [model.labelKey, ...plottedKeys] : plottedKeys;
|
|
35021
35036
|
return /* @__PURE__ */ jsx2(
|
|
35022
35037
|
"div",
|
|
35023
35038
|
{
|
|
@@ -35026,10 +35041,10 @@ function ChartCard({ data }) {
|
|
|
35026
35041
|
role: "figure",
|
|
35027
35042
|
"aria-label": [title, `${chartType} chart`].filter(Boolean).join(", "),
|
|
35028
35043
|
children: /* @__PURE__ */ jsxs("div", { className: "rounded-xl bg-sidebar dark:bg-card px-5 py-4 [--chart-surface:var(--sidebar)] dark:[--chart-surface:var(--card)]", children: [
|
|
35029
|
-
/* @__PURE__ */ jsx2(ChartHeader, { title:
|
|
35044
|
+
/* @__PURE__ */ jsx2(ChartHeader, { title: model.title, trend }),
|
|
35030
35045
|
/* @__PURE__ */ jsxs("table", { style: VISUALLY_HIDDEN, children: [
|
|
35031
35046
|
/* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsx2("tr", { children: tableColumns.map((column) => /* @__PURE__ */ jsx2("th", { scope: "col", children: column }, column)) }) }),
|
|
35032
|
-
/* @__PURE__ */ jsx2("tbody", { children: chartData.map((point, row) => /* @__PURE__ */ jsx2("tr", { children: tableColumns.map((column) => /* @__PURE__ */ jsx2("td", { children:
|
|
35047
|
+
/* @__PURE__ */ jsx2("tbody", { children: chartData.map((point, row) => /* @__PURE__ */ jsx2("tr", { children: tableColumns.map((column) => /* @__PURE__ */ jsx2("td", { children: chartCellText(point[column]) }, column)) }, row)) })
|
|
35033
35048
|
] }),
|
|
35034
35049
|
ready ? /* @__PURE__ */ jsx2(
|
|
35035
35050
|
ChartContainer,
|
|
@@ -35145,7 +35160,7 @@ function ChartCard({ data }) {
|
|
|
35145
35160
|
x: box.cx,
|
|
35146
35161
|
y: box.cy - 6,
|
|
35147
35162
|
className: "fill-foreground text-lg font-semibold",
|
|
35148
|
-
children: formatters.value(
|
|
35163
|
+
children: formatters.value(model.total)
|
|
35149
35164
|
}
|
|
35150
35165
|
),
|
|
35151
35166
|
/* @__PURE__ */ jsx2("tspan", { x: box.cx, y: box.cy + 14, className: "fill-muted-foreground", children: "Total" })
|
package/dist/tools/index.cjs
CHANGED
|
@@ -74,11 +74,14 @@ __export(index_exports, {
|
|
|
74
74
|
auditDesign: () => auditDesign,
|
|
75
75
|
buildAppFileManifest: () => buildAppFileManifest,
|
|
76
76
|
buildAppSystemPrompt: () => buildAppSystemPrompt,
|
|
77
|
+
buildChartModel: () => buildChartModel,
|
|
77
78
|
buildConnectorErrorResult: () => buildConnectorErrorResult,
|
|
78
79
|
buildDocumentSystemPrompt: () => buildDocumentSystemPrompt,
|
|
79
80
|
buildFontsUrl: () => buildFontsUrl,
|
|
80
81
|
buildSlideSystemPrompt: () => buildSlideSystemPrompt,
|
|
81
82
|
callNotionMCPTool: () => callNotionMCPTool,
|
|
83
|
+
chartCellText: () => chartCellText,
|
|
84
|
+
chartSeriesLabel: () => chartSeriesLabel,
|
|
82
85
|
connectorMintErrorToToolResult: () => connectorMintErrorToToolResult,
|
|
83
86
|
convertLegacyDeckJson: () => convertLegacyDeckJson,
|
|
84
87
|
createAgentresClient: () => createAgentresClient,
|
|
@@ -2658,6 +2661,157 @@ function createChartTool(options) {
|
|
|
2658
2661
|
});
|
|
2659
2662
|
}
|
|
2660
2663
|
|
|
2664
|
+
// src/tools/chartModel.ts
|
|
2665
|
+
var DOT_LIMIT = 12;
|
|
2666
|
+
var MAX_TICKS = 8;
|
|
2667
|
+
var MINUS = "\u2212";
|
|
2668
|
+
function chartCellText(value) {
|
|
2669
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? String(value) : "";
|
|
2670
|
+
}
|
|
2671
|
+
function tickDigits(ticks) {
|
|
2672
|
+
if (!ticks || ticks.length < 2) return 3;
|
|
2673
|
+
const step = ticks[1] - ticks[0];
|
|
2674
|
+
const magnitude = Math.max(...ticks.map(Math.abs));
|
|
2675
|
+
if (step <= 0 || magnitude === 0) return 3;
|
|
2676
|
+
const needed = Math.floor(Math.log10(magnitude)) - Math.floor(Math.log10(step)) + 1;
|
|
2677
|
+
return Math.min(21, Math.max(3, needed));
|
|
2678
|
+
}
|
|
2679
|
+
function keepSmall(options) {
|
|
2680
|
+
const small = new Intl.NumberFormat(void 0, { ...options, maximumSignificantDigits: 3 });
|
|
2681
|
+
const regular = new Intl.NumberFormat(void 0, { ...options, maximumFractionDigits: 2 });
|
|
2682
|
+
return (n, format) => format(n !== 0 && Math.abs(n) < 1 ? small : regular, n);
|
|
2683
|
+
}
|
|
2684
|
+
function buildFormatters(format, currency, ticks) {
|
|
2685
|
+
const digits = tickDigits(ticks);
|
|
2686
|
+
if (format === "currency") {
|
|
2687
|
+
const money = (options) => new Intl.NumberFormat(void 0, {
|
|
2688
|
+
style: "currency",
|
|
2689
|
+
currency: currency ?? "USD",
|
|
2690
|
+
...options
|
|
2691
|
+
});
|
|
2692
|
+
const compact2 = money({ notation: "compact", maximumSignificantDigits: 3 });
|
|
2693
|
+
const tick2 = money({ notation: "compact", maximumSignificantDigits: digits });
|
|
2694
|
+
const small2 = money({ maximumSignificantDigits: 4 });
|
|
2695
|
+
const cents = money({ minimumFractionDigits: 2, maximumFractionDigits: 2 });
|
|
2696
|
+
const value2 = (n) => Math.abs(n) >= 1e6 ? compact2.format(n) : n !== 0 && Math.abs(n) < 1 ? small2.format(n) : cents.format(n);
|
|
2697
|
+
return { tick: (n) => tick2.format(n), value: value2, change: (d) => value2(Math.abs(d)) };
|
|
2698
|
+
}
|
|
2699
|
+
if (format === "percent") {
|
|
2700
|
+
const percent = keepSmall({ style: "percent" });
|
|
2701
|
+
const points = keepSmall({});
|
|
2702
|
+
const tick2 = new Intl.NumberFormat(void 0, {
|
|
2703
|
+
style: "percent",
|
|
2704
|
+
maximumSignificantDigits: digits
|
|
2705
|
+
});
|
|
2706
|
+
return {
|
|
2707
|
+
tick: (n) => tick2.format(n / 100),
|
|
2708
|
+
value: (n) => percent(n, (formatter) => formatter.format(n / 100)),
|
|
2709
|
+
change: (d) => `${points(Math.abs(d), (formatter, n) => formatter.format(n))} pts`
|
|
2710
|
+
};
|
|
2711
|
+
}
|
|
2712
|
+
const tick = new Intl.NumberFormat(void 0, {
|
|
2713
|
+
notation: "compact",
|
|
2714
|
+
maximumSignificantDigits: digits
|
|
2715
|
+
});
|
|
2716
|
+
const compact = new Intl.NumberFormat(void 0, {
|
|
2717
|
+
notation: "compact",
|
|
2718
|
+
maximumSignificantDigits: 3
|
|
2719
|
+
});
|
|
2720
|
+
const small = new Intl.NumberFormat(void 0, { maximumSignificantDigits: 4 });
|
|
2721
|
+
const plain = new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 });
|
|
2722
|
+
const value = (n) => Math.abs(n) >= 1e6 ? compact.format(n) : n !== 0 && Math.abs(n) < 1 ? small.format(n) : plain.format(n);
|
|
2723
|
+
return { tick: (n) => tick.format(n), value, change: (d) => value(Math.abs(d)) };
|
|
2724
|
+
}
|
|
2725
|
+
function seriesValues(points, keys) {
|
|
2726
|
+
return points.flatMap(
|
|
2727
|
+
(point) => keys.map((key) => point[key]).filter((v) => typeof v === "number")
|
|
2728
|
+
);
|
|
2729
|
+
}
|
|
2730
|
+
function niceStep(rough) {
|
|
2731
|
+
const exponent = Math.floor(Math.log10(rough));
|
|
2732
|
+
const base = 10 ** exponent;
|
|
2733
|
+
const fraction = rough / base;
|
|
2734
|
+
const nice = fraction <= 1 ? 1 : fraction <= 2 ? 2 : fraction <= 2.5 ? 2.5 : fraction <= 5 ? 5 : 10;
|
|
2735
|
+
return nice * base;
|
|
2736
|
+
}
|
|
2737
|
+
function niceTicks(values) {
|
|
2738
|
+
if (values.length === 0) return void 0;
|
|
2739
|
+
const min = Math.min(...values);
|
|
2740
|
+
const max = Math.max(...values);
|
|
2741
|
+
const span = max - min || Math.abs(max) * 0.02 || 1;
|
|
2742
|
+
const low = min - span * 0.1;
|
|
2743
|
+
const high = max + span * 0.1;
|
|
2744
|
+
const step = niceStep((high - low) / 3);
|
|
2745
|
+
const start = min >= 0 ? Math.max(0, Math.floor(low / step) * step) : Math.floor(low / step) * step;
|
|
2746
|
+
const ticks = [];
|
|
2747
|
+
for (let index = 0; index <= MAX_TICKS; index++) {
|
|
2748
|
+
const tick = Number((start + index * step).toPrecision(15));
|
|
2749
|
+
if (ticks.length > 0 && tick <= ticks[ticks.length - 1]) break;
|
|
2750
|
+
ticks.push(tick);
|
|
2751
|
+
if (tick >= high) break;
|
|
2752
|
+
}
|
|
2753
|
+
return ticks.length >= 2 ? ticks : void 0;
|
|
2754
|
+
}
|
|
2755
|
+
function buildTrend(values, format, formatters) {
|
|
2756
|
+
if (values.length < 2) return void 0;
|
|
2757
|
+
const first = values[0];
|
|
2758
|
+
const last = values[values.length - 1];
|
|
2759
|
+
const difference = last - first;
|
|
2760
|
+
const direction = difference > 0 ? "up" : difference < 0 ? "down" : "flat";
|
|
2761
|
+
const sign = direction === "up" ? "+" : direction === "down" ? MINUS : "";
|
|
2762
|
+
const percent = format !== "percent" && first !== 0 ? ` (${sign}${new Intl.NumberFormat(void 0, { maximumFractionDigits: 2 }).format(
|
|
2763
|
+
Math.abs(difference / Math.abs(first) * 100)
|
|
2764
|
+
)}%)` : "";
|
|
2765
|
+
return {
|
|
2766
|
+
value: formatters.value(last),
|
|
2767
|
+
change: `${sign}${formatters.change(difference)}${percent}`,
|
|
2768
|
+
direction
|
|
2769
|
+
};
|
|
2770
|
+
}
|
|
2771
|
+
function lastValueIndex(points, key) {
|
|
2772
|
+
for (let index = points.length - 1; index >= 0; index--) {
|
|
2773
|
+
if (typeof points[index][key] === "number") return index;
|
|
2774
|
+
}
|
|
2775
|
+
return -1;
|
|
2776
|
+
}
|
|
2777
|
+
function chartSeriesLabel(key) {
|
|
2778
|
+
return key.charAt(0).toUpperCase() + key.slice(1);
|
|
2779
|
+
}
|
|
2780
|
+
function buildChartModel(spec) {
|
|
2781
|
+
const { chartType, title, data, dataKeys, xAxisKey, valueFormat, currency } = spec;
|
|
2782
|
+
const isTrendChart = chartType === "line" || chartType === "area";
|
|
2783
|
+
const plottedKeys = chartType === "pie" ? dataKeys.slice(0, 1) : dataKeys;
|
|
2784
|
+
const values = seriesValues(data, plottedKeys);
|
|
2785
|
+
const yTicks = isTrendChart ? niceTicks(values) : void 0;
|
|
2786
|
+
const yDomain = yTicks ? [yTicks[0], yTicks[yTicks.length - 1]] : void 0;
|
|
2787
|
+
const formatters = buildFormatters(valueFormat, currency, yTicks);
|
|
2788
|
+
const seriesLabels = Object.fromEntries(dataKeys.map((key) => [key, chartSeriesLabel(key)]));
|
|
2789
|
+
const trendBase = isTrendChart && dataKeys.length === 1 ? buildTrend(values, valueFormat, formatters) : void 0;
|
|
2790
|
+
const trendRows = trendBase ? data.filter((point) => typeof point[dataKeys[0]] === "number") : [];
|
|
2791
|
+
const range = trendBase && xAxisKey ? [trendRows[0], trendRows[trendRows.length - 1]].map((point) => chartCellText(point[xAxisKey])).filter(Boolean).join(" \u2013 ") || void 0 : void 0;
|
|
2792
|
+
const trend = trendBase ? { ...trendBase, range } : void 0;
|
|
2793
|
+
const tickSamples = [...yDomain ?? [], ...values].map((value) => formatters.tick(value));
|
|
2794
|
+
const showDots = data.length <= DOT_LIMIT;
|
|
2795
|
+
return {
|
|
2796
|
+
isTrendChart,
|
|
2797
|
+
plottedKeys,
|
|
2798
|
+
seriesLabels,
|
|
2799
|
+
labelKey: chartType === "pie" ? xAxisKey || "name" : xAxisKey,
|
|
2800
|
+
values,
|
|
2801
|
+
yTicks,
|
|
2802
|
+
yDomain,
|
|
2803
|
+
formatters,
|
|
2804
|
+
trend,
|
|
2805
|
+
title: title ?? (trend ? seriesLabels[dataKeys[0]] : void 0),
|
|
2806
|
+
showDots,
|
|
2807
|
+
endIndexes: Object.fromEntries(plottedKeys.map((key) => [key, lastValueIndex(data, key)])),
|
|
2808
|
+
curve: showDots ? "linear" : "monotone",
|
|
2809
|
+
hasNegative: values.some((value) => value < 0),
|
|
2810
|
+
longestTickLength: tickSamples.reduce((max, label) => Math.max(max, label.length), 0),
|
|
2811
|
+
total: values.reduce((sum, value) => sum + value, 0)
|
|
2812
|
+
};
|
|
2813
|
+
}
|
|
2814
|
+
|
|
2661
2815
|
// src/tools/choice.ts
|
|
2662
2816
|
var CHOICE_TOOL_NAME = "prompt_user_choice";
|
|
2663
2817
|
function createChoiceTool(options) {
|
|
@@ -14141,11 +14295,14 @@ function createXTools(callProxy) {
|
|
|
14141
14295
|
auditDesign,
|
|
14142
14296
|
buildAppFileManifest,
|
|
14143
14297
|
buildAppSystemPrompt,
|
|
14298
|
+
buildChartModel,
|
|
14144
14299
|
buildConnectorErrorResult,
|
|
14145
14300
|
buildDocumentSystemPrompt,
|
|
14146
14301
|
buildFontsUrl,
|
|
14147
14302
|
buildSlideSystemPrompt,
|
|
14148
14303
|
callNotionMCPTool,
|
|
14304
|
+
chartCellText,
|
|
14305
|
+
chartSeriesLabel,
|
|
14149
14306
|
connectorMintErrorToToolResult,
|
|
14150
14307
|
convertLegacyDeckJson,
|
|
14151
14308
|
createAgentresClient,
|