);
+
+ if (!heading) {
+ return childrenOutput;
+ }
+
+ return (
+
+ );
}
}
@@ -32,6 +49,9 @@ DoubleChain.label = 'Double Chain – Arc Block';
DoubleChain.propTypes = {
children: PropTypes.array,
customFields: PropTypes.shape({
+ heading: PropTypes.string.tag({
+ label: 'Heading',
+ }),
columnOne: PropTypes.number.isRequired.tag({
label: 'Column one size',
description: 'The number of features which will appear in the first column. The rest will go into the second column.',
diff --git a/blocks/double-chain-block/chains/double-chain/default.test.jsx b/blocks/double-chain-block/chains/double-chain/default.test.jsx
index f586e7a971..326e29d281 100644
--- a/blocks/double-chain-block/chains/double-chain/default.test.jsx
+++ b/blocks/double-chain-block/chains/double-chain/default.test.jsx
@@ -76,4 +76,32 @@ describe('the double chain block', () => {
expect(component).toBeEmptyRender();
});
+
+ it('should render heading from custom field and children', () => {
+ const customFields = { columnOne: 1, heading: 'Double Chain Heading' };
+ const component = mount(
+
,
+ );
+
+ expect(component.find('Heading').text()).toBe('Double Chain Heading');
+ expect(component.find('HeadingSection').exists()).toBe(true);
+ expect(component.find('.column-1').text()).toBe('1');
+ });
+
+ it('should not render heading from custom field and children', () => {
+ const customFields = { columnOne: 1 };
+ const component = mount(
+
,
+ );
+
+ expect(component.find('Heading').exists()).toBe(false);
+ expect(component.find('HeadingSection').exists()).toBe(false);
+ expect(component.find('.column-1').text()).toBe('1');
+ });
});
diff --git a/blocks/double-chain-block/index.story.jsx b/blocks/double-chain-block/index.story.jsx
new file mode 100644
index 0000000000..7c8c34ec76
--- /dev/null
+++ b/blocks/double-chain-block/index.story.jsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { withKnobs } from '@storybook/addon-knobs';
+import DoubleChain from './chains/double-chain/default';
+
+export default {
+ title: 'Chains/Double',
+ decorators: [withKnobs],
+ parameters: {
+ // Set the viewports in Chromatic at a component level.
+ chromatic: { viewports: [320, 740, 1200] },
+ },
+};
+
+const styles = {
+ backgroundColor: 'rgb(240 240 240)',
+};
+
+const Comp1 = () =>
;
+
+export const allColumns = () => {
+ const customFields = {
+ columnOne: 1,
+ heading: 'Double Chain Heading',
+ };
+
+ return (
+
+ );
+};
+
+export const allColumnsNoTitle = () => {
+ const customFields = {
+ columnOne: 1,
+ };
+
+ return (
+
+ );
+};
+
+export const zeroColumns = () => {
+ const customFields = {
+ heading: 'Double Chain Heading',
+ };
+
+ return (
+
+ );
+};
diff --git a/blocks/double-chain-block/package.json b/blocks/double-chain-block/package.json
index d1a2f29948..fe3cc3e1f3 100644
--- a/blocks/double-chain-block/package.json
+++ b/blocks/double-chain-block/package.json
@@ -22,8 +22,9 @@
"directory": "blocks/double-chain-block"
},
"peerDependencies": {
+ "@arc-fusion/prop-types": "^0.1.5",
"@wpmedia/engine-theme-sdk": "*",
- "@wpmedia/news-theme-css": "*"
+ "@wpmedia/shared-styles": "*"
},
"scripts": {
"test": "echo \"Error: run tests from root\" && exit 1",
diff --git a/blocks/quad-chain-block/chains/quad-chain/default.jsx b/blocks/quad-chain-block/chains/quad-chain/default.jsx
index 848711f17c..c0be101605 100644
--- a/blocks/quad-chain-block/chains/quad-chain/default.jsx
+++ b/blocks/quad-chain-block/chains/quad-chain/default.jsx
@@ -1,5 +1,8 @@
import React from 'react';
-import PropTypes from 'prop-types';
+import PropTypes from '@arc-fusion/prop-types';
+import { Heading, HeadingSection } from '@wpmedia/shared-styles';
+
+import '@wpmedia/shared-styles/scss/_chains.scss';
const QuadChain = ({ children, customFields }) => {
if (children && children.length && children.length > 0) {
@@ -9,6 +12,7 @@ const QuadChain = ({ children, customFields }) => {
columnOne: columnOneLength = children.length,
columnTwo: columnTwoLength = 0,
columnThree: columnThreeLength = 0,
+ heading = null,
} = customFields;
// check column length not negative
@@ -17,7 +21,7 @@ const QuadChain = ({ children, customFields }) => {
const endOfColumnThreeIndex = endOfColumnTwoIndex + columnThreeLength;
- return (
+ const childrenOutput = (
@@ -35,6 +39,17 @@ const QuadChain = ({ children, customFields }) => {
);
+
+ if (!heading) {
+ return childrenOutput;
+ }
+
+ return (
+
+ {heading}
+ {childrenOutput}
+
+ );
}
}
@@ -46,6 +61,9 @@ QuadChain.label = 'Quad Chain – Arc Block';
QuadChain.propTypes = {
children: PropTypes.array,
customFields: PropTypes.shape({
+ heading: PropTypes.string.tag({
+ label: 'Heading',
+ }),
columnOne: PropTypes.number.isRequired.tag({
label: 'Number of blocks in Column 1:',
description: 'The number of features which will appear in the first column',
diff --git a/blocks/quad-chain-block/chains/quad-chain/default.test.jsx b/blocks/quad-chain-block/chains/quad-chain/default.test.jsx
index b731efdff9..8f7fc8dc1c 100644
--- a/blocks/quad-chain-block/chains/quad-chain/default.test.jsx
+++ b/blocks/quad-chain-block/chains/quad-chain/default.test.jsx
@@ -7,12 +7,14 @@ describe('the quad chain block', () => {
const Comp2 = () =>
2
;
const Comp3 = () =>
3
;
const Comp4 = () =>
4
;
+
it('should only render if there are children', () => {
const component = shallow(
,
);
expect(component).toBeEmptyRender();
});
+
it('should put all features into the first column by default', () => {
const customFields = {};
const component = shallow(
@@ -30,6 +32,7 @@ describe('the quad chain block', () => {
expect(columnOne.children().length).toBe(4);
expect(columnTwo.children().length).toBe(0);
});
+
it('should be able to accept a number in the custom field, and that number of features within the chain should appear in the first column. ', () => {
const customFields = { columnOne: 2, columnTwo: 2, columnThree: 0 };
const component = mount(
@@ -47,6 +50,7 @@ describe('the quad chain block', () => {
expect(columnOne.text()).toEqual('12');
expect(columnTwo.text()).toEqual('34');
});
+
it('should be able to accept numbers in the custom field, any additional features in the chain should be placed in the fourth column. ', () => {
const customFields = { columnOne: 1, columnTwo: 1, columnThree: 1 };
const component = mount(
@@ -68,6 +72,7 @@ describe('the quad chain block', () => {
expect(columnThree.text()).toEqual('3');
expect(columnFour.text()).toEqual('4');
});
+
it('should render nothing if negative column 1 amount', () => {
const customFields = { columnOne: -10 };
const component = mount(
@@ -81,4 +86,41 @@ describe('the quad chain block', () => {
expect(component).toBeEmptyRender();
});
+
+ it('should render heading from custom field and children', () => {
+ const customFields = { columnOne: 1, columnTwo: 1, heading: 'Quad Chain Heading' };
+ const component = mount(
+
+
+
+ ,
+ );
+
+ expect(component.find('Heading').text()).toBe('Quad Chain Heading');
+ expect(component.find('HeadingSection').exists()).toBe(true);
+
+ const columnOne = component.find('.row').children().at(0);
+ const columnTwo = component.find('.row').children().at(1);
+
+ expect(columnOne.text()).toEqual('1');
+ expect(columnTwo.text()).toEqual('2');
+ });
+
+ it('should not render heading from custom field and children', () => {
+ const customFields = { columnOne: 1, columnTwo: 1 };
+ const component = mount(
+
+
+
+ ,
+ );
+
+ expect(component.find('Heading').exists()).toBe(false);
+ expect(component.find('HeadingSection').exists()).toBe(false);
+ const columnOne = component.find('.row').children().at(0);
+ const columnTwo = component.find('.row').children().at(1);
+
+ expect(columnOne.text()).toEqual('1');
+ expect(columnTwo.text()).toEqual('2');
+ });
});
diff --git a/blocks/quad-chain-block/index.story.jsx b/blocks/quad-chain-block/index.story.jsx
new file mode 100644
index 0000000000..7636770620
--- /dev/null
+++ b/blocks/quad-chain-block/index.story.jsx
@@ -0,0 +1,110 @@
+import React from 'react';
+import { withKnobs } from '@storybook/addon-knobs';
+import QuadChain from './chains/quad-chain/default';
+
+export default {
+ title: 'Chains/Quad',
+ decorators: [withKnobs],
+ parameters: {
+ // Set the viewports in Chromatic at a component level.
+ chromatic: { viewports: [320, 740, 1200] },
+ },
+};
+
+const styles = {
+ backgroundColor: 'rgb(240 240 240)',
+};
+
+const Comp1 = () =>
1
;
+const Comp2 = () =>
2
;
+const Comp3 = () =>
3
;
+const Comp4 = () =>
4
;
+
+export const allColumns = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 1,
+ columnThree: 1,
+ heading: 'Quad Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export const allColumnsNoTitle = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 1,
+ columnThree: 1,
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export const zeroColumns = () => {
+ const customFields = {
+ columnOne: 0,
+ columnTwo: 0,
+ columnThree: 0,
+ heading: 'Quad Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export const columnOneOnly = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 0,
+ columnThree: 0,
+ heading: 'Quad Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+export const columnOneAndTwo = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 1,
+ columnThree: 0,
+ heading: 'Quad Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
diff --git a/blocks/quad-chain-block/package.json b/blocks/quad-chain-block/package.json
index 62dbfdf75f..b91deb7e48 100644
--- a/blocks/quad-chain-block/package.json
+++ b/blocks/quad-chain-block/package.json
@@ -28,6 +28,8 @@
},
"gitHead": "83fb8d6685958d85ddbfcfbf01d9a5c864cd6c95",
"peerDependencies": {
- "@wpmedia/engine-theme-sdk": "*"
+ "@arc-fusion/prop-types": "^0.1.5",
+ "@wpmedia/engine-theme-sdk": "*",
+ "@wpmedia/shared-styles": "*"
}
}
diff --git a/blocks/shared-styles/scss/_chains.scss b/blocks/shared-styles/scss/_chains.scss
new file mode 100644
index 0000000000..e5cbff3d1e
--- /dev/null
+++ b/blocks/shared-styles/scss/_chains.scss
@@ -0,0 +1,4 @@
+.chain-heading {
+ font-size: calculateRem(26px);
+ line-height: calculateRem(32px);
+}
diff --git a/blocks/single-chain-block/chains/single-chain/default.jsx b/blocks/single-chain-block/chains/single-chain/default.jsx
index 36f5c4b02d..85cae4b1bd 100644
--- a/blocks/single-chain-block/chains/single-chain/default.jsx
+++ b/blocks/single-chain-block/chains/single-chain/default.jsx
@@ -1,7 +1,33 @@
import React from 'react';
+import PropTypes from '@arc-fusion/prop-types';
+import { Heading, HeadingSection } from '@wpmedia/shared-styles';
-const SingleChain = ({ children }) => <>{children}>;
+import '@wpmedia/shared-styles/scss/_chains.scss';
+
+const SingleChain = ({ children, customFields = {} }) => {
+ const { heading = null } = customFields;
+
+ if (!heading) {
+ return <>{children}>;
+ }
+
+ return (
+
+ {heading}
+ {children}
+
+ );
+};
SingleChain.label = 'Single Chain – Arc Block';
+SingleChain.propTypes = {
+ children: PropTypes.array,
+ customFields: PropTypes.shape({
+ heading: PropTypes.string.tag({
+ label: 'Heading',
+ }),
+ }),
+};
+
export default SingleChain;
diff --git a/blocks/single-chain-block/chains/single-chain/default.test.jsx b/blocks/single-chain-block/chains/single-chain/default.test.jsx
index 927c044ca8..5f9638cc0f 100644
--- a/blocks/single-chain-block/chains/single-chain/default.test.jsx
+++ b/blocks/single-chain-block/chains/single-chain/default.test.jsx
@@ -15,19 +15,52 @@ describe('single chain', () => {
);
expect(wrapper.text()).toBe(testText);
+ expect(wrapper.find('HeadingSection').exists()).toBe(false);
expect(wrapper.html()).toBe(`
${testText}
`);
});
+
it('should render null when null is the child', () => {
const wrapper = mount(
{null});
expect(wrapper.text()).toBe('');
expect(wrapper.html()).toBe(null);
});
+
it('should render null when no child', () => {
const wrapper = mount(
);
expect(wrapper.text()).toBe('');
expect(wrapper.html()).toBe(null);
});
+
+ it('should render heading from custom field', () => {
+ const wrapper = mount(
);
+
+ expect(wrapper.find('Heading').text()).toBe('Single Chain Heading');
+ });
+
+ it('should render heading from custom field and children', () => {
+ const wrapper = mount(
+
+ Test
+ ,
+ );
+
+ expect(wrapper.find('Heading').text()).toBe('Single Chain Heading');
+ expect(wrapper.find('HeadingSection').exists()).toBe(true);
+ expect(wrapper.find('p').text()).toBe('Test');
+ });
+
+ it('should not render heading from custom field and children', () => {
+ const wrapper = mount(
+
+ Test
+ ,
+ );
+
+ expect(wrapper.find('Heading').exists()).toBe(false);
+ expect(wrapper.find('HeadingSection').exists()).toBe(false);
+ expect(wrapper.find('p').text()).toBe('Test');
+ });
});
});
diff --git a/blocks/single-chain-block/index.story.jsx b/blocks/single-chain-block/index.story.jsx
new file mode 100644
index 0000000000..8ece5b57d7
--- /dev/null
+++ b/blocks/single-chain-block/index.story.jsx
@@ -0,0 +1,57 @@
+import React from 'react';
+import { withKnobs } from '@storybook/addon-knobs';
+import SingleChain from './chains/single-chain/default';
+
+export default {
+ title: 'Chains/Single',
+ decorators: [withKnobs],
+ parameters: {
+ // Set the viewports in Chromatic at a component level.
+ chromatic: { viewports: [320, 1600] },
+ },
+};
+
+const styles = {
+ backgroundColor: 'rgb(240 240 240)',
+};
+
+const Comp1 = () =>
1
;
+const Comp2 = () =>
2
;
+
+export const oneChild = () => {
+ const customFields = {
+ columnOne: 1,
+ heading: 'Single Chain Heading',
+ };
+
+ return (
+
+
+
+ );
+};
+
+export const noHeading = () => {
+ const customFields = {
+ columnOne: 1,
+ };
+
+ return (
+
+
+
+ );
+};
+
+export const twoChildren = () => {
+ const customFields = {
+ heading: 'Single Chain Heading',
+ };
+
+ return (
+
+
+
+
+ );
+};
diff --git a/blocks/single-chain-block/package.json b/blocks/single-chain-block/package.json
index b888c1f48f..e4f172ed97 100644
--- a/blocks/single-chain-block/package.json
+++ b/blocks/single-chain-block/package.json
@@ -24,6 +24,8 @@
},
"gitHead": "83fb8d6685958d85ddbfcfbf01d9a5c864cd6c95",
"peerDependencies": {
- "@wpmedia/engine-theme-sdk": "*"
+ "@arc-fusion/prop-types": "^0.1.5",
+ "@wpmedia/engine-theme-sdk": "*",
+ "@wpmedia/shared-styles": "*"
}
}
diff --git a/blocks/triple-chain-block/chains/triple-chain/default.jsx b/blocks/triple-chain-block/chains/triple-chain/default.jsx
index d40341e12b..2f2f07a406 100644
--- a/blocks/triple-chain-block/chains/triple-chain/default.jsx
+++ b/blocks/triple-chain-block/chains/triple-chain/default.jsx
@@ -1,5 +1,8 @@
import React from 'react';
-import PropTypes from 'prop-types';
+import PropTypes from '@arc-fusion/prop-types';
+import { Heading, HeadingSection } from '@wpmedia/shared-styles';
+
+import '@wpmedia/shared-styles/scss/_chains.scss';
const TripleChain = ({ children, customFields }) => {
if (children && children.length && children.length > 0) {
@@ -8,13 +11,14 @@ const TripleChain = ({ children, customFields }) => {
const {
columnOne: columnOneLength = children.length,
columnTwo: columnTwoLength = 0,
+ heading = null,
} = customFields;
// check column length not negative
if (columnOneLength >= 0 && columnTwoLength >= 0) {
const endOfColumnTwoIndex = columnOneLength + columnTwoLength;
- return (
+ const childrenOutput = (
@@ -29,6 +33,17 @@ const TripleChain = ({ children, customFields }) => {
);
+
+ if (!heading) {
+ return childrenOutput;
+ }
+
+ return (
+
+ {heading}
+ {childrenOutput}
+
+ );
}
}
@@ -40,6 +55,9 @@ TripleChain.label = 'Triple Chain – Arc Block';
TripleChain.propTypes = {
children: PropTypes.array,
customFields: PropTypes.shape({
+ heading: PropTypes.string.tag({
+ label: 'Heading',
+ }),
columnOne: PropTypes.number.isRequired.tag({
label: 'Number of blocks in Column 1:',
description: 'The number of features which will appear in the first column',
diff --git a/blocks/triple-chain-block/chains/triple-chain/default.test.jsx b/blocks/triple-chain-block/chains/triple-chain/default.test.jsx
index a2a7b32f5e..21b0ef37f4 100644
--- a/blocks/triple-chain-block/chains/triple-chain/default.test.jsx
+++ b/blocks/triple-chain-block/chains/triple-chain/default.test.jsx
@@ -7,12 +7,14 @@ describe('the triple chain block', () => {
const Comp2 = () =>
2
;
const Comp3 = () =>
3
;
const Comp4 = () =>
4
;
+
it('should only render if there are children', () => {
const component = shallow(
,
);
expect(component).toBeEmptyRender();
});
+
it('should put all features into the first column by default', () => {
const customFields = {};
const component = shallow(
@@ -30,6 +32,7 @@ describe('the triple chain block', () => {
expect(columnOne.children().length).toBe(4);
expect(columnTwo.children().length).toBe(0);
});
+
it('should be able to accept a number in the custom field, and that number of features within the chain should appear in the first column. ', () => {
const customFields = { columnOne: 2, columnTwo: 2 };
const component = mount(
@@ -47,6 +50,7 @@ describe('the triple chain block', () => {
expect(columnOne.text()).toEqual('12');
expect(columnTwo.text()).toEqual('34');
});
+
it('should be able to accept numbers in the custom field, any additional features in the chain should be placed in the third column. ', () => {
const customFields = { columnOne: 1, columnTwo: 1 };
const component = mount(
@@ -67,6 +71,7 @@ describe('the triple chain block', () => {
expect(columnThree.text()).toEqual('34');
});
+
it('should render nothing if negative column 1 amount', () => {
const customFields = { columnOne: -10 };
const component = mount(
@@ -80,4 +85,41 @@ describe('the triple chain block', () => {
expect(component).toBeEmptyRender();
});
+
+ it('should render heading from custom field and children', () => {
+ const customFields = { columnOne: 1, columnTwo: 1, heading: 'Triple Chain Heading' };
+ const component = mount(
+
+
+
+ ,
+ );
+
+ expect(component.find('Heading').text()).toBe('Triple Chain Heading');
+ expect(component.find('HeadingSection').exists()).toBe(true);
+
+ const columnOne = component.find('.row').children().at(0);
+ const columnTwo = component.find('.row').children().at(1);
+
+ expect(columnOne.text()).toEqual('1');
+ expect(columnTwo.text()).toEqual('2');
+ });
+
+ it('should not render heading from custom field and children', () => {
+ const customFields = { columnOne: 1, columnTwo: 1 };
+ const component = mount(
+
+
+
+ ,
+ );
+
+ expect(component.find('Heading').exists()).toBe(false);
+ expect(component.find('HeadingSection').exists()).toBe(false);
+ const columnOne = component.find('.row').children().at(0);
+ const columnTwo = component.find('.row').children().at(1);
+
+ expect(columnOne.text()).toEqual('1');
+ expect(columnTwo.text()).toEqual('2');
+ });
});
diff --git a/blocks/triple-chain-block/index.story.jsx b/blocks/triple-chain-block/index.story.jsx
new file mode 100644
index 0000000000..fabdc920a0
--- /dev/null
+++ b/blocks/triple-chain-block/index.story.jsx
@@ -0,0 +1,83 @@
+import React from 'react';
+import { withKnobs } from '@storybook/addon-knobs';
+import TripleChain from './chains/triple-chain/default';
+
+export default {
+ title: 'Chains/Triple',
+ decorators: [withKnobs],
+ parameters: {
+ // Set the viewports in Chromatic at a component level.
+ chromatic: { viewports: [320, 740, 1200] },
+ },
+};
+
+const styles = {
+ backgroundColor: 'rgb(240 240 240)',
+};
+
+const Comp1 = () =>
1
;
+const Comp2 = () =>
2
;
+const Comp3 = () =>
3
;
+
+export const allColumns = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 1,
+ heading: 'Triple Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+ );
+};
+
+export const allColumnsNoTitle = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 1,
+ };
+
+ return (
+
+
+
+
+
+ );
+};
+
+export const zeroColumns = () => {
+ const customFields = {
+ columnOne: 0,
+ columnTwo: 0,
+ heading: 'Triple Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+ );
+};
+
+export const columnOneOnly = () => {
+ const customFields = {
+ columnOne: 1,
+ columnTwo: 0,
+ heading: 'Triple Chain Heading',
+ };
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/blocks/triple-chain-block/package.json b/blocks/triple-chain-block/package.json
index 2af39a65a9..d1d6aa7e58 100644
--- a/blocks/triple-chain-block/package.json
+++ b/blocks/triple-chain-block/package.json
@@ -24,6 +24,8 @@
},
"gitHead": "83fb8d6685958d85ddbfcfbf01d9a5c864cd6c95",
"peerDependencies": {
- "@wpmedia/engine-theme-sdk": "*"
+ "@arc-fusion/prop-types": "^0.1.5",
+ "@wpmedia/engine-theme-sdk": "*",
+ "@wpmedia/shared-styles": "*"
}
}
diff --git a/jest/mocks/context.js b/jest/mocks/context.js
index 0724825fcf..e64c73b59c 100644
--- a/jest/mocks/context.js
+++ b/jest/mocks/context.js
@@ -1,3 +1,3 @@
-export const useComponentContext = jest.fn();
-export const useAppContext = jest.fn();
-export const useFusionContext = jest.fn();
+export const useComponentContext = jest.fn(() => ({}));
+export const useAppContext = jest.fn(() => ({}));
+export const useFusionContext = jest.fn(() => ({}));
diff --git a/jest/mocks/themes.js b/jest/mocks/themes.js
index 0bb2acf508..51e0d44b23 100644
--- a/jest/mocks/themes.js
+++ b/jest/mocks/themes.js
@@ -1 +1 @@
-export default jest.fn();
+export default jest.fn(() => ({}));