UNPKG

@ariakit/react-core

Version:

Ariakit React core

126 lines (123 loc) 3.88 kB
"use client"; import { useEvent, useLiveRef, useSafeLayoutEffect } from "./5GGHRIN3.js"; import { __spreadProps, __spreadValues } from "./3YLGPPWQ.js"; // src/utils/store.tsx import { hasOwnProperty, identity } from "@ariakit/core/utils/misc"; import { batch, init, subscribe, sync } from "@ariakit/core/utils/store"; import * as React from "react"; import useSyncExternalStoreExports from "use-sync-external-store/shim/index.js"; var { useSyncExternalStore } = useSyncExternalStoreExports; var noopSubscribe = () => () => { }; function useStoreState(store, keyOrSelector = identity) { const storeSubscribe = React.useCallback( (callback) => { if (!store) return noopSubscribe(); return subscribe(store, null, callback); }, [store] ); const getSnapshot = () => { const key = typeof keyOrSelector === "string" ? keyOrSelector : null; const selector = typeof keyOrSelector === "function" ? keyOrSelector : null; const state = store == null ? void 0 : store.getState(); if (selector) return selector(state); if (!state) return; if (!key) return; if (!hasOwnProperty(state, key)) return; return state[key]; }; return useSyncExternalStore(storeSubscribe, getSnapshot, getSnapshot); } function useStoreStateObject(store, object) { const objRef = React.useRef( {} ); const storeSubscribe = React.useCallback( (callback) => { if (!store) return noopSubscribe(); return subscribe(store, null, callback); }, [store] ); const getSnapshot = () => { const state = store == null ? void 0 : store.getState(); let updated = false; const obj = objRef.current; for (const prop in object) { const keyOrSelector = object[prop]; if (typeof keyOrSelector === "function") { const value = keyOrSelector(state); if (value !== obj[prop]) { obj[prop] = value; updated = true; } } if (typeof keyOrSelector === "string") { if (!state) continue; if (!hasOwnProperty(state, keyOrSelector)) continue; const value = state[keyOrSelector]; if (value !== obj[prop]) { obj[prop] = value; updated = true; } } } if (updated) { objRef.current = __spreadValues({}, obj); } return objRef.current; }; return useSyncExternalStore(storeSubscribe, getSnapshot, getSnapshot); } function useStoreProps(store, props, key, setKey) { const value = hasOwnProperty(props, key) ? props[key] : void 0; const setValue = setKey ? props[setKey] : void 0; const propsRef = useLiveRef({ value, setValue }); useSafeLayoutEffect(() => { return sync(store, [key], (state, prev) => { const { value: value2, setValue: setValue2 } = propsRef.current; if (!setValue2) return; if (state[key] === prev[key]) return; if (state[key] === value2) return; setValue2(state[key]); }); }, [store, key]); useSafeLayoutEffect(() => { if (value === void 0) return; store.setState(key, value); return batch(store, [key], () => { if (value === void 0) return; store.setState(key, value); }); }); } function useStore(createStore, props) { const [store, setStore] = React.useState(() => createStore(props)); useSafeLayoutEffect(() => init(store), [store]); const useState2 = React.useCallback( (keyOrSelector) => useStoreState(store, keyOrSelector), [store] ); const memoizedStore = React.useMemo( () => __spreadProps(__spreadValues({}, store), { useState: useState2 }), [store, useState2] ); const updateStore = useEvent(() => { setStore((store2) => createStore(__spreadValues(__spreadValues({}, props), store2.getState()))); }); return [memoizedStore, updateStore]; } export { useStoreState, useStoreStateObject, useStoreProps, useStore };