@taprootio/espalier 2.5.0 → 2.7.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.
@@ -0,0 +1,77 @@
1
+ import { type PropertyValues } from "lit";
2
+ import { EspalierElementBase } from "../shared/esp-element-base.js";
3
+ import { type FocusPoint } from "../image/image-focus.js";
4
+ import "../image/esp-image.js";
5
+ export declare const FOCUS_CHANGED_EVENT = "focus-changed";
6
+ export type FocusChangedDetail = FocusPoint;
7
+ /**
8
+ * A keyboard- and pointer-operable focal-point authoring control with live
9
+ * banner-cover previews.
10
+ *
11
+ * The HTML value is `focus="x y"`. In JavaScript use `.focusPoint`; the name
12
+ * avoids replacing the platform's required `HTMLElement.focus()` method.
13
+ *
14
+ * ```html
15
+ * <esp-focus-picker
16
+ * src="/assets/focus-picker-unsplash.jpg"
17
+ * alt="A woman standing in a sunlit field with her back to the camera"
18
+ * focus="0.65 0.55"
19
+ * ratio="3/1"
20
+ * compact-ratio="3/2"
21
+ * ></esp-focus-picker>
22
+ * <p>
23
+ * Photo by <a href="https://unsplash.com/@sashafreemind?utm_source=espalier&utm_medium=referral">Sasha Freemind</a>
24
+ * on <a href="https://unsplash.com/?utm_source=espalier&utm_medium=referral">Unsplash</a>.
25
+ * </p>
26
+ * <script>
27
+ * const picker = findByTagName("esp-focus-picker")[0];
28
+ * picker.addEventListener("focus-changed", (event) => {
29
+ * localStorage.setItem("banner-focus", JSON.stringify(event.detail));
30
+ * });
31
+ * </script>
32
+ * ```
33
+ *
34
+ * @event {CustomEvent<{x: number, y: number}>} focus-changed - Bubbles across
35
+ * shadow boundaries after every pointer or keyboard adjustment.
36
+ * @csspart picker - The complete control layout.
37
+ * @csspart stage - The source-image authoring surface.
38
+ * @csspart image - The source image.
39
+ * @csspart marker - The focusable focal-point marker.
40
+ * @csspart previews - The live preview group.
41
+ * @csspart preview - A live `esp-image` preview cell.
42
+ * @cssprop --esp-focus-picker-gap - Gap between the stage and previews.
43
+ * @cssprop --esp-focus-picker-stage-background - Empty/loading stage color.
44
+ * @cssprop --esp-focus-picker-marker-size - Focal marker diameter.
45
+ * @cssprop --esp-focus-picker-marker-color - Focal marker fill.
46
+ * @cssprop --esp-focus-picker-marker-border - Focal marker border.
47
+ * @cssprop --esp-focus-picker-marker-shadow - Focal marker shadow.
48
+ * @cssprop --esp-focus-picker-focus-outline - Marker focus-visible outline.
49
+ * @docPageTitle Focus Picker
50
+ * @docUrl /components/focus-picker
51
+ * @menuGroup Media
52
+ * @menuLabel Focus Picker
53
+ * @menuIcon target
54
+ */
55
+ export declare class EspalierFocusPicker extends EspalierElementBase {
56
+ /** Image URL shown in the authoring surface and live previews. */
57
+ src: string;
58
+ /** Alternative text for the source-image authoring surface. */
59
+ alt: string;
60
+ /** Normalized current value. Its HTML attribute is named `focus`. */
61
+ focusPoint: FocusPoint;
62
+ /** Aspect ratio for the wide live preview. */
63
+ ratio: string;
64
+ /** Aspect ratio for the compact live preview. */
65
+ compactRatio: string;
66
+ protected willUpdate(changedProperties: PropertyValues): void;
67
+ protected render(): import("lit-html").TemplateResult<1>;
68
+ static styles: import("lit").CSSResult[];
69
+ }
70
+ declare global {
71
+ interface HTMLElementTagNameMap {
72
+ "esp-focus-picker": EspalierFocusPicker;
73
+ }
74
+ interface HTMLElementEventMap {
75
+ "focus-changed": CustomEvent<FocusChangedDetail>;
76
+ }
77
+ }
@@ -0,0 +1,129 @@
1
+ var s=function(n,e,r,i){var c=arguments.length,o=c<3?e:i===null?i=Object.getOwnPropertyDescriptor(e,r):i,p;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")o=Reflect.decorate(n,e,r,i);else for(var l=n.length-1;l>=0;l--)(p=n[l])&&(o=(c<3?p(o):c>3?p(e,r,o):p(e,r))||o);return c>3&&o&&Object.defineProperty(e,r,o),o};import{css as d,html as f}from"lit";import{customElement as m,property as a}from"lit/decorators.js";import{styleMap as h}from"lit/directives/style-map.js";import{EspalierElementBase as u}from"../shared/esp-element-base.js";import{clampFocus as g,focusConverter as v,normalizeFocus as b}from"../image/image-focus.js";import"../image/esp-image.js";const $="focus-changed";let t=class extends u{constructor(){super(...arguments),this.src="",this.alt="",this.focusPoint={x:.5,y:.5},this.ratio="3/1",this.compactRatio="3/2",this.activePointer=null,this.handlePointerDown=e=>{e.button===0&&(e.preventDefault(),this.activePointer=e.pointerId,e.currentTarget.setPointerCapture?.(e.pointerId),this.updateFromPointer(e))},this.handlePointerMove=e=>{e.pointerId===this.activePointer&&this.updateFromPointer(e)},this.handlePointerEnd=e=>{e.pointerId===this.activePointer&&(e.currentTarget.releasePointerCapture?.(e.pointerId),this.activePointer=null)},this.handleKeyDown=e=>{const r=e.shiftKey?.01:.05,i={};if(e.key==="ArrowLeft")i.x=-r;else if(e.key==="ArrowRight")i.x=r;else if(e.key==="ArrowUp")i.y=-r;else if(e.key==="ArrowDown")i.y=r;else return;e.preventDefault(),this.updateFocus({x:this.focusPoint.x+(i.x??0),y:this.focusPoint.y+(i.y??0)})}}willUpdate(e){if(super.willUpdate(e),e.has("focusPoint")){const r=this.focusPoint,i=b(r);(i.x!==r?.x||i.y!==r?.y)&&(this.focusPoint=i)}}updateFocus(e){const r=g(e),i={x:Number(r.x.toFixed(4)),y:Number(r.y.toFixed(4))};i.x===this.focusPoint.x&&i.y===this.focusPoint.y||(this.focusPoint=i,this.dispatchEvent(new CustomEvent("focus-changed",{detail:{...i},bubbles:!0,composed:!0})))}updateFromPointer(e){const i=e.currentTarget.getBoundingClientRect();i.width<=0||i.height<=0||this.updateFocus({x:(e.clientX-i.left)/i.width,y:(e.clientY-i.top)/i.height})}render(){const e=Math.round(this.focusPoint.x*100),r=Math.round(this.focusPoint.y*100),i={"--_esp-focus-picker-x":`${this.focusPoint.x*100}%`,"--_esp-focus-picker-y":`${this.focusPoint.y*100}%`};return f`
2
+ <div part="picker" class="picker">
3
+ <div
4
+ part="stage"
5
+ class="stage"
6
+ @pointerdown=${this.handlePointerDown}
7
+ @pointermove=${this.handlePointerMove}
8
+ @pointerup=${this.handlePointerEnd}
9
+ @pointercancel=${this.handlePointerEnd}
10
+ >
11
+ <img part="image" src=${this.src} alt=${this.alt} draggable="false" />
12
+
13
+ <div
14
+ part="marker"
15
+ class="marker"
16
+ style=${h(i)}
17
+ role="slider"
18
+ tabindex="0"
19
+ aria-label="Image focal point"
20
+ aria-valuemin="0"
21
+ aria-valuemax="100"
22
+ aria-valuenow=${e}
23
+ aria-valuetext=${`Horizontal ${e}%, vertical ${r}%`}
24
+ @keydown=${this.handleKeyDown}
25
+ ></div>
26
+ </div>
27
+
28
+ <div part="previews" class="previews" aria-label="Banner framing previews">
29
+ <figure part="preview" class="preview wide">
30
+ <figcaption>Wide (${this.ratio})</figcaption>
31
+ <esp-image
32
+ banner
33
+ scrim="none"
34
+ .localImage=${this.src}
35
+ .caption=${""}
36
+ .focusPoint=${this.focusPoint}
37
+ .ratio=${this.ratio}
38
+ ></esp-image>
39
+ </figure>
40
+ <figure part="preview" class="preview compact">
41
+ <figcaption>Compact (${this.compactRatio})</figcaption>
42
+ <esp-image
43
+ banner
44
+ scrim="none"
45
+ .localImage=${this.src}
46
+ .caption=${""}
47
+ .focusPoint=${this.focusPoint}
48
+ .ratio=${this.compactRatio}
49
+ ></esp-image>
50
+ </figure>
51
+ </div>
52
+ </div>
53
+ `}};t.styles=[...u.styles,d`
54
+ :host {
55
+ display: block;
56
+ min-inline-size: 0;
57
+ }
58
+
59
+ .picker {
60
+ display: grid;
61
+ gap: var(--esp-focus-picker-gap, var(--esp-size-big));
62
+ min-inline-size: 0;
63
+ }
64
+
65
+ .stage {
66
+ position: relative;
67
+ overflow: hidden;
68
+ min-block-size: var(--esp-size-big);
69
+ border: 1px solid var(--esp-color-border);
70
+ border-radius: var(--esp-size-border-radius);
71
+ background: var(--esp-focus-picker-stage-background, var(--esp-color-layer-2));
72
+ cursor: crosshair;
73
+ touch-action: none;
74
+ user-select: none;
75
+ }
76
+
77
+ .stage img {
78
+ display: block;
79
+ inline-size: 100%;
80
+ block-size: auto;
81
+ pointer-events: none;
82
+ }
83
+
84
+ .marker {
85
+ position: absolute;
86
+ inset-inline-start: var(--_esp-focus-picker-x);
87
+ inset-block-start: var(--_esp-focus-picker-y);
88
+ inline-size: var(--esp-focus-picker-marker-size, var(--esp-size-medium));
89
+ block-size: var(--esp-focus-picker-marker-size, var(--esp-size-medium));
90
+ translate: -50% -50%;
91
+ box-sizing: border-box;
92
+ border: var(--esp-focus-picker-marker-border, 2px solid white);
93
+ border-radius: 50%;
94
+ background: var(--esp-focus-picker-marker-color, var(--esp-color-action-background));
95
+ box-shadow: var(--esp-focus-picker-marker-shadow, 0 1px 5px oklch(0 0 0 / 0.65));
96
+ cursor: grab;
97
+ }
98
+
99
+ .marker:active {
100
+ cursor: grabbing;
101
+ }
102
+ .marker:focus-visible {
103
+ outline: var(--esp-focus-picker-focus-outline, 3px solid var(--esp-color-link));
104
+ outline-offset: 3px;
105
+ }
106
+
107
+ .previews {
108
+ display: grid;
109
+ grid-template-columns: repeat(auto-fit, minmax(min(100%, 16rem), 1fr));
110
+ gap: var(--esp-focus-picker-gap, var(--esp-size-big));
111
+ min-inline-size: 0;
112
+ }
113
+
114
+ figure {
115
+ min-inline-size: 0;
116
+ margin: 0;
117
+ }
118
+ figcaption {
119
+ margin-block-end: var(--esp-size-tiny);
120
+ color: var(--esp-color-text);
121
+ font-size: var(--esp-type-small);
122
+ }
123
+
124
+ @media (prefers-reduced-motion: reduce) {
125
+ .marker {
126
+ transition: none;
127
+ }
128
+ }
129
+ `],s([a({type:String})],t.prototype,"src",void 0),s([a({type:String})],t.prototype,"alt",void 0),s([a({attribute:"focus",converter:v,reflect:!0})],t.prototype,"focusPoint",void 0),s([a({type:String})],t.prototype,"ratio",void 0),s([a({attribute:"compact-ratio",type:String})],t.prototype,"compactRatio",void 0),t=s([m("esp-focus-picker")],t);export{t as EspalierFocusPicker,$ as FOCUS_CHANGED_EVENT};
@@ -0,0 +1,47 @@
1
+ import { EspalierElementBase } from "../shared/esp-element-base.js";
2
+ /**
3
+ * A layout-only column for creator-controlled link-group stacking inside
4
+ * [`<esp-footer>`](/components/footer/).
5
+ *
6
+ * Use bare `esp-footer-link-group` children when groups should auto-flow
7
+ * independently through the footer grid. Wrap ordered groups in
8
+ * `esp-footer-column` when they must remain together as one grid item:
9
+ *
10
+ * ```html
11
+ * <esp-footer columns="3">
12
+ * <esp-footer-column>
13
+ * <esp-footer-link-group heading="Product">
14
+ * <a href="/features">Features</a>
15
+ * <a href="/pricing">Pricing</a>
16
+ * </esp-footer-link-group>
17
+ * <esp-footer-link-group heading="Company">
18
+ * <a href="/about">About</a>
19
+ * <a href="/careers">Careers</a>
20
+ * </esp-footer-link-group>
21
+ * </esp-footer-column>
22
+ * </esp-footer>
23
+ * ```
24
+ *
25
+ * The component adds no heading, landmark, or chrome. It preserves the
26
+ * slotted order of its child groups and uses `--esp-footer-row-gap`, defaulting
27
+ * to `var(--esp-size-big)`, for its vertical rhythm.
28
+ *
29
+ * @customElement esp-footer-column
30
+ * @slot - Ordered `esp-footer-link-group` children belonging to this column.
31
+ * @cssprop --esp-footer-row-gap - Vertical gap between footer grid rows and
32
+ * link groups stacked in `esp-footer-column`. Defaults to `var(--esp-size-big)`.
33
+ * @docPageTitle Footer Column
34
+ * @docUrl /components/footer/column
35
+ * @menuGroup Structure
36
+ * @menuLabel Footer Column
37
+ * @menuIcon columns
38
+ */
39
+ export declare class EspalierFooterColumn extends EspalierElementBase {
40
+ protected render(): import("lit-html").TemplateResult<1>;
41
+ static styles: import("lit").CSSResult[];
42
+ }
43
+ declare global {
44
+ interface HTMLElementTagNameMap {
45
+ "esp-footer-column": EspalierFooterColumn;
46
+ }
47
+ }
@@ -0,0 +1,8 @@
1
+ var m=function(r,o,t,l){var n=arguments.length,e=n<3?o:l===null?l=Object.getOwnPropertyDescriptor(o,t):l,s;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(r,o,t,l);else for(var f=r.length-1;f>=0;f--)(s=r[f])&&(e=(n<3?s(e):n>3?s(o,t,e):s(o,t))||e);return n>3&&e&&Object.defineProperty(o,t,e),e};import{css as c,html as a}from"lit";import{customElement as u}from"lit/decorators.js";import{EspalierElementBase as p}from"../shared/esp-element-base.js";let i=class extends p{render(){return a`<slot></slot>`}};i.styles=[...p.styles,c`
2
+ :host {
3
+ display: flex;
4
+ flex-direction: column;
5
+ gap: var(--esp-footer-row-gap, var(--esp-size-big));
6
+ min-inline-size: 0;
7
+ }
8
+ `],i=m([u("esp-footer-column")],i);export{i as EspalierFooterColumn};
@@ -1,5 +1,6 @@
1
1
  import { type PropertyValues } from "lit";
2
2
  import { EspalierElementBase } from "../shared/esp-element-base.js";
3
+ import "./esp-footer-column.js";
3
4
  import "./esp-footer-link-group.js";
4
5
  export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
5
6
  /**
@@ -7,10 +8,12 @@ export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
7
8
  * artwork, link groups, supporting actions, and legal or utility content.
8
9
  * Its background remains full-bleed while its content automatically aligns
9
10
  * to the surface of a containing [`<esp-page>`](/components/page/).
11
+ * The decorative background uses the same internal visual-layer primitive as
12
+ * `esp-image` banners; the footer's public background tokens are unchanged.
10
13
  *
11
- * Use [`<esp-footer-link-group>`](/components/footer/link-group/) children for
12
- * ordinary navigation columns. `columns` is a maximum: the grid always drops
13
- * columns when they no longer fit.
14
+ * Use bare [`<esp-footer-link-group>`](/components/footer/link-group/) children
15
+ * when navigation groups should auto-flow independently through the grid.
16
+ * `columns` is a maximum: the grid always drops columns when they no longer fit.
14
17
  *
15
18
  * ```html
16
19
  * <esp-footer
@@ -35,6 +38,33 @@ export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
35
38
  * </esp-footer>
36
39
  * ```
37
40
  *
41
+ * For creator-controlled columns, wrap each ordered stack of groups in
42
+ * [`<esp-footer-column>`](/components/footer/column/). Each wrapper is one grid
43
+ * item at wide sizes; below the footer's compact container breakpoint, the
44
+ * columns become full-width rows in their slotted order. `columns` remains the
45
+ * maximum number of grid items per row:
46
+ *
47
+ * ```html
48
+ * <esp-footer columns="3">
49
+ * <esp-footer-column>
50
+ * <esp-footer-link-group heading="Product">
51
+ * <a href="/features">Features</a>
52
+ * <a href="/pricing">Pricing</a>
53
+ * </esp-footer-link-group>
54
+ * <esp-footer-link-group heading="Company">
55
+ * <a href="/about">About</a>
56
+ * <a href="/careers">Careers</a>
57
+ * </esp-footer-link-group>
58
+ * </esp-footer-column>
59
+ * <esp-footer-column>
60
+ * <esp-footer-link-group heading="Resources">
61
+ * <a href="/docs">Documentation</a>
62
+ * <a href="/support">Support</a>
63
+ * </esp-footer-link-group>
64
+ * </esp-footer-column>
65
+ * </esp-footer>
66
+ * ```
67
+ *
38
68
  * A slotted brand replaces configured branding, while the media slot accepts
39
69
  * a responsive `picture`, native image, or `esp-image`. Media spans the
40
70
  * surface-aligned content well; use the decorative background layer for
@@ -112,7 +142,8 @@ export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
112
142
  * preferably responsive `<picture>` markup or an `esp-image` with appropriate
113
143
  * alternative text.
114
144
  * @slot brand - Custom brand identity. Overrides configured brand properties.
115
- * @slot - `esp-footer-link-group` navigation columns.
145
+ * @slot - Bare `esp-footer-link-group` children for automatic flow, or
146
+ * `esp-footer-column` children for creator-controlled group stacks.
116
147
  * @slot aside - Supporting content such as a newsletter, call to action,
117
148
  * contact details, social links, or locale controls.
118
149
  * @slot bottom - Copyright, legal/utility links, attribution, accessibility
@@ -137,7 +168,8 @@ export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
137
168
  * @cssprop --esp-footer-padding-inline - Content inline padding. Defaults to `var(--esp-size-padding-page)`.
138
169
  * @cssprop --esp-footer-section-gap - Gap between media, primary, and bottom regions. Defaults to `var(--esp-size-big)`.
139
170
  * @cssprop --esp-footer-column-gap - Gap between link-group columns and major primary regions. Defaults to `var(--esp-size-padding-page)`.
140
- * @cssprop --esp-footer-row-gap - Compact-layout row gap. Defaults to `var(--esp-size-big)`.
171
+ * @cssprop --esp-footer-row-gap - Vertical gap between footer grid rows and
172
+ * link groups stacked in `esp-footer-column`. Defaults to `var(--esp-size-big)`.
141
173
  * @cssprop --esp-footer-link-group-min-width - Intrinsic minimum link-group column width. Defaults to `10rem`.
142
174
  * @cssprop --esp-footer-link-group-gap - Space between a link-group heading and its links. Defaults to `var(--esp-size-small)`.
143
175
  * @cssprop --esp-footer-brand-logo-size - Configured logo block size. Defaults to `3rem`.
@@ -1,24 +1,24 @@
1
- var t=function(i,o,e,a){var s=arguments.length,d=s<3?o:a===null?a=Object.getOwnPropertyDescriptor(o,e):a,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")d=Reflect.decorate(i,o,e,a);else for(var p=i.length-1;p>=0;p--)(l=i[p])&&(d=(s<3?l(d):s>3?l(o,e,d):l(o,e))||d);return s>3&&d&&Object.defineProperty(o,e,d),d};import{css as f,html as v,nothing as y}from"lit";import{customElement as x,property as n,state as C}from"lit/decorators.js";import{classMap as k}from"lit/directives/class-map.js";import{styleMap as _}from"lit/directives/style-map.js";import{renderConfiguredBrand as z,resolveConfiguredBrand as B}from"../shared/configured-brand.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{slotHasContent as h}from"../shared/slot-content.js";import"./esp-footer-link-group.js";const m=new Set(["auto","1","2","3","4","5","6"]),c={media:!1,brand:!1,groups:!1,aside:!1,bottom:!1},S={fromAttribute(i){return i&&m.has(i)?i:"auto"},toAttribute(i){return m.has(i)?i:"auto"}};let r=class extends g{constructor(){super(...arguments),this.slotContent={...c},this.brandText="",this.brandLogo="",this.lightBrandLogo="",this.darkBrandLogo="",this.brandHref="",this.brandAlt="",this.brandColor="",this.lightBrandColor="",this.darkBrandColor="",this.columns="auto",this.fullBleedContent=!1,this.landmarkLabel="",this.handleSlotChange=o=>{if(!(o.target instanceof HTMLSlotElement))return;const e=this.slotRegion(o.target);if(!e)return;const a=h(o.target);this.slotContent[e]!==a&&(this.slotContent={...this.slotContent,[e]:a})}}willUpdate(o){super.willUpdate(o),o.has("columns")&&!m.has(this.columns)&&(this.columns="auto")}slotRegion(o){return o.name?["media","brand","aside","bottom"].includes(o.name)?o.name:null:"groups"}firstUpdated(o){super.firstUpdated(o);const e={...c};for(const a of this.shadowRoot?.querySelectorAll("slot")??[]){const s=this.slotRegion(a);s&&(e[s]=h(a))}Object.entries(e).some(([a,s])=>this.slotContent[a]!==s)&&(this.slotContent=e)}render(){const{media:o,brand:e,groups:a,aside:s,bottom:d}=this.slotContent,l=B({scheme:this.scheme,brandLogo:this.brandLogo,brandColor:this.brandColor,lightBrandLogo:this.lightBrandLogo,darkBrandLogo:this.darkBrandLogo,lightBrandColor:this.lightBrandColor,darkBrandColor:this.darkBrandColor}),p=e||!!(l.brandLogo||this.brandText),u=p||a||s,b={primary:!0,"has-brand":p,"has-groups":a,"has-aside":s};return v`
1
+ var t=function(i,o,a,e){var s=arguments.length,d=s<3?o:e===null?e=Object.getOwnPropertyDescriptor(o,a):e,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")d=Reflect.decorate(i,o,a,e);else for(var p=i.length-1;p>=0;p--)(l=i[p])&&(d=(s<3?l(d):s>3?l(o,a,d):l(o,a))||d);return s>3&&d&&Object.defineProperty(o,a,d),d};import{css as f,html as v,nothing as y}from"lit";import{customElement as x,property as n,state as _}from"lit/decorators.js";import{classMap as C}from"lit/directives/class-map.js";import{styleMap as k}from"lit/directives/style-map.js";import{renderConfiguredBrand as z,resolveConfiguredBrand as B}from"../shared/configured-brand.js";import{EspalierElementBase as g}from"../shared/esp-element-base.js";import{slotHasContent as h}from"../shared/slot-content.js";import{renderVisualOverlay as S,visualOverlayStyles as L}from"../shared/visual-overlay.js";import"./esp-footer-column.js";import"./esp-footer-link-group.js";const m=new Set(["auto","1","2","3","4","5","6"]),c={media:!1,brand:!1,groups:!1,aside:!1,bottom:!1},w={fromAttribute(i){return i&&m.has(i)?i:"auto"},toAttribute(i){return m.has(i)?i:"auto"}};let r=class extends g{constructor(){super(...arguments),this.slotContent={...c},this.brandText="",this.brandLogo="",this.lightBrandLogo="",this.darkBrandLogo="",this.brandHref="",this.brandAlt="",this.brandColor="",this.lightBrandColor="",this.darkBrandColor="",this.columns="auto",this.fullBleedContent=!1,this.landmarkLabel="",this.handleSlotChange=o=>{if(!(o.target instanceof HTMLSlotElement))return;const a=this.slotRegion(o.target);if(!a)return;const e=h(o.target);this.slotContent[a]!==e&&(this.slotContent={...this.slotContent,[a]:e})}}willUpdate(o){super.willUpdate(o),o.has("columns")&&!m.has(this.columns)&&(this.columns="auto")}slotRegion(o){return o.name?["media","brand","aside","bottom"].includes(o.name)?o.name:null:"groups"}firstUpdated(o){super.firstUpdated(o);const a={...c};for(const e of this.shadowRoot?.querySelectorAll("slot")??[]){const s=this.slotRegion(e);s&&(a[s]=h(e))}Object.entries(a).some(([e,s])=>this.slotContent[e]!==s)&&(this.slotContent=a)}render(){const{media:o,brand:a,groups:e,aside:s,bottom:d}=this.slotContent,l=B({scheme:this.scheme,brandLogo:this.brandLogo,brandColor:this.brandColor,lightBrandLogo:this.lightBrandLogo,darkBrandLogo:this.darkBrandLogo,lightBrandColor:this.lightBrandColor,darkBrandColor:this.darkBrandColor}),p=a||!!(l.brandLogo||this.brandText),u=p||e||s,b={primary:!0,"has-brand":p,"has-groups":e,"has-aside":s};return v`
2
2
  <footer
3
3
  part="footer"
4
4
  aria-label=${this.landmarkLabel||y}
5
- style=${_({"--_esp-footer-brand-color":l.brandColor||null})}
5
+ style=${k({"--_esp-footer-brand-color":l.brandColor||null})}
6
6
  >
7
- <div part="background" class="background" aria-hidden="true"></div>
7
+ ${S({className:"background",rootPart:"background"})}
8
8
  <div part="content" class="content-frame">
9
9
  <div class="content">
10
10
  <div part="media" class="media" ?hidden=${!o}>
11
11
  <slot name="media" @slotchange=${this.handleSlotChange}></slot>
12
12
  </div>
13
13
 
14
- <div part="primary" class=${k(b)} ?hidden=${!u}>
14
+ <div part="primary" class=${C(b)} ?hidden=${!u}>
15
15
  <div part="brand" class="brand" ?hidden=${!p}>
16
16
  <slot name="brand" @slotchange=${this.handleSlotChange}
17
17
  >${z({brandLogo:l.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt})}</slot
18
18
  >
19
19
  </div>
20
20
 
21
- <div part="groups" class="groups" ?hidden=${!a}>
21
+ <div part="groups" class="groups" ?hidden=${!e}>
22
22
  <slot @slotchange=${this.handleSlotChange}></slot>
23
23
  </div>
24
24
 
@@ -44,28 +44,23 @@ var t=function(i,o,e,a){var s=arguments.length,d=s<3?o:a===null?a=Object.getOwnP
44
44
  }
45
45
 
46
46
  footer {
47
+ --_esp-overlay-base-color: var(--esp-footer-background, var(--esp-color-layer-2));
48
+ --_esp-overlay-image: var(--esp-footer-background-image, none);
49
+ --_esp-overlay-image-opacity: var(--esp-footer-background-image-opacity, 1);
50
+ --_esp-overlay-image-repeat: var(--esp-footer-background-repeat, repeat);
51
+ --_esp-overlay-image-position: var(--esp-footer-background-position, 0 0);
52
+ --_esp-overlay-image-size: var(--esp-footer-background-size, auto);
53
+ --_esp-overlay-image-blend-mode: var(--esp-footer-background-blend-mode, normal);
54
+ --_esp-overlay-z-index: -1;
55
+
47
56
  position: relative;
48
57
  isolation: isolate;
49
58
  min-inline-size: 0;
50
59
  overflow: hidden;
51
60
  color: var(--esp-footer-color, var(--esp-color-text));
52
- background: var(--esp-footer-background, var(--esp-color-layer-2));
53
61
  border-block-start: var(--esp-footer-border, 1px solid var(--esp-color-border));
54
62
  }
55
63
 
56
- .background {
57
- position: absolute;
58
- z-index: -1;
59
- inset: 0;
60
- pointer-events: none;
61
- background-image: var(--esp-footer-background-image, none);
62
- background-repeat: var(--esp-footer-background-repeat, repeat);
63
- background-position: var(--esp-footer-background-position, 0 0);
64
- background-size: var(--esp-footer-background-size, auto);
65
- opacity: var(--esp-footer-background-image-opacity, 1);
66
- mix-blend-mode: var(--esp-footer-background-blend-mode, normal);
67
- }
68
-
69
64
  .content-frame {
70
65
  --_esp-footer-content-surplus: max(
71
66
  0px,
@@ -257,6 +252,10 @@ var t=function(i,o,e,a){var s=arguments.length,d=s<3?o:a===null?a=Object.getOwnP
257
252
  }
258
253
 
259
254
  @container esp-footer (max-width: 48rem) {
255
+ .groups ::slotted(esp-footer-column) {
256
+ grid-column: 1 / -1;
257
+ }
258
+
260
259
  .primary,
261
260
  .primary.has-brand.has-groups:not(.has-aside),
262
261
  .primary.has-groups.has-aside:not(.has-brand),
@@ -304,4 +303,4 @@ var t=function(i,o,e,a){var s=arguments.length,d=s<3?o:a===null?a=Object.getOwnP
304
303
  grid-template-areas: "aside";
305
304
  }
306
305
  }
307
- `],t([C()],r.prototype,"slotContent",void 0),t([n({attribute:"brand-text",type:String})],r.prototype,"brandText",void 0),t([n({attribute:"brand-logo",type:String})],r.prototype,"brandLogo",void 0),t([n({attribute:"light-brand-logo",type:String})],r.prototype,"lightBrandLogo",void 0),t([n({attribute:"dark-brand-logo",type:String})],r.prototype,"darkBrandLogo",void 0),t([n({attribute:"brand-href",type:String})],r.prototype,"brandHref",void 0),t([n({attribute:"brand-alt",type:String})],r.prototype,"brandAlt",void 0),t([n({attribute:"brand-color",type:String})],r.prototype,"brandColor",void 0),t([n({attribute:"light-brand-color",type:String})],r.prototype,"lightBrandColor",void 0),t([n({attribute:"dark-brand-color",type:String})],r.prototype,"darkBrandColor",void 0),t([n({converter:S,reflect:!0})],r.prototype,"columns",void 0),t([n({attribute:"full-bleed-content",type:Boolean,reflect:!0})],r.prototype,"fullBleedContent",void 0),t([n({attribute:"landmark-label",type:String})],r.prototype,"landmarkLabel",void 0),r=t([x("esp-footer")],r);export{r as EspalierFooter};
306
+ `,L],t([_()],r.prototype,"slotContent",void 0),t([n({attribute:"brand-text",type:String})],r.prototype,"brandText",void 0),t([n({attribute:"brand-logo",type:String})],r.prototype,"brandLogo",void 0),t([n({attribute:"light-brand-logo",type:String})],r.prototype,"lightBrandLogo",void 0),t([n({attribute:"dark-brand-logo",type:String})],r.prototype,"darkBrandLogo",void 0),t([n({attribute:"brand-href",type:String})],r.prototype,"brandHref",void 0),t([n({attribute:"brand-alt",type:String})],r.prototype,"brandAlt",void 0),t([n({attribute:"brand-color",type:String})],r.prototype,"brandColor",void 0),t([n({attribute:"light-brand-color",type:String})],r.prototype,"lightBrandColor",void 0),t([n({attribute:"dark-brand-color",type:String})],r.prototype,"darkBrandColor",void 0),t([n({converter:w,reflect:!0})],r.prototype,"columns",void 0),t([n({attribute:"full-bleed-content",type:Boolean,reflect:!0})],r.prototype,"fullBleedContent",void 0),t([n({attribute:"landmark-label",type:String})],r.prototype,"landmarkLabel",void 0),r=t([x("esp-footer")],r);export{r as EspalierFooter};
@@ -1,2 +1,3 @@
1
+ export * from "./esp-footer-column.js";
1
2
  export * from "./esp-footer-link-group.js";
2
3
  export * from "./esp-footer.js";
@@ -1 +1 @@
1
- export*from"./esp-footer-link-group.js";export*from"./esp-footer.js";
1
+ export*from"./esp-footer-column.js";export*from"./esp-footer-link-group.js";export*from"./esp-footer.js";