@niekes/charts-3d 0.0.0-stage → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright 2026, Stefan Nieke
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without modification,
5
+ are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the author nor the names of contributors may be used to
15
+ endorse or promote products derived from this software without specific prior
16
+ written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22
+ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25
+ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
package/NOTICE ADDED
@@ -0,0 +1,33 @@
1
+ charts-3d
2
+ Copyright 2026, Stefan Nieke
3
+ Licensed under the BSD 3-Clause License, see LICENSE.
4
+
5
+ charts-3d includes code adapted from shadcn/ui (https://github.com/shadcn-ui/ui):
6
+
7
+ - the ChartConfig type and the ChartStyle component in
8
+ registry/new-york/ui/chart-3d.tsx, which mirror the chart component of shadcn/ui
9
+ - the theme tokens in docs/app.css, the neutral theme of shadcn/ui
10
+
11
+ shadcn/ui is licensed under the MIT License:
12
+
13
+ MIT License
14
+
15
+ Copyright (c) 2023 shadcn
16
+
17
+ Permission is hereby granted, free of charge, to any person obtaining a copy
18
+ of this software and associated documentation files (the "Software"), to deal
19
+ in the Software without restriction, including without limitation the rights
20
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
21
+ copies of the Software, and to permit persons to whom the Software is
22
+ furnished to do so, subject to the following conditions:
23
+
24
+ The above copyright notice and this permission notice shall be included in all
25
+ copies or substantial portions of the Software.
26
+
27
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
28
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
29
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
30
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,89 @@
1
- # Temporary Holding Version
1
+ <p align="center">
2
+ <a href="https://github.com/sponsors/niekes"><img src="https://img.shields.io/badge/Sponsor_charts--3d-EA4AAA?logo=githubsponsors&logoColor=white&style=for-the-badge" alt="Sponsor charts-3d"></a>
3
+ </p>
2
4
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
5
+ <p align="center">
6
+ <strong>3D charts for <a href="https://ui.shadcn.com">shadcn/ui</a>, built on <a href="https://github.com/niekes/d3-3d">d3-3d</a>.</strong><br>
7
+ Free and open source, kept alive by one maintainer and the people who sponsor the work.
8
+ </p>
9
+
10
+ <p align="center">
11
+ <a href="https://github.com/niekes/charts-3d/actions/workflows/main.yml"><img src="https://github.com/niekes/charts-3d/actions/workflows/main.yml/badge.svg" alt="Build"></a>
12
+ <a href="https://github.com/niekes/charts-3d/actions/workflows/main.yml"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fraw.githubusercontent.com%2Fniekes%2Fcharts-3d%2Fmaster%2F.github%2Fbadges%2Fcoverage.json" alt="Coverage"></a>
13
+ <a href="https://fallow.tools/docs/explanations/health/"><img src="https://raw.githubusercontent.com/niekes/charts-3d/master/.github/badges/health.svg" alt="fallow health"></a>
14
+ <a href="https://ui.shadcn.com/docs/registry"><img src="https://img.shields.io/badge/shadcn-registry-000000?logo=shadcnui&logoColor=white" alt="shadcn registry"></a>
15
+ <a href="https://www.npmjs.com/package/@niekes/charts-3d"><img src="https://img.shields.io/npm/v/@niekes/charts-3d" alt="npm version"></a>
16
+ <a href="https://www.npmjs.com/package/@niekes/charts-3d"><img src="https://img.shields.io/npm/dw/@niekes/charts-3d" alt="npm weekly downloads"></a>
17
+ <a href="https://www.npmjs.com/package/d3-3d"><img src="https://img.shields.io/npm/v/d3-3d?label=d3-3d" alt="d3-3d version"></a>
18
+ <a href="https://github.com/niekes/charts-3d/blob/master/LICENSE"><img src="https://img.shields.io/github/license/niekes/charts-3d" alt="License"></a>
19
+ <img src="https://img.shields.io/badge/TypeScript-Ready-blue" alt="TypeScript">
20
+ <a href="https://github.com/niekes/charts-3d"><img src="https://img.shields.io/github/stars/niekes/charts-3d" alt="GitHub stars"></a>
21
+ <a href="https://github.com/sponsors/niekes"><img src="https://img.shields.io/github/sponsors/niekes?logo=GitHub+Sponsors&logoColor=%23EA4AAA&style=flat" alt="GitHub Sponsors"></a>
22
+ </p>
23
+
24
+ <p align="center">
25
+ <a href="https://niekes.github.io/charts-3d/docs">Docs</a> ·
26
+ <a href="https://niekes.github.io/charts-3d/docs/installation">Installation</a> ·
27
+ <a href="https://niekes.github.io/charts-3d/docs/components/bar-chart-3d">Components</a> ·
28
+ <a href="https://niekes.github.io/charts-3d/docs/theming">Theming</a> ·
29
+ <a href="https://niekes.github.io/charts-3d/docs/how-it-works">How it works</a>
30
+ </p>
31
+
32
+ ---
33
+
34
+ <table>
35
+ <tr style="background-color: #f6f8fa">
36
+ <td><a target="_blank" href="https://niekes.github.io/charts-3d/docs/components/bar-chart-3d"><img src="assets/examples/bar-chart-3d.png" alt="Bar Chart 3D"></a></td>
37
+ <td><a target="_blank" href="https://niekes.github.io/charts-3d/docs/components/scatter-chart-3d"><img src="assets/examples/scatter-chart-3d.png" alt="Scatter Chart 3D"></a></td>
38
+ </tr>
39
+ <tr style="background-color: #f6f8fa">
40
+ <td><a target="_blank" href="https://niekes.github.io/charts-3d/docs/components/surface-chart-3d"><img src="assets/examples/surface-chart-3d.png" alt="Surface Chart 3D"></a></td>
41
+ <td><a target="_blank" href="https://niekes.github.io/charts-3d/docs/components/sankey-chart-3d"><img src="assets/examples/sankey-chart-3d.png" alt="Sankey Chart 3D"></a></td>
42
+ </tr>
43
+ </table>
44
+
45
+ Copy-paste components or an npm package, plain SVG, themed by the `--chart-*` tokens you already have. They render on the server, take the same `ChartConfig` as the chart of shadcn/ui and turn on drag and on the arrow keys.
46
+
47
+ ## Sponsor charts-3d
48
+
49
+ **charts-3d** is free, and it always will be. There is no company behind it — just one maintainer working in spare time — so the cost of keeping it alive is paid for by the people who depend on it.
50
+
51
+ If charts-3d saves you time, [become a sponsor](https://github.com/sponsors/niekes).
52
+
53
+ | Tier | What you get |
54
+ | ----------- | ------------------------------------------------------------------------------------------- |
55
+ | **$5/mo** | Your name in the [sponsors list](#sponsors) and my sincere thanks |
56
+ | **$25/mo** | The above, plus your logo in the README and on the docs site, and priority issue triage |
57
+ | **$100/mo** | The above, plus direct email access for feature requests and a mention in the release notes |
58
+
59
+ Where the money goes:
60
+
61
+ - **Issue triage and bug fixes.** Sponsorship buys a reply within a couple of days instead of whenever I get to it.
62
+ - **Components that keep up.** Keeping the registry in step with shadcn/ui, React, Tailwind CSS and d3-3d.
63
+ - **The documentation site.** Hosting, builds and the live examples.
64
+ - **Time for new work.** More charts, transitions, and eventually a WebGL renderer for large data.
65
+
66
+ Prefer a one-off? The [sponsor page](https://github.com/sponsors/niekes) also takes one-time contributions.
67
+
68
+ **Need a company sponsorship or an invoice?** [Get in touch](mailto:s@niekes.com).
69
+
70
+ ## Sponsors
71
+
72
+ Thank you to the people who make this possible. Sponsors at $25/mo and above get their logo in this README and on the docs site; everyone gets their name below.
73
+
74
+ <!-- New sponsors go below this line, one per line. -->
75
+
76
+ ## Using charts-3d
77
+
78
+ ```bash
79
+ npx shadcn@latest add niekes/charts-3d/bar-chart-3d # the code, in your project
80
+ npm install @niekes/charts-3d # the same components, from npm
81
+ ```
82
+
83
+ Everything else lives in the [documentation](https://niekes.github.io/charts-3d/docs): [installation](https://niekes.github.io/charts-3d/docs/installation), the [components](https://niekes.github.io/charts-3d/docs/components/bar-chart-3d), [theming](https://niekes.github.io/charts-3d/docs/theming) and [how it works](https://niekes.github.io/charts-3d/docs/how-it-works).
84
+
85
+ charts-3d is not affiliated with shadcn/ui.
86
+
87
+ ## Star History
88
+
89
+ [![Star History Chart](https://api.star-history.com/svg?repos=niekes/charts-3d&type=date&legend=bottom-right)](https://www.star-history.com/#niekes/charts-3d&type=date&legend=bottom-right)
@@ -0,0 +1,267 @@
1
+ "use client"
2
+ import * as React from "react";
3
+ import { AxesSpec, AxisSpec, Camera3DInstance, CubeFace, Point2D, TransformedPoint } from "d3-3d";
4
+ declare const THEMES: {
5
+ readonly light: "";
6
+ readonly dark: ".dark";
7
+ };
8
+ export type ChartConfig = { [k in string]: {
9
+ label?: React.ReactNode;
10
+ icon?: React.ComponentType;
11
+ } & ({
12
+ color?: string;
13
+ theme?: never;
14
+ } | {
15
+ color?: never;
16
+ theme: Record<keyof typeof THEMES, string>;
17
+ }); };
18
+ /** How the camera looks at the chart box, angles in radians. */
19
+ export type View3D = {
20
+ yaw: number;
21
+ /** The angle above the floor the camera looks down from. */
22
+ tilt: number;
23
+ zoom?: number;
24
+ /** How far the chart is moved, in the units of the view box. */
25
+ pan?: Point2D;
26
+ /** The distance of the eye in box units; Infinity, the default, is orthographic. */
27
+ perspective?: number;
28
+ };
29
+ /** How the marks of a chart are drawn. The box, its labels, the tooltip and the legend are always SVG and HTML. */
30
+ export type Renderer3D = "svg" | "canvas";
31
+ /** Maps data values to the world box, which spans -1 to 1 on every axis, y up. */
32
+ export type World = Record<keyof AxesSpec, (value: number) => number>;
33
+ export type Tooltip3D = {
34
+ /** The anchor in the units of the view box. */
35
+ at: Point2D;
36
+ title?: React.ReactNode;
37
+ items: {
38
+ label: React.ReactNode;
39
+ value: React.ReactNode;
40
+ color?: string;
41
+ }[];
42
+ };
43
+ /** One shape of a chart, projected, in paint order: a polygon, or a circle of radius `r` around its one point. */
44
+ export type Mark3D = {
45
+ /** Stable across renders, so React moves the shape instead of redrawing it. */
46
+ key: string;
47
+ /** The corners of a polygon, or the center of a circle, in the units of the view box. */
48
+ points: Point2D[];
49
+ r?: number;
50
+ /** A CSS color, such as the result of `shade` or `var(--color-x)`. */
51
+ fill: string;
52
+ /** The ring around a circle, a CSS color. */
53
+ stroke?: string;
54
+ /** Shown while the pointer is over the mark. */
55
+ tooltip?: Tooltip3D;
56
+ };
57
+ type ChartContext3D = {
58
+ config: ChartConfig;
59
+ camera: Camera3DInstance;
60
+ renderer: Renderer3D;
61
+ /** The marks of the chart, which the hover and the canvas read. */
62
+ scene: React.RefObject<Mark3D[]>;
63
+ repaint: () => void;
64
+ };
65
+ export declare function useChart3D(): ChartContext3D;
66
+ export type ChartContainer3DProps = {
67
+ /** The series of the chart: a label and a color per key, as in the chart of shadcn/ui. */
68
+ config: ChartConfig;
69
+ /**
70
+ * Where the camera starts, and where a reset returns it.
71
+ * @defaultValue { yaw: π/6, tilt: π/6 }
72
+ */
73
+ defaultView?: View3D;
74
+ /**
75
+ * The width of the view box the chart is drawn in.
76
+ * @defaultValue 640
77
+ */
78
+ width?: number;
79
+ /**
80
+ * The height of the view box the chart is drawn in.
81
+ * @defaultValue 400
82
+ */
83
+ height?: number;
84
+ /**
85
+ * Shows the label and the color of every config key below the chart.
86
+ * @defaultValue false
87
+ */
88
+ legend?: boolean;
89
+ /**
90
+ * How the marks of the chart are drawn: "canvas" suits many marks. The
91
+ * chart draws as SVG until the browser shows it has a canvas, and where it
92
+ * has none.
93
+ * @defaultValue "svg"
94
+ */
95
+ renderer?: Renderer3D;
96
+ /**
97
+ * Shows a button that lists the keyboard shortcuts of the chart; `?` lists them too.
98
+ * @defaultValue true
99
+ */
100
+ shortcuts?: boolean;
101
+ };
102
+ declare function ChartContainer3D({ id, config, defaultView, width, height, legend, renderer: requested, shortcuts, className, children, "aria-label": ariaLabel, ...props }: React.ComponentProps<"div"> & ChartContainer3DProps): React.JSX.Element;
103
+ /**
104
+ * The marks of a chart, drawn by the renderer of the container: as SVG
105
+ * elements, or on the canvas over the chart box. The hover reads them too.
106
+ */
107
+ declare function Marks3D({ marks }: {
108
+ marks: Mark3D[];
109
+ }): React.JSX.Element[] | null;
110
+ /** A label beside a mark: `at` in the units of the view box, `anchor` the end of the text that sits there. */
111
+ export type Label3D = {
112
+ key: string;
113
+ at: Point2D;
114
+ text: React.ReactNode;
115
+ anchor: "start" | "middle" | "end";
116
+ };
117
+ /**
118
+ * The labels of the marks of a chart, ringed by the background so that they
119
+ * read on the marks. Like the labels of the box, they are SVG with every renderer.
120
+ */
121
+ declare function Labels3D({ labels }: {
122
+ labels: Label3D[];
123
+ }): React.JSX.Element;
124
+ declare function ChartLegend3D({ config }: {
125
+ config: ChartConfig;
126
+ }): React.JSX.Element;
127
+ /**
128
+ * The walls of the chart box that face away from the camera, with their
129
+ * gridlines, and an axis with ticks on the outline of the box.
130
+ */
131
+ declare function Axes3D({ spec, world, format, titles }: {
132
+ spec: AxesSpec;
133
+ world: World;
134
+ format?: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>;
135
+ titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>;
136
+ }): React.JSX.Element;
137
+ /** A nice axis from `lo` to `hi` with about `count` ticks. */
138
+ declare function axis(lo: number, hi: number, count?: number): AxisSpec;
139
+ /** The linear map from `domain` to `range`. */
140
+ declare function linear([d0, d1]: number[], [r0, r1]: number[]): (value: number) => number;
141
+ /** The world box of `spec`: x from -1 to 1, y up from 1 to -1, z from -`depth` to `depth`. */
142
+ declare function worldBox(spec: AxesSpec, depth?: number): World;
143
+ /**
144
+ * `color` lit by the light from the upper left: the face that looks at it
145
+ * keeps the color, one that turns away gets darker. A CSS color-mix, so the
146
+ * shade follows the theme variables.
147
+ */
148
+ declare function shade(face: TransformedPoint<unknown>[], color: string): string;
149
+ /** The mean of the projected points, where a tooltip points at. */
150
+ declare function center(points: TransformedPoint<unknown>[]): Point2D;
151
+ /** The marks of a cube: its faces that look at the camera, shaded in `color`, each with `tooltip` on hover. */
152
+ declare function cubeMarks(id: string, faces: CubeFace[], color: string, tooltip: Tooltip3D): Mark3D[];
153
+ export type BarChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {
154
+ /** One entry per row of bars, with a value per series. */
155
+ data: T[];
156
+ /** The field that names each entry, such as "month". */
157
+ index: keyof T & string;
158
+ /**
159
+ * The fields that hold the series, one row of bars each.
160
+ * @defaultValue the keys of the chart config
161
+ */
162
+ keys?: string[];
163
+ /**
164
+ * The share of its cell a bar covers.
165
+ * @defaultValue 0.6
166
+ */
167
+ barSize?: number;
168
+ /** Formats the labels of the entries along x and the values along y. */
169
+ format?: {
170
+ x?: (label: string) => React.ReactNode;
171
+ y?: (value: number) => React.ReactNode;
172
+ };
173
+ /** The titles of the axes. */
174
+ titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>;
175
+ };
176
+ /**
177
+ * Bars on a floor: one row per entry of `data` along x, one per series
178
+ * along z, the value as the height. The series are the keys of the chart
179
+ * config unless `keys` names them.
180
+ */
181
+ export declare function BarChart3D<T extends Record<string, unknown>>({ data, index, keys, barSize, format, titles }: BarChart3DProps<T>): React.JSX.Element;
182
+ export type ScatterChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {
183
+ /** One entry per point. */
184
+ data: T[];
185
+ /** The field of the position along x. */
186
+ x: keyof T & string;
187
+ /** The field of the position along y, the height. */
188
+ y: keyof T & string;
189
+ /** The field of the position along z. */
190
+ z: keyof T & string;
191
+ /**
192
+ * The field whose value is the config key of the color of a point.
193
+ * @defaultValue the first key of the chart config for every point
194
+ */
195
+ series?: keyof T & string;
196
+ /**
197
+ * The radius of a point in the units of the view box.
198
+ * @defaultValue 4
199
+ */
200
+ radius?: number;
201
+ /** Formats the tick labels of each axis. */
202
+ format?: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>;
203
+ /** The titles of the axes. */
204
+ titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>;
205
+ };
206
+ /**
207
+ * Points in the chart box, at the fields `x`, `y` and `z` of each entry.
208
+ * `series` names the field whose value is the config key of the color.
209
+ */
210
+ export declare function ScatterChart3D<T extends Record<string, unknown>>({ data, x, y, z, series, radius, format, titles }: ScatterChart3DProps<T>): React.JSX.Element;
211
+ export type SurfaceChart3DProps = {
212
+ /** The heights on the grid, `data[row][column]`. */
213
+ data: number[][];
214
+ /**
215
+ * The data values the first and the last column (x) and row (z) stand for.
216
+ * @defaultValue the indices of the columns and rows
217
+ */
218
+ domain?: {
219
+ x?: [number, number];
220
+ z?: [number, number];
221
+ };
222
+ /**
223
+ * The config keys of the colors at the lowest and at the highest height.
224
+ * @defaultValue the first two keys of the chart config
225
+ */
226
+ colors?: [string, string];
227
+ /** Formats the tick labels of each axis. */
228
+ format?: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>;
229
+ /** The titles of the axes. */
230
+ titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>;
231
+ };
232
+ /**
233
+ * A surface over a grid: `data[row][column]` is the height, the columns run
234
+ * along x and the rows along z. The fill ramps from the first color of
235
+ * `colors` at the lowest height to the second at the highest; both are keys
236
+ * of the chart config, by default its first two.
237
+ */
238
+ export declare function SurfaceChart3D({ data, domain, colors, format, titles }: SurfaceChart3DProps): React.JSX.Element;
239
+ export type SankeyChart3DProps = {
240
+ /** One entry per flow. `source` and `target` are keys of the chart config, which names and colors the nodes. */
241
+ data: {
242
+ source: string;
243
+ target: string;
244
+ value: number;
245
+ }[];
246
+ /**
247
+ * The width of a node, as a share of the distance between two columns.
248
+ * @defaultValue 0.2
249
+ */
250
+ nodeWidth?: number;
251
+ /**
252
+ * The gap between two nodes of a column, as a share of the height.
253
+ * @defaultValue 0.05
254
+ */
255
+ nodePadding?: number;
256
+ /** Formats the values in the tooltip. */
257
+ format?: (value: number) => React.ReactNode;
258
+ };
259
+ /**
260
+ * Flows from left to right: every node a box in its column, as high as the
261
+ * larger of what flows in and what flows out, and every flow a band from node
262
+ * to node, as thick as its value, that turns from the color of its source to
263
+ * the color of its target.
264
+ */
265
+ export declare function SankeyChart3D({ data, nodeWidth, nodePadding, format }: SankeyChart3DProps): React.JSX.Element;
266
+ export { Axes3D, ChartContainer3D, ChartLegend3D, Labels3D, Marks3D, axis, center, cubeMarks, linear, shade, worldBox };
267
+ //# sourceMappingURL=index.d.ts.map