@taprootio/espalier 3.2.0 → 3.4.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.
- package/CHANGELOG.md +42 -0
- package/custom-elements.json +4475 -3579
- package/dist/action-menu/esp-action-menu-item.d.ts +2 -1
- package/dist/action-menu/esp-action-menu-item.js +1 -1
- package/dist/action-menu/esp-action-menu.js +1 -1
- package/dist/button/esp-button-group.js +1 -1
- package/dist/cli/espalier.js +2 -0
- package/dist/cli/theme-check.js +2 -0
- package/dist/form/esp-form.d.ts +2 -2
- package/dist/form/esp-form.js +1 -1
- package/dist/header/esp-header-button.d.ts +1 -0
- package/dist/header/esp-header-button.js +2 -2
- package/dist/icons/icon-sprite.generated.d.ts +17 -0
- package/dist/icons/icon-sprite.generated.js +702 -0
- package/dist/icons/index.d.ts +40 -0
- package/dist/icons/index.js +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +1 -1
- package/dist/pickers/esp-picker-item.js +3 -3
- package/dist/popover/esp-popover.js +2 -2
- package/dist/root/esp-root.d.ts +16 -0
- package/dist/root/helpers/compute-theme-properties.js +1 -1
- package/dist/root/helpers/data-companion-properties.js +1 -0
- package/dist/shared/document-sprite.js +1 -0
- package/dist/shared/esp-element-base.d.ts +1 -0
- package/dist/shared/esp-element-base.js +2 -2
- package/dist/shared/intent-values.d.ts +29 -0
- package/dist/shared/intent-values.js +1 -1
- package/dist/shared/theme-fit-report.d.ts +94 -4
- package/dist/shared/theme-fit-report.js +1 -1
- package/dist/shared/theme-swatches.d.ts +79 -0
- package/dist/shared/theme-swatches.js +1 -0
- package/dist/shared/theme.d.ts +36 -0
- package/dist/shared/theme.js +1 -1
- package/dist/shared/unsafe-keys.js +1 -0
- package/espalier.token-manifest.json +80 -0
- package/licenses/asset-provenance.json +9 -7
- package/package.json +8 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module theme-swatches
|
|
3
|
+
*
|
|
4
|
+
* Brand book in, reviewable theme out (ESP0175).
|
|
5
|
+
*
|
|
6
|
+
* The lightness-ramps guide documents the fitting procedure by hand:
|
|
7
|
+
* convert every swatch to OKLCH, seat each on the ramp stop whose job
|
|
8
|
+
* matches its lightness (set the stop to the swatch's *exact* L so the
|
|
9
|
+
* anchor lands on its swatch instead of a relative of it), interpolate
|
|
10
|
+
* the unseated stops between their seated neighbors, and repeat against
|
|
11
|
+
* the dark scheme's inverted expectations. This module automates those
|
|
12
|
+
* mechanical steps — {@link deriveLightnessRamp} — and wraps them in
|
|
13
|
+
* {@link themeFromSwatches}, which returns a paired partial-theme
|
|
14
|
+
* **starter**: anchors, seated ramps, and the two role guesses that are
|
|
15
|
+
* safe to make from lightness alone. Everything else — the remaining
|
|
16
|
+
* roles, contexts, intents — is the design work the guide walks through,
|
|
17
|
+
* and the output is meant to be hand-tuned and reviewed, not shipped
|
|
18
|
+
* as-is. Verify the result the way the guide says to: a fit report per
|
|
19
|
+
* scheme (a seated anchor shows a near-zero ΔE), then `validateThemePair`.
|
|
20
|
+
*/
|
|
21
|
+
import { type LightnessMap, type PartialTheme } from "./theme.js";
|
|
22
|
+
/**
|
|
23
|
+
* Derive a full lightness ramp by seating brand swatches on the scheme's
|
|
24
|
+
* default ramp — the guide's procedure, steps 1–4, automated.
|
|
25
|
+
*
|
|
26
|
+
* The stops that carry a token identity — `surface` (the canvas) and
|
|
27
|
+
* `text` (body copy) — seat first, each taking the nearest swatch within
|
|
28
|
+
* tolerance: those are the two seats where "the anchor lands on its
|
|
29
|
+
* swatch" matters most, and a numerically closer neighboring stop must
|
|
30
|
+
* not steal their swatch (the guide seats cream on `surface`, not on
|
|
31
|
+
* the fractionally closer `raised1`). The remaining seating is greedy
|
|
32
|
+
* by closeness: the (stop, swatch) pair with the smallest lightness
|
|
33
|
+
* distance seats first, each stop and each swatch seat at most once, a
|
|
34
|
+
* pair further than the seating tolerance never seats, and a seat that
|
|
35
|
+
* would invert the ramp's ordering (relative to the stops already
|
|
36
|
+
* seated) is skipped. Unseated stops interpolate between their seated
|
|
37
|
+
* neighbors along the default ramp; stops outside the seated span shift
|
|
38
|
+
* parallel to their nearest seated neighbor, so the ramp keeps the
|
|
39
|
+
* default's shape wherever the brand is silent.
|
|
40
|
+
*
|
|
41
|
+
* @param swatches Brand swatches, name → CSS color (any accepted form).
|
|
42
|
+
* @param scheme Which scheme's default ramp to seat against.
|
|
43
|
+
*/
|
|
44
|
+
export declare function deriveLightnessRamp(swatches: Record<string, string>, scheme: "light" | "dark"): LightnessMap;
|
|
45
|
+
/** Options for {@link themeFromSwatches}. */
|
|
46
|
+
export interface ThemeFromSwatchesOptions {
|
|
47
|
+
/** Brand swatches, name → CSS color in any accepted form. */
|
|
48
|
+
swatches: Record<string, string>;
|
|
49
|
+
/** Seed override; defaults to the most chromatic swatch's color. */
|
|
50
|
+
seedColor?: string;
|
|
51
|
+
}
|
|
52
|
+
/** The paired starter {@link themeFromSwatches} returns. */
|
|
53
|
+
export interface ThemeFromSwatchesResult {
|
|
54
|
+
light: PartialTheme;
|
|
55
|
+
dark: PartialTheme;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Turn a brand book's swatches into a paired partial-theme starter.
|
|
59
|
+
*
|
|
60
|
+
* What it derives, and why only this much:
|
|
61
|
+
*
|
|
62
|
+
* - **anchors** — every swatch, keyed by its normalized slug: names are
|
|
63
|
+
* lowercased with non-alphanumeric runs collapsed to single hyphens
|
|
64
|
+
* ("Rose Gold" → `rose-gold`); unnormalizable or colliding names
|
|
65
|
+
* throw rather than silently renaming past each other.
|
|
66
|
+
* - **seedColor** — the most chromatic swatch unless overridden; the
|
|
67
|
+
* seed drives every derived family, and the brand's most saturated
|
|
68
|
+
* color is where that identity lives.
|
|
69
|
+
* - **lightness** — both schemes' ramps via {@link deriveLightnessRamp}.
|
|
70
|
+
* - **roles** — only the two guesses lightness alone justifies: a
|
|
71
|
+
* near-white swatch (L ≥ 0.9) becomes the light scheme's `canvas`, a
|
|
72
|
+
* near-black one (L ≤ 0.3) the dark scheme's; the most chromatic
|
|
73
|
+
* mid-band swatch (0.3 ≤ L ≤ 0.65) becomes `action` in both.
|
|
74
|
+
*
|
|
75
|
+
* Every other decision — ink, accent, contexts, intents — is design, not
|
|
76
|
+
* derivation: make them in the theming guide's order, and verify with a
|
|
77
|
+
* fit report per scheme.
|
|
78
|
+
*/
|
|
79
|
+
export declare function themeFromSwatches(options: ThemeFromSwatchesOptions): ThemeFromSwatchesResult;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{parseCssColor as M}from"./color-engine.js";import{isSafeKey as b}from"./unsafe-keys.js";import{ANCHOR_SLUG_PATTERN as L,COLOR_SOURCES as T,DEFAULT_DARK_THEME as F,DEFAULT_LIGHT_THEME as _,LIGHTNESS_KEYS as E}from"./theme.js";const $=.08;function x(i){return Object.entries(i).map(([c,n])=>{const s=M(n);if(!s)throw new Error(`themeFromSwatches: swatch "${c}" is not a parseable CSS color: "${n}".`);return{name:c,l:s.l,c:s.c}})}function O(i,c){const n=(c==="light"?_:F).lightness,s=x(i),o=[...E].sort((e,t)=>n[e]-n[t]),a=new Map,w=new Set,p=(e,t)=>{if(a.has(e)||w.has(t.name))return!1;const r=o.indexOf(e);for(const[l,h]of a){const d=o.indexOf(l);if(d<r&&h>t.l||d>r&&h<t.l)return!1}return a.set(e,t.l),w.add(t.name),!0};for(const e of["surface","text"]){const t=[...s].filter(r=>Math.abs(n[e]-r.l)<=$).sort((r,l)=>Math.abs(n[e]-r.l)-Math.abs(n[e]-l.l))[0];t&&p(e,t)}const S=o.flatMap(e=>s.map(t=>({stop:e,swatch:t,distance:Math.abs(n[e]-t.l)}))).filter(e=>e.distance<=$).sort((e,t)=>e.distance-t.distance);for(const{stop:e,swatch:t}of S)p(e,t);const f={};for(const e of E){const t=a.get(e);if(t!==void 0){f[e]=t;continue}const r=o.indexOf(e);let l,h;for(const[m]of a){const u=o.indexOf(m);u<r&&(l===void 0||u>o.indexOf(l))&&(l=m),u>r&&(h===void 0||u<o.indexOf(h))&&(h=m)}const d=n[e];if(l!==void 0&&h!==void 0){const m=n[l],u=n[h],g=a.get(l),C=a.get(h);f[e]=u===m?g:g+(d-m)/(u-m)*(C-g)}else l!==void 0?f[e]=R(d+(a.get(l)-n[l])):h!==void 0?f[e]=R(d+(a.get(h)-n[h])):f[e]=d}for(const e of E)f[e]=y(f[e]);return f}function R(i){return Math.min(1,Math.max(0,i))}function y(i){return Math.round(i*1e3)/1e3}function v(i){const c=new Map;for(const s of Object.keys(i)){const o=s.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"");if(!L.test(o))throw new Error(`themeFromSwatches: swatch name "${s}" cannot become an anchor slug (normalized to "${o}"; a slug is lowercase letters, digits, and hyphens, starting with a letter). Rename the swatch.`);if(T.includes(o))throw new Error(`themeFromSwatches: swatch name "${s}" normalizes to the reserved color source "${o}". Rename the swatch.`);if(!b(o))throw new Error(`themeFromSwatches: swatch name "${s}" normalizes to "${o}", a reserved JavaScript property name. Rename the swatch.`);const a=c.get(o);if(a!==void 0)throw new Error(`themeFromSwatches: swatch names "${a}" and "${s}" collide as "${o}". Rename one.`);c.set(o,s)}const n={};for(const[s,o]of c)n[s]=i[o];return n}function H(i){const c=v(i.swatches),n=x(c);if(n.length===0)throw new Error("themeFromSwatches: at least one swatch is required.");const s=[...n].sort((t,r)=>r.c-t.c)[0],o=i.seedColor??c[s.name],a={},w={},p=[...n].sort((t,r)=>r.l-t.l)[0];p.l>=.9&&(a.canvas=`anchor:${p.name}`);const S=[...n].sort((t,r)=>t.l-r.l)[0];S.l<=.3&&(w.canvas=`anchor:${S.name}`);const f=n.filter(t=>t.l>=.3&&t.l<=.65).sort((t,r)=>r.c-t.c)[0];f&&(a.action=`anchor:${f.name}`,w.action=`anchor:${f.name}`);const e={...c};return{light:{anchors:e,lightness:O(c,"light"),roles:a,seedColor:o},dark:{anchors:e,lightness:O(c,"dark"),roles:w,seedColor:o}}}export{O as deriveLightnessRamp,H as themeFromSwatches};
|
package/dist/shared/theme.d.ts
CHANGED
|
@@ -228,9 +228,16 @@ export type ThemeRoles = {
|
|
|
228
228
|
* A context may also carry a partial lightness ramp. Color sources alone
|
|
229
229
|
* cannot make a dark zone inside a light scheme because semantic derivation
|
|
230
230
|
* deliberately takes lightness from the ramp rather than from an anchor.
|
|
231
|
+
*
|
|
232
|
+
* A context may also carry token-level `semanticMappings` (ESP0175).
|
|
233
|
+
* Root-level explicit mappings survive into every context by design —
|
|
234
|
+
* they are deliberate token pins — so a zone that needs a different
|
|
235
|
+
* value for one of them declares its own mapping here, which layers over
|
|
236
|
+
* the inherited pin exactly as a root-level mapping layers over roles.
|
|
231
237
|
*/
|
|
232
238
|
export type ThemeContext = ThemeRoles & {
|
|
233
239
|
lightness?: Partial<LightnessMap>;
|
|
240
|
+
semanticMappings?: Partial<SemanticMappings>;
|
|
234
241
|
};
|
|
235
242
|
/** Named role-rebinding zones available to `context` attributes. */
|
|
236
243
|
export type ThemeContexts = Record<string, ThemeContext>;
|
|
@@ -274,6 +281,8 @@ interface CompileRoleOptions {
|
|
|
274
281
|
explicitMappings?: Partial<SemanticMappings>;
|
|
275
282
|
/** Exact maximum paired-ink contrast of an action surface candidate. */
|
|
276
283
|
actionSurfaceContrast?: (source: MappingSource, stop: LightnessKey) => number;
|
|
284
|
+
/** ΔE-OK between an action surface candidate and the theme's background. */
|
|
285
|
+
actionSurfaceSeparation?: (source: MappingSource, stop: LightnessKey) => number;
|
|
277
286
|
}
|
|
278
287
|
/**
|
|
279
288
|
* Compile roles into semantic mappings.
|
|
@@ -635,6 +644,18 @@ export declare function parseTheme(base64: string): PartialTheme | null;
|
|
|
635
644
|
* @returns A Base64-encoded JSON string.
|
|
636
645
|
*/
|
|
637
646
|
export declare function encodeTheme(partial: PartialTheme): string;
|
|
647
|
+
/**
|
|
648
|
+
* Recover explicit mapping provenance from a resolved theme.
|
|
649
|
+
*
|
|
650
|
+
* Themes produced in this process carry exact provenance in the WeakMap.
|
|
651
|
+
* The comparison fallback preserves the historical behavior for a fully
|
|
652
|
+
* resolved theme reconstructed outside `mergeTheme`, where provenance is
|
|
653
|
+
* necessarily unavailable because it is not part of the serialized model.
|
|
654
|
+
*
|
|
655
|
+
* Exported for the fit report (ESP0175), which marks explicit tokens so
|
|
656
|
+
* a zone's surprising value traces to the mapping that pinned it.
|
|
657
|
+
*/
|
|
658
|
+
export declare function explicitMappingTokens(theme: EspalierTheme): Set<SemanticColorName>;
|
|
638
659
|
/**
|
|
639
660
|
* Deep-merge a {@link PartialTheme} over a set of defaults.
|
|
640
661
|
*
|
|
@@ -648,6 +669,21 @@ export declare function encodeTheme(partial: PartialTheme): string;
|
|
|
648
669
|
* @returns A new fully-resolved {@link EspalierTheme}.
|
|
649
670
|
*/
|
|
650
671
|
export declare function mergeTheme(defaults: EspalierTheme, overrides: PartialTheme): EspalierTheme;
|
|
672
|
+
/**
|
|
673
|
+
* Compile a named context over a resolved theme — the exact theme a
|
|
674
|
+
* `context="<name>"` zone renders (ESP0175).
|
|
675
|
+
*
|
|
676
|
+
* This is the same compilation `esp-element-base` performs for a zone
|
|
677
|
+
* host, exported so a check script or the fit report can inspect a
|
|
678
|
+
* context surface without a DOM: role rebindings and the partial
|
|
679
|
+
* lightness ramp merge over the root theme, and any context-level
|
|
680
|
+
* `semanticMappings` layer on top as explicit token pins. Returns `null`
|
|
681
|
+
* when the theme does not define the context.
|
|
682
|
+
*
|
|
683
|
+
* @param theme A resolved theme (as `mergeTheme` returns).
|
|
684
|
+
* @param name The context name a zone would set in its attribute.
|
|
685
|
+
*/
|
|
686
|
+
export declare function resolveContextTheme(theme: EspalierTheme, name: string): EspalierTheme | null;
|
|
651
687
|
/**
|
|
652
688
|
* Validate a single encoded theme partial.
|
|
653
689
|
*
|
package/dist/shared/theme.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{ACCEPTED_COLOR_FORMS as ee,apcaContrast as nt,clampChannel as le,deriveSemantic as we,gamutMapToSRGB as fe,linearRgbToOklab as ot,oklchToSRGB as st,parseCssColor as N,parseOklch as rt,serializeOklch as ae,srgbToLinearRGB as at}from"./color-engine.js";import{computeVariants as Ee,parseAnchorSource as it,resolveAnchorColor as ct,resolveMappingSource as _e}from"./variant-engine.js";import{auditColorDistances as Ie,auditDataPalette as ut,DATA_SERIES_KEYS as ie,DEFAULT_DATA_PALETTE as pe,DEFAULT_DATA_RAMP_STEPS as lt,MAX_DATA_RAMP_STEPS as me,MIN_DATA_RAMP_LIGHTNESS_STEP as Le,MIN_DATA_RAMP_STEPS as he}from"./data-colors.js";const z=/^[a-z][a-z0-9-]*$/;function de(e){return it(e)}function He(e,n){return ct(e,n)}function ft(e,n){const t=de(e);if(t){const o=He(n,t);return o&&N(o)?o:null}return N(e)?e:null}const Z=["canvas","ink","accent","action","structure"],Pe={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["inputSelection","text"]],heading:[["headings","muted"],["headingsHover","ink"]]},accent:{color:[["linkHoverBg","raised2"],["inputSelectionBg","raised2"],["inputCaret","ink"]],text:[["link","accent"]],hover:[["linkHover","text"]]},action:{color:[["actionBackground","muted"]],ink:[["actionText","surface"]]},structure:{color:[["border","border"],["shadow","shadow"]]}},pt=new Set(["action.color"]),mt={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},ht={"action.ink":{role:"canvas",slot:"color"}},dt=.45;function De(e,n){const t=Fe.actionText,o=[...j].sort((p,S)=>e[p]-e[S]||j.indexOf(p)-j.indexOf(S)),a=n?o.filter(p=>n(p)>=t.targetLc):o,u=a.length>0?a:o;let f,h=1/0;for(const p of u){const S=Math.abs(e[p]-dt);S<h&&(h=S,f=p)}return f??"muted"}function gt(e,n){const t=n[e]>.5;let o=j[0];for(const a of j)(t?n[a]<n[o]:n[a]>n[o])&&(o=a);return o}const yt={"accent.hover":"text"};function bt(e,n){const t=new Map;try{const o=se(n,e),a=(u,f,h,p)=>{const S=de(f),$=S?He(p,S):null,x=$===null?null:N($),C=t.get(u)??[];C.some(s=>s.source===f&&s.chroma===x?.c)||(C.push({source:f,where:h,chroma:x?.c}),t.set(u,C))};for(const[u,f]of Object.entries(o.semanticMappings))f.source.startsWith("anchor:")&&a(u,f.source,"the root table",o.anchors);for(const[u,f]of Object.entries(o.contexts)){const h={};for(const S of Z){const $=f[S];$!==void 0&&(h[S]=$)}const p=se(o,{lightness:f.lightness,roles:h});for(const[S,$]of Object.entries(p.semanticMappings))$.source.startsWith("anchor:")&&a(S,$.source,`contexts.${u}`,p.anchors)}}catch{return new Map}return t}function te(e,n){if(e===void 0)return;if(typeof e=="string")return n==="color"?e:void 0;const t=e[n];return typeof t=="string"?t:void 0}function Ne(e,n,t,o={}){const a={},u={};for(const[f,h]of Object.entries(o.explicitMappings??{}))h!==void 0&&(u[f]=h.lightness);for(const f of Z){const h=e[f];if(h!==void 0)for(const[p,S]of Object.entries(Pe[f])){const $=ht[`${f}.${p}`];let x=te(h,p),C=!1;if(x===void 0){$&&(x=te(e[$.role],$.slot),x??=t[mt[$.role]]?.source,C=x!==void 0);const s=yt[`${f}.${p}`];s!==void 0&&(x??=te(h,s)),x??=te(h,"color")}if(x!==void 0)for(const[s,r]of S){let i=r;if(pt.has(`${f}.${p}`))i=De(n,o.actionSurfaceContrast?c=>o.actionSurfaceContrast(x,c):void 0);else if(C&&$){const c=Fe[s],m=(c&&u[c.bg])??De(n,o.actionSurfaceContrast?y=>o.actionSurfaceContrast(te(h,"color"),y):void 0);i=gt(m,n)}a[s]={source:x,lightness:i}}}}return a}const Fe={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"background",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},ge=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],ye=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],Q=["danger","success","warning","info"],$t=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],j=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],St={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},xt={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},be={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},G=.4;function $e(){const e={};for(const n of ge)e[n]={min:0,max:G};return e}const We={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90,info:244},variantChroma:{},intents:{},chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{}},Se={...We,chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{},lightness:{...St}},Ke={...We,chroma:$e(),semanticMappings:{...be},anchors:{},roles:{},contexts:{},dataPalette:{...pe},dataRamps:{},lightness:{...xt}},ce=new WeakMap;ce.set(Se,new Set),ce.set(Ke,new Set);const Ue=new Set(["__proto__","constructor","prototype"]);function A(e){return!Ue.has(e)}function kt(e,n){return Ue.has(e)?void 0:n}function Wt(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function At(e){try{const n=ze(e),t=JSON.parse(n,kt);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}const xe="\xEF\xBB\xBF";function vt(e){if(/^[\u0000-\u007f]*$/.test(e))return btoa(e);const n=new TextEncoder().encode(e);let t=xe;for(const o of n)t+=String.fromCharCode(o);return btoa(t)}function ze(e){const n=atob(e);if(!n.startsWith(xe))return n;const t=Uint8Array.from(n.slice(xe.length),o=>o.charCodeAt(0));return new TextDecoder("utf-8",{fatal:!0}).decode(t)}function ke(e){return vt(JSON.stringify(e))}function Rt(e){const n={};for(const t of Q){const o=e[t];typeof o=="string"&&(n[t]=o.startsWith("anchor:")?o:ne(o))}return n}function ne(e){if(rt(e))return e;const n=N(e);return n?ae(n):e}function je(e,n){const t={};for(const[o,a]of Object.entries(e))A(o)&&(t[o]=a);if(!n)return t;for(const[o,a]of Object.entries(n)){if(a===void 0||!A(o))continue;const u=t[o];if(u!==void 0&&typeof a=="object"&&a!==null){const f={};if(typeof u=="string")f.color=u;else for(const[h,p]of Object.entries(u))A(h)&&(f[h]=p);for(const[h,p]of Object.entries(a))p!==void 0&&A(h)&&(f[h]=p);t[o]=f;continue}t[o]=a}return t}function Ge(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const n=e,t={};for(const o of Z){const a=n[o];a!==void 0&&(t[o]=a)}if(typeof n.lightness=="object"&&n.lightness!==null&&!Array.isArray(n.lightness)){const o={};for(const a of j){const u=n.lightness[a];u!==void 0&&(o[a]=u)}t.lightness=o}return t}function Ot(e,n){const t={};for(const[o,a]of Object.entries(e)){if(!A(o)||!z.test(o))continue;const u=Ge(a);u&&(t[o]=u)}if(!n)return t;for(const[o,a]of Object.entries(n)){if(!A(o)||!z.test(o)||a===void 0)continue;const u=Ge(a);if(!u)continue;const f=t[o];t[o]={...f??{},...u,...f?.lightness||u.lightness?{lightness:{...f?.lightness,...u.lightness}}:{}}}return t}function V(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Y(e){const n={};for(const[t,o]of Object.entries(e))o!==void 0&&A(t)&&(n[t]=o);return n}function Je(e){if(!V(e))return e;const n=Y(e);return V(e.lightness)&&(n.lightness=Y(e.lightness)),n}function Ct(e,n){const t={};for(const[o,a]of Object.entries(e))A(o)&&(t[o]=Je(a));if(!n)return t;for(const[o,a]of Object.entries(n)){if(!A(o)||a===void 0)continue;const u=t[o];if(!V(u)||!V(a)){t[o]=Je(a);continue}const f={...Y(u),...Y(a)};V(u.lightness)&&V(a.lightness)?f.lightness={...Y(u.lightness),...Y(a.lightness)}:V(a.lightness)&&(f.lightness=Y(a.lightness)),t[o]=f}return t}function Mt(e){const n={};for(const[t,o]of Object.entries(e)){if(!A(t))continue;if(typeof o=="string"){n[t]=ne(o);continue}const a={};for(const[u,f]of Object.entries(o))A(u)&&(a[u]=typeof f=="string"?ne(f):f);n[t]=a}return n}function oe(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:ne(e)}function Tt(e){const n={};for(const t of ie)n[t]=oe(e[t]);return n}function Ve(e,n){const t={};for(const[o,a]of Object.entries(e))A(o)&&z.test(o)&&a&&typeof a=="object"&&!Array.isArray(a)&&(t[o]={...a});if(!n)return t;for(const[o,a]of Object.entries(n)){if(!A(o)||!z.test(o)||!a||typeof a!="object"||Array.isArray(a))continue;const u=t[o],f=u!==void 0&&a.type!==void 0&&a.type!==u.type;t[o]={...f?{}:u??{},...a}}return t}function Bt(e){const n={};for(const[t,o]of Object.entries(e))if(A(t)){if(o.type==="sequential"&&typeof o.source=="string"){n[t]={...o,source:oe(o.source)};continue}if(o.type==="diverging"&&typeof o.start=="string"&&typeof o.end=="string"){n[t]={...o,start:oe(o.start),end:oe(o.end),...typeof o.neutral=="string"?{neutral:oe(o.neutral)}:{}};continue}n[t]={...o}}return n}function Ye(e){const n=N(e.seedColor);if(!n)return;const t=Ee(n,e);return(o,a)=>{const u=_e(o,t,e.anchors)??t.primary,f=e.chroma.actionBackground,h=we(u,e.lightness[a],f.min,f.max),p={l:h.l>.5?0:1,c:0,h:0};return Math.abs(nt(p,h))}}function wt(e){const n=ce.get(e);if(n)return new Set(n);const t=new Set,o=Ne(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:Ye(e)});for(const[a,u]of Object.entries(o)){const f=e.semanticMappings[a];(f.source!==u.source||f.lightness!==u.lightness)&&t.add(a)}return t}function se(e,n){const t={...e.roles,...n.roles},o=Ot(e.contexts,n.contexts),a={...e.lightness,...n.lightness},u=Mt(je(e.anchors,n.anchors)),f=typeof n.seedColor=="string"?ne(n.seedColor):e.seedColor,h=n.semanticMappings,p={...e.angles,...n.angles},S={...e.semanticHues,...n.semanticHues},$={...e.variantChroma,...n.variantChroma},x=Rt({...e.intents,...n.intents}),C=re(e.chroma,n.chroma),s=Tt(re(e.dataPalette,n.dataPalette)),r=Bt(Ve(e.dataRamps,n.dataRamps)),i=wt(e),c=new Set(i),m={};for(const g of i)m[g]=e.semanticMappings[g];for(const[g,b]of Object.entries(h??{}))b!==void 0&&(c.add(g),m[g]=b);const y=re(e.semanticMappings,h),I=Ye({angles:p,anchors:u,chroma:C,intents:x,lightness:a,seedColor:f,semanticHues:S,variantChroma:$}),D=Ne(t,a,y,{explicitMappings:m,actionSurfaceContrast:I}),W={};for(const[g,b]of Object.entries(D))c.has(g)||(W[g]=b);const l=re(re(e.semanticMappings,W),h),d={...e,seedColor:f,fontBody:n.fontBody??e.fontBody,fontHeadings:n.fontHeadings??e.fontHeadings,fontBrand:n.fontBrand??e.fontBrand,fontMonospace:n.fontMonospace??e.fontMonospace,fontWeightBody:String(n.fontWeightBody??e.fontWeightBody),fontWeightHeadings:String(n.fontWeightHeadings??e.fontWeightHeadings),fontWeightBrand:String(n.fontWeightBrand??e.fontWeightBrand),fontWeightMonospace:String(n.fontWeightMonospace??e.fontWeightMonospace),stylesheets:n.stylesheets??[...e.stylesheets],rootFontSize:n.rootFontSize??e.rootFontSize,typeRatio:n.typeRatio??e.typeRatio,spaceRatio:n.spaceRatio??e.spaceRatio,borderRadius:n.borderRadius??e.borderRadius,viewportMin:n.viewportMin??e.viewportMin,viewportMax:n.viewportMax??e.viewportMax,angles:p,semanticHues:S,variantChroma:$,intents:x,lightness:a,chroma:C,semanticMappings:l,anchors:u,roles:t,contexts:o,dataPalette:s,dataRamps:r};return n.pageBackgroundImage!==void 0&&(d.pageBackgroundImage=n.pageBackgroundImage),n.pageBackgroundImageOpacity!==void 0&&(d.pageBackgroundImageOpacity=n.pageBackgroundImageOpacity),n.boxBackgroundImage!==void 0&&(d.boxBackgroundImage=n.boxBackgroundImage),n.boxBackgroundImageOpacity!==void 0&&(d.boxBackgroundImageOpacity=n.boxBackgroundImageOpacity),n.vellumOpacity!==void 0&&(d.vellumOpacity=n.vellumOpacity),n.vellumBackgroundImage!==void 0&&(d.vellumBackgroundImage=n.vellumBackgroundImage),n.vellumBackgroundImageOpacity!==void 0&&(d.vellumBackgroundImageOpacity=n.vellumBackgroundImageOpacity),ce.set(d,new Set(c)),d}function re(e,n){if(!n)return{...e};const t={...e};for(const o of Object.keys(n)){const a=n[o];a!==void 0&&(t[o]=a)}return t}function Ae(e){let n;try{n=ze(e)}catch{return{error:"Failed to decode Base64 string."}}let t;try{t=JSON.parse(n)}catch{return{error:"Decoded string is not valid JSON."}}return typeof t!="object"||t===null||Array.isArray(t)?{error:"Theme must be a JSON object."}:{value:t}}function Kt(e){const n=Ae(e);return n.error!==void 0?{valid:!1,errors:[n.error],warnings:[]}:ve(n.value)}function ve(e,n=Se){const t=[],o=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):N(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${ee}.`));for(const s of["fontBody","fontHeadings","fontBrand","fontMonospace"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);const a=["normal","bold","lighter","bolder"],u=["inherit","initial","unset","revert","revert-layer"];for(const s of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(s in e){const r=e[s];if(typeof r=="number")(r<1||r>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got ${r}).`);else if(typeof r=="string"){const i=a.includes(r)||u.includes(r);if(/^\d+$/.test(r)){const m=Number(r);(m<1||m>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got "${r}").`)}else i||o.push(`${s} = "${r}" is not a standard font-weight value.`)}else t.push(`${s} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(s=>typeof s!="string")&&t.push("Every entry in stylesheets must be a string."):t.push("stylesheets must be an array of strings."));const f=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[s,r,i]of f)if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const c=e[s];r!==void 0&&c<r&&t.push(`${s} must be \u2265 ${r} (got ${c}).`),i!==void 0&&c>i&&o.push(`${s} = ${c} is unusually high (max ${i}).`)}for(const s of["typeRatio","spaceRatio"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];r<=1&&t.push(`${s} must be > 1 (got ${r}).`);const i=s==="typeRatio"?1.3:2;r>i&&o.push(`${s} = ${r} is very high (max ${i}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const s=e.viewportMin,r=e.viewportMax;typeof s=="number"&&typeof r=="number"&&s>=r&&t.push(`viewportMin (${s}) must be less than viewportMax (${r}).`)}if("angles"in e)if(typeof e.angles!="object"||e.angles===null)t.push("angles must be an object.");else{const s=e.angles;for(const r of["analogous","complementary","splitComplementary","triadic"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`angles.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.push(`angles.${r} = ${i} is outside 0\u2013360.`)}}if("semanticHues"in e)if(typeof e.semanticHues!="object"||e.semanticHues===null)t.push("semanticHues must be an object.");else{const s=e.semanticHues;for(const r of["danger","success","warning","info"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`semanticHues.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.push(`semanticHues.${r} = ${i} is outside 0\u2013360.`)}}if("variantChroma"in e)if(typeof e.variantChroma!="object"||e.variantChroma===null)t.push("variantChroma must be an object.");else{const s=e.variantChroma;for(const r of $t)if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`variantChroma["${r}"] must be a finite number.`);else{const i=s[r];i<0&&t.push(`variantChroma["${r}"] must be \u2265 0 (got ${i}).`),i>G&&o.push(`variantChroma["${r}"] = ${i} exceeds ${G}.`)}}function h(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const c of j)if(c in i)if(typeof i[c]!="number"||!isFinite(i[c]))t.push(`${r}.${c} must be a finite number.`);else{const m=i[c];(m<0||m>1)&&t.push(`${r}.${c} must be 0\u20131 (got ${m}).`)}}if("lightness"in e&&h(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const s=e.chroma,r=bt(e,n);for(const i of ge)if(i in s){const c=s[i];if(typeof c!="object"||c===null){t.push(`chroma.${i} must be { min, max }.`);continue}const m=c;for(const I of r.get(i)??[])I.chroma!==void 0&&typeof m.min=="number"&&typeof m.max=="number"&&(I.chroma<m.min-1e-9||I.chroma>m.max+1e-9)&&o.push(`chroma.${i} clamps the anchor-sourced token ${i} ("${I.source}", effective in ${I.where}) and moves it off its declared swatch. Remove the band if that is unintended \u2014 anchors otherwise keep their own chroma.`);const y=c;(typeof y.min!="number"||y.min<0)&&t.push(`chroma.${i}.min must be \u2265 0.`),(typeof y.max!="number"||y.max<0||y.max>G)&&t.push(`chroma.${i}.max must be 0\u2013${G}.`),typeof y.min=="number"&&typeof y.max=="number"&&y.min>y.max&&t.push(`chroma.${i}.min (${y.min}) must be \u2264 max (${y.max}).`)}}if("anchors"in e)if(typeof e.anchors!="object"||e.anchors===null||Array.isArray(e.anchors))t.push("anchors must be an object of named colors.");else for(const[s,r]of Object.entries(e.anchors))if(A(s)?z.test(s)||t.push(`anchors: "${s}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${s}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),ye.includes(s)&&t.push(`anchors: "${s}" collides with a reserved color source name.`),typeof r=="string")N(r)||t.push(`anchors.${s} is not a valid CSS color: "${r}". Accepted forms: ${ee}.`);else if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const i=r;typeof i.color!="string"&&t.push(`anchors.${s} must declare its base "color".`);for(const[c,m]of Object.entries(i))A(c)?c!=="color"&&!z.test(c)&&t.push(`anchors.${s}: "${c}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${s}: "${c}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof m!="string"?t.push(`anchors.${s}.${c} must be a CSS color string.`):N(m)||t.push(`anchors.${s}.${c} is not a valid CSS color: "${m}". Accepted forms: ${ee}.`)}else t.push(`anchors.${s} must be a color string or a { color, \u2026slots } object.`);const p=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[s,r]of Object.entries(e.anchors))p.set(s,r);function S(s,r){const i=de(s);if(!i){t.push(`${r} "${s}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!p.has(i.name)){const c=[...p.keys()];t.push(`${r} references undeclared anchor "${i.name}". Declared anchors: ${c.length>0?c.join(", "):"(none)"}.`);return}if(i.slot!==void 0){const c=p.get(i.name);if(typeof(typeof c=="object"&&c!==null&&!Array.isArray(c)?c[i.slot]:void 0)!="string"){const y=typeof c=="object"&&c!==null?Object.keys(c).filter(I=>I!=="color"):[];t.push(`${r} references unknown slot "${i.slot}" on anchor "${i.name}". Declared slots: ${y.length>0?y.join(", "):"(none)"}.`)}}}function $(s,r){if(s.startsWith("anchor:")){S(s,r);return}ye.includes(s)||t.push(`${r} must be one of: ${ye.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("intents"in e)if(typeof e.intents!="object"||e.intents===null||Array.isArray(e.intents))t.push("intents must be an object.");else for(const[s,r]of Object.entries(e.intents)){const i=`intents.${s}`;if(!Q.includes(s)){t.push(`${i} is not a status family; expected one of: ${Q.join(", ")}.`);continue}if(typeof r!="string"){t.push(`${i} must be a string (a CSS color or an anchor: reference).`);continue}if(r.startsWith("anchor:")){S(r,i);continue}N(r)||t.push(`${i} "${r}" is not a supported color form or anchor: reference. Accepted forms: ${ee}, or anchor:<name> / anchor:<name>.<slot>. An override retunes a family with a declared color; it never points one family at another \u2014 retune, never reassign.`)}function x(s,r){if(s.startsWith("anchor:")){S(s,r);return}N(s)||t.push(`${r} is not a valid CSS color: "${s}". Accepted forms: ${ee}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("dataPalette"in e)if(typeof e.dataPalette!="object"||e.dataPalette===null||Array.isArray(e.dataPalette))t.push("dataPalette must be an object with series1\u2013series8 color values.");else{const s=e.dataPalette;for(const[r,i]of Object.entries(s)){if(!ie.includes(r)){t.push(`dataPalette.${r} is not a series slot; expected one of: ${ie.join(", ")}.`);continue}typeof i!="string"?t.push(`dataPalette.${r} must be a CSS color or anchor reference string.`):x(i,`dataPalette.${r}`)}}if("dataRamps"in e)if(typeof e.dataRamps!="object"||e.dataRamps===null||Array.isArray(e.dataRamps))t.push("dataRamps must be an object of named ramp declarations.");else for(const[s,r]of Object.entries(e.dataRamps)){if(A(s)?z.test(s)||t.push(`dataRamps: "${s}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${s}" is a reserved JavaScript property name and cannot be a ramp name; rename it.`),typeof r!="object"||r===null||Array.isArray(r)){t.push(`dataRamps.${s} must be a sequential or diverging ramp object.`);continue}const i=r,c=i.steps??lt;if((typeof c!="number"||!Number.isInteger(c)||c<he||c>me)&&t.push(`dataRamps.${s}.steps must be an integer from ${he} through ${me}.`),i.type==="sequential"){typeof i.source!="string"?t.push(`dataRamps.${s}.source must be a CSS color or anchor reference string.`):x(i.source,`dataRamps.${s}.source`);const m=i.lightnessStart??.95,y=i.lightnessEnd??.25;for(const[I,D]of[["lightnessStart",m],["lightnessEnd",y]])(typeof D!="number"||!Number.isFinite(D)||D<0||D>1)&&t.push(`dataRamps.${s}.${I} must be a finite number from 0 through 1.`);typeof m=="number"&&typeof y=="number"&&m<=y?t.push(`dataRamps.${s}.lightnessStart must be greater than lightnessEnd.`):typeof m=="number"&&Number.isFinite(m)&&typeof y=="number"&&Number.isFinite(y)&&typeof c=="number"&&Number.isInteger(c)&&c>=he&&c<=me&&(m-y)/(c-1)<=Le&&t.push(`dataRamps.${s} lightness bounds must leave more than ${Le} lightness between serialized stops.`);continue}if(i.type==="diverging"){typeof c=="number"&&Number.isInteger(c)&&c%2===0&&t.push(`dataRamps.${s}.steps must be odd so the neutral is the exact midpoint.`);for(const m of["start","end"])typeof i[m]!="string"?t.push(`dataRamps.${s}.${m} must be a CSS color or anchor reference string.`):x(i[m],`dataRamps.${s}.${m}`);"neutral"in i&&(typeof i.neutral!="string"?t.push(`dataRamps.${s}.neutral must be a CSS color or anchor reference string.`):x(i.neutral,`dataRamps.${s}.neutral`));continue}t.push(`dataRamps.${s}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const s=se(Se,e),r={};let i=!0;for(const c of ie){const m=ft(s.dataPalette[c],s.anchors);if(!m){i=!1;break}r[c]=m}if(i)for(const c of ut(r))o.push(`dataPalette.${c.series[0]} and dataPalette.${c.series[1]} are only ${c.distance.toFixed(4)} apart under ${c.simulation} simulation (minimum ${c.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function C(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const[c,m]of Object.entries(i)){const y=`${r}.${c}`;if(!Z.includes(c)){t.push(`${y} is not a role; expected one of: ${Z.join(", ")}. (The status family is reserved and is not a role.)`);continue}const I=c,D=Pe[I];if(typeof m=="string"){$(m,y);continue}if(typeof m!="object"||m===null||Array.isArray(m)){t.push(`${y} must be a color source or a { color, \u2026slots } object.`);continue}const W=m;typeof W.color!="string"&&t.push(`${y} must declare its base "color".`);for(const[l,d]of Object.entries(W)){if(!Object.prototype.hasOwnProperty.call(D,l)||!A(l)){const g=Object.keys(D).filter(b=>b!=="color");t.push(`${y}.${l} is not a slot of the ${I} role. Declared slots: ${g.length>0?g.join(", "):"(none)"}.`);continue}typeof d!="string"?t.push(`${y}.${l} must be a color source string.`):$(d,`${y}.${l}`)}}}if("roles"in e&&C(e.roles,"roles"),"contexts"in e)if(typeof e.contexts!="object"||e.contexts===null||Array.isArray(e.contexts))t.push("contexts must be an object.");else for(const[s,r]of Object.entries(e.contexts)){if(!A(s)||!z.test(s)){t.push(`contexts.${s} must be a lowercase slug matching ${z.source}.`);continue}if(typeof r!="object"||r===null||Array.isArray(r)){C(r,`contexts.${s}`);continue}const i=r,c=Object.fromEntries(Object.entries(i).filter(([m])=>m!=="lightness"));C(c,`contexts.${s}`),"lightness"in i&&h(i.lightness,`contexts.${s}.lightness`)}if("semanticMappings"in e)if(typeof e.semanticMappings!="object"||e.semanticMappings===null)t.push("semanticMappings must be an object.");else{const s=e.semanticMappings;for(const r of ge)if(r in s){const i=s[r];if(typeof i!="object"||i===null){t.push(`semanticMappings.${r} must be { source, lightness }.`);continue}const c=i;typeof c.source!="string"?t.push(`semanticMappings.${r}.source must be a string.`):$(c.source,`semanticMappings.${r}.source`),(typeof c.lightness!="string"||!j.includes(c.lightness))&&t.push(`semanticMappings.${r}.lightness must be one of: ${j.join(", ")}.`)}}for(const s of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);for(const s of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];(r<0||r>1)&&t.push(`${s} must be 0\u20131 (got ${r}).`)}return o.push(...Et(e,n)),{valid:t.length===0,errors:t,warnings:o}}const O=.045;function Et(e,n){try{return _t(e,n)}catch{return[]}}function _t(e,n){const t=se(n,e),o=Ze(t),a=[...o],u=new Set(o);for(const[f,h]of Object.entries(t.contexts)){const p={};for(const $ of Z){const x=h[$];x!==void 0&&(p[$]=x)}const S=se(t,{lightness:h.lightness,roles:p});for(const $ of Ze(S))u.has($)||a.push(`contexts.${f}: ${$}`)}return a}function It(e){const n=st(fe(e)),t=at(n);return ot({r:le(t.r),g:le(t.g),b:le(t.b)})}function q(e,n){return Math.hypot(e.L-n.L,e.a-n.a,e.b-n.b)}function J(e){return It(N(ae(fe(e))))}function qe(e){return(Math.floor(e*1e4)/1e4).toFixed(4)}const X=2,Xe=1e-4;function Ze(e){const n=N(e.seedColor);if(!n)return[];const t=Ee(n,e),o=e.semanticMappings.actionBackground,a=e.chroma.actionBackground,u=e.lightness[o.lightness],f=(l,d,g,b)=>fe(we(l,d,g,b)),h=Q.map(l=>({name:l,base:t[l]})),p=[];if(Q.includes(o.source))p.push(`actionBackground is sourced from the "${o.source}" status family: ordinary and ${o.source}-intent action surfaces render identically (their labels may still differ). Remap the action to a non-status source \u2014 retuning "${o.source}" via intents moves both colors together.`);else{const l=_e(o.source,t,e.anchors);l&&h.push({name:"action",base:l})}const S=Ie(h.map(({name:l,base:d})=>[l,ae(f(d,u,a.min,a.max))]),O,["normal"]);if(S.length===0)return p;const $=new Map,x=(l,d)=>{const g=`${l}:${d}`;let b=$.get(g);if(!b){b=[];for(let B=0;B<360;B+=X)b.push(J({l,c:d,h:B}));$.set(g,b)}return b},C=O-.002,s=(l,d,g,b)=>{const B=Math.hypot(l.a,l.b),M=Math.atan2(l.b,l.a)*180/Math.PI+180;let E=0;for(const T of g===b?[b]:[g,b]){if(T+B<O-1e-4)continue;let L=M,R=q(J({l:d,c:T,h:M}),l);if(R>=O)return R;const P=x(d,T);for(let v=0;v<P.length;v+=1){const k=q(P[v],l);if(k>=O)return k;k>R&&(R=k,L=v*X)}let H=L;for(let v=L-X;v<=L+X;v+=.1){const k=q(J({l:d,c:T,h:v}),l);if(k>=O)return k;k>R&&(R=k,H=v)}if(R>=C)for(let v=H-.1;v<=H+.1;v+=.001){const k=q(J({l:d,c:T,h:v}),l);if(k>=O)return k;k>R&&(R=k)}R>E&&(E=R)}return E},r=(l,d,g)=>{const b=d===g?[g]:[d,g];let B=0;for(const M of b)for(const E of b){if(M+E<O-1e-4)continue;const T=x(l,M),L=x(l,E);let R=0,P=0,H=-1;for(let _=0;_<T.length;_+=1)for(let F=0;F<L.length;F+=1){const K=q(T[_],L[F]);if(K>=O)return K;K>H&&(H=K,R=_*X,P=F*X)}const v=(_,F,K,Re)=>{const Oe=[];for(let U=F-K;U<=F+K;U+=Re)Oe.push({h:U,lab:J({l,c:E,h:U})});let ue=-1,Ce=_,Me=F;for(let U=_-K;U<=_+K;U+=Re){const tt=J({l,c:M,h:U});for(const Te of Oe){const Be=q(tt,Te.lab);Be>ue&&(ue=Be,Ce=U,Me=Te.h)}}return{distance:ue,hueA:Ce,hueB:Me}},k=v(R,P,X,.1);if(k.distance>=O)return k.distance;let w=Math.max(H,k.distance);if(w>=C){const _=v(k.hueA,k.hueB,.1,.001);if(_.distance>w&&(w=_.distance),w>=O)return w}w>B&&(B=w)}return B},i=l=>Q.includes(l),c=(l,d,g,b,B)=>{const M=J(f(l.base,g,b,B)),E=J(f(d.base,g,b,B));if(q(M,E)>=O)return{outcome:"direct"};const T=i(l.name)&&i(d.name),L=[l,d].filter(H=>i(H.name)),R=T?"one of them":`"${i(l.name)?l.name:d.name}"`;let P;for(const H of L){const v=s(H===l?E:M,g,b,B);if(v>=O)return{outcome:"retune",target:R};v>=O-Xe&&(P=P??R)}if(T){const H=r(g,b,B);if(H>=O)return{outcome:"retune",target:"both"};H>=O-Xe&&(P=P??"both")}return P!==void 0?{outcome:"near",target:P}:{outcome:"no"}},m=l=>l.outcome==="direct"?4:l.outcome==="retune"?l.target==="both"?2:3:l.outcome==="near"?1:0,y=l=>[...l].sort().join("|"),I=new Set(Ie(h.map(({name:l,base:d})=>[l,ae(f(d,u,0,G))]),O,["normal"]).map(l=>y(l.pair))),D=new Map(h.map(l=>[l.name,l])),W=new Map;for(const{pair:l,distance:d}of S){const g=D.get(l[0]),b=D.get(l[1]),B=i(g.name)&&i(b.name),M=c(g,b,u,a.min,a.max);if(M.outcome==="direct"||M.outcome==="retune"){const w=M.target??(B?"one of them":`"${i(g.name)?g.name:b.name}"`);I.has(y(l))?p.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish under normal vision (distance ${qe(d)} < ${O}); status meanings must stay distinguishable \u2014 retune ${w} via intents.`):p.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish as rendered (distance ${qe(d)} < ${O}); the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }) pushes them together \u2014 widen the band, or retune ${w} via intents.`);continue}const E=c(g,b,u,0,G);let T={outcome:"no"};for(let w=1;w<=19&&T.outcome!=="direct";w+=1){const _=w*.05;if(Math.abs(_-u)<.001)continue;const F=c(g,b,_,a.min,a.max);m(F)>m(T)&&(T=F)}let L={outcome:"no"};const R=E.outcome==="direct"||E.outcome==="retune",P=T.outcome==="direct"||T.outcome==="retune";if(!R&&!P)for(let w=1;w<=19&&L.outcome!=="direct";w+=1){const _=c(g,b,w*.05,0,G);m(_)>m(L)&&(L=_)}const H=Lt(E,T,L),v=`${M.outcome}|${H}`;let k=W.get(v);k||(k=[],W.set(v,k)),k.push(l)}for(const[l,d]of W){const g=l.indexOf("|"),b=l.slice(0,g),B=l.slice(g+1),M=d.map(([L,R])=>`"${L}"/"${R}"`),E=M.length>1?`${M.slice(0,-1).join(", ")} and ${M[M.length-1]}`:M[0],T=b==="near"?`Status colors ${E} may not separate by retuning as rendered: at the action stop's lightness (${u}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), the closest reachable retune found comes within the audit's search margin of the ${O} threshold`:`Status colors ${E} cannot be separated as rendered: at the action stop's lightness (${u}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), no intent retuning can pull ${d.length>1?"these pairs":"the pair"} ${O} apart`;p.push(T+B)}return p}function Lt(e,n,t){if(e.outcome==="direct"&&n.outcome==="direct")return" \u2014 widen the chroma band or move the action lightness stop.";if(e.outcome==="direct")return n.outcome==="no"?"; no other action lightness stop can help while the band holds \u2014 widen the chroma band.":" \u2014 widen the chroma band.";if(n.outcome==="direct")return e.outcome==="no"?"; no wider chroma band can help at this lightness \u2014 move the action lightness stop.":" \u2014 move the action lightness stop.";if(e.outcome==="retune"&&n.outcome==="retune")return` \u2014 widen the chroma band or move the action lightness stop, then retune ${e.target} via intents.`;if(e.outcome==="retune")return n.outcome==="no"?`; no other action lightness stop can help while the band holds \u2014 widen the chroma band, then retune ${e.target} via intents.`:` \u2014 widen the chroma band, then retune ${e.target} via intents.`;if(n.outcome==="retune")return e.outcome==="no"?`; no wider chroma band can help at this lightness \u2014 move the action lightness stop, then retune ${n.target} via intents.`:` \u2014 move the action lightness stop, then retune ${n.target} via intents.`;const o=e.outcome==="no"&&n.outcome==="no"?"; neither a wider chroma band alone nor another stop alone can help":"; neither a wider chroma band alone nor another stop alone provably helps";return t.outcome==="direct"?`${o} \u2014 change the band and the stop together.`:t.outcome==="retune"?`${o} \u2014 change the band and the stop together, then retune ${t.target} via intents.`:"; no explored band or stop change provably separates this pair."}function Ut(e,n){const t=Ae(e),o=Ae(n),a=t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:ve(t.value),u=o.error!==void 0?{valid:!1,errors:[o.error],warnings:[]}:ve(o.value,Ke),f=[...a.errors.map(p=>`light: ${p}`),...u.errors.map(p=>`dark: ${p}`)],h=[...a.warnings.map(p=>`light: ${p}`),...u.warnings.map(p=>`dark: ${p}`)];if(a.valid&&u.valid){const p=new Set(Object.keys(t.value?.contexts??{})),S=new Set(Object.keys(o.value?.contexts??{})),$=[...S].filter(C=>!p.has(C)).sort(),x=[...p].filter(C=>!S.has(C)).sort();($.length>0||x.length>0)&&f.push(`contexts must declare the same names in both schemes. Missing from light: ${$.join(", ")||"(none)"}. Missing from dark: ${x.join(", ")||"(none)"}.`)}return{valid:f.length===0,errors:f,warnings:h}}const Ht=["anchors","angles","contexts","dataPalette","dataRamps","intents","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function Pt(e,n){const t={};for(const[o,a]of Object.entries(e))A(o)&&(t[o]=a);for(const[o,a]of Object.entries(n))a!==void 0&&A(o)&&(t[o]=a);for(const o of Ht){const a=e[o],u=n[o];if(a&&typeof a=="object"&&!Array.isArray(a)&&u&&typeof u=="object"&&!Array.isArray(u)){if(o==="anchors"){t[o]=je(a,u);continue}if(o==="contexts"){t[o]=Ct(a,u);continue}if(o==="dataRamps"){t[o]=Ve(a,u);continue}const f={};for(const[h,p]of Object.entries(a))A(h)&&(f[h]=p);for(const[h,p]of Object.entries(u))p!==void 0&&A(h)&&(f[h]=p);t[o]=f}}return t}function zt(...e){let n={};for(const t of e){if(!t)continue;const o=At(t);o&&(n=Pt(n,o))}return ke(n)}function Qe(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const et={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function jt(e){return ke({...et,pageBackgroundImage:`url("${Qe(e)}")`,pageBackgroundImageOpacity:.5})}function Gt(e){return ke({...et,pageBackgroundImage:`url("${Qe(e)}")`,pageBackgroundImageOpacity:.55})}export{z as ANCHOR_SLUG_PATTERN,ye as COLOR_SOURCES,xt as DEFAULT_DARK_LIGHTNESS,Ke as DEFAULT_DARK_THEME,St as DEFAULT_LIGHT_LIGHTNESS,Se as DEFAULT_LIGHT_THEME,be as DEFAULT_SEMANTIC_MAPPINGS,j as LIGHTNESS_KEYS,Ht as NESTED_THEME_KEYS,Z as ROLE_NAMES,ht as ROLE_PAIRED_INK,Pe as ROLE_TOKEN_PLAN,ge as SEMANTIC_COLOR_NAMES,Q as STATUS_COLOR_SOURCES,Fe as TOKEN_PAIRINGS,$t as VARIANT_COLOR_SOURCES,Gt as buildTaprootDarkTheme,jt as buildTaprootLightTheme,Ne as compileRoles,ke as encodeTheme,zt as layerThemes,Pt as mergePartials,se as mergeTheme,de as parseAnchorSource,At as parseTheme,He as resolveAnchorColor,ft as resolveDataColorSource,Wt as semanticToCSS,Kt as validateTheme,Ut as validateThemePair};
|
|
1
|
+
import{UNSAFE_KEYS as st,isSafeKey as v}from"./unsafe-keys.js";import{ACCEPTED_COLOR_FORMS as te,apcaContrast as rt,clampChannel as me,deltaEOK as at,deriveSemantic as ae,gamutMapToSRGB as de,linearRgbToOklab as it,oklchToSRGB as ct,parseCssColor as W,parseOklch as ut,serializeOklch as ie,srgbToLinearRGB as ft}from"./color-engine.js";import{computeVariants as he,parseAnchorSource as lt,resolveAnchorColor as pt,resolveMappingSource as ce}from"./variant-engine.js";import{auditColorDistances as He,auditDataPalette as mt,DATA_SERIES_KEYS as ue,DEFAULT_DATA_PALETTE as ge,DEFAULT_DATA_RAMP_STEPS as dt,MAX_DATA_RAMP_STEPS as ye,MIN_DATA_RAMP_LIGHTNESS_STEP as Le,MIN_DATA_RAMP_STEPS as be}from"./data-colors.js";const V=/^[a-z][a-z0-9-]*$/;function $e(e){return lt(e)}function Pe(e,n){return pt(e,n)}function ht(e,n){const t=$e(e);if(t){const o=Pe(n,t);return o&&W(o)?o:null}return W(e)?e:null}const ne=["canvas","ink","accent","action","structure"],Se={canvas:{color:[["background","surface"],["layer1","raised1"],["layer2","raised2"],["layer3","raised3"],["layer4","raised4"]]},ink:{color:[["text","text"],["inputSelection","text"]],heading:[["headings","muted"],["headingsHover","ink"]]},accent:{color:[["linkHoverBg","raised2"],["inputSelectionBg","raised2"],["inputCaret","ink"]],text:[["link","accent"]],hover:[["linkHover","text"]]},action:{color:[["actionBackground","muted"]],ink:[["actionText","surface"]]},structure:{color:[["border","border"],["shadow","shadow"]]}},gt=new Set(["action.color"]),yt={canvas:"background",ink:"text",accent:"link",action:"actionBackground",structure:"border"},bt={"action.ink":{role:"canvas",slot:"color"}},$t=.45,St=.045;function De(e,n,t){const o=We.actionText,a=[...j].sort((g,x)=>e[g]-e[x]||j.indexOf(g)-j.indexOf(x)),c=n?a.filter(g=>n(g)>=o.targetLc):a,f=t?c.filter(g=>t(g)>=St):c,p=f.length>0?f:c,m=p.length>0?p:a;let O,k=1/0;for(const g of m){const x=Math.abs(e[g]-$t);x<k&&(k=x,O=g)}return O??"muted"}function kt(e,n){const t=n[e]>.5;let o=j[0];for(const a of j)(t?n[a]<n[o]:n[a]>n[o])&&(o=a);return o}const xt={"accent.hover":"text"};function At(e,n){const t=new Map;try{const o=le(n,e),a=(c,f,p,m)=>{const O=$e(f),k=O?Pe(m,O):null,g=k===null?null:W(k),x=t.get(c)??[];x.some(P=>P.source===f&&P.chroma===g?.c)||(x.push({source:f,where:p,chroma:g?.c}),t.set(c,x))};for(const[c,f]of Object.entries(o.semanticMappings))f.source.startsWith("anchor:")&&a(c,f.source,"the root table",o.anchors);for(const c of Object.keys(o.contexts)){const f=Xe(o,c);if(f)for(const[p,m]of Object.entries(f.semanticMappings))m.source.startsWith("anchor:")&&a(p,m.source,`contexts.${c}`,f.anchors)}}catch{return new Map}return t}function q(e,n){if(e===void 0)return;if(typeof e=="string")return n==="color"?e:void 0;const t=e[n];return typeof t=="string"?t:void 0}function Ne(e,n,t,o={}){const a={},c={};for(const[f,p]of Object.entries(o.explicitMappings??{}))p!==void 0&&(c[f]=p.lightness);for(const f of ne){const p=e[f];if(p!==void 0)for(const[m,O]of Object.entries(Se[f])){const k=bt[`${f}.${m}`];let g=q(p,m),x=!1;if(g===void 0){k&&(g=q(e[k.role],k.slot),g??=t[yt[k.role]]?.source,x=g!==void 0);const P=xt[`${f}.${m}`];P!==void 0&&(g??=q(p,P)),g??=q(p,"color")}if(g!==void 0)for(const[P,s]of O){let r=s;if(gt.has(`${f}.${m}`))r=De(n,o.actionSurfaceContrast?i=>o.actionSurfaceContrast(g,i):void 0,o.actionSurfaceSeparation?i=>o.actionSurfaceSeparation(g,i):void 0);else if(x&&k){const i=We[P],u=(i&&c[i.bg])??De(n,o.actionSurfaceContrast?d=>o.actionSurfaceContrast(q(p,"color"),d):void 0,o.actionSurfaceSeparation?d=>o.actionSurfaceSeparation(q(p,"color"),d):void 0);r=kt(u,n)}a[P]={source:g,lightness:r}}}}return a}const We={text:{bg:"background",targetLc:75},dangerText:{bg:"background",targetLc:75},headings:{bg:"background",targetLc:60},headingsHover:{bg:"background",targetLc:60},link:{bg:"background",targetLc:75},linkHover:{bg:"linkHoverBg",targetLc:75},actionText:{bg:"actionBackground",targetLc:75},inputCaret:{bg:"layer2",targetLc:60},inputSelection:{bg:"inputSelectionBg",targetLc:60}},Q=["background","layer1","layer2","layer3","layer4","actionBackground","actionText","border","shadow","text","dangerText","headings","headingsHover","link","linkHover","linkHoverBg","inputCaret","inputSelection","inputSelectionBg"],ke=["primary","analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],ee=["danger","success","warning","info"],Mt=["analogous-left","analogous-right","complementary","split-complementary-left","split-complementary-right","triadic-left","triadic-right","danger","success","warning","info"],j=["surface","raised1","raised2","raised3","raised4","accent","muted","text","border","ink","shadow"],vt={surface:.99,raised1:.97,raised2:.9,raised3:.8,raised4:.72,accent:.5,muted:.45,text:.35,border:.3,ink:.25,shadow:.2},Ot={surface:.15,raised1:.2,raised2:.3,raised3:.4,raised4:.36,accent:.6,muted:.75,text:.85,border:.7,ink:.95,shadow:.6},xe={background:{source:"primary",lightness:"surface"},layer1:{source:"primary",lightness:"raised1"},layer2:{source:"primary",lightness:"raised2"},layer3:{source:"primary",lightness:"raised3"},layer4:{source:"primary",lightness:"raised4"},actionBackground:{source:"primary",lightness:"raised3"},actionText:{source:"primary",lightness:"ink"},border:{source:"primary",lightness:"border"},shadow:{source:"primary",lightness:"shadow"},text:{source:"primary",lightness:"text"},dangerText:{source:"danger",lightness:"text"},headings:{source:"primary",lightness:"muted"},headingsHover:{source:"primary",lightness:"text"},link:{source:"complementary",lightness:"accent"},linkHover:{source:"complementary",lightness:"text"},linkHoverBg:{source:"triadic-left",lightness:"raised2"},inputCaret:{source:"triadic-right",lightness:"ink"},inputSelection:{source:"complementary",lightness:"text"},inputSelectionBg:{source:"triadic-left",lightness:"raised2"}},J=.4;function Ae(){const e={};for(const n of Q)e[n]={min:0,max:J};return e}const Fe={seedColor:"oklch(0.7 0.125 216)",fontBody:"",fontHeadings:"",fontBrand:"",fontMonospace:"",fontWeightBody:"normal",fontWeightHeadings:"bold",fontWeightBrand:"bold",fontWeightMonospace:"normal",stylesheets:[],rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200,angles:{analogous:30,complementary:180,splitComplementary:30,triadic:120},semanticHues:{danger:27,success:150,warning:90,info:244},variantChroma:{},intents:{},chroma:Ae(),semanticMappings:{...xe},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{}},Me={...Fe,chroma:Ae(),semanticMappings:{...xe},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{},lightness:{...vt}},je={...Fe,chroma:Ae(),semanticMappings:{...xe},anchors:{},roles:{},contexts:{},dataPalette:{...ge},dataRamps:{},lightness:{...Ot}},fe=new WeakMap;fe.set(Me,new Set),fe.set(je,new Set);function Rt(e,n){return st.has(e)?void 0:n}function Jt(e){return`--esp-color-${e.replace(/([A-Z])/g,"-$1").replace(/(\d)/g,"-$1").toLowerCase()}`}function Ct(e){try{const n=Ke(e),t=JSON.parse(n,Rt);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}const ve="\xEF\xBB\xBF";function Tt(e){if(/^[\u0000-\u007f]*$/.test(e))return btoa(e);const n=new TextEncoder().encode(e);let t=ve;for(const o of n)t+=String.fromCharCode(o);return btoa(t)}function Ke(e){const n=atob(e);if(!n.startsWith(ve))return n;const t=Uint8Array.from(n.slice(ve.length),o=>o.charCodeAt(0));return new TextDecoder("utf-8",{fatal:!0}).decode(t)}function Oe(e){return Tt(JSON.stringify(e))}function Bt(e){const n={};for(const t of ee){const o=e[t];typeof o=="string"&&(n[t]=o.startsWith("anchor:")?o:oe(o))}return n}function oe(e){if(ut(e))return e;const n=W(e);return n?ie(n):e}function Ue(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&(t[o]=a);if(!n)return t;for(const[o,a]of Object.entries(n)){if(a===void 0||!v(o))continue;const c=t[o];if(c!==void 0&&typeof a=="object"&&a!==null){const f={};if(typeof c=="string")f.color=c;else for(const[p,m]of Object.entries(c))v(p)&&(f[p]=m);for(const[p,m]of Object.entries(a))m!==void 0&&v(p)&&(f[p]=m);t[o]=f;continue}t[o]=a}return t}function ze(e){if(typeof e!="object"||e===null||Array.isArray(e))return null;const n=e,t={};for(const o of ne){const a=n[o];a!==void 0&&(t[o]=a)}if(typeof n.lightness=="object"&&n.lightness!==null&&!Array.isArray(n.lightness)){const o={};for(const a of j){const c=n.lightness[a];c!==void 0&&(o[a]=c)}t.lightness=o}if(typeof n.semanticMappings=="object"&&n.semanticMappings!==null&&!Array.isArray(n.semanticMappings)){const o={};for(const[a,c]of Object.entries(n.semanticMappings)){if(!v(a)||!Q.includes(a)||typeof c!="object"||c===null||Array.isArray(c))continue;const{source:f,lightness:p}=c;typeof f=="string"&&(typeof p!="string"||!j.includes(p)||(o[a]={source:f,lightness:p}))}Object.keys(o).length>0&&(t.semanticMappings=o)}return t}function wt(e,n){const t={};for(const[o,a]of Object.entries(e)){if(!v(o)||!V.test(o))continue;const c=ze(a);c&&(t[o]=c)}if(!n)return t;for(const[o,a]of Object.entries(n)){if(!v(o)||!V.test(o)||a===void 0)continue;const c=ze(a);if(!c)continue;const f=t[o];t[o]={...f??{},...c,...f?.lightness||c.lightness?{lightness:{...f?.lightness,...c.lightness}}:{},...f?.semanticMappings||c.semanticMappings?{semanticMappings:{...f?.semanticMappings,...c.semanticMappings}}:{}}}return t}function K(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function U(e){const n={};for(const[t,o]of Object.entries(e))o!==void 0&&v(t)&&(n[t]=o);return n}function Ge(e){if(!K(e))return e;const n=U(e);return K(e.lightness)&&(n.lightness=U(e.lightness)),n}function Et(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&(t[o]=Ge(a));if(!n)return t;for(const[o,a]of Object.entries(n)){if(!v(o)||a===void 0)continue;const c=t[o];if(!K(c)||!K(a)){t[o]=Ge(a);continue}const f={...U(c),...U(a)};K(c.lightness)&&K(a.lightness)?f.lightness={...U(c.lightness),...U(a.lightness)}:K(a.lightness)&&(f.lightness=U(a.lightness)),K(c.semanticMappings)&&K(a.semanticMappings)?f.semanticMappings={...U(c.semanticMappings),...U(a.semanticMappings)}:K(a.semanticMappings)&&(f.semanticMappings=U(a.semanticMappings)),t[o]=f}return t}function _t(e){const n={};for(const[t,o]of Object.entries(e)){if(!v(t))continue;if(typeof o=="string"){n[t]=oe(o);continue}const a={};for(const[c,f]of Object.entries(o))v(c)&&(a[c]=typeof f=="string"?oe(f):f);n[t]=a}return n}function se(e){return typeof e!="string"?"":e.startsWith("anchor:")?e:oe(e)}function It(e){const n={};for(const t of ue)n[t]=se(e[t]);return n}function Ve(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&V.test(o)&&a&&typeof a=="object"&&!Array.isArray(a)&&(t[o]={...a});if(!n)return t;for(const[o,a]of Object.entries(n)){if(!v(o)||!V.test(o)||!a||typeof a!="object"||Array.isArray(a))continue;const c=t[o],f=c!==void 0&&a.type!==void 0&&a.type!==c.type;t[o]={...f?{}:c??{},...a}}return t}function Ht(e){const n={};for(const[t,o]of Object.entries(e))if(v(t)){if(o.type==="sequential"&&typeof o.source=="string"){n[t]={...o,source:se(o.source)};continue}if(o.type==="diverging"&&typeof o.start=="string"&&typeof o.end=="string"){n[t]={...o,start:se(o.start),end:se(o.end),...typeof o.neutral=="string"?{neutral:se(o.neutral)}:{}};continue}n[t]={...o}}return n}function Je(e){const n=W(e.seedColor);if(!n)return;const t=he(n,e);return(o,a)=>{const c=ce(o,t,e.anchors)??t.primary,f=e.chroma.actionBackground,p=ae(c,e.lightness[a],f.min,f.max),m={l:p.l>.5?0:1,c:0,h:0};return Math.abs(rt(m,p))}}function Lt(e,n,t){if(n?.background)return n.background;const o=q(e.canvas,"color");if(o!==void 0){const a=Se.canvas.color?.find(([c])=>c==="background");if(a)return{source:o,lightness:a[1]}}return t.background}function Ye(e,n){const t=W(e.seedColor);if(!t||!n)return;const o=he(t,e),a=ce(n.source,o,e.anchors)??o.primary,c=e.chroma.background,f=ae(a,e.lightness[n.lightness],c.min,c.max);return(p,m)=>{const O=ce(p,o,e.anchors)??o.primary,k=e.chroma.actionBackground,g=ae(O,e.lightness[m],k.min,k.max);return at(g,f)}}function Pt(e){const n=fe.get(e);if(n)return new Set(n);const t=new Set,o=Ne(e.roles,e.lightness,e.semanticMappings,{actionSurfaceContrast:Je(e),actionSurfaceSeparation:Ye(e,e.semanticMappings.background)});for(const[a,c]of Object.entries(o)){const f=e.semanticMappings[a];(f.source!==c.source||f.lightness!==c.lightness)&&t.add(a)}return t}function le(e,n){const t={...e.roles,...n.roles},o=wt(e.contexts,n.contexts),a={...e.lightness,...n.lightness},c=_t(Ue(e.anchors,n.anchors)),f=typeof n.seedColor=="string"?oe(n.seedColor):e.seedColor,p=n.semanticMappings,m={...e.angles,...n.angles},O={...e.semanticHues,...n.semanticHues},k={...e.variantChroma,...n.variantChroma},g=Bt({...e.intents,...n.intents}),x=re(e.chroma,n.chroma),P=It(re(e.dataPalette,n.dataPalette)),s=Ht(Ve(e.dataRamps,n.dataRamps)),r=Pt(e),i=new Set(r),u={};for(const S of r)u[S]=e.semanticMappings[S];for(const[S,A]of Object.entries(p??{}))A!==void 0&&(i.add(S),u[S]=A);const d=re(e.semanticMappings,p),y={angles:m,anchors:c,chroma:x,intents:g,lightness:a,seedColor:f,semanticHues:O,variantChroma:k},E=Je(y),D=Ye(y,Lt(t,u,d)),l=Ne(t,a,d,{explicitMappings:u,actionSurfaceContrast:E,actionSurfaceSeparation:D}),b={};for(const[S,A]of Object.entries(l))i.has(S)||(b[S]=A);const $=re(re(e.semanticMappings,b),p),h={...e,seedColor:f,fontBody:n.fontBody??e.fontBody,fontHeadings:n.fontHeadings??e.fontHeadings,fontBrand:n.fontBrand??e.fontBrand,fontMonospace:n.fontMonospace??e.fontMonospace,fontWeightBody:String(n.fontWeightBody??e.fontWeightBody),fontWeightHeadings:String(n.fontWeightHeadings??e.fontWeightHeadings),fontWeightBrand:String(n.fontWeightBrand??e.fontWeightBrand),fontWeightMonospace:String(n.fontWeightMonospace??e.fontWeightMonospace),stylesheets:n.stylesheets??[...e.stylesheets],rootFontSize:n.rootFontSize??e.rootFontSize,typeRatio:n.typeRatio??e.typeRatio,spaceRatio:n.spaceRatio??e.spaceRatio,borderRadius:n.borderRadius??e.borderRadius,viewportMin:n.viewportMin??e.viewportMin,viewportMax:n.viewportMax??e.viewportMax,angles:m,semanticHues:O,variantChroma:k,intents:g,lightness:a,chroma:x,semanticMappings:$,anchors:c,roles:t,contexts:o,dataPalette:P,dataRamps:s};return n.pageBackgroundImage!==void 0&&(h.pageBackgroundImage=n.pageBackgroundImage),n.pageBackgroundImageOpacity!==void 0&&(h.pageBackgroundImageOpacity=n.pageBackgroundImageOpacity),n.boxBackgroundImage!==void 0&&(h.boxBackgroundImage=n.boxBackgroundImage),n.boxBackgroundImageOpacity!==void 0&&(h.boxBackgroundImageOpacity=n.boxBackgroundImageOpacity),n.vellumOpacity!==void 0&&(h.vellumOpacity=n.vellumOpacity),n.vellumBackgroundImage!==void 0&&(h.vellumBackgroundImage=n.vellumBackgroundImage),n.vellumBackgroundImageOpacity!==void 0&&(h.vellumBackgroundImageOpacity=n.vellumBackgroundImageOpacity),fe.set(h,new Set(i)),h}const qe=new WeakMap;function Xe(e,n){const t=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,n)?e.contexts[n]:void 0;if(!t)return null;let o=qe.get(e);const a=o?.get(n);if(a)return a;const c={};for(const p of ne){const m=t[p];m!==void 0&&(c[p]=m)}const f=le(e,{lightness:t.lightness,roles:c,semanticMappings:t.semanticMappings});return o||(o=new Map,qe.set(e,o)),o.set(n,f),f}function re(e,n){if(!n)return{...e};const t={...e};for(const o of Object.keys(n)){const a=n[o];a!==void 0&&(t[o]=a)}return t}function Re(e){let n;try{n=Ke(e)}catch{return{error:"Failed to decode Base64 string."}}let t;try{t=JSON.parse(n)}catch{return{error:"Decoded string is not valid JSON."}}return typeof t!="object"||t===null||Array.isArray(t)?{error:"Theme must be a JSON object."}:{value:t}}function Yt(e){const n=Re(e);return n.error!==void 0?{valid:!1,errors:[n.error],warnings:[]}:Ce(n.value)}function Ce(e,n=Me){const t=[],o=[];"seedColor"in e&&(typeof e.seedColor!="string"?t.push("seedColor must be a string."):W(e.seedColor)||t.push(`seedColor is not a valid CSS color: "${e.seedColor}". Accepted forms: ${te}.`));for(const s of["fontBody","fontHeadings","fontBrand","fontMonospace"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);const a=["normal","bold","lighter","bolder"],c=["inherit","initial","unset","revert","revert-layer"];for(const s of["fontWeightBody","fontWeightHeadings","fontWeightBrand","fontWeightMonospace"])if(s in e){const r=e[s];if(typeof r=="number")(r<1||r>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got ${r}).`);else if(typeof r=="string"){const i=a.includes(r)||c.includes(r);if(/^\d+$/.test(r)){const d=Number(r);(d<1||d>1e3)&&t.push(`${s} numeric value must be 1\u20131000 (got "${r}").`)}else i||o.push(`${s} = "${r}" is not a standard font-weight value.`)}else t.push(`${s} must be a string or number.`)}"stylesheets"in e&&(Array.isArray(e.stylesheets)?e.stylesheets.some(s=>typeof s!="string")&&t.push("Every entry in stylesheets must be a string."):t.push("stylesheets must be an array of strings."));const f=[["rootFontSize",1,100],["borderRadius",0,10],["viewportMin",100,1e4],["viewportMax",200,1e4]];for(const[s,r,i]of f)if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const u=e[s];r!==void 0&&u<r&&t.push(`${s} must be \u2265 ${r} (got ${u}).`),i!==void 0&&u>i&&o.push(`${s} = ${u} is unusually high (max ${i}).`)}for(const s of["typeRatio","spaceRatio"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];r<=1&&t.push(`${s} must be > 1 (got ${r}).`);const i=s==="typeRatio"?1.3:2;r>i&&o.push(`${s} = ${r} is very high (max ${i}); scales may be extreme.`)}if("viewportMin"in e&&"viewportMax"in e){const s=e.viewportMin,r=e.viewportMax;typeof s=="number"&&typeof r=="number"&&s>=r&&t.push(`viewportMin (${s}) must be less than viewportMax (${r}).`)}if("angles"in e)if(typeof e.angles!="object"||e.angles===null)t.push("angles must be an object.");else{const s=e.angles;for(const r of["analogous","complementary","splitComplementary","triadic"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`angles.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.push(`angles.${r} = ${i} is outside 0\u2013360.`)}}if("semanticHues"in e)if(typeof e.semanticHues!="object"||e.semanticHues===null)t.push("semanticHues must be an object.");else{const s=e.semanticHues;for(const r of["danger","success","warning","info"])if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`semanticHues.${r} must be a finite number.`);else{const i=s[r];(i<0||i>360)&&o.push(`semanticHues.${r} = ${i} is outside 0\u2013360.`)}}if("variantChroma"in e)if(typeof e.variantChroma!="object"||e.variantChroma===null)t.push("variantChroma must be an object.");else{const s=e.variantChroma;for(const r of Mt)if(r in s)if(typeof s[r]!="number"||!isFinite(s[r]))t.push(`variantChroma["${r}"] must be a finite number.`);else{const i=s[r];i<0&&t.push(`variantChroma["${r}"] must be \u2265 0 (got ${i}).`),i>J&&o.push(`variantChroma["${r}"] = ${i} exceeds ${J}.`)}}function p(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const u of j)if(u in i)if(typeof i[u]!="number"||!isFinite(i[u]))t.push(`${r}.${u} must be a finite number.`);else{const d=i[u];(d<0||d>1)&&t.push(`${r}.${u} must be 0\u20131 (got ${d}).`)}}if("lightness"in e&&p(e.lightness,"lightness"),"chroma"in e)if(typeof e.chroma!="object"||e.chroma===null)t.push("chroma must be an object.");else{const s=e.chroma,r=At(e,n);for(const i of Q)if(i in s){const u=s[i];if(typeof u!="object"||u===null){t.push(`chroma.${i} must be { min, max }.`);continue}const d=u;for(const E of r.get(i)??[])E.chroma!==void 0&&typeof d.min=="number"&&typeof d.max=="number"&&(E.chroma<d.min-1e-9||E.chroma>d.max+1e-9)&&o.push(`chroma.${i} clamps the anchor-sourced token ${i} ("${E.source}", effective in ${E.where}) and moves it off its declared swatch. Remove the band if that is unintended \u2014 anchors otherwise keep their own chroma.`);const y=u;(typeof y.min!="number"||y.min<0)&&t.push(`chroma.${i}.min must be \u2265 0.`),(typeof y.max!="number"||y.max<0||y.max>J)&&t.push(`chroma.${i}.max must be 0\u2013${J}.`),typeof y.min=="number"&&typeof y.max=="number"&&y.min>y.max&&t.push(`chroma.${i}.min (${y.min}) must be \u2264 max (${y.max}).`)}}if("anchors"in e)if(typeof e.anchors!="object"||e.anchors===null||Array.isArray(e.anchors))t.push("anchors must be an object of named colors.");else for(const[s,r]of Object.entries(e.anchors))if(v(s)?V.test(s)||t.push(`anchors: "${s}" is not a valid anchor name; use a lowercase slug (letters, digits, hyphens).`):t.push(`anchors: "${s}" is a reserved JavaScript property name and cannot be an anchor name; rename it.`),ke.includes(s)&&t.push(`anchors: "${s}" collides with a reserved color source name.`),typeof r=="string")W(r)||t.push(`anchors.${s} is not a valid CSS color: "${r}". Accepted forms: ${te}.`);else if(typeof r=="object"&&r!==null&&!Array.isArray(r)){const i=r;typeof i.color!="string"&&t.push(`anchors.${s} must declare its base "color".`);for(const[u,d]of Object.entries(i))v(u)?u!=="color"&&!V.test(u)&&t.push(`anchors.${s}: "${u}" is not a valid slot name; use a lowercase slug.`):t.push(`anchors.${s}: "${u}" is a reserved JavaScript property name and cannot be a slot name; rename it.`),typeof d!="string"?t.push(`anchors.${s}.${u} must be a CSS color string.`):W(d)||t.push(`anchors.${s}.${u} is not a valid CSS color: "${d}". Accepted forms: ${te}.`)}else t.push(`anchors.${s} must be a color string or a { color, \u2026slots } object.`);const m=new Map;if("anchors"in e&&typeof e.anchors=="object"&&e.anchors!==null&&!Array.isArray(e.anchors))for(const[s,r]of Object.entries(e.anchors))m.set(s,r);function O(s,r){const i=$e(s);if(!i){t.push(`${r} "${s}" is not valid anchor syntax; use anchor:<name> or anchor:<name>.<slot>.`);return}if(!m.has(i.name)){const u=[...m.keys()];t.push(`${r} references undeclared anchor "${i.name}". Declared anchors: ${u.length>0?u.join(", "):"(none)"}.`);return}if(i.slot!==void 0){const u=m.get(i.name);if(typeof(typeof u=="object"&&u!==null&&!Array.isArray(u)?u[i.slot]:void 0)!="string"){const y=typeof u=="object"&&u!==null?Object.keys(u).filter(E=>E!=="color"):[];t.push(`${r} references unknown slot "${i.slot}" on anchor "${i.name}". Declared slots: ${y.length>0?y.join(", "):"(none)"}.`)}}}function k(s,r){if(s.startsWith("anchor:")){O(s,r);return}ke.includes(s)||t.push(`${r} must be one of: ${ke.join(", ")}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("intents"in e)if(typeof e.intents!="object"||e.intents===null||Array.isArray(e.intents))t.push("intents must be an object.");else for(const[s,r]of Object.entries(e.intents)){const i=`intents.${s}`;if(!ee.includes(s)){t.push(`${i} is not a status family; expected one of: ${ee.join(", ")}.`);continue}if(typeof r!="string"){t.push(`${i} must be a string (a CSS color or an anchor: reference).`);continue}if(r.startsWith("anchor:")){O(r,i);continue}W(r)||t.push(`${i} "${r}" is not a supported color form or anchor: reference. Accepted forms: ${te}, or anchor:<name> / anchor:<name>.<slot>. An override retunes a family with a declared color; it never points one family at another \u2014 retune, never reassign.`)}function g(s,r){if(s.startsWith("anchor:")){O(s,r);return}W(s)||t.push(`${r} is not a valid CSS color: "${s}". Accepted forms: ${te}, or a declared anchor as anchor:<name> / anchor:<name>.<slot>.`)}if("dataPalette"in e)if(typeof e.dataPalette!="object"||e.dataPalette===null||Array.isArray(e.dataPalette))t.push("dataPalette must be an object with series1\u2013series8 color values.");else{const s=e.dataPalette;for(const[r,i]of Object.entries(s)){if(!ue.includes(r)){t.push(`dataPalette.${r} is not a series slot; expected one of: ${ue.join(", ")}.`);continue}typeof i!="string"?t.push(`dataPalette.${r} must be a CSS color or anchor reference string.`):g(i,`dataPalette.${r}`)}}if("dataRamps"in e)if(typeof e.dataRamps!="object"||e.dataRamps===null||Array.isArray(e.dataRamps))t.push("dataRamps must be an object of named ramp declarations.");else for(const[s,r]of Object.entries(e.dataRamps)){if(v(s)?V.test(s)||t.push(`dataRamps: "${s}" is not a valid ramp name; use a lowercase slug (letters, digits, hyphens).`):t.push(`dataRamps: "${s}" is a reserved JavaScript property name and cannot be a ramp name; rename it.`),typeof r!="object"||r===null||Array.isArray(r)){t.push(`dataRamps.${s} must be a sequential or diverging ramp object.`);continue}const i=r,u=i.steps??dt;if((typeof u!="number"||!Number.isInteger(u)||u<be||u>ye)&&t.push(`dataRamps.${s}.steps must be an integer from ${be} through ${ye}.`),i.type==="sequential"){typeof i.source!="string"?t.push(`dataRamps.${s}.source must be a CSS color or anchor reference string.`):g(i.source,`dataRamps.${s}.source`);const d=i.lightnessStart??.95,y=i.lightnessEnd??.25;for(const[E,D]of[["lightnessStart",d],["lightnessEnd",y]])(typeof D!="number"||!Number.isFinite(D)||D<0||D>1)&&t.push(`dataRamps.${s}.${E} must be a finite number from 0 through 1.`);typeof d=="number"&&typeof y=="number"&&d<=y?t.push(`dataRamps.${s}.lightnessStart must be greater than lightnessEnd.`):typeof d=="number"&&Number.isFinite(d)&&typeof y=="number"&&Number.isFinite(y)&&typeof u=="number"&&Number.isInteger(u)&&u>=be&&u<=ye&&(d-y)/(u-1)<=Le&&t.push(`dataRamps.${s} lightness bounds must leave more than ${Le} lightness between serialized stops.`);continue}if(i.type==="diverging"){typeof u=="number"&&Number.isInteger(u)&&u%2===0&&t.push(`dataRamps.${s}.steps must be odd so the neutral is the exact midpoint.`);for(const d of["start","end"])typeof i[d]!="string"?t.push(`dataRamps.${s}.${d} must be a CSS color or anchor reference string.`):g(i[d],`dataRamps.${s}.${d}`);"neutral"in i&&(typeof i.neutral!="string"?t.push(`dataRamps.${s}.neutral must be a CSS color or anchor reference string.`):g(i.neutral,`dataRamps.${s}.neutral`));continue}t.push(`dataRamps.${s}.type must be "sequential" or "diverging".`)}if("dataPalette"in e&&t.length===0){const s=le(Me,e),r={};let i=!0;for(const u of ue){const d=ht(s.dataPalette[u],s.anchors);if(!d){i=!1;break}r[u]=d}if(i)for(const u of mt(r))o.push(`dataPalette.${u.series[0]} and dataPalette.${u.series[1]} are only ${u.distance.toFixed(4)} apart under ${u.simulation} simulation (minimum ${u.threshold.toFixed(4)}); also distinguish the series with labels, shapes, or patterns.`)}function x(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const[u,d]of Object.entries(i)){const y=`${r}.${u}`;if(!ne.includes(u)){t.push(`${y} is not a role; expected one of: ${ne.join(", ")}. (The status family is reserved and is not a role.)`);continue}const E=u,D=Se[E];if(typeof d=="string"){k(d,y);continue}if(typeof d!="object"||d===null||Array.isArray(d)){t.push(`${y} must be a color source or a { color, \u2026slots } object.`);continue}const l=d;typeof l.color!="string"&&t.push(`${y} must declare its base "color".`);for(const[b,$]of Object.entries(l)){if(!Object.prototype.hasOwnProperty.call(D,b)||!v(b)){const h=Object.keys(D).filter(S=>S!=="color");t.push(`${y}.${b} is not a slot of the ${E} role. Declared slots: ${h.length>0?h.join(", "):"(none)"}.`);continue}typeof $!="string"?t.push(`${y}.${b} must be a color source string.`):k($,`${y}.${b}`)}}}if("roles"in e&&x(e.roles,"roles"),"contexts"in e)if(typeof e.contexts!="object"||e.contexts===null||Array.isArray(e.contexts))t.push("contexts must be an object.");else for(const[s,r]of Object.entries(e.contexts)){if(!v(s)||!V.test(s)){t.push(`contexts.${s} must be a lowercase slug matching ${V.source}.`);continue}if(typeof r!="object"||r===null||Array.isArray(r)){x(r,`contexts.${s}`);continue}const i=r,u=Object.fromEntries(Object.entries(i).filter(([d])=>d!=="lightness"&&d!=="semanticMappings"));x(u,`contexts.${s}`),"lightness"in i&&p(i.lightness,`contexts.${s}.lightness`),"semanticMappings"in i&&P(i.semanticMappings,`contexts.${s}.semanticMappings`)}function P(s,r){if(typeof s!="object"||s===null||Array.isArray(s)){t.push(`${r} must be an object.`);return}const i=s;for(const u of Object.keys(i))Q.includes(u)||t.push(`${r}.${u} is not a semantic token; expected one of: ${Q.join(", ")}.`);for(const u of Q)if(u in i){const d=i[u];if(typeof d!="object"||d===null){t.push(`${r}.${u} must be { source, lightness }.`);continue}const y=d;typeof y.source!="string"?t.push(`${r}.${u}.source must be a string.`):k(y.source,`${r}.${u}.source`),(typeof y.lightness!="string"||!j.includes(y.lightness))&&t.push(`${r}.${u}.lightness must be one of: ${j.join(", ")}.`)}}"semanticMappings"in e&&P(e.semanticMappings,"semanticMappings");for(const s of["pageBackgroundImage","boxBackgroundImage","vellumBackgroundImage"])s in e&&typeof e[s]!="string"&&t.push(`${s} must be a string.`);for(const s of["pageBackgroundImageOpacity","boxBackgroundImageOpacity","vellumOpacity","vellumBackgroundImageOpacity"])if(s in e)if(typeof e[s]!="number"||!isFinite(e[s]))t.push(`${s} must be a finite number.`);else{const r=e[s];(r<0||r>1)&&t.push(`${s} must be 0\u20131 (got ${r}).`)}return o.push(...Dt(e,n)),{valid:t.length===0,errors:t,warnings:o}}const T=.045;function Dt(e,n){try{return Nt(e,n)}catch{return[]}}function Nt(e,n){const t=le(n,e),o=et(t),a=[...o],c=new Set(o);for(const f of Object.keys(t.contexts)){const p=Xe(t,f);if(p)for(const m of et(p))c.has(m)||a.push(`contexts.${f}: ${m}`)}return a}function Wt(e){const n=ct(de(e)),t=ft(n);return it({r:me(t.r),g:me(t.g),b:me(t.b)})}function X(e,n){return Math.hypot(e.L-n.L,e.a-n.a,e.b-n.b)}function Y(e){return Wt(W(ie(de(e))))}function Ze(e){return(Math.floor(e*1e4)/1e4).toFixed(4)}const Z=2,Qe=1e-4;function et(e){const n=W(e.seedColor);if(!n)return[];const t=he(n,e),o=e.semanticMappings.actionBackground,a=e.chroma.actionBackground,c=e.lightness[o.lightness],f=(l,b,$,h)=>de(ae(l,b,$,h)),p=ee.map(l=>({name:l,base:t[l]})),m=[];if(ee.includes(o.source))m.push(`actionBackground is sourced from the "${o.source}" status family: ordinary and ${o.source}-intent action surfaces render identically (their labels may still differ). Remap the action to a non-status source \u2014 retuning "${o.source}" via intents moves both colors together.`);else{const l=ce(o.source,t,e.anchors);l&&p.push({name:"action",base:l})}const O=He(p.map(({name:l,base:b})=>[l,ie(f(b,c,a.min,a.max))]),T,["normal"]);if(O.length===0)return m;const k=new Map,g=(l,b)=>{const $=`${l}:${b}`;let h=k.get($);if(!h){h=[];for(let S=0;S<360;S+=Z)h.push(Y({l,c:b,h:S}));k.set($,h)}return h},x=T-.002,P=(l,b,$,h)=>{const S=Math.hypot(l.a,l.b),A=Math.atan2(l.b,l.a)*180/Math.PI+180;let _=0;for(const B of $===h?[h]:[$,h]){if(B+S<T-1e-4)continue;let H=A,C=X(Y({l:b,c:B,h:A}),l);if(C>=T)return C;const N=g(b,B);for(let R=0;R<N.length;R+=1){const M=X(N[R],l);if(M>=T)return M;M>C&&(C=M,H=R*Z)}let L=H;for(let R=H-Z;R<=H+Z;R+=.1){const M=X(Y({l:b,c:B,h:R}),l);if(M>=T)return M;M>C&&(C=M,L=R)}if(C>=x)for(let R=L-.1;R<=L+.1;R+=.001){const M=X(Y({l:b,c:B,h:R}),l);if(M>=T)return M;M>C&&(C=M)}C>_&&(_=C)}return _},s=(l,b,$)=>{const h=b===$?[$]:[b,$];let S=0;for(const A of h)for(const _ of h){if(A+_<T-1e-4)continue;const B=g(l,A),H=g(l,_);let C=0,N=0,L=-1;for(let I=0;I<B.length;I+=1)for(let F=0;F<H.length;F+=1){const z=X(B[I],H[F]);if(z>=T)return z;z>L&&(L=z,C=I*Z,N=F*Z)}const R=(I,F,z,Te)=>{const Be=[];for(let G=F-z;G<=F+z;G+=Te)Be.push({h:G,lab:Y({l,c:_,h:G})});let pe=-1,we=I,Ee=F;for(let G=I-z;G<=I+z;G+=Te){const ot=Y({l,c:A,h:G});for(const _e of Be){const Ie=X(ot,_e.lab);Ie>pe&&(pe=Ie,we=G,Ee=_e.h)}}return{distance:pe,hueA:we,hueB:Ee}},M=R(C,N,Z,.1);if(M.distance>=T)return M.distance;let w=Math.max(L,M.distance);if(w>=x){const I=R(M.hueA,M.hueB,.1,.001);if(I.distance>w&&(w=I.distance),w>=T)return w}w>S&&(S=w)}return S},r=l=>ee.includes(l),i=(l,b,$,h,S)=>{const A=Y(f(l.base,$,h,S)),_=Y(f(b.base,$,h,S));if(X(A,_)>=T)return{outcome:"direct"};const B=r(l.name)&&r(b.name),H=[l,b].filter(L=>r(L.name)),C=B?"one of them":`"${r(l.name)?l.name:b.name}"`;let N;for(const L of H){const R=P(L===l?_:A,$,h,S);if(R>=T)return{outcome:"retune",target:C};R>=T-Qe&&(N=N??C)}if(B){const L=s($,h,S);if(L>=T)return{outcome:"retune",target:"both"};L>=T-Qe&&(N=N??"both")}return N!==void 0?{outcome:"near",target:N}:{outcome:"no"}},u=l=>l.outcome==="direct"?4:l.outcome==="retune"?l.target==="both"?2:3:l.outcome==="near"?1:0,d=l=>[...l].sort().join("|"),y=new Set(He(p.map(({name:l,base:b})=>[l,ie(f(b,c,0,J))]),T,["normal"]).map(l=>d(l.pair))),E=new Map(p.map(l=>[l.name,l])),D=new Map;for(const{pair:l,distance:b}of O){const $=E.get(l[0]),h=E.get(l[1]),S=r($.name)&&r(h.name),A=i($,h,c,a.min,a.max);if(A.outcome==="direct"||A.outcome==="retune"){const w=A.target??(S?"one of them":`"${r($.name)?$.name:h.name}"`);y.has(d(l))?m.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish under normal vision (distance ${Ze(b)} < ${T}); status meanings must stay distinguishable \u2014 retune ${w} via intents.`):m.push(`Status colors "${l[0]}" and "${l[1]}" are hard to distinguish as rendered (distance ${Ze(b)} < ${T}); the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }) pushes them together \u2014 widen the band, or retune ${w} via intents.`);continue}const _=i($,h,c,0,J);let B={outcome:"no"};for(let w=1;w<=19&&B.outcome!=="direct";w+=1){const I=w*.05;if(Math.abs(I-c)<.001)continue;const F=i($,h,I,a.min,a.max);u(F)>u(B)&&(B=F)}let H={outcome:"no"};const C=_.outcome==="direct"||_.outcome==="retune",N=B.outcome==="direct"||B.outcome==="retune";if(!C&&!N)for(let w=1;w<=19&&H.outcome!=="direct";w+=1){const I=i($,h,w*.05,0,J);u(I)>u(H)&&(H=I)}const L=Ft(_,B,H),R=`${A.outcome}|${L}`;let M=D.get(R);M||(M=[],D.set(R,M)),M.push(l)}for(const[l,b]of D){const $=l.indexOf("|"),h=l.slice(0,$),S=l.slice($+1),A=b.map(([H,C])=>`"${H}"/"${C}"`),_=A.length>1?`${A.slice(0,-1).join(", ")} and ${A[A.length-1]}`:A[0],B=h==="near"?`Status colors ${_} may not separate by retuning as rendered: at the action stop's lightness (${c}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), the closest reachable retune found comes within the audit's search margin of the ${T} threshold`:`Status colors ${_} cannot be separated as rendered: at the action stop's lightness (${c}) with the actionBackground chroma band ({ min: ${a.min}, max: ${a.max} }), no intent retuning can pull ${b.length>1?"these pairs":"the pair"} ${T} apart`;m.push(B+S)}return m}function Ft(e,n,t){if(e.outcome==="direct"&&n.outcome==="direct")return" \u2014 widen the chroma band or move the action lightness stop.";if(e.outcome==="direct")return n.outcome==="no"?"; no other action lightness stop can help while the band holds \u2014 widen the chroma band.":" \u2014 widen the chroma band.";if(n.outcome==="direct")return e.outcome==="no"?"; no wider chroma band can help at this lightness \u2014 move the action lightness stop.":" \u2014 move the action lightness stop.";if(e.outcome==="retune"&&n.outcome==="retune")return` \u2014 widen the chroma band or move the action lightness stop, then retune ${e.target} via intents.`;if(e.outcome==="retune")return n.outcome==="no"?`; no other action lightness stop can help while the band holds \u2014 widen the chroma band, then retune ${e.target} via intents.`:` \u2014 widen the chroma band, then retune ${e.target} via intents.`;if(n.outcome==="retune")return e.outcome==="no"?`; no wider chroma band can help at this lightness \u2014 move the action lightness stop, then retune ${n.target} via intents.`:` \u2014 move the action lightness stop, then retune ${n.target} via intents.`;const o=e.outcome==="no"&&n.outcome==="no"?"; neither a wider chroma band alone nor another stop alone can help":"; neither a wider chroma band alone nor another stop alone provably helps";return t.outcome==="direct"?`${o} \u2014 change the band and the stop together.`:t.outcome==="retune"?`${o} \u2014 change the band and the stop together, then retune ${t.target} via intents.`:"; no explored band or stop change provably separates this pair."}function qt(e,n){const t=Re(e),o=Re(n),a=t.error!==void 0?{valid:!1,errors:[t.error],warnings:[]}:Ce(t.value),c=o.error!==void 0?{valid:!1,errors:[o.error],warnings:[]}:Ce(o.value,je),f=[...a.errors.map(m=>`light: ${m}`),...c.errors.map(m=>`dark: ${m}`)],p=[...a.warnings.map(m=>`light: ${m}`),...c.warnings.map(m=>`dark: ${m}`)];if(a.valid&&c.valid){const m=new Set(Object.keys(t.value?.contexts??{})),O=new Set(Object.keys(o.value?.contexts??{})),k=[...O].filter(x=>!m.has(x)).sort(),g=[...m].filter(x=>!O.has(x)).sort();(k.length>0||g.length>0)&&f.push(`contexts must declare the same names in both schemes. Missing from light: ${k.join(", ")||"(none)"}. Missing from dark: ${g.join(", ")||"(none)"}.`)}return{valid:f.length===0,errors:f,warnings:p}}const jt=["anchors","angles","contexts","dataPalette","dataRamps","intents","roles","chroma","lightness","semanticHues","semanticMappings","variantChroma"];function Kt(e,n){const t={};for(const[o,a]of Object.entries(e))v(o)&&(t[o]=a);for(const[o,a]of Object.entries(n))a!==void 0&&v(o)&&(t[o]=a);for(const o of jt){const a=e[o],c=n[o];if(a&&typeof a=="object"&&!Array.isArray(a)&&c&&typeof c=="object"&&!Array.isArray(c)){if(o==="anchors"){t[o]=Ue(a,c);continue}if(o==="contexts"){t[o]=Et(a,c);continue}if(o==="dataRamps"){t[o]=Ve(a,c);continue}const f={};for(const[p,m]of Object.entries(a))v(p)&&(f[p]=m);for(const[p,m]of Object.entries(c))m!==void 0&&v(p)&&(f[p]=m);t[o]=f}}return t}function Xt(...e){let n={};for(const t of e){if(!t)continue;const o=Ct(t);o&&(n=Kt(n,o))}return Oe(n)}function tt(e){return e.replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\n/g,"\\n").replace(/\r/g,"\\r")}const nt={borderRadius:.1,fontBody:'"Noto Sans", sans-serif',fontWeightBody:"normal",fontHeadings:'"Inika", serif',fontWeightHeadings:"normal",fontBrand:'"Inika", serif',fontWeightBrand:"normal",fontMonospace:'"JetBrains Mono", monospace',fontWeightMonospace:"normal",seedColor:"oklch(.07 0.15 216)"};function Zt(e){return Oe({...nt,pageBackgroundImage:`url("${tt(e)}")`,pageBackgroundImageOpacity:.5})}function Qt(e){return Oe({...nt,pageBackgroundImage:`url("${tt(e)}")`,pageBackgroundImageOpacity:.55})}export{V as ANCHOR_SLUG_PATTERN,ke as COLOR_SOURCES,Ot as DEFAULT_DARK_LIGHTNESS,je as DEFAULT_DARK_THEME,vt as DEFAULT_LIGHT_LIGHTNESS,Me as DEFAULT_LIGHT_THEME,xe as DEFAULT_SEMANTIC_MAPPINGS,j as LIGHTNESS_KEYS,jt as NESTED_THEME_KEYS,ne as ROLE_NAMES,bt as ROLE_PAIRED_INK,Se as ROLE_TOKEN_PLAN,Q as SEMANTIC_COLOR_NAMES,ee as STATUS_COLOR_SOURCES,We as TOKEN_PAIRINGS,Mt as VARIANT_COLOR_SOURCES,Qt as buildTaprootDarkTheme,Zt as buildTaprootLightTheme,Ne as compileRoles,Oe as encodeTheme,Pt as explicitMappingTokens,Xt as layerThemes,Kt as mergePartials,le as mergeTheme,$e as parseAnchorSource,Ct as parseTheme,Pe as resolveAnchorColor,Xe as resolveContextTheme,ht as resolveDataColorSource,Jt as semanticToCSS,Yt as validateTheme,qt as validateThemePair};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const o=new Set(["__proto__","constructor","prototype"]);function e(t){return!o.has(t)}export{o as UNSAFE_KEYS,e as isSafeKey};
|
|
@@ -352,41 +352,121 @@
|
|
|
352
352
|
"category": "root-theme",
|
|
353
353
|
"description": "First categorical data-series color."
|
|
354
354
|
},
|
|
355
|
+
{
|
|
356
|
+
"name": "--esp-color-series-1-ink",
|
|
357
|
+
"category": "root-theme",
|
|
358
|
+
"description": "First series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
"name": "--esp-color-series-1-wash",
|
|
362
|
+
"category": "root-theme",
|
|
363
|
+
"description": "First series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
364
|
+
},
|
|
355
365
|
{
|
|
356
366
|
"name": "--esp-color-series-2",
|
|
357
367
|
"category": "root-theme",
|
|
358
368
|
"description": "Second categorical data-series color."
|
|
359
369
|
},
|
|
370
|
+
{
|
|
371
|
+
"name": "--esp-color-series-2-ink",
|
|
372
|
+
"category": "root-theme",
|
|
373
|
+
"description": "Second series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"name": "--esp-color-series-2-wash",
|
|
377
|
+
"category": "root-theme",
|
|
378
|
+
"description": "Second series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
379
|
+
},
|
|
360
380
|
{
|
|
361
381
|
"name": "--esp-color-series-3",
|
|
362
382
|
"category": "root-theme",
|
|
363
383
|
"description": "Third categorical data-series color."
|
|
364
384
|
},
|
|
385
|
+
{
|
|
386
|
+
"name": "--esp-color-series-3-ink",
|
|
387
|
+
"category": "root-theme",
|
|
388
|
+
"description": "Third series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
"name": "--esp-color-series-3-wash",
|
|
392
|
+
"category": "root-theme",
|
|
393
|
+
"description": "Third series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
394
|
+
},
|
|
365
395
|
{
|
|
366
396
|
"name": "--esp-color-series-4",
|
|
367
397
|
"category": "root-theme",
|
|
368
398
|
"description": "Fourth categorical data-series color."
|
|
369
399
|
},
|
|
400
|
+
{
|
|
401
|
+
"name": "--esp-color-series-4-ink",
|
|
402
|
+
"category": "root-theme",
|
|
403
|
+
"description": "Fourth series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
404
|
+
},
|
|
405
|
+
{
|
|
406
|
+
"name": "--esp-color-series-4-wash",
|
|
407
|
+
"category": "root-theme",
|
|
408
|
+
"description": "Fourth series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
409
|
+
},
|
|
370
410
|
{
|
|
371
411
|
"name": "--esp-color-series-5",
|
|
372
412
|
"category": "root-theme",
|
|
373
413
|
"description": "Fifth categorical data-series color."
|
|
374
414
|
},
|
|
415
|
+
{
|
|
416
|
+
"name": "--esp-color-series-5-ink",
|
|
417
|
+
"category": "root-theme",
|
|
418
|
+
"description": "Fifth series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
"name": "--esp-color-series-5-wash",
|
|
422
|
+
"category": "root-theme",
|
|
423
|
+
"description": "Fifth series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
424
|
+
},
|
|
375
425
|
{
|
|
376
426
|
"name": "--esp-color-series-6",
|
|
377
427
|
"category": "root-theme",
|
|
378
428
|
"description": "Sixth categorical data-series color."
|
|
379
429
|
},
|
|
430
|
+
{
|
|
431
|
+
"name": "--esp-color-series-6-ink",
|
|
432
|
+
"category": "root-theme",
|
|
433
|
+
"description": "Sixth series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
434
|
+
},
|
|
435
|
+
{
|
|
436
|
+
"name": "--esp-color-series-6-wash",
|
|
437
|
+
"category": "root-theme",
|
|
438
|
+
"description": "Sixth series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
439
|
+
},
|
|
380
440
|
{
|
|
381
441
|
"name": "--esp-color-series-7",
|
|
382
442
|
"category": "root-theme",
|
|
383
443
|
"description": "Seventh categorical data-series color."
|
|
384
444
|
},
|
|
445
|
+
{
|
|
446
|
+
"name": "--esp-color-series-7-ink",
|
|
447
|
+
"category": "root-theme",
|
|
448
|
+
"description": "Seventh series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
"name": "--esp-color-series-7-wash",
|
|
452
|
+
"category": "root-theme",
|
|
453
|
+
"description": "Seventh series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
454
|
+
},
|
|
385
455
|
{
|
|
386
456
|
"name": "--esp-color-series-8",
|
|
387
457
|
"category": "root-theme",
|
|
388
458
|
"description": "Eighth categorical data-series color."
|
|
389
459
|
},
|
|
460
|
+
{
|
|
461
|
+
"name": "--esp-color-series-8-ink",
|
|
462
|
+
"category": "root-theme",
|
|
463
|
+
"description": "Eighth series pushed to the text contrast tier against the local background (best-contrast pole when a mid-lightness surface makes the tier unreachable)."
|
|
464
|
+
},
|
|
465
|
+
{
|
|
466
|
+
"name": "--esp-color-series-8-wash",
|
|
467
|
+
"category": "root-theme",
|
|
468
|
+
"description": "Eighth series washed toward the local background (75% identity in OKLab) for large fills; theme zones re-emit it against their own canvas."
|
|
469
|
+
},
|
|
390
470
|
{
|
|
391
471
|
"name": "--esp-color-shadow",
|
|
392
472
|
"category": "root-theme",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"updatedAt": "2026-08-
|
|
3
|
+
"updatedAt": "2026-08-22",
|
|
4
4
|
"entries": [
|
|
5
5
|
{
|
|
6
6
|
"id": "google-font-preview-assets",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
{
|
|
29
29
|
"id": "tabler-svg-sprite",
|
|
30
30
|
"paths": [
|
|
31
|
-
"assets/icons.svg"
|
|
31
|
+
"assets/icons.svg",
|
|
32
|
+
"icon-sprite.generated.ts"
|
|
32
33
|
],
|
|
33
34
|
"assetType": "SVG sprite",
|
|
34
35
|
"classification": "mixed third-party and Taproot-owned",
|
|
@@ -38,9 +39,10 @@
|
|
|
38
39
|
"transformations": [
|
|
39
40
|
"Converted selected SVG icons into <symbol> entries",
|
|
40
41
|
"Normalized currentColor usage and sprite ids",
|
|
41
|
-
"Added Taproot-owned taproot-logo symbol"
|
|
42
|
+
"Added Taproot-owned taproot-logo symbol",
|
|
43
|
+
"Generated importable module (icon-sprite.generated.ts) from the sprite via scripts/build-icon-module.js for the offline story (ESP0176)"
|
|
42
44
|
],
|
|
43
|
-
"packageInclusion": "
|
|
45
|
+
"packageInclusion": "included in npm package as dist/icons/icon-sprite.generated.js (the importable inline sprite); the .svg asset itself is not packaged",
|
|
44
46
|
"docsInclusion": "copied to public docs assets by Eleventy and referenced by examples",
|
|
45
47
|
"noticeRequirement": "required",
|
|
46
48
|
"noticePaths": [
|
|
@@ -293,7 +295,7 @@
|
|
|
293
295
|
"None; used as-is as a repeating docs-site canvas gutter background at 50% image-layer opacity"
|
|
294
296
|
],
|
|
295
297
|
"packageInclusion": "not included in npm package",
|
|
296
|
-
"docsInclusion": "docs-site only
|
|
298
|
+
"docsInclusion": "docs-site only \u2014 referenced as --esp-page-canvas-background-image in css/docs.css (which the public @taprootio/espalier package excludes) and served from the Eleventy /assets passthrough",
|
|
297
299
|
"noticeRequirement": "none",
|
|
298
300
|
"noticePaths": [],
|
|
299
301
|
"reviewStatus": "documented"
|
|
@@ -312,7 +314,7 @@
|
|
|
312
314
|
"None; used as-is as a repeating docs-site dark-mode canvas gutter background at 50% image-layer opacity"
|
|
313
315
|
],
|
|
314
316
|
"packageInclusion": "not included in npm package",
|
|
315
|
-
"docsInclusion": "docs-site only
|
|
317
|
+
"docsInclusion": "docs-site only \u2014 referenced as --esp-page-canvas-background-image under esp-root[scheme=\"dark\"] in css/docs.css (excluded from the public @taprootio/espalier package) and served from the Eleventy /assets passthrough",
|
|
316
318
|
"noticeRequirement": "none",
|
|
317
319
|
"noticePaths": [],
|
|
318
320
|
"reviewStatus": "documented"
|
|
@@ -366,7 +368,7 @@
|
|
|
366
368
|
}
|
|
367
369
|
],
|
|
368
370
|
"packageInclusion": "not included in npm package",
|
|
369
|
-
"docsInclusion": "docs-site only
|
|
371
|
+
"docsInclusion": "docs-site only \u2014 linked from docs/_includes/layout.vto and docs/404.vto and served from the Eleventy /assets passthrough, so the documentation shell renders its theme faces without runtime fonts.googleapis.com links",
|
|
370
372
|
"noticeRequirement": "required",
|
|
371
373
|
"noticePaths": [
|
|
372
374
|
"licenses/THIRD_PARTY_NOTICES.md"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@taprootio/espalier",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.4.0",
|
|
4
4
|
"packageManager": "bun@1.3.12",
|
|
5
5
|
"description": "Espalier — a themeable, accessible, framework-agnostic, enterprise-grade design system built on web standards and love.",
|
|
6
6
|
"customElements": "custom-elements.json",
|
|
@@ -8,6 +8,9 @@
|
|
|
8
8
|
"main": "dist/index.js",
|
|
9
9
|
"module": "dist/index.js",
|
|
10
10
|
"types": "dist/index.d.ts",
|
|
11
|
+
"bin": {
|
|
12
|
+
"espalier": "./dist/cli/espalier.js"
|
|
13
|
+
},
|
|
11
14
|
"exports": {
|
|
12
15
|
".": {
|
|
13
16
|
"types": "./dist/index.d.ts",
|
|
@@ -130,6 +133,10 @@
|
|
|
130
133
|
"types": "./dist/grid/esp-grid.d.ts",
|
|
131
134
|
"import": "./dist/grid/esp-grid.js"
|
|
132
135
|
},
|
|
136
|
+
"./icons": {
|
|
137
|
+
"types": "./dist/icons/index.d.ts",
|
|
138
|
+
"import": "./dist/icons/index.js"
|
|
139
|
+
},
|
|
133
140
|
"./header": {
|
|
134
141
|
"types": "./dist/header/index.d.ts",
|
|
135
142
|
"import": "./dist/header/index.js"
|