@prosopo/procaptcha-puzzle 2.10.45 → 2.10.46

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prosopo/procaptcha-puzzle",
3
- "version": "2.10.45",
3
+ "version": "2.10.46",
4
4
  "author": "PROSOPO LIMITED <info@prosopo.io>",
5
5
  "license": "Apache-2.0",
6
6
  "main": "dist/index.js",
@@ -33,14 +33,14 @@
33
33
  "browserslist": ["> 0.5%, last 2 versions, not dead"],
34
34
  "dependencies": {
35
35
  "@polkadot/util": "13.5.7",
36
- "@prosopo/api": "4.0.2",
37
- "@prosopo/common": "3.1.49",
38
- "@prosopo/locale": "3.2.9",
39
- "@prosopo/procaptcha-common": "2.11.22",
40
- "@prosopo/types": "5.0.2",
41
- "@prosopo/util": "3.3.5",
36
+ "@prosopo/api": "4.0.3",
37
+ "@prosopo/common": "3.1.50",
38
+ "@prosopo/locale": "3.3.0",
39
+ "@prosopo/procaptcha-common": "2.11.23",
40
+ "@prosopo/types": "5.0.3",
41
+ "@prosopo/util": "3.3.6",
42
42
  "@prosopo/util-crypto": "13.5.30",
43
- "@prosopo/widget-skeleton": "2.8.5",
43
+ "@prosopo/widget-skeleton": "2.8.6",
44
44
  "react": "18.3.1"
45
45
  },
46
46
  "devDependencies": {
@@ -14,7 +14,7 @@
14
14
 
15
15
  import { loadI18next, useTranslation } from "@prosopo/locale";
16
16
  import { buildUpdateState, useProcaptcha } from "@prosopo/procaptcha-common";
17
- import { Checkbox, Honeypot } from "@prosopo/procaptcha-common";
17
+ import { Checkbox, Honeypot, isEventTrusted } from "@prosopo/procaptcha-common";
18
18
  import {
19
19
  type GetPuzzleCaptchaResponse,
20
20
  ModeEnum,
@@ -230,6 +230,7 @@ const Procaptcha = (props: ProcaptchaProps) => {
230
230
  onComplete={handlePuzzleComplete}
231
231
  showRetry={showRetry}
232
232
  submitting={puzzlePhase === "submitting"}
233
+ theme={theme}
233
234
  />
234
235
  )}
235
236
 
@@ -251,7 +252,7 @@ const Procaptcha = (props: ProcaptchaProps) => {
251
252
  let x = 0;
252
253
  let y = 0;
253
254
  const mouseOrTouchEvent = event.nativeEvent;
254
- if (!mouseOrTouchEvent.isTrusted) {
255
+ if (!isEventTrusted(mouseOrTouchEvent)) {
255
256
  // Don't capture coordinates for non-trusted events
256
257
  } else if (
257
258
  "touches" in mouseOrTouchEvent &&
@@ -13,6 +13,7 @@
13
13
  // limitations under the License.
14
14
 
15
15
  import type { PuzzleEvent } from "@prosopo/types";
16
+ import type { Theme } from "@prosopo/widget-skeleton";
16
17
  import { useCallback, useEffect, useRef, useState } from "react";
17
18
 
18
19
  interface PuzzleCanvasProps {
@@ -27,6 +28,7 @@ interface PuzzleCanvasProps {
27
28
  ) => void;
28
29
  showRetry: boolean;
29
30
  submitting: boolean;
31
+ theme: Theme;
30
32
  }
31
33
 
32
34
  const CONTAINER_WIDTH = 300;
@@ -50,6 +52,7 @@ export const PuzzleCanvas = ({
50
52
  onComplete,
51
53
  showRetry,
52
54
  submitting,
55
+ theme,
53
56
  }: PuzzleCanvasProps) => {
54
57
  const [posX, setPosX] = useState<number>(originX);
55
58
  const [posY, setPosY] = useState<number>(originY);
@@ -213,10 +216,17 @@ export const PuzzleCanvas = ({
213
216
  : "Drag the piece to the target";
214
217
 
215
218
  const headerBorderColor = showRetry
216
- ? "rgba(220, 53, 69, 0.4)"
219
+ ? theme.palette.error.main
217
220
  : "transparent";
218
221
 
219
- const headerTextColor = showRetry ? "#dc3545" : "#333";
222
+ const headerTextColor = showRetry
223
+ ? theme.palette.error.main
224
+ : theme.palette.onSurface;
225
+
226
+ // Material 3 purple tonal puzzle surface + affordances (mode-specific values
227
+ // come from the theme's puzzle tokens).
228
+ const puzzleAreaBg = `linear-gradient(135deg, ${theme.palette.surface} 0%, ${theme.palette.primaryContainer.main} 50%, ${theme.palette.surface} 100%)`;
229
+ const puzzle = theme.palette.puzzle;
220
230
 
221
231
  return (
222
232
  <div
@@ -250,20 +260,17 @@ export const PuzzleCanvas = ({
250
260
  {/* Instruction text */}
251
261
  <div
252
262
  style={{
253
- backgroundColor: "#fff",
254
- borderRadius: "8px 8px 0 0",
263
+ backgroundColor: theme.palette.surface,
264
+ borderRadius: "20px 20px 0 0",
255
265
  padding: "12px 20px",
256
266
  width: `${CONTAINER_WIDTH}px`,
257
267
  boxSizing: "border-box",
258
268
  textAlign: "center",
259
- fontFamily:
260
- '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
269
+ fontFamily: theme.font.fontFamily,
261
270
  fontSize: "14px",
262
271
  fontWeight: 500,
263
272
  color: headerTextColor,
264
273
  borderBottom: `2px solid ${headerBorderColor}`,
265
- boxShadow:
266
- "0px 11px 15px -7px rgba(0,0,0,0.2), 0px 24px 38px 3px rgba(0,0,0,0.14), 0px 9px 46px 8px rgba(0,0,0,0.12)",
267
274
  transition: "color 0.3s ease, border-color 0.3s ease",
268
275
  }}
269
276
  >
@@ -277,13 +284,10 @@ export const PuzzleCanvas = ({
277
284
  position: "relative",
278
285
  width: `${CONTAINER_WIDTH}px`,
279
286
  height: `${CONTAINER_HEIGHT}px`,
280
- background:
281
- "linear-gradient(135deg, #e8eaf6 0%, #c5cae9 50%, #e8eaf6 100%)",
282
- borderRadius: "0 0 8px 8px",
287
+ background: puzzleAreaBg,
288
+ borderRadius: "0 0 20px 20px",
283
289
  overflow: "hidden",
284
290
  userSelect: "none",
285
- boxShadow:
286
- "0px 11px 15px -7px rgba(0,0,0,0.2), 0px 24px 38px 3px rgba(0,0,0,0.14), 0px 9px 46px 8px rgba(0,0,0,0.12)",
287
291
  opacity: submitting ? 0.6 : 1,
288
292
  pointerEvents: submitting ? "none" : "auto",
289
293
  transition: "opacity 0.2s ease",
@@ -298,8 +302,8 @@ export const PuzzleCanvas = ({
298
302
  width: `${TARGET_SIZE}px`,
299
303
  height: `${TARGET_SIZE}px`,
300
304
  borderRadius: "50%",
301
- border: "2px dashed rgba(74, 144, 217, 0.6)",
302
- backgroundColor: "rgba(74, 144, 217, 0.08)",
305
+ border: `2px dashed ${puzzle.targetBorder}`,
306
+ backgroundColor: puzzle.targetFill,
303
307
  boxSizing: "border-box",
304
308
  }}
305
309
  />
@@ -326,19 +330,21 @@ export const PuzzleCanvas = ({
326
330
  width: `${PIECE_SIZE}px`,
327
331
  height: `${PIECE_SIZE}px`,
328
332
  borderRadius: "50%",
329
- background:
330
- "radial-gradient(circle at 40% 40%, #6ab0ff, #4a90d9)",
333
+ background: puzzle.pieceGradient,
331
334
  cursor: submitting
332
335
  ? "default"
333
336
  : isDragging.current
334
337
  ? "grabbing"
335
338
  : "grab",
336
- boxShadow: isDragging.current
337
- ? "0 4px 12px rgba(74, 144, 217, 0.5)"
338
- : "0 2px 6px rgba(74, 144, 217, 0.3)",
339
+ // Shadowless drag feedback: an outline ring in place of a
340
+ // lifted drop shadow.
341
+ outline: isDragging.current
342
+ ? `3px solid ${puzzle.targetBorder}`
343
+ : "none",
344
+ outlineOffset: "2px",
339
345
  transition: isDragging.current
340
346
  ? "none"
341
- : "box-shadow 0.2s ease, left 0.3s ease, top 0.3s ease",
347
+ : "outline 0.2s ease, left 0.3s ease, top 0.3s ease",
342
348
  }}
343
349
  />
344
350
  </div>
@@ -23,6 +23,7 @@ import type {
23
23
  ProcaptchaStateUpdateFn,
24
24
  PuzzleEvent,
25
25
  } from "@prosopo/types";
26
+ import { lightTheme } from "@prosopo/widget-skeleton";
26
27
  import type { ReactElement } from "react";
27
28
  import { assertType, describe, expectTypeOf, test } from "vitest";
28
29
  import { PuzzleCanvas } from "../components/PuzzleCanvas.js";
@@ -156,6 +157,7 @@ describe("PuzzleCanvas' types", () => {
156
157
  targetY: 1,
157
158
  onComplete,
158
159
  showRetry: false,
160
+ theme: lightTheme,
159
161
  });
160
162
  });
161
163
 
@@ -169,6 +171,7 @@ describe("PuzzleCanvas' types", () => {
169
171
  onComplete,
170
172
  showRetry: false,
171
173
  submitting: false,
174
+ theme: lightTheme,
172
175
  }),
173
176
  ).toExtend<ReactElement>();
174
177
  });
@@ -13,6 +13,7 @@
13
13
  // limitations under the License.
14
14
 
15
15
  import type { PuzzleEvent } from "@prosopo/types";
16
+ import { type Theme, lightTheme } from "@prosopo/widget-skeleton";
16
17
  import { type ReactElement, act, createElement } from "react";
17
18
  import { type Root, createRoot } from "react-dom/client";
18
19
  import {
@@ -47,6 +48,7 @@ interface CanvasProps {
47
48
  >;
48
49
  showRetry: boolean;
49
50
  submitting: boolean;
51
+ theme: Theme;
50
52
  }
51
53
 
52
54
  let container: HTMLDivElement;
@@ -63,6 +65,7 @@ const props = (overrides: Partial<CanvasProps> = {}): CanvasProps => ({
63
65
  onComplete,
64
66
  showRetry: false,
65
67
  submitting: false,
68
+ theme: lightTheme,
66
69
  ...overrides,
67
70
  });
68
71