@prosopo/client-bundle-example 2.7.0 → 2.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/assets/{ProcaptchaWidget-3gKvjeiH.js → ProcaptchaWidget-DrBDhP6X.js} +7 -7
  3. package/dist/assets/{ProcaptchaWidget-D6-M7iAv.js → ProcaptchaWidget-rAM-9Rap.js} +4 -4
  4. package/dist/assets/{asU8a-DCECA0Qe.js → asU8a-CJdNkNEq.js} +1 -1
  5. package/dist/assets/{bip39-BQoZog_M.js → bip39-Du2cANEV.js} +2 -2
  6. package/dist/assets/captcha-BhkVCEXM.css +1 -0
  7. package/dist/assets/{captchaComponentProvider-BW2eXmc3.js → captchaComponentProvider-DmV1WTrT.js} +4 -4
  8. package/dist/assets/{captchaRenderer-B_MgGzr9.js → captchaRenderer-RIsSZXCC.js} +2 -2
  9. package/dist/assets/{emotion-element-5486c51c.browser.esm-CCAJ8JId.js → emotion-element-5486c51c.browser.esm-C3u8NMUC.js} +127 -125
  10. package/dist/assets/frictionless-explicit-C_AXK63E.js +1 -0
  11. package/dist/assets/frictionless-implicit-Dq_sNGRK.js +1 -0
  12. package/dist/assets/{hash-BR0YLxPF.js → hash-_rWungeW.js} +1 -1
  13. package/dist/assets/image-explicit-DQvfVB7-.js +4 -0
  14. package/dist/assets/image-implicit-Bwa9QJO5.js +1 -0
  15. package/dist/assets/{index-WqEmiYQ_.js → index-BVr9fC_3.js} +4 -4
  16. package/dist/assets/{index-BYUYvvuq.js → index-Cu5oL_7b.js} +4 -4
  17. package/dist/assets/index-Dpt_5E72.js +1 -0
  18. package/dist/assets/{index-BCjHZ8o6.js → index-DxIFpl6U.js} +1 -1
  19. package/dist/assets/{index-2or4-1WF.js → index-Wgw2GQWq.js} +2 -2
  20. package/dist/assets/invisible-frictionless-explicit-DugBtRe4.js +4 -0
  21. package/dist/assets/invisible-frictionless-implicit-DYYos8W9.js +1 -0
  22. package/dist/assets/invisible-image-explicit-C5Z4gSb1.js +4 -0
  23. package/dist/assets/invisible-image-implicit-DfNFNlFj.js +1 -0
  24. package/dist/assets/invisible-pow-explicit-DjqGWFUb.js +4 -0
  25. package/dist/assets/invisible-pow-implicit-BRXL14FH.js +4 -0
  26. package/dist/assets/pow-explicit-BexxbnHM.js +4 -0
  27. package/dist/assets/pow-implicit-Dpt_5E72.js +1 -0
  28. package/dist/assets/procaptcha.bundle.js +1 -1
  29. package/dist/assets/{useTranslation-BPbGzrhj.js → useTranslation-CJplXtqb.js} +1 -1
  30. package/dist/frictionless-explicit.html +875 -0
  31. package/dist/frictionless-implicit.html +874 -0
  32. package/dist/image-explicit.html +877 -0
  33. package/dist/index.html +575 -74
  34. package/dist/invisible-frictionless-explicit.html +626 -283
  35. package/dist/invisible-frictionless-implicit.html +631 -173
  36. package/dist/invisible-image-explicit.html +627 -284
  37. package/dist/invisible-image-implicit.html +631 -173
  38. package/dist/invisible-pow-explicit.html +627 -284
  39. package/dist/invisible-pow-implicit.html +629 -177
  40. package/dist/plugins/explanation-injector.ts +250 -0
  41. package/dist/plugins/form-filler-injector.ts +233 -0
  42. package/dist/plugins/navigation-injector.ts +237 -89
  43. package/dist/plugins/status-log-injector.ts +199 -0
  44. package/dist/pow-explicit.html +877 -0
  45. package/dist/pow-implicit.html +881 -0
  46. package/package.json +1 -1
  47. package/vite.config.ts +32 -3
  48. package/dist/assets/frictionless-ZgzyuneX.js +0 -1
  49. package/dist/assets/index-BWsu-rGU.js +0 -1
  50. package/dist/assets/invisible-frictionless-explicit-DgCaJtPg.js +0 -1
  51. package/dist/assets/invisible-image-explicit-DgCaJtPg.js +0 -1
  52. package/dist/assets/invisible-pow-explicit-DgCaJtPg.js +0 -1
  53. package/dist/assets/pow-BW3QYcgP.js +0 -1
  54. package/dist/frictionless.html +0 -343
  55. package/dist/pow.html +0 -323
  56. /package/dist/assets/{modulepreload-polyfill-B5Qt9EMX.js → captcha-ByKnSsbG.js} +0 -0
@@ -1,150 +1,9 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
- <title>Procaptcha Invisible Mode - Explicit Rendering</title>
5
- <!-- Load the Procaptcha script with explicit rendering -->
6
- <script type="module" src="https://staging-js.prosopo.io/js/procaptcha.bundle.js?render=explicit" async defer></script>
7
- <style>
8
- body {
9
- font-family: Arial, sans-serif;
10
- margin: 0 auto;
11
- padding: 20px;
12
- }
13
- form {
14
- border: 1px solid #ddd;
15
- padding: 20px;
16
- border-radius: 5px;
17
- }
18
- label {
19
- display: block;
20
- margin-bottom: 5px;
21
- }
22
- input[type="text"],
23
- input[type="email"] {
24
- width: 100%;
25
- padding: 8px;
26
- margin-bottom: 15px;
27
- border: 1px solid #ccc;
28
- border-radius: 4px;
29
- }
30
- button {
31
- background-color: #4CAF50;
32
- color: white;
33
- padding: 10px 15px;
34
- border: none;
35
- border-radius: 4px;
36
- cursor: pointer;
37
- }
38
- button:hover {
39
- background-color: #45a049;
40
- }
41
- #result {
42
- margin-top: 15px;
43
- padding: 10px;
44
- border: 1px solid #ddd;
45
- border-radius: 4px;
46
- background-color: #f9f9f9;
47
- display: none;
48
- }
49
- .console-output {
50
- margin-top: 20px;
51
- padding: 10px;
52
- background-color: #f5f5f5;
53
- border: 1px solid #ddd;
54
- border-radius: 4px;
55
- font-family: monospace;
56
- white-space: pre-wrap;
57
- max-height: 200px;
58
- overflow-y: auto;
59
- }
60
- .info-box {
61
- background-color: #e7f3fe;
62
- border-left: 4px solid #2196F3;
63
- padding: 15px;
64
- margin: 20px 0;
65
- }
66
- </style>
67
- <script type="text/javascript">
68
- function onSubmit(token) {
69
- console.log('Procaptcha verified, token:', token);
70
-
71
- const name = document.getElementById('name').value;
72
- const email = document.getElementById('email').value;
73
-
74
- const resultElement = document.getElementById('result');
75
- resultElement.textContent = `Form submitted with:
76
- - Name: ${name}
77
- - Email: ${email}
78
- - Procaptcha verified: Yes`;
79
- resultElement.style.display = 'block';
80
-
81
- return false;
82
- }
83
-
84
- function validate(event) {
85
- event.preventDefault();
86
-
87
- // Simple form validation
88
- if (!document.getElementById('name').value) {
89
- alert("Please enter your name");
90
- return;
91
- }
92
-
93
- if (!document.getElementById('email').value) {
94
- alert("Please enter your email");
95
- return;
96
- }
97
-
98
- document.getElementById('console-output').innerHTML = '';
99
- const originalConsoleLog = console.log;
100
- const consoleOutput = document.getElementById('console-output');
101
-
102
- console.log = function() {
103
- originalConsoleLog.apply(console, arguments);
104
-
105
- // Format and display the arguments in our custom console
106
- const args = Array.from(arguments).map(arg => {
107
- if (typeof arg === 'object') {
108
- try {
109
- return JSON.stringify(arg, null, 2);
110
- } catch (e) {
111
- return "[Object cannot be stringified]";
112
- }
113
- }
114
- return String(arg);
115
- });
116
-
117
- consoleOutput.innerHTML += args.join(' ') + '<br>';
118
- consoleOutput.style.display = 'block';
119
- };
120
-
121
- console.log('Executing Procaptcha verification...');
122
- window.procaptcha.execute();
123
-
124
- setTimeout(() => {
125
- console.log = originalConsoleLog;
126
- }, 1000);
127
- }
128
-
129
- function onloadCallback() {
130
- console.log('Procaptcha script loaded, initializing explicit rendering');
131
-
132
- // Render the Procaptcha widget
133
- window.procaptcha.render(document.getElementById('procaptcha-container'), {
134
- 'siteKey': 'undefined',
135
- 'callback': onSubmit,
136
- 'captchaType': 'frictionless',
137
- 'size': 'invisible'
138
- });
139
-
140
- document.getElementById('submit-button').addEventListener('click', validate);
141
- }
142
-
143
- document.addEventListener('DOMContentLoaded', function() {
144
- // Set up the onload callback for Procaptcha
145
- window.onProcaptchaLoad = onloadCallback;
146
- });
147
- </script>
4
+ <link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
5
+ <title>Procaptcha Frictionless Mode - Explicit Rendering</title>
6
+ <!-- Status log will be injected by the status-log-injector plugin -->
148
7
 
149
8
  <style>
150
9
  .nav-topbar {
@@ -153,60 +12,64 @@
153
12
  margin-bottom: 20px;
154
13
  transition: all 0.3s ease;
155
14
  overflow: hidden;
156
- max-height: 500px; /* Initial state - visible */
15
+ max-height: 500px;
157
16
  box-shadow: 0 2px 5px rgba(0,0,0,0.2);
17
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
158
18
  }
159
19
  .nav-topbar.collapsed {
160
- max-height: 50px; /* Collapsed state - only show toggle button and title */
20
+ max-height: 60px;
161
21
  }
162
22
  .nav-container {
163
23
  max-width: 1200px;
164
24
  margin: 0 auto;
165
- padding: 0 15px;
25
+ padding: 0 20px;
166
26
  position: relative;
167
27
  }
168
28
  .nav-header {
169
29
  display: flex;
170
30
  justify-content: space-between;
171
31
  align-items: center;
172
- padding: 10px 0;
32
+ padding: 12px 0;
173
33
  position: relative;
174
34
  z-index: 20;
175
35
  }
176
36
  .nav-title {
177
37
  color: white;
178
- font-size: 18px;
179
- font-weight: bold;
38
+ font-size: 1.25rem;
39
+ font-weight: 600;
180
40
  margin: 0;
181
41
  display: flex;
182
42
  align-items: center;
43
+ gap: 8px;
183
44
  }
184
45
  .nav-title-text {
185
- margin-right: 10px;
46
+ margin-right: 8px;
186
47
  }
187
48
  .nav-title-hint {
188
- font-size: 14px;
49
+ font-size: 0.875rem;
189
50
  font-weight: normal;
190
51
  opacity: 0;
191
52
  transition: opacity 0.3s ease;
53
+ color: rgba(255,255,255,0.8);
192
54
  }
193
55
  .collapsed .nav-title-hint {
194
56
  opacity: 0.8;
195
57
  }
196
58
  .nav-toggle {
197
- background-color: rgba(0,0,0,0.1);
59
+ background-color: rgba(255,255,255,0.1);
198
60
  color: white;
199
61
  border: none;
200
- padding: 5px 10px;
62
+ padding: 8px 12px;
201
63
  cursor: pointer;
202
- border-radius: 4px;
64
+ border-radius: 6px;
203
65
  z-index: 10;
204
66
  display: flex;
205
67
  align-items: center;
206
68
  justify-content: center;
69
+ transition: background-color 0.2s ease;
207
70
  }
208
71
  .nav-toggle:hover {
209
- background-color: rgba(0,0,0,0.2);
72
+ background-color: rgba(255,255,255,0.2);
210
73
  }
211
74
  .nav-toggle-icon {
212
75
  width: 24px;
@@ -233,29 +96,42 @@
233
96
  opacity: 1;
234
97
  }
235
98
  .nav-content {
236
- padding: 0 0 15px 0;
99
+ padding: 0 0 20px 0;
237
100
  transition: opacity 0.3s ease;
238
101
  }
239
102
  .collapsed .nav-content {
240
103
  opacity: 0;
241
104
  }
242
- .nav-row {
105
+ .nav-sections {
243
106
  display: flex;
244
107
  flex-wrap: wrap;
245
- margin-bottom: 15px;
108
+ gap: 20px;
246
109
  }
247
- .nav-group {
110
+ .nav-section {
248
111
  flex: 1;
249
- min-width: 250px;
250
- margin-bottom: 10px;
251
- margin-right: 20px;
112
+ min-width: 280px;
113
+ }
114
+ .nav-section h3 {
115
+ color: white;
116
+ font-size: 1rem;
117
+ font-weight: 600;
118
+ margin: 0 0 12px 0;
119
+ padding-bottom: 8px;
120
+ border-bottom: 1px solid rgba(255,255,255,0.2);
121
+ }
122
+ .nav-group {
123
+ background: rgba(255,255,255,0.1);
124
+ border-radius: 8px;
125
+ padding: 12px;
126
+ margin-bottom: 12px;
252
127
  }
253
128
  .nav-group-title {
254
- color: rgba(255,255,255,0.8);
255
- font-size: 0.9em;
256
- margin: 0 0 5px 0;
257
- text-transform: uppercase;
129
+ color: rgba(255,255,255,0.9);
130
+ font-size: 0.875rem;
258
131
  font-weight: 500;
132
+ margin: 0 0 8px 0;
133
+ text-transform: uppercase;
134
+ letter-spacing: 0.5px;
259
135
  }
260
136
  .nav-group-links {
261
137
  list-style: none;
@@ -263,37 +139,348 @@
263
139
  padding: 0;
264
140
  }
265
141
  .nav-group-links li {
266
- margin: 5px 0;
142
+ margin: 6px 0;
267
143
  }
268
144
  .nav-group-links a {
269
145
  color: white;
270
146
  text-decoration: none;
271
- font-weight: bold;
272
- padding: 5px 0;
147
+ font-weight: 500;
148
+ padding: 6px 8px;
273
149
  display: inline-block;
150
+ border-radius: 4px;
151
+ transition: background-color 0.2s ease;
274
152
  }
275
153
  .nav-group-links a:hover {
276
- text-decoration: underline;
154
+ background-color: rgba(255,255,255,0.2);
277
155
  }
278
156
  .nav-group-links .active {
279
- border-bottom: 2px solid white;
157
+ background-color: rgba(255,255,255,0.2);
158
+ font-weight: 600;
280
159
  }
281
160
  .nav-group-links .disabled {
282
161
  color: rgba(255,255,255,0.5);
283
162
  cursor: not-allowed;
163
+ opacity: 0.7;
284
164
  }
285
165
 
286
166
  @media (max-width: 768px) {
287
- .nav-row {
288
- flex-direction: column;
167
+ .nav-container {
168
+ padding: 0 16px;
169
+ }
170
+ .nav-title {
171
+ font-size: 1.125rem;
289
172
  }
290
173
  .nav-title-hint {
291
174
  display: none;
292
175
  }
176
+ .nav-sections {
177
+ flex-direction: column;
178
+ gap: 16px;
179
+ }
180
+ .nav-section {
181
+ min-width: 100%;
182
+ }
183
+ .nav-section h3 {
184
+ font-size: 0.875rem;
185
+ }
186
+ .nav-group {
187
+ padding: 10px;
188
+ }
189
+ .nav-group-title {
190
+ font-size: 0.8125rem;
191
+ }
192
+ .nav-group-links a {
193
+ padding: 8px 10px;
194
+ width: 100%;
195
+ }
196
+ }
197
+
198
+ @media (max-width: 480px) {
199
+ .nav-topbar {
200
+ max-height: 60px;
201
+ }
202
+ .nav-topbar.collapsed {
203
+ max-height: 60px;
204
+ }
205
+ .nav-title {
206
+ font-size: 1rem;
207
+ }
208
+ .nav-toggle {
209
+ padding: 6px 10px;
210
+ }
211
+ }
212
+
213
+ .nav-group-dropdown {
214
+ position: relative;
215
+ display: inline-block;
216
+ }
217
+
218
+ .nav-group-dropdown-btn {
219
+ background: none;
220
+ border: none;
221
+ color: white;
222
+ font-weight: 500;
223
+ padding: 6px 8px;
224
+ cursor: pointer;
225
+ display: flex;
226
+ align-items: center;
227
+ gap: 4px;
228
+ border-radius: 4px;
229
+ transition: background-color 0.2s ease;
230
+ }
231
+
232
+ .nav-group-dropdown-btn:hover {
233
+ background-color: rgba(255,255,255,0.2);
234
+ }
235
+
236
+ .nav-group-dropdown-btn svg {
237
+ width: 16px;
238
+ height: 16px;
239
+ transition: transform 0.2s ease;
240
+ }
241
+
242
+ .nav-group-dropdown-btn.open svg {
243
+ transform: rotate(180deg);
244
+ }
245
+
246
+ .nav-group-dropdown-content {
247
+ display: none;
248
+ position: absolute;
249
+ background-color: rgba(33, 150, 243, 0.95);
250
+ min-width: 160px;
251
+ box-shadow: 0 8px 16px rgba(0,0,0,0.2);
252
+ z-index: 1;
253
+ border-radius: 4px;
254
+ padding: 8px 0;
255
+ margin-top: 4px;
256
+ }
257
+
258
+ .nav-group-dropdown-btn.open + .nav-group-dropdown-content {
259
+ display: block;
260
+ }
261
+
262
+ .nav-group-dropdown-content a {
263
+ color: white;
264
+ padding: 8px 16px;
265
+ text-decoration: none;
266
+ display: block;
267
+ transition: background-color 0.2s ease;
268
+ }
269
+
270
+ .nav-group-dropdown-content a:hover {
271
+ background-color: rgba(255,255,255,0.2);
272
+ }
273
+
274
+ .nav-group-dropdown-content a.active {
275
+ background-color: rgba(255,255,255,0.2);
276
+ font-weight: 600;
277
+ }
278
+
279
+ @media (max-width: 768px) {
280
+ .nav-group-dropdown-content {
281
+ position: static;
282
+ box-shadow: none;
283
+ background-color: rgba(255,255,255,0.1);
284
+ margin-top: 8px;
285
+ }
286
+ }
287
+ </style>
288
+ <script type="module" crossorigin src="/assets/invisible-frictionless-explicit-DugBtRe4.js"></script>
289
+ <link rel="modulepreload" crossorigin href="/assets/captcha-ByKnSsbG.js">
290
+ <link rel="stylesheet" crossorigin href="/assets/captcha-BhkVCEXM.css">
291
+
292
+ <style>
293
+ .form-filler-button {
294
+ position: fixed;
295
+ bottom: 20px;
296
+ right: 20px;
297
+ background-color: #2196F3;
298
+ color: white;
299
+ border: none;
300
+ border-radius: 30px;
301
+ padding: 12px 20px;
302
+ font-size: 14px;
303
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
304
+ cursor: pointer;
305
+ box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
306
+ z-index: 9999;
307
+ display: flex;
308
+ align-items: center;
309
+ gap: 8px;
310
+ transition: all 0.2s ease;
311
+ outline: none;
312
+ }
313
+
314
+ .form-filler-button:hover {
315
+ background-color: #1976D2;
316
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.25);
317
+ transform: translateY(-2px);
318
+ }
319
+
320
+ .form-filler-button:active {
321
+ transform: translateY(1px);
322
+ box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
323
+ }
324
+
325
+ .form-filler-button svg {
326
+ width: 18px;
327
+ height: 18px;
328
+ fill: white;
329
+ }
330
+
331
+ .form-filler-button span {
332
+ font-weight: 500;
333
+ }
334
+
335
+ @media (max-width: 768px) {
336
+ .form-filler-button {
337
+ bottom: 15px;
338
+ right: 15px;
339
+ padding: 10px 15px;
340
+ font-size: 12px;
341
+ }
342
+
343
+ .form-filler-button svg {
344
+ width: 14px;
345
+ height: 14px;
346
+ }
293
347
  }
294
348
  </style>
295
- <script type="module" crossorigin src="/assets/invisible-frictionless-explicit-DgCaJtPg.js"></script>
296
- <link rel="modulepreload" crossorigin href="/assets/modulepreload-polyfill-B5Qt9EMX.js">
349
+
350
+ <style>
351
+ .captcha-status {
352
+ margin-top: 20px;
353
+ padding: 15px;
354
+ background-color: #f0f8ff;
355
+ border: 2px solid #2196F3;
356
+ border-radius: 5px;
357
+ font-family: monospace;
358
+ font-size: 14px;
359
+ }
360
+ .status-item {
361
+ margin: 5px 0;
362
+ padding: 5px;
363
+ }
364
+ .status-success {
365
+ color: #4CAF50;
366
+ font-weight: bold;
367
+ }
368
+ .status-error {
369
+ color: #F44336;
370
+ font-weight: bold;
371
+ }
372
+ .status-info {
373
+ color: #2196F3;
374
+ }
375
+ .status-warning {
376
+ color: #FF9800;
377
+ }
378
+ .status-title {
379
+ font-weight: bold;
380
+ margin-bottom: 10px;
381
+ border-bottom: 1px solid #2196F3;
382
+ padding-bottom: 5px;
383
+ }
384
+ .console-output {
385
+ margin-top: 20px;
386
+ padding: 10px;
387
+ background-color: #f5f5f5;
388
+ border: 1px solid #ddd;
389
+ border-radius: 4px;
390
+ font-family: monospace;
391
+ white-space: pre-wrap;
392
+ max-height: 200px;
393
+ overflow-y: auto;
394
+ }
395
+ </style>
396
+
397
+ <script type="module">
398
+ // Function to update CAPTCHA status display
399
+ function updateCaptchaStatus(message, type = 'info') {
400
+ const statusContainer = document.getElementById('captcha-status');
401
+ if (!statusContainer) return;
402
+
403
+ const timestamp = new Date().toLocaleTimeString();
404
+ const statusItem = document.createElement('div');
405
+ statusItem.className = `status-item status-${type}`;
406
+ statusItem.innerHTML = `[${timestamp}] ${message}`;
407
+ statusContainer.appendChild(statusItem);
408
+
409
+ // Also log to console
410
+ console.log(`CAPTCHA Status: ${message}`);
411
+ }
412
+
413
+ // Make updateCaptchaStatus available globally
414
+ window.updateCaptchaStatus = updateCaptchaStatus;
415
+
416
+ // Override the original callbacks with enhanced versions that use status logging
417
+ const originalOnCaptchaFailed = window.onCaptchaFailed;
418
+ window.onCaptchaFailed = function() {
419
+ updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
420
+ if (originalOnCaptchaFailed) originalOnCaptchaFailed();
421
+ };
422
+
423
+ const originalOnCaptchaVerified = window.onCaptchaVerified;
424
+ window.onCaptchaVerified = function(output) {
425
+ updateCaptchaStatus('Challenge passed successfully!', 'success');
426
+ updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
427
+ if (originalOnCaptchaVerified) originalOnCaptchaVerified(output);
428
+ };
429
+
430
+ const originalOnActionHandler = window.onActionHandler;
431
+ window.onActionHandler = function() {
432
+ const procaptchaElements = document.getElementsByName('procaptcha-response');
433
+
434
+ if (!procaptchaElements.length) {
435
+ updateCaptchaStatus('Error: No CAPTCHA response token found', 'error');
436
+ alert("Must complete captcha");
437
+ return;
438
+ }
439
+
440
+ updateCaptchaStatus('Form submission initiated with valid CAPTCHA token', 'info');
441
+ if (originalOnActionHandler) originalOnActionHandler();
442
+ };
443
+
444
+ document.addEventListener('DOMContentLoaded', function() {
445
+ updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
446
+
447
+ // Monitor DOM for CAPTCHA initialization
448
+ const observer = new MutationObserver((mutations) => {
449
+ mutations.forEach((mutation) => {
450
+ if (mutation.addedNodes.length) {
451
+ for (let i = 0; i < mutation.addedNodes.length; i++) {
452
+ const node = mutation.addedNodes[i];
453
+ if (node.classList && (node.classList.contains('procaptcha') ||
454
+ node.querySelector && node.querySelector('.procaptcha'))) {
455
+ updateCaptchaStatus('CAPTCHA DOM elements initialized', 'info');
456
+ observer.disconnect();
457
+ break;
458
+ }
459
+ }
460
+ }
461
+ });
462
+ });
463
+
464
+ observer.observe(document.body, { childList: true, subtree: true });
465
+ });
466
+
467
+ // Create a method to show CAPTCHA execution events
468
+ document.addEventListener('procaptcha:execute', function(e) {
469
+ // Determine captcha type from the page URL
470
+ const url = window.location.pathname;
471
+ const isFrictionless = url.includes('frictionless');
472
+ const isImage = url.includes('image');
473
+ const isPow = url.includes('pow');
474
+
475
+ let captchaType = 'unknown';
476
+ if (isFrictionless) captchaType = 'frictionless';
477
+ else if (isImage) captchaType = 'image';
478
+ else if (isPow) captchaType = 'pow';
479
+
480
+ updateCaptchaStatus(`CAPTCHA execution started: type=${captchaType}`, 'info');
481
+ updateCaptchaStatus(`Container: ${e.detail.containerId}, timestamp: ${new Date(e.detail.timestamp).toLocaleTimeString()}`, 'info');
482
+ });
483
+ </script>
297
484
  </head>
298
485
  <body>
299
486
 
@@ -316,36 +503,36 @@
316
503
  </button>
317
504
  </div>
318
505
  <div class="nav-content">
319
- <div class="nav-row">
506
+ <div class="nav-sections">
320
507
 
321
508
  <div class="nav-section">
322
- <h3 style="color: white; margin: 0 0 10px 0;">Standard Captchas</h3>
509
+ <h3>Standard Captchas</h3>
323
510
  <div class="nav-row">
324
511
 
325
512
  <div class="nav-group">
326
513
  <div class="nav-group-title">Image</div>
327
- <ul class="nav-group-links">
328
- <li><a href="index.html">Implicit</a></li>
329
- <li><span class="disabled" title="Coming Soon">Explicit</span></li>
330
- </ul>
514
+ <div class="nav-group-links">
515
+ <a href="image-implicit.html">Implicit</a>
516
+ <a href="image-explicit.html">Explicit</a>
517
+ </div>
331
518
  </div>
332
519
 
333
520
 
334
521
  <div class="nav-group">
335
522
  <div class="nav-group-title">Pow</div>
336
- <ul class="nav-group-links">
337
- <li><span class="disabled" title="Coming Soon">Implicit</span></li>
338
- <li><span class="disabled" title="Coming Soon">Explicit</span></li>
339
- </ul>
523
+ <div class="nav-group-links">
524
+ <a href="pow-implicit.html">Implicit</a>
525
+ <a href="pow-explicit.html">Explicit</a>
526
+ </div>
340
527
  </div>
341
528
 
342
529
 
343
530
  <div class="nav-group">
344
531
  <div class="nav-group-title">Frictionless</div>
345
- <ul class="nav-group-links">
346
- <li><span class="disabled" title="Coming Soon">Implicit</span></li>
347
- <li><a href="frictionless-explicit.html">Explicit</a></li>
348
- </ul>
532
+ <div class="nav-group-links">
533
+ <a href="frictionless-implicit.html">Implicit</a>
534
+ <a href="frictionless-explicit.html">Explicit</a>
535
+ </div>
349
536
  </div>
350
537
 
351
538
  </div>
@@ -353,33 +540,33 @@
353
540
 
354
541
 
355
542
  <div class="nav-section">
356
- <h3 style="color: white; margin: 0 0 10px 0;">Invisible Captchas</h3>
543
+ <h3>Invisible Captchas</h3>
357
544
  <div class="nav-row">
358
545
 
359
546
  <div class="nav-group">
360
547
  <div class="nav-group-title">Image</div>
361
- <ul class="nav-group-links">
362
- <li><a href="invisible-image-implicit.html">Implicit</a></li>
363
- <li><a href="invisible-image-explicit.html">Explicit</a></li>
364
- </ul>
548
+ <div class="nav-group-links">
549
+ <a href="invisible-image-implicit.html">Implicit</a>
550
+ <a href="invisible-image-explicit.html">Explicit</a>
551
+ </div>
365
552
  </div>
366
553
 
367
554
 
368
555
  <div class="nav-group">
369
556
  <div class="nav-group-title">Pow</div>
370
- <ul class="nav-group-links">
371
- <li><a href="invisible-pow-implicit.html">Implicit</a></li>
372
- <li><a href="invisible-pow-explicit.html">Explicit</a></li>
373
- </ul>
557
+ <div class="nav-group-links">
558
+ <a href="invisible-pow-implicit.html">Implicit</a>
559
+ <a href="invisible-pow-explicit.html">Explicit</a>
560
+ </div>
374
561
  </div>
375
562
 
376
563
 
377
564
  <div class="nav-group">
378
565
  <div class="nav-group-title">Frictionless</div>
379
- <ul class="nav-group-links">
380
- <li><a href="invisible-frictionless-implicit.html">Implicit</a></li>
381
- <li><a href="invisible-frictionless-explicit.html" class="active">Explicit</a></li>
382
- </ul>
566
+ <div class="nav-group-links">
567
+ <a href="invisible-frictionless-implicit.html">Implicit</a>
568
+ <a href="invisible-frictionless-explicit.html" class="active">Explicit</a>
569
+ </div>
383
570
  </div>
384
571
 
385
572
  </div>
@@ -390,90 +577,54 @@
390
577
  </div>
391
578
  </div>
392
579
 
393
- <h1>Procaptcha Invisible Mode</h1>
394
- <p>This example demonstrates how to use Procaptcha in invisible mode with explicit rendering.</p>
395
-
396
- <form id="demo-form" action="javascript:void(0);" method="POST">
397
- <div>
398
- <label for="name">Name:</label>
399
- <input type="text" id="name" name="name" placeholder="Your name" required />
400
- </div>
580
+ <div class="mui-container">
581
+ <h1>Procaptcha Frictionless Mode - Explicit Rendering</h1>
582
+ <p>This example demonstrates how to use Procaptcha in frictionless mode with explicit rendering.</p>
401
583
 
402
- <div>
403
- <label for="email">Email:</label>
404
- <input type="email" id="email" name="email" placeholder="Your email" required />
405
- </div>
584
+ <!-- Status log will be injected by the status-log-injector plugin -->
406
585
 
407
- <!-- Invisible Procaptcha container -->
408
- <div id="procaptcha-container" data-size="invisible"></div>
586
+ <form id="demo-form" class="mui-form">
587
+ <h2>Example Form</h2>
588
+
589
+ <div class="mui-textfield mui-textfield--float-label">
590
+ <label for="name">Name</label>
591
+ <input type="text" id="name" name="name" required />
592
+ </div>
593
+
594
+ <div class="mui-textfield mui-textfield--float-label">
595
+ <label for="email">Email</label>
596
+ <input type="email" id="email" name="email" required />
597
+ </div>
598
+
599
+ <!-- The container for the CAPTCHA -->
600
+ <div id="procaptcha-container"></div>
601
+
602
+ <button type="submit" class="mui-btn mui-btn--raised" data-cy="submit-button">Submit</button>
603
+
604
+ <div id="error"></div>
605
+ </form>
606
+ <!-- CAPTCHA Status Display -->
607
+ <div id="captcha-status" class="captcha-status">
608
+ <div class="status-title">CAPTCHA Status Log</div>
609
+ </div>
610
+
611
+ <!-- Console output display area -->
612
+ <div id="console-output" class="console-output" style="display: none;"></div>
613
+
409
614
 
410
- <!-- Regular submit button (not directly tied to Procaptcha) -->
411
- <button id="submit-button" type="button">Submit</button>
412
- </form>
413
-
414
- <!-- Result display area -->
415
- <div id="result"></div>
416
-
417
- <!-- Console output display area -->
418
- <div id="console-output" class="console-output" style="display: none;"></div>
419
-
420
- <div style="margin-top: 20px;">
421
- <h2>How It Works</h2>
422
- <p>This example demonstrates how to use Procaptcha in invisible mode with explicit rendering:</p>
423
- <ol>
424
- <li>Include the Procaptcha script with <code>?render=explicit</code> parameter</li>
425
- <li>Create a container div with <code>data-size="invisible"</code></li>
426
- <li>Define an <code>onloadCallback</code> function that renders the Procaptcha widget</li>
427
- <li>Add a click handler to your submit button that validates the form and executes Procaptcha</li>
428
- <li>When Procaptcha verification succeeds, your callback function is called</li>
429
- </ol>
430
- <p>The key elements are:</p>
431
- <pre>
432
- &lt;script type="module" src="./assets/procaptcha.bundle.js?render=explicit" async defer&gt;&lt;/script&gt;
433
-
434
- &lt;div id="procaptcha-container" data-size="invisible"&gt;&lt;/div&gt;
435
-
436
- &lt;script&gt;
437
- // Render the widget
438
- window.procaptcha.render('procaptcha-container', {
439
- 'siteKey': 'your_site_key',
440
- 'callback': onSubmit,
441
- 'size': 'invisible'
442
- });
615
+ <div id="result" class="info-box" style="display: none;"></div>
443
616
 
444
- // Execute the verification
445
- window.procaptcha.execute();
446
- &lt;/script&gt;
447
- </pre>
448
617
 
449
- <h3>Console Output</h3>
450
- <p>When you click the Submit button, the <code>execute()</code> function will:</p>
451
- <ol>
452
- <li>Find all Procaptcha containers on the page</li>
453
- <li>Log each container and its attributes to the console</li>
454
- <li>Log all child elements of each container</li>
455
- <li>Dispatch a custom <code>procaptcha:execute</code> event to show the modal</li>
456
- </ol>
457
- <p>This helps debug and understand how the invisible Procaptcha is structured in the DOM.</p>
458
-
459
- <h3>Event-Based Communication System</h3>
460
- <p>To connect the vanilla JavaScript bundle with the React components, we use a custom event system:</p>
461
- <ol>
462
- <li>When <code>window.procaptcha.execute()</code> is called, it dispatches a <code>procaptcha:execute</code> event</li>
463
- <li>The ProcaptchaWidget React component listens for this event</li>
464
- <li>When the event is received, the component sets <code>state.showModal = true</code></li>
465
- <li>This causes the CAPTCHA modal to appear and verification to begin</li>
466
- </ol>
467
- <p>This decoupled approach allows the JavaScript bundle to communicate with React components without direct references.</p>
618
+ <!-- Explanation will be injected by the explanation-injector plugin -->
468
619
  </div>
469
620
 
470
- <!-- Initialize Procaptcha with onload callback -->
471
621
 
472
622
  <script>
473
623
  document.addEventListener('DOMContentLoaded', function() {
474
624
  const toggleBtn = document.getElementById('nav-toggle');
475
625
  const navBar = document.getElementById('nav-topbar');
476
626
  const navHeader = document.getElementById('nav-header');
627
+ const isMobile = window.innerWidth <= 768;
477
628
 
478
629
  // Check if navigation was previously collapsed
479
630
  const navCollapsed = localStorage.getItem('navCollapsed') === 'true';
@@ -505,20 +656,21 @@ window.procaptcha.execute();
505
656
 
506
657
  // Toggle on button click
507
658
  toggleBtn.addEventListener('click', function(e) {
508
- e.stopPropagation(); // Prevent header click from firing
659
+ e.stopPropagation();
509
660
  toggleNav();
510
661
  });
511
662
 
512
- // Expand on toggle button hover when collapsed
513
- toggleBtn.addEventListener('mouseenter', function() {
514
- if (navBar.classList.contains('collapsed')) {
515
- expandNav();
516
- }
517
- });
663
+ // Expand on toggle button hover when collapsed (desktop only)
664
+ if (!isMobile) {
665
+ toggleBtn.addEventListener('mouseenter', function() {
666
+ if (navBar.classList.contains('collapsed')) {
667
+ expandNav();
668
+ }
669
+ });
670
+ }
518
671
 
519
672
  // Toggle on header click
520
673
  navHeader.addEventListener('click', function(e) {
521
- // Don't toggle if a link within the header was clicked
522
674
  if (e.target.tagName === 'A') {
523
675
  return;
524
676
  }
@@ -527,8 +679,199 @@ window.procaptcha.execute();
527
679
 
528
680
  // Make the header appear clickable with cursor style
529
681
  navHeader.style.cursor = 'pointer';
682
+
683
+ // Handle window resize
684
+ window.addEventListener('resize', function() {
685
+ const newIsMobile = window.innerWidth <= 768;
686
+ if (newIsMobile !== isMobile) {
687
+ if (newIsMobile) {
688
+ // On mobile, collapse the nav by default
689
+ collapseNav();
690
+ } else {
691
+ // On desktop, expand the nav by default
692
+ expandNav();
693
+ }
694
+ }
695
+ });
696
+
697
+ // Handle dropdown toggles
698
+ document.querySelectorAll('.nav-group-dropdown-btn').forEach(button => {
699
+ button.addEventListener('click', function(e) {
700
+ e.stopPropagation();
701
+ this.classList.toggle('open');
702
+ });
703
+ });
704
+
705
+ // Close dropdowns when clicking outside
706
+ document.addEventListener('click', function(e) {
707
+ if (!e.target.closest('.nav-group-dropdown')) {
708
+ document.querySelectorAll('.nav-group-dropdown-btn').forEach(button => {
709
+ button.classList.remove('open');
710
+ });
711
+ }
712
+ });
713
+ });
714
+ </script>
715
+
716
+
717
+ <button id="form-filler-button" class="form-filler-button" title="Fill all form fields with default values">
718
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
719
+ <path d="M3 17.25V21h3.75L17.81 9.94l-3.75-3.75L3 17.25zM20.71 7.04c.39-.39.39-1.02 0-1.41l-2.34-2.34c-.39-.39-1.02-.39-1.41 0l-1.83 1.83 3.75 3.75 1.83-1.83z"/>
720
+ </svg>
721
+ <span>Fill Form</span>
722
+ </button>
723
+
724
+ <script>
725
+ document.addEventListener('DOMContentLoaded', function() {
726
+ // Create a function to fill the form with sensible default values
727
+ function fillFormWithDefaults() {
728
+ // Get all input elements
729
+ const inputs = document.querySelectorAll('input, select, textarea');
730
+
731
+ // Record which elements were filled for status feedback
732
+ const filledElements = [];
733
+
734
+ // Process each input
735
+ inputs.forEach(input => {
736
+ let filled = true;
737
+
738
+ // Skip hidden inputs and those with existing values
739
+ if (input.type === 'hidden' || (input.value && input.value.trim() !== '')) {
740
+ filled = false;
741
+ }
742
+ // Handle different input types
743
+ else if (input.type === 'text') {
744
+ if (input.id.toLowerCase().includes('name') || input.name.toLowerCase().includes('name')) {
745
+ input.value = 'John Doe';
746
+ } else {
747
+ input.value = 'Default Text';
748
+ }
749
+ }
750
+ else if (input.type === 'email') {
751
+ input.value = 'test@example.com';
752
+ }
753
+ else if (input.type === 'password') {
754
+ input.value = 'Password123!';
755
+ }
756
+ else if (input.type === 'tel') {
757
+ input.value = '+1234567890';
758
+ }
759
+ else if (input.type === 'number') {
760
+ input.value = '42';
761
+ }
762
+ else if (input.type === 'url') {
763
+ input.value = 'https://example.com';
764
+ }
765
+ else if (input.type === 'date') {
766
+ const today = new Date();
767
+ const yyyy = today.getFullYear();
768
+ const mm = String(today.getMonth() + 1).padStart(2, '0');
769
+ const dd = String(today.getDate()).padStart(2, '0');
770
+ input.value = `${yyyy}-${mm}-${dd}`;
771
+ }
772
+ else if (input.type === 'time') {
773
+ input.value = '12:00';
774
+ }
775
+ else if (input.type === 'checkbox' || input.type === 'radio') {
776
+ input.checked = true;
777
+ }
778
+ else if (input.tagName === 'SELECT') {
779
+ if (input.options.length > 0) {
780
+ input.selectedIndex = 1 >= input.options.length ? 0 : 1; // Select second option if available, first otherwise
781
+ }
782
+ }
783
+ else if (input.tagName === 'TEXTAREA') {
784
+ input.value = 'This is a sample text for the textarea field.';
785
+ }
786
+ else {
787
+ // For any other input types
788
+ input.value = 'Default Value';
789
+ }
790
+
791
+ // Add to filled elements if we actually filled it
792
+ if (filled) {
793
+ filledElements.push(input);
794
+
795
+ // Dispatch input event to trigger any listeners
796
+ const event = new Event('input', { bubbles: true });
797
+ input.dispatchEvent(event);
798
+
799
+ // For select elements, also dispatch change event
800
+ if (input.tagName === 'SELECT') {
801
+ const changeEvent = new Event('change', { bubbles: true });
802
+ input.dispatchEvent(changeEvent);
803
+ }
804
+ }
805
+ });
806
+
807
+ // Show a notification about what was filled
808
+ if (filledElements.length > 0) {
809
+ // If an updateCaptchaStatus function exists (from our other demos), use it
810
+ if (typeof window.updateCaptchaStatus === 'function') {
811
+ window.updateCaptchaStatus(`Filled ${filledElements.length} form fields with default values`, 'info');
812
+ } else {
813
+ console.log(`Filled ${filledElements.length} form fields with default values`);
814
+ }
815
+
816
+ // Highlight the filled fields briefly
817
+ filledElements.forEach(el => {
818
+ const originalBackground = el.style.backgroundColor;
819
+ const originalTransition = el.style.transition;
820
+
821
+ el.style.transition = 'background-color 1.5s ease';
822
+ el.style.backgroundColor = '#e3f2fd';
823
+
824
+ setTimeout(() => {
825
+ el.style.backgroundColor = originalBackground;
826
+ setTimeout(() => {
827
+ el.style.transition = originalTransition;
828
+ }, 1500);
829
+ }, 500);
830
+ });
831
+ }
832
+ }
833
+
834
+ // Add the click event listener to the form filler button
835
+ const formFillerButton = document.getElementById('form-filler-button');
836
+ if (formFillerButton) {
837
+ formFillerButton.addEventListener('click', fillFormWithDefaults);
838
+ }
530
839
  });
531
840
  </script>
532
841
 
533
- </body>
842
+ <div class="explanation">
843
+ <h2>How Invisible Frictionless CAPTCHA Works (Explicit Rendering)</h2>
844
+
845
+ <h3>Implementation Details</h3>
846
+ <p>This example demonstrates how to use Procaptcha in frictionless mode with explicit rendering:</p>
847
+ <ol>
848
+ <li>Import the Procaptcha render function</li>
849
+ <li>Create a container for the CAPTCHA</li>
850
+ <li>Render the CAPTCHA explicitly</li>
851
+ <li>Handle the verification result in the callback function</li>
852
+ </ol>
853
+
854
+ <h3>Key Code Example</h3>
855
+ <pre>// Import the render function
856
+ import { render } from &quot;%VITE_BUNDLE_URL%&quot;
857
+ import { CaptchaType } from &quot;@prosopo/types&quot;;
858
+
859
+ // Render CAPTCHA
860
+ const widgetId = render(document.getElementById(&#39;procaptcha-container&#39;), {
861
+ siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
862
+ captchaType: CaptchaType.frictionless,
863
+ callback: handleCaptchaResponse,
864
+ &quot;failed-callback&quot;: handleCaptchaFailed,
865
+ size: &quot;invisible&quot;
866
+ });</pre>
867
+
868
+ <h3>Execution Flow</h3>
869
+ <ol>
870
+ <li>On page load, the render function is called to initialize</li>
871
+ <li>The CAPTCHA verification happens invisibly in the background</li>
872
+ <li>When verification is complete, the callback function is called with the token</li>
873
+ <li>On successful verification, the form can be submitted with the token</li>
874
+ </ol>
875
+ </div>
876
+ </body>
534
877
  </html>