@stackshift-ui/features 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 +12 -11
- package/src/features.test.tsx +13 -0
- package/src/features.tsx +64 -0
- package/src/features_a.tsx +95 -0
- package/src/features_b.tsx +119 -0
- package/src/features_c.tsx +76 -0
- package/src/features_d.tsx +74 -0
- package/src/features_e.tsx +143 -0
- package/src/features_f.tsx +120 -0
- package/src/features_g.tsx +138 -0
- package/src/features_h.tsx +135 -0
- package/src/index.ts +12 -0
- package/src/types.ts +412 -0
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackshift-ui/features",
|
|
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": {
|
|
@@ -34,15 +35,15 @@
|
|
|
34
35
|
"dependencies": {
|
|
35
36
|
"classnames": "^2.5.1",
|
|
36
37
|
"@stackshift-ui/scripts": "6.0.2",
|
|
37
|
-
"@stackshift-ui/system": "6.0.
|
|
38
|
-
"@stackshift-ui/heading": "6.0.
|
|
39
|
-
"@stackshift-ui/text": "6.0.
|
|
40
|
-
"@stackshift-ui/image": "6.0.
|
|
41
|
-
"@stackshift-ui/button": "6.0.
|
|
42
|
-
"@stackshift-ui/
|
|
43
|
-
"@stackshift-ui/
|
|
44
|
-
"@stackshift-ui/container": "6.0.
|
|
45
|
-
"@stackshift-ui/
|
|
38
|
+
"@stackshift-ui/system": "6.0.3",
|
|
39
|
+
"@stackshift-ui/heading": "6.0.3",
|
|
40
|
+
"@stackshift-ui/text": "6.0.3",
|
|
41
|
+
"@stackshift-ui/image": "6.0.3",
|
|
42
|
+
"@stackshift-ui/button": "6.0.3",
|
|
43
|
+
"@stackshift-ui/section": "6.0.3",
|
|
44
|
+
"@stackshift-ui/card": "6.0.3",
|
|
45
|
+
"@stackshift-ui/container": "6.0.3",
|
|
46
|
+
"@stackshift-ui/flex": "6.0.3"
|
|
46
47
|
},
|
|
47
48
|
"peerDependencies": {
|
|
48
49
|
"@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 { Features } from "./features";
|
|
4
|
+
|
|
5
|
+
describe.concurrent("features", () => {
|
|
6
|
+
afterEach(cleanup);
|
|
7
|
+
|
|
8
|
+
test.skip("Dummy test - test if renders without errors", ({ expect }) => {
|
|
9
|
+
const clx = "my-class";
|
|
10
|
+
render(<Features />);
|
|
11
|
+
expect(screen.getByTestId("{ kebabCase name }}").classList).toContain(clx);
|
|
12
|
+
});
|
|
13
|
+
});
|
package/src/features.tsx
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import React, { lazy } from "react";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
SectionsProps,
|
|
5
|
+
ArrayOfImageTitleAndText,
|
|
6
|
+
FeaturedItem,
|
|
7
|
+
Images,
|
|
8
|
+
LabeledRoute,
|
|
9
|
+
} from "./types";
|
|
10
|
+
|
|
11
|
+
const Variants = {
|
|
12
|
+
variant_a: lazy(() => import("./features_a")),
|
|
13
|
+
variant_b: lazy(() => import("./features_b")),
|
|
14
|
+
variant_c: lazy(() => import("./features_c")),
|
|
15
|
+
variant_d: lazy(() => import("./features_d")),
|
|
16
|
+
variant_e: lazy(() => import("./features_e")),
|
|
17
|
+
variant_f: lazy(() => import("./features_f")),
|
|
18
|
+
variant_g: lazy(() => import("./features_g")),
|
|
19
|
+
variant_h: lazy(() => import("./features_h")),
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
export interface FeaturesProps {
|
|
23
|
+
caption?: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
features?: ArrayOfImageTitleAndText[];
|
|
27
|
+
tags?: string[];
|
|
28
|
+
featuredItems?: FeaturedItem[];
|
|
29
|
+
images?: Images[];
|
|
30
|
+
primaryButton?: LabeledRoute;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface FeaturesProps {
|
|
34
|
+
caption?: string;
|
|
35
|
+
title?: string;
|
|
36
|
+
description?: string;
|
|
37
|
+
features?: ArrayOfImageTitleAndText[];
|
|
38
|
+
tags?: string[];
|
|
39
|
+
featuredItems?: FeaturedItem[];
|
|
40
|
+
images?: Images[];
|
|
41
|
+
primaryButton?: LabeledRoute;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const displayName = "Features";
|
|
45
|
+
|
|
46
|
+
export const Features: React.FC<SectionsProps> = ({ data }) => {
|
|
47
|
+
const variant = data?.variant;
|
|
48
|
+
const Variant = variant && Variants[variant as keyof typeof Variants];
|
|
49
|
+
|
|
50
|
+
const props = {
|
|
51
|
+
caption: data?.variants?.caption ?? undefined,
|
|
52
|
+
title: data?.variants?.title ?? undefined,
|
|
53
|
+
description: data?.variants?.description ?? undefined,
|
|
54
|
+
features: data?.variants?.arrayOfImageTitleAndText ?? undefined,
|
|
55
|
+
tags: data?.variants?.tags ?? undefined,
|
|
56
|
+
featuredItems: data?.variants?.featuredItems ?? undefined,
|
|
57
|
+
images: data?.variants?.images ?? undefined,
|
|
58
|
+
primaryButton: data?.variants?.primaryButton ?? undefined,
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
return Variant ? <Variant {...props} /> : null;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
Features.displayName = displayName;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { Container } from "@stackshift-ui/container";
|
|
2
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
3
|
+
import { Heading } from "@stackshift-ui/heading";
|
|
4
|
+
import { Image } from "@stackshift-ui/image";
|
|
5
|
+
import { Section } from "@stackshift-ui/section";
|
|
6
|
+
import { Text } from "@stackshift-ui/text";
|
|
7
|
+
import React from "react";
|
|
8
|
+
import { FeaturesProps } from ".";
|
|
9
|
+
import { ArrayOfImageTitleAndText, Images } from "./types";
|
|
10
|
+
|
|
11
|
+
interface FeatureItemProps {
|
|
12
|
+
feature: {
|
|
13
|
+
caption?: string | null;
|
|
14
|
+
title?: string | null;
|
|
15
|
+
plainText?: string | null;
|
|
16
|
+
mainImage?: Images;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default function Features_A({ caption, title, features }: FeaturesProps) {
|
|
21
|
+
return (
|
|
22
|
+
<Section className="py-20 bg-background">
|
|
23
|
+
<Container maxWidth={1280}>
|
|
24
|
+
<Container maxWidth={448} className="mb-16 text-center ">
|
|
25
|
+
<CaptionAndTitleText caption={caption} title={title} />
|
|
26
|
+
</Container>
|
|
27
|
+
<Flex wrap>
|
|
28
|
+
<FeatureItems features={features} />
|
|
29
|
+
</Flex>
|
|
30
|
+
</Container>
|
|
31
|
+
</Section>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function CaptionAndTitleText({ caption, title }: { caption?: string; title?: string }) {
|
|
36
|
+
return (
|
|
37
|
+
<React.Fragment>
|
|
38
|
+
{caption ? (
|
|
39
|
+
<Text weight="bold" className="text-secondary">
|
|
40
|
+
{caption}
|
|
41
|
+
</Text>
|
|
42
|
+
) : null}
|
|
43
|
+
{title ? <Heading fontSize="3xl">{title}</Heading> : null}
|
|
44
|
+
</React.Fragment>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function FeatureItems({ features }: { features?: ArrayOfImageTitleAndText[] }) {
|
|
49
|
+
if (!features) return null;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<React.Fragment>
|
|
53
|
+
{features?.map(feature => {
|
|
54
|
+
return <FeatureItem feature={feature} key={feature._key} />;
|
|
55
|
+
})}
|
|
56
|
+
</React.Fragment>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function FeatureItem({ feature }: FeatureItemProps) {
|
|
61
|
+
return (
|
|
62
|
+
<div className="w-full px-4 mt-16 mb-12 md:w-1/2 lg:mb-0 lg:w-1/4">
|
|
63
|
+
{feature?.mainImage?.image ? <FeatureImage feature={feature} /> : null}
|
|
64
|
+
|
|
65
|
+
{feature?.title ? (
|
|
66
|
+
<Text weight="bold" className="mb-4 text-gray-500" fontSize="xl">
|
|
67
|
+
{feature?.title}
|
|
68
|
+
</Text>
|
|
69
|
+
) : null}
|
|
70
|
+
{feature?.plainText ? (
|
|
71
|
+
<Text muted className="leading-loose">
|
|
72
|
+
{feature?.plainText}
|
|
73
|
+
</Text>
|
|
74
|
+
) : null}
|
|
75
|
+
</div>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function FeatureImage({ feature }: FeatureItemProps) {
|
|
80
|
+
if (!feature?.mainImage?.image) return null;
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<span className="inline-block p-3 mb-4 rounded bg-secondary-foreground text-primary-foreground md:mb-6">
|
|
84
|
+
<Image
|
|
85
|
+
className="object-scale-down"
|
|
86
|
+
src={`${feature?.mainImage?.image}`}
|
|
87
|
+
width={40}
|
|
88
|
+
height={40}
|
|
89
|
+
alt={feature?.mainImage?.alt ?? `features-image-`}
|
|
90
|
+
/>
|
|
91
|
+
</span>
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { Features_A };
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { Card } from "@stackshift-ui/card";
|
|
2
|
+
import { Container } from "@stackshift-ui/container";
|
|
3
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
4
|
+
import { Heading } from "@stackshift-ui/heading";
|
|
5
|
+
import { Image } from "@stackshift-ui/image";
|
|
6
|
+
import { Section } from "@stackshift-ui/section";
|
|
7
|
+
import { Text } from "@stackshift-ui/text";
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { FeaturesProps } from ".";
|
|
10
|
+
import { ArrayOfImageTitleAndText } from "./types";
|
|
11
|
+
|
|
12
|
+
export default function Features_B({ caption, title, description, features, tags }: FeaturesProps) {
|
|
13
|
+
return (
|
|
14
|
+
<Section className="py-20 bg-background">
|
|
15
|
+
<Container maxWidth={1280}>
|
|
16
|
+
<Flex wrap align="center">
|
|
17
|
+
<div className="w-full mb-12 lg:mb-0 lg:w-1/2">
|
|
18
|
+
<Container maxWidth={448}>
|
|
19
|
+
<FeatureInfo caption={caption} title={title} description={description} />
|
|
20
|
+
<TagList tags={tags} />
|
|
21
|
+
</Container>
|
|
22
|
+
</div>
|
|
23
|
+
<FeaturesLists features={features} />
|
|
24
|
+
</Flex>
|
|
25
|
+
</Container>
|
|
26
|
+
</Section>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function FeatureInfo({
|
|
31
|
+
caption,
|
|
32
|
+
title,
|
|
33
|
+
description,
|
|
34
|
+
}: {
|
|
35
|
+
caption?: string;
|
|
36
|
+
title?: string;
|
|
37
|
+
description?: string;
|
|
38
|
+
}) {
|
|
39
|
+
return (
|
|
40
|
+
<React.Fragment>
|
|
41
|
+
{caption && (
|
|
42
|
+
<Text weight="bold" className="text-primary">
|
|
43
|
+
{caption}
|
|
44
|
+
</Text>
|
|
45
|
+
)}
|
|
46
|
+
{title && <Heading fontSize="3xl">{title}</Heading>}
|
|
47
|
+
{description && (
|
|
48
|
+
<Text muted className="mb-6 leading-loose">
|
|
49
|
+
{description}
|
|
50
|
+
</Text>
|
|
51
|
+
)}
|
|
52
|
+
</React.Fragment>
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function TagList({ tags }: { tags?: string[] }) {
|
|
57
|
+
if (!tags) return null;
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<ul>
|
|
61
|
+
{tags &&
|
|
62
|
+
tags.map(item => (
|
|
63
|
+
<li className="flex mb-4" key={item}>
|
|
64
|
+
<svg
|
|
65
|
+
className="w-6 h-6 mr-2 text-secondary"
|
|
66
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
67
|
+
viewBox="0 0 20 20"
|
|
68
|
+
fill="currentColor">
|
|
69
|
+
<path
|
|
70
|
+
fillRule="evenodd"
|
|
71
|
+
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
|
72
|
+
clipRule="evenodd"
|
|
73
|
+
/>
|
|
74
|
+
</svg>
|
|
75
|
+
<Text muted weight="bold">
|
|
76
|
+
{item}
|
|
77
|
+
</Text>
|
|
78
|
+
</li>
|
|
79
|
+
))}
|
|
80
|
+
</ul>
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function FeaturesLists({ features }: { features?: ArrayOfImageTitleAndText[] }) {
|
|
85
|
+
if (!features) return null;
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<Flex wrap className="w-full lg:w-1/2">
|
|
89
|
+
{features &&
|
|
90
|
+
features?.map((feature, index) => (
|
|
91
|
+
<div
|
|
92
|
+
className={`w-full px-4 mb-8 md:w-1/2 ${index % 2 === 0 ? `lg:mb-0` : "lg:mt-12"}`}
|
|
93
|
+
key={index}>
|
|
94
|
+
<Card className="py-6 pl-6 pr-4 mb-8">
|
|
95
|
+
<span className="inline-block p-3 mb-4 rounded-lg bg-secondary-foreground">
|
|
96
|
+
{feature?.mainImage?.image && (
|
|
97
|
+
<Image
|
|
98
|
+
className="object-scale-down"
|
|
99
|
+
src={`${feature?.mainImage?.image}`}
|
|
100
|
+
width={40}
|
|
101
|
+
height={40}
|
|
102
|
+
alt={feature?.mainImage?.alt ?? `features-image-${index}`}
|
|
103
|
+
/>
|
|
104
|
+
)}
|
|
105
|
+
</span>
|
|
106
|
+
<Text weight="bold" fontSize="2xl" className="mb-2 text-gray-500">
|
|
107
|
+
{feature?.title}
|
|
108
|
+
</Text>
|
|
109
|
+
<Text muted className="leading-loose">
|
|
110
|
+
{feature?.plainText}
|
|
111
|
+
</Text>
|
|
112
|
+
</Card>
|
|
113
|
+
</div>
|
|
114
|
+
))}
|
|
115
|
+
</Flex>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export { Features_B };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { Card } from "@stackshift-ui/card";
|
|
2
|
+
import { Container } from "@stackshift-ui/container";
|
|
3
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
4
|
+
import { Heading } from "@stackshift-ui/heading";
|
|
5
|
+
import { Image } from "@stackshift-ui/image";
|
|
6
|
+
import { Section } from "@stackshift-ui/section";
|
|
7
|
+
import { Text } from "@stackshift-ui/text";
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { FeaturesProps } from ".";
|
|
10
|
+
import { ArrayOfImageTitleAndText } from "./types";
|
|
11
|
+
|
|
12
|
+
export default function Features_C({ caption, title, features }: FeaturesProps) {
|
|
13
|
+
return (
|
|
14
|
+
<Section className="py-20 bg-background">
|
|
15
|
+
<Container maxWidth={1280}>
|
|
16
|
+
<Container maxWidth={448} className="mb-16 text-center ">
|
|
17
|
+
<CaptionAndTitleSection caption={caption} title={title} />
|
|
18
|
+
</Container>
|
|
19
|
+
<FeatureItems features={features} />
|
|
20
|
+
</Container>
|
|
21
|
+
</Section>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function CaptionAndTitleSection({ caption, title }: { caption?: string; title?: string }) {
|
|
26
|
+
return (
|
|
27
|
+
<React.Fragment>
|
|
28
|
+
{caption ? (
|
|
29
|
+
<Text weight="bold" className="text-secondary">
|
|
30
|
+
{caption}
|
|
31
|
+
</Text>
|
|
32
|
+
) : null}
|
|
33
|
+
{title ? <Heading fontSize="3xl">{title}</Heading> : null}
|
|
34
|
+
</React.Fragment>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function FeatureItems({ features }: { features?: ArrayOfImageTitleAndText[] }) {
|
|
39
|
+
if (!features) return null;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Flex wrap justify="start" className="-mx-3">
|
|
43
|
+
{features.map(feature => {
|
|
44
|
+
return <FeatureItem feature={feature} key={feature._key} />;
|
|
45
|
+
})}
|
|
46
|
+
</Flex>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function FeatureItem({ feature }: { feature: ArrayOfImageTitleAndText }) {
|
|
51
|
+
return (
|
|
52
|
+
<div className="w-full px-3 mb-6 lg:w-1/2">
|
|
53
|
+
<Card className="flex flex-wrap h-full p-6">
|
|
54
|
+
<div className="self-start inline-block p-3 mb-4 mr-6 rounded-lg bg-secondary-foreground md:p-5 lg:mb-0">
|
|
55
|
+
{feature?.mainImage?.image && (
|
|
56
|
+
<Image
|
|
57
|
+
className="object-scale-down"
|
|
58
|
+
src={`${feature?.mainImage?.image}`}
|
|
59
|
+
width={40}
|
|
60
|
+
height={40}
|
|
61
|
+
alt={feature?.mainImage?.alt ?? "features-main-image"}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
<div className="w-full lg:w-2/3">
|
|
66
|
+
<Text fontSize="2xl" weight="bold" className="mb-2 text-gray-500">
|
|
67
|
+
{feature?.title}
|
|
68
|
+
</Text>
|
|
69
|
+
<Text muted>{feature?.plainText}</Text>
|
|
70
|
+
</div>
|
|
71
|
+
</Card>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { Features_C };
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Card } from "@stackshift-ui/card";
|
|
2
|
+
import { Container } from "@stackshift-ui/container";
|
|
3
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
4
|
+
import { Heading } from "@stackshift-ui/heading";
|
|
5
|
+
import { Image } from "@stackshift-ui/image";
|
|
6
|
+
import { Section } from "@stackshift-ui/section";
|
|
7
|
+
import { Text } from "@stackshift-ui/text";
|
|
8
|
+
import React from "react";
|
|
9
|
+
import { FeaturesProps } from ".";
|
|
10
|
+
import { ArrayOfImageTitleAndText } from "./types";
|
|
11
|
+
|
|
12
|
+
export default function Features_D({ caption, title, features }: FeaturesProps) {
|
|
13
|
+
return (
|
|
14
|
+
<Section className="py-20 bg-background">
|
|
15
|
+
<Container maxWidth={1280}>
|
|
16
|
+
<Container maxWidth={448} className="mb-8 text-center">
|
|
17
|
+
<CaptionAndTitleSection caption={caption} title={title} />
|
|
18
|
+
</Container>
|
|
19
|
+
<FeatureItems features={features} />
|
|
20
|
+
</Container>
|
|
21
|
+
</Section>
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function CaptionAndTitleSection({ caption, title }: { caption?: string; title?: string }) {
|
|
26
|
+
return (
|
|
27
|
+
<React.Fragment>
|
|
28
|
+
{caption ? (
|
|
29
|
+
<Text weight="bold" className="text-primary">
|
|
30
|
+
{caption}
|
|
31
|
+
</Text>
|
|
32
|
+
) : null}
|
|
33
|
+
{title ? <Heading fontSize="3xl">{title}</Heading> : null}
|
|
34
|
+
</React.Fragment>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function FeatureItems({ features }: { features?: ArrayOfImageTitleAndText[] }) {
|
|
39
|
+
if (!features) return null;
|
|
40
|
+
|
|
41
|
+
return (
|
|
42
|
+
<Flex wrap justify="center">
|
|
43
|
+
{features.map(feature => (
|
|
44
|
+
<FeatureItem feature={feature} key={feature._key} />
|
|
45
|
+
))}
|
|
46
|
+
</Flex>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function FeatureItem({ feature }: { feature: ArrayOfImageTitleAndText }) {
|
|
51
|
+
return (
|
|
52
|
+
<div className="w-full px-4 mt-8 lg:mb-0 lg:w-1/3">
|
|
53
|
+
<Card className="h-full px-6 py-12 text-center">
|
|
54
|
+
<div className="self-start inline-block p-3 mb-6 rounded-lg bg-secondary-foreground md:p-5">
|
|
55
|
+
{feature?.mainImage?.image && (
|
|
56
|
+
<Image
|
|
57
|
+
className="object-scale-down"
|
|
58
|
+
src={`${feature?.mainImage?.image}`}
|
|
59
|
+
width={40}
|
|
60
|
+
height={40}
|
|
61
|
+
alt={feature?.mainImage?.alt ?? `features-image-`}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
<Text fontSize="xl" weight="bold" className="px-8 mb-4 text-gray-500">
|
|
66
|
+
{feature?.title}
|
|
67
|
+
</Text>
|
|
68
|
+
<Text muted>{feature?.plainText}</Text>
|
|
69
|
+
</Card>
|
|
70
|
+
</div>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export { Features_D };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { Button } from "@stackshift-ui/button";
|
|
2
|
+
import { Card } from "@stackshift-ui/card";
|
|
3
|
+
import { Container } from "@stackshift-ui/container";
|
|
4
|
+
import { Flex } from "@stackshift-ui/flex";
|
|
5
|
+
import { Heading } from "@stackshift-ui/heading";
|
|
6
|
+
import { Image } from "@stackshift-ui/image";
|
|
7
|
+
import { Section } from "@stackshift-ui/section";
|
|
8
|
+
import { Text } from "@stackshift-ui/text";
|
|
9
|
+
import React from "react";
|
|
10
|
+
import { FeaturesProps } from ".";
|
|
11
|
+
import { FeaturedItem } from "./types";
|
|
12
|
+
|
|
13
|
+
export default function Features_E({ featuredItems }: FeaturesProps) {
|
|
14
|
+
//for image carousel
|
|
15
|
+
let [item, setItem] = React.useState<number>(0);
|
|
16
|
+
|
|
17
|
+
const slider = (action: string) => {
|
|
18
|
+
if (featuredItems) {
|
|
19
|
+
action === "next"
|
|
20
|
+
? item !== featuredItems.length - 1
|
|
21
|
+
? setItem(prevState => prevState + 1)
|
|
22
|
+
: setItem(0)
|
|
23
|
+
: item >= 1
|
|
24
|
+
? setItem(prevState => prevState - 1)
|
|
25
|
+
: setItem(featuredItems.length - 1);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Section className="py-20 overflow-x-auto bg-background">
|
|
31
|
+
<Container maxWidth={1280}>
|
|
32
|
+
<Flex className="relative">
|
|
33
|
+
<SliderControls featuredItems={featuredItems} slider={slider}>
|
|
34
|
+
<div className="order-1 w-full ml-auto xl:w-4/5">
|
|
35
|
+
<ImageSection featuredItems={featuredItems} item={item} />
|
|
36
|
+
<FeaturesInfo featuredItems={featuredItems} item={item} />
|
|
37
|
+
</div>
|
|
38
|
+
</SliderControls>
|
|
39
|
+
</Flex>
|
|
40
|
+
</Container>
|
|
41
|
+
</Section>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function ImageSection({ featuredItems, item }: { featuredItems?: FeaturedItem[]; item: number }) {
|
|
46
|
+
if (!featuredItems?.[item]?.mainImage?.image) return null;
|
|
47
|
+
return (
|
|
48
|
+
<div className="mx-auto overflow-hidden rounded-md md:max-w-xl xl:max-w-4xl">
|
|
49
|
+
<Image
|
|
50
|
+
className="relative object-cover rounded-global"
|
|
51
|
+
src={`${featuredItems?.[item]?.mainImage?.image}`}
|
|
52
|
+
sizes="100vw"
|
|
53
|
+
width={896}
|
|
54
|
+
height={575}
|
|
55
|
+
alt={featuredItems?.[item]?.mainImage?.alt ?? `features-image-${item}`}
|
|
56
|
+
/>
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function FeaturesInfo({ featuredItems, item }: { featuredItems?: FeaturedItem[]; item: number }) {
|
|
62
|
+
if (!featuredItems) return null;
|
|
63
|
+
|
|
64
|
+
return (
|
|
65
|
+
<Card className="top-0 left-0 max-w-xl p-6 mx-auto text-center bg-white md:mt-12 md:p-10 lg:mt-12 lg:p-10 xl:absolute xl:mx-0 xl:mt-20 xl:py-24">
|
|
66
|
+
<Text weight="bold" className="text-xs lg:text-md md:text-sm xl:text-lg text-secondary">
|
|
67
|
+
{featuredItems?.[item]?.subtitle && featuredItems?.[item]?.subtitle}
|
|
68
|
+
</Text>
|
|
69
|
+
<Heading fontSize="3xl">
|
|
70
|
+
{featuredItems?.[item]?.title && featuredItems?.[item]?.title}
|
|
71
|
+
</Heading>
|
|
72
|
+
<Text
|
|
73
|
+
muted
|
|
74
|
+
className="text-xs leading-loose text-center md:mt-5 md:text-sm lg:mt-5 lg:text-sm">
|
|
75
|
+
{featuredItems?.[item]?.description && featuredItems?.[item]?.description}
|
|
76
|
+
</Text>
|
|
77
|
+
</Card>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function SliderControls({
|
|
82
|
+
featuredItems,
|
|
83
|
+
children,
|
|
84
|
+
slider,
|
|
85
|
+
}: {
|
|
86
|
+
featuredItems?: FeaturedItem[];
|
|
87
|
+
children: React.ReactNode;
|
|
88
|
+
slider: (action: string) => void;
|
|
89
|
+
}) {
|
|
90
|
+
if (!featuredItems) return null;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<React.Fragment>
|
|
94
|
+
<div className="absolute left-0 z-40 items-center mt-20 -mx-3 order-0 md:mt-40 lg:mt-60 xl:-mx-6 xl:flex">
|
|
95
|
+
{featuredItems?.length >= 2 && (
|
|
96
|
+
<Button
|
|
97
|
+
as="button"
|
|
98
|
+
ariaLabel="Show Previous Feature"
|
|
99
|
+
className="z-10 p-4 text-white "
|
|
100
|
+
onClick={() => slider("prev")}>
|
|
101
|
+
<svg
|
|
102
|
+
className="w-4 h-4"
|
|
103
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
104
|
+
fill="none"
|
|
105
|
+
viewBox="0 0 24 24"
|
|
106
|
+
stroke="currentColor">
|
|
107
|
+
<path
|
|
108
|
+
strokeLinecap="round"
|
|
109
|
+
strokeLinejoin="round"
|
|
110
|
+
strokeWidth="2"
|
|
111
|
+
d="M10 19l-7-7m0 0l7-7m-7 7h18"></path>
|
|
112
|
+
</svg>
|
|
113
|
+
</Button>
|
|
114
|
+
)}
|
|
115
|
+
</div>
|
|
116
|
+
{children}
|
|
117
|
+
<div className="absolute right-0 z-40 items-center order-2 mt-20 -mx-3 md:mt-40 lg:mt-60 xl:-mx-6 xl:flex">
|
|
118
|
+
{featuredItems?.length >= 2 && (
|
|
119
|
+
<Button
|
|
120
|
+
as="button"
|
|
121
|
+
ariaLabel="Show Next Feature"
|
|
122
|
+
className="p-4 text-white "
|
|
123
|
+
onClick={() => slider("next")}>
|
|
124
|
+
<svg
|
|
125
|
+
className="w-4 h-4"
|
|
126
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
127
|
+
fill="none"
|
|
128
|
+
viewBox="0 0 24 24"
|
|
129
|
+
stroke="currentColor">
|
|
130
|
+
<path
|
|
131
|
+
strokeLinecap="round"
|
|
132
|
+
strokeLinejoin="round"
|
|
133
|
+
strokeWidth="2"
|
|
134
|
+
d="M14 5l7 7m0 0l-7 7m7-7H3"></path>
|
|
135
|
+
</svg>
|
|
136
|
+
</Button>
|
|
137
|
+
)}
|
|
138
|
+
</div>
|
|
139
|
+
</React.Fragment>
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export { Features_E };
|