@field-ui/vanilla
v0.3.1
Published
Framework-free TypeScript wrapper for field-ui — the reciprocal DOM-physics field as a typed FieldField class + mountField(), with no custom-element registration and no framework dependency.
Downloads
436
Maintainers
Readme
@field-ui/vanilla
The framework-free door to @field-ui/core — a reciprocal DOM-physics field as a typed
FieldField class and the imperative mountField(). Elements you mark with data-body become forces;
the single background field reacts to them, and its density reacts back. No custom-element
registration, no framework dependency, no import side effects.
→ Live manual, Lab, and gallery at field-ui.com.
Install
npm i @field-ui/vanillaThe only dependency is the zero-dependency core plus @field-ui/platform (which supplies
the browser host). Reach for this from plain TypeScript, or any stack where you want to drive the field
by hand.
The class
import { FieldField } from '@field-ui/vanilla';
const field = new FieldField({ accent: '#4da3ff', render: 'dots' });
field.setFormation('wells');
field.burst(window.innerWidth / 2, 200);
// field.scan(); // re-pick-up bodies after a DOM change
// field.destroy(); // stop the loop and remove the managed canvasnew FieldField() builds a fixed, full-viewport canvas behind your page and starts the engine on it.
It takes every FieldOptions value, implements the full FieldHandle surface, and exposes the
canvas it runs on — the same engine the <field-root> custom element and the React <FieldField>
wrap.
Options (FieldOptions)
| Option | Type | Effect |
|---|---|---|
| accent | string | base hue (any CSS color) |
| density | number | particle density multiplier |
| render | 'dots' \| 'trails' \| 'links' \| 'metaballs' \| 'voronoi' \| 'streamlines' | underlay render method |
| palette | string \| string[] | named palette (ours / heatmap / infrared / spectrum) or colors |
| waves | boolean | wave propagation |
| mass | boolean | first-class mass in the integrator |
| attention · causality · heatmap | boolean | diagnostics |
| canvas | HTMLCanvasElement | drive a canvas you own (the field won't create/remove one) |
Methods (FieldHandle)
| Method | Use |
|---|---|
| scan() / rescan() | re-read [data-body] elements after the DOM changes |
| setAccent(hex) · setPalette(p) | recolor live |
| setFormation(name) | arrange particles into a named formation |
| setRender(mode) · setOverlay(mode) | underlay (behind content) / overlay (in front) |
| setAttention(on) · setCausality(on) · setHeatmap(on) | toggle diagnostics |
| burst(x, y, hex?) · flowTo(x, y) · clearFlow() | impulses and a movable focus |
| threads(list) | draw relationship threads between bodies |
| destroy() | stop the engine (and remove the managed canvas, if it created one) |
Client only. The field is a browser effect:
new FieldField()(andmountField()) touchdocumentright away and throw a clear error during server-side rendering. In Next.js, Astro, SvelteKit, and similar, construct it on the client — insideuseEffect,onMount, or a "client only" boundary.
Drive a <canvas> you own instead by passing it — then the field never creates or removes a canvas,
and destroy() only stops the engine:
const field = new FieldField({ canvas: myCanvas, density: 1.2 });The function
If you prefer a plain factory over a class, mountField() returns the bare FieldHandle:
import { mountField } from '@field-ui/vanilla';
const field = mountField({ render: 'trails' });
// field.destroy() also removes the canvas it created.To run the engine on a <canvas> with no managed wrapper at all, the host-bundled createField is
re-exported (this one supplies browserHost() for you, unlike the core primitive):
import { createField } from '@field-ui/vanilla';
const field = createField(document.querySelector('canvas')!, { accent: '#2dd4bf' });Marking bodies — the data-body vocabulary
| Attribute | Meaning |
|---|---|
| data-body="attract" | the force token (attract, gravity, charge, sink, …) |
| data-strength | how hard it bends the field |
| data-range | radius of influence, in px |
| data-feedback | opt in to receiving --field-* variables back |
| data-absorb / data-max | for sink bodies: accretion load and capacity |
Call field.scan() after adding new [data-body] elements so the engine picks them up.
Catalog
For building UI around the field (a force picker, a legend), the catalog data is re-exported so you
need no second install: FORCES, FORMATIONS, CONDITIONS, PALETTE.
import { FORCES, FORMATIONS } from '@field-ui/vanilla';Recipes & data binding
To apply a named recipe over your markup or bind data to the field, use applyRecipe() / bindData()
from @field-ui/platform; browse all 64 recipes at
/docs/gallery.
Related
@field-ui/core · @field-ui/platform · @field-ui/elements
· @field-ui/react · the documentation map.
License
MIT © Zach Shallbetter
