@humanspeak/svelte-motion
Version:
Framer Motion for Svelte 5. Declarative motion.<tag> components with AnimatePresence exit animations, gestures (hover, tap, drag, focus, in-view), variants, FLIP layout animations, shared-layout transitions, spring physics, and scroll-linked motion values
49 lines (48 loc) • 1.54 kB
JavaScript
import { SvelteSet } from 'svelte/reactivity';
/**
* Build a `{ current, subscribe }` snapshot + an internal `set`
* function. Centralises the dedupe + subscriber-fanout that all three
* boolean-snapshot hooks need.
*
* Returns a tuple so consumers can hand the snapshot to callers while
* keeping `set` internal (it's not on the returned state object).
*
* Same-value writes via `set` are no-ops — saves a fanout call and
* means callers don't need their own change-detection guard.
*
* @param initial Starting value for the `current` cell.
* @returns A `[state, set]` tuple where `state` is the publicly-shared
* `{ current, subscribe }` and `set` is the internal updater the hook
* uses to push values from its event source.
*
* @example
* ```ts
* const [state, set] = createBooleanSnapshot(media.matches)
* media.addEventListener('change', (e) => set(e.matches))
* return state // { current, subscribe }
* ```
*/
export const createBooleanSnapshot = (initial) => {
let current = $state(initial);
const subscribers = new SvelteSet();
const state = {
get current() {
return current;
},
subscribe(run) {
subscribers.add(run);
run(current);
return () => {
subscribers.delete(run);
};
}
};
const set = (value) => {
if (value === current)
return;
current = value;
for (const sub of subscribers)
sub(value);
};
return [state, set];
};