@kitconcept/volto-light-theme 8.0.0-alpha.7 → 8.0.0-alpha.9

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 CHANGED
@@ -1,14 +1,16 @@
1
- ## 8.0.0-alpha.7 (2025-11-24)
1
+ ## 8.0.0-alpha.9 (2025-12-08)
2
2
 
3
- ### Bugfix
3
+ ### Feature
4
4
 
5
- - Fix css of unauthorized Page @iRohitSingh [#unauthorizedpageCss](https://github.com/kitconcept/volto-light-theme/pull/unauthorizedpageCss)
6
- - Fixed Accordion arrow/buttons no longer shrink when the title text becomes too long. @jnptk
5
+ - Add volto-calendar-block @iRohitSingh
6
+ - Added cross language support for blocks chooser search @Tishasoumya-02 [#7657](https://github.com/plone/volto/issues/7657)
7
+ Added support for selecting Path and Depth in the Listing Block’s Location criteria using the ObjectBrowserWidget and NumberWidget. @iFlameing @giuliaghisini [#7661](https://github.com/plone/volto/issues/7661)
8
+ Added feature of drag and drop files in folder contents. @Tishasoumya-02
9
+ (Update to Volto 19a9) @sneridagh
7
10
 
8
- ### Internal
11
+ ### Bugfix
9
12
 
10
- - Refactoring to TS some components. @sneridagh [#731](https://github.com/kitconcept/volto-light-theme/pull/731)
11
- - Update to latest RAC to match the @plone/components one. @sneridagh
12
- - Use forked Razzle. Update to use Volto 19a14. @sneridagh
13
+ - Fixed highlight block ENTER, create a new block consistently. Update highlight block to 4.5.1. @sneridagh
14
+ - Fixed introduction block error on pressing ENTER. Update add-on to 1.2.0. @sneridagh
13
15
 
14
16
 
package/CHANGELOG.md CHANGED
@@ -8,6 +8,29 @@
8
8
 
9
9
  <!-- towncrier release notes start -->
10
10
 
11
+ ## 8.0.0-alpha.9 (2025-12-08)
12
+
13
+ ### Feature
14
+
15
+ - Add volto-calendar-block @iRohitSingh
16
+ - Added cross language support for blocks chooser search @Tishasoumya-02 [#7657](https://github.com/plone/volto/issues/7657)
17
+ Added support for selecting Path and Depth in the Listing Block’s Location criteria using the ObjectBrowserWidget and NumberWidget. @iFlameing @giuliaghisini [#7661](https://github.com/plone/volto/issues/7661)
18
+ Added feature of drag and drop files in folder contents. @Tishasoumya-02
19
+ (Update to Volto 19a9) @sneridagh
20
+
21
+ ### Bugfix
22
+
23
+ - Fixed highlight block ENTER, create a new block consistently. Update highlight block to 4.5.1. @sneridagh
24
+ - Fixed introduction block error on pressing ENTER. Update add-on to 1.2.0. @sneridagh
25
+
26
+ ## 8.0.0-alpha.8 (2025-12-01)
27
+
28
+ ### Bugfix
29
+
30
+ - Improve block model 3 support across views. Fixed nasty BDandD console error. @sneridagh [#740](https://github.com/kitconcept/volto-light-theme/pull/740)
31
+ - Fixed problem with the description not showing in rendering if the description was undefined. @sneridagh
32
+ - Hide complementary logo in mobile devices @Tishasoumya-02
33
+
11
34
  ## 8.0.0-alpha.7 (2025-11-24)
12
35
 
13
36
  ### Bugfix
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kitconcept/volto-light-theme",
3
- "version": "8.0.0-alpha.7",
3
+ "version": "8.0.0-alpha.9",
4
4
  "description": "Volto Light Theme by kitconcept",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -57,8 +57,8 @@
57
57
  "react-aria-components": "^1.13.0",
58
58
  "react-colorful": "^5.6.1",
59
59
  "uuid": "^11.0.0",
60
- "@plone/components": "^4.0.0-alpha.4",
61
- "@kitconcept/volto-bm3-compat": "^1.0.0-alpha.1"
60
+ "@kitconcept/volto-bm3-compat": "^1.0.0-alpha.1",
61
+ "@plone/components": "^4.0.0-alpha.4"
62
62
  },
63
63
  "peerDependencies": {
64
64
  "classnames": "^2.5.1",
@@ -84,7 +84,15 @@ const EditBlockWrapper = (props) => {
84
84
  style: { ...style, ...draginfo.draggableProps.style },
85
85
  };
86
86
 
87
- return blocksConfig?.[type]?.blockModel !== 3 ? (
87
+ if (blocksConfig?.[type]?.blockModel === 3) {
88
+ // We still need to attach the draggable props/ref so RBD stays happy,
89
+ // but we skip rendering the drag handle and friends
90
+ // consider removing the whole EditBlockWrapper for BlockModelv3 blocks in the future
91
+ // or moving the handlers here.
92
+ return <>{children}</>;
93
+ }
94
+
95
+ return (
88
96
  <div
89
97
  ref={draginfo.innerRef}
90
98
  {...styleMergedWithDragProps}
@@ -160,8 +168,6 @@ const EditBlockWrapper = (props) => {
160
168
  </div>
161
169
  </div>
162
170
  </div>
163
- ) : (
164
- <>{children}</>
165
171
  );
166
172
  };
167
173
 
@@ -20,19 +20,27 @@ const TeaserDefaultTemplate = (props) => {
20
20
  const openLinkInNewTab =
21
21
  data.openLinkInNewTab ||
22
22
  (openExternalLinkInNewTab && !isInternalURL(href['@id']));
23
- const { '@id': id, ...filteredData } = data;
23
+
24
+ // Ensures that overridden fields are used when "overwrite" is true
25
+ // and fallbacks to empty strings if they are not provided to ensure no undefined
26
+ // values are passed
27
+ const localOverrides = {
28
+ title: data.title || '',
29
+ description: data.description || '',
30
+ head_title: data.head_title || '',
31
+ };
24
32
 
25
33
  return (
26
34
  <Card item={showLink ? href : null} openLinkInNewTab={openLinkInNewTab}>
27
35
  <Card.Image
28
36
  src={url && !image?.image_field ? url : undefined}
29
- item={!data.overwrite ? href : { ...href, ...filteredData }}
37
+ item={!data.overwrite ? href : { ...href, ...localOverrides }}
30
38
  image={data.overwrite ? image : undefined}
31
39
  imageComponent={Image}
32
40
  />
33
41
  <Card.Summary>
34
42
  <Summary
35
- item={!data.overwrite ? href : { ...href, ...filteredData }}
43
+ item={!data.overwrite ? href : { ...href, ...localOverrides }}
36
44
  HeadingTag="h2"
37
45
  hide_description={props.data?.hide_description}
38
46
  />
@@ -16,6 +16,7 @@ import RenderEmptyBlock from '@plone/volto/components/theme/View/RenderEmptyBloc
16
16
  import cx from 'classnames';
17
17
  import { groupByBGColor } from '../../helpers/grouping';
18
18
  import ErrorBoundary from '../Blocks/Block/ErrorBoundary';
19
+ import StyleWrapperV3 from './StyleWrapperV3';
19
20
 
20
21
  const messages = defineMessages({
21
22
  unknownBlock: {
@@ -68,6 +69,9 @@ const RenderBlocks = (props) => {
68
69
  }
69
70
  >
70
71
  {group.map((block) => {
72
+ const currentBlockModel =
73
+ blocksConfig[content[blocksFieldname]?.[block]?.['@type']]
74
+ ?.blockModel;
71
75
  const Block =
72
76
  blocksConfig[content[blocksFieldname]?.[block]?.['@type']]
73
77
  ?.view || ViewDefaultBlock;
@@ -104,23 +108,42 @@ const RenderBlocks = (props) => {
104
108
  condition={blockWrapperTag}
105
109
  as={blockWrapperTag}
106
110
  >
107
- <StyleWrapper
108
- key={block}
109
- {...props}
110
- id={block}
111
- block={block}
112
- data={blockData}
113
- isContainer={isContainer}
114
- >
115
- <Block
116
- id={block}
117
- metadata={metadata}
118
- properties={content}
111
+ {currentBlockModel === 3 ? (
112
+ <StyleWrapperV3
113
+ block={block}
114
+ content={content}
119
115
  data={blockData}
120
- path={getBaseUrl(location?.pathname || '')}
121
116
  blocksConfig={blocksConfig}
122
- />
123
- </StyleWrapper>
117
+ isContainer={isContainer}
118
+ >
119
+ <Block
120
+ id={block}
121
+ metadata={metadata}
122
+ properties={content}
123
+ data={blockData}
124
+ path={getBaseUrl(location?.pathname || '')}
125
+ blocksConfig={blocksConfig}
126
+ />
127
+ </StyleWrapperV3>
128
+ ) : (
129
+ <StyleWrapper
130
+ key={block}
131
+ {...props}
132
+ id={block}
133
+ block={block}
134
+ data={blockData}
135
+ isContainer={isContainer}
136
+ >
137
+ <Block
138
+ id={block}
139
+ metadata={metadata}
140
+ properties={content}
141
+ data={blockData}
142
+ path={getBaseUrl(location?.pathname || '')}
143
+ blocksConfig={blocksConfig}
144
+ />
145
+ </StyleWrapper>
146
+ )}
124
147
  </MaybeWrap>
125
148
  </ErrorBoundary>
126
149
  );
@@ -0,0 +1,263 @@
1
+ /**
2
+ * OVERRIDE: DragDropList.jsx
3
+ * REASON: Adding BlockModelv3 guards and customizations.
4
+ * Not moved to core yet, and as it's temporary, we keep it here.
5
+ * DATE: 2025-12-01
6
+ * DEVELOPER: @sneridagh
7
+ */
8
+
9
+ import React, { useRef } from 'react';
10
+ import isEmpty from 'lodash/isEmpty';
11
+ import { injectLazyLibs } from '@plone/volto/helpers/Loadable/Loadable';
12
+ import { v4 as uuid } from 'uuid';
13
+ import config from '@plone/volto/registry';
14
+
15
+ const getVerticalPlaceholder = (
16
+ draggedDOM,
17
+ sourceIndex,
18
+ destinationIndex,
19
+ parentDOM,
20
+ ) => {
21
+ // Because of the margin rendering rules, there is no easy
22
+ // way to calculate the offset of the placeholder.
23
+ //
24
+ // (Note that this is the reason we cannot use the solutions
25
+ // published on the net, because they assume that we are in control
26
+ // of the content and there are no additional margins involved.)
27
+ //
28
+ // To get a placeholder that looks good in all cases, we
29
+ // fill up the space between the previous and the next element.
30
+ const childrenArray = [...parentDOM.children];
31
+ // Remove the source element
32
+ childrenArray.splice(sourceIndex, 1);
33
+ // Also remove the placeholder that the library always inserts at the end
34
+ childrenArray.splice(-1, 1);
35
+ const parentRect = parentDOM.getBoundingClientRect();
36
+ const prevNode = childrenArray[destinationIndex - 1];
37
+ const nextNode = childrenArray[destinationIndex];
38
+ let top, bottom;
39
+ if (prevNode) {
40
+ const prevRect = prevNode.getBoundingClientRect();
41
+ top = prevRect.top + prevRect.height - parentRect.top;
42
+ } else {
43
+ top = 0;
44
+ }
45
+ if (nextNode) {
46
+ const nextRect = nextNode.getBoundingClientRect();
47
+ bottom = nextRect.top - parentRect.top;
48
+ } else {
49
+ bottom =
50
+ parentRect.bottom +
51
+ draggedDOM.getBoundingClientRect().height -
52
+ parentRect.top;
53
+ }
54
+ return {
55
+ clientY: top,
56
+ clientHeight: bottom - top,
57
+ clientX: parseFloat(window.getComputedStyle(parentDOM).paddingLeft),
58
+ clientWidth: draggedDOM.clientWidth,
59
+ };
60
+ };
61
+
62
+ const getHorizontalPlaceholder = (draggedDOM, destinationIndex, parentDOM) => {
63
+ // The next element will be the one with a gray placeholder behind it.
64
+ //
65
+ // If the element is the last (doesn't have a next element), the whole draggable
66
+ // area will be highlighted
67
+
68
+ const parentRect = parentDOM.getBoundingClientRect();
69
+ let height;
70
+
71
+ height = parentRect.bottom - parentRect.top;
72
+
73
+ let clientWidth = draggedDOM.clientWidth;
74
+
75
+ let innerDroppablePlaceholderMarginLeft =
76
+ parentDOM.children[destinationIndex].getBoundingClientRect().x;
77
+ if (parentDOM.children.length - 1 === destinationIndex) {
78
+ innerDroppablePlaceholderMarginLeft = parentRect.x;
79
+ clientWidth = parentDOM.getBoundingClientRect().width;
80
+ }
81
+ return {
82
+ clientY: 0,
83
+ clientHeight: height,
84
+ clientX: parseFloat(innerDroppablePlaceholderMarginLeft - parentRect.x),
85
+ clientWidth: clientWidth,
86
+ };
87
+ };
88
+
89
+ const DragDropList = (props) => {
90
+ const {
91
+ childList,
92
+ children,
93
+ direction = 'vertical',
94
+ onMoveItem,
95
+ as = 'div',
96
+ style,
97
+ forwardedAriaLabelledBy,
98
+ reactBeautifulDnd,
99
+ } = props; //renderChild
100
+ const { DragDropContext, Draggable, Droppable } = reactBeautifulDnd;
101
+ const [placeholderProps, setPlaceholderProps] = React.useState({});
102
+ const [uid] = React.useState(uuid());
103
+ // queueing timed action
104
+ const timer = useRef(null);
105
+ const parentRef = useRef(null);
106
+ const onDragStart = React.useCallback(
107
+ (event) => {
108
+ clearTimeout(timer.current);
109
+ const queryAttr = 'data-rbd-draggable-id';
110
+ const domQuery = `[${queryAttr}='${event.draggableId}']`;
111
+ const draggedDOM = document.querySelector(domQuery);
112
+ if (!draggedDOM) {
113
+ return;
114
+ }
115
+ const sourceIndex = event.source.index;
116
+ setPlaceholderProps(
117
+ direction === 'horizontal'
118
+ ? getHorizontalPlaceholder(draggedDOM, sourceIndex, parentRef.current)
119
+ : getVerticalPlaceholder(
120
+ draggedDOM,
121
+ sourceIndex,
122
+ sourceIndex,
123
+ parentRef.current,
124
+ ),
125
+ );
126
+ },
127
+ [direction],
128
+ );
129
+
130
+ const onDragEnd = React.useCallback(
131
+ (result) => {
132
+ clearTimeout(timer.current);
133
+ onMoveItem(result);
134
+ setPlaceholderProps({});
135
+ },
136
+ [onMoveItem],
137
+ );
138
+
139
+ const onDragUpdate = React.useCallback(
140
+ (update) => {
141
+ clearTimeout(timer.current);
142
+ setPlaceholderProps({});
143
+ if (!update.destination) {
144
+ return;
145
+ }
146
+ const draggableId = update.draggableId;
147
+ const queryAttr = 'data-rbd-draggable-id';
148
+ const domQuery = `[${queryAttr}='${draggableId}']`;
149
+ const draggedDOM = document.querySelector(domQuery);
150
+ if (!draggedDOM) {
151
+ return;
152
+ }
153
+ const sourceIndex = update.source.index;
154
+ const destinationIndex = update.destination.index;
155
+ // Wait until the animations have finished, to make it look good.
156
+ timer.current = setTimeout(() => {
157
+ setPlaceholderProps(
158
+ direction === 'horizontal'
159
+ ? getHorizontalPlaceholder(
160
+ draggedDOM,
161
+ destinationIndex,
162
+ parentRef.current,
163
+ )
164
+ : getVerticalPlaceholder(
165
+ draggedDOM,
166
+ sourceIndex,
167
+ destinationIndex,
168
+ parentRef.current,
169
+ ),
170
+ );
171
+ }, 250);
172
+ },
173
+ [direction],
174
+ );
175
+
176
+ const AsDomComponent = as;
177
+ return (
178
+ <DragDropContext
179
+ onDragStart={onDragStart}
180
+ onDragUpdate={onDragUpdate}
181
+ onDragEnd={onDragEnd}
182
+ >
183
+ <Droppable
184
+ droppableId={uid}
185
+ direction={direction}
186
+ renderClone={(provided, snapshot, rubric) => {
187
+ const index = rubric.source.index;
188
+ return children({
189
+ child: childList[index][1],
190
+ childId: childList[index][0],
191
+ index,
192
+ draginfo: provided,
193
+ });
194
+ }}
195
+ >
196
+ {(provided, snapshot) => (
197
+ <AsDomComponent
198
+ ref={(el) => {
199
+ provided.innerRef(el);
200
+ parentRef.current = el;
201
+ }}
202
+ {...provided.droppableProps}
203
+ style={{ ...style, position: 'relative' }}
204
+ aria-labelledby={forwardedAriaLabelledBy}
205
+ >
206
+ {childList
207
+ .filter(([id, child]) => id && child) // beware numbers!
208
+ .map(([childId, child], index) => {
209
+ const dragDisabled =
210
+ config.blocks.blocksConfig?.[child?.['@type']]?.blockModel ===
211
+ 3;
212
+ if (!dragDisabled) {
213
+ return (
214
+ <Draggable
215
+ draggableId={childId.toString()}
216
+ index={index}
217
+ key={childId}
218
+ isDragDisabled={!!dragDisabled}
219
+ style={{
220
+ userSelect: 'none',
221
+ }}
222
+ >
223
+ {(draginfo) =>
224
+ children({ child, childId, index, draginfo })
225
+ }
226
+ </Draggable>
227
+ );
228
+ } else {
229
+ return (
230
+ <React.Fragment key={childId}>
231
+ {children({
232
+ child,
233
+ childId,
234
+ index,
235
+ draginfo: { draggableProps: {} },
236
+ })}
237
+ </React.Fragment>
238
+ );
239
+ }
240
+ })}
241
+ {provided.placeholder}
242
+ {!isEmpty(placeholderProps) && snapshot.isDraggingOver && (
243
+ <div
244
+ style={{
245
+ position: 'absolute',
246
+ top: placeholderProps.clientY,
247
+ left: placeholderProps.clientX,
248
+ height: placeholderProps.clientHeight,
249
+ background: '#eee',
250
+ width: placeholderProps.clientWidth,
251
+ borderRadius: '3px',
252
+ ...(direction === 'horizontal' && { zIndex: -1 }),
253
+ }}
254
+ />
255
+ )}
256
+ </AsDomComponent>
257
+ )}
258
+ </Droppable>
259
+ </DragDropContext>
260
+ );
261
+ };
262
+
263
+ export default injectLazyLibs(['reactBeautifulDnd'])(DragDropList);
@@ -418,6 +418,10 @@
418
418
  flex: 1 1 auto;
419
419
  flex-direction: row-reverse;
420
420
 
421
+ @media only screen and (max-width: $largest-mobile-screen) {
422
+ display: none;
423
+ }
424
+
421
425
  @media only screen and (max-width: $computer-breakpoint) {
422
426
  flex: 0 1 55px;
423
427
  }
@@ -1,4 +1,5 @@
1
1
  .view-editview.is-anonymous,
2
+ .view-unauthorized,
2
3
  .page-not-found {
3
4
  .content-area {
4
5
  @include default-container-width();