UNPKG

@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
"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