svelte-settings
Version:
> [!WARNING] > This project is a work in progress. Do not use it in any of your projects yet.
54 lines (53 loc) • 1.8 kB
JavaScript
import { deepEqual } from '../deep.js';
import { readable, writable } from 'svelte/store';
import { browser } from '$app/environment';
/**
* Creates a subscription to a nested part of the store according to the selector.
* The subscription only fires when this part changes, and ignores changes to the rest of the store.
*
* @param selector A function which returns the part of the store to subscribe to. Being a callback allows for type support.
* @param isEqual A callback which allows for overriding the equality checks, e.g. for objects.
*/
export function select(store, selector, isEqual = deepEqual) {
return {
subscribe(run) {
let prev;
return store.subscribe((value) => {
const next = selector(value);
console.debug('store select compare', prev, next, isEqual(prev, next));
if (prev === undefined || !isEqual(prev, next)) {
prev = structuredClone(next);
run(next);
}
});
},
};
}
export function isStore(value) {
return (typeof value === 'object' &&
value !== null &&
'subscribe' in value &&
typeof value.subscribe === 'function');
}
/**
* A helper to convert either a value, a value callback or a Readable to a Readable.
*/
export function toReadable(value) {
if (isStore(value)) {
return value;
}
if (typeof value === 'function') {
const fn = value;
return readable(undefined, (set) => {
let cancelled = false;
fn().then((res) => {
if (!cancelled)
set(res);
});
return () => {
cancelled = true;
};
});
}
return readable(value);
}