@comicrelief/component-library 8.2.1 → 8.3.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.
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+
3
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
4
+ Object.defineProperty(exports, "__esModule", {
5
+ value: true
6
+ });
7
+ exports.default = void 0;
8
+ var _react = _interopRequireWildcard(require("react"));
9
+ var _pureReactCarousel = require("pure-react-carousel");
10
+ require("pure-react-carousel/dist/react-carousel.es.css");
11
+ var _RichtextCarousel = require("./RichtextCarousel.style");
12
+ var _allBreakpoints = require("../../../theme/shared/allBreakpoints");
13
+ const RichtextCarousel = _ref => {
14
+ let {
15
+ data: {
16
+ contentful_id: thisID,
17
+ autoPlay,
18
+ nodes,
19
+ headingCopy,
20
+ // Set some defaults for good measure:
21
+ mobileHeight = 300,
22
+ tabletHeight = 350,
23
+ desktopHeight = 350,
24
+ carouselBackgroundColour = 'white',
25
+ nodeBackgroundColour = 'white',
26
+ nodeOutlineColour = 'grey'
27
+ }
28
+ } = _ref;
29
+ // Defaults to mobile config:
30
+ const [isMobile, setIsMobile] = (0, _react.useState)(true);
31
+ const [visibleSlides, setVisibleSlides] = (0, _react.useState)(1);
32
+ const [totalSlides, setTotalSlides] = (0, _react.useState)(null);
33
+ const [theseItems, setTheseItems] = (0, _react.useState)();
34
+
35
+ // Custom function to let us update the carousel config dynamically
36
+ const screenResize = (0, _react.useCallback)(() => {
37
+ const screenSize = typeof window !== 'undefined' ? window.innerWidth : null;
38
+ const isCurrentlyMobile = window.innerWidth < _allBreakpoints.breakpointValues.M;
39
+ if (screenSize !== null && isMobile !== isCurrentlyMobile) {
40
+ setIsMobile(isCurrentlyMobile);
41
+ setVisibleSlides(isCurrentlyMobile ? 1 : 3);
42
+ setTotalSlides(isCurrentlyMobile ? theseItems.length : theseItems.length + 2);
43
+ }
44
+ }, [isMobile, theseItems]);
45
+
46
+ // Cache our data source, using as a flag for render logic:
47
+ (0, _react.useEffect)(() => {
48
+ setTheseItems(nodes);
49
+ }, [setTheseItems, nodes]);
50
+ (0, _react.useEffect)(() => {
51
+ if (window !== 'undefined' && window.innerWidth >= _allBreakpoints.breakpointValues.M) {
52
+ // On inital render, update carousel plugin config
53
+ // to suit the non-mobile layout and functionality:
54
+ setIsMobile(false);
55
+ setVisibleSlides(3);
56
+ }
57
+
58
+ // Hook into browser's own onresize event to call our custom wrapper function:
59
+ if (typeof window !== 'undefined') window.onresize = screenResize;
60
+ }, [screenResize]);
61
+ if (theseItems && totalSlides === null) {
62
+ // Reflects our two dummy/bookend slides for non-mobile/tablet views:
63
+ setTotalSlides(isMobile ? theseItems.length : theseItems.length + 2);
64
+ }
65
+ return /*#__PURE__*/_react.default.createElement(_RichtextCarousel.CarouselWrapper, {
66
+ className: "CarouselWrapper",
67
+ id: thisID,
68
+ mobileHeight: mobileHeight,
69
+ tabletHeight: tabletHeight,
70
+ desktopHeight: desktopHeight,
71
+ carouselBackgroundColour: carouselBackgroundColour
72
+ }, /*#__PURE__*/_react.default.createElement(_RichtextCarousel.HeadingCopyWrapper, null, headingCopy), theseItems && /*#__PURE__*/_react.default.createElement(_pureReactCarousel.CarouselProvider, {
73
+ naturalSlideWidth: 50,
74
+ naturalSlideHeight: 200,
75
+ totalSlides: totalSlides,
76
+ isPlaying: autoPlay,
77
+ interval: 5000,
78
+ visibleSlides: visibleSlides,
79
+ infinite: true
80
+ }, /*#__PURE__*/_react.default.createElement(_pureReactCarousel.Slider, {
81
+ classNameAnimation: "richtext-carousel"
82
+ }, isMobile === false && /*#__PURE__*/_react.default.createElement(_pureReactCarousel.Slide, {
83
+ index: 0,
84
+ key: 0
85
+ }), Object.keys(theseItems).map((key, index) => {
86
+ // Reflect that initial dummy/bookend slide shown on non-mobile/tablet views:
87
+ const thisOffsetIndex = index + (isMobile ? 0 : 1);
88
+ return (
89
+ /*#__PURE__*/
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
+ _react.default.createElement(_pureReactCarousel.Slide, {
93
+ index: thisOffsetIndex,
94
+ className: index === theseItems.length - 1 && 'last-slide',
95
+ key: thisOffsetIndex
96
+ }, /*#__PURE__*/_react.default.createElement(_RichtextCarousel.SlideCopyWrapper, {
97
+ className: "slide-copy-wrapper",
98
+ mobileHeight: mobileHeight,
99
+ tabletHeight: tabletHeight,
100
+ desktopHeight: desktopHeight,
101
+ nodeBackgroundColour: nodeBackgroundColour,
102
+ nodeOutlineColour: nodeOutlineColour
103
+ }, theseItems[index].copy))
104
+ );
105
+ }), isMobile === false && /*#__PURE__*/_react.default.createElement(_pureReactCarousel.Slide, {
106
+ index: theseItems.length + 1,
107
+ key: "bookend-last"
108
+ })), /*#__PURE__*/_react.default.createElement(_pureReactCarousel.ButtonBack, null, "Back"), /*#__PURE__*/_react.default.createElement(_pureReactCarousel.ButtonNext, null, "Next")));
109
+ };
110
+ var _default = exports.default = RichtextCarousel;
@@ -0,0 +1,14 @@
1
+ # Richtext Carousel
2
+
3
+ ```js
4
+ const { RichtextCarouselItems } = require('../../../styleguide/data/data');
5
+
6
+ <div>
7
+ <h2 style={{textAlign: 'center'}}>
8
+ Richtext Carousel #1
9
+ </h2>
10
+ <RichtextCarousel
11
+ data={RichtextCarouselItems}/>
12
+ </div>
13
+
14
+ ```
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
5
+ Object.defineProperty(exports, "__esModule", {
6
+ value: true
7
+ });
8
+ exports.SlideCopyWrapper = exports.HeadingCopyWrapper = exports.CarouselWrapper = void 0;
9
+ var _styledComponents = _interopRequireWildcard(require("styled-components"));
10
+ var _spacing = _interopRequireDefault(require("../../../theme/shared/spacing"));
11
+ // import Text from '../../Atoms/Text/Text';
12
+ // Duration in seconds
13
+ const animationSpeed = 0.75;
14
+ const SlideCopyWrapper = exports.SlideCopyWrapper = _styledComponents.default.div.withConfig({
15
+ displayName: "RichtextCarouselstyle__SlideCopyWrapper",
16
+ componentId: "sc-35wlbv-0"
17
+ })(["background:", ";height:", "px;width:75%;display:flex;flex-direction:column;justify-content:center;padding:25px;border:1px dashed ", ";border-radius:20px;position:relative;overflow:visible;word-wrap:break-word;&:after{position:absolute;content:'';top:50%;width:34%;right:calc(-34% - 0px);height:2px;border-bottom:1px dashed ", ";}@media ", "{height:", "px;width:85%;}@media ", "{height:", "px;}"], _ref => {
18
+ let {
19
+ theme,
20
+ nodeBackgroundColour
21
+ } = _ref;
22
+ return theme.color(nodeBackgroundColour);
23
+ }, props => props.mobileHeight, _ref2 => {
24
+ let {
25
+ theme,
26
+ nodeOutlineColour
27
+ } = _ref2;
28
+ return theme.color(nodeOutlineColour);
29
+ }, _ref3 => {
30
+ let {
31
+ theme,
32
+ nodeOutlineColour
33
+ } = _ref3;
34
+ return theme.color(nodeOutlineColour);
35
+ }, _ref4 => {
36
+ let {
37
+ theme
38
+ } = _ref4;
39
+ return theme.allBreakpoints('M');
40
+ }, props => props.tabletHeight, _ref5 => {
41
+ let {
42
+ theme
43
+ } = _ref5;
44
+ return theme.allBreakpoints('L');
45
+ }, props => props.desktopHeight);
46
+ const HeadingCopyWrapper = exports.HeadingCopyWrapper = _styledComponents.default.div.withConfig({
47
+ displayName: "RichtextCarouselstyle__HeadingCopyWrapper",
48
+ componentId: "sc-35wlbv-1"
49
+ })(["text-align:center;"]);
50
+
51
+ // Unfortunately having to target plugin-created markup ye olde fashioned way:
52
+ const CarouselWrapper = exports.CarouselWrapper = _styledComponents.default.div.withConfig({
53
+ displayName: "RichtextCarouselstyle__CarouselWrapper",
54
+ componentId: "sc-35wlbv-2"
55
+ })(["height:100%;background:", ";max-width:760px;padding:2.5rem ", " 3.5rem;margin:0 auto;border-radius:20px;box-shadow:0px 0px 20px rgba(0,0,0,0.15);.carousel{position:relative;margin:0 auto;padding-top:", ";button.carousel__back-button,button.carousel__next-button{position:absolute;left:0;top:0;width:33% !important;height:100%;padding:0 !important;box-shadow:none;text-indent:-9999px;background-color:transparent;border:none;&:after{content:\"\";position:absolute;top:0;left:0;width:50%;height:100%;transition:opacity 0.2s linear;background:", ";}&:hover{&:after{opacity:0.5;}}@media ", "{width:33.3% !important;&:after{width:100%;}}}button.carousel__next-button{left:auto;right:0;&:before{transform:translate(0,-50%) rotate(-90deg);}&:after{left:auto;right:0;background:", ";}}.richtext-carousel{transition:-webkit-transform ", "s;-o-transition:transform ", "s;transition:transform ", "s;-webkit-transform:", "s;will-change:transform;.last-slide{.slide-copy-wrapper:after{content:none;}}.carousel__slide{padding-bottom:", "px !important;@media ", "{padding-bottom:", "px !important;.carousel__inner-slide{> div:first-child{transition:transform ", "s ease;transform-origin:center;transform:scale(0.8);&:after{transition:transform ", "s ease,width ", "s ease,right ", "s ease;width:100%;right:calc(-100% - 6px);transform:scale(1);}}}&.carousel__slide--visible{.carousel__inner-slide{> div:first-child{&:after{width:33%;right:calc(-33% - 3px);transform:scale(1);}}}+ .carousel__slide--visible{.carousel__inner-slide{> div:first-child{transform:scale(1);&:after{width:33%;right:calc(-33% + 3px);transform:scale(0.8);}}}+ .carousel__slide--visible{> div > div:first-child{transform:scale(0.8);&:after{width:50%;right:calc(-50% - 6px);transform:scale(1);}}}}}}@media ", "{padding-bottom:", "px !important;&.carousel__slide--visible{+ .carousel__slide--visible{+ .carousel__slide--visible{.carousel__inner-slide{> div:first-child{&:after{right:calc(-125% - 5px);width:125%;}}}}}}}.carousel__inner-slide{text-align:center;display:inline-flex;align-items:center;justify-content:flex-start;flex-direction:column;}}}}"], _ref6 => {
56
+ let {
57
+ theme,
58
+ carouselBackgroundColour
59
+ } = _ref6;
60
+ return theme.color(carouselBackgroundColour);
61
+ }, (0, _spacing.default)('l'), (0, _spacing.default)('l'), _ref7 => {
62
+ let {
63
+ theme,
64
+ carouselBackgroundColour
65
+ } = _ref7;
66
+ return (0, _styledComponents.css)(["linear-gradient(90deg,", ",", "7a,", "00);"], theme.color(carouselBackgroundColour), theme.color(carouselBackgroundColour), theme.color(carouselBackgroundColour));
67
+ }, _ref8 => {
68
+ let {
69
+ theme
70
+ } = _ref8;
71
+ return theme.allBreakpoints('M');
72
+ }, _ref9 => {
73
+ let {
74
+ theme,
75
+ carouselBackgroundColour
76
+ } = _ref9;
77
+ return (0, _styledComponents.css)(["linear-gradient(90deg,", "00,", "7a,", ");"], theme.color(carouselBackgroundColour), theme.color(carouselBackgroundColour), theme.color(carouselBackgroundColour));
78
+ }, animationSpeed, animationSpeed, animationSpeed, animationSpeed, props => props.mobileHeight, _ref10 => {
79
+ let {
80
+ theme
81
+ } = _ref10;
82
+ return theme.allBreakpoints('M');
83
+ }, props => props.tabletHeight, animationSpeed, animationSpeed, animationSpeed, animationSpeed, _ref11 => {
84
+ let {
85
+ theme
86
+ } = _ref11;
87
+ return theme.allBreakpoints('L');
88
+ }, props => props.desktopHeight);
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+
3
+ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
4
+ var _react = _interopRequireDefault(require("react"));
5
+ require("jest-styled-components");
6
+ var _shallowWithTheme = _interopRequireDefault(require("../../../../tests/hoc/shallowWithTheme"));
7
+ var _RichtextCarousel = _interopRequireDefault(require("./RichtextCarousel"));
8
+ const {
9
+ RichtextCarouselItems
10
+ } = require("../../../styleguide/data/data");
11
+ it("renders correctly", () => {
12
+ const tree = (0, _shallowWithTheme.default)( /*#__PURE__*/_react.default.createElement(_RichtextCarousel.default, {
13
+ data: RichtextCarouselItems
14
+ })).toJSON();
15
+ expect(tree).toMatchInlineSnapshot("\n .c1 {\n text-align: center;\n }\n\n .c0 {\n height: 100%;\n background: #FFFFFF;\n max-width: 760px;\n padding: 2.5rem 2rem 3.5rem;\n margin: 0 auto;\n border-radius: 20px;\n box-shadow: 0px 0px 20px rgba(0,0,0,0.15);\n }\n\n .c0 .carousel {\n position: relative;\n margin: 0 auto;\n padding-top: 2rem;\n }\n\n .c0 .carousel button.carousel__back-button,\n .c0 .carousel button.carousel__next-button {\n position: absolute;\n left: 0;\n top: 0;\n width: 33% !important;\n height: 100%;\n padding: 0 !important;\n box-shadow: none;\n text-indent: -9999px;\n background-color: transparent;\n border: none;\n }\n\n .c0 .carousel button.carousel__back-button:after,\n .c0 .carousel button.carousel__next-button:after {\n content: \"\";\n position: absolute;\n top: 0;\n left: 0;\n width: 50%;\n height: 100%;\n -webkit-transition: opacity 0.2s linear;\n transition: opacity 0.2s linear;\n background: linear-gradient(90deg,#FFFFFF,#FFFFFF7a,#FFFFFF00);\n }\n\n .c0 .carousel button.carousel__back-button:hover:after,\n .c0 .carousel button.carousel__next-button:hover:after {\n opacity: 0.5;\n }\n\n .c0 .carousel button.carousel__next-button {\n left: auto;\n right: 0;\n }\n\n .c0 .carousel button.carousel__next-button:before {\n -webkit-transform: translate(0,-50%) rotate(-90deg);\n -ms-transform: translate(0,-50%) rotate(-90deg);\n transform: translate(0,-50%) rotate(-90deg);\n }\n\n .c0 .carousel button.carousel__next-button:after {\n left: auto;\n right: 0;\n background: linear-gradient(90deg,#FFFFFF00,#FFFFFF7a,#FFFFFF);\n }\n\n .c0 .carousel .richtext-carousel {\n -webkit-transition: -webkit-transform 0.75s;\n -webkit-transition: -webkit-transform 0.75s;\n transition: -webkit-transform 0.75s;\n -o-transition: transform 0.75s;\n -webkit-transition: -webkit-transform 0.75s;\n -webkit-transition: transform 0.75s;\n transition: transform 0.75s;\n -webkit-transform: 0.75s;\n will-change: transform;\n }\n\n .c0 .carousel .richtext-carousel .last-slide .slide-copy-wrapper:after {\n content: none;\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide {\n padding-bottom: 300px !important;\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide .carousel__inner-slide {\n text-align: center;\n display: -webkit-inline-box;\n display: -webkit-inline-flex;\n display: -ms-inline-flexbox;\n display: inline-flex;\n -webkit-align-items: center;\n -webkit-box-align: center;\n -ms-flex-align: center;\n align-items: center;\n -webkit-box-pack: start;\n -webkit-justify-content: flex-start;\n -ms-flex-pack: start;\n justify-content: flex-start;\n -webkit-flex-direction: column;\n -ms-flex-direction: column;\n flex-direction: column;\n }\n\n @media (min-width:740px) {\n .c0 .carousel button.carousel__back-button,\n .c0 .carousel button.carousel__next-button {\n width: 33.3% !important;\n }\n\n .c0 .carousel button.carousel__back-button:after,\n .c0 .carousel button.carousel__next-button:after {\n width: 100%;\n }\n }\n\n @media (min-width:740px) {\n .c0 .carousel .richtext-carousel .carousel__slide {\n padding-bottom: 350px !important;\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide .carousel__inner-slide > div:first-child {\n -webkit-transition: -webkit-transform 0.75s ease;\n -webkit-transition: transform 0.75s ease;\n transition: transform 0.75s ease;\n -webkit-transform-origin: center;\n -ms-transform-origin: center;\n transform-origin: center;\n -webkit-transform: scale(0.8);\n -ms-transform: scale(0.8);\n transform: scale(0.8);\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide .carousel__inner-slide > div:first-child:after {\n -webkit-transition: -webkit-transform 0.75s ease,width 0.75s ease,right 0.75s ease;\n -webkit-transition: transform 0.75s ease,width 0.75s ease,right 0.75s ease;\n transition: transform 0.75s ease,width 0.75s ease,right 0.75s ease;\n width: 100%;\n right: calc(-100% - 6px);\n -webkit-transform: scale(1);\n -ms-transform: scale(1);\n transform: scale(1);\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible .carousel__inner-slide > div:first-child:after {\n width: 33%;\n right: calc(-33% - 3px);\n -webkit-transform: scale(1);\n -ms-transform: scale(1);\n transform: scale(1);\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible .carousel__inner-slide > div:first-child {\n -webkit-transform: scale(1);\n -ms-transform: scale(1);\n transform: scale(1);\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible .carousel__inner-slide > div:first-child:after {\n width: 33%;\n right: calc(-33% + 3px);\n -webkit-transform: scale(0.8);\n -ms-transform: scale(0.8);\n transform: scale(0.8);\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible + .carousel__slide--visible > div > div:first-child {\n -webkit-transform: scale(0.8);\n -ms-transform: scale(0.8);\n transform: scale(0.8);\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible + .carousel__slide--visible > div > div:first-child:after {\n width: 50%;\n right: calc(-50% - 6px);\n -webkit-transform: scale(1);\n -ms-transform: scale(1);\n transform: scale(1);\n }\n }\n\n @media (min-width:1024px) {\n .c0 .carousel .richtext-carousel .carousel__slide {\n padding-bottom: 350px !important;\n }\n\n .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible + .carousel__slide--visible .carousel__inner-slide > div:first-child:after {\n right: calc(-125% - 5px);\n width: 125%;\n }\n }\n\n <div\n className=\"c0 CarouselWrapper\"\n id=\"nqIEHjiYE8Yd2A2a5cI3O\"\n >\n <div\n className=\"c1\"\n >\n Some heading copy that will be nicely constructed in-situ\n </div>\n </div>\n ");
16
+ });
package/dist/index.js CHANGED
@@ -232,6 +232,12 @@ Object.defineProperty(exports, "RichText", {
232
232
  return _RichText.default;
233
233
  }
234
234
  });
235
+ Object.defineProperty(exports, "RichtextCarousel", {
236
+ enumerable: true,
237
+ get: function () {
238
+ return _RichtextCarousel.default;
239
+ }
240
+ });
235
241
  Object.defineProperty(exports, "SchoolLookup", {
236
242
  enumerable: true,
237
243
  get: function () {
@@ -454,4 +460,5 @@ var _CookieBanner = _interopRequireDefault(require("./components/Organisms/Cooki
454
460
  var _Membership = _interopRequireDefault(require("./components/Organisms/Membership/Membership"));
455
461
  var _MarketingPreferencesDS = require("./components/Organisms/MarketingPreferencesDS/_MarketingPreferencesDS");
456
462
  var _ImpactSlider = _interopRequireDefault(require("./components/Organisms/ImpactSlider/ImpactSlider"));
457
- var _WYMDCarousel = _interopRequireDefault(require("./components/Organisms/WYMDCarousel/WYMDCarousel"));
463
+ var _WYMDCarousel = _interopRequireDefault(require("./components/Organisms/WYMDCarousel/WYMDCarousel"));
464
+ var _RichtextCarousel = _interopRequireDefault(require("./components/Organisms/RichtextCarousel/RichtextCarousel"));
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.testImpactSliderItems = exports.mobileImages = exports.defaultData = exports.carouselItemsMinimal = exports.carouselItemsIncomplete = exports.carouselItemsComplete = void 0;
6
+ exports.testImpactSliderItems = exports.mobileImages = exports.defaultData = exports.carouselItemsMinimal = exports.carouselItemsIncomplete = exports.carouselItemsComplete = exports.RichtextCarouselItems = void 0;
7
7
  const defaultData = exports.defaultData = {
8
8
  title: 'What your money does',
9
9
  text: 'When you donate to Comic Relief or Sport Relief, you’re supporting vulnerable people and communities in the UK and internationally.',
@@ -210,4 +210,19 @@ const carouselItemsMinimal = exports.carouselItemsMinimal = {
210
210
  url: '//images.ctfassets.net/zsfivwzfgl3t/45yv3H0XZsvsySHtutQ8vb/1fb6d1afe4037c7dccde743a747f6b4f/Test-Carousel-Icon.png'
211
211
  }
212
212
  }
213
+ };
214
+ const RichtextCarouselItems = exports.RichtextCarouselItems = {
215
+ contentful_id: 'nqIEHjiYE8Yd2A2a5cI3O',
216
+ // Ugly here, but to be provided by Richtextrender function in-situ:
217
+ headingCopy: 'Some heading copy that will be nicely constructed in-situ',
218
+ nodes: [{
219
+ copy: 'Some other longside but not really all that long copy, who knows, it could be this long or LESS.'
220
+ }, {
221
+ copy: '140 character count limit imposed in messages to fix the design height of each container and restrict anomalies. This is based on Twitters character limit for tweets.'
222
+ }, {
223
+ copy: 'Some other longside but not really all that long copy, who knows, it could be this long or LESS'
224
+ }, {
225
+ copy: '140 character count limit imposed in messages to fix the design height of each container and restrict anomalies. This is based on Twitters character limit for tweets. ABIGLONGLINETOFORCEONTOANEWONE'
226
+ }],
227
+ autoPlay: true
213
228
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@comicrelief/component-library",
3
3
  "author": "Comic Relief Engineering Team",
4
- "version": "8.2.1",
4
+ "version": "8.3.0",
5
5
  "main": "dist/index.js",
6
6
  "license": "ISC",
7
7
  "jest": {
@@ -0,0 +1,160 @@
1
+ import React, {
2
+ useEffect, useState, useCallback
3
+ } from 'react';
4
+ import PropTypes from 'prop-types';
5
+ import {
6
+ CarouselProvider, Slider, Slide, ButtonBack, ButtonNext
7
+ } from 'pure-react-carousel';
8
+ import 'pure-react-carousel/dist/react-carousel.es.css';
9
+ import {
10
+ CarouselWrapper, SlideCopyWrapper, HeadingCopyWrapper
11
+ } from './RichtextCarousel.style';
12
+ import { breakpointValues } from '../../../theme/shared/allBreakpoints';
13
+
14
+ const RichtextCarousel = ({
15
+ data: {
16
+ contentful_id: thisID,
17
+ autoPlay,
18
+ nodes,
19
+ headingCopy,
20
+ // Set some defaults for good measure:
21
+ mobileHeight = 300,
22
+ tabletHeight = 350,
23
+ desktopHeight = 350,
24
+ carouselBackgroundColour = 'white',
25
+ nodeBackgroundColour = 'white',
26
+ nodeOutlineColour = 'grey'
27
+ }
28
+ }) => {
29
+ // Defaults to mobile config:
30
+ const [isMobile, setIsMobile] = useState(true);
31
+ const [visibleSlides, setVisibleSlides] = useState(1);
32
+ const [totalSlides, setTotalSlides] = useState(null);
33
+ const [theseItems, setTheseItems] = useState();
34
+
35
+ // Custom function to let us update the carousel config dynamically
36
+ const screenResize = useCallback(() => {
37
+ const screenSize = typeof window !== 'undefined' ? window.innerWidth : null;
38
+ const isCurrentlyMobile = window.innerWidth < breakpointValues.M;
39
+
40
+ if (screenSize !== null && (isMobile !== isCurrentlyMobile)) {
41
+ setIsMobile(isCurrentlyMobile);
42
+ setVisibleSlides(isCurrentlyMobile ? 1 : 3);
43
+ setTotalSlides(isCurrentlyMobile ? theseItems.length : theseItems.length + 2);
44
+ }
45
+ }, [isMobile, theseItems]);
46
+
47
+ // Cache our data source, using as a flag for render logic:
48
+ useEffect(() => {
49
+ setTheseItems(nodes);
50
+ }, [setTheseItems, nodes]);
51
+
52
+ useEffect(() => {
53
+ if (window !== 'undefined' && window.innerWidth >= breakpointValues.M) {
54
+ // On inital render, update carousel plugin config
55
+ // to suit the non-mobile layout and functionality:
56
+ setIsMobile(false);
57
+ setVisibleSlides(3);
58
+ }
59
+
60
+ // Hook into browser's own onresize event to call our custom wrapper function:
61
+ if (typeof window !== 'undefined') window.onresize = screenResize;
62
+ }, [screenResize]);
63
+
64
+ if (theseItems && totalSlides === null) {
65
+ // Reflects our two dummy/bookend slides for non-mobile/tablet views:
66
+ setTotalSlides(isMobile ? theseItems.length : theseItems.length + 2);
67
+ }
68
+
69
+ return (
70
+ <CarouselWrapper
71
+ className="CarouselWrapper"
72
+ id={thisID}
73
+ mobileHeight={mobileHeight}
74
+ tabletHeight={tabletHeight}
75
+ desktopHeight={desktopHeight}
76
+ carouselBackgroundColour={carouselBackgroundColour}
77
+ >
78
+
79
+ <HeadingCopyWrapper>
80
+ {headingCopy}
81
+ </HeadingCopyWrapper>
82
+
83
+ {theseItems && (
84
+ <CarouselProvider
85
+ naturalSlideWidth={50}
86
+ naturalSlideHeight={200}
87
+ totalSlides={totalSlides}
88
+ isPlaying={autoPlay}
89
+ interval={5000}
90
+ visibleSlides={visibleSlides}
91
+ infinite
92
+ >
93
+ <Slider classNameAnimation="richtext-carousel">
94
+
95
+ {/* Dummy slide for our desired non-mobile layout and functionality */}
96
+ {isMobile === false && (
97
+ <Slide index={0} key={0} />
98
+ )}
99
+
100
+ {Object.keys(theseItems).map((key, index) => {
101
+ // Reflect that initial dummy/bookend slide shown on non-mobile/tablet views:
102
+ const thisOffsetIndex = index + (isMobile ? 0 : 1);
103
+
104
+ return (
105
+ // Calculate the index offset accordingly to reflect the number of slides,
106
+ // but use the REAL index when determining if its the last REAL slide
107
+ <Slide
108
+ index={thisOffsetIndex}
109
+ className={index === (theseItems.length - 1) && 'last-slide'}
110
+ key={thisOffsetIndex}
111
+ >
112
+
113
+ <SlideCopyWrapper
114
+ className="slide-copy-wrapper"
115
+ mobileHeight={mobileHeight}
116
+ tabletHeight={tabletHeight}
117
+ desktopHeight={desktopHeight}
118
+ nodeBackgroundColour={nodeBackgroundColour}
119
+ nodeOutlineColour={nodeOutlineColour}
120
+ >
121
+ {theseItems[index].copy}
122
+ </SlideCopyWrapper>
123
+
124
+ </Slide>
125
+ );
126
+ })}
127
+
128
+ {/* Dummy slide for our desired non-mobile layout and functionality */}
129
+ {isMobile === false && (
130
+ <Slide index={theseItems.length + 1} key="bookend-last" />
131
+ )}
132
+
133
+ </Slider>
134
+ <ButtonBack>Back</ButtonBack>
135
+ <ButtonNext>Next</ButtonNext>
136
+ </CarouselProvider>
137
+ )}
138
+
139
+ </CarouselWrapper>
140
+ );
141
+ };
142
+
143
+ RichtextCarousel.propTypes = {
144
+ data: PropTypes.shape({
145
+ headingCopy: PropTypes.string.isRequired,
146
+ nodes: PropTypes.arrayOf(PropTypes.shape({
147
+ copy: PropTypes.string.isRequired
148
+ })).isRequired,
149
+ autoPlay: PropTypes.bool.isRequired,
150
+ contentful_id: PropTypes.string.isRequired,
151
+ mobileHeight: PropTypes.number,
152
+ tabletHeight: PropTypes.number,
153
+ desktopHeight: PropTypes.number,
154
+ carouselBackgroundColour: PropTypes.string,
155
+ nodeBackgroundColour: PropTypes.string,
156
+ nodeOutlineColour: PropTypes.string
157
+ }).isRequired
158
+ };
159
+
160
+ export default RichtextCarousel;
@@ -0,0 +1,14 @@
1
+ # Richtext Carousel
2
+
3
+ ```js
4
+ const { RichtextCarouselItems } = require('../../../styleguide/data/data');
5
+
6
+ <div>
7
+ <h2 style={{textAlign: 'center'}}>
8
+ Richtext Carousel #1
9
+ </h2>
10
+ <RichtextCarousel
11
+ data={RichtextCarouselItems}/>
12
+ </div>
13
+
14
+ ```
@@ -0,0 +1,248 @@
1
+ import styled, { css } from 'styled-components';
2
+ import spacing from '../../../theme/shared/spacing';
3
+ // import Text from '../../Atoms/Text/Text';
4
+
5
+ // Duration in seconds
6
+ const animationSpeed = 0.75;
7
+
8
+ const SlideCopyWrapper = styled.div`
9
+ background: ${({ theme, nodeBackgroundColour }) => theme.color(nodeBackgroundColour)};
10
+ height: ${props => props.mobileHeight}px;
11
+ width: 75%;
12
+ display: flex;
13
+ flex-direction: column;
14
+ justify-content: center;
15
+ padding: 25px;
16
+ border: 1px dashed ${({ theme, nodeOutlineColour }) => theme.color(nodeOutlineColour)};
17
+ border-radius: 20px;
18
+ position: relative;
19
+ overflow: visible;
20
+ word-wrap: break-word;
21
+
22
+ &:after {
23
+ position: absolute;
24
+ content: '';
25
+ top: 50%;
26
+ width: 34%;
27
+ right: calc(-34% - 0px);
28
+ height: 2px;
29
+ border-bottom: 1px dashed ${({ theme, nodeOutlineColour }) => theme.color(nodeOutlineColour)};
30
+ }
31
+
32
+ @media ${({ theme }) => theme.allBreakpoints('M')} {
33
+ height: ${props => props.tabletHeight}px;
34
+ width: 85%;
35
+ }
36
+
37
+ @media ${({ theme }) => theme.allBreakpoints('L')} {
38
+ height: ${props => props.desktopHeight}px;
39
+ }
40
+ `;
41
+
42
+ const HeadingCopyWrapper = styled.div`
43
+ text-align: center;
44
+ `;
45
+
46
+ // Unfortunately having to target plugin-created markup ye olde fashioned way:
47
+ const CarouselWrapper = styled.div`
48
+ height: 100%;
49
+ background: ${({ theme, carouselBackgroundColour }) => theme.color(carouselBackgroundColour)};
50
+
51
+ max-width: 760px;
52
+ padding: 2.5rem ${spacing('l')} 3.5rem;
53
+ margin: 0 auto;
54
+
55
+ border-radius: 20px;
56
+ box-shadow: 0px 0px 20px rgba(0, 0, 0, 0.15);
57
+
58
+ .carousel {
59
+ position: relative;
60
+ margin: 0 auto;
61
+ padding-top: ${spacing('l')};
62
+
63
+ button.carousel__back-button,
64
+ button.carousel__next-button {
65
+ position: absolute;
66
+ left: 0;
67
+ top: 0;
68
+ width: 33% !important;
69
+ height: 100%;
70
+ padding: 0 !important;
71
+ box-shadow: none;
72
+ text-indent: -9999px;
73
+ background-color: transparent;
74
+ border: none;
75
+
76
+ &:after {
77
+ content: "";
78
+ position: absolute;
79
+ top: 0;
80
+ left: 0;
81
+ width: 50%;
82
+ height: 100%;
83
+ transition: opacity 0.2s linear;
84
+ background: ${({ theme, carouselBackgroundColour }) => css`
85
+ linear-gradient(90deg, ${theme.color(carouselBackgroundColour)},
86
+ ${theme.color(carouselBackgroundColour)}7a, ${theme.color(carouselBackgroundColour)}00);
87
+ `};
88
+ }
89
+
90
+ &:hover {
91
+ &:after {
92
+ opacity: 0.5;
93
+ }
94
+ }
95
+
96
+ @media ${({ theme }) => theme.allBreakpoints('M')} {
97
+ width: 33.3% !important;
98
+ &:after {
99
+ width: 100%;
100
+ }
101
+ }
102
+ }
103
+
104
+ button.carousel__next-button {
105
+ left: auto;
106
+ right: 0;
107
+
108
+ &:before {
109
+ transform: translate(0, -50%) rotate(-90deg);
110
+ }
111
+
112
+ &:after {
113
+ left: auto;
114
+ right: 0;
115
+
116
+ background: ${({ theme, carouselBackgroundColour }) => css`
117
+ linear-gradient(90deg, ${theme.color(carouselBackgroundColour)}00,
118
+ ${theme.color(carouselBackgroundColour)}7a, ${theme.color(carouselBackgroundColour)});
119
+ `};
120
+ }
121
+ }
122
+
123
+ .richtext-carousel {
124
+ // Override default animations
125
+ transition: -webkit-transform ${animationSpeed}s;
126
+ -o-transition: transform ${animationSpeed}s;
127
+ transition: transform ${animationSpeed}s;
128
+ -webkit-transform: ${animationSpeed}s;
129
+ will-change: transform;
130
+
131
+ .last-slide {
132
+ .slide-copy-wrapper:after {
133
+ content: none;
134
+ }
135
+ }
136
+
137
+ .carousel__slide {
138
+ // 'Mobile'
139
+ padding-bottom: ${props => props.mobileHeight}px !important;
140
+
141
+ // 'Tablet' (and up) tweaks for the 3-visible layout
142
+ @media ${({ theme }) => theme.allBreakpoints('M')} {
143
+
144
+ padding-bottom: ${props => props.tabletHeight}px !important;
145
+
146
+ // All slides:
147
+ .carousel__inner-slide {
148
+
149
+ // All 'SlideCopyWrapper's:
150
+ > div:first-child {
151
+ transition: transform ${animationSpeed}s ease;
152
+ transform-origin: center;
153
+ transform: scale(0.8);
154
+
155
+ &:after {
156
+ transition: transform ${animationSpeed}s ease,
157
+ width ${animationSpeed}s ease,
158
+ right ${animationSpeed}s ease;
159
+ width: 100%;
160
+ right: calc(-100% - 6px);
161
+ transform: scale(1);
162
+
163
+ }
164
+ }
165
+ }
166
+
167
+ // Our 'first' slide of the three:
168
+ &.carousel__slide--visible {
169
+ .carousel__inner-slide {
170
+ > div:first-child {
171
+ &:after {
172
+ width: 33%;
173
+ right: calc(-33% - 3px);
174
+ transform: scale(1);
175
+ }
176
+ }
177
+ }
178
+
179
+ // 2nd and 3rd:
180
+ + .carousel__slide--visible {
181
+ .carousel__inner-slide {
182
+ > div:first-child {
183
+ transform: scale(1);
184
+ &:after {
185
+ width: 33%;
186
+ right: calc(-33% + 3px);
187
+ transform: scale(0.8);
188
+ }
189
+ }
190
+ }
191
+
192
+ // Resets the 3rd slide:
193
+ + .carousel__slide--visible {
194
+ > div > div:first-child {
195
+ transform: scale(0.8);
196
+ &:after {
197
+ width: 50%;
198
+ right: calc(-50% - 6px);
199
+ transform: scale(1);
200
+ }
201
+ }
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ // 'Desktop'
208
+ @media ${({ theme }) => theme.allBreakpoints('L')} {
209
+ padding-bottom: ${props => props.desktopHeight}px !important;
210
+
211
+ // First
212
+ &.carousel__slide--visible {
213
+
214
+ // 2nd and 3rd
215
+ + .carousel__slide--visible {
216
+
217
+ // 3rd only
218
+ + .carousel__slide--visible {
219
+ .carousel__inner-slide {
220
+ > div:first-child {
221
+ &:after {
222
+ right: calc(-125% - 5px);
223
+ width: 125%;
224
+ }
225
+ }
226
+ }
227
+ }
228
+ }
229
+ }
230
+ }
231
+ // END OF DESKTOP
232
+
233
+ .carousel__inner-slide {
234
+ text-align: center;
235
+ display: inline-flex;
236
+ align-items: center;
237
+ justify-content: flex-start;
238
+ flex-direction: column;
239
+ }
240
+ }
241
+ }
242
+ }
243
+ `;
244
+
245
+ export {
246
+ CarouselWrapper, SlideCopyWrapper,
247
+ HeadingCopyWrapper
248
+ };
@@ -0,0 +1,221 @@
1
+ import React from "react";
2
+ import "jest-styled-components";
3
+
4
+ import renderWithTheme from "../../../../tests/hoc/shallowWithTheme";
5
+ import RichtextCarousel from "./RichtextCarousel";
6
+ const { RichtextCarouselItems } = require("../../../styleguide/data/data");
7
+
8
+ it("renders correctly", () => {
9
+ const tree = renderWithTheme(
10
+ <RichtextCarousel data={RichtextCarouselItems} />
11
+ ).toJSON();
12
+
13
+ expect(tree).toMatchInlineSnapshot(`
14
+ .c1 {
15
+ text-align: center;
16
+ }
17
+
18
+ .c0 {
19
+ height: 100%;
20
+ background: #FFFFFF;
21
+ max-width: 760px;
22
+ padding: 2.5rem 2rem 3.5rem;
23
+ margin: 0 auto;
24
+ border-radius: 20px;
25
+ box-shadow: 0px 0px 20px rgba(0,0,0,0.15);
26
+ }
27
+
28
+ .c0 .carousel {
29
+ position: relative;
30
+ margin: 0 auto;
31
+ padding-top: 2rem;
32
+ }
33
+
34
+ .c0 .carousel button.carousel__back-button,
35
+ .c0 .carousel button.carousel__next-button {
36
+ position: absolute;
37
+ left: 0;
38
+ top: 0;
39
+ width: 33% !important;
40
+ height: 100%;
41
+ padding: 0 !important;
42
+ box-shadow: none;
43
+ text-indent: -9999px;
44
+ background-color: transparent;
45
+ border: none;
46
+ }
47
+
48
+ .c0 .carousel button.carousel__back-button:after,
49
+ .c0 .carousel button.carousel__next-button:after {
50
+ content: "";
51
+ position: absolute;
52
+ top: 0;
53
+ left: 0;
54
+ width: 50%;
55
+ height: 100%;
56
+ -webkit-transition: opacity 0.2s linear;
57
+ transition: opacity 0.2s linear;
58
+ background: linear-gradient(90deg,#FFFFFF,#FFFFFF7a,#FFFFFF00);
59
+ }
60
+
61
+ .c0 .carousel button.carousel__back-button:hover:after,
62
+ .c0 .carousel button.carousel__next-button:hover:after {
63
+ opacity: 0.5;
64
+ }
65
+
66
+ .c0 .carousel button.carousel__next-button {
67
+ left: auto;
68
+ right: 0;
69
+ }
70
+
71
+ .c0 .carousel button.carousel__next-button:before {
72
+ -webkit-transform: translate(0,-50%) rotate(-90deg);
73
+ -ms-transform: translate(0,-50%) rotate(-90deg);
74
+ transform: translate(0,-50%) rotate(-90deg);
75
+ }
76
+
77
+ .c0 .carousel button.carousel__next-button:after {
78
+ left: auto;
79
+ right: 0;
80
+ background: linear-gradient(90deg,#FFFFFF00,#FFFFFF7a,#FFFFFF);
81
+ }
82
+
83
+ .c0 .carousel .richtext-carousel {
84
+ -webkit-transition: -webkit-transform 0.75s;
85
+ -webkit-transition: -webkit-transform 0.75s;
86
+ transition: -webkit-transform 0.75s;
87
+ -o-transition: transform 0.75s;
88
+ -webkit-transition: -webkit-transform 0.75s;
89
+ -webkit-transition: transform 0.75s;
90
+ transition: transform 0.75s;
91
+ -webkit-transform: 0.75s;
92
+ will-change: transform;
93
+ }
94
+
95
+ .c0 .carousel .richtext-carousel .last-slide .slide-copy-wrapper:after {
96
+ content: none;
97
+ }
98
+
99
+ .c0 .carousel .richtext-carousel .carousel__slide {
100
+ padding-bottom: 300px !important;
101
+ }
102
+
103
+ .c0 .carousel .richtext-carousel .carousel__slide .carousel__inner-slide {
104
+ text-align: center;
105
+ display: -webkit-inline-box;
106
+ display: -webkit-inline-flex;
107
+ display: -ms-inline-flexbox;
108
+ display: inline-flex;
109
+ -webkit-align-items: center;
110
+ -webkit-box-align: center;
111
+ -ms-flex-align: center;
112
+ align-items: center;
113
+ -webkit-box-pack: start;
114
+ -webkit-justify-content: flex-start;
115
+ -ms-flex-pack: start;
116
+ justify-content: flex-start;
117
+ -webkit-flex-direction: column;
118
+ -ms-flex-direction: column;
119
+ flex-direction: column;
120
+ }
121
+
122
+ @media (min-width:740px) {
123
+ .c0 .carousel button.carousel__back-button,
124
+ .c0 .carousel button.carousel__next-button {
125
+ width: 33.3% !important;
126
+ }
127
+
128
+ .c0 .carousel button.carousel__back-button:after,
129
+ .c0 .carousel button.carousel__next-button:after {
130
+ width: 100%;
131
+ }
132
+ }
133
+
134
+ @media (min-width:740px) {
135
+ .c0 .carousel .richtext-carousel .carousel__slide {
136
+ padding-bottom: 350px !important;
137
+ }
138
+
139
+ .c0 .carousel .richtext-carousel .carousel__slide .carousel__inner-slide > div:first-child {
140
+ -webkit-transition: -webkit-transform 0.75s ease;
141
+ -webkit-transition: transform 0.75s ease;
142
+ transition: transform 0.75s ease;
143
+ -webkit-transform-origin: center;
144
+ -ms-transform-origin: center;
145
+ transform-origin: center;
146
+ -webkit-transform: scale(0.8);
147
+ -ms-transform: scale(0.8);
148
+ transform: scale(0.8);
149
+ }
150
+
151
+ .c0 .carousel .richtext-carousel .carousel__slide .carousel__inner-slide > div:first-child:after {
152
+ -webkit-transition: -webkit-transform 0.75s ease,width 0.75s ease,right 0.75s ease;
153
+ -webkit-transition: transform 0.75s ease,width 0.75s ease,right 0.75s ease;
154
+ transition: transform 0.75s ease,width 0.75s ease,right 0.75s ease;
155
+ width: 100%;
156
+ right: calc(-100% - 6px);
157
+ -webkit-transform: scale(1);
158
+ -ms-transform: scale(1);
159
+ transform: scale(1);
160
+ }
161
+
162
+ .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible .carousel__inner-slide > div:first-child:after {
163
+ width: 33%;
164
+ right: calc(-33% - 3px);
165
+ -webkit-transform: scale(1);
166
+ -ms-transform: scale(1);
167
+ transform: scale(1);
168
+ }
169
+
170
+ .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible .carousel__inner-slide > div:first-child {
171
+ -webkit-transform: scale(1);
172
+ -ms-transform: scale(1);
173
+ transform: scale(1);
174
+ }
175
+
176
+ .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible .carousel__inner-slide > div:first-child:after {
177
+ width: 33%;
178
+ right: calc(-33% + 3px);
179
+ -webkit-transform: scale(0.8);
180
+ -ms-transform: scale(0.8);
181
+ transform: scale(0.8);
182
+ }
183
+
184
+ .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible + .carousel__slide--visible > div > div:first-child {
185
+ -webkit-transform: scale(0.8);
186
+ -ms-transform: scale(0.8);
187
+ transform: scale(0.8);
188
+ }
189
+
190
+ .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible + .carousel__slide--visible > div > div:first-child:after {
191
+ width: 50%;
192
+ right: calc(-50% - 6px);
193
+ -webkit-transform: scale(1);
194
+ -ms-transform: scale(1);
195
+ transform: scale(1);
196
+ }
197
+ }
198
+
199
+ @media (min-width:1024px) {
200
+ .c0 .carousel .richtext-carousel .carousel__slide {
201
+ padding-bottom: 350px !important;
202
+ }
203
+
204
+ .c0 .carousel .richtext-carousel .carousel__slide.carousel__slide--visible + .carousel__slide--visible + .carousel__slide--visible .carousel__inner-slide > div:first-child:after {
205
+ right: calc(-125% - 5px);
206
+ width: 125%;
207
+ }
208
+ }
209
+
210
+ <div
211
+ className="c0 CarouselWrapper"
212
+ id="nqIEHjiYE8Yd2A2a5cI3O"
213
+ >
214
+ <div
215
+ className="c1"
216
+ >
217
+ Some heading copy that will be nicely constructed in-situ
218
+ </div>
219
+ </div>
220
+ `);
221
+ });
package/src/index.js CHANGED
@@ -76,3 +76,4 @@ export {
76
76
  } from './components/Organisms/MarketingPreferencesDS/_MarketingPreferencesDS';
77
77
  export { default as ImpactSlider } from './components/Organisms/ImpactSlider/ImpactSlider';
78
78
  export { default as WYMDCarousel } from './components/Organisms/WYMDCarousel/WYMDCarousel';
79
+ export { default as RichtextCarousel } from './components/Organisms/RichtextCarousel/RichtextCarousel';
@@ -223,7 +223,20 @@ const carouselItemsMinimal = {
223
223
  }
224
224
  };
225
225
 
226
+ const RichtextCarouselItems = {
227
+ contentful_id: 'nqIEHjiYE8Yd2A2a5cI3O',
228
+ // Ugly here, but to be provided by Richtextrender function in-situ:
229
+ headingCopy: 'Some heading copy that will be nicely constructed in-situ',
230
+ nodes: [
231
+ { copy: 'Some other longside but not really all that long copy, who knows, it could be this long or LESS.' },
232
+ { copy: '140 character count limit imposed in messages to fix the design height of each container and restrict anomalies. This is based on Twitters character limit for tweets.' },
233
+ { copy: 'Some other longside but not really all that long copy, who knows, it could be this long or LESS' },
234
+ { copy: '140 character count limit imposed in messages to fix the design height of each container and restrict anomalies. This is based on Twitters character limit for tweets. ABIGLONGLINETOFORCEONTOANEWONE' }
235
+ ],
236
+ autoPlay: true
237
+ };
238
+
226
239
  export {
227
240
  defaultData, mobileImages, testImpactSliderItems,
228
- carouselItemsComplete, carouselItemsIncomplete, carouselItemsMinimal
241
+ carouselItemsComplete, carouselItemsIncomplete, carouselItemsMinimal, RichtextCarouselItems
229
242
  };