├── .gitattributes ├── .github ├── FUNDING.yml └── workflows │ ├── ci.yml │ ├── close-stale-issues.yml │ └── publish.yml ├── .gitignore ├── .husky └── pre-commit ├── .vscode ├── extensions.json └── settings.json ├── .yarn └── plugins │ └── @yarnpkg │ └── plugin-nolyfill.cjs ├── .yarnrc.yml ├── LICENSE ├── README.md ├── biome.json ├── package.json ├── packages └── react-recaptcha-v3 │ ├── LICENSE │ ├── README.md │ ├── custom.d.ts │ ├── package.json │ ├── src │ ├── ReCaptcha.tsx │ ├── ReCaptchaContext.ts │ ├── ReCaptchaProvider.tsx │ ├── index.ts │ ├── manager.ts │ ├── types.ts │ ├── useReCaptcha.ts │ ├── utils.spec.ts │ └── utils.ts │ ├── tsconfig.build.json │ ├── tsconfig.json │ ├── vitest.config.ts │ └── vitest.setup.ts ├── sample ├── .gitignore ├── Sample.css ├── Sample.tsx ├── index.html ├── index.tsx ├── package.json ├── tsconfig.json ├── vite.config.ts └── yarn.lock ├── test ├── .gitignore ├── RecaptchaOptions.tsx ├── Test.css ├── Test.tsx ├── VisibilityOptions.tsx ├── index.html ├── index.tsx ├── package.json ├── tsconfig.json └── vite.config.ts └── yarn.lock /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto eol=lf 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: wojtekmaj 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: ['*'] 6 | pull_request: 7 | branches: [main] 8 | 9 | env: 10 | HUSKY: 0 11 | 12 | jobs: 13 | lint: 14 | name: Static code analysis 15 | runs-on: ubuntu-24.04-arm 16 | 17 | steps: 18 | - name: Checkout 19 | uses: actions/checkout@v4 20 | 21 | - name: Setup Biome 22 | uses: biomejs/setup-biome@v2 23 | 24 | - name: Run tests 25 | run: biome lint 26 | 27 | typescript: 28 | name: Type checking 29 | runs-on: ubuntu-24.04-arm 30 | 31 | steps: 32 | - name: Checkout 33 | uses: actions/checkout@v4 34 | 35 | - name: Cache Yarn cache 36 | uses: actions/cache@v4 37 | env: 38 | cache-name: yarn-cache 39 | with: 40 | path: ~/.yarn/berry/cache 41 | key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} 42 | restore-keys: | 43 | ${{ runner.os }}-${{ env.cache-name }} 44 | 45 | - name: Use Node.js 46 | uses: actions/setup-node@v4 47 | with: 48 | node-version: '22' 49 | 50 | - name: Enable Corepack 51 | run: corepack enable 52 | 53 | - name: Install dependencies 54 | run: yarn --immutable 55 | 56 | - name: Build package 57 | run: yarn build 58 | 59 | - name: Run type checking 60 | run: yarn tsc 61 | 62 | format: 63 | name: Formatting 64 | runs-on: ubuntu-24.04-arm 65 | 66 | steps: 67 | - name: Checkout 68 | uses: actions/checkout@v4 69 | 70 | - name: Setup Biome 71 | uses: biomejs/setup-biome@v2 72 | 73 | - name: Run formatting 74 | run: biome format 75 | 76 | unit: 77 | name: Unit tests 78 | runs-on: ubuntu-24.04-arm 79 | 80 | steps: 81 | - name: Checkout 82 | uses: actions/checkout@v4 83 | 84 | - name: Cache Yarn cache 85 | uses: actions/cache@v4 86 | env: 87 | cache-name: yarn-cache 88 | with: 89 | path: ~/.yarn/berry/cache 90 | key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} 91 | restore-keys: | 92 | ${{ runner.os }}-${{ env.cache-name }} 93 | 94 | - name: Use Node.js 95 | uses: actions/setup-node@v4 96 | with: 97 | node-version: '22' 98 | 99 | - name: Enable Corepack 100 | run: corepack enable 101 | 102 | - name: Install dependencies 103 | run: yarn --immutable 104 | 105 | - name: Run tests 106 | run: yarn unit 107 | -------------------------------------------------------------------------------- /.github/workflows/close-stale-issues.yml: -------------------------------------------------------------------------------- 1 | name: Close stale issues 2 | 3 | on: 4 | schedule: 5 | - cron: '0 0 * * 1' # Every Monday 6 | workflow_dispatch: 7 | 8 | jobs: 9 | close-issues: 10 | name: Close stale issues 11 | runs-on: ubuntu-24.04-arm 12 | 13 | steps: 14 | - name: Close stale issues 15 | uses: actions/stale@v8 16 | with: 17 | days-before-issue-stale: 90 18 | days-before-issue-close: 14 19 | stale-issue-label: 'stale' 20 | stale-issue-message: 'This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this issue will be closed in 14 days.' 21 | close-issue-message: 'This issue was closed because it has been stalled for 14 days with no activity.' 22 | exempt-issue-labels: 'fresh' 23 | remove-issue-stale-when-updated: true 24 | days-before-pr-stale: -1 25 | days-before-pr-close: -1 26 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | env: 8 | HUSKY: 0 9 | 10 | permissions: 11 | id-token: write 12 | 13 | jobs: 14 | publish: 15 | name: Publish 16 | runs-on: ubuntu-24.04-arm 17 | 18 | steps: 19 | - name: Checkout 20 | uses: actions/checkout@v4 21 | 22 | - name: Cache Yarn cache 23 | uses: actions/cache@v4 24 | env: 25 | cache-name: yarn-cache 26 | with: 27 | path: ~/.yarn/berry/cache 28 | key: ${{ runner.os }}-${{ env.cache-name }}-${{ hashFiles('**/yarn.lock') }} 29 | restore-keys: | 30 | ${{ runner.os }}-${{ env.cache-name }} 31 | 32 | - name: Use Node.js 33 | uses: actions/setup-node@v4 34 | with: 35 | node-version: '22' 36 | registry-url: 'https://registry.npmjs.org' 37 | 38 | - name: Enable Corepack 39 | run: corepack enable 40 | 41 | - name: Install dependencies 42 | run: yarn --immutable 43 | 44 | - name: Publish with latest tag 45 | if: github.event.release.prelease == false 46 | run: yarn npm publish --tag latest --provenance 47 | working-directory: packages/react-recaptcha-v3 48 | env: 49 | YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 50 | 51 | - name: Publish with next tag 52 | if: github.event.release.prelease == true 53 | run: yarn npm publish --tag next --provenance 54 | working-directory: packages/react-recaptcha-v3 55 | env: 56 | YARN_NPM_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 57 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # OS 2 | .DS_Store 3 | 4 | # Cache 5 | .cache 6 | .playwright 7 | .tmp 8 | *.tsbuildinfo 9 | .eslintcache 10 | 11 | # Yarn 12 | .pnp.* 13 | **/.yarn/* 14 | !**/.yarn/patches 15 | !**/.yarn/plugins 16 | !**/.yarn/releases 17 | !**/.yarn/sdks 18 | !**/.yarn/versions 19 | 20 | # Project-generated directories and files 21 | coverage 22 | dist 23 | node_modules 24 | playwright-report 25 | test-results 26 | package.tgz 27 | 28 | # Logs 29 | npm-debug.log 30 | yarn-error.log 31 | 32 | # .env files 33 | **/.env 34 | **/.env.* 35 | !**/.env.example 36 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | yarn format --staged --no-errors-on-unmatched --write 2 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": ["biomejs.biome"], 3 | "unwantedRecommendations": ["dbaeumer.jshint", "dbaeumer.vscode-eslint", "esbenp.prettier-vscode"] 4 | } 5 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "biomejs.biome", 3 | "editor.formatOnSave": true, 4 | "search.exclude": { 5 | "**/.yarn": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.yarn/plugins/@yarnpkg/plugin-nolyfill.cjs: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | //prettier-ignore 3 | module.exports = { 4 | name: "@yarnpkg/plugin-nolyfill", 5 | factory: function (require) { 6 | "use strict";var plugin=(()=>{var p=Object.defineProperty;var i=Object.getOwnPropertyDescriptor;var n=Object.getOwnPropertyNames;var y=Object.prototype.hasOwnProperty;var c=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(r,e)=>(typeof require<"u"?require:r)[e]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var l=(t,r)=>{for(var e in r)p(t,e,{get:r[e],enumerable:!0})},g=(t,r,e,s)=>{if(r&&typeof r=="object"||typeof r=="function")for(let a of n(r))!y.call(t,a)&&a!==e&&p(t,a,{get:()=>r[a],enumerable:!(s=i(r,a))||s.enumerable});return t};var f=t=>g(p({},"__esModule",{value:!0}),t);var b={};l(b,{default:()=>u});var o=c("@yarnpkg/core"),d=["array-buffer-byte-length","array-includes","array.from","array.of","array.prototype.at","array.prototype.every","array.prototype.find","array.prototype.findlast","array.prototype.findlastindex","array.prototype.flat","array.prototype.flatmap","array.prototype.flatmap","array.prototype.foreach","array.prototype.reduce","array.prototype.tosorted","arraybuffer.prototype.slice","assert","asynciterator.prototype","available-typed-arrays","deep-equal","define-properties","es-aggregate-error","es-iterator-helpers","es-set-tostringtag","es6-object-assign","function-bind","function.prototype.name","get-symbol-description","globalthis","gopd","harmony-reflect","has","has-property-descriptors","has-proto","has-symbols","has-tostringtag","hasown","internal-slot","is-arguments","is-array-buffer","is-date-object","is-generator-function","is-nan","is-regex","is-shared-array-buffer","is-string","is-symbol","is-typed-array","is-weakref","isarray","iterator.prototype","jsonify","object-is","object-keys","object.assign","object.entries","object.fromentries","object.getownpropertydescriptors","object.groupby","object.hasown","object.values","promise.allsettled","promise.any","reflect.getprototypeof","reflect.ownkeys","regexp.prototype.flags","safe-array-concat","safe-regex-test","set-function-length","side-channel","string.prototype.at","string.prototype.codepointat","string.prototype.includes","string.prototype.matchall","string.prototype.padend","string.prototype.padstart","string.prototype.repeat","string.prototype.replaceall","string.prototype.split","string.prototype.startswith","string.prototype.trim","string.prototype.trimend","string.prototype.trimleft","string.prototype.trimright","string.prototype.trimstart","typed-array-buffer","typed-array-byte-length","typed-array-byte-offset","typed-array-length","typedarray","unbox-primitive","which-boxed-primitive","which-typed-array"],h=new Map(d.map(t=>[o.structUtils.makeIdent(null,t).identHash,o.structUtils.makeIdent("nolyfill",t)])),m={hooks:{reduceDependency:async t=>{let r=h.get(t.identHash);if(r){let e=o.structUtils.makeDescriptor(r,"latest"),s=o.structUtils.makeRange({protocol:"npm:",source:null,selector:o.structUtils.stringifyDescriptor(e),params:null});return o.structUtils.makeDescriptor(t,s)}return t}}},u=m;return f(b);})(); 7 | return plugin; 8 | } 9 | }; 10 | -------------------------------------------------------------------------------- /.yarnrc.yml: -------------------------------------------------------------------------------- 1 | logFilters: 2 | - code: YN0076 3 | level: discard 4 | 5 | nodeLinker: node-modules 6 | 7 | plugins: 8 | - checksum: e3ca535b4c4288976eebb726082e2e6547c43e0ba1492b3ddbb0cdadc9d61d82ff14307358da06c46a446328345a464364d6c148b2d39fccc18cf6d232291858 9 | path: .yarn/plugins/@yarnpkg/plugin-nolyfill.cjs 10 | spec: "https://raw.githubusercontent.com/wojtekmaj/yarn-plugin-nolyfill/v0.1.1/bundles/@yarnpkg/plugin-nolyfill.js" 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Wojciech Maj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | /packages/react-recaptcha-v3/README.md -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.9.0/schema.json", 3 | "files": { 4 | "ignore": [".tsimp", ".yarn", "coverage", "dist", ".pnp.cjs", ".pnp.loader.mjs"] 5 | }, 6 | "formatter": { 7 | "lineWidth": 100, 8 | "indentStyle": "space" 9 | }, 10 | "linter": { 11 | "rules": { 12 | "complexity": { 13 | "noUselessSwitchCase": "off" 14 | }, 15 | "correctness": { 16 | "noUnusedImports": "warn", 17 | "noUnusedVariables": "warn" 18 | }, 19 | "suspicious": { 20 | "noConsoleLog": "warn" 21 | } 22 | } 23 | }, 24 | "css": { 25 | "formatter": { 26 | "quoteStyle": "single" 27 | } 28 | }, 29 | "javascript": { 30 | "formatter": { 31 | "quoteStyle": "single" 32 | } 33 | }, 34 | "overrides": [ 35 | { 36 | "include": ["**/package.json"], 37 | "formatter": { 38 | "lineWidth": 1 39 | } 40 | }, 41 | { 42 | "include": ["**/vite.config.ts"], 43 | "linter": { 44 | "rules": { 45 | "suspicious": { 46 | "noConsoleLog": "off" 47 | } 48 | } 49 | } 50 | } 51 | ] 52 | } 53 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wojtekmaj/react-recaptcha-v3-monorepo", 3 | "version": "1.0.0", 4 | "description": "@wojtekmaj/react-recaptcha-v3 monorepo", 5 | "type": "module", 6 | "workspaces": [ 7 | "packages/*", 8 | "test" 9 | ], 10 | "scripts": { 11 | "build": "yarn workspace @wojtekmaj/react-recaptcha-v3 build", 12 | "dev": "yarn workspace @wojtekmaj/react-recaptcha-v3 watch & yarn workspace test dev", 13 | "format": "yarn workspaces foreach --all run format", 14 | "lint": "yarn workspaces foreach --all run lint", 15 | "postinstall": "husky", 16 | "test": "yarn workspaces foreach --all run test", 17 | "tsc": "yarn workspaces foreach --all run tsc", 18 | "unit": "yarn workspaces foreach --all run unit" 19 | }, 20 | "devDependencies": { 21 | "husky": "^9.0.0" 22 | }, 23 | "packageManager": "yarn@4.9.1" 24 | } 25 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Wojciech Maj 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/README.md: -------------------------------------------------------------------------------- 1 | [![npm](https://img.shields.io/npm/v/@wojtekmaj/react-recaptcha-v3.svg)](https://www.npmjs.com/package/@wojtekmaj/react-recaptcha-v3) ![downloads](https://img.shields.io/npm/dt/@wojtekmaj/react-recaptcha-v3.svg) [![CI](https://github.com/wojtekmaj/react-recaptcha-v3/actions/workflows/ci.yml/badge.svg)](https://github.com/wojtekmaj/react-recaptcha-v3/actions) 2 | 3 | # @wojtekmaj/react-recaptcha-v3 4 | 5 | Integrate Google reCAPTCHA v3 with your React app. 6 | 7 | ## tl;dr 8 | 9 | - Install by executing `npm install @wojtekmaj/react-recaptcha-v3` or `yarn add @wojtekmaj/react-recaptcha-v3`. 10 | - Import by adding `import { ReCaptchaProvider, ReCaptcha } from '@wojtekmaj/react-recaptcha-v3'`. 11 | - Use by wrapping your app in ``, then using `` component. Use `onVerify` prop to get the token. 12 | 13 | ## Getting started 14 | 15 | ### Obtain reCAPTCHA key 16 | 17 | To use Google reCAPTCHA v3, you need to obtain a site key from the Google reCAPTCHA admin console. Visit [Google reCAPTCHA](https://www.google.com/recaptcha/admin) to get your site key. 18 | 19 | ### Installation 20 | 21 | Add @wojtekmaj/react-recaptcha-v3 to your project by executing `npm install @wojtekmaj/react-recaptcha-v3` or `yarn add @wojtekmaj/react-recaptcha-v3`. 22 | 23 | ### Usage 24 | 25 | Here's an example of basic usage: 26 | 27 | ```tsx 28 | import { useState } from 'react'; 29 | import { ReCaptchaProvider, ReCaptcha } from '@wojtekmaj/react-recaptcha-v3'; 30 | 31 | export default function Sample() { 32 | const [token, setToken] = useState(''); 33 | 34 | return ( 35 |
36 |
37 |

@wojtekmaj/react-recaptcha-v3 sample page

38 |
39 |
40 |
41 | 42 |
43 | 44 | 45 |
46 | 47 | 48 |
49 | 50 | 51 |
52 |
53 |
54 |
55 | ); 56 | } 57 | ``` 58 | 59 | ## User guide 60 | 61 | ### ReCaptchaProvider 62 | 63 | Alternative export name: `GoogleReCaptchaProvider`. 64 | 65 | Provides the reCAPTCHA context to your application. It should wrap your entire application or the part of your application where you want to use reCAPTCHA. 66 | 67 | You may have multiple `ReCaptchaProvider` components in your application, however, they must use the same settings. 68 | 69 | #### Props 70 | 71 | | Prop name | Description | Default value | Example | 72 | | --------------- | -------------------------------------------------------------------------- | ------------- | ----------------------------------------------------------- | 73 | | container | Configuration for the reCAPTCHA container. | n/a | `{ element: 'recaptcha', parameters: { badge: 'inline' } }` | 74 | | children | The child components that will have access to the reCAPTCHA context. | n/a | `` | 75 | | language | The language code for the reCAPTCHA widget. | n/a | `"en"` | 76 | | reCaptchaKey | The reCAPTCHA site key. | n/a | `"YOUR_SITE_KEY"` | 77 | | scriptProps | Additional props for the reCAPTCHA script. | n/a | `{ async: true, defer: true }` | 78 | | useEnterprise | Whether to use the reCAPTCHA Enterprise. | `false` | `true` | 79 | | useRecaptchaNet | Whether to use recaptcha.net instead of google.com for loading the script. | `false` | `true` | 80 | 81 | ### ReCaptcha 82 | 83 | Alternative export name: `GoogleReCaptcha`. 84 | 85 | Initializes the reCAPTCHA verification process. 86 | 87 | #### Props 88 | 89 | | Prop name | Description | Default value | Example | 90 | | ---------------- | --------------------------------------------------------- | ------------- | ------------------------------- | 91 | | action | The action name for the reCAPTCHA verification. | n/a | `"homepage"` | 92 | | onVerify | Callback function to handle the token after verification. | n/a | `(token) => console.log(token)` | 93 | | refreshReCaptcha | A value to trigger reCAPTCHA verification again. | n/a | `7` | 94 | 95 | ### useReCaptcha 96 | 97 | Alternative export name: `useGoogleReCaptcha`. 98 | 99 | Used to get the Google reCAPTCHA v3 context. 100 | 101 | #### Returns 102 | 103 | - `container` - The container element for the reCAPTCHA widget if applicable. 104 | - `executeRecaptcha` - A function to execute the reCAPTCHA verification process. 105 | - `reCaptchaInstance` - The reCAPTCHA instance. 106 | 107 | ## `react-google-recaptcha-v3` vs `@wojtekmaj/react-recaptcha-v3` 108 | 109 | `@wojtekmaj/react-recaptcha-v3` is a complete rewrite of `react-google-recaptcha-v3`. It was created to enhance TypeScript support and fix some long-standing issues (handling of multiple instances, `nonce` support, hiding reCAPTCHA badge, etc.). 110 | 111 | `@wojtekmaj/react-recaptcha-v3` is meant to be a drop-in replacement for `react-google-recaptcha-v3`, so you can use it without any changes to your code, unless you rely on `withGoogleReCaptcha` HOC which has already been deprecated in the original package. 112 | 113 | ## License 114 | 115 | The MIT License. 116 | 117 | ## Author 118 | 119 | 120 | 121 | 124 | 127 | 128 |
122 | Wojciech Maj 123 | 125 | Wojciech Maj 126 |
129 | 130 | ## Thank you 131 | 132 | This project wouldn't be possible without the awesome work of [Duong Tran](https://github.com/t49tran) who created its original version. Thank you! 133 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare global { 2 | type Grecaptcha = { 3 | execute: ( 4 | clientIdOrReCaptchaKey: number | string, 5 | options: { action?: string }, 6 | ) => Promise; 7 | getResponse: (action: string) => string; 8 | ready: (cb: () => void) => void; 9 | render: (container: string | HTMLElement, options: Record) => number; 10 | reset: (widgetId: number) => void; 11 | }; 12 | 13 | interface Window { 14 | grecaptcha?: Partial & { 15 | enterprise?: Partial; 16 | getPageId?: () => string; 17 | }; 18 | ___grecaptcha_cfg?: { 19 | clients?: Record>; 20 | fns?: (() => void)[]; 21 | }; 22 | } 23 | } 24 | 25 | export {}; 26 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@wojtekmaj/react-recaptcha-v3", 3 | "version": "0.1.4", 4 | "description": "Integrate Google reCAPTCHA v3 with your React app", 5 | "type": "module", 6 | "sideEffects": false, 7 | "main": "./dist/index.js", 8 | "module": "./dist/index.js", 9 | "source": "./src/index.ts", 10 | "types": "./dist/index.d.ts", 11 | "exports": { 12 | ".": "./dist/index.js", 13 | "./*": "./dist/*" 14 | }, 15 | "scripts": { 16 | "build": "tsc --project tsconfig.build.json", 17 | "clean": "node -e \"fs.rmSync('./dist', { recursive: true, force: true })\"", 18 | "format": "biome format", 19 | "lint": "biome lint", 20 | "prepack": "yarn clean && yarn build", 21 | "test": "yarn lint && yarn tsc && yarn format && yarn unit", 22 | "tsc": "tsc", 23 | "unit": "vitest", 24 | "watch": "yarn build --watch" 25 | }, 26 | "keywords": [ 27 | "captcha", 28 | "google", 29 | "react", 30 | "recaptcha-v3", 31 | "recaptcha" 32 | ], 33 | "author": { 34 | "name": "Wojciech Maj", 35 | "email": "kontakt@wojtekmaj.pl" 36 | }, 37 | "license": "MIT", 38 | "dependencies": { 39 | "warning": "^4.0.0" 40 | }, 41 | "devDependencies": { 42 | "@biomejs/biome": "1.9.0", 43 | "@testing-library/dom": "^10.0.0", 44 | "@testing-library/jest-dom": "^6.0.0", 45 | "@testing-library/react": "^16.0.0", 46 | "@types/react": "^18.3.0", 47 | "@types/react-dom": "^18.3.0", 48 | "@types/warning": "^3.0.0", 49 | "happy-dom": "^15.10.2", 50 | "react": "^18.2.0", 51 | "react-dom": "^18.2.0", 52 | "typescript": "^5.5.2", 53 | "vitest": "^3.0.5" 54 | }, 55 | "peerDependencies": { 56 | "@types/react": "^18.0.0 || ^19.0.0", 57 | "react": "^18.0.0 || ^19.0.0", 58 | "react-dom": "^18.0.0 || ^19.0.0" 59 | }, 60 | "peerDependenciesMeta": { 61 | "@types/react": { 62 | "optional": true 63 | } 64 | }, 65 | "publishConfig": { 66 | "access": "public", 67 | "provenance": true 68 | }, 69 | "files": [ 70 | "dist", 71 | "src" 72 | ], 73 | "repository": { 74 | "type": "git", 75 | "url": "git+https://github.com/wojtekmaj/react-recaptcha-v3.git", 76 | "directory": "packages/react-recaptcha-v3" 77 | }, 78 | "funding": "https://github.com/wojtekmaj/react-recaptcha-v3?sponsor=1" 79 | } 80 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/ReCaptcha.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect } from 'react'; 2 | 3 | import useReCaptcha from './useReCaptcha.js'; 4 | 5 | type ReCaptchaProps = { 6 | /** 7 | * The action name for the reCAPTCHA verification. 8 | */ 9 | action?: string; 10 | /** 11 | * Callback function to handle the token after verification. 12 | */ 13 | onVerify: (token: string) => void; 14 | /** 15 | * A value to trigger reCAPTCHA verification again. 16 | */ 17 | refreshReCaptcha?: boolean | string | number | null; 18 | }; 19 | 20 | /** 21 | * Initializes the reCAPTCHA verification process. 22 | */ 23 | export default function ReCaptcha({ action, onVerify, refreshReCaptcha }: ReCaptchaProps) { 24 | const { container, executeRecaptcha } = useReCaptcha(); 25 | 26 | // biome-ignore lint/correctness/useExhaustiveDependencies(refreshReCaptcha): refreshReCaptcha provides a way to execute reCAPTCHA again 27 | useEffect(() => { 28 | if (!executeRecaptcha) { 29 | return; 30 | } 31 | 32 | (async () => { 33 | const token = await executeRecaptcha(action); 34 | 35 | if (token) { 36 | onVerify(token); 37 | } 38 | })(); 39 | }, [action, executeRecaptcha, refreshReCaptcha, onVerify]); 40 | 41 | if (typeof container === 'string') { 42 | return
; 43 | } 44 | 45 | return null; 46 | } 47 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/ReCaptchaContext.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from 'react'; 2 | 3 | import type { ReCaptchaInstance } from './types.js'; 4 | 5 | export type ReCaptchaContextType = { 6 | /** 7 | * The container element for the reCAPTCHA widget if applicable. 8 | */ 9 | container?: string | HTMLElement; 10 | /** 11 | * A function to execute the reCAPTCHA verification process. 12 | * 13 | * @param {string} [action] The action name for the reCAPTCHA verification. 14 | * @returns {Promise | null} The reCAPTCHA token or null if the reCAPTCHA verification 15 | * failed. 16 | */ 17 | executeRecaptcha?: (action?: string) => Promise | null; 18 | /** 19 | * The reCAPTCHA instance. 20 | */ 21 | reCaptchaInstance?: ReCaptchaInstance | null; 22 | }; 23 | 24 | const ReCaptchaContext = createContext({}); 25 | 26 | export default ReCaptchaContext; 27 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/ReCaptchaProvider.tsx: -------------------------------------------------------------------------------- 1 | import { useEffect, useId, useMemo, useRef, useState } from 'react'; 2 | import warning from 'warning'; 3 | 4 | import ReCaptchaContext from './ReCaptchaContext.js'; 5 | 6 | import { registerInstance, removeClient, unregisterInstance } from './manager.js'; 7 | 8 | import type { ReCaptchaInstance, ScriptProps } from './types.js'; 9 | 10 | let didWarnAboutHiddenBadge = false; 11 | 12 | type ReCaptchaProviderProps = { 13 | /** 14 | * Configuration for the reCAPTCHA container. 15 | */ 16 | container?: { 17 | /** 18 | * The ID of the container element. If provided, the reCAPTCHA will be rendered into this 19 | * element. If not, the reCAPTCHA badge will be rendered. 20 | */ 21 | element?: string | HTMLElement; 22 | parameters: { 23 | /** 24 | * The position of the badge. 25 | */ 26 | badge?: 'inline' | 'bottomleft' | 'bottomright'; 27 | /** 28 | * Hides the reCAPTCHA badge. 29 | * 30 | * @see https://cloud.google.com/recaptcha/docs/faq#id_like_to_hide_the_badge_what_is_allowed 31 | */ 32 | hidden?: boolean; 33 | /** 34 | * The name of your callback function, executed when the user submits a successful response. 35 | * The g-recaptcha-response token is passed to your callback. 36 | */ 37 | callback?: () => void; 38 | /** 39 | * The name of your callback function, executed when reCAPTCHA encounters an error (usually 40 | * network connectivity) and cannot continue until connectivity is restored. If you specify a 41 | * function here, you are responsible for informing the user that they should retry. 42 | */ 43 | errorCallback?: () => void; 44 | /** 45 | * The name of your callback function, executed when the reCAPTCHA response expires and the 46 | * user needs to re-verify. 47 | */ 48 | expiredCallback?: () => void; 49 | /** 50 | * The tabindex of the widget and challenge. If other elements in your page use tabindex, it 51 | * should be set to make user navigation easier. 52 | */ 53 | tabindex?: number; 54 | /** 55 | * The color theme of the widget. 56 | */ 57 | theme?: 'dark' | 'light'; 58 | }; 59 | }; 60 | /** 61 | * The child components that will have access to the reCAPTCHA context. 62 | */ 63 | children?: React.ReactNode; 64 | /** 65 | * The language code for the reCAPTCHA widget. 66 | */ 67 | language?: string; 68 | /** 69 | * The reCAPTCHA site key. 70 | */ 71 | reCaptchaKey: string; 72 | /** 73 | * Additional props for the reCAPTCHA script. 74 | */ 75 | scriptProps?: Omit & { 76 | onLoadCallbackName?: string; 77 | }; 78 | /** 79 | * Whether to use the reCAPTCHA Enterprise. 80 | * 81 | * @default false 82 | */ 83 | useEnterprise?: boolean; 84 | /** 85 | * Whether to use recaptcha.net instead of google.com for loading the script. 86 | * 87 | * @default false 88 | */ 89 | useRecaptchaNet?: boolean; 90 | }; 91 | 92 | /** 93 | * Provides the reCAPTCHA context to your application. It should wrap your entire application or the 94 | * part of your application where you want to use reCAPTCHA. 95 | * 96 | * You may have multiple `ReCaptchaProvider` components in your application, however, they must use 97 | * the same settings. 98 | */ 99 | export default function ReCaptchaProvider({ 100 | container, 101 | children, 102 | language, 103 | reCaptchaKey, 104 | scriptProps, 105 | useEnterprise, 106 | useRecaptchaNet, 107 | }: ReCaptchaProviderProps) { 108 | const id = useId(); 109 | const [reCaptchaInstance, setReCaptchaInstance] = useState(null); 110 | const [clientId, setClientId] = useState(null); 111 | const clientIdMounted = useRef(false); 112 | 113 | useEffect(() => { 114 | function onLoadCallback() { 115 | const nextReCaptchaInstance = useEnterprise 116 | ? window.grecaptcha?.enterprise 117 | : window.grecaptcha; 118 | 119 | if (!nextReCaptchaInstance) { 120 | throw new Error('reCAPTCHA not found'); 121 | } 122 | 123 | if (!nextReCaptchaInstance.ready) { 124 | throw new Error('reCAPTCHA ready callback not found'); 125 | } 126 | 127 | nextReCaptchaInstance.ready(() => { 128 | setReCaptchaInstance(nextReCaptchaInstance); 129 | }); 130 | } 131 | 132 | registerInstance(id, { 133 | language, 134 | onLoadCallback, 135 | onLoadCallbackName: scriptProps?.onLoadCallbackName, 136 | render: container?.element ? 'explicit' : reCaptchaKey, 137 | scriptProps: { 138 | appendTo: scriptProps?.appendTo, 139 | async: scriptProps?.async, 140 | defer: scriptProps?.defer, 141 | id: scriptProps?.id, 142 | nonce: scriptProps?.nonce, 143 | }, 144 | useEnterprise, 145 | useRecaptchaNet, 146 | }); 147 | 148 | return () => { 149 | unregisterInstance(id); 150 | 151 | setReCaptchaInstance(null); 152 | }; 153 | }, [ 154 | container?.element, 155 | id, 156 | language, 157 | reCaptchaKey, 158 | scriptProps?.appendTo, 159 | scriptProps?.async, 160 | scriptProps?.defer, 161 | scriptProps?.id, 162 | scriptProps?.nonce, 163 | scriptProps?.onLoadCallbackName, 164 | useEnterprise, 165 | useRecaptchaNet, 166 | ]); 167 | 168 | useEffect(() => { 169 | if (!container?.element || !reCaptchaInstance?.render) { 170 | return; 171 | } 172 | 173 | const params = { 174 | 'error-callback': container.parameters.errorCallback, 175 | 'expired-callback': container.parameters.expiredCallback, 176 | badge: container.parameters?.badge || 'inline', 177 | callback: container.parameters.callback, 178 | sitekey: reCaptchaKey, 179 | size: 'invisible', 180 | tabindex: container.parameters.tabindex, 181 | theme: container.parameters.theme, 182 | }; 183 | 184 | const actualContainerElement = 185 | typeof container?.element === 'string' 186 | ? document.getElementById(container.element) 187 | : container?.element; 188 | 189 | if (!actualContainerElement) { 190 | throw new Error('reCAPTCHA container element not found'); 191 | } 192 | 193 | const nextClientId = reCaptchaInstance.render(actualContainerElement, params); 194 | 195 | if (container?.parameters?.hidden) { 196 | if (!didWarnAboutHiddenBadge) { 197 | warning( 198 | false, 199 | 'reCAPTCHA badge hidden. See https://cloud.google.com/recaptcha/docs/faq#id_like_to_hide_the_badge_what_is_allowed for more information.', 200 | ); 201 | 202 | didWarnAboutHiddenBadge = true; 203 | } 204 | 205 | ( 206 | actualContainerElement.querySelector('.grecaptcha-badge') as HTMLDivElement | null 207 | )?.style.setProperty('display', 'none'); 208 | } 209 | 210 | setClientId(nextClientId); 211 | clientIdMounted.current = true; 212 | 213 | return () => { 214 | setClientId(null); 215 | clientIdMounted.current = false; 216 | 217 | removeClient(nextClientId); 218 | 219 | actualContainerElement.innerHTML = ''; 220 | }; 221 | }, [ 222 | container?.element, 223 | container?.parameters?.badge, 224 | container?.parameters?.hidden, 225 | container?.parameters?.callback, 226 | container?.parameters?.errorCallback, 227 | container?.parameters?.expiredCallback, 228 | container?.parameters?.tabindex, 229 | container?.parameters?.theme, 230 | reCaptchaInstance, 231 | reCaptchaKey, 232 | ]); 233 | 234 | const shouldUseClientId = Boolean(container?.element); 235 | const clientIdOrReCaptchaKey = shouldUseClientId ? clientId : reCaptchaKey; 236 | 237 | const executeRecaptcha = useMemo( 238 | () => 239 | clientIdOrReCaptchaKey !== null && reCaptchaInstance?.execute 240 | ? (action?: string) => { 241 | if (clientIdOrReCaptchaKey === null || !reCaptchaInstance?.execute) { 242 | throw new Error('reCAPTCHA has not been loaded'); 243 | } 244 | 245 | if (shouldUseClientId && !clientIdMounted.current) { 246 | console.warn('Client ID not mounted'); 247 | return null; 248 | } 249 | 250 | return reCaptchaInstance.execute(clientIdOrReCaptchaKey, { action }); 251 | } 252 | : undefined, 253 | [clientIdOrReCaptchaKey, reCaptchaInstance, shouldUseClientId], 254 | ); 255 | 256 | return ( 257 | 264 | {children} 265 | 266 | ); 267 | } 268 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/index.ts: -------------------------------------------------------------------------------- 1 | import ReCaptcha from './ReCaptcha.js'; 2 | import ReCaptchaProvider from './ReCaptchaProvider.js'; 3 | import useReCaptcha from './useReCaptcha.js'; 4 | 5 | export { 6 | ReCaptcha, 7 | ReCaptcha as GoogleReCaptcha, 8 | ReCaptchaProvider, 9 | ReCaptchaProvider as GoogleReCaptchaProvider, 10 | useReCaptcha, 11 | useReCaptcha as useGoogleReCaptcha, 12 | }; 13 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/manager.ts: -------------------------------------------------------------------------------- 1 | import { loadScript } from './utils.js'; 2 | 3 | import type { ScriptProps } from './types.js'; 4 | 5 | /** 6 | * Holds the loaded script type. This is used to prevent multiple versions of the script from 7 | * being loaded. 8 | */ 9 | let loadedUrl: string | null = null; 10 | 11 | let isLoaded = false; 12 | 13 | const instances = new Set(); 14 | const onLoadCallbacks = new Set<() => void>(); 15 | 16 | const isBrowser = typeof window !== 'undefined'; 17 | const cfgKey = '___grecaptcha_cfg'; 18 | 19 | // Random name to prevent conflicts with other scripts 20 | const onLoadCallbackName = `onLoadCallback_${Math.random().toString(36).slice(2)}`; 21 | 22 | function initialize() { 23 | if (!isBrowser) { 24 | return; 25 | } 26 | 27 | /** 28 | * Makes it possible for multiple reCAPTCHA instances to be loaded by wrapping the onReady 29 | * callback in a function that pushes the callbacks to a global array (fns). This array is then 30 | * executed when reCAPTCHA loads. 31 | * 32 | * A modified version of the script provided by Google: 33 | * https://developers.google.com/recaptcha/docs/loading#loading_recaptcha_asynchronously 34 | */ 35 | function ready(cb: () => void) { 36 | if (isLoaded) { 37 | cb(); 38 | } else { 39 | if (!window[cfgKey]) { 40 | window[cfgKey] = {}; 41 | } 42 | const cfg = window[cfgKey]; 43 | if (!cfg.fns) { 44 | cfg.fns = []; 45 | } 46 | const fns = cfg.fns; 47 | fns.push(cb); 48 | } 49 | } 50 | 51 | if (!window.grecaptcha) { 52 | window.grecaptcha = {}; 53 | } 54 | 55 | if (!window.grecaptcha.enterprise) { 56 | window.grecaptcha.enterprise = {}; 57 | } 58 | 59 | window.grecaptcha.ready = ready; 60 | window.grecaptcha.enterprise.ready = ready; 61 | 62 | function onLoadCallback() { 63 | isLoaded = true; 64 | 65 | for (const callback of onLoadCallbacks) { 66 | callback(); 67 | } 68 | 69 | onLoadCallbacks.clear(); 70 | } 71 | 72 | // @ts-ignore 73 | window[onLoadCallbackName] = onLoadCallback; 74 | } 75 | 76 | function generateGoogleRecaptchaSrc({ 77 | language, 78 | onLoadCallbackName, 79 | render, 80 | useEnterprise = false, 81 | useRecaptchaNet = false, 82 | }: { 83 | language?: string; 84 | onLoadCallbackName?: string; 85 | render: 'explicit' | (string & {}); 86 | useEnterprise?: boolean; 87 | useRecaptchaNet?: boolean; 88 | }): string { 89 | const host = useRecaptchaNet ? 'recaptcha.net' : 'google.com'; 90 | const script = useEnterprise ? 'enterprise.js' : 'api.js'; 91 | 92 | const params = new URLSearchParams({ 93 | render, 94 | }); 95 | 96 | if (onLoadCallbackName) { 97 | params.set('onload', onLoadCallbackName); 98 | } 99 | if (language) { 100 | params.set('hl', language); 101 | } 102 | 103 | return `https://www.${host}/recaptcha/${script}?${params.toString()}`; 104 | } 105 | 106 | type LoadGoogleRecaptchaScriptOptions = { 107 | language?: string; 108 | render: 'explicit' | (string & {}); 109 | scriptProps?: Omit; 110 | useEnterprise?: boolean; 111 | useRecaptchaNet?: boolean; 112 | }; 113 | 114 | function loadGoogleRecaptchaScript({ 115 | language, 116 | render, 117 | scriptProps, 118 | useEnterprise, 119 | useRecaptchaNet, 120 | }: LoadGoogleRecaptchaScriptOptions) { 121 | const defaultScriptProps: Omit = { 122 | id: 'google-recaptcha-v3', 123 | }; 124 | 125 | const src = generateGoogleRecaptchaSrc({ 126 | language, 127 | onLoadCallbackName, 128 | render, 129 | useEnterprise, 130 | useRecaptchaNet, 131 | }); 132 | 133 | if (loadedUrl) { 134 | if (loadedUrl !== src) { 135 | throw new Error( 136 | 'reCAPTCHA has already been loaded with different parameters. Remove the existing script and load it again.', 137 | ); 138 | } 139 | 140 | return; 141 | } 142 | 143 | loadedUrl = src; 144 | 145 | loadScript({ ...defaultScriptProps, ...scriptProps, src }); 146 | } 147 | 148 | export function removeClient(clientId: number) { 149 | if (!window[cfgKey]) { 150 | return; 151 | } 152 | 153 | const cfg = window[cfgKey]; 154 | 155 | if (!cfg.clients) { 156 | return; 157 | } 158 | 159 | delete cfg.clients[clientId]; 160 | } 161 | 162 | export function registerInstance( 163 | instanceId: string, 164 | { 165 | onLoadCallback, 166 | onLoadCallbackName, 167 | ...loadGoogleRecaptchaScriptOptions 168 | }: LoadGoogleRecaptchaScriptOptions & { 169 | onLoadCallback?: () => void; 170 | onLoadCallbackName?: string; 171 | }, 172 | ) { 173 | if (instances.size === 0) { 174 | initialize(); 175 | } 176 | 177 | loadGoogleRecaptchaScript(loadGoogleRecaptchaScriptOptions); 178 | 179 | instances.add(instanceId); 180 | 181 | if (onLoadCallback) { 182 | if (isLoaded) { 183 | onLoadCallback(); 184 | } else { 185 | onLoadCallbacks.add(onLoadCallback); 186 | } 187 | } 188 | 189 | if (onLoadCallbackName) { 190 | function callOnLoadCallbackIfExists() { 191 | if (!onLoadCallbackName) { 192 | return; 193 | } 194 | 195 | // @ts-ignore 196 | const maybeOnLoadCallback = window[onLoadCallbackName]; 197 | 198 | if (typeof maybeOnLoadCallback === 'function') { 199 | maybeOnLoadCallback(); 200 | } 201 | } 202 | 203 | if (isLoaded) { 204 | callOnLoadCallbackIfExists(); 205 | } else { 206 | onLoadCallbacks.add(callOnLoadCallbackIfExists); 207 | } 208 | } 209 | } 210 | 211 | export function unregisterInstance(instanceId: string) { 212 | instances.delete(instanceId); 213 | 214 | if (instances.size === 0) { 215 | window.grecaptcha = undefined; 216 | 217 | window[cfgKey] = undefined; 218 | 219 | document.querySelector('.grecaptcha-badge')?.remove(); 220 | 221 | document.querySelector(`script[src="${loadedUrl}"]`)?.remove(); 222 | 223 | document.querySelector(`script[src^="https://www.gstatic.com/recaptcha/releases"]`)?.remove(); 224 | 225 | loadedUrl = null; 226 | 227 | isLoaded = false; 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/types.ts: -------------------------------------------------------------------------------- 1 | export type ReCaptchaInstance = { 2 | execute?: ( 3 | clientIdOrReCaptchaKey: number | string, 4 | options: { action?: string }, 5 | ) => Promise; 6 | render?: (container: string | HTMLElement, options: Record) => number; 7 | }; 8 | 9 | export type ScriptProps = { 10 | appendTo?: 'head' | 'body'; 11 | async?: boolean; 12 | defer?: boolean; 13 | id?: string; 14 | nonce?: string; 15 | src: string; 16 | }; 17 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/useReCaptcha.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from 'react'; 2 | 3 | import ReCaptchaContext from './ReCaptchaContext.js'; 4 | 5 | import type { ReCaptchaContextType } from './ReCaptchaContext.js'; 6 | 7 | /** 8 | * Used to get the Google reCAPTCHA v3 context. 9 | * 10 | * @returns {ReCaptchaContextType} Google reCAPTCHA v3 context 11 | */ 12 | export default function useReCaptcha(): ReCaptchaContextType { 13 | return useContext(ReCaptchaContext); 14 | } 15 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/utils.spec.ts: -------------------------------------------------------------------------------- 1 | import { afterEach, describe, expect, it } from 'vitest'; 2 | import { loadScript } from './utils.js'; 3 | 4 | describe('loadScript', () => { 5 | afterEach(() => { 6 | document.head.innerHTML = ''; 7 | document.body.innerHTML = ''; 8 | }); 9 | 10 | it('should append script to head when appendTo is head', () => { 11 | loadScript({ 12 | async: true, 13 | appendTo: 'head', 14 | defer: true, 15 | id: 'test-script', 16 | nonce: 'test-nonce', 17 | src: 'https://example.com/script.js', 18 | }); 19 | 20 | const script = document.head.querySelector('script'); 21 | 22 | expect(script).not.toBeNull(); 23 | expect(script?.async).toBe(true); 24 | expect(script?.defer).toBe(true); 25 | expect(script?.id).toBe('test-script'); 26 | expect(script).toHaveAttribute('nonce', 'test-nonce'); 27 | expect(script?.src).toBe('https://example.com/script.js'); 28 | }); 29 | 30 | it('should append script to body when appendTo is body', () => { 31 | loadScript({ 32 | async: true, 33 | appendTo: 'body', 34 | defer: true, 35 | id: 'test-script', 36 | nonce: 'test-nonce', 37 | src: 'https://example.com/script.js', 38 | }); 39 | 40 | const script = document.body.querySelector('script'); 41 | 42 | expect(script).not.toBeNull(); 43 | expect(script?.async).toBe(true); 44 | expect(script?.defer).toBe(true); 45 | expect(script?.id).toBe('test-script'); 46 | expect(script).toHaveAttribute('nonce', 'test-nonce'); 47 | expect(script?.src).toBe('https://example.com/script.js'); 48 | }); 49 | 50 | it('should not set async and defer if they are undefined', () => { 51 | loadScript({ appendTo: 'head', id: 'test-script', src: 'https://example.com/script.js' }); 52 | 53 | const script = document.head.querySelector('script'); 54 | expect(script).not.toBeNull(); 55 | expect(script?.async).toBe(false); 56 | expect(script?.defer).toBe(false); 57 | }); 58 | }); 59 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/src/utils.ts: -------------------------------------------------------------------------------- 1 | import type { ScriptProps } from './types.js'; 2 | 3 | export function loadScript({ async, appendTo, defer, id, nonce, src }: ScriptProps) { 4 | const script = document.createElement('script'); 5 | if (async !== undefined) { 6 | script.async = async; 7 | } 8 | if (defer !== undefined) { 9 | script.defer = defer; 10 | } 11 | if (id) { 12 | script.id = id; 13 | } 14 | if (nonce) { 15 | script.setAttribute('nonce', nonce); 16 | } 17 | script.src = src; 18 | 19 | const appendTarget = appendTo === 'head' ? document.head : document.body; 20 | 21 | appendTarget.appendChild(script); 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/tsconfig.build.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.json", 3 | "compilerOptions": { 4 | "noEmit": false, 5 | "outDir": "dist", 6 | "rootDir": "src" 7 | }, 8 | "include": ["src", "custom.d.ts"], 9 | "exclude": ["src/**/*.spec.ts", "src/**/*.spec.tsx"] 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "esModuleInterop": true, 5 | "isolatedModules": true, 6 | "jsx": "react-jsx", 7 | "module": "nodenext", 8 | "moduleDetection": "force", 9 | "noEmit": true, 10 | "noUncheckedIndexedAccess": true, 11 | "outDir": "dist", 12 | "skipLibCheck": true, 13 | "strict": true, 14 | "target": "es2017", 15 | "verbatimModuleSyntax": true 16 | }, 17 | "exclude": ["dist"] 18 | } 19 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/vitest.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vitest/config'; 2 | 3 | export default defineConfig({ 4 | test: { 5 | environment: 'happy-dom', 6 | setupFiles: 'vitest.setup.ts', 7 | watch: false, 8 | }, 9 | }); 10 | -------------------------------------------------------------------------------- /packages/react-recaptcha-v3/vitest.setup.ts: -------------------------------------------------------------------------------- 1 | import { afterEach } from 'vitest'; 2 | import { cleanup } from '@testing-library/react'; 3 | import '@testing-library/jest-dom/vitest'; 4 | 5 | afterEach(() => { 6 | cleanup(); 7 | }); 8 | -------------------------------------------------------------------------------- /sample/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /sample/Sample.css: -------------------------------------------------------------------------------- 1 | html, 2 | body { 3 | height: 100%; 4 | } 5 | 6 | body { 7 | margin: 0; 8 | font-family: Segoe UI, Tahoma, sans-serif; 9 | } 10 | 11 | .Sample input, 12 | .Sample output, 13 | .Sample button { 14 | font: inherit; 15 | } 16 | 17 | .Sample header { 18 | background-color: #323639; 19 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.5); 20 | padding: 20px; 21 | color: white; 22 | } 23 | 24 | .Sample header h1 { 25 | font-size: inherit; 26 | margin: 0; 27 | } 28 | 29 | .Sample__container { 30 | display: flex; 31 | flex-direction: row; 32 | flex-wrap: wrap; 33 | align-items: flex-start; 34 | margin: 10px 0; 35 | padding: 10px; 36 | } 37 | 38 | .Sample__container > * > * { 39 | margin: 10px; 40 | } 41 | 42 | .Sample__container__content { 43 | display: flex; 44 | max-width: 100%; 45 | flex-basis: 420px; 46 | flex-direction: column; 47 | flex-grow: 100; 48 | align-items: stretch; 49 | padding-top: 1em; 50 | } 51 | -------------------------------------------------------------------------------- /sample/Sample.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from 'react'; 2 | import { ReCaptchaProvider, ReCaptcha } from '@wojtekmaj/react-recaptcha-v3'; 3 | 4 | import './Sample.css'; 5 | 6 | export default function Sample() { 7 | const [token, setToken] = useState(''); 8 | 9 | return ( 10 |
11 |
12 |

@wojtekmaj/react-recaptcha-v3 sample page

13 |
14 |
15 |
16 | 17 |
18 | 19 | 20 |
21 | 22 | 23 |
24 | 25 | 26 |
27 |
28 |
29 |
30 | ); 31 | } 32 | -------------------------------------------------------------------------------- /sample/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | @wojtekmaj/react-recaptcha-v3 sample page 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /sample/index.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | 3 | import Sample from './Sample.js'; 4 | 5 | const root = document.getElementById('root'); 6 | 7 | if (!root) { 8 | throw new Error('Could not find root element'); 9 | } 10 | 11 | createRoot(root).render(); 12 | -------------------------------------------------------------------------------- /sample/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-recaptcha-v3-sample-page", 3 | "version": "1.0.0", 4 | "description": "A sample page for React-reCAPTCHA-v3.", 5 | "private": true, 6 | "type": "module", 7 | "scripts": { 8 | "build": "vite build", 9 | "dev": "vite", 10 | "preview": "vite preview" 11 | }, 12 | "author": { 13 | "name": "Wojciech Maj", 14 | "email": "kontakt@wojtekmaj.pl" 15 | }, 16 | "license": "MIT", 17 | "dependencies": { 18 | "@wojtekmaj/react-recaptcha-v3": "portal:../packages/react-recaptcha-v3", 19 | "react": "^18.2.0", 20 | "react-dom": "^18.2.0" 21 | }, 22 | "devDependencies": { 23 | "@vitejs/plugin-react": "^4.3.4", 24 | "typescript": "^5.0.0", 25 | "vite": "^6.2.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /sample/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "isolatedModules": true, 4 | "jsx": "react-jsx", 5 | "module": "preserve", 6 | "moduleDetection": "force", 7 | "noEmit": true, 8 | "noUncheckedIndexedAccess": true, 9 | "skipLibCheck": true, 10 | "strict": true, 11 | "target": "esnext", 12 | "verbatimModuleSyntax": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /sample/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | export default defineConfig({ 5 | base: './', 6 | plugins: [react()], 7 | }); 8 | -------------------------------------------------------------------------------- /sample/yarn.lock: -------------------------------------------------------------------------------- 1 | # This file is generated by running "yarn install" inside your project. 2 | # Manual changes might be lost - proceed with caution! 3 | 4 | __metadata: 5 | version: 8 6 | cacheKey: 10c0 7 | 8 | "@ampproject/remapping@npm:^2.2.0": 9 | version: 2.3.0 10 | resolution: "@ampproject/remapping@npm:2.3.0" 11 | dependencies: 12 | "@jridgewell/gen-mapping": "npm:^0.3.5" 13 | "@jridgewell/trace-mapping": "npm:^0.3.24" 14 | checksum: 10c0/81d63cca5443e0f0c72ae18b544cc28c7c0ec2cea46e7cb888bb0e0f411a1191d0d6b7af798d54e30777d8d1488b2ec0732aac2be342d3d7d3ffd271c6f489ed 15 | languageName: node 16 | linkType: hard 17 | 18 | "@babel/code-frame@npm:^7.25.9, @babel/code-frame@npm:^7.26.0, @babel/code-frame@npm:^7.26.2": 19 | version: 7.26.2 20 | resolution: "@babel/code-frame@npm:7.26.2" 21 | dependencies: 22 | "@babel/helper-validator-identifier": "npm:^7.25.9" 23 | js-tokens: "npm:^4.0.0" 24 | picocolors: "npm:^1.0.0" 25 | checksum: 10c0/7d79621a6849183c415486af99b1a20b84737e8c11cd55b6544f688c51ce1fd710e6d869c3dd21232023da272a79b91efb3e83b5bc2dc65c1187c5fcd1b72ea8 26 | languageName: node 27 | linkType: hard 28 | 29 | "@babel/compat-data@npm:^7.25.9": 30 | version: 7.26.3 31 | resolution: "@babel/compat-data@npm:7.26.3" 32 | checksum: 10c0/d63e71845c34dfad8d7ff8c15b562e620dbf60e68e3abfa35681d24d612594e8e5ec9790d831a287ecd79ce00f48e7ffddc85c5ce94af7242d45917b9c1a5f90 33 | languageName: node 34 | linkType: hard 35 | 36 | "@babel/core@npm:^7.26.0": 37 | version: 7.26.0 38 | resolution: "@babel/core@npm:7.26.0" 39 | dependencies: 40 | "@ampproject/remapping": "npm:^2.2.0" 41 | "@babel/code-frame": "npm:^7.26.0" 42 | "@babel/generator": "npm:^7.26.0" 43 | "@babel/helper-compilation-targets": "npm:^7.25.9" 44 | "@babel/helper-module-transforms": "npm:^7.26.0" 45 | "@babel/helpers": "npm:^7.26.0" 46 | "@babel/parser": "npm:^7.26.0" 47 | "@babel/template": "npm:^7.25.9" 48 | "@babel/traverse": "npm:^7.25.9" 49 | "@babel/types": "npm:^7.26.0" 50 | convert-source-map: "npm:^2.0.0" 51 | debug: "npm:^4.1.0" 52 | gensync: "npm:^1.0.0-beta.2" 53 | json5: "npm:^2.2.3" 54 | semver: "npm:^6.3.1" 55 | checksum: 10c0/91de73a7ff5c4049fbc747930aa039300e4d2670c2a91f5aa622f1b4868600fc89b01b6278385fbcd46f9574186fa3d9b376a9e7538e50f8d118ec13cfbcb63e 56 | languageName: node 57 | linkType: hard 58 | 59 | "@babel/generator@npm:^7.26.0, @babel/generator@npm:^7.26.3": 60 | version: 7.26.3 61 | resolution: "@babel/generator@npm:7.26.3" 62 | dependencies: 63 | "@babel/parser": "npm:^7.26.3" 64 | "@babel/types": "npm:^7.26.3" 65 | "@jridgewell/gen-mapping": "npm:^0.3.5" 66 | "@jridgewell/trace-mapping": "npm:^0.3.25" 67 | jsesc: "npm:^3.0.2" 68 | checksum: 10c0/54f260558e3e4ec8942da3cde607c35349bb983c3a7c5121243f96893fba3e8cd62e1f1773b2051f936f8c8a10987b758d5c7d76dbf2784e95bb63ab4843fa00 69 | languageName: node 70 | linkType: hard 71 | 72 | "@babel/helper-compilation-targets@npm:^7.25.9": 73 | version: 7.25.9 74 | resolution: "@babel/helper-compilation-targets@npm:7.25.9" 75 | dependencies: 76 | "@babel/compat-data": "npm:^7.25.9" 77 | "@babel/helper-validator-option": "npm:^7.25.9" 78 | browserslist: "npm:^4.24.0" 79 | lru-cache: "npm:^5.1.1" 80 | semver: "npm:^6.3.1" 81 | checksum: 10c0/a6b26a1e4222e69ef8e62ee19374308f060b007828bc11c65025ecc9e814aba21ff2175d6d3f8bf53c863edd728ee8f94ba7870f8f90a37d39552ad9933a8aaa 82 | languageName: node 83 | linkType: hard 84 | 85 | "@babel/helper-module-imports@npm:^7.25.9": 86 | version: 7.25.9 87 | resolution: "@babel/helper-module-imports@npm:7.25.9" 88 | dependencies: 89 | "@babel/traverse": "npm:^7.25.9" 90 | "@babel/types": "npm:^7.25.9" 91 | checksum: 10c0/078d3c2b45d1f97ffe6bb47f61961be4785d2342a4156d8b42c92ee4e1b7b9e365655dd6cb25329e8fe1a675c91eeac7e3d04f0c518b67e417e29d6e27b6aa70 92 | languageName: node 93 | linkType: hard 94 | 95 | "@babel/helper-module-transforms@npm:^7.26.0": 96 | version: 7.26.0 97 | resolution: "@babel/helper-module-transforms@npm:7.26.0" 98 | dependencies: 99 | "@babel/helper-module-imports": "npm:^7.25.9" 100 | "@babel/helper-validator-identifier": "npm:^7.25.9" 101 | "@babel/traverse": "npm:^7.25.9" 102 | peerDependencies: 103 | "@babel/core": ^7.0.0 104 | checksum: 10c0/ee111b68a5933481d76633dad9cdab30c41df4479f0e5e1cc4756dc9447c1afd2c9473b5ba006362e35b17f4ebddd5fca090233bef8dfc84dca9d9127e56ec3a 105 | languageName: node 106 | linkType: hard 107 | 108 | "@babel/helper-plugin-utils@npm:^7.25.9": 109 | version: 7.25.9 110 | resolution: "@babel/helper-plugin-utils@npm:7.25.9" 111 | checksum: 10c0/483066a1ba36ff16c0116cd24f93de05de746a603a777cd695ac7a1b034928a65a4ecb35f255761ca56626435d7abdb73219eba196f9aa83b6c3c3169325599d 112 | languageName: node 113 | linkType: hard 114 | 115 | "@babel/helper-string-parser@npm:^7.25.9": 116 | version: 7.25.9 117 | resolution: "@babel/helper-string-parser@npm:7.25.9" 118 | checksum: 10c0/7244b45d8e65f6b4338a6a68a8556f2cb161b782343e97281a5f2b9b93e420cad0d9f5773a59d79f61d0c448913d06f6a2358a87f2e203cf112e3c5b53522ee6 119 | languageName: node 120 | linkType: hard 121 | 122 | "@babel/helper-validator-identifier@npm:^7.25.9": 123 | version: 7.25.9 124 | resolution: "@babel/helper-validator-identifier@npm:7.25.9" 125 | checksum: 10c0/4fc6f830177b7b7e887ad3277ddb3b91d81e6c4a24151540d9d1023e8dc6b1c0505f0f0628ae653601eb4388a8db45c1c14b2c07a9173837aef7e4116456259d 126 | languageName: node 127 | linkType: hard 128 | 129 | "@babel/helper-validator-option@npm:^7.25.9": 130 | version: 7.25.9 131 | resolution: "@babel/helper-validator-option@npm:7.25.9" 132 | checksum: 10c0/27fb195d14c7dcb07f14e58fe77c44eea19a6a40a74472ec05c441478fa0bb49fa1c32b2d64be7a38870ee48ef6601bdebe98d512f0253aea0b39756c4014f3e 133 | languageName: node 134 | linkType: hard 135 | 136 | "@babel/helpers@npm:^7.26.0": 137 | version: 7.26.0 138 | resolution: "@babel/helpers@npm:7.26.0" 139 | dependencies: 140 | "@babel/template": "npm:^7.25.9" 141 | "@babel/types": "npm:^7.26.0" 142 | checksum: 10c0/343333cced6946fe46617690a1d0789346960910225ce359021a88a60a65bc0d791f0c5d240c0ed46cf8cc63b5fd7df52734ff14e43b9c32feae2b61b1647097 143 | languageName: node 144 | linkType: hard 145 | 146 | "@babel/parser@npm:^7.1.0, @babel/parser@npm:^7.20.7, @babel/parser@npm:^7.25.9, @babel/parser@npm:^7.26.0, @babel/parser@npm:^7.26.3": 147 | version: 7.26.3 148 | resolution: "@babel/parser@npm:7.26.3" 149 | dependencies: 150 | "@babel/types": "npm:^7.26.3" 151 | bin: 152 | parser: ./bin/babel-parser.js 153 | checksum: 10c0/48f736374e61cfd10ddbf7b80678514ae1f16d0e88bc793d2b505d73d9b987ea786fc8c2f7ee8f8b8c467df062030eb07fd0eb2168f0f541ca1f542775852cad 154 | languageName: node 155 | linkType: hard 156 | 157 | "@babel/plugin-transform-react-jsx-self@npm:^7.25.9": 158 | version: 7.25.9 159 | resolution: "@babel/plugin-transform-react-jsx-self@npm:7.25.9" 160 | dependencies: 161 | "@babel/helper-plugin-utils": "npm:^7.25.9" 162 | peerDependencies: 163 | "@babel/core": ^7.0.0-0 164 | checksum: 10c0/ce0e289f6af93d7c4dc6b385512199c5bb138ae61507b4d5117ba88b6a6b5092f704f1bdf80080b7d69b1b8c36649f2a0b250e8198667d4d30c08bbb1546bd99 165 | languageName: node 166 | linkType: hard 167 | 168 | "@babel/plugin-transform-react-jsx-source@npm:^7.25.9": 169 | version: 7.25.9 170 | resolution: "@babel/plugin-transform-react-jsx-source@npm:7.25.9" 171 | dependencies: 172 | "@babel/helper-plugin-utils": "npm:^7.25.9" 173 | peerDependencies: 174 | "@babel/core": ^7.0.0-0 175 | checksum: 10c0/fc9ee08efc9be7cbd2cc6788bbf92579adf3cab37912481f1b915221be3d22b0613b5b36a721df5f4c0ab65efe8582fcf8673caab83e6e1ce4cc04ceebf57dfa 176 | languageName: node 177 | linkType: hard 178 | 179 | "@babel/template@npm:^7.25.9": 180 | version: 7.25.9 181 | resolution: "@babel/template@npm:7.25.9" 182 | dependencies: 183 | "@babel/code-frame": "npm:^7.25.9" 184 | "@babel/parser": "npm:^7.25.9" 185 | "@babel/types": "npm:^7.25.9" 186 | checksum: 10c0/ebe677273f96a36c92cc15b7aa7b11cc8bc8a3bb7a01d55b2125baca8f19cae94ff3ce15f1b1880fb8437f3a690d9f89d4e91f16fc1dc4d3eb66226d128983ab 187 | languageName: node 188 | linkType: hard 189 | 190 | "@babel/traverse@npm:^7.25.9": 191 | version: 7.26.4 192 | resolution: "@babel/traverse@npm:7.26.4" 193 | dependencies: 194 | "@babel/code-frame": "npm:^7.26.2" 195 | "@babel/generator": "npm:^7.26.3" 196 | "@babel/parser": "npm:^7.26.3" 197 | "@babel/template": "npm:^7.25.9" 198 | "@babel/types": "npm:^7.26.3" 199 | debug: "npm:^4.3.1" 200 | globals: "npm:^11.1.0" 201 | checksum: 10c0/cf25d0eda9505daa0f0832ad786b9e28c9d967e823aaf7fbe425250ab198c656085495aa6bed678b27929e095c84eea9fd778b851a31803da94c9bc4bf4eaef7 202 | languageName: node 203 | linkType: hard 204 | 205 | "@babel/types@npm:^7.0.0, @babel/types@npm:^7.20.7, @babel/types@npm:^7.25.9, @babel/types@npm:^7.26.0, @babel/types@npm:^7.26.3, @babel/types@npm:^7.3.0": 206 | version: 7.26.3 207 | resolution: "@babel/types@npm:7.26.3" 208 | dependencies: 209 | "@babel/helper-string-parser": "npm:^7.25.9" 210 | "@babel/helper-validator-identifier": "npm:^7.25.9" 211 | checksum: 10c0/966c5242c5e55c8704bf7a7418e7be2703a0afa4d19a8480999d5a4ef13d095dd60686615fe5983cb7593b4b06ba3a7de8d6ca501c1d78bdd233a10d90be787b 212 | languageName: node 213 | linkType: hard 214 | 215 | "@esbuild/aix-ppc64@npm:0.25.0": 216 | version: 0.25.0 217 | resolution: "@esbuild/aix-ppc64@npm:0.25.0" 218 | conditions: os=aix & cpu=ppc64 219 | languageName: node 220 | linkType: hard 221 | 222 | "@esbuild/android-arm64@npm:0.25.0": 223 | version: 0.25.0 224 | resolution: "@esbuild/android-arm64@npm:0.25.0" 225 | conditions: os=android & cpu=arm64 226 | languageName: node 227 | linkType: hard 228 | 229 | "@esbuild/android-arm@npm:0.25.0": 230 | version: 0.25.0 231 | resolution: "@esbuild/android-arm@npm:0.25.0" 232 | conditions: os=android & cpu=arm 233 | languageName: node 234 | linkType: hard 235 | 236 | "@esbuild/android-x64@npm:0.25.0": 237 | version: 0.25.0 238 | resolution: "@esbuild/android-x64@npm:0.25.0" 239 | conditions: os=android & cpu=x64 240 | languageName: node 241 | linkType: hard 242 | 243 | "@esbuild/darwin-arm64@npm:0.25.0": 244 | version: 0.25.0 245 | resolution: "@esbuild/darwin-arm64@npm:0.25.0" 246 | conditions: os=darwin & cpu=arm64 247 | languageName: node 248 | linkType: hard 249 | 250 | "@esbuild/darwin-x64@npm:0.25.0": 251 | version: 0.25.0 252 | resolution: "@esbuild/darwin-x64@npm:0.25.0" 253 | conditions: os=darwin & cpu=x64 254 | languageName: node 255 | linkType: hard 256 | 257 | "@esbuild/freebsd-arm64@npm:0.25.0": 258 | version: 0.25.0 259 | resolution: "@esbuild/freebsd-arm64@npm:0.25.0" 260 | conditions: os=freebsd & cpu=arm64 261 | languageName: node 262 | linkType: hard 263 | 264 | "@esbuild/freebsd-x64@npm:0.25.0": 265 | version: 0.25.0 266 | resolution: "@esbuild/freebsd-x64@npm:0.25.0" 267 | conditions: os=freebsd & cpu=x64 268 | languageName: node 269 | linkType: hard 270 | 271 | "@esbuild/linux-arm64@npm:0.25.0": 272 | version: 0.25.0 273 | resolution: "@esbuild/linux-arm64@npm:0.25.0" 274 | conditions: os=linux & cpu=arm64 275 | languageName: node 276 | linkType: hard 277 | 278 | "@esbuild/linux-arm@npm:0.25.0": 279 | version: 0.25.0 280 | resolution: "@esbuild/linux-arm@npm:0.25.0" 281 | conditions: os=linux & cpu=arm 282 | languageName: node 283 | linkType: hard 284 | 285 | "@esbuild/linux-ia32@npm:0.25.0": 286 | version: 0.25.0 287 | resolution: "@esbuild/linux-ia32@npm:0.25.0" 288 | conditions: os=linux & cpu=ia32 289 | languageName: node 290 | linkType: hard 291 | 292 | "@esbuild/linux-loong64@npm:0.25.0": 293 | version: 0.25.0 294 | resolution: "@esbuild/linux-loong64@npm:0.25.0" 295 | conditions: os=linux & cpu=loong64 296 | languageName: node 297 | linkType: hard 298 | 299 | "@esbuild/linux-mips64el@npm:0.25.0": 300 | version: 0.25.0 301 | resolution: "@esbuild/linux-mips64el@npm:0.25.0" 302 | conditions: os=linux & cpu=mips64el 303 | languageName: node 304 | linkType: hard 305 | 306 | "@esbuild/linux-ppc64@npm:0.25.0": 307 | version: 0.25.0 308 | resolution: "@esbuild/linux-ppc64@npm:0.25.0" 309 | conditions: os=linux & cpu=ppc64 310 | languageName: node 311 | linkType: hard 312 | 313 | "@esbuild/linux-riscv64@npm:0.25.0": 314 | version: 0.25.0 315 | resolution: "@esbuild/linux-riscv64@npm:0.25.0" 316 | conditions: os=linux & cpu=riscv64 317 | languageName: node 318 | linkType: hard 319 | 320 | "@esbuild/linux-s390x@npm:0.25.0": 321 | version: 0.25.0 322 | resolution: "@esbuild/linux-s390x@npm:0.25.0" 323 | conditions: os=linux & cpu=s390x 324 | languageName: node 325 | linkType: hard 326 | 327 | "@esbuild/linux-x64@npm:0.25.0": 328 | version: 0.25.0 329 | resolution: "@esbuild/linux-x64@npm:0.25.0" 330 | conditions: os=linux & cpu=x64 331 | languageName: node 332 | linkType: hard 333 | 334 | "@esbuild/netbsd-arm64@npm:0.25.0": 335 | version: 0.25.0 336 | resolution: "@esbuild/netbsd-arm64@npm:0.25.0" 337 | conditions: os=netbsd & cpu=arm64 338 | languageName: node 339 | linkType: hard 340 | 341 | "@esbuild/netbsd-x64@npm:0.25.0": 342 | version: 0.25.0 343 | resolution: "@esbuild/netbsd-x64@npm:0.25.0" 344 | conditions: os=netbsd & cpu=x64 345 | languageName: node 346 | linkType: hard 347 | 348 | "@esbuild/openbsd-arm64@npm:0.25.0": 349 | version: 0.25.0 350 | resolution: "@esbuild/openbsd-arm64@npm:0.25.0" 351 | conditions: os=openbsd & cpu=arm64 352 | languageName: node 353 | linkType: hard 354 | 355 | "@esbuild/openbsd-x64@npm:0.25.0": 356 | version: 0.25.0 357 | resolution: "@esbuild/openbsd-x64@npm:0.25.0" 358 | conditions: os=openbsd & cpu=x64 359 | languageName: node 360 | linkType: hard 361 | 362 | "@esbuild/sunos-x64@npm:0.25.0": 363 | version: 0.25.0 364 | resolution: "@esbuild/sunos-x64@npm:0.25.0" 365 | conditions: os=sunos & cpu=x64 366 | languageName: node 367 | linkType: hard 368 | 369 | "@esbuild/win32-arm64@npm:0.25.0": 370 | version: 0.25.0 371 | resolution: "@esbuild/win32-arm64@npm:0.25.0" 372 | conditions: os=win32 & cpu=arm64 373 | languageName: node 374 | linkType: hard 375 | 376 | "@esbuild/win32-ia32@npm:0.25.0": 377 | version: 0.25.0 378 | resolution: "@esbuild/win32-ia32@npm:0.25.0" 379 | conditions: os=win32 & cpu=ia32 380 | languageName: node 381 | linkType: hard 382 | 383 | "@esbuild/win32-x64@npm:0.25.0": 384 | version: 0.25.0 385 | resolution: "@esbuild/win32-x64@npm:0.25.0" 386 | conditions: os=win32 & cpu=x64 387 | languageName: node 388 | linkType: hard 389 | 390 | "@isaacs/cliui@npm:^8.0.2": 391 | version: 8.0.2 392 | resolution: "@isaacs/cliui@npm:8.0.2" 393 | dependencies: 394 | string-width: "npm:^5.1.2" 395 | string-width-cjs: "npm:string-width@^4.2.0" 396 | strip-ansi: "npm:^7.0.1" 397 | strip-ansi-cjs: "npm:strip-ansi@^6.0.1" 398 | wrap-ansi: "npm:^8.1.0" 399 | wrap-ansi-cjs: "npm:wrap-ansi@^7.0.0" 400 | checksum: 10c0/b1bf42535d49f11dc137f18d5e4e63a28c5569de438a221c369483731e9dac9fb797af554e8bf02b6192d1e5eba6e6402cf93900c3d0ac86391d00d04876789e 401 | languageName: node 402 | linkType: hard 403 | 404 | "@isaacs/fs-minipass@npm:^4.0.0": 405 | version: 4.0.1 406 | resolution: "@isaacs/fs-minipass@npm:4.0.1" 407 | dependencies: 408 | minipass: "npm:^7.0.4" 409 | checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 410 | languageName: node 411 | linkType: hard 412 | 413 | "@jridgewell/gen-mapping@npm:^0.3.5": 414 | version: 0.3.8 415 | resolution: "@jridgewell/gen-mapping@npm:0.3.8" 416 | dependencies: 417 | "@jridgewell/set-array": "npm:^1.2.1" 418 | "@jridgewell/sourcemap-codec": "npm:^1.4.10" 419 | "@jridgewell/trace-mapping": "npm:^0.3.24" 420 | checksum: 10c0/c668feaf86c501d7c804904a61c23c67447b2137b813b9ce03eca82cb9d65ac7006d766c218685d76e3d72828279b6ee26c347aa1119dab23fbaf36aed51585a 421 | languageName: node 422 | linkType: hard 423 | 424 | "@jridgewell/resolve-uri@npm:^3.1.0": 425 | version: 3.1.2 426 | resolution: "@jridgewell/resolve-uri@npm:3.1.2" 427 | checksum: 10c0/d502e6fb516b35032331406d4e962c21fe77cdf1cbdb49c6142bcbd9e30507094b18972778a6e27cbad756209cfe34b1a27729e6fa08a2eb92b33943f680cf1e 428 | languageName: node 429 | linkType: hard 430 | 431 | "@jridgewell/set-array@npm:^1.2.1": 432 | version: 1.2.1 433 | resolution: "@jridgewell/set-array@npm:1.2.1" 434 | checksum: 10c0/2a5aa7b4b5c3464c895c802d8ae3f3d2b92fcbe84ad12f8d0bfbb1f5ad006717e7577ee1fd2eac00c088abe486c7adb27976f45d2941ff6b0b92b2c3302c60f4 435 | languageName: node 436 | linkType: hard 437 | 438 | "@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.14": 439 | version: 1.5.0 440 | resolution: "@jridgewell/sourcemap-codec@npm:1.5.0" 441 | checksum: 10c0/2eb864f276eb1096c3c11da3e9bb518f6d9fc0023c78344cdc037abadc725172c70314bdb360f2d4b7bffec7f5d657ce006816bc5d4ecb35e61b66132db00c18 442 | languageName: node 443 | linkType: hard 444 | 445 | "@jridgewell/trace-mapping@npm:^0.3.24, @jridgewell/trace-mapping@npm:^0.3.25": 446 | version: 0.3.25 447 | resolution: "@jridgewell/trace-mapping@npm:0.3.25" 448 | dependencies: 449 | "@jridgewell/resolve-uri": "npm:^3.1.0" 450 | "@jridgewell/sourcemap-codec": "npm:^1.4.14" 451 | checksum: 10c0/3d1ce6ebc69df9682a5a8896b414c6537e428a1d68b02fcc8363b04284a8ca0df04d0ee3013132252ab14f2527bc13bea6526a912ecb5658f0e39fd2860b4df4 452 | languageName: node 453 | linkType: hard 454 | 455 | "@npmcli/agent@npm:^3.0.0": 456 | version: 3.0.0 457 | resolution: "@npmcli/agent@npm:3.0.0" 458 | dependencies: 459 | agent-base: "npm:^7.1.0" 460 | http-proxy-agent: "npm:^7.0.0" 461 | https-proxy-agent: "npm:^7.0.1" 462 | lru-cache: "npm:^10.0.1" 463 | socks-proxy-agent: "npm:^8.0.3" 464 | checksum: 10c0/efe37b982f30740ee77696a80c196912c274ecd2cb243bc6ae7053a50c733ce0f6c09fda085145f33ecf453be19654acca74b69e81eaad4c90f00ccffe2f9271 465 | languageName: node 466 | linkType: hard 467 | 468 | "@npmcli/fs@npm:^4.0.0": 469 | version: 4.0.0 470 | resolution: "@npmcli/fs@npm:4.0.0" 471 | dependencies: 472 | semver: "npm:^7.3.5" 473 | checksum: 10c0/c90935d5ce670c87b6b14fab04a965a3b8137e585f8b2a6257263bd7f97756dd736cb165bb470e5156a9e718ecd99413dccc54b1138c1a46d6ec7cf325982fe5 474 | languageName: node 475 | linkType: hard 476 | 477 | "@pkgjs/parseargs@npm:^0.11.0": 478 | version: 0.11.0 479 | resolution: "@pkgjs/parseargs@npm:0.11.0" 480 | checksum: 10c0/5bd7576bb1b38a47a7fc7b51ac9f38748e772beebc56200450c4a817d712232b8f1d3ef70532c80840243c657d491cf6a6be1e3a214cff907645819fdc34aadd 481 | languageName: node 482 | linkType: hard 483 | 484 | "@rollup/rollup-android-arm-eabi@npm:4.34.9": 485 | version: 4.34.9 486 | resolution: "@rollup/rollup-android-arm-eabi@npm:4.34.9" 487 | conditions: os=android & cpu=arm 488 | languageName: node 489 | linkType: hard 490 | 491 | "@rollup/rollup-android-arm64@npm:4.34.9": 492 | version: 4.34.9 493 | resolution: "@rollup/rollup-android-arm64@npm:4.34.9" 494 | conditions: os=android & cpu=arm64 495 | languageName: node 496 | linkType: hard 497 | 498 | "@rollup/rollup-darwin-arm64@npm:4.34.9": 499 | version: 4.34.9 500 | resolution: "@rollup/rollup-darwin-arm64@npm:4.34.9" 501 | conditions: os=darwin & cpu=arm64 502 | languageName: node 503 | linkType: hard 504 | 505 | "@rollup/rollup-darwin-x64@npm:4.34.9": 506 | version: 4.34.9 507 | resolution: "@rollup/rollup-darwin-x64@npm:4.34.9" 508 | conditions: os=darwin & cpu=x64 509 | languageName: node 510 | linkType: hard 511 | 512 | "@rollup/rollup-freebsd-arm64@npm:4.34.9": 513 | version: 4.34.9 514 | resolution: "@rollup/rollup-freebsd-arm64@npm:4.34.9" 515 | conditions: os=freebsd & cpu=arm64 516 | languageName: node 517 | linkType: hard 518 | 519 | "@rollup/rollup-freebsd-x64@npm:4.34.9": 520 | version: 4.34.9 521 | resolution: "@rollup/rollup-freebsd-x64@npm:4.34.9" 522 | conditions: os=freebsd & cpu=x64 523 | languageName: node 524 | linkType: hard 525 | 526 | "@rollup/rollup-linux-arm-gnueabihf@npm:4.34.9": 527 | version: 4.34.9 528 | resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.34.9" 529 | conditions: os=linux & cpu=arm & libc=glibc 530 | languageName: node 531 | linkType: hard 532 | 533 | "@rollup/rollup-linux-arm-musleabihf@npm:4.34.9": 534 | version: 4.34.9 535 | resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.34.9" 536 | conditions: os=linux & cpu=arm & libc=musl 537 | languageName: node 538 | linkType: hard 539 | 540 | "@rollup/rollup-linux-arm64-gnu@npm:4.34.9": 541 | version: 4.34.9 542 | resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.34.9" 543 | conditions: os=linux & cpu=arm64 & libc=glibc 544 | languageName: node 545 | linkType: hard 546 | 547 | "@rollup/rollup-linux-arm64-musl@npm:4.34.9": 548 | version: 4.34.9 549 | resolution: "@rollup/rollup-linux-arm64-musl@npm:4.34.9" 550 | conditions: os=linux & cpu=arm64 & libc=musl 551 | languageName: node 552 | linkType: hard 553 | 554 | "@rollup/rollup-linux-loongarch64-gnu@npm:4.34.9": 555 | version: 4.34.9 556 | resolution: "@rollup/rollup-linux-loongarch64-gnu@npm:4.34.9" 557 | conditions: os=linux & cpu=loong64 & libc=glibc 558 | languageName: node 559 | linkType: hard 560 | 561 | "@rollup/rollup-linux-powerpc64le-gnu@npm:4.34.9": 562 | version: 4.34.9 563 | resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.34.9" 564 | conditions: os=linux & cpu=ppc64 & libc=glibc 565 | languageName: node 566 | linkType: hard 567 | 568 | "@rollup/rollup-linux-riscv64-gnu@npm:4.34.9": 569 | version: 4.34.9 570 | resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.34.9" 571 | conditions: os=linux & cpu=riscv64 & libc=glibc 572 | languageName: node 573 | linkType: hard 574 | 575 | "@rollup/rollup-linux-s390x-gnu@npm:4.34.9": 576 | version: 4.34.9 577 | resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.34.9" 578 | conditions: os=linux & cpu=s390x & libc=glibc 579 | languageName: node 580 | linkType: hard 581 | 582 | "@rollup/rollup-linux-x64-gnu@npm:4.34.9": 583 | version: 4.34.9 584 | resolution: "@rollup/rollup-linux-x64-gnu@npm:4.34.9" 585 | conditions: os=linux & cpu=x64 & libc=glibc 586 | languageName: node 587 | linkType: hard 588 | 589 | "@rollup/rollup-linux-x64-musl@npm:4.34.9": 590 | version: 4.34.9 591 | resolution: "@rollup/rollup-linux-x64-musl@npm:4.34.9" 592 | conditions: os=linux & cpu=x64 & libc=musl 593 | languageName: node 594 | linkType: hard 595 | 596 | "@rollup/rollup-win32-arm64-msvc@npm:4.34.9": 597 | version: 4.34.9 598 | resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.34.9" 599 | conditions: os=win32 & cpu=arm64 600 | languageName: node 601 | linkType: hard 602 | 603 | "@rollup/rollup-win32-ia32-msvc@npm:4.34.9": 604 | version: 4.34.9 605 | resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.34.9" 606 | conditions: os=win32 & cpu=ia32 607 | languageName: node 608 | linkType: hard 609 | 610 | "@rollup/rollup-win32-x64-msvc@npm:4.34.9": 611 | version: 4.34.9 612 | resolution: "@rollup/rollup-win32-x64-msvc@npm:4.34.9" 613 | conditions: os=win32 & cpu=x64 614 | languageName: node 615 | linkType: hard 616 | 617 | "@types/babel__core@npm:^7.20.5": 618 | version: 7.20.5 619 | resolution: "@types/babel__core@npm:7.20.5" 620 | dependencies: 621 | "@babel/parser": "npm:^7.20.7" 622 | "@babel/types": "npm:^7.20.7" 623 | "@types/babel__generator": "npm:*" 624 | "@types/babel__template": "npm:*" 625 | "@types/babel__traverse": "npm:*" 626 | checksum: 10c0/bdee3bb69951e833a4b811b8ee9356b69a61ed5b7a23e1a081ec9249769117fa83aaaf023bb06562a038eb5845155ff663e2d5c75dd95c1d5ccc91db012868ff 627 | languageName: node 628 | linkType: hard 629 | 630 | "@types/babel__generator@npm:*": 631 | version: 7.6.4 632 | resolution: "@types/babel__generator@npm:7.6.4" 633 | dependencies: 634 | "@babel/types": "npm:^7.0.0" 635 | checksum: 10c0/e0051b450e4ba2df0a7e386f08df902a4e920f6f8d6f185d69ddbe9b0e2e2d3ae434bb51e437bc0fca2a9a0f5dc4ca44d3a1941ef75e74371e8be5bf64416fe4 636 | languageName: node 637 | linkType: hard 638 | 639 | "@types/babel__template@npm:*": 640 | version: 7.4.1 641 | resolution: "@types/babel__template@npm:7.4.1" 642 | dependencies: 643 | "@babel/parser": "npm:^7.1.0" 644 | "@babel/types": "npm:^7.0.0" 645 | checksum: 10c0/6f180e96c39765487f27e861d43eebed341ec7a2fc06cdf5a52c22872fae67f474ca165d149c708f4fd9d5482beb66c0a92f77411b234bb30262ed2303e50b1a 646 | languageName: node 647 | linkType: hard 648 | 649 | "@types/babel__traverse@npm:*": 650 | version: 7.18.3 651 | resolution: "@types/babel__traverse@npm:7.18.3" 652 | dependencies: 653 | "@babel/types": "npm:^7.3.0" 654 | checksum: 10c0/4214fd3e95925d9a7efa01142969a310263430d4f5de89be6c9c193110666677415161b474fa627d751dfd0f1eb7dc1c84c48f8b53098625c6bc78917683215a 655 | languageName: node 656 | linkType: hard 657 | 658 | "@types/estree@npm:1.0.6": 659 | version: 1.0.6 660 | resolution: "@types/estree@npm:1.0.6" 661 | checksum: 10c0/cdfd751f6f9065442cd40957c07fd80361c962869aa853c1c2fd03e101af8b9389d8ff4955a43a6fcfa223dd387a089937f95be0f3eec21ca527039fd2d9859a 662 | languageName: node 663 | linkType: hard 664 | 665 | "@vitejs/plugin-react@npm:^4.3.4": 666 | version: 4.3.4 667 | resolution: "@vitejs/plugin-react@npm:4.3.4" 668 | dependencies: 669 | "@babel/core": "npm:^7.26.0" 670 | "@babel/plugin-transform-react-jsx-self": "npm:^7.25.9" 671 | "@babel/plugin-transform-react-jsx-source": "npm:^7.25.9" 672 | "@types/babel__core": "npm:^7.20.5" 673 | react-refresh: "npm:^0.14.2" 674 | peerDependencies: 675 | vite: ^4.2.0 || ^5.0.0 || ^6.0.0 676 | checksum: 10c0/38a47a1dbafae0b97142943d83ee3674cb3331153a60b1a3fd29d230c12c9dfe63b7c345b231a3450168ed8a9375a9a1a253c3d85e9efdc19478c0d56b98496c 677 | languageName: node 678 | linkType: hard 679 | 680 | "@wojtekmaj/react-recaptcha-v3@portal:../packages/react-recaptcha-v3::locator=react-recaptcha-v3-sample-page%40workspace%3A.": 681 | version: 0.0.0-use.local 682 | resolution: "@wojtekmaj/react-recaptcha-v3@portal:../packages/react-recaptcha-v3::locator=react-recaptcha-v3-sample-page%40workspace%3A." 683 | dependencies: 684 | warning: "npm:^4.0.0" 685 | peerDependencies: 686 | "@types/react": ^18.0.0 || ^19.0.0 687 | react: ^18.0.0 || ^19.0.0 688 | react-dom: ^18.0.0 || ^19.0.0 689 | peerDependenciesMeta: 690 | "@types/react": 691 | optional: true 692 | languageName: node 693 | linkType: soft 694 | 695 | "abbrev@npm:^3.0.0": 696 | version: 3.0.0 697 | resolution: "abbrev@npm:3.0.0" 698 | checksum: 10c0/049704186396f571650eb7b22ed3627b77a5aedf98bb83caf2eac81ca2a3e25e795394b0464cfb2d6076df3db6a5312139eac5b6a126ca296ac53c5008069c28 699 | languageName: node 700 | linkType: hard 701 | 702 | "agent-base@npm:^7.0.2, agent-base@npm:^7.1.0, agent-base@npm:^7.1.2": 703 | version: 7.1.3 704 | resolution: "agent-base@npm:7.1.3" 705 | checksum: 10c0/6192b580c5b1d8fb399b9c62bf8343d76654c2dd62afcb9a52b2cf44a8b6ace1e3b704d3fe3547d91555c857d3df02603341ff2cb961b9cfe2b12f9f3c38ee11 706 | languageName: node 707 | linkType: hard 708 | 709 | "ansi-regex@npm:^5.0.1": 710 | version: 5.0.1 711 | resolution: "ansi-regex@npm:5.0.1" 712 | checksum: 10c0/9a64bb8627b434ba9327b60c027742e5d17ac69277960d041898596271d992d4d52ba7267a63ca10232e29f6107fc8a835f6ce8d719b88c5f8493f8254813737 713 | languageName: node 714 | linkType: hard 715 | 716 | "ansi-regex@npm:^6.0.1": 717 | version: 6.0.1 718 | resolution: "ansi-regex@npm:6.0.1" 719 | checksum: 10c0/cbe16dbd2c6b2735d1df7976a7070dd277326434f0212f43abf6d87674095d247968209babdaad31bb00882fa68807256ba9be340eec2f1004de14ca75f52a08 720 | languageName: node 721 | linkType: hard 722 | 723 | "ansi-styles@npm:^4.0.0": 724 | version: 4.3.0 725 | resolution: "ansi-styles@npm:4.3.0" 726 | dependencies: 727 | color-convert: "npm:^2.0.1" 728 | checksum: 10c0/895a23929da416f2bd3de7e9cb4eabd340949328ab85ddd6e484a637d8f6820d485f53933446f5291c3b760cbc488beb8e88573dd0f9c7daf83dccc8fe81b041 729 | languageName: node 730 | linkType: hard 731 | 732 | "ansi-styles@npm:^6.1.0": 733 | version: 6.2.1 734 | resolution: "ansi-styles@npm:6.2.1" 735 | checksum: 10c0/5d1ec38c123984bcedd996eac680d548f31828bd679a66db2bdf11844634dde55fec3efa9c6bb1d89056a5e79c1ac540c4c784d592ea1d25028a92227d2f2d5c 736 | languageName: node 737 | linkType: hard 738 | 739 | "balanced-match@npm:^1.0.0": 740 | version: 1.0.2 741 | resolution: "balanced-match@npm:1.0.2" 742 | checksum: 10c0/9308baf0a7e4838a82bbfd11e01b1cb0f0cf2893bc1676c27c2a8c0e70cbae1c59120c3268517a8ae7fb6376b4639ef81ca22582611dbee4ed28df945134aaee 743 | languageName: node 744 | linkType: hard 745 | 746 | "brace-expansion@npm:^2.0.1": 747 | version: 2.0.1 748 | resolution: "brace-expansion@npm:2.0.1" 749 | dependencies: 750 | balanced-match: "npm:^1.0.0" 751 | checksum: 10c0/b358f2fe060e2d7a87aa015979ecea07f3c37d4018f8d6deb5bd4c229ad3a0384fe6029bb76cd8be63c81e516ee52d1a0673edbe2023d53a5191732ae3c3e49f 752 | languageName: node 753 | linkType: hard 754 | 755 | "browserslist@npm:^4.24.0": 756 | version: 4.24.3 757 | resolution: "browserslist@npm:4.24.3" 758 | dependencies: 759 | caniuse-lite: "npm:^1.0.30001688" 760 | electron-to-chromium: "npm:^1.5.73" 761 | node-releases: "npm:^2.0.19" 762 | update-browserslist-db: "npm:^1.1.1" 763 | bin: 764 | browserslist: cli.js 765 | checksum: 10c0/bab261ef7b6e1656a719a9fa31240ae7ce4d5ba68e479f6b11e348d819346ab4c0ff6f4821f43adcc9c193a734b186775a83b37979e70a69d182965909fe569a 766 | languageName: node 767 | linkType: hard 768 | 769 | "cacache@npm:^19.0.1": 770 | version: 19.0.1 771 | resolution: "cacache@npm:19.0.1" 772 | dependencies: 773 | "@npmcli/fs": "npm:^4.0.0" 774 | fs-minipass: "npm:^3.0.0" 775 | glob: "npm:^10.2.2" 776 | lru-cache: "npm:^10.0.1" 777 | minipass: "npm:^7.0.3" 778 | minipass-collect: "npm:^2.0.1" 779 | minipass-flush: "npm:^1.0.5" 780 | minipass-pipeline: "npm:^1.2.4" 781 | p-map: "npm:^7.0.2" 782 | ssri: "npm:^12.0.0" 783 | tar: "npm:^7.4.3" 784 | unique-filename: "npm:^4.0.0" 785 | checksum: 10c0/01f2134e1bd7d3ab68be851df96c8d63b492b1853b67f2eecb2c37bb682d37cb70bb858a16f2f0554d3c0071be6dfe21456a1ff6fa4b7eed996570d6a25ffe9c 786 | languageName: node 787 | linkType: hard 788 | 789 | "caniuse-lite@npm:^1.0.30001688": 790 | version: 1.0.30001690 791 | resolution: "caniuse-lite@npm:1.0.30001690" 792 | checksum: 10c0/646bd469032afa90400a84dec30a2b00a6eda62c03ead358117e3f884cda8aacec02ec058a6dbee5eaf9714f83e483b9b0eb4fb42febb8076569f5ca40f1d347 793 | languageName: node 794 | linkType: hard 795 | 796 | "chownr@npm:^3.0.0": 797 | version: 3.0.0 798 | resolution: "chownr@npm:3.0.0" 799 | checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 800 | languageName: node 801 | linkType: hard 802 | 803 | "color-convert@npm:^2.0.1": 804 | version: 2.0.1 805 | resolution: "color-convert@npm:2.0.1" 806 | dependencies: 807 | color-name: "npm:~1.1.4" 808 | checksum: 10c0/37e1150172f2e311fe1b2df62c6293a342ee7380da7b9cfdba67ea539909afbd74da27033208d01d6d5cfc65ee7868a22e18d7e7648e004425441c0f8a15a7d7 809 | languageName: node 810 | linkType: hard 811 | 812 | "color-name@npm:~1.1.4": 813 | version: 1.1.4 814 | resolution: "color-name@npm:1.1.4" 815 | checksum: 10c0/a1a3f914156960902f46f7f56bc62effc6c94e84b2cae157a526b1c1f74b677a47ec602bf68a61abfa2b42d15b7c5651c6dbe72a43af720bc588dff885b10f95 816 | languageName: node 817 | linkType: hard 818 | 819 | "convert-source-map@npm:^2.0.0": 820 | version: 2.0.0 821 | resolution: "convert-source-map@npm:2.0.0" 822 | checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b 823 | languageName: node 824 | linkType: hard 825 | 826 | "cross-spawn@npm:^7.0.0": 827 | version: 7.0.6 828 | resolution: "cross-spawn@npm:7.0.6" 829 | dependencies: 830 | path-key: "npm:^3.1.0" 831 | shebang-command: "npm:^2.0.0" 832 | which: "npm:^2.0.1" 833 | checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 834 | languageName: node 835 | linkType: hard 836 | 837 | "debug@npm:4, debug@npm:^4.1.0, debug@npm:^4.3.1, debug@npm:^4.3.4": 838 | version: 4.4.0 839 | resolution: "debug@npm:4.4.0" 840 | dependencies: 841 | ms: "npm:^2.1.3" 842 | peerDependenciesMeta: 843 | supports-color: 844 | optional: true 845 | checksum: 10c0/db94f1a182bf886f57b4755f85b3a74c39b5114b9377b7ab375dc2cfa3454f09490cc6c30f829df3fc8042bc8b8995f6567ce5cd96f3bc3688bd24027197d9de 846 | languageName: node 847 | linkType: hard 848 | 849 | "eastasianwidth@npm:^0.2.0": 850 | version: 0.2.0 851 | resolution: "eastasianwidth@npm:0.2.0" 852 | checksum: 10c0/26f364ebcdb6395f95124fda411f63137a4bfb5d3a06453f7f23dfe52502905bd84e0488172e0f9ec295fdc45f05c23d5d91baf16bd26f0fe9acd777a188dc39 853 | languageName: node 854 | linkType: hard 855 | 856 | "electron-to-chromium@npm:^1.5.73": 857 | version: 1.5.75 858 | resolution: "electron-to-chromium@npm:1.5.75" 859 | checksum: 10c0/df769b7a5e9895a8ba8eb7f31b9525a0e00b8aef6e3ecab3faebe90756fc9ac008dddb8d9a2a78d2079cbaebd27da6e1379f77e910163f405bb1a3d622ec4276 860 | languageName: node 861 | linkType: hard 862 | 863 | "emoji-regex@npm:^8.0.0": 864 | version: 8.0.0 865 | resolution: "emoji-regex@npm:8.0.0" 866 | checksum: 10c0/b6053ad39951c4cf338f9092d7bfba448cdfd46fe6a2a034700b149ac9ffbc137e361cbd3c442297f86bed2e5f7576c1b54cc0a6bf8ef5106cc62f496af35010 867 | languageName: node 868 | linkType: hard 869 | 870 | "emoji-regex@npm:^9.2.2": 871 | version: 9.2.2 872 | resolution: "emoji-regex@npm:9.2.2" 873 | checksum: 10c0/af014e759a72064cf66e6e694a7fc6b0ed3d8db680427b021a89727689671cefe9d04151b2cad51dbaf85d5ba790d061cd167f1cf32eb7b281f6368b3c181639 874 | languageName: node 875 | linkType: hard 876 | 877 | "encoding@npm:^0.1.13": 878 | version: 0.1.13 879 | resolution: "encoding@npm:0.1.13" 880 | dependencies: 881 | iconv-lite: "npm:^0.6.2" 882 | checksum: 10c0/36d938712ff00fe1f4bac88b43bcffb5930c1efa57bbcdca9d67e1d9d6c57cfb1200fb01efe0f3109b2ce99b231f90779532814a81370a1bd3274a0f58585039 883 | languageName: node 884 | linkType: hard 885 | 886 | "env-paths@npm:^2.2.0": 887 | version: 2.2.1 888 | resolution: "env-paths@npm:2.2.1" 889 | checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 890 | languageName: node 891 | linkType: hard 892 | 893 | "err-code@npm:^2.0.2": 894 | version: 2.0.3 895 | resolution: "err-code@npm:2.0.3" 896 | checksum: 10c0/b642f7b4dd4a376e954947550a3065a9ece6733ab8e51ad80db727aaae0817c2e99b02a97a3d6cecc648a97848305e728289cf312d09af395403a90c9d4d8a66 897 | languageName: node 898 | linkType: hard 899 | 900 | "esbuild@npm:^0.25.0": 901 | version: 0.25.0 902 | resolution: "esbuild@npm:0.25.0" 903 | dependencies: 904 | "@esbuild/aix-ppc64": "npm:0.25.0" 905 | "@esbuild/android-arm": "npm:0.25.0" 906 | "@esbuild/android-arm64": "npm:0.25.0" 907 | "@esbuild/android-x64": "npm:0.25.0" 908 | "@esbuild/darwin-arm64": "npm:0.25.0" 909 | "@esbuild/darwin-x64": "npm:0.25.0" 910 | "@esbuild/freebsd-arm64": "npm:0.25.0" 911 | "@esbuild/freebsd-x64": "npm:0.25.0" 912 | "@esbuild/linux-arm": "npm:0.25.0" 913 | "@esbuild/linux-arm64": "npm:0.25.0" 914 | "@esbuild/linux-ia32": "npm:0.25.0" 915 | "@esbuild/linux-loong64": "npm:0.25.0" 916 | "@esbuild/linux-mips64el": "npm:0.25.0" 917 | "@esbuild/linux-ppc64": "npm:0.25.0" 918 | "@esbuild/linux-riscv64": "npm:0.25.0" 919 | "@esbuild/linux-s390x": "npm:0.25.0" 920 | "@esbuild/linux-x64": "npm:0.25.0" 921 | "@esbuild/netbsd-arm64": "npm:0.25.0" 922 | "@esbuild/netbsd-x64": "npm:0.25.0" 923 | "@esbuild/openbsd-arm64": "npm:0.25.0" 924 | "@esbuild/openbsd-x64": "npm:0.25.0" 925 | "@esbuild/sunos-x64": "npm:0.25.0" 926 | "@esbuild/win32-arm64": "npm:0.25.0" 927 | "@esbuild/win32-ia32": "npm:0.25.0" 928 | "@esbuild/win32-x64": "npm:0.25.0" 929 | dependenciesMeta: 930 | "@esbuild/aix-ppc64": 931 | optional: true 932 | "@esbuild/android-arm": 933 | optional: true 934 | "@esbuild/android-arm64": 935 | optional: true 936 | "@esbuild/android-x64": 937 | optional: true 938 | "@esbuild/darwin-arm64": 939 | optional: true 940 | "@esbuild/darwin-x64": 941 | optional: true 942 | "@esbuild/freebsd-arm64": 943 | optional: true 944 | "@esbuild/freebsd-x64": 945 | optional: true 946 | "@esbuild/linux-arm": 947 | optional: true 948 | "@esbuild/linux-arm64": 949 | optional: true 950 | "@esbuild/linux-ia32": 951 | optional: true 952 | "@esbuild/linux-loong64": 953 | optional: true 954 | "@esbuild/linux-mips64el": 955 | optional: true 956 | "@esbuild/linux-ppc64": 957 | optional: true 958 | "@esbuild/linux-riscv64": 959 | optional: true 960 | "@esbuild/linux-s390x": 961 | optional: true 962 | "@esbuild/linux-x64": 963 | optional: true 964 | "@esbuild/netbsd-arm64": 965 | optional: true 966 | "@esbuild/netbsd-x64": 967 | optional: true 968 | "@esbuild/openbsd-arm64": 969 | optional: true 970 | "@esbuild/openbsd-x64": 971 | optional: true 972 | "@esbuild/sunos-x64": 973 | optional: true 974 | "@esbuild/win32-arm64": 975 | optional: true 976 | "@esbuild/win32-ia32": 977 | optional: true 978 | "@esbuild/win32-x64": 979 | optional: true 980 | bin: 981 | esbuild: bin/esbuild 982 | checksum: 10c0/5767b72da46da3cfec51661647ec850ddbf8a8d0662771139f10ef0692a8831396a0004b2be7966cecdb08264fb16bdc16290dcecd92396fac5f12d722fa013d 983 | languageName: node 984 | linkType: hard 985 | 986 | "escalade@npm:^3.2.0": 987 | version: 3.2.0 988 | resolution: "escalade@npm:3.2.0" 989 | checksum: 10c0/ced4dd3a78e15897ed3be74e635110bbf3b08877b0a41be50dcb325ee0e0b5f65fc2d50e9845194d7c4633f327e2e1c6cce00a71b617c5673df0374201d67f65 990 | languageName: node 991 | linkType: hard 992 | 993 | "exponential-backoff@npm:^3.1.1": 994 | version: 3.1.1 995 | resolution: "exponential-backoff@npm:3.1.1" 996 | checksum: 10c0/160456d2d647e6019640bd07111634d8c353038d9fa40176afb7cd49b0548bdae83b56d05e907c2cce2300b81cae35d800ef92fefb9d0208e190fa3b7d6bb579 997 | languageName: node 998 | linkType: hard 999 | 1000 | "foreground-child@npm:^3.1.0": 1001 | version: 3.1.1 1002 | resolution: "foreground-child@npm:3.1.1" 1003 | dependencies: 1004 | cross-spawn: "npm:^7.0.0" 1005 | signal-exit: "npm:^4.0.1" 1006 | checksum: 10c0/9700a0285628abaeb37007c9a4d92bd49f67210f09067638774338e146c8e9c825c5c877f072b2f75f41dc6a2d0be8664f79ffc03f6576649f54a84fb9b47de0 1007 | languageName: node 1008 | linkType: hard 1009 | 1010 | "fs-minipass@npm:^3.0.0": 1011 | version: 3.0.3 1012 | resolution: "fs-minipass@npm:3.0.3" 1013 | dependencies: 1014 | minipass: "npm:^7.0.3" 1015 | checksum: 10c0/63e80da2ff9b621e2cb1596abcb9207f1cf82b968b116ccd7b959e3323144cce7fb141462200971c38bbf2ecca51695069db45265705bed09a7cd93ae5b89f94 1016 | languageName: node 1017 | linkType: hard 1018 | 1019 | "fsevents@npm:~2.3.2, fsevents@npm:~2.3.3": 1020 | version: 2.3.3 1021 | resolution: "fsevents@npm:2.3.3" 1022 | dependencies: 1023 | node-gyp: "npm:latest" 1024 | checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 1025 | conditions: os=darwin 1026 | languageName: node 1027 | linkType: hard 1028 | 1029 | "fsevents@patch:fsevents@npm%3A~2.3.2#optional!builtin, fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": 1030 | version: 2.3.3 1031 | resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" 1032 | dependencies: 1033 | node-gyp: "npm:latest" 1034 | conditions: os=darwin 1035 | languageName: node 1036 | linkType: hard 1037 | 1038 | "gensync@npm:^1.0.0-beta.2": 1039 | version: 1.0.0-beta.2 1040 | resolution: "gensync@npm:1.0.0-beta.2" 1041 | checksum: 10c0/782aba6cba65b1bb5af3b095d96249d20edbe8df32dbf4696fd49be2583faf676173bf4809386588828e4dd76a3354fcbeb577bab1c833ccd9fc4577f26103f8 1042 | languageName: node 1043 | linkType: hard 1044 | 1045 | "glob@npm:^10.2.2, glob@npm:^10.3.10": 1046 | version: 10.3.10 1047 | resolution: "glob@npm:10.3.10" 1048 | dependencies: 1049 | foreground-child: "npm:^3.1.0" 1050 | jackspeak: "npm:^2.3.5" 1051 | minimatch: "npm:^9.0.1" 1052 | minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" 1053 | path-scurry: "npm:^1.10.1" 1054 | bin: 1055 | glob: dist/esm/bin.mjs 1056 | checksum: 10c0/13d8a1feb7eac7945f8c8480e11cd4a44b24d26503d99a8d8ac8d5aefbf3e9802a2b6087318a829fad04cb4e829f25c5f4f1110c68966c498720dd261c7e344d 1057 | languageName: node 1058 | linkType: hard 1059 | 1060 | "globals@npm:^11.1.0": 1061 | version: 11.12.0 1062 | resolution: "globals@npm:11.12.0" 1063 | checksum: 10c0/758f9f258e7b19226bd8d4af5d3b0dcf7038780fb23d82e6f98932c44e239f884847f1766e8fa9cc5635ccb3204f7fa7314d4408dd4002a5e8ea827b4018f0a1 1064 | languageName: node 1065 | linkType: hard 1066 | 1067 | "graceful-fs@npm:^4.2.6": 1068 | version: 4.2.11 1069 | resolution: "graceful-fs@npm:4.2.11" 1070 | checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 1071 | languageName: node 1072 | linkType: hard 1073 | 1074 | "http-cache-semantics@npm:^4.1.1": 1075 | version: 4.1.1 1076 | resolution: "http-cache-semantics@npm:4.1.1" 1077 | checksum: 10c0/ce1319b8a382eb3cbb4a37c19f6bfe14e5bb5be3d09079e885e8c513ab2d3cd9214902f8a31c9dc4e37022633ceabfc2d697405deeaf1b8f3552bb4ed996fdfc 1078 | languageName: node 1079 | linkType: hard 1080 | 1081 | "http-proxy-agent@npm:^7.0.0": 1082 | version: 7.0.0 1083 | resolution: "http-proxy-agent@npm:7.0.0" 1084 | dependencies: 1085 | agent-base: "npm:^7.1.0" 1086 | debug: "npm:^4.3.4" 1087 | checksum: 10c0/a11574ff39436cee3c7bc67f259444097b09474605846ddd8edf0bf4ad8644be8533db1aa463426e376865047d05dc22755e638632819317c0c2f1b2196657c8 1088 | languageName: node 1089 | linkType: hard 1090 | 1091 | "https-proxy-agent@npm:^7.0.1": 1092 | version: 7.0.2 1093 | resolution: "https-proxy-agent@npm:7.0.2" 1094 | dependencies: 1095 | agent-base: "npm:^7.0.2" 1096 | debug: "npm:4" 1097 | checksum: 10c0/7735eb90073db087e7e79312e3d97c8c04baf7ea7ca7b013382b6a45abbaa61b281041a98f4e13c8c80d88f843785bcc84ba189165b4b4087b1e3496ba656d77 1098 | languageName: node 1099 | linkType: hard 1100 | 1101 | "iconv-lite@npm:^0.6.2": 1102 | version: 0.6.3 1103 | resolution: "iconv-lite@npm:0.6.3" 1104 | dependencies: 1105 | safer-buffer: "npm:>= 2.1.2 < 3.0.0" 1106 | checksum: 10c0/98102bc66b33fcf5ac044099d1257ba0b7ad5e3ccd3221f34dd508ab4070edff183276221684e1e0555b145fce0850c9f7d2b60a9fcac50fbb4ea0d6e845a3b1 1107 | languageName: node 1108 | linkType: hard 1109 | 1110 | "imurmurhash@npm:^0.1.4": 1111 | version: 0.1.4 1112 | resolution: "imurmurhash@npm:0.1.4" 1113 | checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 1114 | languageName: node 1115 | linkType: hard 1116 | 1117 | "ip-address@npm:^9.0.5": 1118 | version: 9.0.5 1119 | resolution: "ip-address@npm:9.0.5" 1120 | dependencies: 1121 | jsbn: "npm:1.1.0" 1122 | sprintf-js: "npm:^1.1.3" 1123 | checksum: 10c0/331cd07fafcb3b24100613e4b53e1a2b4feab11e671e655d46dc09ee233da5011284d09ca40c4ecbdfe1d0004f462958675c224a804259f2f78d2465a87824bc 1124 | languageName: node 1125 | linkType: hard 1126 | 1127 | "is-fullwidth-code-point@npm:^3.0.0": 1128 | version: 3.0.0 1129 | resolution: "is-fullwidth-code-point@npm:3.0.0" 1130 | checksum: 10c0/bb11d825e049f38e04c06373a8d72782eee0205bda9d908cc550ccb3c59b99d750ff9537982e01733c1c94a58e35400661f57042158ff5e8f3e90cf936daf0fc 1131 | languageName: node 1132 | linkType: hard 1133 | 1134 | "isexe@npm:^2.0.0": 1135 | version: 2.0.0 1136 | resolution: "isexe@npm:2.0.0" 1137 | checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d 1138 | languageName: node 1139 | linkType: hard 1140 | 1141 | "isexe@npm:^3.1.1": 1142 | version: 3.1.1 1143 | resolution: "isexe@npm:3.1.1" 1144 | checksum: 10c0/9ec257654093443eb0a528a9c8cbba9c0ca7616ccb40abd6dde7202734d96bb86e4ac0d764f0f8cd965856aacbff2f4ce23e730dc19dfb41e3b0d865ca6fdcc7 1145 | languageName: node 1146 | linkType: hard 1147 | 1148 | "jackspeak@npm:^2.3.5": 1149 | version: 2.3.6 1150 | resolution: "jackspeak@npm:2.3.6" 1151 | dependencies: 1152 | "@isaacs/cliui": "npm:^8.0.2" 1153 | "@pkgjs/parseargs": "npm:^0.11.0" 1154 | dependenciesMeta: 1155 | "@pkgjs/parseargs": 1156 | optional: true 1157 | checksum: 10c0/f01d8f972d894cd7638bc338e9ef5ddb86f7b208ce177a36d718eac96ec86638a6efa17d0221b10073e64b45edc2ce15340db9380b1f5d5c5d000cbc517dc111 1158 | languageName: node 1159 | linkType: hard 1160 | 1161 | "js-tokens@npm:^3.0.0 || ^4.0.0, js-tokens@npm:^4.0.0": 1162 | version: 4.0.0 1163 | resolution: "js-tokens@npm:4.0.0" 1164 | checksum: 10c0/e248708d377aa058eacf2037b07ded847790e6de892bbad3dac0abba2e759cb9f121b00099a65195616badcb6eca8d14d975cb3e89eb1cfda644756402c8aeed 1165 | languageName: node 1166 | linkType: hard 1167 | 1168 | "jsbn@npm:1.1.0": 1169 | version: 1.1.0 1170 | resolution: "jsbn@npm:1.1.0" 1171 | checksum: 10c0/4f907fb78d7b712e11dea8c165fe0921f81a657d3443dde75359ed52eb2b5d33ce6773d97985a089f09a65edd80b11cb75c767b57ba47391fee4c969f7215c96 1172 | languageName: node 1173 | linkType: hard 1174 | 1175 | "jsesc@npm:^3.0.2": 1176 | version: 3.1.0 1177 | resolution: "jsesc@npm:3.1.0" 1178 | bin: 1179 | jsesc: bin/jsesc 1180 | checksum: 10c0/531779df5ec94f47e462da26b4cbf05eb88a83d9f08aac2ba04206508fc598527a153d08bd462bae82fc78b3eaa1a908e1a4a79f886e9238641c4cdefaf118b1 1181 | languageName: node 1182 | linkType: hard 1183 | 1184 | "json5@npm:^2.2.3": 1185 | version: 2.2.3 1186 | resolution: "json5@npm:2.2.3" 1187 | bin: 1188 | json5: lib/cli.js 1189 | checksum: 10c0/5a04eed94810fa55c5ea138b2f7a5c12b97c3750bc63d11e511dcecbfef758003861522a070c2272764ee0f4e3e323862f386945aeb5b85b87ee43f084ba586c 1190 | languageName: node 1191 | linkType: hard 1192 | 1193 | "loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0": 1194 | version: 1.4.0 1195 | resolution: "loose-envify@npm:1.4.0" 1196 | dependencies: 1197 | js-tokens: "npm:^3.0.0 || ^4.0.0" 1198 | bin: 1199 | loose-envify: cli.js 1200 | checksum: 10c0/655d110220983c1a4b9c0c679a2e8016d4b67f6e9c7b5435ff5979ecdb20d0813f4dec0a08674fcbdd4846a3f07edbb50a36811fd37930b94aaa0d9daceb017e 1201 | languageName: node 1202 | linkType: hard 1203 | 1204 | "lru-cache@npm:^10.0.1, lru-cache@npm:^9.1.1 || ^10.0.0": 1205 | version: 10.2.0 1206 | resolution: "lru-cache@npm:10.2.0" 1207 | checksum: 10c0/c9847612aa2daaef102d30542a8d6d9b2c2bb36581c1bf0dc3ebf5e5f3352c772a749e604afae2e46873b930a9e9523743faac4e5b937c576ab29196774712ee 1208 | languageName: node 1209 | linkType: hard 1210 | 1211 | "lru-cache@npm:^5.1.1": 1212 | version: 5.1.1 1213 | resolution: "lru-cache@npm:5.1.1" 1214 | dependencies: 1215 | yallist: "npm:^3.0.2" 1216 | checksum: 10c0/89b2ef2ef45f543011e38737b8a8622a2f8998cddf0e5437174ef8f1f70a8b9d14a918ab3e232cb3ba343b7abddffa667f0b59075b2b80e6b4d63c3de6127482 1217 | languageName: node 1218 | linkType: hard 1219 | 1220 | "make-fetch-happen@npm:^14.0.3": 1221 | version: 14.0.3 1222 | resolution: "make-fetch-happen@npm:14.0.3" 1223 | dependencies: 1224 | "@npmcli/agent": "npm:^3.0.0" 1225 | cacache: "npm:^19.0.1" 1226 | http-cache-semantics: "npm:^4.1.1" 1227 | minipass: "npm:^7.0.2" 1228 | minipass-fetch: "npm:^4.0.0" 1229 | minipass-flush: "npm:^1.0.5" 1230 | minipass-pipeline: "npm:^1.2.4" 1231 | negotiator: "npm:^1.0.0" 1232 | proc-log: "npm:^5.0.0" 1233 | promise-retry: "npm:^2.0.1" 1234 | ssri: "npm:^12.0.0" 1235 | checksum: 10c0/c40efb5e5296e7feb8e37155bde8eb70bc57d731b1f7d90e35a092fde403d7697c56fb49334d92d330d6f1ca29a98142036d6480a12681133a0a1453164cb2f0 1236 | languageName: node 1237 | linkType: hard 1238 | 1239 | "minimatch@npm:^9.0.1": 1240 | version: 9.0.3 1241 | resolution: "minimatch@npm:9.0.3" 1242 | dependencies: 1243 | brace-expansion: "npm:^2.0.1" 1244 | checksum: 10c0/85f407dcd38ac3e180f425e86553911d101455ca3ad5544d6a7cec16286657e4f8a9aa6695803025c55e31e35a91a2252b5dc8e7d527211278b8b65b4dbd5eac 1245 | languageName: node 1246 | linkType: hard 1247 | 1248 | "minipass-collect@npm:^2.0.1": 1249 | version: 2.0.1 1250 | resolution: "minipass-collect@npm:2.0.1" 1251 | dependencies: 1252 | minipass: "npm:^7.0.3" 1253 | checksum: 10c0/5167e73f62bb74cc5019594709c77e6a742051a647fe9499abf03c71dca75515b7959d67a764bdc4f8b361cf897fbf25e2d9869ee039203ed45240f48b9aa06e 1254 | languageName: node 1255 | linkType: hard 1256 | 1257 | "minipass-fetch@npm:^4.0.0": 1258 | version: 4.0.0 1259 | resolution: "minipass-fetch@npm:4.0.0" 1260 | dependencies: 1261 | encoding: "npm:^0.1.13" 1262 | minipass: "npm:^7.0.3" 1263 | minipass-sized: "npm:^1.0.3" 1264 | minizlib: "npm:^3.0.1" 1265 | dependenciesMeta: 1266 | encoding: 1267 | optional: true 1268 | checksum: 10c0/7fa30ce7c373fb6f94c086b374fff1589fd7e78451855d2d06c2e2d9df936d131e73e952163063016592ed3081444bd8d1ea608533313b0149156ce23311da4b 1269 | languageName: node 1270 | linkType: hard 1271 | 1272 | "minipass-flush@npm:^1.0.5": 1273 | version: 1.0.5 1274 | resolution: "minipass-flush@npm:1.0.5" 1275 | dependencies: 1276 | minipass: "npm:^3.0.0" 1277 | checksum: 10c0/2a51b63feb799d2bb34669205eee7c0eaf9dce01883261a5b77410c9408aa447e478efd191b4de6fc1101e796ff5892f8443ef20d9544385819093dbb32d36bd 1278 | languageName: node 1279 | linkType: hard 1280 | 1281 | "minipass-pipeline@npm:^1.2.4": 1282 | version: 1.2.4 1283 | resolution: "minipass-pipeline@npm:1.2.4" 1284 | dependencies: 1285 | minipass: "npm:^3.0.0" 1286 | checksum: 10c0/cbda57cea20b140b797505dc2cac71581a70b3247b84480c1fed5ca5ba46c25ecc25f68bfc9e6dcb1a6e9017dab5c7ada5eab73ad4f0a49d84e35093e0c643f2 1287 | languageName: node 1288 | linkType: hard 1289 | 1290 | "minipass-sized@npm:^1.0.3": 1291 | version: 1.0.3 1292 | resolution: "minipass-sized@npm:1.0.3" 1293 | dependencies: 1294 | minipass: "npm:^3.0.0" 1295 | checksum: 10c0/298f124753efdc745cfe0f2bdfdd81ba25b9f4e753ca4a2066eb17c821f25d48acea607dfc997633ee5bf7b6dfffb4eee4f2051eb168663f0b99fad2fa4829cb 1296 | languageName: node 1297 | linkType: hard 1298 | 1299 | "minipass@npm:^3.0.0": 1300 | version: 3.3.6 1301 | resolution: "minipass@npm:3.3.6" 1302 | dependencies: 1303 | yallist: "npm:^4.0.0" 1304 | checksum: 10c0/a114746943afa1dbbca8249e706d1d38b85ed1298b530f5808ce51f8e9e941962e2a5ad2e00eae7dd21d8a4aae6586a66d4216d1a259385e9d0358f0c1eba16c 1305 | languageName: node 1306 | linkType: hard 1307 | 1308 | "minipass@npm:^5.0.0 || ^6.0.2 || ^7.0.0, minipass@npm:^7.0.2, minipass@npm:^7.0.3, minipass@npm:^7.0.4, minipass@npm:^7.1.2": 1309 | version: 7.1.2 1310 | resolution: "minipass@npm:7.1.2" 1311 | checksum: 10c0/b0fd20bb9fb56e5fa9a8bfac539e8915ae07430a619e4b86ff71f5fc757ef3924b23b2c4230393af1eda647ed3d75739e4e0acb250a6b1eb277cf7f8fe449557 1312 | languageName: node 1313 | linkType: hard 1314 | 1315 | "minizlib@npm:^3.0.1": 1316 | version: 3.0.2 1317 | resolution: "minizlib@npm:3.0.2" 1318 | dependencies: 1319 | minipass: "npm:^7.1.2" 1320 | checksum: 10c0/9f3bd35e41d40d02469cb30470c55ccc21cae0db40e08d1d0b1dff01cc8cc89a6f78e9c5d2b7c844e485ec0a8abc2238111213fdc5b2038e6d1012eacf316f78 1321 | languageName: node 1322 | linkType: hard 1323 | 1324 | "mkdirp@npm:^3.0.1": 1325 | version: 3.0.1 1326 | resolution: "mkdirp@npm:3.0.1" 1327 | bin: 1328 | mkdirp: dist/cjs/src/bin.js 1329 | checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d 1330 | languageName: node 1331 | linkType: hard 1332 | 1333 | "ms@npm:^2.1.3": 1334 | version: 2.1.3 1335 | resolution: "ms@npm:2.1.3" 1336 | checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 1337 | languageName: node 1338 | linkType: hard 1339 | 1340 | "nanoid@npm:^3.3.8": 1341 | version: 3.3.8 1342 | resolution: "nanoid@npm:3.3.8" 1343 | bin: 1344 | nanoid: bin/nanoid.cjs 1345 | checksum: 10c0/4b1bb29f6cfebf3be3bc4ad1f1296fb0a10a3043a79f34fbffe75d1621b4318319211cd420549459018ea3592f0d2f159247a6f874911d6d26eaaadda2478120 1346 | languageName: node 1347 | linkType: hard 1348 | 1349 | "negotiator@npm:^1.0.0": 1350 | version: 1.0.0 1351 | resolution: "negotiator@npm:1.0.0" 1352 | checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b 1353 | languageName: node 1354 | linkType: hard 1355 | 1356 | "node-gyp@npm:latest": 1357 | version: 11.0.0 1358 | resolution: "node-gyp@npm:11.0.0" 1359 | dependencies: 1360 | env-paths: "npm:^2.2.0" 1361 | exponential-backoff: "npm:^3.1.1" 1362 | glob: "npm:^10.3.10" 1363 | graceful-fs: "npm:^4.2.6" 1364 | make-fetch-happen: "npm:^14.0.3" 1365 | nopt: "npm:^8.0.0" 1366 | proc-log: "npm:^5.0.0" 1367 | semver: "npm:^7.3.5" 1368 | tar: "npm:^7.4.3" 1369 | which: "npm:^5.0.0" 1370 | bin: 1371 | node-gyp: bin/node-gyp.js 1372 | checksum: 10c0/a3b885bbee2d271f1def32ba2e30ffcf4562a3db33af06b8b365e053153e2dd2051b9945783c3c8e852d26a0f20f65b251c7e83361623383a99635c0280ee573 1373 | languageName: node 1374 | linkType: hard 1375 | 1376 | "node-releases@npm:^2.0.19": 1377 | version: 2.0.19 1378 | resolution: "node-releases@npm:2.0.19" 1379 | checksum: 10c0/52a0dbd25ccf545892670d1551690fe0facb6a471e15f2cfa1b20142a5b255b3aa254af5f59d6ecb69c2bec7390bc643c43aa63b13bf5e64b6075952e716b1aa 1380 | languageName: node 1381 | linkType: hard 1382 | 1383 | "nopt@npm:^8.0.0": 1384 | version: 8.1.0 1385 | resolution: "nopt@npm:8.1.0" 1386 | dependencies: 1387 | abbrev: "npm:^3.0.0" 1388 | bin: 1389 | nopt: bin/nopt.js 1390 | checksum: 10c0/62e9ea70c7a3eb91d162d2c706b6606c041e4e7b547cbbb48f8b3695af457dd6479904d7ace600856bf923dd8d1ed0696f06195c8c20f02ac87c1da0e1d315ef 1391 | languageName: node 1392 | linkType: hard 1393 | 1394 | "p-map@npm:^7.0.2": 1395 | version: 7.0.3 1396 | resolution: "p-map@npm:7.0.3" 1397 | checksum: 10c0/46091610da2b38ce47bcd1d8b4835a6fa4e832848a6682cf1652bc93915770f4617afc844c10a77d1b3e56d2472bb2d5622353fa3ead01a7f42b04fc8e744a5c 1398 | languageName: node 1399 | linkType: hard 1400 | 1401 | "path-key@npm:^3.1.0": 1402 | version: 3.1.1 1403 | resolution: "path-key@npm:3.1.1" 1404 | checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c 1405 | languageName: node 1406 | linkType: hard 1407 | 1408 | "path-scurry@npm:^1.10.1": 1409 | version: 1.10.1 1410 | resolution: "path-scurry@npm:1.10.1" 1411 | dependencies: 1412 | lru-cache: "npm:^9.1.1 || ^10.0.0" 1413 | minipass: "npm:^5.0.0 || ^6.0.2 || ^7.0.0" 1414 | checksum: 10c0/e5dc78a7348d25eec61ab166317e9e9c7b46818aa2c2b9006c507a6ff48c672d011292d9662527213e558f5652ce0afcc788663a061d8b59ab495681840c0c1e 1415 | languageName: node 1416 | linkType: hard 1417 | 1418 | "picocolors@npm:^1.0.0, picocolors@npm:^1.1.0, picocolors@npm:^1.1.1": 1419 | version: 1.1.1 1420 | resolution: "picocolors@npm:1.1.1" 1421 | checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 1422 | languageName: node 1423 | linkType: hard 1424 | 1425 | "postcss@npm:^8.5.3": 1426 | version: 8.5.3 1427 | resolution: "postcss@npm:8.5.3" 1428 | dependencies: 1429 | nanoid: "npm:^3.3.8" 1430 | picocolors: "npm:^1.1.1" 1431 | source-map-js: "npm:^1.2.1" 1432 | checksum: 10c0/b75510d7b28c3ab728c8733dd01538314a18c52af426f199a3c9177e63eb08602a3938bfb66b62dc01350b9aed62087eabbf229af97a1659eb8d3513cec823b3 1433 | languageName: node 1434 | linkType: hard 1435 | 1436 | "proc-log@npm:^5.0.0": 1437 | version: 5.0.0 1438 | resolution: "proc-log@npm:5.0.0" 1439 | checksum: 10c0/bbe5edb944b0ad63387a1d5b1911ae93e05ce8d0f60de1035b218cdcceedfe39dbd2c697853355b70f1a090f8f58fe90da487c85216bf9671f9499d1a897e9e3 1440 | languageName: node 1441 | linkType: hard 1442 | 1443 | "promise-retry@npm:^2.0.1": 1444 | version: 2.0.1 1445 | resolution: "promise-retry@npm:2.0.1" 1446 | dependencies: 1447 | err-code: "npm:^2.0.2" 1448 | retry: "npm:^0.12.0" 1449 | checksum: 10c0/9c7045a1a2928094b5b9b15336dcd2a7b1c052f674550df63cc3f36cd44028e5080448175b6f6ca32b642de81150f5e7b1a98b728f15cb069f2dd60ac2616b96 1450 | languageName: node 1451 | linkType: hard 1452 | 1453 | "react-dom@npm:^18.2.0": 1454 | version: 18.2.0 1455 | resolution: "react-dom@npm:18.2.0" 1456 | dependencies: 1457 | loose-envify: "npm:^1.1.0" 1458 | scheduler: "npm:^0.23.0" 1459 | peerDependencies: 1460 | react: ^18.2.0 1461 | checksum: 10c0/66dfc5f93e13d0674e78ef41f92ed21dfb80f9c4ac4ac25a4b51046d41d4d2186abc915b897f69d3d0ebbffe6184e7c5876f2af26bfa956f179225d921be713a 1462 | languageName: node 1463 | linkType: hard 1464 | 1465 | "react-recaptcha-v3-sample-page@workspace:.": 1466 | version: 0.0.0-use.local 1467 | resolution: "react-recaptcha-v3-sample-page@workspace:." 1468 | dependencies: 1469 | "@vitejs/plugin-react": "npm:^4.3.4" 1470 | "@wojtekmaj/react-recaptcha-v3": "portal:../packages/react-recaptcha-v3" 1471 | react: "npm:^18.2.0" 1472 | react-dom: "npm:^18.2.0" 1473 | typescript: "npm:^5.0.0" 1474 | vite: "npm:^6.2.4" 1475 | languageName: unknown 1476 | linkType: soft 1477 | 1478 | "react-refresh@npm:^0.14.2": 1479 | version: 0.14.2 1480 | resolution: "react-refresh@npm:0.14.2" 1481 | checksum: 10c0/875b72ef56b147a131e33f2abd6ec059d1989854b3ff438898e4f9310bfcc73acff709445b7ba843318a953cb9424bcc2c05af2b3d80011cee28f25aef3e2ebb 1482 | languageName: node 1483 | linkType: hard 1484 | 1485 | "react@npm:^18.2.0": 1486 | version: 18.2.0 1487 | resolution: "react@npm:18.2.0" 1488 | dependencies: 1489 | loose-envify: "npm:^1.1.0" 1490 | checksum: 10c0/b562d9b569b0cb315e44b48099f7712283d93df36b19a39a67c254c6686479d3980b7f013dc931f4a5a3ae7645eae6386b4aa5eea933baa54ecd0f9acb0902b8 1491 | languageName: node 1492 | linkType: hard 1493 | 1494 | "retry@npm:^0.12.0": 1495 | version: 0.12.0 1496 | resolution: "retry@npm:0.12.0" 1497 | checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe 1498 | languageName: node 1499 | linkType: hard 1500 | 1501 | "rollup@npm:^4.30.1": 1502 | version: 4.34.9 1503 | resolution: "rollup@npm:4.34.9" 1504 | dependencies: 1505 | "@rollup/rollup-android-arm-eabi": "npm:4.34.9" 1506 | "@rollup/rollup-android-arm64": "npm:4.34.9" 1507 | "@rollup/rollup-darwin-arm64": "npm:4.34.9" 1508 | "@rollup/rollup-darwin-x64": "npm:4.34.9" 1509 | "@rollup/rollup-freebsd-arm64": "npm:4.34.9" 1510 | "@rollup/rollup-freebsd-x64": "npm:4.34.9" 1511 | "@rollup/rollup-linux-arm-gnueabihf": "npm:4.34.9" 1512 | "@rollup/rollup-linux-arm-musleabihf": "npm:4.34.9" 1513 | "@rollup/rollup-linux-arm64-gnu": "npm:4.34.9" 1514 | "@rollup/rollup-linux-arm64-musl": "npm:4.34.9" 1515 | "@rollup/rollup-linux-loongarch64-gnu": "npm:4.34.9" 1516 | "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.34.9" 1517 | "@rollup/rollup-linux-riscv64-gnu": "npm:4.34.9" 1518 | "@rollup/rollup-linux-s390x-gnu": "npm:4.34.9" 1519 | "@rollup/rollup-linux-x64-gnu": "npm:4.34.9" 1520 | "@rollup/rollup-linux-x64-musl": "npm:4.34.9" 1521 | "@rollup/rollup-win32-arm64-msvc": "npm:4.34.9" 1522 | "@rollup/rollup-win32-ia32-msvc": "npm:4.34.9" 1523 | "@rollup/rollup-win32-x64-msvc": "npm:4.34.9" 1524 | "@types/estree": "npm:1.0.6" 1525 | fsevents: "npm:~2.3.2" 1526 | dependenciesMeta: 1527 | "@rollup/rollup-android-arm-eabi": 1528 | optional: true 1529 | "@rollup/rollup-android-arm64": 1530 | optional: true 1531 | "@rollup/rollup-darwin-arm64": 1532 | optional: true 1533 | "@rollup/rollup-darwin-x64": 1534 | optional: true 1535 | "@rollup/rollup-freebsd-arm64": 1536 | optional: true 1537 | "@rollup/rollup-freebsd-x64": 1538 | optional: true 1539 | "@rollup/rollup-linux-arm-gnueabihf": 1540 | optional: true 1541 | "@rollup/rollup-linux-arm-musleabihf": 1542 | optional: true 1543 | "@rollup/rollup-linux-arm64-gnu": 1544 | optional: true 1545 | "@rollup/rollup-linux-arm64-musl": 1546 | optional: true 1547 | "@rollup/rollup-linux-loongarch64-gnu": 1548 | optional: true 1549 | "@rollup/rollup-linux-powerpc64le-gnu": 1550 | optional: true 1551 | "@rollup/rollup-linux-riscv64-gnu": 1552 | optional: true 1553 | "@rollup/rollup-linux-s390x-gnu": 1554 | optional: true 1555 | "@rollup/rollup-linux-x64-gnu": 1556 | optional: true 1557 | "@rollup/rollup-linux-x64-musl": 1558 | optional: true 1559 | "@rollup/rollup-win32-arm64-msvc": 1560 | optional: true 1561 | "@rollup/rollup-win32-ia32-msvc": 1562 | optional: true 1563 | "@rollup/rollup-win32-x64-msvc": 1564 | optional: true 1565 | fsevents: 1566 | optional: true 1567 | bin: 1568 | rollup: dist/bin/rollup 1569 | checksum: 10c0/dd0be1f7c4f8a93040026be13ecc39259fb55313db0dac7eafd97a3ac01ab4584e6b1a8afd86b0259dcf391699d5560a678abe6c0729af0aa4f2d5df70f05c8c 1570 | languageName: node 1571 | linkType: hard 1572 | 1573 | "safer-buffer@npm:>= 2.1.2 < 3.0.0": 1574 | version: 2.1.2 1575 | resolution: "safer-buffer@npm:2.1.2" 1576 | checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 1577 | languageName: node 1578 | linkType: hard 1579 | 1580 | "scheduler@npm:^0.23.0": 1581 | version: 0.23.0 1582 | resolution: "scheduler@npm:0.23.0" 1583 | dependencies: 1584 | loose-envify: "npm:^1.1.0" 1585 | checksum: 10c0/b777f7ca0115e6d93e126ac490dbd82642d14983b3079f58f35519d992fa46260be7d6e6cede433a92db70306310c6f5f06e144f0e40c484199e09c1f7be53dd 1586 | languageName: node 1587 | linkType: hard 1588 | 1589 | "semver@npm:^6.3.1": 1590 | version: 6.3.1 1591 | resolution: "semver@npm:6.3.1" 1592 | bin: 1593 | semver: bin/semver.js 1594 | checksum: 10c0/e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d 1595 | languageName: node 1596 | linkType: hard 1597 | 1598 | "semver@npm:^7.3.5": 1599 | version: 7.6.3 1600 | resolution: "semver@npm:7.6.3" 1601 | bin: 1602 | semver: bin/semver.js 1603 | checksum: 10c0/88f33e148b210c153873cb08cfe1e281d518aaa9a666d4d148add6560db5cd3c582f3a08ccb91f38d5f379ead256da9931234ed122057f40bb5766e65e58adaf 1604 | languageName: node 1605 | linkType: hard 1606 | 1607 | "shebang-command@npm:^2.0.0": 1608 | version: 2.0.0 1609 | resolution: "shebang-command@npm:2.0.0" 1610 | dependencies: 1611 | shebang-regex: "npm:^3.0.0" 1612 | checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e 1613 | languageName: node 1614 | linkType: hard 1615 | 1616 | "shebang-regex@npm:^3.0.0": 1617 | version: 3.0.0 1618 | resolution: "shebang-regex@npm:3.0.0" 1619 | checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 1620 | languageName: node 1621 | linkType: hard 1622 | 1623 | "signal-exit@npm:^4.0.1": 1624 | version: 4.1.0 1625 | resolution: "signal-exit@npm:4.1.0" 1626 | checksum: 10c0/41602dce540e46d599edba9d9860193398d135f7ff72cab629db5171516cfae628d21e7bfccde1bbfdf11c48726bc2a6d1a8fb8701125852fbfda7cf19c6aa83 1627 | languageName: node 1628 | linkType: hard 1629 | 1630 | "smart-buffer@npm:^4.2.0": 1631 | version: 4.2.0 1632 | resolution: "smart-buffer@npm:4.2.0" 1633 | checksum: 10c0/a16775323e1404dd43fabafe7460be13a471e021637bc7889468eb45ce6a6b207261f454e4e530a19500cc962c4cc5348583520843b363f4193cee5c00e1e539 1634 | languageName: node 1635 | linkType: hard 1636 | 1637 | "socks-proxy-agent@npm:^8.0.3": 1638 | version: 8.0.5 1639 | resolution: "socks-proxy-agent@npm:8.0.5" 1640 | dependencies: 1641 | agent-base: "npm:^7.1.2" 1642 | debug: "npm:^4.3.4" 1643 | socks: "npm:^2.8.3" 1644 | checksum: 10c0/5d2c6cecba6821389aabf18728325730504bf9bb1d9e342e7987a5d13badd7a98838cc9a55b8ed3cb866ad37cc23e1086f09c4d72d93105ce9dfe76330e9d2a6 1645 | languageName: node 1646 | linkType: hard 1647 | 1648 | "socks@npm:^2.8.3": 1649 | version: 2.8.3 1650 | resolution: "socks@npm:2.8.3" 1651 | dependencies: 1652 | ip-address: "npm:^9.0.5" 1653 | smart-buffer: "npm:^4.2.0" 1654 | checksum: 10c0/d54a52bf9325165770b674a67241143a3d8b4e4c8884560c4e0e078aace2a728dffc7f70150660f51b85797c4e1a3b82f9b7aa25e0a0ceae1a243365da5c51a7 1655 | languageName: node 1656 | linkType: hard 1657 | 1658 | "source-map-js@npm:^1.2.1": 1659 | version: 1.2.1 1660 | resolution: "source-map-js@npm:1.2.1" 1661 | checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf 1662 | languageName: node 1663 | linkType: hard 1664 | 1665 | "sprintf-js@npm:^1.1.3": 1666 | version: 1.1.3 1667 | resolution: "sprintf-js@npm:1.1.3" 1668 | checksum: 10c0/09270dc4f30d479e666aee820eacd9e464215cdff53848b443964202bf4051490538e5dd1b42e1a65cf7296916ca17640aebf63dae9812749c7542ee5f288dec 1669 | languageName: node 1670 | linkType: hard 1671 | 1672 | "ssri@npm:^12.0.0": 1673 | version: 12.0.0 1674 | resolution: "ssri@npm:12.0.0" 1675 | dependencies: 1676 | minipass: "npm:^7.0.3" 1677 | checksum: 10c0/caddd5f544b2006e88fa6b0124d8d7b28208b83c72d7672d5ade44d794525d23b540f3396108c4eb9280dcb7c01f0bef50682f5b4b2c34291f7c5e211fd1417d 1678 | languageName: node 1679 | linkType: hard 1680 | 1681 | "string-width-cjs@npm:string-width@^4.2.0, string-width@npm:^4.1.0": 1682 | version: 4.2.3 1683 | resolution: "string-width@npm:4.2.3" 1684 | dependencies: 1685 | emoji-regex: "npm:^8.0.0" 1686 | is-fullwidth-code-point: "npm:^3.0.0" 1687 | strip-ansi: "npm:^6.0.1" 1688 | checksum: 10c0/1e525e92e5eae0afd7454086eed9c818ee84374bb80328fc41217ae72ff5f065ef1c9d7f72da41de40c75fa8bb3dee63d92373fd492c84260a552c636392a47b 1689 | languageName: node 1690 | linkType: hard 1691 | 1692 | "string-width@npm:^5.0.1, string-width@npm:^5.1.2": 1693 | version: 5.1.2 1694 | resolution: "string-width@npm:5.1.2" 1695 | dependencies: 1696 | eastasianwidth: "npm:^0.2.0" 1697 | emoji-regex: "npm:^9.2.2" 1698 | strip-ansi: "npm:^7.0.1" 1699 | checksum: 10c0/ab9c4264443d35b8b923cbdd513a089a60de339216d3b0ed3be3ba57d6880e1a192b70ae17225f764d7adbf5994e9bb8df253a944736c15a0240eff553c678ca 1700 | languageName: node 1701 | linkType: hard 1702 | 1703 | "strip-ansi-cjs@npm:strip-ansi@^6.0.1, strip-ansi@npm:^6.0.0, strip-ansi@npm:^6.0.1": 1704 | version: 6.0.1 1705 | resolution: "strip-ansi@npm:6.0.1" 1706 | dependencies: 1707 | ansi-regex: "npm:^5.0.1" 1708 | checksum: 10c0/1ae5f212a126fe5b167707f716942490e3933085a5ff6c008ab97ab2f272c8025d3aa218b7bd6ab25729ca20cc81cddb252102f8751e13482a5199e873680952 1709 | languageName: node 1710 | linkType: hard 1711 | 1712 | "strip-ansi@npm:^7.0.1": 1713 | version: 7.1.0 1714 | resolution: "strip-ansi@npm:7.1.0" 1715 | dependencies: 1716 | ansi-regex: "npm:^6.0.1" 1717 | checksum: 10c0/a198c3762e8832505328cbf9e8c8381de14a4fa50a4f9b2160138158ea88c0f5549fb50cb13c651c3088f47e63a108b34622ec18c0499b6c8c3a5ddf6b305ac4 1718 | languageName: node 1719 | linkType: hard 1720 | 1721 | "tar@npm:^7.4.3": 1722 | version: 7.4.3 1723 | resolution: "tar@npm:7.4.3" 1724 | dependencies: 1725 | "@isaacs/fs-minipass": "npm:^4.0.0" 1726 | chownr: "npm:^3.0.0" 1727 | minipass: "npm:^7.1.2" 1728 | minizlib: "npm:^3.0.1" 1729 | mkdirp: "npm:^3.0.1" 1730 | yallist: "npm:^5.0.0" 1731 | checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d 1732 | languageName: node 1733 | linkType: hard 1734 | 1735 | "typescript@npm:^5.0.0": 1736 | version: 5.0.4 1737 | resolution: "typescript@npm:5.0.4" 1738 | bin: 1739 | tsc: bin/tsc 1740 | tsserver: bin/tsserver 1741 | checksum: 10c0/2f5bd1cead194905957cb34e220b1d6ff1662399adef8ec1864f74620922d860ee35b6e50eafb3b636ea6fd437195e454e1146cb630a4236b5095ed7617395c2 1742 | languageName: node 1743 | linkType: hard 1744 | 1745 | "typescript@patch:typescript@npm%3A^5.0.0#optional!builtin": 1746 | version: 5.0.4 1747 | resolution: "typescript@patch:typescript@npm%3A5.0.4#optional!builtin::version=5.0.4&hash=b5f058" 1748 | bin: 1749 | tsc: bin/tsc 1750 | tsserver: bin/tsserver 1751 | checksum: 10c0/c3f7b80577bddf6fab202a7925131ac733bfc414aec298c2404afcddc7a6f242cfa8395cf2d48192265052e11a7577c27f6e5fac8d8fe6a6602023c83d6b3292 1752 | languageName: node 1753 | linkType: hard 1754 | 1755 | "unique-filename@npm:^4.0.0": 1756 | version: 4.0.0 1757 | resolution: "unique-filename@npm:4.0.0" 1758 | dependencies: 1759 | unique-slug: "npm:^5.0.0" 1760 | checksum: 10c0/38ae681cceb1408ea0587b6b01e29b00eee3c84baee1e41fd5c16b9ed443b80fba90c40e0ba69627e30855570a34ba8b06702d4a35035d4b5e198bf5a64c9ddc 1761 | languageName: node 1762 | linkType: hard 1763 | 1764 | "unique-slug@npm:^5.0.0": 1765 | version: 5.0.0 1766 | resolution: "unique-slug@npm:5.0.0" 1767 | dependencies: 1768 | imurmurhash: "npm:^0.1.4" 1769 | checksum: 10c0/d324c5a44887bd7e105ce800fcf7533d43f29c48757ac410afd42975de82cc38ea2035c0483f4de82d186691bf3208ef35c644f73aa2b1b20b8e651be5afd293 1770 | languageName: node 1771 | linkType: hard 1772 | 1773 | "update-browserslist-db@npm:^1.1.1": 1774 | version: 1.1.1 1775 | resolution: "update-browserslist-db@npm:1.1.1" 1776 | dependencies: 1777 | escalade: "npm:^3.2.0" 1778 | picocolors: "npm:^1.1.0" 1779 | peerDependencies: 1780 | browserslist: ">= 4.21.0" 1781 | bin: 1782 | update-browserslist-db: cli.js 1783 | checksum: 10c0/536a2979adda2b4be81b07e311bd2f3ad5e978690987956bc5f514130ad50cac87cd22c710b686d79731e00fbee8ef43efe5fcd72baa241045209195d43dcc80 1784 | languageName: node 1785 | linkType: hard 1786 | 1787 | "vite@npm:^6.2.4": 1788 | version: 6.2.4 1789 | resolution: "vite@npm:6.2.4" 1790 | dependencies: 1791 | esbuild: "npm:^0.25.0" 1792 | fsevents: "npm:~2.3.3" 1793 | postcss: "npm:^8.5.3" 1794 | rollup: "npm:^4.30.1" 1795 | peerDependencies: 1796 | "@types/node": ^18.0.0 || ^20.0.0 || >=22.0.0 1797 | jiti: ">=1.21.0" 1798 | less: "*" 1799 | lightningcss: ^1.21.0 1800 | sass: "*" 1801 | sass-embedded: "*" 1802 | stylus: "*" 1803 | sugarss: "*" 1804 | terser: ^5.16.0 1805 | tsx: ^4.8.1 1806 | yaml: ^2.4.2 1807 | dependenciesMeta: 1808 | fsevents: 1809 | optional: true 1810 | peerDependenciesMeta: 1811 | "@types/node": 1812 | optional: true 1813 | jiti: 1814 | optional: true 1815 | less: 1816 | optional: true 1817 | lightningcss: 1818 | optional: true 1819 | sass: 1820 | optional: true 1821 | sass-embedded: 1822 | optional: true 1823 | stylus: 1824 | optional: true 1825 | sugarss: 1826 | optional: true 1827 | terser: 1828 | optional: true 1829 | tsx: 1830 | optional: true 1831 | yaml: 1832 | optional: true 1833 | bin: 1834 | vite: bin/vite.js 1835 | checksum: 10c0/5a011ee5cce91de023a22564a314f04bf64d0d02b420d92c3d539d10257448d60e98e52b491404656426fba4a50dc25f107282540d7388fc5303dc441280155e 1836 | languageName: node 1837 | linkType: hard 1838 | 1839 | "warning@npm:^4.0.0": 1840 | version: 4.0.3 1841 | resolution: "warning@npm:4.0.3" 1842 | dependencies: 1843 | loose-envify: "npm:^1.0.0" 1844 | checksum: 10c0/aebab445129f3e104c271f1637fa38e55eb25f968593e3825bd2f7a12bd58dc3738bb70dc8ec85826621d80b4acfed5a29ebc9da17397c6125864d72301b937e 1845 | languageName: node 1846 | linkType: hard 1847 | 1848 | "which@npm:^2.0.1": 1849 | version: 2.0.2 1850 | resolution: "which@npm:2.0.2" 1851 | dependencies: 1852 | isexe: "npm:^2.0.0" 1853 | bin: 1854 | node-which: ./bin/node-which 1855 | checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f 1856 | languageName: node 1857 | linkType: hard 1858 | 1859 | "which@npm:^5.0.0": 1860 | version: 5.0.0 1861 | resolution: "which@npm:5.0.0" 1862 | dependencies: 1863 | isexe: "npm:^3.1.1" 1864 | bin: 1865 | node-which: bin/which.js 1866 | checksum: 10c0/e556e4cd8b7dbf5df52408c9a9dd5ac6518c8c5267c8953f5b0564073c66ed5bf9503b14d876d0e9c7844d4db9725fb0dcf45d6e911e17e26ab363dc3965ae7b 1867 | languageName: node 1868 | linkType: hard 1869 | 1870 | "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": 1871 | version: 7.0.0 1872 | resolution: "wrap-ansi@npm:7.0.0" 1873 | dependencies: 1874 | ansi-styles: "npm:^4.0.0" 1875 | string-width: "npm:^4.1.0" 1876 | strip-ansi: "npm:^6.0.0" 1877 | checksum: 10c0/d15fc12c11e4cbc4044a552129ebc75ee3f57aa9c1958373a4db0292d72282f54373b536103987a4a7594db1ef6a4f10acf92978f79b98c49306a4b58c77d4da 1878 | languageName: node 1879 | linkType: hard 1880 | 1881 | "wrap-ansi@npm:^8.1.0": 1882 | version: 8.1.0 1883 | resolution: "wrap-ansi@npm:8.1.0" 1884 | dependencies: 1885 | ansi-styles: "npm:^6.1.0" 1886 | string-width: "npm:^5.0.1" 1887 | strip-ansi: "npm:^7.0.1" 1888 | checksum: 10c0/138ff58a41d2f877eae87e3282c0630fc2789012fc1af4d6bd626eeb9a2f9a65ca92005e6e69a75c7b85a68479fe7443c7dbe1eb8fbaa681a4491364b7c55c60 1889 | languageName: node 1890 | linkType: hard 1891 | 1892 | "yallist@npm:^3.0.2": 1893 | version: 3.1.1 1894 | resolution: "yallist@npm:3.1.1" 1895 | checksum: 10c0/c66a5c46bc89af1625476f7f0f2ec3653c1a1791d2f9407cfb4c2ba812a1e1c9941416d71ba9719876530e3340a99925f697142989371b72d93b9ee628afd8c1 1896 | languageName: node 1897 | linkType: hard 1898 | 1899 | "yallist@npm:^4.0.0": 1900 | version: 4.0.0 1901 | resolution: "yallist@npm:4.0.0" 1902 | checksum: 10c0/2286b5e8dbfe22204ab66e2ef5cc9bbb1e55dfc873bbe0d568aa943eb255d131890dfd5bf243637273d31119b870f49c18fcde2c6ffbb7a7a092b870dc90625a 1903 | languageName: node 1904 | linkType: hard 1905 | 1906 | "yallist@npm:^5.0.0": 1907 | version: 5.0.0 1908 | resolution: "yallist@npm:5.0.0" 1909 | checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 1910 | languageName: node 1911 | linkType: hard 1912 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | -------------------------------------------------------------------------------- /test/RecaptchaOptions.tsx: -------------------------------------------------------------------------------- 1 | type OptionsProps = { 2 | useRecaptchaNet: boolean; 3 | setUseRecaptchaNet: (value: boolean) => void; 4 | useRecaptchaEnterprise: boolean; 5 | setUseRecaptchaEnterprise: (value: boolean) => void; 6 | reCaptchaKey: string; 7 | setRecaptchaKey: (value: string) => void; 8 | }; 9 | 10 | export default function RecaptchaOptions({ 11 | useRecaptchaNet, 12 | setUseRecaptchaNet, 13 | useRecaptchaEnterprise, 14 | setUseRecaptchaEnterprise, 15 | reCaptchaKey, 16 | setRecaptchaKey, 17 | }: OptionsProps) { 18 | function onUseRecaptchaNetChange(event: React.ChangeEvent) { 19 | setUseRecaptchaNet(event.target.checked); 20 | } 21 | 22 | function onUseRecaptchaEnterpriseChange(event: React.ChangeEvent) { 23 | setUseRecaptchaEnterprise(event.target.checked); 24 | } 25 | 26 | function onRecaptchaKeyChange(event: React.ChangeEvent) { 27 | setRecaptchaKey(event.target.value); 28 | } 29 | 30 | return ( 31 |
32 | reCAPTCHA options 33 | 34 |
35 | 36 | 37 |
38 | 39 |
40 | 45 | 46 |
47 | 48 |
49 | 50 | 51 |
52 |
53 | ); 54 | } 55 | -------------------------------------------------------------------------------- /test/Test.css: -------------------------------------------------------------------------------- 1 | body { 2 | margin: 0; 3 | font-family: Segoe UI, Tahoma, sans-serif; 4 | } 5 | 6 | .Test header { 7 | background-color: #323639; 8 | box-shadow: 0 0 8px rgba(0, 0, 0, 0.5); 9 | padding: 20px; 10 | color: white; 11 | } 12 | 13 | .Test header h1 { 14 | font-size: inherit; 15 | margin: 0; 16 | } 17 | 18 | .Test__container { 19 | display: flex; 20 | flex-direction: row; 21 | flex-wrap: wrap; 22 | align-items: flex-start; 23 | margin: 10px 0; 24 | padding: 10px; 25 | } 26 | 27 | .Test__container > * > * { 28 | margin: 10px; 29 | } 30 | 31 | .Test__container__options { 32 | display: flex; 33 | flex-basis: 400px; 34 | flex-grow: 1; 35 | flex-wrap: wrap; 36 | margin: 0; 37 | } 38 | 39 | .Test__container__options input, 40 | .Test__container__options button { 41 | font: inherit; 42 | } 43 | 44 | .Test__container__options fieldset { 45 | border: 1px solid black; 46 | flex-grow: 1; 47 | position: relative; 48 | top: -10px; 49 | } 50 | 51 | .Test__container__options fieldset legend { 52 | font-weight: 600; 53 | } 54 | 55 | .Test__container__options fieldset legend + * { 56 | margin-top: 0 !important; 57 | } 58 | 59 | .Test__container__options fieldset label { 60 | font-weight: 600; 61 | display: block; 62 | } 63 | 64 | .Test__container__options fieldset label:not(:first-of-type) { 65 | margin-top: 1em; 66 | } 67 | 68 | .Test__container__options fieldset input[type='checkbox'] + label, 69 | .Test__container__options fieldset input[type='radio'] + label { 70 | font-weight: normal; 71 | display: inline-block; 72 | margin: 0; 73 | } 74 | 75 | .Test__container__options fieldset form:not(:first-child), 76 | .Test__container__options fieldset div:not(:first-child) { 77 | margin-top: 1em; 78 | } 79 | 80 | .Test__container__options fieldset form:not(:last-child), 81 | .Test__container__options fieldset div:not(:last-child) { 82 | margin-bottom: 1em; 83 | } 84 | 85 | .Test__container__content { 86 | display: flex; 87 | max-width: 100%; 88 | flex-basis: 420px; 89 | flex-direction: column; 90 | flex-grow: 100; 91 | align-items: stretch; 92 | } 93 | 94 | .Test__container__content__token { 95 | display: block; 96 | max-width: 200px; 97 | white-space: nowrap; 98 | overflow: hidden; 99 | text-overflow: ellipsis; 100 | } 101 | -------------------------------------------------------------------------------- /test/Test.tsx: -------------------------------------------------------------------------------- 1 | import { useId, useState } from 'react'; 2 | import { ReCaptchaProvider, ReCaptcha } from '@wojtekmaj/react-recaptcha-v3'; 3 | 4 | import RecaptchaOptions from './RecaptchaOptions.js'; 5 | import VisibilityOptions from './VisibilityOptions.js'; 6 | 7 | import './Test.css'; 8 | 9 | function onLoadCallback() { 10 | console.log('reCAPTCHA loaded'); 11 | } 12 | 13 | const onLoadCallbackName = 'onLoadCallback'; 14 | 15 | // @ts-ignore 16 | window[onLoadCallbackName] = onLoadCallback; 17 | 18 | const scriptProps = { onLoadCallbackName }; 19 | 20 | export default function Test() { 21 | const [useRecaptchaNet, setUseRecaptchaNet] = useState(false); 22 | const [useRecaptchaEnterprise, setUseRecaptchaEnterprise] = useState(true); 23 | const [reCaptchaKey, setRecaptchaKey] = useState(''); 24 | const [showInstance1, setShowInstance1Internal] = useState(false); 25 | const [showInstance2, setShowInstance2Internal] = useState(false); 26 | const [showInstance3, setShowInstance3Internal] = useState(false); 27 | const [showInstance4, setShowInstance4Internal] = useState(false); 28 | 29 | const containerId2 = useId(); 30 | const containerId3 = useId(); 31 | 32 | const [token, setToken] = useState(''); 33 | const [token2, setToken2] = useState(''); 34 | const [token3, setToken3] = useState(''); 35 | const [token4, setToken4] = useState(''); 36 | 37 | function setShowInstance1(value: boolean) { 38 | setShowInstance1Internal(value); 39 | if (!value) { 40 | setToken(''); 41 | } 42 | } 43 | 44 | function setShowInstance2(value: boolean) { 45 | setShowInstance2Internal(value); 46 | if (!value) { 47 | setToken2(''); 48 | } 49 | } 50 | 51 | function setShowInstance3(value: boolean) { 52 | setShowInstance3Internal(value); 53 | if (!value) { 54 | setToken3(''); 55 | } 56 | } 57 | 58 | function setShowInstance4(value: boolean) { 59 | setShowInstance4Internal(value); 60 | if (!value) { 61 | setToken4(''); 62 | } 63 | } 64 | 65 | return ( 66 |
67 |
68 |

@wojtekmaj/react-recaptcha-v3 test page

69 |
70 |
71 | 91 |
92 | {showInstance1 ? ( 93 | <> 94 |

Instance 1

95 | 96 |
97 |
98 | {token} 99 | 100 |
101 |
102 |
103 | 104 | ) : null} 105 | {showInstance2 ? ( 106 | <> 107 |

Instance 2

108 | 117 |
118 |
119 |
120 | 121 | {token2} 122 |
123 | 124 | 125 | 126 | ) : null} 127 | {showInstance3 ? ( 128 | <> 129 |

Instance 3

130 | 140 |
141 |
142 |
143 | 144 | {token3} 145 |
146 | 147 | 148 | 149 | ) : null} 150 | {showInstance4 ? ( 151 | <> 152 |

Instance 4

153 | 154 |
155 |
156 | 157 | {token4} 158 |
159 |
160 |
161 | 162 | ) : null} 163 |
164 |
165 |
166 | ); 167 | } 168 | -------------------------------------------------------------------------------- /test/VisibilityOptions.tsx: -------------------------------------------------------------------------------- 1 | type VisibilityOptionsProps = { 2 | showInstance1: boolean; 3 | setShowInstance1: (value: boolean) => void; 4 | showInstance2: boolean; 5 | setShowInstance2: (value: boolean) => void; 6 | showInstance3: boolean; 7 | setShowInstance3: (value: boolean) => void; 8 | showInstance4: boolean; 9 | setShowInstance4: (value: boolean) => void; 10 | }; 11 | 12 | export default function VisibilityOptions({ 13 | showInstance1, 14 | setShowInstance1, 15 | showInstance2, 16 | setShowInstance2, 17 | showInstance3, 18 | setShowInstance3, 19 | showInstance4, 20 | setShowInstance4, 21 | }: VisibilityOptionsProps) { 22 | function onShowInstance1Change(event: React.ChangeEvent) { 23 | setShowInstance1(event.target.checked); 24 | } 25 | 26 | function onShowInstance2Change(event: React.ChangeEvent) { 27 | setShowInstance2(event.target.checked); 28 | } 29 | 30 | function onShowInstance3Change(event: React.ChangeEvent) { 31 | setShowInstance3(event.target.checked); 32 | } 33 | 34 | function onShowInstance4Change(event: React.ChangeEvent) { 35 | setShowInstance4(event.target.checked); 36 | } 37 | 38 | return ( 39 |
40 | Visibility options 41 | 42 |
43 | 49 | (default badge) 50 |
51 | 52 |
53 | 59 | (inline badge) 60 |
61 | 62 |
63 | 69 | {' '} 70 | (inline badge, too; hidden badge; use to test multiple instances) 71 |
72 | 73 |
74 | 80 | {' '} 81 | (different settings; should crash unless 1 and 2 are hidden) 82 |
83 |
84 | ); 85 | } 86 | -------------------------------------------------------------------------------- /test/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | @wojtekmaj/react-recaptcha-v3 test page 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /test/index.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from 'react'; 2 | import { createRoot } from 'react-dom/client'; 3 | 4 | import Test from './Test.js'; 5 | 6 | const root = document.getElementById('root'); 7 | 8 | if (!root) { 9 | throw new Error('Could not find root element'); 10 | } 11 | 12 | createRoot(root).render( 13 | 14 | , 15 | , 16 | ); 17 | -------------------------------------------------------------------------------- /test/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "test", 3 | "version": "1.0.0", 4 | "description": "A test page for React-reCAPTCHA-v3.", 5 | "private": true, 6 | "type": "module", 7 | "scripts": { 8 | "build": "vite build", 9 | "dev": "vite", 10 | "format": "biome format", 11 | "lint": "biome lint", 12 | "preview": "vite preview", 13 | "test": "yarn lint && yarn tsc && yarn format", 14 | "tsc": "tsc" 15 | }, 16 | "author": { 17 | "name": "Wojciech Maj", 18 | "email": "kontakt@wojtekmaj.pl" 19 | }, 20 | "license": "MIT", 21 | "dependencies": { 22 | "@wojtekmaj/react-recaptcha-v3": "workspace:packages/react-recaptcha-v3", 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0" 25 | }, 26 | "devDependencies": { 27 | "@biomejs/biome": "1.9.0", 28 | "@types/react": "*", 29 | "@vitejs/plugin-react": "^4.3.4", 30 | "typescript": "^5.5.2", 31 | "vite": "^6.2.4" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "isolatedModules": true, 4 | "jsx": "react-jsx", 5 | "module": "preserve", 6 | "moduleDetection": "force", 7 | "noEmit": true, 8 | "noUncheckedIndexedAccess": true, 9 | "skipLibCheck": true, 10 | "strict": true, 11 | "target": "esnext", 12 | "verbatimModuleSyntax": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /test/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'vite'; 2 | import react from '@vitejs/plugin-react'; 3 | 4 | export default defineConfig({ 5 | base: './', 6 | plugins: [react()], 7 | }); 8 | --------------------------------------------------------------------------------