@mochabug/adapt-angular 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.
- package/README.md +502 -0
- package/dist/esm/adapt-automation.component.d.ts +60 -0
- package/dist/esm/adapt-automation.component.js +177 -0
- package/dist/esm/adapt-cap.component.d.ts +31 -0
- package/dist/esm/adapt-cap.component.js +82 -0
- package/dist/esm/cap.d.ts +3 -0
- package/dist/esm/cap.js +4 -0
- package/dist/esm/core.d.ts +2 -0
- package/dist/esm/core.js +3 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +4 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
# @mochabug/adapt-angular
|
|
2
|
+
|
|
3
|
+
Angular component for Adapt.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @mochabug/adapt-angular
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Requires Angular 19 or later.
|
|
10
|
+
|
|
11
|
+
## Quickstart
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { Component } from '@angular/core';
|
|
15
|
+
import { AdaptAutomation } from '@mochabug/adapt-angular';
|
|
16
|
+
|
|
17
|
+
@Component({
|
|
18
|
+
selector: 'app-root',
|
|
19
|
+
standalone: true,
|
|
20
|
+
imports: [AdaptAutomation],
|
|
21
|
+
template: `
|
|
22
|
+
<mb-adapt-automation [automationId]="'auto-123'" style="height: 600px;" />
|
|
23
|
+
`,
|
|
24
|
+
})
|
|
25
|
+
export class AppComponent {}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
With authentication:
|
|
29
|
+
|
|
30
|
+
```html
|
|
31
|
+
<mb-adapt-automation [automationId]="'auto-123'" [authToken]="'your-token'" style="height: 600px;" />
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
With proof-of-work challenge:
|
|
35
|
+
|
|
36
|
+
```html
|
|
37
|
+
<mb-adapt-automation [automationId]="'auto-123'" [requiresChallenge]="true" style="height: 600px;" />
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## SSR (Angular Universal / SSR)
|
|
41
|
+
|
|
42
|
+
Keep auth token on server:
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
import { Component, OnInit } from '@angular/core';
|
|
46
|
+
import { AdaptAutomation } from '@mochabug/adapt-angular';
|
|
47
|
+
import { startSession } from '@mochabug/adapt-core';
|
|
48
|
+
|
|
49
|
+
@Component({
|
|
50
|
+
selector: 'app-root',
|
|
51
|
+
standalone: true,
|
|
52
|
+
imports: [AdaptAutomation],
|
|
53
|
+
template: `
|
|
54
|
+
@if (sessionToken) {
|
|
55
|
+
<mb-adapt-automation [automationId]="'auto-123'" [sessionToken]="sessionToken" style="height: 600px;" />
|
|
56
|
+
}
|
|
57
|
+
`,
|
|
58
|
+
})
|
|
59
|
+
export class AppComponent implements OnInit {
|
|
60
|
+
sessionToken?: string;
|
|
61
|
+
|
|
62
|
+
async ngOnInit() {
|
|
63
|
+
const authToken = await getAuthTokenFromBackend();
|
|
64
|
+
const { token } = await startSession({ id: 'auto-123' }, authToken);
|
|
65
|
+
this.sessionToken = token;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Session inheritance
|
|
71
|
+
|
|
72
|
+
```html
|
|
73
|
+
<!-- direct -->
|
|
74
|
+
<mb-adapt-automation [automationId]="'auto-123'" [inheritToken]="'token-from-parent'" />
|
|
75
|
+
|
|
76
|
+
<!-- from URL hash: example.com#mb_session=xxx -->
|
|
77
|
+
<mb-adapt-automation [automationId]="'auto-123'" [inheritFrom]="{ hash: 'mb_session' }" />
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Fork display
|
|
81
|
+
|
|
82
|
+
```html
|
|
83
|
+
<!-- side-by-side (default) -->
|
|
84
|
+
<mb-adapt-automation [automationId]="'auto-123'" [forkDisplay]="{ mode: 'side-by-side', split: 60 }" />
|
|
85
|
+
|
|
86
|
+
<!-- dialog -->
|
|
87
|
+
<mb-adapt-automation [automationId]="'auto-123'" [forkDisplay]="{ mode: 'dialog' }" />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Events
|
|
91
|
+
|
|
92
|
+
```html
|
|
93
|
+
<mb-adapt-automation
|
|
94
|
+
[automationId]="'auto-123'"
|
|
95
|
+
(session)="onSession($event)"
|
|
96
|
+
(adaptOutput)="onOutput($event)"
|
|
97
|
+
(forkActive)="onForkActive($event)"
|
|
98
|
+
/>
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```typescript
|
|
102
|
+
onSession(event: { status: StatusJson; fork?: string }) {
|
|
103
|
+
console.log(event.status, event.fork);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
onOutput(output: Output) {
|
|
107
|
+
console.log(output);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
onForkActive(active: boolean) {
|
|
111
|
+
console.log(active);
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 2. `AdaptCap`
|
|
118
|
+
|
|
119
|
+
Standalone proof-of-work challenge widget. Use when you manage the automation client yourself.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import { Component } from '@angular/core';
|
|
123
|
+
import { AdaptCap, createConnectClient } from '@mochabug/adapt-angular/cap';
|
|
124
|
+
|
|
125
|
+
@Component({
|
|
126
|
+
selector: 'app-challenge',
|
|
127
|
+
standalone: true,
|
|
128
|
+
imports: [AdaptCap],
|
|
129
|
+
template: `
|
|
130
|
+
<mb-adapt-cap
|
|
131
|
+
[automationId]="'YOUR_ID'"
|
|
132
|
+
[client]="client"
|
|
133
|
+
(solve)="onSolve($event)"
|
|
134
|
+
(error)="onError($event)"
|
|
135
|
+
/>
|
|
136
|
+
`,
|
|
137
|
+
})
|
|
138
|
+
export class ChallengeComponent {
|
|
139
|
+
client = createConnectClient({ id: 'YOUR_ID' });
|
|
140
|
+
|
|
141
|
+
onSolve(event: { token: string; expires: Date }) {
|
|
142
|
+
console.log('Solved:', event.token, event.expires);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
onError(error: Error) {
|
|
146
|
+
console.error(error);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Props
|
|
152
|
+
|
|
153
|
+
| Input | Type |
|
|
154
|
+
|-------|------|
|
|
155
|
+
| `automationId` | `string` (required) |
|
|
156
|
+
| `client` | `AutomationClient` (required) |
|
|
157
|
+
| `workerCount` | `number` |
|
|
158
|
+
| `i18n` | `CapWidgetI18n` |
|
|
159
|
+
| `darkMode` | `boolean` |
|
|
160
|
+
|
|
161
|
+
### Events
|
|
162
|
+
|
|
163
|
+
| Output | Payload |
|
|
164
|
+
|--------|---------|
|
|
165
|
+
| `solve` | `{ token: string; expires: Date }` |
|
|
166
|
+
| `error` | `Error` |
|
|
167
|
+
|
|
168
|
+
### Headless (no UI)
|
|
169
|
+
|
|
170
|
+
Use the lower-level API to create and redeem challenges yourself:
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
import { createChallenge, redeemChallenge, createConnectClient } from '@mochabug/adapt-angular/cap';
|
|
174
|
+
|
|
175
|
+
const client = createConnectClient({ id: 'YOUR_ID' });
|
|
176
|
+
const challenge = await createChallenge(client);
|
|
177
|
+
// ... solve with Cap.js or your own solver ...
|
|
178
|
+
const redeemed = await redeemChallenge(client, solutions);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## Styling
|
|
184
|
+
|
|
185
|
+
All visuals are controlled via CSS custom properties on `.mb-adapt`. The `[darkMode]="true"` input automatically switches to dark defaults, but you can override any variable for either mode.
|
|
186
|
+
|
|
187
|
+
### Where to put the CSS
|
|
188
|
+
|
|
189
|
+
Add a CSS file and import it in your `angular.json` styles array:
|
|
190
|
+
|
|
191
|
+
```json
|
|
192
|
+
{
|
|
193
|
+
"styles": ["src/styles.css", "src/adapt-theme.css"]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Or import a global CSS file in your root `styles.css`:
|
|
198
|
+
|
|
199
|
+
```css
|
|
200
|
+
@import './adapt-theme.css';
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### Matching your site's toolbar
|
|
204
|
+
|
|
205
|
+
Map your existing design tokens to the panel toolbar. These six variables control almost everything you see in the tab bar:
|
|
206
|
+
|
|
207
|
+
```css
|
|
208
|
+
/* adapt-theme.css */
|
|
209
|
+
|
|
210
|
+
/* Light mode — derive from your site's surface/text colors */
|
|
211
|
+
.mb-adapt {
|
|
212
|
+
--mb-adapt-fork-bg: #ffffff; /* panel content background */
|
|
213
|
+
--mb-adapt-fork-tab-bg: #f5f5f5; /* inactive tab / toolbar background */
|
|
214
|
+
--mb-adapt-fork-tab-active-bg: #ffffff; /* active tab background */
|
|
215
|
+
--mb-adapt-fork-tab-color: #1a1a1a; /* active tab text */
|
|
216
|
+
--mb-adapt-fork-tab-inactive-color: #888; /* inactive tab text */
|
|
217
|
+
--mb-adapt-fork-separator: #e0e0e0; /* borders between tabs & panels */
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
/* Dark mode — active when [darkMode]="true" */
|
|
221
|
+
.mb-adapt[dark-mode] {
|
|
222
|
+
--mb-adapt-fork-bg: #1e1e1e;
|
|
223
|
+
--mb-adapt-fork-tab-bg: #2a2a2a;
|
|
224
|
+
--mb-adapt-fork-tab-active-bg: #1e1e1e;
|
|
225
|
+
--mb-adapt-fork-tab-color: #e0e0e0;
|
|
226
|
+
--mb-adapt-fork-tab-inactive-color: #777;
|
|
227
|
+
--mb-adapt-fork-separator: #3a3a3a;
|
|
228
|
+
}
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
**Typical mapping from your site's design system:**
|
|
232
|
+
|
|
233
|
+
| Your site has | Maps to |
|
|
234
|
+
|---|---|
|
|
235
|
+
| Surface / card background | `--mb-adapt-fork-bg` |
|
|
236
|
+
| Secondary / muted background | `--mb-adapt-fork-tab-bg` |
|
|
237
|
+
| Primary text color | `--mb-adapt-fork-tab-color` |
|
|
238
|
+
| Muted / secondary text | `--mb-adapt-fork-tab-inactive-color` |
|
|
239
|
+
| Border / divider color | `--mb-adapt-fork-separator` |
|
|
240
|
+
| Accent color | `--mb-adapt-separator-active` (resize handle highlight) |
|
|
241
|
+
| Interactive hover tint | `--mb-adapt-button-hover-bg` |
|
|
242
|
+
|
|
243
|
+
### Custom theme (light & dark)
|
|
244
|
+
|
|
245
|
+
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. Add this as a global CSS file via `angular.json` styles array or import it in your root stylesheet:
|
|
246
|
+
|
|
247
|
+
```css
|
|
248
|
+
/* adapt-brand-theme.css */
|
|
249
|
+
|
|
250
|
+
/*
|
|
251
|
+
* Example: brand theme using primary / secondary / accent colors.
|
|
252
|
+
* Maps your design-system tokens to Adapt's CSS variables for both modes.
|
|
253
|
+
*/
|
|
254
|
+
|
|
255
|
+
/* ── Light mode ────────────────────────────────── */
|
|
256
|
+
.mb-adapt {
|
|
257
|
+
/* Brand palette */
|
|
258
|
+
--mb-adapt-fork-bg: #ffffff; /* surface */
|
|
259
|
+
--mb-adapt-fork-tab-bg: #f0f4ff; /* primary-50 */
|
|
260
|
+
--mb-adapt-fork-tab-active-bg: #ffffff; /* surface */
|
|
261
|
+
--mb-adapt-fork-tab-color: #1e293b; /* on-surface */
|
|
262
|
+
--mb-adapt-fork-tab-inactive-color: #64748b; /* on-surface-muted */
|
|
263
|
+
--mb-adapt-fork-separator: #cbd5e1; /* outline */
|
|
264
|
+
|
|
265
|
+
/* Accent — resize handle highlight */
|
|
266
|
+
--mb-adapt-separator-active: rgba(79, 70, 229, 0.5); /* primary */
|
|
267
|
+
|
|
268
|
+
/* Cap widget */
|
|
269
|
+
--mb-adapt-cap-background: #ffffff;
|
|
270
|
+
--mb-adapt-cap-border-color: #e2e8f0;
|
|
271
|
+
--mb-adapt-cap-color: #1e293b;
|
|
272
|
+
--mb-adapt-cap-spinner-color: #4f46e5; /* primary */
|
|
273
|
+
|
|
274
|
+
/* Status cards */
|
|
275
|
+
--mb-adapt-status-card-bg: #ffffff;
|
|
276
|
+
--mb-adapt-status-card-border: #e2e8f0;
|
|
277
|
+
--mb-adapt-status-text: #334155;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/* ── Dark mode ─────────────────────────────────── */
|
|
281
|
+
.mb-adapt[dark-mode] {
|
|
282
|
+
--mb-adapt-fork-bg: #0f172a; /* surface-dark */
|
|
283
|
+
--mb-adapt-fork-tab-bg: #1e293b; /* primary-900 */
|
|
284
|
+
--mb-adapt-fork-tab-active-bg: #0f172a; /* surface-dark */
|
|
285
|
+
--mb-adapt-fork-tab-color: #f1f5f9; /* on-surface-dark */
|
|
286
|
+
--mb-adapt-fork-tab-inactive-color: #94a3b8; /* muted-dark */
|
|
287
|
+
--mb-adapt-fork-separator: #334155; /* outline-dark */
|
|
288
|
+
|
|
289
|
+
--mb-adapt-separator-active: rgba(129, 140, 248, 0.6); /* primary-light */
|
|
290
|
+
|
|
291
|
+
--mb-adapt-cap-background: #1e293b;
|
|
292
|
+
--mb-adapt-cap-border-color: #334155;
|
|
293
|
+
--mb-adapt-cap-color: #f1f5f9;
|
|
294
|
+
--mb-adapt-cap-spinner-color: #818cf8; /* primary-light */
|
|
295
|
+
|
|
296
|
+
--mb-adapt-status-card-bg: #1e293b;
|
|
297
|
+
--mb-adapt-status-card-border: #334155;
|
|
298
|
+
--mb-adapt-status-text: #e2e8f0;
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### Font
|
|
303
|
+
|
|
304
|
+
```css
|
|
305
|
+
.mb-adapt {
|
|
306
|
+
--mb-adapt-font: "Inter", sans-serif;
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
### Elevation and borders
|
|
311
|
+
|
|
312
|
+
```css
|
|
313
|
+
/* Subtle, modern elevation */
|
|
314
|
+
.mb-adapt {
|
|
315
|
+
--mb-adapt-floating-shadow: 0 8px 32px rgba(0, 0, 0, 0.08);
|
|
316
|
+
--mb-adapt-floating-border: 1px solid rgba(0, 0, 0, 0.06);
|
|
317
|
+
--mb-adapt-floating-radius: 12px;
|
|
318
|
+
--mb-adapt-floating-backdrop: none;
|
|
319
|
+
|
|
320
|
+
--mb-adapt-status-card-shadow: 0 2px 12px rgba(0, 0, 0, 0.06);
|
|
321
|
+
--mb-adapt-drag-ghost-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
|
322
|
+
--mb-adapt-border-radius: 8px; /* iframe border radius */
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/* Dark mode */
|
|
326
|
+
.mb-adapt[dark-mode] {
|
|
327
|
+
--mb-adapt-floating-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
328
|
+
--mb-adapt-floating-border: 1px solid rgba(255, 255, 255, 0.08);
|
|
329
|
+
--mb-adapt-status-card-shadow: 0 2px 12px rgba(0, 0, 0, 0.3);
|
|
330
|
+
--mb-adapt-drag-ghost-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
|
|
331
|
+
}
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
**Frosted glass effect:**
|
|
335
|
+
|
|
336
|
+
```css
|
|
337
|
+
.mb-adapt {
|
|
338
|
+
--mb-adapt-fork-bg: rgba(255, 255, 255, 0.7);
|
|
339
|
+
--mb-adapt-fork-tab-bg: rgba(245, 245, 245, 0.5);
|
|
340
|
+
--mb-adapt-floating-backdrop: blur(16px) saturate(180%);
|
|
341
|
+
--mb-adapt-floating-border: 1px solid rgba(255, 255, 255, 0.2);
|
|
342
|
+
--mb-adapt-floating-shadow: 0 4px 24px rgba(0, 0, 0, 0.06);
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**Flat / borderless:**
|
|
347
|
+
|
|
348
|
+
```css
|
|
349
|
+
.mb-adapt {
|
|
350
|
+
--mb-adapt-floating-shadow: none;
|
|
351
|
+
--mb-adapt-floating-border: 1px solid var(--mb-adapt-fork-separator);
|
|
352
|
+
--mb-adapt-floating-radius: 4px;
|
|
353
|
+
--mb-adapt-status-card-shadow: none;
|
|
354
|
+
--mb-adapt-drag-ghost-shadow: none;
|
|
355
|
+
}
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Using the `classNames` input
|
|
359
|
+
|
|
360
|
+
Override internal element classes for deeper customization:
|
|
361
|
+
|
|
362
|
+
```html
|
|
363
|
+
<mb-adapt-automation
|
|
364
|
+
[automationId]="'auto-123'"
|
|
365
|
+
[classNames]="{
|
|
366
|
+
root: 'my-adapt-root',
|
|
367
|
+
iframe: 'my-adapt-iframe',
|
|
368
|
+
statusMessage: 'my-status-overlay',
|
|
369
|
+
statusCard: 'my-status-card'
|
|
370
|
+
}"
|
|
371
|
+
/>
|
|
372
|
+
```
|
|
373
|
+
|
|
374
|
+
### Using the `styles` input
|
|
375
|
+
|
|
376
|
+
Apply inline styles to the internal root element (useful for sizing):
|
|
377
|
+
|
|
378
|
+
```html
|
|
379
|
+
<mb-adapt-automation
|
|
380
|
+
[automationId]="'auto-123'"
|
|
381
|
+
[styles]="{ height: '600px', maxWidth: '1200px', margin: '0 auto' }"
|
|
382
|
+
/>
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
> **Note:** `[styles]` targets the internal `.mb-adapt` root. Use Angular's `style` attribute or `[ngStyle]` for styles on the outer `<mb-adapt-automation>` host element.
|
|
386
|
+
|
|
387
|
+
<details>
|
|
388
|
+
<summary>Full CSS variable reference</summary>
|
|
389
|
+
|
|
390
|
+
### General
|
|
391
|
+
|
|
392
|
+
| Variable | Light default | Dark default | Description |
|
|
393
|
+
|---|---|---|---|
|
|
394
|
+
| `--mb-adapt-bg` | `transparent` | | Root & group backgrounds |
|
|
395
|
+
| `--mb-adapt-font` | `system-ui, -apple-system, sans-serif` | | All panel UI text |
|
|
396
|
+
| `--mb-adapt-button-hover-bg` | `rgba(128,128,128,0.2)` | `rgba(128,128,128,0.3)` | Close/popout/action button hover |
|
|
397
|
+
| `--mb-adapt-separator-active` | `rgba(59,130,246,0.5)` | `rgba(99,130,246,0.6)` | Resize handle hover/active |
|
|
398
|
+
| `--mb-adapt-border-radius` | `8px` | | Iframe border radius |
|
|
399
|
+
|
|
400
|
+
### Toolbar and tabs
|
|
401
|
+
|
|
402
|
+
| Variable | Light default | Dark default | Description |
|
|
403
|
+
|---|---|---|---|
|
|
404
|
+
| `--mb-adapt-fork-bg` | `#ffffff` | `#1e1e1e` | Panel content background |
|
|
405
|
+
| `--mb-adapt-fork-tab-bg` | `#f3f3f3` | `#252526` | Toolbar / inactive tab bg |
|
|
406
|
+
| `--mb-adapt-fork-tab-active-bg` | `#ffffff` | `#1e1e1e` | Active tab background |
|
|
407
|
+
| `--mb-adapt-fork-tab-color` | `rgb(51,51,51)` | `#ffffff` | Active tab text |
|
|
408
|
+
| `--mb-adapt-fork-tab-inactive-color` | `rgba(51,51,51,0.7)` | `#969696` | Inactive tab text |
|
|
409
|
+
| `--mb-adapt-fork-separator` | `rgba(128,128,128,0.35)` | `rgb(68,68,68)` | Tab/panel borders |
|
|
410
|
+
|
|
411
|
+
### Floating panels (elevation)
|
|
412
|
+
|
|
413
|
+
| Variable | Light default | Dark default | Description |
|
|
414
|
+
|---|---|---|---|
|
|
415
|
+
| `--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 |
|
|
416
|
+
| `--mb-adapt-floating-border` | `none` | `1px solid rgba(255,255,255,0.06)` | Overlay border |
|
|
417
|
+
| `--mb-adapt-floating-backdrop` | `none` | | Overlay backdrop-filter |
|
|
418
|
+
| `--mb-adapt-floating-radius` | `8px` | | Overlay border-radius |
|
|
419
|
+
| `--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 |
|
|
420
|
+
| `--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 |
|
|
421
|
+
|
|
422
|
+
### Drop targets
|
|
423
|
+
|
|
424
|
+
| Variable | Light default | Dark default |
|
|
425
|
+
|---|---|---|
|
|
426
|
+
| `--mb-adapt-drop-header-bg` | `rgba(99,102,241,0.18)` | `rgba(129,140,248,0.22)` |
|
|
427
|
+
| `--mb-adapt-drop-center-bg` | `rgba(99,102,241,0.12)` | `rgba(129,140,248,0.15)` |
|
|
428
|
+
| `--mb-adapt-drop-split-bg` | `rgba(99,102,241,0.14)` | `rgba(129,140,248,0.18)` |
|
|
429
|
+
| `--mb-adapt-drop-border` | `rgba(99,102,241,0.55)` | `rgba(129,140,248,0.6)` |
|
|
430
|
+
|
|
431
|
+
### Status cards
|
|
432
|
+
|
|
433
|
+
| Variable | Light default | Dark default |
|
|
434
|
+
|---|---|---|
|
|
435
|
+
| `--mb-adapt-status-card-bg` | `#ffffff` | `#1e293b` |
|
|
436
|
+
| `--mb-adapt-status-card-border` | `#e5e7eb` | `#334155` |
|
|
437
|
+
| `--mb-adapt-status-icon-bg` | `#fef2f2` | `#351c1c` |
|
|
438
|
+
| `--mb-adapt-status-text` | `#374151` | `#e2e8f0` |
|
|
439
|
+
|
|
440
|
+
### Cap widget
|
|
441
|
+
|
|
442
|
+
| Variable | Light default | Dark default |
|
|
443
|
+
|---|---|---|
|
|
444
|
+
| `--mb-adapt-cap-background` | `#ffffff` | `#1e293b` |
|
|
445
|
+
| `--mb-adapt-cap-border-color` | `#e2e8f0` | `#334155` |
|
|
446
|
+
| `--mb-adapt-cap-border-radius` | `16px` | |
|
|
447
|
+
| `--mb-adapt-cap-height` | `72px` | |
|
|
448
|
+
| `--mb-adapt-cap-width` | `380px` | |
|
|
449
|
+
| `--mb-adapt-cap-padding` | `20px 28px` | |
|
|
450
|
+
| `--mb-adapt-cap-gap` | `20px` | |
|
|
451
|
+
| `--mb-adapt-cap-color` | `#1e293b` | `#f1f5f9` |
|
|
452
|
+
| `--mb-adapt-cap-checkbox-size` | `36px` | |
|
|
453
|
+
| `--mb-adapt-cap-checkbox-border` | `2px solid #cbd5e1` | `2px solid #475569` |
|
|
454
|
+
| `--mb-adapt-cap-checkbox-radius` | `10px` | |
|
|
455
|
+
| `--mb-adapt-cap-checkbox-background` | `#f8fafc` | `#0f172a` |
|
|
456
|
+
| `--mb-adapt-cap-spinner-color` | `#6366f1` | `#818cf8` |
|
|
457
|
+
| `--mb-adapt-cap-spinner-bg` | `#e2e8f0` | `#334155` |
|
|
458
|
+
| `--mb-adapt-cap-spinner-thickness` | `3px` | |
|
|
459
|
+
| `--mb-adapt-cap-font` | `inherit` | |
|
|
460
|
+
|
|
461
|
+
</details>
|
|
462
|
+
|
|
463
|
+
---
|
|
464
|
+
|
|
465
|
+
## Props
|
|
466
|
+
|
|
467
|
+
| Input | Type |
|
|
468
|
+
|-------|------|
|
|
469
|
+
| `automationId` | `string` (required) |
|
|
470
|
+
| `sessionToken` | `string` |
|
|
471
|
+
| `authToken` | `string` |
|
|
472
|
+
| `transmitter` | `string` |
|
|
473
|
+
| `signals` | `{ [key: string]: SignalValue }` |
|
|
474
|
+
| `challengeToken` | `string` |
|
|
475
|
+
| `requiresChallenge` | `boolean` |
|
|
476
|
+
| `capWidgetOptions` | `{ workerCount?: number; i18n?: CapWidgetI18n }` |
|
|
477
|
+
| `inheritToken` | `string` |
|
|
478
|
+
| `inheritFrom` | `{ hash: string } \| { param: string }` |
|
|
479
|
+
| `forkDisplay` | `{ mode: 'side-by-side', split?: number } \| { mode: 'dialog' }` |
|
|
480
|
+
| `darkMode` | `boolean` |
|
|
481
|
+
| `autoResizing` | `boolean` |
|
|
482
|
+
| `allowFloating` | `boolean` — hide pop-out buttons and block user-initiated floating (default `true`) |
|
|
483
|
+
| `allowDocking` | `boolean` — hide dock buttons and block user-initiated docking (default `true`) |
|
|
484
|
+
| `allowDialogDocking` | `boolean` — allow tab splits inside floating dialog overlays (default `true`) |
|
|
485
|
+
| `floatingAutoResize` | `boolean` — floating overlays auto-resize from iframe content (default `false`) |
|
|
486
|
+
| `confirmOnClose` | `boolean` — show confirmation dialog before leaving page (default `false`) |
|
|
487
|
+
| `persist` | `boolean \| PersistOptions` |
|
|
488
|
+
| `text` | `StatusText` |
|
|
489
|
+
| `classNames` | `{ root?: string; iframe?: string; statusMessage?: string; statusCard?: string }` |
|
|
490
|
+
| `styles` | `Partial<CSSStyleDeclaration>` |
|
|
491
|
+
|
|
492
|
+
## Events
|
|
493
|
+
|
|
494
|
+
| Output | Payload |
|
|
495
|
+
|--------|---------|
|
|
496
|
+
| `session` | `{ status: StatusJson; fork?: string }` |
|
|
497
|
+
| `adaptOutput` | `Output` |
|
|
498
|
+
| `forkActive` | `boolean` |
|
|
499
|
+
|
|
500
|
+
## License
|
|
501
|
+
|
|
502
|
+
ISC (c) mochabug AB
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { AfterViewInit, EventEmitter, NgZone, OnChanges, OnDestroy } from "@angular/core";
|
|
2
|
+
import { type AdaptWebClientOptions, type ForkDisplay, type Output as AdaptOutput, type PersistOptions, type SignalValue, type StatusJson, type StatusText } from "@mochabug/adapt-web";
|
|
3
|
+
import "@mochabug/adapt-web/cap";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Angular component for embedding Adapt automations.
|
|
7
|
+
* Renders the `<adapt-automation>` custom element internally and syncs
|
|
8
|
+
* Angular inputs/outputs to the element's attributes and properties.
|
|
9
|
+
*/
|
|
10
|
+
export declare class AdaptAutomation implements AfterViewInit, OnChanges, OnDestroy {
|
|
11
|
+
private zone;
|
|
12
|
+
private elRef;
|
|
13
|
+
automationId: string;
|
|
14
|
+
sessionToken?: string;
|
|
15
|
+
authToken?: string;
|
|
16
|
+
transmitter?: string;
|
|
17
|
+
signals?: Record<string, SignalValue>;
|
|
18
|
+
challengeToken?: string;
|
|
19
|
+
requiresChallenge?: boolean;
|
|
20
|
+
capWidgetOptions?: AdaptWebClientOptions["capWidgetOptions"];
|
|
21
|
+
inheritToken?: string;
|
|
22
|
+
inheritFrom?: {
|
|
23
|
+
hash: string;
|
|
24
|
+
} | {
|
|
25
|
+
param: string;
|
|
26
|
+
};
|
|
27
|
+
forkDisplay?: ForkDisplay;
|
|
28
|
+
darkMode?: boolean;
|
|
29
|
+
autoResizing?: boolean;
|
|
30
|
+
allowFloating?: boolean;
|
|
31
|
+
allowDocking?: boolean;
|
|
32
|
+
allowDialogDocking?: boolean;
|
|
33
|
+
allowMinimize?: boolean;
|
|
34
|
+
allowMaximize?: boolean;
|
|
35
|
+
floatingAutoResize?: boolean;
|
|
36
|
+
confirmOnClose?: boolean;
|
|
37
|
+
persist?: boolean | PersistOptions;
|
|
38
|
+
text?: StatusText;
|
|
39
|
+
classNames?: AdaptWebClientOptions["classNames"];
|
|
40
|
+
styles?: Partial<CSSStyleDeclaration>;
|
|
41
|
+
session: EventEmitter<{
|
|
42
|
+
status: StatusJson;
|
|
43
|
+
fork?: string;
|
|
44
|
+
}>;
|
|
45
|
+
adaptOutput: EventEmitter<AdaptOutput>;
|
|
46
|
+
forkActive: EventEmitter<boolean>;
|
|
47
|
+
private initialized;
|
|
48
|
+
constructor(zone: NgZone);
|
|
49
|
+
ngAfterViewInit(): void;
|
|
50
|
+
ngOnChanges(): void;
|
|
51
|
+
ngOnDestroy(): void;
|
|
52
|
+
/** End current session and start a new one. */
|
|
53
|
+
newSession(): Promise<void>;
|
|
54
|
+
private sync;
|
|
55
|
+
private setAttr;
|
|
56
|
+
private setBoolAttr;
|
|
57
|
+
private setFalseAttr;
|
|
58
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AdaptAutomation, never>;
|
|
59
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AdaptAutomation, "mb-adapt-automation", never, { "automationId": { "alias": "automationId"; "required": true; }; "sessionToken": { "alias": "sessionToken"; "required": false; }; "authToken": { "alias": "authToken"; "required": false; }; "transmitter": { "alias": "transmitter"; "required": false; }; "signals": { "alias": "signals"; "required": false; }; "challengeToken": { "alias": "challengeToken"; "required": false; }; "requiresChallenge": { "alias": "requiresChallenge"; "required": false; }; "capWidgetOptions": { "alias": "capWidgetOptions"; "required": false; }; "inheritToken": { "alias": "inheritToken"; "required": false; }; "inheritFrom": { "alias": "inheritFrom"; "required": false; }; "forkDisplay": { "alias": "forkDisplay"; "required": false; }; "darkMode": { "alias": "darkMode"; "required": false; }; "autoResizing": { "alias": "autoResizing"; "required": false; }; "allowFloating": { "alias": "allowFloating"; "required": false; }; "allowDocking": { "alias": "allowDocking"; "required": false; }; "allowDialogDocking": { "alias": "allowDialogDocking"; "required": false; }; "allowMinimize": { "alias": "allowMinimize"; "required": false; }; "allowMaximize": { "alias": "allowMaximize"; "required": false; }; "floatingAutoResize": { "alias": "floatingAutoResize"; "required": false; }; "confirmOnClose": { "alias": "confirmOnClose"; "required": false; }; "persist": { "alias": "persist"; "required": false; }; "text": { "alias": "text"; "required": false; }; "classNames": { "alias": "classNames"; "required": false; }; "styles": { "alias": "styles"; "required": false; }; }, { "session": "session"; "adaptOutput": "adaptOutput"; "forkActive": "forkActive"; }, never, never, true, never>;
|
|
60
|
+
}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, Input, Output, ViewChild, } from "@angular/core";
|
|
2
|
+
import { AdaptAutomationElement, } from "@mochabug/adapt-web";
|
|
3
|
+
import "@mochabug/adapt-web/cap";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
// Ensure custom element is registered
|
|
6
|
+
void AdaptAutomationElement;
|
|
7
|
+
/**
|
|
8
|
+
* Angular component for embedding Adapt automations.
|
|
9
|
+
* Renders the `<adapt-automation>` custom element internally and syncs
|
|
10
|
+
* Angular inputs/outputs to the element's attributes and properties.
|
|
11
|
+
*/
|
|
12
|
+
export class AdaptAutomation {
|
|
13
|
+
constructor(zone) {
|
|
14
|
+
this.zone = zone;
|
|
15
|
+
this.session = new EventEmitter();
|
|
16
|
+
this.adaptOutput = new EventEmitter();
|
|
17
|
+
this.forkActive = new EventEmitter();
|
|
18
|
+
this.initialized = false;
|
|
19
|
+
}
|
|
20
|
+
ngAfterViewInit() {
|
|
21
|
+
this.sync();
|
|
22
|
+
this.initialized = true;
|
|
23
|
+
}
|
|
24
|
+
ngOnChanges() {
|
|
25
|
+
if (this.initialized) {
|
|
26
|
+
this.sync();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
ngOnDestroy() {
|
|
30
|
+
// Custom element handles cleanup via disconnectedCallback
|
|
31
|
+
}
|
|
32
|
+
/** End current session and start a new one. */
|
|
33
|
+
async newSession() {
|
|
34
|
+
await this.elRef.nativeElement.newSession();
|
|
35
|
+
}
|
|
36
|
+
sync() {
|
|
37
|
+
const el = this.elRef.nativeElement;
|
|
38
|
+
// String attributes
|
|
39
|
+
this.setAttr(el, "automation-id", this.automationId);
|
|
40
|
+
this.setAttr(el, "session-token", this.sessionToken);
|
|
41
|
+
this.setAttr(el, "auth-token", this.authToken);
|
|
42
|
+
this.setAttr(el, "transmitter", this.transmitter);
|
|
43
|
+
this.setAttr(el, "challenge-token", this.challengeToken);
|
|
44
|
+
this.setAttr(el, "inherit-token", this.inheritToken);
|
|
45
|
+
// Boolean presence attributes
|
|
46
|
+
this.setBoolAttr(el, "requires-challenge", this.requiresChallenge);
|
|
47
|
+
this.setBoolAttr(el, "dark-mode", this.darkMode);
|
|
48
|
+
this.setBoolAttr(el, "auto-resizing", this.autoResizing);
|
|
49
|
+
this.setBoolAttr(el, "floating-auto-resize", this.floatingAutoResize);
|
|
50
|
+
this.setBoolAttr(el, "confirm-on-close", this.confirmOnClose);
|
|
51
|
+
this.setBoolAttr(el, "persist", !!this.persist);
|
|
52
|
+
// Boolean "false" attributes (default true, set "false" to disable)
|
|
53
|
+
this.setFalseAttr(el, "allow-floating", this.allowFloating);
|
|
54
|
+
this.setFalseAttr(el, "allow-docking", this.allowDocking);
|
|
55
|
+
this.setFalseAttr(el, "allow-dialog-docking", this.allowDialogDocking);
|
|
56
|
+
this.setFalseAttr(el, "allow-minimize", this.allowMinimize);
|
|
57
|
+
this.setFalseAttr(el, "allow-maximize", this.allowMaximize);
|
|
58
|
+
// Fork display attributes
|
|
59
|
+
if (this.forkDisplay) {
|
|
60
|
+
el.setAttribute("fork-display-mode", this.forkDisplay.mode);
|
|
61
|
+
if (this.forkDisplay.mode === "side-by-side" &&
|
|
62
|
+
this.forkDisplay.split !== undefined) {
|
|
63
|
+
el.setAttribute("side-by-side-split", String(this.forkDisplay.split));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
el.removeAttribute("side-by-side-split");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Non-serializable properties
|
|
70
|
+
el.signals = this.signals;
|
|
71
|
+
el.capWidgetOptions = this.capWidgetOptions;
|
|
72
|
+
el.inheritFrom = this.inheritFrom;
|
|
73
|
+
el.classNames = this.classNames;
|
|
74
|
+
el.styles = this.styles;
|
|
75
|
+
el.persistOptions =
|
|
76
|
+
typeof this.persist === "object" ? this.persist : undefined;
|
|
77
|
+
el.text = this.text;
|
|
78
|
+
// Callbacks — run inside NgZone for change detection
|
|
79
|
+
el.onSessionCallback = (status, fork) => {
|
|
80
|
+
this.zone.run(() => this.session.emit({ status, fork }));
|
|
81
|
+
};
|
|
82
|
+
el.onOutputCallback = (output) => {
|
|
83
|
+
this.zone.run(() => this.adaptOutput.emit(output));
|
|
84
|
+
};
|
|
85
|
+
el.onForkActiveCallback = (active) => {
|
|
86
|
+
this.zone.run(() => this.forkActive.emit(active));
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
setAttr(el, name, value) {
|
|
90
|
+
if (value != null) {
|
|
91
|
+
el.setAttribute(name, value);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
el.removeAttribute(name);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
setBoolAttr(el, name, value) {
|
|
98
|
+
if (value) {
|
|
99
|
+
el.setAttribute(name, "");
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
el.removeAttribute(name);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
setFalseAttr(el, name, value) {
|
|
106
|
+
if (value === false) {
|
|
107
|
+
el.setAttribute(name, "false");
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
el.removeAttribute(name);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
AdaptAutomation.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AdaptAutomation, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
115
|
+
AdaptAutomation.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: AdaptAutomation, isStandalone: true, selector: "mb-adapt-automation", inputs: { automationId: "automationId", sessionToken: "sessionToken", authToken: "authToken", transmitter: "transmitter", signals: "signals", challengeToken: "challengeToken", requiresChallenge: "requiresChallenge", capWidgetOptions: "capWidgetOptions", inheritToken: "inheritToken", inheritFrom: "inheritFrom", forkDisplay: "forkDisplay", darkMode: "darkMode", autoResizing: "autoResizing", allowFloating: "allowFloating", allowDocking: "allowDocking", allowDialogDocking: "allowDialogDocking", allowMinimize: "allowMinimize", allowMaximize: "allowMaximize", floatingAutoResize: "floatingAutoResize", confirmOnClose: "confirmOnClose", persist: "persist", text: "text", classNames: "classNames", styles: "styles" }, outputs: { session: "session", adaptOutput: "adaptOutput", forkActive: "forkActive" }, viewQueries: [{ propertyName: "elRef", first: true, predicate: ["el"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `<adapt-automation #el></adapt-automation>`, isInline: true, styles: [":host { display: block; }", "adapt-automation { display: block; width: 100%; height: 100%; }"] });
|
|
116
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AdaptAutomation, decorators: [{
|
|
117
|
+
type: Component,
|
|
118
|
+
args: [{ selector: "mb-adapt-automation", standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `<adapt-automation #el></adapt-automation>`, styles: [":host { display: block; }", "adapt-automation { display: block; width: 100%; height: 100%; }"] }]
|
|
119
|
+
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { elRef: [{
|
|
120
|
+
type: ViewChild,
|
|
121
|
+
args: ["el", { static: true }]
|
|
122
|
+
}], automationId: [{
|
|
123
|
+
type: Input,
|
|
124
|
+
args: [{ required: true }]
|
|
125
|
+
}], sessionToken: [{
|
|
126
|
+
type: Input
|
|
127
|
+
}], authToken: [{
|
|
128
|
+
type: Input
|
|
129
|
+
}], transmitter: [{
|
|
130
|
+
type: Input
|
|
131
|
+
}], signals: [{
|
|
132
|
+
type: Input
|
|
133
|
+
}], challengeToken: [{
|
|
134
|
+
type: Input
|
|
135
|
+
}], requiresChallenge: [{
|
|
136
|
+
type: Input
|
|
137
|
+
}], capWidgetOptions: [{
|
|
138
|
+
type: Input
|
|
139
|
+
}], inheritToken: [{
|
|
140
|
+
type: Input
|
|
141
|
+
}], inheritFrom: [{
|
|
142
|
+
type: Input
|
|
143
|
+
}], forkDisplay: [{
|
|
144
|
+
type: Input
|
|
145
|
+
}], darkMode: [{
|
|
146
|
+
type: Input
|
|
147
|
+
}], autoResizing: [{
|
|
148
|
+
type: Input
|
|
149
|
+
}], allowFloating: [{
|
|
150
|
+
type: Input
|
|
151
|
+
}], allowDocking: [{
|
|
152
|
+
type: Input
|
|
153
|
+
}], allowDialogDocking: [{
|
|
154
|
+
type: Input
|
|
155
|
+
}], allowMinimize: [{
|
|
156
|
+
type: Input
|
|
157
|
+
}], allowMaximize: [{
|
|
158
|
+
type: Input
|
|
159
|
+
}], floatingAutoResize: [{
|
|
160
|
+
type: Input
|
|
161
|
+
}], confirmOnClose: [{
|
|
162
|
+
type: Input
|
|
163
|
+
}], persist: [{
|
|
164
|
+
type: Input
|
|
165
|
+
}], text: [{
|
|
166
|
+
type: Input
|
|
167
|
+
}], classNames: [{
|
|
168
|
+
type: Input
|
|
169
|
+
}], styles: [{
|
|
170
|
+
type: Input
|
|
171
|
+
}], session: [{
|
|
172
|
+
type: Output
|
|
173
|
+
}], adaptOutput: [{
|
|
174
|
+
type: Output
|
|
175
|
+
}], forkActive: [{
|
|
176
|
+
type: Output
|
|
177
|
+
}] } });
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { AfterViewInit, EventEmitter, NgZone, OnChanges, OnDestroy } from "@angular/core";
|
|
2
|
+
import type { AutomationClient } from "@mochabug/adapt-core";
|
|
3
|
+
import { type CapWidgetI18n } from "@mochabug/adapt-web/cap";
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* Angular component for Cap.js proof-of-work challenges.
|
|
7
|
+
* Renders the `<adapt-cap>` custom element internally and syncs
|
|
8
|
+
* non-serializable properties via ViewChild.
|
|
9
|
+
*/
|
|
10
|
+
export declare class AdaptCap implements AfterViewInit, OnChanges, OnDestroy {
|
|
11
|
+
private zone;
|
|
12
|
+
private elRef;
|
|
13
|
+
automationId: string;
|
|
14
|
+
client: AutomationClient;
|
|
15
|
+
workerCount?: number;
|
|
16
|
+
i18n?: CapWidgetI18n;
|
|
17
|
+
darkMode?: boolean;
|
|
18
|
+
solve: EventEmitter<{
|
|
19
|
+
token: string;
|
|
20
|
+
expires: Date;
|
|
21
|
+
}>;
|
|
22
|
+
error: EventEmitter<Error>;
|
|
23
|
+
private initialized;
|
|
24
|
+
constructor(zone: NgZone);
|
|
25
|
+
ngAfterViewInit(): void;
|
|
26
|
+
ngOnChanges(): void;
|
|
27
|
+
ngOnDestroy(): void;
|
|
28
|
+
private sync;
|
|
29
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AdaptCap, never>;
|
|
30
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AdaptCap, "mb-adapt-cap", never, { "automationId": { "alias": "automationId"; "required": true; }; "client": { "alias": "client"; "required": true; }; "workerCount": { "alias": "workerCount"; "required": false; }; "i18n": { "alias": "i18n"; "required": false; }; "darkMode": { "alias": "darkMode"; "required": false; }; }, { "solve": "solve"; "error": "error"; }, never, never, true, never>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Component, CUSTOM_ELEMENTS_SCHEMA, EventEmitter, Input, Output, ViewChild, } from "@angular/core";
|
|
2
|
+
import { AdaptCapElement } from "@mochabug/adapt-web/cap";
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
// Ensure custom element is registered
|
|
5
|
+
void AdaptCapElement;
|
|
6
|
+
/**
|
|
7
|
+
* Angular component for Cap.js proof-of-work challenges.
|
|
8
|
+
* Renders the `<adapt-cap>` custom element internally and syncs
|
|
9
|
+
* non-serializable properties via ViewChild.
|
|
10
|
+
*/
|
|
11
|
+
export class AdaptCap {
|
|
12
|
+
constructor(zone) {
|
|
13
|
+
this.zone = zone;
|
|
14
|
+
this.solve = new EventEmitter();
|
|
15
|
+
this.error = new EventEmitter();
|
|
16
|
+
this.initialized = false;
|
|
17
|
+
}
|
|
18
|
+
ngAfterViewInit() {
|
|
19
|
+
this.sync();
|
|
20
|
+
this.initialized = true;
|
|
21
|
+
}
|
|
22
|
+
ngOnChanges() {
|
|
23
|
+
if (this.initialized) {
|
|
24
|
+
this.sync();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
ngOnDestroy() {
|
|
28
|
+
// Custom element handles cleanup
|
|
29
|
+
}
|
|
30
|
+
sync() {
|
|
31
|
+
const el = this.elRef.nativeElement;
|
|
32
|
+
// Attributes
|
|
33
|
+
el.setAttribute("automation-id", this.automationId);
|
|
34
|
+
if (this.workerCount !== undefined) {
|
|
35
|
+
el.setAttribute("worker-count", String(this.workerCount));
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
el.removeAttribute("worker-count");
|
|
39
|
+
}
|
|
40
|
+
if (this.darkMode) {
|
|
41
|
+
el.setAttribute("dark-mode", "");
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
el.removeAttribute("dark-mode");
|
|
45
|
+
}
|
|
46
|
+
// Non-serializable properties
|
|
47
|
+
el.client = this.client;
|
|
48
|
+
el.i18n = this.i18n;
|
|
49
|
+
// Callbacks — run inside NgZone for change detection
|
|
50
|
+
el.onSolveCallback = (token, expires) => {
|
|
51
|
+
this.zone.run(() => this.solve.emit({ token, expires }));
|
|
52
|
+
};
|
|
53
|
+
el.onErrorCallback = (error) => {
|
|
54
|
+
this.zone.run(() => this.error.emit(error));
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
AdaptCap.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AdaptCap, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component });
|
|
59
|
+
AdaptCap.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.4", type: AdaptCap, isStandalone: true, selector: "mb-adapt-cap", inputs: { automationId: "automationId", client: "client", workerCount: "workerCount", i18n: "i18n", darkMode: "darkMode" }, outputs: { solve: "solve", error: "error" }, viewQueries: [{ propertyName: "elRef", first: true, predicate: ["el"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `<adapt-cap #el></adapt-cap>`, isInline: true, styles: [":host { display: block; }", "adapt-cap { display: block; width: 100%; height: 100%; }"] });
|
|
60
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.4", ngImport: i0, type: AdaptCap, decorators: [{
|
|
61
|
+
type: Component,
|
|
62
|
+
args: [{ selector: "mb-adapt-cap", standalone: true, schemas: [CUSTOM_ELEMENTS_SCHEMA], template: `<adapt-cap #el></adapt-cap>`, styles: [":host { display: block; }", "adapt-cap { display: block; width: 100%; height: 100%; }"] }]
|
|
63
|
+
}], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { elRef: [{
|
|
64
|
+
type: ViewChild,
|
|
65
|
+
args: ["el", { static: true }]
|
|
66
|
+
}], automationId: [{
|
|
67
|
+
type: Input,
|
|
68
|
+
args: [{ required: true }]
|
|
69
|
+
}], client: [{
|
|
70
|
+
type: Input,
|
|
71
|
+
args: [{ required: true }]
|
|
72
|
+
}], workerCount: [{
|
|
73
|
+
type: Input
|
|
74
|
+
}], i18n: [{
|
|
75
|
+
type: Input
|
|
76
|
+
}], darkMode: [{
|
|
77
|
+
type: Input
|
|
78
|
+
}], solve: [{
|
|
79
|
+
type: Output
|
|
80
|
+
}], error: [{
|
|
81
|
+
type: Output
|
|
82
|
+
}] } });
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import "@mochabug/adapt-web/cap";
|
|
2
|
+
export { AdaptCap } from "./adapt-cap.component.js";
|
|
3
|
+
export { Cap as AdaptCapWidget, type AdaptCapWidgetOptions, createChallenge, redeemChallenge, AdaptCapElement, createConnectClient, type ChallengeInfo, type RedeemedChallenge, type CapWidgetI18n, type CapWidgetOptions, } from "@mochabug/adapt-web/cap";
|
package/dist/esm/cap.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Cap entry — standalone Cap.js widget for Angular
|
|
2
|
+
import "@mochabug/adapt-web/cap";
|
|
3
|
+
export { AdaptCap } from "./adapt-cap.component.js";
|
|
4
|
+
export { Cap as AdaptCapWidget, createChallenge, redeemChallenge, AdaptCapElement, createConnectClient, } from "@mochabug/adapt-web/cap";
|
package/dist/esm/core.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mochabug/adapt-angular",
|
|
3
|
+
"version": "1.0.1-rc.9",
|
|
4
|
+
"description": "Angular component for Adapt automation platform",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/esm/index.js",
|
|
7
|
+
"types": "./dist/esm/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/esm/index.d.ts",
|
|
11
|
+
"import": "./dist/esm/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./core": {
|
|
14
|
+
"types": "./dist/esm/core.d.ts",
|
|
15
|
+
"import": "./dist/esm/core.js"
|
|
16
|
+
},
|
|
17
|
+
"./cap": {
|
|
18
|
+
"types": "./dist/esm/cap.d.ts",
|
|
19
|
+
"import": "./dist/esm/cap.js"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist"
|
|
24
|
+
],
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build:esm": "ngc --project tsconfig.esm.json",
|
|
27
|
+
"build": "(cd ../web && npm run build) && rm -rf dist && npm run build:esm",
|
|
28
|
+
"sample": "npm run build && cd sample && npm run dev"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"adapt",
|
|
32
|
+
"automations",
|
|
33
|
+
"mochabug",
|
|
34
|
+
"angular"
|
|
35
|
+
],
|
|
36
|
+
"author": "mochabug AB",
|
|
37
|
+
"license": "ISC",
|
|
38
|
+
"publishConfig": {
|
|
39
|
+
"access": "public"
|
|
40
|
+
},
|
|
41
|
+
"peerDependencies": {
|
|
42
|
+
"@angular/core": "^19.0.0 || ^20.0.0 || ^21.0.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@angular/core": "^21.2.4",
|
|
46
|
+
"@angular/compiler": "^21.2.4",
|
|
47
|
+
"@angular/compiler-cli": "^21.2.4",
|
|
48
|
+
"rxjs": "^7.8.2",
|
|
49
|
+
"typescript": "~5.9.3",
|
|
50
|
+
"zone.js": "^0.16.1"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"@mochabug/adapt-web": "*"
|
|
54
|
+
}
|
|
55
|
+
}
|