@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.
- package/dist/components/NavFooter/NavFooter.d.ts +9 -0
- package/dist/components/NavFooter/NavFooter.d.ts.map +1 -0
- package/dist/components/NavFooter/NavFooter.helpers.d.ts +27 -0
- package/dist/components/NavFooter/NavFooter.helpers.d.ts.map +1 -0
- package/dist/components/NavFooter/NavFooter.helpers.js +78 -0
- package/dist/components/NavFooter/NavFooter.js +251 -0
- package/dist/components/NavFooter/NavFooter.styles.d.ts +37 -0
- package/dist/components/NavFooter/NavFooter.styles.d.ts.map +1 -0
- package/dist/components/NavFooter/NavFooter.styles.js +54 -0
- package/dist/components/NavFooter/NavFooter.types.d.ts +414 -0
- package/dist/components/NavFooter/NavFooter.types.d.ts.map +1 -0
- package/dist/components/NavFooter/index.d.ts +1 -0
- package/dist/components/NavFooter/index.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterBrand.d.ts +16 -0
- package/dist/components/NavFooter/subcomponents/FooterBrand.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterBrand.js +99 -0
- package/dist/components/NavFooter/subcomponents/FooterLegalBar.d.ts +10 -0
- package/dist/components/NavFooter/subcomponents/FooterLegalBar.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterLegalBar.js +60 -0
- package/dist/components/NavFooter/subcomponents/FooterNavSection.d.ts +15 -0
- package/dist/components/NavFooter/subcomponents/FooterNavSection.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterNavSection.js +123 -0
- package/dist/components/NavFooter/subcomponents/FooterNewsletter.d.ts +9 -0
- package/dist/components/NavFooter/subcomponents/FooterNewsletter.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterNewsletter.js +95 -0
- package/dist/components/NavFooter/subcomponents/FooterOffice.d.ts +9 -0
- package/dist/components/NavFooter/subcomponents/FooterOffice.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterOffice.js +63 -0
- package/dist/components/NavFooter/subcomponents/FooterSocial.d.ts +12 -0
- package/dist/components/NavFooter/subcomponents/FooterSocial.d.ts.map +1 -0
- package/dist/components/NavFooter/subcomponents/FooterSocial.js +50 -0
- package/dist/test-mocks/next-headers.d.ts +1 -0
- package/dist/test-mocks/next-headers.d.ts.map +1 -0
- package/package.json +5 -5
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import { motion, footerChevronVariants, AnimatePresence, footerAccordionVariants } from '@timmbr/motion';
|
|
4
|
+
import { ChevronDown } from '@timmbr/icons';
|
|
5
|
+
import { cn } from '@timmbr/utils';
|
|
6
|
+
import { footerSectionTitleVariants, footerNavLinkVariants } from '../NavFooter.styles.js';
|
|
7
|
+
import { resolveNavDestination, isCrossZoneNavigation } from '../NavFooter.helpers.js';
|
|
8
|
+
import { useTimmbrConfig } from '../../../providers/TimmbrConfigProvider.js';
|
|
9
|
+
|
|
10
|
+
const FooterNavSection = ({
|
|
11
|
+
section,
|
|
12
|
+
isMobileAccordion = true,
|
|
13
|
+
isOpen = false,
|
|
14
|
+
onToggle,
|
|
15
|
+
shouldAnimate = true,
|
|
16
|
+
motionClass,
|
|
17
|
+
linkComponent: CustomLink,
|
|
18
|
+
className
|
|
19
|
+
}) => {
|
|
20
|
+
const config = useTimmbrConfig();
|
|
21
|
+
const { id, title, items = [], collapsible = true, className: sectionClass } = section;
|
|
22
|
+
const contentId = `footer-section-content-${id}`;
|
|
23
|
+
const headerId = `footer-section-header-${id}`;
|
|
24
|
+
const renderLink = (item) => {
|
|
25
|
+
if (item.render) {
|
|
26
|
+
return /* @__PURE__ */ jsx("li", { className: "list-none", children: item.render({ item }) }, item.id ?? String(item.label));
|
|
27
|
+
}
|
|
28
|
+
const resolvedHref = resolveNavDestination(item.href, item.zone, config.zones?.zones) ?? "#";
|
|
29
|
+
const requiresCrossZone = isCrossZoneNavigation(item.zone, config.zones?.currentZone, item.crossZone);
|
|
30
|
+
const isExternal = item.external || item.href.startsWith("http://") || item.href.startsWith("https://");
|
|
31
|
+
const linkContent = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32
|
+
item.icon && /* @__PURE__ */ jsx("span", { className: "shrink-0", children: item.icon }),
|
|
33
|
+
/* @__PURE__ */ jsx("span", { children: item.label }),
|
|
34
|
+
item.badge && /* @__PURE__ */ jsx("span", { className: "inline-flex items-center px-1.5 py-0.2 rounded text-[10px] font-bold bg-[#D39375] text-[#1A1714] uppercase tracking-wider", children: item.badge })
|
|
35
|
+
] });
|
|
36
|
+
const linkProps = {
|
|
37
|
+
href: resolvedHref,
|
|
38
|
+
target: item.target ?? (isExternal ? "_blank" : void 0),
|
|
39
|
+
rel: item.rel ?? (isExternal ? "noopener noreferrer" : void 0),
|
|
40
|
+
onClick: item.onClick,
|
|
41
|
+
className: cn(footerNavLinkVariants(), item.className),
|
|
42
|
+
"data-cross-zone": requiresCrossZone ? "true" : void 0,
|
|
43
|
+
"data-slot": "footer-nav-link"
|
|
44
|
+
};
|
|
45
|
+
return /* @__PURE__ */ jsx("li", { className: "list-none", children: CustomLink && !requiresCrossZone && !isExternal ? /* @__PURE__ */ jsx(CustomLink, { ...linkProps, children: linkContent }) : /* @__PURE__ */ jsx("a", { ...linkProps, children: linkContent }) }, item.id ?? String(item.label));
|
|
46
|
+
};
|
|
47
|
+
const linksList = /* @__PURE__ */ jsx(
|
|
48
|
+
"ul",
|
|
49
|
+
{
|
|
50
|
+
id: contentId,
|
|
51
|
+
role: "region",
|
|
52
|
+
"aria-labelledby": headerId,
|
|
53
|
+
className: "flex flex-col gap-3.5 pt-1 pb-3 md:py-0 list-none p-0 m-0",
|
|
54
|
+
"data-slot": "footer-nav-links-list",
|
|
55
|
+
children: items.map(renderLink)
|
|
56
|
+
}
|
|
57
|
+
);
|
|
58
|
+
return /* @__PURE__ */ jsxs(
|
|
59
|
+
"div",
|
|
60
|
+
{
|
|
61
|
+
className: cn(
|
|
62
|
+
"flex flex-col border-b border-white/10 md:border-b-0 py-3 md:py-0 transition-colors",
|
|
63
|
+
sectionClass,
|
|
64
|
+
className
|
|
65
|
+
),
|
|
66
|
+
"data-slot": "footer-nav-section",
|
|
67
|
+
"data-section-id": id,
|
|
68
|
+
children: [
|
|
69
|
+
isMobileAccordion && collapsible ? /* @__PURE__ */ jsxs("div", { className: "md:hidden", children: [
|
|
70
|
+
/* @__PURE__ */ jsxs(
|
|
71
|
+
"button",
|
|
72
|
+
{
|
|
73
|
+
id: headerId,
|
|
74
|
+
type: "button",
|
|
75
|
+
"aria-expanded": isOpen,
|
|
76
|
+
"aria-controls": contentId,
|
|
77
|
+
onClick: onToggle,
|
|
78
|
+
className: cn(
|
|
79
|
+
footerSectionTitleVariants(),
|
|
80
|
+
"py-2 cursor-pointer focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[#D39375]/50 rounded"
|
|
81
|
+
),
|
|
82
|
+
"data-slot": "footer-section-accordion-trigger",
|
|
83
|
+
children: [
|
|
84
|
+
/* @__PURE__ */ jsx("span", { children: title }),
|
|
85
|
+
/* @__PURE__ */ jsx(
|
|
86
|
+
motion.span,
|
|
87
|
+
{
|
|
88
|
+
variants: shouldAnimate ? footerChevronVariants : void 0,
|
|
89
|
+
initial: false,
|
|
90
|
+
animate: shouldAnimate ? isOpen ? "expanded" : "collapsed" : void 0,
|
|
91
|
+
className: cn(
|
|
92
|
+
"shrink-0 text-[#D39375] transition-transform duration-200",
|
|
93
|
+
!shouldAnimate && (isOpen ? "rotate-180" : "rotate-0"),
|
|
94
|
+
motionClass
|
|
95
|
+
),
|
|
96
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { size: 18, className: "stroke-[2]" })
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
]
|
|
100
|
+
}
|
|
101
|
+
),
|
|
102
|
+
/* @__PURE__ */ jsx(AnimatePresence, { initial: false, children: isOpen && /* @__PURE__ */ jsx(
|
|
103
|
+
motion.div,
|
|
104
|
+
{
|
|
105
|
+
initial: shouldAnimate ? "hidden" : false,
|
|
106
|
+
animate: shouldAnimate ? "visible" : void 0,
|
|
107
|
+
exit: shouldAnimate ? "exit" : void 0,
|
|
108
|
+
variants: shouldAnimate ? footerAccordionVariants : void 0,
|
|
109
|
+
className: cn("overflow-hidden", motionClass),
|
|
110
|
+
children: linksList
|
|
111
|
+
}
|
|
112
|
+
) })
|
|
113
|
+
] }) : null,
|
|
114
|
+
/* @__PURE__ */ jsxs("div", { className: cn(isMobileAccordion && collapsible ? "hidden md:flex flex-col gap-5" : "flex flex-col gap-5"), children: [
|
|
115
|
+
/* @__PURE__ */ jsx("div", { className: footerSectionTitleVariants(), "data-slot": "footer-section-title", children: /* @__PURE__ */ jsx("span", { children: title }) }),
|
|
116
|
+
linksList
|
|
117
|
+
] })
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
);
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export { FooterNavSection };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NavFooterNewsletterConfig } from '../NavFooter.types';
|
|
3
|
+
export interface FooterNewsletterProps {
|
|
4
|
+
newsletter?: NavFooterNewsletterConfig;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const FooterNewsletter: React.FC<FooterNewsletterProps>;
|
|
8
|
+
export default FooterNewsletter;
|
|
9
|
+
//# sourceMappingURL=FooterNewsletter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FooterNewsletter.d.ts","sourceRoot":"","sources":["../../../../src/components/NavFooter/subcomponents/FooterNewsletter.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEpE,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,yBAAyB,CAAC;IACvC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyG5D,CAAC;AAEF,eAAe,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { CheckCircle, Loader2, ArrowRight, AlertCircle } from '@timmbr/icons';
|
|
5
|
+
import { cn } from '@timmbr/utils';
|
|
6
|
+
|
|
7
|
+
const FooterNewsletter = ({
|
|
8
|
+
newsletter,
|
|
9
|
+
className
|
|
10
|
+
}) => {
|
|
11
|
+
const {
|
|
12
|
+
title = "Stay in the loop",
|
|
13
|
+
description = "Sign up for our newsletter to receive updates and exclusive offers.",
|
|
14
|
+
placeholder = "Enter your email...",
|
|
15
|
+
buttonText = "Subscribe",
|
|
16
|
+
onSubmit,
|
|
17
|
+
status: controlledStatus,
|
|
18
|
+
errorMessage = "Something went wrong. Please try again.",
|
|
19
|
+
successMessage = "Thank you for subscribing!",
|
|
20
|
+
className: newsletterClass
|
|
21
|
+
} = newsletter || {};
|
|
22
|
+
const [email, setEmail] = React.useState("");
|
|
23
|
+
const [internalStatus, setInternalStatus] = React.useState("idle");
|
|
24
|
+
const currentStatus = controlledStatus !== void 0 ? controlledStatus : internalStatus;
|
|
25
|
+
const handleSubmit = async (e) => {
|
|
26
|
+
e.preventDefault();
|
|
27
|
+
if (!email || !email.includes("@") || currentStatus === "loading") return;
|
|
28
|
+
if (onSubmit) {
|
|
29
|
+
try {
|
|
30
|
+
setInternalStatus("loading");
|
|
31
|
+
await onSubmit(email);
|
|
32
|
+
setInternalStatus("success");
|
|
33
|
+
setEmail("");
|
|
34
|
+
} catch {
|
|
35
|
+
setInternalStatus("error");
|
|
36
|
+
}
|
|
37
|
+
} else {
|
|
38
|
+
setInternalStatus("success");
|
|
39
|
+
setEmail("");
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"div",
|
|
44
|
+
{
|
|
45
|
+
className: cn("flex flex-col gap-3 max-w-[420px]", newsletterClass, className),
|
|
46
|
+
"data-slot": "footer-newsletter",
|
|
47
|
+
children: [
|
|
48
|
+
title && /* @__PURE__ */ jsx("div", { className: "font-title text-xs font-semibold text-[#D39375] uppercase tracking-[0.14em]", children: title }),
|
|
49
|
+
description && /* @__PURE__ */ jsx("p", { className: "text-sm font-sans text-[#B7AEA2] m-0 leading-relaxed", children: description }),
|
|
50
|
+
currentStatus === "success" ? /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 p-3 rounded-lg bg-[#4E8752]/20 border border-[#4E8752]/40 text-[#4E8752] text-sm font-sans", children: [
|
|
51
|
+
/* @__PURE__ */ jsx(CheckCircle, { size: 18, className: "shrink-0" }),
|
|
52
|
+
/* @__PURE__ */ jsx("span", { children: successMessage })
|
|
53
|
+
] }) : /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-2", children: [
|
|
54
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center rounded-lg bg-black/40 border border-white/15 focus-within:border-[#D39375] focus-within:ring-2 focus-within:ring-[#D39375]/30 transition-all p-1", children: [
|
|
55
|
+
/* @__PURE__ */ jsx(
|
|
56
|
+
"input",
|
|
57
|
+
{
|
|
58
|
+
type: "email",
|
|
59
|
+
value: email,
|
|
60
|
+
onChange: (e) => {
|
|
61
|
+
setEmail(e.target.value);
|
|
62
|
+
if (currentStatus === "error") setInternalStatus("idle");
|
|
63
|
+
},
|
|
64
|
+
placeholder,
|
|
65
|
+
required: true,
|
|
66
|
+
disabled: currentStatus === "loading",
|
|
67
|
+
className: "flex-1 bg-transparent px-3 py-2 text-sm text-[#F7F1E6] placeholder-[#B7AEA2]/60 focus:outline-none disabled:opacity-50",
|
|
68
|
+
"data-slot": "footer-newsletter-input"
|
|
69
|
+
}
|
|
70
|
+
),
|
|
71
|
+
/* @__PURE__ */ jsx(
|
|
72
|
+
"button",
|
|
73
|
+
{
|
|
74
|
+
type: "submit",
|
|
75
|
+
disabled: currentStatus === "loading" || !email,
|
|
76
|
+
className: "inline-flex items-center justify-center gap-1.5 px-4 py-2 rounded-md bg-[#D39375] text-[#1A1714] font-title text-xs font-semibold uppercase tracking-wider hover:bg-[#D39375]/90 transition-all disabled:opacity-40 disabled:cursor-not-allowed cursor-pointer shrink-0",
|
|
77
|
+
"data-slot": "footer-newsletter-button",
|
|
78
|
+
children: currentStatus === "loading" ? /* @__PURE__ */ jsx(Loader2, { size: 16, className: "animate-spin" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
79
|
+
/* @__PURE__ */ jsx("span", { children: buttonText }),
|
|
80
|
+
/* @__PURE__ */ jsx(ArrowRight, { size: 14, className: "stroke-[2.5]" })
|
|
81
|
+
] })
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
] }),
|
|
85
|
+
currentStatus === "error" && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-red-400", children: [
|
|
86
|
+
/* @__PURE__ */ jsx(AlertCircle, { size: 14, className: "shrink-0" }),
|
|
87
|
+
/* @__PURE__ */ jsx("span", { children: errorMessage })
|
|
88
|
+
] })
|
|
89
|
+
] })
|
|
90
|
+
]
|
|
91
|
+
}
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
export { FooterNewsletter };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NavFooterOfficeConfig } from '../NavFooter.types';
|
|
3
|
+
export interface FooterOfficeProps {
|
|
4
|
+
office?: NavFooterOfficeConfig;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare const FooterOffice: React.FC<FooterOfficeProps>;
|
|
8
|
+
export default FooterOffice;
|
|
9
|
+
//# sourceMappingURL=FooterOffice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FooterOffice.d.ts","sourceRoot":"","sources":["../../../../src/components/NavFooter/subcomponents/FooterOffice.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAC;AAGhE,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA+DpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { cn } from '@timmbr/utils';
|
|
4
|
+
import { footerOfficeBlockVariants } from '../NavFooter.styles.js';
|
|
5
|
+
|
|
6
|
+
const FooterOffice = ({ office, className }) => {
|
|
7
|
+
const {
|
|
8
|
+
title = "Registered Office:",
|
|
9
|
+
address = "Timmbr Furnitures SABN Kallappa Layout, Ashwini Extenstion, Chintamani Karnataka 563125",
|
|
10
|
+
email,
|
|
11
|
+
phone,
|
|
12
|
+
extraContent,
|
|
13
|
+
className: officeClass
|
|
14
|
+
} = office || {};
|
|
15
|
+
return /* @__PURE__ */ jsxs(
|
|
16
|
+
"div",
|
|
17
|
+
{
|
|
18
|
+
className: cn("flex flex-col gap-2 max-w-[320px]", officeClass, className),
|
|
19
|
+
"data-slot": "footer-office",
|
|
20
|
+
children: [
|
|
21
|
+
title && /* @__PURE__ */ jsx(
|
|
22
|
+
"div",
|
|
23
|
+
{
|
|
24
|
+
className: "font-bold text-sm text-[#F7F1E6]/90 font-sans select-text",
|
|
25
|
+
"data-slot": "footer-office-title",
|
|
26
|
+
children: title
|
|
27
|
+
}
|
|
28
|
+
),
|
|
29
|
+
address && /* @__PURE__ */ jsx(
|
|
30
|
+
"div",
|
|
31
|
+
{
|
|
32
|
+
className: cn(footerOfficeBlockVariants(), "select-text text-sm"),
|
|
33
|
+
"data-slot": "footer-office-address",
|
|
34
|
+
children: typeof address === "string" ? /* @__PURE__ */ jsx("p", { className: "m-0 leading-relaxed whitespace-pre-line", children: address }) : address
|
|
35
|
+
}
|
|
36
|
+
),
|
|
37
|
+
(email || phone) && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1 pt-1 text-xs text-[#B7AEA2] font-sans", children: [
|
|
38
|
+
email && /* @__PURE__ */ jsx(
|
|
39
|
+
"a",
|
|
40
|
+
{
|
|
41
|
+
href: `mailto:${email}`,
|
|
42
|
+
className: "hover:text-[#D39375] transition-colors inline-block select-text",
|
|
43
|
+
"data-slot": "footer-office-email",
|
|
44
|
+
children: email
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
phone && /* @__PURE__ */ jsx(
|
|
48
|
+
"a",
|
|
49
|
+
{
|
|
50
|
+
href: `tel:${phone.replace(/\s+/g, "")}`,
|
|
51
|
+
className: "hover:text-[#D39375] transition-colors inline-block select-text",
|
|
52
|
+
"data-slot": "footer-office-phone",
|
|
53
|
+
children: phone
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
] }),
|
|
57
|
+
extraContent
|
|
58
|
+
]
|
|
59
|
+
}
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export { FooterOffice };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import type { NavFooterSocialLink } from '../NavFooter.types';
|
|
3
|
+
export interface FooterSocialProps {
|
|
4
|
+
links?: NavFooterSocialLink[];
|
|
5
|
+
title?: React.ReactNode;
|
|
6
|
+
shouldAnimate?: boolean;
|
|
7
|
+
motionClass?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const FooterSocial: React.FC<FooterSocialProps>;
|
|
11
|
+
export default FooterSocial;
|
|
12
|
+
//# sourceMappingURL=FooterSocial.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FooterSocial.d.ts","sourceRoot":"","sources":["../../../../src/components/NavFooter/subcomponents/FooterSocial.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAI9D,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,EAAE,mBAAmB,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACxB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CAsDpD,CAAC;AAEF,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { motion, footerSocialHoverVariants } from '@timmbr/motion';
|
|
4
|
+
import { cn } from '@timmbr/utils';
|
|
5
|
+
import { footerSocialButtonVariants } from '../NavFooter.styles.js';
|
|
6
|
+
import { DefaultSocialIcons } from '../NavFooter.helpers.js';
|
|
7
|
+
|
|
8
|
+
const FooterSocial = ({
|
|
9
|
+
links = [],
|
|
10
|
+
title,
|
|
11
|
+
shouldAnimate = true,
|
|
12
|
+
motionClass,
|
|
13
|
+
className
|
|
14
|
+
}) => {
|
|
15
|
+
if (!links || links.length === 0) return null;
|
|
16
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-3", className), "data-slot": "footer-social", children: [
|
|
17
|
+
title && /* @__PURE__ */ jsx("div", { className: "text-xs font-semibold text-[#D39375] uppercase tracking-[0.14em] font-title", children: title }),
|
|
18
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-4 sm:gap-6 flex-wrap", "data-slot": "footer-social-icons", children: links.map((link) => {
|
|
19
|
+
const platformKey = link.name.toLowerCase();
|
|
20
|
+
const iconElement = link.icon ?? DefaultSocialIcons[platformKey] ?? /* @__PURE__ */ jsx("span", { className: "text-sm uppercase font-bold", children: link.name.slice(0, 2) });
|
|
21
|
+
const defaultAria = `Follow us on ${link.name.charAt(0).toUpperCase() + link.name.slice(1)}`;
|
|
22
|
+
return /* @__PURE__ */ jsx(
|
|
23
|
+
motion.a,
|
|
24
|
+
{
|
|
25
|
+
href: link.href,
|
|
26
|
+
target: link.target ?? "_blank",
|
|
27
|
+
rel: link.rel ?? "noopener noreferrer",
|
|
28
|
+
"aria-label": link.ariaLabel ?? defaultAria,
|
|
29
|
+
onClick: link.onClick,
|
|
30
|
+
variants: shouldAnimate ? footerSocialHoverVariants : void 0,
|
|
31
|
+
initial: "initial",
|
|
32
|
+
whileHover: shouldAnimate ? "hover" : void 0,
|
|
33
|
+
whileTap: shouldAnimate ? "tap" : void 0,
|
|
34
|
+
className: cn(
|
|
35
|
+
footerSocialButtonVariants(),
|
|
36
|
+
"relative p-1.5 text-[#D39375] hover:text-[#F7F1E6] transition-colors",
|
|
37
|
+
motionClass,
|
|
38
|
+
link.className
|
|
39
|
+
),
|
|
40
|
+
"data-slot": "footer-social-link",
|
|
41
|
+
"data-platform": link.name,
|
|
42
|
+
children: iconElement
|
|
43
|
+
},
|
|
44
|
+
`${link.name}-${link.href}`
|
|
45
|
+
);
|
|
46
|
+
}) })
|
|
47
|
+
] });
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export { FooterSocial };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=next-headers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"next-headers.d.ts","sourceRoot":"","sources":["../../src/test-mocks/next-headers.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timmbr/ui",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "High-performance, Next.js App Router-compatible UI design system components for Timmbr",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -41,11 +41,11 @@
|
|
|
41
41
|
"@radix-ui/react-toast": "^1.2.23",
|
|
42
42
|
"@radix-ui/react-tooltip": "^1.2.16",
|
|
43
43
|
"class-variance-authority": "^0.7.1",
|
|
44
|
+
"@timmbr/motion": "1.2.0",
|
|
45
|
+
"@timmbr/icons": "1.2.1",
|
|
44
46
|
"@timmbr/hooks": "1.0.0-beta",
|
|
45
|
-
"@timmbr/
|
|
46
|
-
"@timmbr/utils": "1.
|
|
47
|
-
"@timmbr/icons": "1.2.0",
|
|
48
|
-
"@timmbr/theme": "1.1.0"
|
|
47
|
+
"@timmbr/theme": "1.2.0",
|
|
48
|
+
"@timmbr/utils": "1.2.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"next": ">=13.0.0 || >=14.0.0 || >=15.0.0 || >=16.0.0",
|