@nexub/react 6.5.0 → 6.6.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": "6.5.0",
2
+ "version": "6.6.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, and on open popups (menus, listboxes, dialogs), on every pull request; a new violation fails the build.",
@@ -238,6 +238,17 @@
238
238
  "Each series is a toggle button with `aria-pressed`. The last visible series cannot be switched off."
239
239
  ]
240
240
  },
241
+ {
242
+ "slug": "chart-zoom",
243
+ "name": "Chart Zoom",
244
+ "package": "@nexub/react",
245
+ "automated": "pass",
246
+ "exceptions": [],
247
+ "keyboard": [
248
+ "Arrow keys / Home / End: Move the focused thumb."
249
+ ],
250
+ "screenReader": []
251
+ },
241
252
  {
242
253
  "slug": "checkbox-card",
243
254
  "name": "Checkbox Card",
@@ -1430,6 +1441,15 @@
1430
1441
  "keyboard": [],
1431
1442
  "screenReader": []
1432
1443
  },
1444
+ {
1445
+ "slug": "notification-center",
1446
+ "name": "NotificationCenter",
1447
+ "package": "@nexub/patterns",
1448
+ "automated": "pass",
1449
+ "exceptions": [],
1450
+ "keyboard": [],
1451
+ "screenReader": []
1452
+ },
1433
1453
  {
1434
1454
  "slug": "notification-item",
1435
1455
  "name": "NotificationItem",
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ export interface ChartZoomProps<T> {
3
+ data: T[];
4
+ /** The category key, shown as the range's ends. */
5
+ index: keyof T;
6
+ /** Render the chart for the visible slice (charts stay server-friendly; only this wrapper is client). */
7
+ children: (slice: T[]) => React.ReactNode;
8
+ /** Start and end indexes. @default the whole range */
9
+ defaultRange?: [number, number];
10
+ /** Fewest categories shown. @default 2 */
11
+ minSpan?: number;
12
+ className?: string;
13
+ }
14
+ /**
15
+ * Zoom a chart to part of its range with a two-thumb slider under it (keyboard
16
+ * and touch friendly), and reset to the whole range.
17
+ */
18
+ export declare function ChartZoom<T>({ data, index, children, defaultRange, minSpan, className }: ChartZoomProps<T>): React.JSX.Element;
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Slider } from "../Slider/Slider.js";
5
+ import { Button } from "../Button/Button.js";
6
+ import { cn } from "../../utils/cn.js";
7
+ import { useNexubMessages } from "../NexubProvider/NexubProvider.js";
8
+ function ChartZoom({ data, index, children, defaultRange, minSpan = 2, className }) {
9
+ const t = useNexubMessages();
10
+ const full = [0, Math.max(0, data.length - 1)];
11
+ const [range, setRange] = React.useState(defaultRange ?? full);
12
+ const [a, b] = [Math.max(0, range[0]), Math.min(full[1], range[1])];
13
+ const zoomed = a > 0 || b < full[1];
14
+ const label = (i) => String(data[i]?.[index] ?? "");
15
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), children: [
16
+ children(data.slice(a, b + 1)),
17
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
18
+ /* @__PURE__ */ jsx(
19
+ Slider,
20
+ {
21
+ min: 0,
22
+ max: full[1],
23
+ step: 1,
24
+ minStepsBetweenThumbs: Math.max(1, minSpan - 1),
25
+ value: [a, b],
26
+ onValueChange: (v) => setRange([v[0], v[1]]),
27
+ thumbLabels: [`${t.zoomStart}: ${label(a)}`, `${t.zoomEnd}: ${label(b)}`],
28
+ className: "flex-1"
29
+ }
30
+ ),
31
+ /* @__PURE__ */ jsxs("span", { "aria-hidden": "true", className: "min-w-max text-label-md tabular-nums text-[var(--color-on-surface-muted)]", children: [
32
+ label(a),
33
+ " \u2013 ",
34
+ label(b)
35
+ ] }),
36
+ /* @__PURE__ */ jsx(Button, { variant: "text", size: "sm", disabled: !zoomed, onClick: () => setRange(full), children: t.resetZoom })
37
+ ] })
38
+ ] });
39
+ }
40
+ export {
41
+ ChartZoom
42
+ };
@@ -0,0 +1,2 @@
1
+ export { ChartZoom } from './ChartZoom.js';
2
+ export type { ChartZoomProps } from './ChartZoom.js';
@@ -0,0 +1,4 @@
1
+ import { ChartZoom } from "./ChartZoom.js";
2
+ export {
3
+ ChartZoom
4
+ };
package/dist/index.d.ts CHANGED
@@ -53,6 +53,8 @@ export type { AuroraProps } from './components/Aurora/index.js';
53
53
  export { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from './components/Chart/index.js';
54
54
  export { Gauge, Heatmap, Funnel, KpiTile } from './components/Chart/index.js';
55
55
  export { ChartToggle } from './components/Chart/index.js';
56
+ export { ChartZoom } from './components/ChartZoom/index.js';
57
+ export type { ChartZoomProps } from './components/ChartZoom/index.js';
56
58
  export type { ChartToggleProps } from './components/Chart/index.js';
57
59
  export type { GaugeProps, HeatmapProps, FunnelProps, KpiTileProps } from './components/Chart/index.js';
58
60
  export type { BarChartProps, LineChartProps, DonutChartProps, SparklineProps, ChartLegendProps, ChartSeries, ChartColor } from './components/Chart/index.js';
@@ -238,6 +240,8 @@ export { Sortable } from './components/Sortable/index.js';
238
240
  export type { SortableProps } from './components/Sortable/index.js';
239
241
  export { Kanban } from './components/Kanban/index.js';
240
242
  export type { KanbanProps, KanbanColumn } from './components/Kanban/index.js';
243
+ export { toCSV } from './utils/csv.js';
244
+ export type { CSVColumn } from './utils/csv.js';
241
245
  export type { OTPInputProps } from './components/OTPInput/index.js';
242
246
  export { DatePicker } from './components/DatePicker/index.js';
243
247
  export type { DatePickerProps } from './components/DatePicker/index.js';
package/dist/index.js CHANGED
@@ -32,6 +32,7 @@ import { Aurora } from "./components/Aurora/index.js";
32
32
  import { BarChart, LineChart, DonutChart, Sparkline, ChartLegend, niceMax, niceDomain } from "./components/Chart/index.js";
33
33
  import { Gauge, Heatmap, Funnel, KpiTile } from "./components/Chart/index.js";
34
34
  import { ChartToggle } from "./components/Chart/index.js";
35
+ import { ChartZoom } from "./components/ChartZoom/index.js";
35
36
  import { NumberTicker } from "./components/NumberTicker/index.js";
36
37
  import { SearchInput } from "./components/SearchInput/index.js";
37
38
  import { PasswordInput } from "./components/PasswordInput/index.js";
@@ -133,6 +134,7 @@ import { Stepper } from "./components/Stepper/index.js";
133
134
  import { ActionBar } from "./components/ActionBar/index.js";
134
135
  import { Sortable } from "./components/Sortable/index.js";
135
136
  import { Kanban } from "./components/Kanban/index.js";
137
+ import { toCSV } from "./utils/csv.js";
136
138
  import { DatePicker } from "./components/DatePicker/index.js";
137
139
  import { DateRangePicker } from "./components/DateRangePicker/index.js";
138
140
  import { todayIn } from "./components/DateRangePicker/index.js";
@@ -162,6 +164,7 @@ export {
162
164
  Celebrate,
163
165
  ChartLegend,
164
166
  ChartToggle,
167
+ ChartZoom,
165
168
  CheckList,
166
169
  CheckListItem,
167
170
  Checkbox,
@@ -331,6 +334,7 @@ export {
331
334
  startViewTransition,
332
335
  textVariants,
333
336
  textareaVariants,
337
+ toCSV,
334
338
  toast,
335
339
  todayIn,
336
340
  toggleVariants,
@@ -0,0 +1,11 @@
1
+ export interface CSVColumn<T> {
2
+ header: string;
3
+ /** A key of the row, or a function returning the cell's value. */
4
+ value: keyof T | ((row: T) => unknown);
5
+ }
6
+ /**
7
+ * Rows to CSV text (RFC 4180, CRLF line ends). Text that starts like a formula
8
+ * gets a leading `'` so spreadsheets show it instead of running it. Pass the
9
+ * rows and columns the person sees, e.g. after sorting and hiding columns.
10
+ */
11
+ export declare function toCSV<T>(rows: T[], columns: CSVColumn<T>[]): string;
@@ -0,0 +1,17 @@
1
+ const FORMULA = /^[=+\-@\t\r]/;
2
+ function cell(value) {
3
+ if (value == null) return "";
4
+ let text = value instanceof Date ? value.toISOString() : String(value);
5
+ if (typeof value !== "number" && FORMULA.test(text)) text = `'${text}`;
6
+ return /[",\r\n]/.test(text) || text !== text.trim() ? `"${text.replace(/"/g, '""')}"` : text;
7
+ }
8
+ function toCSV(rows, columns) {
9
+ const lines = [columns.map((c) => cell(c.header)).join(",")];
10
+ for (const row of rows) {
11
+ lines.push(columns.map((c) => cell(typeof c.value === "function" ? c.value(row) : row[c.value])).join(","));
12
+ }
13
+ return lines.join("\r\n") + "\r\n";
14
+ }
15
+ export {
16
+ toCSV
17
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nexub/react",
3
- "version": "6.5.0",
3
+ "version": "6.6.0",
4
4
  "description": "React component library for Nexub Design System — 90+ accessible, themeable UI components built on Radix UI primitives.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -81,14 +81,14 @@
81
81
  "date-fns": "^4.4.0",
82
82
  "react-day-picker": "^10.0.2",
83
83
  "tailwind-merge": "^3.7.0",
84
- "@nexub/core": "6.5.0",
85
- "@nexub/icons": "6.5.0"
84
+ "@nexub/core": "6.6.0",
85
+ "@nexub/icons": "6.6.0"
86
86
  },
87
87
  "peerDependencies": {
88
88
  "react": ">=19 <20",
89
89
  "react-dom": ">=19 <20",
90
90
  "@tanstack/react-virtual": "^3.14.22",
91
- "@nexub/tokens": "^6.5.0"
91
+ "@nexub/tokens": "^6.6.0"
92
92
  },
93
93
  "peerDependenciesMeta": {
94
94
  "@tanstack/react-virtual": {
@@ -120,8 +120,8 @@
120
120
  "vaul": "1.1.2",
121
121
  "vite": "^8.3.5",
122
122
  "vitest": "^5.0.5",
123
- "@nexub/themes": "6.5.0",
124
- "@nexub/tokens": "6.5.0"
123
+ "@nexub/themes": "6.6.0",
124
+ "@nexub/tokens": "6.6.0"
125
125
  },
126
126
  "scripts": {
127
127
  "build": "rm -rf dist && tsup && tsc -p tsconfig.build.json && rm -f dist/vendor/*.d.ts && node scripts/check-dts.mjs && tailwindcss -i src/styles.css -o dist/styles.css --minify && cp -R ../themes/src/fonts dist/fonts",