@comicrelief/component-library 8.77.3 → 8.77.5
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/index.cjs.js +1080 -1127
- package/dist/index.es.js +14245 -15072
- package/dist/style.css +1 -1
- package/package.json +1 -1
- package/src/components/Atoms/LogoNav2026/LogoNav2026.test.js +114 -114
- package/src/components/Molecules/ArticleTeaser/ArticleTeaser.js +1 -1
- package/src/components/Molecules/ArticleTeaser/ArticleTeaser.style.js +3 -3
- package/src/components/Molecules/ArticleTeaser/ArticleTeaser.test.js +58 -44
- package/src/components/Molecules/CTA/CTAMultiCard/__snapshots__/CTAMultiCard.test.js.snap +240 -100
- package/src/components/Molecules/CTA/CTASingleCard/__snapshots__/CTASingleCard.test.js.snap +101 -49
- package/src/components/Molecules/CTA/shared/CTACard.js +4 -3
- package/src/components/Molecules/CTA/shared/CTACard.style.js +48 -33
- package/src/components/Molecules/HeroBanner/HeroBanner.js +2 -3
- package/src/components/Molecules/HeroBanner/HeroBanner.style.js +35 -16
- package/src/components/Molecules/HeroBanner/__snapshots__/HeroBanner.test.js.snap +9 -6
- package/src/components/Molecules/shared/ctaArrow/CtaArrowCircle.style.js +5 -8
- package/src/components/Molecules/shared/ctaText/ctaText.style.js +1 -0
- package/src/components/Organisms/DonateBanner/Form/PopUpComponent.js +1 -1
- package/src/components/Organisms/RichtextCarousel/RichtextCarousel.js +43 -76
- package/src/components/Organisms/RichtextCarousel/RichtextCarousel.style.js +88 -157
- package/src/components/Organisms/RichtextCarousel/RichtextCarousel.test.js +167 -382
- package/src/components/Organisms/RichtextCarousel/RichtextCarouselExample.jsx +2 -2
- package/src/components/Organisms/WYMDCarousel/WYMDCarousel.js +29 -5
- package/src/components/Organisms/WYMDCarousel/WYMDCarousel.style.js +0 -13
- package/src/components/Organisms/WYMDCarousel/WYMDCarouselExample.jsx +2 -1
- package/src/components/Organisms/WYMDCarousel/__snapshots__/WYMDCarousel.test.js.snap +38 -22
- package/src/data/data.js +3 -2
- package/src/theme/shared/animations.js +4 -2
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import React, {
|
|
2
|
-
useEffect, useState
|
|
2
|
+
useEffect, useState
|
|
3
3
|
} from 'react';
|
|
4
4
|
import PropTypes from 'prop-types';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
import 'pure-react-carousel/dist/react-carousel.es.css';
|
|
5
|
+
|
|
6
|
+
import { Splide, SplideSlide } from '@splidejs/react-splide';
|
|
7
|
+
|
|
9
8
|
import {
|
|
10
9
|
CarouselWrapper, SlideCopyWrapper, HeadingCopyWrapper, Container
|
|
11
10
|
} from './RichtextCarousel.style';
|
|
@@ -29,51 +28,19 @@ const RichtextCarousel = ({
|
|
|
29
28
|
rowBackgroundColour = 'grey_light'
|
|
30
29
|
}
|
|
31
30
|
}) => {
|
|
32
|
-
// Defaults to mobile config:
|
|
33
|
-
const [isMobile, setIsMobile] = useState(true);
|
|
34
|
-
const [visibleSlides, setVisibleSlides] = useState(1);
|
|
35
|
-
const [totalSlides, setTotalSlides] = useState(null);
|
|
36
31
|
const [theseItems, setTheseItems] = useState();
|
|
37
32
|
|
|
38
|
-
// Custom function to let us update the carousel config dynamically
|
|
39
|
-
const screenResize = useCallback(() => {
|
|
40
|
-
const screenSize = typeof window !== 'undefined' ? window.innerWidth : null;
|
|
41
|
-
const isCurrentlyMobile = window.innerWidth < breakpointValues.M;
|
|
42
|
-
|
|
43
|
-
if (screenSize !== null && (isMobile !== isCurrentlyMobile)) {
|
|
44
|
-
setIsMobile(isCurrentlyMobile);
|
|
45
|
-
setVisibleSlides(isCurrentlyMobile ? 1 : 3);
|
|
46
|
-
setTotalSlides(isCurrentlyMobile ? theseItems.length : theseItems.length + 2);
|
|
47
|
-
}
|
|
48
|
-
}, [isMobile, theseItems]);
|
|
49
|
-
|
|
50
33
|
// Cache our data source, using as a flag for render logic:
|
|
51
34
|
useEffect(() => {
|
|
52
35
|
setTheseItems(nodes);
|
|
53
36
|
}, [setTheseItems, nodes]);
|
|
54
37
|
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
if (window !== 'undefined' && window.innerWidth >= breakpointValues.M) {
|
|
57
|
-
// On inital render, update carousel plugin config
|
|
58
|
-
// to suit the non-mobile layout and functionality:
|
|
59
|
-
setIsMobile(false);
|
|
60
|
-
setVisibleSlides(3);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// Hook into browser's own onresize event to call our custom wrapper function:
|
|
64
|
-
if (typeof window !== 'undefined') window.onresize = screenResize;
|
|
65
|
-
}, [screenResize]);
|
|
66
|
-
|
|
67
|
-
if (theseItems && totalSlides === null) {
|
|
68
|
-
// Reflects our two dummy/bookend slides for non-mobile/tablet views:
|
|
69
|
-
setTotalSlides(isMobile ? theseItems.length : theseItems.length + 2);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
38
|
return (
|
|
73
39
|
<Container
|
|
74
40
|
$paddingTop={paddingTop}
|
|
75
41
|
$paddingBottom={paddingBottom}
|
|
76
42
|
$rowBackgroundColour={rowBackgroundColour}
|
|
43
|
+
data-testid="richtext-carousel--container"
|
|
77
44
|
>
|
|
78
45
|
|
|
79
46
|
<CarouselWrapper
|
|
@@ -83,42 +50,52 @@ const RichtextCarousel = ({
|
|
|
83
50
|
$tabletHeight={tabletHeight}
|
|
84
51
|
$desktopHeight={desktopHeight}
|
|
85
52
|
$carouselBackgroundColour={carouselBackgroundColour}
|
|
53
|
+
data-testid="richtext-carousel--wrapper"
|
|
86
54
|
>
|
|
87
55
|
|
|
88
|
-
<HeadingCopyWrapper>
|
|
56
|
+
<HeadingCopyWrapper data-testid="richtext-carousel--heading">
|
|
89
57
|
{headingCopy}
|
|
90
58
|
</HeadingCopyWrapper>
|
|
91
59
|
|
|
92
60
|
{theseItems && (
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
61
|
+
<Splide
|
|
62
|
+
className="richtext-carousel"
|
|
63
|
+
data-testid="richtext-carousel--splide"
|
|
64
|
+
options={{
|
|
65
|
+
speed: 1000,
|
|
66
|
+
arrows: true,
|
|
67
|
+
pagination: false,
|
|
68
|
+
drag: 'free',
|
|
69
|
+
flickPower: 50,
|
|
70
|
+
perMove: 1,
|
|
71
|
+
dragMinThreshold: { mouse: 50, touch: 50 },
|
|
72
|
+
updateOnMove: true,
|
|
73
|
+
snap: true,
|
|
74
|
+
autoplay: autoPlay,
|
|
75
|
+
focus: 'center',
|
|
76
|
+
trimSpace: false,
|
|
77
|
+
perPage: 3,
|
|
78
|
+
rewind: true,
|
|
79
|
+
breakpoints: {
|
|
80
|
+
[breakpointValues.M]: {
|
|
81
|
+
perPage: 1
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}}
|
|
85
|
+
>
|
|
109
86
|
{Object.keys(theseItems).map((key, index) => {
|
|
110
|
-
|
|
111
|
-
const thisOffsetIndex = index + (isMobile ? 0 : 1);
|
|
87
|
+
const safeIndex = index;
|
|
112
88
|
|
|
113
89
|
return (
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
<
|
|
117
|
-
index={thisOffsetIndex}
|
|
90
|
+
// Calculate the index offset accordingly to reflect the number of slides,
|
|
91
|
+
// but use the REAL index when determining if its the last REAL slide
|
|
92
|
+
<SplideSlide
|
|
118
93
|
className={index === (theseItems.length - 1) && 'last-slide'}
|
|
119
|
-
key={
|
|
94
|
+
key={safeIndex}
|
|
95
|
+
index={safeIndex}
|
|
96
|
+
data-index={safeIndex}
|
|
97
|
+
data-testid="richtext-carousel--slide"
|
|
120
98
|
>
|
|
121
|
-
|
|
122
99
|
<SlideCopyWrapper
|
|
123
100
|
className="slide-copy-wrapper"
|
|
124
101
|
$mobileHeight={mobileHeight}
|
|
@@ -126,28 +103,18 @@ const RichtextCarousel = ({
|
|
|
126
103
|
$desktopHeight={desktopHeight}
|
|
127
104
|
$nodeBackgroundColour={nodeBackgroundColour}
|
|
128
105
|
$nodeOutlineColour={nodeOutlineColour}
|
|
106
|
+
data-testid="richtext-carousel--copy"
|
|
129
107
|
>
|
|
130
108
|
{theseItems[index].copy}
|
|
131
109
|
</SlideCopyWrapper>
|
|
132
110
|
|
|
133
|
-
</
|
|
111
|
+
</SplideSlide>
|
|
134
112
|
);
|
|
135
113
|
})}
|
|
136
|
-
|
|
137
|
-
{/* Dummy slide for our desired non-mobile layout and functionality */}
|
|
138
|
-
{isMobile === false && (
|
|
139
|
-
<Slide index={theseItems.length + 1} key="bookend-last" />
|
|
140
|
-
)}
|
|
141
|
-
|
|
142
|
-
</Slider>
|
|
143
|
-
<ButtonBack>Back</ButtonBack>
|
|
144
|
-
<ButtonNext>Next</ButtonNext>
|
|
145
|
-
</CarouselProvider>
|
|
114
|
+
</Splide>
|
|
146
115
|
)}
|
|
147
|
-
|
|
148
116
|
</CarouselWrapper>
|
|
149
117
|
</Container>
|
|
150
|
-
|
|
151
118
|
);
|
|
152
119
|
};
|
|
153
120
|
|
|
@@ -18,6 +18,13 @@ const SlideCopyWrapper = styled.div`
|
|
|
18
18
|
position: relative;
|
|
19
19
|
overflow: visible;
|
|
20
20
|
word-wrap: break-word;
|
|
21
|
+
font-size: 0.9rem;
|
|
22
|
+
line-height: 0.9rem;
|
|
23
|
+
|
|
24
|
+
* {
|
|
25
|
+
font-size: inherit;
|
|
26
|
+
line-height: inherit;
|
|
27
|
+
}
|
|
21
28
|
|
|
22
29
|
&:after {
|
|
23
30
|
position: absolute;
|
|
@@ -41,54 +48,61 @@ const SlideCopyWrapper = styled.div`
|
|
|
41
48
|
|
|
42
49
|
const HeadingCopyWrapper = styled.div`
|
|
43
50
|
text-align: center;
|
|
51
|
+
|
|
52
|
+
* {
|
|
53
|
+
margin-top: 0;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
h1, h2, h3 {
|
|
57
|
+
margin-bottom: 1.5rem;
|
|
58
|
+
}
|
|
44
59
|
`;
|
|
45
60
|
|
|
46
61
|
// Unfortunately having to target plugin-created markup ye olde fashioned way:
|
|
47
62
|
const CarouselWrapper = styled.div`
|
|
48
63
|
height: 100%;
|
|
49
64
|
background: ${({ theme, $carouselBackgroundColour }) => theme.color($carouselBackgroundColour)};
|
|
50
|
-
|
|
51
65
|
max-width: 760px;
|
|
52
66
|
padding: 2.5rem ${spacing('l')} 3.5rem;
|
|
53
67
|
margin: 0 auto;
|
|
54
|
-
|
|
55
68
|
border-radius: 20px;
|
|
56
69
|
${defaultBoxShadow()}
|
|
57
70
|
|
|
58
|
-
|
|
59
|
-
* {
|
|
60
|
-
margin-top: 0;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
h1, h2, h3 {
|
|
64
|
-
margin-bottom: 1.5rem;
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
.carousel {
|
|
71
|
+
.splide {
|
|
69
72
|
position: relative;
|
|
70
73
|
margin: 0 auto;
|
|
71
74
|
padding-top: ${spacing('l')};
|
|
72
75
|
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
// Navigation buttons:
|
|
77
|
+
.splide__arrows {
|
|
78
|
+
width: 100%;
|
|
79
|
+
position: absolute;
|
|
80
|
+
top: 0;
|
|
81
|
+
left: 0;
|
|
82
|
+
height: 100%;
|
|
83
|
+
width: 100%;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
button.splide__arrow {
|
|
75
87
|
position: absolute;
|
|
76
88
|
left: 0;
|
|
77
89
|
top: 0;
|
|
78
|
-
width: 33
|
|
90
|
+
width: 33.3%;
|
|
79
91
|
height: 100%;
|
|
80
|
-
padding: 0
|
|
92
|
+
padding: 0;
|
|
81
93
|
box-shadow: none;
|
|
82
94
|
text-indent: -9999px;
|
|
83
95
|
background-color: transparent;
|
|
84
|
-
|
|
96
|
+
transform: none;
|
|
97
|
+
border-radius: 0;
|
|
98
|
+
opacity: 1;
|
|
85
99
|
|
|
86
100
|
&:after {
|
|
87
101
|
content: "";
|
|
88
102
|
position: absolute;
|
|
89
103
|
top: 0;
|
|
90
104
|
left: 0;
|
|
91
|
-
width:
|
|
105
|
+
width: 100%;
|
|
92
106
|
height: 100%;
|
|
93
107
|
transition: opacity 0.2s linear;
|
|
94
108
|
background: ${({ theme, $carouselBackgroundColour }) => css`
|
|
@@ -97,165 +111,82 @@ const CarouselWrapper = styled.div`
|
|
|
97
111
|
`};
|
|
98
112
|
}
|
|
99
113
|
|
|
100
|
-
|
|
101
|
-
&:after {
|
|
102
|
-
opacity: 0.5;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
107
|
-
width: 33.3% !important;
|
|
108
|
-
&:after {
|
|
109
|
-
width: 100%;
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
button.carousel__next-button {
|
|
115
|
-
left: auto;
|
|
116
|
-
right: 0;
|
|
117
|
-
|
|
118
|
-
&:before {
|
|
119
|
-
transform: translate(0, -50%) rotate(-90deg);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
&:after {
|
|
114
|
+
&.splide__arrow--next {
|
|
123
115
|
left: auto;
|
|
124
116
|
right: 0;
|
|
125
117
|
|
|
126
|
-
|
|
118
|
+
&:after {
|
|
119
|
+
left: auto;
|
|
120
|
+
right: 0;
|
|
121
|
+
background: ${({ theme, $carouselBackgroundColour }) => css`
|
|
127
122
|
linear-gradient(90deg, ${theme.color($carouselBackgroundColour)}00,
|
|
128
123
|
${theme.color($carouselBackgroundColour)}7a, ${theme.color($carouselBackgroundColour)});
|
|
129
124
|
`};
|
|
125
|
+
}
|
|
130
126
|
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
.richtext-carousel {
|
|
134
|
-
// Override default animations
|
|
135
|
-
transition: -webkit-transform ${animationSpeed}s;
|
|
136
|
-
-o-transition: transform ${animationSpeed}s;
|
|
137
|
-
transition: transform ${animationSpeed}s;
|
|
138
|
-
-webkit-transform: ${animationSpeed}s;
|
|
139
|
-
will-change: transform;
|
|
140
127
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
128
|
+
&:hover {
|
|
129
|
+
&:after {
|
|
130
|
+
opacity: 0.5;
|
|
144
131
|
}
|
|
145
132
|
}
|
|
146
133
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
134
|
+
svg {
|
|
135
|
+
display: none;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
150
138
|
|
|
139
|
+
// Carousel:
|
|
140
|
+
&.richtext-carousel {
|
|
141
|
+
|
|
142
|
+
// All sides:
|
|
143
|
+
.splide__slide {
|
|
144
|
+
text-align: center;
|
|
145
|
+
display: inline-flex;
|
|
146
|
+
align-items: center;
|
|
147
|
+
justify-content: flex-start;
|
|
148
|
+
flex-direction: column;
|
|
149
|
+
height: ${props => props.$mobileHeight}px;
|
|
150
|
+
|
|
151
|
+
// No dashed 'connecting' line on the final slide
|
|
152
|
+
&.last-slide {
|
|
153
|
+
${SlideCopyWrapper} {
|
|
154
|
+
&:after {
|
|
155
|
+
content: none !important;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
151
160
|
// 'Tablet' (and up) tweaks for the 3-visible layout
|
|
152
161
|
@media ${({ theme }) => theme.allBreakpoints('M')} {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
right ${animationSpeed}s ease;
|
|
169
|
-
width: 100%;
|
|
170
|
-
right: calc(-100% - 6px);
|
|
171
|
-
transform: scale(1);
|
|
172
|
-
|
|
173
|
-
}
|
|
162
|
+
height: ${props => props.$tabletHeight}px;
|
|
163
|
+
|
|
164
|
+
// All 'SlideCopyWrapper's:
|
|
165
|
+
${SlideCopyWrapper} {
|
|
166
|
+
transition: transform ${animationSpeed}s ease;
|
|
167
|
+
transform-origin: center;
|
|
168
|
+
transform: scale(0.8);
|
|
169
|
+
|
|
170
|
+
&:after {
|
|
171
|
+
transition: transform ${animationSpeed}s ease,
|
|
172
|
+
width ${animationSpeed}s ease,
|
|
173
|
+
right ${animationSpeed}s ease;
|
|
174
|
+
width: 50%;
|
|
175
|
+
right: calc(-50% - 1px);
|
|
176
|
+
transform: scale(1);
|
|
174
177
|
}
|
|
175
178
|
}
|
|
176
179
|
|
|
177
|
-
// Our
|
|
178
|
-
&.
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
width: 33%;
|
|
183
|
-
right: calc(-33% - 3px);
|
|
184
|
-
transform: scale(1);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// 2nd and 3rd:
|
|
190
|
-
+ .carousel__slide--visible {
|
|
191
|
-
.carousel__inner-slide {
|
|
192
|
-
> div:first-child {
|
|
193
|
-
transform: scale(1);
|
|
194
|
-
&:after {
|
|
195
|
-
width: 33%;
|
|
196
|
-
right: calc(-33% + 3px);
|
|
197
|
-
transform: scale(0.8);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
|
|
202
|
-
// Resets the 3rd slide:
|
|
203
|
-
+ .carousel__slide--visible {
|
|
204
|
-
> div > div:first-child {
|
|
205
|
-
transform: scale(0.8);
|
|
206
|
-
&:after {
|
|
207
|
-
width: 50%;
|
|
208
|
-
right: calc(-50% - 6px);
|
|
209
|
-
transform: scale(1);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
180
|
+
// Our middle, active slide:
|
|
181
|
+
&.is-active {
|
|
182
|
+
${SlideCopyWrapper} {
|
|
183
|
+
transform: scale(1.0);
|
|
184
|
+
}
|
|
214
185
|
}
|
|
215
186
|
}
|
|
216
187
|
|
|
217
|
-
// 'Desktop'
|
|
218
188
|
@media ${({ theme }) => theme.allBreakpoints('L')} {
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
// First
|
|
222
|
-
&.carousel__slide--visible {
|
|
223
|
-
|
|
224
|
-
// 2nd and 3rd
|
|
225
|
-
+ .carousel__slide--visible {
|
|
226
|
-
|
|
227
|
-
// 3rd only
|
|
228
|
-
+ .carousel__slide--visible {
|
|
229
|
-
.carousel__inner-slide {
|
|
230
|
-
> div:first-child {
|
|
231
|
-
&:after {
|
|
232
|
-
right: calc(-125% - 5px);
|
|
233
|
-
width: 125%;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
// END OF DESKTOP
|
|
242
|
-
|
|
243
|
-
.carousel__inner-slide {
|
|
244
|
-
text-align: center;
|
|
245
|
-
display: inline-flex;
|
|
246
|
-
align-items: center;
|
|
247
|
-
justify-content: flex-start;
|
|
248
|
-
flex-direction: column;
|
|
249
|
-
|
|
250
|
-
.slide-copy-wrapper {
|
|
251
|
-
font-size: 0.9rem;
|
|
252
|
-
line-height: 0.9rem;
|
|
253
|
-
|
|
254
|
-
* {
|
|
255
|
-
font-size: inherit;
|
|
256
|
-
line-height: inherit;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
189
|
+
height: ${props => props.$desktopHeight}px;
|
|
259
190
|
}
|
|
260
191
|
}
|
|
261
192
|
}
|