@happyvertical/smrt-ui 0.57.39 → 0.57.40

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/AGENTS.md CHANGED
@@ -84,6 +84,11 @@ own theme provider or static preset stylesheet.
84
84
 
85
85
  ## Theme presets
86
86
 
87
+ Only a root `ThemeProvider` writes the document attributes (`<html>` `data-theme`,
88
+ `data-color-scheme`, `dark`, `data-contrast`, `data-density`). A nested one is
89
+ `scope="local"` by default and themes its own wrapper only; `scope="document"`
90
+ opts back in (#4485).
91
+
87
92
  Adding or editing a preset touches four things that must stay in lockstep:
88
93
  `src/themes/<id>/index.ts` (the `Theme`), the `ThemePreset` union in
89
94
  `src/themes/types.ts`, the `registry.ts` entry, and the static
@@ -2,7 +2,11 @@
2
2
  import type { Snippet } from 'svelte';
3
3
  import { onMount, untrack } from 'svelte';
4
4
  import { SMRT_CASCADE_LAYERS_CSS } from '../styles/layers.js';
5
- import { setThemeContext, type ThemeContext } from './context.svelte.js';
5
+ import {
6
+ setThemeContext,
7
+ type ThemeContext,
8
+ tryGetThemeContext,
9
+ } from './context.svelte.js';
6
10
  import { derivePrimaryOverrides } from './create-theme.js';
7
11
  import { generateThemeVariables } from './css-generator.js';
8
12
  import { FORCED_COLORS_TOKENS } from './forced-colors.js';
@@ -56,6 +60,16 @@ interface Props {
56
60
  * static stylesheet for a built-in preset.
57
61
  */
58
62
  inlineVariables?: boolean;
63
+ /**
64
+ * Where the theme attributes land. `document` (the default for a root
65
+ * provider) also stamps `data-theme`, `data-color-scheme`, the `dark` class,
66
+ * `color-scheme`, `data-contrast`, `data-density` and
67
+ * `data-smrt-theme-changing` onto `<html>`. `local` themes only this
68
+ * provider's own wrapper and never touches the document. A provider nested
69
+ * inside another `ThemeProvider` is `local` by default, so an embedded
70
+ * widget cannot retheme its host page (#4485).
71
+ */
72
+ scope?: 'document' | 'local';
59
73
  /** Content */
60
74
  children: Snippet;
61
75
  }
@@ -70,6 +84,7 @@ let {
70
84
  persist = defaultThemeConfig.persist,
71
85
  storageKey = defaultThemeConfig.storageKey,
72
86
  inlineVariables,
87
+ scope,
73
88
  children,
74
89
  density,
75
90
  contrast = 'auto',
@@ -318,6 +333,13 @@ const context: ThemeContext = {
318
333
  updateConfig,
319
334
  };
320
335
 
336
+ // Resolved before this provider registers itself: a parent context means this
337
+ // provider is nested, so it themes its own subtree only unless told otherwise.
338
+ // Fixed at creation: a provider does not move between root and nested.
339
+ const writesDocument = untrack(
340
+ () => (scope ?? (tryGetThemeContext() ? 'local' : 'document')) === 'document',
341
+ );
342
+
321
343
  setThemeContext(context);
322
344
 
323
345
  onMount(() => {
@@ -362,7 +384,7 @@ onMount(() => {
362
384
 
363
385
  // Update document classes and attributes
364
386
  $effect(() => {
365
- if (typeof document !== 'undefined' && mounted) {
387
+ if (typeof document !== 'undefined' && mounted && writesDocument) {
366
388
  const html = document.documentElement;
367
389
 
368
390
  // Dark mode class for Tailwind/tailwindcss-dark-mode compatibility
@@ -422,7 +444,7 @@ $effect(() => {
422
444
  });
423
445
 
424
446
  $effect(() => {
425
- if (typeof document === 'undefined' || !mounted) return;
447
+ if (typeof document === 'undefined' || !mounted || !writesDocument) return;
426
448
  document.documentElement.toggleAttribute(
427
449
  'data-smrt-theme-changing',
428
450
  isChangingScheme,
@@ -38,6 +38,16 @@ interface Props {
38
38
  * static stylesheet for a built-in preset.
39
39
  */
40
40
  inlineVariables?: boolean;
41
+ /**
42
+ * Where the theme attributes land. `document` (the default for a root
43
+ * provider) also stamps `data-theme`, `data-color-scheme`, the `dark` class,
44
+ * `color-scheme`, `data-contrast`, `data-density` and
45
+ * `data-smrt-theme-changing` onto `<html>`. `local` themes only this
46
+ * provider's own wrapper and never touches the document. A provider nested
47
+ * inside another `ThemeProvider` is `local` by default, so an embedded
48
+ * widget cannot retheme its host page (#4485).
49
+ */
50
+ scope?: 'document' | 'local';
41
51
  /** Content */
42
52
  children: Snippet;
43
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ThemeProvider.svelte.d.ts","sourceRoot":"","sources":["../../src/themes/ThemeProvider.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAQtC,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAGlB,WAAW,EACX,WAAW,EAEZ,MAAM,YAAY,CAAC;AAIpB,UAAU,KAAK;IACb,wFAAwF;IACxF,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC3C,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AAkfD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
1
+ {"version":3,"file":"ThemeProvider.svelte.d.ts","sourceRoot":"","sources":["../../src/themes/ThemeProvider.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAYtC,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAGlB,WAAW,EACX,WAAW,EAEZ,MAAM,YAAY,CAAC;AAIpB,UAAU,KAAK;IACb,wFAAwF;IACxF,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC;IACjC;;;OAGG;IACH,QAAQ,CAAC,EAAE,kBAAkB,CAAC;IAC9B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8BAA8B;IAC9B,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,+BAA+B;IAC/B,YAAY,CAAC,EAAE,WAAW,CAAC,cAAc,CAAC,CAAC;IAC3C,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;OAQG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAC7B,cAAc;IACd,QAAQ,EAAE,OAAO,CAAC;CACnB;AA0fD,QAAA,MAAM,aAAa,2CAAwC,CAAC;AAC5D,KAAK,aAAa,GAAG,UAAU,CAAC,OAAO,aAAa,CAAC,CAAC;AACtD,eAAe,aAAa,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-ui",
3
- "version": "0.57.39",
3
+ "version": "0.57.40",
4
4
  "smrtJsdoc": "strict",
5
5
  "description": "Domain-agnostic Svelte 5 UI runtime for SMRT: primitives, i18n client, theme system, and module UI registry",
6
6
  "type": "module",
@@ -176,7 +176,7 @@
176
176
  "access": "public"
177
177
  },
178
178
  "dependencies": {
179
- "@happyvertical/smrt-types": "0.57.39",
179
+ "@happyvertical/smrt-types": "0.57.40",
180
180
  "esm-env": "^1.2.2"
181
181
  },
182
182
  "peerDependencies": {