@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,43 @@
|
|
|
1
|
+
import { jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* ListItem component represents a list item in a block editor.
|
|
5
|
+
*
|
|
6
|
+
* @param children - The content of the list item.
|
|
7
|
+
* @returns The rendered list item element.
|
|
8
|
+
*/
|
|
9
|
+
const ListItem = ({
|
|
10
|
+
children
|
|
11
|
+
}) => {
|
|
12
|
+
return jsx("li", {
|
|
13
|
+
children: children
|
|
14
|
+
});
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Renders an ordered list component.
|
|
18
|
+
*
|
|
19
|
+
* @param children - The content to be rendered inside the ordered list.
|
|
20
|
+
* @returns The ordered list component.
|
|
21
|
+
*/
|
|
22
|
+
const OrderedList = ({
|
|
23
|
+
children
|
|
24
|
+
}) => {
|
|
25
|
+
return jsx("ol", {
|
|
26
|
+
children: children
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Renders a bullet list component.
|
|
31
|
+
*
|
|
32
|
+
* @param children - The content of the bullet list.
|
|
33
|
+
* @returns The rendered bullet list component.
|
|
34
|
+
*/
|
|
35
|
+
const BulletList = ({
|
|
36
|
+
children
|
|
37
|
+
}) => {
|
|
38
|
+
return jsx("ul", {
|
|
39
|
+
children: children
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { BulletList, ListItem, OrderedList };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
|
+
|
|
3
|
+
const NoComponentProvided = ({
|
|
4
|
+
contentType
|
|
5
|
+
}) => {
|
|
6
|
+
const style = {
|
|
7
|
+
backgroundColor: '#fffaf0',
|
|
8
|
+
color: '#333',
|
|
9
|
+
padding: '1rem',
|
|
10
|
+
borderRadius: '0.5rem',
|
|
11
|
+
marginBottom: '1rem',
|
|
12
|
+
marginTop: '1rem',
|
|
13
|
+
border: '1px solid #ed8936'
|
|
14
|
+
};
|
|
15
|
+
return jsxs("div", {
|
|
16
|
+
"data-testid": "no-component-provided",
|
|
17
|
+
style: style,
|
|
18
|
+
children: [jsx("strong", {
|
|
19
|
+
style: {
|
|
20
|
+
color: '#c05621'
|
|
21
|
+
},
|
|
22
|
+
children: "Dev Warning"
|
|
23
|
+
}), ": No component or custom renderer provided for content type", jsx("strong", {
|
|
24
|
+
style: {
|
|
25
|
+
color: '#c05621'
|
|
26
|
+
},
|
|
27
|
+
children: contentType || 'Unknown'
|
|
28
|
+
}), ".", jsx("br", {}), "Please refer to the", jsx("a", {
|
|
29
|
+
href: "https://dev.dotcms.com/docs/block-editor",
|
|
30
|
+
target: "_blank",
|
|
31
|
+
rel: "noopener noreferrer",
|
|
32
|
+
style: {
|
|
33
|
+
color: '#c05621'
|
|
34
|
+
},
|
|
35
|
+
children: "Block Editor Custom Renderers Documentation"
|
|
36
|
+
}), ' ', "for guidance."]
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export { NoComponentProvided };
|
|
@@ -0,0 +1,55 @@
|
|
|
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 { jsxs, jsx } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Renders a table component for the Block Editor.
|
|
7
|
+
*
|
|
8
|
+
* @param content - The content of the table.
|
|
9
|
+
* @param blockEditorItem - The Block Editor item component.
|
|
10
|
+
*/
|
|
11
|
+
const TableRenderer = ({
|
|
12
|
+
content,
|
|
13
|
+
blockEditorItem
|
|
14
|
+
}) => {
|
|
15
|
+
const BlockEditorItemComponent = blockEditorItem;
|
|
16
|
+
const renderTableContent = node => {
|
|
17
|
+
var _node$content;
|
|
18
|
+
return jsx(BlockEditorItemComponent, {
|
|
19
|
+
content: (_node$content = node.content) != null ? _node$content : []
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
return jsxs("table", {
|
|
23
|
+
children: [jsx("thead", {
|
|
24
|
+
children: content.slice(0, 1).map((rowNode, rowIndex) => {
|
|
25
|
+
var _rowNode$content;
|
|
26
|
+
return jsx("tr", {
|
|
27
|
+
children: (_rowNode$content = rowNode.content) == null ? void 0 : _rowNode$content.map((cellNode, cellIndex) => {
|
|
28
|
+
var _cellNode$attrs, _cellNode$attrs2;
|
|
29
|
+
return jsx("th", {
|
|
30
|
+
colSpan: Number(((_cellNode$attrs = cellNode.attrs) == null ? void 0 : _cellNode$attrs.colspan) || 1),
|
|
31
|
+
rowSpan: Number(((_cellNode$attrs2 = cellNode.attrs) == null ? void 0 : _cellNode$attrs2.rowspan) || 1),
|
|
32
|
+
children: renderTableContent(cellNode)
|
|
33
|
+
}, `${cellNode.type}-${cellIndex}`);
|
|
34
|
+
})
|
|
35
|
+
}, `${rowNode.type}-${rowIndex}`);
|
|
36
|
+
})
|
|
37
|
+
}), jsx("tbody", {
|
|
38
|
+
children: content.slice(1).map((rowNode, rowIndex) => {
|
|
39
|
+
var _rowNode$content2;
|
|
40
|
+
return jsx("tr", {
|
|
41
|
+
children: (_rowNode$content2 = rowNode.content) == null ? void 0 : _rowNode$content2.map((cellNode, cellIndex) => {
|
|
42
|
+
var _cellNode$attrs3, _cellNode$attrs4;
|
|
43
|
+
return jsx("td", {
|
|
44
|
+
colSpan: Number(((_cellNode$attrs3 = cellNode.attrs) == null ? void 0 : _cellNode$attrs3.colspan) || 1),
|
|
45
|
+
rowSpan: Number(((_cellNode$attrs4 = cellNode.attrs) == null ? void 0 : _cellNode$attrs4.rowspan) || 1),
|
|
46
|
+
children: renderTableContent(cellNode)
|
|
47
|
+
}, `${cellNode.type}-${cellIndex}`);
|
|
48
|
+
})
|
|
49
|
+
}, `${rowNode.type}-${rowIndex}`);
|
|
50
|
+
})
|
|
51
|
+
})]
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export { TableRenderer };
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import '../../../../../../../../../../node_modules/core-js/modules/es.object.assign.esm.js';
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Renders the text in bold.
|
|
6
|
+
*
|
|
7
|
+
* @param children - The content to be rendered in bold.
|
|
8
|
+
*/
|
|
9
|
+
const Bold = ({
|
|
10
|
+
children
|
|
11
|
+
}) => jsx("strong", {
|
|
12
|
+
children: children
|
|
13
|
+
});
|
|
14
|
+
/**
|
|
15
|
+
* Renders the text in italic format.
|
|
16
|
+
*
|
|
17
|
+
* @param children - The content to be rendered in italic.
|
|
18
|
+
*/
|
|
19
|
+
const Italic = ({
|
|
20
|
+
children
|
|
21
|
+
}) => jsx("em", {
|
|
22
|
+
children: children
|
|
23
|
+
});
|
|
24
|
+
/**
|
|
25
|
+
* Renders a strike-through text.
|
|
26
|
+
*
|
|
27
|
+
* @param children - The content to be rendered within the strike-through element.
|
|
28
|
+
*/
|
|
29
|
+
const Strike = ({
|
|
30
|
+
children
|
|
31
|
+
}) => jsx("s", {
|
|
32
|
+
children: children
|
|
33
|
+
});
|
|
34
|
+
/**
|
|
35
|
+
* Renders an underline element for the given children.
|
|
36
|
+
*
|
|
37
|
+
* @param children - The content to be underlined.
|
|
38
|
+
*/
|
|
39
|
+
const Underline = ({
|
|
40
|
+
children
|
|
41
|
+
}) => jsx("u", {
|
|
42
|
+
children: children
|
|
43
|
+
});
|
|
44
|
+
/**
|
|
45
|
+
* Renders a paragraph element.
|
|
46
|
+
*
|
|
47
|
+
* @param children - The content of the paragraph.
|
|
48
|
+
* @param attrs - The style attributes for the paragraph.
|
|
49
|
+
* @returns The rendered paragraph element.
|
|
50
|
+
*/
|
|
51
|
+
const Paragraph = ({
|
|
52
|
+
children,
|
|
53
|
+
node
|
|
54
|
+
}) => {
|
|
55
|
+
const attrs = (node == null ? void 0 : node.attrs) || {};
|
|
56
|
+
return jsx("p", {
|
|
57
|
+
style: attrs,
|
|
58
|
+
children: children
|
|
59
|
+
});
|
|
60
|
+
};
|
|
61
|
+
/**
|
|
62
|
+
* Renders a link component.
|
|
63
|
+
*
|
|
64
|
+
* @param children - The content of the link.
|
|
65
|
+
* @param attrs - The attributes to be applied to the link.
|
|
66
|
+
* @returns The rendered link component.
|
|
67
|
+
*/
|
|
68
|
+
const Link = ({
|
|
69
|
+
children,
|
|
70
|
+
attrs
|
|
71
|
+
}) => {
|
|
72
|
+
return jsx("a", Object.assign({}, attrs, {
|
|
73
|
+
children: children
|
|
74
|
+
}));
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Renders a heading element with the specified level.
|
|
78
|
+
*
|
|
79
|
+
* @param children - The content of the heading.
|
|
80
|
+
* @param attrs - The attributes for the heading.
|
|
81
|
+
* @returns The rendered heading element.
|
|
82
|
+
*/
|
|
83
|
+
const Heading = ({
|
|
84
|
+
children,
|
|
85
|
+
node
|
|
86
|
+
}) => {
|
|
87
|
+
const attrs = (node == null ? void 0 : node.attrs) || {};
|
|
88
|
+
const level = attrs.level || 1;
|
|
89
|
+
const Tag = `h${level}`;
|
|
90
|
+
return jsx(Tag, {
|
|
91
|
+
children: children
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Renders the superscript text.
|
|
96
|
+
*
|
|
97
|
+
* @param children - The content to be rendered as superscript.
|
|
98
|
+
*/
|
|
99
|
+
const Superscript = ({
|
|
100
|
+
children
|
|
101
|
+
}) => jsx("sup", {
|
|
102
|
+
children: children
|
|
103
|
+
});
|
|
104
|
+
/**
|
|
105
|
+
* Renders a subscript element.
|
|
106
|
+
*
|
|
107
|
+
* @param children - The content to be rendered as subscript.
|
|
108
|
+
*/
|
|
109
|
+
const Subscript = ({
|
|
110
|
+
children
|
|
111
|
+
}) => jsx("sub", {
|
|
112
|
+
children: children
|
|
113
|
+
});
|
|
114
|
+
const nodeMarks = {
|
|
115
|
+
bold: Bold,
|
|
116
|
+
link: Link,
|
|
117
|
+
italic: Italic,
|
|
118
|
+
strike: Strike,
|
|
119
|
+
subscript: Subscript,
|
|
120
|
+
underline: Underline,
|
|
121
|
+
superscript: Superscript
|
|
122
|
+
};
|
|
123
|
+
const defaultMark = {
|
|
124
|
+
type: '',
|
|
125
|
+
attrs: {}
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* Renders a text block with optional marks.
|
|
129
|
+
*
|
|
130
|
+
* @param props - The props for the TextBlock component.
|
|
131
|
+
* @returns The rendered text block.
|
|
132
|
+
*/
|
|
133
|
+
const TextBlock = (props = {}) => {
|
|
134
|
+
const {
|
|
135
|
+
marks = [],
|
|
136
|
+
text
|
|
137
|
+
} = props;
|
|
138
|
+
const mark = marks[0] || defaultMark;
|
|
139
|
+
const textProps = Object.assign({}, props, {
|
|
140
|
+
marks: marks.slice(1)
|
|
141
|
+
});
|
|
142
|
+
const Component = nodeMarks[mark == null ? void 0 : mark.type];
|
|
143
|
+
// In React, class is not a valid attribute name, so we need to rename it to className
|
|
144
|
+
if (mark.attrs) {
|
|
145
|
+
mark.attrs.className = mark.attrs.class;
|
|
146
|
+
delete mark.attrs.class;
|
|
147
|
+
}
|
|
148
|
+
if (!Component) {
|
|
149
|
+
return text;
|
|
150
|
+
}
|
|
151
|
+
return jsx(Component, {
|
|
152
|
+
type: mark.type,
|
|
153
|
+
attrs: mark.attrs,
|
|
154
|
+
children: jsx(TextBlock, Object.assign({}, textProps))
|
|
155
|
+
});
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export { Bold, Heading, Italic, Link, Paragraph, Strike, Subscript, Superscript, TextBlock, Underline };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import '../../../../../../../../../../node_modules/core-js/modules/es.object.assign.esm.js';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Renders a video component for displaying videos.
|
|
6
|
+
*
|
|
7
|
+
* @param props - The properties for the video component.
|
|
8
|
+
* @returns The rendered video component.
|
|
9
|
+
*/
|
|
10
|
+
const DotCMSVideo = ({
|
|
11
|
+
node
|
|
12
|
+
}) => {
|
|
13
|
+
const {
|
|
14
|
+
data,
|
|
15
|
+
src,
|
|
16
|
+
mimeType,
|
|
17
|
+
width,
|
|
18
|
+
height
|
|
19
|
+
} = node.attrs;
|
|
20
|
+
const poster = data == null ? void 0 : data.thumbnail;
|
|
21
|
+
const posterAttribute = poster ? {
|
|
22
|
+
poster
|
|
23
|
+
} : {};
|
|
24
|
+
return jsxs("video", Object.assign({
|
|
25
|
+
controls: true,
|
|
26
|
+
preload: "metadata",
|
|
27
|
+
width: width,
|
|
28
|
+
height: height
|
|
29
|
+
}, posterAttribute, {
|
|
30
|
+
children: [jsx("track", {
|
|
31
|
+
default: true,
|
|
32
|
+
kind: "captions",
|
|
33
|
+
srcLang: "en"
|
|
34
|
+
}), jsx("source", {
|
|
35
|
+
src: src,
|
|
36
|
+
type: mimeType
|
|
37
|
+
}), "Your browser does not support the ", jsx("code", {
|
|
38
|
+
children: "video"
|
|
39
|
+
}), " element."]
|
|
40
|
+
}));
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { DotCMSVideo };
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import '../../../../../../../../node_modules/core-js/modules/es.array.iterator.esm.js';
|
|
2
|
+
import '../../../../../../../../node_modules/core-js/modules/es.regexp.to-string.esm.js';
|
|
3
|
+
import '../../../../../../../../node_modules/core-js/modules/web.dom-collections.iterator.esm.js';
|
|
4
|
+
import '../../../../../../../../node_modules/core-js/modules/web.url.constructor.esm.js';
|
|
5
|
+
import '../../../../../../../../node_modules/core-js/modules/web.url.to-json.esm.js';
|
|
6
|
+
import '../../../../../../../../node_modules/core-js/modules/web.url-search-params.constructor.esm.js';
|
|
7
|
+
import '../../../../../../../../node_modules/core-js/modules/web.url-search-params.delete.esm.js';
|
|
8
|
+
import '../../../../../../../../node_modules/core-js/modules/web.url-search-params.has.esm.js';
|
|
9
|
+
import '../../../../../../../../node_modules/core-js/modules/web.url-search-params.size.esm.js';
|
|
10
|
+
import { jsx } from 'react/jsx-runtime';
|
|
11
|
+
import { Editor } from '@tinymce/tinymce-react';
|
|
12
|
+
import { useRef, useState, useEffect } from 'react';
|
|
13
|
+
import { UVE_MODE, DotCMSUVEAction } from '@dotcms/types';
|
|
14
|
+
import { __DOTCMS_UVE_EVENT__ } from '@dotcms/types/internal';
|
|
15
|
+
import { getUVEState, sendMessageToUVE } from '@dotcms/uve';
|
|
16
|
+
import { __TINYMCE_PATH_ON_DOTCMS__ } from '@dotcms/uve/internal';
|
|
17
|
+
import { TINYMCE_CONFIG } from './utils.esm.js';
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Allows inline edit content pulled from dotCMS API using TinyMCE editor
|
|
21
|
+
*
|
|
22
|
+
* @export
|
|
23
|
+
* @component
|
|
24
|
+
* @param {Readonly<DotCMSEditableTextProps>} props {
|
|
25
|
+
* mode = 'plain',
|
|
26
|
+
* format = 'text',
|
|
27
|
+
* contentlet,
|
|
28
|
+
* fieldName = ''
|
|
29
|
+
* }
|
|
30
|
+
* @example
|
|
31
|
+
* ```javascript
|
|
32
|
+
* import { DotCMSEditableText } from '@dotcms/react';
|
|
33
|
+
*
|
|
34
|
+
* const MyContentletWithTitle = ({ contentlet }) => (
|
|
35
|
+
* <h2>
|
|
36
|
+
* <DotCMSEditableText
|
|
37
|
+
* contentlet={contentlet}
|
|
38
|
+
* fieldName="title"
|
|
39
|
+
* mode='full'
|
|
40
|
+
* format='text'/>
|
|
41
|
+
* </h2>
|
|
42
|
+
* );
|
|
43
|
+
* ```
|
|
44
|
+
* @returns {JSX.Element} A component to edit content inline
|
|
45
|
+
*/
|
|
46
|
+
function DotCMSEditableText({
|
|
47
|
+
mode = 'plain',
|
|
48
|
+
format = 'text',
|
|
49
|
+
contentlet,
|
|
50
|
+
fieldName
|
|
51
|
+
}) {
|
|
52
|
+
const editorRef = useRef(null);
|
|
53
|
+
const [scriptSrc, setScriptSrc] = useState('');
|
|
54
|
+
const [initEditor, setInitEditor] = useState(false);
|
|
55
|
+
const [content, setContent] = useState((contentlet == null ? void 0 : contentlet[fieldName]) || '');
|
|
56
|
+
useEffect(() => {
|
|
57
|
+
setContent((contentlet == null ? void 0 : contentlet[fieldName]) || '');
|
|
58
|
+
}, [fieldName, contentlet]);
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
var _state$dotCMSHost, _editorRef$current;
|
|
61
|
+
const state = getUVEState();
|
|
62
|
+
setInitEditor((state == null ? void 0 : state.mode) === UVE_MODE.EDIT && !!(state != null && (_state$dotCMSHost = state.dotCMSHost) != null && _state$dotCMSHost.length));
|
|
63
|
+
if (!contentlet || !fieldName) {
|
|
64
|
+
console.error('[DotCMSEditableText]: contentlet or fieldName is missing', 'Ensure that all needed props are passed to view and edit the content');
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (state && state.mode !== UVE_MODE.EDIT) {
|
|
68
|
+
console.warn('[DotCMSEditableText]: TinyMCE is not available in the current mode');
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (!(state != null && state.dotCMSHost)) {
|
|
72
|
+
console.warn('[DotCMSEditableText]: The `dotCMSHost` parameter is not defined. Check that the UVE is sending the correct parameters.');
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const createURL = new URL(__TINYMCE_PATH_ON_DOTCMS__, state.dotCMSHost);
|
|
76
|
+
setScriptSrc(createURL.toString());
|
|
77
|
+
const content = (contentlet == null ? void 0 : contentlet[fieldName]) || '';
|
|
78
|
+
(_editorRef$current = editorRef.current) == null || _editorRef$current.setContent(content, {
|
|
79
|
+
format
|
|
80
|
+
});
|
|
81
|
+
}, [format, fieldName, contentlet, content]);
|
|
82
|
+
useEffect(() => {
|
|
83
|
+
var _getUVEState;
|
|
84
|
+
if (((_getUVEState = getUVEState()) == null ? void 0 : _getUVEState.mode) !== UVE_MODE.EDIT) {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const onMessage = ({
|
|
88
|
+
data
|
|
89
|
+
}) => {
|
|
90
|
+
const {
|
|
91
|
+
name,
|
|
92
|
+
payload
|
|
93
|
+
} = data;
|
|
94
|
+
if (name !== __DOTCMS_UVE_EVENT__.UVE_COPY_CONTENTLET_INLINE_EDITING_SUCCESS) {
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
const {
|
|
98
|
+
oldInode,
|
|
99
|
+
inode
|
|
100
|
+
} = payload;
|
|
101
|
+
const currentInode = contentlet.inode;
|
|
102
|
+
const shouldFocus = currentInode === oldInode || currentInode === inode;
|
|
103
|
+
if (shouldFocus) {
|
|
104
|
+
var _editorRef$current2;
|
|
105
|
+
(_editorRef$current2 = editorRef.current) == null || _editorRef$current2.focus();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
window.addEventListener('message', onMessage);
|
|
109
|
+
return () => {
|
|
110
|
+
window.removeEventListener('message', onMessage);
|
|
111
|
+
};
|
|
112
|
+
}, [contentlet == null ? void 0 : contentlet.inode]);
|
|
113
|
+
const onMouseDown = event => {
|
|
114
|
+
var _editorRef$current3;
|
|
115
|
+
const {
|
|
116
|
+
onNumberOfPages = 1
|
|
117
|
+
} = contentlet;
|
|
118
|
+
const {
|
|
119
|
+
inode,
|
|
120
|
+
languageId: language
|
|
121
|
+
} = contentlet;
|
|
122
|
+
if (Number(onNumberOfPages) <= 1 || (_editorRef$current3 = editorRef.current) != null && _editorRef$current3.hasFocus()) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
event.stopPropagation();
|
|
126
|
+
event.preventDefault();
|
|
127
|
+
sendMessageToUVE({
|
|
128
|
+
action: DotCMSUVEAction.COPY_CONTENTLET_INLINE_EDITING,
|
|
129
|
+
payload: {
|
|
130
|
+
dataset: {
|
|
131
|
+
inode,
|
|
132
|
+
language,
|
|
133
|
+
fieldName
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
});
|
|
137
|
+
};
|
|
138
|
+
const onFocusOut = () => {
|
|
139
|
+
var _editorRef$current4, _editorRef$current5;
|
|
140
|
+
const editedContent = ((_editorRef$current4 = editorRef.current) == null ? void 0 : _editorRef$current4.getContent({
|
|
141
|
+
format: format
|
|
142
|
+
})) || '';
|
|
143
|
+
const {
|
|
144
|
+
inode,
|
|
145
|
+
languageId: langId
|
|
146
|
+
} = contentlet;
|
|
147
|
+
if (!((_editorRef$current5 = editorRef.current) != null && _editorRef$current5.isDirty()) || !didContentChange(editedContent)) {
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
sendMessageToUVE({
|
|
151
|
+
action: DotCMSUVEAction.UPDATE_CONTENTLET_INLINE_EDITING,
|
|
152
|
+
payload: {
|
|
153
|
+
content: editedContent,
|
|
154
|
+
dataset: {
|
|
155
|
+
inode,
|
|
156
|
+
langId,
|
|
157
|
+
fieldName
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
};
|
|
162
|
+
const didContentChange = editedContent => {
|
|
163
|
+
return content !== editedContent;
|
|
164
|
+
};
|
|
165
|
+
if (!initEditor) {
|
|
166
|
+
// We can let the user pass the Child Component and create a root to get the HTML for the editor
|
|
167
|
+
return jsx("span", {
|
|
168
|
+
dangerouslySetInnerHTML: {
|
|
169
|
+
__html: content
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return jsx("div", {
|
|
174
|
+
style: {
|
|
175
|
+
outline: '2px solid #006ce7',
|
|
176
|
+
borderRadius: '4px'
|
|
177
|
+
},
|
|
178
|
+
children: jsx(Editor, {
|
|
179
|
+
tinymceScriptSrc: scriptSrc,
|
|
180
|
+
inline: true,
|
|
181
|
+
onInit: (_, editor) => editorRef.current = editor,
|
|
182
|
+
init: TINYMCE_CONFIG[mode],
|
|
183
|
+
initialValue: content,
|
|
184
|
+
onMouseDown: onMouseDown,
|
|
185
|
+
onFocusOut: onFocusOut
|
|
186
|
+
})
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
export { DotCMSEditableText };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import '../../../../../../../../node_modules/core-js/modules/es.object.assign.esm.js';
|
|
2
|
+
import { __DEFAULT_TINYMCE_CONFIG__, __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__ } from '@dotcms/uve/internal';
|
|
3
|
+
|
|
4
|
+
const DEFAULT_TINYMCE_CONFIG = Object.assign({}, __DEFAULT_TINYMCE_CONFIG__, {
|
|
5
|
+
licenseKey: 'gpl' // Using self-hosted license key
|
|
6
|
+
});
|
|
7
|
+
const TINYMCE_CONFIG = {
|
|
8
|
+
full: Object.assign({}, DEFAULT_TINYMCE_CONFIG, __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__.full),
|
|
9
|
+
plain: Object.assign({}, DEFAULT_TINYMCE_CONFIG, __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__.plain),
|
|
10
|
+
minimal: Object.assign({}, DEFAULT_TINYMCE_CONFIG, __BASE_TINYMCE_CONFIG_WITH_NO_DEFAULT__.minimal)
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export { TINYMCE_CONFIG };
|
|
@@ -0,0 +1,44 @@
|
|
|
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 { ErrorMessage } from './components/ErrorMessage.esm.js';
|
|
5
|
+
import { DotCMSPageProvider } from './DotCMSPageProvider.esm.js';
|
|
6
|
+
import { Row } from '../Row/Row.esm.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* DotCMSLayoutBody component renders the layout body for a DotCMS page.
|
|
10
|
+
*
|
|
11
|
+
* It utilizes the dotCMS page asset's layout body to render the page body.
|
|
12
|
+
* If the layout body does not exist, it renders an error message in the mode is `development`.
|
|
13
|
+
*
|
|
14
|
+
* @public
|
|
15
|
+
* @component
|
|
16
|
+
* @param {Object} props - Component properties.
|
|
17
|
+
* @param {DotCMSPageAsset} props.page - The DotCMS page asset containing the layout information.
|
|
18
|
+
* @param {Record<string, React.ComponentType<DotCMSContentlet>>} [props.components] - mapping of custom components for content rendering.
|
|
19
|
+
* @param {DotCMSPageRendererMode} [props.mode='production'] - The renderer mode; defaults to 'production'. Alternate modes might trigger different behaviors.
|
|
20
|
+
* @param {Record<string, ReactNode>} [props.slots] - Pre-rendered server component nodes keyed by contentlet identifier.
|
|
21
|
+
*
|
|
22
|
+
* @returns {JSX.Element} The rendered DotCMS page body or an error message if the layout body is missing.
|
|
23
|
+
*
|
|
24
|
+
*/
|
|
25
|
+
const DotCMSLayoutBody = ({
|
|
26
|
+
page,
|
|
27
|
+
components: _components = {},
|
|
28
|
+
mode: _mode = 'production',
|
|
29
|
+
slots: _slots = {}
|
|
30
|
+
}) => {
|
|
31
|
+
var _page$layout;
|
|
32
|
+
const dotCMSPageBody = page == null || (_page$layout = page.layout) == null ? void 0 : _page$layout.body;
|
|
33
|
+
return jsx(DotCMSPageProvider, {
|
|
34
|
+
page: page,
|
|
35
|
+
components: _components,
|
|
36
|
+
mode: _mode,
|
|
37
|
+
slots: _slots,
|
|
38
|
+
children: dotCMSPageBody ? dotCMSPageBody.rows.map((row, index) => jsx(Row, {
|
|
39
|
+
row: row
|
|
40
|
+
}, index)) : jsx(ErrorMessage, {})
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export { DotCMSLayoutBody };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { DotCMSPageContext } from '../../contexts/DotCMSPageContext.esm.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @internal
|
|
7
|
+
*
|
|
8
|
+
* Client boundary that provides the DotCMS page context to the layout tree.
|
|
9
|
+
* Keeping this separate from DotCMSLayoutBody allows the layout to remain
|
|
10
|
+
* a server component while only the context provider runs on the client.
|
|
11
|
+
*/
|
|
12
|
+
function DotCMSPageProvider({
|
|
13
|
+
page,
|
|
14
|
+
components,
|
|
15
|
+
mode,
|
|
16
|
+
slots,
|
|
17
|
+
children
|
|
18
|
+
}) {
|
|
19
|
+
return jsx(DotCMSPageContext.Provider, {
|
|
20
|
+
value: {
|
|
21
|
+
pageAsset: page,
|
|
22
|
+
userComponents: components,
|
|
23
|
+
mode,
|
|
24
|
+
slots
|
|
25
|
+
},
|
|
26
|
+
children: children
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export { DotCMSPageProvider };
|
package/libs/sdk/react/src/lib/next/components/DotCMSLayoutBody/components/ErrorMessage.esm.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
import { useEffect } from 'react';
|
|
4
|
+
import { useIsDevMode } from '../../../hooks/useIsDevMode.esm.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Error message component for when the page body is missing
|
|
8
|
+
*
|
|
9
|
+
* @return {JSX.Element} Error message component
|
|
10
|
+
*/
|
|
11
|
+
const ErrorMessage = () => {
|
|
12
|
+
const isDevMode = useIsDevMode();
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
console.warn('Missing required layout.body property in page');
|
|
15
|
+
}, []);
|
|
16
|
+
return isDevMode && jsxs("div", {
|
|
17
|
+
"data-testid": "error-message",
|
|
18
|
+
style: {
|
|
19
|
+
padding: '1rem',
|
|
20
|
+
border: '1px solid #e0e0e0',
|
|
21
|
+
borderRadius: '4px'
|
|
22
|
+
},
|
|
23
|
+
children: [jsxs("p", {
|
|
24
|
+
style: {
|
|
25
|
+
margin: '0 0 0.5rem',
|
|
26
|
+
color: '#666'
|
|
27
|
+
},
|
|
28
|
+
children: ["The ", jsx("code", {
|
|
29
|
+
children: "page"
|
|
30
|
+
}), " is missing the required ", jsx("code", {
|
|
31
|
+
children: "layout.body"
|
|
32
|
+
}), " property."]
|
|
33
|
+
}), jsx("p", {
|
|
34
|
+
style: {
|
|
35
|
+
margin: 0,
|
|
36
|
+
color: '#666'
|
|
37
|
+
},
|
|
38
|
+
children: "Make sure the page asset is properly loaded and includes a layout configuration."
|
|
39
|
+
})]
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { ErrorMessage };
|