@dotcms/react 1.2.5-next.7 → 1.2.6-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 +71 -17
- package/_virtual/_commonjsHelpers.esm.js +3 -0
- package/_virtual/_style-inject.esm.js +30 -0
- package/_virtual/make-built-in.esm.js +3 -0
- package/_virtual/new-promise-capability.esm.js +3 -0
- package/_virtual/object-define-properties.esm.js +3 -0
- package/_virtual/object-define-property.esm.js +3 -0
- package/_virtual/object-get-own-property-descriptor.esm.js +3 -0
- package/_virtual/object-get-own-property-names.esm.js +3 -0
- package/_virtual/object-get-own-property-symbols.esm.js +3 -0
- package/_virtual/object-property-is-enumerable.esm.js +3 -0
- package/_virtual/shared-store.esm.js +3 -0
- package/index.esm.js +9 -7168
- package/index.server.d.ts +1 -0
- package/index.server.esm.js +8 -0
- package/libs/sdk/react/src/lib/next/components/Column/Column.esm.js +50 -0
- package/libs/sdk/react/src/lib/next/components/Column/Column.module.css.esm.js +8 -0
- package/libs/sdk/react/src/lib/next/components/Container/Container.esm.js +58 -0
- package/libs/sdk/react/src/lib/next/components/Container/ContainerFallbacks.esm.js +61 -0
- package/libs/sdk/react/src/lib/next/components/Contentlet/Contentlet.esm.js +88 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer.esm.js +46 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/BlockEditorBlock.esm.js +182 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Code.esm.js +37 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/DotContent.esm.js +47 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/GridBlock.esm.js +47 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Image.esm.js +22 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Lists.esm.js +43 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/NoComponentProvided.esm.js +40 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Table.esm.js +55 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Texts.esm.js +158 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Video.esm.js +43 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSEditableText/DotCMSEditableText.esm.js +190 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSEditableText/utils.esm.js +13 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody.esm.js +44 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/DotCMSPageProvider.esm.js +30 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/components/ErrorMessage.esm.js +43 -0
- package/libs/sdk/react/src/lib/next/components/DotCMSShow/DotCMSShow.esm.js +49 -0
- package/libs/sdk/react/src/lib/next/components/FallbackComponent/FallbackComponent.esm.js +55 -0
- package/libs/sdk/react/src/lib/next/components/Row/Row.esm.js +32 -0
- package/libs/sdk/react/src/lib/next/components/Row/Row.module.css.esm.js +8 -0
- package/libs/sdk/react/src/lib/next/contexts/DotCMSPageContext.esm.js +16 -0
- package/libs/sdk/react/src/lib/next/hooks/useAISearch.esm.js +131 -0
- package/libs/sdk/react/src/lib/next/hooks/useCheckVisibleContent.esm.js +42 -0
- package/libs/sdk/react/src/lib/next/hooks/useDotCMSShowWhen.esm.js +44 -0
- package/libs/sdk/react/src/lib/next/hooks/useEditableDotCMSPage.esm.js +133 -0
- package/libs/sdk/react/src/lib/next/hooks/useIsDevMode.esm.js +37 -0
- package/libs/sdk/react/src/lib/next/hooks/useStyleEditorSchemas.esm.js +15 -0
- package/libs/sdk/react/src/lib/next/utils/buildSlots.esm.js +46 -0
- package/package.json +2 -1
- package/src/index.d.ts +1 -0
- package/src/index.server.d.ts +11 -0
- package/src/lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer.d.ts +2 -1
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/BlockEditorBlock.d.ts +2 -1
- package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/DotContent.d.ts +2 -1
- package/src/lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody.d.ts +20 -1
- package/src/lib/next/components/DotCMSLayoutBody/DotCMSPageProvider.d.ts +18 -0
- package/src/lib/next/contexts/DotCMSPageContext.d.ts +3 -0
- package/src/lib/next/utils/buildSlots.d.ts +24 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { UVE_MODE } from '@dotcms/types';
|
|
2
|
+
import { useDotCMSShowWhen } from '../../hooks/useDotCMSShowWhen.esm.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* DotCMSShow component is used to conditionally render its children
|
|
6
|
+
* based on the Universal Visual Editor (UVE) mode. It checks if the UVE
|
|
7
|
+
* is in a specified mode and only renders its children in that case.
|
|
8
|
+
*
|
|
9
|
+
* @param {Object} props - The component props.
|
|
10
|
+
* @param {React.ReactNode} props.children - The children to be rendered when the condition is met.
|
|
11
|
+
* @param {UVE_MODE} [props.when=UVE_MODE.EDIT] - The UVE mode in which the children should be rendered.
|
|
12
|
+
* @returns {React.ReactNode | null} The children if the current UVE mode matches the `when` prop, otherwise null.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Basic usage: Render content only in edit mode
|
|
16
|
+
* <DotCMSShow when={UVE_MODE.EDIT}>
|
|
17
|
+
* <div>Edit Mode Content</div>
|
|
18
|
+
* </DotCMSShow>
|
|
19
|
+
*
|
|
20
|
+
* // This will render <div>Edit Mode Content</div> only if the UVE is in edit mode.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* // Render content in preview mode
|
|
24
|
+
* <DotCMSShow when={UVE_MODE.PREVIEW}>
|
|
25
|
+
* <MyCustomPreviewComponent />
|
|
26
|
+
* </DotCMSShow>
|
|
27
|
+
*
|
|
28
|
+
* // MyCustomPreviewComponent will only be rendered if the UVE is in preview mode.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* // Render content in live mode
|
|
32
|
+
* <DotCMSShow when={UVE_MODE.LIVE}>
|
|
33
|
+
* <LiveContentComponent />
|
|
34
|
+
* </DotCMSShow>
|
|
35
|
+
*
|
|
36
|
+
* // LiveContentComponent will only be rendered if the UVE is in live mode.
|
|
37
|
+
*/
|
|
38
|
+
const DotCMSShow = ({
|
|
39
|
+
children,
|
|
40
|
+
when: _when = UVE_MODE.EDIT
|
|
41
|
+
}) => {
|
|
42
|
+
const show = useDotCMSShowWhen(_when);
|
|
43
|
+
if (!show) {
|
|
44
|
+
return null;
|
|
45
|
+
}
|
|
46
|
+
return children;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export { DotCMSShow };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import '../../../../../../../../node_modules/core-js/modules/es.object.assign.esm.js';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
import { useIsDevMode } from '../../hooks/useIsDevMode.esm.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @internal
|
|
8
|
+
*
|
|
9
|
+
* Renders a fallback component when no matching component is found for a content type
|
|
10
|
+
*
|
|
11
|
+
* @component
|
|
12
|
+
* @param {DotCMSFallbackComponentProps} props - Component properties
|
|
13
|
+
* @param {NoComponentType} [props.UserNoComponent] - Optional custom component to render
|
|
14
|
+
* @param {DotCMSContentlet} [props.contentlet] - The contentlet that couldn't be rendered
|
|
15
|
+
* @returns {JSX.Element} The rendered fallback component
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```tsx
|
|
19
|
+
* <FallbackComponent
|
|
20
|
+
* UserNoComponent={CustomNoComponent}
|
|
21
|
+
* contentlet={contentlet}
|
|
22
|
+
* />
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
function FallbackComponent({
|
|
26
|
+
UserNoComponent,
|
|
27
|
+
contentlet
|
|
28
|
+
}) {
|
|
29
|
+
const isDevMode = useIsDevMode();
|
|
30
|
+
if (!isDevMode) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
const NoComponentFound = UserNoComponent || NoComponent;
|
|
34
|
+
return jsx(NoComponentFound, Object.assign({}, contentlet));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* @internal
|
|
38
|
+
*
|
|
39
|
+
* Component to render when there is no component for the content type.
|
|
40
|
+
*
|
|
41
|
+
* @param {DotCMSBasicContentlet} contentType - The content type that couldn't be rendered
|
|
42
|
+
* @return {*}
|
|
43
|
+
*/
|
|
44
|
+
function NoComponent({
|
|
45
|
+
contentType
|
|
46
|
+
}) {
|
|
47
|
+
return jsxs("div", {
|
|
48
|
+
"data-testid": "no-component",
|
|
49
|
+
children: ["No Component for ", jsx("strong", {
|
|
50
|
+
children: contentType
|
|
51
|
+
}), "."]
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { FallbackComponent };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import '../../../../../../../../node_modules/core-js/modules/esnext.iterator.constructor.esm.js';
|
|
2
|
+
import '../../../../../../../../node_modules/core-js/modules/esnext.iterator.map.esm.js';
|
|
3
|
+
import { jsx } from 'react/jsx-runtime';
|
|
4
|
+
import { combineClasses } from '@dotcms/uve/internal';
|
|
5
|
+
import styles from './Row.module.css.esm.js';
|
|
6
|
+
import { Column } from '../Column/Column.esm.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* This component renders a row with all it's content using the layout provided by dotCMS Page API.
|
|
10
|
+
*
|
|
11
|
+
* @see {@link https://www.dotcms.com/docs/latest/page-rest-api-layout-as-a-service-laas}
|
|
12
|
+
* @category Components
|
|
13
|
+
* @param {React.ForwardedRef<HTMLDivElement, DotCMS>} ref
|
|
14
|
+
* @return {JSX.Element} Rendered rows with columns
|
|
15
|
+
*/
|
|
16
|
+
const Row = ({
|
|
17
|
+
row
|
|
18
|
+
}) => {
|
|
19
|
+
const customRowClass = combineClasses(['dot-row-container', row.styleClass || '']);
|
|
20
|
+
return jsx("div", {
|
|
21
|
+
className: customRowClass,
|
|
22
|
+
children: jsx("div", {
|
|
23
|
+
className: styles.row,
|
|
24
|
+
"data-dot-object": 'row',
|
|
25
|
+
children: row.columns.map((column, index) => jsx(Column, {
|
|
26
|
+
column: column
|
|
27
|
+
}, index))
|
|
28
|
+
})
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export { Row };
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import styleInject from '../../../../../../../../_virtual/_style-inject.esm.js';
|
|
2
|
+
|
|
3
|
+
var css = "._row_1e5l5_1 {\n display: grid;\n grid-template-columns: repeat(12, 1fr);\n gap: 1rem;\n}\n";
|
|
4
|
+
|
|
5
|
+
styleInject(css);
|
|
6
|
+
var styles = {"row":"_row_1e5l5_1"};
|
|
7
|
+
|
|
8
|
+
export { styles as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { createContext } from 'react';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* The `PageContext` is a React context that provides access to the DotCMS page context.
|
|
6
|
+
*
|
|
7
|
+
* @category Contexts
|
|
8
|
+
*/
|
|
9
|
+
const DotCMSPageContext = /*#__PURE__*/createContext({
|
|
10
|
+
pageAsset: {},
|
|
11
|
+
mode: 'production',
|
|
12
|
+
userComponents: {},
|
|
13
|
+
slots: {}
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
export { DotCMSPageContext };
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import '../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../node_modules/core-js/modules/es.object.assign.esm.js';
|
|
3
|
+
import '../../../../../../../node_modules/core-js/modules/es.promise.constructor.esm.js';
|
|
4
|
+
import '../../../../../../../node_modules/core-js/modules/es.promise.all.esm.js';
|
|
5
|
+
import '../../../../../../../node_modules/core-js/modules/es.promise.catch.esm.js';
|
|
6
|
+
import '../../../../../../../node_modules/core-js/modules/es.promise.race.esm.js';
|
|
7
|
+
import '../../../../../../../node_modules/core-js/modules/es.promise.reject.esm.js';
|
|
8
|
+
import '../../../../../../../node_modules/core-js/modules/es.promise.resolve.esm.js';
|
|
9
|
+
import '../../../../../../../node_modules/core-js/modules/es.regexp.exec.esm.js';
|
|
10
|
+
import '../../../../../../../node_modules/core-js/modules/es.string.search.esm.js';
|
|
11
|
+
import '../../../../../../../node_modules/core-js/modules/es.string.trim.esm.js';
|
|
12
|
+
import '../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
13
|
+
import { useReducer, useRef, useEffect, useCallback } from 'react';
|
|
14
|
+
import { DotCMSEntityState } from '@dotcms/types';
|
|
15
|
+
|
|
16
|
+
function reducer(state, action) {
|
|
17
|
+
switch (action.type) {
|
|
18
|
+
case DotCMSEntityState.LOADING:
|
|
19
|
+
return Object.assign({}, state, {
|
|
20
|
+
status: {
|
|
21
|
+
state: DotCMSEntityState.LOADING
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
case DotCMSEntityState.SUCCESS:
|
|
25
|
+
return {
|
|
26
|
+
response: action.payload,
|
|
27
|
+
status: {
|
|
28
|
+
state: DotCMSEntityState.SUCCESS
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
case DotCMSEntityState.ERROR:
|
|
32
|
+
return Object.assign({}, state, {
|
|
33
|
+
status: {
|
|
34
|
+
state: DotCMSEntityState.ERROR,
|
|
35
|
+
error: action.payload
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
case DotCMSEntityState.IDLE:
|
|
39
|
+
return {
|
|
40
|
+
response: null,
|
|
41
|
+
status: {
|
|
42
|
+
state: DotCMSEntityState.IDLE
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
default:
|
|
46
|
+
return state;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Hook to search for contentlets using AI.
|
|
51
|
+
* @template T - The type of the contentlet.
|
|
52
|
+
* @param client - The client to use for the search.
|
|
53
|
+
* @param indexName - The name of the index to search in.
|
|
54
|
+
* @param params - The parameters for the search.
|
|
55
|
+
* @returns The search results.
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* ```typescript
|
|
59
|
+
* const { results, status, search, reset } = useAISearch<BlogPost>({
|
|
60
|
+
* client: dotCMSClient,
|
|
61
|
+
* indexName: 'blog-search-index',
|
|
62
|
+
* params: {
|
|
63
|
+
* query: {
|
|
64
|
+
* limit: 10,
|
|
65
|
+
* offset: 0,
|
|
66
|
+
* contentType: 'Blog'
|
|
67
|
+
* },
|
|
68
|
+
* config: {
|
|
69
|
+
* threshold: 0.5,
|
|
70
|
+
* responseLength: 1024
|
|
71
|
+
* }
|
|
72
|
+
* }
|
|
73
|
+
* });
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
const useAISearch = ({
|
|
77
|
+
client,
|
|
78
|
+
indexName,
|
|
79
|
+
params
|
|
80
|
+
}) => {
|
|
81
|
+
var _state$response$resul, _state$response;
|
|
82
|
+
const [state, dispatch] = useReducer(reducer, {
|
|
83
|
+
response: null,
|
|
84
|
+
status: {
|
|
85
|
+
state: DotCMSEntityState.IDLE
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
// Use ref to store params so search callback doesn't change when params change
|
|
89
|
+
const paramsRef = useRef(params);
|
|
90
|
+
// Keep ref updated with latest params
|
|
91
|
+
useEffect(() => {
|
|
92
|
+
paramsRef.current = params;
|
|
93
|
+
}, [params]);
|
|
94
|
+
const reset = useCallback(() => {
|
|
95
|
+
dispatch({
|
|
96
|
+
type: DotCMSEntityState.IDLE
|
|
97
|
+
});
|
|
98
|
+
}, []);
|
|
99
|
+
const search = useCallback(async prompt => {
|
|
100
|
+
if (!prompt.trim()) {
|
|
101
|
+
dispatch({
|
|
102
|
+
type: DotCMSEntityState.IDLE
|
|
103
|
+
});
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
dispatch({
|
|
107
|
+
type: DotCMSEntityState.LOADING
|
|
108
|
+
});
|
|
109
|
+
try {
|
|
110
|
+
const response = await client.ai.search(prompt, indexName, Object.assign({}, paramsRef.current));
|
|
111
|
+
dispatch({
|
|
112
|
+
type: DotCMSEntityState.SUCCESS,
|
|
113
|
+
payload: response
|
|
114
|
+
});
|
|
115
|
+
} catch (error) {
|
|
116
|
+
dispatch({
|
|
117
|
+
type: DotCMSEntityState.ERROR,
|
|
118
|
+
payload: error
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}, [client, indexName]);
|
|
122
|
+
return {
|
|
123
|
+
response: state.response,
|
|
124
|
+
results: (_state$response$resul = (_state$response = state.response) == null ? void 0 : _state$response.results) != null ? _state$response$resul : [],
|
|
125
|
+
status: state.status,
|
|
126
|
+
search,
|
|
127
|
+
reset
|
|
128
|
+
};
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export { useAISearch };
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import '../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
3
|
+
import { useState, useLayoutEffect } from 'react';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
* A custom React hook that checks whether a referenced HTMLDivElement has visible content based on its height.
|
|
8
|
+
*
|
|
9
|
+
* @param {RefObject<HTMLDivElement>} ref - A React ref object pointing to an HTMLDivElement.
|
|
10
|
+
* @returns {boolean} - Returns true if the element's height is greater than zero (indicating visible content), otherwise false.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* import { useRef } from 'react';
|
|
14
|
+
* import { useCheckVisibleContent } from 'src/lib/next/hooks/useCheckVisibleContent';
|
|
15
|
+
*
|
|
16
|
+
* function MyComponent() {
|
|
17
|
+
* const contentRef = useRef<HTMLDivElement>(null);
|
|
18
|
+
* const isContentVisible = useCheckVisibleContent(contentRef);
|
|
19
|
+
*
|
|
20
|
+
* return (
|
|
21
|
+
* <div ref={contentRef}>
|
|
22
|
+
* {isContentVisible ? 'Content is visible' : 'Content is not visible'}
|
|
23
|
+
* </div>
|
|
24
|
+
* );
|
|
25
|
+
* }
|
|
26
|
+
*/
|
|
27
|
+
const useCheckVisibleContent = ref => {
|
|
28
|
+
const [haveContent, setHaveContent] = useState(false);
|
|
29
|
+
useLayoutEffect(() => {
|
|
30
|
+
if (!ref.current) {
|
|
31
|
+
setHaveContent(false);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const {
|
|
35
|
+
height
|
|
36
|
+
} = ref.current.getBoundingClientRect();
|
|
37
|
+
setHaveContent(height > 0);
|
|
38
|
+
}, [ref]);
|
|
39
|
+
return haveContent;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { useCheckVisibleContent };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import '../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { getUVEState } from '@dotcms/uve';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Custom hook to determine if the current UVE (Universal Visual Editor) mode
|
|
8
|
+
* matches the specified mode. This hook is useful for conditionally rendering
|
|
9
|
+
* components based on the UVE mode.
|
|
10
|
+
*
|
|
11
|
+
* @param {UVE_MODE} when - The UVE mode to check against.
|
|
12
|
+
* @returns {boolean} True if the current UVE mode matches the specified mode, otherwise false.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Basic usage: Check if the UVE is in edit mode
|
|
16
|
+
* const showInEditMode = useDotCMSShowWhen(UVE_MODE.EDIT);
|
|
17
|
+
* if (showInEditMode) {
|
|
18
|
+
* // Render edit-specific components
|
|
19
|
+
* }
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // Check if the UVE is in preview mode
|
|
23
|
+
* const showInPreviewMode = useDotCMSShowWhen(UVE_MODE.PREVIEW);
|
|
24
|
+
* if (showInPreviewMode) {
|
|
25
|
+
* // Render preview-specific components
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // Check if the UVE is in live mode
|
|
30
|
+
* const showInLiveMode = useDotCMSShowWhen(UVE_MODE.LIVE);
|
|
31
|
+
* if (showInLiveMode) {
|
|
32
|
+
* // Render live-specific components
|
|
33
|
+
* }
|
|
34
|
+
*/
|
|
35
|
+
const useDotCMSShowWhen = when => {
|
|
36
|
+
const [show, setShow] = useState(false);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
var _getUVEState;
|
|
39
|
+
setShow(((_getUVEState = getUVEState()) == null ? void 0 : _getUVEState.mode) === when);
|
|
40
|
+
}, [when]);
|
|
41
|
+
return show;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { useDotCMSShowWhen };
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import '../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
3
|
+
import { useState, useEffect } from 'react';
|
|
4
|
+
import { UVEEventType } from '@dotcms/types';
|
|
5
|
+
import { getUVEState, initUVE, updateNavigation, createUVESubscription } from '@dotcms/uve';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Custom hook to manage the editable state of a DotCMS page.
|
|
9
|
+
*
|
|
10
|
+
* This hook initializes the Universal Visual Editor (UVE) and subscribes to content changes.
|
|
11
|
+
* It updates the editable page state when content changes are detected in the UVE,
|
|
12
|
+
* ensuring your React components always display the latest content when editing in DotCMS.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* // Import the hook and the client
|
|
17
|
+
* import { useEditableDotCMSPage } from '@dotcms/react';
|
|
18
|
+
* import { createDotCMSClient } from '@dotcms/client';
|
|
19
|
+
*
|
|
20
|
+
* // Create the client
|
|
21
|
+
* const client = createDotCMSClient({
|
|
22
|
+
* dotcmsURL: 'https://your-dotcms-instance.com',
|
|
23
|
+
* authToken: 'your-auth-token'
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* // Get the page
|
|
27
|
+
* const page = await client.page.get('/', {
|
|
28
|
+
* languageId: '1',
|
|
29
|
+
* });
|
|
30
|
+
*
|
|
31
|
+
* // Use the hook to get an editable version of the page
|
|
32
|
+
* const editablePage = useEditableDotCMSPage(page);
|
|
33
|
+
*
|
|
34
|
+
* // Then use the page data in your component
|
|
35
|
+
* return (
|
|
36
|
+
* <div>
|
|
37
|
+
* <h1>{editablePage.page.title}</h1>
|
|
38
|
+
* <div dangerouslySetInnerHTML={{ __html: editablePage.page.body }} />
|
|
39
|
+
* </div>
|
|
40
|
+
* );
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```ts
|
|
45
|
+
* // Import the hook and the client
|
|
46
|
+
* import { useEditableDotCMSPage } from '@dotcms/react';
|
|
47
|
+
* import { createDotCMSClient } from '@dotcms/client';
|
|
48
|
+
*
|
|
49
|
+
* // Create the client
|
|
50
|
+
* const client = createDotCMSClient({
|
|
51
|
+
* dotcmsURL: 'https://your-dotcms-instance.com',
|
|
52
|
+
* authToken: 'your-auth-token'
|
|
53
|
+
* });
|
|
54
|
+
*
|
|
55
|
+
* // Get the page with GraphQL content
|
|
56
|
+
* const page = await client.page.get('/', {
|
|
57
|
+
* languageId: '1',
|
|
58
|
+
* graphql: {
|
|
59
|
+
* content: {
|
|
60
|
+
* products: `ProductCollection(query: "+title:snow", limit: 10, offset: 0, sortBy: "score") {
|
|
61
|
+
* title
|
|
62
|
+
* urlMap
|
|
63
|
+
* category {
|
|
64
|
+
* name
|
|
65
|
+
* inode
|
|
66
|
+
* }
|
|
67
|
+
* retailPrice
|
|
68
|
+
* image {
|
|
69
|
+
* versionPath
|
|
70
|
+
* }
|
|
71
|
+
* }`
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* });
|
|
75
|
+
*
|
|
76
|
+
* // Use the hook to get an editable version of the page and its content
|
|
77
|
+
* const editablePage = useEditableDotCMSPage(page);
|
|
78
|
+
*
|
|
79
|
+
* // Access both page data and GraphQL content
|
|
80
|
+
* const { page: pageData, content } = editablePage;
|
|
81
|
+
*
|
|
82
|
+
* // Use the products from GraphQL content
|
|
83
|
+
* return (
|
|
84
|
+
* <div>
|
|
85
|
+
* <h1>{pageData.title}</h1>
|
|
86
|
+
* <ProductList products={content.products} />
|
|
87
|
+
* </div>
|
|
88
|
+
* );
|
|
89
|
+
* ```
|
|
90
|
+
* @param {DotCMSPageResponse} pageResponse - The initial editable page data from client.page.get().
|
|
91
|
+
*
|
|
92
|
+
* @returns {DotCMSPageResponse} The updated editable page state that reflects any changes made in the UVE.
|
|
93
|
+
* The structure includes page data and any GraphQL content that was requested.
|
|
94
|
+
*/
|
|
95
|
+
const useEditableDotCMSPage = pageResponse => {
|
|
96
|
+
const [updatedPageResponse, setUpdatedPageResponse] = useState(pageResponse);
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
var _pageResponse$pageAss;
|
|
99
|
+
if (!getUVEState()) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
if (!pageResponse) {
|
|
103
|
+
console.warn('[useEditableDotCMSPage]: No DotCMSPageResponse provided');
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const pageURI = pageResponse == null || (_pageResponse$pageAss = pageResponse.pageAsset) == null || (_pageResponse$pageAss = _pageResponse$pageAss.page) == null ? void 0 : _pageResponse$pageAss.pageURI;
|
|
107
|
+
const {
|
|
108
|
+
destroyUVESubscriptions
|
|
109
|
+
} = initUVE(pageResponse);
|
|
110
|
+
// Update the navigation to the pageURI, when we have a pageURI
|
|
111
|
+
// Sometimes the page is null due to permissions, so we don't want to update the navigation
|
|
112
|
+
// And wait for the UVE to resolve the page
|
|
113
|
+
if (pageURI) {
|
|
114
|
+
updateNavigation(pageURI);
|
|
115
|
+
}
|
|
116
|
+
return () => {
|
|
117
|
+
destroyUVESubscriptions();
|
|
118
|
+
};
|
|
119
|
+
}, [pageResponse]);
|
|
120
|
+
useEffect(() => {
|
|
121
|
+
const {
|
|
122
|
+
unsubscribe
|
|
123
|
+
} = createUVESubscription(UVEEventType.CONTENT_CHANGES, payload => {
|
|
124
|
+
setUpdatedPageResponse(payload);
|
|
125
|
+
});
|
|
126
|
+
return () => {
|
|
127
|
+
unsubscribe();
|
|
128
|
+
};
|
|
129
|
+
}, []);
|
|
130
|
+
return updatedPageResponse;
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export { useEditableDotCMSPage };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import '../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
3
|
+
import { useContext, useState, useEffect } from 'react';
|
|
4
|
+
import { UVE_MODE } from '@dotcms/types';
|
|
5
|
+
import { getUVEState } from '@dotcms/uve';
|
|
6
|
+
import { DEVELOPMENT_MODE } from '@dotcms/uve/internal';
|
|
7
|
+
import { DotCMSPageContext } from '../contexts/DotCMSPageContext.esm.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @internal
|
|
11
|
+
* A React hook that determines if the current environment is in development mode.
|
|
12
|
+
*
|
|
13
|
+
* The hook returns `true` if either:
|
|
14
|
+
* - The application is running inside the DotCMS editor (as determined by `getUVEState()`).
|
|
15
|
+
*
|
|
16
|
+
* @returns {boolean} - `true` if in development mode or inside the editor; otherwise, `false`.
|
|
17
|
+
*/
|
|
18
|
+
const useIsDevMode = () => {
|
|
19
|
+
const {
|
|
20
|
+
mode
|
|
21
|
+
} = useContext(DotCMSPageContext);
|
|
22
|
+
const [isDevMode, setIsDevMode] = useState(mode === 'development');
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
var _getUVEState;
|
|
25
|
+
// Inside UVE we rely on the UVE state to determine if we are in development mode
|
|
26
|
+
if ((_getUVEState = getUVEState()) != null && _getUVEState.mode) {
|
|
27
|
+
var _getUVEState2;
|
|
28
|
+
const isUVEInEditor = ((_getUVEState2 = getUVEState()) == null ? void 0 : _getUVEState2.mode) === UVE_MODE.EDIT;
|
|
29
|
+
setIsDevMode(isUVEInEditor);
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
setIsDevMode(mode === DEVELOPMENT_MODE);
|
|
33
|
+
}, [mode]);
|
|
34
|
+
return isDevMode;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export { useIsDevMode };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { registerStyleEditorSchemas } from '@dotcms/uve';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Hook to register style editor forms with the UVE editor.
|
|
6
|
+
* @param forms - Array of style editor form schemas to register
|
|
7
|
+
* @returns void
|
|
8
|
+
*/
|
|
9
|
+
const useStyleEditorSchemas = styleEditorForms => {
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
registerStyleEditorSchemas(styleEditorForms);
|
|
12
|
+
}, [styleEditorForms]);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export { useStyleEditorSchemas };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import '../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../node_modules/core-js/modules/es.object.assign.esm.js';
|
|
3
|
+
import '../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
4
|
+
import { jsx } from 'react/jsx-runtime';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Builds a slots map of pre-rendered server component nodes keyed by contentlet identifier.
|
|
8
|
+
*
|
|
9
|
+
* Use this in Next.js server components to render async server components
|
|
10
|
+
* (e.g., components that fetch data) within a DotCMS page layout. Pass the
|
|
11
|
+
* resulting map to `DotCMSLayoutBody` via the `slots` prop.
|
|
12
|
+
*
|
|
13
|
+
* @public
|
|
14
|
+
* @param containers - The containers map from `pageAsset.containers`
|
|
15
|
+
* @param serverComponents - A map of content type names to async server components
|
|
16
|
+
* @returns A record mapping contentlet identifiers to pre-rendered ReactNodes
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const slots = buildSlots(pageContent.pageAsset.containers, {
|
|
21
|
+
* BlogList: BlogListContainer,
|
|
22
|
+
* });
|
|
23
|
+
*
|
|
24
|
+
* <DotCMSLayoutBody page={pageAsset} components={pageComponents} slots={slots} />
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function buildSlots(containers,
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
serverComponents) {
|
|
30
|
+
const slots = {};
|
|
31
|
+
for (const {
|
|
32
|
+
contentlets
|
|
33
|
+
} of Object.values(containers)) {
|
|
34
|
+
for (const contentletList of Object.values(contentlets)) {
|
|
35
|
+
for (const contentlet of contentletList) {
|
|
36
|
+
const Component = serverComponents[contentlet.contentType];
|
|
37
|
+
if (Component) {
|
|
38
|
+
slots[contentlet.identifier] = jsx(Component, Object.assign({}, contentlet));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return slots;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { buildSlots };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dotcms/react",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.6-next.1",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"react": ">=18",
|
|
6
6
|
"react-dom": ">=18"
|
|
@@ -30,6 +30,7 @@
|
|
|
30
30
|
"exports": {
|
|
31
31
|
"./package.json": "./package.json",
|
|
32
32
|
".": {
|
|
33
|
+
"react-server": "./index.server.esm.js",
|
|
33
34
|
"import": "./index.esm.js",
|
|
34
35
|
"types": "./index.d.ts"
|
|
35
36
|
}
|
package/src/index.d.ts
CHANGED
|
@@ -8,3 +8,4 @@ export { DotCMSLayoutBodyProps } from './lib/next/components/DotCMSLayoutBody/Do
|
|
|
8
8
|
export { useAISearch } from './lib/next/hooks/useAISearch';
|
|
9
9
|
export { useStyleEditorSchemas } from './lib/next/hooks/useStyleEditorSchemas';
|
|
10
10
|
export type { DotCMSAISearchValue, DotCMSAISearchProps } from './lib/next/shared/types';
|
|
11
|
+
export { buildSlots } from './lib/next/utils/buildSlots';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { DotCMSLayoutBody } from './lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody';
|
|
2
|
+
export { DotCMSShow } from './lib/next/components/DotCMSShow/DotCMSShow';
|
|
3
|
+
export { useDotCMSShowWhen } from './lib/next/hooks/useDotCMSShowWhen';
|
|
4
|
+
export { useEditableDotCMSPage } from './lib/next/hooks/useEditableDotCMSPage';
|
|
5
|
+
export { DotCMSBlockEditorRenderer, CustomRenderer } from './lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer';
|
|
6
|
+
export type { BlockEditorRendererProps, CustomRendererProps } from './lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer';
|
|
7
|
+
export type { DotCMSLayoutBodyProps } from './lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody';
|
|
8
|
+
export { useAISearch } from './lib/next/hooks/useAISearch';
|
|
9
|
+
export { useStyleEditorSchemas } from './lib/next/hooks/useStyleEditorSchemas';
|
|
10
|
+
export type { DotCMSAISearchValue, DotCMSAISearchProps } from './lib/next/shared/types';
|
|
11
|
+
export { buildSlots } from './lib/next/utils/buildSlots';
|
|
@@ -38,6 +38,7 @@ export interface BlockEditorRendererProps {
|
|
|
38
38
|
style?: React.CSSProperties;
|
|
39
39
|
className?: string;
|
|
40
40
|
customRenderers?: CustomRenderer;
|
|
41
|
+
isDevMode?: boolean;
|
|
41
42
|
}
|
|
42
43
|
/**
|
|
43
44
|
* BlockEditorRenderer component for rendering block editor field.
|
|
@@ -50,4 +51,4 @@ export interface BlockEditorRendererProps {
|
|
|
50
51
|
* @param {React.CSSProperties} [props.style] - Optional inline styles for the container div.
|
|
51
52
|
* @returns {JSX.Element} A div containing the rendered blocks of content.
|
|
52
53
|
*/
|
|
53
|
-
export declare const DotCMSBlockEditorRenderer: ({ blocks, style, className, customRenderers }: BlockEditorRendererProps) => import("react/jsx-runtime").JSX.Element | null;
|
|
54
|
+
export declare const DotCMSBlockEditorRenderer: ({ blocks, style, className, customRenderers, isDevMode }: BlockEditorRendererProps) => import("react/jsx-runtime").JSX.Element | null;
|