@mochabug/adapt-web 1.0.1-rc.8 → 1.0.1-rc.9

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 (59) hide show
  1. package/README.md +373 -382
  2. package/dist/README.md +478 -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 +96 -0
  11. package/dist/esm/css-panel.js +854 -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 -2404
  15. package/dist/esm/panel-manager.js +1 -0
  16. package/dist/esm/panel-setup.js +1 -0
  17. package/dist/esm/types.js +0 -1
  18. package/dist/esm/umd-cap-entry.js +1 -0
  19. package/dist/esm/umd-entry.js +1 -0
  20. package/dist/esm/umd-full-entry.js +1 -0
  21. package/dist/esm/umd-headless-entry.js +1 -0
  22. package/dist/styles.css +951 -0
  23. package/dist/types/AdaptAutomationElement.d.ts +15 -5
  24. package/dist/types/adapt.d.ts +27 -0
  25. package/dist/types/cap-adapter.d.ts +5 -0
  26. package/dist/types/cap.d.ts +24 -0
  27. package/dist/types/core.d.ts +20 -0
  28. package/dist/types/css-cap.d.ts +1 -0
  29. package/dist/types/css-panel.d.ts +1 -0
  30. package/dist/types/elements.d.ts +0 -1
  31. package/dist/types/index.d.ts +139 -82
  32. package/dist/types/panel-manager.d.ts +540 -0
  33. package/dist/types/panel-setup.d.ts +231 -0
  34. package/dist/types/types.d.ts +76 -40
  35. package/dist/types/umd-cap-entry.d.ts +1 -0
  36. package/dist/types/umd-entry.d.ts +2 -0
  37. package/dist/types/umd-full-entry.d.ts +2 -0
  38. package/dist/types/umd-headless-entry.d.ts +2 -0
  39. package/dist/umd/adapt-core.js +6702 -0
  40. package/dist/umd/adapt-core.js.br +0 -0
  41. package/dist/umd/adapt-core.min.js +4 -0
  42. package/dist/umd/adapt-core.min.js.br +0 -0
  43. package/dist/umd/adapt-web.cap.js +6987 -0
  44. package/dist/umd/adapt-web.cap.js.br +0 -0
  45. package/dist/umd/adapt-web.cap.min.js +101 -0
  46. package/dist/umd/adapt-web.cap.min.js.br +0 -0
  47. package/dist/umd/adapt-web.core.js +12436 -0
  48. package/dist/umd/adapt-web.core.js.br +0 -0
  49. package/dist/umd/adapt-web.core.min.js +857 -0
  50. package/dist/umd/adapt-web.core.min.js.br +0 -0
  51. package/dist/umd/adapt-web.js +6674 -2915
  52. package/dist/umd/adapt-web.js.br +0 -0
  53. package/dist/umd/adapt-web.min.js +729 -480
  54. package/dist/umd/adapt-web.min.js.br +0 -0
  55. package/dist/umd/cap_wasm.js.br +0 -0
  56. package/dist/umd/cap_wasm_bg.wasm.br +0 -0
  57. package/dist/umd/styles.css +951 -0
  58. package/dist/umd/styles.css.br +0 -0
  59. package/package.json +28 -14
package/README.md CHANGED
@@ -6,482 +6,473 @@ 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>
53
-
54
- <!-- pin exact -->
55
- <script src="https://cdn.jsdelivr.net/npm/@mochabug/adapt-web@1.0.0/dist/umd/adapt-web.min.js"></script>
56
-
57
- <!-- pin minor -->
58
- <script src="https://cdn.jsdelivr.net/npm/@mochabug/adapt-web@1.0/dist/umd/adapt-web.min.js"></script>
59
-
60
- <!-- unpkg works too -->
61
- <script src="https://unpkg.com/@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>
62
66
  ```
63
67
 
64
- ## SSR (keep auth token server-side)
68
+ ### Embedded — no `<head>` access (Wix, Squarespace, WordPress, etc.)
65
69
 
66
- Create session on server, pass session token to client:
70
+ Just the element and script. CSS is auto-injected at runtime.
67
71
 
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
- });
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>
79
75
  ```
80
76
 
81
- ## Session inheritance
82
-
83
- Join existing session instead of starting new:
77
+ Without challenges:
84
78
 
85
- ```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
- });
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>
106
82
  ```
107
83
 
108
- ## Fork display (for AI agents with UI)
84
+ ### ESM
109
85
 
110
86
  ```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
- });
117
-
118
- // modal dialog
119
- new AdaptWebClient({
120
- container: 'auto',
121
- id: 'auto-123',
122
- forkDisplay: { mode: 'dialog', backdropClose: true, resizeToContent: true }
123
- });
87
+ import '@mochabug/adapt-web'; // with challenges
88
+ import '@mochabug/adapt-web/styles.css';
124
89
  ```
125
90
 
126
- ## Callbacks
127
-
128
91
  ```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
- });
92
+ import '@mochabug/adapt-web/core'; // without challenges (lighter)
93
+ import '@mochabug/adapt-web/styles.css';
135
94
  ```
136
95
 
137
- ## Advanced: Multiple transmitters or initial signals
138
-
139
- For automations with multiple entry points or when you need to pass initial data:
140
-
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
- });
151
-
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
- };
164
-
165
- new AdaptWebClient({
166
- container: 'auto',
167
- id: 'auto-123',
168
- authToken: 'your-token',
169
- transmitter: 'file-processor',
170
- signals
171
- });
96
+ ```html
97
+ <adapt-automation automation-id="YOUR_ID" style="height: 600px"></adapt-automation>
172
98
  ```
173
99
 
174
- ---
175
-
176
- ## Proof-of-Work Challenge (Cap.js Widget)
177
-
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.
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
+ | `fork-display-mode` | `side-by-side` (default) or `dialog` |
112
+ | `side-by-side-split` | Split percentage, e.g. `60` |
113
+ | `dark-mode` | Enable dark mode |
114
+ | `auto-resizing` | Container follows iframe content height |
115
+ | `allow-floating` | Set to `"false"` to hide pop-out buttons and block user-initiated floating |
116
+ | `allow-docking` | Set to `"false"` to hide dock buttons and block user-initiated docking |
117
+ | `allow-dialog-docking` | Set to `"false"` to prevent tab splits inside floating dialog overlays |
118
+ | `floating-auto-resize` | Floating overlays auto-resize based on iframe content height |
119
+ | `persist` | Persist session across page refreshes |
120
+ | `confirm-on-close` | Show a confirmation dialog before the user leaves the page while a session is active |
121
+
122
+ ### JS-only properties
123
+
124
+ Set via element reference — not available as HTML attributes.
125
+
126
+ | Property | Type |
127
+ |----------|------|
128
+ | `signals` | `Record<string, SignalValue>` |
129
+ | `capWidgetOptions` | `{ workerCount?: number; i18n?: CapWidgetI18n }` |
130
+ | `inheritFrom` | `{ hash: string } \| { param: string }` |
131
+ | `classNames` | `{ root?: string; iframe?: string; statusMessage?: string; statusCard?: string }` |
132
+ | `styles` | `Partial<CSSStyleDeclaration>` |
133
+ | `persistOptions` | `{ storage?: 'session' \| 'local'; ttl?: number; key?: string }` |
134
+ | `text` | `StatusText` |
135
+
136
+ ### Events
137
+
138
+ | Event | Detail |
139
+ |-------|--------|
140
+ | `adapt-session` | `{ status: StatusJson, fork?: string }` |
141
+ | `adapt-output` | `{ output: Output }` |
142
+ | `adapt-fork-active` | `{ active: boolean }` |
143
+
144
+ ### Methods
145
+
146
+ | Method | Description |
147
+ |--------|-------------|
148
+ | `newSession()` | Ends the current session and starts a new one. Returns a `Promise<void>`. |
179
149
 
180
- ### Using with AdaptWebClient
181
-
182
- Set `requiresChallenge: true` and the widget appears automatically, centered inside the container, before the automation starts:
150
+ ---
183
151
 
184
- ```typescript
185
- new AdaptWebClient({
186
- container: 'auto',
187
- id: 'auto-123',
188
- requiresChallenge: true
189
- });
190
- ```
152
+ ## 2. `<adapt-cap>`
191
153
 
192
- Optionally customize the widget labels and worker count:
154
+ Standalone proof-of-work challenge widget. Use when you manage the automation client yourself.
193
155
 
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
- ```
156
+ Requires a `client` JS property — set it after the element is in the DOM.
210
157
 
211
- Or skip the widget entirely by providing a pre-solved token:
158
+ ### Optimal
212
159
 
213
- ```typescript
214
- new AdaptWebClient({
215
- container: 'auto',
216
- id: 'auto-123',
217
- challengeToken: presolvedToken
218
- });
160
+ ```html
161
+ <head>
162
+ <link rel="preload" href="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js" as="script">
163
+ <link rel="stylesheet" href="https://cdn.mochabug.com/adapt/web/__VERSION__/styles.css">
164
+ </head>
165
+ <body>
166
+ <adapt-cap automation-id="YOUR_ID"></adapt-cap>
167
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js"></script>
168
+ <script>
169
+ var el = document.querySelector('adapt-cap');
170
+ el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
171
+ el.addEventListener('adapt-cap-solve', function(e) {
172
+ console.log('Token:', e.detail.token);
173
+ });
174
+ </script>
175
+ </body>
219
176
  ```
220
177
 
221
- ### Using the `<adapt-cap>` web component
222
-
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).
178
+ ### Embedded
224
179
 
225
180
  ```html
226
- <adapt-cap
227
- automation-id="auto-123"
228
- dark-mode
229
- worker-count="4"
230
- ></adapt-cap>
181
+ <adapt-cap automation-id="YOUR_ID"></adapt-cap>
182
+ <script src="https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js"></script>
183
+ <script>
184
+ var el = document.querySelector('adapt-cap');
185
+ el.client = MbAdapt.createConnectClient({ id: 'YOUR_ID' });
186
+ el.addEventListener('adapt-cap-solve', function(e) {
187
+ console.log('Token:', e.detail.token);
188
+ });
189
+ </script>
231
190
  ```
232
191
 
233
- ```typescript
234
- import '@mochabug/adapt-web/elements';
235
- import { createConnectClient } from '@mochabug/adapt-core/connect';
192
+ ### ESM
236
193
 
237
- const el = document.querySelector('adapt-cap');
238
- el.client = createConnectClient({ id: 'auto-123' });
194
+ ```typescript
195
+ import { createConnectClient } from '@mochabug/adapt-web/cap';
196
+ import '@mochabug/adapt-web/styles.css';
239
197
 
198
+ const el = document.querySelector('adapt-cap')!;
199
+ el.client = createConnectClient({ id: 'YOUR_ID' });
240
200
  el.addEventListener('adapt-cap-solve', (e) => {
241
201
  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
202
  });
248
203
  ```
249
204
 
250
- **Attributes:**
205
+ ### Attributes
251
206
 
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). |
207
+ | Attribute | Description |
208
+ |-----------|-------------|
209
+ | `automation-id` | **Required.** Automation ID |
210
+ | `dark-mode` | Enable dark mode |
211
+ | `worker-count` | Number of WASM workers |
257
212
 
258
- **Properties (set via JS):**
213
+ ### JS-only properties
259
214
 
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. |
215
+ | Property | Type |
216
+ |----------|------|
217
+ | `client` | `AutomationClient` **required**, set via JS |
218
+ | `i18n` | `CapWidgetI18n` label overrides (set before `client`) |
266
219
 
267
- **Events:**
220
+ ### Events
268
221
 
269
- | Event | Detail | When |
270
- |---|---|---|
271
- | `adapt-cap-solve` | `{ token: string, expires: Date }` | Challenge solved. |
272
- | `adapt-cap-error` | `{ error: Error }` | Solving failed. |
222
+ | Event | Detail |
223
+ |-------|--------|
224
+ | `adapt-cap-solve` | `{ token: string, expires: Date }` |
225
+ | `adapt-cap-error` | `{ error: Error }` |
273
226
 
274
- ### Using AdaptCapWidget (imperative API)
227
+ ---
275
228
 
276
- For full control without custom elements:
229
+ ## Styling
277
230
 
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
- });
231
+ All visuals are controlled via CSS custom properties on `.mb-adapt`. The `dark-mode` attribute on the element automatically switches to dark defaults, but you can override any variable for either mode.
297
232
 
298
- // Toggle dark mode at runtime
299
- widget.setDarkMode(true);
233
+ ### Matching your site's toolbar
300
234
 
301
- // Manual cleanup (called automatically after solve)
302
- widget.destroy();
303
- ```
235
+ Map your site's existing design tokens to the panel toolbar. These six variables control almost everything you see in the tab bar:
304
236
 
305
- ---
237
+ ```css
238
+ /* Light mode — derive from your site's surface/text colors */
239
+ .mb-adapt {
240
+ --mb-adapt-fork-bg: #ffffff; /* panel content background */
241
+ --mb-adapt-fork-tab-bg: #f5f5f5; /* inactive tab / toolbar background */
242
+ --mb-adapt-fork-tab-active-bg: #ffffff; /* active tab background */
243
+ --mb-adapt-fork-tab-color: #1a1a1a; /* active tab text */
244
+ --mb-adapt-fork-tab-inactive-color: #888; /* inactive tab text */
245
+ --mb-adapt-fork-separator: #e0e0e0; /* borders between tabs & panels */
246
+ }
306
247
 
307
- ## Styling
248
+ /* Dark mode — add `dark-mode` attribute, then override */
249
+ .mb-adapt[dark-mode] {
250
+ --mb-adapt-fork-bg: #1e1e1e;
251
+ --mb-adapt-fork-tab-bg: #2a2a2a;
252
+ --mb-adapt-fork-tab-active-bg: #1e1e1e;
253
+ --mb-adapt-fork-tab-color: #e0e0e0;
254
+ --mb-adapt-fork-tab-inactive-color: #777;
255
+ --mb-adapt-fork-separator: #3a3a3a;
256
+ }
257
+ ```
308
258
 
309
- ### CSS Custom Properties
259
+ **Typical mapping from your site's design system:**
310
260
 
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.
261
+ | Your site has | Maps to |
262
+ |---|---|
263
+ | Surface / card background | `--mb-adapt-fork-bg` |
264
+ | Secondary / muted background | `--mb-adapt-fork-tab-bg` |
265
+ | Primary text color | `--mb-adapt-fork-tab-color` |
266
+ | Muted / secondary text | `--mb-adapt-fork-tab-inactive-color` |
267
+ | Border / divider color | `--mb-adapt-fork-separator` |
268
+ | Accent color | `--mb-adapt-separator-active` (resize handle highlight) |
269
+ | Interactive hover tint | `--mb-adapt-button-hover-bg` |
312
270
 
313
- #### AdaptWebClient variables
271
+ ### Custom theme (light & dark)
314
272
 
315
- When using `AdaptWebClient` with `requiresChallenge: true`, the Cap.js widget is styled via `--mb-adapt-cap-*` variables on the `.mb-adapt` root:
273
+ A more complete example mapping a full brand palette primary, secondary, and accent colors — to Adapt's CSS variables for both light and dark modes:
316
274
 
317
275
  ```css
318
- /* Override on your container or a parent element */
276
+ /*
277
+ * Example: brand theme using primary / secondary / accent colors.
278
+ * Maps your design-system tokens to Adapt's CSS variables for both modes.
279
+ */
280
+
281
+ /* ── Light mode ────────────────────────────────── */
319
282
  .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;
283
+ /* Brand palette */
284
+ --mb-adapt-fork-bg: #ffffff; /* surface */
285
+ --mb-adapt-fork-tab-bg: #f0f4ff; /* primary-50 */
286
+ --mb-adapt-fork-tab-active-bg: #ffffff; /* surface */
287
+ --mb-adapt-fork-tab-color: #1e293b; /* on-surface */
288
+ --mb-adapt-fork-tab-inactive-color: #64748b; /* on-surface-muted */
289
+ --mb-adapt-fork-separator: #cbd5e1; /* outline */
290
+
291
+ /* Accent — resize handle highlight */
292
+ --mb-adapt-separator-active: rgba(79, 70, 229, 0.5); /* primary */
293
+
294
+ /* Cap widget */
295
+ --mb-adapt-cap-background: #ffffff;
296
+ --mb-adapt-cap-border-color: #e2e8f0;
297
+ --mb-adapt-cap-color: #1e293b;
298
+ --mb-adapt-cap-spinner-color: #4f46e5; /* primary */
299
+
300
+ /* Status cards */
301
+ --mb-adapt-status-card-bg: #ffffff;
302
+ --mb-adapt-status-card-border: #e2e8f0;
303
+ --mb-adapt-status-text: #334155;
343
304
  }
344
- ```
345
305
 
346
- Dark mode overrides are applied automatically when `darkMode: true` is set.
306
+ /* ── Dark mode ─────────────────────────────────── */
307
+ .mb-adapt[dark-mode] {
308
+ --mb-adapt-fork-bg: #0f172a; /* surface-dark */
309
+ --mb-adapt-fork-tab-bg: #1e293b; /* primary-900 */
310
+ --mb-adapt-fork-tab-active-bg: #0f172a; /* surface-dark */
311
+ --mb-adapt-fork-tab-color: #f1f5f9; /* on-surface-dark */
312
+ --mb-adapt-fork-tab-inactive-color: #94a3b8; /* muted-dark */
313
+ --mb-adapt-fork-separator: #334155; /* outline-dark */
314
+
315
+ --mb-adapt-separator-active: rgba(129, 140, 248, 0.6); /* primary-light */
316
+
317
+ --mb-adapt-cap-background: #1e293b;
318
+ --mb-adapt-cap-border-color: #334155;
319
+ --mb-adapt-cap-color: #f1f5f9;
320
+ --mb-adapt-cap-spinner-color: #818cf8; /* primary-light */
321
+
322
+ --mb-adapt-status-card-bg: #1e293b;
323
+ --mb-adapt-status-card-border: #334155;
324
+ --mb-adapt-status-text: #e2e8f0;
325
+ }
326
+ ```
347
327
 
348
- #### `<adapt-cap>` / AdaptCapWidget variables
328
+ ### Font
349
329
 
350
- The standalone widget uses `--mb-cap-*` variables on the `.mb-adapt-cap` wrapper. These are the defaults:
330
+ Set `--mb-adapt-font` to match your site's typeface. This applies to tab labels, status messages, drag ghosts, and all panel UI text.
351
331
 
352
332
  ```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;
333
+ .mb-adapt {
334
+ --mb-adapt-font: "Inter", sans-serif;
378
335
  }
379
336
  ```
380
337
 
381
- Dark mode is toggled via `widget.setDarkMode(true)` or the `dark-mode` attribute.
382
-
383
- #### Styling rules
338
+ ### Elevation and borders
384
339
 
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.
340
+ Floating panels, status cards, and drag ghosts each have independent shadow, border, and radius variables. Use these to match your site's elevation system.
386
341
 
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.
342
+ ```css
343
+ /* Subtle, modern elevation */
344
+ .mb-adapt {
345
+ --mb-adapt-floating-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
346
+ --mb-adapt-floating-border: 1px solid rgba(0, 0, 0, 0.06);
347
+ --mb-adapt-floating-radius: 12px;
348
+ --mb-adapt-floating-backdrop: none;
349
+
350
+ --mb-adapt-status-card-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
351
+ --mb-adapt-drag-ghost-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
352
+ --mb-adapt-border-radius: 8px; /* iframe border radius */
353
+ }
388
354
 
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.
355
+ /* Dark mode increase shadow density, add subtle light border */
356
+ .mb-adapt[dark-mode] {
357
+ --mb-adapt-floating-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
358
+ --mb-adapt-floating-border: 1px solid rgba(255, 255, 255, 0.08);
359
+ --mb-adapt-status-card-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
360
+ --mb-adapt-drag-ghost-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
361
+ }
362
+ ```
390
363
 
391
- ### General layout variables
364
+ **Frosted glass effect** — set a translucent background and enable `backdrop-filter`:
392
365
 
393
366
  ```css
394
367
  .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);
368
+ --mb-adapt-fork-bg: rgba(255, 255, 255, 0.7);
369
+ --mb-adapt-fork-tab-bg: rgba(245, 245, 245, 0.5);
370
+ --mb-adapt-floating-backdrop: blur(16px) saturate(180%);
371
+ --mb-adapt-floating-border: 1px solid rgba(255, 255, 255, 0.2);
372
+ --mb-adapt-floating-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
417
373
  }
418
374
  ```
419
375
 
420
- ## All options
376
+ **Flat / borderless** — remove all elevation:
421
377
 
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>;
378
+ ```css
379
+ .mb-adapt {
380
+ --mb-adapt-floating-shadow: none;
381
+ --mb-adapt-floating-border: 1px solid var(--mb-adapt-fork-separator);
382
+ --mb-adapt-floating-radius: 4px;
383
+ --mb-adapt-status-card-shadow: none;
384
+ --mb-adapt-drag-ghost-shadow: none;
482
385
  }
483
386
  ```
484
387
 
388
+ **Typical mapping from your site's design system:**
389
+
390
+ | Your site has | Maps to |
391
+ |---|---|
392
+ | Card shadow / `--shadow-lg` | `--mb-adapt-floating-shadow` |
393
+ | Card border / `--border-subtle` | `--mb-adapt-floating-border` |
394
+ | Card radius / `--radius-lg` | `--mb-adapt-floating-radius` |
395
+ | Tooltip/popover shadow | `--mb-adapt-status-card-shadow`, `--mb-adapt-drag-ghost-shadow` |
396
+ | Glass/blur effect | `--mb-adapt-floating-backdrop` |
397
+
398
+ <details>
399
+ <summary>Full CSS variable reference</summary>
400
+
401
+ ### General
402
+
403
+ | Variable | Light default | Dark default | Description |
404
+ |---|---|---|---|
405
+ | `--mb-adapt-bg` | `transparent` | | Root & group backgrounds |
406
+ | `--mb-adapt-font` | `system-ui, -apple-system, sans-serif` | | All panel UI text |
407
+ | `--mb-adapt-button-hover-bg` | `rgba(128,128,128,0.2)` | `rgba(128,128,128,0.3)` | Close/popout/action button hover |
408
+ | `--mb-adapt-separator-active` | `rgba(59,130,246,0.5)` | `rgba(99,130,246,0.6)` | Resize handle hover/active |
409
+ | `--mb-adapt-border-radius` | `8px` | | Iframe border radius |
410
+
411
+ ### Toolbar and tabs
412
+
413
+ | Variable | Light default | Dark default | Description |
414
+ |---|---|---|---|
415
+ | `--mb-adapt-fork-bg` | `#ffffff` | `#1e1e1e` | Panel content background |
416
+ | `--mb-adapt-fork-tab-bg` | `#f3f3f3` | `#252526` | Toolbar / inactive tab bg |
417
+ | `--mb-adapt-fork-tab-active-bg` | `#ffffff` | `#1e1e1e` | Active tab background |
418
+ | `--mb-adapt-fork-tab-color` | `rgb(51,51,51)` | `#ffffff` | Active tab text |
419
+ | `--mb-adapt-fork-tab-inactive-color` | `rgba(51,51,51,0.7)` | `#969696` | Inactive tab text |
420
+ | `--mb-adapt-fork-separator` | `rgba(128,128,128,0.35)` | `rgb(68,68,68)` | Tab/panel borders |
421
+
422
+ ### Floating panels (elevation)
423
+
424
+ | Variable | Light default | Dark default | Description |
425
+ |---|---|---|---|
426
+ | `--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 |
427
+ | `--mb-adapt-floating-border` | `none` | `1px solid rgba(255,255,255,0.06)` | Overlay border |
428
+ | `--mb-adapt-floating-backdrop` | `none` | | Overlay backdrop-filter |
429
+ | `--mb-adapt-floating-radius` | `8px` | | Overlay border-radius |
430
+ | `--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 |
431
+ | `--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 |
432
+
433
+ ### Drop targets
434
+
435
+ | Variable | Light default | Dark default |
436
+ |---|---|---|
437
+ | `--mb-adapt-drop-header-bg` | `rgba(99,102,241,0.18)` | `rgba(129,140,248,0.22)` |
438
+ | `--mb-adapt-drop-center-bg` | `rgba(99,102,241,0.12)` | `rgba(129,140,248,0.15)` |
439
+ | `--mb-adapt-drop-split-bg` | `rgba(99,102,241,0.14)` | `rgba(129,140,248,0.18)` |
440
+ | `--mb-adapt-drop-border` | `rgba(99,102,241,0.55)` | `rgba(129,140,248,0.6)` |
441
+
442
+ ### Status cards
443
+
444
+ | Variable | Light default | Dark default |
445
+ |---|---|---|
446
+ | `--mb-adapt-status-card-bg` | `#ffffff` | `#1e293b` |
447
+ | `--mb-adapt-status-card-border` | `#e5e7eb` | `#334155` |
448
+ | `--mb-adapt-status-icon-bg` | `#fef2f2` | `#351c1c` |
449
+ | `--mb-adapt-status-text` | `#374151` | `#e2e8f0` |
450
+
451
+ ### Cap widget
452
+
453
+ | Variable | Light default | Dark default |
454
+ |---|---|---|
455
+ | `--mb-adapt-cap-background` | `#ffffff` | `#1e293b` |
456
+ | `--mb-adapt-cap-border-color` | `#e2e8f0` | `#334155` |
457
+ | `--mb-adapt-cap-border-radius` | `16px` | |
458
+ | `--mb-adapt-cap-height` | `72px` | |
459
+ | `--mb-adapt-cap-width` | `380px` | |
460
+ | `--mb-adapt-cap-padding` | `20px 28px` | |
461
+ | `--mb-adapt-cap-gap` | `20px` | |
462
+ | `--mb-adapt-cap-color` | `#1e293b` | `#f1f5f9` |
463
+ | `--mb-adapt-cap-checkbox-size` | `36px` | |
464
+ | `--mb-adapt-cap-checkbox-border` | `2px solid #cbd5e1` | `2px solid #475569` |
465
+ | `--mb-adapt-cap-checkbox-radius` | `10px` | |
466
+ | `--mb-adapt-cap-checkbox-background` | `#f8fafc` | `#0f172a` |
467
+ | `--mb-adapt-cap-spinner-color` | `#6366f1` | `#818cf8` |
468
+ | `--mb-adapt-cap-spinner-bg` | `#e2e8f0` | `#334155` |
469
+ | `--mb-adapt-cap-spinner-thickness` | `3px` | |
470
+ | `--mb-adapt-cap-font` | `inherit` | |
471
+
472
+ </details>
473
+
474
+ ---
475
+
485
476
  ## License
486
477
 
487
478
  ISC (c) mochabug AB