@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.
Files changed (118) hide show
  1. package/.changelog.draft +26 -1
  2. package/CHANGELOG.md +34 -0
  3. package/locales/af/LC_MESSAGES/volto.po +645 -0
  4. package/locales/ar/LC_MESSAGES/volto.po +645 -0
  5. package/locales/bg/LC_MESSAGES/volto.po +645 -0
  6. package/locales/bn/LC_MESSAGES/volto.po +645 -0
  7. package/locales/ca/LC_MESSAGES/volto.po +645 -0
  8. package/locales/cs/LC_MESSAGES/volto.po +645 -0
  9. package/locales/cy/LC_MESSAGES/volto.po +645 -0
  10. package/locales/da/LC_MESSAGES/volto.po +645 -0
  11. package/locales/de/LC_MESSAGES/volto.po +58 -57
  12. package/locales/el/LC_MESSAGES/volto.po +645 -0
  13. package/locales/en_AU/LC_MESSAGES/volto.po +645 -0
  14. package/locales/en_GB/LC_MESSAGES/volto.po +645 -0
  15. package/locales/eo/LC_MESSAGES/volto.po +645 -0
  16. package/locales/es/LC_MESSAGES/volto.po +50 -50
  17. package/locales/et/LC_MESSAGES/volto.po +645 -0
  18. package/locales/eu/LC_MESSAGES/volto.po +7 -7
  19. package/locales/fa/LC_MESSAGES/volto.po +645 -0
  20. package/locales/fi/LC_MESSAGES/volto.po +645 -0
  21. package/locales/fr/LC_MESSAGES/volto.po +645 -0
  22. package/locales/fu/LC_MESSAGES/volto.po +645 -0
  23. package/locales/ga/LC_MESSAGES/volto.po +645 -0
  24. package/locales/gl/LC_MESSAGES/volto.po +645 -0
  25. package/locales/he/LC_MESSAGES/volto.po +645 -0
  26. package/locales/hi/LC_MESSAGES/volto.po +645 -0
  27. package/locales/hr/LC_MESSAGES/volto.po +645 -0
  28. package/locales/hu/LC_MESSAGES/volto.po +645 -0
  29. package/locales/hy/LC_MESSAGES/volto.po +645 -0
  30. package/locales/id/LC_MESSAGES/volto.po +645 -0
  31. package/locales/it/LC_MESSAGES/volto.po +645 -0
  32. package/locales/ja/LC_MESSAGES/volto.po +645 -0
  33. package/locales/ka/LC_MESSAGES/volto.po +645 -0
  34. package/locales/kn/LC_MESSAGES/volto.po +645 -0
  35. package/locales/ko/LC_MESSAGES/volto.po +645 -0
  36. package/locales/lt/LC_MESSAGES/volto.po +645 -0
  37. package/locales/lv/LC_MESSAGES/volto.po +645 -0
  38. package/locales/mi/LC_MESSAGES/volto.po +645 -0
  39. package/locales/mk_MK/LC_MESSAGES/volto.po +645 -0
  40. package/locales/ms/LC_MESSAGES/volto.po +645 -0
  41. package/locales/mt/LC_MESSAGES/volto.po +645 -0
  42. package/locales/my/LC_MESSAGES/volto.po +645 -0
  43. package/locales/nl/LC_MESSAGES/volto.po +645 -0
  44. package/locales/nl_BE/LC_MESSAGES/volto.po +645 -0
  45. package/locales/nn/LC_MESSAGES/volto.po +645 -0
  46. package/locales/no/LC_MESSAGES/volto.po +645 -0
  47. package/locales/pl/LC_MESSAGES/volto.po +645 -0
  48. package/locales/pt/LC_MESSAGES/volto.po +645 -0
  49. package/locales/rm/LC_MESSAGES/volto.po +645 -0
  50. package/locales/ro/LC_MESSAGES/volto.po +645 -0
  51. package/locales/ru/LC_MESSAGES/volto.po +645 -0
  52. package/locales/sk/LC_MESSAGES/volto.po +645 -0
  53. package/locales/sl/LC_MESSAGES/volto.po +645 -0
  54. package/locales/sm/LC_MESSAGES/volto.po +645 -0
  55. package/locales/sq/LC_MESSAGES/volto.po +645 -0
  56. package/locales/sr/LC_MESSAGES/volto.po +645 -0
  57. package/locales/sr_Cyrl/LC_MESSAGES/volto.po +645 -0
  58. package/locales/sr_Latn/LC_MESSAGES/volto.po +645 -0
  59. package/locales/sv/LC_MESSAGES/volto.po +645 -0
  60. package/locales/sw/LC_MESSAGES/volto.po +645 -0
  61. package/locales/ta/LC_MESSAGES/volto.po +645 -0
  62. package/locales/te/LC_MESSAGES/volto.po +645 -0
  63. package/locales/th/LC_MESSAGES/volto.po +645 -0
  64. package/locales/tl/LC_MESSAGES/volto.po +645 -0
  65. package/locales/to/LC_MESSAGES/volto.po +645 -0
  66. package/locales/tr/LC_MESSAGES/volto.po +645 -0
  67. package/locales/uk/LC_MESSAGES/volto.po +645 -0
  68. package/locales/vi/LC_MESSAGES/volto.po +645 -0
  69. package/locales/zh_CN/LC_MESSAGES/volto.po +645 -0
  70. package/locales/zh_HK/LC_MESSAGES/volto.po +645 -0
  71. package/locales/zh_TW/LC_MESSAGES/volto.po +645 -0
  72. package/package.json +5 -5
  73. package/src/components/Blocks/Button/schema.js +12 -0
  74. package/src/components/Blocks/Image/Edit.jsx +8 -32
  75. package/src/components/Blocks/Image/View.jsx +9 -26
  76. package/src/components/Blocks/Image/adapter.js +28 -14
  77. package/src/components/Blocks/Image/adapter.test.js +156 -0
  78. package/src/components/Blocks/Image/schema.js +21 -7
  79. package/src/components/Blocks/Listing/GridTemplate.jsx +1 -0
  80. package/src/components/Blocks/Listing/SummaryTemplate.jsx +1 -0
  81. package/src/components/Blocks/Maps/MapsSidebar.jsx +68 -0
  82. package/src/components/Blocks/Maps/View.jsx +37 -0
  83. package/src/components/Blocks/Maps/adapter.js +27 -0
  84. package/src/components/Blocks/Maps/adapter.test.js +63 -0
  85. package/src/components/Blocks/Maps/schema.js +42 -2
  86. package/src/components/Blocks/Separator/schema.js +12 -0
  87. package/src/components/Blocks/Teaser/DefaultBody.tsx +10 -1
  88. package/src/components/Blocks/Video/VideoSidebar.jsx +68 -0
  89. package/src/components/Blocks/Video/View.jsx +38 -0
  90. package/src/components/Blocks/Video/adapter.js +28 -0
  91. package/src/components/Blocks/Video/adapter.test.js +63 -0
  92. package/src/components/Blocks/Video/schema.js +42 -2
  93. package/src/components/Footer/Footer.tsx +2 -2
  94. package/src/components/Footer/slots/FollowUsLogoAndLinks.tsx +12 -23
  95. package/src/components/Theme/ImageView.jsx +8 -1
  96. package/src/components/Widgets/ObjectList.tsx +37 -27
  97. package/src/config/blocks.tsx +63 -0
  98. package/src/config/classExtenders.ts +11 -10
  99. package/src/config/settings.ts +6 -0
  100. package/src/customizations/volto/components/manage/Blocks/Maps/MapsSidebar.jsx +10 -0
  101. package/src/customizations/volto/components/manage/Blocks/Maps/View.jsx +10 -0
  102. package/src/customizations/volto/components/manage/Blocks/Video/VideoSidebar.jsx +10 -0
  103. package/src/customizations/volto/components/manage/Blocks/Video/View.jsx +10 -0
  104. package/src/index.ts +8 -0
  105. package/src/primitives/Card/Card.tsx +4 -1
  106. package/src/theme/_bgcolor-blocks-layout.scss +1 -1
  107. package/src/theme/_footer.scss +61 -51
  108. package/src/theme/_layout.scss +7 -62
  109. package/src/theme/_typo-custom.scss +1 -1
  110. package/src/theme/_variables.scss +21 -0
  111. package/src/theme/blocks/_grid.scss +1 -0
  112. package/src/theme/blocks/_highlight.scss +10 -7
  113. package/src/theme/blocks/_image.scss +96 -186
  114. package/src/theme/blocks/_listing.scss +5 -1
  115. package/src/theme/blocks/_maps.scss +60 -34
  116. package/src/transforms/to6.ts +5 -49
  117. package/src/transforms/to8.test.js +201 -0
  118. package/src/transforms/to8.ts +109 -0
@@ -50,42 +50,17 @@ function Edit(props) {
50
50
 
51
51
  return (
52
52
  <>
53
- <div
54
- className={cx(
55
- 'block image align',
56
- {
57
- center: !Boolean(data.align),
58
- },
59
- data.align,
60
- )}
61
- >
53
+ <div className={cx('block image')}>
62
54
  {data.url ? (
63
55
  <figure
64
- className={cx(
65
- 'figure',
66
- {
67
- center: !Boolean(data.align),
68
- },
69
- data.align,
70
- {
71
- // START CUSTOMIZATION
72
- // 'full-width': data.align === 'full',
73
- // END CUSTOMIZATION
74
- large: data.size === 'l',
75
- medium: data.size === 'm' || !data.size,
76
- small: data.size === 's',
77
- },
78
- )}
56
+ // START CUSTOMIZATION
57
+ className={cx({
58
+ large: data.size === 'l' || !data.size,
59
+ medium: data.size === 'm',
60
+ small: data.size === 's',
61
+ })}
79
62
  >
80
63
  <Image
81
- // START CUSTOMIZATION - Moved to the figure
82
- // className={cx({
83
- // 'full-width': data.align === 'full',
84
- // large: data.size === 'l',
85
- // medium: data.size === 'm',
86
- // small: data.size === 's',
87
- // })}
88
- // END CUSTOMIZATION
89
64
  item={
90
65
  data.image_scales
91
66
  ? {
@@ -95,6 +70,7 @@ function Edit(props) {
95
70
  }
96
71
  : undefined
97
72
  }
73
+ // END CUSTOMIZATION
98
74
  src={
99
75
  data.image_scales
100
76
  ? undefined
@@ -37,12 +37,10 @@ export const ImageView = ({ className, data, detached, properties, style }) => {
37
37
  return (
38
38
  <div
39
39
  className={cx(
40
- 'block image align',
40
+ 'block image',
41
41
  {
42
- center: !Boolean(data.align),
43
42
  detached,
44
43
  },
45
- data.align,
46
44
  className,
47
45
  )}
48
46
  style={style}
@@ -52,31 +50,16 @@ export const ImageView = ({ className, data, detached, properties, style }) => {
52
50
  {(() => {
53
51
  const image = (
54
52
  <figure
55
- className={cx(
56
- 'figure',
57
- {
58
- center: !Boolean(data.align),
59
- detached,
60
- },
61
- data.align,
62
- {
63
- // START CUSTOMIZATION
64
- // 'full-width': data.align === 'full',
65
- // END CUSTOMIZATION
66
- large: data.size === 'l',
67
- medium: data.size === 'm' || !data.size,
68
- small: data.size === 's',
69
- },
70
- )}
53
+ // START CUSTOMIZATION
54
+ className={cx({
55
+ detached,
56
+ large: data.size === 'l' || !data.size,
57
+ medium: data.size === 'm',
58
+ small: data.size === 's',
59
+ })}
60
+ // END CUSTOMIZATION
71
61
  >
72
62
  <Image
73
- // Removed for now
74
- // className={cx({
75
- // 'full-width': data.align === 'full',
76
- // large: data.size === 'l',
77
- // medium: data.size === 'm',
78
- // small: data.size === 's',
79
- // })}
80
63
  item={
81
64
  data.image_scales
82
65
  ? {
@@ -17,25 +17,39 @@ export const ImageBlockDataAdapter = ({
17
17
  [id]: value,
18
18
  };
19
19
 
20
- if (id === 'align' && !(value === 'left' || value === 'right')) {
21
- if (data.size !== 'l') {
22
- dataSaved = {
23
- ...dataSaved,
24
- size: 'l',
25
- styles: {
26
- ...dataSaved.styles,
27
- 'size:noprefix': SIZEMAP['l'],
28
- },
29
- };
30
- }
31
- }
20
+ const align = dataSaved.styles?.['align:noprefix'];
21
+ const isFloating = align === 'left' || align === 'right';
22
+ const isLarge =
23
+ dataSaved.size === 'l' ||
24
+ dataSaved.styles?.['size:noprefix'] === 'var(--size-large)';
32
25
 
33
- if (id === 'size') {
26
+ if (!isFloating) {
27
+ dataSaved = {
28
+ ...dataSaved,
29
+ size: 'l',
30
+ styles: {
31
+ ...dataSaved.styles,
32
+ 'size:noprefix': SIZEMAP['l'],
33
+ },
34
+ };
35
+ }
36
+ if (!isLarge && isFloating) {
37
+ dataSaved = {
38
+ ...dataSaved,
39
+ styles: {
40
+ ...dataSaved.styles,
41
+ 'size:noprefix': SIZEMAP[dataSaved.size] || 'large',
42
+ 'blockWidth:noprefix': 'narrow',
43
+ },
44
+ };
45
+ }
46
+ if (isLarge && isFloating) {
34
47
  dataSaved = {
35
48
  ...dataSaved,
36
49
  styles: {
37
50
  ...dataSaved.styles,
38
- 'size:noprefix': SIZEMAP[value],
51
+ 'size:noprefix': SIZEMAP['l'],
52
+ 'blockWidth:noprefix': 'default',
39
53
  },
40
54
  };
41
55
  }
@@ -0,0 +1,156 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { ImageBlockDataAdapter } from './adapter';
3
+
4
+ const alignLeft = { 'align:noprefix': 'left' };
5
+ const alignRight = { 'align:noprefix': 'right' };
6
+
7
+ describe('ImageBlockDataAdapter', () => {
8
+ it('forces a large size for non-floating images', () => {
9
+ const onChangeBlock = vi.fn();
10
+
11
+ ImageBlockDataAdapter({
12
+ block: 'block-1',
13
+ data: { '@type': 'image' },
14
+ id: 'align',
15
+ onChangeBlock,
16
+ value: 'center',
17
+ });
18
+
19
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
20
+ '@type': 'image',
21
+ align: 'center',
22
+ size: 'l',
23
+ styles: { 'size:noprefix': 'large' },
24
+ });
25
+ });
26
+
27
+ it('maps the current size and applies a narrow width for a floating, non-large image', () => {
28
+ const onChangeBlock = vi.fn();
29
+
30
+ ImageBlockDataAdapter({
31
+ block: 'block-1',
32
+ data: { '@type': 'image', size: 'm', styles: { ...alignLeft } },
33
+ id: 'align',
34
+ onChangeBlock,
35
+ value: 'left',
36
+ });
37
+
38
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
39
+ '@type': 'image',
40
+ align: 'left',
41
+ size: 'm',
42
+ styles: {
43
+ ...alignLeft,
44
+ 'size:noprefix': 'medium',
45
+ 'blockWidth:noprefix': 'narrow',
46
+ },
47
+ });
48
+ });
49
+
50
+ it('applies the default width for a floating image that is large by size', () => {
51
+ const onChangeBlock = vi.fn();
52
+
53
+ ImageBlockDataAdapter({
54
+ block: 'block-1',
55
+ data: { '@type': 'image', size: 'l', styles: { ...alignRight } },
56
+ id: 'align',
57
+ onChangeBlock,
58
+ value: 'right',
59
+ });
60
+
61
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
62
+ '@type': 'image',
63
+ align: 'right',
64
+ size: 'l',
65
+ styles: {
66
+ ...alignRight,
67
+ 'size:noprefix': 'large',
68
+ 'blockWidth:noprefix': 'default',
69
+ },
70
+ });
71
+ });
72
+
73
+ it('applies the default width for a floating image that is large by style', () => {
74
+ const onChangeBlock = vi.fn();
75
+
76
+ ImageBlockDataAdapter({
77
+ block: 'block-1',
78
+ data: {
79
+ '@type': 'image',
80
+ styles: { ...alignLeft, 'size:noprefix': 'var(--size-large)' },
81
+ },
82
+ id: 'align',
83
+ onChangeBlock,
84
+ value: 'left',
85
+ });
86
+
87
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
88
+ '@type': 'image',
89
+ align: 'left',
90
+ styles: {
91
+ ...alignLeft,
92
+ 'size:noprefix': 'large',
93
+ 'blockWidth:noprefix': 'default',
94
+ },
95
+ });
96
+ });
97
+
98
+ it('copies the item metadata when a url value is set', () => {
99
+ const onChangeBlock = vi.fn();
100
+ const item = {
101
+ credit: 'A photographer',
102
+ Description: 'A description',
103
+ Title: 'A title',
104
+ image_field: 'image',
105
+ image_scales: { image: [{ download: 'image.png' }] },
106
+ };
107
+
108
+ ImageBlockDataAdapter({
109
+ block: 'block-1',
110
+ data: { '@type': 'image' },
111
+ id: 'url',
112
+ item,
113
+ onChangeBlock,
114
+ value: '/an-image',
115
+ });
116
+
117
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
118
+ '@type': 'image',
119
+ url: '/an-image',
120
+ size: 'l',
121
+ styles: { 'size:noprefix': 'large' },
122
+ credit: { data: 'A photographer' },
123
+ description: 'A description',
124
+ title: 'A title',
125
+ image_field: 'image',
126
+ image_scales: { image: [{ download: 'image.png' }] },
127
+ });
128
+ });
129
+
130
+ it('clears the item metadata when the url value is removed', () => {
131
+ const onChangeBlock = vi.fn();
132
+
133
+ ImageBlockDataAdapter({
134
+ block: 'block-1',
135
+ data: {
136
+ '@type': 'image',
137
+ alt: 'alt text',
138
+ credit: { data: 'credit' },
139
+ description: 'description',
140
+ image_scales: {},
141
+ image_field: 'image',
142
+ title: 'title',
143
+ },
144
+ id: 'url',
145
+ onChangeBlock,
146
+ value: '',
147
+ });
148
+
149
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
150
+ '@type': 'image',
151
+ url: '',
152
+ size: 'l',
153
+ styles: { 'size:noprefix': 'large' },
154
+ });
155
+ });
156
+ });
@@ -16,6 +16,10 @@ const messages = defineMessages({
16
16
  id: 'Block Width',
17
17
  defaultMessage: 'Block Width',
18
18
  },
19
+ Alignment: {
20
+ id: 'Alignment',
21
+ defaultMessage: 'Alignment',
22
+ },
19
23
  });
20
24
 
21
25
  export const imageBlockSchemaEnhancer = ({ formData, schema, intl }) => {
@@ -49,28 +53,38 @@ export const standAloneImageBlockSchemaEnhancer = ({
49
53
  intl,
50
54
  }) => {
51
55
  if (formData.url) {
52
- schema.properties.align.default = 'center';
53
- schema.properties.align.actions = ['left', 'right', 'center'];
56
+ schema.fieldsets[0].fields = schema.fieldsets[0].fields.filter(
57
+ (f) => f !== 'align',
58
+ );
59
+
60
+ const align = formData.styles?.['align:noprefix'];
61
+ const isFloating = align === 'left' || align === 'right';
54
62
 
55
63
  schema.properties.size.default = 'l';
56
- schema.properties.size.disabled = formData.align === 'center';
57
64
  schema.properties.styles.schema.fieldsets[0].fields = [
65
+ 'align:noprefix',
58
66
  'blockWidth:noprefix',
59
67
  ...schema.properties.styles.schema.fieldsets[0].fields,
60
68
  ];
61
69
 
70
+ schema.properties.styles.schema.properties['align:noprefix'] = {
71
+ widget: 'blockAlignment',
72
+ title: intl.formatMessage(messages.Alignment),
73
+ default: 'center',
74
+ actions: config.blocks.alignments.map((alignment) => alignment.name),
75
+ };
76
+
62
77
  schema.properties.styles.schema.properties['blockWidth:noprefix'] = {
63
78
  widget: 'blockWidth',
64
79
  title: intl.formatMessage(messages.BlockWidth),
65
80
  default: 'default',
66
- filterActions: ['narrow', 'default', 'layout', 'full'],
67
- actions: config.blocks.widths,
81
+ actions: config.blocks.widths.map((width) => width.name),
68
82
  };
69
83
 
70
84
  schema.properties.styles.schema.properties['blockWidth:noprefix'].disabled =
71
- formData.align === 'left' || formData.align === 'right';
85
+ isFloating;
86
+ schema.properties.size.disabled = !isFloating;
72
87
  }
73
-
74
88
  return schema;
75
89
  };
76
90
 
@@ -53,6 +53,7 @@ const GridTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
53
53
  className="item-image"
54
54
  item={item}
55
55
  imageComponent={PreviewImageComponent}
56
+ sizes={`(max-width: ${config.settings.layout.tabletBreakpoint}px) 100vw, ${Math.trunc(config.settings.layout.defaultContainerWidth / 2)}px`}
56
57
  />
57
58
  )}
58
59
  <Card.Summary
@@ -50,6 +50,7 @@ const SummaryTemplate = ({ items, linkTitle, linkHref, isEditMode }) => {
50
50
  item={item}
51
51
  showPlaceholderImage={true}
52
52
  imageComponent={PreviewImageComponent}
53
+ sizes={`(max-width: ${config.settings.layout.tabletBreakpoint}px) 100vw, 220px`}
53
54
  />
54
55
  <Card.Summary
55
56
  a11yLabelId={props.a11yLabelId}
@@ -0,0 +1,68 @@
1
+ import React from 'react';
2
+ import { MapsSchema } from '@plone/volto/components/manage/Blocks/Maps/schema';
3
+ import { useIntl, defineMessages } from 'react-intl';
4
+ import globeSVG from '@plone/volto/icons/globe.svg';
5
+ import Icon from '@plone/volto/components/theme/Icon/Icon';
6
+ import { BlockDataForm } from '@plone/volto/components/manage/Form';
7
+ import { Segment } from 'semantic-ui-react';
8
+
9
+ const messages = defineMessages({
10
+ Maps: {
11
+ id: 'Maps',
12
+ defaultMessage: 'Maps',
13
+ },
14
+ NoMaps: {
15
+ id: 'No map selected',
16
+ defaultMessage: 'No map selected',
17
+ },
18
+ });
19
+
20
+ const MapsSidebar = (props) => {
21
+ const {
22
+ data,
23
+ block,
24
+ blocksErrors,
25
+ onChangeBlock,
26
+ navRoot,
27
+ contentType,
28
+ blocksConfig,
29
+ } = props;
30
+ const intl = useIntl();
31
+ const schema = MapsSchema({ ...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.NoMaps)}
39
+ <Icon name={globeSVG} size="100px" color="#b8c6c8" />
40
+ </Segment>
41
+ ) : (
42
+ <BlockDataForm
43
+ schema={schema}
44
+ title={intl.formatMessage(messages.Maps)}
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 MapsSidebar;
@@ -0,0 +1,37 @@
1
+ /**
2
+ * View map block.
3
+ * @module components/manage/Blocks/Maps/View
4
+ */
5
+
6
+ import React from 'react';
7
+ import { injectIntl } from 'react-intl';
8
+ import PropTypes from 'prop-types';
9
+ import cx from 'classnames';
10
+ import { compose } from 'redux';
11
+ import Body from '@plone/volto/components/manage/Blocks/Maps/Body';
12
+ import { withBlockExtensions } from '@plone/volto/helpers/Extensions';
13
+
14
+ /**
15
+ * View image block class.
16
+ * @class View
17
+ * @extends Component
18
+ */
19
+
20
+ const View = ({ data, intl, style, className }) => (
21
+ // START CUSTOMIZATION
22
+ <div className={cx('block maps', className)} style={style}>
23
+ {/* // END CUSTOMIZATION */}
24
+ <Body data={data} />
25
+ </div>
26
+ );
27
+
28
+ /**
29
+ * Property types.
30
+ * @property {Object} propTypes Property types.
31
+ * @static
32
+ */
33
+ View.propTypes = {
34
+ data: PropTypes.objectOf(PropTypes.any).isRequired,
35
+ };
36
+
37
+ export default compose(injectIntl, withBlockExtensions)(View);
@@ -0,0 +1,27 @@
1
+ export const MapsBlockDataAdapter = ({
2
+ block,
3
+ data,
4
+ id,
5
+ onChangeBlock,
6
+ value,
7
+ }) => {
8
+ let dataSaved = {
9
+ ...data,
10
+ [id]: value,
11
+ };
12
+
13
+ const align = dataSaved.styles?.['align:noprefix'];
14
+ const isFloating = align === 'left' || align === 'right';
15
+
16
+ if (isFloating) {
17
+ dataSaved = {
18
+ ...dataSaved,
19
+ styles: {
20
+ ...dataSaved.styles,
21
+ 'blockWidth:noprefix': 'default',
22
+ },
23
+ };
24
+ }
25
+
26
+ onChangeBlock(block, dataSaved);
27
+ };
@@ -0,0 +1,63 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { MapsBlockDataAdapter } from './adapter';
3
+
4
+ const alignRight = { 'align:noprefix': 'right' };
5
+ const alignCenter = { 'align:noprefix': 'center' };
6
+
7
+ describe('MapsBlockDataAdapter', () => {
8
+ it('applies the default width for a floating map', () => {
9
+ const onChangeBlock = vi.fn();
10
+
11
+ MapsBlockDataAdapter({
12
+ block: 'block-1',
13
+ data: { '@type': 'maps', styles: { ...alignRight } },
14
+ id: 'url',
15
+ onChangeBlock,
16
+ value: 'https://maps.example.com',
17
+ });
18
+
19
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
20
+ '@type': 'maps',
21
+ url: 'https://maps.example.com',
22
+ styles: {
23
+ ...alignRight,
24
+ 'blockWidth:noprefix': 'default',
25
+ },
26
+ });
27
+ });
28
+
29
+ it('leaves the styles untouched for a non-floating map', () => {
30
+ const onChangeBlock = vi.fn();
31
+
32
+ MapsBlockDataAdapter({
33
+ block: 'block-1',
34
+ data: { '@type': 'maps', styles: { ...alignCenter } },
35
+ id: 'url',
36
+ onChangeBlock,
37
+ value: 'https://maps.example.com',
38
+ });
39
+
40
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
41
+ '@type': 'maps',
42
+ url: 'https://maps.example.com',
43
+ styles: { ...alignCenter },
44
+ });
45
+ });
46
+
47
+ it('leaves the styles untouched when no alignment is set', () => {
48
+ const onChangeBlock = vi.fn();
49
+
50
+ MapsBlockDataAdapter({
51
+ block: 'block-1',
52
+ data: { '@type': 'maps' },
53
+ id: 'url',
54
+ onChangeBlock,
55
+ value: 'https://maps.example.com',
56
+ });
57
+
58
+ expect(onChangeBlock).toHaveBeenCalledWith('block-1', {
59
+ '@type': 'maps',
60
+ url: 'https://maps.example.com',
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 mapsBlockSchemaEnhancer = ({ formData, schema, intl }) => {
2
- schema.properties.align.default = 'wide';
3
- schema.properties.align.actions = ['left', 'right', 'center', 'wide', 'full'];
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
  };
@@ -1,7 +1,19 @@
1
1
  import { defaultStylingSchema } from '../schema';
2
+ import config from '@plone/volto/registry';
2
3
 
3
4
  export const SeparatorStylingSchema = ({ schema, formData, intl }) => {
4
5
  defaultStylingSchema({ schema, formData, intl });
6
+ const styleProps = schema.properties.styles?.schema?.properties;
7
+ if (styleProps?.['align:noprefix']) {
8
+ delete styleProps['align:noprefix'].filterActions;
9
+ styleProps['align:noprefix'].actions = config.blocks.alignments.map(
10
+ (alignment) => alignment.name,
11
+ );
12
+ }
13
+ if (styleProps?.['blockWidth:noprefix']) {
14
+ delete styleProps['blockWidth:noprefix'].filterActions;
15
+ styleProps['blockWidth:noprefix'].actions = ['narrow', 'default'];
16
+ }
5
17
 
6
18
  return schema;
7
19
  };