@blaze-cms/react-page-builder 0.146.0-alpha.2 → 0.146.0-alpha.21

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 (228) hide show
  1. package/CHANGELOG.md +132 -0
  2. package/lib/components/Card/Card.js +14 -9
  3. package/lib/components/Card/Card.js.map +1 -1
  4. package/lib/components/Card/CardsContainer.js +8 -4
  5. package/lib/components/Card/CardsContainer.js.map +1 -1
  6. package/lib/components/Card/CardsFactory.js +37 -7
  7. package/lib/components/Card/CardsFactory.js.map +1 -1
  8. package/lib/components/Card/CardsRender.js +8 -4
  9. package/lib/components/Card/CardsRender.js.map +1 -1
  10. package/lib/components/Card/helpers/index.js +6 -6
  11. package/lib/components/Card/helpers/index.js.map +1 -1
  12. package/lib/components/Image/Lightbox/Lightbox.js +2 -2
  13. package/lib/components/Image/Lightbox/Lightbox.js.map +1 -1
  14. package/lib/components/List/ListRender.js.map +1 -1
  15. package/lib/components/MenuItem/MenuEntitiesItem.js +204 -0
  16. package/lib/components/MenuItem/MenuEntitiesItem.js.map +1 -0
  17. package/lib/components/MenuItem/MenuItem.js +25 -68
  18. package/lib/components/MenuItem/MenuItem.js.map +1 -1
  19. package/lib/components/MenuItem/MenuItemRender.js +104 -0
  20. package/lib/components/MenuItem/MenuItemRender.js.map +1 -0
  21. package/lib/components/MenuItem/helpers/index.js +15 -0
  22. package/lib/components/MenuItem/helpers/index.js.map +1 -0
  23. package/lib/components/MenuItem/helpers/inject-helper-into-template.js +17 -0
  24. package/lib/components/MenuItem/helpers/inject-helper-into-template.js.map +1 -0
  25. package/lib/components/Modal/Modal.js +2 -2
  26. package/lib/components/Modal/Modal.js.map +1 -1
  27. package/lib/components/ModalAdapter/ModalAdapter.js +21 -0
  28. package/lib/components/ModalAdapter/ModalAdapter.js.map +1 -0
  29. package/lib/components/ModalAdapter/index.js +11 -0
  30. package/lib/components/ModalAdapter/index.js.map +1 -0
  31. package/lib/components/SearchFilter/SearchFilter/SearchFilter.js +22 -4
  32. package/lib/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
  33. package/lib/components/SearchFilter/SearchFilterContainer.js +22 -27
  34. package/lib/components/SearchFilter/SearchFilterContainer.js.map +1 -1
  35. package/lib/components/SearchFilter/components/Select.js.map +1 -1
  36. package/lib/components/SearchFilter/helpers/build-list-name-query.js +31 -0
  37. package/lib/components/SearchFilter/helpers/build-list-name-query.js.map +1 -0
  38. package/lib/components/SearchFilter/helpers/decode-encode.js.map +1 -1
  39. package/lib/components/SearchFilter/helpers/index.js +7 -0
  40. package/lib/components/SearchFilter/helpers/index.js.map +1 -1
  41. package/lib/components/Video/Video.js +2 -1
  42. package/lib/components/Video/Video.js.map +1 -1
  43. package/lib/components/Video/VideoContext.js +12 -0
  44. package/lib/components/Video/VideoContext.js.map +1 -0
  45. package/lib/components/Video/VideoModal.js +2 -2
  46. package/lib/components/Video/VideoModal.js.map +1 -1
  47. package/lib/components/Video/VideoRender.js +36 -3
  48. package/lib/components/Video/VideoRender.js.map +1 -1
  49. package/lib/components/Video/constants.js +14 -0
  50. package/lib/components/Video/constants.js.map +1 -0
  51. package/lib/components/Video/helpers/emit-gtm-event.js +31 -0
  52. package/lib/components/Video/helpers/emit-gtm-event.js.map +1 -0
  53. package/lib/components/Video/providers/JWPlayer/JWPlayerController.js +28 -8
  54. package/lib/components/Video/providers/JWPlayer/JWPlayerController.js.map +1 -1
  55. package/lib/components/Video/providers/JWPlayer/JWPlayerProvider.js +16 -4
  56. package/lib/components/Video/providers/JWPlayer/JWPlayerProvider.js.map +1 -1
  57. package/lib/components/Video/providers/YouTube/YoutubeEmbeded.js +57 -0
  58. package/lib/components/Video/providers/YouTube/YoutubeEmbeded.js.map +1 -1
  59. package/lib/helpers/build-filters-query.js +1 -2
  60. package/lib/helpers/build-filters-query.js.map +1 -1
  61. package/lib/{components/Card/helpers → helpers}/filter-query-setup.js +10 -7
  62. package/lib/helpers/filter-query-setup.js.map +1 -0
  63. package/lib/{components/Card/helpers → helpers}/filters-setup.js +8 -5
  64. package/lib/helpers/filters-setup.js.map +1 -0
  65. package/lib/helpers/get-updated-items-to-display.js.map +1 -0
  66. package/lib/helpers/get-updated-sort-properties.js.map +1 -0
  67. package/lib/helpers/index.js +42 -0
  68. package/lib/helpers/index.js.map +1 -1
  69. package/lib/helpers/should-return.js.map +1 -0
  70. package/lib/{components/Card/helpers → helpers}/should-skip-single-query.js +1 -1
  71. package/lib/helpers/should-skip-single-query.js.map +1 -0
  72. package/lib/hooks/index.js +14 -0
  73. package/lib/hooks/index.js.map +1 -1
  74. package/lib/hooks/use-filter-aggregation-values.js +54 -0
  75. package/lib/hooks/use-filter-aggregation-values.js.map +1 -0
  76. package/lib/hooks/use-portal.js +30 -0
  77. package/lib/hooks/use-portal.js.map +1 -0
  78. package/lib-es/components/Card/Card.js +14 -9
  79. package/lib-es/components/Card/Card.js.map +1 -1
  80. package/lib-es/components/Card/CardsContainer.js +9 -5
  81. package/lib-es/components/Card/CardsContainer.js.map +1 -1
  82. package/lib-es/components/Card/CardsFactory.js +40 -9
  83. package/lib-es/components/Card/CardsFactory.js.map +1 -1
  84. package/lib-es/components/Card/CardsRender.js +9 -5
  85. package/lib-es/components/Card/CardsRender.js.map +1 -1
  86. package/lib-es/components/Card/helpers/index.js +6 -6
  87. package/lib-es/components/Card/helpers/index.js.map +1 -1
  88. package/lib-es/components/Image/Lightbox/Lightbox.js +1 -1
  89. package/lib-es/components/Image/Lightbox/Lightbox.js.map +1 -1
  90. package/lib-es/components/List/ListRender.js.map +1 -1
  91. package/lib-es/components/MenuItem/MenuEntitiesItem.js +178 -0
  92. package/lib-es/components/MenuItem/MenuEntitiesItem.js.map +1 -0
  93. package/lib-es/components/MenuItem/MenuItem.js +28 -57
  94. package/lib-es/components/MenuItem/MenuItem.js.map +1 -1
  95. package/lib-es/components/MenuItem/MenuItemRender.js +84 -0
  96. package/lib-es/components/MenuItem/MenuItemRender.js.map +1 -0
  97. package/lib-es/components/MenuItem/helpers/index.js +3 -0
  98. package/lib-es/components/MenuItem/helpers/index.js.map +1 -0
  99. package/lib-es/components/MenuItem/helpers/inject-helper-into-template.js +8 -0
  100. package/lib-es/components/MenuItem/helpers/inject-helper-into-template.js.map +1 -0
  101. package/lib-es/components/Modal/Modal.js +1 -1
  102. package/lib-es/components/Modal/Modal.js.map +1 -1
  103. package/lib-es/components/ModalAdapter/ModalAdapter.js +13 -0
  104. package/lib-es/components/ModalAdapter/ModalAdapter.js.map +1 -0
  105. package/lib-es/components/ModalAdapter/index.js +3 -0
  106. package/lib-es/components/ModalAdapter/index.js.map +1 -0
  107. package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js +15 -4
  108. package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
  109. package/lib-es/components/SearchFilter/SearchFilterContainer.js +23 -20
  110. package/lib-es/components/SearchFilter/SearchFilterContainer.js.map +1 -1
  111. package/lib-es/components/SearchFilter/components/Select.js.map +1 -1
  112. package/lib-es/components/SearchFilter/helpers/build-list-name-query.js +15 -0
  113. package/lib-es/components/SearchFilter/helpers/build-list-name-query.js.map +1 -0
  114. package/lib-es/components/SearchFilter/helpers/decode-encode.js.map +1 -1
  115. package/lib-es/components/SearchFilter/helpers/index.js +2 -1
  116. package/lib-es/components/SearchFilter/helpers/index.js.map +1 -1
  117. package/lib-es/components/Video/Video.js +2 -1
  118. package/lib-es/components/Video/Video.js.map +1 -1
  119. package/lib-es/components/Video/VideoContext.js +6 -0
  120. package/lib-es/components/Video/VideoContext.js.map +1 -0
  121. package/lib-es/components/Video/VideoModal.js +1 -1
  122. package/lib-es/components/Video/VideoModal.js.map +1 -1
  123. package/lib-es/components/Video/VideoRender.js +28 -3
  124. package/lib-es/components/Video/VideoRender.js.map +1 -1
  125. package/lib-es/components/Video/constants.js +7 -0
  126. package/lib-es/components/Video/constants.js.map +1 -0
  127. package/lib-es/components/Video/helpers/emit-gtm-event.js +25 -0
  128. package/lib-es/components/Video/helpers/emit-gtm-event.js.map +1 -0
  129. package/lib-es/components/Video/providers/JWPlayer/JWPlayerController.js +28 -4
  130. package/lib-es/components/Video/providers/JWPlayer/JWPlayerController.js.map +1 -1
  131. package/lib-es/components/Video/providers/JWPlayer/JWPlayerProvider.js +10 -4
  132. package/lib-es/components/Video/providers/JWPlayer/JWPlayerProvider.js.map +1 -1
  133. package/lib-es/components/Video/providers/YouTube/YoutubeEmbeded.js +60 -2
  134. package/lib-es/components/Video/providers/YouTube/YoutubeEmbeded.js.map +1 -1
  135. package/lib-es/helpers/build-filters-query.js +1 -2
  136. package/lib-es/helpers/build-filters-query.js.map +1 -1
  137. package/lib-es/{components/Card/helpers → helpers}/filter-query-setup.js +5 -3
  138. package/lib-es/helpers/filter-query-setup.js.map +1 -0
  139. package/lib-es/{components/Card/helpers → helpers}/filters-setup.js +4 -2
  140. package/lib-es/helpers/filters-setup.js.map +1 -0
  141. package/lib-es/helpers/get-updated-items-to-display.js.map +1 -0
  142. package/lib-es/helpers/get-updated-sort-properties.js.map +1 -0
  143. package/lib-es/helpers/index.js +6 -0
  144. package/lib-es/helpers/index.js.map +1 -1
  145. package/lib-es/helpers/should-return.js.map +1 -0
  146. package/lib-es/{components/Card/helpers → helpers}/should-skip-single-query.js +1 -1
  147. package/lib-es/helpers/should-skip-single-query.js.map +1 -0
  148. package/lib-es/hooks/index.js +2 -0
  149. package/lib-es/hooks/index.js.map +1 -1
  150. package/lib-es/hooks/use-filter-aggregation-values.js +31 -0
  151. package/lib-es/hooks/use-filter-aggregation-values.js.map +1 -0
  152. package/lib-es/hooks/use-portal.js +14 -0
  153. package/lib-es/hooks/use-portal.js.map +1 -0
  154. package/package.json +7 -7
  155. package/src/components/Card/Card.js +25 -16
  156. package/src/components/Card/CardsContainer.js +7 -3
  157. package/src/components/Card/CardsFactory.js +34 -6
  158. package/src/components/Card/CardsRender.js +6 -2
  159. package/src/components/Card/helpers/index.js +6 -6
  160. package/src/components/Image/Lightbox/Lightbox.js +1 -1
  161. package/src/components/List/ListRender.js +0 -1
  162. package/src/components/MenuItem/MenuEntitiesItem.js +204 -0
  163. package/src/components/MenuItem/MenuItem.js +15 -58
  164. package/src/components/MenuItem/MenuItemRender.js +92 -0
  165. package/src/components/MenuItem/helpers/index.js +3 -0
  166. package/src/components/MenuItem/helpers/inject-helper-into-template.js +11 -0
  167. package/src/components/Modal/Modal.js +1 -1
  168. package/src/components/ModalAdapter/ModalAdapter.js +12 -0
  169. package/src/components/ModalAdapter/index.js +3 -0
  170. package/src/components/SearchFilter/SearchFilter/SearchFilter.js +16 -5
  171. package/src/components/SearchFilter/SearchFilterContainer.js +21 -22
  172. package/src/components/SearchFilter/components/Select.js +2 -0
  173. package/src/components/SearchFilter/helpers/build-list-name-query.js +18 -0
  174. package/src/components/SearchFilter/helpers/decode-encode.js +0 -1
  175. package/src/components/SearchFilter/helpers/index.js +2 -0
  176. package/src/components/Video/Video.js +1 -1
  177. package/src/components/Video/VideoContext.js +7 -0
  178. package/src/components/Video/VideoModal.js +1 -1
  179. package/src/components/Video/VideoRender.js +28 -3
  180. package/src/components/Video/constants.js +6 -0
  181. package/src/components/Video/helpers/emit-gtm-event.js +25 -0
  182. package/src/components/Video/providers/JWPlayer/JWPlayerController.js +21 -4
  183. package/src/components/Video/providers/JWPlayer/JWPlayerProvider.js +7 -5
  184. package/src/components/Video/providers/YouTube/YoutubeEmbeded.js +65 -2
  185. package/src/helpers/build-filters-query.js +1 -3
  186. package/src/{components/Card/helpers → helpers}/filter-query-setup.js +5 -3
  187. package/src/{components/Card/helpers → helpers}/filters-setup.js +5 -2
  188. package/src/helpers/index.js +6 -0
  189. package/src/{components/Card/helpers → helpers}/should-skip-single-query.js +1 -1
  190. package/src/hooks/index.js +2 -0
  191. package/src/hooks/use-filter-aggregation-values.js +37 -0
  192. package/src/hooks/use-portal.js +18 -0
  193. package/tests/unit/src/components/Card/Card.test.js +16 -1
  194. package/tests/unit/src/components/Card/__snapshots__/Card.test.js.snap +83 -0
  195. package/tests/unit/src/components/Card/helpers/get-updated-items-to-display.test.js +1 -1
  196. package/tests/unit/src/components/Image/Lightbox/Lightbox.test.js +4 -0
  197. package/tests/unit/src/components/Image/Lightbox/__snapshots__/Lightbox.test.js.snap +3 -38
  198. package/tests/unit/src/components/MenuItem/MenuEntitiesItem.test.js +23 -0
  199. package/tests/unit/src/components/MenuItem/MenuItem.test.js +30 -11
  200. package/tests/unit/src/components/MenuItem/MenuItemRender.test.js +55 -0
  201. package/tests/unit/src/components/MenuItem/__snapshots__/MenuEntitiesItem.test.js.snap +3 -0
  202. package/tests/unit/src/components/MenuItem/__snapshots__/MenuItem.test.js.snap +5 -51
  203. package/tests/unit/src/components/MenuItem/helpers/inject-helper-into-template.test.js +44 -0
  204. package/tests/unit/src/components/MenuItem/mocks.js +71 -0
  205. package/tests/unit/src/components/Modal/Modal.test.js +4 -0
  206. package/tests/unit/src/components/Modal/__snapshots__/Modal.test.js.snap +7 -42
  207. package/tests/unit/src/components/SearchFilter/__snapshots__/SearchFilterContainer.test.js.snap +7 -1
  208. package/lib/components/Card/helpers/filter-query-setup.js.map +0 -1
  209. package/lib/components/Card/helpers/filters-setup.js.map +0 -1
  210. package/lib/components/Card/helpers/get-updated-items-to-display.js.map +0 -1
  211. package/lib/components/Card/helpers/get-updated-sort-properties.js.map +0 -1
  212. package/lib/components/Card/helpers/should-return.js.map +0 -1
  213. package/lib/components/Card/helpers/should-skip-single-query.js.map +0 -1
  214. package/lib-es/components/Card/helpers/filter-query-setup.js.map +0 -1
  215. package/lib-es/components/Card/helpers/filters-setup.js.map +0 -1
  216. package/lib-es/components/Card/helpers/get-updated-items-to-display.js.map +0 -1
  217. package/lib-es/components/Card/helpers/get-updated-sort-properties.js.map +0 -1
  218. package/lib-es/components/Card/helpers/should-return.js.map +0 -1
  219. package/lib-es/components/Card/helpers/should-skip-single-query.js.map +0 -1
  220. /package/lib/{components/Card/helpers → helpers}/get-updated-items-to-display.js +0 -0
  221. /package/lib/{components/Card/helpers → helpers}/get-updated-sort-properties.js +0 -0
  222. /package/lib/{components/Card/helpers → helpers}/should-return.js +0 -0
  223. /package/lib-es/{components/Card/helpers → helpers}/get-updated-items-to-display.js +0 -0
  224. /package/lib-es/{components/Card/helpers → helpers}/get-updated-sort-properties.js +0 -0
  225. /package/lib-es/{components/Card/helpers → helpers}/should-return.js +0 -0
  226. /package/src/{components/Card/helpers → helpers}/get-updated-items-to-display.js +0 -0
  227. /package/src/{components/Card/helpers → helpers}/get-updated-sort-properties.js +0 -0
  228. /package/src/{components/Card/helpers → helpers}/should-return.js +0 -0
@@ -1,76 +1,33 @@
1
- import React, { useState, useContext, useEffect } from 'react';
1
+ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
4
- import { HOVER, MOUSE_ENTER, MOUSE_LEAVE, HIDDEN } from '../../constants';
5
- import { hasChildren } from '../../helpers';
6
- import BlazeLink from '../BlazeLink';
7
- import MenuContext from '../Menu/MenuContext';
3
+ import MenuItemRender from './MenuItemRender';
4
+ import MenuEntitiesItem from './MenuEntitiesItem';
8
5
 
9
- const MenuItem = ({ children, eventType, text, modifier, url }) => {
10
- const [displayChildren, setDisplayChildren] = useState(false);
11
- const { showMobileMenu } = useContext(MenuContext);
6
+ const MenuItem = ({ entities, parent, ...props }) => {
7
+ const hasEntities = entities && entities.length;
12
8
 
13
- useEffect(
14
- () => {
15
- if (!showMobileMenu) setDisplayChildren(false);
16
- },
17
- [showMobileMenu]
18
- );
9
+ if (!hasEntities) return <MenuItemRender parent={parent} {...props} />;
19
10
 
20
- const isHoverEvent = eventType === HOVER;
21
- const childrenDisplayClass = displayChildren ? '' : HIDDEN;
22
-
23
- const handleItemEvent = ({ type }) => {
24
- if (isHoverEvent) {
25
- if (type === MOUSE_ENTER) {
26
- setDisplayChildren(true);
27
- }
28
- if (type === MOUSE_LEAVE) {
29
- setDisplayChildren(false);
30
- }
31
- }
32
- };
33
- const hasValidChildren = hasChildren(children);
34
-
35
- return (
36
- <li className={modifier} onMouseEnter={handleItemEvent} onMouseLeave={handleItemEvent}>
37
- <div className="menu--item--link">
38
- {url ? (
39
- <BlazeLink href={url}>{text}</BlazeLink>
40
- ) : (
41
- <span role="button" onClick={handleItemEvent}>
42
- {text}
43
- </span>
44
- )}
45
- {hasValidChildren && (
46
- <i
47
- role="button"
48
- className="menu--item--link--icon"
49
- onClick={() => setDisplayChildren(!displayChildren)}>
50
- {displayChildren ? <FaChevronUp /> : <FaChevronDown />}
51
- </i>
52
- )}
53
- </div>
54
- {hasValidChildren && (
55
- <div className={`menu--item-children ${childrenDisplayClass}`}>{children}</div>
56
- )}
57
- </li>
58
- );
11
+ return <MenuEntitiesItem entities={entities} parent={parent} {...props} />;
59
12
  };
60
13
 
61
14
  MenuItem.propTypes = {
15
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node]),
16
+ eventType: PropTypes.string.isRequired,
62
17
  modifier: PropTypes.string,
18
+ parent: PropTypes.object,
63
19
  text: PropTypes.string,
64
20
  url: PropTypes.string,
65
- eventType: PropTypes.string.isRequired,
66
- children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
21
+ entities: PropTypes.array
67
22
  };
68
23
 
69
24
  MenuItem.defaultProps = {
70
- url: '',
25
+ children: null,
71
26
  modifier: '',
27
+ parent: {},
72
28
  text: '',
73
- children: null
29
+ url: '',
30
+ entities: []
74
31
  };
75
32
 
76
33
  export default MenuItem;
@@ -0,0 +1,92 @@
1
+ import React, { useState, useContext, useEffect } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { FaChevronDown, FaChevronUp } from 'react-icons/fa';
4
+ import { useStringTemplate } from '@blaze-cms/utils-handlebars';
5
+ import { HOVER, MOUSE_ENTER, MOUSE_LEAVE, HIDDEN } from '../../constants';
6
+ import { hasChildren } from '../../helpers';
7
+ import BlazeLink from '../BlazeLink';
8
+ import MenuContext from '../Menu/MenuContext';
9
+ import { injectHelperIntoTemplate } from './helpers';
10
+
11
+ const MenuItemRender = ({ children, eventType, text, modifier, url, parent }) => {
12
+ const [displayChildren, setDisplayChildren] = useState(false);
13
+ const { showMobileMenu } = useContext(MenuContext);
14
+ const {
15
+ loading: loadingText,
16
+ data: [textToUse]
17
+ } = useStringTemplate(parent, [text]);
18
+
19
+ const {
20
+ loading: loadingUrl,
21
+ data: [urlToUse]
22
+ } = useStringTemplate(parent, [injectHelperIntoTemplate(url, 'url_encode')]);
23
+
24
+ useEffect(
25
+ () => {
26
+ if (!showMobileMenu) setDisplayChildren(false);
27
+ },
28
+ [showMobileMenu]
29
+ );
30
+
31
+ if (loadingUrl || loadingText) return '';
32
+
33
+ const isHoverEvent = eventType === HOVER;
34
+ const childrenDisplayClass = displayChildren ? '' : HIDDEN;
35
+
36
+ const handleItemEvent = ({ type }) => {
37
+ if (isHoverEvent) {
38
+ if (type === MOUSE_ENTER) {
39
+ setDisplayChildren(true);
40
+ }
41
+ if (type === MOUSE_LEAVE) {
42
+ setDisplayChildren(false);
43
+ }
44
+ }
45
+ };
46
+ const hasValidChildren = hasChildren(children);
47
+
48
+ return (
49
+ <li className={modifier} onMouseEnter={handleItemEvent} onMouseLeave={handleItemEvent}>
50
+ <div className="menu--item--link">
51
+ {urlToUse ? (
52
+ <BlazeLink href={urlToUse}>{textToUse}</BlazeLink>
53
+ ) : (
54
+ <span role="button" onClick={handleItemEvent}>
55
+ {textToUse}
56
+ </span>
57
+ )}
58
+ {hasValidChildren && (
59
+ <i
60
+ role="button"
61
+ className="menu--item--link--icon"
62
+ onClick={() => setDisplayChildren(!displayChildren)}>
63
+ {displayChildren ? <FaChevronUp /> : <FaChevronDown />}
64
+ </i>
65
+ )}
66
+ </div>
67
+
68
+ {hasValidChildren && (
69
+ <div className={`menu--item-children ${childrenDisplayClass}`}>{children}</div>
70
+ )}
71
+ </li>
72
+ );
73
+ };
74
+
75
+ MenuItemRender.propTypes = {
76
+ modifier: PropTypes.string,
77
+ text: PropTypes.string,
78
+ url: PropTypes.string,
79
+ eventType: PropTypes.string.isRequired,
80
+ parent: PropTypes.object,
81
+ children: PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.node), PropTypes.node])
82
+ };
83
+
84
+ MenuItemRender.defaultProps = {
85
+ url: '',
86
+ modifier: '',
87
+ text: '',
88
+ children: null,
89
+ parent: {}
90
+ };
91
+
92
+ export default MenuItemRender;
@@ -0,0 +1,3 @@
1
+ import injectHelperIntoTemplate from './inject-helper-into-template';
2
+
3
+ export { injectHelperIntoTemplate };
@@ -0,0 +1,11 @@
1
+ const injectHelperIntoTemplate = (template, helper) => {
2
+ if (!helper || !template) return template;
3
+
4
+ let result = template.replace(/{{{([^{}]+)}}}/g, `{{{${helper} $1}}}`);
5
+
6
+ result = result.replace(/{{([^{}]+)}}(?!})/g, `{{${helper} $1}}`);
7
+
8
+ return result;
9
+ };
10
+
11
+ export default injectHelperIntoTemplate;
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import BlazeModal from '@blaze-react/modal';
3
+ import BlazeModal from '../ModalAdapter';
4
4
  import { renderChildren, updateChildrensParent, hasChildren } from '../../helpers';
5
5
 
6
6
  const Modal = ({ children, elementTitle, onClose, ...otherProps }) => {
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+ import Modal from '@blaze-react/modal';
3
+ import ReactDOM from 'react-dom';
4
+ import { usePortal } from '../../hooks';
5
+
6
+ const ModalAdapter = ({ ...props }) => {
7
+ const target = usePortal();
8
+
9
+ return ReactDOM.createPortal(<Modal {...props} />, target);
10
+ };
11
+
12
+ export default ModalAdapter;
@@ -0,0 +1,3 @@
1
+ import ModalAdapter from './ModalAdapter';
2
+
3
+ export default ModalAdapter;
@@ -3,17 +3,17 @@ import PropTypes from 'prop-types';
3
3
  import classnames from 'classnames';
4
4
  import debounce from 'lodash.debounce';
5
5
  import FiltersList from './FiltersList';
6
- import { isDeviceDesktop, getResponsiveFilterClassnames, buildUrlQuery } from '../helpers';
7
-
8
6
  import CloseMobileForm from './CloseMobileForm';
9
7
  import ResetDesktopForm from './ResetDesktopForm';
10
8
  import MobileFormToolbar from './MobileFormToolbar';
9
+ import { useFilterAggregationValues } from '../../../hooks';
10
+ import { isDeviceDesktop, getResponsiveFilterClassnames, buildUrlQuery } from '../helpers';
11
11
  import { SEARCH, REFINE, MORE_FILTERS_CLASSES } from '../constants';
12
12
 
13
13
  const SearchFilter = ({
14
14
  searchFilterRef,
15
15
  listComponentName,
16
- data,
16
+ data: filterData,
17
17
  filters,
18
18
  hasUrl,
19
19
  entity,
@@ -26,11 +26,17 @@ const SearchFilter = ({
26
26
  groupAfterMobile,
27
27
  filterValues,
28
28
  setAppliedFilters,
29
+ mobileRefineButtonText,
29
30
  query
30
31
  }) => {
31
32
  const [moreFiltersMobileCollapsed, setMoreFiltersMobileCollapsed] = useState(true);
32
33
  const [moreFiltersDesktopCollapsed, setMoreFiltersDesktopCollapsed] = useState(true);
33
34
 
35
+ const [data, setStateValues, setSelectProp] = useFilterAggregationValues({
36
+ data: filterData,
37
+ filterValues
38
+ });
39
+
34
40
  const doSubmit = newValues => {
35
41
  const newQuery = filterValues
36
42
  ? buildUrlQuery(newValues, filters, listComponentName, query)
@@ -74,6 +80,8 @@ const SearchFilter = ({
74
80
  };
75
81
 
76
82
  const updateFilterValues = (newValues, shouldSubmit) => {
83
+ const [lastChangedFilter] = Object.keys(newValues);
84
+ setSelectProp(lastChangedFilter);
77
85
  setAppliedFilters({ newValues, shouldSearch: shouldSubmit, type: 'update' });
78
86
  };
79
87
 
@@ -89,6 +97,7 @@ const SearchFilter = ({
89
97
  onSubmit={e => {
90
98
  e.preventDefault();
91
99
  doSubmit(filterValues);
100
+ setStateValues(filterData);
92
101
  }}>
93
102
  {displaySearchFilter && (
94
103
  <CloseMobileForm handleClose={() => setDisplaySearchFilter(false)} />
@@ -216,7 +225,7 @@ const SearchFilter = ({
216
225
  data-testid="refine-mobile"
217
226
  aria-label="Toggle Search Filter">
218
227
  <div role="button" onClick={() => setDisplaySearchFilter(true)}>
219
- {REFINE}
228
+ {mobileRefineButtonText || REFINE}
220
229
  </div>
221
230
  </div>
222
231
  )}
@@ -240,10 +249,12 @@ SearchFilter.propTypes = {
240
249
  filterValues: PropTypes.object.isRequired,
241
250
  setAppliedFilters: PropTypes.func.isRequired,
242
251
  listComponentName: PropTypes.string,
243
- query: PropTypes.object
252
+ query: PropTypes.object,
253
+ mobileRefineButtonText: PropTypes.string
244
254
  };
245
255
 
246
256
  SearchFilter.defaultProps = {
257
+ mobileRefineButtonText: '',
247
258
  listComponentName: '',
248
259
  query: {}
249
260
  };
@@ -11,7 +11,8 @@ import {
11
11
  buildNewUrl,
12
12
  getFilterValues,
13
13
  getFilterRangesAndCheckboxesValues,
14
- getUpdatedFilterBy
14
+ getUpdatedFilterBy,
15
+ buildListNameQuery
15
16
  } from './helpers';
16
17
  import {
17
18
  getEntityData,
@@ -25,23 +26,6 @@ import { SCROLL_OFFSET } from '../../constants';
25
26
  import searchFilterReducer from './searchFilterReducer';
26
27
  import { useGetEntitySchemasAsObj } from '../../hooks';
27
28
 
28
- const getFiltersUrlQuery = (query, listName) => {
29
- if (!listName) return query;
30
- const updatedQuery = {};
31
- const listKey = `pb[${listName}]`;
32
- Object.keys(query).forEach(queryKey => {
33
- const isListKey = queryKey.indexOf(`${listName}`) !== -1;
34
- if (!isListKey) return;
35
- const decodedQueryValue = Array.isArray(query[queryKey])
36
- ? query[queryKey].map(value => decodeURIComponent(value))
37
- : decodeURIComponent(query[queryKey]);
38
- const strippedKey = queryKey.substring(listKey.length + 1, queryKey.length - 1);
39
- if (isListKey) updatedQuery[strippedKey] = decodedQueryValue;
40
- });
41
-
42
- return updatedQuery;
43
- };
44
-
45
29
  const SearchFilterContainer = ({
46
30
  entity,
47
31
  url,
@@ -54,7 +38,8 @@ const SearchFilterContainer = ({
54
38
  filterByProperty,
55
39
  shouldAddFilters,
56
40
  listComponentName,
57
- parent
41
+ parent,
42
+ mobileRefineButtonText
58
43
  }) => {
59
44
  const { isPreview } = useContext(MainContext);
60
45
  const router = useRouter();
@@ -65,15 +50,26 @@ const SearchFilterContainer = ({
65
50
  const [urlPath, setUrlPath] = useState(asPath); // used as asPath can take too long to update
66
51
  const [filterValues, dispatch] = useReducer(searchFilterReducer, null);
67
52
  const { url: currentUrl, query } = parseUrl(urlPath);
68
- const updatedQuery = getFiltersUrlQuery(query, listComponentName);
53
+ const updatedQuery = buildListNameQuery(query, listComponentName);
69
54
  const { itemId: parentId, itemEntity: parentEntity } = parent;
70
55
 
71
56
  useEffect(
72
57
  () => {
73
- if (asPath) setUrlPath(asPath);
58
+ const { query: newQuery } = parseUrl(asPath);
59
+ const updatedNewQuery = buildListNameQuery(newQuery, listComponentName);
60
+ const newValues = getFilterValues({}, filters, updatedNewQuery);
61
+ if (newValues)
62
+ dispatch({
63
+ newValues,
64
+ shouldSearch: false,
65
+ type: 'update'
66
+ });
67
+ setUrlPath(asPath);
74
68
  },
69
+ // eslint-disable-next-line react-hooks/exhaustive-deps
75
70
  [asPath]
76
71
  );
72
+
77
73
  const { data: mainSchemas = {}, loading: schemasLoading } = useGetEntitySchemasAsObj([
78
74
  parentEntity,
79
75
  entity
@@ -186,11 +182,13 @@ const SearchFilterContainer = ({
186
182
  setDisplaySearchFilter={setDisplaySearchFilter}
187
183
  groupAfterMobile={groupAfterMobile}
188
184
  groupAfterDesktop={groupAfterDesktop}
185
+ mobileRefineButtonText={mobileRefineButtonText}
189
186
  />
190
187
  );
191
188
  };
192
189
 
193
190
  SearchFilterContainer.propTypes = {
191
+ mobileRefineButtonText: PropTypes.string,
194
192
  entity: PropTypes.string,
195
193
  url: PropTypes.string,
196
194
  filters: PropTypes.array,
@@ -216,7 +214,8 @@ SearchFilterContainer.defaultProps = {
216
214
  filterByProperty: [],
217
215
  shouldAddFilters: false,
218
216
  listComponentName: '',
219
- parent: {}
217
+ parent: {},
218
+ mobileRefineButtonText: ''
220
219
  };
221
220
 
222
221
  export default withTitle(SearchFilterContainer);
@@ -17,6 +17,7 @@ const SelectFilter = ({
17
17
  const filterValue = filterValues[prop] || '';
18
18
  const disabledOptions = [];
19
19
  const { buckets = [] } = data[prop] || {};
20
+
20
21
  const options = buckets
21
22
  .map(({ key, doc_count: count }) => {
22
23
  if (!count) disabledOptions.push(key);
@@ -48,6 +49,7 @@ const SelectFilter = ({
48
49
  onChange={({ value }) => {
49
50
  let valueToUse = value;
50
51
  if (value === defaultTextValue) valueToUse = '';
52
+
51
53
  updateFilterValues({ [prop]: valueToUse }, shouldSearch);
52
54
  }}
53
55
  disabled={disabledOptions}
@@ -0,0 +1,18 @@
1
+ const buildListNameQuery = (query, listName) => {
2
+ if (!listName) return query;
3
+ const updatedQuery = {};
4
+ const listKey = `pb[${listName}]`;
5
+ Object.keys(query).forEach(queryKey => {
6
+ const isListKey = queryKey.indexOf(`${listName}`) !== -1;
7
+ if (!isListKey) return;
8
+ const decodedQueryValue = Array.isArray(query[queryKey])
9
+ ? query[queryKey].map(value => decodeURIComponent(value))
10
+ : decodeURIComponent(query[queryKey]);
11
+ const strippedKey = queryKey.substring(listKey.length + 1, queryKey.length - 1);
12
+ if (isListKey) updatedQuery[strippedKey] = decodedQueryValue;
13
+ });
14
+
15
+ return updatedQuery;
16
+ };
17
+
18
+ export default buildListNameQuery;
@@ -1,5 +1,4 @@
1
1
  const decodeValue = value => decodeURIComponent(value);
2
-
3
2
  const encodeValue = value => encodeURIComponent(value);
4
3
 
5
4
  export { decodeValue, encodeValue };
@@ -1,3 +1,4 @@
1
+ import buildListNameQuery from './build-list-name-query';
1
2
  import buildNewUrl from './build-new-url';
2
3
  import { decodeValue, encodeValue } from './decode-encode';
3
4
  import checkIfRangeUpdated from './check-if-range-updated';
@@ -16,6 +17,7 @@ import getUpdatedFilterBy from './get-updated-filter-by';
16
17
  import buildUrlQuery from './build-url-query';
17
18
 
18
19
  export {
20
+ buildListNameQuery,
19
21
  buildNewUrl,
20
22
  decodeValue,
21
23
  encodeValue,
@@ -43,7 +43,7 @@ const Video = ({
43
43
  });
44
44
 
45
45
  return (
46
- <Wrapper className="video" modifiers={modifiers}>
46
+ <Wrapper className="video" modifiers={modifiers} key={url}>
47
47
  {playInModal ? (
48
48
  <VideoModal
49
49
  url={url}
@@ -0,0 +1,7 @@
1
+ import { createContext } from 'react';
2
+
3
+ const VideoContext = createContext({});
4
+ const VideoContextProvider = VideoContext.Provider;
5
+ const VideoContextConsumer = VideoContext.Consumer;
6
+
7
+ export { VideoContext, VideoContextProvider, VideoContextConsumer };
@@ -1,5 +1,5 @@
1
1
  import React, { useState } from 'react';
2
- import Modal from '@blaze-react/modal';
2
+ import Modal from '../ModalAdapter';
3
3
  import VideoRender from './VideoRender';
4
4
 
5
5
  const VideoModal = ({ ...props }) => {
@@ -1,15 +1,40 @@
1
- import React from 'react';
1
+ import React, { useRef } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import getProvider from './providers';
4
4
  import { withTitle } from '../../HOC';
5
+ import { VideoContextProvider } from './VideoContext';
6
+ import emitGtmEvent from './helpers/emit-gtm-event';
5
7
 
6
8
  const VideoRender = ({ provider, ...props }) => {
9
+ const ref = useRef(0);
7
10
  const Provider = getProvider(provider);
8
- return <Provider {...props} />;
11
+ const { gtmEventName: propEventName } = props;
12
+ const gtmEventName = propEventName || process.env.BLAZE_VIDEO_EVENT_NAME;
13
+ const emitEvent = gtmEventName
14
+ ? ({ action, videoId }) =>
15
+ emitGtmEvent({
16
+ gtmEventName,
17
+ provider,
18
+ action,
19
+ videoId,
20
+ playCounter: ref
21
+ })
22
+ : null;
23
+
24
+ return (
25
+ <VideoContextProvider value={{ emitEvent }}>
26
+ <Provider {...props} />
27
+ </VideoContextProvider>
28
+ );
9
29
  };
10
30
 
11
31
  VideoRender.propTypes = {
12
- provider: PropTypes.string.isRequired
32
+ provider: PropTypes.string.isRequired,
33
+ gtmEventName: PropTypes.string
34
+ };
35
+
36
+ VideoRender.defaultProps = {
37
+ gtmEventName: ''
13
38
  };
14
39
 
15
40
  export default withTitle(VideoRender);
@@ -0,0 +1,6 @@
1
+ export const EVENT_ACTIONS = {
2
+ START: 'start',
3
+ PLAYING: 'playing',
4
+ PAUSED: 'paused',
5
+ ENDED: 'ended'
6
+ };
@@ -0,0 +1,25 @@
1
+ import { EVENT_ACTIONS } from '../constants';
2
+
3
+ const emitGtmEvent = ({ gtmEventName, provider, action, videoId, playCounter }) => {
4
+ if (!window.dataLayer || !action) return;
5
+
6
+ const actionToUse =
7
+ action === EVENT_ACTIONS.PLAYING && playCounter.current < 1 ? EVENT_ACTIONS.START : action;
8
+
9
+ if (action === EVENT_ACTIONS.PLAYING) {
10
+ // eslint-disable-next-line no-param-reassign
11
+ playCounter.current += 1;
12
+ }
13
+
14
+ const playCount = playCounter.current;
15
+
16
+ window.dataLayer.push({
17
+ event: gtmEventName,
18
+ video_action: actionToUse,
19
+ video_provider: provider,
20
+ video_id: videoId,
21
+ video_play_count: playCount
22
+ });
23
+ };
24
+
25
+ export default emitGtmEvent;
@@ -2,10 +2,13 @@
2
2
  Custom controller to extend and scale the 'react-jw-player' library for future updates.
3
3
  */
4
4
 
5
+ import { EVENT_ACTIONS } from '../../constants';
6
+
5
7
  class JWPlayerController {
6
- constructor() {
8
+ constructor({ emitEvent }) {
7
9
  this.player = null;
8
10
  this.error = null;
11
+ this.emitEvent = emitEvent;
9
12
  }
10
13
 
11
14
  setPlayer = player => {
@@ -24,11 +27,25 @@ class JWPlayerController {
24
27
  this.error = message;
25
28
  };
26
29
 
27
- onComplete = event => {};
30
+ doEmitEvent = action => {
31
+ const { emitEvent } = this;
32
+ if (emitEvent) {
33
+ const { mediaid: videoId } = this.player.getPlaylistItem();
34
+ emitEvent({ action, videoId });
35
+ }
36
+ };
37
+
38
+ onComplete = event => {
39
+ this.doEmitEvent(EVENT_ACTIONS.ENDED);
40
+ };
28
41
 
29
- onPause = event => {};
42
+ onPause = event => {
43
+ this.doEmitEvent(EVENT_ACTIONS.PAUSED);
44
+ };
30
45
 
31
- onPlay = event => {};
46
+ onPlay = event => {
47
+ this.doEmitEvent(EVENT_ACTIONS.PLAYING);
48
+ };
32
49
 
33
50
  get events() {
34
51
  return {
@@ -1,10 +1,9 @@
1
- import React from 'react';
1
+ import React, { useContext, useRef } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import ReactJWPlayer from 'react-jw-player';
4
4
  import { JW_PLAYER_TYPE_FILE, VIDEO_WRAPPER_CLASS_NAME } from '../../../../constants';
5
5
  import JWPlayerController from './JWPlayerController';
6
-
7
- const PlayerController = new JWPlayerController();
6
+ import { VideoContext } from '../../VideoContext';
8
7
 
9
8
  const JWPlayerProvider = ({
10
9
  url,
@@ -17,15 +16,18 @@ const JWPlayerProvider = ({
17
16
  imageData,
18
17
  loop: repeat
19
18
  }) => {
19
+ const { emitEvent } = useContext(VideoContext);
20
+ const PlayerController = useRef(new JWPlayerController({ emitEvent }));
21
+
20
22
  const handleOnReady = () => {
21
23
  const jwPlayer = window.jwplayer(name);
22
24
  if (jwPlayer) {
23
- PlayerController.setPlayer(jwPlayer);
25
+ PlayerController.current.setPlayer(jwPlayer);
24
26
  }
25
27
  };
26
28
 
27
29
  const getJWPlayerProps = () => {
28
- const { events } = PlayerController;
30
+ const { events } = PlayerController.current;
29
31
 
30
32
  const props = {
31
33
  customProps: { repeat, controls, events },