@timmbr/ui 1.3.1 → 1.4.1
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 +5 -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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ export * from './components/Tooltip';
|
|
|
25
25
|
export * from './components/Tabs';
|
|
26
26
|
export * from './components/SideBarNavigation';
|
|
27
27
|
export * from './components/NavHeader';
|
|
28
|
+
export * from './components/NavFooter';
|
|
28
29
|
export * from './components/Button';
|
|
29
30
|
export * from './components/LinkButton';
|
|
30
31
|
export * from './components/Accordion';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC;AAG/B,cAAc,aAAa,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,gBAAgB,CAAC;AAG/B,cAAc,aAAa,CAAC;AAG5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,mBAAmB,CAAC;AAClC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AAGpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,0BAA0B,CAAC;AACzC,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AAGvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,yBAAyB,CAAC;AACxC,cAAc,wBAAwB,CAAC;AACvC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,mBAAmB,CAAC;AAClC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,oBAAoB,CAAC;AACnC,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AAGxC,cAAc,oBAAoB,CAAC;AACnC,cAAc,yBAAyB,CAAC;AACxC,cAAc,uBAAuB,CAAC;AACtC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC;AAClC,cAAc,mBAAmB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -12,6 +12,7 @@ export { Checkbox } from './components/Checkbox/Checkbox.js';
|
|
|
12
12
|
export { Chip } from './components/Chip/Chip.js';
|
|
13
13
|
export { Container } from './components/Container/Container.js';
|
|
14
14
|
export { DEFAULT_ALL_ACCEPT, DEFAULT_IMAGE_ACCEPT, DEFAULT_IMAGE_MAX_SIZE, DEFAULT_VIDEO_ACCEPT, DEFAULT_VIDEO_MAX_SIZE, GRID_COLS_MAP, VIDEO_EXTENSIONS, isVideoMedia, normalizeUploadItems, validateUploadFiles } from './components/ImageUpload/ImageUpload.helpers.js';
|
|
15
|
+
export { DEFAULT_FOOTER_LEGAL_LINKS, DEFAULT_FOOTER_SECTIONS, DEFAULT_FOOTER_SOCIAL_LINKS, isCrossZoneNavigation, resolveNavDestination } from './components/NavFooter/NavFooter.helpers.js';
|
|
15
16
|
export { DEFAULT_STORAGE_KEY, isNavItemActive, isRouteActive, readStoredCollapsed, writeStoredCollapsed } from './components/SideBarNavigation/SideBarNavigation.helpers.js';
|
|
16
17
|
export { DataList, DataListItem, DataListLabel, DataListValue } from './components/DataList/DataList.js';
|
|
17
18
|
export { Dialog, DialogBody, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger } from './components/Dialog/Dialog.js';
|
|
@@ -20,6 +21,7 @@ export { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, Dr
|
|
|
20
21
|
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from './components/Dropdown/Dropdown.js';
|
|
21
22
|
export { EmptyState } from './components/EmptyState/EmptyState.js';
|
|
22
23
|
export { FilmIcon, ImageIcon, PlayIcon, UploadCloudIcon } from './components/ImageUpload/subcomponents/ImageUploadIcons.js';
|
|
24
|
+
export { Footer, NavFooter } from './components/NavFooter/NavFooter.js';
|
|
23
25
|
export { FormField } from './components/FormField/FormField.js';
|
|
24
26
|
export { Grid } from './components/Grid/Grid.js';
|
|
25
27
|
export { Header, NavHeader } from './components/NavHeader/NavHeader.js';
|
|
@@ -88,6 +90,7 @@ export { dividerVariants } from './components/Divider/Divider.styles.js';
|
|
|
88
90
|
export { drawerContentVariants, drawerFooterVariants, drawerHeaderVariants, drawerOverlayVariants } from './components/Drawer/Drawer.styles.js';
|
|
89
91
|
export { dropdownContentVariants, dropdownItemVariants } from './components/Dropdown/Dropdown.styles.js';
|
|
90
92
|
export { emptyStateIconWrapperVariants, emptyStateVariants } from './components/EmptyState/EmptyState.styles.js';
|
|
93
|
+
export { footerLegalBarVariants, footerLegalLinkVariants, footerNavLinkVariants, footerOfficeBlockVariants, footerSectionTitleVariants, footerSocialButtonVariants, navFooterContainerVariants, navFooterRootVariants } from './components/NavFooter/NavFooter.styles.js';
|
|
91
94
|
export { formFieldVariants } from './components/FormField/FormField.styles.js';
|
|
92
95
|
export { headingVariants } from './components/Heading/Heading.styles.js';
|
|
93
96
|
export { iconVariants } from './components/Icon/Icon.styles.js';
|
|
@@ -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.1",
|
|
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",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"@radix-ui/react-tooltip": "^1.2.16",
|
|
43
43
|
"class-variance-authority": "^0.7.1",
|
|
44
44
|
"@timmbr/hooks": "1.0.0-beta",
|
|
45
|
-
"@timmbr/
|
|
46
|
-
"@timmbr/
|
|
47
|
-
"@timmbr/
|
|
48
|
-
"@timmbr/
|
|
45
|
+
"@timmbr/icons": "1.2.1",
|
|
46
|
+
"@timmbr/theme": "1.2.0",
|
|
47
|
+
"@timmbr/utils": "1.2.0",
|
|
48
|
+
"@timmbr/motion": "1.2.0"
|
|
49
49
|
},
|
|
50
50
|
"peerDependencies": {
|
|
51
51
|
"next": ">=13.0.0 || >=14.0.0 || >=15.0.0 || >=16.0.0",
|