cms-block-editor 1.0.7 → 1.0.9
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/LICENSE +1 -1
- package/README.md +44 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +54 -19
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -71,6 +71,8 @@ Main editor component with full editing capabilities.
|
|
|
71
71
|
**Props:**
|
|
72
72
|
- `value?: string` - Initial editor state (JSON string)
|
|
73
73
|
- `onChange?: (state: any) => void` - Callback fired when content changes
|
|
74
|
+
- `onImageAdded?: (file: File) => Promise<string>` - Custom image upload handler that returns the image URL
|
|
75
|
+
- `useBase64Url?: boolean` - Use base64 encoding for images (default: `true`)
|
|
74
76
|
|
|
75
77
|
### CMSRenderer
|
|
76
78
|
|
|
@@ -92,7 +94,7 @@ Read-only renderer for displaying saved content.
|
|
|
92
94
|
- Code blocks
|
|
93
95
|
|
|
94
96
|
### Media
|
|
95
|
-
- **Images**: Upload from computer, resize with 8-point handles, drag-and-drop positioning
|
|
97
|
+
- **Images**: Upload from computer, resize with 8-point handles, drag-and-drop positioning, custom upload handler support
|
|
96
98
|
- **YouTube**: Embed videos with custom sizing
|
|
97
99
|
- **Embeds**: Support for 8+ platforms with automatic URL detection
|
|
98
100
|
- **Tables**: Visual builder with configurable dimensions, header rows, and professional styling
|
|
@@ -130,6 +132,47 @@ Read-only renderer for displaying saved content.
|
|
|
130
132
|
|
|
131
133
|
## Advanced Usage
|
|
132
134
|
|
|
135
|
+
### Custom Image Upload
|
|
136
|
+
|
|
137
|
+
Upload images to your server instead of using base64 encoding:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { CMSBlockEditor } from 'cms-block-editor';
|
|
141
|
+
|
|
142
|
+
function Editor() {
|
|
143
|
+
const [content, setContent] = useState('');
|
|
144
|
+
|
|
145
|
+
const handleImageUpload = async (file: File): Promise<string> => {
|
|
146
|
+
// Upload to your server
|
|
147
|
+
const formData = new FormData();
|
|
148
|
+
formData.append('image', file);
|
|
149
|
+
|
|
150
|
+
const response = await fetch('/api/upload', {
|
|
151
|
+
method: 'POST',
|
|
152
|
+
body: formData,
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const data = await response.json();
|
|
156
|
+
return data.url; // Return the uploaded image URL
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
return (
|
|
160
|
+
<CMSBlockEditor
|
|
161
|
+
value={content}
|
|
162
|
+
onChange={(state) => setContent(JSON.stringify(state))}
|
|
163
|
+
onImageAdded={handleImageUpload}
|
|
164
|
+
useBase64Url={false}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Image Upload Options:**
|
|
171
|
+
|
|
172
|
+
- **With `onImageAdded`**: Provide a custom upload handler that uploads the file to your server and returns the URL
|
|
173
|
+
- **With `useBase64Url={true}`** (default): Images are encoded as base64 strings (no server upload needed)
|
|
174
|
+
- **With `useBase64Url={false}` and no `onImageAdded`**: Image upload will be disabled
|
|
175
|
+
|
|
133
176
|
### With Persistence
|
|
134
177
|
|
|
135
178
|
```tsx
|
package/dist/index.d.mts
CHANGED
|
@@ -4,8 +4,10 @@ import { LexicalEditor } from 'lexical';
|
|
|
4
4
|
interface CMSBlockEditorProps {
|
|
5
5
|
value?: string;
|
|
6
6
|
onChange?: (state: any) => void;
|
|
7
|
+
onImageAdded?: (file: File) => Promise<string>;
|
|
8
|
+
useBase64Url?: boolean;
|
|
7
9
|
}
|
|
8
|
-
declare function CMSBlockEditor({ value, onChange }: CMSBlockEditorProps): react_jsx_runtime.JSX.Element;
|
|
10
|
+
declare function CMSBlockEditor({ value, onChange, onImageAdded, useBase64Url }: CMSBlockEditorProps): react_jsx_runtime.JSX.Element;
|
|
9
11
|
|
|
10
12
|
interface CMSRendererProps {
|
|
11
13
|
content: string;
|
package/dist/index.mjs
CHANGED
|
@@ -4152,7 +4152,10 @@ function ToolbarPlugin() {
|
|
|
4152
4152
|
import { useLexicalComposerContext as useLexicalComposerContext8 } from "@lexical/react/LexicalComposerContext";
|
|
4153
4153
|
import { useEffect as useEffect9 } from "react";
|
|
4154
4154
|
import { $getSelection as $getSelection7, $isRangeSelection as $isRangeSelection7, COMMAND_PRIORITY_LOW as COMMAND_PRIORITY_LOW2, DRAGOVER_COMMAND, DROP_COMMAND } from "lexical";
|
|
4155
|
-
function ImageUploadPlugin(
|
|
4155
|
+
function ImageUploadPlugin({
|
|
4156
|
+
onImageAdded,
|
|
4157
|
+
useBase64Url = true
|
|
4158
|
+
}) {
|
|
4156
4159
|
const [editor] = useLexicalComposerContext8();
|
|
4157
4160
|
useEffect9(() => {
|
|
4158
4161
|
const removeDragOverListener = editor.registerCommand(
|
|
@@ -4165,25 +4168,41 @@ function ImageUploadPlugin() {
|
|
|
4165
4168
|
);
|
|
4166
4169
|
const removeDropListener = editor.registerCommand(
|
|
4167
4170
|
DROP_COMMAND,
|
|
4168
|
-
|
|
4171
|
+
//@ts-ignore
|
|
4172
|
+
async (event) => {
|
|
4169
4173
|
event.preventDefault();
|
|
4170
4174
|
const files = event.dataTransfer?.files;
|
|
4171
4175
|
if (files && files.length > 0) {
|
|
4172
4176
|
const file = files[0];
|
|
4173
4177
|
if (file.type.startsWith("image/")) {
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4178
|
+
let url;
|
|
4179
|
+
const alt = file.name.replace(/\.[^/.]+$/, "");
|
|
4180
|
+
if (onImageAdded) {
|
|
4181
|
+
try {
|
|
4182
|
+
url = await onImageAdded(file);
|
|
4183
|
+
} catch (error) {
|
|
4184
|
+
console.error("Error uploading image:", error);
|
|
4185
|
+
return false;
|
|
4186
|
+
}
|
|
4187
|
+
} else if (useBase64Url) {
|
|
4188
|
+
url = await new Promise((resolve) => {
|
|
4189
|
+
const reader = new FileReader();
|
|
4190
|
+
reader.onload = (e) => {
|
|
4191
|
+
resolve(e.target?.result);
|
|
4192
|
+
};
|
|
4193
|
+
reader.readAsDataURL(file);
|
|
4184
4194
|
});
|
|
4185
|
-
}
|
|
4186
|
-
|
|
4195
|
+
} else {
|
|
4196
|
+
console.warn("No image upload handler provided and useBase64Url is false");
|
|
4197
|
+
return false;
|
|
4198
|
+
}
|
|
4199
|
+
editor.update(() => {
|
|
4200
|
+
const selection = $getSelection7();
|
|
4201
|
+
if ($isRangeSelection7(selection)) {
|
|
4202
|
+
const imageNode = new ImageNode(url, alt);
|
|
4203
|
+
selection.insertNodes([imageNode]);
|
|
4204
|
+
}
|
|
4205
|
+
});
|
|
4187
4206
|
return true;
|
|
4188
4207
|
}
|
|
4189
4208
|
}
|
|
@@ -4195,7 +4214,7 @@ function ImageUploadPlugin() {
|
|
|
4195
4214
|
removeDragOverListener();
|
|
4196
4215
|
removeDropListener();
|
|
4197
4216
|
};
|
|
4198
|
-
}, [editor]);
|
|
4217
|
+
}, [editor, onImageAdded, useBase64Url]);
|
|
4199
4218
|
return null;
|
|
4200
4219
|
}
|
|
4201
4220
|
|
|
@@ -5532,7 +5551,11 @@ function EmbedPlugin() {
|
|
|
5532
5551
|
|
|
5533
5552
|
// src/core/EditorShell.tsx
|
|
5534
5553
|
import { jsx as jsx14, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
5535
|
-
function EditorShell({
|
|
5554
|
+
function EditorShell({
|
|
5555
|
+
onChange,
|
|
5556
|
+
onImageAdded,
|
|
5557
|
+
useBase64Url
|
|
5558
|
+
}) {
|
|
5536
5559
|
return /* @__PURE__ */ jsxs14("div", { className: "cms-editor-shell", children: [
|
|
5537
5560
|
/* @__PURE__ */ jsx14(ToolbarPlugin, {}),
|
|
5538
5561
|
/* @__PURE__ */ jsx14(
|
|
@@ -5548,7 +5571,7 @@ function EditorShell({ onChange }) {
|
|
|
5548
5571
|
/* @__PURE__ */ jsx14(LexicalLinkPlugin, {}),
|
|
5549
5572
|
/* @__PURE__ */ jsx14(LexicalTablePlugin, {}),
|
|
5550
5573
|
/* @__PURE__ */ jsx14(SlashCommandPlugin, {}),
|
|
5551
|
-
/* @__PURE__ */ jsx14(ImageUploadPlugin, {}),
|
|
5574
|
+
/* @__PURE__ */ jsx14(ImageUploadPlugin, { onImageAdded, useBase64Url }),
|
|
5552
5575
|
/* @__PURE__ */ jsx14(LinkPlugin, {}),
|
|
5553
5576
|
/* @__PURE__ */ jsx14(SectionEditorPlugin, {}),
|
|
5554
5577
|
/* @__PURE__ */ jsx14(EmbedPlugin, {}),
|
|
@@ -5613,8 +5636,20 @@ function createEditorConfig(value) {
|
|
|
5613
5636
|
|
|
5614
5637
|
// src/core/CMSBlockEditor.tsx
|
|
5615
5638
|
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
5616
|
-
function CMSBlockEditor({
|
|
5617
|
-
|
|
5639
|
+
function CMSBlockEditor({
|
|
5640
|
+
value,
|
|
5641
|
+
onChange,
|
|
5642
|
+
onImageAdded,
|
|
5643
|
+
useBase64Url = true
|
|
5644
|
+
}) {
|
|
5645
|
+
return /* @__PURE__ */ jsx15(LexicalComposer, { initialConfig: createEditorConfig(value), children: /* @__PURE__ */ jsx15(
|
|
5646
|
+
EditorShell,
|
|
5647
|
+
{
|
|
5648
|
+
onChange,
|
|
5649
|
+
onImageAdded,
|
|
5650
|
+
useBase64Url
|
|
5651
|
+
}
|
|
5652
|
+
) });
|
|
5618
5653
|
}
|
|
5619
5654
|
|
|
5620
5655
|
// src/core/CMSRenderer.tsx
|