@nexub/react 3.9.0 → 4.1.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/accessibility.json +25 -25
- package/dist/components/Chart/Chart.d.ts +7 -5
- package/dist/components/Chart/Chart.js +82 -41
- package/dist/components/Chart/index.d.ts +1 -1
- package/dist/components/Chart/index.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -1
- package/dist/styles.css +1 -1
- package/package.json +6 -6
package/accessibility.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "
|
|
2
|
+
"version": "4.1.0",
|
|
3
3
|
"standard": "WCAG 2.2 Level AA",
|
|
4
4
|
"method": {
|
|
5
5
|
"automated": "axe-core rules tagged wcag2a, wcag2aa, wcag21a, wcag21aa and wcag22aa, run on every Storybook story in light and dark on every pull request; a new violation fails the build.",
|
|
@@ -114,7 +114,7 @@
|
|
|
114
114
|
"slug": "bar-chart",
|
|
115
115
|
"name": "Bar Chart",
|
|
116
116
|
"package": "@nexub/react",
|
|
117
|
-
"automated": "
|
|
117
|
+
"automated": "pass",
|
|
118
118
|
"exceptions": [],
|
|
119
119
|
"keyboard": [],
|
|
120
120
|
"screenReader": [
|
|
@@ -298,7 +298,7 @@
|
|
|
298
298
|
"slug": "donut-chart",
|
|
299
299
|
"name": "Donut Chart",
|
|
300
300
|
"package": "@nexub/react",
|
|
301
|
-
"automated": "
|
|
301
|
+
"automated": "pass",
|
|
302
302
|
"exceptions": [],
|
|
303
303
|
"keyboard": [],
|
|
304
304
|
"screenReader": [
|
|
@@ -461,7 +461,7 @@
|
|
|
461
461
|
"slug": "line-chart",
|
|
462
462
|
"name": "Line Chart",
|
|
463
463
|
"package": "@nexub/react",
|
|
464
|
-
"automated": "
|
|
464
|
+
"automated": "pass",
|
|
465
465
|
"exceptions": [],
|
|
466
466
|
"keyboard": [],
|
|
467
467
|
"screenReader": [
|
|
@@ -513,7 +513,7 @@
|
|
|
513
513
|
"slug": "money-input",
|
|
514
514
|
"name": "Money Input",
|
|
515
515
|
"package": "@nexub/react",
|
|
516
|
-
"automated": "
|
|
516
|
+
"automated": "pass",
|
|
517
517
|
"exceptions": [],
|
|
518
518
|
"keyboard": [],
|
|
519
519
|
"screenReader": []
|
|
@@ -540,7 +540,7 @@
|
|
|
540
540
|
"slug": "motion-float",
|
|
541
541
|
"name": "Float",
|
|
542
542
|
"package": "@nexub/react",
|
|
543
|
-
"automated": "
|
|
543
|
+
"automated": "pass",
|
|
544
544
|
"exceptions": [],
|
|
545
545
|
"keyboard": [],
|
|
546
546
|
"screenReader": []
|
|
@@ -549,7 +549,7 @@
|
|
|
549
549
|
"slug": "motion-marquee",
|
|
550
550
|
"name": "Marquee",
|
|
551
551
|
"package": "@nexub/react",
|
|
552
|
-
"automated": "
|
|
552
|
+
"automated": "pass",
|
|
553
553
|
"exceptions": [],
|
|
554
554
|
"keyboard": [],
|
|
555
555
|
"screenReader": []
|
|
@@ -558,7 +558,7 @@
|
|
|
558
558
|
"slug": "motion-reveal",
|
|
559
559
|
"name": "Reveal",
|
|
560
560
|
"package": "@nexub/react",
|
|
561
|
-
"automated": "
|
|
561
|
+
"automated": "pass",
|
|
562
562
|
"exceptions": [],
|
|
563
563
|
"keyboard": [],
|
|
564
564
|
"screenReader": []
|
|
@@ -585,7 +585,7 @@
|
|
|
585
585
|
"slug": "navigation-rail",
|
|
586
586
|
"name": "Navigation Rail",
|
|
587
587
|
"package": "@nexub/react",
|
|
588
|
-
"automated": "
|
|
588
|
+
"automated": "pass",
|
|
589
589
|
"exceptions": [],
|
|
590
590
|
"keyboard": [],
|
|
591
591
|
"screenReader": []
|
|
@@ -748,7 +748,7 @@
|
|
|
748
748
|
"slug": "sheet",
|
|
749
749
|
"name": "Sheet",
|
|
750
750
|
"package": "@nexub/react",
|
|
751
|
-
"automated": "
|
|
751
|
+
"automated": "pass",
|
|
752
752
|
"exceptions": [],
|
|
753
753
|
"keyboard": [],
|
|
754
754
|
"screenReader": []
|
|
@@ -775,7 +775,7 @@
|
|
|
775
775
|
"slug": "sparkline",
|
|
776
776
|
"name": "Sparkline",
|
|
777
777
|
"package": "@nexub/react",
|
|
778
|
-
"automated": "
|
|
778
|
+
"automated": "pass",
|
|
779
779
|
"exceptions": [],
|
|
780
780
|
"keyboard": [],
|
|
781
781
|
"screenReader": [
|
|
@@ -796,7 +796,7 @@
|
|
|
796
796
|
"slug": "split-button",
|
|
797
797
|
"name": "Split Button",
|
|
798
798
|
"package": "@nexub/react",
|
|
799
|
-
"automated": "
|
|
799
|
+
"automated": "pass",
|
|
800
800
|
"exceptions": [],
|
|
801
801
|
"keyboard": [],
|
|
802
802
|
"screenReader": []
|
|
@@ -970,7 +970,7 @@
|
|
|
970
970
|
"slug": "cta-band",
|
|
971
971
|
"name": "CTABand",
|
|
972
972
|
"package": "@nexub/marketing",
|
|
973
|
-
"automated": "
|
|
973
|
+
"automated": "pass",
|
|
974
974
|
"exceptions": [],
|
|
975
975
|
"keyboard": [],
|
|
976
976
|
"screenReader": []
|
|
@@ -992,7 +992,7 @@
|
|
|
992
992
|
"slug": "faq",
|
|
993
993
|
"name": "FAQ",
|
|
994
994
|
"package": "@nexub/marketing",
|
|
995
|
-
"automated": "
|
|
995
|
+
"automated": "pass",
|
|
996
996
|
"exceptions": [],
|
|
997
997
|
"keyboard": [],
|
|
998
998
|
"screenReader": []
|
|
@@ -1001,7 +1001,7 @@
|
|
|
1001
1001
|
"slug": "feature-split",
|
|
1002
1002
|
"name": "FeatureSplit",
|
|
1003
1003
|
"package": "@nexub/marketing",
|
|
1004
|
-
"automated": "
|
|
1004
|
+
"automated": "pass",
|
|
1005
1005
|
"exceptions": [],
|
|
1006
1006
|
"keyboard": [],
|
|
1007
1007
|
"screenReader": []
|
|
@@ -1019,7 +1019,7 @@
|
|
|
1019
1019
|
"slug": "hero",
|
|
1020
1020
|
"name": "Hero",
|
|
1021
1021
|
"package": "@nexub/marketing",
|
|
1022
|
-
"automated": "
|
|
1022
|
+
"automated": "pass",
|
|
1023
1023
|
"exceptions": [],
|
|
1024
1024
|
"keyboard": [],
|
|
1025
1025
|
"screenReader": []
|
|
@@ -1028,7 +1028,7 @@
|
|
|
1028
1028
|
"slug": "how-it-works",
|
|
1029
1029
|
"name": "HowItWorks",
|
|
1030
1030
|
"package": "@nexub/marketing",
|
|
1031
|
-
"automated": "
|
|
1031
|
+
"automated": "pass",
|
|
1032
1032
|
"exceptions": [],
|
|
1033
1033
|
"keyboard": [],
|
|
1034
1034
|
"screenReader": []
|
|
@@ -1055,7 +1055,7 @@
|
|
|
1055
1055
|
"slug": "logo-strip",
|
|
1056
1056
|
"name": "LogoStrip",
|
|
1057
1057
|
"package": "@nexub/marketing",
|
|
1058
|
-
"automated": "
|
|
1058
|
+
"automated": "pass",
|
|
1059
1059
|
"exceptions": [],
|
|
1060
1060
|
"keyboard": [],
|
|
1061
1061
|
"screenReader": []
|
|
@@ -1064,7 +1064,7 @@
|
|
|
1064
1064
|
"slug": "marketing-footer",
|
|
1065
1065
|
"name": "MarketingFooter",
|
|
1066
1066
|
"package": "@nexub/marketing",
|
|
1067
|
-
"automated": "
|
|
1067
|
+
"automated": "pass",
|
|
1068
1068
|
"exceptions": [],
|
|
1069
1069
|
"keyboard": [],
|
|
1070
1070
|
"screenReader": []
|
|
@@ -1073,7 +1073,7 @@
|
|
|
1073
1073
|
"slug": "marketing-nav",
|
|
1074
1074
|
"name": "MarketingNav",
|
|
1075
1075
|
"package": "@nexub/marketing",
|
|
1076
|
-
"automated": "
|
|
1076
|
+
"automated": "pass",
|
|
1077
1077
|
"exceptions": [],
|
|
1078
1078
|
"keyboard": [],
|
|
1079
1079
|
"screenReader": []
|
|
@@ -1100,7 +1100,7 @@
|
|
|
1100
1100
|
"slug": "pricing-table",
|
|
1101
1101
|
"name": "PricingTable",
|
|
1102
1102
|
"package": "@nexub/marketing",
|
|
1103
|
-
"automated": "
|
|
1103
|
+
"automated": "pass",
|
|
1104
1104
|
"exceptions": [],
|
|
1105
1105
|
"keyboard": [],
|
|
1106
1106
|
"screenReader": []
|
|
@@ -1109,7 +1109,7 @@
|
|
|
1109
1109
|
"slug": "product-grid",
|
|
1110
1110
|
"name": "ProductGrid",
|
|
1111
1111
|
"package": "@nexub/marketing",
|
|
1112
|
-
"automated": "
|
|
1112
|
+
"automated": "pass",
|
|
1113
1113
|
"exceptions": [],
|
|
1114
1114
|
"keyboard": [],
|
|
1115
1115
|
"screenReader": []
|
|
@@ -1118,7 +1118,7 @@
|
|
|
1118
1118
|
"slug": "section-header",
|
|
1119
1119
|
"name": "SectionHeader",
|
|
1120
1120
|
"package": "@nexub/marketing",
|
|
1121
|
-
"automated": "
|
|
1121
|
+
"automated": "pass",
|
|
1122
1122
|
"exceptions": [],
|
|
1123
1123
|
"keyboard": [],
|
|
1124
1124
|
"screenReader": []
|
|
@@ -1136,7 +1136,7 @@
|
|
|
1136
1136
|
"slug": "stat-band",
|
|
1137
1137
|
"name": "StatBand",
|
|
1138
1138
|
"package": "@nexub/marketing",
|
|
1139
|
-
"automated": "
|
|
1139
|
+
"automated": "pass",
|
|
1140
1140
|
"exceptions": [],
|
|
1141
1141
|
"keyboard": [],
|
|
1142
1142
|
"screenReader": []
|
|
@@ -1163,7 +1163,7 @@
|
|
|
1163
1163
|
"slug": "testimonial-grid",
|
|
1164
1164
|
"name": "TestimonialGrid",
|
|
1165
1165
|
"package": "@nexub/marketing",
|
|
1166
|
-
"automated": "
|
|
1166
|
+
"automated": "pass",
|
|
1167
1167
|
"exceptions": [],
|
|
1168
1168
|
"keyboard": [],
|
|
1169
1169
|
"screenReader": []
|
|
@@ -4,13 +4,15 @@ export type ChartColor = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8;
|
|
|
4
4
|
export interface ChartSeries {
|
|
5
5
|
/** Key of the value in each data row. */
|
|
6
6
|
key: string;
|
|
7
|
-
/** Name shown in the legend and the data table. Defaults to `key`. */
|
|
7
|
+
/** Name shown in the legend, the tooltip and the data table. Defaults to `key`. */
|
|
8
8
|
label?: string;
|
|
9
9
|
/** Palette colour, 1–8. Defaults to the series' position. */
|
|
10
10
|
color?: ChartColor;
|
|
11
11
|
}
|
|
12
12
|
/** Rounds up to 1, 2, 2.5 or 5 × 10ⁿ so the four gridlines get round labels. */
|
|
13
13
|
export declare function niceMax(max: number): number;
|
|
14
|
+
/** The axis range for a set of values: [0, nice max], or [−nice, +nice] when some are negative. */
|
|
15
|
+
export declare function niceDomain(values: number[]): [number, number];
|
|
14
16
|
declare const PLOT_HEIGHT: {
|
|
15
17
|
readonly sm: "h-32";
|
|
16
18
|
readonly md: "h-48";
|
|
@@ -33,7 +35,7 @@ interface CartesianProps<T> extends Omit<React.HTMLAttributes<HTMLElement>, 'tit
|
|
|
33
35
|
series: ChartSeries[];
|
|
34
36
|
/** Accessible name of the chart, e.g. "Revenue by month". */
|
|
35
37
|
title: string;
|
|
36
|
-
/** Formats axis labels, the
|
|
38
|
+
/** Formats axis labels, the tooltip and the data table. */
|
|
37
39
|
valueFormat?: (value: number) => string;
|
|
38
40
|
/** Height of the plot area. */
|
|
39
41
|
size?: keyof typeof PLOT_HEIGHT;
|
|
@@ -44,13 +46,13 @@ export interface BarChartProps<T> extends CartesianProps<T> {
|
|
|
44
46
|
/** Stack the series in one bar per category instead of side by side. */
|
|
45
47
|
stacked?: boolean;
|
|
46
48
|
}
|
|
47
|
-
/** Bars per category, grouped or stacked.
|
|
49
|
+
/** Bars per category, grouped or stacked. Negative values grow down from the zero line. */
|
|
48
50
|
export declare function BarChart<T extends object>({ stacked, ...props }: BarChartProps<T>): React.JSX.Element;
|
|
49
51
|
export interface LineChartProps<T> extends CartesianProps<T> {
|
|
50
|
-
/** Fill the area under each line. */
|
|
52
|
+
/** Fill the area under each line (down to the zero line). */
|
|
51
53
|
area?: boolean;
|
|
52
54
|
}
|
|
53
|
-
/** One line per series across the categories.
|
|
55
|
+
/** One line per series across the categories. Negative values go below the zero line. */
|
|
54
56
|
export declare function LineChart<T extends object>({ area, ...props }: LineChartProps<T>): React.JSX.Element;
|
|
55
57
|
export interface DonutChartProps extends Omit<React.HTMLAttributes<HTMLElement>, 'title'> {
|
|
56
58
|
data: {
|
|
@@ -11,6 +11,13 @@ function niceMax(max) {
|
|
|
11
11
|
const step = [1, 2, 2.5, 5, 10].find((s) => s * pow >= max);
|
|
12
12
|
return step * pow;
|
|
13
13
|
}
|
|
14
|
+
function niceDomain(values) {
|
|
15
|
+
const lo = Math.min(0, ...values);
|
|
16
|
+
const hi = Math.max(0, ...values);
|
|
17
|
+
if (lo === 0) return [0, niceMax(hi)];
|
|
18
|
+
if (hi === 0) return [-niceMax(-lo), 0];
|
|
19
|
+
return [-niceMax(-lo), niceMax(hi)];
|
|
20
|
+
}
|
|
14
21
|
const defaultFormat = (n) => n.toLocaleString();
|
|
15
22
|
const PLOT_HEIGHT = { sm: "h-32", md: "h-48", lg: "h-64" };
|
|
16
23
|
const VB_W = 300;
|
|
@@ -21,6 +28,7 @@ function ChartLegend({ items, className, ...props }) {
|
|
|
21
28
|
item.label
|
|
22
29
|
] }, item.label)) });
|
|
23
30
|
}
|
|
31
|
+
const valueOf = (row, key) => Number(row[key]) || 0;
|
|
24
32
|
function Frame({
|
|
25
33
|
data,
|
|
26
34
|
index,
|
|
@@ -29,33 +37,46 @@ function Frame({
|
|
|
29
37
|
valueFormat = defaultFormat,
|
|
30
38
|
size = "md",
|
|
31
39
|
legend,
|
|
32
|
-
|
|
40
|
+
domain,
|
|
33
41
|
className,
|
|
34
42
|
children,
|
|
35
43
|
...props
|
|
36
44
|
}) {
|
|
37
45
|
const labels = series.map((s) => s.label ?? s.key);
|
|
46
|
+
const [lo, hi] = domain;
|
|
38
47
|
const ticks = [1, 0.75, 0.5, 0.25, 0];
|
|
48
|
+
const zero = VB_H - (0 - lo) / (hi - lo) * VB_H;
|
|
39
49
|
return /* @__PURE__ */ jsxs("figure", { "aria-label": title, className: cn("m-0 flex flex-col gap-3", className), ...props, children: [
|
|
40
50
|
(legend ?? series.length > 1) && /* @__PURE__ */ jsx(ChartLegend, { "aria-hidden": "true", items: series.map((s, i) => ({ label: labels[i], color: s.color })) }),
|
|
41
51
|
/* @__PURE__ */ jsxs("div", { "aria-hidden": "true", className: "flex gap-2", children: [
|
|
42
|
-
/* @__PURE__ */ jsx("div", { className: cn("flex flex-col justify-between text-end text-label-sm tabular-nums text-[var(--color-on-surface-muted)]", PLOT_HEIGHT[size]), children: ticks.map((t) => /* @__PURE__ */ jsx("span", { className: "flex h-0 items-center justify-end", children: valueFormat(
|
|
52
|
+
/* @__PURE__ */ jsx("div", { className: cn("flex flex-col justify-between text-end text-label-sm tabular-nums text-[var(--color-on-surface-muted)]", PLOT_HEIGHT[size]), children: ticks.map((t) => /* @__PURE__ */ jsx("span", { className: "flex h-0 items-center justify-end", children: valueFormat(lo + (hi - lo) * t) }, t)) }),
|
|
43
53
|
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col gap-1", children: [
|
|
44
|
-
/* @__PURE__ */ jsxs("
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
54
|
+
/* @__PURE__ */ jsxs("div", { className: cn("relative", PLOT_HEIGHT[size]), children: [
|
|
55
|
+
/* @__PURE__ */ jsxs("svg", { viewBox: `0 0 ${VB_W} ${VB_H}`, preserveAspectRatio: "none", className: "size-full overflow-visible rtl:-scale-x-100", children: [
|
|
56
|
+
ticks.map((t) => /* @__PURE__ */ jsx(
|
|
57
|
+
"line",
|
|
58
|
+
{
|
|
59
|
+
x1: "0",
|
|
60
|
+
x2: VB_W,
|
|
61
|
+
y1: VB_H * (1 - t),
|
|
62
|
+
y2: VB_H * (1 - t),
|
|
63
|
+
strokeWidth: "1",
|
|
64
|
+
vectorEffect: "non-scaling-stroke",
|
|
65
|
+
className: "stroke-[var(--color-outline-variant)]"
|
|
66
|
+
},
|
|
67
|
+
t
|
|
68
|
+
)),
|
|
69
|
+
/* @__PURE__ */ jsx("line", { x1: "0", x2: VB_W, y1: zero, y2: zero, strokeWidth: "1", vectorEffect: "non-scaling-stroke", className: "stroke-[var(--color-outline)]" }),
|
|
70
|
+
children
|
|
71
|
+
] }),
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "absolute inset-0 grid auto-cols-fr grid-flow-col", children: data.map((row, i) => /* @__PURE__ */ jsx("div", { className: "group/col relative rounded-shape-tooltip transition-colors hover:bg-[color-mix(in_oklab,var(--color-on-surface)_6%,transparent)]", children: /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute top-1 start-1/2 z-10 min-w-max -translate-x-1/2 rounded-shape-tooltip bg-[var(--color-inverse-surface)] px-3 py-2 text-label-md text-[var(--color-inverse-on-surface)] opacity-0 shadow-elevation-2 transition-opacity group-hover/col:opacity-100 rtl:translate-x-1/2", children: [
|
|
73
|
+
/* @__PURE__ */ jsx("div", { className: "mb-1 font-semibold", children: String(row[index]) }),
|
|
74
|
+
series.map((s, j) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 tabular-nums", children: [
|
|
75
|
+
/* @__PURE__ */ jsx("span", { className: cn("size-2 shrink-0 rounded-full", BG[colorIndex(s.color, j)]) }),
|
|
76
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: labels[j] }),
|
|
77
|
+
/* @__PURE__ */ jsx("span", { className: "ps-3", children: valueFormat(valueOf(row, s.key)) })
|
|
78
|
+
] }, s.key))
|
|
79
|
+
] }) }, i)) })
|
|
59
80
|
] }),
|
|
60
81
|
/* @__PURE__ */ jsx("div", { className: "grid auto-cols-fr grid-flow-col text-center text-label-sm text-[var(--color-on-surface-muted)]", children: data.map((row, i) => /* @__PURE__ */ jsx("span", { className: "truncate px-0.5", children: String(row[index]) }, i)) })
|
|
61
82
|
] })
|
|
@@ -68,46 +89,65 @@ function Frame({
|
|
|
68
89
|
] }) }),
|
|
69
90
|
/* @__PURE__ */ jsx("tbody", { children: data.map((row, i) => /* @__PURE__ */ jsxs("tr", { children: [
|
|
70
91
|
/* @__PURE__ */ jsx("th", { scope: "row", children: String(row[index]) }),
|
|
71
|
-
series.map((s) => /* @__PURE__ */ jsx("td", { children: valueFormat(
|
|
92
|
+
series.map((s) => /* @__PURE__ */ jsx("td", { children: valueFormat(valueOf(row, s.key)) }, s.key))
|
|
72
93
|
] }, i)) })
|
|
73
94
|
] })
|
|
74
95
|
] });
|
|
75
96
|
}
|
|
76
|
-
const valueOf = (row, key) => Math.max(0, Number(row[key]) || 0);
|
|
77
97
|
function BarChart({ stacked = false, ...props }) {
|
|
78
|
-
const { data, series
|
|
79
|
-
const
|
|
98
|
+
const { data, series } = props;
|
|
99
|
+
const totals = data.flatMap((row) => {
|
|
100
|
+
if (!stacked) return series.map((s) => valueOf(row, s.key));
|
|
101
|
+
const vals = series.map((s) => valueOf(row, s.key));
|
|
102
|
+
return [vals.filter((v) => v > 0).reduce((a, b) => a + b, 0), vals.filter((v) => v < 0).reduce((a, b) => a + b, 0)];
|
|
103
|
+
});
|
|
104
|
+
const domain = niceDomain(totals);
|
|
105
|
+
const [lo, hi] = domain;
|
|
106
|
+
const y = (v) => VB_H - (v - lo) / (hi - lo) * VB_H;
|
|
80
107
|
const slot = VB_W / Math.max(1, data.length);
|
|
81
108
|
const groupW = slot * 0.7;
|
|
82
109
|
const barW = stacked ? groupW : groupW / series.length;
|
|
83
|
-
return /* @__PURE__ */ jsx(Frame, { ...props,
|
|
84
|
-
let
|
|
110
|
+
return /* @__PURE__ */ jsx(Frame, { ...props, domain, children: data.map((row, i) => {
|
|
111
|
+
let up = 0;
|
|
112
|
+
let down = 0;
|
|
85
113
|
return /* @__PURE__ */ jsx("g", { children: series.map((s, j) => {
|
|
86
114
|
const v = valueOf(row, s.key);
|
|
87
|
-
const
|
|
115
|
+
const from = stacked ? v >= 0 ? up : down : 0;
|
|
116
|
+
const to = from + v;
|
|
117
|
+
if (stacked) {
|
|
118
|
+
if (v >= 0) up = to;
|
|
119
|
+
else down = to;
|
|
120
|
+
}
|
|
121
|
+
const top = Math.min(y(from), y(to));
|
|
88
122
|
const x = i * slot + (slot - groupW) / 2 + (stacked ? 0 : j * barW);
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
123
|
+
return /* @__PURE__ */ jsx(
|
|
124
|
+
"rect",
|
|
125
|
+
{
|
|
126
|
+
x,
|
|
127
|
+
y: top,
|
|
128
|
+
width: Math.max(0, barW - (stacked ? 0 : 1)),
|
|
129
|
+
height: Math.abs(y(to) - y(from)),
|
|
130
|
+
"data-negative": v < 0 ? "" : void 0,
|
|
131
|
+
className: cn("nx-chart-bar", FILL[colorIndex(s.color, j)])
|
|
132
|
+
},
|
|
133
|
+
s.key
|
|
134
|
+
);
|
|
92
135
|
}) }, i);
|
|
93
136
|
}) });
|
|
94
137
|
}
|
|
95
138
|
function LineChart({ area = false, ...props }) {
|
|
96
|
-
const { data, series
|
|
97
|
-
const
|
|
139
|
+
const { data, series } = props;
|
|
140
|
+
const domain = niceDomain(data.flatMap((row) => series.map((s) => valueOf(row, s.key))));
|
|
141
|
+
const [lo, hi] = domain;
|
|
98
142
|
const slot = VB_W / Math.max(1, data.length);
|
|
99
143
|
const x = (i) => i * slot + slot / 2;
|
|
100
|
-
const y = (v) => VB_H - v /
|
|
101
|
-
return /* @__PURE__ */ jsx(Frame, { ...props,
|
|
144
|
+
const y = (v) => VB_H - (v - lo) / (hi - lo) * VB_H;
|
|
145
|
+
return /* @__PURE__ */ jsx(Frame, { ...props, domain, children: series.map((s, j) => {
|
|
102
146
|
const c = colorIndex(s.color, j);
|
|
103
147
|
const pts = data.map((row, i) => `${x(i)},${y(valueOf(row, s.key))}`);
|
|
104
|
-
return /* @__PURE__ */ jsxs("g", { children: [
|
|
105
|
-
area && data.length > 0 && /* @__PURE__ */ jsx("polygon", { points: `${x(0)},${
|
|
106
|
-
/* @__PURE__ */ jsx("polyline", { points: pts.join(" "), fill: "none", strokeWidth: "2", strokeLinejoin: "round", strokeLinecap: "round", vectorEffect: "non-scaling-stroke", className: STROKE[c] })
|
|
107
|
-
data.map((row, i) => (
|
|
108
|
-
// A wide, invisible hit area per point carries the hover text.
|
|
109
|
-
/* @__PURE__ */ jsx("rect", { x: x(i) - slot / 2, y: "0", width: slot, height: VB_H, className: "fill-transparent", children: /* @__PURE__ */ jsx("title", { children: `${String(row[index])} \xB7 ${s.label ?? s.key}: ${valueFormat(valueOf(row, s.key))}` }) }, i)
|
|
110
|
-
))
|
|
148
|
+
return /* @__PURE__ */ jsxs("g", { className: "nx-chart-line", children: [
|
|
149
|
+
area && data.length > 0 && /* @__PURE__ */ jsx("polygon", { points: `${x(0)},${y(0)} ${pts.join(" ")} ${x(data.length - 1)},${y(0)}`, className: cn(FILL[c], "opacity-15") }),
|
|
150
|
+
/* @__PURE__ */ jsx("polyline", { points: pts.join(" "), fill: "none", strokeWidth: "2", strokeLinejoin: "round", strokeLinecap: "round", vectorEffect: "non-scaling-stroke", className: STROKE[c] })
|
|
111
151
|
] }, s.key);
|
|
112
152
|
}) });
|
|
113
153
|
}
|
|
@@ -149,7 +189,7 @@ function Sparkline({ values, label, color = 1, area = false, className, ...props
|
|
|
149
189
|
const step = values.length > 1 ? VB_W / (values.length - 1) : 0;
|
|
150
190
|
const pts = values.map((v, i) => `${i * step},${VB_H - 4 - (v - min) / span * (VB_H - 8)}`).join(" ");
|
|
151
191
|
const c = colorIndex(color, 0);
|
|
152
|
-
return /* @__PURE__ */
|
|
192
|
+
return /* @__PURE__ */ jsx(
|
|
153
193
|
"svg",
|
|
154
194
|
{
|
|
155
195
|
viewBox: `0 0 ${VB_W} ${VB_H}`,
|
|
@@ -157,10 +197,10 @@ function Sparkline({ values, label, color = 1, area = false, className, ...props
|
|
|
157
197
|
...label ? { role: "img", "aria-label": label } : { "aria-hidden": true },
|
|
158
198
|
className: cn("h-8 w-24 overflow-visible rtl:-scale-x-100", className),
|
|
159
199
|
...props,
|
|
160
|
-
children: [
|
|
200
|
+
children: /* @__PURE__ */ jsxs("g", { className: "nx-chart-line", children: [
|
|
161
201
|
area && values.length > 1 && /* @__PURE__ */ jsx("polygon", { points: `0,${VB_H} ${pts} ${VB_W},${VB_H}`, className: cn(FILL[c], "opacity-15") }),
|
|
162
202
|
/* @__PURE__ */ jsx("polyline", { points: pts, fill: "none", strokeWidth: "1.5", strokeLinejoin: "round", strokeLinecap: "round", vectorEffect: "non-scaling-stroke", className: STROKE[c] })
|
|
163
|
-
]
|
|
203
|
+
] })
|
|
164
204
|
}
|
|
165
205
|
);
|
|
166
206
|
}
|
|
@@ -170,5 +210,6 @@ export {
|
|
|
170
210
|
DonutChart,
|
|
171
211
|
LineChart,
|
|
172
212
|
Sparkline,
|
|
213
|
+
niceDomain,
|
|
173
214
|
niceMax
|
|
174
215
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax } from './Chart.js';
|
|
1
|
+
export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from './Chart.js';
|
|
2
2
|
export type { BarChartProps, LineChartProps, DonutChartProps, SparklineProps, ChartLegendProps, ChartSeries, ChartColor } from './Chart.js';
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax } from "./Chart.js";
|
|
1
|
+
import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from "./Chart.js";
|
|
2
2
|
export {
|
|
3
3
|
BarChart,
|
|
4
4
|
ChartLegend,
|
|
5
5
|
DonutChart,
|
|
6
6
|
LineChart,
|
|
7
7
|
Sparkline,
|
|
8
|
+
niceDomain,
|
|
8
9
|
niceMax
|
|
9
10
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -36,7 +36,7 @@ export type { NumberInputProps } from './components/NumberInput/index.js';
|
|
|
36
36
|
export { MoneyInput } from './components/MoneyInput/index.js';
|
|
37
37
|
export type { MoneyInputProps } from './components/MoneyInput/index.js';
|
|
38
38
|
export { Amount } from './components/Amount/index.js';
|
|
39
|
-
export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax } from './components/Chart/index.js';
|
|
39
|
+
export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from './components/Chart/index.js';
|
|
40
40
|
export type { BarChartProps, LineChartProps, DonutChartProps, SparklineProps, ChartLegendProps, ChartSeries, ChartColor } from './components/Chart/index.js';
|
|
41
41
|
export type { AmountProps } from './components/Amount/index.js';
|
|
42
42
|
export { NumberTicker } from './components/NumberTicker/index.js';
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,7 @@ import { Textarea, textareaVariants } from "./components/Textarea/index.js";
|
|
|
21
21
|
import { NumberInput } from "./components/NumberInput/index.js";
|
|
22
22
|
import { MoneyInput } from "./components/MoneyInput/index.js";
|
|
23
23
|
import { Amount } from "./components/Amount/index.js";
|
|
24
|
-
import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax } from "./components/Chart/index.js";
|
|
24
|
+
import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from "./components/Chart/index.js";
|
|
25
25
|
import { NumberTicker } from "./components/NumberTicker/index.js";
|
|
26
26
|
import { SearchInput } from "./components/SearchInput/index.js";
|
|
27
27
|
import { PasswordInput } from "./components/PasswordInput/index.js";
|
|
@@ -255,6 +255,7 @@ export {
|
|
|
255
255
|
labelVariants,
|
|
256
256
|
linkVariants,
|
|
257
257
|
logoVariants,
|
|
258
|
+
niceDomain,
|
|
258
259
|
niceMax,
|
|
259
260
|
progressFillVariants,
|
|
260
261
|
progressTrackVariants,
|