@taprootio/espalier 6.2.0 → 6.3.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 (65) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +5 -5
  3. package/custom-elements.json +945 -241
  4. package/dist/action-menu/esp-action-menu-item.js +1 -0
  5. package/dist/action-menu/esp-action-menu.js +4 -3
  6. package/dist/box/esp-box.d.ts +14 -3
  7. package/dist/box/esp-box.js +5 -5
  8. package/dist/button/esp-button.d.ts +4 -4
  9. package/dist/date-picker/helpers/styles.js +1 -0
  10. package/dist/details/esp-details.d.ts +3 -0
  11. package/dist/details/esp-details.js +13 -6
  12. package/dist/dialog/esp-dialog.d.ts +6 -2
  13. package/dist/dialog/esp-dialog.js +62 -62
  14. package/dist/flyout/esp-flyout.d.ts +2 -2
  15. package/dist/flyout/esp-flyout.js +6 -5
  16. package/dist/focus-picker/esp-focus-picker.js +3 -2
  17. package/dist/footer/esp-footer.d.ts +3 -3
  18. package/dist/footer/esp-footer.js +10 -10
  19. package/dist/grid/esp-grid.d.ts +3 -0
  20. package/dist/grid/esp-grid.js +25 -17
  21. package/dist/header/esp-header-button.d.ts +6 -15
  22. package/dist/header/esp-header.d.ts +4 -2
  23. package/dist/header/esp-header.js +8 -7
  24. package/dist/image-picker/esp-image-picker.js +1 -0
  25. package/dist/image-upload/esp-image-upload.js +1 -0
  26. package/dist/info/esp-info.d.ts +3 -1
  27. package/dist/info/esp-info.js +8 -8
  28. package/dist/lightbox/esp-lightbox.d.ts +3 -0
  29. package/dist/lightbox/esp-lightbox.js +12 -9
  30. package/dist/menu/esp-menu-group.js +6 -2
  31. package/dist/menu/esp-menu-item.js +7 -3
  32. package/dist/menu/esp-menu.js +4 -2
  33. package/dist/page/esp-page.d.ts +1 -1
  34. package/dist/page/esp-page.styles.js +1 -0
  35. package/dist/pickers/esp-pick-one.d.ts +1 -2
  36. package/dist/pickers/esp-pick-some.d.ts +1 -1
  37. package/dist/pickers/esp-picker-item.js +9 -5
  38. package/dist/pickers/esp-picker-menu.js +2 -0
  39. package/dist/popover/esp-popover.d.ts +2 -4
  40. package/dist/repeater/esp-repeater.js +1 -0
  41. package/dist/root/esp-root.d.ts +4 -4
  42. package/dist/root/esp-root.js +5 -3
  43. package/dist/row/esp-row.d.ts +1 -2
  44. package/dist/search/esp-search.js +2 -0
  45. package/dist/section/esp-section.d.ts +1 -1
  46. package/dist/section/esp-section.js +2 -1
  47. package/dist/shared/configured-brand.d.ts +11 -37
  48. package/dist/shared/esp-element-base.d.ts +4 -1
  49. package/dist/shared/esp-element-base.js +27 -30
  50. package/dist/shared/justified-layout.d.ts +6 -18
  51. package/dist/shared/surface-layer.d.ts +12 -0
  52. package/dist/shared/surface-layer.js +10 -0
  53. package/dist/shared/theme.d.ts +7 -18
  54. package/dist/slider/esp-slider.d.ts +2 -4
  55. package/dist/stack/esp-stack.d.ts +1 -2
  56. package/dist/switch/esp-switch.d.ts +2 -4
  57. package/dist/tabs/esp-tab-group.d.ts +3 -0
  58. package/dist/tabs/esp-tab-group.js +7 -7
  59. package/dist/tooltip/esp-tooltip.js +1 -0
  60. package/dist/tree/esp-tree.d.ts +0 -5
  61. package/dist/tree/esp-tree.js +3 -0
  62. package/espalier.css-data.json +1 -1
  63. package/espalier.token-manifest.json +1 -1
  64. package/licenses/README.md +18 -15
  65. package/package.json +5 -1
@@ -1,4 +1,6 @@
1
- var r=function(c,e,t,s){var h=arguments.length,i=h<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 l=c.length-1;l>=0;l--)(m=c[l])&&(i=(h<3?m(i):h>3?m(e,t,i):m(e,t))||i);return h>3&&i&&Object.defineProperty(e,t,i),i},a;import{css as b,html as w,LitElement as E}from"lit";import{customElement as C,property as n,state as R}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 u,mergeTheme as v}from"../shared/theme.js";import{extractFamily as p,isLocalFontFamily as L,removeRuntimeGoogleFontLinks as S,syncRuntimeGoogleFontLink as D}from"../shared/font-helpers.js";import{computeThemeProperties as A}from"./helpers/compute-theme-properties.js";import{registerImageTexture as F,registeredImageTextures as I}from"../shared/image-texture-registry.js";import{registerImageTexture as Q,registeredImageTextures as $,BUILT_IN_IMAGE_TEXTURES as N}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={...g},this.appliedThemeProperties=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){F(e,t)}static registeredTextures(){return I()}subscribeScoped(e,t){return x(this,e,t)}get lightTheme(){return this.lightThemeAttr?u(this.lightThemeAttr):null}set lightTheme(e){this.lightThemeAttr=e?y(e):""}get darkTheme(){return this.darkThemeAttr?u(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,h=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const i=t||this.resolveDefaultScheme();h!==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 h=`${this.correlationId}-${e}`,i=L(t)?"":t;D({owner:`root:${h}`,family:i,weight:s,enabled:this.googleFontLoading!=="none"})}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",p(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",p(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",p(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("menu",p(e.fontMenu),e.fontWeightMenu),this.injectGoogleFontLink("monospace",p(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){S(`root:${this.correlationId}-`),S(`picker:${this.correlationId}:`)}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?u(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?u(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(l=>e.has(l)))&&(this.resolveThemes(),this.themeEventsReady&&d().publish("theme-changed",{correlationId:this.correlationId})),this.hasAuthorTheme&&this.settleTheme();const h=A(this.activeTheme,this.scheme==="dark"?"dark":"light"),i=new Set(Object.keys(h));for(const l of this.appliedThemeProperties)i.has(l)||this.style.removeProperty(l);for(const[l,k]of Object.entries(h))this.style.setProperty(l,k);this.appliedThemeProperties=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=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");d().publish("close-popovers",{source:c.target??void 0,skipPopovers:e})},o.lightDomStyles=`
1
+ var r=function(c,e,t,s){var h=arguments.length,i=h<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 l=c.length-1;l>=0;l--)(m=c[l])&&(i=(h<3?m(i):h>3?m(e,t,i):m(e,t))||i);return h>3&&i&&Object.defineProperty(e,t,i),i},a;import{surfaceLayerAttributes as b}from"../shared/surface-layer.js";import{css as w,html as E,LitElement as C}from"lit";import{customElement as R,property as n,state as x}from"lit/decorators.js";import{getEspBus as d}from"../shared/bus-events.js";import{subscribeToRootEvent as L}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as f,DEFAULT_DARK_THEME as g,encodeTheme as y,parseTheme as u,mergeTheme as v}from"../shared/theme.js";import{extractFamily as p,isLocalFontFamily as A,removeRuntimeGoogleFontLinks as S,syncRuntimeGoogleFontLink as D}from"../shared/font-helpers.js";import{computeThemeProperties as F}from"./helpers/compute-theme-properties.js";import{registerImageTexture as I,registeredImageTextures as z}from"../shared/image-texture-registry.js";import{registerImageTexture as N,registeredImageTextures as V,BUILT_IN_IMAGE_TEXTURES as q}from"../shared/image-texture-registry.js";const T=1e3;let o=a=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.appliedThemeProperties=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 z()}subscribeScoped(e,t){return L(this,e,t)}get lightTheme(){return this.lightThemeAttr?u(this.lightThemeAttr):null}set lightTheme(e){this.lightThemeAttr=e?y(e):""}get darkTheme(){return this.darkThemeAttr?u(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,h=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const i=t||this.resolveDefaultScheme();h!==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 h=`${this.correlationId}-${e}`,i=A(t)?"":t;D({owner:`root:${h}`,family:i,weight:s,enabled:this.googleFontLoading!=="none"})}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",p(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",p(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",p(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("menu",p(e.fontMenu),e.fontWeightMenu),this.injectGoogleFontLink("monospace",p(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){S(`root:${this.correlationId}-`),S(`picker:${this.correlationId}:`)}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?u(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(f,e):{...f};const t=this.darkThemeAttr?u(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(l=>e.has(l)))&&(this.resolveThemes(),this.themeEventsReady&&d().publish("theme-changed",{correlationId:this.correlationId})),this.hasAuthorTheme&&this.settleTheme();const h=F(this.activeTheme,this.scheme==="dark"?"dark":"light"),i=new Set(Object.keys(h));for(const l of this.appliedThemeProperties)i.has(l)||this.style.removeProperty(l);for(const[l,k]of Object.entries(h))this.style.setProperty(l,k);this.appliedThemeProperties=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=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 E`<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
+ ${b("esp-root [surface-layer]").cssText}
3
+
2
4
 
3
5
  esp-root {
4
6
  font-family: var(--_esp-font-body-effective, var(--esp-font-body, system-ui, sans-serif));
@@ -127,7 +129,7 @@ var r=function(c,e,t,s){var h=arguments.length,i=h<3?e:s===null?s=Object.getOwnP
127
129
  max-width: 100%;
128
130
  display: block;
129
131
  }
130
- `,o.styles=b`
132
+ `,o.styles=w`
131
133
  :host {
132
134
  display: block;
133
135
  }
@@ -136,4 +138,4 @@ var r=function(c,e,t,s){var h=arguments.length,i=h<3?e:s===null?s=Object.getOwnP
136
138
  :host([theme-pending]:not([data-theme-ready])) {
137
139
  visibility: hidden;
138
140
  }
139
- `,r([n({attribute:!1})],o.prototype,"correlationId",void 0),r([n({attribute:"light-theme"})],o.prototype,"lightThemeAttr",void 0),r([n({attribute:"dark-theme"})],o.prototype,"darkThemeAttr",void 0),r([n({attribute:!1})],o.prototype,"lightTheme",null),r([n({attribute:!1})],o.prototype,"darkTheme",null),r([n({attribute:"font-css-root",type:String})],o.prototype,"fontCSSRoot",void 0),r([n({attribute:"font-definitions-url",type:String})],o.prototype,"fontDefinitionsUrl",void 0),r([n({attribute:"google-font-loading",type:String})],o.prototype,"googleFontLoading",void 0),r([n({attribute:"icon-sprite-url",type:String})],o.prototype,"iconSpriteUrl",void 0),r([n({attribute:"theme-pending",reflect:!0,type:Boolean})],o.prototype,"themePending",void 0),r([R()],o.prototype,"themeReadyState",void 0),r([n({attribute:"default-scheme",type:String,reflect:!0})],o.prototype,"defaultScheme",void 0),r([n({attribute:"scheme",type:String,reflect:!0})],o.prototype,"scheme",null),o=a=r([C("esp-root")],o);export{N as BUILT_IN_IMAGE_TEXTURES,o as EspalierRoot,Q as registerImageTexture,$ as registeredImageTextures};
141
+ `,r([n({attribute:!1})],o.prototype,"correlationId",void 0),r([n({attribute:"light-theme"})],o.prototype,"lightThemeAttr",void 0),r([n({attribute:"dark-theme"})],o.prototype,"darkThemeAttr",void 0),r([n({attribute:!1})],o.prototype,"lightTheme",null),r([n({attribute:!1})],o.prototype,"darkTheme",null),r([n({attribute:"font-css-root",type:String})],o.prototype,"fontCSSRoot",void 0),r([n({attribute:"font-definitions-url",type:String})],o.prototype,"fontDefinitionsUrl",void 0),r([n({attribute:"google-font-loading",type:String})],o.prototype,"googleFontLoading",void 0),r([n({attribute:"icon-sprite-url",type:String})],o.prototype,"iconSpriteUrl",void 0),r([n({attribute:"theme-pending",reflect:!0,type:Boolean})],o.prototype,"themePending",void 0),r([x()],o.prototype,"themeReadyState",void 0),r([n({attribute:"default-scheme",type:String,reflect:!0})],o.prototype,"defaultScheme",void 0),r([n({attribute:"scheme",type:String,reflect:!0})],o.prototype,"scheme",null),o=a=r([R("esp-root")],o);export{q as BUILT_IN_IMAGE_TEXTURES,o as EspalierRoot,N as registerImageTexture,V as registeredImageTextures};
@@ -5,8 +5,7 @@ declare const ROW_JUSTIFIES: readonly ["start", "center", "end", "between"];
5
5
  export type EspalierJustify = (typeof ROW_JUSTIFIES)[number];
6
6
  export { ROW_JUSTIFIES };
7
7
  /**
8
- * A horizontal flow: children sit in a wrapping row with a themed gap —
9
- * "row, wrap, gap Y" without writing flexbox (ADR-010's micro half).
8
+ * Arranges children in a wrapping row with a themed gap.
10
9
  *
11
10
  * ```html
12
11
  * <esp-row gap="small" justify="between">
@@ -83,6 +83,7 @@ var o=function(a,e,t,c){var h=arguments.length,r=h<3?e:c===null?c=Object.getOwnP
83
83
  }
84
84
 
85
85
  .panel {
86
+ --_esp-surface-layer: 1;
86
87
  position: relative;
87
88
  z-index: 2;
88
89
  width: 100%;
@@ -175,6 +176,7 @@ var o=function(a,e,t,c){var h=arguments.length,r=h<3?e:c===null?c=Object.getOwnP
175
176
  }
176
177
 
177
178
  &.active {
179
+ --_esp-surface-layer: 2;
178
180
  background: var(--esp-search-active-background, var(--esp-color-layer-2));
179
181
  }
180
182
  }
@@ -6,7 +6,7 @@ import { EspalierElementBase } from "../shared/esp-element-base.js";
6
6
  * `esp-section` paints the local `--esp-color-background` edge to edge
7
7
  * and centers its content in a capped well. It carries no card identity:
8
8
  * no raised surface, no border radius, no shadow. Give it a `context`
9
- * (see the theming guide, `/guides/color/theming` on the docs site) and
9
+ * (see [theme overview](/espalier-guides/#foundations)) and
10
10
  * the band renders the zone's complete token table with nothing to
11
11
  * neutralize:
12
12
  *
@@ -1,4 +1,4 @@
1
- var p=function(r,t,o,n){var s=arguments.length,e=s<3?t:n===null?n=Object.getOwnPropertyDescriptor(t,o):n,a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(r,t,o,n);else for(var l=r.length-1;l>=0;l--)(a=r[l])&&(e=(s<3?a(e):s>3?a(t,o,e):a(t,o))||e);return s>3&&e&&Object.defineProperty(t,o,e),e};import{css as d,html as v,nothing as m}from"lit";import{customElement as u,property as h}from"lit/decorators.js";import{EspalierElementBase as c}from"../shared/esp-element-base.js";import{renderVisualOverlay as y,visualOverlayStyles as f}from"../shared/visual-overlay.js";let i=class extends c{constructor(){super(...arguments),this.decoration=!1}render(){return v`
1
+ var p=function(r,t,o,a){var n=arguments.length,e=n<3?t:a===null?a=Object.getOwnPropertyDescriptor(t,o):a,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(r,t,o,a);else for(var l=r.length-1;l>=0;l--)(s=r[l])&&(e=(n<3?s(e):n>3?s(t,o,e):s(t,o))||e);return n>3&&e&&Object.defineProperty(t,o,e),e};import{css as d,html as v,nothing as m}from"lit";import{customElement as u,property as h}from"lit/decorators.js";import{EspalierElementBase as c}from"../shared/esp-element-base.js";import{renderVisualOverlay as y,visualOverlayStyles as f}from"../shared/visual-overlay.js";let i=class extends c{constructor(){super(...arguments),this.decoration=!1}render(){return v`
2
2
  <div class="esp-section" part="section">
3
3
  ${this.decoration?y({className:"decoration"}):m}
4
4
  <div class="esp-section-well" part="well">
@@ -7,6 +7,7 @@ var p=function(r,t,o,n){var s=arguments.length,e=s<3?t:n===null?n=Object.getOwnP
7
7
  </div>
8
8
  `}};i.styles=[...c.styles,d`
9
9
  :host {
10
+ --_esp-surface-layer: initial;
10
11
  display: block;
11
12
  }
12
13
 
@@ -26,49 +26,23 @@ export interface ResolvedConfiguredBrand {
26
26
  */
27
27
  export declare function resolveConfiguredBrand({ scheme, brandLogo, brandColor, lightBrandLogo, darkBrandLogo, lightBrandColor, darkBrandColor, }: ConfiguredBrandConfiguration): ResolvedConfiguredBrand;
28
28
  /**
29
- * The ratio a configured-brand logo's box is reserved at before its bytes
30
- * arrive, shared by both consumers so they cannot drift apart.
29
+ * Reserve a logo's width while its image is loading or has failed.
31
30
  *
32
- * Both hosts give the logo a definite block size and leave the inline size to
33
- * the image, so until the image resolves there is no natural ratio to derive it
34
- * from: a pending request lays the element out at zero inline size and a failed
35
- * one at the width of its alt text. Either way the brand region resizes for a
36
- * reason that has nothing to do with the logo — on first paint, and again on
37
- * every scheme swap that fails, because both schemes exchange `src` at runtime.
31
+ * The header and footer give logos a fixed block size, so an image without
32
+ * intrinsic dimensions would otherwise have zero width or use its alt text's
33
+ * width. `aspect-ratio: auto <ratio>` uses this fallback only until a natural
34
+ * ratio is available, keeping loaded logos unchanged.
38
35
  *
39
- * Each host spends it as the fallback of its own
40
- * `--esp-{header,footer}-brand-logo-aspect-ratio`, in an
41
- * `aspect-ratio: auto <ratio>` declaration. `auto` is what makes this one
42
- * declaration the whole fix: it keeps a replaced element's *natural* ratio
43
- * authoritative whenever it has one, so a logo that loads is laid out exactly
44
- * as it is today — including a very wide one, where the inline cap clamps the
45
- * used width without feeding back into the definite block size. The ratio
46
- * governs only the states with nothing to measure.
47
- *
48
- * `3 / 1` because the existing caps already imply a wordmark of about that
49
- * shape: the footer's `3rem` block size against a `12rem` inline cap clamps at
50
- * 4:1, and the header's `0.72 x --esp-header-height` against the same cap
51
- * clamps near 3.7:1. A 3:1 reservation is therefore never born clamped, so the
52
- * reserved box is always the full ratio box.
36
+ * The 3:1 fallback fits below both hosts' existing inline caps, so the initial
37
+ * reservation is not clipped.
53
38
  */
54
39
  export declare const CONFIGURED_BRAND_LOGO_ASPECT_RATIO: import("lit").CSSResult;
55
40
  /**
56
- * Keep a failed logo's alt text from deciding how wide the logo's box is.
57
- *
58
- * The `alt` text is not suppressed — it still names the image for assistive
59
- * technology and still renders as the visible fallback. But a failed image is
60
- * no longer replaced content, so it takes an automatic minimum size from its
61
- * own text, and a minimum wider than the reserved box wins: measured in real
62
- * Chrome, a one-word alt of 37 characters pushed the header's logo back out to
63
- * its inline cap and swallowed the reservation whole. Allowing a break anywhere
64
- * makes that minimum one character wide, so the reserved ratio decides the box
65
- * and the alt text wraps inside it.
41
+ * Allow failed-image alt text to wrap within the reserved logo width.
66
42
  *
67
- * The footer already had this by inheritance — it sets `overflow-wrap` on
68
- * `.configured-brand`, where the header sets it only on `.brand-text` — so this
69
- * makes the two consumers agree rather than changing the footer. It has no
70
- * effect at all on an image that loads, because replaced content has no text to
71
- * break.
43
+ * A failed image can take its automatic minimum width from its alt text.
44
+ * Breaking long words prevents that minimum from overriding the reserved box.
45
+ * The text remains visible and accessible. Loaded images are unaffected.
72
46
  */
73
47
  export declare const configuredBrandLogoGeometry: import("lit").CSSResult;
74
48
  /**
@@ -8,7 +8,10 @@ import { type EspalierIntentVariant } from "./intent-values.js";
8
8
  * pickers, date pickers, buttons, and similar controls exposes the
9
9
  * following shared styling hooks:
10
10
  *
11
- * @cssprop --esp-field-background - Background color of the shared field shell. Defaults to `var(--esp-color-layer-2)`.
11
+ * A field fills one layer above the surface it sits on.
12
+ *
13
+ * @attr {"1"|"2"|"3"|"4"} surface-layer - Declares the painted surface depth. Fields use the next local layer, capped at layer 4.
14
+ * @cssprop --esp-field-background - Background color of the shared field shell. Defaults to one layer above the nearest declared surface, capped at `var(--esp-color-layer-4)`, or `var(--esp-color-layer-2)` without a declared surface. An explicit override wins.
12
15
  * @cssprop --esp-field-border-color - Border color of the shared field shell. Defaults to `var(--esp-color-border)`.
13
16
  * @cssprop --esp-field-border-width - Border width of the shared field shell. Defaults to `1px`.
14
17
  * @cssprop --esp-field-text-color - Text color used inside the shared field shell. Defaults to `var(--esp-color-text)`.
@@ -1,19 +1,8 @@
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`
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 C,LitElement as S}from"lit";import{property as h,state as w}from"lit/decorators.js";import{subscribeToRootEvent as p}from"./root-event-subscription.js";import{traverseToClosest as b}from"./utilities.js";import{parseCssColor as P,serializeOklch as x,gamutMapToSRGB as E}from"./color-engine.js";import{computeVariants as m}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as v}from"../root/helpers/compute-semantic-properties.js";import{DocumentSpriteController as V}from"./document-sprite.js";import{dataCompanionProperties as U}from"../root/helpers/data-companion-properties.js";import{dataSeriesProperties as _}from"../root/helpers/compute-theme-properties.js";import{lightnessRampProperties as I}from"../root/helpers/lightness-ramp-properties.js";import{ELEVATION_PROPERTIES as A,TYPE_ROLE_COLOR_PROPERTIES as O}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 j}from"./attribute-helpers.js";import{INTENT_VARIANTS as k,normalizeIntentVariant as B}from"./intent-values.js";import{ESP_EVENTS as W}from"./events.js";import{surfaceLayerAttributes as R,surfaceLayerColor as L}from"./surface-layer.js";class n extends S{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(W.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=B(e);j(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=b(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 V(this,{reactToSpriteChanges:!1})}traverseToClosest(e){return b(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=P(o.seedColor);if(!s)return;const a=m(s,o),i={};if(r.applied&&(Object.assign(i,v(o,a)),Object.assign(i,I(o)),Object.assign(i,A),Object.assign(i,O),Object.assign(i,U(i,_(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:m(s,l),T=v(l,g,{effectiveSource:(u,d)=>n.semanticActionTokens.has(u)?e:d});i["--esp-color-primary"]=x(E(g[e]));for(const u of n.semanticActionTokens){const d=z(u);i[d]=T[d]}}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=[R(":host"),R("[surface-layer]"),F(".esp-field:focus-within","--esp-field-focus-shadow"),N,C`
2
2
  :host {
3
3
 
4
4
  --_esp-font-body-fallback: system-ui, sans-serif;
5
5
  --_esp-font-monospace-fallback: monospace;
6
-
7
-
8
- --_esp-field-resolved-hover-bg: var(
9
- --esp-field-hover-bg,
10
- oklch(from var(--esp-field-background, var(--esp-color-layer-2)) calc(l * 0.88) c h)
11
- );
12
- --_esp-field-resolved-focus-bg: var(
13
- --esp-field-focus-bg,
14
- oklch(from var(--esp-field-background, var(--esp-color-layer-2)) calc(l * 0.82) c h)
15
- );
16
-
17
6
  display: block;
18
7
 
19
8
  * {
@@ -21,21 +10,6 @@ var c=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
21
10
  }
22
11
  }
23
12
 
24
- :host([scheme="light"]) {
25
- --_esp-field-resolved-hover-bg: var(
26
- --esp-field-hover-bg,
27
- oklch(
28
- from var(--esp-field-background, var(--esp-color-layer-2)) calc(l + (1 - l) * 0.5) c h
29
- )
30
- );
31
- --_esp-field-resolved-focus-bg: var(
32
- --esp-field-focus-bg,
33
- oklch(
34
- from var(--esp-field-background, var(--esp-color-layer-2)) calc(l + (1 - l) * 0.75) c h
35
- )
36
- );
37
- }
38
-
39
13
  ::placeholder {
40
14
  color: var(--esp-color-headings);
41
15
  }
@@ -68,13 +42,25 @@ var c=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
68
42
  }
69
43
 
70
44
  .esp-field {
45
+ --_esp-field-resolved-background: var(--esp-field-background, ${L(2)});
46
+
47
+
48
+ --_esp-field-resolved-hover-bg: var(
49
+ --esp-field-hover-bg,
50
+ oklch(from var(--_esp-field-resolved-background) calc(l * 0.88) c h)
51
+ );
52
+ --_esp-field-resolved-focus-bg: var(
53
+ --esp-field-focus-bg,
54
+ oklch(from var(--_esp-field-resolved-background) calc(l * 0.82) c h)
55
+ );
56
+
71
57
  font-family: var(
72
58
  --_esp-font-body-effective,
73
59
  var(--esp-font-body, var(--_esp-font-body-fallback))
74
60
  );
75
61
  font-size: var(--esp-size-font);
76
62
  font-weight: var(--esp-font-weight-body);
77
- background-color: var(--esp-field-background, var(--esp-color-layer-2));
63
+ background-color: var(--_esp-field-resolved-background);
78
64
  border-radius: var(--esp-size-border-radius);
79
65
  border: var(--esp-field-border-width, 1px) solid
80
66
  var(--esp-field-border-color, var(--esp-color-border));
@@ -125,6 +111,17 @@ var c=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
125
111
  }
126
112
  }
127
113
 
114
+ :host([scheme="light"]) .esp-field {
115
+ --_esp-field-resolved-hover-bg: var(
116
+ --esp-field-hover-bg,
117
+ oklch(from var(--_esp-field-resolved-background) calc(l + (1 - l) * 0.5) c h)
118
+ );
119
+ --_esp-field-resolved-focus-bg: var(
120
+ --esp-field-focus-bg,
121
+ oklch(from var(--_esp-field-resolved-background) calc(l + (1 - l) * 0.75) c h)
122
+ );
123
+ }
124
+
128
125
  .esp-field:has(button:disabled),
129
126
  .esp-field:has(a:disabled),
130
127
  .esp-field:has(input:disabled),
@@ -136,6 +133,6 @@ var c=function(f,e,t,r){var o=arguments.length,s=o<3?e:r===null?r=Object.getOwnP
136
133
  .esp-field:has(a:disabled):hover,
137
134
  .esp-field:has(input:disabled):hover,
138
135
  .esp-field:has(textarea:disabled):hover {
139
- background-color: var(--esp-field-background, var(--esp-color-layer-2));
136
+ background-color: var(--_esp-field-resolved-background);
140
137
  }
141
- `],c([S()],n.prototype,"seedColor",null),c([d({attribute:!1})],n.prototype,"correlationId",void 0),c([d({type:String,reflect:!0})],n.prototype,"scheme",void 0),c([d({type:String,attribute:"intent",reflect:!0,useDefault:!0})],n.prototype,"intent",null),c([d({type:String,attribute:"context",reflect:!0})],n.prototype,"context",null);export{n as EspalierElementBase};
138
+ `],c([w()],n.prototype,"seedColor",null),c([h({attribute:!1})],n.prototype,"correlationId",void 0),c([h({type:String,reflect:!0})],n.prototype,"scheme",void 0),c([h({type:String,attribute:"intent",reflect:!0,useDefault:!0})],n.prototype,"intent",null),c([h({type:String,attribute:"context",reflect:!0})],n.prototype,"context",null);export{n as EspalierElementBase};
@@ -67,25 +67,13 @@ export declare function normalizeAlbumMaxRowHeightVh(value: unknown): number;
67
67
  */
68
68
  export declare function normalizeMaxImagesPerRow(value: unknown, fallback?: number, maximum?: number): number;
69
69
  /**
70
- * Compute justified album rows with explicit cell widths.
70
+ * Compute justified album rows and the geometry a renderer needs for cropping.
71
71
  *
72
- * Algorithm:
73
- * 1. Add images to a row one at a time, scaled to the target row height.
74
- * 2. When the combined width overflows the container, the row breaks either
75
- * before or after the overflowing image — whichever leaves the row height
76
- * closer to the target. Keeping the image shrinks the row slightly below
77
- * target; pushing it to the next row stretches the row above target.
78
- * 3. Scale the finished row so it fills the container width exactly.
72
+ * Completed rows fill the available width. A row capped by `maxRowHeight` keeps
73
+ * relative cell widths, allowing `object-fit: cover` to crop its images. A final
74
+ * row below a finite `maxImagesPerRow` remains partial and preserves proportions;
75
+ * its height is capped by the preceding rows or target height and `maxRowHeight`.
79
76
  *
80
- * Completed rows always span the available width. When their justified height exceeds
81
- * `maxRowHeight`, their cells retain their relative widths while expanding to
82
- * the row width at the ceiling; a renderer can use `object-fit: cover` to crop
83
- * the resulting cells. A final row below a finite `maxImagesPerRow` instead
84
- * remains partial and preserves its image proportions. Its height is capped by
85
- * the tallest preceding row (or the target height when it is the only row) and
86
- * by `maxRowHeight`.
87
- *
88
- * With an omitted or invalid `maxImagesPerRow`, rows are unlimited in length
89
- * and every row is completed.
77
+ * An omitted or invalid `maxImagesPerRow` means unlimited, completed rows.
90
78
  */
91
79
  export declare function calculateAlbumLayout<T extends LayoutImage>(images: T[], options: AlbumLayoutOptions): AlbumLayoutRow<T>[];
@@ -0,0 +1,12 @@
1
+ import { type CSSResult } from "lit";
2
+ export type SurfaceLayer = 1 | 2 | 3 | 4;
3
+ /**
4
+ * Support `surface-layer="1|2|3|4"` on consumer surfaces in a shadow root.
5
+ * Include `surfaceLayerAttributes(":host")` for the consumer component's host,
6
+ * or `surfaceLayerAttributes("[surface-layer]")` for elements inside its shadow
7
+ * tree. Espalier installs these rules for its own hosts and root light DOM.
8
+ * The attribute declares depth; consumer components still paint their surface.
9
+ * A component that always paints a known layer can pass that depth as its
10
+ * default, so callers do not need to declare it on each instance.
11
+ */
12
+ export declare function surfaceLayerAttributes(selector: string, defaultLayer?: SurfaceLayer): CSSResult;
@@ -0,0 +1,10 @@
1
+ import{css as t,unsafeCSS as a}from"lit";function l(r,o){return a((o===void 0?"":`${r} { --_esp-surface-layer: ${o}; }
2
+ `)+[1,2,3,4].map(e=>`${r===":host"?`:host([surface-layer="${e}"])`:`${r}[surface-layer="${e}"]`} { --_esp-surface-layer: ${e}; }`).join(`
3
+ `))}function $(r,o=r){const e=["","var(--esp-color-layer-1)","var(--esp-color-layer-2)","var(--esp-color-layer-3)","var(--esp-color-layer-4)"],c=s=>s===o?e[s]:`${e[s].slice(0,-1)}, ${e[o]})`;let n=c(r);for(let s=r+1;s<=4;s++){const u=s-r;n=`color-mix(in oklch, ${n}, ${c(s)} calc(clamp(0, var(--_esp-surface-layer, 1) - ${u}, 1) * 100%))`}return a(n)}function f(r,o=":host"){return t`
4
+ ${a(o)} {
5
+ --_esp-surface-layer: ${r};
6
+ --_esp-surface-background: ${$(1,r)};
7
+ }
8
+ ${o===":host"?t``:a([1,2,3,4].map(e=>`:host([surface-layer="${e}"]) ${o} { --_esp-surface-layer: ${e}; }`).join(`
9
+ `))}
10
+ `}export{f as paintedSurface,l as surfaceLayerAttributes,$ as surfaceLayerColor};
@@ -254,19 +254,11 @@ export type PartialThemeContexts = Record<string, ThemeContext | undefined>;
254
254
  /** Ordered role names, for validation and iteration. */
255
255
  export declare const ROLE_NAMES: readonly RoleName[];
256
256
  /**
257
- * Which semantic tokens each role slot paints, and at which ramp stop.
257
+ * Map role slots to semantic tokens and ramp stops.
258
258
  *
259
- * This is the compilation table: it turns five designer-facing roles
260
- * into the twenty-three engine-room tokens. `dangerText` is absent by
261
- * design — the status family is reserved and keeps its own source.
262
- *
263
- * The `accent` role has no body-text slot on purpose. "Rose is
264
- * decorative only" is a structural guarantee here, not a comment: text
265
- * that must come from the accent family comes through `accent.text`,
266
- * the deepened variant a designer picked for legibility. `accent.hover`
267
- * lets a hover change *family*, not just lightness — "plum link, rose
268
- * hover" is an ordinary brand rule (ESP0172); absent, `linkHover` keeps
269
- * following `accent.text` exactly as before.
259
+ * `dangerText` stays outside the roles layer because status meanings are reserved.
260
+ * Accent body copy must use the legible `accent.text` slot. `accent.hover` can
261
+ * select a different family; without it, hovered links follow `accent.text`.
270
262
  */
271
263
  export declare const ROLE_TOKEN_PLAN: Readonly<Record<RoleName, Readonly<Record<string, ReadonlyArray<[SemanticColorName, LightnessKey]>>>>>;
272
264
  /**
@@ -323,13 +315,10 @@ interface CompileRoleOptions {
323
315
  actionSurfacePole?: (source: MappingSource, lightness: number) => "dark" | "light";
324
316
  }
325
317
  /**
326
- * Compile roles into semantic mappings.
318
+ * Compile declared roles into semantic mappings.
327
319
  *
328
- * Only the tokens a declared role owns are emitted, so a theme that
329
- * declares no roles compiles to nothing and every existing theme keeps
330
- * its exact output. Token-level `semanticMappings` layer over the
331
- * result — the engine room stays available for the cases roles do not
332
- * reach.
320
+ * A theme with no roles produces no role overrides. Token-level
321
+ * `semanticMappings` take precedence over the compiled result.
333
322
  */
334
323
  export declare function compileRoles(roles: ThemeRoles, lightness: LightnessMap, baseMappings: SemanticMappings, options?: CompileRoleOptions): Partial<SemanticMappings>;
335
324
  /**
@@ -2,10 +2,8 @@ import { type PropertyValues } from "lit";
2
2
  import { EspalierElementBase } from "../shared/esp-element-base.js";
3
3
  import { type EspalierFormField } from "../form-item/esp-form-item.js";
4
4
  /**
5
- * A range slider for selecting numeric values. Built entirely from
6
- * custom elements with ARIA `role="slider"` — no native
7
- * `<input type="range">` — for consistent cross-browser styling and
8
- * intentional touch interaction.
5
+ * A numeric range slider with ARIA `role="slider"`, keyboard support,
6
+ * and separate touch and pointer behavior.
9
7
  *
10
8
  * On touch devices, only dragging the thumb changes the value.
11
9
  * Tapping the track is ignored so the user can scroll the page
@@ -7,8 +7,7 @@ declare const STACK_ALIGNS: readonly ["start", "center", "end", "stretch"];
7
7
  export type EspalierAlign = (typeof STACK_ALIGNS)[number];
8
8
  export { STACK_GAPS, STACK_ALIGNS };
9
9
  /**
10
- * A vertical flow: children stack in a column with a themed gap —
11
- * "column, gap X" without writing flexbox (ADR-010's micro half).
10
+ * Stacks children vertically with a themed gap.
12
11
  *
13
12
  * ```html
14
13
  * <esp-stack gap="medium">
@@ -1,10 +1,8 @@
1
1
  import { EspalierElementBase } from "../shared/esp-element-base.js";
2
2
  import { type EspalierFormField } from "../form-item/esp-form-item.js";
3
3
  /**
4
- * A toggle switch for boolean on/off values. Uses a CSS-only
5
- * track-and-thumb design with a smooth sliding transition.
6
- * Functionally equivalent to a checkbox but visually communicates
7
- * an immediate state change rather than a deferred selection.
4
+ * An on/off switch for settings that take effect immediately. Use a
5
+ * checkbox when the choice should be applied with a later form submission.
8
6
  *
9
7
  * ```html
10
8
  * <esp-box>
@@ -6,6 +6,9 @@ import { EspalierElementBase } from "../shared/esp-element-base.js";
6
6
  * generated automatically from each child's `label` attribute.
7
7
  * Only one tab panel is visible at a time.
8
8
  *
9
+ * A field fills one layer above the surface it sits on.
10
+ * Use `surface-layer="1|2|3|4"` to select the default painted layer.
11
+ *
9
12
  * ```html
10
13
  * <esp-tab-group>
11
14
  * <esp-tab label="Overview">
@@ -1,4 +1,4 @@
1
- var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,a):e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(l,t,a,e);else for(var n=l.length-1;n>=0;n--)(o=l[n])&&(r=(s<3?o(r):s>3?o(t,a,r):o(t,a))||r);return s>3&&r&&Object.defineProperty(t,a,r),r};import{css as u,html as c,nothing as v}from"lit";import{customElement as f,property as g,state as m}from"lit/decorators.js";import{createRef as y,ref as w}from"lit/directives/ref.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ESP_EVENTS as x}from"../shared/events.js";import{EspalierTab as p}from"./esp-tab.js";import{disabledControl as T}from"../shared/style-fragments.js";let i=class extends b{constructor(){super(...arguments),this.panelsSlot=y(),this.disabled=!1,this.tabData=[]}getTabs(){const t=this.panelsSlot.value?Array.from(this.panelsSlot.value.assignedElements()).filter(a=>a instanceof p):[];return t.length>0?t:Array.from(this.children).filter(a=>a instanceof p)}syncTabData(){const t=this.getTabs();if(t.length===0){this.tabData=[];return}const a=t.find(e=>e.active&&!e.disabled);if(a)for(const e of t)e!==a&&(e.active=!1);else{const e=t.find(s=>!s.disabled);e?e.active=!0:t[0].active=!0}this.tabData=t.map((e,s)=>{const r=`esp-tab-btn-${this.correlationId}-${s}`,o=`esp-tab-panel-${this.correlationId}-${s}`;return e.panelId=o,e.ariaLabelledBy=r,{label:e.label,active:e.active,disabled:this.disabled||e.disabled,buttonId:r,panelId:o}})}activateTab(t){const a=this.getTabs(),e=a[t];if(!(!e||e.disabled||this.disabled)){for(const s of a)s.active=s===e;this.syncTabData(),this.dispatchEvent(new CustomEvent(x.TAB_GROUP_CHANGED,{detail:{index:t,label:e.label},bubbles:!0,composed:!0}))}}handleTabClick(t){this.activateTab(t),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[t]?.buttonId)?.focus()})}handleKeyDown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;t.preventDefault();const e=this.tabData.map((n,h)=>({td:n,i:h})).filter(({td:n})=>!n.disabled).map(({i:n})=>n);if(e.length===0)return;const s=this.tabData.findIndex(n=>n.active),r=e.indexOf(s);let o;switch(t.key){case"ArrowRight":r===-1?o=e[0]:o=e[(r+1)%e.length];break;case"ArrowLeft":r===-1?o=e[e.length-1]:o=e[(r-1+e.length)%e.length];break;case"Home":o=e[0];break;case"End":o=e[e.length-1];break;default:return}this.activateTab(o),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[o]?.buttonId)?.focus()})}handleChildUpdated(){this.syncTabData()}handleSlotChange(){this.syncTabData()}connectedCallback(){super.connectedCallback(),this.syncTabData()}willUpdate(t){super.willUpdate(t),t.has("disabled")&&this.syncTabData()}render(){return c`
1
+ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,a):e,o;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")r=Reflect.decorate(l,t,a,e);else for(var n=l.length-1;n>=0;n--)(o=l[n])&&(r=(s<3?o(r):s>3?o(t,a,r):o(t,a))||r);return s>3&&r&&Object.defineProperty(t,a,r),r};import{paintedSurface as u}from"../shared/surface-layer.js";import{css as v,html as c,nothing as f}from"lit";import{customElement as g,property as m,state as y}from"lit/decorators.js";import{createRef as w,ref as x}from"lit/directives/ref.js";import{EspalierElementBase as b}from"../shared/esp-element-base.js";import{ESP_EVENTS as T}from"../shared/events.js";import{EspalierTab as p}from"./esp-tab.js";import{disabledControl as k}from"../shared/style-fragments.js";let i=class extends b{constructor(){super(...arguments),this.panelsSlot=w(),this.disabled=!1,this.tabData=[]}getTabs(){const t=this.panelsSlot.value?Array.from(this.panelsSlot.value.assignedElements()).filter(a=>a instanceof p):[];return t.length>0?t:Array.from(this.children).filter(a=>a instanceof p)}syncTabData(){const t=this.getTabs();if(t.length===0){this.tabData=[];return}const a=t.find(e=>e.active&&!e.disabled);if(a)for(const e of t)e!==a&&(e.active=!1);else{const e=t.find(s=>!s.disabled);e?e.active=!0:t[0].active=!0}this.tabData=t.map((e,s)=>{const r=`esp-tab-btn-${this.correlationId}-${s}`,o=`esp-tab-panel-${this.correlationId}-${s}`;return e.panelId=o,e.ariaLabelledBy=r,{label:e.label,active:e.active,disabled:this.disabled||e.disabled,buttonId:r,panelId:o}})}activateTab(t){const a=this.getTabs(),e=a[t];if(!(!e||e.disabled||this.disabled)){for(const s of a)s.active=s===e;this.syncTabData(),this.dispatchEvent(new CustomEvent(T.TAB_GROUP_CHANGED,{detail:{index:t,label:e.label},bubbles:!0,composed:!0}))}}handleTabClick(t){this.activateTab(t),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[t]?.buttonId)?.focus()})}handleKeyDown(t){if(!["ArrowLeft","ArrowRight","Home","End"].includes(t.key))return;t.preventDefault();const e=this.tabData.map((n,h)=>({td:n,i:h})).filter(({td:n})=>!n.disabled).map(({i:n})=>n);if(e.length===0)return;const s=this.tabData.findIndex(n=>n.active),r=e.indexOf(s);let o;switch(t.key){case"ArrowRight":r===-1?o=e[0]:o=e[(r+1)%e.length];break;case"ArrowLeft":r===-1?o=e[e.length-1]:o=e[(r-1+e.length)%e.length];break;case"Home":o=e[0];break;case"End":o=e[e.length-1];break;default:return}this.activateTab(o),this.updateComplete.then(()=>{this.shadowRoot?.getElementById(this.tabData[o]?.buttonId)?.focus()})}handleChildUpdated(){this.syncTabData()}handleSlotChange(){this.syncTabData()}connectedCallback(){super.connectedCallback(),this.syncTabData()}willUpdate(t){super.willUpdate(t),t.has("disabled")&&this.syncTabData()}render(){return c`
2
2
  <div class="tab-container">
3
3
  <div class="tab-list" role="tablist" part="tab-list" @keydown=${this.handleKeyDown}>
4
4
  ${this.tabData.map((t,a)=>c`
@@ -9,7 +9,7 @@ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnP
9
9
  part="tab-button"
10
10
  aria-selected=${t.active?"true":"false"}
11
11
  aria-controls=${t.panelId}
12
- aria-disabled=${t.disabled?"true":v}
12
+ aria-disabled=${t.disabled?"true":f}
13
13
  tabindex=${t.active?"0":"-1"}
14
14
  ?disabled=${t.disabled}
15
15
  @click=${()=>this.handleTabClick(a)}
@@ -20,13 +20,13 @@ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnP
20
20
  </div>
21
21
  <div class="panels" part="panels">
22
22
  <slot
23
- ${w(this.panelsSlot)}
23
+ ${x(this.panelsSlot)}
24
24
  @slotchange=${this.handleSlotChange}
25
25
  @esp-internal-tab-updated=${this.handleChildUpdated}
26
26
  ></slot>
27
27
  </div>
28
28
  </div>
29
- `}};i.styles=[...b.styles,T(".tab-button[disabled]"),u`
29
+ `}};i.styles=[...b.styles,u(1),k(".tab-button[disabled]"),v`
30
30
  :host {
31
31
  display: block;
32
32
  --_esp-tab-resolved-button-hover: var(
@@ -45,7 +45,7 @@ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnP
45
45
  .tab-container {
46
46
 
47
47
  --_esp-tab-inner-radius: max(0px, calc(var(--esp-size-border-radius) - 1px));
48
- background-color: var(--esp-tab-color-background, var(--esp-color-layer-1));
48
+ background-color: var(--esp-tab-color-background, var(--_esp-surface-background));
49
49
  border-radius: var(--esp-size-border-radius);
50
50
  box-shadow: 1px 1px 4px var(--esp-color-shadow);
51
51
  border: 1px solid var(--esp-tab-color-border, var(--esp-color-border));
@@ -56,7 +56,7 @@ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnP
56
56
  .tab-list {
57
57
  display: flex;
58
58
  overflow-x: auto;
59
- background-color: var(--esp-tab-color-strip-background, var(--esp-color-layer-1));
59
+ background-color: var(--esp-tab-color-strip-background, var(--_esp-surface-background));
60
60
  border-bottom: 1px solid var(--esp-tab-color-border, var(--esp-color-border));
61
61
  border-start-start-radius: var(--_esp-tab-inner-radius);
62
62
  border-start-end-radius: var(--_esp-tab-inner-radius);
@@ -119,4 +119,4 @@ var d=function(l,t,a,e){var s=arguments.length,r=s<3?t:e===null?e=Object.getOwnP
119
119
  .panels {
120
120
 
121
121
  }
122
- `],d([g({type:Boolean,reflect:!0})],i.prototype,"disabled",void 0),d([m()],i.prototype,"tabData",void 0),i=d([f("esp-tab-group")],i);export{i as EspalierTabGroup};
122
+ `],d([m({type:Boolean,reflect:!0})],i.prototype,"disabled",void 0),d([y()],i.prototype,"tabData",void 0),i=d([g("esp-tab-group")],i);export{i as EspalierTabGroup};
@@ -44,6 +44,7 @@ var o=function(a,e,t,n){var p=arguments.length,r=p<3?e:n===null?n=Object.getOwnP
44
44
  }
45
45
 
46
46
  .tooltip-content {
47
+ --_esp-surface-layer: 1;
47
48
 
48
49
  white-space: normal;
49
50
  overflow-wrap: anywhere;
@@ -127,11 +127,6 @@ export declare function buildWebTreePath({ parentPath, segment, rootPath, }: Esp
127
127
  * For static declarative node definitions, see
128
128
  * [`<esp-tree-item>`](/components/tree/item/).
129
129
  *
130
- * The name is apt: an espalier is a tree trained flat against a frame,
131
- * so the visual language — branches trained to vertical guide wires,
132
- * grafting a new shoot onto an existing limb — is the component's own
133
- * metaphor.
134
- *
135
130
  * ## Data-driven first, composition-capable
136
131
  *
137
132
  * Bind a hierarchy to the `nodes` property for the primary, data-driven
@@ -311,6 +311,7 @@ var d=function(c,e,t,i){var s=arguments.length,o=s<3?e:i===null?i=Object.getOwnP
311
311
  }
312
312
 
313
313
  .row {
314
+ --_esp-surface-layer: 1;
314
315
  background-color: var(--esp-tree-row-bg, var(--esp-color-layer-1));
315
316
  border: 1px solid var(--esp-tree-row-border-color, var(--esp-color-border));
316
317
  border-radius: var(--esp-size-border-radius);
@@ -334,6 +335,7 @@ var d=function(c,e,t,i){var s=arguments.length,o=s<3?e:i===null?i=Object.getOwnP
334
335
  }
335
336
 
336
337
  .row:hover {
338
+ --_esp-surface-layer: 2;
337
339
  background-color: var(--esp-tree-hover-bg, var(--esp-color-layer-2));
338
340
  border-color: oklch(
339
341
  from var(--esp-tree-row-border-color, var(--esp-color-border)) calc(l * 1.1) c h
@@ -341,6 +343,7 @@ var d=function(c,e,t,i){var s=arguments.length,o=s<3?e:i===null?i=Object.getOwnP
341
343
  }
342
344
 
343
345
  .row.selected {
346
+ --_esp-surface-layer: 3;
344
347
  border-color: var(--esp-color-primary);
345
348
  background-color: var(--esp-tree-selected-bg, var(--esp-color-layer-3));
346
349
  }