@taprootio/espalier 2.3.1 → 2.5.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/CHANGELOG.md +26 -0
- package/custom-elements.json +4152 -2209
- package/dist/data-cell/esp-data-cell.js +1 -1
- package/dist/footer/esp-footer-link-group.d.ts +40 -0
- package/dist/footer/esp-footer-link-group.js +57 -0
- package/dist/footer/esp-footer.d.ts +217 -0
- package/dist/footer/esp-footer.js +307 -0
- package/dist/footer/index.d.ts +2 -0
- package/dist/footer/index.js +1 -0
- package/dist/header/esp-header.d.ts +59 -6
- package/dist/header/esp-header.js +15 -17
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/menu/esp-menu.d.ts +14 -1
- package/dist/menu/esp-menu.js +3 -4
- package/dist/page/esp-page.d.ts +9 -6
- package/dist/page/esp-page.js +33 -11
- package/dist/shared/configured-brand.js +4 -0
- package/dist/shared/events.d.ts +7 -0
- package/dist/shared/events.js +1 -1
- package/dist/shared/slot-content.js +1 -0
- package/dist/slider/esp-slider.js +2 -2
- package/espalier.token-manifest.json +144 -0
- package/package.json +10 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
var c=function(
|
|
1
|
+
var c=function(a,e,s,n){var r=arguments.length,t=r<3?e:n===null?n=Object.getOwnPropertyDescriptor(e,s):n,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")t=Reflect.decorate(a,e,s,n);else for(var i=a.length-1;i>=0;i--)(l=a[i])&&(t=(r<3?l(t):r>3?l(e,s,t):l(e,s))||t);return r>3&&t&&Object.defineProperty(e,s,t),t};import{css as h,html as m}from"lit";import{customElement as y,property as f,state as u}from"lit/decorators.js";import{classMap as g}from"lit/directives/class-map.js";import{createRef as S,ref as p}from"lit/directives/ref.js";import{EspalierElementBase as d}from"../shared/esp-element-base.js";import{SlottedIconController as v}from"../shared/slotted-icon-controller.js";import{slotHasContent as w}from"../shared/slot-content.js";let o=class extends d{constructor(){super(...arguments),this.iconSlot=new v(this),this.secondarySlot=S(),this.hasSecondary=!1,this.truncate=!1,this.handleSecondarySlotChange=()=>{this.hasSecondary=w(this.secondarySlot.value)}}firstUpdated(e){super.firstUpdated(e),this.iconSlot.handleSlotChange(),this.handleSecondarySlotChange()}render(){const e={cell:!0,"has-icon":this.iconSlot.hasAssignedSlotContent,"has-secondary":this.hasSecondary,truncate:this.truncate};return m`
|
|
2
2
|
<span part="cell" class=${g(e)}>
|
|
3
3
|
<span part="icon" class="icon">
|
|
4
4
|
<slot
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { EspalierElementBase } from "../shared/esp-element-base.js";
|
|
2
|
+
/**
|
|
3
|
+
* A labelled group of related links inside [`<esp-footer>`](/components/footer/).
|
|
4
|
+
* Supply ordinary anchors in the default slot; the component provides the
|
|
5
|
+
* compact vertical rhythm and an accessible navigation landmark.
|
|
6
|
+
*
|
|
7
|
+
* ```html
|
|
8
|
+
* <esp-footer-link-group heading="Explore">
|
|
9
|
+
* <a href="/components">Components</a>
|
|
10
|
+
* <a href="/guides">Guides</a>
|
|
11
|
+
* <a href="/api">API</a>
|
|
12
|
+
* </esp-footer-link-group>
|
|
13
|
+
* ```
|
|
14
|
+
*
|
|
15
|
+
* @customElement esp-footer-link-group
|
|
16
|
+
* @slot - Links belonging to the group. Native anchors are preferred because
|
|
17
|
+
* footer links do not need application-menu disclosure or drawer behavior.
|
|
18
|
+
* @csspart nav - The group's navigation landmark.
|
|
19
|
+
* @csspart heading - The visible heading used to label the navigation landmark.
|
|
20
|
+
* @csspart links - The link-list container.
|
|
21
|
+
* @docPageTitle Footer Link Group
|
|
22
|
+
* @docUrl /components/footer/link-group
|
|
23
|
+
* @menuGroup Navigation
|
|
24
|
+
* @menuIcon list-details
|
|
25
|
+
*/
|
|
26
|
+
export declare class EspalierFooterLinkGroup extends EspalierElementBase {
|
|
27
|
+
/**
|
|
28
|
+
* Visible heading for the link group. It also labels the navigation
|
|
29
|
+
* landmark. When omitted, the landmark receives the fallback label
|
|
30
|
+
* “Footer links” without rendering an empty heading.
|
|
31
|
+
*/
|
|
32
|
+
heading: string;
|
|
33
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
34
|
+
static styles: import("lit").CSSResult[];
|
|
35
|
+
}
|
|
36
|
+
declare global {
|
|
37
|
+
interface HTMLElementTagNameMap {
|
|
38
|
+
"esp-footer-link-group": EspalierFooterLinkGroup;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var d=function(t,o,r,n){var s=arguments.length,e=s<3?o:n===null?n=Object.getOwnPropertyDescriptor(o,r):n,l;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")e=Reflect.decorate(t,o,r,n);else for(var a=t.length-1;a>=0;a--)(l=t[a])&&(e=(s<3?l(e):s>3?l(o,r,e):l(o,r))||e);return s>3&&e&&Object.defineProperty(o,r,e),e};import{css as v,html as f,nothing as p}from"lit";import{customElement as g,property as u}from"lit/decorators.js";import{EspalierElementBase as c}from"../shared/esp-element-base.js";const h="esp-footer-link-group-heading";let i=class extends c{constructor(){super(...arguments),this.heading=""}render(){return f`
|
|
2
|
+
<nav
|
|
3
|
+
part="nav"
|
|
4
|
+
aria-labelledby=${this.heading?h:p}
|
|
5
|
+
aria-label=${this.heading?p:"Footer links"}
|
|
6
|
+
>
|
|
7
|
+
${this.heading?f`<h2 part="heading" id=${h}>${this.heading}</h2>`:p}
|
|
8
|
+
<div part="links" class="links"><slot></slot></div>
|
|
9
|
+
</nav>
|
|
10
|
+
`}};i.styles=[...c.styles,v`
|
|
11
|
+
:host {
|
|
12
|
+
display: block;
|
|
13
|
+
min-inline-size: 0;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
nav {
|
|
17
|
+
display: grid;
|
|
18
|
+
gap: var(--esp-footer-link-group-gap, var(--esp-size-small));
|
|
19
|
+
min-inline-size: 0;
|
|
20
|
+
color: var(--esp-footer-color, var(--esp-color-text));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
h2 {
|
|
24
|
+
margin: 0;
|
|
25
|
+
color: var(--esp-footer-heading-color, var(--esp-color-headings));
|
|
26
|
+
font-family: var(--esp-font-headings);
|
|
27
|
+
font-size: var(--esp-type-normal);
|
|
28
|
+
font-weight: var(--esp-font-weight-headings);
|
|
29
|
+
line-height: 1.25;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.links {
|
|
33
|
+
display: grid;
|
|
34
|
+
gap: var(--esp-size-tiny);
|
|
35
|
+
min-inline-size: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
::slotted(a) {
|
|
39
|
+
inline-size: fit-content;
|
|
40
|
+
max-inline-size: 100%;
|
|
41
|
+
color: var(--esp-footer-link-color, var(--esp-color-link));
|
|
42
|
+
overflow-wrap: anywhere;
|
|
43
|
+
text-decoration: none;
|
|
44
|
+
text-underline-offset: 0.18em;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
::slotted(a:hover) {
|
|
48
|
+
color: var(--esp-footer-link-hover-color, var(--esp-color-link-hover));
|
|
49
|
+
text-decoration: underline;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
::slotted(a:focus-visible) {
|
|
53
|
+
border-radius: var(--esp-size-border-radius);
|
|
54
|
+
outline: var(--esp-footer-focus-outline, 2px solid var(--esp-color-link));
|
|
55
|
+
outline-offset: 3px;
|
|
56
|
+
}
|
|
57
|
+
`],d([u({type:String})],i.prototype,"heading",void 0),i=d([g("esp-footer-link-group")],i);export{i as EspalierFooterLinkGroup};
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import { type PropertyValues } from "lit";
|
|
2
|
+
import { EspalierElementBase } from "../shared/esp-element-base.js";
|
|
3
|
+
import "./esp-footer-link-group.js";
|
|
4
|
+
export type FooterColumns = "auto" | "1" | "2" | "3" | "4" | "5" | "6";
|
|
5
|
+
/**
|
|
6
|
+
* A responsive site footer with structured spaces for branding, feature
|
|
7
|
+
* artwork, link groups, supporting actions, and legal or utility content.
|
|
8
|
+
* Its background remains full-bleed while its content automatically aligns
|
|
9
|
+
* to the surface of a containing [`<esp-page>`](/components/page/).
|
|
10
|
+
*
|
|
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
|
+
*
|
|
15
|
+
* ```html
|
|
16
|
+
* <esp-footer
|
|
17
|
+
* light-brand-logo="/assets/logo-light.svg"
|
|
18
|
+
* dark-brand-logo="/assets/logo-dark.svg"
|
|
19
|
+
* brand-text="Espalier"
|
|
20
|
+
* brand-href="/"
|
|
21
|
+
* brand-alt="Espalier logo"
|
|
22
|
+
* light-brand-color="oklch(0.35 0.12 216)"
|
|
23
|
+
* dark-brand-color="oklch(0.9 0.08 216)"
|
|
24
|
+
* columns="3">
|
|
25
|
+
* <esp-footer-link-group heading="Explore">
|
|
26
|
+
* <a href="/components">Components</a>
|
|
27
|
+
* <a href="/api">API</a>
|
|
28
|
+
* </esp-footer-link-group>
|
|
29
|
+
* <esp-footer-link-group heading="Learn">
|
|
30
|
+
* <a href="/guides/getting-started">Getting started</a>
|
|
31
|
+
* <a href="/guides/styling">Styling</a>
|
|
32
|
+
* </esp-footer-link-group>
|
|
33
|
+
* <p slot="aside">Themeable web components built on web standards.</p>
|
|
34
|
+
* <div slot="bottom">Copyright 2026 Example Organization</div>
|
|
35
|
+
* </esp-footer>
|
|
36
|
+
* ```
|
|
37
|
+
*
|
|
38
|
+
* A slotted brand replaces configured branding, while the media slot accepts
|
|
39
|
+
* a responsive `picture`, native image, or `esp-image`. Media spans the
|
|
40
|
+
* surface-aligned content well; use the decorative background layer for
|
|
41
|
+
* edge-to-edge artwork:
|
|
42
|
+
*
|
|
43
|
+
* ```html
|
|
44
|
+
* <esp-footer columns="4">
|
|
45
|
+
* <picture slot="media">
|
|
46
|
+
* <source media="(prefers-color-scheme: dark)" srcset="/assets/canvas-bg-dark.jpg" />
|
|
47
|
+
* <img
|
|
48
|
+
* src="/assets/canvas-bg.jpg"
|
|
49
|
+
* alt="A colorful floral pattern"
|
|
50
|
+
* style="display: block; width: 100%; height: auto;" />
|
|
51
|
+
* </picture>
|
|
52
|
+
* <a slot="brand" href="/" aria-label="Espalier home">
|
|
53
|
+
* <img src="/assets/espalier-logo.svg" alt="Espalier" />
|
|
54
|
+
* </a>
|
|
55
|
+
* <esp-footer-link-group heading="Product">
|
|
56
|
+
* <a href="/components">Components</a>
|
|
57
|
+
* </esp-footer-link-group>
|
|
58
|
+
* </esp-footer>
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* Decorative art uses an image layer independent of the base color. The same
|
|
62
|
+
* API supports a repeating landscape band or one large cover image:
|
|
63
|
+
*
|
|
64
|
+
* ```html
|
|
65
|
+
* <style>
|
|
66
|
+
* esp-footer.mountains {
|
|
67
|
+
* --esp-footer-background: oklch(0.48 0.12 145);
|
|
68
|
+
* --esp-footer-background-image-opacity: 0.55;
|
|
69
|
+
* --esp-footer-background-image:
|
|
70
|
+
* linear-gradient(to bottom, transparent 8rem, oklch(0.48 0.12 145)),
|
|
71
|
+
* url("/assets/espalier-geometric-texture.png");
|
|
72
|
+
* --esp-footer-background-repeat: no-repeat, repeat-x;
|
|
73
|
+
* --esp-footer-background-position: 0 0, top;
|
|
74
|
+
* --esp-footer-background-size: 100% 100%, auto 10rem;
|
|
75
|
+
* --esp-footer-padding-block: 6rem;
|
|
76
|
+
* }
|
|
77
|
+
*
|
|
78
|
+
* esp-footer.photo {
|
|
79
|
+
* --esp-footer-background: oklch(0.2 0.04 216);
|
|
80
|
+
* --esp-footer-heading-color: white;
|
|
81
|
+
* --esp-footer-background-image:
|
|
82
|
+
* linear-gradient(oklch(0.1 0 0 / 0.55), oklch(0.1 0 0 / 0.55)),
|
|
83
|
+
* url("/assets/canvas-bg.jpg");
|
|
84
|
+
* --esp-footer-background-repeat: no-repeat;
|
|
85
|
+
* --esp-footer-background-position: center;
|
|
86
|
+
* --esp-footer-background-size: cover;
|
|
87
|
+
* }
|
|
88
|
+
* </style>
|
|
89
|
+
* <esp-footer class="mountains" brand-text="Mountain Studio"></esp-footer>
|
|
90
|
+
* <esp-footer class="photo" brand-text="Photo Studio"></esp-footer>
|
|
91
|
+
* ```
|
|
92
|
+
*
|
|
93
|
+
* Surface alignment is automatic inside `esp-page`; opt out only when the
|
|
94
|
+
* footer's content should also span the entire bar:
|
|
95
|
+
*
|
|
96
|
+
* ```html
|
|
97
|
+
* <esp-page align="center" style="--esp-page-max-width: 36rem;">
|
|
98
|
+
* <main>Surface-aligned page content</main>
|
|
99
|
+
* <esp-footer slot="footer" brand-text="Aligned Studio" columns="3">
|
|
100
|
+
* <esp-footer-link-group heading="Explore">
|
|
101
|
+
* <a href="/work">Work</a>
|
|
102
|
+
* <a href="/about">About</a>
|
|
103
|
+
* </esp-footer-link-group>
|
|
104
|
+
* </esp-footer>
|
|
105
|
+
* </esp-page>
|
|
106
|
+
*
|
|
107
|
+
* <esp-footer full-bleed-content brand-text="Full-width Studio"></esp-footer>
|
|
108
|
+
* ```
|
|
109
|
+
*
|
|
110
|
+
* @customElement esp-footer
|
|
111
|
+
* @slot media - Meaningful artwork spanning the surface-aligned content well,
|
|
112
|
+
* preferably responsive `<picture>` markup or an `esp-image` with appropriate
|
|
113
|
+
* alternative text.
|
|
114
|
+
* @slot brand - Custom brand identity. Overrides configured brand properties.
|
|
115
|
+
* @slot - `esp-footer-link-group` navigation columns.
|
|
116
|
+
* @slot aside - Supporting content such as a newsletter, call to action,
|
|
117
|
+
* contact details, social links, or locale controls.
|
|
118
|
+
* @slot bottom - Copyright, legal/utility links, attribution, accessibility
|
|
119
|
+
* controls, site credit, or a final wordmark.
|
|
120
|
+
* @csspart footer - The native footer landmark and full-bleed base surface.
|
|
121
|
+
* @csspart background - The independent decorative image layer.
|
|
122
|
+
* @csspart content - The surface-aligned content wrapper.
|
|
123
|
+
* @csspart media - The media region spanning the aligned content well.
|
|
124
|
+
* @csspart primary - The grid containing brand, link groups, and aside content.
|
|
125
|
+
* @csspart brand - The brand region.
|
|
126
|
+
* @csspart groups - The link-group grid.
|
|
127
|
+
* @csspart aside - The supporting-content region.
|
|
128
|
+
* @csspart bottom - The final legal/utility region.
|
|
129
|
+
* @cssprop --esp-footer-background - Base footer color. Defaults to `var(--esp-color-layer-2)`.
|
|
130
|
+
* @cssprop --esp-footer-color - Body text color. Defaults to `var(--esp-color-text)`.
|
|
131
|
+
* @cssprop --esp-footer-heading-color - Heading and configured-brand color. Defaults to `var(--esp-color-headings)`.
|
|
132
|
+
* @cssprop --esp-footer-link-color - Link color. Defaults to `var(--esp-color-link)`.
|
|
133
|
+
* @cssprop --esp-footer-link-hover-color - Hovered link color. Defaults to `var(--esp-color-link-hover)`.
|
|
134
|
+
* @cssprop --esp-footer-focus-outline - Focus-visible outline. Defaults to `2px solid var(--esp-color-link)`.
|
|
135
|
+
* @cssprop --esp-footer-border - Block-start footer border. Defaults to `1px solid var(--esp-color-border)`.
|
|
136
|
+
* @cssprop --esp-footer-padding-block - Content block padding. Defaults to `var(--esp-size-padding-page)`.
|
|
137
|
+
* @cssprop --esp-footer-padding-inline - Content inline padding. Defaults to `var(--esp-size-padding-page)`.
|
|
138
|
+
* @cssprop --esp-footer-section-gap - Gap between media, primary, and bottom regions. Defaults to `var(--esp-size-big)`.
|
|
139
|
+
* @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)`.
|
|
141
|
+
* @cssprop --esp-footer-link-group-min-width - Intrinsic minimum link-group column width. Defaults to `10rem`.
|
|
142
|
+
* @cssprop --esp-footer-link-group-gap - Space between a link-group heading and its links. Defaults to `var(--esp-size-small)`.
|
|
143
|
+
* @cssprop --esp-footer-brand-logo-size - Configured logo block size. Defaults to `3rem`.
|
|
144
|
+
* @cssprop --esp-footer-brand-logo-max-width - Configured logo maximum inline size. Defaults to `12rem`.
|
|
145
|
+
* @cssprop --esp-footer-background-image - Decorative image or gradient layer. Defaults to `none`.
|
|
146
|
+
* @cssprop --esp-footer-background-image-opacity - Decorative layer opacity. Defaults to `1`.
|
|
147
|
+
* @cssprop --esp-footer-background-repeat - Decorative layer repeat behavior. Defaults to `repeat`.
|
|
148
|
+
* @cssprop --esp-footer-background-position - Decorative layer position. Defaults to `0 0`.
|
|
149
|
+
* @cssprop --esp-footer-background-size - Decorative layer size. Defaults to `auto`.
|
|
150
|
+
* @cssprop --esp-footer-background-blend-mode - Decorative layer blend mode. Defaults to `normal`.
|
|
151
|
+
* @cssprop --esp-footer-content-max-width - Surface-alignment cap published by `esp-page`. Defaults to `100%`.
|
|
152
|
+
* @cssprop --esp-footer-content-lead - Fraction of surplus placed before content (`0`, `0.5`, or `1`). Defaults to `0`.
|
|
153
|
+
* @docPageTitle Footer
|
|
154
|
+
* @docUrl /components/footer
|
|
155
|
+
* @menuGroup Structure
|
|
156
|
+
* @menuLabel Footer
|
|
157
|
+
* @menuIcon layout
|
|
158
|
+
*/
|
|
159
|
+
export declare class EspalierFooter extends EspalierElementBase {
|
|
160
|
+
/** Configured brand text used when the `brand` slot is empty. */
|
|
161
|
+
brandText: string;
|
|
162
|
+
/** Configured brand logo URL used when the `brand` slot is empty. */
|
|
163
|
+
brandLogo: string;
|
|
164
|
+
/**
|
|
165
|
+
* Configured brand logo URL used in light scheme. A non-empty value
|
|
166
|
+
* overrides `brand-logo`; an empty value falls back to it.
|
|
167
|
+
*/
|
|
168
|
+
lightBrandLogo: string;
|
|
169
|
+
/**
|
|
170
|
+
* Configured brand logo URL used in dark scheme. A non-empty value
|
|
171
|
+
* overrides `brand-logo`; an empty value falls back to it.
|
|
172
|
+
*/
|
|
173
|
+
darkBrandLogo: string;
|
|
174
|
+
/** Optional configured-brand link target. */
|
|
175
|
+
brandHref: string;
|
|
176
|
+
/** Accessible text for a configured logo. */
|
|
177
|
+
brandAlt: string;
|
|
178
|
+
/**
|
|
179
|
+
* Optional configured brand color. Scheme-specific colors override it;
|
|
180
|
+
* when all configured colors are empty, `--esp-footer-heading-color`
|
|
181
|
+
* remains the fallback.
|
|
182
|
+
*/
|
|
183
|
+
brandColor: string;
|
|
184
|
+
/**
|
|
185
|
+
* Configured brand color used in light scheme. A non-empty value
|
|
186
|
+
* overrides `brand-color`; an empty value falls back to it and then
|
|
187
|
+
* `--esp-footer-heading-color`.
|
|
188
|
+
*/
|
|
189
|
+
lightBrandColor: string;
|
|
190
|
+
/**
|
|
191
|
+
* Configured brand color used in dark scheme. A non-empty value
|
|
192
|
+
* overrides `brand-color`; an empty value falls back to it and then
|
|
193
|
+
* `--esp-footer-heading-color`.
|
|
194
|
+
*/
|
|
195
|
+
darkBrandColor: string;
|
|
196
|
+
/**
|
|
197
|
+
* Maximum number of link-group columns. Numeric values cap the wide layout;
|
|
198
|
+
* the intrinsic grid still renders fewer columns when space is limited.
|
|
199
|
+
*/
|
|
200
|
+
columns: FooterColumns;
|
|
201
|
+
/**
|
|
202
|
+
* Opt out of the `esp-page` surface-alignment contract and allow footer
|
|
203
|
+
* content to use the full bar width. The background is always full-bleed.
|
|
204
|
+
*/
|
|
205
|
+
fullBleedContent: boolean;
|
|
206
|
+
/** Optional accessible label for pages containing multiple footer landmarks. */
|
|
207
|
+
landmarkLabel: string;
|
|
208
|
+
protected willUpdate(changedProperties: PropertyValues): void;
|
|
209
|
+
protected firstUpdated(changedProperties: PropertyValues): void;
|
|
210
|
+
protected render(): import("lit-html").TemplateResult<1>;
|
|
211
|
+
static styles: import("lit").CSSResult[];
|
|
212
|
+
}
|
|
213
|
+
declare global {
|
|
214
|
+
interface HTMLElementTagNameMap {
|
|
215
|
+
"esp-footer": EspalierFooter;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
@@ -0,0 +1,307 @@
|
|
|
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`
|
|
2
|
+
<footer
|
|
3
|
+
part="footer"
|
|
4
|
+
aria-label=${this.landmarkLabel||y}
|
|
5
|
+
style=${_({"--_esp-footer-brand-color":l.brandColor||null})}
|
|
6
|
+
>
|
|
7
|
+
<div part="background" class="background" aria-hidden="true"></div>
|
|
8
|
+
<div part="content" class="content-frame">
|
|
9
|
+
<div class="content">
|
|
10
|
+
<div part="media" class="media" ?hidden=${!o}>
|
|
11
|
+
<slot name="media" @slotchange=${this.handleSlotChange}></slot>
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
<div part="primary" class=${k(b)} ?hidden=${!u}>
|
|
15
|
+
<div part="brand" class="brand" ?hidden=${!p}>
|
|
16
|
+
<slot name="brand" @slotchange=${this.handleSlotChange}
|
|
17
|
+
>${z({brandLogo:l.brandLogo,brandText:this.brandText,brandHref:this.brandHref,brandAlt:this.brandAlt})}</slot
|
|
18
|
+
>
|
|
19
|
+
</div>
|
|
20
|
+
|
|
21
|
+
<div part="groups" class="groups" ?hidden=${!a}>
|
|
22
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
<div part="aside" class="aside" ?hidden=${!s}>
|
|
26
|
+
<slot name="aside" @slotchange=${this.handleSlotChange}></slot>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<div part="bottom" class="bottom" ?hidden=${!d}>
|
|
31
|
+
<slot name="bottom" @slotchange=${this.handleSlotChange}></slot>
|
|
32
|
+
</div>
|
|
33
|
+
</div>
|
|
34
|
+
</div>
|
|
35
|
+
</footer>
|
|
36
|
+
`}};r.styles=[...g.styles,f`
|
|
37
|
+
:host {
|
|
38
|
+
display: block;
|
|
39
|
+
min-inline-size: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
[hidden] {
|
|
43
|
+
display: none !important;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
footer {
|
|
47
|
+
position: relative;
|
|
48
|
+
isolation: isolate;
|
|
49
|
+
min-inline-size: 0;
|
|
50
|
+
overflow: hidden;
|
|
51
|
+
color: var(--esp-footer-color, var(--esp-color-text));
|
|
52
|
+
background: var(--esp-footer-background, var(--esp-color-layer-2));
|
|
53
|
+
border-block-start: var(--esp-footer-border, 1px solid var(--esp-color-border));
|
|
54
|
+
}
|
|
55
|
+
|
|
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
|
+
.content-frame {
|
|
70
|
+
--_esp-footer-content-surplus: max(
|
|
71
|
+
0px,
|
|
72
|
+
calc(100% - var(--esp-footer-content-max-width, 100%))
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
box-sizing: border-box;
|
|
76
|
+
min-inline-size: 0;
|
|
77
|
+
padding-inline: calc(var(--_esp-footer-content-surplus) * var(--esp-footer-content-lead, 0))
|
|
78
|
+
calc(var(--_esp-footer-content-surplus) * (1 - var(--esp-footer-content-lead, 0)));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
:host([full-bleed-content]) .content-frame {
|
|
82
|
+
padding-inline: 0;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.content {
|
|
86
|
+
display: grid;
|
|
87
|
+
container: esp-footer / inline-size;
|
|
88
|
+
gap: var(--esp-footer-section-gap, var(--esp-size-big));
|
|
89
|
+
min-inline-size: 0;
|
|
90
|
+
padding-block: var(--esp-footer-padding-block, var(--esp-size-padding-page))
|
|
91
|
+
calc(
|
|
92
|
+
var(--esp-footer-padding-block, var(--esp-size-padding-page)) +
|
|
93
|
+
env(safe-area-inset-bottom, 0px)
|
|
94
|
+
);
|
|
95
|
+
padding-inline: var(--esp-footer-padding-inline, var(--esp-size-padding-page));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.media,
|
|
99
|
+
.primary,
|
|
100
|
+
.brand,
|
|
101
|
+
.groups,
|
|
102
|
+
.aside,
|
|
103
|
+
.bottom {
|
|
104
|
+
min-inline-size: 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.media ::slotted(img),
|
|
108
|
+
.media ::slotted(picture),
|
|
109
|
+
.media ::slotted(esp-image) {
|
|
110
|
+
display: block;
|
|
111
|
+
inline-size: 100%;
|
|
112
|
+
max-inline-size: 100%;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.primary {
|
|
116
|
+
display: grid;
|
|
117
|
+
grid-template-columns: minmax(10rem, 1fr) minmax(0, 3fr) minmax(10rem, 1fr);
|
|
118
|
+
grid-template-areas: "brand groups aside";
|
|
119
|
+
gap: var(--esp-footer-row-gap, var(--esp-size-big))
|
|
120
|
+
var(--esp-footer-column-gap, var(--esp-size-padding-page));
|
|
121
|
+
align-items: start;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.primary.has-brand.has-groups:not(.has-aside),
|
|
125
|
+
.primary.has-groups.has-aside:not(.has-brand) {
|
|
126
|
+
grid-template-columns: minmax(10rem, 1fr) minmax(0, 3fr);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.primary.has-brand.has-groups:not(.has-aside) {
|
|
130
|
+
grid-template-areas: "brand groups";
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.primary.has-groups.has-aside:not(.has-brand) {
|
|
134
|
+
grid-template-areas: "groups aside";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.primary.has-brand.has-aside:not(.has-groups) {
|
|
138
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
139
|
+
grid-template-areas: "brand aside";
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.primary.has-brand:not(.has-groups):not(.has-aside) {
|
|
143
|
+
grid-template-columns: minmax(0, 1fr);
|
|
144
|
+
grid-template-areas: "brand";
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.primary.has-groups:not(.has-brand):not(.has-aside) {
|
|
148
|
+
grid-template-columns: minmax(0, 1fr);
|
|
149
|
+
grid-template-areas: "groups";
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.primary.has-aside:not(.has-brand):not(.has-groups) {
|
|
153
|
+
grid-template-columns: minmax(0, 1fr);
|
|
154
|
+
grid-template-areas: "aside";
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.brand {
|
|
158
|
+
grid-area: brand;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.groups {
|
|
162
|
+
--_esp-footer-column-gap: var(--esp-footer-column-gap, var(--esp-size-padding-page));
|
|
163
|
+
--_esp-footer-column-min: var(--esp-footer-link-group-min-width, 10rem);
|
|
164
|
+
--_esp-footer-column-basis: var(--_esp-footer-column-min);
|
|
165
|
+
|
|
166
|
+
grid-area: groups;
|
|
167
|
+
display: grid;
|
|
168
|
+
grid-template-columns: repeat(
|
|
169
|
+
auto-fit,
|
|
170
|
+
minmax(min(100%, var(--_esp-footer-column-basis)), 1fr)
|
|
171
|
+
);
|
|
172
|
+
gap: var(--esp-footer-row-gap, var(--esp-size-big)) var(--_esp-footer-column-gap);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
:host([columns="1"]) .groups {
|
|
176
|
+
--_esp-footer-column-basis: 100%;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
:host([columns="2"]) .groups {
|
|
180
|
+
--_esp-footer-column-basis: max(
|
|
181
|
+
var(--_esp-footer-column-min),
|
|
182
|
+
calc(50% - var(--_esp-footer-column-gap))
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
:host([columns="3"]) .groups {
|
|
187
|
+
--_esp-footer-column-basis: max(
|
|
188
|
+
var(--_esp-footer-column-min),
|
|
189
|
+
calc(33.3333% - var(--_esp-footer-column-gap))
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
:host([columns="4"]) .groups {
|
|
194
|
+
--_esp-footer-column-basis: max(
|
|
195
|
+
var(--_esp-footer-column-min),
|
|
196
|
+
calc(25% - var(--_esp-footer-column-gap))
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
:host([columns="5"]) .groups {
|
|
201
|
+
--_esp-footer-column-basis: max(
|
|
202
|
+
var(--_esp-footer-column-min),
|
|
203
|
+
calc(20% - var(--_esp-footer-column-gap))
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
:host([columns="6"]) .groups {
|
|
208
|
+
--_esp-footer-column-basis: max(
|
|
209
|
+
var(--_esp-footer-column-min),
|
|
210
|
+
calc(16.6667% - var(--_esp-footer-column-gap))
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
.aside {
|
|
215
|
+
grid-area: aside;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.configured-brand {
|
|
219
|
+
display: inline-flex;
|
|
220
|
+
align-items: center;
|
|
221
|
+
gap: var(--esp-size-small);
|
|
222
|
+
max-inline-size: 100%;
|
|
223
|
+
color: var(
|
|
224
|
+
--_esp-footer-brand-color,
|
|
225
|
+
var(--esp-footer-heading-color, var(--esp-color-headings))
|
|
226
|
+
);
|
|
227
|
+
font-family: var(--esp-font-brand, var(--esp-font-headings));
|
|
228
|
+
font-size: var(--esp-type-medium);
|
|
229
|
+
font-weight: var(--esp-font-weight-brand, var(--esp-font-weight-headings));
|
|
230
|
+
line-height: 1.1;
|
|
231
|
+
overflow-wrap: anywhere;
|
|
232
|
+
text-decoration: none;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
a.configured-brand:hover {
|
|
236
|
+
color: var(--esp-footer-link-hover-color, var(--esp-color-link-hover));
|
|
237
|
+
text-decoration: underline;
|
|
238
|
+
text-underline-offset: 0.18em;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
a.configured-brand:focus-visible {
|
|
242
|
+
border-radius: var(--esp-size-border-radius);
|
|
243
|
+
outline: var(--esp-footer-focus-outline, 2px solid var(--esp-color-link));
|
|
244
|
+
outline-offset: 3px;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.brand-logo {
|
|
248
|
+
display: block;
|
|
249
|
+
inline-size: auto;
|
|
250
|
+
max-inline-size: min(var(--esp-footer-brand-logo-max-width, 12rem), 100%);
|
|
251
|
+
block-size: var(--esp-footer-brand-logo-size, 3rem);
|
|
252
|
+
object-fit: contain;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.brand-text {
|
|
256
|
+
min-inline-size: 0;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
@container esp-footer (max-width: 48rem) {
|
|
260
|
+
.primary,
|
|
261
|
+
.primary.has-brand.has-groups:not(.has-aside),
|
|
262
|
+
.primary.has-groups.has-aside:not(.has-brand),
|
|
263
|
+
.primary.has-brand.has-aside:not(.has-groups),
|
|
264
|
+
.primary.has-brand:not(.has-groups):not(.has-aside),
|
|
265
|
+
.primary.has-groups:not(.has-brand):not(.has-aside),
|
|
266
|
+
.primary.has-aside:not(.has-brand):not(.has-groups) {
|
|
267
|
+
grid-template-columns: minmax(0, 1fr);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
.primary.has-brand.has-groups.has-aside {
|
|
271
|
+
grid-template-areas:
|
|
272
|
+
"brand"
|
|
273
|
+
"groups"
|
|
274
|
+
"aside";
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.primary.has-brand.has-groups:not(.has-aside) {
|
|
278
|
+
grid-template-areas:
|
|
279
|
+
"brand"
|
|
280
|
+
"groups";
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.primary.has-groups.has-aside:not(.has-brand) {
|
|
284
|
+
grid-template-areas:
|
|
285
|
+
"groups"
|
|
286
|
+
"aside";
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.primary.has-brand.has-aside:not(.has-groups) {
|
|
290
|
+
grid-template-areas:
|
|
291
|
+
"brand"
|
|
292
|
+
"aside";
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
.primary.has-brand:not(.has-groups):not(.has-aside) {
|
|
296
|
+
grid-template-areas: "brand";
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
.primary.has-groups:not(.has-brand):not(.has-aside) {
|
|
300
|
+
grid-template-areas: "groups";
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.primary.has-aside:not(.has-brand):not(.has-groups) {
|
|
304
|
+
grid-template-areas: "aside";
|
|
305
|
+
}
|
|
306
|
+
}
|
|
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};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export*from"./esp-footer-link-group.js";export*from"./esp-footer.js";
|