@mochabug/adapt-web 1.0.1-rc.3 → 1.0.1-rc.30

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.
Files changed (63) hide show
  1. package/README.md +373 -379
  2. package/dist/README.md +481 -0
  3. package/dist/esm/AdaptAutomationElement.js +1 -282
  4. package/dist/esm/AdaptCapElement.js +1 -170
  5. package/dist/esm/AdaptCapWidget.js +1 -261
  6. package/dist/esm/adapt.js +1 -0
  7. package/dist/esm/cap-adapter.js +1 -146
  8. package/dist/esm/cap.js +1 -0
  9. package/dist/esm/core.js +1 -0
  10. package/dist/esm/css-cap.js +109 -0
  11. package/dist/esm/css-panel.js +895 -0
  12. package/dist/esm/elements.js +1 -4
  13. package/dist/esm/iframe-url.js +1 -24
  14. package/dist/esm/index.js +1 -2353
  15. package/dist/esm/panel-manager.js +1 -0
  16. package/dist/esm/panel-setup.js +1 -0
  17. package/dist/esm/theme.js +1 -0
  18. package/dist/esm/types.js +0 -1
  19. package/dist/esm/umd-cap-entry.js +1 -0
  20. package/dist/esm/umd-entry.js +1 -0
  21. package/dist/esm/umd-full-entry.js +1 -0
  22. package/dist/esm/umd-headless-entry.js +1 -0
  23. package/dist/styles.css +1005 -0
  24. package/dist/types/AdaptAutomationElement.d.ts +44 -8
  25. package/dist/types/AdaptCapElement.d.ts +3 -3
  26. package/dist/types/AdaptCapWidget.d.ts +19 -5
  27. package/dist/types/adapt.d.ts +29 -0
  28. package/dist/types/cap-adapter.d.ts +14 -2
  29. package/dist/types/cap.d.ts +25 -0
  30. package/dist/types/core.d.ts +22 -0
  31. package/dist/types/css-cap.d.ts +1 -0
  32. package/dist/types/css-panel.d.ts +1 -0
  33. package/dist/types/elements.d.ts +0 -1
  34. package/dist/types/index.d.ts +181 -87
  35. package/dist/types/panel-manager.d.ts +595 -0
  36. package/dist/types/panel-setup.d.ts +231 -0
  37. package/dist/types/theme.d.ts +42 -0
  38. package/dist/types/types.d.ts +165 -40
  39. package/dist/types/umd-cap-entry.d.ts +1 -0
  40. package/dist/types/umd-entry.d.ts +2 -0
  41. package/dist/types/umd-full-entry.d.ts +2 -0
  42. package/dist/types/umd-headless-entry.d.ts +2 -0
  43. package/dist/umd/adapt-core.js +6767 -0
  44. package/dist/umd/adapt-core.js.br +0 -0
  45. package/dist/umd/adapt-core.min.js +4 -0
  46. package/dist/umd/adapt-core.min.js.br +0 -0
  47. package/dist/umd/adapt-web.cap.js +7174 -0
  48. package/dist/umd/adapt-web.cap.js.br +0 -0
  49. package/dist/umd/adapt-web.cap.min.js +114 -0
  50. package/dist/umd/adapt-web.cap.min.js.br +0 -0
  51. package/dist/umd/adapt-web.core.js +13271 -0
  52. package/dist/umd/adapt-web.core.js.br +0 -0
  53. package/dist/umd/adapt-web.core.min.js +898 -0
  54. package/dist/umd/adapt-web.core.min.js.br +0 -0
  55. package/dist/umd/adapt-web.js +7766 -2982
  56. package/dist/umd/adapt-web.js.br +0 -0
  57. package/dist/umd/adapt-web.min.js +839 -536
  58. package/dist/umd/adapt-web.min.js.br +0 -0
  59. package/dist/umd/cap_wasm.js.br +0 -0
  60. package/dist/umd/cap_wasm_bg.wasm.br +0 -0
  61. package/dist/umd/styles.css +1005 -0
  62. package/dist/umd/styles.css.br +0 -0
  63. package/package.json +35 -16
package/README.md CHANGED
@@ -6,481 +6,475 @@ Embed Adapt automations in any website.
6
6
  npm install @mochabug/adapt-web
7
7
  ```
8
8
 
9
- ## Quickstart
9
+ **CDN base:** `https://cdn.mochabug.com/adapt/web/__VERSION__/`
10
+
11
+ | Bundle | File | Includes |
12
+ |--------|------|----------|
13
+ | Full | `adapt-web.min.js` | Automation + Cap.js challenges |
14
+ | Core | `adapt-web.core.min.js` | Automation only (~40KB smaller) |
15
+ | Cap | `adapt-web.cap.min.js` | Cap.js challenge widget only |
16
+ | Headless | `adapt-core.min.js` | Headless client (no UI) |
17
+
18
+ ### Composable loading
19
+
20
+ Bundles merge into a single `MbAdapt` global, so you can combine them. For example, headless + Cap for automations that need proof-of-work but no UI:
10
21
 
11
22
  ```html
12
- <div id="auto" style="height:600px"></div>
13
- <script src="https://cdn.jsdelivr.net/npm/@mochabug/adapt-web/dist/umd/adapt-web.min.js"></script>
23
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-core.min.js"></script>
24
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js"></script>
14
25
  <script>
15
- new MbAdapt.AdaptWebClient({
16
- container: 'auto',
17
- id: 'your-automation-id'
18
- });
26
+ // MbAdapt has exports from both scripts
27
+ var client = MbAdapt.createAdaptClient(
28
+ MbAdapt.createConnectClient({ id: "YOUR_ID" }),
29
+ "YOUR_ID"
30
+ );
19
31
  </script>
20
32
  ```
21
33
 
22
- ## ES Modules
34
+ ---
23
35
 
24
- ```typescript
25
- import { AdaptWebClient } from '@mochabug/adapt-web';
36
+ ## 1. `<adapt-automation>`
26
37
 
27
- const client = new AdaptWebClient({
28
- container: 'auto',
29
- id: 'your-automation-id'
30
- });
38
+ The main component. Drop it in, set `automation-id`, done.
31
39
 
32
- // cleanup
33
- await client.destroy();
34
- ```
35
-
36
- ## With auth token
40
+ ### Optimal — `<head>` access available
37
41
 
38
- Only needed if the automation requires authentication:
42
+ Preload the script and load the stylesheet in `<head>` to eliminate flash of unstyled content.
39
43
 
40
- ```typescript
41
- new AdaptWebClient({
42
- container: 'auto',
43
- id: 'your-automation-id',
44
- authToken: 'your-token'
45
- });
44
+ ```html
45
+ <head>
46
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.min.js" as="script">
47
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/__VERSION__/styles.css">
48
+ </head>
49
+ <body>
50
+ <adapt-automation automation-id="YOUR_ID" requires-challenge style="height: 600px"></adapt-automation>
51
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.min.js"></script>
52
+ </body>
46
53
  ```
47
54
 
48
- ## CDN versions
55
+ No challenges? Use the core bundle and drop `requires-challenge`:
49
56
 
50
57
  ```html
51
- <!-- latest -->
52
- <script src="https://cdn.jsdelivr.net/npm/@mochabug/adapt-web/dist/umd/adapt-web.min.js"></script>
58
+ <head>
59
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.core.min.js" as="script">
60
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/__VERSION__/styles.css">
61
+ </head>
62
+ <body>
63
+ <adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
64
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.core.min.js"></script>
65
+ </body>
66
+ ```
53
67
 
54
- <!-- pin exact -->
55
- <script src="https://cdn.jsdelivr.net/npm/@mochabug/adapt-web@1.0.0/dist/umd/adapt-web.min.js"></script>
68
+ ### Embedded no `<head>` access (Wix, Squarespace, WordPress, etc.)
56
69
 
57
- <!-- pin minor -->
58
- <script src="https://cdn.jsdelivr.net/npm/@mochabug/adapt-web@1.0/dist/umd/adapt-web.min.js"></script>
70
+ Just the element and script. CSS is auto-injected at runtime.
59
71
 
60
- <!-- unpkg works too -->
61
- <script src="https://unpkg.com/@mochabug/adapt-web/dist/umd/adapt-web.min.js"></script>
72
+ ```html
73
+ <adapt-automation automation-id="YOUR_ID" requires-challenge style="height: 600px"></adapt-automation>
74
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.min.js"></script>
62
75
  ```
63
76
 
64
- ## SSR (keep auth token server-side)
65
-
66
- Create session on server, pass session token to client:
77
+ Without challenges:
67
78
 
68
- ```typescript
69
- // server
70
- import { startSession } from '@mochabug/adapt-core';
71
- const { token } = await startSession({ id: 'auto-123' }, authToken);
72
-
73
- // client
74
- new AdaptWebClient({
75
- container: 'auto',
76
- id: 'auto-123',
77
- sessionToken: token // not authToken
78
- });
79
+ ```html
80
+ <adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
81
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.core.min.js"></script>
79
82
  ```
80
83
 
81
- ## Session inheritance
82
-
83
- Join existing session instead of starting new:
84
+ ### ESM
84
85
 
85
86
  ```typescript
86
- // direct token
87
- new AdaptWebClient({
88
- container: 'auto',
89
- id: 'auto-123',
90
- inheritToken: 'token-from-parent'
91
- });
92
-
93
- // from URL hash: example.com#mb_session=xxx
94
- new AdaptWebClient({
95
- container: 'auto',
96
- id: 'auto-123',
97
- inheritFrom: { hash: 'mb_session' }
98
- });
99
-
100
- // from URL param: example.com?token=xxx
101
- new AdaptWebClient({
102
- container: 'auto',
103
- id: 'auto-123',
104
- inheritFrom: { param: 'token' }
105
- });
87
+ import '@mochabug/adapt-web'; // with challenges
88
+ import '@mochabug/adapt-web/styles.css';
106
89
  ```
107
90
 
108
- ## Fork display (for AI agents with UI)
109
-
110
91
  ```typescript
111
- // side-by-side panels
112
- new AdaptWebClient({
113
- container: 'auto',
114
- id: 'auto-123',
115
- forkDisplay: { mode: 'side-by-side', split: 60 }
116
- });
92
+ import '@mochabug/adapt-web/core'; // without challenges (lighter)
93
+ import '@mochabug/adapt-web/styles.css';
94
+ ```
117
95
 
118
- // modal dialog
119
- new AdaptWebClient({
120
- container: 'auto',
121
- id: 'auto-123',
122
- forkDisplay: { mode: 'dialog', backdropClose: true, resizeToContent: true }
123
- });
96
+ ```html
97
+ <adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
124
98
  ```
125
99
 
126
- ## Callbacks
100
+ ### Attributes
101
+
102
+ | Attribute | Description |
103
+ |-----------|-------------|
104
+ | `automation-id` | **Required.** Automation ID |
105
+ | `requires-challenge` | Require proof-of-work before starting (full bundle only) |
106
+ | `auth-token` | Client-side auth token |
107
+ | `session-token` | Server-created session token |
108
+ | `inherit-token` | Join an existing session |
109
+ | `challenge-token` | Pre-solved challenge token |
110
+ | `transmitter` | Transmitter ID |
111
+ | `inherit-from` | JSON object: `{"hash":"mb_session"}` or `{"param":"token"}` |
112
+ | `signals` | JSON object of initial signal values |
113
+ | `fork-display-mode` | `side-by-side` (default) or `dialog` |
114
+ | `side-by-side-split` | Split percentage, e.g. `60` |
115
+ | `dark-mode` | Enable dark mode |
116
+ | `auto-resizing` | Container follows iframe content height |
117
+ | `allow-floating` | Set to `"false"` to hide pop-out buttons and block user-initiated floating |
118
+ | `allow-docking` | Set to `"false"` to hide dock buttons and block user-initiated docking |
119
+ | `allow-dialog-docking` | Set to `"false"` to prevent tab splits inside floating dialog overlays |
120
+ | `floating-auto-resize` | Floating overlays auto-resize based on iframe content height |
121
+ | `persist` | Persist session across page refreshes |
122
+ | `confirm-on-close` | Show a confirmation dialog before the user leaves the page while a session is active |
123
+
124
+ Initial JSON options can be written directly on the element:
127
125
 
128
- ```typescript
129
- new AdaptWebClient({
130
- container: 'auto',
131
- id: 'auto-123',
132
- onSession: (status, fork) => console.log(status, fork),
133
- onOutput: (output) => console.log(output)
134
- });
126
+ ```html
127
+ <adapt-automation
128
+ automation-id="YOUR_ID"
129
+ inherit-from='{"hash":"mb_session"}'
130
+ signals='{"key":"value"}'
131
+ style="height: 600px"
132
+ ></adapt-automation>
133
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.core.min.js"></script>
135
134
  ```
136
135
 
137
- ## Advanced: Multiple transmitters or initial signals
136
+ For complex values that are easier to build in JavaScript, set properties before loading the bundle:
138
137
 
139
- For automations with multiple entry points or when you need to pass initial data:
138
+ ```html
139
+ <adapt-automation id="automation" automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
140
+ <script>
141
+ const el = document.getElementById('automation');
142
+ el.inheritFrom = { hash: 'mb_session' };
143
+ el.signals = { key: 'value' };
144
+ </script>
145
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.core.min.js"></script>
146
+ ```
140
147
 
141
- ```typescript
142
- import { AdaptWebClient, type SignalValue } from '@mochabug/adapt-web';
143
-
144
- // Start from a specific transmitter
145
- new AdaptWebClient({
146
- container: 'auto',
147
- id: 'auto-123',
148
- authToken: 'your-token',
149
- transmitter: 'my-transmitter'
150
- });
148
+ ### JS-only properties
151
149
 
152
- // Start with initial signals (data must be base64 encoded)
153
- const signals: { [key: string]: SignalValue } = {
154
- 'input': {
155
- mimeType: 'text/plain',
156
- data: btoa('Hello World')
157
- },
158
- 'file': {
159
- mimeType: 'application/pdf',
160
- filename: 'document.pdf',
161
- data: base64FileContent
162
- }
163
- };
150
+ Set via element reference not available as HTML attributes.
164
151
 
165
- new AdaptWebClient({
166
- container: 'auto',
167
- id: 'auto-123',
168
- authToken: 'your-token',
169
- transmitter: 'file-processor',
170
- signals
171
- });
172
- ```
152
+ | Property | Type |
153
+ |----------|------|
154
+ | `capWidgetOptions` | `{ workerCount?: number; i18n?: CapWidgetI18n }` |
155
+ | `classNames` | `{ root?: string; iframe?: string; statusMessage?: string; statusCard?: string }` |
156
+ | `styles` | `Partial<CSSStyleDeclaration>` |
157
+ | `persistOptions` | `{ storage?: 'session' \| 'local'; ttl?: number; key?: string }` |
158
+ | `text` | `StatusText` |
159
+ | `theme` | `AdaptTheme` |
173
160
 
174
- ---
161
+ `signals` and `inheritFrom` are also available as JS properties. They are initial options; set them before the element initializes.
175
162
 
176
- ## Proof-of-Work Challenge (Cap.js Widget)
163
+ ### Events
177
164
 
178
- Automations can require a proof-of-work challenge before starting. The widget uses [Cap.js](https://capjs.js.org/) under the hood — a lightweight CAPTCHA alternative that runs entirely client-side.
165
+ | Event | Detail |
166
+ |-------|--------|
167
+ | `adapt-session` | `{ status: StatusJson, fork?: string }` |
168
+ | `adapt-output` | `{ output: Output }` |
169
+ | `adapt-fork-active` | `{ active: boolean }` |
179
170
 
180
- ### Using with AdaptWebClient
171
+ ### Methods
181
172
 
182
- Set `requiresChallenge: true` and the widget appears automatically, centered inside the container, before the automation starts:
173
+ | Method | Description |
174
+ |--------|-------------|
175
+ | `newSession()` | Ends the current session and starts a new one. Returns a `Promise<void>`. |
183
176
 
184
- ```typescript
185
- new AdaptWebClient({
186
- container: 'auto',
187
- id: 'auto-123',
188
- requiresChallenge: true
189
- });
190
- ```
177
+ ---
191
178
 
192
- Optionally customize the widget labels and worker count:
179
+ ## 2. `<adapt-cap>`
193
180
 
194
- ```typescript
195
- new AdaptWebClient({
196
- container: 'auto',
197
- id: 'auto-123',
198
- requiresChallenge: true,
199
- capWidgetOptions: {
200
- workerCount: 4,
201
- i18n: {
202
- initialState: "Verify you're human",
203
- verifyingLabel: 'Verifying...',
204
- solvedLabel: 'Verified!',
205
- errorLabel: 'Error'
206
- }
207
- }
208
- });
209
- ```
181
+ Standalone proof-of-work challenge widget. Use when you manage the automation client yourself.
210
182
 
211
- Or skip the widget entirely by providing a pre-solved token:
183
+ Requires a `client` JS property set it after the element is in the DOM.
212
184
 
213
- ```typescript
214
- new AdaptWebClient({
215
- container: 'auto',
216
- id: 'auto-123',
217
- challengeToken: presolvedToken
218
- });
219
- ```
185
+ ### Optimal
220
186
 
221
- ### Using the `<adapt-cap>` web component
187
+ ```html
188
+ <head>
189
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js" as="script">
190
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/__VERSION__/styles.css">
191
+ </head>
192
+ <body>
193
+ <adapt-cap automation-id="YOUR_ID"></adapt-cap>
194
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js"></script>
195
+ <script>
196
+ var el = document.querySelector('adapt-cap');
197
+ el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
198
+ el.addEventListener('adapt-cap-solve', function(e) {
199
+ console.log('Token:', e.detail.token);
200
+ });
201
+ </script>
202
+ </body>
203
+ ```
222
204
 
223
- For framework integration. The element renders a Cap.js widget and dispatches events on solve/error. Requires both `automation-id` and a `client` property (set via JS).
205
+ ### Embedded
224
206
 
225
207
  ```html
226
- <adapt-cap
227
- automation-id="auto-123"
228
- dark-mode
229
- worker-count="4"
230
- ></adapt-cap>
208
+ <adapt-cap automation-id="YOUR_ID"></adapt-cap>
209
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js"></script>
210
+ <script>
211
+ var el = document.querySelector('adapt-cap');
212
+ el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
213
+ el.addEventListener('adapt-cap-solve', function(e) {
214
+ console.log('Token:', e.detail.token);
215
+ });
216
+ </script>
231
217
  ```
232
218
 
233
- ```typescript
234
- import '@mochabug/adapt-web/elements';
235
- import { createConnectClient } from '@mochabug/adapt-core/connect';
219
+ ### ESM
236
220
 
237
- const el = document.querySelector('adapt-cap');
238
- el.client = createConnectClient({ id: 'auto-123' });
221
+ ```typescript
222
+ import { createConnectClient } from '@mochabug/adapt-web/cap';
223
+ import '@mochabug/adapt-web/styles.css';
239
224
 
225
+ const el = document.querySelector('adapt-cap')!;
226
+ el.client = createConnectClient({ id: 'YOUR_ID' });
240
227
  el.addEventListener('adapt-cap-solve', (e) => {
241
228
  console.log('Token:', e.detail.token);
242
- console.log('Expires:', e.detail.expires);
243
- });
244
-
245
- el.addEventListener('adapt-cap-error', (e) => {
246
- console.error('Error:', e.detail.error);
247
229
  });
248
230
  ```
249
231
 
250
- **Attributes:**
232
+ ### Attributes
251
233
 
252
- | Attribute | Type | Description |
253
- |---|---|---|
254
- | `automation-id` | string, required | Automation ID. Changing this recreates the widget. |
255
- | `dark-mode` | boolean | Toggle dark mode styling at runtime. |
256
- | `worker-count` | number | Number of Web Workers for solving (read at creation only). |
234
+ | Attribute | Description |
235
+ |-----------|-------------|
236
+ | `automation-id` | **Required.** Automation ID |
237
+ | `dark-mode` | Enable dark mode |
238
+ | `worker-count` | Number of WASM workers |
257
239
 
258
- **Properties (set via JS):**
240
+ ### JS-only properties
259
241
 
260
- | Property | Type | Description |
261
- |---|---|---|
262
- | `client` | `AutomationClient` | Required. Created via `createConnectClient({ id })`. Widget initializes when both `client` and `automation-id` are set. |
263
- | `i18n` | `CapWidgetI18n` | Custom label overrides (set before `client`). |
264
- | `onSolveCallback` | `(token, expires) => void` | JS callback alternative to the event. |
265
- | `onErrorCallback` | `(error) => void` | JS callback alternative to the event. |
266
-
267
- **Events:**
242
+ | Property | Type |
243
+ |----------|------|
244
+ | `client` | `AutomationClient` **required**, set via JS |
245
+ | `i18n` | `CapWidgetI18n` label overrides (set before `client`) |
268
246
 
269
- | Event | Detail | When |
270
- |---|---|---|
271
- | `adapt-cap-solve` | `{ token: string, expires: Date }` | Challenge solved. |
272
- | `adapt-cap-error` | `{ error: Error }` | Solving failed. |
247
+ ### Events
273
248
 
274
- ### Using AdaptCapWidget (imperative API)
249
+ | Event | Detail |
250
+ |-------|--------|
251
+ | `adapt-cap-solve` | `{ token: string, expires: Date }` |
252
+ | `adapt-cap-error` | `{ error: Error }` |
275
253
 
276
- For full control without custom elements:
254
+ ---
277
255
 
278
- ```typescript
279
- import { AdaptCapWidget } from '@mochabug/adapt-web';
280
- import { createConnectClient } from '@mochabug/adapt-core/connect';
281
-
282
- const widget = new AdaptCapWidget({
283
- container: 'cap-container', // element ID or HTMLElement
284
- automationId: 'auto-123',
285
- client: createConnectClient({ id: 'auto-123' }),
286
- onSolve: (token, expires) => {
287
- console.log('Solved:', token);
288
- },
289
- onError: (error) => {
290
- console.error('Failed:', error);
291
- },
292
- workerCount: 4, // optional
293
- i18n: { // optional
294
- initialState: "Verify you're human"
295
- }
296
- });
256
+ ## Styling
297
257
 
298
- // Toggle dark mode at runtime
299
- widget.setDarkMode(true);
258
+ Three ways to theme, from simplest to most powerful:
300
259
 
301
- // Manual cleanup (called automatically after solve)
302
- widget.destroy();
303
- ```
260
+ ### 1. `theme` prop (recommended)
304
261
 
305
- ---
262
+ Set the `theme` JS property for semantic theming. Derives 30+ CSS variables from a few tokens.
306
263
 
307
- ## Styling
308
-
309
- ### CSS Custom Properties
264
+ ```javascript
265
+ const el = document.querySelector('adapt-automation');
266
+ el.theme = {
267
+ mode: 'dark',
268
+ primary: '#6366f1',
269
+ background: '#0f172a',
270
+ surface: '#1e293b',
271
+ text: '#f1f5f9',
272
+ border: '#334155',
273
+ font: '"Inter", sans-serif',
274
+ };
275
+ ```
310
276
 
311
- All styling is done through CSS custom properties. The widget uses [Cap.js CSS variables](https://capjs.js.org/guide/widget.html#styling) internally — **never use `::part()` selectors**, as they override Cap.js's internal Shadow DOM transitions and break animations.
277
+ **`AdaptTheme` interface:**
278
+
279
+ | Token | Effect |
280
+ |-------|--------|
281
+ | `mode` | `'light'` or `'dark'` — toggles dark mode class |
282
+ | `primary` | Accent color — derives separator, drop target, spinner colors |
283
+ | `background` | Root bg, active tab bg, status card bg |
284
+ | `surface` | Panel content bg, tab bar bg |
285
+ | `text` | Active tab text, status text, cap widget text |
286
+ | `textSecondary` | Inactive tab text |
287
+ | `border` | Tab separators, status card border, cap border |
288
+ | `font` | All panel UI text + cap widget |
289
+ | `vars` | `Record<string, string>` — direct variable overrides (key = name without `--mb-adapt-` prefix) |
290
+
291
+ The `vars` escape hatch lets you override any variable:
292
+
293
+ ```javascript
294
+ el.theme = {
295
+ primary: '#6366f1',
296
+ vars: {
297
+ 'floating-shadow': 'none',
298
+ 'floating-border': '2px solid #6366f1',
299
+ 'cap-border-radius': '0px',
300
+ },
301
+ };
302
+ ```
312
303
 
313
- #### AdaptWebClient variables
304
+ ### 2. CSS custom properties
314
305
 
315
- When using `AdaptWebClient` with `requiresChallenge: true`, the Cap.js widget is styled via `--mb-adapt-cap-*` variables on the `.mb-adapt` root:
306
+ Set `--mb-adapt-*` variables on `.mb-adapt` or any ancestor. No Shadow DOM standard CSS inheritance works.
316
307
 
317
308
  ```css
318
- /* Override on your container or a parent element */
319
309
  .mb-adapt {
320
- /* Widget dimensions */
321
- --mb-adapt-cap-background: #ffffff;
322
- --mb-adapt-cap-border-color: #e2e8f0;
323
- --mb-adapt-cap-border-radius: 16px;
324
- --mb-adapt-cap-height: 72px;
325
- --mb-adapt-cap-width: 380px;
326
- --mb-adapt-cap-padding: 20px 28px;
327
- --mb-adapt-cap-gap: 20px;
328
- --mb-adapt-cap-color: #1e293b;
329
-
330
- /* Checkbox */
331
- --mb-adapt-cap-checkbox-size: 36px;
332
- --mb-adapt-cap-checkbox-border: 2px solid #cbd5e1;
333
- --mb-adapt-cap-checkbox-radius: 10px;
334
- --mb-adapt-cap-checkbox-background: #f8fafc;
335
-
336
- /* Spinner */
337
- --mb-adapt-cap-spinner-color: #6366f1;
338
- --mb-adapt-cap-spinner-bg: #e2e8f0;
339
- --mb-adapt-cap-spinner-thickness: 3px;
340
-
341
- /* Typography */
342
- --mb-adapt-cap-font: inherit;
310
+ --mb-adapt-fork-bg: #ffffff;
311
+ --mb-adapt-fork-tab-bg: #f5f5f5;
312
+ --mb-adapt-fork-tab-color: #1a1a1a;
313
+ --mb-adapt-fork-separator: #e0e0e0;
314
+ }
315
+
316
+ .mb-adapt--dark {
317
+ --mb-adapt-fork-bg: #1e1e1e;
318
+ --mb-adapt-fork-tab-bg: #2a2a2a;
319
+ --mb-adapt-fork-tab-color: #e0e0e0;
320
+ --mb-adapt-fork-separator: #3a3a3a;
343
321
  }
344
322
  ```
345
323
 
346
- Dark mode overrides are applied automatically when `darkMode: true` is set.
324
+ ### 3. Direct CSS on internal classes
347
325
 
348
- #### `<adapt-cap>` / AdaptCapWidget variables
326
+ No Shadow DOM — all internal elements use plain CSS classes. Target them directly for effects that CSS variables can't express: animations, pseudo-elements, transitions, media queries.
349
327
 
350
- The standalone widget uses `--mb-cap-*` variables on the `.mb-adapt-cap` wrapper. These are the defaults:
328
+ **Animated gradient toolbar (liquid glass):**
351
329
 
352
330
  ```css
353
- .mb-adapt-cap {
354
- /* Sizing */
355
- --mb-cap-border-radius: 16px;
356
- --mb-cap-height: 72px;
357
- --mb-cap-width: 320px;
358
- --mb-cap-padding: 18px 22px;
359
- --mb-cap-gap: 16px;
360
-
361
- /* Colors */
362
- --mb-cap-bg: #ffffff;
363
- --mb-cap-border-color: #e5e7eb;
364
- --mb-cap-text-color: #111827;
365
-
366
- /* Checkbox */
367
- --mb-cap-checkbox-size: 30px;
368
- --mb-cap-checkbox-radius: 8px;
369
- --mb-cap-checkbox-border-color: #d1d5db;
370
- --mb-cap-checkbox-bg: #f9fafb;
371
-
372
- /* Spinner */
373
- --mb-cap-spinner-color: #6366f1;
374
- --mb-cap-spinner-bg: #e5e7eb;
375
-
376
- /* Typography */
377
- --mb-cap-font: inherit;
331
+ @keyframes toolbar-glow {
332
+ 0%, 100% { background-position: 0% 50%; }
333
+ 50% { background-position: 100% 50%; }
334
+ }
335
+
336
+ /* Light mode — warm aurora */
337
+ .mb-adapt .mb-group-header {
338
+ background: linear-gradient(
339
+ 135deg,
340
+ rgba(99, 102, 241, 0.08) 0%,
341
+ rgba(168, 85, 247, 0.08) 25%,
342
+ rgba(236, 72, 153, 0.06) 50%,
343
+ rgba(99, 102, 241, 0.08) 100%
344
+ ) !important;
345
+ background-size: 300% 300%;
346
+ animation: toolbar-glow 8s ease infinite;
347
+ }
348
+
349
+ /* Dark mode — deep neon */
350
+ .mb-adapt--dark .mb-group-header {
351
+ background: linear-gradient(
352
+ 135deg,
353
+ rgba(99, 102, 241, 0.15) 0%,
354
+ rgba(168, 85, 247, 0.12) 25%,
355
+ rgba(236, 72, 153, 0.10) 50%,
356
+ rgba(99, 102, 241, 0.15) 100%
357
+ ) !important;
358
+ background-size: 300% 300%;
359
+ animation: toolbar-glow 8s ease infinite;
378
360
  }
379
361
  ```
380
362
 
381
- Dark mode is toggled via `widget.setDarkMode(true)` or the `dark-mode` attribute.
363
+ **Key classes you can target:**
364
+
365
+ | Class | Element |
366
+ |-------|---------|
367
+ | `.mb-group-header` | Tab toolbar |
368
+ | `.mb-tab` | Individual tab |
369
+ | `.mb-tab[data-active="true"]` | Active tab |
370
+ | `.mb-group-content` | Panel content area |
371
+ | `.mb-floating-overlay` | Floating panel container |
372
+ | `.mb-layout-separator` | Resize handle between panels |
373
+ | `.mb-drag-ghost` | Tab drag preview |
374
+ | `.mb-adapt__status-card` | Error/stopped status card |
375
+ | `.mb-adapt__status-icon` | Status card icon |
376
+ | `.mb-adapt-minimized-tab` | Minimized panel tab |
377
+ | `.mb-drop-overlay` | Drop target highlight |
378
+
379
+ All three approaches compose — use `theme` for colors, CSS variables for fine-tuning, and direct class targeting for animations.
380
+
381
+ <details>
382
+ <summary>Full CSS variable reference</summary>
383
+
384
+ ### General
385
+
386
+ | Variable | Light default | Dark default | Description |
387
+ |---|---|---|---|
388
+ | `--mb-adapt-bg` | `transparent` | | Root & group backgrounds |
389
+ | `--mb-adapt-font` | `system-ui, -apple-system, sans-serif` | | All panel UI text |
390
+ | `--mb-adapt-button-hover-bg` | `rgba(128,128,128,0.2)` | `rgba(128,128,128,0.3)` | Close/popout/action button hover |
391
+ | `--mb-adapt-separator-active` | `rgba(59,130,246,0.5)` | `rgba(99,130,246,0.6)` | Resize handle hover/active |
392
+ | `--mb-adapt-border-radius` | `8px` | | Iframe border radius |
393
+
394
+ ### Toolbar and tabs
395
+
396
+ | Variable | Light default | Dark default | Description |
397
+ |---|---|---|---|
398
+ | `--mb-adapt-fork-bg` | `#ffffff` | `#1e1e1e` | Panel content background |
399
+ | `--mb-adapt-fork-tab-bg` | `#f3f3f3` | `#252526` | Toolbar / inactive tab bg |
400
+ | `--mb-adapt-fork-tab-active-bg` | `#ffffff` | `#1e1e1e` | Active tab background |
401
+ | `--mb-adapt-fork-tab-color` | `rgb(51,51,51)` | `#ffffff` | Active tab text |
402
+ | `--mb-adapt-fork-tab-inactive-color` | `rgba(51,51,51,0.7)` | `#969696` | Inactive tab text |
403
+ | `--mb-adapt-fork-separator` | `rgba(128,128,128,0.35)` | `rgb(68,68,68)` | Tab/panel borders |
404
+ | `--mb-adapt-tab-radius` | `0` | | Tab border-radius (use `999px` for pill shape) |
405
+ | `--mb-adapt-tab-shadow` | `none` | | Tab box-shadow |
406
+ | `--mb-adapt-tab-active-shadow` | `none` | | Active tab box-shadow |
407
+ | `--mb-adapt-tab-gap` | `0px` | | Tab margin (spacing between tabs) |
408
+ | `--mb-adapt-tab-padding` | `0 14px` | | Tab padding |
409
+ | `--mb-adapt-tab-font-size` | `13px` | | Tab label font size |
410
+ | `--mb-adapt-toolbar-height` | `40px` | | Toolbar / tab bar height |
411
+ | `--mb-adapt-toolbar-padding` | `0` | | Toolbar inner padding (standard CSS shorthand) |
412
+ | `--mb-adapt-tab-min-width` | `100px` | | Tab minimum width |
413
+ | `--mb-adapt-tab-spacing` | `6px` | | Gap between tab label and action buttons |
414
+
415
+ ### Floating panels (elevation)
416
+
417
+ | Variable | Light default | Dark default | Description |
418
+ |---|---|---|---|
419
+ | `--mb-adapt-floating-shadow` | `0 25px 50px -12px rgba(0,0,0,0.25), 0 12px 24px -8px rgba(0,0,0,0.15)` | `… rgba(0,0,0,0.5), … rgba(0,0,0,0.3)` | Overlay box-shadow |
420
+ | `--mb-adapt-floating-border` | `none` | `1px solid rgba(255,255,255,0.06)` | Overlay border |
421
+ | `--mb-adapt-floating-backdrop` | `none` | | Overlay backdrop-filter |
422
+ | `--mb-adapt-floating-radius` | `8px` | | Overlay border-radius |
423
+ | `--mb-adapt-status-card-shadow` | `0 4px 24px rgba(0,0,0,0.08), 0 2px 8px rgba(0,0,0,0.04)` | `… rgba(0,0,0,0.25), … rgba(0,0,0,0.15)` | Status card box-shadow |
424
+ | `--mb-adapt-drag-ghost-shadow` | `0 4px 12px rgba(0,0,0,0.15)` | `0 4px 12px rgba(0,0,0,0.35)` | Drag ghost box-shadow |
425
+
426
+ ### Drop targets
427
+
428
+ | Variable | Light default | Dark default |
429
+ |---|---|---|
430
+ | `--mb-adapt-drop-header-bg` | `rgba(99,102,241,0.18)` | `rgba(129,140,248,0.22)` |
431
+ | `--mb-adapt-drop-center-bg` | `rgba(99,102,241,0.12)` | `rgba(129,140,248,0.15)` |
432
+ | `--mb-adapt-drop-split-bg` | `rgba(99,102,241,0.14)` | `rgba(129,140,248,0.18)` |
433
+ | `--mb-adapt-drop-border` | `rgba(99,102,241,0.55)` | `rgba(129,140,248,0.6)` |
382
434
 
383
- #### Styling rules
435
+ ### Status cards
384
436
 
385
- 1. **Only use CSS custom properties** to style the Cap.js widget. These are mapped to [Cap.js's own `--cap-*` variables](https://capjs.js.org/guide/widget.html#styling) internally.
437
+ | Variable | Light default | Dark default |
438
+ |---|---|---|
439
+ | `--mb-adapt-status-card-bg` | `#ffffff` | `#1e293b` |
440
+ | `--mb-adapt-status-card-border` | `#e5e7eb` | `#334155` |
441
+ | `--mb-adapt-status-icon-bg` | `#fef2f2` | `#351c1c` |
442
+ | `--mb-adapt-status-text` | `#374151` | `#e2e8f0` |
386
443
 
387
- 2. **Do NOT use `::part()` selectors** on `cap-widget`. Cap.js uses Shadow DOM with internal CSS transitions for the checkbox animation, spinner, and label sliding. Outer `::part()` rules take precedence over Shadow DOM styles and will break these animations.
444
+ ### Cap widget
388
445
 
389
- 3. **Do NOT set `transition`, `transform`, `box-shadow`, or `border-radius` directly on the `cap-widget` element.** These interfere with Cap.js's internal `:host` and `.captcha` styling. Use wrapper elements if you need hover effects or shadows.
446
+ | Variable | Light default | Dark default |
447
+ |---|---|---|
448
+ | `--mb-adapt-cap-background` | `#ffffff` | `#1e293b` |
449
+ | `--mb-adapt-cap-border-color` | `#e2e8f0` | `#334155` |
450
+ | `--mb-adapt-cap-border-radius` | `16px` | |
451
+ | `--mb-adapt-cap-height` | `72px` | |
452
+ | `--mb-adapt-cap-width` | `380px` | |
453
+ | `--mb-adapt-cap-padding` | `20px 28px` | |
454
+ | `--mb-adapt-cap-gap` | `20px` | |
455
+ | `--mb-adapt-cap-color` | `#1e293b` | `#f1f5f9` |
456
+ | `--mb-adapt-cap-checkbox-size` | `36px` | |
457
+ | `--mb-adapt-cap-checkbox-border` | `2px solid #cbd5e1` | `2px solid #475569` |
458
+ | `--mb-adapt-cap-checkbox-radius` | `10px` | |
459
+ | `--mb-adapt-cap-checkbox-background` | `#f8fafc` | `#0f172a` |
460
+ | `--mb-adapt-cap-spinner-color` | `#6366f1` | `#818cf8` |
461
+ | `--mb-adapt-cap-spinner-bg` | `#e2e8f0` | `#334155` |
462
+ | `--mb-adapt-cap-spinner-thickness` | `3px` | |
463
+ | `--mb-adapt-cap-font` | `inherit` | |
464
+
465
+ ### Z-index / stacking
466
+
467
+ | Variable | Default | Description |
468
+ |---|---|---|
469
+ | `--mb-adapt-z-base` | `0` | Base z-index offset — added to all internal z-index values |
390
470
 
391
- ### General layout variables
471
+ Set `--mb-adapt-z-base` to shift all internal z-index values. Useful when embedding inside modals or drawers that have their own stacking context. Example: `--mb-adapt-z-base: 10000` lifts all layers by 10000.
392
472
 
393
- ```css
394
- .mb-adapt {
395
- --mb-adapt-border-radius: 8px;
396
- --mb-adapt-backdrop-color: rgba(0, 0, 0, 0.5);
397
- --mb-adapt-backdrop-z: 999;
398
- --mb-adapt-dialog-z: 1000;
399
- --mb-adapt-dialog-min-height: 300px;
400
- --mb-adapt-drag-handle-width: 4px;
401
- --mb-adapt-drag-handle-color: transparent;
402
- --mb-adapt-drag-handle-hover: transparent;
403
- --mb-adapt-drag-indicator: #94a3b8;
404
- --mb-adapt-drag-indicator-hover: #64748b;
405
- --mb-adapt-toolbar-height: 36px;
406
- --mb-adapt-toolbar-bg: #f3f4f6;
407
- --mb-adapt-toolbar-border: #e5e7eb;
408
- --mb-adapt-toolbar-color: #6b7280;
409
- --mb-adapt-toolbar-btn-hover: #e5e7eb;
410
- --mb-adapt-banner-height: 40px;
411
- --mb-adapt-banner-bg: #f9fafb;
412
- --mb-adapt-banner-border: #e5e7eb;
413
- --mb-adapt-button-color: #374151;
414
- --mb-adapt-button-hover-bg: #e5e7eb;
415
- --mb-adapt-fork-border: rgba(0, 0, 0, 0.10);
416
- --mb-adapt-fork-shadow: 0 1px 3px rgba(0, 0, 0, 0.08), 0 4px 12px rgba(0, 0, 0, 0.04);
417
- }
418
- ```
473
+ Internal stacking order from low to high: separators (1), resize handles (10), minimized tabs (100), floating panels (100000+), status/cap (200000), confirm dialog (300000), drop targets (999998), drag ghost (999999). All values are offset by `--mb-adapt-z-base`.
419
474
 
420
- ## All options
475
+ </details>
421
476
 
422
- ```typescript
423
- {
424
- container: string | HTMLElement; // required - DOM element or id
425
- id: string; // required - automation id
426
-
427
- // Auth (pick one)
428
- authToken?: string; // starts new session
429
- sessionToken?: string; // uses pre-created session (SSR)
430
- inheritToken?: string; // joins existing session
431
- inheritFrom?: { hash: string } | { param: string };
432
-
433
- // Advanced start
434
- transmitter?: string; // specific transmitter to start from
435
- signals?: Record<string, SignalValue>;
436
-
437
- // Challenge (proof-of-work)
438
- requiresChallenge?: boolean; // show Cap.js widget before start
439
- challengeToken?: string; // skip widget with pre-solved token
440
- capWidgetOptions?: {
441
- workerCount?: number;
442
- i18n?: {
443
- initialState?: string;
444
- verifyingLabel?: string;
445
- solvedLabel?: string;
446
- errorLabel?: string;
447
- };
448
- };
449
-
450
- // Fork display
451
- forkDisplay?:
452
- | { mode: 'side-by-side'; split?: number }
453
- | { mode: 'dialog'; backdropClose?: boolean; resizeToContent?: boolean };
454
-
455
- // Appearance
456
- darkMode?: boolean;
457
- autoResizing?: boolean;
458
-
459
- // Callbacks
460
- onSession?: (status: StatusJson, fork?: string) => void;
461
- onOutput?: (output: Output) => void;
462
- onForkActive?: (active: boolean) => void;
463
-
464
- // Session persistence
465
- persist?: boolean | { storage?: 'session' | 'local'; ttl?: number };
466
-
467
- // Custom status text
468
- text?: {
469
- stopped?: string;
470
- sessionExpired?: string;
471
- resourceExhausted?: string;
472
- notFound?: string;
473
- sessionNotFound?: string;
474
- permissionDenied?: string;
475
- error?: string;
476
- restartButton?: string;
477
- };
478
-
479
- // Styling
480
- classNames?: { root?, wrapper?, frame?, iframe?, dialog?, ... };
481
- styles?: Partial<CSSStyleDeclaration>;
482
- }
483
- ```
477
+ ---
484
478
 
485
479
  ## License
486
480