@codenhub/theme 0.0.1 → 0.0.3

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/dist/index.d.ts CHANGED
@@ -1,12 +1,12 @@
1
- //#region src/index.d.ts
2
- /** Window event name dispatched with `ThemeChangeDetail` after a theme change is applied in browser environments. */
3
- declare const THEME_CHANGE_EVENT = "themechange";
1
+ //#region src/types.d.ts
4
2
  /** Theme option stored, applied to the configured DOM attribute, and mapped to the browser color scheme. */
5
- interface ThemeDefinition {
3
+ interface ThemeDefinition<TSchema extends Record<string, string> = Record<string, string>> {
6
4
  /** Unique configured theme name used for storage, DOM attributes, and generated default classes. */
7
5
  name: string;
8
6
  /** Browser color scheme applied to `document.documentElement.style.colorScheme`. */
9
7
  colorScheme: "light" | "dark";
8
+ /** Optional theme-specific static token values. */
9
+ tokens?: Partial<Record<keyof TSchema, string>>;
10
10
  }
11
11
  /** Mapping from OS color-scheme preferences to configured theme names. */
12
12
  interface SystemThemeMap {
@@ -16,24 +16,24 @@ interface SystemThemeMap {
16
16
  dark: string;
17
17
  }
18
18
  /** Resolves the single DOM class token applied for a theme when custom class application is enabled. */
19
- type ThemeClassResolver = (theme: ThemeDefinition) => string;
19
+ type ThemeClassResolver<TSchema extends Record<string, string> = Record<string, string>> = (theme: ThemeDefinition<TSchema>) => string;
20
20
  /** Reason a theme change notification was emitted. */
21
21
  type ThemeChangeSource = "init" | "set" | "toggle" | "clearPreference" | "system";
22
22
  /** Payload passed to subscribers and the browser `themechange` event after a theme change. */
23
- interface ThemeChangeDetail {
23
+ interface ThemeChangeDetail<TSchema extends Record<string, string> = Record<string, string>> {
24
24
  /** Active theme name after the change. */
25
25
  name: string;
26
26
  /** Active theme definition after the change. */
27
- theme: ThemeDefinition;
27
+ theme: ThemeDefinition<TSchema>;
28
28
  /** Operation or browser signal that caused the change notification. */
29
29
  source: ThemeChangeSource;
30
30
  }
31
31
  /** In-process callback registered with `Theme.subscribe()` for applied theme changes. */
32
- type ThemeChangeListener = (detail: ThemeChangeDetail) => void;
32
+ type ThemeChangeListener<TSchema extends Record<string, string> = Record<string, string>> = (detail: ThemeChangeDetail<TSchema>) => void;
33
33
  /** Configuration for theme definitions, persistence, DOM application, and system preference mapping. */
34
- interface ThemeOptions {
35
- /** Available themes. Names must be unique, non-empty, and valid default class tokens when `applyClass` is `true`. */
36
- themes?: readonly ThemeDefinition[];
34
+ interface ThemeOptions<TSchema extends Record<string, string> = Record<string, string>> {
35
+ /** Available themes. Names must be unique, non-empty, and valid default class tokens when `shouldApplyClass` is `true`. */
36
+ themes?: readonly ThemeDefinition<TSchema>[];
37
37
  /** Configured theme name used before initialization and when browser APIs are unavailable. */
38
38
  defaultTheme?: string;
39
39
  /** Configured theme names selected for OS light and dark color-scheme preferences. */
@@ -43,42 +43,116 @@ interface ThemeOptions {
43
43
  /** Attribute set on `document.documentElement` with the active theme name. */
44
44
  attribute?: string;
45
45
  /** Whether to toggle Tailwind CSS's `dark` class for themes with `colorScheme: "dark"`. */
46
- tailwindcss?: boolean;
46
+ isTailwindCss?: boolean;
47
47
  /** Whether and how to apply a theme-specific class to `document.documentElement`. */
48
- applyClass?: boolean | ThemeClassResolver;
48
+ shouldApplyClass?: boolean | ThemeClassResolver<TSchema>;
49
+ /** Schema mapping theme token names to their corresponding CSS Custom Property names. */
50
+ tokenSchema?: TSchema;
49
51
  }
50
- /** Built-in light theme used by default and available for custom theme lists. */
51
- declare const lightTheme: ThemeDefinition;
52
- /** Built-in dark theme used by default and available for custom theme lists. */
53
- declare const darkTheme: ThemeDefinition;
54
52
  /**
55
- * Manages theme preference, DOM application, system preference changes, and change notifications.
56
- *
57
- * The constructor validates configured theme names, default and system mappings, and default class tokens.
58
- * Theme application throws `Error` when a requested theme is missing or a class resolver returns an invalid class token.
53
+ * Core theme preference handler. Manages initialization, switching themes,
54
+ * persistence to localStorage, synchronizing with the OS prefers-color-scheme preference,
55
+ * dynamic token mapping to CSS Custom Properties, and dispatching change events.
59
56
  */
60
- declare class Theme {
61
- #private;
62
- /** Creates a theme manager with default light/dark themes unless overridden. */
63
- constructor(options?: ThemeOptions);
64
- /** Registers system preference handling, applies the initial theme, emits an `init` change, and returns this instance. */
65
- init(): this;
66
- /** Returns the currently active theme definition. */
67
- get(): ThemeDefinition;
68
- /** Applies a configured theme by name, stores it when possible, emits a `set` change, and throws `Error` for unknown names. */
69
- set(name: string): ThemeDefinition;
70
- /** Toggles between the configured system light and dark themes, stores the preference when possible, and emits a `toggle` change. */
71
- toggle(): ThemeDefinition;
72
- /** Removes the stored preference when possible, applies the current system theme, and emits a `clearPreference` change. */
73
- clearPreference(): ThemeDefinition;
74
- /** Returns the stored configured theme name, or `null` during SSR, storage failures, or invalid stored preferences. */
57
+ interface Theme<TSchema extends Record<string, string> = Record<string, string>> {
58
+ /**
59
+ * Initializes the theme manager. Resolves the active theme (using the stored preference if valid,
60
+ * falling back to the current OS color-scheme preference), applies classes/attributes to the DOM,
61
+ * and registers the media query listener for automatic system preference updates.
62
+ *
63
+ * @param tokens - Optional runtime override token values to merge and apply.
64
+ * @returns The current `Theme` manager instance for method chaining.
65
+ * @sideEffect Registers a media query event listener on `window` and updates root DOM element attributes/styles. Dispatches a "themechange" event.
66
+ */
67
+ init(tokens?: Partial<Record<keyof TSchema, string>>): this;
68
+ /**
69
+ * Retrieves the active theme configuration including static and computed tokens.
70
+ *
71
+ * Token values are merged in this priority order (last wins):
72
+ * 1. CSS computed style — values read from `window.getComputedStyle` for tokens not defined in JS.
73
+ * 2. Theme static tokens — values defined in `ThemeDefinition.tokens` for the active theme.
74
+ * 3. Runtime overrides — values passed to `init()`, `set()`, `toggle()`, or other methods.
75
+ *
76
+ * @returns The active `ThemeDefinition` object. If `tokenSchema` is configured and a token is not
77
+ * explicitly defined in JS, its value is dynamically resolved from the computed style of the root DOM element in browser environments.
78
+ * @warning Reading computed styles from the DOM via `window.getComputedStyle` can trigger a synchronous layout reflow. Avoid calling `get()` frequently or inside high-performance loops.
79
+ */
80
+ get(): ThemeDefinition<TSchema>;
81
+ /**
82
+ * Activates a configured theme by name and updates the stored preference in `localStorage`.
83
+ *
84
+ * @param name - The name of the configured theme to activate.
85
+ * @param tokens - Optional runtime override token values to apply. Active overrides persist across subsequent theme changes unless cleared (by passing new overrides or an empty object).
86
+ * @returns The activated `ThemeDefinition` with merged and resolved tokens.
87
+ * @throws {Error} If the specified theme name is not found in the configured themes list.
88
+ * @sideEffect Updates root DOM attributes, colorscheme styles, classes, and saves preference to `localStorage`. Dispatches a "themechange" event.
89
+ */
90
+ set(name: string, tokens?: Partial<Record<keyof TSchema, string>>): ThemeDefinition<TSchema>;
91
+ /**
92
+ * Switches the theme between the configured system light and dark themes and persists the change.
93
+ * The next theme is always selected from `systemTheme.light` or `systemTheme.dark` based on the
94
+ * active theme's `colorScheme`, not by cycling the active theme name. In multi-theme setups where
95
+ * the active theme is not one of the system themes, `toggle()` still targets `systemTheme.light`
96
+ * or `systemTheme.dark`.
97
+ *
98
+ * @param tokens - Optional runtime override token values to apply. Active overrides persist across subsequent theme changes unless cleared (by passing new overrides or an empty object).
99
+ * @returns The activated `ThemeDefinition` with merged and resolved tokens.
100
+ * @sideEffect Updates root DOM attributes, colorscheme styles, classes, and saves preference to `localStorage`. Dispatches a "themechange" event.
101
+ */
102
+ toggle(tokens?: Partial<Record<keyof TSchema, string>>): ThemeDefinition<TSchema>;
103
+ /**
104
+ * Removes the explicit user theme preference from storage and resets the theme to match the OS system preference.
105
+ *
106
+ * @returns The activated system `ThemeDefinition` with merged and resolved tokens.
107
+ * @sideEffect Deletes the storage key from `localStorage`, updates root DOM attributes, styles, classes. Dispatches a "themechange" event.
108
+ */
109
+ clearPreference(): ThemeDefinition<TSchema>;
110
+ /**
111
+ * Retrieves the currently stored theme preference name from `localStorage`.
112
+ *
113
+ * @returns The stored theme name if valid and currently configured; otherwise `null` (e.g. during SSR, if storage is empty/unavailable, or if the stored theme name is not configured).
114
+ */
75
115
  getStored(): string | null;
76
- /** Returns the configured theme for the current OS color-scheme preference, or the default theme without browser support. */
77
- getSystem(): ThemeDefinition;
78
- /** Registers a listener for in-process theme changes and returns an unsubscribe function. */
79
- subscribe(listener: ThemeChangeListener): () => void;
80
- /** Removes the system preference listener and clears in-process subscribers. */
116
+ /**
117
+ * Resolves the configured theme that matches the active OS color-scheme preference.
118
+ *
119
+ * @returns The matching `ThemeDefinition`. Falls back to the default theme during SSR or if `matchMedia` is unavailable.
120
+ */
121
+ getSystem(): ThemeDefinition<TSchema>;
122
+ /**
123
+ * Registers a callback listener to receive notifications when the theme or its tokens change.
124
+ *
125
+ * @param listener - Callback function invoked on theme changes.
126
+ * @returns An unsubscribe function to remove the registered listener.
127
+ * @sideEffect Adds the listener to the internal callbacks registry.
128
+ */
129
+ subscribe(listener: ThemeChangeListener<TSchema>): () => void;
130
+ /**
131
+ * Cleans up the theme instance by removing all in-process change listeners and the system
132
+ * preference media query listener. Resets active tokens and the active theme name to the
133
+ * configured `defaultTheme` so the instance can be safely re-initialized with `init()`.
134
+ *
135
+ * @sideEffect Removes event listeners from `window` and clears internal subscriber sets.
136
+ */
81
137
  destroy(): void;
82
138
  }
83
139
  //#endregion
84
- export { SystemThemeMap, THEME_CHANGE_EVENT, Theme, ThemeChangeDetail, ThemeChangeListener, ThemeChangeSource, ThemeClassResolver, ThemeDefinition, ThemeOptions, darkTheme, lightTheme };
140
+ //#region src/constants.d.ts
141
+ /** Window event name dispatched with `ThemeChangeDetail` after a theme change is applied in browser environments. */
142
+ declare const THEME_CHANGE_EVENT = "themechange";
143
+ /** Built-in light theme used by default and available for custom theme lists. */
144
+ declare const LIGHT_THEME: ThemeDefinition;
145
+ /** Built-in dark theme used by default and available for custom theme lists. */
146
+ declare const DARK_THEME: ThemeDefinition;
147
+ //#endregion
148
+ //#region src/theme.d.ts
149
+ /**
150
+ * Factory function that creates and returns a `Theme` instance.
151
+ *
152
+ * @param options - Configuration options for theme definitions, persistence keys, DOM attributes, custom class resolvers, and dynamic token schemas.
153
+ * @returns A `Theme` instance.
154
+ * @throws {Error} If configured theme names are empty, duplicated, invalid for CSS class application, or if the default/system themes are not present in the configured list.
155
+ */
156
+ declare function createTheme<TSchema extends Record<string, string> = Record<string, string>>(options?: ThemeOptions<TSchema>): Theme<TSchema>;
157
+ //#endregion
158
+ export { DARK_THEME, LIGHT_THEME, type SystemThemeMap, THEME_CHANGE_EVENT, type Theme, type ThemeChangeDetail, type ThemeChangeListener, type ThemeChangeSource, type ThemeClassResolver, type ThemeDefinition, type ThemeOptions, createTheme };