@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.
Files changed (58) hide show
  1. package/README.md +71 -17
  2. package/_virtual/_commonjsHelpers.esm.js +3 -0
  3. package/_virtual/_style-inject.esm.js +30 -0
  4. package/_virtual/make-built-in.esm.js +3 -0
  5. package/_virtual/new-promise-capability.esm.js +3 -0
  6. package/_virtual/object-define-properties.esm.js +3 -0
  7. package/_virtual/object-define-property.esm.js +3 -0
  8. package/_virtual/object-get-own-property-descriptor.esm.js +3 -0
  9. package/_virtual/object-get-own-property-names.esm.js +3 -0
  10. package/_virtual/object-get-own-property-symbols.esm.js +3 -0
  11. package/_virtual/object-property-is-enumerable.esm.js +3 -0
  12. package/_virtual/shared-store.esm.js +3 -0
  13. package/index.esm.js +9 -7168
  14. package/index.server.d.ts +1 -0
  15. package/index.server.esm.js +8 -0
  16. package/libs/sdk/react/src/lib/next/components/Column/Column.esm.js +50 -0
  17. package/libs/sdk/react/src/lib/next/components/Column/Column.module.css.esm.js +8 -0
  18. package/libs/sdk/react/src/lib/next/components/Container/Container.esm.js +58 -0
  19. package/libs/sdk/react/src/lib/next/components/Container/ContainerFallbacks.esm.js +61 -0
  20. package/libs/sdk/react/src/lib/next/components/Contentlet/Contentlet.esm.js +88 -0
  21. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer.esm.js +46 -0
  22. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/BlockEditorBlock.esm.js +182 -0
  23. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Code.esm.js +37 -0
  24. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/DotContent.esm.js +47 -0
  25. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/GridBlock.esm.js +47 -0
  26. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Image.esm.js +22 -0
  27. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Lists.esm.js +43 -0
  28. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/NoComponentProvided.esm.js +40 -0
  29. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Table.esm.js +55 -0
  30. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Texts.esm.js +158 -0
  31. package/libs/sdk/react/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/Video.esm.js +43 -0
  32. package/libs/sdk/react/src/lib/next/components/DotCMSEditableText/DotCMSEditableText.esm.js +190 -0
  33. package/libs/sdk/react/src/lib/next/components/DotCMSEditableText/utils.esm.js +13 -0
  34. package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody.esm.js +44 -0
  35. package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/DotCMSPageProvider.esm.js +30 -0
  36. package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/components/ErrorMessage.esm.js +43 -0
  37. package/libs/sdk/react/src/lib/next/components/DotCMSShow/DotCMSShow.esm.js +49 -0
  38. package/libs/sdk/react/src/lib/next/components/FallbackComponent/FallbackComponent.esm.js +55 -0
  39. package/libs/sdk/react/src/lib/next/components/Row/Row.esm.js +32 -0
  40. package/libs/sdk/react/src/lib/next/components/Row/Row.module.css.esm.js +8 -0
  41. package/libs/sdk/react/src/lib/next/contexts/DotCMSPageContext.esm.js +16 -0
  42. package/libs/sdk/react/src/lib/next/hooks/useAISearch.esm.js +131 -0
  43. package/libs/sdk/react/src/lib/next/hooks/useCheckVisibleContent.esm.js +42 -0
  44. package/libs/sdk/react/src/lib/next/hooks/useDotCMSShowWhen.esm.js +44 -0
  45. package/libs/sdk/react/src/lib/next/hooks/useEditableDotCMSPage.esm.js +133 -0
  46. package/libs/sdk/react/src/lib/next/hooks/useIsDevMode.esm.js +37 -0
  47. package/libs/sdk/react/src/lib/next/hooks/useStyleEditorSchemas.esm.js +15 -0
  48. package/libs/sdk/react/src/lib/next/utils/buildSlots.esm.js +46 -0
  49. package/package.json +2 -1
  50. package/src/index.d.ts +1 -0
  51. package/src/index.server.d.ts +11 -0
  52. package/src/lib/next/components/DotCMSBlockEditorRenderer/DotCMSBlockEditorRenderer.d.ts +2 -1
  53. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/BlockEditorBlock.d.ts +2 -1
  54. package/src/lib/next/components/DotCMSBlockEditorRenderer/components/blocks/DotContent.d.ts +2 -1
  55. package/src/lib/next/components/DotCMSLayoutBody/DotCMSLayoutBody.d.ts +20 -1
  56. package/src/lib/next/components/DotCMSLayoutBody/DotCMSPageProvider.d.ts +18 -0
  57. package/src/lib/next/contexts/DotCMSPageContext.d.ts +3 -0
  58. 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.5-next.7",
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;