@lpdsgn/astro-themes 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +26 -6
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
|
|
6
6
|
Perfect dark mode in Astro with no flash. An Astro integration that mirrors the behavior of [next-themes](https://github.com/pacocoursey/next-themes).
|
|
7
7
|
|
|
8
|
+
Compatible with **Astro v5** and **Astro v6**.
|
|
9
|
+
|
|
8
10
|
## Features
|
|
9
11
|
|
|
10
12
|
- ✅ **Perfect dark mode in 2 lines of code**
|
|
@@ -72,15 +74,33 @@ By default, `@lpdsgn/astro-themes` sets `data-theme` on the `<html>` element:
|
|
|
72
74
|
|
|
73
75
|
### TailwindCSS
|
|
74
76
|
|
|
75
|
-
|
|
77
|
+
If you use Tailwind's `dark:` variant, you need to tell Tailwind how to detect the active theme.
|
|
78
|
+
|
|
79
|
+
**With the default `data-theme` attribute:**
|
|
80
|
+
|
|
81
|
+
Tailwind v4:
|
|
82
|
+
|
|
83
|
+
```css frame="code" title="src/styles/global.css" ins={3}
|
|
84
|
+
@import 'tailwindcss';
|
|
85
|
+
|
|
86
|
+
@custom-variant dark (&:where([data-theme="dark"], [data-theme="dark"] *));
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Tailwind v3:
|
|
90
|
+
|
|
91
|
+
```js frame="code" title="tailwind.config.js" ins={2-4}
|
|
92
|
+
module.exports = {
|
|
93
|
+
darkMode: ['selector', '[data-theme="dark"]'],
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**With `attribute="class"`:**
|
|
76
98
|
|
|
77
99
|
```astro
|
|
78
100
|
<ThemeProvider attribute="class" />
|
|
79
101
|
```
|
|
80
102
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
**Tailwind v4:**
|
|
103
|
+
Tailwind v4:
|
|
84
104
|
|
|
85
105
|
```css frame="code" title="src/styles/global.css" ins={3}
|
|
86
106
|
@import 'tailwindcss';
|
|
@@ -88,7 +108,7 @@ Then configure Tailwind:
|
|
|
88
108
|
@custom-variant dark (&:is(.dark *));
|
|
89
109
|
```
|
|
90
110
|
|
|
91
|
-
|
|
111
|
+
Tailwind v3:
|
|
92
112
|
|
|
93
113
|
```js frame="code" title="tailwind.config.js" ins={2}
|
|
94
114
|
module.exports = {
|
|
@@ -96,7 +116,7 @@ module.exports = {
|
|
|
96
116
|
}
|
|
97
117
|
```
|
|
98
118
|
|
|
99
|
-
|
|
119
|
+
Then use dark-mode classes:
|
|
100
120
|
|
|
101
121
|
```html
|
|
102
122
|
<h1 class="text-black dark:text-white">Hello</h1>
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{defineIntegration as h}from"astro-integration-kit";import{z as n}from"astro/zod";var m=n.object({devToolbar:n.boolean().default(!0)}).default({}),i=h({name:"astro-themes",optionsSchema:m,setup({options:t}){return{hooks:{"astro:config:setup":({logger:e,addDevToolbarApp:r,command:s})=>{e.info("astro-themes initialized"),t.devToolbar&&s==="dev"&&(r({id:"astro-themes-toolbar",name:"Theme Switcher",icon:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>',entrypoint:"@lpdsgn/astro-themes/toolbar"}),e.debug("Dev Toolbar App registered"))},"astro:config:done":({injectTypes:e})=>{e({filename:"types.d.ts",content:`declare global {
|
|
1
|
+
import{defineIntegration as h}from"astro-integration-kit";import{z as n}from"astro/zod";var m=n.object({devToolbar:n.boolean().default(!0)}).default({devToolbar:!0}),i=h({name:"astro-themes",optionsSchema:m,setup({options:t}){return{hooks:{"astro:config:setup":({logger:e,addDevToolbarApp:r,command:s})=>{e.info("astro-themes initialized"),t.devToolbar&&s==="dev"&&(r({id:"astro-themes-toolbar",name:"Theme Switcher",icon:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M12 2v2"/><path d="M12 20v2"/><path d="m4.93 4.93 1.41 1.41"/><path d="m17.66 17.66 1.41 1.41"/><path d="M2 12h2"/><path d="M20 12h2"/><path d="m6.34 17.66-1.41 1.41"/><path d="m19.07 4.93-1.41 1.41"/></svg>',entrypoint:"@lpdsgn/astro-themes/toolbar"}),e.debug("Dev Toolbar App registered"))},"astro:config:done":({injectTypes:e})=>{e({filename:"types.d.ts",content:`declare global {
|
|
2
2
|
interface Window {
|
|
3
3
|
__ASTRO_THEMES__?: {
|
|
4
4
|
theme: string;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/integration.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["import { defineIntegration } from \"astro-integration-kit\";\nimport { z } from \"astro/zod\";\nimport type { AstroThemesConfig, ThemeProviderProps } from \"./types.js\";\n\n// Options schema for the integration\nconst optionsSchema = z\n\t.object({\n\t\t/**\n\t\t * Enable the Dev Toolbar App for theme switching during development\n\t\t * @default true\n\t\t */\n\t\tdevToolbar: z.boolean().default(true),\n\t})\n\t.default({});\n\nexport const integration = defineIntegration({\n\tname: \"astro-themes\",\n\toptionsSchema,\n\tsetup({ options }) {\n\t\treturn {\n\t\t\thooks: {\n\t\t\t\t\"astro:config:setup\": ({\n\t\t\t\t\tlogger,\n\t\t\t\t\taddDevToolbarApp,\n\t\t\t\t\tcommand,\n\t\t\t\t}) => {\n\t\t\t\t\tlogger.info(\"astro-themes initialized\");\n\n\t\t\t\t\t// Add Dev Toolbar App in dev mode\n\t\t\t\t\tif (options.devToolbar && command === \"dev\") {\n\t\t\t\t\t\taddDevToolbarApp({\n\t\t\t\t\t\t\tid: \"astro-themes-toolbar\",\n\t\t\t\t\t\t\tname: \"Theme Switcher\",\n\t\t\t\t\t\t\ticon: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2\"/><path d=\"M12 20v2\"/><path d=\"m4.93 4.93 1.41 1.41\"/><path d=\"m17.66 17.66 1.41 1.41\"/><path d=\"M2 12h2\"/><path d=\"M20 12h2\"/><path d=\"m6.34 17.66-1.41 1.41\"/><path d=\"m19.07 4.93-1.41 1.41\"/></svg>`,\n\t\t\t\t\t\t\tentrypoint: \"@lpdsgn/astro-themes/toolbar\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\tlogger.debug(\"Dev Toolbar App registered\");\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"astro:config:done\": ({ injectTypes }) => {\n\t\t\t\t\t// Inject global types for window.__ASTRO_THEMES__\n\t\t\t\t\tinjectTypes({\n\t\t\t\t\t\tfilename: \"types.d.ts\",\n\t\t\t\t\t\tcontent: `declare global {\n interface Window {\n __ASTRO_THEMES__?: {\n theme: string;\n resolvedTheme: string;\n systemTheme: \"dark\" | \"light\";\n forcedTheme?: string;\n themes: string[];\n setTheme: (theme: string | ((prevTheme: string) => string)) => void;\n };\n }\n}\nexport {};`,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n});\n\nexport type { AstroThemesConfig, ThemeProviderProps };\n","/**\n * Client-side helpers for interacting with the theme\n * These are meant to be used in client-side scripts\n */\n\nimport type { ThemeState } from \"./types.js\";\n\ndeclare global {\n\tinterface Window {\n\t\t__ASTRO_THEMES__?: ThemeState;\n\t}\n}\n\n/**\n * Get the current theme state\n * Returns undefined if ThemeProvider is not mounted\n */\nexport function getTheme(): ThemeState | undefined {\n\tif (typeof window === \"undefined\") return undefined;\n\treturn window.__ASTRO_THEMES__;\n}\n\n/**\n * Set the theme\n * @param theme - Theme name or function that receives current theme and returns new theme\n */\nexport function setTheme(theme: string | ((prevTheme: string) => string)): void {\n\tconst state = getTheme();\n\tif (state) {\n\t\tstate.setTheme(theme);\n\t}\n}\n\n/**\n * Get the resolved theme (system theme resolved to actual value)\n */\nexport function getResolvedTheme(): string | undefined {\n\treturn getTheme()?.resolvedTheme;\n}\n\n/**\n * Get the system theme preference\n */\nexport function getSystemTheme(): \"dark\" | \"light\" | undefined {\n\treturn getTheme()?.systemTheme;\n}\n\n/**\n * Check if theme is forced for the current page\n */\nexport function isForcedTheme(): boolean {\n\treturn !!getTheme()?.forcedTheme;\n}\n\n/**\n * Get the list of available themes\n */\nexport function getThemes(): string[] {\n\treturn getTheme()?.themes ?? [];\n}\n\n/**\n * Subscribe to theme changes\n * @param callback - Function called when theme changes\n * @returns Cleanup function to unsubscribe\n */\nexport function onThemeChange(\n\tcallback: (detail: { theme: string; resolvedTheme: string }) => void\n): () => void {\n\tif (typeof window === \"undefined\") return () => {};\n\n\tconst handler = (e: CustomEvent<{ theme: string; resolvedTheme: string }>) => {\n\t\tcallback(e.detail);\n\t};\n\n\twindow.addEventListener(\"astro-themes:change\", handler as EventListener);\n\n\treturn () => {\n\t\twindow.removeEventListener(\"astro-themes:change\", handler as EventListener);\n\t};\n}\n\n/**\n * Toggle between light and dark themes\n * If current theme is neither light nor dark, switches to light\n */\nexport function toggleTheme(): void {\n\tconst state = getTheme();\n\tif (!state) return;\n\n\tconst resolved = state.resolvedTheme;\n\tstate.setTheme(resolved === \"light\" ? \"dark\" : \"light\");\n}\n","// Main integration export\nimport { integration } from \"./integration.js\";\n\nexport default integration;\n\n// Re-export integration\nexport { integration };\n\n// Re-export types\nexport type {\n\tAttribute,\n\tValueObject,\n\tScriptProps,\n\tThemeProviderProps,\n\tThemeState,\n\tAstroThemesConfig,\n} from \"./types.js\";\n\n// Re-export client helpers\nexport {\n\tgetTheme,\n\tsetTheme,\n\tgetResolvedTheme,\n\tgetSystemTheme,\n\tisForcedTheme,\n\tgetThemes,\n\tonThemeChange,\n\ttoggleTheme,\n} from \"./client.js\";\n"],"mappings":"AAAA,OAAS,qBAAAA,MAAyB,wBAClC,OAAS,KAAAC,MAAS,YAIlB,IAAMC,EAAgBD,EACpB,OAAO,CAKP,WAAYA,EAAE,QAAQ,EAAE,QAAQ,EAAI,CACrC,CAAC,EACA,QAAQ,
|
|
1
|
+
{"version":3,"sources":["../src/integration.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["import { defineIntegration } from \"astro-integration-kit\";\nimport { z } from \"astro/zod\";\nimport type { AstroThemesConfig, ThemeProviderProps } from \"./types.js\";\n\n// Options schema for the integration\nconst optionsSchema = z\n\t.object({\n\t\t/**\n\t\t * Enable the Dev Toolbar App for theme switching during development\n\t\t * @default true\n\t\t */\n\t\tdevToolbar: z.boolean().default(true),\n\t})\n\t.default({ devToolbar: true });\n\nexport const integration = defineIntegration({\n\tname: \"astro-themes\",\n\toptionsSchema,\n\tsetup({ options }) {\n\t\treturn {\n\t\t\thooks: {\n\t\t\t\t\"astro:config:setup\": ({\n\t\t\t\t\tlogger,\n\t\t\t\t\taddDevToolbarApp,\n\t\t\t\t\tcommand,\n\t\t\t\t}) => {\n\t\t\t\t\tlogger.info(\"astro-themes initialized\");\n\n\t\t\t\t\t// Add Dev Toolbar App in dev mode\n\t\t\t\t\tif (options.devToolbar && command === \"dev\") {\n\t\t\t\t\t\taddDevToolbarApp({\n\t\t\t\t\t\t\tid: \"astro-themes-toolbar\",\n\t\t\t\t\t\t\tname: \"Theme Switcher\",\n\t\t\t\t\t\t\ticon: `<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"12\" cy=\"12\" r=\"4\"/><path d=\"M12 2v2\"/><path d=\"M12 20v2\"/><path d=\"m4.93 4.93 1.41 1.41\"/><path d=\"m17.66 17.66 1.41 1.41\"/><path d=\"M2 12h2\"/><path d=\"M20 12h2\"/><path d=\"m6.34 17.66-1.41 1.41\"/><path d=\"m19.07 4.93-1.41 1.41\"/></svg>`,\n\t\t\t\t\t\t\tentrypoint: \"@lpdsgn/astro-themes/toolbar\",\n\t\t\t\t\t\t});\n\t\t\t\t\t\tlogger.debug(\"Dev Toolbar App registered\");\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t\"astro:config:done\": ({ injectTypes }) => {\n\t\t\t\t\t// Inject global types for window.__ASTRO_THEMES__\n\t\t\t\t\tinjectTypes({\n\t\t\t\t\t\tfilename: \"types.d.ts\",\n\t\t\t\t\t\tcontent: `declare global {\n interface Window {\n __ASTRO_THEMES__?: {\n theme: string;\n resolvedTheme: string;\n systemTheme: \"dark\" | \"light\";\n forcedTheme?: string;\n themes: string[];\n setTheme: (theme: string | ((prevTheme: string) => string)) => void;\n };\n }\n}\nexport {};`,\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t},\n});\n\nexport type { AstroThemesConfig, ThemeProviderProps };\n","/**\n * Client-side helpers for interacting with the theme\n * These are meant to be used in client-side scripts\n */\n\nimport type { ThemeState } from \"./types.js\";\n\ndeclare global {\n\tinterface Window {\n\t\t__ASTRO_THEMES__?: ThemeState;\n\t}\n}\n\n/**\n * Get the current theme state\n * Returns undefined if ThemeProvider is not mounted\n */\nexport function getTheme(): ThemeState | undefined {\n\tif (typeof window === \"undefined\") return undefined;\n\treturn window.__ASTRO_THEMES__;\n}\n\n/**\n * Set the theme\n * @param theme - Theme name or function that receives current theme and returns new theme\n */\nexport function setTheme(theme: string | ((prevTheme: string) => string)): void {\n\tconst state = getTheme();\n\tif (state) {\n\t\tstate.setTheme(theme);\n\t}\n}\n\n/**\n * Get the resolved theme (system theme resolved to actual value)\n */\nexport function getResolvedTheme(): string | undefined {\n\treturn getTheme()?.resolvedTheme;\n}\n\n/**\n * Get the system theme preference\n */\nexport function getSystemTheme(): \"dark\" | \"light\" | undefined {\n\treturn getTheme()?.systemTheme;\n}\n\n/**\n * Check if theme is forced for the current page\n */\nexport function isForcedTheme(): boolean {\n\treturn !!getTheme()?.forcedTheme;\n}\n\n/**\n * Get the list of available themes\n */\nexport function getThemes(): string[] {\n\treturn getTheme()?.themes ?? [];\n}\n\n/**\n * Subscribe to theme changes\n * @param callback - Function called when theme changes\n * @returns Cleanup function to unsubscribe\n */\nexport function onThemeChange(\n\tcallback: (detail: { theme: string; resolvedTheme: string }) => void\n): () => void {\n\tif (typeof window === \"undefined\") return () => {};\n\n\tconst handler = (e: CustomEvent<{ theme: string; resolvedTheme: string }>) => {\n\t\tcallback(e.detail);\n\t};\n\n\twindow.addEventListener(\"astro-themes:change\", handler as EventListener);\n\n\treturn () => {\n\t\twindow.removeEventListener(\"astro-themes:change\", handler as EventListener);\n\t};\n}\n\n/**\n * Toggle between light and dark themes\n * If current theme is neither light nor dark, switches to light\n */\nexport function toggleTheme(): void {\n\tconst state = getTheme();\n\tif (!state) return;\n\n\tconst resolved = state.resolvedTheme;\n\tstate.setTheme(resolved === \"light\" ? \"dark\" : \"light\");\n}\n","// Main integration export\nimport { integration } from \"./integration.js\";\n\nexport default integration;\n\n// Re-export integration\nexport { integration };\n\n// Re-export types\nexport type {\n\tAttribute,\n\tValueObject,\n\tScriptProps,\n\tThemeProviderProps,\n\tThemeState,\n\tAstroThemesConfig,\n} from \"./types.js\";\n\n// Re-export client helpers\nexport {\n\tgetTheme,\n\tsetTheme,\n\tgetResolvedTheme,\n\tgetSystemTheme,\n\tisForcedTheme,\n\tgetThemes,\n\tonThemeChange,\n\ttoggleTheme,\n} from \"./client.js\";\n"],"mappings":"AAAA,OAAS,qBAAAA,MAAyB,wBAClC,OAAS,KAAAC,MAAS,YAIlB,IAAMC,EAAgBD,EACpB,OAAO,CAKP,WAAYA,EAAE,QAAQ,EAAE,QAAQ,EAAI,CACrC,CAAC,EACA,QAAQ,CAAE,WAAY,EAAK,CAAC,EAEjBE,EAAcH,EAAkB,CAC5C,KAAM,eACN,cAAAE,EACA,MAAM,CAAE,QAAAE,CAAQ,EAAG,CAClB,MAAO,CACN,MAAO,CACN,qBAAsB,CAAC,CACtB,OAAAC,EACA,iBAAAC,EACA,QAAAC,CACD,IAAM,CACLF,EAAO,KAAK,0BAA0B,EAGlCD,EAAQ,YAAcG,IAAY,QACrCD,EAAiB,CAChB,GAAI,uBACJ,KAAM,iBACN,KAAM,+aACN,WAAY,8BACb,CAAC,EACDD,EAAO,MAAM,4BAA4B,EAE3C,EACA,oBAAqB,CAAC,CAAE,YAAAG,CAAY,IAAM,CAEzCA,EAAY,CACX,SAAU,aACV,QAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,WAaV,CAAC,CACF,CACD,CACD,CACD,CACD,CAAC,EC5CM,SAASC,GAAmC,CAClD,GAAI,SAAO,OAAW,KACtB,OAAO,OAAO,gBACf,CAMO,SAASC,EAASC,EAAuD,CAC/E,IAAMC,EAAQH,EAAS,EACnBG,GACHA,EAAM,SAASD,CAAK,CAEtB,CAKO,SAASE,GAAuC,CACtD,OAAOJ,EAAS,GAAG,aACpB,CAKO,SAASK,GAA+C,CAC9D,OAAOL,EAAS,GAAG,WACpB,CAKO,SAASM,GAAyB,CACxC,MAAO,CAAC,CAACN,EAAS,GAAG,WACtB,CAKO,SAASO,GAAsB,CACrC,OAAOP,EAAS,GAAG,QAAU,CAAC,CAC/B,CAOO,SAASQ,EACfC,EACa,CACb,GAAI,OAAO,OAAW,IAAa,MAAO,IAAM,CAAC,EAEjD,IAAMC,EAAWC,GAA6D,CAC7EF,EAASE,EAAE,MAAM,CAClB,EAEA,cAAO,iBAAiB,sBAAuBD,CAAwB,EAEhE,IAAM,CACZ,OAAO,oBAAoB,sBAAuBA,CAAwB,CAC3E,CACD,CAMO,SAASE,GAAoB,CACnC,IAAMT,EAAQH,EAAS,EACvB,GAAI,CAACG,EAAO,OAEZ,IAAMU,EAAWV,EAAM,cACvBA,EAAM,SAASU,IAAa,QAAU,OAAS,OAAO,CACvD,CCzFA,IAAOC,EAAQC","names":["defineIntegration","z","optionsSchema","integration","options","logger","addDevToolbarApp","command","injectTypes","getTheme","setTheme","theme","state","getResolvedTheme","getSystemTheme","isForcedTheme","getThemes","onThemeChange","callback","handler","e","toggleTheme","resolved","index_default","integration"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lpdsgn/astro-themes",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Perfect dark mode in Astro with no flash. System preference, multiple themes, and sync across tabs.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -49,10 +49,10 @@
|
|
|
49
49
|
"homepage": "https://github.com/LPdsgn/astro-themes#readme",
|
|
50
50
|
"license": "MIT",
|
|
51
51
|
"peerDependencies": {
|
|
52
|
-
"astro": "^5.1.3"
|
|
52
|
+
"astro": "^5.1.3 || ^6.0.0"
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
55
|
-
"astro-integration-kit": "0.
|
|
55
|
+
"astro-integration-kit": "0.20.0",
|
|
56
56
|
"zod": "^4.3.5"
|
|
57
57
|
},
|
|
58
58
|
"devDependencies": {
|