{"_id":"@brustack/alpine-theme-transitions","_rev":"4-8555bd50c3420d666b6497038d8e9056","name":"@brustack/alpine-theme-transitions","dist-tags":{"latest":"1.0.3"},"versions":{"1.0.0":{"name":"@brustack/alpine-theme-transitions","version":"1.0.0","keywords":["alpine","alpinejs","alpine-plugin","theme","theme-toggle","theme-switcher","dark-mode","dark-theme","view-transitions","view-transitions-api","spread","fade","transition","animation"],"author":{"name":"Bruno Neckel"},"license":"MIT","_id":"@brustack/alpine-theme-transitions@1.0.0","maintainers":[{"name":"bncodes","email":"neckel.bw+bncodes@gmail.com"},{"name":"brunoneckel","email":"neckel.bw@gmail.com"}],"homepage":"https://github.com/brustack/theme-transitions#readme","bugs":{"url":"https://github.com/brustack/theme-transitions/issues"},"dist":{"shasum":"03846b978ce26bbfd85d0d0ccb59d4fb2e4af0be","tarball":"https://registry.npmjs.org/@brustack/alpine-theme-transitions/-/alpine-theme-transitions-1.0.0.tgz","fileCount":7,"integrity":"sha512-yLxcxZNBp4p5NcKKB8J/2RMQHFWCzkG5VU3TytKSprwzOOXxCczb4tlnhegToQ7j5Gv21seMGtBsl4Umk3YXdQ==","signatures":[{"sig":"MEUCIG1Bta/jVy3Y3PNFmVT3G0Kic3ft14VRp2KK5SPAFbcbAiEAuIwP92HHqn2IA0/9fP3VLluPFKdDF3A2cubeo3CZXDM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":17737},"main":"./dist/index.mjs","type":"module","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"}},"gitHead":"363701387d59fef9dd692297ecef84c90f442f84","scripts":{"build":"unbuild && node scripts/build-cdn.mjs","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"brunoneckel","email":"neckel.bw@gmail.com"},"repository":{"url":"git+https://github.com/brustack/theme-transitions.git","type":"git","directory":"packages/alpine"},"_npmVersion":"11.16.0","description":"Alpine.js plugin for animated dark/light theme transitions using the View Transitions API","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@brustack/theme-transitions-core":"^2.2.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.1","alpinejs":"^3.15.12","happy-dom":"^20.11.1","@types/alpinejs":"^3.13.11"},"peerDependencies":{"alpinejs":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/alpine-theme-transitions_1.0.0_1786203321128_0.02085561503107014","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@brustack/alpine-theme-transitions","version":"1.0.1","keywords":["alpine","alpinejs","alpine-plugin","theme","theme-toggle","theme-switcher","dark-mode","dark-theme","view-transitions","view-transitions-api","spread","fade","transition","animation","custom-themes","cdn","zero-build","laravel","blade","rails","django"],"author":{"name":"Bruno Neckel"},"license":"MIT","_id":"@brustack/alpine-theme-transitions@1.0.1","maintainers":[{"name":"bncodes","email":"neckel.bw+bncodes@gmail.com"},{"name":"brunoneckel","email":"neckel.bw@gmail.com"}],"homepage":"https://github.com/brustack/theme-transitions#readme","bugs":{"url":"https://github.com/brustack/theme-transitions/issues"},"dist":{"shasum":"86cdbcac107746d4cb68bfdcc5b6bdbbbeb982f7","tarball":"https://registry.npmjs.org/@brustack/alpine-theme-transitions/-/alpine-theme-transitions-1.0.1.tgz","fileCount":7,"integrity":"sha512-XPOneaiMNFJvyjTGzjdyogEd2d0a1am9d9N64s856imQJGbQOf50PldbhHkoN7DC8Qaj/Rz9oNYbsYXuplNtKw==","signatures":[{"sig":"MEQCIBcOv6QX4GGRjeq7ZFGWVAmp8Y6KXwcroRfTrC7yJu72AiAE40PCD6mTWx0hkYNu1ywzIogYLnjqWTXytAHluvOOpg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@brustack%2falpine-theme-transitions@1.0.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":17813},"main":"./dist/index.mjs","type":"module","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"}},"gitHead":"2bc2a22f2df2e0e2bfdc95948d058b063b65da06","scripts":{"build":"unbuild && node scripts/build-cdn.mjs","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:549f19de-a66f-48d0-9b2c-ad9c4bb1e938"}},"repository":{"url":"git+https://github.com/brustack/theme-transitions.git","type":"git","directory":"packages/alpine"},"_npmVersion":"11.16.0","description":"Alpine.js plugin for animated theme transitions using the View Transitions API","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@brustack/theme-transitions-core":"^2.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.1","alpinejs":"^3.15.12","happy-dom":"^20.11.1","@types/alpinejs":"^3.13.11"},"peerDependencies":{"alpinejs":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/alpine-theme-transitions_1.0.1_1786252833274_0.20521222320539545","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@brustack/alpine-theme-transitions","version":"1.0.2","keywords":["alpine","alpinejs","alpine-plugin","theme","theme-toggle","theme-switcher","dark-mode","dark-theme","view-transitions","view-transitions-api","spread","fade","transition","animation","custom-themes","cdn","zero-build","laravel","blade","rails","django"],"author":{"name":"Bruno Neckel"},"license":"MIT","_id":"@brustack/alpine-theme-transitions@1.0.2","maintainers":[{"name":"bncodes","email":"neckel.bw+bncodes@gmail.com"},{"name":"brunoneckel","email":"neckel.bw@gmail.com"}],"homepage":"https://github.com/brustack/theme-transitions#readme","bugs":{"url":"https://github.com/brustack/theme-transitions/issues"},"dist":{"shasum":"f385d1dba6f5017bb61a78ee375c37f0dbb4d62b","tarball":"https://registry.npmjs.org/@brustack/alpine-theme-transitions/-/alpine-theme-transitions-1.0.2.tgz","fileCount":7,"integrity":"sha512-3IYXuJbIwe3grb3fk8tH5GOsW9M5yWiYoBInaUNCBIgS9hnRrGObjNZH9irs1UIPKmlPUEgFS/HnbldwgqM+iA==","signatures":[{"sig":"MEUCIQC5YwhYTMS9oLoiYpCgDOhfLWwIBfblVg6DERTlKgVK5gIgVSgyD68/PMg2m+QASxLlCbBHddVG6Lk2Ze/V4apAm60=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@brustack%2falpine-theme-transitions@1.0.2","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":18506},"main":"./dist/index.mjs","type":"module","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"}},"gitHead":"4e1a122fcbdd3e99860a2081ba60873fbd15d0d2","scripts":{"build":"unbuild && node scripts/build-cdn.mjs","typecheck":"tsc --noEmit","prepublishOnly":"npm run build"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:549f19de-a66f-48d0-9b2c-ad9c4bb1e938"}},"repository":{"url":"git+https://github.com/brustack/theme-transitions.git","type":"git","directory":"packages/alpine"},"_npmVersion":"11.16.0","description":"Alpine.js plugin for animated theme transitions using the View Transitions API","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@brustack/theme-transitions-core":"^3.0.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.1","alpinejs":"^3.15.12","happy-dom":"^20.11.1","@types/alpinejs":"^3.13.11"},"peerDependencies":{"alpinejs":"^3.0.0"},"_npmOperationalInternal":{"tmp":"tmp/alpine-theme-transitions_1.0.2_1786264570864_0.9854868646852348","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"@brustack/alpine-theme-transitions","version":"1.0.3","description":"Alpine.js plugin for animated theme transitions using the View Transitions API","author":{"name":"Bruno Neckel"},"license":"MIT","type":"module","sideEffects":false,"main":"./dist/index.mjs","types":"./dist/index.d.mts","exports":{".":{"types":"./dist/index.d.mts","import":"./dist/index.mjs"}},"repository":{"type":"git","url":"git+https://github.com/brustack/theme-transitions.git","directory":"packages/alpine"},"publishConfig":{"access":"public"},"peerDependencies":{"alpinejs":"^3.0.0"},"dependencies":{"@brustack/theme-transitions-core":"^3.1.0"},"devDependencies":{"@types/alpinejs":"^3.13.11","alpinejs":"^3.15.12","esbuild":"^0.28.1","happy-dom":"^20.11.1"},"scripts":{"build":"unbuild && node scripts/build-cdn.mjs","prepublishOnly":"npm run build","typecheck":"tsc --noEmit"},"keywords":["alpine","alpinejs","alpine-plugin","theme","theme-toggle","theme-switcher","dark-mode","dark-theme","view-transitions","view-transitions-api","spread","fade","transition","animation","custom-themes","cdn","zero-build","laravel","blade","rails","django"],"gitHead":"4845a776a8ab12fe65a58024ee8fbb6ba23d75fd","_id":"@brustack/alpine-theme-transitions@1.0.3","bugs":{"url":"https://github.com/brustack/theme-transitions/issues"},"homepage":"https://github.com/brustack/theme-transitions#readme","_nodeVersion":"24.19.0","_npmVersion":"11.17.0","dist":{"integrity":"sha512-V57iaHsHwBsIjGZjGu1A142jj2f6J9Zjp0HDYyzaBfE32pWi1L5xDlGsQ1A9IyWK/jj3U+PYh2Dw701uZ3U+yw==","shasum":"e5d85067b7b4015dcd8f940ec5059c8450350af8","tarball":"https://registry.npmjs.org/@brustack/alpine-theme-transitions/-/alpine-theme-transitions-1.0.3.tgz","fileCount":7,"unpackedSize":18087,"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@brustack%2falpine-theme-transitions@1.0.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIACSVW1AKDssFd+yDNcuhzrsNN56J8zcJBZcwIoENSPlAiEApMh060LNYOIOB7YsNYdalzhllDZW325se2voMtqRHIE="}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:549f19de-a66f-48d0-9b2c-ad9c4bb1e938"}},"directories":{},"maintainers":[{"name":"bncodes","email":"neckel.bw+bncodes@gmail.com"},{"name":"brunoneckel","email":"neckel.bw@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/alpine-theme-transitions_1.0.3_1786564424641_0.4842830334667787"},"_hasShrinkwrap":false}},"time":{"created":"2026-08-08T15:35:20.990Z","modified":"2026-08-12T19:53:45.159Z","1.0.0":"2026-08-08T15:35:21.255Z","1.0.1":"2026-08-09T05:20:33.404Z","1.0.2":"2026-08-09T08:36:11.009Z","1.0.3":"2026-08-12T19:53:44.793Z"},"bugs":{"url":"https://github.com/brustack/theme-transitions/issues"},"author":{"name":"Bruno Neckel"},"license":"MIT","homepage":"https://github.com/brustack/theme-transitions#readme","keywords":["alpine","alpinejs","alpine-plugin","theme","theme-toggle","theme-switcher","dark-mode","dark-theme","view-transitions","view-transitions-api","spread","fade","transition","animation","custom-themes","cdn","zero-build","laravel","blade","rails","django"],"repository":{"type":"git","url":"git+https://github.com/brustack/theme-transitions.git","directory":"packages/alpine"},"description":"Alpine.js plugin for animated theme transitions using the View Transitions API","maintainers":[{"name":"bncodes","email":"neckel.bw+bncodes@gmail.com"},{"name":"brunoneckel","email":"neckel.bw@gmail.com"}],"readme":"# alpine-theme-transitions\n\n[![made by brustack](https://img.shields.io/badge/MADE%20BY%20brustack-000000.svg?style=for-the-badge&labelColor=000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMjYuNzcgMjI2Ljc3Ij48cG9seWdvbiBmaWxsPSIjRjRGMkVEIiBwb2ludHM9IjE1My43MyA4My4zOSAxNTMuNzMgMTUzLjczIDgzLjM5IDE1My43MyA4My4zOSAyMTMuNzMgMjEzLjczIDIxMy43MyAyMTMuNzMgODMuMzkgMTUzLjczIDgzLjM5Ii8%2BPHJlY3QgZmlsbD0iI0Y0RjJFRCIgeD0iODMuMzkiIHk9IjEzLjA0IiB3aWR0aD0iNjAiIGhlaWdodD0iNjAiLz48cmVjdCBmaWxsPSIjRjRGMkVEIiB4PSIxMy4wNCIgeT0iODMuMzkiIHdpZHRoPSI2MCIgaGVpZ2h0PSI2MCIvPjxyZWN0IGZpbGw9IiNGNEYyRUQiIHg9IjgzLjM5IiB5PSI4My4zOSIgd2lkdGg9IjYwIiBoZWlnaHQ9IjYwIi8%2BPC9zdmc%2BCg%3D%3D)](https://github.com/brustack)\n[![npm version](https://img.shields.io/npm/v/@brustack/alpine-theme-transitions.svg?style=for-the-badge&labelColor=000000)](https://www.npmjs.com/package/@brustack/alpine-theme-transitions)\n[![license](https://img.shields.io/npm/l/@brustack/alpine-theme-transitions.svg?style=for-the-badge&labelColor=000000)](https://github.com/brustack/theme-transitions/blob/main/packages/alpine/LICENSE)\n\nAlpine.js plugin for animated theme transitions using the View Transitions API.\n\n- ✅ Multiple effects to choose from\n- ✅ Zero flash of the wrong theme on load\n- ✅ Syncs automatically with OS `prefers-color-scheme`\n- ✅ Custom themes beyond light/dark\n- ✅ Origin auto-derived from the click event, bind `toggleTheme` straight to `@click`\n- ✅ Works with zero build step, drop in via CDN, or install via npm\n- ✅ No Context, no Provider, no store, just `x-data`\n\n<br>\n\n<p align=\"center\">\n  <img src=\"../../.github/assets/demo.gif\" alt=\"Demo: clicking anywhere on the page triggers an animated theme transition originating from the cursor\" />\n</p>\n\n<p align=\"center\">Check out the <a href=\"https://theme-transitions.brustack.dev\">Live Example</a> to try it for yourself.</p>\n\n## Install\n\n```sh\nnpm install @brustack/alpine-theme-transitions\n# or\npnpm add @brustack/alpine-theme-transitions\n# or\nyarn add @brustack/alpine-theme-transitions\n```\n\nNot using a bundler? No install needed, see the CDN usage below.\n\nPrefer to see it running first?\n\n```sh\ngit clone https://github.com/brustack/theme-transitions.git\ncd theme-transitions\nnpm run install:alpine-demo\nnpm run dev:alpine-demo\n```\n\n## Usage\n\n### CDN (zero-build)\n\n```html\n<head>\n  <script src=\"https://cdn.jsdelivr.net/npm/@brustack/theme-transitions-core/dist/theme-init.js\"></script>\n  <link rel=\"stylesheet\" href=\"https://cdn.jsdelivr.net/npm/@brustack/theme-transitions-core/style.css\">\n</head>\n<body>\n  <div x-data=\"themeTransition()\">\n    <button @click=\"toggleTheme\" x-text=\"theme\"></button>\n  </div>\n\n  <script defer src=\"https://cdn.jsdelivr.net/npm/@brustack/alpine-theme-transitions/dist/alpine-theme-transitions.iife.js\"></script>\n  <script defer src=\"https://cdn.jsdelivr.net/npm/alpinejs@3/dist/cdn.min.js\"></script>\n</body>\n```\n\nScript order matters: the plugin's `<script>` tag comes before Alpine core's own `<script>` tag, both `defer`, the plugin attaches its `alpine:init` listener before Alpine's CDN bundle fires that event and starts itself. No manual `Alpine.plugin(...)` call needed for CDN usage.\n\n### npm / bundler\n\n```js\nimport Alpine from 'alpinejs';\nimport themeTransition from '@brustack/alpine-theme-transitions';\nimport '@brustack/theme-transitions-core/style.css';\n\nAlpine.plugin(themeTransition);\nAlpine.start();\n```\n\n```html\n<div x-data=\"themeTransition()\">\n  <button @click=\"toggleTheme\" x-text=\"theme\"></button>\n</div>\n```\n\nBinding `toggleTheme` directly to `@click` works because it accepts the native `MouseEvent` and derives the spread effect's origin from the click position automatically. Options are passed through the markup (`x-data=\"themeTransition({...})\"`), not through JS setup, see Configuration below.\n\n## Styling\n\n`themeTransition` applies the current theme's name (`dark`, `light`, or a custom name, see Custom themes below) as a class on `<html>`. Style your palette off that class with any approach.\n\n### CSS variables\n\n```css\n:root {\n  --bg: #ffffff;\n  --text: #111111;\n}\n\nhtml.dark {\n  --bg: #0b0b10;\n  --text: #f4f2ed;\n}\n\nhtml.sepia {\n  --bg: #f4ecd8;\n  --text: #4b3621;\n}\n\nbody {\n  background: var(--bg);\n  color: var(--text);\n}\n```\n\n### Tailwind\n\nSet `darkMode: 'class'` in your Tailwind config (see Install above), then map your color tokens to the CSS variables above:\n\n```js\n// tailwind.config.js\nmodule.exports = {\n  darkMode: 'class',\n  theme: {\n    extend: {\n      colors: {\n        bg: 'var(--bg)',\n        text: 'var(--text)',\n      },\n    },\n  },\n};\n```\n\n## Configuration (optional)\n\n| Variant | `duration` | `easing` |\n|---|:---:|:---:|\n| `spread` | `'1s'` | ❌ |\n| `fade` (default) | `'400ms'` | `'ease'` |\n| `none` | ❌ | ❌ |\n\n```html\n<div x-data=\"themeTransition({ variant: 'spread', duration: '1s' })\">\n```\n\nThe first component to initialize on the page sets the shared default. Pass a `MouseEvent` (as shown in Usage) or an options object to `toggleTheme`/`setTheme` to override just that one call.\n\n### Custom themes\n\nRegister extra theme names beyond `light`/`dark`/`system` via `themes`:\n\n```html\n<div x-data=\"themeTransition({ themes: ['sepia', 'sunset'] })\">\n```\n\n`setTheme('sepia')` then applies a `sepia` class the same way `light`/`dark` do (see Styling above). The component's `themes` property always includes `['light', 'dark', 'system', ...your custom names]`, useful for building a theme switcher. `toggleTheme()` is unaffected, it always flips between `light` and `dark`.\n\n## API\n\n| | |\n|---|---|\n| `Alpine.plugin(themeTransition)` | Registers the `themeTransition` Alpine.data component |\n| `x-data=\"themeTransition(options?)\"` | Creates a component instance; first one on the page sets the shared default |\n| `theme` | Current resolved theme: `'light'`, `'dark'`, or a custom theme name |\n| `mode` | Current preference: `'light'`, `'dark'`, `'system'`, or a custom theme name |\n| `isAnimating` | `true` while a transition is running |\n| `themes` | All registered theme names: `['light', 'dark', 'system', ...custom]` |\n| `toggleTheme(eventOrOptions?)` | Switch between light and dark |\n| `setTheme(mode, eventOrOptions?)` | Set `light`, `dark`, `system`, or a custom theme name |\n\n## Notes\n\n- This package has no Alpine-specific storage. Persistence, system-preference sync, and all other state management come from `@brustack/theme-transitions-core`'s shared controller, the same singleton every other adapter in this project reads from, `themeTransition` is just a thin `x-data` reflection of it.\n- `@alpinejs/persist` is deliberately not a dependency. Its `$persist()` restores its own `localStorage` copy into the data object before `init()` runs, which would create a second, unsynchronized copy of state the core controller already owns via its own storage key.\n\n## Known issues\n\n- Chrome 150 has a regression where the `spread` effect's clip-path animation can render from the wrong position after the browser window moves between displays with different DPI/scaling. This is a Chrome bug, not something this package can work around. It's already fixed upstream and verified in Chrome Canary; the fix should reach the Stable channel in a future release. See [Chromium issue #535696703](https://issues.chromium.org/issues/535696703).\n","readmeFilename":"README.md"}