@taprootio/espalier 2.17.0 → 2.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -73,3 +73,4 @@ export { type TypeaheadFetchItems } from "./pickers/types.js";
73
73
  export { type EspalierTheme, type PartialTheme, type VariantColorSource, encodeTheme, parseTheme, mergePartials, layerThemes, buildTaprootLightTheme, buildTaprootDarkTheme, NESTED_THEME_KEYS, } from "./shared/theme.js";
74
74
  export { WEIGHT_LABELS, extractWeights, normalizeWeight, bestAvailableWeight, extractFamily, getFallbackFont, } from "./shared/font-helpers.js";
75
75
  export { getGoogleFonts } from "./font-picker/esp-font-picker.js";
76
+ export { themeFitReport, themeFitRows, printThemeFitReport, type ThemeFitReport, type ThemeFitToken, type ThemeFitApcaAction, type ThemeFitAnchor, type ThemeFitRow, } from "./shared/theme-fit-report.js";
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export*from"./box/esp-box.js";export*from"./action-menu/esp-action-menu.js";export*from"./action-menu/esp-action-menu-item.js";export*from"./avatar/esp-avatar.js";export*from"./avatar/esp-profile-chip.js";export*from"./badge/esp-badge.js";export*from"./checkbox/esp-checkbox.js";export*from"./checkbox/esp-checkbox-group.js";export*from"./data-cell/esp-data-cell.js";export*from"./radio-button/esp-radio-button.js";export*from"./radio-button/esp-radio-button-group.js";export*from"./repeater/esp-repeater.js";export*from"./breadcrumbs/esp-breadcrumbs.js";export*from"./button/esp-button.js";export*from"./button/esp-button-group.js";export*from"./color-picker/esp-color-picker.js";export*from"./flyout/esp-flyout.js";export*from"./form/esp-form.js";export*from"./form-item/esp-form-item.js";export*from"./help/esp-help-button.js";export*from"./help/esp-help-provider.js";export*from"./header/index.js";export*from"./page/esp-page.js";export*from"./popover/esp-popover.js";export*from"./dialog/esp-dialog.js";export*from"./empty-state/esp-empty-state.js";export*from"./image-upload/esp-image-upload.js";export*from"./file-upload/esp-file-upload.js";export*from"./font-picker/esp-font-picker.js";export*from"./focus-picker/esp-focus-picker.js";export*from"./footer/index.js";export*from"./grid/esp-grid.js";export*from"./image/esp-image.js";export*from"./image/image-focus.js";export*from"./lightbox/esp-lightbox.js";export*from"./info/esp-info.js";export*from"./input/esp-input.js";export*from"./textarea/esp-textarea.js";export*from"./pickers/esp-pick-one.js";export*from"./pickers/esp-pick-some.js";export*from"./pickers/esp-picker-menu.js";export*from"./pickers/esp-picker-item.js";export*from"./root/esp-root.js";export*from"./menu/index.js";export*from"./burger/esp-burger.js";export*from"./date-picker/esp-date-picker.js";export*from"./details/esp-details.js";export*from"./details/esp-details-group.js";export*from"./tabs/esp-tab.js";export*from"./tabs/esp-tab-group.js";export*from"./slider/esp-slider.js";export*from"./switch/esp-switch.js";export*from"./toaster/esp-toaster.js";export*from"./tooltip/esp-tooltip.js";export*from"./progress/esp-progress.js";export*from"./search/esp-search.js";export*from"./status-indicator/esp-status-indicator.js";export*from"./tree/esp-tree.js";export*from"./tree/esp-tree-item.js";import{DEFAULT_ICON_SPRITE_URL as xo,DEFAULT_ICON_VIEW_BOX as ao,INTENT_VARIANTS as lo,normalizeIntentVariant as so,getIconHref as To,getIconHrefForHost as Eo,getIconSpriteUrl as io}from"./shared/intent-values.js";import{EspalierElementBase as Io}from"./shared/esp-element-base.js";import{VALIDITY_CHANGED_EVENT as ho}from"./shared/validation.js";import{FormFieldController as Fo}from"./shared/form-field-controller.js";import{traverseToClosest as uo}from"./shared/utilities.js";import{showToast as Lo}from"./shared/toast-events.js";import{showFlyout as Do,closeFlyout as Ho}from"./shared/flyout-events.js";import{requestHelp as bo}from"./shared/help-events.js";import{getEspBus as Co}from"./shared/bus-events.js";export*from"./shared/events.js";import{getImageDetails as Wo,releasePreviewUrl as Bo}from"./image-upload/image-helpers.js";import{calculatePhotoLayout as vo}from"./shared/justified-layout.js";import{encodeTheme as Go,parseTheme as Oo,mergePartials as Ro,layerThemes as ko,buildTaprootLightTheme as zo,buildTaprootDarkTheme as Yo,NESTED_THEME_KEYS as qo}from"./shared/theme.js";import{WEIGHT_LABELS as Mo,extractWeights as Xo,normalizeWeight as jo,bestAvailableWeight as Jo,extractFamily as Qo,getFallbackFont as Zo}from"./shared/font-helpers.js";import{getGoogleFonts as or}from"./font-picker/esp-font-picker.js";export{xo as DEFAULT_ICON_SPRITE_URL,ao as DEFAULT_ICON_VIEW_BOX,Io as EspalierElementBase,Fo as FormFieldController,lo as INTENT_VARIANTS,qo as NESTED_THEME_KEYS,ho as VALIDITY_CHANGED_EVENT,Mo as WEIGHT_LABELS,Jo as bestAvailableWeight,Yo as buildTaprootDarkTheme,zo as buildTaprootLightTheme,vo as calculatePhotoLayout,Ho as closeFlyout,Go as encodeTheme,Qo as extractFamily,Xo as extractWeights,Co as getEspBus,Zo as getFallbackFont,or as getGoogleFonts,To as getIconHref,Eo as getIconHrefForHost,io as getIconSpriteUrl,Wo as getImageDetails,ko as layerThemes,Ro as mergePartials,so as normalizeIntentVariant,jo as normalizeWeight,Oo as parseTheme,Bo as releasePreviewUrl,bo as requestHelp,Do as showFlyout,Lo as showToast,uo as traverseToClosest};
1
+ export*from"./box/esp-box.js";export*from"./action-menu/esp-action-menu.js";export*from"./action-menu/esp-action-menu-item.js";export*from"./avatar/esp-avatar.js";export*from"./avatar/esp-profile-chip.js";export*from"./badge/esp-badge.js";export*from"./checkbox/esp-checkbox.js";export*from"./checkbox/esp-checkbox-group.js";export*from"./data-cell/esp-data-cell.js";export*from"./radio-button/esp-radio-button.js";export*from"./radio-button/esp-radio-button-group.js";export*from"./repeater/esp-repeater.js";export*from"./breadcrumbs/esp-breadcrumbs.js";export*from"./button/esp-button.js";export*from"./button/esp-button-group.js";export*from"./color-picker/esp-color-picker.js";export*from"./flyout/esp-flyout.js";export*from"./form/esp-form.js";export*from"./form-item/esp-form-item.js";export*from"./help/esp-help-button.js";export*from"./help/esp-help-provider.js";export*from"./header/index.js";export*from"./page/esp-page.js";export*from"./popover/esp-popover.js";export*from"./dialog/esp-dialog.js";export*from"./empty-state/esp-empty-state.js";export*from"./image-upload/esp-image-upload.js";export*from"./file-upload/esp-file-upload.js";export*from"./font-picker/esp-font-picker.js";export*from"./focus-picker/esp-focus-picker.js";export*from"./footer/index.js";export*from"./grid/esp-grid.js";export*from"./image/esp-image.js";export*from"./image/image-focus.js";export*from"./lightbox/esp-lightbox.js";export*from"./info/esp-info.js";export*from"./input/esp-input.js";export*from"./textarea/esp-textarea.js";export*from"./pickers/esp-pick-one.js";export*from"./pickers/esp-pick-some.js";export*from"./pickers/esp-picker-menu.js";export*from"./pickers/esp-picker-item.js";export*from"./root/esp-root.js";export*from"./menu/index.js";export*from"./burger/esp-burger.js";export*from"./date-picker/esp-date-picker.js";export*from"./details/esp-details.js";export*from"./details/esp-details-group.js";export*from"./tabs/esp-tab.js";export*from"./tabs/esp-tab-group.js";export*from"./slider/esp-slider.js";export*from"./switch/esp-switch.js";export*from"./toaster/esp-toaster.js";export*from"./tooltip/esp-tooltip.js";export*from"./progress/esp-progress.js";export*from"./search/esp-search.js";export*from"./status-indicator/esp-status-indicator.js";export*from"./tree/esp-tree.js";export*from"./tree/esp-tree-item.js";import{DEFAULT_ICON_SPRITE_URL as xo,DEFAULT_ICON_VIEW_BOX as ao,INTENT_VARIANTS as lo,normalizeIntentVariant as so,getIconHref as io,getIconHrefForHost as To,getIconSpriteUrl as Eo}from"./shared/intent-values.js";import{EspalierElementBase as go}from"./shared/esp-element-base.js";import{VALIDITY_CHANGED_EVENT as Fo}from"./shared/validation.js";import{FormFieldController as _o}from"./shared/form-field-controller.js";import{traverseToClosest as uo}from"./shared/utilities.js";import{showToast as Lo}from"./shared/toast-events.js";import{showFlyout as Do,closeFlyout as Ho}from"./shared/flyout-events.js";import{requestHelp as So}from"./shared/help-events.js";import{getEspBus as yo}from"./shared/bus-events.js";export*from"./shared/events.js";import{getImageDetails as Vo,releasePreviewUrl as Wo}from"./image-upload/image-helpers.js";import{calculatePhotoLayout as Bo}from"./shared/justified-layout.js";import{encodeTheme as vo,parseTheme as Go,mergePartials as Oo,layerThemes as ko,buildTaprootLightTheme as zo,buildTaprootDarkTheme as Yo,NESTED_THEME_KEYS as qo}from"./shared/theme.js";import{WEIGHT_LABELS as Mo,extractWeights as Xo,normalizeWeight as jo,bestAvailableWeight as Jo,extractFamily as Qo,getFallbackFont as Zo}from"./shared/font-helpers.js";import{getGoogleFonts as or}from"./font-picker/esp-font-picker.js";import{themeFitReport as er,themeFitRows as tr,printThemeFitReport as mr}from"./shared/theme-fit-report.js";export{xo as DEFAULT_ICON_SPRITE_URL,ao as DEFAULT_ICON_VIEW_BOX,go as EspalierElementBase,_o as FormFieldController,lo as INTENT_VARIANTS,qo as NESTED_THEME_KEYS,Fo as VALIDITY_CHANGED_EVENT,Mo as WEIGHT_LABELS,Jo as bestAvailableWeight,Yo as buildTaprootDarkTheme,zo as buildTaprootLightTheme,Bo as calculatePhotoLayout,Ho as closeFlyout,vo as encodeTheme,Qo as extractFamily,Xo as extractWeights,yo as getEspBus,Zo as getFallbackFont,or as getGoogleFonts,io as getIconHref,To as getIconHrefForHost,Eo as getIconSpriteUrl,Vo as getImageDetails,ko as layerThemes,Oo as mergePartials,so as normalizeIntentVariant,jo as normalizeWeight,Go as parseTheme,mr as printThemeFitReport,Wo as releasePreviewUrl,So as requestHelp,Do as showFlyout,Lo as showToast,er as themeFitReport,tr as themeFitRows,uo as traverseToClosest};
@@ -9,7 +9,7 @@ var n=function(d,t,e,i){var l=arguments.length,s=l<3?t:i===null?i=Object.getOwnP
9
9
  style=${P(i)}
10
10
  >
11
11
  ${t.slotNodes?.map(l=>l.cloneNode(!0))}
12
- </esp-picker-item>`},this.internals.role="listbox"}connectedCallback(){super.connectedCallback(),this.setAttribute("popover","manual"),this.hasAttribute("role")||this.setAttribute("role","listbox")}updated(t){super.updated(t),t.has("multiSelect")&&(this.internals.ariaMultiSelectable=String(this.multiSelect),this.setAttribute("aria-multiselectable",String(this.multiSelect))),t.has("label")&&(this.internals.ariaLabel=this.label,this.label?this.setAttribute("aria-label",this.label):this.removeAttribute("aria-label")),(t.has("virtualizedItemsPool")||t.has("loading"))&&this.maxAvailableHeight>0&&this.matches(":popover-open")&&this.resizeAndHighlight(t.has("virtualizedItemsPool"))}get pickerItems(){return this.virtualizedItemsPool}set pickerItems(t){const e=this.virtualizedItemsPool.filter(s=>s.selected).map(s=>s.value);this.virtualizedItemsPool=t;const i=t.filter(s=>s.selected),l=i.map(s=>s.value);(e.length!==l.length||e.some((s,r)=>s!==l[r]))&&this.dispatchEvent(new CustomEvent("selection-changed",{detail:i,bubbles:!0,composed:!0}))}setHighlight(t){const e=this.virtualizedItemsPool;if(e.length===0)return;(this.highlightIndex<0||this.highlightIndex>e.length-1)&&(this.highlightIndex=t);const i=this.virtualizerRef.value;i&&i.scrollToIndex(this.highlightIndex,"nearest"),this.applyHighlightClass()}async setHighlightAsync(t){const e=this.virtualizedItemsPool;if(e.length===0)return;(this.highlightIndex<0||this.highlightIndex>e.length-1)&&(this.highlightIndex=t);const i=this.virtualizerRef.value;i&&(i.scrollToIndex(this.highlightIndex,"nearest"),await i.layoutComplete),this.applyHighlightClass()}applyHighlightClass(){this.clearHighlight();const t=this.getHighlightedElement();t&&t.classList.add(c)}clearHighlight(){const t=this.virtualizerRef.value;if(t)for(const e of t.querySelectorAll(`esp-picker-item.${c}`))e.classList.remove(c)}resetHighlight(){this.clearHighlight();const t=this.virtualizedItemsPool.find(e=>e.selected);this.highlightIndex=t?this.virtualizedItemsPool.indexOf(t):-1}applyHighlightWithRetry(t){if(!this.isConnected||!this.matches(":popover-open"))return;this.clearHighlight();const e=this.getHighlightedElement();if(e){e.classList.add(c);return}t>0&&requestAnimationFrame(()=>this.applyHighlightWithRetry(t-1))}getHighlightedElement(){if(this.highlightIndex<0)return null;const t=this.virtualizerRef.value;if(!t)return null;const e=t.querySelectorAll("esp-picker-item");for(const i of e)if(this.virtualizedItemsPool.findIndex(s=>s.value===i.value&&s.text===i.text)===this.highlightIndex)return i;return null}pickItem(t){for(const i of this.pickerItems)i===t?i.selected=!i.selected:this.multiSelect||(i.selected=!1);const e=this.virtualizedItemsPool.indexOf(t);if(e!==-1){this.highlightIndex=e,this.clearHighlight();const i=this.getHighlightedElement();i&&i.classList.add(c)}this.pickerItems=[...this.pickerItems],this.dispatchEvent(new CustomEvent("selection-changed",{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0})),this.multiSelect||this.dispatchEvent(new CustomEvent("close-menu",{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0}))}selectItemByIndex(t){const e=Number.isInteger(t)?this.virtualizedItemsPool[t]:void 0;return e?(this.pickItem(e),!0):!1}getPickerItemElementAtPoint(t,e){const i=this.shadowRoot?.querySelectorAll("esp-picker-item[data-picker-index]");if(!i)return null;for(const l of i){const s=l.getBoundingClientRect();if(t>=s.left&&t<=s.right&&e>=s.top&&e<=s.bottom)return l}return null}selectPickerItemElement(t){return t?this.selectItemByIndex(Number(t.dataset.pickerIndex)):!1}selectItemAtPoint(t,e){return this.selectPickerItemElement(this.getPickerItemElementAtPoint(t,e))}selectItemFromPointerEvent(t){const e=t.composedPath().find(l=>l instanceof HTMLElement&&l.matches("esp-picker-item[data-picker-index]"));return this.selectPickerItemElement(e??this.getPickerItemElementAtPoint(t.clientX,t.clientY))?(t.preventDefault(),t.stopPropagation(),!0):!1}positionSelf(t){const e=t.getBoundingClientRect(),{height:i}=u(),{spaceAbove:l,spaceBelow:s}=f(e,i),r=Math.max(Math.max(l,s)-75,0);this.maxAvailableHeight=r,this.lastViewportHeight=i,this.style.setProperty("height",`${r}px`),this.style.setProperty("min-width",`${e.width}px`),this.style.setProperty("left",`${e.left}px`),this.style.removeProperty("top"),this.style.removeProperty("bottom"),l>s?this.style.setProperty("bottom",`${i-e.top}px`):this.style.setProperty("top",`${e.bottom}px`),this.classList.remove("visible"),this.matches(":popover-open")||this.showPopover();const o=this.pickerItems.find(a=>a.selected);this.highlightIndex=o?this.pickerItems.indexOf(o):0,this.setHighlightAsync(0).then(()=>{requestAnimationFrame(()=>{this.shrinkToFit(r),this.widenToFitContent(e),this.classList.add("visible")})})}async resizeAndHighlight(t){try{await this.updateComplete}catch{return}if(!this.isConnected||!this.matches(":popover-open"))return;const e=this.virtualizerRef.value;if(!e){requestAnimationFrame(()=>{if(!this.isConnected)return;const s=this.shadowRoot?.querySelector(".status-message");if(s){const r=Math.min(s.scrollHeight,this.maxAvailableHeight);this.style.setProperty("height",`${r}px`)}});return}try{const s=e.layoutComplete;s&&await s}catch{return}if(!this.isConnected||!this.matches(":popover-open")||(e.scrollTop=0,this.sizeToContent(this.maxAvailableHeight),!t))return;try{const s=e.layoutComplete;s&&await s}catch{return}if(!this.isConnected||!this.matches(":popover-open"))return;const i=this.virtualizedItemsPool;if(i.length===0)return;const l=i.findIndex(s=>s.selected);l>=0?this.highlightIndex=l:this.highlightIndex>=i.length?this.highlightIndex=i.length-1:this.highlightIndex<0&&(this.highlightIndex=0);try{e.scrollToIndex(this.highlightIndex,"nearest")}catch{}try{const s=e.layoutComplete;s&&await s}catch{return}!this.isConnected||!this.matches(":popover-open")||this.applyHighlightWithRetry(3)}sizeToContent(t){const e=this.measureContentHeight();e>0&&this.style.setProperty("height",`${Math.min(e,t)}px`)}shrinkToFit(t){const e=this.measureContentHeight();e>2&&e<t&&this.style.setProperty("height",`${e}px`)}measureContentHeight(){const t=this.virtualizerRef.value;if(!t)return 0;const e=t.querySelectorAll("esp-picker-item");if(e.length===0)return 0;const i=getComputedStyle(this),l=(parseFloat(i.borderTopWidth)||0)+(parseFloat(i.borderBottomWidth)||0),s=this.virtualizedItemsPool.length;if(e.length<s)return t.scrollHeight+l;t.scrollTop=0;const r=t.getBoundingClientRect();return e[e.length-1].getBoundingClientRect().bottom-r.top+l}widenToFitContent(t){const e=this.virtualizerRef.value;if(!e)return;const i=e.querySelectorAll("esp-picker-item");let l=t.width;for(const s of i)l=Math.max(l,s.scrollWidth);if(l+=2,l>t.width){const{width:s}=u(),r=Math.min(l,s-t.left);this.style.setProperty("width",`${r}px`)}}updatePosition(t){const e=t.getBoundingClientRect(),{height:i}=u();if(i!==this.lastViewportHeight){const{spaceAbove:r,spaceBelow:o}=f(e,i),a=Math.max(Math.max(r,o)-75,0);this.maxAvailableHeight=a,this.lastViewportHeight=i,(parseFloat(this.style.getPropertyValue("height"))||0)>a&&this.style.setProperty("height",`${a}px`),this.sizeToContent(a)}this.style.setProperty("left",`${e.left}px`);const l=e.top,s=i-e.bottom;l>s?(this.style.removeProperty("top"),this.style.setProperty("bottom",`${i-e.top}px`)):(this.style.removeProperty("bottom"),this.style.setProperty("top",`${e.bottom}px`))}hideMenu(){this.classList.remove("visible");try{this.hidePopover()}catch{}}doKeyboardNav(t){const e=this.virtualizedItemsPool;if(e.length!==0)switch(t){case"ArrowDown":this.highlightIndex+=1,this.setHighlight(0);break;case"ArrowUp":this.highlightIndex-=1,this.setHighlight(e.length-1);break;case"Home":this.highlightIndex=0,this.setHighlight(0);break;case"End":this.highlightIndex=e.length-1,this.setHighlight(e.length-1);break;case"Enter":if(this.highlightIndex===-1)return;this.pickItem(e[this.highlightIndex]);break}}render(){return this.loading?p`<div class="status-message">Searching…</div>`:this.virtualizedItemsPool.length===0&&this.emptyMessage?p`<div class="status-message">${this.emptyMessage}</div>`:p`<lit-virtualizer
12
+ </esp-picker-item>`},this.internals.role="listbox"}connectedCallback(){super.connectedCallback(),this.setAttribute("popover","manual"),this.hasAttribute("role")||this.setAttribute("role","listbox")}updated(t){super.updated(t),t.has("multiSelect")&&(this.internals.ariaMultiSelectable=String(this.multiSelect),this.setAttribute("aria-multiselectable",String(this.multiSelect))),t.has("label")&&(this.internals.ariaLabel=this.label,this.label?this.setAttribute("aria-label",this.label):this.removeAttribute("aria-label")),(t.has("virtualizedItemsPool")||t.has("loading"))&&this.maxAvailableHeight>0&&this.matches(":popover-open")&&this.resizeAndHighlight(t.has("virtualizedItemsPool"))}get pickerItems(){return this.virtualizedItemsPool}set pickerItems(t){const e=this.virtualizedItemsPool.filter(s=>s.selected).map(s=>s.value);this.virtualizedItemsPool=t;const i=t.filter(s=>s.selected),l=i.map(s=>s.value);(e.length!==l.length||e.some((s,r)=>s!==l[r]))&&this.dispatchEvent(new CustomEvent("selection-changed",{detail:i,bubbles:!0,composed:!0}))}setHighlight(t){const e=this.virtualizedItemsPool;if(e.length===0)return;(this.highlightIndex<0||this.highlightIndex>e.length-1)&&(this.highlightIndex=t);const i=this.virtualizerRef.value;i&&i.scrollToIndex(this.highlightIndex,"nearest"),this.applyHighlightClass()}async setHighlightAsync(t){const e=this.virtualizedItemsPool;if(e.length===0)return;(this.highlightIndex<0||this.highlightIndex>e.length-1)&&(this.highlightIndex=t);const i=this.virtualizerRef.value;if(i)try{const l=i.layoutComplete;l&&await l,i.scrollToIndex(this.highlightIndex,"nearest");const s=i.layoutComplete;s&&await s}catch{return}this.applyHighlightClass()}applyHighlightClass(){this.clearHighlight();const t=this.getHighlightedElement();t&&t.classList.add(c)}clearHighlight(){const t=this.virtualizerRef.value;if(t)for(const e of t.querySelectorAll(`esp-picker-item.${c}`))e.classList.remove(c)}resetHighlight(){this.clearHighlight();const t=this.virtualizedItemsPool.find(e=>e.selected);this.highlightIndex=t?this.virtualizedItemsPool.indexOf(t):-1}applyHighlightWithRetry(t){if(!this.isConnected||!this.matches(":popover-open"))return;this.clearHighlight();const e=this.getHighlightedElement();if(e){e.classList.add(c);return}t>0&&requestAnimationFrame(()=>this.applyHighlightWithRetry(t-1))}getHighlightedElement(){if(this.highlightIndex<0)return null;const t=this.virtualizerRef.value;if(!t)return null;const e=t.querySelectorAll("esp-picker-item");for(const i of e)if(this.virtualizedItemsPool.findIndex(s=>s.value===i.value&&s.text===i.text)===this.highlightIndex)return i;return null}pickItem(t){for(const i of this.pickerItems)i===t?i.selected=!i.selected:this.multiSelect||(i.selected=!1);const e=this.virtualizedItemsPool.indexOf(t);if(e!==-1){this.highlightIndex=e,this.clearHighlight();const i=this.getHighlightedElement();i&&i.classList.add(c)}this.pickerItems=[...this.pickerItems],this.dispatchEvent(new CustomEvent("selection-changed",{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0})),this.multiSelect||this.dispatchEvent(new CustomEvent("close-menu",{detail:this.pickerItems.filter(i=>i.selected),bubbles:!0,composed:!0}))}selectItemByIndex(t){const e=Number.isInteger(t)?this.virtualizedItemsPool[t]:void 0;return e?(this.pickItem(e),!0):!1}getPickerItemElementAtPoint(t,e){const i=this.shadowRoot?.querySelectorAll("esp-picker-item[data-picker-index]");if(!i)return null;for(const l of i){const s=l.getBoundingClientRect();if(t>=s.left&&t<=s.right&&e>=s.top&&e<=s.bottom)return l}return null}selectPickerItemElement(t){return t?this.selectItemByIndex(Number(t.dataset.pickerIndex)):!1}selectItemAtPoint(t,e){return this.selectPickerItemElement(this.getPickerItemElementAtPoint(t,e))}selectItemFromPointerEvent(t){const e=t.composedPath().find(l=>l instanceof HTMLElement&&l.matches("esp-picker-item[data-picker-index]"));return this.selectPickerItemElement(e??this.getPickerItemElementAtPoint(t.clientX,t.clientY))?(t.preventDefault(),t.stopPropagation(),!0):!1}positionSelf(t){const e=t.getBoundingClientRect(),{height:i}=u(),{spaceAbove:l,spaceBelow:s}=f(e,i),r=Math.max(Math.max(l,s)-75,0);this.maxAvailableHeight=r,this.lastViewportHeight=i,this.style.setProperty("height",`${r}px`),this.style.setProperty("min-width",`${e.width}px`),this.style.setProperty("left",`${e.left}px`),this.style.removeProperty("top"),this.style.removeProperty("bottom"),l>s?this.style.setProperty("bottom",`${i-e.top}px`):this.style.setProperty("top",`${e.bottom}px`),this.classList.remove("visible"),this.matches(":popover-open")||this.showPopover();const o=this.pickerItems.find(a=>a.selected);this.highlightIndex=o?this.pickerItems.indexOf(o):0,this.setHighlightAsync(0).then(()=>{requestAnimationFrame(()=>{this.shrinkToFit(r),this.widenToFitContent(e),this.classList.add("visible")})})}async resizeAndHighlight(t){try{await this.updateComplete}catch{return}if(!this.isConnected||!this.matches(":popover-open"))return;const e=this.virtualizerRef.value;if(!e){requestAnimationFrame(()=>{if(!this.isConnected)return;const s=this.shadowRoot?.querySelector(".status-message");if(s){const r=Math.min(s.scrollHeight,this.maxAvailableHeight);this.style.setProperty("height",`${r}px`)}});return}try{const s=e.layoutComplete;s&&await s}catch{return}if(!this.isConnected||!this.matches(":popover-open")||(e.scrollTop=0,this.sizeToContent(this.maxAvailableHeight),!t))return;try{const s=e.layoutComplete;s&&await s}catch{return}if(!this.isConnected||!this.matches(":popover-open"))return;const i=this.virtualizedItemsPool;if(i.length===0)return;const l=i.findIndex(s=>s.selected);l>=0?this.highlightIndex=l:this.highlightIndex>=i.length?this.highlightIndex=i.length-1:this.highlightIndex<0&&(this.highlightIndex=0);try{e.scrollToIndex(this.highlightIndex,"nearest")}catch{}try{const s=e.layoutComplete;s&&await s}catch{return}!this.isConnected||!this.matches(":popover-open")||this.applyHighlightWithRetry(3)}sizeToContent(t){const e=this.measureContentHeight();e>0&&this.style.setProperty("height",`${Math.min(e,t)}px`)}shrinkToFit(t){const e=this.measureContentHeight();e>2&&e<t&&this.style.setProperty("height",`${e}px`)}measureContentHeight(){const t=this.virtualizerRef.value;if(!t)return 0;const e=t.querySelectorAll("esp-picker-item");if(e.length===0)return 0;const i=getComputedStyle(this),l=(parseFloat(i.borderTopWidth)||0)+(parseFloat(i.borderBottomWidth)||0),s=this.virtualizedItemsPool.length;if(e.length<s)return t.scrollHeight+l;t.scrollTop=0;const r=t.getBoundingClientRect();return e[e.length-1].getBoundingClientRect().bottom-r.top+l}widenToFitContent(t){const e=this.virtualizerRef.value;if(!e)return;const i=e.querySelectorAll("esp-picker-item");let l=t.width;for(const s of i)l=Math.max(l,s.scrollWidth);if(l+=2,l>t.width){const{width:s}=u(),r=Math.min(l,s-t.left);this.style.setProperty("width",`${r}px`)}}updatePosition(t){const e=t.getBoundingClientRect(),{height:i}=u();if(i!==this.lastViewportHeight){const{spaceAbove:r,spaceBelow:o}=f(e,i),a=Math.max(Math.max(r,o)-75,0);this.maxAvailableHeight=a,this.lastViewportHeight=i,(parseFloat(this.style.getPropertyValue("height"))||0)>a&&this.style.setProperty("height",`${a}px`),this.sizeToContent(a)}this.style.setProperty("left",`${e.left}px`);const l=e.top,s=i-e.bottom;l>s?(this.style.removeProperty("top"),this.style.setProperty("bottom",`${i-e.top}px`)):(this.style.removeProperty("bottom"),this.style.setProperty("top",`${e.bottom}px`))}hideMenu(){this.classList.remove("visible");try{this.hidePopover()}catch{}}doKeyboardNav(t){const e=this.virtualizedItemsPool;if(e.length!==0)switch(t){case"ArrowDown":this.highlightIndex+=1,this.setHighlight(0);break;case"ArrowUp":this.highlightIndex-=1,this.setHighlight(e.length-1);break;case"Home":this.highlightIndex=0,this.setHighlight(0);break;case"End":this.highlightIndex=e.length-1,this.setHighlight(e.length-1);break;case"Enter":if(this.highlightIndex===-1)return;this.pickItem(e[this.highlightIndex]);break}}render(){return this.loading?p`<div class="status-message">Searching…</div>`:this.virtualizedItemsPool.length===0&&this.emptyMessage?p`<div class="status-message">${this.emptyMessage}</div>`:p`<lit-virtualizer
13
13
  ${b(this.virtualizerRef)}
14
14
  scroller
15
15
  .items=${this.virtualizedItemsPool}
@@ -1 +1 @@
1
- import{parseCssColor as y,serializeOklch as p,gamutMapToSRGB as B,deriveSemantic as C,deriveSemanticWithContrast as x}from"../../shared/color-engine.js";import{generateScaleProperties as I}from"../../shared/scale-engine.js";import{SEMANTIC_COLOR_NAMES as k,LIGHTNESS_KEYS as M,semanticToCSS as m}from"../../shared/theme.js";import{lightnessKeyToCSS as O}from"./lightness-key-to-css.js";import{computeVariants as L,resolveMappingSource as w}from"./compute-variants.js";function R(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function N(o,S){const d=y(o.seedColor);if(!d)return{};const n={};n["--esp-scheme"]=S,n["--esp-seed-color"]=o.seedColor;const e=L(d,o);for(const[a,t]of Object.entries(e))n[`--esp-color-${a}`]=p(B(t));for(const a of M)n[O(a)]=`${Math.round(o.lightness[a]*100)}%`;const u={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}},f=new Set,l=a=>{const t=w(a,e,o.anchors);return t||(f.has(a)||(f.add(a),console.warn(`Espalier theme: color source "${a}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`)),e.primary)},g={};for(const a of k){if(u[a])continue;const t=o.semanticMappings[a],r=o.chroma[a],i=l(t.source),s=o.lightness[t.lightness],c=C(i,s,r.min,r.max);g[a]=c,n[m(a)]=p(c)}for(const a of k){const t=u[a];if(!t)continue;const r=o.semanticMappings[a],i=o.chroma[a],s=l(r.source),c=o.lightness[r.lightness],v=g[t.bg],b=x(s,c,i.min,i.max,v,t.targetLc);g[a]=b,n[m(a)]=p(b)}return Object.assign(n,I(R(o))),o.fontBody&&(n["--esp-font-body"]=o.fontBody),o.fontHeadings&&(n["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(n["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(n["--esp-font-monospace"]=o.fontMonospace),n["--esp-font-weight-body"]=o.fontWeightBody,n["--esp-font-weight-headings"]=o.fontWeightHeadings,n["--esp-font-weight-brand"]=o.fontWeightBrand,n["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(n["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(n["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(n["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(n["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(n["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(n["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(n["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),n}export{N as computeThemeProperties};
1
+ import{parseCssColor as I,serializeOklch as b,gamutMapToSRGB as M,deriveSemantic as O,deriveSemanticWithContrast as R}from"../../shared/color-engine.js";import{generateScaleProperties as x}from"../../shared/scale-engine.js";import{SEMANTIC_COLOR_NAMES as B,LIGHTNESS_KEYS as w,TOKEN_PAIRINGS as T,semanticToCSS as u}from"../../shared/theme.js";import{lightnessKeyToCSS as E}from"./lightness-key-to-css.js";import{computeVariants as L,resolveMappingSource as N}from"./compute-variants.js";function W(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function K(o,C,e){const v=I(o.seedColor);if(!v)return{};const n={};n["--esp-scheme"]=C,n["--esp-seed-color"]=o.seedColor;const f=L(v,o);for(const[a,s]of Object.entries(f))n[`--esp-color-${a}`]=b(M(s));for(const a of w)n[E(a)]=`${Math.round(o.lightness[a]*100)}%`;const m=T,c=new Set,k=a=>{const s=N(a,f,o.anchors);return s||(c.has(a)||(c.add(a),console.warn(`Espalier theme: color source "${a}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`)),f.primary)},l={};for(const a of B){if(m[a])continue;const s=o.semanticMappings[a],r=o.chroma[a],i=k(s.source),g=o.lightness[s.lightness],p=O(i,g,r.min,r.max);if(l[a]=p,n[u(a)]=b(p),e){const t=u(a);e.push({token:a,property:t,resolved:n[t],source:s.source,lightness:s.lightness,sourceResolved:!c.has(s.source),base:i})}}for(const a of B){const s=m[a];if(!s)continue;const r=o.semanticMappings[a],i=o.chroma[a],g=k(r.source),p=o.lightness[r.lightness],t=l[s.bg];let y;const S=R(g,p,i.min,i.max,t,s.targetLc,e&&(d=>{y=d}));if(l[a]=S,n[u(a)]=b(S),e){const d=u(a);e.push({token:a,property:d,resolved:n[d],source:r.source,lightness:r.lightness,sourceResolved:!c.has(r.source),base:g,requested:y,contrast:{against:s.bg,background:t,targetLc:s.targetLc}})}}return Object.assign(n,x(W(o))),o.fontBody&&(n["--esp-font-body"]=o.fontBody),o.fontHeadings&&(n["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(n["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(n["--esp-font-monospace"]=o.fontMonospace),n["--esp-font-weight-body"]=o.fontWeightBody,n["--esp-font-weight-headings"]=o.fontWeightHeadings,n["--esp-font-weight-brand"]=o.fontWeightBrand,n["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(n["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(n["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(n["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(n["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(n["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(n["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(n["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),n}export{K as computeThemeProperties};
@@ -1 +1 @@
1
- import{parseCssColor as h,rotateHue as n}from"../../shared/color-engine.js";import{parseAnchorSource as e,resolveAnchorColor as p}from"../../shared/theme.js";const s=.6,u=.85;function y(t,c){const{angles:r,semanticHues:a,variantChroma:o}=c,l=m=>o[m]??t.c,i=Math.min(u,Math.max(s,t.l));return{primary:t,"analogous-left":{l:t.l,c:l("analogous-left"),h:n(t.h,-r.analogous)},"analogous-right":{l:t.l,c:l("analogous-right"),h:n(t.h,r.analogous)},complementary:{l:t.l,c:l("complementary"),h:n(t.h,r.complementary)},"split-complementary-left":{l:t.l,c:l("split-complementary-left"),h:n(t.h,r.complementary-r.splitComplementary)},"split-complementary-right":{l:t.l,c:l("split-complementary-right"),h:n(t.h,r.complementary+r.splitComplementary)},"triadic-left":{l:t.l,c:l("triadic-left"),h:n(t.h,r.triadic)},"triadic-right":{l:t.l,c:l("triadic-right"),h:n(t.h,-r.triadic)},danger:{l:i,c:l("danger"),h:n(a.danger,0)},success:{l:i,c:l("success"),h:n(a.success,0)},warning:{l:i,c:l("warning"),h:n(a.warning,0)}}}function S(t,c,r){const a=e(t);if(!a)return c[t]??null;const o=p(r,a);return o===null?null:h(o)}export{y as computeVariants,S as resolveMappingSource};
1
+ import{computeVariants as e}from"../../shared/variant-engine.js";import{resolveMappingSource as t}from"../../shared/variant-engine.js";export{e as computeVariants,t as resolveMappingSource};
@@ -1 +1 @@
1
- const S=Math.PI/180,h=1e-4,$=50,m="[+-]?(?:\\d+|\\d*\\.\\d+)(?:[eE][+-]?\\d+)?",i="[\\t\\n\\f\\r ]",X=new RegExp(i+"*,"+i+"*"),y=new RegExp(i+"+");function G(t){return t.replace(/\/\*[\s\S]*?(?:\*\/|$)/g," ").replace(/^[\t\n\f\r ]+|[\t\n\f\r ]+$/g,"")}const L={"":1,deg:1,grad:.9,rad:180/Math.PI,turn:360},H=.4,U=new RegExp("^oklch\\("+i+"*("+m+")(%?)"+i+"+("+m+")(%?)"+i+"+("+m+")(deg|grad|rad|turn)?"+i+"*\\)$","i");function V(t){const n=t.h*S;return{L:t.l,a:t.c*Math.cos(n),b:t.c*Math.sin(n)}}function W(t){const n=t.L+.3963377774*t.a+.2158037573*t.b,r=t.L-.1055613458*t.a-.0638541728*t.b,e=t.L-.0894841775*t.a-1.291485548*t.b,o=n*n*n,u=r*r*r,c=e*e*e;return{r:4.0767416621*o-3.3077115913*u+.2309699292*c,g:-1.2684380046*o+2.6097574011*u-.3413193965*c,b:-.0041960863*o-.7034186147*u+1.707614701*c}}function T(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function z(t){return{r:T(t.r),g:T(t.g),b:T(t.b)}}function Y(t){return t.r>=-h&&t.r<=1+h&&t.g>=-h&&t.g<=1+h&&t.b>=-h&&t.b<=1+h}function g(t){return Math.max(0,Math.min(1,t))}function q(t){const n=G(t).match(U);if(!n)return null;let r=parseFloat(n[1]);n[2]==="%"&&(r/=100);let e=parseFloat(n[3]);n[4]==="%"&&(e=e/100*H);const o=parseFloat(n[5])*L[(n[6]??"").toLowerCase()];return!isFinite(r)||!isFinite(e)||!isFinite(o)?null:{l:Math.max(0,Math.min(1,r)),c:Math.max(0,e),h:(o%360+360)%360}}function ct(t){const n=p(t.l,6),r=p(t.c,6),e=p((t.h%360+360)%360,4);return`oklch(${n} ${r} ${e})`}function _(t){return z(W(V(t)))}function x(t){return Y(_(t))}function M(t){if(t.c<=h||x(t))return{...t};let n=0,r=t.c,e={...t};for(let o=0;o<$;o++){const u=(n+r)/2;if(e={l:t.l,c:u,h:t.h},x(e)?n=u:r=u,r-n<h)break}return{l:t.l,c:n,h:t.h}}function K(t,n,r){const e={l:t.l,c:Math.max(n,Math.min(r,t.c)),h:t.h};return M(e)}const C=.022,w=.012,O=.022,b=.57,k=.56,P=1.14,A=.001,R=.027;function B(t){const n=Math.pow(g(t.r),2.4),r=Math.pow(g(t.g),2.4),e=Math.pow(g(t.b),2.4);return .2126729*n+.7151522*r+.072175*e}function I(t,n){const r=_(M(t)),e=_(M(n));let o=B(r),u=B(e);if(o=o>C?o:o+Math.pow(C-o,1.414),u=u>C?u:u+Math.pow(C-u,1.414),Math.abs(u-o)<A)return 0;let c;if(u>o){const s=Math.pow(u,k),a=Math.pow(o,b);if(c=(s-a)*P,c<A)return 0;c=c<R?c-c*O*R:c-O}else{const s=Math.pow(u,k),a=Math.pow(o,b);if(c=(s-a)*P,c>-A)return 0;c=c>-R?c-c*w*R:c+w}return c*100}function j(t,n,r=60){let e=M({...t}),o=Math.abs(I(e,n));if(o>=r)return e;const u=n.l>.5,c=.01,s=u?0:1;for(let a=0;a<100;a++){if(u?e.l=Math.max(s,e.l-c):e.l=Math.min(s,e.l+c),e=M(e),o=Math.abs(I(e,n)),o>=r)return e;if(e.l<=0||e.l>=1)break}return e}function st(t,n){return((t+n)%360+360)%360}function J(t,n,r,e){return K({l:n,c:t.c,h:t.h},r,e)}function at(t,n,r,e,o,u=60){const c=J(t,n,r,e);return j(c,o,u)}function E(t){return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Q(t){const n=E(t.r),r=E(t.g),e=E(t.b),o=Math.cbrt(.4122214708*n+.5363325363*r+.0514459929*e),u=Math.cbrt(.2119034982*n+.6806995451*r+.1073969566*e),c=Math.cbrt(.0883024619*n+.2817188376*r+.6299787005*e);return{L:.2104542553*o+.793617785*u-.0040720468*c,a:1.9779984951*o-2.428592205*u+.4505937099*c,b:.0259040371*o+.7827717662*u-.808675766*c}}function Z(t){const n=Math.sqrt(t.a*t.a+t.b*t.b),r=(Math.atan2(t.b,t.a)/S%360+360)%360;return{l:t.L,c:n,h:r}}function tt(t){const n=p(t.c,4);return{l:p(t.l,3),c:n,h:n===0?0:p(t.h,1)}}function f(t){return Math.round(g(t)*255)}function d(t){const n=Z(Q(t)),r=t.r===t.g&&t.g===t.b?{l:n.l,c:0,h:0}:n,e=tt(r);if(x(e)){const o=_(e);if(f(o.r)===f(t.r)&&f(o.g)===f(t.g)&&f(o.b)===f(t.b))return e}return r}function nt(t){const n=t.slice(1);if(!/^[0-9a-f]+$/i.test(n))return null;if(n.length===3){const[r,e,o]=n.split("").map(u=>parseInt(u+u,16));return{r:r/255,g:e/255,b:o/255}}return n.length===6?{r:parseInt(n.slice(0,2),16)/255,g:parseInt(n.slice(2,4),16)/255,b:parseInt(n.slice(4,6),16)/255}:null}function F(t,n){const r=t.match(new RegExp("^"+n+"\\("+i+"*([^)]*?)"+i+"*\\)$","i"));if(!r)return null;const e=r[1];if(e.includes("/"))return null;const o=e.includes(","),u=e.split(o?X:y);return u.length!==3||u.some(c=>c.length===0)?null:{args:u,legacy:o}}const rt=new RegExp("^("+m+")([a-z%]*)$","i");function D(t){const n=t.match(rt);if(!n)return null;const r=parseFloat(n[1]);return isFinite(r)?{value:r,unit:n[2].toLowerCase()}:null}function et(t){if(t.unit!==""&&t.unit!=="%")return null;const n=t.unit==="%"?t.value/100:t.value/255;return Math.max(0,Math.min(1,n))}function ot(t){const n=L[t.unit];return n===void 0?null:t.value*n}function N(t){return t.unit!==""&&t.unit!=="%"?null:Math.max(0,Math.min(1,t.value/100))}function ut(t,n,r){const e=(t%360+360)%360,o=u=>{const c=(u+e/30)%12,s=n*Math.min(r,1-r);return r-s*Math.max(-1,Math.min(c-3,9-c,1))};return{r:o(0),g:o(8),b:o(4)}}const it='"#rrggbb", "#rgb", "rgb(\u2026)", "hsl(\u2026)", "oklch(\u2026)"';function lt(t){const n=G(t);if(n.startsWith("#")){const r=nt(n);return r?d(r):null}if(/^oklch\(/i.test(n))return q(n);if(/^rgba?\(/i.test(n)){const r=F(n,"rgba?");if(!r)return null;const e=r.args.map(D);if(e.some(l=>l===null))return null;const o=e;if(r.legacy&&new Set(o.map(l=>l.unit)).size>1)return null;const u=o.map(et);if(u.some(l=>l===null))return null;const[c,s,a]=u;return d({r:c,g:s,b:a})}if(/^hsla?\(/i.test(n)){const r=F(n,"hsla?");if(!r)return null;const e=r.args.map(D);if(e.some(v=>v===null))return null;const[o,u,c]=e;if(r.legacy&&(u.unit!=="%"||c.unit!=="%"))return null;const s=ot(o),a=N(u),l=N(c);return s===null||a===null||l===null?null:d(ut(s,a,l))}return null}function p(t,n){const r=Math.pow(10,n);return Math.round(t*r)/r}export{it as ACCEPTED_COLOR_FORMS,I as apcaContrast,K as clampChromaAndGamutMap,J as deriveSemantic,at as deriveSemanticWithContrast,j as ensureContrast,M as gamutMapToSRGB,x as isInSRGBGamut,_ as oklchToSRGB,lt as parseCssColor,q as parseOklch,st as rotateHue,ct as serializeOklch};
1
+ const S=Math.PI/180,h=1e-4,X=50,m="[+-]?(?:\\d+|\\d*\\.\\d+)(?:[eE][+-]?\\d+)?",i="[\\t\\n\\f\\r ]",y=new RegExp(i+"*,"+i+"*"),H=new RegExp(i+"+");function G(t){return t.replace(/\/\*[\s\S]*?(?:\*\/|$)/g," ").replace(/^[\t\n\f\r ]+|[\t\n\f\r ]+$/g,"")}const b={"":1,deg:1,grad:.9,rad:180/Math.PI,turn:360},U=.4,V=new RegExp("^oklch\\("+i+"*("+m+")(%?)"+i+"+("+m+")(%?)"+i+"+("+m+")(deg|grad|rad|turn)?"+i+"*\\)$","i");function x(t){const n=t.h*S;return{L:t.l,a:t.c*Math.cos(n),b:t.c*Math.sin(n)}}function W(t){const n=t.L+.3963377774*t.a+.2158037573*t.b,r=t.L-.1055613458*t.a-.0638541728*t.b,e=t.L-.0894841775*t.a-1.291485548*t.b,o=n*n*n,c=r*r*r,u=e*e*e;return{r:4.0767416621*o-3.3077115913*c+.2309699292*u,g:-1.2684380046*o+2.6097574011*c-.3413193965*u,b:-.0041960863*o-.7034186147*c+1.707614701*u}}function A(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function z(t){return{r:A(t.r),g:A(t.g),b:A(t.b)}}function Y(t){return t.r>=-h&&t.r<=1+h&&t.g>=-h&&t.g<=1+h&&t.b>=-h&&t.b<=1+h}function g(t){return Math.max(0,Math.min(1,t))}function q(t){const n=G(t).match(V);if(!n)return null;let r=parseFloat(n[1]);n[2]==="%"&&(r/=100);let e=parseFloat(n[3]);n[4]==="%"&&(e=e/100*U);const o=parseFloat(n[5])*b[(n[6]??"").toLowerCase()];return!isFinite(r)||!isFinite(e)||!isFinite(o)?null:{l:Math.max(0,Math.min(1,r)),c:Math.max(0,e),h:(o%360+360)%360}}function ut(t){const n=p(t.l,6),r=p(t.c,6),e=p((t.h%360+360)%360,4);return`oklch(${n} ${r} ${e})`}function _(t){return z(W(x(t)))}function T(t){return Y(_(t))}function M(t){if(t.c<=h||T(t))return{...t};let n=0,r=t.c,e={...t};for(let o=0;o<X;o++){const c=(n+r)/2;if(e={l:t.l,c,h:t.h},T(e)?n=c:r=c,r-n<h)break}return{l:t.l,c:n,h:t.h}}function K(t,n,r){const e={l:t.l,c:Math.max(n,Math.min(r,t.c)),h:t.h};return M(e)}const C=.022,O=.012,w=.022,k=.57,B=.56,P=1.14,d=.001,R=.027;function I(t){const n=Math.pow(g(t.r),2.4),r=Math.pow(g(t.g),2.4),e=Math.pow(g(t.b),2.4);return .2126729*n+.7151522*r+.072175*e}function F(t,n){const r=_(M(t)),e=_(M(n));let o=I(r),c=I(e);if(o=o>C?o:o+Math.pow(C-o,1.414),c=c>C?c:c+Math.pow(C-c,1.414),Math.abs(c-o)<d)return 0;let u;if(c>o){const s=Math.pow(c,B),a=Math.pow(o,k);if(u=(s-a)*P,u<d)return 0;u=u<R?u-u*w*R:u-w}else{const s=Math.pow(c,B),a=Math.pow(o,k);if(u=(s-a)*P,u>-d)return 0;u=u>-R?u-u*O*R:u+O}return u*100}function j(t,n,r=60){let e=M({...t}),o=Math.abs(F(e,n));if(o>=r)return e;const c=n.l>.5,u=.01,s=c?0:1;for(let a=0;a<100;a++){if(c?e.l=Math.max(s,e.l-u):e.l=Math.min(s,e.l+u),e=M(e),o=Math.abs(F(e,n)),o>=r)return e;if(e.l<=0||e.l>=1)break}return e}function st(t,n){return((t+n)%360+360)%360}function at(t,n){const r=x(t),e=x(n),o=r.L-e.L,c=r.a-e.a,u=r.b-e.b;return Math.sqrt(o*o+c*c+u*u)}function J(t,n,r,e){return K({l:n,c:t.c,h:t.h},r,e)}function it(t,n,r,e,o,c=60,u){const s=J(t,n,r,e);return u?.(s),j(s,o,c)}function E(t){return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Q(t){const n=E(t.r),r=E(t.g),e=E(t.b),o=Math.cbrt(.4122214708*n+.5363325363*r+.0514459929*e),c=Math.cbrt(.2119034982*n+.6806995451*r+.1073969566*e),u=Math.cbrt(.0883024619*n+.2817188376*r+.6299787005*e);return{L:.2104542553*o+.793617785*c-.0040720468*u,a:1.9779984951*o-2.428592205*c+.4505937099*u,b:.0259040371*o+.7827717662*c-.808675766*u}}function Z(t){const n=Math.sqrt(t.a*t.a+t.b*t.b),r=(Math.atan2(t.b,t.a)/S%360+360)%360;return{l:t.L,c:n,h:r}}function tt(t){const n=p(t.c,4);return{l:p(t.l,3),c:n,h:n===0?0:p(t.h,1)}}function f(t){return Math.round(g(t)*255)}function L(t){const n=Z(Q(t)),r=t.r===t.g&&t.g===t.b?{l:n.l,c:0,h:0}:n,e=tt(r);if(T(e)){const o=_(e);if(f(o.r)===f(t.r)&&f(o.g)===f(t.g)&&f(o.b)===f(t.b))return e}return r}function nt(t){const n=t.slice(1);if(!/^[0-9a-f]+$/i.test(n))return null;if(n.length===3){const[r,e,o]=n.split("").map(c=>parseInt(c+c,16));return{r:r/255,g:e/255,b:o/255}}return n.length===6?{r:parseInt(n.slice(0,2),16)/255,g:parseInt(n.slice(2,4),16)/255,b:parseInt(n.slice(4,6),16)/255}:null}function D(t,n){const r=t.match(new RegExp("^"+n+"\\("+i+"*([^)]*?)"+i+"*\\)$","i"));if(!r)return null;const e=r[1];if(e.includes("/"))return null;const o=e.includes(","),c=e.split(o?y:H);return c.length!==3||c.some(u=>u.length===0)?null:{args:c,legacy:o}}const rt=new RegExp("^("+m+")([a-z%]*)$","i");function N(t){const n=t.match(rt);if(!n)return null;const r=parseFloat(n[1]);return isFinite(r)?{value:r,unit:n[2].toLowerCase()}:null}function et(t){if(t.unit!==""&&t.unit!=="%")return null;const n=t.unit==="%"?t.value/100:t.value/255;return Math.max(0,Math.min(1,n))}function ot(t){const n=b[t.unit];return n===void 0?null:t.value*n}function v(t){return t.unit!==""&&t.unit!=="%"?null:Math.max(0,Math.min(1,t.value/100))}function ct(t,n,r){const e=(t%360+360)%360,o=c=>{const u=(c+e/30)%12,s=n*Math.min(r,1-r);return r-s*Math.max(-1,Math.min(u-3,9-u,1))};return{r:o(0),g:o(8),b:o(4)}}const lt='"#rrggbb", "#rgb", "rgb(\u2026)", "hsl(\u2026)", "oklch(\u2026)"';function ht(t){const n=G(t);if(n.startsWith("#")){const r=nt(n);return r?L(r):null}if(/^oklch\(/i.test(n))return q(n);if(/^rgba?\(/i.test(n)){const r=D(n,"rgba?");if(!r)return null;const e=r.args.map(N);if(e.some(l=>l===null))return null;const o=e;if(r.legacy&&new Set(o.map(l=>l.unit)).size>1)return null;const c=o.map(et);if(c.some(l=>l===null))return null;const[u,s,a]=c;return L({r:u,g:s,b:a})}if(/^hsla?\(/i.test(n)){const r=D(n,"hsla?");if(!r)return null;const e=r.args.map(N);if(e.some($=>$===null))return null;const[o,c,u]=e;if(r.legacy&&(c.unit!=="%"||u.unit!=="%"))return null;const s=ot(o),a=v(c),l=v(u);return s===null||a===null||l===null?null:L(ct(s,a,l))}return null}function p(t,n){const r=Math.pow(10,n);return Math.round(t*r)/r}export{lt as ACCEPTED_COLOR_FORMS,F as apcaContrast,K as clampChromaAndGamutMap,at as deltaEOK,J as deriveSemantic,it as deriveSemanticWithContrast,j as ensureContrast,M as gamutMapToSRGB,T as isInSRGBGamut,_ as oklchToSRGB,ht as parseCssColor,q as parseOklch,st as rotateHue,ut as serializeOklch};
@@ -1,4 +1,4 @@
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 x,LitElement as U}from"lit";import{property as y,state as A}from"lit/decorators.js";import{subscribeToRootEvent as g}from"./root-event-subscription.js";import{traverseToClosest as T}from"./utilities.js";import{parseCssColor as L,serializeOklch as k,gamutMapToSRGB as O,deriveSemantic as F,deriveSemanticWithContrast as _}from"./color-engine.js";import{computeVariants as S,resolveMappingSource as z}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as P,semanticToCSS as w}from"./theme.js";import{alignAttributeTextInheritance as D,focusRing as B}from"./style-fragments.js";class n extends U{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=T(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 T(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,o=L(t.seedColor);if(!o)return;const s=S(o,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",k(O(s)));const a=S(s,t),c=n.statusVariantSources.has(e),{textContrast:C}=n,b={},R=i=>z(i,a,t.anchors)??a.primary;for(const i of P){if(C[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),v=R(d),m=t.lightness[l.lightness],u=F(v,m,h.min,h.max);b[i]=u,this.setVariantTokenProperty(w(i),k(u))}for(const i of P){const l=C[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],v=this.effectiveVariantTokenSource(i,h.source,c),m=R(v),u=t.lightness[h.lightness],E=b[l.bg],V=_(m,u,d.min,d.max,E,l.targetLc);b[i]=V,this.setVariantTokenProperty(w(i),k(V))}}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=[B(".esp-field:focus-within","--esp-field-focus-shadow"),D,x`
1
+ var p=function(v,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(v,e,t,o);else for(var c=v.length-1;c>=0;c--)(a=v[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 x,LitElement as A}from"lit";import{property as y,state as U}from"lit/decorators.js";import{subscribeToRootEvent as f}from"./root-event-subscription.js";import{traverseToClosest as T}from"./utilities.js";import{parseCssColor as O,serializeOklch as k,gamutMapToSRGB as F,deriveSemantic as _,deriveSemanticWithContrast as z}from"./color-engine.js";import{computeVariants as S,resolveMappingSource as D}from"../root/helpers/compute-variants.js";import{SEMANTIC_COLOR_NAMES as P,TOKEN_PAIRINGS as I,semanticToCSS as w}from"./theme.js";import{alignAttributeTextInheritance as M,focusRing as B}from"./style-fragments.js";class n extends A{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=T(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=[f(e,"seed-color-changed",this.handleSeedColorChanged),f(e,"scheme-changed",this.handleSchemeChanged),f(e,"theme-changed",this.handleThemeChanged),f(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 T(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e){this.clearVariantTokens();return}const t=this.espRoot.activeTheme,o=O(t.seedColor);if(!o)return;const s=S(o,t)[e];if(!s){this.clearVariantTokens();return}this.setVariantTokenProperty("--esp-color-primary",k(F(s)));const a=S(s,t),c=n.statusVariantSources.has(e),{textContrast:C}=n,g={},R=i=>D(i,a,t.anchors)??a.primary;for(const i of P){if(C[i])continue;const l=t.semanticMappings[i],h=t.chroma[i],d=this.effectiveVariantTokenSource(i,l.source,c),b=R(d),m=t.lightness[l.lightness],u=_(b,m,h.min,h.max);g[i]=u,this.setVariantTokenProperty(w(i),k(u))}for(const i of P){const l=C[i];if(!l)continue;const h=t.semanticMappings[i],d=t.chroma[i],b=this.effectiveVariantTokenSource(i,h.source,c),m=R(b),u=t.lightness[h.lightness],E=g[l.bg],V=z(m,u,d.min,d.max,E,l.targetLc);g[i]=V,this.setVariantTokenProperty(w(i),k(V))}}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=I,n.statusVariantSources=new Set(["danger","success","warning"]),n.semanticActionTokens=new Set(["actionBackground","actionText"]),n.styles=[B(".esp-field:focus-within","--esp-field-focus-shadow"),M,x`
2
2
  :host {
3
3
 
4
4
  --_esp-field-resolved-hover-bg: var(
@@ -122,4 +122,4 @@ var p=function(f,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=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([A()],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};
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};
@@ -0,0 +1,162 @@
1
+ /**
2
+ * @module theme-fit-report
3
+ *
4
+ * Dev-mode explanation of what the theme pipeline did to a theme
5
+ * (ESP0163).
6
+ *
7
+ * Two pipeline mechanisms move a token away from the value a designer
8
+ * wrote down, and both are silent:
9
+ *
10
+ * - **APCA enforcement** (ADR-002) shifts the lightness of a text token
11
+ * until it clears its Lc target against its background pair. Fitting
12
+ * the SHY brand moved three tokens and reported none of them.
13
+ * - **Brand anchors** (ADR-015) resolve a `anchor:<name>[.<slot>]`
14
+ * source to a declared swatch, then re-light it from the mapping's
15
+ * ramp stop — so the emitted color is a relative of the swatch, not
16
+ * the swatch.
17
+ *
18
+ * The result is a mock that says one color and a render that says
19
+ * another, with no record of the step in between. This module produces
20
+ * that record.
21
+ *
22
+ * ## Sharing the derivation, not repeating it
23
+ *
24
+ * The report **cannot** disagree with the pipeline, because it does not
25
+ * compute any token value:
26
+ *
27
+ * - `resolved` is read back out of the property record
28
+ * `computeThemeProperties` returns — it is the emitted custom
29
+ * property's value, not a re-derivation of it.
30
+ * - `requested` is the pre-enforcement binding `deriveSemanticWithContrast`
31
+ * hands to its `onRequested` observer, i.e. the exact value
32
+ * `ensureContrast` then consumed.
33
+ *
34
+ * Only the *descriptive* numbers are computed here — the achieved Lc
35
+ * scores and the ΔE to a declared anchor — and each of those calls the
36
+ * same engine function the pipeline uses.
37
+ *
38
+ * Nothing runs unless a report is asked for: `computeThemeProperties`
39
+ * takes the trace sink as an optional argument and does no reporting
40
+ * work when it is absent.
41
+ *
42
+ * @example
43
+ * ```ts
44
+ * import { themeFitReport, printThemeFitReport } from './theme-fit-report.js';
45
+ *
46
+ * const report = themeFitReport(mergeTheme(DEFAULT_LIGHT_THEME, brand), 'light');
47
+ * printThemeFitReport(report); // console.table
48
+ * report.adjustedTokens; // ['linkHover']
49
+ * ```
50
+ */
51
+ import { type EspalierTheme, type LightnessKey, type MappingSource, type SemanticColorName } from "./theme.js";
52
+ /** What APCA enforcement did to one token. */
53
+ export interface ThemeFitApcaAction {
54
+ /** The requested value, as an `oklch()` string. */
55
+ from: string;
56
+ /** The emitted value. */
57
+ to: string;
58
+ /** The minimum |Lc| the pairing requires. */
59
+ targetLc: number;
60
+ /** The semantic token supplying the background. */
61
+ against: SemanticColorName;
62
+ /** That background's value. */
63
+ againstColor: string;
64
+ /** |Lc| the requested value achieved against that background. */
65
+ fromLc: number;
66
+ /** |Lc| the emitted value achieves against that background. */
67
+ toLc: number;
68
+ }
69
+ /** How far the emitted token landed from the brand swatch it names. */
70
+ export interface ThemeFitAnchor {
71
+ /** The declared reference — `rose` or `rose.hover`. */
72
+ reference: string;
73
+ /** The anchor's declared color, as an `oklch()` string. */
74
+ color: string;
75
+ /**
76
+ * ΔE-OK between the declared anchor and the emitted token. Expect a
77
+ * non-zero number even on a perfect fit: lightness always comes from
78
+ * the mapping's ramp stop, so a swatch used as a source is re-lit by
79
+ * design (ADR-015).
80
+ */
81
+ deltaE: number;
82
+ }
83
+ /** One semantic token's trip through the pipeline. */
84
+ export interface ThemeFitToken {
85
+ /** The semantic token name. */
86
+ token: SemanticColorName;
87
+ /** The custom property it is emitted as. */
88
+ property: string;
89
+ /** The mapping's declared source. */
90
+ source: MappingSource;
91
+ /** The lightness ramp stop the mapping selected. */
92
+ lightness: LightnessKey;
93
+ /** The value the mapping asked for, before contrast enforcement. */
94
+ requested: string;
95
+ /** The value actually emitted. */
96
+ resolved: string;
97
+ /** `true` when enforcement moved the token — `requested !== resolved`. */
98
+ adjusted: boolean;
99
+ /**
100
+ * `false` when the source could not be resolved and the seed stood in.
101
+ * A theme that passes `validateTheme` never reports this.
102
+ */
103
+ sourceResolved: boolean;
104
+ /** Present when the source is a resolved anchor reference. */
105
+ anchor?: ThemeFitAnchor;
106
+ /** Present for the text tokens APCA enforcement guards. */
107
+ apca?: ThemeFitApcaAction;
108
+ }
109
+ /**
110
+ * A theme's fit report — the stable JSON shape the docs site renders.
111
+ */
112
+ export interface ThemeFitReport {
113
+ /** The scheme the theme was computed for. */
114
+ scheme: "light" | "dark";
115
+ /** The theme's seed color, as declared. */
116
+ seedColor: string;
117
+ /**
118
+ * The theme's declared anchors, flattened to the reference strings a
119
+ * mapping uses: `{ "rose": "oklch(…)", "rose.hover": "oklch(…)" }`.
120
+ */
121
+ anchors: Record<string, string>;
122
+ /** Every semantic token, in the pipeline's derivation order. */
123
+ tokens: ThemeFitToken[];
124
+ /** The tokens APCA enforcement moved — the headline of the report. */
125
+ adjustedTokens: SemanticColorName[];
126
+ }
127
+ /** One `console.table` row. */
128
+ export interface ThemeFitRow {
129
+ token: string;
130
+ source: string;
131
+ requested: string;
132
+ resolved: string;
133
+ /** The APCA pairing and what it did; empty for unenforced tokens. */
134
+ apca: string;
135
+ /** The anchor reference and its ΔE; empty for non-anchor sources. */
136
+ anchor: string;
137
+ }
138
+ /**
139
+ * Build the fit report for a resolved theme.
140
+ *
141
+ * Runs the real pipeline once with a trace sink attached and describes
142
+ * what it did. An unparseable seed produces an empty token list, exactly
143
+ * as it produces an empty property record.
144
+ *
145
+ * @param theme A resolved theme (as `mergeTheme` returns).
146
+ * @param scheme The scheme to compute.
147
+ */
148
+ export declare function themeFitReport(theme: EspalierTheme, scheme: "light" | "dark"): ThemeFitReport;
149
+ /**
150
+ * Render a report as `console.table` rows.
151
+ *
152
+ * Exposed separately from {@link printThemeFitReport} so a host can put
153
+ * the same rows somewhere other than the console.
154
+ */
155
+ export declare function themeFitRows(report: ThemeFitReport): ThemeFitRow[];
156
+ /**
157
+ * Print a fit report to the console — the common case.
158
+ *
159
+ * One summary line naming the scheme and the tokens enforcement moved,
160
+ * then a `console.table` of every token.
161
+ */
162
+ export declare function printThemeFitReport(report: ThemeFitReport): void;
@@ -0,0 +1 @@
1
+ import{apcaContrast as d,deltaEOK as f,parseOklch as u,serializeOklch as n}from"./color-engine.js";import{parseAnchorSource as l}from"./theme.js";import{computeThemeProperties as h}from"../root/helpers/compute-theme-properties.js";function A(e,o){const s=[];h(e,o,s);const r=s.map(v);return{scheme:o,seedColor:e.seedColor,anchors:m(e.anchors),tokens:r,adjustedTokens:r.filter(t=>t.adjusted).map(t=>t.token)}}function p(e){return e.tokens.map(o=>({token:o.token,source:o.source,requested:o.requested,resolved:o.resolved,apca:$(o),anchor:g(o)}))}function R(e){const o=e.adjustedTokens.length>0?`APCA moved ${e.adjustedTokens.join(", ")}`:"APCA moved nothing";console.info(`Espalier theme fit \u2014 ${e.scheme} scheme, seed ${e.seedColor}. ${o}.`),console.table(p(e))}function a(e,o){const s=Math.pow(10,o);return Math.round(e*s)/s}function i(e,o){return o===void 0?e:`${e}.${o}`}function m(e){const o={};for(const[s,r]of Object.entries(e)){if(typeof r=="string"){o[s]=r;continue}for(const[t,c]of Object.entries(r))o[t==="color"?s:i(s,t)]=c}return o}function v(e){const o=u(e.resolved),s=e.requested===void 0?e.resolved:n(e.requested),r={token:e.token,property:e.property,source:e.source,lightness:e.lightness,requested:s,resolved:e.resolved,adjusted:s!==e.resolved,sourceResolved:e.sourceResolved},t=l(e.source);if(t&&e.sourceResolved&&(r.anchor={reference:i(t.name,t.slot),color:n(e.base),deltaE:a(f(e.base,o),4)}),e.contrast){const c=e.contrast.background;r.apca={from:s,to:e.resolved,targetLc:e.contrast.targetLc,against:e.contrast.against,againstColor:n(c),fromLc:a(Math.abs(d(u(s),c)),1),toLc:a(Math.abs(d(o,c)),1)}}return r}function $(e){if(!e.apca)return"";const{targetLc:o,against:s,fromLc:r,toLc:t}=e.apca;return e.adjusted?`Lc ${o} vs ${s} \u2014 pushed from Lc ${r} to Lc ${t}`:`Lc ${o} vs ${s} \u2014 met at Lc ${r}`}function g(e){return e.anchor?`${e.anchor.reference} \u0394E ${e.anchor.deltaE}`:e.sourceResolved?"":"unresolved \u2014 seed used"}export{R as printThemeFitReport,A as themeFitReport,p as themeFitRows};
File without changes
@@ -148,6 +148,100 @@ export interface SemanticMapping {
148
148
  }
149
149
  /** Full mapping table — one entry per semantic color token. */
150
150
  export type SemanticMappings = Record<SemanticColorName, SemanticMapping>;
151
+ /**
152
+ * The designer-facing color roles.
153
+ *
154
+ * `semantic-groups.md` has always described these groups and then warned
155
+ * that exposing the nineteen raw tokens is "handing users the engine
156
+ * room instead of the dashboard" — but the groups were documentation
157
+ * only. Roles make them addressable: a sentence a designer would say
158
+ * becomes a line of theme.
159
+ *
160
+ * - `canvas` — the page and its raised surfaces
161
+ * - `ink` — body copy, with a `heading` slot for titles
162
+ * - `accent` — decoration (rules, icons, hover washes), with a `text`
163
+ * slot for the deepened variant that may carry copy
164
+ * - `action` — filled action surfaces; its paired ink derives
165
+ * automatically (see {@link ROLE_PAIRED_INK})
166
+ * - `structure` — borders and shadows
167
+ *
168
+ * `status` is deliberately absent: the danger/success/warning families
169
+ * carry meaning through fixed hues (ADR-004) and are not a brand
170
+ * decision.
171
+ */
172
+ export type RoleName = "canvas" | "ink" | "accent" | "action" | "structure";
173
+ /**
174
+ * A role binding: a color source, or an object with the base `color`
175
+ * plus role-specific slots.
176
+ *
177
+ * Sources are the same vocabulary mappings use — a geometric family, a
178
+ * status family, or an `anchor:<name>` reference (ADR-015).
179
+ */
180
+ export type RoleSlotName = {
181
+ canvas: never;
182
+ ink: "heading";
183
+ accent: "text";
184
+ action: "ink";
185
+ structure: never;
186
+ };
187
+ export type RoleBinding<R extends RoleName = RoleName> = MappingSource | ({
188
+ color: MappingSource;
189
+ } & Partial<Record<RoleSlotName[R], MappingSource>>);
190
+ /**
191
+ * The roles a theme declares. Every role is optional, and each one
192
+ * admits only its own slots — `ink.heading`, `accent.text`,
193
+ * `action.ink` — so the structural claims the roles layer makes are
194
+ * checked by the type system, not only by validateTheme.
195
+ */
196
+ export type ThemeRoles = {
197
+ [R in RoleName]?: RoleBinding<R>;
198
+ };
199
+ /** Ordered role names, for validation and iteration. */
200
+ export declare const ROLE_NAMES: readonly RoleName[];
201
+ /**
202
+ * Which semantic tokens each role slot paints, and at which ramp stop.
203
+ *
204
+ * This is the compilation table: it turns five designer-facing roles
205
+ * into the nineteen engine-room tokens. `dangerText` is absent by
206
+ * design — the status family is reserved and keeps its own source.
207
+ *
208
+ * The `accent` role has no body-text slot on purpose. "Rose is
209
+ * decorative only" is a structural guarantee here, not a comment: text
210
+ * that must come from the accent family comes through `accent.text`,
211
+ * the deepened variant a designer picked for legibility.
212
+ */
213
+ export declare const ROLE_TOKEN_PLAN: Readonly<Record<RoleName, Readonly<Record<string, ReadonlyArray<[SemanticColorName, LightnessKey]>>>>>;
214
+ /**
215
+ * Ink slots that derive from another role when the theme does not
216
+ * declare them.
217
+ *
218
+ * A role that paints a surface must also answer "what writes on it".
219
+ * `action.ink` defaults to the canvas color: the ink paired with a
220
+ * filled action is the page ground, and APCA enforcement against
221
+ * `actionBackground` then guarantees it is legible — which is exactly
222
+ * how "white on plum for reversed sections" becomes one theme line
223
+ * instead of a hand-picked hex.
224
+ */
225
+ export declare const ROLE_PAIRED_INK: Readonly<Record<string, {
226
+ role: RoleName;
227
+ slot: string;
228
+ }>>;
229
+ interface CompileRoleOptions {
230
+ /** Token mappings declared explicitly at this merge boundary. */
231
+ explicitMappings?: Partial<SemanticMappings>;
232
+ /** Exact maximum paired-ink contrast of an action surface candidate. */
233
+ actionSurfaceContrast?: (source: MappingSource, stop: LightnessKey) => number;
234
+ }
235
+ /**
236
+ * Compile roles into semantic mappings.
237
+ *
238
+ * Only the tokens a declared role owns are emitted, so a theme that
239
+ * declares no roles compiles to nothing and every existing theme keeps
240
+ * its exact output. Token-level `semanticMappings` layer over the
241
+ * result — the engine room stays available for the cases roles do not
242
+ * reach.
243
+ */
244
+ export declare function compileRoles(roles: ThemeRoles, lightness: LightnessMap, baseMappings: SemanticMappings, options?: CompileRoleOptions): Partial<SemanticMappings>;
151
245
  /** The complete, resolved Espalier theme. */
152
246
  export interface EspalierTheme {
153
247
  /**
@@ -284,6 +378,13 @@ export interface EspalierTheme {
284
378
  * of bending hue angles. See {@link ThemeAnchors} and ADR-015.
285
379
  */
286
380
  anchors: ThemeAnchors;
381
+ /**
382
+ * Designer-facing color roles, compiled into
383
+ * {@link EspalierTheme.semanticMappings} at merge time. Empty by
384
+ * default; token-level mappings layer over whatever roles produce.
385
+ * See {@link ThemeRoles} and ADR-016.
386
+ */
387
+ roles: ThemeRoles;
287
388
  /** Optional CSS `background-image` for the page surface. */
288
389
  pageBackgroundImage?: string;
289
390
  /** Opacity (0–1) for the page background image. */
@@ -318,6 +419,29 @@ export interface ThemeValidationResult {
318
419
  /** Soft issues — the theme will work but values are unusual. */
319
420
  warnings: string[];
320
421
  }
422
+ /**
423
+ * Which semantic tokens are ink, what surface each sits on, and the
424
+ * APCA contrast each must clear.
425
+ *
426
+ * This pairing lived as an identical hardcoded table inside both
427
+ * `compute-theme-properties.ts` and `esp-element-base.ts` — invisible to
428
+ * themes and duplicated in exactly the way this repository's adoption
429
+ * rules exist to prevent. It belongs to the model: every serious system
430
+ * makes the surface/ink pair the unit designers see (Material's
431
+ * `on-primary`, shadcn's `-foreground`), and the roles layer derives an
432
+ * action's ink from it rather than asking a designer to hand-pick a
433
+ * legible color.
434
+ *
435
+ * Lc targets follow the APCA guidelines (ADR-002):
436
+ * 90 → body text at any size
437
+ * 75 → 16 px+ text (UI labels, links, body)
438
+ * 60 → 24 px+ bold / 28 px+ normal (headings, carets, decorative)
439
+ */
440
+ type TokenPairing = Readonly<{
441
+ bg: SemanticColorName;
442
+ targetLc: number;
443
+ }>;
444
+ export declare const TOKEN_PAIRINGS: Readonly<Record<"actionText", TokenPairing> & Partial<Record<SemanticColorName, TokenPairing>>>;
321
445
  /** Ordered list of all semantic color token names. */
322
446
  export declare const SEMANTIC_COLOR_NAMES: readonly SemanticColorName[];
323
447
  /** Valid color-source identifiers for {@link SemanticMapping.source}. */
@@ -438,7 +562,7 @@ export declare function validateTheme(base64: string): ThemeValidationResult;
438
562
  * and therefore need key-by-key merging instead of wholesale
439
563
  * replacement when combining two {@link PartialTheme} objects.
440
564
  */
441
- export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
565
+ export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
442
566
  /**
443
567
  * Deep-merge two {@link PartialTheme} objects.
444
568
  *