@dotcms/react 0.0.1-beta.9 → 1.0.0-next.1
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/README.md +531 -93
- package/index.esm.js +2992 -786
- package/package.json +10 -12
- package/src/index.d.ts +7 -1
- package/src/lib/next/__test__/mock.d.ts +2 -1
- package/src/lib/next/components/Column/Column.d.ts +1 -1
- package/src/lib/next/components/Container/Container.d.ts +1 -1
- package/src/lib/next/components/Container/{ContainerFallbakcs.d.ts → ContainerFallbacks.d.ts} +2 -2
- package/src/lib/next/components/Contentlet/Contentlet.d.ts +2 -2
- package/src/lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer.d.ts +27 -0
- package/src/lib/{deprecated/components/BlockEditorRenderer/item → next/components/DotCMSBlockEditorRenderer/components}/BlockEditorBlock.d.ts +8 -5
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Code.d.ts +24 -0
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/DotContent.d.ts +14 -0
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Image.d.ts +10 -0
- package/src/lib/{deprecated/components/BlockEditorRenderer → next/components/DotCMSBlockEditorRenderer/components}/blocks/Lists.d.ts +8 -4
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/NoComponentProvided.d.ts +3 -0
- package/src/lib/{deprecated/components/BlockEditorRenderer → next/components/DotCMSBlockEditorRenderer/components}/blocks/Table.d.ts +3 -3
- package/src/lib/{deprecated/components/BlockEditorRenderer → next/components/DotCMSBlockEditorRenderer/components}/blocks/Texts.d.ts +23 -13
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Video.d.ts +10 -0
- package/src/lib/{deprecated/components/DotEditableText/DotEditableText.d.ts → next/components/DotCMSEditableText/DotCMSEditableText.d.ts} +8 -6
- package/src/lib/{deprecated/components/DotEditableText → next/components/DotCMSEditableText}/utils.d.ts +9 -9
- package/src/lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody.d.ts +5 -5
- package/src/lib/next/components/DotCMSLayoutBody/components/ErrorMessage.d.ts +1 -4
- package/src/lib/next/components/DotCMSShow/DotCMSShow.d.ts +2 -2
- package/src/lib/next/components/FallbackComponent/FallbackComponent.d.ts +6 -6
- package/src/lib/next/components/Row/Row.d.ts +1 -1
- package/src/lib/next/contexts/DotCMSPageContext.d.ts +2 -3
- package/src/lib/next/hooks/{useShowInUVE.d.ts → useDotCMSShowWhen.d.ts} +5 -5
- package/src/lib/next/hooks/useEditableDotCMSPage.d.ts +90 -0
- package/src/lib/next/hooks/useIsDevMode.d.ts +2 -5
- package/es.regexp.to-string.esm.js +0 -1878
- package/next.esm.d.ts +0 -1
- package/next.esm.js +0 -738
- package/src/lib/deprecated/components/BlockEditorRenderer/BlockEditorRenderer.d.ts +0 -37
- package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Code.d.ts +0 -17
- package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Contentlet.d.ts +0 -41
- package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Image.d.ts +0 -8
- package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Video.d.ts +0 -8
- package/src/lib/deprecated/components/Column/Column.d.ts +0 -19
- package/src/lib/deprecated/components/Container/Container.d.ts +0 -19
- package/src/lib/deprecated/components/DotcmsLayout/DotcmsLayout.d.ts +0 -34
- package/src/lib/deprecated/components/PageProvider/PageProvider.d.ts +0 -14
- package/src/lib/deprecated/components/Row/Row.d.ts +0 -26
- package/src/lib/deprecated/contexts/PageContext.d.ts +0 -8
- package/src/lib/deprecated/deprecated_api.d.ts +0 -7
- package/src/lib/deprecated/hooks/useCheckHaveContent.d.ts +0 -5
- package/src/lib/deprecated/hooks/useDotcmsEditor.d.ts +0 -13
- package/src/lib/deprecated/hooks/useDotcmsPageContext.d.ts +0 -9
- package/src/lib/deprecated/mocks/index.d.ts +0 -1
- package/src/lib/deprecated/mocks/mockPageContext.d.ts +0 -7
- package/src/lib/deprecated/models/blocks.interface.d.ts +0 -89
- package/src/lib/deprecated/models/content-node.interface.d.ts +0 -82
- package/src/lib/deprecated/models/index.d.ts +0 -127
- package/src/lib/deprecated/utils/utils.d.ts +0 -58
- package/src/lib/next/types.d.ts +0 -421
- package/src/lib/next/utils/index.d.ts +0 -136
- package/src/next.d.ts +0 -3
package/next.esm.js
DELETED
|
@@ -1,738 +0,0 @@
|
|
|
1
|
-
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
-
import { createContext, useContext, useState, useEffect, useLayoutEffect, useRef, useMemo } from 'react';
|
|
3
|
-
import { s as styleInject } from './es.regexp.to-string.esm.js';
|
|
4
|
-
import { getUVEState } from '@dotcms/uve';
|
|
5
|
-
import { UVE_MODE } from '@dotcms/uve/types';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* The `PageContext` is a React context that provides access to the DotCMS page context.
|
|
9
|
-
*
|
|
10
|
-
* @category Contexts
|
|
11
|
-
*/
|
|
12
|
-
const DotCMSPageContext = /*#__PURE__*/createContext({
|
|
13
|
-
pageAsset: {},
|
|
14
|
-
mode: 'production',
|
|
15
|
-
userComponents: {}
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @internal
|
|
20
|
-
* A React hook that determines if the current environment is in development mode.
|
|
21
|
-
*
|
|
22
|
-
* The hook returns `true` if either:
|
|
23
|
-
* - The context mode (or the optional `renderMode` argument) is set to 'development', or
|
|
24
|
-
* - The application is running inside the DotCMS editor (as determined by `isInsideEditor()`).
|
|
25
|
-
*
|
|
26
|
-
* @param {DotCMSPageRendererMode} [renderMode] - Optional override for the render mode.
|
|
27
|
-
* @returns {boolean} - `true` if in development mode or inside the editor; otherwise, `false`.
|
|
28
|
-
*/
|
|
29
|
-
const useIsDevMode = renderMode => {
|
|
30
|
-
const {
|
|
31
|
-
mode
|
|
32
|
-
} = useContext(DotCMSPageContext);
|
|
33
|
-
const effectiveMode = renderMode != null ? renderMode : mode;
|
|
34
|
-
const [isDevMode, setIsDevMode] = useState(effectiveMode === 'development');
|
|
35
|
-
useEffect(() => {
|
|
36
|
-
var _getUVEState;
|
|
37
|
-
// Inside UVE we rely on the UVE state to determine if we are in development mode
|
|
38
|
-
if ((_getUVEState = getUVEState()) != null && _getUVEState.mode) {
|
|
39
|
-
var _getUVEState2;
|
|
40
|
-
const isUVEInEditor = ((_getUVEState2 = getUVEState()) == null ? void 0 : _getUVEState2.mode) === UVE_MODE.EDIT;
|
|
41
|
-
setIsDevMode(isUVEInEditor);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const effectiveMode = renderMode != null ? renderMode : mode;
|
|
45
|
-
setIsDevMode(effectiveMode === 'development');
|
|
46
|
-
}, [renderMode, mode]);
|
|
47
|
-
return isDevMode;
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Error message component for when the page body is missing
|
|
52
|
-
*
|
|
53
|
-
* @return {JSX.Element} Error message component
|
|
54
|
-
*/
|
|
55
|
-
const ErrorMessage = ({
|
|
56
|
-
mode
|
|
57
|
-
}) => {
|
|
58
|
-
useEffect(() => {
|
|
59
|
-
console.warn('Missing required layout.body property in page');
|
|
60
|
-
}, []);
|
|
61
|
-
const isDevMode = useIsDevMode(mode);
|
|
62
|
-
if (!isDevMode) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
return jsxs("div", {
|
|
66
|
-
"data-testid": "error-message",
|
|
67
|
-
style: {
|
|
68
|
-
padding: '1rem',
|
|
69
|
-
border: '1px solid #e0e0e0',
|
|
70
|
-
borderRadius: '4px'
|
|
71
|
-
},
|
|
72
|
-
children: [jsxs("p", {
|
|
73
|
-
style: {
|
|
74
|
-
margin: '0 0 0.5rem',
|
|
75
|
-
color: '#666'
|
|
76
|
-
},
|
|
77
|
-
children: ["The ", jsx("code", {
|
|
78
|
-
children: "page"
|
|
79
|
-
}), " is missing the required ", jsx("code", {
|
|
80
|
-
children: "layout.body"
|
|
81
|
-
}), " property."]
|
|
82
|
-
}), jsx("p", {
|
|
83
|
-
style: {
|
|
84
|
-
margin: 0,
|
|
85
|
-
color: '#666'
|
|
86
|
-
},
|
|
87
|
-
children: "Make sure the page asset is properly loaded and includes a layout configuration."
|
|
88
|
-
})]
|
|
89
|
-
});
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
var css_248z$1 = ".Row-module_row__PS0UP {\n display: grid;\n grid-template-columns: repeat(12, 1fr);\n gap: 1rem;\n}\n";
|
|
93
|
-
var styles$1 = {"row":"Row-module_row__PS0UP"};
|
|
94
|
-
styleInject(css_248z$1);
|
|
95
|
-
|
|
96
|
-
var css_248z = ".Column-module_col-start-1__xylw6 {\n grid-column-start: 1;\n}\n\n.Column-module_col-start-2__Mod81 {\n grid-column-start: 2;\n}\n\n.Column-module_col-start-3__HHbXB {\n grid-column-start: 3;\n}\n\n.Column-module_col-start-4__Uk-Qj {\n grid-column-start: 4;\n}\n\n.Column-module_col-start-5__jlV8e {\n grid-column-start: 5;\n}\n\n.Column-module_col-start-6__oi8k0 {\n grid-column-start: 6;\n}\n\n.Column-module_col-start-7__EmPky {\n grid-column-start: 7;\n}\n\n.Column-module_col-start-8__hLI1h {\n grid-column-start: 8;\n}\n\n.Column-module_col-start-9__Kcv9X {\n grid-column-start: 9;\n}\n\n.Column-module_col-start-10__-MOrt {\n grid-column-start: 10;\n}\n\n.Column-module_col-start-11__gDEQM {\n grid-column-start: 11;\n}\n\n.Column-module_col-start-12__omVX6 {\n grid-column-start: 12;\n}\n\n.Column-module_col-end-1__Ho2y9 {\n grid-column-end: 1;\n}\n\n.Column-module_col-end-2__KwFu9 {\n grid-column-end: 2;\n}\n\n.Column-module_col-end-3__vfbJk {\n grid-column-end: 3;\n}\n\n.Column-module_col-end-4__d4pyL {\n grid-column-end: 4;\n}\n\n.Column-module_col-end-5__6yPd4 {\n grid-column-end: 5;\n}\n\n.Column-module_col-end-6__xQpAX {\n grid-column-end: 6;\n}\n\n.Column-module_col-end-7__CCF7e {\n grid-column-end: 7;\n}\n\n.Column-module_col-end-8__fVWEi {\n grid-column-end: 8;\n}\n\n.Column-module_col-end-9__tpIGv {\n grid-column-end: 9;\n}\n\n.Column-module_col-end-10__SX75K {\n grid-column-end: 10;\n}\n\n.Column-module_col-end-11__9K1zv {\n grid-column-end: 11;\n}\n\n.Column-module_col-end-12__oqTiE {\n grid-column-end: 12;\n}\n\n.Column-module_col-end-13__L-nK9 {\n grid-column-end: 13;\n}\n";
|
|
97
|
-
var styles = {"col-start-1":"Column-module_col-start-1__xylw6","col-start-2":"Column-module_col-start-2__Mod81","col-start-3":"Column-module_col-start-3__HHbXB","col-start-4":"Column-module_col-start-4__Uk-Qj","col-start-5":"Column-module_col-start-5__jlV8e","col-start-6":"Column-module_col-start-6__oi8k0","col-start-7":"Column-module_col-start-7__EmPky","col-start-8":"Column-module_col-start-8__hLI1h","col-start-9":"Column-module_col-start-9__Kcv9X","col-start-10":"Column-module_col-start-10__-MOrt","col-start-11":"Column-module_col-start-11__gDEQM","col-start-12":"Column-module_col-start-12__omVX6","col-end-1":"Column-module_col-end-1__Ho2y9","col-end-2":"Column-module_col-end-2__KwFu9","col-end-3":"Column-module_col-end-3__vfbJk","col-end-4":"Column-module_col-end-4__d4pyL","col-end-5":"Column-module_col-end-5__6yPd4","col-end-6":"Column-module_col-end-6__xQpAX","col-end-7":"Column-module_col-end-7__CCF7e","col-end-8":"Column-module_col-end-8__fVWEi","col-end-9":"Column-module_col-end-9__tpIGv","col-end-10":"Column-module_col-end-10__SX75K","col-end-11":"Column-module_col-end-11__9K1zv","col-end-12":"Column-module_col-end-12__oqTiE","col-end-13":"Column-module_col-end-13__L-nK9"};
|
|
98
|
-
styleInject(css_248z);
|
|
99
|
-
|
|
100
|
-
const endClassMap = {
|
|
101
|
-
1: 'col-end-1',
|
|
102
|
-
2: 'col-end-2',
|
|
103
|
-
3: 'col-end-3',
|
|
104
|
-
4: 'col-end-4',
|
|
105
|
-
5: 'col-end-5',
|
|
106
|
-
6: 'col-end-6',
|
|
107
|
-
7: 'col-end-7',
|
|
108
|
-
8: 'col-end-8',
|
|
109
|
-
9: 'col-end-9',
|
|
110
|
-
10: 'col-end-10',
|
|
111
|
-
11: 'col-end-11',
|
|
112
|
-
12: 'col-end-12',
|
|
113
|
-
13: 'col-end-13'
|
|
114
|
-
};
|
|
115
|
-
const startClassMap = {
|
|
116
|
-
1: 'col-start-1',
|
|
117
|
-
2: 'col-start-2',
|
|
118
|
-
3: 'col-start-3',
|
|
119
|
-
4: 'col-start-4',
|
|
120
|
-
5: 'col-start-5',
|
|
121
|
-
6: 'col-start-6',
|
|
122
|
-
7: 'col-start-7',
|
|
123
|
-
8: 'col-start-8',
|
|
124
|
-
9: 'col-start-9',
|
|
125
|
-
10: 'col-start-10',
|
|
126
|
-
11: 'col-start-11',
|
|
127
|
-
12: 'col-start-12'
|
|
128
|
-
};
|
|
129
|
-
/**
|
|
130
|
-
* @internal
|
|
131
|
-
*
|
|
132
|
-
* Combine classes into a single string.
|
|
133
|
-
*
|
|
134
|
-
* @param {string[]} classes
|
|
135
|
-
* @returns {string} Combined classes
|
|
136
|
-
*/
|
|
137
|
-
const combineClasses = classes => classes.filter(Boolean).join(' ');
|
|
138
|
-
/**
|
|
139
|
-
* @internal
|
|
140
|
-
*
|
|
141
|
-
* Calculates and returns the CSS Grid positioning classes for a column based on its configuration.
|
|
142
|
-
* Uses a 12-column grid system where columns are positioned using grid-column-start and grid-column-end.
|
|
143
|
-
*
|
|
144
|
-
* @example
|
|
145
|
-
* ```typescript
|
|
146
|
-
* const classes = getColumnPositionClasses({
|
|
147
|
-
* leftOffset: 1, // Starts at the first column
|
|
148
|
-
* width: 6 // Spans 6 columns
|
|
149
|
-
* });
|
|
150
|
-
* // Returns: { startClass: 'col-start-1', endClass: 'col-end-7' }
|
|
151
|
-
* ```
|
|
152
|
-
*
|
|
153
|
-
* @param {DotPageAssetLayoutColumn} column - Column configuration object
|
|
154
|
-
* @param {number} column.leftOffset - Starting position (0-based) in the grid
|
|
155
|
-
* @param {number} column.width - Number of columns to span
|
|
156
|
-
* @returns {{ startClass: string, endClass: string }} Object containing CSS class names for grid positioning
|
|
157
|
-
*/
|
|
158
|
-
const getColumnPositionClasses = column => {
|
|
159
|
-
const {
|
|
160
|
-
leftOffset,
|
|
161
|
-
width
|
|
162
|
-
} = column;
|
|
163
|
-
const startClass = startClassMap[leftOffset];
|
|
164
|
-
const endClass = endClassMap[leftOffset + width];
|
|
165
|
-
return {
|
|
166
|
-
startClass,
|
|
167
|
-
endClass
|
|
168
|
-
};
|
|
169
|
-
};
|
|
170
|
-
/**
|
|
171
|
-
* @internal
|
|
172
|
-
*
|
|
173
|
-
* Helper function that returns an object containing the dotCMS data attributes.
|
|
174
|
-
* @param {DotCMSContentlet} contentlet - The contentlet to get the attributes for
|
|
175
|
-
* @param {string} container - The container to get the attributes for
|
|
176
|
-
* @returns {DotContentletAttributes} The dotCMS data attributes
|
|
177
|
-
*/
|
|
178
|
-
function getDotContentletAttributes(contentlet, container) {
|
|
179
|
-
return {
|
|
180
|
-
'data-dot-identifier': contentlet == null ? void 0 : contentlet.identifier,
|
|
181
|
-
'data-dot-basetype': contentlet == null ? void 0 : contentlet.baseType,
|
|
182
|
-
'data-dot-title': (contentlet == null ? void 0 : contentlet.widgetTitle) || (contentlet == null ? void 0 : contentlet.title),
|
|
183
|
-
'data-dot-inode': contentlet == null ? void 0 : contentlet.inode,
|
|
184
|
-
'data-dot-type': contentlet == null ? void 0 : contentlet.contentType,
|
|
185
|
-
'data-dot-container': container,
|
|
186
|
-
'data-dot-on-number-of-pages': contentlet == null ? void 0 : contentlet.onNumberOfPages
|
|
187
|
-
};
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* @internal
|
|
191
|
-
*
|
|
192
|
-
* Retrieves container data from a DotCMS page asset using the container reference.
|
|
193
|
-
* This function processes the container information and returns a standardized format
|
|
194
|
-
* for container editing.
|
|
195
|
-
*
|
|
196
|
-
* @param {DotCMSPageAsset} dotCMSPageAsset - The page asset containing all containers data
|
|
197
|
-
* @param {DotCMSColumnContainer} columContainer - The container reference from the layout
|
|
198
|
-
* @throws {Error} When page asset is invalid or container is not found
|
|
199
|
-
* @returns {EditableContainerData} Formatted container data for editing
|
|
200
|
-
*
|
|
201
|
-
* @example
|
|
202
|
-
* const containerData = getContainersData(pageAsset, containerRef);
|
|
203
|
-
* // Returns: { uuid: '123', identifier: 'cont1', acceptTypes: 'type1,type2', maxContentlets: 5 }
|
|
204
|
-
*/
|
|
205
|
-
const getContainersData = (dotCMSPageAsset, columContainer) => {
|
|
206
|
-
var _containerStructures$, _container$parentPerm, _container$maxContent;
|
|
207
|
-
const {
|
|
208
|
-
identifier,
|
|
209
|
-
uuid
|
|
210
|
-
} = columContainer;
|
|
211
|
-
const dotContainer = dotCMSPageAsset.containers[identifier];
|
|
212
|
-
if (!dotContainer) {
|
|
213
|
-
return null;
|
|
214
|
-
}
|
|
215
|
-
const {
|
|
216
|
-
containerStructures,
|
|
217
|
-
container
|
|
218
|
-
} = dotContainer;
|
|
219
|
-
const acceptTypes = (_containerStructures$ = containerStructures == null ? void 0 : containerStructures.map(structure => structure.contentTypeVar).join(',')) != null ? _containerStructures$ : '';
|
|
220
|
-
const variantId = container == null || (_container$parentPerm = container.parentPermissionable) == null ? void 0 : _container$parentPerm.variantId;
|
|
221
|
-
const maxContentlets = (_container$maxContent = container == null ? void 0 : container.maxContentlets) != null ? _container$maxContent : 0;
|
|
222
|
-
const path = container == null ? void 0 : container.path;
|
|
223
|
-
return {
|
|
224
|
-
uuid,
|
|
225
|
-
variantId,
|
|
226
|
-
acceptTypes,
|
|
227
|
-
maxContentlets,
|
|
228
|
-
identifier: path != null ? path : identifier
|
|
229
|
-
};
|
|
230
|
-
};
|
|
231
|
-
/**
|
|
232
|
-
* @internal
|
|
233
|
-
*
|
|
234
|
-
* Retrieves the contentlets (content items) associated with a specific container.
|
|
235
|
-
* Handles different UUID formats and provides warning for missing contentlets.
|
|
236
|
-
*
|
|
237
|
-
* @param {DotCMSPageAsset} dotCMSPageAsset - The page asset containing all containers data
|
|
238
|
-
* @param {DotCMSColumnContainer} columContainer - The container reference from the layout
|
|
239
|
-
* @returns {DotCMSContentlet[]} Array of contentlets in the container
|
|
240
|
-
*
|
|
241
|
-
* @example
|
|
242
|
-
* const contentlets = getContentletsInContainer(pageAsset, containerRef);
|
|
243
|
-
* // Returns: [{ identifier: 'cont1', ... }, { identifier: 'cont2', ... }]
|
|
244
|
-
*/
|
|
245
|
-
const getContentletsInContainer = (dotCMSPageAsset, columContainer) => {
|
|
246
|
-
const {
|
|
247
|
-
identifier,
|
|
248
|
-
uuid
|
|
249
|
-
} = columContainer;
|
|
250
|
-
const {
|
|
251
|
-
contentlets
|
|
252
|
-
} = dotCMSPageAsset.containers[identifier];
|
|
253
|
-
const contentletsInContainer = contentlets[`uuid-${uuid}`] || contentlets[`uuid-dotParser_${uuid}`] || [];
|
|
254
|
-
if (!contentletsInContainer) {
|
|
255
|
-
console.warn(`We couldn't find the contentlets for the container with the identifier ${identifier} and the uuid ${uuid} becareful by adding content to this container.\nWe recommend to change the container in the layout and add the content again.`);
|
|
256
|
-
}
|
|
257
|
-
return contentletsInContainer;
|
|
258
|
-
};
|
|
259
|
-
/**
|
|
260
|
-
* @internal
|
|
261
|
-
*
|
|
262
|
-
* Generates the required DotCMS data attributes for a container element.
|
|
263
|
-
* These attributes are used by DotCMS for container identification and functionality.
|
|
264
|
-
*
|
|
265
|
-
* @param {EditableContainerData} params - Container data including uuid, identifier, acceptTypes, and maxContentlets
|
|
266
|
-
* @returns {DotContainerAttributes} Object containing all necessary data attributes
|
|
267
|
-
*
|
|
268
|
-
* @example
|
|
269
|
-
* const attributes = getDotContainerAttributes({
|
|
270
|
-
* uuid: '123',
|
|
271
|
-
* identifier: 'cont1',
|
|
272
|
-
* acceptTypes: 'type1,type2',
|
|
273
|
-
* maxContentlets: 5
|
|
274
|
-
* });
|
|
275
|
-
* // Returns: { 'data-dot-object': 'container', 'data-dot-identifier': 'cont1', ... }
|
|
276
|
-
*/
|
|
277
|
-
function getDotContainerAttributes({
|
|
278
|
-
uuid,
|
|
279
|
-
identifier,
|
|
280
|
-
acceptTypes,
|
|
281
|
-
maxContentlets
|
|
282
|
-
}) {
|
|
283
|
-
return {
|
|
284
|
-
'data-dot-object': 'container',
|
|
285
|
-
'data-dot-accept-types': acceptTypes,
|
|
286
|
-
'data-dot-identifier': identifier,
|
|
287
|
-
'data-max-contentlets': maxContentlets.toString(),
|
|
288
|
-
'data-dot-uuid': uuid
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
const EMPTY_CONTAINER_STYLE = {
|
|
293
|
-
width: '100%',
|
|
294
|
-
backgroundColor: '#ECF0FD',
|
|
295
|
-
display: 'flex',
|
|
296
|
-
justifyContent: 'center',
|
|
297
|
-
alignItems: 'center',
|
|
298
|
-
color: '#030E32',
|
|
299
|
-
height: '10rem'
|
|
300
|
-
};
|
|
301
|
-
/**
|
|
302
|
-
* @internal
|
|
303
|
-
*
|
|
304
|
-
* Component to display when a container is not found in the system.
|
|
305
|
-
* Only renders in development mode for debugging purposes.
|
|
306
|
-
*
|
|
307
|
-
* @component
|
|
308
|
-
* @param {Object} props - Component properties
|
|
309
|
-
* @param {string} props.identifier - Container identifier
|
|
310
|
-
* @returns {JSX.Element | null} Message about missing container or null in production
|
|
311
|
-
*/
|
|
312
|
-
const ContainerNoFound = ({
|
|
313
|
-
identifier
|
|
314
|
-
}) => {
|
|
315
|
-
const isDevMode = useIsDevMode();
|
|
316
|
-
useEffect(() => {
|
|
317
|
-
if (!isDevMode) {
|
|
318
|
-
return;
|
|
319
|
-
}
|
|
320
|
-
console.error(`Container with identifier ${identifier} not found`);
|
|
321
|
-
}, [identifier, isDevMode]);
|
|
322
|
-
if (!isDevMode) {
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
return jsxs("div", {
|
|
326
|
-
"data-testid": "container-not-found",
|
|
327
|
-
style: EMPTY_CONTAINER_STYLE,
|
|
328
|
-
children: ["This container with identifier ", identifier, " was not found."]
|
|
329
|
-
});
|
|
330
|
-
};
|
|
331
|
-
/**
|
|
332
|
-
* @internal
|
|
333
|
-
*
|
|
334
|
-
* Component to display when a container is empty.
|
|
335
|
-
*
|
|
336
|
-
* @param {DotContainerAttributes} dotAttributes
|
|
337
|
-
* @return {*}
|
|
338
|
-
*/
|
|
339
|
-
const EmptyContainer = dotAttributes => {
|
|
340
|
-
const isDevMode = useIsDevMode();
|
|
341
|
-
if (!isDevMode) {
|
|
342
|
-
return null;
|
|
343
|
-
}
|
|
344
|
-
return jsx("div", Object.assign({}, dotAttributes, {
|
|
345
|
-
style: EMPTY_CONTAINER_STYLE,
|
|
346
|
-
children: jsx("span", {
|
|
347
|
-
"data-testid": "empty-container-message",
|
|
348
|
-
children: "This container is empty."
|
|
349
|
-
})
|
|
350
|
-
}));
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* @internal
|
|
355
|
-
* A custom React hook that checks whether a referenced HTMLDivElement has visible content based on its height.
|
|
356
|
-
*
|
|
357
|
-
* @param {RefObject<HTMLDivElement>} ref - A React ref object pointing to an HTMLDivElement.
|
|
358
|
-
* @returns {boolean} - Returns true if the element's height is greater than zero (indicating visible content), otherwise false.
|
|
359
|
-
*
|
|
360
|
-
* @example
|
|
361
|
-
* import { useRef } from 'react';
|
|
362
|
-
* import { useCheckVisibleContent } from 'src/lib/next/hooks/useCheckVisibleContent';
|
|
363
|
-
*
|
|
364
|
-
* function MyComponent() {
|
|
365
|
-
* const contentRef = useRef<HTMLDivElement>(null);
|
|
366
|
-
* const isContentVisible = useCheckVisibleContent(contentRef);
|
|
367
|
-
*
|
|
368
|
-
* return (
|
|
369
|
-
* <div ref={contentRef}>
|
|
370
|
-
* {isContentVisible ? 'Content is visible' : 'Content is not visible'}
|
|
371
|
-
* </div>
|
|
372
|
-
* );
|
|
373
|
-
* }
|
|
374
|
-
*/
|
|
375
|
-
const useCheckVisibleContent = ref => {
|
|
376
|
-
const [haveContent, setHaveContent] = useState(false);
|
|
377
|
-
useLayoutEffect(() => {
|
|
378
|
-
if (!ref.current) {
|
|
379
|
-
setHaveContent(false);
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
const {
|
|
383
|
-
height
|
|
384
|
-
} = ref.current.getBoundingClientRect();
|
|
385
|
-
setHaveContent(height > 0);
|
|
386
|
-
}, [ref]);
|
|
387
|
-
return haveContent;
|
|
388
|
-
};
|
|
389
|
-
|
|
390
|
-
/**
|
|
391
|
-
* @internal
|
|
392
|
-
*
|
|
393
|
-
* Renders a fallback component when no matching component is found for a content type
|
|
394
|
-
*
|
|
395
|
-
* @component
|
|
396
|
-
* @param {DotCMSFallbackComponentProps} props - Component properties
|
|
397
|
-
* @param {NoComponentType} [props.UserNoComponent] - Optional custom component to render
|
|
398
|
-
* @param {DotCMSContentlet} [props.contentlet] - The contentlet that couldn't be rendered
|
|
399
|
-
* @returns {JSX.Element} The rendered fallback component
|
|
400
|
-
*
|
|
401
|
-
* @example
|
|
402
|
-
* ```tsx
|
|
403
|
-
* <FallbackComponent
|
|
404
|
-
* UserNoComponent={CustomNoComponent}
|
|
405
|
-
* contentlet={contentlet}
|
|
406
|
-
* />
|
|
407
|
-
* ```
|
|
408
|
-
*/
|
|
409
|
-
function FallbackComponent({
|
|
410
|
-
UserNoComponent,
|
|
411
|
-
contentlet
|
|
412
|
-
}) {
|
|
413
|
-
const isDevMode = useIsDevMode();
|
|
414
|
-
if (!isDevMode) {
|
|
415
|
-
return null;
|
|
416
|
-
}
|
|
417
|
-
const NoComponentFound = UserNoComponent || NoComponent;
|
|
418
|
-
return jsx(NoComponentFound, Object.assign({}, contentlet));
|
|
419
|
-
}
|
|
420
|
-
/**
|
|
421
|
-
* @internal
|
|
422
|
-
*
|
|
423
|
-
* Component to render when there is no component for the content type.
|
|
424
|
-
*
|
|
425
|
-
* @param {DotCMSContentlet} contentType - The content type that couldn't be rendered
|
|
426
|
-
* @return {*}
|
|
427
|
-
*/
|
|
428
|
-
function NoComponent({
|
|
429
|
-
contentType
|
|
430
|
-
}) {
|
|
431
|
-
return jsxs("div", {
|
|
432
|
-
"data-testid": "no-component",
|
|
433
|
-
children: ["No Component for ", jsx("strong", {
|
|
434
|
-
children: contentType
|
|
435
|
-
}), "."]
|
|
436
|
-
});
|
|
437
|
-
}
|
|
438
|
-
|
|
439
|
-
/**
|
|
440
|
-
* Contentlet component that renders DotCMS content with development mode support
|
|
441
|
-
*
|
|
442
|
-
* @component
|
|
443
|
-
* @param {DotCMSContentletRendererProps} props - Component properties
|
|
444
|
-
* @param {DotCMSContentlet} props.contentlet - The contentlet to be rendered
|
|
445
|
-
* @param {string} props.container - The container identifier
|
|
446
|
-
* @returns {JSX.Element} Rendered contentlet with appropriate wrapper and attributes
|
|
447
|
-
*
|
|
448
|
-
* @example
|
|
449
|
-
* ```tsx
|
|
450
|
-
* <Contentlet
|
|
451
|
-
* contentlet={myContentlet}
|
|
452
|
-
* container="container-1"
|
|
453
|
-
* />
|
|
454
|
-
* ```
|
|
455
|
-
*/
|
|
456
|
-
function Contentlet({
|
|
457
|
-
contentlet,
|
|
458
|
-
container
|
|
459
|
-
}) {
|
|
460
|
-
const ref = useRef(null);
|
|
461
|
-
const isDevMode = useIsDevMode();
|
|
462
|
-
const haveContent = useCheckVisibleContent(ref);
|
|
463
|
-
const style = useMemo(() => isDevMode ? {
|
|
464
|
-
minHeight: haveContent ? undefined : '4rem'
|
|
465
|
-
} : {}, [isDevMode, haveContent]);
|
|
466
|
-
const dotAttributes = useMemo(() => isDevMode ? getDotContentletAttributes(contentlet, container) : {}, [isDevMode, contentlet, container]);
|
|
467
|
-
return jsx("div", Object.assign({}, dotAttributes, {
|
|
468
|
-
"data-dot-object": "contentlet",
|
|
469
|
-
ref: ref,
|
|
470
|
-
style: style,
|
|
471
|
-
children: jsx(CustomComponent, {
|
|
472
|
-
contentlet: contentlet
|
|
473
|
-
})
|
|
474
|
-
}));
|
|
475
|
-
}
|
|
476
|
-
/**
|
|
477
|
-
* Renders a custom component based on the contentlet type or falls back to a default component
|
|
478
|
-
*
|
|
479
|
-
* @component
|
|
480
|
-
* @param {CustomComponentProps} props - Component properties
|
|
481
|
-
* @param {DotCMSContentlet} props.contentlet - The contentlet data to render
|
|
482
|
-
* @returns {JSX.Element} The rendered custom component or fallback component
|
|
483
|
-
*
|
|
484
|
-
* @internal
|
|
485
|
-
*/
|
|
486
|
-
function CustomComponent({
|
|
487
|
-
contentlet
|
|
488
|
-
}) {
|
|
489
|
-
const {
|
|
490
|
-
userComponents
|
|
491
|
-
} = useContext(DotCMSPageContext);
|
|
492
|
-
const UserComponent = userComponents[contentlet == null ? void 0 : contentlet.contentType];
|
|
493
|
-
if (UserComponent) {
|
|
494
|
-
return jsx(UserComponent, Object.assign({}, contentlet));
|
|
495
|
-
}
|
|
496
|
-
const UserNoComponent = userComponents['CustomNoComponent'];
|
|
497
|
-
return jsx(FallbackComponent, {
|
|
498
|
-
UserNoComponent: UserNoComponent,
|
|
499
|
-
contentlet: contentlet
|
|
500
|
-
});
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/**
|
|
504
|
-
* @internal
|
|
505
|
-
*
|
|
506
|
-
* Container component that renders DotCMS containers and their contentlets.
|
|
507
|
-
* This component is responsible for:
|
|
508
|
-
* - Rendering container content based on DotCMS Page API data
|
|
509
|
-
* - Handling empty container states
|
|
510
|
-
* - Providing proper data attributes for DotCMS functionality
|
|
511
|
-
* - Managing container contentlets rendering
|
|
512
|
-
*
|
|
513
|
-
* @component
|
|
514
|
-
* @param {DotCMSContainerRendererProps} props - Component properties
|
|
515
|
-
* @returns {JSX.Element} Rendered container with its contentlets or empty state message
|
|
516
|
-
*
|
|
517
|
-
* @example
|
|
518
|
-
* ```tsx
|
|
519
|
-
* <Container container={containerData} />
|
|
520
|
-
* ```
|
|
521
|
-
*/
|
|
522
|
-
function Container({
|
|
523
|
-
container
|
|
524
|
-
}) {
|
|
525
|
-
const {
|
|
526
|
-
pageAsset
|
|
527
|
-
} = useContext(DotCMSPageContext);
|
|
528
|
-
const containerData = useMemo(() => getContainersData(pageAsset, container), [pageAsset, container]);
|
|
529
|
-
const contentlets = useMemo(() => getContentletsInContainer(pageAsset, container), [pageAsset, container]);
|
|
530
|
-
if (!containerData) {
|
|
531
|
-
return jsx(ContainerNoFound, {
|
|
532
|
-
identifier: container.identifier
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
const isEmpty = contentlets.length === 0;
|
|
536
|
-
const dotAttributes = getDotContainerAttributes(containerData);
|
|
537
|
-
if (isEmpty) {
|
|
538
|
-
return jsx(EmptyContainer, Object.assign({}, dotAttributes));
|
|
539
|
-
}
|
|
540
|
-
return jsx("div", Object.assign({}, dotAttributes, {
|
|
541
|
-
children: contentlets.map(contentlet => jsx(Contentlet, {
|
|
542
|
-
contentlet: contentlet,
|
|
543
|
-
container: JSON.stringify(containerData)
|
|
544
|
-
}, contentlet.identifier))
|
|
545
|
-
}));
|
|
546
|
-
}
|
|
547
|
-
|
|
548
|
-
/**
|
|
549
|
-
* @internal
|
|
550
|
-
*
|
|
551
|
-
* Renders a Column component that represents a single column in a 12-column grid system.
|
|
552
|
-
* The column's position and width are determined by the leftOffset and width properties
|
|
553
|
-
* from the dotCMS Page API. Uses CSS Grid classes for positioning.
|
|
554
|
-
*
|
|
555
|
-
* @example
|
|
556
|
-
* ```tsx
|
|
557
|
-
* <Column column={{
|
|
558
|
-
* leftOffset: 0,
|
|
559
|
-
* width: 6,
|
|
560
|
-
* styleClass: "custom-class",
|
|
561
|
-
* containers: []
|
|
562
|
-
* }} />
|
|
563
|
-
* ```
|
|
564
|
-
*
|
|
565
|
-
* @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
|
|
566
|
-
* @export
|
|
567
|
-
* @param {ColumnProps} { column } - Column configuration object
|
|
568
|
-
* @return {JSX.Element} Rendered column with its containers positioned in the grid
|
|
569
|
-
*/
|
|
570
|
-
function Column({
|
|
571
|
-
column
|
|
572
|
-
}) {
|
|
573
|
-
const {
|
|
574
|
-
startClass,
|
|
575
|
-
endClass
|
|
576
|
-
} = getColumnPositionClasses(column);
|
|
577
|
-
const combinedClasses = combineClasses([styles[endClass], styles[startClass]]);
|
|
578
|
-
return jsx("div", {
|
|
579
|
-
"data-dot": "column",
|
|
580
|
-
className: combinedClasses,
|
|
581
|
-
children: jsx("div", {
|
|
582
|
-
className: column.styleClass,
|
|
583
|
-
children: column.containers.map(container => jsx(Container, {
|
|
584
|
-
container: container
|
|
585
|
-
}, `${container.identifier}-${container.uuid}`))
|
|
586
|
-
})
|
|
587
|
-
});
|
|
588
|
-
}
|
|
589
|
-
|
|
590
|
-
/**
|
|
591
|
-
* This component renders a row with all it's content using the layout provided by dotCMS Page API.
|
|
592
|
-
*
|
|
593
|
-
* @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
|
|
594
|
-
* @category Components
|
|
595
|
-
* @param {React.ForwardedRef<HTMLDivElement, DotCMS>} ref
|
|
596
|
-
* @return {JSX.Element} Rendered rows with columns
|
|
597
|
-
*/
|
|
598
|
-
const Row = ({
|
|
599
|
-
row
|
|
600
|
-
}) => {
|
|
601
|
-
const customRowClass = `${row.styleClass || ''} ${styles$1.row}`;
|
|
602
|
-
return jsx("div", {
|
|
603
|
-
className: "dot-row-container",
|
|
604
|
-
children: jsx("div", {
|
|
605
|
-
className: customRowClass,
|
|
606
|
-
"data-dot-object": 'row',
|
|
607
|
-
children: row.columns.map((column, index) => jsx(Column, {
|
|
608
|
-
column: column
|
|
609
|
-
}, index))
|
|
610
|
-
})
|
|
611
|
-
});
|
|
612
|
-
};
|
|
613
|
-
|
|
614
|
-
/**
|
|
615
|
-
* DotCMSLayoutBody component renders the layout body for a DotCMS page.
|
|
616
|
-
*
|
|
617
|
-
* It utilizes the dotCMS page asset's layout body to render the page body.
|
|
618
|
-
* If the layout body does not exist, it renders an error message in the mode is `development`.
|
|
619
|
-
*
|
|
620
|
-
* @public
|
|
621
|
-
* @component
|
|
622
|
-
* @param {Object} props - Component properties.
|
|
623
|
-
* @param {DotCMSPageAsset} props.page - The DotCMS page asset containing the layout information.
|
|
624
|
-
* @param {Record<string, React.ComponentType<DotCMSContentlet>>} [props.components] - mapping of custom components for content rendering.
|
|
625
|
-
* @param {DotCMSPageRendererMode} [props.mode='production'] - The renderer mode; defaults to 'production'. Alternate modes might trigger different behaviors.
|
|
626
|
-
*
|
|
627
|
-
* @returns {JSX.Element} The rendered DotCMS page body or an error message if the layout body is missing.
|
|
628
|
-
*
|
|
629
|
-
*/
|
|
630
|
-
const DotCMSLayoutBody = ({
|
|
631
|
-
page,
|
|
632
|
-
components: _components = {},
|
|
633
|
-
mode: _mode = 'production'
|
|
634
|
-
}) => {
|
|
635
|
-
var _page$layout;
|
|
636
|
-
const dotCMSPageBody = page == null || (_page$layout = page.layout) == null ? void 0 : _page$layout.body;
|
|
637
|
-
if (!dotCMSPageBody) {
|
|
638
|
-
return jsx(ErrorMessage, {
|
|
639
|
-
mode: _mode
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
const contextValue = {
|
|
643
|
-
pageAsset: page,
|
|
644
|
-
userComponents: _components,
|
|
645
|
-
mode: _mode
|
|
646
|
-
};
|
|
647
|
-
return jsx(DotCMSPageContext.Provider, {
|
|
648
|
-
value: contextValue,
|
|
649
|
-
children: dotCMSPageBody.rows.map((row, index) => jsx(Row, {
|
|
650
|
-
row: row
|
|
651
|
-
}, index))
|
|
652
|
-
});
|
|
653
|
-
};
|
|
654
|
-
|
|
655
|
-
/**
|
|
656
|
-
* Custom hook to determine if the current UVE (Universal Visual Editor) mode
|
|
657
|
-
* matches the specified mode. This hook is useful for conditionally rendering
|
|
658
|
-
* components based on the UVE mode.
|
|
659
|
-
*
|
|
660
|
-
* @param {UVE_MODE} when - The UVE mode to check against.
|
|
661
|
-
* @returns {boolean} True if the current UVE mode matches the specified mode, otherwise false.
|
|
662
|
-
*
|
|
663
|
-
* @example
|
|
664
|
-
* // Basic usage: Check if the UVE is in edit mode
|
|
665
|
-
* const showInEditMode = useShowInUVE(UVE_MODE.EDIT);
|
|
666
|
-
* if (showInEditMode) {
|
|
667
|
-
* // Render edit-specific components
|
|
668
|
-
* }
|
|
669
|
-
*
|
|
670
|
-
* @example
|
|
671
|
-
* // Check if the UVE is in preview mode
|
|
672
|
-
* const showInPreviewMode = useShowInUVE(UVE_MODE.PREVIEW);
|
|
673
|
-
* if (showInPreviewMode) {
|
|
674
|
-
* // Render preview-specific components
|
|
675
|
-
* }
|
|
676
|
-
*
|
|
677
|
-
* @example
|
|
678
|
-
* // Check if the UVE is in live mode
|
|
679
|
-
* const showInLiveMode = useShowInUVE(UVE_MODE.LIVE);
|
|
680
|
-
* if (showInLiveMode) {
|
|
681
|
-
* // Render live-specific components
|
|
682
|
-
* }
|
|
683
|
-
*/
|
|
684
|
-
const useShowInUVE = when => {
|
|
685
|
-
const [show, setShow] = useState(false);
|
|
686
|
-
useEffect(() => {
|
|
687
|
-
var _getUVEState;
|
|
688
|
-
setShow(((_getUVEState = getUVEState()) == null ? void 0 : _getUVEState.mode) === when);
|
|
689
|
-
}, [when]);
|
|
690
|
-
return show;
|
|
691
|
-
};
|
|
692
|
-
|
|
693
|
-
/**
|
|
694
|
-
* DotCMSShow component is used to conditionally render its children
|
|
695
|
-
* based on the Universal Visual Editor (UVE) mode. It checks if the UVE
|
|
696
|
-
* is in a specified mode and only renders its children in that case.
|
|
697
|
-
*
|
|
698
|
-
* @param {Object} props - The component props.
|
|
699
|
-
* @param {React.ReactNode} props.children - The children to be rendered when the condition is met.
|
|
700
|
-
* @param {UVE_MODE} [props.when=UVE_MODE.EDIT] - The UVE mode in which the children should be rendered.
|
|
701
|
-
* @returns {React.ReactNode | null} The children if the current UVE mode matches the `when` prop, otherwise null.
|
|
702
|
-
*
|
|
703
|
-
* @example
|
|
704
|
-
* // Basic usage: Render content only in edit mode
|
|
705
|
-
* <DotCMSShow when={UVE_MODE.EDIT}>
|
|
706
|
-
* <div>Edit Mode Content</div>
|
|
707
|
-
* </DotCMSShow>
|
|
708
|
-
*
|
|
709
|
-
* // This will render <div>Edit Mode Content</div> only if the UVE is in edit mode.
|
|
710
|
-
*
|
|
711
|
-
* @example
|
|
712
|
-
* // Render content in preview mode
|
|
713
|
-
* <DotCMSShow when={UVE_MODE.PREVIEW}>
|
|
714
|
-
* <MyCustomPreviewComponent />
|
|
715
|
-
* </DotCMSShow>
|
|
716
|
-
*
|
|
717
|
-
* // MyCustomPreviewComponent will only be rendered if the UVE is in preview mode.
|
|
718
|
-
*
|
|
719
|
-
* @example
|
|
720
|
-
* // Render content in live mode
|
|
721
|
-
* <DotCMSShow when={UVE_MODE.LIVE}>
|
|
722
|
-
* <LiveContentComponent />
|
|
723
|
-
* </DotCMSShow>
|
|
724
|
-
*
|
|
725
|
-
* // LiveContentComponent will only be rendered if the UVE is in live mode.
|
|
726
|
-
*/
|
|
727
|
-
const DotCMSShow = ({
|
|
728
|
-
children,
|
|
729
|
-
when: _when = UVE_MODE.EDIT
|
|
730
|
-
}) => {
|
|
731
|
-
const show = useShowInUVE(_when);
|
|
732
|
-
if (!show) {
|
|
733
|
-
return null;
|
|
734
|
-
}
|
|
735
|
-
return children;
|
|
736
|
-
};
|
|
737
|
-
|
|
738
|
-
export { DotCMSLayoutBody, DotCMSShow, useShowInUVE };
|