@niekes/charts-3d 0.0.0-stage → 0.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.
- package/LICENSE +27 -0
- package/NOTICE +33 -0
- package/README.md +85 -2
- package/dist/index.d.ts +224 -0
- package/dist/index.js +875 -0
- package/dist/index.js.map +1 -0
- package/package.json +112 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../lib/utils.ts","../registry/new-york/ui/chart-3d.tsx","../registry/new-york/ui/bar-chart-3d.tsx","../registry/new-york/ui/scatter-chart-3d.tsx","../registry/new-york/ui/surface-chart-3d.tsx"],"sourcesContent":["import { clsx, type ClassValue } from \"clsx\"\nimport { twMerge } from \"tailwind-merge\"\n\nexport function cn(...inputs: ClassValue[]) {\n return twMerge(clsx(inputs))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { nice, ticks } from \"d3-array\"\nimport {\n axes3D,\n camera3D,\n normal,\n type AxesSpec,\n type AxisEdge,\n type AxisSpec,\n type Camera3DInstance,\n type Point2D,\n type TransformedPoint,\n} from \"d3-3d\"\nimport { KeyboardIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n// The same shape as the ChartConfig of shadcn's chart, so one config drives\n// a 2D and a 3D chart side by side.\nconst THEMES = { light: \"\", dark: \".dark\" } as const\n\nexport type ChartConfig = {\n [k in string]: {\n label?: React.ReactNode\n icon?: React.ComponentType\n } & (\n | { color?: string; theme?: never }\n | { color?: never; theme: Record<keyof typeof THEMES, string> }\n )\n}\n\n/** How the camera looks at the chart box, angles in radians. */\nexport type View3D = {\n yaw: number\n /** The angle above the floor the camera looks down from. */\n tilt: number\n zoom?: number\n /** How far the chart is moved, in the units of the view box. */\n pan?: Point2D\n /** The distance of the eye in box units; Infinity, the default, is orthographic. */\n perspective?: number\n}\n\n/** How the marks of a chart are drawn. The box, its labels, the tooltip and the legend are always SVG and HTML. */\nexport type Renderer3D = \"svg\" | \"canvas\"\n\n/** Maps data values to the world box, which spans -1 to 1 on every axis, y up. */\nexport type World = Record<keyof AxesSpec, (value: number) => number>\n\nexport type Tooltip3D = {\n /** The anchor in the units of the view box. */\n at: Point2D\n title?: React.ReactNode\n items: { label: React.ReactNode; value: React.ReactNode; color?: string }[]\n}\n\n/** One shape of a chart, projected, in paint order: a polygon, or a circle of radius `r` around its one point. */\nexport type Mark3D = {\n /** Stable across renders, so React moves the shape instead of redrawing it. */\n key: string\n /** The corners of a polygon, or the center of a circle, in the units of the view box. */\n points: Point2D[]\n r?: number\n /** A CSS color, such as the result of `shade` or `var(--color-x)`. */\n fill: string\n /** The ring around a circle, a CSS color. */\n stroke?: string\n /** Shown while the pointer is over the mark. */\n tooltip?: Tooltip3D\n}\n\ntype ChartContext3D = {\n config: ChartConfig\n camera: Camera3DInstance\n renderer: Renderer3D\n /** The marks of the chart, which the hover and the canvas read. */\n scene: React.RefObject<Mark3D[]>\n repaint: () => void\n}\n\nconst Chart3DContext = React.createContext<ChartContext3D | null>(null)\n\nexport function useChart3D() {\n const context = React.useContext(Chart3DContext)\n if (!context) {\n throw new Error(\"useChart3D must be used within a <ChartContainer3D />\")\n }\n return context\n}\n\nconst DRAG = Math.PI / 230\nconst KEY_STEP = Math.PI / 36\nconst PAN_STEP = 20\nconst ZOOM_STEP = 1.2\nconst CLICK_DISTANCE = 4\n\n/** A step of the camera: turned by `yaw` and `tilt`, moved by `pan`, zoomed by the factor `zoom`, or reset. */\ntype Move = { yaw?: number; tilt?: number; pan?: Point2D; zoom?: number; reset?: boolean }\n\n// The shortcuts of a chart: the keys of a row move the camera, and the\n// shortcut panel lists every row, so the two never disagree.\nconst SHORTCUTS: { hint: string[]; label: string; keys?: Record<string, Move> }[] = [\n { hint: [\"Drag\"], label: \"Rotate\" },\n {\n hint: [\"←\", \"→\", \"↑\", \"↓\"],\n label: \"Rotate\",\n keys: {\n ArrowLeft: { yaw: -KEY_STEP },\n ArrowRight: { yaw: KEY_STEP },\n ArrowUp: { tilt: -KEY_STEP },\n ArrowDown: { tilt: KEY_STEP },\n },\n },\n { hint: [\"Space\", \"Drag\"], label: \"Pan\" },\n {\n hint: [\"Shift\", \"←\", \"→\", \"↑\", \"↓\"],\n label: \"Pan\",\n keys: {\n \"Shift+ArrowLeft\": { pan: { x: -PAN_STEP, y: 0 } },\n \"Shift+ArrowRight\": { pan: { x: PAN_STEP, y: 0 } },\n \"Shift+ArrowUp\": { pan: { x: 0, y: -PAN_STEP } },\n \"Shift+ArrowDown\": { pan: { x: 0, y: PAN_STEP } },\n },\n },\n {\n hint: [\"+\", \"−\"],\n label: \"Zoom\",\n keys: { \"+\": { zoom: ZOOM_STEP }, \"=\": { zoom: ZOOM_STEP }, \"-\": { zoom: 1 / ZOOM_STEP } },\n },\n { hint: [\"Ctrl\", \"Scroll\"], label: \"Zoom\" },\n { hint: [\"0\"], label: \"Reset\", keys: { \"0\": { reset: true } } },\n { hint: [\"Double-click\"], label: \"Reset\" },\n { hint: [\"?\"], label: \"Shortcuts\" },\n]\nconst KEYS: Record<string, Move | undefined> = Object.assign({}, ...SHORTCUTS.map((s) => s.keys))\n\nexport type ChartContainer3DProps = {\n /** The series of the chart: a label and a color per key, as in the chart of shadcn/ui. */\n config: ChartConfig\n /**\n * Where the camera starts, and where a reset returns it.\n * @defaultValue { yaw: π/6, tilt: π/6 }\n */\n defaultView?: View3D\n /**\n * The width of the view box the chart is drawn in.\n * @defaultValue 640\n */\n width?: number\n /**\n * The height of the view box the chart is drawn in.\n * @defaultValue 400\n */\n height?: number\n /**\n * Shows the label and the color of every config key below the chart.\n * @defaultValue false\n */\n legend?: boolean\n /**\n * How the marks of the chart are drawn: \"canvas\" suits many marks. The\n * chart draws as SVG until the browser shows it has a canvas, and where it\n * has none.\n * @defaultValue \"svg\"\n */\n renderer?: Renderer3D\n /**\n * Shows a button that lists the keyboard shortcuts of the chart; `?` lists them too.\n * @defaultValue true\n */\n shortcuts?: boolean\n}\n\nfunction ChartContainer3D({\n id,\n config,\n defaultView = { yaw: Math.PI / 6, tilt: Math.PI / 6 },\n width = 640,\n height = 400,\n legend = false,\n renderer: requested = \"svg\",\n shortcuts = true,\n className,\n children,\n \"aria-label\": ariaLabel = \"3D chart. Drag to rotate it, press ? for all shortcuts.\",\n ...props\n}: React.ComponentProps<\"div\"> & ChartContainer3DProps) {\n const uniqueId = React.useId()\n const chartId = `chart-${id || uniqueId.replace(/:/g, \"\")}`\n const [tooltip, setTooltip] = React.useState<Tooltip3D | null>(null)\n const { scene, renderer, canvas, repaint, hover, leave } = useScene(\n requested,\n width,\n height,\n setTooltip\n )\n const { view, orbiting, handlers } = useOrbit(defaultView, width, leave, hover)\n const camera = useCamera(view, width, height)\n const context = React.useMemo(\n () => ({ config, camera, renderer, scene, repaint }),\n [config, camera, renderer, repaint]\n )\n\n return (\n <div\n data-slot=\"chart-3d\"\n data-chart={chartId}\n className={cn(\"relative w-full text-xs\", className)}\n {...props}\n >\n <ChartStyle id={chartId} config={config} />\n <svg\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n aria-label={ariaLabel}\n tabIndex={0}\n className=\"block h-auto w-full cursor-grab touch-none rounded-lg outline-hidden select-none focus-visible:ring-[3px] focus-visible:ring-ring/50 active:cursor-grabbing\"\n data-orbiting={orbiting}\n onPointerLeave={leave}\n {...handlers}\n >\n <Chart3DContext.Provider value={context}>{children}</Chart3DContext.Provider>\n </svg>\n <ChartCanvas3D renderer={renderer} canvas={canvas} width={width} height={height} />\n <ChartTooltip3D tooltip={tooltip} width={width} height={height} />\n {shortcuts && <ChartShortcuts3D />}\n {legend && <ChartLegend3D config={config} />}\n </div>\n )\n}\n\n/**\n * The marks of the chart and what reads them: the renderer that draws them,\n * the canvas it paints them on and the hover that shows their tooltips.\n */\nfunction useScene(\n requested: Renderer3D,\n width: number,\n height: number,\n setTooltip: (tooltip: Tooltip3D | null) => void\n) {\n const scene = React.useRef<Mark3D[]>([])\n const renderer = useRenderer(requested)\n const { canvas, repaint } = useCanvas(scene, width)\n const { hover, leave } = useHover(scene, width, height, setTooltip)\n return { scene, renderer, canvas, repaint, hover, leave }\n}\n\n/** The camera of a view. The shapes of the chart hang on it, so a new view re-projects them all. */\nfunction useCamera(view: View3D, width: number, height: number) {\n return React.useMemo(\n () =>\n camera3D()\n .origin({ x: width / 2 + (view.pan?.x ?? 0), y: height / 2 + (view.pan?.y ?? 0) })\n .scale(Math.min(width, height) * 0.3 * (view.zoom ?? 1))\n .perspective(view.perspective ?? Infinity)\n .rotateY(view.yaw)\n .rotateX(-view.tilt),\n [view, width, height]\n )\n}\n\n/** `view` moved by one step. The tilt stops at the zenith and the nadir, the zoom at 1/4 and 8. */\nfunction moved(view: View3D, move: Move, initial: View3D): View3D {\n if (move.reset) return initial\n const step = { yaw: 0, tilt: 0, zoom: 1, pan: { x: 0, y: 0 }, ...move }\n const pan = view.pan ?? { x: 0, y: 0 }\n const clamp = (lo: number, hi: number, value: number) => Math.max(lo, Math.min(hi, value))\n return {\n ...view,\n yaw: view.yaw + step.yaw,\n tilt: clamp(-Math.PI / 2, Math.PI / 2, view.tilt + step.tilt),\n zoom: clamp(0.25, 8, (view.zoom ?? 1) * step.zoom),\n pan: { x: pan.x + step.pan.x, y: pan.y + step.pan.y },\n }\n}\n\n/**\n * The view of the camera, and the handlers that move it: a drag turns it,\n * or pans it while Space is held, the keys of `SHORTCUTS` step it, Ctrl or ⌘\n * with the wheel zooms it and a double click resets it. `orbiting` is true\n * while the camera turns. `onDragStart` runs when a press becomes a drag,\n * `onHover` on a move without one.\n */\nfunction useOrbit(\n defaultView: View3D,\n width: number,\n onDragStart: () => void,\n onHover: (e: React.PointerEvent<SVGSVGElement>) => void\n) {\n const [view, setView] = React.useState(defaultView)\n const [orbiting, setOrbiting] = React.useState(false)\n const drag = React.useRef<Point2D & { moved: boolean }>(null)\n const space = React.useRef(false)\n const ref = useWheelZoom(setView)\n const move = (step: Move) => setView((v) => moved(v, step, defaultView))\n const release = () => {\n drag.current = null\n setOrbiting(false)\n }\n\n const handlers: React.SVGProps<SVGSVGElement> = {\n ref,\n onPointerDown: (e) => {\n drag.current = { x: e.clientX, y: e.clientY, moved: false }\n },\n onPointerMove: (e) => {\n const d = drag.current\n if (!d) return onHover(e)\n const dx = e.clientX - d.x\n const dy = e.clientY - d.y\n // A press that wanders a few pixels is still a click on a bar.\n if (!d.moved && Math.hypot(dx, dy) < CLICK_DISTANCE) return\n if (!d.moved) {\n e.currentTarget.setPointerCapture(e.pointerId)\n onDragStart()\n }\n drag.current = { x: e.clientX, y: e.clientY, moved: true }\n const k = width / e.currentTarget.getBoundingClientRect().width\n setOrbiting(!space.current)\n move(space.current ? { pan: { x: dx * k, y: dy * k } } : { yaw: dx * DRAG, tilt: dy * DRAG })\n },\n onPointerUp: release,\n onPointerCancel: release,\n onDoubleClick: () => move({ reset: true }),\n onKeyDown: (e) => {\n // Held on the chart, Space pans a drag instead of scrolling the page.\n if (e.key === \" \") space.current = true\n const step = (e.shiftKey && KEYS[`Shift+${e.key}`]) || KEYS[e.key]\n if (!step && e.key !== \" \") return\n e.preventDefault()\n if (!step) return\n setOrbiting(Boolean(step.yaw || step.tilt))\n move(step)\n },\n onKeyUp: (e) => {\n if (e.key === \" \") space.current = false\n setOrbiting(false)\n },\n }\n\n return { view, orbiting, handlers }\n}\n\n/**\n * A ref for the svg that zooms the view with Ctrl or ⌘ and the wheel, which\n * is also how a trackpad pinches. The wheel alone still scrolls the page.\n */\nfunction useWheelZoom(setView: React.Dispatch<React.SetStateAction<View3D>>) {\n // React listens to the wheel passively, and only a listener that is not\n // passive can keep the browser from zooming the page.\n return React.useCallback(\n (svg: SVGSVGElement | null) => {\n const onWheel = (e: WheelEvent) => {\n if (!e.ctrlKey && !e.metaKey) return\n e.preventDefault()\n setView((v) => moved(v, { zoom: 2 ** (-e.deltaY / 200) }, v))\n }\n svg?.addEventListener(\"wheel\", onWheel, { passive: false })\n return () => svg?.removeEventListener(\"wheel\", onWheel)\n },\n [setView]\n )\n}\n\n/**\n * The tooltip of the mark under the pointer, the one painted last. `hover`\n * sets it only when the pointer moves onto another mark, so a move within\n * one does not render the chart again.\n */\nfunction useHover(\n scene: React.RefObject<Mark3D[]>,\n width: number,\n height: number,\n setTooltip: (tooltip: Tooltip3D | null) => void\n) {\n const hovered = React.useRef<Mark3D>(undefined)\n const show = (mark?: Mark3D) => {\n if (mark?.key === hovered.current?.key) return\n hovered.current = mark\n setTooltip(mark?.tooltip ?? null)\n }\n\n return {\n hover: (e: React.PointerEvent<SVGSVGElement>) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const at = {\n x: ((e.clientX - rect.left) / rect.width) * width,\n y: ((e.clientY - rect.top) / rect.height) * height,\n }\n show(hit(scene.current, at))\n },\n leave: () => show(undefined),\n }\n}\n\n/** The topmost mark under `at`: the last one painted that holds it. */\nfunction hit(marks: Mark3D[], at: Point2D) {\n for (let i = marks.length - 1; i >= 0; i -= 1) {\n const { points, r } = marks[i]\n const holds =\n r === undefined ? inside(points, at) : Math.hypot(points[0].x - at.x, points[0].y - at.y) <= r\n if (holds) return marks[i]\n }\n}\n\n/** Whether `at` lies inside `polygon`: a ray from it crosses an odd number of its edges. */\nfunction inside(polygon: Point2D[], at: Point2D) {\n let odd = false\n for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i, i += 1) {\n const a = polygon[i]\n const b = polygon[j]\n if (a.y > at.y !== b.y > at.y && at.x < ((b.x - a.x) * (at.y - a.y)) / (b.y - a.y) + a.x) {\n odd = !odd\n }\n }\n return odd\n}\n\n/**\n * The renderer the chart draws with: SVG on the server and in the first\n * render on the client, then the requested one if the browser has it.\n */\nfunction useRenderer(requested: Renderer3D) {\n const [renderer, setRenderer] = React.useState<Renderer3D>(\"svg\")\n React.useEffect(() => {\n // A canvas of its own, as one that gave out a context cannot give another.\n const canvas = requested === \"canvas\" && document.createElement(\"canvas\").getContext(\"2d\")\n setRenderer(canvas ? \"canvas\" : \"svg\")\n }, [requested])\n return renderer\n}\n\n/**\n * A ref for the canvas of the marks, and the repaint that paints them: on new\n * marks, when the canvas changes its size and when the theme changes. A color\n * resolves on the canvas itself, inside the chart, so the `--color-*` apply.\n */\nfunction useCanvas(scene: React.RefObject<Mark3D[]>, width: number) {\n const element = React.useRef<HTMLCanvasElement>(null)\n const colors = React.useRef(new Map<string, string>())\n\n const repaint = React.useCallback(() => {\n const canvas = element.current\n if (!canvas) return\n paint(canvas, scene.current, width, (css) => {\n let color = colors.current.get(css)\n if (color === undefined) {\n canvas.style.color = css\n color = getComputedStyle(canvas).color\n colors.current.set(css, color)\n }\n return color\n })\n }, [scene, width])\n\n const canvas = React.useCallback(\n (node: HTMLCanvasElement | null) => {\n element.current = node\n if (!node) return\n repaint()\n const resize = new ResizeObserver(repaint)\n resize.observe(node)\n // ponytail: watches the theme on <html> only, as the class `.dark` of THEMES does.\n const theme = new MutationObserver(() => {\n colors.current.clear()\n repaint()\n })\n theme.observe(document.documentElement, { attributeFilter: [\"class\", \"style\"] })\n return () => {\n element.current = null\n resize.disconnect()\n theme.disconnect()\n }\n },\n [repaint]\n )\n\n return { canvas, repaint }\n}\n\n/** Paints `marks` on `canvas`, from the view box of `width` to the pixels of the canvas. */\nfunction paint(\n canvas: HTMLCanvasElement,\n marks: Mark3D[],\n width: number,\n color: (css: string) => string\n) {\n canvas.width = Math.round(canvas.clientWidth * devicePixelRatio)\n canvas.height = Math.round(canvas.clientHeight * devicePixelRatio)\n const ctx = canvas.getContext(\"2d\")\n if (!ctx) return\n const scale = canvas.width / width\n ctx.setTransform(scale, 0, 0, scale, 0, 0)\n ctx.lineJoin = \"round\"\n\n for (const { points, r, fill, stroke } of marks) {\n ctx.beginPath()\n if (r === undefined) {\n for (const p of points) ctx.lineTo(p.x, p.y)\n ctx.closePath()\n } else {\n ctx.arc(points[0].x, points[0].y, r, 0, 2 * Math.PI)\n }\n ctx.fillStyle = color(fill)\n ctx.fill()\n // A polygon is outlined in its own color, which closes the seams to its neighbours.\n const outline = r === undefined ? fill : stroke\n if (!outline) continue\n ctx.strokeStyle = color(outline)\n ctx.lineWidth = r === undefined ? 0.5 : 1\n ctx.stroke()\n }\n}\n\n/** The canvas over the chart box that the marks are painted on, if the chart draws on one. */\nfunction ChartCanvas3D({\n renderer,\n canvas,\n width,\n height,\n}: {\n renderer: Renderer3D\n canvas: React.Ref<HTMLCanvasElement>\n width: number\n height: number\n}) {\n if (renderer !== \"canvas\") return null\n\n return (\n <canvas\n ref={canvas}\n className=\"pointer-events-none absolute top-0 left-0 w-full\"\n style={{ aspectRatio: `${width} / ${height}` }}\n />\n )\n}\n\n/**\n * The marks of a chart, drawn by the renderer of the container: as SVG\n * elements, or on the canvas over the chart box. The hover reads them too.\n */\nfunction Marks3D({ marks }: { marks: Mark3D[] }) {\n const { renderer, scene, repaint } = useChart3D()\n React.useLayoutEffect(() => {\n scene.current = marks\n repaint()\n })\n\n if (renderer === \"canvas\") return null\n return marks.map(({ key, points, r, fill, stroke }) =>\n r === undefined ? (\n <path\n key={key}\n d={`M${points.map((p) => `${+p.x.toFixed(2)},${+p.y.toFixed(2)}`).join(\"L\")}Z`}\n fill={fill}\n stroke={fill}\n strokeWidth={0.5}\n strokeLinejoin=\"round\"\n />\n ) : (\n <circle\n key={key}\n cx={points[0].x}\n cy={points[0].y}\n r={r}\n fill={fill}\n stroke={stroke}\n strokeWidth={stroke ? 1 : undefined}\n />\n )\n )\n}\n\nfunction ChartStyle({ id, config }: { id: string; config: ChartConfig }) {\n const colorConfig = Object.entries(config).filter(([, c]) => c.theme || c.color)\n\n if (!colorConfig.length) {\n return null\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: Object.entries(THEMES)\n .map(\n ([theme, prefix]) => `\n${prefix} [data-chart=${id}] {\n${colorConfig\n .map(([key, item]) => {\n const color = item.theme?.[theme as keyof typeof item.theme] || item.color\n return color ? ` --color-${key}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n )\n .join(\"\\n\"),\n }}\n />\n )\n}\n\nfunction ChartTooltip3D({\n tooltip,\n width,\n height,\n}: {\n tooltip: Tooltip3D | null\n width: number\n height: number\n}) {\n if (!tooltip) return null\n\n return (\n <div\n className=\"pointer-events-none absolute z-10 grid min-w-32 -translate-x-1/2 -translate-y-[calc(100%+0.5rem)] gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl\"\n style={{ left: `${(tooltip.at.x / width) * 100}%`, top: `${(tooltip.at.y / height) * 100}%` }}\n >\n {tooltip.title && <div className=\"font-medium\">{tooltip.title}</div>}\n {tooltip.items.map((item, i) => (\n <div key={i} className=\"flex items-center gap-2\">\n {item.color && (\n <span className=\"size-2.5 shrink-0 rounded-[2px]\" style={{ background: item.color }} />\n )}\n <span className=\"text-muted-foreground\">{item.label}</span>\n <span className=\"ml-auto font-mono font-medium text-foreground tabular-nums\">\n {typeof item.value === \"number\" ? item.value.toLocaleString() : item.value}\n </span>\n </div>\n ))}\n </div>\n )\n}\n\n/**\n * A button in the corner of the chart that lists `SHORTCUTS`. `?` on the\n * chart opens and closes the list, Escape closes it.\n */\nfunction ChartShortcuts3D() {\n const [open, setOpen] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n\n React.useEffect(() => {\n const chart = ref.current?.parentElement\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"?\") setOpen((o) => !o)\n if (e.key === \"Escape\") setOpen(false)\n }\n chart?.addEventListener(\"keydown\", onKeyDown)\n return () => chart?.removeEventListener(\"keydown\", onKeyDown)\n }, [])\n\n return (\n <div ref={ref} className=\"absolute top-2 right-2 z-10 flex flex-col items-end gap-1\">\n <button\n type=\"button\"\n aria-label=\"Keyboard shortcuts\"\n aria-expanded={open}\n onClick={() => setOpen((o) => !o)}\n className=\"inline-flex size-7 items-center justify-center rounded-md text-muted-foreground outline-none hover:bg-accent hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 [&_svg]:size-4\"\n >\n <KeyboardIcon />\n </button>\n {open && (\n <div className=\"grid grid-cols-[auto_1fr] items-center gap-x-3 gap-y-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-2 shadow-xl\">\n {SHORTCUTS.map(({ hint, label }, i) => (\n <React.Fragment key={i}>\n <span className=\"flex gap-1\">\n {hint.map((key) => (\n <kbd\n key={key}\n className=\"pointer-events-none inline-flex h-5 min-w-5 items-center justify-center rounded-sm bg-muted px-1 font-sans text-xs font-medium text-muted-foreground select-none\"\n >\n {key}\n </kbd>\n ))}\n </span>\n <span className=\"text-muted-foreground\">{label}</span>\n </React.Fragment>\n ))}\n </div>\n )}\n </div>\n )\n}\n\nfunction ChartLegend3D({ config }: { config: ChartConfig }) {\n return (\n <div className=\"flex items-center justify-center gap-4 pt-3\">\n {Object.entries(config).map(([key, item]) => (\n <div key={key} className=\"flex items-center gap-1.5\">\n {item.icon ? (\n <item.icon />\n ) : (\n <span className=\"size-2 rounded-[2px]\" style={{ background: `var(--color-${key})` }} />\n )}\n {item.label ?? key}\n </div>\n ))}\n </div>\n )\n}\n\n/**\n * The walls of the chart box that face away from the camera, with their\n * gridlines, and an axis with ticks on the outline of the box.\n */\nfunction Axes3D({\n spec,\n world,\n format = {},\n titles = {},\n}: {\n spec: AxesSpec\n world: World\n format?: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>\n titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>\n}) {\n const { camera } = useChart3D()\n const box = axes3D()\n .camera(camera)\n .x((p) => world.x(p.x))\n .y((p) => world.y(p.y))\n .z((p) => world.z(p.z))\n\n return (\n <g data-slot=\"chart-3d-axes\">\n {box\n .data(spec)\n .filter((wall) => !wall.ccw)\n .map((wall) => (\n <path\n key={`${wall.axis}${wall.side}`}\n d={box.draw(wall)}\n className=\"fill-muted/40 stroke-border\"\n strokeWidth={0.75}\n />\n ))}\n {box.axes(spec).map((edge) => (\n <AxisEdge3D\n key={edge.axis}\n edge={edge}\n format={format[edge.axis] ?? String}\n title={titles[edge.axis]}\n />\n ))}\n </g>\n )\n}\n\n/**\n * The tick labels of one axis on the outline of the box, pushed away from the\n * box along the normal of the edge, and the title of the axis further out.\n */\nfunction AxisEdge3D({\n edge,\n format,\n title,\n}: {\n edge: AxisEdge\n format: (value: number) => React.ReactNode\n title?: React.ReactNode\n}) {\n // An axis without ticks, such as the rows of an empty chart, has nothing to label.\n if (!edge.length) return null\n const { normal: n } = edge\n const start = edge[0].projected\n const end = edge[edge.length - 1].projected\n const anchor = n.x > 0.3 ? \"start\" : n.x < -0.3 ? \"end\" : \"middle\"\n\n // The labels jump to another edge as the camera turns, so they fade out\n // while it turns and fade back in a moment after it rests.\n return (\n <g className=\"transition-opacity delay-300 duration-300 in-data-[orbiting=true]:opacity-0 in-data-[orbiting=true]:delay-0 in-data-[orbiting=true]:duration-150\">\n {edge.map((tick, i) => (\n <text\n key={i}\n x={tick.projected.x + n.x * 10}\n y={tick.projected.y + n.y * 10}\n textAnchor={anchor}\n dominantBaseline=\"central\"\n className=\"fill-muted-foreground text-[10px]\"\n >\n {format(tick[edge.axis])}\n </text>\n ))}\n {title && (\n <text\n x={(start.x + end.x) / 2 + n.x * 44}\n y={(start.y + end.y) / 2 + n.y * 44}\n textAnchor={anchor}\n dominantBaseline=\"central\"\n className=\"fill-foreground font-medium\"\n >\n {title}\n </text>\n )}\n </g>\n )\n}\n\n/** A nice axis from `lo` to `hi` with about `count` ticks. */\nfunction axis(lo: number, hi: number, count = 5): AxisSpec {\n const [start, stop] = nice(lo, lo === hi ? hi + 1 : hi, count)\n return { domain: [start, stop], ticks: ticks(start, stop, count) }\n}\n\n/** The linear map from `domain` to `range`. */\nfunction linear([d0, d1]: number[], [r0, r1]: number[]) {\n return (value: number) => r0 + ((value - d0) / (d1 - d0 || 1)) * (r1 - r0)\n}\n\n/** The world box of `spec`: x from -1 to 1, y up from 1 to -1, z from -`depth` to `depth`. */\nfunction worldBox(spec: AxesSpec, depth = 1): World {\n return {\n x: linear(spec.x.domain, [-1, 1]),\n y: linear(spec.y.domain, [1, -1]),\n z: linear(spec.z.domain, [-depth, depth]),\n }\n}\n\n// From the upper left, towards the viewer, in view space where y points down.\nconst LIGHT = { x: -0.4, y: -0.8, z: 0.44 }\n\n/**\n * `color` lit by the light from the upper left: the face that looks at it\n * keeps the color, one that turns away gets darker. A CSS color-mix, so the\n * shade follows the theme variables.\n */\nfunction shade(face: TransformedPoint<unknown>[], color: string) {\n const n = normal(face.map((p) => p.rotated))\n // The normal of the side the camera sees, whichever way the face winds.\n const side = n.z < 0 ? -1 : 1\n const light = Math.max(0, side * (n.x * LIGHT.x + n.y * LIGHT.y + n.z * LIGHT.z))\n return `color-mix(in oklch, ${color} ${Math.round(65 + 35 * light)}%, black)`\n}\n\n/** The mean of the projected points, where a tooltip points at. */\nfunction center(points: TransformedPoint<unknown>[]): Point2D {\n const sum = points.reduce((s, p) => ({ x: s.x + p.projected.x, y: s.y + p.projected.y }), {\n x: 0,\n y: 0,\n })\n return { x: sum.x / points.length, y: sum.y / points.length }\n}\n\nexport { ChartContainer3D, ChartLegend3D, Axes3D, Marks3D, axis, linear, worldBox, shade, center }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { box, cubes3D, sort, type AxesSpec, type CubeFace } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n center,\n shade,\n useChart3D,\n worldBox,\n type Mark3D,\n type World,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type BarChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per row of bars, with a value per series. */\n data: T[]\n /** The field that names each entry, such as \"month\". */\n index: keyof T & string\n /**\n * The fields that hold the series, one row of bars each.\n * @defaultValue the keys of the chart config\n */\n keys?: string[]\n /**\n * The share of its cell a bar covers.\n * @defaultValue 0.6\n */\n barSize?: number\n /** Formats the labels of the entries along x and the values along y. */\n format?: { x?: (label: string) => React.ReactNode; y?: (value: number) => React.ReactNode }\n /** The titles of the axes. */\n titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>\n}\n\n/**\n * Bars on a floor: one row per entry of `data` along x, one per series\n * along z, the value as the height. The series are the keys of the chart\n * config unless `keys` names them.\n */\nexport function BarChart3D<T extends Record<string, unknown>>({\n data,\n index,\n keys,\n barSize = 0.6,\n format = {},\n titles,\n}: BarChart3DProps<T>) {\n const { config, camera } = useChart3D()\n const series = keys ?? Object.keys(config)\n const values = data.flatMap((d) => series.map((key) => Number(d[key]) || 0))\n\n const { spec, world, size } = barBox(data.length, series.length, values, barSize)\n const bars = cubes3D()\n .camera(camera)\n .data(\n data.flatMap((d, i) =>\n series.map((key, j) => {\n const value = Number(d[key]) || 0\n return Object.assign(barCorners(world, i, j, value, size), { i, key, value })\n })\n )\n )\n .map((bar) => Object.assign(bar, { bottom: bar.faces.find((f) => f.face === \"bottom\")! }))\n // The bars stand on one floor, so they paint back to front by their footprint.\n .sort((a, b) => sort(a.bottom, b.bottom))\n\n return (\n <>\n <Axes3D\n spec={spec}\n world={world}\n titles={titles}\n format={{\n x: (i) => (format.x ?? String)(String(data[i]?.[index] ?? \"\")),\n y: format.y,\n z: (j) => config[series[j]]?.label ?? series[j],\n }}\n />\n <Marks3D\n marks={bars.flatMap((bar) =>\n barMarks({\n id: `${bar.i}-${bar.key}`,\n faces: bar.faces,\n color: `var(--color-${bar.key})`,\n title: String(data[bar.i][index]),\n label: config[bar.key]?.label ?? bar.key,\n value: bar.value,\n })\n )}\n />\n </>\n )\n}\n\n/**\n * The box of a bar chart: a row per entry along x, a row per series along z,\n * and the size of a bar, the share `barSize` of its cell.\n */\nfunction barBox(entries: number, series: number, values: number[], barSize: number) {\n const index = (length: number) => Array.from({ length }, (_, i) => i)\n const spec: AxesSpec = {\n x: { domain: [-0.5, entries - 0.5], ticks: index(entries) },\n y: axis(Math.min(0, ...values), Math.max(0, ...values)),\n z: { domain: [-0.5, series - 0.5], ticks: index(series) },\n }\n // A shallow box for few series, so the bars stay square.\n const depth = Math.min(1, Math.max(0.25, series / entries))\n const size = { width: (2 / entries) * barSize, depth: ((2 * depth) / series) * barSize }\n return { spec, world: worldBox(spec, depth), size }\n}\n\n/**\n * The corners of one bar, from the floor to its value, at row `x` and series\n * `z`. box() rises towards -y, so a negative bar starts at its value.\n */\nfunction barCorners(\n world: World,\n x: number,\n z: number,\n value: number,\n size: { width: number; depth: number }\n) {\n const floor = world.y(0)\n const top = world.y(value)\n return box({\n x: world.x(x),\n y: Math.max(floor, top),\n z: world.z(z),\n ...size,\n height: Math.abs(floor - top),\n })\n}\n\n/** The marks of one bar: the faces that look at the camera, shaded, each with its entry and value on hover. */\nfunction barMarks({\n id,\n faces,\n color,\n title,\n label,\n value,\n}: {\n id: string\n faces: CubeFace[]\n color: string\n title: string\n label: React.ReactNode\n value: number\n}): Mark3D[] {\n const tooltip = {\n at: center(faces.find((face) => face.face === \"top\")!),\n title,\n items: [{ label, value, color }],\n }\n\n // The faces point outwards: a convex bar shows the ones facing the camera.\n return faces\n .filter((face) => face.ccw)\n .map((face) => ({\n key: `${id}-${face.face}`,\n points: face.map((p) => p.projected),\n fill: shade(face, color),\n tooltip,\n }))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport { points3D, sort, type AxesSpec } from \"d3-3d\"\n\nimport { Axes3D, Marks3D, axis, useChart3D, worldBox } from \"@/registry/new-york/ui/chart-3d\"\n\nexport type ScatterChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per point. */\n data: T[]\n /** The field of the position along x. */\n x: keyof T & string\n /** The field of the position along y, the height. */\n y: keyof T & string\n /** The field of the position along z. */\n z: keyof T & string\n /**\n * The field whose value is the config key of the color of a point.\n * @defaultValue the first key of the chart config for every point\n */\n series?: keyof T & string\n /**\n * The radius of a point in the units of the view box.\n * @defaultValue 4\n */\n radius?: number\n /** Formats the tick labels of each axis. */\n format?: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>\n /** The titles of the axes. */\n titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>\n}\n\n/**\n * Points in the chart box, at the fields `x`, `y` and `z` of each entry.\n * `series` names the field whose value is the config key of the color.\n */\nexport function ScatterChart3D<T extends Record<string, unknown>>({\n data,\n x,\n y,\n z,\n series,\n radius = 4,\n format,\n titles,\n}: ScatterChart3DProps<T>) {\n const { config, camera } = useChart3D()\n const fields = { x, y, z }\n const read = (d: T, axis: keyof AxesSpec) => Number(d[fields[axis]])\n\n const range = (a: keyof AxesSpec) => {\n const [lo = 0, hi = 0] = extent(data, (d) => read(d, a))\n return axis(lo, hi)\n }\n const spec: AxesSpec = { x: range(\"x\"), y: range(\"y\"), z: range(\"z\") }\n const world = worldBox(spec)\n\n const points = points3D<{ d: T; i: number }>()\n .camera(camera)\n .x(({ d }) => world.x(read(d, \"x\")))\n .y(({ d }) => world.y(read(d, \"y\")))\n .z(({ d }) => world.z(read(d, \"z\")))\n const fallback = Object.keys(config)[0]\n\n const marks = points\n .data(data.map((d, i) => ({ d, i })))\n .sort(sort)\n .map((p) => {\n const key = series ? String(p.d[series]) : fallback\n return {\n key: String(p.i),\n points: [p.projected],\n r: radius,\n fill: `var(--color-${key})`,\n // Ringed by the background, so that points in front stand out.\n stroke: \"var(--background)\",\n tooltip: {\n at: p.projected,\n title: series ? (config[key]?.label ?? key) : undefined,\n items: ([\"x\", \"y\", \"z\"] as const).map((a) => ({\n label: titles?.[a] ?? fields[a],\n value: read(p.d, a),\n })),\n },\n }\n })\n\n return (\n <>\n <Axes3D spec={spec} world={world} format={format} titles={titles} />\n <Marks3D marks={marks} />\n </>\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport { gridPlanes3D, sort, type AxesSpec, type Point3D } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n center,\n linear,\n shade,\n useChart3D,\n worldBox,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type SurfaceChart3DProps = {\n /** The heights on the grid, `data[row][column]`. */\n data: number[][]\n /**\n * The data values the first and the last column (x) and row (z) stand for.\n * @defaultValue the indices of the columns and rows\n */\n domain?: { x?: [number, number]; z?: [number, number] }\n /**\n * The config keys of the colors at the lowest and at the highest height.\n * @defaultValue the first two keys of the chart config\n */\n colors?: [string, string]\n /** Formats the tick labels of each axis. */\n format?: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>\n /** The titles of the axes. */\n titles?: Partial<Record<keyof AxesSpec, React.ReactNode>>\n}\n\n/**\n * A surface over a grid: `data[row][column]` is the height, the columns run\n * along x and the rows along z. The fill ramps from the first color of\n * `colors` at the lowest height to the second at the highest; both are keys\n * of the chart config, by default its first two.\n */\nexport function SurfaceChart3D({ data, domain = {}, colors, format, titles }: SurfaceChart3DProps) {\n const { config, camera } = useChart3D()\n const [low, high = low] = colors ?? Object.keys(config)\n const rows = data.length\n const columns = data[0]?.length ?? 0\n const [x0, x1] = domain.x ?? [0, columns - 1]\n const [z0, z1] = domain.z ?? [0, rows - 1]\n const [lo = 0, hi = 0] = extent(data.flat())\n\n const spec: AxesSpec = { x: axis(x0, x1), y: axis(lo, hi), z: axis(z0, z1) }\n const world = worldBox(spec)\n const toX = linear([0, columns - 1], [x0, x1])\n const toZ = linear([0, rows - 1], [z0, z1])\n\n const grid = gridPlanes3D<Point3D>()\n .camera(camera)\n .rows(columns)\n .x((p) => world.x(p.x))\n .y((p) => world.y(p.y))\n .z((p) => world.z(p.z))\n const points = data.flatMap((row, r) => row.map((y, c) => ({ x: toX(c), y, z: toZ(r) })))\n\n const marks = grid\n .data(points)\n .sort(sort)\n .map((quad) => {\n const height = quad.reduce((sum, p) => sum + p.y, 0) / quad.length\n const t = Math.round(((height - lo) / (hi - lo || 1)) * 100)\n return {\n key: quad.plane,\n points: quad.map((p) => p.projected),\n fill: shade(quad, `color-mix(in oklch, var(--color-${high}) ${t}%, var(--color-${low}))`),\n tooltip: { at: center(quad), items: [{ label: titles?.y ?? \"value\", value: height }] },\n }\n })\n\n return (\n <>\n <Axes3D spec={spec} world={world} format={format} titles={titles} />\n <Marks3D marks={marks} />\n </>\n )\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,114 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@niekes/charts-3d",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "3D charts for shadcn/ui, built on d3-3d. A shadcn registry and an npm package from the same source.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"3D",
|
|
7
|
+
"charts",
|
|
8
|
+
"d3",
|
|
9
|
+
"d3-3d",
|
|
10
|
+
"react",
|
|
11
|
+
"registry",
|
|
12
|
+
"shadcn",
|
|
13
|
+
"shadcn-ui",
|
|
14
|
+
"svg",
|
|
15
|
+
"visualization"
|
|
16
|
+
],
|
|
17
|
+
"homepage": "https://niekes.github.io/charts-3d/",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/niekes/charts-3d/issues"
|
|
20
|
+
},
|
|
21
|
+
"license": "BSD-3-Clause",
|
|
22
|
+
"author": "Niekes (https://niekes.com)",
|
|
23
|
+
"repository": {
|
|
24
|
+
"type": "git",
|
|
25
|
+
"url": "git+https://github.com/niekes/charts-3d.git"
|
|
26
|
+
},
|
|
27
|
+
"funding": {
|
|
28
|
+
"type": "github",
|
|
29
|
+
"url": "https://github.com/sponsors/niekes"
|
|
30
|
+
},
|
|
31
|
+
"files": [
|
|
32
|
+
"dist",
|
|
33
|
+
"NOTICE"
|
|
34
|
+
],
|
|
35
|
+
"type": "module",
|
|
36
|
+
"sideEffects": false,
|
|
37
|
+
"module": "./dist/index.js",
|
|
38
|
+
"types": "./dist/index.d.ts",
|
|
39
|
+
"exports": {
|
|
40
|
+
".": {
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"import": "./dist/index.js"
|
|
43
|
+
},
|
|
44
|
+
"./package.json": "./package.json"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"typecheck": "react-router typegen && tsc --noEmit",
|
|
51
|
+
"build": "npm run typecheck && npm run registry:build && npm run docs:build && npm run build:pack",
|
|
52
|
+
"build:pack": "vp pack",
|
|
53
|
+
"prepack": "npm run typecheck && npm run build:pack",
|
|
54
|
+
"test": "vp test run",
|
|
55
|
+
"test:watch": "vp test",
|
|
56
|
+
"coverage": "vp test run --coverage",
|
|
57
|
+
"coverage:badge": "node scripts/coverage-badge.mjs",
|
|
58
|
+
"registry:build": "shadcn build",
|
|
59
|
+
"docs:dev": "react-router dev",
|
|
60
|
+
"docs:build": "react-router build && mv build/client/index.html build/client/404.html && cp -R build/client/charts-3d/. build/client && rm -rf build/client/charts-3d",
|
|
61
|
+
"docs:preview": "vp preview --outDir build/client",
|
|
62
|
+
"lint:template": "node scripts/check-template.mjs",
|
|
63
|
+
"lint:fallow": "fallow dead-code --ci --format ${FALLOW_FORMAT:-human} && fallow health --ci --coverage-gaps --min-score 98 --format ${FALLOW_FORMAT:-human} && fallow dupes --ci --format ${FALLOW_FORMAT:-human}",
|
|
64
|
+
"lint": "react-router typegen && vp fmt --check && vp lint && npm run lint:template && npm run lint:fallow",
|
|
65
|
+
"hooks:install": "fallow hooks install --target git && fallow hooks install --target agent --agent claude && fallow hooks install --target agent --agent codex"
|
|
66
|
+
},
|
|
67
|
+
"dependencies": {
|
|
68
|
+
"clsx": "^2.1.1",
|
|
69
|
+
"d3-3d": "^2.2.0",
|
|
70
|
+
"d3-array": "^3.2.4",
|
|
71
|
+
"lucide-react": "^1.61.0",
|
|
72
|
+
"tailwind-merge": "^3.7.0"
|
|
73
|
+
},
|
|
74
|
+
"devDependencies": {
|
|
75
|
+
"@react-router/dev": "^8.5.0",
|
|
76
|
+
"@react-router/node": "^8.5.0",
|
|
77
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
78
|
+
"@types/d3-array": "^3.2.2",
|
|
79
|
+
"@types/mdx": "^2.0.14",
|
|
80
|
+
"@types/node": "^26.6.5",
|
|
81
|
+
"@types/react": "^19.3.0",
|
|
82
|
+
"@types/react-dom": "^19.3.0",
|
|
83
|
+
"@vitest/coverage-v8": "^5.0.5",
|
|
84
|
+
"fallow": "^3.34.1",
|
|
85
|
+
"fumadocs-core": "^16.17.8",
|
|
86
|
+
"fumadocs-mdx": "^15.4.10",
|
|
87
|
+
"fumadocs-typescript": "^5.6.0",
|
|
88
|
+
"fumadocs-ui": "^16.17.8",
|
|
89
|
+
"jsdom": "^30.1.3",
|
|
90
|
+
"publint": "^0.3.25",
|
|
91
|
+
"react": "^19.3.1",
|
|
92
|
+
"react-dom": "^19.3.1",
|
|
93
|
+
"react-router": "^8.5.0",
|
|
94
|
+
"shadcn": "^4.22.1",
|
|
95
|
+
"tailwindcss": "^4.3.3",
|
|
96
|
+
"typescript": "^7.0.2",
|
|
97
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
|
|
98
|
+
"vite-plus": "1.4.0",
|
|
99
|
+
"vitest": "5.0.5"
|
|
100
|
+
},
|
|
101
|
+
"peerDependencies": {
|
|
102
|
+
"react": "^19.0.0"
|
|
103
|
+
},
|
|
104
|
+
"overrides": {
|
|
105
|
+
"vite": "npm:@voidzero-dev/vite-plus-core@1.4.0",
|
|
106
|
+
"vitest": "5.0.5"
|
|
107
|
+
},
|
|
108
|
+
"devEngines": {
|
|
109
|
+
"runtime": {
|
|
110
|
+
"name": "node",
|
|
111
|
+
"version": "^22.18.0 || ^24.11.0 || >=26.0.0"
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|