@taprootio/espalier 2.4.0 → 2.6.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.
@@ -1,4 +1,4 @@
1
- var h=function(m,e,t,o){var n=arguments.length,s=n<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(m,e,t,o);else for(var a=m.length-1;a>=0;a--)(r=m[a])&&(s=(n<3?r(s):n>3?r(e,t,s):r(e,t))||s);return n>3&&s&&Object.defineProperty(e,t,s),s},c;import{css as k,html as b,LitElement as T}from"lit";import{customElement as w,property as l}from"lit/decorators.js";import{getEspBus as p}from"../shared/bus-events.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as g,parseTheme as y,mergeTheme as v}from"../shared/theme.js";import{computeThemeProperties as E}from"./helpers/compute-theme-properties.js";let i=c=class extends T{constructor(){super(...arguments),this.schemeBacker="",this.schemeExplicitlySet=!1,this.resolvingDefaultScheme=!1,this.systemSchemeQuery=null,this.lastSeedColor="",this.resolvedLightTheme={...f},this.resolvedDarkTheme={...g},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.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)}}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",o=this.schemeBacker;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0),t!==o&&(this.schemeBacker=t,this.requestUpdate("scheme",o),t&&p().publish("scheme-changed",{scheme:t,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,o){const n="data-esp-font",s=`${this.correlationId}-${e}`,r=document.head.querySelector(`link[${n}="${s}"]`);if(this.googleFontLoading==="none"){r?.remove();return}if(r&&t&&r.dataset.espFamily===t&&r.dataset.espWeight===(o??"")||(r?.remove(),!t))return;const a=encodeURIComponent(t),u=o==="bold"?"700":o==="normal"?"400":o,S=u&&u!=="400"?`:wght@${u}`:"",d=document.createElement("link");d.rel="stylesheet",d.href=`https://fonts.googleapis.com/css2?family=${a}${S}&display=swap`,d.setAttribute(n,s),d.dataset.espFamily=t,d.dataset.espWeight=o??"",document.head.appendChild(d)}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",c.extractFamily(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",c.extractFamily(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",c.extractFamily(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",c.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?y(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?y(this.darkThemeAttr):null;this.resolvedDarkTheme=t?v(g,t):{...g}}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(r=>e.has(r)))&&(this.resolveThemes(),p().publish("theme-changed",{correlationId:this.correlationId}));const n=E(this.activeTheme,this.scheme==="dark"?"dark":"light");for(const[r,a]of Object.entries(n))this.style.setProperty(r,a);const s=this.activeTheme.seedColor;this.lastSeedColor&&this.lastSeedColor!==s&&p().publish("seed-color-changed",{seedColor:s,correlationId:this.correlationId}),this.lastSeedColor=s,e.has("iconSpriteUrl")&&p().publish("icon-sprite-url-changed",{iconSpriteUrl:this.iconSpriteUrl,correlationId:this.correlationId}),this.syncGoogleFontLinks()}firstUpdated(){document.addEventListener("click",t=>{const o=t.composedPath().filter(n=>n instanceof HTMLElement&&n.tagName==="ESP-POPOVER");p().publish("close-popovers",{source:t.target??void 0,skipPopovers:o})}),this.resizeObserver.observe(this);const e=this.activeTheme.stylesheets;if(e.length)for(const t of e){const o=document.createElement("link");o.rel="stylesheet",o.href=t,document.head.appendChild(o)}if(!document.getElementById("esp-root-base-styles")){const t=document.createElement("style");t.id="esp-root-base-styles",t.textContent=c.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme()}updated(e){(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),super.disconnectedCallback()}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.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 b`<slot></slot>`}};i.lightDomStyles=`
1
+ var l=function(c,e,t,s){var h=arguments.length,o=h<3?e:s===null?s=Object.getOwnPropertyDescriptor(e,t):s,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(c,e,t,s);else for(var d=c.length-1;d>=0;d--)(r=c[d])&&(o=(h<3?r(o):h>3?r(e,t,o):r(e,t))||o);return h>3&&o&&Object.defineProperty(e,t,o),o},n;import{css as k,html as b,LitElement as C}from"lit";import{customElement as E,property as a}from"lit/decorators.js";import{getEspBus as p}from"../shared/bus-events.js";import{subscribeToRootEvent as T}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as g,parseTheme as y,mergeTheme as v}from"../shared/theme.js";import{computeThemeProperties as x}from"./helpers/compute-theme-properties.js";let i=n=class extends C{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.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.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)}}subscribeScoped(e,t){return T(this,e,t)}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",s=this.schemeBacker,h=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const o=t||this.resolveDefaultScheme();h!==this.schemeExplicitlySet&&this.isConnected&&this.syncSystemSchemeListener(),o!==s&&(this.schemeBacker=o,this.requestUpdate("scheme",s),this.themeEventsReady&&p().publish("scheme-changed",{scheme:o,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,s){const h="data-esp-font",o=`${this.correlationId}-${e}`,r=document.head.querySelector(`link[${h}="${o}"]`);if(this.googleFontLoading==="none"){r?.remove();return}if(r&&t&&r.dataset.espFamily===t&&r.dataset.espWeight===(s??"")||(r?.remove(),!t))return;const d=encodeURIComponent(t),u=s==="bold"?"700":s==="normal"?"400":s,S=u&&u!=="400"?`:wght@${u}`:"",m=document.createElement("link");m.rel="stylesheet",m.href=`https://fonts.googleapis.com/css2?family=${d}${S}&display=swap`,m.setAttribute(h,o),m.dataset.espFamily=t,m.dataset.espWeight=s??"",document.head.appendChild(m)}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",n.extractFamily(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",n.extractFamily(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",n.extractFamily(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",n.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?y(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?y(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())}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(r=>e.has(r)))&&(this.resolveThemes(),this.themeEventsReady&&p().publish("theme-changed",{correlationId:this.correlationId}));const h=x(this.activeTheme,this.scheme==="dark"?"dark":"light");for(const[r,d]of Object.entries(h))this.style.setProperty(r,d);const o=this.activeTheme.seedColor;this.themeEventsReady&&this.lastSeedColor&&this.lastSeedColor!==o&&p().publish("seed-color-changed",{seedColor:o,correlationId:this.correlationId}),this.lastSeedColor=o,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 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=n.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme(),this.lastSeedColor=this.activeTheme.seedColor,this.themeEventsReady=!0}updated(e){(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.unregisterDocumentClickBridge(),this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),this.removeRuntimeGoogleFontLinks(),super.disconnectedCallback()}registerDocumentClickBridge(){this.documentClickRegistrationActive||(this.documentClickRegistrationActive=!0,n.connectedRootCount+=1,n.connectedRootCount===1&&document.addEventListener("click",n.handleDocumentClick))}unregisterDocumentClickBridge(){this.documentClickRegistrationActive&&(this.documentClickRegistrationActive=!1,n.connectedRootCount=Math.max(0,n.connectedRootCount-1),n.connectedRootCount===0&&document.removeEventListener("click",n.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 b`<slot></slot>`}};i.connectedRootCount=0,i.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})},i.lightDomStyles=`
2
2
 
3
3
  esp-root {
4
4
  font-family: var(--esp-font-body);
@@ -125,4 +125,4 @@ var h=function(m,e,t,o){var n=arguments.length,s=n<3?e:o===null?o=Object.getOwnP
125
125
  :host {
126
126
  display: block;
127
127
  }
128
- `,h([l({attribute:!1})],i.prototype,"correlationId",void 0),h([l({attribute:"light-theme"})],i.prototype,"lightThemeAttr",void 0),h([l({attribute:"dark-theme"})],i.prototype,"darkThemeAttr",void 0),h([l({attribute:"font-css-root",type:String})],i.prototype,"fontCSSRoot",void 0),h([l({attribute:"font-definitions-url",type:String})],i.prototype,"fontDefinitionsUrl",void 0),h([l({attribute:"google-font-loading",type:String})],i.prototype,"googleFontLoading",void 0),h([l({attribute:"icon-sprite-url",type:String})],i.prototype,"iconSpriteUrl",void 0),h([l({attribute:"default-scheme",type:String,reflect:!0})],i.prototype,"defaultScheme",void 0),h([l({attribute:"scheme",type:String,reflect:!0})],i.prototype,"scheme",null),i=c=h([w("esp-root")],i);export{i as EspalierRoot};
128
+ `,l([a({attribute:!1})],i.prototype,"correlationId",void 0),l([a({attribute:"light-theme"})],i.prototype,"lightThemeAttr",void 0),l([a({attribute:"dark-theme"})],i.prototype,"darkThemeAttr",void 0),l([a({attribute:"font-css-root",type:String})],i.prototype,"fontCSSRoot",void 0),l([a({attribute:"font-definitions-url",type:String})],i.prototype,"fontDefinitionsUrl",void 0),l([a({attribute:"google-font-loading",type:String})],i.prototype,"googleFontLoading",void 0),l([a({attribute:"icon-sprite-url",type:String})],i.prototype,"iconSpriteUrl",void 0),l([a({attribute:"default-scheme",type:String,reflect:!0})],i.prototype,"defaultScheme",void 0),l([a({attribute:"scheme",type:String,reflect:!0})],i.prototype,"scheme",null),i=n=l([E("esp-root")],i);export{i as EspalierRoot};
@@ -9,11 +9,15 @@
9
9
  * ```ts
10
10
  * import { getEspBus } from "@taprootio/espalier";
11
11
  *
12
- * // Use built-in Espalier events out of the box:
12
+ * // Use the global bus for application-global Espalier events:
13
13
  * const bus = getEspBus();
14
- * bus.subscribe("scheme-changed", (payload) => { … });
15
14
  * bus.publish("show-toast", { message: "Done!" });
16
15
  *
16
+ * // Theme events are root-scoped. Subscribe through the owning root so
17
+ * // nested preview roots cannot trigger an application-level handler:
18
+ * const root = document.querySelector("esp-root")!;
19
+ * const unsubscribe = root.subscribeScoped("scheme-changed", ({ scheme }) => { … });
20
+ *
17
21
  * // Or extend with your own application events:
18
22
  * type MyAppEvents = EspBusEventMap & {
19
23
  * "sse-notification": { type: string; payload: unknown };
@@ -41,9 +45,12 @@ export interface SeedColorRoot {
41
45
  /**
42
46
  * Theme coordination events.
43
47
  *
44
- * Published by `<esp-root>` and subscribed to by every
45
- * `EspalierElementBase` descendant so that scheme, seed,
46
- * and full-theme changes propagate to variant-aware children.
48
+ * Published by `<esp-root>` after initial mount and subscribed to by every
49
+ * `EspalierElementBase` descendant so that scheme, seed, and full-theme changes
50
+ * propagate to variant-aware children. All roots share one global bus, so
51
+ * consumers should use `EspalierRoot.subscribeScoped()` instead of subscribing
52
+ * to these events directly. Read initial values from the root; these events are
53
+ * change-only and are not replayed for late subscribers.
47
54
  *
48
55
  * @docUrl /api/scheme-events
49
56
  * @menuGroup Bus Events
@@ -1,4 +1,4 @@
1
- import{html as n,nothing as t}from"lit";function e({brandLogo:s,brandText:o,brandHref:l,brandAlt:c}){if(!s&&!o)return t;const r=n`
2
- ${s?n`<img class="brand-logo" src=${s} alt=${c||(o?"":"Site logo")} />`:t}
3
- ${o?n`<span class="brand-text">${o}</span>`:t}
4
- `;return l?n`<a class="configured-brand" href=${l}>${r}</a>`:n`<span class="configured-brand">${r}</span>`}export{e as renderConfiguredBrand};
1
+ import{html as r,nothing as t}from"lit";function u({scheme:o,brandLogo:n,brandColor:s,lightBrandLogo:e,darkBrandLogo:c,lightBrandColor:a,darkBrandColor:l}){return{brandLogo:(o==="dark"?c:e)||n,brandColor:(o==="dark"?l:a)||s}}function f({brandLogo:o,brandText:n,brandHref:s,brandAlt:e}){if(!o&&!n)return t;const a=r`
2
+ ${o?r`<img class="brand-logo" src=${o} alt=${e||(n?"":"Site logo")} />`:t}
3
+ ${n?r`<span class="brand-text">${n}</span>`:t}
4
+ `;return s?r`<a class="configured-brand" href=${s}>${a}</a>`:r`<span class="configured-brand">${a}</span>`}export{f as renderConfiguredBrand,u as resolveConfiguredBrand};
@@ -1,4 +1,4 @@
1
- var p=function(g,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(g,e,t,r);else for(var c=g.length-1;c>=0;c--)(a=g[c])&&(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 x,LitElement as E}from"lit";import{property as m,state as I}from"lit/decorators.js";import{getEspBus as V}from"./bus-events.js";import{traverseToClosest as S}from"./utilities.js";import{parseOklch as A,serializeOklch as y,gamutMapToSRGB as O,deriveSemantic as L,deriveSemanticWithContrast as U}from"./color-engine.js";import{computeVariants as T}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as R,semanticToCSS as P}from"./theme.js";import{alignAttributeTextInheritance as _,focusRing as z}from"./style-fragments.js";class n extends E{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.variantTokenOriginalValues=new Map,this.rootEventSubscriptionsActive=!1,this.variantBacker="primary",this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{const t=this.syncRootFromDom(!1);!t||e.correlationId!==t.correlationId||(this.seedColor=e.seedColor,this.applyVariantTokens())},this.handleSchemeChanged=e=>{const t=this.syncRootFromDom(!1);!t||e.correlationId!==t.correlationId||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyVariantTokens())},this.handleThemeChanged=e=>{const t=this.syncRootFromDom(!1);!t||e.correlationId!==t.correlationId||this.applyVariantTokens()},this.handleIconSpriteUrlChanged=e=>{const t=this.syncRootFromDom(!1);!t||e.correlationId!==t.correlationId||this.requestUpdate()}}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("value-changed",{detail:e,bubbles:!0,composed:!0}))}get variant(){return this.variantBacker}set variant(e){this.variantBacker=e,this.applyVariantTokens()}connectedCallback(){super.connectedCallback(),this.subscribeToRootEvents(),this.hasUpdated&&this.syncRootFromDom(!1)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents()}firstUpdated(e){this.syncRootFromDom(!0)}syncRootFromDom(e){const t=S(this,"esp-root");if(!t){if(this.espRoot&&this.clearVariantTokens(),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,c=this.seedColor!==t.seedColor;return this.espRoot=t,(r||a||c)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyVariantTokens()),r&&this.requestUpdate(),t}subscribeToRootEvents(){if(this.rootEventSubscriptionsActive)return;const e=V();e.subscribe("seed-color-changed",this.handleSeedColorChanged),e.subscribe("scheme-changed",this.handleSchemeChanged),e.subscribe("theme-changed",this.handleThemeChanged),e.subscribe("icon-sprite-url-changed",this.handleIconSpriteUrlChanged),this.rootEventSubscriptionsActive=!0}unsubscribeFromRootEvents(){if(!this.rootEventSubscriptionsActive)return;const e=V();e.unsubscribe("seed-color-changed",this.handleSeedColorChanged),e.unsubscribe("scheme-changed",this.handleSchemeChanged),e.unsubscribe("theme-changed",this.handleThemeChanged),e.unsubscribe("icon-sprite-url-changed",this.handleIconSpriteUrlChanged),this.rootEventSubscriptionsActive=!1}traverseToClosest(e){return S(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,r=A(t.seedColor);if(!r)return;const s=T(r,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",y(O(s)));const a=T(s,t),c=n.statusVariantSources.has(e),{textContrast:k}=n,f={};for(const i of R){if(k[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),b=a[d],v=t.lightness[l.lightness],u=L(b,v,h.min,h.max);f[i]=u,this.setVariantTokenProperty(P(i),y(u))}for(const i of R){const l=k[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],b=this.effectiveVariantTokenSource(i,h.source,c),v=a[b],u=t.lightness[h.lightness],w=f[l.bg],C=U(v,u,d.min,d.max,w,l.targetLc);f[i]=C,this.setVariantTokenProperty(P(i),y(C))}}effectiveVariantTokenSource(e,t,r){return r&&n.semanticActionTokens.has(e)?"primary":t}getVariantColorSource(){switch(this.variant){case"":case"primary":case"neutral":return"";case"info":return"complementary";default:return this.variant}}setVariantTokenProperty(e,t){const r=this.variantTokenOriginalValues.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.variantTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:o.length?o:null})}this.style.setProperty(e,t)}clearVariantTokens(){for(const[e,t]of this.variantTokenOriginalValues){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.variantTokenOriginalValues.clear()}}n.textContrast={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}},n.statusVariantSources=new Set(["danger","success","warning"]),n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[z(".esp-field:focus-within","--esp-field-focus-shadow"),_,x`
1
+ var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(f,e,t,o);else for(var c=f.length-1;c>=0;c--)(a=f[c])&&(s=(r<3?a(s):r>3?a(e,t,s):a(e,t))||s);return r>3&&s&&Object.defineProperty(e,t,s),s};import{css as E,LitElement as x}from"lit";import{property as y,state as U}from"lit/decorators.js";import{subscribeToRootEvent as g}from"./root-event-subscription.js";import{traverseToClosest as V}from"./utilities.js";import{parseOklch as A,serializeOklch as k,gamutMapToSRGB as O,deriveSemantic as L,deriveSemanticWithContrast as F}from"./color-engine.js";import{computeVariants as T}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as S,semanticToCSS as P}from"./theme.js";import{alignAttributeTextInheritance as _,focusRing as z}from"./style-fragments.js";class n extends x{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.variantTokenOriginalValues=new Map,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.variantBacker="primary",this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.scheme="light",this.handleSeedColorChanged=e=>{this.syncRootFromDom(!1)&&(this.seedColor=e.seedColor,this.applyVariantTokens())},this.handleSchemeChanged=e=>{!this.syncRootFromDom(!1)||this.scheme===e.scheme||(this.scheme=e.scheme,this.applyVariantTokens())},this.handleThemeChanged=()=>{this.syncRootFromDom(!1)&&this.applyVariantTokens()},this.handleIconSpriteUrlChanged=()=>{this.syncRootFromDom(!1)&&this.requestUpdate()}}get seedColor(){return this.seedColorBacker}set seedColor(e){this.seedColorBacker=e}focusResolvedElementAfterUpdate(e,t){const o=()=>{const r=e();return r?(r.focus(t),!0):!1};o()||this.updateComplete.then(()=>{o()})}focusShadowElementAfterUpdate(e,t){this.focusResolvedElementAfterUpdate(()=>this.shadowRoot?.querySelector(e),t)}emitValueChanged(e){this.dispatchEvent(new CustomEvent("value-changed",{detail:e,bubbles:!0,composed:!0}))}get variant(){return this.variantBacker}set variant(e){this.variantBacker=e,this.applyVariantTokens()}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents()}firstUpdated(e){this.syncRootFromDom(!0)}syncRootFromDom(e){const t=V(this,"esp-root");if(!t){if(this.espRoot&&this.clearVariantTokens(),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 o=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",a=this.scheme!==s,c=this.seedColor!==t.seedColor;return this.espRoot=t,o&&this.isConnected&&this.subscribeToRootEvents(t),(o||a||c)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyVariantTokens()),o&&this.requestUpdate(),t}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[g(e,"seed-color-changed",this.handleSeedColorChanged),g(e,"scheme-changed",this.handleSchemeChanged),g(e,"theme-changed",this.handleThemeChanged),g(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}}traverseToClosest(e){return V(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,o=A(t.seedColor);if(!o)return;const s=T(o,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",k(O(s)));const a=T(s,t),c=n.statusVariantSources.has(e),{textContrast:C}=n,b={};for(const i of S){if(C[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),v=a[d],m=t.lightness[l.lightness],u=L(v,m,h.min,h.max);b[i]=u,this.setVariantTokenProperty(P(i),k(u))}for(const i of S){const l=C[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],v=this.effectiveVariantTokenSource(i,h.source,c),m=a[v],u=t.lightness[h.lightness],w=b[l.bg],R=F(m,u,d.min,d.max,w,l.targetLc);b[i]=R,this.setVariantTokenProperty(P(i),k(R))}}effectiveVariantTokenSource(e,t,o){return o&&n.semanticActionTokens.has(e)?"primary":t}getVariantColorSource(){switch(this.variant){case"":case"primary":case"neutral":return"";case"info":return"complementary";default:return this.variant}}setVariantTokenProperty(e,t){const o=this.variantTokenOriginalValues.get(e);if(o){const r=this.style.getPropertyValue(e),s=this.style.getPropertyPriority(e);(r!==o.generatedValue||s!==o.generatedPriority)&&(o.originalValue=r.length?r:null,o.originalPriority=s),o.generatedValue=t,o.generatedPriority=""}else{const r=this.style.getPropertyValue(e);this.variantTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:r.length?r:null})}this.style.setProperty(e,t)}clearVariantTokens(){for(const[e,t]of this.variantTokenOriginalValues){const o=this.style.getPropertyValue(e),r=this.style.getPropertyPriority(e);(o!==t.generatedValue||r!==t.generatedPriority)&&(t.originalValue=o.length?o:null,t.originalPriority=r),t.originalValue===null?this.style.removeProperty(e):this.style.setProperty(e,t.originalValue,t.originalPriority)}this.variantTokenOriginalValues.clear()}}n.textContrast={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}},n.statusVariantSources=new Set(["danger","success","warning"]),n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[z(".esp-field:focus-within","--esp-field-focus-shadow"),_,E`
2
2
  :host {
3
3
 
4
4
  --_esp-field-resolved-hover-bg: var(
@@ -122,4 +122,4 @@ var p=function(g,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
122
122
  .esp-field:has(textarea:disabled):hover {
123
123
  background-color: var(--esp-field-background, var(--esp-color-layer-2));
124
124
  }
125
- `],p([I()],n.prototype,"seedColor",null),p([m({attribute:!1})],n.prototype,"correlationId",void 0),p([m({type:String,reflect:!0})],n.prototype,"scheme",void 0),p([m({type:String,attribute:"variant",reflect:!0})],n.prototype,"variant",null);export{n as EspalierElementBase};
125
+ `],p([U()],n.prototype,"seedColor",null),p([y({attribute:!1})],n.prototype,"correlationId",void 0),p([y({type:String,reflect:!0})],n.prototype,"scheme",void 0),p([y({type:String,attribute:"variant",reflect:!0})],n.prototype,"variant",null);export{n as EspalierElementBase};
@@ -30,6 +30,7 @@ export { type FlyoutConfig, type FlyoutCloseReason } from "./flyout-events.js";
30
30
  export { type PickerItem } from "../pickers/esp-picker-item.js";
31
31
  export { type EspalierUploadImage } from "../image-upload/image-helpers.js";
32
32
  export { type FontPickerValueChangedDetail, type GoogleFont, type WebSafeFont, } from "../font-picker/esp-font-picker.js";
33
+ export { type EspThemeToggleEventDetail } from "../header/esp-header.js";
33
34
  import type { EspalierDetails } from "../details/esp-details.js";
34
35
  import type { FlyoutCloseReason } from "./flyout-events.js";
35
36
  import type { ValidityChangedDetail } from "./validation.js";
@@ -39,6 +40,7 @@ import type { PickerItem } from "../pickers/esp-picker-item.js";
39
40
  import type { EspalierUploadImage, UploadEventDetail } from "../image-upload/image-helpers.js";
40
41
  export type { UploadEventDetail } from "../image-upload/image-helpers.js";
41
42
  import type { FontPickerValueChangedDetail } from "../font-picker/esp-font-picker.js";
43
+ import type { EspThemeToggleEventDetail } from "../header/esp-header.js";
42
44
  /**
43
45
  * Canonical event name strings for every CustomEvent in the library.
44
46
  *
@@ -65,6 +67,7 @@ export declare const ESP_EVENTS: {
65
67
  readonly ESP_ACCORDION_CHANGE: "esp-accordion-change";
66
68
  readonly DRAWER_OPENED: "drawer-opened";
67
69
  readonly DRAWER_CLOSED: "drawer-closed";
70
+ readonly ESP_THEME_TOGGLE: "esp-theme-toggle";
68
71
  readonly FLYOUT_OPENED: "flyout-opened";
69
72
  readonly FLYOUT_CLOSED: "flyout-closed";
70
73
  readonly FLYOUT_STATE_CHANGED: "flyout-state-changed";
@@ -284,6 +287,10 @@ export interface EspalierFlyoutEventMap {
284
287
  export interface EspalierHeaderButtonEventMap {
285
288
  [ESP_EVENTS.CLICKED]: CustomEvent<Record<string, never>>;
286
289
  }
290
+ /** Events fired by `<esp-header>`. */
291
+ export interface EspalierHeaderEventMap {
292
+ [ESP_EVENTS.ESP_THEME_TOGGLE]: CustomEvent<EspThemeToggleEventDetail>;
293
+ }
287
294
  /** Events fired by `<esp-grid>`. */
288
295
  export interface EspalierGridEventMap {
289
296
  [ESP_EVENTS.GRID_EVENT]: CustomEvent<GridClickedEvent>;
@@ -1 +1 @@
1
- import{VALIDITY_CHANGED_EVENT as D}from"./validation.js";const e={VALUE_CHANGED:"value-changed",VALIDITY_CHANGED:"validity-changed",CLICKED:"clicked",ESP_SUBMIT:"esp-submit",ESP_SUBMIT_RESPONSE:"esp-submit-response",ESP_SUBMIT_ERROR:"esp-submit-error",ESP_TAB_CHANGED:"esp-tab-changed",ESP_TAB_UPDATED:"esp-tab-updated",ESP_TOGGLE:"esp-toggle",ESP_ACCORDION_CHANGE:"esp-accordion-change",DRAWER_OPENED:"drawer-opened",DRAWER_CLOSED:"drawer-closed",FLYOUT_OPENED:"flyout-opened",FLYOUT_CLOSED:"flyout-closed",FLYOUT_STATE_CHANGED:"flyout-state-changed",POPOVER_OPENED:"popover-opened",POPOVER_CLOSED:"popover-closed",GRID_EVENT:"grid-event",GRID_LOAD_START:"esp-grid-load-start",GRID_LOAD_SUCCESS:"esp-grid-load-success",GRID_LOAD_ERROR:"esp-grid-load-error",GRID_ITEMS_CHANGED:"esp-grid-items-changed",DESTROY:"destroy",FILE_SELECTED:"file-selected",FILE_REMOVED:"file-removed",FILES_SELECTED:"files-selected",FILES_REJECTED:"files-rejected",UPLOAD_RETRY:"upload-retry",RETRY_UPLOAD:"retry-upload",IMAGES_REORDERED:"images-reordered",SEARCH_REQUESTED:"search-requested",RESULT_SELECTED:"result-selected",SEARCH_CLOSED:"search-closed",SELECTION_CHANGED:"selection-changed",CLOSE_MENU:"close-menu",REMOVE_IMAGE:"remove-image"};export{e as ESP_EVENTS,D as VALIDITY_CHANGED_EVENT};
1
+ import{VALIDITY_CHANGED_EVENT as s}from"./validation.js";const e={VALUE_CHANGED:"value-changed",VALIDITY_CHANGED:"validity-changed",CLICKED:"clicked",ESP_SUBMIT:"esp-submit",ESP_SUBMIT_RESPONSE:"esp-submit-response",ESP_SUBMIT_ERROR:"esp-submit-error",ESP_TAB_CHANGED:"esp-tab-changed",ESP_TAB_UPDATED:"esp-tab-updated",ESP_TOGGLE:"esp-toggle",ESP_ACCORDION_CHANGE:"esp-accordion-change",DRAWER_OPENED:"drawer-opened",DRAWER_CLOSED:"drawer-closed",ESP_THEME_TOGGLE:"esp-theme-toggle",FLYOUT_OPENED:"flyout-opened",FLYOUT_CLOSED:"flyout-closed",FLYOUT_STATE_CHANGED:"flyout-state-changed",POPOVER_OPENED:"popover-opened",POPOVER_CLOSED:"popover-closed",GRID_EVENT:"grid-event",GRID_LOAD_START:"esp-grid-load-start",GRID_LOAD_SUCCESS:"esp-grid-load-success",GRID_LOAD_ERROR:"esp-grid-load-error",GRID_ITEMS_CHANGED:"esp-grid-items-changed",DESTROY:"destroy",FILE_SELECTED:"file-selected",FILE_REMOVED:"file-removed",FILES_SELECTED:"files-selected",FILES_REJECTED:"files-rejected",UPLOAD_RETRY:"upload-retry",RETRY_UPLOAD:"retry-upload",IMAGES_REORDERED:"images-reordered",SEARCH_REQUESTED:"search-requested",RESULT_SELECTED:"result-selected",SEARCH_CLOSED:"search-closed",SELECTION_CHANGED:"selection-changed",CLOSE_MENU:"close-menu",REMOVE_IMAGE:"remove-image"};export{e as ESP_EVENTS,s as VALIDITY_CHANGED_EVENT};
@@ -0,0 +1 @@
1
+ import{getEspBus as n}from"./bus-events.js";function u(c,o,e){const r=t=>{t.correlationId===c.correlationId&&e(t)},s=n();return s.subscribe(o,r),()=>s.unsubscribe(o,r)}export{u as subscribeToRootEvent};
@@ -672,7 +672,7 @@
672
672
  "name": "--esp-footer-row-gap",
673
673
  "category": "component",
674
674
  "component": "esp-footer",
675
- "description": "Compact-layout row gap. Defaults to `var(--esp-size-big)`."
675
+ "description": "Vertical gap between footer grid rows and link groups stacked in `esp-footer-column`. Defaults to `var(--esp-size-big)`."
676
676
  },
677
677
  {
678
678
  "name": "--esp-footer-section-gap",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taprootio/espalier",
3
- "version": "2.4.0",
3
+ "version": "2.6.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",
@@ -102,6 +102,10 @@
102
102
  "types": "./dist/footer/index.d.ts",
103
103
  "import": "./dist/footer/index.js"
104
104
  },
105
+ "./footer/column": {
106
+ "types": "./dist/footer/esp-footer-column.d.ts",
107
+ "import": "./dist/footer/esp-footer-column.js"
108
+ },
105
109
  "./footer/link-group": {
106
110
  "types": "./dist/footer/esp-footer-link-group.d.ts",
107
111
  "import": "./dist/footer/esp-footer-link-group.js"