diff --git a/package.json b/package.json index 9bdc47f6..41fc64c0 100644 --- a/package.json +++ b/package.json @@ -34,6 +34,7 @@ "react-dom": "^18.3.1", "react-toastify": "^10.0.6", "react-tooltip": "^5.26.3", + "torph": "0.0.5", "urql": "^3.0.3", "yaml": "^2.4.5", "zod": "^3.21.2", @@ -56,6 +57,7 @@ "eslint-config-prettier": "^9.1.0", "globals": "^16.5.0", "jest": "^29.6.3", + "jest-environment-jsdom": "^29.6.3", "postcss": "^8.4.49", "prettier": "^3.2.5", "prettier-plugin-organize-imports": "^4.1.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a1f6875f..4ce875d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -106,6 +106,9 @@ importers: react-tooltip: specifier: ^5.26.3 version: 5.28.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + torph: + specifier: 0.0.5 + version: 0.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1) urql: specifier: ^3.0.3 version: 3.0.3(graphql@16.6.0)(react@18.3.1) @@ -167,6 +170,9 @@ importers: jest: specifier: ^29.6.3 version: 29.7.0(@types/node@24.10.9)(ts-node@10.9.2(@types/node@24.10.9)(typescript@5.7.2)) + jest-environment-jsdom: + specifier: ^29.6.3 + version: 29.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10) postcss: specifier: ^8.4.49 version: 8.4.49 @@ -3532,6 +3538,10 @@ packages: '@tanstack/virtual-core@3.10.9': resolution: {integrity: sha512-kBknKOKzmeR7lN+vSadaKWXaLS0SZZG+oqpQ/k80Q6g9REn6zRHS/ZYdrIzHnpHgy/eWs00SujveUN/GJT2qTw==} + '@tootallnate/once@2.0.0': + resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==} + engines: {node: '>= 10'} + '@trpc/client@10.45.2': resolution: {integrity: sha512-ykALM5kYWTLn1zYuUOZ2cPWlVfrXhc18HzBDyRhoPYN0jey4iQHEFSEowfnhg1RvYnrAVjNBgHNeSAXjrDbGwg==} peerDependencies: @@ -3662,6 +3672,9 @@ packages: '@types/jest@29.5.4': resolution: {integrity: sha512-PhglGmhWeD46FYOVLt3X7TiWjzwuVGW9wG/4qocPevXMjCmrIc5b6db9WjeGE4QYVpUAWMDv3v0IiBwObY289A==} + '@types/jsdom@20.0.1': + resolution: {integrity: sha512-d0r18sZPmMQr1eG35u12FZfhIXNrnsPU/g5wvRKCUf/tOGilKKwYMYGqh33BNR6ba+2gkHw1EUiHoN3mn7E5IQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -3737,6 +3750,9 @@ packages: '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} + '@types/tough-cookie@4.0.5': + resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/trusted-types@2.0.7': resolution: {integrity: sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==} @@ -4010,6 +4026,10 @@ packages: resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} hasBin: true + abab@2.0.6: + resolution: {integrity: sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==} + deprecated: Use your platform's native atob() and btoa() methods instead + abi-wan-kanabi@2.2.4: resolution: {integrity: sha512-0aA81FScmJCPX+8UvkXLki3X1+yPQuWxEkqXBVKltgPAK79J+NB+Lp5DouMXa7L6f+zcRlIA/6XO7BN/q9fnvg==} hasBin: true @@ -4044,6 +4064,9 @@ packages: resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} engines: {node: '>= 0.6'} + acorn-globals@7.0.1: + resolution: {integrity: sha512-umOSDSDrfHbTNPuNpC2NSnnA3LUrqpevPb4T9jRx4MagXNS0rs+gwiTcAvqCRmsD6utzsrzNt+ebm00SNWiC3Q==} + acorn-import-attributes@1.9.5: resolution: {integrity: sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==} peerDependencies: @@ -4809,12 +4832,26 @@ packages: engines: {node: '>=4'} hasBin: true + cssom@0.3.8: + resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} + + cssom@0.5.0: + resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==} + + cssstyle@2.3.0: + resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} + engines: {node: '>=8'} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} damerau-levenshtein@1.0.8: resolution: {integrity: sha512-sdQSFB7+llfUcQHUQO3+B8ERRj0Oa4w9POWMI/puGtuf7gFywGmkaLCElnudfTiKZV+NvHqL0ifzdrI8Ro7ESA==} + data-urls@3.0.2: + resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} + engines: {node: '>=12'} + data-view-buffer@1.0.1: resolution: {integrity: sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==} engines: {node: '>= 0.4'} @@ -4879,6 +4916,9 @@ packages: decimal.js@10.4.3: resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decimal.js@10.6.0: + resolution: {integrity: sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==} + decode-uri-component@0.2.2: resolution: {integrity: sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==} engines: {node: '>=0.10'} @@ -5015,6 +5055,11 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} + domexception@4.0.0: + resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==} + engines: {node: '>=12'} + deprecated: Use your platform's native DOMException instead + dot-case@3.0.4: resolution: {integrity: sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==} @@ -5091,6 +5136,10 @@ packages: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} + entities@6.0.1: + resolution: {integrity: sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==} + engines: {node: '>=0.12'} + env-paths@2.2.1: resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} engines: {node: '>=6'} @@ -5160,6 +5209,11 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} + escodegen@2.1.0: + resolution: {integrity: sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==} + engines: {node: '>=6.0'} + hasBin: true + eslint-config-next@15.0.4: resolution: {integrity: sha512-97mLaAhbJKVQYXUBBrenRtEUAA6bNDPxWfaFEd6mEhKfpajP4wJrW4l7BUlHuYWxR8oQa9W014qBJpumpJQwWA==} peerDependencies: @@ -5616,11 +5670,12 @@ packages: glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me hasBin: true glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} - deprecated: Glob versions prior to v9 are no longer supported + deprecated: Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} @@ -5759,6 +5814,10 @@ packages: resolution: {integrity: sha512-amUFmHr6Z16370Wn57lYOkl+gb3wDBUc0nyPlx9ODMTaJ09kAVY0MrOU7JCzJJjL0bN8nKPU5vfXLBRjCmREOw==} engines: {node: '>=16.0.0'} + html-encoding-sniffer@3.0.0: + resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==} + engines: {node: '>=12'} + html-escaper@2.0.2: resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} @@ -5770,6 +5829,10 @@ packages: resolution: {integrity: sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==} engines: {node: '>= 0.8'} + http-proxy-agent@5.0.0: + resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==} + engines: {node: '>= 6'} + http-shutdown@1.2.2: resolution: {integrity: sha512-S9wWkJ/VSY9/k4qcjG318bqJNruzE4HySUhFYknwmu6LBP97KLLfwNf+n4V1BHurvFNkSKLFnK/RsuUnRTf9Vw==} engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} @@ -5806,6 +5869,10 @@ packages: resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} engines: {node: '>=0.10.0'} + iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + idb-keyval@6.2.1: resolution: {integrity: sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==} @@ -5978,6 +6045,9 @@ packages: resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} engines: {node: '>=8'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-promise@4.0.0: resolution: {integrity: sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==} @@ -6148,6 +6218,15 @@ packages: resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + jest-environment-jsdom@29.7.0: + resolution: {integrity: sha512-k9iQbsf9OyOfdzWH8HDmrRT0gSIcX+FLNW7IQq94tFX0gynPwqDTW0Ho6iMVNjGz/nb+l/vW3dWM2bbLLpkbXA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + jest-environment-node@29.7.0: resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -6263,6 +6342,15 @@ packages: jsc-safe-url@0.2.4: resolution: {integrity: sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==} + jsdom@20.0.3: + resolution: {integrity: sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==} + engines: {node: '>=14'} + peerDependencies: + canvas: ^2.5.0 + peerDependenciesMeta: + canvas: + optional: true + jsesc@3.0.2: resolution: {integrity: sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==} engines: {node: '>=6'} @@ -6816,6 +6904,9 @@ packages: nullthrows@1.1.1: resolution: {integrity: sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==} + nwsapi@2.2.23: + resolution: {integrity: sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==} + ob1@0.83.3: resolution: {integrity: sha512-egUxXCDwoWG06NGCS5s5AdcpnumHKJlfd3HH06P3m9TEMwwScfcY35wpQxbm9oHof+dM/lVH9Rfyu1elTVelSA==} engines: {node: '>=20.19.4'} @@ -6993,6 +7084,9 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} + parse5@7.3.0: + resolution: {integrity: sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==} + parseurl@1.3.3: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} @@ -7369,6 +7463,9 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.15.0: + resolution: {integrity: sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==} + pump@1.0.3: resolution: {integrity: sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw==} @@ -7379,6 +7476,10 @@ packages: resolution: {integrity: sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==} engines: {node: '>=6'} + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + pure-rand@6.0.3: resolution: {integrity: sha512-KddyFewCsO0j3+np81IQ+SweXLDnDQTs5s67BOnrYmYe/yNmUhttQyGsYzy8yUnoljGAQ9sl38YB4vH8ur7Y+w==} @@ -7417,6 +7518,9 @@ packages: resolution: {integrity: sha512-hh2WYhq4fi8+b+/2Kg9CEge4fDPvHS534aOOvOZeQ3+Vf2mCFsaFBYj0i+iXcAq6I9Vzp5fjMFBlONvayDC1qg==} engines: {node: '>=6'} + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -7623,6 +7727,9 @@ packages: require-main-filename@2.0.0: resolution: {integrity: sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-cwd@3.0.0: resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} engines: {node: '>=8'} @@ -7712,6 +7819,10 @@ packages: resolution: {integrity: sha512-ZvHN3ygzZ8FuxjSNB+mKBiF/NIoqHzlBGbD0MJiT+MvSsFOvotnWOhdTjxKzhHRT2wPC1QbhLzx2q/Y83VhfYQ==} engines: {node: '>=16'} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + scheduler@0.23.2: resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} @@ -8089,6 +8200,9 @@ packages: resolution: {integrity: sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==} engines: {node: '>=0.10'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + synckit@0.8.4: resolution: {integrity: sha512-Dn2ZkzMdSX827QbowGbU/4yjWuvNaCoScLLoMo/yKbu+P4GBR6cRGKZH27k6a9bRzdqcyd1DE96pQtQ6uNkmyw==} engines: {node: ^14.18.0 || >=16.0.0} @@ -8208,9 +8322,34 @@ packages: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} + torph@0.0.5: + resolution: {integrity: sha512-A9mwvWouyRIIZ8Y9McJioZ4O5itSjgtfPQMGxU+qvA5MYaF31EY1Cq3OpOLT34wXLhsfOC7tto5Gzg0d6I3NQg==} + peerDependencies: + react: '>=18' + react-dom: '>=18' + svelte: '>=4' + vue: '>=3' + peerDependenciesMeta: + react: + optional: true + react-dom: + optional: true + svelte: + optional: true + vue: + optional: true + + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@3.0.0: + resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} + engines: {node: '>=12'} + trpc-browser@1.4.4: resolution: {integrity: sha512-5ZH/LqSoF008W8KU+4tfQ+g3F4Yl6BywDUnSlx5jT6fKa87mm8PkIXfhjGN1k6LoxjpMjy82bxvQzNLkJ3vUvw==} peerDependencies: @@ -8357,6 +8496,10 @@ packages: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} + universalify@0.2.0: + resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} + engines: {node: '>= 4.0.0'} + universalify@2.0.1: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} @@ -8434,6 +8577,9 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + urql@3.0.3: resolution: {integrity: sha512-aVUAMRLdc5AOk239DxgXt6ZxTl/fEmjr7oyU5OGo8uvpqu42FkeJErzd2qBzhAQ3DyusoZIbqbBLPlnKo/yy2A==} peerDependencies: @@ -8542,6 +8688,10 @@ packages: vlq@1.0.1: resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==} + w3c-xmlserializer@4.0.0: + resolution: {integrity: sha512-d+BFHzbiCx6zGfz0HyQ6Rg69w9k19nviJspaj4yNscGjrHu94sVP+aRm75yEbCh+r2/yR+7q6hux9LVtbuTGBw==} + engines: {node: '>=14'} + wagmi@2.13.0: resolution: {integrity: sha512-afgHaOYXkji0QvDUNCcwIWYvzjwcDtoAPRqSBfGq9rj4v2SCztv/sYz0C43b5NoazI0LoKar8ykx8LEr3Euofg==} peerDependencies: @@ -8565,9 +8715,26 @@ packages: webidl-conversions@3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + webidl-conversions@7.0.0: + resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} + engines: {node: '>=12'} + + whatwg-encoding@2.0.0: + resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==} + engines: {node: '>=12'} + deprecated: Use @exodus/bytes instead for a more spec-conformant and faster implementation + whatwg-fetch@3.6.20: resolution: {integrity: sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==} + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-url@11.0.0: + resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} + engines: {node: '>=12'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -8692,6 +8859,13 @@ packages: utf-8-validate: optional: true + xml-name-validator@4.0.0: + resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} + engines: {node: '>=12'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + xmlhttprequest-ssl@2.1.2: resolution: {integrity: sha512-TEU+nJVUUnA4CYJFLvK5X9AOeH4KvDvhIfm0vV1GaQRtchnG0hgK5p8hw/xjv8cunWYCsiPCSDzObPyhEwq3KQ==} engines: {node: '>=0.4.0'} @@ -14678,6 +14852,8 @@ snapshots: '@tanstack/virtual-core@3.10.9': {} + '@tootallnate/once@2.0.0': {} + '@trpc/client@10.45.2(@trpc/server@10.45.2)': dependencies: '@trpc/server': 10.45.2 @@ -14917,6 +15093,12 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 + '@types/jsdom@20.0.1': + dependencies: + '@types/node': 24.10.9 + '@types/tough-cookie': 4.0.5 + parse5: 7.3.0 + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -15005,6 +15187,8 @@ snapshots: dependencies: '@types/node': 24.10.9 + '@types/tough-cookie@4.0.5': {} + '@types/trusted-types@2.0.7': {} '@types/uuid@8.3.4': {} @@ -15750,6 +15934,8 @@ snapshots: jsonparse: 1.3.1 through: 2.3.8 + abab@2.0.6: {} + abi-wan-kanabi@2.2.4: dependencies: ansicolors: 0.3.2 @@ -15776,6 +15962,11 @@ snapshots: mime-types: 2.1.35 negotiator: 0.6.3 + acorn-globals@7.0.1: + dependencies: + acorn: 8.15.0 + acorn-walk: 8.2.0 + acorn-import-attributes@1.9.5(acorn@8.15.0): dependencies: acorn: 8.15.0 @@ -16673,10 +16864,24 @@ snapshots: cssesc@3.0.0: {} + cssom@0.3.8: {} + + cssom@0.5.0: {} + + cssstyle@2.3.0: + dependencies: + cssom: 0.3.8 + csstype@3.1.3: {} damerau-levenshtein@1.0.8: {} + data-urls@3.0.2: + dependencies: + abab: 2.0.6 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + data-view-buffer@1.0.1: dependencies: call-bind: 1.0.8 @@ -16725,6 +16930,8 @@ snapshots: decimal.js@10.4.3: {} + decimal.js@10.6.0: {} + decode-uri-component@0.2.2: {} dedent@1.5.3: {} @@ -16840,6 +17047,10 @@ snapshots: dependencies: esutils: 2.0.3 + domexception@4.0.0: + dependencies: + webidl-conversions: 7.0.0 + dot-case@3.0.4: dependencies: no-case: 3.0.4 @@ -16929,6 +17140,8 @@ snapshots: ansi-colors: 4.1.3 strip-ansi: 6.0.1 + entities@6.0.1: {} + env-paths@2.2.1: {} error-ex@1.3.2: @@ -17049,6 +17262,14 @@ snapshots: escape-string-regexp@4.0.0: {} + escodegen@2.1.0: + dependencies: + esprima: 4.0.1 + estraverse: 5.3.0 + esutils: 2.0.3 + optionalDependencies: + source-map: 0.6.1 + eslint-config-next@15.0.4(eslint@9.16.0(jiti@2.4.0))(typescript@5.7.2): dependencies: '@next/eslint-plugin-next': 15.0.4 @@ -17878,6 +18099,10 @@ snapshots: '@hpke/dhkem-x25519': 1.6.4 '@hpke/dhkem-x448': 1.6.4 + html-encoding-sniffer@3.0.0: + dependencies: + whatwg-encoding: 2.0.0 + html-escaper@2.0.2: {} http-errors@2.0.0: @@ -17896,6 +18121,14 @@ snapshots: statuses: 2.0.2 toidentifier: 1.0.1 + http-proxy-agent@5.0.0: + dependencies: + '@tootallnate/once': 2.0.0 + agent-base: 6.0.2 + debug: 4.4.0(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + http-shutdown@1.2.2: {} https-proxy-agent@5.0.1: @@ -17934,6 +18167,10 @@ snapshots: dependencies: safer-buffer: 2.1.2 + iconv-lite@0.6.3: + dependencies: + safer-buffer: 2.1.2 + idb-keyval@6.2.1: {} ieee754@1.2.1: {} @@ -18086,6 +18323,8 @@ snapshots: is-plain-obj@2.1.0: {} + is-potential-custom-element-name@1.0.1: {} + is-promise@4.0.0: {} is-regex@1.1.4: @@ -18336,6 +18575,21 @@ snapshots: jest-util: 29.7.0 pretty-format: 29.7.0 + jest-environment-jsdom@29.7.0(bufferutil@4.0.8)(utf-8-validate@5.0.10): + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/jsdom': 20.0.1 + '@types/node': 24.10.9 + jest-mock: 29.7.0 + jest-util: 29.7.0 + jsdom: 20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jest-environment-node@29.7.0: dependencies: '@jest/environment': 29.7.0 @@ -18565,6 +18819,39 @@ snapshots: jsc-safe-url@0.2.4: {} + jsdom@20.0.3(bufferutil@4.0.8)(utf-8-validate@5.0.10): + dependencies: + abab: 2.0.6 + acorn: 8.15.0 + acorn-globals: 7.0.1 + cssom: 0.5.0 + cssstyle: 2.3.0 + data-urls: 3.0.2 + decimal.js: 10.6.0 + domexception: 4.0.0 + escodegen: 2.1.0 + form-data: 4.0.4 + html-encoding-sniffer: 3.0.0 + http-proxy-agent: 5.0.0 + https-proxy-agent: 5.0.1 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.23 + parse5: 7.3.0 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 4.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 2.0.0 + whatwg-mimetype: 3.0.0 + whatwg-url: 11.0.0 + ws: 8.18.3(bufferutil@4.0.8)(utf-8-validate@5.0.10) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@3.0.2: {} json-buffer@3.0.1: {} @@ -19228,6 +19515,8 @@ snapshots: nullthrows@1.1.1: {} + nwsapi@2.2.23: {} + ob1@0.83.3: dependencies: flow-enums-runtime: 0.0.6 @@ -19429,6 +19718,10 @@ snapshots: json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 + parse5@7.3.0: + dependencies: + entities: 6.0.1 + parseurl@1.3.3: {} pascal-case@3.1.2: @@ -19776,6 +20069,10 @@ snapshots: proxy-from-env@1.1.0: {} + psl@1.15.0: + dependencies: + punycode: 2.3.1 + pump@1.0.3: dependencies: end-of-stream: 1.4.4 @@ -19788,6 +20085,8 @@ snapshots: punycode@2.1.1: {} + punycode@2.3.1: {} + pure-rand@6.0.3: {} pvtsutils@1.3.6: @@ -19826,6 +20125,8 @@ snapshots: split-on-first: 1.1.0 strict-uri-encode: 2.0.0 + querystringify@2.2.0: {} + queue-microtask@1.2.3: {} queue@6.0.2: @@ -20149,6 +20450,8 @@ snapshots: require-main-filename@2.0.0: {} + requires-port@1.0.0: {} + resolve-cwd@3.0.0: dependencies: resolve-from: 5.0.0 @@ -20259,6 +20562,10 @@ snapshots: postcss-value-parser: 4.2.0 yoga-layout: 3.2.1 + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + scheduler@0.23.2: dependencies: loose-envify: 1.4.0 @@ -20734,6 +21041,8 @@ snapshots: symbol-observable@2.0.3: {} + symbol-tree@3.2.4: {} + synckit@0.8.4: dependencies: '@pkgr/utils': 2.3.1 @@ -20897,8 +21206,24 @@ snapshots: toidentifier@1.0.1: {} + torph@0.0.5(react-dom@18.3.1(react@18.3.1))(react@18.3.1): + optionalDependencies: + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + + tough-cookie@4.1.4: + dependencies: + psl: 1.15.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + tr46@0.0.3: {} + tr46@3.0.0: + dependencies: + punycode: 2.3.1 + trpc-browser@1.4.4(@trpc/client@10.45.2(@trpc/server@10.45.2))(@trpc/server@10.45.2): dependencies: '@trpc/client': 10.45.2(@trpc/server@10.45.2) @@ -21048,6 +21373,8 @@ snapshots: universalify@0.1.2: {} + universalify@0.2.0: {} + universalify@2.0.1: {} unpipe@1.0.0: {} @@ -21101,6 +21428,11 @@ snapshots: dependencies: punycode: 2.1.1 + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + urql@3.0.3(graphql@16.6.0)(react@18.3.1): dependencies: '@urql/core': 3.0.3(graphql@16.6.0) @@ -21196,6 +21528,10 @@ snapshots: vlq@1.0.1: {} + w3c-xmlserializer@4.0.0: + dependencies: + xml-name-validator: 4.0.0 + wagmi@2.13.0(@react-native-async-storage/async-storage@1.24.0(react-native@0.82.1(@babel/core@7.28.5)(@types/react@18.3.14)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10)))(@tanstack/query-core@5.71.3)(@tanstack/react-query@5.71.3(react@18.3.1))(@types/react@18.3.14)(bufferutil@4.0.8)(immer@10.1.3)(react-dom@18.3.1(react@18.3.1))(react-native@0.82.1(@babel/core@7.28.5)(@types/react@18.3.14)(bufferutil@4.0.8)(react@18.3.1)(utf-8-validate@5.0.10))(react@18.3.1)(typescript@5.7.2)(utf-8-validate@5.0.10)(viem@2.39.3(bufferutil@4.0.8)(typescript@5.7.2)(utf-8-validate@5.0.10)(zod@3.24.2))(zod@3.24.2): dependencies: '@tanstack/react-query': 5.71.3(react@18.3.1) @@ -21241,8 +21577,21 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@7.0.0: {} + + whatwg-encoding@2.0.0: + dependencies: + iconv-lite: 0.6.3 + whatwg-fetch@3.6.20: {} + whatwg-mimetype@3.0.0: {} + + whatwg-url@11.0.0: + dependencies: + tr46: 3.0.0 + webidl-conversions: 7.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -21365,6 +21714,10 @@ snapshots: bufferutil: 4.0.8 utf-8-validate: 5.0.10 + xml-name-validator@4.0.0: {} + + xmlchars@2.2.0: {} + xmlhttprequest-ssl@2.1.2: {} xmlhttprequest-ssl@4.0.0: {} diff --git a/src/components/SafeTextMorph.test.tsx b/src/components/SafeTextMorph.test.tsx new file mode 100644 index 00000000..c5ff9870 --- /dev/null +++ b/src/components/SafeTextMorph.test.tsx @@ -0,0 +1,78 @@ +/** + * @jest-environment jsdom + */ +import { act } from 'react'; +import { createRoot } from 'react-dom/client'; + +import { SafeTextMorph } from './SafeTextMorph'; + +globalThis.IS_REACT_ACT_ENVIRONMENT = true; + +let shouldThrow = false; + +jest.mock('torph/react', () => ({ + TextMorph: ({ children, as: Tag = 'span', ...props }: any) => { + if (shouldThrow) { + throw new Error('TextMorph animation error'); + } + // eslint-disable-next-line @typescript-eslint/no-require-imports + const ReactLib = require('react'); + return ReactLib.createElement(Tag, props, children); + }, +})); + +let container: HTMLDivElement; +let root: ReturnType; + +beforeEach(() => { + shouldThrow = false; + container = document.createElement('div'); + document.body.appendChild(container); + root = createRoot(container); +}); + +afterEach(() => { + act(() => { + root.unmount(); + }); + container.remove(); +}); + +describe('SafeTextMorph', () => { + it('renders children string correctly', () => { + act(() => { + root.render(Hello World); + }); + expect(container.textContent).toBe('Hello World'); + }); + + it('renders fallback when TextMorph throws', () => { + const consoleSpy = jest.spyOn(console, 'error').mockImplementation(() => {}); + shouldThrow = true; + + act(() => { + root.render(Fallback Text); + }); + + expect(container.textContent).toBe('Fallback Text'); + const span = container.querySelector('span'); + expect(span).not.toBeNull(); + expect(consoleSpy).toHaveBeenCalledWith('TextMorph error:', expect.any(Error)); + + consoleSpy.mockRestore(); + }); + + it('handles empty string', () => { + act(() => { + root.render({''}); + }); + expect(container.textContent).toBe(''); + }); + + it('coerces number to string', () => { + act(() => { + root.render({42}); + }); + expect(container.textContent).toBe('42'); + }); +}); diff --git a/src/components/SafeTextMorph.tsx b/src/components/SafeTextMorph.tsx new file mode 100644 index 00000000..da07a04c --- /dev/null +++ b/src/components/SafeTextMorph.tsx @@ -0,0 +1,77 @@ +'use client'; + +import React, { type CSSProperties, type ReactNode } from 'react'; +import { TextMorph } from 'torph/react'; + +type TextMorphErrorBoundaryProps = { + children: ReactNode; + fallbackText: string; + as: keyof JSX.IntrinsicElements; + className?: string; + style?: CSSProperties; +}; + +class TextMorphErrorBoundary extends React.Component< + TextMorphErrorBoundaryProps, + { hasError: boolean } +> { + constructor(props: TextMorphErrorBoundaryProps) { + super(props); + this.state = { hasError: false }; + } + + static getDerivedStateFromError() { + return { hasError: true }; + } + + componentDidCatch(error: Error) { + // eslint-disable-next-line no-console + console.error('TextMorph error:', error); + } + + componentDidUpdate(prevProps: TextMorphErrorBoundaryProps) { + if ( + this.state.hasError && + (prevProps.fallbackText !== this.props.fallbackText || + prevProps.as !== this.props.as || + prevProps.className !== this.props.className || + prevProps.style !== this.props.style) + ) { + this.setState({ hasError: false }); + } + } + + render() { + if (this.state.hasError) { + const { as: Tag, className, style, fallbackText } = this.props; + return React.createElement(Tag, { className, style }, fallbackText); + } + return this.props.children; + } +} + +interface SafeTextMorphProps { + children: string | number | boolean | null | undefined; + as?: keyof JSX.IntrinsicElements; + className?: string; + style?: CSSProperties; + duration?: number; +} + +export function SafeTextMorph({ + children, + as = 'span', + className, + style, + duration, +}: SafeTextMorphProps) { + const textContent = String(children ?? ''); + + return ( + + + {textContent} + + + ); +} diff --git a/src/components/search/SearchFilterBar.tsx b/src/components/search/SearchFilterBar.tsx index 635c9986..4f2460ee 100644 --- a/src/components/search/SearchFilterBar.tsx +++ b/src/components/search/SearchFilterBar.tsx @@ -19,6 +19,7 @@ import { Color } from '../../styles/Color'; import { MessageStatusFilter } from '../../types'; import { SolidButton } from '../buttons/SolidButton'; import { TextButton } from '../buttons/TextButton'; +import { SafeTextMorph } from '../SafeTextMorph'; interface Props { originChain: string | null; @@ -100,7 +101,7 @@ function ChainSelector({ )} onClick={open} > - {chainDisplayName || text} + {chainDisplayName || text} {!value && ( - {hasValue ? currentLabel : 'Status'} + {hasValue ? ( + {currentLabel} + ) : ( + Status + )} {!hasValue && ( -

{`${ - isIcaMsg ? 'ICA ' : '' - } Message ${trimToLength(msgId, 6)} to ${getChainDisplayName( - multiProvider, - destinationChainName, - )}`}

+

+ {`${isIcaMsg ? 'ICA ' : ''} Message ${trimToLength(msgId, 6)} to ${getChainDisplayName( + multiProvider, + destinationChainName, + )}`} +

-

{text}

+

+ {text} +

{icon} ); diff --git a/src/features/messages/MessageTable.tsx b/src/features/messages/MessageTable.tsx index a106cef2..eb875939 100644 --- a/src/features/messages/MessageTable.tsx +++ b/src/features/messages/MessageTable.tsx @@ -1,10 +1,12 @@ import { MultiProtocolProvider } from '@hyperlane-xyz/sdk'; import { shortenAddress } from '@hyperlane-xyz/utils'; +import clsx from 'clsx'; import Image from 'next/image'; import Link from 'next/link'; import { PropsWithChildren, useMemo } from 'react'; import { ChainLogo } from '../../components/icons/ChainLogo'; import { TokenIcon } from '../../components/icons/TokenIcon'; +import { SafeTextMorph } from '../../components/SafeTextMorph'; import CheckmarkIcon from '../../images/icons/checkmark-circle.svg'; import ErrorIcon from '../../images/icons/error-circle.svg'; import { useMultiProvider, useStore } from '../../store'; @@ -42,9 +44,10 @@ export function MessageTable({ {messageList.map((m) => ( -
{getChainDisplayName(mp, originChainName, true)}
+
+ {getChainDisplayName(mp, originChainName, true)} +
-
{getChainDisplayName(mp, destinationChainName, true)}
+
+ {getChainDisplayName(mp, destinationChainName, true)} +
{shortenAddress(formattedSender) || 'Invalid Address'} diff --git a/tsconfig.json b/tsconfig.json index dd9e8846..63d628a8 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,7 +10,7 @@ "jsx": "preserve", "lib": ["dom", "dom.iterable", "esnext"], "module": "esnext", - "moduleResolution": "node", + "moduleResolution": "bundler", "noEmit": true, "noEmitOnError": true, "noFallthroughCasesInSwitch": true, @@ -29,7 +29,8 @@ "include": ["next-env.d.ts", "./src/"], "ts-node": { "compilerOptions": { - "module": "commonjs" + "module": "commonjs", + "moduleResolution": "node" } } }