@blaze-cms/react-page-builder 0.123.0-alpha.3 → 0.123.0-alpha.6

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 (34) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/lib/components/DataSummary/helpers/build-props-to-display-with-content.js +20 -3
  3. package/lib/components/DataSummary/helpers/build-props-to-display-with-content.js.map +1 -1
  4. package/lib/components/DataSummary/helpers/get-link-based-on-value.js +28 -0
  5. package/lib/components/DataSummary/helpers/get-link-based-on-value.js.map +1 -0
  6. package/lib/components/DataSummary/helpers/index.js +8 -0
  7. package/lib/components/DataSummary/helpers/index.js.map +1 -1
  8. package/lib/components/Menu/Menu.js +17 -8
  9. package/lib/components/Menu/Menu.js.map +1 -1
  10. package/lib/components/SearchContent/index.js +65 -43
  11. package/lib/components/SearchContent/index.js.map +1 -1
  12. package/lib/constants/index.js +6 -2
  13. package/lib/constants/index.js.map +1 -1
  14. package/lib-es/components/DataSummary/helpers/build-props-to-display-with-content.js +19 -3
  15. package/lib-es/components/DataSummary/helpers/build-props-to-display-with-content.js.map +1 -1
  16. package/lib-es/components/DataSummary/helpers/get-link-based-on-value.js +16 -0
  17. package/lib-es/components/DataSummary/helpers/get-link-based-on-value.js.map +1 -0
  18. package/lib-es/components/DataSummary/helpers/index.js +2 -1
  19. package/lib-es/components/DataSummary/helpers/index.js.map +1 -1
  20. package/lib-es/components/Menu/Menu.js +17 -8
  21. package/lib-es/components/Menu/Menu.js.map +1 -1
  22. package/lib-es/components/SearchContent/index.js +29 -24
  23. package/lib-es/components/SearchContent/index.js.map +1 -1
  24. package/lib-es/constants/index.js +3 -1
  25. package/lib-es/constants/index.js.map +1 -1
  26. package/package.json +2 -2
  27. package/src/components/DataSummary/helpers/build-props-to-display-with-content.js +15 -3
  28. package/src/components/DataSummary/helpers/get-link-based-on-value.js +14 -0
  29. package/src/components/DataSummary/helpers/index.js +3 -1
  30. package/src/components/Menu/Menu.js +25 -11
  31. package/src/components/SearchContent/index.js +40 -30
  32. package/src/constants/index.js +6 -1
  33. package/tests/unit/src/components/DataSummary/helpers/build-props-to-display-with-content.test.js +22 -0
  34. package/tests/unit/src/components/DataSummary/helpers/get-link-based-on-value.test.js +29 -0
@@ -3,6 +3,7 @@ import flatten from 'lodash.flatten';
3
3
  import { isObject } from '../../../helpers';
4
4
  import getLinkToPublishedContent from './get-link-to-published-content';
5
5
  import getPropValue from './get-prop-value';
6
+ import getLinkBasedOnValue from './get-link-based-on-value';
6
7
 
7
8
  const buildPropsToDisplayWithContent = (props, propsToDisplay = []) => {
8
9
  if (!isObject(propsToDisplay[0])) {
@@ -19,18 +20,29 @@ const buildPropsToDisplayWithContent = (props, propsToDisplay = []) => {
19
20
 
20
21
  return flatten(
21
22
  propsToDisplay.map(options => {
22
- const { propertiesToDisplay, label, modifier = '' } = options;
23
+ const { propertiesToDisplay, label, modifier = '', enableLink } = options;
23
24
  return propertiesToDisplay.map(key => {
24
25
  if (!key) return null;
25
26
 
26
27
  const objPropValue = getPropValue(key, props, options);
27
28
  if (!objPropValue) return null;
28
- const linkToPublishedContent = getLinkToPublishedContent(key, props);
29
29
 
30
- return [upperFirst(label), objPropValue, linkToPublishedContent, modifier];
30
+ const link = getLink(enableLink, key, props, objPropValue);
31
+
32
+ return [upperFirst(label), objPropValue, link, modifier];
31
33
  });
32
34
  })
33
35
  ).filter(Boolean);
34
36
  };
35
37
 
36
38
  export default buildPropsToDisplayWithContent;
39
+ function getLink(enableLink, key, props, objPropValue) {
40
+ let link = '';
41
+ if (enableLink) {
42
+ link = getLinkToPublishedContent(key, props);
43
+ if (!link) {
44
+ link = getLinkBasedOnValue(objPropValue);
45
+ }
46
+ }
47
+ return link;
48
+ }
@@ -0,0 +1,14 @@
1
+ import { DATA_SUMMARY_EMAIL_REGEX, DATA_SUMMARY_URL_REGEX } from '../../../constants';
2
+
3
+ function getLinkBasedOnValue(value) {
4
+ if (DATA_SUMMARY_EMAIL_REGEX.test(value)) {
5
+ return `mailto:${value}`;
6
+ }
7
+ if (DATA_SUMMARY_URL_REGEX.test(value)) {
8
+ return value;
9
+ }
10
+
11
+ return '';
12
+ }
13
+
14
+ export default getLinkBasedOnValue;
@@ -4,6 +4,7 @@ import getLinkToPublishedContent from './get-link-to-published-content';
4
4
  import stripSummaryPropsContent from './strip-summary-props-content';
5
5
  import buildLoopPropsContent from './build-loop-props-content';
6
6
  import parseBooleanValues from './parse-boolean-values';
7
+ import getLinkBasedOnValue from './get-link-based-on-value';
7
8
 
8
9
  export {
9
10
  getDataSummaryQuery,
@@ -11,5 +12,6 @@ export {
11
12
  getLinkToPublishedContent,
12
13
  stripSummaryPropsContent,
13
14
  buildLoopPropsContent,
14
- parseBooleanValues
15
+ parseBooleanValues,
16
+ getLinkBasedOnValue
15
17
  };
@@ -16,12 +16,15 @@ const Menu = ({
16
16
  mobileButtonModifier,
17
17
  hamburgerIconModifier,
18
18
  searchInputAlignment,
19
+ searchInputWrapperMobile,
20
+ searchInputWrapperDesktop,
19
21
  logoOnMobile,
20
22
  logoOnDesktop,
21
23
  logoOnMobileUrl,
22
24
  logoOnMobileAlt,
23
25
  logoOnMobileModifier,
24
26
  logoOnDesktopModifier,
27
+
25
28
  closeIconModifier,
26
29
  entity,
27
30
  ...rest
@@ -57,18 +60,14 @@ const Menu = ({
57
60
  )}
58
61
  </i>
59
62
  </BlazeButton>
60
- {showMobileMenu && (
61
- <SearchContent searchInputAlignment={searchInputAlignment} entity={entity} />
62
- )}
63
63
  </div>
64
64
  </div>
65
65
  )}
66
- {logoOnMobile &&
67
- !showMobileMenu && (
68
- <a href="/">
69
- <img src={logoOnMobileUrl} alt={logoOnMobileAlt} className={logoOnMobileModifier} />
70
- </a>
71
- )}
66
+ {logoOnMobile && (
67
+ <a href="/">
68
+ <img src={logoOnMobileUrl} alt={logoOnMobileAlt} className={logoOnMobileModifier} />
69
+ </a>
70
+ )}
72
71
 
73
72
  <div className="menu--desktop-wrapper">
74
73
  <ul className={isMobile ? childrenMobileModifier : childrenDesktopModifier}>
@@ -78,6 +77,17 @@ const Menu = ({
78
77
  </a>
79
78
  )}
80
79
  {children}
80
+ {searchInputAlignment === 'right' && (
81
+ <li>
82
+ <SearchContent
83
+ searchInputWrapperMobile={searchInputWrapperMobile}
84
+ searchInputWrapperDesktop={searchInputWrapperDesktop}
85
+ searchInputAlignment={searchInputAlignment}
86
+ entity={entity}
87
+ isMobile={isMobile}
88
+ />
89
+ </li>
90
+ )}
81
91
  </ul>
82
92
  </div>
83
93
  </>
@@ -99,8 +109,10 @@ Menu.propTypes = {
99
109
  mobileMenuChildrenModifier: PropTypes.string,
100
110
  modifier: PropTypes.string,
101
111
  mobileIconAlignment: PropTypes.string,
102
- searchInputAlignment: PropTypes.string,
103
112
  entity: PropTypes.string,
113
+ searchInputAlignment: PropTypes.string,
114
+ searchInputWrapperMobile: PropTypes.string,
115
+ searchInputWrapperDesktop: PropTypes.string,
104
116
  children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
105
117
  };
106
118
 
@@ -115,7 +127,9 @@ Menu.defaultProps = {
115
127
  mobileIconAlignment: '',
116
128
  mobileMenuModifier: '',
117
129
  mobileMenuChildrenModifier: '',
118
- searchInputAlignment: '',
130
+ searchInputAlignment: 'right',
131
+ searchInputWrapperMobile: '',
132
+ searchInputWrapperDesktop: '',
119
133
  modifier: '',
120
134
  entity: 'PublishedPage',
121
135
  children: []
@@ -1,20 +1,20 @@
1
- import { useState } from 'react';
1
+ import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { gql, useQuery } from '@apollo/client';
4
4
  import { useRouter } from 'next/router';
5
5
  import { getPublishedContent } from '../../application/query';
6
-
7
- const SearchContent = ({ searchInputAlignment, entity }) => {
6
+ import BlazeLink from '../BlazeLink';
7
+
8
+ const SearchContent = ({
9
+ entity,
10
+ searchInputWrapperMobile,
11
+ searchInputWrapperDesktop,
12
+ isMobile
13
+ }) => {
8
14
  const [collapsed, setCollapsed] = useState(true);
9
15
  const [searchTerm, setSearchTerm] = useState(null);
10
16
  const router = useRouter();
11
17
 
12
- let alignmentModifier = '';
13
-
14
- if (searchInputAlignment && searchInputAlignment !== '') {
15
- alignmentModifier = searchInputAlignment === 'left' ? 'left-6' : 'right-16';
16
- }
17
-
18
18
  const capitalize = s => {
19
19
  if (typeof s !== 'string') return '';
20
20
  return s.charAt(0).toUpperCase() + s.slice(1);
@@ -51,22 +51,22 @@ const SearchContent = ({ searchInputAlignment, entity }) => {
51
51
  if (loading) return null;
52
52
  if (error) return `Error! ${error}`;
53
53
 
54
+ const handleClick = (e, url) => {
55
+ e.preventDefault();
56
+ router.push(url);
57
+ };
58
+
54
59
  const renderResults = () => {
55
60
  // eslint-disable-next-line no-undef
56
61
  const { results } = data?.searchPublishedContent;
57
62
 
58
- const handleClick = (e, url) => {
59
- e.preventDefault();
60
- router.push(url);
61
- };
62
-
63
63
  if (results && searchTerm && searchTerm !== '') {
64
64
  return results.map(({ name, url }) => {
65
65
  if (name.match(searchTerm)) {
66
66
  return (
67
- <a href={url} onClick={e => handleClick(e, url)}>
67
+ <BlazeLink href={url} onClick={e => handleClick(e, url)}>
68
68
  {name}
69
- </a>
69
+ </BlazeLink>
70
70
  );
71
71
  }
72
72
 
@@ -80,7 +80,7 @@ const SearchContent = ({ searchInputAlignment, entity }) => {
80
80
  const searchResultsMessage = searchTerm ? `Search results for: ${searchTerm}` : '';
81
81
 
82
82
  return collapsed ? (
83
- <div className={`absolute rounded-3xl overflow-clip top-3 ${alignmentModifier}`}>
83
+ <div className={isMobile ? searchInputWrapperMobile : searchInputWrapperDesktop}>
84
84
  <div className="w-11 mx-auto">
85
85
  <label className="relative block">
86
86
  <span className="absolute inset-y-0 right-3 flex items-center pl-2 cursor-pointer">
@@ -99,14 +99,14 @@ const SearchContent = ({ searchInputAlignment, entity }) => {
99
99
  type="text"
100
100
  name="search"
101
101
  value=""
102
- className="disabled:bg-white block bg-white w-full rounded-full py-2 pl-5 pr-3 placeholder:italic placeholder:text-gray-400 focus:outline-none sm:text-sm"
102
+ className="disabled:bg-white block bg-white w-full rounded-none border-white py-2 pl-5 pr-3 placeholder:italic placeholder:text-gray-400 focus:outline-none sm:text-sm"
103
103
  />
104
104
  </label>
105
105
  </div>
106
106
  </div>
107
107
  ) : (
108
108
  <>
109
- <div className={`absolute overflow-clip top-3 ${alignmentModifier}`}>
109
+ <div className={`${isMobile ? searchInputWrapperMobile : searchInputWrapperDesktop}`}>
110
110
  <div className="w-96 mx-auto rounded-3xl">
111
111
  <label className="relative block">
112
112
  <span className="absolute inset-y-0 right-3 flex items-center pl-2">
@@ -123,31 +123,41 @@ const SearchContent = ({ searchInputAlignment, entity }) => {
123
123
  type="text"
124
124
  name="search"
125
125
  onChange={e => setSearchTerm(e.target.value)}
126
- className="block bg-white w-full rounded-full py-2 pl-3 pr-3 placeholder:italic placeholder:text-slate-400 focus:outline-none sm:text-sm"
126
+ className="block w-full rounded-full rounded-white py-2 pl-3 pr-3 placeholder:italic placeholder:text-slate-400 focus:outline-none sm:text-sm"
127
127
  placeholder="Search for anything..."
128
- onBlur={() => setCollapsed(true)}
128
+ onBlur={() => {
129
+ if (!searchTerm || searchTerm === '') setCollapsed(true);
130
+ }}
129
131
  />
130
132
  </label>
131
133
  </div>
132
- <div className="bg-white ml-1 mr-1 rounded rounded-lg relative top-0 flex flex-col">
133
- <div className="text-sm pt-2">{searchResultsMessage}</div>
134
-
135
- <div className="text-left px-4 py-2">
136
- <div className="text-bold">{data && renderResults()}</div>
137
- </div>
138
- </div>
134
+ {data &&
135
+ searchResultsMessage !== '' && (
136
+ <div className="bg-white ml-1 mr-1 rounded rounded-lg relative top-0 flex flex-col z-50 border-2 border-gray-50">
137
+ <div className="text-sm pt-2">{searchResultsMessage}</div>
138
+
139
+ <div className="text-left px-4 py-2">
140
+ <div className="text-bold">{renderResults()}</div>
141
+ </div>
142
+ </div>
143
+ )}
139
144
  </div>
140
145
  </>
141
146
  );
142
147
  };
143
148
 
144
149
  SearchContent.propTypes = {
145
- searchInputAlignment: PropTypes.string,
150
+ searchInputWrapperMobile: PropTypes.string,
151
+ searchInputWrapperDesktop: PropTypes.string,
152
+ isMobile: PropTypes.bool,
146
153
  entity: PropTypes.string.isRequired
147
154
  };
148
155
 
149
156
  SearchContent.defaultProps = {
150
- searchInputAlignment: ''
157
+ searchInputAlignment: '',
158
+ searchInputWrapperMobile: '',
159
+ searchInputWrapperDesktop: '',
160
+ isMobile: false
151
161
  };
152
162
 
153
163
  export default SearchContent;
@@ -205,6 +205,9 @@ const BANNER_LOADED = 'loaded';
205
205
  const ANCHOR_TAG = 'a';
206
206
  const TARGET_BLANK = '_blank';
207
207
 
208
+ const DATA_SUMMARY_EMAIL_REGEX = /^([a-z0-9_\.\+-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
209
+ const DATA_SUMMARY_URL_REGEX = /(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/;
210
+
208
211
  export {
209
212
  BANNER_LOADING,
210
213
  BANNER_EMPTY,
@@ -313,5 +316,7 @@ export {
313
316
  AZ,
314
317
  SCROLL_OFFSET,
315
318
  ANCHOR_TAG,
316
- TARGET_BLANK
319
+ TARGET_BLANK,
320
+ DATA_SUMMARY_EMAIL_REGEX,
321
+ DATA_SUMMARY_URL_REGEX
317
322
  };
@@ -27,4 +27,26 @@ describe('build props to display func', () => {
27
27
  it('should return an empty array if no values are passed', () => {
28
28
  expect(emptyPropsToDisplay.length).toEqual(0);
29
29
  });
30
+
31
+ it('should add link if enableLink=true', () => {
32
+ const obj = {
33
+ name: 'Item name',
34
+ url: '/url',
35
+ email: 'email@blazecms.app'
36
+ };
37
+ const propsTorDisplay = [
38
+ {
39
+ propertiesToDisplay: ['name'],
40
+ enableLink: false
41
+ },
42
+ {
43
+ propertiesToDisplay: ['email'],
44
+ enableLink: true
45
+ }
46
+ ];
47
+ const [nameProp, emailProp] = buildPropsToDisplayWithContent(obj, propsTorDisplay);
48
+
49
+ expect(nameProp[2]).toEqual('');
50
+ expect(emailProp[2]).toEqual('mailto:email@blazecms.app');
51
+ });
30
52
  });
@@ -0,0 +1,29 @@
1
+ /**
2
+ * @testEnvironment node
3
+ */
4
+ import { getLinkBasedOnValue } from '../../../../../../src/components/DataSummary/helpers';
5
+
6
+ describe('Get link based on value', () => {
7
+ it('should be a function', () => {
8
+ expect(typeof getLinkBasedOnValue).toEqual('function');
9
+ });
10
+
11
+ it('should not return link if value does not match values', () => {
12
+ const result = getLinkBasedOnValue('not matched');
13
+ expect(result).toEqual('');
14
+ });
15
+
16
+ it('should return mailto: link for email string', () => {
17
+ const email = 'email@blazecms.app';
18
+ const result = getLinkBasedOnValue(email);
19
+ expect(result).toEqual(`mailto:${email}`);
20
+ });
21
+
22
+ it('should return url link with or without scheme', () => {
23
+ const urls = ['https://www.blazecms.app/path?query=string', 'blazecms.app/page'];
24
+ urls.forEach(url => {
25
+ expect(getLinkBasedOnValue(url)).toEqual(url);
26
+ });
27
+ expect.hasAssertions();
28
+ });
29
+ });