@sankhyatronics/sankhya-cms 0.0.0-stage → 0.1.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/README.md +34 -3
- package/custom-elements.json +4008 -0
- package/dist/bento-grid/index.d.ts +27 -0
- package/dist/bento-grid/index.js +10 -0
- package/dist/bento-grid/index.js.map +1 -0
- package/dist/card/index.d.ts +20 -0
- package/dist/card/index.js +9 -0
- package/dist/card/index.js.map +1 -0
- package/dist/carousel/index.d.ts +44 -0
- package/dist/carousel/index.js +10 -0
- package/dist/carousel/index.js.map +1 -0
- package/dist/chunk-23IHTBAB.js +557 -0
- package/dist/chunk-23IHTBAB.js.map +1 -0
- package/dist/chunk-2VZFHTBC.js +203 -0
- package/dist/chunk-2VZFHTBC.js.map +1 -0
- package/dist/chunk-3ERKQNZT.js +155 -0
- package/dist/chunk-3ERKQNZT.js.map +1 -0
- package/dist/chunk-3JU3R22O.js +193 -0
- package/dist/chunk-3JU3R22O.js.map +1 -0
- package/dist/chunk-3TCP25JG.js +347 -0
- package/dist/chunk-3TCP25JG.js.map +1 -0
- package/dist/chunk-3VE6VFJ4.js +87 -0
- package/dist/chunk-3VE6VFJ4.js.map +1 -0
- package/dist/chunk-4HKSA5UT.js +312 -0
- package/dist/chunk-4HKSA5UT.js.map +1 -0
- package/dist/chunk-5REZSZCK.js +266 -0
- package/dist/chunk-5REZSZCK.js.map +1 -0
- package/dist/chunk-5UFRGZWG.js +268 -0
- package/dist/chunk-5UFRGZWG.js.map +1 -0
- package/dist/chunk-74MILER4.js +215 -0
- package/dist/chunk-74MILER4.js.map +1 -0
- package/dist/chunk-7PSYCTEN.js +118 -0
- package/dist/chunk-7PSYCTEN.js.map +1 -0
- package/dist/chunk-CDC4P77V.js +299 -0
- package/dist/chunk-CDC4P77V.js.map +1 -0
- package/dist/chunk-E52WO7R7.js +279 -0
- package/dist/chunk-E52WO7R7.js.map +1 -0
- package/dist/chunk-EUXUH3YW.js +15 -0
- package/dist/chunk-EUXUH3YW.js.map +1 -0
- package/dist/chunk-IMACP7HN.js +156 -0
- package/dist/chunk-IMACP7HN.js.map +1 -0
- package/dist/chunk-LHU23TF6.js +273 -0
- package/dist/chunk-LHU23TF6.js.map +1 -0
- package/dist/chunk-OEX5FDMR.js +250 -0
- package/dist/chunk-OEX5FDMR.js.map +1 -0
- package/dist/chunk-RHAOQ6K4.js +138 -0
- package/dist/chunk-RHAOQ6K4.js.map +1 -0
- package/dist/chunk-RMIJVTFS.js +397 -0
- package/dist/chunk-RMIJVTFS.js.map +1 -0
- package/dist/chunk-U7YKCCJG.js +228 -0
- package/dist/chunk-U7YKCCJG.js.map +1 -0
- package/dist/chunk-USNFT4DU.js +125 -0
- package/dist/chunk-USNFT4DU.js.map +1 -0
- package/dist/chunk-VYON56QO.js +90 -0
- package/dist/chunk-VYON56QO.js.map +1 -0
- package/dist/chunk-WCO7JAIK.js +195 -0
- package/dist/chunk-WCO7JAIK.js.map +1 -0
- package/dist/chunk-XHBC23TV.js +254 -0
- package/dist/chunk-XHBC23TV.js.map +1 -0
- package/dist/chunk-XXPBFHWR.js +70 -0
- package/dist/chunk-XXPBFHWR.js.map +1 -0
- package/dist/cms-theme.css +15 -0
- package/dist/content-block/index.d.ts +25 -0
- package/dist/content-block/index.js +11 -0
- package/dist/content-block/index.js.map +1 -0
- package/dist/cookie-consent/index.d.ts +33 -0
- package/dist/cookie-consent/index.js +9 -0
- package/dist/cookie-consent/index.js.map +1 -0
- package/dist/dropdown/index.d.ts +89 -0
- package/dist/dropdown/index.js +9 -0
- package/dist/dropdown/index.js.map +1 -0
- package/dist/feature-split/index.d.ts +38 -0
- package/dist/feature-split/index.js +11 -0
- package/dist/feature-split/index.js.map +1 -0
- package/dist/features-section/index.d.ts +50 -0
- package/dist/features-section/index.js +14 -0
- package/dist/features-section/index.js.map +1 -0
- package/dist/footer/index.d.ts +64 -0
- package/dist/footer/index.js +9 -0
- package/dist/footer/index.js.map +1 -0
- package/dist/header/index.d.ts +112 -0
- package/dist/header/index.js +10 -0
- package/dist/header/index.js.map +1 -0
- package/dist/hero/index.d.ts +32 -0
- package/dist/hero/index.js +10 -0
- package/dist/hero/index.js.map +1 -0
- package/dist/icon-button/index.d.ts +23 -0
- package/dist/icon-button/index.js +9 -0
- package/dist/icon-button/index.js.map +1 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +93 -0
- package/dist/index.js.map +1 -0
- package/dist/items-accordion/index.d.ts +31 -0
- package/dist/items-accordion/index.js +10 -0
- package/dist/items-accordion/index.js.map +1 -0
- package/dist/markdown/index.d.ts +33 -0
- package/dist/markdown/index.js +9 -0
- package/dist/markdown/index.js.map +1 -0
- package/dist/menu-grid/index.d.ts +21 -0
- package/dist/menu-grid/index.js +9 -0
- package/dist/menu-grid/index.js.map +1 -0
- package/dist/menu-grid-item/index.d.ts +53 -0
- package/dist/menu-grid-item/index.js +9 -0
- package/dist/menu-grid-item/index.js.map +1 -0
- package/dist/menu-item/index.d.ts +50 -0
- package/dist/menu-item/index.js +9 -0
- package/dist/menu-item/index.js.map +1 -0
- package/dist/promo-banner/index.d.ts +22 -0
- package/dist/promo-banner/index.js +10 -0
- package/dist/promo-banner/index.js.map +1 -0
- package/dist/schema/index.d.ts +72 -0
- package/dist/schema/index.js +75 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/select/index.d.ts +77 -0
- package/dist/select/index.js +10 -0
- package/dist/select/index.js.map +1 -0
- package/dist/shared/icons.d.ts +77 -0
- package/dist/shared/icons.js +64 -0
- package/dist/shared/icons.js.map +1 -0
- package/dist/shared/styles.d.ts +90 -0
- package/dist/shared/styles.js +48 -0
- package/dist/shared/styles.js.map +1 -0
- package/dist/stats/index.d.ts +17 -0
- package/dist/stats/index.js +9 -0
- package/dist/stats/index.js.map +1 -0
- package/dist/testimonials/index.d.ts +25 -0
- package/dist/testimonials/index.js +10 -0
- package/dist/testimonials/index.js.map +1 -0
- package/dist/theme.css +292 -0
- package/dist/themes.css +65 -0
- package/dist/theming/index.d.ts +28 -0
- package/dist/theming/index.js +53 -0
- package/dist/theming/index.js.map +1 -0
- package/package.json +161 -4
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import {
|
|
2
|
+
controlBaseStyles,
|
|
3
|
+
rootFontFamilyStyles
|
|
4
|
+
} from "./chunk-RHAOQ6K4.js";
|
|
5
|
+
import {
|
|
6
|
+
__decorateClass
|
|
7
|
+
} from "./chunk-EUXUH3YW.js";
|
|
8
|
+
|
|
9
|
+
// src/footer/Footer.ts
|
|
10
|
+
import { LitElement, css, html, nothing } from "lit";
|
|
11
|
+
import { customElement, property } from "lit/decorators.js";
|
|
12
|
+
import "iconify-icon";
|
|
13
|
+
var Footer = class extends LitElement {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
this.inverted = false;
|
|
17
|
+
this.companyName = "";
|
|
18
|
+
this.copyright = "";
|
|
19
|
+
this.poweredBy = "";
|
|
20
|
+
this.poweredByLink = "";
|
|
21
|
+
this.version = "";
|
|
22
|
+
this.imageSrc = "";
|
|
23
|
+
this.description = "";
|
|
24
|
+
this.columns = [];
|
|
25
|
+
this.socialLinks = [];
|
|
26
|
+
}
|
|
27
|
+
get isSite() {
|
|
28
|
+
return !!(this.columns.length || this.socialLinks.length || this.description || this.imageSrc);
|
|
29
|
+
}
|
|
30
|
+
get resolvedCopyright() {
|
|
31
|
+
if (this.copyright) return this.copyright;
|
|
32
|
+
if (this.companyName) return `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${this.companyName}`;
|
|
33
|
+
return `\xA9 ${(/* @__PURE__ */ new Date()).getFullYear()}`;
|
|
34
|
+
}
|
|
35
|
+
willUpdate(changed) {
|
|
36
|
+
if (changed.size) this.toggleAttribute("site", this.isSite);
|
|
37
|
+
}
|
|
38
|
+
onLinkClick(event, href) {
|
|
39
|
+
const select = new CustomEvent("footer-link", {
|
|
40
|
+
detail: { href },
|
|
41
|
+
bubbles: true,
|
|
42
|
+
composed: true,
|
|
43
|
+
cancelable: true
|
|
44
|
+
});
|
|
45
|
+
this.dispatchEvent(select);
|
|
46
|
+
if (select.defaultPrevented) event.preventDefault();
|
|
47
|
+
}
|
|
48
|
+
renderLink(link) {
|
|
49
|
+
return /^https?:/i.test(link.href) ? html`<a part="link" class="link" href=${link.href} target="_blank" rel="noopener noreferrer">${link.label}</a>` : html`<a part="link" class="link" href=${link.href} @click=${(event) => this.onLinkClick(event, link.href)}>${link.label}</a>`;
|
|
50
|
+
}
|
|
51
|
+
renderPoweredBy() {
|
|
52
|
+
return this.poweredBy ? html`
|
|
53
|
+
<a part="powered-by" class="powered-by" href=${this.poweredByLink || "#"} target="_blank" rel="noopener noreferrer">
|
|
54
|
+
${this.poweredBy}
|
|
55
|
+
</a>
|
|
56
|
+
` : nothing;
|
|
57
|
+
}
|
|
58
|
+
renderSite() {
|
|
59
|
+
return html`
|
|
60
|
+
<div class="site" part="site">
|
|
61
|
+
<div class="grid">
|
|
62
|
+
<div class="brand" part="brand">
|
|
63
|
+
${this.imageSrc || this.companyName ? html`<div class="logo">
|
|
64
|
+
${this.imageSrc ? html`<img class="logo-img" src=${this.imageSrc} alt=${this.companyName || "Logo"} />` : nothing}
|
|
65
|
+
${this.companyName ? html`<span>${this.companyName}</span>` : nothing}
|
|
66
|
+
</div>` : nothing}
|
|
67
|
+
${this.description ? html`<p class="description">${this.description}</p>` : nothing}
|
|
68
|
+
${this.socialLinks.length ? html`<div class="social">
|
|
69
|
+
${this.socialLinks.map(
|
|
70
|
+
(social) => html`<a part="social" class="social-link" href=${social.href} target="_blank" rel="noopener noreferrer" aria-label=${social.icon}>
|
|
71
|
+
<iconify-icon icon=${social.icon} width="24" height="24"></iconify-icon>
|
|
72
|
+
</a>`
|
|
73
|
+
)}
|
|
74
|
+
</div>` : nothing}
|
|
75
|
+
</div>
|
|
76
|
+
${this.columns.map(
|
|
77
|
+
(column) => html`<div class="column" part="column">
|
|
78
|
+
<h4 class="column-title">${column.title}</h4>
|
|
79
|
+
<div class="links">${column.links.map((link) => this.renderLink(link))}</div>
|
|
80
|
+
</div>`
|
|
81
|
+
)}
|
|
82
|
+
</div>
|
|
83
|
+
<div class="bottom" part="bottom">
|
|
84
|
+
<div class="bottom-text">
|
|
85
|
+
<span part="copyright">${this.resolvedCopyright}</span>
|
|
86
|
+
${this.version ? html`<span part="version">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
</div>
|
|
90
|
+
`;
|
|
91
|
+
}
|
|
92
|
+
render() {
|
|
93
|
+
if (this.isSite) return this.renderSite();
|
|
94
|
+
return html`
|
|
95
|
+
<span part="copyright">${this.resolvedCopyright}</span>
|
|
96
|
+
${this.version ? html`<span part="version">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}
|
|
97
|
+
`;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
Footer.styles = css`
|
|
101
|
+
${controlBaseStyles}
|
|
102
|
+
|
|
103
|
+
:host {
|
|
104
|
+
display: flex;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: space-between;
|
|
107
|
+
gap: var(--st-space-16);
|
|
108
|
+
flex-wrap: wrap;
|
|
109
|
+
/* !important on padding/border-top only: a shadow host's own :host rule always loses to ANY
|
|
110
|
+
* rule the consuming page has for the same property on that element, regardless of
|
|
111
|
+
* specificity — so a page that resets margin/padding/border on every element (e.g. Tailwind
|
|
112
|
+
* Preflight, which every app but Template Hub loads) silently zeroes this footer's padding
|
|
113
|
+
* and top border unless these two win the conflict outright via !important. */
|
|
114
|
+
padding: var(--st-space-16) var(--st-space-28) !important;
|
|
115
|
+
border-top: 1px solid var(--st-color-border) !important;
|
|
116
|
+
color: var(--st-color-text-muted);
|
|
117
|
+
font-size: var(--st-text-xs);
|
|
118
|
+
${rootFontFamilyStyles}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.powered-by {
|
|
122
|
+
color: inherit;
|
|
123
|
+
text-decoration: none;
|
|
124
|
+
font-weight: var(--st-font-weight-semibold);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.powered-by:hover {
|
|
128
|
+
color: var(--st-color-text-strong);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
:host([inverted]) {
|
|
132
|
+
background: var(--st-color-text-strong);
|
|
133
|
+
color: var(--st-color-on-solid);
|
|
134
|
+
border-top-color: transparent !important;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Site layout */
|
|
138
|
+
:host([site]) {
|
|
139
|
+
display: block;
|
|
140
|
+
padding: 64px var(--st-space-28) 32px !important;
|
|
141
|
+
font-size: var(--st-text-sm);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
.site {
|
|
145
|
+
max-width: 1200px;
|
|
146
|
+
margin: 0 auto;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.grid {
|
|
150
|
+
display: grid;
|
|
151
|
+
grid-template-columns: 2fr repeat(3, 1fr);
|
|
152
|
+
gap: 64px;
|
|
153
|
+
margin-bottom: 64px;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
.brand {
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
gap: 16px;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
.logo {
|
|
163
|
+
display: flex;
|
|
164
|
+
align-items: center;
|
|
165
|
+
gap: 8px;
|
|
166
|
+
font-size: 1.25rem;
|
|
167
|
+
font-weight: 700;
|
|
168
|
+
color: var(--st-color-text-strong);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.logo-img {
|
|
172
|
+
height: 32px;
|
|
173
|
+
width: auto;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.description {
|
|
177
|
+
margin: 0;
|
|
178
|
+
max-width: 300px;
|
|
179
|
+
line-height: 1.6;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.social {
|
|
183
|
+
display: flex;
|
|
184
|
+
gap: 16px;
|
|
185
|
+
margin-top: 16px;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.social-link,
|
|
189
|
+
.link {
|
|
190
|
+
color: inherit;
|
|
191
|
+
text-decoration: none;
|
|
192
|
+
transition: color 0.2s ease;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.social-link:hover,
|
|
196
|
+
.link:hover {
|
|
197
|
+
color: var(--st-color-text-strong);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
.column-title {
|
|
201
|
+
margin: 0 0 24px;
|
|
202
|
+
font-size: var(--st-text-xs);
|
|
203
|
+
font-weight: var(--st-font-weight-semibold);
|
|
204
|
+
color: var(--st-color-text-strong);
|
|
205
|
+
text-transform: uppercase;
|
|
206
|
+
letter-spacing: 0.05em;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
.links {
|
|
210
|
+
display: flex;
|
|
211
|
+
flex-direction: column;
|
|
212
|
+
gap: 16px;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.bottom {
|
|
216
|
+
padding-top: 32px;
|
|
217
|
+
border-top: 1px solid var(--st-color-border);
|
|
218
|
+
font-size: var(--st-text-xs);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.bottom-text {
|
|
222
|
+
display: flex;
|
|
223
|
+
flex-direction: column;
|
|
224
|
+
gap: 4px;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.bottom-text .powered-by {
|
|
228
|
+
font-size: 0.85em;
|
|
229
|
+
font-weight: inherit;
|
|
230
|
+
opacity: 0.8;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
@media (max-width: 1024px) {
|
|
234
|
+
.grid {
|
|
235
|
+
grid-template-columns: repeat(3, 1fr);
|
|
236
|
+
gap: 48px;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
@media (max-width: 768px) {
|
|
241
|
+
.grid {
|
|
242
|
+
grid-template-columns: 1fr;
|
|
243
|
+
gap: 40px;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
.bottom {
|
|
247
|
+
text-align: center;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
:host([site][inverted]) .logo,
|
|
252
|
+
:host([site][inverted]) .column-title,
|
|
253
|
+
:host([site][inverted]) .social-link:hover,
|
|
254
|
+
:host([site][inverted]) .link:hover {
|
|
255
|
+
color: var(--st-color-on-solid);
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
:host([site][inverted]) .bottom {
|
|
259
|
+
border-top-color: color-mix(in oklch, var(--st-color-on-solid) 20%, var(--st-color-text-strong));
|
|
260
|
+
}
|
|
261
|
+
`;
|
|
262
|
+
__decorateClass([
|
|
263
|
+
property({ type: Boolean, reflect: true })
|
|
264
|
+
], Footer.prototype, "inverted", 2);
|
|
265
|
+
__decorateClass([
|
|
266
|
+
property({ type: String, attribute: "company-name" })
|
|
267
|
+
], Footer.prototype, "companyName", 2);
|
|
268
|
+
__decorateClass([
|
|
269
|
+
property({ type: String })
|
|
270
|
+
], Footer.prototype, "copyright", 2);
|
|
271
|
+
__decorateClass([
|
|
272
|
+
property({ type: String, attribute: "powered-by" })
|
|
273
|
+
], Footer.prototype, "poweredBy", 2);
|
|
274
|
+
__decorateClass([
|
|
275
|
+
property({ type: String, attribute: "powered-by-link" })
|
|
276
|
+
], Footer.prototype, "poweredByLink", 2);
|
|
277
|
+
__decorateClass([
|
|
278
|
+
property({ type: String })
|
|
279
|
+
], Footer.prototype, "version", 2);
|
|
280
|
+
__decorateClass([
|
|
281
|
+
property({ type: String, attribute: "image-src" })
|
|
282
|
+
], Footer.prototype, "imageSrc", 2);
|
|
283
|
+
__decorateClass([
|
|
284
|
+
property({ type: String })
|
|
285
|
+
], Footer.prototype, "description", 2);
|
|
286
|
+
__decorateClass([
|
|
287
|
+
property({ attribute: false })
|
|
288
|
+
], Footer.prototype, "columns", 2);
|
|
289
|
+
__decorateClass([
|
|
290
|
+
property({ attribute: false })
|
|
291
|
+
], Footer.prototype, "socialLinks", 2);
|
|
292
|
+
Footer = __decorateClass([
|
|
293
|
+
customElement("st-footer")
|
|
294
|
+
], Footer);
|
|
295
|
+
|
|
296
|
+
export {
|
|
297
|
+
Footer
|
|
298
|
+
};
|
|
299
|
+
//# sourceMappingURL=chunk-CDC4P77V.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/footer/Footer.ts"],"sourcesContent":["import { LitElement, PropertyValues, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, rootFontFamilyStyles } from '../shared/styles';\r\n\r\nexport interface FooterLink {\r\n label: string;\r\n href: string;\r\n}\r\n\r\nexport interface FooterColumn {\r\n title: string;\r\n links: FooterLink[];\r\n}\r\n\r\nexport interface FooterSocialLink {\r\n /** Iconify icon name, e.g. `mdi:github`. */\r\n icon: string;\r\n href: string;\r\n}\r\n\r\n/** Fired when an internal footer link is activated — cancelable, so an SPA can `preventDefault()` and route instead. */\r\nexport interface FooterLinkEventDetail {\r\n href: string;\r\n}\r\n\r\n/**\r\n * The footer, in two layouts:\r\n *\r\n * - **Bar** (default): a copyright line plus an optional \"powered by\" link — what the suite's\r\n * authenticated apps use.\r\n * - **Site**: when `columns`, `socialLinks`, `description` or `imageSrc` is set, the footer becomes a\r\n * marketing-site footer — brand (logo/company name, description, social icons), link columns and a\r\n * bottom bar with the copyright and \"powered by\".\r\n *\r\n * Fires a cancelable `footer-link` event (detail `{ href }`) when an internal link is clicked.\r\n */\r\n@customElement('st-footer')\r\nexport class Footer extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: var(--st-space-16);\r\n flex-wrap: wrap;\r\n /* !important on padding/border-top only: a shadow host's own :host rule always loses to ANY\r\n * rule the consuming page has for the same property on that element, regardless of\r\n * specificity — so a page that resets margin/padding/border on every element (e.g. Tailwind\r\n * Preflight, which every app but Template Hub loads) silently zeroes this footer's padding\r\n * and top border unless these two win the conflict outright via !important. */\r\n padding: var(--st-space-16) var(--st-space-28) !important;\r\n border-top: 1px solid var(--st-color-border) !important;\r\n color: var(--st-color-text-muted);\r\n font-size: var(--st-text-xs);\r\n ${rootFontFamilyStyles}\r\n }\r\n\r\n .powered-by {\r\n color: inherit;\r\n text-decoration: none;\r\n font-weight: var(--st-font-weight-semibold);\r\n }\r\n\r\n .powered-by:hover {\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n color: var(--st-color-on-solid);\r\n border-top-color: transparent !important;\r\n }\r\n\r\n /* Site layout */\r\n :host([site]) {\r\n display: block;\r\n padding: 64px var(--st-space-28) 32px !important;\r\n font-size: var(--st-text-sm);\r\n }\r\n\r\n .site {\r\n max-width: 1200px;\r\n margin: 0 auto;\r\n }\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: 2fr repeat(3, 1fr);\r\n gap: 64px;\r\n margin-bottom: 64px;\r\n }\r\n\r\n .brand {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n\r\n .logo {\r\n display: flex;\r\n align-items: center;\r\n gap: 8px;\r\n font-size: 1.25rem;\r\n font-weight: 700;\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .logo-img {\r\n height: 32px;\r\n width: auto;\r\n }\r\n\r\n .description {\r\n margin: 0;\r\n max-width: 300px;\r\n line-height: 1.6;\r\n }\r\n\r\n .social {\r\n display: flex;\r\n gap: 16px;\r\n margin-top: 16px;\r\n }\r\n\r\n .social-link,\r\n .link {\r\n color: inherit;\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .social-link:hover,\r\n .link:hover {\r\n color: var(--st-color-text-strong);\r\n }\r\n\r\n .column-title {\r\n margin: 0 0 24px;\r\n font-size: var(--st-text-xs);\r\n font-weight: var(--st-font-weight-semibold);\r\n color: var(--st-color-text-strong);\r\n text-transform: uppercase;\r\n letter-spacing: 0.05em;\r\n }\r\n\r\n .links {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 16px;\r\n }\r\n\r\n .bottom {\r\n padding-top: 32px;\r\n border-top: 1px solid var(--st-color-border);\r\n font-size: var(--st-text-xs);\r\n }\r\n\r\n .bottom-text {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 4px;\r\n }\r\n\r\n .bottom-text .powered-by {\r\n font-size: 0.85em;\r\n font-weight: inherit;\r\n opacity: 0.8;\r\n }\r\n\r\n @media (max-width: 1024px) {\r\n .grid {\r\n grid-template-columns: repeat(3, 1fr);\r\n gap: 48px;\r\n }\r\n }\r\n\r\n @media (max-width: 768px) {\r\n .grid {\r\n grid-template-columns: 1fr;\r\n gap: 40px;\r\n }\r\n\r\n .bottom {\r\n text-align: center;\r\n }\r\n }\r\n\r\n :host([site][inverted]) .logo,\r\n :host([site][inverted]) .column-title,\r\n :host([site][inverted]) .social-link:hover,\r\n :host([site][inverted]) .link:hover {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n :host([site][inverted]) .bottom {\r\n border-top-color: color-mix(in oklch, var(--st-color-on-solid) 20%, var(--st-color-text-strong));\r\n }\r\n `;\r\n\r\n /** Inverts the footer's color roles (light-on-dark instead of dark-on-light) — matches the\r\n * source component's `inverted` (from its shared `BaseProps`), same as `st-header`'s. */\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n /** Used to build the default `copyright` line (`© {year} {companyName}`) when `copyright` isn't set explicitly. */\r\n @property({ type: String, attribute: 'company-name' })\r\n companyName = '';\r\n\r\n /** Overrides the default computed copyright line entirely. */\r\n @property({ type: String })\r\n copyright = '';\r\n\r\n @property({ type: String, attribute: 'powered-by' })\r\n poweredBy = '';\r\n\r\n @property({ type: String, attribute: 'powered-by-link' })\r\n poweredByLink = '';\r\n\r\n /** App version, rendered as `v{version}` after the copyright line — for apps that show their own\r\n * version in the footer rather than the header title. */\r\n @property({ type: String })\r\n version = '';\r\n\r\n /** Logo shown in the brand block (site layout). */\r\n @property({ type: String, attribute: 'image-src' })\r\n imageSrc = '';\r\n\r\n /** Short blurb under the logo (site layout). */\r\n @property({ type: String })\r\n description = '';\r\n\r\n /** Link columns (site layout). */\r\n @property({ attribute: false })\r\n columns: FooterColumn[] = [];\r\n\r\n /** Social icon links under the description (site layout). */\r\n @property({ attribute: false })\r\n socialLinks: FooterSocialLink[] = [];\r\n\r\n private get isSite(): boolean {\r\n return !!(this.columns.length || this.socialLinks.length || this.description || this.imageSrc);\r\n }\r\n\r\n private get resolvedCopyright(): string {\r\n if (this.copyright) return this.copyright;\r\n if (this.companyName) return `© ${new Date().getFullYear()} ${this.companyName}`;\r\n return `© ${new Date().getFullYear()}`;\r\n }\r\n\r\n protected willUpdate(changed: PropertyValues): void {\r\n if (changed.size) this.toggleAttribute('site', this.isSite);\r\n }\r\n\r\n private onLinkClick(event: MouseEvent, href: string): void {\r\n const select = new CustomEvent<FooterLinkEventDetail>('footer-link', {\r\n detail: { href },\r\n bubbles: true,\r\n composed: true,\r\n cancelable: true\r\n });\r\n this.dispatchEvent(select);\r\n if (select.defaultPrevented) event.preventDefault();\r\n }\r\n\r\n private renderLink(link: FooterLink) {\r\n return /^https?:/i.test(link.href)\r\n ? html`<a part=\"link\" class=\"link\" href=${link.href} target=\"_blank\" rel=\"noopener noreferrer\">${link.label}</a>`\r\n : html`<a part=\"link\" class=\"link\" href=${link.href} @click=${(event: MouseEvent) => this.onLinkClick(event, link.href)}>${link.label}</a>`;\r\n }\r\n\r\n private renderPoweredBy() {\r\n return this.poweredBy\r\n ? html`\r\n <a part=\"powered-by\" class=\"powered-by\" href=${this.poweredByLink || '#'} target=\"_blank\" rel=\"noopener noreferrer\">\r\n ${this.poweredBy}\r\n </a>\r\n `\r\n : nothing;\r\n }\r\n\r\n private renderSite() {\r\n return html`\r\n <div class=\"site\" part=\"site\">\r\n <div class=\"grid\">\r\n <div class=\"brand\" part=\"brand\">\r\n ${this.imageSrc || this.companyName\r\n ? html`<div class=\"logo\">\r\n ${this.imageSrc ? html`<img class=\"logo-img\" src=${this.imageSrc} alt=${this.companyName || 'Logo'} />` : nothing}\r\n ${this.companyName ? html`<span>${this.companyName}</span>` : nothing}\r\n </div>`\r\n : nothing}\r\n ${this.description ? html`<p class=\"description\">${this.description}</p>` : nothing}\r\n ${this.socialLinks.length\r\n ? html`<div class=\"social\">\r\n ${this.socialLinks.map(\r\n social => html`<a part=\"social\" class=\"social-link\" href=${social.href} target=\"_blank\" rel=\"noopener noreferrer\" aria-label=${social.icon}>\r\n <iconify-icon icon=${social.icon} width=\"24\" height=\"24\"></iconify-icon>\r\n </a>`\r\n )}\r\n </div>`\r\n : nothing}\r\n </div>\r\n ${this.columns.map(\r\n column => html`<div class=\"column\" part=\"column\">\r\n <h4 class=\"column-title\">${column.title}</h4>\r\n <div class=\"links\">${column.links.map(link => this.renderLink(link))}</div>\r\n </div>`\r\n )}\r\n </div>\r\n <div class=\"bottom\" part=\"bottom\">\r\n <div class=\"bottom-text\">\r\n <span part=\"copyright\">${this.resolvedCopyright}</span>\r\n ${this.version ? html`<span part=\"version\">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}\r\n </div>\r\n </div>\r\n </div>\r\n `;\r\n }\r\n\r\n render() {\r\n if (this.isSite) return this.renderSite();\r\n return html`\r\n <span part=\"copyright\">${this.resolvedCopyright}</span>\r\n ${this.version ? html`<span part=\"version\">v${this.version}</span>` : nothing} ${this.renderPoweredBy()}\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cardDescriptionStyles,
|
|
3
|
+
cardTitleStyles,
|
|
4
|
+
sectionHeaderStyles,
|
|
5
|
+
sectionSubtitleStyles,
|
|
6
|
+
sectionTitleStyles
|
|
7
|
+
} from "./chunk-3VE6VFJ4.js";
|
|
8
|
+
import {
|
|
9
|
+
controlBaseStyles,
|
|
10
|
+
fontFamilyStyles
|
|
11
|
+
} from "./chunk-RHAOQ6K4.js";
|
|
12
|
+
import {
|
|
13
|
+
__decorateClass
|
|
14
|
+
} from "./chunk-EUXUH3YW.js";
|
|
15
|
+
|
|
16
|
+
// src/features-section/FeaturesSection.ts
|
|
17
|
+
import { LitElement as LitElement2, css as css2, html as html2, nothing as nothing2 } from "lit";
|
|
18
|
+
import { customElement as customElement2, property as property2 } from "lit/decorators.js";
|
|
19
|
+
|
|
20
|
+
// src/features-section/FeatureItem.ts
|
|
21
|
+
import { LitElement, css, html, nothing } from "lit";
|
|
22
|
+
import { customElement, property } from "lit/decorators.js";
|
|
23
|
+
import "iconify-icon";
|
|
24
|
+
var FeatureItem = class extends LitElement {
|
|
25
|
+
constructor() {
|
|
26
|
+
super(...arguments);
|
|
27
|
+
this.icon = "";
|
|
28
|
+
this.title = "";
|
|
29
|
+
this.description = "";
|
|
30
|
+
this.href = "";
|
|
31
|
+
this.actionLabel = "Learn more";
|
|
32
|
+
this.inverted = false;
|
|
33
|
+
}
|
|
34
|
+
render() {
|
|
35
|
+
const external = this.href.startsWith("http");
|
|
36
|
+
return html`
|
|
37
|
+
<st-card hoverable elevation="sm" ?inverted=${this.inverted} part="card">
|
|
38
|
+
<div class="content" part="content">
|
|
39
|
+
${this.icon ? html`<div class="icon" part="icon"><iconify-icon icon=${this.icon}></iconify-icon></div>` : nothing}
|
|
40
|
+
<h3 class="title" part="title">${this.title}</h3>
|
|
41
|
+
<st-markdown class="description" part="description" .content=${this.description}></st-markdown>
|
|
42
|
+
${this.href ? html`
|
|
43
|
+
<a
|
|
44
|
+
class="link"
|
|
45
|
+
part="link"
|
|
46
|
+
href=${this.href}
|
|
47
|
+
target=${external ? "_blank" : "_self"}
|
|
48
|
+
rel=${external ? "noopener noreferrer" : nothing}
|
|
49
|
+
>
|
|
50
|
+
${this.actionLabel} <span>→</span>
|
|
51
|
+
</a>
|
|
52
|
+
` : nothing}
|
|
53
|
+
</div>
|
|
54
|
+
</st-card>
|
|
55
|
+
`;
|
|
56
|
+
}
|
|
57
|
+
};
|
|
58
|
+
FeatureItem.styles = css`
|
|
59
|
+
${controlBaseStyles}
|
|
60
|
+
|
|
61
|
+
:host {
|
|
62
|
+
display: block;
|
|
63
|
+
${fontFamilyStyles}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
st-card {
|
|
67
|
+
height: 100%;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.content {
|
|
71
|
+
display: flex;
|
|
72
|
+
flex-direction: column;
|
|
73
|
+
align-items: flex-start;
|
|
74
|
+
gap: var(--st-space-16);
|
|
75
|
+
height: 100%;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.icon {
|
|
79
|
+
display: flex;
|
|
80
|
+
align-items: center;
|
|
81
|
+
justify-content: center;
|
|
82
|
+
width: 48px;
|
|
83
|
+
height: 48px;
|
|
84
|
+
border-radius: var(--st-radius-lg);
|
|
85
|
+
background: var(--st-color-subtle);
|
|
86
|
+
color: var(--st-color-text-strong);
|
|
87
|
+
margin-bottom: var(--st-space-8);
|
|
88
|
+
font-size: 24px;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
:host([inverted]) .icon {
|
|
92
|
+
background: var(--st-color-text-muted);
|
|
93
|
+
color: var(--st-color-on-solid);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.title {
|
|
97
|
+
${cardTitleStyles}
|
|
98
|
+
margin: 0;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.description {
|
|
102
|
+
${cardDescriptionStyles}
|
|
103
|
+
margin: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
:host([inverted]) .title,
|
|
107
|
+
:host([inverted]) .description {
|
|
108
|
+
color: inherit;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.link {
|
|
112
|
+
display: flex;
|
|
113
|
+
align-items: center;
|
|
114
|
+
gap: var(--st-space-4);
|
|
115
|
+
margin-top: auto;
|
|
116
|
+
color: var(--st-color-text-muted);
|
|
117
|
+
font-weight: var(--st-font-weight-medium);
|
|
118
|
+
font-size: var(--st-text-md);
|
|
119
|
+
text-decoration: none;
|
|
120
|
+
transition: color 0.2s ease;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.link:hover {
|
|
124
|
+
color: var(--st-color-text-strong);
|
|
125
|
+
text-decoration: underline;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
:host([inverted]) .link,
|
|
129
|
+
:host([inverted]) .link:hover {
|
|
130
|
+
color: inherit;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
@media (prefers-reduced-motion: reduce) {
|
|
134
|
+
.link {
|
|
135
|
+
transition: none;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
`;
|
|
139
|
+
__decorateClass([
|
|
140
|
+
property({ type: String })
|
|
141
|
+
], FeatureItem.prototype, "icon", 2);
|
|
142
|
+
__decorateClass([
|
|
143
|
+
property({ type: String })
|
|
144
|
+
], FeatureItem.prototype, "title", 2);
|
|
145
|
+
__decorateClass([
|
|
146
|
+
property({ type: String })
|
|
147
|
+
], FeatureItem.prototype, "description", 2);
|
|
148
|
+
__decorateClass([
|
|
149
|
+
property({ type: String })
|
|
150
|
+
], FeatureItem.prototype, "href", 2);
|
|
151
|
+
__decorateClass([
|
|
152
|
+
property({ type: String, attribute: "action-label" })
|
|
153
|
+
], FeatureItem.prototype, "actionLabel", 2);
|
|
154
|
+
__decorateClass([
|
|
155
|
+
property({ type: Boolean, reflect: true })
|
|
156
|
+
], FeatureItem.prototype, "inverted", 2);
|
|
157
|
+
FeatureItem = __decorateClass([
|
|
158
|
+
customElement("st-feature-item")
|
|
159
|
+
], FeatureItem);
|
|
160
|
+
|
|
161
|
+
// src/features-section/FeaturesSection.ts
|
|
162
|
+
var FeaturesSection = class extends LitElement2 {
|
|
163
|
+
constructor() {
|
|
164
|
+
super(...arguments);
|
|
165
|
+
this.title = "";
|
|
166
|
+
this.subtitle = "";
|
|
167
|
+
this.actionLabel = "Learn more";
|
|
168
|
+
this.columns = 0;
|
|
169
|
+
this.inverted = false;
|
|
170
|
+
this.items = [];
|
|
171
|
+
}
|
|
172
|
+
render() {
|
|
173
|
+
const gridStyle = this.columns ? `--features-columns: ${this.columns}` : nothing2;
|
|
174
|
+
return html2`
|
|
175
|
+
<section class="container" part="container">
|
|
176
|
+
<div class="header" part="header">
|
|
177
|
+
<div class="title" part="title">${this.title}</div>
|
|
178
|
+
${this.subtitle ? html2`<div class="subtitle" part="subtitle">${this.subtitle}</div>` : nothing2}
|
|
179
|
+
</div>
|
|
180
|
+
<div class="grid" part="grid" style=${gridStyle}>
|
|
181
|
+
<slot></slot>
|
|
182
|
+
${this.items.map(
|
|
183
|
+
(item) => html2`
|
|
184
|
+
<st-feature-item
|
|
185
|
+
.icon=${item.icon ?? ""}
|
|
186
|
+
.title=${item.title}
|
|
187
|
+
.description=${item.description}
|
|
188
|
+
.href=${item.href ?? ""}
|
|
189
|
+
.actionLabel=${this.actionLabel}
|
|
190
|
+
?inverted=${this.inverted}
|
|
191
|
+
></st-feature-item>
|
|
192
|
+
`
|
|
193
|
+
)}
|
|
194
|
+
</div>
|
|
195
|
+
</section>
|
|
196
|
+
`;
|
|
197
|
+
}
|
|
198
|
+
};
|
|
199
|
+
FeaturesSection.styles = css2`
|
|
200
|
+
${controlBaseStyles}
|
|
201
|
+
|
|
202
|
+
:host {
|
|
203
|
+
display: block;
|
|
204
|
+
${fontFamilyStyles}
|
|
205
|
+
padding: var(--st-cms-section-padding) var(--st-space-24);
|
|
206
|
+
background: var(--st-color-surface);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
:host([inverted]) {
|
|
210
|
+
background: var(--st-color-text-strong);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
.container {
|
|
214
|
+
max-width: var(--st-cms-container-max);
|
|
215
|
+
margin: 0 auto;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
.header {
|
|
219
|
+
${sectionHeaderStyles}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
.title {
|
|
223
|
+
${sectionTitleStyles}
|
|
224
|
+
margin: 0;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
.subtitle {
|
|
228
|
+
${sectionSubtitleStyles}
|
|
229
|
+
margin: 0 auto;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
:host([inverted]) .title,
|
|
233
|
+
:host([inverted]) .subtitle {
|
|
234
|
+
color: var(--st-color-on-solid);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
.grid {
|
|
238
|
+
display: grid;
|
|
239
|
+
grid-template-columns: repeat(var(--features-columns, 2), 1fr);
|
|
240
|
+
gap: var(--st-space-32);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
@media (max-width: 768px) {
|
|
244
|
+
:host {
|
|
245
|
+
padding: var(--st-space-48) var(--st-space-16);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.grid {
|
|
249
|
+
grid-template-columns: 1fr;
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
`;
|
|
253
|
+
__decorateClass([
|
|
254
|
+
property2({ type: String })
|
|
255
|
+
], FeaturesSection.prototype, "title", 2);
|
|
256
|
+
__decorateClass([
|
|
257
|
+
property2({ type: String })
|
|
258
|
+
], FeaturesSection.prototype, "subtitle", 2);
|
|
259
|
+
__decorateClass([
|
|
260
|
+
property2({ type: String, attribute: "action-label" })
|
|
261
|
+
], FeaturesSection.prototype, "actionLabel", 2);
|
|
262
|
+
__decorateClass([
|
|
263
|
+
property2({ type: Number })
|
|
264
|
+
], FeaturesSection.prototype, "columns", 2);
|
|
265
|
+
__decorateClass([
|
|
266
|
+
property2({ type: Boolean, reflect: true })
|
|
267
|
+
], FeaturesSection.prototype, "inverted", 2);
|
|
268
|
+
__decorateClass([
|
|
269
|
+
property2({ attribute: false })
|
|
270
|
+
], FeaturesSection.prototype, "items", 2);
|
|
271
|
+
FeaturesSection = __decorateClass([
|
|
272
|
+
customElement2("st-features-section")
|
|
273
|
+
], FeaturesSection);
|
|
274
|
+
|
|
275
|
+
export {
|
|
276
|
+
FeatureItem,
|
|
277
|
+
FeaturesSection
|
|
278
|
+
};
|
|
279
|
+
//# sourceMappingURL=chunk-E52WO7R7.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/features-section/FeaturesSection.ts","../src/features-section/FeatureItem.ts"],"sourcesContent":["import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { sectionSubtitleStyles, sectionTitleStyles, sectionHeaderStyles } from '../shared/section-styles';\r\nimport './FeatureItem';\r\n\r\n/** Data for one tile when using the `items` property (mirrors `st-feature-item`'s properties). */\r\nexport interface FeatureItemData {\r\n icon?: string;\r\n title: string;\r\n description: string;\r\n href?: string;\r\n}\r\n\r\n/**\r\n * A titled grid of feature tiles. Ports `SankhyaUI`'s React `FeaturesSection`: tiles come from the\r\n * `items` property, from slotted `st-feature-item` elements (the source's `children`), or both\r\n * (slotted first). `columns` sets the grid width (default 2; one column below 768px). `inverted`\r\n * is passed on to the `items` tiles; slotted tiles need their own `inverted` attribute.\r\n */\r\n@customElement('st-features-section')\r\nexport class FeaturesSection extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n padding: var(--st-cms-section-padding) var(--st-space-24);\r\n background: var(--st-color-surface);\r\n }\r\n\r\n :host([inverted]) {\r\n background: var(--st-color-text-strong);\r\n }\r\n\r\n .container {\r\n max-width: var(--st-cms-container-max);\r\n margin: 0 auto;\r\n }\r\n\r\n .header {\r\n ${sectionHeaderStyles}\r\n }\r\n\r\n .title {\r\n ${sectionTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .subtitle {\r\n ${sectionSubtitleStyles}\r\n margin: 0 auto;\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .subtitle {\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .grid {\r\n display: grid;\r\n grid-template-columns: repeat(var(--features-columns, 2), 1fr);\r\n gap: var(--st-space-32);\r\n }\r\n\r\n @media (max-width: 768px) {\r\n :host {\r\n padding: var(--st-space-48) var(--st-space-16);\r\n }\r\n\r\n .grid {\r\n grid-template-columns: 1fr;\r\n }\r\n }\r\n `;\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n @property({ type: String })\r\n subtitle = '';\r\n\r\n /** Applied to every tile built from `items`. */\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = 'Learn more';\r\n\r\n @property({ type: Number })\r\n columns = 0;\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n /** Tiles to render (property only). */\r\n @property({ attribute: false })\r\n items: FeatureItemData[] = [];\r\n\r\n render() {\r\n const gridStyle = this.columns ? `--features-columns: ${this.columns}` : nothing;\r\n return html`\r\n <section class=\"container\" part=\"container\">\r\n <div class=\"header\" part=\"header\">\r\n <div class=\"title\" part=\"title\">${this.title}</div>\r\n ${this.subtitle ? html`<div class=\"subtitle\" part=\"subtitle\">${this.subtitle}</div>` : nothing}\r\n </div>\r\n <div class=\"grid\" part=\"grid\" style=${gridStyle}>\r\n <slot></slot>\r\n ${this.items.map(\r\n (item) => html`\r\n <st-feature-item\r\n .icon=${item.icon ?? ''}\r\n .title=${item.title}\r\n .description=${item.description}\r\n .href=${item.href ?? ''}\r\n .actionLabel=${this.actionLabel}\r\n ?inverted=${this.inverted}\r\n ></st-feature-item>\r\n `\r\n )}\r\n </div>\r\n </section>\r\n `;\r\n }\r\n}\r\n","import { LitElement, css, html, nothing } from 'lit';\r\nimport { customElement, property } from 'lit/decorators.js';\r\nimport 'iconify-icon';\r\n\r\nimport { controlBaseStyles, fontFamilyStyles } from '../shared/styles';\r\nimport { cardDescriptionStyles, cardTitleStyles } from '../shared/section-styles';\r\nimport '../card';\r\nimport '../markdown';\r\n\r\n/**\r\n * One feature tile for `st-features-section`: optional icon, title, Markdown description and an\r\n * optional \"Learn more\" link, rendered on an `st-card`. `icon` is an Iconify name (e.g.\r\n * `mdi:rocket`). The link is a plain `<a>` (the source used react-router's `Link` for non-http\r\n * hrefs; there is no Lit equivalent). The click is composed, so an SPA router can intercept it\r\n * (e.g. via `event.composedPath()`) and navigate client-side; `http(s)` links open in a new tab.\r\n */\r\n@customElement('st-feature-item')\r\nexport class FeatureItem extends LitElement {\r\n static styles = css`\r\n ${controlBaseStyles}\r\n\r\n :host {\r\n display: block;\r\n ${fontFamilyStyles}\r\n }\r\n\r\n st-card {\r\n height: 100%;\r\n }\r\n\r\n .content {\r\n display: flex;\r\n flex-direction: column;\r\n align-items: flex-start;\r\n gap: var(--st-space-16);\r\n height: 100%;\r\n }\r\n\r\n .icon {\r\n display: flex;\r\n align-items: center;\r\n justify-content: center;\r\n width: 48px;\r\n height: 48px;\r\n border-radius: var(--st-radius-lg);\r\n background: var(--st-color-subtle);\r\n color: var(--st-color-text-strong);\r\n margin-bottom: var(--st-space-8);\r\n font-size: 24px;\r\n }\r\n\r\n :host([inverted]) .icon {\r\n background: var(--st-color-text-muted);\r\n color: var(--st-color-on-solid);\r\n }\r\n\r\n .title {\r\n ${cardTitleStyles}\r\n margin: 0;\r\n }\r\n\r\n .description {\r\n ${cardDescriptionStyles}\r\n margin: 0;\r\n }\r\n\r\n :host([inverted]) .title,\r\n :host([inverted]) .description {\r\n color: inherit;\r\n }\r\n\r\n .link {\r\n display: flex;\r\n align-items: center;\r\n gap: var(--st-space-4);\r\n margin-top: auto;\r\n color: var(--st-color-text-muted);\r\n font-weight: var(--st-font-weight-medium);\r\n font-size: var(--st-text-md);\r\n text-decoration: none;\r\n transition: color 0.2s ease;\r\n }\r\n\r\n .link:hover {\r\n color: var(--st-color-text-strong);\r\n text-decoration: underline;\r\n }\r\n\r\n :host([inverted]) .link,\r\n :host([inverted]) .link:hover {\r\n color: inherit;\r\n }\r\n\r\n @media (prefers-reduced-motion: reduce) {\r\n .link {\r\n transition: none;\r\n }\r\n }\r\n `;\r\n\r\n /** Iconify icon name, e.g. `mdi:rocket`. */\r\n @property({ type: String })\r\n icon = '';\r\n\r\n @property({ type: String })\r\n title = '';\r\n\r\n /** Markdown. */\r\n @property({ type: String })\r\n description = '';\r\n\r\n @property({ type: String })\r\n href = '';\r\n\r\n @property({ type: String, attribute: 'action-label' })\r\n actionLabel = 'Learn more';\r\n\r\n @property({ type: Boolean, reflect: true })\r\n inverted = false;\r\n\r\n render() {\r\n const external = this.href.startsWith('http');\r\n return html`\r\n <st-card hoverable elevation=\"sm\" ?inverted=${this.inverted} part=\"card\">\r\n <div class=\"content\" part=\"content\">\r\n ${this.icon\r\n ? html`<div class=\"icon\" part=\"icon\"><iconify-icon icon=${this.icon}></iconify-icon></div>`\r\n : nothing}\r\n <h3 class=\"title\" part=\"title\">${this.title}</h3>\r\n <st-markdown class=\"description\" part=\"description\" .content=${this.description}></st-markdown>\r\n ${this.href\r\n ? html`\r\n <a\r\n class=\"link\"\r\n part=\"link\"\r\n href=${this.href}\r\n target=${external ? '_blank' : '_self'}\r\n rel=${external ? 'noopener noreferrer' : nothing}\r\n >\r\n ${this.actionLabel} <span>→</span>\r\n </a>\r\n `\r\n : nothing}\r\n </div>\r\n </st-card>\r\n `;\r\n }\r\n}\r\n"],"mappings":"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","names":["LitElement","css","html","nothing","customElement","property","LitElement","nothing","html","css","property","customElement"]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export {
|
|
13
|
+
__decorateClass
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-EUXUH3YW.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|