From a7c0ab9735cd9e423db2f413044ac60bca393188 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 8 Oct 2025 13:33:01 -0300 Subject: [PATCH 1/6] feat: integrate testing framework and add test cases for SuperDocESign component - Added Vitest as the testing framework and configured test scripts in package.json. - Implemented test cases for the SuperDocESign component, covering rendering, state management, and audit trail functionality. - Updated Vite configuration to support testing with jsdom environment. - Enhanced GitHub workflows to include testing in PR validation and release processes. --- .github/workflows/pr-validation.yml | 1 + .github/workflows/release-package.yml | 1 + package.json | 9 +- pnpm-lock.yaml | 663 +++++++++++++++++++++- src/__tests__/SuperDocESign.test.tsx | 534 ++++++++++++++++++ src/defaults/SignatureInput.tsx | 5 +- src/index.tsx | 768 +++++++++++++------------- src/test/setup.ts | 94 ++++ src/types.ts | 6 + tsconfig.json | 3 +- vite.config.ts | 7 + 11 files changed, 1713 insertions(+), 378 deletions(-) create mode 100644 src/__tests__/SuperDocESign.test.tsx create mode 100644 src/test/setup.ts diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index e2b795b..dba754e 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -43,3 +43,4 @@ jobs: - run: pnpm lint - run: pnpm build + - run: pnpm test diff --git a/.github/workflows/release-package.yml b/.github/workflows/release-package.yml index 900a797..b2e38cd 100644 --- a/.github/workflows/release-package.yml +++ b/.github/workflows/release-package.yml @@ -41,6 +41,7 @@ jobs: - run: pnpm install --frozen-lockfile - run: pnpm build + - run: pnpm test - name: Release id: release diff --git a/package.json b/package.json index 0d98375..4031a6a 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,8 @@ "type-check": "tsc --noEmit", "lint": "eslint src --ext .ts,.tsx", "format": "prettier --write \"src/**/*.{ts,tsx}\"", + "test": "vitest", + "test:watch": "vitest --watch", "prepare": "husky", "release": "semantic-release", "check:all": "pnpm run type-check && pnpm run lint && pnpm run format" @@ -58,6 +60,9 @@ "@eslint/js": "^9.36.0", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.0", + "@testing-library/user-event": "^14.6.1", "@types/node": "^24.5.2", "@types/react": "^19.2.2", "@types/react-dom": "^19.2.1", @@ -66,6 +71,7 @@ "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^6.1.0", "husky": "^9.1.7", + "jsdom": "^27.0.0", "prettier": "^3.6.2", "react": "^19.2.0", "react-dom": "^19.2.0", @@ -73,7 +79,8 @@ "typescript": "^5.9.2", "typescript-eslint": "^8.44.1", "vite": "^7.1.7", - "vite-plugin-dts": "^4.5.4" + "vite-plugin-dts": "^4.5.4", + "vitest": "^3.2.4" }, "publishConfig": { "access": "public" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 28a7b65..3fbe5ca 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: superdoc: specifier: ^0.22.0 - version: 0.22.3(@hocuspocus/provider@2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(canvas@2.11.2)(pdfjs-dist@4.6.82)(typescript@5.9.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.2)(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(yjs@13.6.19) + version: 0.22.3(@hocuspocus/provider@2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(pdfjs-dist@4.6.82)(typescript@5.9.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.2)(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(yjs@13.6.19) devDependencies: '@eslint/js': specifier: ^9.36.0 @@ -21,6 +21,15 @@ importers: '@semantic-release/git': specifier: ^10.0.1 version: 10.0.1(semantic-release@24.2.9(typescript@5.9.3)) + '@testing-library/jest-dom': + specifier: ^6.9.1 + version: 6.9.1 + '@testing-library/react': + specifier: ^16.3.0 + version: 16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0) + '@testing-library/user-event': + specifier: ^14.6.1 + version: 14.6.1(@testing-library/dom@10.4.1) '@types/node': specifier: ^24.5.2 version: 24.7.0 @@ -45,6 +54,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + jsdom: + specifier: ^27.0.0 + version: 27.0.0(postcss@8.5.6) prettier: specifier: ^3.6.2 version: 3.6.2 @@ -69,12 +81,27 @@ importers: vite-plugin-dts: specifier: ^4.5.4 version: 4.5.4(@types/node@24.7.0)(rollup@4.52.4)(typescript@5.9.3)(vite@7.1.9(@types/node@24.7.0)) + vitest: + specifier: ^3.2.4 + version: 3.2.4(@types/node@24.7.0)(jsdom@27.0.0(postcss@8.5.6)) packages: + '@adobe/css-tools@4.4.4': + resolution: {integrity: sha512-Elp+iwUx5rN5+Y8xLt5/GRoG20WGoDCQ/1Fb+1LiGtvwbDavuSk0jhD/eZdckHAuzcDzccnkv+rEjyWfRx18gg==} + '@asamuzakjp/css-color@3.2.0': resolution: {integrity: sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==} + '@asamuzakjp/css-color@4.0.5': + resolution: {integrity: sha512-lMrXidNhPGsDjytDy11Vwlb6OIGrT3CmLg3VWNFyWkLWtijKl7xjvForlh8vuj0SHGjgl4qZEQzUmYTeQA2JFQ==} + + '@asamuzakjp/dom-selector@6.6.1': + resolution: {integrity: sha512-8QT9pokVe1fUt1C8IrJketaeFOdRfTOS96DL3EBjE8CRZm3eHnwMlQe2NPoOSEYPwJ5Q25uYoX1+m9044l3ysQ==} + + '@asamuzakjp/nwsapi@2.3.9': + resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -146,6 +173,10 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/runtime@7.28.4': + resolution: {integrity: sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==} + engines: {node: '>=6.9.0'} + '@babel/template@7.27.2': resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} engines: {node: '>=6.9.0'} @@ -196,6 +227,12 @@ packages: peerDependencies: '@csstools/css-tokenizer': ^3.0.4 + '@csstools/css-syntax-patches-for-csstree@1.0.14': + resolution: {integrity: sha512-zSlIxa20WvMojjpCSy8WrNpcZ61RqfTfX3XTaOeVlGJrt/8HF3YbzgFZa01yTbT4GWQLwfTcC3EB8i3XnB647Q==} + engines: {node: '>=18'} + peerDependencies: + postcss: ^8.4 + '@csstools/css-tokenizer@3.0.4': resolution: {integrity: sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==} engines: {node: '>=18'} @@ -748,9 +785,41 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + '@testing-library/dom@10.4.1': + resolution: {integrity: sha512-o4PXJQidqJl82ckFaXUeoAW+XysPLauYI43Abki5hABd853iMhitooc6znOnczgbTYmEP6U6/y1ZyKAIsvMKGg==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.9.1': + resolution: {integrity: sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + + '@testing-library/react@16.3.0': + resolution: {integrity: sha512-kFSyxiEDwv1WLl2fgsq6pPBbw5aWKrsY2/noi1Id0TK0UParSF62oFQFGHXIyaG4pp2tEub/Zlel+fjjZILDsw==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 || ^19.0.0 + '@types/react-dom': ^18.0.0 || ^19.0.0 + react: ^18.0.0 || ^19.0.0 + react-dom: ^18.0.0 || ^19.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@testing-library/user-event@14.6.1': + resolution: {integrity: sha512-vq7fv0rnt+QTXgPxr5Hjc210p6YKq2kmdziLgnsZGgLJ9e6VAShx1pACLuRjd/AS/sr7phAR58OIIpf0LlmQNw==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + '@types/babel__core@7.20.5': resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} @@ -763,6 +832,12 @@ packages: '@types/babel__traverse@7.28.0': resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==} + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + + '@types/deep-eql@4.0.2': + resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} + '@types/estree@1.0.8': resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==} @@ -867,6 +942,35 @@ packages: peerDependencies: vite: ^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 + '@vitest/expect@3.2.4': + resolution: {integrity: sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==} + + '@vitest/mocker@3.2.4': + resolution: {integrity: sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==} + peerDependencies: + msw: ^2.4.9 + vite: ^5.0.0 || ^6.0.0 || ^7.0.0-0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + + '@vitest/pretty-format@3.2.4': + resolution: {integrity: sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==} + + '@vitest/runner@3.2.4': + resolution: {integrity: sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==} + + '@vitest/snapshot@3.2.4': + resolution: {integrity: sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==} + + '@vitest/spy@3.2.4': + resolution: {integrity: sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==} + + '@vitest/utils@3.2.4': + resolution: {integrity: sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==} + '@volar/language-core@2.4.23': resolution: {integrity: sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==} @@ -996,6 +1100,10 @@ packages: resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} engines: {node: '>=8'} + ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -1016,6 +1124,13 @@ packages: argv-formatter@1.0.0: resolution: {integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==} + aria-query@5.3.0: + resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} + + aria-query@5.3.2: + resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} + engines: {node: '>= 0.4'} + array-buffer-byte-length@1.0.2: resolution: {integrity: sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==} engines: {node: '>= 0.4'} @@ -1051,6 +1166,10 @@ packages: resolution: {integrity: sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==} engines: {node: '>= 0.4'} + assertion-error@2.0.1: + resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==} + engines: {node: '>=12'} + async-function@1.0.0: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} @@ -1075,6 +1194,9 @@ packages: before-after-hook@4.0.0: resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==} + bidi-js@1.0.3: + resolution: {integrity: sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==} + bottleneck@2.19.5: resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} @@ -1097,6 +1219,10 @@ packages: resolution: {integrity: sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==} engines: {node: '>=8.0.0'} + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + call-bind-apply-helpers@1.0.2: resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} engines: {node: '>= 0.4'} @@ -1120,6 +1246,10 @@ packages: resolution: {integrity: sha512-ItanGBMrmRV7Py2Z+Xhs7cT+FNt5K0vPL4p9EZ/UX/Mu7hFbkxSjKF2KVtPwX7UYWp7dRKnrTvReflgrItJbdw==} engines: {node: '>=6'} + chai@5.3.3: + resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==} + engines: {node: '>=18'} + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1136,6 +1266,10 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + check-error@2.1.1: + resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==} + engines: {node: '>= 16'} + chownr@2.0.0: resolution: {integrity: sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==} engines: {node: '>=10'} @@ -1257,10 +1391,21 @@ packages: css-render@0.15.14: resolution: {integrity: sha512-9nF4PdUle+5ta4W5SyZdLCCmFd37uVimSjg1evcTqKJCyvCEEj12WKzOSBNak6r4im4J4iYXKH1OWpUV5LBYFg==} + css-tree@3.1.0: + resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} + engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} + + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + cssstyle@4.6.0: resolution: {integrity: sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==} engines: {node: '>=18'} + cssstyle@5.3.1: + resolution: {integrity: sha512-g5PC9Aiph9eiczFpcgUhd9S4UUO3F+LHGRIi5NUMZ+4xtoIYbHNZwZnWA2JsFGe8OU8nl4WyaEFiZuGuxlutJQ==} + engines: {node: '>=20'} + csstype@3.0.11: resolution: {integrity: sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==} @@ -1271,6 +1416,10 @@ packages: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} + data-urls@6.0.0: + resolution: {integrity: sha512-BnBS08aLUM+DKamupXs3w2tJJoqU+AkaE/+6vQxi/G/DPmIZFJJp9Dkb1kM03AZx8ADehDUZgsNxju3mPXZYIA==} + engines: {node: '>=20'} + data-view-buffer@1.0.2: resolution: {integrity: sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==} engines: {node: '>= 0.4'} @@ -1310,6 +1459,10 @@ packages: resolution: {integrity: sha512-jOSne2qbyE+/r8G1VU+G/82LBs2Fs4LAsTiLSHOCOMZQl2OKZ6i8i4IyHemTe+/yIXOtTcRQMzPcgyhoFlqPkw==} engines: {node: '>=8'} + deep-eql@5.0.2: + resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==} + engines: {node: '>=6'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -1332,6 +1485,10 @@ packages: delegates@1.0.0: resolution: {integrity: sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==} + dequal@2.0.3: + resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} + engines: {node: '>=6'} + detect-libc@2.1.2: resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==} engines: {node: '>=8'} @@ -1344,6 +1501,12 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + dot-prop@5.3.0: resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} engines: {node: '>=8'} @@ -1403,6 +1566,9 @@ packages: resolution: {integrity: sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==} engines: {node: '>= 0.4'} + es-module-lexer@1.7.0: + resolution: {integrity: sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==} + es-object-atoms@1.1.1: resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} engines: {node: '>= 0.4'} @@ -1493,6 +1659,9 @@ packages: estree-walker@2.0.2: resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} + estree-walker@3.0.3: + resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} + esutils@2.0.3: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} @@ -1515,6 +1684,10 @@ packages: resolution: {integrity: sha512-jpWzZ1ZhwUmeWRhS7Qv3mhpOhLfwI+uAX4e5fOcXqwMR7EcJ0pj2kV1CVzHVMX/LphnKWD3LObjZCoJ71lKpHw==} engines: {node: ^18.19.0 || >=20.5.0} + expect-type@1.2.2: + resolution: {integrity: sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==} + engines: {node: '>=12.0.0'} + exsolve@1.0.7: resolution: {integrity: sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw==} @@ -2039,6 +2212,9 @@ packages: js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-tokens@9.0.1: + resolution: {integrity: sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==} + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2052,6 +2228,15 @@ packages: canvas: optional: true + jsdom@27.0.0: + resolution: {integrity: sha512-lIHeR1qlIRrIN5VMccd8tI2Sgw6ieYXSVktcSHaNe3Z5nE/tcPQYQWOq00wxMvYOsz+73eAkNenVvmPC6bba9A==} + engines: {node: '>=20'} + peerDependencies: + canvas: ^3.0.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.1.0: resolution: {integrity: sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==} engines: {node: '>=6'} @@ -2152,9 +2337,16 @@ packages: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true + loupe@3.2.1: + resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==} + lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@11.2.2: + resolution: {integrity: sha512-F9ODfyqML2coTIsQpSkRHnLSZMtkU8Q+mSfcaIyKwy58u+8k5nvAYeiNhsyMARvzNcXJ9QfWVrcPsC9e9rAxtg==} + engines: {node: 20 || >=22} + lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} @@ -2162,6 +2354,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.19: resolution: {integrity: sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==} @@ -2184,6 +2380,9 @@ packages: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} engines: {node: '>= 0.4'} + mdn-data@2.12.2: + resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + meow@13.2.0: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} @@ -2224,6 +2423,10 @@ packages: resolution: {integrity: sha512-wXqjST+SLt7R009ySCglWBCFpjUygmCIfD790/kVbiGmUgfYGuB14PiTd5DwVxSV4NcYHjzMkoj5LjQZwTQLEA==} engines: {node: '>=8'} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimatch@10.0.3: resolution: {integrity: sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==} engines: {node: 20 || >=22} @@ -2574,6 +2777,10 @@ packages: pathe@2.0.3: resolution: {integrity: sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==} + pathval@2.0.1: + resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==} + engines: {node: '>= 14.16'} + pdfjs-dist@4.6.82: resolution: {integrity: sha512-BUOryeRFwvbLe0lOU6NhkJNuVQUp06WxlJVVCsxdmJ4y5cU3O3s3/0DunVdK1PMm7v2MUw52qKYaidhDH1Z9+w==} engines: {node: '>=18'} @@ -2629,6 +2836,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-ms@9.3.0: resolution: {integrity: sha512-gjVS5hOP+M3wMm5nmNOucbIrqudzs9v/57bWRHQWLYklXqoXKrVfYW2W9+glfGsqtPgpiz5WwyEEB+ksXIx3gQ==} engines: {node: '>=18'} @@ -2676,6 +2887,9 @@ packages: react-is@16.13.1: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-refresh@0.17.0: resolution: {integrity: sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==} engines: {node: '>=0.10.0'} @@ -2699,6 +2913,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -2861,6 +3079,9 @@ packages: resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} engines: {node: '>= 0.4'} + siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -2915,6 +3136,12 @@ packages: sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + + std-env@3.9.0: + resolution: {integrity: sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==} + stop-iteration-iterator@1.1.0: resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==} engines: {node: '>= 0.4'} @@ -2975,6 +3202,10 @@ packages: resolution: {integrity: sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw==} engines: {node: '>=18'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -2983,6 +3214,9 @@ packages: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} + strip-literal@3.1.0: + resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + super-regex@1.0.0: resolution: {integrity: sha512-CY8u7DtbvucKuquCmOFEKhr9Besln7n9uN8eFbwcoGYWXOMW07u2o8njWaiXt11ylS3qoGF55pILjRmPlbodyg==} engines: {node: '>=18'} @@ -3044,20 +3278,45 @@ packages: resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} engines: {node: '>=12'} + tinybench@2.9.0: + resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} + + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} + tinypool@1.1.1: + resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} + engines: {node: ^18.0.0 || >=20.0.0} + + tinyrainbow@2.0.0: + resolution: {integrity: sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==} + engines: {node: '>=14.0.0'} + + tinyspy@4.0.4: + resolution: {integrity: sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==} + engines: {node: '>=14.0.0'} + tippy@0.0.0: resolution: {integrity: sha512-GOrE/mzoeL4t7Q2Bky+7efOZJKH3W95DZIUez+nUns37jHf8R9PEupuEx9F7HolxX+0fzzpKfas2N+LIlYHXAA==} tldts-core@6.1.86: resolution: {integrity: sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==} + tldts-core@7.0.16: + resolution: {integrity: sha512-XHhPmHxphLi+LGbH0G/O7dmUH9V65OY20R7vH8gETHsp5AZCjBk9l8sqmRKLaGOxnETU7XNSDUPtewAy/K6jbA==} + tldts@6.1.86: resolution: {integrity: sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==} hasBin: true + tldts@7.0.16: + resolution: {integrity: sha512-5bdPHSwbKTeHmXrgecID4Ljff8rQjv7g8zKQPkCozRo2HWWni+p310FSn5ImI+9kWw9kK4lzOB5q/a6iv0IJsw==} + hasBin: true + to-regex-range@5.0.1: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} @@ -3066,6 +3325,10 @@ packages: resolution: {integrity: sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==} engines: {node: '>=16'} + tough-cookie@6.0.0: + resolution: {integrity: sha512-kXuRi1mtaKMrsLUxz3sQYvVl37B0Ns6MzfrtV5DvJceE9bPyspOqk9xxv7XbZWcfLWbFmm997vl83qUWVJA64w==} + engines: {node: '>=16'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} @@ -3073,6 +3336,10 @@ packages: resolution: {integrity: sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==} engines: {node: '>=18'} + tr46@6.0.0: + resolution: {integrity: sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==} + engines: {node: '>=20'} + traverse@0.6.8: resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} engines: {node: '>= 0.4'} @@ -3201,6 +3468,11 @@ packages: peerDependencies: vue: ^3.0.11 + vite-node@3.2.4: + resolution: {integrity: sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + vite-plugin-dts@4.5.4: resolution: {integrity: sha512-d4sOM8M/8z7vRXHHq/ebbblfaxENjogAAekcfcDCCwAyvGqnPrc7f4NZbvItS+g4WTgerW0xDwSz5qz11JT3vg==} peerDependencies: @@ -3250,6 +3522,34 @@ packages: yaml: optional: true + vitest@3.2.4: + resolution: {integrity: sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==} + engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/debug': ^4.1.12 + '@types/node': ^18.0.0 || ^20.0.0 || >=22.0.0 + '@vitest/browser': 3.2.4 + '@vitest/ui': 3.2.4 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/debug': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vooks@0.2.12: resolution: {integrity: sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==} peerDependencies: @@ -3293,6 +3593,10 @@ packages: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} engines: {node: '>=12'} + webidl-conversions@8.0.0: + resolution: {integrity: sha512-n4W4YFyz5JzOfQeA8oN7dUYpR+MBP3PIUsn2jLjWXwK5ASUzt0Jc/A5sAUZoCYFJRGF0FBKJ+1JjN43rNdsQzA==} + engines: {node: '>=20'} + whatwg-encoding@3.1.1: resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} engines: {node: '>=18'} @@ -3305,6 +3609,10 @@ packages: resolution: {integrity: sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==} engines: {node: '>=18'} + whatwg-url@15.1.0: + resolution: {integrity: sha512-2ytDk0kiEj/yu90JOAp44PVPUkO9+jVhyf+SybKlRHSDlvOOZhdPIrr7xTH64l4WixO2cP+wQIcgujkGBPPz6g==} + engines: {node: '>=20'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -3329,6 +3637,11 @@ packages: engines: {node: '>= 8'} hasBin: true + why-is-node-running@2.3.0: + resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==} + engines: {node: '>=8'} + hasBin: true + wide-align@1.1.5: resolution: {integrity: sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==} @@ -3440,6 +3753,8 @@ packages: snapshots: + '@adobe/css-tools@4.4.4': {} + '@asamuzakjp/css-color@3.2.0': dependencies: '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) @@ -3448,6 +3763,24 @@ snapshots: '@csstools/css-tokenizer': 3.0.4 lru-cache: 10.4.3 + '@asamuzakjp/css-color@4.0.5': + dependencies: + '@csstools/css-calc': 2.1.4(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-color-parser': 3.1.0(@csstools/css-parser-algorithms@3.0.5(@csstools/css-tokenizer@3.0.4))(@csstools/css-tokenizer@3.0.4) + '@csstools/css-parser-algorithms': 3.0.5(@csstools/css-tokenizer@3.0.4) + '@csstools/css-tokenizer': 3.0.4 + lru-cache: 11.2.2 + + '@asamuzakjp/dom-selector@6.6.1': + dependencies: + '@asamuzakjp/nwsapi': 2.3.9 + bidi-js: 1.0.3 + css-tree: 3.1.0 + is-potential-custom-element-name: 1.0.1 + lru-cache: 11.2.2 + + '@asamuzakjp/nwsapi@2.3.9': {} + '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -3537,6 +3870,8 @@ snapshots: '@babel/core': 7.28.4 '@babel/helper-plugin-utils': 7.27.1 + '@babel/runtime@7.28.4': {} + '@babel/template@7.27.2': dependencies: '@babel/code-frame': 7.27.1 @@ -3589,6 +3924,10 @@ snapshots: dependencies: '@csstools/css-tokenizer': 3.0.4 + '@csstools/css-syntax-patches-for-csstree@1.0.14(postcss@8.5.6)': + dependencies: + postcss: 8.5.6 + '@csstools/css-tokenizer@3.0.4': {} '@emotion/hash@0.8.0': {} @@ -4123,8 +4462,44 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} + '@testing-library/dom@10.4.1': + dependencies: + '@babel/code-frame': 7.27.1 + '@babel/runtime': 7.28.4 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + picocolors: 1.1.1 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.9.1': + dependencies: + '@adobe/css-tools': 4.4.4 + aria-query: 5.3.2 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + picocolors: 1.1.1 + redent: 3.0.0 + + '@testing-library/react@16.3.0(@testing-library/dom@10.4.1)(@types/react-dom@19.2.1(@types/react@19.2.2))(@types/react@19.2.2)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)': + dependencies: + '@babel/runtime': 7.28.4 + '@testing-library/dom': 10.4.1 + react: 19.2.0 + react-dom: 19.2.0(react@19.2.0) + optionalDependencies: + '@types/react': 19.2.2 + '@types/react-dom': 19.2.1(@types/react@19.2.2) + + '@testing-library/user-event@14.6.1(@testing-library/dom@10.4.1)': + dependencies: + '@testing-library/dom': 10.4.1 + '@types/argparse@1.0.38': {} + '@types/aria-query@5.0.4': {} + '@types/babel__core@7.20.5': dependencies: '@babel/parser': 7.28.4 @@ -4146,6 +4521,12 @@ snapshots: dependencies: '@babel/types': 7.28.4 + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + + '@types/deep-eql@4.0.2': {} + '@types/estree@1.0.8': {} '@types/fs-extra@8.1.5': @@ -4290,6 +4671,48 @@ snapshots: transitivePeerDependencies: - supports-color + '@vitest/expect@3.2.4': + dependencies: + '@types/chai': 5.2.2 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + tinyrainbow: 2.0.0 + + '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.0))': + dependencies: + '@vitest/spy': 3.2.4 + estree-walker: 3.0.3 + magic-string: 0.30.19 + optionalDependencies: + vite: 7.1.9(@types/node@24.7.0) + + '@vitest/pretty-format@3.2.4': + dependencies: + tinyrainbow: 2.0.0 + + '@vitest/runner@3.2.4': + dependencies: + '@vitest/utils': 3.2.4 + pathe: 2.0.3 + strip-literal: 3.1.0 + + '@vitest/snapshot@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + magic-string: 0.30.19 + pathe: 2.0.3 + + '@vitest/spy@3.2.4': + dependencies: + tinyspy: 4.0.4 + + '@vitest/utils@3.2.4': + dependencies: + '@vitest/pretty-format': 3.2.4 + loupe: 3.2.1 + tinyrainbow: 2.0.0 + '@volar/language-core@2.4.23': dependencies: '@volar/source-map': 2.4.23 @@ -4451,6 +4874,8 @@ snapshots: dependencies: color-convert: 2.0.1 + ansi-styles@5.2.0: {} + any-promise@1.3.0: {} aproba@2.1.0: @@ -4470,6 +4895,12 @@ snapshots: argv-formatter@1.0.0: {} + aria-query@5.3.0: + dependencies: + dequal: 2.0.3 + + aria-query@5.3.2: {} + array-buffer-byte-length@1.0.2: dependencies: call-bound: 1.0.4 @@ -4531,6 +4962,8 @@ snapshots: get-intrinsic: 1.3.0 is-array-buffer: 3.0.5 + assertion-error@2.0.1: {} + async-function@1.0.0: {} async-validator@4.2.5: {} @@ -4547,6 +4980,10 @@ snapshots: before-after-hook@4.0.0: {} + bidi-js@1.0.3: + dependencies: + require-from-string: 2.0.2 + bottleneck@2.19.5: {} brace-expansion@1.1.12: @@ -4572,6 +5009,8 @@ snapshots: buffer-crc32@1.0.0: {} + cac@6.7.14: {} + call-bind-apply-helpers@1.0.2: dependencies: es-errors: 1.3.0 @@ -4603,6 +5042,14 @@ snapshots: - supports-color optional: true + chai@5.3.3: + dependencies: + assertion-error: 2.0.1 + check-error: 2.1.1 + deep-eql: 5.0.2 + loupe: 3.2.1 + pathval: 2.0.1 + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -4618,6 +5065,8 @@ snapshots: char-regex@1.0.2: {} + check-error@2.1.1: {} + chownr@2.0.0: optional: true @@ -4743,11 +5192,26 @@ snapshots: '@emotion/hash': 0.8.0 csstype: 3.0.11 + css-tree@3.1.0: + dependencies: + mdn-data: 2.12.2 + source-map-js: 1.2.1 + + css.escape@1.5.1: {} + cssstyle@4.6.0: dependencies: '@asamuzakjp/css-color': 3.2.0 rrweb-cssom: 0.8.0 + cssstyle@5.3.1(postcss@8.5.6): + dependencies: + '@asamuzakjp/css-color': 4.0.5 + '@csstools/css-syntax-patches-for-csstree': 1.0.14(postcss@8.5.6) + css-tree: 3.1.0 + transitivePeerDependencies: + - postcss + csstype@3.0.11: {} csstype@3.1.3: {} @@ -4757,6 +5221,11 @@ snapshots: whatwg-mimetype: 4.0.0 whatwg-url: 14.2.0 + data-urls@6.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + data-view-buffer@1.0.2: dependencies: call-bound: 1.0.4 @@ -4794,6 +5263,8 @@ snapshots: mimic-response: 2.1.0 optional: true + deep-eql@5.0.2: {} + deep-extend@0.6.0: {} deep-is@0.1.4: {} @@ -4815,6 +5286,8 @@ snapshots: delegates@1.0.0: optional: true + dequal@2.0.3: {} + detect-libc@2.1.2: optional: true @@ -4826,6 +5299,10 @@ snapshots: dependencies: esutils: 2.0.3 + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + dot-prop@5.3.0: dependencies: is-obj: 2.0.0 @@ -4943,6 +5420,8 @@ snapshots: iterator.prototype: 1.1.5 safe-array-concat: 1.1.3 + es-module-lexer@1.7.0: {} + es-object-atoms@1.1.1: dependencies: es-errors: 1.3.0 @@ -5100,6 +5579,10 @@ snapshots: estree-walker@2.0.2: {} + estree-walker@3.0.3: + dependencies: + '@types/estree': 1.0.8 + esutils@2.0.3: {} eventemitter3@5.0.1: {} @@ -5145,6 +5628,8 @@ snapshots: strip-final-newline: 4.0.0 yoctocolors: 2.1.2 + expect-type@1.2.2: {} + exsolve@1.0.7: {} fast-content-type-parse@3.0.0: {} @@ -5667,11 +6152,13 @@ snapshots: js-tokens@4.0.0: {} + js-tokens@9.0.1: {} + js-yaml@4.1.0: dependencies: argparse: 2.0.1 - jsdom@25.0.1(canvas@2.11.2): + jsdom@25.0.1: dependencies: cssstyle: 4.6.0 data-urls: 5.0.0 @@ -5694,13 +6181,39 @@ snapshots: whatwg-url: 14.2.0 ws: 8.18.3 xml-name-validator: 5.0.0 - optionalDependencies: - canvas: 2.11.2 transitivePeerDependencies: - bufferutil - supports-color - utf-8-validate + jsdom@27.0.0(postcss@8.5.6): + dependencies: + '@asamuzakjp/dom-selector': 6.6.1 + cssstyle: 5.3.1(postcss@8.5.6) + data-urls: 6.0.0 + decimal.js: 10.6.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.6 + is-potential-custom-element-name: 1.0.1 + parse5: 7.3.0 + rrweb-cssom: 0.8.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 6.0.0 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 8.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 15.1.0 + ws: 8.18.3 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - postcss + - supports-color + - utf-8-validate + jsesc@3.1.0: {} json-buffer@3.0.1: {} @@ -5793,8 +6306,12 @@ snapshots: dependencies: js-tokens: 4.0.0 + loupe@3.2.1: {} + lru-cache@10.4.3: {} + lru-cache@11.2.2: {} + lru-cache@5.1.1: dependencies: yallist: 3.1.1 @@ -5803,6 +6320,8 @@ snapshots: dependencies: yallist: 4.0.0 + lz-string@1.5.0: {} + magic-string@0.30.19: dependencies: '@jridgewell/sourcemap-codec': 1.5.5 @@ -5827,6 +6346,8 @@ snapshots: math-intrinsics@1.1.0: {} + mdn-data@2.12.2: {} + meow@13.2.0: {} merge-stream@2.0.0: {} @@ -5853,6 +6374,8 @@ snapshots: mimic-response@2.1.0: optional: true + min-indent@1.0.1: {} + minimatch@10.0.3: dependencies: '@isaacs/brace-expansion': 5.0.0 @@ -6141,6 +6664,8 @@ snapshots: pathe@2.0.3: {} + pathval@2.0.1: {} + pdfjs-dist@4.6.82: optionalDependencies: canvas: 2.11.2 @@ -6196,6 +6721,12 @@ snapshots: prettier@3.6.2: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-ms@9.3.0: dependencies: parse-ms: 4.0.0 @@ -6250,6 +6781,8 @@ snapshots: react-is@16.13.1: {} + react-is@17.0.2: {} + react-refresh@0.17.0: {} react@19.2.0: {} @@ -6285,6 +6818,11 @@ snapshots: util-deprecate: 1.0.2 optional: true + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -6522,6 +7060,8 @@ snapshots: side-channel-map: 1.0.1 side-channel-weakmap: 1.0.2 + siginfo@2.0.0: {} + signal-exit@3.0.7: {} signal-exit@4.1.0: {} @@ -6574,6 +7114,10 @@ snapshots: sprintf-js@1.0.3: {} + stackback@0.0.2: {} + + std-env@3.9.0: {} + stop-iteration-iterator@1.1.0: dependencies: es-errors: 1.3.0 @@ -6657,21 +7201,29 @@ snapshots: strip-final-newline@4.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} + strip-literal@3.1.0: + dependencies: + js-tokens: 9.0.1 + super-regex@1.0.0: dependencies: function-timeout: 1.0.2 time-span: 5.1.0 - superdoc@0.22.3(@hocuspocus/provider@2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(canvas@2.11.2)(pdfjs-dist@4.6.82)(typescript@5.9.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.2)(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(yjs@13.6.19): + superdoc@0.22.3(@hocuspocus/provider@2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(pdfjs-dist@4.6.82)(typescript@5.9.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.2)(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(yjs@13.6.19): dependencies: '@hocuspocus/provider': 2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19) buffer-crc32: 1.0.0 eventemitter3: 5.0.1 - jsdom: 25.0.1(canvas@2.11.2) + jsdom: 25.0.1 naive-ui: 2.43.1(vue@3.5.22(typescript@5.9.3)) pdfjs-dist: 4.6.82 pinia: 2.3.1(typescript@5.9.3)(vue@3.5.22(typescript@5.9.3)) @@ -6746,19 +7298,35 @@ snapshots: dependencies: convert-hrtime: 5.0.0 + tinybench@2.9.0: {} + + tinyexec@0.3.2: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) picomatch: 4.0.3 + tinypool@1.1.1: {} + + tinyrainbow@2.0.0: {} + + tinyspy@4.0.4: {} + tippy@0.0.0: {} tldts-core@6.1.86: {} + tldts-core@7.0.16: {} + tldts@6.1.86: dependencies: tldts-core: 6.1.86 + tldts@7.0.16: + dependencies: + tldts-core: 7.0.16 + to-regex-range@5.0.1: dependencies: is-number: 7.0.0 @@ -6767,6 +7335,10 @@ snapshots: dependencies: tldts: 6.1.86 + tough-cookie@6.0.0: + dependencies: + tldts: 7.0.16 + tr46@0.0.3: optional: true @@ -6774,6 +7346,10 @@ snapshots: dependencies: punycode: 2.3.1 + tr46@6.0.0: + dependencies: + punycode: 2.3.1 + traverse@0.6.8: {} treemate@0.3.11: {} @@ -6894,6 +7470,27 @@ snapshots: evtd: 0.2.4 vue: 3.5.22(typescript@5.9.3) + vite-node@3.2.4(@types/node@24.7.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.1.9(@types/node@24.7.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vite-plugin-dts@4.5.4(@types/node@24.7.0)(rollup@4.52.4)(typescript@5.9.3)(vite@7.1.9(@types/node@24.7.0)): dependencies: '@microsoft/api-extractor': 7.53.0(@types/node@24.7.0) @@ -6925,6 +7522,48 @@ snapshots: '@types/node': 24.7.0 fsevents: 2.3.3 + vitest@3.2.4(@types/node@24.7.0)(jsdom@27.0.0(postcss@8.5.6)): + dependencies: + '@types/chai': 5.2.2 + '@vitest/expect': 3.2.4 + '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.0)) + '@vitest/pretty-format': 3.2.4 + '@vitest/runner': 3.2.4 + '@vitest/snapshot': 3.2.4 + '@vitest/spy': 3.2.4 + '@vitest/utils': 3.2.4 + chai: 5.3.3 + debug: 4.4.3 + expect-type: 1.2.2 + magic-string: 0.30.19 + pathe: 2.0.3 + picomatch: 4.0.3 + std-env: 3.9.0 + tinybench: 2.9.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.15 + tinypool: 1.1.1 + tinyrainbow: 2.0.0 + vite: 7.1.9(@types/node@24.7.0) + vite-node: 3.2.4(@types/node@24.7.0) + why-is-node-running: 2.3.0 + optionalDependencies: + '@types/node': 24.7.0 + jsdom: 27.0.0(postcss@8.5.6) + transitivePeerDependencies: + - jiti + - less + - lightningcss + - msw + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + vooks@0.2.12(vue@3.5.22(typescript@5.9.3)): dependencies: evtd: 0.2.4 @@ -6966,6 +7605,8 @@ snapshots: webidl-conversions@7.0.0: {} + webidl-conversions@8.0.0: {} + whatwg-encoding@3.1.1: dependencies: iconv-lite: 0.6.3 @@ -6977,6 +7618,11 @@ snapshots: tr46: 5.1.1 webidl-conversions: 7.0.0 + whatwg-url@15.1.0: + dependencies: + tr46: 6.0.0 + webidl-conversions: 8.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -7028,6 +7674,11 @@ snapshots: dependencies: isexe: 2.0.0 + why-is-node-running@2.3.0: + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + wide-align@1.1.5: dependencies: string-width: 4.2.3 diff --git a/src/__tests__/SuperDocESign.test.tsx b/src/__tests__/SuperDocESign.test.tsx new file mode 100644 index 0000000..104f572 --- /dev/null +++ b/src/__tests__/SuperDocESign.test.tsx @@ -0,0 +1,534 @@ +import React, { createRef } from "react"; +import { + render, + screen, + fireEvent, + waitFor, + act, +} from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; +import { + beforeAll, + afterAll, + beforeEach, + describe, + expect, + it, + vi, +} from "vitest"; + +import SuperDocESign from "../index"; +import type { + FieldComponentProps, + SuperDocESignHandle, + SuperDocESignProps, + AuditEvent, +} from "../types"; + +import { SuperDoc } from "superdoc"; +import { getAuditEventTypes, resetAuditEvents } from "../test/setup"; + +const scrollListeners = new WeakMap(); +const originalAddEventListener = HTMLElement.prototype.addEventListener; + +beforeAll(() => { + HTMLElement.prototype.addEventListener = function ( + type: string, + listener: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions, + ) { + if (type === "scroll" && typeof listener === "function") { + scrollListeners.set(this as HTMLElement, listener); + } + return originalAddEventListener.call(this, type, listener, options); + }; +}); + +afterAll(() => { + HTMLElement.prototype.addEventListener = originalAddEventListener; +}); + +type ScrollMetrics = { + scrollTop: number; + scrollHeight: number; + clientHeight: number; +}; + +const configureScrollElement = ( + element: HTMLElement, + initial: ScrollMetrics, +) => { + const metrics: ScrollMetrics = { ...initial }; + + Object.defineProperties(element, { + scrollTop: { + configurable: true, + get: () => metrics.scrollTop, + set: (value: number) => { + metrics.scrollTop = value; + }, + }, + scrollHeight: { + configurable: true, + get: () => metrics.scrollHeight, + set: (value: number) => { + metrics.scrollHeight = value; + }, + }, + clientHeight: { + configurable: true, + get: () => metrics.clientHeight, + set: (value: number) => { + metrics.clientHeight = value; + }, + }, + }); + + const dispatch = () => { + const listener = scrollListeners.get(element); + if (listener) { + listener.call(element, new Event("scroll")); + } + }; + + const update = (partial: Partial, shouldDispatch = true) => { + if (partial.scrollTop !== undefined) metrics.scrollTop = partial.scrollTop; + if (partial.scrollHeight !== undefined) + metrics.scrollHeight = partial.scrollHeight; + if (partial.clientHeight !== undefined) + metrics.clientHeight = partial.clientHeight; + if (shouldDispatch) dispatch(); + }; + + return { update, dispatch, metrics }; +}; + +type MockFn = ReturnType; +type SuperDocMockType = typeof SuperDoc & { + mockUpdateStructuredContentById: MockFn; + mockGetStructuredContentTags: MockFn; + mockDestroy: MockFn; +}; + +const superDocMock = SuperDoc as unknown as SuperDocMockType; + +const baseDocument: SuperDocESignProps["document"] = { + source: "

Test Document

", + mode: "full", + validation: { + scroll: { + required: false, + }, + }, +}; + +const renderComponent = ( + props: Partial = {}, + options: { ref?: React.RefObject } = {}, +) => { + const { document: customDocument, ...restProps } = props; + + const mergedProps: SuperDocESignProps = { + eventId: "evt_test", + fields: {}, + onSubmit: vi.fn(), + ...restProps, + document: { + ...baseDocument, + ...(customDocument || {}), + }, + } as SuperDocESignProps; + + return render(); +}; + +const waitForSuperDocReady = async () => { + await waitFor(() => { + expect(superDocMock.mockGetStructuredContentTags).toHaveBeenCalled(); + }); +}; + +beforeEach(() => { + vi.clearAllMocks(); + superDocMock.mockGetStructuredContentTags.mockReset(); + superDocMock.mockGetStructuredContentTags.mockReturnValue([]); + superDocMock.mockUpdateStructuredContentById.mockReset(); + superDocMock.mockDestroy.mockReset(); + resetAuditEvents(); +}); + +describe("SuperDocESign component", () => { + it("renders with minimum required props", async () => { + renderComponent(); + + await waitForSuperDocReady(); + + expect(screen.getByTestId("superdoc-esign-document")).toBeInTheDocument(); + expect(screen.getByRole("button", { name: /submit/i })).toBeInTheDocument(); + expect( + screen.getByRole("button", { name: /download/i }), + ).toBeInTheDocument(); + }); + + it("requires scroll completion before enabling submit when validation is enforced", async () => { + const onSubmit = vi.fn(); + const ref = createRef(); + + const { getByPlaceholderText, getByRole, getByTestId } = renderComponent( + { + onSubmit, + document: { + source: "

Scroll document

", + mode: "full", + validation: { scroll: { required: true } }, + }, + fields: { + signer: [ + { + id: "sig-1", + type: "signature", + label: "Signature", + validation: { required: true }, + }, + ], + }, + }, + { ref }, + ); + + const scrollContainer = getByTestId("superdoc-scroll-container"); + const scrollController = configureScrollElement(scrollContainer, { + scrollHeight: 200, + clientHeight: 100, + scrollTop: 0, + }); + + await waitForSuperDocReady(); + + const submitButton = getByRole("button", { name: /submit/i }); + const input = getByPlaceholderText("Type your full name"); + fireEvent.change(input, { target: { value: "Jane Doe" } }); + + await waitFor(() => expect(submitButton).toBeDisabled()); + + act(() => { + scrollController.update({ + scrollHeight: 1000, + clientHeight: 100, + scrollTop: 950, + }); + }); + + await waitFor(() => { + const state = ref.current?.getState(); + expect(state?.scrolled).toBe(true); + expect(state?.isValid).toBe(true); + }); + + const updatedSubmitButton = getByRole("button", { name: /submit/i }); + await userEvent.click(updatedSubmitButton); + await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1)); + }); + + it("invokes field and state change callbacks and updates SuperDoc document", async () => { + const onFieldChange = vi.fn(); + const onStateChange = vi.fn(); + + const { getByPlaceholderText } = renderComponent({ + onFieldChange, + onStateChange, + fields: { + signer: [ + { + id: "sig-field", + type: "signature", + label: "Signature", + validation: { required: true }, + }, + ], + }, + }); + + await waitForSuperDocReady(); + + const input = getByPlaceholderText("Type your full name"); + fireEvent.change(input, { target: { value: "John Doe" } }); + + await waitFor(() => { + expect(onFieldChange).toHaveBeenCalled(); + expect(onStateChange).toHaveBeenCalled(); + }); + + const lastFieldChange = onFieldChange.mock.calls.at(-1)?.[0]; + expect(lastFieldChange).toMatchObject({ + id: "sig-field", + value: "John Doe", + }); + + const lastState = onStateChange.mock.calls.at(-1)?.[0]; + expect(lastState?.fields.get("sig-field")).toBe("John Doe"); + + expect(superDocMock.mockUpdateStructuredContentById).toHaveBeenCalledWith( + "sig-field", + expect.objectContaining({ + json: expect.objectContaining({ + attrs: expect.objectContaining({ src: expect.any(String) }), + }), + }), + ); + }); + + it("tracks audit trail and exposes ref methods", async () => { + const ref = createRef(); + + const { getByPlaceholderText, getByRole, getByTestId } = renderComponent( + { + document: { + source: "

Scroll doc

", + mode: "full", + validation: { scroll: { required: true } }, + }, + fields: { + signer: [ + { + id: "sig-field", + type: "signature", + label: "Signature", + validation: { required: true }, + }, + ], + }, + }, + { ref }, + ); + + await waitForSuperDocReady(); + await waitFor(() => expect(ref.current).toBeTruthy()); + + const scrollContainer = getByTestId("superdoc-scroll-container"); + const scrollController = configureScrollElement(scrollContainer, { + scrollHeight: 300, + clientHeight: 100, + scrollTop: 0, + }); + + const input = getByPlaceholderText("Type your full name"); + fireEvent.change(input, { target: { value: "Audit User" } }); + + act(() => { + scrollController.update({ scrollTop: 250 }); + }); + + const submitButton = getByRole("button", { name: /submit/i }); + await waitFor(() => expect(submitButton).not.toBeDisabled(), { + timeout: 2000, + }); + await userEvent.click(submitButton); + + await waitFor(() => { + const auditTrail = ref.current?.getAuditTrail() ?? []; + expect(auditTrail.length).toBeGreaterThanOrEqual(4); + }); + + const auditTrail = ref.current?.getAuditTrail() ?? []; + const types = auditTrail.map((event) => event.type); + expect(types[0]).toBe("ready"); + expect(types).to.include("field_change"); + expect( + types.filter((type) => type === "scroll").length, + ).toBeGreaterThanOrEqual(1); + expect(types).to.include("submit"); + + auditTrail.forEach((event: AuditEvent) => { + expect(typeof event.timestamp).toBe("string"); + expect(Number.isNaN(new Date(event.timestamp).getTime())).toBe(false); + }); + + const stateBeforeReset = ref.current?.getState(); + expect(stateBeforeReset).toMatchObject({ + scrolled: true, + isValid: true, + isSubmitting: false, + }); + expect(stateBeforeReset?.fields.get("sig-field")).toBe("Audit User"); + + act(() => { + ref.current?.reset(); + }); + + const stateAfterReset = ref.current?.getState(); + expect(stateAfterReset).toMatchObject({ + scrolled: false, + isValid: false, + }); + expect(stateAfterReset?.fields.size).toBe(0); + expect(ref.current?.getAuditTrail()).toEqual([]); + }); + + it("prefers custom components when provided", async () => { + const onSubmit = vi.fn(); + const onDownload = vi.fn(); + + const CustomField: React.FC = ({ + onChange, + label, + }) => ( +
+ {label} + +
+ ); + const SubmitButton: React.FC<{ + onClick: () => void; + isDisabled: boolean; + isValid: boolean; + isSubmitting: boolean; + }> = ({ onClick, isDisabled, isValid }) => ( + + ); + + const DownloadButton: React.FC<{ + onClick: () => void; + fileName?: string; + isDisabled: boolean; + }> = ({ onClick, isDisabled }) => ( + + ); + + renderComponent({ + onSubmit, + onDownload, + fields: { + signer: [ + { + id: "custom-field", + type: "text", + label: "Custom Field", + component: CustomField, + validation: { required: true }, + }, + ], + }, + submit: { + component: SubmitButton as unknown as React.ComponentType, + }, + download: { + component: DownloadButton as unknown as React.ComponentType, + }, + }); + + await waitFor(() => expect(superDocMock).toHaveBeenCalled()); + await waitForSuperDocReady(); + + expect(screen.getByText("Custom Field")).toBeInTheDocument(); + expect( + screen.queryByPlaceholderText("Type your full name"), + ).not.toBeInTheDocument(); + + await userEvent.click(screen.getByText("Set Custom Value")); + + const submitButton = screen.getByRole("button", { name: "Send It" }); + await waitFor(() => expect(submitButton).not.toBeDisabled()); + await userEvent.click(submitButton); + + await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1)); + + const downloadButton = screen.getByRole("button", { name: "Grab Copy" }); + expect(downloadButton).toBeEnabled(); + await userEvent.click(downloadButton); + await waitFor(() => expect(onDownload).toHaveBeenCalledTimes(1)); + + const downloadPayload = onDownload.mock.calls.at(0)?.[0]; + expect(downloadPayload).toMatchObject({ + eventId: "evt_test", + fields: { + signer: [{ id: "custom-field", value: "custom-value" }], + }, + fileName: "document.pdf", + }); + }); + + it("generates submit payload with expected structure and audit trail", async () => { + const onSubmit = vi.fn(); + + const { getByPlaceholderText, getByRole, getByTestId } = renderComponent({ + onSubmit, + document: { + source: "

Full payload doc

", + mode: "full", + validation: { scroll: { required: true } }, + }, + fields: { + document: [ + { + id: "doc-field", + value: "Document Value", + }, + ], + signer: [ + { + id: "sig-field", + type: "signature", + label: "Signature", + validation: { required: true }, + }, + ], + }, + }); + + const scrollContainer = getByTestId("superdoc-scroll-container"); + const scrollController = configureScrollElement(scrollContainer, { + scrollHeight: 400, + clientHeight: 100, + scrollTop: 0, + }); + + await waitForSuperDocReady(); + + fireEvent.change(getByPlaceholderText("Type your full name"), { + target: { value: "Payload User" }, + }); + + act(() => { + scrollController.update({ scrollTop: 390 }); + }); + + const submitButton = getByRole("button", { name: /submit/i }); + await waitFor(() => expect(submitButton).not.toBeDisabled()); + await userEvent.click(submitButton); + + await waitFor(() => expect(onSubmit).toHaveBeenCalledTimes(1)); + + await waitFor(() => { + const types = getAuditEventTypes(); + expect(types).to.include("submit"); + }); + + const submitData = onSubmit.mock.calls[0][0]; + expect(submitData.eventId).toBe("evt_test"); + expect(typeof submitData.timestamp).toBe("string"); + expect(Number.isNaN(new Date(submitData.timestamp).getTime())).toBe(false); + expect(typeof submitData.duration).toBe("number"); + expect(submitData.isFullyCompleted).toBe(true); + + expect(submitData.documentFields).toEqual([ + { id: "doc-field", value: "Document Value" }, + ]); + + expect(submitData.signerFields).toEqual([ + { id: "sig-field", value: "Payload User" }, + ]); + + const auditTypes = submitData.auditTrail.map( + (event: AuditEvent) => event.type, + ); + expect(auditTypes).to.include.members(["ready", "field_change"]); + expect(auditTypes).to.include("submit"); + }); +}); diff --git a/src/defaults/SignatureInput.tsx b/src/defaults/SignatureInput.tsx index b8672f9..a78c7e9 100644 --- a/src/defaults/SignatureInput.tsx +++ b/src/defaults/SignatureInput.tsx @@ -8,7 +8,10 @@ export const SignatureInput: React.FC = ({ label, }) => { return ( -
+
{label && } ; -const SuperDocESign = forwardRef( - (props, ref) => { - const { - eventId, - document, - fields = {}, - download, - submit, - onSubmit, - onDownload, - onStateChange, - onFieldChange, - onFieldsDiscovered, - isDisabled = false, - className, - style, - documentHeight = "600px", - } = props; - - const [scrolled, setScrolled] = useState( - !document.validation?.scroll?.required, +const SuperDocESign = forwardRef< + Types.SuperDocESignHandle, + Types.SuperDocESignProps +>((props, ref) => { + const { + eventId, + document, + fields = {}, + download, + submit, + onSubmit, + onDownload, + onStateChange, + onFieldChange, + onFieldsDiscovered, + isDisabled = false, + className, + style, + documentHeight = "600px", + } = props; + + const [scrolled, setScrolled] = useState( + !document.validation?.scroll?.required, + ); + const [fieldValues, setFieldValues] = useState>( + new Map(), + ); + const [isValid, setIsValid] = useState(false); + const [isSubmitting, setIsSubmitting] = useState(false); + const [auditTrail, setAuditTrail] = useState([]); + const [isReady, setIsReady] = useState(false); + + const containerRef = useRef(null); + const superdocRef = useRef(null); + const startTimeRef = useRef(Date.now()); + const fieldsRef = useRef(fields); + const auditTrailRef = useRef([]); + fieldsRef.current = fields; + + useEffect(() => { + auditTrailRef.current = auditTrail; + }, [auditTrail]); + + const updateFieldInDocument = useCallback((field: Types.FieldUpdate) => { + if (!superdocRef.current?.activeEditor) return; + const editor = superdocRef.current.activeEditor; + + const signerField = fieldsRef.current.signer?.find( + (f) => f.id === field.id, ); - const [fieldValues, setFieldValues] = useState< - Map - >(new Map()); - const [isValid, setIsValid] = useState(false); - const [isSubmitting, setIsSubmitting] = useState(false); - const [auditTrail, setAuditTrail] = useState([]); - const [isReady, setIsReady] = useState(false); - - const containerRef = useRef(null); - const superdocRef = useRef(null); - const startTimeRef = useRef(Date.now()); - const fieldsRef = useRef(fields); - fieldsRef.current = fields; - - const updateFieldInDocument = useCallback((field: Types.FieldUpdate) => { - if (!superdocRef.current?.activeEditor) return; - const editor = superdocRef.current.activeEditor; - - const signerField = fieldsRef.current.signer?.find((f) => f.id === field.id); - - let updatePayload; - - if (signerField?.type === "signature" && field.value) { - const imageUrl = - typeof field.value === "string" && - field.value.startsWith("data:image/") - ? field.value - : textToImageDataUrl(String(field.value)); - - updatePayload = { - json: { - type: "image", - attrs: { src: imageUrl, alt: "Signature" }, - }, - }; - } else { - updatePayload = { text: String(field.value ?? "") }; - } - if (field.id) { - editor.commands.updateStructuredContentById( - field.id, - updatePayload, - ); - } - }, []); + let updatePayload; - function textToImageDataUrl(text: string): string { - const canvas = globalThis.document.createElement("canvas"); - const ctx = canvas.getContext("2d")!; + if (signerField?.type === "signature" && field.value) { + const imageUrl = + typeof field.value === "string" && field.value.startsWith("data:image/") + ? field.value + : textToImageDataUrl(String(field.value)); - const fontSize = 30; - ctx.font = `italic ${fontSize}px cursive`; + updatePayload = { + json: { + type: "image", + attrs: { src: imageUrl, alt: "Signature" }, + }, + }; + } else { + updatePayload = { text: String(field.value ?? "") }; + } - const metrics = ctx.measureText(text); - const textWidth = metrics.width; + if (field.id) { + editor.commands.updateStructuredContentById(field.id, updatePayload); + } + }, []); - const estimatedHeight = fontSize * 1.3; // Cursive fonts typically need ~1.3x font size - const paddingX = 4; - const paddingY = 6; // Extra vertical padding for cursive descenders + function textToImageDataUrl(text: string): string { + const canvas = globalThis.document.createElement("canvas"); + const ctx = canvas.getContext("2d")!; - canvas.width = Math.ceil(textWidth + paddingX * 2) + 20; - canvas.height = Math.ceil(estimatedHeight + paddingY * 2); + const fontSize = 30; + ctx.font = `italic ${fontSize}px cursive`; - ctx.font = `italic ${fontSize}px cursive`; - ctx.fillStyle = "black"; - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; + const metrics = ctx.measureText(text); + const textWidth = metrics.width; - ctx.fillText( - text, - canvas.width / 2, - canvas.height / 2 - ); + const estimatedHeight = fontSize * 1.3; // Cursive fonts typically need ~1.3x font size + const paddingX = 4; + const paddingY = 6; // Extra vertical padding for cursive descenders - return canvas.toDataURL("image/png"); - } + canvas.width = Math.ceil(textWidth + paddingX * 2) + 20; + canvas.height = Math.ceil(estimatedHeight + paddingY * 2); - const discoverAndApplyFields = useCallback( - (editor: Editor) => { - if (!editor) return; + ctx.font = `italic ${fontSize}px cursive`; + ctx.fillStyle = "black"; + ctx.textAlign = "center"; + ctx.textBaseline = "middle"; - const tags = - editor.helpers.structuredContentCommands.getStructuredContentTags( - editor.state, - ); + ctx.fillText(text, canvas.width / 2, canvas.height / 2); - const configValues = new Map(); + return canvas.toDataURL("image/png"); + } - fieldsRef.current.document?.forEach((f) => { - if (f.id) configValues.set(f.id, f.value); - }); + const discoverAndApplyFields = useCallback( + (editor: Editor) => { + if (!editor) return; - fieldsRef.current.signer?.forEach((f) => { - if (f.value !== undefined) { - configValues.set(f.id, f.value); - } - }); + const tags = + editor.helpers.structuredContentCommands.getStructuredContentTags( + editor.state, + ); + + const configValues = new Map(); - const discovered: Types.FieldInfo[] = tags - .map(({ node }: any) => ({ - id: node.attrs.id, - label: node.attrs.label, - value: - configValues.get(node.attrs.id) ?? - node.textContent ?? - "", - })) - .filter((f: Types.FieldInfo) => f.id); - - if (discovered.length > 0) { - onFieldsDiscovered?.(discovered); - - const allFields = [ - ...(fieldsRef.current.document || []), - ...(fieldsRef.current.signer || []), - ]; - - allFields - .filter((field) => field.value !== undefined) - .forEach((field) => - updateFieldInDocument({ - id: field.id, - value: field.value!, - }), - ); + fieldsRef.current.document?.forEach((f) => { + if (f.id) configValues.set(f.id, f.value); + }); + + fieldsRef.current.signer?.forEach((f) => { + if (f.value !== undefined) { + configValues.set(f.id, f.value); } - }, - [onFieldsDiscovered, updateFieldInDocument], - ); + }); - const addAuditEvent = (event: Omit) => { - const auditEvent: Types.AuditEvent = { - ...event, - timestamp: new Date().toISOString(), - }; - setAuditTrail((prev) => [...prev, auditEvent]); + const discovered: Types.FieldInfo[] = tags + .map(({ node }: any) => ({ + id: node.attrs.id, + label: node.attrs.label, + value: configValues.get(node.attrs.id) ?? node.textContent ?? "", + })) + .filter((f: Types.FieldInfo) => f.id); + + if (discovered.length > 0) { + onFieldsDiscovered?.(discovered); + + const allFields = [ + ...(fieldsRef.current.document || []), + ...(fieldsRef.current.signer || []), + ]; + + allFields + .filter((field) => field.value !== undefined) + .forEach((field) => + updateFieldInDocument({ + id: field.id, + value: field.value!, + }), + ); + } + }, + [onFieldsDiscovered, updateFieldInDocument], + ); + + const addAuditEvent = ( + event: Omit, + ): Types.AuditEvent[] => { + const auditEvent: Types.AuditEvent = { + ...event, + timestamp: new Date().toISOString(), }; + const auditMock = (globalThis as any)?.__SUPERDOC_AUDIT_MOCK__; + if (auditMock) { + auditMock(auditEvent); + } + const nextTrail = [...auditTrailRef.current, auditEvent]; + auditTrailRef.current = nextTrail; + setAuditTrail(nextTrail); + return nextTrail; + }; + + // Initialize SuperDoc - ONLY ONCE per document + useEffect(() => { + if (!containerRef.current) return; + + const initSuperDoc = async () => { + const { SuperDoc } = await import("superdoc"); + + const instance = new SuperDoc({ + selector: containerRef.current!, + document: document.source, + documentMode: "viewing", + onReady: () => { + if (instance.activeEditor) { + discoverAndApplyFields(instance.activeEditor); + } + addAuditEvent({ type: "ready" }); + setIsReady(true); + }, + }); - // Initialize SuperDoc - ONLY ONCE per document - useEffect(() => { - if (!containerRef.current) return; - - const initSuperDoc = async () => { - const { SuperDoc } = await import("superdoc"); - - const instance = new SuperDoc({ - selector: containerRef.current!, - document: document.source, - documentMode: "viewing", - onReady: () => { - if (instance.activeEditor) { - discoverAndApplyFields(instance.activeEditor); - } - addAuditEvent({ type: "ready" }); - setIsReady(true); - }, - }); - - superdocRef.current = instance; - }; + superdocRef.current = instance; + }; - initSuperDoc(); + initSuperDoc(); - return () => { - if (superdocRef.current) { + return () => { + if (superdocRef.current) { + if (typeof superdocRef.current.destroy === "function") { superdocRef.current.destroy(); - superdocRef.current = null; } - }; - }, [document.source, document.mode, discoverAndApplyFields]); + superdocRef.current = null; + } + }; + }, [document.source, document.mode, discoverAndApplyFields]); - useEffect(() => { - if (!document.validation?.scroll?.required || !isReady) return; + useEffect(() => { + if (!document.validation?.scroll?.required || !isReady) return; - const scrollContainer = containerRef.current; - if (!scrollContainer) return; + const scrollContainer = containerRef.current; + if (!scrollContainer) return; - const handleScroll = () => { - const { scrollTop, scrollHeight, clientHeight } = scrollContainer; - const scrollPercentage = scrollTop / (scrollHeight - clientHeight); + const handleScroll = () => { + const { scrollTop, scrollHeight, clientHeight } = scrollContainer; + const scrollPercentage = scrollTop / (scrollHeight - clientHeight); - if (scrollPercentage >= 0.95 || scrollHeight <= clientHeight) { - setScrolled(true); - addAuditEvent({ - type: "scroll", - data: { percent: Math.round(scrollPercentage * 100) }, - }); - } - }; - - scrollContainer.addEventListener("scroll", handleScroll); - handleScroll(); + if (scrollPercentage >= 0.95 || scrollHeight <= clientHeight) { + setScrolled(true); + addAuditEvent({ + type: "scroll", + data: { percent: Math.round(scrollPercentage * 100) }, + }); + } + }; - return () => scrollContainer.removeEventListener("scroll", handleScroll); - }, [document.validation?.scroll?.required, isReady]); + scrollContainer.addEventListener("scroll", handleScroll); + handleScroll(); - const handleFieldChange = useCallback( - (fieldId: string, value: Types.FieldValue) => { - setFieldValues((prev) => { - const previousValue = prev.get(fieldId); - const newMap = new Map(prev); - newMap.set(fieldId, value); + return () => scrollContainer.removeEventListener("scroll", handleScroll); + }, [document.validation?.scroll?.required, isReady]); - updateFieldInDocument({ - id: fieldId, - value: value, - }); + const handleFieldChange = useCallback( + (fieldId: string, value: Types.FieldValue) => { + setFieldValues((prev) => { + const previousValue = prev.get(fieldId); + const newMap = new Map(prev); + newMap.set(fieldId, value); - addAuditEvent({ - type: "field_change", - data: { fieldId, value, previousValue }, - }); + updateFieldInDocument({ + id: fieldId, + value: value, + }); - onFieldChange?.({ - id: fieldId, - value, - previousValue, - }); + addAuditEvent({ + type: "field_change", + data: { fieldId, value, previousValue }, + }); - return newMap; + onFieldChange?.({ + id: fieldId, + value, + previousValue, }); - }, - [onFieldChange, updateFieldInDocument], - ); - const checkIsValid = useCallback((): boolean => { - if (document.validation?.scroll?.required && !scrolled) { - return false; - } - return (fields.signer || []).every((field) => { - if (!field.validation?.required) return true; - const value = fieldValues.get(field.id); - return value && (typeof value !== "string" || value.trim()); + return newMap; }); - }, [scrolled, fields.signer, fieldValues, document.validation?.scroll?.required]); - useEffect(() => { - const valid = checkIsValid(); - setIsValid(valid); - - const state: Types.SigningState = { - scrolled, - fields: fieldValues, - isValid: valid, - isSubmitting, - }; - onStateChange?.(state); - }, [scrolled, fieldValues, isSubmitting, checkIsValid, onStateChange]); - - const handleDownload = useCallback(async () => { - if (isDisabled) return; - - const downloadData: Types.DownloadData = { - eventId, - documentSource: document.source, - fields: { - document: fields.document || [], - signer: (fields.signer || []).map(field => ({ - id: field.id, - value: fieldValues.get(field.id) ?? null, - })), - }, - fileName: download?.fileName || "document.pdf" - }; - - await onDownload?.(downloadData); - }, [isDisabled, eventId, document.source, fields, fieldValues, download, onDownload]); + }, + [onFieldChange, updateFieldInDocument], + ); + const checkIsValid = useCallback((): boolean => { + if (document.validation?.scroll?.required && !scrolled) { + return false; + } - const handleSubmit = useCallback(async () => { - if (!isValid || isDisabled || isSubmitting) return; + return (fields.signer || []).every((field) => { + if (!field.validation?.required) return true; + const value = fieldValues.get(field.id); + return value && (typeof value !== "string" || value.trim()); + }); + }, [ + scrolled, + fields.signer, + fieldValues, + document.validation?.scroll?.required, + ]); + useEffect(() => { + const valid = checkIsValid(); + setIsValid(valid); + + const state: Types.SigningState = { + scrolled, + fields: fieldValues, + isValid: valid, + isSubmitting, + }; + onStateChange?.(state); + }, [scrolled, fieldValues, isSubmitting, checkIsValid, onStateChange]); - setIsSubmitting(true); - addAuditEvent({ type: "submit" }); + const handleDownload = useCallback(async () => { + if (isDisabled) return; - const submitData: Types.SubmitData = { - eventId, - timestamp: new Date().toISOString(), - duration: Math.floor((Date.now() - startTimeRef.current) / 1000), - auditTrail, - documentFields: fields.document || [], - signerFields: (fields.signer || []).map((field) => ({ + const downloadData: Types.DownloadData = { + eventId, + documentSource: document.source, + fields: { + document: fields.document || [], + signer: (fields.signer || []).map((field) => ({ id: field.id, value: fieldValues.get(field.id) ?? null, })), - isFullyCompleted: isValid, - }; + }, + fileName: download?.fileName || "document.pdf", + }; - try { - await onSubmit(submitData); - } finally { - setIsSubmitting(false); - } - }, [ - isValid, - isDisabled, - isSubmitting, + await onDownload?.(downloadData); + }, [ + isDisabled, + eventId, + document.source, + fields, + fieldValues, + download, + onDownload, + ]); + + const handleSubmit = useCallback(async () => { + if (!isValid || isDisabled || isSubmitting) return; + + setIsSubmitting(true); + addAuditEvent({ type: "submit" }); + + const nextAuditTrail = addAuditEvent({ type: "submit" }); + + const submitData: Types.SubmitData = { eventId, - auditTrail, - fields, - fieldValues, - onSubmit, - ]); - - const renderField = (field: Types.SignerField) => { - const Component = field.component || getDefaultComponent(field.type); - - return ( - handleFieldChange(field.id, value)} - isDisabled={isDisabled} - label={field.label} - /> - ); + timestamp: new Date().toISOString(), + duration: Math.floor((Date.now() - startTimeRef.current) / 1000), + auditTrail: nextAuditTrail, + documentFields: fields.document || [], + signerFields: (fields.signer || []).map((field) => ({ + id: field.id, + value: fieldValues.get(field.id) ?? null, + })), + isFullyCompleted: isValid, }; - const getDefaultComponent = ( - type: "signature" | "checkbox" | "text", - ) => { - switch (type) { - case "signature": - case "text": - return SignatureInput; - case "checkbox": - return CheckboxInput; - } - }; + try { + await onSubmit(submitData); + } finally { + setIsSubmitting(false); + } + }, [ + isValid, + isDisabled, + isSubmitting, + eventId, + fields, + fieldValues, + onSubmit, + ]); + + const renderField = (field: Types.SignerField) => { + const Component = field.component || getDefaultComponent(field.type); + + return ( + handleFieldChange(field.id, value)} + isDisabled={isDisabled} + label={field.label} + /> + ); + }; + + const getDefaultComponent = (type: "signature" | "checkbox" | "text") => { + switch (type) { + case "signature": + case "text": + return SignatureInput; + case "checkbox": + return CheckboxInput; + } + }; - const renderActionButtons = () => { - const DownloadButton = - download?.component || createDownloadButton(download); - const SubmitButton = submit?.component || createSubmitButton(submit); + const renderActionButtons = () => { + const DownloadButton = + download?.component || createDownloadButton(download); + const SubmitButton = submit?.component || createSubmitButton(submit); - return ( -
- {document.mode !== "download" && ( - - )} - + {document.mode !== "download" && ( + -
- ); - }; + )} + +
+ ); + }; - useImperativeHandle(ref, () => ({ - getState: () => ({ - scrolled, - fields: fieldValues, - isValid, - isSubmitting, - }), - getAuditTrail: () => auditTrail, - reset: () => { - setScrolled(!document.validation?.scroll?.required); - setFieldValues(new Map()); - setIsValid(false); - setAuditTrail([]); - }, - })); + useImperativeHandle(ref, () => ({ + getState: () => ({ + scrolled, + fields: fieldValues, + isValid, + isSubmitting, + }), + getAuditTrail: () => auditTrailRef.current, + reset: () => { + setScrolled(!document.validation?.scroll?.required); + setFieldValues(new Map()); + setIsValid(false); + auditTrailRef.current = []; + setAuditTrail([]); + }, + })); + + return ( +
+ {/* Document viewer section */} +
+
+
- return ( + {/* Controls section - separate from document */}
- {/* Document viewer section */} -
+ {/* Signer fields */} + {fields.signer && fields.signer.length > 0 && (
-
- - {/* Controls section - separate from document */} -
- {/* Signer fields */} - {fields.signer && fields.signer.length > 0 && ( -
- {fields.signer.map(renderField)} -
- )} - - {/* Action buttons */} - {renderActionButtons()} -
+ className="superdoc-esign-fields" + style={{ marginBottom: "20px" }} + data-testid="superdoc-esign-fields" + > + {fields.signer.map(renderField)} +
+ )} + + {/* Action buttons */} + {renderActionButtons()}
- ); - }, -); +
+ ); +}); SuperDocESign.displayName = "SuperDocESign"; diff --git a/src/test/setup.ts b/src/test/setup.ts new file mode 100644 index 0000000..94d9122 --- /dev/null +++ b/src/test/setup.ts @@ -0,0 +1,94 @@ +import "@testing-library/jest-dom/vitest"; + +const mockUpdateStructuredContentById = vi.fn(); +const mockGetStructuredContentTags = vi.fn(() => []); +const mockDestroy = vi.fn(); + +const auditEvents: Array<{ type: string; data?: Record }> = []; + +export const resetAuditEvents = () => { + auditEvents.length = 0; +}; + +export const recordAuditEvent = ( + type: string, + data?: Record, +) => { + auditEvents.push({ type, data }); +}; + +export const getAuditEventTypes = () => auditEvents.map((event) => event.type); + +if (typeof window !== "undefined") { + (window as any).__SUPERDOC_AUDIT_MOCK__ = (event: { + type: string; + data?: Record; + }) => { + recordAuditEvent(event.type, event.data); + }; +} + +vi.stubGlobal( + "__SUPERDOC_AUDIT_MOCK__", + (event: { type: string; data?: Record }) => { + recordAuditEvent(event.type, event.data); + }, +); + +const mockEditor = { + commands: { + updateStructuredContentById: mockUpdateStructuredContentById, + }, + helpers: { + structuredContentCommands: { + getStructuredContentTags: mockGetStructuredContentTags, + }, + }, + state: {}, +}; + +const SuperDocMock = vi.fn((options: any = {}) => { + if (options?.onReady) { + if (typeof queueMicrotask === "function") { + queueMicrotask(() => options.onReady()); + } else { + Promise.resolve().then(() => options.onReady()); + } + } + + return { + destroy: mockDestroy, + activeEditor: mockEditor, + on: vi.fn(), + }; +}); + +(SuperDocMock as any).mockEditor = mockEditor; +(SuperDocMock as any).mockUpdateStructuredContentById = + mockUpdateStructuredContentById; +(SuperDocMock as any).mockGetStructuredContentTags = + mockGetStructuredContentTags; +(SuperDocMock as any).mockDestroy = mockDestroy; +(SuperDocMock as any).mockAuditEvents = auditEvents; +(SuperDocMock as any).resetAuditEvents = resetAuditEvents; +(SuperDocMock as any).recordAuditEvent = recordAuditEvent; +(SuperDocMock as any).getAuditEventTypes = getAuditEventTypes; + +vi.mock("superdoc", () => ({ + SuperDoc: SuperDocMock, +})); + +const canvasProto = globalThis.HTMLCanvasElement?.prototype; + +if (canvasProto) { + canvasProto.getContext = vi.fn(() => ({ + font: "", + fillStyle: "", + textAlign: "", + textBaseline: "", + measureText: () => ({ width: 100 }), + fillText: () => undefined, + })) as any; + + canvasProto.toDataURL = vi.fn(() => "data:image/png;base64,mock"); +} diff --git a/src/types.ts b/src/types.ts index f685038..7193790 100644 --- a/src/types.ts +++ b/src/types.ts @@ -96,6 +96,12 @@ export interface SigningState { isSubmitting: boolean; } +export interface SuperDocESignHandle { + getState: () => SigningState; + getAuditTrail: () => AuditEvent[]; + reset: () => void; +} + export interface DownloadData { eventId: string; documentSource: string | File | Blob; diff --git a/tsconfig.json b/tsconfig.json index dd1a171..5a5a554 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -3,10 +3,11 @@ "target": "ES2020", "module": "ESNext", "lib": [ - "ES2020", + "ES2022", "DOM", "DOM.Iterable" ], + "types": ["vitest/globals"], "jsx": "react-jsx", "strict": true, "esModuleInterop": true, diff --git a/vite.config.ts b/vite.config.ts index 2a4c48f..5fbfb1d 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -17,4 +17,11 @@ export default defineConfig({ react(), dts() ], + test: { + environment: 'jsdom', + setupFiles: ['./src/test/setup.ts'], + globals: true, + clearMocks: true, + restoreMocks: true + } }); \ No newline at end of file From e9363464c4c89d4bc04ed14845b42cfb0c5f0bcb Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 8 Oct 2025 13:38:33 -0300 Subject: [PATCH 2/6] chore: add commitlint configuration for conventional commit messages --- commitlint.config.js | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 commitlint.config.js diff --git a/commitlint.config.js b/commitlint.config.js new file mode 100644 index 0000000..85f0985 --- /dev/null +++ b/commitlint.config.js @@ -0,0 +1,4 @@ +export default { + extends: ['@commitlint/config-conventional'], +}; + From 4d16f9efbac126dc88b01b1d044c545bffbc98f8 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 8 Oct 2025 13:51:56 -0300 Subject: [PATCH 3/6] chore: add @commitlint/config-conventional to devDependencies --- package.json | 1 + pnpm-lock.yaml | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/package.json b/package.json index 4031a6a..f0b6c04 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "superdoc": "^0.22.0" }, "devDependencies": { + "@commitlint/config-conventional": "^20.0.0", "@eslint/js": "^9.36.0", "@semantic-release/changelog": "^6.0.3", "@semantic-release/git": "^10.0.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3fbe5ca..bea7642 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: specifier: ^0.22.0 version: 0.22.3(@hocuspocus/provider@2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(pdfjs-dist@4.6.82)(typescript@5.9.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.2)(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(yjs@13.6.19) devDependencies: + '@commitlint/config-conventional': + specifier: ^20.0.0 + version: 20.0.0 '@eslint/js': specifier: ^9.36.0 version: 9.37.0 @@ -193,6 +196,14 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} + '@commitlint/config-conventional@20.0.0': + resolution: {integrity: sha512-q7JroPIkDBtyOkVe9Bca0p7kAUYxZMxkrBArCfuD3yN4KjRAenP9PmYwnn7rsw8Q+hHq1QB2BRmBh0/Z19ZoJw==} + engines: {node: '>=v18'} + + '@commitlint/types@20.0.0': + resolution: {integrity: sha512-bVUNBqG6aznYcYjTjnc3+Cat/iBgbgpflxbIBTnsHTX0YVpnmINPEkSRWymT2Q8aSH3Y7aKnEbunilkYe8TybA==} + engines: {node: '>=v18'} + '@css-render/plugin-bem@0.15.14': resolution: {integrity: sha512-QK513CJ7yEQxm/P3EwsI+d+ha8kSOcjGvD6SevM41neEMxdULE+18iuQK6tEChAWMOQNQPLG/Rw3Khb69r5neg==} peerDependencies: @@ -835,6 +846,9 @@ packages: '@types/chai@5.2.2': resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + '@types/conventional-commits-parser@5.0.1': + resolution: {integrity: sha512-7uz5EHdzz2TqoMfV7ee61Egf5y6NkcO4FB/1iCCQnbeiI1F3xzv3vK5dBCXUCLQgGYS+mUeigK1iKQzvED+QnQ==} + '@types/deep-eql@4.0.2': resolution: {integrity: sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==} @@ -1347,6 +1361,10 @@ packages: resolution: {integrity: sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==} engines: {node: '>=18'} + conventional-changelog-conventionalcommits@7.0.2: + resolution: {integrity: sha512-NKXYmMR/Hr1DevQegFB4MwfM5Vv0m4UIxKZTTYuD98lpTknaZlSRrDOG4X7wIXpGkfsYxZTghUN+Qq+T0YQI7w==} + engines: {node: '>=16'} + conventional-changelog-writer@8.2.0: resolution: {integrity: sha512-Y2aW4596l9AEvFJRwFGJGiQjt2sBYTjPD18DdvxX9Vpz0Z7HQ+g1Z+6iYDAm1vR3QOJrDBkRHixHK/+FhkR6Pw==} engines: {node: '>=18'} @@ -3898,6 +3916,16 @@ snapshots: '@colors/colors@1.5.0': optional: true + '@commitlint/config-conventional@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + conventional-changelog-conventionalcommits: 7.0.2 + + '@commitlint/types@20.0.0': + dependencies: + '@types/conventional-commits-parser': 5.0.1 + chalk: 5.6.2 + '@css-render/plugin-bem@0.15.14(css-render@0.15.14)': dependencies: css-render: 0.15.14 @@ -4525,6 +4553,10 @@ snapshots: dependencies: '@types/deep-eql': 4.0.2 + '@types/conventional-commits-parser@5.0.1': + dependencies: + '@types/node': 24.7.0 + '@types/deep-eql@4.0.2': {} '@types/estree@1.0.8': {} @@ -5149,6 +5181,10 @@ snapshots: dependencies: compare-func: 2.0.0 + conventional-changelog-conventionalcommits@7.0.2: + dependencies: + compare-func: 2.0.0 + conventional-changelog-writer@8.2.0: dependencies: conventional-commits-filter: 5.0.0 From 4c2aa620688df52e02345a61636ed4d2cb011a4d Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 8 Oct 2025 13:53:23 -0300 Subject: [PATCH 4/6] chore: update commitlint configuration to enforce line length rules for body and footer --- commitlint.config.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/commitlint.config.js b/commitlint.config.js index 85f0985..2c1e5d9 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,4 +1,6 @@ export default { extends: ['@commitlint/config-conventional'], + 'body-max-line-length': [0, 'always'], + 'footer-max-line-length': [0, 'always'], }; From ef383cb764e74bcccaa0ee56ed87895e264475be Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 8 Oct 2025 14:01:45 -0300 Subject: [PATCH 5/6] chore: add @commitlint/cli to devDependencies and update GitHub workflow to use pnpm exec for commitlint --- .github/workflows/pr-validation.yml | 2 +- package.json | 1 + pnpm-lock.yaml | 465 +++++++++++++++++++++++++--- 3 files changed, 420 insertions(+), 48 deletions(-) diff --git a/.github/workflows/pr-validation.yml b/.github/workflows/pr-validation.yml index dba754e..0963925 100644 --- a/.github/workflows/pr-validation.yml +++ b/.github/workflows/pr-validation.yml @@ -37,7 +37,7 @@ jobs: - name: Validate commits run: | - pnpm dlx commitlint \ + pnpm exec commitlint \ --from ${{ github.event.pull_request.base.sha }} \ --to ${{ github.event.pull_request.head.sha }} diff --git a/package.json b/package.json index f0b6c04..22750af 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,7 @@ "superdoc": "^0.22.0" }, "devDependencies": { + "@commitlint/cli": "^20.1.0", "@commitlint/config-conventional": "^20.0.0", "@eslint/js": "^9.36.0", "@semantic-release/changelog": "^6.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bea7642..cfe1955 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -12,6 +12,9 @@ importers: specifier: ^0.22.0 version: 0.22.3(@hocuspocus/provider@2.15.3(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(pdfjs-dist@4.6.82)(typescript@5.9.3)(y-prosemirror@1.3.7(prosemirror-model@1.25.3)(prosemirror-state@1.4.3)(prosemirror-view@1.41.2)(y-protocols@1.0.6(yjs@13.6.19))(yjs@13.6.19))(yjs@13.6.19) devDependencies: + '@commitlint/cli': + specifier: ^20.1.0 + version: 20.1.0(@types/node@24.7.0)(typescript@5.9.3) '@commitlint/config-conventional': specifier: ^20.0.0 version: 20.0.0 @@ -44,16 +47,16 @@ importers: version: 19.2.1(@types/react@19.2.2) '@vitejs/plugin-react': specifier: ^5.0.4 - version: 5.0.4(vite@7.1.9(@types/node@24.7.0)) + version: 5.0.4(vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1)) eslint: specifier: ^9.36.0 - version: 9.37.0 + version: 9.37.0(jiti@2.6.1) eslint-plugin-react: specifier: ^7.37.5 - version: 7.37.5(eslint@9.37.0) + version: 7.37.5(eslint@9.37.0(jiti@2.6.1)) eslint-plugin-react-hooks: specifier: ^6.1.0 - version: 6.1.1(eslint@9.37.0) + version: 6.1.1(eslint@9.37.0(jiti@2.6.1)) husky: specifier: ^9.1.7 version: 9.1.7 @@ -77,16 +80,16 @@ importers: version: 5.9.3 typescript-eslint: specifier: ^8.44.1 - version: 8.46.0(eslint@9.37.0)(typescript@5.9.3) + version: 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) vite: specifier: ^7.1.7 - version: 7.1.9(@types/node@24.7.0) + version: 7.1.9(@types/node@24.7.0)(jiti@2.6.1) vite-plugin-dts: specifier: ^4.5.4 - version: 4.5.4(@types/node@24.7.0)(rollup@4.52.4)(typescript@5.9.3)(vite@7.1.9(@types/node@24.7.0)) + version: 4.5.4(@types/node@24.7.0)(rollup@4.52.4)(typescript@5.9.3)(vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1)) vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@24.7.0)(jsdom@27.0.0(postcss@8.5.6)) + version: 3.2.4(@types/node@24.7.0)(jiti@2.6.1)(jsdom@27.0.0(postcss@8.5.6)) packages: @@ -196,10 +199,71 @@ packages: resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} + '@commitlint/cli@20.1.0': + resolution: {integrity: sha512-pW5ujjrOovhq5RcYv5xCpb4GkZxkO2+GtOdBW2/qrr0Ll9tl3PX0aBBobGQl3mdZUbOBgwAexEQLeH6uxL0VYg==} + engines: {node: '>=v18'} + hasBin: true + '@commitlint/config-conventional@20.0.0': resolution: {integrity: sha512-q7JroPIkDBtyOkVe9Bca0p7kAUYxZMxkrBArCfuD3yN4KjRAenP9PmYwnn7rsw8Q+hHq1QB2BRmBh0/Z19ZoJw==} engines: {node: '>=v18'} + '@commitlint/config-validator@20.0.0': + resolution: {integrity: sha512-BeyLMaRIJDdroJuYM2EGhDMGwVBMZna9UiIqV9hxj+J551Ctc6yoGuGSmghOy/qPhBSuhA6oMtbEiTmxECafsg==} + engines: {node: '>=v18'} + + '@commitlint/ensure@20.0.0': + resolution: {integrity: sha512-WBV47Fffvabe68n+13HJNFBqiMH5U1Ryls4W3ieGwPC0C7kJqp3OVQQzG2GXqOALmzrgAB+7GXmyy8N9ct8/Fg==} + engines: {node: '>=v18'} + + '@commitlint/execute-rule@20.0.0': + resolution: {integrity: sha512-xyCoOShoPuPL44gVa+5EdZsBVao/pNzpQhkzq3RdtlFdKZtjWcLlUFQHSWBuhk5utKYykeJPSz2i8ABHQA+ZZw==} + engines: {node: '>=v18'} + + '@commitlint/format@20.0.0': + resolution: {integrity: sha512-zrZQXUcSDmQ4eGGrd+gFESiX0Rw+WFJk7nW4VFOmxub4mAATNKBQ4vNw5FgMCVehLUKG2OT2LjOqD0Hk8HvcRg==} + engines: {node: '>=v18'} + + '@commitlint/is-ignored@20.0.0': + resolution: {integrity: sha512-ayPLicsqqGAphYIQwh9LdAYOVAQ9Oe5QCgTNTj+BfxZb9b/JW222V5taPoIBzYnAP0z9EfUtljgBk+0BN4T4Cw==} + engines: {node: '>=v18'} + + '@commitlint/lint@20.0.0': + resolution: {integrity: sha512-kWrX8SfWk4+4nCexfLaQT3f3EcNjJwJBsSZ5rMBw6JCd6OzXufFHgel2Curos4LKIxwec9WSvs2YUD87rXlxNQ==} + engines: {node: '>=v18'} + + '@commitlint/load@20.1.0': + resolution: {integrity: sha512-qo9ER0XiAimATQR5QhvvzePfeDfApi/AFlC1G+YN+ZAY8/Ua6IRrDrxRvQAr+YXUKAxUsTDSp9KXeXLBPsNRWg==} + engines: {node: '>=v18'} + + '@commitlint/message@20.0.0': + resolution: {integrity: sha512-gLX4YmKnZqSwkmSB9OckQUrI5VyXEYiv3J5JKZRxIp8jOQsWjZgHSG/OgEfMQBK9ibdclEdAyIPYggwXoFGXjQ==} + engines: {node: '>=v18'} + + '@commitlint/parse@20.0.0': + resolution: {integrity: sha512-j/PHCDX2bGM5xGcWObOvpOc54cXjn9g6xScXzAeOLwTsScaL4Y+qd0pFC6HBwTtrH92NvJQc+2Lx9HFkVi48cg==} + engines: {node: '>=v18'} + + '@commitlint/read@20.0.0': + resolution: {integrity: sha512-Ti7Y7aEgxsM1nkwA4ZIJczkTFRX/+USMjNrL9NXwWQHqNqrBX2iMi+zfuzZXqfZ327WXBjdkRaytJ+z5vNqTOA==} + engines: {node: '>=v18'} + + '@commitlint/resolve-extends@20.1.0': + resolution: {integrity: sha512-cxKXQrqHjZT3o+XPdqDCwOWVFQiae++uwd9dUBC7f2MdV58ons3uUvASdW7m55eat5sRiQ6xUHyMWMRm6atZWw==} + engines: {node: '>=v18'} + + '@commitlint/rules@20.0.0': + resolution: {integrity: sha512-gvg2k10I/RfvHn5I5sxvVZKM1fl72Sqrv2YY/BnM7lMHcYqO0E2jnRWoYguvBfEcZ39t+rbATlciggVe77E4zA==} + engines: {node: '>=v18'} + + '@commitlint/to-lines@20.0.0': + resolution: {integrity: sha512-2l9gmwiCRqZNWgV+pX1X7z4yP0b3ex/86UmUFgoRt672Ez6cAM2lOQeHFRUTuE6sPpi8XBCGnd8Kh3bMoyHwJw==} + engines: {node: '>=v18'} + + '@commitlint/top-level@20.0.0': + resolution: {integrity: sha512-drXaPSP2EcopukrUXvUXmsQMu3Ey/FuJDc/5oiW4heoCfoE5BdLQyuc7veGeE3aoQaTVqZnh4D5WTWe2vefYKg==} + engines: {node: '>=v18'} + '@commitlint/types@20.0.0': resolution: {integrity: sha512-bVUNBqG6aznYcYjTjnc3+Cat/iBgbgpflxbIBTnsHTX0YVpnmINPEkSRWymT2Q8aSH3Y7aKnEbunilkYe8TybA==} engines: {node: '>=v18'} @@ -1037,6 +1101,10 @@ packages: '@vue/shared@3.5.22': resolution: {integrity: sha512-F4yc6palwq3TT0u+FYf0Ns4Tfl9GRFURDN2gWG7L1ecIaS/4fCIuFOjMTnCyjsu/OK6vaDKLCrGAa+KvvH+h4w==} + JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + abbrev@1.1.1: resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} @@ -1357,6 +1425,10 @@ packages: console-control-strings@1.1.0: resolution: {integrity: sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==} + conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + conventional-changelog-angular@8.0.0: resolution: {integrity: sha512-CLf+zr6St0wIxos4bmaKHRXWAcsCXrJU6F4VdNDrGRK3B8LDLKoX3zuMV5GhtbGkVR/LohZ6MT6im43vZLSjmA==} engines: {node: '>=18'} @@ -1374,6 +1446,11 @@ packages: resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==} engines: {node: '>=18'} + conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + conventional-commits-parser@6.2.0: resolution: {integrity: sha512-uLnoLeIW4XaoFtH37qEcg/SXMJmKF4vi7V0H2rnPueg+VEtFGA/asSCNTcq4M/GQ6QmlzchAEtOoDTtKqWeHag==} engines: {node: '>=18'} @@ -1389,6 +1466,14 @@ packages: core-util-is@1.0.3: resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cosmiconfig-typescript-loader@6.1.0: + resolution: {integrity: sha512-tJ1w35ZRUiM5FeTzT7DtYWAFFv37ZLqSRkGi2oeCK1gPhvaWjkAtfXvLmvE1pRfxxp9aQo6ba/Pvg1dKj05D4g==} + engines: {node: '>=v18'} + peerDependencies: + '@types/node': '*' + cosmiconfig: '>=9' + typescript: '>=5' + cosmiconfig@9.0.0: resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} engines: {node: '>=14'} @@ -1430,6 +1515,10 @@ packages: csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + dargs@8.1.0: + resolution: {integrity: sha512-wAV9QHOsNbwnWdNW2FYvE1P56wtgSbM+3SZcdGiWQILwVjACCXDCI3Ai8QlCjMDB8YK5zySiXZYBiwGmNY3lnw==} + engines: {node: '>=12'} + data-urls@5.0.0: resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} engines: {node: '>=18'} @@ -1765,6 +1854,10 @@ packages: resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} engines: {node: '>=10'} + find-up@7.0.0: + resolution: {integrity: sha512-YyZM99iHrqLKjmt4LJDj58KI+fYyufRLBSYcqycxf//KpBk9FoewoGX0450m9nB44qrZnovzC2oeP5hUibxc/g==} + engines: {node: '>=18'} + find-versions@6.0.0: resolution: {integrity: sha512-2kCCtc+JvcZ86IGAz3Z2Y0A1baIz9fL31pH/0S1IqZr9Iwnjq8izfPtrCyQKO6TLMPELLsQMre7VDqeIKCsHkA==} engines: {node: '>=18'} @@ -1869,6 +1962,11 @@ packages: git-log-parser@1.2.1: resolution: {integrity: sha512-PI+sPDvHXNPl5WNOErAK05s3j0lgwUzMN6o8cyQrDaKfT3qd7TmNJKeXX+SknI5I0QhG5fVPAEwSY4tRGDtYoQ==} + git-raw-commits@4.0.0: + resolution: {integrity: sha512-ICsMM1Wk8xSGMowkOmPrzo2Fgmfo4bMHLNX6ytHjajRJUqvHOw/TFapQ+QG75c3X/tTDDhOSRPGC52dDbNM8FQ==} + engines: {node: '>=16'} + hasBin: true + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -1881,6 +1979,10 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported + global-directory@4.0.1: + resolution: {integrity: sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==} + engines: {node: '>=18'} + globals@14.0.0: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} @@ -2054,6 +2156,10 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + ini@4.1.1: + resolution: {integrity: sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -2180,6 +2286,10 @@ packages: resolution: {integrity: sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==} engines: {node: '>= 0.4'} + is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + is-typed-array@1.1.15: resolution: {integrity: sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==} engines: {node: '>= 0.4'} @@ -2224,6 +2334,10 @@ packages: resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==} engines: {node: '>= 0.6.0'} + jiti@2.6.1: + resolution: {integrity: sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==} + hasBin: true + jju@1.4.0: resolution: {integrity: sha512-8wb9Yw966OSxApiCt0K3yNJL8pnNeIv+OEq2YMidz4FKP6nonSRoOXc80iXY4JaN2FC11B9qsNmDsm+ZOfMROA==} @@ -2289,6 +2403,10 @@ packages: jsonfile@6.2.0: resolution: {integrity: sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==} + jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + jsx-ast-utils@3.3.5: resolution: {integrity: sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==} engines: {node: '>=4.0'} @@ -2327,9 +2445,16 @@ packages: resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} engines: {node: '>=10'} + locate-path@7.2.0: + resolution: {integrity: sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + lodash.camelcase@4.3.0: + resolution: {integrity: sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==} + lodash.capitalize@4.2.1: resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==} @@ -2342,12 +2467,30 @@ packages: lodash.isstring@4.0.1: resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + lodash.kebabcase@4.1.1: + resolution: {integrity: sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==} + lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + lodash.mergewith@4.6.2: + resolution: {integrity: sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==} + + lodash.snakecase@4.1.1: + resolution: {integrity: sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==} + + lodash.startcase@4.4.0: + resolution: {integrity: sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==} + + lodash.uniq@4.5.0: + resolution: {integrity: sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==} + lodash.uniqby@4.7.0: resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} + lodash.upperfirst@4.3.1: + resolution: {integrity: sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -2401,6 +2544,10 @@ packages: mdn-data@2.12.2: resolution: {integrity: sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==} + meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + meow@13.2.0: resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==} engines: {node: '>=18'} @@ -2702,6 +2849,10 @@ packages: resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} engines: {node: '>=10'} + p-limit@4.0.0: + resolution: {integrity: sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-locate@2.0.0: resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} engines: {node: '>=4'} @@ -2710,6 +2861,10 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-locate@6.0.0: + resolution: {integrity: sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + p-map@7.0.3: resolution: {integrity: sha512-VkndIv2fIB99swvQoA65bm+fsmt6UNdGeIB0oxBs+WhAhdh08QA04JXpI7rbB9r08/nkbysKoya9rtDERYOYMA==} engines: {node: '>=18'} @@ -2769,6 +2924,10 @@ packages: resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} engines: {node: '>=8'} + path-exists@5.0.0: + resolution: {integrity: sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + path-is-absolute@1.0.1: resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} engines: {node: '>=0.10.0'} @@ -3151,6 +3310,10 @@ packages: split2@1.0.0: resolution: {integrity: sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==} + split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + sprintf-js@1.0.3: resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} @@ -3282,6 +3445,10 @@ packages: resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} engines: {node: '>=14.16'} + text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -3292,6 +3459,9 @@ packages: through2@2.0.5: resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + time-span@5.1.0: resolution: {integrity: sha512-75voc/9G4rDIJleOo4jPvN4/YC4GRZrY8yy1uU4lwrB3XEQbWve8zXoO5No4eFrGcTAMYyoY67p8jRQdtA1HbA==} engines: {node: '>=12'} @@ -3302,6 +3472,9 @@ packages: tinyexec@0.3.2: resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + tinyexec@1.0.1: + resolution: {integrity: sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw==} + tinyglobby@0.2.15: resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} engines: {node: '>=12.0.0'} @@ -3756,6 +3929,10 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + yocto-queue@1.2.1: + resolution: {integrity: sha512-AyeEbWOu/TAXdxlV9wmGcR0+yh2j3vYPGOECcIj2S7MkrLyC7ne+oye2BKTItt0ii2PHk4cDy+95+LshzbXnGg==} + engines: {node: '>=12.20'} + yoctocolors@2.1.2: resolution: {integrity: sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==} engines: {node: '>=18'} @@ -3916,11 +4093,111 @@ snapshots: '@colors/colors@1.5.0': optional: true + '@commitlint/cli@20.1.0(@types/node@24.7.0)(typescript@5.9.3)': + dependencies: + '@commitlint/format': 20.0.0 + '@commitlint/lint': 20.0.0 + '@commitlint/load': 20.1.0(@types/node@24.7.0)(typescript@5.9.3) + '@commitlint/read': 20.0.0 + '@commitlint/types': 20.0.0 + tinyexec: 1.0.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + '@commitlint/config-conventional@20.0.0': dependencies: '@commitlint/types': 20.0.0 conventional-changelog-conventionalcommits: 7.0.2 + '@commitlint/config-validator@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + ajv: 8.13.0 + + '@commitlint/ensure@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + lodash.camelcase: 4.3.0 + lodash.kebabcase: 4.1.1 + lodash.snakecase: 4.1.1 + lodash.startcase: 4.4.0 + lodash.upperfirst: 4.3.1 + + '@commitlint/execute-rule@20.0.0': {} + + '@commitlint/format@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + chalk: 5.6.2 + + '@commitlint/is-ignored@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + semver: 7.7.3 + + '@commitlint/lint@20.0.0': + dependencies: + '@commitlint/is-ignored': 20.0.0 + '@commitlint/parse': 20.0.0 + '@commitlint/rules': 20.0.0 + '@commitlint/types': 20.0.0 + + '@commitlint/load@20.1.0(@types/node@24.7.0)(typescript@5.9.3)': + dependencies: + '@commitlint/config-validator': 20.0.0 + '@commitlint/execute-rule': 20.0.0 + '@commitlint/resolve-extends': 20.1.0 + '@commitlint/types': 20.0.0 + chalk: 5.6.2 + cosmiconfig: 9.0.0(typescript@5.9.3) + cosmiconfig-typescript-loader: 6.1.0(@types/node@24.7.0)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3) + lodash.isplainobject: 4.0.6 + lodash.merge: 4.6.2 + lodash.uniq: 4.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + + '@commitlint/message@20.0.0': {} + + '@commitlint/parse@20.0.0': + dependencies: + '@commitlint/types': 20.0.0 + conventional-changelog-angular: 7.0.0 + conventional-commits-parser: 5.0.0 + + '@commitlint/read@20.0.0': + dependencies: + '@commitlint/top-level': 20.0.0 + '@commitlint/types': 20.0.0 + git-raw-commits: 4.0.0 + minimist: 1.2.8 + tinyexec: 1.0.1 + + '@commitlint/resolve-extends@20.1.0': + dependencies: + '@commitlint/config-validator': 20.0.0 + '@commitlint/types': 20.0.0 + global-directory: 4.0.1 + import-meta-resolve: 4.2.0 + lodash.mergewith: 4.6.2 + resolve-from: 5.0.0 + + '@commitlint/rules@20.0.0': + dependencies: + '@commitlint/ensure': 20.0.0 + '@commitlint/message': 20.0.0 + '@commitlint/to-lines': 20.0.0 + '@commitlint/types': 20.0.0 + + '@commitlint/to-lines@20.0.0': {} + + '@commitlint/top-level@20.0.0': + dependencies: + find-up: 7.0.0 + '@commitlint/types@20.0.0': dependencies: '@types/conventional-commits-parser': 5.0.1 @@ -4038,9 +4315,9 @@ snapshots: '@esbuild/win32-x64@0.25.10': optional: true - '@eslint-community/eslint-utils@4.9.0(eslint@9.37.0)': + '@eslint-community/eslint-utils@4.9.0(eslint@9.37.0(jiti@2.6.1))': dependencies: - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.12.1': {} @@ -4598,15 +4875,15 @@ snapshots: dependencies: csstype: 3.1.3 - '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.46.0(eslint@9.37.0)(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.46.0 - '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0)(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.0(eslint@9.37.0)(typescript@5.9.3) + '@typescript-eslint/type-utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.46.0 - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) graphemer: 1.4.0 ignore: 7.0.5 natural-compare: 1.4.0 @@ -4615,14 +4892,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.0(eslint@9.37.0)(typescript@5.9.3)': + '@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.46.0 '@typescript-eslint/types': 8.46.0 '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) '@typescript-eslint/visitor-keys': 8.46.0 debug: 4.4.3 - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4645,13 +4922,13 @@ snapshots: dependencies: typescript: 5.9.3 - '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0)(typescript@5.9.3)': + '@typescript-eslint/type-utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.46.0 '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.0(eslint@9.37.0)(typescript@5.9.3) + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) debug: 4.4.3 - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) ts-api-utils: 2.1.0(typescript@5.9.3) typescript: 5.9.3 transitivePeerDependencies: @@ -4675,13 +4952,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.46.0(eslint@9.37.0)(typescript@5.9.3)': + '@typescript-eslint/utils@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3)': dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@typescript-eslint/scope-manager': 8.46.0 '@typescript-eslint/types': 8.46.0 '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -4691,7 +4968,7 @@ snapshots: '@typescript-eslint/types': 8.46.0 eslint-visitor-keys: 4.2.1 - '@vitejs/plugin-react@5.0.4(vite@7.1.9(@types/node@24.7.0))': + '@vitejs/plugin-react@5.0.4(vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1))': dependencies: '@babel/core': 7.28.4 '@babel/plugin-transform-react-jsx-self': 7.27.1(@babel/core@7.28.4) @@ -4699,7 +4976,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.38 '@types/babel__core': 7.20.5 react-refresh: 0.17.0 - vite: 7.1.9(@types/node@24.7.0) + vite: 7.1.9(@types/node@24.7.0)(jiti@2.6.1) transitivePeerDependencies: - supports-color @@ -4711,13 +4988,13 @@ snapshots: chai: 5.3.3 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.0))': + '@vitest/mocker@3.2.4(vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1))': dependencies: '@vitest/spy': 3.2.4 estree-walker: 3.0.3 magic-string: 0.30.19 optionalDependencies: - vite: 7.1.9(@types/node@24.7.0) + vite: 7.1.9(@types/node@24.7.0)(jiti@2.6.1) '@vitest/pretty-format@3.2.4': dependencies: @@ -4831,6 +5108,11 @@ snapshots: '@vue/shared@3.5.22': {} + JSONStream@1.3.5: + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + abbrev@1.1.1: optional: true @@ -5177,6 +5459,10 @@ snapshots: console-control-strings@1.1.0: optional: true + conventional-changelog-angular@7.0.0: + dependencies: + compare-func: 2.0.0 + conventional-changelog-angular@8.0.0: dependencies: compare-func: 2.0.0 @@ -5194,6 +5480,13 @@ snapshots: conventional-commits-filter@5.0.0: {} + conventional-commits-parser@5.0.0: + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + conventional-commits-parser@6.2.0: dependencies: meow: 13.2.0 @@ -5204,6 +5497,13 @@ snapshots: core-util-is@1.0.3: {} + cosmiconfig-typescript-loader@6.1.0(@types/node@24.7.0)(cosmiconfig@9.0.0(typescript@5.9.3))(typescript@5.9.3): + dependencies: + '@types/node': 24.7.0 + cosmiconfig: 9.0.0(typescript@5.9.3) + jiti: 2.6.1 + typescript: 5.9.3 + cosmiconfig@9.0.0(typescript@5.9.3): dependencies: env-paths: 2.2.1 @@ -5252,6 +5552,8 @@ snapshots: csstype@3.1.3: {} + dargs@8.1.0: {} + data-urls@5.0.0: dependencies: whatwg-mimetype: 4.0.0 @@ -5516,17 +5818,17 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-plugin-react-hooks@6.1.1(eslint@9.37.0): + eslint-plugin-react-hooks@6.1.1(eslint@9.37.0(jiti@2.6.1)): dependencies: '@babel/core': 7.28.4 '@babel/parser': 7.28.4 - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) zod: 4.1.12 zod-validation-error: 4.0.2(zod@4.1.12) transitivePeerDependencies: - supports-color - eslint-plugin-react@7.37.5(eslint@9.37.0): + eslint-plugin-react@7.37.5(eslint@9.37.0(jiti@2.6.1)): dependencies: array-includes: 3.1.9 array.prototype.findlast: 1.2.5 @@ -5534,7 +5836,7 @@ snapshots: array.prototype.tosorted: 1.1.4 doctrine: 2.1.0 es-iterator-helpers: 1.2.1 - eslint: 9.37.0 + eslint: 9.37.0(jiti@2.6.1) estraverse: 5.3.0 hasown: 2.0.2 jsx-ast-utils: 3.3.5 @@ -5557,9 +5859,9 @@ snapshots: eslint-visitor-keys@4.2.1: {} - eslint@9.37.0: + eslint@9.37.0(jiti@2.6.1): dependencies: - '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0) + '@eslint-community/eslint-utils': 4.9.0(eslint@9.37.0(jiti@2.6.1)) '@eslint-community/regexpp': 4.12.1 '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.4.0 @@ -5594,6 +5896,8 @@ snapshots: minimatch: 3.1.2 natural-compare: 1.4.0 optionator: 0.9.4 + optionalDependencies: + jiti: 2.6.1 transitivePeerDependencies: - supports-color @@ -5719,6 +6023,12 @@ snapshots: locate-path: 6.0.0 path-exists: 4.0.0 + find-up@7.0.0: + dependencies: + locate-path: 7.2.0 + path-exists: 5.0.0 + unicorn-magic: 0.1.0 + find-versions@6.0.0: dependencies: semver-regex: 4.0.5 @@ -5848,6 +6158,12 @@ snapshots: through2: 2.0.5 traverse: 0.6.8 + git-raw-commits@4.0.0: + dependencies: + dargs: 8.1.0 + meow: 12.1.1 + split2: 4.2.0 + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -5865,6 +6181,10 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + global-directory@4.0.1: + dependencies: + ini: 4.1.1 + globals@14.0.0: {} globalthis@1.0.4: @@ -6018,6 +6338,8 @@ snapshots: ini@1.3.8: {} + ini@4.1.1: {} + internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -6140,6 +6462,10 @@ snapshots: has-symbols: 1.1.0 safe-regex-test: 1.1.0 + is-text-path@2.0.0: + dependencies: + text-extensions: 2.4.0 + is-typed-array@1.1.15: dependencies: which-typed-array: 1.1.19 @@ -6184,6 +6510,8 @@ snapshots: java-properties@1.0.2: {} + jiti@2.6.1: {} + jju@1.4.0: {} js-tokens@4.0.0: {} @@ -6276,6 +6604,8 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 + jsonparse@1.3.1: {} + jsx-ast-utils@3.3.5: dependencies: array-includes: 3.1.9 @@ -6322,8 +6652,14 @@ snapshots: dependencies: p-locate: 5.0.0 + locate-path@7.2.0: + dependencies: + p-locate: 6.0.0 + lodash-es@4.17.21: {} + lodash.camelcase@4.3.0: {} + lodash.capitalize@4.2.1: {} lodash.escaperegexp@4.1.2: {} @@ -6332,10 +6668,22 @@ snapshots: lodash.isstring@4.0.1: {} + lodash.kebabcase@4.1.1: {} + lodash.merge@4.6.2: {} + lodash.mergewith@4.6.2: {} + + lodash.snakecase@4.1.1: {} + + lodash.startcase@4.4.0: {} + + lodash.uniq@4.5.0: {} + lodash.uniqby@4.7.0: {} + lodash.upperfirst@4.3.1: {} + lodash@4.17.21: {} loose-envify@1.4.0: @@ -6384,6 +6732,8 @@ snapshots: mdn-data@2.12.2: {} + meow@12.1.1: {} + meow@13.2.0: {} merge-stream@2.0.0: {} @@ -6627,6 +6977,10 @@ snapshots: dependencies: yocto-queue: 0.1.0 + p-limit@4.0.0: + dependencies: + yocto-queue: 1.2.1 + p-locate@2.0.0: dependencies: p-limit: 1.3.0 @@ -6635,6 +6989,10 @@ snapshots: dependencies: p-limit: 3.1.0 + p-locate@6.0.0: + dependencies: + p-limit: 4.0.0 + p-map@7.0.3: {} p-reduce@2.1.0: {} @@ -6685,6 +7043,8 @@ snapshots: path-exists@4.0.0: {} + path-exists@5.0.0: {} + path-is-absolute@1.0.1: {} path-key@3.1.1: {} @@ -7148,6 +7508,8 @@ snapshots: dependencies: through2: 2.0.5 + split2@4.2.0: {} + sprintf-js@1.0.3: {} stackback@0.0.2: {} @@ -7317,6 +7679,8 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 + text-extensions@2.4.0: {} + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -7330,6 +7694,8 @@ snapshots: readable-stream: 2.3.8 xtend: 4.0.2 + through@2.3.8: {} + time-span@5.1.0: dependencies: convert-hrtime: 5.0.0 @@ -7338,6 +7704,8 @@ snapshots: tinyexec@0.3.2: {} + tinyexec@1.0.1: {} + tinyglobby@0.2.15: dependencies: fdir: 6.5.0(picomatch@4.0.3) @@ -7437,13 +7805,13 @@ snapshots: possible-typed-array-names: 1.1.0 reflect.getprototypeof: 1.0.10 - typescript-eslint@8.46.0(eslint@9.37.0)(typescript@5.9.3): + typescript-eslint@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3): dependencies: - '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0)(typescript@5.9.3))(eslint@9.37.0)(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.0(eslint@9.37.0)(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.46.0(@typescript-eslint/parser@8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3))(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + '@typescript-eslint/parser': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/typescript-estree': 8.46.0(typescript@5.9.3) - '@typescript-eslint/utils': 8.46.0(eslint@9.37.0)(typescript@5.9.3) - eslint: 9.37.0 + '@typescript-eslint/utils': 8.46.0(eslint@9.37.0(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.37.0(jiti@2.6.1) typescript: 5.9.3 transitivePeerDependencies: - supports-color @@ -7506,13 +7874,13 @@ snapshots: evtd: 0.2.4 vue: 3.5.22(typescript@5.9.3) - vite-node@3.2.4(@types/node@24.7.0): + vite-node@3.2.4(@types/node@24.7.0)(jiti@2.6.1): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.1.9(@types/node@24.7.0) + vite: 7.1.9(@types/node@24.7.0)(jiti@2.6.1) transitivePeerDependencies: - '@types/node' - jiti @@ -7527,7 +7895,7 @@ snapshots: - tsx - yaml - vite-plugin-dts@4.5.4(@types/node@24.7.0)(rollup@4.52.4)(typescript@5.9.3)(vite@7.1.9(@types/node@24.7.0)): + vite-plugin-dts@4.5.4(@types/node@24.7.0)(rollup@4.52.4)(typescript@5.9.3)(vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1)): dependencies: '@microsoft/api-extractor': 7.53.0(@types/node@24.7.0) '@rollup/pluginutils': 5.3.0(rollup@4.52.4) @@ -7540,13 +7908,13 @@ snapshots: magic-string: 0.30.19 typescript: 5.9.3 optionalDependencies: - vite: 7.1.9(@types/node@24.7.0) + vite: 7.1.9(@types/node@24.7.0)(jiti@2.6.1) transitivePeerDependencies: - '@types/node' - rollup - supports-color - vite@7.1.9(@types/node@24.7.0): + vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1): dependencies: esbuild: 0.25.10 fdir: 6.5.0(picomatch@4.0.3) @@ -7557,12 +7925,13 @@ snapshots: optionalDependencies: '@types/node': 24.7.0 fsevents: 2.3.3 + jiti: 2.6.1 - vitest@3.2.4(@types/node@24.7.0)(jsdom@27.0.0(postcss@8.5.6)): + vitest@3.2.4(@types/node@24.7.0)(jiti@2.6.1)(jsdom@27.0.0(postcss@8.5.6)): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.0)) + '@vitest/mocker': 3.2.4(vite@7.1.9(@types/node@24.7.0)(jiti@2.6.1)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -7580,8 +7949,8 @@ snapshots: tinyglobby: 0.2.15 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 7.1.9(@types/node@24.7.0) - vite-node: 3.2.4(@types/node@24.7.0) + vite: 7.1.9(@types/node@24.7.0)(jiti@2.6.1) + vite-node: 3.2.4(@types/node@24.7.0)(jiti@2.6.1) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 24.7.0 @@ -7796,6 +8165,8 @@ snapshots: yocto-queue@0.1.0: {} + yocto-queue@1.2.1: {} + yoctocolors@2.1.2: {} zod-validation-error@4.0.2(zod@4.1.12): From 48e439df9d2472b0bfb6b21150e37f37ad169416 Mon Sep 17 00:00:00 2001 From: Caio Pizzol Date: Wed, 8 Oct 2025 14:06:50 -0300 Subject: [PATCH 6/6] chore: update commitlint configuration to include header-max-length rule --- commitlint.config.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/commitlint.config.js b/commitlint.config.js index 2c1e5d9..30ea2dc 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,6 +1,9 @@ export default { extends: ['@commitlint/config-conventional'], - 'body-max-line-length': [0, 'always'], - 'footer-max-line-length': [0, 'always'], + rules: { + 'body-max-line-length': [0, 'always'], + 'footer-max-line-length': [0, 'always'], + 'header-max-length': [0, 'always'], + }, };