@mochabug/adapt-react 1.0.0-rc16 → 1.0.0-rc17

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.
@@ -1,39 +1,16 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { AdaptCapWidget, } from "@mochabug/adapt-web";
3
- import { forwardRef, useEffect, useRef } from "react";
2
+ import { AdaptCapElement, } from "@mochabug/adapt-web";
3
+ import { forwardRef, useLayoutEffect, useRef } from "react";
4
4
  // Re-export for direct use
5
5
  export { AdaptCapWidget, } from "@mochabug/adapt-web";
6
+ // Ensure custom element is registered
7
+ void AdaptCapElement;
6
8
  /**
7
9
  * React component for Cap.js proof-of-work challenges.
8
- *
9
- * Use this component independently of the Adapt iframe component
10
- * to solve PoW challenges and get a token for starting sessions.
11
- *
12
- * @example
13
- * ```tsx
14
- * import { AdaptCap } from "@mochabug/adapt-react";
15
- * import { createConnectClient } from "@mochabug/adapt-core/connect";
16
- * import { createAdaptClient } from "@mochabug/adapt-core";
17
- *
18
- * function MyComponent() {
19
- * const rawClient = createConnectClient({ id: "my-automation" });
20
- *
21
- * return (
22
- * <AdaptCap
23
- * automationId="my-automation"
24
- * client={rawClient}
25
- * onSolve={async (token) => {
26
- * const client = createAdaptClient(rawClient, "my-automation");
27
- * await client.run({ challengeToken: token });
28
- * }}
29
- * />
30
- * );
31
- * }
32
- * ```
10
+ * Renders `<adapt-cap>` custom element and syncs non-serializable properties via ref.
33
11
  */
34
12
  export const AdaptCap = forwardRef(function AdaptCap({ automationId, client, onSolve, onError, workerCount, i18n, darkMode, className, style, }, ref) {
35
13
  const internalRef = useRef(null);
36
- const widgetRef = useRef(null);
37
14
  // Merge refs
38
15
  const setRef = (element) => {
39
16
  internalRef.current = element;
@@ -44,28 +21,15 @@ export const AdaptCap = forwardRef(function AdaptCap({ automationId, client, onS
44
21
  ref.current = element;
45
22
  }
46
23
  };
47
- useEffect(() => {
48
- if (!internalRef.current)
24
+ // Sync non-serializable properties
25
+ useLayoutEffect(() => {
26
+ const el = internalRef.current;
27
+ if (!el)
49
28
  return;
50
- widgetRef.current = new AdaptCapWidget({
51
- container: internalRef.current,
52
- automationId,
53
- client,
54
- onSolve,
55
- onError,
56
- ...(workerCount !== undefined && { workerCount }),
57
- ...(i18n !== undefined && { i18n }),
58
- });
59
- return () => {
60
- widgetRef.current?.destroy();
61
- widgetRef.current = null;
62
- };
63
- }, [automationId, client]);
64
- // Update dark mode
65
- useEffect(() => {
66
- if (darkMode !== undefined) {
67
- widgetRef.current?.setDarkMode(darkMode);
68
- }
69
- }, [darkMode]);
70
- return _jsx("div", { ref: setRef, className: className, style: style });
29
+ el.client = client;
30
+ el.i18n = i18n;
31
+ el.onSolveCallback = onSolve;
32
+ el.onErrorCallback = onError;
33
+ });
34
+ return (_jsx("adapt-cap", { ref: setRef, className: className, style: style, "automation-id": automationId, "dark-mode": darkMode ? "" : undefined, "worker-count": workerCount !== undefined ? String(workerCount) : undefined }));
71
35
  });
package/dist/esm/index.js CHANGED
@@ -1,18 +1,18 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- import { AdaptWebClient, } from "@mochabug/adapt-web";
3
- import { forwardRef, useEffect, useRef } from "react";
2
+ import { AdaptAutomationElement, } from "@mochabug/adapt-web";
3
+ import { forwardRef, useLayoutEffect, useRef } from "react";
4
4
  // Re-export everything from web
5
5
  export * from "@mochabug/adapt-web";
6
6
  // Export standalone Cap widget component
7
7
  export { AdaptCap } from "./AdaptCap.js";
8
+ // Ensure custom element is registered
9
+ void AdaptAutomationElement;
8
10
  /**
9
11
  * React component for embedding Adapt automations.
12
+ * Renders `<adapt-automation>` custom element and syncs non-serializable properties via ref.
10
13
  */
11
- export const Adapt = forwardRef(function Adapt({ id, sessionToken, authToken, transmitter, signals, challengeToken, requiresChallenge, capWidgetOptions, inheritToken, inheritFrom, forkDisplayMode, sideBySideSplit, dialogBackdropClose, darkMode, autoResizing, onSession, onOutput, classNames, className, style, }, ref) {
12
- const clientRef = useRef(null);
14
+ export const Adapt = forwardRef(function Adapt({ id, sessionToken, authToken, transmitter, signals, challengeToken, requiresChallenge, capWidgetOptions, inheritToken, inheritFrom, forkDisplayMode, sideBySideSplit, dialogBackdropClose, darkMode, autoResizing, onSession, onOutput, classNames, styles, className, style, }, ref) {
13
15
  const internalRef = useRef(null);
14
- const containerIdRef = useRef(`adapt-${Math.random().toString(36).slice(2, 11)}`);
15
- const containerId = containerIdRef.current;
16
16
  // Merge refs
17
17
  const setRef = (element) => {
18
18
  internalRef.current = element;
@@ -23,57 +23,20 @@ export const Adapt = forwardRef(function Adapt({ id, sessionToken, authToken, tr
23
23
  ref.current = element;
24
24
  }
25
25
  };
26
- useEffect(() => {
27
- clientRef.current = new AdaptWebClient({
28
- container: containerId,
29
- id,
30
- sessionToken,
31
- authToken,
32
- transmitter,
33
- signals,
34
- challengeToken,
35
- requiresChallenge,
36
- capWidgetOptions,
37
- inheritToken,
38
- inheritFrom,
39
- forkDisplayMode,
40
- sideBySideSplit,
41
- dialogBackdropClose,
42
- darkMode,
43
- autoResizing,
44
- onSession,
45
- onOutput,
46
- classNames,
47
- });
48
- return () => {
49
- clientRef.current?.destroy();
50
- clientRef.current = null;
51
- };
52
- // Only recreate client if automation ID changes
53
- }, [id]);
54
- // Runtime updates for darkMode
55
- useEffect(() => {
56
- if (darkMode !== undefined) {
57
- clientRef.current?.setDarkMode(darkMode);
58
- }
59
- }, [darkMode]);
60
- // Runtime updates for autoResizing
61
- useEffect(() => {
62
- if (autoResizing !== undefined) {
63
- clientRef.current?.setAutoResizing(autoResizing);
64
- }
65
- }, [autoResizing]);
66
- // Runtime updates for forkDisplayMode
67
- useEffect(() => {
68
- if (forkDisplayMode !== undefined) {
69
- clientRef.current?.setForkDisplayMode(forkDisplayMode);
70
- }
71
- }, [forkDisplayMode]);
72
- // Runtime updates for dialogBackdropClose
73
- useEffect(() => {
74
- if (dialogBackdropClose !== undefined) {
75
- clientRef.current?.setDialogBackdropClose(dialogBackdropClose);
76
- }
77
- }, [dialogBackdropClose]);
78
- return (_jsx("div", { ref: setRef, id: containerId, className: className, style: style }));
26
+ // Sync non-serializable properties to the element
27
+ useLayoutEffect(() => {
28
+ const el = internalRef.current;
29
+ if (!el)
30
+ return;
31
+ el.signals = signals;
32
+ el.capWidgetOptions = capWidgetOptions;
33
+ el.inheritFrom = inheritFrom;
34
+ el.classNames = classNames;
35
+ el.styles = styles;
36
+ el.onSessionCallback = onSession;
37
+ el.onOutputCallback = onOutput;
38
+ });
39
+ // React doesn't natively set properties on custom elements (pre-19),
40
+ // so we use attributes for serializable values and ref for the rest.
41
+ return (_jsx("adapt-automation", { ref: setRef, className: className, style: style, "automation-id": id, "session-token": sessionToken, "auth-token": authToken, transmitter: transmitter, "challenge-token": challengeToken, "requires-challenge": requiresChallenge ? "" : undefined, "inherit-token": inheritToken, "fork-display-mode": forkDisplayMode, "side-by-side-split": sideBySideSplit !== undefined ? String(sideBySideSplit) : undefined, "dialog-backdrop-close": dialogBackdropClose ? "" : undefined, "dark-mode": darkMode ? "" : undefined, "auto-resizing": autoResizing ? "" : undefined }));
79
42
  });
@@ -1,42 +1,35 @@
1
- import { type AdaptCapWidgetOptions } from "@mochabug/adapt-web";
1
+ import type { AutomationClient } from "@mochabug/adapt-core";
2
+ import { AdaptCapElement, type CapWidgetI18n } from "@mochabug/adapt-web";
2
3
  export { AdaptCapWidget, type AdaptCapWidgetOptions, } from "@mochabug/adapt-web";
4
+ declare module "react" {
5
+ namespace JSX {
6
+ interface IntrinsicElements {
7
+ "adapt-cap": React.DetailedHTMLProps<React.HTMLAttributes<AdaptCapElement> & {
8
+ "automation-id"?: string;
9
+ "dark-mode"?: string;
10
+ "worker-count"?: string;
11
+ }, AdaptCapElement>;
12
+ }
13
+ }
14
+ }
3
15
  /**
4
16
  * Props for the AdaptCap React component.
5
17
  */
6
- export interface AdaptCapProps extends Omit<AdaptCapWidgetOptions, "container"> {
18
+ export interface AdaptCapProps {
19
+ automationId: string;
20
+ client: AutomationClient;
21
+ workerCount?: number;
22
+ i18n?: CapWidgetI18n;
23
+ darkMode?: boolean;
24
+ onSolve?: (token: string, expires: Date) => void;
25
+ onError?: (error: Error) => void;
7
26
  /** CSS class name for the container */
8
27
  className?: string;
9
28
  /** Inline styles for the container */
10
29
  style?: React.CSSProperties;
11
- /** Enable dark mode styling */
12
- darkMode?: boolean;
13
30
  }
14
31
  /**
15
32
  * React component for Cap.js proof-of-work challenges.
16
- *
17
- * Use this component independently of the Adapt iframe component
18
- * to solve PoW challenges and get a token for starting sessions.
19
- *
20
- * @example
21
- * ```tsx
22
- * import { AdaptCap } from "@mochabug/adapt-react";
23
- * import { createConnectClient } from "@mochabug/adapt-core/connect";
24
- * import { createAdaptClient } from "@mochabug/adapt-core";
25
- *
26
- * function MyComponent() {
27
- * const rawClient = createConnectClient({ id: "my-automation" });
28
- *
29
- * return (
30
- * <AdaptCap
31
- * automationId="my-automation"
32
- * client={rawClient}
33
- * onSolve={async (token) => {
34
- * const client = createAdaptClient(rawClient, "my-automation");
35
- * await client.run({ challengeToken: token });
36
- * }}
37
- * />
38
- * );
39
- * }
40
- * ```
33
+ * Renders `<adapt-cap>` custom element and syncs non-serializable properties via ref.
41
34
  */
42
- export declare const AdaptCap: import("react").ForwardRefExoticComponent<AdaptCapProps & import("react").RefAttributes<HTMLDivElement>>;
35
+ export declare const AdaptCap: import("react").ForwardRefExoticComponent<AdaptCapProps & import("react").RefAttributes<AdaptCapElement>>;
@@ -1,16 +1,62 @@
1
- import { type AdaptWebClientOptions } from "@mochabug/adapt-web";
1
+ import { AdaptAutomationElement, type AdaptWebClientOptions, type Output, type SignalValue, type StatusJson } from "@mochabug/adapt-web";
2
+ declare module "react" {
3
+ namespace JSX {
4
+ interface IntrinsicElements {
5
+ "adapt-automation": React.DetailedHTMLProps<React.HTMLAttributes<AdaptAutomationElement> & {
6
+ "automation-id"?: string;
7
+ "session-token"?: string;
8
+ "auth-token"?: string;
9
+ transmitter?: string;
10
+ "challenge-token"?: string;
11
+ "requires-challenge"?: string;
12
+ "inherit-token"?: string;
13
+ "fork-display-mode"?: string;
14
+ "side-by-side-split"?: string;
15
+ "dialog-backdrop-close"?: string;
16
+ "dark-mode"?: string;
17
+ "auto-resizing"?: string;
18
+ }, AdaptAutomationElement>;
19
+ }
20
+ }
21
+ }
2
22
  export * from "@mochabug/adapt-web";
3
23
  export { AdaptCap, type AdaptCapProps } from "./AdaptCap.js";
4
24
  /**
5
25
  * Props for the Adapt React component.
6
26
  */
7
- export interface AdaptProps extends Pick<AdaptWebClientOptions, "id" | "sessionToken" | "authToken" | "transmitter" | "signals" | "challengeToken" | "requiresChallenge" | "capWidgetOptions" | "inheritToken" | "inheritFrom" | "forkDisplayMode" | "sideBySideSplit" | "dialogBackdropClose" | "darkMode" | "autoResizing" | "onSession" | "onOutput" | "classNames"> {
8
- /** CSS class name for the container */
27
+ export interface AdaptProps {
28
+ id: string;
29
+ sessionToken?: string;
30
+ authToken?: string;
31
+ transmitter?: string;
32
+ signals?: {
33
+ [key: string]: SignalValue;
34
+ };
35
+ challengeToken?: string;
36
+ requiresChallenge?: boolean;
37
+ capWidgetOptions?: AdaptWebClientOptions["capWidgetOptions"];
38
+ inheritToken?: string;
39
+ inheritFrom?: {
40
+ hash: string;
41
+ } | {
42
+ param: string;
43
+ };
44
+ forkDisplayMode?: "side-by-side" | "dialog";
45
+ sideBySideSplit?: number;
46
+ dialogBackdropClose?: boolean;
47
+ darkMode?: boolean;
48
+ autoResizing?: boolean;
49
+ onSession?: (status: StatusJson, fork?: string) => void;
50
+ onOutput?: (output: Output) => void;
51
+ classNames?: AdaptWebClientOptions["classNames"];
52
+ styles?: Partial<CSSStyleDeclaration>;
53
+ /** CSS class name for the host element */
9
54
  className?: string;
10
- /** Inline styles for the container */
55
+ /** Inline styles for the host element */
11
56
  style?: React.CSSProperties;
12
57
  }
13
58
  /**
14
59
  * React component for embedding Adapt automations.
60
+ * Renders `<adapt-automation>` custom element and syncs non-serializable properties via ref.
15
61
  */
16
- export declare const Adapt: import("react").ForwardRefExoticComponent<AdaptProps & import("react").RefAttributes<HTMLDivElement>>;
62
+ export declare const Adapt: import("react").ForwardRefExoticComponent<AdaptProps & import("react").RefAttributes<AdaptAutomationElement>>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mochabug/adapt-react",
3
- "version": "1.0.0-rc16",
3
+ "version": "1.0.0-rc17",
4
4
  "description": "React component for Adapt automation platform",
5
5
  "type": "module",
6
6
  "main": "./dist/esm/index.js",
@@ -32,11 +32,11 @@
32
32
  "react": "^17.0.0 || ^18.0.0 || ^19.0.0"
33
33
  },
34
34
  "devDependencies": {
35
- "@types/react": "^19.2.10",
35
+ "@types/react": "^19.2.13",
36
36
  "react": "^19.2.4",
37
37
  "typescript": "^5.9.3"
38
38
  },
39
39
  "dependencies": {
40
- "@mochabug/adapt-web": "^1.0.0-rc38"
40
+ "@mochabug/adapt-web": "^1.0.0-rc39"
41
41
  }
42
42
  }