@sevenfold/setto-client 0.10.0 → 0.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/chrome.d.ts CHANGED
@@ -6,6 +6,21 @@ export interface SettoChromeHandshake {
6
6
  /** The host's React, so the chrome bundle ships no framework of its own. */
7
7
  react: typeof React;
8
8
  reactDom: typeof ReactDOM;
9
+ /**
10
+ * Hand back a component and the host renders it.
11
+ *
12
+ * Inverted deliberately. The first cut had the chrome create its own React
13
+ * root, which cannot work: `createRoot` lives in `react-dom/client`, not
14
+ * `react-dom`, and React 19 removed `render` altogether — so the bundle
15
+ * loaded, found neither, and mounted nothing at all.
16
+ *
17
+ * Rendering it from here is better than passing `createRoot` across would
18
+ * have been. The chrome ends up inside the host's own tree, so its hooks are
19
+ * the host's hooks with no second root to keep in step, and the error
20
+ * boundary that keeps a mistake off the customer's page lives on this side
21
+ * where it cannot be forgotten.
22
+ */
23
+ mount: (Component: React.ComponentType) => void;
9
24
  config: {
10
25
  siteId: string;
11
26
  apiUrl: string;
@@ -33,4 +48,4 @@ declare global {
33
48
  __settoChromeLoaded__?: boolean;
34
49
  }
35
50
  }
36
- export declare function SettoChrome(): null;
51
+ export declare function SettoChrome(): import("react/jsx-runtime").JSX.Element | null;
@@ -21364,8 +21364,21 @@ const CHROME_CONTRACT = 1;
21364
21364
  function chromeUrl(apiUrl) {
21365
21365
  return `${apiUrl.replace(/\/$/, "")}/chrome/v${CHROME_CONTRACT}.js`;
21366
21366
  }
21367
+ class ChromeBoundary extends React.Component {
21368
+ state = { dead: false };
21369
+ static getDerivedStateFromError() {
21370
+ return { dead: true };
21371
+ }
21372
+ componentDidCatch(error) {
21373
+ console.warn("[setto] chrome failed, continuing without it", error);
21374
+ }
21375
+ render() {
21376
+ return this.state.dead ? null : this.props.children;
21377
+ }
21378
+ }
21367
21379
  function SettoChrome() {
21368
21380
  const setto = useSetto();
21381
+ const [Chrome, setChrome] = useState(null);
21369
21382
  const listeners = useRef(/* @__PURE__ */ new Set());
21370
21383
  const stateRef = useRef(() => ({
21371
21384
  hasSession: false,
@@ -21412,7 +21425,10 @@ function SettoChrome() {
21412
21425
  subscribe: (listener) => {
21413
21426
  listeners.current.add(listener);
21414
21427
  return () => listeners.current.delete(listener);
21415
- }
21428
+ },
21429
+ // `setChrome(() => C)`: a component is a function, and the updater form
21430
+ // is the only way to put one into state without React calling it.
21431
+ mount: (Component) => setChrome(() => Component)
21416
21432
  };
21417
21433
  const script = document.createElement("script");
21418
21434
  script.src = chromeUrl(setto.config.apiUrl);
@@ -21423,7 +21439,8 @@ function SettoChrome() {
21423
21439
  } catch {
21424
21440
  }
21425
21441
  }, []);
21426
- return null;
21442
+ if (!Chrome) return null;
21443
+ return /* @__PURE__ */ jsx(ChromeBoundary, { children: /* @__PURE__ */ jsx(Chrome, {}) });
21427
21444
  }
21428
21445
  const SETTO_BASE = "/setto";
21429
21446
  function siteHomeUrl(pathname = "/") {