@prosopo/client-bundle-example 2.7.0 → 2.8.0

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