@taprootio/espalier 4.3.0 → 4.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.
Files changed (55) hide show
  1. package/css/fonts/font-fallback-profiles.json +1 -0
  2. package/custom-elements.json +7405 -6807
  3. package/dist/action-menu/esp-action-menu-item.js +7 -4
  4. package/dist/avatar/esp-avatar.js +14 -8
  5. package/dist/avatar/esp-profile-chip.js +4 -1
  6. package/dist/badge/esp-badge.js +7 -4
  7. package/dist/box/esp-box.d.ts +1 -1
  8. package/dist/checkbox/esp-checkbox.js +6 -3
  9. package/dist/color-picker/esp-color-picker.js +1 -1
  10. package/dist/data-cell/esp-data-cell.js +6 -3
  11. package/dist/date-picker/helpers/styles.js +10 -4
  12. package/dist/details/esp-details.d.ts +4 -4
  13. package/dist/details/esp-details.js +11 -5
  14. package/dist/empty-state/esp-empty-state.js +16 -7
  15. package/dist/flyout/esp-flyout.js +5 -2
  16. package/dist/font-picker/esp-font-picker.d.ts +1 -0
  17. package/dist/font-picker/esp-font-picker.js +4 -4
  18. package/dist/footer/esp-footer-link-group.js +12 -6
  19. package/dist/footer/esp-footer.js +21 -6
  20. package/dist/form-item/esp-form-item.js +4 -1
  21. package/dist/header/esp-header.d.ts +2 -1
  22. package/dist/header/esp-header.js +24 -6
  23. package/dist/help/esp-help-button.d.ts +1 -1
  24. package/dist/help/help-document.js +4 -4
  25. package/dist/index.d.ts +2 -1
  26. package/dist/index.js +1 -1
  27. package/dist/lightbox/esp-lightbox.d.ts +1 -1
  28. package/dist/page/esp-page.js +4 -1
  29. package/dist/pickers/esp-picker-menu.js +6 -6
  30. package/dist/progress/esp-progress.js +11 -5
  31. package/dist/radio-button/esp-radio-button.js +6 -3
  32. package/dist/root/esp-root.d.ts +8 -0
  33. package/dist/root/esp-root.js +13 -7
  34. package/dist/root/helpers/compute-theme-properties.js +1 -1
  35. package/dist/search/esp-search.js +10 -4
  36. package/dist/shared/esp-element-base.js +20 -4
  37. package/dist/shared/font-helpers.d.ts +26 -0
  38. package/dist/shared/font-helpers.js +1 -1
  39. package/dist/shared/font-plan.d.ts +90 -0
  40. package/dist/shared/font-plan.js +5 -0
  41. package/dist/shared/scale-engine.js +1 -1
  42. package/dist/shared/theme.d.ts +28 -4
  43. package/dist/shared/theme.js +1 -1
  44. package/dist/slider/esp-slider.js +8 -5
  45. package/dist/status-indicator/esp-status-indicator.d.ts +1 -1
  46. package/dist/switch/esp-switch.js +11 -5
  47. package/dist/tabs/esp-tab-group.js +6 -3
  48. package/dist/tabs/esp-tab.js +6 -3
  49. package/dist/tree/esp-tree.js +4 -1
  50. package/espalier.css-data.json +9 -5
  51. package/espalier.token-manifest.json +13 -5
  52. package/licenses/ASSET_PROVENANCE.md +2 -1
  53. package/licenses/THIRD_PARTY_NOTICES.md +35 -0
  54. package/licenses/asset-provenance.json +26 -2
  55. package/package.json +8 -2
@@ -63,6 +63,10 @@ export type { SchemeEvents } from "../shared/bus-events.js";
63
63
  *
64
64
  * @customElement esp-root
65
65
  * @slot - Place Espalier components and content here.
66
+ * @cssprop --esp-font-body - Always-emitted family for body and UI text. Defaults to `system-ui, sans-serif` when `fontBody` is omitted or empty.
67
+ * @cssprop --esp-font-headings - Consumer-authored heading family. Emitted only when configured; heading recipes otherwise fall back to `--esp-font-body`.
68
+ * @cssprop --esp-font-brand - Consumer-authored brand family. Emitted only when configured; brand recipes otherwise fall back through headings to `--esp-font-body`.
69
+ * @cssprop --esp-font-monospace - Family for code and monospace text. Defaults to `monospace`.
66
70
  * @cssprop --esp-color-series-1 - First categorical data-series color.
67
71
  * @cssprop --esp-color-series-2 - Second categorical data-series color.
68
72
  * @cssprop --esp-color-series-3 - Third categorical data-series color.
@@ -243,6 +247,10 @@ export declare class EspalierRoot extends LitElement implements SeedColorRoot {
243
247
  * `fonts.googleapis.com`. `none` prevents those runtime Google
244
248
  * Fonts links, leaving local preview CSS and web-safe font stacks
245
249
  * available for locked-down, offline, or strict-CSP environments.
250
+ * Static generators should compile the resolved light/dark themes with
251
+ * `compileFontPlan()`, embed its CSS in the page head, and set this policy
252
+ * to `none`; the predeclared target and metric-matched fallback faces then
253
+ * participate in first layout without any runtime catalog request.
246
254
  *
247
255
  * @type {"auto" | "none"}
248
256
  * @default "auto"
@@ -1,7 +1,7 @@
1
- var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,t):i,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(c,e,t,i);else for(var n=c.length-1;n>=0;n--)(r=c[n])&&(s=(l<3?r(s):l>3?r(e,t,s):r(e,t))||s);return l>3&&s&&Object.defineProperty(e,t,s),s},a;import{css as b,html as w,LitElement as E}from"lit";import{customElement as C,property as m,state as R}from"lit/decorators.js";import{getEspBus as p}from"../shared/bus-events.js";import{subscribeToRootEvent as x}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as y,encodeTheme as S,parseTheme as g,mergeTheme as v}from"../shared/theme.js";import{computeThemeProperties as D}from"./helpers/compute-theme-properties.js";import{registerImageTexture as A,registeredImageTextures as L}from"../shared/image-texture-registry.js";import{registerImageTexture as O,registeredImageTextures as j,BUILT_IN_IMAGE_TEXTURES as H}from"../shared/image-texture-registry.js";const T=1e3;let o=a=class extends E{constructor(){super(...arguments),this.schemeBacker="",this.schemeExplicitlySet=!1,this.resolvingDefaultScheme=!1,this.themeEventsReady=!1,this.systemSchemeQuery=null,this.lastSeedColor="",this.resolvedLightTheme={...f},this.resolvedDarkTheme={...y},this.appliedDataRampProperties=new Set,this.documentClickRegistrationActive=!1,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.lightThemeAttr="",this.darkThemeAttr="",this.fontCSSRoot="/css/fonts/",this.fontDefinitionsUrl="",this.googleFontLoading="auto",this.iconSpriteUrl="/assets/icons.svg",this.themePending=!1,this.themeReadyState=!1,this.themeSettleWaiters=[],this.warnedThemeSettleTimeout=!1,this.defaultScheme="light",this.resizeObserver=new ResizeObserver(()=>{p().publish("window-resized",{emWidth:window.innerWidth/parseFloat(getComputedStyle(document.documentElement).fontSize),emHeight:window.innerHeight/parseFloat(getComputedStyle(document.documentElement).fontSize),pxWidth:window.innerWidth,pxHeight:window.innerHeight})}),this.handleSystemSchemeChange=e=>{this.schemeExplicitlySet||this.defaultScheme!=="system"||(this.resolvingDefaultScheme=!0,this.scheme=e.matches?"dark":"light",this.resolvingDefaultScheme=!1)}}static registerTexture(e,t){A(e,t)}static registeredTextures(){return L()}subscribeScoped(e,t){return x(this,e,t)}get lightTheme(){return this.lightThemeAttr?g(this.lightThemeAttr):null}set lightTheme(e){this.lightThemeAttr=e?S(e):""}get darkTheme(){return this.darkThemeAttr?g(this.darkThemeAttr):null}set darkTheme(e){this.darkThemeAttr=e?S(e):""}get themeSettled(){return this.themeReadyState}whenThemeSettled(){return this.themeReadyState?Promise.resolve():new Promise(e=>{this.themeSettleWaiters.push(e)})}get hasAuthorTheme(){return!!(this.scheme==="dark"?this.darkThemeAttr:this.lightThemeAttr)}settleTheme(){if(this.themeSettleTimer!==void 0&&(clearTimeout(this.themeSettleTimer),this.themeSettleTimer=void 0),this.themeReadyState)return;this.themeReadyState=!0;const e=this.themeSettleWaiters;this.themeSettleWaiters=[];for(const t of e)t()}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",i=this.schemeBacker,l=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const s=t||this.resolveDefaultScheme();l!==this.schemeExplicitlySet&&this.isConnected&&this.syncSystemSchemeListener(),s!==i&&(this.schemeBacker=s,this.requestUpdate("scheme",i),this.themeEventsReady&&p().publish("scheme-changed",{scheme:s,correlationId:this.correlationId}))}get seedColor(){return this.activeTheme.seedColor}static extractFamily(e){if(!e)return"";const t=e.match(/^"([^"]+)"|^'([^']+)'/);return t&&(t[1]||t[2])||""}injectGoogleFontLink(e,t,i){const l="data-esp-font",s=`${this.correlationId}-${e}`,r=document.head.querySelector(`link[${l}="${s}"]`);if(this.googleFontLoading==="none"){r?.remove();return}if(r&&t&&r.dataset.espFamily===t&&r.dataset.espWeight===(i??"")||(r?.remove(),!t))return;const n=encodeURIComponent(t),u=i==="bold"?"700":i==="normal"?"400":i,k=u&&u!=="400"?`:wght@${u}`:"",d=document.createElement("link");d.rel="stylesheet",d.href=`https://fonts.googleapis.com/css2?family=${n}${k}&display=swap`,d.setAttribute(l,s),d.dataset.espFamily=t,d.dataset.espWeight=i??"",document.head.appendChild(d)}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",a.extractFamily(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",a.extractFamily(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",a.extractFamily(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",a.extractFamily(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){for(const e of document.head.querySelectorAll(`link[data-esp-font^="${this.correlationId}-"]`))e.remove();for(const e of document.head.querySelectorAll(`link[data-esp-font-picker-root="${CSS.escape(this.correlationId)}"]`))e.remove()}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?g(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?g(this.darkThemeAttr):null;this.resolvedDarkTheme=t?v(y,t):{...y}}connectedCallback(){super.connectedCallback(),this.registerDocumentClickBridge(),this.resizeObserver.observe(this),this.hasUpdated&&(this.applyDefaultScheme(),this.syncGoogleFontLinks(),this.hasAuthorTheme||this.startThemeSettleTimer())}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(n=>e.has(n)))&&(this.resolveThemes(),this.themeEventsReady&&p().publish("theme-changed",{correlationId:this.correlationId})),this.hasAuthorTheme&&this.settleTheme();const l=D(this.activeTheme,this.scheme==="dark"?"dark":"light"),s=new Set(Object.keys(l).filter(n=>n.startsWith("--esp-color-ramp-")));for(const n of this.appliedDataRampProperties)s.has(n)||this.style.removeProperty(n);for(const[n,u]of Object.entries(l))this.style.setProperty(n,u);this.appliedDataRampProperties=s;const r=this.activeTheme.seedColor;this.themeEventsReady&&this.lastSeedColor&&this.lastSeedColor!==r&&p().publish("seed-color-changed",{seedColor:r,correlationId:this.correlationId}),this.lastSeedColor=r,this.themeEventsReady&&e.has("iconSpriteUrl")&&p().publish("icon-sprite-url-changed",{iconSpriteUrl:this.iconSpriteUrl,correlationId:this.correlationId}),this.syncGoogleFontLinks()}firstUpdated(){const e=this.activeTheme.stylesheets;if(e.length)for(const t of e){const i=document.createElement("link");i.rel="stylesheet",i.href=t,document.head.appendChild(i)}if(!document.getElementById("esp-root-base-styles")){const t=document.createElement("style");t.id="esp-root-base-styles",t.textContent=a.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme(),this.lastSeedColor=this.activeTheme.seedColor,this.themeEventsReady=!0,this.startThemeSettleTimer()}startThemeSettleTimer(){if(this.themeReadyState||this.themeSettleTimer!==void 0)return;this.themeSettleDeadline??=performance.now()+T;const e=Math.max(0,this.themeSettleDeadline-performance.now());if(e===0){this.closeThemeWindow();return}this.themeSettleTimer=setTimeout(()=>this.closeThemeWindow(),e)}closeThemeWindow(){this.themeSettleTimer=void 0,this.themePending&&!this.warnedThemeSettleTimeout&&(this.warnedThemeSettleTimeout=!0,console.warn(`Espalier root: theme-pending was declared but no ${this.scheme} theme arrived within ${T}ms, so the default palette is rendering. Assign ${this.scheme==="dark"?"darkTheme":"lightTheme"} (or remove theme-pending).`)),this.settleTheme()}updated(e){this.toggleAttribute("data-theme-ready",this.themeReadyState),(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.themeSettleTimer!==void 0&&(clearTimeout(this.themeSettleTimer),this.themeSettleTimer=void 0),this.unregisterDocumentClickBridge(),this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),this.removeRuntimeGoogleFontLinks(),super.disconnectedCallback()}registerDocumentClickBridge(){this.documentClickRegistrationActive||(this.documentClickRegistrationActive=!0,a.connectedRootCount+=1,a.connectedRootCount===1&&document.addEventListener("click",a.handleDocumentClick))}unregisterDocumentClickBridge(){this.documentClickRegistrationActive&&(this.documentClickRegistrationActive=!1,a.connectedRootCount=Math.max(0,a.connectedRootCount-1),a.connectedRootCount===0&&document.removeEventListener("click",a.handleDocumentClick))}applyDefaultScheme(){this.schemeExplicitlySet||(this.resolvingDefaultScheme=!0,this.scheme=this.resolveDefaultScheme(),this.resolvingDefaultScheme=!1,this.syncSystemSchemeListener())}resolveDefaultScheme(){return this.defaultScheme==="dark"||this.defaultScheme==="system"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light"}syncSystemSchemeListener(){if(this.schemeExplicitlySet||this.defaultScheme!=="system"||!window.matchMedia){this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null;return}this.systemSchemeQuery||(this.systemSchemeQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.systemSchemeQuery.addEventListener("change",this.handleSystemSchemeChange))}render(){return w`<slot></slot>`}};o.connectedRootCount=0,o.handleDocumentClick=c=>{const e=c.composedPath().filter(t=>t instanceof HTMLElement&&t.tagName==="ESP-POPOVER");p().publish("close-popovers",{source:c.target??void 0,skipPopovers:e})},o.lightDomStyles=`
1
+ var r=function(c,e,t,s){var n=arguments.length,i=n<3?e:s===null?s=Object.getOwnPropertyDescriptor(e,t):s,m;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")i=Reflect.decorate(c,e,t,s);else for(var h=c.length-1;h>=0;h--)(m=c[h])&&(i=(n<3?m(i):n>3?m(e,t,i):m(e,t))||i);return n>3&&i&&Object.defineProperty(e,t,i),i},l;import{css as b,html as w,LitElement as E}from"lit";import{customElement as R,property as a,state as C}from"lit/decorators.js";import{getEspBus as d}from"../shared/bus-events.js";import{subscribeToRootEvent as x}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as g,encodeTheme as y,parseTheme as p,mergeTheme as v}from"../shared/theme.js";import{extractFamily as u,isLocalFontFamily as D,removeRuntimeGoogleFontLinks as S,syncRuntimeGoogleFontLink as L}from"../shared/font-helpers.js";import{computeThemeProperties as A}from"./helpers/compute-theme-properties.js";import{registerImageTexture as I,registeredImageTextures as F}from"../shared/image-texture-registry.js";import{registerImageTexture as $,registeredImageTextures as Q,BUILT_IN_IMAGE_TEXTURES as q}from"../shared/image-texture-registry.js";const T=1e3;let o=l=class extends E{constructor(){super(...arguments),this.schemeBacker="",this.schemeExplicitlySet=!1,this.resolvingDefaultScheme=!1,this.themeEventsReady=!1,this.systemSchemeQuery=null,this.lastSeedColor="",this.resolvedLightTheme={...f},this.resolvedDarkTheme={...g},this.appliedDataRampProperties=new Set,this.documentClickRegistrationActive=!1,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.lightThemeAttr="",this.darkThemeAttr="",this.fontCSSRoot="/css/fonts/",this.fontDefinitionsUrl="",this.googleFontLoading="auto",this.iconSpriteUrl="/assets/icons.svg",this.themePending=!1,this.themeReadyState=!1,this.themeSettleWaiters=[],this.warnedThemeSettleTimeout=!1,this.defaultScheme="light",this.resizeObserver=new ResizeObserver(()=>{d().publish("window-resized",{emWidth:window.innerWidth/parseFloat(getComputedStyle(document.documentElement).fontSize),emHeight:window.innerHeight/parseFloat(getComputedStyle(document.documentElement).fontSize),pxWidth:window.innerWidth,pxHeight:window.innerHeight})}),this.handleSystemSchemeChange=e=>{this.schemeExplicitlySet||this.defaultScheme!=="system"||(this.resolvingDefaultScheme=!0,this.scheme=e.matches?"dark":"light",this.resolvingDefaultScheme=!1)}}static registerTexture(e,t){I(e,t)}static registeredTextures(){return F()}subscribeScoped(e,t){return x(this,e,t)}get lightTheme(){return this.lightThemeAttr?p(this.lightThemeAttr):null}set lightTheme(e){this.lightThemeAttr=e?y(e):""}get darkTheme(){return this.darkThemeAttr?p(this.darkThemeAttr):null}set darkTheme(e){this.darkThemeAttr=e?y(e):""}get themeSettled(){return this.themeReadyState}whenThemeSettled(){return this.themeReadyState?Promise.resolve():new Promise(e=>{this.themeSettleWaiters.push(e)})}get hasAuthorTheme(){return!!(this.scheme==="dark"?this.darkThemeAttr:this.lightThemeAttr)}settleTheme(){if(this.themeSettleTimer!==void 0&&(clearTimeout(this.themeSettleTimer),this.themeSettleTimer=void 0),this.themeReadyState)return;this.themeReadyState=!0;const e=this.themeSettleWaiters;this.themeSettleWaiters=[];for(const t of e)t()}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",s=this.schemeBacker,n=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const i=t||this.resolveDefaultScheme();n!==this.schemeExplicitlySet&&this.isConnected&&this.syncSystemSchemeListener(),i!==s&&(this.schemeBacker=i,this.requestUpdate("scheme",s),this.themeEventsReady&&d().publish("scheme-changed",{scheme:i,correlationId:this.correlationId}))}get seedColor(){return this.activeTheme.seedColor}injectGoogleFontLink(e,t,s){const n=`${this.correlationId}-${e}`,i=D(t)?"":t;L({owner:`root:${n}`,family:i,weight:s,enabled:this.googleFontLoading!=="none",attributes:{"data-esp-font":n}})}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",u(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",u(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",u(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",u(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){S(`root:${this.correlationId}-`),S(`picker:${this.correlationId}:`);for(const e of document.head.querySelectorAll(`link[data-esp-font^="${this.correlationId}-"]`))e.remove();for(const e of document.head.querySelectorAll(`link[data-esp-font-picker-root="${CSS.escape(this.correlationId)}"]`))e.remove()}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?p(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?p(this.darkThemeAttr):null;this.resolvedDarkTheme=t?v(g,t):{...g}}connectedCallback(){super.connectedCallback(),this.registerDocumentClickBridge(),this.resizeObserver.observe(this),this.hasUpdated&&(this.applyDefaultScheme(),this.syncGoogleFontLinks(),this.hasAuthorTheme||this.startThemeSettleTimer())}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(h=>e.has(h)))&&(this.resolveThemes(),this.themeEventsReady&&d().publish("theme-changed",{correlationId:this.correlationId})),this.hasAuthorTheme&&this.settleTheme();const n=A(this.activeTheme,this.scheme==="dark"?"dark":"light"),i=new Set(Object.keys(n).filter(h=>h.startsWith("--esp-color-ramp-")));for(const h of this.appliedDataRampProperties)i.has(h)||this.style.removeProperty(h);for(const[h,k]of Object.entries(n))this.style.setProperty(h,k);this.appliedDataRampProperties=i;const m=this.activeTheme.seedColor;this.themeEventsReady&&this.lastSeedColor&&this.lastSeedColor!==m&&d().publish("seed-color-changed",{seedColor:m,correlationId:this.correlationId}),this.lastSeedColor=m,this.themeEventsReady&&e.has("iconSpriteUrl")&&d().publish("icon-sprite-url-changed",{iconSpriteUrl:this.iconSpriteUrl,correlationId:this.correlationId}),this.syncGoogleFontLinks()}firstUpdated(){const e=this.activeTheme.stylesheets;if(e.length)for(const t of e){const s=document.createElement("link");s.rel="stylesheet",s.href=t,document.head.appendChild(s)}if(!document.getElementById("esp-root-base-styles")){const t=document.createElement("style");t.id="esp-root-base-styles",t.textContent=l.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme(),this.lastSeedColor=this.activeTheme.seedColor,this.themeEventsReady=!0,this.startThemeSettleTimer()}startThemeSettleTimer(){if(this.themeReadyState||this.themeSettleTimer!==void 0)return;this.themeSettleDeadline??=performance.now()+T;const e=Math.max(0,this.themeSettleDeadline-performance.now());if(e===0){this.closeThemeWindow();return}this.themeSettleTimer=setTimeout(()=>this.closeThemeWindow(),e)}closeThemeWindow(){this.themeSettleTimer=void 0,this.themePending&&!this.warnedThemeSettleTimeout&&(this.warnedThemeSettleTimeout=!0,console.warn(`Espalier root: theme-pending was declared but no ${this.scheme} theme arrived within ${T}ms, so the default palette is rendering. Assign ${this.scheme==="dark"?"darkTheme":"lightTheme"} (or remove theme-pending).`)),this.settleTheme()}updated(e){this.toggleAttribute("data-theme-ready",this.themeReadyState),(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.themeSettleTimer!==void 0&&(clearTimeout(this.themeSettleTimer),this.themeSettleTimer=void 0),this.unregisterDocumentClickBridge(),this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),this.removeRuntimeGoogleFontLinks(),super.disconnectedCallback()}registerDocumentClickBridge(){this.documentClickRegistrationActive||(this.documentClickRegistrationActive=!0,l.connectedRootCount+=1,l.connectedRootCount===1&&document.addEventListener("click",l.handleDocumentClick))}unregisterDocumentClickBridge(){this.documentClickRegistrationActive&&(this.documentClickRegistrationActive=!1,l.connectedRootCount=Math.max(0,l.connectedRootCount-1),l.connectedRootCount===0&&document.removeEventListener("click",l.handleDocumentClick))}applyDefaultScheme(){this.schemeExplicitlySet||(this.resolvingDefaultScheme=!0,this.scheme=this.resolveDefaultScheme(),this.resolvingDefaultScheme=!1,this.syncSystemSchemeListener())}resolveDefaultScheme(){return this.defaultScheme==="dark"||this.defaultScheme==="system"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light"}syncSystemSchemeListener(){if(this.schemeExplicitlySet||this.defaultScheme!=="system"||!window.matchMedia){this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null;return}this.systemSchemeQuery||(this.systemSchemeQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.systemSchemeQuery.addEventListener("change",this.handleSystemSchemeChange))}render(){return w`<slot></slot>`}};o.connectedRootCount=0,o.handleDocumentClick=c=>{const e=c.composedPath().filter(t=>t instanceof HTMLElement&&t.tagName==="ESP-POPOVER");d().publish("close-popovers",{source:c.target??void 0,skipPopovers:e})},o.lightDomStyles=`
2
2
 
3
3
  esp-root {
4
- font-family: var(--esp-font-body);
4
+ font-family: var(--_esp-font-body-effective, var(--esp-font-body, system-ui, sans-serif));
5
5
  font-weight: var(--esp-font-weight-body);
6
6
  line-height: 1.5;
7
7
  font-size: var(--esp-type-normal);
@@ -23,7 +23,7 @@ var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnP
23
23
  esp-root input,
24
24
  esp-root select,
25
25
  esp-root button {
26
- font-family: var(--esp-font-body);
26
+ font-family: var(--_esp-font-body-effective, var(--esp-font-body, system-ui, sans-serif));
27
27
  }
28
28
 
29
29
 
@@ -53,7 +53,7 @@ var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnP
53
53
  esp-root p,
54
54
  esp-root ul,
55
55
  esp-root li {
56
- font-family: var(--esp-font-body);
56
+ font-family: var(--_esp-font-body-effective, var(--esp-font-body, system-ui, sans-serif));
57
57
  color: var(--esp-color-text);
58
58
  font-size: inherit;
59
59
  }
@@ -68,7 +68,13 @@ var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnP
68
68
  esp-root h3,
69
69
  esp-root h4,
70
70
  esp-root h5 {
71
- font-family: var(--esp-font-headings);
71
+ font-family: var(
72
+ --_esp-font-headings-effective,
73
+ var(
74
+ --esp-font-headings,
75
+ var(--_esp-font-body-effective, var(--esp-font-body, system-ui, sans-serif))
76
+ )
77
+ );
72
78
  font-weight: var(--esp-font-weight-headings);
73
79
  color: var(--esp-color-headings);
74
80
  margin: var(--esp-size-small-to-normal) 0 var(--esp-size-tiny-to-small);
@@ -83,7 +89,7 @@ var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnP
83
89
 
84
90
  esp-root pre,
85
91
  esp-root code {
86
- font-family: var(--esp-font-monospace);
92
+ font-family: var(--_esp-font-monospace-effective, var(--esp-font-monospace, monospace));
87
93
  font-weight: var(--esp-font-weight-monospace);
88
94
  }
89
95
 
@@ -130,4 +136,4 @@ var h=function(c,e,t,i){var l=arguments.length,s=l<3?e:i===null?i=Object.getOwnP
130
136
  :host([theme-pending]:not([data-theme-ready])) {
131
137
  visibility: hidden;
132
138
  }
133
- `,h([m({attribute:!1})],o.prototype,"correlationId",void 0),h([m({attribute:"light-theme"})],o.prototype,"lightThemeAttr",void 0),h([m({attribute:"dark-theme"})],o.prototype,"darkThemeAttr",void 0),h([m({attribute:!1})],o.prototype,"lightTheme",null),h([m({attribute:!1})],o.prototype,"darkTheme",null),h([m({attribute:"font-css-root",type:String})],o.prototype,"fontCSSRoot",void 0),h([m({attribute:"font-definitions-url",type:String})],o.prototype,"fontDefinitionsUrl",void 0),h([m({attribute:"google-font-loading",type:String})],o.prototype,"googleFontLoading",void 0),h([m({attribute:"icon-sprite-url",type:String})],o.prototype,"iconSpriteUrl",void 0),h([m({attribute:"theme-pending",reflect:!0,type:Boolean})],o.prototype,"themePending",void 0),h([R()],o.prototype,"themeReadyState",void 0),h([m({attribute:"default-scheme",type:String,reflect:!0})],o.prototype,"defaultScheme",void 0),h([m({attribute:"scheme",type:String,reflect:!0})],o.prototype,"scheme",null),o=a=h([C("esp-root")],o);export{H as BUILT_IN_IMAGE_TEXTURES,o as EspalierRoot,O as registerImageTexture,j as registeredImageTextures};
139
+ `,r([a({attribute:!1})],o.prototype,"correlationId",void 0),r([a({attribute:"light-theme"})],o.prototype,"lightThemeAttr",void 0),r([a({attribute:"dark-theme"})],o.prototype,"darkThemeAttr",void 0),r([a({attribute:!1})],o.prototype,"lightTheme",null),r([a({attribute:!1})],o.prototype,"darkTheme",null),r([a({attribute:"font-css-root",type:String})],o.prototype,"fontCSSRoot",void 0),r([a({attribute:"font-definitions-url",type:String})],o.prototype,"fontDefinitionsUrl",void 0),r([a({attribute:"google-font-loading",type:String})],o.prototype,"googleFontLoading",void 0),r([a({attribute:"icon-sprite-url",type:String})],o.prototype,"iconSpriteUrl",void 0),r([a({attribute:"theme-pending",reflect:!0,type:Boolean})],o.prototype,"themePending",void 0),r([C()],o.prototype,"themeReadyState",void 0),r([a({attribute:"default-scheme",type:String,reflect:!0})],o.prototype,"defaultScheme",void 0),r([a({attribute:"scheme",type:String,reflect:!0})],o.prototype,"scheme",null),o=l=r([R("esp-root")],o);export{q as BUILT_IN_IMAGE_TEXTURES,o as EspalierRoot,$ as registerImageTexture,Q as registeredImageTextures};
@@ -1 +1 @@
1
- import{parseCssColor as f,serializeOklch as u,gamutMapToSRGB as m}from"../../shared/color-engine.js";import{generateScaleProperties as y}from"../../shared/scale-engine.js";import{DATA_SERIES_KEYS as b,DEFAULT_DATA_PALETTE as k,generateDivergingRamp as v,generateSequentialRamp as B}from"../../shared/data-colors.js";import{resolveDataColorSource as R}from"../../shared/theme.js";import{dataCompanionProperties as O}from"./data-companion-properties.js";import{lightnessRampProperties as w}from"./lightness-ramp-properties.js";import{computeVariants as $}from"./compute-variants.js";import{computeSemanticProperties as E}from"./compute-semantic-properties.js";function I(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function x(o,d,g){const i={},a=o.dataPalette??k;for(let r=0;r<b.length;r+=1){const c=b[r],t=f(g(a[c],`dataPalette.${c}`))??d;i[`--esp-color-series-${r+1}`]=u(m(t))}return i}function _(o,d,g){const i=f(o.seedColor);if(!i)return{};const a={};a["--esp-scheme"]=d,a["--esp-seed-color"]=o.seedColor;const r=$(i,o);for(const[e,n]of Object.entries(r))a[`--esp-color-${e}`]=u(m(n));const c=new Set,t=(e,n)=>{const s=typeof e=="string"?R(e,o.anchors):null;if(s)return s;const p=typeof e=="string"?e:String(e);return c.has(p)||(c.add(p),console.warn(`Espalier theme: ${n} color source "${p}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared data colors.`)),o.seedColor};Object.assign(a,x(o,i,t));for(const[e,n]of Object.entries(o.dataRamps??{}))try{(n.type==="sequential"?B(t(n.source,`dataRamps.${e}.source`),{steps:n.steps,lightnessStart:n.lightnessStart,lightnessEnd:n.lightnessEnd}):v(t(n.start,`dataRamps.${e}.start`),t(n.end,`dataRamps.${e}.end`),{steps:n.steps,neutral:n.neutral===void 0?void 0:t(n.neutral,`dataRamps.${e}.neutral`)})).forEach((p,S)=>{a[`--esp-color-ramp-${e}-${S+1}`]=p})}catch(s){console.warn(`Espalier theme: dataRamps.${e} cannot be generated \u2014 ${s instanceof Error?s.message:String(s)}`)}Object.assign(a,w(o));const l=new Set;return Object.assign(a,E(o,r,{trace:g,onUnresolvedSource:e=>{l.has(e)||(l.add(e),console.warn(`Espalier theme: color source "${e}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`))}})),Object.assign(a,O(a)),Object.assign(a,y(I(o))),o.fontBody&&(a["--esp-font-body"]=o.fontBody),o.fontHeadings&&(a["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(a["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(a["--esp-font-monospace"]=o.fontMonospace),a["--esp-font-weight-body"]=o.fontWeightBody,a["--esp-font-weight-headings"]=o.fontWeightHeadings,a["--esp-font-weight-brand"]=o.fontWeightBrand,a["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(a["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(a["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(a["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(a["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(a["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(a["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(a["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),a}export{_ as computeThemeProperties,x as dataSeriesProperties};
1
+ import{parseCssColor as f,serializeOklch as u,gamutMapToSRGB as m}from"../../shared/color-engine.js";import{generateScaleProperties as y}from"../../shared/scale-engine.js";import{DATA_SERIES_KEYS as b,DEFAULT_DATA_PALETTE as k,generateDivergingRamp as v,generateSequentialRamp as O}from"../../shared/data-colors.js";import{DEFAULT_BODY_FONT_FAMILY as B,DEFAULT_MONOSPACE_FONT_FAMILY as R,resolveDataColorSource as E}from"../../shared/theme.js";import{dataCompanionProperties as w}from"./data-companion-properties.js";import{lightnessRampProperties as I}from"./lightness-ramp-properties.js";import{computeVariants as $}from"./compute-variants.js";import{computeSemanticProperties as T}from"./compute-semantic-properties.js";function x(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function A(o,d,g){const i={},a=o.dataPalette??k;for(let r=0;r<b.length;r+=1){const c=b[r],t=f(g(a[c],`dataPalette.${c}`))??d;i[`--esp-color-series-${r+1}`]=u(m(t))}return i}function U(o,d,g){const i=f(o.seedColor);if(!i)return{};const a={};a["--esp-scheme"]=d,a["--esp-seed-color"]=o.seedColor;const r=$(i,o);for(const[e,n]of Object.entries(r))a[`--esp-color-${e}`]=u(m(n));const c=new Set,t=(e,n)=>{const s=typeof e=="string"?E(e,o.anchors):null;if(s)return s;const p=typeof e=="string"?e:String(e);return c.has(p)||(c.add(p),console.warn(`Espalier theme: ${n} color source "${p}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared data colors.`)),o.seedColor};Object.assign(a,A(o,i,t));for(const[e,n]of Object.entries(o.dataRamps??{}))try{(n.type==="sequential"?O(t(n.source,`dataRamps.${e}.source`),{steps:n.steps,lightnessStart:n.lightnessStart,lightnessEnd:n.lightnessEnd}):v(t(n.start,`dataRamps.${e}.start`),t(n.end,`dataRamps.${e}.end`),{steps:n.steps,neutral:n.neutral===void 0?void 0:t(n.neutral,`dataRamps.${e}.neutral`)})).forEach((p,S)=>{a[`--esp-color-ramp-${e}-${S+1}`]=p})}catch(s){console.warn(`Espalier theme: dataRamps.${e} cannot be generated \u2014 ${s instanceof Error?s.message:String(s)}`)}Object.assign(a,I(o));const l=new Set;return Object.assign(a,T(o,r,{trace:g,onUnresolvedSource:e=>{l.has(e)||(l.add(e),console.warn(`Espalier theme: color source "${e}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`))}})),Object.assign(a,w(a)),Object.assign(a,y(x(o))),a["--esp-font-body"]=o.fontBody||B,o.fontHeadings&&(a["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(a["--esp-font-brand"]=o.fontBrand),a["--esp-font-monospace"]=o.fontMonospace||R,a["--esp-font-weight-body"]=o.fontWeightBody,a["--esp-font-weight-headings"]=o.fontWeightHeadings,a["--esp-font-weight-brand"]=o.fontWeightBrand,a["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(a["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(a["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(a["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(a["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(a["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(a["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(a["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),a}export{U as computeThemeProperties,A as dataSeriesProperties};
@@ -1,7 +1,7 @@
1
- var o=function(a,e,t,c){var h=arguments.length,r=h<3?e:c===null?c=Object.getOwnPropertyDescriptor(e,t):c,p;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(a,e,t,c);else for(var d=a.length-1;d>=0;d--)(p=a[d])&&(r=(h<3?p(r):h>3?p(e,t,r):p(e,t))||r);return h>3&&r&&Object.defineProperty(e,t,r),r};import{css as y,html as l,nothing as i}from"lit";import{customElement as k,property as w,state as n}from"lit/decorators.js";import{classMap as f}from"lit/directives/class-map.js";import{createRef as u,ref as v}from"lit/directives/ref.js";import{unsafeHTML as E}from"lit/directives/unsafe-html.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{OverlayController as I}from"../shared/overlay-controller.js";import{ESP_EVENTS as m}from"../shared/events.js";import{srOnly as R}from"../shared/style-fragments.js";const g="%%ESP_MARK_OPEN%%",x="%%ESP_MARK_CLOSE%%";function $(a){return a.replace(/<mark>/gi,g).replace(/<\/mark>/gi,x).replace(/<[^>]*>/g,"").replaceAll(g,"<mark>").replaceAll(x,"</mark>")}let s=class extends b{constructor(){super(...arguments),this.placeholder="Search\u2026",this.isOpen=!1,this.results=[],this.loading=!1,this.query="",this.activeIndex=-1,this.vellumRef=u(),this.inputRef=u(),this.resultsRef=u(),this.idPrefix=`esp-search-${this.correlationId}`,this._overlay=new I({host:this,getFocusTrapContainer:()=>this.vellumRef.value??null,getFocusFallback:()=>this.inputRef.value??null})}show(){this.isOpen||(this.isOpen=!0,this._overlay.open(),this.updateComplete.then(()=>{this.inputRef.value?.focus()}))}hide(){this.isOpen&&(this.isOpen=!1,this.query="",this.results=[],this.activeIndex=-1,this.loading=!1,this._overlay.close(),this.dispatchEvent(new CustomEvent(m.SEARCH_CLOSED,{detail:{},bubbles:!0,composed:!0})))}setResults(e){this.results=e,this.activeIndex=e.length>0?0:-1}setLoading(e){this.loading=e}handleInput(e){const t=e.target.value;this.query=t,this.activeIndex=-1,this.dispatchEvent(new CustomEvent(m.SEARCH_REQUESTED,{detail:{query:t},bubbles:!0,composed:!0})),t.trim()||(this.results=[])}selectResult(e){this.dispatchEvent(new CustomEvent(m.SEARCH_RESULT_SELECTED,{detail:{url:e.url},bubbles:!0,composed:!0})),this.hide()}handleKeyDown(e){if(this.isOpen)switch(e.key){case"Escape":e.preventDefault(),this.hide();break;case"ArrowDown":e.preventDefault(),this.results.length>0&&(this.activeIndex=Math.min(this.activeIndex+1,this.results.length-1),this.scrollActiveIntoView());break;case"ArrowUp":e.preventDefault(),this.results.length>0&&(this.activeIndex=Math.max(this.activeIndex-1,0),this.scrollActiveIntoView());break;case"Enter":e.preventDefault(),this.activeIndex>=0&&this.activeIndex<this.results.length&&this.selectResult(this.results[this.activeIndex]);break;case"Tab":this._overlay.trapFocus(e);break}}handleBackdropClick(e){e.target===this.vellumRef.value&&this.hide()}scrollActiveIntoView(){this.updateComplete.then(()=>{const e=this.resultsRef.value?.querySelectorAll(".result");e&&this.activeIndex>=0&&e[this.activeIndex]&&e[this.activeIndex].scrollIntoView({block:"nearest"})})}get hasListbox(){return this.results.length>0}get listboxId(){return`${this.idPrefix}-listbox`}optionId(e){return`${this.idPrefix}-option-${e}`}render(){return l`
1
+ var o=function(a,e,t,c){var h=arguments.length,r=h<3?e:c===null?c=Object.getOwnPropertyDescriptor(e,t):c,p;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(a,e,t,c);else for(var d=a.length-1;d>=0;d--)(p=a[d])&&(r=(h<3?p(r):h>3?p(e,t,r):p(e,t))||r);return h>3&&r&&Object.defineProperty(e,t,r),r};import{css as y,html as l,nothing as i}from"lit";import{customElement as k,property as w,state as n}from"lit/decorators.js";import{classMap as m}from"lit/directives/class-map.js";import{createRef as u,ref as v}from"lit/directives/ref.js";import{unsafeHTML as E}from"lit/directives/unsafe-html.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{OverlayController as I}from"../shared/overlay-controller.js";import{ESP_EVENTS as f}from"../shared/events.js";import{srOnly as R}from"../shared/style-fragments.js";const g="%%ESP_MARK_OPEN%%",x="%%ESP_MARK_CLOSE%%";function $(a){return a.replace(/<mark>/gi,g).replace(/<\/mark>/gi,x).replace(/<[^>]*>/g,"").replaceAll(g,"<mark>").replaceAll(x,"</mark>")}let s=class extends b{constructor(){super(...arguments),this.placeholder="Search\u2026",this.isOpen=!1,this.results=[],this.loading=!1,this.query="",this.activeIndex=-1,this.vellumRef=u(),this.inputRef=u(),this.resultsRef=u(),this.idPrefix=`esp-search-${this.correlationId}`,this._overlay=new I({host:this,getFocusTrapContainer:()=>this.vellumRef.value??null,getFocusFallback:()=>this.inputRef.value??null})}show(){this.isOpen||(this.isOpen=!0,this._overlay.open(),this.updateComplete.then(()=>{this.inputRef.value?.focus()}))}hide(){this.isOpen&&(this.isOpen=!1,this.query="",this.results=[],this.activeIndex=-1,this.loading=!1,this._overlay.close(),this.dispatchEvent(new CustomEvent(f.SEARCH_CLOSED,{detail:{},bubbles:!0,composed:!0})))}setResults(e){this.results=e,this.activeIndex=e.length>0?0:-1}setLoading(e){this.loading=e}handleInput(e){const t=e.target.value;this.query=t,this.activeIndex=-1,this.dispatchEvent(new CustomEvent(f.SEARCH_REQUESTED,{detail:{query:t},bubbles:!0,composed:!0})),t.trim()||(this.results=[])}selectResult(e){this.dispatchEvent(new CustomEvent(f.SEARCH_RESULT_SELECTED,{detail:{url:e.url},bubbles:!0,composed:!0})),this.hide()}handleKeyDown(e){if(this.isOpen)switch(e.key){case"Escape":e.preventDefault(),this.hide();break;case"ArrowDown":e.preventDefault(),this.results.length>0&&(this.activeIndex=Math.min(this.activeIndex+1,this.results.length-1),this.scrollActiveIntoView());break;case"ArrowUp":e.preventDefault(),this.results.length>0&&(this.activeIndex=Math.max(this.activeIndex-1,0),this.scrollActiveIntoView());break;case"Enter":e.preventDefault(),this.activeIndex>=0&&this.activeIndex<this.results.length&&this.selectResult(this.results[this.activeIndex]);break;case"Tab":this._overlay.trapFocus(e);break}}handleBackdropClick(e){e.target===this.vellumRef.value&&this.hide()}scrollActiveIntoView(){this.updateComplete.then(()=>{const e=this.resultsRef.value?.querySelectorAll(".result");e&&this.activeIndex>=0&&e[this.activeIndex]&&e[this.activeIndex].scrollIntoView({block:"nearest"})})}get hasListbox(){return this.results.length>0}get listboxId(){return`${this.idPrefix}-listbox`}optionId(e){return`${this.idPrefix}-option-${e}`}render(){return l`
2
2
  <div
3
3
  ${v(this.vellumRef)}
4
- class=${f({vellum:!0,"is-open":this.isOpen})}
4
+ class=${m({vellum:!0,"is-open":this.isOpen})}
5
5
  role=${this.isOpen?"dialog":i}
6
6
  aria-modal=${this.isOpen?"true":i}
7
7
  aria-label="Search"
@@ -42,7 +42,7 @@ var o=function(a,e,t,c){var h=arguments.length,r=h<3?e:c===null?c=Object.getOwnP
42
42
  ${this.results.map((e,t)=>l`
43
43
  <li
44
44
  id=${this.optionId(t)}
45
- class=${f({result:!0,active:t===this.activeIndex})}
45
+ class=${m({result:!0,active:t===this.activeIndex})}
46
46
  role="option"
47
47
  aria-selected=${t===this.activeIndex}
48
48
  @click=${()=>this.selectResult(e)}
@@ -182,7 +182,13 @@ var o=function(a,e,t,c){var h=arguments.length,r=h<3?e:c===null?c=Object.getOwnP
182
182
  .result-title {
183
183
  display: block;
184
184
  font-weight: 600;
185
- font-family: var(--esp-font-headings, inherit);
185
+ font-family: var(
186
+ --_esp-font-headings-effective,
187
+ var(
188
+ --esp-font-headings,
189
+ var(--_esp-font-body-effective, var(--esp-font-body, var(--_esp-font-body-fallback)))
190
+ )
191
+ );
186
192
  color: var(--esp-search-title-color, var(--esp-color-headings));
187
193
  }
188
194
 
@@ -1,6 +1,10 @@
1
- var c=function(u,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(u,e,t,r);else for(var i=u.length-1;i>=0;i--)(a=u[i])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as C}from"lit";import{property as d,state as S}from"lit/decorators.js";import{subscribeToRootEvent as p}from"./root-event-subscription.js";import{traverseToClosest as m}from"./utilities.js";import{parseCssColor as w,serializeOklch as P,gamutMapToSRGB as x}from"./color-engine.js";import{computeVariants as b}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as v}from"../root/helpers/compute-semantic-properties.js";import{DocumentSpriteController as E}from"./document-sprite.js";import{dataCompanionProperties as V}from"../root/helpers/data-companion-properties.js";import{dataSeriesProperties as U}from"../root/helpers/compute-theme-properties.js";import{lightnessRampProperties as I}from"../root/helpers/lightness-ramp-properties.js";import{ELEVATION_PROPERTIES as O,TYPE_ROLE_COLOR_PROPERTIES as A}from"./scale-engine.js";import{resolveContextTheme as y,resolveDataColorSource as D,semanticToCSS as z}from"./theme.js";import{alignAttributeTextInheritance as N,focusRing as F}from"./style-fragments.js";import{syncNormalizedAttribute as _}from"./attribute-helpers.js";import{INTENT_VARIANTS as k,normalizeIntentVariant as j}from"./intent-values.js";import{ESP_EVENTS as B}from"./events.js";class n extends C{get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const r=()=>{const o=e();return o?(o.focus(t),!0):!1};r()||this.updateComplete.then(()=>{r()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent(B.VALUE_CHANGED,{detail:e,bubbles:!0,composed:!0}))}get intent(){return this.intentBacker}set intent(e){const t=typeof e=="string"?e.trim():"";t!==""&&!k.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${k.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=j(e);_(this,"intent",o),o!==r&&(this.intentBacker=o,this.requestUpdate("intent",r),this.applyTokensWhenRootReady())}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady(),this.refreshDescendantIntentDerivations())}refreshDescendantIntentDerivations(){const e=new Set,t=o=>{for(const s of Array.from(o.children))r(s)},r=o=>{if(!e.has(o)){if(e.add(o),o instanceof n&&o.applyTokensWhenRootReady(),o.shadowRoot&&t(o.shadowRoot),o instanceof HTMLSlotElement)for(const s of o.assignedElements({flatten:!0}))r(s);t(o)}};t(this),this.shadowRoot&&t(this.shadowRoot)}static flattenedParent(e){return e instanceof Element&&e.assignedSlot?e.assignedSlot:e instanceof ShadowRoot?e.host:e.parentNode}resolveAncestorZoneTheme(e){let t=n.flattenedParent(this);for(;t;){if(t instanceof Element&&t.localName==="esp-root")return null;if(t instanceof n){const r=t.contextBacker.trim();if(r){const o=this.resolveNamedContextTheme(e,r);if(o)return o}}t=n.flattenedParent(t)}return null}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents(),this.clearScopedTokens(),this.espRoot=null}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=m(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const r=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,r&&this.isConnected&&this.subscribeToRootEvents(t),(r||a||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),r&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyScopedColorTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyScopedColorTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyScopedColorTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[p(e,"seed-color-changed",this.handleSeedColorChanged),p(e,"scheme-changed",this.handleSchemeChanged),p(e,"theme-changed",this.handleThemeChanged),p(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}constructor(){super(),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.intentBacker="neutral",this.intentEmitsTokens=!0,this.warnedUnknownIntents=new Set,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyScopedColorTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyScopedColorTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyScopedColorTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()},new E(this,{reactToSpriteChanges:!1})}traverseToClosest(e){return m(this,e)}applyScopedColorTokens(){if(!this.espRoot)return;const e=this.intentEmitsTokens?n.intentColorSources[this.intentBacker]:"";if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const r=this.resolveContextTheme(t),o=r.theme,s=w(o.seedColor);if(!s)return;const a=b(s,o),i={};if(r.applied&&(Object.assign(i,v(o,a)),Object.assign(i,I(o)),Object.assign(i,O),Object.assign(i,A),Object.assign(i,V(i,U(o,s,l=>(typeof l=="string"?D(l,o.anchors):null)??o.seedColor)))),e){let l=o;r.applied||(l=this.resolveAncestorZoneTheme(t)??o);const g=l===o?a:b(s,l),T=v(l,g,{effectiveSource:(f,h)=>n.semanticActionTokens.has(f)?e:h});i["--esp-color-primary"]=P(x(g[e]));for(const f of n.semanticActionTokens){const h=z(f);i[h]=T[h]}}this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const r=this.resolveNamedContextTheme(e,t);return r?{applied:!0,theme:r}:(this.warnUnknownContextWhenSettled(t),{applied:!1,theme:e})}warnUnknownContextWhenSettled(e){if(this.warnedUnknownContexts.has(e))return;const t=this.espRoot;if(t&&!t.themeSettled){t.whenThemeSettled().then(()=>{if(!this.isConnected||this.espRoot!==t||this.context.trim()!==e)return;const r=t.activeTheme;r&&y(r,e)||this.warnUnknownContextWhenSettled(e)});return}this.warnedUnknownContexts.add(e),console.warn(`Espalier context: "${e}" is not defined by the active theme; inheriting root tokens.`)}resolveNamedContextTheme(e,t){return y(e,t)}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,r]of Object.entries(e))this.setScopedTokenProperty(t,r)}setScopedTokenProperty(e,t){const r=this.scopedTokenOriginalValues.get(e);if(r){const o=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(o!==r.generatedValue||s!==r.generatedPriority)&&(r.originalValue=o.length?o:null,r.originalPriority=s),r.generatedValue=t,r.generatedPriority=""}else{const o=this.style.getPropertyValue(e);this.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;const r=this.style.getPropertyValue(e),o=this.style.getPropertyPriority(e);(r!==t.generatedValue||o!==t.generatedPriority)&&(t.originalValue=r.length?r:null,t.originalPriority=o),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority),this.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}n.intentColorSources={danger:"danger",info:"info",neutral:"",success:"success",warning:"warning"},n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[F(".esp-field:focus-within","--esp-field-focus-shadow"),N,R`
1
+ var c=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnPropertyDescriptor(e,t):r,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,r);else for(var i=f.length-1;i>=0;i--)(a=f[i])&&(s=(o<3?a(s):o>3?a(e,t,s):a(e,t))||s);return o>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as C}from"lit";import{property as d,state as S}from"lit/decorators.js";import{subscribeToRootEvent as p}from"./root-event-subscription.js";import{traverseToClosest as g}from"./utilities.js";import{parseCssColor as w,serializeOklch as P,gamutMapToSRGB as x}from"./color-engine.js";import{computeVariants as v}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as m}from"../root/helpers/compute-semantic-properties.js";import{DocumentSpriteController as E}from"./document-sprite.js";import{dataCompanionProperties as V}from"../root/helpers/data-companion-properties.js";import{dataSeriesProperties as U}from"../root/helpers/compute-theme-properties.js";import{lightnessRampProperties as I}from"../root/helpers/lightness-ramp-properties.js";import{ELEVATION_PROPERTIES as O,TYPE_ROLE_COLOR_PROPERTIES as A}from"./scale-engine.js";import{resolveContextTheme as y,resolveDataColorSource as _,semanticToCSS as D}from"./theme.js";import{alignAttributeTextInheritance as z,focusRing as N}from"./style-fragments.js";import{syncNormalizedAttribute as F}from"./attribute-helpers.js";import{INTENT_VARIANTS as k,normalizeIntentVariant as j}from"./intent-values.js";import{ESP_EVENTS as B}from"./events.js";class n extends C{get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const r=()=>{const o=e();return o?(o.focus(t),!0):!1};r()||this.updateComplete.then(()=>{r()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent(B.VALUE_CHANGED,{detail:e,bubbles:!0,composed:!0}))}get intent(){return this.intentBacker}set intent(e){const t=typeof e=="string"?e.trim():"";t!==""&&!k.includes(t)&&!this.warnedUnknownIntents.has(t)&&(this.warnedUnknownIntents.add(t),console.warn(`Espalier intent: "${t}" is not an intent; expected one of ${k.join(", ")}. Treating it as "neutral".`));const r=this.intentBacker,o=j(e);F(this,"intent",o),o!==r&&(this.intentBacker=o,this.requestUpdate("intent",r),this.applyTokensWhenRootReady())}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady(),this.refreshDescendantIntentDerivations())}refreshDescendantIntentDerivations(){const e=new Set,t=o=>{for(const s of Array.from(o.children))r(s)},r=o=>{if(!e.has(o)){if(e.add(o),o instanceof n&&o.applyTokensWhenRootReady(),o.shadowRoot&&t(o.shadowRoot),o instanceof HTMLSlotElement)for(const s of o.assignedElements({flatten:!0}))r(s);t(o)}};t(this),this.shadowRoot&&t(this.shadowRoot)}static flattenedParent(e){return e instanceof Element&&e.assignedSlot?e.assignedSlot:e instanceof ShadowRoot?e.host:e.parentNode}resolveAncestorZoneTheme(e){let t=n.flattenedParent(this);for(;t;){if(t instanceof Element&&t.localName==="esp-root")return null;if(t instanceof n){const r=t.contextBacker.trim();if(r){const o=this.resolveNamedContextTheme(e,r);if(o)return o}}t=n.flattenedParent(t)}return null}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents(),this.clearScopedTokens(),this.espRoot=null}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=g(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const r=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,r&&this.isConnected&&this.subscribeToRootEvents(t),(r||a||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),r&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyScopedColorTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyScopedColorTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyScopedColorTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[p(e,"seed-color-changed",this.handleSeedColorChanged),p(e,"scheme-changed",this.handleSchemeChanged),p(e,"theme-changed",this.handleThemeChanged),p(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}constructor(){super(),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.intentBacker="neutral",this.intentEmitsTokens=!0,this.warnedUnknownIntents=new Set,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyScopedColorTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyScopedColorTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyScopedColorTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()},new E(this,{reactToSpriteChanges:!1})}traverseToClosest(e){return g(this,e)}applyScopedColorTokens(){if(!this.espRoot)return;const e=this.intentEmitsTokens?n.intentColorSources[this.intentBacker]:"";if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const r=this.resolveContextTheme(t),o=r.theme,s=w(o.seedColor);if(!s)return;const a=v(s,o),i={};if(r.applied&&(Object.assign(i,m(o,a)),Object.assign(i,I(o)),Object.assign(i,O),Object.assign(i,A),Object.assign(i,V(i,U(o,s,l=>(typeof l=="string"?_(l,o.anchors):null)??o.seedColor)))),e){let l=o;r.applied||(l=this.resolveAncestorZoneTheme(t)??o);const b=l===o?a:v(s,l),T=m(l,b,{effectiveSource:(u,h)=>n.semanticActionTokens.has(u)?e:h});i["--esp-color-primary"]=P(x(b[e]));for(const u of n.semanticActionTokens){const h=D(u);i[h]=T[h]}}this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const r=this.resolveNamedContextTheme(e,t);return r?{applied:!0,theme:r}:(this.warnUnknownContextWhenSettled(t),{applied:!1,theme:e})}warnUnknownContextWhenSettled(e){if(this.warnedUnknownContexts.has(e))return;const t=this.espRoot;if(t&&!t.themeSettled){t.whenThemeSettled().then(()=>{if(!this.isConnected||this.espRoot!==t||this.context.trim()!==e)return;const r=t.activeTheme;r&&y(r,e)||this.warnUnknownContextWhenSettled(e)});return}this.warnedUnknownContexts.add(e),console.warn(`Espalier context: "${e}" is not defined by the active theme; inheriting root tokens.`)}resolveNamedContextTheme(e,t){return y(e,t)}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,r]of Object.entries(e))this.setScopedTokenProperty(t,r)}setScopedTokenProperty(e,t){const r=this.scopedTokenOriginalValues.get(e);if(r){const o=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(o!==r.generatedValue||s!==r.generatedPriority)&&(r.originalValue=o.length?o:null,r.originalPriority=s),r.generatedValue=t,r.generatedPriority=""}else{const o=this.style.getPropertyValue(e);this.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;const r=this.style.getPropertyValue(e),o=this.style.getPropertyPriority(e);(r!==t.generatedValue||o!==t.generatedPriority)&&(t.originalValue=r.length?r:null,t.originalPriority=o),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority),this.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}n.intentColorSources={danger:"danger",info:"info",neutral:"",success:"success",warning:"warning"},n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[N(".esp-field:focus-within","--esp-field-focus-shadow"),z,R`
2
2
  :host {
3
3
 
4
+ --_esp-font-body-fallback: system-ui, sans-serif;
5
+ --_esp-font-monospace-fallback: monospace;
6
+
7
+
4
8
  --_esp-field-resolved-hover-bg: var(
5
9
  --esp-field-hover-bg,
6
10
  oklch(from var(--esp-field-background, var(--esp-color-layer-2)) calc(l * 0.88) c h)
@@ -42,7 +46,13 @@ var c=function(u,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
42
46
  h4,
43
47
  h5,
44
48
  h6 {
45
- font-family: var(--esp-font-headings);
49
+ font-family: var(
50
+ --_esp-font-headings-effective,
51
+ var(
52
+ --esp-font-headings,
53
+ var(--_esp-font-body-effective, var(--esp-font-body, var(--_esp-font-body-fallback)))
54
+ )
55
+ );
46
56
  font-weight: var(--esp-font-weight-headings);
47
57
  color: var(--esp-color-headings);
48
58
  }
@@ -58,7 +68,10 @@ var c=function(u,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
58
68
  }
59
69
 
60
70
  .esp-field {
61
- font-family: var(--esp-font-body);
71
+ font-family: var(
72
+ --_esp-font-body-effective,
73
+ var(--esp-font-body, var(--_esp-font-body-fallback))
74
+ );
62
75
  font-size: var(--esp-size-font);
63
76
  font-weight: var(--esp-font-weight-body);
64
77
  background-color: var(--esp-field-background, var(--esp-color-layer-2));
@@ -89,7 +102,10 @@ var c=function(u,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
89
102
  > button,
90
103
  > a {
91
104
  text-decoration: none;
92
- font-family: var(--esp-font-body);
105
+ font-family: var(
106
+ --_esp-font-body-effective,
107
+ var(--esp-font-body, var(--_esp-font-body-fallback))
108
+ );
93
109
  font-size: var(--esp-size-font);
94
110
  width: 100%;
95
111
  color: inherit;
@@ -45,6 +45,8 @@ export declare function extractWeights(font: GoogleFont | null): string[];
45
45
  * @param defaultWeight Fallback when `weight` is falsy.
46
46
  */
47
47
  export declare function normalizeWeight(weight: string | undefined, defaultWeight: string): string;
48
+ /** Normalize a face weight to the numeric range accepted by Google Fonts and font plans. */
49
+ export declare function normalizeFontFaceWeight(weight: string | number | undefined, defaultWeight?: string | number): number | null;
48
50
  /**
49
51
  * Find the closest available weight to a desired one.
50
52
  *
@@ -73,6 +75,8 @@ export declare function bestAvailableWeight(desired: string, available: string[]
73
75
  * ```
74
76
  */
75
77
  export declare function extractFamily(cssFamily: string): string;
78
+ /** Whether a first-family name is a generic, platform, or conventional web-safe local face. */
79
+ export declare function isLocalFontFamily(family: string): boolean;
76
80
  /**
77
81
  * Return the generic CSS fallback for a Google Font category.
78
82
  *
@@ -83,3 +87,25 @@ export declare function extractFamily(cssFamily: string): string;
83
87
  * `"sans-serif"`
84
88
  */
85
89
  export declare function getFallbackFont(category: string): string;
90
+ export declare const RUNTIME_GOOGLE_FONT_OWNER_ATTR = "data-esp-google-font-owner";
91
+ export type RuntimeGoogleFontLinkOptions = {
92
+ /** Stable owner key, for example `root:<id>:body` or `picker:<id>:Roboto`. */
93
+ owner: string;
94
+ family: string;
95
+ weight?: string;
96
+ enabled?: boolean;
97
+ /** Compatibility/debug attributes retained on the generated link. */
98
+ attributes?: Readonly<Record<string, string>>;
99
+ };
100
+ /** Build the canonical Google Fonts CSS2 URL used by roots and pickers. */
101
+ export declare function googleFontStylesheetUrl(family: string, weight?: string): string;
102
+ /**
103
+ * Create, update, or remove one document-global Google Fonts stylesheet link.
104
+ * The caller owns only its stable key, so unrelated roots and picker instances
105
+ * cannot replace or clean up one another's links.
106
+ */
107
+ export declare function syncRuntimeGoogleFontLink(options: RuntimeGoogleFontLinkOptions): HTMLLinkElement | null;
108
+ /** Remove one shared runtime font link by its exact owner key. */
109
+ export declare function removeRuntimeGoogleFontLink(owner: string): void;
110
+ /** Remove all shared runtime font links whose owner begins with `ownerPrefix`. */
111
+ export declare function removeRuntimeGoogleFontLinks(ownerPrefix: string): void;
@@ -1 +1 @@
1
- const u={100:"100 Thin",200:"200 Extra Light",300:"300 Light",400:"400 Regular",500:"500 Medium",600:"600 Semi Bold",700:"700 Bold",800:"800 Extra Bold",900:"900 Black"};function c(t){if(!t)return["400"];const r=new Set;for(const e of t.variants)e.includes("italic")||r.add(e==="regular"?"400":e);const n=[...r].sort((e,o)=>Number(e)-Number(o));return n.length>0?n:["400"]}function a(t,r){return t?t==="bold"?"700":t==="normal"?"400":t:r}function f(t,r){if(r.length===0)return"400";if(r.includes(t))return t;const n=Number(t);let e=r[0],o=Math.abs(Number(e)-n);for(const i of r){const s=Math.abs(Number(i)-n);s<o&&(e=i,o=s)}return e}function l(t){return t.split(",")[0].replace(/["']/g,"").trim()}function m(t){switch(t){case"serif":return"serif";case"monospace":return"monospace";case"handwriting":return"cursive";default:return"sans-serif"}}export{u as WEIGHT_LABELS,f as bestAvailableWeight,l as extractFamily,c as extractWeights,m as getFallbackFont,a as normalizeWeight};
1
+ const m={100:"100 Thin",200:"200 Extra Light",300:"300 Light",400:"400 Regular",500:"500 Medium",600:"600 Semi Bold",700:"700 Bold",800:"800 Extra Bold",900:"900 Black"};function d(e){if(!e)return["400"];const t=new Set;for(const r of e.variants)r.includes("italic")||t.add(r==="regular"?"400":r);const n=[...t].sort((r,o)=>Number(r)-Number(o));return n.length>0?n:["400"]}function h(e,t){return e?e==="bold"?"700":e==="normal"?"400":e:t}function u(e,t){const n=e===void 0||e===""?t:e;if(n===void 0)return null;if(typeof n=="number")return Number.isInteger(n)&&n>=1&&n<=1e3?n:null;const r=n.trim().toLowerCase();if(r==="normal")return 400;if(r==="bold")return 700;if(!/^\d{1,4}$/.test(r))return null;const o=Number(r);return Number.isInteger(o)&&o>=1&&o<=1e3?o:null}function g(e,t){if(t.length===0)return"400";if(t.includes(e))return e;const n=Number(e);let r=t[0],o=Math.abs(Number(r)-n);for(const s of t){const i=Math.abs(Number(s)-n);i<o&&(r=s,o=i)}return r}function p(e){let t="",n="",r=!1,o=0;for(const i of e.trim()){if(r){t+=i,r=!1;continue}if(i==="\\"){t+=i,r=!0;continue}if(n){t+=i,i===n&&(n="");continue}if(i==='"'||i==="'"){t+=i,n=i;continue}if(i==="("&&(o+=1),i===")"&&(o=Math.max(0,o-1)),i===","&&o===0)break;t+=i}const s=t.trim();return s.length>=2&&(s.startsWith('"')&&s.endsWith('"')||s.startsWith("'")&&s.endsWith("'"))?s.slice(1,-1).replace(/\\([\\"'])/g,"$1"):s}const l=new Set(["serif","sans-serif","monospace","cursive","fantasy","system-ui","ui-serif","ui-sans-serif","ui-monospace","ui-rounded","math","fangsong","-apple-system","blinkmacsystemfont","arial","helvetica","helvetica neue","liberation sans","verdana","tahoma","trebuchet ms","georgia","times new roman","courier new","segoe ui"].map(e=>e.toLowerCase()));function b(e){return l.has(e.trim().toLowerCase())}function x(e){switch(e){case"serif":return"serif";case"monospace":return"monospace";case"handwriting":return"cursive";default:return"sans-serif"}}const a="data-esp-google-font-owner";function f(e,t){const n=u(t,400)??400,r=n!==400?`:wght@${n}`:"";return`https://fonts.googleapis.com/css2?family=${encodeURIComponent(e)}${r}&display=swap`}function c(e){return document.head.querySelector(`link[${a}="${CSS.escape(e)}"]`)}function y(e){const t=c(e.owner),n=e.family.trim(),r=String(u(e.weight,400)??400);if(e.enabled===!1||!n)return t?.remove(),null;if(t?.dataset.espFamily===n&&t.dataset.espWeight===r)return t;t?.remove();const o=document.createElement("link");o.rel="stylesheet",o.href=f(n,r),o.setAttribute(a,e.owner),o.dataset.espFamily=n,o.dataset.espWeight=r;for(const[s,i]of Object.entries(e.attributes??{}))o.setAttribute(s,i);return document.head.appendChild(o),o}function F(e){c(e)?.remove()}function L(e){for(const t of document.head.querySelectorAll(`link[${a}]`))t.getAttribute(a)?.startsWith(e)&&t.remove()}export{a as RUNTIME_GOOGLE_FONT_OWNER_ATTR,m as WEIGHT_LABELS,g as bestAvailableWeight,p as extractFamily,d as extractWeights,x as getFallbackFont,f as googleFontStylesheetUrl,b as isLocalFontFamily,u as normalizeFontFaceWeight,h as normalizeWeight,F as removeRuntimeGoogleFontLink,L as removeRuntimeGoogleFontLinks,y as syncRuntimeGoogleFontLink};
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Dependency-free compiler for first-paint, site-specific font plans.
3
+ *
4
+ * Hosts load the checked-in fallback profile catalog at build time, collect
5
+ * the exact requested faces, resolve only those WOFF2 sources, and embed the
6
+ * resulting CSS in the document head before `<esp-root>` can paint.
7
+ */
8
+ import type { EspalierTheme } from "./theme.js";
9
+ export type FontPlanTheme = Pick<EspalierTheme, "fontBody" | "fontHeadings" | "fontBrand" | "fontMonospace" | "fontWeightBody" | "fontWeightHeadings" | "fontWeightBrand" | "fontWeightMonospace">;
10
+ export type FontPlanSlot = "body" | "headings" | "brand" | "monospace";
11
+ export type FontPlanScheme = "light" | "dark";
12
+ export type FontPlanStyle = "normal" | "italic";
13
+ export type FontFaceRequest = {
14
+ key: string;
15
+ family: string;
16
+ weight: number;
17
+ style: FontPlanStyle;
18
+ };
19
+ export type ResolvedFontSource = {
20
+ /** Absolute or root-relative URL for one WOFF2 face or subset. */
21
+ url: string;
22
+ /** Optional CSS unicode-range for this source's subset. */
23
+ unicodeRange?: string;
24
+ };
25
+ export type FontFallbackProfile = readonly [
26
+ fallbackIndex: number,
27
+ fallbackVariant: string,
28
+ sizeAdjust: number | null,
29
+ ascentOverride: number | null,
30
+ descentOverride: number | null,
31
+ lineGapOverride: number | null
32
+ ];
33
+ export type FontFallbackCatalog = {
34
+ version: 1;
35
+ metadata: {
36
+ subset: string;
37
+ percentScale: number;
38
+ familyCount: number;
39
+ variantCount: number;
40
+ [key: string]: unknown;
41
+ };
42
+ bases: ReadonlyArray<readonly [family: string, variants: Readonly<Record<string, readonly string[]>>]>;
43
+ profiles: Readonly<Record<string, Readonly<Record<string, readonly FontFallbackProfile[]>>>>;
44
+ };
45
+ export type FontPlanProfileMiss = {
46
+ family: string;
47
+ weight: number | null;
48
+ style: FontPlanStyle;
49
+ schemes: FontPlanScheme[];
50
+ slots: FontPlanSlot[];
51
+ };
52
+ export type CompileFontPlanOptions = {
53
+ lightTheme: FontPlanTheme;
54
+ darkTheme: FontPlanTheme;
55
+ catalog: FontFallbackCatalog;
56
+ /** Sources keyed with {@link fontFaceRequestKey}. Unselected keys are ignored. */
57
+ sources?: Readonly<Record<string, ResolvedFontSource | readonly ResolvedFontSource[]>>;
58
+ /** Optional unique root id selector, for example `#site-shell`. Defaults to every `esp-root`. */
59
+ rootSelector?: string;
60
+ };
61
+ export type CompiledFontPlan = {
62
+ /** Minified CSS suitable for the existing inline page-head style block. */
63
+ css: string;
64
+ /** Exact, deduplicated faces that the host must resolve. */
65
+ requests: FontFaceRequest[];
66
+ /** Requested faces for which no source was supplied. */
67
+ missingSources: FontFaceRequest[];
68
+ /** Catalog families that lacked the requested weight/style profile. */
69
+ missingProfiles: FontPlanProfileMiss[];
70
+ /** Scheme/slot stacks represented by the emitted private effective tokens. */
71
+ effectiveStacks: Record<FontPlanScheme, Record<FontPlanSlot, string>>;
72
+ /** UTF-8 byte size of `css`, convenient for static-site budget checks. */
73
+ byteLength: number;
74
+ };
75
+ /** Return the stable source-map key for a requested target face. */
76
+ export declare function fontFaceRequestKey(family: string, weight: number, style?: FontPlanStyle): string;
77
+ /** Return the fallback base indexes used for one Google Fonts category. */
78
+ export declare function fontFallbackBaseIndexes(category: string): readonly number[];
79
+ /**
80
+ * Return the deterministic profile aliases a runtime font stack may reference
81
+ * without loading the build-time profile catalog in the browser.
82
+ */
83
+ export declare function fontFallbackAliases(family: string, weight: string | number, category: string, style?: FontPlanStyle): string[];
84
+ /**
85
+ * Compile a complete, first-paint font plan from two resolved themes.
86
+ *
87
+ * Call once without `sources` to discover `requests`, resolve those assets in
88
+ * the host build, then call again with the keyed source map for final CSS.
89
+ */
90
+ export declare function compileFontPlan(options: CompileFontPlanOptions): CompiledFontPlan;
@@ -0,0 +1,5 @@
1
+ import{extractFamily as R,normalizeFontFaceWeight as A}from"./font-helpers.js";const N="U+0000-024F,U+1E00-1EFF,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD",F=["body","headings","brand","monospace"],z={"sans-serif":[0,1],display:[0,1],handwriting:[0,1],"not-display":[0,1],serif:[2],monospace:[3]};function b(t){let e="";for(const n of t){const s=n.codePointAt(0)??0;n==="\\"?e+="\\\\":n==='"'?e+='\\"':n==="<"?e+="\\3c ":s<=31||s===127?e+=`\\${s.toString(16)} `:e+=n}return`"${e}"`}function I(t){return`url(${b(t)}) format("woff2")`}function U(t){for(const o of t){const y=o.codePointAt(0)??0;if(o===";"||o==="{"||o==="}"||o==="<"||y<=31||y===127)throw new Error("Font stack contains characters that cannot be embedded in inline CSS")}if(t.includes("/*")||t.includes("*/"))throw new Error("Font stack contains characters that cannot be embedded in inline CSS");const e=[];let n="",s="",r=!1,a=0;for(const o of t){if(r){n+=o,r=!1;continue}if(o==="\\"){n+=o,r=!0;continue}if(s){n+=o,o===s&&(s="");continue}if(o==='"'||o==="'"){n+=o,s=o;continue}if(o==="("&&(a+=1),o===")"&&(a=Math.max(0,a-1)),o===","&&a===0){n.trim()&&e.push(n.trim()),n="";continue}n+=o}if(r||s||a!==0)throw new Error("Font stack contains an unterminated escape, quote, or function");return n.trim()&&e.push(n.trim()),e}function W(t){return A(t)}function _(t,e){return`${t}${e==="italic"?"i":""}`}function x(t,e,n="normal"){return`${encodeURIComponent(t)}~${e}~${n==="italic"?"i":"n"}`}function j(t,e){return t.family.localeCompare(e.family,"en")||t.weight-e.weight||t.style.localeCompare(e.style,"en")}function q(t,e){let n=2166136261;for(const s of`${t}:${e}`)n^=s.charCodeAt(0),n=Math.imul(n,16777619);return`ef${(n>>>0).toString(36)}`}function B(t){return z[t]??[]}function H(t,e,n,s="normal"){const r=A(e);if(!t.trim()||r===null)return[];const a=x(t.trim(),r,s);return B(n).map(o=>q(a,o))}function O(t,e){if(!Number.isInteger(t)||t<0||!Number.isInteger(e)||e<=0)throw new Error("Font fallback catalog contains an invalid encoded percentage");const n=Math.floor(t/e),s=String(t%e).padStart(String(e).length-1,"0").replace(/0+$/,"");return`${n}${s?`.${s}`:""}%`}function k(t,e,n,s){n!==null&&t.push(`${e}:${O(n,s)};`)}function P(t,e){const n=U(t);return n.length===0||e.length===0?t:[n[0],...e,...n.slice(1)].join(",")}function M(t){const e=t.fontBody,n=t.fontHeadings||e,s=t.fontBrand||n,r=t.fontMonospace;return{body:[e,t.fontWeightBody],headings:[n,t.fontWeightHeadings],brand:[s,t.fontWeightBrand],monospace:[r,t.fontWeightMonospace]}}function C(t,e,n,s,r){const a={},o={},y=M(e);for(const l of F){const[f,$]=y[l];a[l]=f,U(f);const u=R(f),i=n.profiles[u];if(!i)continue;const d=W($);if(d===null){const w=`${u}
2
+ ${$}
3
+ normal`,p=r.get(w)??{family:u,weight:null,style:"normal",schemes:[],slots:[]};p.schemes.includes(t)||p.schemes.push(t),p.slots.includes(l)||p.slots.push(l),r.set(w,p);continue}const c="normal",m=i[_(d,c)];if(!m){const w=`${u}
4
+ ${d}
5
+ ${c}`,p=r.get(w)??{family:u,weight:d,style:c,schemes:[],slots:[]};p.schemes.includes(t)||p.schemes.push(t),p.slots.includes(l)||p.slots.push(l),r.set(w,p);continue}const h=x(u,d,c),g=s.get(h)??{request:{key:h,family:u,weight:d,style:c},profile:m,schemes:new Set,slots:new Set};g.schemes.add(t),g.slots.add(l),s.set(h,g),o[l]=g}return{stacks:a,uses:o}}function T(t){const e=t.trim();if(!/^U\+[0-9A-F?]{1,6}(?:-[0-9A-F]{1,6})?(?:\s*,\s*U\+[0-9A-F?]{1,6}(?:-[0-9A-F]{1,6})?)*$/i.test(e))throw new Error(`Invalid font source unicode-range "${t}"`);return e.replace(/\s+/g,"")}function L(t){return t?Array.isArray(t)?t:[t]:[]}function D(t,e){return e.map(n=>{if(!n.url.trim())throw new Error(`Empty WOFF2 source for ${t.key}`);const s=n.unicodeRange?`unicode-range:${T(n.unicodeRange)};`:"";return`@font-face{font-family:${b(t.family)};src:${I(n.url)};font-style:${t.style};font-weight:${t.weight};font-display:swap;${s}}`}).join("")}function G(t,e,n){const[s,r,a,o,y,l]=e,f=n.bases[s],$=f?.[1]?.[r];if(!f||!$||$.length===0)throw new Error(`Font fallback catalog is missing base ${s} ${r}`);const u=q(t.key,s),i=[`@font-face{font-family:${u};src:${$.map(d=>`local(${b(d)})`).join(",")};`,`font-style:${t.style};font-weight:${t.weight};`];return k(i,"size-adjust",a,n.metadata.percentScale),k(i,"ascent-override",o,n.metadata.percentScale),k(i,"descent-override",y,n.metadata.percentScale),k(i,"line-gap-override",l,n.metadata.percentScale),i.push(`unicode-range:${N};}`),{alias:u,css:i.join("")}}function E(t,e){const n=F.map(s=>`--_esp-font-${s}-effective:${e[s]};`).join("");return`${t}{${n}}`}function K(t){if(t===void 0||t.trim()==="")return"esp-root";const e=t.trim();if(!/^#[A-Za-z_][A-Za-z0-9_-]*$/.test(e))throw new Error('rootSelector must be a unique id selector such as "#site-shell"');return e}function J(t){const{catalog:e}=t;if(e.version!==1||e.metadata?.subset!=="latin"||!/^10+$/.test(String(e.metadata?.percentScale)))throw new Error(`Unsupported font fallback catalog metadata: version ${String(e.version)}, subset ${String(e.metadata?.subset)}, percentScale ${String(e.metadata?.percentScale)}`);const n=new Map,s=K(t.rootSelector),r=new Map,a={light:C("light",t.lightTheme,e,n,r),dark:C("dark",t.darkTheme,e,n,r)},o=[...n.values()].sort((c,m)=>j(c.request,m.request)),y=o.map(({request:c})=>c),l=[],f=[],$=new Map,u=new Map;for(const c of o){const m=L(t.sources?.[c.request.key]);m.length===0?l.push(c.request):f.push(D(c.request,m));const h=[];for(const S of c.profile){const g=G(c.request,S,e),w=u.get(g.alias);if(w&&w!==`${c.request.key}:${S[0]}`)throw new Error(`Generated fallback family collision for ${g.alias}`);u.set(g.alias,`${c.request.key}:${S[0]}`),h.push(g.alias),f.push(g.css)}$.set(c.request.key,h)}const i={light:{},dark:{}};for(const c of["light","dark"]){const m=a[c];for(const h of F){const S=m.uses[h];i[c][h]=S?P(m.stacks[h],$.get(S.request.key)??[]):m.stacks[h]}}f.push(E(s,i.light)),JSON.stringify(i.dark)!==JSON.stringify(i.light)&&(f.push(E(`${s}[scheme=dark],${s}[default-scheme=dark]:not([scheme])`,i.dark)),f.push(`@media(prefers-color-scheme:dark){${E(`${s}[default-scheme=system]:not([scheme])`,i.dark)}}`));const d=f.join("");return{css:d,requests:y,missingSources:l,missingProfiles:[...r.values()],effectiveStacks:i,byteLength:new TextEncoder().encode(d).byteLength}}export{J as compileFontPlan,x as fontFaceRequestKey,H as fontFallbackAliases,B as fontFallbackBaseIndexes};
@@ -1 +1 @@
1
- const l=["tiny","small","normal","medium","big","large","huge"],O=2,b=1.125,f=1.3333333333333333,h=[["tiny","small"],["small","normal"],["normal","medium"],["medium","big"],["big","large"],["large","huge"]],u=.375,z={rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200};function c(s,e=4){const t=10**e;return Math.round(s*t)/t}function m(s,e,t,p,o){if(Math.abs(e-s)<1e-4)return`${c(s)}rem`;const y=(e-s)*t*100/(o-p),n=s-y*p/(100*t);return`clamp(${c(s)}rem, ${c(n)}rem + ${c(y)}vw, ${c(e)}rem)`}function E(s){const e={};for(let t=0;t<l.length;t++){const p=t-2,o=1.125*s.typeRatio**p;e[l[t]]={min:o,max:o*f}}return e}function x(s){const e={};for(let t=0;t<l.length;t++){const p=u*s.spaceRatio**t;e[l[t]]={min:p,max:p*f}}return e}const w={"--esp-shadow-1":"1px 1px 4px var(--esp-color-shadow)","--esp-shadow-2":"0 2px 8px var(--esp-color-shadow)","--esp-shadow-3":"0 6px 20px var(--esp-color-shadow)"},S={"--esp-type-overline-color":"var(--esp-color-type-overline, var(--esp-color-text))","--esp-type-label-color":"var(--esp-color-type-label, var(--esp-color-text))","--esp-type-lead-color":"var(--esp-color-type-lead, var(--esp-color-text))","--esp-type-caption-color":"var(--esp-color-type-caption, var(--esp-color-text))","--esp-type-display-color":"var(--esp-color-headings, var(--esp-color-text))"},_={"--esp-type-overline-font-size":"var(--esp-type-tiny)","--esp-type-overline-font-weight":"var(--esp-font-weight-headings)","--esp-type-overline-letter-spacing":"0.08em","--esp-type-overline-text-transform":"uppercase","--esp-type-label-font-size":"var(--esp-type-normal)","--esp-type-label-font-weight":"var(--esp-font-weight-headings)","--esp-type-label-letter-spacing":"0.01em","--esp-type-lead-font-size":"var(--esp-type-medium)","--esp-type-lead-font-weight":"var(--esp-font-weight-body)","--esp-type-lead-letter-spacing":"normal","--esp-type-caption-font-size":"var(--esp-type-small)","--esp-type-caption-font-weight":"var(--esp-font-weight-body)","--esp-type-caption-letter-spacing":"normal","--esp-type-display-font-family":"var(--esp-font-headings)","--esp-type-display-font-weight":"var(--esp-font-weight-headings)","--esp-type-display-line-height":"1.1","--esp-type-display-letter-spacing":"normal",...S};function P(s){const e={},{rootFontSize:t,viewportMin:p,viewportMax:o,borderRadius:y}=s,n=16,r=t/n,d=E(s);for(const a of l){const{min:i,max:v}=d[a];e[`--esp-type-${a}`]=m(i*r,v*r,n,p,o)}e["--esp-type-display-font-size"]=m(d.large.min*r,d.huge.max*r,n,p,o),Object.assign(e,_);const g=x(s);for(const a of l){const{min:i,max:v}=g[a];e[`--esp-size-${a}`]=m(i*r,v*r,n,p,o)}for(const[a,i]of h)e[`--esp-size-${a}-to-${i}`]=m(g[a].min*r,g[i].max*r,n,p,o);return e["--esp-size-font"]="var(--esp-type-normal)",e["--esp-size-padding"]="var(--esp-size-tiny-to-small)",e["--esp-size-padding-page"]="var(--esp-size-small-to-normal)",e["--esp-size-border-radius"]=`${c(y*r)}rem`,e["--esp-measure"]="66ch",e["--esp-measure-wide"]="90ch",e["--esp-size-section"]="clamp(var(--esp-size-big), 7vw, var(--esp-size-huge))",Object.assign(e,w),e["--esp-card-min"]="16rem",e}export{z as DEFAULT_SCALE_CONFIG,w as ELEVATION_PROPERTIES,l as STEP_NAMES,S as TYPE_ROLE_COLOR_PROPERTIES,_ as TYPE_ROLE_PROPERTIES,P as generateScaleProperties};
1
+ const l=["tiny","small","normal","medium","big","large","huge"],b=2,O=1.125,g=1.3333333333333333,h=[["tiny","small"],["small","normal"],["normal","medium"],["medium","big"],["big","large"],["large","huge"]],u=.375,z={rootFontSize:16,typeRatio:1.25,spaceRatio:1.618,borderRadius:.2,viewportMin:320,viewportMax:1200};function c(s,e=4){const t=10**e;return Math.round(s*t)/t}function d(s,e,t,o,p){if(Math.abs(e-s)<1e-4)return`${c(s)}rem`;const y=(e-s)*t*100/(p-o),n=s-y*o/(100*t);return`clamp(${c(s)}rem, ${c(n)}rem + ${c(y)}vw, ${c(e)}rem)`}function E(s){const e={};for(let t=0;t<l.length;t++){const o=t-2,p=1.125*s.typeRatio**o;e[l[t]]={min:p,max:p*g}}return e}function x(s){const e={};for(let t=0;t<l.length;t++){const o=u*s.spaceRatio**t;e[l[t]]={min:o,max:o*g}}return e}const _={"--esp-shadow-1":"1px 1px 4px var(--esp-color-shadow)","--esp-shadow-2":"0 2px 8px var(--esp-color-shadow)","--esp-shadow-3":"0 6px 20px var(--esp-color-shadow)"},w={"--esp-type-overline-color":"var(--esp-color-type-overline, var(--esp-color-text))","--esp-type-label-color":"var(--esp-color-type-label, var(--esp-color-text))","--esp-type-lead-color":"var(--esp-color-type-lead, var(--esp-color-text))","--esp-type-caption-color":"var(--esp-color-type-caption, var(--esp-color-text))","--esp-type-display-color":"var(--esp-color-headings, var(--esp-color-text))"},S={"--esp-type-overline-font-size":"var(--esp-type-tiny)","--esp-type-overline-font-weight":"var(--esp-font-weight-headings)","--esp-type-overline-letter-spacing":"0.08em","--esp-type-overline-text-transform":"uppercase","--esp-type-label-font-size":"var(--esp-type-normal)","--esp-type-label-font-weight":"var(--esp-font-weight-headings)","--esp-type-label-letter-spacing":"0.01em","--esp-type-lead-font-size":"var(--esp-type-medium)","--esp-type-lead-font-weight":"var(--esp-font-weight-body)","--esp-type-lead-letter-spacing":"normal","--esp-type-caption-font-size":"var(--esp-type-small)","--esp-type-caption-font-weight":"var(--esp-font-weight-body)","--esp-type-caption-letter-spacing":"normal","--esp-type-display-font-family":"var(--_esp-font-headings-effective, var(--esp-font-headings, var(--_esp-font-body-effective, var(--esp-font-body, system-ui, sans-serif))))","--esp-type-display-font-weight":"var(--esp-font-weight-headings)","--esp-type-display-line-height":"1.1","--esp-type-display-letter-spacing":"normal",...w};function P(s){const e={},{rootFontSize:t,viewportMin:o,viewportMax:p,borderRadius:y}=s,n=16,r=t/n,m=E(s);for(const a of l){const{min:i,max:f}=m[a];e[`--esp-type-${a}`]=d(i*r,f*r,n,o,p)}e["--esp-type-display-font-size"]=d(m.large.min*r,m.huge.max*r,n,o,p),Object.assign(e,S);const v=x(s);for(const a of l){const{min:i,max:f}=v[a];e[`--esp-size-${a}`]=d(i*r,f*r,n,o,p)}for(const[a,i]of h)e[`--esp-size-${a}-to-${i}`]=d(v[a].min*r,v[i].max*r,n,o,p);return e["--esp-size-font"]="var(--esp-type-normal)",e["--esp-size-padding"]="var(--esp-size-tiny-to-small)",e["--esp-size-padding-page"]="var(--esp-size-small-to-normal)",e["--esp-size-border-radius"]=`${c(y*r)}rem`,e["--esp-measure"]="66ch",e["--esp-measure-wide"]="90ch",e["--esp-size-section"]="clamp(var(--esp-size-big), 7vw, var(--esp-size-huge))",Object.assign(e,_),e["--esp-card-min"]="16rem",e}export{z as DEFAULT_SCALE_CONFIG,_ as ELEVATION_PROPERTIES,l as STEP_NAMES,w as TYPE_ROLE_COLOR_PROPERTIES,S as TYPE_ROLE_PROPERTIES,P as generateScaleProperties};
@@ -315,13 +315,33 @@ export interface EspalierTheme {
315
315
  * carries an `oklch()` string here.
316
316
  */
317
317
  seedColor: string;
318
- /** CSS `font-family` for body / UI text. */
318
+ /**
319
+ * CSS `font-family` for body / UI text. Empty and omitted overrides resolve
320
+ * to the built-in UI stack.
321
+ *
322
+ * @default "system-ui, sans-serif"
323
+ */
319
324
  fontBody: string;
320
- /** CSS `font-family` for headings. */
325
+ /**
326
+ * CSS `font-family` for headings. When empty, heading recipes fall back to
327
+ * {@link fontBody} without changing this authored value.
328
+ *
329
+ * @default ""
330
+ */
321
331
  fontHeadings: string;
322
- /** CSS `font-family` for brand marks and product names. */
332
+ /**
333
+ * CSS `font-family` for brand marks and product names. When empty, brand
334
+ * recipes fall back through {@link fontHeadings} to {@link fontBody}.
335
+ *
336
+ * @default ""
337
+ */
323
338
  fontBrand: string;
324
- /** CSS `font-family` for code / monospace text. */
339
+ /**
340
+ * CSS `font-family` for code / monospace text. Empty and omitted overrides
341
+ * resolve to the built-in monospace family.
342
+ *
343
+ * @default "monospace"
344
+ */
325
345
  fontMonospace: string;
326
346
  /**
327
347
  * CSS `font-weight` for body / UI text.
@@ -629,6 +649,10 @@ export declare const DEFAULT_DARK_LIGHTNESS: Readonly<LightnessMap>;
629
649
  * hue and which lightness key sets the perceived brightness.
630
650
  */
631
651
  export declare const DEFAULT_SEMANTIC_MAPPINGS: Readonly<SemanticMappings>;
652
+ /** Built-in authored stack for body and UI text. */
653
+ export declare const DEFAULT_BODY_FONT_FAMILY = "system-ui, sans-serif";
654
+ /** Built-in authored family for code and monospace text. */
655
+ export declare const DEFAULT_MONOSPACE_FONT_FAMILY = "monospace";
632
656
  /**
633
657
  * The built-in **light** theme.
634
658
  *