/** * uSES bridge: turns any bare observable snapshot source into a typed * selector hook. Client-side-rendered only, so no server snapshot is wired. * This is the ONE hook constructor in the client stack — engines and hosts * traffic in bare sources; binding happens on the React side. */ import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/shim/with-selector.js' import type { HostObservable, SnapshotSelectorHook } from '@deepseek-ai/dsh-client-ui-slots' /** * Bind a bare observable source to a typed uSES selector hook. * subscribe/getSnapshot are captured once per source into stable closures * (also re-binds `this` for method-based sources), so components never * resubscribe across renders. Equality defaults to Object.is. * @param w - snapshot source (engine store, Session object, store instance). * @returns the selector hook. */ export function bindSnapshotSelector(w: HostObservable): SnapshotSelectorHook { const subscribe = (fn: () => void) => w.subscribe(fn) const getSnapshot = () => w.getSnapshot() return function useSelector(sel: (s: T) => S, eq?: (a: S, b: S) => boolean): S { return useSyncExternalStoreWithSelector(subscribe, getSnapshot, undefined, sel, eq) } }