Troubleshooting
The errors VisDelta throws, what causes them and how to fix them.
VisDelta validates declarations instead of guessing, so most problems surface as an explicit error. The messages below are quoted from the library.
Before inventing an option or a scroll controller, check the automatic behavior table, agent workflow and runnable scroll template.
Setup
transition() and sequence() require a target. The library never guesses a
host element.
await transition(from, to, { target: '#chart' });
await transition(from, to, { target: document.querySelector('#chart')! });The selector matched nothing when the transition was created. Create the transition after the element is in the document, for example in a component's mount effect, or pass the element itself.
Both endpoints must come from the same chart family. A Bar state cannot
transition into a Line state. delta() has the same rule. Use one chart type
and change its encodings, layout or grain instead.
A plain spec was rendered without its chart module. Builders carry their module; plain objects cannot. Register the module first:
import { barModule } from 'visdelta/bar';
import { registerChartModule } from 'visdelta/plugins';
registerChartModule(barModule);Import the stylesheet once: import 'visdelta/style.css', or link
dist/visdelta.css from the CDN.
Browsers block ES modules on file://. Serve the folder with any static server,
for example npx serve, and open the http:// URL it prints.
Data
A bare string could be a file or a named dataset. Be explicit:
bar({ url: 'sales.csv' }); // a file
bar({ name: 'sales' }); // a named dataset, supplied in transition optionsA state uses { name: 'sales' }, but the transition options do not provide it:
await transition(from, to, { target: '#chart', data: { sales: rows } });The data source has an unsupported shape. Pass an array of objects,
{ values: rows } or { url }.
A hand-written transform has an unknown key, or more than one operation in one
entry. Each entry holds exactly one of filter, timeUnit, fold, bin,
aggregate, sort or limit. See Transforms.
Selectors use the operator equal, not equals. Range operators (gt, gte,
lt, lte) need finite numbers, Date values or ISO date strings, and
missing values never match a range. Repeated calls narrow the selection with
AND; use .reset() to start over. See Selectors.
Playback
A controller was used after destroy(). In component code, clear your reference
in the cleanup function, and guard asynchronous callbacks. See
Use with React.
progress() received NaN or Infinity, often from an empty input value.
Finite values are clamped to [0, 1] automatically.
On a pair controller, play() starts from 0 unless you pass from. Resume
with change.play({ from: change.value, to: 1 }). A sequence's play()
already starts from its current value.
duration applies to each serial route stage. A route with generated
intermediate states has several stages, so it takes a multiple of duration.
See Progress.
VisDelta reads CSS tokens when it renders. Call change.resize() after changing
the theme. See Dark mode.
Marks that should continue need matching identity at both endpoints. Add
.key() with a field that identifies the same item in both states. See
Identity.
Still stuck?
Open an issue on GitHub with a
minimal pair of states. JSON.stringify(state.toSpec()) for both endpoints is
usually enough to reproduce a problem.