@marianmeres/stuic 3.89.0 → 3.91.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,9 +3,22 @@
3
3
  export interface Props {}
4
4
  </script>
5
5
 
6
+ <script lang="ts">
7
+ import { ColorScheme } from "./color-scheme.svelte.js";
8
+ $effect(() => {
9
+ // Bootstrap <script> below has run by the time this effect fires;
10
+ // re-seed the runtime from whatever the DOM is now showing.
11
+ ColorScheme.syncFromDom();
12
+ });
13
+ </script>
14
+
6
15
  <!--
7
- Similar to PrefersColorScheme, except that it never reads window.matchMedia and only
8
- relies on the local userland setting
16
+ Similar to ColorSchemeSystemAware, except that it never reads window.matchMedia and only
17
+ relies on the local userland setting.
18
+
19
+ Uses the hardcoded default storage key "stuic-color-scheme". Apps that
20
+ override the runtime key via `ColorScheme.configure({ key })` should ship
21
+ their own inline bootstrap in `app.html` if FOUC-free hydration matters.
9
22
  -->
10
23
  <svelte:head>
11
24
  <script>
@@ -1,21 +1,6 @@
1
1
  /** ColorSchemeLocal has no props - it's a pure hydration component */
2
2
  export interface Props {
3
3
  }
4
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
- $$bindings?: Bindings;
7
- } & Exports;
8
- (internal: unknown, props: {
9
- $$events?: Events;
10
- $$slots?: Slots;
11
- }): Exports & {
12
- $set?: any;
13
- $on?: any;
14
- };
15
- z_$$bindings?: Bindings;
16
- }
17
- declare const ColorSchemeLocal: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {}, {}, string>;
20
- type ColorSchemeLocal = InstanceType<typeof ColorSchemeLocal>;
4
+ declare const ColorSchemeLocal: import("svelte").Component<Record<string, never>, {}, "">;
5
+ type ColorSchemeLocal = ReturnType<typeof ColorSchemeLocal>;
21
6
  export default ColorSchemeLocal;
@@ -3,8 +3,21 @@
3
3
  export interface Props {}
4
4
  </script>
5
5
 
6
+ <script lang="ts">
7
+ import { ColorScheme } from "./color-scheme.svelte.js";
8
+ $effect(() => {
9
+ // Bootstrap <script> below has run by the time this effect fires;
10
+ // re-seed the runtime from whatever the DOM is now showing.
11
+ ColorScheme.syncFromDom();
12
+ });
13
+ </script>
14
+
6
15
  <!--
7
- If you do not wish to take the system preference into account use LocalColorScheme sibling
16
+ If you do not wish to take the system preference into account use ColorSchemeLocal sibling.
17
+
18
+ Uses the hardcoded default storage key "stuic-color-scheme". Apps that
19
+ override the runtime key via `ColorScheme.configure({ key })` should ship
20
+ their own inline bootstrap in `app.html` if FOUC-free hydration matters.
8
21
  -->
9
22
  <svelte:head>
10
23
  <script>
@@ -1,21 +1,6 @@
1
1
  /** ColorSchemeSystemAware has no props - it's a pure hydration component */
2
2
  export interface Props {
3
3
  }
4
- interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
5
- new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
6
- $$bindings?: Bindings;
7
- } & Exports;
8
- (internal: unknown, props: {
9
- $$events?: Events;
10
- $$slots?: Slots;
11
- }): Exports & {
12
- $set?: any;
13
- $on?: any;
14
- };
15
- z_$$bindings?: Bindings;
16
- }
17
- declare const ColorSchemeSystemAware: $$__sveltets_2_IsomorphicComponent<Record<string, never>, {
18
- [evt: string]: CustomEvent<any>;
19
- }, {}, {}, string>;
20
- type ColorSchemeSystemAware = InstanceType<typeof ColorSchemeSystemAware>;
4
+ declare const ColorSchemeSystemAware: import("svelte").Component<Record<string, never>, {}, "">;
5
+ type ColorSchemeSystemAware = ReturnType<typeof ColorSchemeSystemAware>;
21
6
  export default ColorSchemeSystemAware;
@@ -0,0 +1,84 @@
1
+ type Scheme = "dark" | "light";
2
+ /**
3
+ * A utility class for managing light/dark color scheme preferences.
4
+ *
5
+ * Handles localStorage persistence and DOM class toggling.
6
+ * Works with Tailwind CSS dark mode (class-based strategy).
7
+ *
8
+ * The `ColorScheme.current` getter is reactive (Svelte 5 `$state`): reading it
9
+ * inside a `$derived`/`$effect`/template will react to toggles and cross-tab
10
+ * `storage` events.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * // Reactive current value (use in templates / $derived / $effect):
15
+ * const scheme = ColorScheme.current; // 'light' or 'dark'
16
+ *
17
+ * // Toggle between light and dark
18
+ * ColorScheme.toggle();
19
+ *
20
+ * // Reset to system preference
21
+ * ColorScheme.reset();
22
+ *
23
+ * // Use a custom localStorage key (call early in app boot):
24
+ * ColorScheme.configure({ key: "myapp:color-scheme" });
25
+ * ```
26
+ *
27
+ * @remarks
28
+ * - Default localStorage key: "stuic-color-scheme" (override via `configure`)
29
+ * - Adds/removes "dark" class on `<html>` element
30
+ * - Works with Tailwind's `darkMode: 'class'` configuration
31
+ * - Pair with `<ColorSchemeLocal />` or `<ColorSchemeSystemAware />` for
32
+ * FOUC-free initial paint
33
+ */
34
+ export declare class ColorScheme {
35
+ static readonly DARK: "dark";
36
+ static readonly LIGHT: "light";
37
+ /**
38
+ * The active localStorage key. Default is `"stuic-color-scheme"`. Override via
39
+ * `ColorScheme.configure({ key })` or the `key` prop on the hydration components.
40
+ */
41
+ static get KEY(): string;
42
+ /**
43
+ * Configure the runtime. Call early in app boot, before any consumer reads
44
+ * `ColorScheme.current`. Mutates module state; safe to call more than once
45
+ * (last write wins). Calling without changes is a no-op.
46
+ */
47
+ static configure(opts: {
48
+ key?: string;
49
+ }): void;
50
+ /**
51
+ * Reactive current value. Read inside `$derived`, `$effect`, or a Svelte
52
+ * template to react to scheme changes (including cross-tab `storage` events).
53
+ */
54
+ static get current(): Scheme;
55
+ /**
56
+ * Re-seed `current` from the actual `<html>` class state. Used by the
57
+ * hydration components after their inline bootstrap `<script>` has run, so
58
+ * the runtime matches whichever strategy actually painted the DOM. Does NOT
59
+ * write to the DOM.
60
+ */
61
+ static syncFromDom(): void;
62
+ /**
63
+ * Reads the `prefers-color-scheme` system setting
64
+ */
65
+ static getSystemValue(): Scheme;
66
+ /**
67
+ * Reads locally (localStorage) saved value
68
+ */
69
+ static getLocalValue(fallback?: Scheme): Scheme;
70
+ /**
71
+ * Backward-compatible alias for `current`.
72
+ */
73
+ static getValue(): Scheme;
74
+ /**
75
+ * Toggles between light and dark, persists to localStorage, and updates the DOM.
76
+ */
77
+ static toggle(): void;
78
+ /**
79
+ * Resets color scheme to system preference by removing the localStorage value
80
+ * and re-applying the resolved scheme.
81
+ */
82
+ static reset(): void;
83
+ }
84
+ export {};
@@ -0,0 +1,142 @@
1
+ const DEFAULT_KEY = "stuic-color-scheme";
2
+ let _key = DEFAULT_KEY;
3
+ let _current = $state("light");
4
+ function _compute() {
5
+ const local = globalThis.localStorage?.getItem(_key);
6
+ if (local === "dark" || local === "light")
7
+ return local;
8
+ return ColorScheme.getSystemValue();
9
+ }
10
+ function _applyDom(scheme) {
11
+ globalThis?.document?.documentElement.classList.toggle(ColorScheme.DARK, scheme === ColorScheme.DARK);
12
+ }
13
+ function _sync() {
14
+ const next = _compute();
15
+ if (next !== _current) {
16
+ _current = next;
17
+ _applyDom(next);
18
+ }
19
+ }
20
+ /**
21
+ * A utility class for managing light/dark color scheme preferences.
22
+ *
23
+ * Handles localStorage persistence and DOM class toggling.
24
+ * Works with Tailwind CSS dark mode (class-based strategy).
25
+ *
26
+ * The `ColorScheme.current` getter is reactive (Svelte 5 `$state`): reading it
27
+ * inside a `$derived`/`$effect`/template will react to toggles and cross-tab
28
+ * `storage` events.
29
+ *
30
+ * @example
31
+ * ```ts
32
+ * // Reactive current value (use in templates / $derived / $effect):
33
+ * const scheme = ColorScheme.current; // 'light' or 'dark'
34
+ *
35
+ * // Toggle between light and dark
36
+ * ColorScheme.toggle();
37
+ *
38
+ * // Reset to system preference
39
+ * ColorScheme.reset();
40
+ *
41
+ * // Use a custom localStorage key (call early in app boot):
42
+ * ColorScheme.configure({ key: "myapp:color-scheme" });
43
+ * ```
44
+ *
45
+ * @remarks
46
+ * - Default localStorage key: "stuic-color-scheme" (override via `configure`)
47
+ * - Adds/removes "dark" class on `<html>` element
48
+ * - Works with Tailwind's `darkMode: 'class'` configuration
49
+ * - Pair with `<ColorSchemeLocal />` or `<ColorSchemeSystemAware />` for
50
+ * FOUC-free initial paint
51
+ */
52
+ export class ColorScheme {
53
+ static DARK = "dark";
54
+ static LIGHT = "light";
55
+ /**
56
+ * The active localStorage key. Default is `"stuic-color-scheme"`. Override via
57
+ * `ColorScheme.configure({ key })` or the `key` prop on the hydration components.
58
+ */
59
+ static get KEY() {
60
+ return _key;
61
+ }
62
+ /**
63
+ * Configure the runtime. Call early in app boot, before any consumer reads
64
+ * `ColorScheme.current`. Mutates module state; safe to call more than once
65
+ * (last write wins). Calling without changes is a no-op.
66
+ */
67
+ static configure(opts) {
68
+ if (opts?.key && opts.key !== _key) {
69
+ _key = opts.key;
70
+ _sync();
71
+ }
72
+ }
73
+ /**
74
+ * Reactive current value. Read inside `$derived`, `$effect`, or a Svelte
75
+ * template to react to scheme changes (including cross-tab `storage` events).
76
+ */
77
+ static get current() {
78
+ return _current;
79
+ }
80
+ /**
81
+ * Re-seed `current` from the actual `<html>` class state. Used by the
82
+ * hydration components after their inline bootstrap `<script>` has run, so
83
+ * the runtime matches whichever strategy actually painted the DOM. Does NOT
84
+ * write to the DOM.
85
+ */
86
+ static syncFromDom() {
87
+ if (typeof document === "undefined")
88
+ return;
89
+ const next = document.documentElement.classList.contains(ColorScheme.DARK)
90
+ ? ColorScheme.DARK
91
+ : ColorScheme.LIGHT;
92
+ if (next !== _current)
93
+ _current = next;
94
+ }
95
+ /**
96
+ * Reads the `prefers-color-scheme` system setting
97
+ */
98
+ static getSystemValue() {
99
+ return globalThis.matchMedia?.(`(prefers-color-scheme: ${ColorScheme.DARK})`).matches
100
+ ? ColorScheme.DARK
101
+ : ColorScheme.LIGHT;
102
+ }
103
+ /**
104
+ * Reads locally (localStorage) saved value
105
+ */
106
+ static getLocalValue(fallback = "light") {
107
+ return globalThis.localStorage?.getItem(_key) || fallback;
108
+ }
109
+ /**
110
+ * Backward-compatible alias for `current`.
111
+ */
112
+ static getValue() {
113
+ return _current;
114
+ }
115
+ /**
116
+ * Toggles between light and dark, persists to localStorage, and updates the DOM.
117
+ */
118
+ static toggle() {
119
+ const next = _current === ColorScheme.DARK ? ColorScheme.LIGHT : ColorScheme.DARK;
120
+ globalThis.localStorage?.setItem(_key, next);
121
+ _applyDom(next);
122
+ _current = next;
123
+ }
124
+ /**
125
+ * Resets color scheme to system preference by removing the localStorage value
126
+ * and re-applying the resolved scheme.
127
+ */
128
+ static reset() {
129
+ globalThis.localStorage?.removeItem(_key);
130
+ _sync();
131
+ }
132
+ }
133
+ if (typeof window !== "undefined") {
134
+ // Seed from localStorage (with system-pref fallback). Reading from the DOM
135
+ // here is unreliable: module init runs before the hydration component's
136
+ // inline <script> is appended to <head>, so the dark class isn't there yet.
137
+ _current = _compute();
138
+ window.addEventListener("storage", (e) => {
139
+ if (e.key === _key)
140
+ _sync();
141
+ });
142
+ }
@@ -1,3 +1,3 @@
1
- export * from "./color-scheme.js";
1
+ export * from "./color-scheme.svelte.js";
2
2
  export { default as ColorSchemeLocal, type Props as ColorSchemeLocalProps, } from "./ColorSchemeLocal.svelte";
3
3
  export { default as ColorSchemeSystemAware, type Props as ColorSchemeSystemAwareProps, } from "./ColorSchemeSystemAware.svelte";
@@ -1,3 +1,3 @@
1
- export * from "./color-scheme.js";
1
+ export * from "./color-scheme.svelte.js";
2
2
  export { default as ColorSchemeLocal, } from "./ColorSchemeLocal.svelte";
3
3
  export { default as ColorSchemeSystemAware, } from "./ColorSchemeSystemAware.svelte";
@@ -205,14 +205,13 @@
205
205
  colorScheme === false ? false : cs.enabled !== false /* default true */
206
206
  );
207
207
 
208
- function readIsDark(): boolean {
209
- return cs.isDark ? cs.isDark() : ColorScheme.getValue() === "dark";
210
- }
211
-
212
- let isDark = $state(false);
213
- $effect(() => {
214
- if (csEnabled) isDark = readIsDark();
215
- });
208
+ const isDark = $derived(
209
+ csEnabled
210
+ ? cs.isDark
211
+ ? cs.isDark()
212
+ : ColorScheme.current === "dark"
213
+ : false
214
+ );
216
215
 
217
216
  function toggleColorScheme() {
218
217
  if (cs.onToggle) {
@@ -220,7 +219,6 @@
220
219
  } else {
221
220
  ColorScheme.toggle();
222
221
  }
223
- isDark = readIsDark();
224
222
  }
225
223
 
226
224
  // Default labels (English)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marianmeres/stuic",
3
- "version": "3.89.0",
3
+ "version": "3.91.0",
4
4
  "scripts": {
5
5
  "dev": "vite dev",
6
6
  "build": "vite build && pnpm run prepack",
@@ -1,51 +0,0 @@
1
- /**
2
- * A utility class for managing light/dark color scheme preferences.
3
- *
4
- * Handles system preferences, localStorage persistence, and DOM class toggling.
5
- * Works with Tailwind CSS dark mode (class-based strategy).
6
- *
7
- * @example
8
- * ```ts
9
- * // Get current color scheme (local preference or system default)
10
- * const scheme = ColorScheme.getValue(); // 'light' or 'dark'
11
- *
12
- * // Toggle between light and dark
13
- * ColorScheme.toggle();
14
- *
15
- * // Check system preference only
16
- * const systemPref = ColorScheme.getSystemValue();
17
- *
18
- * // Reset to system preference
19
- * ColorScheme.reset();
20
- * ```
21
- *
22
- * @remarks
23
- * - Uses localStorage key: "stuic-color-scheme"
24
- * - Adds/removes "dark" class on `<html>` element
25
- * - Works with Tailwind's `darkMode: 'class'` configuration
26
- */
27
- export declare class ColorScheme {
28
- static readonly KEY: "stuic-color-scheme";
29
- static readonly DARK: "dark";
30
- static readonly LIGHT: "light";
31
- /**
32
- * Reads the `prefers-color-scheme` system setting
33
- */
34
- static getSystemValue(): "dark" | "light";
35
- /**
36
- * Reads locally (localStorage) saved value
37
- */
38
- static getLocalValue(fallback?: "dark" | "light"): "dark" | "light";
39
- /**
40
- * Tries local first, fallbacks to system
41
- */
42
- static getValue(): "dark" | "light";
43
- /**
44
- * Sets and saves the opposite of current.
45
- */
46
- static toggle(): void;
47
- /**
48
- * Resets color scheme to system preference by removing localStorage value and classes.
49
- */
50
- static reset(): void;
51
- }
@@ -1,66 +0,0 @@
1
- /**
2
- * A utility class for managing light/dark color scheme preferences.
3
- *
4
- * Handles system preferences, localStorage persistence, and DOM class toggling.
5
- * Works with Tailwind CSS dark mode (class-based strategy).
6
- *
7
- * @example
8
- * ```ts
9
- * // Get current color scheme (local preference or system default)
10
- * const scheme = ColorScheme.getValue(); // 'light' or 'dark'
11
- *
12
- * // Toggle between light and dark
13
- * ColorScheme.toggle();
14
- *
15
- * // Check system preference only
16
- * const systemPref = ColorScheme.getSystemValue();
17
- *
18
- * // Reset to system preference
19
- * ColorScheme.reset();
20
- * ```
21
- *
22
- * @remarks
23
- * - Uses localStorage key: "stuic-color-scheme"
24
- * - Adds/removes "dark" class on `<html>` element
25
- * - Works with Tailwind's `darkMode: 'class'` configuration
26
- */
27
- export class ColorScheme {
28
- static KEY = "stuic-color-scheme";
29
- static DARK = "dark";
30
- static LIGHT = "light";
31
- /**
32
- * Reads the `prefers-color-scheme` system setting
33
- */
34
- static getSystemValue() {
35
- return globalThis.matchMedia?.(`(prefers-color-scheme: ${ColorScheme.DARK})`).matches
36
- ? ColorScheme.DARK
37
- : ColorScheme.LIGHT;
38
- }
39
- /**
40
- * Reads locally (localStorage) saved value
41
- */
42
- static getLocalValue(fallback = "light") {
43
- return (globalThis.localStorage?.getItem(ColorScheme.KEY) || fallback);
44
- }
45
- /**
46
- * Tries local first, fallbacks to system
47
- */
48
- static getValue() {
49
- return ColorScheme.getLocalValue(ColorScheme.getSystemValue());
50
- }
51
- /**
52
- * Sets and saves the opposite of current.
53
- */
54
- static toggle() {
55
- // returns bool, indicating whether token is in the list after the call or not.
56
- const isDark = globalThis?.document?.documentElement.classList.toggle(ColorScheme.DARK);
57
- globalThis.localStorage?.setItem(ColorScheme.KEY, isDark ? ColorScheme.DARK : ColorScheme.LIGHT);
58
- }
59
- /**
60
- * Resets color scheme to system preference by removing localStorage value and classes.
61
- */
62
- static reset() {
63
- globalThis.localStorage?.removeItem(ColorScheme.KEY);
64
- globalThis?.document?.documentElement.classList.remove(ColorScheme.DARK, ColorScheme.LIGHT);
65
- }
66
- }