From 3b6ae778fb325509310fd967271617e10a8d90e4 Mon Sep 17 00:00:00 2001 From: macbook Date: Thu, 28 May 2026 20:41:48 +0100 Subject: [PATCH] Portfolio Management --- docs/THREAD_CERTIFICATE_PORTFOLIO_UPDATES.md | 26 + pnpm-lock.yaml | 1340 +++-------------- src/app/components/courses/CourseReviews.tsx | 133 +- .../social/CertificateManagementPanel.tsx | 172 +++ .../social/GroupDiscussionThread.tsx | 147 +- .../__tests__/GroupDiscussionThread.test.tsx | 37 +- .../hooks/__tests__/useStudyGroups.test.tsx | 51 + src/app/hooks/useStudyGroups.tsx | 155 +- src/app/pages/StudyGroups.tsx | 24 +- .../__tests__/threadSupport.test.ts | 54 + src/lib/accessibility/threadSupport.ts | 74 + .../__tests__/portfolioManagement.test.ts | 51 + src/lib/reviews/portfolioManagement.ts | 43 + 13 files changed, 1095 insertions(+), 1212 deletions(-) create mode 100644 docs/THREAD_CERTIFICATE_PORTFOLIO_UPDATES.md create mode 100644 src/app/components/social/CertificateManagementPanel.tsx create mode 100644 src/lib/accessibility/__tests__/threadSupport.test.ts create mode 100644 src/lib/accessibility/threadSupport.ts create mode 100644 src/lib/reviews/__tests__/portfolioManagement.test.ts create mode 100644 src/lib/reviews/portfolioManagement.ts diff --git a/docs/THREAD_CERTIFICATE_PORTFOLIO_UPDATES.md b/docs/THREAD_CERTIFICATE_PORTFOLIO_UPDATES.md new file mode 100644 index 00000000..776a9547 --- /dev/null +++ b/docs/THREAD_CERTIFICATE_PORTFOLIO_UPDATES.md @@ -0,0 +1,26 @@ +# Thread, Certificate, and Portfolio Updates + +## Accessibility Thread Support + +- Discussion messages now support `parentId` so replies render as nested thread items. +- Thread rendering uses `role="list"` / `role="listitem"` and concise ARIA labels such as "Thread starter with 1 reply". +- Malformed thread data is handled defensively: missing parents and self-parented messages render as root messages. +- Visual nesting is capped to avoid runaway indentation and keep long conversations readable. + +## Discussion Forum Certificate Management + +- Study groups include a Certificates tab for issuing and revoking forum certificates. +- Certificate fingerprints are normalized and must be valid 64-character SHA-256 hex strings. +- Active duplicate fingerprints are rejected to prevent ambiguous trust state. +- Certificate state is derived as `active`, `expired`, or `revoked` and persists with the existing local study-group storage. + +## Review Portfolio Management + +- Course reviews can attach portfolio evidence such as projects, repositories, case studies, and certificates. +- Portfolio URLs are filtered to `http` and `https` protocols before rendering. +- Duplicate portfolio links are removed and review cards expose an accessible portfolio summary. + +## Verification + +- Unit coverage was added for thread tree construction, certificate lifecycle behavior, and portfolio validation. +- Existing study-group discussion tests were expanded to cover reply posting. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f467216a..c5a4c4a7 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -361,10 +361,6 @@ packages: resolution: {integrity: sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==} engines: {node: '>=6.9.0'} - '@babel/generator@7.29.1': - resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} - engines: {node: '>=6.9.0'} - '@babel/generator@7.29.7': resolution: {integrity: sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==} engines: {node: '>=6.9.0'} @@ -448,10 +444,6 @@ packages: resolution: {integrity: sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==} engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.28.6': - resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} - engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.29.7': resolution: {integrity: sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==} engines: {node: '>=6.9.0'} @@ -482,10 +474,6 @@ packages: resolution: {integrity: sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==} engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.27.1': - resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.29.7': resolution: {integrity: sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==} engines: {node: '>=6.9.0'} @@ -514,11 +502,6 @@ packages: resolution: {integrity: sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.29.2': - resolution: {integrity: sha512-4GgRzy/+fsBa72/RZVJmGKPmZu9Byn8o4MoLpmNe1m8ZfYnz5emHLQz3U4gLud6Zwl0RZIcgiLD7Uq7ySFuDLA==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/parser@7.29.7': resolution: {integrity: sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==} engines: {node: '>=6.0.0'} @@ -1032,10 +1015,6 @@ packages: resolution: {integrity: sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==} engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': - resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} - engines: {node: '>=6.9.0'} - '@babel/template@7.29.7': resolution: {integrity: sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==} engines: {node: '>=6.9.0'} @@ -1048,10 +1027,6 @@ packages: resolution: {integrity: sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==} engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': - resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} - engines: {node: '>=6.9.0'} - '@babel/types@7.29.7': resolution: {integrity: sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==} engines: {node: '>=6.9.0'} @@ -8012,15 +7987,15 @@ snapshots: '@babel/core@7.29.0': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) '@babel/helpers': 7.29.2 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@jridgewell/remapping': 2.3.5 convert-source-map: 2.0.0 debug: 4.4.3 @@ -8030,14 +8005,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/generator@7.29.1': - dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - jsesc: 3.1.0 - '@babel/generator@7.29.7': dependencies: '@babel/parser': 7.29.7 @@ -8048,7 +8015,7 @@ snapshots: '@babel/helper-annotate-as-pure@7.27.3': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@babel/helper-annotate-as-pure@7.29.7': dependencies: @@ -8099,7 +8066,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 debug: 4.4.3 lodash.debounce: 4.0.8 resolve: 1.22.12 @@ -8113,7 +8080,7 @@ snapshots: '@babel/helper-member-expression-to-functions@7.28.5': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -8127,7 +8094,7 @@ snapshots: '@babel/helper-module-imports@7.28.6': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -8142,7 +8109,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8158,14 +8125,12 @@ snapshots: '@babel/helper-optimise-call-expression@7.27.1': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@babel/helper-optimise-call-expression@7.29.7': dependencies: '@babel/types': 7.29.7 - '@babel/helper-plugin-utils@7.28.6': {} - '@babel/helper-plugin-utils@7.29.7': {} '@babel/helper-remap-async-to-generator@7.27.1(@babel/core@7.29.0)': @@ -8198,7 +8163,7 @@ snapshots: '@babel/helper-skip-transparent-expression-wrappers@7.27.1': dependencies: '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color @@ -8209,10 +8174,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-string-parser@7.27.1': {} - - '@babel/helper-string-parser@7.29.7': {} - '@babel/helper-string-parser@7.29.7': {} '@babel/helper-validator-identifier@7.28.5': {} @@ -8225,20 +8186,16 @@ snapshots: '@babel/helper-wrap-function@7.28.6': dependencies: - '@babel/template': 7.28.6 + '@babel/template': 7.29.7 '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 transitivePeerDependencies: - supports-color '@babel/helpers@7.29.2': dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 - - '@babel/parser@7.29.2': - dependencies: - '@babel/types': 7.29.0 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 '@babel/parser@7.29.7': dependencies: @@ -8247,7 +8204,7 @@ snapshots: '@babel/plugin-bugfix-firefox-class-in-computed-class-key@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8255,17 +8212,17 @@ snapshots: '@babel/plugin-bugfix-safari-class-field-initializer-scope@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 '@babel/plugin-transform-optional-chaining': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: @@ -8274,7 +8231,7 @@ snapshots: '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8286,42 +8243,42 @@ snapshots: '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-import-assertions@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-import-attributes@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-jsx@7.29.7(@babel/core@7.29.0)': dependencies: @@ -8331,42 +8288,42 @@ snapshots: '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-syntax-typescript@7.29.7(@babel/core@7.29.0)': dependencies: @@ -8377,17 +8334,17 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-arrow-functions@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-async-generator-functions@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) '@babel/traverse': 7.29.0 transitivePeerDependencies: @@ -8397,7 +8354,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-imports': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-remap-async-to-generator': 7.27.1(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -8405,18 +8362,18 @@ snapshots: '@babel/plugin-transform-block-scoped-functions@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-block-scoping@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-class-properties@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -8424,7 +8381,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -8434,7 +8391,7 @@ snapshots: '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-compilation-targets': 7.28.6 '@babel/helper-globals': 7.28.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) '@babel/traverse': 7.29.0 transitivePeerDependencies: @@ -8443,13 +8400,13 @@ snapshots: '@babel/plugin-transform-computed-properties@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/template': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/template': 7.29.7 '@babel/plugin-transform-destructuring@7.28.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8458,28 +8415,28 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-duplicate-keys@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-duplicate-named-capturing-groups-regex@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-dynamic-import@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-explicit-resource-management@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -8487,17 +8444,17 @@ snapshots: '@babel/plugin-transform-exponentiation-operator@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-export-namespace-from@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-for-of@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -8506,7 +8463,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8514,28 +8471,28 @@ snapshots: '@babel/plugin-transform-json-strings@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-logical-assignment-operators@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-member-expression-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-modules-amd@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -8543,7 +8500,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -8559,8 +8516,8 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 - '@babel/helper-validator-identifier': 7.28.5 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/helper-validator-identifier': 7.29.7 '@babel/traverse': 7.29.0 transitivePeerDependencies: - supports-color @@ -8569,7 +8526,7 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-module-transforms': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -8577,28 +8534,28 @@ snapshots: dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-new-target@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-nullish-coalescing-operator@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-numeric-separator@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-object-rest-spread@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-destructuring': 7.28.5(@babel/core@7.29.0) '@babel/plugin-transform-parameters': 7.27.7(@babel/core@7.29.0) '@babel/traverse': 7.29.0 @@ -8608,7 +8565,7 @@ snapshots: '@babel/plugin-transform-object-super@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-replace-supers': 7.28.6(@babel/core@7.29.0) transitivePeerDependencies: - supports-color @@ -8616,12 +8573,12 @@ snapshots: '@babel/plugin-transform-optional-catch-binding@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-optional-chaining@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -8629,13 +8586,13 @@ snapshots: '@babel/plugin-transform-parameters@7.27.7(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-private-methods@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color @@ -8644,14 +8601,14 @@ snapshots: '@babel/core': 7.29.0 '@babel/helper-annotate-as-pure': 7.27.3 '@babel/helper-create-class-features-plugin': 7.28.6(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 transitivePeerDependencies: - supports-color '@babel/plugin-transform-property-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-react-display-name@7.29.7(@babel/core@7.29.0)': dependencies: @@ -8685,28 +8642,28 @@ snapshots: '@babel/plugin-transform-regenerator@7.29.0(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-regexp-modifiers@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-reserved-words@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-shorthand-properties@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-spread@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 transitivePeerDependencies: - supports-color @@ -8714,17 +8671,17 @@ snapshots: '@babel/plugin-transform-sticky-regex@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-template-literals@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-typeof-symbol@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-typescript@7.29.7(@babel/core@7.29.0)': dependencies: @@ -8740,32 +8697,32 @@ snapshots: '@babel/plugin-transform-unicode-escapes@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-unicode-property-regex@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-unicode-regex@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/plugin-transform-unicode-sets-regex@7.28.6(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 '@babel/helper-create-regexp-features-plugin': 7.28.5(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/preset-env@7.29.2(@babel/core@7.29.0)': dependencies: '@babel/compat-data': 7.29.0 '@babel/core': 7.29.0 '@babel/helper-compilation-targets': 7.28.6 - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@babel/helper-validator-option': 7.27.1 '@babel/plugin-bugfix-firefox-class-in-computed-class-key': 7.28.5(@babel/core@7.29.0) '@babel/plugin-bugfix-safari-class-field-initializer-scope': 7.27.1(@babel/core@7.29.0) @@ -8839,8 +8796,8 @@ snapshots: '@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.28.6 - '@babel/types': 7.29.0 + '@babel/helper-plugin-utils': 7.29.7 + '@babel/types': 7.29.7 esutils: 2.0.3 '@babel/preset-react@7.29.7(@babel/core@7.29.0)': @@ -8868,12 +8825,6 @@ snapshots: '@babel/runtime@7.29.2': {} - '@babel/template@7.28.6': - dependencies: - '@babel/code-frame': 7.29.0 - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 - '@babel/template@7.29.7': dependencies: '@babel/code-frame': 7.29.7 @@ -8882,12 +8833,12 @@ snapshots: '@babel/traverse@7.29.0': dependencies: - '@babel/code-frame': 7.29.0 - '@babel/generator': 7.29.1 + '@babel/code-frame': 7.29.7 + '@babel/generator': 7.29.7 '@babel/helper-globals': 7.28.0 - '@babel/parser': 7.29.2 - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 debug: 4.4.3 transitivePeerDependencies: - supports-color @@ -8904,11 +8855,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.29.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - '@babel/types@7.29.7': dependencies: '@babel/helper-string-parser': 7.29.7 @@ -9608,7 +9554,6 @@ snapshots: '@noble/curves@1.9.7': dependencies: '@noble/hashes': 1.8.0 - optional: true '@noble/hashes@1.1.5': {} @@ -9869,674 +9814,112 @@ snapshots: optionalDependencies: '@types/react': 18.3.28 - '@img/sharp-linuxmusl-arm64@0.34.5': + '@radix-ui/react-toast@1.2.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@img/sharp-libvips-linuxmusl-arm64': 1.2.4 - optional: true + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@img/sharp-linuxmusl-x64@0.34.5': + '@radix-ui/react-tooltip@1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@radix-ui/primitive': 1.1.3 + '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) optionalDependencies: - '@img/sharp-libvips-linuxmusl-x64': 1.2.4 - optional: true + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@img/sharp-wasm32@0.34.5': + '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.28)(react@18.3.1)': dependencies: - '@emnapi/runtime': 1.10.0 - optional: true + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@img/sharp-win32-arm64@0.34.5': - optional: true + '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.28)(react@18.3.1) + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@img/sharp-win32-ia32@0.34.5': - optional: true + '@radix-ui/react-use-effect-event@0.0.2(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@img/sharp-win32-x64@0.34.5': - optional: true + '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@isaacs/cliui@9.0.0': {} + '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.28)(react@18.3.1)': + dependencies: + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@istanbuljs/load-nyc-config@1.1.0': + '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.28)(react@18.3.1)': dependencies: - camelcase: 5.3.1 - find-up: 4.1.0 - get-package-type: 0.1.0 - js-yaml: 3.14.2 - resolve-from: 5.0.0 + '@radix-ui/rect': 1.1.1 + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@istanbuljs/schema@0.1.6': {} + '@radix-ui/react-use-size@1.1.1(@types/react@18.3.28)(react@18.3.1)': + dependencies: + '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) + react: 18.3.1 + optionalDependencies: + '@types/react': 18.3.28 - '@jest/console@29.7.0': + '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: - '@jest/types': 29.6.3 - '@types/node': 20.19.39 - chalk: 4.1.2 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - slash: 3.0.0 + '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.28 + '@types/react-dom': 18.3.7(@types/react@18.3.28) - '@jest/core@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/reporters': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.19.39 - ansi-escapes: 4.3.2 - chalk: 4.1.2 - ci-info: 3.9.0 - exit: 0.1.2 - graceful-fs: 4.2.11 - jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.19.39) - jest-haste-map: 29.7.0 - jest-message-util: 29.7.0 - jest-regex-util: 29.6.3 - jest-resolve: 29.7.0 - jest-resolve-dependencies: 29.7.0 - jest-runner: 29.7.0 - jest-runtime: 29.7.0 - jest-snapshot: 29.7.0 - jest-util: 29.7.0 - jest-validate: 29.7.0 - jest-watcher: 29.7.0 - micromatch: 4.0.8 - pretty-format: 29.7.0 - slash: 3.0.0 - strip-ansi: 6.0.1 - transitivePeerDependencies: - - babel-plugin-macros - - supports-color - - ts-node - - '@jest/environment@29.7.0': - dependencies: - '@jest/fake-timers': 29.7.0 - '@jest/types': 29.6.3 - '@types/node': 20.19.39 - jest-mock: 29.7.0 - - '@jest/expect-utils@29.7.0': - dependencies: - jest-get-type: 29.6.3 - - '@jest/expect@29.7.0': - dependencies: - expect: 29.7.0 - jest-snapshot: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/fake-timers@29.7.0': - dependencies: - '@jest/types': 29.6.3 - '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.19.39 - jest-message-util: 29.7.0 - jest-mock: 29.7.0 - jest-util: 29.7.0 - - '@jest/globals@29.7.0': - dependencies: - '@jest/environment': 29.7.0 - '@jest/expect': 29.7.0 - '@jest/types': 29.6.3 - jest-mock: 29.7.0 - transitivePeerDependencies: - - supports-color - - '@jest/reporters@29.7.0': - dependencies: - '@bcoe/v8-coverage': 0.2.3 - '@jest/console': 29.7.0 - '@jest/test-result': 29.7.0 - '@jest/transform': 29.7.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.31 - '@types/node': 20.19.39 - chalk: 4.1.2 - collect-v8-coverage: 1.0.3 - exit: 0.1.2 - glob: 7.2.3 - graceful-fs: 4.2.11 - istanbul-lib-coverage: 3.2.2 - istanbul-lib-instrument: 6.0.3 - istanbul-lib-report: 3.0.1 - istanbul-lib-source-maps: 4.0.1 - istanbul-reports: 3.2.0 - jest-message-util: 29.7.0 - jest-util: 29.7.0 - jest-worker: 29.7.0 - slash: 3.0.0 - string-length: 4.0.2 - strip-ansi: 6.0.1 - v8-to-istanbul: 9.3.0 - transitivePeerDependencies: - - supports-color - - '@jest/schemas@29.6.3': - dependencies: - '@sinclair/typebox': 0.27.10 - - '@jest/source-map@29.6.3': - dependencies: - '@jridgewell/trace-mapping': 0.3.31 - callsites: 3.1.0 - graceful-fs: 4.2.11 - - '@jest/test-result@29.7.0': - dependencies: - '@jest/console': 29.7.0 - '@jest/types': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - collect-v8-coverage: 1.0.3 - - '@jest/test-sequencer@29.7.0': - dependencies: - '@jest/test-result': 29.7.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - slash: 3.0.0 - - '@jest/transform@29.7.0': - dependencies: - '@babel/core': 7.29.0 - '@jest/types': 29.6.3 - '@jridgewell/trace-mapping': 0.3.31 - babel-plugin-istanbul: 6.1.1 - chalk: 4.1.2 - convert-source-map: 2.0.0 - fast-json-stable-stringify: 2.1.0 - graceful-fs: 4.2.11 - jest-haste-map: 29.7.0 - jest-regex-util: 29.6.3 - jest-util: 29.7.0 - micromatch: 4.0.8 - pirates: 4.0.7 - slash: 3.0.0 - write-file-atomic: 4.0.2 - transitivePeerDependencies: - - supports-color - - '@jest/types@29.6.3': - dependencies: - '@jest/schemas': 29.6.3 - '@types/istanbul-lib-coverage': 2.0.6 - '@types/istanbul-reports': 3.0.4 - '@types/node': 20.19.39 - '@types/yargs': 17.0.35 - chalk: 4.1.2 - - '@jridgewell/gen-mapping@0.3.13': - dependencies: - '@jridgewell/sourcemap-codec': 1.5.5 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/remapping@2.3.5': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/resolve-uri@3.1.2': {} - - '@jridgewell/source-map@0.3.11': - dependencies: - '@jridgewell/gen-mapping': 0.3.13 - '@jridgewell/trace-mapping': 0.3.31 - - '@jridgewell/sourcemap-codec@1.5.5': {} - - '@jridgewell/trace-mapping@0.3.31': - dependencies: - '@jridgewell/resolve-uri': 3.1.2 - '@jridgewell/sourcemap-codec': 1.5.5 - - '@lit-labs/ssr-dom-shim@1.6.0': {} - - '@lit/react@1.0.8(@types/react@18.3.28)': - dependencies: - '@types/react': 18.3.28 - optional: true - - '@lit/reactive-element@2.1.2': - dependencies: - '@lit-labs/ssr-dom-shim': 1.6.0 - - '@monaco-editor/loader@1.7.0': - dependencies: - state-local: 1.0.7 - - '@monaco-editor/react@4.7.0(monaco-editor@0.55.1)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@monaco-editor/loader': 1.7.0 - monaco-editor: 0.55.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - - '@msgpack/msgpack@3.1.2': {} - - '@napi-rs/wasm-runtime@0.2.12': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.1 - optional: true - - '@next/env@15.3.1': {} - - '@next/eslint-plugin-next@15.3.1': - dependencies: - fast-glob: 3.3.1 - - '@next/swc-darwin-arm64@15.3.1': - optional: true - - '@next/swc-darwin-x64@15.3.1': - optional: true - - '@next/swc-linux-arm64-gnu@15.3.1': - optional: true - - '@next/swc-linux-arm64-musl@15.3.1': - optional: true - - '@next/swc-linux-x64-gnu@15.3.1': - optional: true - - '@next/swc-linux-x64-musl@15.3.1': - optional: true - - '@next/swc-win32-arm64-msvc@15.3.1': - optional: true - - '@next/swc-win32-x64-msvc@15.3.1': - optional: true - - '@noble/ciphers@1.3.0': {} - - '@noble/curves@1.8.0': - dependencies: - '@noble/hashes': 1.7.0 - - '@noble/curves@1.9.1': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/curves@1.9.2': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/curves@1.9.7': - dependencies: - '@noble/hashes': 1.8.0 - - '@noble/hashes@1.1.5': {} - - '@noble/hashes@1.7.0': {} - - '@noble/hashes@1.8.0': {} - - '@noble/secp256k1@1.7.1': {} - - '@noble/secp256k1@1.7.2': {} - - '@nodelib/fs.scandir@2.1.5': - dependencies: - '@nodelib/fs.stat': 2.0.5 - run-parallel: 1.2.0 - - '@nodelib/fs.stat@2.0.5': {} - - '@nodelib/fs.walk@1.2.8': - dependencies: - '@nodelib/fs.scandir': 2.1.5 - fastq: 1.20.1 - - '@nolyfill/is-core-module@1.0.39': {} - - '@pinojs/redact@0.4.0': {} - - '@playwright/test@1.60.0': - dependencies: - playwright: 1.60.0 - - '@popperjs/core@2.11.8': {} - - '@puppeteer/browsers@2.13.2': - dependencies: - debug: 4.4.3 - extract-zip: 2.0.1 - progress: 2.0.3 - proxy-agent: 6.5.0 - semver: 7.7.4 - tar-fs: 3.1.2 - yargs: 17.7.2 - transitivePeerDependencies: - - bare-abort-controller - - bare-buffer - - react-native-b4a - - supports-color - - '@radix-ui/primitive@1.1.3': {} - - '@radix-ui/react-arrow@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-collection@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-compose-refs@1.1.2(@types/react@18.3.28)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-context@1.1.2(@types/react@18.3.28)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-dialog@1.1.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - aria-hidden: 1.2.6 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.2(@types/react@18.3.28)(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-direction@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-dismissable-layer@1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-escape-keydown': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-dropdown-menu@2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-menu': 2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-focus-guards@1.1.3(@types/react@18.3.28)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-focus-scope@1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-id@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-menu@2.1.16(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-direction': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-focus-guards': 1.1.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-focus-scope': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-roving-focus': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - aria-hidden: 1.2.6 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - react-remove-scroll: 2.7.2(@types/react@18.3.28)(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-popper@1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@floating-ui/react-dom': 2.1.8(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-arrow': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-rect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-size': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/rect': 1.1.1 - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-portal@1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-presence@1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-primitive@2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-slot@1.2.3(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-toast@1.2.15(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-collection': 1.1.7(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-tooltip@1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/primitive': 1.1.3 - '@radix-ui/react-compose-refs': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-context': 1.1.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-dismissable-layer': 1.1.11(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-id': 1.1.1(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-popper': 1.2.8(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-portal': 1.1.9(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-presence': 1.1.5(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - '@radix-ui/react-slot': 1.2.3(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-controllable-state': 1.2.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-visually-hidden': 1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/react-use-callback-ref@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-use-controllable-state@1.2.2(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-effect-event': 0.0.2(@types/react@18.3.28)(react@18.3.1) - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-use-escape-keydown@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-callback-ref': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-use-layout-effect@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/rect': 1.1.1 - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-use-rect@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/rect': 1.1.1 - '@radix-ui/react-use-size@1.1.1(@types/react@18.3.28)(react@18.3.1)': - dependencies: - '@radix-ui/react-use-layout-effect': 1.1.1(@types/react@18.3.28)(react@18.3.1) - react: 18.3.1 - optionalDependencies: - '@types/react': 18.3.28 - - '@radix-ui/react-visually-hidden@1.2.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': - dependencies: - '@radix-ui/react-primitive': 2.1.3(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) - react: 18.3.1 - react-dom: 18.3.1(react@18.3.1) - optionalDependencies: - '@types/react': 18.3.28 - '@types/react-dom': 18.3.7(@types/react@18.3.28) - - '@radix-ui/rect@1.1.1': {} - - '@react-dnd/asap@5.0.2': {} - - '@react-dnd/invariant@4.0.2': {} - - '@react-dnd/shallowequal@4.0.2': {} - - '@reown/appkit-common@1.7.17(typescript@5.9.3)(zod@3.22.4)': + '@radix-ui/rect@1.1.1': {} + + '@react-dnd/asap@5.0.2': {} + + '@react-dnd/invariant@4.0.2': {} + + '@react-dnd/shallowequal@4.0.2': {} + + '@reown/appkit-common@1.7.17(typescript@5.9.3)(zod@3.22.4)': dependencies: big.js: 6.2.2 dayjs: 1.11.13 @@ -10552,97 +9935,19 @@ snapshots: big.js: 6.2.2 dayjs: 1.11.13 viem: 2.51.2(typescript@5.9.3)(zod@3.25.76) - transitivePeerDependencies: - - bufferutil - - typescript - - utf-8-validate - - zod - - '@reown/appkit-controllers@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': - dependencies: - '@reown/appkit-common': 1.7.17(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-wallet': 1.7.17(typescript@5.9.3) - '@walletconnect/universal-provider': 2.21.5(typescript@5.9.3)(zod@3.25.76) - valtio: 2.1.5(@types/react@18.3.28)(react@18.3.1) - viem: 2.51.2(typescript@5.9.3)(zod@3.25.76) - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - ioredis - - react - - typescript - - uploadthing - - utf-8-validate - - zod - - '@reown/appkit-pay@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': - dependencies: - '@reown/appkit-common': 1.7.17(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-ui': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-utils': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) - lit: 3.3.0 - valtio: 2.1.5(@types/react@18.3.28)(react@18.3.1) - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - ioredis - - react + transitivePeerDependencies: + - bufferutil - typescript - - uploadthing - utf-8-validate - zod - '@reown/appkit-polyfills@1.7.17': - dependencies: - buffer: 6.0.3 - - '@reown/appkit-scaffold-ui@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': + '@reown/appkit-controllers@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.17(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-controllers': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-ui': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-utils': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) - lit: 3.3.0 - valtio: 2.1.5(@types/react@18.3.28)(react@18.3.1) '@reown/appkit-wallet': 1.7.17(typescript@5.9.3) - lit: 3.3.0 + '@walletconnect/universal-provider': 2.21.5(typescript@5.9.3)(zod@3.25.76) + valtio: 2.1.5(@types/react@18.3.28)(react@18.3.1) + viem: 2.51.2(typescript@5.9.3)(zod@3.25.76) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10669,21 +9974,16 @@ snapshots: - typescript - uploadthing - utf-8-validate - - valtio - zod - '@reown/appkit-siwx@1.7.17(@types/react@18.3.28)(lit@3.3.0)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': + '@reown/appkit-pay@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.17(typescript@5.9.3)(zod@3.25.76) '@reown/appkit-controllers': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-scaffold-ui': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) '@reown/appkit-ui': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) '@reown/appkit-utils': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) - bip322-js: 2.0.0 - bs58: 6.0.0 lit: 3.3.0 - tweetnacl: 1.0.3 - viem: 2.32.0(typescript@5.9.3)(zod@3.25.76) + valtio: 2.1.5(@types/react@18.3.28)(react@18.3.1) transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -10710,17 +10010,20 @@ snapshots: - typescript - uploadthing - utf-8-validate - - valtio - zod - optional: true - '@reown/appkit-ui@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': + '@reown/appkit-polyfills@1.7.17': + dependencies: + buffer: 6.0.3 + + '@reown/appkit-scaffold-ui@1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76)': dependencies: '@reown/appkit-common': 1.7.17(typescript@5.9.3)(zod@3.25.76) '@reown/appkit-controllers': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-ui': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) + '@reown/appkit-utils': 1.7.17(@types/react@18.3.28)(react@18.3.1)(typescript@5.9.3)(valtio@2.1.5(@types/react@18.3.28)(react@18.3.1))(zod@3.25.76) '@reown/appkit-wallet': 1.7.17(typescript@5.9.3) lit: 3.3.0 - qrcode: 1.5.3 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -11134,7 +10437,7 @@ snapshots: '@scure/bip32@1.7.0': dependencies: - '@noble/curves': 1.9.1 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/base': 1.2.6 @@ -11284,191 +10587,6 @@ snapshots: '@stacks/stacks-blockchain-api-types@0.61.0': {} - '@stacks/storage@7.4.0': - dependencies: - '@stacks/auth': 7.4.0 - '@stacks/common': 7.3.1 - '@stacks/encryption': 7.4.0 - '@stacks/network': 7.3.1 - base64-js: 1.5.1 - jsontokens: 4.0.1 - transitivePeerDependencies: - - encoding - - '@stacks/transactions@6.17.0': - dependencies: - '@noble/hashes': 1.1.5 - '@noble/secp256k1': 1.7.1 - '@stacks/common': 6.16.0 - '@stacks/network': 6.17.0 - c32check: 2.0.0 - lodash.clonedeep: 4.5.0 - transitivePeerDependencies: - - encoding - - '@stacks/transactions@7.4.0': - dependencies: - '@noble/hashes': 1.1.5 - '@noble/secp256k1': 1.7.1 - '@stacks/common': 7.3.1 - '@stacks/network': 7.3.1 - c32check: 2.0.0 - lodash.clonedeep: 4.5.0 - transitivePeerDependencies: - - encoding - - '@stacks/wallet-sdk@7.4.0': - dependencies: - '@scure/bip32': 1.1.3 - '@scure/bip39': 1.1.0 - '@stacks/auth': 7.4.0 - '@stacks/common': 7.3.1 - '@stacks/encryption': 7.4.0 - '@stacks/network': 7.3.1 - '@stacks/profile': 7.4.0 - '@stacks/storage': 7.4.0 - '@stacks/transactions': 7.4.0 - c32check: 2.0.0 - jsontokens: 4.0.1 - zone-file: 2.0.0-beta.3 - transitivePeerDependencies: - - encoding - - '@stencil/core@4.43.4': - optionalDependencies: - '@rollup/rollup-darwin-arm64': 4.44.0 - '@rollup/rollup-darwin-x64': 4.44.0 - '@rollup/rollup-linux-arm64-gnu': 4.44.0 - '@rollup/rollup-linux-arm64-musl': 4.44.0 - '@rollup/rollup-linux-x64-gnu': 4.44.0 - '@rollup/rollup-linux-x64-musl': 4.44.0 - '@rollup/rollup-win32-arm64-msvc': 4.44.0 - '@rollup/rollup-win32-x64-msvc': 4.44.0 - - '@stacks/auth@7.4.0': - dependencies: - '@noble/secp256k1': 1.7.1 - '@stacks/common': 7.3.1 - '@stacks/encryption': 7.4.0 - '@stacks/network': 7.3.1 - '@stacks/profile': 7.4.0 - cross-fetch: 3.2.0 - jsontokens: 4.0.1 - transitivePeerDependencies: - - encoding - - '@stacks/bns@7.4.0': - dependencies: - '@stacks/common': 7.3.1 - '@stacks/network': 7.3.1 - '@stacks/transactions': 7.4.0 - transitivePeerDependencies: - - encoding - - '@stacks/common@6.16.0': - dependencies: - '@types/bn.js': 5.2.0 - '@types/node': 18.19.130 - - '@stacks/common@7.3.1': {} - - '@stacks/connect-ui@8.1.2': - dependencies: - '@stencil/core': 4.43.4 - - '@stacks/connect@8.2.6(@types/react@18.3.28)(lit@3.3.0)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76)': - dependencies: - '@reown/appkit': 1.7.17(@types/react@18.3.28)(lit@3.3.0)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@reown/appkit-universal-connector': 1.7.17(@types/react@18.3.28)(lit@3.3.0)(react@18.3.1)(typescript@5.9.3)(zod@3.25.76) - '@scure/base': 1.2.6 - '@stacks/common': 7.3.1 - '@stacks/connect-ui': 8.1.2 - '@stacks/network': 7.3.1 - '@stacks/network-v6': '@stacks/network@6.17.0' - '@stacks/profile': 7.4.0 - '@stacks/transactions': 7.4.0 - '@stacks/transactions-v6': '@stacks/transactions@6.17.0' - type-fest: 5.6.0 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@netlify/blobs' - - '@planetscale/database' - - '@react-native-async-storage/async-storage' - - '@types/react' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/functions' - - '@vercel/kv' - - aws4fetch - - bufferutil - - db0 - - encoding - - ioredis - - lit - - react - - typescript - - uploadthing - - utf-8-validate - - zod - - '@stacks/encryption@7.4.0': - dependencies: - '@noble/hashes': 1.1.5 - '@noble/secp256k1': 1.7.1 - '@scure/bip39': 1.1.0 - '@stacks/common': 7.3.1 - base64-js: 1.5.1 - bs58: 5.0.0 - ripemd160-min: 0.0.6 - varuint-bitcoin: 1.1.2 - - '@stacks/network@6.17.0': - dependencies: - '@stacks/common': 6.16.0 - cross-fetch: 3.2.0 - transitivePeerDependencies: - - encoding - - '@stacks/network@7.3.1': - dependencies: - '@stacks/common': 7.3.1 - cross-fetch: 3.2.0 - transitivePeerDependencies: - - encoding - - '@stacks/profile@7.4.0': - dependencies: - '@stacks/common': 7.3.1 - '@stacks/network': 7.3.1 - '@stacks/transactions': 7.4.0 - jsontokens: 4.0.1 - schema-inspector: 2.1.0 - zone-file: 2.0.0-beta.3 - transitivePeerDependencies: - - encoding - - '@stacks/stacking@7.4.0': - dependencies: - '@noble/hashes': 1.1.5 - '@scure/base': 1.1.1 - '@stacks/common': 7.3.1 - '@stacks/encryption': 7.4.0 - '@stacks/network': 7.3.1 - '@stacks/stacks-blockchain-api-types': 0.61.0 - '@stacks/transactions': 7.4.0 - bs58: 5.0.0 - transitivePeerDependencies: - - encoding - - '@stacks/stacks-blockchain-api-types@0.61.0': {} - '@stacks/storage@7.4.0': dependencies: '@stacks/auth': 7.4.0 @@ -11912,24 +11030,24 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@types/babel__generator': 7.27.0 '@types/babel__template': 7.4.4 '@types/babel__traverse': 7.28.0 '@types/babel__generator@7.27.0': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@types/babel__template@7.4.4': dependencies: - '@babel/parser': 7.29.2 - '@babel/types': 7.29.0 + '@babel/parser': 7.29.7 + '@babel/types': 7.29.7 '@types/babel__traverse@7.28.0': dependencies: - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@types/bn.js@5.2.0': dependencies: @@ -12931,7 +12049,7 @@ snapshots: babel-plugin-istanbul@6.1.1: dependencies: - '@babel/helper-plugin-utils': 7.28.6 + '@babel/helper-plugin-utils': 7.29.7 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.6 istanbul-lib-instrument: 5.2.1 @@ -12941,8 +12059,8 @@ snapshots: babel-plugin-jest-hoist@29.6.3: dependencies: - '@babel/template': 7.28.6 - '@babel/types': 7.29.0 + '@babel/template': 7.29.7 + '@babel/types': 7.29.7 '@types/babel__core': 7.20.5 '@types/babel__traverse': 7.28.0 @@ -13194,7 +12312,7 @@ snapshots: c32check@2.0.0: dependencies: - '@noble/hashes': 1.1.5 + '@noble/hashes': 1.8.0 base-x: 4.0.1 cac@6.7.14: {} @@ -14767,7 +13885,7 @@ snapshots: istanbul-lib-instrument@5.2.1: dependencies: '@babel/core': 7.29.0 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.7 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 6.3.1 @@ -14777,7 +13895,7 @@ snapshots: istanbul-lib-instrument@6.0.3: dependencies: '@babel/core': 7.29.0 - '@babel/parser': 7.29.2 + '@babel/parser': 7.29.7 '@istanbuljs/schema': 0.1.6 istanbul-lib-coverage: 3.2.2 semver: 7.7.4 @@ -14963,7 +14081,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.29.0 + '@babel/code-frame': 7.29.7 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -15060,10 +14178,10 @@ snapshots: jest-snapshot@29.7.0: dependencies: '@babel/core': 7.29.0 - '@babel/generator': 7.29.1 + '@babel/generator': 7.29.7 '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) '@babel/plugin-syntax-typescript': 7.29.7(@babel/core@7.29.0) - '@babel/types': 7.29.0 + '@babel/types': 7.29.7 '@jest/expect-utils': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 @@ -15445,12 +14563,6 @@ snapshots: min-indent@1.0.1: {} - minimalistic-assert@1.0.1: - optional: true - - minimalistic-crypto-utils@1.0.1: - optional: true - minimalistic-assert@1.0.1: optional: true @@ -15713,11 +14825,11 @@ snapshots: dependencies: '@adraffy/ens-normalize': 1.11.1 '@noble/ciphers': 1.3.0 - '@noble/curves': 1.9.2 + '@noble/curves': 1.9.7 '@noble/hashes': 1.8.0 '@scure/bip32': 1.7.0 '@scure/bip39': 1.6.0 - abitype: 1.0.8(typescript@5.9.3)(zod@3.25.76) + abitype: 1.2.3(typescript@5.9.3)(zod@3.25.76) eventemitter3: 5.0.1 optionalDependencies: typescript: 5.9.3 @@ -15784,7 +14896,7 @@ snapshots: parse-json@5.2.0: dependencies: - '@babel/code-frame': 7.29.0 + '@babel/code-frame': 7.29.7 error-ex: 1.3.4 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -16318,11 +15430,11 @@ snapshots: dependencies: loose-envify: 1.4.0 - reacts-cli@1.0.3(@babel/core@7.29.0)(@babel/preset-react@7.29.7(@babel/core@7.29.0))(@babel/preset-typescript@7.29.7(@babel/core@7.29.0))(@babel/traverse@7.29.0)(@playwright/test@1.60.0)(@tanstack/query-core@5.100.14)(@types/node@20.19.39)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(cli-table@0.3.11)(lit@3.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1))(zod@3.25.76): + reacts-cli@1.0.3(@babel/core@7.29.0)(@babel/preset-react@7.29.7(@babel/core@7.29.0))(@babel/preset-typescript@7.29.7(@babel/core@7.29.0))(@babel/traverse@7.29.7)(@playwright/test@1.60.0)(@tanstack/query-core@5.100.14)(@types/node@20.19.39)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(cli-table@0.3.11)(lit@3.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(use-sync-external-store@1.4.0(react@18.3.1))(zod@3.25.76): dependencies: '@babel/preset-react': 7.29.7(@babel/core@7.29.0) '@babel/preset-typescript': 7.29.7(@babel/core@7.29.0) - '@babel/traverse': 7.29.0 + '@babel/traverse': 7.29.7 '@stacks/network': 6.17.0 '@stacks/transactions': 6.17.0 chessify-protocol: 0.1.2(@babel/core@7.29.0)(@playwright/test@1.60.0)(@tanstack/query-core@5.100.14)(@types/react-dom@18.3.7(@types/react@18.3.28))(@types/react@18.3.28)(lit@3.3.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)(typescript@5.9.3)(use-sync-external-store@1.4.0(react@18.3.1))(zod@3.25.76) diff --git a/src/app/components/courses/CourseReviews.tsx b/src/app/components/courses/CourseReviews.tsx index 29d7670f..994e95fb 100644 --- a/src/app/components/courses/CourseReviews.tsx +++ b/src/app/components/courses/CourseReviews.tsx @@ -1,6 +1,11 @@ 'use client'; import { useState } from 'react'; +import { + getPortfolioSummary, + normalizePortfolioItems, + type ReviewPortfolioItem, +} from '@/lib/reviews/portfolioManagement'; interface Review { id: string; @@ -10,6 +15,7 @@ interface Review { date: string; comment: string; helpful: number; + portfolio?: ReviewPortfolioItem[]; } interface CourseReviewsProps { @@ -31,6 +37,15 @@ export default function CourseReviews({ comment: 'Excellent course! The instructor explains complex concepts in a very clear and understandable way. Highly recommend!', helpful: 24, + portfolio: [ + { + id: 'portfolio-1', + title: 'Capstone accessibility audit', + url: 'https://example.com/portfolio/accessibility-audit', + type: 'case-study', + description: 'Before-and-after notes from the final project review.', + }, + ], }, { id: '2', @@ -132,53 +147,87 @@ export default function CourseReviews({
- {reviews.map((review) => ( -
-
- {/* eslint-disable-next-line @next/next/no-img-element */} - {review.userName} -
-
-
-

- {review.userName} -

-
- {renderStars(review.rating)} - - {review.date} - + {reviews.map((review) => { + const portfolio = normalizePortfolioItems(review.portfolio); + + return ( +
+
+ {/* eslint-disable-next-line @next/next/no-img-element */} + {review.userName} +
+
+
+

+ {review.userName} +

+
+ {renderStars(review.rating)} + + {review.date} + +
+

+ {review.comment} +

+ {portfolio.length > 0 ? ( +
+
+ Portfolio evidence +
+
    + {portfolio.map((item) => ( +
  • + + {item.title} + + + {item.type.replace('-', ' ')} + + {item.description ? ( +

    + {item.description} +

    + ) : null} +
  • + ))} +
+
+ ) : null} +
-

- {review.comment} -

-
-
- ))} + ); + })}
); diff --git a/src/app/components/social/CertificateManagementPanel.tsx b/src/app/components/social/CertificateManagementPanel.tsx new file mode 100644 index 00000000..892d86e3 --- /dev/null +++ b/src/app/components/social/CertificateManagementPanel.tsx @@ -0,0 +1,172 @@ +'use client'; + +import { useState } from 'react'; +import type { ForumCertificate } from '@/app/hooks/useStudyGroups'; + +interface CertificateManagementPanelProps { + certificates: ForumCertificate[]; + onIssue: (input: { + subjectUserId: string; + subjectName: string; + fingerprint: string; + validFrom: string; + validUntil: string; + }) => void; + onRevoke: (certificateId: string) => void; +} + +const today = () => new Date().toISOString().slice(0, 10); +const tomorrow = () => { + const date = new Date(); + date.setDate(date.getDate() + 1); + return date.toISOString().slice(0, 10); +}; + +export default function CertificateManagementPanel({ + certificates, + onIssue, + onRevoke, +}: CertificateManagementPanelProps) { + const [subjectName, setSubjectName] = useState(''); + const [subjectUserId, setSubjectUserId] = useState(''); + const [fingerprint, setFingerprint] = useState(''); + const [validFrom, setValidFrom] = useState(today()); + const [validUntil, setValidUntil] = useState(tomorrow()); + const [error, setError] = useState(null); + + const submit = () => { + setError(null); + try { + onIssue({ + subjectName, + subjectUserId, + fingerprint, + validFrom: new Date(validFrom).toISOString(), + validUntil: new Date(validUntil).toISOString(), + }); + setSubjectName(''); + setSubjectUserId(''); + setFingerprint(''); + } catch (err) { + setError(err instanceof Error ? err.message : 'Unable to issue certificate.'); + } + }; + + return ( +
+
+

+ Certificate Management +

+

+ Issue and revoke SHA-256 fingerprint certificates for trusted forum participation. +

+
+ +
+ + + + + + {error ? ( +

+ {error} +

+ ) : null} + +
+ +
+ {certificates.length === 0 ? ( +

+ No forum certificates have been issued for this group. +

+ ) : ( + certificates.map((certificate) => ( +
+
+
+

+ {certificate.subjectName} +

+

+ {certificate.fingerprint} +

+

+ Valid until {new Date(certificate.validUntil).toLocaleDateString()} +

+
+
+ + {certificate.status} + + {certificate.status === 'active' ? ( + + ) : null} +
+
+
+ )) + )} +
+
+ ); +} diff --git a/src/app/components/social/GroupDiscussionThread.tsx b/src/app/components/social/GroupDiscussionThread.tsx index 4ad1eb49..1d4c5112 100644 --- a/src/app/components/social/GroupDiscussionThread.tsx +++ b/src/app/components/social/GroupDiscussionThread.tsx @@ -5,11 +5,16 @@ import { motion, AnimatePresence } from 'framer-motion'; import { Paperclip, Send } from 'lucide-react'; import RichTextEditor from '@/app/components/ui/RichTextEditor'; import type { GroupMessage, Attachment } from '@/app/hooks/useStudyGroups'; +import { + buildAccessibleThreadTree, + getThreadPositionLabel, + type ThreadNode, +} from '@/lib/accessibility/threadSupport'; import { formatDistanceToNow } from 'date-fns'; interface GroupDiscussionThreadProps { messages: GroupMessage[]; - onPost: (contentHtml: string, attachments?: Attachment[]) => void; + onPost: (contentHtml: string, attachments?: Attachment[], parentId?: string | null) => void; } const getInitials = (name: string) => { @@ -24,6 +29,7 @@ const getInitials = (name: string) => { export default function GroupDiscussionThread({ messages, onPost }: GroupDiscussionThreadProps) { const [content, setContent] = useState(''); const [files, setFiles] = useState([]); + const [replyTo, setReplyTo] = useState(null); const messagesEndRef = useRef(null); const fileInputRef = useRef(null); @@ -37,6 +43,7 @@ export default function GroupDiscussionThread({ messages, onPost }: GroupDiscuss })), [files], ); + const threadedMessages = useMemo(() => buildAccessibleThreadTree(messages), [messages]); // Auto-scroll to bottom when new messages arrive useEffect(() => { @@ -45,14 +52,89 @@ export default function GroupDiscussionThread({ messages, onPost }: GroupDiscuss const handlePost = () => { if (!content || content === '

' || content.trim() === '') return; - onPost(content, attachments.length ? attachments : undefined); + onPost(content, attachments.length ? attachments : undefined, replyTo?.id ?? null); setContent(''); setFiles([]); + setReplyTo(null); if (fileInputRef.current) { fileInputRef.current.value = ''; } }; + const renderMessageNode = (node: ThreadNode, index: number) => { + const m = node.item; + const replyCount = node.replies.length; + const indent = Math.min(node.depth, 4) * 1.25; + + return ( + +
+ {/* Avatar */} + + + {/* Message Content */} +
+
+ + {m.senderName} + + + {formatDistanceToNow(new Date(m.createdAt), { addSuffix: true })} + +
+
+ {!!m.attachments?.length && ( +
+ {m.attachments.map((a) => ( + + + ))} +
+ )} + +
+
+ {node.replies.length > 0 ? ( +
+ {node.replies.map((reply, replyIndex) => renderMessageNode(reply, replyIndex))} +
+ ) : null} +
+ ); + }; + return (
@@ -62,52 +144,9 @@ export default function GroupDiscussionThread({ messages, onPost }: GroupDiscuss
) : ( - {messages.map((m, index) => ( - - {/* Avatar */} -
- {getInitials(m.senderName)} -
- - {/* Message Content */} -
-
- - {m.senderName} - - - {formatDistanceToNow(new Date(m.createdAt), { addSuffix: true })} - -
-
- {!!m.attachments?.length && ( -
- {m.attachments.map((a) => ( - - - {a.name} - - ))} -
- )} -
- - ))} +
+ {threadedMessages.map((node, index) => renderMessageNode(node, index))} +
)}
@@ -115,6 +154,18 @@ export default function GroupDiscussionThread({ messages, onPost }: GroupDiscuss {/* Message Input */}
+ {replyTo ? ( +
+ Replying to {replyTo.senderName} + +
+ ) : null}
diff --git a/src/lib/accessibility/__tests__/threadSupport.test.ts b/src/lib/accessibility/__tests__/threadSupport.test.ts new file mode 100644 index 00000000..520a79ad --- /dev/null +++ b/src/lib/accessibility/__tests__/threadSupport.test.ts @@ -0,0 +1,54 @@ +import { describe, expect, it } from 'vitest'; +import { + buildAccessibleThreadTree, + flattenThreadTree, + getThreadPositionLabel, + type ThreadableItem, +} from '../threadSupport'; + +const item = (id: string, parentId: string | null, minute: number): ThreadableItem => ({ + id, + parentId, + createdAt: `2026-05-28T10:${String(minute).padStart(2, '0')}:00.000Z`, +}); + +describe('threadSupport', () => { + it('builds ordered nested threads from parent ids', () => { + const tree = buildAccessibleThreadTree([ + item('reply-2', 'root', 3), + item('root', null, 1), + item('reply-1', 'root', 2), + item('nested', 'reply-1', 4), + ]); + + expect(tree).toHaveLength(1); + expect(tree[0].item.id).toBe('root'); + expect(tree[0].replies.map((node) => node.item.id)).toEqual(['reply-1', 'reply-2']); + expect(tree[0].replies[0].replies[0].depth).toBe(2); + }); + + it('promotes orphaned and self-parented messages to roots', () => { + const tree = buildAccessibleThreadTree([item('orphan', 'missing', 1), item('self', 'self', 2)]); + + expect(tree.map((node) => node.item.id)).toEqual(['orphan', 'self']); + }); + + it('flattens threads in screen-reader reading order', () => { + const tree = buildAccessibleThreadTree([ + item('root', null, 1), + item('reply', 'root', 2), + item('second-root', null, 3), + ]); + + expect(flattenThreadTree(tree).map((node) => node.item.id)).toEqual([ + 'root', + 'reply', + 'second-root', + ]); + }); + + it('creates concise position labels for accessible thread summaries', () => { + expect(getThreadPositionLabel(0, 1)).toBe('Thread starter with 1 reply'); + expect(getThreadPositionLabel(2, 0)).toBe('Reply level 2 with 0 nested replies'); + }); +}); diff --git a/src/lib/accessibility/threadSupport.ts b/src/lib/accessibility/threadSupport.ts new file mode 100644 index 00000000..24c16187 --- /dev/null +++ b/src/lib/accessibility/threadSupport.ts @@ -0,0 +1,74 @@ +export interface ThreadableItem { + id: string; + parentId?: string | null; + createdAt: string; +} + +export interface ThreadNode { + item: T; + depth: number; + replies: Array>; +} + +export interface ThreadBuildOptions { + maxDepth?: number; +} + +const DEFAULT_MAX_DEPTH = 4; + +export function buildAccessibleThreadTree( + items: T[], + options: ThreadBuildOptions = {}, +): Array> { + const maxDepth = options.maxDepth ?? DEFAULT_MAX_DEPTH; + const sorted = [...items].sort((a, b) => a.createdAt.localeCompare(b.createdAt)); + const byId = new Map(sorted.map((item) => [item.id, item])); + const childrenByParent = new Map(); + const roots: T[] = []; + + for (const item of sorted) { + const parentId = item.parentId ?? null; + + if (!parentId || !byId.has(parentId) || parentId === item.id) { + roots.push(item); + continue; + } + + const siblings = childrenByParent.get(parentId) ?? []; + siblings.push(item); + childrenByParent.set(parentId, siblings); + } + + const buildNode = (item: T, depth: number, ancestors: Set): ThreadNode => { + const childDepth = Math.min(depth + 1, maxDepth); + const children = childrenByParent.get(item.id) ?? []; + const nextAncestors = new Set(ancestors); + nextAncestors.add(item.id); + + return { + item, + depth, + replies: children + .filter((child) => !nextAncestors.has(child.id)) + .map((child) => buildNode(child, childDepth, nextAncestors)), + }; + }; + + return roots.map((item) => buildNode(item, 0, new Set())); +} + +export function flattenThreadTree( + nodes: Array>, +): Array> { + return nodes.flatMap((node) => [node, ...flattenThreadTree(node.replies)]); +} + +export function getThreadPositionLabel(depth: number, replyCount: number): string { + if (depth === 0) { + return replyCount === 1 ? 'Thread starter with 1 reply' : `Thread starter with ${replyCount} replies`; + } + + return replyCount === 1 + ? `Reply level ${depth} with 1 nested reply` + : `Reply level ${depth} with ${replyCount} nested replies`; +} diff --git a/src/lib/reviews/__tests__/portfolioManagement.test.ts b/src/lib/reviews/__tests__/portfolioManagement.test.ts new file mode 100644 index 00000000..95d4ce7d --- /dev/null +++ b/src/lib/reviews/__tests__/portfolioManagement.test.ts @@ -0,0 +1,51 @@ +import { describe, expect, it } from 'vitest'; +import { + getPortfolioSummary, + isSafePortfolioUrl, + normalizePortfolioItems, +} from '../portfolioManagement'; + +describe('portfolioManagement', () => { + it('accepts http and https portfolio links only', () => { + expect(isSafePortfolioUrl('https://example.com/work')).toBe(true); + expect(isSafePortfolioUrl('http://example.com/work')).toBe(true); + expect(isSafePortfolioUrl('javascript:alert(1)')).toBe(false); + expect(isSafePortfolioUrl('not-a-url')).toBe(false); + }); + + it('normalizes, de-duplicates, and filters portfolio evidence', () => { + const items = normalizePortfolioItems([ + { + id: '1', + title: ' Capstone ', + url: 'https://example.com/capstone', + type: 'project', + }, + { + id: '2', + title: 'Duplicate', + url: 'https://example.com/capstone', + type: 'project', + }, + { + id: '3', + title: 'Unsafe', + url: 'javascript:alert(1)', + type: 'repository', + }, + ]); + + expect(items).toHaveLength(1); + expect(items[0].title).toBe('Capstone'); + }); + + it('summarizes portfolio attachments for accessible review labels', () => { + expect(getPortfolioSummary([])).toBe('No portfolio evidence attached'); + expect( + getPortfolioSummary([ + { id: '1', title: 'Demo', url: 'https://example.com', type: 'project' }, + { id: '2', title: 'Repo', url: 'https://github.com/example/repo', type: 'repository' }, + ]), + ).toBe('2 portfolio items attached'); + }); +}); diff --git a/src/lib/reviews/portfolioManagement.ts b/src/lib/reviews/portfolioManagement.ts new file mode 100644 index 00000000..3237951f --- /dev/null +++ b/src/lib/reviews/portfolioManagement.ts @@ -0,0 +1,43 @@ +export interface ReviewPortfolioItem { + id: string; + title: string; + url: string; + type: 'project' | 'repository' | 'case-study' | 'certificate'; + description?: string; +} + +const SAFE_PORTFOLIO_PROTOCOLS = new Set(['https:', 'http:']); + +export function isSafePortfolioUrl(url: string): boolean { + try { + const parsed = new URL(url); + return SAFE_PORTFOLIO_PROTOCOLS.has(parsed.protocol); + } catch { + return false; + } +} + +export function normalizePortfolioItems(items: ReviewPortfolioItem[] = []): ReviewPortfolioItem[] { + const seen = new Set(); + + return items + .filter((item) => item.title.trim() && isSafePortfolioUrl(item.url)) + .filter((item) => { + const key = `${item.type}:${item.url}`; + if (seen.has(key)) return false; + seen.add(key); + return true; + }) + .map((item) => ({ + ...item, + title: item.title.trim(), + description: item.description?.trim() || undefined, + })); +} + +export function getPortfolioSummary(items: ReviewPortfolioItem[] = []): string { + const normalized = normalizePortfolioItems(items); + if (normalized.length === 0) return 'No portfolio evidence attached'; + if (normalized.length === 1) return '1 portfolio item attached'; + return `${normalized.length} portfolio items attached`; +}