brand-shell 0.11.0 → 0.13.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/dist/brand-shell.schema.json +22 -3
- package/dist/index.d.mts +17 -61
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +61 -23
- package/dist/index.mjs.map +1 -1
- package/dist/svelte.d.mts +1 -1
- package/dist/svelte.mjs +1 -1
- package/dist/validation-Cic4hPME.d.mts +164 -0
- package/dist/validation-Cic4hPME.d.mts.map +1 -0
- package/dist/{validation-xdqzwr3p.mjs → validation-CtH2UkVv.mjs} +90 -39
- package/dist/validation-CtH2UkVv.mjs.map +1 -0
- package/dist/vue.d.mts +22 -2
- package/dist/vue.d.mts.map +1 -1
- package/dist/vue.mjs +10 -4
- package/dist/vue.mjs.map +1 -1
- package/dist/web.d.mts +17 -5
- package/dist/web.d.mts.map +1 -1
- package/dist/web.mjs +77 -33
- package/dist/web.mjs.map +1 -1
- package/package.json +6 -4
- package/src/svelte/BrandFooter.svelte +24 -0
- package/src/svelte/BrandHeader.svelte +24 -0
- package/src/svelte/index.svelte.ts +4 -0
- package/dist/types-PQziYg7Z.d.mts +0 -81
- package/dist/types-PQziYg7Z.d.mts.map +0 -1
- package/dist/validation-xdqzwr3p.mjs.map +0 -1
package/dist/web.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { C as BrandAction, E as BrandTheme, T as BrandNavLink, c as validateBrandTheme, s as validateBrandDetails, w as BrandDetails } from "./validation-Cic4hPME.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/web/index.d.ts
|
|
4
4
|
declare const HTMLElementBase: typeof HTMLElement;
|
|
@@ -6,15 +6,24 @@ interface RegisterBrandShellElementsOptions {
|
|
|
6
6
|
headerTagName?: string;
|
|
7
7
|
footerTagName?: string;
|
|
8
8
|
}
|
|
9
|
+
interface LinkFactoryOptions {
|
|
10
|
+
href: string;
|
|
11
|
+
className: string;
|
|
12
|
+
ariaLabel: string;
|
|
13
|
+
target: string;
|
|
14
|
+
rel?: string;
|
|
15
|
+
}
|
|
9
16
|
interface BrandShellElementProps {
|
|
10
17
|
details: BrandDetails;
|
|
11
18
|
theme?: BrandTheme | null;
|
|
12
19
|
shellClass?: string | null;
|
|
20
|
+
linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement;
|
|
13
21
|
}
|
|
14
22
|
type BrandShellElementLike = HTMLElement & {
|
|
15
23
|
details?: BrandDetails | null;
|
|
16
24
|
theme?: BrandTheme | null;
|
|
17
25
|
shellClass?: string | null;
|
|
26
|
+
linkFactory?: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null;
|
|
18
27
|
};
|
|
19
28
|
interface SerializedBrandShellAttributes {
|
|
20
29
|
details: string;
|
|
@@ -26,23 +35,26 @@ declare abstract class BaseBrandShellElement extends HTMLElementBase {
|
|
|
26
35
|
private _details;
|
|
27
36
|
private _theme;
|
|
28
37
|
private _shellClass;
|
|
38
|
+
private _linkFactory;
|
|
29
39
|
get details(): BrandDetails | null;
|
|
30
40
|
set details(value: BrandDetails | null);
|
|
31
41
|
get theme(): BrandTheme | null;
|
|
32
42
|
set theme(value: BrandTheme | null);
|
|
33
43
|
get shellClass(): string | null;
|
|
34
44
|
set shellClass(value: string | null);
|
|
45
|
+
get linkFactory(): ((options: LinkFactoryOptions) => HTMLAnchorElement) | null;
|
|
46
|
+
set linkFactory(value: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null);
|
|
35
47
|
connectedCallback(): void;
|
|
36
48
|
attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null): void;
|
|
37
|
-
protected abstract build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement;
|
|
49
|
+
protected abstract build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null, linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null): HTMLElement;
|
|
38
50
|
private render;
|
|
39
51
|
private upgradeProperty;
|
|
40
52
|
}
|
|
41
53
|
declare class BrandHeaderElement extends BaseBrandShellElement {
|
|
42
|
-
protected build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement;
|
|
54
|
+
protected build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null, linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null): HTMLElement;
|
|
43
55
|
}
|
|
44
56
|
declare class BrandFooterElement extends BaseBrandShellElement {
|
|
45
|
-
protected build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement;
|
|
57
|
+
protected build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null, linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null): HTMLElement;
|
|
46
58
|
}
|
|
47
59
|
declare function registerBrandShellElements(options?: RegisterBrandShellElementsOptions): {
|
|
48
60
|
headerTagName: string;
|
|
@@ -57,5 +69,5 @@ declare global {
|
|
|
57
69
|
}
|
|
58
70
|
} //# sourceMappingURL=index.d.ts.map
|
|
59
71
|
//#endregion
|
|
60
|
-
export { type BrandAction, type BrandDetails, BrandFooterElement, BrandHeaderElement, type BrandNavLink, BrandShellElementLike, BrandShellElementProps, type BrandTheme, RegisterBrandShellElementsOptions, SerializedBrandShellAttributes, applyBrandShellProps, registerBrandShellElements, serializeBrandShellAttributes };
|
|
72
|
+
export { type BrandAction, type BrandDetails, BrandFooterElement, BrandHeaderElement, type BrandNavLink, BrandShellElementLike, BrandShellElementProps, type BrandTheme, LinkFactoryOptions, RegisterBrandShellElementsOptions, SerializedBrandShellAttributes, applyBrandShellProps, registerBrandShellElements, serializeBrandShellAttributes, validateBrandDetails, validateBrandTheme };
|
|
61
73
|
//# sourceMappingURL=web.d.mts.map
|
package/dist/web.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.d.mts","names":[],"sources":["../src/web/index.ts"],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"web.d.mts","names":[],"sources":["../src/web/index.ts"],"mappings":";;;cAyBM,eAAA,SAAwB,WAAA;AAAA,UAGb,iCAAA;EACf,aAAA;EACA,aAAA;AAAA;AAAA,UAGe,kBAAA;EACf,IAAA;EACA,SAAA;EACA,SAAA;EACA,MAAA;EACA,GAAA;AAAA;AAAA,UAGe,sBAAA;EACf,OAAA,EAAS,YAAA;EACT,KAAA,GAAQ,UAAA;EACR,UAAA;EACA,WAAA,IAAe,OAAA,EAAS,kBAAA,KAAuB,iBAAA;AAAA;AAAA,KAGrC,qBAAA,GAAwB,WAAA;EAClC,OAAA,GAAU,YAAA;EACV,KAAA,GAAQ,UAAA;EACR,UAAA;EACA,WAAA,KAAgB,OAAA,EAAS,kBAAA,KAAuB,iBAAA;AAAA;AAAA,UAGjC,8BAAA;EACf,OAAA;EACA,KAAA;EACA,aAAA;AAAA;AAAA,uBASa,qBAAA,SAA8B,eAAA;EAAA,WAChC,kBAAA,CAAA;EAAA,QAIH,QAAA;EAAA,QACA,MAAA;EAAA,QACA,WAAA;EAAA,QACA,YAAA;EAAA,IAEJ,OAAA,CAAA,GAAW,YAAA;EAAA,IAIX,OAAA,CAAQ,KAAA,EAAO,YAAA;EAAA,IAKf,KAAA,CAAA,GAAS,UAAA;EAAA,IAIT,KAAA,CAAM,KAAA,EAAO,UAAA;EAAA,IAKb,UAAA,CAAA;EAAA,IAIA,UAAA,CAAW,KAAA;EAAA,IAKX,WAAA,CAAA,KAAiB,OAAA,EAAS,kBAAA,KAAuB,iBAAA;EAAA,IAIjD,WAAA,CAAY,KAAA,IAAS,OAAA,EAAS,kBAAA,KAAuB,iBAAA;EAKzD,iBAAA,CAAA;EAeA,wBAAA,CAAyB,IAAA,UAAc,SAAA,iBAA0B,QAAA;EAAA,mBAW9C,KAAA,CACjB,OAAA,EAAS,YAAA,EACT,KAAA,EAAO,UAAA,SACP,UAAA,iBACA,WAAA,IAAe,OAAA,EAAS,kBAAA,KAAuB,iBAAA,WAC9C,WAAA;EAAA,QAEK,MAAA;EAAA,QA2BA,eAAA;AAAA;AAAA,cASG,kBAAA,SAA2B,qBAAA;EAAA,UAC5B,KAAA,CACR,OAAA,EAAS,YAAA,EACT,KAAA,EAAO,UAAA,SACP,UAAA,iBACA,WAAA,IAAe,OAAA,EAAS,kBAAA,KAAuB,iBAAA,WAC9C,WAAA;AAAA;AAAA,cAKQ,kBAAA,SAA2B,qBAAA;EAAA,UAC5B,KAAA,CACR,OAAA,EAAS,YAAA,EACT,KAAA,EAAO,UAAA,SACP,UAAA,iBACA,WAAA,IAAe,OAAA,EAAS,kBAAA,KAAuB,iBAAA,WAC9C,WAAA;AAAA;AAAA,iBAKW,0BAAA,CAA2B,OAAA,GAAS,iCAAA;;;;iBAsBpC,oBAAA,CACd,OAAA,EAAS,qBAAA,qBACT,KAAA,EAAO,sBAAA;AAAA,iBAaO,6BAAA,CAA8B,KAAA,EAAO,sBAAA,GAAyB,8BAAA;AAAA,QAwXtE,MAAA;EAAA,UACI,qBAAA;IACR,cAAA,EAAgB,kBAAA;IAChB,cAAA,EAAgB,kBAAA;EAAA;AAAA"}
|
package/dist/web.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as normalizeBrandTheme, c as themeToCssVariables, l as shouldValidateInDev, n as assertValidBrandDetails, o as validateBrandDetails, r as assertValidBrandTheme, s as validateBrandTheme, t as BrandShellValidationError, u as buildShellViewModel } from "./validation-
|
|
1
|
+
import { a as normalizeBrandTheme, c as themeToCssVariables, l as shouldValidateInDev, n as assertValidBrandDetails, o as validateBrandDetails, r as assertValidBrandTheme, s as validateBrandTheme, t as BrandShellValidationError, u as buildShellViewModel } from "./validation-CtH2UkVv.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/web/index.ts
|
|
4
4
|
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
@@ -9,6 +9,7 @@ var BaseBrandShellElement = class extends HTMLElementBase {
|
|
|
9
9
|
this._details = null;
|
|
10
10
|
this._theme = null;
|
|
11
11
|
this._shellClass = null;
|
|
12
|
+
this._linkFactory = null;
|
|
12
13
|
}
|
|
13
14
|
static get observedAttributes() {
|
|
14
15
|
return [
|
|
@@ -38,10 +39,18 @@ var BaseBrandShellElement = class extends HTMLElementBase {
|
|
|
38
39
|
this._shellClass = value;
|
|
39
40
|
this.render();
|
|
40
41
|
}
|
|
42
|
+
get linkFactory() {
|
|
43
|
+
return this._linkFactory;
|
|
44
|
+
}
|
|
45
|
+
set linkFactory(value) {
|
|
46
|
+
this._linkFactory = value;
|
|
47
|
+
this.render();
|
|
48
|
+
}
|
|
41
49
|
connectedCallback() {
|
|
42
50
|
this.upgradeProperty("details");
|
|
43
51
|
this.upgradeProperty("theme");
|
|
44
52
|
this.upgradeProperty("shellClass");
|
|
53
|
+
this.upgradeProperty("linkFactory");
|
|
45
54
|
const attrs = parseAttributes(this);
|
|
46
55
|
if (this._details == null) this._details = attrs.details;
|
|
47
56
|
if (this._theme == null) this._theme = attrs.theme;
|
|
@@ -70,7 +79,7 @@ var BaseBrandShellElement = class extends HTMLElementBase {
|
|
|
70
79
|
if (!themeResult.valid && shouldValidateInDev()) throw new BrandShellValidationError("brand-shell/web theme", themeResult.errors);
|
|
71
80
|
const normalizedDetails = detailsResult.normalized;
|
|
72
81
|
const normalizedTheme = themeResult.normalized ?? null;
|
|
73
|
-
const element = this.build(normalizedDetails, normalizedTheme, this._shellClass);
|
|
82
|
+
const element = this.build(normalizedDetails, normalizedTheme, this._shellClass, this._linkFactory);
|
|
74
83
|
this.replaceChildren(element);
|
|
75
84
|
}
|
|
76
85
|
upgradeProperty(propertyName) {
|
|
@@ -82,13 +91,13 @@ var BaseBrandShellElement = class extends HTMLElementBase {
|
|
|
82
91
|
}
|
|
83
92
|
};
|
|
84
93
|
var BrandHeaderElement = class extends BaseBrandShellElement {
|
|
85
|
-
build(details, theme, shellClass) {
|
|
86
|
-
return createHeader(details, theme, shellClass);
|
|
94
|
+
build(details, theme, shellClass, linkFactory) {
|
|
95
|
+
return createHeader(details, theme, shellClass, linkFactory ?? void 0);
|
|
87
96
|
}
|
|
88
97
|
};
|
|
89
98
|
var BrandFooterElement = class extends BaseBrandShellElement {
|
|
90
|
-
build(details, theme, shellClass) {
|
|
91
|
-
return createFooter(details, theme, shellClass);
|
|
99
|
+
build(details, theme, shellClass, linkFactory) {
|
|
100
|
+
return createFooter(details, theme, shellClass, linkFactory ?? void 0);
|
|
92
101
|
}
|
|
93
102
|
};
|
|
94
103
|
function registerBrandShellElements(options = {}) {
|
|
@@ -117,6 +126,7 @@ function applyBrandShellProps(element, props) {
|
|
|
117
126
|
element.details = validateBrandDetails(props.details).normalized ?? props.details;
|
|
118
127
|
element.theme = normalizeBrandTheme(props.theme ?? null);
|
|
119
128
|
element.shellClass = props.shellClass ?? null;
|
|
129
|
+
element.linkFactory = props.linkFactory ?? null;
|
|
120
130
|
}
|
|
121
131
|
function serializeBrandShellAttributes(props) {
|
|
122
132
|
if (shouldValidateInDev()) {
|
|
@@ -151,7 +161,7 @@ function normalizeClassName(value) {
|
|
|
151
161
|
const trimmed = value.trim();
|
|
152
162
|
return trimmed.length > 0 ? trimmed : null;
|
|
153
163
|
}
|
|
154
|
-
function createHeader(details, theme, shellClass) {
|
|
164
|
+
function createHeader(details, theme, shellClass, linkFactory) {
|
|
155
165
|
const header = document.createElement("header");
|
|
156
166
|
header.className = joinClassNames("brand-shell-header", shellClass);
|
|
157
167
|
header.setAttribute("role", "banner");
|
|
@@ -159,20 +169,19 @@ function createHeader(details, theme, shellClass) {
|
|
|
159
169
|
header.dataset.brandCtaLayout = resolveCtaLayout(theme);
|
|
160
170
|
const inner = document.createElement("div");
|
|
161
171
|
inner.className = "brand-shell-header__inner";
|
|
162
|
-
const identity = details.homeHref ? createAnchor(details.homeHref, "brand-shell-header__name", details.name) : createSpan("brand-shell-header__name", details.name);
|
|
163
|
-
if (details.homeHref && identity instanceof HTMLAnchorElement) identity.setAttribute("aria-label", `${details.name} home`);
|
|
172
|
+
const identity = details.homeHref ? createAnchor(details.homeHref, "brand-shell-header__name", details.name, `${details.name} home`, "_self", void 0, linkFactory) : createSpan("brand-shell-header__name", details.name);
|
|
164
173
|
inner.append(identity);
|
|
165
174
|
const actions = document.createElement("div");
|
|
166
175
|
actions.className = "brand-shell-header__actions";
|
|
167
176
|
const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(details);
|
|
168
|
-
if (navLinks.length > 0) actions.append(createNav(navLinks, "brand-shell-header", "Primary"));
|
|
169
|
-
if (ctaLinks.length > 0) actions.append(createCtas(ctaLinks, "brand-shell-header__ctas"));
|
|
177
|
+
if (navLinks.length > 0) actions.append(createNav(navLinks, "brand-shell-header", "Primary", linkFactory));
|
|
178
|
+
if (ctaLinks.length > 0) actions.append(createCtas(ctaLinks, "brand-shell-header__ctas", linkFactory));
|
|
170
179
|
if (socialLinks.length > 0) actions.append(createSocialLinks(socialLinks, "brand-shell-header__social", "brand-shell-header__social-link"));
|
|
171
180
|
inner.append(actions);
|
|
172
181
|
header.append(inner);
|
|
173
182
|
return header;
|
|
174
183
|
}
|
|
175
|
-
function createFooter(details, theme, shellClass) {
|
|
184
|
+
function createFooter(details, theme, shellClass, linkFactory) {
|
|
176
185
|
const footer = document.createElement("footer");
|
|
177
186
|
footer.className = joinClassNames("brand-shell-footer", shellClass);
|
|
178
187
|
footer.setAttribute("role", "contentinfo");
|
|
@@ -188,15 +197,15 @@ function createFooter(details, theme, shellClass) {
|
|
|
188
197
|
if (details.tagline) brand.append(createParagraph("brand-shell-footer__tagline", details.tagline));
|
|
189
198
|
top.append(brand);
|
|
190
199
|
const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(details);
|
|
191
|
-
if (navLinks.length > 0) top.append(createNav(navLinks, "brand-shell-footer", "Footer"));
|
|
192
|
-
if (ctaLinks.length > 0) top.append(createCtas(ctaLinks, "brand-shell-footer__ctas"));
|
|
200
|
+
if (navLinks.length > 0) top.append(createNav(navLinks, "brand-shell-footer", "Footer", linkFactory));
|
|
201
|
+
if (ctaLinks.length > 0) top.append(createCtas(ctaLinks, "brand-shell-footer__ctas", linkFactory));
|
|
193
202
|
if (socialLinks.length > 0) top.append(createSocialLinks(socialLinks, "brand-shell-footer__social", "brand-shell-footer__social-link"));
|
|
194
203
|
const copy = createParagraph("brand-shell-footer__copy", `© ${(/* @__PURE__ */ new Date()).getFullYear()} ${details.name}`);
|
|
195
204
|
inner.append(top, copy);
|
|
196
205
|
footer.append(inner);
|
|
197
206
|
return footer;
|
|
198
207
|
}
|
|
199
|
-
function createNav(links, blockClass, ariaLabel) {
|
|
208
|
+
function createNav(links, blockClass, ariaLabel, linkFactory) {
|
|
200
209
|
const nav = document.createElement("nav");
|
|
201
210
|
nav.className = `${blockClass}__nav`;
|
|
202
211
|
nav.setAttribute("aria-label", ariaLabel);
|
|
@@ -204,25 +213,18 @@ function createNav(links, blockClass, ariaLabel) {
|
|
|
204
213
|
list.className = `${blockClass}__list`;
|
|
205
214
|
for (const link of links) {
|
|
206
215
|
const item = document.createElement("li");
|
|
207
|
-
const anchor = createAnchor(link.href, `${blockClass}__link`, link.label);
|
|
208
|
-
anchor.target = link.target;
|
|
209
|
-
if (link.rel) anchor.rel = link.rel;
|
|
210
|
-
anchor.setAttribute("aria-label", link.ariaLabel);
|
|
216
|
+
const anchor = createAnchor(link.href, `${blockClass}__link`, link.label, link.ariaLabel, link.target, link.rel, linkFactory);
|
|
211
217
|
item.append(anchor);
|
|
212
218
|
list.append(item);
|
|
213
219
|
}
|
|
214
220
|
nav.append(list);
|
|
215
221
|
return nav;
|
|
216
222
|
}
|
|
217
|
-
function createCtas(actions, containerClass) {
|
|
223
|
+
function createCtas(actions, containerClass, linkFactory) {
|
|
218
224
|
const container = document.createElement("div");
|
|
219
225
|
container.className = containerClass;
|
|
220
226
|
actions.forEach((action) => {
|
|
221
|
-
const anchor = createAnchor(action.href, "brand-shell-button", action.label);
|
|
222
|
-
anchor.className = joinClassNames(anchor.className, `brand-shell-button--${action.variant}`);
|
|
223
|
-
anchor.setAttribute("aria-label", action.ariaLabel);
|
|
224
|
-
anchor.target = action.target;
|
|
225
|
-
if (action.rel) anchor.rel = action.rel;
|
|
227
|
+
const anchor = createAnchor(action.href, joinClassNames("brand-shell-button", `brand-shell-button--${action.variant}`), action.label, action.ariaLabel, action.target, action.rel, linkFactory);
|
|
226
228
|
container.append(anchor);
|
|
227
229
|
});
|
|
228
230
|
return container;
|
|
@@ -234,24 +236,33 @@ function createSocialLinks(links, containerClass, linkClass) {
|
|
|
234
236
|
for (const link of links) {
|
|
235
237
|
const anchor = createAnchor(link.href, linkClass, "");
|
|
236
238
|
anchor.setAttribute("aria-label", link.label);
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
239
|
+
if (!link.href.startsWith("mailto:")) {
|
|
240
|
+
anchor.target = "_blank";
|
|
241
|
+
anchor.rel = "noopener noreferrer";
|
|
242
|
+
}
|
|
243
|
+
const icon = createSocialIcon(link.platform, link.iconSvg);
|
|
240
244
|
if (icon) anchor.append(icon);
|
|
241
245
|
else anchor.append(createSpan("", link.label[0] ?? "?"));
|
|
242
246
|
container.append(anchor);
|
|
243
247
|
}
|
|
244
248
|
return container;
|
|
245
249
|
}
|
|
246
|
-
function createSocialIcon(platform) {
|
|
250
|
+
function createSocialIcon(platform, iconSvg) {
|
|
247
251
|
switch (platform) {
|
|
248
252
|
case "github": return createFilledIcon("M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z");
|
|
249
253
|
case "twitter": return createFilledIcon("M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z");
|
|
250
254
|
case "linkedin": return createFilledIcon("M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z");
|
|
251
255
|
case "discord": return createFilledIcon("M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z");
|
|
252
256
|
case "email": return createStrokedIcon(["m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"], { rx: "2" });
|
|
253
|
-
case "website": return
|
|
254
|
-
default:
|
|
257
|
+
case "website": return createGlobeIcon();
|
|
258
|
+
default:
|
|
259
|
+
if (iconSvg) {
|
|
260
|
+
const span = document.createElement("span");
|
|
261
|
+
span.setAttribute("aria-hidden", "true");
|
|
262
|
+
span.innerHTML = iconSvg;
|
|
263
|
+
return span;
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
255
266
|
}
|
|
256
267
|
}
|
|
257
268
|
function createFilledIcon(pathData) {
|
|
@@ -285,6 +296,25 @@ function createStrokedIcon(pathData, rectAttributes) {
|
|
|
285
296
|
}
|
|
286
297
|
return svg;
|
|
287
298
|
}
|
|
299
|
+
function createGlobeIcon() {
|
|
300
|
+
const svg = createBaseSvg();
|
|
301
|
+
svg.setAttribute("fill", "none");
|
|
302
|
+
svg.setAttribute("stroke", "currentColor");
|
|
303
|
+
svg.setAttribute("stroke-width", "2");
|
|
304
|
+
svg.setAttribute("stroke-linecap", "round");
|
|
305
|
+
svg.setAttribute("stroke-linejoin", "round");
|
|
306
|
+
const circle = document.createElementNS(SVG_NS, "circle");
|
|
307
|
+
circle.setAttribute("cx", "12");
|
|
308
|
+
circle.setAttribute("cy", "12");
|
|
309
|
+
circle.setAttribute("r", "10");
|
|
310
|
+
svg.append(circle);
|
|
311
|
+
for (const d of ["M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20", "M2 12h20"]) {
|
|
312
|
+
const path = document.createElementNS(SVG_NS, "path");
|
|
313
|
+
path.setAttribute("d", d);
|
|
314
|
+
svg.append(path);
|
|
315
|
+
}
|
|
316
|
+
return svg;
|
|
317
|
+
}
|
|
288
318
|
function createBaseSvg() {
|
|
289
319
|
const svg = document.createElementNS(SVG_NS, "svg");
|
|
290
320
|
svg.setAttribute("viewBox", "0 0 24 24");
|
|
@@ -303,11 +333,25 @@ function resolveCtaLayout(theme) {
|
|
|
303
333
|
function joinClassNames(...classNames) {
|
|
304
334
|
return classNames.filter(Boolean).join(" ");
|
|
305
335
|
}
|
|
306
|
-
function createAnchor(href, className, text) {
|
|
336
|
+
function createAnchor(href, className, text, ariaLabel, target, rel, linkFactory) {
|
|
337
|
+
if (linkFactory) {
|
|
338
|
+
const anchor = linkFactory({
|
|
339
|
+
href,
|
|
340
|
+
className,
|
|
341
|
+
ariaLabel: ariaLabel ?? text,
|
|
342
|
+
target: target ?? "_self",
|
|
343
|
+
rel
|
|
344
|
+
});
|
|
345
|
+
anchor.textContent = text;
|
|
346
|
+
return anchor;
|
|
347
|
+
}
|
|
307
348
|
const anchor = document.createElement("a");
|
|
308
349
|
anchor.href = href;
|
|
309
350
|
anchor.className = className;
|
|
310
351
|
anchor.textContent = text;
|
|
352
|
+
if (ariaLabel) anchor.setAttribute("aria-label", ariaLabel);
|
|
353
|
+
if (target) anchor.target = target;
|
|
354
|
+
if (rel) anchor.rel = rel;
|
|
311
355
|
return anchor;
|
|
312
356
|
}
|
|
313
357
|
function createParagraph(className, text) {
|
|
@@ -324,5 +368,5 @@ function createSpan(className, text) {
|
|
|
324
368
|
}
|
|
325
369
|
|
|
326
370
|
//#endregion
|
|
327
|
-
export { BrandFooterElement, BrandHeaderElement, applyBrandShellProps, registerBrandShellElements, serializeBrandShellAttributes };
|
|
371
|
+
export { BrandFooterElement, BrandHeaderElement, applyBrandShellProps, registerBrandShellElements, serializeBrandShellAttributes, validateBrandDetails, validateBrandTheme };
|
|
328
372
|
//# sourceMappingURL=web.mjs.map
|
package/dist/web.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web.mjs","names":[],"sources":["../src/web/index.ts"],"sourcesContent":["import { buildShellViewModel, themeToCssVariables } from \"../core\";\nimport type {\n BrandDetails,\n BrandTheme,\n NormalizedBrandDetails,\n ShellActionLink,\n ShellNavLink,\n SocialLink,\n SocialPlatform,\n} from \"../core\";\nimport {\n BrandShellValidationError,\n assertValidBrandDetails,\n assertValidBrandTheme,\n normalizeBrandTheme,\n shouldValidateInDev,\n validateBrandDetails,\n validateBrandTheme,\n} from \"../core\";\n\nexport type { BrandAction, BrandDetails, BrandNavLink, BrandTheme } from \"../core\";\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\nconst HTMLElementBase: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nexport interface RegisterBrandShellElementsOptions {\n headerTagName?: string;\n footerTagName?: string;\n}\n\nexport interface BrandShellElementProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n shellClass?: string | null;\n}\n\nexport type BrandShellElementLike = HTMLElement & {\n details?: BrandDetails | null;\n theme?: BrandTheme | null;\n shellClass?: string | null;\n};\n\nexport interface SerializedBrandShellAttributes {\n details: string;\n theme?: string;\n \"shell-class\"?: string;\n}\n\ninterface ParsedAttributes {\n details: BrandDetails | null;\n theme: BrandTheme | null;\n shellClass: string | null;\n}\n\nabstract class BaseBrandShellElement extends HTMLElementBase {\n static get observedAttributes() {\n return [\"details\", \"theme\", \"shell-class\"];\n }\n\n private _details: BrandDetails | null = null;\n private _theme: BrandTheme | null = null;\n private _shellClass: string | null = null;\n\n get details(): BrandDetails | null {\n return this._details;\n }\n\n set details(value: BrandDetails | null) {\n this._details = value;\n this.render();\n }\n\n get theme(): BrandTheme | null {\n return this._theme;\n }\n\n set theme(value: BrandTheme | null) {\n this._theme = value;\n this.render();\n }\n\n get shellClass(): string | null {\n return this._shellClass;\n }\n\n set shellClass(value: string | null) {\n this._shellClass = value;\n this.render();\n }\n\n connectedCallback() {\n this.upgradeProperty(\"details\");\n this.upgradeProperty(\"theme\");\n this.upgradeProperty(\"shellClass\");\n\n const attrs = parseAttributes(this);\n if (this._details == null) this._details = attrs.details;\n if (this._theme == null) this._theme = attrs.theme;\n if (this._shellClass == null) this._shellClass = attrs.shellClass;\n\n if (this.style.display !== \"block\") this.style.display = \"block\";\n this.render();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {\n if (name === \"details\") {\n this._details = parseJsonAttribute<BrandDetails>(newValue);\n } else if (name === \"theme\") {\n this._theme = parseJsonAttribute<BrandTheme>(newValue);\n } else if (name === \"shell-class\") {\n this._shellClass = normalizeClassName(newValue);\n }\n this.render();\n }\n\n protected abstract build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement;\n\n private render() {\n if (this._details == null) {\n this.replaceChildren();\n return;\n }\n\n const detailsResult = validateBrandDetails(this._details);\n if (!detailsResult.valid) {\n if (shouldValidateInDev()) {\n throw new BrandShellValidationError(\"brand-shell/web details\", detailsResult.errors);\n }\n this.replaceChildren();\n return;\n }\n\n const themeResult = validateBrandTheme(this._theme);\n if (!themeResult.valid && shouldValidateInDev()) {\n throw new BrandShellValidationError(\"brand-shell/web theme\", themeResult.errors);\n }\n\n const normalizedDetails = detailsResult.normalized as NormalizedBrandDetails;\n const normalizedTheme = themeResult.normalized ?? null;\n\n const element = this.build(normalizedDetails, normalizedTheme, this._shellClass);\n this.replaceChildren(element);\n }\n\n private upgradeProperty(propertyName: \"details\" | \"theme\" | \"shellClass\") {\n if (Object.prototype.hasOwnProperty.call(this, propertyName)) {\n const value = (this as unknown as Record<string, unknown>)[propertyName];\n delete (this as unknown as Record<string, unknown>)[propertyName];\n (this as unknown as Record<string, unknown>)[propertyName] = value;\n }\n }\n}\n\nexport class BrandHeaderElement extends BaseBrandShellElement {\n protected build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement {\n return createHeader(details, theme, shellClass);\n }\n}\n\nexport class BrandFooterElement extends BaseBrandShellElement {\n protected build(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement {\n return createFooter(details, theme, shellClass);\n }\n}\n\nexport function registerBrandShellElements(options: RegisterBrandShellElementsOptions = {}) {\n if (typeof customElements === \"undefined\") {\n throw new Error(\"Custom elements are not available in this environment.\");\n }\n\n const headerTagName = options.headerTagName ?? \"brand-header\";\n const footerTagName = options.footerTagName ?? \"brand-footer\";\n\n if (!customElements.get(headerTagName)) {\n const HeaderConstructor =\n headerTagName === \"brand-header\" ? BrandHeaderElement : class extends BrandHeaderElement {};\n customElements.define(headerTagName, HeaderConstructor);\n }\n if (!customElements.get(footerTagName)) {\n const FooterConstructor =\n footerTagName === \"brand-footer\" ? BrandFooterElement : class extends BrandFooterElement {};\n customElements.define(footerTagName, FooterConstructor);\n }\n\n return { headerTagName, footerTagName };\n}\n\nexport function applyBrandShellProps(\n element: BrandShellElementLike | null | undefined,\n props: BrandShellElementProps,\n) {\n if (!element) return;\n if (shouldValidateInDev()) {\n assertValidBrandDetails(props.details, \"brand-shell/web details\");\n assertValidBrandTheme(props.theme, \"brand-shell/web theme\");\n }\n element.details = validateBrandDetails(props.details).normalized ?? props.details;\n element.theme = normalizeBrandTheme(props.theme ?? null);\n element.shellClass = props.shellClass ?? null;\n}\n\nexport function serializeBrandShellAttributes(props: BrandShellElementProps): SerializedBrandShellAttributes {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(props.details, \"brand-shell/web serialize details\");\n assertValidBrandTheme(props.theme, \"brand-shell/web serialize theme\");\n }\n\n const normalizedDetails = validateBrandDetails(props.details).normalized ?? props.details;\n const normalizedTheme = normalizeBrandTheme(props.theme ?? null);\n\n const attributes: SerializedBrandShellAttributes = {\n details: JSON.stringify(normalizedDetails),\n };\n\n if (normalizedTheme) {\n attributes.theme = JSON.stringify(normalizedTheme);\n }\n\n const shellClass = normalizeClassName(props.shellClass ?? null);\n if (shellClass) {\n attributes[\"shell-class\"] = shellClass;\n }\n\n return attributes;\n}\n\nfunction parseAttributes(element: Element): ParsedAttributes {\n return {\n details: parseJsonAttribute<BrandDetails>(element.getAttribute(\"details\")),\n theme: parseJsonAttribute<BrandTheme>(element.getAttribute(\"theme\")),\n shellClass: normalizeClassName(element.getAttribute(\"shell-class\")),\n };\n}\n\nfunction parseJsonAttribute<T>(value: string | null): T | null {\n if (!value) return null;\n try {\n return JSON.parse(value) as T;\n } catch {\n return null;\n }\n}\n\nfunction normalizeClassName(value: string | null): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction createHeader(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement {\n const header = document.createElement(\"header\");\n header.className = joinClassNames(\"brand-shell-header\", shellClass);\n header.setAttribute(\"role\", \"banner\");\n applyThemeVariables(header, theme);\n header.dataset.brandCtaLayout = resolveCtaLayout(theme);\n\n const inner = document.createElement(\"div\");\n inner.className = \"brand-shell-header__inner\";\n\n const identity = details.homeHref ? createAnchor(details.homeHref, \"brand-shell-header__name\", details.name) : createSpan(\"brand-shell-header__name\", details.name);\n if (details.homeHref && identity instanceof HTMLAnchorElement) {\n identity.setAttribute(\"aria-label\", `${details.name} home`);\n }\n inner.append(identity);\n\n const actions = document.createElement(\"div\");\n actions.className = \"brand-shell-header__actions\";\n\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(details);\n\n if (navLinks.length > 0) {\n actions.append(createNav(navLinks, \"brand-shell-header\", \"Primary\"));\n }\n\n if (ctaLinks.length > 0) {\n actions.append(createCtas(ctaLinks, \"brand-shell-header__ctas\"));\n }\n\n if (socialLinks.length > 0) {\n actions.append(createSocialLinks(socialLinks, \"brand-shell-header__social\", \"brand-shell-header__social-link\"));\n }\n\n inner.append(actions);\n header.append(inner);\n return header;\n}\n\nfunction createFooter(details: BrandDetails, theme: BrandTheme | null, shellClass: string | null): HTMLElement {\n const footer = document.createElement(\"footer\");\n footer.className = joinClassNames(\"brand-shell-footer\", shellClass);\n footer.setAttribute(\"role\", \"contentinfo\");\n applyThemeVariables(footer, theme);\n footer.dataset.brandCtaLayout = resolveCtaLayout(theme);\n\n const inner = document.createElement(\"div\");\n inner.className = \"brand-shell-footer__inner\";\n\n const top = document.createElement(\"div\");\n top.className = \"brand-shell-footer__top\";\n\n const brand = document.createElement(\"div\");\n brand.className = \"brand-shell-footer__brand\";\n brand.append(createParagraph(\"brand-shell-footer__name\", details.name));\n if (details.tagline) {\n brand.append(createParagraph(\"brand-shell-footer__tagline\", details.tagline));\n }\n top.append(brand);\n\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(details);\n\n if (navLinks.length > 0) {\n top.append(createNav(navLinks, \"brand-shell-footer\", \"Footer\"));\n }\n\n if (ctaLinks.length > 0) {\n top.append(createCtas(ctaLinks, \"brand-shell-footer__ctas\"));\n }\n\n if (socialLinks.length > 0) {\n top.append(createSocialLinks(socialLinks, \"brand-shell-footer__social\", \"brand-shell-footer__social-link\"));\n }\n\n const copy = createParagraph(\"brand-shell-footer__copy\", `© ${new Date().getFullYear()} ${details.name}`);\n\n inner.append(top, copy);\n footer.append(inner);\n return footer;\n}\n\nfunction createNav(links: ShellNavLink[], blockClass: \"brand-shell-header\" | \"brand-shell-footer\", ariaLabel: string): HTMLElement {\n const nav = document.createElement(\"nav\");\n nav.className = `${blockClass}__nav`;\n nav.setAttribute(\"aria-label\", ariaLabel);\n\n const list = document.createElement(\"ul\");\n list.className = `${blockClass}__list`;\n\n for (const link of links) {\n const item = document.createElement(\"li\");\n const anchor = createAnchor(link.href, `${blockClass}__link`, link.label);\n anchor.target = link.target;\n if (link.rel) anchor.rel = link.rel;\n anchor.setAttribute(\"aria-label\", link.ariaLabel);\n item.append(anchor);\n list.append(item);\n }\n\n nav.append(list);\n return nav;\n}\n\nfunction createCtas(actions: ShellActionLink[], containerClass: string): HTMLElement {\n const container = document.createElement(\"div\");\n container.className = containerClass;\n\n actions.forEach((action) => {\n const anchor = createAnchor(action.href, \"brand-shell-button\", action.label);\n anchor.className = joinClassNames(anchor.className, `brand-shell-button--${action.variant}`);\n anchor.setAttribute(\"aria-label\", action.ariaLabel);\n anchor.target = action.target;\n if (action.rel) anchor.rel = action.rel;\n\n container.append(anchor);\n });\n\n return container;\n}\n\nfunction createSocialLinks(\n links: SocialLink[],\n containerClass: string,\n linkClass: string,\n): HTMLElement {\n const container = document.createElement(\"div\");\n container.className = containerClass;\n container.setAttribute(\"aria-label\", \"Social links\");\n\n for (const link of links) {\n const anchor = createAnchor(link.href, linkClass, \"\");\n anchor.setAttribute(\"aria-label\", link.label);\n anchor.target = \"_blank\";\n anchor.rel = \"noopener noreferrer\";\n\n const icon = createSocialIcon(link.platform);\n if (icon) {\n anchor.append(icon);\n } else {\n anchor.append(createSpan(\"\", link.label[0] ?? \"?\"));\n }\n\n container.append(anchor);\n }\n\n return container;\n}\n\nfunction createSocialIcon(platform: SocialPlatform): SVGSVGElement | null {\n switch (platform) {\n case \"github\":\n return createFilledIcon(\n \"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z\",\n );\n case \"twitter\":\n return createFilledIcon(\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\");\n case \"linkedin\":\n return createFilledIcon(\n \"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\",\n );\n case \"discord\":\n return createFilledIcon(\n \"M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z\",\n );\n case \"email\":\n return createStrokedIcon([\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\"], { rx: \"2\" });\n case \"website\":\n return createStrokedIcon([\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\"]);\n default:\n return null;\n }\n}\n\nfunction createFilledIcon(pathData: string): SVGSVGElement {\n const svg = createBaseSvg();\n svg.setAttribute(\"fill\", \"currentColor\");\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", pathData);\n svg.append(path);\n return svg;\n}\n\nfunction createStrokedIcon(pathData: string[], rectAttributes?: Record<string, string>): SVGSVGElement {\n const svg = createBaseSvg();\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"2\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n if (rectAttributes) {\n const rect = document.createElementNS(SVG_NS, \"rect\");\n rect.setAttribute(\"width\", \"20\");\n rect.setAttribute(\"height\", \"16\");\n rect.setAttribute(\"x\", \"2\");\n rect.setAttribute(\"y\", \"4\");\n for (const [attribute, value] of Object.entries(rectAttributes)) {\n rect.setAttribute(attribute, value);\n }\n svg.append(rect);\n }\n\n for (const d of pathData) {\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", d);\n svg.append(path);\n }\n\n return svg;\n}\n\nfunction createBaseSvg(): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"width\", \"1em\");\n svg.setAttribute(\"height\", \"1em\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n return svg;\n}\n\nfunction applyThemeVariables(element: HTMLElement, theme: BrandTheme | null) {\n const style = themeToCssVariables(theme);\n for (const [name, value] of Object.entries(style)) {\n element.style.setProperty(name, value);\n }\n}\n\nfunction resolveCtaLayout(theme: BrandTheme | null): \"inline\" | \"stacked\" {\n return theme?.ctaLayout === \"stacked\" ? \"stacked\" : \"inline\";\n}\n\nfunction joinClassNames(...classNames: Array<string | null | undefined>) {\n return classNames.filter(Boolean).join(\" \");\n}\n\nfunction createAnchor(href: string, className: string, text: string): HTMLAnchorElement {\n const anchor = document.createElement(\"a\");\n anchor.href = href;\n anchor.className = className;\n anchor.textContent = text;\n return anchor;\n}\n\nfunction createParagraph(className: string, text: string): HTMLParagraphElement {\n const paragraph = document.createElement(\"p\");\n paragraph.className = className;\n paragraph.textContent = text;\n return paragraph;\n}\n\nfunction createSpan(className: string, text: string): HTMLSpanElement {\n const span = document.createElement(\"span\");\n span.className = className;\n span.textContent = text;\n return span;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"brand-header\": BrandHeaderElement;\n \"brand-footer\": BrandFooterElement;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"web.mjs","names":[],"sources":["../src/web/index.ts"],"sourcesContent":["import { buildShellViewModel, themeToCssVariables } from \"../core\";\nimport type {\n BrandDetails,\n BrandTheme,\n NormalizedBrandDetails,\n ShellActionLink,\n ShellNavLink,\n SocialLink,\n SocialPlatform,\n} from \"../core\";\nimport {\n BrandShellValidationError,\n assertValidBrandDetails,\n assertValidBrandTheme,\n normalizeBrandTheme,\n shouldValidateInDev,\n validateBrandDetails,\n validateBrandTheme,\n} from \"../core\";\n\nexport type { BrandAction, BrandDetails, BrandNavLink, BrandTheme } from \"../core\";\nexport { validateBrandDetails, validateBrandTheme } from \"../core\";\n\nconst SVG_NS = \"http://www.w3.org/2000/svg\";\n\nconst HTMLElementBase: typeof HTMLElement =\n typeof HTMLElement === \"undefined\" ? (class {} as unknown as typeof HTMLElement) : HTMLElement;\n\nexport interface RegisterBrandShellElementsOptions {\n headerTagName?: string;\n footerTagName?: string;\n}\n\nexport interface LinkFactoryOptions {\n href: string;\n className: string;\n ariaLabel: string;\n target: string;\n rel?: string;\n}\n\nexport interface BrandShellElementProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n shellClass?: string | null;\n linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement;\n}\n\nexport type BrandShellElementLike = HTMLElement & {\n details?: BrandDetails | null;\n theme?: BrandTheme | null;\n shellClass?: string | null;\n linkFactory?: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null;\n};\n\nexport interface SerializedBrandShellAttributes {\n details: string;\n theme?: string;\n \"shell-class\"?: string;\n}\n\ninterface ParsedAttributes {\n details: BrandDetails | null;\n theme: BrandTheme | null;\n shellClass: string | null;\n}\n\nabstract class BaseBrandShellElement extends HTMLElementBase {\n static get observedAttributes() {\n return [\"details\", \"theme\", \"shell-class\"];\n }\n\n private _details: BrandDetails | null = null;\n private _theme: BrandTheme | null = null;\n private _shellClass: string | null = null;\n private _linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null = null;\n\n get details(): BrandDetails | null {\n return this._details;\n }\n\n set details(value: BrandDetails | null) {\n this._details = value;\n this.render();\n }\n\n get theme(): BrandTheme | null {\n return this._theme;\n }\n\n set theme(value: BrandTheme | null) {\n this._theme = value;\n this.render();\n }\n\n get shellClass(): string | null {\n return this._shellClass;\n }\n\n set shellClass(value: string | null) {\n this._shellClass = value;\n this.render();\n }\n\n get linkFactory(): ((options: LinkFactoryOptions) => HTMLAnchorElement) | null {\n return this._linkFactory;\n }\n\n set linkFactory(value: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null) {\n this._linkFactory = value;\n this.render();\n }\n\n connectedCallback() {\n this.upgradeProperty(\"details\");\n this.upgradeProperty(\"theme\");\n this.upgradeProperty(\"shellClass\");\n this.upgradeProperty(\"linkFactory\");\n\n const attrs = parseAttributes(this);\n if (this._details == null) this._details = attrs.details;\n if (this._theme == null) this._theme = attrs.theme;\n if (this._shellClass == null) this._shellClass = attrs.shellClass;\n\n if (this.style.display !== \"block\") this.style.display = \"block\";\n this.render();\n }\n\n attributeChangedCallback(name: string, _oldValue: string | null, newValue: string | null) {\n if (name === \"details\") {\n this._details = parseJsonAttribute<BrandDetails>(newValue);\n } else if (name === \"theme\") {\n this._theme = parseJsonAttribute<BrandTheme>(newValue);\n } else if (name === \"shell-class\") {\n this._shellClass = normalizeClassName(newValue);\n }\n this.render();\n }\n\n protected abstract build(\n details: BrandDetails,\n theme: BrandTheme | null,\n shellClass: string | null,\n linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null,\n ): HTMLElement;\n\n private render() {\n if (this._details == null) {\n this.replaceChildren();\n return;\n }\n\n const detailsResult = validateBrandDetails(this._details);\n if (!detailsResult.valid) {\n if (shouldValidateInDev()) {\n throw new BrandShellValidationError(\"brand-shell/web details\", detailsResult.errors);\n }\n this.replaceChildren();\n return;\n }\n\n const themeResult = validateBrandTheme(this._theme);\n if (!themeResult.valid && shouldValidateInDev()) {\n throw new BrandShellValidationError(\"brand-shell/web theme\", themeResult.errors);\n }\n\n const normalizedDetails = detailsResult.normalized as NormalizedBrandDetails;\n const normalizedTheme = themeResult.normalized ?? null;\n\n const element = this.build(normalizedDetails, normalizedTheme, this._shellClass, this._linkFactory);\n this.replaceChildren(element);\n }\n\n private upgradeProperty(propertyName: \"details\" | \"theme\" | \"shellClass\" | \"linkFactory\") {\n if (Object.prototype.hasOwnProperty.call(this, propertyName)) {\n const value = (this as unknown as Record<string, unknown>)[propertyName];\n delete (this as unknown as Record<string, unknown>)[propertyName];\n (this as unknown as Record<string, unknown>)[propertyName] = value;\n }\n }\n}\n\nexport class BrandHeaderElement extends BaseBrandShellElement {\n protected build(\n details: BrandDetails,\n theme: BrandTheme | null,\n shellClass: string | null,\n linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null,\n ): HTMLElement {\n return createHeader(details, theme, shellClass, linkFactory ?? undefined);\n }\n}\n\nexport class BrandFooterElement extends BaseBrandShellElement {\n protected build(\n details: BrandDetails,\n theme: BrandTheme | null,\n shellClass: string | null,\n linkFactory: ((options: LinkFactoryOptions) => HTMLAnchorElement) | null,\n ): HTMLElement {\n return createFooter(details, theme, shellClass, linkFactory ?? undefined);\n }\n}\n\nexport function registerBrandShellElements(options: RegisterBrandShellElementsOptions = {}) {\n if (typeof customElements === \"undefined\") {\n throw new Error(\"Custom elements are not available in this environment.\");\n }\n\n const headerTagName = options.headerTagName ?? \"brand-header\";\n const footerTagName = options.footerTagName ?? \"brand-footer\";\n\n if (!customElements.get(headerTagName)) {\n const HeaderConstructor =\n headerTagName === \"brand-header\" ? BrandHeaderElement : class extends BrandHeaderElement {};\n customElements.define(headerTagName, HeaderConstructor);\n }\n if (!customElements.get(footerTagName)) {\n const FooterConstructor =\n footerTagName === \"brand-footer\" ? BrandFooterElement : class extends BrandFooterElement {};\n customElements.define(footerTagName, FooterConstructor);\n }\n\n return { headerTagName, footerTagName };\n}\n\nexport function applyBrandShellProps(\n element: BrandShellElementLike | null | undefined,\n props: BrandShellElementProps,\n) {\n if (!element) return;\n if (shouldValidateInDev()) {\n assertValidBrandDetails(props.details, \"brand-shell/web details\");\n assertValidBrandTheme(props.theme, \"brand-shell/web theme\");\n }\n element.details = validateBrandDetails(props.details).normalized ?? props.details;\n element.theme = normalizeBrandTheme(props.theme ?? null);\n element.shellClass = props.shellClass ?? null;\n element.linkFactory = props.linkFactory ?? null;\n}\n\nexport function serializeBrandShellAttributes(props: BrandShellElementProps): SerializedBrandShellAttributes {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(props.details, \"brand-shell/web serialize details\");\n assertValidBrandTheme(props.theme, \"brand-shell/web serialize theme\");\n }\n\n const normalizedDetails = validateBrandDetails(props.details).normalized ?? props.details;\n const normalizedTheme = normalizeBrandTheme(props.theme ?? null);\n\n const attributes: SerializedBrandShellAttributes = {\n details: JSON.stringify(normalizedDetails),\n };\n\n if (normalizedTheme) {\n attributes.theme = JSON.stringify(normalizedTheme);\n }\n\n const shellClass = normalizeClassName(props.shellClass ?? null);\n if (shellClass) {\n attributes[\"shell-class\"] = shellClass;\n }\n\n return attributes;\n}\n\nfunction parseAttributes(element: Element): ParsedAttributes {\n return {\n details: parseJsonAttribute<BrandDetails>(element.getAttribute(\"details\")),\n theme: parseJsonAttribute<BrandTheme>(element.getAttribute(\"theme\")),\n shellClass: normalizeClassName(element.getAttribute(\"shell-class\")),\n };\n}\n\nfunction parseJsonAttribute<T>(value: string | null): T | null {\n if (!value) return null;\n try {\n return JSON.parse(value) as T;\n } catch {\n return null;\n }\n}\n\nfunction normalizeClassName(value: string | null): string | null {\n if (!value) return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction createHeader(\n details: BrandDetails,\n theme: BrandTheme | null,\n shellClass: string | null,\n linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement,\n): HTMLElement {\n const header = document.createElement(\"header\");\n header.className = joinClassNames(\"brand-shell-header\", shellClass);\n header.setAttribute(\"role\", \"banner\");\n applyThemeVariables(header, theme);\n header.dataset.brandCtaLayout = resolveCtaLayout(theme);\n\n const inner = document.createElement(\"div\");\n inner.className = \"brand-shell-header__inner\";\n\n const identity = details.homeHref\n ? createAnchor(details.homeHref, \"brand-shell-header__name\", details.name, `${details.name} home`, \"_self\", undefined, linkFactory)\n : createSpan(\"brand-shell-header__name\", details.name);\n inner.append(identity);\n\n const actions = document.createElement(\"div\");\n actions.className = \"brand-shell-header__actions\";\n\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(details);\n\n if (navLinks.length > 0) {\n actions.append(createNav(navLinks, \"brand-shell-header\", \"Primary\", linkFactory));\n }\n\n if (ctaLinks.length > 0) {\n actions.append(createCtas(ctaLinks, \"brand-shell-header__ctas\", linkFactory));\n }\n\n if (socialLinks.length > 0) {\n actions.append(createSocialLinks(socialLinks, \"brand-shell-header__social\", \"brand-shell-header__social-link\"));\n }\n\n inner.append(actions);\n header.append(inner);\n return header;\n}\n\nfunction createFooter(\n details: BrandDetails,\n theme: BrandTheme | null,\n shellClass: string | null,\n linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement,\n): HTMLElement {\n const footer = document.createElement(\"footer\");\n footer.className = joinClassNames(\"brand-shell-footer\", shellClass);\n footer.setAttribute(\"role\", \"contentinfo\");\n applyThemeVariables(footer, theme);\n footer.dataset.brandCtaLayout = resolveCtaLayout(theme);\n\n const inner = document.createElement(\"div\");\n inner.className = \"brand-shell-footer__inner\";\n\n const top = document.createElement(\"div\");\n top.className = \"brand-shell-footer__top\";\n\n const brand = document.createElement(\"div\");\n brand.className = \"brand-shell-footer__brand\";\n brand.append(createParagraph(\"brand-shell-footer__name\", details.name));\n if (details.tagline) {\n brand.append(createParagraph(\"brand-shell-footer__tagline\", details.tagline));\n }\n top.append(brand);\n\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(details);\n\n if (navLinks.length > 0) {\n top.append(createNav(navLinks, \"brand-shell-footer\", \"Footer\", linkFactory));\n }\n\n if (ctaLinks.length > 0) {\n top.append(createCtas(ctaLinks, \"brand-shell-footer__ctas\", linkFactory));\n }\n\n if (socialLinks.length > 0) {\n top.append(createSocialLinks(socialLinks, \"brand-shell-footer__social\", \"brand-shell-footer__social-link\"));\n }\n\n const copy = createParagraph(\"brand-shell-footer__copy\", `© ${new Date().getFullYear()} ${details.name}`);\n\n inner.append(top, copy);\n footer.append(inner);\n return footer;\n}\n\nfunction createNav(\n links: ShellNavLink[],\n blockClass: \"brand-shell-header\" | \"brand-shell-footer\",\n ariaLabel: string,\n linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement,\n): HTMLElement {\n const nav = document.createElement(\"nav\");\n nav.className = `${blockClass}__nav`;\n nav.setAttribute(\"aria-label\", ariaLabel);\n\n const list = document.createElement(\"ul\");\n list.className = `${blockClass}__list`;\n\n for (const link of links) {\n const item = document.createElement(\"li\");\n const anchor = createAnchor(link.href, `${blockClass}__link`, link.label, link.ariaLabel, link.target, link.rel, linkFactory);\n item.append(anchor);\n list.append(item);\n }\n\n nav.append(list);\n return nav;\n}\n\nfunction createCtas(\n actions: ShellActionLink[],\n containerClass: string,\n linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement,\n): HTMLElement {\n const container = document.createElement(\"div\");\n container.className = containerClass;\n\n actions.forEach((action) => {\n const anchor = createAnchor(\n action.href,\n joinClassNames(\"brand-shell-button\", `brand-shell-button--${action.variant}`),\n action.label,\n action.ariaLabel,\n action.target,\n action.rel,\n linkFactory,\n );\n container.append(anchor);\n });\n\n return container;\n}\n\nfunction createSocialLinks(\n links: SocialLink[],\n containerClass: string,\n linkClass: string,\n): HTMLElement {\n const container = document.createElement(\"div\");\n container.className = containerClass;\n container.setAttribute(\"aria-label\", \"Social links\");\n\n for (const link of links) {\n const anchor = createAnchor(link.href, linkClass, \"\");\n anchor.setAttribute(\"aria-label\", link.label);\n if (!link.href.startsWith(\"mailto:\")) {\n anchor.target = \"_blank\";\n anchor.rel = \"noopener noreferrer\";\n }\n\n const icon = createSocialIcon(link.platform, link.iconSvg);\n if (icon) {\n anchor.append(icon);\n } else {\n anchor.append(createSpan(\"\", link.label[0] ?? \"?\"));\n }\n\n container.append(anchor);\n }\n\n return container;\n}\n\nfunction createSocialIcon(platform: SocialPlatform | string, iconSvg?: string): Element | null {\n switch (platform) {\n case \"github\":\n return createFilledIcon(\n \"M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z\",\n );\n case \"twitter\":\n return createFilledIcon(\"M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z\");\n case \"linkedin\":\n return createFilledIcon(\n \"M20.447 20.452h-3.554v-5.569c0-1.328-.027-3.037-1.852-3.037-1.853 0-2.136 1.445-2.136 2.939v5.667H9.351V9h3.414v1.561h.046c.477-.9 1.637-1.85 3.37-1.85 3.601 0 4.267 2.37 4.267 5.455v6.286zM5.337 7.433c-1.144 0-2.063-.926-2.063-2.065 0-1.138.92-2.063 2.063-2.063 1.14 0 2.064.925 2.064 2.063 0 1.139-.925 2.065-2.064 2.065zm1.782 13.019H3.555V9h3.564v11.452zM22.225 0H1.771C.792 0 0 .774 0 1.729v20.542C0 23.227.792 24 1.771 24h20.451C23.2 24 24 23.227 24 22.271V1.729C24 .774 23.2 0 22.222 0h.003z\",\n );\n case \"discord\":\n return createFilledIcon(\n \"M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028 14.09 14.09 0 0 0 1.226-1.994.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.096 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z\",\n );\n case \"email\":\n return createStrokedIcon([\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\"], { rx: \"2\" });\n case \"website\":\n return createGlobeIcon();\n default:\n if (iconSvg) {\n const span = document.createElement(\"span\");\n span.setAttribute(\"aria-hidden\", \"true\");\n span.innerHTML = iconSvg;\n return span;\n }\n return null;\n }\n}\n\nfunction createFilledIcon(pathData: string): SVGSVGElement {\n const svg = createBaseSvg();\n svg.setAttribute(\"fill\", \"currentColor\");\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", pathData);\n svg.append(path);\n return svg;\n}\n\nfunction createStrokedIcon(pathData: string[], rectAttributes?: Record<string, string>): SVGSVGElement {\n const svg = createBaseSvg();\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"2\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n if (rectAttributes) {\n const rect = document.createElementNS(SVG_NS, \"rect\");\n rect.setAttribute(\"width\", \"20\");\n rect.setAttribute(\"height\", \"16\");\n rect.setAttribute(\"x\", \"2\");\n rect.setAttribute(\"y\", \"4\");\n for (const [attribute, value] of Object.entries(rectAttributes)) {\n rect.setAttribute(attribute, value);\n }\n svg.append(rect);\n }\n\n for (const d of pathData) {\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", d);\n svg.append(path);\n }\n\n return svg;\n}\n\nfunction createGlobeIcon(): SVGSVGElement {\n const svg = createBaseSvg();\n svg.setAttribute(\"fill\", \"none\");\n svg.setAttribute(\"stroke\", \"currentColor\");\n svg.setAttribute(\"stroke-width\", \"2\");\n svg.setAttribute(\"stroke-linecap\", \"round\");\n svg.setAttribute(\"stroke-linejoin\", \"round\");\n\n const circle = document.createElementNS(SVG_NS, \"circle\");\n circle.setAttribute(\"cx\", \"12\");\n circle.setAttribute(\"cy\", \"12\");\n circle.setAttribute(\"r\", \"10\");\n svg.append(circle);\n\n for (const d of [\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\", \"M2 12h20\"]) {\n const path = document.createElementNS(SVG_NS, \"path\");\n path.setAttribute(\"d\", d);\n svg.append(path);\n }\n\n return svg;\n}\n\nfunction createBaseSvg(): SVGSVGElement {\n const svg = document.createElementNS(SVG_NS, \"svg\");\n svg.setAttribute(\"viewBox\", \"0 0 24 24\");\n svg.setAttribute(\"width\", \"1em\");\n svg.setAttribute(\"height\", \"1em\");\n svg.setAttribute(\"aria-hidden\", \"true\");\n return svg;\n}\n\nfunction applyThemeVariables(element: HTMLElement, theme: BrandTheme | null) {\n const style = themeToCssVariables(theme);\n for (const [name, value] of Object.entries(style)) {\n element.style.setProperty(name, value);\n }\n}\n\nfunction resolveCtaLayout(theme: BrandTheme | null): \"inline\" | \"stacked\" {\n return theme?.ctaLayout === \"stacked\" ? \"stacked\" : \"inline\";\n}\n\nfunction joinClassNames(...classNames: Array<string | null | undefined>) {\n return classNames.filter(Boolean).join(\" \");\n}\n\nfunction createAnchor(\n href: string,\n className: string,\n text: string,\n ariaLabel?: string,\n target?: string,\n rel?: string,\n linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement,\n): HTMLAnchorElement {\n if (linkFactory) {\n const anchor = linkFactory({\n href,\n className,\n ariaLabel: ariaLabel ?? text,\n target: target ?? \"_self\",\n rel,\n });\n anchor.textContent = text;\n return anchor;\n }\n\n const anchor = document.createElement(\"a\");\n anchor.href = href;\n anchor.className = className;\n anchor.textContent = text;\n if (ariaLabel) anchor.setAttribute(\"aria-label\", ariaLabel);\n if (target) anchor.target = target;\n if (rel) anchor.rel = rel;\n return anchor;\n}\n\nfunction createParagraph(className: string, text: string): HTMLParagraphElement {\n const paragraph = document.createElement(\"p\");\n paragraph.className = className;\n paragraph.textContent = text;\n return paragraph;\n}\n\nfunction createSpan(className: string, text: string): HTMLSpanElement {\n const span = document.createElement(\"span\");\n span.className = className;\n span.textContent = text;\n return span;\n}\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"brand-header\": BrandHeaderElement;\n \"brand-footer\": BrandFooterElement;\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "brand-shell",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Reusable Header and Footer components with typed details and theme. Premium default UX, works in React, Vite, Next.js.",
|
|
5
5
|
"homepage": "https://github.com/venwork-dev/brand-shell#readme",
|
|
6
6
|
"repository": {
|
|
@@ -11,8 +11,6 @@
|
|
|
11
11
|
"url": "https://github.com/venwork-dev/brand-shell/issues"
|
|
12
12
|
},
|
|
13
13
|
"type": "module",
|
|
14
|
-
"main": "./dist/index.mjs",
|
|
15
|
-
"module": "./dist/index.mjs",
|
|
16
14
|
"types": "./dist/index.d.mts",
|
|
17
15
|
"exports": {
|
|
18
16
|
".": {
|
|
@@ -28,6 +26,7 @@
|
|
|
28
26
|
"types": "./dist/vue.d.mts"
|
|
29
27
|
},
|
|
30
28
|
"./svelte": {
|
|
29
|
+
"svelte": "./src/svelte/index.svelte.ts",
|
|
31
30
|
"import": "./dist/svelte.mjs",
|
|
32
31
|
"types": "./dist/svelte.d.mts"
|
|
33
32
|
},
|
|
@@ -37,7 +36,10 @@
|
|
|
37
36
|
"./dist/default.css": "./dist/default.css"
|
|
38
37
|
},
|
|
39
38
|
"files": [
|
|
40
|
-
"dist"
|
|
39
|
+
"dist",
|
|
40
|
+
"src/svelte/BrandHeader.svelte",
|
|
41
|
+
"src/svelte/BrandFooter.svelte",
|
|
42
|
+
"src/svelte/index.svelte.ts"
|
|
41
43
|
],
|
|
42
44
|
"scripts": {
|
|
43
45
|
"prepare": "bun run build",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { registerBrandShellElements, applyBrandShellProps } from 'brand-shell/web';
|
|
3
|
+
import type { BrandDetails, BrandTheme } from 'brand-shell';
|
|
4
|
+
import type { LinkFactoryOptions } from 'brand-shell/web';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
details: BrandDetails;
|
|
8
|
+
theme?: BrandTheme | null;
|
|
9
|
+
shellClass?: string | null;
|
|
10
|
+
linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { details, theme = null, shellClass = null, linkFactory }: Props = $props();
|
|
14
|
+
|
|
15
|
+
let element: HTMLElement | undefined = $state();
|
|
16
|
+
|
|
17
|
+
$effect(() => {
|
|
18
|
+
if (!element) return;
|
|
19
|
+
registerBrandShellElements();
|
|
20
|
+
applyBrandShellProps(element as any, { details, theme, shellClass, linkFactory });
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<brand-footer bind:this={element}></brand-footer>
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { registerBrandShellElements, applyBrandShellProps } from 'brand-shell/web';
|
|
3
|
+
import type { BrandDetails, BrandTheme } from 'brand-shell';
|
|
4
|
+
import type { LinkFactoryOptions } from 'brand-shell/web';
|
|
5
|
+
|
|
6
|
+
interface Props {
|
|
7
|
+
details: BrandDetails;
|
|
8
|
+
theme?: BrandTheme | null;
|
|
9
|
+
shellClass?: string | null;
|
|
10
|
+
linkFactory?: (options: LinkFactoryOptions) => HTMLAnchorElement;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let { details, theme = null, shellClass = null, linkFactory }: Props = $props();
|
|
14
|
+
|
|
15
|
+
let element: HTMLElement | undefined = $state();
|
|
16
|
+
|
|
17
|
+
$effect(() => {
|
|
18
|
+
if (!element) return;
|
|
19
|
+
registerBrandShellElements();
|
|
20
|
+
applyBrandShellProps(element as any, { details, theme, shellClass, linkFactory });
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<brand-header bind:this={element}></brand-header>
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Svelte condition entry point — exports .svelte components for SvelteKit / vite-plugin-svelte.
|
|
2
|
+
// The brandShell action and types remain available via the "import" condition (dist/svelte.mjs).
|
|
3
|
+
export { default as BrandHeader } from './BrandHeader.svelte';
|
|
4
|
+
export { default as BrandFooter } from './BrandFooter.svelte';
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
//#region src/core/types.d.ts
|
|
2
|
-
/**
|
|
3
|
-
* Schema for header/footer content. Caller passes these; package does not store them.
|
|
4
|
-
*/
|
|
5
|
-
interface BrandNavLink {
|
|
6
|
-
/** Visible label (e.g. Blog, Docs, About) */
|
|
7
|
-
label: string;
|
|
8
|
-
/** Destination URL or path */
|
|
9
|
-
href: string;
|
|
10
|
-
/** Optional custom aria-label for accessibility */
|
|
11
|
-
ariaLabel?: string;
|
|
12
|
-
/** Optional target attribute (defaults to _self) */
|
|
13
|
-
target?: "_blank" | "_self" | "_parent" | "_top";
|
|
14
|
-
/** Optional rel attribute (e.g. noopener) */
|
|
15
|
-
rel?: string;
|
|
16
|
-
}
|
|
17
|
-
interface BrandAction {
|
|
18
|
-
/** Visible label on the CTA button */
|
|
19
|
-
label: string;
|
|
20
|
-
/** URL the CTA points to */
|
|
21
|
-
href: string;
|
|
22
|
-
/** Optional aria-label override */
|
|
23
|
-
ariaLabel?: string;
|
|
24
|
-
/** Optional target attribute */
|
|
25
|
-
target?: "_blank" | "_self" | "_parent" | "_top";
|
|
26
|
-
/** Optional rel attribute */
|
|
27
|
-
rel?: string;
|
|
28
|
-
/** Style variant hint */
|
|
29
|
-
variant?: "primary" | "secondary" | "ghost";
|
|
30
|
-
}
|
|
31
|
-
interface BrandDetails {
|
|
32
|
-
/** Display name (e.g. in header and footer) */
|
|
33
|
-
name: string;
|
|
34
|
-
/** Optional home URL (header name links here when set) */
|
|
35
|
-
homeHref?: string;
|
|
36
|
-
/** Primary nav links shown in the header/footer text nav */
|
|
37
|
-
navLinks?: BrandNavLink[];
|
|
38
|
-
/** Optional highlighted CTA button */
|
|
39
|
-
primaryAction?: BrandAction;
|
|
40
|
-
/** Optional secondary CTA button */
|
|
41
|
-
secondaryAction?: BrandAction;
|
|
42
|
-
/** LinkedIn profile URL */
|
|
43
|
-
linkedin?: string;
|
|
44
|
-
/** Email address (e.g. mailto: or plain) */
|
|
45
|
-
gmail?: string;
|
|
46
|
-
/** GitHub profile URL */
|
|
47
|
-
github?: string;
|
|
48
|
-
/** Twitter/X profile URL */
|
|
49
|
-
twitter?: string;
|
|
50
|
-
/** Discord community or profile URL */
|
|
51
|
-
discord?: string;
|
|
52
|
-
/** Personal or site website URL */
|
|
53
|
-
website?: string;
|
|
54
|
-
/** Optional tagline (e.g. in footer) */
|
|
55
|
-
tagline?: string;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Optional theme to adapt branding without custom CSS.
|
|
59
|
-
* Applied as CSS custom properties on the component root.
|
|
60
|
-
*/
|
|
61
|
-
interface BrandTheme {
|
|
62
|
-
/** Accent/link hover and active state color */
|
|
63
|
-
primaryColor?: string;
|
|
64
|
-
/** Header/footer background color */
|
|
65
|
-
backgroundColor?: string;
|
|
66
|
-
/** Main text color (name, nav labels) */
|
|
67
|
-
textColor?: string;
|
|
68
|
-
/** Font stack for header/footer */
|
|
69
|
-
fontFamily?: string;
|
|
70
|
-
/** Link default color (defaults from primaryColor if omitted) */
|
|
71
|
-
linkColor?: string;
|
|
72
|
-
/** Size for social icon buttons (e.g. 2rem, 32px) */
|
|
73
|
-
socialIconSize?: string;
|
|
74
|
-
/** Optional override for primary CTA text color */
|
|
75
|
-
buttonTextColor?: string;
|
|
76
|
-
/** Mobile CTA arrangement: side-by-side (`inline`) or one-per-row (`stacked`) */
|
|
77
|
-
ctaLayout?: "inline" | "stacked";
|
|
78
|
-
}
|
|
79
|
-
//#endregion
|
|
80
|
-
export { BrandTheme as i, BrandDetails as n, BrandNavLink as r, BrandAction as t };
|
|
81
|
-
//# sourceMappingURL=types-PQziYg7Z.d.mts.map
|