Vanilla Disintegrate adds a Thanos-snap particle deletion effect to any measurable DOM element. The vanilla-disintegrate/snapdom entry wires SnapDOM capture for you, and no CSS import is required.
Installation
Use any supported package manager:
# npm
npm install vanilla-disintegrate @zumer/snapdom
# Yarn
yarn add vanilla-disintegrate @zumer/snapdom
# pnpm
pnpm add vanilla-disintegrate @zumer/snapdom
# Bun
bun add vanilla-disintegrate @zumer/snapdom
The library captures the current appearance of an element before splitting it into particles, and the capture library is your choice. The package ships two entry points:
| Entry | Contents | Requires |
|---|---|---|
vanilla-disintegrate | Core: effects, lifecycle, layout, audio. You supply capture. | Nothing |
vanilla-disintegrate/snapdom | The same API with SnapDOM wired as the default capture. | @zumer/snapdom |
Both entries export the identical Disintegrator API. @zumer/snapdom is an optional peer dependency: install it only for the /snapdom entry, and the core entry never reaches for it.
import Disintegrator from 'vanilla-disintegrate/snapdom';
const effects = new Disintegrator();
const card = document.querySelector<HTMLElement>('.card');
if (card) {
effects.remove(card, { effect: 'dust' });
}
remove() returns immediately. Use operation.finished only when later code must wait for the visual to settle.
Remove and restore the same node
Set retain: true only when the original node may be needed again. The application still decides where to insert it.
const removal = effects.remove(card, {
effect: 'dust',
retain: true,
});
await removal.finished;
if (removal.removalId) {
const retained = effects.take(removal.removalId);
if (retained) {
list.append(retained);
await effects.restore(retained).finished;
}
}
The restore phase uses the effect remembered during removal unless the call supplies another effect.
Use another capture library
capture is a small adapter contract, not a SnapDOM-only API. For example, an application can use html2canvas:
import html2canvas from 'html2canvas';
import Disintegrator from 'vanilla-disintegrate';
const effects = new Disintegrator({
capture: (element, context) => {
context.signal.throwIfAborted();
return html2canvas(element, {
backgroundColor: null,
logging: false,
scale: 1,
useCORS: true,
onclone: (_document, clone) => {
if (context.restoreRootOpacity !== undefined) {
clone.style.setProperty('opacity', context.restoreRootOpacity, 'important');
}
},
});
},
});
The supplied function completely replaces capture. Import the core vanilla-disintegrate entry on this path: it has no runtime dependencies, and nothing from SnapDOM enters the module graph.
Clean up
Call destroy() when the owning view or application is permanently disposed. It cancels active visuals, clears prepared snapshots, stops observers, and releases all retained references.
effects.destroy();
Browser support
The core needs ES2020 output, Canvas, Web Animations, AbortController, and requestAnimationFrame. The four built-in effects draw their particles with WebGL2, which sets the baseline: Chrome 80+, Firefox 74+, Edge 80+, Opera 67+, and Safari 15+.
Where WebGL2 is missing or a context cannot be created, the built-in effects degrade instead of failing: remove() still detaches the element, restore() still reveals it, the operation resolves with status skipped, and onError receives the reason. Custom effects built on WAAPI, CSS, or Canvas 2D keep animating on older engines.
Each running built-in effect holds one WebGL2 context and releases it the moment the operation ends, so removing a long list stays well inside the per-page context limit browsers enforce.