@kitconcept/volto-light-theme 7.0.0-alpha.3 → 7.0.0-alpha.5
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 +8 -3
- package/CHANGELOG.md +18 -0
- package/package.json +5 -1
- package/src/components/Blocks/Listing/DefaultTemplate.jsx +7 -1
- package/src/components/Blocks/Listing/ListingBody.jsx +6 -8
- package/src/components/Blocks/Listing/SummaryTemplate.jsx +7 -1
- package/src/components/Blocks/Teaser/Body.tsx +53 -0
- package/src/components/Blocks/Teaser/DefaultBody.tsx +45 -0
- package/src/components/SearchWidget/IntranetSearchWidget.jsx +5 -5
- package/src/components/Summary/PersonSummary.tsx +73 -0
- package/src/config/summary.ts +6 -0
- package/src/config/widgets.ts +5 -0
- package/src/customizations/volto/components/manage/Blocks/Teaser/Body.jsx +8 -0
- package/src/index.ts +8 -0
- package/src/stories/grid.teaser.stories.tsx +80 -0
- package/src/stories/listing.stories.tsx +63 -0
- package/src/stories/mocks.ts +284 -0
- package/src/stories/static/person.png +0 -0
- package/src/stories/teaser.stories.tsx +22 -7
- package/src/theme/_footer.scss +0 -1
- package/src/theme/_layout.scss +2 -0
- package/src/theme/card.scss +1 -3
- package/src/theme/main.scss +1 -0
- package/src/theme/person.scss +123 -0
- package/src/components/Blocks/Teaser/DefaultBody.jsx +0 -81
package/.changelog.draft
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
## 7.0.0-alpha.
|
|
1
|
+
## 7.0.0-alpha.5 (2025-06-04)
|
|
2
|
+
|
|
3
|
+
### Breaking
|
|
4
|
+
|
|
5
|
+
- The `Body` Teaser component has been shadowed, including the `placeholder` in case that the Teaser is empty. @sneridagh
|
|
6
|
+
See [the upgrade guide](https://volto-light-theme.readthedocs.io/how-to-guides/upgrade-guide.html) for more information. [#555](https://github.com/kitconcept/volto-light-theme/pull/555)
|
|
2
7
|
|
|
3
8
|
### Feature
|
|
4
9
|
|
|
5
|
-
-
|
|
6
|
-
- Added
|
|
10
|
+
- Add support for Person content type in teasers, teasers in grids and listings. @sneridagh [#555](https://github.com/kitconcept/volto-light-theme/pull/555)
|
|
11
|
+
- Added string interpolation {searchTerm} in the custom searchURL in intranet header search widget. @sneridagh
|
|
7
12
|
|
|
8
13
|
|
package/CHANGELOG.md
CHANGED
|
@@ -8,6 +8,24 @@
|
|
|
8
8
|
|
|
9
9
|
<!-- towncrier release notes start -->
|
|
10
10
|
|
|
11
|
+
## 7.0.0-alpha.5 (2025-06-04)
|
|
12
|
+
|
|
13
|
+
### Breaking
|
|
14
|
+
|
|
15
|
+
- The `Body` Teaser component has been shadowed, including the `placeholder` in case that the Teaser is empty. @sneridagh
|
|
16
|
+
See [the upgrade guide](https://volto-light-theme.readthedocs.io/how-to-guides/upgrade-guide.html) for more information. [#555](https://github.com/kitconcept/volto-light-theme/pull/555)
|
|
17
|
+
|
|
18
|
+
### Feature
|
|
19
|
+
|
|
20
|
+
- Add support for Person content type in teasers, teasers in grids and listings. @sneridagh [#555](https://github.com/kitconcept/volto-light-theme/pull/555)
|
|
21
|
+
- Added string interpolation {searchTerm} in the custom searchURL in intranet header search widget. @sneridagh
|
|
22
|
+
|
|
23
|
+
## 7.0.0-alpha.4 (2025-05-22)
|
|
24
|
+
|
|
25
|
+
### Internal
|
|
26
|
+
|
|
27
|
+
- Added some of the Volto's Cypress tests. @sneridagh [#540](https://github.com/kitconcept/volto-light-theme/pull/540)
|
|
28
|
+
|
|
11
29
|
## 7.0.0-alpha.3 (2025-05-20)
|
|
12
30
|
|
|
13
31
|
### Feature
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kitconcept/volto-light-theme",
|
|
3
|
-
"version": "7.0.0-alpha.
|
|
3
|
+
"version": "7.0.0-alpha.5",
|
|
4
4
|
"description": "Volto Light Theme by kitconcept",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"types": "src/index.ts",
|
|
@@ -26,6 +26,9 @@
|
|
|
26
26
|
"publishConfig": {
|
|
27
27
|
"access": "public"
|
|
28
28
|
},
|
|
29
|
+
"addons": [
|
|
30
|
+
"@kitconcept/volto-bm3-compat"
|
|
31
|
+
],
|
|
29
32
|
"devDependencies": {
|
|
30
33
|
"@plone/scripts": "^3.6.2",
|
|
31
34
|
"@storybook/react": "^8.6.12",
|
|
@@ -47,6 +50,7 @@
|
|
|
47
50
|
"@plone/components": "^3.0.2"
|
|
48
51
|
},
|
|
49
52
|
"peerDependencies": {
|
|
53
|
+
"@kitconcept/volto-bm3-compat": "^1.0.0-alpha.1",
|
|
50
54
|
"@eeacms/volto-accordion-block": "^10.4.6",
|
|
51
55
|
"@kitconcept/volto-banner-block": "^1.0.1",
|
|
52
56
|
"@kitconcept/volto-button-block": "^4.0.0-alpha.0",
|
|
@@ -5,6 +5,7 @@ import UniversalLink from '@plone/volto/components/manage/UniversalLink/Universa
|
|
|
5
5
|
import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
6
6
|
import config from '@plone/volto/registry';
|
|
7
7
|
import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/DefaultSummary';
|
|
8
|
+
import cx from 'classnames';
|
|
8
9
|
|
|
9
10
|
const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
10
11
|
let link = null;
|
|
@@ -30,7 +31,12 @@ const DefaultTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
30
31
|
dependencies: [item['@type']],
|
|
31
32
|
}).component || DefaultSummary;
|
|
32
33
|
return (
|
|
33
|
-
<div
|
|
34
|
+
<div
|
|
35
|
+
className={cx('listing-item', {
|
|
36
|
+
[`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
|
|
37
|
+
})}
|
|
38
|
+
key={item['@id']}
|
|
39
|
+
>
|
|
34
40
|
<ConditionalLink item={item} condition={!isEditMode}>
|
|
35
41
|
<div className="listing-body">
|
|
36
42
|
<Summary item={item} HeadingTag="h2" />
|
|
@@ -35,7 +35,7 @@ const Headline = ({
|
|
|
35
35
|
);
|
|
36
36
|
};
|
|
37
37
|
|
|
38
|
-
const ListingBody =
|
|
38
|
+
export const ListingBody = (props) => {
|
|
39
39
|
const {
|
|
40
40
|
data = {},
|
|
41
41
|
isEditMode,
|
|
@@ -68,11 +68,9 @@ const ListingBody = withQuerystringResults((props) => {
|
|
|
68
68
|
ListingBodyTemplate =
|
|
69
69
|
variation?.template ?? defaultVariation?.template ?? null;
|
|
70
70
|
}
|
|
71
|
-
let galleryRef;
|
|
72
71
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
}
|
|
72
|
+
const galleryRef = useRef();
|
|
73
|
+
|
|
76
74
|
const listingRef = createRef();
|
|
77
75
|
const NoResults = variation?.noResultsComponent
|
|
78
76
|
? variation.noResultsComponent
|
|
@@ -95,7 +93,7 @@ const ListingBody = withQuerystringResults((props) => {
|
|
|
95
93
|
<ListingBodyTemplate
|
|
96
94
|
items={listingItems}
|
|
97
95
|
isEditMode={isEditMode}
|
|
98
|
-
ref={galleryRef}
|
|
96
|
+
ref={data.variation === 'imageGallery' ? galleryRef : undefined}
|
|
99
97
|
{...data}
|
|
100
98
|
{...variation}
|
|
101
99
|
/>
|
|
@@ -192,6 +190,6 @@ const ListingBody = withQuerystringResults((props) => {
|
|
|
192
190
|
)}
|
|
193
191
|
</>
|
|
194
192
|
);
|
|
195
|
-
}
|
|
193
|
+
};
|
|
196
194
|
|
|
197
|
-
export default injectIntl(ListingBody);
|
|
195
|
+
export default injectIntl(withQuerystringResults(ListingBody));
|
|
@@ -5,6 +5,7 @@ import Component from '@plone/volto/components/theme/Component/Component';
|
|
|
5
5
|
import { flattenToAppURL, isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
6
6
|
import config from '@plone/volto/registry';
|
|
7
7
|
import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/DefaultSummary';
|
|
8
|
+
import cx from 'classnames';
|
|
8
9
|
|
|
9
10
|
const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
10
11
|
let link = null;
|
|
@@ -46,7 +47,12 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
|
|
|
46
47
|
</>
|
|
47
48
|
);
|
|
48
49
|
return (
|
|
49
|
-
<div
|
|
50
|
+
<div
|
|
51
|
+
className={cx('listing-item', {
|
|
52
|
+
[`${item['@type']?.toLowerCase()}-listing`]: item['@type'],
|
|
53
|
+
})}
|
|
54
|
+
key={item['@id']}
|
|
55
|
+
>
|
|
50
56
|
<ConditionalLink item={item} condition={!isEditMode}>
|
|
51
57
|
<ItemBodyTemplate item={item} />
|
|
52
58
|
</ConditionalLink>
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import DefaultBody from './DefaultBody';
|
|
2
|
+
import { BlockWrapper } from '@kitconcept/volto-bm3-compat';
|
|
3
|
+
import config from '@plone/volto/registry';
|
|
4
|
+
import cx from 'classnames';
|
|
5
|
+
import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
|
|
6
|
+
import isEmpty from 'lodash/isEmpty';
|
|
7
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
8
|
+
|
|
9
|
+
const messages = defineMessages({
|
|
10
|
+
PleaseChooseContent: {
|
|
11
|
+
id: 'Please choose an existing content as source for this element',
|
|
12
|
+
defaultMessage:
|
|
13
|
+
'Please choose an existing content as source for this element',
|
|
14
|
+
},
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const TeaserBody = (props) => {
|
|
18
|
+
const { variation, data, className, isEditMode } = props;
|
|
19
|
+
const intl = useIntl();
|
|
20
|
+
|
|
21
|
+
const hasType = data.href?.[0]?.['@type'];
|
|
22
|
+
|
|
23
|
+
const BodyComponent =
|
|
24
|
+
(config?.getComponent &&
|
|
25
|
+
hasType &&
|
|
26
|
+
config.getComponent({ name: 'Teaser', dependencies: [hasType] })
|
|
27
|
+
.component) ||
|
|
28
|
+
variation?.template ||
|
|
29
|
+
DefaultBody;
|
|
30
|
+
|
|
31
|
+
return (
|
|
32
|
+
<BlockWrapper
|
|
33
|
+
{...props}
|
|
34
|
+
className={cx(
|
|
35
|
+
{ [`${hasType?.toLowerCase()}-teaser`]: hasType },
|
|
36
|
+
className,
|
|
37
|
+
)}
|
|
38
|
+
>
|
|
39
|
+
{isEmpty(data.href) && isEditMode ? (
|
|
40
|
+
<div className="ui message">
|
|
41
|
+
<div className="teaser-item placeholder">
|
|
42
|
+
<img src={imageBlockSVG} alt="" />
|
|
43
|
+
<p>{intl.formatMessage(messages.PleaseChooseContent)}</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
) : (
|
|
47
|
+
<BodyComponent {...props} />
|
|
48
|
+
)}
|
|
49
|
+
</BlockWrapper>
|
|
50
|
+
);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export default TeaserBody;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
2
|
+
import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/DefaultSummary';
|
|
3
|
+
import Card from '../../../primitives/Card/Card';
|
|
4
|
+
import config from '@plone/volto/registry';
|
|
5
|
+
|
|
6
|
+
const TeaserDefaultTemplate = (props) => {
|
|
7
|
+
const { data, isEditMode } = props;
|
|
8
|
+
const href = data.href?.[0] || {};
|
|
9
|
+
const image = data.preview_image?.[0];
|
|
10
|
+
const url = data.preview_image?.[0]?.['@id'];
|
|
11
|
+
|
|
12
|
+
const Image = config.getComponent('Image').component;
|
|
13
|
+
const Summary =
|
|
14
|
+
config.getComponent({
|
|
15
|
+
name: 'Summary',
|
|
16
|
+
dependencies: [href['@type']],
|
|
17
|
+
}).component || DefaultSummary;
|
|
18
|
+
const { openExternalLinkInNewTab } = config.settings;
|
|
19
|
+
const openLinkInNewTab =
|
|
20
|
+
data.openLinkInNewTab ||
|
|
21
|
+
(openExternalLinkInNewTab && !isInternalURL(href['@id']));
|
|
22
|
+
const { '@id': id, ...filteredData } = data;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Card
|
|
26
|
+
href={!isEditMode ? href['@id'] : null}
|
|
27
|
+
openLinkInNewTab={openLinkInNewTab}
|
|
28
|
+
>
|
|
29
|
+
<Card.Image
|
|
30
|
+
src={url && !image?.image_field ? url : undefined}
|
|
31
|
+
item={!data.overwrite ? href : { ...href, ...filteredData }}
|
|
32
|
+
image={data.overwrite ? image : undefined}
|
|
33
|
+
imageComponent={Image}
|
|
34
|
+
/>
|
|
35
|
+
<Card.Summary>
|
|
36
|
+
<Summary
|
|
37
|
+
item={!data.overwrite ? href : { ...href, ...filteredData }}
|
|
38
|
+
HeadingTag="h2"
|
|
39
|
+
/>
|
|
40
|
+
</Card.Summary>
|
|
41
|
+
</Card>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export default TeaserDefaultTemplate;
|
|
@@ -87,11 +87,11 @@ class IntranetSearchWidget extends Component {
|
|
|
87
87
|
: '';
|
|
88
88
|
|
|
89
89
|
if (searchURL) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
'
|
|
93
|
-
|
|
94
|
-
);
|
|
90
|
+
// If searchURL contains {searchTerm}, replace it with the encoded search text
|
|
91
|
+
const externalUrl =
|
|
92
|
+
searchURL.replace('{searchTerm}', encodeURIComponent(this.state.text)) +
|
|
93
|
+
path;
|
|
94
|
+
window.open(externalUrl, '_blank', 'noopener,noreferrer');
|
|
95
95
|
} else {
|
|
96
96
|
this.props.history.push(
|
|
97
97
|
`/search?SearchableText=${encodeURIComponent(this.state.text)}${path}`,
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import Icon from '@plone/volto/components/theme/Icon/Icon';
|
|
3
|
+
import mailSVG from '@plone/volto/icons/email.svg';
|
|
4
|
+
import locationSVG from '@plone/volto/icons/map.svg';
|
|
5
|
+
import phoneSVG from '@plone/volto/icons/mobile.svg';
|
|
6
|
+
import type { DefaultSummaryProps } from './DefaultSummary';
|
|
7
|
+
import { defineMessages, useIntl } from 'react-intl';
|
|
8
|
+
|
|
9
|
+
const messages = defineMessages({
|
|
10
|
+
phone: {
|
|
11
|
+
id: 'Phone',
|
|
12
|
+
defaultMessage: 'Phone',
|
|
13
|
+
},
|
|
14
|
+
email: {
|
|
15
|
+
id: 'eMail',
|
|
16
|
+
defaultMessage: 'eMail',
|
|
17
|
+
},
|
|
18
|
+
room: {
|
|
19
|
+
id: 'Room',
|
|
20
|
+
defaultMessage: 'Room',
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
const PersonSummary = (props: DefaultSummaryProps) => {
|
|
25
|
+
const { item, HeadingTag = 'h3', a11yLabelId, hide_description } = props;
|
|
26
|
+
const intl = useIntl();
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<>
|
|
30
|
+
{item?.head_title && <div className="headline">{item.head_title}</div>}
|
|
31
|
+
<HeadingTag className="title" id={a11yLabelId}>
|
|
32
|
+
{item.title ? item.title : item.id}
|
|
33
|
+
</HeadingTag>
|
|
34
|
+
{!hide_description && <p className="description">{item.description}</p>}
|
|
35
|
+
|
|
36
|
+
{item.contact_email && (
|
|
37
|
+
<div className="summary-extra-info">
|
|
38
|
+
<Icon
|
|
39
|
+
title={intl.formatMessage(messages.email)}
|
|
40
|
+
name={mailSVG}
|
|
41
|
+
size="24px"
|
|
42
|
+
/>
|
|
43
|
+
<a href={`mailto:${item.contact_email}`}>{item.contact_email}</a>
|
|
44
|
+
</div>
|
|
45
|
+
)}
|
|
46
|
+
|
|
47
|
+
<div className="summary-room-phone">
|
|
48
|
+
{item.contact_room && (
|
|
49
|
+
<div className="summary-extra-info">
|
|
50
|
+
<Icon
|
|
51
|
+
title={intl.formatMessage(messages.room)}
|
|
52
|
+
name={locationSVG}
|
|
53
|
+
size="24px"
|
|
54
|
+
/>
|
|
55
|
+
{item.contact_room}
|
|
56
|
+
</div>
|
|
57
|
+
)}
|
|
58
|
+
{item.contact_phone && (
|
|
59
|
+
<div className="summary-extra-info">
|
|
60
|
+
<Icon
|
|
61
|
+
title={intl.formatMessage(messages.phone)}
|
|
62
|
+
name={phoneSVG}
|
|
63
|
+
size="24px"
|
|
64
|
+
/>
|
|
65
|
+
{item.contact_phone}
|
|
66
|
+
</div>
|
|
67
|
+
)}
|
|
68
|
+
</div>
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
export default PersonSummary;
|
package/src/config/summary.ts
CHANGED
|
@@ -2,6 +2,7 @@ import type { ConfigType } from '@plone/registry';
|
|
|
2
2
|
import NewsItemSummary from '../components/Summary/NewsItemSummary';
|
|
3
3
|
import EventSummary from '../components/Summary/EventSummary';
|
|
4
4
|
import FileSummary from '../components/Summary/FileSummary';
|
|
5
|
+
import PersonSummary from '../components/Summary/PersonSummary';
|
|
5
6
|
|
|
6
7
|
export default function install(config: ConfigType) {
|
|
7
8
|
config.registerComponent({
|
|
@@ -19,6 +20,11 @@ export default function install(config: ConfigType) {
|
|
|
19
20
|
component: FileSummary,
|
|
20
21
|
dependencies: ['File'],
|
|
21
22
|
});
|
|
23
|
+
config.registerComponent({
|
|
24
|
+
name: 'Summary',
|
|
25
|
+
component: PersonSummary,
|
|
26
|
+
dependencies: ['Person'],
|
|
27
|
+
});
|
|
22
28
|
|
|
23
29
|
return config;
|
|
24
30
|
}
|
package/src/config/widgets.ts
CHANGED
|
@@ -13,6 +13,10 @@ import { footerLinksSchema } from '../components/Widgets/schema/footerLinksSchem
|
|
|
13
13
|
import { iconLinkListSchema } from '../components/Widgets/schema/iconLinkListSchema';
|
|
14
14
|
|
|
15
15
|
declare module '@plone/types' {
|
|
16
|
+
export interface WidgetsConfigById {
|
|
17
|
+
preview_image_link: React.ComponentType;
|
|
18
|
+
}
|
|
19
|
+
|
|
16
20
|
export interface WidgetsConfigByWidget {
|
|
17
21
|
themeColorSwatch: typeof ColorSwatch;
|
|
18
22
|
blockWidth: typeof BlockWidth;
|
|
@@ -20,6 +24,7 @@ declare module '@plone/types' {
|
|
|
20
24
|
size: typeof Size;
|
|
21
25
|
colorPicker: typeof ColorPicker;
|
|
22
26
|
blocksObject: typeof BlocksObject;
|
|
27
|
+
image: React.ComponentType;
|
|
23
28
|
}
|
|
24
29
|
}
|
|
25
30
|
|
package/src/index.ts
CHANGED
|
@@ -61,6 +61,14 @@ declare module '@plone/types' {
|
|
|
61
61
|
'plonegovbr.socialmedia.settings': CustomInheritBehavior<PloneGobrSocialMediaSettings>;
|
|
62
62
|
};
|
|
63
63
|
}
|
|
64
|
+
|
|
65
|
+
export interface ObjectBrowserItem {
|
|
66
|
+
contact_email: string;
|
|
67
|
+
contact_phone: string;
|
|
68
|
+
contact_room: string;
|
|
69
|
+
contact_website: string;
|
|
70
|
+
contact_building: string;
|
|
71
|
+
}
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
const applyConfig = (config: ConfigType) => {
|
|
@@ -5,6 +5,11 @@ import {
|
|
|
5
5
|
gridBlockTwo,
|
|
6
6
|
gridBlockThree,
|
|
7
7
|
gridBlockFour,
|
|
8
|
+
gridBlockTwoDocumentPerson,
|
|
9
|
+
gridBlockOnePerson,
|
|
10
|
+
gridBlockTwoPerson,
|
|
11
|
+
gridBlockThreePerson,
|
|
12
|
+
gridBlockFourPerson,
|
|
8
13
|
} from './mocks';
|
|
9
14
|
import Wrapper from '@plone/volto/storybook';
|
|
10
15
|
import BlockWrapper from './BlockWrapper';
|
|
@@ -154,3 +159,78 @@ export const FourInversed: Story = {
|
|
|
154
159
|
data: { ...gridBlockFour, theme: 'grey' },
|
|
155
160
|
},
|
|
156
161
|
};
|
|
162
|
+
|
|
163
|
+
export const OnePerson: Story = {
|
|
164
|
+
render: (args) => (
|
|
165
|
+
<Wrapper>
|
|
166
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
167
|
+
<BlockWrapper {...args}>
|
|
168
|
+
<GridBlockView {...args} />
|
|
169
|
+
</BlockWrapper>
|
|
170
|
+
</div>
|
|
171
|
+
</Wrapper>
|
|
172
|
+
),
|
|
173
|
+
args: {
|
|
174
|
+
data: gridBlockOnePerson,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
|
|
178
|
+
export const TwoDocumentPerson: Story = {
|
|
179
|
+
render: (args) => (
|
|
180
|
+
<Wrapper>
|
|
181
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
182
|
+
<BlockWrapper {...args}>
|
|
183
|
+
<GridBlockView {...args} />
|
|
184
|
+
</BlockWrapper>
|
|
185
|
+
</div>
|
|
186
|
+
</Wrapper>
|
|
187
|
+
),
|
|
188
|
+
args: {
|
|
189
|
+
data: gridBlockTwoDocumentPerson,
|
|
190
|
+
},
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export const TwoPerson: Story = {
|
|
194
|
+
render: (args) => (
|
|
195
|
+
<Wrapper>
|
|
196
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
197
|
+
<BlockWrapper {...args}>
|
|
198
|
+
<GridBlockView {...args} />
|
|
199
|
+
</BlockWrapper>
|
|
200
|
+
</div>
|
|
201
|
+
</Wrapper>
|
|
202
|
+
),
|
|
203
|
+
args: {
|
|
204
|
+
data: gridBlockTwoPerson,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
export const ThreePerson: Story = {
|
|
209
|
+
render: (args) => (
|
|
210
|
+
<Wrapper>
|
|
211
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
212
|
+
<BlockWrapper {...args}>
|
|
213
|
+
<GridBlockView {...args} />
|
|
214
|
+
</BlockWrapper>
|
|
215
|
+
</div>
|
|
216
|
+
</Wrapper>
|
|
217
|
+
),
|
|
218
|
+
args: {
|
|
219
|
+
data: gridBlockThreePerson,
|
|
220
|
+
},
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
export const FourPerson: Story = {
|
|
224
|
+
render: (args) => (
|
|
225
|
+
<Wrapper>
|
|
226
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
227
|
+
<BlockWrapper {...args}>
|
|
228
|
+
<GridBlockView {...args} />
|
|
229
|
+
</BlockWrapper>
|
|
230
|
+
</div>
|
|
231
|
+
</Wrapper>
|
|
232
|
+
),
|
|
233
|
+
args: {
|
|
234
|
+
data: gridBlockFourPerson,
|
|
235
|
+
},
|
|
236
|
+
};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ListingBody } from '../components/Blocks/Listing/ListingBody';
|
|
3
|
+
import SummaryTemplate from '../components/Blocks/Listing/SummaryTemplate';
|
|
4
|
+
import { listingBlockPerson } from './mocks';
|
|
5
|
+
import Wrapper from '@plone/volto/storybook';
|
|
6
|
+
import BlockWrapper from './BlockWrapper';
|
|
7
|
+
|
|
8
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
9
|
+
|
|
10
|
+
const meta = {
|
|
11
|
+
title: 'Blocks/Listing',
|
|
12
|
+
component: ListingBody,
|
|
13
|
+
parameters: {
|
|
14
|
+
layout: 'centered',
|
|
15
|
+
},
|
|
16
|
+
tags: ['autodocs'],
|
|
17
|
+
} satisfies Meta<typeof ListingBody>;
|
|
18
|
+
|
|
19
|
+
export default meta;
|
|
20
|
+
type Story = StoryObj<typeof meta>;
|
|
21
|
+
|
|
22
|
+
export const PersonListing: Story = {
|
|
23
|
+
render: (args) => (
|
|
24
|
+
<Wrapper>
|
|
25
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
26
|
+
<BlockWrapper {...args}>
|
|
27
|
+
<div className="block listing">
|
|
28
|
+
<ListingBody {...args} />
|
|
29
|
+
</div>
|
|
30
|
+
</BlockWrapper>
|
|
31
|
+
</div>
|
|
32
|
+
</Wrapper>
|
|
33
|
+
),
|
|
34
|
+
args: {
|
|
35
|
+
data: listingBlockPerson,
|
|
36
|
+
listingItems: listingBlockPerson.items,
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export const PersonListingSummary: Story = {
|
|
41
|
+
render: (args) => (
|
|
42
|
+
<Wrapper>
|
|
43
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
44
|
+
<BlockWrapper {...args}>
|
|
45
|
+
<div className="block listing summary">
|
|
46
|
+
<ListingBody {...args} />
|
|
47
|
+
</div>
|
|
48
|
+
</BlockWrapper>
|
|
49
|
+
</div>
|
|
50
|
+
</Wrapper>
|
|
51
|
+
),
|
|
52
|
+
args: {
|
|
53
|
+
data: {
|
|
54
|
+
...listingBlockPerson,
|
|
55
|
+
},
|
|
56
|
+
listingItems: listingBlockPerson.items,
|
|
57
|
+
variation: {
|
|
58
|
+
id: 'summary',
|
|
59
|
+
template: SummaryTemplate,
|
|
60
|
+
title: 'List with images',
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
};
|
package/src/stories/mocks.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const demoImage = 'black-starry-night.jpg';
|
|
2
|
+
const personImage = 'person.png';
|
|
2
3
|
|
|
3
4
|
export function ObjectBrowserItem(demoImage) {
|
|
4
5
|
return {
|
|
@@ -169,6 +170,98 @@ export const teaserBlock = {
|
|
|
169
170
|
title: 'Headline H2',
|
|
170
171
|
};
|
|
171
172
|
|
|
173
|
+
export const personBlock = {
|
|
174
|
+
'@type': 'teaser',
|
|
175
|
+
href: [
|
|
176
|
+
{
|
|
177
|
+
'@id': '.',
|
|
178
|
+
'@type': 'Person',
|
|
179
|
+
title: 'Kathryn Janeway',
|
|
180
|
+
Title: 'Kathryn Janeway',
|
|
181
|
+
description:
|
|
182
|
+
'USS Voyager Captain from the 24th century. She is known for her strong leadership skills and her ability to make tough decisions in difficult situations.',
|
|
183
|
+
Description:
|
|
184
|
+
'USS Voyager Captain from the 24th century. She is known for her strong leadership skills and her ability to make tough decisions in difficult situations.',
|
|
185
|
+
contact_email: 'janeway@ufp.earth.com',
|
|
186
|
+
contact_room: "Captain's Ready Room",
|
|
187
|
+
contact_phone: '123456789',
|
|
188
|
+
contact_building: 'Sapphire Building',
|
|
189
|
+
contact_website: null,
|
|
190
|
+
getRemoteUrl: null,
|
|
191
|
+
hasPreviewImage: true,
|
|
192
|
+
image_field: 'preview_image',
|
|
193
|
+
image_scales: {
|
|
194
|
+
preview_image: [
|
|
195
|
+
{
|
|
196
|
+
'content-type': 'image/jpeg',
|
|
197
|
+
download: personImage,
|
|
198
|
+
filename: 'black-starry-night.jpg',
|
|
199
|
+
height: 1708,
|
|
200
|
+
scales: {
|
|
201
|
+
great: {
|
|
202
|
+
download: personImage,
|
|
203
|
+
height: 854,
|
|
204
|
+
width: 1200,
|
|
205
|
+
},
|
|
206
|
+
huge: {
|
|
207
|
+
download: personImage,
|
|
208
|
+
height: 1138,
|
|
209
|
+
width: 1600,
|
|
210
|
+
},
|
|
211
|
+
icon: {
|
|
212
|
+
download: personImage,
|
|
213
|
+
height: 22,
|
|
214
|
+
width: 32,
|
|
215
|
+
},
|
|
216
|
+
large: {
|
|
217
|
+
download: personImage,
|
|
218
|
+
height: 569,
|
|
219
|
+
width: 800,
|
|
220
|
+
},
|
|
221
|
+
larger: {
|
|
222
|
+
download: personImage,
|
|
223
|
+
height: 711,
|
|
224
|
+
width: 1000,
|
|
225
|
+
},
|
|
226
|
+
mini: {
|
|
227
|
+
download: personImage,
|
|
228
|
+
height: 142,
|
|
229
|
+
width: 200,
|
|
230
|
+
},
|
|
231
|
+
preview: {
|
|
232
|
+
download: personImage,
|
|
233
|
+
height: 284,
|
|
234
|
+
width: 400,
|
|
235
|
+
},
|
|
236
|
+
teaser: {
|
|
237
|
+
download: personImage,
|
|
238
|
+
height: 427,
|
|
239
|
+
width: 600,
|
|
240
|
+
},
|
|
241
|
+
thumb: {
|
|
242
|
+
download: personImage,
|
|
243
|
+
height: 91,
|
|
244
|
+
width: 128,
|
|
245
|
+
},
|
|
246
|
+
tile: {
|
|
247
|
+
download: personImage,
|
|
248
|
+
height: 45,
|
|
249
|
+
width: 64,
|
|
250
|
+
},
|
|
251
|
+
},
|
|
252
|
+
size: 693013,
|
|
253
|
+
width: 2400,
|
|
254
|
+
},
|
|
255
|
+
],
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
styles: {
|
|
260
|
+
align: 'left',
|
|
261
|
+
},
|
|
262
|
+
title: 'Headline H2',
|
|
263
|
+
};
|
|
264
|
+
|
|
172
265
|
export const gridBlockOne = {
|
|
173
266
|
'@type': 'gridBlock',
|
|
174
267
|
blocks: {
|
|
@@ -502,3 +595,194 @@ export const gridBlock = {
|
|
|
502
595
|
backgroundColor: 'grey',
|
|
503
596
|
},
|
|
504
597
|
};
|
|
598
|
+
|
|
599
|
+
export const gridBlockTwoDocumentPerson = {
|
|
600
|
+
'@type': 'gridBlock',
|
|
601
|
+
blocks: {
|
|
602
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a': {
|
|
603
|
+
...teaserBlock,
|
|
604
|
+
},
|
|
605
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1': {
|
|
606
|
+
...personBlock,
|
|
607
|
+
},
|
|
608
|
+
},
|
|
609
|
+
blocks_layout: {
|
|
610
|
+
items: [
|
|
611
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a',
|
|
612
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1',
|
|
613
|
+
],
|
|
614
|
+
},
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
export const gridBlockOnePerson = {
|
|
618
|
+
'@type': 'gridBlock',
|
|
619
|
+
blocks: {
|
|
620
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1': {
|
|
621
|
+
...personBlock,
|
|
622
|
+
},
|
|
623
|
+
},
|
|
624
|
+
blocks_layout: {
|
|
625
|
+
items: ['f34fa7dd-ce59-4f7f-b795-7d7f1e388df1'],
|
|
626
|
+
},
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
export const gridBlockTwoPerson = {
|
|
630
|
+
'@type': 'gridBlock',
|
|
631
|
+
blocks: {
|
|
632
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a': {
|
|
633
|
+
...personBlock,
|
|
634
|
+
},
|
|
635
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1': {
|
|
636
|
+
...personBlock,
|
|
637
|
+
},
|
|
638
|
+
},
|
|
639
|
+
blocks_layout: {
|
|
640
|
+
items: [
|
|
641
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a',
|
|
642
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1',
|
|
643
|
+
],
|
|
644
|
+
},
|
|
645
|
+
};
|
|
646
|
+
|
|
647
|
+
export const gridBlockThreePerson = {
|
|
648
|
+
'@type': 'gridBlock',
|
|
649
|
+
blocks: {
|
|
650
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a': {
|
|
651
|
+
...personBlock,
|
|
652
|
+
},
|
|
653
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1': {
|
|
654
|
+
...personBlock,
|
|
655
|
+
},
|
|
656
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df2': {
|
|
657
|
+
...personBlock,
|
|
658
|
+
},
|
|
659
|
+
},
|
|
660
|
+
blocks_layout: {
|
|
661
|
+
items: [
|
|
662
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a',
|
|
663
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1',
|
|
664
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df2',
|
|
665
|
+
],
|
|
666
|
+
},
|
|
667
|
+
};
|
|
668
|
+
|
|
669
|
+
export const gridBlockFourPerson = {
|
|
670
|
+
'@type': 'gridBlock',
|
|
671
|
+
blocks: {
|
|
672
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a': {
|
|
673
|
+
...personBlock,
|
|
674
|
+
},
|
|
675
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1': {
|
|
676
|
+
...personBlock,
|
|
677
|
+
},
|
|
678
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df2': {
|
|
679
|
+
...personBlock,
|
|
680
|
+
},
|
|
681
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df3': {
|
|
682
|
+
...personBlock,
|
|
683
|
+
},
|
|
684
|
+
},
|
|
685
|
+
blocks_layout: {
|
|
686
|
+
items: [
|
|
687
|
+
'281a22fb-c353-4b91-b2bc-88e6a52ed65a',
|
|
688
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df1',
|
|
689
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df2',
|
|
690
|
+
'f34fa7dd-ce59-4f7f-b795-7d7f1e388df3',
|
|
691
|
+
],
|
|
692
|
+
},
|
|
693
|
+
};
|
|
694
|
+
|
|
695
|
+
export const listingBlockPerson = {
|
|
696
|
+
'@type': 'listing',
|
|
697
|
+
items: [
|
|
698
|
+
{
|
|
699
|
+
'@id': 'http://localhost:3000/asdasd-asdasdasd',
|
|
700
|
+
'@type': 'Person',
|
|
701
|
+
CreationDate: '2025-05-19T17:23:06+02:00',
|
|
702
|
+
Creator: 'admin',
|
|
703
|
+
Date: '2025-05-22T09:10:50+02:00',
|
|
704
|
+
Description:
|
|
705
|
+
'USS Voyager Captain from the 24th century. She is known for her strong leadership skills and her ability to make tough decisions in difficult situations.',
|
|
706
|
+
EffectiveDate: 'None',
|
|
707
|
+
ExpirationDate: 'None',
|
|
708
|
+
ModificationDate: '2025-05-22T09:10:50+02:00',
|
|
709
|
+
Subject: [],
|
|
710
|
+
Title: 'Kathryn Janeway',
|
|
711
|
+
Type: 'Person',
|
|
712
|
+
UID: '2b730627efc24a089e00a315735bfe5b',
|
|
713
|
+
cmf_uid: 1,
|
|
714
|
+
contact_building: null,
|
|
715
|
+
contact_email: 'janeway@ufp.earth.com',
|
|
716
|
+
contact_phone: '124312312313',
|
|
717
|
+
contact_room: 'Ready room',
|
|
718
|
+
country: null,
|
|
719
|
+
created: '2025-05-19T15:23:06+00:00',
|
|
720
|
+
description:
|
|
721
|
+
'USS Voyager Captain from the 24th century. She is known for her strong leadership skills and her ability to make tough decisions in difficult situations.',
|
|
722
|
+
effective: '1969-12-30T22:00:00+00:00',
|
|
723
|
+
end: null,
|
|
724
|
+
exclude_from_nav: false,
|
|
725
|
+
expires: '2499-12-30T22:00:00+00:00',
|
|
726
|
+
getIcon: null,
|
|
727
|
+
getId: 'asdasd-asdasdasd',
|
|
728
|
+
getObjSize: '0 KB',
|
|
729
|
+
getPath: '/Plone/asdasd-asdasdasd',
|
|
730
|
+
getRemoteUrl: null,
|
|
731
|
+
getURL: 'http://localhost:3000/asdasd-asdasdasd',
|
|
732
|
+
hasPreviewImage: null,
|
|
733
|
+
head_title: null,
|
|
734
|
+
id: 'asdasd-asdasdasd',
|
|
735
|
+
image_field: 'preview_image_link',
|
|
736
|
+
image_scales: {
|
|
737
|
+
preview_image_link: [
|
|
738
|
+
{
|
|
739
|
+
base_path: './',
|
|
740
|
+
'content-type': 'image/png',
|
|
741
|
+
download: personImage,
|
|
742
|
+
filename: 'person.png',
|
|
743
|
+
height: 286,
|
|
744
|
+
scales: {
|
|
745
|
+
icon: {
|
|
746
|
+
download: personImage,
|
|
747
|
+
height: 32,
|
|
748
|
+
width: 24,
|
|
749
|
+
},
|
|
750
|
+
mini: {
|
|
751
|
+
download: personImage,
|
|
752
|
+
height: 260,
|
|
753
|
+
width: 200,
|
|
754
|
+
},
|
|
755
|
+
thumb: {
|
|
756
|
+
download: personImage,
|
|
757
|
+
height: 128,
|
|
758
|
+
width: 98,
|
|
759
|
+
},
|
|
760
|
+
tile: {
|
|
761
|
+
download: personImage,
|
|
762
|
+
height: 64,
|
|
763
|
+
width: 49,
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
size: 37757,
|
|
767
|
+
width: 220,
|
|
768
|
+
},
|
|
769
|
+
],
|
|
770
|
+
},
|
|
771
|
+
is_folderish: true,
|
|
772
|
+
listCreators: ['admin'],
|
|
773
|
+
location: null,
|
|
774
|
+
mime_type: 'text/plain',
|
|
775
|
+
modified: '2025-05-22T07:10:50+00:00',
|
|
776
|
+
nav_title: null,
|
|
777
|
+
portal_type: 'Person',
|
|
778
|
+
review_state: 'private',
|
|
779
|
+
roles: ['member'],
|
|
780
|
+
start: null,
|
|
781
|
+
sync_uid: null,
|
|
782
|
+
title: 'Kathryn Janeway',
|
|
783
|
+
type_title: 'Person',
|
|
784
|
+
username: null,
|
|
785
|
+
},
|
|
786
|
+
],
|
|
787
|
+
items_total: 1,
|
|
788
|
+
};
|
|
Binary file
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
import { teaserBlock } from './mocks';
|
|
2
|
+
import TeaserBody from '@plone/volto/components/manage/Blocks/Teaser/Body';
|
|
3
|
+
import { teaserBlock, personBlock } from './mocks';
|
|
4
4
|
import Wrapper from '@plone/volto/storybook';
|
|
5
5
|
import BlockWrapper from './BlockWrapper';
|
|
6
6
|
|
|
@@ -8,12 +8,12 @@ import type { Meta, StoryObj } from '@storybook/react';
|
|
|
8
8
|
|
|
9
9
|
const meta = {
|
|
10
10
|
title: 'Blocks/Teaser',
|
|
11
|
-
component:
|
|
11
|
+
component: TeaserBody,
|
|
12
12
|
parameters: {
|
|
13
13
|
layout: 'centered',
|
|
14
14
|
},
|
|
15
15
|
tags: ['autodocs'],
|
|
16
|
-
} satisfies Meta<typeof
|
|
16
|
+
} satisfies Meta<typeof TeaserBody>;
|
|
17
17
|
|
|
18
18
|
export default meta;
|
|
19
19
|
type Story = StoryObj<typeof meta>;
|
|
@@ -23,7 +23,7 @@ export const Left: Story = {
|
|
|
23
23
|
<Wrapper>
|
|
24
24
|
<div style={{ width: 'var(--default-container-width)' }}>
|
|
25
25
|
<BlockWrapper {...args}>
|
|
26
|
-
<
|
|
26
|
+
<TeaserBody {...args} />
|
|
27
27
|
</BlockWrapper>
|
|
28
28
|
</div>
|
|
29
29
|
</Wrapper>
|
|
@@ -38,7 +38,7 @@ export const Right: Story = {
|
|
|
38
38
|
<Wrapper>
|
|
39
39
|
<div style={{ width: 'var(--default-container-width)' }}>
|
|
40
40
|
<BlockWrapper {...args}>
|
|
41
|
-
<
|
|
41
|
+
<TeaserBody {...args} />
|
|
42
42
|
</BlockWrapper>
|
|
43
43
|
</div>
|
|
44
44
|
</Wrapper>
|
|
@@ -58,7 +58,7 @@ export const Center: Story = {
|
|
|
58
58
|
<Wrapper>
|
|
59
59
|
<div style={{ width: 'var(--default-container-width)' }}>
|
|
60
60
|
<BlockWrapper {...args}>
|
|
61
|
-
<
|
|
61
|
+
<TeaserBody {...args} />
|
|
62
62
|
</BlockWrapper>
|
|
63
63
|
</div>
|
|
64
64
|
</Wrapper>
|
|
@@ -72,3 +72,18 @@ export const Center: Story = {
|
|
|
72
72
|
},
|
|
73
73
|
},
|
|
74
74
|
};
|
|
75
|
+
|
|
76
|
+
export const PersonTeaser: Story = {
|
|
77
|
+
render: (args) => (
|
|
78
|
+
<Wrapper>
|
|
79
|
+
<div style={{ width: 'var(--default-container-width)' }}>
|
|
80
|
+
<BlockWrapper {...args}>
|
|
81
|
+
<TeaserBody {...args} />
|
|
82
|
+
</BlockWrapper>
|
|
83
|
+
</div>
|
|
84
|
+
</Wrapper>
|
|
85
|
+
),
|
|
86
|
+
args: {
|
|
87
|
+
data: personBlock,
|
|
88
|
+
},
|
|
89
|
+
};
|
package/src/theme/_footer.scss
CHANGED
package/src/theme/_layout.scss
CHANGED
|
@@ -358,6 +358,7 @@ External link removal for all the blocks.
|
|
|
358
358
|
.block.teaser.has--align--center,
|
|
359
359
|
.block.eventMetadata .details-container,
|
|
360
360
|
.block-editor-teaser .teaser-item.default,
|
|
361
|
+
.block-editor-teaser .card-inner, // deprecate when category is in place
|
|
361
362
|
.block-editor-slateTable .block.table,
|
|
362
363
|
.block-editor-highlight .teaser-description-title,
|
|
363
364
|
.block-editor-toc .table-of-contents {
|
|
@@ -460,6 +461,7 @@ body.has-toolbar.has-sidebar .block .ui.basic.button.delete-button {
|
|
|
460
461
|
#page-edit,
|
|
461
462
|
#page-document {
|
|
462
463
|
img {
|
|
464
|
+
object-fit: cover;
|
|
463
465
|
object-position: center;
|
|
464
466
|
}
|
|
465
467
|
}
|
package/src/theme/card.scss
CHANGED
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
}
|
|
68
68
|
}
|
|
69
69
|
|
|
70
|
-
// //
|
|
70
|
+
// // Side-aligned
|
|
71
71
|
.card {
|
|
72
72
|
.has--align--left:not(.contained) &,
|
|
73
73
|
.has--align--right:not(.contained) & {
|
|
@@ -149,7 +149,6 @@
|
|
|
149
149
|
display: flex;
|
|
150
150
|
|
|
151
151
|
.image-wrapper {
|
|
152
|
-
// width: 50%;
|
|
153
152
|
flex: 0 1 var(--card-listing-image-size, 220px);
|
|
154
153
|
margin-right: 20px;
|
|
155
154
|
|
|
@@ -160,7 +159,6 @@
|
|
|
160
159
|
}
|
|
161
160
|
|
|
162
161
|
.card-summary {
|
|
163
|
-
// width: 50%;
|
|
164
162
|
flex: 1 1 50%;
|
|
165
163
|
padding: 0;
|
|
166
164
|
}
|
package/src/theme/main.scss
CHANGED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
.card {
|
|
2
|
+
.person-teaser.has--align--left:not(.contained) &,
|
|
3
|
+
.has--align--left:not(.contained) .person-teaser &,
|
|
4
|
+
.person-teaser.has--align--right:not(.contained) & {
|
|
5
|
+
.card-inner {
|
|
6
|
+
.image-wrapper {
|
|
7
|
+
flex: 0 1 var(--card-listing-image-size, 220px);
|
|
8
|
+
img {
|
|
9
|
+
aspect-ratio: initial !important;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.card-summary {
|
|
15
|
+
align-self: center;
|
|
16
|
+
|
|
17
|
+
.description {
|
|
18
|
+
margin-bottom: $spacing-small;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.person-teaser & {
|
|
24
|
+
.card-summary {
|
|
25
|
+
.description {
|
|
26
|
+
margin-bottom: $spacing-small;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.contained.person-teaser & {
|
|
32
|
+
.image-wrapper {
|
|
33
|
+
display: flex;
|
|
34
|
+
height: 255px;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
aspect-ratio: var(--image-aspect-ratio, 1.7777777778);
|
|
37
|
+
|
|
38
|
+
img {
|
|
39
|
+
max-width: 198px; // 255x198px Roughly 3:4 (enough to cover the 16:9 portrait height)
|
|
40
|
+
height: 100%;
|
|
41
|
+
flex: 0 1 auto;
|
|
42
|
+
aspect-ratio: initial !important;
|
|
43
|
+
object-fit: cover;
|
|
44
|
+
object-position: top center;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// One column exception for contained person-teasers
|
|
51
|
+
.one .contained.person-teaser {
|
|
52
|
+
width: calc(var(--default-container-width) / 2);
|
|
53
|
+
|
|
54
|
+
.column & {
|
|
55
|
+
align-items: center;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.one .column:has(.contained.person-teaser) {
|
|
60
|
+
align-items: center;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Three column exception for contained person-teasers
|
|
64
|
+
.three .contained.person-teaser,
|
|
65
|
+
.four .contained.person-teaser {
|
|
66
|
+
.summary-room-phone {
|
|
67
|
+
flex-direction: column;
|
|
68
|
+
|
|
69
|
+
.summary-extra-info {
|
|
70
|
+
margin-bottom: 0;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// contained person-teasers do not have background color, so we need to set it to --theme-color
|
|
76
|
+
body .block.gridBlock .block.teaser.contained.person-teaser .card-inner {
|
|
77
|
+
background: var(--theme-color);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// contained person-teasers do not have background color, so we need to remove the padding
|
|
81
|
+
// to snap to the default container width
|
|
82
|
+
.contained.person-teaser {
|
|
83
|
+
.card-summary {
|
|
84
|
+
padding-right: 0px;
|
|
85
|
+
padding-left: 0px;
|
|
86
|
+
text-align: center;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.summary-extra-info,
|
|
90
|
+
.summary-room-phone {
|
|
91
|
+
justify-content: center;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.summary-extra-info {
|
|
96
|
+
display: flex;
|
|
97
|
+
align-items: center;
|
|
98
|
+
margin-bottom: $spacing-small;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.summary-room-phone {
|
|
102
|
+
display: flex;
|
|
103
|
+
gap: $spacing-small;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Listings (no card)
|
|
107
|
+
.block.listing {
|
|
108
|
+
.listing-item.person-listing {
|
|
109
|
+
&,
|
|
110
|
+
& a {
|
|
111
|
+
align-items: center;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
h2,
|
|
115
|
+
h3 {
|
|
116
|
+
margin-bottom: $spacing-small !important;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
img {
|
|
120
|
+
aspect-ratio: initial !important;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import PropTypes from 'prop-types';
|
|
3
|
-
import { Message } from 'semantic-ui-react';
|
|
4
|
-
import { defineMessages, useIntl } from 'react-intl';
|
|
5
|
-
import imageBlockSVG from '@plone/volto/components/manage/Blocks/Image/block-image.svg';
|
|
6
|
-
import { isInternalURL } from '@plone/volto/helpers/Url/Url';
|
|
7
|
-
import cx from 'classnames';
|
|
8
|
-
import config from '@plone/volto/registry';
|
|
9
|
-
import DefaultSummary from '@kitconcept/volto-light-theme/components/Summary/DefaultSummary';
|
|
10
|
-
import Card from '../../../primitives/Card/Card';
|
|
11
|
-
import isEmpty from 'lodash/isEmpty';
|
|
12
|
-
|
|
13
|
-
const messages = defineMessages({
|
|
14
|
-
PleaseChooseContent: {
|
|
15
|
-
id: 'Please choose an existing content as source for this element',
|
|
16
|
-
defaultMessage:
|
|
17
|
-
'Please choose an existing content as source for this element',
|
|
18
|
-
},
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
const TeaserDefaultTemplate = (props) => {
|
|
22
|
-
const { className, data, isEditMode, style } = props;
|
|
23
|
-
const intl = useIntl();
|
|
24
|
-
const href = data.href?.[0] || {};
|
|
25
|
-
const image = data.preview_image?.[0];
|
|
26
|
-
const url = data.preview_image?.[0]?.['@id'];
|
|
27
|
-
|
|
28
|
-
const Image = config.getComponent('Image').component;
|
|
29
|
-
const Summary =
|
|
30
|
-
config.getComponent({
|
|
31
|
-
name: 'Summary',
|
|
32
|
-
dependencies: [href['@type']],
|
|
33
|
-
}).component || DefaultSummary;
|
|
34
|
-
const { openExternalLinkInNewTab } = config.settings;
|
|
35
|
-
const openLinkInNewTab =
|
|
36
|
-
data.openLinkInNewTab ||
|
|
37
|
-
(openExternalLinkInNewTab && !isInternalURL(href['@id']))
|
|
38
|
-
? '_blank'
|
|
39
|
-
: null;
|
|
40
|
-
const { '@id': id, ...filteredData } = data;
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<div className={cx('block teaser', className)} style={style}>
|
|
44
|
-
<>
|
|
45
|
-
{isEmpty(href) && isEditMode ? (
|
|
46
|
-
<Message>
|
|
47
|
-
<div className="teaser-item placeholder">
|
|
48
|
-
<img src={imageBlockSVG} alt="" />
|
|
49
|
-
<p>{intl.formatMessage(messages.PleaseChooseContent)}</p>
|
|
50
|
-
</div>
|
|
51
|
-
</Message>
|
|
52
|
-
) : (
|
|
53
|
-
<Card
|
|
54
|
-
href={!isEditMode ? href['@id'] : null}
|
|
55
|
-
openLinkInNewTab={openLinkInNewTab}
|
|
56
|
-
>
|
|
57
|
-
<Card.Image
|
|
58
|
-
src={url && !image?.image_field ? url : undefined}
|
|
59
|
-
item={!data.overwrite ? href : { ...href, ...filteredData }}
|
|
60
|
-
image={data.overwrite ? image : undefined}
|
|
61
|
-
imageComponent={Image}
|
|
62
|
-
/>
|
|
63
|
-
<Card.Summary>
|
|
64
|
-
<Summary
|
|
65
|
-
item={!data.overwrite ? href : { ...href, ...filteredData }}
|
|
66
|
-
HeadingTag="h2"
|
|
67
|
-
/>
|
|
68
|
-
</Card.Summary>
|
|
69
|
-
</Card>
|
|
70
|
-
)}
|
|
71
|
-
</>
|
|
72
|
-
</div>
|
|
73
|
-
);
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
TeaserDefaultTemplate.propTypes = {
|
|
77
|
-
data: PropTypes.objectOf(PropTypes.any).isRequired,
|
|
78
|
-
isEditMode: PropTypes.bool,
|
|
79
|
-
};
|
|
80
|
-
|
|
81
|
-
export default TeaserDefaultTemplate;
|