@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.
- package/CHANGELOG.md +10 -0
- package/dist/assets/{ProcaptchaWidget-3gKvjeiH.js → ProcaptchaWidget-DrBDhP6X.js} +7 -7
- package/dist/assets/{ProcaptchaWidget-D6-M7iAv.js → ProcaptchaWidget-rAM-9Rap.js} +4 -4
- package/dist/assets/{asU8a-DCECA0Qe.js → asU8a-CJdNkNEq.js} +1 -1
- package/dist/assets/{bip39-BQoZog_M.js → bip39-Du2cANEV.js} +2 -2
- package/dist/assets/captcha-BhkVCEXM.css +1 -0
- package/dist/assets/{captchaComponentProvider-BW2eXmc3.js → captchaComponentProvider-DmV1WTrT.js} +4 -4
- package/dist/assets/{captchaRenderer-B_MgGzr9.js → captchaRenderer-RIsSZXCC.js} +2 -2
- package/dist/assets/{emotion-element-5486c51c.browser.esm-CCAJ8JId.js → emotion-element-5486c51c.browser.esm-C3u8NMUC.js} +127 -125
- package/dist/assets/frictionless-explicit-Dq_sNGRK.js +1 -0
- package/dist/assets/frictionless-implicit-Dq_sNGRK.js +1 -0
- package/dist/assets/{hash-BR0YLxPF.js → hash-_rWungeW.js} +1 -1
- package/dist/assets/image-explicit-DQvfVB7-.js +4 -0
- package/dist/assets/image-implicit-Bwa9QJO5.js +1 -0
- package/dist/assets/{index-WqEmiYQ_.js → index-BVr9fC_3.js} +4 -4
- package/dist/assets/{index-BYUYvvuq.js → index-Cu5oL_7b.js} +4 -4
- package/dist/assets/index-Dpt_5E72.js +1 -0
- package/dist/assets/{index-BCjHZ8o6.js → index-DxIFpl6U.js} +1 -1
- package/dist/assets/{index-2or4-1WF.js → index-Wgw2GQWq.js} +2 -2
- package/dist/assets/invisible-frictionless-explicit-DugBtRe4.js +4 -0
- package/dist/assets/invisible-frictionless-implicit-DYYos8W9.js +1 -0
- package/dist/assets/invisible-image-explicit-C5Z4gSb1.js +4 -0
- package/dist/assets/invisible-image-implicit-DfNFNlFj.js +1 -0
- package/dist/assets/invisible-pow-explicit-DjqGWFUb.js +4 -0
- package/dist/assets/invisible-pow-implicit-BRXL14FH.js +4 -0
- package/dist/assets/pow-explicit-BexxbnHM.js +4 -0
- package/dist/assets/pow-implicit-Dpt_5E72.js +1 -0
- package/dist/assets/procaptcha.bundle.js +1 -1
- package/dist/assets/{useTranslation-BPbGzrhj.js → useTranslation-CJplXtqb.js} +1 -1
- package/dist/frictionless-explicit.html +881 -0
- package/dist/frictionless-implicit.html +874 -0
- package/dist/image-explicit.html +877 -0
- package/dist/index.html +575 -74
- package/dist/invisible-frictionless-explicit.html +626 -283
- package/dist/invisible-frictionless-implicit.html +631 -173
- package/dist/invisible-image-explicit.html +627 -284
- package/dist/invisible-image-implicit.html +631 -173
- package/dist/invisible-pow-explicit.html +627 -284
- package/dist/invisible-pow-implicit.html +629 -177
- package/dist/plugins/explanation-injector.ts +250 -0
- package/dist/plugins/form-filler-injector.ts +233 -0
- package/dist/plugins/navigation-injector.ts +237 -89
- package/dist/plugins/status-log-injector.ts +199 -0
- package/dist/pow-explicit.html +877 -0
- package/dist/pow-implicit.html +881 -0
- package/package.json +1 -1
- package/vite.config.ts +32 -3
- package/dist/assets/frictionless-ZgzyuneX.js +0 -1
- package/dist/assets/index-BWsu-rGU.js +0 -1
- package/dist/assets/invisible-frictionless-explicit-DgCaJtPg.js +0 -1
- package/dist/assets/invisible-image-explicit-DgCaJtPg.js +0 -1
- package/dist/assets/invisible-pow-explicit-DgCaJtPg.js +0 -1
- package/dist/assets/pow-BW3QYcgP.js +0 -1
- package/dist/frictionless.html +0 -343
- package/dist/pow.html +0 -323
- /package/dist/assets/{modulepreload-polyfill-B5Qt9EMX.js → captcha-ByKnSsbG.js} +0 -0
|
@@ -0,0 +1,877 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
|
|
5
|
+
<title>Procaptcha Image Mode - Explicit Rendering</title>
|
|
6
|
+
|
|
7
|
+
<style>
|
|
8
|
+
.nav-topbar {
|
|
9
|
+
background-color: #2196F3;
|
|
10
|
+
padding: 0;
|
|
11
|
+
margin-bottom: 20px;
|
|
12
|
+
transition: all 0.3s ease;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
max-height: 500px;
|
|
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;
|
|
17
|
+
}
|
|
18
|
+
.nav-topbar.collapsed {
|
|
19
|
+
max-height: 60px;
|
|
20
|
+
}
|
|
21
|
+
.nav-container {
|
|
22
|
+
max-width: 1200px;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
padding: 0 20px;
|
|
25
|
+
position: relative;
|
|
26
|
+
}
|
|
27
|
+
.nav-header {
|
|
28
|
+
display: flex;
|
|
29
|
+
justify-content: space-between;
|
|
30
|
+
align-items: center;
|
|
31
|
+
padding: 12px 0;
|
|
32
|
+
position: relative;
|
|
33
|
+
z-index: 20;
|
|
34
|
+
}
|
|
35
|
+
.nav-title {
|
|
36
|
+
color: white;
|
|
37
|
+
font-size: 1.25rem;
|
|
38
|
+
font-weight: 600;
|
|
39
|
+
margin: 0;
|
|
40
|
+
display: flex;
|
|
41
|
+
align-items: center;
|
|
42
|
+
gap: 8px;
|
|
43
|
+
}
|
|
44
|
+
.nav-title-text {
|
|
45
|
+
margin-right: 8px;
|
|
46
|
+
}
|
|
47
|
+
.nav-title-hint {
|
|
48
|
+
font-size: 0.875rem;
|
|
49
|
+
font-weight: normal;
|
|
50
|
+
opacity: 0;
|
|
51
|
+
transition: opacity 0.3s ease;
|
|
52
|
+
color: rgba(255,255,255,0.8);
|
|
53
|
+
}
|
|
54
|
+
.collapsed .nav-title-hint {
|
|
55
|
+
opacity: 0.8;
|
|
56
|
+
}
|
|
57
|
+
.nav-toggle {
|
|
58
|
+
background-color: rgba(255,255,255,0.1);
|
|
59
|
+
color: white;
|
|
60
|
+
border: none;
|
|
61
|
+
padding: 8px 12px;
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
border-radius: 6px;
|
|
64
|
+
z-index: 10;
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
justify-content: center;
|
|
68
|
+
transition: background-color 0.2s ease;
|
|
69
|
+
}
|
|
70
|
+
.nav-toggle:hover {
|
|
71
|
+
background-color: rgba(255,255,255,0.2);
|
|
72
|
+
}
|
|
73
|
+
.nav-toggle-icon {
|
|
74
|
+
width: 24px;
|
|
75
|
+
height: 24px;
|
|
76
|
+
display: inline-block;
|
|
77
|
+
position: relative;
|
|
78
|
+
}
|
|
79
|
+
.nav-toggle-icon svg {
|
|
80
|
+
position: absolute;
|
|
81
|
+
top: 0;
|
|
82
|
+
left: 0;
|
|
83
|
+
transition: opacity 0.3s ease;
|
|
84
|
+
}
|
|
85
|
+
.nav-toggle-icon .icon-collapse {
|
|
86
|
+
opacity: 1;
|
|
87
|
+
}
|
|
88
|
+
.nav-toggle-icon .icon-expand {
|
|
89
|
+
opacity: 0;
|
|
90
|
+
}
|
|
91
|
+
.collapsed .nav-toggle-icon .icon-collapse {
|
|
92
|
+
opacity: 0;
|
|
93
|
+
}
|
|
94
|
+
.collapsed .nav-toggle-icon .icon-expand {
|
|
95
|
+
opacity: 1;
|
|
96
|
+
}
|
|
97
|
+
.nav-content {
|
|
98
|
+
padding: 0 0 20px 0;
|
|
99
|
+
transition: opacity 0.3s ease;
|
|
100
|
+
}
|
|
101
|
+
.collapsed .nav-content {
|
|
102
|
+
opacity: 0;
|
|
103
|
+
}
|
|
104
|
+
.nav-sections {
|
|
105
|
+
display: flex;
|
|
106
|
+
flex-wrap: wrap;
|
|
107
|
+
gap: 20px;
|
|
108
|
+
}
|
|
109
|
+
.nav-section {
|
|
110
|
+
flex: 1;
|
|
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;
|
|
126
|
+
}
|
|
127
|
+
.nav-group-title {
|
|
128
|
+
color: rgba(255,255,255,0.9);
|
|
129
|
+
font-size: 0.875rem;
|
|
130
|
+
font-weight: 500;
|
|
131
|
+
margin: 0 0 8px 0;
|
|
132
|
+
text-transform: uppercase;
|
|
133
|
+
letter-spacing: 0.5px;
|
|
134
|
+
}
|
|
135
|
+
.nav-group-links {
|
|
136
|
+
list-style: none;
|
|
137
|
+
margin: 0;
|
|
138
|
+
padding: 0;
|
|
139
|
+
}
|
|
140
|
+
.nav-group-links li {
|
|
141
|
+
margin: 6px 0;
|
|
142
|
+
}
|
|
143
|
+
.nav-group-links a {
|
|
144
|
+
color: white;
|
|
145
|
+
text-decoration: none;
|
|
146
|
+
font-weight: 500;
|
|
147
|
+
padding: 6px 8px;
|
|
148
|
+
display: inline-block;
|
|
149
|
+
border-radius: 4px;
|
|
150
|
+
transition: background-color 0.2s ease;
|
|
151
|
+
}
|
|
152
|
+
.nav-group-links a:hover {
|
|
153
|
+
background-color: rgba(255,255,255,0.2);
|
|
154
|
+
}
|
|
155
|
+
.nav-group-links .active {
|
|
156
|
+
background-color: rgba(255,255,255,0.2);
|
|
157
|
+
font-weight: 600;
|
|
158
|
+
}
|
|
159
|
+
.nav-group-links .disabled {
|
|
160
|
+
color: rgba(255,255,255,0.5);
|
|
161
|
+
cursor: not-allowed;
|
|
162
|
+
opacity: 0.7;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
@media (max-width: 768px) {
|
|
166
|
+
.nav-container {
|
|
167
|
+
padding: 0 16px;
|
|
168
|
+
}
|
|
169
|
+
.nav-title {
|
|
170
|
+
font-size: 1.125rem;
|
|
171
|
+
}
|
|
172
|
+
.nav-title-hint {
|
|
173
|
+
display: none;
|
|
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/image-explicit-DQvfVB7-.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
|
+
}
|
|
346
|
+
}
|
|
347
|
+
</style>
|
|
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>
|
|
483
|
+
</head>
|
|
484
|
+
<body>
|
|
485
|
+
|
|
486
|
+
<div id="nav-topbar" class="nav-topbar">
|
|
487
|
+
<div class="nav-container">
|
|
488
|
+
<div id="nav-header" class="nav-header">
|
|
489
|
+
<h1 class="nav-title">
|
|
490
|
+
<span class="nav-title-text">Procaptcha Demo Playground</span>
|
|
491
|
+
<span class="nav-title-hint">(Click anywhere to see more examples)</span>
|
|
492
|
+
</h1>
|
|
493
|
+
<button id="nav-toggle" class="nav-toggle" aria-label="Toggle navigation">
|
|
494
|
+
<span class="nav-toggle-icon">
|
|
495
|
+
<svg class="icon-collapse" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
496
|
+
<polyline points="18 15 12 9 6 15"></polyline>
|
|
497
|
+
</svg>
|
|
498
|
+
<svg class="icon-expand" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
499
|
+
<polyline points="6 9 12 15 18 9"></polyline>
|
|
500
|
+
</svg>
|
|
501
|
+
</span>
|
|
502
|
+
</button>
|
|
503
|
+
</div>
|
|
504
|
+
<div class="nav-content">
|
|
505
|
+
<div class="nav-sections">
|
|
506
|
+
|
|
507
|
+
<div class="nav-section">
|
|
508
|
+
<h3>Standard Captchas</h3>
|
|
509
|
+
<div class="nav-row">
|
|
510
|
+
|
|
511
|
+
<div class="nav-group">
|
|
512
|
+
<div class="nav-group-title">Image</div>
|
|
513
|
+
<div class="nav-group-links">
|
|
514
|
+
<a href="image-implicit.html">Implicit</a>
|
|
515
|
+
<a href="image-explicit.html" class="active">Explicit</a>
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
|
|
519
|
+
|
|
520
|
+
<div class="nav-group">
|
|
521
|
+
<div class="nav-group-title">Pow</div>
|
|
522
|
+
<div class="nav-group-links">
|
|
523
|
+
<a href="pow-implicit.html">Implicit</a>
|
|
524
|
+
<a href="pow-explicit.html">Explicit</a>
|
|
525
|
+
</div>
|
|
526
|
+
</div>
|
|
527
|
+
|
|
528
|
+
|
|
529
|
+
<div class="nav-group">
|
|
530
|
+
<div class="nav-group-title">Frictionless</div>
|
|
531
|
+
<div class="nav-group-links">
|
|
532
|
+
<a href="frictionless-implicit.html">Implicit</a>
|
|
533
|
+
<a href="frictionless-explicit.html">Explicit</a>
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
|
|
537
|
+
</div>
|
|
538
|
+
</div>
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
<div class="nav-section">
|
|
542
|
+
<h3>Invisible Captchas</h3>
|
|
543
|
+
<div class="nav-row">
|
|
544
|
+
|
|
545
|
+
<div class="nav-group">
|
|
546
|
+
<div class="nav-group-title">Image</div>
|
|
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>
|
|
551
|
+
</div>
|
|
552
|
+
|
|
553
|
+
|
|
554
|
+
<div class="nav-group">
|
|
555
|
+
<div class="nav-group-title">Pow</div>
|
|
556
|
+
<div class="nav-group-links">
|
|
557
|
+
<a href="invisible-pow-implicit.html">Implicit</a>
|
|
558
|
+
<a href="invisible-pow-explicit.html">Explicit</a>
|
|
559
|
+
</div>
|
|
560
|
+
</div>
|
|
561
|
+
|
|
562
|
+
|
|
563
|
+
<div class="nav-group">
|
|
564
|
+
<div class="nav-group-title">Frictionless</div>
|
|
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>
|
|
569
|
+
</div>
|
|
570
|
+
|
|
571
|
+
</div>
|
|
572
|
+
</div>
|
|
573
|
+
|
|
574
|
+
</div>
|
|
575
|
+
</div>
|
|
576
|
+
</div>
|
|
577
|
+
</div>
|
|
578
|
+
|
|
579
|
+
<div class="mui-container">
|
|
580
|
+
<h1>Procaptcha Image Mode - Explicit Rendering</h1>
|
|
581
|
+
<p>This example demonstrates how to use Procaptcha in image mode with explicit rendering.</p>
|
|
582
|
+
|
|
583
|
+
<!-- CAPTCHA Status Display will be injected by the status-log-injector plugin -->
|
|
584
|
+
|
|
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
|
+
|
|
613
|
+
|
|
614
|
+
<div id="result" class="info-box" style="display: none;"></div>
|
|
615
|
+
|
|
616
|
+
<!-- Console output display area -->
|
|
617
|
+
<div id="console-output" class="console-output" style="display: none;"></div>
|
|
618
|
+
|
|
619
|
+
<!-- Explanation will be injected by the explanation-injector plugin -->
|
|
620
|
+
</div>
|
|
621
|
+
|
|
622
|
+
|
|
623
|
+
<script>
|
|
624
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
625
|
+
const toggleBtn = document.getElementById('nav-toggle');
|
|
626
|
+
const navBar = document.getElementById('nav-topbar');
|
|
627
|
+
const navHeader = document.getElementById('nav-header');
|
|
628
|
+
const isMobile = window.innerWidth <= 768;
|
|
629
|
+
|
|
630
|
+
// Check if navigation was previously collapsed
|
|
631
|
+
const navCollapsed = localStorage.getItem('navCollapsed') === 'true';
|
|
632
|
+
if (navCollapsed) {
|
|
633
|
+
navBar.classList.add('collapsed');
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
// Function to expand the navigation
|
|
637
|
+
function expandNav() {
|
|
638
|
+
if (navBar.classList.contains('collapsed')) {
|
|
639
|
+
navBar.classList.remove('collapsed');
|
|
640
|
+
localStorage.setItem('navCollapsed', 'false');
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// Function to collapse the navigation
|
|
645
|
+
function collapseNav() {
|
|
646
|
+
if (!navBar.classList.contains('collapsed')) {
|
|
647
|
+
navBar.classList.add('collapsed');
|
|
648
|
+
localStorage.setItem('navCollapsed', 'true');
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
// Function to toggle the navigation
|
|
653
|
+
function toggleNav() {
|
|
654
|
+
navBar.classList.toggle('collapsed');
|
|
655
|
+
localStorage.setItem('navCollapsed', navBar.classList.contains('collapsed'));
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
// Toggle on button click
|
|
659
|
+
toggleBtn.addEventListener('click', function(e) {
|
|
660
|
+
e.stopPropagation();
|
|
661
|
+
toggleNav();
|
|
662
|
+
});
|
|
663
|
+
|
|
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
|
+
}
|
|
672
|
+
|
|
673
|
+
// Toggle on header click
|
|
674
|
+
navHeader.addEventListener('click', function(e) {
|
|
675
|
+
if (e.target.tagName === 'A') {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
toggleNav();
|
|
679
|
+
});
|
|
680
|
+
|
|
681
|
+
// Make the header appear clickable with cursor style
|
|
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
|
+
}
|
|
840
|
+
});
|
|
841
|
+
</script>
|
|
842
|
+
|
|
843
|
+
<div class="explanation">
|
|
844
|
+
<h2>How Image CAPTCHA Works (Explicit Rendering)</h2>
|
|
845
|
+
|
|
846
|
+
<h3>Implementation Details</h3>
|
|
847
|
+
<p>This example demonstrates how to use Procaptcha in image 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 "%VITE_BUNDLE_URL%"
|
|
858
|
+
import { CaptchaType } from "@prosopo/types";
|
|
859
|
+
|
|
860
|
+
// Render CAPTCHA
|
|
861
|
+
const widgetId = render(document.getElementById('procaptcha-container'), {
|
|
862
|
+
siteKey: import.meta.env.PROSOPO_SITE_KEY_IMAGE,
|
|
863
|
+
captchaType: CaptchaType.image,
|
|
864
|
+
callback: handleCaptchaResponse,
|
|
865
|
+
"failed-callback": handleCaptchaFailed
|
|
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 challenge is rendered in the specified container</li>
|
|
872
|
+
<li>When the user completes the challenge, the callback function is called</li>
|
|
873
|
+
<li>On successful verification, the form can be submitted with the token</li>
|
|
874
|
+
</ol>
|
|
875
|
+
</div>
|
|
876
|
+
</body>
|
|
877
|
+
</html>
|