@taprootio/espalier 2.17.0 → 2.19.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/custom-elements.json +12235 -11311
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -1
- package/dist/pickers/esp-picker-menu.js +1 -1
- package/dist/root/esp-root.d.ts +8 -0
- package/dist/root/esp-root.js +2 -2
- package/dist/root/helpers/compute-theme-properties.js +1 -1
- package/dist/root/helpers/compute-variants.js +1 -1
- package/dist/shared/color-engine.js +1 -1
- package/dist/shared/data-colors.d.ts +122 -0
- package/dist/shared/data-colors.js +1 -0
- package/dist/shared/esp-element-base.js +2 -2
- package/dist/shared/theme-fit-report.d.ts +162 -0
- package/dist/shared/theme-fit-report.js +1 -0
- package/dist/shared/theme-fit-trace.js +0 -0
- package/dist/shared/theme.d.ts +147 -2
- package/dist/shared/theme.js +1 -1
- package/dist/shared/variant-engine.js +1 -0
- package/espalier.css-data.json +32 -0
- package/espalier.token-manifest.json +49 -1
- package/package.json +5 -1
package/dist/index.d.ts
CHANGED
|
@@ -71,5 +71,7 @@ export { getImageDetails, releasePreviewUrl, type EspalierUploadImage, type Imag
|
|
|
71
71
|
export { calculatePhotoLayout, type LayoutImage, type PhotoRow, } from "./shared/justified-layout.js";
|
|
72
72
|
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
|
+
export { auditDataPalette, generateSequentialRamp, generateDivergingRamp, COLOR_VISION_SIMULATIONS, DATA_SERIES_KEYS, DEFAULT_DATA_PALETTE, DEFAULT_DATA_RAMP_STEPS, DEFAULT_DIVERGING_NEUTRAL, MAX_DATA_RAMP_STEPS, MIN_DATA_COLOR_DISTANCE, MIN_DATA_RAMP_LIGHTNESS_STEP, MIN_DATA_RAMP_STEPS, type ColorVisionSimulation, type DataPalette, type DataPaletteIssue, type DataRamp, type DataRamps, type DataSeriesKey, type DivergingDataRamp, type DivergingRampOptions, type PartialDataRamp, type PartialDataRamps, type SequentialDataRamp, type SequentialRampOptions, } from "./shared/data-colors.js";
|
|
74
75
|
export { WEIGHT_LABELS, extractWeights, normalizeWeight, bestAvailableWeight, extractFamily, getFallbackFont, } from "./shared/font-helpers.js";
|
|
75
76
|
export { getGoogleFonts } from "./font-picker/esp-font-picker.js";
|
|
77
|
+
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
|
|
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 To,INTENT_VARIANTS as ao,normalizeIntentVariant as _o,getIconHref as Ao,getIconHrefForHost as Eo,getIconSpriteUrl as lo}from"./shared/intent-values.js";import{EspalierElementBase as io}from"./shared/esp-element-base.js";import{VALIDITY_CHANGED_EVENT as so}from"./shared/validation.js";import{FormFieldController as go}from"./shared/form-field-controller.js";import{traverseToClosest as Fo}from"./shared/utilities.js";import{showToast as No}from"./shared/toast-events.js";import{showFlyout as ho,closeFlyout as Po}from"./shared/flyout-events.js";import{requestHelp as uo}from"./shared/help-events.js";import{getEspBus as Uo}from"./shared/bus-events.js";export*from"./shared/events.js";import{getImageDetails as Ho,releasePreviewUrl as Vo}from"./image-upload/image-helpers.js";import{calculatePhotoLayout as bo}from"./shared/justified-layout.js";import{encodeTheme as Wo,parseTheme as vo,mergePartials as wo,layerThemes as Bo,buildTaprootLightTheme as Yo,buildTaprootDarkTheme as ko,NESTED_THEME_KEYS as qo}from"./shared/theme.js";import{auditDataPalette as Ko,generateSequentialRamp as Xo,generateDivergingRamp as jo,COLOR_VISION_SIMULATIONS as Jo,DATA_SERIES_KEYS as Qo,DEFAULT_DATA_PALETTE as Zo,DEFAULT_DATA_RAMP_STEPS as $o,DEFAULT_DIVERGING_NEUTRAL as or,MAX_DATA_RAMP_STEPS as rr,MIN_DATA_COLOR_DISTANCE as er,MIN_DATA_RAMP_LIGHTNESS_STEP as tr,MIN_DATA_RAMP_STEPS as mr}from"./shared/data-colors.js";import{WEIGHT_LABELS as fr,extractWeights as xr,normalizeWeight as Tr,bestAvailableWeight as ar,extractFamily as _r,getFallbackFont as Ar}from"./shared/font-helpers.js";import{getGoogleFonts as lr}from"./font-picker/esp-font-picker.js";import{themeFitReport as ir,themeFitRows as Sr,printThemeFitReport as sr}from"./shared/theme-fit-report.js";export{Jo as COLOR_VISION_SIMULATIONS,Qo as DATA_SERIES_KEYS,Zo as DEFAULT_DATA_PALETTE,$o as DEFAULT_DATA_RAMP_STEPS,or as DEFAULT_DIVERGING_NEUTRAL,xo as DEFAULT_ICON_SPRITE_URL,To as DEFAULT_ICON_VIEW_BOX,io as EspalierElementBase,go as FormFieldController,ao as INTENT_VARIANTS,rr as MAX_DATA_RAMP_STEPS,er as MIN_DATA_COLOR_DISTANCE,tr as MIN_DATA_RAMP_LIGHTNESS_STEP,mr as MIN_DATA_RAMP_STEPS,qo as NESTED_THEME_KEYS,so as VALIDITY_CHANGED_EVENT,fr as WEIGHT_LABELS,Ko as auditDataPalette,ar as bestAvailableWeight,ko as buildTaprootDarkTheme,Yo as buildTaprootLightTheme,bo as calculatePhotoLayout,Po as closeFlyout,Wo as encodeTheme,_r as extractFamily,xr as extractWeights,jo as generateDivergingRamp,Xo as generateSequentialRamp,Uo as getEspBus,Ar as getFallbackFont,lr as getGoogleFonts,Ao as getIconHref,Eo as getIconHrefForHost,lo as getIconSpriteUrl,Ho as getImageDetails,Bo as layerThemes,wo as mergePartials,_o as normalizeIntentVariant,Tr as normalizeWeight,vo as parseTheme,sr as printThemeFitReport,Vo as releasePreviewUrl,uo as requestHelp,ho as showFlyout,No as showToast,ir as themeFitReport,Sr as themeFitRows,Fo 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&&
|
|
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}
|
package/dist/root/esp-root.d.ts
CHANGED
|
@@ -63,6 +63,14 @@ export type { SchemeEvents } from "../shared/bus-events.js";
|
|
|
63
63
|
*
|
|
64
64
|
* @customElement esp-root
|
|
65
65
|
* @slot - Place Espalier components and content here.
|
|
66
|
+
* @cssprop --esp-color-series-1 - First categorical data-series color.
|
|
67
|
+
* @cssprop --esp-color-series-2 - Second categorical data-series color.
|
|
68
|
+
* @cssprop --esp-color-series-3 - Third categorical data-series color.
|
|
69
|
+
* @cssprop --esp-color-series-4 - Fourth categorical data-series color.
|
|
70
|
+
* @cssprop --esp-color-series-5 - Fifth categorical data-series color.
|
|
71
|
+
* @cssprop --esp-color-series-6 - Sixth categorical data-series color.
|
|
72
|
+
* @cssprop --esp-color-series-7 - Seventh categorical data-series color.
|
|
73
|
+
* @cssprop --esp-color-series-8 - Eighth categorical data-series color.
|
|
66
74
|
*
|
|
67
75
|
* @docPageTitle Root
|
|
68
76
|
* @docUrl /components/root
|
package/dist/root/esp-root.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var a=function(d,e,t,o){var l=arguments.length,s=l<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,r;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(d,e,t,o);else for(var n=d.length-1;n>=0;n--)(r=d[n])&&(s=(l<3?r(s):l>3?r(e,t,s):r(e,t))||s);return l>3&&s&&Object.defineProperty(e,t,s),s},h;import{css as k,html as b,LitElement as C}from"lit";import{customElement as E,property as c}from"lit/decorators.js";import{getEspBus as p}from"../shared/bus-events.js";import{subscribeToRootEvent as T}from"../shared/root-event-subscription.js";import{DEFAULT_LIGHT_THEME as g,DEFAULT_DARK_THEME as f,parseTheme as y,mergeTheme as v}from"../shared/theme.js";import{computeThemeProperties as x}from"./helpers/compute-theme-properties.js";import{registerImageTexture as R,registeredImageTextures as D}from"../shared/image-texture-registry.js";import{registerImageTexture as W,registeredImageTextures as _,BUILT_IN_IMAGE_TEXTURES as H}from"../shared/image-texture-registry.js";let i=h=class extends C{constructor(){super(...arguments),this.schemeBacker="",this.schemeExplicitlySet=!1,this.resolvingDefaultScheme=!1,this.themeEventsReady=!1,this.systemSchemeQuery=null,this.lastSeedColor="",this.resolvedLightTheme={...g},this.resolvedDarkTheme={...f},this.appliedDataRampProperties=new Set,this.documentClickRegistrationActive=!1,this.correlationId=globalThis.crypto?.randomUUID?.()??Math.random().toString(36),this.lightThemeAttr="",this.darkThemeAttr="",this.fontCSSRoot="/css/fonts/",this.fontDefinitionsUrl="",this.googleFontLoading="auto",this.iconSpriteUrl="/assets/icons.svg",this.defaultScheme="light",this.resizeObserver=new ResizeObserver(()=>{p().publish("window-resized",{emWidth:window.innerWidth/parseFloat(getComputedStyle(document.documentElement).fontSize),emHeight:window.innerHeight/parseFloat(getComputedStyle(document.documentElement).fontSize),pxWidth:window.innerWidth,pxHeight:window.innerHeight})}),this.handleSystemSchemeChange=e=>{this.schemeExplicitlySet||this.defaultScheme!=="system"||(this.resolvingDefaultScheme=!0,this.scheme=e.matches?"dark":"light",this.resolvingDefaultScheme=!1)}}static registerTexture(e,t){R(e,t)}static registeredTextures(){return D()}subscribeScoped(e,t){return T(this,e,t)}get scheme(){return this.schemeBacker}set scheme(e){const t=e==="dark"?"dark":e==="light"?"light":"",o=this.schemeBacker,l=this.schemeExplicitlySet;this.resolvingDefaultScheme||(this.schemeExplicitlySet=t.length>0);const s=t||this.resolveDefaultScheme();l!==this.schemeExplicitlySet&&this.isConnected&&this.syncSystemSchemeListener(),s!==o&&(this.schemeBacker=s,this.requestUpdate("scheme",o),this.themeEventsReady&&p().publish("scheme-changed",{scheme:s,correlationId:this.correlationId}))}get seedColor(){return this.activeTheme.seedColor}static extractFamily(e){if(!e)return"";const t=e.match(/^"([^"]+)"|^'([^']+)'/);return t&&(t[1]||t[2])||""}injectGoogleFontLink(e,t,o){const l="data-esp-font",s=`${this.correlationId}-${e}`,r=document.head.querySelector(`link[${l}="${s}"]`);if(this.googleFontLoading==="none"){r?.remove();return}if(r&&t&&r.dataset.espFamily===t&&r.dataset.espWeight===(o??"")||(r?.remove(),!t))return;const n=encodeURIComponent(t),u=o==="bold"?"700":o==="normal"?"400":o,S=u&&u!=="400"?`:wght@${u}`:"",m=document.createElement("link");m.rel="stylesheet",m.href=`https://fonts.googleapis.com/css2?family=${n}${S}&display=swap`,m.setAttribute(l,s),m.dataset.espFamily=t,m.dataset.espWeight=o??"",document.head.appendChild(m)}syncGoogleFontLinks(){this.googleFontLoading==="none"&&this.removeRuntimeGoogleFontLinks();const e=this.activeTheme;this.injectGoogleFontLink("body",h.extractFamily(e.fontBody),e.fontWeightBody),this.injectGoogleFontLink("headings",h.extractFamily(e.fontHeadings),e.fontWeightHeadings),this.injectGoogleFontLink("brand",h.extractFamily(e.fontBrand),e.fontWeightBrand),this.injectGoogleFontLink("monospace",h.extractFamily(e.fontMonospace),e.fontWeightMonospace)}removeRuntimeGoogleFontLinks(){for(const e of document.head.querySelectorAll(`link[data-esp-font^="${this.correlationId}-"]`))e.remove();for(const e of document.head.querySelectorAll(`link[data-esp-font-picker-root="${CSS.escape(this.correlationId)}"]`))e.remove()}get activeTheme(){return this.scheme==="dark"?this.resolvedDarkTheme:this.resolvedLightTheme}resolveThemes(){const e=this.lightThemeAttr?y(this.lightThemeAttr):null;this.resolvedLightTheme=e?v(g,e):{...g};const t=this.darkThemeAttr?y(this.darkThemeAttr):null;this.resolvedDarkTheme=t?v(f,t):{...f}}connectedCallback(){super.connectedCallback(),this.registerDocumentClickBridge(),this.resizeObserver.observe(this),this.hasUpdated&&(this.applyDefaultScheme(),this.syncGoogleFontLinks())}willUpdate(e){const t=["lightThemeAttr","darkThemeAttr"];(!this.lastSeedColor||t.some(n=>e.has(n)))&&(this.resolveThemes(),this.themeEventsReady&&p().publish("theme-changed",{correlationId:this.correlationId}));const l=x(this.activeTheme,this.scheme==="dark"?"dark":"light"),s=new Set(Object.keys(l).filter(n=>n.startsWith("--esp-color-ramp-")));for(const n of this.appliedDataRampProperties)s.has(n)||this.style.removeProperty(n);for(const[n,u]of Object.entries(l))this.style.setProperty(n,u);this.appliedDataRampProperties=s;const r=this.activeTheme.seedColor;this.themeEventsReady&&this.lastSeedColor&&this.lastSeedColor!==r&&p().publish("seed-color-changed",{seedColor:r,correlationId:this.correlationId}),this.lastSeedColor=r,this.themeEventsReady&&e.has("iconSpriteUrl")&&p().publish("icon-sprite-url-changed",{iconSpriteUrl:this.iconSpriteUrl,correlationId:this.correlationId}),this.syncGoogleFontLinks()}firstUpdated(){const e=this.activeTheme.stylesheets;if(e.length)for(const t of e){const o=document.createElement("link");o.rel="stylesheet",o.href=t,document.head.appendChild(o)}if(!document.getElementById("esp-root-base-styles")){const t=document.createElement("style");t.id="esp-root-base-styles",t.textContent=h.lightDomStyles,document.head.appendChild(t)}this.applyDefaultScheme(),this.lastSeedColor=this.activeTheme.seedColor,this.themeEventsReady=!0}updated(e){(e.has("defaultScheme")||e.has("scheme"))&&!this.schemeExplicitlySet&&this.applyDefaultScheme()}disconnectedCallback(){this.unregisterDocumentClickBridge(),this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null,this.resizeObserver.disconnect(),this.removeRuntimeGoogleFontLinks(),super.disconnectedCallback()}registerDocumentClickBridge(){this.documentClickRegistrationActive||(this.documentClickRegistrationActive=!0,h.connectedRootCount+=1,h.connectedRootCount===1&&document.addEventListener("click",h.handleDocumentClick))}unregisterDocumentClickBridge(){this.documentClickRegistrationActive&&(this.documentClickRegistrationActive=!1,h.connectedRootCount=Math.max(0,h.connectedRootCount-1),h.connectedRootCount===0&&document.removeEventListener("click",h.handleDocumentClick))}applyDefaultScheme(){this.schemeExplicitlySet||(this.resolvingDefaultScheme=!0,this.scheme=this.resolveDefaultScheme(),this.resolvingDefaultScheme=!1,this.syncSystemSchemeListener())}resolveDefaultScheme(){return this.defaultScheme==="dark"||this.defaultScheme==="system"&&window.matchMedia?.("(prefers-color-scheme: dark)").matches?"dark":"light"}syncSystemSchemeListener(){if(this.schemeExplicitlySet||this.defaultScheme!=="system"||!window.matchMedia){this.systemSchemeQuery?.removeEventListener("change",this.handleSystemSchemeChange),this.systemSchemeQuery=null;return}this.systemSchemeQuery||(this.systemSchemeQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.systemSchemeQuery.addEventListener("change",this.handleSystemSchemeChange))}render(){return b`<slot></slot>`}};i.connectedRootCount=0,i.handleDocumentClick=d=>{const e=d.composedPath().filter(t=>t instanceof HTMLElement&&t.tagName==="ESP-POPOVER");p().publish("close-popovers",{source:d.target??void 0,skipPopovers:e})},i.lightDomStyles=`
|
|
2
2
|
|
|
3
3
|
esp-root {
|
|
4
4
|
font-family: var(--esp-font-body);
|
|
@@ -125,4 +125,4 @@ var l=function(c,e,t,s){var h=arguments.length,o=h<3?e:s===null?s=Object.getOwnP
|
|
|
125
125
|
:host {
|
|
126
126
|
display: block;
|
|
127
127
|
}
|
|
128
|
-
`,
|
|
128
|
+
`,a([c({attribute:!1})],i.prototype,"correlationId",void 0),a([c({attribute:"light-theme"})],i.prototype,"lightThemeAttr",void 0),a([c({attribute:"dark-theme"})],i.prototype,"darkThemeAttr",void 0),a([c({attribute:"font-css-root",type:String})],i.prototype,"fontCSSRoot",void 0),a([c({attribute:"font-definitions-url",type:String})],i.prototype,"fontDefinitionsUrl",void 0),a([c({attribute:"google-font-loading",type:String})],i.prototype,"googleFontLoading",void 0),a([c({attribute:"icon-sprite-url",type:String})],i.prototype,"iconSpriteUrl",void 0),a([c({attribute:"default-scheme",type:String,reflect:!0})],i.prototype,"defaultScheme",void 0),a([c({attribute:"scheme",type:String,reflect:!0})],i.prototype,"scheme",null),i=h=a([E("esp-root")],i);export{H as BUILT_IN_IMAGE_TEXTURES,i as EspalierRoot,W as registerImageTexture,_ as registeredImageTextures};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseCssColor as
|
|
1
|
+
import{parseCssColor as C,serializeOklch as u,gamutMapToSRGB as E,deriveSemantic as M,deriveSemanticWithContrast as T}from"../../shared/color-engine.js";import{generateScaleProperties as x}from"../../shared/scale-engine.js";import{DATA_SERIES_KEYS as I,DEFAULT_DATA_PALETTE as h,generateDivergingRamp as A,generateSequentialRamp as L}from"../../shared/data-colors.js";import{SEMANTIC_COLOR_NAMES as w,LIGHTNESS_KEYS as _,TOKEN_PAIRINGS as P,resolveDataColorSource as D,semanticToCSS as f}from"../../shared/theme.js";import{lightnessKeyToCSS as N}from"./lightness-key-to-css.js";import{computeVariants as W,resolveMappingSource as H}from"./compute-variants.js";function K(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function U(o,O,i){const m=C(o.seedColor);if(!m)return{};const e={};e["--esp-scheme"]=O,e["--esp-seed-color"]=o.seedColor;const S=W(m,o);for(const[n,a]of Object.entries(S))e[`--esp-color-${n}`]=u(E(a));const v=new Set,c=(n,a)=>{const s=typeof n=="string"?D(n,o.anchors):null;if(s)return s;const t=typeof n=="string"?n:String(n);return v.has(t)||(v.add(t),console.warn(`Espalier theme: ${a} color source "${t}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared data colors.`)),o.seedColor},$=o.dataPalette??h;for(let n=0;n<I.length;n+=1){const a=I[n],s=C(c($[a],`dataPalette.${a}`))??m;e[`--esp-color-series-${n+1}`]=u(E(s))}for(const[n,a]of Object.entries(o.dataRamps??{}))try{(a.type==="sequential"?L(c(a.source,`dataRamps.${n}.source`),{steps:a.steps,lightnessStart:a.lightnessStart,lightnessEnd:a.lightnessEnd}):A(c(a.start,`dataRamps.${n}.start`),c(a.end,`dataRamps.${n}.end`),{steps:a.steps,neutral:a.neutral===void 0?void 0:c(a.neutral,`dataRamps.${n}.neutral`)})).forEach((t,r)=>{e[`--esp-color-ramp-${n}-${r+1}`]=t})}catch(s){console.warn(`Espalier theme: dataRamps.${n} cannot be generated \u2014 ${s instanceof Error?s.message:String(s)}`)}for(const n of _)e[N(n)]=`${Math.round(o.lightness[n]*100)}%`;const y=P,p=new Set,k=n=>{const a=H(n,S,o.anchors);return a||(p.has(n)||(p.add(n),console.warn(`Espalier theme: color source "${n}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`)),S.primary)},b={};for(const n of w){if(y[n])continue;const a=o.semanticMappings[n],s=o.chroma[n],t=k(a.source),r=o.lightness[a.lightness],d=M(t,r,s.min,s.max);if(b[n]=d,e[f(n)]=u(d),i){const g=f(n);i.push({token:n,property:g,resolved:e[g],source:a.source,lightness:a.lightness,sourceResolved:!p.has(a.source),base:t})}}for(const n of w){const a=y[n];if(!a)continue;const s=o.semanticMappings[n],t=o.chroma[n],r=k(s.source),d=o.lightness[s.lightness],g=b[a.bg];let R;const B=T(r,d,t.min,t.max,g,a.targetLc,i&&(l=>{R=l}));if(b[n]=B,e[f(n)]=u(B),i){const l=f(n);i.push({token:n,property:l,resolved:e[l],source:s.source,lightness:s.lightness,sourceResolved:!p.has(s.source),base:r,requested:R,contrast:{against:a.bg,background:g,targetLc:a.targetLc}})}}return Object.assign(e,x(K(o))),o.fontBody&&(e["--esp-font-body"]=o.fontBody),o.fontHeadings&&(e["--esp-font-headings"]=o.fontHeadings),o.fontBrand&&(e["--esp-font-brand"]=o.fontBrand),o.fontMonospace&&(e["--esp-font-monospace"]=o.fontMonospace),e["--esp-font-weight-body"]=o.fontWeightBody,e["--esp-font-weight-headings"]=o.fontWeightHeadings,e["--esp-font-weight-brand"]=o.fontWeightBrand,e["--esp-font-weight-monospace"]=o.fontWeightMonospace,o.pageBackgroundImage&&(e["--esp-page-background-image"]=o.pageBackgroundImage),o.pageBackgroundImageOpacity!==void 0&&(e["--esp-page-background-image-opacity"]=o.pageBackgroundImageOpacity.toString()),o.boxBackgroundImage&&(e["--esp-box-background-image"]=o.boxBackgroundImage),o.boxBackgroundImageOpacity!==void 0&&(e["--esp-box-background-image-opacity"]=o.boxBackgroundImageOpacity.toString()),o.vellumOpacity!==void 0&&(e["--esp-vellum-opacity"]=o.vellumOpacity.toString()),o.vellumBackgroundImage&&(e["--esp-vellum-background-image"]=o.vellumBackgroundImage),o.vellumBackgroundImageOpacity!==void 0&&(e["--esp-vellum-background-image-opacity"]=o.vellumBackgroundImageOpacity.toString()),e}export{U as computeThemeProperties};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
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
|
|
1
|
+
const G=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 S(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 T(t){const n=t.h*G;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 C(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function z(t){return{r:C(t.r),g:C(t.g),b:C(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 x(t){return Math.max(0,Math.min(1,t))}function q(t){const n=S(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 st(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 g(t){return z(W(T(t)))}function A(t){return Y(g(t))}function M(t){if(t.c<=h||A(t))return{...t};let n=0,r=t.c,e={...t};for(let o=0;o<X;o++){const u=(n+r)/2;if(e={l:t.l,c:u,h:t.h},A(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 _=.022,O=.012,k=.022,w=.57,B=.56,P=1.14,d=.001,R=.027;function I(t){const n=Math.pow(x(t.r),2.4),r=Math.pow(x(t.g),2.4),e=Math.pow(x(t.b),2.4);return .2126729*n+.7151522*r+.072175*e}function F(t,n){const r=g(M(t)),e=g(M(n));let o=I(r),u=I(e);if(o=o>_?o:o+Math.pow(_-o,1.414),u=u>_?u:u+Math.pow(_-u,1.414),Math.abs(u-o)<d)return 0;let c;if(u>o){const a=Math.pow(u,B),s=Math.pow(o,w);if(c=(a-s)*P,c<d)return 0;c=c<R?c-c*k*R:c-k}else{const a=Math.pow(u,B),s=Math.pow(o,w);if(c=(a-s)*P,c>-d)return 0;c=c>-R?c-c*O*R:c+O}return c*100}function j(t,n,r=60){let e=M({...t}),o=Math.abs(F(e,n));if(o>=r)return e;const u=n.l>.5,c=.01,a=u?0:1;for(let s=0;s<100;s++){if(u?e.l=Math.max(a,e.l-c):e.l=Math.min(a,e.l+c),e=M(e),o=Math.abs(F(e,n)),o>=r)return e;if(e.l<=0||e.l>=1)break}return e}function it(t,n){return((t+n)%360+360)%360}function lt(t,n){const r=T(t),e=T(n),o=r.L-e.L,u=r.a-e.a,c=r.b-e.b;return Math.sqrt(o*o+u*u+c*c)}function J(t,n,r,e){return K({l:n,c:t.c,h:t.h},r,e)}function ht(t,n,r,e,o,u=60,c){const a=J(t,n,r,e);return c?.(a),j(a,o,u)}function E(t){return t<=.04045?t/12.92:Math.pow((t+.055)/1.055,2.4)}function Q(t){return{r:E(t.r),g:E(t.g),b:E(t.b)}}function Z({r:t,g:n,b:r}){const e=Math.cbrt(.4122214708*t+.5363325363*n+.0514459929*r),o=Math.cbrt(.2119034982*t+.6806995451*n+.1073969566*r),u=Math.cbrt(.0883024619*t+.2817188376*n+.6299787005*r);return{L:.2104542553*e+.793617785*o-.0040720468*u,a:1.9779984951*e-2.428592205*o+.4505937099*u,b:.0259040371*e+.7827717662*o-.808675766*u}}function tt(t){return Z(Q(t))}function nt(t){const n=Math.sqrt(t.a*t.a+t.b*t.b),r=n<1e-12?0:(Math.atan2(t.b,t.a)/G%360+360)%360;return{l:t.L,c:n,h:r}}function rt(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(x(t)*255)}function L(t){const n=nt(tt(t)),r=t.r===t.g&&t.g===t.b?{l:n.l,c:0,h:0}:n,e=rt(r);if(A(e)){const o=g(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 et(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 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(","),u=e.split(o?y:H);return u.length!==3||u.some(c=>c.length===0)?null:{args:u,legacy:o}}const ot=new RegExp("^("+m+")([a-z%]*)$","i");function N(t){const n=t.match(ot);if(!n)return null;const r=parseFloat(n[1]);return isFinite(r)?{value:r,unit:n[2].toLowerCase()}:null}function ut(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 ct(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 at(t,n,r){const e=(t%360+360)%360,o=u=>{const c=(u+e/30)%12,a=n*Math.min(r,1-r);return r-a*Math.max(-1,Math.min(c-3,9-c,1))};return{r:o(0),g:o(8),b:o(4)}}const ft='"#rrggbb", "#rgb", "rgb(\u2026)", "hsl(\u2026)", "oklch(\u2026)"';function pt(t){const n=S(t);if(n.startsWith("#")){const r=et(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 u=o.map(ut);if(u.some(l=>l===null))return null;const[c,a,s]=u;return L({r:c,g:a,b:s})}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,u,c]=e;if(r.legacy&&(u.unit!=="%"||c.unit!=="%"))return null;const a=ct(o),s=v(u),l=v(c);return a===null||s===null||l===null?null:L(at(a,s,l))}return null}function p(t,n){const r=Math.pow(10,n);return Math.round(t*r)/r}export{ft as ACCEPTED_COLOR_FORMS,F as apcaContrast,x as clampChannel,K as clampChromaAndGamutMap,lt as deltaEOK,J as deriveSemantic,ht as deriveSemanticWithContrast,j as ensureContrast,E as gammaToLinear,M as gamutMapToSRGB,A as isInSRGBGamut,Z as linearRgbToOklab,nt as oklabToOklch,T as oklchToOklab,g as oklchToSRGB,pt as parseCssColor,q as parseOklch,it as rotateHue,st as serializeOklch,Q as srgbToLinearRGB};
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module data-colors
|
|
3
|
+
*
|
|
4
|
+
* Categorical palette auditing and perceptual data-ramp generation.
|
|
5
|
+
*
|
|
6
|
+
* The theme layer resolves brand-anchor references before calling these
|
|
7
|
+
* helpers. The helpers themselves accept concrete CSS colors so they remain
|
|
8
|
+
* useful without an `EspalierTheme` instance.
|
|
9
|
+
*/
|
|
10
|
+
/** Stable keys in the theme's categorical data palette. */
|
|
11
|
+
export declare const DATA_SERIES_KEYS: readonly ["series1", "series2", "series3", "series4", "series5", "series6", "series7", "series8"];
|
|
12
|
+
/** One stable slot in the categorical data palette. */
|
|
13
|
+
export type DataSeriesKey = (typeof DATA_SERIES_KEYS)[number];
|
|
14
|
+
/** Eight categorical colors, each a CSS color or theme anchor reference. */
|
|
15
|
+
export type DataPalette = Record<DataSeriesKey, string>;
|
|
16
|
+
/**
|
|
17
|
+
* The shipped categorical baseline: the eight-color Okabe–Ito palette.
|
|
18
|
+
*
|
|
19
|
+
* These familiar hex values are kept as the authoring contract. Theme output
|
|
20
|
+
* converts them to gamut-mapped OKLCH alongside consumer overrides.
|
|
21
|
+
*/
|
|
22
|
+
export declare const DEFAULT_DATA_PALETTE: Readonly<DataPalette>;
|
|
23
|
+
/** Full color-vision-deficiency simulations used by the palette audit. */
|
|
24
|
+
export declare const COLOR_VISION_SIMULATIONS: readonly ["deuteranopia", "protanopia", "tritanopia"];
|
|
25
|
+
/** A supported full color-vision-deficiency simulation. */
|
|
26
|
+
export type ColorVisionSimulation = (typeof COLOR_VISION_SIMULATIONS)[number];
|
|
27
|
+
/**
|
|
28
|
+
* Minimum OKLab distance used for categorical-palette advice.
|
|
29
|
+
*
|
|
30
|
+
* This is a conservative separation heuristic, not an accessibility
|
|
31
|
+
* certification. The shipped Okabe–Ito palette clears it under every
|
|
32
|
+
* simulation; consumer failures are warnings because charts must also use
|
|
33
|
+
* labels, shapes, or patterns rather than color alone.
|
|
34
|
+
*/
|
|
35
|
+
export declare const MIN_DATA_COLOR_DISTANCE = 0.07;
|
|
36
|
+
/** One pair that falls below the categorical distinguishability threshold. */
|
|
37
|
+
export interface DataPaletteIssue {
|
|
38
|
+
/** The two series slots whose simulated colors are too close. */
|
|
39
|
+
series: readonly [DataSeriesKey, DataSeriesKey];
|
|
40
|
+
/** The simulated color-vision deficiency under which they collide. */
|
|
41
|
+
simulation: ColorVisionSimulation;
|
|
42
|
+
/** Euclidean distance between the simulated colors in OKLab. */
|
|
43
|
+
distance: number;
|
|
44
|
+
/** The threshold the pair was checked against. */
|
|
45
|
+
threshold: number;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Audit every categorical pair after full CVD simulation.
|
|
49
|
+
*
|
|
50
|
+
* Palette values must be concrete CSS colors. Resolve `anchor:` references
|
|
51
|
+
* through the theme first. The return value is empty when every pair clears
|
|
52
|
+
* the threshold.
|
|
53
|
+
*/
|
|
54
|
+
export declare function auditDataPalette(palette: Readonly<DataPalette>, threshold?: number): DataPaletteIssue[];
|
|
55
|
+
/** Minimum supported number of colors in a generated data ramp. */
|
|
56
|
+
export declare const MIN_DATA_RAMP_STEPS = 3;
|
|
57
|
+
/** Maximum supported number of colors in a generated data ramp. */
|
|
58
|
+
export declare const MAX_DATA_RAMP_STEPS = 11;
|
|
59
|
+
/** Default number of colors in a generated data ramp. */
|
|
60
|
+
export declare const DEFAULT_DATA_RAMP_STEPS = 7;
|
|
61
|
+
/** Smallest lightness separation preserved by serialized ramp output. */
|
|
62
|
+
export declare const MIN_DATA_RAMP_LIGHTNESS_STEP = 0.000001;
|
|
63
|
+
/** Default neutral midpoint for diverging ramps. */
|
|
64
|
+
export declare const DEFAULT_DIVERGING_NEUTRAL = "oklch(0.96 0 0)";
|
|
65
|
+
/** Options for a sequential, single-hue data ramp. */
|
|
66
|
+
export interface SequentialRampOptions {
|
|
67
|
+
/** Number of colors, from 3 through 11. @default 7 */
|
|
68
|
+
steps?: number;
|
|
69
|
+
/** Lightest output value. Must be greater than `lightnessEnd`. @default 0.95 */
|
|
70
|
+
lightnessStart?: number;
|
|
71
|
+
/** Darkest output value. Must be less than `lightnessStart`. @default 0.25 */
|
|
72
|
+
lightnessEnd?: number;
|
|
73
|
+
}
|
|
74
|
+
/** Options for a two-ended diverging data ramp. */
|
|
75
|
+
export interface DivergingRampOptions {
|
|
76
|
+
/** Odd number of colors, from 3 through 11. @default 7 */
|
|
77
|
+
steps?: number;
|
|
78
|
+
/** Concrete CSS color at the exact midpoint. @default oklch(0.96 0 0) */
|
|
79
|
+
neutral?: string;
|
|
80
|
+
}
|
|
81
|
+
/** A sequential ramp declaration inside a theme. */
|
|
82
|
+
export interface SequentialDataRamp {
|
|
83
|
+
type: "sequential";
|
|
84
|
+
/** CSS color or `anchor:<name>[.<slot>]` source. */
|
|
85
|
+
source: string;
|
|
86
|
+
steps?: number;
|
|
87
|
+
lightnessStart?: number;
|
|
88
|
+
lightnessEnd?: number;
|
|
89
|
+
}
|
|
90
|
+
/** A diverging ramp declaration inside a theme. */
|
|
91
|
+
export interface DivergingDataRamp {
|
|
92
|
+
type: "diverging";
|
|
93
|
+
/** CSS color or anchor reference at the low end. */
|
|
94
|
+
start: string;
|
|
95
|
+
/** CSS color or anchor reference at the high end. */
|
|
96
|
+
end: string;
|
|
97
|
+
/** CSS color or anchor reference at the exact midpoint. */
|
|
98
|
+
neutral?: string;
|
|
99
|
+
steps?: number;
|
|
100
|
+
}
|
|
101
|
+
/** A named data-ramp declaration inside a theme. */
|
|
102
|
+
export type DataRamp = SequentialDataRamp | DivergingDataRamp;
|
|
103
|
+
/** Named data ramps emitted by a theme. */
|
|
104
|
+
export type DataRamps = Record<string, DataRamp>;
|
|
105
|
+
/** One ramp while partial themes are being layered. */
|
|
106
|
+
export type PartialDataRamp = Partial<SequentialDataRamp> | Partial<DivergingDataRamp>;
|
|
107
|
+
/** Named ramp refinements in a partial theme. */
|
|
108
|
+
export type PartialDataRamps = Record<string, PartialDataRamp>;
|
|
109
|
+
/**
|
|
110
|
+
* Generate a single-hue, light-to-dark sequential ramp.
|
|
111
|
+
*
|
|
112
|
+
* Chroma is reduced only when needed to keep each stop in sRGB. Gamut mapping
|
|
113
|
+
* preserves lightness, so the requested sequence remains strictly monotone.
|
|
114
|
+
*/
|
|
115
|
+
export declare function generateSequentialRamp(color: string, options?: SequentialRampOptions): string[];
|
|
116
|
+
/**
|
|
117
|
+
* Generate a two-ended diverging ramp with an exact neutral midpoint.
|
|
118
|
+
*
|
|
119
|
+
* Each half interpolates in OKLab, avoiding the hue spin that polar
|
|
120
|
+
* interpolation produces as chroma approaches zero.
|
|
121
|
+
*/
|
|
122
|
+
export declare function generateDivergingRamp(start: string, end: string, options?: DivergingRampOptions): string[];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{clampChannel as L,gamutMapToSRGB as E,linearRgbToOklab as I,oklabToOklch as C,oklchToOklab as S,oklchToSRGB as w,parseCssColor as M,serializeOklch as b,srgbToLinearRGB as N}from"./color-engine.js";const u=["series1","series2","series3","series4","series5","series6","series7","series8"],y={series1:"#000000",series2:"#E69F00",series3:"#56B4E9",series4:"#009E73",series5:"#F0E442",series6:"#0072B2",series7:"#D55E00",series8:"#CC79A7"},k=["deuteranopia","protanopia","tritanopia"],O=.07,P={protanopia:[[.152286,1.052583,-.204868],[.114503,.786281,.099216],[-.003882,-.048116,1.051998]],deuteranopia:[[.367322,.860646,-.227968],[.280085,.672501,.047413],[-.01182,.04294,.968881]],tritanopia:[[1.255528,-.076749,-.178779],[-.078411,.930809,.147602],[.004733,.691367,.3039]]};function x(e,t){const r=w(E(e)),o=N(r),n=s=>L(s[0]*o.r+s[1]*o.g+s[2]*o.b);return{r:n(t[0]),g:n(t[1]),b:n(t[2])}}function q(e,t){return Math.hypot(e.L-t.L,e.a-t.a,e.b-t.b)}function p(e,t){const r=M(e);if(!r)throw new TypeError(`${t} is not a valid opaque CSS color: "${e}".`);return r}function G(e,t=O){if(!Number.isFinite(t)||t<0)throw new RangeError("Data-palette distance threshold must be a finite number \u2265 0.");const r=new Map;for(const n of u)r.set(n,p(e[n],`dataPalette.${n}`));const o=[];for(const n of k){const s=new Map;for(const a of u)s.set(a,I(x(r.get(a),P[n])));for(let a=0;a<u.length;a+=1)for(let i=a+1;i<u.length;i+=1){const l=u[a],c=u[i],g=q(s.get(l),s.get(c));g<t&&o.push({series:[l,c],simulation:n,distance:g,threshold:t})}}return o}const A=3,f=11,m=7,T=1e-6,v="oklch(0.96 0 0)";function _(e,t){if(!Number.isInteger(e)||e<A||e>f)throw new RangeError(`Data-ramp steps must be an integer from ${A} through ${f}.`);if(t&&e%2===0)throw new RangeError("Diverging data-ramp steps must be odd so the neutral is the midpoint.")}function d(e,t){if(!Number.isFinite(e)||e<0||e>1)throw new RangeError(`${t} must be a finite number from 0 through 1.`)}function U(e,t={}){const r=p(e,"Sequential ramp source"),o=t.steps??m,n=t.lightnessStart??.95,s=t.lightnessEnd??.25;if(_(o,!1),d(n,"Sequential ramp lightnessStart"),d(s,"Sequential ramp lightnessEnd"),n<=s)throw new RangeError("Sequential ramp lightnessStart must be greater than lightnessEnd.");if((n-s)/(o-1)<=T)throw new RangeError(`Sequential ramp lightness bounds must leave more than ${T} lightness between serialized stops.`);return Array.from({length:o},(a,i)=>{const l=i/(o-1),c=n+(s-n)*l;return b(E({l:c,c:r.c,h:r.h}))})}function R(e,t,r){return{L:e.L+(t.L-e.L)*r,a:e.a+(t.a-e.a)*r,b:e.b+(t.b-e.b)*r}}function B(e,t,r={}){const o=p(e,"Diverging ramp start"),n=p(t,"Diverging ramp end"),s=p(r.neutral??v,"Diverging ramp neutral"),a=r.steps??m;_(a,!0);const i=(a-1)/2,l=S(o),c=S(s),g=S(n);return Array.from({length:a},(F,h)=>{if(h===i)return b(E(s));const D=h<i?R(l,c,h/i):R(c,g,(h-i)/i);return b(E(C(D)))})}export{k as COLOR_VISION_SIMULATIONS,u as DATA_SERIES_KEYS,y as DEFAULT_DATA_PALETTE,m as DEFAULT_DATA_RAMP_STEPS,v as DEFAULT_DIVERGING_NEUTRAL,f as MAX_DATA_RAMP_STEPS,O as MIN_DATA_COLOR_DISTANCE,T as MIN_DATA_RAMP_LIGHTNESS_STEP,A as MIN_DATA_RAMP_STEPS,G as auditDataPalette,B as generateDivergingRamp,U as generateSequentialRamp};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var p=function(
|
|
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([
|
|
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
|