@yamada-ui/react
Version:
React UI components of the Yamada, by the Yamada, for the Yamada built with React and Emotion
74 lines (70 loc) • 2.19 kB
JavaScript
"use client";
import { useSyncExternalStore } from "react";
import { getMemoizedObject, isArray, isObject, isUndefined, runIfFn, toArray } from "@yamada-ui/utils";
//#region src/utils/store.ts
const DEFAULT_IDENTIFIER = "default";
function createStore(initialState, additionalMethods, options = {}) {
const queue = /* @__PURE__ */ new Map();
const ref = new Proxy({ current: runIfFn(initialState) }, { ...options.proxyHandler });
function get() {
return ref.current;
}
function executeQueue(key) {
const listeners = queue.get(key) ?? [];
if (!listeners.length) console.warn(`createStore: ${key} is not subscribed.`);
listeners.forEach((listener) => listener());
}
function update(key) {
if (!isUndefined(key)) toArray(key).forEach(executeQueue);
executeQueue(DEFAULT_IDENTIFIER);
}
function set(nextState, key) {
ref.current = runIfFn(nextState, ref.current);
update(key);
}
const methods = {
ref,
get,
queue,
set,
update
};
function useStore(path, key) {
const customSubscribe = options.subscribe?.({
key,
...methods
});
const subscribe = function(listener) {
if (key) {
if ((queue.get(key) ?? []).length) console.warn(`createStore: ${key} is already subscribed.`);
queue.set(key, [listener]);
} else {
const listeners = queue.get(DEFAULT_IDENTIFIER) ?? [];
queue.set(DEFAULT_IDENTIFIER, [...listeners, listener]);
}
return function() {
if (key) queue.delete(key);
else {
const listeners = queue.get(DEFAULT_IDENTIFIER) ?? [];
queue.set(DEFAULT_IDENTIFIER, listeners.filter((fn) => fn !== listener));
}
};
};
function getSnapshot() {
if (!isUndefined(path)) {
if (isObject(ref.current)) return getMemoizedObject(ref.current, path);
else if (isArray(ref.current)) return ref.current[path];
}
return ref.current;
}
return useSyncExternalStore(customSubscribe ?? subscribe, getSnapshot, getSnapshot);
}
const customMethods = Object.fromEntries(Object.entries(additionalMethods ?? {}).map(([key, value]) => [key, value(methods)]));
return [useStore, {
...methods,
...customMethods
}];
}
//#endregion
export { createStore };
//# sourceMappingURL=store.js.map