UNPKG

@open-game-system/app-bridge-react

Version:

React hooks and components for the app-bridge ecosystem

125 lines 3.74 kB
// src/index.tsx import { createContext, memo, useCallback, useContext, useMemo, useSyncExternalStore } from "react"; import { Fragment, jsx } from "react/jsx-runtime"; function createBridgeContext() { const throwBridge = new Proxy({}, { get() { throw new Error( "Bridge not found in context. Did you forget to wrap your app in <BridgeContext.Provider bridge={...}>?" ); } }); const BridgeContext = createContext({ bridge: throwBridge }); const Provider = memo( ({ children, bridge }) => { const value = useMemo(() => ({ bridge }), [bridge]); return /* @__PURE__ */ jsx(BridgeContext.Provider, { value, children }); } ); Provider.displayName = "BridgeProvider"; function useBridge() { const context = useContext(BridgeContext); return context.bridge; } function createStoreContext(storeKey) { const throwStore = new Proxy({}, { get() { throw new Error( `Store "${String(storeKey)}" is not available. Make sure to use the store hooks inside a StoreContext.Provider.` ); } }); const StoreContext = createContext(throwStore); StoreContext.displayName = `Store<${String(storeKey)}>`; const Provider2 = memo(({ children }) => { const bridge = useBridge(); const getStore = useCallback(() => { return bridge.getStore(storeKey) || null; }, [bridge]); const subscribe = useCallback((callback) => { return bridge.subscribe(callback); }, [bridge]); const store = useSyncExternalStore( subscribe, getStore, getStore // Same for server ); if (!store) return null; return /* @__PURE__ */ jsx(StoreContext.Provider, { value: store, children }); }); Provider2.displayName = `Store.Provider<${String(storeKey)}>`; const Loading = memo(({ children }) => { const bridge = useBridge(); const isSupported = bridge.isSupported(); const getStoreAvailability = useCallback(() => { return bridge.getStore(storeKey); }, [bridge]); const subscribe = useCallback((callback) => { return bridge.subscribe(callback); }, [bridge]); const store = useSyncExternalStore( subscribe, getStoreAvailability, getStoreAvailability // Same for server ); return isSupported && !store ? /* @__PURE__ */ jsx(Fragment, { children }) : null; }); Loading.displayName = `Store.Loading<${String(storeKey)}>`; function useStore() { return useContext(StoreContext); } function useSelector(selector) { const store = useStore(); const memoizedSelector = useMemo(() => selector, [selector]); return useSyncExternalStore( store.subscribe, () => memoizedSelector(store.getSnapshot()), () => memoizedSelector(store.getSnapshot()) // Same for server ); } return { Provider: Provider2, Loading, useStore, useSelector }; } const Supported = memo(({ children }) => { const bridge = useBridge(); const isSupported = bridge.isSupported(); return isSupported ? /* @__PURE__ */ jsx(Fragment, { children }) : null; }); Supported.displayName = "BridgeSupported"; const Unsupported = memo(({ children }) => { const bridge = useBridge(); const isSupported = bridge.isSupported(); return !isSupported ? /* @__PURE__ */ jsx(Fragment, { children }) : null; }); Unsupported.displayName = "BridgeUnsupported"; return { Provider, createStoreContext, Supported, Unsupported }; } export { createBridgeContext }; //# sourceMappingURL=index.mjs.map