ngx-theme-stack 3.7.0 → 3.8.2

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 CHANGED
@@ -105,7 +105,7 @@ The installation command automates the following:
105
105
  | `package.json` | Adds a `"prebuild"` script for theme synchronization |
106
106
  | `angular.json` | Registers `themes.css` and optimizes build config |
107
107
  | `themes.css` | Scaffolds base theme tokens if they don't exist |
108
- | `SKILL.md` | Generates an AI Agent Skill under `.agents/skills/` (optional) |
108
+ | `SKILL.md` | Generates an AI Agent Skill under `.agents/skills/` (optional) |
109
109
 
110
110
  > [!TIP]
111
111
  > **Re-configuration support:** Run `ng add` multiple times freely. The schematic updates existing code without duplicating it.
@@ -143,7 +143,7 @@ import { provideThemeStack } from 'ngx-theme-stack';
143
143
  export const appConfig: ApplicationConfig = {
144
144
  providers: [
145
145
  provideThemeStack({
146
- themes: ['light', 'dark', 'sunset'], // your theme identifiers
146
+ themes: ['light', 'dark', 'sunset'] as const, // your theme identifiers
147
147
  defaultTheme: 'system', // resolves via matchMedia
148
148
  mode: 'class', // 'class' | 'attribute' | 'both'
149
149
  strategy: 'critters', // 'critters' | 'blocking'
@@ -207,9 +207,7 @@ import { ThemeCycleService } from 'ngx-theme-stack';
207
207
  selector: 'app-theme-cycle',
208
208
  template: `
209
209
  @if (theme.isHydrated()) {
210
- <button (click)="theme.cycle()">
211
- 🔄 Cycle Theme
212
- </button>
210
+ <button (click)="theme.cycle()">🔄 Cycle Theme</button>
213
211
  } @else {
214
212
  <div class="theme-cycle-skeleton"></div>
215
213
  }
@@ -290,7 +288,7 @@ export class MyAdvancedComponent {
290
288
  >
291
289
  > ```html
292
290
  > @if (theme.isHydrated()) {
293
- > <img [src]="theme.isDark() ? 'dark-logo.png' : 'light-logo.png'">
291
+ > <img [src]="theme.isDark() ? darkLogo : lightLogo" />
294
292
  > }
295
293
  > ```
296
294
 
@@ -364,6 +362,7 @@ Only needed if you want `dark:` utilities tied to ngx-theme-stack's toggle:
364
362
  </details>
365
363
 
366
364
  ---
365
+
367
366
  ## 🤖 AI Code Assistants Integration
368
367
 
369
368
  `ngx-theme-stack` includes out-of-the-box support for AI coding assistants (such as Google Antigravity, Gemini, Claude Code, and other agents that support the open `SKILL.md` standard).
@@ -389,10 +388,11 @@ Once the skill is in your workspace, your AI assistant will automatically read i
389
388
  `ng add` injects a minimal blocking script as the **first child of `<head>`**. It runs before any stylesheet or Angular bundle:
390
389
 
391
390
  ```
392
- 1. Read stored theme from localStorage
393
- 2. If 'system' resolve OS preference via matchMedia('prefers-color-scheme: dark')
394
- 3. Apply theme to <html> (class, attribute, or both)
395
- 4. Set color-scheme CSS property for native browser adaptation
391
+ 1. Read stored theme from localStorage (or fallback to default theme)
392
+ 2. Validate the theme name format (regex) and ensure it exists in the configured themes (otherwise fallback to default)
393
+ 3. If 'system' resolve OS preference via matchMedia('prefers-color-scheme: dark')
394
+ 4. Apply theme to <html> (class, attribute, or both)
395
+ 5. Set color-scheme CSS property for native browser adaptation
396
396
  ```
397
397
 
398
398
  ### Strategy comparison
@@ -403,7 +403,7 @@ Once the skill is in your workspace, your AI assistant will automatically read i
403
403
  | **Network requests** | Zero | One (then cached) |
404
404
  | **Flash risk** | None | None |
405
405
  | **Works with CSR** | ✅ | ✅ |
406
- | **Works with SSR/SSG** | ✅ | ⚠️ May flash on SSG |
406
+ | **Works with SSR/SSG** | ✅ | ⚠️ May flash on SSG |
407
407
  | **Strict CSP compatible** | ❌ requires `unsafe-inline` | ✅ |
408
408
  | **Best for** | Most apps | Strict CSP, many themes |
409
409
 
@@ -218,7 +218,8 @@ class CoreThemeService {
218
218
  * {{ theme.isHydrated() ? theme.selectedTheme() : '...' }}
219
219
  * ```
220
220
  */
221
- isHydrated = signal(false, ...(ngDevMode ? [{ debugName: "isHydrated" }] : /* istanbul ignore next */ []));
221
+ #isHydrated = signal(false, ...(ngDevMode ? [{ debugName: "#isHydrated" }] : /* istanbul ignore next */ []));
222
+ isHydrated = this.#isHydrated.asReadonly();
222
223
  // ── Event handler ─────────────────────────────────────────────────────────
223
224
  #onSystemPreferenceChange = () => this.#systemPreference.set(this.resolveSystemPreference());
224
225
  // ── Lifecycle ─────────────────────────────────────────────────────────────
@@ -228,7 +229,7 @@ class CoreThemeService {
228
229
  this.startSystemThemeListener();
229
230
  }
230
231
  effect(() => this.applyThemeToDOM(this.resolvedTheme()));
231
- afterNextRender(() => this.isHydrated.set(true));
232
+ afterNextRender(() => this.#isHydrated.set(true));
232
233
  this.#destroyRef.onDestroy(() => this.stopSystemThemeListener());
233
234
  }
234
235
  // ── Public API ────────────────────────────────────────────────────────────
@@ -314,7 +315,8 @@ class CoreThemeService {
314
315
  captureAntiFlashClass() {
315
316
  if (!this.#isBrowser || !this.#initialStoredTheme)
316
317
  return;
317
- if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(this.#initialStoredTheme)) {
318
+ if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(this.#initialStoredTheme) ||
319
+ !this.#validThemes.has(this.#initialStoredTheme)) {
318
320
  this.#antiFlashClass = null;
319
321
  return;
320
322
  }
@@ -394,7 +396,7 @@ class ThemeCycleService {
394
396
  * Whether the service has completed client-side initialization and
395
397
  * resolved the real persisted theme. Use to prevent hydration flashes.
396
398
  */
397
- isHydrated = this.#core.isHydrated.asReadonly();
399
+ isHydrated = this.#core.isHydrated;
398
400
  /**
399
401
  * Advances to the next theme in the cycle.
400
402
  *
@@ -438,7 +440,7 @@ class ThemeSelectService {
438
440
  * Whether the service has completed client-side initialization and
439
441
  * resolved the real persisted theme. Use to prevent hydration flashes.
440
442
  */
441
- isHydrated = this.#core.isHydrated.asReadonly();
443
+ isHydrated = this.#core.isHydrated;
442
444
  /**
443
445
  * Applies the given theme.
444
446
  *
@@ -478,7 +480,7 @@ class ThemeToggleService {
478
480
  * Whether the service has completed client-side initialization and
479
481
  * resolved the real persisted theme. Use to prevent hydration flashes.
480
482
  */
481
- isHydrated = this.#core.isHydrated.asReadonly();
483
+ isHydrated = this.#core.isHydrated;
482
484
  /**
483
485
  * Toggles between `'dark'` and `'light'`.
484
486
  *
@@ -1 +1 @@
1
- {"version":3,"file":"ngx-theme-stack.mjs","sources":["../../../projects/ngx-theme-stack/src/lib/errors.ts","../../../projects/ngx-theme-stack/src/lib/types.ts","../../../projects/ngx-theme-stack/src/lib/config/index.ts","../../../projects/ngx-theme-stack/src/lib/core/core-theme.service.ts","../../../projects/ngx-theme-stack/src/lib/services/theme-cycle.service.ts","../../../projects/ngx-theme-stack/src/lib/services/theme-select.service.ts","../../../projects/ngx-theme-stack/src/lib/services/theme-toggle.service.ts","../../../projects/ngx-theme-stack/src/public-api.ts","../../../projects/ngx-theme-stack/src/ngx-theme-stack.ts"],"sourcesContent":["/**\n * Base error class for `ngx-theme-stack`.\n *\n * Thrown when the library configuration is invalid.\n * Consumers can use `instanceof NgxThemeStackError` to catch only\n * errors originating from this library.\n *\n * @example\n * try {\n * bootstrapApplication(AppComponent, appConfig);\n * } catch (e) {\n * if (e instanceof NgxThemeStackError) {\n * console.error('Bad ngx-theme-stack config:', e.message);\n * }\n * }\n */\nexport class NgxThemeStackError extends Error {\n override readonly name = 'NgxThemeStackError';\n\n constructor(message: string) {\n super(`[ngx-theme-stack] ${message}`);\n // Restore prototype chain (required when targeting ES5 or older)\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","/**\n * Runtime list of built-in themes.\n *\n * Lives here (and not in config/index.ts) because it defines a type:\n * config/index.ts already imports from types.ts, so placing DEFAULT_THEMES\n * here avoids any circular dependency.\n *\n * ⚠ KEEP IN SYNC with the duplicate in:\n * projects/ngx-theme-stack/schematics/ng-add/constants.ts → DEFAULT_THEMES\n *\n * Schematics compile to CommonJS and cannot import from this ESM file,\n * so the values are intentionally duplicated. Change both at the same time.\n */\nexport const DEFAULT_THEMES = ['system', 'light', 'dark'] as const;\n\n/** Literal union of built-in themes: `'system' | 'light' | 'dark'`. */\nexport type DefaultNgTheme = (typeof DEFAULT_THEMES)[number];\n\n/**\n * Theme type.\n *\n * - **Without** `T`: open union — accepts any `string` with IDE autocomplete\n * hints for the built-in themes (`'system' | 'light' | 'dark'`).\n * - **With** `T`: closed union — exactly `DefaultNgTheme | T`, enabling\n * full type-safety for custom theme sets.\n *\n * @example\n * NgTheme // 'system' | 'light' | 'dark' | (string & {})\n * NgTheme<'sepia'> // 'system' | 'light' | 'dark' | 'sepia'\n */\nexport type NgTheme<T extends string = string & {}> = DefaultNgTheme | T;\n\n/**\n * Resolved theme — always `'light'` or `'dark'`, never `'system'`.\n * Represents the value that comes from `matchMedia`, not user selection.\n */\nexport type NgSystemTheme = Exclude<DefaultNgTheme, 'system'>;\n\n/**\n * Theme application mode.\n * - `'attribute'`: sets `data-theme` attribute on `<html>`\n * - `'class'`: adds theme class to `<html>`\n * - `'both'`: uses both attribute and class\n */\nexport type NgMode = 'attribute' | 'class' | 'both';\n\n/**\n * Theme application strategy.\n * - `'blocking'`: theme CSS is loaded synchronously before rendering\n * - `'critters'`: theme CSS is inlined using Critters for SSR/SSG\n */\nexport type NgStrategy = 'blocking' | 'critters';\n\n/**\n * Library configuration.\n *\n * @typeParam T - Custom theme literals. Defaults to open `string`, preserving\n * backwards compatibility. Pass specific literals (e.g. `'sepia' | 'ocean'`)\n * via {@link provideThemeStack} to get a closed, type-safe theme union.\n */\nexport interface NgConfig<T extends string = string & {}> {\n /** The theme to use on first visit or when no preference is saved. Default: 'system'. */\n defaultTheme: NgTheme<T>;\n\n /** Key used to persist theme preference in localStorage. Default: 'ngx-theme-stack'. */\n storageKey: string;\n\n /** \n * How the theme should be applied to the document (via class, attribute or both). \n * Default: 'class'.\n */\n mode: NgMode;\n\n /** \n * Performance strategy for anti-flash.\n * Use 'critters' (default) to inline all theme CSS in <head> — works for CSR, SSR, and SSG.\n * Use 'blocking' to load themes.css as a render-blocking stylesheet (HTTP-cacheable).\n */\n strategy: NgStrategy;\n\n /**\n * The **resolved** list of supported theme identifiers, always including the\n * built-in themes (`'light'`, `'dark'`, `'system'`).\n *\n * When you pass custom themes to {@link provideThemeStack}, they are **merged**\n * with the built-in defaults — your custom values are appended after them.\n *\n * @example\n * // Input to provideThemeStack:\n * themes: ['sepia', 'ocean'] as const\n *\n * // Resolved value stored in NgConfig:\n * // ['system', 'light', 'dark', 'sepia', 'ocean']\n *\n * Default (no custom themes): `['system', 'light', 'dark']`.\n */\n themes: NgTheme<T>[];\n}\n","import { InjectionToken } from '@angular/core';\nimport { NgxThemeStackError } from '../errors';\nimport { DEFAULT_THEMES, DefaultNgTheme, NgConfig } from '../types';\n\n/**\n * ⚠ ATTENTION: SHARED CONFIGURATION VALUES\n *\n * These defaults MUST match the schematic defaults in:\n * projects/ngx-theme-stack/schematics/ng-add/constants.ts → DEFAULTS\n *\n * Schematics compile to CommonJS and cannot import from this ESM file,\n * so the values are intentionally duplicated. Change both at the same time.\n *\n * If you change defaults here, also update:\n * schematics/ng-add/constants.ts → DEFAULTS + DEFAULT_THEMES\n */\n\nexport const DEFAULT_NG_CONFIG = {\n defaultTheme: 'system',\n storageKey: 'ngx-theme-stack',\n mode: 'class',\n strategy: 'critters',\n themes: [...DEFAULT_THEMES],\n} satisfies NgConfig;\n\n// The token uses NgConfig<string> because Angular DI resolves types at runtime\n// and cannot carry generic parameters. Type-safety is enforced at the\n// provideThemeStack() call site instead.\nexport const NGX_THEME_STACK_CONFIG = new InjectionToken<NgConfig<string>>(\n 'NGX_THEME_STACK_CONFIG',\n {\n factory: () => DEFAULT_NG_CONFIG,\n },\n);\n\n/**\n * Provides Theme Stack configuration to Angular's DI system.\n *\n * The `themes` option accepts **additional** theme identifiers beyond the\n * built-in defaults. They are merged with `'light'`, `'dark'`, and `'system'`\n * so that the resolved {@link NgConfig.themes} array always includes all of\n * them — your custom values are appended after the built-ins.\n *\n * **Defaults:**\n * - `themes`: `['light', 'dark', 'system']`\n * - `defaultTheme`: `'system'`\n * - `storageKey`: `'ngx-theme-stack'`\n * - `mode`: `'class'`\n * - `strategy`: `'critters'`\n\n *\n * The type parameter `T` is **inferred automatically** from the `themes` array\n * when passed as a `const` — no need to specify it manually.\n *\n * @typeParam T - Custom theme string literals, inferred from the `themes` option.\n *\n * @param config - Optional partial configuration. Omitted fields fall back to\n * {@link DEFAULT_NG_CONFIG}.\n *\n * @throws {@link NgxThemeStackError}\n * - If any entry in `themes` is an empty or whitespace-only string.\n * - If `defaultTheme` is not present in the resolved (merged) themes array.\n * - If `storageKey` is an empty or whitespace-only string.\n *\n * @example\n * // Default — uses built-in themes and sensible defaults\n * provideThemeStack()\n *\n * @example\n * // Critters strategy — inlines all theme CSS in <head> (works for CSR, SSR, and SSG)\n * provideThemeStack({\n * strategy: 'critters',\n * mode: 'class',\n * })\n *\n * @example\n * // Closed union: TypeScript infers 'sepia' | 'ocean' from the array\n * provideThemeStack({\n * themes: ['sepia', 'ocean'] as const,\n * defaultTheme: 'sepia', // ✅ in resolved themes\n * // defaultTheme: 'nope', // ❌ throws NgxThemeStackError at runtime\n * })\n *\n * @example\n * // Custom storage key and mode\n * provideThemeStack({\n * storageKey: 'my-app-theme',\n * mode: 'attribute',\n * })\n */\nexport function provideThemeStack<const T extends string = DefaultNgTheme>(\n config: Partial<NgConfig<T>> = {},\n) {\n config.themes?.forEach((t) => {\n if (t.trim() === '') throw new NgxThemeStackError('Theme cannot be empty or whitespace.');\n });\n\n const themes = config.themes\n ? Array.from(new Set([...DEFAULT_NG_CONFIG.themes, ...config.themes]))\n : DEFAULT_NG_CONFIG.themes;\n\n if (config.defaultTheme && !(themes as string[]).includes(config.defaultTheme as string)) {\n throw new NgxThemeStackError(\n `\"defaultTheme\" must be one of the resolved themes: [${themes.join(', ')}].`,\n );\n }\n\n if (config.storageKey !== undefined && config.storageKey.trim() === '') {\n throw new NgxThemeStackError('\"storageKey\" cannot be empty or whitespace.');\n }\n\n return {\n provide: NGX_THEME_STACK_CONFIG,\n useValue: {\n ...DEFAULT_NG_CONFIG,\n ...config,\n themes,\n } as NgConfig<string>,\n };\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n afterNextRender,\n computed,\n DestroyRef,\n DOCUMENT,\n effect,\n inject,\n Injectable,\n PLATFORM_ID,\n signal,\n} from '@angular/core';\nimport { NGX_THEME_STACK_CONFIG } from '../config';\nimport { NgxThemeStackError } from '../errors';\nimport { NgSystemTheme, NgTheme } from '../types';\n\n/**\n * Core service for managing the application's color theme.\n *\n * Handles theme persistence, system preference detection, and DOM updates.\n * Supports built-in themes ('dark', 'light', 'system') and custom extensions.\n */\n@Injectable({ providedIn: 'root' })\nexport class CoreThemeService {\n // ── Dependencies ──────────────────────────────────────────────────────────\n\n readonly #config = inject(NGX_THEME_STACK_CONFIG);\n readonly #destroyRef = inject(DestroyRef);\n readonly #document = inject(DOCUMENT);\n readonly #isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n // ── Theme configuration ───────────────────────────────────────────────────\n\n /** The initial stored theme read from localStorage on startup. */\n readonly #initialStoredTheme = this.readStoredTheme();\n\n /** List of available themes for Select/Cycle services. Defaults to ['system', 'light', 'dark']. */\n readonly availableThemes = this.#config.themes;\n\n /** Internal Set for O(1) existence checks. */\n readonly #validThemes = new Set<NgTheme>(this.availableThemes);\n\n /**\n * The anti-flash class to remove from the host element.\n * Internal mechanism to bridge the gap between the blocking script's\n * initial DOM state and Angular's first effect run.\n */\n #antiFlashClass: string | null = null;\n\n // ── System preference ─────────────────────────────────────────────────────\n\n /** MediaQueryList for OS color scheme, created once and reused. Null in SSR. */\n readonly #mediaQuery: MediaQueryList | null = this.#isBrowser\n ? (this.#document.defaultView?.matchMedia('(prefers-color-scheme: dark)') ?? null)\n : null;\n\n readonly #systemPreference = signal<NgSystemTheme>(this.resolveSystemPreference());\n\n // ── Theme state ───────────────────────────────────────────────────────────\n\n readonly #selectedTheme = signal<NgTheme>(this.resolveInitialTheme());\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#selectedTheme.asReadonly();\n\n /** Resolved theme applied to the DOM. Always `'dark'` or `'light'` (or custom) — never `'system'`. */\n readonly resolvedTheme = computed(() => {\n const theme = this.#selectedTheme();\n return theme === 'system' ? this.#systemPreference() : theme;\n });\n\n /**\n * Whether the currently applied theme is dark.\n *\n * Returns `false` when a custom theme (e.g. `'sunset'`) is active — use\n * `resolvedTheme()` directly if you need to inspect the current custom theme.\n */\n readonly isDark = computed(() => this.resolvedTheme() === 'dark');\n\n /**\n * Whether the currently applied theme is light.\n *\n * Returns `false` when a custom theme (e.g. `'sepia'`) is active — use\n * `resolvedTheme()` directly if you need to inspect the current custom theme.\n */\n readonly isLight = computed(() => this.resolvedTheme() === 'light');\n\n /** Whether the currently applied theme is system. */\n readonly isSystem = computed(() => this.selectedTheme() === 'system');\n\n /**\n * Whether the service has completed client-side initialization.\n *\n * `false` during SSR and on the very first render pass before the initial theme\n * is resolved from `localStorage`. Becomes `true` immediately after the\n * first browser render pass.\n *\n * **Important:** Guard template elements that display `selectedTheme()` or\n * `resolvedTheme()` behind this signal to prevent hydration-mismatch flashes\n * (e.g. if the server renders the default 'system' but the user has 'dark' stored).\n *\n * @example\n * ```html\n * {{ theme.isHydrated() ? theme.selectedTheme() : '...' }}\n * ```\n */\n readonly isHydrated = signal(false);\n\n // ── Event handler ─────────────────────────────────────────────────────────\n\n readonly #onSystemPreferenceChange = () =>\n this.#systemPreference.set(this.resolveSystemPreference());\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n\n constructor() {\n this.captureAntiFlashClass();\n\n if (this.#isBrowser && this.#selectedTheme() === 'system') {\n this.startSystemThemeListener();\n }\n\n effect(() => this.applyThemeToDOM(this.resolvedTheme()));\n afterNextRender(() => this.isHydrated.set(true));\n this.#destroyRef.onDestroy(() => this.stopSystemThemeListener());\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n\n /**\n * Changes the active theme.\n *\n * Persists the choice explicitly so that switching e.g. from `'system'` to\n * `'light'` is saved even when the resolved theme did not change\n * (system preference was already `'light'`).\n *\n * @param theme - The theme to apply: `'dark'`, `'light'`, `'system'`, or a custom theme name.\n * @throws If `theme` is not a valid theme according to library configuration.\n */\n public setTheme(theme: NgTheme): void {\n if (!this.#validThemes.has(theme)) {\n throw new NgxThemeStackError(\n `Invalid theme: \"${theme}\". Valid values are: ${[...this.#validThemes].join(', ')}.`,\n );\n }\n if (!this.#isBrowser) return;\n if (theme === this.#selectedTheme()) return;\n if (theme === 'system') {\n this.#systemPreference.set(this.resolveSystemPreference());\n this.startSystemThemeListener();\n } else {\n this.stopSystemThemeListener();\n }\n\n this.#selectedTheme.set(theme);\n this.saveTheme(theme);\n }\n\n // ── Private ───────────────────────────────────────────────────────────────\n\n private resolveSystemPreference(): NgSystemTheme {\n return this.#mediaQuery?.matches ? 'dark' : 'light';\n }\n\n private resolveInitialTheme(): NgTheme {\n const theme = this.#initialStoredTheme;\n if (theme && this.#validThemes.has(theme as NgTheme)) {\n return theme as NgTheme;\n }\n return this.#config.defaultTheme;\n }\n\n private startSystemThemeListener(): void {\n if (!this.#mediaQuery) return;\n this.stopSystemThemeListener();\n this.#mediaQuery.addEventListener('change', this.#onSystemPreferenceChange);\n }\n\n private stopSystemThemeListener(): void {\n this.#mediaQuery?.removeEventListener('change', this.#onSystemPreferenceChange);\n }\n\n private applyThemeToDOM(theme: NgTheme): void {\n if (!this.#isBrowser) return;\n\n const host = this.#document.documentElement;\n\n if (this.#antiFlashClass) {\n host.classList.remove(this.#antiFlashClass);\n this.#antiFlashClass = null;\n }\n\n const { mode } = this.#config;\n\n if (mode === 'attribute' || mode === 'both') {\n this.applyThemeAttribute(host, theme);\n }\n\n if (mode === 'class' || mode === 'both') {\n this.applyThemeClasses(host, theme);\n }\n\n this.applyColorSchemeHint(host, theme);\n }\n\n private applyThemeAttribute(host: HTMLElement, theme: NgTheme): void {\n host.setAttribute('data-theme', theme);\n }\n\n private applyThemeClasses(host: HTMLElement, theme: NgTheme): void {\n host.classList.remove(...this.availableThemes);\n host.classList.add(theme);\n }\n\n private applyColorSchemeHint(host: HTMLElement, theme: NgTheme): void {\n if (theme === 'dark' || theme === 'light') {\n host.style.setProperty('color-scheme', theme);\n return;\n }\n\n host.style.removeProperty('color-scheme');\n }\n\n private captureAntiFlashClass(): void {\n if (!this.#isBrowser || !this.#initialStoredTheme) return;\n\n if (!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(this.#initialStoredTheme)) {\n this.#antiFlashClass = null;\n return;\n }\n\n if (this.#initialStoredTheme === 'system') {\n this.#antiFlashClass = this.resolveSystemPreference();\n return;\n }\n\n this.#antiFlashClass = this.#initialStoredTheme;\n }\n\n private readStoredTheme(): string | null {\n if (!this.#isBrowser) return null;\n\n try {\n return localStorage.getItem(this.#config.storageKey);\n } catch (e) {\n console.warn('[ngx-theme-stack] Could not read theme from localStorage.', e);\n return null;\n }\n }\n\n private saveTheme(theme: NgTheme): void {\n if (!this.#isBrowser) return;\n\n try {\n localStorage.setItem(this.#config.storageKey, theme);\n } catch (e) {\n console.warn('[ngx-theme-stack] Could not save theme to localStorage.', e);\n }\n }\n}\n","import { computed, inject, Injectable } from '@angular/core';\nimport { CoreThemeService } from '../core/core-theme.service';\n\n/**\n * Convenience service for cycling through themes in a fixed order.\n *\n * Default cycle: `'system'` → `'light'` → `'dark'` → `'system'` → ...\n *\n * Use this when you want to offer users a single button that rotates\n * through all available theme options.\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeCycleService {\n readonly #core = inject(CoreThemeService);\n\n /** List of all configured themes for cycling. Defaults to `['light', 'dark', 'system']`. */\n readonly availableThemes = this.#core.availableThemes;\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#core.selectedTheme;\n\n /** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */\n readonly resolvedTheme = this.#core.resolvedTheme;\n\n /** Index of the currently selected theme in the cycle. */\n readonly cycleIndex = computed(() => {\n return this.availableThemes.indexOf(this.selectedTheme());\n });\n\n /** The theme that comes before the currently selected theme in the cycle. */\n readonly preceding = computed(() => {\n const index = this.cycleIndex();\n const len = this.availableThemes.length;\n return this.availableThemes[(index - 1 + len) % len];\n });\n\n /** The theme that comes after the currently selected theme in the cycle. */\n readonly upcoming = computed(() => {\n const index = this.cycleIndex();\n return this.availableThemes[(index + 1) % this.availableThemes.length];\n });\n\n /** Whether the currently applied theme is `'dark'`. */\n readonly isDark = this.#core.isDark;\n\n /** Whether the currently applied theme is `'light'`. */\n readonly isLight = this.#core.isLight;\n\n /** Whether the user has explicitly selected `'system'` preference. */\n readonly isSystem = this.#core.isSystem;\n\n /**\n * Whether the service has completed client-side initialization and\n * resolved the real persisted theme. Use to prevent hydration flashes.\n */\n readonly isHydrated = this.#core.isHydrated.asReadonly();\n\n /**\n * Advances to the next theme in the cycle.\n *\n * Cycle order is determined by the configured `themes` property in `NgConfig`.\n *\n * If the current theme is not found in the cycle (e.g. set externally),\n * the cycle restarts from the first theme.\n */\n cycle(): void {\n this.#core.setTheme(this.upcoming());\n }\n}\n","import { inject, Injectable } from '@angular/core';\nimport { CoreThemeService } from '../core/core-theme.service';\nimport { NgTheme } from '../types';\n\n/**\n * Convenience service for selecting a theme from a list.\n *\n * Use this when you want to bind a `<select>` or a group of radio/tab\n * buttons to the full set of available themes.\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeSelectService {\n readonly #core = inject(CoreThemeService);\n\n /** List of all configured themes. Defaults to `['light', 'dark', 'system']`. */\n readonly availableThemes = this.#core.availableThemes;\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#core.selectedTheme;\n\n /** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */\n readonly resolvedTheme = this.#core.resolvedTheme;\n\n /** Whether the currently applied theme is `'dark'`. */\n readonly isDark = this.#core.isDark;\n\n /** Whether the currently applied theme is `'light'`. */\n readonly isLight = this.#core.isLight;\n\n /** Whether the user has explicitly selected `'system'` preference. */\n readonly isSystem = this.#core.isSystem;\n\n /**\n * Whether the service has completed client-side initialization and\n * resolved the real persisted theme. Use to prevent hydration flashes.\n */\n readonly isHydrated = this.#core.isHydrated.asReadonly();\n\n /**\n * Applies the given theme.\n *\n * @param theme - The theme to apply: `'dark'`, `'light'`, `'system'`, or custom.\n * @throws If `theme` is not a valid theme according to library configuration.\n */\n select(theme: NgTheme): void {\n this.#core.setTheme(theme);\n }\n}\n","import { inject, Injectable } from '@angular/core';\nimport { CoreThemeService } from '../core/core-theme.service';\n\n/**\n * Convenience service for toggling between `'dark'` and `'light'`.\n *\n * Use this when you only need a simple on/off switch and do not\n * need to manage `'system'` or cycle through themes.\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeToggleService {\n readonly #core = inject(CoreThemeService);\n\n /** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */\n readonly resolvedTheme = this.#core.resolvedTheme;\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#core.selectedTheme;\n\n /** Whether the currently applied theme is `'dark'`. */\n readonly isDark = this.#core.isDark;\n\n /** Whether the currently applied theme is `'light'`. */\n readonly isLight = this.#core.isLight;\n\n /** Whether the user has explicitly selected `'system'` preference. */\n readonly isSystem = this.#core.isSystem;\n\n /**\n * Whether the service has completed client-side initialization and\n * resolved the real persisted theme. Use to prevent hydration flashes.\n */\n readonly isHydrated = this.#core.isHydrated.asReadonly();\n\n /**\n * Toggles between `'dark'` and `'light'`.\n *\n * If the selected theme is explicitly `'dark'`, switches to `'light'`.\n * Otherwise (including `'system'`), switches to `'dark'`.\n */\n toggle(): void {\n const next = this.#core.resolvedTheme() === 'dark' ? 'light' : 'dark';\n this.#core.setTheme(next);\n }\n}\n","/*\n * Public API Surface of ngx-theme-stack\n */\n\nexport * from './lib/core/core-theme.service';\nexport * from './lib/config';\nexport * from './lib/services/theme-cycle.service';\nexport * from './lib/services/theme-select.service';\nexport * from './lib/services/theme-toggle.service';\nexport * from './lib/types';\nexport * from './lib/errors';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ngx-theme-stack.mjs","sources":["../../../projects/ngx-theme-stack/src/lib/errors.ts","../../../projects/ngx-theme-stack/src/lib/types.ts","../../../projects/ngx-theme-stack/src/lib/config/index.ts","../../../projects/ngx-theme-stack/src/lib/core/core-theme.service.ts","../../../projects/ngx-theme-stack/src/lib/services/theme-cycle.service.ts","../../../projects/ngx-theme-stack/src/lib/services/theme-select.service.ts","../../../projects/ngx-theme-stack/src/lib/services/theme-toggle.service.ts","../../../projects/ngx-theme-stack/src/public-api.ts","../../../projects/ngx-theme-stack/src/ngx-theme-stack.ts"],"sourcesContent":["/**\n * Base error class for `ngx-theme-stack`.\n *\n * Thrown when the library configuration is invalid.\n * Consumers can use `instanceof NgxThemeStackError` to catch only\n * errors originating from this library.\n *\n * @example\n * try {\n * bootstrapApplication(AppComponent, appConfig);\n * } catch (e) {\n * if (e instanceof NgxThemeStackError) {\n * console.error('Bad ngx-theme-stack config:', e.message);\n * }\n * }\n */\nexport class NgxThemeStackError extends Error {\n override readonly name = 'NgxThemeStackError';\n\n constructor(message: string) {\n super(`[ngx-theme-stack] ${message}`);\n // Restore prototype chain (required when targeting ES5 or older)\n Object.setPrototypeOf(this, new.target.prototype);\n }\n}\n","/**\n * Runtime list of built-in themes.\n *\n * Lives here (and not in config/index.ts) because it defines a type:\n * config/index.ts already imports from types.ts, so placing DEFAULT_THEMES\n * here avoids any circular dependency.\n *\n * ⚠ KEEP IN SYNC with the duplicate in:\n * projects/ngx-theme-stack/schematics/ng-add/constants.ts → DEFAULT_THEMES\n *\n * Schematics compile to CommonJS and cannot import from this ESM file,\n * so the values are intentionally duplicated. Change both at the same time.\n */\nexport const DEFAULT_THEMES = ['system', 'light', 'dark'] as const;\n\n/** Literal union of built-in themes: `'system' | 'light' | 'dark'`. */\nexport type DefaultNgTheme = (typeof DEFAULT_THEMES)[number];\n\n/**\n * Theme type.\n *\n * - **Without** `T`: open union — accepts any `string` with IDE autocomplete\n * hints for the built-in themes (`'system' | 'light' | 'dark'`).\n * - **With** `T`: closed union — exactly `DefaultNgTheme | T`, enabling\n * full type-safety for custom theme sets.\n *\n * @example\n * NgTheme // 'system' | 'light' | 'dark' | (string & {})\n * NgTheme<'sepia'> // 'system' | 'light' | 'dark' | 'sepia'\n */\nexport type NgTheme<T extends string = string & {}> = DefaultNgTheme | T;\n\n/**\n * Resolved theme — always `'light'` or `'dark'`, never `'system'`.\n * Represents the value that comes from `matchMedia`, not user selection.\n */\nexport type NgSystemTheme = Exclude<DefaultNgTheme, 'system'>;\n\n/**\n * Theme application mode.\n * - `'attribute'`: sets `data-theme` attribute on `<html>`\n * - `'class'`: adds theme class to `<html>`\n * - `'both'`: uses both attribute and class\n */\nexport type NgMode = 'attribute' | 'class' | 'both';\n\n/**\n * Theme application strategy.\n * - `'blocking'`: theme CSS is loaded synchronously before rendering\n * - `'critters'`: theme CSS is inlined using Critters for SSR/SSG\n */\nexport type NgStrategy = 'blocking' | 'critters';\n\n/**\n * Library configuration.\n *\n * @typeParam T - Custom theme literals. Defaults to open `string`, preserving\n * backwards compatibility. Pass specific literals (e.g. `'sepia' | 'ocean'`)\n * via {@link provideThemeStack} to get a closed, type-safe theme union.\n */\nexport interface NgConfig<T extends string = string & {}> {\n /** The theme to use on first visit or when no preference is saved. Default: 'system'. */\n defaultTheme: NgTheme<T>;\n\n /** Key used to persist theme preference in localStorage. Default: 'ngx-theme-stack'. */\n storageKey: string;\n\n /** \n * How the theme should be applied to the document (via class, attribute or both). \n * Default: 'class'.\n */\n mode: NgMode;\n\n /** \n * Performance strategy for anti-flash.\n * Use 'critters' (default) to inline all theme CSS in <head> — works for CSR, SSR, and SSG.\n * Use 'blocking' to load themes.css as a render-blocking stylesheet (HTTP-cacheable).\n */\n strategy: NgStrategy;\n\n /**\n * The **resolved** list of supported theme identifiers, always including the\n * built-in themes (`'light'`, `'dark'`, `'system'`).\n *\n * When you pass custom themes to {@link provideThemeStack}, they are **merged**\n * with the built-in defaults — your custom values are appended after them.\n *\n * @example\n * // Input to provideThemeStack:\n * themes: ['sepia', 'ocean'] as const\n *\n * // Resolved value stored in NgConfig:\n * // ['system', 'light', 'dark', 'sepia', 'ocean']\n *\n * Default (no custom themes): `['system', 'light', 'dark']`.\n */\n themes: NgTheme<T>[];\n}\n","import { InjectionToken } from '@angular/core';\nimport { NgxThemeStackError } from '../errors';\nimport { DEFAULT_THEMES, DefaultNgTheme, NgConfig } from '../types';\n\n/**\n * ⚠ ATTENTION: SHARED CONFIGURATION VALUES\n *\n * These defaults MUST match the schematic defaults in:\n * projects/ngx-theme-stack/schematics/ng-add/constants.ts → DEFAULTS\n *\n * Schematics compile to CommonJS and cannot import from this ESM file,\n * so the values are intentionally duplicated. Change both at the same time.\n *\n * If you change defaults here, also update:\n * schematics/ng-add/constants.ts → DEFAULTS + DEFAULT_THEMES\n */\n\nexport const DEFAULT_NG_CONFIG = {\n defaultTheme: 'system',\n storageKey: 'ngx-theme-stack',\n mode: 'class',\n strategy: 'critters',\n themes: [...DEFAULT_THEMES],\n} satisfies NgConfig;\n\n// The token uses NgConfig<string> because Angular DI resolves types at runtime\n// and cannot carry generic parameters. Type-safety is enforced at the\n// provideThemeStack() call site instead.\nexport const NGX_THEME_STACK_CONFIG = new InjectionToken<NgConfig<string>>(\n 'NGX_THEME_STACK_CONFIG',\n {\n factory: () => DEFAULT_NG_CONFIG,\n },\n);\n\n/**\n * Provides Theme Stack configuration to Angular's DI system.\n *\n * The `themes` option accepts **additional** theme identifiers beyond the\n * built-in defaults. They are merged with `'light'`, `'dark'`, and `'system'`\n * so that the resolved {@link NgConfig.themes} array always includes all of\n * them — your custom values are appended after the built-ins.\n *\n * **Defaults:**\n * - `themes`: `['light', 'dark', 'system']`\n * - `defaultTheme`: `'system'`\n * - `storageKey`: `'ngx-theme-stack'`\n * - `mode`: `'class'`\n * - `strategy`: `'critters'`\n\n *\n * The type parameter `T` is **inferred automatically** from the `themes` array\n * when passed as a `const` — no need to specify it manually.\n *\n * @typeParam T - Custom theme string literals, inferred from the `themes` option.\n *\n * @param config - Optional partial configuration. Omitted fields fall back to\n * {@link DEFAULT_NG_CONFIG}.\n *\n * @throws {@link NgxThemeStackError}\n * - If any entry in `themes` is an empty or whitespace-only string.\n * - If `defaultTheme` is not present in the resolved (merged) themes array.\n * - If `storageKey` is an empty or whitespace-only string.\n *\n * @example\n * // Default — uses built-in themes and sensible defaults\n * provideThemeStack()\n *\n * @example\n * // Critters strategy — inlines all theme CSS in <head> (works for CSR, SSR, and SSG)\n * provideThemeStack({\n * strategy: 'critters',\n * mode: 'class',\n * })\n *\n * @example\n * // Closed union: TypeScript infers 'sepia' | 'ocean' from the array\n * provideThemeStack({\n * themes: ['sepia', 'ocean'] as const,\n * defaultTheme: 'sepia', // ✅ in resolved themes\n * // defaultTheme: 'nope', // ❌ throws NgxThemeStackError at runtime\n * })\n *\n * @example\n * // Custom storage key and mode\n * provideThemeStack({\n * storageKey: 'my-app-theme',\n * mode: 'attribute',\n * })\n */\nexport function provideThemeStack<const T extends string = DefaultNgTheme>(\n config: Partial<NgConfig<T>> = {},\n) {\n config.themes?.forEach((t) => {\n if (t.trim() === '') throw new NgxThemeStackError('Theme cannot be empty or whitespace.');\n });\n\n const themes = config.themes\n ? Array.from(new Set([...DEFAULT_NG_CONFIG.themes, ...config.themes]))\n : DEFAULT_NG_CONFIG.themes;\n\n if (config.defaultTheme && !(themes as string[]).includes(config.defaultTheme as string)) {\n throw new NgxThemeStackError(\n `\"defaultTheme\" must be one of the resolved themes: [${themes.join(', ')}].`,\n );\n }\n\n if (config.storageKey !== undefined && config.storageKey.trim() === '') {\n throw new NgxThemeStackError('\"storageKey\" cannot be empty or whitespace.');\n }\n\n return {\n provide: NGX_THEME_STACK_CONFIG,\n useValue: {\n ...DEFAULT_NG_CONFIG,\n ...config,\n themes,\n } as NgConfig<string>,\n };\n}\n","import { isPlatformBrowser } from '@angular/common';\nimport {\n afterNextRender,\n computed,\n DestroyRef,\n DOCUMENT,\n effect,\n inject,\n Injectable,\n PLATFORM_ID,\n signal,\n} from '@angular/core';\nimport { NGX_THEME_STACK_CONFIG } from '../config';\nimport { NgxThemeStackError } from '../errors';\nimport { NgSystemTheme, NgTheme } from '../types';\n\n/**\n * Core service for managing the application's color theme.\n *\n * Handles theme persistence, system preference detection, and DOM updates.\n * Supports built-in themes ('dark', 'light', 'system') and custom extensions.\n */\n@Injectable({ providedIn: 'root' })\nexport class CoreThemeService {\n // ── Dependencies ──────────────────────────────────────────────────────────\n\n readonly #config = inject(NGX_THEME_STACK_CONFIG);\n readonly #destroyRef = inject(DestroyRef);\n readonly #document = inject(DOCUMENT);\n readonly #isBrowser = isPlatformBrowser(inject(PLATFORM_ID));\n\n // ── Theme configuration ───────────────────────────────────────────────────\n\n /** The initial stored theme read from localStorage on startup. */\n readonly #initialStoredTheme = this.readStoredTheme();\n\n /** List of available themes for Select/Cycle services. Defaults to ['system', 'light', 'dark']. */\n readonly availableThemes = this.#config.themes;\n\n /** Internal Set for O(1) existence checks. */\n readonly #validThemes = new Set<NgTheme>(this.availableThemes);\n\n /**\n * The anti-flash class to remove from the host element.\n * Internal mechanism to bridge the gap between the blocking script's\n * initial DOM state and Angular's first effect run.\n */\n #antiFlashClass: string | null = null;\n\n // ── System preference ─────────────────────────────────────────────────────\n\n /** MediaQueryList for OS color scheme, created once and reused. Null in SSR. */\n readonly #mediaQuery: MediaQueryList | null = this.#isBrowser\n ? (this.#document.defaultView?.matchMedia('(prefers-color-scheme: dark)') ?? null)\n : null;\n\n readonly #systemPreference = signal<NgSystemTheme>(this.resolveSystemPreference());\n\n // ── Theme state ───────────────────────────────────────────────────────────\n\n readonly #selectedTheme = signal<NgTheme>(this.resolveInitialTheme());\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#selectedTheme.asReadonly();\n\n /** Resolved theme applied to the DOM. Always `'dark'` or `'light'` (or custom) — never `'system'`. */\n readonly resolvedTheme = computed(() => {\n const theme = this.#selectedTheme();\n return theme === 'system' ? this.#systemPreference() : theme;\n });\n\n /**\n * Whether the currently applied theme is dark.\n *\n * Returns `false` when a custom theme (e.g. `'sunset'`) is active — use\n * `resolvedTheme()` directly if you need to inspect the current custom theme.\n */\n readonly isDark = computed(() => this.resolvedTheme() === 'dark');\n\n /**\n * Whether the currently applied theme is light.\n *\n * Returns `false` when a custom theme (e.g. `'sepia'`) is active — use\n * `resolvedTheme()` directly if you need to inspect the current custom theme.\n */\n readonly isLight = computed(() => this.resolvedTheme() === 'light');\n\n /** Whether the currently applied theme is system. */\n readonly isSystem = computed(() => this.selectedTheme() === 'system');\n\n /**\n * Whether the service has completed client-side initialization.\n *\n * `false` during SSR and on the very first render pass before the initial theme\n * is resolved from `localStorage`. Becomes `true` immediately after the\n * first browser render pass.\n *\n * **Important:** Guard template elements that display `selectedTheme()` or\n * `resolvedTheme()` behind this signal to prevent hydration-mismatch flashes\n * (e.g. if the server renders the default 'system' but the user has 'dark' stored).\n *\n * @example\n * ```html\n * {{ theme.isHydrated() ? theme.selectedTheme() : '...' }}\n * ```\n */\n readonly #isHydrated = signal(false);\n\n readonly isHydrated = this.#isHydrated.asReadonly();\n\n // ── Event handler ─────────────────────────────────────────────────────────\n\n readonly #onSystemPreferenceChange = () =>\n this.#systemPreference.set(this.resolveSystemPreference());\n\n // ── Lifecycle ─────────────────────────────────────────────────────────────\n\n constructor() {\n this.captureAntiFlashClass();\n\n if (this.#isBrowser && this.#selectedTheme() === 'system') {\n this.startSystemThemeListener();\n }\n\n effect(() => this.applyThemeToDOM(this.resolvedTheme()));\n afterNextRender(() => this.#isHydrated.set(true));\n this.#destroyRef.onDestroy(() => this.stopSystemThemeListener());\n }\n\n // ── Public API ────────────────────────────────────────────────────────────\n\n /**\n * Changes the active theme.\n *\n * Persists the choice explicitly so that switching e.g. from `'system'` to\n * `'light'` is saved even when the resolved theme did not change\n * (system preference was already `'light'`).\n *\n * @param theme - The theme to apply: `'dark'`, `'light'`, `'system'`, or a custom theme name.\n * @throws If `theme` is not a valid theme according to library configuration.\n */\n public setTheme(theme: NgTheme): void {\n if (!this.#validThemes.has(theme)) {\n throw new NgxThemeStackError(\n `Invalid theme: \"${theme}\". Valid values are: ${[...this.#validThemes].join(', ')}.`,\n );\n }\n if (!this.#isBrowser) return;\n if (theme === this.#selectedTheme()) return;\n if (theme === 'system') {\n this.#systemPreference.set(this.resolveSystemPreference());\n this.startSystemThemeListener();\n } else {\n this.stopSystemThemeListener();\n }\n\n this.#selectedTheme.set(theme);\n this.saveTheme(theme);\n }\n\n // ── Private ───────────────────────────────────────────────────────────────\n\n private resolveSystemPreference(): NgSystemTheme {\n return this.#mediaQuery?.matches ? 'dark' : 'light';\n }\n\n private resolveInitialTheme(): NgTheme {\n const theme = this.#initialStoredTheme;\n if (theme && this.#validThemes.has(theme as NgTheme)) {\n return theme as NgTheme;\n }\n return this.#config.defaultTheme;\n }\n\n private startSystemThemeListener(): void {\n if (!this.#mediaQuery) return;\n this.stopSystemThemeListener();\n this.#mediaQuery.addEventListener('change', this.#onSystemPreferenceChange);\n }\n\n private stopSystemThemeListener(): void {\n this.#mediaQuery?.removeEventListener('change', this.#onSystemPreferenceChange);\n }\n\n private applyThemeToDOM(theme: NgTheme): void {\n if (!this.#isBrowser) return;\n\n const host = this.#document.documentElement;\n\n if (this.#antiFlashClass) {\n host.classList.remove(this.#antiFlashClass);\n this.#antiFlashClass = null;\n }\n\n const { mode } = this.#config;\n\n if (mode === 'attribute' || mode === 'both') {\n this.applyThemeAttribute(host, theme);\n }\n\n if (mode === 'class' || mode === 'both') {\n this.applyThemeClasses(host, theme);\n }\n\n this.applyColorSchemeHint(host, theme);\n }\n\n private applyThemeAttribute(host: HTMLElement, theme: NgTheme): void {\n host.setAttribute('data-theme', theme);\n }\n\n private applyThemeClasses(host: HTMLElement, theme: NgTheme): void {\n host.classList.remove(...this.availableThemes);\n host.classList.add(theme);\n }\n\n private applyColorSchemeHint(host: HTMLElement, theme: NgTheme): void {\n if (theme === 'dark' || theme === 'light') {\n host.style.setProperty('color-scheme', theme);\n return;\n }\n\n host.style.removeProperty('color-scheme');\n }\n\n private captureAntiFlashClass(): void {\n if (!this.#isBrowser || !this.#initialStoredTheme) return;\n\n if (\n !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(this.#initialStoredTheme) ||\n !this.#validThemes.has(this.#initialStoredTheme as NgTheme)\n ) {\n this.#antiFlashClass = null;\n return;\n }\n\n if (this.#initialStoredTheme === 'system') {\n this.#antiFlashClass = this.resolveSystemPreference();\n return;\n }\n\n this.#antiFlashClass = this.#initialStoredTheme;\n }\n\n private readStoredTheme(): string | null {\n if (!this.#isBrowser) return null;\n\n try {\n return localStorage.getItem(this.#config.storageKey);\n } catch (e) {\n console.warn('[ngx-theme-stack] Could not read theme from localStorage.', e);\n return null;\n }\n }\n\n private saveTheme(theme: NgTheme): void {\n if (!this.#isBrowser) return;\n\n try {\n localStorage.setItem(this.#config.storageKey, theme);\n } catch (e) {\n console.warn('[ngx-theme-stack] Could not save theme to localStorage.', e);\n }\n }\n}\n","import { computed, inject, Injectable } from '@angular/core';\nimport { CoreThemeService } from '../core/core-theme.service';\n\n/**\n * Convenience service for cycling through themes in a fixed order.\n *\n * Default cycle: `'system'` → `'light'` → `'dark'` → `'system'` → ...\n *\n * Use this when you want to offer users a single button that rotates\n * through all available theme options.\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeCycleService {\n readonly #core = inject(CoreThemeService);\n\n /** List of all configured themes for cycling. Defaults to `['light', 'dark', 'system']`. */\n readonly availableThemes = this.#core.availableThemes;\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#core.selectedTheme;\n\n /** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */\n readonly resolvedTheme = this.#core.resolvedTheme;\n\n /** Index of the currently selected theme in the cycle. */\n readonly cycleIndex = computed(() => {\n return this.availableThemes.indexOf(this.selectedTheme());\n });\n\n /** The theme that comes before the currently selected theme in the cycle. */\n readonly preceding = computed(() => {\n const index = this.cycleIndex();\n const len = this.availableThemes.length;\n return this.availableThemes[(index - 1 + len) % len];\n });\n\n /** The theme that comes after the currently selected theme in the cycle. */\n readonly upcoming = computed(() => {\n const index = this.cycleIndex();\n return this.availableThemes[(index + 1) % this.availableThemes.length];\n });\n\n /** Whether the currently applied theme is `'dark'`. */\n readonly isDark = this.#core.isDark;\n\n /** Whether the currently applied theme is `'light'`. */\n readonly isLight = this.#core.isLight;\n\n /** Whether the user has explicitly selected `'system'` preference. */\n readonly isSystem = this.#core.isSystem;\n\n /**\n * Whether the service has completed client-side initialization and\n * resolved the real persisted theme. Use to prevent hydration flashes.\n */\n readonly isHydrated = this.#core.isHydrated;\n\n /**\n * Advances to the next theme in the cycle.\n *\n * Cycle order is determined by the configured `themes` property in `NgConfig`.\n *\n * If the current theme is not found in the cycle (e.g. set externally),\n * the cycle restarts from the first theme.\n */\n cycle(): void {\n this.#core.setTheme(this.upcoming());\n }\n}\n","import { inject, Injectable } from '@angular/core';\nimport { CoreThemeService } from '../core/core-theme.service';\nimport { NgTheme } from '../types';\n\n/**\n * Convenience service for selecting a theme from a list.\n *\n * Use this when you want to bind a `<select>` or a group of radio/tab\n * buttons to the full set of available themes.\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeSelectService {\n readonly #core = inject(CoreThemeService);\n\n /** List of all configured themes. Defaults to `['light', 'dark', 'system']`. */\n readonly availableThemes = this.#core.availableThemes;\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#core.selectedTheme;\n\n /** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */\n readonly resolvedTheme = this.#core.resolvedTheme;\n\n /** Whether the currently applied theme is `'dark'`. */\n readonly isDark = this.#core.isDark;\n\n /** Whether the currently applied theme is `'light'`. */\n readonly isLight = this.#core.isLight;\n\n /** Whether the user has explicitly selected `'system'` preference. */\n readonly isSystem = this.#core.isSystem;\n\n /**\n * Whether the service has completed client-side initialization and\n * resolved the real persisted theme. Use to prevent hydration flashes.\n */\n readonly isHydrated = this.#core.isHydrated;\n\n /**\n * Applies the given theme.\n *\n * @param theme - The theme to apply: `'dark'`, `'light'`, `'system'`, or custom.\n * @throws If `theme` is not a valid theme according to library configuration.\n */\n select(theme: NgTheme): void {\n this.#core.setTheme(theme);\n }\n}\n","import { inject, Injectable } from '@angular/core';\nimport { CoreThemeService } from '../core/core-theme.service';\n\n/**\n * Convenience service for toggling between `'dark'` and `'light'`.\n *\n * Use this when you only need a simple on/off switch and do not\n * need to manage `'system'` or cycle through themes.\n */\n@Injectable({ providedIn: 'root' })\nexport class ThemeToggleService {\n readonly #core = inject(CoreThemeService);\n\n /** Resolved theme currently applied to the DOM. Always concrete — never `'system'`. */\n readonly resolvedTheme = this.#core.resolvedTheme;\n\n /** The theme explicitly selected by the user. May be `'system'`. */\n readonly selectedTheme = this.#core.selectedTheme;\n\n /** Whether the currently applied theme is `'dark'`. */\n readonly isDark = this.#core.isDark;\n\n /** Whether the currently applied theme is `'light'`. */\n readonly isLight = this.#core.isLight;\n\n /** Whether the user has explicitly selected `'system'` preference. */\n readonly isSystem = this.#core.isSystem;\n\n /**\n * Whether the service has completed client-side initialization and\n * resolved the real persisted theme. Use to prevent hydration flashes.\n */\n readonly isHydrated = this.#core.isHydrated;\n\n /**\n * Toggles between `'dark'` and `'light'`.\n *\n * If the selected theme is explicitly `'dark'`, switches to `'light'`.\n * Otherwise (including `'system'`), switches to `'dark'`.\n */\n toggle(): void {\n const next = this.#core.resolvedTheme() === 'dark' ? 'light' : 'dark';\n this.#core.setTheme(next);\n }\n}\n","/*\n * Public API Surface of ngx-theme-stack\n */\n\nexport * from './lib/core/core-theme.service';\nexport * from './lib/config';\nexport * from './lib/services/theme-cycle.service';\nexport * from './lib/services/theme-select.service';\nexport * from './lib/services/theme-toggle.service';\nexport * from './lib/types';\nexport * from './lib/errors';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ngx-theme-stack",
3
- "version": "3.7.0",
3
+ "version": "3.8.2",
4
4
  "description": "A stack of themes for Angular applications.",
5
5
  "keywords": [
6
6
  "angular",
@@ -1,36 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.patchIndexHtml = patchIndexHtml;
4
- /**
5
- * Generates a minimal blocking inline script that applies the stored theme
6
- * to `<html>` before the browser paints.
7
- *
8
- * This is the single source of truth for the anti-flash script logic.
9
- * Schematics compile to CommonJS (Node.js) and cannot import from the
10
- * library's ESM build, so this logic lives here — close to its only consumer.
11
- *
12
- * The generated script:
13
- * 1. Reads `localStorage` for the stored theme key.
14
- * 2. Validates the value using a Regex to prevent injections.
15
- * 3. Falls back to `defaultTheme`; resolves `'system'` via `matchMedia`.
16
- * 4. Applies the theme according to the configured `mode` (class, attribute, or both).
17
- * 5. Sets the `color-scheme` CSS property for native browser adaptation.
18
- */
19
- function buildAntiFlashScript(options) {
20
- const { storageKey, defaultTheme, mode } = options;
21
- return (`(function(){try{` +
22
- `var k=${JSON.stringify(storageKey)},` +
23
- `d=${JSON.stringify(defaultTheme)},` +
24
- `m=${JSON.stringify(mode)},` +
25
- `t=localStorage.getItem(k)||d,` +
26
- `e=document.documentElement;` +
27
- `if(!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(t))t=d;` +
28
- `if(t==='system')t=window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';` +
29
- `if(m==='class'||m==='both')e.classList.add(t);` +
30
- `if(m==='attribute'||m==='both')e.setAttribute('data-theme',t);` +
31
- `if(t==='dark'||t==='light')e.style.setProperty('color-scheme',t);` +
32
- `}catch(x){}})();`);
33
- }
4
+ const anti_flash_script_1 = require("../utils/anti-flash-script");
34
5
  /**
35
6
  * Finds `index.html` and injects the anti-flash blocking script as the very
36
7
  * first child of `<head>`. This is intentional: the script must run before
@@ -55,10 +26,11 @@ function patchIndexHtml(tree, context, sourceRoot, options) {
55
26
  if (!tree.exists(path))
56
27
  continue;
57
28
  const content = tree.readText(path);
58
- const scriptTag = `\n <!-- ngx-theme-stack anti-flash -->\n <script>${buildAntiFlashScript({
29
+ const scriptTag = `\n <!-- ngx-theme-stack anti-flash -->\n <script>${(0, anti_flash_script_1.buildAntiFlashScript)({
59
30
  storageKey: options.storageKey,
60
31
  defaultTheme: options.defaultTheme,
61
32
  mode: options.mode,
33
+ themes: options.themes,
62
34
  })}</script>`;
63
35
  let updated = content;
64
36
  // ── 1. Update Anti-Flash Script ──────────────────────────────────────────
@@ -1 +1 @@
1
- {"version":3,"file":"anti-flash.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/ng-add/anti-flash.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"anti-flash.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/ng-add/anti-flash.ts"],"names":[],"mappings":"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"}
@@ -43,7 +43,7 @@ function buildProvideCall(defaultTheme, storageKey, mode, themes, strategy) {
43
43
  const themesArr = themes.map((t) => `'${t}'`).join(', ');
44
44
  return [
45
45
  'provideThemeStack({',
46
- ` themes: [${themesArr}],`,
46
+ ` themes: [${themesArr}] as const,`,
47
47
  ` defaultTheme: '${defaultTheme}',`,
48
48
  ` storageKey: '${storageKey}',`,
49
49
  ` mode: '${mode}',`,
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/ng-add/utils.ts"],"names":[],"mappings":";;;;;;;;;;;AAKA,4BAEC;AAKD,kBAEC;AAMD,0BAWC;AAED,4CAiBC;AAlDD,qCAAqC;AAErC;;GAEG;AACH,SAAgB,QAAQ;IACtB,OAAO,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,SAAgB,GAAG,CAAC,EAAsB,EAAE,QAAgB;IAC1D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC;AAED;;;GAGG;AACH,SAAsB,OAAO;yDAC3B,EAAsB,EACtB,KAAa,EACb,KAAwB,EACxB,YAAY,GAAG,CAAC;QAEhB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,aAAa,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpF,CAAC;CAAA;AAED,SAAgB,gBAAgB,CAC9B,YAAoB,EACpB,UAAkB,EAClB,IAAY,EACZ,MAAgB,EAChB,QAAgB;IAEhB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO;QACL,qBAAqB;QACrB,kBAAkB,SAAS,IAAI;QAC/B,wBAAwB,YAAY,IAAI;QACxC,sBAAsB,UAAU,IAAI;QACpC,gBAAgB,IAAI,IAAI;QACxB,oBAAoB,QAAQ,IAAI;QAChC,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/ng-add/utils.ts"],"names":[],"mappings":";;;;;;;;;;;AAKA,4BAEC;AAKD,kBAEC;AAMD,0BAWC;AAED,4CAiBC;AAlDD,qCAAqC;AAErC;;GAEG;AACH,SAAgB,QAAQ;IACtB,OAAO,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;AACpF,CAAC;AAED;;GAEG;AACH,SAAgB,GAAG,CAAC,EAAsB,EAAE,QAAgB;IAC1D,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC;AAED;;;GAGG;AACH,SAAsB,OAAO;yDAC3B,EAAsB,EACtB,KAAa,EACb,KAAwB,EACxB,YAAY,GAAG,CAAC;QAEhB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,CAAC;QACvC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC;QAC5E,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,EAAE,EAAE,aAAa,YAAY,GAAG,CAAC,KAAK,CAAC,CAAC;QAC9D,MAAM,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAC5B,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IACpF,CAAC;CAAA;AAED,SAAgB,gBAAgB,CAC9B,YAAoB,EACpB,UAAkB,EAClB,IAAY,EACZ,MAAgB,EAChB,QAAgB;IAEhB,MAAM,SAAS,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACzD,OAAO;QACL,qBAAqB;QACrB,kBAAkB,SAAS,aAAa;QACxC,wBAAwB,YAAY,IAAI;QACxC,sBAAsB,UAAU,IAAI;QACpC,gBAAgB,IAAI,IAAI;QACxB,oBAAoB,QAAQ,IAAI;QAChC,QAAQ;KACT,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -111,8 +111,9 @@ export const appConfig: ApplicationConfig = {
111
111
 
112
112
  All services expose these signals: \`selectedTheme()\`, \`resolvedTheme()\`, \`isDark()\`, \`isLight()\`, \`isSystem()\`, \`isHydrated()\`.
113
113
 
114
- For complete component templates, copy from \`assets/\` directory in this skill folder.
115
- For full API details, read \`references/api-reference.md\`.
114
+ Ver [ejemplo Toggle](assets/theme-toggle.ts) · [ejemplo Cycle](assets/theme-cycle.ts) · [ejemplo Select](assets/theme-select.ts)
115
+
116
+ For full API details, read [references/api-reference.md](references/api-reference.md).
116
117
 
117
118
  ## SSR Hydration Guard & Layout Stability
118
119
 
@@ -120,7 +121,7 @@ Guard theme-dependent template content behind \`isHydrated()\` in SSR to prevent
120
121
 
121
122
  \`\`\`html
122
123
  @if (theme.isHydrated()) {
123
- <img [src]="theme.isDark() ? 'dark-logo.png' : 'light-logo.png'">
124
+ <img [src]="theme.isDark() ? darkLogo : lightLogo">
124
125
  } @else {
125
126
  <!-- The placeholder/skeleton MUST match the exact size and spacing of the hydrated image -->
126
127
  <div class="logo-skeleton" style="width: 150px; height: 40px; display: inline-block;"></div>
@@ -303,13 +304,8 @@ Inherits: \`selectedTheme()\`, \`resolvedTheme()\`, \`isDark()\`, \`isLight()\`,
303
304
 
304
305
  Catch with: \`if (e instanceof NgxThemeStackError) { ... }\`
305
306
  `;
306
- // ── assets/ templates (Tier 3 — copied on demand) ───────────────────────────
307
- const TEMPLATE_TOGGLE = `# Theme Toggle Component
308
-
309
- A simple button component to toggle between light and dark themes.
310
-
311
- \`\`\`typescript
312
- import { inject, Component } from '@angular/core';
307
+ // ── assets/ component examples (Tier 3 — pure TypeScript, read on demand) ───
308
+ const TEMPLATE_TOGGLE = `import { inject, Component } from '@angular/core';
313
309
  import { ThemeToggleService } from 'ngx-theme-stack';
314
310
 
315
311
  @Component({
@@ -327,23 +323,15 @@ import { ThemeToggleService } from 'ngx-theme-stack';
327
323
  export class ThemeToggle {
328
324
  protected readonly theme = inject(ThemeToggleService);
329
325
  }
330
- \`\`\`
331
326
  `;
332
- const TEMPLATE_CYCLE = `# Theme Cycle Component
333
-
334
- A button component to cycle through all available themes.
335
-
336
- \`\`\`typescript
337
- import { inject, Component } from '@angular/core';
327
+ const TEMPLATE_CYCLE = `import { inject, Component } from '@angular/core';
338
328
  import { ThemeCycleService } from 'ngx-theme-stack';
339
329
 
340
330
  @Component({
341
331
  selector: 'app-theme-cycle',
342
332
  template: \`
343
333
  @if (theme.isHydrated()) {
344
- <button (click)="theme.cycle()">
345
- 🔄 Cycle Theme
346
- </button>
334
+ <button (click)="theme.cycle()">🔄 Cycle Theme</button>
347
335
  } @else {
348
336
  <div class="theme-cycle-skeleton"></div>
349
337
  }
@@ -352,14 +340,8 @@ import { ThemeCycleService } from 'ngx-theme-stack';
352
340
  export class ThemeCycle {
353
341
  protected readonly theme = inject(ThemeCycleService);
354
342
  }
355
- \`\`\`
356
343
  `;
357
- const TEMPLATE_SELECT = `# Theme Select Component
358
-
359
- A dropdown select component to choose any available theme.
360
-
361
- \`\`\`typescript
362
- import { inject, Component } from '@angular/core';
344
+ const TEMPLATE_SELECT = `import { inject, Component } from '@angular/core';
363
345
  import { ThemeSelectService } from 'ngx-theme-stack';
364
346
 
365
347
  @Component({
@@ -386,16 +368,15 @@ export class ThemeSelect {
386
368
  this.theme.select(value);
387
369
  }
388
370
  }
389
- \`\`\`
390
371
  `;
391
372
  // ── Schematic logic ─────────────────────────────────────────────────────────
392
373
  const SKILL_ROOT = '.agents/skills/ngx-theme-stack';
393
374
  const FILES = [
394
375
  { path: `${SKILL_ROOT}/SKILL.md`, content: SKILL_CONTENT },
395
376
  { path: `${SKILL_ROOT}/references/api-reference.md`, content: API_REFERENCE },
396
- { path: `${SKILL_ROOT}/assets/theme-toggle.component.md`, content: TEMPLATE_TOGGLE },
397
- { path: `${SKILL_ROOT}/assets/theme-cycle.component.md`, content: TEMPLATE_CYCLE },
398
- { path: `${SKILL_ROOT}/assets/theme-select.component.md`, content: TEMPLATE_SELECT },
377
+ { path: `${SKILL_ROOT}/assets/theme-toggle.ts`, content: TEMPLATE_TOGGLE },
378
+ { path: `${SKILL_ROOT}/assets/theme-cycle.ts`, content: TEMPLATE_CYCLE },
379
+ { path: `${SKILL_ROOT}/assets/theme-select.ts`, content: TEMPLATE_SELECT },
399
380
  ];
400
381
  function generateSkill(tree, context) {
401
382
  for (const file of FILES) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/skill/index.ts"],"names":[],"mappings":";;AAyZA,sCAUC;AAED,sBAMC;AAxaD,+EAA+E;AAE/E,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiKrB,CAAC;AAEF,+EAA+E;AAE/E,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwIrB,CAAC;AAEF,+EAA+E;AAE/E,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBvB,CAAC;AAEF,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwBtB,CAAC;AAEF,MAAM,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCvB,CAAC;AAEF,+EAA+E;AAE/E,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD,MAAM,KAAK,GAAwC;IACjD,EAAE,IAAI,EAAE,GAAG,UAAU,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE;IAC1D,EAAE,IAAI,EAAE,GAAG,UAAU,8BAA8B,EAAE,OAAO,EAAE,aAAa,EAAE;IAC7E,EAAE,IAAI,EAAE,GAAG,UAAU,mCAAmC,EAAE,OAAO,EAAE,eAAe,EAAE;IACpF,EAAE,IAAI,EAAE,GAAG,UAAU,kCAAkC,EAAE,OAAO,EAAE,cAAc,EAAE;IAClF,EAAE,IAAI,EAAE,GAAG,UAAU,mCAAmC,EAAE,OAAO,EAAE,eAAe,EAAE;CACrF,CAAC;AAEF,SAAgB,aAAa,CAAC,IAAU,EAAE,OAAyB;IACjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,IAAI,YAAY,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,IAAU,EAAE,OAAyB,EAAE,EAAE;QAC/C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/skill/index.ts"],"names":[],"mappings":";;AAyYA,sCAUC;AAED,sBAMC;AAxZD,+EAA+E;AAE/E,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkKrB,CAAC;AAEF,+EAA+E;AAE/E,MAAM,aAAa,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAwIrB,CAAC;AAEF,+EAA+E;AAE/E,MAAM,eAAe,GACrB;;;;;;;;;;;;;;;;;;CAkBC,CAAC;AAEF,MAAM,cAAc,GACpB;;;;;;;;;;;;;;;;CAgBC,CAAC;AAEF,MAAM,eAAe,GACrB;;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BC,CAAC;AAEF,+EAA+E;AAE/E,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD,MAAM,KAAK,GAAwC;IACjD,EAAE,IAAI,EAAE,GAAG,UAAU,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE;IAC1D,EAAE,IAAI,EAAE,GAAG,UAAU,8BAA8B,EAAE,OAAO,EAAE,aAAa,EAAE;IAC7E,EAAE,IAAI,EAAE,GAAG,UAAU,yBAAyB,EAAE,OAAO,EAAE,eAAe,EAAE;IAC1E,EAAE,IAAI,EAAE,GAAG,UAAU,wBAAwB,EAAE,OAAO,EAAE,cAAc,EAAE;IACxE,EAAE,IAAI,EAAE,GAAG,UAAU,yBAAyB,EAAE,OAAO,EAAE,eAAe,EAAE;CAC3E,CAAC;AAEF,SAAgB,aAAa,CAAC,IAAU,EAAE,OAAyB;IACjE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3B,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACxC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,IAAI,YAAY,CAAC,CAAC;QACtE,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,yBAAyB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAgB,KAAK,CAAC,OAAe;IACnC,OAAO,CAAC,IAAU,EAAE,OAAyB,EAAE,EAAE;QAC/C,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,0CAA0C,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QACjF,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC,CAAC;AACJ,CAAC"}
@@ -13,6 +13,7 @@ exports.sync = sync;
13
13
  const app_config_1 = require("../ng-add/app-config");
14
14
  const utils_1 = require("../ng-add/utils");
15
15
  const constants_1 = require("../ng-add/constants");
16
+ const anti_flash_script_1 = require("../utils/anti-flash-script");
16
17
  // ── Regex patterns ────────────────────────────────────────────────────────────
17
18
  /**
18
19
  * Matches the provideThemeStack() call in app.config.ts.
@@ -96,25 +97,6 @@ function extractConfig(tree, sourceRoot, context) {
96
97
  };
97
98
  }
98
99
  // ── Anti-flash script generation ──────────────────────────────────────────────
99
- /**
100
- * Builds the minimal blocking inline script — identical logic to anti-flash.ts
101
- * but kept here to avoid cross-directory dependencies in the schematic build.
102
- */
103
- function buildScript(config) {
104
- const { storageKey, defaultTheme, mode } = config;
105
- return (`(function(){try{` +
106
- `var k=${JSON.stringify(storageKey)},` +
107
- `d=${JSON.stringify(defaultTheme)},` +
108
- `m=${JSON.stringify(mode)},` +
109
- `t=localStorage.getItem(k)||d,` +
110
- `e=document.documentElement;` +
111
- `if(!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(t))t=d;` +
112
- `if(t==='system')t=window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';` +
113
- `if(m==='class'||m==='both')e.classList.add(t);` +
114
- `if(m==='attribute'||m==='both')e.setAttribute('data-theme',t);` +
115
- `if(t==='dark'||t==='light')e.style.setProperty('color-scheme',t);` +
116
- `}catch(x){}})();`);
117
- }
118
100
  // ── Critters Trick div generation ─────────────────────────────────────────────
119
101
  /**
120
102
  * Generates the hidden divs for the Critters Trick based on the mode.
@@ -213,7 +195,7 @@ function sync(options) {
213
195
  let content = tree.readText(path);
214
196
  let changed = false;
215
197
  if (content.includes('ngx-theme-stack anti-flash')) {
216
- const newScriptBlock = `<!-- ngx-theme-stack anti-flash -->\n <script>${buildScript(config)}</script>`;
198
+ const newScriptBlock = `<!-- ngx-theme-stack anti-flash -->\n <script>${(0, anti_flash_script_1.buildAntiFlashScript)(config)}</script>`;
217
199
  if (SCRIPT_BLOCK_RE.test(content)) {
218
200
  const updatedScript = content.replace(SCRIPT_BLOCK_RE, newScriptBlock);
219
201
  if (updatedScript !== content) {
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/sync/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/sync/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ export interface AntiFlashScriptOptions {
2
+ storageKey: string;
3
+ defaultTheme: string;
4
+ mode: string;
5
+ themes: string[];
6
+ }
7
+ /**
8
+ * Generates a minimal blocking inline script that applies the stored theme
9
+ * to `<html>` before the browser paints.
10
+ *
11
+ * This is the single source of truth for the anti-flash script logic, shared
12
+ * between ng-add and sync schematics.
13
+ */
14
+ export declare function buildAntiFlashScript(options: AntiFlashScriptOptions): string;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAntiFlashScript = buildAntiFlashScript;
4
+ /**
5
+ * Generates a minimal blocking inline script that applies the stored theme
6
+ * to `<html>` before the browser paints.
7
+ *
8
+ * This is the single source of truth for the anti-flash script logic, shared
9
+ * between ng-add and sync schematics.
10
+ */
11
+ function buildAntiFlashScript(options) {
12
+ const { storageKey, defaultTheme, mode, themes } = options;
13
+ return (`(function(){try{` +
14
+ `var k=${JSON.stringify(storageKey)},` +
15
+ `d=${JSON.stringify(defaultTheme)},` +
16
+ `m=${JSON.stringify(mode)},` +
17
+ `v=${JSON.stringify(themes)},` +
18
+ `t=localStorage.getItem(k)||d,` +
19
+ `e=document.documentElement;` +
20
+ `if(!/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(t)||v.indexOf(t)===-1)t=d;` +
21
+ `if(t==='system')t=window.matchMedia('(prefers-color-scheme: dark)').matches?'dark':'light';` +
22
+ `if(m==='class'||m==='both')e.classList.add(t);` +
23
+ `if(m==='attribute'||m==='both')e.setAttribute('data-theme',t);` +
24
+ `if(t==='dark'||t==='light')e.style.setProperty('color-scheme',t);` +
25
+ `}catch(x){}})();`);
26
+ }
27
+ //# sourceMappingURL=anti-flash-script.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"anti-flash-script.js","sourceRoot":"","sources":["../../../../projects/ngx-theme-stack/schematics/utils/anti-flash-script.ts"],"names":[],"mappings":";;AAcA,oDAkBC;AAzBD;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAAC,OAA+B;IAClE,MAAM,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAE3D,OAAO,CACL,kBAAkB;QAClB,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG;QACtC,KAAK,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,GAAG;QACpC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG;QAC5B,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;QAC9B,+BAA+B;QAC/B,6BAA6B;QAC7B,gEAAgE;QAChE,6FAA6F;QAC7F,gDAAgD;QAChD,gEAAgE;QAChE,mEAAmE;QACnE,kBAAkB,CACnB,CAAC;AACJ,CAAC"}
@@ -121,23 +121,7 @@ declare class CoreThemeService {
121
121
  readonly isLight: _angular_core.Signal<boolean>;
122
122
  /** Whether the currently applied theme is system. */
123
123
  readonly isSystem: _angular_core.Signal<boolean>;
124
- /**
125
- * Whether the service has completed client-side initialization.
126
- *
127
- * `false` during SSR and on the very first render pass before the initial theme
128
- * is resolved from `localStorage`. Becomes `true` immediately after the
129
- * first browser render pass.
130
- *
131
- * **Important:** Guard template elements that display `selectedTheme()` or
132
- * `resolvedTheme()` behind this signal to prevent hydration-mismatch flashes
133
- * (e.g. if the server renders the default 'system' but the user has 'dark' stored).
134
- *
135
- * @example
136
- * ```html
137
- * {{ theme.isHydrated() ? theme.selectedTheme() : '...' }}
138
- * ```
139
- */
140
- readonly isHydrated: _angular_core.WritableSignal<boolean>;
124
+ readonly isHydrated: _angular_core.Signal<boolean>;
141
125
  constructor();
142
126
  /**
143
127
  * Changes the active theme.