@eeacms/volto-marine-policy 0.1.20

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 (150) hide show
  1. package/.coverage.babel.config.js +9 -0
  2. package/.eslintrc.js +65 -0
  3. package/.husky/pre-commit +2 -0
  4. package/.release-it.json +17 -0
  5. package/CHANGELOG.md +5 -0
  6. package/DEVELOP.md +53 -0
  7. package/LICENSE.md +9 -0
  8. package/README.md +172 -0
  9. package/RELEASE.md +74 -0
  10. package/babel.config.js +17 -0
  11. package/bootstrap +41 -0
  12. package/cypress.config.js +24 -0
  13. package/docker-compose.yml +32 -0
  14. package/jest-addon.config.js +50 -0
  15. package/jest.setup.js +65 -0
  16. package/locales/de/LC_MESSAGES/volto.po +14 -0
  17. package/locales/en/LC_MESSAGES/volto.po +14 -0
  18. package/locales/it/LC_MESSAGES/volto.po +14 -0
  19. package/locales/ro/LC_MESSAGES/volto.po +14 -0
  20. package/locales/volto.pot +16 -0
  21. package/package.json +69 -0
  22. package/razzle.extend.js +29 -0
  23. package/src/components/Blocks/CustomBlockTemplates/customBlockTemplates.js +25 -0
  24. package/src/components/Blocks/MsfdDataExplorerBlock/Edit.jsx +29 -0
  25. package/src/components/Blocks/MsfdDataExplorerBlock/View.jsx +105 -0
  26. package/src/components/Blocks/MsfdDataExplorerBlock/index.js +23 -0
  27. package/src/components/Blocks/MsfdDataExplorerBlock/schema.jsx +30 -0
  28. package/src/components/Result/MarineMeasureItem.jsx +83 -0
  29. package/src/components/Widgets/MeasureViewWidget.jsx +233 -0
  30. package/src/components/Widgets/String.jsx +15 -0
  31. package/src/components/Widgets/TextAlign.jsx +41 -0
  32. package/src/components/Widgets/measure.css +101 -0
  33. package/src/components/index.js +15 -0
  34. package/src/components/theme/AppExtras/PrintPage/PrintPage.jsx +61 -0
  35. package/src/components/theme/AppExtras/PrintPage/css/printpage.less +29 -0
  36. package/src/components/theme/AppExtras/PrintPage/index.js +3 -0
  37. package/src/components/theme/AppExtras/ScrollToTop/ScrollToTop.jsx +61 -0
  38. package/src/components/theme/AppExtras/ScrollToTop/css/scrolltop.less +19 -0
  39. package/src/components/theme/AppExtras/ScrollToTop/index.js +3 -0
  40. package/src/components/theme/AppExtras/index.js +18 -0
  41. package/src/components/theme/DatabaseItemView/DatabaseItemView.jsx +39 -0
  42. package/src/components/theme/DatabaseItemView/style.less +87 -0
  43. package/src/components/theme/Header/HeroSection.jsx +45 -0
  44. package/src/components/theme/Header/StickyHeader.jsx +51 -0
  45. package/src/components/theme/Header/less/globals.less +18 -0
  46. package/src/components/theme/Header/less/herosection.less +64 -0
  47. package/src/components/theme/Header/less/herosection.variables +18 -0
  48. package/src/components/theme/ItemMetadata/ItemMetadata.jsx +217 -0
  49. package/src/components/theme/ItemMetadata/ItemMetadataSnippet.jsx +69 -0
  50. package/src/components/theme/ItemMetadata/ItemTitle.jsx +29 -0
  51. package/src/components/theme/MetadataListingView/MapPreview.jsx +105 -0
  52. package/src/components/theme/MetadataListingView/MetadataHeader.jsx +66 -0
  53. package/src/components/theme/MetadataListingView/MetadataListingView.jsx +36 -0
  54. package/src/components/theme/MetadataListingView/style.less +219 -0
  55. package/src/components/theme/SimpleListingView/SimpleListingView.jsx +97 -0
  56. package/src/components/theme/SimpleListingView/style.less +33 -0
  57. package/src/components/theme/Tableau/TableauDownload.jsx +86 -0
  58. package/src/components/theme/Tableau/TableauFullscreen.jsx +78 -0
  59. package/src/components/theme/Tableau/TableauShare.jsx +128 -0
  60. package/src/components/theme/View/FullwidthView.jsx +102 -0
  61. package/src/components/theme/View/HeroSectionView.jsx +125 -0
  62. package/src/constants/ActionTypes.js +12 -0
  63. package/src/constants/measureFields.js +56 -0
  64. package/src/customizations/@eeacms/volto-block-style/StyleWrapper/schema.js +217 -0
  65. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/Header.jsx +358 -0
  66. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderMenuPopUp.js +403 -0
  67. package/src/customizations/@eeacms/volto-eea-design-system/ui/Header/HeaderSearchPopUp.js +131 -0
  68. package/src/customizations/@eeacms/volto-eea-design-system/ui/Logo/Logo.jsx +32 -0
  69. package/src/customizations/@eeacms/volto-eea-design-system/ui/Logo/marine_logo.svg +63 -0
  70. package/src/customizations/volto/components/manage/Contents/ContentsBreadcrumbs.jsx +81 -0
  71. package/src/customizations/volto/components/manage/Contents/README.md +1 -0
  72. package/src/customizations/volto/components/manage/Toolbar/PersonalTools.jsx +205 -0
  73. package/src/customizations/volto/components/manage/Toolbar/Toolbar.jsx +624 -0
  74. package/src/customizations/volto/components/theme/Breadcrumbs/Breadcrumbs.jsx +49 -0
  75. package/src/customizations/volto/components/theme/Breadcrumbs/README.md +1 -0
  76. package/src/customizations/volto/components/theme/Header/Header.jsx +272 -0
  77. package/src/helpers/index.js +2 -0
  78. package/src/helpers/useCopyToClipboard.js +25 -0
  79. package/src/helpers/useOutsideClick.js +20 -0
  80. package/src/icons/arrow.svg +3 -0
  81. package/src/icons/basket.svg +3 -0
  82. package/src/icons/newspaper.svg +3 -0
  83. package/src/icons/popup.svg +3 -0
  84. package/src/icons/search.svg +3 -0
  85. package/src/icons/star-full.svg +3 -0
  86. package/src/icons/user.svg +3 -0
  87. package/src/index.js +467 -0
  88. package/src/reducers/breadcrumb/breadcrumb.js +59 -0
  89. package/src/reducers/index.js +2 -0
  90. package/src/reducers/localnavigation/localnavigation.js +69 -0
  91. package/src/search/config.js +93 -0
  92. package/src/search/facets.js +85 -0
  93. package/src/search/index.js +48 -0
  94. package/src/search/views.js +15 -0
  95. package/src/slate-styles.less +43 -0
  96. package/src/static/bise_logo.svg +1 -0
  97. package/src/static/cca_logo.svg +20 -0
  98. package/src/static/ec_logo.svg +343 -0
  99. package/src/static/ec_logo_white.svg +10 -0
  100. package/src/static/eea_logo.svg +14 -0
  101. package/src/static/footer-fishes.svg +21 -0
  102. package/src/static/forest_logo.svg +30 -0
  103. package/src/static/freshwater_logo.svg +12 -0
  104. package/src/static/marine_logo.svg +63 -0
  105. package/src/static/marine_logo_white.svg +44 -0
  106. package/src/utils.js +38 -0
  107. package/theme/assets/fonts/Poppins/Poppins-Bold.ttf +0 -0
  108. package/theme/assets/fonts/Poppins/Poppins-Bold.woff +0 -0
  109. package/theme/assets/fonts/Poppins/Poppins-Bold.woff2 +0 -0
  110. package/theme/assets/fonts/Poppins/Poppins-ExtraBold.ttf +0 -0
  111. package/theme/assets/fonts/Poppins/Poppins-Light.ttf +0 -0
  112. package/theme/assets/fonts/Poppins/Poppins-Light.woff +0 -0
  113. package/theme/assets/fonts/Poppins/Poppins-Light.woff2 +0 -0
  114. package/theme/assets/fonts/Poppins/Poppins-Regular.ttf +0 -0
  115. package/theme/assets/fonts/Poppins/Poppins-Regular.woff +0 -0
  116. package/theme/assets/fonts/Poppins/Poppins-Regular.woff2 +0 -0
  117. package/theme/assets/fonts/Poppins/Poppins-SemiBold.ttf +0 -0
  118. package/theme/assets/fonts/Poppins/Poppins-SemiBold.woff +0 -0
  119. package/theme/assets/fonts/Poppins/Poppins-SemiBold.woff2 +0 -0
  120. package/theme/assets/fonts/Roboto/Roboto-Light.ttf +0 -0
  121. package/theme/assets/fonts/Roboto/Roboto-Light.woff +0 -0
  122. package/theme/assets/fonts/Roboto/Roboto-Light.woff2 +0 -0
  123. package/theme/assets/fonts/Roboto/Roboto-Medium.ttf +0 -0
  124. package/theme/assets/fonts/Roboto/Roboto-Medium.woff +0 -0
  125. package/theme/assets/fonts/Roboto/Roboto-Medium.woff2 +0 -0
  126. package/theme/assets/fonts/Roboto/Roboto-Regular.ttf +0 -0
  127. package/theme/assets/fonts/Roboto/Roboto-Regular.woff +0 -0
  128. package/theme/assets/fonts/Roboto/Roboto-Regular.woff2 +0 -0
  129. package/theme/assets/images/Footer/ec_logo.svg +10 -0
  130. package/theme/assets/images/Header/climate-adapt-logo-1.svg +20 -0
  131. package/theme/assets/images/Header/climate-adapt-logo.svg +22 -0
  132. package/theme/assets/images/Header/wise-marine-logo-white.svg +143 -0
  133. package/theme/assets/images/Header/wise-marine-logo.svg +143 -0
  134. package/theme/assets/images/spinner.svg +1 -0
  135. package/theme/collections/table.variables +17 -0
  136. package/theme/elements/button.overrides +22 -0
  137. package/theme/extras/banner.variables +5 -0
  138. package/theme/extras/contextNavigation.overrides +60 -0
  139. package/theme/extras/contextNavigation.variables +32 -0
  140. package/theme/extras/footer.variables +6 -0
  141. package/theme/extras/header.overrides +20 -0
  142. package/theme/extras/header.variables +7 -0
  143. package/theme/extras/hero.overrides +4 -0
  144. package/theme/extras/inpageNavigation.variables +5 -0
  145. package/theme/extras/mixins.less +8 -0
  146. package/theme/globals/site.overrides +349 -0
  147. package/theme/globals/site.variables +997 -0
  148. package/theme/theme.config +136 -0
  149. package/theme/tokens/colors.less +9 -0
  150. package/theme/tokens/tokens.less +1 -0
@@ -0,0 +1,403 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import {
3
+ Accordion,
4
+ Container,
5
+ Grid,
6
+ Icon,
7
+ List,
8
+ Transition,
9
+ } from 'semantic-ui-react';
10
+
11
+ import { cloneDeep } from 'lodash';
12
+
13
+ import { useClickOutside } from '@eeacms/volto-eea-design-system/helpers';
14
+
15
+ const createColumns = (item, renderMenuItem, item_id) => {
16
+ return item.items.map((item, index) => (
17
+ <React.Fragment key={index}>
18
+ {renderMenuItem(item, {
19
+ className: 'item',
20
+ key: index,
21
+ id: item_id,
22
+ })}
23
+ </React.Fragment>
24
+ ));
25
+ };
26
+
27
+ const ItemGrid = ({
28
+ item,
29
+ columns,
30
+ renderMenuItem,
31
+ hideChildrenFromNavigation,
32
+ }) => {
33
+ const item_id = item.title.toLowerCase().replaceAll(' ', '-') + '-sub-title';
34
+ return (
35
+ <>
36
+ {renderMenuItem(item, { className: 'sub-title', id: item_id })}
37
+ {item.items.length && !hideChildrenFromNavigation ? (
38
+ <List
39
+ aria-labelledby={item_id}
40
+ className={columns && columns > 1 ? `has--${columns}--columns` : ''}
41
+ >
42
+ {createColumns(item, renderMenuItem, item_id)}
43
+ </List>
44
+ ) : null}
45
+ </>
46
+ );
47
+ };
48
+
49
+ const Item = ({
50
+ item,
51
+ icon = false,
52
+ iconName,
53
+ renderMenuItem,
54
+ hideChildrenFromNavigation,
55
+ }) => {
56
+ const item_id = item.title.toLowerCase().replaceAll(' ', '-') + '-sub-title';
57
+ return (
58
+ <>
59
+ {renderMenuItem(item, {
60
+ className: 'sub-title',
61
+ id: item_id,
62
+ })}
63
+ {!hideChildrenFromNavigation && (
64
+ <List className="menu-list" aria-labelledby={item_id}>
65
+ {item.items.map((listItem, index) => (
66
+ <React.Fragment key={index}>
67
+ {renderMenuItem(
68
+ listItem,
69
+ {
70
+ className: 'item',
71
+ key: index,
72
+ },
73
+ { children: icon && <Icon className={iconName} /> },
74
+ )}
75
+ </React.Fragment>
76
+ ))}
77
+ </List>
78
+ )}
79
+ </>
80
+ );
81
+ };
82
+
83
+ const RenderItem = ({ layout, section, renderMenuItem, index }) => {
84
+ const hideChildrenFromNavigation =
85
+ layout.hideChildrenFromNavigation === undefined
86
+ ? true
87
+ : layout.hideChildrenFromNavigation;
88
+ return !layout.menuItemChildrenListColumns ||
89
+ layout.menuItemChildrenListColumns[index] === 1 ? (
90
+ <Item
91
+ item={section}
92
+ renderMenuItem={renderMenuItem}
93
+ hideChildrenFromNavigation={hideChildrenFromNavigation}
94
+ />
95
+ ) : (
96
+ <ItemGrid
97
+ item={section}
98
+ columns={layout.menuItemChildrenListColumns[index]}
99
+ renderMenuItem={renderMenuItem}
100
+ hideChildrenFromNavigation={hideChildrenFromNavigation}
101
+ />
102
+ );
103
+ };
104
+
105
+ export const StandardMegaMenuGrid = ({ menuItem, renderMenuItem, layout }) => {
106
+ const menuItemColumns = layout && layout.menuItemColumns;
107
+ const menuItemColumnsLength =
108
+ (menuItemColumns && menuItemColumns.length - 1) || 0;
109
+
110
+ const renderColumnContent = (section, columnIndex) => (
111
+ <RenderItem
112
+ layout={layout}
113
+ section={section}
114
+ renderMenuItem={renderMenuItem}
115
+ index={columnIndex}
116
+ />
117
+ );
118
+
119
+ const renderColumns = () => (
120
+ <Grid>
121
+ {menuItemColumns.map((section, columnIndex) => (
122
+ <div className={layout.menuItemColumns[columnIndex]} key={columnIndex}>
123
+ {columnIndex !== menuItemColumnsLength
124
+ ? renderColumnContent(menuItem.items[columnIndex], columnIndex)
125
+ : menuItem.items
126
+ .slice(menuItemColumnsLength)
127
+ .map((section, _idx) =>
128
+ renderColumnContent(section, columnIndex),
129
+ )}
130
+ </div>
131
+ ))}
132
+ </Grid>
133
+ );
134
+
135
+ const renderDefaultColumns = () => (
136
+ <div className={layout?.gridContainerClass || 'ui four column grid'}>
137
+ {menuItem.items.map((section, index) => (
138
+ <Grid.Column key={index}>
139
+ {renderColumnContent(section, index)}
140
+ </Grid.Column>
141
+ ))}
142
+ </div>
143
+ );
144
+
145
+ return menuItemColumns ? renderColumns() : renderDefaultColumns();
146
+ };
147
+
148
+ const FirstLevelContent = ({ element, renderMenuItem, pathName }) => {
149
+ const topics = element.title === 'Topics';
150
+ let defaultIndex = -1;
151
+
152
+ return (
153
+ <>
154
+ {!topics ? (
155
+ <React.Fragment>
156
+ {element.items.map((item, index) => {
157
+ let firstLevelPanels = [];
158
+ if (!item.items.length) {
159
+ return (
160
+ <React.Fragment key={index}>
161
+ {renderMenuItem(item, { className: 'item sub-title' })}
162
+ </React.Fragment>
163
+ );
164
+ }
165
+ let x = {};
166
+ x.key = item['@id'] || item['url'];
167
+ if (pathName.indexOf(item.url) !== -1) {
168
+ defaultIndex = index;
169
+ }
170
+ x.title = (
171
+ <Accordion.Title
172
+ key={`title=${index}`}
173
+ as="button"
174
+ aria-expanded={false}
175
+ onClick={(e) => {
176
+ e.currentTarget.setAttribute(
177
+ 'aria-expanded',
178
+ e.currentTarget.className.indexOf('active') === -1,
179
+ );
180
+ }}
181
+ >
182
+ {item.title}
183
+ <Icon className="ri-arrow-down-s-line" size="small" />
184
+ </Accordion.Title>
185
+ );
186
+ let overflow_item = cloneDeep(item);
187
+ overflow_item.title = 'See all';
188
+ x.content = (
189
+ <Accordion.Content>
190
+ {renderMenuItem(overflow_item, {
191
+ className: 'item title-item',
192
+ })}
193
+ <SecondLevelContent
194
+ element={item}
195
+ renderMenuItem={renderMenuItem}
196
+ />
197
+ </Accordion.Content>
198
+ );
199
+ firstLevelPanels.push(x);
200
+ return (
201
+ <Accordion.Accordion
202
+ panels={firstLevelPanels}
203
+ key={index}
204
+ defaultActiveIndex={defaultIndex === index ? 0 : -1}
205
+ />
206
+ );
207
+ })}
208
+ </React.Fragment>
209
+ ) : (
210
+ <SecondLevelContent
211
+ element={element}
212
+ topics={true}
213
+ renderMenuItem={renderMenuItem}
214
+ />
215
+ )}
216
+ </>
217
+ );
218
+ };
219
+
220
+ const SecondLevelContent = ({ element, topics = false, renderMenuItem }) => {
221
+ let content;
222
+ if (topics) {
223
+ const atAGlance = element.items.find(
224
+ (element) => element.title === 'At a glance',
225
+ );
226
+ const inDepth = element.items.find(
227
+ (element) => element.url.indexOf('in-depth') !== -1,
228
+ );
229
+ content = (
230
+ <List>
231
+ {atAGlance &&
232
+ atAGlance.items.map((item, index) => (
233
+ <React.Fragment key={index}>
234
+ {renderMenuItem(item, {
235
+ key: index,
236
+ className: 'item',
237
+ })}
238
+ </React.Fragment>
239
+ ))}
240
+ {inDepth && (
241
+ <React.Fragment key={inDepth.url}>
242
+ {renderMenuItem(inDepth, {
243
+ key: inDepth.url,
244
+ className: 'item',
245
+ })}
246
+ </React.Fragment>
247
+ )}
248
+ </List>
249
+ );
250
+ } else {
251
+ content = (
252
+ <List>
253
+ {element.items.map((item, index) => (
254
+ <React.Fragment key={index}>
255
+ {renderMenuItem(item, {
256
+ key: index,
257
+ className: 'item',
258
+ })}
259
+ </React.Fragment>
260
+ ))}
261
+ </List>
262
+ );
263
+ }
264
+
265
+ return <>{content}</>;
266
+ };
267
+
268
+ const NestedAccordion = ({ menuItems, renderMenuItem, pathName }) => {
269
+ const [activeIndex, setActiveIndex] = useState(-1);
270
+
271
+ useEffect(() => {
272
+ let index = 0;
273
+ menuItems.forEach((menuItem) => {
274
+ if (pathName.includes(menuItem.url)) setActiveIndex(index);
275
+ ++index;
276
+ });
277
+ }, [menuItems, pathName]);
278
+
279
+ const rootPanels = [];
280
+ menuItems.forEach((element, index) => {
281
+ let x = {};
282
+ x.key = index;
283
+ x.title = (
284
+ <Accordion.Title
285
+ key={`title-${index}`}
286
+ index={index}
287
+ aria-expanded={activeIndex === index}
288
+ as="button"
289
+ onClick={() => {
290
+ if (activeIndex === index) {
291
+ setActiveIndex(-1);
292
+ } else setActiveIndex(index);
293
+ }}
294
+ >
295
+ {element.title}
296
+ <Icon className="ri-arrow-down-s-line" size="small" />
297
+ </Accordion.Title>
298
+ );
299
+ let overview = cloneDeep(element);
300
+ x.content = (
301
+ <Accordion.Content key={index}>
302
+ <div className="mega-menu-title">
303
+ {/* Inverted right labeled button as a category title - Mobile */}
304
+ {renderMenuItem(
305
+ overview,
306
+ { className: 'ui button inverted icon right labeled' },
307
+ {
308
+ iconPosition: 'right',
309
+ children: (
310
+ <>
311
+ {/* Add word overview to titles */}
312
+ <span> overview</span>
313
+ <Icon className={'arrow right icon'} alt={'Title icon'} />
314
+ </>
315
+ ),
316
+ },
317
+ )}
318
+ </div>
319
+ <FirstLevelContent
320
+ element={element}
321
+ renderMenuItem={renderMenuItem}
322
+ pathName={pathName}
323
+ />
324
+ </Accordion.Content>
325
+ );
326
+ rootPanels.push(x);
327
+ });
328
+
329
+ return <Accordion activeIndex={activeIndex} panels={rootPanels} />;
330
+ };
331
+
332
+ function HeaderMenuPopUp({
333
+ menuItems,
334
+ menuItemsLayouts,
335
+ renderMenuItem,
336
+ pathName,
337
+ onClose,
338
+ triggerRefs,
339
+ activeItem,
340
+ visible,
341
+ }) {
342
+ const nodeRef = React.useRef();
343
+ useClickOutside({ targetRefs: [nodeRef, ...triggerRefs], callback: onClose });
344
+
345
+ const menuItem = menuItems.find(
346
+ (current) => current.url === activeItem || current['@id'] === activeItem,
347
+ );
348
+
349
+ const layout =
350
+ !!menuItemsLayouts &&
351
+ Object.keys(menuItemsLayouts).includes(menuItem?.url) &&
352
+ menuItemsLayouts[menuItem.url];
353
+
354
+ return (
355
+ <Transition visible={visible} animation="slide down" duration={300}>
356
+ <div id="mega-menu" ref={nodeRef}>
357
+ <Container>
358
+ {menuItem && (
359
+ <div className="menu-content tablet hidden mobile hidden">
360
+ {/* Inverted right labeled button as a category title,
361
+ for topics the button goes inside the grid */}
362
+ {menuItem.title && (
363
+ <div className="mega-menu-title">
364
+ {renderMenuItem(
365
+ menuItem,
366
+ { className: 'ui button inverted icon right labeled' },
367
+ {
368
+ iconPosition: 'right',
369
+ children: (
370
+ <>
371
+ {/* Add word overview to titles */}
372
+ <span> overview</span>
373
+ <Icon
374
+ className={'arrow right icon'}
375
+ alt={'Title icon'}
376
+ />
377
+ </>
378
+ ),
379
+ },
380
+ )}
381
+ </div>
382
+ )}
383
+ <StandardMegaMenuGrid
384
+ menuItem={menuItem}
385
+ renderMenuItem={renderMenuItem}
386
+ layout={layout}
387
+ />
388
+ </div>
389
+ )}
390
+ <div className="tablet only mobile only">
391
+ <NestedAccordion
392
+ menuItems={menuItems}
393
+ renderMenuItem={renderMenuItem}
394
+ pathName={pathName}
395
+ />
396
+ </div>
397
+ </Container>
398
+ </div>
399
+ </Transition>
400
+ );
401
+ }
402
+
403
+ export default HeaderMenuPopUp;
@@ -0,0 +1,131 @@
1
+ import React, { useEffect } from 'react';
2
+ import { Container, Input, List } from 'semantic-ui-react';
3
+ import { withRouter, Link } from 'react-router-dom';
4
+ import { useClickOutside } from '@eeacms/volto-eea-design-system/helpers';
5
+ import { handleEnterKeyPress } from '@eeacms/volto-eea-design-system/helpers';
6
+
7
+ const getRandomItems = (arr, max) => {
8
+ return (
9
+ arr?.slice(0, max).map(function () {
10
+ return this.splice(Math.floor(Math.random() * this.length), 1)[0];
11
+ }, arr.slice()) || []
12
+ );
13
+ };
14
+
15
+ function HeaderSearchPopUp({
16
+ history,
17
+ location,
18
+ onClose,
19
+ searchInputRef,
20
+ headerSearchBox,
21
+ triggerRefs = [],
22
+ }) {
23
+ const nodeRef = React.useRef();
24
+ const headerSearchViews = headerSearchBox || [];
25
+ const defaultView = headerSearchViews.filter((v) => v.isDefault);
26
+ const localView = headerSearchViews.filter((v) =>
27
+ location.pathname.match(v.matchpath ? v.matchpath : v.path),
28
+ );
29
+ const activeView = localView.length > 0 ? localView[0] : defaultView[0];
30
+
31
+ const {
32
+ path = '',
33
+ buttonTitle,
34
+ buttonUrl,
35
+ description,
36
+ placeholder = 'Search',
37
+ searchSuggestions,
38
+ } = activeView || {};
39
+ const { suggestionsTitle, suggestions, maxToShow } = searchSuggestions || {};
40
+
41
+ const [visibleSuggestions, setVisibileSuggestions] = React.useState(
42
+ getRandomItems(suggestions, maxToShow),
43
+ );
44
+
45
+ useEffect(() => {
46
+ setVisibileSuggestions(getRandomItems(suggestions, maxToShow));
47
+ }, [maxToShow, suggestions]);
48
+
49
+ useClickOutside({ targetRefs: [nodeRef, ...triggerRefs], callback: onClose });
50
+
51
+ const onSubmit = (event) => {
52
+ const text = searchInputRef?.current?.inputRef?.current?.value;
53
+ history.push(`${path}?q=${text}`);
54
+
55
+ if (window?.searchContext?.resetSearch) {
56
+ window.searchContext.resetSearch({ searchTerm: text });
57
+ }
58
+
59
+ onClose();
60
+ event.preventDefault();
61
+ };
62
+
63
+ const onClickHandler = (suggestion) => {
64
+ if (window?.searchContext?.resetSearch) {
65
+ window.searchContext.resetSearch({ searchTerm: suggestion });
66
+ }
67
+
68
+ onClose();
69
+ };
70
+
71
+ return (
72
+ <div id="search-box" ref={nodeRef}>
73
+ <div className="wrapper">
74
+ <Container>
75
+ <form method="get" onSubmit={onSubmit}>
76
+ <Input
77
+ ref={searchInputRef}
78
+ className="icon search"
79
+ action={{
80
+ className: 'icon ri-search-line',
81
+ 'aria-label': 'Submit search',
82
+ onClick: onSubmit,
83
+ onKeyDown: (event) => {
84
+ handleEnterKeyPress(event, onSubmit);
85
+ },
86
+ }}
87
+ placeholder={placeholder}
88
+ fluid
89
+ />
90
+ </form>
91
+ {searchSuggestions && suggestions.length > 0 && (
92
+ <div className="search-suggestions">
93
+ {suggestionsTitle && <h4>{suggestionsTitle}</h4>}
94
+
95
+ <List>
96
+ {visibleSuggestions.map((item, i) => {
97
+ return (
98
+ <List.Item key={i}>
99
+ <Link
100
+ to={`${path}?q=${item}`}
101
+ onClick={() => onClickHandler(item)}
102
+ >
103
+ {item}
104
+ </Link>
105
+ </List.Item>
106
+ );
107
+ })}
108
+ </List>
109
+ </div>
110
+ )}
111
+ </Container>
112
+ {buttonTitle && (
113
+ <div className="advanced-search">
114
+ <Container>
115
+ <div>{description}</div>
116
+ <a
117
+ href={buttonUrl || defaultView[0].path}
118
+ className="ui button white inverted"
119
+ title="Advanced search"
120
+ >
121
+ {buttonTitle}
122
+ </a>
123
+ </Container>
124
+ </div>
125
+ )}
126
+ </div>
127
+ </div>
128
+ );
129
+ }
130
+
131
+ export default withRouter(HeaderSearchPopUp);
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Logo component.
3
+ * @module components/theme/Logo/Logo
4
+ */
5
+
6
+ import React from 'react';
7
+ import { Link } from 'react-router-dom';
8
+ import { LazyLoadImage } from 'react-lazy-load-image-component';
9
+ import config from '@plone/volto/registry';
10
+ /**
11
+ * Logo component class.
12
+ * @function Logo
13
+ * @param {Object} intl Intl object
14
+ * @returns {string} Markup of the component.
15
+ */
16
+ const Logo = ({ src, invertedSrc, id, url, alt, title, inverted }) => {
17
+ const root = config.settings.prefixPath ?? '/';
18
+
19
+ return (
20
+ <Link to={root} title={title} className={'logo'}>
21
+ <LazyLoadImage
22
+ src={inverted ? invertedSrc : src}
23
+ alt={alt}
24
+ title={title}
25
+ className="eea-logo"
26
+ id={id}
27
+ />
28
+ </Link>
29
+ );
30
+ };
31
+
32
+ export default Logo;