mock dashboard + 2 way sync in nanostores (i hate ctx)

This commit is contained in:
grngxd 2025-06-08 14:45:40 +01:00
parent d792cec873
commit 31594891e5
5 changed files with 150 additions and 70 deletions

View file

@ -1,17 +1,67 @@
import { isServer, noSerialize, useSignal, type NoSerialize } from '@builder.io/qwik';
import type { ReadableAtom } from 'nanostores';
import {
implicit$FirstArg,
noSerialize,
NoSerialize,
QRL,
Signal,
useSignal,
useTask$,
useVisibleTask$,
} from "@builder.io/qwik";
import { Atom, WritableAtom } from "nanostores";
export function useNanostore<T>(atom: ReadableAtom<T>) {
if (isServer) return
function writeable<T = any>(store: Atom<T> | WritableAtom<T>): store is WritableAtom<T> {
return typeof (store as WritableAtom<T>).set === 'function';
}
const state = useSignal<T>(atom.get());
const store = useSignal<NoSerialize<ReadableAtom<T>> | undefined>(undefined);
export function useNanostoreQrl<T>(qrl: QRL<WritableAtom<T> | Atom<T>>): Signal<T> {
const signal = useSignal<T | undefined>(undefined);
const storeSignal = useSignal<NoSerialize<WritableAtom<T> | Atom<T>> | undefined>(undefined);
store.value = noSerialize(atom);
const unsubscribe = atom.subscribe((value) => {
state.value = value;
useTask$(async ({ track }) => {
let store: WritableAtom<T> | Atom<T> | undefined = storeSignal.value;
if (!store) {
const modified = await qrl.resolve();
storeSignal.value = noSerialize(modified);
store = modified;
}
if (signal.value === undefined && store.value !== undefined) {
signal.value = store.value;
}
const v = track(signal);
if (writeable(store) && v !== undefined && store.value !== v) {
store.set(v);
}
});
window.addEventListener('beforeunload', () => unsubscribe());
return state;
}
// eslint-disable-next-line qwik/no-use-visible-task
useVisibleTask$(async ({ cleanup }) => {
let store: WritableAtom<T> | Atom<T> | undefined = storeSignal.value;
if (!store) {
const modified = await qrl.resolve();
storeSignal.value = noSerialize(modified);
store = modified;
}
if (store.value !== undefined && signal.value !== store.value) {
signal.value = store.value;
}
const unsub = store.subscribe((value) => {
if (signal.value !== value) {
signal.value = value;
}
});
cleanup(unsub);
});
return signal as Signal<T>;
}
export const useNanostore$ = implicit$FirstArg(useNanostoreQrl);