{"_id":"grainlet","_rev":"29-bfef80540058f32cc678c12191627749","name":"grainlet","dist-tags":{"latest":"1.1.1"},"versions":{"1.0.0":{"name":"grainlet","version":"1.0.0","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained"],"license":"MIT","_id":"grainlet@1.0.0","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"4e38a4f9c21bde494e2bd9dc9bb833b9db4fe972","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.0.tgz","fileCount":50,"integrity":"sha512-aGu8iKfBHs5U0F6GgW4rW1CrI9qEcH0YtQ156Y48NZHZjBujCDjD9WqLeawdSJkQxJXMTYJhYkymf7XupoDNOA==","signatures":[{"sig":"MEQCIAbDfxtHJjikh0kebm3e4q0Trx6XbKix0IEd0O5XtFR6AiBlB6d+BjtRYqOAr0ISF2+0mmqk1fcD47Pn7gdXegvd6Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":96709},"main":"./index.js","type":"module","exports":{".":"./index.js","./vite":"./core/jsx-compiler-new/grain-jsx.vite.js","./jsx-runtime":"./core/jsx-compiler-new/jsx-runtime.js","./package.json":"./package.json","./jsx-runtime.js":"./core/jsx-compiler-new/jsx-runtime.js","./jsx-dev-runtime":"./core/jsx-compiler-new/jsx-dev-runtime.js","./jsx-dev-runtime.js":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"gitHead":"6e7fa110f3d29a9edb50cf95c3c280bc81418da0","_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"peerDependencies":{"@babel/core":"^7.23.0","@babel/plugin-syntax-jsx":"^7.23.0"},"peerDependenciesMeta":{"@babel/core":{"optional":true},"@babel/plugin-syntax-jsx":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.0_1784221920934_0.7381220238820068","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"grainlet","version":"1.0.1","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained"],"license":"MIT","_id":"grainlet@1.0.1","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"3b541f7353db8efdcce15c0dfcc2cde3a721ef74","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.1.tgz","fileCount":48,"integrity":"sha512-JcIITWaKVFiD4wc3LT4RmaiRkL9ND1PqUVMsxda6c8TA0ii4xXoDsvPaQS/5fwETAki0+vlTOloUd/amc0uhQw==","signatures":[{"sig":"MEQCICo07GM5kUYGkBKdED4H7bJ/isDh60JSrT1X8z/e3tbIAiAaJWI72tV04nnz3xvIEA8qnz8otI7I+vJsSCzsSTC8NQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":92488},"main":"./index.js","type":"module","exports":{".":"./index.js","./jsx-runtime":"./core/jsx-compiler-new/jsx-runtime.js","./package.json":"./package.json","./jsx-runtime.js":"./core/jsx-compiler-new/jsx-runtime.js","./jsx-dev-runtime":"./core/jsx-compiler-new/jsx-dev-runtime.js","./jsx-dev-runtime.js":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"gitHead":"6e7fa110f3d29a9edb50cf95c3c280bc81418da0","_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.1_1784222480173_0.8083669051408502","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"grainlet","version":"1.0.5","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained"],"license":"MIT","_id":"grainlet@1.0.5","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"b03d8c5ddecaf04a8fd85cc0138429fd3177900f","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.5.tgz","fileCount":51,"integrity":"sha512-hX/f3SY/RXxA80qZ8zVfARwalxO8iQlP1ZhnSSwAv0osuLLu1ffLhGX2wh6slJLBxjSPqShqmV4gBtODq0wA1g==","signatures":[{"sig":"MEQCIGoinjaepVumt7DHDhs7d1acyE1/ptIiLA202umpgqnRAiBIe1+NejziJmVPV/ozFMkzdrjXOafL8OnWJ6Qi1fnFSQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":103972},"main":"./index.js","type":"module","exports":{".":"./index.js","./jsx-runtime":"./core/jsx-compiler-new/jsx-runtime.js","./package.json":"./package.json","./jsx-runtime.js":"./core/jsx-compiler-new/jsx-runtime.js","./jsx-dev-runtime":"./core/jsx-compiler-new/jsx-dev-runtime.js","./jsx-dev-runtime.js":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"gitHead":"d0fd5b853456de4e9e2023b18318825f4c2f66e6","_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.5_1784226082447_0.09972016142987306","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"grainlet","version":"1.0.6","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.6","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"cc8c549380915f7d432614c007d52df12352e4df","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.6.tgz","fileCount":59,"integrity":"sha512-e8p+32lTux8eOOYyfu23LAu02ZdG/unyCMvjOqm8cndQETKCq0gu7T1oZ1K3Zg7XE+PBFW2WJjL1NLtP3hznYQ==","signatures":[{"sig":"MEQCIFBfJqahG7jPSsy9VLbH/Kj15kDu/lcvhHiu77/3IVqHAiAxC5VmBaOE7JDM9Y2XuEp6LLHVkg4I06018YIZryC61Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117997},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"1d8a4bdcd3ffc3418add8d01a5ab531434cc2fa5","_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.6_1784226984449_0.913560144230191","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"grainlet","version":"1.0.7","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.7","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"aedf67f3dcac9fbff8d7c3ec10c28f808014955f","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.7.tgz","fileCount":57,"integrity":"sha512-SACgUpt0L7pbX9K6Y5e0buaBt1r9CtVkJlEBZqHzFJIGn2NDT3oPkkc8dfqVv0C0SmI0dS9IWZkj7gUUvHEf3w==","signatures":[{"sig":"MEYCIQCmUf4UR1g1OjEGwFbPCuSQ0ogN0qEVBWBR7G5vvufGQwIhAOaXVQRDw79irOzP4E7A9ubg/xlfIJjqQmgeraWeZzLg","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":109548},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"ab3e3f5ba98d2543839cb48636c906d13dbb7dfc","_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.7_1784227866171_0.7198694767920897","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"grainlet","version":"1.0.8","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.8","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"77e8212c5c627453765574e5db6a75d4ba15d71e","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.8.tgz","fileCount":57,"integrity":"sha512-RmKGoxYThqv3O8VQzKO3rN3Pa/sxesFNe0HV61E4Sh567D0+7pChoDYQ8sXJac3wSum6MijayPXUPvxU1vBP/g==","signatures":[{"sig":"MEQCIDP3FjXoO7OkVWcvyNrq0hK0ZPUMHKdVbjYwXktrc/QeAiBXoqnnQTtI1bXYh1bOXiroPYEfOlT1pJ3wWQvo5h2tcA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":111013},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"18846a13da3b5935303b9c95aafed6b5ea3477c2","scripts":{"test":"node test/keyed-unmount.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.8_1784229076333_0.9578033065024687","host":"s3://npm-registry-packages-npm-production"}},"1.0.9":{"name":"grainlet","version":"1.0.9","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.9","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"4223b1114d3fd9f117e02fdda887f2fdf8f2a18d","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.9.tgz","fileCount":58,"integrity":"sha512-ZbfCjl45acvDuJdN2ZLHQwuN88yIF5oyOq25vKEjx/YYaAoKBGtxst1sE7JEzgjvb89lhTyd1RSUPRPDNR2qtg==","signatures":[{"sig":"MEUCIQCT7rALBkcHGVO6UJfSXg/febpjHqj117YA3bf+c4GTpgIgRyrHpttzpd+5pxlxiEb3LU9BI9PlVkL8M+t9YSE4fyI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":125445},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"529e444585178d57a4644457bc58eb6db3272db8","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.9_1784233637923_0.17036968681484743","host":"s3://npm-registry-packages-npm-production"}},"1.0.10":{"name":"grainlet","version":"1.0.10","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.10","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"8f000451db4cce313a9992e6353b041ef8837bba","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.10.tgz","fileCount":58,"integrity":"sha512-A80hKi+mcBxf5Qh32Dc/+WVX2sHAXhpUe1GwkcpsrmtTwWEhEDzG1Wl7A7DqopUz72u1P+lkHdwZ8FTEXJrcWQ==","signatures":[{"sig":"MEUCIDIGWfB0LevGw1VAj/KOxFJBoKAd6kESfDpL+fPbASw7AiEAzAzD0UVjHgiVjh5r6X28eWoGPu425uKo8BRnQUJJxxU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":128661},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"ab4f959793187773153476056cb65fa017cd8061","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.10_1784234049334_0.6274998403803802","host":"s3://npm-registry-packages-npm-production"}},"1.0.11":{"name":"grainlet","version":"1.0.11","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.11","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"81d8603c64ed7e76cf25daa537dfbe83dd9f0581","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.11.tgz","fileCount":63,"integrity":"sha512-HNy/UtkHjstj2GcaOhTgM6RyNk7P5Fsqx3gZ/PC2i6LUyEJPCgrorbcN55fqamIXqOkOBfL9ZjzPe+/SAnxg0g==","signatures":[{"sig":"MEUCIQCJAf7Q0fZe+2L96fhQJ11eQsu1J+i2OYTA4YR4D1c2/AIgeWyGWuqVJVbQSifRA5/1u0CweS5JkqGIybYXZzIfYlo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136568},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"58a17d32597ca84b881f774e1c2289be7b38ce36","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.11_1784305419848_0.24958341145713336","host":"s3://npm-registry-packages-npm-production"}},"1.0.12":{"name":"grainlet","version":"1.0.12","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.12","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"f3a70d0a30654bfc010ae914aa19bd9fe3b4c1db","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.12.tgz","fileCount":63,"integrity":"sha512-aGebk3VqQrz8XRREm+MDV5hs478mDbPc6dhhvE8+ty/HRbDZIdVFMr0xN8hejNzTTgalllMzkEUv96825lw31g==","signatures":[{"sig":"MEYCIQCka98uSPkIvJQGSY2Riw0qmj9m1JXMTmeiQORjkcd7wQIhANaqrerWImJlTBw0SkAYD28/1HQbLPLwtt14R79txfak","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136278},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"d69bbc7cdb3bac6c3a6a80f8432207c739383e98","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.12_1784306132321_0.9145091485238157","host":"s3://npm-registry-packages-npm-production"}},"1.0.13":{"name":"grainlet","version":"1.0.13","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.13","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"5ceafc951961f968414e57c269be3415e51e180f","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.13.tgz","fileCount":64,"integrity":"sha512-zQ1htQBUvB31qxpdtkS/m2PgieaQfN4xrSmc7jN20FmTmXfB9SpabzVDq1MnUhPcIIVGt7u4HM0LEKVhAhbwvQ==","signatures":[{"sig":"MEUCIQDpOiv221e42O2QimHZiwECASSZUxDirW0ZKrJ/wHkNjAIgNBLBQz7jLxwMEQTIpxwIv3Iytmduj0yQ7OOlvBjDUFQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136115},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.13_1784307554169_0.4837365753735392","host":"s3://npm-registry-packages-npm-production"}},"1.0.14":{"name":"grainlet","version":"1.0.14","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.14","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"11681e4590225b478053ac511058eb8d07b791d5","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.14.tgz","fileCount":64,"integrity":"sha512-1eK1HhycOXw8qRiWizcY5n2F+Xa1ny0GR2+mQZDlCbGVeREXYkfbbCe8juhrF/py8Lz3YyKVfdBAcmOd7QIf0g==","signatures":[{"sig":"MEQCIDEoQ3azbjQKiMM8lzwc0KEmO44R97I3J+TP+wd1JR2mAiA0usisSYSfg9xpPB2tZUpy4ILYh/CpEpIILlhh8mZWLg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":136634},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.14_1784323533471_0.19482545530598228","host":"s3://npm-registry-packages-npm-production"}},"1.0.15":{"name":"grainlet","version":"1.0.15","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.15","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"7234c3d3c47be81a47c4ac9b834620623dcde4c3","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.15.tgz","fileCount":65,"integrity":"sha512-pBmwh1d0b7a+c5I9y4pcIO3KYd2h8YzZvt+20kfivSwmr3/pg1GZyC+oX8N6gsKp0s6/Oki8Er+rR3tLQw42wA==","signatures":[{"sig":"MEYCIQCKsiL+3+vTahZ1vLFPDwzNvHHxIv5K+sG7Jp5JKvg9NgIhAM2IxVHa+T3dKb4N8ZtcA1rZcKSfvnuMlR72730tb1bu","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":141762},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.15_1784324260276_0.477969424972466","host":"s3://npm-registry-packages-npm-production"}},"1.0.16":{"name":"grainlet","version":"1.0.16","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.16","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"d6d39eccf2f17eb880f2f6bad5778bb57a5bd6bf","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.16.tgz","fileCount":64,"integrity":"sha512-WVtNs4jfnMncRmLOpWWgKANAdQtgBupNe7ogJmFsHiFT/utbTMHq2itJYZ2rR3FhwwoUfDY3ibZSxHttgLdm3g==","signatures":[{"sig":"MEQCIHTED5vdd9zlpCf8b/woTyETgO+acEAvk31lc1M7QgaqAiBIyTrUtRlSrTEsfmUqLBa5dnEYlqOF+FFlMa3Wf8Nz0g==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":138794},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.16_1784324469656_0.4033208269594091","host":"s3://npm-registry-packages-npm-production"}},"1.0.17":{"name":"grainlet","version":"1.0.17","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.17","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"8a35d944c332edf846ae4875ba0615474da62326","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.17.tgz","fileCount":64,"integrity":"sha512-FSTbzyTrOexU1ljwLxZoUZ5mQtTvzlbZ34ElLVp9KekdOz71+7uOcNluVw0WsKSRYQjb6RcAqRYJV9sPlD/PpA==","signatures":[{"sig":"MEYCIQCocG3SNSfMVtvygh99Epf2/a/EBpt4BqcP6qgOVMRJgAIhAOuSh02tgtqageGfYK1y71ghvYs/xbGhai4aw3B/3uvd","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":141626},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.17_1784325026111_0.08910614800736916","host":"s3://npm-registry-packages-npm-production"}},"1.0.18":{"name":"grainlet","version":"1.0.18","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.18","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"867c0ab29671194c96bdccdca785c6fdeaf719a4","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.18.tgz","fileCount":64,"integrity":"sha512-BDhG/FkXCz8k7oCD3MBiR7CL0HeduEgAVyXuFot5YmETrG54eIYPk6VcrnptsFOIGOlFw2oGhhVFFsNl1jtBaw==","signatures":[{"sig":"MEQCIB9hRA8rvJQyue9kR+B66LJdHhX3gDM8ZIA/SF33UtUBAiBukrvbnWjVnomH6WSgzN2mtkF0x0KGoMYzwAw69Iw9cQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":143014},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.18_1784325511525_0.5950030506863215","host":"s3://npm-registry-packages-npm-production"}},"1.0.19":{"name":"grainlet","version":"1.0.19","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.19","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"151ace63184d3abff4d919a11a66fadc74baa78f","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.19.tgz","fileCount":64,"integrity":"sha512-CsvRyJ4Hy7cRz9vrZRk38KBhxAtZpPaqlqjfdYGRo0JMatXzPpsoSr+NwrFF7iwTN4EPzmZgOZEhyrWpQHuJfQ==","signatures":[{"sig":"MEUCIQC8hlFngICndiPNQe+ElxEJei3Qg04J28dfs8dp/CkCtwIgaH2EGQYQCjytMFEADHO1BOmNCmuOjHJpA3DZd9q6pcA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":145776},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"94f89ab4dd23e739e833cf3a3c8d7cee0cda3dc4","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.19_1784326100351_0.2560358045220108","host":"s3://npm-registry-packages-npm-production"}},"1.0.20":{"name":"grainlet","version":"1.0.20","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.20","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"042dd7222980a69a72c0c42f43a3f0798e7da39a","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.20.tgz","fileCount":65,"integrity":"sha512-Cvv8PVp1wvOZOsBcS4Z8FFJd9UzXaXf8fOF822xcY3SsvKz0FB/nZ/QXWuixGbdQjx03+KUKG0l/XvmKtnJf3g==","signatures":[{"sig":"MEUCIAq5NDF8nMxcAly/YAg5dd66I6ECnVm3uXOPcTCBKHmGAiEA699n9z+Hm/LCd2rKMx+xsI+3hzWfrGjSyeQarJKlXiw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":150930},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"92530f5bb55aea761e90764d5901522d8c507f5a","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.20_1784374324158_0.5498817221226433","host":"s3://npm-registry-packages-npm-production"}},"1.0.21":{"name":"grainlet","version":"1.0.21","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.21","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"85695c405cf771e3c92d80d35d43c09ecbccf16b","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.21.tgz","fileCount":66,"integrity":"sha512-qKzP8ldqyBIQ+iWUE86y+WCj/R7dcV8bWVUcupLdGEf2RcnEf7eVQ9noMbhwyJI2qtyEMKyScJpqHXwCDsYkpQ==","signatures":[{"sig":"MEQCIBy7p3tWtNnwx0yYD5VBUj57YdlMDy7oHENWX1NPbsPgAiB7wJxddLBw6cVQ5cXDgCoVi3DDFcvcbaUAR6AoQz6KvA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":151284},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"92530f5bb55aea761e90764d5901522d8c507f5a","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.21_1784377231396_0.046568559441623414","host":"s3://npm-registry-packages-npm-production"}},"1.0.22":{"name":"grainlet","version":"1.0.22","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.22","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"99f4143e8fba3b7c0c1cad1068ded3a104cac29a","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.22.tgz","fileCount":66,"integrity":"sha512-F2z3ipLwQRaSQRWtCJdAkm9hUwhxLyr7c1zxtBc6FIJRfYDbGdylk8j/1JFnU4t9q6Kokm0hAC1p14SA9MNhYw==","signatures":[{"sig":"MEUCIDi/hVt88XuEzddaLZQlcmnVx/vyKIDn6vIjt+c2SsIgAiEA0hi52IOcET64csBiaqJ8eT4AD5p4c3AgBZ0W8wE4MeQ=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":152576},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"b15657484f82126689f867bb261d12651e0af90b","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"jsdom":"^26.1.0"},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.22_1784380113405_0.9629358436332005","host":"s3://npm-registry-packages-npm-production"}},"1.0.23":{"name":"grainlet","version":"1.0.23","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.23","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"2d0766ecd703f0530839931a79f50d6a3d90175b","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.23.tgz","fileCount":81,"integrity":"sha512-DY9xi2j+alzKZZUZ76CKD0wSNDT3w5c8RjcTgaarRT9UN8/9jstnfjzTFUvTz/Scmrg8M8kTwrZV/sRkCSp1Cw==","signatures":[{"sig":"MEQCIDEdnynRtEOrze7SHrVcsrpTV+i7ZhuQQB8CScpNxSp6AiBkLGoIqB/LwUOhFW8O6UzqcW7Xa3VoazLEwdG7JqrxAA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":227821},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"6ed150f8157650c55cfc5784778f0eaa5340ffd2","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.23_1784574731666_0.9570045567373029","host":"s3://npm-registry-packages-npm-production"}},"1.0.24":{"name":"grainlet","version":"1.0.24","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.24","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"dc1745ba84d33ae66e018ae8863d769c41c7a5e9","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.24.tgz","fileCount":81,"integrity":"sha512-jMuJgR8OXPZbbhfGQ8HrHsN2M327PstHMJ3ykl8arjixn0gNokAgnf/ufUbyqSkDDqdq3OS9tjSOWLXW1+deqQ==","signatures":[{"sig":"MEUCIEuIq78DpqXl/17rB0EENogfdq1PpeUQcwCGo6NwJaV7AiEA2uzxDag5+DNA05L1ENbchJPjqSZWNfcOT/Q/QVOcgcc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":228498},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"6ed150f8157650c55cfc5784778f0eaa5340ffd2","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/default-key-of.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/forms-field-array-remove.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.24_1784575662474_0.09524896053468734","host":"s3://npm-registry-packages-npm-production"}},"1.0.25":{"name":"grainlet","version":"1.0.25","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.25","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"aea9e47ce3170a62878f0c1d31faaf5a8edb3fc2","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.25.tgz","fileCount":81,"integrity":"sha512-kG4KnHXlE3+uRJrhV9seQ9yoUhNAUI1tUMKauLCqn9dY8WxpTPlriB1T9Mdp0W4IhzaRc3OTdzDzvTMZr6rHSw==","signatures":[{"sig":"MEYCIQCuV8mAbiN1WkY6tg71EjLGiVZHiPQqwe0ocN+EMM+vpAIhAM5PI/rG7PRnceBklqZgD4L7dVKiGeFlQ/RJrdVe3BD7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":228434},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"6ed150f8157650c55cfc5784778f0eaa5340ffd2","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/default-key-of.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/forms-field-array-remove.test.mjs && node test/forms-field-array-typing.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.25_1784575938707_0.14304638588429786","host":"s3://npm-registry-packages-npm-production"}},"1.0.26":{"name":"grainlet","version":"1.0.26","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.26","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"cba04eceeb6bf82b6bfaf57b6785a642257d4b6d","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.26.tgz","fileCount":81,"integrity":"sha512-9WUII69tap8yohM5OBk0PHAHAoEDAfABVMiJ4TErEowYyrsOLxfvq5rluvvKX18SokPEq3aQS8CW5Maa80KCrw==","signatures":[{"sig":"MEQCIH/Ps362RVyeBbXRXhQSuQ4eZbSPu/uA1cq4eY0DZyRTAiBr7FCSkIsMd7EweLx/OSot+ft4YfZKFBOZze4Stm5PAA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":228270},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"6ed150f8157650c55cfc5784778f0eaa5340ffd2","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/default-key-of.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/forms-field-array-remove.test.mjs && node test/forms-field-array-typing.test.mjs && node test/forms-example-22-mount.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.9.0","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"22.12.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.26_1784576407313_0.051568250105030744","host":"s3://npm-registry-packages-npm-production"}},"1.0.27":{"name":"grainlet","version":"1.0.27","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.27","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"01a868af2df5c52b2385ea2a46fc4ac497202719","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.27.tgz","fileCount":101,"integrity":"sha512-iT25Kr+5i3K9k+Aepo1uNkiOvp+/ME6h6p5bcBpWIDB2C+GNF5sQaRqgrtH43gmX0jixIul62EfS4CI3/HVOXA==","signatures":[{"sig":"MEQCIGLJIv9ePltuacsovNWECqQyjnz4aSKCYfp4XCDY3B63AiAw06WAfchvGpmvEBkdaa0KifdSoOAV1M14HWrmnlfvPw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":261283},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./auth":{"types":"./auth.d.ts","default":"./auth/index.js"},"./i18n":{"types":"./i18n.d.ts","default":"./i18n/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"e35fbe0701f27e60b94839f1f9416bf7ab83a1d0","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/auth-core.test.mjs && node test/auth-provider.test.mjs && node test/i18n-core.test.mjs && node test/i18n-provider.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.2.4","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.27_1786039835565_0.2869815185742457","host":"s3://npm-registry-packages-npm-production"}},"1.0.28":{"name":"grainlet","version":"1.0.28","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.28","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"8f1ace37c515f75311c5d24ced17a520c937ae67","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.28.tgz","fileCount":112,"integrity":"sha512-Y9Cj5KthLQm0plY2DIU0ENQUToAqRRkXI4CaZmYSkVtbXQkKtIBBzAwM4N8HVh6CFporipj/8fAds3nT0aQGQw==","signatures":[{"sig":"MEQCIAtkFFRnwuP+nbD+TeaSV3SZu9yA+Set8PYFZpdPCT1WAiAgtWLb1ouNuUUj0bblN/M9xTK4kovJbh0R0bTDVCrgNw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":295148},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./auth":{"types":"./auth.d.ts","default":"./auth/index.js"},"./i18n":{"types":"./i18n.d.ts","default":"./i18n/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./auth-sdk":{"types":"./auth-sdk.d.ts","default":"./auth-sdk/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"0fd2ede881c593ee29222478c5eb1c18a75bc0c9","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/auth-core.test.mjs && node test/auth-provider.test.mjs && node test/auth-sdk-core.test.mjs && node test/auth-sdk-providers.test.mjs && node test/i18n-core.test.mjs && node test/i18n-provider.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.2.4","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.28_1786049242697_0.6975305059041261","host":"s3://npm-registry-packages-npm-production"}},"1.0.29":{"name":"grainlet","version":"1.0.29","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.0.29","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"9f05fadac0a01e470e855908d2fb8339a483e41b","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.0.29.tgz","fileCount":112,"integrity":"sha512-WtpptbJaU6c1b5T++eTauvKr6EPa2m0LDxEXECPirQ+qkvdnuPQeeLvxb5Oc0qIJpETpO3SU9CtFG3+YQwyubg==","signatures":[{"sig":"MEUCICeTM7bjyImH/ZsN0ELZUoI4rCmod+paoE3Xj5UMabmKAiEAtGtLYltn/zLTe8KvDcruz8WLM7O7x42nPbvle+uC3H8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":303722},"main":"./index.js","type":"module","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"types":"./ssr.d.ts","default":"./ssr/index.js"},"./auth":{"types":"./auth.d.ts","default":"./auth/index.js"},"./i18n":{"types":"./i18n.d.ts","default":"./i18n/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./route":{"types":"./route.d.ts","default":"./route/index.js"},"./auth-sdk":{"types":"./auth-sdk.d.ts","default":"./auth-sdk/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"e041cf9354dac0fe1c9db21a59a8523dc3bac7a5","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/auth-core.test.mjs && node test/auth-provider.test.mjs && node test/auth-sdk-core.test.mjs && node test/auth-sdk-providers.test.mjs && node test/i18n-core.test.mjs && node test/i18n-provider.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.2.4","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.0.29_1786477119283_0.26541702885184426","host":"s3://npm-registry-packages-npm-production"}},"1.1.0":{"name":"grainlet","version":"1.1.0","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"license":"MIT","_id":"grainlet@1.1.0","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"dist":{"shasum":"e2aff0fc53b92f5298bc0d00cf986cc5dc141bfe","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.1.0.tgz","fileCount":163,"integrity":"sha512-VHqFErp9ghIfqnQdnPCMO/i6tQFCp/9dWBCJMw8GRRhNaxQ2DAUJ6HCJ3KJBqitaaqlg5fRXpgzNhPHOK4nHCA==","signatures":[{"sig":"MEQCIEz9EqOtwjAkIBHMVpP2gZDDsz5rRLz4ih5JE1/R+2keAiBjXagTmXcjizPryIMSdyhA9m2oHZKOmI/5R74wcDPv+w==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":505913},"main":"./index.js","type":"module","types":"./index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./ssr":{"node":"./ssr/node-index.js","types":"./ssr.d.ts","default":"./ssr/index.js"},"./auth":{"types":"./auth.d.ts","default":"./auth/index.js"},"./i18n":{"types":"./i18n.d.ts","default":"./i18n/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./query":{"types":"./query.d.ts","default":"./query/index.js"},"./route":{"node":"./route/node-index.js","types":"./route.d.ts","default":"./route/index.js"},"./store":{"types":"./store.d.ts","default":"./store/index.js"},"./utils":{"types":"./utils.d.ts","default":"./utils/index.js"},"./testing":{"types":"./testing.d.ts","default":"./testing/index.js"},"./auth-sdk":{"types":"./auth-sdk.d.ts","default":"./auth-sdk/index.js"},"./devtools":{"types":"./devtools.d.ts","default":"./devtools/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./package.json":"./package.json","./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"}},"gitHead":"7f18670ce1b1c844095da61c00eb60e872fea2eb","scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/streaming-ssr.test.mjs && node test/ssr-adapters-ssg.test.mjs && node test/hydration-diagnostics.test.mjs && node test/reactivity-runtime.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/auth-core.test.mjs && node test/auth-provider.test.mjs && node test/auth-sdk-core.test.mjs && node test/auth-sdk-providers.test.mjs && node test/i18n-core.test.mjs && node test/i18n-provider.test.mjs && node test/utils.test.mjs && node test/query-core.test.mjs && node test/query-hooks.test.mjs && node test/query-infinite-ssr.test.mjs && node test/router-ssr-integration.test.mjs"},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"_npmVersion":"10.2.4","description":"Fine-grained signals, JSX, routing, and SSR for the web","directories":{},"sideEffects":false,"_nodeVersion":"20.11.0","_hasShrinkwrap":false,"devDependencies":{"yup":"^1.7.1","jsdom":"^26.1.0"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/grainlet_1.1.0_1787329402367_0.801721374680243","host":"s3://npm-registry-packages-npm-production"}},"1.1.1":{"name":"grainlet","version":"1.1.1","description":"Fine-grained signals, JSX, routing, and SSR for the web","type":"module","license":"MIT","main":"./index.js","types":"./index.d.ts","exports":{".":{"types":"./index.d.ts","default":"./index.js"},"./route":{"types":"./route.d.ts","node":"./route/node-index.js","default":"./route/index.js"},"./forms":{"types":"./forms.d.ts","default":"./forms/index.js"},"./auth":{"types":"./auth.d.ts","default":"./auth/index.js"},"./auth-sdk":{"types":"./auth-sdk.d.ts","default":"./auth-sdk/index.js"},"./i18n":{"types":"./i18n.d.ts","default":"./i18n/index.js"},"./query":{"types":"./query.d.ts","default":"./query/index.js"},"./utils":{"types":"./utils.d.ts","default":"./utils/index.js"},"./store":{"types":"./store.d.ts","default":"./store/index.js"},"./testing":{"types":"./testing.d.ts","default":"./testing/index.js"},"./devtools":{"types":"./devtools.d.ts","default":"./devtools/index.js"},"./ssr":{"types":"./ssr.d.ts","node":"./ssr/node-index.js","default":"./ssr/index.js"},"./jsx-runtime":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-runtime.js":{"types":"./jsx-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-runtime.js"},"./jsx-dev-runtime":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./jsx-dev-runtime.js":{"types":"./jsx-dev-runtime.d.ts","default":"./core/jsx-compiler-new/jsx-dev-runtime.js"},"./package.json":"./package.json"},"sideEffects":false,"engines":{"node":">=20"},"scripts":{"test":"node test/keyed-unmount.test.mjs && node test/virtual-list.test.mjs && node test/render-async.test.mjs && node test/streaming-ssr.test.mjs && node test/ssr-adapters-ssg.test.mjs && node test/hydration-diagnostics.test.mjs && node test/reactivity-runtime.test.mjs && node test/for-bench-repro.test.mjs && node test/template-for-smoke.test.mjs && node test/forms-paths.test.mjs && node test/forms-createForm.test.mjs && node test/forms-provider-smoke.test.mjs && node test/forms-yup.test.mjs && node test/forms-validators.test.mjs && node test/auth-core.test.mjs && node test/auth-provider.test.mjs && node test/auth-sdk-core.test.mjs && node test/auth-sdk-providers.test.mjs && node test/i18n-core.test.mjs && node test/i18n-provider.test.mjs && node test/utils.test.mjs && node test/query-core.test.mjs && node test/query-hooks.test.mjs && node test/query-infinite-ssr.test.mjs && node test/router-ssr-integration.test.mjs"},"peerDependencies":{"yup":"^1.0.0"},"peerDependenciesMeta":{"yup":{"optional":true}},"devDependencies":{"jsdom":"^26.1.0","yup":"^1.7.1"},"keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"_id":"grainlet@1.1.1","gitHead":"c96b29b65e1cfc48d0add478ab06aa970f72bba8","_nodeVersion":"20.11.0","_npmVersion":"10.2.4","dist":{"integrity":"sha512-eitMImOxpEp1NjuvN6v1G4rAho7mMFsSPiML9fP35vcjkmbdtMkWVOn0a3ffyilAPxbX6+lHOeHy6c0sE5CiXQ==","shasum":"2a1065230dada99d7410bbcaec2fdfdf83df698f","tarball":"https://registry.npmjs.org/grainlet/-/grainlet-1.1.1.tgz","fileCount":163,"unpackedSize":512612,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIADnrL9ZIiP8qE1bHeVPLnOVns5vOO/7FbyOZPJ0IXxfAiEAmHpvPNGSM8N/hrd/aUG7QC0ClS9f9Nu2MRhacuZXQGk="}]},"_npmUser":{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"},"directories":{},"maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/grainlet_1.1.1_1787331337635_0.34615030865964425"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-16T17:12:00.814Z","modified":"2026-08-21T16:55:37.962Z","1.0.0":"2026-07-16T17:12:01.066Z","1.0.1":"2026-07-16T17:21:20.339Z","1.0.5":"2026-07-16T18:21:22.579Z","1.0.6":"2026-07-16T18:36:24.624Z","1.0.7":"2026-07-16T18:51:06.347Z","1.0.8":"2026-07-16T19:11:16.470Z","1.0.9":"2026-07-16T20:27:18.055Z","1.0.10":"2026-07-16T20:34:09.473Z","1.0.11":"2026-07-17T16:23:39.981Z","1.0.12":"2026-07-17T16:35:32.461Z","1.0.13":"2026-07-17T16:59:14.319Z","1.0.14":"2026-07-17T21:25:33.603Z","1.0.15":"2026-07-17T21:37:40.413Z","1.0.16":"2026-07-17T21:41:09.794Z","1.0.17":"2026-07-17T21:50:26.304Z","1.0.18":"2026-07-17T21:58:31.670Z","1.0.19":"2026-07-17T22:08:20.513Z","1.0.20":"2026-07-18T11:32:04.364Z","1.0.21":"2026-07-18T12:20:31.536Z","1.0.22":"2026-07-18T13:08:33.551Z","1.0.23":"2026-07-20T19:12:11.805Z","1.0.24":"2026-07-20T19:27:42.637Z","1.0.25":"2026-07-20T19:32:18.838Z","1.0.26":"2026-07-20T19:40:07.470Z","1.0.27":"2026-08-06T18:10:35.719Z","1.0.28":"2026-08-06T20:47:22.836Z","1.0.29":"2026-08-11T19:38:39.448Z","1.1.0":"2026-08-21T16:23:22.520Z","1.1.1":"2026-08-21T16:55:37.805Z"},"license":"MIT","keywords":["grainlet","grain","signals","jsx","router","ssr","fine-grained","typescript"],"description":"Fine-grained signals, JSX, routing, and SSR for the web","maintainers":[{"name":"enigma_08","email":"slavik.golovatskyu@gmail.com"}],"readme":"# grainlet\n\nFine-grained reactive UI: **signals**, **JSX**, **queries**, **forms**, **auth**, **i18n**, **History API routing**, and **SSR / hydrate**.\n\n## Install\n\n```bash\nnpm install grainlet\n```\n\nFor Vite JSX (dev only — install as `devDependencies`):\n\n```bash\nnpm install -D grainlet-vite vite @babel/core @babel/plugin-syntax-jsx\n```\n\nOr scaffold a project:\n\n```bash\nnpx create-grainlet my-app\n```\n\n## Usage\n\n```js\nimport { createSignal, render } from 'grainlet';\n\nfunction App() {\n  const [count, setCount] = createSignal(0);\n  return (\n    <button type=\"button\" onClick={() => setCount((c) => c + 1)}>\n      {count()}\n    </button>\n  );\n}\n\nrender(App, document.getElementById('app'));\n```\n\n## Vite\n\n```js\nimport { defineConfig } from 'vite';\nimport { grainJsx } from 'grainlet-vite';\n\nexport default defineConfig({\n  plugins: [grainJsx()],\n  esbuild: {\n    jsx: 'automatic',\n    jsxImportSource: 'grainlet',\n  },\n});\n```\n\n## Entry points\n\n| Import | Purpose |\n|--------|---------|\n| `grainlet` | Core API (signals, flow, render, hydrate) |\n| `grainlet/route` | History API routing (`Router`, `Route`, `Link`, …) |\n| `grainlet/forms` | Form state (`FormProvider`, `Field`, `createForm`, …) — see [forms/README.md](./forms/README.md) |\n| `grainlet/auth` | Session auth (`createAuth`, `AuthProvider`, `useSession`, …) — see [auth/README.md](./auth/README.md) |\n| `grainlet/auth-sdk` | Google, Apple, and GitHub OAuth integration — see [auth-sdk/README.md](./auth-sdk/README.md) |\n| `grainlet/i18n` | Translations (`createI18n`, `I18nProvider`, `useTranslation`, …) — see [i18n/README.md](./i18n/README.md) |\n| `grainlet/query` | Async server state (`QueryClient`, `useQuery`, `useMutation`, …) — see [query/README.md](./query/README.md) |\n| `grainlet/utils` | Generic helpers (`stableHash`, `replaceEqualDeep`, `Subscribable`, …) — see [utils/README.md](./utils/README.md) |\n| `grainlet/store` | Fine-grained proxy stores (`createStore`, `produce`, `reconcile`) — see [store/README.md](./store/README.md) |\n| `grainlet/testing` | Component, hook, event, wait, and hydration test helpers — see [testing/README.md](./testing/README.md) |\n| `grainlet/devtools` | Development signal/owner and Query inspectors — see [devtools/README.md](./devtools/README.md) |\n| `grainlet/ssr` | Buffered/streaming SSR, SSG, head, and Web/Node adapters — see [ssr/README.md](./ssr/README.md) |\n| `grainlet/jsx-runtime` | Automatic JSX runtime |\n| `grainlet-vite` | `grainJsx()` Vite plugin (separate package, `devDependency`) |\n| `grainlet-adapters` | Vercel and Cloudflare SSR deploy adapters (separate package) |\n\n> **Breaking:** Router and SSR APIs are no longer re-exported from `grainlet`. Import them from `grainlet/route` and `grainlet/ssr`. Forms, auth, auth-sdk, and i18n live under their respective `grainlet/*` entry points only.\n\n## Signals and lifecycle\n\n```js\nimport {\n  batch,\n  createDeferred,\n  createEffect,\n  createMemo,\n  createSignal,\n  isServer,\n  onCleanup,\n  onMount,\n  startTransition,\n  untrack,\n  useTransition,\n} from 'grainlet';\n```\n\n| API | Role |\n|-----|------|\n| `createSignal(initial)` | `[get, set]` — `get()` reads, `set(v)` or `set(prev => next)` writes |\n| `createMemo(fn)` | Cached accessor; recomputes when dependencies change |\n| `createEffect(fn)` | Run when dependencies change; may return cleanup. No-op on the server |\n| `onMount(fn)` | Once after this component's DOM is mounted; may return cleanup. No-op on the server |\n| `onCleanup(fn)` | Run when the current effect or component is disposed |\n| `batch(fn)` | Coalesce writes; flush effects once |\n| `untrack(fn)` | Read signals without subscribing |\n| `startTransition(fn)` | Schedule non-urgent updates; returns a `Promise` that settles after the flush |\n| `useTransition()` | `[pending, start]` — `pending()` is true while a transition is flushing |\n| `createDeferred(source, { timeoutMs? })` | Deferred copy of `source`, updated through `startTransition` |\n| `isServer()` | True during SSR |\n\n### onMount\n\n`onMount` runs after the owned DOM exists, so refs and measurements are valid. It\ndoes not re-run on later updates. Returning a function registers cleanup on\nunmount.\n\n```js\nfunction Chat() {\n  let root;\n\n  onMount(() => {\n    root.focus();\n    const id = setInterval(poll, 5000);\n    return () => clearInterval(id);\n  });\n\n  return <section ref={(el) => { root = el; }} tabIndex={-1}>…</section>;\n}\n```\n\nUse `onMount` for one-shot DOM setup (focus, observers, subscriptions). Use\n`createEffect` when work should re-run as signals change; it may also return\ncleanup, or register extra teardown with `onCleanup`.\n\n```js\nfunction Title(props) {\n  createEffect(() => {\n    document.title = props.title();\n  });\n\n  onCleanup(() => {\n    document.title = 'Grainlet';\n  });\n}\n```\n\n### batch and transitions\n\nDefault writes flush effects synchronously. `batch` groups several sets into one\nflush. `startTransition` keeps that flush off the urgent path so typing and\nclicks stay snappy while a large list catches up.\n\n```js\nconst [first, setFirst] = createSignal('');\nconst [last, setLast] = createSignal('');\nconst [filter, setFilter] = createSignal('');\nconst [pending, start] = useTransition();\nconst deferredFilter = createDeferred(filter);\n\ncreateEffect(() => {\n  first();\n  last();\n  // runs once per batch, not twice\n});\n\nbatch(() => {\n  setFirst('Ada');\n  setLast('Lovelace');\n});\n\nfunction Search() {\n  return (\n    <>\n      <input\n        value={filter()}\n        onInput={(e) => setFilter(e.currentTarget.value)}\n      />\n      <button\n        type=\"button\"\n        disabled={pending()}\n        onClick={() => start(() => setFilter(filter().trim()))}\n      >\n        Apply\n      </button>\n      <List filter={deferredFilter()} />\n    </>\n  );\n}\n```\n\n`isServer()` is true inside `renderToString*` / streaming SSR. Skip browser APIs\nthere; `onMount` and `createEffect` already no-op on the server.\n\n## Store\n\nNested objects and arrays — import from **`grainlet/store`**. Reads track\nindividual paths; one setter call is batched.\n\n```js\nimport { createStore, produce, reconcile } from 'grainlet/store';\n\nconst [state, setState] = createStore({\n  user: { name: 'Ada', age: 1 },\n  todos: [{ title: 'Ship', done: false }],\n});\n\nsetState('user', 'name', 'Grace');\nsetState({ user: { name: 'Grace', age: 2 } });\nsetState('todos', 0, produce((todo) => {\n  todo.done = true;\n}));\nsetState('user', reconcile({ name: 'Grace', age: 3 }));\n\ncreateEffect(() => {\n  state.user.name; // does not re-run when age changes\n});\n```\n\n`produce` mutates a cloned draft. `reconcile` applies a new tree while preserving\nunchanged nodes. Full guide: **[store/README.md](./store/README.md)**.\n\n## Control flow\n\n```js\nimport {\n  Show,\n  For,\n  VirtualList,\n  Switch,\n  Match,\n  Suspense,\n  ErrorBoundary,\n  Portal,\n  createContext,\n  useContext,\n  createResource,\n  lazy,\n} from 'grainlet';\n```\n\n| Component | Role |\n|-----------|------|\n| `Show` | Render children when `when` is truthy (else `fallback`) |\n| `For` | Map `each` list to children; prefers `item.id` keys |\n| `VirtualList` | Windowed list (vertical or horizontal) — overscan, optional `debounceTime`, infinite scroll via `onEndReached` |\n| `Switch` / `Match` | First matching `when` branch |\n| `Suspense` | `fallback` while nested `createResource` / `lazy` is pending |\n| `ErrorBoundary` | Catch render/update errors; `fallback` or `(error, reset) => …` |\n| `Portal` | Render children into `document.body` (or `mount`) |\n| `createContext` / `useContext` | Share data without prop drilling (`Provider` + consume) |\n| `createResource` | Async data `[resource]` — `resource()` reads value |\n| `lazy` | Lazy-load a component (`lazy(() => import('./Page.js'))`) |\n\nPrefer these over `{cond() && <X/>}` so conditionals update without re-running the parent.\n\n```js\n<VirtualList\n  each={items()}\n  itemHeight={48}\n  height={400}\n  overscan={5}\n  aria-label=\"Items\"\n>\n  {(item) => <div class=\"row\">{item.label}</div>}\n</VirtualList>\n\n// The outer scroller accepts normal div props, a DOM ref, and an imperative API.\nlet scroller;\nlet listApi;\n\n<VirtualList\n  each={items()}\n  itemHeight={48}\n  height={400}\n  id=\"search-results\"\n  aria-label=\"Search results\"\n  data-testid=\"results-list\"\n  ref={(element) => (scroller = element)}\n  apiRef={(api) => (listApi = api)}\n  onScroll={(event) => console.log(event.currentTarget.scrollTop)}\n>\n  {(item) => <div class=\"row\">{item.label}</div>}\n</VirtualList>\n\nlistApi?.scrollToIndex(250, { align: 'center', behavior: 'smooth' });\nlistApi?.scrollToItem(items()[0]);\nlistApi?.scrollToOffset(0);\nlistApi?.getVisibleRange(); // { start, end }\nlistApi?.getElement() === scroller; // true\n\n<VirtualList\n  orientation=\"horizontal\"\n  each={items()}\n  itemWidth={120}\n  width={480}\n  height={80}\n  debounceTime={32}\n  aria-label=\"Horizontal items\"\n  data-layout=\"horizontal\"\n  apiRef={(api) => (listApi = api)}\n>\n  {(item) => <div class=\"card\">{item.label}</div>}\n</VirtualList>\n\n// Infinite scroll — parent owns fetch + append\nconst [page, setPage] = createSignal([]);\nconst [loading, setLoading] = createSignal(false);\nconst [hasMore, setHasMore] = createSignal(true);\n\nasync function loadMore() {\n  if (loading() || !hasMore()) return;\n  setLoading(true);\n  const next = await fetchPage(page().length);\n  setPage((list) => [...list, ...next.items]);\n  setHasMore(next.hasMore);\n  setLoading(false);\n}\n\n<VirtualList\n  each={page()}\n  itemHeight={88}\n  height={520}\n  onEndReached={loadMore}\n  endReachedThreshold={0.2}\n  endReachedLoading={loading()}\n  aria-label=\"Infinite results\"\n  aria-busy={loading()}\n  apiRef={(api) => (listApi = api)}\n>\n  {(item) => <div class=\"row\">{item.label}</div>}\n</VirtualList>\n```\n\n```js\n<ErrorBoundary\n  fallback={(error, reset) => (\n    <div>\n      <p>Something went wrong: {error.message}</p>\n      <button type=\"button\" onClick={reset}>Try Again</button>\n    </div>\n  )}\n>\n  <ErrorProne />\n</ErrorBoundary>\n```\n\nEvent handlers and `setTimeout` callbacks are not caught (same as Solid).\n\n```js\n<div style={{ overflow: 'hidden' }}>\n  <Portal>\n    <div class=\"popup\">Escapes overflow clipping</div>\n  </Portal>\n</div>\n\n<Portal mount={document.querySelector('#portal-root')}>\n  <p>Custom mount node</p>\n</Portal>\n\n{/* SVG: wrap in <g>; head: no wrapper */}\n<Portal mount={svgEl} isSVG>\n  <circle r=\"4\" />\n</Portal>\n```\n\n```js\nconst CounterContext = createContext();\n\nfunction CounterProvider(props) {\n  const [count, setCount] = createSignal(props.count ?? 0);\n  return (\n    <CounterContext.Provider value={[count, setCount]}>\n      {props.children}\n    </CounterContext.Provider>\n  );\n}\n\nfunction useCounter() {\n  const value = useContext(CounterContext);\n  if (!value) throw new Error('Missing CounterProvider');\n  return value;\n}\n\nfunction Child() {\n  const [count, setCount] = useCounter();\n  return (\n    <button type=\"button\" onClick={() => setCount((n) => n + 1)}>\n      {count()}\n    </button>\n  );\n}\n```\n\nPass a signal (or store) as `value` so consumers stay reactive without remounting the Provider.\n\n## Refs\n\nAttach `ref` to any host element to get the DOM node (Solid-compatible):\n\n```js\n// Callback\n<input ref={(el) => { inputEl = el; }} />\n\n// Signal setter (stable function identity)\nconst [el, setEl] = createSignal(null);\n<div ref={setEl} />\n\n// Variable form — requires grainJsx() (rewrites to an assignment callback)\nlet box;\n<div ref={box} />\n\n// Forwarding\nfunction Field(props) {\n  return <input ref={props.ref} />;\n}\n<Field ref={setEl} />\n```\n\nRefs are set when the node is created and cleared with `null` when it is removed (e.g. inside `Show`).\n\n## TypeScript\n\nTypes ship with the package (no extra install). Use the same Vite config with `jsxImportSource: 'grainlet'`:\n\n```ts\nimport { createSignal, render, type Accessor } from 'grainlet';\n\nfunction App() {\n  const [count, setCount] = createSignal(0);\n  return (\n    <button type=\"button\" onClick={() => setCount((c) => c + 1)}>\n      {count()}\n    </button>\n  );\n}\n\nrender(App, document.getElementById('app')!);\n```\n\n```json\n{\n  \"compilerOptions\": {\n    \"jsx\": \"react-jsx\",\n    \"jsxImportSource\": \"grainlet\"\n  }\n}\n```\n\n`grainlet-vite` includes typings for `grainJsx()`.\n\n## Forms\n\nFormik-inspired forms — import from **`grainlet/forms`**:\n\n```js\nimport {\n  FormProvider,\n  Form,\n  Field,\n  ErrorMessage,\n  createForm,\n  useFormContext,\n  required,\n  isEmail,\n  minLength,\n} from 'grainlet/forms';\n\nfunction Signup() {\n  return (\n    <FormProvider\n      initialValues={{ email: '', password: '' }}\n      rules={{\n        email: [required('Email is required'), isEmail('Enter a valid email')],\n        password: [\n          required('Password is required'),\n          minLength(8, 'Use at least 8 characters'),\n        ],\n      }}\n      onSubmit={async (values) => {\n        await api.signup(values);\n      }}\n    >\n      <Form>\n        <Field name=\"email\" type=\"email\" />\n        <ErrorMessage name=\"email\" />\n        <Field name=\"password\" type=\"password\" />\n        <ErrorMessage name=\"password\" />\n        <button type=\"submit\">Sign up</button>\n      </Form>\n    </FormProvider>\n  );\n}\n```\n\nHeadless (no provider):\n\n```js\nconst form = createForm({\n  initialValues: { email: '' },\n  rules: { email: [required(), isEmail()] },\n  onSubmit: async (values) => { /* … */ },\n});\n// form.values(), form.handleChange, form.handleSubmit, …\n```\n\nSupports nested paths (`social.facebook`, `friends[0]`), field-level `validate={[required(), isEmail()]}`, optional Yup `validationSchema`, and `FieldArray`. Full guide: **[forms/README.md](./forms/README.md)**.\n\n## Auth\n\nHeadless, Auth.js-style sessions — import from **`grainlet/auth`**. Your app owns the API, cookies, and OAuth SDK:\n\n```js\nimport { Show, render } from 'grainlet';\nimport {\n  AuthProvider,\n  Credentials,\n  createAuth,\n  createLocalStorageAdapter,\n  useSession,\n  ProtectedRoute,\n} from 'grainlet/auth';\n\nconst auth = createAuth({\n  providers: [\n    Credentials({\n      credentials: {\n        email: { label: 'Email', type: 'email' },\n        password: { label: 'Password', type: 'password' },\n      },\n      authorize: (credentials) =>\n        api.post('/api/auth/login', credentials),\n    }),\n  ],\n  refresh: ({ userId, refreshToken }) =>\n    api.post('/api/auth/refresh', { userId, refreshToken }),\n  storage: createLocalStorageAdapter(),\n});\n\nfunction AccountMenu() {\n  const session = useSession();\n\n  return (\n    <Show\n      when={() => session.status() === 'authenticated'}\n      fallback={\n        <button\n          type=\"button\"\n          onClick={() =>\n            session.signIn('credentials', {\n              email: 'user@example.com',\n              password: 'secret',\n            })\n          }\n        >\n          Sign in\n        </button>\n      }\n    >\n      <span>{session.data()?.user.email}</span>\n      <button type=\"button\" onClick={() => session.signOut()}>\n        Sign out\n      </button>\n    </Show>\n  );\n}\n\nfunction SettingsRoute() {\n  return (\n    <ProtectedRoute\n      redirectTo=\"/auth/signin\"\n      loadingFallback={<p>Checking session…</p>}\n    >\n      <Settings />\n    </ProtectedRoute>\n  );\n}\n\nrender(\n  () => (\n    <AuthProvider client={auth}>\n      <AccountMenu />\n    </AuthProvider>\n  ),\n  document.getElementById('app')\n);\n```\n\n`useSession()` returns the auth client. Call accessors: `data()`, `status()` (`loading` | `authenticated` | `unauthenticated`), `error()`. Also: `signIn`, `signOut`, `getSession`, `refresh`, `update`. Default storage is memory-only; use `createLocalStorageAdapter()` to persist across reloads. Full guide: **[auth/README.md](./auth/README.md)**.\n\nFor batteries-included Google, Apple, and GitHub sign-in, configure\n`createAuthSdk()` and add `GoogleSignIn(sdk)`, `AppleSignIn(sdk)`, and\n`GitHubSignIn(sdk)` to the providers array. The SDK handles provider scripts,\npopups, tokens, and calls to your backend. Full guide:\n**[auth-sdk/README.md](./auth-sdk/README.md)**.\n\n## i18n\n\nNamespaced JSON translations — import from **`grainlet/i18n`**:\n\n```js\nimport { render } from 'grainlet';\nimport { createI18n, I18nProvider, useTranslation } from 'grainlet/i18n';\nimport enCommon from './locales/en/common.json';\nimport ukCommon from './locales/uk/common.json';\n\n// en/common.json — { \"welcome\": \"Welcome, {name}\", \"actions\": { \"continue\": \"Continue\" } }\n\nconst i18n = createI18n({\n  locale: 'en',\n  fallbackLocale: 'en',\n  resources: {\n    en: {\n      common: enCommon,\n      // Lazy namespace: auth: () => import('./locales/en/auth.json'),\n    },\n    uk: { common: ukCommon },\n  },\n});\n\nfunction Welcome() {\n  const { t, locale, setLocale } = useTranslation('common');\n\n  return (\n    <main>\n      <h1>{t('welcome', { name: 'Mike' })}</h1>\n      <p>{t('actions.continue')}</p>\n      <button type=\"button\" onClick={() => setLocale(locale() === 'en' ? 'uk' : 'en')}>\n        Switch language\n      </button>\n    </main>\n  );\n}\n\nrender(\n  () => (\n    <I18nProvider client={i18n}>\n      <Welcome />\n    </I18nProvider>\n  ),\n  document.getElementById('app')\n);\n```\n\nPass a namespace to `useTranslation`, then use keys relative to that file. Nested keys use dot paths (`segment.title.key`). Missing keys fall back to `fallbackLocale`, then the key string. For form validators, pass lazy messages: `required(() => t('validation.required'))`. Full guide: **[i18n/README.md](./i18n/README.md)**.\n\n## Query\n\nAsync server state — import from **`grainlet/query`**. Query and mutation fields\nare Grainlet accessors (`data()`, `isPending()`), not plain properties.\n\n```js\nimport { QueryClient, QueryClientProvider, useQuery } from 'grainlet/query';\n\nconst queryClient = new QueryClient({\n  defaultOptions: { queries: { staleTime: 30_000 } },\n});\n\nfunction Todo({ id }) {\n  const todo = useQuery({\n    queryKey: ['todo', id],\n    queryFn: ({ signal }) =>\n      fetch(`/api/todos/${id}`, { signal }).then((r) => r.json()),\n  });\n\n  return <h1>{todo.data()?.title}</h1>;\n}\n```\n\nAlso: `useMutation`, `useInfiniteQuery`, `useQueries`, `HydrationBoundary`,\n`dehydrate` / `hydrate`. Full guide: **[query/README.md](./query/README.md)**.\n\n## Routing\n\nHistory API router — no hash required:\n\n```js\nimport {\n  Router,\n  Route,\n  Link,\n  navigate,\n  useParams,\n  useLocation,\n} from 'grainlet/route';\n\nfunction User() {\n  const params = useParams();\n  const location = useLocation();\n  return (\n    <section>\n      <h2>User {params().id}</h2>\n      <p>{location().pathname}</p>\n    </section>\n  );\n}\n\nfunction App() {\n  return (\n    <>\n      <nav>\n        <Link href=\"/\" activeClass=\"active\">Home</Link>\n        <Link href=\"/users/1\" activeClass=\"active\">User 1</Link>\n      </nav>\n      <Router basename=\"/app\">\n        <Route path=\"/\" component={Home} />\n        <Route path=\"/users/:id\" component={User} />\n        <Route path=\"*\" component={NotFound} />\n      </Router>\n    </>\n  );\n}\n\n// Imperative navigation (respects Router basename)\nnavigate('/users/3');\n```\n\n| API | Role |\n|-----|------|\n| `Router` | Match location to `Route` children (optional `basename`) |\n| `Route` | `path` + `component` (`:param`, `*` catch-all) |\n| `Link` | Client-side `<a>`; `activeClass` when the path matches |\n| `navigate(to)` | Push/replace history |\n| `useParams()` | Signal of route params (`params().id`) |\n| `useLocation()` | Signal of `{ pathname, search, hash, state }` |\n\nNested layouts, loaders, and actions are opt-in with `mode=\"nested\"`:\n\n```js\nimport {\n  Link,\n  Outlet,\n  Route,\n  Router,\n  queryLoader,\n  useNavigation,\n  useRouteLoaderData,\n} from 'grainlet/route';\n\nfunction Layout() {\n  const navigation = useNavigation();\n  return (\n    <main>\n      <Link href=\"/\">Home</Link>\n      <p>{() => navigation().state}</p>\n      <Outlet />\n    </main>\n  );\n}\n\nfunction Project() {\n  const project = useRouteLoaderData();\n  return <h1>{() => project().name}</h1>;\n}\n\n<Router mode=\"nested\" queryClient={queryClient} hydrationState={routeState}>\n  <Route element={Layout}>\n    <Route\n      path=\"projects/:id\"\n      id=\"project\"\n      component={Project}\n      loader={queryLoader(({ params }) => ({\n        queryKey: ['project', params.id],\n        queryFn: () =>\n          fetch(`/api/projects/${params.id}`).then((r) => r.json()),\n      }))}\n    />\n  </Route>\n</Router>\n```\n\n`queryLoader` shares the Router `queryClient` with `useQuery`. Also:\n`useSubmit`, `useMatches`, `useOutletContext`, `useRouteActionData`,\n`useRouteError`, `useSearchParams`, `redirect`. On the server,\n`prepareRoutes` / `renderRouteDocument` run loaders before HTML; call\n`hydrateRouterState(state, queryClient)` before client mount. Full guide:\n**[route/README.md](./route/README.md)**.\n\n## SSR\n\n```js\nimport { Suspense, lazy, hydrate } from 'grainlet';\nimport {\n  renderToString,\n  renderToStringAsync,\n  wrapHtmlDocument,\n} from 'grainlet/ssr';\n\nconst body = renderToString(App, {}, { url: 'http://localhost/' });\n\n// Await lazy / createResource before emitting HTML (resolved content, not fallback)\nconst Home = lazy(() => import('./pages/home.js'));\nfunction App() {\n  return (\n    <Suspense fallback={<p>Loading</p>}>\n      <Home />\n    </Suspense>\n  );\n}\nconst asyncBody = await renderToStringAsync(App);\n```\n\nOn the server, `createEffect` is a no-op; `createMemo` evaluates once for the HTML snapshot.\n`renderToStringAsync` keeps SSR mode on across passes until pending Suspense work settles.\n\nProduction apps should use `createRequestHandler` (Web `Response`) or the Node\n`createNodeHandler` export. Streaming uses `renderToReadableStream` and\n`renderRouteToReadableStream`: the document shell and Suspense fallbacks flush\nfirst, then escaped boundary patches replace resolved regions out of order.\nRedirects from loaders happen before the shell. After shell emission, failures\nstay inside their boundary and surface through `onError`.\n\nAlways create one `QueryClient` per request. `head` is escaped text; trusted\nmarkup belongs in `unsafeHead`. Prefer `Title`, `Meta`, `HeadLink`, `Canonical`,\n`JsonLd`, and `OpenGraph`. Pass a CSP `nonce` so state scripts and stream\npatches inherit it. `prerenderPaths` / `writePrerendered` generate static HTML\nplus a `grainlet-prerender.json` manifest. Scaffold this pipeline with\n`npx create-grainlet my-app --ssr`.\n\n`configureHydration({ onMismatch, strict })` reports expected/actual nodes,\nJSX source, and a component stack. Hydration mismatches replace the subtree\non the client unless strict mode throws. Full guide: **[ssr/README.md](./ssr/README.md)**.\n\n## Testing\n\n`grainlet/testing` uses the DOM from Vitest, Jest, JSDOM, happy-dom, or a\nbrowser. It does not bundle a DOM implementation.\n\n```js\nimport {\n  cleanup,\n  fireEvent,\n  hydrate,\n  render,\n  renderHook,\n  screen,\n  waitFor,\n} from 'grainlet/testing';\n\nconst view = render(Counter);\nfireEvent.click(screen.getByRole('button', { name: 'Increment' }));\nawait waitFor(() => screen.getByText('1'));\nview.unmount();\ncleanup();\n```\n\nPass `html` to `hydrate` to attach to existing markup without clearing the\ncontainer. Full guide: **[testing/README.md](./testing/README.md)**.\n\n## Devtools\n\nInstall the hook before application signals are created, then render the panel\nin development only:\n\n```js\nimport { GrainletDevtools, installDevtoolsHook } from 'grainlet/devtools';\n\ninstallDevtoolsHook();\n\n<GrainletDevtools queryClient={queryClient} />\n```\n\nThe inspector shows signal / effect / owner events and Query cache state. Full\nguide: **[devtools/README.md](./devtools/README.md)**.\n","readmeFilename":"README.md"}