brand-shell 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/Header.tsx","../src/Footer.tsx","../src/core/social.ts","../src/core/shell.ts","../src/core/dev.ts","../src/core/theme.ts","../src/core/validation.ts"],"mappings":";;;;UAqBiB,WAAA;EACf,OAAA,EAAS,YAAA;EACT,KAAA,GAAQ,UAAA;EACR,SAAA;AAAA;AAAA,iBAGc,MAAA,CAAA;EAAS,OAAA;EAAS,KAAA;EAAO;AAAA,GAAa,WAAA,GAAW,kBAAA,CAAA,GAAA,CAAA,OAAA;;;UCNhD,WAAA;EACf,OAAA,EAAS,YAAA;EACT,KAAA,GAAQ,UAAA;EACR,SAAA;AAAA;AAAA,iBAGc,MAAA,CAAA;EAAS,OAAA;EAAS,KAAA;EAAO;AAAA,GAAa,WAAA,GAAW,kBAAA,CAAA,GAAA,CAAA,OAAA;;;KCzBrD,cAAA;AAAA,UAEK,UAAA;EACf,QAAA,EAAU,cAAA;EACV,IAAA;EACA,KAAA;AAAA;AAAA,iBAGc,oBAAA,CAAqB,OAAA,EAAS,YAAA,GAAe,UAAA;;;KCNjD,UAAA,GAAa,WAAA,CAAY,YAAA;AAAA,UAEpB,YAAA,SAAqB,YAAA;EACpC,SAAA;EACA,GAAA;EACA,MAAA,EAAQ,UAAA;AAAA;AAAA,UAGO,eAAA,SAAwB,WAAA;EACvC,SAAA;EACA,GAAA;EACA,MAAA,EAAQ,UAAA;EACR,OAAA,EAAS,WAAA,CAAY,WAAA;AAAA;AAAA,UAGN,cAAA;EACf,QAAA,EAAU,YAAA;EACV,QAAA,EAAU,eAAA;EACV,WAAA,EAAa,UAAA;AAAA;AAAA,KAGH,oBAAA,GAAuB,IAAA,CAAK,eAAA,eAA8B,IAAA,CAAK,WAAA;AAAA,UAE1D,sBAAA,SAA+B,IAAA,CAAK,YAAA;EACnD,QAAA,EAAU,YAAA;EACV,aAAA,GAAgB,oBAAA;EAChB,eAAA,GAAkB,oBAAA;AAAA;AAAA,iBAGJ,iBAAA,CAAkB,QAAA,GAAU,YAAA,KAAsB,YAAA;AAAA,iBAgBlD,qBAAA,CAAsB,OAAA,EAAS,YAAA,GAAe,sBAAA;AAAA,iBAmB9C,iBAAA,CACd,aAAA,GAAgB,WAAA,EAChB,eAAA,GAAkB,WAAA,GACjB,eAAA;AAAA,iBAkBa,mBAAA,CAAoB,OAAA,EAAS,YAAA,GAAe,cAAA;AAAA,iBAU5C,kBAAA,CAAmB,KAAA;;;iBC1FnB,mBAAA,CAAA;;;KCHJ,cAAA,GAAiB,MAAA;AAAA,iBAEb,mBAAA,CAAoB,KAAA,GAAQ,UAAA,UAAoB,cAAA;;;UCY/C,qBAAA;EACf,KAAA;EACA,MAAA;EACA,UAAA,EAAY,CAAA;AAAA;AAAA,cAGD,yBAAA,SAAkC,KAAA;EAAA,SACpC,OAAA;EAAA,SACA,MAAA;cAEG,OAAA,UAAiB,MAAA;AAAA;AAAA,iBAQf,oBAAA,CAAqB,OAAA,YAAmB,qBAAA,CAAsB,sBAAA;AAAA,iBAmD9D,kBAAA,CAAmB,KAAA,YAAiB,qBAAA,CAAsB,UAAA;AAAA,iBAuC1D,uBAAA,CAAwB,OAAA,WAAkB,OAAA,oBAAmC,OAAA,IAAW,YAAA;AAAA,iBAOxF,qBAAA,CAAsB,KAAA,WAAgB,OAAA,oBAAiC,KAAA,IAAS,UAAA;AAAA,iBAOhF,mBAAA,CAAoB,KAAA,GAAQ,UAAA,UAAoB,UAAA;AAAA,iBAwBhD,sBAAA,CAAuB,OAAA,UAAiB,MAAA"}
package/dist/index.mjs ADDED
@@ -0,0 +1,280 @@
1
+ import { a as normalizeBrandTheme, c as themeToCssVariables, d as normalizeBrandDetails, f as normalizeCtaLinks, h as detailsToSocialLinks, i as formatValidationErrors, l as shouldValidateInDev, m as normalizeNavLinks, n as assertValidBrandDetails, o as validateBrandDetails, p as normalizeGmailHref, r as assertValidBrandTheme, s as validateBrandTheme, t as BrandShellValidationError, u as buildShellViewModel } from "./validation-xdqzwr3p.mjs";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+
4
+ //#region src/react/theme.ts
5
+ function themeToStyle(theme) {
6
+ return themeToCssVariables(theme);
7
+ }
8
+
9
+ //#endregion
10
+ //#region src/icons.tsx
11
+ function GithubIcon({ className, width = "1em", height = "1em", ...props }) {
12
+ return /* @__PURE__ */ jsx("svg", {
13
+ viewBox: "0 0 24 24",
14
+ fill: "currentColor",
15
+ className,
16
+ width,
17
+ height,
18
+ ...props,
19
+ children: /* @__PURE__ */ jsx("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" })
20
+ });
21
+ }
22
+ function TwitterIcon({ className, width = "1em", height = "1em", ...props }) {
23
+ return /* @__PURE__ */ jsx("svg", {
24
+ viewBox: "0 0 24 24",
25
+ fill: "currentColor",
26
+ className,
27
+ width,
28
+ height,
29
+ ...props,
30
+ children: /* @__PURE__ */ jsx("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" })
31
+ });
32
+ }
33
+ function LinkedinIcon({ className, width = "1em", height = "1em", ...props }) {
34
+ return /* @__PURE__ */ jsx("svg", {
35
+ viewBox: "0 0 24 24",
36
+ fill: "currentColor",
37
+ className,
38
+ width,
39
+ height,
40
+ ...props,
41
+ children: /* @__PURE__ */ jsx("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" })
42
+ });
43
+ }
44
+ function DiscordIcon({ className, width = "1em", height = "1em", ...props }) {
45
+ return /* @__PURE__ */ jsx("svg", {
46
+ viewBox: "0 0 24 24",
47
+ fill: "currentColor",
48
+ className,
49
+ width,
50
+ height,
51
+ ...props,
52
+ children: /* @__PURE__ */ jsx("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" })
53
+ });
54
+ }
55
+ function MailIcon({ className, width = "1em", height = "1em", ...props }) {
56
+ return /* @__PURE__ */ jsxs("svg", {
57
+ viewBox: "0 0 24 24",
58
+ fill: "none",
59
+ stroke: "currentColor",
60
+ strokeWidth: "2",
61
+ strokeLinecap: "round",
62
+ strokeLinejoin: "round",
63
+ className,
64
+ width,
65
+ height,
66
+ ...props,
67
+ children: [/* @__PURE__ */ jsx("rect", {
68
+ width: "20",
69
+ height: "16",
70
+ x: "2",
71
+ y: "4",
72
+ rx: "2"
73
+ }), /* @__PURE__ */ jsx("path", { d: "m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7" })]
74
+ });
75
+ }
76
+ function MessageCircleIcon({ className, width = "1em", height = "1em", ...props }) {
77
+ return /* @__PURE__ */ jsx("svg", {
78
+ viewBox: "0 0 24 24",
79
+ fill: "none",
80
+ stroke: "currentColor",
81
+ strokeWidth: "2",
82
+ strokeLinecap: "round",
83
+ strokeLinejoin: "round",
84
+ className,
85
+ width,
86
+ height,
87
+ ...props,
88
+ children: /* @__PURE__ */ jsx("path", { d: "M7.9 20A9 9 0 1 0 4 16.1L2 22Z" })
89
+ });
90
+ }
91
+
92
+ //#endregion
93
+ //#region src/Header.tsx
94
+ function Header({ details, theme, className }) {
95
+ if (shouldValidateInDev()) {
96
+ assertValidBrandDetails(details, "brand-shell/Header details");
97
+ assertValidBrandTheme(theme, "brand-shell/Header theme");
98
+ }
99
+ const normalizedDetails = normalizeBrandDetails(details);
100
+ const normalizedTheme = normalizeBrandTheme(theme);
101
+ const ctaLayout = normalizedTheme?.ctaLayout === "stacked" ? "stacked" : "inline";
102
+ const style = themeToStyle(normalizedTheme);
103
+ const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(normalizedDetails);
104
+ const combinedClassName = ["brand-shell-header", className].filter(Boolean).join(" ");
105
+ const brandIdentity = normalizedDetails.homeHref ? /* @__PURE__ */ jsx("a", {
106
+ href: normalizedDetails.homeHref,
107
+ className: "brand-shell-header__name",
108
+ "aria-label": `${normalizedDetails.name} home`,
109
+ children: normalizedDetails.name
110
+ }) : /* @__PURE__ */ jsx("span", {
111
+ className: "brand-shell-header__name",
112
+ children: normalizedDetails.name
113
+ });
114
+ return /* @__PURE__ */ jsx("header", {
115
+ className: combinedClassName,
116
+ "data-brand-cta-layout": ctaLayout,
117
+ style,
118
+ role: "banner",
119
+ children: /* @__PURE__ */ jsxs("div", {
120
+ className: "brand-shell-header__inner",
121
+ children: [brandIdentity, /* @__PURE__ */ jsxs("div", {
122
+ className: "brand-shell-header__actions",
123
+ children: [
124
+ navLinks.length > 0 && /* @__PURE__ */ jsx("nav", {
125
+ className: "brand-shell-header__nav",
126
+ "aria-label": "Primary",
127
+ children: /* @__PURE__ */ jsx("ul", {
128
+ className: "brand-shell-header__list",
129
+ children: navLinks.map((link) => {
130
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
131
+ href: link.href,
132
+ className: "brand-shell-header__link",
133
+ "aria-label": link.ariaLabel,
134
+ target: link.target,
135
+ rel: link.rel,
136
+ children: link.label
137
+ }) }, link.href + link.label);
138
+ })
139
+ })
140
+ }),
141
+ ctaLinks.length > 0 && /* @__PURE__ */ jsx("div", {
142
+ className: "brand-shell-header__ctas",
143
+ children: ctaLinks.map((action) => /* @__PURE__ */ jsx("a", {
144
+ href: action.href,
145
+ className: ["brand-shell-button", `brand-shell-button--${action.variant}`].join(" "),
146
+ "aria-label": action.ariaLabel,
147
+ target: action.target,
148
+ rel: action.rel,
149
+ children: action.label
150
+ }, action.href + action.label))
151
+ }),
152
+ socialLinks.length > 0 && /* @__PURE__ */ jsx("div", {
153
+ className: "brand-shell-header__social",
154
+ "aria-label": "Social links",
155
+ children: socialLinks.map((link) => {
156
+ const Icon = SOCIAL_ICON_COMPONENTS$1[link.platform];
157
+ return /* @__PURE__ */ jsx("a", {
158
+ href: link.href,
159
+ className: "brand-shell-header__social-link",
160
+ "aria-label": link.label,
161
+ target: "_blank",
162
+ rel: "noopener noreferrer",
163
+ children: Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx("span", { children: link.label[0] })
164
+ }, link.href + link.platform);
165
+ })
166
+ })
167
+ ]
168
+ })]
169
+ })
170
+ });
171
+ }
172
+ const SOCIAL_ICON_COMPONENTS$1 = {
173
+ website: MessageCircleIcon,
174
+ linkedin: LinkedinIcon,
175
+ email: MailIcon,
176
+ github: GithubIcon,
177
+ twitter: TwitterIcon,
178
+ discord: DiscordIcon
179
+ };
180
+
181
+ //#endregion
182
+ //#region src/Footer.tsx
183
+ function Footer({ details, theme, className }) {
184
+ if (shouldValidateInDev()) {
185
+ assertValidBrandDetails(details, "brand-shell/Footer details");
186
+ assertValidBrandTheme(theme, "brand-shell/Footer theme");
187
+ }
188
+ const normalizedDetails = normalizeBrandDetails(details);
189
+ const normalizedTheme = normalizeBrandTheme(theme);
190
+ const ctaLayout = normalizedTheme?.ctaLayout === "stacked" ? "stacked" : "inline";
191
+ const style = themeToStyle(normalizedTheme);
192
+ const { navLinks, ctaLinks, socialLinks } = buildShellViewModel(normalizedDetails);
193
+ return /* @__PURE__ */ jsx("footer", {
194
+ className: ["brand-shell-footer", className].filter(Boolean).join(" "),
195
+ "data-brand-cta-layout": ctaLayout,
196
+ style,
197
+ role: "contentinfo",
198
+ children: /* @__PURE__ */ jsxs("div", {
199
+ className: "brand-shell-footer__inner",
200
+ children: [/* @__PURE__ */ jsxs("div", {
201
+ className: "brand-shell-footer__top",
202
+ children: [
203
+ /* @__PURE__ */ jsxs("div", {
204
+ className: "brand-shell-footer__brand",
205
+ children: [/* @__PURE__ */ jsx("p", {
206
+ className: "brand-shell-footer__name",
207
+ children: normalizedDetails.name
208
+ }), normalizedDetails.tagline && /* @__PURE__ */ jsx("p", {
209
+ className: "brand-shell-footer__tagline",
210
+ children: normalizedDetails.tagline
211
+ })]
212
+ }),
213
+ navLinks.length > 0 && /* @__PURE__ */ jsx("nav", {
214
+ className: "brand-shell-footer__nav",
215
+ "aria-label": "Footer",
216
+ children: /* @__PURE__ */ jsx("ul", {
217
+ className: "brand-shell-footer__list",
218
+ children: navLinks.map((link) => {
219
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("a", {
220
+ href: link.href,
221
+ className: "brand-shell-footer__link",
222
+ "aria-label": link.ariaLabel,
223
+ target: link.target,
224
+ rel: link.rel,
225
+ children: link.label
226
+ }) }, link.href + link.label);
227
+ })
228
+ })
229
+ }),
230
+ ctaLinks.length > 0 && /* @__PURE__ */ jsx("div", {
231
+ className: "brand-shell-footer__ctas",
232
+ children: ctaLinks.map((action) => /* @__PURE__ */ jsx("a", {
233
+ href: action.href,
234
+ className: ["brand-shell-button", `brand-shell-button--${action.variant}`].join(" "),
235
+ "aria-label": action.ariaLabel,
236
+ target: action.target,
237
+ rel: action.rel,
238
+ children: action.label
239
+ }, action.href + action.label))
240
+ }),
241
+ socialLinks.length > 0 && /* @__PURE__ */ jsx("div", {
242
+ className: "brand-shell-footer__social",
243
+ "aria-label": "Social links",
244
+ children: socialLinks.map((link) => {
245
+ const Icon = SOCIAL_ICON_COMPONENTS[link.platform];
246
+ return /* @__PURE__ */ jsx("a", {
247
+ href: link.href,
248
+ className: "brand-shell-footer__social-link",
249
+ "aria-label": link.label,
250
+ target: "_blank",
251
+ rel: "noopener noreferrer",
252
+ children: Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": "true" }) : /* @__PURE__ */ jsx("span", { children: link.label[0] })
253
+ }, link.href + link.platform);
254
+ })
255
+ })
256
+ ]
257
+ }), /* @__PURE__ */ jsxs("p", {
258
+ className: "brand-shell-footer__copy",
259
+ children: [
260
+ "© ",
261
+ (/* @__PURE__ */ new Date()).getFullYear(),
262
+ " ",
263
+ normalizedDetails.name
264
+ ]
265
+ })]
266
+ })
267
+ });
268
+ }
269
+ const SOCIAL_ICON_COMPONENTS = {
270
+ website: MessageCircleIcon,
271
+ linkedin: LinkedinIcon,
272
+ email: MailIcon,
273
+ github: GithubIcon,
274
+ twitter: TwitterIcon,
275
+ discord: DiscordIcon
276
+ };
277
+
278
+ //#endregion
279
+ export { BrandShellValidationError, Footer, Header, assertValidBrandDetails, assertValidBrandTheme, buildShellViewModel, detailsToSocialLinks, formatValidationErrors, normalizeBrandDetails, normalizeBrandTheme, normalizeCtaLinks, normalizeGmailHref, normalizeNavLinks, shouldValidateInDev, themeToCssVariables, validateBrandDetails, validateBrandTheme };
280
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +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 MessageCircleIcon({ 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 <path d=\"M7.9 20A9 9 0 1 0 4 16.1L2 22Z\" />\n </svg>\n );\n}\n","import type { BrandDetails, BrandTheme } from \"./types\";\nimport {\n assertValidBrandDetails,\n assertValidBrandTheme,\n buildShellViewModel,\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 LinkedinIcon,\n MailIcon,\n MessageCircleIcon,\n TwitterIcon,\n} from \"./icons\";\n\nexport interface HeaderProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n className?: string;\n}\n\nexport function Header({ details, theme, className }: 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 } = buildShellViewModel(normalizedDetails);\n const combinedClassName = [\"brand-shell-header\", className].filter(Boolean).join(\" \");\n const brandIdentity = normalizedDetails.homeHref ? (\n <a\n href={normalizedDetails.homeHref}\n className=\"brand-shell-header__name\"\n aria-label={`${normalizedDetails.name} home`}\n >\n {normalizedDetails.name}\n </a>\n ) : (\n <span className=\"brand-shell-header__name\">{normalizedDetails.name}</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 <a\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 </a>\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 <a\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 </a>\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];\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 target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {Icon ? <Icon aria-hidden=\"true\" /> : <span>{link.label[0]}</span>}\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: MessageCircleIcon,\n linkedin: LinkedinIcon,\n email: MailIcon,\n github: GithubIcon,\n twitter: TwitterIcon,\n discord: DiscordIcon,\n};\n","import type { BrandDetails, BrandTheme } from \"./types\";\nimport {\n assertValidBrandDetails,\n assertValidBrandTheme,\n buildShellViewModel,\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 LinkedinIcon,\n MailIcon,\n MessageCircleIcon,\n TwitterIcon,\n} from \"./icons\";\n\nexport interface FooterProps {\n details: BrandDetails;\n theme?: BrandTheme | null;\n className?: string;\n}\n\nexport function Footer({ details, theme, className }: 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 } = buildShellViewModel(normalizedDetails);\n const combinedClassName = [\"brand-shell-footer\", className].filter(Boolean).join(\" \");\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 <p className=\"brand-shell-footer__name\">{normalizedDetails.name}</p>\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 <a\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 </a>\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 <a\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 </a>\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];\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 target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {Icon ? <Icon aria-hidden=\"true\" /> : <span>{link.label[0]}</span>}\n </a>\n );\n })}\n </div>\n )}\n </div>\n <p className=\"brand-shell-footer__copy\">&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: MessageCircleIcon,\n linkedin: LinkedinIcon,\n email: MailIcon,\n github: GithubIcon,\n twitter: TwitterIcon,\n discord: DiscordIcon,\n};\n"],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import { i as BrandTheme, n as BrandDetails } from "./types-PQziYg7Z.mjs";
2
+ import { BrandShellElementProps } from "./web.mjs";
3
+ import { Action } from "svelte/action";
4
+
5
+ //#region src/svelte/index.d.ts
6
+ type BrandShellSvelteProps = BrandShellElementProps;
7
+ declare const brandShell: Action<HTMLElement, BrandShellSvelteProps>;
8
+ declare function registerBrandShellSvelteElements(): {
9
+ headerTagName: string;
10
+ footerTagName: string;
11
+ };
12
+ //#endregion
13
+ export { type BrandDetails, BrandShellSvelteProps, type BrandTheme, brandShell, registerBrandShellSvelteElements };
14
+ //# sourceMappingURL=svelte.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svelte.d.mts","names":[],"sources":["../src/svelte/index.ts"],"mappings":";;;;;KAaY,qBAAA,GAAwB,sBAAA;AAAA,cAevB,UAAA,EAAY,MAAA,CAAO,WAAA,EAAa,qBAAA;AAAA,iBAW7B,gCAAA,CAAA;EAAgC,aAAA;EAAA,aAAA;AAAA"}
@@ -0,0 +1,29 @@
1
+ import { l as shouldValidateInDev, n as assertValidBrandDetails, r as assertValidBrandTheme } from "./validation-xdqzwr3p.mjs";
2
+ import { applyBrandShellProps, registerBrandShellElements } from "./web.mjs";
3
+
4
+ //#region src/svelte/index.ts
5
+ function syncProps(node, props) {
6
+ if (shouldValidateInDev()) {
7
+ assertValidBrandDetails(props.details, "brand-shell/svelte details");
8
+ assertValidBrandTheme(props.theme, "brand-shell/svelte theme");
9
+ }
10
+ applyBrandShellProps(node, {
11
+ details: props.details,
12
+ theme: props.theme ?? null,
13
+ shellClass: props.shellClass ?? null
14
+ });
15
+ }
16
+ const brandShell = (node, props) => {
17
+ registerBrandShellElements();
18
+ syncProps(node, props);
19
+ return { update(nextProps) {
20
+ syncProps(node, nextProps);
21
+ } };
22
+ };
23
+ function registerBrandShellSvelteElements() {
24
+ return registerBrandShellElements();
25
+ }
26
+
27
+ //#endregion
28
+ export { brandShell, registerBrandShellSvelteElements };
29
+ //# sourceMappingURL=svelte.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"svelte.mjs","names":[],"sources":["../src/svelte/index.ts"],"sourcesContent":["import type { Action } from \"svelte/action\";\n\nimport type { BrandDetails, BrandTheme } from \"../core\";\nimport { assertValidBrandDetails, assertValidBrandTheme, shouldValidateInDev } from \"../core\";\nimport {\n applyBrandShellProps,\n registerBrandShellElements,\n type BrandShellElementLike,\n type BrandShellElementProps,\n} from \"../web\";\n\nexport type { BrandDetails, BrandTheme } from \"../core\";\n\nexport type BrandShellSvelteProps = BrandShellElementProps;\n\nfunction syncProps(node: BrandShellElementLike, props: BrandShellSvelteProps) {\n if (shouldValidateInDev()) {\n assertValidBrandDetails(props.details, \"brand-shell/svelte details\");\n assertValidBrandTheme(props.theme, \"brand-shell/svelte theme\");\n }\n\n applyBrandShellProps(node, {\n details: props.details,\n theme: props.theme ?? null,\n shellClass: props.shellClass ?? null,\n });\n}\n\nexport const brandShell: Action<HTMLElement, BrandShellSvelteProps> = (node, props) => {\n registerBrandShellElements();\n syncProps(node as BrandShellElementLike, props);\n\n return {\n update(nextProps) {\n syncProps(node as BrandShellElementLike, nextProps);\n },\n };\n};\n\nexport function registerBrandShellSvelteElements() {\n return registerBrandShellElements();\n}\n"],"mappings":";;;;AAeA,SAAS,UAAU,MAA6B,OAA8B;AAC5E,KAAI,qBAAqB,EAAE;AACzB,0BAAwB,MAAM,SAAS,6BAA6B;AACpE,wBAAsB,MAAM,OAAO,2BAA2B;;AAGhE,sBAAqB,MAAM;EACzB,SAAS,MAAM;EACf,OAAO,MAAM,SAAS;EACtB,YAAY,MAAM,cAAc;EACjC,CAAC;;AAGJ,MAAa,cAA0D,MAAM,UAAU;AACrF,6BAA4B;AAC5B,WAAU,MAA+B,MAAM;AAE/C,QAAO,EACL,OAAO,WAAW;AAChB,YAAU,MAA+B,UAAU;IAEtD;;AAGH,SAAgB,mCAAmC;AACjD,QAAO,4BAA4B"}
@@ -0,0 +1,81 @@
1
+ //#region src/core/types.d.ts
2
+ /**
3
+ * Schema for header/footer content. Caller passes these; package does not store them.
4
+ */
5
+ interface BrandNavLink {
6
+ /** Visible label (e.g. Blog, Docs, About) */
7
+ label: string;
8
+ /** Destination URL or path */
9
+ href: string;
10
+ /** Optional custom aria-label for accessibility */
11
+ ariaLabel?: string;
12
+ /** Optional target attribute (defaults to _self) */
13
+ target?: "_blank" | "_self" | "_parent" | "_top";
14
+ /** Optional rel attribute (e.g. noopener) */
15
+ rel?: string;
16
+ }
17
+ interface BrandAction {
18
+ /** Visible label on the CTA button */
19
+ label: string;
20
+ /** URL the CTA points to */
21
+ href: string;
22
+ /** Optional aria-label override */
23
+ ariaLabel?: string;
24
+ /** Optional target attribute */
25
+ target?: "_blank" | "_self" | "_parent" | "_top";
26
+ /** Optional rel attribute */
27
+ rel?: string;
28
+ /** Style variant hint */
29
+ variant?: "primary" | "secondary" | "ghost";
30
+ }
31
+ interface BrandDetails {
32
+ /** Display name (e.g. in header and footer) */
33
+ name: string;
34
+ /** Optional home URL (header name links here when set) */
35
+ homeHref?: string;
36
+ /** Primary nav links shown in the header/footer text nav */
37
+ navLinks?: BrandNavLink[];
38
+ /** Optional highlighted CTA button */
39
+ primaryAction?: BrandAction;
40
+ /** Optional secondary CTA button */
41
+ secondaryAction?: BrandAction;
42
+ /** LinkedIn profile URL */
43
+ linkedin?: string;
44
+ /** Email address (e.g. mailto: or plain) */
45
+ gmail?: string;
46
+ /** GitHub profile URL */
47
+ github?: string;
48
+ /** Twitter/X profile URL */
49
+ twitter?: string;
50
+ /** Discord community or profile URL */
51
+ discord?: string;
52
+ /** Personal or site website URL */
53
+ website?: string;
54
+ /** Optional tagline (e.g. in footer) */
55
+ tagline?: string;
56
+ }
57
+ /**
58
+ * Optional theme to adapt branding without custom CSS.
59
+ * Applied as CSS custom properties on the component root.
60
+ */
61
+ interface BrandTheme {
62
+ /** Accent/link hover and active state color */
63
+ primaryColor?: string;
64
+ /** Header/footer background color */
65
+ backgroundColor?: string;
66
+ /** Main text color (name, nav labels) */
67
+ textColor?: string;
68
+ /** Font stack for header/footer */
69
+ fontFamily?: string;
70
+ /** Link default color (defaults from primaryColor if omitted) */
71
+ linkColor?: string;
72
+ /** Size for social icon buttons (e.g. 2rem, 32px) */
73
+ socialIconSize?: string;
74
+ /** Optional override for primary CTA text color */
75
+ buttonTextColor?: string;
76
+ /** Mobile CTA arrangement: side-by-side (`inline`) or one-per-row (`stacked`) */
77
+ ctaLayout?: "inline" | "stacked";
78
+ }
79
+ //#endregion
80
+ export { BrandTheme as i, BrandDetails as n, BrandNavLink as r, BrandAction as t };
81
+ //# sourceMappingURL=types-PQziYg7Z.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-PQziYg7Z.d.mts","names":[],"sources":["../src/core/types.ts"],"mappings":";;AAGA;;UAAiB,YAAA;EAAY;EAE3B,KAAA;EAEA;EAAA,IAAA;EAIA;EAFA,SAAA;EAIG;EAFH,MAAA;EAKe;EAHf,GAAA;AAAA;AAAA,UAGe,WAAA;EAEf;EAAA,KAAA;EAIA;EAFA,IAAA;EAMA;EAJA,SAAA;EAMO;EAJP,MAAA;EAOe;EALf,GAAA;;EAEA,OAAA;AAAA;AAAA,UAGe,YAAA;EAUc;EAR7B,IAAA;EAAA;EAEA,QAAA;EAEA;EAAA,QAAA,GAAW,YAAA;EAEX;EAAA,aAAA,GAAgB,WAAA;EAEhB;EAAA,eAAA,GAAkB,WAAA;EAElB;EAAA,QAAA;EAIA;EAFA,KAAA;EAMA;EAJA,MAAA;EAQA;EANA,OAAA;EAMO;EAJP,OAAA;EAWyB;EATzB,OAAA;EASyB;EAPzB,OAAA;AAAA;;;;;UAOe,UAAA;EAgBf;EAdA,YAAA;EAcS;EAZT,eAAA;;EAEA,SAAA;;EAEA,UAAA;;EAEA,SAAA;;EAEA,cAAA;;EAEA,eAAA;;EAEA,SAAA;AAAA"}