rj-editor 1.1.8 → 1.2.0

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 CHANGED
@@ -12,7 +12,7 @@ It provides a ready-to-use `RJTextEditor` component with a tabbed toolbar, text
12
12
  - Style controls: font size, font family, text color, background color, clear formatting.
13
13
  - Paragraph tools: alignment, ordered list, unordered list, indent, outdent, line and paragraph spacing.
14
14
  - Insert tools: table, link, image, YouTube video, and editable code blocks.
15
- - Code blocks: syntax highlighting, language selection, and persistent copy controls in both the editor and rendered HTML.
15
+ - Code blocks: editable code blocks, language selection, and persistent copy controls in both the editor and rendered HTML.
16
16
  - Table editing: add/remove rows and columns, merge/split cells, header row/column, cell background, vertical alignment, delete table.
17
17
  - Image editing: upload, drag-and-drop, paste from clipboard, resize, align, alt text, caption, link, border, border radius, shadow, object fit, wrapping, rotate, replace, delete.
18
18
  - Browser fullscreen mode.
@@ -169,6 +169,7 @@ When validation fails, the editor border follows the Ant Design error state.
169
169
  | `onBlur` | `React.FocusEventHandler<HTMLDivElement>` | `undefined` | Called when the editor root loses focus. |
170
170
  | `onChange` | `(html, json, editorState) => void` | `undefined` | Called whenever editor content changes. |
171
171
  | `onFocus` | `React.FocusEventHandler<HTMLDivElement>` | `undefined` | Called when the editor root receives focus. |
172
+ | `onUpload` | `(file: File) => Promise<string>` | base64 fallback | Uploads image files and returns the image URL to store in editor content. |
172
173
  | `placeholder` | `string` | Locale-based text | Placeholder shown when the editor is empty. |
173
174
  | `showFooter` | `boolean` | `false` | Shows the optional editor footer status bar. |
174
175
  | `translations` | `DeepPartial<RJEditorTranslations>` | `undefined` | Overrides translations for the active locale. |
@@ -218,13 +219,44 @@ For a fully custom footer, pass a render function:
218
219
 
219
220
  ## Images
220
221
 
221
- Images can be inserted from the local file picker, drag-and-drop, or clipboard paste. The image is stored as a base64 data URL inside the editor content.
222
+ Images can be inserted from the local file picker, drag-and-drop, or clipboard paste. By default, the editor converts images to base64 data URLs and stores them inside the HTML content. For production, pass `onUpload` so images are uploaded to your own server or storage service and only the returned URL is stored in the content.
222
223
 
223
224
  Important details:
224
225
 
225
226
  - Maximum image size is `5MB`.
226
- - Base64 images increase HTML size.
227
- - For large production systems, a server upload flow or storage adapter is recommended.
227
+ - If `onUpload` is not provided, base64 fallback keeps local/demo usage working.
228
+ - `onUpload` is used for image insert, paste, drop, and replace actions.
229
+ - While the upload promise is pending, the relevant image controls show loading and are disabled.
230
+ - If the upload promise rejects, the image is not inserted/replaced and the editor shows the localized upload error.
231
+
232
+ Upload example:
233
+
234
+ ```tsx
235
+ <RJTextEditor
236
+ onUpload={async (file) => {
237
+ const formData = new FormData()
238
+ formData.append('file', file)
239
+
240
+ const response = await fetch('/api/uploads/images', {
241
+ method: 'POST',
242
+ body: formData,
243
+ })
244
+
245
+ if (!response.ok) {
246
+ throw new Error('Image upload failed')
247
+ }
248
+
249
+ const data = await response.json()
250
+ return data.url
251
+ }}
252
+ />
253
+ ```
254
+
255
+ The returned string must be the final image URL used in exported HTML:
256
+
257
+ ```html
258
+ <img src="https://cdn.example.com/uploads/image.webp" alt="..." />
259
+ ```
228
260
 
229
261
  Image tools include:
230
262
 
@@ -273,7 +305,6 @@ Paste a YouTube URL from the `Insert` tab to add an embedded video. The editor c
273
305
  Insert a code block from the `Insert` tab. Code blocks support:
274
306
 
275
307
  - direct editing inside the document;
276
- - syntax highlighting;
277
308
  - language selection;
278
309
  - a copy button that remains visible when the block is not focused;
279
310
  - a persistent copy button in exported HTML rendered with `dangerouslySetInnerHTML`;
@@ -1,4 +1,5 @@
1
1
  import type { RJTextEditorProps } from './rj-text-editor/RJTextEditor.types';
2
2
  import './RJTextEditor.scss';
3
3
  export type { RJTextEditorProps } from './rj-text-editor/RJTextEditor.types';
4
- export declare function RJTextEditor({ autofocus, className, defaultValue, footer, footerItems, footerLanguageLabel, footerZoom, id, locale, locales, namespace, onBlur, onChange, onFocus, placeholder, showFooter, translations, theme, value, }: RJTextEditorProps): import("react/jsx-runtime").JSX.Element;
4
+ export type { RJEditorImageUploadHandler } from './rj-text-editor/RJEditorImageUploadContext';
5
+ export declare function RJTextEditor({ autofocus, className, defaultValue, footer, footerItems, footerLanguageLabel, footerZoom, id, locale, locales, namespace, onBlur, onChange, onFocus, onUpload, placeholder, showFooter, translations, theme, value, }: RJTextEditorProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,6 @@
1
+ type Props = {
2
+ size?: number;
3
+ className?: string;
4
+ };
5
+ export default function SpinIndicator({ size, className }: Props): import("react/jsx-runtime").JSX.Element;
6
+ export {};
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { type RJEditorImageUploadHandler } from './RJEditorImageUploadContext';
3
+ type ImageUploadProviderProps = {
4
+ children: React.ReactNode;
5
+ onImageUpload?: RJEditorImageUploadHandler;
6
+ };
7
+ export declare function ImageUploadProvider({ children, onImageUpload, }: ImageUploadProviderProps): import("react/jsx-runtime").JSX.Element;
8
+ export {};
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export type RJEditorImageUploadHandler = (file: File) => Promise<string>;
3
+ export declare const ImageUploadContext: React.Context<RJEditorImageUploadHandler>;
4
+ export declare function useRJEditorImageUpload(): RJEditorImageUploadHandler;
@@ -14,6 +14,7 @@ export type RJTextEditorProps = {
14
14
  onBlur?: React.FocusEventHandler<HTMLDivElement>;
15
15
  onChange?: (html: string, json: string, editorState: EditorState) => void;
16
16
  onFocus?: React.FocusEventHandler<HTMLDivElement>;
17
+ onUpload?: (file: File) => Promise<string>;
17
18
  locale?: RJEditorLocaleCode;
18
19
  locales?: Record<string, DeepPartial<RJEditorTranslations>>;
19
20
  placeholder?: string;
@@ -1,7 +1,7 @@
1
1
  import { LinkNode } from '@lexical/link';
2
2
  import { ListItemNode, ListNode } from '@lexical/list';
3
3
  import { TableCellNode, TableNode, TableRowNode } from '@lexical/table';
4
- import { CodeHighlightNode, CodeNode } from '@lexical/code';
4
+ import { CodeHighlightNode, CodeNode } from '@lexical/code-core';
5
5
  import { TextNode, type LexicalEditor } from 'lexical';
6
6
  import { EquationNode, ExtendedTextNode, ImageNode, YouTubeNode, replaceTextNodeWithExtendedTextNode } from '../../nodes/index';
7
7
  type CreateInitialConfigOptions = {
package/dist/index.d.ts CHANGED
@@ -2,4 +2,5 @@ import './styles/main.scss';
2
2
  export { RJTextEditor } from './components/RJTextEditor';
3
3
  export { enTranslations, mergeTranslations, RJEditorI18nProvider, ruTranslations, useRJEditorI18n, uzTranslations, } from './i18n/index';
4
4
  export type { RJTextEditorProps } from './components/RJTextEditor';
5
+ export type { RJEditorImageUploadHandler } from './components/RJTextEditor';
5
6
  export type { DeepPartial, RJEditorFooterItem, RJEditorFooterStats, RJEditorLocaleCode, RJEditorTheme, RJEditorTranslations, RJTextEditorFooterRender, RJTextEditorValue, } from './types/index';