@niekes/charts-3d 0.2.0 → 0.4.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/NOTICE CHANGED
@@ -31,3 +31,36 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
31
31
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
32
32
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33
33
  SOFTWARE.
34
+
35
+ charts-3d includes code adapted from React Bits (https://reactbits.dev),
36
+ the Scanner component in docs/components/scanner.tsx, which draws the
37
+ animated background of the landing page of the docs. It stays in the docs,
38
+ which are not part of the npm package: React Bits is licensed under the
39
+ MIT + Commons Clause License Condition v1.0, which permits use as part of
40
+ an application but forbids selling or redistributing the components
41
+ themselves.
42
+
43
+ Copyright (c) 2026 David Haz
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining a copy
46
+ of this software and associated documentation files (the "Software"), to deal
47
+ in the Software without restriction, including without limitation the rights
48
+ to use, copy, modify, merge, publish, and distribute the Software as part of
49
+ an application, website, or product, subject to the following conditions:
50
+
51
+ The above copyright notice and this permission notice shall be included in all
52
+ copies or substantial portions of the Software.
53
+
54
+ Commons Clause Restriction
55
+
56
+ You may use this Software, including for any commercial purpose, so long as
57
+ you do not sell, sublicense, or redistribute the components themselves -
58
+ whether alone, in a bundle, or as a ported version.
59
+
60
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
61
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
62
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
63
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
64
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
65
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
66
+ SOFTWARE.
package/README.md CHANGED
@@ -35,7 +35,10 @@
35
35
  <tr style="background-color: #f6f8fa">
36
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
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">
38
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>
39
42
  </tr>
40
43
  </table>
41
44
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client"
2
2
  import * as React from "react";
3
- import { AxesSpec, AxisSpec, Camera3DInstance, Point2D, TransformedPoint } from "d3-3d";
3
+ import { AxesSpec, AxisSpec, Camera3DInstance, CubeFace, Point2D, Point3D, ShapeInstance, TransformedPoint } from "d3-3d";
4
4
  declare const THEMES: {
5
5
  readonly light: "";
6
6
  readonly dark: ".dark";
@@ -53,6 +53,18 @@ export type Mark3D = {
53
53
  stroke?: string;
54
54
  /** Shown while the pointer is over the mark. */
55
55
  tooltip?: Tooltip3D;
56
+ /**
57
+ * What the mark belongs to, such as a flow, or connects, such as a node.
58
+ * Pointing at a mark fades every mark and label that shares none of its
59
+ * groups, until the pointer leaves the chart; one without groups never fades.
60
+ */
61
+ groups?: string[];
62
+ };
63
+ /** The groups in focus, a store, so a change reaches the marks and labels without rendering the chart again. */
64
+ type Focus3D = {
65
+ get: () => string[] | undefined;
66
+ set: (groups?: string[]) => void;
67
+ subscribe: (listener: () => void) => () => void;
56
68
  };
57
69
  type ChartContext3D = {
58
70
  config: ChartConfig;
@@ -61,11 +73,36 @@ type ChartContext3D = {
61
73
  /** The marks of the chart, which the hover and the canvas read. */
62
74
  scene: React.RefObject<Mark3D[]>;
63
75
  repaint: () => void;
76
+ focus: Focus3D;
77
+ /** The time in ms a chart takes to glide into new data, 600 unless the container says. */
78
+ animationDuration?: number;
64
79
  };
65
80
  export declare function useChart3D(): ChartContext3D;
81
+ /** The actions a key triggers: each steps the camera, `help` opens the shortcut panel. */
82
+ export type KeyAction3D = "rotateLeft" | "rotateRight" | "rotateUp" | "rotateDown" | "panLeft" | "panRight" | "panUp" | "panDown" | "zoomIn" | "zoomOut" | "reset" | "help";
83
+ /** The gestures of the pointer: a drag turns the camera, with Space held it pans, Ctrl or ⌘ with the wheel zooms, a double click resets. */
84
+ export type Gesture3D = "dragRotate" | "dragPan" | "wheelZoom" | "doubleClickReset";
85
+ /**
86
+ * The shortcuts of a chart over their defaults, per action: `false` turns an
87
+ * action off, keys replace its keys and a label renames it in the shortcut
88
+ * panel, where the actions of one label share a row. Keys are written the way
89
+ * `aria-keyshortcuts` writes them, such as `"Shift+ArrowLeft"` or
90
+ * `"Control+Plus"`, and the panel shows the first.
91
+ */
92
+ export type Keymap3D = { [A in KeyAction3D]?: false | string[] | {
93
+ keys?: string[];
94
+ label?: string;
95
+ }; } & { [G in Gesture3D]?: false | {
96
+ label?: string;
97
+ }; };
66
98
  export type ChartContainer3DProps = {
67
99
  /** The series of the chart: a label and a color per key, as in the chart of shadcn/ui. */
68
100
  config: ChartConfig;
101
+ /**
102
+ * The time in ms a chart takes to glide into new data; 0 makes it jump.
103
+ * @defaultValue 600
104
+ */
105
+ animationDuration?: number;
69
106
  /**
70
107
  * Where the camera starts, and where a reset returns it.
71
108
  * @defaultValue { yaw: π/6, tilt: π/6 }
@@ -98,8 +135,33 @@ export type ChartContainer3DProps = {
98
135
  * @defaultValue true
99
136
  */
100
137
  shortcuts?: boolean;
138
+ /**
139
+ * Rebinds, renames or turns off the keys and the gestures of the chart, per
140
+ * action; `false` turns them all off and the chart stands still.
141
+ * @defaultValue {}
142
+ */
143
+ keymap?: Keymap3D | false;
144
+ /**
145
+ * The corner that shows the axes of the chart, turned with the camera; `false` hides them.
146
+ * @defaultValue "bottom-left"
147
+ */
148
+ gizmo?: "top-left" | "top-right" | "bottom-left" | "bottom-right" | false;
101
149
  };
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;
150
+ declare function ChartContainer3D({ id, config, defaultView, width, height, animationDuration, legend, renderer: requested, shortcuts, keymap, gizmo, className, children, "aria-label": ariaLabel, ...props }: React.ComponentProps<"div"> & ChartContainer3DProps): React.JSX.Element;
151
+ /**
152
+ * Eases a chart into new data: the numbers of `values` glide from the ones
153
+ * on screen to these over the animationDuration of the container. A key
154
+ * that is new starts at `enter`, or where it ends; a key that is gone goes
155
+ * at once. Without time, or with reduced motion, the numbers jump.
156
+ */
157
+ declare function useTween(values: Record<string, number>, enter?: number): Record<string, number>;
158
+ /**
159
+ * `spec` gliding into new data with the marks: the ends of every axis glide
160
+ * as `useTween` glides the numbers, where ends rounded from the numbers on
161
+ * screen would jump from one round number to the next, and the box with
162
+ * them. The ticks are those of `spec` that lie between the ends.
163
+ */
164
+ declare function useTweenAxes(spec: AxesSpec): AxesSpec;
103
165
  /**
104
166
  * The marks of a chart, drawn by the renderer of the container: as SVG
105
167
  * elements, or on the canvas over the chart box. The hover reads them too.
@@ -107,12 +169,37 @@ declare function ChartContainer3D({ id, config, defaultView, width, height, lege
107
169
  declare function Marks3D({ marks }: {
108
170
  marks: Mark3D[];
109
171
  }): React.JSX.Element[] | null;
172
+ /**
173
+ * A label beside a mark, at `at` in the units of the view box. `toward`, a
174
+ * unit vector, lays the label on that side of `at`, touching it, and slides
175
+ * it round `at` as the vector turns; without it, `anchor` is the end of the
176
+ * text that sits at `at`.
177
+ */
178
+ export type Label3D = {
179
+ key: string;
180
+ at: Point2D;
181
+ text: React.ReactNode;
182
+ anchor?: "start" | "middle" | "end";
183
+ toward?: Point2D;
184
+ /** The groups of the mark it names, so it fades with the mark out of focus. */
185
+ groups?: string[];
186
+ };
187
+ /**
188
+ * The labels of the marks of a chart, ringed by the background so that they
189
+ * read on the marks. Like the labels of the box, they are SVG with every renderer.
190
+ */
191
+ declare function Labels3D({ labels }: {
192
+ labels: Label3D[];
193
+ }): React.JSX.Element;
110
194
  declare function ChartLegend3D({ config }: {
111
195
  config: ChartConfig;
112
196
  }): React.JSX.Element;
113
197
  /**
114
198
  * The walls of the chart box that face away from the camera, with their
115
- * gridlines, and an axis with ticks on the outline of the box.
199
+ * gridlines, the line of every axis along its edge with the mark of each of
200
+ * its ticks, and the labels of every axis on each of its four edges. Only the
201
+ * edge the axis sits on shows them, so when the axis moves to another edge,
202
+ * its line, its marks and its labels fade from one to the other.
116
203
  */
117
204
  declare function Axes3D({ spec, world, format, titles }: {
118
205
  spec: AxesSpec;
@@ -122,10 +209,21 @@ declare function Axes3D({ spec, world, format, titles }: {
122
209
  }): React.JSX.Element;
123
210
  /** A nice axis from `lo` to `hi` with about `count` ticks. */
124
211
  declare function axis(lo: number, hi: number, count?: number): AxisSpec;
212
+ /**
213
+ * The axis `spec` with its domain widened by half a `cell` on each side, so
214
+ * the box keeps room between the outermost data and its walls. The ticks stay
215
+ * where they were, on the data.
216
+ */
217
+ declare function pad(spec: AxisSpec, cell: number): AxisSpec;
125
218
  /** The linear map from `domain` to `range`. */
126
219
  declare function linear([d0, d1]: number[], [r0, r1]: number[]): (value: number) => number;
127
220
  /** The world box of `spec`: x from -1 to 1, y up from 1 to -1, z from -`depth` to `depth`. */
128
221
  declare function worldBox(spec: AxesSpec, depth?: number): World;
222
+ /**
223
+ * Hands the projection its accessors into the world box, so every chart maps
224
+ * its shapes onto the screen the same way.
225
+ */
226
+ declare function intoWorld<Datum extends Point3D, T extends ShapeInstance<Datum>>(projection: T, world: World): T;
129
227
  /**
130
228
  * `color` lit by the light from the upper left: the face that looks at it
131
229
  * keeps the color, one that turns away gets darker. A CSS color-mix, so the
@@ -134,6 +232,8 @@ declare function worldBox(spec: AxesSpec, depth?: number): World;
134
232
  declare function shade(face: TransformedPoint<unknown>[], color: string): string;
135
233
  /** The mean of the projected points, where a tooltip points at. */
136
234
  declare function center(points: TransformedPoint<unknown>[]): Point2D;
235
+ /** The marks of a cube: its faces that look at the camera, shaded in `color`, each with `tooltip` on hover. */
236
+ declare function cubeMarks(id: string, faces: CubeFace[], color: string, tooltip: Tooltip3D): Mark3D[];
137
237
  export type BarChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {
138
238
  /** One entry per row of bars, with a value per series. */
139
239
  data: T[];
@@ -197,6 +297,8 @@ export type SurfaceChart3DProps = {
197
297
  data: number[][];
198
298
  /**
199
299
  * The data values the first and the last column (x) and row (z) stand for.
300
+ * The chart keeps half a cell between the grid and the walls of its box; a
301
+ * domain given here names the box exactly, without that room.
200
302
  * @defaultValue the indices of the columns and rows
201
303
  */
202
304
  domain?: {
@@ -220,5 +322,32 @@ export type SurfaceChart3DProps = {
220
322
  * of the chart config, by default its first two.
221
323
  */
222
324
  export declare function SurfaceChart3D({ data, domain, colors, format, titles }: SurfaceChart3DProps): React.JSX.Element;
223
- export { Axes3D, ChartContainer3D, ChartLegend3D, Marks3D, axis, center, linear, shade, worldBox };
325
+ export type SankeyChart3DProps = {
326
+ /** One entry per flow. `source` and `target` are keys of the chart config, which names and colors the nodes. */
327
+ data: {
328
+ source: string;
329
+ target: string;
330
+ value: number;
331
+ }[];
332
+ /**
333
+ * The width of a node, as a share of the distance between two columns.
334
+ * @defaultValue 0.2
335
+ */
336
+ nodeWidth?: number;
337
+ /**
338
+ * The gap between two nodes of a column, as a share of the height.
339
+ * @defaultValue 0.05
340
+ */
341
+ nodePadding?: number;
342
+ /** Formats the values in the tooltip. */
343
+ format?: (value: number) => React.ReactNode;
344
+ };
345
+ /**
346
+ * Flows from left to right: every node a box in its column, as high as the
347
+ * larger of what flows in and what flows out, and every flow a band from node
348
+ * to node, as thick as its value, that turns from the color of its source to
349
+ * the color of its target.
350
+ */
351
+ export declare function SankeyChart3D({ data, nodeWidth, nodePadding, format }: SankeyChart3DProps): React.JSX.Element;
352
+ export { Axes3D, ChartContainer3D, ChartLegend3D, Labels3D, Marks3D, axis, center, cubeMarks, intoWorld, linear, pad, shade, useTween, useTweenAxes, worldBox };
224
353
  //# sourceMappingURL=index.d.ts.map