@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.
Files changed (57) hide show
  1. package/README.md +531 -93
  2. package/index.esm.js +2992 -786
  3. package/package.json +10 -12
  4. package/src/index.d.ts +7 -1
  5. package/src/lib/next/__test__/mock.d.ts +2 -1
  6. package/src/lib/next/components/Column/Column.d.ts +1 -1
  7. package/src/lib/next/components/Container/Container.d.ts +1 -1
  8. package/src/lib/next/components/Container/{ContainerFallbakcs.d.ts → ContainerFallbacks.d.ts} +2 -2
  9. package/src/lib/next/components/Contentlet/Contentlet.d.ts +2 -2
  10. package/src/lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer.d.ts +27 -0
  11. package/src/lib/{deprecated/components/BlockEditorRenderer/item → next/components/DotCMSBlockEditorRenderer/components}/BlockEditorBlock.d.ts +8 -5
  12. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Code.d.ts +24 -0
  13. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/DotContent.d.ts +14 -0
  14. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Image.d.ts +10 -0
  15. package/src/lib/{deprecated/components/BlockEditorRenderer → next/components/DotCMSBlockEditorRenderer/components}/blocks/Lists.d.ts +8 -4
  16. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/NoComponentProvided.d.ts +3 -0
  17. package/src/lib/{deprecated/components/BlockEditorRenderer → next/components/DotCMSBlockEditorRenderer/components}/blocks/Table.d.ts +3 -3
  18. package/src/lib/{deprecated/components/BlockEditorRenderer → next/components/DotCMSBlockEditorRenderer/components}/blocks/Texts.d.ts +23 -13
  19. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Video.d.ts +10 -0
  20. package/src/lib/{deprecated/components/DotEditableText/DotEditableText.d.ts → next/components/DotCMSEditableText/DotCMSEditableText.d.ts} +8 -6
  21. package/src/lib/{deprecated/components/DotEditableText → next/components/DotCMSEditableText}/utils.d.ts +9 -9
  22. package/src/lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody.d.ts +5 -5
  23. package/src/lib/next/components/DotCMSLayoutBody/components/ErrorMessage.d.ts +1 -4
  24. package/src/lib/next/components/DotCMSShow/DotCMSShow.d.ts +2 -2
  25. package/src/lib/next/components/FallbackComponent/FallbackComponent.d.ts +6 -6
  26. package/src/lib/next/components/Row/Row.d.ts +1 -1
  27. package/src/lib/next/contexts/DotCMSPageContext.d.ts +2 -3
  28. package/src/lib/next/hooks/{useShowInUVE.d.ts → useDotCMSShowWhen.d.ts} +5 -5
  29. package/src/lib/next/hooks/useEditableDotCMSPage.d.ts +90 -0
  30. package/src/lib/next/hooks/useIsDevMode.d.ts +2 -5
  31. package/es.regexp.to-string.esm.js +0 -1878
  32. package/next.esm.d.ts +0 -1
  33. package/next.esm.js +0 -738
  34. package/src/lib/deprecated/components/BlockEditorRenderer/BlockEditorRenderer.d.ts +0 -37
  35. package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Code.d.ts +0 -17
  36. package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Contentlet.d.ts +0 -41
  37. package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Image.d.ts +0 -8
  38. package/src/lib/deprecated/components/BlockEditorRenderer/blocks/Video.d.ts +0 -8
  39. package/src/lib/deprecated/components/Column/Column.d.ts +0 -19
  40. package/src/lib/deprecated/components/Container/Container.d.ts +0 -19
  41. package/src/lib/deprecated/components/DotcmsLayout/DotcmsLayout.d.ts +0 -34
  42. package/src/lib/deprecated/components/PageProvider/PageProvider.d.ts +0 -14
  43. package/src/lib/deprecated/components/Row/Row.d.ts +0 -26
  44. package/src/lib/deprecated/contexts/PageContext.d.ts +0 -8
  45. package/src/lib/deprecated/deprecated_api.d.ts +0 -7
  46. package/src/lib/deprecated/hooks/useCheckHaveContent.d.ts +0 -5
  47. package/src/lib/deprecated/hooks/useDotcmsEditor.d.ts +0 -13
  48. package/src/lib/deprecated/hooks/useDotcmsPageContext.d.ts +0 -9
  49. package/src/lib/deprecated/mocks/index.d.ts +0 -1
  50. package/src/lib/deprecated/mocks/mockPageContext.d.ts +0 -7
  51. package/src/lib/deprecated/models/blocks.interface.d.ts +0 -89
  52. package/src/lib/deprecated/models/content-node.interface.d.ts +0 -82
  53. package/src/lib/deprecated/models/index.d.ts +0 -127
  54. package/src/lib/deprecated/utils/utils.d.ts +0 -58
  55. package/src/lib/next/types.d.ts +0 -421
  56. package/src/lib/next/utils/index.d.ts +0 -136
  57. 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 };