@timmbr/ui 1.3.1 → 1.4.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.
Files changed (34) hide show
  1. package/dist/components/NavFooter/NavFooter.d.ts +9 -0
  2. package/dist/components/NavFooter/NavFooter.d.ts.map +1 -0
  3. package/dist/components/NavFooter/NavFooter.helpers.d.ts +27 -0
  4. package/dist/components/NavFooter/NavFooter.helpers.d.ts.map +1 -0
  5. package/dist/components/NavFooter/NavFooter.helpers.js +78 -0
  6. package/dist/components/NavFooter/NavFooter.js +251 -0
  7. package/dist/components/NavFooter/NavFooter.styles.d.ts +37 -0
  8. package/dist/components/NavFooter/NavFooter.styles.d.ts.map +1 -0
  9. package/dist/components/NavFooter/NavFooter.styles.js +54 -0
  10. package/dist/components/NavFooter/NavFooter.types.d.ts +414 -0
  11. package/dist/components/NavFooter/NavFooter.types.d.ts.map +1 -0
  12. package/dist/components/NavFooter/index.d.ts +1 -0
  13. package/dist/components/NavFooter/index.d.ts.map +1 -0
  14. package/dist/components/NavFooter/subcomponents/FooterBrand.d.ts +16 -0
  15. package/dist/components/NavFooter/subcomponents/FooterBrand.d.ts.map +1 -0
  16. package/dist/components/NavFooter/subcomponents/FooterBrand.js +99 -0
  17. package/dist/components/NavFooter/subcomponents/FooterLegalBar.d.ts +10 -0
  18. package/dist/components/NavFooter/subcomponents/FooterLegalBar.d.ts.map +1 -0
  19. package/dist/components/NavFooter/subcomponents/FooterLegalBar.js +60 -0
  20. package/dist/components/NavFooter/subcomponents/FooterNavSection.d.ts +15 -0
  21. package/dist/components/NavFooter/subcomponents/FooterNavSection.d.ts.map +1 -0
  22. package/dist/components/NavFooter/subcomponents/FooterNavSection.js +123 -0
  23. package/dist/components/NavFooter/subcomponents/FooterNewsletter.d.ts +9 -0
  24. package/dist/components/NavFooter/subcomponents/FooterNewsletter.d.ts.map +1 -0
  25. package/dist/components/NavFooter/subcomponents/FooterNewsletter.js +95 -0
  26. package/dist/components/NavFooter/subcomponents/FooterOffice.d.ts +9 -0
  27. package/dist/components/NavFooter/subcomponents/FooterOffice.d.ts.map +1 -0
  28. package/dist/components/NavFooter/subcomponents/FooterOffice.js +63 -0
  29. package/dist/components/NavFooter/subcomponents/FooterSocial.d.ts +12 -0
  30. package/dist/components/NavFooter/subcomponents/FooterSocial.d.ts.map +1 -0
  31. package/dist/components/NavFooter/subcomponents/FooterSocial.js +50 -0
  32. package/dist/test-mocks/next-headers.d.ts +1 -0
  33. package/dist/test-mocks/next-headers.d.ts.map +1 -0
  34. package/package.json +5 -5
@@ -0,0 +1,414 @@
1
+ import * as React from 'react';
2
+ import type { MotionProps } from '../../types/motion';
3
+ /**
4
+ * Single navigation or legal link item in the footer.
5
+ */
6
+ export interface NavFooterLinkItem {
7
+ /**
8
+ * Unique identifier for the link.
9
+ */
10
+ id?: string;
11
+ /**
12
+ * Display label for the link.
13
+ */
14
+ label: React.ReactNode;
15
+ /**
16
+ * Destination URL.
17
+ */
18
+ href: string;
19
+ /**
20
+ * Optional zone for multi-zone micro-frontend navigation.
21
+ */
22
+ zone?: string;
23
+ /**
24
+ * Force cross-zone full page transition even if zone matches.
25
+ */
26
+ crossZone?: boolean;
27
+ /**
28
+ * Standard anchor target (e.g., '_blank').
29
+ */
30
+ target?: string;
31
+ /**
32
+ * Standard anchor rel attribute.
33
+ */
34
+ rel?: string;
35
+ /**
36
+ * Optional badge indicator (e.g., 'NEW', 'SALE').
37
+ */
38
+ badge?: React.ReactNode;
39
+ /**
40
+ * Leading or trailing icon.
41
+ */
42
+ icon?: React.ReactNode;
43
+ /**
44
+ * Marks as external link (auto sets target="_blank" and rel="noopener noreferrer").
45
+ */
46
+ external?: boolean;
47
+ /**
48
+ * Custom click handler.
49
+ */
50
+ onClick?: (e: React.MouseEvent<HTMLElement>) => void;
51
+ /**
52
+ * Additional CSS classes for this link.
53
+ */
54
+ className?: string;
55
+ /**
56
+ * Custom render function override for this item.
57
+ */
58
+ render?: (props: {
59
+ item: NavFooterLinkItem;
60
+ }) => React.ReactNode;
61
+ }
62
+ /**
63
+ * Column of navigation links in the footer (e.g., Shop, Craft, Help).
64
+ */
65
+ export interface NavFooterSection {
66
+ /**
67
+ * Unique identifier for the section.
68
+ */
69
+ id: string;
70
+ /**
71
+ * Column section title (e.g. 'SHOP', 'CRAFT', 'HELP').
72
+ */
73
+ title: React.ReactNode;
74
+ /**
75
+ * List of links within this section.
76
+ */
77
+ items: NavFooterLinkItem[];
78
+ /**
79
+ * Whether this section can collapse into an accordion on mobile viewports.
80
+ * @default true
81
+ */
82
+ collapsible?: boolean;
83
+ /**
84
+ * Initial open state on mobile accordion.
85
+ * @default false
86
+ */
87
+ defaultOpen?: boolean;
88
+ /**
89
+ * Optional custom className for the column container.
90
+ */
91
+ className?: string;
92
+ }
93
+ /**
94
+ * Social media link item in the footer.
95
+ */
96
+ export interface NavFooterSocialLink {
97
+ /**
98
+ * Platform identifier or name ('instagram' | 'facebook' | 'linkedin' | 'x' | 'twitter' | 'youtube' | 'pinterest' | string).
99
+ */
100
+ name: 'instagram' | 'facebook' | 'linkedin' | 'x' | 'twitter' | 'youtube' | 'pinterest' | string;
101
+ /**
102
+ * Target URL for the social profile.
103
+ */
104
+ href: string;
105
+ /**
106
+ * Custom icon element. If not provided, a built-in SVG is used for recognized platforms.
107
+ */
108
+ icon?: React.ReactNode;
109
+ /**
110
+ * Accessible ARIA label for screen readers.
111
+ */
112
+ ariaLabel?: string;
113
+ /**
114
+ * Target attribute (default: '_blank').
115
+ */
116
+ target?: string;
117
+ /**
118
+ * Rel attribute (default: 'noopener noreferrer').
119
+ */
120
+ rel?: string;
121
+ /**
122
+ * Custom click handler.
123
+ */
124
+ onClick?: (e: React.MouseEvent<HTMLElement>) => void;
125
+ /**
126
+ * Additional CSS classes for this social link icon.
127
+ */
128
+ className?: string;
129
+ }
130
+ /**
131
+ * Brand logo and tagline configuration.
132
+ */
133
+ export interface NavFooterBranding {
134
+ /**
135
+ * Brand logo node or image.
136
+ */
137
+ logo?: React.ReactNode;
138
+ /**
139
+ * Short tagline or description below the logo.
140
+ */
141
+ description?: React.ReactNode;
142
+ /**
143
+ * Destination URL when clicking the logo (default: '/').
144
+ */
145
+ href?: string;
146
+ /**
147
+ * Optional zone for multi-zone micro-frontend routing.
148
+ */
149
+ zone?: string;
150
+ /**
151
+ * Alt text / ARIA label for the logo link.
152
+ */
153
+ alt?: string;
154
+ /**
155
+ * Additional CSS classes for the brand block.
156
+ */
157
+ className?: string;
158
+ /**
159
+ * Custom click handler on brand logo.
160
+ */
161
+ onClick?: (e: React.MouseEvent<HTMLElement>) => void;
162
+ }
163
+ /**
164
+ * Registered office and contact information configuration.
165
+ */
166
+ export interface NavFooterOfficeConfig {
167
+ /**
168
+ * Block title (default: 'Registered Office:').
169
+ */
170
+ title?: React.ReactNode;
171
+ /**
172
+ * Office address text or custom JSX.
173
+ */
174
+ address?: React.ReactNode;
175
+ /**
176
+ * Optional support / contact email.
177
+ */
178
+ email?: string;
179
+ /**
180
+ * Optional support phone number.
181
+ */
182
+ phone?: string;
183
+ /**
184
+ * Additional custom content rendered beneath the address.
185
+ */
186
+ extraContent?: React.ReactNode;
187
+ /**
188
+ * Additional CSS classes for the office block.
189
+ */
190
+ className?: string;
191
+ }
192
+ /**
193
+ * Newsletter subscription form configuration.
194
+ */
195
+ export interface NavFooterNewsletterConfig {
196
+ /**
197
+ * Explicit toggle to show/hide the newsletter form.
198
+ */
199
+ show?: boolean;
200
+ /**
201
+ * Title for the newsletter block (e.g. 'Stay in the loop').
202
+ */
203
+ title?: React.ReactNode;
204
+ /**
205
+ * Subtitle or explanation for the newsletter.
206
+ */
207
+ description?: React.ReactNode;
208
+ /**
209
+ * Input placeholder text.
210
+ * @default 'Enter your email...'
211
+ */
212
+ placeholder?: string;
213
+ /**
214
+ * Label for the subscribe button.
215
+ * @default 'Subscribe'
216
+ */
217
+ buttonText?: string;
218
+ /**
219
+ * Submit event handler with entered email.
220
+ */
221
+ onSubmit?: (email: string) => void | Promise<void>;
222
+ /**
223
+ * Current submission state.
224
+ */
225
+ status?: 'idle' | 'loading' | 'success' | 'error';
226
+ /**
227
+ * Error message displayed when status is 'error'.
228
+ */
229
+ errorMessage?: string;
230
+ /**
231
+ * Success message displayed when status is 'success'.
232
+ */
233
+ successMessage?: string;
234
+ /**
235
+ * Additional CSS classes for the newsletter block.
236
+ */
237
+ className?: string;
238
+ }
239
+ /**
240
+ * Legal links and copyright configuration.
241
+ */
242
+ export interface NavFooterLegalConfig {
243
+ /**
244
+ * Copyright text (default: '© {year} Timmbr Furniture Co.').
245
+ */
246
+ copyright?: React.ReactNode;
247
+ /**
248
+ * List of legal policy links (e.g., Privacy, Terms, Cookies).
249
+ */
250
+ links?: NavFooterLinkItem[];
251
+ /**
252
+ * Additional JSX rendered on the legal bar.
253
+ */
254
+ extra?: React.ReactNode;
255
+ /**
256
+ * Additional CSS classes for the legal bar.
257
+ */
258
+ className?: string;
259
+ }
260
+ /**
261
+ * Mobile-specific behavior configuration.
262
+ */
263
+ export interface NavFooterMobileConfig {
264
+ /**
265
+ * Whether navigation sections collapse into accordions on mobile (< 768px).
266
+ * @default true
267
+ */
268
+ accordion?: boolean;
269
+ /**
270
+ * Whether multiple accordion sections can be open simultaneously on mobile.
271
+ * @default true
272
+ */
273
+ allowMultipleOpen?: boolean;
274
+ }
275
+ /**
276
+ * Modular Navigation Configuration Object.
277
+ */
278
+ export interface NavFooterNavigationConfig {
279
+ /**
280
+ * Array of column sections.
281
+ */
282
+ sections: NavFooterSection[];
283
+ /**
284
+ * Master visibility toggle for the navigation columns.
285
+ * @default true
286
+ */
287
+ show?: boolean;
288
+ }
289
+ /**
290
+ * Modular Social Configuration Object.
291
+ */
292
+ export interface NavFooterSocialConfig {
293
+ /**
294
+ * Array of social links.
295
+ */
296
+ links: NavFooterSocialLink[];
297
+ /**
298
+ * Optional title above the social icons.
299
+ */
300
+ title?: React.ReactNode;
301
+ /**
302
+ * Master visibility toggle for social links.
303
+ * @default true
304
+ */
305
+ show?: boolean;
306
+ }
307
+ /**
308
+ * Comprehensive Props for the `NavFooter` component.
309
+ */
310
+ export interface NavFooterProps extends MotionProps {
311
+ /**
312
+ * Brand logo and tagline description.
313
+ */
314
+ branding?: NavFooterBranding;
315
+ /**
316
+ * Structured navigation columns config or array of sections.
317
+ */
318
+ navigation?: NavFooterNavigationConfig | NavFooterSection[];
319
+ /**
320
+ * Structured social media configuration or array of social links.
321
+ */
322
+ social?: NavFooterSocialConfig | NavFooterSocialLink[];
323
+ /**
324
+ * Registered office and contact information configuration.
325
+ */
326
+ office?: NavFooterOfficeConfig & {
327
+ show?: boolean;
328
+ };
329
+ /**
330
+ * Optional newsletter subscription configuration.
331
+ */
332
+ newsletter?: NavFooterNewsletterConfig;
333
+ /**
334
+ * Legal policy links and copyright configuration.
335
+ */
336
+ legal?: NavFooterLegalConfig & {
337
+ show?: boolean;
338
+ };
339
+ /**
340
+ * Mobile-specific accordion behavior settings.
341
+ */
342
+ mobile?: NavFooterMobileConfig;
343
+ /**
344
+ * Shorthand brand logo node.
345
+ */
346
+ logo?: React.ReactNode;
347
+ /**
348
+ * Shorthand brand tagline description.
349
+ */
350
+ description?: React.ReactNode;
351
+ /**
352
+ * Shorthand array of navigation sections.
353
+ */
354
+ sections?: NavFooterSection[];
355
+ /**
356
+ * Shorthand array of social links.
357
+ */
358
+ socialLinks?: NavFooterSocialLink[];
359
+ /**
360
+ * Shorthand office address node or string.
361
+ */
362
+ address?: React.ReactNode;
363
+ /**
364
+ * Shorthand office block title.
365
+ */
366
+ officeTitle?: React.ReactNode;
367
+ /**
368
+ * Shorthand copyright notice.
369
+ */
370
+ copyright?: React.ReactNode;
371
+ /**
372
+ * Shorthand legal policy links.
373
+ */
374
+ legalLinks?: NavFooterLinkItem[];
375
+ /**
376
+ * Master toggle for the entire navigation section.
377
+ * @default true
378
+ */
379
+ showNavigation?: boolean;
380
+ /**
381
+ * Master toggle for social icons.
382
+ */
383
+ showSocial?: boolean;
384
+ /**
385
+ * Master toggle for registered office block.
386
+ */
387
+ showOffice?: boolean;
388
+ /**
389
+ * Master toggle for the bottom copyright & legal bar.
390
+ */
391
+ showLegal?: boolean;
392
+ /**
393
+ * Master toggle for the optional newsletter section.
394
+ */
395
+ showNewsletter?: boolean;
396
+ /**
397
+ * Maximum container width constraint.
398
+ * @default '2xl' (1440px)
399
+ */
400
+ containerMaxWidth?: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | 'full';
401
+ /**
402
+ * Custom Link component injection (e.g. Next.js `next/link`).
403
+ */
404
+ linkComponent?: React.ComponentType<any>;
405
+ /**
406
+ * Additional root container CSS classes.
407
+ */
408
+ className?: string;
409
+ /**
410
+ * Optional custom children to append before the legal bar.
411
+ */
412
+ children?: React.ReactNode;
413
+ }
414
+ //# sourceMappingURL=NavFooter.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavFooter.types.d.ts","sourceRoot":"","sources":["../../../src/components/NavFooter/NavFooter.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/NavFooter/index.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import type { NavFooterBranding } from '../NavFooter.types';
3
+ export interface FooterBrandProps {
4
+ branding?: NavFooterBranding;
5
+ linkComponent?: React.ComponentType<any>;
6
+ className?: string;
7
+ }
8
+ /**
9
+ * Default Timmbr Brand Wordmark SVG with green sprout leaf accent.
10
+ */
11
+ export declare const DefaultFooterWordmark: React.FC<{
12
+ className?: string;
13
+ }>;
14
+ export declare const FooterBrand: React.FC<FooterBrandProps>;
15
+ export default FooterBrand;
16
+ //# sourceMappingURL=FooterBrand.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FooterBrand.d.ts","sourceRoot":"","sources":["../../../../src/components/NavFooter/subcomponents/FooterBrand.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,iBAAiB,CAAC;IAC7B,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,EAAE,KAAK,CAAC,EAAE,CAAC;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAwBlE,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC,gBAAgB,CAiElD,CAAC;AAEF,eAAe,WAAW,CAAC"}
@@ -0,0 +1,99 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { cn } from '@timmbr/utils';
4
+ import { resolveNavDestination, isCrossZoneNavigation } from '../NavFooter.helpers.js';
5
+ import { useTimmbrConfig } from '../../../providers/TimmbrConfigProvider.js';
6
+
7
+ const DefaultFooterWordmark = ({ className }) => /* @__PURE__ */ jsxs(
8
+ "svg",
9
+ {
10
+ viewBox: "0 0 201 50",
11
+ fill: "none",
12
+ xmlns: "http://www.w3.org/2000/svg",
13
+ className: cn("h-10 sm:h-11 w-auto shrink-0", className),
14
+ "aria-label": "Timmbr Logo",
15
+ children: [
16
+ /* @__PURE__ */ jsx(
17
+ "path",
18
+ {
19
+ d: "M33 9.5C33 9.5 35 2 41 2C42.5 7 38.5 12 33 13.5V9.5Z",
20
+ fill: "#4E8752"
21
+ }
22
+ ),
23
+ /* @__PURE__ */ jsx(
24
+ "text",
25
+ {
26
+ x: "0",
27
+ y: "38",
28
+ fill: "#D39375",
29
+ fontFamily: "Outfit, sans-serif",
30
+ fontWeight: "700",
31
+ fontSize: "40",
32
+ letterSpacing: "-0.02em",
33
+ children: "timmbr"
34
+ }
35
+ )
36
+ ]
37
+ }
38
+ );
39
+ const FooterBrand = ({
40
+ branding,
41
+ linkComponent: CustomLink,
42
+ className
43
+ }) => {
44
+ const config = useTimmbrConfig();
45
+ const {
46
+ logo,
47
+ description = "Solid-wood furniture, made by hand in Portland and built to be kept for life.",
48
+ href = "/",
49
+ zone,
50
+ alt = "Timmbr Home",
51
+ className: brandClass,
52
+ onClick
53
+ } = branding || {};
54
+ const resolvedHref = resolveNavDestination(href, zone, config.zones?.zones) ?? "/";
55
+ const requiresCrossZone = isCrossZoneNavigation(zone, config.zones?.currentZone);
56
+ const logoContent = logo ?? /* @__PURE__ */ jsx(DefaultFooterWordmark, {});
57
+ const logoNode = CustomLink && !requiresCrossZone ? /* @__PURE__ */ jsx(
58
+ CustomLink,
59
+ {
60
+ href: resolvedHref,
61
+ "aria-label": alt,
62
+ onClick,
63
+ className: "inline-flex items-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#D39375]/50 rounded-md transition-opacity hover:opacity-90",
64
+ "data-slot": "footer-brand-link",
65
+ children: logoContent
66
+ }
67
+ ) : /* @__PURE__ */ jsx(
68
+ "a",
69
+ {
70
+ href: resolvedHref,
71
+ "aria-label": alt,
72
+ onClick,
73
+ "data-cross-zone": requiresCrossZone ? "true" : void 0,
74
+ className: "inline-flex items-center focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#D39375]/50 rounded-md transition-opacity hover:opacity-90",
75
+ "data-slot": "footer-brand-link",
76
+ children: logoContent
77
+ }
78
+ );
79
+ return /* @__PURE__ */ jsxs(
80
+ "div",
81
+ {
82
+ className: cn("flex flex-col gap-4 items-start max-w-[320px]", brandClass, className),
83
+ "data-slot": "footer-brand",
84
+ children: [
85
+ logoNode,
86
+ description && /* @__PURE__ */ jsx(
87
+ "div",
88
+ {
89
+ className: "text-sm font-sans text-[#B7AEA2] leading-relaxed select-text",
90
+ "data-slot": "footer-brand-description",
91
+ children: typeof description === "string" ? /* @__PURE__ */ jsx("p", { className: "whitespace-pre-line m-0", children: description }) : description
92
+ }
93
+ )
94
+ ]
95
+ }
96
+ );
97
+ };
98
+
99
+ export { DefaultFooterWordmark, FooterBrand };
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import type { NavFooterLegalConfig } from '../NavFooter.types';
3
+ export interface FooterLegalBarProps {
4
+ legal?: NavFooterLegalConfig;
5
+ linkComponent?: React.ComponentType<any>;
6
+ className?: string;
7
+ }
8
+ export declare const FooterLegalBar: React.FC<FooterLegalBarProps>;
9
+ export default FooterLegalBar;
10
+ //# sourceMappingURL=FooterLegalBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FooterLegalBar.d.ts","sourceRoot":"","sources":["../../../../src/components/NavFooter/subcomponents/FooterLegalBar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,oBAAoB,EAAqB,MAAM,oBAAoB,CAAC;AAIlF,MAAM,WAAW,mBAAmB;IAClC,KAAK,CAAC,EAAE,oBAAoB,CAAC;IAC7B,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,cAAc,EAAE,KAAK,CAAC,EAAE,CAAC,mBAAmB,CAyExD,CAAC;AAEF,eAAe,cAAc,CAAC"}
@@ -0,0 +1,60 @@
1
+ "use client";
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { cn } from '@timmbr/utils';
4
+ import { footerLegalBarVariants, footerLegalLinkVariants } from '../NavFooter.styles.js';
5
+ import { DEFAULT_FOOTER_LEGAL_LINKS, resolveNavDestination, isCrossZoneNavigation } from '../NavFooter.helpers.js';
6
+ import { useTimmbrConfig } from '../../../providers/TimmbrConfigProvider.js';
7
+
8
+ const FooterLegalBar = ({
9
+ legal,
10
+ linkComponent: CustomLink,
11
+ className
12
+ }) => {
13
+ const config = useTimmbrConfig();
14
+ const currentYear = (/* @__PURE__ */ new Date()).getFullYear();
15
+ const {
16
+ copyright = `© ${currentYear} Timmbr Furniture Co.`,
17
+ links = DEFAULT_FOOTER_LEGAL_LINKS,
18
+ extra,
19
+ className: legalClass
20
+ } = legal || {};
21
+ const renderLegalLink = (item) => {
22
+ if (item.render) {
23
+ return /* @__PURE__ */ jsx("li", { className: "list-none", children: item.render({ item }) }, item.id ?? String(item.label));
24
+ }
25
+ const resolvedHref = resolveNavDestination(item.href, item.zone, config.zones?.zones) ?? "#";
26
+ const requiresCrossZone = isCrossZoneNavigation(item.zone, config.zones?.currentZone, item.crossZone);
27
+ const isExternal = item.external || item.href.startsWith("http://") || item.href.startsWith("https://");
28
+ const linkProps = {
29
+ href: resolvedHref,
30
+ target: item.target ?? (isExternal ? "_blank" : void 0),
31
+ rel: item.rel ?? (isExternal ? "noopener noreferrer" : void 0),
32
+ onClick: item.onClick,
33
+ className: cn(footerLegalLinkVariants(), item.className),
34
+ "data-cross-zone": requiresCrossZone ? "true" : void 0,
35
+ "data-slot": "footer-legal-link"
36
+ };
37
+ return /* @__PURE__ */ jsx("li", { className: "list-none", children: CustomLink && !requiresCrossZone && !isExternal ? /* @__PURE__ */ jsx(CustomLink, { ...linkProps, children: item.label }) : /* @__PURE__ */ jsx("a", { ...linkProps, children: item.label }) }, item.id ?? String(item.label));
38
+ };
39
+ return /* @__PURE__ */ jsxs(
40
+ "div",
41
+ {
42
+ className: cn(footerLegalBarVariants(), legalClass, className),
43
+ "data-slot": "footer-legal-bar",
44
+ children: [
45
+ /* @__PURE__ */ jsx("div", { className: "select-text", "data-slot": "footer-copyright", children: typeof copyright === "string" ? /* @__PURE__ */ jsx("span", { children: copyright }) : copyright }),
46
+ extra && /* @__PURE__ */ jsx("div", { className: "text-xs text-[#B7AEA2]", children: extra }),
47
+ links && links.length > 0 && /* @__PURE__ */ jsx(
48
+ "ul",
49
+ {
50
+ className: "flex items-center gap-4 sm:gap-6 flex-wrap list-none p-0 m-0",
51
+ "data-slot": "footer-legal-links",
52
+ children: links.map(renderLegalLink)
53
+ }
54
+ )
55
+ ]
56
+ }
57
+ );
58
+ };
59
+
60
+ export { FooterLegalBar };
@@ -0,0 +1,15 @@
1
+ import * as React from 'react';
2
+ import type { NavFooterSection } from '../NavFooter.types';
3
+ export interface FooterNavSectionProps {
4
+ section: NavFooterSection;
5
+ isMobileAccordion?: boolean;
6
+ isOpen?: boolean;
7
+ onToggle?: () => void;
8
+ shouldAnimate?: boolean;
9
+ motionClass?: string;
10
+ linkComponent?: React.ComponentType<any>;
11
+ className?: string;
12
+ }
13
+ export declare const FooterNavSection: React.FC<FooterNavSectionProps>;
14
+ export default FooterNavSection;
15
+ //# sourceMappingURL=FooterNavSection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FooterNavSection.d.ts","sourceRoot":"","sources":["../../../../src/components/NavFooter/subcomponents/FooterNavSection.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,KAAK,EAAE,gBAAgB,EAAqB,MAAM,oBAAoB,CAAC;AAI9E,MAAM,WAAW,qBAAqB;IACpC,OAAO,EAAE,gBAAgB,CAAC;IAC1B,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CA4I5D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}