@shined/reactive
Version:
⚛️ Proxy-driven state library for JavaScript application, Intuitive, Flexible and Written in TypeScript.
70 lines (63 loc) • 1.94 kB
text/typescript
import { useSnapshot } from '../../react/use-snapshot.js'
import { isFunction } from '../../utils/index.js'
import type { StoreUseSnapshot } from '../../react/create-with-hooks.js'
import type { SnapshotOptions, SnapshotSelector } from '../../react/use-snapshot.js'
import type { VanillaStore } from '../../vanilla/create.js'
export interface WithUseSnapshotContributes<State extends object> {
/**
* Get the snapshot of the state.
*/
useSnapshot: StoreUseSnapshot<State>
}
/**
* Enhances a store with `useSnapshot` method that returns a snapshot of the store's state.
*
* @param store - The store to enhance.
* @returns The enhanced store.
*
* @since 0.2.0
*
* @example
*
* ```tsx
* const store = withUseSnapshot(
* createVanilla({
* count: 123,
* info: { name: 'Viki' },
* }),
* )
*
* // in normal JS/TS
* console.log(store.snapshot(), store.snapshot((s) => s.count))
*
* // in React component
* export function App() {
* const { count } = store.useSnapshot()
* const count = store.useSnapshot((s) => s.count)
* }
*
* ```
*/
export function withUseSnapshot<Store extends VanillaStore<object>>(
store: Store,
): Store & WithUseSnapshotContributes<Store['mutate']> {
const boundUseSnapshot: StoreUseSnapshot<Store['mutate']> = <StateSlice>(
selectorOrOption?: SnapshotOptions<StateSlice> | SnapshotSelector<Store['mutate'], StateSlice> | undefined,
maybeOptions?: SnapshotOptions<StateSlice>,
) => {
let options: SnapshotOptions<StateSlice> | undefined
let selector: SnapshotSelector<Store['mutate'], StateSlice> | undefined
if (selectorOrOption && !isFunction(selectorOrOption)) {
options = selectorOrOption
selector = undefined
} else {
options = maybeOptions
selector = selectorOrOption
}
return useSnapshot(store.mutate, selector, options)
}
return {
...store,
useSnapshot: boundUseSnapshot,
}
}