@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
@@ -0,0 +1,201 @@
1
+ import { describe, it, expect, beforeAll } from 'vitest';
2
+ import config from '@plone/volto/registry';
3
+ import { migrateToVLT8FloatingBlocks } from './to8';
4
+
5
+ const alignLeft = { 'align:noprefix': 'left' };
6
+ const alignRight = { 'align:noprefix': 'right' };
7
+ const alignCenter = { 'align:noprefix': 'center' };
8
+ const narrowWidth = { 'blockWidth:noprefix': 'narrow' };
9
+ const defaultWidth = { 'blockWidth:noprefix': 'default' };
10
+ const fullWidth = { 'blockWidth:noprefix': 'full' };
11
+
12
+ // Wraps a single block in the `data` shape the transform expects and runs it.
13
+ const migrate = (block) => {
14
+ const data = { blocks: { 'block-1': block } };
15
+ migrateToVLT8FloatingBlocks(data);
16
+ return data.blocks['block-1'];
17
+ };
18
+
19
+ beforeAll(() => {
20
+ config.blocks.widths = [
21
+ {
22
+ name: 'narrow',
23
+ style: { '--block-width': 'var(--narrow-container-width)' },
24
+ },
25
+ {
26
+ name: 'default',
27
+ style: { '--block-width': 'var(--default-container-width)' },
28
+ },
29
+ {
30
+ name: 'layout',
31
+ style: { '--block-width': 'var(--layout-container-width)' },
32
+ },
33
+ { name: 'full', style: { '--block-width': '100%' } },
34
+ ];
35
+ config.blocks.alignments = [
36
+ { name: 'left', style: { '--block-alignment': 'var(--align-left)' } },
37
+ { name: 'center', style: { '--block-alignment': 'var(--align-center)' } },
38
+ { name: 'right', style: { '--block-alignment': 'var(--align-right)' } },
39
+ ];
40
+ });
41
+
42
+ describe('migrateToVLT8FloatingBlocks', () => {
43
+ it('centers a non-floating image and applies the narrow width', () => {
44
+ expect(migrate({ '@type': 'image', align: 'center' })).toEqual({
45
+ '@type': 'image',
46
+ styles: { ...alignCenter, ...narrowWidth },
47
+ });
48
+ });
49
+
50
+ it('applies the default width to a wide image', () => {
51
+ expect(migrate({ '@type': 'image', align: 'wide' })).toEqual({
52
+ '@type': 'image',
53
+ styles: { ...alignCenter, ...defaultWidth },
54
+ });
55
+ });
56
+
57
+ it('applies the full width to a full image', () => {
58
+ expect(migrate({ '@type': 'image', align: 'full' })).toEqual({
59
+ '@type': 'image',
60
+ styles: { ...alignCenter, ...fullWidth },
61
+ });
62
+ });
63
+
64
+ it('applies the narrow width to a small floating image', () => {
65
+ expect(migrate({ '@type': 'image', align: 'left', size: 'm' })).toEqual({
66
+ '@type': 'image',
67
+ size: 'm',
68
+ styles: { ...alignLeft, ...narrowWidth },
69
+ });
70
+ });
71
+
72
+ it('applies the default width to a floating image that is large by size', () => {
73
+ expect(migrate({ '@type': 'image', align: 'right', size: 'l' })).toEqual({
74
+ '@type': 'image',
75
+ size: 'l',
76
+ styles: { ...alignRight, ...defaultWidth },
77
+ });
78
+ });
79
+
80
+ it('applies the default width to a floating image that is large by style', () => {
81
+ expect(
82
+ migrate({
83
+ '@type': 'image',
84
+ align: 'left',
85
+ styles: { 'size:noprefix': 'var(--size-large)' },
86
+ }),
87
+ ).toEqual({
88
+ '@type': 'image',
89
+ styles: {
90
+ 'size:noprefix': 'var(--size-large)',
91
+ ...alignLeft,
92
+ ...defaultWidth,
93
+ },
94
+ });
95
+ });
96
+
97
+ it('applies the default width to a floating video', () => {
98
+ expect(migrate({ '@type': 'video', align: 'left' })).toEqual({
99
+ '@type': 'video',
100
+ styles: { ...alignLeft, ...defaultWidth },
101
+ });
102
+ });
103
+
104
+ it('applies the narrow width to a non-floating video', () => {
105
+ expect(migrate({ '@type': 'video', align: 'center' })).toEqual({
106
+ '@type': 'video',
107
+ styles: { ...alignCenter, ...narrowWidth },
108
+ });
109
+ });
110
+
111
+ it('applies the default width to a floating map', () => {
112
+ expect(migrate({ '@type': 'maps', align: 'right' })).toEqual({
113
+ '@type': 'maps',
114
+ styles: { ...alignRight, ...defaultWidth },
115
+ });
116
+ });
117
+
118
+ it('applies the full width to a full map', () => {
119
+ expect(migrate({ '@type': 'maps', align: 'full' })).toEqual({
120
+ '@type': 'maps',
121
+ styles: { ...alignCenter, ...fullWidth },
122
+ });
123
+ });
124
+
125
+ it('migrates the button inneralign to the align literal', () => {
126
+ expect(migrate({ '@type': '__button', inneralign: 'right' })).toEqual({
127
+ '@type': '__button',
128
+ styles: { ...alignRight },
129
+ });
130
+ });
131
+
132
+ it('keeps an existing button alignment over the legacy inneralign', () => {
133
+ expect(
134
+ migrate({
135
+ '@type': '__button',
136
+ inneralign: 'right',
137
+ styles: { ...alignLeft },
138
+ }),
139
+ ).toEqual({
140
+ '@type': '__button',
141
+ styles: { ...alignLeft },
142
+ });
143
+ });
144
+
145
+ it('drops the button inneralign property when it has no value', () => {
146
+ expect(migrate({ '@type': '__button', inneralign: '' })).toEqual({
147
+ '@type': '__button',
148
+ });
149
+ });
150
+
151
+ it('leaves an already migrated block untouched', () => {
152
+ // No legacy `align`, alignment and width already stored as literals.
153
+ expect(
154
+ migrate({ '@type': 'image', styles: { ...alignLeft, ...defaultWidth } }),
155
+ ).toEqual({
156
+ '@type': 'image',
157
+ styles: { ...alignLeft, ...defaultWidth },
158
+ });
159
+ });
160
+
161
+ it('keeps a pre-existing width for a non-floating block', () => {
162
+ expect(
163
+ migrate({ '@type': 'image', align: 'center', styles: { ...fullWidth } }),
164
+ ).toEqual({
165
+ '@type': 'image',
166
+ styles: { ...fullWidth, ...alignCenter },
167
+ });
168
+ });
169
+
170
+ it('ignores blocks of other types', () => {
171
+ expect(migrate({ '@type': 'slate', align: 'left' })).toEqual({
172
+ '@type': 'slate',
173
+ align: 'left',
174
+ });
175
+ });
176
+
177
+ it('migrates nested blocks recursively', () => {
178
+ const data = {
179
+ blocks: {
180
+ 'block-1': {
181
+ '@type': 'image',
182
+ align: 'left',
183
+ blocks: {
184
+ 'block-2': { '@type': 'video', align: 'right' },
185
+ },
186
+ },
187
+ },
188
+ };
189
+
190
+ migrateToVLT8FloatingBlocks(data);
191
+
192
+ expect(data.blocks['block-1']).toMatchObject({
193
+ '@type': 'image',
194
+ styles: { ...alignLeft, ...narrowWidth },
195
+ });
196
+ expect(data.blocks['block-1'].blocks['block-2']).toEqual({
197
+ '@type': 'video',
198
+ styles: { ...alignRight, ...defaultWidth },
199
+ });
200
+ });
201
+ });
@@ -0,0 +1,109 @@
1
+ import type { BlocksFormData, StyleDefinition } from '@plone/types';
2
+ import config from '@plone/volto/registry';
3
+
4
+ function* visitBlocks(blocks: any): Generator<any> {
5
+ for (const key in blocks) {
6
+ if (blocks.hasOwnProperty(key)) {
7
+ const block = blocks[key];
8
+ yield block;
9
+ if (block.blocks) {
10
+ yield* visitBlocks(block.blocks);
11
+ }
12
+ }
13
+ }
14
+ }
15
+
16
+ function alignmentLiteral(align: string | undefined): string {
17
+ if (align === 'left') return 'left';
18
+ if (align === 'right') return 'right';
19
+ return 'center';
20
+ }
21
+
22
+ // The block alignments can be overridden per block, falling back to the global
23
+ // definitions, the same way themes work.
24
+ function alignmentsFor(block: any): StyleDefinition[] {
25
+ return (
26
+ config.blocks.blocksConfig?.[block['@type']]?.alignments ||
27
+ config.blocks.alignments ||
28
+ []
29
+ );
30
+ }
31
+
32
+ // Pre-VLT8 the resolved CSS object was stored in the style field
33
+ // (e.g. `{ '--block-width': 'var(--narrow-container-width)' }`). VLT8 stores
34
+ // only the token literal (`narrow`) and resolves it at runtime through the
35
+ // `styleFieldDefinition` utility.
36
+ function normalizeStyleField(
37
+ block: any,
38
+ fieldName: string,
39
+ definitions: StyleDefinition[],
40
+ ) {
41
+ const value = block?.styles?.[fieldName];
42
+ if (!value || typeof value !== 'object') return;
43
+
44
+ const match = definitions.find((definition) =>
45
+ Object.entries(definition.style ?? {}).every(
46
+ ([key, css]) => value[key] === css,
47
+ ),
48
+ );
49
+ if (match) {
50
+ block.styles[fieldName] = match.name;
51
+ }
52
+ }
53
+
54
+ // Migrates the legacy `align` field of a media block to the `align:noprefix` /
55
+ // `blockWidth:noprefix` style literals. `sizeAware` images keep a narrow width
56
+ // while floating unless they are large; videos and maps always go to default.
57
+ function migrateMediaBlock(block: any, sizeAware: boolean) {
58
+ const align = block?.align;
59
+ const isFloating = align === 'left' || align === 'right';
60
+ const isLarge =
61
+ block?.styles?.['size:noprefix'] === 'var(--size-large)' ||
62
+ block?.size === 'l';
63
+
64
+ const isWide = align === 'wide' || (isFloating && (!sizeAware || isLarge));
65
+ const width = isWide ? 'default' : align === 'full' ? 'full' : 'narrow';
66
+
67
+ block.styles = {
68
+ ...block?.styles,
69
+ 'align:noprefix':
70
+ block?.styles?.['align:noprefix'] ?? alignmentLiteral(align),
71
+ // While floating, the width is driven by the adapter, so it always wins;
72
+ // otherwise an explicit width already on the block is kept.
73
+ 'blockWidth:noprefix': isFloating
74
+ ? width
75
+ : block?.styles?.['blockWidth:noprefix'] ?? width,
76
+ };
77
+
78
+ delete block.align;
79
+ }
80
+
81
+ export function migrateToVLT8FloatingBlocks(data: BlocksFormData) {
82
+ const widths = config.blocks.widths || [];
83
+
84
+ for (const block of visitBlocks(data.blocks)) {
85
+ // Rewrite any CSS object left over from before VLT8 to its token literal.
86
+ normalizeStyleField(block, 'align:noprefix', alignmentsFor(block));
87
+ normalizeStyleField(block, 'blockWidth:noprefix', widths);
88
+
89
+ if (block['@type'] === 'image') {
90
+ migrateMediaBlock(block, true);
91
+ }
92
+
93
+ if (block['@type'] === 'video' || block['@type'] === 'maps') {
94
+ migrateMediaBlock(block, false);
95
+ }
96
+
97
+ // The button's legacy `inneralign` becomes the `align:noprefix` literal.
98
+ if (block['@type'] === '__button') {
99
+ if (block.inneralign) {
100
+ block.styles = {
101
+ ...block.styles,
102
+ 'align:noprefix':
103
+ block.styles?.['align:noprefix'] ?? block.inneralign,
104
+ };
105
+ }
106
+ delete block.inneralign;
107
+ }
108
+ }
109
+ }