diff --git a/package.json b/package.json index 3676403..5c0840c 100644 --- a/package.json +++ b/package.json @@ -82,5 +82,17 @@ "volta": { "node": "20.12.2", "pnpm": "9.0.5" + }, + "pnpm": { + "patchedDependencies": { + "signal-polyfill@0.1.0": "patches/signal-polyfill@0.1.0.patch" + } + }, + "dependencies": { + "@testing-library/jest-dom": "^6.4.6", + "@testing-library/react": "^16.0.0", + "@testing-library/user-event": "^14.5.2", + "@vitejs/plugin-react": "^4.3.1", + "react": "^18.3.1" } } diff --git a/patches/signal-polyfill@0.1.0.patch b/patches/signal-polyfill@0.1.0.patch new file mode 100644 index 0000000..ebafb83 --- /dev/null +++ b/patches/signal-polyfill@0.1.0.patch @@ -0,0 +1,78 @@ +diff --git a/dist/index.js b/dist/index.js +index ac1ae216236d55b0a31ca78915f45997b32a5e8b..9edf329d851e0c294cc6e1c9c9f21f934e646c43 100644 +--- a/dist/index.js ++++ b/dist/index.js +@@ -81,7 +81,11 @@ function L(r) { + function nr() { + A++; + } +-function H(r) { ++function H(r, shouldForceRecompute) { ++ if (shouldForceRecompute) { ++ r.producerRecomputeValue(r), r.dirty = !1, r.lastCleanEpoch = A; ++ return ++ } + if (!(D(r) && !r.dirty) && !(!r.dirty && r.lastCleanEpoch === A)) { + if (!r.producerMustRecompute(r) && !fr(r)) { + r.dirty = !1, r.lastCleanEpoch = A; +@@ -171,8 +175,8 @@ function j(r) { + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.io/license + */ +-function Q(r) { +- if (H(r), L(r), r.value === W) ++function Q(r, shouldForceRecompute = false) { ++ if (H(r, shouldForceRecompute), L(r), r.value === W) + throw r.error; + return r.value; + } +@@ -318,12 +322,25 @@ var B; + m && (p.equal = m), p.watched = f[r.subtle.watched], p.unwatched = f[r.subtle.unwatched]; + } + } +- get() { ++ get(shouldForceRecompute = false) { + if (!v(this)) + throw new TypeError( + "Wrong receiver type for Signal.Computed.prototype.get" + ); +- return Q(this[s]); ++ return Q(this[s], shouldForceRecompute); ++ } ++ isPending() { ++ const node = this[s]; ++ r.subtle.introspectSources(this).map((s) => s.get()); ++ if (!node.producerNode?.length) return false ++ ++ for (let len= node.producerNode.length, i = 0; i < len; i++) { ++ debugger ++ if (node.producerNode[i].version !== node.producerLastReadVersion[i]) { ++ return true ++ } ++ } ++ return false + } + } + X = s, S = new WeakSet(), Sr = function() { +@@ -436,6 +453,7 @@ var B; + d.currentComputed = Z, d.watched = Symbol("watched"), d.unwatched = Symbol("unwatched"); + })(r.subtle || (r.subtle = {})); + })(B || (B = {})); ++ + export { + B as Signal + }; +diff --git a/dist/wrapper.d.ts b/dist/wrapper.d.ts +index 8c96d454dc46f9cd069e73325c125eb576f495d5..15beddda67c5f582ab50dbd7a05ce35b9fb6dd36 100644 +--- a/dist/wrapper.d.ts ++++ b/dist/wrapper.d.ts +@@ -15,7 +15,8 @@ export declare namespace Signal { + #private; + readonly [NODE]: ComputedNode; + constructor(computation: () => T, options?: Signal.Options); +- get(): T; ++ get(shouldForceRecompute?: boolean): T; ++ isPending(): boolean; + } + type AnySignal = State | Computed; + type AnySink = Computed | subtle.Watcher; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 6a0c478..52d8f66 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,13 +4,33 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + signal-polyfill@0.1.0: + hash: mvi5cgrb6l747k4iwgeb4hh37q + path: patches/signal-polyfill@0.1.0.patch + importers: .: dependencies: + '@testing-library/jest-dom': + specifier: ^6.4.6 + version: 6.4.6(vitest@1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0)) + '@testing-library/react': + specifier: ^16.0.0 + version: 16.0.0(@testing-library/dom@10.1.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + '@testing-library/user-event': + specifier: ^14.5.2 + version: 14.5.2(@testing-library/dom@10.1.0) + '@vitejs/plugin-react': + specifier: ^4.3.1 + version: 4.3.1(vite@5.2.8(@types/node@20.12.2)) + react: + specifier: ^18.3.1 + version: 18.3.1 signal-polyfill: specifier: ^0.1.0 - version: 0.1.0 + version: 0.1.0(patch_hash=mvi5cgrb6l747k4iwgeb4hh37q) devDependencies: '@babel/core': specifier: ^7.24.4 @@ -29,7 +49,7 @@ importers: version: 7.24.1(@babel/core@7.24.4) '@rollup/plugin-babel': specifier: ^6.0.4 - version: 6.0.4(@babel/core@7.24.4)(rollup@4.14.0) + version: 6.0.4(@babel/core@7.24.4)(@types/babel__core@7.20.5)(rollup@4.14.0) '@tsconfig/strictest': specifier: ^2.0.5 version: 2.0.5 @@ -62,7 +82,20 @@ importers: version: 3.8.1(@types/node@20.12.2)(rollup@4.14.0)(typescript@5.4.3)(vite@5.2.8(@types/node@20.12.2)) vitest: specifier: ^1.4.0 - version: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0) + version: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0) + + react: + dependencies: + react: + specifier: '*' + version: 18.3.1 + devDependencies: + '@types/react': + specifier: ^18.3.3 + version: 18.3.3 + jsdom: + specifier: ^24.1.0 + version: 24.1.0 tests-public: devDependencies: @@ -83,7 +116,7 @@ importers: version: 7.24.1(@babel/core@7.24.4) '@rollup/plugin-babel': specifier: ^6.0.4 - version: 6.0.4(@babel/core@7.24.4)(rollup@4.14.0) + version: 6.0.4(@babel/core@7.24.4)(@types/babel__core@7.20.5)(rollup@4.14.0) '@tsconfig/strictest': specifier: ^2.0.5 version: 2.0.5 @@ -104,7 +137,7 @@ importers: version: 3.2.5 signal-polyfill: specifier: ^0.1.0 - version: 0.1.0 + version: 0.1.0(patch_hash=mvi5cgrb6l747k4iwgeb4hh37q) signal-utils: specifier: workspace:* version: link:.. @@ -116,13 +149,16 @@ importers: version: 5.2.8(@types/node@20.12.2) vitest: specifier: ^1.4.0 - version: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0) + version: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0) webdriverio: specifier: ^8.35.1 version: 8.35.1(encoding@0.1.13)(typescript@5.4.3) packages: + '@adobe/css-tools@4.4.0': + resolution: {integrity: sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==} + '@ampproject/remapping@2.3.0': resolution: {integrity: sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==} engines: {node: '>=6.0.0'} @@ -131,18 +167,34 @@ packages: resolution: {integrity: sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ==} engines: {node: '>=6.9.0'} + '@babel/code-frame@7.24.7': + resolution: {integrity: sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==} + engines: {node: '>=6.9.0'} + '@babel/compat-data@7.24.4': resolution: {integrity: sha512-vg8Gih2MLK+kOkHJp4gBEIkyaIi00jgWot2D9QOmmfLC8jINSOzmCLta6Bvz/JSBCqnegV0L80jhxkol5GWNfQ==} engines: {node: '>=6.9.0'} + '@babel/compat-data@7.24.7': + resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==} + engines: {node: '>=6.9.0'} + '@babel/core@7.24.4': resolution: {integrity: sha512-MBVlMXP+kkl5394RBLSxxk/iLTeVGuXTV3cIDXavPpMMqnSnt6apKgan/U8O3USWZCWZT/TbgfEpKa4uMgN4Dg==} engines: {node: '>=6.9.0'} + '@babel/core@7.24.7': + resolution: {integrity: sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==} + engines: {node: '>=6.9.0'} + '@babel/generator@7.24.4': resolution: {integrity: sha512-Xd6+v6SnjWVx/nus+y0l1sxMOTOMBkyL4+BIdbALyatQnAe/SRVjANeDPSCYaX+i1iJmuGSKf3Z+E+V/va1Hvw==} engines: {node: '>=6.9.0'} + '@babel/generator@7.24.7': + resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==} + engines: {node: '>=6.9.0'} + '@babel/helper-annotate-as-pure@7.22.5': resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} engines: {node: '>=6.9.0'} @@ -151,6 +203,10 @@ packages: resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} engines: {node: '>=6.9.0'} + '@babel/helper-compilation-targets@7.24.7': + resolution: {integrity: sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==} + engines: {node: '>=6.9.0'} + '@babel/helper-create-class-features-plugin@7.24.1': resolution: {integrity: sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA==} engines: {node: '>=6.9.0'} @@ -167,14 +223,26 @@ packages: resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} engines: {node: '>=6.9.0'} + '@babel/helper-environment-visitor@7.24.7': + resolution: {integrity: sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-function-name@7.23.0': resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} engines: {node: '>=6.9.0'} + '@babel/helper-function-name@7.24.7': + resolution: {integrity: sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==} + engines: {node: '>=6.9.0'} + '@babel/helper-hoist-variables@7.22.5': resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} engines: {node: '>=6.9.0'} + '@babel/helper-hoist-variables@7.24.7': + resolution: {integrity: sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==} + engines: {node: '>=6.9.0'} + '@babel/helper-member-expression-to-functions@7.23.0': resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} engines: {node: '>=6.9.0'} @@ -183,12 +251,22 @@ packages: resolution: {integrity: sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg==} engines: {node: '>=6.9.0'} + '@babel/helper-module-imports@7.24.7': + resolution: {integrity: sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==} + engines: {node: '>=6.9.0'} + '@babel/helper-module-transforms@7.23.3': resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} engines: {node: '>=6.9.0'} peerDependencies: '@babel/core': ^7.0.0 + '@babel/helper-module-transforms@7.24.7': + resolution: {integrity: sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + '@babel/helper-optimise-call-expression@7.22.5': resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} engines: {node: '>=6.9.0'} @@ -197,6 +275,10 @@ packages: resolution: {integrity: sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w==} engines: {node: '>=6.9.0'} + '@babel/helper-plugin-utils@7.24.7': + resolution: {integrity: sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==} + engines: {node: '>=6.9.0'} + '@babel/helper-replace-supers@7.24.1': resolution: {integrity: sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ==} engines: {node: '>=6.9.0'} @@ -207,6 +289,10 @@ packages: resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} engines: {node: '>=6.9.0'} + '@babel/helper-simple-access@7.24.7': + resolution: {integrity: sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==} + engines: {node: '>=6.9.0'} + '@babel/helper-skip-transparent-expression-wrappers@7.22.5': resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} engines: {node: '>=6.9.0'} @@ -215,26 +301,50 @@ packages: resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} engines: {node: '>=6.9.0'} + '@babel/helper-split-export-declaration@7.24.7': + resolution: {integrity: sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==} + engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.24.1': resolution: {integrity: sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==} engines: {node: '>=6.9.0'} + '@babel/helper-string-parser@7.24.7': + resolution: {integrity: sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.22.20': resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-identifier@7.24.7': + resolution: {integrity: sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==} + engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.23.5': resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} + '@babel/helper-validator-option@7.24.7': + resolution: {integrity: sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==} + engines: {node: '>=6.9.0'} + '@babel/helpers@7.24.4': resolution: {integrity: sha512-FewdlZbSiwaVGlgT1DPANDuCHaDMiOo+D/IDYRFYjHOuv66xMSJ7fQwwODwRNAPkADIO/z1EoF/l2BCWlWABDw==} engines: {node: '>=6.9.0'} + '@babel/helpers@7.24.7': + resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==} + engines: {node: '>=6.9.0'} + '@babel/highlight@7.24.2': resolution: {integrity: sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA==} engines: {node: '>=6.9.0'} + '@babel/highlight@7.24.7': + resolution: {integrity: sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==} + engines: {node: '>=6.9.0'} + '@babel/parser@7.24.1': resolution: {integrity: sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==} engines: {node: '>=6.0.0'} @@ -245,6 +355,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + '@babel/parser@7.24.7': + resolution: {integrity: sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==} + engines: {node: '>=6.0.0'} + hasBin: true + '@babel/plugin-proposal-decorators@7.24.1': resolution: {integrity: sha512-zPEvzFijn+hRvJuX2Vu3KbEBN39LN3f7tW3MQO2LsIs57B26KU+kUc82BdAktS1VCM6libzh45eKGI65lg0cpA==} engines: {node: '>=6.9.0'} @@ -275,6 +390,18 @@ packages: peerDependencies: '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-react-jsx-self@7.24.7': + resolution: {integrity: sha512-fOPQYbGSgH0HUp4UJO4sMBFjY6DuWq+2i8rixyUMb3CdGixs/gccURvYOAhajBdKDoGajFr3mUq5rH3phtkGzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + + '@babel/plugin-transform-react-jsx-source@7.24.7': + resolution: {integrity: sha512-J2z+MWzZHVOemyLweMqngXrgGC42jQ//R0KdxqkIz/OrbVIIlhFI3WigZ5fO+nwFvBlncr4MGapd8vTyc7RPNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + '@babel/plugin-transform-typescript@7.24.4': resolution: {integrity: sha512-79t3CQ8+oBGk/80SQ8MN3Bs3obf83zJ0YZjDmDaEZN8MqhMI760apl5z6a20kFeMXBwJX99VpKT8CKxEBp5H1g==} engines: {node: '>=6.9.0'} @@ -295,14 +422,26 @@ packages: resolution: {integrity: sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA==} engines: {node: '>=6.9.0'} + '@babel/template@7.24.7': + resolution: {integrity: sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==} + engines: {node: '>=6.9.0'} + '@babel/traverse@7.24.1': resolution: {integrity: sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ==} engines: {node: '>=6.9.0'} + '@babel/traverse@7.24.7': + resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==} + engines: {node: '>=6.9.0'} + '@babel/types@7.24.0': resolution: {integrity: sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w==} engines: {node: '>=6.9.0'} + '@babel/types@7.24.7': + resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==} + engines: {node: '>=6.9.0'} + '@esbuild/aix-ppc64@0.20.2': resolution: {integrity: sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==} engines: {node: '>=12'} @@ -748,6 +887,52 @@ packages: resolution: {integrity: sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==} engines: {node: '>=14.16'} + '@testing-library/dom@10.1.0': + resolution: {integrity: sha512-wdsYKy5zupPyLCW2Je5DLHSxSfbIp6h80WoHOQc+RPtmPGA52O9x5MJEkv92Sjonpq+poOAtUKhh1kBGAXBrNA==} + engines: {node: '>=18'} + + '@testing-library/jest-dom@6.4.6': + resolution: {integrity: sha512-8qpnGVincVDLEcQXWaHOf6zmlbwTKc6Us6PPu4CRnPXCzo2OGBS5cwgMMOWdxDpEz1mkbvXHpEy99M5Yvt682w==} + engines: {node: '>=14', npm: '>=6', yarn: '>=1'} + peerDependencies: + '@jest/globals': '>= 28' + '@types/bun': latest + '@types/jest': '>= 28' + jest: '>= 28' + vitest: '>= 0.32' + peerDependenciesMeta: + '@jest/globals': + optional: true + '@types/bun': + optional: true + '@types/jest': + optional: true + jest: + optional: true + vitest: + optional: true + + '@testing-library/react@16.0.0': + resolution: {integrity: sha512-guuxUKRWQ+FgNX0h0NS0FIq3Q3uLtWVpBzcLOggmfMoUpgBnzBzvLLd4fbm6yS8ydJd94cIfY4yP9qUQjM2KwQ==} + engines: {node: '>=18'} + peerDependencies: + '@testing-library/dom': ^10.0.0 + '@types/react': ^18.0.0 + '@types/react-dom': ^18.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 + peerDependenciesMeta: + '@types/react': + optional: true + '@types/react-dom': + optional: true + + '@testing-library/user-event@14.5.2': + resolution: {integrity: sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==} + engines: {node: '>=12', npm: '>=6'} + peerDependencies: + '@testing-library/dom': '>=7.21.4' + '@tootallnate/once@1.1.2': resolution: {integrity: sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==} engines: {node: '>= 6'} @@ -761,6 +946,21 @@ packages: '@types/argparse@1.0.38': resolution: {integrity: sha512-ebDJ9b0e702Yr7pWgB0jzm+CX4Srzz8RcXtLJDJB+BSccqMa36uyH/zUsSYao5+BD1ytv3k3rPYCq4mAE1hsXA==} + '@types/aria-query@5.0.4': + resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} + + '@types/babel__core@7.20.5': + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + + '@types/babel__generator@7.6.8': + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + + '@types/babel__template@7.4.4': + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + + '@types/babel__traverse@7.20.6': + resolution: {integrity: sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==} + '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} @@ -779,6 +979,12 @@ packages: '@types/node@20.12.2': resolution: {integrity: sha512-zQ0NYO87hyN6Xrclcqp7f8ZbXNbRfoGWNcMvHTPQp9UUrwI0mI7XBz+cu7/W6/VClYo2g63B0cjull/srU7LgQ==} + '@types/prop-types@15.7.12': + resolution: {integrity: sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==} + + '@types/react@18.3.3': + resolution: {integrity: sha512-hti/R0pS0q1/xx+TsI73XIqk26eBsISZ2R0wUijXIngRK9R/e7Xw/cXVxQK7R5JjW+SV4zGcn5hXjudkN/pLIw==} + '@types/responselike@1.0.3': resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} @@ -800,6 +1006,12 @@ packages: '@types/yauzl@2.10.3': resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + '@vitejs/plugin-react@4.3.1': + resolution: {integrity: sha512-m/V2syj5CuVnaxcUJOQRel/Wr31FFXRFlnOoq1TVtkCxsY5veGMTEmpWHndrhB2U8ScHtCQB1e+4hWYExQc6Lg==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.2.0 || ^5.0.0 + '@vitest/browser@1.4.0': resolution: {integrity: sha512-kC44DzuqPZZrqe2P7SX2a3zHDAt919WtpkUMAxzv9eP5uPfVXtpk2Ipms2NXJGY5190aJc1uY+ambfJ3rwDJRA==} peerDependencies: @@ -977,6 +1189,9 @@ packages: async@3.2.5: resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + b4a@1.6.6: resolution: {integrity: sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg==} @@ -1088,6 +1303,10 @@ packages: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} + chalk@3.0.0: + resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==} + engines: {node: '>=8'} + chalk@4.1.2: resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} engines: {node: '>=10'} @@ -1140,6 +1359,10 @@ packages: color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@9.5.0: resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} engines: {node: ^12.20.0 || >=14} @@ -1187,6 +1410,16 @@ packages: css-value@0.0.1: resolution: {integrity: sha512-FUV3xaJ63buRLgHrLQVlVgQnQdR4yqdLGaDu7g8CQcWjInDfM9plBTPI9FRfpahju1UBSaMckeb2/46ApS/V1Q==} + css.escape@1.5.1: + resolution: {integrity: sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg==} + + cssstyle@4.0.1: + resolution: {integrity: sha512-8ZYiJ3A/3OkDd093CBT/0UKDWry7ak4BdPTFP2+QEP7cmhouyq/Up709ASSj2cK02BbZiMgk7kYjZNS4QP5qrQ==} + engines: {node: '>=18'} + + csstype@3.1.3: + resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} + data-uri-to-buffer@4.0.1: resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==} engines: {node: '>= 12'} @@ -1195,6 +1428,10 @@ packages: resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} engines: {node: '>= 14'} + data-urls@5.0.0: + resolution: {integrity: sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==} + engines: {node: '>=18'} + date-fns@2.30.0: resolution: {integrity: sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==} engines: {node: '>=0.11'} @@ -1215,6 +1452,9 @@ packages: resolution: {integrity: sha512-Fv96DCsdOgB6mdGl67MT5JaTNKRzrzill5OH5s8bjYJXVlcXyPYGyPsUkWyGV5p1TXI5esYIYMMeDJL0hEIwaA==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + decimal.js@10.4.3: + resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==} + decompress-response@3.3.0: resolution: {integrity: sha512-BzRPQuY1ip+qDonAOz42gRm/pg9F768C+npV/4JOsxRC2sq+Rlk+Q4ZCAsOhnIaMrgarILY+RMUIvMmmX1qAEA==} engines: {node: '>=4'} @@ -1246,6 +1486,10 @@ packages: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + deprecation@2.3.1: resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} @@ -1267,6 +1511,12 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} + dom-accessibility-api@0.5.16: + resolution: {integrity: sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==} + + dom-accessibility-api@0.6.3: + resolution: {integrity: sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==} + duplexer2@0.1.4: resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} @@ -1420,6 +1670,10 @@ packages: resolution: {integrity: sha512-yDYSgNMraqvnxiEXO4hi88+YZxaHC6QKzb5N84iRCTDeRO7ZALpir/lVmf/uXUhnwUr2O4HU8s/n6x+yNjQkHw==} engines: {node: '>= 14.17'} + form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + formdata-polyfill@4.0.10: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} @@ -1569,6 +1823,10 @@ packages: resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} engines: {node: ^16.14.0 || >=18.0.0} + html-encoding-sniffer@4.0.0: + resolution: {integrity: sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==} + engines: {node: '>=18'} + http-cache-semantics@4.1.1: resolution: {integrity: sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==} @@ -1679,6 +1937,9 @@ packages: resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} engines: {node: '>=0.10.0'} + is-potential-custom-element-name@1.0.1: + resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-stream@2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} engines: {node: '>=8'} @@ -1721,6 +1982,15 @@ packages: jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} + jsdom@24.1.0: + resolution: {integrity: sha512-6gpM7pRXCwIOKxX47cgOyvyQDN/Eh0f1MeKySBV2xGdKtqJBLj8P25eY3EVCWo2mglDDzozR2r2MW4T+JiNUZA==} + engines: {node: '>=18'} + peerDependencies: + canvas: ^2.11.2 + peerDependenciesMeta: + canvas: + optional: true + jsesc@2.5.2: resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} engines: {node: '>=4'} @@ -1810,6 +2080,10 @@ packages: resolution: {integrity: sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==} engines: {node: '>= 0.6.0'} + loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + loupe@2.3.7: resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} @@ -1840,6 +2114,10 @@ packages: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} + lz-string@1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} + hasBin: true + magic-string@0.30.8: resolution: {integrity: sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==} engines: {node: '>=12'} @@ -1859,6 +2137,14 @@ packages: resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} @@ -1879,6 +2165,10 @@ packages: resolution: {integrity: sha512-e5ISH9xMYU0DzrT+jl8q2ze9D6eWBto+I8CNpe+VI+K2J/F/k3PdkdTdz4wvGVH4NTpo+NRYTVIuMQEMMcsLqg==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + min-indent@1.0.1: + resolution: {integrity: sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==} + engines: {node: '>=4'} + minimatch@3.0.8: resolution: {integrity: sha512-6FsRAQsxQ61mw+qP1ZzbL9Bc78x2p5OqNgNpnoAFLTrX8n5Kxph0CsnhmKKNXTWjXqU5L0pGPR7hYk+XWZr60Q==} @@ -2042,6 +2332,9 @@ packages: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + nwsapi@2.2.10: + resolution: {integrity: sha512-QK0sRs7MKv0tKe1+5uZIQk/C8XGza4DAnztJG8iD+TpJIORARrCxczA738awHrZoHeTjSSoHqao2teO0dC/gFQ==} + object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -2113,6 +2406,9 @@ packages: parse5@6.0.1: resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + parse5@7.1.2: + resolution: {integrity: sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw==} + path-browserify@1.0.1: resolution: {integrity: sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==} @@ -2183,6 +2479,10 @@ packages: engines: {node: '>=14'} hasBin: true + pretty-format@27.5.1: + resolution: {integrity: sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==} + engines: {node: ^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0} + pretty-format@29.7.0: resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -2225,6 +2525,9 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + psl@1.9.0: + resolution: {integrity: sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==} + pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} @@ -2244,6 +2547,9 @@ packages: query-selector-shadow-dom@1.0.1: resolution: {integrity: sha512-lT5yCqEBgfoMYpf3F2xQRK7zEr1rhIIZuceDK6+xRkJQ4NMbHTwXqk4NkwDwQMNqXgG9r9fyHnzwNVs6zV5KRw==} + querystringify@2.2.0: + resolution: {integrity: sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2258,9 +2564,25 @@ packages: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true + react-dom@18.3.1: + resolution: {integrity: sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==} + peerDependencies: + react: ^18.3.1 + + react-is@17.0.2: + resolution: {integrity: sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==} + react-is@18.2.0: resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + react-refresh@0.14.2: + resolution: {integrity: sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==} + engines: {node: '>=0.10.0'} + + react@18.3.1: + resolution: {integrity: sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==} + engines: {node: '>=0.10.0'} + read-yaml-file@1.1.0: resolution: {integrity: sha512-VIMnQi/Z4HT2Fxuwg5KrY174U1VdUIASQVWXXyqtNRtxSr9IYkn1rsI6Tb6HsrHCmB7gVpNwX6JxPTHcH6IoTA==} engines: {node: '>=6'} @@ -2275,6 +2597,10 @@ packages: readdir-glob@1.1.3: resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==} + redent@3.0.0: + resolution: {integrity: sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==} + engines: {node: '>=8'} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -2294,6 +2620,9 @@ packages: resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} engines: {node: '>=0.10.0'} + requires-port@1.0.0: + resolution: {integrity: sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==} + resolve-alpn@1.2.1: resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} @@ -2338,6 +2667,12 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rrweb-cssom@0.6.0: + resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} + + rrweb-cssom@0.7.1: + resolution: {integrity: sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==} + run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} @@ -2356,6 +2691,13 @@ packages: safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + saxes@6.0.0: + resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==} + engines: {node: '>=v12.22.7'} + + scheduler@0.23.2: + resolution: {integrity: sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==} + semver@6.3.1: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true @@ -2513,6 +2855,10 @@ packages: resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} engines: {node: '>=12'} + strip-indent@3.0.0: + resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==} + engines: {node: '>=8'} + strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -2540,6 +2886,9 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} + symbol-tree@3.2.4: + resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + tar-fs@3.0.4: resolution: {integrity: sha512-5AFQU8b9qLfZCX9zp2duONhPmZv0hGYiBPJsyUdqMjzq/mqVpy/rEUSeHk1+YitmxugaptgBh5oDGU3VsAJq4w==} @@ -2590,9 +2939,17 @@ packages: resolution: {integrity: sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==} engines: {node: '>=6'} + tough-cookie@4.1.4: + resolution: {integrity: sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==} + engines: {node: '>=6'} + tr46@0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + tr46@5.0.0: + resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} + engines: {node: '>=18'} + traverse@0.3.9: resolution: {integrity: sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==} @@ -2651,6 +3008,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'} @@ -2671,6 +3032,9 @@ packages: resolution: {integrity: sha512-NjFKA0DidqPa5ciFcSrXnAltTtzz84ogy+NebPvfEgAck0+TNg4UJ4IN+fB7zRZfbgUf0syOo9MDxFkDSMuFaQ==} engines: {node: '>=4'} + url-parse@1.5.10: + resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + userhome@1.0.0: resolution: {integrity: sha512-ayFKY3H+Pwfy4W98yPdtH1VqH4psDeyW8lYYFzfecR9d6hqLpqhecktvYR3SEEXt7vG0S1JEpciI3g94pMErig==} engines: {node: '>= 0.8.0'} @@ -2766,6 +3130,10 @@ packages: peerDependencies: typescript: '*' + w3c-xmlserializer@5.0.0: + resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} + engines: {node: '>=18'} + wait-port@1.1.0: resolution: {integrity: sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q==} engines: {node: '>=10'} @@ -2791,6 +3159,22 @@ 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@3.1.1: + resolution: {integrity: sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==} + engines: {node: '>=18'} + + whatwg-mimetype@4.0.0: + resolution: {integrity: sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==} + engines: {node: '>=18'} + + whatwg-url@14.0.0: + resolution: {integrity: sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==} + engines: {node: '>=18'} + whatwg-url@5.0.0: resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} @@ -2844,6 +3228,25 @@ packages: utf-8-validate: optional: true + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + xml-name-validator@5.0.0: + resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} + engines: {node: '>=18'} + + xmlchars@2.2.0: + resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} + y18n@5.0.8: resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} engines: {node: '>=10'} @@ -2892,6 +3295,8 @@ packages: snapshots: + '@adobe/css-tools@4.4.0': {} + '@ampproject/remapping@2.3.0': dependencies: '@jridgewell/gen-mapping': 0.3.5 @@ -2902,8 +3307,15 @@ snapshots: '@babel/highlight': 7.24.2 picocolors: 1.0.0 + '@babel/code-frame@7.24.7': + dependencies: + '@babel/highlight': 7.24.7 + picocolors: 1.0.0 + '@babel/compat-data@7.24.4': {} + '@babel/compat-data@7.24.7': {} + '@babel/core@7.24.4': dependencies: '@ampproject/remapping': 2.3.0 @@ -2924,6 +3336,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/core@7.24.7': + dependencies: + '@ampproject/remapping': 2.3.0 + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-compilation-targets': 7.24.7 + '@babel/helper-module-transforms': 7.24.7(@babel/core@7.24.7) + '@babel/helpers': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/template': 7.24.7 + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + '@babel/generator@7.24.4': dependencies: '@babel/types': 7.24.0 @@ -2931,6 +3363,13 @@ snapshots: '@jridgewell/trace-mapping': 0.3.25 jsesc: 2.5.2 + '@babel/generator@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@jridgewell/gen-mapping': 0.3.5 + '@jridgewell/trace-mapping': 0.3.25 + jsesc: 2.5.2 + '@babel/helper-annotate-as-pure@7.22.5': dependencies: '@babel/types': 7.24.0 @@ -2943,6 +3382,14 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 + '@babel/helper-compilation-targets@7.24.7': + dependencies: + '@babel/compat-data': 7.24.7 + '@babel/helper-validator-option': 7.24.7 + browserslist: 4.23.0 + lru-cache: 5.1.1 + semver: 6.3.1 + '@babel/helper-create-class-features-plugin@7.24.1(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -2971,15 +3418,28 @@ snapshots: '@babel/helper-environment-visitor@7.22.20': {} + '@babel/helper-environment-visitor@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@babel/helper-function-name@7.23.0': dependencies: '@babel/template': 7.24.0 '@babel/types': 7.24.0 + '@babel/helper-function-name@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + '@babel/helper-hoist-variables@7.22.5': dependencies: '@babel/types': 7.24.0 + '@babel/helper-hoist-variables@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@babel/helper-member-expression-to-functions@7.23.0': dependencies: '@babel/types': 7.24.0 @@ -2988,6 +3448,13 @@ snapshots: dependencies: '@babel/types': 7.24.0 + '@babel/helper-module-imports@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-module-transforms@7.23.3(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -2997,12 +3464,25 @@ snapshots: '@babel/helper-split-export-declaration': 7.22.6 '@babel/helper-validator-identifier': 7.22.20 + '@babel/helper-module-transforms@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-module-imports': 7.24.7 + '@babel/helper-simple-access': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-optimise-call-expression@7.22.5': dependencies: '@babel/types': 7.24.0 '@babel/helper-plugin-utils@7.24.0': {} + '@babel/helper-plugin-utils@7.24.7': {} + '@babel/helper-replace-supers@7.24.1(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -3014,6 +3494,13 @@ snapshots: dependencies: '@babel/types': 7.24.0 + '@babel/helper-simple-access@7.24.7': + dependencies: + '@babel/traverse': 7.24.7 + '@babel/types': 7.24.7 + transitivePeerDependencies: + - supports-color + '@babel/helper-skip-transparent-expression-wrappers@7.22.5': dependencies: '@babel/types': 7.24.0 @@ -3022,12 +3509,22 @@ snapshots: dependencies: '@babel/types': 7.24.0 + '@babel/helper-split-export-declaration@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@babel/helper-string-parser@7.24.1': {} + '@babel/helper-string-parser@7.24.7': {} + '@babel/helper-validator-identifier@7.22.20': {} + '@babel/helper-validator-identifier@7.24.7': {} + '@babel/helper-validator-option@7.23.5': {} + '@babel/helper-validator-option@7.24.7': {} + '@babel/helpers@7.24.4': dependencies: '@babel/template': 7.24.0 @@ -3036,6 +3533,11 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/helpers@7.24.7': + dependencies: + '@babel/template': 7.24.7 + '@babel/types': 7.24.7 + '@babel/highlight@7.24.2': dependencies: '@babel/helper-validator-identifier': 7.22.20 @@ -3043,6 +3545,13 @@ snapshots: js-tokens: 4.0.0 picocolors: 1.0.0 + '@babel/highlight@7.24.7': + dependencies: + '@babel/helper-validator-identifier': 7.24.7 + chalk: 2.4.2 + js-tokens: 4.0.0 + picocolors: 1.0.0 + '@babel/parser@7.24.1': dependencies: '@babel/types': 7.24.0 @@ -3051,6 +3560,10 @@ snapshots: dependencies: '@babel/types': 7.24.0 + '@babel/parser@7.24.7': + dependencies: + '@babel/types': 7.24.7 + '@babel/plugin-proposal-decorators@7.24.1(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -3080,6 +3593,16 @@ snapshots: '@babel/helper-plugin-utils': 7.24.0 '@babel/helper-simple-access': 7.22.5 + '@babel/plugin-transform-react-jsx-self@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + + '@babel/plugin-transform-react-jsx-source@7.24.7(@babel/core@7.24.7)': + dependencies: + '@babel/core': 7.24.7 + '@babel/helper-plugin-utils': 7.24.7 + '@babel/plugin-transform-typescript@7.24.4(@babel/core@7.24.4)': dependencies: '@babel/core': 7.24.4 @@ -3107,6 +3630,12 @@ snapshots: '@babel/parser': 7.24.1 '@babel/types': 7.24.0 + '@babel/template@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + '@babel/traverse@7.24.1': dependencies: '@babel/code-frame': 7.24.2 @@ -3122,12 +3651,33 @@ snapshots: transitivePeerDependencies: - supports-color + '@babel/traverse@7.24.7': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/generator': 7.24.7 + '@babel/helper-environment-visitor': 7.24.7 + '@babel/helper-function-name': 7.24.7 + '@babel/helper-hoist-variables': 7.24.7 + '@babel/helper-split-export-declaration': 7.24.7 + '@babel/parser': 7.24.7 + '@babel/types': 7.24.7 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + '@babel/types@7.24.0': dependencies: '@babel/helper-string-parser': 7.24.1 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 + '@babel/types@7.24.7': + dependencies: + '@babel/helper-string-parser': 7.24.7 + '@babel/helper-validator-identifier': 7.24.7 + to-fast-properties: 2.0.0 + '@esbuild/aix-ppc64@0.20.2': optional: true @@ -3445,12 +3995,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@rollup/plugin-babel@6.0.4(@babel/core@7.24.4)(rollup@4.14.0)': + '@rollup/plugin-babel@6.0.4(@babel/core@7.24.4)(@types/babel__core@7.20.5)(rollup@4.14.0)': dependencies: '@babel/core': 7.24.4 '@babel/helper-module-imports': 7.24.3 '@rollup/pluginutils': 5.1.0(rollup@4.14.0) optionalDependencies: + '@types/babel__core': 7.20.5 rollup: 4.14.0 '@rollup/pluginutils@5.1.0(rollup@4.14.0)': @@ -3554,6 +4105,43 @@ snapshots: dependencies: defer-to-connect: 2.0.1 + '@testing-library/dom@10.1.0': + dependencies: + '@babel/code-frame': 7.24.7 + '@babel/runtime': 7.24.1 + '@types/aria-query': 5.0.4 + aria-query: 5.3.0 + chalk: 4.1.2 + dom-accessibility-api: 0.5.16 + lz-string: 1.5.0 + pretty-format: 27.5.1 + + '@testing-library/jest-dom@6.4.6(vitest@1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0))': + dependencies: + '@adobe/css-tools': 4.4.0 + '@babel/runtime': 7.24.1 + aria-query: 5.3.0 + chalk: 3.0.0 + css.escape: 1.5.1 + dom-accessibility-api: 0.6.3 + lodash: 4.17.21 + redent: 3.0.0 + optionalDependencies: + vitest: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0) + + '@testing-library/react@16.0.0(@testing-library/dom@10.1.0)(@types/react@18.3.3)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + dependencies: + '@babel/runtime': 7.24.1 + '@testing-library/dom': 10.1.0 + react: 18.3.1 + react-dom: 18.3.1(react@18.3.1) + optionalDependencies: + '@types/react': 18.3.3 + + '@testing-library/user-event@14.5.2(@testing-library/dom@10.1.0)': + dependencies: + '@testing-library/dom': 10.1.0 + '@tootallnate/once@1.1.2': {} '@tootallnate/quickjs-emscripten@0.23.0': {} @@ -3562,6 +4150,29 @@ snapshots: '@types/argparse@1.0.38': {} + '@types/aria-query@5.0.4': {} + + '@types/babel__core@7.20.5': + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.6 + + '@types/babel__generator@7.6.8': + dependencies: + '@babel/types': 7.24.0 + + '@types/babel__template@7.4.4': + dependencies: + '@babel/parser': 7.24.4 + '@babel/types': 7.24.0 + + '@types/babel__traverse@7.20.6': + dependencies: + '@babel/types': 7.24.0 + '@types/estree@1.0.5': {} '@types/fs-extra@9.0.13': @@ -3580,6 +4191,13 @@ snapshots: dependencies: undici-types: 5.26.5 + '@types/prop-types@15.7.12': {} + + '@types/react@18.3.3': + dependencies: + '@types/prop-types': 15.7.12 + csstype: 3.1.3 + '@types/responselike@1.0.3': dependencies: '@types/node': 20.12.2 @@ -3603,12 +4221,23 @@ snapshots: '@types/node': 20.12.2 optional: true + '@vitejs/plugin-react@4.3.1(vite@5.2.8(@types/node@20.12.2))': + dependencies: + '@babel/core': 7.24.7 + '@babel/plugin-transform-react-jsx-self': 7.24.7(@babel/core@7.24.7) + '@babel/plugin-transform-react-jsx-source': 7.24.7(@babel/core@7.24.7) + '@types/babel__core': 7.20.5 + react-refresh: 0.14.2 + vite: 5.2.8(@types/node@20.12.2) + transitivePeerDependencies: + - supports-color + '@vitest/browser@1.4.0(vitest@1.4.0)(webdriverio@8.35.1(encoding@0.1.13)(typescript@5.4.3))': dependencies: '@vitest/utils': 1.4.0 magic-string: 0.30.8 sirv: 2.0.4 - vitest: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0) + vitest: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0) optionalDependencies: webdriverio: 8.35.1(encoding@0.1.13)(typescript@5.4.3) @@ -3643,7 +4272,7 @@ snapshots: pathe: 1.1.2 picocolors: 1.0.0 sirv: 2.0.4 - vitest: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0) + vitest: 1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0) '@vitest/utils@1.4.0': dependencies: @@ -3837,6 +4466,8 @@ snapshots: async@3.2.5: {} + asynckit@0.4.0: {} + b4a@1.6.6: {} balanced-match@1.0.2: {} @@ -3985,6 +4616,11 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 5.5.0 + chalk@3.0.0: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + chalk@4.1.2: dependencies: ansi-styles: 4.3.0 @@ -4042,6 +4678,10 @@ snapshots: color-name@1.1.4: {} + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@9.5.0: {} compress-commons@6.0.2: @@ -4095,10 +4735,23 @@ snapshots: css-value@0.0.1: {} + css.escape@1.5.1: {} + + cssstyle@4.0.1: + dependencies: + rrweb-cssom: 0.6.0 + + csstype@3.1.3: {} + data-uri-to-buffer@4.0.1: {} data-uri-to-buffer@6.0.2: {} + data-urls@5.0.0: + dependencies: + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + date-fns@2.30.0: dependencies: '@babel/runtime': 7.24.1 @@ -4111,6 +4764,8 @@ snapshots: decamelize@6.0.0: {} + decimal.js@10.4.3: {} + decompress-response@3.3.0: dependencies: mimic-response: 1.0.1 @@ -4137,6 +4792,8 @@ snapshots: escodegen: 2.1.0 esprima: 4.0.1 + delayed-stream@1.0.0: {} + deprecation@2.3.1: {} dequal@2.0.3: {} @@ -4151,6 +4808,10 @@ snapshots: dependencies: path-type: 4.0.0 + dom-accessibility-api@0.5.16: {} + + dom-accessibility-api@0.6.3: {} + duplexer2@0.1.4: dependencies: readable-stream: 2.3.8 @@ -4343,6 +5004,12 @@ snapshots: form-data-encoder@2.1.4: {} + form-data@4.0.0: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + formdata-polyfill@4.0.10: dependencies: fetch-blob: 3.2.0 @@ -4541,6 +5208,10 @@ snapshots: dependencies: lru-cache: 10.2.0 + html-encoding-sniffer@4.0.0: + dependencies: + whatwg-encoding: 3.1.1 + http-cache-semantics@4.1.1: {} http-proxy-agent@4.0.1: @@ -4590,7 +5261,6 @@ snapshots: iconv-lite@0.6.3: dependencies: safer-buffer: 2.1.2 - optional: true ieee754@1.2.1: {} @@ -4640,6 +5310,8 @@ snapshots: is-plain-object@5.0.0: {} + is-potential-custom-element-name@1.0.1: {} + is-stream@2.0.1: {} is-stream@3.0.0: {} @@ -4673,6 +5345,34 @@ snapshots: jsbn@1.1.0: {} + jsdom@24.1.0: + dependencies: + cssstyle: 4.0.1 + data-urls: 5.0.0 + decimal.js: 10.4.3 + form-data: 4.0.0 + html-encoding-sniffer: 4.0.0 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + is-potential-custom-element-name: 1.0.1 + nwsapi: 2.2.10 + parse5: 7.1.2 + rrweb-cssom: 0.7.1 + saxes: 6.0.0 + symbol-tree: 3.2.4 + tough-cookie: 4.1.4 + w3c-xmlserializer: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-encoding: 3.1.1 + whatwg-mimetype: 4.0.0 + whatwg-url: 14.0.0 + ws: 8.17.1 + xml-name-validator: 5.0.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + jsesc@2.5.2: {} json-buffer@3.0.0: {} @@ -4748,6 +5448,10 @@ snapshots: loglevel@1.9.1: {} + loose-envify@1.4.0: + dependencies: + js-tokens: 4.0.0 + loupe@2.3.7: dependencies: get-func-name: 2.0.2 @@ -4770,6 +5474,8 @@ snapshots: lru-cache@7.18.3: {} + lz-string@1.5.0: {} + magic-string@0.30.8: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 @@ -4805,6 +5511,12 @@ snapshots: braces: 3.0.2 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + mimic-fn@2.1.0: {} mimic-fn@4.0.0: {} @@ -4815,6 +5527,8 @@ snapshots: mimic-response@4.0.0: {} + min-indent@1.0.1: {} + minimatch@3.0.8: dependencies: brace-expansion: 1.1.11 @@ -4966,6 +5680,8 @@ snapshots: dependencies: path-key: 4.0.0 + nwsapi@2.2.10: {} + object-assign@4.1.1: {} once@1.4.0: @@ -5041,6 +5757,10 @@ snapshots: parse5@6.0.1: {} + parse5@7.1.2: + dependencies: + entities: 4.5.0 + path-browserify@1.0.1: {} path-exists@4.0.0: {} @@ -5090,6 +5810,12 @@ snapshots: prettier@3.2.5: {} + pretty-format@27.5.1: + dependencies: + ansi-regex: 5.0.1 + ansi-styles: 5.2.0 + react-is: 17.0.2 + pretty-format@29.7.0: dependencies: '@jest/schemas': 29.6.3 @@ -5139,6 +5865,8 @@ snapshots: proxy-from-env@1.1.0: {} + psl@1.9.0: {} + pump@3.0.0: dependencies: end-of-stream: 1.4.4 @@ -5164,6 +5892,8 @@ snapshots: query-selector-shadow-dom@1.0.1: {} + querystringify@2.2.0: {} + queue-microtask@1.2.3: {} queue-tick@1.0.1: {} @@ -5177,8 +5907,22 @@ snapshots: minimist: 1.2.8 strip-json-comments: 2.0.1 + react-dom@18.3.1(react@18.3.1): + dependencies: + loose-envify: 1.4.0 + react: 18.3.1 + scheduler: 0.23.2 + + react-is@17.0.2: {} + react-is@18.2.0: {} + react-refresh@0.14.2: {} + + react@18.3.1: + dependencies: + loose-envify: 1.4.0 + read-yaml-file@1.1.0: dependencies: graceful-fs: 4.2.11 @@ -5208,6 +5952,11 @@ snapshots: dependencies: minimatch: 5.1.6 + redent@3.0.0: + dependencies: + indent-string: 4.0.0 + strip-indent: 3.0.0 + regenerator-runtime@0.14.1: {} registry-auth-token@4.2.2: @@ -5245,6 +5994,8 @@ snapshots: require-directory@2.1.1: {} + requires-port@1.0.0: {} + resolve-alpn@1.2.1: {} resolve@1.19.0: @@ -5305,6 +6056,10 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.14.0 fsevents: 2.3.3 + rrweb-cssom@0.6.0: {} + + rrweb-cssom@0.7.1: {} + run-parallel@1.2.0: dependencies: queue-microtask: 1.2.3 @@ -5319,8 +6074,15 @@ snapshots: safe-buffer@5.2.1: {} - safer-buffer@2.1.2: - optional: true + safer-buffer@2.1.2: {} + + saxes@6.0.0: + dependencies: + xmlchars: 2.2.0 + + scheduler@0.23.2: + dependencies: + loose-envify: 1.4.0 semver@6.3.1: {} @@ -5352,7 +6114,7 @@ snapshots: signal-exit@4.1.0: {} - signal-polyfill@0.1.0: {} + signal-polyfill@0.1.0(patch_hash=mvi5cgrb6l747k4iwgeb4hh37q): {} sirv@2.0.4: dependencies: @@ -5464,6 +6226,10 @@ snapshots: strip-final-newline@3.0.0: {} + strip-indent@3.0.0: + dependencies: + min-indent: 1.0.1 + strip-json-comments@2.0.1: {} strip-json-comments@3.1.1: {} @@ -5486,6 +6252,8 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} + symbol-tree@3.2.4: {} + tar-fs@3.0.4: dependencies: mkdirp-classic: 0.5.3 @@ -5541,8 +6309,19 @@ snapshots: totalist@3.0.1: {} + tough-cookie@4.1.4: + dependencies: + psl: 1.9.0 + punycode: 2.3.1 + universalify: 0.2.0 + url-parse: 1.5.10 + tr46@0.0.3: {} + tr46@5.0.0: + dependencies: + punycode: 2.3.1 + traverse@0.3.9: {} tree-kill@1.2.2: {} @@ -5582,6 +6361,8 @@ snapshots: universalify@0.1.2: {} + universalify@0.2.0: {} + universalify@2.0.1: {} unzipper@0.10.14: @@ -5611,6 +6392,11 @@ snapshots: dependencies: prepend-http: 2.0.0 + url-parse@1.5.10: + dependencies: + querystringify: 2.2.0 + requires-port: 1.0.0 + userhome@1.0.0: {} util-deprecate@1.0.2: {} @@ -5669,7 +6455,7 @@ snapshots: '@types/node': 20.12.2 fsevents: 2.3.3 - vitest@1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0): + vitest@1.4.0(@types/node@20.12.2)(@vitest/browser@1.4.0)(@vitest/ui@1.4.0)(jsdom@24.1.0): dependencies: '@vitest/expect': 1.4.0 '@vitest/runner': 1.4.0 @@ -5695,6 +6481,7 @@ snapshots: '@types/node': 20.12.2 '@vitest/browser': 1.4.0(vitest@1.4.0)(webdriverio@8.35.1(encoding@0.1.13)(typescript@5.4.3)) '@vitest/ui': 1.4.0(vitest@1.4.0) + jsdom: 24.1.0 transitivePeerDependencies: - less - lightningcss @@ -5716,6 +6503,10 @@ snapshots: semver: 7.6.0 typescript: 5.4.3 + w3c-xmlserializer@5.0.0: + dependencies: + xml-name-validator: 5.0.0 + wait-port@1.1.0: dependencies: chalk: 4.1.2 @@ -5779,6 +6570,19 @@ snapshots: webidl-conversions@3.0.1: {} + webidl-conversions@7.0.0: {} + + whatwg-encoding@3.1.1: + dependencies: + iconv-lite: 0.6.3 + + whatwg-mimetype@4.0.0: {} + + whatwg-url@14.0.0: + dependencies: + tr46: 5.0.0 + webidl-conversions: 7.0.0 + whatwg-url@5.0.0: dependencies: tr46: 0.0.3 @@ -5815,6 +6619,12 @@ snapshots: ws@8.16.0: {} + ws@8.17.1: {} + + xml-name-validator@5.0.0: {} + + xmlchars@2.2.0: {} + y18n@5.0.8: {} yallist@3.1.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index 76f9176..312d8f5 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,3 +1,4 @@ packages: - "." - "tests-public" + - "react" diff --git a/react/package.json b/react/package.json new file mode 100644 index 0000000..9f2e408 --- /dev/null +++ b/react/package.json @@ -0,0 +1,19 @@ +{ + "name": "react", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "David Sheldrick", + "license": "ISC", + "peerDependencies": { + "react": "*" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "jsdom": "^24.1.0" + } +} diff --git a/react/react.test.tsx b/react/react.test.tsx new file mode 100644 index 0000000..123065b --- /dev/null +++ b/react/react.test.tsx @@ -0,0 +1,170 @@ +import "@testing-library/jest-dom/vitest"; +import { act, cleanup, render, screen } from "@testing-library/react"; +import React, { useCallback } from "react"; +import { Signal } from "signal-polyfill"; +import { afterEach, describe, expect, it } from "vitest"; +import { track } from "./track"; +import { useSignalState } from "./useSignalState"; +import { useSignalValue } from "./useSignalValue"; + +// runs a clean after each test case (e.g. clearing jsdom) +afterEach(() => { + cleanup(); +}); + +describe("track", () => { + it("untracked components do not update", async () => { + const signal = new Signal.State(0); + const App = () =>
count: {signal.get()}
; + render(); + + expect(screen.getByText("count: 0")).toBeInTheDocument(); + + // it does not re-render when the signal is updated + signal.set(1); + await 0; + + expect(screen.getByText("count: 0")).toBeInTheDocument(); + }); + + it("tracked components do update", async () => { + const signal = new Signal.State(0); + const App = track(() => { + return
count: {signal.get()}
; + }); + render(); + + expect(screen.getByText("count: 0")).toBeInTheDocument(); + + // it does not re-render when the signal is updated + await act(() => { + signal.set(1); + }); + + expect(screen.getByText("count: 1")).toBeInTheDocument(); + }); + + it("allows tracked components to use hooks", async () => { + const signal = new Signal.State(0); + let setState; + const App = track(() => { + const [state, _setState] = React.useState("a"); + setState = _setState; + return ( +
+ count: {state} + {signal.get()} +
+ ); + }); + render(); + + expect(screen.getByText("count: a0")).toBeInTheDocument(); + + await act(() => { + signal.set(1); + }); + + expect(screen.getByText("count: a1")).toBeInTheDocument(); + + await act(() => { + setState("b"); + }); + + expect(screen.getByText("count: b1")).toBeInTheDocument(); + }); +}); + +describe("useSignalState", () => { + it("creates a reactive value", async () => { + const App = track(() => { + const signal = useSignalState(0); + const increment = useCallback(() => { + signal.set(signal.get() + 1); + }, [signal]); + return ; + }); + + render(); + expect(screen.getByText("count: 0")).toBeInTheDocument(); + + await act(async () => { + screen.getByRole("button").click(); + }); + + expect(screen.getByText("count: 1")).toBeInTheDocument(); + + await act(async () => { + screen.getByRole("button").click(); + }); + + expect(screen.getByText("count: 2")).toBeInTheDocument(); + }); +}); + +describe("useSignalValue", () => { + it("allows subscribing to signals individually outside of a tracked component", async () => { + const signal = new Signal.State(0); + let setState; + const App = () => { + const value = useSignalValue(signal); + const [state, _setState] = React.useState(value); + return
count: {value}
; + }; + render(); + expect(screen.getByText("count: 0")).toBeInTheDocument(); + + await act(() => { + signal.set(1); + }); + expect(screen.getByText("count: 1")).toBeInTheDocument(); + + await act(() => { + signal.set(2); + }); + + expect(screen.getByText("count: 2")).toBeInTheDocument(); + }); + + it("allows using normal hooks too", async () => { + const signal = new Signal.State(0); + let setState; + const App = () => { + const value = useSignalValue(signal); + const [state, _setState] = React.useState("a"); + setState = _setState; + return ( +
+ count: {state} + {value} +
+ ); + }; + render(); + expect(screen.getByText("count: a0")).toBeInTheDocument(); + + await act(() => { + signal.set(1); + }); + expect(screen.getByText("count: a1")).toBeInTheDocument(); + + await act(() => { + signal.set(2); + }); + + expect(screen.getByText("count: a2")).toBeInTheDocument(); + + await act(() => { + setState("b"); + }); + + expect(screen.getByText("count: b2")).toBeInTheDocument(); + + await act(() => { + setState("c"); + signal.set(3); + }); + + expect(screen.getByText("count: c3")).toBeInTheDocument(); + }); +}); diff --git a/react/track.ts b/react/track.ts new file mode 100644 index 0000000..704cb1c --- /dev/null +++ b/react/track.ts @@ -0,0 +1,125 @@ +import React from "react"; +import { Signal } from "signal-polyfill"; + +// subtle, render should be stable +function useSignalTracking(render: () => T): T { + // This hook creates an watcher that will trigger re-renders when any signals ready during the passed render function update + + // We need the render fn to always be up-to-date when calling computed.get() but it'd be wasteful to + // instantiate a new Computed on every render, so we use an immediately-updated ref + // to wrap it + const renderRef = React.useRef(render); + renderRef.current = render; + + const [computedRender] = React.useState( + () => + new Signal.Computed(() => { + return renderRef.current(); + }) + ); + + const [watcher, subscribe, getSnapshot] = React.useMemo(() => { + let scheduleUpdate = null as null | (() => void); + // useSyncExternalStore requires a subscribe function that returns an unsubscribe function + const subscribe = (cb: () => void) => { + scheduleUpdate = cb; + return () => { + scheduleUpdate = null; + }; + }; + + let numSchedules = 0; + const watcher = new Signal.subtle.Watcher(async () => { + await 0; + if (computedRender.isPending()) { + numSchedules++; + scheduleUpdate?.(); + watcher.watch() + } + }); + + // we use an incrementing number based on when this + const getSnapshot = () => numSchedules; + + return [watcher, subscribe, getSnapshot]; + }, [name]); + + React.useSyncExternalStore(subscribe, getSnapshot, getSnapshot); + + // reactive dependencies are captured when `computed.get()` is called + // and then to make it reactive we wait for a `useEffect` to 'attach' + // this allows us to avoid rendering outside of React's render phase + // and avoid 'zombie' components that try to render with bad/deleted data before + // react has a chance to umount them. + React.useEffect(() => { + watcher.watch(computedRender); + return () => { + watcher.unwatch(computedRender); + }; + }, [watcher]); + + return computedRender.get(true); +} + +export const ProxyHandlers = { + /** + * This is a function call trap for functional components. When this is called, we know it means + * React did run 'Component()', that means we can use any hooks here to setup our effect and + * store. + * + * With the native Proxy, all other calls such as access/setting to/of properties will be + * forwarded to the target Component, so we don't need to copy the Component's own or inherited + * properties. + * + * @see https://github.com/facebook/react/blob/2d80a0cd690bb5650b6c8a6c079a87b5dc42bd15/packages/react-reconciler/src/ReactFiberHooks.old.js#L460 + */ + apply(Component: React.FunctionComponent, thisArg: any, argumentsList: any) { + // eslint-disable-next-line react-hooks/rules-of-hooks + return useSignalTracking(() => Component.apply(thisArg, argumentsList)); + }, +}; + +export const ReactMemoSymbol = Symbol.for("react.memo"); +export const ReactForwardRefSymbol = Symbol.for("react.forward_ref"); + +/** + * Returns a tracked version of the given component. + * Any signals whose values are read while the component renders will be tracked. + * If any of the tracked signals change later it will cause the component to re-render. + * + * This also wraps the component in a React.memo() call, so it will only re-render if the props change. + * + * @example + * ```ts + * const Counter = track(function Counter(props: CounterProps) { + * const count = useSignalState(0) + * const increment = useCallback(() => count.set(count.get() + 1), [count]) + * return + * }) + * ``` + * + * @param baseComponent - The base component to track. + * @public + */ +export function track>( + baseComponent: T +): T extends React.MemoExoticComponent ? T : React.MemoExoticComponent { + let compare = undefined; + const $$typeof = baseComponent["$$typeof" as keyof typeof baseComponent]; + if ($$typeof === ReactMemoSymbol) { + baseComponent = (baseComponent as any).type; + compare = (baseComponent as any).compare; + } + if ($$typeof === ReactForwardRefSymbol) { + return React.memo( + React.forwardRef( + new Proxy((baseComponent as any).render, ProxyHandlers) as any + ) + ) as any; + } + + return React.memo( + new Proxy(baseComponent, ProxyHandlers) as any, + compare + ) as any; +} diff --git a/react/useSignalState.ts b/react/useSignalState.ts new file mode 100644 index 0000000..9b884f2 --- /dev/null +++ b/react/useSignalState.ts @@ -0,0 +1,18 @@ +import { useState } from "react"; +import { Signal } from "signal-polyfill"; + +export function useSignalState( + initialValue: T | (() => T), + opts?: Signal.Options +) { + const [signal] = useState( + () => + new Signal.State( + typeof initialValue === "function" + ? (initialValue as () => T)() + : initialValue, + opts + ) + ); + return signal; +} diff --git a/react/useSignalValue.ts b/react/useSignalValue.ts new file mode 100644 index 0000000..a3585f8 --- /dev/null +++ b/react/useSignalValue.ts @@ -0,0 +1,59 @@ +/* eslint-disable prefer-rest-params */ +import { useMemo, useRef, useSyncExternalStore } from "react"; +import { Signal } from "signal-polyfill"; + +type Gettable = { get(): T }; + +/** + * Extracts the value from a signal and subscribes to it. + * + * Note that you do not need to use this hook if you are wrapping the component with [[track]] + * + * @public + */ +export function useSignalValue(value: Gettable): Value; +/** @public */ +export function useSignalValue(fn: () => Value, deps: unknown[]): Value; +/** @public */ +export function useSignalValue() { + const args = arguments; + const deps = args.length === 2 ? args[1] : [args[0]]; + + const $val = useMemo(() => { + return new Signal.Computed(() => { + if (args.length === 1) { + return args[0].get(); + } + return args[0](); + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, deps); + + const { subscribe, watcher, getSnapshot } = useMemo(() => { + let listen = () => {}; + let numSchedules = 0; + const watcher = new Signal.subtle.Watcher(async () => { + await 0; + if ($val.isPending()) { + numSchedules++; + listen(); + watcher.watch(); + } + }); + return { + subscribe: (_listen: () => void) => { + listen = _listen; + watcher.watch($val); + return () => watcher.unwatch($val); + }, + watcher, + getSnapshot: () => { + return numSchedules; + }, + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [$val]); + + useSyncExternalStore(subscribe, getSnapshot, getSnapshot); + return $val.get(); +} diff --git a/tsconfig.json b/tsconfig.json index 0357aa4..9e058bc 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -9,6 +9,7 @@ "moduleResolution": "bundler", "declaration": true, "emitDeclarationOnly": true, + "jsx": "react-jsx", /** Stylistic / linting. Does not provide extra type safety. diff --git a/vite.config.ts b/vite.config.ts index 5e39784..7c0d71b 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -4,6 +4,7 @@ import { defineConfig } from "vite"; import dts from "vite-plugin-dts"; import { globbySync } from "globby"; import { babel } from "@rollup/plugin-babel"; +import react from '@vitejs/plugin-react' const require = createRequire(import.meta.url); const manifest = require("./package.json"); @@ -20,6 +21,10 @@ for (let entry of entryFiles) { export default defineConfig({ // esbuild in vite does not support decorators // https://github.com/evanw/esbuild/issues/104 + test: { + // 👋 add the line below to add jsdom to vite + environment: 'jsdom', + }, esbuild: false, build: { outDir: "dist", @@ -77,5 +82,6 @@ export default defineConfig({ // ignore tests include: ["src"], }), + react() ], });