@stackshift-ui/footer 6.0.3 → 6.0.4
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/package.json +14 -13
- package/src/footer.test.tsx +13 -0
- package/src/footer.tsx +40 -0
- package/src/footer_a.tsx +152 -0
- package/src/footer_b.tsx +154 -0
- package/src/footer_c.tsx +154 -0
- package/src/footer_d.tsx +154 -0
- package/src/helper/index.tsx +15 -0
- package/src/index.ts +8 -0
- package/src/types.ts +412 -0
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackshift-ui/footer",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "6.0.
|
|
4
|
+
"version": "6.0.4",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"module": "./dist/index.mjs",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"files": [
|
|
11
|
-
"dist/**"
|
|
11
|
+
"dist/**",
|
|
12
|
+
"src"
|
|
12
13
|
],
|
|
13
14
|
"author": "WebriQ <info@webriq.com>",
|
|
14
15
|
"devDependencies": {
|
|
@@ -33,18 +34,18 @@
|
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
36
|
"classnames": "^2.5.1",
|
|
37
|
+
"@stackshift-ui/button": "6.0.3",
|
|
38
|
+
"@stackshift-ui/system": "6.0.3",
|
|
36
39
|
"@stackshift-ui/scripts": "6.0.2",
|
|
37
|
-
"@stackshift-ui/text": "6.0.
|
|
38
|
-
"@stackshift-ui/
|
|
39
|
-
"@stackshift-ui/
|
|
40
|
-
"@stackshift-ui/
|
|
41
|
-
"@stackshift-ui/
|
|
42
|
-
"@stackshift-ui/
|
|
43
|
-
"@stackshift-ui/
|
|
44
|
-
"@stackshift-ui/
|
|
45
|
-
"@stackshift-ui/
|
|
46
|
-
"@stackshift-ui/grid": "6.0.2",
|
|
47
|
-
"@stackshift-ui/grid-item": "6.0.2"
|
|
40
|
+
"@stackshift-ui/text": "6.0.3",
|
|
41
|
+
"@stackshift-ui/image": "6.0.3",
|
|
42
|
+
"@stackshift-ui/link": "6.0.3",
|
|
43
|
+
"@stackshift-ui/section": "6.0.3",
|
|
44
|
+
"@stackshift-ui/container": "6.0.3",
|
|
45
|
+
"@stackshift-ui/flex": "6.0.3",
|
|
46
|
+
"@stackshift-ui/grid": "6.0.3",
|
|
47
|
+
"@stackshift-ui/grid-item": "6.0.3",
|
|
48
|
+
"@stackshift-ui/social-icons": "6.0.3"
|
|
48
49
|
},
|
|
49
50
|
"peerDependencies": {
|
|
50
51
|
"@types/react": "16.8 - 19",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { cleanup, render, screen } from "@testing-library/react";
|
|
2
|
+
import { afterEach, describe, test } from "vitest";
|
|
3
|
+
import { Footer } from "./footer";
|
|
4
|
+
|
|
5
|
+
describe.concurrent("footer", () => {
|
|
6
|
+
afterEach(cleanup);
|
|
7
|
+
|
|
8
|
+
test.skip("Dummy test - test if renders without errors", ({ expect }) => {
|
|
9
|
+
const clx = "my-class";
|
|
10
|
+
render(<Footer />);
|
|
11
|
+
expect(screen.getByTestId("{ kebabCase name }}").classList).toContain(clx);
|
|
12
|
+
});
|
|
13
|
+
});
|
package/src/footer.tsx
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import React, { lazy } from "react";
|
|
2
|
+
import { SectionsProps, Logo, ContactDetails, SocialLink, LabeledRouteWithKey } from "./types";
|
|
3
|
+
|
|
4
|
+
const Variants = {
|
|
5
|
+
variant_a: lazy(() => import("./footer_a")),
|
|
6
|
+
variant_b: lazy(() => import("./footer_b")),
|
|
7
|
+
variant_c: lazy(() => import("./footer_c")),
|
|
8
|
+
variant_d: lazy(() => import("./footer_d")),
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export interface FooterProps {
|
|
12
|
+
logo?: Logo;
|
|
13
|
+
text?: string;
|
|
14
|
+
contacts?: ContactDetails[];
|
|
15
|
+
copyright?: string;
|
|
16
|
+
socialMedia?: SocialLink[];
|
|
17
|
+
menu?: LabeledRouteWithKey[];
|
|
18
|
+
multipleMenus?: any;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const displayName = "Footer";
|
|
22
|
+
|
|
23
|
+
export const Footer: React.FC<SectionsProps> = ({ data }) => {
|
|
24
|
+
const variant = data?.variant;
|
|
25
|
+
const Variant = variant && Variants[variant as keyof typeof Variants];
|
|
26
|
+
|
|
27
|
+
const props = {
|
|
28
|
+
logo: data?.variants?.logo ?? undefined,
|
|
29
|
+
text: data?.variants?.plainText ?? undefined,
|
|
30
|
+
contacts: data?.variants?.contactDetails ?? undefined,
|
|
31
|
+
copyright: data?.variants?.copyright ?? undefined,
|
|
32
|
+
socialMedia: data?.variants?.socialLinks ?? undefined,
|
|
33
|
+
menu: data?.variants?.menu ?? undefined,
|
|
34
|
+
multipleMenus: data?.variants?.multipleMenus ?? undefined,
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
return Variant ? <Variant {...props} /> : null;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
Footer.displayName = displayName;
|
package/src/footer_a.tsx
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { Container } from "@stackshift-ui/container";
|
|
2
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
3
|
+
import { Grid } from "@stackshift-ui/grid";
|
|
4
|
+
import { GridItem } from "@stackshift-ui/grid-item";
|
|
5
|
+
import { Image } from "@stackshift-ui/image";
|
|
6
|
+
import { Link } from "@stackshift-ui/link";
|
|
7
|
+
import { Section } from "@stackshift-ui/section";
|
|
8
|
+
import { SocialIcons } from "@stackshift-ui/social-icons";
|
|
9
|
+
import { Text } from "@stackshift-ui/text";
|
|
10
|
+
|
|
11
|
+
import { FooterProps } from ".";
|
|
12
|
+
import { logoLink } from "./helper";
|
|
13
|
+
import { ContactDetails, Logo, SocialLink, Socials } from "./types";
|
|
14
|
+
|
|
15
|
+
export default function Footer_A({ logo, text, contacts, copyright, socialMedia }: FooterProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Section className="py-20 bg-background">
|
|
18
|
+
<Container maxWidth={1000}>
|
|
19
|
+
<Flex wrap className="mb-5 lg:mb-20">
|
|
20
|
+
<LogoSection logo={logo} />
|
|
21
|
+
<TextContainer text={text} />
|
|
22
|
+
<ContactsContainer contacts={contacts} />
|
|
23
|
+
</Flex>
|
|
24
|
+
<Flex justify="between" align="center" className="w-full mx-auto lg:flex">
|
|
25
|
+
<CopyrightContainer copyright={copyright} />
|
|
26
|
+
<SocialMediaContainer socialMedia={socialMedia} />
|
|
27
|
+
</Flex>
|
|
28
|
+
</Container>
|
|
29
|
+
</Section>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function LogoSection({ logo }: { logo?: Logo }) {
|
|
34
|
+
if (!logo?.image) return null;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<div className="w-full mb-5 lg:w-1/5">
|
|
38
|
+
<Link
|
|
39
|
+
aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
|
|
40
|
+
className="text-3xl font-bold leading-none"
|
|
41
|
+
href={logoLink(logo)}
|
|
42
|
+
target={logo?.linkTarget}
|
|
43
|
+
rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
|
|
44
|
+
<Image
|
|
45
|
+
className="h-14"
|
|
46
|
+
src={`${logo?.image}`}
|
|
47
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
48
|
+
width={132}
|
|
49
|
+
height={56}
|
|
50
|
+
alt={logo?.alt ?? "footer-logo"}
|
|
51
|
+
/>
|
|
52
|
+
</Link>
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function TextContainer({ text }: { text?: string }) {
|
|
58
|
+
if (!text) return null;
|
|
59
|
+
|
|
60
|
+
return (
|
|
61
|
+
<Container className="w-full mb-5 lg:w-1/5" maxWidth={1000}>
|
|
62
|
+
<Text muted className="leading-loose">
|
|
63
|
+
{text}
|
|
64
|
+
</Text>
|
|
65
|
+
</Container>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function ContactsContainer({ contacts }: { contacts?: ContactDetails[] }) {
|
|
70
|
+
if (!contacts) return null;
|
|
71
|
+
|
|
72
|
+
return (
|
|
73
|
+
<Container className="w-full mt-1 ml-auto lg:w-1/2" maxWidth={1000}>
|
|
74
|
+
{contacts?.map((contact, index) => (
|
|
75
|
+
<Grid columns={1} gap={4} className="lg:gap-10 md:grid-cols-3" key={index}>
|
|
76
|
+
<GridItem span={1}>
|
|
77
|
+
<Text weight="bold" className="mb-4">
|
|
78
|
+
Address
|
|
79
|
+
</Text>
|
|
80
|
+
<Text muted className="mb-5">
|
|
81
|
+
{contact?.addressInfo}
|
|
82
|
+
</Text>
|
|
83
|
+
</GridItem>
|
|
84
|
+
<GridItem span={1}>
|
|
85
|
+
<Text weight="bold" className="mb-4">
|
|
86
|
+
Email
|
|
87
|
+
</Text>
|
|
88
|
+
<Text muted className="mb-5">
|
|
89
|
+
{contact?.emailInfo}
|
|
90
|
+
</Text>
|
|
91
|
+
</GridItem>
|
|
92
|
+
<GridItem span={1}>
|
|
93
|
+
<Text weight="bold" className="mb-4">
|
|
94
|
+
Number
|
|
95
|
+
</Text>
|
|
96
|
+
<Text muted className="mb-5">
|
|
97
|
+
{contact?.contactInfo}
|
|
98
|
+
</Text>
|
|
99
|
+
</GridItem>
|
|
100
|
+
</Grid>
|
|
101
|
+
))}
|
|
102
|
+
</Container>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function CopyrightContainer({ copyright }: { copyright?: string }) {
|
|
107
|
+
if (!copyright) return null;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<Text muted className="text-sm">
|
|
111
|
+
{copyright}
|
|
112
|
+
</Text>
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
|
|
117
|
+
if (!socialMedia) return null;
|
|
118
|
+
|
|
119
|
+
return (
|
|
120
|
+
<Flex wrap className="space-x-2 lg:mx-10 lg:space-x-4">
|
|
121
|
+
{socialMedia?.map((social, index) => <SocialMediaLink social={social} index={index} />)}
|
|
122
|
+
</Flex>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function SocialMediaLink({ social, index }: { social?: SocialLink; index?: number }) {
|
|
127
|
+
if (!social?.socialMediaLink) return null;
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<Link
|
|
131
|
+
aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
|
|
132
|
+
className="inline-block p-2 mr-2 rounded bg-gray-50 hover:bg-gray-100"
|
|
133
|
+
target="_blank"
|
|
134
|
+
rel="noopener noreferrer"
|
|
135
|
+
href={social?.socialMediaLink}
|
|
136
|
+
key={index}>
|
|
137
|
+
{social?.socialMediaIcon?.image ? (
|
|
138
|
+
<Image
|
|
139
|
+
className="h-6"
|
|
140
|
+
src={`${social?.socialMediaIcon?.image}`}
|
|
141
|
+
width={24}
|
|
142
|
+
height={24}
|
|
143
|
+
alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
|
|
144
|
+
/>
|
|
145
|
+
) : (
|
|
146
|
+
<SocialIcons social={social?.socialMedia as Socials} />
|
|
147
|
+
)}
|
|
148
|
+
</Link>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export { Footer_A };
|
package/src/footer_b.tsx
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Button } from "@stackshift-ui/button";
|
|
2
|
+
import { Container } from "@stackshift-ui/container";
|
|
3
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
4
|
+
import { Image } from "@stackshift-ui/image";
|
|
5
|
+
import { Link } from "@stackshift-ui/link";
|
|
6
|
+
import { Section } from "@stackshift-ui/section";
|
|
7
|
+
import { SocialIcons } from "@stackshift-ui/social-icons";
|
|
8
|
+
import { Text } from "@stackshift-ui/text";
|
|
9
|
+
import React from "react";
|
|
10
|
+
|
|
11
|
+
import { FooterProps } from ".";
|
|
12
|
+
import { logoLink } from "./helper";
|
|
13
|
+
import { LabeledRoute, LabeledRouteWithKey, Logo, SocialLink, Socials } from "./types";
|
|
14
|
+
|
|
15
|
+
export default function Footer_B({ logo, copyright, socialMedia, menu }: FooterProps) {
|
|
16
|
+
return (
|
|
17
|
+
<Section className="py-20 bg-background">
|
|
18
|
+
<Container maxWidth={1280}>
|
|
19
|
+
<Flex wrap align="center" justify="between" className="pb-12 border-b border-gray-100">
|
|
20
|
+
<LogoSection logo={logo} />
|
|
21
|
+
<MenuLists menu={menu} />
|
|
22
|
+
</Flex>
|
|
23
|
+
<Flex wrap align="center" justify="between" className="mt-8">
|
|
24
|
+
<CopyrightContainer copyright={copyright} />
|
|
25
|
+
<SocialMediaContainer socialMedia={socialMedia} />
|
|
26
|
+
</Flex>
|
|
27
|
+
</Container>
|
|
28
|
+
</Section>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function LogoSection({ logo }: { logo?: Logo }) {
|
|
33
|
+
if (!logo?.image) return null;
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="w-full mb-12 lg:mb-4 lg:w-1/5">
|
|
37
|
+
<Link
|
|
38
|
+
aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
|
|
39
|
+
className="inline-block text-3xl font-bold leading-none"
|
|
40
|
+
href={logoLink(logo)}
|
|
41
|
+
target={logo?.linkTarget}
|
|
42
|
+
rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
|
|
43
|
+
<Image
|
|
44
|
+
src={logo?.image}
|
|
45
|
+
alt={logo?.alt ?? "footer-logo"}
|
|
46
|
+
width={132}
|
|
47
|
+
height={132}
|
|
48
|
+
className="inline-block text-3xl font-bold leading-none"
|
|
49
|
+
/>
|
|
50
|
+
</Link>
|
|
51
|
+
</div>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function MenuLists({ menu }: { menu?: LabeledRouteWithKey[] }) {
|
|
56
|
+
if (!menu) return null;
|
|
57
|
+
|
|
58
|
+
return (
|
|
59
|
+
<div className="w-full lg:w-auto">
|
|
60
|
+
<Flex wrap align="center" justify="between" as="ul" className=" mt-8 lg:space-x-5">
|
|
61
|
+
{menu?.map((links, index, { length }) => (
|
|
62
|
+
<React.Fragment key={links?._key || index}>
|
|
63
|
+
<MenuList links={links} />
|
|
64
|
+
{index + 1 !== length ? <MenuSeparatorIcon /> : null}
|
|
65
|
+
</React.Fragment>
|
|
66
|
+
))}
|
|
67
|
+
</Flex>
|
|
68
|
+
</div>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function MenuList({ links, index }: { links?: LabeledRoute; index?: number }) {
|
|
73
|
+
if (!links) return null;
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<li className="w-full mb-2 md:mb-0 md:w-auto" key={index}>
|
|
77
|
+
<Button
|
|
78
|
+
as="link"
|
|
79
|
+
link={links}
|
|
80
|
+
className="text-gray-500 no-underline lg:text-sm hover:text-gray-700"
|
|
81
|
+
ariaLabel={links?.label}>
|
|
82
|
+
{links?.label}
|
|
83
|
+
</Button>
|
|
84
|
+
</li>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function MenuSeparatorIcon() {
|
|
89
|
+
return (
|
|
90
|
+
<li className="hidden md:block">
|
|
91
|
+
<svg
|
|
92
|
+
className="w-4 h-4 mx-4 text-gray-500"
|
|
93
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
94
|
+
fill="none"
|
|
95
|
+
viewBox="0 0 24 24"
|
|
96
|
+
stroke="currentColor">
|
|
97
|
+
<path
|
|
98
|
+
strokeLinecap="round"
|
|
99
|
+
strokeLinejoin="round"
|
|
100
|
+
strokeWidth="2"
|
|
101
|
+
d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"
|
|
102
|
+
/>
|
|
103
|
+
</svg>
|
|
104
|
+
</li>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function CopyrightContainer({ copyright }: { copyright?: string }) {
|
|
109
|
+
if (!copyright) return null;
|
|
110
|
+
|
|
111
|
+
return (
|
|
112
|
+
<Text muted className="order-last text-sm ">
|
|
113
|
+
{copyright}
|
|
114
|
+
</Text>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
|
|
119
|
+
if (!socialMedia) return null;
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<div className="order-first mb-4 lg:order-last lg:mb-0">
|
|
123
|
+
{socialMedia?.map(social => <SocialMediaLink social={social} />)}
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function SocialMediaLink({ social }: { social?: SocialLink }) {
|
|
129
|
+
if (!social?.socialMediaLink) return null;
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<Link
|
|
133
|
+
aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
|
|
134
|
+
className="inline-block p-2 mr-2 rounded bg-gray-50 hover:bg-gray-100"
|
|
135
|
+
target="_blank"
|
|
136
|
+
rel="noopener noreferrer"
|
|
137
|
+
href={social?.socialMediaLink}
|
|
138
|
+
key={social?._key}>
|
|
139
|
+
{social?.socialMediaIcon?.image ? (
|
|
140
|
+
<Image
|
|
141
|
+
className="h-6"
|
|
142
|
+
src={`${social?.socialMediaIcon?.image}`}
|
|
143
|
+
width={24}
|
|
144
|
+
height={24}
|
|
145
|
+
alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
|
|
146
|
+
/>
|
|
147
|
+
) : (
|
|
148
|
+
<SocialIcons social={social?.socialMedia as Socials} />
|
|
149
|
+
)}
|
|
150
|
+
</Link>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { Footer_B };
|
package/src/footer_c.tsx
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Button } from "@stackshift-ui/button";
|
|
2
|
+
import { Container } from "@stackshift-ui/container";
|
|
3
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
4
|
+
import { Image } from "@stackshift-ui/image";
|
|
5
|
+
import { Link } from "@stackshift-ui/link";
|
|
6
|
+
import { Section } from "@stackshift-ui/section";
|
|
7
|
+
import { SocialIcons } from "@stackshift-ui/social-icons";
|
|
8
|
+
import { Text } from "@stackshift-ui/text";
|
|
9
|
+
|
|
10
|
+
import { FooterProps } from ".";
|
|
11
|
+
import { logoLink } from "./helper";
|
|
12
|
+
import { LabeledRoute, LabeledRouteWithKey, Logo, SocialLink, Socials } from "./types";
|
|
13
|
+
|
|
14
|
+
export default function Footer_C({ logo, menu, copyright, socialMedia }: FooterProps) {
|
|
15
|
+
return (
|
|
16
|
+
<Section className="bg-background">
|
|
17
|
+
<BorderStyle />
|
|
18
|
+
<Container maxWidth={1000}>
|
|
19
|
+
<div className="pt-10 pb-12">
|
|
20
|
+
<Flex
|
|
21
|
+
justify="between"
|
|
22
|
+
align="center"
|
|
23
|
+
className="relative flex-col gap-8 mb-8 md:flex-row lg:border-b lg:border-gray-300 lg:pb-8">
|
|
24
|
+
<CopyrightSection copyright={copyright} />
|
|
25
|
+
<MenuLists menu={menu} />
|
|
26
|
+
<LogoSection logo={logo} />
|
|
27
|
+
</Flex>
|
|
28
|
+
<SocialMediaContainer socialMedia={socialMedia} />
|
|
29
|
+
</div>
|
|
30
|
+
</Container>
|
|
31
|
+
</Section>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function CopyrightSection({ copyright }: { copyright?: string }) {
|
|
36
|
+
if (!copyright) return null;
|
|
37
|
+
|
|
38
|
+
return <Text className="w-full text-sm text-center">{copyright}</Text>;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function LogoSection({ logo }: { logo?: Logo }) {
|
|
42
|
+
if (!logo?.image) return null;
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div className="w-full text-center">
|
|
46
|
+
<Link
|
|
47
|
+
className="inline-block text-xl font-bold leading-none"
|
|
48
|
+
aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
|
|
49
|
+
href={logoLink(logo)}
|
|
50
|
+
target={logo?.linkTarget}
|
|
51
|
+
rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
|
|
52
|
+
<Image
|
|
53
|
+
src={logo?.image}
|
|
54
|
+
alt={logo?.alt ?? "footer-logo"}
|
|
55
|
+
className="inline-block text-xl font-bold leading-none"
|
|
56
|
+
width={64}
|
|
57
|
+
height={64}
|
|
58
|
+
/>
|
|
59
|
+
</Link>
|
|
60
|
+
</div>
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function MenuLists({ menu }: { menu?: LabeledRouteWithKey[] }) {
|
|
65
|
+
if (!menu) return null;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className="mx-auto">
|
|
69
|
+
<Flex
|
|
70
|
+
className="flex-col gap-0 lg:flex-row lg:gap-10"
|
|
71
|
+
as="ul"
|
|
72
|
+
align="center"
|
|
73
|
+
justify="center">
|
|
74
|
+
{menu?.map((links, index) => <MenuList links={links} index={index} />)}
|
|
75
|
+
</Flex>
|
|
76
|
+
</div>
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function MenuList({ links, index }: { links?: LabeledRoute; index?: number }) {
|
|
81
|
+
if (!links) return null;
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<li className="w-full text-center" key={index}>
|
|
85
|
+
<Button
|
|
86
|
+
as="link"
|
|
87
|
+
link={links}
|
|
88
|
+
className="text-sm text-center text-black no-underline hover:text-gray-500 whitespace-nowrap"
|
|
89
|
+
ariaLabel={links?.label}>
|
|
90
|
+
{links?.label}
|
|
91
|
+
</Button>
|
|
92
|
+
</li>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
|
|
97
|
+
if (!socialMedia) return null;
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Flex wrap justify="center" className="space-y-2 sm:space-y-0">
|
|
101
|
+
{socialMedia?.map((social, index) => <SocialMediaLink social={social} index={index} />)}
|
|
102
|
+
</Flex>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function SocialMediaLink({ social, index }: { social?: SocialLink; index?: number }) {
|
|
107
|
+
if (!social?.socialMediaLink) return null;
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<Link
|
|
111
|
+
aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
|
|
112
|
+
className="inline-block p-2 mr-2 rounded bg-gray-50 hover:bg-gray-100"
|
|
113
|
+
target="_blank"
|
|
114
|
+
rel="noopener noreferrer"
|
|
115
|
+
href={social?.socialMediaLink}
|
|
116
|
+
key={index}>
|
|
117
|
+
{social?.socialMediaIcon?.image ? (
|
|
118
|
+
<Image
|
|
119
|
+
className="h-6"
|
|
120
|
+
src={`${social?.socialMediaIcon?.image}`}
|
|
121
|
+
width={24}
|
|
122
|
+
height={24}
|
|
123
|
+
alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
|
|
124
|
+
/>
|
|
125
|
+
) : (
|
|
126
|
+
<SocialIcons social={social?.socialMedia as Socials} />
|
|
127
|
+
)}
|
|
128
|
+
</Link>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function BorderStyle() {
|
|
133
|
+
return (
|
|
134
|
+
<div className="flex w-full">
|
|
135
|
+
<div className="flex w-1/3">
|
|
136
|
+
<div className="w-1/3 py-1 bg-secondary" />
|
|
137
|
+
<div className="w-1/3 py-1 bg-primary-foreground" />
|
|
138
|
+
<div className="w-1/3 py-1 bg-primary" />
|
|
139
|
+
</div>
|
|
140
|
+
<div className="flex w-1/3">
|
|
141
|
+
<div className="w-1/3 py-1 bg-secondary" />
|
|
142
|
+
<div className="w-1/3 py-1 bg-primary-foreground" />
|
|
143
|
+
<div className="w-1/3 py-1 bg-primary" />
|
|
144
|
+
</div>
|
|
145
|
+
<div className="flex w-1/3">
|
|
146
|
+
<div className="w-1/3 py-1 bg-secondary" />
|
|
147
|
+
<div className="w-1/3 py-1 bg-primary-foreground" />
|
|
148
|
+
<div className="w-1/3 py-1 bg-primary" />
|
|
149
|
+
</div>
|
|
150
|
+
</div>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { Footer_C };
|
package/src/footer_d.tsx
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Button } from "@stackshift-ui/button";
|
|
2
|
+
import { Container } from "@stackshift-ui/container";
|
|
3
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
4
|
+
import { Image } from "@stackshift-ui/image";
|
|
5
|
+
import { Link } from "@stackshift-ui/link";
|
|
6
|
+
import { Section } from "@stackshift-ui/section";
|
|
7
|
+
import { SocialIcons } from "@stackshift-ui/social-icons";
|
|
8
|
+
import { Text } from "@stackshift-ui/text";
|
|
9
|
+
|
|
10
|
+
import { FooterProps } from ".";
|
|
11
|
+
import { logoLink } from "./helper";
|
|
12
|
+
import { Logo, SocialLink, Socials } from "./types";
|
|
13
|
+
|
|
14
|
+
export default function Footer_D({
|
|
15
|
+
logo,
|
|
16
|
+
multipleMenus,
|
|
17
|
+
copyright,
|
|
18
|
+
socialMedia,
|
|
19
|
+
text,
|
|
20
|
+
}: FooterProps) {
|
|
21
|
+
return (
|
|
22
|
+
<Section className="py-20 overflow-hidden bg-background">
|
|
23
|
+
<Container maxWidth={1280}>
|
|
24
|
+
<Flex wrap className="space-y-4 lg:space-y-0">
|
|
25
|
+
<div className="w-full max-w-2xl space-y-4 lg:w-1/4">
|
|
26
|
+
<LogoSection logo={logo} />
|
|
27
|
+
<TextSection text={text} />
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<MenuSection multipleMenus={multipleMenus} />
|
|
31
|
+
<SocialMediaContainer socialMedia={socialMedia} />
|
|
32
|
+
</Flex>
|
|
33
|
+
<CopyrightSection copyright={copyright} />
|
|
34
|
+
</Container>
|
|
35
|
+
</Section>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function LogoSection({ logo }: { logo?: Logo }) {
|
|
40
|
+
if (!logo?.image) return null;
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Link
|
|
44
|
+
className="inline-block text-xl font-bold leading-none"
|
|
45
|
+
aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
|
|
46
|
+
href={logoLink(logo)}
|
|
47
|
+
target={logo?.linkTarget}
|
|
48
|
+
rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
|
|
49
|
+
<Image
|
|
50
|
+
className="h-14"
|
|
51
|
+
src={`${logo?.image}`}
|
|
52
|
+
sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
|
|
53
|
+
width={132}
|
|
54
|
+
height={56}
|
|
55
|
+
alt={logo?.alt ?? "footer-logo"}
|
|
56
|
+
/>
|
|
57
|
+
</Link>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function TextSection({ text }: { text?: string }) {
|
|
62
|
+
if (!text) return null;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Text muted className="leading-normal">
|
|
66
|
+
{text}
|
|
67
|
+
</Text>
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function CopyrightSection({ copyright }: { copyright?: string }) {
|
|
72
|
+
if (!copyright) return null;
|
|
73
|
+
|
|
74
|
+
return <Text className="pt-10 text-sm">{copyright}</Text>;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function MenuSection({ multipleMenus }: { multipleMenus?: any[] }) {
|
|
78
|
+
if (!multipleMenus) return null;
|
|
79
|
+
|
|
80
|
+
return (
|
|
81
|
+
<Flex wrap className="flex-grow lg:justify-around" gap={4}>
|
|
82
|
+
{multipleMenus?.map(menu => <MenuLinks key={menu?._key} menu={menu} />)}
|
|
83
|
+
</Flex>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Individual Menu Links Component
|
|
88
|
+
function MenuLinks({ menu }: { menu?: any }) {
|
|
89
|
+
if (!menu) return null;
|
|
90
|
+
|
|
91
|
+
return (
|
|
92
|
+
<div className="w-[200px] flex-none">
|
|
93
|
+
{menu?.title && (
|
|
94
|
+
<Text weight="bold" className="mb-3">
|
|
95
|
+
{menu?.title}
|
|
96
|
+
</Text>
|
|
97
|
+
)}
|
|
98
|
+
{menu?.links?.length > 0 && (
|
|
99
|
+
<Flex as="ul" direction="col" className="space-y-2">
|
|
100
|
+
{menu?.links?.map((link: any) => (
|
|
101
|
+
<li key={link?._key}>
|
|
102
|
+
<Button
|
|
103
|
+
as="link"
|
|
104
|
+
link={link}
|
|
105
|
+
className="text-gray-500 no-underline hover:text-gray-700"
|
|
106
|
+
ariaLabel={link?.label}>
|
|
107
|
+
{link?.label}
|
|
108
|
+
</Button>
|
|
109
|
+
</li>
|
|
110
|
+
))}
|
|
111
|
+
</Flex>
|
|
112
|
+
)}
|
|
113
|
+
</div>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
|
|
118
|
+
if (!socialMedia) return null;
|
|
119
|
+
|
|
120
|
+
return (
|
|
121
|
+
<Flex className="w-full ml-auto lg:justify-end lg:w-1/6">
|
|
122
|
+
{socialMedia?.map(social => social?.socialMediaLink && <SocialMediaLink social={social} />)}
|
|
123
|
+
</Flex>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function SocialMediaLink({ social }: { social?: SocialLink }) {
|
|
128
|
+
if (!social?.socialMediaLink) return null;
|
|
129
|
+
|
|
130
|
+
return (
|
|
131
|
+
<span key={social?._key}>
|
|
132
|
+
<Link
|
|
133
|
+
aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
|
|
134
|
+
className="inline-block p-2 mr-2 rounded bg-gray-50 hover:bg-gray-100"
|
|
135
|
+
target="_blank"
|
|
136
|
+
rel="noopener noreferrer"
|
|
137
|
+
href={social?.socialMediaLink}>
|
|
138
|
+
{social?.socialMediaIcon?.image ? (
|
|
139
|
+
<Image
|
|
140
|
+
className="h-6"
|
|
141
|
+
src={`${social?.socialMediaIcon?.image}`}
|
|
142
|
+
width={24}
|
|
143
|
+
height={24}
|
|
144
|
+
alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
|
|
145
|
+
/>
|
|
146
|
+
) : (
|
|
147
|
+
<SocialIcons social={social?.socialMedia as Socials} />
|
|
148
|
+
)}
|
|
149
|
+
</Link>
|
|
150
|
+
</span>
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
export { Footer_D };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Logo } from "../types";
|
|
2
|
+
|
|
3
|
+
// Logo link
|
|
4
|
+
export const logoLink = (logo: Logo) => {
|
|
5
|
+
if (logo?.internalLink && logo?.type === "linkInternal") {
|
|
6
|
+
if (logo?.internalLink?.toLowerCase()?.includes("home")) {
|
|
7
|
+
return "/";
|
|
8
|
+
}
|
|
9
|
+
return `/${logo.internalLink}`;
|
|
10
|
+
} else if (logo?.externalLink && logo?.type === "linkExternal") {
|
|
11
|
+
return logo?.externalLink ?? "/";
|
|
12
|
+
} else {
|
|
13
|
+
return "/";
|
|
14
|
+
}
|
|
15
|
+
};
|
package/src/index.ts
ADDED
package/src/types.ts
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
export type StyleVariants<T extends string> = Record<T, string>;
|
|
2
|
+
|
|
3
|
+
export type Socials = "facebook" | "instagram" | "youtube" | "linkedin" | "twitter";
|
|
4
|
+
export interface MainImage {
|
|
5
|
+
image: string;
|
|
6
|
+
alt?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface LabeledRoute extends ConditionalLink {
|
|
10
|
+
ariaLabel?: string;
|
|
11
|
+
label?: string;
|
|
12
|
+
linkTarget?: string;
|
|
13
|
+
linkType?: string;
|
|
14
|
+
_type?: string;
|
|
15
|
+
linkInternal?: any;
|
|
16
|
+
}
|
|
17
|
+
export interface ConditionalLink {
|
|
18
|
+
type?: string;
|
|
19
|
+
internalLink?: string | null;
|
|
20
|
+
externalLink?: string | null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface StatItems {
|
|
24
|
+
label?: string;
|
|
25
|
+
mainImage?: MainImage;
|
|
26
|
+
value?: string;
|
|
27
|
+
_key?: string;
|
|
28
|
+
_type?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface Logo extends ConditionalLink {
|
|
32
|
+
alt?: string;
|
|
33
|
+
linkTarget?: string;
|
|
34
|
+
image?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface Images {
|
|
38
|
+
image?: string;
|
|
39
|
+
_key?: string;
|
|
40
|
+
_type?: string;
|
|
41
|
+
alt?: string;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface ContactDetails {
|
|
45
|
+
addressInfo?: string;
|
|
46
|
+
contactInfo?: string;
|
|
47
|
+
emailInfo?: string;
|
|
48
|
+
_key?: string;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface SocialLink {
|
|
52
|
+
socialMedia?: string | null;
|
|
53
|
+
socialMediaLink?: string | null;
|
|
54
|
+
_key?: string | null;
|
|
55
|
+
_type?: string | null;
|
|
56
|
+
socialMediaIcon?: {
|
|
57
|
+
alt?: string;
|
|
58
|
+
image?: string;
|
|
59
|
+
} | null;
|
|
60
|
+
socialMediaPlatform?: string | null;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export interface LabeledRouteWithKey extends LabeledRoute {
|
|
64
|
+
_key?: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface ArrayOfImageTitleAndText {
|
|
68
|
+
mainImage?: {
|
|
69
|
+
alt?: string;
|
|
70
|
+
image?: string;
|
|
71
|
+
};
|
|
72
|
+
plainText?: string;
|
|
73
|
+
title?: string;
|
|
74
|
+
_key?: string;
|
|
75
|
+
_type?: string;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export interface FeaturedItem {
|
|
79
|
+
description?: string;
|
|
80
|
+
mainImage?: MainImage;
|
|
81
|
+
title?: string;
|
|
82
|
+
subtitle?: string;
|
|
83
|
+
_key?: string;
|
|
84
|
+
_type?: string;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface ArrayOfTitleAndText {
|
|
88
|
+
_key?: string;
|
|
89
|
+
plainText?: string;
|
|
90
|
+
title?: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface BlogPost extends SanityBody {
|
|
94
|
+
authors?: Author[] | null;
|
|
95
|
+
body?: any;
|
|
96
|
+
categories?: Category[] | null;
|
|
97
|
+
excerpt?: string | null;
|
|
98
|
+
link?: string | null;
|
|
99
|
+
mainImage?: string | null;
|
|
100
|
+
publishedAt?: string;
|
|
101
|
+
seo?: Seo | null;
|
|
102
|
+
slug?: SanitySlug | null;
|
|
103
|
+
title?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface Seo {
|
|
107
|
+
_type?: string;
|
|
108
|
+
seoTitle?: string;
|
|
109
|
+
seoDescription?: string;
|
|
110
|
+
seoImage?: string;
|
|
111
|
+
seoKeywords?: string;
|
|
112
|
+
seoSynonyms?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface SanitySlug {
|
|
116
|
+
current?: string;
|
|
117
|
+
_type?: "slug";
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export interface SanityBody {
|
|
121
|
+
_createdAt?: string;
|
|
122
|
+
_id?: string;
|
|
123
|
+
_rev?: string;
|
|
124
|
+
_type?: string;
|
|
125
|
+
_updatedAt?: string;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface Author extends SanityBody {
|
|
129
|
+
link?: string | null;
|
|
130
|
+
bio?: string | null;
|
|
131
|
+
name?: string | null;
|
|
132
|
+
slug?: SanitySlug | null;
|
|
133
|
+
image?: string | null;
|
|
134
|
+
profile?: {
|
|
135
|
+
alt: string;
|
|
136
|
+
image: string;
|
|
137
|
+
} | null;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export interface Category extends SanityBody {
|
|
141
|
+
title?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface Form {
|
|
145
|
+
id?: string | null;
|
|
146
|
+
buttonLabel?: string | null;
|
|
147
|
+
name?: string | null;
|
|
148
|
+
subtitle?: string | null;
|
|
149
|
+
fields?: FormFields[] | null;
|
|
150
|
+
thankYouPage?: ThankYouPage | null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
export interface FormFields {
|
|
154
|
+
name?: string;
|
|
155
|
+
placeholder?: string;
|
|
156
|
+
pricingType?: string;
|
|
157
|
+
type?: FormTypes;
|
|
158
|
+
_key?: string;
|
|
159
|
+
_type?: string;
|
|
160
|
+
isRequired?: boolean;
|
|
161
|
+
label?: string;
|
|
162
|
+
items?: string[];
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
export type FormTypes =
|
|
166
|
+
| "inputText"
|
|
167
|
+
| "inputEmail"
|
|
168
|
+
| "inputPassword"
|
|
169
|
+
| "inputNumber"
|
|
170
|
+
| "textarea"
|
|
171
|
+
| "inputFile"
|
|
172
|
+
| "inputRadio"
|
|
173
|
+
| "inputCheckbox"
|
|
174
|
+
| "inputSelect";
|
|
175
|
+
|
|
176
|
+
export interface ThankYouPage {
|
|
177
|
+
externalLink?: string | null;
|
|
178
|
+
internalLink?: string | null;
|
|
179
|
+
linkInternal?: any;
|
|
180
|
+
linkTarget?: string;
|
|
181
|
+
linkType?: string;
|
|
182
|
+
type?: string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
//Used on different sections
|
|
186
|
+
export interface SectionsProps {
|
|
187
|
+
template?: Template;
|
|
188
|
+
data?: Sections;
|
|
189
|
+
variant?: string | null | undefined;
|
|
190
|
+
schema?: Variants;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface Sections extends SanityBody {
|
|
194
|
+
label?: string;
|
|
195
|
+
variant?: string;
|
|
196
|
+
variants?: Variants;
|
|
197
|
+
_key?: string;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
//*EDIT THIS SECTION WHEN CREATING/UPDATING SCHEMAS ON STUDIO */
|
|
201
|
+
export interface Variants {
|
|
202
|
+
template?: Template;
|
|
203
|
+
multipleMenus?: any;
|
|
204
|
+
arrayOfTitleAndText?: ArrayOfTitleAndText[] | null;
|
|
205
|
+
logo?: Logo | null;
|
|
206
|
+
primaryButton?: LabeledRoute | null;
|
|
207
|
+
secondaryButton?: LabeledRoute | null;
|
|
208
|
+
routes?: LabeledRouteWithKey[] | null;
|
|
209
|
+
menu?: LabeledRouteWithKey[] | null;
|
|
210
|
+
plans?: Plans[] | null;
|
|
211
|
+
formLinks?: LabeledRouteWithKey[] | null;
|
|
212
|
+
portfolios?: Portfolios[] | null;
|
|
213
|
+
portfoliosWithCategories?: PortfoliosWithCategories[] | null;
|
|
214
|
+
length?: number;
|
|
215
|
+
signInLink?: LabeledRoute | null;
|
|
216
|
+
signinLink?: LabeledRoute | null;
|
|
217
|
+
tags?: string[] | null;
|
|
218
|
+
posts?: BlogPost[] | null;
|
|
219
|
+
blogsPerPage?: number | null;
|
|
220
|
+
form?: Form | null;
|
|
221
|
+
collections?: Collection | null;
|
|
222
|
+
products?: CollectionProduct | null;
|
|
223
|
+
allProducts?: Collection[];
|
|
224
|
+
subtitle?: string | null;
|
|
225
|
+
caption?: string | null;
|
|
226
|
+
title?: string | null;
|
|
227
|
+
plainText?: string | null;
|
|
228
|
+
contactDescription?: string | null;
|
|
229
|
+
officeInformation?: string | null;
|
|
230
|
+
contactEmail?: string | null;
|
|
231
|
+
contactNumber?: string | null;
|
|
232
|
+
socialLinks?: SocialLink[] | null;
|
|
233
|
+
block?: any;
|
|
234
|
+
heading?: string | null;
|
|
235
|
+
acceptButtonLabel?: string | null;
|
|
236
|
+
declineButtonLabel?: string | null;
|
|
237
|
+
faqsWithCategories?: FaqsWithCategory[] | null;
|
|
238
|
+
faqs?: AskedQuestion[] | null;
|
|
239
|
+
arrayOfImageTitleAndText?: ArrayOfImageTitleAndText[] | null;
|
|
240
|
+
description?: string | null;
|
|
241
|
+
featuredItems?: FeaturedItem[] | null;
|
|
242
|
+
images?: Images[] | null;
|
|
243
|
+
contactDetails?: ContactDetails[] | null;
|
|
244
|
+
copyright?: string | null;
|
|
245
|
+
mainImage?: MainImage | null;
|
|
246
|
+
youtubeLink?: string | null;
|
|
247
|
+
banner?: any;
|
|
248
|
+
stats?: StatItems[] | null;
|
|
249
|
+
teams?: Team[] | null;
|
|
250
|
+
testimonials?: Testimonial[] | null;
|
|
251
|
+
selectStripeAccount?: string;
|
|
252
|
+
annualBilling?: string;
|
|
253
|
+
monthlyBilling?: string;
|
|
254
|
+
productDetails?: ProductDetail[];
|
|
255
|
+
btnLabel?: string;
|
|
256
|
+
selectAccount?: string;
|
|
257
|
+
hashtags?: string[];
|
|
258
|
+
numberOfPosts?: number;
|
|
259
|
+
text?: string;
|
|
260
|
+
button?: LabeledRoute;
|
|
261
|
+
features?: string[];
|
|
262
|
+
config?: {
|
|
263
|
+
enableAnalytics: boolean;
|
|
264
|
+
cookiePolicy?: {
|
|
265
|
+
siteName: string;
|
|
266
|
+
cookiePolicyPage: Reference;
|
|
267
|
+
};
|
|
268
|
+
consentModalPosition?: string;
|
|
269
|
+
};
|
|
270
|
+
contactLink?: LabeledRoute;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface Template {
|
|
274
|
+
bg?: string;
|
|
275
|
+
color?: string;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export type Plans = {
|
|
279
|
+
_key?: string | null;
|
|
280
|
+
_type?: "planItems" | null;
|
|
281
|
+
checkoutButtonName?: string | null;
|
|
282
|
+
description?: string | null;
|
|
283
|
+
monthlyPrice?: string | null;
|
|
284
|
+
planType?: string | null;
|
|
285
|
+
yearlyPrice?: string | null;
|
|
286
|
+
planIncludes?: string[] | null;
|
|
287
|
+
primaryButton?: LabeledRoute | null;
|
|
288
|
+
} & Record<string, string>;
|
|
289
|
+
|
|
290
|
+
export interface Portfolios {
|
|
291
|
+
dateAdded?: string | null;
|
|
292
|
+
mainImage?: {
|
|
293
|
+
image?: string | null;
|
|
294
|
+
alt?: string | null;
|
|
295
|
+
} | null;
|
|
296
|
+
primaryButton?: LabeledRoute | null;
|
|
297
|
+
title?: string | null;
|
|
298
|
+
_key?: string | null;
|
|
299
|
+
_type?: string | null;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
export interface PortfoliosWithCategories {
|
|
303
|
+
category?: string | null;
|
|
304
|
+
content?: Content[] | null;
|
|
305
|
+
primaryButton?: LabeledRoute | null;
|
|
306
|
+
_key?: string | null;
|
|
307
|
+
_type?: string | null;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
export interface Content extends Portfolios {
|
|
311
|
+
description?: string | null;
|
|
312
|
+
subtitle?: string | null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
export interface Collection extends SanityBody {
|
|
316
|
+
collectionInfoVariant?: {
|
|
317
|
+
variant?: string;
|
|
318
|
+
} | null;
|
|
319
|
+
name?: string | null;
|
|
320
|
+
products?: CollectionProduct[] | null;
|
|
321
|
+
sections?: any; //todo
|
|
322
|
+
seo?: Seo | null;
|
|
323
|
+
slug?: SanitySlug | null;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface CollectionProduct extends SanityBody {
|
|
327
|
+
compareToPrice?: number | null;
|
|
328
|
+
description?: string | null;
|
|
329
|
+
ecwidProductId?: number | null;
|
|
330
|
+
name?: string | null;
|
|
331
|
+
price?: number | null;
|
|
332
|
+
productInfo?: ProductInfo | null;
|
|
333
|
+
productInfoVariant?: {
|
|
334
|
+
variant?: string;
|
|
335
|
+
} | null;
|
|
336
|
+
sections?: any; //todo
|
|
337
|
+
seo?: Seo | null;
|
|
338
|
+
slug?: SanitySlug | null;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
//TODO, RECHECK PRODUCT INFO DATA FROM SANITY
|
|
342
|
+
interface ProductInfo {
|
|
343
|
+
btnLabel?: string | null;
|
|
344
|
+
images?: ProductInfoImage[] | null;
|
|
345
|
+
productDetails?: ProductDetail[] | null;
|
|
346
|
+
socialLinks?: SocialLink[] | null;
|
|
347
|
+
subtitle?: string | null;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
//TODO, RECHECK PRODUCT INFO DATA FROM SANITY
|
|
351
|
+
export interface ProductDetail {
|
|
352
|
+
blockContent?: any;
|
|
353
|
+
contentType?: string;
|
|
354
|
+
tabName?: string;
|
|
355
|
+
_key?: string;
|
|
356
|
+
[key: string]: any;
|
|
357
|
+
}
|
|
358
|
+
interface ProductInfoImage {
|
|
359
|
+
alt?: string | null;
|
|
360
|
+
_key: string;
|
|
361
|
+
_type: string;
|
|
362
|
+
image?: string | null;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
export interface FaqsWithCategory {
|
|
366
|
+
askedQuestions?: AskedQuestion[] | null;
|
|
367
|
+
category?: string | null;
|
|
368
|
+
_key?: string;
|
|
369
|
+
_type?: string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
export interface AskedQuestion {
|
|
373
|
+
answer?: string | null;
|
|
374
|
+
question?: string | null;
|
|
375
|
+
hidden?: boolean;
|
|
376
|
+
_key?: string;
|
|
377
|
+
_type?: string;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
export interface Team {
|
|
381
|
+
jobTitle?: string;
|
|
382
|
+
mainImage?: MainImage;
|
|
383
|
+
name?: string;
|
|
384
|
+
plainText?: string;
|
|
385
|
+
_key?: string;
|
|
386
|
+
_type?: string;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
export interface Testimonial {
|
|
390
|
+
jobTitle?: string;
|
|
391
|
+
mainImage?: MainImage;
|
|
392
|
+
name?: string;
|
|
393
|
+
rating?: string;
|
|
394
|
+
testimony?: string;
|
|
395
|
+
_key?: string;
|
|
396
|
+
_type?: string;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
export declare interface Reference {
|
|
400
|
+
_type: string;
|
|
401
|
+
_ref: string;
|
|
402
|
+
_key?: string;
|
|
403
|
+
_weak?: boolean;
|
|
404
|
+
_strengthenOnPublish?: {
|
|
405
|
+
type: string;
|
|
406
|
+
weak?: boolean;
|
|
407
|
+
template?: {
|
|
408
|
+
id: string;
|
|
409
|
+
params: Record<string, string | number | boolean>;
|
|
410
|
+
};
|
|
411
|
+
};
|
|
412
|
+
}
|