@cruxext/theme 0.0.5 → 0.0.7
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 +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +7 -7
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
10
|
<div align="center">
|
|
11
|
-
<img src="https://img.shields.io/badge/v-0.0.
|
|
11
|
+
<img src="https://img.shields.io/badge/v-0.0.7-black"/>
|
|
12
12
|
<a href="https://github.com/cruxext-org"><img src="https://img.shields.io/badge/🔥-@cruxext-black"/></a>
|
|
13
13
|
<br>
|
|
14
14
|
<img src="https://img.shields.io/github/issues/cruxext-org/theme?style=flat" alt="Github Repo Issues" />
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var store=require('@minejs/store'),signals=require('@minejs/signals')
|
|
1
|
+
'use strict';var store=require('@minejs/store'),signals=require('@minejs/signals');var i=class{constructor(e){this.config=e;let t=new store.Storage({type:"local"});this.store=store.createStore({state:{theme:e.default},persist:true,storage:t,storageKey:"app:theme"}),this.signal=this.store.state.theme;let a=t.get("app:theme:theme")||e.default;this.signal.set(a),this.applyTheme(a),signals.effect(()=>{let n=this.signal?.();n&&this.applyTheme(n),console.log(`[ThemeManager] Reactive effect applied theme: ${n}`);}),signals.effect(()=>{let n=window.matchMedia("(prefers-color-scheme: dark)"),h=g=>{t.get("app:theme:theme")||this.signal.set(g.matches?"dark":"light");};return n.addEventListener("change",h),()=>n.removeEventListener("change",h)});}getTheme(){return this.signal?.()??this.config.default??"light"}setTheme(e){if(!this.config.available.includes(e)){console.warn(`[ThemeManager] Unsupported theme: ${e}`);return}this.signal&&(this.signal.set(e),console.log(`[ThemeManager] Theme set to: ${e}`));}toggleTheme(){if(!this.signal)return;let e=this.signal(),t=this.config.available.find(r=>r!==e);t&&(this.signal.set(t),console.log(`[ThemeManager] Theme toggled to: ${t}`));}applyTheme(e){(document.documentElement||document.rootElement).setAttribute("data-theme",e),console.log(`[ThemeManager] Applied theme: ${e}`);}};var m,s=()=>m,E=o=>s().setTheme(o),x=()=>s().toggleTheme(),y=()=>s().getTheme();function C(o){return {name:"ThemeExtension",onBoot:e=>{o&&(e.cconfig.theme={...e.cconfig.theme,...o}),e.cconfig.theme||(e.cconfig.theme={default:"dark",available:["dark","light"]}),m=new i({default:e.cconfig.theme.default,available:e.cconfig.theme.available});}}}exports.ThemeManager=i;exports.createThemeExtension=C;exports.getCurrentTheme=y;exports.getThemeManager=s;exports.setTheme=E;exports.toggleTheme=x;//# sourceMappingURL=index.cjs.map
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mod/theme_manager.ts","../src/index.ts"],"names":["ThemeManager","config","storage","Storage","createStore","initialTheme","effect","currentTheme","mediaQuery","handleChange","e","themeName","nextTheme","t","themeManager","getThemeManager","setTheme","toggleTheme","getCurrentTheme","createThemeExtension","ctx"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/mod/theme_manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ThemeConfig } from \"../types\";\r\n import { createStore, Storage } from '@minejs/store';\r\n import { signal, effect } from '@minejs/signals';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class ThemeManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n public store: ReturnType<typeof createStore>;\r\n public signal: ReturnType<typeof signal<string>>;\r\n\r\n constructor(public config: ThemeConfig) {\r\n\r\n const storage = new Storage({ type: 'local' });\r\n\r\n this.store = createStore({\r\n state: {\r\n theme: config.default\r\n },\r\n persist: true,\r\n storage,\r\n storageKey: 'app:theme'\r\n });\r\n\r\n this.signal = this.store.state.theme;\r\n\r\n // Set initial theme on body\r\n const storedTheme = storage.get('app:theme:theme') as string | null;\r\n const initialTheme = storedTheme || config.default;\r\n this.signal.set(initialTheme);\r\n this.applyTheme(initialTheme);\r\n\r\n // Setup reactive effect: apply theme whenever signal changes\r\n effect(() => {\r\n const currentTheme = this.signal?.();\r\n if (currentTheme) {\r\n this.applyTheme(currentTheme);\r\n }\r\n\r\n console.log(`[ThemeManager] Reactive effect applied theme: ${currentTheme}`);\r\n });\r\n\r\n // Listen for system theme changes\r\n effect(() => {\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n\r\n const handleChange = (e: MediaQueryListEvent) => {\r\n if (!storage.get('app:theme:theme')) this.signal.set(e.matches ? 'dark' : 'light');\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n });\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n getTheme(): string {\r\n return this.signal?.() ?? this.config.default ?? 'light';\r\n }\r\n\r\n setTheme(themeName: string): void {\r\n if (!this.config.available.includes(themeName)) {\r\n console.warn(`[ThemeManager] Unsupported theme: ${themeName}`);\r\n return;\r\n }\r\n\r\n // Update signal directly - effect will handle DOM updates\r\n if (this.signal) {\r\n this.signal.set(themeName);\r\n console.log(`[ThemeManager] Theme set to: ${themeName}`);\r\n }\r\n }\r\n\r\n toggleTheme(): void {\r\n if (!this.signal) return;\r\n const currentTheme = this.signal();\r\n const nextTheme = this.config.available.find(t => t !== currentTheme);\r\n if (nextTheme) {\r\n this.signal.set(nextTheme);\r\n console.log(`[ThemeManager] Theme toggled to: ${nextTheme}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n private applyTheme(themeName: string): void {\r\n const htmlEl = document.documentElement || document.rootElement;\r\n htmlEl.setAttribute('data-theme', themeName);\r\n console.log(`[ThemeManager] Applied theme: ${themeName}`);\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientExtension, ExtensionContext } from \"@cruxjs/client\";\r\n import { ThemeConfig } from \"./types\";\r\n import { ThemeManager } from \"./mod/theme_manager\";\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n // Theme manager instance\r\n let themeManager : ThemeManager;\r\n\r\n // Exported theme functions\r\n export const getThemeManager = () => themeManager;\r\n export const setTheme = (themeName: string) => getThemeManager().setTheme(themeName);\r\n export const toggleTheme = () => getThemeManager().toggleTheme();\r\n export const getCurrentTheme = () => getThemeManager().getTheme();\r\n\r\n // Theme extension\r\n export function createThemeExtension(config?: ThemeConfig) : ClientExtension {\r\n return {\r\n name : 'ThemeExtension',\r\n\r\n onBoot: (ctx: ExtensionContext) => {\r\n // if config provided, merge into client config\r\n if (config) {\r\n ctx.cconfig.theme = {\r\n ...ctx.cconfig.theme,\r\n ...config\r\n };\r\n }\r\n\r\n // if no theme config provided, set default\r\n if (!ctx.cconfig.theme) {\r\n ctx.cconfig.theme = {\r\n default : 'dark',\r\n available : ['dark', 'light']\r\n };\r\n }\r\n\r\n // create theme manager instance\r\n themeManager = new ThemeManager({\r\n default : ctx.cconfig.theme!.default,\r\n available : ctx.cconfig.theme!.available\r\n });\r\n }\r\n };\r\n };\r\n\r\n // export\r\n export * from \"./types\";\r\n export { ThemeManager };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
|
1
|
+
{"version":3,"sources":["../src/mod/theme_manager.ts","../src/index.ts"],"names":["ThemeManager","config","storage","Storage","createStore","initialTheme","effect","currentTheme","mediaQuery","handleChange","e","themeName","nextTheme","t","themeManager","getThemeManager","setTheme","toggleTheme","getCurrentTheme","createThemeExtension","ctx"],"mappings":"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","file":"index.cjs","sourcesContent":["// src/mod/theme_manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ThemeConfig } from \"../types\";\r\n import { createStore, Storage } from '@minejs/store';\r\n import { signal, effect } from '@minejs/signals';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class ThemeManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n public store: ReturnType<typeof createStore>;\r\n public signal: ReturnType<typeof signal<string>>;\r\n\r\n constructor(public config: ThemeConfig) {\r\n\r\n const storage = new Storage({ type: 'local' });\r\n\r\n this.store = createStore({\r\n state: {\r\n theme: config.default\r\n },\r\n persist: true,\r\n storage,\r\n storageKey: 'app:theme'\r\n });\r\n\r\n this.signal = this.store.state.theme;\r\n\r\n // Set initial theme on body\r\n const storedTheme = storage.get('app:theme:theme') as string | null;\r\n const initialTheme = storedTheme || config.default;\r\n this.signal.set(initialTheme);\r\n this.applyTheme(initialTheme);\r\n\r\n // Setup reactive effect: apply theme whenever signal changes\r\n effect(() => {\r\n const currentTheme = this.signal?.();\r\n if (currentTheme) {\r\n this.applyTheme(currentTheme);\r\n }\r\n\r\n console.log(`[ThemeManager] Reactive effect applied theme: ${currentTheme}`);\r\n });\r\n\r\n // Listen for system theme changes\r\n effect(() => {\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n\r\n const handleChange = (e: MediaQueryListEvent) => {\r\n if (!storage.get('app:theme:theme')) this.signal.set(e.matches ? 'dark' : 'light');\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n });\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n getTheme(): string {\r\n return this.signal?.() ?? this.config.default ?? 'light';\r\n }\r\n\r\n setTheme(themeName: string): void {\r\n if (!this.config.available.includes(themeName)) {\r\n console.warn(`[ThemeManager] Unsupported theme: ${themeName}`);\r\n return;\r\n }\r\n\r\n // Update signal directly - effect will handle DOM updates\r\n if (this.signal) {\r\n this.signal.set(themeName);\r\n console.log(`[ThemeManager] Theme set to: ${themeName}`);\r\n }\r\n }\r\n\r\n toggleTheme(): void {\r\n if (!this.signal) return;\r\n const currentTheme = this.signal();\r\n const nextTheme = this.config.available.find(t => t !== currentTheme);\r\n if (nextTheme) {\r\n this.signal.set(nextTheme);\r\n console.log(`[ThemeManager] Theme toggled to: ${nextTheme}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n private applyTheme(themeName: string): void {\r\n const htmlEl = document.documentElement || document.rootElement;\r\n htmlEl.setAttribute('data-theme', themeName);\r\n console.log(`[ThemeManager] Applied theme: ${themeName}`);\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientExtension, ExtensionContext } from \"@cruxjs/base\";\r\n import { ThemeConfig } from \"./types\";\r\n import { ThemeManager } from \"./mod/theme_manager\";\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n // Theme manager instance\r\n let themeManager : ThemeManager;\r\n\r\n // Exported theme functions\r\n export const getThemeManager = () => themeManager;\r\n export const setTheme = (themeName: string) => getThemeManager().setTheme(themeName);\r\n export const toggleTheme = () => getThemeManager().toggleTheme();\r\n export const getCurrentTheme = () => getThemeManager().getTheme();\r\n\r\n // Theme extension\r\n export function createThemeExtension(config?: ThemeConfig) : ClientExtension {\r\n return {\r\n name : 'ThemeExtension',\r\n\r\n onBoot: (ctx: ExtensionContext) => {\r\n // if config provided, merge into client config\r\n if (config) {\r\n ctx.cconfig.theme = {\r\n ...ctx.cconfig.theme,\r\n ...config\r\n };\r\n }\r\n\r\n // if no theme config provided, set default\r\n if (!ctx.cconfig.theme) {\r\n ctx.cconfig.theme = {\r\n default : 'dark',\r\n available : ['dark', 'light']\r\n };\r\n }\r\n\r\n // create theme manager instance\r\n themeManager = new ThemeManager({\r\n default : ctx.cconfig.theme!.default,\r\n available : ctx.cconfig.theme!.available\r\n });\r\n }\r\n };\r\n };\r\n\r\n // export\r\n export * from \"./types\";\r\n export { ThemeManager };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ThemeConfig, ClientExtension } from '@cruxjs/
|
|
2
|
-
export { ThemeConfig } from '@cruxjs/
|
|
1
|
+
import { ThemeConfig, ClientExtension } from '@cruxjs/base';
|
|
2
|
+
export { ThemeConfig } from '@cruxjs/base';
|
|
3
3
|
import { createStore } from '@minejs/store';
|
|
4
4
|
import { signal } from '@minejs/signals';
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ThemeConfig, ClientExtension } from '@cruxjs/
|
|
2
|
-
export { ThemeConfig } from '@cruxjs/
|
|
1
|
+
import { ThemeConfig, ClientExtension } from '@cruxjs/base';
|
|
2
|
+
export { ThemeConfig } from '@cruxjs/base';
|
|
3
3
|
import { createStore } from '@minejs/store';
|
|
4
4
|
import { signal } from '@minejs/signals';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {Storage,createStore}from'@minejs/store';import {effect}from'@minejs/signals';
|
|
1
|
+
import {Storage,createStore}from'@minejs/store';import {effect}from'@minejs/signals';var i=class{constructor(e){this.config=e;let t=new Storage({type:"local"});this.store=createStore({state:{theme:e.default},persist:true,storage:t,storageKey:"app:theme"}),this.signal=this.store.state.theme;let a=t.get("app:theme:theme")||e.default;this.signal.set(a),this.applyTheme(a),effect(()=>{let n=this.signal?.();n&&this.applyTheme(n),console.log(`[ThemeManager] Reactive effect applied theme: ${n}`);}),effect(()=>{let n=window.matchMedia("(prefers-color-scheme: dark)"),h=g=>{t.get("app:theme:theme")||this.signal.set(g.matches?"dark":"light");};return n.addEventListener("change",h),()=>n.removeEventListener("change",h)});}getTheme(){return this.signal?.()??this.config.default??"light"}setTheme(e){if(!this.config.available.includes(e)){console.warn(`[ThemeManager] Unsupported theme: ${e}`);return}this.signal&&(this.signal.set(e),console.log(`[ThemeManager] Theme set to: ${e}`));}toggleTheme(){if(!this.signal)return;let e=this.signal(),t=this.config.available.find(r=>r!==e);t&&(this.signal.set(t),console.log(`[ThemeManager] Theme toggled to: ${t}`));}applyTheme(e){(document.documentElement||document.rootElement).setAttribute("data-theme",e),console.log(`[ThemeManager] Applied theme: ${e}`);}};var m,s=()=>m,E=o=>s().setTheme(o),x=()=>s().toggleTheme(),y=()=>s().getTheme();function C(o){return {name:"ThemeExtension",onBoot:e=>{o&&(e.cconfig.theme={...e.cconfig.theme,...o}),e.cconfig.theme||(e.cconfig.theme={default:"dark",available:["dark","light"]}),m=new i({default:e.cconfig.theme.default,available:e.cconfig.theme.available});}}}export{i as ThemeManager,C as createThemeExtension,y as getCurrentTheme,s as getThemeManager,E as setTheme,x as toggleTheme};//# sourceMappingURL=index.js.map
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mod/theme_manager.ts","../src/index.ts"],"names":["ThemeManager","config","storage","Storage","createStore","initialTheme","effect","currentTheme","mediaQuery","handleChange","e","themeName","nextTheme","t","themeManager","getThemeManager","setTheme","toggleTheme","getCurrentTheme","createThemeExtension","ctx"],"mappings":"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","file":"index.js","sourcesContent":["// src/mod/theme_manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ThemeConfig } from \"../types\";\r\n import { createStore, Storage } from '@minejs/store';\r\n import { signal, effect } from '@minejs/signals';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class ThemeManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n public store: ReturnType<typeof createStore>;\r\n public signal: ReturnType<typeof signal<string>>;\r\n\r\n constructor(public config: ThemeConfig) {\r\n\r\n const storage = new Storage({ type: 'local' });\r\n\r\n this.store = createStore({\r\n state: {\r\n theme: config.default\r\n },\r\n persist: true,\r\n storage,\r\n storageKey: 'app:theme'\r\n });\r\n\r\n this.signal = this.store.state.theme;\r\n\r\n // Set initial theme on body\r\n const storedTheme = storage.get('app:theme:theme') as string | null;\r\n const initialTheme = storedTheme || config.default;\r\n this.signal.set(initialTheme);\r\n this.applyTheme(initialTheme);\r\n\r\n // Setup reactive effect: apply theme whenever signal changes\r\n effect(() => {\r\n const currentTheme = this.signal?.();\r\n if (currentTheme) {\r\n this.applyTheme(currentTheme);\r\n }\r\n\r\n console.log(`[ThemeManager] Reactive effect applied theme: ${currentTheme}`);\r\n });\r\n\r\n // Listen for system theme changes\r\n effect(() => {\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n\r\n const handleChange = (e: MediaQueryListEvent) => {\r\n if (!storage.get('app:theme:theme')) this.signal.set(e.matches ? 'dark' : 'light');\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n });\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n getTheme(): string {\r\n return this.signal?.() ?? this.config.default ?? 'light';\r\n }\r\n\r\n setTheme(themeName: string): void {\r\n if (!this.config.available.includes(themeName)) {\r\n console.warn(`[ThemeManager] Unsupported theme: ${themeName}`);\r\n return;\r\n }\r\n\r\n // Update signal directly - effect will handle DOM updates\r\n if (this.signal) {\r\n this.signal.set(themeName);\r\n console.log(`[ThemeManager] Theme set to: ${themeName}`);\r\n }\r\n }\r\n\r\n toggleTheme(): void {\r\n if (!this.signal) return;\r\n const currentTheme = this.signal();\r\n const nextTheme = this.config.available.find(t => t !== currentTheme);\r\n if (nextTheme) {\r\n this.signal.set(nextTheme);\r\n console.log(`[ThemeManager] Theme toggled to: ${nextTheme}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n private applyTheme(themeName: string): void {\r\n const htmlEl = document.documentElement || document.rootElement;\r\n htmlEl.setAttribute('data-theme', themeName);\r\n console.log(`[ThemeManager] Applied theme: ${themeName}`);\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientExtension, ExtensionContext } from \"@cruxjs/client\";\r\n import { ThemeConfig } from \"./types\";\r\n import { ThemeManager } from \"./mod/theme_manager\";\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n // Theme manager instance\r\n let themeManager : ThemeManager;\r\n\r\n // Exported theme functions\r\n export const getThemeManager = () => themeManager;\r\n export const setTheme = (themeName: string) => getThemeManager().setTheme(themeName);\r\n export const toggleTheme = () => getThemeManager().toggleTheme();\r\n export const getCurrentTheme = () => getThemeManager().getTheme();\r\n\r\n // Theme extension\r\n export function createThemeExtension(config?: ThemeConfig) : ClientExtension {\r\n return {\r\n name : 'ThemeExtension',\r\n\r\n onBoot: (ctx: ExtensionContext) => {\r\n // if config provided, merge into client config\r\n if (config) {\r\n ctx.cconfig.theme = {\r\n ...ctx.cconfig.theme,\r\n ...config\r\n };\r\n }\r\n\r\n // if no theme config provided, set default\r\n if (!ctx.cconfig.theme) {\r\n ctx.cconfig.theme = {\r\n default : 'dark',\r\n available : ['dark', 'light']\r\n };\r\n }\r\n\r\n // create theme manager instance\r\n themeManager = new ThemeManager({\r\n default : ctx.cconfig.theme!.default,\r\n available : ctx.cconfig.theme!.available\r\n });\r\n }\r\n };\r\n };\r\n\r\n // export\r\n export * from \"./types\";\r\n export { ThemeManager };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
|
1
|
+
{"version":3,"sources":["../src/mod/theme_manager.ts","../src/index.ts"],"names":["ThemeManager","config","storage","Storage","createStore","initialTheme","effect","currentTheme","mediaQuery","handleChange","e","themeName","nextTheme","t","themeManager","getThemeManager","setTheme","toggleTheme","getCurrentTheme","createThemeExtension","ctx"],"mappings":"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","file":"index.js","sourcesContent":["// src/mod/theme_manager.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ThemeConfig } from \"../types\";\r\n import { createStore, Storage } from '@minejs/store';\r\n import { signal, effect } from '@minejs/signals';\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ CORE ════════════════════════════════════════╗\r\n\r\n export class ThemeManager {\r\n\r\n // ┌──────────────────────────────── INIT ──────────────────────────────┐\r\n\r\n public store: ReturnType<typeof createStore>;\r\n public signal: ReturnType<typeof signal<string>>;\r\n\r\n constructor(public config: ThemeConfig) {\r\n\r\n const storage = new Storage({ type: 'local' });\r\n\r\n this.store = createStore({\r\n state: {\r\n theme: config.default\r\n },\r\n persist: true,\r\n storage,\r\n storageKey: 'app:theme'\r\n });\r\n\r\n this.signal = this.store.state.theme;\r\n\r\n // Set initial theme on body\r\n const storedTheme = storage.get('app:theme:theme') as string | null;\r\n const initialTheme = storedTheme || config.default;\r\n this.signal.set(initialTheme);\r\n this.applyTheme(initialTheme);\r\n\r\n // Setup reactive effect: apply theme whenever signal changes\r\n effect(() => {\r\n const currentTheme = this.signal?.();\r\n if (currentTheme) {\r\n this.applyTheme(currentTheme);\r\n }\r\n\r\n console.log(`[ThemeManager] Reactive effect applied theme: ${currentTheme}`);\r\n });\r\n\r\n // Listen for system theme changes\r\n effect(() => {\r\n const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\r\n\r\n const handleChange = (e: MediaQueryListEvent) => {\r\n if (!storage.get('app:theme:theme')) this.signal.set(e.matches ? 'dark' : 'light');\r\n };\r\n\r\n mediaQuery.addEventListener('change', handleChange);\r\n return () => mediaQuery.removeEventListener('change', handleChange);\r\n });\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── MAIN ──────────────────────────────┐\r\n\r\n getTheme(): string {\r\n return this.signal?.() ?? this.config.default ?? 'light';\r\n }\r\n\r\n setTheme(themeName: string): void {\r\n if (!this.config.available.includes(themeName)) {\r\n console.warn(`[ThemeManager] Unsupported theme: ${themeName}`);\r\n return;\r\n }\r\n\r\n // Update signal directly - effect will handle DOM updates\r\n if (this.signal) {\r\n this.signal.set(themeName);\r\n console.log(`[ThemeManager] Theme set to: ${themeName}`);\r\n }\r\n }\r\n\r\n toggleTheme(): void {\r\n if (!this.signal) return;\r\n const currentTheme = this.signal();\r\n const nextTheme = this.config.available.find(t => t !== currentTheme);\r\n if (nextTheme) {\r\n this.signal.set(nextTheme);\r\n console.log(`[ThemeManager] Theme toggled to: ${nextTheme}`);\r\n }\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n\r\n // ┌──────────────────────────────── HELP ──────────────────────────────┐\r\n\r\n private applyTheme(themeName: string): void {\r\n const htmlEl = document.documentElement || document.rootElement;\r\n htmlEl.setAttribute('data-theme', themeName);\r\n console.log(`[ThemeManager] Applied theme: ${themeName}`);\r\n }\r\n\r\n // └────────────────────────────────────────────────────────────────────┘\r\n\r\n };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n","// src/index.ts\r\n//\r\n// Made with ❤️ by Maysara.\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ PACK ════════════════════════════════════════╗\r\n\r\n import { ClientExtension, ExtensionContext } from \"@cruxjs/base\";\r\n import { ThemeConfig } from \"./types\";\r\n import { ThemeManager } from \"./mod/theme_manager\";\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝\r\n\r\n\r\n\r\n// ╔════════════════════════════════════════ MAIN ════════════════════════════════════════╗\r\n\r\n // Theme manager instance\r\n let themeManager : ThemeManager;\r\n\r\n // Exported theme functions\r\n export const getThemeManager = () => themeManager;\r\n export const setTheme = (themeName: string) => getThemeManager().setTheme(themeName);\r\n export const toggleTheme = () => getThemeManager().toggleTheme();\r\n export const getCurrentTheme = () => getThemeManager().getTheme();\r\n\r\n // Theme extension\r\n export function createThemeExtension(config?: ThemeConfig) : ClientExtension {\r\n return {\r\n name : 'ThemeExtension',\r\n\r\n onBoot: (ctx: ExtensionContext) => {\r\n // if config provided, merge into client config\r\n if (config) {\r\n ctx.cconfig.theme = {\r\n ...ctx.cconfig.theme,\r\n ...config\r\n };\r\n }\r\n\r\n // if no theme config provided, set default\r\n if (!ctx.cconfig.theme) {\r\n ctx.cconfig.theme = {\r\n default : 'dark',\r\n available : ['dark', 'light']\r\n };\r\n }\r\n\r\n // create theme manager instance\r\n themeManager = new ThemeManager({\r\n default : ctx.cconfig.theme!.default,\r\n available : ctx.cconfig.theme!.available\r\n });\r\n }\r\n };\r\n };\r\n\r\n // export\r\n export * from \"./types\";\r\n export { ThemeManager };\r\n\r\n// ╚══════════════════════════════════════════════════════════════════════════════════════╝"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cruxext/theme",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Lightweight reactive theme manager for CruxJS with dark/light mode support and persistent storage.",
|
|
5
5
|
"keywords": ["cruxjs", "extension", "theme"],
|
|
6
6
|
"license": "MIT",
|
|
@@ -40,20 +40,20 @@
|
|
|
40
40
|
"bun": "^1.3.3"
|
|
41
41
|
},
|
|
42
42
|
"dependencies": {
|
|
43
|
-
"@cruxjs/
|
|
43
|
+
"@cruxjs/base": "^0.1.8",
|
|
44
44
|
"@minejs/signals": "^0.0.6",
|
|
45
45
|
"@minejs/store": "^0.0.3"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@eslint/js": "^9.39.2",
|
|
49
|
-
"@stylistic/eslint-plugin": "^5.
|
|
50
|
-
"@types/bun": "^1.3.
|
|
51
|
-
"@types/node": "^20.19.
|
|
49
|
+
"@stylistic/eslint-plugin": "^5.7.0",
|
|
50
|
+
"@types/bun": "^1.3.6",
|
|
51
|
+
"@types/node": "^20.19.30",
|
|
52
52
|
"bun-plugin-dts": "^0.3.0",
|
|
53
|
-
"bun-types": "^1.3.
|
|
53
|
+
"bun-types": "^1.3.6",
|
|
54
54
|
"ts-node": "^10.9.2",
|
|
55
55
|
"tsup": "^8.5.1",
|
|
56
56
|
"typescript": "^5.9.3",
|
|
57
|
-
"typescript-eslint": "^8.
|
|
57
|
+
"typescript-eslint": "^8.53.0"
|
|
58
58
|
}
|
|
59
59
|
}
|