@pie-players/pie-theme 0.3.67 → 0.3.69

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
@@ -2,6 +2,11 @@
2
2
 
3
3
  Shared PIE theming primitives and the `pie-theme` custom element.
4
4
 
5
+ This file is the reference. For how the pieces fit — why a host stylesheet
6
+ cannot override a mounted element, what the provider choice actually decides, and
7
+ how a host carries an accommodation into its own chrome — see
8
+ [`docs/theming/how-theming-works.md`](../../docs/theming/how-theming-works.md).
9
+
5
10
  `pie-theme` resolves PIE theme tokens (`--pie-*`) with this precedence:
6
11
 
7
12
  1. Base PIE theme (`theme=light|dark|auto`)
@@ -177,6 +182,59 @@ cascade requirements are intentional. Such a selector follows the normal
177
182
  cascade in a stylesheet-only integration; when it competes with a mounted
178
183
  `<pie-theme>`'s inline tokens, it needs `!important`.
179
184
 
185
+ ## SchoolCity scheme parity
186
+
187
+ SchoolCity offers 15 schemes. Four are built in here — Black on White, White on
188
+ Black, Black on Rose, Yellow on Blue — and the other eleven are host palettes a
189
+ programme registers itself, from these values:
190
+
191
+ | SchoolCity token | Value |
192
+ | --- | --- |
193
+ | blue | `#0028a1` |
194
+ | red | `#bf0d00` |
195
+ | green | `#008272` |
196
+ | yellow | `#ffe072` |
197
+ | light gray | `#c0c3cf` |
198
+ | dark gray | `#9297a6` |
199
+ | rose | `#f8d1ce` |
200
+
201
+ All 15 clear 4.5:1 for ordinary text; Green on White is the tightest at 4.73:1.
202
+ Ordinary text is not the whole cost, though, because the light base chose every
203
+ semantic colour against white. What an overlay has to carry scales with how far
204
+ its background sits from white:
205
+
206
+ | Background | Tokens | Why |
207
+ | --- | --- | --- |
208
+ | white | 2 | ink and page; every base colour already holds |
209
+ | white, with a mid-tone ink | 4 | the ink misses the tinted recessed surfaces |
210
+ | `#000000` | 10 | inverted page; borrow the dark base theme's inks |
211
+ | mid-tone (blue, red, green, dark gray) | ~18 | neither light nor dark inks hold, so icons, boundaries and focus rings are re-chosen too |
212
+
213
+ ```ts
214
+ registerPieColorSchemes([
215
+ {
216
+ id: "sc-blue-on-white",
217
+ name: "Blue on White",
218
+ variables: { "--pie-text": "#0028a1", "--pie-background": "#ffffff" },
219
+ },
220
+ ]);
221
+ ```
222
+
223
+ `packages/theme/tests/schoolcity-scheme-registration.test.ts` carries a validated
224
+ palette for one scheme of each cost class and is the place to copy from.
225
+
226
+ Read the receipt. Contrast diagnostics are warnings, not errors, because the
227
+ palette is host-owned — a two-token White on Blue registers successfully and
228
+ returns fourteen warnings, and a host that filters on `severity === "error"`
229
+ ships cyan links on a mid-blue page. `registerPieColorSchemes` checks only the
230
+ relationships whose tokens the overlay touches, so covering a flagged token is
231
+ what clears its relationship.
232
+
233
+ These are host palettes rather than built-ins on purpose. A built-in is a full
234
+ 48-token palette, since a two-colour scheme is a promise the whole surface has to
235
+ keep, and which schemes a programme wants is still open on
236
+ [PIE-472](https://illuminate.atlassian.net/browse/PIE-472).
237
+
180
238
  ## Fixed hues
181
239
 
182
240
  Some components paint a hue the palette does not own: a data encoding, like the
@@ -201,6 +259,59 @@ accessible name.
201
259
  - If DaisyUI tokens are present on the target scope, `pie-theme` uses the built-in `daisyui` provider adapter.
202
260
  - Override precedence is: base PIE -> provider output -> scheme -> `variables`.
203
261
  - `provider="none"` (`PIE_THEME_PROVIDER_NONE`) resolves no provider at all, leaving this package's shipped defaults. It is how a host reproduces the palette it had before adopting a provider, which is the first thing to check when colours differ between two environments.
262
+ - The adapter is the whole integration. `DAISYUI_PIE_TOKEN_MAP` is its sole source, and it corrects a slot that would land illegible because it reads resolved colours — which a stylesheet cannot do. The separate `pie-theme-daisyui` package that shipped the same table as static CSS was removed: `<pie-theme scope="document">` writes `--pie-*` as inline styles, so a stylesheet declaring them lost to it and the import did nothing.
263
+ - A host on some other token vocabulary aliases its own names to `--pie-*` in its own stylesheet, which is what a non-DaisyUI design system needs anyway. Do that under `[data-color-scheme]` to make an accommodation reach host chrome, since `<pie-theme>` never writes `--color-*` or any other host prefix.
264
+
265
+ ## Font size scaling
266
+
267
+ `font-sizes.css` carries four presets on `--pie-font-scale` — `normal` (1),
268
+ `large` (1.25), `xlarge` (1.5), `xxlarge` (1.75). They are Learnosity's steps,
269
+ which K-12 accommodation profiles are already written against, so the numbers are
270
+ a contract: changing one changes what `large` means for every learner assigned it.
271
+
272
+ A host selects a preset with `data-font-size` on any ancestor of the player, or
273
+ on a player element itself:
274
+
275
+ ```html
276
+ <html data-font-size="large">
277
+ <div data-font-size="xlarge"><pie-section-player></pie-section-player></div>
278
+ ```
279
+
280
+ A host already driving `<pie-theme>` sets the token instead and needs nothing
281
+ from the stylesheet:
282
+
283
+ ```html
284
+ <pie-theme variables='{"--pie-font-scale":"1.25"}'>
285
+ ```
286
+
287
+ The content path scales completely. The rules set `font-size` on the content
288
+ hosts — `pie-item-shell`, `pie-passage-shell`, `pie-item-player` and the
289
+ externally loaded `pie-player` wrapper — and `font-size` inheritance crosses
290
+ shadow boundaries, so text that inherits its size follows. Every font size in
291
+ `components.css`, which styles item content, is relative (`em`, `%`,
292
+ `larger`/`smaller`) and follows too. The learner-facing text that declares its
293
+ own size and therefore cannot inherit the scale — the item and passage card
294
+ titles, the formative status line, the tabbed layout's labels, the item player's
295
+ build warning — reads `--pie-font-scale` directly, because a card wraps the shell
296
+ that gets scaled rather than sitting inside it.
297
+
298
+ Tool and debug chrome does not scale, deliberately: an accommodation applies to
299
+ what the learner reads, and a calculator keypad growing with the passage is a
300
+ layout problem rather than an accommodation.
301
+
302
+ A rule elsewhere that sizes text in `rem` or `px` still will not follow — `rem`
303
+ resolves against the document root and `px` against nothing, and no rule inside a
304
+ subtree can change what either means — so a host adding its own content chrome
305
+ either sizes it relatively or reads the token as these rules do. Browser zoom is
306
+ unaffected throughout, so WCAG 2.2 1.4.4 does not depend on this feature.
307
+
308
+ The scale is applied as `calc(1rem * var(--pie-font-scale))` rather than an `em`
309
+ factor because the content hosts nest — an `em` factor would compound, turning a
310
+ requested 1.25 into 1.56 wherever an item shell sits inside a themed region.
311
+
312
+ There is no student-facing control here. The picker is host chrome, which in the
313
+ Renaissance context is Quiz Engine's surface; this package owns the token, the
314
+ presets, and the rules that consume them.
204
315
 
205
316
  ## Token registry
206
317
 
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Find the nearest `<pie-theme>` that owns `from`'s scheme, walking out
3
+ * across shadow-root boundaries. `Element.closest()` alone stops at a
4
+ * shadow root: a caller mounted inside its own `shadow: "open"` root would
5
+ * never find a `<pie-theme>` ancestor that lives in the light DOM outside
6
+ * it, so this repeats the search from each shadow root's host until it
7
+ * either finds one or reaches the document.
8
+ *
9
+ * Falls back to a document-scoped `<pie-theme>` anywhere in the page, then
10
+ * any `<pie-theme>` at all, matching how a page with exactly one theme host
11
+ * is normally set up.
12
+ */
13
+ export declare function resolvePieThemeHost(from?: Node | null): HTMLElement | null;
14
+ export interface ApplyPieColorSchemeOptions {
15
+ /** Search from this node outward for the nearest `<pie-theme>` ancestor. */
16
+ from?: Node | null;
17
+ /** localStorage key to persist the requested scheme under. Pass `null` to skip persistence. */
18
+ persistenceKey?: string | null;
19
+ }
20
+ /**
21
+ * Apply a requested color scheme and persist it, the one canonical way —
22
+ * shared by every caller that offers scheme selection outside `<pie-theme>`
23
+ * itself (a picker tool, a demo host's own theme controls).
24
+ */
25
+ export declare function applyPieColorScheme(schemeId: string, options?: ApplyPieColorSchemeOptions): void;
@@ -0,0 +1,65 @@
1
+ const DEFAULT_COLOR_SCHEME_STORAGE_KEY = "pie-color-scheme";
2
+ /**
3
+ * Find the nearest `<pie-theme>` that owns `from`'s scheme, walking out
4
+ * across shadow-root boundaries. `Element.closest()` alone stops at a
5
+ * shadow root: a caller mounted inside its own `shadow: "open"` root would
6
+ * never find a `<pie-theme>` ancestor that lives in the light DOM outside
7
+ * it, so this repeats the search from each shadow root's host until it
8
+ * either finds one or reaches the document.
9
+ *
10
+ * Falls back to a document-scoped `<pie-theme>` anywhere in the page, then
11
+ * any `<pie-theme>` at all, matching how a page with exactly one theme host
12
+ * is normally set up.
13
+ */
14
+ export function resolvePieThemeHost(from) {
15
+ if (typeof document === "undefined")
16
+ return null;
17
+ let current = from instanceof Element ? from : null;
18
+ while (current) {
19
+ const found = current.closest("pie-theme");
20
+ if (found)
21
+ return found;
22
+ const root = current.getRootNode();
23
+ current = root instanceof ShadowRoot ? root.host : null;
24
+ }
25
+ return (document.querySelector('pie-theme[scope="document"]') ||
26
+ document.querySelector("pie-theme"));
27
+ }
28
+ /**
29
+ * Apply a requested color scheme and persist it, the one canonical way —
30
+ * shared by every caller that offers scheme selection outside `<pie-theme>`
31
+ * itself (a picker tool, a demo host's own theme controls).
32
+ */
33
+ export function applyPieColorScheme(schemeId, options = {}) {
34
+ if (typeof document === "undefined")
35
+ return;
36
+ const nextScheme = (schemeId || "default").trim() || "default";
37
+ const themeHost = resolvePieThemeHost(options.from);
38
+ if (themeHost) {
39
+ if (themeHost.getAttribute("scheme") !== nextScheme) {
40
+ themeHost.setAttribute("scheme", nextScheme);
41
+ }
42
+ }
43
+ else {
44
+ // No <pie-theme> owns `data-color-scheme` on this document, so this is
45
+ // the only way the shared color-scheme CSS can still pick up the
46
+ // requested scheme. A scope="document" <pie-theme> that mounts later
47
+ // captures whatever is already on `documentElement` as its restore
48
+ // baseline rather than silently discarding this write.
49
+ const root = document.documentElement;
50
+ if (nextScheme === "default")
51
+ root.removeAttribute("data-color-scheme");
52
+ else
53
+ root.setAttribute("data-color-scheme", nextScheme);
54
+ }
55
+ if (options.persistenceKey === null)
56
+ return;
57
+ try {
58
+ if (typeof localStorage === "undefined")
59
+ return;
60
+ localStorage.setItem(options.persistenceKey ?? DEFAULT_COLOR_SCHEME_STORAGE_KEY, nextScheme);
61
+ }
62
+ catch {
63
+ // Storage may be unavailable (privacy mode, quota); the scheme still applies this session.
64
+ }
65
+ }
@@ -227,7 +227,7 @@
227
227
  --pie-background-dark: #ffb3cc;
228
228
  --pie-black: #000000;
229
229
  --pie-blue-grey-100: #ffeef5;
230
- --pie-blue-grey-300: #ffccdd;
230
+ --pie-blue-grey-300: #ffb3cc;
231
231
  --pie-blue-grey-600: #cc6688;
232
232
  --pie-blue-grey-900: #000000;
233
233
  --pie-border: #000000;
@@ -1,4 +1,4 @@
1
- import { createBuiltInColorSchemeDescriptor, createPieColorSchemePreview, diagnoseThemeContrast, getBaseThemeVariables, getBuiltInColorSchemeDefinition, getDefaultColorSchemeDescriptor, getSchemeParticipation, listBuiltInColorSchemeDefinitions, } from "./theme-definitions.js";
1
+ import { createBuiltInColorSchemeDescriptor, createPieColorSchemePreview, diagnoseThemeContrast, getBaseThemeVariables, getBuiltInColorSchemeDefinition, getDefaultColorSchemeDescriptor, getSchemeParticipation, listBuiltInColorSchemeDefinitions, resolvePaletteColorScheme, } from "./theme-definitions.js";
2
2
  import { normalizePieThemeVariables, } from "./theme-types.js";
3
3
  const customSchemes = new Map();
4
4
  const observers = new Set();
@@ -455,12 +455,20 @@ export function resolvePieTheme(input = {}) {
455
455
  }
456
456
  for (const item of diagnostics)
457
457
  warnDiagnostic(item);
458
+ // Only a resolved scheme decides polarity. Without one -- including a requested
459
+ // scheme that turned out unavailable -- the host's theme still owns
460
+ // `color-scheme`, and deciding it from the base palette would take that
461
+ // ownership away from every host that never asked for an accommodation.
462
+ const colorScheme = status === "built-in" || status === "custom"
463
+ ? resolvePaletteColorScheme(variables)
464
+ : null;
458
465
  return Object.freeze({
459
466
  baseTheme,
460
467
  requestedScheme,
461
468
  resolvedScheme,
462
469
  status,
463
470
  variables: freezeVariables(variables),
471
+ colorScheme,
464
472
  diagnostics: freezeDiagnostics(diagnostics),
465
473
  });
466
474
  }
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * The one table that says which DaisyUI slot each `--pie-*` token comes from,
3
- * and one renderer that turns it into variables.
3
+ * and one renderer that turns it into variables. Sole source: the `daisyui`
4
+ * provider adapter is the only thing that reads it, and a host reaches it by
5
+ * mounting `<pie-theme provider="daisyui">` or leaving `provider` on `auto`.
4
6
  *
5
- * It exists because the same 47-row table was written out four times — the
6
- * provider adapter here, two mappers in `@pie-players/pie-theme-daisyui`, and
7
- * that package's `bridge.css` — and copies drift. Two defects lived in the drift:
8
- * `--pie-missing` was corrected to `--color-warning` in one copy while three kept
9
- * it on `--color-error`, and the parity test that was supposed to catch this
10
- * compared only the token names, never the slot each one derived from.
11
- *
12
- * CSS cannot import a table, so `bridge.css` stays hand-written and is held to
13
- * this one by `tests/daisyui-mapping-parity.test.mjs` instead.
7
+ * It was consolidated here after the same table had been written out four
8
+ * times — this adapter, two mappers in a separate `pie-theme-daisyui` package, and
9
+ * that package's static `bridge.css` — and copies drift. Two defects lived in the
10
+ * drift: `--pie-missing` was corrected to `--color-warning` in one copy while three
11
+ * kept it on `--color-error`, and the parity test meant to catch that compared only
12
+ * the token names, never the slot each one derived from. The copies are gone; the
13
+ * package was removed once its CSS turned out to be outranked by the inline
14
+ * variables `<pie-theme>` writes, leaving it inert wherever it was imported.
14
15
  */
15
16
  import { type ColorMeasure } from "./contrast.js";
16
17
  /** The DaisyUI slots this mapping reads. Not all of DaisyUI's palette. */
@@ -1,16 +1,17 @@
1
1
  /**
2
2
  * The one table that says which DaisyUI slot each `--pie-*` token comes from,
3
- * and one renderer that turns it into variables.
3
+ * and one renderer that turns it into variables. Sole source: the `daisyui`
4
+ * provider adapter is the only thing that reads it, and a host reaches it by
5
+ * mounting `<pie-theme provider="daisyui">` or leaving `provider` on `auto`.
4
6
  *
5
- * It exists because the same 47-row table was written out four times — the
6
- * provider adapter here, two mappers in `@pie-players/pie-theme-daisyui`, and
7
- * that package's `bridge.css` — and copies drift. Two defects lived in the drift:
8
- * `--pie-missing` was corrected to `--color-warning` in one copy while three kept
9
- * it on `--color-error`, and the parity test that was supposed to catch this
10
- * compared only the token names, never the slot each one derived from.
11
- *
12
- * CSS cannot import a table, so `bridge.css` stays hand-written and is held to
13
- * this one by `tests/daisyui-mapping-parity.test.mjs` instead.
7
+ * It was consolidated here after the same table had been written out four
8
+ * times — this adapter, two mappers in a separate `pie-theme-daisyui` package, and
9
+ * that package's static `bridge.css` — and copies drift. Two defects lived in the
10
+ * drift: `--pie-missing` was corrected to `--color-warning` in one copy while three
11
+ * kept it on `--color-error`, and the parity test meant to catch that compared only
12
+ * the token names, never the slot each one derived from. The copies are gone; the
13
+ * package was removed once its CSS turned out to be outranked by the inline
14
+ * variables `<pie-theme>` writes, leaving it inert wherever it was imported.
14
15
  */
15
16
  import { LEGIBLE_NON_TEXT_MINIMUM, LEGIBLE_TEXT_MINIMUM, UNMEASURED_HUE_WEIGHT, UNMEASURED_NON_TEXT_HUE_WEIGHT, legibleColorAgainst, } from "./contrast.js";
16
17
  export const DAISY_SLOT_CSS_VARIABLES = {
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The full set of built-in DaisyUI theme ids. `<pie-theme>`'s DaisyUI
3
+ * provider adapter maps any of these onto the `--pie-*` token contract, so
4
+ * every demo host offering a DaisyUI theme picker draws from this one list
5
+ * instead of each hand-typing its own copy.
6
+ */
7
+ export declare const DAISYUI_THEME_CATALOG: readonly ["light", "dark", "cupcake", "bumblebee", "emerald", "corporate", "synthwave", "retro", "cyberpunk", "valentine", "halloween", "garden", "forest", "aqua", "lofi", "pastel", "fantasy", "wireframe", "black", "luxury", "dracula", "cmyk", "autumn", "business", "acid", "lemonade", "night", "coffee", "winter", "dim", "nord", "sunset", "caramellatte", "abyss", "silk"];
8
+ export type DaisyUIThemeId = (typeof DAISYUI_THEME_CATALOG)[number];
@@ -0,0 +1,43 @@
1
+ /**
2
+ * The full set of built-in DaisyUI theme ids. `<pie-theme>`'s DaisyUI
3
+ * provider adapter maps any of these onto the `--pie-*` token contract, so
4
+ * every demo host offering a DaisyUI theme picker draws from this one list
5
+ * instead of each hand-typing its own copy.
6
+ */
7
+ export const DAISYUI_THEME_CATALOG = [
8
+ "light",
9
+ "dark",
10
+ "cupcake",
11
+ "bumblebee",
12
+ "emerald",
13
+ "corporate",
14
+ "synthwave",
15
+ "retro",
16
+ "cyberpunk",
17
+ "valentine",
18
+ "halloween",
19
+ "garden",
20
+ "forest",
21
+ "aqua",
22
+ "lofi",
23
+ "pastel",
24
+ "fantasy",
25
+ "wireframe",
26
+ "black",
27
+ "luxury",
28
+ "dracula",
29
+ "cmyk",
30
+ "autumn",
31
+ "business",
32
+ "acid",
33
+ "lemonade",
34
+ "night",
35
+ "coffee",
36
+ "winter",
37
+ "dim",
38
+ "nord",
39
+ "sunset",
40
+ "caramellatte",
41
+ "abyss",
42
+ "silk",
43
+ ];
@@ -1,141 +1,94 @@
1
- /* PIE Font Size System - Learnosity-compatible font scaling for K-12 assessments
1
+ /* PIE font size scaling.
2
2
  *
3
- * Based on Learnosity's font size accommodation feature which provides 4 preset sizes:
4
- * - Normal (100% - default)
5
- * - Large (125% - 1.25x scale)
6
- * - Extra Large (150% - 1.5x scale)
7
- * - Extra Extra Large (175% - 1.75x scale)
3
+ * Four presets on `--pie-font-scale`, selected by `data-font-size` on any
4
+ * ancestor of the player — matching Learnosity's font-size accommodation
5
+ * (100/125/150/175%), which is the scale K-12 programs already specify against.
8
6
  *
9
- * All sizes meet WCAG 2.2 Level AA requirements for text sizing:
10
- * - Users can scale text up to 200% without assistive technology
11
- * - Text remains readable and functional at all scale levels
12
- * - No horizontal scrolling required in scaled states
7
+ * <html data-font-size="large"> host owns the whole page
8
+ * <div data-font-size="large"> host scopes it to a region
13
9
  *
14
- * Usage: Apply data-font-size attribute to document root or pie-player element
15
- * Example: <html data-font-size="large">
10
+ * A host that drives theming through `<pie-theme>` sets the token directly
11
+ * instead, and needs nothing from this file:
16
12
  *
17
- * Implementation Note: Uses CSS custom property (--pie-font-scale) to scale all
18
- * typography consistently. Base font sizes are defined in the PIE player components.
13
+ * <pie-theme variables='{"--pie-font-scale":"1.25"}'>
14
+ *
15
+ * WHAT SCALES. Text that inherits its size scales, because the rules below set
16
+ * `font-size` on the content hosts and inheritance crosses shadow boundaries.
17
+ * Text whose own rule names `rem` or `px` does not: `rem` resolves against the
18
+ * document root and `px` against nothing, and no rule inside a subtree can
19
+ * change what either means. A host that needs those to follow as well has to
20
+ * scale the root font size itself, which is a page-wide decision this package
21
+ * does not make on its behalf. WCAG 2.2 1.4.4 is satisfied either way — browser
22
+ * zoom remains available and unaffected — so this is a comfort accommodation
23
+ * layered over that, not a substitute for it.
24
+ *
25
+ * `calc(1rem * var(--pie-font-scale))` is deliberately root-relative rather than
26
+ * `em`-relative: the hosts nest (an item shell inside a section player inside a
27
+ * themed region), and an `em` factor would compound at each level and multiply
28
+ * 1.25 into 1.95.
19
29
  */
20
30
 
21
- /* Default font size (100% - no scaling) */
31
+ /* The unset default. Also declared by the base theme, so the token resolves
32
+ * whether a host loads this file, `tokens.css`, or drives `<pie-theme>`. */
22
33
  :root {
23
34
  --pie-font-scale: 1;
24
35
  }
25
36
 
26
- /* Normal (100% - explicit setting) */
27
37
  [data-font-size="normal"] {
28
38
  --pie-font-scale: 1;
29
39
  }
30
40
 
31
- /* Large (125%) - Learnosity "large" preset */
32
41
  [data-font-size="large"] {
33
42
  --pie-font-scale: 1.25;
34
43
  }
35
44
 
36
- /* Extra Large (150%) - Learnosity "xlarge" preset */
37
45
  [data-font-size="xlarge"] {
38
46
  --pie-font-scale: 1.5;
39
47
  }
40
48
 
41
- /* Extra Extra Large (175%) - Learnosity "xxlarge" preset */
42
49
  [data-font-size="xxlarge"] {
43
50
  --pie-font-scale: 1.75;
44
51
  }
45
52
 
46
- /* Apply font scaling to assessment content
47
- * Target PIE player elements and assessment content
48
- * Exclude tool UIs (calculator, graph, etc.) which should remain at normal size
53
+ /* Content hosts.
49
54
  *
50
- * Using !important to override PIE's inline styles and component-specific styles
55
+ * `pie-item-shell` and `pie-passage-shell` are this repo's section-player
56
+ * content hosts and `pie-item-player` its standalone one; each renders PIE
57
+ * elements directly into its own shadow tree. `pie-player` is the externally
58
+ * loaded item wrapper some hosts render items through instead, so both delivery
59
+ * paths are covered — targeting only the wrapper, as this file previously did,
60
+ * missed every item this repo renders itself.
61
+ *
62
+ * Scoped under `[data-font-size]` so the declaration only exists once a host has
63
+ * opted in, and so a host's own rules keep the upper hand at equal specificity.
51
64
  */
52
-
53
- /* Apply to pie-player root element */
65
+ [data-font-size] pie-item-shell,
66
+ [data-font-size] pie-passage-shell,
67
+ [data-font-size] pie-item-player,
68
+ [data-font-size] pie-player,
69
+ pie-item-shell[data-font-size],
70
+ pie-passage-shell[data-font-size],
71
+ pie-item-player[data-font-size],
54
72
  pie-player[data-font-size] {
55
- font-size: calc(1rem * var(--pie-font-scale)) !important;
56
- }
57
-
58
- /* Apply to all text elements within pie-player - using inherit to cascade from root */
59
- pie-player[data-font-size] *,
60
- pie-player[data-font-size] p,
61
- pie-player[data-font-size] span,
62
- pie-player[data-font-size] div,
63
- pie-player[data-font-size] li,
64
- pie-player[data-font-size] label,
65
- pie-player[data-font-size] input,
66
- pie-player[data-font-size] textarea,
67
- pie-player[data-font-size] select,
68
- pie-player[data-font-size] button,
69
- pie-player[data-font-size] h1,
70
- pie-player[data-font-size] h2,
71
- pie-player[data-font-size] h3,
72
- pie-player[data-font-size] h4,
73
- pie-player[data-font-size] h5,
74
- pie-player[data-font-size] h6,
75
- pie-player[data-font-size] td,
76
- pie-player[data-font-size] th,
77
- pie-player[data-font-size] option {
78
- font-size: inherit !important;
79
- }
73
+ font-size: calc(1rem * var(--pie-font-scale, 1));
80
74
 
81
- /* Also apply to parent container if data-font-size is on document root */
82
- [data-font-size] pie-player {
83
- font-size: calc(1rem * var(--pie-font-scale)) !important;
84
- }
85
-
86
- [data-font-size] pie-player *,
87
- [data-font-size] pie-player p,
88
- [data-font-size] pie-player span,
89
- [data-font-size] pie-player div,
90
- [data-font-size] pie-player li,
91
- [data-font-size] pie-player label,
92
- [data-font-size] pie-player input,
93
- [data-font-size] pie-player textarea,
94
- [data-font-size] pie-player select,
95
- [data-font-size] pie-player button,
96
- [data-font-size] pie-player h1,
97
- [data-font-size] pie-player h2,
98
- [data-font-size] pie-player h3,
99
- [data-font-size] pie-player h4,
100
- [data-font-size] pie-player h5,
101
- [data-font-size] pie-player h6,
102
- [data-font-size] pie-player td,
103
- [data-font-size] pie-player th,
104
- [data-font-size] pie-player option {
105
- font-size: inherit !important;
106
- }
107
-
108
- /* Preserve normal size for tool UIs and controls */
109
- [data-font-size] .pie-tool-toolbar,
110
- [data-font-size] .pie-tool-toolbar *,
111
- [data-font-size] .pie-tool-calculator,
112
- [data-font-size] .pie-tool-calculator *,
113
- [data-font-size] .tool-settings-panel,
114
- [data-font-size] .tool-settings-panel *,
115
- [data-font-size] [class*="pie-tool-"],
116
- [data-font-size] [class*="pie-tool-"] *,
117
- [data-font-size] header,
118
- [data-font-size] header *,
119
- [data-font-size] footer,
120
- [data-font-size] footer *,
121
- [data-font-size] nav,
122
- [data-font-size] nav *,
123
- [data-font-size] button:not(.pie-button),
124
- [data-font-size] .btn,
125
- [data-font-size] .btn * {
126
- font-size: 1rem !important;
75
+ /* Long words at 175% overflow a column that fits them at 100%. */
76
+ overflow-wrap: break-word;
127
77
  }
128
78
 
129
- /* Ensure proper line-height scaling for readability */
79
+ /* Line height has to open up with the type or the block tightens as it grows.
80
+ * A ratio, so a host that sets its own line-height still wins. */
81
+ [data-font-size="large"] pie-item-shell,
82
+ [data-font-size="large"] pie-passage-shell,
83
+ [data-font-size="large"] pie-item-player,
130
84
  [data-font-size="large"] pie-player,
85
+ [data-font-size="xlarge"] pie-item-shell,
86
+ [data-font-size="xlarge"] pie-passage-shell,
87
+ [data-font-size="xlarge"] pie-item-player,
131
88
  [data-font-size="xlarge"] pie-player,
89
+ [data-font-size="xxlarge"] pie-item-shell,
90
+ [data-font-size="xxlarge"] pie-passage-shell,
91
+ [data-font-size="xxlarge"] pie-item-player,
132
92
  [data-font-size="xxlarge"] pie-player {
133
93
  line-height: 1.6;
134
94
  }
135
-
136
- /* Prevent layout issues with scaled text */
137
- [data-font-size] pie-player {
138
- overflow-wrap: break-word;
139
- word-wrap: break-word;
140
- hyphens: auto;
141
- }
package/dist/index.d.ts CHANGED
@@ -2,7 +2,9 @@ import { PieThemeElement, definePieTheme } from "./theme-element.js";
2
2
  export { PieThemeElement, definePieTheme };
3
3
  export { DAISYUI_THEME_PROVIDER_ADAPTER, getPieThemeProvider, PIE_THEME_PROVIDER_NONE, listPieThemeProviders, registerPieThemeProvider, resolveProviderVariables, unregisterPieThemeProvider, type ThemeProviderAdapter, } from "./providers.js";
4
4
  export { DAISY_SLOT_CSS_VARIABLES, DAISYUI_PIE_TOKEN_MAP, resolveDaisyPieVariables, type DaisyMappingEntry, type DaisySlot, } from "./daisyui-mapping.js";
5
+ export { DAISYUI_THEME_CATALOG, type DaisyUIThemeId, } from "./daisyui-theme-catalog.js";
5
6
  export { createCanvasColorMeasure, type ColorMeasure, } from "./contrast.js";
6
7
  export { isThemeMode, isThemeScope, normalizePieThemeVariables, type ColorSchemeSnapshot, type PieColorSchemeDescriptor, type PieColorSchemePreview, type PieThemeDiagnostic, type PieThemeDiagnosticCode, type PieThemeObserver, type PieThemeResolutionStatus, type RegisteredPieColorScheme, type RegistrationReceipt, type ResolvePieThemeInput, type ThemeResolution, type ThemeMode, type ThemeScope, type ThemeTokenName, type ThemeVariables, type Unsubscribe, } from "./theme-types.js";
7
8
  export type { PieThemeSchemeParticipation, PieThemeTokenRegistry, PieThemeTokenRegistryEntry, PieThemeTokenScope, PieThemeTokenStatus, } from "./token-registry-types.js";
8
9
  export { listPieColorSchemes, observePieColorSchemes, registerPieColorSchemes, resolvePieTheme, } from "./color-schemes.js";
10
+ export { applyPieColorScheme, resolvePieThemeHost, type ApplyPieColorSchemeOptions, } from "./apply-color-scheme.js";
package/dist/index.js CHANGED
@@ -2,7 +2,9 @@ import { PieThemeElement, definePieTheme } from "./theme-element.js";
2
2
  export { PieThemeElement, definePieTheme };
3
3
  export { DAISYUI_THEME_PROVIDER_ADAPTER, getPieThemeProvider, PIE_THEME_PROVIDER_NONE, listPieThemeProviders, registerPieThemeProvider, resolveProviderVariables, unregisterPieThemeProvider, } from "./providers.js";
4
4
  export { DAISY_SLOT_CSS_VARIABLES, DAISYUI_PIE_TOKEN_MAP, resolveDaisyPieVariables, } from "./daisyui-mapping.js";
5
+ export { DAISYUI_THEME_CATALOG, } from "./daisyui-theme-catalog.js";
5
6
  export { createCanvasColorMeasure, } from "./contrast.js";
6
7
  export { isThemeMode, isThemeScope, normalizePieThemeVariables, } from "./theme-types.js";
7
8
  export { listPieColorSchemes, observePieColorSchemes, registerPieColorSchemes, resolvePieTheme, } from "./color-schemes.js";
9
+ export { applyPieColorScheme, resolvePieThemeHost, } from "./apply-color-scheme.js";
8
10
  definePieTheme();
@@ -23,6 +23,12 @@ export declare const PIE_THEME_SCHEME_PARTICIPATION: {
23
23
  readonly "--pie-button-hover-bg": "required";
24
24
  readonly "--pie-button-hover-border": "required";
25
25
  readonly "--pie-button-hover-color": "required";
26
+ readonly "--pie-calculator-series-1": "optional";
27
+ readonly "--pie-calculator-series-2": "optional";
28
+ readonly "--pie-calculator-series-3": "optional";
29
+ readonly "--pie-calculator-series-4": "optional";
30
+ readonly "--pie-calculator-series-5": "optional";
31
+ readonly "--pie-calculator-series-6": "optional";
26
32
  readonly "--pie-content-styles": "excluded";
27
33
  readonly "--pie-content-emphasis": "required";
28
34
  readonly "--pie-correct": "required";
@@ -50,11 +56,15 @@ export declare const PIE_THEME_SCHEME_PARTICIPATION: {
50
56
  readonly "--pie-primary": "required";
51
57
  readonly "--pie-primary-dark": "required";
52
58
  readonly "--pie-primary-light": "required";
59
+ readonly "--pie-scrollbar-thumb": "excluded";
60
+ readonly "--pie-scrollbar-thumb-hover": "excluded";
61
+ readonly "--pie-scrollbar-track": "excluded";
53
62
  readonly "--pie-secondary": "required";
54
63
  readonly "--pie-secondary-background": "required";
55
64
  readonly "--pie-secondary-dark": "required";
56
65
  readonly "--pie-secondary-light": "required";
57
66
  readonly "--pie-section-player-card-header-background": "optional";
67
+ readonly "--pie-section-player-card-header-background-dark": "optional";
58
68
  readonly "--pie-section-player-card-header-radius": "excluded";
59
69
  readonly "--pie-section-player-card-radius": "excluded";
60
70
  readonly "--pie-section-player-item-media-aspect-ratio": "excluded";
@@ -84,5 +94,10 @@ export declare const PIE_THEME_SCHEME_PARTICIPATION: {
84
94
  readonly "--pie-tool-trigger-active-color": "optional";
85
95
  readonly "--pie-toolbar-tools-row-height": "excluded";
86
96
  readonly "--pie-tts-controls-row-height": "excluded";
97
+ readonly "--pie-tts-line-highlight": "excluded";
98
+ readonly "--pie-tts-sentence-highlight": "excluded";
99
+ readonly "--pie-tts-word-highlight": "excluded";
100
+ readonly "--pie-tts-word-shadow": "excluded";
101
+ readonly "--pie-tts-word-underline": "excluded";
87
102
  readonly "--pie-white": "required";
88
103
  };