@crashbytes/contentful-richtext-editor 1.0.3 → 1.0.6
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 +158 -125
- package/dist/components/ContentfulEditor.d.ts +4 -0
- package/dist/components/Toolbar.d.ts +2 -0
- package/dist/index.esm.js +65 -59
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +65 -59
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,105 +24,126 @@ A modern, Tiptap-based rich text editor that's fully compatible with Contentful'
|
|
|
24
24
|
|
|
25
25
|
## Installation
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
```bash
|
|
28
|
+
npm install @crashbytes/contentful-richtext-editor
|
|
29
|
+
```
|
|
28
30
|
|
|
29
31
|
## Basic Usage
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
33
|
+
```jsx
|
|
34
|
+
import React, { useState } from 'react';
|
|
35
|
+
import { ContentfulRichTextEditor } from '@crashbytes/contentful-richtext-editor';
|
|
36
|
+
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
37
|
+
import { Document } from '@contentful/rich-text-types';
|
|
38
|
+
|
|
39
|
+
function App() {
|
|
40
|
+
const [content, setContent] = useState();
|
|
41
|
+
|
|
42
|
+
const handleChange = (document) => {
|
|
43
|
+
setContent(document);
|
|
44
|
+
console.log('Contentful document:', document);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div>
|
|
49
|
+
<h1>My Rich Text Editor</h1>
|
|
50
|
+
<ContentfulRichTextEditor
|
|
51
|
+
placeholder="Start writing your content..."
|
|
52
|
+
onChange={handleChange}
|
|
53
|
+
initialValue={content}
|
|
54
|
+
/>
|
|
55
|
+
</div>
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default App;
|
|
60
|
+
```
|
|
57
61
|
|
|
58
62
|
## Advanced Usage
|
|
59
63
|
|
|
60
64
|
### With Contentful Entry/Asset Embedding
|
|
61
65
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
function ContentfulEditor() {
|
|
66
|
-
const handleEmbedEntry = async () => {
|
|
67
|
-
// Your logic to select a Contentful entry
|
|
68
|
-
const entry = await openEntrySelector();
|
|
69
|
-
return entry;
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
const handleEmbedAsset = async () => {
|
|
73
|
-
// Your logic to select a Contentful asset
|
|
74
|
-
const asset = await openAssetSelector();
|
|
75
|
-
return asset;
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
return (
|
|
79
|
-
<ContentfulRichTextEditor
|
|
80
|
-
placeholder="Write your travel tip..."
|
|
81
|
-
onChange={(doc) => saveToContentful(doc)}
|
|
82
|
-
onEmbedEntry={handleEmbedEntry}
|
|
83
|
-
onEmbedAsset={handleEmbedAsset}
|
|
84
|
-
theme="contentful"
|
|
85
|
-
/>
|
|
86
|
-
);
|
|
87
|
-
}
|
|
66
|
+
```jsx
|
|
67
|
+
import { ContentfulRichTextEditor } from '@crashbytes/contentful-richtext-editor';
|
|
68
|
+
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
88
69
|
|
|
89
|
-
|
|
70
|
+
function ContentfulEditor() {
|
|
71
|
+
const handleEmbedEntry = async () => {
|
|
72
|
+
// Your logic to select a Contentful entry
|
|
73
|
+
const entry = await openEntrySelector();
|
|
74
|
+
return entry;
|
|
75
|
+
};
|
|
90
76
|
|
|
77
|
+
const handleEmbedAsset = async () => {
|
|
78
|
+
// Your logic to select a Contentful asset
|
|
79
|
+
const asset = await openAssetSelector();
|
|
80
|
+
return asset;
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
return (
|
|
91
84
|
<ContentfulRichTextEditor
|
|
92
|
-
placeholder="
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
85
|
+
placeholder="Write your travel tip..."
|
|
86
|
+
onChange={(doc) => saveToContentful(doc)}
|
|
87
|
+
onEmbedEntry={handleEmbedEntry}
|
|
88
|
+
onEmbedAsset={handleEmbedAsset}
|
|
89
|
+
theme="contentful"
|
|
97
90
|
/>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Customizing Features
|
|
96
|
+
|
|
97
|
+
```jsx
|
|
98
|
+
<ContentfulRichTextEditor
|
|
99
|
+
placeholder="Simple editor..."
|
|
100
|
+
disabledFeatures={['table', 'embed', 'quote']}
|
|
101
|
+
theme="minimal"
|
|
102
|
+
readonly={false}
|
|
103
|
+
onChange={handleChange}
|
|
104
|
+
/>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Controlling Available Headings and Formatting
|
|
108
|
+
|
|
109
|
+
```jsx
|
|
110
|
+
<ContentfulRichTextEditor
|
|
111
|
+
placeholder="Limited editor..."
|
|
112
|
+
availableHeadings={[1, 2, 3]} // Only H1, H2, H3
|
|
113
|
+
availableMarks={['bold', 'italic']} // Only bold and italic, no underline
|
|
114
|
+
onChange={handleChange}
|
|
115
|
+
/>
|
|
116
|
+
```
|
|
98
117
|
|
|
99
118
|
### With Initial Content
|
|
100
119
|
|
|
101
|
-
|
|
120
|
+
```jsx
|
|
121
|
+
import { createEmptyDocument } from '@crashbytes/contentful-richtext-editor';
|
|
102
122
|
|
|
103
|
-
|
|
104
|
-
|
|
123
|
+
const initialContent = {
|
|
124
|
+
nodeType: 'document',
|
|
125
|
+
data: {},
|
|
126
|
+
content: [
|
|
127
|
+
{
|
|
128
|
+
nodeType: 'paragraph',
|
|
105
129
|
data: {},
|
|
106
130
|
content: [
|
|
107
131
|
{
|
|
108
|
-
nodeType: '
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
nodeType: 'text',
|
|
113
|
-
value: 'Hello world!',
|
|
114
|
-
marks: [{ type: 'bold' }],
|
|
115
|
-
data: {}
|
|
116
|
-
}
|
|
117
|
-
]
|
|
132
|
+
nodeType: 'text',
|
|
133
|
+
value: 'Hello world!',
|
|
134
|
+
marks: [{ type: 'bold' }],
|
|
135
|
+
data: {}
|
|
118
136
|
}
|
|
119
137
|
]
|
|
120
|
-
}
|
|
138
|
+
}
|
|
139
|
+
]
|
|
140
|
+
};
|
|
121
141
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
142
|
+
<ContentfulRichTextEditor
|
|
143
|
+
initialValue={initialContent}
|
|
144
|
+
onChange={handleChange}
|
|
145
|
+
/>
|
|
146
|
+
```
|
|
126
147
|
|
|
127
148
|
## API Reference
|
|
128
149
|
|
|
@@ -139,6 +160,8 @@ A modern, Tiptap-based rich text editor that's fully compatible with Contentful'
|
|
|
139
160
|
| `className` | `string` | `''` | Additional CSS classes |
|
|
140
161
|
| `theme` | `'default' \| 'minimal' \| 'contentful'` | `'contentful'` | Visual theme |
|
|
141
162
|
| `disabledFeatures` | `Array<string>` | `[]` | Features to disable |
|
|
163
|
+
| `availableHeadings` | `Array<1\|2\|3\|4\|5\|6>` | `[1,2,3,4,5,6]` | Which heading levels to show |
|
|
164
|
+
| `availableMarks` | `Array<'bold'\|'italic'\|'underline'>` | `['bold','italic','underline']` | Which text formatting options to show |
|
|
142
165
|
|
|
143
166
|
### Disabled Features
|
|
144
167
|
|
|
@@ -156,44 +179,50 @@ You can disable specific features by passing them in the `disabledFeatures` arra
|
|
|
156
179
|
|
|
157
180
|
### Utility Functions
|
|
158
181
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
182
|
+
```jsx
|
|
183
|
+
import {
|
|
184
|
+
contentfulToTiptap,
|
|
185
|
+
tiptapToContentful,
|
|
186
|
+
validateContentfulDocument,
|
|
187
|
+
createEmptyDocument
|
|
188
|
+
} from '@crashbytes/contentful-richtext-editor';
|
|
165
189
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
190
|
+
// Convert between formats
|
|
191
|
+
const tiptapJson = contentfulToTiptap(contentfulDocument);
|
|
192
|
+
const contentfulDoc = tiptapToContentful(tiptapJson);
|
|
169
193
|
|
|
170
|
-
|
|
171
|
-
|
|
194
|
+
// Validation
|
|
195
|
+
const isValid = validateContentfulDocument(someDocument);
|
|
172
196
|
|
|
173
|
-
|
|
174
|
-
|
|
197
|
+
// Create empty document
|
|
198
|
+
const emptyDoc = createEmptyDocument();
|
|
199
|
+
```
|
|
175
200
|
|
|
176
201
|
## Styling
|
|
177
202
|
|
|
178
203
|
The editor comes with default styles that match Contentful's design. Import the CSS:
|
|
179
204
|
|
|
180
|
-
|
|
205
|
+
```jsx
|
|
206
|
+
import '@crashbytes/contentful-richtext-editor/dist/index.css';
|
|
207
|
+
```
|
|
181
208
|
|
|
182
209
|
### Custom Styling
|
|
183
210
|
|
|
184
211
|
You can override the default styles by targeting the CSS classes:
|
|
185
212
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
213
|
+
```css
|
|
214
|
+
.contentful-editor {
|
|
215
|
+
border: 2px solid #your-color;
|
|
216
|
+
}
|
|
189
217
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
218
|
+
.contentful-toolbar {
|
|
219
|
+
background: #your-background;
|
|
220
|
+
}
|
|
193
221
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
222
|
+
.contentful-editor-content {
|
|
223
|
+
font-family: 'Your Font', sans-serif;
|
|
224
|
+
}
|
|
225
|
+
```
|
|
197
226
|
|
|
198
227
|
## Themes
|
|
199
228
|
|
|
@@ -208,36 +237,40 @@ Standard rich text editor appearance with serif fonts.
|
|
|
208
237
|
|
|
209
238
|
## Integration with Next.js
|
|
210
239
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
240
|
+
```jsx
|
|
241
|
+
// pages/editor.tsx or app/editor/page.tsx
|
|
242
|
+
import dynamic from 'next/dynamic';
|
|
243
|
+
|
|
244
|
+
const ContentfulEditor = dynamic(
|
|
245
|
+
() => import('@crashbytes/contentful-richtext-editor').then(mod => mod.ContentfulRichTextEditor),
|
|
246
|
+
{ ssr: false }
|
|
247
|
+
);
|
|
248
|
+
|
|
249
|
+
export default function EditorPage() {
|
|
250
|
+
return (
|
|
251
|
+
<div>
|
|
252
|
+
<ContentfulEditor
|
|
253
|
+
placeholder="Write something amazing..."
|
|
254
|
+
onChange={(doc) => console.log(doc)}
|
|
255
|
+
/>
|
|
256
|
+
</div>
|
|
257
|
+
);
|
|
258
|
+
}
|
|
259
|
+
```
|
|
229
260
|
|
|
230
261
|
## TypeScript Support
|
|
231
262
|
|
|
232
263
|
This package is written in TypeScript and includes full type definitions. All Contentful rich text types are re-exported for convenience:
|
|
233
264
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
265
|
+
```tsx
|
|
266
|
+
import type {
|
|
267
|
+
Document,
|
|
268
|
+
Block,
|
|
269
|
+
Inline,
|
|
270
|
+
Text,
|
|
271
|
+
ContentfulRichTextEditorProps
|
|
272
|
+
} from '@crashbytes/contentful-richtext-editor';
|
|
273
|
+
```
|
|
241
274
|
|
|
242
275
|
## Browser Support
|
|
243
276
|
|
|
@@ -20,6 +20,10 @@ export interface ContentfulRichTextEditorProps {
|
|
|
20
20
|
disabledFeatures?: Array<'bold' | 'italic' | 'underline' | 'link' | 'lists' | 'headings' | 'quote' | 'table' | 'embed'>;
|
|
21
21
|
/** Custom styling options */
|
|
22
22
|
theme?: 'default' | 'minimal' | 'contentful';
|
|
23
|
+
/** Which heading levels to make available (1-6) */
|
|
24
|
+
availableHeadings?: Array<1 | 2 | 3 | 4 | 5 | 6>;
|
|
25
|
+
/** Which text formatting marks to make available */
|
|
26
|
+
availableMarks?: Array<'bold' | 'italic' | 'underline'>;
|
|
23
27
|
}
|
|
24
28
|
export declare const ContentfulRichTextEditor: React.FC<ContentfulRichTextEditorProps>;
|
|
25
29
|
export default ContentfulRichTextEditor;
|
|
@@ -5,6 +5,8 @@ interface ToolbarProps {
|
|
|
5
5
|
onEmbedEntry?: () => void;
|
|
6
6
|
onEmbedAsset?: () => void;
|
|
7
7
|
disabledFeatures?: Array<string>;
|
|
8
|
+
availableHeadings?: Array<1 | 2 | 3 | 4 | 5 | 6>;
|
|
9
|
+
availableMarks?: Array<'bold' | 'italic' | 'underline'>;
|
|
8
10
|
}
|
|
9
11
|
export declare const ContentfulToolbar: React.FC<ToolbarProps>;
|
|
10
12
|
export {};
|
package/dist/index.esm.js
CHANGED
|
@@ -26529,10 +26529,11 @@ const Underline = Mark.create({
|
|
|
26529
26529
|
},
|
|
26530
26530
|
});
|
|
26531
26531
|
|
|
26532
|
-
const ContentfulToolbar = ({ editor, onEmbedEntry, onEmbedAsset, disabledFeatures = [] }) => {
|
|
26532
|
+
const ContentfulToolbar = ({ editor, onEmbedEntry, onEmbedAsset, disabledFeatures = [], availableHeadings = [1, 2, 3, 4, 5, 6], availableMarks = ['bold', 'italic', 'underline'] }) => {
|
|
26533
26533
|
const [showLinkInput, setShowLinkInput] = useState(false);
|
|
26534
26534
|
const [linkUrl, setLinkUrl] = useState('');
|
|
26535
26535
|
const isDisabled = (feature) => disabledFeatures.includes(feature);
|
|
26536
|
+
const isMarkAvailable = (mark) => availableMarks.includes(mark);
|
|
26536
26537
|
const handleHeadingChange = (level) => {
|
|
26537
26538
|
if (level === 0) {
|
|
26538
26539
|
editor.chain().focus().setParagraph().run();
|
|
@@ -26561,14 +26562,15 @@ const ContentfulToolbar = ({ editor, onEmbedEntry, onEmbedAsset, disabledFeature
|
|
|
26561
26562
|
editor.chain().focus().insertTable({ rows: 3, cols: 3, withHeaderRow: true }).run();
|
|
26562
26563
|
};
|
|
26563
26564
|
const getActiveHeading = () => {
|
|
26564
|
-
for (
|
|
26565
|
-
if (editor.isActive('heading', { level
|
|
26566
|
-
return `Heading ${
|
|
26565
|
+
for (const level of availableHeadings) {
|
|
26566
|
+
if (editor.isActive('heading', { level })) {
|
|
26567
|
+
return `Heading ${level}`;
|
|
26567
26568
|
}
|
|
26568
26569
|
}
|
|
26569
26570
|
return 'Normal text';
|
|
26570
26571
|
};
|
|
26571
|
-
|
|
26572
|
+
const hasHeadings = !isDisabled('headings') && availableHeadings.length > 0;
|
|
26573
|
+
return (jsxs("div", { className: "contentful-toolbar", children: [jsxs("div", { className: "contentful-toolbar__group", children: [hasHeadings && (jsxs("select", { className: "contentful-toolbar__select", value: getActiveHeading(), onChange: (e) => {
|
|
26572
26574
|
const value = e.target.value;
|
|
26573
26575
|
if (value === 'Normal text') {
|
|
26574
26576
|
handleHeadingChange(0);
|
|
@@ -26577,7 +26579,7 @@ const ContentfulToolbar = ({ editor, onEmbedEntry, onEmbedAsset, disabledFeature
|
|
|
26577
26579
|
const level = parseInt(value.replace('Heading ', ''));
|
|
26578
26580
|
handleHeadingChange(level);
|
|
26579
26581
|
}
|
|
26580
|
-
}, children: [jsx("option", { value: "Normal text", children: "Normal text" }),
|
|
26582
|
+
}, children: [jsx("option", { value: "Normal text", children: "Normal text" }), availableHeadings.map(level => (jsxs("option", { value: `Heading ${level}`, children: ["Heading ", level] }, level)))] })), jsx("button", { className: "contentful-toolbar__button", onClick: () => editor.chain().focus().undo().run(), disabled: !editor.can().undo(), title: "Undo", children: "\u21B6" }), jsx("button", { className: "contentful-toolbar__button", onClick: () => editor.chain().focus().redo().run(), disabled: !editor.can().redo(), title: "Redo", children: "\u21B7" })] }), jsx("div", { className: "contentful-toolbar__separator" }), jsxs("div", { className: "contentful-toolbar__group", children: [!isDisabled('bold') && isMarkAvailable('bold') && (jsx("button", { className: `contentful-toolbar__button ${editor.isActive('bold') ? 'contentful-toolbar__button--active' : ''}`, onClick: () => editor.chain().focus().toggleBold().run(), title: "Bold", children: jsx("strong", { children: "B" }) })), !isDisabled('italic') && isMarkAvailable('italic') && (jsx("button", { className: `contentful-toolbar__button ${editor.isActive('italic') ? 'contentful-toolbar__button--active' : ''}`, onClick: () => editor.chain().focus().toggleItalic().run(), title: "Italic", children: jsx("em", { children: "I" }) })), !isDisabled('underline') && isMarkAvailable('underline') && (jsx("button", { className: `contentful-toolbar__button ${editor.isActive('underline') ? 'contentful-toolbar__button--active' : ''}`, onClick: () => editor.chain().focus().toggleUnderline().run(), title: "Underline", children: jsx("u", { children: "U" }) })), jsx("button", { className: "contentful-toolbar__button", title: "More formatting options", children: "\u22EF" }), !isDisabled('link') && (jsxs(Fragment$1, { children: [jsx("button", { className: `contentful-toolbar__button ${editor.isActive('link') ? 'contentful-toolbar__button--active' : ''}`, onClick: handleLinkToggle, title: "Link", children: "\uD83D\uDD17" }), showLinkInput && (jsxs("div", { className: "contentful-toolbar__link-input", children: [jsx("input", { type: "url", value: linkUrl, onChange: (e) => setLinkUrl(e.target.value), placeholder: "Enter URL", onKeyDown: (e) => {
|
|
26581
26583
|
if (e.key === 'Enter') {
|
|
26582
26584
|
handleLinkSubmit();
|
|
26583
26585
|
}
|
|
@@ -27268,59 +27270,63 @@ const createEmptyDocument = () => ({
|
|
|
27268
27270
|
],
|
|
27269
27271
|
});
|
|
27270
27272
|
|
|
27271
|
-
const ContentfulRichTextEditor = ({ initialValue, onChange, onEmbedEntry, onEmbedAsset, className = '', readonly = false, placeholder = 'Start writing...', disabledFeatures = [], theme = 'contentful' }) => {
|
|
27273
|
+
const ContentfulRichTextEditor = ({ initialValue, onChange, onEmbedEntry, onEmbedAsset, className = '', readonly = false, placeholder = 'Start writing...', disabledFeatures = [], theme = 'contentful', availableHeadings = [1, 2, 3, 4, 5, 6], availableMarks = ['bold', 'italic', 'underline'] }) => {
|
|
27274
|
+
// Build extensions array based on available features
|
|
27275
|
+
const extensions = [];
|
|
27276
|
+
// Add StarterKit with configuration
|
|
27277
|
+
extensions.push(StarterKit.configure({
|
|
27278
|
+
heading: {
|
|
27279
|
+
levels: availableHeadings,
|
|
27280
|
+
},
|
|
27281
|
+
bold: availableMarks.includes('bold') ? {} : false,
|
|
27282
|
+
italic: availableMarks.includes('italic') ? {} : false,
|
|
27283
|
+
bulletList: {
|
|
27284
|
+
HTMLAttributes: {
|
|
27285
|
+
class: 'contentful-bullet-list',
|
|
27286
|
+
},
|
|
27287
|
+
},
|
|
27288
|
+
orderedList: {
|
|
27289
|
+
HTMLAttributes: {
|
|
27290
|
+
class: 'contentful-ordered-list',
|
|
27291
|
+
},
|
|
27292
|
+
},
|
|
27293
|
+
blockquote: {
|
|
27294
|
+
HTMLAttributes: {
|
|
27295
|
+
class: 'contentful-blockquote',
|
|
27296
|
+
},
|
|
27297
|
+
},
|
|
27298
|
+
}));
|
|
27299
|
+
// Add underline extension only if it's in availableMarks
|
|
27300
|
+
if (availableMarks.includes('underline')) {
|
|
27301
|
+
extensions.push(Underline);
|
|
27302
|
+
}
|
|
27303
|
+
// Add other extensions
|
|
27304
|
+
extensions.push(Link.configure({
|
|
27305
|
+
openOnClick: false,
|
|
27306
|
+
HTMLAttributes: {
|
|
27307
|
+
class: 'contentful-link',
|
|
27308
|
+
rel: 'noopener noreferrer',
|
|
27309
|
+
},
|
|
27310
|
+
}), Table.configure({
|
|
27311
|
+
resizable: true,
|
|
27312
|
+
HTMLAttributes: {
|
|
27313
|
+
class: 'contentful-table',
|
|
27314
|
+
},
|
|
27315
|
+
}), TableRow.configure({
|
|
27316
|
+
HTMLAttributes: {
|
|
27317
|
+
class: 'contentful-table-row',
|
|
27318
|
+
},
|
|
27319
|
+
}), TableHeader.configure({
|
|
27320
|
+
HTMLAttributes: {
|
|
27321
|
+
class: 'contentful-table-header',
|
|
27322
|
+
},
|
|
27323
|
+
}), TableCell.configure({
|
|
27324
|
+
HTMLAttributes: {
|
|
27325
|
+
class: 'contentful-table-cell',
|
|
27326
|
+
},
|
|
27327
|
+
}));
|
|
27272
27328
|
const editor = useEditor({
|
|
27273
|
-
extensions
|
|
27274
|
-
StarterKit.configure({
|
|
27275
|
-
heading: {
|
|
27276
|
-
levels: [1, 2, 3, 4, 5, 6],
|
|
27277
|
-
},
|
|
27278
|
-
bulletList: {
|
|
27279
|
-
HTMLAttributes: {
|
|
27280
|
-
class: 'contentful-bullet-list',
|
|
27281
|
-
},
|
|
27282
|
-
},
|
|
27283
|
-
orderedList: {
|
|
27284
|
-
HTMLAttributes: {
|
|
27285
|
-
class: 'contentful-ordered-list',
|
|
27286
|
-
},
|
|
27287
|
-
},
|
|
27288
|
-
blockquote: {
|
|
27289
|
-
HTMLAttributes: {
|
|
27290
|
-
class: 'contentful-blockquote',
|
|
27291
|
-
},
|
|
27292
|
-
},
|
|
27293
|
-
}),
|
|
27294
|
-
Underline,
|
|
27295
|
-
Link.configure({
|
|
27296
|
-
openOnClick: false,
|
|
27297
|
-
HTMLAttributes: {
|
|
27298
|
-
class: 'contentful-link',
|
|
27299
|
-
rel: 'noopener noreferrer',
|
|
27300
|
-
},
|
|
27301
|
-
}),
|
|
27302
|
-
Table.configure({
|
|
27303
|
-
resizable: true,
|
|
27304
|
-
HTMLAttributes: {
|
|
27305
|
-
class: 'contentful-table',
|
|
27306
|
-
},
|
|
27307
|
-
}),
|
|
27308
|
-
TableRow.configure({
|
|
27309
|
-
HTMLAttributes: {
|
|
27310
|
-
class: 'contentful-table-row',
|
|
27311
|
-
},
|
|
27312
|
-
}),
|
|
27313
|
-
TableHeader.configure({
|
|
27314
|
-
HTMLAttributes: {
|
|
27315
|
-
class: 'contentful-table-header',
|
|
27316
|
-
},
|
|
27317
|
-
}),
|
|
27318
|
-
TableCell.configure({
|
|
27319
|
-
HTMLAttributes: {
|
|
27320
|
-
class: 'contentful-table-cell',
|
|
27321
|
-
},
|
|
27322
|
-
}),
|
|
27323
|
-
],
|
|
27329
|
+
extensions,
|
|
27324
27330
|
content: initialValue ? contentfulToTiptap(initialValue) : '',
|
|
27325
27331
|
editable: !readonly,
|
|
27326
27332
|
editorProps: {
|
|
@@ -27399,7 +27405,7 @@ const ContentfulRichTextEditor = ({ initialValue, onChange, onEmbedEntry, onEmbe
|
|
|
27399
27405
|
if (!editor) {
|
|
27400
27406
|
return (jsx("div", { className: `contentful-editor contentful-editor--loading ${className}`, children: jsx("div", { className: "contentful-editor__loading", children: "Loading editor..." }) }));
|
|
27401
27407
|
}
|
|
27402
|
-
return (jsxs("div", { className: `contentful-editor contentful-editor--${theme} ${className}`, children: [!readonly && (jsx(ContentfulToolbar, { editor: editor, onEmbedEntry: handleEmbedEntry, onEmbedAsset: handleEmbedAsset, disabledFeatures: disabledFeatures })), jsx("div", { className: "contentful-editor__content-wrapper", children: jsx(EditorContent, { editor: editor, className: "contentful-editor__content" }) })] }));
|
|
27408
|
+
return (jsxs("div", { className: `contentful-editor contentful-editor--${theme} ${className}`, children: [!readonly && (jsx(ContentfulToolbar, { editor: editor, onEmbedEntry: handleEmbedEntry, onEmbedAsset: handleEmbedAsset, disabledFeatures: disabledFeatures, availableHeadings: availableHeadings, availableMarks: availableMarks })), jsx("div", { className: "contentful-editor__content-wrapper", children: jsx(EditorContent, { editor: editor, className: "contentful-editor__content" }) })] }));
|
|
27403
27409
|
};
|
|
27404
27410
|
|
|
27405
27411
|
export { ContentfulRichTextEditor, ContentfulToolbar, contentfulToTiptap, createEmptyDocument, tiptapToContentful, validateContentfulDocument };
|