UNPKG

@whop/embedded-components-react-js

Version:

React components for Whop.js

88 lines (87 loc) 2.5 kB
"use client"; import { __publicField } from "./chunk-NSSMTXJJ.mjs"; import React, { useSyncExternalStore } from "react"; import { createContext, useContext, useEffect, useMemo } from "react"; const ElementsContext = createContext(null); function useElements() { const ctx = useContext(ElementsContext); if (!ctx) { throw new Error("useElements must be used within a ElementsProvider"); } return ctx.elements; } function normalizeElementsProp(prop) { if (prop instanceof Promise) return prop; return Promise.resolve(prop); } class PromiseStore { constructor(promise){ __publicField(this, "subscribers", new Set()); __publicField(this, "value", { state: "pending" }); __publicField(this, "subscribe", (listener)=>{ this.subscribers.add(listener); return ()=>{ this.subscribers.delete(listener); }; }); promise.then((value)=>{ this.value = { state: "fulfilled", value }; for (const subscriber of this.subscribers){ subscriber(); } }).catch((err)=>{ this.value = { state: "rejected", error: err }; for (const subscriber of this.subscribers){ subscriber(); } }); } getSnapshot() { return this.value; } } function useAwaitElements(elements) { const store = useMemo(()=>new PromiseStore(Promise.resolve(elements)), [ elements ]); const state = useSyncExternalStore(store.subscribe, ()=>{ const snapshot = store.getSnapshot(); if (snapshot.state === "fulfilled") { return snapshot.value; } return null; }, ()=>null); return state; } function Elements({ children, elements: elementsProp, appearance, locale }) { const elementsPromise = normalizeElementsProp(elementsProp); const elements = useAwaitElements(elementsPromise); useEffect(()=>{ if (!elements) return; elements.updateOptions({ appearance, locale }); }, [ elements, appearance, locale ]); const value = useMemo(()=>({ elements }), [ elements ]); return React.createElement(ElementsContext.Provider, { value }, children); } export { Elements, useElements };