@siyahi/ui 0.1.9-next.25 → 0.1.9-next.27
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/agents/examples/chart-area-log.tsx +45 -0
- package/agents/examples/chart-line-log.tsx +39 -0
- package/agents/examples/scatter-chart-quadrants.tsx +4 -4
- package/agents/examples/scatter-chart-scales.tsx +46 -0
- package/agents/examples/scatter-chart.tsx +5 -2
- package/agents/manifest.json +25 -0
- package/dist/components/registry/charts/area-chart-card.d.ts +2 -2
- package/dist/components/registry/charts/area-chart-card.js +1 -0
- package/dist/components/registry/charts/line-chart-card.d.ts +2 -2
- package/dist/components/registry/heatmap/weekday-heatmap.js +5 -10
- package/dist/components/siyahi/drawdown-chart.js +1 -1
- package/dist/components/siyahi/histogram-chart.js +1 -1
- package/dist/components/siyahi/scale-toggle.d.ts +32 -0
- package/dist/components/siyahi/scale-toggle.js +61 -0
- package/dist/components/siyahi/scatter-chart.d.ts +15 -5
- package/dist/components/siyahi/scatter-chart.js +40 -12
- package/dist/index.d.ts +3 -2
- package/dist/index.js +2 -1
- package/dist/lib/chart-frame.d.ts +5 -3
- package/dist/lib/chart-frame.js +24 -7
- package/dist/lib/chart-series.d.ts +12 -0
- package/dist/lib/scatter.d.ts +3 -13
- package/dist/lib/scatter.js +4 -43
- package/dist/lib/ticks.d.ts +27 -0
- package/dist/lib/ticks.js +67 -0
- package/package.json +1 -1
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { AreaChartCard, ToggleGroup, ToggleGroupItem, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Money a new fund manages, month by month from launch, made up for the catalogue: ₹2L to ₹3.1Cr.
|
|
4
|
+
const data = [
|
|
5
|
+
{ month: "Nov", managed: 200000 },
|
|
6
|
+
{ month: "Dec", managed: 450000 },
|
|
7
|
+
{ month: "Jan", managed: 900000 },
|
|
8
|
+
{ month: "Feb", managed: 1600000 },
|
|
9
|
+
{ month: "Mar", managed: 2400000 },
|
|
10
|
+
{ month: "Apr", managed: 3900000 },
|
|
11
|
+
{ month: "May", managed: 5800000 },
|
|
12
|
+
{ month: "Jun", managed: 8200000 },
|
|
13
|
+
{ month: "Jul", managed: 12500000 },
|
|
14
|
+
{ month: "Aug", managed: 17000000 },
|
|
15
|
+
{ month: "Sep", managed: 23500000 },
|
|
16
|
+
{ month: "Oct", managed: 31000000 },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const series: ChartSeries<(typeof data)[number]> = [
|
|
20
|
+
{ key: "managed", label: "Money managed", color: "var(--chart-1)" },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export default function ChartAreaLogExample() {
|
|
24
|
+
const { money, moneyCompact } = useFormat();
|
|
25
|
+
return (
|
|
26
|
+
<AreaChartCard
|
|
27
|
+
title="₹3.1Cr managed a year after launch"
|
|
28
|
+
description="Linear shows the size today; Log shows the early months, when it grew fastest."
|
|
29
|
+
action={
|
|
30
|
+
<ToggleGroup defaultValue={["1Y"]} variant="outline" size="sm" aria-label="Range">
|
|
31
|
+
<ToggleGroupItem value="6M">6M</ToggleGroupItem>
|
|
32
|
+
<ToggleGroupItem value="1Y">1Y</ToggleGroupItem>
|
|
33
|
+
</ToggleGroup>
|
|
34
|
+
}
|
|
35
|
+
data={data}
|
|
36
|
+
xKey="month"
|
|
37
|
+
series={series}
|
|
38
|
+
// Linear is selected first; the buttons after the range toggle let the reader switch to log.
|
|
39
|
+
yScaleToggle
|
|
40
|
+
valueFormatter={money}
|
|
41
|
+
yTickFormatter={moneyCompact}
|
|
42
|
+
height={256}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Badge, LineChartCard, useFormat, type ChartSeries } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// Monthly active users in the app's first year, made up for the catalogue: from a few hundred to tens of thousands.
|
|
4
|
+
const data = [
|
|
5
|
+
{ month: "Nov", users: 240 },
|
|
6
|
+
{ month: "Dec", users: 410 },
|
|
7
|
+
{ month: "Jan", users: 780 },
|
|
8
|
+
{ month: "Feb", users: 1350 },
|
|
9
|
+
{ month: "Mar", users: 2100 },
|
|
10
|
+
{ month: "Apr", users: 3900 },
|
|
11
|
+
{ month: "May", users: 6200 },
|
|
12
|
+
{ month: "Jun", users: 9800 },
|
|
13
|
+
{ month: "Jul", users: 14100 },
|
|
14
|
+
{ month: "Aug", users: 21500 },
|
|
15
|
+
{ month: "Sep", users: 30200 },
|
|
16
|
+
{ month: "Oct", users: 46800 },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
const series: ChartSeries<(typeof data)[number]> = [{ key: "users", label: "Active users", color: "var(--chart-1)" }];
|
|
20
|
+
|
|
21
|
+
export default function ChartLineLogExample() {
|
|
22
|
+
const { count } = useFormat();
|
|
23
|
+
return (
|
|
24
|
+
<LineChartCard
|
|
25
|
+
title="Active users grew about 1.5× a month all year"
|
|
26
|
+
description="On log, steady growth is a straight line; Linear shows how much of it came in the last few months."
|
|
27
|
+
action={<Badge variant="outline">First year</Badge>}
|
|
28
|
+
data={data}
|
|
29
|
+
xKey="month"
|
|
30
|
+
series={series}
|
|
31
|
+
// Log is selected first; the buttons in the header let the reader switch.
|
|
32
|
+
yScale="log"
|
|
33
|
+
yScaleToggle
|
|
34
|
+
yLabel="Active users"
|
|
35
|
+
valueFormatter={count}
|
|
36
|
+
height={256}
|
|
37
|
+
/>
|
|
38
|
+
);
|
|
39
|
+
}
|
|
@@ -52,10 +52,10 @@ export default function ScatterChartQuadrantsExample() {
|
|
|
52
52
|
x: 0,
|
|
53
53
|
y: 0,
|
|
54
54
|
labels: {
|
|
55
|
-
topLeft: "Cheaper,
|
|
56
|
-
topRight: "Dearer, still
|
|
57
|
-
bottomLeft: "Cheaper,
|
|
58
|
-
bottomRight: "Dearer,
|
|
55
|
+
topLeft: "Cheaper, sells more",
|
|
56
|
+
topRight: "Dearer, still sells more",
|
|
57
|
+
bottomLeft: "Cheaper, sells less",
|
|
58
|
+
bottomRight: "Dearer, sells less",
|
|
59
59
|
},
|
|
60
60
|
}}
|
|
61
61
|
/>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { ScatterChartCard, useFormat, type ScatterPoint } from "@siyahi/ui";
|
|
2
|
+
|
|
3
|
+
// A shop's products this month: x is units sold, y the shelf price; made-up figures. Both run from a few to
|
|
4
|
+
// thousands, so both axes open on log. Largest sellers first, so they take the labels.
|
|
5
|
+
const products: ScatterPoint[] = [
|
|
6
|
+
{ name: "Milk 500 ml", x: 38000, y: 32 },
|
|
7
|
+
{ name: "Bread", x: 21000, y: 45 },
|
|
8
|
+
{ name: "Eggs, 6", x: 14500, y: 60 },
|
|
9
|
+
{ name: "Tea 250 g", x: 6200, y: 140 },
|
|
10
|
+
{ name: "Atta 5 kg", x: 4800, y: 260 },
|
|
11
|
+
{ name: "Rice 5 kg", x: 3900, y: 420 },
|
|
12
|
+
{ name: "Oil 1 L", x: 3100, y: 180 },
|
|
13
|
+
{ name: "Ghee 500 ml", x: 1400, y: 340 },
|
|
14
|
+
{ name: "Coffee 200 g", x: 900, y: 480 },
|
|
15
|
+
{ name: "Dry fruit box", x: 260, y: 1200 },
|
|
16
|
+
{ name: "Saffron 1 g", x: 120, y: 350 },
|
|
17
|
+
{ name: "Olive oil 1 L", x: 95, y: 980 },
|
|
18
|
+
{ name: "Gift hamper", x: 40, y: 3500 },
|
|
19
|
+
{ name: "Mixer grinder", x: 18, y: 4200 },
|
|
20
|
+
{ name: "Pressure cooker", x: 25, y: 2100 },
|
|
21
|
+
];
|
|
22
|
+
|
|
23
|
+
export default function ScatterChartScalesExample() {
|
|
24
|
+
const { count, money } = useFormat();
|
|
25
|
+
return (
|
|
26
|
+
<ScatterChartCard
|
|
27
|
+
title="A few cheap products sell most of the units"
|
|
28
|
+
description="Units sold this month against shelf price. Both axes switch: each pair of buttons is named for its axis."
|
|
29
|
+
points={products}
|
|
30
|
+
height={360}
|
|
31
|
+
xLabel="Units sold"
|
|
32
|
+
yLabel="Price"
|
|
33
|
+
xScale="log"
|
|
34
|
+
xScaleToggle
|
|
35
|
+
yScale="log"
|
|
36
|
+
yScaleToggle
|
|
37
|
+
xFormatter={count}
|
|
38
|
+
yFormatter={(value) => money(value)}
|
|
39
|
+
quadrants={{
|
|
40
|
+
x: 1000,
|
|
41
|
+
y: 500,
|
|
42
|
+
labels: { topLeft: "Dear, few sold", bottomRight: "Cheap, many sold" },
|
|
43
|
+
}}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ScatterChartCard, useFormat, type ScatterPoint } from "@siyahi/ui";
|
|
1
|
+
import { Badge, ScatterChartCard, useFormat, type ScatterPoint } from "@siyahi/ui";
|
|
2
2
|
import { useState } from "react";
|
|
3
3
|
|
|
4
4
|
interface Store extends ScatterPoint {
|
|
@@ -40,12 +40,15 @@ export default function ScatterChartExample() {
|
|
|
40
40
|
return (
|
|
41
41
|
<ScatterChartCard
|
|
42
42
|
title="Stores by size and growth"
|
|
43
|
-
description="Across is the store's share of sales
|
|
43
|
+
description="Across is the store's share of sales, up its growth on last year. Log spreads out the small stores; Linear shows how far ahead the largest are."
|
|
44
|
+
action={<Badge variant="outline">This month</Badge>}
|
|
44
45
|
points={stores}
|
|
45
46
|
height={360}
|
|
46
47
|
xLabel="Share of sales"
|
|
47
48
|
yLabel="Growth"
|
|
49
|
+
// Log is selected first; the buttons in the header let the reader switch.
|
|
48
50
|
xScale="log"
|
|
51
|
+
xScaleToggle
|
|
49
52
|
xFormatter={(x) => pct(x)}
|
|
50
53
|
yFormatter={(y) => growth(y)}
|
|
51
54
|
details={(s) => [
|
package/agents/manifest.json
CHANGED
|
@@ -522,6 +522,15 @@
|
|
|
522
522
|
"ChangeGrid"
|
|
523
523
|
]
|
|
524
524
|
},
|
|
525
|
+
{
|
|
526
|
+
"file": "agents/examples/chart-area-log.tsx",
|
|
527
|
+
"components": [
|
|
528
|
+
"AreaChartCard",
|
|
529
|
+
"ToggleGroup",
|
|
530
|
+
"ToggleGroupItem",
|
|
531
|
+
"useFormat"
|
|
532
|
+
]
|
|
533
|
+
},
|
|
525
534
|
{
|
|
526
535
|
"file": "agents/examples/chart-area.tsx",
|
|
527
536
|
"components": [
|
|
@@ -590,6 +599,14 @@
|
|
|
590
599
|
"LineChartCard"
|
|
591
600
|
]
|
|
592
601
|
},
|
|
602
|
+
{
|
|
603
|
+
"file": "agents/examples/chart-line-log.tsx",
|
|
604
|
+
"components": [
|
|
605
|
+
"Badge",
|
|
606
|
+
"LineChartCard",
|
|
607
|
+
"useFormat"
|
|
608
|
+
]
|
|
609
|
+
},
|
|
593
610
|
{
|
|
594
611
|
"file": "agents/examples/chart-line-timeline.tsx",
|
|
595
612
|
"components": [
|
|
@@ -1022,9 +1039,17 @@
|
|
|
1022
1039
|
"useFormat"
|
|
1023
1040
|
]
|
|
1024
1041
|
},
|
|
1042
|
+
{
|
|
1043
|
+
"file": "agents/examples/scatter-chart-scales.tsx",
|
|
1044
|
+
"components": [
|
|
1045
|
+
"ScatterChartCard",
|
|
1046
|
+
"useFormat"
|
|
1047
|
+
]
|
|
1048
|
+
},
|
|
1025
1049
|
{
|
|
1026
1050
|
"file": "agents/examples/scatter-chart.tsx",
|
|
1027
1051
|
"components": [
|
|
1052
|
+
"Badge",
|
|
1028
1053
|
"ScatterChartCard",
|
|
1029
1054
|
"useFormat"
|
|
1030
1055
|
]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-series.js";
|
|
1
|
+
import { ChartCurve, NumericXProps, SeriesChartProps, ValueScaleProps } from "../../../lib/chart-series.js";
|
|
2
2
|
//#region src/components/registry/charts/area-chart-card.d.ts
|
|
3
|
-
export interface AreaChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
|
|
3
|
+
export interface AreaChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps, ValueScaleProps {
|
|
4
4
|
/** Stack the series into a total instead of overlapping them. */
|
|
5
5
|
stacked?: boolean;
|
|
6
6
|
curve?: ChartCurve;
|
|
@@ -9,6 +9,7 @@ function AreaChartCard({ stacked = false, curve = "monotone", ...props }) {
|
|
|
9
9
|
const id = useId();
|
|
10
10
|
return /* @__PURE__ */ jsxs(ChartFrame, {
|
|
11
11
|
chart: AreaChart,
|
|
12
|
+
logBlocked: stacked ? "Log cannot show stacked areas" : void 0,
|
|
12
13
|
...props,
|
|
13
14
|
children: [/* @__PURE__ */ jsx("defs", { children: props.series.map(({ key, color }, index) => /* @__PURE__ */ jsxs("linearGradient", {
|
|
14
15
|
id: `${id}-${index}`,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ChartCurve, NumericXProps, SeriesChartProps } from "../../../lib/chart-series.js";
|
|
1
|
+
import { ChartCurve, NumericXProps, SeriesChartProps, ValueScaleProps } from "../../../lib/chart-series.js";
|
|
2
2
|
//#region src/components/registry/charts/line-chart-card.d.ts
|
|
3
|
-
export interface LineChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps {
|
|
3
|
+
export interface LineChartCardProps<T extends object, K extends keyof T> extends SeriesChartProps<T, K>, NumericXProps, ValueScaleProps {
|
|
4
4
|
curve?: ChartCurve;
|
|
5
5
|
}
|
|
6
6
|
/** Values over an ordered axis as lines: one series, or several to compare, such as sales against a target. */
|
|
@@ -18,13 +18,12 @@ const calculateLevel = (value, minValue, maxValue, levels, isNormalized) => {
|
|
|
18
18
|
const percentage = value / maxValue;
|
|
19
19
|
return Math.max(1, Math.min(steps, Math.ceil(percentage * steps)));
|
|
20
20
|
};
|
|
21
|
-
const getLevelFill = (level, levels, isNormalized,
|
|
21
|
+
const getLevelFill = (level, levels, isNormalized, colors) => {
|
|
22
22
|
const emptyColor = colors?.empty ?? "var(--color-secondary)";
|
|
23
23
|
const scaleColor = colors?.scale ?? "var(--color-chart-1)";
|
|
24
24
|
if (level === 0) return emptyColor;
|
|
25
25
|
const steps = colorStepCount(levels, isNormalized);
|
|
26
|
-
|
|
27
|
-
return `color-mix(in oklch, ${scaleColor} ${highlighted ? Math.round(opacity * .6) : opacity}%, transparent)`;
|
|
26
|
+
return `color-mix(in oklch, ${scaleColor} ${steps === 1 ? 100 : Math.round(20 + (level - 1) * 80 / (steps - 1))}%, transparent)`;
|
|
28
27
|
};
|
|
29
28
|
const DEFAULT_HOUR_LABELS = Array.from({ length: 24 }, (_, i) => i.toString().padStart(2, "0"));
|
|
30
29
|
const TWELVE_HOUR_LABELS = Array.from({ length: 24 }, (_, i) => {
|
|
@@ -259,7 +258,7 @@ const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, select
|
|
|
259
258
|
"aria-pressed": onCellClick ? selected : void 0,
|
|
260
259
|
tabIndex: onCellClick ? 0 : -1,
|
|
261
260
|
"aria-label": ariaLabel,
|
|
262
|
-
className: cn("
|
|
261
|
+
className: cn("hover:stroke-foreground hover:stroke-1", highlighted && "stroke-foreground stroke-1", selected && "stroke-foreground stroke-2 hover:stroke-2", onCellClick && "cursor-pointer focus-visible:outline-none focus-visible:stroke-ring focus-visible:stroke-2", className),
|
|
263
262
|
"data-value": activity.value,
|
|
264
263
|
"data-weekday": isExtraRow ? "extra" : activity.weekday,
|
|
265
264
|
"data-hour": isExtraColumn ? "extra" : activity.hour,
|
|
@@ -273,11 +272,7 @@ const WeekdayHeatmapBlock = ({ ref, activity, extra, highlighted = false, select
|
|
|
273
272
|
x: xPosition,
|
|
274
273
|
y: yPosition,
|
|
275
274
|
style: {
|
|
276
|
-
fill: getLevelFill(level, levels, isNormalized,
|
|
277
|
-
...selected ? {
|
|
278
|
-
stroke: "var(--foreground)",
|
|
279
|
-
strokeWidth: 2
|
|
280
|
-
} : {},
|
|
275
|
+
fill: getLevelFill(level, levels, isNormalized, colors),
|
|
281
276
|
...styleProp
|
|
282
277
|
},
|
|
283
278
|
onClick: (event) => {
|
|
@@ -510,7 +505,7 @@ const WeekdayHeatmapLegend = ({ labels: labelsProp, className, children, ...prop
|
|
|
510
505
|
rx: blockRadius,
|
|
511
506
|
ry: blockRadius,
|
|
512
507
|
width: LEGEND_SWATCH,
|
|
513
|
-
style: { fill: getLevelFill(level, levels, isNormalized,
|
|
508
|
+
style: { fill: getLevelFill(level, levels, isNormalized, colors) }
|
|
514
509
|
})
|
|
515
510
|
}, `legend-level-${level}`)),
|
|
516
511
|
/* @__PURE__ */ jsx("span", {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
+
import { linearTicks } from "../../lib/ticks.js";
|
|
1
2
|
import { ChartFrame } from "../../lib/chart-frame.js";
|
|
2
3
|
import { useFormat } from "../../lib/format.js";
|
|
3
|
-
import { linearTicks } from "../../lib/scatter.js";
|
|
4
4
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { useMemo } from "react";
|
|
6
6
|
import { Area, AreaChart } from "recharts";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useLocale } from "./siyahi-provider.js";
|
|
2
|
+
import { linearTicks } from "../../lib/ticks.js";
|
|
2
3
|
import { ChartFrame } from "../../lib/chart-frame.js";
|
|
3
|
-
import { linearTicks } from "../../lib/scatter.js";
|
|
4
4
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
5
|
import { useMemo } from "react";
|
|
6
6
|
import { Bar, BarChart } from "recharts";
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AxisScale } from "../../lib/ticks.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/components/siyahi/scale-toggle.d.ts
|
|
4
|
+
/** Why Log is disabled when a value is at or below zero. */
|
|
5
|
+
export declare const LOG_BLOCKED = "Log needs every value above zero";
|
|
6
|
+
export interface ScaleToggleProps {
|
|
7
|
+
/** The group's accessible name, such as "Share of book scale". */
|
|
8
|
+
label: string;
|
|
9
|
+
/** The axis' name shown before the buttons, for a card with a toggle on each axis. */
|
|
10
|
+
caption?: string;
|
|
11
|
+
value: AxisScale;
|
|
12
|
+
onValueChange: (scale: AxisScale) => void;
|
|
13
|
+
/** Why log cannot draw this data, such as a value at or below zero: Log is disabled and this shows beside it. */
|
|
14
|
+
logBlocked?: string;
|
|
15
|
+
}
|
|
16
|
+
/** Linear and Log buttons for one chart axis, in the header's toggle style. */
|
|
17
|
+
export declare function ScaleToggle({ label, caption, value, onValueChange, logBlocked }: ScaleToggleProps): import("react").JSX.Element;
|
|
18
|
+
export interface AxisScaleOptions extends Omit<ScaleToggleProps, "value" | "onValueChange"> {
|
|
19
|
+
/** The page's scale: the first selection. */
|
|
20
|
+
initial: AxisScale;
|
|
21
|
+
/** Show the buttons. */
|
|
22
|
+
toggle: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* The scale an axis draws on, and its buttons when `toggle` is set. The page's scale is the first selection; after
|
|
26
|
+
* that the reader's pick holds. Log falls back to linear while `logBlocked` says why it cannot draw the data.
|
|
27
|
+
*/
|
|
28
|
+
export declare function useAxisScale({ initial, toggle, ...buttons }: AxisScaleOptions): {
|
|
29
|
+
scale: AxisScale;
|
|
30
|
+
buttons: ReactNode;
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ToggleGroup, ToggleGroupItem } from "../ui/toggle-group.js";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useId, useState } from "react";
|
|
4
|
+
//#region src/components/siyahi/scale-toggle.tsx
|
|
5
|
+
/** Why Log is disabled when a value is at or below zero. */
|
|
6
|
+
const LOG_BLOCKED = "Log needs every value above zero";
|
|
7
|
+
/** Linear and Log buttons for one chart axis, in the header's toggle style. */
|
|
8
|
+
function ScaleToggle({ label, caption, value, onValueChange, logBlocked }) {
|
|
9
|
+
const reason = useId();
|
|
10
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
11
|
+
"data-slot": "scale-toggle",
|
|
12
|
+
className: "flex flex-wrap items-center gap-x-2 gap-y-1",
|
|
13
|
+
children: [
|
|
14
|
+
caption && /* @__PURE__ */ jsx("span", {
|
|
15
|
+
className: "text-xs text-muted-foreground",
|
|
16
|
+
children: caption
|
|
17
|
+
}),
|
|
18
|
+
/* @__PURE__ */ jsxs(ToggleGroup, {
|
|
19
|
+
value: [value],
|
|
20
|
+
onValueChange: ([next]) => next && onValueChange(next === "log" ? "log" : "linear"),
|
|
21
|
+
variant: "outline",
|
|
22
|
+
size: "sm",
|
|
23
|
+
spacing: 0,
|
|
24
|
+
"aria-label": label,
|
|
25
|
+
"aria-describedby": logBlocked ? reason : void 0,
|
|
26
|
+
children: [/* @__PURE__ */ jsx(ToggleGroupItem, {
|
|
27
|
+
value: "linear",
|
|
28
|
+
children: "Linear"
|
|
29
|
+
}), /* @__PURE__ */ jsx(ToggleGroupItem, {
|
|
30
|
+
value: "log",
|
|
31
|
+
disabled: logBlocked !== void 0,
|
|
32
|
+
children: "Log"
|
|
33
|
+
})]
|
|
34
|
+
}),
|
|
35
|
+
logBlocked && /* @__PURE__ */ jsx("span", {
|
|
36
|
+
id: reason,
|
|
37
|
+
className: "text-xs text-muted-foreground",
|
|
38
|
+
children: logBlocked
|
|
39
|
+
})
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* The scale an axis draws on, and its buttons when `toggle` is set. The page's scale is the first selection; after
|
|
45
|
+
* that the reader's pick holds. Log falls back to linear while `logBlocked` says why it cannot draw the data.
|
|
46
|
+
*/
|
|
47
|
+
function useAxisScale({ initial, toggle, ...buttons }) {
|
|
48
|
+
const [picked, setPicked] = useState(initial);
|
|
49
|
+
const wanted = toggle ? picked : initial;
|
|
50
|
+
const scale = buttons.logBlocked ? "linear" : wanted;
|
|
51
|
+
return {
|
|
52
|
+
scale,
|
|
53
|
+
buttons: toggle ? /* @__PURE__ */ jsx(ScaleToggle, {
|
|
54
|
+
...buttons,
|
|
55
|
+
value: scale,
|
|
56
|
+
onValueChange: setPicked
|
|
57
|
+
}) : null
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
//#endregion
|
|
61
|
+
export { LOG_BLOCKED, ScaleToggle, useAxisScale };
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
+
import { AxisScale } from "../../lib/ticks.js";
|
|
1
2
|
import { ScatterQuadrants } from "../../lib/scatter.js";
|
|
2
3
|
import { ReactNode } from "react";
|
|
3
4
|
//#region src/components/siyahi/scatter-chart.d.ts
|
|
4
5
|
export interface ScatterPoint {
|
|
5
6
|
name: string;
|
|
6
|
-
/** Across.
|
|
7
|
+
/** Across. */
|
|
7
8
|
x: number;
|
|
8
9
|
/** Up. `null` when unknown: the point is not drawn, so say on the page how many are missing. */
|
|
9
10
|
y: number | null;
|
|
@@ -20,7 +21,7 @@ export type ScatterDetail = readonly [label: string, value: string];
|
|
|
20
21
|
export interface ScatterChartCardProps<T extends ScatterPoint> {
|
|
21
22
|
title: ReactNode;
|
|
22
23
|
description?: ReactNode;
|
|
23
|
-
/** A scope badge or a toggle, top right of the card. */
|
|
24
|
+
/** A scope badge or a toggle, top right of the card, before any scale buttons. */
|
|
24
25
|
action?: ReactNode;
|
|
25
26
|
/** Most important first: earlier points take the labels. */
|
|
26
27
|
points: T[];
|
|
@@ -30,8 +31,17 @@ export interface ScatterChartCardProps<T extends ScatterPoint> {
|
|
|
30
31
|
xLabel: string;
|
|
31
32
|
/** What the y axis measures, beside it, such as "Growth on last year". */
|
|
32
33
|
yLabel: string;
|
|
33
|
-
/**
|
|
34
|
-
|
|
34
|
+
/**
|
|
35
|
+
* "log" spreads values across powers of ten, for sizes that run from tiny to large. With xScaleToggle it is the
|
|
36
|
+
* first selection. Log draws only when every x is above zero; otherwise the axis is linear.
|
|
37
|
+
*/
|
|
38
|
+
xScale?: AxisScale;
|
|
39
|
+
/** Linear and Log buttons for the x axis in the header, so a reader can switch. */
|
|
40
|
+
xScaleToggle?: boolean;
|
|
41
|
+
/** As xScale, for the y axis: log draws only when every y is above zero. */
|
|
42
|
+
yScale?: AxisScale;
|
|
43
|
+
/** Linear and Log buttons for the y axis in the header. */
|
|
44
|
+
yScaleToggle?: boolean;
|
|
35
45
|
/** The x ticks and the tooltip's x figure. Defaults to the locale's numbers. */
|
|
36
46
|
xFormatter?: (value: number) => string;
|
|
37
47
|
/** The y ticks and the tooltip's y figure. Defaults to the locale's numbers. */
|
|
@@ -54,6 +64,6 @@ export interface ScatterChartCardProps<T extends ScatterPoint> {
|
|
|
54
64
|
sizeFormatter?: (value: number) => string;
|
|
55
65
|
}
|
|
56
66
|
/** Two measures per item as dots, such as size against growth, with the leading names beside their dots. */
|
|
57
|
-
export declare function ScatterChartCard<T extends ScatterPoint>({ title, description, action, points, height, xLabel, yLabel, xScale, xFormatter, yFormatter, labels, details, selected, onSelect, footer, quadrants, sizeLabel, sizeFormatter }: ScatterChartCardProps<T>): import("react").JSX.Element;
|
|
67
|
+
export declare function ScatterChartCard<T extends ScatterPoint>({ title, description, action, points, height, xLabel, yLabel, xScale, xScaleToggle, yScale, yScaleToggle, xFormatter, yFormatter, labels, details, selected, onSelect, footer, quadrants, sizeLabel, sizeFormatter }: ScatterChartCardProps<T>): import("react").JSX.Element;
|
|
58
68
|
//#endregion
|
|
59
69
|
export type { ScatterQuadrants };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../ui/card.js";
|
|
2
2
|
import { ChartContainer } from "../ui/chart.js";
|
|
3
|
+
import { LOG_BLOCKED, useAxisScale } from "./scale-toggle.js";
|
|
3
4
|
import { useLocale } from "./siyahi-provider.js";
|
|
4
|
-
import {
|
|
5
|
+
import { fitsLog, ticksFor } from "../../lib/ticks.js";
|
|
6
|
+
import { corners, dotSizes, placeLabels, quadrantSplit } from "../../lib/scatter.js";
|
|
5
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
8
|
import { useEffect, useMemo, useRef, useState } from "react";
|
|
7
9
|
import { CartesianGrid, DefaultZIndexes, ReferenceLine, Scatter, ScatterChart, Tooltip, XAxis, YAxis, ZIndexLayer, usePlotArea, useXAxisScale, useYAxisScale } from "recharts";
|
|
@@ -14,8 +16,9 @@ const NAME_BAND = 42;
|
|
|
14
16
|
const TICK = { className: "fill-muted-foreground font-mono" };
|
|
15
17
|
const AXIS_TITLE = "fill-muted-foreground text-xs";
|
|
16
18
|
const keyOf = (point) => point.key ?? point.name;
|
|
19
|
+
const MONO_WIDTH = 7.2;
|
|
17
20
|
/** Two measures per item as dots, such as size against growth, with the leading names beside their dots. */
|
|
18
|
-
function ScatterChartCard({ title, description, action, points, height, xLabel, yLabel, xScale = "linear", xFormatter, yFormatter, labels = 12, details, selected = null, onSelect, footer, quadrants, sizeLabel = "Size", sizeFormatter }) {
|
|
21
|
+
function ScatterChartCard({ title, description, action, points, height, xLabel, yLabel, xScale = "linear", xScaleToggle = false, yScale = "linear", yScaleToggle = false, xFormatter, yFormatter, labels = 12, details, selected = null, onSelect, footer, quadrants, sizeLabel = "Size", sizeFormatter }) {
|
|
19
22
|
const { numberLocale } = useLocale();
|
|
20
23
|
const plotRef = useRef(null);
|
|
21
24
|
const [focusedKey, setFocusedKey] = useState(null);
|
|
@@ -39,18 +42,35 @@ function ScatterChartCard({ title, description, action, points, height, xLabel,
|
|
|
39
42
|
const formatX = useMemo(() => xFormatter ?? new Intl.NumberFormat(numberLocale).format, [xFormatter, numberLocale]);
|
|
40
43
|
const formatY = useMemo(() => yFormatter ?? new Intl.NumberFormat(numberLocale).format, [yFormatter, numberLocale]);
|
|
41
44
|
const formatSize = useMemo(() => sizeFormatter ?? new Intl.NumberFormat(numberLocale).format, [sizeFormatter, numberLocale]);
|
|
42
|
-
const drawn = useMemo(() => points.filter((p) => p.y !== null && Number.isFinite(p.y) && Number.isFinite(p.x)
|
|
45
|
+
const drawn = useMemo(() => points.filter((p) => p.y !== null && Number.isFinite(p.y) && Number.isFinite(p.x)), [points]);
|
|
46
|
+
const both = xScaleToggle && yScaleToggle;
|
|
47
|
+
const across = useAxisScale({
|
|
48
|
+
initial: xScale,
|
|
49
|
+
toggle: xScaleToggle,
|
|
50
|
+
label: `${xLabel} scale`,
|
|
51
|
+
caption: both ? xLabel : void 0,
|
|
52
|
+
logBlocked: fitsLog(drawn.map((p) => p.x)) ? void 0 : LOG_BLOCKED
|
|
53
|
+
});
|
|
54
|
+
const up = useAxisScale({
|
|
55
|
+
initial: yScale,
|
|
56
|
+
toggle: yScaleToggle,
|
|
57
|
+
label: `${yLabel} scale`,
|
|
58
|
+
caption: both ? yLabel : void 0,
|
|
59
|
+
logBlocked: fitsLog(drawn.map((p) => p.y ?? 0)) ? void 0 : LOG_BLOCKED
|
|
60
|
+
});
|
|
43
61
|
const order = useMemo(() => drawn.toSorted((a, b) => a.x - b.x || (a.y ?? 0) - (b.y ?? 0)), [drawn]);
|
|
44
62
|
const { radiusOf, sized } = dotSizes(drawn, RADIUS);
|
|
45
63
|
const painted = sized ? drawn.toSorted((a, b) => radiusOf(b) - radiusOf(a)) : drawn;
|
|
46
|
-
const split = quadrantSplit(quadrants,
|
|
64
|
+
const split = quadrantSplit(quadrants, across.scale, up.scale);
|
|
47
65
|
const xs = [...drawn.map((p) => p.x), ...split ? [split.x] : []];
|
|
48
66
|
const ys = [...drawn.map((p) => p.y ?? 0), ...split ? [split.y] : []];
|
|
49
67
|
const reach = sized ? 23 : 0;
|
|
50
68
|
const names = split?.labels;
|
|
51
69
|
const band = (named) => named ? NAME_BAND + Math.max(reach, 6.5) : reach;
|
|
52
|
-
const xTicks =
|
|
53
|
-
const yTicks =
|
|
70
|
+
const xTicks = ticksFor(across.scale, Math.min(...xs), Math.max(...xs));
|
|
71
|
+
const yTicks = ticksFor(up.scale, Math.min(...ys), Math.max(...ys));
|
|
72
|
+
const lastX = xTicks.at(-1);
|
|
73
|
+
const endRoom = Math.max(16, lastX === void 0 ? 0 : Math.ceil(formatX(lastX).length * MONO_WIDTH / 2) + 4 - reach);
|
|
54
74
|
const crossesZero = ys.some((y) => y < 0) && ys.some((y) => y > 0);
|
|
55
75
|
const selectedKey = selected ? keyOf(selected) : null;
|
|
56
76
|
const rows = details ?? ((p) => [
|
|
@@ -89,7 +109,14 @@ function ScatterChartCard({ title, description, action, points, height, xLabel,
|
|
|
89
109
|
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
90
110
|
/* @__PURE__ */ jsx(CardTitle, { children: title }),
|
|
91
111
|
description && /* @__PURE__ */ jsx(CardDescription, { children: description }),
|
|
92
|
-
action && /* @__PURE__ */
|
|
112
|
+
(action || across.buttons || up.buttons) && /* @__PURE__ */ jsxs(CardAction, {
|
|
113
|
+
className: "flex flex-wrap items-center gap-x-3 gap-y-2",
|
|
114
|
+
children: [
|
|
115
|
+
action,
|
|
116
|
+
across.buttons,
|
|
117
|
+
up.buttons
|
|
118
|
+
]
|
|
119
|
+
})
|
|
93
120
|
] }),
|
|
94
121
|
/* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx("div", {
|
|
95
122
|
ref: plotRef,
|
|
@@ -105,7 +132,7 @@ function ScatterChartCard({ title, description, action, points, height, xLabel,
|
|
|
105
132
|
children: /* @__PURE__ */ jsxs(ScatterChart, {
|
|
106
133
|
margin: {
|
|
107
134
|
top: 12,
|
|
108
|
-
right:
|
|
135
|
+
right: endRoom,
|
|
109
136
|
left: 0
|
|
110
137
|
},
|
|
111
138
|
accessibilityLayer: false,
|
|
@@ -114,10 +141,10 @@ function ScatterChartCard({ title, description, action, points, height, xLabel,
|
|
|
114
141
|
/* @__PURE__ */ jsx(XAxis, {
|
|
115
142
|
type: "number",
|
|
116
143
|
dataKey: "x",
|
|
117
|
-
scale:
|
|
118
|
-
domain: xTicks ? [xTicks[0] ?? "auto", xTicks.at(-1) ?? "auto"] : [(low) => Math.min(low, ...xs), (high) => Math.max(high, ...xs)],
|
|
119
|
-
ticks: xTicks,
|
|
120
|
-
niceTicks: xTicks ? void 0 : "snap125",
|
|
144
|
+
scale: across.scale,
|
|
145
|
+
domain: xTicks.length > 0 ? [xTicks[0] ?? "auto", xTicks.at(-1) ?? "auto"] : [(low) => Math.min(low, ...xs), (high) => Math.max(high, ...xs)],
|
|
146
|
+
ticks: xTicks.length > 0 ? xTicks : void 0,
|
|
147
|
+
niceTicks: xTicks.length > 0 ? void 0 : "snap125",
|
|
121
148
|
padding: reach > 0 ? {
|
|
122
149
|
left: reach,
|
|
123
150
|
right: reach
|
|
@@ -137,6 +164,7 @@ function ScatterChartCard({ title, description, action, points, height, xLabel,
|
|
|
137
164
|
/* @__PURE__ */ jsx(YAxis, {
|
|
138
165
|
type: "number",
|
|
139
166
|
dataKey: "y",
|
|
167
|
+
scale: up.scale,
|
|
140
168
|
domain: [yTicks[0] ?? "auto", yTicks.at(-1) ?? "auto"],
|
|
141
169
|
ticks: yTicks,
|
|
142
170
|
padding: {
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChartColor, ChartCurve, ChartReferenceLine, ChartSeries, ChartSeriesItem, NumericKey, NumericXProps, SeriesChartProps } from "./lib/chart-series.js";
|
|
1
|
+
import { ChartColor, ChartCurve, ChartReferenceLine, ChartSeries, ChartSeriesItem, NumericKey, NumericXProps, SeriesChartProps, ValueScaleProps } from "./lib/chart-series.js";
|
|
2
2
|
import { AreaChartCard, AreaChartCardProps } from "./components/registry/charts/area-chart-card.js";
|
|
3
3
|
import { BarChartCard, BarChartCardProps } from "./components/registry/charts/bar-chart-card.js";
|
|
4
4
|
import { LineChartCard, LineChartCardProps } from "./components/registry/charts/line-chart-card.js";
|
|
@@ -71,6 +71,7 @@ import { PanelGrid, PanelGridProps } from "./components/siyahi/panel-grid.js";
|
|
|
71
71
|
import { PriceChart, PriceChartProps } from "./components/siyahi/price-chart.js";
|
|
72
72
|
import { Quote, QuoteProps } from "./components/siyahi/quote.js";
|
|
73
73
|
import { RangePosition, RangePositionProps } from "./components/siyahi/range-position.js";
|
|
74
|
+
import { AxisScaleOptions, LOG_BLOCKED, ScaleToggle, ScaleToggleProps, useAxisScale } from "./components/siyahi/scale-toggle.js";
|
|
74
75
|
import { ScatterQuadrants } from "./lib/scatter.js";
|
|
75
76
|
import { ScatterChartCard, ScatterChartCardProps, ScatterDetail, ScatterPoint } from "./components/siyahi/scatter-chart.js";
|
|
76
77
|
import { SiyahiLocale, defaultLocale } from "./lib/locale.js";
|
|
@@ -108,4 +109,4 @@ import { Textarea } from "./components/ui/textarea.js";
|
|
|
108
109
|
import { Toggle, toggleVariants } from "./components/ui/toggle.js";
|
|
109
110
|
import { ToggleGroup, ToggleGroupItem } from "./components/ui/toggle-group.js";
|
|
110
111
|
import { Formatters, TimeOptions, count, money, moneyCompact, pct, time, useFormat } from "./lib/format.js";
|
|
111
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActiveCell, ActiveSelection, Activity, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AppSidebarProps, AreaChartCard, AreaChartCardProps, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartCard, BarChartCardProps, BarList, BarListItem, BarListProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBlockProps, CalendarHeatmapBody, CalendarHeatmapBodyProps, CalendarHeatmapFooter, CalendarHeatmapFooterProps, CalendarHeatmapLegend, CalendarHeatmapLegendProps, CalendarHeatmapProps, CalendarHeatmapStat, CalendarHeatmapStatProps, Callout, CalloutProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeBarProps, ChangeGrid, ChangeGridProps, ChangeGridRow, ChartColor, ChartConfig, ChartContainer, ChartCurve, ChartLegend, ChartLegendContent, ChartReferenceLine, ChartSeries, ChartSeriesItem, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorConfig, ColumnResizeInfo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CompactColumns, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataBarProps, DataList, DataListItem, DataListItemProps, DataTable, DataTableActions, DataTableBody, DataTableBodyProps, type DataTableCell, type DataTableColumn, DataTableColumnActions, type DataTableColumnDef, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderProps, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, type DataTableColumns, DataTableCompactColumnsToggle, DataTableConfig, DataTableContainerProps, DataTableContext, DataTableContextState, DataTableEmptyActions, DataTableEmptyActionsProps, DataTableEmptyBody, DataTableEmptyBodyProps, DataTableEmptyDescription, DataTableEmptyDescriptionProps, DataTableEmptyFilteredMessage, DataTableEmptyFilteredMessageProps, DataTableEmptyIcon, DataTableEmptyIconProps, DataTableEmptyMessage, DataTableEmptyMessageProps, DataTableEmptyState, DataTableEmptyStateProps, DataTableEmptyTitle, DataTableEmptyTitleProps, DataTableErrorBoundary, DataTableErrorBoundaryProps, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableFootnoteProps, DataTableGroupRowContextValue, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableGroupedRowsProps, DataTableHeader, type DataTableHeader$1 as DataTableHeaderCell, DataTableHeaderProps, type DataTableInstance, DataTableLoading, DataTableLoadingMore, DataTableLoadingMoreProps, DataTableLoadingProps, DataTableProvider, DataTableRoot, type DataTableRow, DataTableRowContextMenu, DataTableRowContextMenuProps, DataTableRowContextMenuSlot, DataTableRowContextMenuSlotProps, DataTableRowCount, DataTableRowCountProps, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSkeletonProps, DataTableSortHeader, DataTableToolbarSection, DataTableToolbarSectionProps, Delta, DeltaProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DistributionBarProps, DistributionMarker, DistributionSegment, DrawdownChartCard, DrawdownChartCardProps, DrawdownPoint, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type ExtendedColumnFilter, type ExtendedColumnSort, type FilterOperator, type FilterOperatorValues, type FilterVariant, type FilterVariantValues, FlashCellRef, FlashCells, FlashRows, FlashRowsOptions, Formatters, type GlobalFilter, GroupedBodyRow, GroupedBodyRowProps, HistogramBin, HistogramChartCard, HistogramChartCardProps, HistogramMark, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, type JoinOperator, type JoinOperatorValues, Labels, LineChartCard, LineChartCardProps, LocalTime, LocalTimeProps, MetricStrip, MetricStripItem, MetricStripProps, NavMain, NavProjects, NavUser, NumericKey, NumericXProps, type Option, PageHero, PageHeroProps, PageSection, PageSectionProps, PageSubheading, PageToc, PageTocItem, PageTocProps, PanelGrid, PanelGridProps, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, PriceChartProps, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, type QueryKeys, Quote, QuoteProps, RangePosition, RangePositionProps, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScatterChartCard, ScatterChartCardProps, ScatterDetail, ScatterPoint, type ScatterQuadrants, ScrollAlign, ScrollArea, ScrollBar, type ScrollEvent, ScrollRowIntoView, SectionCard, SectionCards, SectionCardsProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SeriesChartProps, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiLocale, SiyahiProvider, SiyahiProviderProps, Skeleton, Slider, SlopeChart, SlopeChartProps, SlopeItem, Sparkline, SparklineProps, StatusActivity, StatusAlert, StatusAlertProps, StatusBadge, StatusBadgeProps, StatusColorConfig, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBlockProps, StatusHeatmapBody, StatusHeatmapBodyProps, StatusHeatmapFooter, StatusHeatmapFooterProps, StatusHeatmapLabels, StatusHeatmapLegend, StatusHeatmapLegendProps, StatusHeatmapProps, StatusHeatmapStat, StatusHeatmapStatProps, StatusValue, Surface, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnActionsProps, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFacetedFilterProps, TableFooter, TableHead, TableHeader, TableRow, TableSearchFilter, TableSearchFilterProps, Tabs, TabsContent, TabsList, TabsTrigger, TargetRow, TargetRows, TargetRowsProps, TargetStatus, TeamSwitcher, Textarea, TimeOptions, Toggle, ToggleGroup, ToggleGroupItem, ToneProgress, ToneProgressProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapItem, TreemapLegend, TreemapLegendProps, TreemapProps, type ValueOf, WaterfallBar, WaterfallChartCard, WaterfallChartCardProps, WaterfallStep, type ColorConfig$1 as WeekdayColorConfig, type WeekdayExtraColumnSpec, type WeekdayExtraRowSpec, WeekdayHeatmap, WeekdayHeatmapBlock, type WeekdayHeatmapBlockProps, WeekdayHeatmapBody, type WeekdayHeatmapBodyProps, WeekdayHeatmapFooter, type WeekdayHeatmapFooterProps, type WeekdayHeatmapLabels, WeekdayHeatmapLegend, type WeekdayHeatmapLegendProps, type WeekdayHeatmapProps, WeekdayHeatmapStat, type WeekdayHeatmapStatProps, type WeekdayHour, type WeekdayHourlyActivity, type WeekdayIndex, badgeVariants, bucketOf, buttonVariants, count, defaultLocale, defaultSidebarOpen, drawdowns, flashCellKey, histogram, markLines, money, moneyCompact, pct, percentile, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, spread, tabsListVariants, time, toggleVariants, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useSurface, useTableFacetedFilter, waterfallBars };
|
|
112
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActiveCell, ActiveSelection, Activity, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AppSidebarProps, AreaChartCard, AreaChartCardProps, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, AxisScaleOptions, Badge, BarChartCard, BarChartCardProps, BarList, BarListItem, BarListProps, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBlockProps, CalendarHeatmapBody, CalendarHeatmapBodyProps, CalendarHeatmapFooter, CalendarHeatmapFooterProps, CalendarHeatmapLegend, CalendarHeatmapLegendProps, CalendarHeatmapProps, CalendarHeatmapStat, CalendarHeatmapStatProps, Callout, CalloutProps, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeBarProps, ChangeGrid, ChangeGridProps, ChangeGridRow, ChartColor, ChartConfig, ChartContainer, ChartCurve, ChartLegend, ChartLegendContent, ChartReferenceLine, ChartSeries, ChartSeriesItem, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, ColorConfig, ColumnResizeInfo, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, CompactColumns, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataBarProps, DataList, DataListItem, DataListItemProps, DataTable, DataTableActions, DataTableBody, DataTableBodyProps, type DataTableCell, type DataTableColumn, DataTableColumnActions, type DataTableColumnDef, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderProps, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, type DataTableColumns, DataTableCompactColumnsToggle, DataTableConfig, DataTableContainerProps, DataTableContext, DataTableContextState, DataTableEmptyActions, DataTableEmptyActionsProps, DataTableEmptyBody, DataTableEmptyBodyProps, DataTableEmptyDescription, DataTableEmptyDescriptionProps, DataTableEmptyFilteredMessage, DataTableEmptyFilteredMessageProps, DataTableEmptyIcon, DataTableEmptyIconProps, DataTableEmptyMessage, DataTableEmptyMessageProps, DataTableEmptyState, DataTableEmptyStateProps, DataTableEmptyTitle, DataTableEmptyTitleProps, DataTableErrorBoundary, DataTableErrorBoundaryProps, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableFootnoteProps, DataTableGroupRowContextValue, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableGroupedRowsProps, DataTableHeader, type DataTableHeader$1 as DataTableHeaderCell, DataTableHeaderProps, type DataTableInstance, DataTableLoading, DataTableLoadingMore, DataTableLoadingMoreProps, DataTableLoadingProps, DataTableProvider, DataTableRoot, type DataTableRow, DataTableRowContextMenu, DataTableRowContextMenuProps, DataTableRowContextMenuSlot, DataTableRowContextMenuSlotProps, DataTableRowCount, DataTableRowCountProps, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSkeletonProps, DataTableSortHeader, DataTableToolbarSection, DataTableToolbarSectionProps, Delta, DeltaProps, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DistributionBarProps, DistributionMarker, DistributionSegment, DrawdownChartCard, DrawdownChartCardProps, DrawdownPoint, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, type ExtendedColumnFilter, type ExtendedColumnSort, type FilterOperator, type FilterOperatorValues, type FilterVariant, type FilterVariantValues, FlashCellRef, FlashCells, FlashRows, FlashRowsOptions, Formatters, type GlobalFilter, GroupedBodyRow, GroupedBodyRowProps, HistogramBin, HistogramChartCard, HistogramChartCardProps, HistogramMark, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, type JoinOperator, type JoinOperatorValues, LOG_BLOCKED, Labels, LineChartCard, LineChartCardProps, LocalTime, LocalTimeProps, MetricStrip, MetricStripItem, MetricStripProps, NavMain, NavProjects, NavUser, NumericKey, NumericXProps, type Option, PageHero, PageHeroProps, PageSection, PageSectionProps, PageSubheading, PageToc, PageTocItem, PageTocProps, PanelGrid, PanelGridProps, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, PriceChartProps, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, type QueryKeys, Quote, QuoteProps, RangePosition, RangePositionProps, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScaleToggle, ScaleToggleProps, ScatterChartCard, ScatterChartCardProps, ScatterDetail, ScatterPoint, type ScatterQuadrants, ScrollAlign, ScrollArea, ScrollBar, type ScrollEvent, ScrollRowIntoView, SectionCard, SectionCards, SectionCardsProps, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, SeriesChartProps, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiLocale, SiyahiProvider, SiyahiProviderProps, Skeleton, Slider, SlopeChart, SlopeChartProps, SlopeItem, Sparkline, SparklineProps, StatusActivity, StatusAlert, StatusAlertProps, StatusBadge, StatusBadgeProps, StatusColorConfig, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBlockProps, StatusHeatmapBody, StatusHeatmapBodyProps, StatusHeatmapFooter, StatusHeatmapFooterProps, StatusHeatmapLabels, StatusHeatmapLegend, StatusHeatmapLegendProps, StatusHeatmapProps, StatusHeatmapStat, StatusHeatmapStatProps, StatusValue, Surface, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnActionsProps, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFacetedFilterProps, TableFooter, TableHead, TableHeader, TableRow, TableSearchFilter, TableSearchFilterProps, Tabs, TabsContent, TabsList, TabsTrigger, TargetRow, TargetRows, TargetRowsProps, TargetStatus, TeamSwitcher, Textarea, TimeOptions, Toggle, ToggleGroup, ToggleGroupItem, ToneProgress, ToneProgressProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapItem, TreemapLegend, TreemapLegendProps, TreemapProps, type ValueOf, ValueScaleProps, WaterfallBar, WaterfallChartCard, WaterfallChartCardProps, WaterfallStep, type ColorConfig$1 as WeekdayColorConfig, type WeekdayExtraColumnSpec, type WeekdayExtraRowSpec, WeekdayHeatmap, WeekdayHeatmapBlock, type WeekdayHeatmapBlockProps, WeekdayHeatmapBody, type WeekdayHeatmapBodyProps, WeekdayHeatmapFooter, type WeekdayHeatmapFooterProps, type WeekdayHeatmapLabels, WeekdayHeatmapLegend, type WeekdayHeatmapLegendProps, type WeekdayHeatmapProps, WeekdayHeatmapStat, type WeekdayHeatmapStatProps, type WeekdayHour, type WeekdayHourlyActivity, type WeekdayIndex, badgeVariants, bucketOf, buttonVariants, count, defaultLocale, defaultSidebarOpen, drawdowns, flashCellKey, histogram, markLines, money, moneyCompact, pct, percentile, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, spread, tabsListVariants, time, toggleVariants, useAxisScale, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useSurface, useTableFacetedFilter, waterfallBars };
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,7 @@ import { Table, TableBody, TableCaption, TableCell, TableFooter, TableHead, Tabl
|
|
|
30
30
|
import { Tabs, TabsContent, TabsList, TabsTrigger, tabsListVariants } from "./components/ui/tabs.js";
|
|
31
31
|
import { Toggle, toggleVariants } from "./components/ui/toggle.js";
|
|
32
32
|
import { ToggleGroup, ToggleGroupItem } from "./components/ui/toggle-group.js";
|
|
33
|
+
import { LOG_BLOCKED, ScaleToggle, useAxisScale } from "./components/siyahi/scale-toggle.js";
|
|
33
34
|
import { defaultLocale } from "./lib/locale.js";
|
|
34
35
|
import { SiyahiProvider, useLocale, useSurface } from "./components/siyahi/siyahi-provider.js";
|
|
35
36
|
import { AreaChartCard } from "./components/registry/charts/area-chart-card.js";
|
|
@@ -104,4 +105,4 @@ import { TargetRows } from "./components/siyahi/target-rows.js";
|
|
|
104
105
|
import { ToneProgress } from "./components/siyahi/tone-progress.js";
|
|
105
106
|
import { Treemap, TreemapLegend } from "./components/siyahi/treemap.js";
|
|
106
107
|
import { WaterfallChartCard, waterfallBars } from "./components/siyahi/waterfall-chart.js";
|
|
107
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AreaChartCard, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartCard, BarList, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBody, CalendarHeatmapFooter, CalendarHeatmapLegend, CalendarHeatmapStat, Callout, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeGrid, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataList, DataListItem, DataTable, DataTableActions, DataTableBody, DataTableColumnActions, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, DataTableCompactColumnsToggle, DataTableContext, DataTableEmptyActions, DataTableEmptyBody, DataTableEmptyDescription, DataTableEmptyFilteredMessage, DataTableEmptyIcon, DataTableEmptyMessage, DataTableEmptyState, DataTableEmptyTitle, DataTableErrorBoundary, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableHeader, DataTableLoading, DataTableLoadingMore, DataTableProvider, DataTableRoot, DataTableRowContextMenu, DataTableRowContextMenuSlot, DataTableRowCount, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSortHeader, DataTableToolbarSection, Delta, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DrawdownChartCard, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, GroupedBodyRow, HistogramChartCard, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, LineChartCard, LocalTime, MetricStrip, NavMain, NavProjects, NavUser, PageHero, PageSection, PageSubheading, PageToc, PanelGrid, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, Quote, RangePosition, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScatterChartCard, ScrollArea, ScrollBar, SectionCards, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiProvider, Skeleton, Slider, SlopeChart, Sparkline, StatusAlert, StatusBadge, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBody, StatusHeatmapFooter, StatusHeatmapLegend, StatusHeatmapStat, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFooter, TableHead, TableHeader, TableRow, TableSearchFilter, Tabs, TabsContent, TabsList, TabsTrigger, TargetRows, TeamSwitcher, Textarea, Toggle, ToggleGroup, ToggleGroupItem, ToneProgress, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapLegend, WaterfallChartCard, WeekdayHeatmap, WeekdayHeatmapBlock, WeekdayHeatmapBody, WeekdayHeatmapFooter, WeekdayHeatmapLegend, WeekdayHeatmapStat, badgeVariants, bucketOf, buttonVariants, count, defaultLocale, defaultSidebarOpen, drawdowns, flashCellKey, histogram, markLines, money, moneyCompact, pct, percentile, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, spread, tabsListVariants, time, toggleVariants, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useSurface, useTableFacetedFilter, waterfallBars };
|
|
108
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, Alert, AlertAction, AlertDescription, AlertTitle, AppSidebar, AreaChartCard, Avatar, AvatarBadge, AvatarFallback, AvatarGroup, AvatarGroupCount, AvatarImage, Badge, BarChartCard, BarList, Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, Button, Calendar, CalendarDayButton, CalendarHeatmap, CalendarHeatmapBlock, CalendarHeatmapBody, CalendarHeatmapFooter, CalendarHeatmapLegend, CalendarHeatmapStat, Callout, Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, ChangeBar, ChangeGrid, ChartContainer, ChartLegend, ChartLegendContent, ChartStyle, ChartTooltip, ChartTooltipContent, CodeBlock, CodeBlockActions, CodeBlockContent, CodeBlockCopyButton, CodeBlockFooter, CodeBlockHeader, CodeBlockLine, CodeBlockTitle, Collapsible, CollapsibleContent, CollapsibleTrigger, Command, CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuPortal, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, CopyButton, DataBar, DataList, DataListItem, DataTable, DataTableActions, DataTableBody, DataTableColumnActions, DataTableColumnFilter, DataTableColumnHeader, DataTableColumnHeaderRoot, DataTableColumnSortMenu, DataTableColumnSortOptions, DataTableColumnTitle, DataTableCompactColumnsToggle, DataTableContext, DataTableEmptyActions, DataTableEmptyBody, DataTableEmptyDescription, DataTableEmptyFilteredMessage, DataTableEmptyIcon, DataTableEmptyMessage, DataTableEmptyState, DataTableEmptyTitle, DataTableErrorBoundary, DataTableFacetedFilter, DataTableFacetedFilterContent, DataTableFootnote, DataTableGroupRowProvider, DataTableGroupedRowCells, DataTableGroupedRows, DataTableHeader, DataTableLoading, DataTableLoadingMore, DataTableProvider, DataTableRoot, DataTableRowContextMenu, DataTableRowContextMenuSlot, DataTableRowCount, DataTableRowMenuScope, DataTableSearchFilter, DataTableSkeleton, DataTableSortHeader, DataTableToolbarSection, Delta, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, DistributionBar, DrawdownChartCard, DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, GroupedBodyRow, HistogramChartCard, InlineCode, Input, InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput, InputGroupText, InputGroupTextarea, LOG_BLOCKED, LineChartCard, LocalTime, MetricStrip, NavMain, NavProjects, NavUser, PageHero, PageSection, PageSubheading, PageToc, PanelGrid, Popover, PopoverContent, PopoverDescription, PopoverHeader, PopoverTitle, PopoverTrigger, PriceChart, Progress, ProgressIndicator, ProgressLabel, ProgressTrack, ProgressValue, Quote, RangePosition, RowMenuGroup, RowMenuItem, RowMenuLabel, RowMenuSeparator, RowMenuSub, RowMenuSubContent, RowMenuSubTrigger, ScaleToggle, ScatterChartCard, ScrollArea, ScrollBar, SectionCards, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, Separator, Sheet, SheetClose, SheetContent, SheetDescription, SheetFooter, SheetHeader, SheetTitle, SheetTrigger, Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupAction, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarInset, SidebarMenu, SidebarMenuAction, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSkeleton, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem, SidebarProvider, SidebarRail, SidebarSeparator, SidebarTrigger, SiyahiProvider, Skeleton, Slider, SlopeChart, Sparkline, StatusAlert, StatusBadge, StatusHeatmap, StatusHeatmapBlock, StatusHeatmapBody, StatusHeatmapFooter, StatusHeatmapLegend, StatusHeatmapStat, Table, TableBody, TableCaption, TableCell, TableColumnActions, TableColumnSortMenu, TableColumnSortOptions, TableColumnTitle, TableFacetedFilter, TableFacetedFilterContent, TableFooter, TableHead, TableHeader, TableRow, TableSearchFilter, Tabs, TabsContent, TabsList, TabsTrigger, TargetRows, TeamSwitcher, Textarea, Toggle, ToggleGroup, ToggleGroupItem, ToneProgress, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, Treemap, TreemapLegend, WaterfallChartCard, WeekdayHeatmap, WeekdayHeatmapBlock, WeekdayHeatmapBody, WeekdayHeatmapFooter, WeekdayHeatmapLegend, WeekdayHeatmapStat, badgeVariants, bucketOf, buttonVariants, count, defaultLocale, defaultSidebarOpen, drawdowns, flashCellKey, histogram, markLines, money, moneyCompact, pct, percentile, resolveGroupedRowsSlot, resolveRowContextMenuRenderer, spread, tabsListVariants, time, toggleVariants, useAxisScale, useColumnHeaderContext, useColumnResizeInfo, useDataTable, useDataTableActiveCell, useDataTableActiveCellSetter, useDataTableGroupRow, useDataTableRow, useFormat, useLocale, useResolvedRowContextMenuRenderer, useSidebar, useSurface, useTableFacetedFilter, waterfallBars };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { ChartColor, ChartSeries, ChartSeriesItem, NumericXProps, SeriesChartProps } from "./chart-series.js";
|
|
1
|
+
import { ChartColor, ChartSeries, ChartSeriesItem, NumericXProps, SeriesChartProps, ValueScaleProps } from "./chart-series.js";
|
|
2
2
|
import { ChartTooltipContent } from "../components/ui/chart.js";
|
|
3
3
|
import { ComponentProps, ReactElement, ReactNode } from "react";
|
|
4
4
|
import { AreaChart, BarChart, LineChart, YAxisProps } from "recharts";
|
|
5
5
|
//#region src/lib/chart-frame.d.ts
|
|
6
|
-
interface ChartFrameProps<T extends object, K extends keyof T> extends Omit<SeriesChartProps<T, K>, "yDomain">, NumericXProps {
|
|
6
|
+
interface ChartFrameProps<T extends object, K extends keyof T> extends Omit<SeriesChartProps<T, K>, "yDomain">, NumericXProps, ValueScaleProps {
|
|
7
7
|
chart: typeof AreaChart | typeof BarChart | typeof LineChart;
|
|
8
8
|
/** The value axis' range: a page's fixed one, or a card's rule such as bars reaching zero. */
|
|
9
9
|
yDomain?: YAxisProps["domain"];
|
|
@@ -22,6 +22,8 @@ interface ChartFrameProps<T extends object, K extends keyof T> extends Omit<Seri
|
|
|
22
22
|
tooltipRow?: ComponentProps<typeof ChartTooltipContent>["formatter"];
|
|
23
23
|
/** The legend under the plot; by default one chip per series. */
|
|
24
24
|
legend?: ReactElement;
|
|
25
|
+
/** Why this chart cannot go on a log scale whatever its values, such as stacked areas adding up from zero. */
|
|
26
|
+
logBlocked?: string;
|
|
25
27
|
}
|
|
26
28
|
/**
|
|
27
29
|
* The colour a series' Bar takes, which its legend chip shows: the negative colour when every value drawn is below
|
|
@@ -47,6 +49,6 @@ export declare function seriesRow<T>(series: ChartSeries<T>, formatValue: (value
|
|
|
47
49
|
* that gave its category axis its own id (dash#88) got a plot split in two
|
|
48
50
|
* and every tooltip headed with the series name instead of the category.
|
|
49
51
|
*/
|
|
50
|
-
export declare function ChartFrame<T extends object, K extends keyof T>({ chart: Chart, children, horizontal, stackOffset, onClick, tooltipRow, legend, title, description, action, data, xKey, series, xFormatter, xTooltipFormatter, valueFormatter, yTickFormatter, yDomain, yTicks, height, xTickDetail, xLabel, yLabel, referenceLines, placeholder, footer, xDomain, xTicks }: ChartFrameProps<T, K>): import("react").JSX.Element;
|
|
52
|
+
export declare function ChartFrame<T extends object, K extends keyof T>({ chart: Chart, children, horizontal, stackOffset, onClick, tooltipRow, legend, title, description, action, data, xKey, series, xFormatter, xTooltipFormatter, valueFormatter, yTickFormatter, yDomain, yTicks, height, xTickDetail, xLabel, yLabel, referenceLines, placeholder, footer, xDomain, xTicks, yScale, yScaleToggle, logBlocked }: ChartFrameProps<T, K>): import("react").JSX.Element;
|
|
51
53
|
//#endregion
|
|
52
54
|
export {};
|
package/dist/lib/chart-frame.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "../components/ui/card.js";
|
|
2
2
|
import { ChartContainer, ChartLegend, ChartLegendContent, ChartTooltip, ChartTooltipContent } from "../components/ui/chart.js";
|
|
3
3
|
import { cn } from "./utils.js";
|
|
4
|
+
import { useAxisScale } from "../components/siyahi/scale-toggle.js";
|
|
4
5
|
import { useLocale } from "../components/siyahi/siyahi-provider.js";
|
|
6
|
+
import { fitsLog, logAxis } from "./ticks.js";
|
|
5
7
|
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
6
8
|
import { useMemo } from "react";
|
|
7
9
|
import { CartesianGrid, ReferenceLine, Text, XAxis, YAxis, useChartWidth, useXAxisTicks, useYAxisTicks } from "recharts";
|
|
@@ -82,11 +84,11 @@ function seriesRow(series, formatValue) {
|
|
|
82
84
|
* never ₹80,000 halfway up. Recharts' tickFormatter sees one value at a time; the axis' ticks come from its hooks.
|
|
83
85
|
* The rest of Recharts' tick props pass on as its own tick does, including the class it measures an auto width by.
|
|
84
86
|
*/
|
|
85
|
-
function ValueTick({ payload, axis, formatter, ...tick }) {
|
|
87
|
+
function ValueTick({ payload, axis, formatter, ownUnit = false, ...tick }) {
|
|
86
88
|
const xTicks = useXAxisTicks();
|
|
87
89
|
const yTicks = useYAxisTicks();
|
|
88
90
|
const value = Number(payload?.value);
|
|
89
|
-
const scale = Math.max(Math.abs(value), ...((axis === "x" ? xTicks : yTicks) ?? []).map((t) => Math.abs(Number(t.value))));
|
|
91
|
+
const scale = ownUnit ? Math.abs(value) : Math.max(Math.abs(value), ...((axis === "x" ? xTicks : yTicks) ?? []).map((t) => Math.abs(Number(t.value))));
|
|
90
92
|
return /* @__PURE__ */ jsx(Text, {
|
|
91
93
|
...tick,
|
|
92
94
|
children: formatter(value, scale)
|
|
@@ -186,7 +188,7 @@ function HorizontalAxis({ data, xKey, xFormatter, xTickDetail, xTicks }) {
|
|
|
186
188
|
* that gave its category axis its own id (dash#88) got a plot split in two
|
|
187
189
|
* and every tooltip headed with the series name instead of the category.
|
|
188
190
|
*/
|
|
189
|
-
function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, onClick, tooltipRow, legend = SERIES_LEGEND, title, description, action, data, xKey, series, xFormatter = String, xTooltipFormatter = xFormatter, valueFormatter, yTickFormatter, yDomain, yTicks, height, xTickDetail, xLabel, yLabel, referenceLines = NO_LINES, placeholder, footer, xDomain, xTicks }) {
|
|
191
|
+
function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, onClick, tooltipRow, legend = SERIES_LEGEND, title, description, action, data, xKey, series, xFormatter = String, xTooltipFormatter = xFormatter, valueFormatter, yTickFormatter, yDomain, yTicks, height, xTickDetail, xLabel, yLabel, referenceLines = NO_LINES, placeholder, footer, xDomain, xTicks, yScale = "linear", yScaleToggle = false, logBlocked }) {
|
|
190
192
|
const { numberLocale } = useLocale();
|
|
191
193
|
const formatValue = useMemo(() => valueFormatter ?? new Intl.NumberFormat(numberLocale).format, [valueFormatter, numberLocale]);
|
|
192
194
|
const config = Object.fromEntries(series.map(({ key, label, color }) => [key, {
|
|
@@ -194,6 +196,16 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
194
196
|
color
|
|
195
197
|
}]));
|
|
196
198
|
const crossesZero = data.some((row) => series.some(({ key }) => Number(row[key]) < 0));
|
|
199
|
+
const [low, high] = Array.isArray(yDomain) ? yDomain : [];
|
|
200
|
+
const range = typeof low === "number" && typeof high === "number" ? [low, high] : void 0;
|
|
201
|
+
const values = [...data.flatMap((row) => series.map(({ key }) => row[key])), ...range ?? []].filter((value) => typeof value === "number" && Number.isFinite(value));
|
|
202
|
+
const valueAxis = useAxisScale({
|
|
203
|
+
initial: yScale,
|
|
204
|
+
toggle: yScaleToggle,
|
|
205
|
+
label: yLabel ? `${yLabel} scale` : "Value axis scale",
|
|
206
|
+
logBlocked: logBlocked ?? (fitsLog(values) ? void 0 : "Log needs every value above zero")
|
|
207
|
+
});
|
|
208
|
+
const log = valueAxis.scale === "log" ? logAxis(values, range) : void 0;
|
|
197
209
|
const detailedRows = horizontal && xTickDetail !== void 0;
|
|
198
210
|
const rowCount = (xTicks ?? data).length;
|
|
199
211
|
const plotClass = detailedRows ? "min-h-(--wrapped-chart-height) @min-[24rem]/chart:min-h-0" : void 0;
|
|
@@ -214,7 +226,10 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
214
226
|
/* @__PURE__ */ jsxs(CardHeader, { children: [
|
|
215
227
|
/* @__PURE__ */ jsx(CardTitle, { children: title }),
|
|
216
228
|
description && /* @__PURE__ */ jsx(CardDescription, { children: description }),
|
|
217
|
-
action && /* @__PURE__ */
|
|
229
|
+
(action || valueAxis.buttons) && /* @__PURE__ */ jsxs(CardAction, {
|
|
230
|
+
className: "flex flex-wrap items-center gap-x-3 gap-y-2",
|
|
231
|
+
children: [action, valueAxis.buttons]
|
|
232
|
+
})
|
|
218
233
|
] }),
|
|
219
234
|
/* @__PURE__ */ jsx(CardContent, {
|
|
220
235
|
className: "@container/chart overflow-x-auto",
|
|
@@ -285,12 +300,13 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
285
300
|
tick: xTickDetail || xTicks ? fittedTick(data, xKey, xFormatter, xTickDetail, false) : TICK,
|
|
286
301
|
interval: xTickDetail || xTicks ? 0 : void 0
|
|
287
302
|
}), /* @__PURE__ */ jsx(YAxis, {
|
|
288
|
-
|
|
303
|
+
scale: valueAxis.scale,
|
|
304
|
+
niceTicks: log ? void 0 : "snap125",
|
|
289
305
|
tickLine: false,
|
|
290
306
|
axisLine: false,
|
|
291
307
|
width: "auto",
|
|
292
|
-
domain: yDomain,
|
|
293
|
-
ticks: yTicks,
|
|
308
|
+
domain: log?.domain ?? yDomain,
|
|
309
|
+
ticks: log?.ticks ?? yTicks,
|
|
294
310
|
label: yLabel ? {
|
|
295
311
|
value: yLabel,
|
|
296
312
|
angle: -90,
|
|
@@ -301,6 +317,7 @@ function ChartFrame({ chart: Chart, children, horizontal = false, stackOffset, o
|
|
|
301
317
|
tick: yTickFormatter ? /* @__PURE__ */ jsx(ValueTick, {
|
|
302
318
|
axis: "y",
|
|
303
319
|
formatter: yTickFormatter,
|
|
320
|
+
ownUnit: log !== void 0,
|
|
304
321
|
...TICK
|
|
305
322
|
}) : TICK,
|
|
306
323
|
tickFormatter: yTickFormatter ? void 0 : (value) => formatValue(value)
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AxisScale } from "./ticks.js";
|
|
1
2
|
import { ReactNode } from "react";
|
|
2
3
|
//#region src/lib/chart-series.d.ts
|
|
3
4
|
/**
|
|
@@ -89,6 +90,17 @@ export interface NumericXProps {
|
|
|
89
90
|
/** The x axis runs over this range of the xKey field, which must hold numbers; without it the axis is one slot per row. */
|
|
90
91
|
xDomain?: [number, number];
|
|
91
92
|
}
|
|
93
|
+
/** A value axis that may run on a log scale: lines and areas, which need not start at zero as bars must. */
|
|
94
|
+
export interface ValueScaleProps {
|
|
95
|
+
/**
|
|
96
|
+
* "log" spreads values across powers of ten, for values that run from tiny to large; the first selection when
|
|
97
|
+
* yScaleToggle is set. Log draws only when every value, and yDomain, is above zero; otherwise the axis is linear.
|
|
98
|
+
* On log the axis ticks at 1, 2 and 5 inside yDomain, if given, and yTicks is not used.
|
|
99
|
+
*/
|
|
100
|
+
yScale?: AxisScale;
|
|
101
|
+
/** Linear and Log buttons for the value axis in the header, after the action, so a reader can switch. */
|
|
102
|
+
yScaleToggle?: boolean;
|
|
103
|
+
}
|
|
92
104
|
/**
|
|
93
105
|
* How a line or an area's edge joins its points: "linear" draws straight segments, as measured samples should
|
|
94
106
|
* be drawn; "monotone", the default, smooths between them without overshooting a point.
|
package/dist/lib/scatter.d.ts
CHANGED
|
@@ -1,15 +1,5 @@
|
|
|
1
|
+
import { AxisScale } from "./ticks.js";
|
|
1
2
|
//#region src/lib/scatter.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Ticks for a log axis at 1, 2 and 5 times a power of ten, from the largest at or under min to the smallest at or
|
|
4
|
-
* over max, so the axis ends on a tick and every label reads as a round number.
|
|
5
|
-
*/
|
|
6
|
-
export declare function logTicks(min: number, max: number): number[];
|
|
7
|
-
/**
|
|
8
|
-
* Ticks for a linear axis that just covers min to max, about `count` of them, a step of 1, 2, 2.5 or 5 times a power
|
|
9
|
-
* of ten: −50% to +75% by 25s, never −50% to +150% because the step had to be 50. Values that differ only by float
|
|
10
|
-
* noise, such as 0.3 and 0.30000000000000004, count as one value and get that value as their only tick.
|
|
11
|
-
*/
|
|
12
|
-
export declare function linearTicks(min: number, max: number, count?: number): number[];
|
|
13
3
|
export interface Box {
|
|
14
4
|
x: number;
|
|
15
5
|
y: number;
|
|
@@ -46,7 +36,7 @@ export interface LabelType {
|
|
|
46
36
|
export declare function placeLabels(candidates: readonly LabelCandidate[], plot: Box, limit: number, { size, measure }: LabelType, reserved?: readonly Box[]): PlacedLabel[];
|
|
47
37
|
/**
|
|
48
38
|
* Splits the plot into four at a value on each axis, such as zero, with an optional name in each corner. On a log
|
|
49
|
-
* axis
|
|
39
|
+
* axis that value must be above zero, or no split is drawn. A name that does not fit its quadrant in two lines is left out.
|
|
50
40
|
*/
|
|
51
41
|
export interface ScatterQuadrants {
|
|
52
42
|
x: number;
|
|
@@ -60,7 +50,7 @@ export interface ScatterQuadrants {
|
|
|
60
50
|
}
|
|
61
51
|
export type QuadrantLabels = ScatterQuadrants["labels"];
|
|
62
52
|
/** A split a log axis cannot place, at or below zero, or one that is not a number, is no split at all. */
|
|
63
|
-
export declare function quadrantSplit(quadrants: ScatterQuadrants | undefined, xScale:
|
|
53
|
+
export declare function quadrantSplit(quadrants: ScatterQuadrants | undefined, xScale: AxisScale, yScale: AxisScale): ScatterQuadrants | undefined;
|
|
64
54
|
/** The largest sized dot; the smallest stays big enough to see and to tap. */
|
|
65
55
|
export declare const MAX_RADIUS = 20;
|
|
66
56
|
/**
|
package/dist/lib/scatter.js
CHANGED
|
@@ -1,44 +1,4 @@
|
|
|
1
1
|
//#region src/lib/scatter.ts
|
|
2
|
-
/**
|
|
3
|
-
* Ticks for a log axis at 1, 2 and 5 times a power of ten, from the largest at or under min to the smallest at or
|
|
4
|
-
* over max, so the axis ends on a tick and every label reads as a round number.
|
|
5
|
-
*/
|
|
6
|
-
function logTicks(min, max) {
|
|
7
|
-
if (!(min > 0) || !Number.isFinite(max) || !(max >= min)) return [];
|
|
8
|
-
const ticks = [];
|
|
9
|
-
for (let decade = Math.floor(Math.log10(min));; decade++) for (const step of [
|
|
10
|
-
1,
|
|
11
|
-
2,
|
|
12
|
-
5
|
|
13
|
-
]) {
|
|
14
|
-
const tick = Number((step * 10 ** decade).toPrecision(12));
|
|
15
|
-
if (Number(((step === 5 ? 10 : step === 2 ? 5 : 2) * 10 ** decade).toPrecision(12)) <= min) continue;
|
|
16
|
-
ticks.push(tick);
|
|
17
|
-
if (tick >= max) return ticks;
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
const clean = (value) => Number(value.toPrecision(12)) || 0;
|
|
21
|
-
/**
|
|
22
|
-
* Ticks for a linear axis that just covers min to max, about `count` of them, a step of 1, 2, 2.5 or 5 times a power
|
|
23
|
-
* of ten: −50% to +75% by 25s, never −50% to +150% because the step had to be 50. Values that differ only by float
|
|
24
|
-
* noise, such as 0.3 and 0.30000000000000004, count as one value and get that value as their only tick.
|
|
25
|
-
*/
|
|
26
|
-
function linearTicks(min, max, count = 5) {
|
|
27
|
-
if (!Number.isFinite(min) || !Number.isFinite(max) || max < min) return [];
|
|
28
|
-
if (max - min <= Math.max(Math.abs(min), Math.abs(max)) * 1e-9) return [clean(min)];
|
|
29
|
-
const rough = (max - min) / (count - 1);
|
|
30
|
-
const power = 10 ** Math.floor(Math.log10(rough));
|
|
31
|
-
const step = ([
|
|
32
|
-
1,
|
|
33
|
-
2,
|
|
34
|
-
2.5,
|
|
35
|
-
5,
|
|
36
|
-
10
|
|
37
|
-
].find((m) => m * power >= rough * (1 - 1e-9)) ?? 10) * power;
|
|
38
|
-
const first = Math.floor(min / step + 1e-9);
|
|
39
|
-
const last = Math.ceil(max / step - 1e-9);
|
|
40
|
-
return Array.from({ length: last - first + 1 }, (_, i) => clean((first + i) * step));
|
|
41
|
-
}
|
|
42
2
|
const HALO = 2;
|
|
43
3
|
const GAP = 4;
|
|
44
4
|
const overlaps = (a, b) => a.x < b.x + b.width && b.x < a.x + a.width && a.y < b.y + b.height && b.y < a.y + a.height;
|
|
@@ -125,10 +85,11 @@ function placeLabels(candidates, plot, limit, { size, measure }, reserved = [])
|
|
|
125
85
|
}
|
|
126
86
|
return placed;
|
|
127
87
|
}
|
|
88
|
+
const fits = (scale, at) => scale === "linear" || at > 0;
|
|
128
89
|
/** A split a log axis cannot place, at or below zero, or one that is not a number, is no split at all. */
|
|
129
|
-
function quadrantSplit(quadrants, xScale) {
|
|
90
|
+
function quadrantSplit(quadrants, xScale, yScale) {
|
|
130
91
|
if (!quadrants || !Number.isFinite(quadrants.x) || !Number.isFinite(quadrants.y)) return void 0;
|
|
131
|
-
return xScale
|
|
92
|
+
return fits(xScale, quadrants.x) && fits(yScale, quadrants.y) ? quadrants : void 0;
|
|
132
93
|
}
|
|
133
94
|
/** The largest sized dot; the smallest stays big enough to see and to tap. */
|
|
134
95
|
const MAX_RADIUS = 20;
|
|
@@ -215,4 +176,4 @@ function corners(plot, names, split, type) {
|
|
|
215
176
|
});
|
|
216
177
|
}
|
|
217
178
|
//#endregion
|
|
218
|
-
export { MAX_RADIUS, corners, dotSizes,
|
|
179
|
+
export { MAX_RADIUS, corners, dotSizes, placeLabels, quadrantSplit };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/lib/ticks.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Ticks for a log axis at 1, 2 and 5 times a power of ten, from the largest at or under min to the smallest at or
|
|
4
|
+
* over max, so the axis ends on a tick and every label reads as a round number.
|
|
5
|
+
*/
|
|
6
|
+
export declare function logTicks(min: number, max: number): number[];
|
|
7
|
+
/**
|
|
8
|
+
* Ticks for a linear axis that just covers min to max, about `count` of them, a step of 1, 2, 2.5 or 5 times a power
|
|
9
|
+
* of ten: −50% to +75% by 25s, never −50% to +150% because the step had to be 50. Values that differ only by float
|
|
10
|
+
* noise, such as 0.3 and 0.30000000000000004, count as one value and get that value as their only tick.
|
|
11
|
+
*/
|
|
12
|
+
export declare function linearTicks(min: number, max: number, count?: number): number[];
|
|
13
|
+
/** How an axis spaces its values: evenly, or by powers of ten for values that run from tiny to large. */
|
|
14
|
+
export type AxisScale = "linear" | "log";
|
|
15
|
+
/** An axis' ticks for its scale: round steps either way, so a linear axis starting at 0.4% reads 0%, 5%, 10%. */
|
|
16
|
+
export declare const ticksFor: (scale: AxisScale, min: number, max: number) => number[];
|
|
17
|
+
/** A log axis has no place for zero or below, so it can draw a set of values only when every one is above zero. */
|
|
18
|
+
export declare const fitsLog: (values: readonly number[]) => boolean;
|
|
19
|
+
/**
|
|
20
|
+
* A log axis' ends and ticks: a page's fixed range when it gives one, with the 1, 2 and 5 ticks inside it, or else the
|
|
21
|
+
* ticks that just cover the values and their outer two as the ends.
|
|
22
|
+
*/
|
|
23
|
+
export declare function logAxis(values: readonly number[], range?: readonly [number, number]): {
|
|
24
|
+
domain: [number, number];
|
|
25
|
+
ticks: number[];
|
|
26
|
+
};
|
|
27
|
+
//#endregion
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
//#region src/lib/ticks.ts
|
|
2
|
+
/**
|
|
3
|
+
* Ticks for a log axis at 1, 2 and 5 times a power of ten, from the largest at or under min to the smallest at or
|
|
4
|
+
* over max, so the axis ends on a tick and every label reads as a round number.
|
|
5
|
+
*/
|
|
6
|
+
function logTicks(min, max) {
|
|
7
|
+
if (!(min > 0) || !Number.isFinite(max) || !(max >= min)) return [];
|
|
8
|
+
const ticks = [];
|
|
9
|
+
for (let decade = Math.floor(Math.log10(min));; decade++) for (const step of [
|
|
10
|
+
1,
|
|
11
|
+
2,
|
|
12
|
+
5
|
|
13
|
+
]) {
|
|
14
|
+
const tick = Number((step * 10 ** decade).toPrecision(12));
|
|
15
|
+
if (Number(((step === 5 ? 10 : step === 2 ? 5 : 2) * 10 ** decade).toPrecision(12)) <= min) continue;
|
|
16
|
+
ticks.push(tick);
|
|
17
|
+
if (tick >= max) return ticks;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
const clean = (value) => Number(value.toPrecision(12)) || 0;
|
|
21
|
+
/**
|
|
22
|
+
* Ticks for a linear axis that just covers min to max, about `count` of them, a step of 1, 2, 2.5 or 5 times a power
|
|
23
|
+
* of ten: −50% to +75% by 25s, never −50% to +150% because the step had to be 50. Values that differ only by float
|
|
24
|
+
* noise, such as 0.3 and 0.30000000000000004, count as one value and get that value as their only tick.
|
|
25
|
+
*/
|
|
26
|
+
function linearTicks(min, max, count = 5) {
|
|
27
|
+
if (!Number.isFinite(min) || !Number.isFinite(max) || max < min) return [];
|
|
28
|
+
if (max - min <= Math.max(Math.abs(min), Math.abs(max)) * 1e-9) return [clean(min)];
|
|
29
|
+
const rough = (max - min) / (count - 1);
|
|
30
|
+
const power = 10 ** Math.floor(Math.log10(rough));
|
|
31
|
+
const step = ([
|
|
32
|
+
1,
|
|
33
|
+
2,
|
|
34
|
+
2.5,
|
|
35
|
+
5,
|
|
36
|
+
10
|
|
37
|
+
].find((m) => m * power >= rough * (1 - 1e-9)) ?? 10) * power;
|
|
38
|
+
const first = Math.floor(min / step + 1e-9);
|
|
39
|
+
const last = Math.ceil(max / step - 1e-9);
|
|
40
|
+
return Array.from({ length: last - first + 1 }, (_, i) => clean((first + i) * step));
|
|
41
|
+
}
|
|
42
|
+
/** An axis' ticks for its scale: round steps either way, so a linear axis starting at 0.4% reads 0%, 5%, 10%. */
|
|
43
|
+
const ticksFor = (scale, min, max) => scale === "log" ? logTicks(min, max) : linearTicks(min, max);
|
|
44
|
+
/** A log axis has no place for zero or below, so it can draw a set of values only when every one is above zero. */
|
|
45
|
+
const fitsLog = (values) => values.length > 0 && values.every((value) => value > 0);
|
|
46
|
+
/**
|
|
47
|
+
* A log axis' ends and ticks: a page's fixed range when it gives one, with the 1, 2 and 5 ticks inside it, or else the
|
|
48
|
+
* ticks that just cover the values and their outer two as the ends.
|
|
49
|
+
*/
|
|
50
|
+
function logAxis(values, range) {
|
|
51
|
+
if (range) {
|
|
52
|
+
const [low, high] = range;
|
|
53
|
+
return {
|
|
54
|
+
domain: [low, high],
|
|
55
|
+
ticks: logTicks(low, high).filter((tick) => tick >= low && tick <= high)
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
const low = Math.min(...values);
|
|
59
|
+
const high = Math.max(...values);
|
|
60
|
+
const ticks = logTicks(low, high);
|
|
61
|
+
return {
|
|
62
|
+
domain: [ticks[0] ?? low, ticks.at(-1) ?? high],
|
|
63
|
+
ticks
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
export { fitsLog, linearTicks, logAxis, logTicks, ticksFor };
|