@treely/strapi-slices 3.3.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/README.md +2 -2
  2. package/dist/constants/slicesConfig.d.ts +5 -0
  3. package/dist/index.d.ts +1 -2
  4. package/dist/rootMessages.de.d.ts +2 -0
  5. package/dist/rootMessages.en.d.ts +2 -0
  6. package/dist/slices/Timeline/Timeline.d.ts +27 -0
  7. package/dist/slices/Timeline/index.d.ts +2 -0
  8. package/dist/slices/Timeline/messages.de.d.ts +5 -0
  9. package/dist/slices/Timeline/messages.en.d.ts +5 -0
  10. package/dist/strapi-slices.cjs.development.js +258 -43
  11. package/dist/strapi-slices.cjs.development.js.map +1 -1
  12. package/dist/strapi-slices.cjs.production.min.js +1 -1
  13. package/dist/strapi-slices.cjs.production.min.js.map +1 -1
  14. package/dist/strapi-slices.esm.js +260 -42
  15. package/dist/strapi-slices.esm.js.map +1 -1
  16. package/package.json +1 -1
  17. package/src/components/SliceRenderer/SliceRenderer.tsx +5 -0
  18. package/src/constants/{sectionsConfig.ts → slicesConfig.ts} +3 -6
  19. package/src/index.tsx +0 -11
  20. package/src/rootMessages.de.ts +2 -0
  21. package/src/rootMessages.en.ts +2 -0
  22. package/src/slices/Timeline/Timeline.stories.tsx +196 -0
  23. package/src/slices/Timeline/Timeline.test.tsx +228 -0
  24. package/src/slices/Timeline/Timeline.tsx +331 -0
  25. package/src/slices/Timeline/index.ts +3 -0
  26. package/src/slices/Timeline/messages.de.ts +5 -0
  27. package/src/slices/Timeline/messages.en.ts +5 -0
  28. package/src/utils/mergeGlobalAndStrapiBlogPostData.ts +6 -4
  29. package/src/utils/mergeGlobalAndStrapiCustomerStoryData.ts +2 -2
  30. package/src/utils/mergeGlobalAndStrapiPageData.ts +7 -7
  31. package/src/utils/mergeGlobalAndStrapiProjectData.ts +5 -5
  32. package/dist/constants/sectionsConfig.d.ts +0 -5
@@ -0,0 +1,331 @@
1
+ import React, { useContext } from 'react';
2
+ import {
3
+ Button,
4
+ Box,
5
+ Container,
6
+ DefaultSectionContainer,
7
+ DefaultSectionHeader,
8
+ Flex,
9
+ Heading,
10
+ RichText,
11
+ SimpleGrid,
12
+ Spacer,
13
+ Tag,
14
+ Text,
15
+ Wrapper,
16
+ useMediaQuery,
17
+ } from 'boemly';
18
+ import Image from 'next/image';
19
+ import StrapiImage from '../../models/strapi/StrapiImage';
20
+ import strapiMediaUrl from '../../utils/strapiMediaUrl';
21
+ import StrapiLink from '../../models/strapi/StrapiLink';
22
+ import StrapiLinkButton from '../../components/StrapiLinkButton';
23
+ import { CDN_URI } from '../../constants/api';
24
+ import { IntlContext } from 'react-intl';
25
+ import { BREAKPOINT_MD_QUERY } from '../../constants/breakpoints';
26
+ import { useState } from 'react';
27
+ import { FormattedMessage } from 'react-intl';
28
+ import FullScreenImage from '../../components/FullScreenImage';
29
+
30
+ export interface TimelineProps {
31
+ slice: {
32
+ title: string;
33
+ text?: string;
34
+ tagline?: string;
35
+
36
+ timelineItems: TimelineItem[];
37
+ };
38
+ }
39
+
40
+ export interface TimelineItem {
41
+ id: number;
42
+ tagline?: string;
43
+ title: string;
44
+ text?: string;
45
+ badge?: { text: string; variant: 'orange' | 'green' | 'red' | 'gray' };
46
+ logo?: StrapiImage;
47
+ icon?: StrapiImage;
48
+ image?: StrapiImage;
49
+ button?: StrapiLink;
50
+ backgroundShapes?: boolean;
51
+ }
52
+
53
+ export const Timeline: React.FC<TimelineProps> = ({ slice }: TimelineProps) => {
54
+ const { formatMessage } = useContext(IntlContext);
55
+ const [visibleItems, setVisibleItems] = useState(3);
56
+ const [mobile] = useMediaQuery(BREAKPOINT_MD_QUERY);
57
+ const [isOpen, setIsOpen] = useState(false);
58
+
59
+ const showMoreItems = () => {
60
+ setVisibleItems((prevVisibleItems) => prevVisibleItems + 3);
61
+ };
62
+
63
+ return (
64
+ <DefaultSectionContainer>
65
+ <Wrapper>
66
+ <Flex flexDir={['column', null, null, 'row']}>
67
+ <Box
68
+ width={['full', null, null, '50%']}
69
+ position={[null, null, null, 'sticky']}
70
+ top={['16', null, null, '32']}
71
+ height="full"
72
+ paddingRight={[null, null, null, '28']}
73
+ >
74
+ <DefaultSectionHeader
75
+ tagline={slice.tagline}
76
+ title={slice.title}
77
+ text={slice.text}
78
+ />
79
+ {mobile && (
80
+ <>
81
+ <Spacer h="10" />
82
+ <Flex justifyContent="center">
83
+ <Box
84
+ borderRadius="full"
85
+ width="3"
86
+ height="3"
87
+ margin="1.5"
88
+ backgroundColor="gray"
89
+ />
90
+ </Flex>
91
+ <Box
92
+ overflow="visible"
93
+ borderRight="dashed 1px var(--boemly-colors-gray-200)"
94
+ transform="translateX(-50%)"
95
+ position="relative"
96
+ height="20"
97
+ />
98
+ </>
99
+ )}
100
+ </Box>
101
+ <Box
102
+ overflow="visible"
103
+ maxWidth={['full', null, null, '50%']}
104
+ borderLeft={[
105
+ null,
106
+ null,
107
+ null,
108
+ 'dashed 1px var(--boemly-colors-gray-200)',
109
+ ]}
110
+ position="relative"
111
+ >
112
+ <Flex
113
+ flexDir="column"
114
+ overflow="visible"
115
+ gap={[null, null, null, '8']}
116
+ >
117
+ {slice.timelineItems.slice(0, visibleItems).map((item, index) => (
118
+ <SimpleGrid
119
+ gap={['none', null, null, '4']}
120
+ key={item.id}
121
+ columns={[1, null, null, 2]}
122
+ alignContent="center"
123
+ gridTemplateColumns={[null, null, null, '5% 85%']}
124
+ position="relative"
125
+ >
126
+ <Flex
127
+ alignItems="center"
128
+ justifyContent={['center', null, null, 'flex-start']}
129
+ >
130
+ <Box
131
+ position="absolute"
132
+ transform={[null, null, null, 'translateX(-50%)']}
133
+ backgroundColor="white"
134
+ >
135
+ {item.icon ? (
136
+ <Box padding="2">
137
+ <Image
138
+ src={strapiMediaUrl(item.icon.img, 'xSmall')}
139
+ alt={item.icon.alt}
140
+ width="21"
141
+ height="21"
142
+ />
143
+ </Box>
144
+ ) : (
145
+ <Box padding="2">
146
+ <Box
147
+ borderRadius="full"
148
+ backgroundColor="primary.800"
149
+ width="2"
150
+ height="2"
151
+ />
152
+ </Box>
153
+ )}
154
+ {mobile && (
155
+ <Box
156
+ overflow="visible"
157
+ borderRight="dashed 1px var(--boemly-colors-gray-200)"
158
+ transform="translateX(-50%)"
159
+ position="relative"
160
+ height="10"
161
+ />
162
+ )}
163
+ </Box>
164
+ </Flex>
165
+ <Container
166
+ p={[null, null, null, '3']}
167
+ zIndex="base"
168
+ position="relative"
169
+ elevation="none"
170
+ >
171
+ {item.backgroundShapes ? (
172
+ <Box
173
+ position="absolute"
174
+ left="0"
175
+ top="0"
176
+ width="full"
177
+ height="full"
178
+ zIndex="-1"
179
+ >
180
+ <Image
181
+ src={`${CDN_URI}/assets/v3/strapi-slices/timeline-shapes.svg`}
182
+ alt={formatMessage({
183
+ id: 'sections.timeline.backgroundShapes',
184
+ })}
185
+ fill
186
+ style={{
187
+ objectFit: 'cover',
188
+ borderRadius: 'var(--boemly-radii-xl)',
189
+ }}
190
+ />
191
+ </Box>
192
+ ) : (
193
+ <></>
194
+ )}
195
+
196
+ <Flex flexDir="column">
197
+ <Flex
198
+ alignItems="flex-start"
199
+ justifyContent="space-between"
200
+ >
201
+ <Box>
202
+ {item.tagline && (
203
+ <>
204
+ <Text color="primary.800" size="smMonoUppercase">
205
+ {item.tagline}
206
+ </Text>
207
+ <Spacer h="2" />
208
+ </>
209
+ )}
210
+ </Box>
211
+ <Flex>
212
+ {item.badge && (
213
+ <Tag
214
+ colorScheme={item.badge.variant}
215
+ borderRadius="md"
216
+ >
217
+ {item.badge.text}
218
+ </Tag>
219
+ )}
220
+ {item.logo && (
221
+ <Box position="relative" height="8" width="16">
222
+ <Image
223
+ src={strapiMediaUrl(item.logo.img, 'small')}
224
+ alt={item.logo.alt}
225
+ fill
226
+ style={{
227
+ objectFit: item.logo.objectFit,
228
+ }}
229
+ />
230
+ </Box>
231
+ )}
232
+ </Flex>
233
+ </Flex>
234
+ <Heading
235
+ size="lg"
236
+ mt={['6', null, null, '3']}
237
+ maxWidth="xs"
238
+ >
239
+ {item.title}
240
+ </Heading>
241
+ {item.text && (
242
+ <Box mt="3">
243
+ <RichText content={item.text} />
244
+ </Box>
245
+ )}
246
+ {item.button && (
247
+ <Box textAlign="left">
248
+ <Spacer h="4" />
249
+ <StrapiLinkButton
250
+ link={item.button}
251
+ size="sm"
252
+ variant="outline"
253
+ />
254
+ </Box>
255
+ )}
256
+ {item.image ? (
257
+ <>
258
+ <Box
259
+ position="relative"
260
+ mt="4"
261
+ height={['2xs', null, null, null, '48']}
262
+ minWidth={[null, null, null, null, '50%']}
263
+ >
264
+ <Image
265
+ src={strapiMediaUrl(item.image.img, 'xLarge')}
266
+ alt={item.image.alt}
267
+ fill
268
+ style={{
269
+ cursor: mobile ? 'unset' : 'pointer',
270
+ objectFit: item.image.objectFit || 'cover',
271
+ borderRadius: 'var(--boemly-radii-xl)',
272
+ }}
273
+ onClick={() => !mobile && setIsOpen(true)}
274
+ />
275
+ <FullScreenImage
276
+ images={[item.image]}
277
+ isOpen={isOpen}
278
+ onClose={() => setIsOpen(false)}
279
+ />
280
+ </Box>
281
+ </>
282
+ ) : (
283
+ <></>
284
+ )}
285
+ </Flex>
286
+ </Container>
287
+ {mobile && index + 1 < slice.timelineItems.length && (
288
+ <Box
289
+ overflow="visible"
290
+ borderRight="dashed 1px var(--boemly-colors-gray-200)"
291
+ transform="translateX(-50%)"
292
+ position="relative"
293
+ height="20"
294
+ />
295
+ )}
296
+ </SimpleGrid>
297
+ ))}
298
+ </Flex>
299
+ {visibleItems < slice.timelineItems.length && (
300
+ <>
301
+ <Box
302
+ width="full"
303
+ height={['36', null, null, '64']}
304
+ position="absolute"
305
+ bottom="0"
306
+ zIndex="1"
307
+ background="linear-gradient(180deg, rgba(255, 255, 255, 0.00) 0%, rgba(255, 255, 255, 0.98) 76.54%, #FFF 100%)"
308
+ />
309
+ <Box
310
+ bottom="0"
311
+ textAlign="center"
312
+ zIndex="overlay"
313
+ position="relative"
314
+ >
315
+ <Button
316
+ variant="outline"
317
+ size="sm"
318
+ onClick={showMoreItems}
319
+ m={[null, null, null, '8']}
320
+ >
321
+ <FormattedMessage id="sections.timeline.showMoreButton" />
322
+ </Button>
323
+ </Box>
324
+ </>
325
+ )}
326
+ </Box>
327
+ </Flex>
328
+ </Wrapper>
329
+ </DefaultSectionContainer>
330
+ );
331
+ };
@@ -0,0 +1,3 @@
1
+ import { Timeline } from './Timeline';
2
+
3
+ export default Timeline;
@@ -0,0 +1,5 @@
1
+ const messagesDe = {
2
+ 'sections.timeline.backgroundShapes': 'Hintergrundformen',
3
+ 'sections.timeline.showMoreButton': 'Drei weitere Meilensteine anzeigen',
4
+ };
5
+ export default messagesDe;
@@ -0,0 +1,5 @@
1
+ const messagesEn = {
2
+ 'sections.timeline.backgroundShapes': 'Background shapes',
3
+ 'sections.timeline.showMoreButton': 'Show three more milestones',
4
+ };
5
+ export default messagesEn;
@@ -2,14 +2,16 @@ import { GetStaticPropsContext } from 'next';
2
2
  import strapiMediaUrl from './strapiMediaUrl';
3
3
  import {
4
4
  IStrapiData,
5
- SECTIONS_WITH_BLOG_POSTS,
6
- SECTIONS_WITH_PROJECTS,
7
5
  StrapiBlogPost,
8
6
  StrapiBlogPostProps,
9
7
  StrapiGlobal,
10
8
  } from '..';
11
9
  import PortfolioProject from '../models/PortfolioProject';
12
10
  import { DEFAULT_SHARE_ALT, DEFAULT_SHARE_IMAGE } from '../constants/metadata';
11
+ import {
12
+ SLICES_WITH_BLOG_POSTS,
13
+ SLICES_WITH_PROJECTS,
14
+ } from '../constants/slicesConfig';
13
15
 
14
16
  const mergeGlobalAndStrapiBlogPostData = (
15
17
  context: GetStaticPropsContext,
@@ -27,10 +29,10 @@ const mergeGlobalAndStrapiBlogPostData = (
27
29
  : DEFAULT_SHARE_IMAGE;
28
30
 
29
31
  const returnBlog = post.attributes.slices.some((slice) =>
30
- SECTIONS_WITH_BLOG_POSTS.includes(slice.__component)
32
+ SLICES_WITH_BLOG_POSTS.includes(slice.__component)
31
33
  );
32
34
  const returnProjects = post.attributes.slices.some((slice) =>
33
- SECTIONS_WITH_PROJECTS.includes(slice.__component)
35
+ SLICES_WITH_PROJECTS.includes(slice.__component)
34
36
  );
35
37
 
36
38
  return {
@@ -2,12 +2,12 @@ import { GetStaticPropsContext } from 'next';
2
2
  import strapiMediaUrl from './strapiMediaUrl';
3
3
  import {
4
4
  IStrapiData,
5
- SECTIONS_WITH_CUSTOMER_STORIES,
6
5
  StrapiCustomerStory,
7
6
  StrapiCustomerStoryProps,
8
7
  StrapiGlobal,
9
8
  } from '..';
10
9
  import { DEFAULT_SHARE_ALT, DEFAULT_SHARE_IMAGE } from '../constants/metadata';
10
+ import { SLICES_WITH_CUSTOMER_STORIES } from '../constants/slicesConfig';
11
11
 
12
12
  const mergeGlobalAndStrapiCustomerStoryData = (
13
13
  context: GetStaticPropsContext,
@@ -24,7 +24,7 @@ const mergeGlobalAndStrapiCustomerStoryData = (
24
24
  : DEFAULT_SHARE_IMAGE;
25
25
 
26
26
  const returnCustomerStories = customerStory.attributes.slices.some((slice) =>
27
- SECTIONS_WITH_CUSTOMER_STORIES.includes(slice.__component)
27
+ SLICES_WITH_CUSTOMER_STORIES.includes(slice.__component)
28
28
  );
29
29
 
30
30
  return {
@@ -12,10 +12,10 @@ import PortfolioProject from '../models/PortfolioProject';
12
12
  import {
13
13
  DARK_THEME_HEADER_SECTIONS,
14
14
  EXTENDABLE_HEADER_SECTIONS,
15
- SECTIONS_WITH_BLOG_POSTS,
16
- SECTIONS_WITH_CUSTOMER_STORIES,
17
- SECTIONS_WITH_PROJECTS,
18
- } from '../constants/sectionsConfig';
15
+ SLICES_WITH_BLOG_POSTS,
16
+ SLICES_WITH_CUSTOMER_STORIES,
17
+ SLICES_WITH_PROJECTS,
18
+ } from '../constants/slicesConfig';
19
19
  import { DEFAULT_SHARE_ALT, DEFAULT_SHARE_IMAGE } from '../constants/metadata';
20
20
 
21
21
  const mergeGlobalAndStrapiPageData = (
@@ -35,13 +35,13 @@ const mergeGlobalAndStrapiPageData = (
35
35
  : DEFAULT_SHARE_IMAGE;
36
36
 
37
37
  const returnBlogPosts = page.attributes.slices.some((slice) =>
38
- SECTIONS_WITH_BLOG_POSTS.includes(slice.__component)
38
+ SLICES_WITH_BLOG_POSTS.includes(slice.__component)
39
39
  );
40
40
  const returnCustomerStories = page.attributes.slices.some((slice) =>
41
- SECTIONS_WITH_CUSTOMER_STORIES.includes(slice.__component)
41
+ SLICES_WITH_CUSTOMER_STORIES.includes(slice.__component)
42
42
  );
43
43
  const returnProjects = page.attributes.slices.some((slice) =>
44
- SECTIONS_WITH_PROJECTS.includes(slice.__component)
44
+ SLICES_WITH_PROJECTS.includes(slice.__component)
45
45
  );
46
46
 
47
47
  return {
@@ -11,9 +11,9 @@ import PortfolioProject from '../models/PortfolioProject';
11
11
  import {
12
12
  DARK_THEME_HEADER_SECTIONS,
13
13
  EXTENDABLE_HEADER_SECTIONS,
14
- SECTIONS_WITH_BLOG_POSTS,
15
- SECTIONS_WITH_PROJECTS,
16
- } from '../constants/sectionsConfig';
14
+ SLICES_WITH_BLOG_POSTS,
15
+ SLICES_WITH_PROJECTS,
16
+ } from '../constants/slicesConfig';
17
17
  import { DEFAULT_SHARE_ALT, DEFAULT_SHARE_IMAGE } from '../constants/metadata';
18
18
 
19
19
  const mergeGlobalAndStrapiProject = (
@@ -32,10 +32,10 @@ const mergeGlobalAndStrapiProject = (
32
32
  : DEFAULT_SHARE_IMAGE;
33
33
 
34
34
  const returnBlogPosts = project.attributes.slices.some((slice) =>
35
- SECTIONS_WITH_BLOG_POSTS.includes(slice.__component)
35
+ SLICES_WITH_BLOG_POSTS.includes(slice.__component)
36
36
  );
37
37
  const returnProjects = project.attributes.slices.some((slice) =>
38
- SECTIONS_WITH_PROJECTS.includes(slice.__component)
38
+ SLICES_WITH_PROJECTS.includes(slice.__component)
39
39
  );
40
40
 
41
41
  return {
@@ -1,5 +0,0 @@
1
- export declare const EXTENDABLE_HEADER_SECTIONS: string[];
2
- export declare const DARK_THEME_HEADER_SECTIONS: string[];
3
- export declare const SECTIONS_WITH_BLOG_POSTS: string[];
4
- export declare const SECTIONS_WITH_CUSTOMER_STORIES: string[];
5
- export declare const SECTIONS_WITH_PROJECTS: string[];