@niekes/charts-3d 0.6.0 → 0.7.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 +22 -0
- package/README.md +6 -6
- package/dist/index.d.ts +469 -28
- package/dist/index.js +1798 -409
- package/dist/index.js.map +1 -1
- package/package.json +13 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../lib/utils.ts","../registry/new-york/ui/chart-3d.tsx","../registry/new-york/ui/area-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 points3D,\n sort,\n type AxesSpec,\n type AxisEdge,\n type AxisSpec,\n type AxisWall,\n type Camera3DInstance,\n type CubeFace,\n type Point2D,\n type Point3D,\n type ShapeInstance,\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\" | \"webgl\"\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\n/** What a mark says while the pointer is on it, beside the pointer. */\nexport type Tooltip3D = {\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 * The marks of the same element as this one: the faces of a bar, the\n * segments of a flow. Pointing at a mark gives them an edge in the focus\n * color - `--chart-3d-focus`, or their own fill lightened - until the\n * pointer leaves the mark; the fill never changes on hover.\n */\n groups?: string[]\n}\n\n/** The groups in focus, a store, so a change reaches the marks and labels without rendering the chart again. */\ntype Focus3D = {\n get: () => string[] | undefined\n set: (groups?: string[]) => void\n subscribe: (listener: () => void) => () => void\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 focus: Focus3D\n /** The time in ms a chart takes to glide into new data, 600 unless the container says. */\n animationDuration?: number\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// How long the zoom cursor outlives the last wheel tick before the hand returns.\nconst ZOOM_CURSOR = 400\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 actions a key triggers: each steps the camera, `help` opens the shortcut panel. */\nexport type KeyAction3D =\n | \"rotateLeft\"\n | \"rotateRight\"\n | \"rotateUp\"\n | \"rotateDown\"\n | \"panLeft\"\n | \"panRight\"\n | \"panUp\"\n | \"panDown\"\n | \"zoomIn\"\n | \"zoomOut\"\n | \"reset\"\n | \"help\"\n\n/** The gestures of the pointer, which `keymap` can turn off or rename but not rebind; the shortcut panel shows each with its modifier on the reader's platform. */\nexport type Gesture3D = \"dragRotate\" | \"dragPan\" | \"wheelZoom\" | \"doubleClickReset\"\n\n/**\n * The shortcuts of a chart over their defaults, per action: `false` turns an\n * action off, keys replace its keys and a label renames it in the shortcut\n * panel, where the actions of one label share a row. Keys are written the way\n * `aria-keyshortcuts` writes them, such as `\"Shift+ArrowLeft\"` or\n * `\"Control+Plus\"`, and the panel shows the first.\n */\nexport type Keymap3D = {\n [A in KeyAction3D]?: false | string[] | { keys?: string[]; label?: string }\n} & { [G in Gesture3D]?: false | { label?: string } }\n\ntype Action3D = KeyAction3D | Gesture3D\n\n// The shortcuts of a chart, in the order of the shortcut panel: the keys of\n// an action move the camera, a gesture shows its hint, and the panel lists\n// every action that is on, so the two never disagree. `keymap` overrides them.\nconst SHORTCUTS: Record<\n Action3D,\n { label: string; keys?: string[]; hint?: string[]; move?: Move }\n> = {\n dragRotate: { label: \"Rotate\", hint: [\"Mod\", \"Drag\"] },\n rotateLeft: { label: \"Rotate\", keys: [\"ArrowLeft\"], move: { yaw: -KEY_STEP } },\n rotateRight: { label: \"Rotate\", keys: [\"ArrowRight\"], move: { yaw: KEY_STEP } },\n rotateUp: { label: \"Rotate\", keys: [\"ArrowUp\"], move: { tilt: -KEY_STEP } },\n rotateDown: { label: \"Rotate\", keys: [\"ArrowDown\"], move: { tilt: KEY_STEP } },\n dragPan: { label: \"Pan\", hint: [\"Alt\", \"Drag\"] },\n panLeft: { label: \"Pan\", keys: [\"Shift+ArrowLeft\"], move: { pan: { x: -PAN_STEP, y: 0 } } },\n panRight: { label: \"Pan\", keys: [\"Shift+ArrowRight\"], move: { pan: { x: PAN_STEP, y: 0 } } },\n panUp: { label: \"Pan\", keys: [\"Shift+ArrowUp\"], move: { pan: { x: 0, y: -PAN_STEP } } },\n panDown: { label: \"Pan\", keys: [\"Shift+ArrowDown\"], move: { pan: { x: 0, y: PAN_STEP } } },\n zoomIn: { label: \"Zoom\", keys: [\"Plus\", \"=\"], move: { zoom: ZOOM_STEP } },\n zoomOut: { label: \"Zoom\", keys: [\"-\"], move: { zoom: 1 / ZOOM_STEP } },\n wheelZoom: { label: \"Zoom\", hint: [\"Mod\", \"Scroll\"] },\n reset: { label: \"Reset\", keys: [\"0\"], move: { reset: true } },\n doubleClickReset: { label: \"Reset\", hint: [\"Double-click\"] },\n help: { label: \"Keyboard shortcuts\", keys: [\"?\"] },\n}\n\nconst MODIFIERS = [\"Control\", \"Alt\", \"Meta\", \"Shift\"]\n\n/** Whether the reader is on a Mac, where the platform modifier is ⌘; elsewhere it is Ctrl. */\nconst mac = () =>\n /mac/i.test(\n (globalThis.navigator as Navigator & { userAgentData?: { platform?: string } })?.userAgentData\n ?.platform ??\n globalThis.navigator?.platform ??\n \"\"\n )\n\n/** The label of the platform modifier: ⌘ on a Mac, Ctrl elsewhere. */\nconst modLabel = () => (mac() ? \"⌘\" : \"Ctrl\")\n\n/** The label of the Alt key: ⌥ on a Mac, Alt elsewhere. */\nconst altLabel = () => (mac() ? \"⌥\" : \"Alt\")\n\n/** Whether the platform modifier - ⌘ on a Mac, Ctrl elsewhere - is held in `e`. */\nconst platformMod = (e: { metaKey: boolean; ctrlKey: boolean }) => (mac() ? e.metaKey : e.ctrlKey)\n\n/** Whether `value` lies between the ends `lo` and `hi`. */\nconst within = (lo: number, hi: number, value: number) => value >= lo && value <= hi\n// The keys that `aria-keyshortcuts` names, because `+` delimits and a space separates.\nconst NAMED: Record<string, string> = { Plus: \"+\", Space: \" \" }\nconst ARIA: Record<string, string> = { \"+\": \"Plus\", \" \": \"Space\" }\nconst KBD: Record<string, string> = {\n ArrowLeft: \"←\",\n ArrowRight: \"→\",\n ArrowUp: \"↑\",\n ArrowDown: \"↓\",\n \"-\": \"−\",\n \" \": \"Space\",\n Control: \"Ctrl\",\n Meta: \"⌘\",\n}\n\n/** Keys split at `+`, which is the key itself at the end: `\"Control++\"` is Control and `+`. */\nconst split = (keys: string) => keys.split(/\\+(?!$)/)\n\n/**\n * Keys in the one form a binding and a press compare in: the modifiers in a\n * fixed order, then the key, Plus as `+` and Space as \" \". Shift counts only\n * beside a named key; a character such as \"?\" or \"A\" is typed with it already.\n */\nfunction combo(keys: string) {\n const parts = split(keys)\n const key = NAMED[parts.at(-1)!] ?? parts.at(-1)!\n const mods = MODIFIERS.filter((m) => parts.includes(m) && (m !== \"Shift\" || key.length > 1))\n return [...mods, key].join(\"+\")\n}\n\n/** The keys of a press, in the form of `combo`. */\nfunction pressed(e: Pick<KeyboardEvent, \"key\" | \"ctrlKey\" | \"altKey\" | \"metaKey\" | \"shiftKey\">) {\n const mods = [\n e.ctrlKey && \"Control\",\n e.altKey && \"Alt\",\n e.metaKey && \"Meta\",\n e.shiftKey && \"Shift\",\n ]\n return combo([...mods, e.key].filter(Boolean).join(\"+\"))\n}\n\n/** Keys in the form of `combo`, the way `aria-keyshortcuts` writes them. */\nfunction aria(keys: string) {\n const parts = split(keys)\n return [...parts.slice(0, -1), ARIA[parts.at(-1)!] ?? parts.at(-1)].join(\"+\")\n}\n\n/** Every action, `keymap` over its defaults: on unless it is off or a key action without keys. */\nfunction shortcutsOf(keymap: Keymap3D | false) {\n return (Object.keys(SHORTCUTS) as Action3D[]).map((action) => {\n const own: Keymap3D[KeyAction3D] = keymap && keymap[action]\n const { keys = [], ...shortcut } = {\n ...SHORTCUTS[action],\n ...(Array.isArray(own) ? { keys: own } : own || {}),\n }\n const on = own !== false && (shortcut.hint !== undefined || keys.length > 0)\n return { ...shortcut, action, on, keys: keys.map(combo) }\n })\n}\n\ntype Shortcut = ReturnType<typeof shortcutsOf>[number]\n\n/**\n * The rows of the shortcut panel: the actions by label, the keys of a row in\n * groups of the same modifiers, left of its gestures, each a group of its own.\n */\nfunction rowsOf(shortcuts: Shortcut[]) {\n const rows = new Map<string, { keys: Map<string, string[]>; gestures: string[][] }>()\n for (const { label, keys, hint } of shortcuts) {\n const parts = (hint ?? split(keys[0])).map((k) =>\n k === \"Mod\" ? modLabel() : k === \"Alt\" ? altLabel() : (KBD[k] ?? k)\n )\n const row = rows.get(label) ?? { keys: new Map<string, string[]>(), gestures: [] }\n if (hint) row.gestures.push(parts)\n else {\n const group = parts.slice(0, -1).join(\"+\")\n const known = row.keys.get(group)\n row.keys.set(group, known ? [...known, parts.at(-1)!] : parts)\n }\n rows.set(label, row)\n }\n return [...rows].map(([label, row]) => ({\n label,\n keys: [...row.keys.values()],\n gestures: row.gestures,\n }))\n}\n\n/**\n * What a keymap does: the actions that are on, the step of each key, the help\n * keys and the rows of the panel. Without the `panel`, the help keys have\n * nothing to open and are off.\n */\nfunction keymapOf(keymap: Keymap3D | false, panel: boolean) {\n const all = shortcutsOf(keymap)\n const on = all.filter((s) => s.on && (panel || s.action !== \"help\"))\n return {\n on: (action: Action3D) => on.some((s) => s.action === action),\n moves: Object.fromEntries(on.flatMap((s) => s.keys.map((k) => [k, s.move]))) as Record<\n string,\n Move | undefined\n >,\n help: on.find((s) => s.action === \"help\")?.keys ?? [],\n label: all.find((s) => s.action === \"help\")!.label,\n aria: on.flatMap((s) => s.keys.map(aria)).join(\" \"),\n rows: panel ? rowsOf(on) : [],\n }\n}\n\ntype Keymap = ReturnType<typeof keymapOf>\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 * The time in ms a chart takes to glide into new data; 0 makes it jump.\n * @defaultValue 600\n */\n animationDuration?: number\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, \"webgl\" more.\n * The chart draws as SVG until the browser shows it has the requested renderer,\n * \"webgl\" falling back to \"canvas\", and where it has none, as SVG.\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 * Rebinds, renames or turns off the keys and the gestures of the chart, per\n * action; `false` turns them all off and the chart stands still.\n * @defaultValue {}\n */\n keymap?: Keymap3D | false\n /**\n * The corner that shows the axes of the chart, turned with the camera; `false` hides them.\n * @defaultValue \"bottom-left\"\n */\n gizmo?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\" | false\n /**\n * The corner beside the pointer the tooltip sits at. Where the tooltip would\n * leave the chart, it flips to the other side, on each axis alone.\n * @defaultValue \"top-right\"\n */\n tooltip?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"\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 animationDuration,\n legend = false,\n renderer: requested = \"svg\",\n shortcuts = true,\n keymap = {},\n gizmo = \"bottom-left\",\n tooltip = \"top-right\",\n className,\n children,\n \"aria-label\": ariaLabel,\n ...props\n}: React.ComponentProps<\"div\"> & ChartContainer3DProps) {\n const chartId = chartIdOf(id, React.useId())\n const { scene, renderer, canvas, repaint, hover, hide, leave, tip, focus } = useScene(\n requested,\n width,\n height,\n tooltip\n )\n const keys = keymapOf(keymap, shortcuts)\n const { view, handlers } = useOrbit(defaultView, width, keys, hide, hover)\n const camera = useCamera(view, width, height)\n const context = React.useMemo(\n () => ({ config, camera, renderer, scene, repaint, focus, animationDuration }),\n [config, camera, renderer, repaint, focus, animationDuration]\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 <div className=\"relative rounded-lg has-focus-visible:ring-[3px] has-focus-visible:ring-ring/50\">\n <svg\n viewBox={`0 0 ${width} ${height}`}\n role=\"img\"\n {...keymapProps(keys, ariaLabel)}\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 <ChartGizmo3D camera={camera} corner={gizmo} />\n <ChartTooltip3D tip={tip} />\n </div>\n <ChartShortcuts3D {...keys} />\n {legend && <ChartLegend3D config={config} />}\n </div>\n )\n}\n\n/** The id the colors of a chart are scoped to: its own `id`, or the one React made up. */\nfunction chartIdOf(id: string | undefined, uniqueId: string) {\n return `chart-${id || uniqueId.replace(/:/g, \"\")}`\n}\n\n/**\n * What the svg says about its keymap: a label that names the drag and the\n * help key if they are on, the keys, the focus only if a key does something\n * and the grab cursor only if a drag does; without one, a touch scrolls the page.\n */\nfunction keymapProps(keys: Keymap, label?: string): React.SVGProps<SVGSVGElement> {\n const drag = keys.on(\"dragRotate\") || keys.on(\"dragPan\")\n const help = keys.help[0]\n const said = [\n \"3D chart.\",\n keys.on(\"dragRotate\") && `${modLabel()} and drag to rotate it.`,\n help && `Press ${aria(help)} for all shortcuts.`,\n ]\n return {\n \"aria-label\": label ?? said.filter(Boolean).join(\" \"),\n \"aria-keyshortcuts\": keys.aria || undefined,\n tabIndex: keys.aria ? 0 : undefined,\n className: cn(\n \"block h-auto w-full outline-hidden select-none mask-x-from-96% mask-y-from-96%\",\n // The default cursor stays, so a plain drag only inspects; the modifier and a drag rotate.\n drag && \"touch-none\"\n ),\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(requested: Renderer3D, width: number, height: number, placement: Placement3D) {\n const scene = React.useRef<Mark3D[]>([])\n const tip = useTip(placement)\n const focus = useFocus()\n const renderer = useRenderer(requested)\n const { canvas, repaint } = useCanvas(scene, width, height, renderer)\n const { hover, hide, leave } = useHover(scene, width, height, tip, focus)\n return { scene, renderer, canvas, repaint, hover, hide, leave, tip, focus }\n}\n\ntype Tip3D = ReturnType<typeof useTip>\ntype Placement3D = NonNullable<ChartContainer3DProps[\"tooltip\"]>\n\n// The room between the pointer and its tooltip, in pixels, and the shift of\n// the tooltip on an axis: before the pointer by its own size and the room, or after it.\nconst TIP_GAP = 12\nconst shift = (isBefore: boolean) => (isBefore ? `calc(-100% - ${TIP_GAP}px)` : `${TIP_GAP}px`)\n\n/**\n * Whether a tooltip of `size` goes before the pointer at `at`, on an axis of\n * `length`: as `preferred`, unless it would leave the chart there and the\n * other side has more room.\n */\nfunction before(at: number, size: number, length: number, preferred: boolean) {\n const room = preferred ? at : length - at\n return room < size + TIP_GAP && length - room > room ? !preferred : preferred\n}\n\n/**\n * The tooltip of the hovered mark and where it sits: beside the pointer, in\n * the pixels of the chart, at `placement`. `follow` moves it with the pointer\n * straight in the DOM, so a move within a mark renders nothing; `place` puts\n * it there again once it shows, or its content changes its size.\n */\nfunction useTip(placement: Placement3D) {\n const [tooltip, set] = React.useState<Tooltip3D | null>(null)\n const ref = React.useRef<HTMLDivElement>(null)\n // The pointer in the chart, and the size of the chart.\n const pointer = React.useRef({ x: 0, y: 0, width: 0, height: 0 })\n const place = React.useCallback(() => {\n const el = ref.current\n if (!el) return\n // A tooltip that shows jumps into its corner; only one on screen glides when it flips.\n const shows = !el.dataset.placement\n if (shows) el.style.transition = \"none\"\n const { x, y, width, height } = pointer.current\n const top = before(y, el.offsetHeight, height, placement.startsWith(\"top\"))\n const left = before(x, el.offsetWidth, width, placement.endsWith(\"left\"))\n el.style.left = `${x}px`\n el.style.top = `${y}px`\n el.style.translate = `${shift(left)} ${shift(top)}`\n el.dataset.placement = `${top ? \"top\" : \"bottom\"}-${left ? \"left\" : \"right\"}`\n if (shows) {\n // Lays the corner out while the transition is off, then turns it on again.\n el.getBoundingClientRect()\n el.style.transition = \"\"\n }\n }, [placement])\n const follow = (at: typeof pointer.current) => {\n pointer.current = at\n place()\n }\n return { tooltip, set, ref, place, follow }\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\nconst clamp = (lo: number, hi: number, value: number) => Math.max(lo, Math.min(hi, value))\nconst ZERO = { x: 0, y: 0 }\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 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 * Whether the chart may move on its own: only where the browser says the\n * reader has not asked for reduced motion. Where it cannot say, as on the\n * server and in jsdom, the chart jumps.\n */\nfunction animates() {\n return Boolean(globalThis.matchMedia?.(\"(prefers-reduced-motion: no-preference)\").matches)\n}\n\n/** One glide of numbers: from `from` into `to`, come the share `t` of the way. */\ntype Tween = { key: string; from: Record<string, number>; to: Record<string, number>; t: number }\n\n/**\n * Eases a chart into new data: the numbers of `values` glide from the ones\n * on screen to these over the animationDuration of the container. A key\n * that is new starts at `enter`, or where it ends; a key that is gone glides\n * back to `enter`, the mirror of its entering - without one it stands where\n * it is - and leaves when the glide is done. Without time, or with reduced\n * motion, the numbers jump.\n */\nfunction useTween(values: Record<string, number>, enter?: number): Record<string, number> {\n const { animationDuration: duration = 600 } = useChart3D()\n // The content, not the record: a chart builds `values` at every render, also while it turns.\n const key = JSON.stringify(values)\n const [tween, setTween] = React.useState<Tween>({ key, from: values, to: values, t: 1 })\n const shown = tweenNumbers(tween, enter)\n\n // Numbers from the render before, the React pattern of state set while rendering.\n if (key !== tween.key) {\n setTween({ key, from: shown, to: values, t: duration > 0 && animates() ? 0 : 1 })\n }\n\n React.useEffect(() => {\n if (tween.t >= 1) return\n let start: number | null = null\n let frame = 0\n const step = (now: number) => {\n start ??= now\n const t = Math.min(1, (now - start) / duration)\n setTween((tw) => ({ ...tw, t }))\n if (t < 1) frame = requestAnimationFrame(step)\n }\n frame = requestAnimationFrame(step)\n return () => cancelAnimationFrame(frame)\n }, [tween.key, duration])\n\n return shown\n}\n\n/** The numbers of `tween` on screen: `from` eased into `to`, a new key from `enter` or where it ends, a gone one gliding back to `enter` until the glide is done. */\nfunction tweenNumbers({ from, to, t }: Tween, enter?: number) {\n const s = t * t * (3 - 2 * t)\n const gone = t >= 1 ? [] : Object.entries(from).filter(([k]) => !(k in to))\n return Object.fromEntries([\n ...Object.entries(to).map(([k, end]) => {\n const start = from[k] ?? enter ?? end\n // At the end the number itself, so no float drift stays in the data.\n return [k, t >= 1 ? end : start + (end - start) * s]\n }),\n // A gone key glides back to `enter`, the mirror of its entering - without\n // one it stands where it is - and leaves when the glide is done.\n ...gone.map(([k, start]) => [k, start + ((enter ?? start) - start) * s]),\n ])\n}\n\n/**\n * An axis gliding into new data: its spec, the ticks the data dropped, fading\n * out in place, and the gliding `span` of its ticks, which its line runs.\n */\ntype GlidingAxis = AxisSpec & { leaving?: number[]; span?: number[] }\n\n/**\n * `spec` gliding into new data with the marks: the ends of every axis glide\n * as `useTween` glides the numbers, where ends rounded from the numbers on\n * screen would jump from one round number to the next, and the box with\n * them. The ticks stay those of `spec`; labels of ticks outside the gliding\n * ends fade out in `edgeLabels` instead of popping out of the range. The\n * outermost ticks glide too, so the line of the axis grows to a new tick and\n * shrinks from a dropped one instead of jumping when the glide is done.\n */\nfunction useTweenAxes(spec: AxesSpec): AxesSpec {\n const axes = [\"x\", \"y\", \"z\"] as const\n const last = (domain: number[]) => domain[domain.length - 1]\n const target = Object.fromEntries(\n axes.flatMap((a) => {\n const { domain, ticks } = spec[a]\n return [\n [`${a}0`, domain[0]],\n [`${a}1`, last(domain)],\n [`${a}t0`, ticks.at(0) ?? domain[0]],\n [`${a}t1`, ticks.at(-1) ?? last(domain)],\n ]\n })\n )\n const ends = useTween(target)\n // At the end of a glide useTween hands back the targets themselves, so the\n // ends tell whether the axes still glide.\n const gliding = Object.keys(target).some((k) => ends[k] !== target[k])\n // The target the glide left, remembered the way useTween keys its numbers,\n // so a retarget in the middle of a glide fades the ticks of that target out.\n const key = JSON.stringify(spec)\n const memory = React.useRef({ key, target: spec, from: spec })\n if (memory.current.key !== key) {\n memory.current = { key, target: spec, from: memory.current.target }\n }\n const glided = (a: keyof AxesSpec): GlidingAxis => {\n const [lo, hi] = [ends[`${a}0`], ends[`${a}1`]]\n // The ticks stay those of the target, so a label whose tick lies outside the\n // gliding ends fades out instead of popping out of the range. Every tick the\n // new data drops stays until the glide is done: one beyond the new ends\n // fades out as the gliding end sweeps past it, one within them fades out in\n // place, named in `leaving`.\n const [d0, d1] = [spec[a].domain[0], last(spec[a].domain)]\n const gone = gliding\n ? memory.current.from[a].ticks.filter((t) => !spec[a].ticks.includes(t))\n : []\n const ticks = gone.length ? [...spec[a].ticks, ...gone].sort((t, u) => t - u) : spec[a].ticks\n const leaving = gone.filter((t) => within(Math.min(d0, d1), Math.max(d0, d1), t))\n const span = [ends[`${a}t0`], ends[`${a}t1`]]\n return { domain: [lo, hi], ticks, span, ...(leaving.length ? { leaving } : {}) }\n }\n return { x: glided(\"x\"), y: glided(\"y\"), z: glided(\"z\") }\n}\n\n// How long the camera glides to the view a key asks for, in milliseconds.\nconst GLIDE = 200\n\n/**\n * The view of the camera, `jump`, which moves it at once, and `glide`, which\n * moves it there in `GLIDE` milliseconds, easing out. A glide under way\n * heads for the next view from where it is, so a held key turns the camera\n * smoothly; a jump stops it. Where the reader asks for reduced motion, or\n * the browser cannot say, a glide jumps.\n */\nfunction useGlide(defaultView: View3D) {\n const [view, setView] = React.useState(defaultView)\n const now = React.useRef(defaultView)\n const run = React.useRef<{ to: View3D; frame: number } | null>(null)\n const show = React.useCallback((v: View3D) => setView((now.current = v)), [])\n const stop = React.useCallback(() => {\n cancelAnimationFrame(run.current?.frame ?? 0)\n run.current = null\n }, [])\n const jump = React.useCallback(\n (to: (from: View3D) => View3D) => {\n stop()\n show(to(now.current))\n },\n [show, stop]\n )\n React.useEffect(() => stop, [stop])\n\n const glide = (to: (from: View3D) => View3D) => {\n if (!animates()) return jump(to)\n const end = to(run.current?.to ?? now.current)\n // The yaw turns the short way round, to an angle that looks the same.\n const from = { ...now.current, yaw: end.yaw + remainder(now.current.yaw - end.yaw) }\n const start = performance.now()\n stop()\n const frame = (time: number) => {\n const t = clamp(0, 1, (time - start) / GLIDE)\n show(t < 1 ? between(from, end, 1 - (1 - t) ** 3) : end)\n if (t < 1) run.current = { to: end, frame: requestAnimationFrame(frame) }\n else run.current = null\n }\n run.current = { to: end, frame: requestAnimationFrame(frame) }\n }\n\n return { view, jump, glide }\n}\n\n/** The angle `a` in the turn from -π to π. */\nfunction remainder(a: number) {\n return a - 2 * Math.PI * Math.round(a / (2 * Math.PI))\n}\n\n/** The view the share `k` of the way from `from` to `to`. */\nfunction between(from: View3D, to: View3D, k: number): View3D {\n const mix = (a: number, b: number) => a + (b - a) * k\n const pan = from.pan ?? ZERO\n const goal = to.pan ?? ZERO\n return {\n ...to,\n yaw: mix(from.yaw, to.yaw),\n tilt: mix(from.tilt, to.tilt),\n zoom: mix(from.zoom ?? 1, to.zoom ?? 1),\n pan: { x: mix(pan.x, goal.x), y: mix(pan.y, goal.y) },\n }\n}\n\n/**\n * The view of the camera, and the handlers that move it, as far as `keys`\n * has them on: a drag turns it, or pans it while Alt is held, the keys step\n * it, Ctrl or ⌘ with the wheel zooms it and a double click resets it.\n * `data-orbiting` among them is true while the camera turns. `onDragStart`\n * runs when a press becomes a drag, `onHover` on a move without one.\n */\nfunction useOrbit(\n defaultView: View3D,\n width: number,\n keys: Keymap,\n onDragStart: () => void,\n onHover: (e: React.PointerEvent<SVGSVGElement>) => void\n) {\n const { view, jump, glide } = useGlide(defaultView)\n const [orbiting, setOrbiting] = React.useState(false)\n const held = useModsHeld()\n const drag = React.useRef<(Point2D & { moved: boolean; rotate: boolean }) | null>(null)\n const ref = useWheelZoom(jump, keys.on(\"wheelZoom\"))\n // A drag follows the pointer at once, a key and a double click glide.\n const move = (step: Move) => jump((v) => moved(v, step, defaultView))\n const step = (step: Move) => glide((v) => moved(v, step, defaultView))\n const keyHandlers = useKeys(keys, step, setOrbiting)\n const release = () => {\n drag.current = null\n setOrbiting(false)\n }\n\n const handlers: OrbitHandlers = {\n ref,\n onPointerDown: (e) => {\n // Alt held, the drag pans; the platform modifier held, it turns.\n const pans = keys.on(\"dragPan\") && e.altKey\n if (pans || (keys.on(\"dragRotate\") && platformMod(e))) {\n drag.current = { x: e.clientX, y: e.clientY, moved: false, rotate: !pans }\n }\n },\n onPointerMove: (e) => {\n const d = drag.current\n if (!d) return onHover(e)\n // A drag moves only while its modifier is held: the platform modifier\n // turning, Alt panning.\n if (d.rotate ? !platformMod(e) : !e.altKey) return release()\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, rotate: d.rotate }\n const k = width / e.currentTarget.getBoundingClientRect().width\n setOrbiting(d.rotate)\n move(d.rotate ? { yaw: dx * DRAG, tilt: dy * DRAG } : { pan: { x: dx * k, y: dy * k } })\n },\n onPointerUp: release,\n onPointerCancel: release,\n onDoubleClick: keys.on(\"doubleClickReset\") ? () => step({ reset: true }) : undefined,\n ...keyHandlers,\n \"data-orbiting\": orbiting,\n \"data-mod\": keys.on(\"dragRotate\") && held.mod ? true : undefined,\n \"data-alt\": keys.on(\"dragPan\") && held.alt ? true : undefined,\n }\n\n return { view, handlers }\n}\n\ntype OrbitHandlers = React.SVGProps<SVGSVGElement> & {\n \"data-orbiting\": boolean\n \"data-mod\"?: boolean\n \"data-alt\"?: boolean\n}\n\n/**\n * Whether the platform modifier or Alt is held, so the cursor shows a hand\n * before the drag rotates and the four arrows before it pans. A missed keyup\n * (window blur while held) must not stick either cursor.\n */\nfunction useModsHeld() {\n const [mod, setMod] = React.useState(false)\n const [alt, setAlt] = React.useState(false)\n React.useEffect(() => {\n const modKey = mac() ? \"Meta\" : \"Control\"\n const onKey = (e: KeyboardEvent) => {\n if (e.key === modKey) setMod(e.type === \"keydown\")\n if (e.key === \"Alt\") setAlt(e.type === \"keydown\")\n }\n const onBlur = () => {\n setMod(false)\n setAlt(false)\n }\n window.addEventListener(\"keydown\", onKey)\n window.addEventListener(\"keyup\", onKey)\n window.addEventListener(\"blur\", onBlur)\n return () => {\n window.removeEventListener(\"keydown\", onKey)\n window.removeEventListener(\"keyup\", onKey)\n window.removeEventListener(\"blur\", onBlur)\n }\n }, [])\n return { mod, alt }\n}\n\n/**\n * The handlers that step the camera with the keys of `keys`. A key that\n * turns the camera marks it as orbiting until it is let go.\n */\nfunction useKeys(\n keys: Keymap,\n move: (step: Move) => void,\n setOrbiting: (orbiting: boolean) => void\n) {\n const onKeyDown = (e: React.KeyboardEvent<SVGSVGElement>) => {\n const step = keys.moves[pressed(e)]\n if (!step) return\n e.preventDefault()\n setOrbiting(Boolean(step.yaw || step.tilt))\n move(step)\n }\n const onKeyUp = () => setOrbiting(false)\n return { onKeyDown, onKeyUp }\n}\n\n/**\n * A ref for the svg that zooms the view with the platform modifier and the\n * wheel, if `on`. Ctrl and the wheel zooms on a Mac too, because a trackpad\n * pinch arrives that way, indistinguishable from the keys. The wheel alone\n * still scrolls the page. While the wheel zooms, the svg says so in\n * `data-zoom` - `\"in\"` or `\"out\"`, the direction of its cursor - until\n * `ZOOM_CURSOR` after the last tick.\n */\nfunction useWheelZoom(jump: (to: (from: View3D) => View3D) => void, on: boolean) {\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 if (!on || !svg) return\n let timer: ReturnType<typeof setTimeout>\n const onWheel = (e: WheelEvent) => {\n if (!platformMod(e) && !e.ctrlKey) return\n e.preventDefault()\n jump((v) => moved(v, { zoom: 2 ** (-e.deltaY / 200) }, v))\n svg.dataset.zoom = e.deltaY < 0 ? \"in\" : \"out\"\n clearTimeout(timer)\n timer = setTimeout(() => delete svg.dataset.zoom, ZOOM_CURSOR)\n }\n svg.addEventListener(\"wheel\", onWheel, { passive: false })\n return () => {\n clearTimeout(timer)\n svg.removeEventListener(\"wheel\", onWheel)\n }\n },\n [jump, on]\n )\n}\n\n/**\n * The tooltip of the mark under the pointer, the one painted last, and the\n * focus on its groups. The highlight follows the mark: `hover` sets the\n * tooltip only when the pointer moves onto another mark, and the focus only\n * when the groups change, so a move within a mark does not render the chart\n * again; off the mark and when the pointer leaves the chart, `leave` drops\n * both. While a drag turns the chart under the captured pointer, `hide`\n * drops the tooltip and keeps the focus, so a flow does not flash away and\n * can be followed from every side.\n */\nfunction useHover(\n scene: React.RefObject<Mark3D[]>,\n width: number,\n height: number,\n tip: Tip3D,\n focus: Focus3D\n) {\n const hovered = React.useRef<Mark3D>(undefined)\n const show = (mark?: Mark3D) => {\n // Also within one mark, whose groups new data can change; the store ignores the groups it holds.\n focus.set(mark?.groups)\n if (mark?.key === hovered.current?.key) return\n hovered.current = mark\n tip.set(mark?.tooltip ?? null)\n }\n\n return {\n hover: (e: React.PointerEvent<SVGSVGElement>) => {\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n tip.follow({ x, y, width: rect.width, height: rect.height })\n show(hit(scene.current, { x: (x / rect.width) * width, y: (y / rect.height) * height }))\n },\n hide: () => {\n hovered.current = undefined\n tip.set(null)\n },\n leave: () => show(undefined),\n }\n}\n\n/** A store for the groups in focus, which tells its listeners only when the groups change. */\nfunction useFocus(): Focus3D {\n const [focus] = React.useState(() => {\n let groups: string[] | undefined\n const listeners = new Set<() => void>()\n return {\n get: () => groups,\n set: (next?: string[]) => {\n if (JSON.stringify(next) === JSON.stringify(groups)) return\n groups = next\n listeners.forEach((listener) => listener())\n },\n subscribe: (listener: () => void) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n }\n })\n return focus\n}\n\n/** Whether an item shares a group with the focus: the hover highlights those items with an edge. */\nfunction useLit(items: { groups?: string[] }[]) {\n const { focus } = useChart3D()\n const groups = React.useSyncExternalStore(focus.subscribe, focus.get, focus.get)\n return (item: { groups?: string[] }) =>\n item.groups !== undefined && (groups?.some((group) => item.groups!.includes(group)) ?? false)\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, with\n * \"webgl\" falling back to \"canvas\" and \"canvas\" to SVG.\n */\nfunction useRenderer(requested: Renderer3D) {\n const [renderer, setRenderer] = React.useState<Renderer3D>(\"svg\")\n React.useEffect(() => {\n // A canvas of its own per probe, as one that gave out a context cannot give another.\n if (requested === \"webgl\" && document.createElement(\"canvas\").getContext(\"webgl\")) {\n return setRenderer(\"webgl\")\n }\n const canvas = requested !== \"svg\" && document.createElement(\"canvas\").getContext(\"2d\")\n setRenderer(canvas ? \"canvas\" : \"svg\")\n }, [requested])\n return renderer\n}\n\n/** A resolved CSS color as bytes, which the webgl renderer draws with. */\ntype RGBA = [number, number, number, number]\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 * webgl takes the resolved color as bytes from a 1×1 canvas.\n */\nfunction useCanvas(\n scene: React.RefObject<Mark3D[]>,\n width: number,\n height: number,\n renderer: Renderer3D\n) {\n const element = React.useRef<HTMLCanvasElement>(null)\n const colors = React.useRef(new Map<string, string>())\n const bytes = React.useRef(new Map<string, RGBA>())\n const pixel = React.useRef<CanvasRenderingContext2D | null>(null)\n\n const repaint = React.useCallback(() => {\n const canvas = element.current\n if (!canvas) return\n const resolve = (css: string) => {\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 if (renderer === \"webgl\") {\n pixel.current ??= onePixel()\n paintGL(canvas, scene.current, width, height, (css) =>\n colorBytes(resolve(css), pixel.current!, bytes.current)\n )\n } else {\n paint(canvas, scene.current, width, resolve)\n }\n }, [scene, width, height, renderer])\n\n const canvas = React.useCallback(\n // A ref that returns its cleanup is never called with null.\n (node: HTMLCanvasElement) => {\n element.current = node\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 bytes.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 // useRenderer draws on a canvas only where the browser gives one a 2D context.\n const ctx = canvas.getContext(\"2d\")!\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 ? (stroke ?? 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/** A 1×1 canvas whose 2D context resolves a color to bytes, for the webgl renderer. */\nfunction onePixel() {\n const canvas = document.createElement(\"canvas\")\n canvas.width = 1\n canvas.height = 1\n // useRenderer draws with webgl only where the browser gives a canvas a context; a 2D one comes with it.\n return canvas.getContext(\"2d\")!\n}\n\n/** The resolved `color` as bytes, drawn on the 1×1 `pixel` and read back, cached per color. */\nfunction colorBytes(\n color: string,\n pixel: CanvasRenderingContext2D,\n cache: Map<string, RGBA>\n): RGBA {\n let rgba = cache.get(color)\n if (rgba === undefined) {\n pixel.clearRect(0, 0, 1, 1)\n pixel.fillStyle = color\n pixel.fillRect(0, 0, 1, 1)\n rgba = [...pixel.getImageData(0, 0, 1, 1).data] as RGBA\n cache.set(color, rgba)\n }\n return rgba\n}\n\n/**\n * Paints `marks` on a webgl `canvas`, from the view box of `width`×`height` to\n * the pixels of the canvas: a polygon ear by ear, a fan of 12 segments per\n * circle, in paint order and without a depth test, the color of each as bytes.\n */\nfunction paintGL(\n canvas: HTMLCanvasElement,\n marks: Mark3D[],\n width: number,\n height: number,\n color: (css: string) => RGBA\n) {\n canvas.width = Math.round(canvas.clientWidth * devicePixelRatio)\n canvas.height = Math.round(canvas.clientHeight * devicePixelRatio)\n // useRenderer draws with webgl only where the browser gives one a context.\n const gl = canvas.getContext(\"webgl\")!\n gl.viewport(0, 0, canvas.width, canvas.height)\n gl.disable(gl.DEPTH_TEST)\n gl.enable(gl.BLEND)\n gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)\n const program = programOf(gl)\n gl.useProgram(program)\n gl.uniform2f(gl.getUniformLocation(program, \"u_res\"), 2 / width, 2 / height)\n const where = gl.getAttribLocation(program, \"a_pos\")\n gl.enableVertexAttribArray(where)\n gl.bindBuffer(gl.ARRAY_BUFFER, bufferOf(gl))\n gl.vertexAttribPointer(where, 2, gl.FLOAT, false, 0, 0)\n const tint = (css: string) => {\n const [r, g, b, a] = color(css)\n gl.uniform4f(gl.getUniformLocation(program, \"u_color\"), r / 255, g / 255, b / 255, a / 255)\n }\n const draw = (mode: number, points: Point2D[]) => {\n gl.bufferData(\n gl.ARRAY_BUFFER,\n new Float32Array(points.flatMap((p) => [p.x, p.y])),\n gl.DYNAMIC_DRAW\n )\n gl.drawArrays(mode, 0, points.length)\n }\n // A stroke - the focus edge, a ring - draws as a line loop over the outline,\n // as wide as the platform gives a line.\n const [, widest] = (gl.getParameter(gl.ALIASED_LINE_WIDTH_RANGE) as Float32Array | null) ?? [1, 1]\n gl.lineWidth(Math.min(1.5 * devicePixelRatio, widest))\n for (const mark of marks) {\n tint(mark.fill)\n draw(gl.TRIANGLES, trianglesOf(mark))\n if (mark.stroke) {\n tint(mark.stroke)\n draw(gl.LINE_LOOP, outlineOf(mark))\n }\n }\n}\n\n/** The 12 points of the circle around `c` of radius `r`. */\nconst ringOf = (c: Point2D, r: number) =>\n Array.from({ length: 12 }, (_, i) => ({\n x: c.x + r * Math.cos((i / 12) * 2 * Math.PI),\n y: c.y + r * Math.sin((i / 12) * 2 * Math.PI),\n }))\n\n/** The triangles of `mark` as view-box points: its polygon ear by ear, a fan of 12 segments per circle. */\nfunction trianglesOf(mark: Mark3D): Point2D[] {\n const { points, r } = mark\n if (r === undefined) return earsOf(points)\n const ring = ringOf(points[0], r)\n return ring.flatMap((p, i) => [points[0], p, ring[(i + 1) % 12]])\n}\n\n/** Twice the signed area of the triangle `a`, `b`, `c`: its sign tells which way it turns, 0 on a line. */\nconst turn = (a: Point2D, b: Point2D, c: Point2D) =>\n (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)\n\n/**\n * The triangles of a polygon, cut off ear by ear, so a concave one - the\n * front of a ribbon - fills as on the canvas, where a fan would spill over\n * its dents. An ear is a corner that turns the way of the polygon, or not at\n * all, with no other corner inside it; a simple polygon always has one. One\n * that crosses itself may have none, and then loses its first corner.\n */\nfunction earsOf(points: Point2D[]): Point2D[] {\n const left = [...points]\n const way = Math.sign(left.reduce((sum, p, i) => sum + turn(left[0], p, left[i + 1] ?? p), 0))\n const triangles: Point2D[] = []\n while (left.length > 3) {\n const corner = (i: number) => [left.at(i - 1)!, left[i], left[(i + 1) % left.length]]\n const ear = left.findIndex((_, i) => {\n const [a, b, c] = corner(i)\n if (way * turn(a, b, c) < 0) return false\n return !left.some(\n (p) => way * turn(a, b, p) > 0 && way * turn(b, c, p) > 0 && way * turn(c, a, p) > 0\n )\n })\n const i = Math.max(0, ear)\n triangles.push(...corner(i))\n left.splice(i, 1)\n }\n return [...triangles, ...left]\n}\n\n/** The outline of `mark` as view-box points: its polygon, or the ring of its circle. */\nconst outlineOf = (mark: Mark3D) =>\n mark.r === undefined ? mark.points : ringOf(mark.points[0], mark.r)\n\n// The paint program and the vertex buffer of a context, each made once.\nconst programs = new WeakMap<WebGLRenderingContext, WebGLProgram>()\nconst buffers = new WeakMap<WebGLRenderingContext, WebGLBuffer>()\n\n/** The paint program of `gl`, compiled once: view-box points in, clip space out, one color per draw. */\nfunction programOf(gl: WebGLRenderingContext) {\n let program = programs.get(gl)\n if (!program) {\n program = gl.createProgram()!\n gl.attachShader(\n program,\n shaderOf(\n gl,\n gl.VERTEX_SHADER,\n \"attribute vec2 a_pos; uniform vec2 u_res; void main() { gl_Position = vec4(a_pos.x * u_res.x - 1.0, 1.0 - a_pos.y * u_res.y, 0.0, 1.0); }\"\n )\n )\n gl.attachShader(\n program,\n shaderOf(\n gl,\n gl.FRAGMENT_SHADER,\n \"precision mediump float; uniform vec4 u_color; void main() { gl_FragColor = u_color; }\"\n )\n )\n gl.linkProgram(program)\n programs.set(gl, program)\n }\n return program\n}\n\nfunction shaderOf(gl: WebGLRenderingContext, type: number, source: string) {\n const shader = gl.createShader(type)!\n gl.shaderSource(shader, source)\n gl.compileShader(shader)\n return shader\n}\n\nfunction bufferOf(gl: WebGLRenderingContext) {\n let buffer = buffers.get(gl)\n if (!buffer) {\n buffer = gl.createBuffer()!\n buffers.set(gl, buffer)\n }\n return buffer\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 === \"svg\") return null\n\n return (\n <canvas\n // A canvas that gave out one context cannot give another, so each renderer gets its own.\n key={renderer}\n data-slot=\"chart-3d-canvas\"\n ref={canvas}\n className=\"pointer-events-none absolute top-0 left-0 w-full mask-x-from-96% mask-y-from-96%\"\n style={{ aspectRatio: `${width} / ${height}` }}\n />\n )\n}\n\n// The ends of the axes of the gizmo, in the space of d3-3d, where y points down: up in the chart.\nconst GIZMO = [\n { axis: \"x\", x: 1, y: 0, z: 0 },\n { axis: \"y\", x: 0, y: -1, z: 0 },\n { axis: \"z\", x: 0, y: 0, z: 1 },\n]\n\nconst CORNERS = {\n \"top-left\": \"top-2 left-2\",\n \"top-right\": \"top-2 right-2\",\n \"bottom-left\": \"bottom-2 left-2\",\n \"bottom-right\": \"bottom-2 right-2\",\n}\n\n/**\n * The axes of the world in a corner of the chart: turned with the camera,\n * neither panned nor zoomed, the axis nearest the camera on top. An axis\n * draws in `currentColor`, so a text color on its `data-axis` recolors it.\n */\nfunction ChartGizmo3D({\n camera,\n corner,\n}: {\n camera: Camera3DInstance\n corner: ChartContainer3DProps[\"gizmo\"]\n}) {\n if (!corner) return null\n // The letters at the ends, in a box of 48 around its middle.\n const eye = camera3D()\n .origin({ x: 24, y: 24 })\n .scale(18)\n .rotateY(camera.rotateY())\n .rotateX(camera.rotateX())\n const ends = points3D<(typeof GIZMO)[number]>().camera(eye).data(GIZMO).sort(sort)\n\n return (\n <svg\n data-slot=\"chart-3d-gizmo\"\n viewBox=\"0 0 48 48\"\n aria-hidden=\"true\"\n className={cn(\"pointer-events-none absolute size-12 text-muted-foreground\", CORNERS[corner])}\n >\n {ends.map(({ axis, projected: p }) => (\n <g key={axis} data-axis={axis}>\n <line\n x1={24}\n y1={24}\n x2={24 + (p.x - 24) * 0.6}\n y2={24 + (p.y - 24) * 0.6}\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n />\n <text\n x={p.x}\n y={p.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fill=\"currentColor\"\n className=\"text-[10px] font-medium\"\n >\n {axis.toUpperCase()}\n </text>\n </g>\n ))}\n </svg>\n )\n}\n\n/**\n * The focus edge of a fill: `--chart-3d-focus`, or the fill itself lightened,\n * so the highlight carries the color of what it highlights.\n */\nconst focusOf = (fill: string) => `var(--chart-3d-focus, color-mix(in oklch, ${fill} 60%, white))`\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 const lit = useLit(marks)\n // The lit marks get an edge in the focus color - `--chart-3d-focus`, their own fill\n // lightened unless set - unless they carry their own stroke: a background ring turns\n // into the edge, a flow's inner faces keep their color, so no seams. The fill never changes\n // on hover, and the order, and with it the depth, stays as painted.\n const drawn = marks.map((mark) =>\n lit(mark)\n ? {\n ...mark,\n stroke:\n mark.stroke && mark.stroke !== \"var(--background)\" ? mark.stroke : focusOf(mark.fill),\n }\n : mark\n )\n React.useLayoutEffect(() => {\n scene.current = drawn\n repaint()\n })\n\n if (renderer !== \"svg\") return null\n return (\n <g data-slot=\"chart-3d-marks\">\n {drawn.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={stroke ?? fill}\n strokeWidth={stroke === focusOf(fill) ? 1.5 : 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 </g>\n )\n}\n\n/**\n * A label beside a mark, at `at` in the units of the view box. `toward`, a\n * unit vector, lays the label on that side of `at`, touching it, and slides\n * it round `at` as the vector turns; without it, `anchor` is the end of the\n * text that sits at `at`.\n */\nexport type Label3D = {\n key: string\n at: Point2D\n text: React.ReactNode\n anchor?: \"start\" | \"middle\" | \"end\"\n toward?: Point2D\n}\n\n/**\n * The labels of the marks of a chart, ringed by the background so that they\n * read on the marks. Like the labels of the box, they are SVG with every renderer.\n */\nfunction Labels3D({ labels }: { labels: Label3D[] }) {\n // ponytail: under the canvas of the canvas renderer, as the labels of the box; an SVG layer over the canvas would lift them.\n return (\n <g data-slot=\"chart-3d-labels\">\n {labels.map((label) => {\n const { x, y } = label.toward\n ? beside(label.at, label.toward, textWidth(label.text, 10), 10, 0)\n : label.at\n return (\n <text\n key={label.key}\n x={x}\n y={y}\n textAnchor={label.toward ? \"middle\" : label.anchor}\n dominantBaseline=\"central\"\n paintOrder=\"stroke\"\n strokeWidth={3}\n strokeLinejoin=\"round\"\n className=\"fill-foreground stroke-background text-[10px] font-medium\"\n >\n {label.text}\n </text>\n )\n })}\n </g>\n )\n}\n\nfunction ChartStyle({ id, config }: { id: string; config: ChartConfig }) {\n const colorConfig = Object.entries(config).filter(([, c]) => c.theme || c.color)\n // Every part of the axes that enters fades in: a label, a tick mark, a gridline, a wall.\n // The cursor names the gesture of the held modifier: the platform modifier\n // a hand (Alt, held with it, wins, as it does on pointer down), Alt the four\n // arrows of the pan, the wheel zoom its direction, and a turning drag grabbing.\n const entering = [\"text\", \"line\", \"path\"]\n .map((el) => `[data-chart=${id}] [data-slot=\"chart-3d-axes\"] ${el}`)\n .join(\", \")\n const base = `@keyframes chart-3d-axes-in { from { opacity: 0; } }\n${entering} { animation: chart-3d-axes-in 300ms ease-out; }\n@media (prefers-reduced-motion: reduce) { ${entering} { animation: none; } }\n[data-chart=${id}] svg[data-mod=\"true\"] { cursor: grab; }\n[data-chart=${id}] svg[data-alt=\"true\"] { cursor: move; }\n[data-chart=${id}] svg[data-zoom=\"in\"] { cursor: zoom-in; }\n[data-chart=${id}] svg[data-zoom=\"out\"] { cursor: zoom-out; }\n[data-chart=${id}] svg[data-orbiting=\"true\"] { cursor: grabbing; }`\n\n if (!colorConfig.length) {\n return <style dangerouslySetInnerHTML={{ __html: base }} />\n }\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: [\n base,\n ...Object.entries(THEMES).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({ tip }: { tip: Tip3D }) {\n const { tooltip, ref, place } = tip\n // Before the browser paints it, so a new tooltip never shows where the last one was.\n React.useLayoutEffect(place, [tooltip, place])\n if (!tooltip) return null\n\n return (\n <div\n ref={ref}\n data-slot=\"chart-3d-tooltip\"\n // As wide as its content wherever it sits, so a tooltip near the right edge is measured whole.\n className=\"pointer-events-none absolute z-10 grid w-max min-w-32 gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl motion-safe:transition-[translate]\"\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, named `label`, that lists the rows of\n * its keymap. The `help` keys on the chart open and close the list, Escape\n * closes it.\n */\nfunction ChartShortcuts3D({ rows, help, label }: Pick<Keymap, \"rows\" | \"help\" | \"label\">) {\n const [open, setOpen] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n const id = React.useId()\n // A dependency that stays the same while the keys do; no key is a line break.\n const keys = help.join(\"\\n\")\n\n React.useEffect(() => {\n const chart = ref.current?.parentElement\n const onKeyDown = (e: KeyboardEvent) => {\n if (keys.split(\"\\n\").includes(pressed(e))) setOpen((o) => !o)\n if (e.key === \"Escape\") setOpen(false)\n }\n chart?.addEventListener(\"keydown\", onKeyDown)\n return () => chart?.removeEventListener(\"keydown\", onKeyDown)\n }, [keys])\n\n // A pointer down outside the corner closes the list; the press still lands.\n React.useEffect(() => {\n if (!open) return\n const onPointerDown = (e: Event) => {\n if (!ref.current?.contains(e.target as Node)) setOpen(false)\n }\n document.addEventListener(\"pointerdown\", onPointerDown)\n return () => document.removeEventListener(\"pointerdown\", onPointerDown)\n }, [open])\n\n // Without a key or a panel, there is nothing to list.\n if (!rows.length) return null\n return (\n <div\n ref={ref}\n data-slot=\"chart-3d-shortcuts\"\n className=\"absolute top-2 right-2 z-10 flex flex-col items-end gap-1\"\n >\n <button\n type=\"button\"\n data-slot=\"chart-3d-shortcuts-trigger\"\n aria-label={label}\n aria-expanded={open}\n aria-controls={open ? id : undefined}\n onClick={() => setOpen((o) => !o)}\n className=\"inline-flex size-7 cursor-pointer items-center justify-center rounded-md bg-background/60 text-muted-foreground outline-none transition-colors hover:bg-background hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 [&_svg]:size-4\"\n >\n <KeyboardIcon />\n </button>\n {open && <ChartShortcutList3D id={id} rows={rows} />}\n </div>\n )\n}\n\n/** One group of keys as chips. */\nfunction KbdGroup3D({ group }: { group: string[] }) {\n return (\n <span data-slot=\"kbd-group\" className=\"flex gap-1\">\n {group.map((key, j) => (\n <kbd\n key={j}\n data-slot=\"kbd\"\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 )\n}\n\n/** The list of the shortcut panel: per row its label, then its keys, a rule, and its gestures. */\nfunction ChartShortcutList3D({ id, rows }: { id: string; rows: Keymap[\"rows\"] }) {\n return (\n <dl\n id={id}\n data-slot=\"chart-3d-shortcuts-panel\"\n 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 >\n {rows.map(({ label, keys, gestures }) => (\n <React.Fragment key={label}>\n <dt data-slot=\"chart-3d-shortcuts-label\" className=\"text-muted-foreground\">\n {label}\n </dt>\n <dd className=\"flex flex-wrap items-center justify-end gap-x-2 gap-y-1\">\n {keys.map((group, i) => (\n <KbdGroup3D key={i} group={group} />\n ))}\n {keys.length > 0 && gestures.length > 0 && (\n <span data-slot=\"chart-3d-shortcuts-rule\" className=\"h-4 w-px bg-border\" />\n )}\n {gestures.map((group, i) => (\n <KbdGroup3D key={i} group={group} />\n ))}\n </dd>\n </React.Fragment>\n ))}\n </dl>\n )\n}\n\nfunction ChartLegend3D({ config }: { config: ChartConfig }) {\n return (\n <div data-slot=\"chart-3d-legend\" 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, the line of every axis along its edge with the mark of each of\n * its ticks, and the labels of every axis on each of its four edges. Only the\n * edge the axis sits on shows them, so when the axis moves to another edge,\n * its line, its marks and its labels fade from one to the other.\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 = intoWorld(axes3D().camera(camera), world)\n const { labels, lines, marks } = labelAxes(box.edges(spec), spec, format, titles)\n // The gridline of a tick the new data dropped fades out with its label.\n const leaving = new Set(\n ([\"x\", \"y\", \"z\"] as const).flatMap((a) =>\n ((spec[a] as GlidingAxis).leaving ?? []).map((value) => `${a}-${value}`)\n )\n )\n\n return (\n <g data-slot=\"chart-3d-axes\">\n {box\n .data(spec)\n .filter((wall) => !wall.ccw)\n .map((wall) => (\n <React.Fragment key={`${wall.axis}${wall.side}`}>\n <path d={quad(wall)} className=\"fill-muted/40 stroke-border\" strokeWidth={0.75} />\n {wall.grid.map((segment) => {\n const [from, to] = [segment[0], segment[segment.length - 1]]\n const key = gridKey(wall, from, to)\n return (\n <line\n key={key}\n x1={from.projected.x}\n y1={from.projected.y}\n x2={to.projected.x}\n y2={to.projected.y}\n style={{ opacity: leaving.has(key) ? 0 : 1 }}\n className=\"stroke-border transition-opacity duration-300 ease-out motion-reduce:transition-none\"\n strokeWidth={0.75}\n />\n )\n })}\n </React.Fragment>\n ))}\n {lines.map((line) => (\n <AxisLine3D key={line.key} line={line} ink=\"stroke-foreground\" width={1.5} />\n ))}\n {marks.map((mark) => (\n <AxisLine3D key={mark.key} line={mark} ink=\"stroke-foreground/60\" width={1} />\n ))}\n {labels.map((label) => (\n <AxisLabel3D key={label.key} label={label} />\n ))}\n </g>\n )\n}\n\n// The space between a tick and its label, the least space between two\n// labels, and the space over which a label fades as it nears another.\nconst GAP = 10\nconst PAD = 2\nconst FADE = 4\n// How far a label may slide along its edge to make room, before the labels take two rows.\nconst DODGE = 12\n// How far the mark of a tick reaches out from its edge.\nconst MARK = 6\n\n/** The closed quad of a wall; its gridlines are their own lines, so a new one fades in. */\nfunction quad(wall: AxisWall) {\n return `M${wall.map(({ projected }) => `${projected.x},${projected.y}`).join(\"L\")}Z`\n}\n\n/**\n * The key of a gridline: the axis and value of the tick it marks - the one\n * coordinate its ends share beside the wall's own axis - so the gridline of\n * a tick that stays glides on, and one of a new tick mounts and fades in.\n * Exactly one coordinate differs along the line, because a domain always has\n * width: `axis` widens an empty extent.\n */\nfunction gridKey(wall: AxisWall, from: Point3D, to: Point3D) {\n const axis = ([\"x\", \"y\", \"z\"] as const).find((a) => a !== wall.axis && from[a] === to[a])!\n return `${axis}-${from[axis]}`\n}\n\n/**\n * A line of an axis: the line that carries its scale along the edge it sits\n * on, or the mark of one of its ticks. Its place follows the camera at once;\n * a change of edge fades it in a transition.\n */\ntype AxisLine = {\n key: string\n from: Point2D\n to: Point2D\n opacity: number\n}\n\n/**\n * A label of the chart box, a tick label or the title of an axis: its box\n * `w`×`h` in the units of the view box, centred at `at` and moved by `shift`\n * along its edge or into a second row.\n */\ntype AxisLabel = {\n key: string\n axis: keyof AxesSpec\n /** The tick value; the axis title has none. */\n value?: number\n at: Point2D\n w: number\n h: number\n shift: Point2D\n text: React.ReactNode\n opacity: number\n title?: boolean\n}\n\n/**\n * The labels of the axes on all their edges, the line of every axis along its\n * edge and the mark of each of its ticks, shown on the edges the axes sit on.\n * Every edge fits its own tick labels; then the labels of an axis give way to\n * those of an axis with fewer ticks, which say more each, and the titles give\n * way to the ticks.\n */\nfunction labelAxes(\n edges: AxisEdge[],\n spec: AxesSpec,\n format: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>,\n titles: Partial<Record<keyof AxesSpec, React.ReactNode>>\n) {\n // An axis without ticks, such as the rows of an empty chart, has nothing to label.\n const axes = edges\n .filter((edge) => edge.length)\n .map((edge) =>\n edgeLabels(edge, spec[edge.axis], format[edge.axis] ?? String, titles[edge.axis])\n )\n const shown = axes.filter((axis) => axis.chosen).sort((a, b) => a.ticks.length - b.ticks.length)\n const placed: AxisLabel[] = []\n for (const label of [...shown.flatMap((a) => a.ticks), ...shown.flatMap((a) => a.title ?? [])]) {\n // A tick outside the gliding ends stays faded out and does not take room from the others.\n if (label.opacity === 0) continue\n label.opacity = shows(label, placed)\n placed.push(label)\n }\n // The marks fade with their labels, also where a label of another axis takes its place.\n for (const axis of axes) axis.marks.forEach((mark, i) => (mark.opacity = axis.ticks[i].opacity))\n return {\n labels: axes.flatMap((axis) => [...axis.ticks, ...(axis.title ? [axis.title] : [])]),\n lines: axes.map((axis) => axis.line),\n marks: axes.flatMap((axis) => axis.marks),\n }\n}\n\n/**\n * The labels of one edge: a label per tick beside it, away from the box, in\n * the rows that `fit` finds, and the title of the axis beyond them. The\n * labels of an edge the axis does not sit on are there, but do not show.\n */\n/**\n * The point of `value` along `edge`, between the ticks that bracket it: the\n * projection keeps the edge straight, so the point lies on their line. An\n * axis of one tick is a point.\n */\nfunction along(edge: AxisEdge, value: number): Point2D {\n if (edge.length === 1) return edge[0].projected\n let i = 0\n while (i < edge.length - 2 && edge[i + 1][edge.axis] < value) i += 1\n const [a, b] = [edge[i][edge.axis], edge[i + 1][edge.axis]]\n // Neighbouring ticks are distinct values, so their span has width.\n const t = clamp(0, 1, (value - a) / (b - a))\n const [p, q] = [edge[i].projected, edge[i + 1].projected]\n return { x: p.x + (q.x - p.x) * t, y: p.y + (q.y - p.y) * t }\n}\n\n/** The ticks whose value lies in `domain`, with the ends of `domain`. */\nfunction inRange(ticks: AxisLabel[], domain: number[]) {\n const range = { lo: Math.min(...domain), hi: Math.max(...domain) }\n return {\n ranged: ticks.filter((t) => t.value !== undefined && within(range.lo, range.hi, t.value)),\n range,\n }\n}\n\n/** An edge the axis does not sit on hides its labels; on a chosen one, the ticks outside the gliding ends fade out. */\nfunction hideOffRange(labels: AxisLabel[], range: { lo: number; hi: number }, chosen: boolean) {\n if (!chosen) for (const l of labels) l.opacity = 0\n else\n for (const l of labels)\n if (l.value !== undefined && !within(range.lo, range.hi, l.value)) l.opacity = 0\n}\n\nfunction edgeLabels(\n edge: AxisEdge,\n { domain, leaving = [], span }: GlidingAxis,\n format: (value: number) => React.ReactNode,\n title?: React.ReactNode\n) {\n const { axis, normal: n, chosen } = edge\n const label = (\n key: string,\n at: Point2D,\n text: React.ReactNode,\n h: number,\n gap: number,\n value?: number\n ) => {\n const w = textWidth(text, h)\n return { key, axis, value, at: beside(at, n, w, h, gap), w, h, shift: ZERO, text, opacity: 1 }\n }\n const id = `${axis}${edge.sides.join(\"\")}`\n // Keyed by value, so a tick that new data keeps glides on as the same label.\n const ticks = edge.map((tick) =>\n label(`${id}-${tick[axis]}`, tick.projected, format(tick[axis]), 10, GAP, tick[axis])\n )\n // A tick the new data dropped fades out in place and takes no room from the others.\n for (const t of ticks) if (t.value !== undefined && leaving.includes(t.value)) t.opacity = 0\n // Ticks outside the gliding ends fade out; only the ones inside take room.\n const { ranged, range } = inRange(\n ticks.filter((t) => t.opacity > 0),\n domain\n )\n // How far a row of labels reaches out from the edge.\n const depth = Math.max(0, ...ranged.map((t) => Math.abs(n.x) * t.w + Math.abs(n.y) * t.h))\n const row = { x: n.x * (depth + PAD), y: n.y * (depth + PAD) }\n const rows = fit(ranged, n, row)\n // The line of the axis runs the gliding span of its ticks, within the\n // gliding ends: a tick beyond them would drag it out of the box, and one\n // the data adds or drops would make it jump instead of glide.\n const [s0, s1] = span ?? [edge[0][axis], edge[edge.length - 1][axis]]\n const start = along(edge, clamp(range.lo, range.hi, s0))\n const end = along(edge, clamp(range.lo, range.hi, s1))\n const middle = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 }\n const head: AxisLabel | undefined = title\n ? { ...label(`${id}-title`, middle, title, 12, GAP + depth + GAP), title: true }\n : undefined\n if (head && rows === 2) head.shift = row\n // The edges the axis does not sit on keep their labels in place, unseen, to fade them in.\n hideOffRange([...ticks, ...(head ? [head] : [])], range, chosen)\n // The axis line runs its edge between its outermost ticks; a mark points out from every\n // tick, as far out as its label is clear of it, and hides where the label does.\n const line: AxisLine = { key: id, from: start, to: end, opacity: chosen ? 1 : 0 }\n const marks = edge.map((tick, i) => ({\n key: ticks[i].key,\n from: tick.projected,\n to: { x: tick.projected.x + n.x * MARK, y: tick.projected.y + n.y * MARK },\n opacity: ticks[i].opacity,\n }))\n return { chosen, ticks, title: head, line, marks }\n}\n\n/**\n * Fits the tick labels of an edge into the space between its ticks: in one\n * row if they keep `PAD` apart, or slid along the edge if no label has to\n * slide further than `DODGE`, else every other label a `row` further out if\n * that is enough, else every `stride`-th label of one row, 2, 4, 8… The\n * labels of a stride are among those of the one before, so as the edge\n * shortens, a label only ever leaves and none comes in for it. Returns the rows.\n */\nfunction fit(ticks: AxisLabel[], normal: Point2D, row: Point2D) {\n if (clear(ticks, 1) || slide(ticks, normal)) return 1\n ticks.forEach((t, i) => (t.shift = i % 2 ? row : ZERO))\n if (clear(ticks, 2)) return 2\n ticks.forEach((t) => (t.shift = ZERO))\n let stride = 2\n while (stride < ticks.length && !clear(ticks, stride, stride)) stride *= 2\n ticks.forEach((t, i) => (t.opacity = i % stride ? 0 : 1))\n return 1\n}\n\n/** Whether every label from every `every`-th keeps `PAD` apart from the one `step` after it. */\nfunction clear(ticks: AxisLabel[], step: number, every = 1) {\n // A hair under PAD, as labels that `slide` sets exactly PAD apart may round to less.\n return ticks.every(\n (t, i) => i % every > 0 || i + step >= ticks.length || apart(t, ticks[i + step]) > PAD - 1e-6\n )\n}\n\n/**\n * Slides the labels of an edge along it, square to its `normal`, as little\n * as they can until each has the room it needs. True if that is enough and\n * no label slides further than `DODGE`; the slide grows from nothing as the\n * labels near, so it follows the camera without a jump.\n */\nfunction slide(ticks: AxisLabel[], normal: Point2D) {\n const t = { x: -normal.y, y: normal.x }\n const along = ({ at }: AxisLabel) => at.x * t.x + at.y * t.y\n // The labels in their order along the edge, whichever way its ticks run.\n const line = [...ticks].sort((a, b) => along(a) - along(b))\n const gaps = line.slice(1).map((b, i) => room(line[i], b, normal, t))\n const placed = dodge(line.map(along), gaps)\n line.forEach((label, i) => {\n const d = placed[i] - along(label)\n label.shift = { x: t.x * d, y: t.y * d }\n })\n return line.every((label, i) => Math.abs(placed[i] - along(label)) <= DODGE) && clear(ticks, 1)\n}\n\n/**\n * How far along `t` the label `b` has to stand from `a`, which comes before\n * it there, for their boxes to keep `PAD` apart, as far as they stand apart\n * along `normal`, square to `t`.\n */\nfunction room(a: AxisLabel, b: AxisLabel, normal: Point2D, t: Point2D) {\n const off = (b.at.x - a.at.x) * normal.x + (b.at.y - a.at.y) * normal.y\n const x = ((a.w + b.w) / 2 + PAD - off * normal.x * Math.sign(t.x)) / Math.abs(t.x)\n const y = ((a.h + b.h) / 2 + PAD - off * normal.y * Math.sign(t.y)) / Math.abs(t.y)\n return Math.min(x, y)\n}\n\n/**\n * Places points on a line in their order, `gaps[i]` at least between the\n * i-th and the next, and moves them as little as it can: points that would\n * come too close move as one block, centred on the places they want.\n */\nfunction dodge(want: number[], gaps: number[]) {\n const blocks: { start: number; offsets: number[]; at: number }[] = []\n want.forEach((at, start) => {\n let block = { start, offsets: [0], at }\n let last = blocks.at(-1)\n while (last && last.at + last.offsets.at(-1)! + gaps[block.start - 1] > block.at) {\n blocks.pop()\n const base = last.offsets.at(-1)! + gaps[block.start - 1]\n const offsets = [...last.offsets, ...block.offsets.map((o) => o + base)]\n const first = last.start\n // Where the block moves its points the least: the mean of the places they want.\n const mean = offsets.reduce((sum, o, k) => sum + want[first + k] - o, 0) / offsets.length\n block = { start: first, offsets, at: mean }\n last = blocks.at(-1)\n }\n blocks.push(block)\n })\n return blocks.flatMap((block) => block.offsets.map((o) => block.at + o))\n}\n\n/**\n * How much of a label shows beside the labels placed before it: it fades as\n * it nears a label of another axis, by as much as that one shows. As this\n * follows the geometry, the label fades as smoothly as the camera turns.\n */\nfunction shows(label: AxisLabel, placed: AxisLabel[]) {\n return placed.reduce(\n (opacity, p) =>\n p.axis === label.axis\n ? opacity\n : Math.min(opacity, 1 - (1 - clamp(0, 1, apart(label, p) / FADE)) * p.opacity),\n label.opacity\n )\n}\n\n/** The space between the boxes of two labels, negative where they overlap. */\nfunction apart(a: AxisLabel, b: AxisLabel) {\n const dx = Math.abs(a.at.x + a.shift.x - b.at.x - b.shift.x) - (a.w + b.w) / 2\n const dy = Math.abs(a.at.y + a.shift.y - b.at.y - b.shift.y) - (a.h + b.h) / 2\n return Math.max(dx, dy)\n}\n\n/**\n * The centre of a box `w`×`h` that lies `gap` from `at` towards `toward`, a\n * unit vector. As the vector turns, the box slides round `at` and keeps the\n * gap, where an anchor that switches from start to end would jump.\n */\nfunction beside(at: Point2D, toward: Point2D, w: number, h: number, gap: number): Point2D {\n const out = gap + (Math.abs(toward.x) * w + Math.abs(toward.y) * h) / 2\n return { x: at.x + toward.x * out, y: at.y + toward.y * out }\n}\n\n/** The width of a label at the font size `size`, guessed from its text, as the browser lays it out only after the render. */\nfunction textWidth(text: React.ReactNode, size: number) {\n // ponytail: 0.6em a character; measure with getBBox if wide fonts or rich labels still overlap.\n const chars = typeof text === \"string\" || typeof text === \"number\" ? String(text).length : 4\n return chars * size * 0.6\n}\n\n/**\n * A line of the axes, in the ink of the kind it is: the line of an axis along\n * its edge, or the mark of one of its ticks. Its place follows the camera at\n * once; a change of edge fades it in a transition.\n */\nfunction AxisLine3D({\n line: { from, to, opacity },\n ink,\n width,\n}: {\n line: AxisLine\n ink: string\n width: number\n}) {\n return (\n <line\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n strokeWidth={width}\n style={{ opacity: Math.round(opacity * 100) / 100 }}\n className={cn(\"transition-opacity duration-300 ease-out motion-reduce:transition-none\", ink)}\n />\n )\n}\n\n/**\n * A label of the chart box. Its place follows the camera at once; a change\n * of edge, of row or of the labels that fit fades and moves it in a transition.\n */\nfunction AxisLabel3D({ label: { at, shift, opacity, text, title } }: { label: AxisLabel }) {\n return (\n <text\n x={at.x}\n y={at.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n style={{ opacity: Math.round(opacity * 100) / 100, translate: `${shift.x}px ${shift.y}px` }}\n className={cn(\n \"transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none\",\n title ? \"fill-foreground font-medium\" : \"fill-muted-foreground text-[10px]\"\n )}\n >\n {text}\n </text>\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/**\n * The axis `spec` with its domain widened by half a `cell` on each side, so\n * the box keeps room between the outermost data and its walls. The ticks stay\n * where they were, on the data.\n */\nfunction pad(spec: AxisSpec, cell: number): AxisSpec {\n return { domain: [spec.domain[0] - cell / 2, spec.domain[1] + cell / 2], ticks: spec.ticks }\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/**\n * Hands the projection its accessors into the world box, so every chart maps\n * its shapes onto the screen the same way.\n */\nfunction intoWorld<Datum extends Point3D, T extends ShapeInstance<Datum>>(\n projection: T,\n world: World\n): T {\n return projection\n .x((p) => world.x(p.x))\n .y((p) => world.y(p.y))\n .z((p) => world.z(p.z))\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/**\n * `color` at `opacity`, from 0 to 1: a CSS color-mix with transparent, so a\n * mark fades on every renderer while its color stays in CSS. Rounded to a\n * percent, so the renderers that resolve colors cache a bounded few. Fade\n * after `shade`, which would mix a translucent color back towards opaque.\n */\nfunction faded(color: string, opacity: number) {\n const percent = Math.round(opacity * 100)\n return percent >= 100 ? color : `color-mix(in oklab, ${color} ${percent}%, transparent)`\n}\n\n/**\n * The entries of `data` and their series, for a chart that lays the entries\n * out along x and the series along z, as the bar and the area chart do. The\n * name of every entry comes from its `index` field, the series are `keys` or\n * the keys of the config, and the `target` of every cell is keyed by the name\n * of its entry and its series, so it follows its entry when the data\n * reorders; a value that is not a number stands as 0. Each glides by name:\n * `values` from 0, `rows` - the place of every entry - to where it stands, and\n * `presence` from 0 to 1 as an entry comes and back as it goes, the gone ones\n * still among them. `labels` name the ticks: the entry at a tick of x, through\n * `format.x` - a tick of a gone entry fades out unnamed - and the series at a\n * tick of z.\n */\nfunction useSeries<T extends Record<string, unknown>>({\n data,\n index,\n keys,\n format = {},\n}: {\n data: T[]\n index: keyof T & string\n keys?: string[]\n format?: { x?: (label: string) => React.ReactNode; y?: (value: number) => React.ReactNode }\n}) {\n const { config } = useChart3D()\n const series = keys ?? Object.keys(config)\n const names = data.map((d) => String(d[index] ?? \"\"))\n const target = Object.fromEntries(\n data.flatMap((d, i) => series.map((key) => [`${names[i]}-${key}`, Number(d[key]) || 0]))\n )\n const labels = {\n x: (i: number) => (format.x ?? String)(names[i] ?? \"\"),\n y: format.y,\n z: (j: number) => config[series[j]]?.label ?? series[j],\n }\n return {\n series,\n target,\n values: useTween(target, 0),\n rows: useTween(Object.fromEntries(names.map((name, i) => [name, i]))),\n presence: useTween(Object.fromEntries(names.map((name) => [name, 1])), 0),\n labels,\n }\n}\n\n/** The marks of a cube: its faces that look at the camera, shaded in `color`, each with `tooltip` on hover. */\nfunction cubeMarks(id: string, faces: CubeFace[], color: string, tooltip: Tooltip3D): Mark3D[] {\n // The faces point outwards: a convex shape 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\nexport {\n ChartContainer3D,\n ChartLegend3D,\n Axes3D,\n Marks3D,\n Labels3D,\n axis,\n pad,\n linear,\n worldBox,\n intoWorld,\n shade,\n faded,\n useSeries,\n cubeMarks,\n useTween,\n useTweenAxes,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { range, ticks } from \"d3-array\"\nimport {\n polygons3D,\n sort,\n type AxesSpec,\n type Point3D,\n type Polygon,\n type Polygons3DInstance,\n} from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n intoWorld,\n pad,\n useSeries,\n shade,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n type Mark3D,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type AreaChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per point along x, with a value per series. */\n data: T[]\n /** The field that names each entry, such as \"year\"; a point follows its name through updates, so the names should be unique. */\n index: keyof T & string\n /**\n * The fields that hold the series, one ribbon each.\n * @defaultValue the keys of the chart config\n */\n keys?: string[]\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// The share of its row along z a ribbon covers.\nconst RIBBON = 2 / 3\n\n/**\n * Areas pushed back into ribbons: the entries of `data` along x, one ribbon\n * per series along z, the area under its line reaching down to the floor of\n * the box. The series are the keys of the chart config unless `keys` names\n * them.\n */\nexport function AreaChart3D<T extends Record<string, unknown>>({\n data,\n index,\n keys,\n format = {},\n titles,\n}: AreaChart3DProps<T>) {\n const { config, camera } = useChart3D()\n // The rows glide to their new places, and an entry that comes or goes\n // unfolds from its neighbour as far as its presence.\n const { series, target, values, rows, presence, labels } = useSeries({\n data,\n index,\n keys,\n format,\n })\n const spec = useTweenAxes(areaAxes(data.length, series.length, Object.values(target)))\n // The box deepens with the series, so a ribbon stays a ribbon, and glides\n // there with the axes.\n const depth = useTween({ depth: Math.min(1, Math.max(0.25, series.length / 6)) }).depth\n const world = worldBox(spec, depth)\n const polygons = intoWorld(polygons3D().camera(camera), world)\n // The x axis keeps half a row beyond the first and the last entry.\n const ends = [spec.x.domain[0] + 0.5, spec.x.domain[1] - 0.5]\n const toward = Math.sign(camera.viewDirection().x)\n const marks = series\n .flatMap((key, j) => {\n const line = linePoints(rows, values, presence, key, ends)\n if (!line.length) return []\n const z = [j - RIBBON / 2, j + RIBBON / 2]\n return [{ key, line, faces: ribbonFaces(polygons, line, spec.y.domain[0], z) }]\n })\n // The ribbons lie in slices of z of their own, and their floors span the\n // same x at the same height: ordered by the middle of the floor, they are\n // painted back to front exactly.\n .sort((a, b) => sort(a.faces[4], b.faces[4]))\n .flatMap(({ key, line, faces }) =>\n ribbonMarks(key, painted(faces, toward), line, config[key]?.label ?? key, format.x ?? String)\n )\n\n return (\n <>\n <Axes3D spec={spec} world={world} titles={titles} format={labels} />\n <Marks3D marks={marks} />\n </>\n )\n}\n\n/** One point of a line: the entry it stands for, its place along x and its value. */\ntype LinePoint = { name: string; x: number; value: number }\n\n/** One face of a ribbon after the projection, with its name and, on the top, its segment. */\ntype RibbonFace = Polygon<\n Point3D,\n Point3D[] & { face: \"front\" | \"back\" | \"left\" | \"right\" | \"bottom\" | \"top\"; segment: number }\n>\n\n/**\n * The points of the line of the series `key`, in order along x: every entry,\n * the ones still gliding away among them, at its gliding row and value. An\n * entry that comes or goes unfolds from the point before it - the one after\n * it, at the start of the line - and folds back into it, as far as its\n * `presence`, so the ribbon opens and closes without a step. Its value comes\n * from nothing as its presence grows - the two glide in step - so the part of\n * its neighbour it has not yet left is added: the point heads straight from\n * the neighbour to its own, never down towards the floor. Every\n * point stays within the gliding `ends` of the x axis, so a line with no\n * neighbour to unfold from - one that was empty - grows inside the box\n * instead of standing beyond its walls. A point only one of the tweens still\n * knows is on its way out and stays unseen.\n */\nfunction linePoints(\n rows: Record<string, number>,\n values: Record<string, number>,\n presence: Record<string, number>,\n key: string,\n [lo, hi]: number[]\n): LinePoint[] {\n const own = Object.entries(rows)\n .sort(([, a], [, b]) => a - b)\n .flatMap(([name, x]) => {\n const value = values[`${name}-${key}`]\n return value === undefined ? [] : [{ name, x, value, seen: presence[name] }]\n })\n let anchor = own.find((p) => p.seen === 1)\n return own\n .map((p) => {\n if (p.seen === 1) anchor = p\n const { x } = anchor ?? p\n return {\n name: p.name,\n x: Math.min(hi, Math.max(lo, x + p.seen * (p.x - x))),\n value: p.value + (1 - p.seen) * (anchor?.value ?? 0),\n }\n })\n .sort((a, b) => a.x - b.x)\n}\n\n/**\n * The faces of the ribbon of `line`, projected: the area under the line,\n * down to `floor`, pushed back from `z[0]` to `z[1]`. Each is wound\n * counter-clockwise as seen from outside, so `ccw` tells whether it faces the\n * camera. The first five lie on its bounding box - the front and the back,\n * one polygon each however many points the line has, the two ends and the\n * bottom - the rest are its top, one quad per segment of the line.\n */\nfunction ribbonFaces(\n polygons: Polygons3DInstance<Point3D>,\n line: LinePoint[],\n floor: number,\n [back, front]: number[]\n): RibbonFace[] {\n const on = (p: LinePoint, z: number) => ({ x: p.x, y: p.value, z })\n const under = (p: LinePoint, z: number) => ({ x: p.x, y: floor, z })\n const face = (name: RibbonFace[\"face\"], points: Point3D[], segment = -1) =>\n Object.assign(points, { face: name, segment })\n const [a, o] = [line[0], line[line.length - 1]]\n return polygons.data([\n face(\"front\", [\n on(a, front),\n under(a, front),\n under(o, front),\n ...line\n .slice(1)\n .reverse()\n .map((p) => on(p, front)),\n ]),\n face(\"back\", [...line.map((p) => on(p, back)), under(o, back), under(a, back)]),\n face(\"left\", [on(a, back), under(a, back), under(a, front), on(a, front)]),\n face(\"right\", [on(o, front), under(o, front), under(o, back), on(o, back)]),\n face(\"bottom\", [under(a, front), under(a, back), under(o, back), under(o, front)]),\n ...line\n .slice(1)\n .map((p, i) =>\n face(\"top\", [on(line[i], front), on(p, front), on(p, back), on(line[i], back)], i)\n ),\n ])\n}\n\n/**\n * The faces of a ribbon that face the camera, in paint order. Every segment\n * of the top is a slab, and the planes x = const separate them: the top is\n * painted from the end of the ribbon away from the camera, which `toward`,\n * the sign of x in the view direction, names. The faces of the bounding box\n * come last: the ribbon lies wholly behind each of them.\n */\nfunction painted(faces: RibbonFace[], toward: number) {\n const shown = faces.filter((f) => f.ccw)\n return [\n ...shown.filter((f) => f.face === \"top\").sort((a, b) => toward * (a.segment - b.segment)),\n ...shown.filter((f) => f.face !== \"top\"),\n ]\n}\n\n/**\n * The marks of one ribbon, shaded in the color of its series. Each face is a\n * group of its own, so hovering highlights the face under the pointer alone.\n * A segment of the top is keyed by the entry it starts at, so it keeps its\n * mark when entries come or go before it. Every face names the series; a\n * segment of the top tells the values at its two ends.\n */\nfunction ribbonMarks(\n key: string,\n faces: RibbonFace[],\n line: LinePoint[],\n label: React.ReactNode,\n name: (label: string) => React.ReactNode\n): Mark3D[] {\n const color = `var(--color-${key})`\n const spans = (f: RibbonFace) => (f.face === \"top\" ? [line[f.segment], line[f.segment + 1]] : [])\n return faces.map((f) => {\n const id = f.face === \"top\" ? `${key}-top-${line[f.segment].name}` : `${key}-${f.face}`\n return {\n key: id,\n points: f.map((p) => p.projected),\n fill: shade(f, color),\n groups: [id],\n tooltip: {\n title: label,\n items: spans(f).map((p) => ({ label: name(p.name), value: p.value, color })),\n },\n }\n })\n}\n\n/**\n * The axes of an area chart: the entries along x, with half a row of room\n * between the first and the last and the walls, a row per series along z.\n * A line has many entries, so x ticks about ten of them, not every one.\n */\nfunction areaAxes(entries: number, series: number, values: number[]): AxesSpec {\n const every = entries ? ticks(0, entries - 1, 10).filter(Number.isInteger) : []\n return {\n x: pad({ domain: [0, Math.max(0, entries - 1)], ticks: every }, 1),\n y: axis(Math.min(0, ...values), Math.max(0, ...values)),\n z: pad({ domain: [0, Math.max(0, series - 1)], ticks: range(series) }, 1),\n }\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { box, cubes3D, sort, type AxesSpec, type Camera3DInstance, type CubeFace } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n cubeMarks,\n faded,\n pad,\n useSeries,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\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\"; a bar follows its name through updates, so the names should be unique. */\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 // A value that is not a number stands as no bar, one of height 0; a new one\n // grows from the floor, and a gone one shrinks back into it. The rows glide\n // to their new cells when the data reorders; a gone row stands in its cell\n // while its bars shrink and fade away, so a flat bar never pops.\n const { series, target, values, rows, presence, labels } = useSeries({\n data,\n index,\n keys,\n format,\n })\n const cells = barCells(rows, series, values)\n\n const box = barBox(data.length, series.length, Object.values(target))\n // Every axis glides with the bars: the value ends with the heights, the row\n // and series ends - and the depth of the box - as rows come and go. The\n // size of a bar comes from the gliding ends, so it eases with its cell.\n const spec = useTweenAxes(box.spec)\n const depth = useTween({ depth: box.depth }).depth\n const world = worldBox(spec, depth)\n const bars = barShapes(camera, cells, world, cellSize(spec, depth, barSize))\n\n return (\n <>\n <Axes3D spec={spec} world={world} titles={titles} format={labels} />\n <Marks3D\n marks={bars.flatMap((bar) =>\n barMarks({\n id: `${bar.name}-${bar.key}`,\n faces: bar.faces,\n color: `var(--color-${bar.key})`,\n title: bar.name,\n label: config[bar.key]?.label ?? bar.key,\n value: bar.value,\n opacity: presence[bar.name],\n })\n )}\n />\n </>\n )\n}\n\n/** The cubes of the cells, projected by `camera` and painted back to front by their footprint, as the bars stand on one floor. */\nfunction barShapes(\n camera: Camera3DInstance,\n cells: ReturnType<typeof barCells>,\n world: World,\n size: { width: number; depth: number }\n) {\n return cubes3D()\n .camera(camera)\n .data(\n cells.map(({ name, x, j, key, value }) =>\n Object.assign(barCorners(world, x, j, value, size), { name, key, value })\n )\n )\n .map((bar) => Object.assign(bar, { bottom: bar.faces.find((f) => f.face === \"bottom\")! }))\n .sort((a, b) => sort(a.bottom, b.bottom))\n}\n\n/**\n * The cell of every bar, the rows still gliding away among them: the row\n * position along x, the series `key` along z, with the tweened value. A cell\n * only one of the tweens still knows is on its way out and stays unseen.\n */\nfunction barCells(rows: Record<string, number>, series: string[], values: Record<string, number>) {\n return Object.entries(rows).flatMap(([name, x]) =>\n series.flatMap((key, j) => {\n const value = values[`${name}-${key}`]\n return value === undefined ? [] : [{ name, x, j, key, value }]\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 * with half a cell of room between the outer rows and the walls.\n */\nfunction barBox(entries: number, series: number, values: number[]) {\n const index = (length: number) => Array.from({ length }, (_, i) => i)\n const spec: AxesSpec = {\n x: pad({ domain: [-0.5, entries - 0.5], ticks: index(entries) }, 1),\n y: axis(Math.min(0, ...values), Math.max(0, ...values)),\n z: pad({ domain: [-0.5, series - 0.5], ticks: index(series) }, 1),\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 return { spec, depth }\n}\n\n/**\n * The size of a bar, the share `barSize` of its cell - of the gliding ends of\n * `spec`, so a bar eases into a new cell size as rows come and go.\n */\nfunction cellSize(spec: AxesSpec, depth: number, barSize: number) {\n return {\n width: (2 / (spec.x.domain[1] - spec.x.domain[0])) * barSize,\n depth: ((2 * depth) / (spec.z.domain[1] - spec.z.domain[0])) * barSize,\n }\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 and faded to `opacity`, each with its entry and value on hover. Its group is the bar alone, so hovering highlights one bar, not its series. */\nfunction barMarks({\n id,\n faces,\n color,\n title,\n label,\n value,\n opacity,\n}: {\n id: string\n faces: CubeFace[]\n color: string\n title: string\n label: React.ReactNode\n value: number\n opacity: number\n}) {\n const tooltip = {\n title,\n items: [{ label, value, color }],\n }\n return cubeMarks(id, faces, color, tooltip).map((mark) => ({\n ...mark,\n fill: faded(mark.fill, opacity),\n groups: [id],\n }))\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport { points3D, sort, type AxesSpec, type Point3D } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n faded,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n type ChartConfig,\n type World,\n} 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 that names an entry, so a point follows its name through\n * updates: a new one grows, a gone one shrinks away, one that moves glides.\n * The names should be unique.\n * @defaultValue the position of the entry\n */\n id?: 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 id,\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 names = data.map((d, i) => (id ? String(d[id]) : String(i)))\n const { radii, opacity, read, key } = usePointTweens(names, data, fields, series, config, radius)\n\n // The axes of the data the chart glides into; their ends glide along.\n const spec = useTweenAxes(pointAxes(data, fields))\n const world = worldBox(spec)\n const placed = usePointPlaces(names, radii, read, world)\n\n const points = points3D<{ name: string } & Point3D>()\n .camera(camera)\n .x((p) => p.x)\n .y((p) => p.y)\n .z((p) => p.z)\n\n const marks = points\n .data(placed)\n .sort(sort)\n .map((p) => ({\n key: p.name,\n points: [p.projected],\n r: radii[p.name],\n fill: faded(`var(--color-${key(p.name)})`, opacity[p.name]),\n // Its group is the point alone, so hovering highlights that point only.\n groups: [p.name],\n // Ringed by the background, so that points in front stand out.\n stroke: faded(\"var(--background)\", opacity[p.name]),\n tooltip: {\n title: series ? (config[key(p.name)]?.label ?? key(p.name)) : undefined,\n items: ([\"x\", \"y\", \"z\"] as const).map((a) => ({\n label: titles?.[a] ?? fields[a],\n value: read(p.name, a),\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\n/** The axes that hold every entry of `data`, a nice one per field. */\nfunction pointAxes<T extends Record<string, unknown>>(\n data: T[],\n fields: Record<keyof AxesSpec, keyof T & string>\n): AxesSpec {\n const range = (a: keyof AxesSpec) => {\n const [lo = 0, hi = 0] = extent(data, (d) => Number(d[fields[a]]))\n return axis(lo, hi)\n }\n return { x: range(\"x\"), y: range(\"y\"), z: range(\"z\") }\n}\n\n/**\n * The tweened numbers of the chart, by the name of each entry: the positions\n * glide entry by entry - a gone point stands in place - and the radius and\n * the opacity enter from 0, so a new point grows as it fades in and a gone\n * one shrinks as it fades away. `read` and `key` look them up, also for a\n * point still leaving.\n */\nfunction usePointTweens<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n fields: Record<keyof AxesSpec, keyof T & string>,\n series: (keyof T & string) | undefined,\n config: ChartConfig,\n radius: number\n) {\n const values = useTween(pointValues(names, data, fields))\n const radii = useTween(Object.fromEntries(names.map((name) => [name, radius])), 0)\n const opacity = useTween(Object.fromEntries(names.map((name) => [name, 1])), 0)\n const fallback = Object.keys(config)[0]\n return {\n radii,\n opacity,\n read: (name: string, axis: keyof AxesSpec) => values[`${axis}${name}`],\n key: usePointKeys(names, data, series, fallback, radii),\n }\n}\n\n/**\n * The place of every point in the world box, by name. A living point follows\n * its gliding numbers through the gliding axes; a gone one stays frozen where\n * it was, so it shrinks away in place instead of riding the rescaling axes\n * out of the box. A point only one of the tweens still knows stays unseen.\n */\nfunction usePointPlaces(\n names: string[],\n alive: Record<string, number>,\n read: (name: string, axis: keyof AxesSpec) => number,\n world: World\n) {\n const places = React.useRef(new Map<string, Point3D>())\n const live = new Set(names)\n const placed = Object.keys(alive).flatMap((name) => {\n if (!live.has(name)) {\n const held = places.current.get(name)\n return held ? [{ name, ...held }] : []\n }\n const p = {\n x: world.x(read(name, \"x\")),\n y: world.y(read(name, \"y\")),\n z: world.z(read(name, \"z\")),\n }\n places.current.set(name, p)\n return [{ name, ...p }]\n })\n // Forgotten with the point, so the memory stays the size of the chart.\n for (const name of places.current.keys()) if (!(name in alive)) places.current.delete(name)\n return placed\n}\n\n/** The position of every entry, keyed by its axis and name, gliding into new data. */\nfunction pointValues<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n fields: Record<keyof AxesSpec, keyof T & string>\n) {\n return Object.fromEntries(\n data.flatMap((d, i) =>\n ([\"x\", \"y\", \"z\"] as const).map((a) => [`${a}${names[i]}`, Number(d[fields[a]])])\n )\n )\n}\n\n/**\n * The config key of every point's color, by name - remembered while a gone\n * point shrinks away, since its entry has already left the data - and\n * forgotten with the point, so the memory stays the size of the chart.\n */\nfunction usePointKeys<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n series: (keyof T & string) | undefined,\n fallback: string,\n alive: Record<string, number>\n) {\n const known = React.useRef(new Map<string, string>())\n data.forEach((d, i) => known.current.set(names[i], series ? String(d[series]) : fallback))\n for (const name of known.current.keys()) {\n if (!(name in alive) && !names.includes(name)) known.current.delete(name)\n }\n return (name: string) => known.current.get(name) ?? fallback\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport {\n gridPlanes3D,\n sort,\n type AxesSpec,\n type GridPlane,\n type GridPlanes3DInstance,\n type Point3D,\n} from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n intoWorld,\n linear,\n pad,\n shade,\n useChart3D,\n useTween,\n useTweenAxes,\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 * The chart keeps half a cell between the grid and the walls of its box; a\n * domain given here names the box exactly, without that room.\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 [floor = 0, peak = 0] = extent(data.flat())\n const target = gridValues(data)\n // The heights glide cell by cell, so the surface, its color ramp and the y\n // axis follow. Coming and going is a fade in place - a new border cell\n // fades in where it belongs, a gone one fades out where it stands and\n // leaves when the glide is done - so the surface never moves where data\n // merely appears or disappears.\n const heights = gridHeights(useTween(target), floor)\n const fade = useTween(Object.fromEntries(Object.keys(target).map((k) => [k, 1])), 0)\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 // A cell of the grid, along x and along z, in the values the data stands for.\n const cell = {\n x: (x1 - x0) / Math.max(1, columns - 1),\n z: (z1 - z0) / Math.max(1, rows - 1),\n }\n // The color ramp follows the heights on screen, the axes glide to those of the data.\n const [lo = 0, hi = 0] = extent(heights.flat())\n\n // The box keeps half a cell beyond the grid; a domain the reader hands the\n // chart names the box exactly.\n const spec = useTweenAxes({\n x: domain.x ? axis(x0, x1) : pad(axis(x0, x1), cell.x),\n y: axis(floor, peak),\n z: domain.z ? axis(z0, z1) : pad(axis(z0, z1), cell.z),\n })\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 = intoWorld<GridPoint, GridPlanes3DInstance<GridPoint>>(\n gridPlanes3D<GridPoint>().camera(camera),\n world\n )\n // d3-3d reads rows(0) as the getter; a grid without columns has no points anyway.\n .rows(Math.max(1, heights[0]?.length ?? 0))\n const points = heights.flatMap((row, r) => row.map((y, c) => ({ x: toX(c), y, z: toZ(r), r, c })))\n\n const marks = grid\n .data(points)\n .sort(sort)\n .map((quad) => quadMark(quad, fade, { lo, hi, low, high }, titles?.y))\n\n return (\n <>\n <Axes3D spec={spec} world={world} format={format} titles={titles} />\n <Marks3D marks={marks} />\n </>\n )\n}\n\n/** A point of the lattice, carrying the row and column it stands for. */\ntype GridPoint = Point3D & { r: number; c: number }\n\n/**\n * The mark of one cell: its quad, shaded by the color ramp at its height and\n * faded in place by `fade` while the cell enters or leaves.\n */\nfunction quadMark(\n quad: GridPlane<GridPoint>,\n fade: Record<string, number>,\n ramp: { lo: number; hi: number; low: string; high: string },\n title: React.ReactNode\n) {\n const height = quad.reduce((sum, p) => sum + p.y, 0) / quad.length\n const t = Math.round(((height - ramp.lo) / (ramp.hi - ramp.lo || 1)) * 100)\n const shaded = shade(\n quad,\n `color-mix(in oklch, var(--color-${ramp.high}) ${t}%, var(--color-${ramp.low}))`\n )\n // A corner only one of the tweens still knows is on its way out and stays unseen.\n const seen = Math.min(...quad.map((p) => fade[`${p.r}-${p.c}`] ?? 0))\n return {\n key: quad.plane,\n points: quad.map((p) => p.projected),\n fill:\n seen < 1 ? `color-mix(in srgb, ${shaded} ${Math.round(seen * 100)}%, transparent)` : shaded,\n // Its group is the cell, so hovering it lights the cell alone.\n groups: [quad.plane],\n tooltip: { items: [{ label: title ?? \"value\", value: height }] },\n }\n}\n\n/** The height of every cell, keyed by its row and column, gliding into new data. */\nfunction gridValues(data: number[][]) {\n return Object.fromEntries(data.flatMap((row, r) => row.map((y, c) => [`${r}-${c}`, y])))\n}\n\n/**\n * The gliding heights as a lattice. It spans the cells still leaving too, so\n * a shrunken grid sinks away instead of popping; a corner only one dimension\n * kept stands at the floor until it goes.\n */\nfunction gridHeights(tweened: Record<string, number>, floor: number) {\n let rows = 0\n let columns = 0\n for (const key of Object.keys(tweened)) {\n const [r, c] = key.split(\"-\").map(Number)\n rows = Math.max(rows, r + 1)\n columns = Math.max(columns, c + 1)\n }\n return Array.from({ length: rows }, (_, r) =>\n Array.from({ length: columns }, (_, c) => tweened[`${r}-${c}`] ?? floor)\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../lib/utils.ts","../registry/new-york/ui/chart-3d.tsx","../registry/new-york/ui/area-chart-3d.tsx","../registry/new-york/ui/bar-chart-3d.tsx","../registry/new-york/ui/bar-field-chart-3d.tsx","../registry/new-york/ui/choropleth-chart-3d.tsx","../registry/new-york/ui/globe-chart-3d.tsx","../registry/new-york/ui/places-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 box,\n camera3D,\n normal,\n points3D,\n sort,\n type AxesSpec,\n type AxisEdge,\n type AxisSpec,\n type AxisWall,\n type Camera3DInstance,\n type CubeFace,\n type Point2D,\n type Point3D,\n type ShapeInstance,\n type TransformedPoint,\n} from \"d3-3d\"\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/**\n * How the marks of a chart are drawn. The box, its labels, the tooltip and the\n * legend are always SVG and HTML. \"webgl\" draws as \"canvas\", as it drew no\n * faster, and goes in 1.0.0.\n */\nexport type Renderer3D = \"svg\" | \"canvas\" | \"webgl\"\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\n/** What a mark says while the pointer is on it, beside the pointer. */\nexport type Tooltip3D = {\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 /**\n * Shown while the pointer is over the mark. A function is called when the\n * pointer lands on the mark, so a chart with thousands of marks pays for\n * one tooltip per hover, not one per mark per frame; `null` shows none.\n */\n tooltip?: Tooltip3D | (() => Tooltip3D | null)\n /**\n * The marks of the same element as this one: the faces of a bar, the\n * segments of a flow. Pointing at a mark fills them with the focus color -\n * `--chart-3d-focus`, or their own fill lightened - until the pointer\n * leaves the mark; a stroke of their own stays.\n */\n groups?: string[]\n}\n\n/** The groups in focus, a store, so a change reaches the marks and labels without rendering the chart again. */\ntype Focus3D = {\n get: () => string[] | undefined\n set: (groups?: string[]) => void\n subscribe: (listener: () => void) => () => void\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 /** Puts the marks of the `Marks3D` of `id`, drawn at `node` in the tree, into the scene, or takes them out. */\n place: (id: string, set?: { marks: Mark3D[]; node: Element }) => void\n repaint: () => void\n focus: Focus3D\n /** The time in ms a chart takes to glide into new data, 600 unless the container says. */\n animationDuration?: number\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// How long the zoom cursor outlives the last wheel tick before the hand returns.\nconst ZOOM_CURSOR = 400\n\n/**\n * A step of the camera: turned by `yaw` and `tilt`, moved by `pan`, zoomed by\n * the factor `zoom` to the point `at`, from the middle of the view, or reset.\n */\ntype Move = {\n yaw?: number\n tilt?: number\n pan?: Point2D\n zoom?: number\n at?: Point2D\n reset?: boolean\n}\n\n/** The actions a key triggers: each steps the camera, `help` opens the shortcut panel. */\nexport type KeyAction3D =\n | \"rotateLeft\"\n | \"rotateRight\"\n | \"rotateUp\"\n | \"rotateDown\"\n | \"panLeft\"\n | \"panRight\"\n | \"panUp\"\n | \"panDown\"\n | \"zoomIn\"\n | \"zoomOut\"\n | \"reset\"\n | \"help\"\n\n/** The gestures of the pointer, which `keymap` can turn off or rename but not rebind; the shortcut panel shows each with its modifier on the reader's platform. */\nexport type Gesture3D =\n | \"dragRotate\"\n | \"touchOrbit\"\n | \"dragPan\"\n | \"wheelZoom\"\n | \"pinchZoom\"\n | \"doubleClickReset\"\n\n/**\n * The shortcuts of a chart over their defaults, per action: `false` turns an\n * action off, keys replace its keys and a label renames it in the shortcut\n * panel, where the actions of one label share a row. Keys are written the way\n * `aria-keyshortcuts` writes them, such as `\"Shift+ArrowLeft\"` or\n * `\"Control+Plus\"`, and the panel shows the first.\n */\nexport type Keymap3D = {\n [A in KeyAction3D]?: false | string[] | { keys?: string[]; label?: string }\n} & { [G in Gesture3D]?: false | { label?: string } }\n\ntype Action3D = KeyAction3D | Gesture3D\n\n// The shortcuts of a chart, in the order of the shortcut panel: the keys of\n// an action move the camera, a gesture shows how it is made, and the panel lists\n// every action that is on, so the two never disagree. `keymap` overrides them.\nconst SHORTCUTS: Record<\n Action3D,\n { label: string; keys?: string[]; gesture?: string[]; move?: Move }\n> = {\n dragRotate: { label: \"Rotate\", gesture: [\"Mod\", \"Drag\"] },\n touchOrbit: { label: \"Rotate\", gesture: [\"Two-finger drag\"] },\n rotateLeft: { label: \"Rotate\", keys: [\"ArrowLeft\"], move: { yaw: -KEY_STEP } },\n rotateRight: { label: \"Rotate\", keys: [\"ArrowRight\"], move: { yaw: KEY_STEP } },\n rotateUp: { label: \"Rotate\", keys: [\"ArrowUp\"], move: { tilt: -KEY_STEP } },\n rotateDown: { label: \"Rotate\", keys: [\"ArrowDown\"], move: { tilt: KEY_STEP } },\n dragPan: { label: \"Pan\", gesture: [\"Alt\", \"Drag\"] },\n panLeft: { label: \"Pan\", keys: [\"Shift+ArrowLeft\"], move: { pan: { x: -PAN_STEP, y: 0 } } },\n panRight: { label: \"Pan\", keys: [\"Shift+ArrowRight\"], move: { pan: { x: PAN_STEP, y: 0 } } },\n panUp: { label: \"Pan\", keys: [\"Shift+ArrowUp\"], move: { pan: { x: 0, y: -PAN_STEP } } },\n panDown: { label: \"Pan\", keys: [\"Shift+ArrowDown\"], move: { pan: { x: 0, y: PAN_STEP } } },\n zoomIn: { label: \"Zoom\", keys: [\"Plus\", \"=\"], move: { zoom: ZOOM_STEP } },\n zoomOut: { label: \"Zoom\", keys: [\"-\"], move: { zoom: 1 / ZOOM_STEP } },\n wheelZoom: { label: \"Zoom\", gesture: [\"Mod\", \"Scroll\"] },\n pinchZoom: { label: \"Zoom\", gesture: [\"Pinch\"] },\n reset: { label: \"Reset\", keys: [\"0\"], move: { reset: true } },\n doubleClickReset: { label: \"Reset\", gesture: [\"Double-click\"] },\n help: { label: \"Keyboard shortcuts\", keys: [\"?\"] },\n}\n\nconst MODIFIERS = [\"Control\", \"Alt\", \"Meta\", \"Shift\"]\n\n/** Whether the reader is on a Mac, where the platform modifier is ⌘; elsewhere it is Ctrl. */\nconst mac = () =>\n /mac/i.test(\n (globalThis.navigator as Navigator & { userAgentData?: { platform?: string } })?.userAgentData\n ?.platform ??\n globalThis.navigator?.platform ??\n \"\"\n )\n\n/** The label of the platform modifier: ⌘ on a Mac, Ctrl elsewhere. */\nconst modLabel = () => (mac() ? \"⌘\" : \"Ctrl\")\n\n/** The label of the Alt key: ⌥ on a Mac, Alt elsewhere. */\nconst altLabel = () => (mac() ? \"⌥\" : \"Alt\")\n\n/** The platform never changes, so its store has nothing to tell. */\nconst never = () => () => {}\n\n/** Whether the platform modifier - ⌘ on a Mac, Ctrl elsewhere - is held in `e`. */\nconst platformMod = (e: { metaKey: boolean; ctrlKey: boolean }) => (mac() ? e.metaKey : e.ctrlKey)\n\n/** Whether `value` lies between the ends `lo` and `hi`. */\nconst within = (lo: number, hi: number, value: number) => value >= lo && value <= hi\n// The keys that `aria-keyshortcuts` names, because `+` delimits and a space separates.\nconst NAMED: Record<string, string> = { Plus: \"+\", Space: \" \" }\nconst ARIA: Record<string, string> = { \"+\": \"Plus\", \" \": \"Space\" }\nconst KBD: Record<string, string> = {\n ArrowLeft: \"←\",\n ArrowRight: \"→\",\n ArrowUp: \"↑\",\n ArrowDown: \"↓\",\n \"-\": \"−\",\n \" \": \"Space\",\n Control: \"Ctrl\",\n Meta: \"⌘\",\n}\n\n/** Keys split at `+`, which is the key itself at the end: `\"Control++\"` is Control and `+`. */\nconst split = (keys: string) => keys.split(/\\+(?!$)/)\n\n/**\n * Keys in the one form a binding and a press compare in: the modifiers in a\n * fixed order, then the key, Plus as `+` and Space as \" \". Shift counts only\n * beside a named key; a character such as \"?\" or \"A\" is typed with it already.\n */\nfunction combo(keys: string) {\n const parts = split(keys)\n const key = NAMED[parts.at(-1)!] ?? parts.at(-1)!\n const mods = MODIFIERS.filter((m) => parts.includes(m) && (m !== \"Shift\" || key.length > 1))\n return [...mods, key].join(\"+\")\n}\n\n/** The keys of a press, in the form of `combo`. */\nfunction pressed(e: Pick<KeyboardEvent, \"key\" | \"ctrlKey\" | \"altKey\" | \"metaKey\" | \"shiftKey\">) {\n const mods = [\n e.ctrlKey && \"Control\",\n e.altKey && \"Alt\",\n e.metaKey && \"Meta\",\n e.shiftKey && \"Shift\",\n ]\n return combo([...mods, e.key].filter(Boolean).join(\"+\"))\n}\n\n/** Keys in the form of `combo`, the way `aria-keyshortcuts` writes them. */\nfunction aria(keys: string) {\n const parts = split(keys)\n return [...parts.slice(0, -1), ARIA[parts.at(-1)!] ?? parts.at(-1)].join(\"+\")\n}\n\n/** Every action, `keymap` over its defaults: on unless it is off or a key action without keys. */\nfunction shortcutsOf(keymap: Keymap3D | false) {\n return (Object.keys(SHORTCUTS) as Action3D[]).map((action) => {\n const own: Keymap3D[KeyAction3D] = keymap && keymap[action]\n const { keys = [], ...shortcut } = {\n ...SHORTCUTS[action],\n ...(Array.isArray(own) ? { keys: own } : own || {}),\n }\n const on = own !== false && (shortcut.gesture !== undefined || keys.length > 0)\n return { ...shortcut, action, on, keys: keys.map(combo) }\n })\n}\n\ntype Shortcut = ReturnType<typeof shortcutsOf>[number]\n\n/** The keys or the gesture of a shortcut as the panel writes them, with the modifiers of the reader's platform. */\nconst partsOf = ({ keys, gesture }: Pick<Shortcut, \"keys\" | \"gesture\">) =>\n (gesture ?? split(keys[0])).map((k) =>\n k === \"Mod\" ? modLabel() : k === \"Alt\" ? altLabel() : (KBD[k] ?? k)\n )\n\n/**\n * The rows of the shortcut panel: the actions by label, the keys of a row in\n * groups of the same modifiers, left of its gestures, each a group of its own.\n */\nfunction rowsOf(shortcuts: Shortcut[]) {\n const rows = new Map<string, { keys: Map<string, string[]>; gestures: string[][] }>()\n for (const { label, keys, gesture } of shortcuts) {\n const parts = partsOf({ keys, gesture })\n const row = rows.get(label) ?? { keys: new Map<string, string[]>(), gestures: [] }\n if (gesture) row.gestures.push(parts)\n else {\n const group = parts.slice(0, -1).join(\"+\")\n const known = row.keys.get(group)\n row.keys.set(group, known ? [...known, parts.at(-1)!] : parts)\n }\n rows.set(label, row)\n }\n return [...rows].map(([label, row]) => ({\n label,\n keys: [...row.keys.values()],\n gestures: row.gestures,\n }))\n}\n\n/**\n * What a keymap does: the actions that are on, the step of each key, the help\n * keys, the rows of the panel and the hint of a gesture. Without the `panel`,\n * the help keys have nothing to open and are off.\n */\nfunction keymapOf(keymap: Keymap3D | false, panel: boolean) {\n const all = shortcutsOf(keymap)\n const on = all.filter((s) => s.on && (panel || s.action !== \"help\"))\n return {\n on: (action: Action3D) => on.some((s) => s.action === action),\n moves: Object.fromEntries(on.flatMap((s) => s.keys.map((k) => [k, s.move]))) as Record<\n string,\n Move | undefined\n >,\n help: on.find((s) => s.action === \"help\")?.keys ?? [],\n label: all.find((s) => s.action === \"help\")!.label,\n aria: on.flatMap((s) => s.keys.map(aria)).join(\" \"),\n rows: panel ? rowsOf(on) : [],\n hint: (action: Gesture3D) => {\n const shortcut = on.find((s) => s.action === action)\n return shortcut && { label: shortcut.label, gesture: partsOf(shortcut) }\n },\n }\n}\n\ntype Keymap = ReturnType<typeof keymapOf>\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 * The time in ms a chart takes to glide into new data; 0 makes it jump.\n * @defaultValue 600\n */\n animationDuration?: number\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 chart\n * draws as SVG until the browser shows it has a canvas, and where it has\n * none, as SVG. \"webgl\" draws as \"canvas\", as it drew no faster; it is\n * deprecated and goes in 1.0.0.\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 * Rebinds, renames or turns off the keys and the gestures of the chart, per\n * action; `false` turns them all off and the chart stands still.\n * @defaultValue {}\n */\n keymap?: Keymap3D | false\n /**\n * The corner that shows the axes of the chart, turned with the camera; `false` hides them.\n * @defaultValue \"bottom-left\"\n */\n gizmo?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\" | false\n /**\n * The corner beside the pointer the tooltip sits at. Where the tooltip would\n * leave the chart, it flips to the other side, on each axis alone.\n * @defaultValue \"top-right\"\n */\n tooltip?: \"top-left\" | \"top-right\" | \"bottom-left\" | \"bottom-right\"\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 animationDuration,\n legend = false,\n renderer: requested = \"svg\",\n shortcuts = true,\n keymap = {},\n gizmo = \"bottom-left\",\n tooltip = \"top-right\",\n className,\n children,\n \"aria-label\": ariaLabel,\n ...props\n}: React.ComponentProps<\"div\"> & ChartContainer3DProps) {\n const chartId = chartIdOf(id, React.useId())\n const drawing = useScene(requested, width, height, tooltip)\n const { scene, place, renderer, canvas, repaint, hover, hide, leave, tip, focus } = drawing\n const keys = keymapOf(keymap, shortcuts)\n const { view, handlers, hint } = useOrbit(defaultView, width, keys, hide, hover)\n const camera = useCamera(view, width, height)\n const context = React.useMemo(\n () => ({ config, camera, renderer, scene, place, repaint, focus, animationDuration }),\n [config, camera, renderer, place, repaint, focus, animationDuration]\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 <div className=\"relative rounded-lg has-focus-visible:ring-[3px] has-focus-visible:ring-ring/50\">\n <ChartSvg3D\n viewBox={`0 0 ${width} ${height}`}\n keys={keys}\n label={ariaLabel}\n onPointerLeave={leave}\n {...handlers}\n >\n <Chart3DContext.Provider value={context}>{children}</Chart3DContext.Provider>\n </ChartSvg3D>\n <ChartCanvas3D renderer={renderer} canvas={canvas} width={width} height={height} />\n <ChartGizmo3D camera={camera} corner={gizmo} />\n <ChartTooltip3D tip={tip} />\n <ChartHint3D {...hint} />\n </div>\n <ChartShortcuts3D {...keys} />\n {legend && <ChartLegend3D config={config} />}\n </div>\n )\n}\n\n/** The id the colors of a chart are scoped to: its own `id`, or the one React made up. */\nfunction chartIdOf(id: string | undefined, uniqueId: string) {\n return `chart-${id || uniqueId.replace(/:/g, \"\")}`\n}\n\n/**\n * The svg of the chart, saying what `keys` do. The server knows no platform\n * and says Ctrl; the store renders once more after hydration, with the\n * modifier of the reader. The panel reads the platform directly: it opens on\n * the client only.\n */\nfunction ChartSvg3D({\n keys,\n label,\n viewBox,\n ...props\n}: React.ComponentProps<\"svg\"> & { keys: Keymap; label?: string }) {\n const mod = React.useSyncExternalStore(never, modLabel, () => \"Ctrl\")\n return <svg viewBox={viewBox} role=\"img\" {...keymapProps(keys, mod, label)} {...props} />\n}\n\n/**\n * What the svg says about its keymap: a label that names the `mod` drag and the\n * help key if they are on, the keys, the focus only if a key does something\n * and, if a drag or two fingers do, `touch-pan-y`: a vertical swipe scrolls\n * the page and every other touch reaches the chart.\n */\nfunction keymapProps(keys: Keymap, mod: string, label?: string): React.SVGProps<SVGSVGElement> {\n const drag = ([\"dragRotate\", \"dragPan\", \"touchOrbit\", \"pinchZoom\"] as const).some(keys.on)\n const help = keys.help[0]\n const said = [\n \"3D chart.\",\n keys.on(\"dragRotate\") && `${mod} and drag to rotate it.`,\n help && `Press ${aria(help)} for all shortcuts.`,\n ]\n return {\n \"aria-label\": label ?? said.filter(Boolean).join(\" \"),\n \"aria-keyshortcuts\": keys.aria || undefined,\n tabIndex: keys.aria ? 0 : undefined,\n className: cn(\n \"block h-auto w-full outline-hidden select-none mask-x-from-96% mask-y-from-96%\",\n // The default cursor stays, so a plain drag only inspects; the modifier and a drag rotate.\n // A touch has no modifier, so its vertical swipe scrolls the page (ADR-0001).\n drag && \"touch-pan-y\"\n ),\n }\n}\n\n// The bit of `a.compareDocumentPosition(b)` that says `b` comes before `a` in the document.\nconst PRECEDING = 2\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. The\n * scene holds the marks of every `Marks3D` in the container, each set placed\n * by `place`, in the order of the sets in the document - the order SVG paints\n * them in - so a set that mounts later but sits earlier lies under the others\n * on every renderer.\n */\nfunction useScene(requested: Renderer3D, width: number, height: number, placement: Placement3D) {\n const scene = React.useRef<Mark3D[]>([])\n const sets = React.useRef(new Map<string, { marks: Mark3D[]; node: Element }>())\n const place = React.useCallback((id: string, set?: { marks: Mark3D[]; node: Element }) => {\n if (set) sets.current.set(id, set)\n else sets.current.delete(id)\n scene.current = [...sets.current.values()]\n .sort((a, b) => (a.node.compareDocumentPosition(b.node) & PRECEDING ? 1 : -1))\n .flatMap((s) => s.marks)\n }, [])\n const tip = useTip(placement)\n const focus = useFocus()\n const renderer = useRenderer(requested)\n const { canvas, repaint } = useCanvas(scene, width)\n const { hover, hide, leave } = useHover(scene, width, height, tip, focus)\n return { scene, place, renderer, canvas, repaint, hover, hide, leave, tip, focus }\n}\n\ntype Tip3D = ReturnType<typeof useTip>\ntype Placement3D = NonNullable<ChartContainer3DProps[\"tooltip\"]>\n\n// The room between the pointer and its tooltip, in pixels, and the shift of\n// the tooltip on an axis: before the pointer by its own size and the room, or after it.\nconst TIP_GAP = 12\nconst shift = (isBefore: boolean) => (isBefore ? `calc(-100% - ${TIP_GAP}px)` : `${TIP_GAP}px`)\n\n/**\n * Whether a tooltip of `size` goes before the pointer at `at`, on an axis of\n * `length`: as `preferred`, unless it would leave the chart there and the\n * other side has more room.\n */\nfunction before(at: number, size: number, length: number, preferred: boolean) {\n const room = preferred ? at : length - at\n return room < size + TIP_GAP && length - room > room ? !preferred : preferred\n}\n\n/**\n * The tooltip of the hovered mark and where it sits: beside the pointer, in\n * the pixels of the chart, at `placement`. `follow` moves it with the pointer\n * straight in the DOM, so a move within a mark renders nothing; `place` puts\n * it there again once it shows, or its content changes its size.\n */\nfunction useTip(placement: Placement3D) {\n const [tooltip, set] = React.useState<Tooltip3D | null>(null)\n const ref = React.useRef<HTMLDivElement>(null)\n // The pointer in the chart, and the size of the chart.\n const pointer = React.useRef({ x: 0, y: 0, width: 0, height: 0 })\n const place = React.useCallback(() => {\n const el = ref.current\n if (!el) return\n // A tooltip that shows jumps into its corner; only one on screen glides when it flips.\n const shows = !el.dataset.placement\n if (shows) el.style.transition = \"none\"\n const { x, y, width, height } = pointer.current\n const top = before(y, el.offsetHeight, height, placement.startsWith(\"top\"))\n const left = before(x, el.offsetWidth, width, placement.endsWith(\"left\"))\n el.style.left = `${x}px`\n el.style.top = `${y}px`\n el.style.translate = `${shift(left)} ${shift(top)}`\n el.dataset.placement = `${top ? \"top\" : \"bottom\"}-${left ? \"left\" : \"right\"}`\n if (shows) {\n // Lays the corner out while the transition is off, then turns it on again.\n el.getBoundingClientRect()\n el.style.transition = \"\"\n }\n }, [placement])\n const follow = (at: typeof pointer.current) => {\n pointer.current = at\n place()\n }\n return { tooltip, set, ref, place, follow }\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\nconst clamp = (lo: number, hi: number, value: number) => Math.max(lo, Math.min(hi, value))\nconst ZERO = { x: 0, y: 0 }\n\n/**\n * `view` moved by one step. The tilt stops at the zenith and the nadir, the\n * zoom at 1/4 and 8, and a turn is divided by the zoom: zoomed in, a drag\n * moves the picture under the pointer as far as zoomed out, and a key turns\n * it as far on screen. A zoom keeps the point `at` where it is, by the zoom\n * after its limits, so the chart stands still at them; without `at` that\n * point is the origin of the chart, and the pan stays.\n */\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 from = view.zoom ?? 1\n const zoom = clamp(0.25, 8, from * step.zoom)\n const k = zoom / from\n const at = move.at ?? pan\n return {\n ...view,\n yaw: view.yaw + step.yaw / from,\n tilt: clamp(-Math.PI / 2, Math.PI / 2, view.tilt + step.tilt / from),\n zoom,\n pan: { x: at.x - (at.x - pan.x) * k + step.pan.x, y: at.y - (at.y - pan.y) * k + step.pan.y },\n }\n}\n\n/**\n * Whether the chart may move on its own: only where the browser says the\n * reader has not asked for reduced motion. Where it cannot say, as on the\n * server and in jsdom, the chart jumps.\n */\nfunction animates() {\n return Boolean(globalThis.matchMedia?.(\"(prefers-reduced-motion: no-preference)\").matches)\n}\n\n/** One glide of numbers: from `from` into `to`, come the share `t` of the way. */\ntype Tween = { key: string; from: Record<string, number>; to: Record<string, number>; t: number }\n\n/**\n * Eases a chart into new data: the numbers of `values` glide from the ones\n * on screen to these over the animationDuration of the container. A key\n * that is new starts at `enter`, or where it ends; a key that is gone glides\n * back to `enter`, the mirror of its entering - without one it stands where\n * it is - and leaves when the glide is done. Without time, or with reduced\n * motion, the numbers jump. At rest it hands back the record of its target,\n * no copy, so no frame rebuilds it: read it, never write to it.\n */\nfunction useTween(values: Record<string, number>, enter?: number): Record<string, number> {\n const { animationDuration: duration = 600 } = useChart3D()\n // The content, not the record, keys the glide: a chart may build `values`\n // anew at any render. The same record as before is the same content, so a\n // chart that keeps its records while the camera turns compares nothing.\n const last = React.useRef<{ values: Record<string, number>; key: string }>(null)\n if (last.current?.values !== values) {\n last.current = { values, key: JSON.stringify(values) }\n }\n const key = last.current.key\n const [tween, setTween] = React.useState<Tween>({ key, from: values, to: values, t: 1 })\n const shown = tweenNumbers(tween, enter)\n\n // Numbers from the render before, the React pattern of state set while rendering.\n if (key !== tween.key) {\n setTween({ key, from: shown, to: values, t: duration > 0 && animates() ? 0 : 1 })\n }\n\n React.useEffect(() => {\n if (tween.t >= 1) return\n let start: number | null = null\n let frame = 0\n const step = (now: number) => {\n start ??= now\n // A duration that turned 0 during the glide: 0 / 0 is NaN, so it jumps to the end.\n const t = duration > 0 ? Math.min(1, (now - start) / duration) : 1\n setTween((tw) => ({ ...tw, t }))\n if (t < 1) frame = requestAnimationFrame(step)\n }\n frame = requestAnimationFrame(step)\n return () => cancelAnimationFrame(frame)\n }, [tween.key, duration])\n\n return shown\n}\n\n/**\n * The numbers of `tween` on screen: `from` eased into `to`, a new key from\n * `enter` or where it ends, a gone one gliding back to `enter` until the\n * glide is done. At rest, as while the camera turns, they are the target\n * itself: nothing to build.\n */\nfunction tweenNumbers({ from, to, t }: Tween, enter?: number) {\n if (t >= 1) return to\n const s = t * t * (3 - 2 * t)\n const gone = Object.entries(from).filter(([k]) => !(k in to))\n return Object.fromEntries([\n ...Object.entries(to).map(([k, end]) => {\n const start = from[k] ?? enter ?? end\n return [k, start + (end - start) * s]\n }),\n // A gone key glides back to `enter`, the mirror of its entering - without\n // one it stands where it is - and leaves when the glide is done.\n ...gone.map(([k, start]) => [k, start + ((enter ?? start) - start) * s]),\n ])\n}\n\n/**\n * An axis gliding into new data: its spec, the ticks the data dropped, fading\n * out in place, and the gliding `span` of its ticks, which its line runs.\n */\ntype GlidingAxis = AxisSpec & { leaving?: number[]; span?: number[] }\n\n/**\n * `spec` gliding into new data with the marks: the ends of every axis glide\n * as `useTween` glides the numbers, where ends rounded from the numbers on\n * screen would jump from one round number to the next, and the box with\n * them. The ticks stay those of `spec`; labels of ticks outside the gliding\n * ends fade out in `edgeLabels` instead of popping out of the range. The\n * outermost ticks glide too, so the line of the axis grows to a new tick and\n * shrinks from a dropped one instead of jumping when the glide is done.\n */\nfunction useTweenAxes(spec: AxesSpec): AxesSpec {\n const axes = [\"x\", \"y\", \"z\"] as const\n const last = (domain: number[]) => domain[domain.length - 1]\n const target = Object.fromEntries(\n axes.flatMap((a) => {\n const { domain, ticks } = spec[a]\n return [\n [`${a}0`, domain[0]],\n [`${a}1`, last(domain)],\n [`${a}t0`, ticks.at(0) ?? domain[0]],\n [`${a}t1`, ticks.at(-1) ?? last(domain)],\n ]\n })\n )\n const ends = useTween(target)\n // At the end of a glide useTween hands back the targets themselves, so the\n // ends tell whether the axes still glide.\n const gliding = Object.keys(target).some((k) => ends[k] !== target[k])\n // The target the glide left, remembered the way useTween keys its numbers,\n // so a retarget in the middle of a glide fades the ticks of that target out.\n const key = JSON.stringify(spec)\n const memory = React.useRef({ key, target: spec, from: spec })\n if (memory.current.key !== key) {\n memory.current = { key, target: spec, from: memory.current.target }\n }\n const glided = (a: keyof AxesSpec): GlidingAxis => {\n const [lo, hi] = [ends[`${a}0`], ends[`${a}1`]]\n // The ticks stay those of the target, so a label whose tick lies outside the\n // gliding ends fades out instead of popping out of the range. Every tick the\n // new data drops stays until the glide is done: one beyond the new ends\n // fades out as the gliding end sweeps past it, one within them fades out in\n // place, named in `leaving`.\n const [d0, d1] = [spec[a].domain[0], last(spec[a].domain)]\n const gone = gliding\n ? memory.current.from[a].ticks.filter((t) => !spec[a].ticks.includes(t))\n : []\n const ticks = gone.length ? [...spec[a].ticks, ...gone].sort((t, u) => t - u) : spec[a].ticks\n const leaving = gone.filter((t) => within(Math.min(d0, d1), Math.max(d0, d1), t))\n const span = [ends[`${a}t0`], ends[`${a}t1`]]\n return { domain: [lo, hi], ticks, span, ...(leaving.length ? { leaving } : {}) }\n }\n return { x: glided(\"x\"), y: glided(\"y\"), z: glided(\"z\") }\n}\n\n// How long the camera glides to the view a key asks for, in milliseconds.\nconst GLIDE = 200\n\n/**\n * The view of the camera, `jump`, which moves it at once, and `glide`, which\n * moves it there in `GLIDE` milliseconds, easing out. A glide under way\n * heads for the next view from where it is, so a held key turns the camera\n * smoothly; a jump stops it. Where the reader asks for reduced motion, or\n * the browser cannot say, a glide jumps.\n */\nfunction useGlide(defaultView: View3D) {\n const [view, setView] = React.useState(defaultView)\n const now = React.useRef(defaultView)\n const run = React.useRef<{ to: View3D; frame: number } | null>(null)\n const show = React.useCallback((v: View3D) => setView((now.current = v)), [])\n const stop = React.useCallback(() => {\n cancelAnimationFrame(run.current?.frame ?? 0)\n run.current = null\n }, [])\n const jump = React.useCallback(\n (to: (from: View3D) => View3D) => {\n stop()\n show(to(now.current))\n },\n [show, stop]\n )\n React.useEffect(() => stop, [stop])\n\n const glide = (to: (from: View3D) => View3D) => {\n if (!animates()) return jump(to)\n const end = to(run.current?.to ?? now.current)\n // The yaw turns the short way round, to an angle that looks the same.\n const from = { ...now.current, yaw: end.yaw + remainder(now.current.yaw - end.yaw) }\n const start = performance.now()\n stop()\n const frame = (time: number) => {\n const t = clamp(0, 1, (time - start) / GLIDE)\n show(t < 1 ? between(from, end, 1 - (1 - t) ** 3) : end)\n if (t < 1) run.current = { to: end, frame: requestAnimationFrame(frame) }\n else run.current = null\n }\n run.current = { to: end, frame: requestAnimationFrame(frame) }\n }\n\n return { view, jump, glide }\n}\n\n/** The angle `a` in the turn from -π to π. */\nfunction remainder(a: number) {\n return a - 2 * Math.PI * Math.round(a / (2 * Math.PI))\n}\n\n/** The view the share `k` of the way from `from` to `to`. */\nfunction between(from: View3D, to: View3D, k: number): View3D {\n const mix = (a: number, b: number) => a + (b - a) * k\n const pan = from.pan ?? ZERO\n const goal = to.pan ?? ZERO\n return {\n ...to,\n yaw: mix(from.yaw, to.yaw),\n tilt: mix(from.tilt, to.tilt),\n zoom: mix(from.zoom ?? 1, to.zoom ?? 1),\n pan: { x: mix(pan.x, goal.x), y: mix(pan.y, goal.y) },\n }\n}\n\n/**\n * The view of the camera, and the handlers that move it, as far as `keys`\n * has them on: a drag turns it, or pans it while Alt is held, the keys step\n * it, Ctrl or ⌘ with the wheel zooms it and a double click resets it - a\n * drag following the pointer at once, a key and a double click gliding.\n * `data-orbiting` among them is true while the camera turns. `onDragStart`\n * runs when a press becomes a drag, `onHover` on a move without one - but\n * under two fingers, where the tooltip would jump from one to the other, it\n * goes, as in a drag.\n */\nfunction useOrbit(\n defaultView: View3D,\n width: number,\n keys: Keymap,\n onDragStart: () => void,\n onHover: (e: React.PointerEvent<SVGSVGElement>) => void\n) {\n const { view, jump, glide } = useGlide(defaultView)\n const [orbiting, setOrbiting] = React.useState(false)\n const held = useModsHeld()\n const drag = React.useRef<(Point2D & { moved: boolean; rotate: boolean }) | null>(null)\n const { ref, touching, hint } = useGestures(jump, keys, width, setOrbiting)\n const move = (step: Move) => jump((v) => moved(v, step, defaultView))\n const step = (step: Move) => glide((v) => moved(v, step, defaultView))\n const keyHandlers = useKeys(keys, step, setOrbiting)\n const release = () => {\n drag.current = null\n setOrbiting(false)\n }\n\n const handlers: OrbitHandlers = {\n ref,\n onPointerDown: (e) => {\n // A finger inspects where it lands, a tap having no move; Alt held, the drag pans, Mod turns.\n if (e.pointerType === \"touch\") return onHover(e)\n const pans = keys.on(\"dragPan\") && e.altKey\n if (pans || (keys.on(\"dragRotate\") && platformMod(e))) {\n drag.current = { x: e.clientX, y: e.clientY, moved: false, rotate: !pans }\n }\n },\n onPointerMove: (e) => {\n const d = drag.current\n if (!d) return touching.current ? onDragStart() : onHover(e)\n // A drag moves only while its modifier is held: the platform modifier\n // turning, Alt panning.\n if (d.rotate ? !platformMod(e) : !e.altKey) return release()\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, rotate: d.rotate }\n const k = width / e.currentTarget.getBoundingClientRect().width\n setOrbiting(d.rotate)\n move(d.rotate ? { yaw: dx * DRAG, tilt: dy * DRAG } : { pan: { x: dx * k, y: dy * k } })\n },\n onPointerUp: release,\n onPointerCancel: release,\n onDoubleClick: keys.on(\"doubleClickReset\") ? () => step({ reset: true }) : undefined,\n ...keyHandlers,\n \"data-orbiting\": orbiting,\n \"data-mod\": keys.on(\"dragRotate\") && held.mod ? true : undefined,\n \"data-alt\": keys.on(\"dragPan\") && held.alt ? true : undefined,\n }\n\n return { view, handlers, hint }\n}\n\ntype OrbitHandlers = React.SVGProps<SVGSVGElement> & {\n \"data-orbiting\": boolean\n \"data-mod\"?: boolean\n \"data-alt\"?: boolean\n}\n\n/**\n * Whether the platform modifier or Alt is held, so the cursor shows a hand\n * before the drag rotates and the four arrows before it pans. A missed keyup\n * (window blur while held) must not stick either cursor.\n */\nfunction useModsHeld() {\n const [mod, setMod] = React.useState(false)\n const [alt, setAlt] = React.useState(false)\n React.useEffect(() => {\n const modKey = mac() ? \"Meta\" : \"Control\"\n const onKey = (e: KeyboardEvent) => {\n if (e.key === modKey) setMod(e.type === \"keydown\")\n if (e.key === \"Alt\") setAlt(e.type === \"keydown\")\n }\n const onBlur = () => {\n setMod(false)\n setAlt(false)\n }\n window.addEventListener(\"keydown\", onKey)\n window.addEventListener(\"keyup\", onKey)\n window.addEventListener(\"blur\", onBlur)\n return () => {\n window.removeEventListener(\"keydown\", onKey)\n window.removeEventListener(\"keyup\", onKey)\n window.removeEventListener(\"blur\", onBlur)\n }\n }, [])\n return { mod, alt }\n}\n\n/**\n * The handlers that step the camera with the keys of `keys`. A key that\n * turns the camera marks it as orbiting until it is let go.\n */\nfunction useKeys(\n keys: Keymap,\n move: (step: Move) => void,\n setOrbiting: (orbiting: boolean) => void\n) {\n const onKeyDown = (e: React.KeyboardEvent<SVGSVGElement>) => {\n const step = keys.moves[pressed(e)]\n if (!step) return\n e.preventDefault()\n setOrbiting(Boolean(step.yaw || step.tilt))\n move(step)\n }\n const onKeyUp = () => setOrbiting(false)\n return { onKeyDown, onKeyUp }\n}\n\n/** A ref for the svg that hands it to the listeners of the wheel, of two fingers and of a missed drag. */\nfunction useGestures(\n jump: (to: (from: View3D) => View3D) => void,\n keys: Keymap,\n width: number,\n setOrbiting: (orbiting: boolean) => void\n) {\n const wheel = useWheelZoom(jump, keys.on(\"wheelZoom\"), width)\n const touch = useTouch(jump, keys, width, setOrbiting)\n const missed = useMissedDrag(keys)\n const ref = React.useCallback(\n (svg: SVGSVGElement | null) => {\n const off = [wheel(svg), touch.ref(svg), missed.ref(svg)]\n return () => off.forEach((f) => f?.())\n },\n [wheel, touch.ref, missed.ref]\n )\n return { ref, touching: touch.touching, hint: missed.hint }\n}\n\n// How far a press goes before it is a drag that missed, how long its hint\n// stays after the lift and how long it fades, in pixels and ms.\nconst MISS_DISTANCE = 8\nconst HINT = 1500\nconst HINT_FADE = 200\n\n/**\n * A ref for the svg that watches for a drag that turns nothing - the mouse\n * without a modifier, or one finger sideways, `MISS_DISTANCE` or further -\n * and the hint that names what would have turned the chart: the gesture of\n * `dragRotate` or `touchOrbit`, none where `keys` has it off. The hint stays\n * `HINT` after the lift, fades for `HINT_FADE` and then says nothing.\n */\nfunction useMissedDrag(keys: Keymap) {\n const [missed, setMissed] = React.useState<\"dragRotate\" | \"touchOrbit\">()\n const [open, setOpen] = React.useState(false)\n const [mouse, finger, pan] = [keys.on(\"dragRotate\"), keys.on(\"touchOrbit\"), keys.on(\"dragPan\")]\n const ref = React.useCallback(\n (svg: SVGSVGElement | null) => {\n if (!svg) return\n let press: (Point2D & { touch: boolean }) | null = null\n let timer: ReturnType<typeof setTimeout> | undefined\n const down = (e: PointerEvent) => {\n const touch = e.pointerType === \"touch\"\n // A second finger makes a pinch, a modifier a turn or a pan: neither misses.\n const plain = touch ? finger && e.isPrimary : mouse && !platformMod(e) && !(pan && e.altKey)\n press = plain && e.button === 0 ? { x: e.clientX, y: e.clientY, touch } : null\n }\n const move = (e: PointerEvent) => {\n const [dx, dy] = press ? [e.clientX - press.x, e.clientY - press.y] : [0, 0]\n if (!press || Math.hypot(dx, dy) < MISS_DISTANCE) return\n // Up or down, a finger scrolls the page.\n if (!press.touch || Math.abs(dx) > Math.abs(dy)) {\n clearTimeout(timer)\n setMissed(press.touch ? \"touchOrbit\" : \"dragRotate\")\n setOpen(true)\n }\n press = null\n }\n const up = () => {\n press = null\n clearTimeout(timer)\n timer = setTimeout(() => {\n setOpen(false)\n timer = setTimeout(() => setMissed(undefined), HINT_FADE)\n }, HINT)\n }\n // A plain drag holds no capture: released beyond the chart, it only leaves it.\n const listeners = {\n pointerdown: down,\n pointermove: move,\n pointerup: up,\n pointercancel: up,\n pointerleave: up,\n }\n for (const [type, f] of Object.entries(listeners))\n svg.addEventListener(type, f as EventListener)\n return () => {\n clearTimeout(timer)\n for (const [type, f] of Object.entries(listeners))\n svg.removeEventListener(type, f as EventListener)\n }\n },\n [mouse, finger, pan]\n )\n return { ref, hint: { shown: missed && keys.hint(missed), open } }\n}\n\n/** The point (`x`, `y`) of the client in the units of the view box of `svg`, `width` wide, from its middle. */\nfunction inViewBox(svg: SVGSVGElement, width: number, x: number, y: number) {\n const box = svg.getBoundingClientRect()\n const k = width / box.width\n return { x: (x - box.left - box.width / 2) * k, y: (y - box.top - box.height / 2) * k }\n}\n\n/** Two fingers as one: the point between them and their distance, in the pixels of the client. */\ntype Pinch = { x: number; y: number; d: number }\n\nconst pinchOf = (a: Touch, b: Touch): Pinch => ({\n x: (a.clientX + b.clientX) / 2,\n y: (a.clientY + b.clientY) / 2,\n d: Math.hypot(b.clientX - a.clientX, b.clientY - a.clientY),\n})\n\n/**\n * The step of the camera from the fingers `last` to `now`: the move of the\n * point between them turns it, if `orbit`, as far as a drag of the mouse, and\n * the change of their distance zooms it, if `zoom`. Two fingers on one pixel\n * have no distance to zoom from.\n */\nfunction pinchStep(last: Pinch, now: Pinch, orbit: boolean, zoom: boolean): Move {\n const [dx, dy] = orbit ? [now.x - last.x, now.y - last.y] : [0, 0]\n return { yaw: dx * DRAG, tilt: dy * DRAG, zoom: zoom ? now.d / Math.max(last.d, 1) : 1 }\n}\n\n/**\n * A ref for the svg that turns the camera with two fingers on it and zooms it\n * with their pinch, as far as `keys` has them on: the move of the point\n * between them turns, the change of their distance zooms to that point, both\n * at once. One finger is left to the browser, which scrolls the page with it\n * (ADR-0001), and so is a touch it has begun to scroll. The listeners are the\n * core's own: only one that is not passive keeps the browser from scrolling\n * under two fingers. `touching` is true while two fingers hold the chart.\n */\nfunction useTouch(\n jump: (to: (from: View3D) => View3D) => void,\n keys: Keymap,\n width: number,\n setOrbiting: (orbiting: boolean) => void\n) {\n const orbit = keys.on(\"touchOrbit\")\n const zoom = keys.on(\"pinchZoom\")\n const touching = React.useRef(false)\n const ref = React.useCallback(\n (svg: SVGSVGElement | null) => {\n if (!svg || !(orbit || zoom)) return\n let last: Pinch | null = null\n const onTouch = (e: TouchEvent) => {\n // Only fingers that landed on the chart count, and a touch the browser\n // scrolls with can no longer be cancelled: it stays the browser's.\n if (e.targetTouches.length !== 2 || !e.cancelable) {\n if (last) setOrbiting(false)\n touching.current = false\n last = null\n return\n }\n e.preventDefault()\n touching.current = true\n const now = pinchOf(e.targetTouches[0], e.targetTouches[1])\n if (last) {\n const step = {\n ...pinchStep(last, now, orbit, zoom),\n at: inViewBox(svg, width, now.x, now.y),\n }\n jump((v) => moved(v, step, v))\n setOrbiting(Boolean(step.yaw || step.tilt))\n }\n last = now\n }\n const events = [\"touchstart\", \"touchmove\", \"touchend\", \"touchcancel\"]\n for (const type of events)\n svg.addEventListener(type, onTouch as EventListener, { passive: false })\n return () => events.forEach((type) => svg.removeEventListener(type, onTouch as EventListener))\n },\n [jump, orbit, zoom, width, setOrbiting]\n )\n return { ref, touching }\n}\n\n/**\n * A ref for the svg that zooms the view to the cursor with the platform\n * modifier and the wheel, if `on`. Ctrl and the wheel zooms on a Mac too, because a trackpad\n * pinch arrives that way, indistinguishable from the keys. The wheel alone\n * still scrolls the page. While the wheel zooms, the svg says so in\n * `data-zoom` - `\"in\"` or `\"out\"`, the direction of its cursor - until\n * `ZOOM_CURSOR` after the last tick.\n */\nfunction useWheelZoom(jump: (to: (from: View3D) => View3D) => void, on: boolean, width: number) {\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 if (!on || !svg) return\n let timer: ReturnType<typeof setTimeout>\n const onWheel = (e: WheelEvent) => {\n if (!platformMod(e) && !e.ctrlKey) return\n e.preventDefault()\n const at = inViewBox(svg, width, e.clientX, e.clientY)\n jump((v) => moved(v, { zoom: 2 ** (-e.deltaY / 200), at }, v))\n svg.dataset.zoom = e.deltaY < 0 ? \"in\" : \"out\"\n clearTimeout(timer)\n timer = setTimeout(() => delete svg.dataset.zoom, ZOOM_CURSOR)\n }\n svg.addEventListener(\"wheel\", onWheel, { passive: false })\n return () => {\n clearTimeout(timer)\n svg.removeEventListener(\"wheel\", onWheel)\n }\n },\n [jump, on, width]\n )\n}\n\n/**\n * The tooltip of the mark under the pointer, the one painted last, and the\n * focus on its groups. The highlight follows the mark: `hover` sets the\n * tooltip only when the pointer moves onto another mark, or onto new data\n * under the same one, and the focus only when the groups change, so a move\n * within a mark of a chart at rest does not render it again; off the mark and\n * when the pointer leaves the chart, `leave` drops both. A finger lifting\n * leaves the chart too: what it tapped stays until a tap elsewhere, on the\n * chart or off it. While a drag turns the chart under the captured pointer,\n * `hide` drops the tooltip and keeps the focus, so a flow does not flash away\n * and can be followed from every side.\n */\nfunction useHover(\n scene: React.RefObject<Mark3D[]>,\n width: number,\n height: number,\n tip: Tip3D,\n focus: Focus3D\n) {\n const hovered = React.useRef<Mark3D>(undefined)\n const svg = React.useRef<SVGSVGElement>(null)\n const { set } = tip\n const clear = React.useCallback(() => {\n hovered.current = undefined\n focus.set(undefined)\n set(null)\n }, [focus, set])\n useTapElsewhere(svg, clear)\n const show = (mark?: Mark3D) => {\n // Also within one mark, whose groups new data can change; the store ignores the groups it holds.\n focus.set(mark?.groups)\n // The tooltip decides what shows: the same one says the same, new data under the same mark another.\n if (mark?.tooltip === hovered.current?.tooltip) return\n hovered.current = mark\n const tooltip = mark?.tooltip\n tip.set((typeof tooltip === \"function\" ? tooltip() : tooltip) ?? null)\n }\n\n return {\n hover: (e: React.PointerEvent<SVGSVGElement>) => {\n svg.current = e.currentTarget\n const rect = e.currentTarget.getBoundingClientRect()\n const x = e.clientX - rect.left\n const y = e.clientY - rect.top\n tip.follow({ x, y, width: rect.width, height: rect.height })\n show(hit(scene.current, { x: (x / rect.width) * width, y: (y / rect.height) * height }))\n },\n hide: () => {\n hovered.current = undefined\n tip.set(null)\n },\n leave: (e: React.PointerEvent) => {\n // A pinch dropped the tooltip already: lifting its fingers drops the focus too.\n if (e.pointerType !== \"touch\" || !hovered.current) show(undefined)\n },\n }\n}\n\n/** Calls `clear` when a finger taps anywhere but `svg`: on the page, or on another chart. */\nfunction useTapElsewhere(svg: React.RefObject<SVGSVGElement | null>, clear: () => void) {\n React.useEffect(() => {\n const tap = (e: PointerEvent) => {\n if (e.pointerType === \"touch\" && !svg.current?.contains(e.target as Node)) clear()\n }\n document.addEventListener(\"pointerdown\", tap)\n return () => document.removeEventListener(\"pointerdown\", tap)\n }, [svg, clear])\n}\n\n/** A store for the groups in focus, which tells its listeners only when the groups change. */\nfunction useFocus(): Focus3D {\n const [focus] = React.useState(() => {\n let groups: string[] | undefined\n const listeners = new Set<() => void>()\n return {\n get: () => groups,\n set: (next?: string[]) => {\n if (JSON.stringify(next) === JSON.stringify(groups)) return\n groups = next\n listeners.forEach((listener) => listener())\n },\n subscribe: (listener: () => void) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n }\n })\n return focus\n}\n\n/** Whether an item shares a group with the focus: the hover lights those items. */\nfunction useLit(items: { groups?: string[] }[]) {\n const { focus } = useChart3D()\n const groups = React.useSyncExternalStore(focus.subscribe, focus.get, focus.get)\n return (item: { groups?: string[] }) =>\n item.groups !== undefined && (groups?.some((group) => item.groups!.includes(group)) ?? false)\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 a canvas if the browser has one, for \"canvas\"\n * and \"webgl\" alike.\n */\nfunction useRenderer(requested: Renderer3D) {\n const [renderer, setRenderer] = React.useState<\"svg\" | \"canvas\">(\"svg\")\n React.useEffect(() => {\n const canvas = requested !== \"svg\" && 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) => resolved(canvas, css, colors.current))\n }, [scene, width])\n\n const canvas = React.useCallback(\n // A ref that returns its cleanup is never called with null.\n (node: HTMLCanvasElement) => {\n element.current = node\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/**\n * The color that `css` resolves to on `canvas`, inside the chart, as the sRGB\n * the canvas paints it in, cached per color: the canvas parses `fillStyle`\n * at every mark, and an `rgb()` four times faster than the `oklch()` the\n * theme resolves to.\n */\nfunction resolved(canvas: HTMLCanvasElement, css: string, cache: Map<string, string>) {\n let color = cache.get(css)\n if (color === undefined) {\n canvas.style.color = css\n color = srgb(getComputedStyle(canvas).color)\n cache.set(css, color)\n }\n return color\n}\n\n// One pixel to read back the sRGB of a color; made the first time a canvas paints.\nlet pixel: CanvasRenderingContext2D | null = null\n\n/** `color` as the `rgb()` a canvas paints it in, read back from a pixel. */\nfunction srgb(color: string) {\n // useRenderer paints on a canvas only where the browser gives one a 2D context.\n pixel ??= document.createElement(\"canvas\").getContext(\"2d\", { willReadFrequently: true })!\n pixel.clearRect(0, 0, 1, 1)\n pixel.fillStyle = color\n pixel.fillRect(0, 0, 1, 1)\n const [r, g, b, a] = pixel.getImageData(0, 0, 1, 1).data\n return `rgb(${r} ${g} ${b} / ${+(a / 255).toFixed(3)})`\n}\n\n/**\n * Sizes `canvas` to its pixels on screen, or, where it has that size, clears\n * it: setting the size throws its buffer away and makes a new one, every frame.\n */\nfunction fitCanvas(canvas: HTMLCanvasElement, ctx: CanvasRenderingContext2D) {\n const width = Math.round(canvas.clientWidth * devicePixelRatio)\n const height = Math.round(canvas.clientHeight * devicePixelRatio)\n if (canvas.width !== width || canvas.height !== height) {\n canvas.width = width\n canvas.height = height\n return\n }\n ctx.setTransform(1, 0, 0, 1, 0, 0)\n ctx.clearRect(0, 0, width, height)\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 // useRenderer draws on a canvas only where the browser gives one a 2D context.\n const ctx = canvas.getContext(\"2d\")!\n fitCanvas(canvas, ctx)\n const scale = canvas.width / width\n ctx.setTransform(scale, 0, 0, scale, 0, 0)\n ctx.lineJoin = \"round\"\n\n for (const mark of marks) {\n const { r, fill, stroke } = mark\n trace(ctx, mark)\n const filled = color(fill)\n ctx.fillStyle = filled\n ctx.fill()\n // A polygon is outlined in its own color, which closes the seams to its neighbours.\n const outline = r === undefined ? (stroke ?? fill) : stroke\n if (!outline) continue\n // Its own color is resolved already: a lookup per mark, not two.\n ctx.strokeStyle = outline === fill ? filled : color(outline)\n ctx.lineWidth = r === undefined ? 0.5 : 1\n ctx.stroke()\n }\n}\n\n/** Traces the outline of `mark` as the path of `ctx`: its polygon, or its circle. */\nfunction trace(ctx: CanvasRenderingContext2D, { points, r }: Mark3D) {\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}\n\n/** Twice the signed area of the triangle `a`, `b`, `c`: its sign tells which way it turns, 0 on a line. */\nconst turn = (a: Point2D, b: Point2D, c: Point2D) =>\n (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x)\n\n/** Twice the signed area of a ring: its sign tells which way it winds. */\nconst areaOf = (ring: Point2D[]) =>\n ring.reduce((sum, p, i) => sum + turn(ring[0], p, ring[i + 1] ?? p), 0)\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: \"svg\" | \"canvas\"\n canvas: React.Ref<HTMLCanvasElement>\n width: number\n height: number\n}) {\n if (renderer === \"svg\") return null\n\n return (\n <canvas\n data-slot=\"chart-3d-canvas\"\n ref={canvas}\n className=\"pointer-events-none absolute top-0 left-0 w-full mask-x-from-96% mask-y-from-96%\"\n style={{ aspectRatio: `${width} / ${height}` }}\n />\n )\n}\n\n// The ends of the axes of the gizmo, in the space of d3-3d, where y points down: up in the chart.\nconst GIZMO = [\n { axis: \"x\", x: 1, y: 0, z: 0 },\n { axis: \"y\", x: 0, y: -1, z: 0 },\n { axis: \"z\", x: 0, y: 0, z: 1 },\n]\n\nconst CORNERS = {\n \"top-left\": \"top-2 left-2\",\n \"top-right\": \"top-2 right-2\",\n \"bottom-left\": \"bottom-2 left-2\",\n \"bottom-right\": \"bottom-2 right-2\",\n}\n\n/**\n * The axes of the world in a corner of the chart: turned with the camera,\n * neither panned nor zoomed, the axis nearest the camera on top. An axis\n * draws in `currentColor`, so a text color on its `data-axis` recolors it.\n */\nfunction ChartGizmo3D({\n camera,\n corner,\n}: {\n camera: Camera3DInstance\n corner: ChartContainer3DProps[\"gizmo\"]\n}) {\n if (!corner) return null\n // The letters at the ends, in a box of 48 around its middle.\n const eye = camera3D()\n .origin({ x: 24, y: 24 })\n .scale(18)\n .rotateY(camera.rotateY())\n .rotateX(camera.rotateX())\n const ends = points3D<(typeof GIZMO)[number]>().camera(eye).data(GIZMO).sort(sort)\n\n return (\n <svg\n data-slot=\"chart-3d-gizmo\"\n viewBox=\"0 0 48 48\"\n aria-hidden=\"true\"\n className={cn(\"pointer-events-none absolute size-12 text-muted-foreground\", CORNERS[corner])}\n >\n {ends.map(({ axis, projected: p }) => (\n <g key={axis} data-axis={axis}>\n <line\n x1={24}\n y1={24}\n x2={24 + (p.x - 24) * 0.6}\n y2={24 + (p.y - 24) * 0.6}\n stroke=\"currentColor\"\n strokeWidth={1.5}\n strokeLinecap=\"round\"\n />\n <text\n x={p.x}\n y={p.y}\n textAnchor=\"middle\"\n dominantBaseline=\"central\"\n fill=\"currentColor\"\n className=\"text-[10px] font-medium\"\n >\n {axis.toUpperCase()}\n </text>\n </g>\n ))}\n </svg>\n )\n}\n\n/**\n * `text` as part of a CSS identifier: every character but an ASCII letter, a\n * digit, `-` and `_` written as its escape, such as the space of \"Net sales\"\n * or the dot of \"q1.sales\". Unescaped, it would end the name, and the browser\n * would drop the rule that declares the color.\n */\nconst cssName = (text: string) =>\n text.replace(/[^\\w-]/gu, (c) => `\\\\${c.codePointAt(0)!.toString(16)} `)\n\n/**\n * The color of the config key `key`: the CSS variable the container declares\n * for it. A chart without a config has no first key to fall back on, and\n * draws in a variable nobody declares: colorless, as before.\n */\nconst colorOf = (key: string | undefined) => `var(--color-${cssName(String(key))})`\n\n/**\n * The focus color of a fill, which a lit mark takes: `--chart-3d-focus`, or the\n * fill itself lightened, so the highlight carries the color of what it highlights.\n */\nconst focusOf = (fill: string) => `var(--chart-3d-focus, color-mix(in oklch, ${fill} 60%, white))`\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, place, repaint } = useChart3D()\n const id = React.useId()\n // Drawn on every renderer, empty off SVG, so the scene orders the sets as SVG does.\n const node = React.useRef<SVGGElement>(null)\n const lit = useLit(marks)\n // The lit marks take the focus color as their fill - `--chart-3d-focus`, their own fill\n // lightened unless set - and keep a stroke of their own: a scatter point its ring, a flow's\n // inner faces their seams. The order, and with it the depth, stays as painted.\n const drawn = marks.map((mark) => (lit(mark) ? { ...mark, fill: focusOf(mark.fill) } : mark))\n React.useLayoutEffect(() => {\n // The group is in the tree once the layout effects run.\n place(id, { marks: drawn, node: node.current! })\n repaint()\n })\n // A chart taken out of its container takes its marks along: the hover finds\n // none, and the canvas paints none.\n React.useLayoutEffect(\n () => () => {\n place(id)\n repaint()\n },\n [id, place, repaint]\n )\n\n return (\n <g ref={node} data-slot=\"chart-3d-marks\">\n {renderer === \"svg\" &&\n drawn.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={stroke ?? fill}\n strokeWidth={0.5}\n strokeLinejoin=\"round\"\n />\n ) : (\n // Rounded like a path, so the server and the browser, whose last\n // bits of a sine differ, write the same HTML.\n <circle\n key={key}\n cx={+points[0].x.toFixed(2)}\n cy={+points[0].y.toFixed(2)}\n r={+r.toFixed(2)}\n fill={fill}\n stroke={stroke}\n strokeWidth={stroke ? 1 : undefined}\n />\n )\n )}\n </g>\n )\n}\n\n/**\n * A label beside a mark, at `at` in the units of the view box. `toward`, a\n * unit vector, lays the label on that side of `at`, touching it, and slides\n * it round `at` as the vector turns; without it, `anchor` is the end of the\n * text that sits at `at`.\n */\nexport type Label3D = {\n key: string\n at: Point2D\n text: React.ReactNode\n anchor?: \"start\" | \"middle\" | \"end\"\n toward?: Point2D\n}\n\n/**\n * The labels of the marks of a chart, ringed by the background so that they\n * read on the marks. Like the labels of the box, they are SVG with every renderer.\n */\nfunction Labels3D({ labels }: { labels: Label3D[] }) {\n // ponytail: under the canvas of the canvas renderer, as the labels of the box; an SVG layer over the canvas would lift them.\n return (\n <g data-slot=\"chart-3d-labels\">\n {labels.map((label) => {\n const { x, y } = label.toward\n ? beside(label.at, label.toward, textWidth(label.text, 10), 10, 0)\n : label.at\n return (\n <text\n key={label.key}\n x={x}\n y={y}\n textAnchor={label.toward ? \"middle\" : label.anchor}\n dominantBaseline=\"central\"\n paintOrder=\"stroke\"\n strokeWidth={3}\n strokeLinejoin=\"round\"\n className=\"fill-foreground stroke-background text-[10px] font-medium\"\n >\n {label.text}\n </text>\n )\n })}\n </g>\n )\n}\n\nfunction ChartStyle({ id, config }: { id: string; config: ChartConfig }) {\n // The id escaped whole, as a CSS identifier, so a dot or a space keeps it one selector.\n const scope = `[data-chart=${cssName(id)}]`\n const colorConfig = Object.entries(config).filter(([, c]) => c.theme || c.color)\n // Every part of the axes that enters fades in: a label, a tick mark, a gridline, a wall.\n // The cursor names the gesture of the held modifier: the platform modifier\n // a hand (Alt, held with it, wins, as it does on pointer down), Alt the four\n // arrows of the pan, the wheel zoom its direction, and a turning drag grabbing.\n const entering = [\"text\", \"line\", \"path\"]\n .map((el) => `${scope} [data-slot=\"chart-3d-axes\"] ${el}`)\n .join(\", \")\n const base = `@keyframes chart-3d-axes-in { from { opacity: 0; } }\n${entering} { animation: chart-3d-axes-in 300ms ease-out; }\n@media (prefers-reduced-motion: reduce) { ${entering} { animation: none; } }\n${scope} svg[data-mod=\"true\"] { cursor: grab; }\n${scope} svg[data-alt=\"true\"] { cursor: move; }\n${scope} svg[data-zoom=\"in\"] { cursor: zoom-in; }\n${scope} svg[data-zoom=\"out\"] { cursor: zoom-out; }\n${scope} svg[data-orbiting=\"true\"] { cursor: grabbing; }`\n\n // No colors, no rule per theme.\n const themes = colorConfig.length ? Object.entries(THEMES) : []\n\n return (\n <style\n dangerouslySetInnerHTML={{\n __html: [\n base,\n ...themes.map(\n ([theme, prefix]) => `\n${prefix} ${scope} {\n${colorConfig\n .map(([key, item]) => {\n const color = item.theme?.[theme as keyof typeof item.theme] || item.color\n return color ? ` --color-${cssName(key)}: ${color};` : null\n })\n .join(\"\\n\")}\n}\n`\n ),\n ]\n .join(\"\\n\")\n // `cssName` has escaped the id and the keys; a color is the caller's text\n // still, and with its `<` escaped it cannot close the style element of a\n // server-rendered page. Whether it is CSS stays with the caller.\n .replaceAll(\"<\", \"\\\\3c \"),\n }}\n />\n )\n}\n\nfunction ChartTooltip3D({ tip }: { tip: Tip3D }) {\n const { tooltip, ref, place } = tip\n // Before the browser paints it, so a new tooltip never shows where the last one was.\n React.useLayoutEffect(place, [tooltip, place])\n if (!tooltip) return null\n\n return (\n <div\n ref={ref}\n data-slot=\"chart-3d-tooltip\"\n // As wide as its content wherever it sits, so a tooltip near the right edge is measured whole.\n className=\"pointer-events-none absolute z-10 grid w-max min-w-32 gap-1.5 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 text-xs shadow-xl motion-safe:transition-[translate]\"\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 * The hint of a drag that missed, a box in the middle of the chart over a\n * light veil, above the tooltip: always there, empty while it has nothing to\n * say, so a screen reader hears its first word. The veil has no blur, which\n * would cost every frame of the drag it shows during.\n */\nfunction ChartHint3D({\n shown,\n open,\n}: {\n shown?: { label: string; gesture: string[] }\n open: boolean\n}) {\n return (\n <div\n role=\"status\"\n data-slot=\"chart-3d-hint\"\n data-state={open ? \"open\" : \"closed\"}\n className=\"pointer-events-none absolute inset-0 z-20 grid place-items-center rounded-[inherit] bg-background/40 motion-safe:transition-opacity data-[state=closed]:opacity-0\"\n >\n {shown && (\n <div\n data-slot=\"chart-3d-hint-box\"\n className=\"flex items-center gap-2 rounded-lg border border-border/50 bg-background px-2.5 py-1.5 shadow-xl\"\n >\n <KbdGroup3D group={shown.gesture} />\n <span className=\"text-muted-foreground\">{shown.label}</span>\n </div>\n )}\n </div>\n )\n}\n\n/**\n * A button in the corner of the chart, named `label`, that lists the rows of\n * its keymap. The `help` keys on the chart open and close the list, Escape\n * closes it.\n */\nfunction ChartShortcuts3D({ rows, help, label }: Pick<Keymap, \"rows\" | \"help\" | \"label\">) {\n const [open, setOpen] = React.useState(false)\n const ref = React.useRef<HTMLDivElement>(null)\n const id = React.useId()\n // A dependency that stays the same while the keys do; no key is a line break.\n const keys = help.join(\"\\n\")\n\n React.useEffect(() => {\n const chart = ref.current?.parentElement\n const onKeyDown = (e: KeyboardEvent) => {\n if (keys.split(\"\\n\").includes(pressed(e))) setOpen((o) => !o)\n if (e.key === \"Escape\") setOpen(false)\n }\n chart?.addEventListener(\"keydown\", onKeyDown)\n return () => chart?.removeEventListener(\"keydown\", onKeyDown)\n }, [keys])\n\n // A pointer down outside the corner closes the list; the press still lands.\n React.useEffect(() => {\n if (!open) return\n const onPointerDown = (e: Event) => {\n if (!ref.current?.contains(e.target as Node)) setOpen(false)\n }\n document.addEventListener(\"pointerdown\", onPointerDown)\n return () => document.removeEventListener(\"pointerdown\", onPointerDown)\n }, [open])\n\n // Without a key or a panel, there is nothing to list.\n if (!rows.length) return null\n return (\n <div\n ref={ref}\n data-slot=\"chart-3d-shortcuts\"\n className=\"absolute top-2 right-2 z-10 flex flex-col items-end gap-1\"\n >\n <button\n type=\"button\"\n data-slot=\"chart-3d-shortcuts-trigger\"\n aria-label={label}\n aria-expanded={open}\n aria-controls={open ? id : undefined}\n onClick={() => setOpen((o) => !o)}\n className=\"inline-flex size-7 cursor-pointer items-center justify-center rounded-md bg-background/60 text-muted-foreground outline-none transition-colors hover:bg-background hover:text-accent-foreground focus-visible:ring-[3px] focus-visible:ring-ring/50 [&_svg]:size-4\"\n >\n <KeyboardIcon3D />\n </button>\n {open && <ChartShortcutList3D id={id} rows={rows} />}\n </div>\n )\n}\n\n/**\n * The keyboard of the shortcut button: the keyboard icon of Lucide,\n * Copyright (c) Lucide Icons and Contributors, ISC License, https://lucide.dev.\n */\nfunction KeyboardIcon3D() {\n return (\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M10 8h.01M12 12h.01M14 8h.01M16 12h.01M18 8h.01M6 8h.01M7 16h10M8 12h.01\" />\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n </svg>\n )\n}\n\n/** One group of keys as chips. */\nfunction KbdGroup3D({ group }: { group: string[] }) {\n return (\n <span data-slot=\"kbd-group\" className=\"flex gap-1\">\n {group.map((key, j) => (\n <kbd\n key={j}\n data-slot=\"kbd\"\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 )\n}\n\n/** The list of the shortcut panel: per row its label, then its keys, a rule, and its gestures. */\nfunction ChartShortcutList3D({ id, rows }: { id: string; rows: Keymap[\"rows\"] }) {\n return (\n <dl\n id={id}\n data-slot=\"chart-3d-shortcuts-panel\"\n 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 >\n {rows.map(({ label, keys, gestures }) => (\n <React.Fragment key={label}>\n <dt data-slot=\"chart-3d-shortcuts-label\" className=\"text-muted-foreground\">\n {label}\n </dt>\n <dd className=\"flex flex-wrap items-center justify-end gap-x-2 gap-y-1\">\n {keys.map((group, i) => (\n <KbdGroup3D key={i} group={group} />\n ))}\n {keys.length > 0 && gestures.length > 0 && (\n <span data-slot=\"chart-3d-shortcuts-rule\" className=\"h-4 w-px bg-border\" />\n )}\n {gestures.map((group, i) => (\n <KbdGroup3D key={i} group={group} />\n ))}\n </dd>\n </React.Fragment>\n ))}\n </dl>\n )\n}\n\nfunction ChartLegend3D({ config }: { config: ChartConfig }) {\n return (\n <div\n data-slot=\"chart-3d-legend\"\n className=\"flex flex-wrap items-center justify-center gap-x-4 gap-y-1 pt-3\"\n >\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: colorOf(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, the line of every axis along its edge with the mark of each of\n * its ticks, and the labels of every axis on each of its four edges. Only the\n * edge the axis sits on shows them, so when the axis moves to another edge,\n * its line, its marks and its labels fade from one to the other.\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 = intoWorld(axes3D().camera(camera), world)\n const { labels, lines, marks } = labelAxes(box.edges(spec), spec, format, titles)\n // The gridline of a tick the new data dropped fades out with its label.\n const leaving = new Set(\n ([\"x\", \"y\", \"z\"] as const).flatMap((a) =>\n ((spec[a] as GlidingAxis).leaving ?? []).map((value) => `${a}-${value}`)\n )\n )\n\n return (\n <g data-slot=\"chart-3d-axes\">\n {box\n .data(spec)\n .filter((wall) => !wall.ccw)\n .map((wall) => (\n <React.Fragment key={`${wall.axis}${wall.side}`}>\n <path d={quad(wall)} className=\"fill-muted/40 stroke-border\" strokeWidth={0.75} />\n {wall.grid.map((segment) => {\n const [from, to] = [segment[0], segment[segment.length - 1]]\n const key = gridKey(wall, from, to)\n return (\n <line\n key={key}\n x1={from.projected.x}\n y1={from.projected.y}\n x2={to.projected.x}\n y2={to.projected.y}\n style={{ opacity: leaving.has(key) ? 0 : 1 }}\n className=\"stroke-border transition-opacity duration-300 ease-out motion-reduce:transition-none\"\n strokeWidth={0.75}\n />\n )\n })}\n </React.Fragment>\n ))}\n {lines.map((line) => (\n <AxisLine3D key={line.key} line={line} ink=\"stroke-foreground\" width={1.5} />\n ))}\n {marks.map((mark) => (\n <AxisLine3D key={mark.key} line={mark} ink=\"stroke-foreground/60\" width={1} />\n ))}\n {labels.map((label) => (\n <AxisLabel3D key={label.key} label={label} />\n ))}\n </g>\n )\n}\n\n// The space between a tick and its label, the least space between two\n// labels, and the space over which a label fades as it nears another.\nconst GAP = 10\nconst PAD = 2\nconst FADE = 4\n// How far a label may slide along its edge to make room, before the labels take two rows.\nconst DODGE = 12\n// How far the mark of a tick reaches out from its edge.\nconst MARK = 6\n// How far the y title rises with the top of the box, so a steep edge crosses it instead of carrying it off its axis.\nconst LIFT = 3 * GAP\n\n/** The closed quad of a wall; its gridlines are their own lines, so a new one fades in. */\nfunction quad(wall: AxisWall) {\n return `M${wall.map(({ projected }) => `${projected.x},${projected.y}`).join(\"L\")}Z`\n}\n\n/**\n * The key of a gridline: the axis and value of the tick it marks - the one\n * coordinate its ends share beside the wall's own axis - so the gridline of\n * a tick that stays glides on, and one of a new tick mounts and fades in.\n * Exactly one coordinate differs along the line, because a domain always has\n * width: `axis` widens an empty extent.\n */\nfunction gridKey(wall: AxisWall, from: Point3D, to: Point3D) {\n const axis = ([\"x\", \"y\", \"z\"] as const).find((a) => a !== wall.axis && from[a] === to[a])!\n return `${axis}-${from[axis]}`\n}\n\n/**\n * A line of an axis: the line that carries its scale along the edge it sits\n * on, or the mark of one of its ticks. Its place follows the camera at once;\n * a change of edge fades it in a transition.\n */\ntype AxisLine = {\n key: string\n from: Point2D\n to: Point2D\n opacity: number\n}\n\n/**\n * A label of the chart box, a tick label or the title of an axis: its box\n * `w`×`h` in the units of the view box, centred at `at` and moved by `shift`\n * along its edge or into a second row.\n */\ntype AxisLabel = {\n key: string\n axis: keyof AxesSpec\n /** The tick value; the axis title has none. */\n value?: number\n at: Point2D\n w: number\n h: number\n shift: Point2D\n text: React.ReactNode\n opacity: number\n title?: boolean\n /** Where the text hangs on its box: its start or end edge; its middle by default. */\n anchor?: \"start\" | \"end\"\n}\n\n/**\n * The labels of the axes on all their edges, the line of every axis along its\n * edge and the mark of each of its ticks, shown on the edges the axes sit on.\n * Every edge fits its own tick labels; then the labels of an axis give way to\n * those of an axis with fewer ticks, which say more each, and the titles give\n * way to the ticks.\n */\nfunction labelAxes(\n edges: AxisEdge[],\n spec: AxesSpec,\n format: Partial<Record<keyof AxesSpec, (value: number) => React.ReactNode>>,\n titles: Partial<Record<keyof AxesSpec, React.ReactNode>>\n) {\n // An axis without ticks, such as the rows of an empty chart, has nothing to label.\n const axes = edges\n .filter((edge) => edge.length)\n .map((edge) =>\n edgeLabels(edge, edges, spec[edge.axis], format[edge.axis] ?? String, titles[edge.axis])\n )\n const shown = axes.filter((axis) => axis.chosen).sort((a, b) => a.ticks.length - b.ticks.length)\n const placed: AxisLabel[] = []\n for (const label of [...shown.flatMap((a) => a.ticks), ...shown.flatMap((a) => a.title ?? [])]) {\n // A tick outside the gliding ends stays faded out and does not take room from the others.\n if (label.opacity === 0) continue\n label.opacity = shows(label, placed)\n placed.push(label)\n }\n // The marks fade with their labels, also where a label of another axis takes its place.\n for (const axis of axes) axis.marks.forEach((mark, i) => (mark.opacity = axis.ticks[i].opacity))\n return {\n labels: axes.flatMap((axis) => [...axis.ticks, ...(axis.title ? [axis.title] : [])]),\n lines: axes.map((axis) => axis.line),\n marks: axes.flatMap((axis) => axis.marks),\n }\n}\n\n/**\n * The labels of one edge: a label per tick beside it, away from the box, in\n * the rows that `fit` finds, and the title of the axis beyond them. The\n * labels of an edge the axis does not sit on are there, but do not show.\n */\n/**\n * The point of `value` along `edge`, between the ticks that bracket it: the\n * projection keeps the edge straight, so the point lies on their line. An\n * axis of one tick is a point.\n */\nfunction along(edge: AxisEdge, value: number): Point2D {\n if (edge.length === 1) return edge[0].projected\n let i = 0\n while (i < edge.length - 2 && edge[i + 1][edge.axis] < value) i += 1\n const [a, b] = [edge[i][edge.axis], edge[i + 1][edge.axis]]\n // Neighbouring ticks are distinct values, so their span has width.\n const t = clamp(0, 1, (value - a) / (b - a))\n const [p, q] = [edge[i].projected, edge[i + 1].projected]\n return { x: p.x + (q.x - p.x) * t, y: p.y + (q.y - p.y) * t }\n}\n\n/** The ticks whose value lies in `domain`, with the ends of `domain`. */\nfunction inRange(ticks: AxisLabel[], domain: number[]) {\n const range = { lo: Math.min(...domain), hi: Math.max(...domain) }\n return {\n ranged: ticks.filter((t) => t.value !== undefined && within(range.lo, range.hi, t.value)),\n range,\n }\n}\n\n/** An edge the axis does not sit on hides its labels; on a chosen one, the ticks outside the gliding ends fade out. */\nfunction hideOffRange(labels: AxisLabel[], range: { lo: number; hi: number }, chosen: boolean) {\n if (!chosen) for (const l of labels) l.opacity = 0\n else\n for (const l of labels)\n if (l.value !== undefined && !within(range.lo, range.hi, l.value)) l.opacity = 0\n}\n\nfunction edgeLabels(\n edge: AxisEdge,\n edges: AxisEdge[],\n { domain, leaving = [], span }: GlidingAxis,\n format: (value: number) => React.ReactNode,\n title?: React.ReactNode\n) {\n const { axis, normal: n, chosen } = edge\n const label = (\n key: string,\n at: Point2D,\n text: React.ReactNode,\n h: number,\n gap: number,\n value?: number\n ) => {\n const w = textWidth(text, h)\n return { key, axis, value, at: beside(at, n, w, h, gap), w, h, shift: ZERO, text, opacity: 1 }\n }\n const id = `${axis}${edge.sides.join(\"\")}`\n // Keyed by value, so a tick that new data keeps glides on as the same label.\n const ticks = edge.map((tick) =>\n label(`${id}-${tick[axis]}`, tick.projected, format(tick[axis]), 10, GAP, tick[axis])\n )\n // A tick the new data dropped fades out in place and takes no room from the others.\n for (const t of ticks) if (t.value !== undefined && leaving.includes(t.value)) t.opacity = 0\n // Ticks outside the gliding ends fade out; only the ones inside take room.\n const { ranged, range } = inRange(\n ticks.filter((t) => t.opacity > 0),\n domain\n )\n // How far a row of labels reaches out from the edge.\n const depth = Math.max(0, ...ranged.map((t) => Math.abs(n.x) * t.w + Math.abs(n.y) * t.h))\n const row = { x: n.x * (depth + PAD), y: n.y * (depth + PAD) }\n const rows = fit(ranged, n, row)\n // The line of the axis runs the gliding span of its ticks, within the\n // gliding ends: a tick beyond them would drag it out of the box, and one\n // the data adds or drops would make it jump instead of glide.\n const [s0, s1] = span ?? [edge[0][axis], edge[edge.length - 1][axis]]\n const start = along(edge, clamp(range.lo, range.hi, s0))\n const end = along(edge, clamp(range.lo, range.hi, s1))\n const upper = clamp(range.lo, range.hi, end.y <= start.y ? s1 : s0)\n const head = title\n ? titleLabel(`${id}-title`, axis, title, start, end, n, depth, face(edge, edges, upper))\n : undefined\n // A second row of tick labels pushes the title of a floor axis out with it; the y title is clear of them.\n if (head && rows === 2 && axis !== \"y\") head.shift = row\n // The edges the axis does not sit on keep their labels in place, unseen, to fade them in.\n hideOffRange([...ticks, ...(head ? [head] : [])], range, chosen)\n // The axis line runs its edge between its outermost ticks; a mark points out from every\n // tick, as far out as its label is clear of it, and hides where the label does.\n const line: AxisLine = { key: id, from: start, to: end, opacity: chosen ? 1 : 0 }\n const marks = edge.map((tick, i) => ({\n key: ticks[i].key,\n from: tick.projected,\n to: { x: tick.projected.x + n.x * MARK, y: tick.projected.y + n.y * MARK },\n opacity: ticks[i].opacity,\n }))\n return { chosen, ticks, title: head, line, marks }\n}\n\n/**\n * The top of the box: the ends at `value` of the four edges of `edge`'s\n * axis, round the face they frame.\n */\nfunction face(edge: AxisEdge, edges: AxisEdge[], value: number) {\n const round = ({ sides: [a, b] }: AxisEdge) => (a ? 3 - b : b)\n return edges\n .filter((e) => e.axis === edge.axis)\n .sort((p, q) => round(p) - round(q))\n .map((e) => along(e, value))\n}\n\n/**\n * The height on screen of `face` between `x0` and `x1`: its least y there,\n * at a corner inside or where an edge crosses either end.\n */\nfunction highest(face: Point2D[], x0: number, x1: number) {\n const [lo, hi] = [Math.min(x0, x1), Math.max(x0, x1)]\n const inside = face.filter((p) => within(lo, hi, p.x)).map((p) => p.y)\n const crossing = face.flatMap((p, i) => {\n const q = face[(i + 1) % face.length]\n return [lo, hi]\n .filter((x) => p.x !== q.x && within(Math.min(p.x, q.x), Math.max(p.x, q.x), x))\n .map((x) => p.y + ((q.y - p.y) * (x - p.x)) / (q.x - p.x))\n })\n return Math.min(...inside, ...crossing)\n}\n\n/**\n * The title of an axis, upright. The y axis has a free end, the top: its\n * title stands over that corner on the box's side of the line, its edge on\n * the line, a gap clear of the `top` of the box as far as it reaches, rising\n * with it by up to `LIFT`. A floor axis ends in corners the other axes label,\n * so its title sits beyond its tick labels, at the middle of its edge,\n * `depth` being how far they reach out.\n */\nfunction titleLabel(\n key: string,\n axis: keyof AxesSpec,\n text: React.ReactNode,\n start: Point2D,\n end: Point2D,\n normal: Point2D,\n depth: number,\n top: Point2D[]\n): AxisLabel {\n const h = 12\n const w = textWidth(text, h)\n const middle = { x: (start.x + end.x) / 2, y: (start.y + end.y) / 2 }\n const label = { key, axis, text, title: true, opacity: 1, shift: ZERO, w, h }\n if (axis !== \"y\") return { ...label, at: beside(middle, normal, w, h, GAP + depth + GAP) }\n // The title runs from the higher end over the box, away from the tick labels, which keep their side.\n const corner = end.y <= start.y ? end : start\n const side = Math.sign(-normal.x) || 1\n const under = Math.max(corner.y - LIFT, highest(top, corner.x, corner.x + side * w))\n return {\n ...label,\n anchor: side > 0 ? \"start\" : \"end\",\n at: { x: corner.x + (side * w) / 2, y: under - GAP - h / 2 },\n }\n}\n\n/**\n * Fits the tick labels of an edge into the space between its ticks: in one\n * row if they keep `PAD` apart, or slid along the edge if no label has to\n * slide further than `DODGE`, else every other label a `row` further out if\n * that is enough, else every `stride`-th label of one row, 2, 4, 8… The\n * labels of a stride are among those of the one before, so as the edge\n * shortens, a label only ever leaves and none comes in for it. Returns the rows.\n */\nfunction fit(ticks: AxisLabel[], normal: Point2D, row: Point2D) {\n if (clear(ticks, 1) || slide(ticks, normal)) return 1\n ticks.forEach((t, i) => (t.shift = i % 2 ? row : ZERO))\n if (clear(ticks, 2)) return 2\n ticks.forEach((t) => (t.shift = ZERO))\n let stride = 2\n while (stride < ticks.length && !clear(ticks, stride, stride)) stride *= 2\n ticks.forEach((t, i) => (t.opacity = i % stride ? 0 : 1))\n return 1\n}\n\n/** Whether every label from every `every`-th keeps `PAD` apart from the one `step` after it. */\nfunction clear(ticks: AxisLabel[], step: number, every = 1) {\n // A hair under PAD, as labels that `slide` sets exactly PAD apart may round to less.\n return ticks.every(\n (t, i) => i % every > 0 || i + step >= ticks.length || apart(t, ticks[i + step]) > PAD - 1e-6\n )\n}\n\n/**\n * Slides the labels of an edge along it, square to its `normal`, as little\n * as they can until each has the room it needs. True if that is enough and\n * no label slides further than `DODGE`; the slide grows from nothing as the\n * labels near, so it follows the camera without a jump.\n */\nfunction slide(ticks: AxisLabel[], normal: Point2D) {\n const t = { x: -normal.y, y: normal.x }\n const along = ({ at }: AxisLabel) => at.x * t.x + at.y * t.y\n // The labels in their order along the edge, whichever way its ticks run.\n const line = [...ticks].sort((a, b) => along(a) - along(b))\n const gaps = line.slice(1).map((b, i) => room(line[i], b, normal, t))\n const placed = dodge(line.map(along), gaps)\n line.forEach((label, i) => {\n const d = placed[i] - along(label)\n label.shift = { x: t.x * d, y: t.y * d }\n })\n return line.every((label, i) => Math.abs(placed[i] - along(label)) <= DODGE) && clear(ticks, 1)\n}\n\n/**\n * How far along `t` the label `b` has to stand from `a`, which comes before\n * it there, for their boxes to keep `PAD` apart, as far as they stand apart\n * along `normal`, square to `t`.\n */\nfunction room(a: AxisLabel, b: AxisLabel, normal: Point2D, t: Point2D) {\n const off = (b.at.x - a.at.x) * normal.x + (b.at.y - a.at.y) * normal.y\n const x = ((a.w + b.w) / 2 + PAD - off * normal.x * Math.sign(t.x)) / Math.abs(t.x)\n const y = ((a.h + b.h) / 2 + PAD - off * normal.y * Math.sign(t.y)) / Math.abs(t.y)\n return Math.min(x, y)\n}\n\n/**\n * Places points on a line in their order, `gaps[i]` at least between the\n * i-th and the next, and moves them as little as it can: points that would\n * come too close move as one block, centred on the places they want.\n */\nfunction dodge(want: number[], gaps: number[]) {\n const blocks: { start: number; offsets: number[]; at: number }[] = []\n want.forEach((at, start) => {\n let block = { start, offsets: [0], at }\n let last = blocks.at(-1)\n while (last && last.at + last.offsets.at(-1)! + gaps[block.start - 1] > block.at) {\n blocks.pop()\n const base = last.offsets.at(-1)! + gaps[block.start - 1]\n const offsets = [...last.offsets, ...block.offsets.map((o) => o + base)]\n const first = last.start\n // Where the block moves its points the least: the mean of the places they want.\n const mean = offsets.reduce((sum, o, k) => sum + want[first + k] - o, 0) / offsets.length\n block = { start: first, offsets, at: mean }\n last = blocks.at(-1)\n }\n blocks.push(block)\n })\n return blocks.flatMap((block) => block.offsets.map((o) => block.at + o))\n}\n\n/**\n * How much of a label shows beside the labels placed before it: it fades as\n * it nears a label of another axis, by as much as that one shows. As this\n * follows the geometry, the label fades as smoothly as the camera turns.\n */\nfunction shows(label: AxisLabel, placed: AxisLabel[]) {\n return placed.reduce(\n (opacity, p) =>\n p.axis === label.axis && !label.title\n ? opacity\n : Math.min(opacity, 1 - (1 - clamp(0, 1, apart(label, p) / FADE)) * p.opacity),\n label.opacity\n )\n}\n\n/** The space between the boxes of two labels, negative where they overlap. */\nfunction apart(a: AxisLabel, b: AxisLabel) {\n const dx = Math.abs(a.at.x + a.shift.x - b.at.x - b.shift.x) - (a.w + b.w) / 2\n const dy = Math.abs(a.at.y + a.shift.y - b.at.y - b.shift.y) - (a.h + b.h) / 2\n return Math.max(dx, dy)\n}\n\n/**\n * The centre of a box `w`×`h` that lies `gap` from `at` towards `toward`, a\n * unit vector. As the vector turns, the box slides round `at` and keeps the\n * gap, where an anchor that switches from start to end would jump.\n */\nfunction beside(at: Point2D, toward: Point2D, w: number, h: number, gap: number): Point2D {\n const out = gap + (Math.abs(toward.x) * w + Math.abs(toward.y) * h) / 2\n return { x: at.x + toward.x * out, y: at.y + toward.y * out }\n}\n\n/** The width of a label at the font size `size`, guessed from its text, as the browser lays it out only after the render. */\nfunction textWidth(text: React.ReactNode, size: number) {\n // ponytail: 0.6em a character; measure with getBBox if wide fonts or rich labels still overlap.\n const chars = typeof text === \"string\" || typeof text === \"number\" ? String(text).length : 4\n return chars * size * 0.6\n}\n\n/**\n * A line of the axes, in the ink of the kind it is: the line of an axis along\n * its edge, or the mark of one of its ticks. Its place follows the camera at\n * once; a change of edge fades it in a transition.\n */\nfunction AxisLine3D({\n line: { from, to, opacity },\n ink,\n width,\n}: {\n line: AxisLine\n ink: string\n width: number\n}) {\n return (\n <line\n x1={from.x}\n y1={from.y}\n x2={to.x}\n y2={to.y}\n strokeWidth={width}\n style={{ opacity: Math.round(opacity * 100) / 100 }}\n className={cn(\"transition-opacity duration-300 ease-out motion-reduce:transition-none\", ink)}\n />\n )\n}\n\n/**\n * A label of the chart box. Its place follows the camera at once; a change\n * of edge, of row or of the labels that fit fades and moves it in a transition.\n */\nfunction AxisLabel3D({\n label: { at, w, shift, opacity, text, title, anchor },\n}: {\n label: AxisLabel\n}) {\n // A label anchored at its start or end begins exactly there, at that edge of its guessed box.\n const x = at.x + (anchor === \"start\" ? -w / 2 : anchor === \"end\" ? w / 2 : 0)\n return (\n <text\n x={x}\n y={at.y}\n textAnchor={anchor ?? \"middle\"}\n dominantBaseline=\"central\"\n style={{ opacity: Math.round(opacity * 100) / 100, translate: `${shift.x}px ${shift.y}px` }}\n className={cn(\n \"transition-[opacity,translate] duration-300 ease-out motion-reduce:transition-none\",\n title ? \"fill-foreground font-medium\" : \"fill-muted-foreground text-[10px]\"\n )}\n >\n {text}\n </text>\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/**\n * The axis `spec` with its domain widened by half a `cell` on each side, so\n * the box keeps room between the outermost data and its walls. The ticks stay\n * where they were, on the data.\n */\nfunction pad(spec: AxisSpec, cell: number): AxisSpec {\n return { domain: [spec.domain[0] - cell / 2, spec.domain[1] + cell / 2], ticks: spec.ticks }\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/**\n * The point at `lon` and `lat`, in degrees, on the sphere of `radius` around\n * the center of the world box: the prime meridian faces the viewer at yaw 0,\n * east lies to the right and the north pole is up - towards -y, as the box\n * counts y. The globe chart builds its tiles from it, since a chart may not\n * do trigonometry of its own.\n */\nfunction globe(lon: number, lat: number, radius = 1): Point3D {\n const [theta, phi] = [lon, lat].map((degrees) => (degrees * Math.PI) / 180)\n const flat = radius * Math.cos(phi)\n return { x: flat * Math.sin(theta), y: -radius * Math.sin(phi), z: flat * Math.cos(theta) }\n}\n\n/** The radius of the globe in the world box: `geoView` projects the land at it, and a geo chart places its marks on it. */\nconst GLOBE_RADIUS = 1.15\n\n/**\n * The camera without its perspective, a copy, since d3-3d shares the view of\n * a camera it is handed: d3-geo has no perspective, so a geo chart projects\n * its marks without one too, and they stay on the land.\n */\nfunction orthographic(camera: Camera3DInstance) {\n return camera3D()\n .origin(camera.origin())\n .scale(camera.scale())\n .rotateX(camera.rotateX())\n .rotateY(camera.rotateY())\n}\n\n/** What `earth` sets on a projection of d3-geo: the three setters it needs, each returning the projection. */\nexport type GeoProjectionLike<P> = {\n rotate(angles: [number, number]): P\n scale(scale: number): P\n translate(point: [number, number]): P\n}\n\n/**\n * Sets a projection of d3-geo to the camera: its rotation in degrees, its\n * scale at the radius of the globe and its origin, so the land turns, pans\n * and zooms with the marks.\n */\nfunction geoView<P extends GeoProjectionLike<P>>(camera: Camera3DInstance, projection: P) {\n const degrees = (radians: number) => (radians * 180) / Math.PI\n const { x, y } = camera.origin()\n return projection\n .rotate([degrees(camera.rotateY()), degrees(camera.rotateX())])\n .scale(camera.scale() * GLOBE_RADIUS)\n .translate([x, y])\n}\n\n/**\n * Stands in for a canvas under d3-geo's `geoPath`: `marks(draw, key, fill)`\n * runs `draw` and returns every ring it drew, cut at the horizon as d3-geo\n * cuts it, as a polygon mark keyed `key-i`. A point is not a region: the ring\n * its `moveTo` began goes with its `arc`. A hole is not one either: a ring\n * wound the other way than the largest ring is left out, so the region\n * around a hole fills it once, not twice.\n */\nfunction ringSink() {\n const rings: Point2D[][] = []\n return {\n beginPath: () => {\n rings.length = 0\n },\n moveTo: (x: number, y: number) => {\n rings.push([{ x, y }])\n },\n lineTo: (x: number, y: number) => {\n rings.at(-1)!.push({ x, y })\n },\n closePath: () => {},\n arc: () => {\n rings.pop()\n },\n marks: (draw: () => void, key: string, fill: string): Mark3D[] => {\n rings.length = 0\n draw()\n const areas = rings.map(areaOf)\n const largest = areas.reduce((a, b) => (Math.abs(b) > Math.abs(a) ? b : a), 0)\n return rings.flatMap((points, i) =>\n areas[i] * largest < 0 ? [] : [{ key: `${key}-${i}`, points, fill }]\n )\n },\n }\n}\n\n/**\n * The earth under the marks of a geo chart: the ocean and the land as marks,\n * flat in `--chart-3d-ocean` and `--chart-3d-land`, falling back to the\n * colors of the walls - scenery, grouped by nothing, with no tooltip, that\n * neither enters nor glides. The chart hands in d3-geo's `geoOrthographic()`\n * and `geoPath`, so the core carries no d3-geo; `earth` sets the projection\n * to the camera and draws through a sink that collects every ring, cut at\n * the horizon, as a polygon. `path` and `sink` come along for a chart that\n * draws regions of its own: `sink.marks(() => path(feature), key, fill)`.\n */\nfunction earth<\n Feature,\n P extends GeoProjectionLike<P>,\n Path extends (object: Feature | { type: \"Sphere\" }) => unknown,\n>(\n land: { features: Feature[] },\n camera: Camera3DInstance,\n projection: P,\n geoPath: (projection: P, sink: ReturnType<typeof ringSink>) => Path\n) {\n const sink = ringSink()\n const path = geoPath(geoView(camera, projection), sink)\n const marks = [\n ...sink.marks(() => path({ type: \"Sphere\" }), \"ocean\", \"var(--chart-3d-ocean, var(--muted))\"),\n ...land.features.flatMap((feature, i) =>\n sink.marks(() => path(feature), `land-${i}`, \"var(--chart-3d-land, var(--border))\")\n ),\n ]\n return { marks, path, sink }\n}\n\n/**\n * Hands the projection its accessors into the world box, so every chart maps\n * its shapes onto the screen the same way.\n */\nfunction intoWorld<Datum extends Point3D, T extends ShapeInstance<Datum>>(\n projection: T,\n world: World\n): T {\n return projection\n .x((p) => world.x(p.x))\n .y((p) => world.y(p.y))\n .z((p) => world.z(p.z))\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/**\n * `color` at `opacity`, from 0 to 1: a CSS color-mix with transparent, so a\n * mark fades on every renderer while its color stays in CSS. Rounded to a\n * percent, so the renderers that resolve colors cache a bounded few. Fade\n * after `shade`, which would mix a translucent color back towards opaque.\n */\nfunction faded(color: string, opacity: number) {\n const percent = Math.round(opacity * 100)\n return percent >= 100 ? color : `color-mix(in oklab, ${color} ${percent}%, transparent)`\n}\n\n/**\n * Whether `value` is a number a chart can place: whatever `Number` reads as a\n * finite number - a number, a string of one, a date, a bigint - but not what\n * it reads as 0 for want of a value: null, a blank string and a boolean would\n * draw an entry without a place at the origin.\n */\nfunction finite(value: unknown) {\n const isBlank = typeof value === \"string\" && value.trim() === \"\"\n const isValue = value != null && typeof value !== \"boolean\" && !isBlank\n return isValue && Number.isFinite(Number(value))\n}\n\n/**\n * `value` as an amount a mark is sized by, such as the area of a dot or the\n * height of a tile: one below 0, or one that is not a finite number, stands\n * as 0.\n */\nfunction nonNegative(value: unknown) {\n return finite(value) ? Math.max(0, Number(value)) : 0\n}\n\n/**\n * The entries of `data` and their series, for a chart that lays the entries\n * out along x and the series along z, as the bar and the area chart do. The\n * name of every entry comes from its `index` field, the series are `keys` or\n * the keys of the config, and the `target` of every cell is keyed by the name\n * of its entry and its series, so it follows its entry when the data\n * reorders; a value that is not a finite number stands as 0. Each glides by name:\n * `values` from 0, `rows` - the place of every entry - to where it stands, and\n * `presence` from 0 to 1 as an entry comes and back as it goes, the gone ones\n * still among them. `labels` name the ticks: the entry at a tick of x, through\n * `format.x` - a tick of a gone entry fades out unnamed - and the series at a\n * tick of z. Every entry is keyed by its id - its name, made unique where a\n * name repeats - and `nameOf` reads the name back; `entries` holds the entry\n * behind every id still in the data.\n */\nfunction useSeries<T extends Record<string, unknown>>({\n data,\n index,\n keys,\n format = {},\n}: {\n data: T[]\n index: keyof T & string\n keys?: string[]\n format?: { x?: (label: string) => React.ReactNode; y?: (value: number) => React.ReactNode }\n}) {\n const { config } = useChart3D()\n const series = React.useMemo(() => keys ?? Object.keys(config), [keys, config])\n // Built once per change of the data, not at every frame the camera turns.\n const { names, ids, target, order, present } = React.useMemo(() => {\n const names = data.map((d) => String(d[index] ?? \"\"))\n const ids = uniqueIds(names)\n return {\n names,\n ids,\n target: Object.fromEntries(\n data.flatMap((d, i) =>\n series.map((key) => [`${ids[i]}-${key}`, finite(d[key]) ? Number(d[key]) : 0])\n )\n ),\n order: Object.fromEntries(ids.map((id, i) => [id, i])),\n present: Object.fromEntries(ids.map((id) => [id, 1])),\n }\n }, [data, index, series])\n const labels = {\n x: (i: number) => (format.x ?? String)(names[i] ?? \"\"),\n y: format.y,\n z: (j: number) => config[series[j]]?.label ?? series[j],\n }\n return {\n series,\n target,\n entries: new Map(data.map((d, i) => [ids[i], d])),\n values: useTween(target, 0),\n rows: useTween(order),\n presence: useTween(present, 0),\n labels,\n nameOf,\n }\n}\n\n// Between a name and the count of its repeat, in the id of an entry: a\n// character no name of the data is expected to hold.\nconst REPEAT = \"\\u0000\"\n\n/**\n * An id per name, unique: a name the first time, the name and its count when\n * it comes again, so entries of the same name are entries of their own.\n * Nothing else tells them apart, so the order of the data does: the first\n * \"Jan\" stays the first through an update, whichever entry that is.\n */\nfunction uniqueIds(names: string[]) {\n const seen = new Map<string, number>()\n return names.map((name) => {\n const count = (seen.get(name) ?? 0) + 1\n seen.set(name, count)\n return count === 1 ? name : `${name}${REPEAT}${count}`\n })\n}\n\n/** The name of the entry of `id`, as its data names it. */\nconst nameOf = (id: string) => id.split(REPEAT)[0]\n\n/** The marks of a cube: its faces that look at the camera, shaded in `color`, each with `tooltip` on hover. */\nfunction cubeMarks(\n id: string,\n faces: CubeFace[],\n color: string,\n tooltip: Mark3D[\"tooltip\"]\n): Mark3D[] {\n // The faces point outwards: a convex shape 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\n/**\n * The corners of a bar on the floor of `world`, at `x` and `z` in the values\n * of the data, from 0 to `value`, `size` wide and deep in the world box.\n * 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 and faded to `opacity`, each with `tooltip` on hover. Its group is the bar alone, so hovering highlights one bar. */\nfunction barMarks({\n id,\n faces,\n color,\n tooltip,\n opacity,\n}: {\n id: string\n faces: CubeFace[]\n color: string\n tooltip: Mark3D[\"tooltip\"]\n opacity: number\n}) {\n return cubeMarks(id, faces, color, tooltip).map((mark) => ({\n ...mark,\n fill: faded(mark.fill, opacity),\n groups: [id],\n }))\n}\n\n/**\n * The color at `value` on a ramp from the config color `low` at `lo` to\n * `high` at `hi` - a value beyond them takes the color of the nearer end: a\n * CSS color-mix, so it follows the theme.\n */\nfunction ramp(value: number, [lo, hi]: [number, number], [low, high]: [string, string]) {\n const t = Math.min(100, Math.max(0, Math.round(((value - lo) / (hi - lo || 1)) * 100)))\n return `color-mix(in oklch, ${colorOf(high)} ${t}%, ${colorOf(low)})`\n}\n\n/**\n * Where the `count` columns or rows of a grid stand along one axis of\n * arrangement: at their value of `at`, in any order, or evenly over `ends`,\n * by default their indices; one without a finite value has no place. With\n * the cell, the smallest gap between two places - 1 where there is none -\n * and the axis over the places, its ticks within: its walls half a cell\n * beyond them - the padding - or at them where not `padded`, never at a\n * rounder tick, which would leave the box empty beyond the data.\n */\nfunction gridAxis(\n count: number,\n {\n at,\n ends = [0, count - 1],\n padded = true,\n }: { at?: number[]; ends?: [number, number]; padded?: boolean } = {}\n) {\n const even = linear([0, count - 1], ends)\n const values = Array.from({ length: count }, (_, i) => (at ? at[i] : even(i)))\n const places: Record<number, number> = Object.fromEntries(\n values.flatMap((v, i) => (finite(v) ? [[i, v]] : []))\n )\n const sorted = [...new Set(Object.values(places))].sort((a, b) => a - b)\n const gaps = sorted.slice(1).map((v, i) => v - sorted[i])\n const cell = gaps.length ? Math.min(...gaps) : 1\n const [lo = 0, hi = lo] = [sorted[0], sorted.at(-1)]\n // A single place has no span of its own: it keeps its padding either way.\n const spec = pad({ domain: [lo, hi], ticks: ticks(lo, hi, 5) }, padded || lo === hi ? cell : 0)\n return { places, cell, spec }\n}\n\n/** `cubes`, each with its bottom face as `floor`, found once: bars on one floor paint back to front by it. */\nfunction floored<C extends { faces: CubeFace[] }>(cubes: C[]) {\n return cubes.map((cube) =>\n Object.assign(cube, { floor: cube.faces.find((f) => f.face === \"bottom\")! })\n )\n}\n\nexport {\n ChartContainer3D,\n ChartLegend3D,\n Axes3D,\n Marks3D,\n Labels3D,\n axis,\n pad,\n linear,\n worldBox,\n globe,\n GLOBE_RADIUS,\n orthographic,\n earth,\n intoWorld,\n shade,\n colorOf,\n faded,\n finite,\n nonNegative,\n useSeries,\n cubeMarks,\n barCorners,\n barMarks,\n floored,\n gridAxis,\n ramp,\n useTween,\n useTweenAxes,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { range, ticks } from \"d3-array\"\nimport {\n polygons3D,\n sort,\n type AxesSpec,\n type Point3D,\n type Polygon,\n type Polygons3DInstance,\n} from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n intoWorld,\n pad,\n useSeries,\n shade,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n colorOf,\n type ChartConfig,\n type Mark3D,\n type Tooltip3D,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type AreaChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per point along x, with a value per series. */\n data: T[]\n /** The field that names each entry, such as \"year\"; a point follows its name through updates, and an entry of a name that repeats is, in the order of the data, a point of its own. */\n index: keyof T & string\n /**\n * The fields that hold the series, one ribbon each.\n * @defaultValue the keys of the chart config\n */\n keys?: string[]\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 * What a face of a ribbon says on hover: `tooltip` is what it would say,\n * its series and, on a segment of the top, the two entries it spans with\n * their values as the ticks name them; `data` the series key and those\n * entries, none on a side; `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (tooltip: Tooltip3D, data: { key: string; entries: T[] }) => Tooltip3D | null\n}\n\n// The share of its row along z a ribbon covers.\nconst RIBBON = 2 / 3\n\n/**\n * Areas pushed back into ribbons: the entries of `data` along x, one ribbon\n * per series along z, the area under its line reaching down to the floor of\n * the box. The series are the keys of the chart config unless `keys` names\n * them.\n */\nexport function AreaChart3D<T extends Record<string, unknown>>({\n data,\n index,\n keys,\n format = {},\n titles,\n tooltip,\n}: AreaChart3DProps<T>) {\n const { config, camera } = useChart3D()\n // The rows glide to their new places, and an entry that comes or goes\n // unfolds from its neighbour as far as its presence.\n const { series, target, entries, values, rows, presence, labels, nameOf } = useSeries({\n data,\n index,\n keys,\n format,\n })\n const spec = useTweenAxes(areaAxes(data.length, series.length, Object.values(target)))\n // The box deepens with the series, so a ribbon stays a ribbon, and glides\n // there with the axes.\n const depth = useTween({ depth: Math.min(1, Math.max(0.25, series.length / 6)) }).depth\n const world = worldBox(spec, depth)\n const polygons = intoWorld(polygons3D().camera(camera), world)\n // The x axis keeps half a row beyond the first and the last entry.\n const ends = [spec.x.domain[0] + 0.5, spec.x.domain[1] - 0.5]\n const toward = Math.sign(camera.viewDirection().x)\n const marks = series\n .flatMap((key, j) => {\n const line = linePoints(rows, values, presence, key, ends)\n if (!line.length) return []\n const z = [j - RIBBON / 2, j + RIBBON / 2]\n return [{ key, line, faces: ribbonFaces(polygons, line, spec.y.domain[0], z) }]\n })\n // The ribbons lie in slices of z of their own, and their floors span the\n // same x at the same height: ordered by the middle of the floor, they are\n // painted back to front exactly.\n .sort((a, b) => sort(a.faces[4], b.faces[4]))\n .flatMap(({ key, line, faces }) =>\n ribbonMarks(key, painted(faces, toward), line, (names) =>\n ribbonTooltip(key, names, { config, entries, target, nameOf }, { format, tooltip })\n )\n )\n\n return (\n <>\n <Axes3D spec={spec} world={world} titles={titles} format={labels} />\n <Marks3D marks={marks} />\n </>\n )\n}\n\n/** One point of a line: the entry it stands for, its place along x and its value. */\ntype LinePoint = { name: string; x: number; value: number }\n\n/** One face of a ribbon after the projection, with its name and, on the top, its segment. */\ntype RibbonFace = Polygon<\n Point3D,\n Point3D[] & { face: \"front\" | \"back\" | \"left\" | \"right\" | \"bottom\" | \"top\"; segment: number }\n>\n\n/**\n * The points of the line of the series `key`, in order along x: every entry,\n * the ones still gliding away among them, at its gliding row and value. An\n * entry that comes or goes unfolds from the point before it - the one after\n * it, at the start of the line - and folds back into it, as far as its\n * `presence`, so the ribbon opens and closes without a step. Its value comes\n * from nothing as its presence grows - the two glide in step - so the part of\n * its neighbour it has not yet left is added: the point heads straight from\n * the neighbour to its own, never down towards the floor. Every\n * point stays within the gliding `ends` of the x axis, so a line with no\n * neighbour to unfold from - one that was empty - grows inside the box\n * instead of standing beyond its walls. A point only one of the tweens still\n * knows is on its way out and stays unseen.\n */\nfunction linePoints(\n rows: Record<string, number>,\n values: Record<string, number>,\n presence: Record<string, number>,\n key: string,\n [lo, hi]: number[]\n): LinePoint[] {\n const own = Object.entries(rows)\n .sort(([, a], [, b]) => a - b)\n .flatMap(([name, x]) => {\n const value = values[`${name}-${key}`]\n return value === undefined ? [] : [{ name, x, value, seen: presence[name] }]\n })\n let anchor = own.find((p) => p.seen === 1)\n return own\n .map((p) => {\n if (p.seen === 1) anchor = p\n const { x } = anchor ?? p\n return {\n name: p.name,\n x: Math.min(hi, Math.max(lo, x + p.seen * (p.x - x))),\n value: p.value + (1 - p.seen) * (anchor?.value ?? 0),\n }\n })\n .sort((a, b) => a.x - b.x)\n}\n\n/**\n * The faces of the ribbon of `line`, projected: the area under the line,\n * down to `floor`, pushed back from `z[0]` to `z[1]`. Each is wound\n * counter-clockwise as seen from outside, so `ccw` tells whether it faces the\n * camera. The first five lie on its bounding box - the front and the back,\n * one polygon each however many points the line has, the two ends and the\n * bottom - the rest are its top, one quad per segment of the line.\n */\nfunction ribbonFaces(\n polygons: Polygons3DInstance<Point3D>,\n line: LinePoint[],\n floor: number,\n [back, front]: number[]\n): RibbonFace[] {\n const on = (p: LinePoint, z: number) => ({ x: p.x, y: p.value, z })\n const under = (p: LinePoint, z: number) => ({ x: p.x, y: floor, z })\n const face = (name: RibbonFace[\"face\"], points: Point3D[], segment = -1) =>\n Object.assign(points, { face: name, segment })\n const [a, o] = [line[0], line[line.length - 1]]\n return polygons.data([\n face(\"front\", [\n on(a, front),\n under(a, front),\n under(o, front),\n ...line\n .slice(1)\n .reverse()\n .map((p) => on(p, front)),\n ]),\n face(\"back\", [...line.map((p) => on(p, back)), under(o, back), under(a, back)]),\n face(\"left\", [on(a, back), under(a, back), under(a, front), on(a, front)]),\n face(\"right\", [on(o, front), under(o, front), under(o, back), on(o, back)]),\n face(\"bottom\", [under(a, front), under(a, back), under(o, back), under(o, front)]),\n ...line\n .slice(1)\n .map((p, i) =>\n face(\"top\", [on(line[i], front), on(p, front), on(p, back), on(line[i], back)], i)\n ),\n ])\n}\n\n/**\n * The faces of a ribbon that face the camera, in paint order. Every segment\n * of the top is a slab, and the planes x = const separate them: the top is\n * painted from the end of the ribbon away from the camera, which `toward`,\n * the sign of x in the view direction, names. The faces of the bounding box\n * come last: the ribbon lies wholly behind each of them.\n */\nfunction painted(faces: RibbonFace[], toward: number) {\n const shown = faces.filter((f) => f.ccw)\n return [\n ...shown.filter((f) => f.face === \"top\").sort((a, b) => toward * (a.segment - b.segment)),\n ...shown.filter((f) => f.face !== \"top\"),\n ]\n}\n\n/**\n * The marks of one ribbon, shaded in the color of its series. Each face is a\n * group of its own, so hovering highlights the face under the pointer alone.\n * A segment of the top is keyed by the entry it starts at, so it keeps its\n * mark when entries come or go before it. Every face says what `tooltip`\n * makes of the entries it spans: the two ends of a segment of the top, none\n * on a side.\n */\nfunction ribbonMarks(\n key: string,\n faces: RibbonFace[],\n line: LinePoint[],\n tooltip: (names: string[]) => Mark3D[\"tooltip\"]\n): Mark3D[] {\n const color = colorOf(key)\n const spans = (f: RibbonFace) =>\n f.face === \"top\" ? [line[f.segment].name, line[f.segment + 1].name] : []\n return faces.map((f) => {\n const id = f.face === \"top\" ? `${key}-top-${line[f.segment].name}` : `${key}-${f.face}`\n return {\n key: id,\n points: f.map((p) => p.projected),\n fill: shade(f, color),\n groups: [id],\n tooltip: tooltip(spans(f)),\n }\n })\n}\n\n/**\n * What a face of the ribbon of `key` says on hover, made when the pointer\n * lands on it: the series and, on a segment of the top, the entries it\n * spans as the ticks of x name them, with their values as the ticks of y\n * name them - or what `tooltip` makes of that. A segment whose entry has\n * left the data says nothing.\n */\nfunction ribbonTooltip<T extends Record<string, unknown>>(\n key: string,\n names: string[],\n {\n config,\n entries,\n target,\n nameOf,\n }: {\n config: ChartConfig\n entries: Map<string, T>\n target: Record<string, number>\n nameOf: (id: string) => string\n },\n { format = {}, tooltip = (tip) => tip }: Pick<AreaChart3DProps<T>, \"format\" | \"tooltip\">\n): Mark3D[\"tooltip\"] {\n const spanned = names.flatMap((name) => {\n const entry = entries.get(name)\n return entry ? [entry] : []\n })\n if (spanned.length < names.length) return undefined\n const color = colorOf(key)\n return () =>\n tooltip(\n {\n title: config[key]?.label ?? key,\n items: names.map((name) => {\n const value = target[`${name}-${key}`]\n return {\n label: (format.x ?? String)(nameOf(name)),\n value: format.y?.(value) ?? value,\n color,\n }\n }),\n },\n { key, entries: spanned }\n )\n}\n\n/**\n * The axes of an area chart: the entries along x, with half a row of room\n * between the first and the last and the walls, a row per series along z.\n * A line has many entries, so x ticks about ten of them, not every one.\n */\nfunction areaAxes(entries: number, series: number, values: number[]): AxesSpec {\n const every = entries ? ticks(0, entries - 1, 10).filter(Number.isInteger) : []\n return {\n x: pad({ domain: [0, Math.max(0, entries - 1)], ticks: every }, 1),\n y: axis(Math.min(0, ...values), Math.max(0, ...values)),\n z: pad({ domain: [0, Math.max(0, series - 1)], ticks: range(series) }, 1),\n }\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { cubes3D, sort, type AxesSpec, type Camera3DInstance } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n barCorners,\n barMarks,\n floored,\n pad,\n useSeries,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n colorOf,\n type ChartConfig,\n type Mark3D,\n type Tooltip3D,\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\"; a bar follows its name through updates, and an entry of a name that repeats is, in the order of the data, a bar of its own. */\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 * What a bar says on hover: `tooltip` is what it would say, its entry and\n * value as the ticks name them, `data` the entry and the series key behind\n * it; `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (tooltip: Tooltip3D, data: { entry: T; key: string }) => Tooltip3D | null\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 tooltip,\n}: BarChart3DProps<T>) {\n const { config, camera } = useChart3D()\n // A value that is not a number stands as no bar, one of height 0; a new one\n // grows from the floor, and a gone one shrinks back into it. The rows glide\n // to their new cells when the data reorders; a gone row stands in its cell\n // while its bars shrink and fade away, so a flat bar never pops.\n const { series, target, entries, values, rows, presence, labels, nameOf } = useSeries({\n data,\n index,\n keys,\n format,\n })\n const cells = barCells(rows, series, values)\n\n const box = barBox(data.length, series.length, Object.values(target))\n // Every axis glides with the bars: the value ends with the heights, the row\n // and series ends - and the depth of the box - as rows come and go. The\n // size of a bar comes from the gliding ends, so it eases with its cell.\n const spec = useTweenAxes(box.spec)\n const depth = useTween({ depth: box.depth }).depth\n const world = worldBox(spec, depth)\n const bars = barShapes(camera, cells, world, cellSize(spec, depth, barSize))\n\n return (\n <>\n <Axes3D spec={spec} world={world} titles={titles} format={labels} />\n <Marks3D\n marks={bars.flatMap((bar) =>\n barMarks({\n id: `${bar.name}-${bar.key}`,\n faces: bar.faces,\n color: colorOf(bar.key),\n tooltip: barTooltip(\n { id: bar.name, name: nameOf(bar.name), key: bar.key },\n entries.get(bar.name),\n target,\n { config, format, tooltip }\n ),\n opacity: presence[bar.name],\n })\n )}\n />\n </>\n )\n}\n\n/** The cubes of the cells, projected by `camera` and painted back to front by their footprint, as the bars stand on one floor. */\nfunction barShapes(\n camera: Camera3DInstance,\n cells: ReturnType<typeof barCells>,\n world: World,\n size: { width: number; depth: number }\n) {\n return floored(\n cubes3D()\n .camera(camera)\n .data(\n cells.map(({ name, x, j, key, value }) =>\n Object.assign(barCorners(world, x, j, value, size), { name, key, value })\n )\n )\n ).sort((a, b) => sort(a.floor, b.floor))\n}\n\n/**\n * The cell of every bar, the rows still gliding away among them: the row\n * position along x, the series `key` along z, with the tweened value. A cell\n * only one of the tweens still knows is on its way out and stays unseen.\n */\nfunction barCells(rows: Record<string, number>, series: string[], values: Record<string, number>) {\n return Object.entries(rows).flatMap(([name, x]) =>\n series.flatMap((key, j) => {\n const value = values[`${name}-${key}`]\n return value === undefined ? [] : [{ name, x, j, key, value }]\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 * with half a cell of room between the outer rows and the walls.\n */\nfunction barBox(entries: number, series: number, values: number[]) {\n const index = (length: number) => Array.from({ length }, (_, i) => i)\n const spec: AxesSpec = {\n x: pad({ domain: [-0.5, entries - 0.5], ticks: index(entries) }, 1),\n y: axis(Math.min(0, ...values), Math.max(0, ...values)),\n z: pad({ domain: [-0.5, series - 0.5], ticks: index(series) }, 1),\n }\n // A shallow box for few series, so the bars stay square.\n // An empty chart has no entries to divide by.\n const depth = Math.min(1, Math.max(0.25, series / (entries || 1)))\n return { spec, depth }\n}\n\n/**\n * The size of a bar, the share `barSize` of its cell - of the gliding ends of\n * `spec`, so a bar eases into a new cell size as rows come and go.\n */\nfunction cellSize(spec: AxesSpec, depth: number, barSize: number) {\n return {\n width: (2 / (spec.x.domain[1] - spec.x.domain[0])) * barSize,\n depth: ((2 * depth) / (spec.z.domain[1] - spec.z.domain[0])) * barSize,\n }\n}\n\n/**\n * What the bar of `entry` says on hover, made when the pointer lands on it:\n * the entry as the ticks of x name it and its value as the ticks of y name\n * it - or what `tooltip` makes of that. A bar whose entry has left the data\n * says nothing.\n */\nfunction barTooltip<T extends Record<string, unknown>>(\n { id, name, key }: { id: string; name: string; key: string },\n entry: T | undefined,\n target: Record<string, number>,\n {\n config,\n format = {},\n tooltip = (tip) => tip,\n }: Pick<BarChart3DProps<T>, \"format\" | \"tooltip\"> & { config: ChartConfig }\n): Mark3D[\"tooltip\"] {\n if (!entry) return undefined\n const value = target[`${id}-${key}`]\n return () =>\n tooltip(\n {\n title: (format.x ?? String)(name),\n items: [\n {\n label: config[key]?.label ?? key,\n value: format.y?.(value) ?? value,\n color: colorOf(key),\n },\n ],\n },\n { entry, key }\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport { cubes3D, sort, type AxesSpec, type Point3D } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n barCorners,\n barMarks,\n finite,\n floored,\n gridAxis,\n ramp,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n type Mark3D,\n type Tooltip3D,\n type World,\n} from \"@/registry/new-york/ui/chart-3d\"\n\n// The share of its cell a bar covers; the rest is the gap that tells two bars apart.\nconst BAR = 0.8\n\nexport type BarFieldChart3DProps = {\n /**\n * The value of every bar, `data[row][column]`: the columns run along x, the\n * rows along z, and a bar rises from 0 to its value. One that is not a\n * finite number draws no bar.\n */\n data: number[][]\n /**\n * The data values the first and the last column (x) and row (z) stand for,\n * the others evenly between. The chart keeps half a cell between the bars\n * and the walls of its box.\n * @defaultValue the indices of the columns and rows\n */\n domain?: { x?: [number, number]; z?: [number, number] }\n /**\n * The value every column stands at along x, `x[column]`, in any order and\n * at any spacing, in place of `domain.x`. A column without a finite value\n * draws no bars.\n * @defaultValue evenly over `domain.x`\n */\n x?: number[]\n /**\n * The value every row stands at along z, `z[row]`, in any order and at any\n * spacing, in place of `domain.z`. A row without a finite value draws no\n * bars.\n * @defaultValue evenly over `domain.z`\n */\n z?: number[]\n /**\n * What a bar says on hover: `tooltip` is what it would say, its x, z and\n * value as the ticks name them, `data` the row and column of the bar, the\n * x and z they stand for and its value; `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (\n tooltip: Tooltip3D,\n data: { row: number; column: number; x: number; z: number; value: number }\n ) => Tooltip3D | null\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 * The config keys of the colors at the lowest and at the highest value.\n * @defaultValue the first two keys of the chart config\n */\n colors?: [string, string]\n}\n\n/**\n * A field of bars over a grid: `data[row][column]` is the value of a bar, the\n * columns run along x and the rows along z. Everything about a bar comes from\n * the data - its place from the value of its column and row, its footprint\n * from the smallest gap between two of them, its height from its value, its\n * color from the ramp between the two `colors` at the lowest and the highest\n * value.\n */\nexport function BarFieldChart3D({\n data,\n domain = {},\n x,\n z,\n tooltip,\n format,\n titles,\n colors,\n}: BarFieldChart3DProps) {\n const { config, camera } = useChart3D()\n const [low, high = low] = colors ?? Object.keys(config)\n const field = useField(data, { domain, x, z })\n // A bar glides to its new value; a new one grows from 0 as it fades in, a\n // gone one shrinks back to 0 as it fades out and leaves when the glide is done.\n const values = useTween(field.target, 0)\n const presence = useTween(field.present, 0)\n // y runs from 0; x and z span the places with half a cell of room.\n const y = axis(Math.min(0, field.lo), Math.max(0, field.hi))\n const spec = useTweenAxes({ x: field.x.spec, y, z: field.z.spec })\n const world = worldBox(spec)\n // Every column and row glides to its place, and the footprint with the cell.\n const places = { x: useTween(field.x.places), z: useTween(field.z.places) }\n const cell = useTween({ x: field.x.cell, z: field.z.cell })\n const size = {\n width: Math.abs(world.x(cell.x) - world.x(0)) * BAR,\n depth: Math.abs(world.z(cell.z) - world.z(0)) * BAR,\n }\n // The ramp glides with the data, not with the bars on screen: one growing\n // from 0 or shrinking to it must not recolor the others.\n const span = useTween({ lo: field.lo, hi: field.hi })\n\n const bars = floored(\n cubes3D<Point3D>()\n .camera(camera)\n .data(fieldCorners(values, world, places, size))\n ).sort((a, b) => sort(a.floor, b.floor))\n const marks = bars.flatMap((bar) =>\n barMarks({\n id: bar.key,\n faces: bar.faces,\n color: ramp(bar.value, [span.lo, span.hi], [low, high]),\n tooltip: fieldTooltip(bar, field, { format, titles, tooltip }),\n opacity: presence[bar.key],\n })\n )\n\n return (\n <>\n <Axes3D spec={spec} world={world} format={format} titles={titles} />\n <Marks3D marks={marks} />\n </>\n )\n}\n\n/** The value every column (x) and row (z) stands at, keyed by its index. */\ntype Place = Record<\"x\" | \"z\", Record<string, number>>\n\n/**\n * The value of every bar, keyed by its row and column so it follows its cell\n * through updates, with its presence, the lowest and highest value and the\n * places of the columns and rows - built once per change of the data, not at\n * every frame the camera turns. A bar draws where its value and both its\n * places are finite numbers.\n */\nfunction useField(\n data: number[][],\n {\n domain,\n x,\n z,\n }: Pick<BarFieldChart3DProps, \"x\" | \"z\"> & { domain: NonNullable<BarFieldChart3DProps[\"domain\"]> }\n) {\n return React.useMemo(() => {\n const columns = Math.max(0, ...data.map((row) => row.length))\n const sides = {\n x: gridAxis(columns, { at: x, ends: domain.x }),\n z: gridAxis(data.length, { at: z, ends: domain.z }),\n }\n const target: Record<string, number> = Object.fromEntries(\n data.flatMap((row, r) =>\n row.flatMap((v, c) =>\n finite(v) && c in sides.x.places && r in sides.z.places ? [[`${r}-${c}`, v]] : []\n )\n )\n )\n const [lo = 0, hi = 0] = extent(Object.values(target))\n return {\n ...sides,\n target,\n present: Object.fromEntries(Object.keys(target).map((key) => [key, 1])),\n lo,\n hi,\n }\n }, [data, x, z, domain.x, domain.z])\n}\n\n/**\n * The corners of every bar still on screen, from 0 to its gliding value, at\n * its row and column, `size` wide and deep.\n */\nfunction fieldCorners(\n values: Record<string, number>,\n world: World,\n at: Place,\n size: { width: number; depth: number }\n) {\n return Object.entries(values).map(([key, value]) => {\n const [row, column] = key.split(\"-\").map(Number)\n const corners = barCorners(world, at.x[column], at.z[row], value, size)\n return Object.assign(corners, { key, row, column, value })\n })\n}\n\n/**\n * What a bar says on hover, made when the pointer lands on it: its x and z\n * as the ticks name them and its value as the ticks of y name it - or what\n * `tooltip` makes of that. A bar that has left the data, its value or its\n * place, says nothing.\n */\nfunction fieldTooltip(\n { key, row, column }: { key: string; row: number; column: number },\n { target, x: xs, z: zs }: ReturnType<typeof useField>,\n {\n format = {},\n titles = {},\n tooltip = (tip) => tip,\n }: Pick<BarFieldChart3DProps, \"format\" | \"titles\" | \"tooltip\">\n): Mark3D[\"tooltip\"] {\n if (!(key in target)) return undefined\n const value = target[key]\n const named = (name: keyof AxesSpec, v: number) => ({\n label: titles[name] ?? (name === \"y\" ? \"value\" : name),\n value: format[name]?.(v) ?? v,\n })\n const [x, z] = [xs.places[column], zs.places[row]]\n return () =>\n tooltip(\n { items: [named(\"x\", x), named(\"z\", z), named(\"y\", value)] },\n { row, column, x, z, value }\n )\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { geoArea, geoOrthographic, geoPath } from \"d3-geo\"\n\nimport {\n Marks3D,\n earth,\n faded,\n useChart3D,\n useTween,\n colorOf,\n type ChartConfig,\n type Mark3D,\n type Tooltip3D,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type ChoroplethChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per region: the region an entry names takes its color, and the last entry on a region wins. */\n data: T[]\n /**\n * The regions of the earth, a GeoJSON feature collection, cut at the\n * horizon; the `id` of a feature is what an entry names. d3-geo reads a\n * region wound clockwise, the opposite of RFC 7946: topojson-client's\n * `feature` winds it so, and a region wound the other way fills the globe\n * around it.\n */\n land: GeoJSON.FeatureCollection\n /**\n * The field whose value, as a string, is the `id` of the region of the land\n * the entry colors: for world-atlas the ISO 3166-1 numeric code, `\"276\"`\n * for Germany.\n */\n id: keyof T & string\n /** The field of the value of an entry, shown in the tooltip of its region. */\n value: keyof T & string\n /**\n * The field whose value is the config key of the color of a region.\n * @defaultValue the first key of the chart config for every region\n */\n series?: keyof T & string\n /**\n * The field that names an entry: the title of the tooltip of its region.\n * @defaultValue the label of the series\n */\n label?: keyof T & string\n /** Formats the value in the tooltip. */\n format?: (value: number) => React.ReactNode\n /**\n * What a region says on hover: `tooltip` is what it would say, its name or\n * its series and its value, `data` the entry behind it; `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (tooltip: Tooltip3D, data: { entry: T }) => Tooltip3D | null\n}\n\n/** A region with an entry: its id in the land, the config key of its color, its value, the entry and, if the chart names entries, its name. */\ntype Region<T> = { rid: string; key: string; value: number; entry: T; name?: string }\n\n/** The fields of an entry: its region, its value and, if the chart has them, its series and its name. */\ntype Fields<T> = {\n id: keyof T & string\n value: keyof T & string\n series?: keyof T & string\n label?: keyof T & string\n}\n\n/**\n * The regions of the land on a globe, each in the color of its class. The\n * region an entry names is colored over the land, in the config color of\n * its series; one without an entry stays land. Nothing grows: a region fades\n * in with its entry, out without it, and one that changes series leaves as\n * one and enters as the other.\n */\nexport function ChoroplethChart3D<T extends Record<string, unknown>>({\n data,\n land,\n id,\n value,\n series,\n label,\n format,\n tooltip,\n}: ChoroplethChart3DProps<T>) {\n const { config, camera } = useChart3D()\n const largerFirst = useLargerFirst(land)\n const reading = { config, value, format, tooltip }\n const { regions, present } = useRegions(\n data,\n { id, value, series, label },\n Object.keys(config)[0]\n )\n const presence = useTween(present, 0)\n\n // A region under an opaque color is drawn once: its land ring is left out.\n const opaque = new Set(\n Object.entries(presence).flatMap(([pid, o]) =>\n o >= 1 ? [(JSON.parse(pid) as [string])[0]] : []\n )\n )\n const {\n marks: scenery,\n path,\n sink,\n } = earth(\n { features: land.features.filter((f) => f.id === undefined || !opaque.has(String(f.id))) },\n camera,\n geoOrthographic(),\n geoPath\n )\n // A feature without an id is never colored.\n const features = new Map(\n land.features.filter((f) => f.id !== undefined).map((f) => [String(f.id), f])\n )\n const painted = Object.entries(presence).sort(([a], [b]) => largerFirst(a, b))\n const overlays = painted.flatMap(([pid, opacity]) => {\n const [rid, key] = JSON.parse(pid) as [string, string]\n const feature = features.get(rid)\n // An entry naming a region the land has not draws nothing.\n if (!feature) return []\n // A region still fading out has no entry, so it says nothing.\n const region = regions.get(rid)\n const says = region?.key === key ? regionTooltip(region, reading) : undefined\n // Its group is the region alone, so hovering highlights every ring of it.\n return sink\n .marks(() => path(feature), `region-${rid}-${key}`, faded(colorOf(key), opacity))\n .map((mark) => ({ ...mark, groups: [rid], tooltip: says }))\n })\n\n return <Marks3D marks={[...scenery, ...overlays]} />\n}\n\n/**\n * Orders the presence ids of two regions, the larger region first, so a\n * region inside another - Lesotho in South Africa - is painted on top, where\n * the pointer finds it.\n */\nfunction useLargerFirst(land: GeoJSON.FeatureCollection) {\n const areas = React.useMemo(\n () => new Map(land.features.map((f) => [String(f.id), geoArea(f)])),\n [land]\n )\n const size = (pid: string) => areas.get((JSON.parse(pid) as [string])[0]) ?? 0\n return (a: string, b: string) => size(b) - size(a)\n}\n\n/**\n * What a region says on hover, made when the pointer lands on it: its name,\n * or the label of its series, over its value in the series color, labelled\n * by the field - or what `tooltip` makes of that.\n */\nfunction regionTooltip<T extends Record<string, unknown>>(\n { key, value, name, entry }: Region<T>,\n {\n config,\n value: field,\n format,\n tooltip = (tip) => tip,\n }: { config: ChartConfig } & Pick<ChoroplethChart3DProps<T>, \"value\" | \"format\" | \"tooltip\">\n): Mark3D[\"tooltip\"] {\n return () =>\n tooltip(\n {\n title: name ?? config[key]?.label ?? key,\n items: [{ label: field, value: format?.(value) ?? value, color: colorOf(key) }],\n },\n { entry }\n )\n}\n\n/**\n * The region of every entry and its presence - built once per change of the\n * data, not at every frame the camera turns. The presence is keyed by the\n * region and its series, so a region that changes color leaves as one and\n * enters as the other, each fading.\n */\nfunction useRegions<T extends Record<string, unknown>>(\n data: T[],\n fields: Fields<T>,\n fallback: string\n) {\n // The fields one by one: the record of them is new at every render.\n const { id, value, series, label } = fields\n return React.useMemo(() => {\n const regions = regionValues(data, { id, value, series, label }, fallback)\n return {\n regions,\n present: Object.fromEntries(\n [...regions.values()].map((r) => [JSON.stringify([r.rid, r.key]), 1])\n ),\n }\n }, [data, id, value, series, label, fallback])\n}\n\n/** The region of every entry - the last entry on a region wins - by the id it names. */\nfunction regionValues<T extends Record<string, unknown>>(\n data: T[],\n fields: Fields<T>,\n fallback: string\n) {\n const regions = new Map<string, Region<T>>()\n for (const d of data) {\n const rid = String(d[fields.id])\n regions.set(rid, {\n rid,\n key: fields.series ? String(d[fields.series]) : fallback,\n value: Number(d[fields.value]) || 0,\n entry: d,\n name: fields.label ? String(d[fields.label]) : undefined,\n })\n }\n return regions\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport {\n points3D,\n polygons3D,\n sort,\n type Camera3DInstance,\n type Point3D,\n type Polygon,\n} from \"d3-3d\"\nimport { geoOrthographic, geoPath } from \"d3-geo\"\n\nimport {\n GLOBE_RADIUS,\n Marks3D,\n axis,\n earth,\n faded,\n finite,\n nonNegative,\n globe,\n orthographic,\n shade,\n useChart3D,\n useTween,\n colorOf,\n type ChartConfig,\n type Mark3D,\n type Tooltip3D,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type GlobeChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per tile: the tile that holds an entry rises to its value, and the last entry on a tile wins. */\n data: T[]\n /**\n * The regions of the earth under the tiles, a GeoJSON feature collection,\n * cut at the horizon. d3-geo reads a region wound clockwise, the opposite\n * of RFC 7946: topojson-client's `feature` winds it so, and a region\n * wound the other way fills the globe around it.\n */\n land: GeoJSON.FeatureCollection\n /** The field of the longitude of an entry, in degrees east. */\n lon: keyof T & string\n /** The field of the latitude of an entry, in degrees north. */\n lat: keyof T & string\n /** The field of the value of an entry, the height of its tile; a value below 0, or one that is not a finite number, stands as 0. */\n value: keyof T & string\n /**\n * The field whose value is the config key of the color of a tile.\n * @defaultValue the first key of the chart config for every tile\n */\n series?: keyof T & string\n /**\n * The field that names an entry: the name of the last entry on a tile is\n * the title of its tooltip.\n * @defaultValue the label of the series\n */\n label?: keyof T & string\n /**\n * The width of a tile in degrees, a divisor of 180; one that is not\n * above 0 and up to 180 draws the default.\n * @defaultValue 5\n */\n step?: number\n /** Formats the value in the tooltip. */\n format?: (value: number) => React.ReactNode\n /**\n * What a tile says on hover: `tooltip` is what it would say, its name or\n * its series, its value and its center, `data` the entries on the tile;\n * `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (tooltip: Tooltip3D, data: { entries: T[] }) => Tooltip3D | null\n}\n\n/** The width of a tile in degrees, unless the chart says. */\nconst STEP = 5\n\n/** The height of a tile at the ceiling, in the world box. */\nconst HEIGHT = 0.4\n\n/** One face of a tile that rises: its corners, lifted, with the id of the tile it belongs to. */\ntype Face = Point3D[] & { id: string; part: \"top\" | `side${number}` }\n\n/** The fields of an entry: its place, its value and, if the chart has them, its series and its name. */\ntype Fields<T> = {\n lon: keyof T & string\n lat: keyof T & string\n value: keyof T & string\n series?: keyof T & string\n label?: keyof T & string\n}\n\n/** A tile with an entry: its id - center and config key - its value, its entries and, if the chart names entries, its name. */\ntype Tile<T> = { id: string; value: number; entries: T[]; name?: string }\n\n/** What the tooltip of a tile reads: the config, the fields, the format and what the reader makes of it. */\ntype Reading<T extends Record<string, unknown>> = {\n config: ChartConfig\n fields: Fields<T>\n} & Pick<GlobeChart3DProps<T>, \"format\" | \"tooltip\">\n\n/**\n * A globe of tiles between meridians and parallels, `step` degrees wide, on\n * the land. The tile that holds an entry rises from the globe to the entry's\n * value, in the color of its series; one without an entry is not drawn.\n */\nexport function GlobeChart3D<T extends Record<string, unknown>>({\n data,\n land,\n lon,\n lat,\n value,\n series,\n label,\n step: requested = STEP,\n format,\n tooltip,\n}: GlobeChart3DProps<T>) {\n const { config, camera } = useChart3D()\n // A step of 0 or below, NaN, Infinity or one wider than half the globe makes no tiles at all.\n const step = requested > 0 && requested <= 180 ? requested : STEP\n const fields = { lon, lat, value, series, label }\n const { tiles, target, present } = useTiles(data, fields, step, Object.keys(config)[0])\n // A tile grows from the globe as it fades in and shrinks back as it fades\n // out; the ceiling glides with the data, so the tallest tile never jumps.\n const heights = useTween(target, 0)\n const presence = useTween(present, 0)\n const peak = Object.values(target).reduce((max, v) => Math.max(max, v), 0)\n const { ceiling } = useTween({ ceiling: axis(0, peak).domain[1] })\n\n const eye = orthographic(camera)\n const ids = Object.keys(heights)\n const shapes = useShapes(ids, step)\n const tooltips = useTileTooltips(tiles, { config, fields, format, tooltip })\n const near = nearTiles(ids, shapes, step, eye)\n const prisms = polygons3D<Point3D>()\n .camera(eye)\n .data<Face>(prismFaces(near, shapes, heights, ceiling, eye.scale()))\n // Mirror tiles share a depth to the last bit, which the server and the\n // browser round differently: rounded, they tie, and the grid order paints\n // west before east on both, so the server HTML hydrates.\n .map((face) =>\n Object.assign(face, { centroid: { ...face.centroid, z: +face.centroid.z.toFixed(9) } })\n )\n .sort(sort)\n // The faces point outwards: the globe shows the ones facing the camera,\n // and hides what lies behind its center plane, as the ocean disc is drawn\n // first and a side of a far tile turned to the camera would show through.\n .filter((face) => face.ccw && face.centroid.z > 0)\n .map((face) =>\n prismMark(face, shapes.get(face.id)!.key, presence[face.id], tooltips.get(face.id))\n )\n\n const scenery = earth(land, camera, geoOrthographic(), geoPath).marks\n return <Marks3D marks={[...scenery, ...prisms]} />\n}\n\n/**\n * The tile of every entry, the value of each and its presence - built once\n * per change of the data, not at every frame the camera turns. A tile is\n * keyed by its place and its series, so a tile that changes color leaves as\n * one and enters as the other.\n */\nfunction useTiles<T extends Record<string, unknown>>(\n data: T[],\n fields: Fields<T>,\n step: number,\n fallback: string\n) {\n // The fields one by one: the record of them is new at every render.\n const { lon, lat, value, series, label } = fields\n return React.useMemo(() => {\n const tiles = tileValues(data, { lon, lat, value, series, label }, step, fallback)\n return {\n tiles,\n target: Object.fromEntries([...tiles.values()].map((t) => [t.id, t.value])),\n present: Object.fromEntries([...tiles.keys()].map((k) => [k, 1])),\n }\n }, [data, lon, lat, value, series, label, step, fallback])\n}\n\n/** Where a tile stands: the config key of its color, its center and its corners on the globe. */\ntype Shape = { key: string; center: Point3D; ground: Point3D[] }\n\n/**\n * The shape of every tile `ids` names, read from its id once and not at\n * every frame the camera turns - the gone ones too, while they shrink - and\n * forgotten with the tile, so the memory stays the size of the globe.\n */\nfunction useShapes(ids: string[], step: number) {\n const memory = React.useRef({ step, shapes: new Map<string, Shape>() })\n if (memory.current.step !== step) memory.current = { step, shapes: new Map() }\n const { shapes } = memory.current\n for (const id of ids) {\n if (shapes.has(id)) continue\n const { lon, lat, key } = tile(id)\n shapes.set(id, {\n key,\n center: globe(lon, lat, GLOBE_RADIUS),\n ground: corners(lon, lat, step, GLOBE_RADIUS),\n })\n }\n if (shapes.size > ids.length) {\n const live = new Set(ids)\n for (const id of shapes.keys()) if (!live.has(id)) shapes.delete(id)\n }\n return shapes\n}\n\n/**\n * What every tile says on hover, made once per change of the tiles or of\n * what reads them, not at every frame the camera turns; every face of a tile\n * shares it.\n */\nfunction useTileTooltips<T extends Record<string, unknown>>(\n tiles: Map<string, Tile<T>>,\n { config, fields, format, tooltip }: Reading<T>\n) {\n // The fields one by one: the record of them is new at every render.\n const { lon, lat, value, series, label } = fields\n return React.useMemo(() => {\n const reading = { config, fields: { lon, lat, value, series, label }, format, tooltip }\n return new Map([...tiles].map(([id, t]) => [id, tileTooltip(t, reading)]))\n }, [tiles, config, lon, lat, value, series, label, format, tooltip])\n}\n\n/**\n * The ids of the tiles whose center lies in front of the center plane of the\n * globe, or less than half a tile behind it: every face of any other tile is\n * behind the plane too, and projecting those only to cull them cost half the\n * frame.\n */\nfunction nearTiles(ids: string[], shapes: Map<string, Shape>, step: number, eye: Camera3DInstance) {\n // Half a tile in the world box - y points down, so the north is negative:\n // a corner lies at most this far in front of its center.\n const edge = -globe(0, step / 2, GLOBE_RADIUS).y\n const centers = ids.map((id) => ({ id, ...shapes.get(id)!.center }))\n return points3D<{ id: string } & Point3D>()\n .camera(eye)\n .data(centers)\n .filter((p) => p.rotated.z > -edge)\n .map((p) => p.id)\n}\n\n/**\n * The tile of every entry - the last entry on a tile wins - keyed by the\n * center of the tile and the config key of its color, with its value and, if\n * the chart names entries, the name of that last entry, and every entry on\n * the tile, gathered in one list: a copy per entry costs the square of them.\n */\nfunction tileValues<T extends Record<string, unknown>>(\n data: T[],\n fields: Fields<T>,\n step: number,\n fallback: string\n) {\n const tiles = new Map<string, Tile<T>>()\n for (const d of data) {\n // An entry without a place on the globe has no tile.\n if (!finite(d[fields.lon]) || !finite(d[fields.lat])) continue\n const [lon, lat] = [Number(d[fields.lon]), Number(d[fields.lat])]\n const center = `${snap(lon, -180, 180, step)},${snap(lat, -90, 90, step)}`\n const key = fields.series ? String(d[fields.series]) : fallback\n const entries = tiles.get(center)?.entries ?? []\n entries.push(d)\n tiles.set(center, {\n id: `${center},${key}`,\n value: nonNegative(d[fields.value]),\n entries,\n name: fields.label ? String(d[fields.label]) : undefined,\n })\n }\n return new Map([...tiles.values()].map((t) => [t.id, t]))\n}\n\n/** The center of the tile between `lo` and `hi` that holds `v`; the last tile holds the far edge and beyond. */\nfunction snap(v: number, lo: number, hi: number, step: number) {\n const index = Math.min(Math.max(0, Math.floor((v - lo) / step)), Math.round((hi - lo) / step) - 1)\n return lo + (index + 0.5) * step\n}\n\n/** The center and the config key of a tile that rises, read back from its id. */\nfunction tile(id: string) {\n const [lon, lat, ...key] = id.split(\",\")\n return { lon: Number(lon), lat: Number(lat), key: key.join(\",\") }\n}\n\n/**\n * The faces of the tiles `ids` - the top of each and, where the tile is a\n * pixel tall on screen, its four sides - the gone ones still shrinking among\n * them. A side thinner than a pixel draws nothing, and on a globe of\n * thousands of flat tiles the sides are most of the faces, so leaving them\n * out turns it about twice as fast.\n */\nfunction prismFaces(\n ids: string[],\n shapes: Map<string, Shape>,\n heights: Record<string, number>,\n ceiling: number,\n scale: number\n): Face[] {\n return ids.flatMap((id) => {\n const bottom = shapes.get(id)!.ground\n const lift = (heights[id] / ceiling) * HEIGHT\n // A point on the globe scales with its radius: the top is the ground, lifted.\n const lifted = (GLOBE_RADIUS + lift) / GLOBE_RADIUS\n const top = Object.assign(\n bottom.map((p) => ({ x: p.x * lifted, y: p.y * lifted, z: p.z * lifted })),\n { id, part: \"top\" as const }\n )\n if (lift * scale < 1) return [top]\n return [\n top,\n ...bottom.map((b, i) => {\n const j = (i + 1) % 4\n return Object.assign([b, bottom[j], top[j], top[i]], { id, part: `side${i}` as const })\n }),\n ]\n })\n}\n\n/** The corners of the tile around `lon` and `lat` at `radius`, wound to face outwards. */\nfunction corners(lon: number, lat: number, step: number, radius: number): Point3D[] {\n const [w, e, s, n] = [lon - step / 2, lon + step / 2, lat - step / 2, lat + step / 2]\n return [globe(w, s, radius), globe(e, s, radius), globe(e, n, radius), globe(w, n, radius)]\n}\n\n/**\n * What a tile says on hover, made when the pointer lands on one of its\n * faces: its name, or the label of its series, over its value in the series\n * color and the center of the tile, labelled by the fields - or what\n * `tooltip` makes of that. A tile whose entries have left the data says\n * nothing.\n */\nfunction tileTooltip<T extends Record<string, unknown>>(\n { id, value, name, entries }: Tile<T>,\n { config, fields, format, tooltip = (tip) => tip }: Reading<T>\n): Mark3D[\"tooltip\"] {\n return () => {\n const { lon, lat, key } = tile(id)\n return tooltip(\n {\n title: name ?? config[key]?.label ?? key,\n items: [\n { label: fields.value, value: format?.(value) ?? value, color: colorOf(key) },\n { label: fields.lat, value: lat },\n { label: fields.lon, value: lon },\n ],\n },\n { entries }\n )\n }\n}\n\n/**\n * The mark of one face of a tile that rises: shaded in the color of its\n * series and faded to its presence. Its group is the tile alone, so hovering\n * highlights one tile, not its series.\n */\nfunction prismMark(\n face: Polygon<Point3D, Face>,\n key: string,\n presence: number,\n tooltip: Mark3D[\"tooltip\"]\n) {\n return {\n key: `${face.id}-${face.part}`,\n points: face.map((p) => p.projected),\n fill: faded(shade(face, colorOf(key)), presence),\n groups: [face.id],\n tooltip,\n }\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { points3D, sort, type Point3D, type TransformedPoint } from \"d3-3d\"\nimport { geoOrthographic, geoPath } from \"d3-geo\"\n\nimport {\n GLOBE_RADIUS,\n Marks3D,\n earth,\n faded,\n finite,\n nonNegative,\n globe,\n orthographic,\n useChart3D,\n useTween,\n colorOf,\n type ChartConfig,\n type Mark3D,\n type Tooltip3D,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type PlacesChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per place: a dot on the globe. */\n data: T[]\n /**\n * The regions of the earth under the dots, a GeoJSON feature collection,\n * cut at the horizon. d3-geo reads a region wound clockwise, the opposite\n * of RFC 7946: topojson-client's `feature` winds it so, and a region\n * wound the other way fills the globe around it.\n */\n land: GeoJSON.FeatureCollection\n /** The field of the longitude of an entry, in degrees east. */\n lon: keyof T & string\n /** The field of the latitude of an entry, in degrees north. */\n lat: keyof T & string\n /**\n * The field of the value of an entry: the area of its dot, relative to the\n * largest; a value below 0, or one that is not a finite number, stands as 0.\n * @defaultValue every dot the same size\n */\n value?: keyof T & string\n /**\n * The field whose value is the config key of the color of a dot.\n * @defaultValue the first key of the chart config for every dot\n */\n series?: keyof T & string\n /**\n * The field that names an entry: the title of its tooltip, and its identity\n * through updates, so a new dot grows, a gone one shrinks away and one that\n * moves glides. The names should be unique.\n * @defaultValue the place of the entry\n */\n id?: keyof T & string\n /**\n * The radius of the largest dot - of every dot, without `value` - in the\n * units of the view box.\n * @defaultValue 6\n */\n radius?: number\n /** Formats the value in the tooltip. */\n format?: (value: number) => React.ReactNode\n /**\n * What a dot says on hover: `tooltip` is what it would say, its name or\n * its series, its value and its place, `data` the entry behind it; `null`\n * shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (tooltip: Tooltip3D, data: { entry: T }) => Tooltip3D | null\n}\n\n/** A dot by name, on the sphere, before the camera projects it. */\ntype Dot = Point3D & { name: string }\n\n/** Where a dot is and which config key colors it, remembered while it leaves. */\ntype Place = { lon: number; lat: number; key: string }\n\n/** The fields of an entry: its place and, if the chart has them, its value, its series and its name. */\ntype Fields<T> = {\n lon: keyof T & string\n lat: keyof T & string\n value?: keyof T & string\n series?: keyof T & string\n id?: keyof T & string\n}\n\n/** What a dot reads for its mark: the config, the fields, the largest radius, the format and what the reader makes of its tooltip. */\ntype Reading<T extends Record<string, unknown>> = {\n config: ChartConfig\n fields: Fields<T>\n radius: number\n} & Pick<PlacesChart3DProps<T>, \"format\" | \"tooltip\">\n\n/**\n * Dots on the land of a globe, one per place, its area its value. A dot on\n * the far side is hidden by the globe.\n */\nexport function PlacesChart3D<T extends Record<string, unknown>>({\n data,\n land,\n lon,\n lat,\n value,\n series,\n id,\n radius = 6,\n format,\n tooltip,\n}: PlacesChart3DProps<T>) {\n const { config, camera } = useChart3D()\n const fields = { lon, lat, value, series, id }\n const { entries, names, target, present } = useDots(data, fields)\n const sizes = useTween(target, 0)\n const opacity = useTween(present, 0)\n const { peak } = useTween({ peak: Math.max(0, ...Object.values(target)) })\n const place = usePlaces(names, entries, fields, Object.keys(config)[0], sizes)\n\n const reading = { config, fields, radius, format, tooltip }\n const behind = new Map(entries.map((d, i) => [names[i], d]))\n const dots = points3D<Dot>()\n .camera(orthographic(camera))\n .x((p) => p.x)\n .y((p) => p.y)\n .z((p) => p.z)\n .data(\n Object.keys(sizes).map((name) => {\n const { lon, lat } = place(name)\n return { name, ...globe(lon, lat, GLOBE_RADIUS) }\n })\n )\n // A dot on the far side is hidden by the globe.\n .filter((p) => p.rotated.z > 0)\n .sort(sort)\n .map((p) =>\n dotMark(\n p,\n place(p.name),\n sizes[p.name] / (peak || 1),\n behind.get(p.name),\n opacity[p.name],\n reading\n )\n )\n\n const scenery = earth(land, camera, geoOrthographic(), geoPath).marks\n return <Marks3D marks={[...scenery, ...dots]} />\n}\n\n/**\n * The entries with a place on the globe, the name of each, their values and\n * their presence - built once per change of the data, not at every frame the\n * camera turns.\n */\nfunction useDots<T extends Record<string, unknown>>(data: T[], fields: Fields<T>) {\n const { lon, lat, value, id } = fields\n return React.useMemo(() => {\n // An entry without a place on the globe has no dot.\n const entries = data.filter((d) => finite(d[lon]) && finite(d[lat]))\n const names = entries.map((d) => (id ? String(d[id]) : `${Number(d[lon])},${Number(d[lat])}`))\n return {\n entries,\n names,\n // The area of a dot is its value, from 0, so a new one grows as it fades\n // in and a gone one shrinks as it fades out; the peak glides along, so no\n // dot jumps when the largest leaves.\n target: Object.fromEntries(\n entries.map((d, i) => [names[i], value ? nonNegative(d[value]) : 1])\n ),\n present: Object.fromEntries(names.map((name) => [name, 1])),\n }\n }, [data, lon, lat, value, id])\n}\n\n/**\n * The mark of one dot: a circle whose area is its share of the peak, in the\n * color of its series, faded to its presence and ringed by the background so\n * that dots in front stand out. Its group is the dot alone, so hovering\n * highlights that dot only.\n */\nfunction dotMark<T extends Record<string, unknown>>(\n p: TransformedPoint<Dot>,\n place: Place,\n share: number,\n entry: T | undefined,\n presence: number,\n reading: Reading<T>\n) {\n return {\n key: p.name,\n points: [p.projected],\n r: reading.radius * Math.sqrt(share),\n fill: faded(colorOf(place.key), presence),\n stroke: faded(\"var(--background)\", presence),\n groups: [p.name],\n tooltip: dotTooltip(p.name, place, entry, reading),\n }\n}\n\n/**\n * What a dot says on hover, made when the pointer lands on it - thousands of\n * dots, one tooltip: its name, or its series, over its value and its place,\n * labelled by the fields - or what `tooltip` makes of that. A dot whose\n * entry has left the data says nothing.\n */\nfunction dotTooltip<T extends Record<string, unknown>>(\n name: string,\n { lon, lat, key }: Place,\n entry: T | undefined,\n { config, fields, format, tooltip = (tip) => tip }: Reading<T>\n): Mark3D[\"tooltip\"] {\n if (!entry) return undefined\n const value = fields.value ? nonNegative(entry[fields.value]) : 0\n return () =>\n tooltip(\n {\n title: fields.id ? name : (config[key]?.label ?? key),\n items: [\n ...(fields.value\n ? [\n {\n label: fields.value,\n value: format?.(value) ?? value,\n color: colorOf(key),\n },\n ]\n : []),\n { label: fields.lat, value: lat },\n { label: fields.lon, value: lon },\n ],\n },\n { entry }\n )\n}\n\n/**\n * The place and the config key of every dot, by name - remembered while a\n * gone dot shrinks away, since its entry has already left the data - and\n * forgotten with the dot, so the memory stays the size of the chart.\n */\nfunction usePlaces<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n fields: Fields<T>,\n fallback: string,\n alive: Record<string, number>\n) {\n const known = React.useRef(new Map<string, Place>())\n data.forEach((d, i) =>\n known.current.set(names[i], {\n lon: Number(d[fields.lon]),\n lat: Number(d[fields.lat]),\n key: fields.series ? String(d[fields.series]) : fallback,\n })\n )\n const live = new Set(names)\n for (const name of known.current.keys()) {\n if (!(name in alive) && !live.has(name)) known.current.delete(name)\n }\n return (name: string) => known.current.get(name)!\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport { points3D, sort, type AxesSpec, type Point3D } from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n faded,\n finite,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n colorOf,\n type ChartConfig,\n type Mark3D,\n type Tooltip3D,\n type World,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type ScatterChart3DProps<T extends Record<string, unknown> = Record<string, unknown>> = {\n /** One entry per point; one whose x, y or z is missing or not a number has none. */\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 that names an entry, so a point follows its name through\n * updates: a new one grows, a gone one shrinks away, one that moves glides.\n * The names should be unique.\n * @defaultValue the position of the entry\n */\n id?: 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 * What a point says on hover: `tooltip` is what it would say, its series\n * and its x, y and z as the ticks name them, `data` the entry behind it;\n * `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (tooltip: Tooltip3D, data: { entry: T }) => Tooltip3D | null\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: all,\n x,\n y,\n z,\n id,\n series,\n radius = 4,\n format,\n titles,\n tooltip,\n}: ScatterChart3DProps<T>) {\n const { config, camera } = useChart3D()\n const { fields, data, names, entries, values, axes } = usePoints(all, x, y, z, id)\n const { radii, opacity, read, key } = usePointTweens(names, data, values, series, config, radius)\n\n // The axes of the data the chart glides into; their ends glide along.\n const spec = useTweenAxes(axes)\n const world = worldBox(spec)\n const placed = usePointPlaces(names, radii, read, world)\n\n const points = points3D<{ name: string } & Point3D>()\n .camera(camera)\n .x((p) => p.x)\n .y((p) => p.y)\n .z((p) => p.z)\n\n const marks = points\n .data(placed)\n .sort(sort)\n .map((p) => ({\n key: p.name,\n points: [p.projected],\n r: radii[p.name],\n fill: faded(colorOf(key(p.name)), opacity[p.name]),\n // Its group is the point alone, so hovering highlights that point only.\n groups: [p.name],\n // Ringed by the background, so that points in front stand out.\n stroke: faded(\"var(--background)\", opacity[p.name]),\n tooltip: pointTooltip(\n entries.get(p.name),\n series ? (config[key(p.name)]?.label ?? key(p.name)) : undefined,\n fields,\n { format, titles, tooltip }\n ),\n }))\n\n return (\n <>\n <Axes3D spec={spec} world={world} format={format} titles={titles} />\n <Marks3D marks={marks} />\n </>\n )\n}\n\n/**\n * What a point says on hover, made when the pointer lands on it: its series,\n * where `title` names one, and its x, y and z as the ticks of each axis name\n * them - or what `tooltip` makes of that. A point whose entry has left the\n * data says nothing.\n */\nfunction pointTooltip<T extends Record<string, unknown>>(\n entry: T | undefined,\n title: React.ReactNode,\n fields: Record<keyof AxesSpec, keyof T & string>,\n {\n format = {},\n titles = {},\n tooltip = (tip) => tip,\n }: Pick<ScatterChart3DProps<T>, \"format\" | \"titles\" | \"tooltip\">\n): Mark3D[\"tooltip\"] {\n if (!entry) return undefined\n return () =>\n tooltip(\n {\n title,\n items: ([\"x\", \"y\", \"z\"] as const).map((a) => {\n const value = Number(entry[fields[a]])\n return { label: titles[a] ?? fields[a], value: format[a]?.(value) ?? value }\n }),\n },\n { entry }\n )\n}\n\n/**\n * The entries with a place in the box, their names, the entry behind each\n * name, their positions and the axes that hold them - built once per change\n * of the data, not at every frame the camera turns.\n */\nfunction usePoints<T extends Record<string, unknown>>(\n all: T[],\n x: keyof T & string,\n y: keyof T & string,\n z: keyof T & string,\n id: (keyof T & string) | undefined\n) {\n return React.useMemo(() => {\n const fields = { x, y, z }\n // An entry without a place in the box has no point.\n // Named by its position in all the data, so a point keeps its name when an\n // entry before it gains or loses its place.\n const placed = all.flatMap((d, i) =>\n [x, y, z].every((f) => finite(d[f])) ? [{ d, name: id ? String(d[id]) : String(i) }] : []\n )\n const data = placed.map((p) => p.d)\n const names = placed.map((p) => p.name)\n return {\n fields,\n data,\n names,\n entries: new Map(names.map((name, i) => [name, data[i]])),\n values: pointValues(names, data, fields),\n axes: pointAxes(data, fields),\n }\n }, [all, x, y, z, id])\n}\n\n/** The axes that hold every entry of `data`, a nice one per field. */\nfunction pointAxes<T extends Record<string, unknown>>(\n data: T[],\n fields: Record<keyof AxesSpec, keyof T & string>\n): AxesSpec {\n const range = (a: keyof AxesSpec) => {\n const [lo = 0, hi = 0] = extent(data, (d) => Number(d[fields[a]]))\n return axis(lo, hi)\n }\n return { x: range(\"x\"), y: range(\"y\"), z: range(\"z\") }\n}\n\n/**\n * The tweened numbers of the chart, by the name of each entry: the positions\n * glide entry by entry - a gone point stands in place - and the radius and\n * the opacity enter from 0, so a new point grows as it fades in and a gone\n * one shrinks as it fades away. `read` and `key` look them up, also for a\n * point still leaving.\n */\nfunction usePointTweens<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n target: Record<string, number>,\n series: (keyof T & string) | undefined,\n config: ChartConfig,\n radius: number\n) {\n const values = useTween(target)\n const sizes = React.useMemo(\n () => Object.fromEntries(names.map((name) => [name, radius])),\n [names, radius]\n )\n const radii = useTween(sizes, 0)\n const present = React.useMemo(() => Object.fromEntries(names.map((name) => [name, 1])), [names])\n const opacity = useTween(present, 0)\n const fallback = Object.keys(config)[0]\n return {\n radii,\n opacity,\n read: (name: string, axis: keyof AxesSpec) => values[`${axis}${name}`],\n key: usePointKeys(names, data, series, fallback, radii),\n }\n}\n\n/**\n * The place of every point in the world box, by name. A living point follows\n * its gliding numbers through the gliding axes; a gone one stays frozen where\n * it was, so it shrinks away in place instead of riding the rescaling axes\n * out of the box. A point only one of the tweens still knows stays unseen.\n */\nfunction usePointPlaces(\n names: string[],\n alive: Record<string, number>,\n read: (name: string, axis: keyof AxesSpec) => number,\n world: World\n) {\n const places = React.useRef(new Map<string, Point3D>())\n const live = new Set(names)\n const placed = Object.keys(alive).flatMap((name) => {\n if (!live.has(name)) {\n const held = places.current.get(name)\n return held ? [{ name, ...held }] : []\n }\n const p = {\n x: world.x(read(name, \"x\")),\n y: world.y(read(name, \"y\")),\n z: world.z(read(name, \"z\")),\n }\n places.current.set(name, p)\n return [{ name, ...p }]\n })\n // Forgotten with the point, so the memory stays the size of the chart.\n for (const name of places.current.keys()) if (!(name in alive)) places.current.delete(name)\n return placed\n}\n\n/** The position of every entry, keyed by its axis and name, gliding into new data. */\nfunction pointValues<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n fields: Record<keyof AxesSpec, keyof T & string>\n) {\n return Object.fromEntries(\n data.flatMap((d, i) =>\n ([\"x\", \"y\", \"z\"] as const).map((a) => [`${a}${names[i]}`, Number(d[fields[a]])])\n )\n )\n}\n\n/**\n * The config key of every point's color, by name - remembered while a gone\n * point shrinks away, since its entry has already left the data - and\n * forgotten with the point, so the memory stays the size of the chart.\n */\nfunction usePointKeys<T extends Record<string, unknown>>(\n names: string[],\n data: T[],\n series: (keyof T & string) | undefined,\n fallback: string,\n alive: Record<string, number>\n) {\n const known = React.useRef(new Map<string, string>())\n data.forEach((d, i) => known.current.set(names[i], series ? String(d[series]) : fallback))\n for (const name of known.current.keys()) {\n if (!(name in alive) && !names.includes(name)) known.current.delete(name)\n }\n return (name: string) => known.current.get(name) ?? fallback\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { extent } from \"d3-array\"\nimport {\n gridPlanes3D,\n sort,\n type AxesSpec,\n type GridPlane,\n type GridPlanes3DInstance,\n type Point3D,\n} from \"d3-3d\"\n\nimport {\n Axes3D,\n Marks3D,\n axis,\n gridAxis,\n intoWorld,\n shade,\n useChart3D,\n useTween,\n useTweenAxes,\n worldBox,\n finite,\n ramp,\n type Mark3D,\n type Tooltip3D,\n} from \"@/registry/new-york/ui/chart-3d\"\n\nexport type SurfaceChart3DProps = {\n /** The heights on the grid, `data[row][column]`; one that is not a finite number stands at the lowest of the others. */\n data: number[][]\n /**\n * The data values the first and the last column (x) and row (z) stand for,\n * the others evenly between. The chart keeps half a cell between the grid\n * and the walls of its box; a domain given here names the box exactly,\n * without that room.\n * @defaultValue the indices of the columns and rows\n */\n domain?: { x?: [number, number]; z?: [number, number] }\n /**\n * The value every column stands at along x, `x[column]`, at any spacing,\n * in place of `domain.x`; the box spans them exactly. The surface joins\n * the columns in the order of the data: give them ascending, or it folds\n * back over itself. A column without a finite value drops out, its\n * neighbours joined.\n * @defaultValue evenly over `domain.x`\n */\n x?: number[]\n /**\n * The value every row stands at along z, `z[row]`, as `x` does for the\n * columns.\n * @defaultValue evenly over `domain.z`\n */\n z?: 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 * What a cell says on hover: `tooltip` is what it would say, its height as\n * the ticks of y name it, `data` the row and column the cell starts at and\n * its height, the mean of its four corners; `null` shows none.\n * @defaultValue (tooltip) => tooltip\n */\n tooltip?: (\n tooltip: Tooltip3D,\n data: { row: number; column: number; value: number }\n ) => Tooltip3D | null\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({\n data: raw,\n domain = {},\n x,\n z,\n colors,\n format,\n titles,\n tooltip,\n}: SurfaceChart3DProps) {\n const { config, camera } = useChart3D()\n const [low, high = low] = colors ?? Object.keys(config)\n const { floor, peak, target, present, ...sides } = useGrid(raw, { domain, x, z })\n // The heights glide cell by cell, so the surface, its color ramp and the y\n // axis follow. Coming and going is a fade in place - a new border cell\n // fades in where it belongs, a gone one fades out where it stands and\n // leaves when the glide is done - so the surface never moves where data\n // merely appears or disappears.\n const heights = useTween(target)\n const fade = useTween(present, 0)\n // Every column and row glides to its place.\n const placesX = useTween(sides.x.places)\n const placesZ = useTween(sides.z.places)\n // Everything of a cell but its shade waits for the data to move, not the camera.\n const { lattice, points } = React.useMemo(() => {\n const lattice = gridLattice(heights, { x: placesX, z: placesZ }, floor)\n const cells = { raw, present, keys: [low, high] as [string, string], format, titles, tooltip }\n return { lattice, points: gridPoints(lattice, { x: placesX, z: placesZ }, cells) }\n }, [heights, placesX, placesZ, floor, raw, present, low, high, format, titles, tooltip])\n const spec = useTweenAxes({ x: sides.x.spec, y: axis(floor, peak), z: sides.z.spec })\n const world = worldBox(spec)\n\n const grid = intoWorld<GridPoint, GridPlanes3DInstance<GridPoint>>(\n gridPlanes3D<GridPoint>().camera(camera),\n world\n )\n // d3-3d reads rows(0) as the getter; a grid without columns has no points anyway.\n .rows(Math.max(1, lattice[0]?.length ?? 0))\n const marks = grid\n .data(points)\n .sort(sort)\n .map((quad) => quadMark(quad, fade))\n\n return (\n <>\n <Axes3D spec={spec} world={world} format={format} titles={titles} />\n <Marks3D marks={marks} />\n </>\n )\n}\n\n/**\n * A point of the lattice, carrying the row and column it stands for, its key\n * and, where a cell starts at it, the key, color and tooltip of that cell.\n */\ntype GridPoint = Point3D & {\n r: number\n c: number\n key: string\n cell?: { key: string; color: string; tooltip: Mark3D[\"tooltip\"] }\n}\n\n/** What the cells of the lattice are colored and named by. */\ntype Cells = Pick<SurfaceChart3DProps, \"format\" | \"titles\" | \"tooltip\"> & {\n raw: number[][]\n present: Record<string, number>\n keys: [string, string]\n}\n\n/**\n * The points of the lattice at their places, each cell on the point it\n * starts at - its lowest row and column - with its color on the ramp at its\n * height, the mean of its corners, and its tooltip.\n */\nfunction gridPoints(\n lattice: { r: number; c: number; y: number }[][],\n places: Record<\"x\" | \"z\", Record<string, number>>,\n { raw, present, keys, ...say }: Cells\n): GridPoint[] {\n const [lo = 0, hi = 0] = extent(lattice.flat(), (p) => p.y)\n return lattice.flatMap((row, i) =>\n row.map(({ r, c, y }, j) => {\n const point: GridPoint = { x: places.x[c], y, z: places.z[r], r, c, key: `${r}-${c}` }\n const corners = [row[j + 1], lattice[i + 1]?.[j], lattice[i + 1]?.[j + 1]]\n if (corners.every(Boolean)) {\n const quad = [{ r, c, y }, ...corners] as { r: number; c: number; y: number }[]\n const height = quad.reduce((sum, p) => sum + p.y, 0) / quad.length\n point.cell = {\n key: point.key,\n color: ramp(height, [lo, hi], keys),\n tooltip: cellTooltip(quad, raw, present, say),\n }\n }\n return point\n })\n )\n}\n\n/**\n * What a cell says on hover, made when the pointer lands on it: its height,\n * the mean of its four corners in the data, as the ticks of y name it - or\n * what `tooltip` makes of that. A cell on its way out of the data - its\n * height or its place - says nothing, and so does one with a height that is no number, where the\n * stand-in at the floor would make a value up.\n */\nfunction cellTooltip(\n quad: { r: number; c: number }[],\n data: number[][],\n present: Record<string, number>,\n {\n format = {},\n titles = {},\n tooltip = (tip) => tip,\n }: Pick<SurfaceChart3DProps, \"format\" | \"titles\" | \"tooltip\">\n): Mark3D[\"tooltip\"] {\n if (quad.some((p) => !(`${p.r}-${p.c}` in present) || !finite(data[p.r][p.c]))) return undefined\n return () => {\n const value = quad.reduce((sum, p) => sum + data[p.r][p.c], 0) / quad.length\n const row = Math.min(...quad.map((p) => p.r))\n const column = Math.min(...quad.map((p) => p.c))\n return tooltip(\n { items: [{ label: titles.y ?? \"value\", value: format.y?.(value) ?? value }] },\n { row, column, value }\n )\n }\n}\n\n/**\n * The mark of one cell: its quad, shaded in the color of its cell and faded\n * in place by `fade` while the cell enters or leaves. It is named by the row\n * and column it starts at, as d3-3d numbers its quads anew as the grid grows.\n */\nfunction quadMark(quad: GridPlane<GridPoint>, fade: Record<string, number>): Mark3D {\n let start = quad[0]\n let seen = 1\n for (const p of quad) {\n if (p.r <= start.r && p.c <= start.c) start = p\n // A corner only one of the tweens still knows is on its way out and stays unseen.\n seen = Math.min(seen, fade[p.key] ?? 0)\n }\n // The point a cell starts at carries it: every quad of the lattice has one.\n const { key, color, tooltip } = start.cell!\n const shaded = shade(quad, color)\n return {\n key,\n points: quad.map((p) => p.projected),\n fill:\n seen < 1 ? `color-mix(in srgb, ${shaded} ${Math.round(seen * 100)}%, transparent)` : shaded,\n // Its group is the cell, so hovering it lights the cell alone.\n groups: [key],\n tooltip,\n }\n}\n\n/**\n * The grid with every height a number, its lowest and highest height, the\n * height of every cell and its presence, and the places of its columns and\n * rows - built once per change of the data, not at every frame the camera\n * turns. A column or row without a place drops out of all of them.\n */\nfunction useGrid(\n raw: number[][],\n {\n domain,\n x,\n z,\n }: Pick<SurfaceChart3DProps, \"x\" | \"z\"> & {\n domain: NonNullable<SurfaceChart3DProps[\"domain\"]>\n }\n) {\n return React.useMemo(() => {\n // Named places span the box exactly; the indices keep half a cell of room.\n const sides = {\n x: gridAxis(Math.max(0, ...raw.map((row) => row.length)), {\n at: x,\n ends: domain.x,\n padded: !(x || domain.x),\n }),\n z: gridAxis(raw.length, { at: z, ends: domain.z, padded: !(z || domain.z) }),\n }\n const placed = raw.map((row, r) =>\n r in sides.z.places ? row.map((y, c) => (c in sides.x.places ? y : NaN)) : []\n )\n const grid = cleanGrid(placed)\n const target = gridValues(grid.data, sides)\n return {\n ...grid,\n ...sides,\n target,\n present: Object.fromEntries(Object.keys(target).map((k) => [k, 1])),\n }\n }, [raw, x, z, domain.x, domain.z])\n}\n\n/**\n * The grid with every height a number: one that is not - NaN, Infinity -\n * stands at the lowest of the others, so one cell cannot blank the surface.\n * With the lowest and the highest height, 0 for a grid without one.\n */\nfunction cleanGrid(raw: number[][]) {\n const [floor = 0, peak = 0] = extent(raw.flat().filter(finite))\n const data = raw.map((row) => row.map((y) => (finite(y) ? y : floor)))\n return { data, floor, peak }\n}\n\n/** The height of every cell with a place, keyed by its row and column, gliding into new data. */\nfunction gridValues(\n data: number[][],\n sides: Record<\"x\" | \"z\", { places: Record<number, number> }>\n) {\n return Object.fromEntries(\n data.flatMap((row, r) =>\n row.flatMap((y, c) => (c in sides.x.places && r in sides.z.places ? [[`${r}-${c}`, y]] : []))\n )\n )\n}\n\n/**\n * The gliding heights as a lattice over the rows and columns they name. It\n * spans the cells still leaving too, so a shrunken grid sinks away instead\n * of popping; a corner only one dimension kept stands at the floor until it\n * goes. A column or row without a place is no line of it: new heights\n * glide a leaving one on while its place, and its fade, are gone.\n */\nfunction gridLattice(\n tweened: Record<string, number>,\n places: Record<\"x\" | \"z\", Record<string, number>>,\n floor: number\n) {\n const rows = new Set<number>()\n const columns = new Set<number>()\n for (const key of Object.keys(tweened)) {\n const [r, c] = key.split(\"-\").map(Number)\n if (r in places.z) rows.add(r)\n if (c in places.x) columns.add(c)\n }\n const ascending = (set: Set<number>) => [...set].sort((a, b) => a - b)\n return ascending(rows).map((r) =>\n ascending(columns).map((c) => ({ r, c, y: tweened[`${r}-${c}`] ?? floor }))\n )\n}\n"],"mappings":"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"}
|