{"_id":"glimm","_rev":"8-4a7e193310269623362c4961ddb7af32","name":"glimm","dist-tags":{"latest":"0.3.1"},"versions":{"0.1.0":{"name":"glimm","version":"0.1.0","keywords":["webgl","shader","page-transition","animation","react","nextjs","iridescent","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"UNLICENSED","_id":"glimm@0.1.0","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"657e05ddbf2961bfeb346b62f00a50d97cd709ad","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.1.0.tgz","fileCount":9,"integrity":"sha512-FyJJNTexsnPthOqithLy9cMdpA/MZ3OAdoye3BHFVR8tMxSCeifi9qent9NxV2iwetOyoHK+O9cLS+3RQi6taw==","signatures":[{"sig":"MEQCIBQ7qISX8heLaXIz/9hFjW7bjJgWzIaTemQO9wrysJ1sAiA5iQtSdkzn1wow8Njh4YWw4unbTDSBra66rO4H4zz12A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":120842},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"ab05e8366dd8581e8dffe3c434a2ea90b40e5161","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL iridescent sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.1.0_1779379803859_0.6874282385670925","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"glimm","version":"0.1.1","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"UNLICENSED","_id":"glimm@0.1.1","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"41fb04c46994f4020e9ced176baf16940b759457","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.1.1.tgz","fileCount":9,"integrity":"sha512-0dgKMSm3zQQtCkfLrcAfQQiUz37Y2Gpx/m98WbIXFJxzS/q2WRmkqEYHuHh4nygwqyIVkVWfiVl1DJVg27z8QA==","signatures":[{"sig":"MEYCIQDdMmM9ThI9cRb/dUpZUleLKm8hH+3DWKSfQQzkudpVTwIhANYdi0bRegikhJbARU5xlLaV+gurhB/nZHMbM+9oBa71","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":120818},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"ab05e8366dd8581e8dffe3c434a2ea90b40e5161","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.1.1_1779381252418_0.21104426946784605","host":"s3://npm-registry-packages-npm-production"}},"0.1.2":{"name":"glimm","version":"0.1.2","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"UNLICENSED","_id":"glimm@0.1.2","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"0d48bf167ac657789fa30b100551b027502502d0","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.1.2.tgz","fileCount":9,"integrity":"sha512-pswzuMHZAPNU6KY8VgcCKp9dJSbXR8JUIAosnXr7ShO2/D2GHoec76BHW0otuA8aWcWcHMuuiS5RL3BprTejrg==","signatures":[{"sig":"MEUCIAZ3yBEMumuMvM9G8lJSaG5BhHCiGBUqwZAv917LiAm3AiEAg+yiB0AD++bGb9irAotee5OhrodSh4pu7cqDVI7Lp4s=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":120271},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"ab05e8366dd8581e8dffe3c434a2ea90b40e5161","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.1.2_1779388082898_0.667263809888132","host":"s3://npm-registry-packages-npm-production"}},"0.1.3":{"name":"glimm","version":"0.1.3","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"UNLICENSED","_id":"glimm@0.1.3","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"6d6ebe6b8cba877a57c939b01cdd2e502d54f180","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.1.3.tgz","fileCount":9,"integrity":"sha512-Ozbn3Dg/YsBzfp5KgeRvZjm6jpMjHBei4VXcJRLIE6v4x3aYC47ZtjgkgHRJw/SDN4eX7g/Qdtmhmxw2orEZ3A==","signatures":[{"sig":"MEUCIEe5RN0589cN+fltrw3chz04ICk1o2jaB+HjK/wQFTZAAiEAs9SO41gHucCt75bLh/e1yDYMUquUZ43eCONQO8JRJ8M=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":117998},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"ab05e8366dd8581e8dffe3c434a2ea90b40e5161","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.1.3_1779458379588_0.32680836398728896","host":"s3://npm-registry-packages-npm-production"}},"0.1.4":{"name":"glimm","version":"0.1.4","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"MIT","_id":"glimm@0.1.4","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"c4d7de30951e8537a20bde533a28b7bf60d5d859","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.1.4.tgz","fileCount":10,"integrity":"sha512-OIfoxkEnayr2oQNG8MzAotjq1ZhND2PwQT/M2a16Z+vxQisxHXKWX1FihgAqQaRt2oWfFFZuBktoVHkho2w2jw==","signatures":[{"sig":"MEUCIQC2iIL6/gCrLI8QQcvX0Mn8h4ITFFWHDovQMUamdPHsQgIgfbOpmDJ6AJRugCrHtmXuqvQ0PGSRCTezoL+NJ766jsM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":119008},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"028d70cf69d4be636fd4496fe9b30fb0a84dd97f","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.1.4_1782137324259_0.22129903586065502","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"glimm","version":"0.2.0","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"MIT","_id":"glimm@0.2.0","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"5d388c0de754d2909e45037775f8eb7585316d57","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.2.0.tgz","fileCount":10,"integrity":"sha512-6CTL3OjT7l9YGHhNKwDEc3ixg8AlxCDfHFNfun3LRFuh0phR9tsWwFxvlD4j9GpRus0yu9X5BU8xsOxEKyBBag==","signatures":[{"sig":"MEYCIQDKCqfwn2HRgkvy0e3CC6Hs3C4S3KmR/oqhT3JaqstYRwIhAOl4MxG3qi8qfTa2wIdQ5BN9nLSLOJn88JG/hLFCwfCh","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":123730},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"d7f618c0f23476253e325d77b0cb4533f25f54f0","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.2.0_1783793914707_0.8962973964160659","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"glimm","version":"0.3.0","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"MIT","_id":"glimm@0.3.0","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"dist":{"shasum":"47fec72939250efaa0774a502d2f937436f0565d","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.3.0.tgz","fileCount":10,"integrity":"sha512-Maw5WJnUsgyfsHl7Vp95wa8G1uaFhUOSoQzAVPX1DxdHxmWNBa9VtDRNPplH1A+bIazn956ZP/wQvH4ZSxKN9Q==","signatures":[{"sig":"MEUCIDxt9CKWDg+AaJCkgbgZySXlLq2QxfguTpw2rHpagF5SAiEAvc9OPq6irfE8hD2DZxT01jv7pDrWQmqGjUq9evI01j8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":126134},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","module":"./dist/index.js","engines":{"node":">=18"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./package.json":"./package.json"},"gitHead":"1693ab1fe529068be1f8b179a378684f74d4e8d8","scripts":{"dev":"tsup --watch","build":"tsup","clean":"rm -rf dist","typecheck":"tsc --noEmit","prepublishOnly":"npm run clean && npm run build"},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"_npmVersion":"10.5.0","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","directories":{},"sideEffects":false,"_nodeVersion":"21.7.3","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"next":"^16.0.0","tsup":"^8.3.5","react":"^19.0.0","react-dom":"^19.0.0","typescript":"^5.7.3","@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/glimm_0.3.0_1784149890464_0.9582462617726437","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"name":"glimm","version":"0.3.1","description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"license":"MIT","author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"type":"module","sideEffects":false,"main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./react":{"types":"./dist/react.d.ts","import":"./dist/react.js"},"./next":{"types":"./dist/next.d.ts","import":"./dist/next.js"},"./package.json":"./package.json"},"scripts":{"build":"tsup","dev":"tsup --watch","typecheck":"tsc --noEmit","clean":"rm -rf dist","prepublishOnly":"npm test && npm run typecheck && npm run clean && npm run build","test":"vitest run","test:browser":"node tests/browser/check.mjs","test:slow":"node tests/browser/slow-check.mjs","test:native":"node tests/browser/native.mjs"},"peerDependencies":{"next":">=14","react":">=18"},"peerDependenciesMeta":{"next":{"optional":true},"react":{"optional":true}},"devDependencies":{"@types/node":"^22.10.0","@types/react":"^19.0.0","@types/react-dom":"^19.0.0","jsdom":"^24.1.3","next":"^16.0.0","playwright-core":"^1.59.1","react":"^19.0.0","react-dom":"^19.0.0","tsup":"^8.3.5","typescript":"^5.7.3","vitest":"^3.2.7"},"engines":{"node":">=18"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/nomanjack/glimm.git","directory":"packages/glimm"},"homepage":"https://glimm.dev","bugs":{"url":"https://github.com/nomanjack/glimm/issues"},"_id":"glimm@0.3.1","gitHead":"ea7f5500b10979c1abd006b2462e38528fce1bb8","_nodeVersion":"21.7.3","_npmVersion":"10.5.0","dist":{"integrity":"sha512-7O+Ga+cqqP8FEFDa63X+BXCYKndlnZZEMjTl1DhMfQ3yWweDgl8nC+ImP/zLo351YEn/6WpnOL6jKfvFWmnyDg==","shasum":"5e24a7060bfd637b3dca383f2251690d0a023285","tarball":"https://registry.npmjs.org/glimm/-/glimm-0.3.1.tgz","fileCount":11,"unpackedSize":148009,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCZ++VOgh2E2F+X0cqAOOeAg5HMm2q2tzW+SVIogMKxIAIhALZcZwhZJSwMHEAdfQ+cRi4iFM8QrBCjMmuwK8HYvKp/"}]},"_npmUser":{"name":"nojack","email":"Noman.ijaz021@gmail.com"},"directories":{},"maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/glimm_0.3.1_1789310403973_0.05375376162996681"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-21T16:10:03.654Z","modified":"2026-09-13T14:40:04.236Z","0.1.0":"2026-05-21T16:10:03.999Z","0.1.1":"2026-05-21T16:34:12.568Z","0.1.2":"2026-05-21T18:28:03.074Z","0.1.3":"2026-05-22T13:59:39.776Z","0.1.4":"2026-06-22T14:08:44.436Z","0.2.0":"2026-07-11T18:18:34.881Z","0.3.0":"2026-07-15T21:11:30.656Z","0.3.1":"2026-09-13T14:40:04.106Z"},"author":{"name":"Noman Ijaz","email":"noman.ijaz021@gmail.com"},"license":"MIT","keywords":["webgl","shader","page-transition","animation","react","nextjs","oklch"],"description":"WebGL sweep transitions for the web — framework-agnostic core with React and Next.js adapters.","maintainers":[{"name":"nojack","email":"Noman.ijaz021@gmail.com"}],"readme":"# glimm\n\nWebGL **sweep transitions** for the web. A colour band sweeps across\nthe viewport, revealing the incoming view behind it while retaining the outgoing\nview ahead — the iOS \"name drop\" feel, as a masked page transition.\n\n- **Framework-agnostic core** — drive the shader directly from vanilla JS.\n- **React adapter** — `<GlimmProvider>` + `useGlimm()`.\n- **Next.js adapter** — `<TransitionLink>`, `useTransitionRouter()`, auto link interception.\n- Zero runtime dependencies. WebGL decoration with browser snapshots and an opaque fallback; no image assets required.\n- Respects `prefers-reduced-motion` and degrades gracefully when WebGL is unavailable.\n\n## Install\n\n```bash\nnpm install glimm\n```\n\n`react` and `next` are optional peer dependencies — install whichever adapter\nyou use. The core entry point needs neither.\n\n## Quick start (Next.js, App Router)\n\n```tsx\n// app/layout.tsx\nimport { GlimmProvider, InterceptLinks } from 'glimm/next'\n\nexport default function RootLayout({ children }: { children: React.ReactNode }) {\n  return (\n    <html lang=\"en\">\n      <body>\n        <GlimmProvider palette=\"prism\">\n          <InterceptLinks />\n          {children}\n        </GlimmProvider>\n      </body>\n    </html>\n  )\n}\n```\n\n`<InterceptLinks />` runs every same-origin link click through a sweep. Opt a\nlink out with `data-glimm-skip`.\n\n### Per-navigation control\n\n```tsx\n'use client'\nimport { TransitionLink, useTransitionRouter } from 'glimm/next'\n\n// Declarative — a drop-in <Link> replacement:\n<TransitionLink href=\"/about\" sweep={{ palette: 'berry', direction: 'rtl' }}>\n  About\n</TransitionLink>\n\n// Programmatic — a drop-in useRouter():\nconst router = useTransitionRouter()\nawait save(form)\nrouter.push('/dashboard', { palette: 'ember' })\n```\n\n## React (without Next.js)\n\n```tsx\nimport { GlimmProvider, useGlimm } from 'glimm/react'\n\nfunction MyButton() {\n  const { sweep } = useGlimm()\n  return <button onClick={() => sweep(() => doNavigation())}>Go</button>\n}\n```\n\n`sweep(navigate, options?)` plays the band, awaits your `navigate` callback at\nthe midpoint, and returns a `{ midpoint, done, cancel }` handle.\n\n## Vanilla / framework-agnostic core\n\n```ts\nimport { createShader, playSweep } from 'glimm'\n\nconst canvas = document.querySelector('canvas')!\nconst ctrl = createShader({ canvas, /* palette, bandTight, direction */ })\n\nplaySweep(ctrl, {\n  palette: 'citrus',\n  onMidpoint: () => swapPageContent(),\n  onComplete: () => ctrl.destroy(),\n})\n```\n\nAlternate looks: `createMeshShader` (vertex-displaced mesh) and\n`createNamedropShader` (radial bulge reveal).\n\n## Sweep options\n\n| Option        | Default  | Notes |\n| ------------- | -------- | ----- |\n| `sweepMs`     | `1100`   | ms for the band to cross the viewport |\n| `outroMs`     | `220`    | ms for the post-traversal fade-out |\n| `midpoint`    | `0.56`   | 0–1 progress point where `onMidpoint` fires |\n| `palette`     | `prism`  | preset name or a custom `Palette` |\n| `direction`   | `ltr`    | `ltr` \\| `rtl` \\| `ttb` \\| `btt` |\n| `easing`      | `ease` | preset name or an `(p) => number` fn |\n| `bandTight`   | —        | band sharpness |\n| `peakAlpha`   | `1`      | caps the band's peak opacity |\n| `brightness`  | `1`      | 0–1.5, multiplies band RGB (dim it on dark backgrounds) |\n| `waveAmount`  | `0`      | 0–2, opt-in edge displacement; 0 is straight |\n| `rippleAmount`| `1`      | 0–2, vertical ripple texture |\n| `waveSpeed`   | `1`      | 0–3, multiplies time-based motion |\n| `swellAmount` | `0.55`   | 0–1, depth swell |\n| `onMidpoint`  | —        | fires when the band reaches `midpoint` — swap pages here |\n| `onComplete`  | —        | fires when the outro fade finishes |\n\n**Built-in palettes:** `prism`, `berry`, `lagoon`, `citrus`, `azure`,\n`ember`. Build your own with `accentPair`,\n`accentChain`, or `shuffleAccentPalette`.\n\n**Built-in easings:** `linear`, `easeOutQuart`, `easeOutCubic`, `easeInCubic`,\n`easeInOutCubic`, `easeOutExpo`, `easeInOutQuint`, `snap`, `ease`, `back`.\n\n## Entry points\n\n| Import          | Use for |\n| --------------- | ------- |\n| `glimm`         | Framework-agnostic core: shader factories, `playSweep`, palettes, easings, colour math. |\n| `glimm/react`   | `<GlimmProvider>` and `useGlimm()` for any React app. |\n| `glimm/next`    | Everything in `glimm/react` plus `<TransitionLink>`, `useTransitionRouter()`, and `interceptLinks` / `<InterceptLinks>`. |\n\nImport the provider and hooks from a **single** entry point per app so they\nshare one React context.\n\n## License\n\n[MIT](./LICENSE) © Noman Ijaz. Free to use, modify, and distribute.\n\n## Lifecycle and cancellation\n\n`midpoint` settles after the midpoint callback finishes. `done` waits for that\nwork and the outro. Callback failures are logged, and handles settle without\nrejecting. Instant reduced-motion and no-WebGL navigation also run the per-call\nlifecycle callbacks.\n\nCancelling settles the handle and prevents any midpoint callback that has not\nstarted. It cannot undo navigation or asynchronous work that has already begun.\nThe core `cancel()` preserves the current band position and alpha for a replacement\nsweep; when stopping without a replacement, call `ctrl.setAlpha(0)` or destroy\nthe controller. The default renderer stops drawing while alpha is zero.\n\nNext.js router calls do not return a readiness promise. The provider coordinates\nthem through React transitions; this does not guarantee that every image, effect,\nor independently streamed boundary has finished loading.\n\n## Local checks\n\nFrom `packages/glimm`, run `npm test`, `npm run typecheck`, and `npm run build`.\nThe regression tests cover cancellation, callback failures, slow midpoint work,\ninvalid timing values, instant fallback behavior, link handling, unmount cleanup,\nand idle rendering.\n\n## Masked React and Next.js transitions\n\nThe provider now retains the outgoing rendered view with the browser View\nTransitions API. The sweep is a real boundary: the incoming view is revealed\nbehind the band, while outgoing pixels remain ahead of it. The browser's default\ncrossfade is disabled. The iridescent canvas is a separate live transition layer.\n\nNavigation/state updates run during snapshot preparation. The provider waits for\nReact transition commits (including suspending updates) and a returned navigation\npromise before revealing the new tree. Supply work through the navigation callback;\nupdates scheduled later by unrelated timers/effects are outside this handoff.\nAn explicitly committed loading boundary can still be the incoming view.\n\nWhen browser snapshots are unavailable or fail, an opaque, theme-aware curtain\ncovers the view before updating it, then reveals the committed content. Its opacity\nis independent of shader brightness and alpha. Reduced motion and unavailable\nWebGL continue to use immediate navigation. An 8-second preparation timeout avoids\ntrapping the page; it cannot cancel application requests already in progress.\n\nThe low-level `playSweep` API remains a decorative canvas sweep; automatic content\ncoordination belongs to `GlimmProvider`. Core cancellation preserves shader state;\nprovider cancellation now also removes its masks and clears the overlay.\n\nRun `npm run test:browser` for browser pixel checks. It uses an installed Chrome\n(default macOS path); set `CHROME_PATH` for another installation. The test verifies\nboth sides of the boundary with shader alpha set to zero, all four directions,\nslow Suspense commits, and opaque fallback behavior.\n\nTo inspect the local form demo at exactly 0.1× animation speed, run\n`npm run test:slow` while the site is running at `http://127.0.0.1:3041`.\nSet `GLIMM_URL` to use another form-demo URL. This slows the animation clock,\nincluding shader motion, and checks the expected ~13.2-second duration, monotonic\nmask movement, cleanup, and browser errors. Captured frames and a JSON report are\nwritten to a temporary directory printed by the command.\n\n\nUse `BROWSER=webkit npm run test:browser` or\n`BROWSER=firefox npm run test:browser` for additional engines. Install their test\nbinaries with `npx playwright-core install webkit firefox` first. Firefox's\nscreenshot implementation omits active View Transitions ([Mozilla bug 2008417](https://bugzilla.mozilla.org/show_bug.cgi?id=2008417)),\nso its suite checks live mask styles and lifecycle behavior; native-window visual\ninspection is required for its composited boundary. Chrome and WebKit assert\noutgoing/incoming pixel colors in all four directions.\n\nFor native Safari or an iOS simulator, run `npm run test:native` and open\n`http://127.0.0.1:3043/?client=safari` (use `client=ios` on the simulator).\nThe page runs manually released Suspense content, replacement transitions,\ncancellation, and a slow visual sweep, then saves its reports in the printed\ntemporary directory. The visual case reports completion/cleanup; inspect the\nactual browser window for rendering. Native Safari automation need not be enabled.\n\nFor a production integration check against the npm tarball in an isolated Next.js\napp, follow the repository’s [packaged fixture instructions](tests/next-app/README.md). This\nchecks the installed public entry points and actual server-route navigation,\nincluding slow responses, rapid navigation, history, anchors, and cancellation.\n","readmeFilename":"README.md","homepage":"https://glimm.dev","repository":{"type":"git","url":"git+https://github.com/nomanjack/glimm.git","directory":"packages/glimm"},"bugs":{"url":"https://github.com/nomanjack/glimm/issues"}}