@blaze-cms/react-page-builder 0.123.0-alpha.7 → 0.123.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.
Files changed (75) hide show
  1. package/CHANGELOG.md +106 -792
  2. package/lib/components/Card/Card.js +20 -6
  3. package/lib/components/Card/Card.js.map +1 -1
  4. package/lib/components/Card/CardContainer.js +20 -4
  5. package/lib/components/Card/CardContainer.js.map +1 -1
  6. package/lib/components/CarouselWrapper.js +12 -5
  7. package/lib/components/CarouselWrapper.js.map +1 -1
  8. package/lib/components/DataSummary/helpers/get-link-based-on-value.js +4 -0
  9. package/lib/components/DataSummary/helpers/get-link-based-on-value.js.map +1 -1
  10. package/lib/components/List/components/Cards/CardsRenderItem.js +23 -4
  11. package/lib/components/List/components/Cards/CardsRenderItem.js.map +1 -1
  12. package/lib/components/Menu/Menu.js +4 -3
  13. package/lib/components/Menu/Menu.js.map +1 -1
  14. package/lib/components/SearchContent/index.js +32 -23
  15. package/lib/components/SearchContent/index.js.map +1 -1
  16. package/lib/components/SearchFilter/SearchFilter/FiltersList.js +16 -11
  17. package/lib/components/SearchFilter/SearchFilter/FiltersList.js.map +1 -1
  18. package/lib/components/SearchFilter/SearchFilter/SearchFilter.js +15 -50
  19. package/lib/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
  20. package/lib/components/SearchFilter/components/Select.js +22 -10
  21. package/lib/components/SearchFilter/components/Select.js.map +1 -1
  22. package/lib/components/index.js +5 -0
  23. package/lib/components/index.js.map +1 -1
  24. package/lib/constants/index.js +5 -2
  25. package/lib/constants/index.js.map +1 -1
  26. package/lib-es/components/Card/Card.js +18 -4
  27. package/lib-es/components/Card/Card.js.map +1 -1
  28. package/lib-es/components/Card/CardContainer.js +21 -5
  29. package/lib-es/components/Card/CardContainer.js.map +1 -1
  30. package/lib-es/components/CarouselWrapper.js +12 -5
  31. package/lib-es/components/CarouselWrapper.js.map +1 -1
  32. package/lib-es/components/DataSummary/helpers/get-link-based-on-value.js +5 -1
  33. package/lib-es/components/DataSummary/helpers/get-link-based-on-value.js.map +1 -1
  34. package/lib-es/components/List/components/Cards/CardsRenderItem.js +23 -4
  35. package/lib-es/components/List/components/Cards/CardsRenderItem.js.map +1 -1
  36. package/lib-es/components/Menu/Menu.js +4 -3
  37. package/lib-es/components/Menu/Menu.js.map +1 -1
  38. package/lib-es/components/SearchContent/index.js +29 -22
  39. package/lib-es/components/SearchContent/index.js.map +1 -1
  40. package/lib-es/components/SearchFilter/SearchFilter/FiltersList.js +20 -16
  41. package/lib-es/components/SearchFilter/SearchFilter/FiltersList.js.map +1 -1
  42. package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js +10 -40
  43. package/lib-es/components/SearchFilter/SearchFilter/SearchFilter.js.map +1 -1
  44. package/lib-es/components/SearchFilter/components/Select.js +22 -6
  45. package/lib-es/components/SearchFilter/components/Select.js.map +1 -1
  46. package/lib-es/components/index.js +4 -1
  47. package/lib-es/components/index.js.map +1 -1
  48. package/lib-es/constants/index.js +3 -1
  49. package/lib-es/constants/index.js.map +1 -1
  50. package/package.json +3 -3
  51. package/src/components/Card/Card.js +28 -3
  52. package/src/components/Card/CardContainer.js +18 -2
  53. package/src/components/CarouselWrapper.js +8 -5
  54. package/src/components/DataSummary/helpers/get-link-based-on-value.js +9 -1
  55. package/src/components/List/components/Cards/CardsRenderItem.js +22 -3
  56. package/src/components/Menu/Menu.js +4 -3
  57. package/src/components/SearchContent/index.js +27 -18
  58. package/src/components/SearchFilter/SearchFilter/FiltersList.js +5 -2
  59. package/src/components/SearchFilter/SearchFilter/SearchFilter.js +113 -148
  60. package/src/components/SearchFilter/components/Select.js +29 -6
  61. package/src/components/index.js +2 -1
  62. package/src/constants/index.js +3 -1
  63. package/tests/unit/src/components/Card/__snapshots__/Card.test.js.snap +10 -10
  64. package/tests/unit/src/components/Card/__snapshots__/CardContainer.test.js.snap +8 -8
  65. package/tests/unit/src/components/Card/__snapshots__/CardRender.test.js.snap +2 -2
  66. package/tests/unit/src/components/Card/mockData.js +2 -0
  67. package/tests/unit/src/components/DataSummary/helpers/get-link-based-on-value.test.js +29 -0
  68. package/tests/unit/src/components/List/components/Cards/__snapshots__/CardsRender.test.js.snap +12 -12
  69. package/tests/unit/src/components/Menu/Menu.test.js +3 -1
  70. package/tests/unit/src/components/Menu/__snapshots__/Menu.test.js.snap +3 -0
  71. package/tests/unit/src/components/SearchFilter/SearchFilter/SearchFilter.test.js +64 -86
  72. package/tests/unit/src/components/SearchFilter/SearchFilter/__snapshots__/SearchFilter.test.js.snap +133 -61
  73. package/tests/unit/src/components/SearchFilter/components/Select.test.js +58 -4
  74. package/tests/unit/src/components/SearchFilter/components/__snapshots__/Select.test.js.snap +28 -5
  75. package/tests/unit/src/components/__snapshots__/index.test.js.snap +4 -0
@@ -7,6 +7,7 @@ import BlazeLink from '../BlazeLink';
7
7
 
8
8
  const SearchContent = ({
9
9
  entity,
10
+ searchInputAlignment,
10
11
  searchInputWrapperMobile,
11
12
  searchInputWrapperDesktop,
12
13
  isMobile
@@ -49,20 +50,26 @@ const SearchContent = ({
49
50
  });
50
51
 
51
52
  if (loading) return null;
52
- if (error) return `Error! ${error}`;
53
+ if (error) return null;
53
54
 
54
55
  const handleClick = (e, url) => {
55
56
  e.preventDefault();
56
57
  router.push(url);
57
58
  };
58
59
 
60
+ const handleKeyPress = e => {
61
+ if (e.key === 'Enter' && e.target.value !== '') {
62
+ router.push(`/search?search_term=${e.target.value}`);
63
+ }
64
+ };
65
+
59
66
  const renderResults = () => {
60
67
  // eslint-disable-next-line no-undef
61
68
  const { results } = data?.searchPublishedContent;
62
69
 
63
70
  if (results && searchTerm && searchTerm !== '') {
64
71
  return results.map(({ name, url }) => {
65
- if (name.match(searchTerm)) {
72
+ if (name.includes(searchTerm)) {
66
73
  return (
67
74
  <BlazeLink href={url} onClick={e => handleClick(e, url)}>
68
75
  {name}
@@ -81,10 +88,10 @@ const SearchContent = ({
81
88
 
82
89
  return collapsed ? (
83
90
  <div className={isMobile ? searchInputWrapperMobile : searchInputWrapperDesktop}>
84
- <div className="w-11 mx-auto">
85
- <label className="relative block">
86
- <span className="absolute inset-y-0 right-3 flex items-center pl-2 cursor-pointer">
87
- <svg className="h-5 w-5 fill-slate-300" viewBox="0 0 20 20">
91
+ <div className="search-content--collapse__wrapper">
92
+ <label className="search-content--collapse__label">
93
+ <span className="search-content--collapse__icon_wrapper">
94
+ <svg className="search-content--collapse__icon" viewBox="0 0 20 20">
88
95
  <path
89
96
  fillRule="evenodd"
90
97
  d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
@@ -92,14 +99,13 @@ const SearchContent = ({
92
99
  />
93
100
  </svg>
94
101
  </span>
95
- <span className="sr-only">Search</span>
96
102
  <input
97
103
  onFocus={() => setCollapsed(false)}
98
104
  onChange={e => setSearchTerm(e.target.value)}
99
105
  type="text"
100
106
  name="search"
101
107
  value=""
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"
108
+ className="search-content--collapse__input"
103
109
  />
104
110
  </label>
105
111
  </div>
@@ -107,10 +113,10 @@ const SearchContent = ({
107
113
  ) : (
108
114
  <>
109
115
  <div className={`${isMobile ? searchInputWrapperMobile : searchInputWrapperDesktop}`}>
110
- <div className="w-96 mx-auto rounded-3xl">
111
- <label className="relative block">
112
- <span className="absolute inset-y-0 right-3 flex items-center pl-2">
113
- <svg className="h-5 w-5 fill-slate-300" viewBox="0 0 20 20">
116
+ <div className="search-content--expanded__wrapper">
117
+ <label className="search-content--expanded__label">
118
+ <span className="search-content--expanded__icon_wrapper">
119
+ <svg className="search-content--expanded__icon" viewBox="0 0 20 20">
114
120
  <path
115
121
  fillRule="evenodd"
116
122
  d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z"
@@ -118,12 +124,12 @@ const SearchContent = ({
118
124
  />
119
125
  </svg>
120
126
  </span>
121
- <span className="sr-only">Search</span>
122
127
  <input
123
128
  type="text"
124
129
  name="search"
125
130
  onChange={e => setSearchTerm(e.target.value)}
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"
131
+ onKeyPress={handleKeyPress}
132
+ className="search-content--expanded__input"
127
133
  placeholder="Search for anything..."
128
134
  onBlur={() => {
129
135
  if (!searchTerm || searchTerm === '') setCollapsed(true);
@@ -133,11 +139,13 @@ const SearchContent = ({
133
139
  </div>
134
140
  {data &&
135
141
  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>
142
+ <div className="search-content--results__wrapper">
143
+ <div className="search-content--results__wrapper--message">
144
+ <div className="text-sm pt-2">{searchResultsMessage}</div>
138
145
 
139
- <div className="text-left px-4 py-2">
140
- <div className="text-bold">{renderResults()}</div>
146
+ <div className="search-content--results__message">
147
+ <div className="search-content--results__content">{renderResults()}</div>
148
+ </div>
141
149
  </div>
142
150
  </div>
143
151
  )}
@@ -147,6 +155,7 @@ const SearchContent = ({
147
155
  };
148
156
 
149
157
  SearchContent.propTypes = {
158
+ searchInputAlignment: PropTypes.string,
150
159
  searchInputWrapperMobile: PropTypes.string,
151
160
  searchInputWrapperDesktop: PropTypes.string,
152
161
  isMobile: PropTypes.bool,
@@ -15,7 +15,7 @@ const FiltersList = ({
15
15
  }) => {
16
16
  const { itemId } = useContext(MainContext);
17
17
 
18
- return filters.map(({ type, label, propsToDisplay, rangeInterval, elementTitle }, index) => {
18
+ return filters.map(({ type, label, propsToDisplay, elementTitle, ...otherProps }, index) => {
19
19
  if (!propsToDisplay && !propsToDisplay.length) return null;
20
20
 
21
21
  const dynamicKey = [itemId, index].join('-');
@@ -32,6 +32,7 @@ const FiltersList = ({
32
32
  key={dynamicKey}
33
33
  className="filter__section filter__section--search-refine filter__section--search">
34
34
  <TextSearch
35
+ {...otherProps}
35
36
  label={label}
36
37
  elementTitle={elementTitle}
37
38
  searchValue={filterValues[SEARCH_TERM]}
@@ -47,6 +48,7 @@ const FiltersList = ({
47
48
  key={dynamicKey}
48
49
  className="filter__section filter__section--search-refine filter__section--checkboxes">
49
50
  <Checkbox
51
+ {...otherProps}
50
52
  data={data}
51
53
  prop={propsToDisplay[0]}
52
54
  label={label}
@@ -66,6 +68,7 @@ const FiltersList = ({
66
68
  key={dynamicKey}
67
69
  className="filter__section filter__section--search-refine filter__section--selects">
68
70
  <SelectFilter
71
+ {...otherProps}
69
72
  data={data}
70
73
  prop={propsToDisplay[0]}
71
74
  label={label}
@@ -83,9 +86,9 @@ const FiltersList = ({
83
86
  !!areAggregationsAvailable && (
84
87
  <div key={dynamicKey} className="range-slider__wrapper">
85
88
  <Range
89
+ {...otherProps}
86
90
  dataAggregations={dataAggregations}
87
91
  propsToDisplay={propsToDisplay}
88
- rangeInterval={rangeInterval}
89
92
  label={label}
90
93
  elementTitle={elementTitle}
91
94
  entity={entity}
@@ -44,8 +44,6 @@ const SearchFilter = ({
44
44
  groupAfterDesktop,
45
45
  groupAfterMobile
46
46
  }) => {
47
- const [isDesktop, setIsDesktop] = useState(true);
48
- const [pageWidth, setPageWidth] = useState(null);
49
47
  const [moreFiltersMobileCollapsed, setMoreFiltersMobileCollapsed] = useState(true);
50
48
  const [moreFiltersDesktopCollapsed, setMoreFiltersDesktopCollapsed] = useState(true);
51
49
  const [filterValues, dispatch] = useReducer(reducer, initialFilterValues);
@@ -55,27 +53,6 @@ const SearchFilter = ({
55
53
  handleSearch(newQuery);
56
54
  }, 200);
57
55
 
58
- useEffect(
59
- () => {
60
- if (window && !pageWidth) {
61
- setPageWidth(window.innerWidth);
62
- setIsDesktop(isDeviceDesktop());
63
- }
64
-
65
- const handleResize = ({ target: { innerWidth } }) => {
66
- setIsDesktop(isDeviceDesktop());
67
- setPageWidth(innerWidth);
68
- if (isDesktop) setDisplaySearchFilter(false);
69
- };
70
-
71
- window.addEventListener('resize', handleResize);
72
- return () => {
73
- window.removeEventListener('resize', handleResize);
74
- };
75
- },
76
- [isDesktop, pageWidth, setDisplaySearchFilter]
77
- );
78
-
79
56
  useEffect(
80
57
  () => {
81
58
  if (filterValues.shouldSearch) {
@@ -86,16 +63,9 @@ const SearchFilter = ({
86
63
  [filterValues, handleSubmit]
87
64
  );
88
65
 
89
- let isDesktopFormDisplayed = true;
90
- let isMobileFormDisplayed = false;
91
-
92
- if (!isDesktop && isCollapsedOnResponsive) {
93
- isMobileFormDisplayed = displaySearchFilter;
94
- isDesktopFormDisplayed = false;
95
- }
96
-
97
- const formClass = classnames({
98
- 'filter__form filter__form--mobile': isMobileFormDisplayed
66
+ const formClass = classnames('filter__form filter__form--initial', {
67
+ 'filter__form--mobile': isCollapsedOnResponsive && displaySearchFilter,
68
+ 'filter__form--collapsible': isCollapsedOnResponsive
99
69
  });
100
70
 
101
71
  const {
@@ -122,143 +92,138 @@ const SearchFilter = ({
122
92
 
123
93
  return (
124
94
  <>
125
- {isDesktopFormDisplayed || isMobileFormDisplayed ? (
126
- <form
127
- ref={searchFilterRef}
128
- className={formClass}
129
- data-testid={formId}
130
- id={formId}
131
- onSubmit={e => {
132
- e.preventDefault();
133
- const newQuery = buildQuery(filterValues, filters);
134
- handleSearch(newQuery);
135
- }}>
136
- {isMobileFormDisplayed && (
137
- <CloseMobileForm handleClose={() => setDisplaySearchFilter(false)} />
138
- )}
139
-
140
- <div className="filter filter--search-refine">
141
- {isDesktopFormDisplayed && <ResetDesktopForm handleReset={handleReset} />}
142
-
143
- <div className="filter__wrapper filter__wrapper--search-refine">
144
- {!shouldGroup && (
95
+ <form
96
+ ref={searchFilterRef}
97
+ className={formClass}
98
+ data-testid={formId}
99
+ id={formId}
100
+ onSubmit={e => {
101
+ e.preventDefault();
102
+ const newQuery = buildQuery(filterValues, filters);
103
+ handleSearch(newQuery);
104
+ }}>
105
+ {displaySearchFilter && (
106
+ <CloseMobileForm handleClose={() => setDisplaySearchFilter(false)} />
107
+ )}
108
+
109
+ <div className="filter filter--search-refine">
110
+ <ResetDesktopForm handleReset={handleReset} />
111
+
112
+ <div className="filter__wrapper filter__wrapper--search-refine">
113
+ {!shouldGroup && (
114
+ <FiltersList
115
+ shouldSearch={shouldSearch}
116
+ data={data}
117
+ filters={filters}
118
+ hasUrl={hasUrl}
119
+ entity={entity}
120
+ filterValues={filterValues}
121
+ updateFilterValues={updateFilterValues}
122
+ />
123
+ )}
124
+
125
+ {shouldGroup && (
126
+ <>
145
127
  <FiltersList
146
128
  shouldSearch={shouldSearch}
147
129
  data={data}
148
- filters={filters}
130
+ filters={filters.slice(0, groupAfterMobile)}
149
131
  hasUrl={hasUrl}
150
132
  entity={entity}
151
133
  filterValues={filterValues}
152
134
  updateFilterValues={updateFilterValues}
153
135
  />
154
- )}
155
-
156
- {shouldGroup && (
157
- <>
158
- <FiltersList
159
- shouldSearch={shouldSearch}
160
- data={data}
161
- filters={filters.slice(0, groupAfterMobile)}
162
- hasUrl={hasUrl}
163
- entity={entity}
164
- filterValues={filterValues}
165
- updateFilterValues={updateFilterValues}
166
- />
167
136
 
168
- {!!groupAfterMobile && (
169
- <button
170
- className={moreFiltersMobileTogglerClass}
171
- type="button"
172
- onClick={() => setMoreFiltersMobileCollapsed(!moreFiltersMobileCollapsed)}>
173
- Filters
174
- </button>
175
- )}
176
-
177
- <div className={moreFiltersMobileWrapperClass}>
178
- <div className={MORE_FILTERS_CLASSES.MOBILE_CONTENT}>
179
- <FiltersList
180
- shouldSearch={shouldSearch && isDeviceDesktop()}
181
- data={data}
182
- filters={filters.slice(
183
- groupAfterMobile,
184
- groupAfterDesktop ? groupAfterDesktop - 1 : 0
185
- )}
186
- hasUrl={hasUrl}
187
- entity={entity}
188
- filterValues={filterValues}
189
- updateFilterValues={updateFilterValues}
190
- />
191
-
192
- {!!groupAfterDesktop && (
193
- <button
194
- className={moreFiltersDesktopTogglerClass}
195
- type="button"
196
- onClick={() =>
197
- setMoreFiltersDesktopCollapsed(!moreFiltersDesktopCollapsed)
198
- }>
199
- More filters
200
- </button>
137
+ {!!groupAfterMobile && (
138
+ <button
139
+ className={moreFiltersMobileTogglerClass}
140
+ type="button"
141
+ onClick={() => setMoreFiltersMobileCollapsed(!moreFiltersMobileCollapsed)}>
142
+ Filters
143
+ </button>
144
+ )}
145
+
146
+ <div className={moreFiltersMobileWrapperClass}>
147
+ <div className={MORE_FILTERS_CLASSES.MOBILE_CONTENT}>
148
+ <FiltersList
149
+ shouldSearch={shouldSearch && isDeviceDesktop()}
150
+ data={data}
151
+ filters={filters.slice(
152
+ groupAfterMobile,
153
+ groupAfterDesktop ? groupAfterDesktop - 1 : 0
201
154
  )}
155
+ hasUrl={hasUrl}
156
+ entity={entity}
157
+ filterValues={filterValues}
158
+ updateFilterValues={updateFilterValues}
159
+ />
160
+
161
+ {!!groupAfterDesktop && (
162
+ <button
163
+ className={moreFiltersDesktopTogglerClass}
164
+ type="button"
165
+ onClick={() =>
166
+ setMoreFiltersDesktopCollapsed(!moreFiltersDesktopCollapsed)
167
+ }>
168
+ More filters
169
+ </button>
170
+ )}
171
+
172
+ <div className={moreFiltersDesktopWrapperClass}>
173
+ <div className={MORE_FILTERS_CLASSES.DESKTOP_CONTENT}>
174
+ <FiltersList
175
+ shouldSearch={false}
176
+ data={data}
177
+ filters={filters.slice(groupAfterDesktop)}
178
+ hasUrl={hasUrl}
179
+ entity={entity}
180
+ filterValues={filterValues}
181
+ updateFilterValues={updateFilterValues}
182
+ />
183
+ </div>
202
184
 
203
- <div className={moreFiltersDesktopWrapperClass}>
204
- <div className={MORE_FILTERS_CLASSES.DESKTOP_CONTENT}>
205
- <FiltersList
206
- shouldSearch={false}
207
- data={data}
208
- filters={filters.slice(groupAfterDesktop)}
209
- hasUrl={hasUrl}
210
- entity={entity}
211
- filterValues={filterValues}
212
- updateFilterValues={updateFilterValues}
213
- />
214
- </div>
215
-
216
- <div className={MORE_FILTERS_CLASSES.DESKTOP_BUTTONS}>
217
- <ResetDesktopForm handleReset={handleReset} />
185
+ <div className={MORE_FILTERS_CLASSES.DESKTOP_BUTTONS}>
186
+ <ResetDesktopForm handleReset={handleReset} />
218
187
 
219
- <button className="button button--full-width" type="submit">
220
- {SEARCH}
221
- </button>
222
- </div>
188
+ <button className="button button--full-width" type="submit">
189
+ {SEARCH}
190
+ </button>
223
191
  </div>
224
192
  </div>
193
+ </div>
225
194
 
226
- <div className={MORE_FILTERS_CLASSES.MOBILE_BUTTONS}>
227
- <ResetDesktopForm handleReset={handleReset} />
195
+ <div className={MORE_FILTERS_CLASSES.MOBILE_BUTTONS}>
196
+ <ResetDesktopForm handleReset={handleReset} />
228
197
 
229
- <button className="button button--full-width" type="submit">
230
- {SEARCH}
231
- </button>
232
- </div>
198
+ <button className="button button--full-width" type="submit">
199
+ {SEARCH}
200
+ </button>
233
201
  </div>
234
- </>
235
- )}
202
+ </div>
203
+ </>
204
+ )}
236
205
 
237
- <br />
206
+ <br />
238
207
 
239
- {isDesktopFormDisplayed && (
240
- <button className="button button--full-width" type="submit">
241
- {SEARCH}
242
- </button>
243
- )}
244
- </div>
208
+ {!displaySearchFilter && (
209
+ <button className="button button--full-width" type="submit">
210
+ {SEARCH}
211
+ </button>
212
+ )}
245
213
  </div>
214
+ </div>
215
+
216
+ {displaySearchFilter && <MobileFormToolbar formId={formId} handleReset={handleReset} />}
217
+ </form>
246
218
 
247
- {isMobileFormDisplayed && <MobileFormToolbar formId={formId} handleReset={handleReset} />}
248
- </form>
249
- ) : (
250
- <>
251
- {isCollapsedOnResponsive && (
252
- <div
253
- className="filter__refine filter__refine--mobile-close"
254
- data-testid="refine-mobile">
255
- <div role="button" onClick={() => setDisplaySearchFilter(true)}>
256
- {REFINE}
257
- </div>
219
+ {isCollapsedOnResponsive &&
220
+ !displaySearchFilter && (
221
+ <div className="filter__refine filter__refine--mobile-close" data-testid="refine-mobile">
222
+ <div role="button" onClick={() => setDisplaySearchFilter(true)}>
223
+ {REFINE}
258
224
  </div>
259
- )}
260
- </>
261
- )}
225
+ </div>
226
+ )}
262
227
  </>
263
228
  );
264
229
  };
@@ -4,7 +4,15 @@ import Select from '@blaze-react/select';
4
4
  import { withTitle } from '../../../HOC';
5
5
  import { DEFAULT_OPTION } from '../constants';
6
6
 
7
- const SelectFilter = ({ data, label, prop, updateFilterValues, filterValues, shouldSearch }) => {
7
+ const SelectFilter = ({
8
+ data,
9
+ label,
10
+ prop,
11
+ updateFilterValues,
12
+ filterValues,
13
+ shouldSearch,
14
+ displayLabelAsPlaceholder
15
+ }) => {
8
16
  const filterValue = filterValues[prop] || '';
9
17
 
10
18
  const options = data[prop].buckets
@@ -12,16 +20,29 @@ const SelectFilter = ({ data, label, prop, updateFilterValues, filterValues, sho
12
20
  .filter(Boolean)
13
21
  .sort();
14
22
 
15
- const optionsJoined = [DEFAULT_OPTION, ...options];
23
+ const optionsJoined = options;
24
+
25
+ const labelText = label || prop;
26
+ let labelToUse = labelText;
27
+ let defaultTextValue = DEFAULT_OPTION;
28
+ if (displayLabelAsPlaceholder) {
29
+ defaultTextValue = labelToUse;
30
+ labelToUse = null;
31
+ }
16
32
 
17
33
  return (
18
34
  <Select
19
- label={`${label || prop}`}
35
+ label={labelToUse}
20
36
  value={filterValue}
21
37
  id={prop}
38
+ data-testid={`filter-${prop}`}
22
39
  options={optionsJoined}
40
+ defaultTextValue={defaultTextValue}
23
41
  onChange={({ value }) => {
24
- updateFilterValues({ [prop]: value }, shouldSearch);
42
+ let valueToUse = value;
43
+ if (value === defaultTextValue) valueToUse = '';
44
+
45
+ updateFilterValues({ [prop]: valueToUse }, shouldSearch);
25
46
  }}
26
47
  />
27
48
  );
@@ -33,12 +54,14 @@ SelectFilter.propTypes = {
33
54
  filterValues: PropTypes.object.isRequired,
34
55
  updateFilterValues: PropTypes.func.isRequired,
35
56
  shouldSearch: PropTypes.bool,
36
- label: PropTypes.string
57
+ label: PropTypes.string,
58
+ displayLabelAsPlaceholder: PropTypes.bool
37
59
  };
38
60
 
39
61
  SelectFilter.defaultProps = {
40
62
  shouldSearch: false,
41
- label: ''
63
+ label: '',
64
+ displayLabelAsPlaceholder: false
42
65
  };
43
66
 
44
67
  export default withTitle(SelectFilter);
@@ -40,5 +40,6 @@ export default {
40
40
  ),
41
41
  passwordresetrequest: dynamic(() =>
42
42
  import(/* webpackChunkName: "blazePbPasswordResetRequest" */ './PasswordResetRequest')
43
- )
43
+ ),
44
+ breadcrumb: dynamic(() => import(/* webpackChunkName: "blazePbBreadcrumb" */ './Breadcrumb'))
44
45
  };
@@ -207,6 +207,7 @@ const TARGET_BLANK = '_blank';
207
207
 
208
208
  const DATA_SUMMARY_EMAIL_REGEX = /^([a-z0-9_\.\+-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})$/;
209
209
  const DATA_SUMMARY_URL_REGEX = /(https?:\/\/)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/;
210
+ const DATA_SUMMARY_TEL_REGEX = /^\+{0,1}[0-9\(\)\.\- \/]{7,}$/; // note: very loose phone number match not for validation
210
211
 
211
212
  export {
212
213
  BANNER_LOADING,
@@ -318,5 +319,6 @@ export {
318
319
  ANCHOR_TAG,
319
320
  TARGET_BLANK,
320
321
  DATA_SUMMARY_EMAIL_REGEX,
321
- DATA_SUMMARY_URL_REGEX
322
+ DATA_SUMMARY_URL_REGEX,
323
+ DATA_SUMMARY_TEL_REGEX
322
324
  };
@@ -19,7 +19,7 @@ exports[`Card component should not render alternative headline if alternativePre
19
19
  </a>
20
20
  </div>
21
21
  <div
22
- class="card__content-wrapper card__content-wrapper--portrait"
22
+ class="card__content-wrapper card__content-wrapper--portrait "
23
23
  >
24
24
  <div
25
25
  class="card__content card__content--portrait"
@@ -31,7 +31,7 @@ exports[`Card component should not render alternative headline if alternativePre
31
31
  category-name
32
32
  </a>
33
33
  <h2
34
- class="card__title card__title--portrait"
34
+ class="card__title card__title--portrait "
35
35
  >
36
36
  <a
37
37
  href="/mockurl"
@@ -93,13 +93,13 @@ exports[`Card component should not render alternative headline if displayCategor
93
93
  </a>
94
94
  </div>
95
95
  <div
96
- class="card__content-wrapper card__content-wrapper--portrait"
96
+ class="card__content-wrapper card__content-wrapper--portrait "
97
97
  >
98
98
  <div
99
99
  class="card__content card__content--portrait"
100
100
  >
101
101
  <h2
102
- class="card__title card__title--portrait"
102
+ class="card__title card__title--portrait "
103
103
  >
104
104
  <a
105
105
  href="/mockurl"
@@ -161,7 +161,7 @@ exports[`Card component should not render preHeader if alternativeHeadline is no
161
161
  </a>
162
162
  </div>
163
163
  <div
164
- class="card__content-wrapper card__content-wrapper--portrait"
164
+ class="card__content-wrapper card__content-wrapper--portrait "
165
165
  >
166
166
  <div
167
167
  class="card__content card__content--portrait"
@@ -173,7 +173,7 @@ exports[`Card component should not render preHeader if alternativeHeadline is no
173
173
  category-name
174
174
  </a>
175
175
  <h2
176
- class="card__title card__title--portrait"
176
+ class="card__title card__title--portrait "
177
177
  >
178
178
  <a
179
179
  href="/mockurl"
@@ -235,7 +235,7 @@ exports[`Card component should render customPreheader and alternativeHeadline in
235
235
  </a>
236
236
  </div>
237
237
  <div
238
- class="card__content-wrapper card__content-wrapper--portrait"
238
+ class="card__content-wrapper card__content-wrapper--portrait "
239
239
  >
240
240
  <div
241
241
  class="card__content card__content--portrait"
@@ -246,7 +246,7 @@ exports[`Card component should render customPreheader and alternativeHeadline in
246
246
  Pre header
247
247
  </div>
248
248
  <h2
249
- class="card__title card__title--portrait"
249
+ class="card__title card__title--portrait "
250
250
  >
251
251
  <a
252
252
  href="/mockurl"
@@ -308,7 +308,7 @@ exports[`Card component should render without throwing an error and match snapsh
308
308
  </a>
309
309
  </div>
310
310
  <div
311
- class="card__content-wrapper card__content-wrapper--portrait"
311
+ class="card__content-wrapper card__content-wrapper--portrait "
312
312
  >
313
313
  <div
314
314
  class="card__content card__content--portrait"
@@ -320,7 +320,7 @@ exports[`Card component should render without throwing an error and match snapsh
320
320
  category-name
321
321
  </a>
322
322
  <h2
323
- class="card__title card__title--portrait"
323
+ class="card__title card__title--portrait "
324
324
  >
325
325
  <a
326
326
  href="/mockurl"