@trokster/l-cursor
v0.0.2
Published
Infinite-zoom radial fractal visualization for Svelte 5: one generic engine with referential rebasing, level-of-detail, and live HTML portals.
Maintainers
Readme
Infinite Zoom
A semantic-zoom visualization library: one generic engine driving a radial
fractal you can fall into forever. As you zoom in, the camera re-bases its
referential (see THEORY.md) so the scale number never escapes a
~3-decade band and floating-point precision never rots. Off-screen and sub-pixel
nodes are never drawn — render cost is O(visible), independent of tree size.
Demo (npm run dev)
/zoom/radial — children ring inside each node; click to dive, wheel/pinch to
zoom, drag to pan, zoom out to rise. Each node carries a live HTML portal (a
real component sized in screen pixels) that swaps detail as you approach.
Architecture
core/engine.js— generic engine: bounded-scale camera, referential rebasing (the infinite-zoom trick), level-of-detail with ghost child previews, sibling context, and viewport culling. Display-agnostic.core/{camera,rebase,interaction,tree}.js— affine camera, the pixel-exact rebase math, pointer/pinch/wheel + inertia, shared tree indexing.layouts/radial.js—layout(index, rootId, opts)returning{ nodes, order }. The engine is generic over any self-similar, child-contained layout; radial is the one shipped here.viz/ZoomScene.svelte— the renderer: world-static SVG under a single animated transform, spring fly-to navigation, breadcrumbs, enter-fades, and resolution-adaptive HTML portals (live components inside each node's core).
import { ZoomScene, indexTree, radialLayout } from '@trokster/l-cursor';
// <ZoomScene index={indexTree(data)} layout={radialLayout} nodeStyle="rings" />The math (rebase derivation, LOD, culling, self-similarity) lives in
THEORY.md. A copy-paste integration guide for LLMs/agents is in
LLM.md. Both ship in the npm tarball.
Integration notes (custom layouts / renderers)
- Layout grammar (THEORY.md §7.1): the
0.5Rcore belongs to the portal; children live in the annulus outside it, fully inside the parent, and small (reference: ring0.75R, child ≤0.15R). The engine doesn't enforce this — setconfig.validate: true(or call the exportedvalidateLayout) in dev to catch violations loudly instead of shipping a subtly broken scene. - Portal sizing: portals must stay inside
0.5R; the inscribed square's side is0.5·√2·ext ≈ 0.707·extof the node's on-screen half-extent. - No
svelte/storeimport:camera.stateimplements the store contract locally, so environments that externalizesvelte/*through an import map need no extra mapping.
Develop
npm install
npm run dev # SvelteKit playground at /zoom/radial
npm run test:unit -- --run # Vitest (engine + component, headless)
npm run lint # Prettier + ESLint
npm run build # package the library to dist/ (svelte-package + publint)The package is Svelte 5 (runes) and SVG-only — no canvas, WebGL, or runtime
dependencies. import from @trokster/l-cursor in any SvelteKit/Vite project.
