brand-shell 0.16.0 → 0.17.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 +2 -1
- package/dist/default.css +25 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +10 -11
- package/dist/index.mjs.map +1 -1
- package/dist/svelte.d.mts +1 -1
- package/dist/svelte.mjs +1 -1
- package/dist/{validation-BhhgC3n1.mjs → validation-BOH3j-R6.mjs} +2 -1
- package/dist/validation-BOH3j-R6.mjs.map +1 -0
- package/dist/{validation-D1q4yKZZ.d.mts → validation-DRG5UAhg.d.mts} +3 -1
- package/dist/validation-DRG5UAhg.d.mts.map +1 -0
- package/dist/vue.d.mts +1 -1
- package/dist/vue.mjs +1 -1
- package/dist/web.d.mts +1 -1
- package/dist/web.d.mts.map +1 -1
- package/dist/web.mjs +7 -2
- package/dist/web.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/validation-BhhgC3n1.mjs.map +0 -1
- package/dist/validation-D1q4yKZZ.d.mts.map +0 -1
|
@@ -85,7 +85,8 @@
|
|
|
85
85
|
"items": { "$ref": "#/$defs/CustomSocialLink" }
|
|
86
86
|
},
|
|
87
87
|
"logoSrc": { "type": "string", "minLength": 1 },
|
|
88
|
-
"logoAlt": { "type": "string", "minLength": 1 }
|
|
88
|
+
"logoAlt": { "type": "string", "minLength": 1 },
|
|
89
|
+
"copyrightText": { "type": "string", "minLength": 1 }
|
|
89
90
|
}
|
|
90
91
|
},
|
|
91
92
|
"BrandTheme": {
|
package/dist/default.css
CHANGED
|
@@ -19,6 +19,31 @@
|
|
|
19
19
|
--brand-button-secondary: rgba(255, 255, 255, 0.12);
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
/* Skip navigation link — visually hidden until focused */
|
|
23
|
+
.brand-shell-skip-nav {
|
|
24
|
+
position: absolute;
|
|
25
|
+
top: 0;
|
|
26
|
+
left: 0;
|
|
27
|
+
z-index: 9999;
|
|
28
|
+
padding: 0.6rem 1.2rem;
|
|
29
|
+
background: var(--_bg, var(--brand-bg));
|
|
30
|
+
color: var(--_text, var(--brand-text));
|
|
31
|
+
font-family: var(--_font, var(--brand-font));
|
|
32
|
+
font-size: 0.875rem;
|
|
33
|
+
font-weight: 600;
|
|
34
|
+
text-decoration: none;
|
|
35
|
+
border-radius: var(--brand-radius);
|
|
36
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
|
|
37
|
+
transform: translateY(-150%);
|
|
38
|
+
transition: transform 0.15s ease;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.brand-shell-skip-nav:focus-visible {
|
|
42
|
+
transform: translateY(0);
|
|
43
|
+
outline: 2px solid var(--_primary, var(--brand-primary));
|
|
44
|
+
outline-offset: 2px;
|
|
45
|
+
}
|
|
46
|
+
|
|
22
47
|
.brand-shell-header,
|
|
23
48
|
.brand-shell-header *,
|
|
24
49
|
.brand-shell-header *::before,
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as BrandAction, D as CustomSocialLink, E as BrandTheme, S as detailsToSocialLinks, T as BrandNavLink, _ as normalizeCtaLinks, a as formatValidationErrors, b as SocialLink, c as validateBrandTheme, d as ShellActionLink, f as ShellNavLink, g as normalizeBrandDetails, h as buildShellViewModelFromNormalized, i as assertValidBrandTheme, l as LinkTarget, m as buildShellViewModel, n as BrandValidationResult, o as normalizeBrandTheme, p as ShellViewModel, r as assertValidBrandDetails, s as validateBrandDetails, t as BrandShellValidationError, u as NormalizedBrandDetails, v as normalizeEmailHref, w as BrandDetails, x as SocialPlatform, y as normalizeNavLinks } from "./validation-
|
|
1
|
+
import { C as BrandAction, D as CustomSocialLink, E as BrandTheme, S as detailsToSocialLinks, T as BrandNavLink, _ as normalizeCtaLinks, a as formatValidationErrors, b as SocialLink, c as validateBrandTheme, d as ShellActionLink, f as ShellNavLink, g as normalizeBrandDetails, h as buildShellViewModelFromNormalized, i as assertValidBrandTheme, l as LinkTarget, m as buildShellViewModel, n as BrandValidationResult, o as normalizeBrandTheme, p as ShellViewModel, r as assertValidBrandDetails, s as validateBrandDetails, t as BrandShellValidationError, u as NormalizedBrandDetails, v as normalizeEmailHref, w as BrandDetails, x as SocialPlatform, y as normalizeNavLinks } from "./validation-DRG5UAhg.mjs";
|
|
2
2
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
3
|
import { ReactElement, ReactNode } from "react";
|
|
4
4
|
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as normalizeBrandTheme, c as themeToCssVariables, d as buildShellViewModelFromNormalized, f as normalizeBrandDetails, g as detailsToSocialLinks, h as normalizeNavLinks, i as formatValidationErrors, l as shouldValidateInDev, m as normalizeEmailHref, n as assertValidBrandDetails, o as validateBrandDetails, p as normalizeCtaLinks, r as assertValidBrandTheme, s as validateBrandTheme, t as BrandShellValidationError, u as buildShellViewModel } from "./validation-
|
|
1
|
+
import { a as normalizeBrandTheme, c as themeToCssVariables, d as buildShellViewModelFromNormalized, f as normalizeBrandDetails, g as detailsToSocialLinks, h as normalizeNavLinks, i as formatValidationErrors, l as shouldValidateInDev, m as normalizeEmailHref, n as assertValidBrandDetails, o as validateBrandDetails, p as normalizeCtaLinks, r as assertValidBrandTheme, s as validateBrandTheme, t as BrandShellValidationError, u as buildShellViewModel } from "./validation-BOH3j-R6.mjs";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
3
|
|
|
4
4
|
//#region src/react/theme.ts
|
|
@@ -133,12 +133,16 @@ function Header({ details, theme, className, renderLink }) {
|
|
|
133
133
|
className: "brand-shell-header__name",
|
|
134
134
|
children: logoContent
|
|
135
135
|
});
|
|
136
|
-
return /* @__PURE__ */
|
|
136
|
+
return /* @__PURE__ */ jsxs("header", {
|
|
137
137
|
className: combinedClassName,
|
|
138
138
|
"data-brand-cta-layout": ctaLayout,
|
|
139
139
|
style,
|
|
140
140
|
role: "banner",
|
|
141
|
-
children: /* @__PURE__ */
|
|
141
|
+
children: [/* @__PURE__ */ jsx("a", {
|
|
142
|
+
href: "#main-content",
|
|
143
|
+
className: "brand-shell-skip-nav",
|
|
144
|
+
children: "Skip to main content"
|
|
145
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
142
146
|
className: "brand-shell-header__inner",
|
|
143
147
|
children: [brandIdentity, /* @__PURE__ */ jsxs("div", {
|
|
144
148
|
className: "brand-shell-header__actions",
|
|
@@ -194,7 +198,7 @@ function Header({ details, theme, className, renderLink }) {
|
|
|
194
198
|
})
|
|
195
199
|
]
|
|
196
200
|
})]
|
|
197
|
-
})
|
|
201
|
+
})]
|
|
198
202
|
});
|
|
199
203
|
}
|
|
200
204
|
const SOCIAL_ICON_COMPONENTS$1 = {
|
|
@@ -311,14 +315,9 @@ function Footer({ details, theme, className, renderLink }) {
|
|
|
311
315
|
})
|
|
312
316
|
})
|
|
313
317
|
]
|
|
314
|
-
}), /* @__PURE__ */
|
|
318
|
+
}), /* @__PURE__ */ jsx("p", {
|
|
315
319
|
className: "brand-shell-footer__copy",
|
|
316
|
-
children:
|
|
317
|
-
"© ",
|
|
318
|
-
(/* @__PURE__ */ new Date()).getFullYear(),
|
|
319
|
-
" ",
|
|
320
|
-
normalizedDetails.name
|
|
321
|
-
]
|
|
320
|
+
children: normalizedDetails.copyrightText ?? `\u00a9 ${(/* @__PURE__ */ new Date()).getFullYear()} ${normalizedDetails.name}`
|
|
322
321
|
})]
|
|
323
322
|
})
|
|
324
323
|
});
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["SOCIAL_ICON_COMPONENTS"],"sources":["../src/react/theme.ts","../src/icons.tsx","../src/Header.tsx","../src/Footer.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport type { BrandTheme } from \"../core/types\";\nimport { themeToCssVariables } from \"../core/theme\";\n\nexport function themeToStyle(theme?: BrandTheme | null): CSSProperties {\n return themeToCssVariables(theme) as CSSProperties;\n}\n","/**\n * Social Media Icons\n *\n * Brand icons from lucide-react are deprecated and will be removed in v1.0.\n * This file provides reusable icon components using Simple Icons SVG paths.\n * See: https://github.com/lucide-icons/lucide/issues/670\n */\n\nimport type { SVGProps } from \"react\";\n\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n className?: string;\n \"aria-label\"?: string;\n}\n\nexport function GithubIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function TwitterIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function LinkedinIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function DiscordIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function MailIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n width={width}\n height={height}\n {...props}\n >\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n );\n}\n\nexport function GlobeIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n width={width}\n height={height}\n {...props}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n","import type { ReactElement, ReactNode } from \"react\";\nimport type { BrandDetails, BrandTheme } from \"./types\";\nimport {\n assertValidBrandDetails,\n assertValidBrandTheme,\n buildShellViewModelFromNormalized,\n normalizeBrandDetails,\n normalizeBrandTheme,\n shouldValidateInDev,\n} from \"./core\";\nimport type { SocialPlatform } from \"./core\";\nimport type { IconProps } from \"./icons\";\nimport { themeToStyle } from \"./react/theme\";\nimport {\n DiscordIcon,\n GithubIcon,\n GlobeIcon,\n LinkedinIcon,\n MailIcon,\n TwitterIcon,\n} from \"./icons\";\n\nexport interface LinkRenderProps {\n href: string;\n className: string;\n \"aria-label\": string;\n target: string;\n rel?: string;\n children: ReactNode;\n}\n\nexport interface HeaderProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n className?: string;\n renderLink?: (props: LinkRenderProps) => ReactElement;\n}\n\nexport function Header({ details, theme, className, renderLink }: HeaderProps) {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(details, \"brand-shell/Header details\");\n assertValidBrandTheme(theme, \"brand-shell/Header theme\");\n }\n\n const normalizedDetails = normalizeBrandDetails(details);\n const normalizedTheme = normalizeBrandTheme(theme);\n const ctaLayout = normalizedTheme?.ctaLayout === \"stacked\" ? \"stacked\" : \"inline\";\n const style = themeToStyle(normalizedTheme);\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModelFromNormalized(normalizedDetails);\n const combinedClassName = [\"brand-shell-header\", className].filter(Boolean).join(\" \");\n\n const LinkEl = renderLink\n ? renderLink\n : ({ href, className: cls, \"aria-label\": ariaLabel, target, rel, children }: LinkRenderProps) => (\n <a href={href} className={cls} aria-label={ariaLabel} target={target} rel={rel}>{children}</a>\n );\n\n const logoContent = normalizedDetails.logoSrc ? (\n <img\n src={normalizedDetails.logoSrc}\n alt={normalizedDetails.logoAlt ?? normalizedDetails.name}\n className=\"brand-shell-header__logo\"\n />\n ) : (\n normalizedDetails.name\n );\n\n const brandIdentity = normalizedDetails.homeHref ? (\n <LinkEl\n href={normalizedDetails.homeHref}\n className=\"brand-shell-header__name\"\n aria-label={`${normalizedDetails.name} home`}\n target=\"_self\"\n >\n {logoContent}\n </LinkEl>\n ) : (\n <span className=\"brand-shell-header__name\">{logoContent}</span>\n );\n\n return (\n <header className={combinedClassName} data-brand-cta-layout={ctaLayout} style={style} role=\"banner\">\n <div className=\"brand-shell-header__inner\">\n {brandIdentity}\n <div className=\"brand-shell-header__actions\">\n {navLinks.length > 0 && (\n <nav className=\"brand-shell-header__nav\" aria-label=\"Primary\">\n <ul className=\"brand-shell-header__list\">\n {navLinks.map((link) => {\n return (\n <li key={link.href + link.label}>\n <LinkEl\n href={link.href}\n className=\"brand-shell-header__link\"\n aria-label={link.ariaLabel}\n target={link.target}\n rel={link.rel}\n >\n {link.label}\n </LinkEl>\n </li>\n );\n })}\n </ul>\n </nav>\n )}\n {ctaLinks.length > 0 && (\n <div className=\"brand-shell-header__ctas\">\n {ctaLinks.map((action) => (\n <LinkEl\n key={action.href + action.label}\n href={action.href}\n className={[\"brand-shell-button\", `brand-shell-button--${action.variant}`].join(\" \")}\n aria-label={action.ariaLabel}\n target={action.target}\n rel={action.rel}\n >\n {action.label}\n </LinkEl>\n ))}\n </div>\n )}\n {socialLinks.length > 0 && (\n <div className=\"brand-shell-header__social\" aria-label=\"Social links\">\n {socialLinks.map((link) => {\n const Icon = SOCIAL_ICON_COMPONENTS[link.platform as SocialPlatform];\n const isMailto = link.href.startsWith(\"mailto:\");\n return (\n <a\n key={link.href + link.platform}\n href={link.href}\n className=\"brand-shell-header__social-link\"\n aria-label={link.label}\n {...(!isMailto && { target: \"_blank\", rel: \"noopener noreferrer\" })}\n >\n {Icon ? (\n <Icon aria-hidden=\"true\" />\n ) : link.iconSvg ? (\n <span dangerouslySetInnerHTML={{ __html: link.iconSvg }} aria-hidden=\"true\" />\n ) : (\n <span>{link.label[0]}</span>\n )}\n </a>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </header>\n );\n}\n\nconst SOCIAL_ICON_COMPONENTS: Record<SocialPlatform, (props: IconProps) => JSX.Element> = {\n website: GlobeIcon,\n linkedin: LinkedinIcon,\n email: MailIcon,\n github: GithubIcon,\n twitter: TwitterIcon,\n discord: DiscordIcon,\n};\n","import type { ReactElement } from \"react\";\nimport type { BrandDetails, BrandTheme } from \"./types\";\nimport {\n assertValidBrandDetails,\n assertValidBrandTheme,\n buildShellViewModelFromNormalized,\n normalizeBrandDetails,\n normalizeBrandTheme,\n shouldValidateInDev,\n} from \"./core\";\nimport type { SocialPlatform } from \"./core\";\nimport type { IconProps } from \"./icons\";\nimport { themeToStyle } from \"./react/theme\";\nimport {\n DiscordIcon,\n GithubIcon,\n GlobeIcon,\n LinkedinIcon,\n MailIcon,\n TwitterIcon,\n} from \"./icons\";\n\nimport type { LinkRenderProps } from \"./Header\";\n\nexport interface FooterProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n className?: string;\n renderLink?: (props: LinkRenderProps) => ReactElement;\n}\n\nexport function Footer({ details, theme, className, renderLink }: FooterProps) {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(details, \"brand-shell/Footer details\");\n assertValidBrandTheme(theme, \"brand-shell/Footer theme\");\n }\n\n const normalizedDetails = normalizeBrandDetails(details);\n const normalizedTheme = normalizeBrandTheme(theme);\n const ctaLayout = normalizedTheme?.ctaLayout === \"stacked\" ? \"stacked\" : \"inline\";\n const style = themeToStyle(normalizedTheme);\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModelFromNormalized(normalizedDetails);\n const combinedClassName = [\"brand-shell-footer\", className].filter(Boolean).join(\" \");\n\n const LinkEl = renderLink\n ? renderLink\n : ({ href, className: cls, \"aria-label\": ariaLabel, target, rel, children }: LinkRenderProps) => (\n <a href={href} className={cls} aria-label={ariaLabel} target={target} rel={rel}>{children}</a>\n );\n\n return (\n <footer className={combinedClassName} data-brand-cta-layout={ctaLayout} style={style} role=\"contentinfo\">\n <div className=\"brand-shell-footer__inner\">\n <div className=\"brand-shell-footer__top\">\n <div className=\"brand-shell-footer__brand\">\n {(() => {\n const logoContent = normalizedDetails.logoSrc ? (\n <img\n src={normalizedDetails.logoSrc}\n alt={normalizedDetails.logoAlt ?? normalizedDetails.name}\n className=\"brand-shell-footer__logo\"\n />\n ) : null;\n\n if (normalizedDetails.homeHref) {\n return (\n <LinkEl\n href={normalizedDetails.homeHref}\n className=\"brand-shell-footer__name\"\n aria-label={`${normalizedDetails.name} home`}\n target=\"_self\"\n >\n {logoContent ?? normalizedDetails.name}\n </LinkEl>\n );\n }\n\n return logoContent\n ? logoContent\n : <p className=\"brand-shell-footer__name\">{normalizedDetails.name}</p>;\n })()}\n {normalizedDetails.tagline && <p className=\"brand-shell-footer__tagline\">{normalizedDetails.tagline}</p>}\n </div>\n {navLinks.length > 0 && (\n <nav className=\"brand-shell-footer__nav\" aria-label=\"Footer\">\n <ul className=\"brand-shell-footer__list\">\n {navLinks.map((link) => {\n return (\n <li key={link.href + link.label}>\n <LinkEl\n href={link.href}\n className=\"brand-shell-footer__link\"\n aria-label={link.ariaLabel}\n target={link.target}\n rel={link.rel}\n >\n {link.label}\n </LinkEl>\n </li>\n );\n })}\n </ul>\n </nav>\n )}\n {ctaLinks.length > 0 && (\n <div className=\"brand-shell-footer__ctas\">\n {ctaLinks.map((action) => (\n <LinkEl\n key={action.href + action.label}\n href={action.href}\n className={[\"brand-shell-button\", `brand-shell-button--${action.variant}`].join(\" \")}\n aria-label={action.ariaLabel}\n target={action.target}\n rel={action.rel}\n >\n {action.label}\n </LinkEl>\n ))}\n </div>\n )}\n {socialLinks.length > 0 && (\n <div className=\"brand-shell-footer__social\" aria-label=\"Social links\">\n {socialLinks.map((link) => {\n const Icon = SOCIAL_ICON_COMPONENTS[link.platform as SocialPlatform];\n const isMailto = link.href.startsWith(\"mailto:\");\n return (\n <a\n key={link.href + link.platform}\n href={link.href}\n className=\"brand-shell-footer__social-link\"\n aria-label={link.label}\n {...(!isMailto && { target: \"_blank\", rel: \"noopener noreferrer\" })}\n >\n {Icon ? (\n <Icon aria-hidden=\"true\" />\n ) : link.iconSvg ? (\n <span dangerouslySetInnerHTML={{ __html: link.iconSvg }} aria-hidden=\"true\" />\n ) : (\n <span>{link.label[0]}</span>\n )}\n </a>\n );\n })}\n </div>\n )}\n </div>\n <p className=\"brand-shell-footer__copy\">© {new Date().getFullYear()} {normalizedDetails.name}</p>\n </div>\n </footer>\n );\n}\n\nconst SOCIAL_ICON_COMPONENTS: Record<SocialPlatform, (props: IconProps) => JSX.Element> = {\n website: GlobeIcon,\n linkedin: LinkedinIcon,\n email: MailIcon,\n github: GithubIcon,\n twitter: TwitterIcon,\n discord: DiscordIcon,\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["SOCIAL_ICON_COMPONENTS"],"sources":["../src/react/theme.ts","../src/icons.tsx","../src/Header.tsx","../src/Footer.tsx"],"sourcesContent":["import type { CSSProperties } from \"react\";\nimport type { BrandTheme } from \"../core/types\";\nimport { themeToCssVariables } from \"../core/theme\";\n\nexport function themeToStyle(theme?: BrandTheme | null): CSSProperties {\n return themeToCssVariables(theme) as CSSProperties;\n}\n","/**\n * Social Media Icons\n *\n * Brand icons from lucide-react are deprecated and will be removed in v1.0.\n * This file provides reusable icon components using Simple Icons SVG paths.\n * See: https://github.com/lucide-icons/lucide/issues/670\n */\n\nimport type { SVGProps } from \"react\";\n\nexport interface IconProps extends SVGProps<SVGSVGElement> {\n className?: string;\n \"aria-label\"?: string;\n}\n\nexport function GithubIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function TwitterIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function LinkedinIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function DiscordIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg viewBox=\"0 0 24 24\" fill=\"currentColor\" className={className} width={width} height={height} {...props}>\n <path d=\"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 </svg>\n );\n}\n\nexport function MailIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n width={width}\n height={height}\n {...props}\n >\n <rect width=\"20\" height=\"16\" x=\"2\" y=\"4\" rx=\"2\" />\n <path d=\"m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7\" />\n </svg>\n );\n}\n\nexport function GlobeIcon({ className, width = \"1em\", height = \"1em\", ...props }: IconProps) {\n return (\n <svg\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n className={className}\n width={width}\n height={height}\n {...props}\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <path d=\"M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20\" />\n <path d=\"M2 12h20\" />\n </svg>\n );\n}\n","import type { ReactElement, ReactNode } from \"react\";\nimport type { BrandDetails, BrandTheme } from \"./types\";\nimport {\n assertValidBrandDetails,\n assertValidBrandTheme,\n buildShellViewModelFromNormalized,\n normalizeBrandDetails,\n normalizeBrandTheme,\n shouldValidateInDev,\n} from \"./core\";\nimport type { SocialPlatform } from \"./core\";\nimport type { IconProps } from \"./icons\";\nimport { themeToStyle } from \"./react/theme\";\nimport {\n DiscordIcon,\n GithubIcon,\n GlobeIcon,\n LinkedinIcon,\n MailIcon,\n TwitterIcon,\n} from \"./icons\";\n\nexport interface LinkRenderProps {\n href: string;\n className: string;\n \"aria-label\": string;\n target: string;\n rel?: string;\n children: ReactNode;\n}\n\nexport interface HeaderProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n className?: string;\n renderLink?: (props: LinkRenderProps) => ReactElement;\n}\n\nexport function Header({ details, theme, className, renderLink }: HeaderProps) {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(details, \"brand-shell/Header details\");\n assertValidBrandTheme(theme, \"brand-shell/Header theme\");\n }\n\n const normalizedDetails = normalizeBrandDetails(details);\n const normalizedTheme = normalizeBrandTheme(theme);\n const ctaLayout = normalizedTheme?.ctaLayout === \"stacked\" ? \"stacked\" : \"inline\";\n const style = themeToStyle(normalizedTheme);\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModelFromNormalized(normalizedDetails);\n const combinedClassName = [\"brand-shell-header\", className].filter(Boolean).join(\" \");\n\n const LinkEl = renderLink\n ? renderLink\n : ({ href, className: cls, \"aria-label\": ariaLabel, target, rel, children }: LinkRenderProps) => (\n <a href={href} className={cls} aria-label={ariaLabel} target={target} rel={rel}>{children}</a>\n );\n\n const logoContent = normalizedDetails.logoSrc ? (\n <img\n src={normalizedDetails.logoSrc}\n alt={normalizedDetails.logoAlt ?? normalizedDetails.name}\n className=\"brand-shell-header__logo\"\n />\n ) : (\n normalizedDetails.name\n );\n\n const brandIdentity = normalizedDetails.homeHref ? (\n <LinkEl\n href={normalizedDetails.homeHref}\n className=\"brand-shell-header__name\"\n aria-label={`${normalizedDetails.name} home`}\n target=\"_self\"\n >\n {logoContent}\n </LinkEl>\n ) : (\n <span className=\"brand-shell-header__name\">{logoContent}</span>\n );\n\n return (\n <header className={combinedClassName} data-brand-cta-layout={ctaLayout} style={style} role=\"banner\">\n <a href=\"#main-content\" className=\"brand-shell-skip-nav\">Skip to main content</a>\n <div className=\"brand-shell-header__inner\">\n {brandIdentity}\n <div className=\"brand-shell-header__actions\">\n {navLinks.length > 0 && (\n <nav className=\"brand-shell-header__nav\" aria-label=\"Primary\">\n <ul className=\"brand-shell-header__list\">\n {navLinks.map((link) => {\n return (\n <li key={link.href + link.label}>\n <LinkEl\n href={link.href}\n className=\"brand-shell-header__link\"\n aria-label={link.ariaLabel}\n target={link.target}\n rel={link.rel}\n >\n {link.label}\n </LinkEl>\n </li>\n );\n })}\n </ul>\n </nav>\n )}\n {ctaLinks.length > 0 && (\n <div className=\"brand-shell-header__ctas\">\n {ctaLinks.map((action) => (\n <LinkEl\n key={action.href + action.label}\n href={action.href}\n className={[\"brand-shell-button\", `brand-shell-button--${action.variant}`].join(\" \")}\n aria-label={action.ariaLabel}\n target={action.target}\n rel={action.rel}\n >\n {action.label}\n </LinkEl>\n ))}\n </div>\n )}\n {socialLinks.length > 0 && (\n <div className=\"brand-shell-header__social\" aria-label=\"Social links\">\n {socialLinks.map((link) => {\n const Icon = SOCIAL_ICON_COMPONENTS[link.platform as SocialPlatform];\n const isMailto = link.href.startsWith(\"mailto:\");\n return (\n <a\n key={link.href + link.platform}\n href={link.href}\n className=\"brand-shell-header__social-link\"\n aria-label={link.label}\n {...(!isMailto && { target: \"_blank\", rel: \"noopener noreferrer\" })}\n >\n {Icon ? (\n <Icon aria-hidden=\"true\" />\n ) : link.iconSvg ? (\n <span dangerouslySetInnerHTML={{ __html: link.iconSvg }} aria-hidden=\"true\" />\n ) : (\n <span>{link.label[0]}</span>\n )}\n </a>\n );\n })}\n </div>\n )}\n </div>\n </div>\n </header>\n );\n}\n\nconst SOCIAL_ICON_COMPONENTS: Record<SocialPlatform, (props: IconProps) => JSX.Element> = {\n website: GlobeIcon,\n linkedin: LinkedinIcon,\n email: MailIcon,\n github: GithubIcon,\n twitter: TwitterIcon,\n discord: DiscordIcon,\n};\n","import type { ReactElement } from \"react\";\nimport type { BrandDetails, BrandTheme } from \"./types\";\nimport {\n assertValidBrandDetails,\n assertValidBrandTheme,\n buildShellViewModelFromNormalized,\n normalizeBrandDetails,\n normalizeBrandTheme,\n shouldValidateInDev,\n} from \"./core\";\nimport type { SocialPlatform } from \"./core\";\nimport type { IconProps } from \"./icons\";\nimport { themeToStyle } from \"./react/theme\";\nimport {\n DiscordIcon,\n GithubIcon,\n GlobeIcon,\n LinkedinIcon,\n MailIcon,\n TwitterIcon,\n} from \"./icons\";\n\nimport type { LinkRenderProps } from \"./Header\";\n\nexport interface FooterProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n className?: string;\n renderLink?: (props: LinkRenderProps) => ReactElement;\n}\n\nexport function Footer({ details, theme, className, renderLink }: FooterProps) {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(details, \"brand-shell/Footer details\");\n assertValidBrandTheme(theme, \"brand-shell/Footer theme\");\n }\n\n const normalizedDetails = normalizeBrandDetails(details);\n const normalizedTheme = normalizeBrandTheme(theme);\n const ctaLayout = normalizedTheme?.ctaLayout === \"stacked\" ? \"stacked\" : \"inline\";\n const style = themeToStyle(normalizedTheme);\n const { navLinks, ctaLinks, socialLinks } = buildShellViewModelFromNormalized(normalizedDetails);\n const combinedClassName = [\"brand-shell-footer\", className].filter(Boolean).join(\" \");\n\n const LinkEl = renderLink\n ? renderLink\n : ({ href, className: cls, \"aria-label\": ariaLabel, target, rel, children }: LinkRenderProps) => (\n <a href={href} className={cls} aria-label={ariaLabel} target={target} rel={rel}>{children}</a>\n );\n\n return (\n <footer className={combinedClassName} data-brand-cta-layout={ctaLayout} style={style} role=\"contentinfo\">\n <div className=\"brand-shell-footer__inner\">\n <div className=\"brand-shell-footer__top\">\n <div className=\"brand-shell-footer__brand\">\n {(() => {\n const logoContent = normalizedDetails.logoSrc ? (\n <img\n src={normalizedDetails.logoSrc}\n alt={normalizedDetails.logoAlt ?? normalizedDetails.name}\n className=\"brand-shell-footer__logo\"\n />\n ) : null;\n\n if (normalizedDetails.homeHref) {\n return (\n <LinkEl\n href={normalizedDetails.homeHref}\n className=\"brand-shell-footer__name\"\n aria-label={`${normalizedDetails.name} home`}\n target=\"_self\"\n >\n {logoContent ?? normalizedDetails.name}\n </LinkEl>\n );\n }\n\n return logoContent\n ? logoContent\n : <p className=\"brand-shell-footer__name\">{normalizedDetails.name}</p>;\n })()}\n {normalizedDetails.tagline && <p className=\"brand-shell-footer__tagline\">{normalizedDetails.tagline}</p>}\n </div>\n {navLinks.length > 0 && (\n <nav className=\"brand-shell-footer__nav\" aria-label=\"Footer\">\n <ul className=\"brand-shell-footer__list\">\n {navLinks.map((link) => {\n return (\n <li key={link.href + link.label}>\n <LinkEl\n href={link.href}\n className=\"brand-shell-footer__link\"\n aria-label={link.ariaLabel}\n target={link.target}\n rel={link.rel}\n >\n {link.label}\n </LinkEl>\n </li>\n );\n })}\n </ul>\n </nav>\n )}\n {ctaLinks.length > 0 && (\n <div className=\"brand-shell-footer__ctas\">\n {ctaLinks.map((action) => (\n <LinkEl\n key={action.href + action.label}\n href={action.href}\n className={[\"brand-shell-button\", `brand-shell-button--${action.variant}`].join(\" \")}\n aria-label={action.ariaLabel}\n target={action.target}\n rel={action.rel}\n >\n {action.label}\n </LinkEl>\n ))}\n </div>\n )}\n {socialLinks.length > 0 && (\n <div className=\"brand-shell-footer__social\" aria-label=\"Social links\">\n {socialLinks.map((link) => {\n const Icon = SOCIAL_ICON_COMPONENTS[link.platform as SocialPlatform];\n const isMailto = link.href.startsWith(\"mailto:\");\n return (\n <a\n key={link.href + link.platform}\n href={link.href}\n className=\"brand-shell-footer__social-link\"\n aria-label={link.label}\n {...(!isMailto && { target: \"_blank\", rel: \"noopener noreferrer\" })}\n >\n {Icon ? (\n <Icon aria-hidden=\"true\" />\n ) : link.iconSvg ? (\n <span dangerouslySetInnerHTML={{ __html: link.iconSvg }} aria-hidden=\"true\" />\n ) : (\n <span>{link.label[0]}</span>\n )}\n </a>\n );\n })}\n </div>\n )}\n </div>\n <p className=\"brand-shell-footer__copy\">\n {normalizedDetails.copyrightText ?? `\\u00a9 ${new Date().getFullYear()} ${normalizedDetails.name}`}\n </p>\n </div>\n </footer>\n );\n}\n\nconst SOCIAL_ICON_COMPONENTS: Record<SocialPlatform, (props: IconProps) => JSX.Element> = {\n website: GlobeIcon,\n linkedin: LinkedinIcon,\n email: MailIcon,\n github: GithubIcon,\n twitter: TwitterIcon,\n discord: DiscordIcon,\n};\n"],"mappings":";;;;AAIA,SAAgB,aAAa,OAA0C;AACrE,QAAO,oBAAoB,MAAM;;;;;ACUnC,SAAgB,WAAW,EAAE,WAAW,QAAQ,OAAO,SAAS,OAAO,GAAG,SAAoB;AAC5F,QACE,oBAAC;EAAI,SAAQ;EAAY,MAAK;EAA0B;EAAkB;EAAe;EAAQ,GAAI;YACnG,oBAAC,UAAK,GAAE,8sBAA8sB;GACltB;;AAIV,SAAgB,YAAY,EAAE,WAAW,QAAQ,OAAO,SAAS,OAAO,GAAG,SAAoB;AAC7F,QACE,oBAAC;EAAI,SAAQ;EAAY,MAAK;EAA0B;EAAkB;EAAe;EAAQ,GAAI;YACnG,oBAAC,UAAK,GAAE,gKAAgK;GACpK;;AAIV,SAAgB,aAAa,EAAE,WAAW,QAAQ,OAAO,SAAS,OAAO,GAAG,SAAoB;AAC9F,QACE,oBAAC;EAAI,SAAQ;EAAY,MAAK;EAA0B;EAAkB;EAAe;EAAQ,GAAI;YACnG,oBAAC,UAAK,GAAE,ufAAuf;GAC3f;;AAIV,SAAgB,YAAY,EAAE,WAAW,QAAQ,OAAO,SAAS,OAAO,GAAG,SAAoB;AAC7F,QACE,oBAAC;EAAI,SAAQ;EAAY,MAAK;EAA0B;EAAkB;EAAe;EAAQ,GAAI;YACnG,oBAAC,UAAK,GAAE,+jCAA+jC;GACnkC;;AAIV,SAAgB,SAAS,EAAE,WAAW,QAAQ,OAAO,SAAS,OAAO,GAAG,SAAoB;AAC1F,QACE,qBAAC;EACC,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACJ;EACJ;EACC;EACR,GAAI;aAEJ,oBAAC;GAAK,OAAM;GAAK,QAAO;GAAK,GAAE;GAAI,GAAE;GAAI,IAAG;IAAM,EAClD,oBAAC,UAAK,GAAE,8CAA8C;GAClD;;AAIV,SAAgB,UAAU,EAAE,WAAW,QAAQ,OAAO,SAAS,OAAO,GAAG,SAAoB;AAC3F,QACE,qBAAC;EACC,SAAQ;EACR,MAAK;EACL,QAAO;EACP,aAAY;EACZ,eAAc;EACd,gBAAe;EACJ;EACJ;EACC;EACR,GAAI;;GAEJ,oBAAC;IAAO,IAAG;IAAK,IAAG;IAAK,GAAE;KAAO;GACjC,oBAAC,UAAK,GAAE,oDAAoD;GAC5D,oBAAC,UAAK,GAAE,aAAa;;GACjB;;;;;AC9CV,SAAgB,OAAO,EAAE,SAAS,OAAO,WAAW,cAA2B;AAC7E,KAAI,qBAAqB,EAAE;AACzB,0BAAwB,SAAS,6BAA6B;AAC9D,wBAAsB,OAAO,2BAA2B;;CAG1D,MAAM,oBAAoB,sBAAsB,QAAQ;CACxD,MAAM,kBAAkB,oBAAoB,MAAM;CAClD,MAAM,YAAY,iBAAiB,cAAc,YAAY,YAAY;CACzE,MAAM,QAAQ,aAAa,gBAAgB;CAC3C,MAAM,EAAE,UAAU,UAAU,gBAAgB,kCAAkC,kBAAkB;CAChG,MAAM,oBAAoB,CAAC,sBAAsB,UAAU,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;CAErF,MAAM,SAAS,aACX,cACC,EAAE,MAAM,WAAW,KAAK,cAAc,WAAW,QAAQ,KAAK,eAC7D,oBAAC;EAAQ;EAAM,WAAW;EAAK,cAAY;EAAmB;EAAa;EAAM;GAAa;CAGpG,MAAM,cAAc,kBAAkB,UACpC,oBAAC;EACC,KAAK,kBAAkB;EACvB,KAAK,kBAAkB,WAAW,kBAAkB;EACpD,WAAU;GACV,GAEF,kBAAkB;CAGpB,MAAM,gBAAgB,kBAAkB,WACtC,oBAAC;EACC,MAAM,kBAAkB;EACxB,WAAU;EACV,cAAY,GAAG,kBAAkB,KAAK;EACtC,QAAO;YAEN;GACM,GAET,oBAAC;EAAK,WAAU;YAA4B;GAAmB;AAGjE,QACE,qBAAC;EAAO,WAAW;EAAmB,yBAAuB;EAAkB;EAAO,MAAK;aACzF,oBAAC;GAAE,MAAK;GAAgB,WAAU;aAAuB;IAAwB,EACjF,qBAAC;GAAI,WAAU;cACZ,eACD,qBAAC;IAAI,WAAU;;KACZ,SAAS,SAAS,KACjB,oBAAC;MAAI,WAAU;MAA0B,cAAW;gBAClD,oBAAC;OAAG,WAAU;iBACX,SAAS,KAAK,SAAS;AACtB,eACE,oBAAC,kBACC,oBAAC;SACC,MAAM,KAAK;SACX,WAAU;SACV,cAAY,KAAK;SACjB,QAAQ,KAAK;SACb,KAAK,KAAK;mBAET,KAAK;UACC,IATF,KAAK,OAAO,KAAK,MAUrB;SAEP;QACC;OACD;KAEP,SAAS,SAAS,KACjB,oBAAC;MAAI,WAAU;gBACZ,SAAS,KAAK,WACb,oBAAC;OAEC,MAAM,OAAO;OACb,WAAW,CAAC,sBAAsB,uBAAuB,OAAO,UAAU,CAAC,KAAK,IAAI;OACpF,cAAY,OAAO;OACnB,QAAQ,OAAO;OACf,KAAK,OAAO;iBAEX,OAAO;SAPH,OAAO,OAAO,OAAO,MAQnB,CACT;OACE;KAEP,YAAY,SAAS,KACpB,oBAAC;MAAI,WAAU;MAA6B,cAAW;gBACpD,YAAY,KAAK,SAAS;OACzB,MAAM,OAAOA,yBAAuB,KAAK;OACzC,MAAM,WAAW,KAAK,KAAK,WAAW,UAAU;AAChD,cACE,oBAAC;QAEC,MAAM,KAAK;QACX,WAAU;QACV,cAAY,KAAK;QACjB,GAAK,CAAC,YAAY;SAAE,QAAQ;SAAU,KAAK;SAAuB;kBAEjE,OACC,oBAAC,QAAK,eAAY,SAAS,GACzB,KAAK,UACP,oBAAC;SAAK,yBAAyB,EAAE,QAAQ,KAAK,SAAS;SAAE,eAAY;UAAS,GAE9E,oBAAC,oBAAM,KAAK,MAAM,KAAU;UAXzB,KAAK,OAAO,KAAK,SAapB;QAEN;OACE;;KAEJ;IACF;GACC;;AAIb,MAAMA,2BAAoF;CACxF,SAAS;CACT,UAAU;CACV,OAAO;CACP,QAAQ;CACR,SAAS;CACT,SAAS;CACV;;;;AClID,SAAgB,OAAO,EAAE,SAAS,OAAO,WAAW,cAA2B;AAC7E,KAAI,qBAAqB,EAAE;AACzB,0BAAwB,SAAS,6BAA6B;AAC9D,wBAAsB,OAAO,2BAA2B;;CAG1D,MAAM,oBAAoB,sBAAsB,QAAQ;CACxD,MAAM,kBAAkB,oBAAoB,MAAM;CAClD,MAAM,YAAY,iBAAiB,cAAc,YAAY,YAAY;CACzE,MAAM,QAAQ,aAAa,gBAAgB;CAC3C,MAAM,EAAE,UAAU,UAAU,gBAAgB,kCAAkC,kBAAkB;CAChG,MAAM,oBAAoB,CAAC,sBAAsB,UAAU,CAAC,OAAO,QAAQ,CAAC,KAAK,IAAI;CAErF,MAAM,SAAS,aACX,cACC,EAAE,MAAM,WAAW,KAAK,cAAc,WAAW,QAAQ,KAAK,eAC7D,oBAAC;EAAQ;EAAM,WAAW;EAAK,cAAY;EAAmB;EAAa;EAAM;GAAa;AAGpG,QACE,oBAAC;EAAO,WAAW;EAAmB,yBAAuB;EAAkB;EAAO,MAAK;YACzF,qBAAC;GAAI,WAAU;cACb,qBAAC;IAAI,WAAU;;KACb,qBAAC;MAAI,WAAU;wBACL;OACN,MAAM,cAAc,kBAAkB,UACpC,oBAAC;QACC,KAAK,kBAAkB;QACvB,KAAK,kBAAkB,WAAW,kBAAkB;QACpD,WAAU;SACV,GACA;AAEJ,WAAI,kBAAkB,SACpB,QACE,oBAAC;QACC,MAAM,kBAAkB;QACxB,WAAU;QACV,cAAY,GAAG,kBAAkB,KAAK;QACtC,QAAO;kBAEN,eAAe,kBAAkB;SAC3B;AAIb,cAAO,cACH,cACA,oBAAC;QAAE,WAAU;kBAA4B,kBAAkB;SAAS;UACtE,EACH,kBAAkB,WAAW,oBAAC;OAAE,WAAU;iBAA+B,kBAAkB;QAAY;OACpG;KACL,SAAS,SAAS,KACjB,oBAAC;MAAI,WAAU;MAA0B,cAAW;gBAClD,oBAAC;OAAG,WAAU;iBACX,SAAS,KAAK,SAAS;AACtB,eACE,oBAAC,kBACC,oBAAC;SACC,MAAM,KAAK;SACX,WAAU;SACV,cAAY,KAAK;SACjB,QAAQ,KAAK;SACb,KAAK,KAAK;mBAET,KAAK;UACC,IATF,KAAK,OAAO,KAAK,MAUrB;SAEP;QACC;OACD;KAEP,SAAS,SAAS,KACjB,oBAAC;MAAI,WAAU;gBACZ,SAAS,KAAK,WACb,oBAAC;OAEC,MAAM,OAAO;OACb,WAAW,CAAC,sBAAsB,uBAAuB,OAAO,UAAU,CAAC,KAAK,IAAI;OACpF,cAAY,OAAO;OACnB,QAAQ,OAAO;OACf,KAAK,OAAO;iBAEX,OAAO;SAPH,OAAO,OAAO,OAAO,MAQnB,CACT;OACE;KAEP,YAAY,SAAS,KACpB,oBAAC;MAAI,WAAU;MAA6B,cAAW;gBACpD,YAAY,KAAK,SAAS;OACzB,MAAM,OAAO,uBAAuB,KAAK;OACzC,MAAM,WAAW,KAAK,KAAK,WAAW,UAAU;AAChD,cACE,oBAAC;QAEC,MAAM,KAAK;QACX,WAAU;QACV,cAAY,KAAK;QACjB,GAAK,CAAC,YAAY;SAAE,QAAQ;SAAU,KAAK;SAAuB;kBAEjE,OACC,oBAAC,QAAK,eAAY,SAAS,GACzB,KAAK,UACP,oBAAC;SAAK,yBAAyB,EAAE,QAAQ,KAAK,SAAS;SAAE,eAAY;UAAS,GAE9E,oBAAC,oBAAM,KAAK,MAAM,KAAU;UAXzB,KAAK,OAAO,KAAK,SAapB;QAEN;OACE;;KAEJ,EACN,oBAAC;IAAE,WAAU;cACV,kBAAkB,iBAAiB,2BAAU,IAAI,MAAM,EAAC,aAAa,CAAC,GAAG,kBAAkB;KAC1F;IACA;GACC;;AAIb,MAAM,yBAAoF;CACxF,SAAS;CACT,UAAU;CACV,OAAO;CACP,QAAQ;CACR,SAAS;CACT,SAAS;CACV"}
|
package/dist/svelte.d.mts
CHANGED
package/dist/svelte.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as shouldValidateInDev, n as assertValidBrandDetails, r as assertValidBrandTheme } from "./validation-
|
|
1
|
+
import { l as shouldValidateInDev, n as assertValidBrandDetails, r as assertValidBrandTheme } from "./validation-BOH3j-R6.mjs";
|
|
2
2
|
import { applyBrandShellProps, registerBrandShellElements } from "./web.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/svelte/index.ts
|
|
@@ -336,6 +336,7 @@ function validateBrandDetails(details) {
|
|
|
336
336
|
validateOptionalString(details.logoSrc, "details.logoSrc", errors);
|
|
337
337
|
validateSafeHref(details.logoSrc, "details.logoSrc", errors);
|
|
338
338
|
validateOptionalString(details.logoAlt, "details.logoAlt", errors);
|
|
339
|
+
validateOptionalString(details.copyrightText, "details.copyrightText", errors);
|
|
339
340
|
if (details.navLinks != null) if (!Array.isArray(details.navLinks)) errors.push("details.navLinks must be an array.");
|
|
340
341
|
else details.navLinks.forEach((link, index) => validateNavLink(link, `details.navLinks[${index}]`, errors));
|
|
341
342
|
if (details.primaryAction != null) validateAction(details.primaryAction, "details.primaryAction", errors);
|
|
@@ -486,4 +487,4 @@ function isRecord(value) {
|
|
|
486
487
|
|
|
487
488
|
//#endregion
|
|
488
489
|
export { normalizeBrandTheme as a, themeToCssVariables as c, buildShellViewModelFromNormalized as d, normalizeBrandDetails as f, detailsToSocialLinks as g, normalizeNavLinks as h, formatValidationErrors as i, shouldValidateInDev as l, normalizeEmailHref as m, assertValidBrandDetails as n, validateBrandDetails as o, normalizeCtaLinks as p, assertValidBrandTheme as r, validateBrandTheme as s, BrandShellValidationError as t, buildShellViewModel as u };
|
|
489
|
-
//# sourceMappingURL=validation-
|
|
490
|
+
//# sourceMappingURL=validation-BOH3j-R6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-BOH3j-R6.mjs","names":[],"sources":["../src/core/social.ts","../src/core/links.ts","../src/core/shell.ts","../src/core/dev.ts","../src/core/theme.ts","../src/core/validation.ts"],"sourcesContent":["import type { BrandDetails } from \"./types\";\n\nexport type SocialPlatform = \"website\" | \"linkedin\" | \"email\" | \"github\" | \"twitter\" | \"discord\";\n\nexport interface SocialLink {\n platform: SocialPlatform | string;\n href: string;\n label: string;\n iconSvg?: string;\n}\n\nexport function detailsToSocialLinks(details: BrandDetails): SocialLink[] {\n const links: SocialLink[] = [];\n if (details.website) links.push({ platform: \"website\", href: details.website, label: \"Website\" });\n if (details.linkedin) links.push({ platform: \"linkedin\", href: details.linkedin, label: \"LinkedIn\" });\n if (details.email) links.push({ platform: \"email\", href: details.email, label: \"Email\" });\n if (details.github) links.push({ platform: \"github\", href: details.github, label: \"GitHub\" });\n if (details.twitter) links.push({ platform: \"twitter\", href: details.twitter, label: \"Twitter\" });\n if (details.discord) links.push({ platform: \"discord\", href: details.discord, label: \"Discord\" });\n if (details.customSocialLinks) {\n for (const custom of details.customSocialLinks) {\n links.push({ platform: custom.platform, href: custom.href, label: custom.label, iconSvg: custom.iconSvg });\n }\n }\n return links;\n}\n","const ABSOLUTE_SCHEME_PATTERN = /^([a-zA-Z][a-zA-Z\\d+.-]*):/;\nconst UNSAFE_CHAR_PATTERN = /[\\u0000-\\u001f\\u007f]/;\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\", \"mailto:\", \"tel:\"]);\nconst REQUIRED_BLANK_REL_TOKENS = [\"noopener\", \"noreferrer\"];\n\nexport function normalizeSafeHref(href: unknown): string | undefined {\n if (typeof href !== \"string\") return undefined;\n const trimmed = href.trim();\n if (trimmed.length === 0) return undefined;\n if (UNSAFE_CHAR_PATTERN.test(trimmed)) return undefined;\n if (trimmed.startsWith(\"//\")) return undefined;\n\n const schemeMatch = trimmed.match(ABSOLUTE_SCHEME_PATTERN);\n if (!schemeMatch) {\n return trimmed;\n }\n\n const protocol = `${schemeMatch[1]?.toLowerCase()}:`;\n if (protocol === \"data:\") {\n return trimmed.startsWith(\"data:image/\") ? trimmed : undefined;\n }\n if (!ALLOWED_PROTOCOLS.has(protocol)) {\n return undefined;\n }\n\n return trimmed;\n}\n\nexport function isSafeHref(href: unknown): boolean {\n return normalizeSafeHref(href) != null;\n}\n\nexport function normalizeRel(target: \"_blank\" | \"_self\" | \"_parent\" | \"_top\", rel?: string): string | undefined {\n const normalizedRel = typeof rel === \"string\" ? rel.trim() : \"\";\n if (target !== \"_blank\") {\n return normalizedRel.length > 0 ? normalizedRel : undefined;\n }\n\n const tokens = normalizedRel.length > 0 ? normalizedRel.split(/\\s+/).filter(Boolean) : [];\n const tokenSet = new Set(tokens.map((token) => token.toLowerCase()));\n\n for (const requiredToken of REQUIRED_BLANK_REL_TOKENS) {\n if (!tokenSet.has(requiredToken)) {\n tokens.push(requiredToken);\n }\n }\n\n return tokens.join(\" \");\n}\n","import { detailsToSocialLinks, type SocialLink } from \"./social\";\nimport type { BrandAction, BrandDetails, BrandNavLink, CustomSocialLink } from \"./types\";\nimport { normalizeRel, normalizeSafeHref } from \"./links\";\n\nexport type LinkTarget = NonNullable<BrandNavLink[\"target\"]>;\n\nexport interface ShellNavLink extends BrandNavLink {\n ariaLabel: string;\n rel?: string;\n target: LinkTarget;\n}\n\nexport interface ShellActionLink extends BrandAction {\n ariaLabel: string;\n rel?: string;\n target: LinkTarget;\n variant: NonNullable<BrandAction[\"variant\"]>;\n}\n\nexport interface ShellViewModel {\n navLinks: ShellNavLink[];\n ctaLinks: ShellActionLink[];\n socialLinks: SocialLink[];\n}\n\nexport type NormalizedActionLink = Omit<ShellActionLink, \"variant\"> & Pick<BrandAction, \"variant\">;\n\nexport interface NormalizedBrandDetails extends Omit<BrandDetails, \"navLinks\" | \"primaryAction\" | \"secondaryAction\"> {\n navLinks: ShellNavLink[];\n primaryAction?: NormalizedActionLink;\n secondaryAction?: NormalizedActionLink;\n}\n\nexport function normalizeNavLinks(navLinks: BrandNavLink[] = []): ShellNavLink[] {\n return navLinks.flatMap((link) => {\n const href = normalizeSafeHref(link.href);\n if (!href) return [];\n\n const { target, rel } = normalizeLinkTargetRel(link.target, link.rel);\n return {\n ...link,\n href,\n ariaLabel: link.ariaLabel ?? link.label,\n target,\n rel,\n };\n });\n}\n\nexport function normalizeBrandDetails(details: BrandDetails): NormalizedBrandDetails {\n const normalizedPrimaryAction = normalizeAction(details.primaryAction);\n const normalizedSecondaryAction = normalizeAction(details.secondaryAction);\n\n return {\n ...details,\n homeHref: normalizeSafeHref(details.homeHref),\n email: normalizeEmailHref(details.email),\n website: normalizeSafeHref(details.website),\n linkedin: normalizeSafeHref(details.linkedin),\n github: normalizeSafeHref(details.github),\n twitter: normalizeSafeHref(details.twitter),\n discord: normalizeSafeHref(details.discord),\n navLinks: normalizeNavLinks(details.navLinks),\n primaryAction: normalizedPrimaryAction,\n secondaryAction: normalizedSecondaryAction,\n customSocialLinks: normalizeCustomSocialLinks(details.customSocialLinks),\n logoSrc: normalizeSafeHref(details.logoSrc),\n logoAlt: details.logoAlt,\n };\n}\n\nexport function normalizeCtaLinks(\n primaryAction?: BrandAction,\n secondaryAction?: BrandAction,\n): ShellActionLink[] {\n const normalizedPrimaryAction = normalizeAction(primaryAction);\n const normalizedSecondaryAction = normalizeAction(secondaryAction);\n const actions = [normalizedSecondaryAction, normalizedPrimaryAction].filter(\n (action): action is NonNullable<typeof action> => Boolean(action),\n );\n\n return actions.map((action, index) => {\n const variant =\n action.variant ?? (action === normalizedPrimaryAction || index === actions.length - 1 ? \"primary\" : \"secondary\");\n\n return {\n ...action,\n variant,\n };\n });\n}\n\nexport function buildShellViewModelFromNormalized(normalized: NormalizedBrandDetails): ShellViewModel {\n return {\n navLinks: normalized.navLinks,\n ctaLinks: normalizeCtaLinks(normalized.primaryAction, normalized.secondaryAction),\n socialLinks: detailsToSocialLinks(normalized),\n };\n}\n\nexport function buildShellViewModel(details: BrandDetails): ShellViewModel {\n return buildShellViewModelFromNormalized(normalizeBrandDetails(details));\n}\n\nexport function normalizeEmailHref(email?: string): string | undefined {\n if (typeof email !== \"string\") return undefined;\n const trimmed = email.trim();\n if (trimmed.length === 0) return undefined;\n if (trimmed.toLowerCase().startsWith(\"mailto:\")) {\n const address = trimmed.slice(7).trim();\n if (address.length === 0) return undefined;\n return normalizeSafeHref(`mailto:${address}`);\n }\n return normalizeSafeHref(`mailto:${trimmed}`);\n}\n\nfunction normalizeCustomSocialLinks(links?: CustomSocialLink[]): CustomSocialLink[] | undefined {\n if (!links || links.length === 0) return undefined;\n const normalized: CustomSocialLink[] = [];\n for (const link of links) {\n const href = normalizeSafeHref(link.href);\n if (!href) continue;\n normalized.push({ ...link, href });\n }\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeAction(action?: BrandAction): NormalizedActionLink | undefined {\n if (!action) return undefined;\n\n const href = normalizeSafeHref(action.href);\n if (!href) return undefined;\n\n const { target, rel } = normalizeLinkTargetRel(action.target, action.rel);\n return {\n ...action,\n href,\n target,\n rel,\n ariaLabel: action.ariaLabel ?? action.label,\n };\n}\n\nexport function normalizeLinkTargetRel(target?: BrandNavLink[\"target\"], rel?: string) {\n const normalizedTarget: LinkTarget = target ?? \"_self\";\n const normalizedRel = normalizeRel(normalizedTarget, rel);\n return {\n target: normalizedTarget,\n rel: normalizedRel,\n };\n}\n","type ImportMetaEnv = {\n DEV?: boolean;\n MODE?: string;\n};\n\ntype ImportMetaLike = {\n env?: ImportMetaEnv;\n};\n\nexport function shouldValidateInDev(): boolean {\n const nodeEnv = typeof process !== \"undefined\" ? process.env?.NODE_ENV : undefined;\n if (typeof nodeEnv === \"string\") {\n return nodeEnv !== \"production\";\n }\n\n const { env } = import.meta as unknown as ImportMetaLike;\n if (typeof env?.DEV === \"boolean\") {\n return env.DEV;\n }\n\n return false;\n}\n","import type { BrandTheme } from \"./types\";\n\nconst THEME_VAR_PREFIX = \"brand\";\nconst DARK_TEXT = \"#0f172a\";\nconst LIGHT_TEXT = \"#f8fafc\";\n\nexport type ThemeVariables = Record<string, string>;\n\nexport function themeToCssVariables(theme?: BrandTheme | null): ThemeVariables {\n if (!theme) return {};\n const style: ThemeVariables = {};\n if (theme.primaryColor != null) style[`--${THEME_VAR_PREFIX}-primary`] = theme.primaryColor;\n if (theme.backgroundColor != null) style[`--${THEME_VAR_PREFIX}-bg`] = theme.backgroundColor;\n if (theme.textColor != null) style[`--${THEME_VAR_PREFIX}-text`] = theme.textColor;\n if (theme.fontFamily != null) style[`--${THEME_VAR_PREFIX}-font`] = theme.fontFamily;\n if (theme.linkColor != null) style[`--${THEME_VAR_PREFIX}-link`] = theme.linkColor;\n if (theme.socialIconSize != null) style[`--${THEME_VAR_PREFIX}-social-size`] = theme.socialIconSize;\n if (theme.buttonTextColor != null) {\n style[`--${THEME_VAR_PREFIX}-button-text`] = theme.buttonTextColor;\n } else if (theme.primaryColor != null) {\n const buttonTextColor = getAccessibleTextColor(theme.primaryColor);\n if (buttonTextColor) style[`--${THEME_VAR_PREFIX}-button-text`] = buttonTextColor;\n }\n if (theme.borderRadius != null) style[`--${THEME_VAR_PREFIX}-radius`] = theme.borderRadius;\n if (theme.headerHeight != null) style[`--${THEME_VAR_PREFIX}-header-height`] = theme.headerHeight;\n if (theme.footerPadding != null) style[`--${THEME_VAR_PREFIX}-footer-padding`] = theme.footerPadding;\n if (theme.secondaryButtonBg != null) style[`--${THEME_VAR_PREFIX}-button-secondary`] = theme.secondaryButtonBg;\n if (theme.logoHeight != null) style[`--${THEME_VAR_PREFIX}-logo-height`] = theme.logoHeight;\n return style;\n}\n\nfunction getAccessibleTextColor(backgroundColor: string): string | undefined {\n const rgb = parseColorToRgb(backgroundColor);\n if (!rgb) return undefined;\n\n const contrastWithDark = contrastRatio(rgb, { r: 15, g: 23, b: 42 });\n const contrastWithLight = contrastRatio(rgb, { r: 248, g: 250, b: 252 });\n\n return contrastWithDark > contrastWithLight ? DARK_TEXT : LIGHT_TEXT;\n}\n\n/**\n * Parses a hex (#rgb / #rrggbb) or rgb()/rgba() color string to RGB components.\n * hsl(), oklch(), and other formats are not supported and return undefined.\n */\nfunction parseColorToRgb(color: string): { r: number; g: number; b: number } | undefined {\n const trimmed = color.trim();\n\n const hexMatch = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(trimmed);\n if (hexMatch) {\n const value = hexMatch[1];\n if (value.length === 3) {\n return {\n r: Number.parseInt(value[0] + value[0], 16),\n g: Number.parseInt(value[1] + value[1], 16),\n b: Number.parseInt(value[2] + value[2], 16),\n };\n }\n return {\n r: Number.parseInt(value.slice(0, 2), 16),\n g: Number.parseInt(value.slice(2, 4), 16),\n b: Number.parseInt(value.slice(4, 6), 16),\n };\n }\n\n const rgbMatch = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/.exec(trimmed);\n if (rgbMatch) {\n return { r: +rgbMatch[1], g: +rgbMatch[2], b: +rgbMatch[3] };\n }\n\n return undefined;\n}\n\nfunction contrastRatio(\n first: { r: number; g: number; b: number },\n second: { r: number; g: number; b: number },\n): number {\n const firstLuminance = relativeLuminance(first);\n const secondLuminance = relativeLuminance(second);\n const lighter = Math.max(firstLuminance, secondLuminance);\n const darker = Math.min(firstLuminance, secondLuminance);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nfunction relativeLuminance(color: { r: number; g: number; b: number }): number {\n const transform = (channel: number) => {\n const normalized = channel / 255;\n if (normalized <= 0.03928) return normalized / 12.92;\n return ((normalized + 0.055) / 1.055) ** 2.4;\n };\n\n const r = transform(color.r);\n const g = transform(color.g);\n const b = transform(color.b);\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n","import { normalizeBrandDetails, normalizeEmailHref, type NormalizedBrandDetails } from \"./shell\";\nimport { normalizeSafeHref } from \"./links\";\nimport type { BrandAction, BrandDetails, BrandNavLink, BrandTheme, CustomSocialLink } from \"./types\";\n\nconst LINK_TARGETS = new Set<NonNullable<BrandNavLink[\"target\"]>>([\"_blank\", \"_self\", \"_parent\", \"_top\"]);\nconst CTA_VARIANTS = new Set<NonNullable<BrandAction[\"variant\"]>>([\"primary\", \"secondary\", \"ghost\"]);\nconst CTA_LAYOUTS = new Set<NonNullable<BrandTheme[\"ctaLayout\"]>>([\"inline\", \"stacked\"]);\nconst THEME_KEYS = new Set<keyof BrandTheme>([\n \"primaryColor\",\n \"backgroundColor\",\n \"textColor\",\n \"fontFamily\",\n \"linkColor\",\n \"socialIconSize\",\n \"buttonTextColor\",\n \"ctaLayout\",\n \"borderRadius\",\n \"headerHeight\",\n \"footerPadding\",\n \"secondaryButtonBg\",\n \"logoHeight\",\n]);\n\ntype ValidationErrorPath = string;\n\nexport interface BrandValidationResult<T> {\n valid: boolean;\n errors: string[];\n normalized: T | null;\n}\n\nexport class BrandShellValidationError extends Error {\n readonly context: string;\n readonly errors: string[];\n\n constructor(context: string, errors: string[]) {\n super(formatValidationErrors(context, errors));\n this.name = \"BrandShellValidationError\";\n this.context = context;\n this.errors = errors;\n }\n}\n\nexport function validateBrandDetails(details: unknown): BrandValidationResult<NormalizedBrandDetails> {\n const errors: string[] = [];\n\n if (!isRecord(details)) {\n errors.push(\"details must be an object.\");\n return { valid: false, errors, normalized: null };\n }\n\n validateRequiredString(details.name, \"details.name\", errors);\n validateOptionalString(details.homeHref, \"details.homeHref\", errors);\n validateSafeHref(details.homeHref, \"details.homeHref\", errors);\n validateOptionalString(details.website, \"details.website\", errors);\n validateSafeHref(details.website, \"details.website\", errors);\n validateOptionalString(details.linkedin, \"details.linkedin\", errors);\n validateSafeHref(details.linkedin, \"details.linkedin\", errors);\n validateOptionalString(details.email, \"details.email\", errors);\n validateEmail(details.email, \"details.email\", errors);\n validateOptionalString(details.github, \"details.github\", errors);\n validateSafeHref(details.github, \"details.github\", errors);\n validateOptionalString(details.twitter, \"details.twitter\", errors);\n validateSafeHref(details.twitter, \"details.twitter\", errors);\n validateOptionalString(details.discord, \"details.discord\", errors);\n validateSafeHref(details.discord, \"details.discord\", errors);\n validateOptionalString(details.tagline, \"details.tagline\", errors);\n validateOptionalString(details.logoSrc, \"details.logoSrc\", errors);\n validateSafeHref(details.logoSrc, \"details.logoSrc\", errors);\n validateOptionalString(details.logoAlt, \"details.logoAlt\", errors);\n validateOptionalString(details.copyrightText, \"details.copyrightText\", errors);\n\n if (details.navLinks != null) {\n if (!Array.isArray(details.navLinks)) {\n errors.push(\"details.navLinks must be an array.\");\n } else {\n details.navLinks.forEach((link, index) => validateNavLink(link, `details.navLinks[${index}]`, errors));\n }\n }\n\n if (details.primaryAction != null) {\n validateAction(details.primaryAction, \"details.primaryAction\", errors);\n }\n if (details.secondaryAction != null) {\n validateAction(details.secondaryAction, \"details.secondaryAction\", errors);\n }\n\n if (details.customSocialLinks != null) {\n if (!Array.isArray(details.customSocialLinks)) {\n errors.push(\"details.customSocialLinks must be an array.\");\n } else {\n details.customSocialLinks.forEach((link, index) =>\n validateCustomSocialLink(link, `details.customSocialLinks[${index}]`, errors),\n );\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors, normalized: null };\n }\n\n return {\n valid: true,\n errors: [],\n normalized: normalizeBrandDetails(details as unknown as BrandDetails),\n };\n}\n\nexport function validateBrandTheme(theme: unknown): BrandValidationResult<BrandTheme | null> {\n if (theme == null) {\n return {\n valid: true,\n errors: [],\n normalized: null,\n };\n }\n\n const errors: string[] = [];\n\n if (!isRecord(theme)) {\n errors.push(\"theme must be an object when provided.\");\n return { valid: false, errors, normalized: null };\n }\n\n for (const key of Object.keys(theme)) {\n if (!THEME_KEYS.has(key as keyof BrandTheme)) {\n errors.push(`theme.${key} is not a supported theme key.`);\n continue;\n }\n if (key === \"ctaLayout\") {\n validateCtaLayout(theme[key], \"theme.ctaLayout\", errors);\n continue;\n }\n validateOptionalString(theme[key], `theme.${key}`, errors);\n }\n\n if (errors.length > 0) {\n return { valid: false, errors, normalized: null };\n }\n\n return {\n valid: true,\n errors: [],\n normalized: normalizeBrandTheme(theme as BrandTheme),\n };\n}\n\nexport function assertValidBrandDetails(details: unknown, context = \"BrandDetails\"): asserts details is BrandDetails {\n const result = validateBrandDetails(details);\n if (!result.valid) {\n throw new BrandShellValidationError(context, result.errors);\n }\n}\n\nexport function assertValidBrandTheme(theme: unknown, context = \"BrandTheme\"): asserts theme is BrandTheme | null | undefined {\n const result = validateBrandTheme(theme);\n if (!result.valid) {\n throw new BrandShellValidationError(context, result.errors);\n }\n}\n\nexport function normalizeBrandTheme(theme?: BrandTheme | null): BrandTheme | null {\n if (!theme) return null;\n\n const normalized: BrandTheme = {};\n for (const key of THEME_KEYS) {\n const value = theme[key];\n if (key === \"ctaLayout\") {\n if (typeof value === \"string\" && CTA_LAYOUTS.has(value as NonNullable<BrandTheme[\"ctaLayout\"]>)) {\n normalized[key] = value as BrandTheme[\"ctaLayout\"];\n }\n continue;\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.length > 0) {\n normalized[key] = trimmed;\n }\n }\n }\n\n return Object.keys(normalized).length > 0 ? normalized : null;\n}\n\nexport function formatValidationErrors(context: string, errors: string[]): string {\n return `${context} validation failed:\\n${errors.map((error) => `- ${error}`).join(\"\\n\")}`;\n}\n\nfunction validateNavLink(link: unknown, path: ValidationErrorPath, errors: string[]) {\n if (!isRecord(link)) {\n errors.push(`${path} must be an object.`);\n return;\n }\n\n validateRequiredString(link.label, `${path}.label`, errors);\n validateRequiredString(link.href, `${path}.href`, errors);\n validateSafeHref(link.href, `${path}.href`, errors);\n validateOptionalString(link.ariaLabel, `${path}.ariaLabel`, errors);\n validateOptionalString(link.rel, `${path}.rel`, errors);\n validateTarget(link.target, `${path}.target`, errors);\n}\n\nfunction validateAction(action: unknown, path: ValidationErrorPath, errors: string[]) {\n if (!isRecord(action)) {\n errors.push(`${path} must be an object.`);\n return;\n }\n\n validateRequiredString(action.label, `${path}.label`, errors);\n validateRequiredString(action.href, `${path}.href`, errors);\n validateSafeHref(action.href, `${path}.href`, errors);\n validateOptionalString(action.ariaLabel, `${path}.ariaLabel`, errors);\n validateOptionalString(action.rel, `${path}.rel`, errors);\n validateTarget(action.target, `${path}.target`, errors);\n\n if (action.variant != null) {\n if (typeof action.variant !== \"string\" || !CTA_VARIANTS.has(action.variant as NonNullable<BrandAction[\"variant\"]>)) {\n errors.push(`${path}.variant must be one of: primary, secondary, ghost.`);\n }\n }\n}\n\nfunction validateCustomSocialLink(link: unknown, path: ValidationErrorPath, errors: string[]) {\n if (!isRecord(link)) {\n errors.push(`${path} must be an object.`);\n return;\n }\n\n if (typeof link.platform !== \"string\" || link.platform.trim().length === 0) {\n errors.push(`${path}.platform must be a non-empty string.`);\n }\n validateRequiredString(link.label, `${path}.label`, errors);\n validateRequiredString(link.href, `${path}.href`, errors);\n validateSafeHref(link.href, `${path}.href`, errors);\n if (link.iconSvg != null) {\n validateOptionalString(link.iconSvg, `${path}.iconSvg`, errors);\n }\n}\n\nfunction validateTarget(target: unknown, path: ValidationErrorPath, errors: string[]) {\n if (target == null) return;\n if (typeof target !== \"string\" || !LINK_TARGETS.has(target as NonNullable<BrandNavLink[\"target\"]>)) {\n errors.push(`${path} must be one of: _blank, _self, _parent, _top.`);\n }\n}\n\nfunction validateCtaLayout(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || !CTA_LAYOUTS.has(value as NonNullable<BrandTheme[\"ctaLayout\"]>)) {\n errors.push(`${path} must be one of: inline, stacked.`);\n }\n}\n\nfunction validateRequiredString(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n errors.push(`${path} must be a non-empty string.`);\n }\n}\n\nfunction validateOptionalString(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || value.trim().length === 0) {\n errors.push(`${path} must be a non-empty string when provided.`);\n }\n}\n\nfunction validateSafeHref(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || value.trim().length === 0) return;\n if (!normalizeSafeHref(value)) {\n errors.push(`${path} must use a safe URL/path (http, https, mailto, tel, or relative path).`);\n }\n}\n\nfunction validateEmail(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || value.trim().length === 0) return;\n if (!normalizeEmailHref(value)) {\n errors.push(`${path} must be a valid email or mailto URL.`);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n"],"mappings":"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"}
|
|
@@ -73,6 +73,8 @@ interface BrandDetails {
|
|
|
73
73
|
logoSrc?: string;
|
|
74
74
|
/** Alt text for the logo. Defaults to `name` if omitted. */
|
|
75
75
|
logoAlt?: string;
|
|
76
|
+
/** Custom copyright line shown in the footer. Defaults to `© {year} {name}` when omitted. */
|
|
77
|
+
copyrightText?: string;
|
|
76
78
|
}
|
|
77
79
|
/**
|
|
78
80
|
* Optional theme to adapt branding without custom CSS.
|
|
@@ -167,4 +169,4 @@ declare function normalizeBrandTheme(theme?: BrandTheme | null): BrandTheme | nu
|
|
|
167
169
|
declare function formatValidationErrors(context: string, errors: string[]): string;
|
|
168
170
|
//#endregion
|
|
169
171
|
export { BrandAction as C, CustomSocialLink as D, BrandTheme as E, detailsToSocialLinks as S, BrandNavLink as T, normalizeCtaLinks as _, formatValidationErrors as a, SocialLink as b, validateBrandTheme as c, ShellActionLink as d, ShellNavLink as f, normalizeBrandDetails as g, buildShellViewModelFromNormalized as h, assertValidBrandTheme as i, LinkTarget as l, buildShellViewModel as m, BrandValidationResult as n, normalizeBrandTheme as o, ShellViewModel as p, assertValidBrandDetails as r, validateBrandDetails as s, BrandShellValidationError as t, NormalizedBrandDetails as u, normalizeEmailHref as v, BrandDetails as w, SocialPlatform as x, normalizeNavLinks as y };
|
|
170
|
-
//# sourceMappingURL=validation-
|
|
172
|
+
//# sourceMappingURL=validation-DRG5UAhg.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validation-DRG5UAhg.d.mts","names":[],"sources":["../src/core/types.ts","../src/core/social.ts","../src/core/shell.ts","../src/core/validation.ts"],"mappings":"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"}
|
package/dist/vue.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { E as BrandTheme, c as validateBrandTheme, s as validateBrandDetails, w as BrandDetails } from "./validation-
|
|
1
|
+
import { E as BrandTheme, c as validateBrandTheme, s as validateBrandDetails, w as BrandDetails } from "./validation-DRG5UAhg.mjs";
|
|
2
2
|
import { LinkFactoryOptions } from "./web.mjs";
|
|
3
3
|
import * as vue from "vue";
|
|
4
4
|
import { PropType } from "vue";
|
package/dist/vue.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { l as shouldValidateInDev, n as assertValidBrandDetails, o as validateBrandDetails, r as assertValidBrandTheme, s as validateBrandTheme } from "./validation-
|
|
1
|
+
import { l as shouldValidateInDev, n as assertValidBrandDetails, o as validateBrandDetails, r as assertValidBrandTheme, s as validateBrandTheme } from "./validation-BOH3j-R6.mjs";
|
|
2
2
|
import { applyBrandShellProps, registerBrandShellElements } from "./web.mjs";
|
|
3
3
|
import { defineComponent, h, onMounted, ref, watch } from "vue";
|
|
4
4
|
|
package/dist/web.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { C as BrandAction, E as BrandTheme, T as BrandNavLink, c as validateBrandTheme, s as validateBrandDetails, w as BrandDetails } from "./validation-
|
|
1
|
+
import { C as BrandAction, E as BrandTheme, T as BrandNavLink, c as validateBrandTheme, s as validateBrandDetails, w as BrandDetails } from "./validation-DRG5UAhg.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/web/index.d.ts
|
|
4
4
|
declare const HTMLElementBase: typeof HTMLElement;
|
package/dist/web.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
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,
|
|
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,QAuZtE,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-BOH3j-R6.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/web/index.ts
|
|
4
4
|
const SVG_NS = "http://www.w3.org/2000/svg";
|
|
@@ -167,6 +167,11 @@ function createHeader(details, theme, shellClass, linkFactory) {
|
|
|
167
167
|
header.setAttribute("role", "banner");
|
|
168
168
|
applyThemeVariables(header, theme);
|
|
169
169
|
header.dataset.brandCtaLayout = resolveCtaLayout(theme);
|
|
170
|
+
const skipNav = document.createElement("a");
|
|
171
|
+
skipNav.href = "#main-content";
|
|
172
|
+
skipNav.className = "brand-shell-skip-nav";
|
|
173
|
+
skipNav.textContent = "Skip to main content";
|
|
174
|
+
header.append(skipNav);
|
|
170
175
|
const inner = document.createElement("div");
|
|
171
176
|
inner.className = "brand-shell-header__inner";
|
|
172
177
|
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);
|
|
@@ -220,7 +225,7 @@ function createFooter(details, theme, shellClass, linkFactory) {
|
|
|
220
225
|
if (navLinks.length > 0) top.append(createNav(navLinks, "brand-shell-footer", "Footer", linkFactory));
|
|
221
226
|
if (ctaLinks.length > 0) top.append(createCtas(ctaLinks, "brand-shell-footer__ctas", linkFactory));
|
|
222
227
|
if (socialLinks.length > 0) top.append(createSocialLinks(socialLinks, "brand-shell-footer__social", "brand-shell-footer__social-link"));
|
|
223
|
-
const copy = createParagraph("brand-shell-footer__copy", `© ${(/* @__PURE__ */ new Date()).getFullYear()} ${details.name}`);
|
|
228
|
+
const copy = createParagraph("brand-shell-footer__copy", details.copyrightText ?? `© ${(/* @__PURE__ */ new Date()).getFullYear()} ${details.name}`);
|
|
224
229
|
inner.append(top, copy);
|
|
225
230
|
footer.append(inner);
|
|
226
231
|
return footer;
|
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\";\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 if (details.logoSrc) {\n const img = document.createElement(\"img\");\n img.src = details.logoSrc;\n img.alt = details.logoAlt ?? details.name;\n img.className = \"brand-shell-header__logo\";\n identity.textContent = \"\";\n identity.append(img);\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\", 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 if (details.logoSrc) {\n const img = document.createElement(\"img\");\n img.src = details.logoSrc;\n img.alt = details.logoAlt ?? details.name;\n img.className = \"brand-shell-footer__logo\";\n if (details.homeHref) {\n const identity = createAnchor(details.homeHref, \"brand-shell-footer__name\", details.name, `${details.name} home`, \"_self\", undefined, linkFactory);\n identity.textContent = \"\";\n identity.append(img);\n brand.append(identity);\n } else {\n brand.append(img);\n }\n } else if (details.homeHref) {\n brand.append(createAnchor(details.homeHref, \"brand-shell-footer__name\", details.name, `${details.name} home`, \"_self\", undefined, linkFactory));\n } else {\n brand.append(createParagraph(\"brand-shell-footer__name\", details.name));\n }\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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"}
|
|
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 skipNav = document.createElement(\"a\");\n skipNav.href = \"#main-content\";\n skipNav.className = \"brand-shell-skip-nav\";\n skipNav.textContent = \"Skip to main content\";\n header.append(skipNav);\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 if (details.logoSrc) {\n const img = document.createElement(\"img\");\n img.src = details.logoSrc;\n img.alt = details.logoAlt ?? details.name;\n img.className = \"brand-shell-header__logo\";\n identity.textContent = \"\";\n identity.append(img);\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\", 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 if (details.logoSrc) {\n const img = document.createElement(\"img\");\n img.src = details.logoSrc;\n img.alt = details.logoAlt ?? details.name;\n img.className = \"brand-shell-footer__logo\";\n if (details.homeHref) {\n const identity = createAnchor(details.homeHref, \"brand-shell-footer__name\", details.name, `${details.name} home`, \"_self\", undefined, linkFactory);\n identity.textContent = \"\";\n identity.append(img);\n brand.append(identity);\n } else {\n brand.append(img);\n }\n } else if (details.homeHref) {\n brand.append(createAnchor(details.homeHref, \"brand-shell-footer__name\", details.name, `${details.name} home`, \"_self\", undefined, linkFactory));\n } else {\n brand.append(createParagraph(\"brand-shell-footer__name\", details.name));\n }\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\", details.copyrightText ?? `© ${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.17.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": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation-BhhgC3n1.mjs","names":[],"sources":["../src/core/social.ts","../src/core/links.ts","../src/core/shell.ts","../src/core/dev.ts","../src/core/theme.ts","../src/core/validation.ts"],"sourcesContent":["import type { BrandDetails } from \"./types\";\n\nexport type SocialPlatform = \"website\" | \"linkedin\" | \"email\" | \"github\" | \"twitter\" | \"discord\";\n\nexport interface SocialLink {\n platform: SocialPlatform | string;\n href: string;\n label: string;\n iconSvg?: string;\n}\n\nexport function detailsToSocialLinks(details: BrandDetails): SocialLink[] {\n const links: SocialLink[] = [];\n if (details.website) links.push({ platform: \"website\", href: details.website, label: \"Website\" });\n if (details.linkedin) links.push({ platform: \"linkedin\", href: details.linkedin, label: \"LinkedIn\" });\n if (details.email) links.push({ platform: \"email\", href: details.email, label: \"Email\" });\n if (details.github) links.push({ platform: \"github\", href: details.github, label: \"GitHub\" });\n if (details.twitter) links.push({ platform: \"twitter\", href: details.twitter, label: \"Twitter\" });\n if (details.discord) links.push({ platform: \"discord\", href: details.discord, label: \"Discord\" });\n if (details.customSocialLinks) {\n for (const custom of details.customSocialLinks) {\n links.push({ platform: custom.platform, href: custom.href, label: custom.label, iconSvg: custom.iconSvg });\n }\n }\n return links;\n}\n","const ABSOLUTE_SCHEME_PATTERN = /^([a-zA-Z][a-zA-Z\\d+.-]*):/;\nconst UNSAFE_CHAR_PATTERN = /[\\u0000-\\u001f\\u007f]/;\nconst ALLOWED_PROTOCOLS = new Set([\"http:\", \"https:\", \"mailto:\", \"tel:\"]);\nconst REQUIRED_BLANK_REL_TOKENS = [\"noopener\", \"noreferrer\"];\n\nexport function normalizeSafeHref(href: unknown): string | undefined {\n if (typeof href !== \"string\") return undefined;\n const trimmed = href.trim();\n if (trimmed.length === 0) return undefined;\n if (UNSAFE_CHAR_PATTERN.test(trimmed)) return undefined;\n if (trimmed.startsWith(\"//\")) return undefined;\n\n const schemeMatch = trimmed.match(ABSOLUTE_SCHEME_PATTERN);\n if (!schemeMatch) {\n return trimmed;\n }\n\n const protocol = `${schemeMatch[1]?.toLowerCase()}:`;\n if (protocol === \"data:\") {\n return trimmed.startsWith(\"data:image/\") ? trimmed : undefined;\n }\n if (!ALLOWED_PROTOCOLS.has(protocol)) {\n return undefined;\n }\n\n return trimmed;\n}\n\nexport function isSafeHref(href: unknown): boolean {\n return normalizeSafeHref(href) != null;\n}\n\nexport function normalizeRel(target: \"_blank\" | \"_self\" | \"_parent\" | \"_top\", rel?: string): string | undefined {\n const normalizedRel = typeof rel === \"string\" ? rel.trim() : \"\";\n if (target !== \"_blank\") {\n return normalizedRel.length > 0 ? normalizedRel : undefined;\n }\n\n const tokens = normalizedRel.length > 0 ? normalizedRel.split(/\\s+/).filter(Boolean) : [];\n const tokenSet = new Set(tokens.map((token) => token.toLowerCase()));\n\n for (const requiredToken of REQUIRED_BLANK_REL_TOKENS) {\n if (!tokenSet.has(requiredToken)) {\n tokens.push(requiredToken);\n }\n }\n\n return tokens.join(\" \");\n}\n","import { detailsToSocialLinks, type SocialLink } from \"./social\";\nimport type { BrandAction, BrandDetails, BrandNavLink, CustomSocialLink } from \"./types\";\nimport { normalizeRel, normalizeSafeHref } from \"./links\";\n\nexport type LinkTarget = NonNullable<BrandNavLink[\"target\"]>;\n\nexport interface ShellNavLink extends BrandNavLink {\n ariaLabel: string;\n rel?: string;\n target: LinkTarget;\n}\n\nexport interface ShellActionLink extends BrandAction {\n ariaLabel: string;\n rel?: string;\n target: LinkTarget;\n variant: NonNullable<BrandAction[\"variant\"]>;\n}\n\nexport interface ShellViewModel {\n navLinks: ShellNavLink[];\n ctaLinks: ShellActionLink[];\n socialLinks: SocialLink[];\n}\n\nexport type NormalizedActionLink = Omit<ShellActionLink, \"variant\"> & Pick<BrandAction, \"variant\">;\n\nexport interface NormalizedBrandDetails extends Omit<BrandDetails, \"navLinks\" | \"primaryAction\" | \"secondaryAction\"> {\n navLinks: ShellNavLink[];\n primaryAction?: NormalizedActionLink;\n secondaryAction?: NormalizedActionLink;\n}\n\nexport function normalizeNavLinks(navLinks: BrandNavLink[] = []): ShellNavLink[] {\n return navLinks.flatMap((link) => {\n const href = normalizeSafeHref(link.href);\n if (!href) return [];\n\n const { target, rel } = normalizeLinkTargetRel(link.target, link.rel);\n return {\n ...link,\n href,\n ariaLabel: link.ariaLabel ?? link.label,\n target,\n rel,\n };\n });\n}\n\nexport function normalizeBrandDetails(details: BrandDetails): NormalizedBrandDetails {\n const normalizedPrimaryAction = normalizeAction(details.primaryAction);\n const normalizedSecondaryAction = normalizeAction(details.secondaryAction);\n\n return {\n ...details,\n homeHref: normalizeSafeHref(details.homeHref),\n email: normalizeEmailHref(details.email),\n website: normalizeSafeHref(details.website),\n linkedin: normalizeSafeHref(details.linkedin),\n github: normalizeSafeHref(details.github),\n twitter: normalizeSafeHref(details.twitter),\n discord: normalizeSafeHref(details.discord),\n navLinks: normalizeNavLinks(details.navLinks),\n primaryAction: normalizedPrimaryAction,\n secondaryAction: normalizedSecondaryAction,\n customSocialLinks: normalizeCustomSocialLinks(details.customSocialLinks),\n logoSrc: normalizeSafeHref(details.logoSrc),\n logoAlt: details.logoAlt,\n };\n}\n\nexport function normalizeCtaLinks(\n primaryAction?: BrandAction,\n secondaryAction?: BrandAction,\n): ShellActionLink[] {\n const normalizedPrimaryAction = normalizeAction(primaryAction);\n const normalizedSecondaryAction = normalizeAction(secondaryAction);\n const actions = [normalizedSecondaryAction, normalizedPrimaryAction].filter(\n (action): action is NonNullable<typeof action> => Boolean(action),\n );\n\n return actions.map((action, index) => {\n const variant =\n action.variant ?? (action === normalizedPrimaryAction || index === actions.length - 1 ? \"primary\" : \"secondary\");\n\n return {\n ...action,\n variant,\n };\n });\n}\n\nexport function buildShellViewModelFromNormalized(normalized: NormalizedBrandDetails): ShellViewModel {\n return {\n navLinks: normalized.navLinks,\n ctaLinks: normalizeCtaLinks(normalized.primaryAction, normalized.secondaryAction),\n socialLinks: detailsToSocialLinks(normalized),\n };\n}\n\nexport function buildShellViewModel(details: BrandDetails): ShellViewModel {\n return buildShellViewModelFromNormalized(normalizeBrandDetails(details));\n}\n\nexport function normalizeEmailHref(email?: string): string | undefined {\n if (typeof email !== \"string\") return undefined;\n const trimmed = email.trim();\n if (trimmed.length === 0) return undefined;\n if (trimmed.toLowerCase().startsWith(\"mailto:\")) {\n const address = trimmed.slice(7).trim();\n if (address.length === 0) return undefined;\n return normalizeSafeHref(`mailto:${address}`);\n }\n return normalizeSafeHref(`mailto:${trimmed}`);\n}\n\nfunction normalizeCustomSocialLinks(links?: CustomSocialLink[]): CustomSocialLink[] | undefined {\n if (!links || links.length === 0) return undefined;\n const normalized: CustomSocialLink[] = [];\n for (const link of links) {\n const href = normalizeSafeHref(link.href);\n if (!href) continue;\n normalized.push({ ...link, href });\n }\n return normalized.length > 0 ? normalized : undefined;\n}\n\nfunction normalizeAction(action?: BrandAction): NormalizedActionLink | undefined {\n if (!action) return undefined;\n\n const href = normalizeSafeHref(action.href);\n if (!href) return undefined;\n\n const { target, rel } = normalizeLinkTargetRel(action.target, action.rel);\n return {\n ...action,\n href,\n target,\n rel,\n ariaLabel: action.ariaLabel ?? action.label,\n };\n}\n\nexport function normalizeLinkTargetRel(target?: BrandNavLink[\"target\"], rel?: string) {\n const normalizedTarget: LinkTarget = target ?? \"_self\";\n const normalizedRel = normalizeRel(normalizedTarget, rel);\n return {\n target: normalizedTarget,\n rel: normalizedRel,\n };\n}\n","type ImportMetaEnv = {\n DEV?: boolean;\n MODE?: string;\n};\n\ntype ImportMetaLike = {\n env?: ImportMetaEnv;\n};\n\nexport function shouldValidateInDev(): boolean {\n const nodeEnv = typeof process !== \"undefined\" ? process.env?.NODE_ENV : undefined;\n if (typeof nodeEnv === \"string\") {\n return nodeEnv !== \"production\";\n }\n\n const { env } = import.meta as unknown as ImportMetaLike;\n if (typeof env?.DEV === \"boolean\") {\n return env.DEV;\n }\n\n return false;\n}\n","import type { BrandTheme } from \"./types\";\n\nconst THEME_VAR_PREFIX = \"brand\";\nconst DARK_TEXT = \"#0f172a\";\nconst LIGHT_TEXT = \"#f8fafc\";\n\nexport type ThemeVariables = Record<string, string>;\n\nexport function themeToCssVariables(theme?: BrandTheme | null): ThemeVariables {\n if (!theme) return {};\n const style: ThemeVariables = {};\n if (theme.primaryColor != null) style[`--${THEME_VAR_PREFIX}-primary`] = theme.primaryColor;\n if (theme.backgroundColor != null) style[`--${THEME_VAR_PREFIX}-bg`] = theme.backgroundColor;\n if (theme.textColor != null) style[`--${THEME_VAR_PREFIX}-text`] = theme.textColor;\n if (theme.fontFamily != null) style[`--${THEME_VAR_PREFIX}-font`] = theme.fontFamily;\n if (theme.linkColor != null) style[`--${THEME_VAR_PREFIX}-link`] = theme.linkColor;\n if (theme.socialIconSize != null) style[`--${THEME_VAR_PREFIX}-social-size`] = theme.socialIconSize;\n if (theme.buttonTextColor != null) {\n style[`--${THEME_VAR_PREFIX}-button-text`] = theme.buttonTextColor;\n } else if (theme.primaryColor != null) {\n const buttonTextColor = getAccessibleTextColor(theme.primaryColor);\n if (buttonTextColor) style[`--${THEME_VAR_PREFIX}-button-text`] = buttonTextColor;\n }\n if (theme.borderRadius != null) style[`--${THEME_VAR_PREFIX}-radius`] = theme.borderRadius;\n if (theme.headerHeight != null) style[`--${THEME_VAR_PREFIX}-header-height`] = theme.headerHeight;\n if (theme.footerPadding != null) style[`--${THEME_VAR_PREFIX}-footer-padding`] = theme.footerPadding;\n if (theme.secondaryButtonBg != null) style[`--${THEME_VAR_PREFIX}-button-secondary`] = theme.secondaryButtonBg;\n if (theme.logoHeight != null) style[`--${THEME_VAR_PREFIX}-logo-height`] = theme.logoHeight;\n return style;\n}\n\nfunction getAccessibleTextColor(backgroundColor: string): string | undefined {\n const rgb = parseColorToRgb(backgroundColor);\n if (!rgb) return undefined;\n\n const contrastWithDark = contrastRatio(rgb, { r: 15, g: 23, b: 42 });\n const contrastWithLight = contrastRatio(rgb, { r: 248, g: 250, b: 252 });\n\n return contrastWithDark > contrastWithLight ? DARK_TEXT : LIGHT_TEXT;\n}\n\n/**\n * Parses a hex (#rgb / #rrggbb) or rgb()/rgba() color string to RGB components.\n * hsl(), oklch(), and other formats are not supported and return undefined.\n */\nfunction parseColorToRgb(color: string): { r: number; g: number; b: number } | undefined {\n const trimmed = color.trim();\n\n const hexMatch = /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.exec(trimmed);\n if (hexMatch) {\n const value = hexMatch[1];\n if (value.length === 3) {\n return {\n r: Number.parseInt(value[0] + value[0], 16),\n g: Number.parseInt(value[1] + value[1], 16),\n b: Number.parseInt(value[2] + value[2], 16),\n };\n }\n return {\n r: Number.parseInt(value.slice(0, 2), 16),\n g: Number.parseInt(value.slice(2, 4), 16),\n b: Number.parseInt(value.slice(4, 6), 16),\n };\n }\n\n const rgbMatch = /^rgba?\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)/.exec(trimmed);\n if (rgbMatch) {\n return { r: +rgbMatch[1], g: +rgbMatch[2], b: +rgbMatch[3] };\n }\n\n return undefined;\n}\n\nfunction contrastRatio(\n first: { r: number; g: number; b: number },\n second: { r: number; g: number; b: number },\n): number {\n const firstLuminance = relativeLuminance(first);\n const secondLuminance = relativeLuminance(second);\n const lighter = Math.max(firstLuminance, secondLuminance);\n const darker = Math.min(firstLuminance, secondLuminance);\n return (lighter + 0.05) / (darker + 0.05);\n}\n\nfunction relativeLuminance(color: { r: number; g: number; b: number }): number {\n const transform = (channel: number) => {\n const normalized = channel / 255;\n if (normalized <= 0.03928) return normalized / 12.92;\n return ((normalized + 0.055) / 1.055) ** 2.4;\n };\n\n const r = transform(color.r);\n const g = transform(color.g);\n const b = transform(color.b);\n return 0.2126 * r + 0.7152 * g + 0.0722 * b;\n}\n","import { normalizeBrandDetails, normalizeEmailHref, type NormalizedBrandDetails } from \"./shell\";\nimport { normalizeSafeHref } from \"./links\";\nimport type { BrandAction, BrandDetails, BrandNavLink, BrandTheme, CustomSocialLink } from \"./types\";\n\nconst LINK_TARGETS = new Set<NonNullable<BrandNavLink[\"target\"]>>([\"_blank\", \"_self\", \"_parent\", \"_top\"]);\nconst CTA_VARIANTS = new Set<NonNullable<BrandAction[\"variant\"]>>([\"primary\", \"secondary\", \"ghost\"]);\nconst CTA_LAYOUTS = new Set<NonNullable<BrandTheme[\"ctaLayout\"]>>([\"inline\", \"stacked\"]);\nconst THEME_KEYS = new Set<keyof BrandTheme>([\n \"primaryColor\",\n \"backgroundColor\",\n \"textColor\",\n \"fontFamily\",\n \"linkColor\",\n \"socialIconSize\",\n \"buttonTextColor\",\n \"ctaLayout\",\n \"borderRadius\",\n \"headerHeight\",\n \"footerPadding\",\n \"secondaryButtonBg\",\n \"logoHeight\",\n]);\n\ntype ValidationErrorPath = string;\n\nexport interface BrandValidationResult<T> {\n valid: boolean;\n errors: string[];\n normalized: T | null;\n}\n\nexport class BrandShellValidationError extends Error {\n readonly context: string;\n readonly errors: string[];\n\n constructor(context: string, errors: string[]) {\n super(formatValidationErrors(context, errors));\n this.name = \"BrandShellValidationError\";\n this.context = context;\n this.errors = errors;\n }\n}\n\nexport function validateBrandDetails(details: unknown): BrandValidationResult<NormalizedBrandDetails> {\n const errors: string[] = [];\n\n if (!isRecord(details)) {\n errors.push(\"details must be an object.\");\n return { valid: false, errors, normalized: null };\n }\n\n validateRequiredString(details.name, \"details.name\", errors);\n validateOptionalString(details.homeHref, \"details.homeHref\", errors);\n validateSafeHref(details.homeHref, \"details.homeHref\", errors);\n validateOptionalString(details.website, \"details.website\", errors);\n validateSafeHref(details.website, \"details.website\", errors);\n validateOptionalString(details.linkedin, \"details.linkedin\", errors);\n validateSafeHref(details.linkedin, \"details.linkedin\", errors);\n validateOptionalString(details.email, \"details.email\", errors);\n validateEmail(details.email, \"details.email\", errors);\n validateOptionalString(details.github, \"details.github\", errors);\n validateSafeHref(details.github, \"details.github\", errors);\n validateOptionalString(details.twitter, \"details.twitter\", errors);\n validateSafeHref(details.twitter, \"details.twitter\", errors);\n validateOptionalString(details.discord, \"details.discord\", errors);\n validateSafeHref(details.discord, \"details.discord\", errors);\n validateOptionalString(details.tagline, \"details.tagline\", errors);\n validateOptionalString(details.logoSrc, \"details.logoSrc\", errors);\n validateSafeHref(details.logoSrc, \"details.logoSrc\", errors);\n validateOptionalString(details.logoAlt, \"details.logoAlt\", errors);\n\n if (details.navLinks != null) {\n if (!Array.isArray(details.navLinks)) {\n errors.push(\"details.navLinks must be an array.\");\n } else {\n details.navLinks.forEach((link, index) => validateNavLink(link, `details.navLinks[${index}]`, errors));\n }\n }\n\n if (details.primaryAction != null) {\n validateAction(details.primaryAction, \"details.primaryAction\", errors);\n }\n if (details.secondaryAction != null) {\n validateAction(details.secondaryAction, \"details.secondaryAction\", errors);\n }\n\n if (details.customSocialLinks != null) {\n if (!Array.isArray(details.customSocialLinks)) {\n errors.push(\"details.customSocialLinks must be an array.\");\n } else {\n details.customSocialLinks.forEach((link, index) =>\n validateCustomSocialLink(link, `details.customSocialLinks[${index}]`, errors),\n );\n }\n }\n\n if (errors.length > 0) {\n return { valid: false, errors, normalized: null };\n }\n\n return {\n valid: true,\n errors: [],\n normalized: normalizeBrandDetails(details as unknown as BrandDetails),\n };\n}\n\nexport function validateBrandTheme(theme: unknown): BrandValidationResult<BrandTheme | null> {\n if (theme == null) {\n return {\n valid: true,\n errors: [],\n normalized: null,\n };\n }\n\n const errors: string[] = [];\n\n if (!isRecord(theme)) {\n errors.push(\"theme must be an object when provided.\");\n return { valid: false, errors, normalized: null };\n }\n\n for (const key of Object.keys(theme)) {\n if (!THEME_KEYS.has(key as keyof BrandTheme)) {\n errors.push(`theme.${key} is not a supported theme key.`);\n continue;\n }\n if (key === \"ctaLayout\") {\n validateCtaLayout(theme[key], \"theme.ctaLayout\", errors);\n continue;\n }\n validateOptionalString(theme[key], `theme.${key}`, errors);\n }\n\n if (errors.length > 0) {\n return { valid: false, errors, normalized: null };\n }\n\n return {\n valid: true,\n errors: [],\n normalized: normalizeBrandTheme(theme as BrandTheme),\n };\n}\n\nexport function assertValidBrandDetails(details: unknown, context = \"BrandDetails\"): asserts details is BrandDetails {\n const result = validateBrandDetails(details);\n if (!result.valid) {\n throw new BrandShellValidationError(context, result.errors);\n }\n}\n\nexport function assertValidBrandTheme(theme: unknown, context = \"BrandTheme\"): asserts theme is BrandTheme | null | undefined {\n const result = validateBrandTheme(theme);\n if (!result.valid) {\n throw new BrandShellValidationError(context, result.errors);\n }\n}\n\nexport function normalizeBrandTheme(theme?: BrandTheme | null): BrandTheme | null {\n if (!theme) return null;\n\n const normalized: BrandTheme = {};\n for (const key of THEME_KEYS) {\n const value = theme[key];\n if (key === \"ctaLayout\") {\n if (typeof value === \"string\" && CTA_LAYOUTS.has(value as NonNullable<BrandTheme[\"ctaLayout\"]>)) {\n normalized[key] = value as BrandTheme[\"ctaLayout\"];\n }\n continue;\n }\n\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (trimmed.length > 0) {\n normalized[key] = trimmed;\n }\n }\n }\n\n return Object.keys(normalized).length > 0 ? normalized : null;\n}\n\nexport function formatValidationErrors(context: string, errors: string[]): string {\n return `${context} validation failed:\\n${errors.map((error) => `- ${error}`).join(\"\\n\")}`;\n}\n\nfunction validateNavLink(link: unknown, path: ValidationErrorPath, errors: string[]) {\n if (!isRecord(link)) {\n errors.push(`${path} must be an object.`);\n return;\n }\n\n validateRequiredString(link.label, `${path}.label`, errors);\n validateRequiredString(link.href, `${path}.href`, errors);\n validateSafeHref(link.href, `${path}.href`, errors);\n validateOptionalString(link.ariaLabel, `${path}.ariaLabel`, errors);\n validateOptionalString(link.rel, `${path}.rel`, errors);\n validateTarget(link.target, `${path}.target`, errors);\n}\n\nfunction validateAction(action: unknown, path: ValidationErrorPath, errors: string[]) {\n if (!isRecord(action)) {\n errors.push(`${path} must be an object.`);\n return;\n }\n\n validateRequiredString(action.label, `${path}.label`, errors);\n validateRequiredString(action.href, `${path}.href`, errors);\n validateSafeHref(action.href, `${path}.href`, errors);\n validateOptionalString(action.ariaLabel, `${path}.ariaLabel`, errors);\n validateOptionalString(action.rel, `${path}.rel`, errors);\n validateTarget(action.target, `${path}.target`, errors);\n\n if (action.variant != null) {\n if (typeof action.variant !== \"string\" || !CTA_VARIANTS.has(action.variant as NonNullable<BrandAction[\"variant\"]>)) {\n errors.push(`${path}.variant must be one of: primary, secondary, ghost.`);\n }\n }\n}\n\nfunction validateCustomSocialLink(link: unknown, path: ValidationErrorPath, errors: string[]) {\n if (!isRecord(link)) {\n errors.push(`${path} must be an object.`);\n return;\n }\n\n if (typeof link.platform !== \"string\" || link.platform.trim().length === 0) {\n errors.push(`${path}.platform must be a non-empty string.`);\n }\n validateRequiredString(link.label, `${path}.label`, errors);\n validateRequiredString(link.href, `${path}.href`, errors);\n validateSafeHref(link.href, `${path}.href`, errors);\n if (link.iconSvg != null) {\n validateOptionalString(link.iconSvg, `${path}.iconSvg`, errors);\n }\n}\n\nfunction validateTarget(target: unknown, path: ValidationErrorPath, errors: string[]) {\n if (target == null) return;\n if (typeof target !== \"string\" || !LINK_TARGETS.has(target as NonNullable<BrandNavLink[\"target\"]>)) {\n errors.push(`${path} must be one of: _blank, _self, _parent, _top.`);\n }\n}\n\nfunction validateCtaLayout(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || !CTA_LAYOUTS.has(value as NonNullable<BrandTheme[\"ctaLayout\"]>)) {\n errors.push(`${path} must be one of: inline, stacked.`);\n }\n}\n\nfunction validateRequiredString(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n errors.push(`${path} must be a non-empty string.`);\n }\n}\n\nfunction validateOptionalString(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || value.trim().length === 0) {\n errors.push(`${path} must be a non-empty string when provided.`);\n }\n}\n\nfunction validateSafeHref(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || value.trim().length === 0) return;\n if (!normalizeSafeHref(value)) {\n errors.push(`${path} must use a safe URL/path (http, https, mailto, tel, or relative path).`);\n }\n}\n\nfunction validateEmail(value: unknown, path: ValidationErrorPath, errors: string[]) {\n if (value == null) return;\n if (typeof value !== \"string\" || value.trim().length === 0) return;\n if (!normalizeEmailHref(value)) {\n errors.push(`${path} must be a valid email or mailto URL.`);\n }\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"validation-D1q4yKZZ.d.mts","names":[],"sources":["../src/core/types.ts","../src/core/social.ts","../src/core/shell.ts","../src/core/validation.ts"],"mappings":"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"}
|