@brandon_m_behring/book-scaffold-astro 4.14.1 → 4.14.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/CLAUDE.md CHANGED
@@ -106,6 +106,28 @@ Two callout families coexist. Authors import what they need.
106
106
 
107
107
  Full reference in `recipes/04-component-library.md`.
108
108
 
109
+ ### Theme-change event (v4.14.2)
110
+
111
+ `Base.astro` emits `book:theme:change` on `window` whenever the **effective** theme changes — both the chrome's dark-mode toggle and a system `prefers-color-scheme` flip (the latter only when no explicit theme is pinned). Use it for **canvas / JS islands** that can't recolor via CSS alone; CSS-token elements recolor automatically from the `[data-theme]` attribute.
112
+
113
+ ```ts
114
+ // inside a Preact island (client:visible / client:idle)
115
+ function currentTheme(): 'light' | 'dark' {
116
+ const t = document.documentElement.getAttribute('data-theme');
117
+ return t === 'light' || t === 'dark'
118
+ ? t
119
+ : matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
120
+ }
121
+ useEffect(() => {
122
+ draw(currentTheme()); // initial paint
123
+ const onChange = (e: Event) => draw((e as CustomEvent).detail.theme);
124
+ window.addEventListener('book:theme:change', onChange);
125
+ return () => window.removeEventListener('book:theme:change', onChange);
126
+ }, []);
127
+ ```
128
+
129
+ `detail.theme` is `'light' | 'dark'`. Pull design-token colors via `getComputedStyle(document.documentElement).getPropertyValue('--…')` so the canvas matches the page, and respect `prefers-reduced-motion` for any redraw animation. (Event-only by design — a `useThemeColors` helper graduates with the demo kit, #103.)
130
+
109
131
  ## Citation patterns
110
132
 
111
133
  Academic profile uses BibTeX → `references.json`:
@@ -176,21 +176,47 @@ const ogDescription = description ?? bookConfig.description ?? '';
176
176
  ) : (
177
177
  <main><slot /></main>
178
178
  )}
179
+ {/*
180
+ Theme-change hook (#103, v4.14.2). Whenever the EFFECTIVE theme changes,
181
+ emit `book:theme:change` on `window` with `detail.theme` ∈ {'light','dark'}.
182
+ CSS recolors via the `data-theme` attribute alone; canvas/JS islands can't,
183
+ so they subscribe to this event (and read the attribute / matchMedia on
184
+ mount for the initial value) to redraw. Contract documented in the package
185
+ CLAUDE.md. Event-only by design — a `useThemeColors` helper graduates later
186
+ with the demo kit.
187
+ */}
179
188
  <script is:inline>
180
189
  (function () {
190
+ var root = document.documentElement;
191
+ function effectiveTheme() {
192
+ var explicit = root.getAttribute('data-theme');
193
+ if (explicit === 'light' || explicit === 'dark') return explicit;
194
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
195
+ }
196
+ function emitThemeChange() {
197
+ window.dispatchEvent(new CustomEvent('book:theme:change', { detail: { theme: effectiveTheme() } }));
198
+ }
181
199
  var btn = document.getElementById('theme-toggle');
182
- if (!btn) return;
183
- btn.addEventListener('click', function () {
184
- var current = document.documentElement.getAttribute('data-theme');
185
- // If no explicit theme, pick the opposite of prefers-color-scheme.
186
- if (!current) {
187
- var prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
188
- current = prefersDark ? 'dark' : 'light';
189
- }
190
- var next = current === 'dark' ? 'light' : 'dark';
191
- document.documentElement.setAttribute('data-theme', next);
192
- try { localStorage.setItem('theme', next); } catch (e) {}
193
- });
200
+ if (btn) {
201
+ btn.addEventListener('click', function () {
202
+ var current = root.getAttribute('data-theme');
203
+ // If no explicit theme, pick the opposite of prefers-color-scheme.
204
+ if (!current) {
205
+ current = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
206
+ }
207
+ var next = current === 'dark' ? 'light' : 'dark';
208
+ root.setAttribute('data-theme', next);
209
+ try { localStorage.setItem('theme', next); } catch (e) {}
210
+ emitThemeChange();
211
+ });
212
+ }
213
+ // A system-preference flip only changes the effective theme when no
214
+ // explicit theme is pinned — emit then so islands can redraw too.
215
+ try {
216
+ window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', function () {
217
+ if (!root.getAttribute('data-theme')) emitThemeChange();
218
+ });
219
+ } catch (e) { /* older browsers: no media-query change events */ }
194
220
  })();
195
221
  </script>
196
222
  </body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@brandon_m_behring/book-scaffold-astro",
3
3
  "description": "Astro 6 + MDX toolkit for long-form technical books. Profile-aware (academic / tools / minimal); ships Tufte typography, KaTeX, BibTeX citations, Pagefind, Cloudflare Workers deploy. See PACKAGE_DESIGN.md for the API contract.",
4
- "version": "4.14.1",
4
+ "version": "4.14.2",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": "Brandon Behring",