@prosopo/client-bundle-example 2.10.24 → 2.11.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 (51) hide show
  1. package/.turbo/turbo-build$colon$cjs.log +5 -4
  2. package/.turbo/turbo-build$colon$tsc.log +11 -11
  3. package/.turbo/turbo-build.log +6 -5
  4. package/CHANGELOG.md +16 -0
  5. package/dist/cjs/index.cjs +13 -41
  6. package/dist/cjs/plugins/pages.cjs +113 -0
  7. package/dist/index.js +2 -42
  8. package/dist/plugins/pages.js +103 -0
  9. package/package.json +2 -2
  10. package/src/frictionless-explicit-web3.html +10 -23
  11. package/src/frictionless-explicit.html +10 -22
  12. package/src/frictionless-implicit.html +60 -86
  13. package/src/frictionless-manual-start.html +13 -33
  14. package/src/image-explicit-web3.html +8 -24
  15. package/src/image-explicit.html +8 -23
  16. package/src/image-implicit.html +192 -0
  17. package/src/index.html +11 -26
  18. package/src/index.ts +1 -62
  19. package/src/invisible-frictionless-explicit.html +8 -17
  20. package/src/invisible-frictionless-implicit.html +8 -25
  21. package/src/invisible-image-explicit.html +8 -23
  22. package/src/invisible-image-implicit.html +8 -24
  23. package/src/invisible-pow-explicit.html +8 -23
  24. package/src/invisible-pow-implicit.html +9 -21
  25. package/src/invisible-puzzle-explicit.html +8 -23
  26. package/src/invisible-puzzle-implicit.html +9 -21
  27. package/src/plugins/code-snippet-injector.ts +179 -0
  28. package/src/plugins/form-filler-injector.ts +36 -121
  29. package/src/plugins/layout-injector.ts +238 -0
  30. package/src/plugins/logo.ts +15 -0
  31. package/src/plugins/pages.ts +219 -0
  32. package/src/plugins/placement-injector.ts +25 -64
  33. package/src/plugins/slots.ts +32 -0
  34. package/src/plugins/status-log-injector.ts +35 -114
  35. package/src/pow-explicit-web3.html +8 -24
  36. package/src/pow-explicit.html +8 -23
  37. package/src/pow-implicit-sessionid.html +10 -24
  38. package/src/pow-implicit.html +9 -24
  39. package/src/puzzle-bind-explicit.html +9 -24
  40. package/src/puzzle-explicit.html +8 -23
  41. package/src/puzzle-implicit.html +9 -24
  42. package/src/styles/demo.css +803 -0
  43. package/src/tests/plugins.unit.test.ts +285 -118
  44. package/tsconfig.tsbuildinfo +1 -1
  45. package/vite.config.ts +5 -5
  46. package/src/plugins/explanation-injector.ts +0 -294
  47. package/src/plugins/navigation-injector.ts +0 -606
  48. package/src/styles/captcha.css +0 -78
  49. package/src/styles/field.css +0 -12
  50. package/src/tests/floatLabel.unit.test.ts +0 -195
  51. package/src/tests/floatLabelReady.unit.test.ts +0 -36
@@ -1,23 +1,11 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
- <link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
5
- <link href="styles/field.css" rel="stylesheet" type="text/css"/>
6
4
 
7
- <script src="index.js"></script>
8
- <link href="styles/captcha.css" rel="stylesheet" type="text/css"/>
9
- <title>Procaptcha demo: Frictionless CAPTCHA</title>
10
- <script type="text/javascript">
11
- window.onCaptchaFailed = function () {
12
- console.log('Challenge failed');
13
- updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
14
- }
15
- </script>
5
+ <title>Procaptcha demo: Frictionless, implicit rendering</title>
16
6
  <script type="module">
17
- // Function to update CAPTCHA status display is now provided by status-log-injector
18
7
 
19
8
  window.addEventListener('load', () => {
20
- updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
21
9
 
22
10
  window.setIsError = (isError) => {
23
11
  const messageContainer = document.getElementById('messageContainer');
@@ -32,12 +20,11 @@
32
20
  window.onLoggedIn = (token) => {
33
21
  updateCaptchaStatus('Logged in, fetching private resource', 'info');
34
22
  const url = new URL("/private", config.serverUrl).href;
35
- const origin = new URL(window.location.href).origin;
36
23
  console.log("getting private resource with token ", token, "at", url);
37
24
  fetch(url, {
38
25
  method: "GET",
39
26
  headers: {
40
- Origin: `${origin}`,
27
+ Origin: "http://localhost:9232", // TODO: change this to env var
41
28
  "Content-Type": "application/json",
42
29
  Authorization: `Bearer ${token}`,
43
30
  },
@@ -100,32 +87,34 @@
100
87
  json,
101
88
  })))
102
89
  })
103
- .then(async ({status, json, ok}) => {
104
- console.log("status", status, "json", json.message, "ok", ok);
105
- console.log("json", json)
106
- try {
107
- if (status !== 200) {
108
- updateCaptchaStatus(`API Error: ${json.message}`, 'error');
109
- setIsError(true);
110
- setMessage(json.message);
111
- } else {
112
- updateCaptchaStatus(`API Success: ${json.message}`, 'success');
113
- setIsError(false);
114
- setMessage(json.message);
90
+ .then(async ({status, json, ok}) => {
91
+ console.log("status", status, "json", json.message, "ok", ok);
92
+ console.log("json", json)
93
+ try {
94
+ if (status !== 200) {
95
+ updateCaptchaStatus(`API Error: ${json.message}`, 'error');
96
+ setIsError(true);
97
+ setMessage(json.message);
98
+ } else {
99
+ updateCaptchaStatus(`API Success: ${json.message}`, 'success');
100
+ setIsError(false);
101
+ setMessage(json.message);
102
+ }
103
+ } catch (err) {
104
+ console.log(err);
105
+ updateCaptchaStatus(`Error processing response: ${err}`, 'error');
115
106
  }
116
- } catch (err) {
107
+ })
108
+ .catch((err) => {
117
109
  console.log(err);
118
- updateCaptchaStatus(`Error processing response: ${err}`, 'error');
119
- }
120
- })
121
- .catch((err) => {
122
- console.log(err);
123
- updateCaptchaStatus(`Fetch error: ${err}`, 'error');
124
- setIsError(true);
125
- setMessage("Error: " + err);
126
- });
110
+ updateCaptchaStatus(`Fetch error: ${err}`, 'error');
111
+ setIsError(true);
112
+ setMessage("Error: " + err);
113
+ });
127
114
  };
128
115
 
116
+ updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
117
+
129
118
  // Monitor DOM for CAPTCHA initialization
130
119
  const observer = new MutationObserver((mutations) => {
131
120
  mutations.forEach((mutation) => {
@@ -146,73 +135,58 @@
146
135
  observer.observe(document.body, { childList: true, subtree: true });
147
136
  });
148
137
 
149
- // updateCaptchaStatus is now provided by status-log-injector
138
+ window.onCaptchaFailed = function () {
139
+ console.log('Challenge failed');
140
+ updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
141
+ }
142
+
143
+ window.onCaptchaVerified = (output) => {
144
+ console.log('Challenge passed');
145
+ updateCaptchaStatus('Challenge passed successfully!', 'success');
146
+ updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
147
+ }
148
+
149
+ // Add custom event listener for CAPTCHA verification stages
150
+ document.addEventListener('DOMContentLoaded', function() {
151
+ setTimeout(() => {
152
+ updateCaptchaStatus('CAPTCHA script loaded and initialized', 'info');
153
+ updateCaptchaStatus('Waiting for user interaction...', 'info');
154
+ }, 500);
155
+ });
150
156
  </script>
157
+ <script id="procaptchaScript" type="module" src="%VITE_BUNDLE_URL%" async defer></script>
151
158
  </head>
152
159
  <body>
153
160
 
154
- <div class="mui-container">
155
- <h1>Frictionless CAPTCHA - Explicit Rendering</h1>
156
- <p>This example demonstrates how to use Procaptcha in frictionless mode with explicit rendering.</p>
161
+ <div class="demo-card">
157
162
 
158
- <!-- CAPTCHA Status Display will be injected by the status-log-injector plugin -->
159
-
160
- <form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="mui-form">
161
- <h2>Example Login Form</h2>
162
- <div class="mui-textfield mui-textfield--float-label">
163
+ <form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="demo-form">
164
+ <h2>Create an account</h2>
165
+ <div class="demo-field">
163
166
  <label for="name">Name</label>
164
167
  <input id="name" type="text" name="name" required/>
165
168
  </div>
166
- <div class="mui-textfield mui-textfield--float-label">
169
+ <div class="demo-field">
167
170
  <label for="email">Email Address</label>
168
171
  <input id="email" type="email" name="email" required/>
169
172
  </div>
170
- <div class="mui-textfield mui-textfield--float-label">
173
+ <div class="demo-field">
171
174
  <label for="password">Password</label>
172
175
  <input id="password" type="password" name="password" required/>
173
176
  </div>
174
- <div class="mui-textfield mui-textfield--float-label">
175
- <div id="procaptcha-container"></div>
177
+ <div class="demo-field">
178
+ <div
179
+ class="procaptcha"
180
+ data-theme="light"
181
+ data-sitekey="%PROSOPO_SITE_KEY_FRICTIONLESS%"
182
+ data-failed-callback="onCaptchaFailed"
183
+ data-callback="onCaptchaVerified"
184
+ ></div>
176
185
  </div>
177
186
  <div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
178
- <button type="button" class="mui-btn mui-btn--raised" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
187
+ <button type="button" class="demo-button" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
179
188
  </form>
180
189
 
181
190
  </div>
182
- <script type="module">
183
- (async () => {
184
-
185
- const host = new URL(window.location.href).host;
186
-
187
- // Use predefined VITE_BUNDLE_URL or default to localhost with the same host as the page, to ensure we load the
188
- // bundle from the correct location in different environments
189
- const bundleUrl = import.meta.env.VITE_BUNDLE_URL || 'https://localhost:9269/procaptcha.bundle.js'.replace('localhost', host);
190
-
191
- // Pattern to avoid race condition between Procaptcha script loading and Procaptcha render function call
192
- const {render} = await import(bundleUrl);
193
-
194
- // Define a callback function to be called when the CAPTCHA is verified
195
- function onCaptchaVerified(output) {
196
- console.log('Challenge passed');
197
- window.updateCaptchaStatus('Challenge passed successfully!', 'success');
198
- window.updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
199
- }
200
-
201
- const captchaContainer = document.getElementById('procaptcha-container');
202
-
203
- // Render the CAPTCHA
204
- const widgetId = render(captchaContainer, {
205
- siteKey: import.meta.env.PROSOPO_SITE_KEY_FRICTIONLESS,
206
- callback: onCaptchaVerified,
207
- "failed-callback": function () {
208
- console.log('Challenge failed');
209
- window.updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
210
- }
211
- });
212
-
213
- window.updateCaptchaStatus('CAPTCHA render function called with widget ID: ' + widgetId, 'info');
214
- })();
215
- </script>
216
-
217
191
  </body>
218
192
  </html>
@@ -1,14 +1,9 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
- <link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
5
- <link href="styles/field.css" rel="stylesheet" type="text/css"/>
6
4
 
7
- <script src="index.js"></script>
8
- <title>Procaptcha demo: Frictionless - Manual Start</title>
9
- <link href="styles/captcha.css" rel="stylesheet" type="text/css"/>
5
+ <title>Procaptcha demo: Frictionless, manual start</title>
10
6
  <script type="module">
11
- // Function to update CAPTCHA status display is now provided by status-log-injector
12
7
 
13
8
  window.onStartCaptcha = () => {
14
9
  updateCaptchaStatus('window.procaptcha.start() called - frictionless flow starting', 'info');
@@ -145,7 +140,6 @@
145
140
  observer.observe(document.body, { childList: true, subtree: true });
146
141
  });
147
142
 
148
-
149
143
  window.onCaptchaFailed = function () {
150
144
  console.log('Challenge failed');
151
145
  updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
@@ -169,34 +163,24 @@
169
163
  </head>
170
164
  <body>
171
165
 
172
- <div class="mui-container">
173
- <h1>Frictionless CAPTCHA - Manual Start</h1>
174
- <p>
175
- This example renders the widget with <code>data-start-mode="manual"</code>. The checkbox appears
176
- immediately at its final size, but no bot detection, behavioural collection or provider request runs
177
- until either the page calls <code>window.procaptcha.start()</code> (the button below) or the visitor
178
- clicks the checkbox. A click that starts the flow also opens whichever challenge the provider picks,
179
- so the visitor never has to click twice.
180
- </p>
181
-
182
- <!-- CAPTCHA Status Display will be injected by the status-log-injector plugin -->
183
-
184
- <form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="mui-form">
185
- <h2>Example Login Form</h2>
186
- <div class="mui-textfield mui-textfield--float-label">
166
+ <div class="demo-card">
167
+
168
+ <form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="demo-form">
169
+ <h2>Create an account</h2>
170
+ <p class="demo-note">Nothing runs until you tick the box or press <strong>Start CAPTCHA now</strong>, which calls <code>window.procaptcha.start()</code>.</p>
171
+ <div class="demo-field">
187
172
  <label for="name">Name</label>
188
173
  <input id="name" type="text" name="name" required/>
189
174
  </div>
190
- <div class="mui-textfield mui-textfield--float-label">
175
+ <div class="demo-field">
191
176
  <label for="email">Email Address</label>
192
177
  <input id="email" type="email" name="email" required/>
193
178
  </div>
194
- <div class="mui-textfield mui-textfield--float-label">
179
+ <div class="demo-field">
195
180
  <label for="password">Password</label>
196
181
  <input id="password" type="password" name="password" required/>
197
182
  </div>
198
- <div class="mui-textfield mui-textfield--float-label">
199
- <!-- Dev sitekey -->
183
+ <div class="demo-field">
200
184
  <div
201
185
  class="procaptcha"
202
186
  data-theme="light"
@@ -206,19 +190,15 @@
206
190
  data-callback="onCaptchaVerified"
207
191
  ></div>
208
192
  </div>
209
- <div class="mui-textfield">
210
- <button type="button" class="mui-btn mui-btn--flat" onclick="onStartCaptcha()" data-cy="start-captcha-button">
193
+ <div class="demo-field">
194
+ <button type="button" class="demo-button demo-button--secondary" onclick="onStartCaptcha()" data-cy="start-captcha-button">
211
195
  Start CAPTCHA now
212
196
  </button>
213
197
  </div>
214
198
  <div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
215
- <button type="button" class="mui-btn mui-btn--raised" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
199
+ <button type="button" class="demo-button" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
216
200
  </form>
217
201
 
218
- <!-- Console output display area -->
219
- <div id="console-output" class="console-output" style="display: none;"></div>
220
-
221
- <!-- Explanation will be injected by the explanation-injector plugin -->
222
202
  </div>
223
203
  </body>
224
204
  </html>
@@ -1,14 +1,9 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
- <link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
5
- <link href="styles/field.css" rel="stylesheet" type="text/css"/>
6
4
 
7
- <script src="index.js"></script>
8
- <title>Procaptcha Image Mode - Explicit Rendering</title>
9
- <link href="styles/captcha.css" rel="stylesheet" type="text/css"/>
5
+ <title>Procaptcha demo: Image, explicit rendering, web3</title>
10
6
  <script type="module">
11
- // Function to update CAPTCHA status display is now provided by status-log-injector
12
7
 
13
8
  document.addEventListener('DOMContentLoaded', function() {
14
9
  updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
@@ -33,43 +28,33 @@
33
28
  observer.observe(document.body, { childList: true, subtree: true });
34
29
  });
35
30
 
36
- // updateCaptchaStatus is now provided by status-log-injector
37
31
  </script>
38
32
  </head>
39
33
  <body>
40
- <div class="mui-container">
41
- <h1>Procaptcha Image Mode - Explicit Rendering</h1>
42
- <p>This example demonstrates how to use Procaptcha in image mode with explicit rendering.</p>
34
+ <div class="demo-card">
43
35
 
44
- <!-- CAPTCHA Status Display will be injected by the status-log-injector plugin -->
36
+ <form id="demo-form" class="demo-form">
37
+ <h2>Create an account</h2>
45
38
 
46
- <form id="demo-form" class="mui-form">
47
- <h2>Example Form</h2>
48
-
49
- <div class="mui-textfield mui-textfield--float-label">
39
+ <div class="demo-field">
50
40
  <label for="name">Name</label>
51
41
  <input type="text" id="name" name="name" required />
52
42
  </div>
53
43
 
54
- <div class="mui-textfield mui-textfield--float-label">
44
+ <div class="demo-field">
55
45
  <label for="email">Email</label>
56
46
  <input type="email" id="email" name="email" required />
57
47
  </div>
58
48
 
59
- <!-- The container for the CAPTCHA -->
60
49
  <div id="procaptcha-container"></div>
61
50
 
62
- <button type="submit" class="mui-btn mui-btn--raised">Submit</button>
51
+ <button type="submit" class="demo-button">Submit</button>
63
52
 
64
53
  <div id="error"></div>
65
54
  </form>
66
55
 
67
- <div id="result" class="info-box" style="display: none;"></div>
68
-
69
- <!-- Console output display area -->
70
- <div id="console-output" class="console-output" style="display: none;"></div>
56
+ <div id="result" class="demo-result" style="display: none;"></div>
71
57
 
72
- <!-- Explanation will be injected by the explanation-injector plugin -->
73
58
  </div>
74
59
 
75
60
  <script type="module">
@@ -141,7 +126,6 @@
141
126
  // render a modal and get the user to select 1 account
142
127
  const accountSelect = document.createElement('select');
143
128
  accountSelect.id = 'account-select';
144
- accountSelect.classList.add('mui-select');
145
129
  accountSelect.classList.add('account-select');
146
130
  accounts.forEach((account) => {
147
131
  const option = document.createElement('option');
@@ -1,14 +1,9 @@
1
1
  <!doctype html>
2
2
  <html lang="en">
3
3
  <head>
4
- <link href="https://cdn.muicss.com/mui-0.10.3/css/mui.min.css" rel="stylesheet" type="text/css"/>
5
- <link href="styles/field.css" rel="stylesheet" type="text/css"/>
6
4
 
7
- <script src="index.js"></script>
8
- <title>Procaptcha Image Mode - Explicit Rendering</title>
9
- <link href="styles/captcha.css" rel="stylesheet" type="text/css"/>
5
+ <title>Procaptcha demo: Image, explicit rendering</title>
10
6
  <script type="module">
11
- // Function to update CAPTCHA status display is now provided by status-log-injector
12
7
 
13
8
  document.addEventListener('DOMContentLoaded', function() {
14
9
  updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
@@ -33,43 +28,33 @@
33
28
  observer.observe(document.body, { childList: true, subtree: true });
34
29
  });
35
30
 
36
- // updateCaptchaStatus is now provided by status-log-injector
37
31
  </script>
38
32
  </head>
39
33
  <body>
40
- <div class="mui-container">
41
- <h1>Procaptcha Image Mode - Explicit Rendering</h1>
42
- <p>This example demonstrates how to use Procaptcha in image mode with explicit rendering.</p>
34
+ <div class="demo-card">
43
35
 
44
- <!-- CAPTCHA Status Display will be injected by the status-log-injector plugin -->
36
+ <form id="demo-form" class="demo-form">
37
+ <h2>Create an account</h2>
45
38
 
46
- <form id="demo-form" class="mui-form">
47
- <h2>Example Form</h2>
48
-
49
- <div class="mui-textfield mui-textfield--float-label">
39
+ <div class="demo-field">
50
40
  <label for="name">Name</label>
51
41
  <input type="text" id="name" name="name" required />
52
42
  </div>
53
43
 
54
- <div class="mui-textfield mui-textfield--float-label">
44
+ <div class="demo-field">
55
45
  <label for="email">Email</label>
56
46
  <input type="email" id="email" name="email" required />
57
47
  </div>
58
48
 
59
- <!-- The container for the CAPTCHA -->
60
49
  <div id="procaptcha-container"></div>
61
50
 
62
- <button type="submit" class="mui-btn mui-btn--raised">Submit</button>
51
+ <button type="submit" class="demo-button">Submit</button>
63
52
 
64
53
  <div id="error"></div>
65
54
  </form>
66
55
 
67
- <div id="result" class="info-box" style="display: none;"></div>
68
-
69
- <!-- Console output display area -->
70
- <div id="console-output" class="console-output" style="display: none;"></div>
56
+ <div id="result" class="demo-result" style="display: none;"></div>
71
57
 
72
- <!-- Explanation will be injected by the explanation-injector plugin -->
73
58
  </div>
74
59
 
75
60
  <script type="module">
@@ -0,0 +1,192 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+
5
+ <title>Procaptcha demo: Image, implicit rendering</title>
6
+ <script type="module">
7
+
8
+ window.addEventListener('load', () => {
9
+
10
+ window.setIsError = (isError) => {
11
+ const messageContainer = document.getElementById('messageContainer');
12
+ messageContainer.style.color = isError ? 'red' : 'black';
13
+ messageContainer.style.display = 'block';
14
+ };
15
+
16
+ window.setMessage = (message) => {
17
+ document.getElementById('message').innerText = message;
18
+ };
19
+
20
+ window.onLoggedIn = (token) => {
21
+ updateCaptchaStatus('Logged in, fetching private resource', 'info');
22
+ const url = new URL("/private", config.serverUrl).href;
23
+ console.log("getting private resource with token ", token, "at", url);
24
+ fetch(url, {
25
+ method: "GET",
26
+ headers: {
27
+ Origin: "http://localhost:9232", // TODO: change this to env var
28
+ "Content-Type": "application/json",
29
+ Authorization: `Bearer ${token}`,
30
+ },
31
+ })
32
+ .then(async (res) => {
33
+ try {
34
+ const jsonRes = await res.json();
35
+ if (res.status === 200) {
36
+ updateCaptchaStatus(`Successfully accessed private resource`, 'success');
37
+ setMessage(jsonRes.message);
38
+ } else {
39
+ updateCaptchaStatus(`Failed to access private resource: ${res.status}`, 'error');
40
+ }
41
+ } catch (err) {
42
+ console.log(err);
43
+ updateCaptchaStatus(`Error parsing response: ${err}`, 'error');
44
+ }
45
+ })
46
+ .catch((err) => {
47
+ console.log(err);
48
+ updateCaptchaStatus(`Fetch error: ${err}`, 'error');
49
+ });
50
+ };
51
+
52
+ window.onActionHandler = () => {
53
+ updateCaptchaStatus('Form submission initiated', 'info');
54
+
55
+ const procaptchaElements = document.getElementsByName('procaptcha-response');
56
+
57
+ if (!procaptchaElements.length) {
58
+ updateCaptchaStatus('Error: No CAPTCHA response found', 'error');
59
+ alert("Must complete captcha");
60
+ return
61
+ }
62
+
63
+ const procaptchaToken = procaptchaElements[0].value;
64
+ updateCaptchaStatus(`Token received: ${procaptchaToken.substring(0, 15)}...`, 'success');
65
+
66
+ const payload = {
67
+ email: document.getElementById('email').value,
68
+ name: document.getElementById('name').value,
69
+ password: document.getElementById('password').value,
70
+ siteKey: import.meta.env.PROSOPO_SITE_KEY_IMAGE,
71
+ "procaptcha-response": procaptchaToken,
72
+ };
73
+ const url = new URL('signup', import.meta.env.PROSOPO_SERVER_URL).href;
74
+ console.log("posting to", url, "with payload", payload);
75
+ fetch(url, {
76
+ method: "POST",
77
+ headers: {
78
+ "Content-Type": "application/json",
79
+ },
80
+ body: JSON.stringify(payload),
81
+ contentType: "application/json",
82
+ }).then((response) => {
83
+ return new Promise((resolve) => response.json()
84
+ .then((json) => resolve({
85
+ status: response.status,
86
+ ok: response.ok,
87
+ json,
88
+ })))
89
+ })
90
+ .then(async ({status, json, ok}) => {
91
+ console.log("status", status, "json", json.message, "ok", ok);
92
+ console.log("json", json)
93
+ try {
94
+ if (status !== 200) {
95
+ updateCaptchaStatus(`API Error: ${json.message}`, 'error');
96
+ setIsError(true);
97
+ setMessage(json.message);
98
+ } else {
99
+ updateCaptchaStatus(`API Success: ${json.message}`, 'success');
100
+ setIsError(false);
101
+ setMessage(json.message);
102
+ }
103
+ } catch (err) {
104
+ console.log(err);
105
+ updateCaptchaStatus(`Error processing response: ${err}`, 'error');
106
+ }
107
+ })
108
+ .catch((err) => {
109
+ console.log(err);
110
+ updateCaptchaStatus(`Fetch error: ${err}`, 'error');
111
+ setIsError(true);
112
+ setMessage("Error: " + err);
113
+ });
114
+ };
115
+
116
+ updateCaptchaStatus('Page loaded - Initializing CAPTCHA system', 'info');
117
+
118
+ // Monitor DOM for CAPTCHA initialization
119
+ const observer = new MutationObserver((mutations) => {
120
+ mutations.forEach((mutation) => {
121
+ if (mutation.addedNodes.length) {
122
+ for (let i = 0; i < mutation.addedNodes.length; i++) {
123
+ const node = mutation.addedNodes[i];
124
+ if (node.classList && (node.classList.contains('procaptcha') ||
125
+ node.querySelector && node.querySelector('.procaptcha'))) {
126
+ updateCaptchaStatus('CAPTCHA DOM elements initialized', 'info');
127
+ observer.disconnect();
128
+ break;
129
+ }
130
+ }
131
+ }
132
+ });
133
+ });
134
+
135
+ observer.observe(document.body, { childList: true, subtree: true });
136
+ });
137
+
138
+ window.onCaptchaFailed = function () {
139
+ console.log('Challenge failed');
140
+ updateCaptchaStatus('Challenge failed - CAPTCHA verification could not be completed', 'error');
141
+ }
142
+
143
+ window.onCaptchaVerified = (output) => {
144
+ console.log('Challenge passed');
145
+ updateCaptchaStatus('Challenge passed successfully!', 'success');
146
+ updateCaptchaStatus(`Token generated: ${output.substring(0, 15)}...`, 'success');
147
+ }
148
+
149
+ // Add custom event listener for CAPTCHA verification stages
150
+ document.addEventListener('DOMContentLoaded', function() {
151
+ setTimeout(() => {
152
+ updateCaptchaStatus('CAPTCHA script loaded and initialized', 'info');
153
+ updateCaptchaStatus('Waiting for user interaction...', 'info');
154
+ }, 500);
155
+ });
156
+ </script>
157
+ <script id="procaptchaScript" type="module" src="%VITE_BUNDLE_URL%" async defer></script>
158
+ </head>
159
+ <body>
160
+
161
+ <div class="demo-card">
162
+
163
+ <form action="%PROSOPO_SERVER_URL%/signup" method="POST" class="demo-form">
164
+ <h2>Create an account</h2>
165
+ <div class="demo-field">
166
+ <label for="name">Name</label>
167
+ <input id="name" type="text" name="name" required/>
168
+ </div>
169
+ <div class="demo-field">
170
+ <label for="email">Email Address</label>
171
+ <input id="email" type="email" name="email" required/>
172
+ </div>
173
+ <div class="demo-field">
174
+ <label for="password">Password</label>
175
+ <input id="password" type="password" name="password" required/>
176
+ </div>
177
+ <div class="demo-field">
178
+ <div
179
+ class="procaptcha"
180
+ data-theme="light"
181
+ data-sitekey="%PROSOPO_SITE_KEY_IMAGE%"
182
+ data-failed-callback="onCaptchaFailed"
183
+ data-callback="onCaptchaVerified"
184
+ ></div>
185
+ </div>
186
+ <div id="messageContainer" style="display: none; color: black;"><span id="message"></span></div>
187
+ <button type="button" class="demo-button" onclick="onActionHandler()" data-cy="submit-button">Submit</button>
188
+ </form>
189
+
190
+ </div>
191
+ </body>
192
+ </html>