spark-html-theme 0.1.0 → 0.1.1

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
@@ -39,7 +39,8 @@ npm install spark-html-theme
39
39
  |--------------|---------|
40
40
  | `mode` | The user's choice: `'system'` \| `'light'` \| `'dark'`. |
41
41
  | `resolved` | What actually applies right now: `'light'` \| `'dark'`. |
42
- | `toggle()` | Cycle to the next mode (in `modes` order) and persist. |
42
+ | `toggle()` | Flip the visible theme (light↔dark) **always a visible change**. Best for a single toggle button. Persists. |
43
+ | `cycle()` | Advance through `modes` (tri-state, includes `'system'`). Adjacent modes can look identical. Persists. |
43
44
  | `set(mode)` | Jump to a specific mode and persist. |
44
45
 
45
46
  Both `mode` and `resolved` are reactive — read them in any component via
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spark-html-theme",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "One-line dark/light/system theming for spark-html — a reactive `theme` store, data-theme attribute, system watch, and localStorage persistence.",
5
5
  "type": "module",
6
6
  "main": "./src/index.js",
package/src/index.d.ts CHANGED
@@ -8,8 +8,10 @@ export interface ThemeStore {
8
8
  mode: string;
9
9
  /** What actually applies right now: 'light' | 'dark'. */
10
10
  resolved: string;
11
- /** Cycle to the next mode (in `modes` order) and persist. */
11
+ /** Flip the visible theme (light↔dark) always a visible change. Persists. */
12
12
  toggle(): void;
13
+ /** Advance through `modes` (tri-state incl. 'system'); persists. */
14
+ cycle(): void;
13
15
  /** Jump to a specific mode and persist. */
14
16
  set(mode: string): void;
15
17
  }
package/src/index.js CHANGED
@@ -17,9 +17,10 @@
17
17
  * </script>
18
18
  *
19
19
  * `mode` is the user's choice ('system' | 'light' | 'dark'); `resolved` is what
20
- * actually applies ('light' | 'dark'); `toggle()` cycles through `modes`;
21
- * `set(mode)` jumps to one. The chosen `resolved` is written to
22
- * `document.documentElement` as `data-theme`.
20
+ * actually applies ('light' | 'dark'); `toggle()` flips the visible theme
21
+ * (light↔dark always a visible change); `cycle()` advances through `modes`
22
+ * (tri-state, including 'system'); `set(mode)` jumps to one. The chosen
23
+ * `resolved` is written to `document.documentElement` as `data-theme`.
23
24
  *
24
25
  * No-flash tip: a deferred module runs after first paint, so to avoid a flash of
25
26
  * the wrong theme add this tiny inline script to <head> (it mirrors the same
@@ -70,11 +71,20 @@ export function theme(options = {}) {
70
71
  write(mode);
71
72
  apply();
72
73
  }
74
+ // Flip the VISIBLE theme. Always changes appearance on every call — the right
75
+ // behaviour for a single toggle button. (A naive system→light→dark cycle can
76
+ // land on two visually-identical states in a row — e.g. explicit "dark" then
77
+ // "system" when the OS is dark — which feels like the click did nothing.)
73
78
  function toggle() {
79
+ set(s.resolved === 'dark' ? 'light' : 'dark');
80
+ }
81
+ // Advance through `modes` (includes 'system'). Use for a tri-state control;
82
+ // note adjacent modes can resolve to the same appearance.
83
+ function cycle() {
74
84
  set(modes[(modes.indexOf(s.mode) + 1) % modes.length]);
75
85
  }
76
86
 
77
- const s = store(name, { mode: initial, resolved: resolve(initial), toggle, set });
87
+ const s = store(name, { mode: initial, resolved: resolve(initial), toggle, cycle, set });
78
88
 
79
89
  apply();
80
90
  if (mq && mq.addEventListener) mq.addEventListener('change', apply);