@taprootio/espalier 2.18.0 → 2.20.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 +12356 -2862
- package/dist/index.d.ts +2 -1
- package/dist/index.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-semantic-properties.js +1 -0
- package/dist/root/helpers/compute-theme-properties.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.d.ts +12 -6
- package/dist/shared/esp-element-base.js +2 -2
- package/dist/shared/theme.d.ts +53 -3
- package/dist/shared/theme.js +1 -1
- 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
|
@@ -70,7 +70,8 @@ export * from "./shared/events.js";
|
|
|
70
70
|
export { getImageDetails, releasePreviewUrl, type EspalierUploadImage, type ImageDetailsOptions, type SelectedUploadImage, type ExistingUploadImage, type ExistingImage, type ResponsiveImageUrl, type UploadCallbacks, type UploadEventDetail, } from "./image-upload/image-helpers.js";
|
|
71
71
|
export { calculatePhotoLayout, type LayoutImage, type PhotoRow, } from "./shared/justified-layout.js";
|
|
72
72
|
export { type TypeaheadFetchItems } from "./pickers/types.js";
|
|
73
|
-
export { type EspalierTheme, type PartialTheme, type VariantColorSource, encodeTheme, parseTheme, mergePartials, layerThemes, buildTaprootLightTheme, buildTaprootDarkTheme, NESTED_THEME_KEYS, } from "./shared/theme.js";
|
|
73
|
+
export { type EspalierTheme, type PartialTheme, type PartialThemeContexts, type ThemeContext, type ThemeContexts, type VariantColorSource, encodeTheme, parseTheme, mergePartials, layerThemes, validateThemePair, 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";
|
|
76
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
|
|
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 xr,DEFAULT_ICON_VIEW_BOX as Tr,INTENT_VARIANTS as ar,normalizeIntentVariant as _r,getIconHref as Ar,getIconHrefForHost as Er,getIconSpriteUrl as lr}from"./shared/intent-values.js";import{EspalierElementBase as Ir}from"./shared/esp-element-base.js";import{VALIDITY_CHANGED_EVENT as sr}from"./shared/validation.js";import{FormFieldController as gr}from"./shared/form-field-controller.js";import{traverseToClosest as Fr}from"./shared/utilities.js";import{showToast as Nr}from"./shared/toast-events.js";import{showFlyout as hr,closeFlyout as Pr}from"./shared/flyout-events.js";import{requestHelp as ur}from"./shared/help-events.js";import{getEspBus as Ur}from"./shared/bus-events.js";export*from"./shared/events.js";import{getImageDetails as Hr,releasePreviewUrl as Vr}from"./image-upload/image-helpers.js";import{calculatePhotoLayout as Gr}from"./shared/justified-layout.js";import{encodeTheme as vr,parseTheme as yr,mergePartials as Wr,layerThemes as wr,validateThemePair as Br,buildTaprootLightTheme as Yr,buildTaprootDarkTheme as kr,NESTED_THEME_KEYS as qr}from"./shared/theme.js";import{auditDataPalette as Kr,generateSequentialRamp as Xr,generateDivergingRamp as jr,COLOR_VISION_SIMULATIONS as Jr,DATA_SERIES_KEYS as Qr,DEFAULT_DATA_PALETTE as Zr,DEFAULT_DATA_RAMP_STEPS as $r,DEFAULT_DIVERGING_NEUTRAL as ro,MAX_DATA_RAMP_STEPS as oo,MIN_DATA_COLOR_DISTANCE as eo,MIN_DATA_RAMP_LIGHTNESS_STEP as to,MIN_DATA_RAMP_STEPS as mo}from"./shared/data-colors.js";import{WEIGHT_LABELS as fo,extractWeights as xo,normalizeWeight as To,bestAvailableWeight as ao,extractFamily as _o,getFallbackFont as Ao}from"./shared/font-helpers.js";import{getGoogleFonts as lo}from"./font-picker/esp-font-picker.js";import{themeFitReport as Io,themeFitRows as So,printThemeFitReport as so}from"./shared/theme-fit-report.js";export{Jr as COLOR_VISION_SIMULATIONS,Qr as DATA_SERIES_KEYS,Zr as DEFAULT_DATA_PALETTE,$r as DEFAULT_DATA_RAMP_STEPS,ro as DEFAULT_DIVERGING_NEUTRAL,xr as DEFAULT_ICON_SPRITE_URL,Tr as DEFAULT_ICON_VIEW_BOX,Ir as EspalierElementBase,gr as FormFieldController,ar as INTENT_VARIANTS,oo as MAX_DATA_RAMP_STEPS,eo as MIN_DATA_COLOR_DISTANCE,to as MIN_DATA_RAMP_LIGHTNESS_STEP,mo as MIN_DATA_RAMP_STEPS,qr as NESTED_THEME_KEYS,sr as VALIDITY_CHANGED_EVENT,fo as WEIGHT_LABELS,Kr as auditDataPalette,ao as bestAvailableWeight,kr as buildTaprootDarkTheme,Yr as buildTaprootLightTheme,Gr as calculatePhotoLayout,Pr as closeFlyout,vr as encodeTheme,_o as extractFamily,xo as extractWeights,jr as generateDivergingRamp,Xr as generateSequentialRamp,Ur as getEspBus,Ao as getFallbackFont,lo as getGoogleFonts,Ar as getIconHref,Er as getIconHrefForHost,lr as getIconSpriteUrl,Hr as getImageDetails,wr as layerThemes,Wr as mergePartials,_r as normalizeIntentVariant,To as normalizeWeight,yr as parseTheme,so as printThemeFitReport,Vr as releasePreviewUrl,ur as requestHelp,hr as showFlyout,Nr as showToast,Io as themeFitReport,So as themeFitRows,Fr as traverseToClosest,Br as validateThemePair};
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{deriveSemantic as C,deriveSemanticWithContrast as M,serializeOklch as d}from"../../shared/color-engine.js";import{SEMANTIC_COLOR_NAMES as v,TOKEN_PAIRINGS as S,semanticToCSS as R}from"../../shared/theme.js";import{resolveMappingSource as k}from"./compute-variants.js";function x(r,m,t={}){const i={},u={},p=(o,e)=>{const c=t.effectiveSource?.(o,e)??e,s=k(c,m,r.anchors);return s||t.onUnresolvedSource?.(c),{color:s??m.primary,resolved:s!==null,source:c}};for(const o of v){if(S[o])continue;const e=r.semanticMappings[o],c=r.chroma[o],s=p(o,e.source),n=r.lightness[e.lightness],l=C(s.color,n,c.min,c.max),a=R(o);u[o]=l,i[a]=d(l),t.trace&&t.trace.push({token:o,property:a,resolved:i[a],source:s.source,lightness:e.lightness,sourceResolved:s.resolved,base:s.color})}for(const o of v){const e=S[o];if(!e)continue;const c=r.semanticMappings[o],s=r.chroma[o],n=p(o,c.source),l=r.lightness[c.lightness],a=u[e.bg];let f;const h=M(n.color,l,s.min,s.max,a,e.targetLc,t.trace&&(b=>{f=b})),g=R(o);u[o]=h,i[g]=d(h),t.trace&&t.trace.push({token:o,property:g,resolved:i[g],source:n.source,lightness:c.lightness,sourceResolved:n.resolved,base:n.color,requested:f,contrast:{against:e.bg,background:a,targetLc:e.targetLc}})}return i}export{x as computeSemanticProperties};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{parseCssColor as
|
|
1
|
+
import{parseCssColor as g,serializeOklch as l,gamutMapToSRGB as f}from"../../shared/color-engine.js";import{generateScaleProperties as k}from"../../shared/scale-engine.js";import{DATA_SERIES_KEYS as u,DEFAULT_DATA_PALETTE as v,generateDivergingRamp as B,generateSequentialRamp as R}from"../../shared/data-colors.js";import{LIGHTNESS_KEYS as w,resolveDataColorSource as E}from"../../shared/theme.js";import{lightnessKeyToCSS as $}from"./lightness-key-to-css.js";import{computeVariants as I}from"./compute-variants.js";import{computeSemanticProperties as O}from"./compute-semantic-properties.js";function T(o){return{rootFontSize:o.rootFontSize,typeRatio:o.typeRatio,spaceRatio:o.spaceRatio,borderRadius:o.borderRadius,viewportMin:o.viewportMin,viewportMax:o.viewportMax}}function j(o,S,b){const i=g(o.seedColor);if(!i)return{};const e={};e["--esp-scheme"]=S,e["--esp-seed-color"]=o.seedColor;const c=I(i,o);for(const[a,n]of Object.entries(c))e[`--esp-color-${a}`]=l(f(n));const d=new Set,t=(a,n)=>{const r=typeof a=="string"?E(a,o.anchors):null;if(r)return r;const s=typeof a=="string"?a:String(a);return d.has(s)||(d.add(s),console.warn(`Espalier theme: ${n} color source "${s}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared data colors.`)),o.seedColor},m=o.dataPalette??v;for(let a=0;a<u.length;a+=1){const n=u[a],r=g(t(m[n],`dataPalette.${n}`))??i;e[`--esp-color-series-${a+1}`]=l(f(r))}for(const[a,n]of Object.entries(o.dataRamps??{}))try{(n.type==="sequential"?R(t(n.source,`dataRamps.${a}.source`),{steps:n.steps,lightnessStart:n.lightnessStart,lightnessEnd:n.lightnessEnd}):B(t(n.start,`dataRamps.${a}.start`),t(n.end,`dataRamps.${a}.end`),{steps:n.steps,neutral:n.neutral===void 0?void 0:t(n.neutral,`dataRamps.${a}.neutral`)})).forEach((s,y)=>{e[`--esp-color-ramp-${a}-${y+1}`]=s})}catch(r){console.warn(`Espalier theme: dataRamps.${a} cannot be generated \u2014 ${r instanceof Error?r.message:String(r)}`)}for(const a of w)e[$(a)]=`${Math.round(o.lightness[a]*100)}%`;const p=new Set;return Object.assign(e,O(o,c,{trace:b,onUnresolvedSource:a=>{p.has(a)||(p.add(a),console.warn(`Espalier theme: color source "${a}" cannot be resolved \u2014 falling back to the seed. Run validateTheme for the declared anchors.`))}})),Object.assign(e,k(T(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{j as computeThemeProperties};
|
|
@@ -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};
|
|
@@ -39,6 +39,13 @@ export declare class EspalierElementBase extends LitElement implements SeedColor
|
|
|
39
39
|
*/
|
|
40
40
|
get variant(): EspalierVariant;
|
|
41
41
|
set variant(val: EspalierVariant);
|
|
42
|
+
/**
|
|
43
|
+
* A theme-defined color zone. The selected context rebinds designer-facing
|
|
44
|
+
* roles and emits a complete, contrast-enforced semantic token table on this
|
|
45
|
+
* host for descendants to inherit.
|
|
46
|
+
*/
|
|
47
|
+
get context(): string;
|
|
48
|
+
set context(value: string);
|
|
42
49
|
connectedCallback(): void;
|
|
43
50
|
disconnectedCallback(): void;
|
|
44
51
|
protected firstUpdated(_changedProperties: PropertyValues): void;
|
|
@@ -51,14 +58,13 @@ export declare class EspalierElementBase extends LitElement implements SeedColor
|
|
|
51
58
|
*/
|
|
52
59
|
traverseToClosest(selector: string): Element | null;
|
|
53
60
|
/**
|
|
54
|
-
* Compute and apply variant-specific semantic color tokens.
|
|
61
|
+
* Compute and apply context- and variant-specific semantic color tokens.
|
|
55
62
|
*
|
|
56
|
-
*
|
|
57
|
-
* cascade from `<esp-root>`
|
|
63
|
+
* With no context and the **primary** variant (or none), all semantic
|
|
64
|
+
* tokens cascade from `<esp-root>` and previous overrides are cleared.
|
|
58
65
|
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* as inline styles on the host element.
|
|
66
|
+
* A non-primary legacy variant is then computed over the contextual theme
|
|
67
|
+
* and applied as the final inline layer until ESP0166 removes re-seeding.
|
|
62
68
|
*/
|
|
63
69
|
protected applyVariantTokens(): void;
|
|
64
70
|
protected getVariantColorSource(): ColorSource | "";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var
|
|
1
|
+
var c=function(u,e,t,o){var r=arguments.length,s=r<3?e:o===null?o=Object.getOwnPropertyDescriptor(e,t):o,n;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")s=Reflect.decorate(u,e,t,o);else for(var i=u.length-1;i>=0;i--)(n=u[i])&&(s=(r<3?n(s):r>3?n(e,t,s):n(e,t))||s);return r>3&&s&&Object.defineProperty(e,t,s),s};import{css as R,LitElement as T}from"lit";import{property as d,state as C}from"lit/decorators.js";import{subscribeToRootEvent as p}from"./root-event-subscription.js";import{traverseToClosest as f}from"./utilities.js";import{parseCssColor as S,serializeOklch as x,gamutMapToSRGB as V}from"./color-engine.js";import{computeVariants as g}from"../root/helpers/compute-variants.js";import{computeSemanticProperties as b}from"../root/helpers/compute-semantic-properties.js";import{ROLE_NAMES as w,mergeTheme as P}from"./theme.js";import{alignAttributeTextInheritance as E,focusRing as U}from"./style-fragments.js";const v=new WeakMap;class a extends T{constructor(){super(...arguments),this.seedColorBacker="oklch(0.7 0.125 216)",this.espRoot=null,this.contextBacker="",this.scopedTokenOriginalValues=new Map,this.warnedUnknownContexts=new Set,this.pendingInitialThemeRoot=null,this.rootEventSubscriptionsActive=!1,this.subscribedRoot=null,this.rootEventUnsubscribers=[],this.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.applyTokensWhenRootReady()}get context(){return this.contextBacker}set context(e){const t=e??"";t!==this.contextBacker&&(this.contextBacker=t,this.applyTokensWhenRootReady())}connectedCallback(){super.connectedCallback();const e=this.syncRootFromDom(!1);e&&this.subscribeToRootEvents(e)}disconnectedCallback(){super.disconnectedCallback(),this.unsubscribeFromRootEvents()}firstUpdated(e){this.syncRootFromDom(!0),this.applyTokensWhenRootReady()}syncRootFromDom(e){const t=f(this,"esp-root");if(!t){if(this.espRoot&&this.clearScopedTokens(),this.unsubscribeFromRootEvents(),this.espRoot=null,!e)return null;throw new Error("No esp-root ancestor found. Espalier components must be placed inside an <esp-root> element.")}const o=t!==this.espRoot,s=t.scheme==="dark"?"dark":"light",n=this.scheme!==s,i=this.seedColor!==t.seedColor;return this.espRoot=t,o&&this.isConnected&&this.subscribeToRootEvents(t),(o||n||i)&&(this.scheme=s,this.seedColor=t.seedColor,this.applyTokensWhenRootReady()),o&&this.requestUpdate(),t}applyTokensWhenRootReady(){const e=this.espRoot;if(e&&(!e.hasUpdated||e.isUpdatePending)){this.applyTokensAfterInitialRootUpdate(e);return}this.applyVariantTokens()}applyTokensAfterInitialRootUpdate(e){if(this.pendingInitialThemeRoot===e)return;this.pendingInitialThemeRoot=e;const t=e.updateComplete;if(!t){this.pendingInitialThemeRoot=null,this.applyVariantTokens();return}t.then(()=>{this.pendingInitialThemeRoot===e&&(this.pendingInitialThemeRoot=null),!(!this.isConnected||this.espRoot!==e)&&(this.scheme=e.scheme==="dark"?"dark":"light",this.seedColor=e.seedColor,this.applyVariantTokens())})}subscribeToRootEvents(e){this.rootEventSubscriptionsActive&&this.subscribedRoot===e||(this.unsubscribeFromRootEvents(),this.subscribedRoot=e,this.rootEventUnsubscribers=[p(e,"seed-color-changed",this.handleSeedColorChanged),p(e,"scheme-changed",this.handleSchemeChanged),p(e,"theme-changed",this.handleThemeChanged),p(e,"icon-sprite-url-changed",this.handleIconSpriteUrlChanged)],this.rootEventSubscriptionsActive=!0)}unsubscribeFromRootEvents(){if(this.rootEventSubscriptionsActive){for(const e of this.rootEventUnsubscribers)e();this.rootEventUnsubscribers=[],this.subscribedRoot=null,this.rootEventSubscriptionsActive=!1}}traverseToClosest(e){return f(this,e)}applyVariantTokens(){if(!this.espRoot)return;const e=this.getVariantColorSource();if(!e&&!this.context.trim()){this.clearScopedTokens();return}const t=this.espRoot.activeTheme;if(!t){this.clearScopedTokens();return}const o=this.resolveContextTheme(t),r=o.theme,s=S(r.seedColor);if(!s)return;const n=g(s,r),i={};if(!e){o.applied&&Object.assign(i,b(r,n)),this.applyScopedTokenProperties(i);return}const l=n[e];if(!l){this.clearScopedTokens();return}i["--esp-color-primary"]=x(V(l));const h=g(l,r),y=a.statusVariantSources.has(e);Object.assign(i,b(r,h,{effectiveSource:(m,k)=>this.effectiveVariantTokenSource(m,k,y)})),this.applyScopedTokenProperties(i)}resolveContextTheme(e){const t=this.context.trim();if(!t)return{applied:!1,theme:e};const o=e.contexts&&Object.prototype.hasOwnProperty.call(e.contexts,t)?e.contexts[t]:void 0;if(o){let r=v.get(e);const s=r?.get(t);if(s)return{applied:!0,theme:s};const n={};for(const l of w){const h=o[l];h!==void 0&&(n[l]=h)}const i=P(e,{lightness:o.lightness,roles:n});return r||(r=new Map,v.set(e,r)),r.set(t,i),{applied:!0,theme:i}}return this.warnedUnknownContexts.has(t)||(this.warnedUnknownContexts.add(t),console.warn(`Espalier context: "${t}" is not defined by the active theme; inheriting root tokens.`)),{applied:!1,theme:e}}effectiveVariantTokenSource(e,t,o){return o&&a.semanticActionTokens.has(e)?"primary":t}getVariantColorSource(){switch(this.variant){case"":case"primary":case"neutral":return"";case"info":return"complementary";default:return this.variant}}applyScopedTokenProperties(e){for(const t of this.scopedTokenOriginalValues.keys())t in e||this.restoreScopedTokenProperty(t);for(const[t,o]of Object.entries(e))this.setScopedTokenProperty(t,o)}setScopedTokenProperty(e,t){const o=this.scopedTokenOriginalValues.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.scopedTokenOriginalValues.set(e,{generatedPriority:"",generatedValue:t,originalPriority:this.style.getPropertyPriority(e),originalValue:r.length?r:null})}this.style.setProperty(e,t)}restoreScopedTokenProperty(e){const t=this.scopedTokenOriginalValues.get(e);if(!t)return;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.scopedTokenOriginalValues.delete(e)}clearScopedTokens(){for(const e of[...this.scopedTokenOriginalValues.keys()])this.restoreScopedTokenProperty(e)}}a.statusVariantSources=new Set(["danger","success","warning"]),a.semanticActionTokens=new Set(["actionBackground","actionText"]),a.styles=[U(".esp-field:focus-within","--esp-field-focus-shadow"),E,R`
|
|
2
2
|
:host {
|
|
3
3
|
|
|
4
4
|
--_esp-field-resolved-hover-bg: var(
|
|
@@ -122,4 +122,4 @@ var p=function(v,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
|
-
`],
|
|
125
|
+
`],c([C()],a.prototype,"seedColor",null),c([d({attribute:!1})],a.prototype,"correlationId",void 0),c([d({type:String,reflect:!0})],a.prototype,"scheme",void 0),c([d({type:String,attribute:"variant",reflect:!0})],a.prototype,"variant",null),c([d({type:String,attribute:"context",reflect:!0})],a.prototype,"context",null);export{a as EspalierElementBase};
|
package/dist/shared/theme.d.ts
CHANGED
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
* }
|
|
31
31
|
* ```
|
|
32
32
|
*/
|
|
33
|
+
import { type DataPalette, type DataRamps, type PartialDataRamps } from "./data-colors.js";
|
|
33
34
|
/** A key in the lightness ramp. Each maps to a perceptual role. */
|
|
34
35
|
export type LightnessKey = "surface" | "raised1" | "raised2" | "raised3" | "raised4" | "accent" | "muted" | "text" | "border" | "ink" | "shadow";
|
|
35
36
|
/** Lightness values (0–1) for every ramp position. */
|
|
@@ -123,6 +124,14 @@ export declare function parseAnchorSource(source: string): AnchorReference | nul
|
|
|
123
124
|
* resolves `null`, as do unknown names and slots.
|
|
124
125
|
*/
|
|
125
126
|
export declare function resolveAnchorColor(anchors: ThemeAnchors, reference: AnchorReference): string | null;
|
|
127
|
+
/**
|
|
128
|
+
* Resolve a data color source to a concrete CSS color.
|
|
129
|
+
*
|
|
130
|
+
* Data palettes and ramps accept either a CSS color directly or the same
|
|
131
|
+
* `anchor:<name>[.<slot>]` references as semantic mappings. The returned color
|
|
132
|
+
* is parseable and opaque; invalid or unresolved sources return `null`.
|
|
133
|
+
*/
|
|
134
|
+
export declare function resolveDataColorSource(source: string, anchors: ThemeAnchors): string | null;
|
|
126
135
|
/** Every semantic color token the system computes. */
|
|
127
136
|
export type SemanticColorName = "background" | "layer1" | "layer2" | "layer3" | "layer4" | "actionBackground" | "actionText" | "border" | "shadow" | "text" | "dangerText" | "headings" | "headingsHover" | "link" | "linkHover" | "linkHoverBg" | "inputCaret" | "inputSelection" | "inputSelectionBg";
|
|
128
137
|
/** Chroma range enforced on a semantic token before gamut mapping. */
|
|
@@ -196,6 +205,20 @@ export type RoleBinding<R extends RoleName = RoleName> = MappingSource | ({
|
|
|
196
205
|
export type ThemeRoles = {
|
|
197
206
|
[R in RoleName]?: RoleBinding<R>;
|
|
198
207
|
};
|
|
208
|
+
/**
|
|
209
|
+
* One named zone-level rebinding of the designer-facing color roles.
|
|
210
|
+
*
|
|
211
|
+
* A context may also carry a partial lightness ramp. Color sources alone
|
|
212
|
+
* cannot make a dark zone inside a light scheme because semantic derivation
|
|
213
|
+
* deliberately takes lightness from the ramp rather than from an anchor.
|
|
214
|
+
*/
|
|
215
|
+
export type ThemeContext = ThemeRoles & {
|
|
216
|
+
lightness?: Partial<LightnessMap>;
|
|
217
|
+
};
|
|
218
|
+
/** Named role-rebinding zones available to `context` attributes. */
|
|
219
|
+
export type ThemeContexts = Record<string, ThemeContext>;
|
|
220
|
+
/** Context declarations while partial themes are being layered. */
|
|
221
|
+
export type PartialThemeContexts = Record<string, ThemeContext | undefined>;
|
|
199
222
|
/** Ordered role names, for validation and iteration. */
|
|
200
223
|
export declare const ROLE_NAMES: readonly RoleName[];
|
|
201
224
|
/**
|
|
@@ -385,6 +408,23 @@ export interface EspalierTheme {
|
|
|
385
408
|
* See {@link ThemeRoles} and ADR-016.
|
|
386
409
|
*/
|
|
387
410
|
roles: ThemeRoles;
|
|
411
|
+
/**
|
|
412
|
+
* Named zone-level role rebindings. A base-derived element selects one with
|
|
413
|
+
* its `context` attribute; the selected context is resolved against this
|
|
414
|
+
* scheme's complete theme and re-enforces every semantic ink pairing.
|
|
415
|
+
*/
|
|
416
|
+
contexts: ThemeContexts;
|
|
417
|
+
/**
|
|
418
|
+
* Eight stable categorical data-series colors. Each value is a CSS color or
|
|
419
|
+
* an `anchor:<name>[.<slot>]` reference. Emitted as
|
|
420
|
+
* `--esp-color-series-1`–`--esp-color-series-8`.
|
|
421
|
+
*/
|
|
422
|
+
dataPalette: DataPalette;
|
|
423
|
+
/**
|
|
424
|
+
* Named sequential and diverging data ramps. Empty by default; each
|
|
425
|
+
* declaration emits `--esp-color-ramp-<name>-1…<steps>`.
|
|
426
|
+
*/
|
|
427
|
+
dataRamps: DataRamps;
|
|
388
428
|
/** Optional CSS `background-image` for the page surface. */
|
|
389
429
|
pageBackgroundImage?: string;
|
|
390
430
|
/** Opacity (0–1) for the page background image. */
|
|
@@ -407,8 +447,10 @@ export interface EspalierTheme {
|
|
|
407
447
|
* carry slot-only anchor overrides, which the resolved
|
|
408
448
|
* {@link ThemeAnchor} deliberately does not permit.
|
|
409
449
|
*/
|
|
410
|
-
export type PartialTheme = Omit<DeepPartial<EspalierTheme>, "anchors"> & {
|
|
450
|
+
export type PartialTheme = Omit<DeepPartial<EspalierTheme>, "anchors" | "contexts" | "dataRamps"> & {
|
|
411
451
|
anchors?: PartialThemeAnchors;
|
|
452
|
+
contexts?: PartialThemeContexts;
|
|
453
|
+
dataRamps?: PartialDataRamps;
|
|
412
454
|
};
|
|
413
455
|
/** Validation result returned by {@link validateTheme}. */
|
|
414
456
|
export interface ThemeValidationResult {
|
|
@@ -535,7 +577,7 @@ export declare function encodeTheme(partial: PartialTheme): string;
|
|
|
535
577
|
* Deep-merge a {@link PartialTheme} over a set of defaults.
|
|
536
578
|
*
|
|
537
579
|
* Primitive fields are replaced; nested objects (`angles`,
|
|
538
|
-
* `semanticHues`, `lightness`, `chroma`, `semanticMappings`)
|
|
580
|
+
* `semanticHues`, `lightness`, `chroma`, `semanticMappings`, `contexts`)
|
|
539
581
|
* are merged key-by-key. Arrays (`stylesheets`) are replaced
|
|
540
582
|
* wholesale.
|
|
541
583
|
*
|
|
@@ -557,12 +599,20 @@ export declare function mergeTheme(defaults: EspalierTheme, overrides: PartialTh
|
|
|
557
599
|
* and `warnings`.
|
|
558
600
|
*/
|
|
559
601
|
export declare function validateTheme(base64: string): ThemeValidationResult;
|
|
602
|
+
/**
|
|
603
|
+
* Validate the light and dark partials that form one scheme-paired theme.
|
|
604
|
+
*
|
|
605
|
+
* Each partial first passes through {@link validateTheme}. Once both are
|
|
606
|
+
* structurally valid, their context-name sets must match exactly so a stable
|
|
607
|
+
* `context` attribute cannot silently change meaning when the scheme changes.
|
|
608
|
+
*/
|
|
609
|
+
export declare function validateThemePair(lightBase64: string, darkBase64: string): ThemeValidationResult;
|
|
560
610
|
/**
|
|
561
611
|
* Keys of {@link EspalierTheme} whose values are nested objects
|
|
562
612
|
* and therefore need key-by-key merging instead of wholesale
|
|
563
613
|
* replacement when combining two {@link PartialTheme} objects.
|
|
564
614
|
*/
|
|
565
|
-
export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
|
|
615
|
+
export declare const NESTED_THEME_KEYS: readonly ["anchors", "angles", "contexts", "dataPalette", "dataRamps", "roles", "chroma", "lightness", "semanticHues", "semanticMappings", "variantChroma"];
|
|
566
616
|
/**
|
|
567
617
|
* Deep-merge two {@link PartialTheme} objects.
|
|
568
618
|
*
|