@kitconcept/volto-light-theme 5.0.1 → 6.0.0-alpha.1

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 (112) hide show
  1. package/.changelog.draft +2 -8
  2. package/CHANGELOG.md +38 -0
  3. package/README.md +7 -367
  4. package/package.json +20 -7
  5. package/razzle.extend.js +38 -0
  6. package/src/components/Anontools/Anontools.jsx +1 -1
  7. package/src/components/Blocks/Button/schema.js +25 -5
  8. package/src/components/Blocks/EventMetadata/View.jsx +8 -7
  9. package/src/components/Blocks/Image/Edit.jsx +4 -6
  10. package/src/components/Blocks/Image/ImageSidebar.jsx +4 -2
  11. package/src/components/Blocks/Image/View.jsx +3 -6
  12. package/src/components/Blocks/Image/schema.js +37 -6
  13. package/src/components/Blocks/Listing/DefaultTemplate.jsx +3 -2
  14. package/src/components/Blocks/Listing/GridTemplate.jsx +4 -2
  15. package/src/components/Blocks/Listing/ImageGallery.jsx +2 -2
  16. package/src/components/Blocks/Listing/SummaryTemplate.jsx +3 -2
  17. package/src/components/Blocks/Search/components/SearchInput.jsx +1 -1
  18. package/src/components/Blocks/Separator/schema.js +59 -0
  19. package/src/components/Blocks/Slider/DefaultBody.jsx +4 -2
  20. package/src/components/Blocks/Teaser/schema.js +21 -1
  21. package/src/components/Blocks/schema.js +16 -15
  22. package/src/components/Breadcrumbs/Breadcrumbs.jsx +4 -3
  23. package/src/components/Footer/Footer.jsx +77 -27
  24. package/src/components/Header/Header.jsx +34 -29
  25. package/src/components/LanguageSelector/{LanguageSelector.js → LanguageSelector.jsx} +11 -7
  26. package/src/components/Logo/Logo.jsx +28 -22
  27. package/src/components/MobileNavigation/MobileNavigation.jsx +3 -2
  28. package/src/components/MobileNavigation/MobileToolsFooter.jsx +1 -1
  29. package/src/components/Navigation/Navigation.jsx +4 -3
  30. package/src/components/SearchWidget/IntranetSearchWidget.jsx +1 -1
  31. package/src/components/SearchWidget/SearchWidget.jsx +1 -1
  32. package/src/components/Theme/EventView.jsx +3 -2
  33. package/src/components/Theme/FileView.jsx +1 -1
  34. package/src/components/Theme/NewsItemView.jsx +1 -1
  35. package/src/components/Theming/Theming.tsx +52 -0
  36. package/src/components/Widgets/AlignWidget.jsx +2 -2
  37. package/src/components/Widgets/BackgroundColorWidget.tsx +18 -0
  38. package/src/components/Widgets/BlockAlignmentWidget.tsx +81 -0
  39. package/src/components/Widgets/BlockWidthWidget.tsx +94 -0
  40. package/src/components/Widgets/BlocksObjectWidget.tsx +333 -0
  41. package/src/components/Widgets/ButtonsWidget.tsx +68 -0
  42. package/src/components/Widgets/ColorPickerWidget.tsx +60 -0
  43. package/src/components/Widgets/FooterLinksWidget.tsx +106 -0
  44. package/src/components/Widgets/FooterLogosWidget.tsx +120 -0
  45. package/src/components/Widgets/ThemingColorPicker.tsx +33 -0
  46. package/src/config/blocks.tsx +352 -0
  47. package/src/config/classExtenders.ts +101 -0
  48. package/src/config/settings.ts +35 -0
  49. package/src/config/slots.ts +12 -0
  50. package/src/config/widgets.ts +31 -0
  51. package/src/customizations/volto/components/theme/View/RenderBlocks.jsx +97 -80
  52. package/src/customizations/volto/components/theme/View/RenderBlocks.test.jsx +16 -48
  53. package/src/helpers/helpers.test.ts +51 -0
  54. package/src/helpers/helpers.ts +48 -0
  55. package/src/index.ts +54 -0
  56. package/src/theme/_bgcolor-blocks-layout.scss +1127 -20
  57. package/src/theme/_footer.scss +8 -5
  58. package/src/theme/_header.scss +3 -8
  59. package/src/theme/_layout.scss +24 -7
  60. package/src/theme/_typo-custom.scss +1 -1
  61. package/src/theme/_variables.scss +95 -12
  62. package/src/theme/_widgets.scss +102 -0
  63. package/src/theme/blocks/_accordion.scss +2 -4
  64. package/src/theme/blocks/_button.scss +32 -31
  65. package/src/theme/blocks/_eventMetadata.scss +7 -0
  66. package/src/theme/blocks/_grid.scss +11 -36
  67. package/src/theme/blocks/_highlight.scss +1 -0
  68. package/src/theme/blocks/_image.scss +38 -17
  69. package/src/theme/blocks/_introduction.scss +16 -0
  70. package/src/theme/blocks/_listing.scss +1 -6
  71. package/src/theme/blocks/_search.scss +1 -23
  72. package/src/theme/blocks/_separator.scss +17 -20
  73. package/src/theme/blocks/_slider.scss +57 -56
  74. package/src/theme/blocks/_teaser.scss +3 -3
  75. package/src/theme/main.scss +1 -0
  76. package/src/transforms/to6.ts +94 -0
  77. package/tsconfig.json +33 -0
  78. package/.release-it.json +0 -31
  79. package/babel.config.js +0 -17
  80. package/build/messages/src/components/Anontools/Anontools.json +0 -10
  81. package/build/messages/src/components/Blocks/Button/schema.json +0 -6
  82. package/build/messages/src/components/Blocks/EventMetadata/View.json +0 -30
  83. package/build/messages/src/components/Blocks/Image/Edit.json +0 -10
  84. package/build/messages/src/components/Blocks/Image/ImageSidebar.json +0 -18
  85. package/build/messages/src/components/Blocks/Image/schema.json +0 -10
  86. package/build/messages/src/components/Blocks/Listing/ListingBody.json +0 -26
  87. package/build/messages/src/components/Blocks/Search/TopSideFacets.json +0 -10
  88. package/build/messages/src/components/Blocks/Search/components/SearchDetails.json +0 -10
  89. package/build/messages/src/components/Blocks/Search/components/SearchInput.json +0 -6
  90. package/build/messages/src/components/Blocks/Slider/DefaultBody.json +0 -18
  91. package/build/messages/src/components/Blocks/Slider/schema.json +0 -14
  92. package/build/messages/src/components/Blocks/schema.json +0 -6
  93. package/build/messages/src/components/Breadcrumbs/Breadcrumbs.json +0 -10
  94. package/build/messages/src/components/Footer/Footer.json +0 -30
  95. package/build/messages/src/components/Header/Header.json +0 -6
  96. package/build/messages/src/components/LanguageSelector/LanguageSelector.json +0 -6
  97. package/build/messages/src/components/Logo/Logo.json +0 -10
  98. package/build/messages/src/components/MobileNavigation/MobileNavigation.json +0 -26
  99. package/build/messages/src/components/Navigation/Navigation.json +0 -10
  100. package/build/messages/src/components/SearchWidget/IntranetSearchWidget.json +0 -14
  101. package/build/messages/src/components/SearchWidget/SearchWidget.json +0 -10
  102. package/build/messages/src/components/Theme/EventView.json +0 -6
  103. package/build/messages/src/components/Widgets/AlignWidget.json +0 -22
  104. package/build/messages/src/index.json +0 -10
  105. package/news/.gitkeep +0 -0
  106. package/src/components/Atoms/Container/Container.jsx +0 -32
  107. package/src/components/Atoms/README.md +0 -1
  108. package/src/components/Atoms/helpers.jsx +0 -9
  109. package/src/components/CQPolyfill.jsx +0 -9
  110. package/src/index.js +0 -367
  111. package/towncrier.toml +0 -33
  112. /package/src/components/Blocks/Slate/{ExtraAlignWrapper.js → ExtraAlignWrapper.jsx} +0 -0
@@ -2,8 +2,10 @@ import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import { Segment, Button } from 'semantic-ui-react';
4
4
  import { useIntl, FormattedMessage, defineMessages } from 'react-intl';
5
- import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers';
6
- import { BlockDataForm, Icon, Image } from '@plone/volto/components';
5
+ import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers/Url/Url';
6
+ import Icon from '@plone/volto/components/theme/Icon/Icon';
7
+ import { BlockDataForm } from '@plone/volto/components/manage/Form';
8
+ import Image from '@plone/volto/components/theme/Image/Image';
7
9
  import { ImageSchema } from '@plone/volto/components/manage/Blocks/Image/schema';
8
10
  import imageSVG from '@plone/volto/icons/image.svg';
9
11
  import trashSVG from '@plone/volto/icons/delete.svg';
@@ -5,14 +5,11 @@
5
5
 
6
6
  import React from 'react';
7
7
  import PropTypes from 'prop-types';
8
- import { UniversalLink } from '@plone/volto/components';
8
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
9
9
  import cx from 'classnames';
10
10
  import Caption from '../../Caption/Caption';
11
- import {
12
- flattenToAppURL,
13
- isInternalURL,
14
- withBlockExtensions,
15
- } from '@plone/volto/helpers';
11
+ import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers/Url/Url';
12
+ import { withBlockExtensions } from '@plone/volto/helpers/Extensions';
16
13
  import config from '@plone/volto/registry';
17
14
 
18
15
  /**
@@ -1,5 +1,6 @@
1
1
  import { defineMessages } from 'react-intl';
2
- import { insertInArray } from '@plone/volto/helpers/Utils/Utils';
2
+ import { insertInArray, reorderArray } from '@plone/volto/helpers/Utils/Utils';
3
+ import config from '@plone/volto/registry';
3
4
 
4
5
  const messages = defineMessages({
5
6
  Description: {
@@ -10,10 +11,15 @@ const messages = defineMessages({
10
11
  id: 'Title',
11
12
  defaultMessage: 'Title',
12
13
  },
14
+ BlockWidth: {
15
+ id: 'Block Width',
16
+ defaultMessage: 'Block Width',
17
+ },
13
18
  });
14
19
 
15
20
  export const imageBlockSchemaEnhancer = ({ formData, schema, intl }) => {
16
21
  if (formData.url) {
22
+ schema.fieldsets = reorderArray(schema.fieldsets, 2, 1);
17
23
  schema.fieldsets[0].fields = insertInArray(
18
24
  schema.fieldsets[0].fields,
19
25
  'description',
@@ -24,6 +30,30 @@ export const imageBlockSchemaEnhancer = ({ formData, schema, intl }) => {
24
30
  'title',
25
31
  1,
26
32
  );
33
+
34
+ schema.properties.styles.schema.fieldsets[0].fields = [
35
+ 'blockWidth:noprefix',
36
+ '--image-aspect-ratio',
37
+ ...schema.properties.styles.schema.fieldsets[0].fields,
38
+ ];
39
+
40
+ schema.properties.styles.schema.properties['blockWidth:noprefix'] = {
41
+ widget: 'blockWidth',
42
+ title: intl.formatMessage(messages.BlockWidth),
43
+ default: 'default',
44
+ filterActions: ['narrow', 'default', 'layout', 'full'],
45
+ actions: config.blocks.widths,
46
+ };
47
+
48
+ schema.properties.styles.schema.properties['--image-aspect-ratio'] = {
49
+ widget: 'select',
50
+ title: 'Aspect Ratio',
51
+ choices: [
52
+ ['1', '1:1'],
53
+ ['16 / 9', '16/9'],
54
+ ],
55
+ };
56
+
27
57
  schema.properties.description = {
28
58
  title: intl.formatMessage(messages.Description),
29
59
  widget: 'textarea',
@@ -33,12 +63,13 @@ export const imageBlockSchemaEnhancer = ({ formData, schema, intl }) => {
33
63
  };
34
64
  }
35
65
  schema.properties.align.default = 'center';
36
- schema.properties.align.actions = ['left', 'right', 'center', 'wide', 'full'];
66
+ schema.properties.align.actions = ['left', 'right', 'center'];
67
+
37
68
  schema.properties.size.default = 'l';
38
- schema.properties.size.disabled =
39
- formData.align === 'full' ||
40
- formData.align === 'wide' ||
41
- formData.align === 'center';
69
+ schema.properties.size.disabled = formData.align === 'center';
70
+
71
+ schema.properties.styles.schema.properties['blockWidth:noprefix'].disabled =
72
+ formData.align === 'left' || formData.align === 'right';
42
73
 
43
74
  return schema;
44
75
  };
@@ -1,8 +1,9 @@
1
1
  // See Customization for more info
2
2
  import React from 'react';
3
3
  import PropTypes from 'prop-types';
4
- import { ConditionalLink, UniversalLink } from '@plone/volto/components';
5
- import { flattenToAppURL } from '@plone/volto/helpers';
4
+ import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
5
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
6
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
6
7
 
7
8
  import { isInternalURL } from '@plone/volto/helpers/Url/Url';
8
9
 
@@ -1,7 +1,9 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { ConditionalLink, Component } from '@plone/volto/components';
4
- import { flattenToAppURL } from '@plone/volto/helpers';
3
+ import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
4
+ import Component from '@plone/volto/components/theme/Component/Component';
5
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
6
+
5
7
  import config from '@plone/volto/registry';
6
8
 
7
9
  import { isInternalURL } from '@plone/volto/helpers/Url/Url';
@@ -3,8 +3,8 @@ import PropTypes from 'prop-types';
3
3
  import loadable from '@loadable/component';
4
4
  import 'react-image-gallery/styles/css/image-gallery.css';
5
5
  import { Button } from 'semantic-ui-react';
6
- import { Icon } from '@plone/volto/components';
7
- import { flattenToAppURL } from '@plone/volto/helpers';
6
+ import Icon from '@plone/volto/components/theme/Icon/Icon';
7
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
8
8
  import config from '@plone/volto/registry';
9
9
 
10
10
  import galleryLeftSVG from '../../../icons/left-key.svg';
@@ -1,7 +1,8 @@
1
1
  import React from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { ConditionalLink, Component } from '@plone/volto/components';
4
- import { flattenToAppURL } from '@plone/volto/helpers';
3
+ import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
4
+ import Component from '@plone/volto/components/theme/Component/Component';
5
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
5
6
  import config from '@plone/volto/registry';
6
7
 
7
8
  import { isInternalURL } from '@plone/volto/helpers/Url/Url';
@@ -5,7 +5,7 @@
5
5
  import React from 'react';
6
6
  import { Button, Input } from 'semantic-ui-react';
7
7
  import { defineMessages, useIntl } from 'react-intl';
8
- import { Icon } from '@plone/volto/components';
8
+ import Icon from '@plone/volto/components/theme/Icon/Icon';
9
9
  import loupeSVG from '@plone/volto/icons/zoom.svg';
10
10
 
11
11
  const messages = defineMessages({
@@ -0,0 +1,59 @@
1
+ import { defineMessages } from 'react-intl';
2
+ import { defaultStylingSchema } from '../schema';
3
+
4
+ const messages = defineMessages({
5
+ BlockWidth: {
6
+ id: 'Block Width',
7
+ defaultMessage: 'Block Width',
8
+ },
9
+ Alignment: {
10
+ id: 'Alignment',
11
+ defaultMessage: 'Alignment',
12
+ },
13
+ shortline: {
14
+ id: 'Short line',
15
+ defaultMessage: 'Short line',
16
+ },
17
+ });
18
+
19
+ export const SeparatorStylingSchema = ({ schema, formData, intl }) => {
20
+ defaultStylingSchema({ schema, formData, intl });
21
+
22
+ schema.properties.styles.schema.fieldsets[0].fields = [
23
+ 'blockWidth:noprefix',
24
+ ...schema.properties.styles.schema.fieldsets[0].fields,
25
+ ];
26
+
27
+ schema.properties.styles.schema.properties['blockWidth:noprefix'] = {
28
+ widget: 'blockWidth',
29
+ title: intl.formatMessage(messages.BlockWidth),
30
+ default: 'default',
31
+ filterActions: ['narrow', 'default'],
32
+ };
33
+
34
+ schema.properties.styles.schema.fieldsets[0].fields = [
35
+ 'align:noprefix',
36
+ ...schema.properties.styles.schema.fieldsets[0].fields,
37
+ ];
38
+
39
+ schema.properties.styles.schema.properties['align:noprefix'] = {
40
+ widget: 'blockAlignment',
41
+ title: intl.formatMessage(messages.Alignment),
42
+ default: 'left',
43
+ };
44
+
45
+ schema.properties.styles.schema.fieldsets[0].fields = [
46
+ 'shortLine',
47
+ ...schema.properties.styles.schema.fieldsets[0].fields,
48
+ ];
49
+
50
+ schema.properties.styles.schema.properties.shortLine = {
51
+ title: intl.formatMessage(messages.shortline),
52
+ type: 'boolean',
53
+ };
54
+
55
+ schema.properties.styles.schema.properties['align:noprefix'].disabled =
56
+ !formData?.styles?.shortLine;
57
+
58
+ return schema;
59
+ };
@@ -1,8 +1,10 @@
1
1
  import React from 'react';
2
2
  import { useIntl, defineMessages } from 'react-intl';
3
- import { Icon, MaybeWrap, UniversalLink } from '@plone/volto/components';
3
+ import Icon from '@plone/volto/components/theme/Icon/Icon';
4
+ import MaybeWrap from '@plone/volto/components/manage/MaybeWrap/MaybeWrap';
5
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
4
6
  import { Input, Button, Message } from 'semantic-ui-react';
5
- import { isInternalURL } from '@plone/volto/helpers';
7
+ import { isInternalURL } from '@plone/volto/helpers/Url/Url';
6
8
  import cx from 'classnames';
7
9
  import navTreeSVG from '@plone/volto/icons/nav.svg';
8
10
  import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
@@ -1,10 +1,30 @@
1
1
  export const teaserSchemaEnhancer = ({ schema, formData, intl }) => {
2
2
  schema.properties.href.selectedItemAttrs.push('getRemoteUrl');
3
3
 
4
+ schema.properties.styles.schema.fieldsets[0].fields = [
5
+ ...schema.properties.styles.schema.fieldsets[0].fields,
6
+ '--image-aspect-ratio',
7
+ ];
8
+
9
+ schema.properties.styles.schema.properties['--image-aspect-ratio'] = {
10
+ widget: 'select',
11
+ title: 'Aspect Ratio',
12
+ choices: [
13
+ ['1', '1:1'],
14
+ ['16 / 9', '16/9'],
15
+ ],
16
+ };
17
+
4
18
  return schema;
5
19
  };
6
20
 
21
+ // Not sure why, but it was in the new one, check with blockModel3
22
+ // export const gridTeaserDisableStylingSchema = ({ schema, formData, intl }) => {
23
+ // schema.fieldsets = schema.fieldsets.filter((item) => item.id !== 'styling');
24
+ // return schema;
25
+ // };
7
26
  export const gridTeaserDisableStylingSchema = ({ schema, formData, intl }) => {
8
- schema.fieldsets = schema.fieldsets.filter((item) => item.id !== 'styling');
27
+ // Remove all the existing fields from the default schema
28
+ schema.properties.styles.schema.fieldsets[0].fields = [];
9
29
  return schema;
10
30
  };
@@ -10,28 +10,29 @@ const messages = defineMessages({
10
10
  });
11
11
 
12
12
  export const defaultStylingSchema = ({ schema, formData, intl }) => {
13
- const BG_COLORS = [
14
- { name: 'transparent', label: 'Transparent' },
15
- { name: 'grey', label: 'Grey' },
16
- ];
17
-
18
- const colors =
19
- config.blocks?.blocksConfig?.[formData['@type']]?.colors || BG_COLORS;
13
+ const themes =
14
+ config.blocks?.blocksConfig?.[formData['@type']]?.themes ||
15
+ config.blocks.themes;
20
16
 
21
- const defaultBGColor =
22
- config.blocks?.blocksConfig?.[formData['@type']]?.defaultBGColor;
17
+ const defaultTheme =
18
+ config.blocks?.blocksConfig?.[formData['@type']]?.defaultTheme ||
19
+ // The default color is the first color in the themes list
20
+ config.blocks.themes?.[0].name;
23
21
 
24
22
  addStyling({ schema, intl });
25
23
 
26
- schema.properties.styles.schema.fieldsets[0].fields = [
27
- ...schema.properties.styles.schema.fieldsets[0].fields,
28
- 'backgroundColor',
24
+ const stylingIndex = schema.fieldsets.findIndex(
25
+ (item) => item.id === 'styling',
26
+ );
27
+ schema.fieldsets[stylingIndex].fields = [
28
+ ...schema.fieldsets[stylingIndex].fields,
29
+ 'theme',
29
30
  ];
30
- schema.properties.styles.schema.properties.backgroundColor = {
31
+ schema.properties.theme = {
31
32
  widget: 'color_picker',
32
33
  title: intl.formatMessage(messages.backgroundColor),
33
- colors,
34
- default: defaultBGColor,
34
+ themes,
35
+ default: defaultTheme,
35
36
  };
36
37
 
37
38
  return schema;
@@ -7,9 +7,10 @@ import { Link } from 'react-router-dom';
7
7
  import { defineMessages, injectIntl } from 'react-intl';
8
8
  import { Container } from '@plone/components';
9
9
 
10
- import { Icon } from '@plone/volto/components';
11
- import { getBreadcrumbs } from '@plone/volto/actions';
12
- import { getBaseUrl, hasApiExpander } from '@plone/volto/helpers';
10
+ import Icon from '@plone/volto/components/theme/Icon/Icon';
11
+ import { getBreadcrumbs } from '@plone/volto/actions/breadcrumbs/breadcrumbs';
12
+ import { getBaseUrl } from '@plone/volto/helpers/Url/Url';
13
+ import { hasApiExpander } from '@plone/volto/helpers/Utils/Utils';
13
14
 
14
15
  import homeSVG from '@plone/volto/icons/home.svg';
15
16
 
@@ -1,11 +1,13 @@
1
1
  // SemanticUI-free pre-@plone/components
2
2
  import React from 'react';
3
-
3
+ import isEmpty from 'lodash/isEmpty';
4
4
  import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
5
5
  import { useSelector, shallowEqual } from 'react-redux';
6
- import { UniversalLink, Logo } from '@plone/volto/components';
6
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
7
+ import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
8
+ import Logo from '@plone/volto/components/theme/Logo/Logo';
7
9
  import { Container } from '@plone/components';
8
- import { flattenToAppURL, addAppURL } from '@plone/volto/helpers';
10
+ import { flattenToAppURL, addAppURL } from '@plone/volto/helpers/Url/Url';
9
11
  import config from '@plone/volto/registry';
10
12
 
11
13
  const messages = defineMessages({
@@ -30,9 +32,13 @@ const Footer = ({ intl }) => {
30
32
  }),
31
33
  shallowEqual,
32
34
  );
35
+ const navroot = useSelector((state) => state.navroot.data.navroot);
36
+ const footerLinks = navroot?.footer_links;
37
+ const footerLogos = navroot?.footer_logos;
38
+
33
39
  return (
34
40
  <footer id="footer">
35
- <Container layout className="footer">
41
+ <Container className="footer">
36
42
  <div className="footer-message">
37
43
  <FormattedMessage
38
44
  id="The {plonecms} is {copyright} 2000-{current_year} by the {plonefoundation} and friends."
@@ -78,29 +84,73 @@ const Footer = ({ intl }) => {
78
84
  }}
79
85
  />
80
86
  </div>
81
- <ul>
82
- {/* wrap in div for a11y reasons: listitem role cannot be on the <a> element directly */}
83
- {siteActions?.length
84
- ? siteActions.map((item) => (
85
- <li className="item" key={item.id}>
86
- <UniversalLink
87
- className="item"
88
- href={
89
- settings.isMultilingual
90
- ? `/${lang}/${
91
- item.url
92
- ? flattenToAppURL(item.url)
93
- : addAppURL(item.id)
94
- }`
95
- : item.url
96
- ? flattenToAppURL(item.url)
97
- : addAppURL(item.id)
98
- }
99
- >
100
- {item?.title}
101
- </UniversalLink>
102
- </li>
103
- ))
87
+ <ul className="footer-links">
88
+ {!isEmpty(footerLinks?.blocks)
89
+ ? footerLinks.blocks_layout.items.map((itemId) => {
90
+ const link = footerLinks.blocks[itemId];
91
+ const title = link.title || link.href[0]['title'];
92
+ const href = flattenToAppURL(link.href[0]['@id']);
93
+
94
+ if (!href) return null;
95
+
96
+ return (
97
+ <li className="item" key={href}>
98
+ <UniversalLink href={href}>{title}</UniversalLink>
99
+ </li>
100
+ );
101
+ })
102
+ : siteActions?.length
103
+ ? siteActions.map((item) => (
104
+ <li className="item" key={item.id}>
105
+ <UniversalLink
106
+ className="item"
107
+ href={
108
+ settings.isMultilingual
109
+ ? `/${lang}/${
110
+ item.url
111
+ ? flattenToAppURL(item.url)
112
+ : addAppURL(item.id)
113
+ }`
114
+ : item.url
115
+ ? flattenToAppURL(item.url)
116
+ : addAppURL(item.id)
117
+ }
118
+ >
119
+ {item?.title}
120
+ </UniversalLink>
121
+ </li>
122
+ ))
123
+ : null}
124
+ </ul>
125
+ <ul className="footer-logos">
126
+ {!isEmpty(footerLogos?.blocks)
127
+ ? footerLogos.blocks_layout.items.map((itemId) => {
128
+ const logo = footerLogos.blocks[itemId];
129
+ let logoHref, hrefTitle, href, srcAlt, src;
130
+ if (logo?.href) {
131
+ hrefTitle = logo.href[0]['title'];
132
+ href = flattenToAppURL(logo.href[0]['@id']);
133
+ }
134
+ if (logo?.logo) {
135
+ logoHref = logo.logo[0]['@id'];
136
+ srcAlt = logo['alt'];
137
+ src = `${flattenToAppURL(logoHref)}/${logo.logo[0].image_scales[logo.logo[0].image_field][0].download}`;
138
+ }
139
+
140
+ if (!src) return null;
141
+
142
+ return (
143
+ <li className="item" key={href}>
144
+ <ConditionalLink
145
+ condition={href}
146
+ to={href}
147
+ title={hrefTitle || srcAlt}
148
+ >
149
+ <img src={src} alt={srcAlt} />
150
+ </ConditionalLink>
151
+ </li>
152
+ );
153
+ })
104
154
  : null}
105
155
  </ul>
106
156
  <div className="logo">
@@ -8,14 +8,14 @@ import config from '@plone/volto/registry';
8
8
  import cx from 'classnames';
9
9
  import IntranetSearchWidget from '../SearchWidget/IntranetSearchWidget';
10
10
 
11
- import {
12
- Anontools,
13
- LanguageSelector,
14
- Logo,
15
- Navigation,
16
- SearchWidget,
17
- UniversalLink,
18
- } from '@plone/volto/components';
11
+ import Anontools from '@plone/volto/components/theme/Anontools/Anontools';
12
+ import LanguageSelector from '@plone/volto/components/theme/LanguageSelector/LanguageSelector';
13
+ import Logo from '@plone/volto/components/theme/Logo/Logo';
14
+ import Navigation from '@plone/volto/components/theme/Navigation/Navigation';
15
+ import SearchWidget from '@plone/volto/components/theme/SearchWidget/SearchWidget';
16
+ import UniversalLink from '@plone/volto/components/manage/UniversalLink/UniversalLink';
17
+
18
+ import SlotRenderer from '@plone/volto/components/theme/SlotRenderer/SlotRenderer';
19
19
 
20
20
  const messages = defineMessages({
21
21
  siteLabel: {
@@ -107,9 +107,11 @@ const Header = (props) => {
107
107
  let siteLabel = config.settings.siteLabel;
108
108
  const intranetHeader = config.settings.intranetHeader;
109
109
  const token = useSelector((state) => state.userSession.token);
110
+ const content = useSelector((state) => state.content.data);
110
111
  const siteAction = useSelector(
111
112
  (state) => state.content.data?.['@components']?.actions?.site_actions,
112
113
  );
114
+ const navRoot = useSelector((state) => state.navroot?.data?.navroot);
113
115
  const intl = useIntl();
114
116
  const translatedSiteLabel = intl.formatMessage(messages.siteLabel);
115
117
 
@@ -120,27 +122,30 @@ const Header = (props) => {
120
122
  : siteLabel);
121
123
 
122
124
  return (
123
- <header
124
- className={cx('header-wrapper', { 'intranet-header': intranetHeader })}
125
- >
126
- <Container layout>
127
- {intranetHeader ? (
128
- <IntranetHeader
129
- pathname={pathname}
130
- siteLabel={siteLabel}
131
- token={token}
132
- siteAction={siteAction}
133
- />
134
- ) : (
135
- <InternetHeader
136
- pathname={pathname}
137
- siteLabel={siteLabel}
138
- token={token}
139
- siteAction={siteAction}
140
- />
141
- )}
142
- </Container>
143
- </header>
125
+ <>
126
+ <SlotRenderer name="aboveHeader" content={content} navRoot={navRoot} />
127
+ <header
128
+ className={cx('header-wrapper', { 'intranet-header': intranetHeader })}
129
+ >
130
+ <Container layout>
131
+ {intranetHeader ? (
132
+ <IntranetHeader
133
+ pathname={pathname}
134
+ siteLabel={siteLabel}
135
+ token={token}
136
+ siteAction={siteAction}
137
+ />
138
+ ) : (
139
+ <InternetHeader
140
+ pathname={pathname}
141
+ siteLabel={siteLabel}
142
+ token={token}
143
+ siteAction={siteAction}
144
+ />
145
+ )}
146
+ </Container>
147
+ </header>
148
+ </>
144
149
  );
145
150
  };
146
151
 
@@ -1,16 +1,20 @@
1
+ /**
2
+ * Language selector component.
3
+ * @module components/LanguageSelector/LanguageSelector
4
+ */
5
+
1
6
  import React from 'react';
2
7
  import PropTypes from 'prop-types';
3
8
  import { Link } from 'react-router-dom';
9
+
4
10
  import { useSelector } from 'react-redux';
5
11
  import cx from 'classnames';
6
12
  import { find, map } from 'lodash';
7
13
 
8
- import {
9
- Helmet,
10
- langmap,
11
- flattenToAppURL,
12
- toReactIntlLang,
13
- } from '@plone/volto/helpers';
14
+ import Helmet from '@plone/volto/helpers/Helmet/Helmet';
15
+ import langmap from '@plone/volto/helpers/LanguageMap/LanguageMap';
16
+ import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
17
+ import { toReactIntlLang } from '@plone/volto/helpers/Utils/Utils';
14
18
 
15
19
  import config from '@plone/volto/registry';
16
20
 
@@ -49,7 +53,7 @@ const LanguageSelector = (props) => {
49
53
  }}
50
54
  key={`language-selector-${lang}`}
51
55
  >
52
- {langmap[lang].nativeName.slice(0, 2)}
56
+ {langmap[lang].nativeName}
53
57
  </Link>
54
58
  );
55
59
  })}