@nexub/react 4.0.0 → 4.2.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.
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "4.0.0",
2
+ "version": "4.2.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.",
@@ -69,6 +69,17 @@
69
69
  "keyboard": [],
70
70
  "screenReader": []
71
71
  },
72
+ {
73
+ "slug": "aurora",
74
+ "name": "Aurora",
75
+ "package": "@nexub/react",
76
+ "automated": "not covered",
77
+ "exceptions": [],
78
+ "keyboard": [],
79
+ "screenReader": [
80
+ "Decorative: the whole layer is `aria-hidden`."
81
+ ]
82
+ },
72
83
  {
73
84
  "slug": "autocomplete",
74
85
  "name": "Autocomplete",
@@ -114,7 +125,7 @@
114
125
  "slug": "bar-chart",
115
126
  "name": "Bar Chart",
116
127
  "package": "@nexub/react",
117
- "automated": "not covered",
128
+ "automated": "pass",
118
129
  "exceptions": [],
119
130
  "keyboard": [],
120
131
  "screenReader": [
@@ -298,7 +309,7 @@
298
309
  "slug": "donut-chart",
299
310
  "name": "Donut Chart",
300
311
  "package": "@nexub/react",
301
- "automated": "not covered",
312
+ "automated": "pass",
302
313
  "exceptions": [],
303
314
  "keyboard": [],
304
315
  "screenReader": [
@@ -461,7 +472,7 @@
461
472
  "slug": "line-chart",
462
473
  "name": "Line Chart",
463
474
  "package": "@nexub/react",
464
- "automated": "not covered",
475
+ "automated": "pass",
465
476
  "exceptions": [],
466
477
  "keyboard": [],
467
478
  "screenReader": [
@@ -513,7 +524,7 @@
513
524
  "slug": "money-input",
514
525
  "name": "Money Input",
515
526
  "package": "@nexub/react",
516
- "automated": "not covered",
527
+ "automated": "pass",
517
528
  "exceptions": [],
518
529
  "keyboard": [],
519
530
  "screenReader": []
@@ -540,7 +551,7 @@
540
551
  "slug": "motion-float",
541
552
  "name": "Float",
542
553
  "package": "@nexub/react",
543
- "automated": "not covered",
554
+ "automated": "pass",
544
555
  "exceptions": [],
545
556
  "keyboard": [],
546
557
  "screenReader": []
@@ -549,7 +560,7 @@
549
560
  "slug": "motion-marquee",
550
561
  "name": "Marquee",
551
562
  "package": "@nexub/react",
552
- "automated": "not covered",
563
+ "automated": "pass",
553
564
  "exceptions": [],
554
565
  "keyboard": [],
555
566
  "screenReader": []
@@ -558,7 +569,7 @@
558
569
  "slug": "motion-reveal",
559
570
  "name": "Reveal",
560
571
  "package": "@nexub/react",
561
- "automated": "not covered",
572
+ "automated": "pass",
562
573
  "exceptions": [],
563
574
  "keyboard": [],
564
575
  "screenReader": []
@@ -585,7 +596,7 @@
585
596
  "slug": "navigation-rail",
586
597
  "name": "Navigation Rail",
587
598
  "package": "@nexub/react",
588
- "automated": "not covered",
599
+ "automated": "pass",
589
600
  "exceptions": [],
590
601
  "keyboard": [],
591
602
  "screenReader": []
@@ -748,7 +759,7 @@
748
759
  "slug": "sheet",
749
760
  "name": "Sheet",
750
761
  "package": "@nexub/react",
751
- "automated": "not covered",
762
+ "automated": "pass",
752
763
  "exceptions": [],
753
764
  "keyboard": [],
754
765
  "screenReader": []
@@ -775,7 +786,7 @@
775
786
  "slug": "sparkline",
776
787
  "name": "Sparkline",
777
788
  "package": "@nexub/react",
778
- "automated": "not covered",
789
+ "automated": "pass",
779
790
  "exceptions": [],
780
791
  "keyboard": [],
781
792
  "screenReader": [
@@ -796,7 +807,7 @@
796
807
  "slug": "split-button",
797
808
  "name": "Split Button",
798
809
  "package": "@nexub/react",
799
- "automated": "not covered",
810
+ "automated": "pass",
800
811
  "exceptions": [],
801
812
  "keyboard": [],
802
813
  "screenReader": []
@@ -970,7 +981,7 @@
970
981
  "slug": "cta-band",
971
982
  "name": "CTABand",
972
983
  "package": "@nexub/marketing",
973
- "automated": "not covered",
984
+ "automated": "pass",
974
985
  "exceptions": [],
975
986
  "keyboard": [],
976
987
  "screenReader": []
@@ -992,7 +1003,7 @@
992
1003
  "slug": "faq",
993
1004
  "name": "FAQ",
994
1005
  "package": "@nexub/marketing",
995
- "automated": "not covered",
1006
+ "automated": "pass",
996
1007
  "exceptions": [],
997
1008
  "keyboard": [],
998
1009
  "screenReader": []
@@ -1001,7 +1012,7 @@
1001
1012
  "slug": "feature-split",
1002
1013
  "name": "FeatureSplit",
1003
1014
  "package": "@nexub/marketing",
1004
- "automated": "not covered",
1015
+ "automated": "pass",
1005
1016
  "exceptions": [],
1006
1017
  "keyboard": [],
1007
1018
  "screenReader": []
@@ -1019,7 +1030,7 @@
1019
1030
  "slug": "hero",
1020
1031
  "name": "Hero",
1021
1032
  "package": "@nexub/marketing",
1022
- "automated": "not covered",
1033
+ "automated": "pass",
1023
1034
  "exceptions": [],
1024
1035
  "keyboard": [],
1025
1036
  "screenReader": []
@@ -1028,7 +1039,7 @@
1028
1039
  "slug": "how-it-works",
1029
1040
  "name": "HowItWorks",
1030
1041
  "package": "@nexub/marketing",
1031
- "automated": "not covered",
1042
+ "automated": "pass",
1032
1043
  "exceptions": [],
1033
1044
  "keyboard": [],
1034
1045
  "screenReader": []
@@ -1055,7 +1066,7 @@
1055
1066
  "slug": "logo-strip",
1056
1067
  "name": "LogoStrip",
1057
1068
  "package": "@nexub/marketing",
1058
- "automated": "not covered",
1069
+ "automated": "pass",
1059
1070
  "exceptions": [],
1060
1071
  "keyboard": [],
1061
1072
  "screenReader": []
@@ -1064,7 +1075,7 @@
1064
1075
  "slug": "marketing-footer",
1065
1076
  "name": "MarketingFooter",
1066
1077
  "package": "@nexub/marketing",
1067
- "automated": "not covered",
1078
+ "automated": "pass",
1068
1079
  "exceptions": [],
1069
1080
  "keyboard": [],
1070
1081
  "screenReader": []
@@ -1073,7 +1084,7 @@
1073
1084
  "slug": "marketing-nav",
1074
1085
  "name": "MarketingNav",
1075
1086
  "package": "@nexub/marketing",
1076
- "automated": "not covered",
1087
+ "automated": "pass",
1077
1088
  "exceptions": [],
1078
1089
  "keyboard": [],
1079
1090
  "screenReader": []
@@ -1100,7 +1111,7 @@
1100
1111
  "slug": "pricing-table",
1101
1112
  "name": "PricingTable",
1102
1113
  "package": "@nexub/marketing",
1103
- "automated": "not covered",
1114
+ "automated": "pass",
1104
1115
  "exceptions": [],
1105
1116
  "keyboard": [],
1106
1117
  "screenReader": []
@@ -1109,7 +1120,7 @@
1109
1120
  "slug": "product-grid",
1110
1121
  "name": "ProductGrid",
1111
1122
  "package": "@nexub/marketing",
1112
- "automated": "not covered",
1123
+ "automated": "pass",
1113
1124
  "exceptions": [],
1114
1125
  "keyboard": [],
1115
1126
  "screenReader": []
@@ -1118,7 +1129,7 @@
1118
1129
  "slug": "section-header",
1119
1130
  "name": "SectionHeader",
1120
1131
  "package": "@nexub/marketing",
1121
- "automated": "not covered",
1132
+ "automated": "pass",
1122
1133
  "exceptions": [],
1123
1134
  "keyboard": [],
1124
1135
  "screenReader": []
@@ -1136,7 +1147,7 @@
1136
1147
  "slug": "stat-band",
1137
1148
  "name": "StatBand",
1138
1149
  "package": "@nexub/marketing",
1139
- "automated": "not covered",
1150
+ "automated": "pass",
1140
1151
  "exceptions": [],
1141
1152
  "keyboard": [],
1142
1153
  "screenReader": []
@@ -1163,7 +1174,7 @@
1163
1174
  "slug": "testimonial-grid",
1164
1175
  "name": "TestimonialGrid",
1165
1176
  "package": "@nexub/marketing",
1166
- "automated": "not covered",
1177
+ "automated": "pass",
1167
1178
  "exceptions": [],
1168
1179
  "keyboard": [],
1169
1180
  "screenReader": []
@@ -0,0 +1,3 @@
1
+ import * as React from 'react';
2
+ export type AuroraProps = Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>;
3
+ export declare const Aurora: React.ForwardRefExoticComponent<AuroraProps & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,12 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import { cn } from "../../utils/cn.js";
4
+ const Aurora = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxs("div", { ref, "aria-hidden": "true", className: cn("nx-aurora", className), ...props, children: [
5
+ /* @__PURE__ */ jsx("span", {}),
6
+ /* @__PURE__ */ jsx("span", {}),
7
+ /* @__PURE__ */ jsx("span", {})
8
+ ] }));
9
+ Aurora.displayName = "Aurora";
10
+ export {
11
+ Aurora
12
+ };
@@ -0,0 +1,2 @@
1
+ export { Aurora } from './Aurora.js';
2
+ export type { AuroraProps } from './Aurora.js';
@@ -0,0 +1,4 @@
1
+ import { Aurora } from "./Aurora.js";
2
+ export {
3
+ Aurora
4
+ };
@@ -95,6 +95,8 @@ const Button = React.forwardRef(
95
95
  className
96
96
  ),
97
97
  "data-tone": tone,
98
+ // Styling hook for opt-in layers (vivid, marketing); no styles depend on it by default.
99
+ "data-variant": variant ?? "primary",
98
100
  ...variant === "glass" && { "data-material": "glass", "data-glass-thickness": "thin" },
99
101
  ...props
100
102
  };
@@ -61,6 +61,7 @@ const Card = React.forwardRef(
61
61
  className: cn(cardVariants({ variant, surface }), toneStyle, sheen && "nx-sheen", className),
62
62
  onPointerMove: handlePointerMove,
63
63
  "data-tone": tone,
64
+ "data-variant": variant ?? "flat",
64
65
  "data-product": accent,
65
66
  "data-material": surface === "glass" ? "glass" : void 0,
66
67
  ...props,
@@ -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 hover text and the data table. */
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. Values must be 0 or more. */
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. Values must be 0 or more. */
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
- max,
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(max * t) }, t)) }),
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("svg", { viewBox: `0 0 ${VB_W} ${VB_H}`, preserveAspectRatio: "none", className: cn("w-full overflow-visible rtl:-scale-x-100", PLOT_HEIGHT[size]), children: [
45
- ticks.map((t) => /* @__PURE__ */ jsx(
46
- "line",
47
- {
48
- x1: "0",
49
- x2: VB_W,
50
- y1: VB_H * (1 - t),
51
- y2: VB_H * (1 - t),
52
- strokeWidth: "1",
53
- vectorEffect: "non-scaling-stroke",
54
- className: t === 0 ? "stroke-[var(--color-outline)]" : "stroke-[var(--color-outline-variant)]"
55
- },
56
- t
57
- )),
58
- children
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(Number(row[s.key]) || 0) }, s.key))
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, index, valueFormat = defaultFormat } = props;
79
- const max = niceMax(Math.max(0, ...data.map((row) => stacked ? series.reduce((sum, s) => sum + valueOf(row, s.key), 0) : Math.max(0, ...series.map((s) => valueOf(row, s.key))))));
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, max, children: data.map((row, i) => {
84
- let base = 0;
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 h = v / max * VB_H;
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
- const y = VB_H - base - h;
90
- if (stacked) base += h;
91
- return /* @__PURE__ */ jsx("rect", { x, y, width: Math.max(0, barW - (stacked ? 0 : 1)), height: h, className: FILL[colorIndex(s.color, j)], children: /* @__PURE__ */ jsx("title", { children: `${String(row[index])} \xB7 ${s.label ?? s.key}: ${valueFormat(v)}` }) }, s.key);
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, index, valueFormat = defaultFormat } = props;
97
- const max = niceMax(Math.max(0, ...data.flatMap((row) => series.map((s) => valueOf(row, s.key)))));
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 / max * VB_H;
101
- return /* @__PURE__ */ jsx(Frame, { ...props, max, children: series.map((s, j) => {
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)},${VB_H} ${pts.join(" ")} ${x(data.length - 1)},${VB_H}`, className: cn(FILL[c], "opacity-15") }),
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__ */ jsxs(
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,9 @@ 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 { Aurora } from './components/Aurora/index.js';
40
+ export type { AuroraProps } from './components/Aurora/index.js';
41
+ export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from './components/Chart/index.js';
40
42
  export type { BarChartProps, LineChartProps, DonutChartProps, SparklineProps, ChartLegendProps, ChartSeries, ChartColor } from './components/Chart/index.js';
41
43
  export type { AmountProps } from './components/Amount/index.js';
42
44
  export { NumberTicker } from './components/NumberTicker/index.js';
package/dist/index.js CHANGED
@@ -21,7 +21,8 @@ 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 { Aurora } from "./components/Aurora/index.js";
25
+ import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from "./components/Chart/index.js";
25
26
  import { NumberTicker } from "./components/NumberTicker/index.js";
26
27
  import { SearchInput } from "./components/SearchInput/index.js";
27
28
  import { PasswordInput } from "./components/PasswordInput/index.js";
@@ -118,6 +119,7 @@ export {
118
119
  Amount,
119
120
  AppShell,
120
121
  AspectRatio,
122
+ Aurora,
121
123
  Autocomplete,
122
124
  Avatar,
123
125
  AvatarGroup,
@@ -255,6 +257,7 @@ export {
255
257
  labelVariants,
256
258
  linkVariants,
257
259
  logoVariants,
260
+ niceDomain,
258
261
  niceMax,
259
262
  progressFillVariants,
260
263
  progressTrackVariants,