@kitconcept/volto-light-theme 8.0.0-alpha.27 → 8.0.0-alpha.29
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.
- package/.changelog.draft +26 -1
- package/CHANGELOG.md +34 -0
- package/locales/af/LC_MESSAGES/volto.po +645 -0
- package/locales/ar/LC_MESSAGES/volto.po +645 -0
- package/locales/bg/LC_MESSAGES/volto.po +645 -0
- package/locales/bn/LC_MESSAGES/volto.po +645 -0
- package/locales/ca/LC_MESSAGES/volto.po +645 -0
- package/locales/cs/LC_MESSAGES/volto.po +645 -0
- package/locales/cy/LC_MESSAGES/volto.po +645 -0
- package/locales/da/LC_MESSAGES/volto.po +645 -0
- package/locales/de/LC_MESSAGES/volto.po +58 -57
- package/locales/el/LC_MESSAGES/volto.po +645 -0
- package/locales/en_AU/LC_MESSAGES/volto.po +645 -0
- package/locales/en_GB/LC_MESSAGES/volto.po +645 -0
- package/locales/eo/LC_MESSAGES/volto.po +645 -0
- package/locales/es/LC_MESSAGES/volto.po +50 -50
- package/locales/et/LC_MESSAGES/volto.po +645 -0
- package/locales/eu/LC_MESSAGES/volto.po +7 -7
- package/locales/fa/LC_MESSAGES/volto.po +645 -0
- package/locales/fi/LC_MESSAGES/volto.po +645 -0
- package/locales/fr/LC_MESSAGES/volto.po +645 -0
- package/locales/fu/LC_MESSAGES/volto.po +645 -0
- package/locales/ga/LC_MESSAGES/volto.po +645 -0
- package/locales/gl/LC_MESSAGES/volto.po +645 -0
- package/locales/he/LC_MESSAGES/volto.po +645 -0
- package/locales/hi/LC_MESSAGES/volto.po +645 -0
- package/locales/hr/LC_MESSAGES/volto.po +645 -0
- package/locales/hu/LC_MESSAGES/volto.po +645 -0
- package/locales/hy/LC_MESSAGES/volto.po +645 -0
- package/locales/id/LC_MESSAGES/volto.po +645 -0
- package/locales/it/LC_MESSAGES/volto.po +645 -0
- package/locales/ja/LC_MESSAGES/volto.po +645 -0
- package/locales/ka/LC_MESSAGES/volto.po +645 -0
- package/locales/kn/LC_MESSAGES/volto.po +645 -0
- package/locales/ko/LC_MESSAGES/volto.po +645 -0
- package/locales/lt/LC_MESSAGES/volto.po +645 -0
- package/locales/lv/LC_MESSAGES/volto.po +645 -0
- package/locales/mi/LC_MESSAGES/volto.po +645 -0
- package/locales/mk_MK/LC_MESSAGES/volto.po +645 -0
- package/locales/ms/LC_MESSAGES/volto.po +645 -0
- package/locales/mt/LC_MESSAGES/volto.po +645 -0
- package/locales/my/LC_MESSAGES/volto.po +645 -0
- package/locales/nl/LC_MESSAGES/volto.po +645 -0
- package/locales/nl_BE/LC_MESSAGES/volto.po +645 -0
- package/locales/nn/LC_MESSAGES/volto.po +645 -0
- package/locales/no/LC_MESSAGES/volto.po +645 -0
- package/locales/pl/LC_MESSAGES/volto.po +645 -0
- package/locales/pt/LC_MESSAGES/volto.po +645 -0
- package/locales/rm/LC_MESSAGES/volto.po +645 -0
- package/locales/ro/LC_MESSAGES/volto.po +645 -0
- package/locales/ru/LC_MESSAGES/volto.po +645 -0
- package/locales/sk/LC_MESSAGES/volto.po +645 -0
- package/locales/sl/LC_MESSAGES/volto.po +645 -0
- package/locales/sm/LC_MESSAGES/volto.po +645 -0
- package/locales/sq/LC_MESSAGES/volto.po +645 -0
- package/locales/sr/LC_MESSAGES/volto.po +645 -0
- package/locales/sr_Cyrl/LC_MESSAGES/volto.po +645 -0
- package/locales/sr_Latn/LC_MESSAGES/volto.po +645 -0
- package/locales/sv/LC_MESSAGES/volto.po +645 -0
- package/locales/sw/LC_MESSAGES/volto.po +645 -0
- package/locales/ta/LC_MESSAGES/volto.po +645 -0
- package/locales/te/LC_MESSAGES/volto.po +645 -0
- package/locales/th/LC_MESSAGES/volto.po +645 -0
- package/locales/tl/LC_MESSAGES/volto.po +645 -0
- package/locales/to/LC_MESSAGES/volto.po +645 -0
- package/locales/tr/LC_MESSAGES/volto.po +645 -0
- package/locales/uk/LC_MESSAGES/volto.po +645 -0
- package/locales/vi/LC_MESSAGES/volto.po +645 -0
- package/locales/zh_CN/LC_MESSAGES/volto.po +645 -0
- package/locales/zh_HK/LC_MESSAGES/volto.po +645 -0
- package/locales/zh_TW/LC_MESSAGES/volto.po +645 -0
- package/package.json +5 -5
- package/src/components/Blocks/Button/schema.js +12 -0
- package/src/components/Blocks/Image/Edit.jsx +8 -32
- package/src/components/Blocks/Image/View.jsx +9 -26
- package/src/components/Blocks/Image/adapter.js +28 -14
- package/src/components/Blocks/Image/adapter.test.js +156 -0
- package/src/components/Blocks/Image/schema.js +21 -7
- package/src/components/Blocks/Listing/GridTemplate.jsx +1 -0
- package/src/components/Blocks/Listing/SummaryTemplate.jsx +1 -0
- package/src/components/Blocks/Maps/MapsSidebar.jsx +68 -0
- package/src/components/Blocks/Maps/View.jsx +37 -0
- package/src/components/Blocks/Maps/adapter.js +27 -0
- package/src/components/Blocks/Maps/adapter.test.js +63 -0
- package/src/components/Blocks/Maps/schema.js +42 -2
- package/src/components/Blocks/Separator/schema.js +12 -0
- package/src/components/Blocks/Teaser/DefaultBody.tsx +10 -1
- package/src/components/Blocks/Video/VideoSidebar.jsx +68 -0
- package/src/components/Blocks/Video/View.jsx +38 -0
- package/src/components/Blocks/Video/adapter.js +28 -0
- package/src/components/Blocks/Video/adapter.test.js +63 -0
- package/src/components/Blocks/Video/schema.js +42 -2
- package/src/components/Footer/Footer.tsx +2 -2
- package/src/components/Footer/slots/FollowUsLogoAndLinks.tsx +12 -23
- package/src/components/Theme/ImageView.jsx +8 -1
- package/src/components/Widgets/ObjectList.tsx +37 -27
- package/src/config/blocks.tsx +63 -0
- package/src/config/classExtenders.ts +11 -10
- package/src/config/settings.ts +6 -0
- package/src/customizations/volto/components/manage/Blocks/Maps/MapsSidebar.jsx +10 -0
- package/src/customizations/volto/components/manage/Blocks/Maps/View.jsx +10 -0
- package/src/customizations/volto/components/manage/Blocks/Video/VideoSidebar.jsx +10 -0
- package/src/customizations/volto/components/manage/Blocks/Video/View.jsx +10 -0
- package/src/index.ts +8 -0
- package/src/primitives/Card/Card.tsx +4 -1
- package/src/theme/_bgcolor-blocks-layout.scss +1 -1
- package/src/theme/_footer.scss +61 -51
- package/src/theme/_layout.scss +7 -62
- package/src/theme/_typo-custom.scss +1 -1
- package/src/theme/_variables.scss +21 -0
- package/src/theme/blocks/_grid.scss +1 -0
- package/src/theme/blocks/_highlight.scss +10 -7
- package/src/theme/blocks/_image.scss +96 -186
- package/src/theme/blocks/_listing.scss +5 -1
- package/src/theme/blocks/_maps.scss +60 -34
- package/src/transforms/to6.ts +5 -49
- package/src/transforms/to8.test.js +201 -0
- package/src/transforms/to8.ts +109 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useContext } from 'react';
|
|
1
2
|
import { useSelector } from 'react-redux';
|
|
2
3
|
import type { GetSiteResponse } from '@plone/types';
|
|
3
4
|
import { isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
@@ -5,6 +6,7 @@ import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/Def
|
|
|
5
6
|
import type { SummaryComponentType } from '@kitconcept/volto-light-theme/components/Summary/DefaultSummary';
|
|
6
7
|
import Card from '../../../primitives/Card/Card';
|
|
7
8
|
import config from '@plone/volto/registry';
|
|
9
|
+
import { GridContext } from '@plone/volto/components/manage/Blocks/Grid/context';
|
|
8
10
|
|
|
9
11
|
type FormState = {
|
|
10
12
|
site: { data: GetSiteResponse };
|
|
@@ -15,7 +17,13 @@ const TeaserDefaultTemplate = (props) => {
|
|
|
15
17
|
(state) => state.site?.data,
|
|
16
18
|
);
|
|
17
19
|
const hideProfileLinks = site?.['kitconcept.disable_profile_links'];
|
|
18
|
-
const { data, isEditMode } = props;
|
|
20
|
+
const { data, isEditMode, isContainer } = props;
|
|
21
|
+
const columns = useContext(GridContext);
|
|
22
|
+
const sizes = config.blocks.blocksConfig.teaser?.getSizes?.({
|
|
23
|
+
data,
|
|
24
|
+
inGrid: isContainer,
|
|
25
|
+
columns,
|
|
26
|
+
});
|
|
19
27
|
const href = data.href?.[0] || {};
|
|
20
28
|
const image = data.preview_image?.[0];
|
|
21
29
|
const url = data.preview_image?.[0]?.['@id'];
|
|
@@ -50,6 +58,7 @@ const TeaserDefaultTemplate = (props) => {
|
|
|
50
58
|
item={!data.overwrite ? href : { ...href, ...localOverrides }}
|
|
51
59
|
image={data.overwrite ? image : undefined}
|
|
52
60
|
imageComponent={Image}
|
|
61
|
+
sizes={sizes}
|
|
53
62
|
/>
|
|
54
63
|
<Card.Summary>
|
|
55
64
|
<Summary
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { VideoBlockSchema } from '@plone/volto/components/manage/Blocks/Video/schema';
|
|
3
|
+
import { Segment } from 'semantic-ui-react';
|
|
4
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
5
|
+
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
6
|
+
import { BlockDataForm } from '@plone/volto/components/manage/Form';
|
|
7
|
+
import videoSVG from '@plone/volto/icons/videocamera.svg';
|
|
8
|
+
|
|
9
|
+
const messages = defineMessages({
|
|
10
|
+
Video: {
|
|
11
|
+
id: 'Video',
|
|
12
|
+
defaultMessage: 'Video',
|
|
13
|
+
},
|
|
14
|
+
NoVideo: {
|
|
15
|
+
id: 'No Video selected',
|
|
16
|
+
defaultMessage: 'No Video selected',
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const VideoSidebar = (props) => {
|
|
21
|
+
const {
|
|
22
|
+
blocksConfig,
|
|
23
|
+
blocksErrors,
|
|
24
|
+
data,
|
|
25
|
+
block,
|
|
26
|
+
onChangeBlock,
|
|
27
|
+
navRoot,
|
|
28
|
+
contentType,
|
|
29
|
+
} = props;
|
|
30
|
+
const intl = useIntl();
|
|
31
|
+
const schema = VideoBlockSchema({ ...props, intl });
|
|
32
|
+
const dataAdapter = blocksConfig[data['@type']].dataAdapter;
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<>
|
|
36
|
+
{!data.url ? (
|
|
37
|
+
<Segment className="sidebar-metadata-container" secondary>
|
|
38
|
+
{intl.formatMessage(messages.NoVideo)}
|
|
39
|
+
<Icon name={videoSVG} size="100px" color="#b8c6c8" />
|
|
40
|
+
</Segment>
|
|
41
|
+
) : (
|
|
42
|
+
<BlockDataForm
|
|
43
|
+
schema={schema}
|
|
44
|
+
title={intl.formatMessage(messages.Video)}
|
|
45
|
+
// START CUSTOMIZATION
|
|
46
|
+
onChangeField={(id, value) => {
|
|
47
|
+
dataAdapter({
|
|
48
|
+
block,
|
|
49
|
+
data,
|
|
50
|
+
id,
|
|
51
|
+
onChangeBlock,
|
|
52
|
+
value,
|
|
53
|
+
});
|
|
54
|
+
}}
|
|
55
|
+
// END CUSTOMIZATION
|
|
56
|
+
onChangeBlock={onChangeBlock}
|
|
57
|
+
formData={data}
|
|
58
|
+
block={block}
|
|
59
|
+
navRoot={navRoot}
|
|
60
|
+
contentType={contentType}
|
|
61
|
+
errors={blocksErrors}
|
|
62
|
+
/>
|
|
63
|
+
)}
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export default VideoSidebar;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* View video block.
|
|
3
|
+
* @module components/manage/Blocks/Video/View
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import PropTypes from 'prop-types';
|
|
8
|
+
import Body from '@plone/volto/components/manage/Blocks/Video/Body';
|
|
9
|
+
import { withBlockExtensions } from '@plone/volto/helpers/Extensions';
|
|
10
|
+
import cx from 'classnames';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* View video block class.
|
|
14
|
+
* @class View
|
|
15
|
+
* @extends Component
|
|
16
|
+
*/
|
|
17
|
+
const View = (props) => {
|
|
18
|
+
const { data, className, style } = props;
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
// START CUSTOMIZATION
|
|
22
|
+
<div className={cx('block video', className)} style={style}>
|
|
23
|
+
{/* // END CUSTOMIZATION */}
|
|
24
|
+
<Body data={data} />
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Property types.
|
|
31
|
+
* @property {Object} propTypes Property types.
|
|
32
|
+
* @static
|
|
33
|
+
*/
|
|
34
|
+
View.propTypes = {
|
|
35
|
+
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export default withBlockExtensions(View);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const VideoBlockDataAdapter = ({
|
|
2
|
+
block,
|
|
3
|
+
data,
|
|
4
|
+
id,
|
|
5
|
+
item,
|
|
6
|
+
onChangeBlock,
|
|
7
|
+
value,
|
|
8
|
+
}) => {
|
|
9
|
+
let dataSaved = {
|
|
10
|
+
...data,
|
|
11
|
+
[id]: value,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const align = dataSaved.styles?.['align:noprefix'];
|
|
15
|
+
const isFloating = align === 'left' || align === 'right';
|
|
16
|
+
|
|
17
|
+
if (isFloating) {
|
|
18
|
+
dataSaved = {
|
|
19
|
+
...dataSaved,
|
|
20
|
+
styles: {
|
|
21
|
+
...dataSaved.styles,
|
|
22
|
+
'blockWidth:noprefix': 'default',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onChangeBlock(block, dataSaved);
|
|
28
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
+
import { VideoBlockDataAdapter } from './adapter';
|
|
3
|
+
|
|
4
|
+
const alignLeft = { 'align:noprefix': 'left' };
|
|
5
|
+
const alignCenter = { 'align:noprefix': 'center' };
|
|
6
|
+
|
|
7
|
+
describe('VideoBlockDataAdapter', () => {
|
|
8
|
+
it('applies the default width for a floating video', () => {
|
|
9
|
+
const onChangeBlock = vi.fn();
|
|
10
|
+
|
|
11
|
+
VideoBlockDataAdapter({
|
|
12
|
+
block: 'block-1',
|
|
13
|
+
data: { '@type': 'video', styles: { ...alignLeft } },
|
|
14
|
+
id: 'url',
|
|
15
|
+
onChangeBlock,
|
|
16
|
+
value: 'https://example.com/video',
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
|
|
20
|
+
'@type': 'video',
|
|
21
|
+
url: 'https://example.com/video',
|
|
22
|
+
styles: {
|
|
23
|
+
...alignLeft,
|
|
24
|
+
'blockWidth:noprefix': 'default',
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('leaves the styles untouched for a non-floating video', () => {
|
|
30
|
+
const onChangeBlock = vi.fn();
|
|
31
|
+
|
|
32
|
+
VideoBlockDataAdapter({
|
|
33
|
+
block: 'block-1',
|
|
34
|
+
data: { '@type': 'video', styles: { ...alignCenter } },
|
|
35
|
+
id: 'url',
|
|
36
|
+
onChangeBlock,
|
|
37
|
+
value: 'https://example.com/video',
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
|
|
41
|
+
'@type': 'video',
|
|
42
|
+
url: 'https://example.com/video',
|
|
43
|
+
styles: { ...alignCenter },
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('leaves the styles untouched when no alignment is set', () => {
|
|
48
|
+
const onChangeBlock = vi.fn();
|
|
49
|
+
|
|
50
|
+
VideoBlockDataAdapter({
|
|
51
|
+
block: 'block-1',
|
|
52
|
+
data: { '@type': 'video' },
|
|
53
|
+
id: 'url',
|
|
54
|
+
onChangeBlock,
|
|
55
|
+
value: 'https://example.com/video',
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
|
|
59
|
+
'@type': 'video',
|
|
60
|
+
url: 'https://example.com/video',
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
});
|
|
@@ -1,5 +1,45 @@
|
|
|
1
|
+
import config from '@plone/volto/registry';
|
|
2
|
+
import { defineMessages } from 'react-intl';
|
|
3
|
+
import { addStyling } from '@plone/volto/helpers/Extensions/withBlockSchemaEnhancer';
|
|
4
|
+
|
|
5
|
+
const messages = defineMessages({
|
|
6
|
+
BlockWidth: {
|
|
7
|
+
id: 'Block Width',
|
|
8
|
+
defaultMessage: 'Block Width',
|
|
9
|
+
},
|
|
10
|
+
Alignment: {
|
|
11
|
+
id: 'Alignment',
|
|
12
|
+
defaultMessage: 'Alignment',
|
|
13
|
+
},
|
|
14
|
+
});
|
|
1
15
|
export const videoBlockSchemaEnhancer = ({ formData, schema, intl }) => {
|
|
2
|
-
schema
|
|
3
|
-
|
|
16
|
+
addStyling({ schema, intl });
|
|
17
|
+
|
|
18
|
+
schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter(
|
|
19
|
+
(f) => f !== 'align',
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
const align = formData.styles?.['align:noprefix'];
|
|
23
|
+
const isFloating = align === 'left' || align === 'right';
|
|
24
|
+
|
|
25
|
+
schema.properties.styles.schema.fieldsets[0].fields = [
|
|
26
|
+
'align:noprefix',
|
|
27
|
+
'blockWidth:noprefix',
|
|
28
|
+
...schema.properties.styles.schema.fieldsets[0].fields,
|
|
29
|
+
];
|
|
30
|
+
schema.properties.styles.schema.properties['align:noprefix'] = {
|
|
31
|
+
widget: 'blockAlignment',
|
|
32
|
+
title: intl.formatMessage(messages.Alignment),
|
|
33
|
+
default: 'center',
|
|
34
|
+
actions: config.blocks.alignments.map((alignment) => alignment.name),
|
|
35
|
+
};
|
|
36
|
+
schema.properties.styles.schema.properties['blockWidth:noprefix'] = {
|
|
37
|
+
widget: 'blockWidth',
|
|
38
|
+
title: intl.formatMessage(messages.BlockWidth),
|
|
39
|
+
default: 'default',
|
|
40
|
+
actions: config.blocks.widths.map((width) => width.name),
|
|
41
|
+
};
|
|
42
|
+
schema.properties.styles.schema.properties['blockWidth:noprefix'].disabled =
|
|
43
|
+
isFloating;
|
|
4
44
|
return schema;
|
|
5
45
|
};
|
|
@@ -20,9 +20,9 @@ const Footer = () => {
|
|
|
20
20
|
|
|
21
21
|
return (
|
|
22
22
|
<footer id="footer">
|
|
23
|
-
<
|
|
23
|
+
<Container className="pre-footer">
|
|
24
24
|
<SlotRenderer name="preFooter" content={content} />
|
|
25
|
-
</
|
|
25
|
+
</Container>
|
|
26
26
|
<SlotRenderer name="footer" content={content} />
|
|
27
27
|
<Container className="post-footer">
|
|
28
28
|
<SlotRenderer name="postFooter" content={content} />
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { FormattedMessage } from 'react-intl';
|
|
2
|
-
import cx from 'classnames';
|
|
3
2
|
import { flattenToAppURL } from '@plone/volto/helpers/Url/Url';
|
|
4
3
|
import ConditionalLink from '@plone/volto/components/manage/ConditionalLink/ConditionalLink';
|
|
5
4
|
import { Container } from '@plone/components';
|
|
@@ -34,27 +33,12 @@ const FollowUsPostFooterLogoAndLinks = ({ content }: { content: Content }) => {
|
|
|
34
33
|
: flattenToAppURL(post_footer_logo?.download);
|
|
35
34
|
|
|
36
35
|
return content ? (
|
|
37
|
-
<Container
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
{social_links?.length > 0 && (
|
|
44
|
-
<div className="follow-us">
|
|
45
|
-
<span>
|
|
46
|
-
<FormattedMessage id="Follow us:" defaultMessage="Follow us:" />
|
|
47
|
-
</span>
|
|
48
|
-
<SlotRenderer name="followUs" content={content} />
|
|
49
|
-
</div>
|
|
50
|
-
)}
|
|
51
|
-
{footer_links?.length > 0 && (
|
|
52
|
-
<div className="footer-links">
|
|
53
|
-
<SlotRenderer name="footerLinks" content={content} />
|
|
54
|
-
<LinkList links={footer_links} />
|
|
55
|
-
</div>
|
|
56
|
-
)}
|
|
57
|
-
</div>
|
|
36
|
+
<Container className="default follow-us-links-and-logo">
|
|
37
|
+
{social_links?.length > 0 && (
|
|
38
|
+
<div className="follow-us">
|
|
39
|
+
<SlotRenderer name="followUs" content={content} />
|
|
40
|
+
</div>
|
|
41
|
+
)}
|
|
58
42
|
{post_footer_logo?.data || post_footer_logo?.download ? (
|
|
59
43
|
<div className="footer-logo">
|
|
60
44
|
<span>
|
|
@@ -63,7 +47,6 @@ const FollowUsPostFooterLogoAndLinks = ({ content }: { content: Content }) => {
|
|
|
63
47
|
defaultMessage="Sponsored by:"
|
|
64
48
|
/>
|
|
65
49
|
</span>
|
|
66
|
-
{/* @ts-ignore */}
|
|
67
50
|
<ConditionalLink
|
|
68
51
|
condition={content?.post_footer_logo_link}
|
|
69
52
|
to={content?.post_footer_logo_link}
|
|
@@ -73,6 +56,12 @@ const FollowUsPostFooterLogoAndLinks = ({ content }: { content: Content }) => {
|
|
|
73
56
|
</ConditionalLink>
|
|
74
57
|
</div>
|
|
75
58
|
) : null}
|
|
59
|
+
{footer_links?.length > 0 && (
|
|
60
|
+
<div className="footer-links">
|
|
61
|
+
<SlotRenderer name="footerLinks" content={content} />
|
|
62
|
+
<LinkList links={footer_links} />
|
|
63
|
+
</div>
|
|
64
|
+
)}
|
|
76
65
|
</Container>
|
|
77
66
|
) : null;
|
|
78
67
|
};
|
|
@@ -23,6 +23,7 @@ const ImageView = ({ content }) => {
|
|
|
23
23
|
const Image = config.getComponent('Image').component;
|
|
24
24
|
const Container =
|
|
25
25
|
config.getComponent({ name: 'Container' }).component || SemanticContainer;
|
|
26
|
+
const width = config.settings.layout.defaultContainerWidth;
|
|
26
27
|
|
|
27
28
|
return (
|
|
28
29
|
<Container id="page-document" className="view-wrapper image-view">
|
|
@@ -30,7 +31,13 @@ const ImageView = ({ content }) => {
|
|
|
30
31
|
<h1 className="documentFirstHeading">{content.title}</h1>
|
|
31
32
|
{content?.image?.download && (
|
|
32
33
|
<figure>
|
|
33
|
-
<Image
|
|
34
|
+
<Image
|
|
35
|
+
item={content}
|
|
36
|
+
imageField="image"
|
|
37
|
+
alt=""
|
|
38
|
+
responsive={true}
|
|
39
|
+
sizes={`(max-width: ${width}px) 100vw, ${width}px`}
|
|
40
|
+
/>
|
|
34
41
|
<Caption
|
|
35
42
|
title={content.title}
|
|
36
43
|
description={content.description}
|
|
@@ -16,10 +16,11 @@ import deleteSVG from '@plone/volto/icons/delete.svg';
|
|
|
16
16
|
import addSVG from '@plone/volto/icons/add.svg';
|
|
17
17
|
import dragSVG from '@plone/volto/icons/drag.svg';
|
|
18
18
|
import { v4 as uuid } from 'uuid';
|
|
19
|
-
import type {
|
|
19
|
+
import type { Content, JSONSchema } from '@plone/types';
|
|
20
20
|
import type { IntlShape } from 'react-intl';
|
|
21
21
|
import config from '@plone/volto/registry';
|
|
22
22
|
import isEmpty from 'lodash/isEmpty';
|
|
23
|
+
import { type DragEndEvent } from '@dnd-kit/core';
|
|
23
24
|
|
|
24
25
|
const messages = defineMessages({
|
|
25
26
|
labelRemoveItem: {
|
|
@@ -114,11 +115,22 @@ export type ObjectListWidgetProps = {
|
|
|
114
115
|
*/
|
|
115
116
|
schemaEnhancer?: (args: {
|
|
116
117
|
schema: JSONSchema & { addMessage: string };
|
|
117
|
-
formData:
|
|
118
|
+
formData: object;
|
|
118
119
|
intl: IntlShape;
|
|
119
|
-
navRoot
|
|
120
|
-
contentType
|
|
120
|
+
navRoot?: Content;
|
|
121
|
+
contentType?: string;
|
|
121
122
|
}) => JSONSchema;
|
|
123
|
+
/**
|
|
124
|
+
* Another optional function to enhance the schema.
|
|
125
|
+
* (Deprecated API with fewer supported arguments.
|
|
126
|
+
* This is here for backwards-compatibility
|
|
127
|
+
* with the ObjectListWidget in Volto.)
|
|
128
|
+
*/
|
|
129
|
+
schemaExtender?: (
|
|
130
|
+
schema: JSONSchema,
|
|
131
|
+
formData: object,
|
|
132
|
+
intl: IntlShape,
|
|
133
|
+
) => JSONSchema;
|
|
122
134
|
};
|
|
123
135
|
|
|
124
136
|
const EMPTY_SCHEMA = {
|
|
@@ -141,14 +153,16 @@ const ObjectListWidget = (props: ObjectListWidgetProps) => {
|
|
|
141
153
|
value = [],
|
|
142
154
|
onChange,
|
|
143
155
|
schemaEnhancer,
|
|
156
|
+
schemaExtender,
|
|
144
157
|
schemaName,
|
|
145
158
|
} = props;
|
|
146
159
|
|
|
147
160
|
const schema =
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
161
|
+
(schemaName &&
|
|
162
|
+
config.getUtility({
|
|
163
|
+
type: 'schema',
|
|
164
|
+
name: schemaName,
|
|
165
|
+
}).method) ||
|
|
152
166
|
props.schema ||
|
|
153
167
|
EMPTY_SCHEMA;
|
|
154
168
|
|
|
@@ -170,7 +184,7 @@ const ObjectListWidget = (props: ObjectListWidgetProps) => {
|
|
|
170
184
|
|
|
171
185
|
const intl = useIntl();
|
|
172
186
|
|
|
173
|
-
function handleChangeActiveObject(index) {
|
|
187
|
+
function handleChangeActiveObject(index: number) {
|
|
174
188
|
const newIndex = activeObject === index ? -1 : index;
|
|
175
189
|
|
|
176
190
|
setActiveObject(newIndex);
|
|
@@ -178,13 +192,22 @@ const ObjectListWidget = (props: ObjectListWidgetProps) => {
|
|
|
178
192
|
|
|
179
193
|
const objectSchema =
|
|
180
194
|
typeof schema === 'function' ? schema({ ...props, activeObject }) : schema;
|
|
195
|
+
const getEnhancedSchema = (data: object) => {
|
|
196
|
+
const enhancedSchema = schemaEnhancer
|
|
197
|
+
? schemaEnhancer({ schema: objectSchema, formData: data, intl })
|
|
198
|
+
: objectSchema;
|
|
199
|
+
const extendedSchema = schemaExtender
|
|
200
|
+
? schemaExtender(objectSchema, data, intl)
|
|
201
|
+
: enhancedSchema;
|
|
202
|
+
return extendedSchema;
|
|
203
|
+
};
|
|
181
204
|
|
|
182
|
-
function handleDragEnd(event) {
|
|
205
|
+
function handleDragEnd(event: DragEndEvent) {
|
|
183
206
|
const { active, over } = event;
|
|
184
207
|
|
|
185
|
-
if (active.id !== over
|
|
208
|
+
if (active.id !== over?.id) {
|
|
186
209
|
const source = value.findIndex((item) => item['@id'] === active.id);
|
|
187
|
-
const destination = value.findIndex((item) => item['@id'] === over
|
|
210
|
+
const destination = value.findIndex((item) => item['@id'] === over?.id);
|
|
188
211
|
|
|
189
212
|
const newValue = reorderArray(value, source, destination);
|
|
190
213
|
onChange(id, newValue);
|
|
@@ -205,13 +228,9 @@ const ObjectListWidget = (props: ObjectListWidgetProps) => {
|
|
|
205
228
|
'@id': uuid(),
|
|
206
229
|
};
|
|
207
230
|
|
|
208
|
-
const objSchema = schemaEnhancer
|
|
209
|
-
? // @ts-ignore - TODO Make sure this continues to have sense
|
|
210
|
-
schemaEnhancer({ schema: objectSchema, formData: data, intl })
|
|
211
|
-
: objectSchema;
|
|
212
231
|
const dataWithDefaults = applySchemaDefaults({
|
|
213
232
|
data,
|
|
214
|
-
schema:
|
|
233
|
+
schema: getEnhancedSchema(data),
|
|
215
234
|
intl,
|
|
216
235
|
});
|
|
217
236
|
|
|
@@ -318,16 +337,7 @@ const ObjectListWidget = (props: ObjectListWidgetProps) => {
|
|
|
318
337
|
id={`${uid}`}
|
|
319
338
|
key={`olw-${uid}`}
|
|
320
339
|
block={block}
|
|
321
|
-
schema={
|
|
322
|
-
schemaEnhancer
|
|
323
|
-
? // @ts-ignore - TODO Make sure this continues to have sense
|
|
324
|
-
schemaEnhancer({
|
|
325
|
-
schema: objectSchema,
|
|
326
|
-
formData: item,
|
|
327
|
-
intl,
|
|
328
|
-
})
|
|
329
|
-
: objectSchema
|
|
330
|
-
}
|
|
340
|
+
schema={getEnhancedSchema(item)}
|
|
331
341
|
value={item}
|
|
332
342
|
onChange={(fieldId: string, fieldValue: any) => {
|
|
333
343
|
const newvalue = value.map((v, i) =>
|
package/src/config/blocks.tsx
CHANGED
|
@@ -30,6 +30,8 @@ import {
|
|
|
30
30
|
standAloneImageBlockSchemaEnhancer,
|
|
31
31
|
} from '../components/Blocks/Image/schema';
|
|
32
32
|
import { ImageBlockDataAdapter } from '../components/Blocks/Image/adapter';
|
|
33
|
+
import { VideoBlockDataAdapter } from '../components/Blocks/Video/adapter';
|
|
34
|
+
import { MapsBlockDataAdapter } from '../components/Blocks/Maps/adapter';
|
|
33
35
|
|
|
34
36
|
import { AccordionSchemaEnhancer } from '../components/Blocks/Accordion/schema';
|
|
35
37
|
|
|
@@ -66,6 +68,7 @@ declare module '@plone/types' {
|
|
|
66
68
|
}
|
|
67
69
|
export interface BlockConfigBase {
|
|
68
70
|
themes?: StyleDefinition[];
|
|
71
|
+
alignments?: StyleDefinition[];
|
|
69
72
|
defaultTheme: string;
|
|
70
73
|
allowedBlocks?: string[];
|
|
71
74
|
allowed_headline_tags?: string[][];
|
|
@@ -81,6 +84,10 @@ declare module '@plone/types' {
|
|
|
81
84
|
export interface SettingsConfig {
|
|
82
85
|
blockModel?: number;
|
|
83
86
|
}
|
|
87
|
+
|
|
88
|
+
export interface BlocksConfig {
|
|
89
|
+
alignments: StyleDefinition[];
|
|
90
|
+
}
|
|
84
91
|
}
|
|
85
92
|
|
|
86
93
|
export default function install(config: ConfigType) {
|
|
@@ -147,6 +154,31 @@ export default function install(config: ConfigType) {
|
|
|
147
154
|
},
|
|
148
155
|
];
|
|
149
156
|
|
|
157
|
+
// Default block alignments
|
|
158
|
+
config.blocks.alignments = [
|
|
159
|
+
{
|
|
160
|
+
style: {
|
|
161
|
+
'--block-alignment': 'var(--align-left)',
|
|
162
|
+
},
|
|
163
|
+
name: 'left',
|
|
164
|
+
label: 'Left',
|
|
165
|
+
},
|
|
166
|
+
{
|
|
167
|
+
style: {
|
|
168
|
+
'--block-alignment': 'var(--align-center)',
|
|
169
|
+
},
|
|
170
|
+
name: 'center',
|
|
171
|
+
label: 'Center',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
style: {
|
|
175
|
+
'--block-alignment': 'var(--align-right)',
|
|
176
|
+
},
|
|
177
|
+
name: 'right',
|
|
178
|
+
label: 'Right',
|
|
179
|
+
},
|
|
180
|
+
];
|
|
181
|
+
|
|
150
182
|
config.registerUtility({
|
|
151
183
|
name: 'blockThemesEnhancer',
|
|
152
184
|
type: 'styleWrapperStyleObjectEnhancer',
|
|
@@ -159,6 +191,20 @@ export default function install(config: ConfigType) {
|
|
|
159
191
|
method: styleDefinitionsEnhancer,
|
|
160
192
|
});
|
|
161
193
|
|
|
194
|
+
config.registerUtility({
|
|
195
|
+
name: 'align:noprefix',
|
|
196
|
+
type: 'styleFieldDefinition',
|
|
197
|
+
method: ({ data }: { data: { '@type'?: string } }) =>
|
|
198
|
+
config.blocks.blocksConfig?.[data?.['@type'] ?? '']?.alignments ||
|
|
199
|
+
config.blocks.alignments,
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
config.registerUtility({
|
|
203
|
+
name: 'blockWidth:noprefix',
|
|
204
|
+
type: 'styleFieldDefinition',
|
|
205
|
+
method: () => config.blocks.widths,
|
|
206
|
+
});
|
|
207
|
+
|
|
162
208
|
// No required blocks except eventMetadata
|
|
163
209
|
config.blocks.requiredBlocks = [
|
|
164
210
|
...config.blocks.requiredBlocks,
|
|
@@ -323,15 +369,25 @@ export default function install(config: ConfigType) {
|
|
|
323
369
|
category: 'title',
|
|
324
370
|
};
|
|
325
371
|
|
|
372
|
+
const getTeaserSizes = ({ inGrid = false, columns = 1 } = {}) => {
|
|
373
|
+
const { defaultContainerWidth, tabletBreakpoint } = config.settings.layout;
|
|
374
|
+
const desktopWidth = Math.floor(
|
|
375
|
+
defaultContainerWidth / (inGrid ? columns : 2),
|
|
376
|
+
);
|
|
377
|
+
return `(max-width: ${tabletBreakpoint}px) 100vw, ${desktopWidth}px`;
|
|
378
|
+
};
|
|
379
|
+
|
|
326
380
|
config.blocks.blocksConfig.teaser = {
|
|
327
381
|
...config.blocks.blocksConfig.teaser,
|
|
328
382
|
group: 'teasers',
|
|
329
383
|
imageScale: 'larger',
|
|
384
|
+
getSizes: getTeaserSizes,
|
|
330
385
|
schemaEnhancer: composeSchema(defaultStylingSchema, teaserSchemaEnhancer),
|
|
331
386
|
};
|
|
332
387
|
|
|
333
388
|
config.blocks.blocksConfig.video = {
|
|
334
389
|
...config.blocks.blocksConfig.video,
|
|
390
|
+
dataAdapter: VideoBlockDataAdapter,
|
|
335
391
|
schemaEnhancer: composeSchema(
|
|
336
392
|
defaultStylingSchema,
|
|
337
393
|
videoBlockSchemaEnhancer,
|
|
@@ -339,6 +395,7 @@ export default function install(config: ConfigType) {
|
|
|
339
395
|
};
|
|
340
396
|
config.blocks.blocksConfig.maps = {
|
|
341
397
|
...config.blocks.blocksConfig.maps,
|
|
398
|
+
dataAdapter: MapsBlockDataAdapter,
|
|
342
399
|
schemaEnhancer: composeSchema(
|
|
343
400
|
defaultStylingSchema,
|
|
344
401
|
mapsBlockSchemaEnhancer,
|
|
@@ -410,5 +467,11 @@ export default function install(config: ConfigType) {
|
|
|
410
467
|
schemaEnhancer: sliderBlockSchemaEnhancer,
|
|
411
468
|
};
|
|
412
469
|
|
|
470
|
+
// Highlight Block
|
|
471
|
+
config.blocks.blocksConfig.highlight = {
|
|
472
|
+
...config.blocks.blocksConfig.highlight,
|
|
473
|
+
schemaEnhancer: defaultStylingSchema,
|
|
474
|
+
};
|
|
475
|
+
|
|
413
476
|
return config;
|
|
414
477
|
}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { ConfigType } from '@plone/registry';
|
|
2
2
|
import { getPreviousNextBlock } from '@plone/volto/helpers/Blocks/Blocks';
|
|
3
|
-
import { getCurrentStyleByName } from '../helpers/helpers';
|
|
4
3
|
|
|
5
4
|
export default function install(config: ConfigType) {
|
|
6
5
|
// Register custom StyleWrapper ClassNames
|
|
@@ -71,15 +70,17 @@ export default function install(config: ConfigType) {
|
|
|
71
70
|
config.settings.styleClassNameExtenders.push(
|
|
72
71
|
({ data, classNames }: { data: any; classNames: Array<string> }) => {
|
|
73
72
|
const currentBlockWidth =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
73
|
+
data?.styles?.['blockWidth:noprefix'] || 'default';
|
|
74
|
+
return [...classNames, `has--block-width--${currentBlockWidth}`];
|
|
75
|
+
},
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// Blocks alignment convenience classes injection
|
|
79
|
+
config.settings.styleClassNameExtenders.push(
|
|
80
|
+
({ data, classNames }: { data: any; classNames: Array<string> }) => {
|
|
81
|
+
const currentBlockAlignment =
|
|
82
|
+
data?.styles?.['align:noprefix'] || 'center';
|
|
83
|
+
return [...classNames, `has--block-alignment--${currentBlockAlignment}`];
|
|
83
84
|
},
|
|
84
85
|
);
|
|
85
86
|
|
package/src/config/settings.ts
CHANGED
|
@@ -28,6 +28,12 @@ export default function install(config: ConfigType) {
|
|
|
28
28
|
config.settings.contentMetadataTagsImageField = 'preview_image';
|
|
29
29
|
config.settings.querystringSearchGet = true;
|
|
30
30
|
|
|
31
|
+
config.settings.layout = {
|
|
32
|
+
...config.settings.layout,
|
|
33
|
+
defaultContainerWidth: 940,
|
|
34
|
+
tabletBreakpoint: 768,
|
|
35
|
+
};
|
|
36
|
+
|
|
31
37
|
config.settings.slidingSearchAnimation = true;
|
|
32
38
|
config.settings.openExternalLinkInNewTab = true;
|
|
33
39
|
|