@ariakit/react-core
Version:
Ariakit React core
126 lines (123 loc) • 3.88 kB
JavaScript
"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
};