@mdaemon/html-editor-react 1.4.0 → 1.5.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 +95 -3
- package/dist/Editor.d.ts +88 -0
- package/dist/index.d.ts +9 -168
- package/dist/index.js +162 -157
- package/dist/index.mjs +147 -157
- package/dist/useEditor.d.ts +44 -0
- package/package.json +15 -9
package/README.md
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
[](https://www.npmjs.com/package/@mdaemon/html-editor-react) [](https://packagephobia.com/result?p=@mdaemon/html-editor-react) [](https://github.com/mdaemon-technologies/MDHTMLEditor-react/blob/master/LICENSE) [](https://github.com/mdaemon-technologies/MDHTMLEditor-react/actions/workflows/ci.yml)
|
|
2
|
+
|
|
1
3
|
# MDHTMLEditor React
|
|
2
4
|
|
|
3
5
|
A React wrapper for [MDHTMLEditor](https://github.com/mdaemon-technologies/MDHTMLEditor) — a WYSIWYG HTML editor built on TipTap. Provides a drop-in replacement for `@tinymce/tinymce-react` with no license key required.
|
|
@@ -222,8 +224,8 @@ The `config` prop (or `useEditor`'s `config` option) accepts an `EditorConfig` o
|
|
|
222
224
|
| `skin` | `'oxide' \| 'oxide-dark' \| 'confab' \| 'confab-dark'` | `'oxide'` | Toolbar and dialog theme. |
|
|
223
225
|
| `content_css` | `'default' \| 'dark' \| 'confab' \| 'confab-dark'` | `'default'` | Content area theme. |
|
|
224
226
|
| `content_style` | `string` | — | Custom CSS injected into the editing surface. |
|
|
225
|
-
| `fontName` | `string` |
|
|
226
|
-
| `fontSize` | `string` |
|
|
227
|
+
| `fontName` | `string` | `'arial, helvetica, sans-serif'` | Default font family. Inlined on every block in the exported HTML — see [Fonts](#fonts). |
|
|
228
|
+
| `fontSize` | `string` | `'12pt'` | Default font size. Inlined on every paragraph in the exported HTML — see [Fonts](#fonts). |
|
|
227
229
|
| `font_family_formats` | `string` | *(TinyMCE defaults)* | Semicolon-delimited font list (`Name=family,...`). |
|
|
228
230
|
| `font_size_formats` | `string` | `'8pt 9pt 10pt 12pt 14pt 18pt 24pt 36pt'` | Space-delimited size options. |
|
|
229
231
|
| `font_names` | `string` | — | CKEditor alias for `font_family_formats`. |
|
|
@@ -334,6 +336,77 @@ const isReadOnly = editorRef.current?.getEditor()?.isReadOnly();
|
|
|
334
336
|
|
|
335
337
|
> The `disabled` prop applies a lightweight visual lock (pointer-events off, reduced opacity). For true non-editable behavior that also dims the toolbar, prefer `readonly` / `setReadOnly()`.
|
|
336
338
|
|
|
339
|
+
## Fonts
|
|
340
|
+
|
|
341
|
+
`fontName` and `fontSize` set the editor's default font. The defaults are written directly onto each block in the exported HTML (`font-family` on `<p>`/`<div>`/`<hN>`, `font-size` on `<p>`/`<div>`) rather than relying on the editor's stylesheet being present, so the content keeps its font when it is rendered somewhere else — an email body opened in another client, for example. Headings keep their level-based sizing and carry no block `font-size`.
|
|
342
|
+
|
|
343
|
+
```tsx
|
|
344
|
+
<Editor
|
|
345
|
+
config={{
|
|
346
|
+
fontName: 'Georgia, serif',
|
|
347
|
+
fontSize: '14pt',
|
|
348
|
+
}}
|
|
349
|
+
/>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
Selecting text and picking a font or size from the `fontfamily` / `fontsize` toolbar dropdowns produces an inline `<span>` that overrides the block default, so a single paragraph can mix fonts and sizes.
|
|
353
|
+
|
|
354
|
+
### The Toolbar Shows the Font at the Cursor
|
|
355
|
+
|
|
356
|
+
The `fontfamily` and `fontsize` toolbar buttons display the value in effect at the cursor — "Georgia", "14pt" — and update as the caret moves, instead of showing the static words "Font" and "Font size". A family is shown by its configured name (the label side of `font_family_formats`); a font that is not in the configured list, such as one pasted in from another editor, is shown by its first family name. Labels are width-constrained and ellipsized so the toolbar does not reflow as the caret moves, with the full text on each button's `title`.
|
|
357
|
+
|
|
358
|
+
Where no single value applies, the button falls back to the generic word. That happens for a selection spanning two different fonts or sizes, and for font size inside a heading.
|
|
359
|
+
|
|
360
|
+
> This is styled by rules in `@mdaemon/html-editor/dist/styles.css` — make sure the [stylesheet import](#styles) is present, and re-check any custom CSS you have layered on top of the toolbar buttons.
|
|
361
|
+
|
|
362
|
+
### Reading the Current Font
|
|
363
|
+
|
|
364
|
+
`getFontFamily()` and `getFontSize()` report the font in effect at the cursor, resolving an inline `<span>` override first, then the block's own font, then the configured default:
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
const editor = editorRef.current?.getEditor();
|
|
368
|
+
|
|
369
|
+
const family = editor?.getFontFamily(); // e.g. 'Georgia, serif'
|
|
370
|
+
const size = editor?.getFontSize(); // e.g. '14pt'
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
Use these to drive a custom font picker outside the toolbar. Unlike reading the inline mark directly, they still return a value when the font comes from the block or the configured default.
|
|
374
|
+
|
|
375
|
+
Both return `''` when there is no single value to report:
|
|
376
|
+
|
|
377
|
+
- the selection spans more than one font family / size
|
|
378
|
+
- for `getFontSize()`, the cursor is in a heading with no inline override (headings size by level and carry no block `font-size`)
|
|
379
|
+
|
|
380
|
+
Treat `''` as "mixed / not applicable" and blank your picker, rather than falling back to a default — that is what the toolbar does.
|
|
381
|
+
|
|
382
|
+
The editor emits no selection event of its own, so subscribe on the TipTap instance to keep a readout in sync with the caret:
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
const handleInit = useCallback((editor: HTMLEditor) => {
|
|
386
|
+
const sync = () => {
|
|
387
|
+
setFamily(editor.getFontFamily());
|
|
388
|
+
setSize(editor.getFontSize());
|
|
389
|
+
};
|
|
390
|
+
|
|
391
|
+
sync();
|
|
392
|
+
editor.getTipTap()?.on('selectionUpdate', sync);
|
|
393
|
+
editor.getTipTap()?.on('transaction', sync);
|
|
394
|
+
}, []);
|
|
395
|
+
|
|
396
|
+
<Editor config={{ fontName: 'Georgia, serif', fontSize: '14pt' }} onInit={handleInit} />
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
### Setting a Block Font
|
|
400
|
+
|
|
401
|
+
To change the font on every block the selection touches — instead of adding an inline override — use the `setBlockFontFamily` / `setBlockFontSize` commands on the underlying TipTap instance:
|
|
402
|
+
|
|
403
|
+
```tsx
|
|
404
|
+
const tiptap = editorRef.current?.getEditor()?.getTipTap();
|
|
405
|
+
|
|
406
|
+
tiptap?.chain().focus().setBlockFontFamily('Georgia, serif').run();
|
|
407
|
+
tiptap?.chain().focus().setBlockFontSize('14pt').run();
|
|
408
|
+
```
|
|
409
|
+
|
|
337
410
|
## Templates
|
|
338
411
|
|
|
339
412
|
Enable the template dropdown and provide a `templates` array:
|
|
@@ -664,7 +737,26 @@ A demo app is included to see the editor in action:
|
|
|
664
737
|
npm run demo
|
|
665
738
|
```
|
|
666
739
|
|
|
667
|
-
This starts a Vite dev server at `http://localhost:5173` with
|
|
740
|
+
This starts a Vite dev server at `http://localhost:5173` with three sections: the `<Editor>` component, the `useEditor` hook, and a [Fonts](#fonts) panel with a live `getFontFamily()` / `getFontSize()` readout that follows the cursor and buttons for the block-font commands.
|
|
741
|
+
|
|
742
|
+
## Development
|
|
743
|
+
|
|
744
|
+
The package is bundled with [Vite 8](https://vite.dev/) (Rolldown) and ships ES, CommonJS, and TypeScript declaration outputs.
|
|
745
|
+
|
|
746
|
+
| Script | Description |
|
|
747
|
+
|--------|-------------|
|
|
748
|
+
| `npm run build` | Production build to `dist/` (ES + CJS + `.d.ts`). |
|
|
749
|
+
| `npm run build:dev` | Development build (unminified, sourcemaps). |
|
|
750
|
+
| `npm run dev` | Rebuild on change (watch mode). |
|
|
751
|
+
| `npm test` | Run the Jest test suite. |
|
|
752
|
+
| `npm run test:coverage` | Run tests with coverage. |
|
|
753
|
+
| `npm run lint` | Lint `src` with ESLint. |
|
|
754
|
+
| `npm run typecheck` | Type-check `src` and `demo` with `tsc --noEmit`. |
|
|
755
|
+
| `npm run demo` | Launch the demo app. |
|
|
756
|
+
|
|
757
|
+
> **Node.js:** building the package requires Node `^20.19.0 || >=22.12.0` (a Vite 8 requirement). Consumers of the published package are unaffected.
|
|
758
|
+
|
|
759
|
+
Lint, typecheck, and tests run automatically in [CI](.github/workflows/ci.yml) on every push and pull request to `master` across Node 20, 22, 24, and 26.
|
|
668
760
|
|
|
669
761
|
## License
|
|
670
762
|
|
package/dist/Editor.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { HTMLEditor, EditorConfig } from '@mdaemon/html-editor';
|
|
2
|
+
export interface EditorProps {
|
|
3
|
+
/**
|
|
4
|
+
* Editor configuration - TinyMCE compatible
|
|
5
|
+
*/
|
|
6
|
+
config: EditorConfig;
|
|
7
|
+
/**
|
|
8
|
+
* Initial HTML content (also known as 'body' for TinyMCE compat)
|
|
9
|
+
*/
|
|
10
|
+
body?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Initial HTML content (alias for body)
|
|
13
|
+
*/
|
|
14
|
+
initialValue?: string;
|
|
15
|
+
/**
|
|
16
|
+
* Name attribute for the hidden textarea
|
|
17
|
+
*/
|
|
18
|
+
name?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Called when content is modified
|
|
21
|
+
*/
|
|
22
|
+
onDirty?: (dirty: boolean) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Called on content change (debounced)
|
|
25
|
+
*/
|
|
26
|
+
onChange?: (content: string) => void;
|
|
27
|
+
/**
|
|
28
|
+
* Called when editor is fully initialized
|
|
29
|
+
*/
|
|
30
|
+
onInit?: (editor: HTMLEditor) => void;
|
|
31
|
+
/**
|
|
32
|
+
* Called when editor receives focus
|
|
33
|
+
*/
|
|
34
|
+
onFocus?: () => void;
|
|
35
|
+
/**
|
|
36
|
+
* Called when editor loses focus
|
|
37
|
+
*/
|
|
38
|
+
onBlur?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Translation function
|
|
41
|
+
*/
|
|
42
|
+
translate?: (key: string) => string;
|
|
43
|
+
/**
|
|
44
|
+
* Function to resolve file paths (like TinyMCE's tinymceScriptSrc path)
|
|
45
|
+
*/
|
|
46
|
+
getFileSrc?: (path: string) => string;
|
|
47
|
+
/**
|
|
48
|
+
* Disable the editor
|
|
49
|
+
*/
|
|
50
|
+
disabled?: boolean;
|
|
51
|
+
}
|
|
52
|
+
export interface EditorRef {
|
|
53
|
+
/**
|
|
54
|
+
* Get the underlying HTMLEditor instance
|
|
55
|
+
*/
|
|
56
|
+
getEditor: () => HTMLEditor | null;
|
|
57
|
+
/**
|
|
58
|
+
* Get the editor content as HTML
|
|
59
|
+
*/
|
|
60
|
+
getContent: () => string;
|
|
61
|
+
/**
|
|
62
|
+
* Set the editor content
|
|
63
|
+
*/
|
|
64
|
+
setContent: (html: string) => void;
|
|
65
|
+
/**
|
|
66
|
+
* Insert content at cursor position
|
|
67
|
+
*/
|
|
68
|
+
insertContent: (html: string) => void;
|
|
69
|
+
/**
|
|
70
|
+
* Focus the editor
|
|
71
|
+
*/
|
|
72
|
+
focus: () => void;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Get content from the global editor instance
|
|
76
|
+
* Note: Only works with single editor on the page
|
|
77
|
+
*/
|
|
78
|
+
export declare function getEditorContent(): string;
|
|
79
|
+
/**
|
|
80
|
+
* Set content on the global editor instance
|
|
81
|
+
* Note: Only works with single editor on the page
|
|
82
|
+
*/
|
|
83
|
+
export declare function setEditorContent(html: string): void;
|
|
84
|
+
/**
|
|
85
|
+
* MDHTMLEditor React Component
|
|
86
|
+
*/
|
|
87
|
+
export declare const Editor: import('react').ForwardRefExoticComponent<EditorProps & import('react').RefAttributes<EditorRef>>;
|
|
88
|
+
export default Editor;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,168 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { ToolbarButtonAPI } from '@mdaemon/html-editor';
|
|
11
|
-
import { ToolbarButtonSpec } from '@mdaemon/html-editor';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* MDHTMLEditor React Component
|
|
15
|
-
*/
|
|
16
|
-
declare const Editor: ForwardRefExoticComponent<EditorProps & RefAttributes<EditorRef>>;
|
|
17
|
-
export { Editor }
|
|
18
|
-
export { Editor as MDEditor }
|
|
19
|
-
|
|
20
|
-
export { EditorConfig }
|
|
21
|
-
|
|
22
|
-
export { EditorEvents }
|
|
23
|
-
|
|
24
|
-
export declare interface EditorProps {
|
|
25
|
-
/**
|
|
26
|
-
* Editor configuration - TinyMCE compatible
|
|
27
|
-
*/
|
|
28
|
-
config: EditorConfig;
|
|
29
|
-
/**
|
|
30
|
-
* Initial HTML content (also known as 'body' for TinyMCE compat)
|
|
31
|
-
*/
|
|
32
|
-
body?: string;
|
|
33
|
-
/**
|
|
34
|
-
* Initial HTML content (alias for body)
|
|
35
|
-
*/
|
|
36
|
-
initialValue?: string;
|
|
37
|
-
/**
|
|
38
|
-
* Name attribute for the hidden textarea
|
|
39
|
-
*/
|
|
40
|
-
name?: string;
|
|
41
|
-
/**
|
|
42
|
-
* Called when content is modified
|
|
43
|
-
*/
|
|
44
|
-
onDirty?: (dirty: boolean) => void;
|
|
45
|
-
/**
|
|
46
|
-
* Called on content change (debounced)
|
|
47
|
-
*/
|
|
48
|
-
onChange?: (content: string) => void;
|
|
49
|
-
/**
|
|
50
|
-
* Called when editor is fully initialized
|
|
51
|
-
*/
|
|
52
|
-
onInit?: (editor: HTMLEditor) => void;
|
|
53
|
-
/**
|
|
54
|
-
* Called when editor receives focus
|
|
55
|
-
*/
|
|
56
|
-
onFocus?: () => void;
|
|
57
|
-
/**
|
|
58
|
-
* Called when editor loses focus
|
|
59
|
-
*/
|
|
60
|
-
onBlur?: () => void;
|
|
61
|
-
/**
|
|
62
|
-
* Translation function
|
|
63
|
-
*/
|
|
64
|
-
translate?: (key: string) => string;
|
|
65
|
-
/**
|
|
66
|
-
* Function to resolve file paths (like TinyMCE's tinymceScriptSrc path)
|
|
67
|
-
*/
|
|
68
|
-
getFileSrc?: (path: string) => string;
|
|
69
|
-
/**
|
|
70
|
-
* Disable the editor
|
|
71
|
-
*/
|
|
72
|
-
disabled?: boolean;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
export declare interface EditorRef {
|
|
76
|
-
/**
|
|
77
|
-
* Get the underlying HTMLEditor instance
|
|
78
|
-
*/
|
|
79
|
-
getEditor: () => HTMLEditor | null;
|
|
80
|
-
/**
|
|
81
|
-
* Get the editor content as HTML
|
|
82
|
-
*/
|
|
83
|
-
getContent: () => string;
|
|
84
|
-
/**
|
|
85
|
-
* Set the editor content
|
|
86
|
-
*/
|
|
87
|
-
setContent: (html: string) => void;
|
|
88
|
-
/**
|
|
89
|
-
* Insert content at cursor position
|
|
90
|
-
*/
|
|
91
|
-
insertContent: (html: string) => void;
|
|
92
|
-
/**
|
|
93
|
-
* Focus the editor
|
|
94
|
-
*/
|
|
95
|
-
focus: () => void;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
export { fontNames }
|
|
99
|
-
|
|
100
|
-
/**
|
|
101
|
-
* Get content from the global editor instance
|
|
102
|
-
* Note: Only works with single editor on the page
|
|
103
|
-
*/
|
|
104
|
-
export declare function getEditorContent(): string;
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* Set content on the global editor instance
|
|
108
|
-
* Note: Only works with single editor on the page
|
|
109
|
-
*/
|
|
110
|
-
export declare function setEditorContent(html: string): void;
|
|
111
|
-
|
|
112
|
-
export { setGetFileSrc }
|
|
113
|
-
|
|
114
|
-
export { setTranslate }
|
|
115
|
-
|
|
116
|
-
export { Template }
|
|
117
|
-
|
|
118
|
-
export { ToolbarButtonAPI }
|
|
119
|
-
|
|
120
|
-
export { ToolbarButtonSpec }
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Hook for programmatic editor control
|
|
124
|
-
*/
|
|
125
|
-
export declare function useEditor(options?: UseEditorOptions): UseEditorReturn;
|
|
126
|
-
|
|
127
|
-
export declare interface UseEditorOptions {
|
|
128
|
-
config?: EditorConfig;
|
|
129
|
-
content?: string;
|
|
130
|
-
onUpdate?: (html: string) => void;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export declare interface UseEditorReturn {
|
|
134
|
-
/**
|
|
135
|
-
* The editor instance
|
|
136
|
-
*/
|
|
137
|
-
editor: HTMLEditor | null;
|
|
138
|
-
/**
|
|
139
|
-
* Ref to attach to the container element
|
|
140
|
-
*/
|
|
141
|
-
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
142
|
-
/**
|
|
143
|
-
* Whether the editor is ready
|
|
144
|
-
*/
|
|
145
|
-
ready: boolean;
|
|
146
|
-
/**
|
|
147
|
-
* Get the current HTML content
|
|
148
|
-
*/
|
|
149
|
-
getContent: () => string;
|
|
150
|
-
/**
|
|
151
|
-
* Set the HTML content
|
|
152
|
-
*/
|
|
153
|
-
setContent: (html: string) => void;
|
|
154
|
-
/**
|
|
155
|
-
* Insert HTML at cursor
|
|
156
|
-
*/
|
|
157
|
-
insertContent: (html: string) => void;
|
|
158
|
-
/**
|
|
159
|
-
* Focus the editor
|
|
160
|
-
*/
|
|
161
|
-
focus: () => void;
|
|
162
|
-
/**
|
|
163
|
-
* Check if editor is dirty
|
|
164
|
-
*/
|
|
165
|
-
isDirty: () => boolean;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export { }
|
|
1
|
+
/**
|
|
2
|
+
* MDHTMLEditor React - Main Entry Point
|
|
3
|
+
*/
|
|
4
|
+
export { Editor as MDEditor, Editor, getEditorContent, setEditorContent } from './Editor';
|
|
5
|
+
export type { EditorProps, EditorRef } from './Editor';
|
|
6
|
+
export { useEditor } from './useEditor';
|
|
7
|
+
export type { UseEditorOptions, UseEditorReturn } from './useEditor';
|
|
8
|
+
export { fontNames, setTranslate, setGetFileSrc, } from '@mdaemon/html-editor';
|
|
9
|
+
export type { EditorConfig, EditorEvents, Template, ToolbarButtonSpec, ToolbarButtonAPI, } from '@mdaemon/html-editor';
|
package/dist/index.js
CHANGED
|
@@ -1,173 +1,178 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
let react = require("react");
|
|
3
|
+
let _mdaemon_html_editor = require("@mdaemon/html-editor");
|
|
4
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
5
|
+
//#region src/Editor.tsx
|
|
6
|
+
/**
|
|
7
|
+
* MDHTMLEditor React Component
|
|
8
|
+
* A TinyMCE-compatible React wrapper for MDHTMLEditor
|
|
9
|
+
*/
|
|
10
|
+
var globalEditor = null;
|
|
11
|
+
/**
|
|
12
|
+
* Get content from the global editor instance
|
|
13
|
+
* Note: Only works with single editor on the page
|
|
14
|
+
*/
|
|
7
15
|
function getEditorContent() {
|
|
8
|
-
|
|
16
|
+
return globalEditor?.getContent() ?? "";
|
|
9
17
|
}
|
|
18
|
+
/**
|
|
19
|
+
* Set content on the global editor instance
|
|
20
|
+
* Note: Only works with single editor on the page
|
|
21
|
+
*/
|
|
10
22
|
function setEditorContent(html) {
|
|
11
|
-
|
|
23
|
+
globalEditor?.setContent(html);
|
|
12
24
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
}, [disabled]);
|
|
87
|
-
react.useImperativeHandle(ref, () => ({
|
|
88
|
-
getEditor: () => editorRef.current,
|
|
89
|
-
getContent: () => editorRef.current?.getContent() ?? "",
|
|
90
|
-
setContent: (html) => editorRef.current?.setContent(html),
|
|
91
|
-
insertContent: (html) => editorRef.current?.insertContent(html),
|
|
92
|
-
focus: () => editorRef.current?.focus()
|
|
93
|
-
}), []);
|
|
94
|
-
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "md-editor-react-wrapper", children: [
|
|
95
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: containerRef, className: "md-editor-container" }),
|
|
96
|
-
name && ready && /* @__PURE__ */ jsxRuntime.jsx(
|
|
97
|
-
"input",
|
|
98
|
-
{
|
|
99
|
-
type: "hidden",
|
|
100
|
-
name,
|
|
101
|
-
value: editorRef.current?.getContent() ?? ""
|
|
102
|
-
}
|
|
103
|
-
)
|
|
104
|
-
] });
|
|
25
|
+
/**
|
|
26
|
+
* MDHTMLEditor React Component
|
|
27
|
+
*/
|
|
28
|
+
var Editor = (0, react.forwardRef)(function Editor(props, ref) {
|
|
29
|
+
const { config, body, initialValue, name, onDirty, onChange, onInit, onFocus, onBlur, translate, getFileSrc, disabled } = props;
|
|
30
|
+
const containerRef = (0, react.useRef)(null);
|
|
31
|
+
const editorRef = (0, react.useRef)(null);
|
|
32
|
+
const [ready, setReady] = (0, react.useState)(false);
|
|
33
|
+
(0, react.useEffect)(() => {
|
|
34
|
+
if (translate) (0, _mdaemon_html_editor.setTranslate)(translate);
|
|
35
|
+
}, [translate]);
|
|
36
|
+
(0, react.useEffect)(() => {
|
|
37
|
+
if (getFileSrc) (0, _mdaemon_html_editor.setGetFileSrc)(getFileSrc);
|
|
38
|
+
}, [getFileSrc]);
|
|
39
|
+
(0, react.useEffect)(() => {
|
|
40
|
+
if (!containerRef.current) return;
|
|
41
|
+
const editor = new _mdaemon_html_editor.HTMLEditor(containerRef.current, {
|
|
42
|
+
...config,
|
|
43
|
+
setup: (ed) => {
|
|
44
|
+
config.setup?.(ed);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
editorRef.current = editor;
|
|
48
|
+
globalEditor = editor;
|
|
49
|
+
const content = body ?? initialValue ?? "";
|
|
50
|
+
if (content) editor.setContent(content);
|
|
51
|
+
editor.on("init", () => {
|
|
52
|
+
setReady(true);
|
|
53
|
+
onInit?.(editor);
|
|
54
|
+
});
|
|
55
|
+
editor.on("dirty", (dirty) => {
|
|
56
|
+
onDirty?.(dirty);
|
|
57
|
+
});
|
|
58
|
+
editor.on("change", (content) => {
|
|
59
|
+
onChange?.(content);
|
|
60
|
+
editor.setDirty(false);
|
|
61
|
+
});
|
|
62
|
+
editor.on("focus", () => {
|
|
63
|
+
onFocus?.();
|
|
64
|
+
});
|
|
65
|
+
editor.on("blur", () => {
|
|
66
|
+
onBlur?.();
|
|
67
|
+
});
|
|
68
|
+
return () => {
|
|
69
|
+
editor.destroy();
|
|
70
|
+
editorRef.current = null;
|
|
71
|
+
if (globalEditor === editor) globalEditor = null;
|
|
72
|
+
};
|
|
73
|
+
}, []);
|
|
74
|
+
(0, react.useEffect)(() => {
|
|
75
|
+
if (containerRef.current) {
|
|
76
|
+
containerRef.current.style.pointerEvents = disabled ? "none" : "";
|
|
77
|
+
containerRef.current.style.opacity = disabled ? "0.6" : "";
|
|
78
|
+
}
|
|
79
|
+
}, [disabled]);
|
|
80
|
+
(0, react.useImperativeHandle)(ref, () => ({
|
|
81
|
+
getEditor: () => editorRef.current,
|
|
82
|
+
getContent: () => editorRef.current?.getContent() ?? "",
|
|
83
|
+
setContent: (html) => editorRef.current?.setContent(html),
|
|
84
|
+
insertContent: (html) => editorRef.current?.insertContent(html),
|
|
85
|
+
focus: () => editorRef.current?.focus()
|
|
86
|
+
}), []);
|
|
87
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
88
|
+
className: "md-editor-react-wrapper",
|
|
89
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
90
|
+
ref: containerRef,
|
|
91
|
+
className: "md-editor-container"
|
|
92
|
+
}), name && ready && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
93
|
+
type: "hidden",
|
|
94
|
+
name,
|
|
95
|
+
value: editorRef.current?.getContent() ?? ""
|
|
96
|
+
})]
|
|
97
|
+
});
|
|
105
98
|
});
|
|
106
99
|
Editor.displayName = "MDHTMLEditor";
|
|
100
|
+
//#endregion
|
|
101
|
+
//#region src/useEditor.ts
|
|
102
|
+
/**
|
|
103
|
+
* useEditor Hook
|
|
104
|
+
* Custom hook for advanced editor usage
|
|
105
|
+
*/
|
|
106
|
+
/**
|
|
107
|
+
* Hook for programmatic editor control
|
|
108
|
+
*/
|
|
107
109
|
function useEditor(options = {}) {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
insertContent,
|
|
153
|
-
focus,
|
|
154
|
-
isDirty
|
|
155
|
-
};
|
|
110
|
+
const { config = {}, content = "", onUpdate } = options;
|
|
111
|
+
const containerRef = (0, react.useRef)(null);
|
|
112
|
+
const editorRef = (0, react.useRef)(null);
|
|
113
|
+
const [ready, setReady] = (0, react.useState)(false);
|
|
114
|
+
(0, react.useEffect)(() => {
|
|
115
|
+
if (!containerRef.current) return;
|
|
116
|
+
const editor = new _mdaemon_html_editor.HTMLEditor(containerRef.current, config);
|
|
117
|
+
editorRef.current = editor;
|
|
118
|
+
if (content) editor.setContent(content);
|
|
119
|
+
editor.on("init", () => {
|
|
120
|
+
setReady(true);
|
|
121
|
+
});
|
|
122
|
+
if (onUpdate) editor.on("change", onUpdate);
|
|
123
|
+
return () => {
|
|
124
|
+
editor.destroy();
|
|
125
|
+
editorRef.current = null;
|
|
126
|
+
setReady(false);
|
|
127
|
+
};
|
|
128
|
+
}, []);
|
|
129
|
+
const getContent = (0, react.useCallback)(() => {
|
|
130
|
+
return editorRef.current?.getContent() ?? "";
|
|
131
|
+
}, []);
|
|
132
|
+
const setContent = (0, react.useCallback)((html) => {
|
|
133
|
+
editorRef.current?.setContent(html);
|
|
134
|
+
}, []);
|
|
135
|
+
const insertContent = (0, react.useCallback)((html) => {
|
|
136
|
+
editorRef.current?.insertContent(html);
|
|
137
|
+
}, []);
|
|
138
|
+
const focus = (0, react.useCallback)(() => {
|
|
139
|
+
editorRef.current?.focus();
|
|
140
|
+
}, []);
|
|
141
|
+
const isDirty = (0, react.useCallback)(() => {
|
|
142
|
+
return editorRef.current?.isDirty() ?? false;
|
|
143
|
+
}, []);
|
|
144
|
+
return {
|
|
145
|
+
editor: editorRef.current,
|
|
146
|
+
containerRef,
|
|
147
|
+
ready,
|
|
148
|
+
getContent,
|
|
149
|
+
setContent,
|
|
150
|
+
insertContent,
|
|
151
|
+
focus,
|
|
152
|
+
isDirty
|
|
153
|
+
};
|
|
156
154
|
}
|
|
155
|
+
//#endregion
|
|
156
|
+
exports.Editor = Editor;
|
|
157
|
+
exports.MDEditor = Editor;
|
|
157
158
|
Object.defineProperty(exports, "fontNames", {
|
|
158
|
-
|
|
159
|
-
|
|
159
|
+
enumerable: true,
|
|
160
|
+
get: function() {
|
|
161
|
+
return _mdaemon_html_editor.fontNames;
|
|
162
|
+
}
|
|
160
163
|
});
|
|
164
|
+
exports.getEditorContent = getEditorContent;
|
|
165
|
+
exports.setEditorContent = setEditorContent;
|
|
161
166
|
Object.defineProperty(exports, "setGetFileSrc", {
|
|
162
|
-
|
|
163
|
-
|
|
167
|
+
enumerable: true,
|
|
168
|
+
get: function() {
|
|
169
|
+
return _mdaemon_html_editor.setGetFileSrc;
|
|
170
|
+
}
|
|
164
171
|
});
|
|
165
172
|
Object.defineProperty(exports, "setTranslate", {
|
|
166
|
-
|
|
167
|
-
|
|
173
|
+
enumerable: true,
|
|
174
|
+
get: function() {
|
|
175
|
+
return _mdaemon_html_editor.setTranslate;
|
|
176
|
+
}
|
|
168
177
|
});
|
|
169
|
-
exports.Editor = Editor;
|
|
170
|
-
exports.MDEditor = Editor;
|
|
171
|
-
exports.getEditorContent = getEditorContent;
|
|
172
|
-
exports.setEditorContent = setEditorContent;
|
|
173
178
|
exports.useEditor = useEditor;
|
package/dist/index.mjs
CHANGED
|
@@ -1,165 +1,155 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from "react";
|
|
2
|
+
import { HTMLEditor, fontNames, setGetFileSrc, setGetFileSrc as setGetFileSrc$1, setTranslate, setTranslate as setTranslate$1 } from "@mdaemon/html-editor";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/Editor.tsx
|
|
5
|
+
/**
|
|
6
|
+
* MDHTMLEditor React Component
|
|
7
|
+
* A TinyMCE-compatible React wrapper for MDHTMLEditor
|
|
8
|
+
*/
|
|
9
|
+
var globalEditor = null;
|
|
10
|
+
/**
|
|
11
|
+
* Get content from the global editor instance
|
|
12
|
+
* Note: Only works with single editor on the page
|
|
13
|
+
*/
|
|
6
14
|
function getEditorContent() {
|
|
7
|
-
|
|
15
|
+
return globalEditor?.getContent() ?? "";
|
|
8
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Set content on the global editor instance
|
|
19
|
+
* Note: Only works with single editor on the page
|
|
20
|
+
*/
|
|
9
21
|
function setEditorContent(html) {
|
|
10
|
-
|
|
22
|
+
globalEditor?.setContent(html);
|
|
11
23
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}, [disabled]);
|
|
86
|
-
useImperativeHandle(ref, () => ({
|
|
87
|
-
getEditor: () => editorRef.current,
|
|
88
|
-
getContent: () => editorRef.current?.getContent() ?? "",
|
|
89
|
-
setContent: (html) => editorRef.current?.setContent(html),
|
|
90
|
-
insertContent: (html) => editorRef.current?.insertContent(html),
|
|
91
|
-
focus: () => editorRef.current?.focus()
|
|
92
|
-
}), []);
|
|
93
|
-
return /* @__PURE__ */ jsxs("div", { className: "md-editor-react-wrapper", children: [
|
|
94
|
-
/* @__PURE__ */ jsx("div", { ref: containerRef, className: "md-editor-container" }),
|
|
95
|
-
name && ready && /* @__PURE__ */ jsx(
|
|
96
|
-
"input",
|
|
97
|
-
{
|
|
98
|
-
type: "hidden",
|
|
99
|
-
name,
|
|
100
|
-
value: editorRef.current?.getContent() ?? ""
|
|
101
|
-
}
|
|
102
|
-
)
|
|
103
|
-
] });
|
|
24
|
+
/**
|
|
25
|
+
* MDHTMLEditor React Component
|
|
26
|
+
*/
|
|
27
|
+
var Editor = forwardRef(function Editor(props, ref) {
|
|
28
|
+
const { config, body, initialValue, name, onDirty, onChange, onInit, onFocus, onBlur, translate, getFileSrc, disabled } = props;
|
|
29
|
+
const containerRef = useRef(null);
|
|
30
|
+
const editorRef = useRef(null);
|
|
31
|
+
const [ready, setReady] = useState(false);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (translate) setTranslate$1(translate);
|
|
34
|
+
}, [translate]);
|
|
35
|
+
useEffect(() => {
|
|
36
|
+
if (getFileSrc) setGetFileSrc$1(getFileSrc);
|
|
37
|
+
}, [getFileSrc]);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
if (!containerRef.current) return;
|
|
40
|
+
const editor = new HTMLEditor(containerRef.current, {
|
|
41
|
+
...config,
|
|
42
|
+
setup: (ed) => {
|
|
43
|
+
config.setup?.(ed);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
editorRef.current = editor;
|
|
47
|
+
globalEditor = editor;
|
|
48
|
+
const content = body ?? initialValue ?? "";
|
|
49
|
+
if (content) editor.setContent(content);
|
|
50
|
+
editor.on("init", () => {
|
|
51
|
+
setReady(true);
|
|
52
|
+
onInit?.(editor);
|
|
53
|
+
});
|
|
54
|
+
editor.on("dirty", (dirty) => {
|
|
55
|
+
onDirty?.(dirty);
|
|
56
|
+
});
|
|
57
|
+
editor.on("change", (content) => {
|
|
58
|
+
onChange?.(content);
|
|
59
|
+
editor.setDirty(false);
|
|
60
|
+
});
|
|
61
|
+
editor.on("focus", () => {
|
|
62
|
+
onFocus?.();
|
|
63
|
+
});
|
|
64
|
+
editor.on("blur", () => {
|
|
65
|
+
onBlur?.();
|
|
66
|
+
});
|
|
67
|
+
return () => {
|
|
68
|
+
editor.destroy();
|
|
69
|
+
editorRef.current = null;
|
|
70
|
+
if (globalEditor === editor) globalEditor = null;
|
|
71
|
+
};
|
|
72
|
+
}, []);
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
if (containerRef.current) {
|
|
75
|
+
containerRef.current.style.pointerEvents = disabled ? "none" : "";
|
|
76
|
+
containerRef.current.style.opacity = disabled ? "0.6" : "";
|
|
77
|
+
}
|
|
78
|
+
}, [disabled]);
|
|
79
|
+
useImperativeHandle(ref, () => ({
|
|
80
|
+
getEditor: () => editorRef.current,
|
|
81
|
+
getContent: () => editorRef.current?.getContent() ?? "",
|
|
82
|
+
setContent: (html) => editorRef.current?.setContent(html),
|
|
83
|
+
insertContent: (html) => editorRef.current?.insertContent(html),
|
|
84
|
+
focus: () => editorRef.current?.focus()
|
|
85
|
+
}), []);
|
|
86
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
87
|
+
className: "md-editor-react-wrapper",
|
|
88
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
89
|
+
ref: containerRef,
|
|
90
|
+
className: "md-editor-container"
|
|
91
|
+
}), name && ready && /* @__PURE__ */ jsx("input", {
|
|
92
|
+
type: "hidden",
|
|
93
|
+
name,
|
|
94
|
+
value: editorRef.current?.getContent() ?? ""
|
|
95
|
+
})]
|
|
96
|
+
});
|
|
104
97
|
});
|
|
105
98
|
Editor.displayName = "MDHTMLEditor";
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/useEditor.ts
|
|
101
|
+
/**
|
|
102
|
+
* useEditor Hook
|
|
103
|
+
* Custom hook for advanced editor usage
|
|
104
|
+
*/
|
|
105
|
+
/**
|
|
106
|
+
* Hook for programmatic editor control
|
|
107
|
+
*/
|
|
106
108
|
function useEditor(options = {}) {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
insertContent,
|
|
152
|
-
focus,
|
|
153
|
-
isDirty
|
|
154
|
-
};
|
|
109
|
+
const { config = {}, content = "", onUpdate } = options;
|
|
110
|
+
const containerRef = useRef(null);
|
|
111
|
+
const editorRef = useRef(null);
|
|
112
|
+
const [ready, setReady] = useState(false);
|
|
113
|
+
useEffect(() => {
|
|
114
|
+
if (!containerRef.current) return;
|
|
115
|
+
const editor = new HTMLEditor(containerRef.current, config);
|
|
116
|
+
editorRef.current = editor;
|
|
117
|
+
if (content) editor.setContent(content);
|
|
118
|
+
editor.on("init", () => {
|
|
119
|
+
setReady(true);
|
|
120
|
+
});
|
|
121
|
+
if (onUpdate) editor.on("change", onUpdate);
|
|
122
|
+
return () => {
|
|
123
|
+
editor.destroy();
|
|
124
|
+
editorRef.current = null;
|
|
125
|
+
setReady(false);
|
|
126
|
+
};
|
|
127
|
+
}, []);
|
|
128
|
+
const getContent = useCallback(() => {
|
|
129
|
+
return editorRef.current?.getContent() ?? "";
|
|
130
|
+
}, []);
|
|
131
|
+
const setContent = useCallback((html) => {
|
|
132
|
+
editorRef.current?.setContent(html);
|
|
133
|
+
}, []);
|
|
134
|
+
const insertContent = useCallback((html) => {
|
|
135
|
+
editorRef.current?.insertContent(html);
|
|
136
|
+
}, []);
|
|
137
|
+
const focus = useCallback(() => {
|
|
138
|
+
editorRef.current?.focus();
|
|
139
|
+
}, []);
|
|
140
|
+
const isDirty = useCallback(() => {
|
|
141
|
+
return editorRef.current?.isDirty() ?? false;
|
|
142
|
+
}, []);
|
|
143
|
+
return {
|
|
144
|
+
editor: editorRef.current,
|
|
145
|
+
containerRef,
|
|
146
|
+
ready,
|
|
147
|
+
getContent,
|
|
148
|
+
setContent,
|
|
149
|
+
insertContent,
|
|
150
|
+
focus,
|
|
151
|
+
isDirty
|
|
152
|
+
};
|
|
155
153
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
Editor as MDEditor,
|
|
159
|
-
fontNames,
|
|
160
|
-
getEditorContent,
|
|
161
|
-
setEditorContent,
|
|
162
|
-
setGetFileSrc2 as setGetFileSrc,
|
|
163
|
-
setTranslate2 as setTranslate,
|
|
164
|
-
useEditor
|
|
165
|
-
};
|
|
154
|
+
//#endregion
|
|
155
|
+
export { Editor, Editor as MDEditor, fontNames, getEditorContent, setEditorContent, setGetFileSrc, setTranslate, useEditor };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { HTMLEditor, EditorConfig } from '@mdaemon/html-editor';
|
|
2
|
+
export interface UseEditorOptions {
|
|
3
|
+
config?: EditorConfig;
|
|
4
|
+
content?: string;
|
|
5
|
+
onUpdate?: (html: string) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface UseEditorReturn {
|
|
8
|
+
/**
|
|
9
|
+
* The editor instance
|
|
10
|
+
*/
|
|
11
|
+
editor: HTMLEditor | null;
|
|
12
|
+
/**
|
|
13
|
+
* Ref to attach to the container element
|
|
14
|
+
*/
|
|
15
|
+
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Whether the editor is ready
|
|
18
|
+
*/
|
|
19
|
+
ready: boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Get the current HTML content
|
|
22
|
+
*/
|
|
23
|
+
getContent: () => string;
|
|
24
|
+
/**
|
|
25
|
+
* Set the HTML content
|
|
26
|
+
*/
|
|
27
|
+
setContent: (html: string) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Insert HTML at cursor
|
|
30
|
+
*/
|
|
31
|
+
insertContent: (html: string) => void;
|
|
32
|
+
/**
|
|
33
|
+
* Focus the editor
|
|
34
|
+
*/
|
|
35
|
+
focus: () => void;
|
|
36
|
+
/**
|
|
37
|
+
* Check if editor is dirty
|
|
38
|
+
*/
|
|
39
|
+
isDirty: () => boolean;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Hook for programmatic editor control
|
|
43
|
+
*/
|
|
44
|
+
export declare function useEditor(options?: UseEditorOptions): UseEditorReturn;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mdaemon/html-editor-react",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "React wrapper for MDHTMLEditor",
|
|
5
5
|
"homepage": "https://github.com/mdaemon-technologies/MDHTMLEditor-react",
|
|
6
6
|
"repository": {
|
|
@@ -53,10 +53,11 @@
|
|
|
53
53
|
"react-dom": "^19.0.0 || ^18.0.0"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
|
-
"@mdaemon/html-editor": "^1.
|
|
57
|
-
"@tiptap/react": "^3.
|
|
56
|
+
"@mdaemon/html-editor": "^1.9.0",
|
|
57
|
+
"@tiptap/react": "^3.27.4"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|
|
60
|
+
"@eslint/js": "^9.39.4",
|
|
60
61
|
"@swc/core": "^1.11.0",
|
|
61
62
|
"@swc/jest": "^0.2.39",
|
|
62
63
|
"@testing-library/jest-dom": "^6.9.1",
|
|
@@ -64,18 +65,23 @@
|
|
|
64
65
|
"@types/jest": "^30.0.0",
|
|
65
66
|
"@types/react": "^19.2.0",
|
|
66
67
|
"@types/react-dom": "^19.2.0",
|
|
67
|
-
"@vitejs/plugin-react": "^
|
|
68
|
+
"@vitejs/plugin-react": "^6.0.2",
|
|
69
|
+
"eslint": "^9.39.4",
|
|
70
|
+
"eslint-plugin-react": "^7.37.5",
|
|
71
|
+
"eslint-plugin-react-hooks": "^5.2.0",
|
|
72
|
+
"globals": "^15.15.0",
|
|
68
73
|
"jest": "^30.3.0",
|
|
69
74
|
"jest-environment-jsdom": "^30.3.0",
|
|
70
75
|
"react": "^19.2.0",
|
|
71
76
|
"react-dom": "^19.2.0",
|
|
72
77
|
"typescript": "^6.0.2",
|
|
73
|
-
"
|
|
74
|
-
"vite
|
|
78
|
+
"typescript-eslint": "^8.61.0",
|
|
79
|
+
"vite": "^8.0.16",
|
|
80
|
+
"vite-plugin-dts": "^5.0.2"
|
|
75
81
|
},
|
|
76
82
|
"allowScripts": {
|
|
77
|
-
"@swc/core
|
|
78
|
-
"esbuild
|
|
79
|
-
"unrs-resolver
|
|
83
|
+
"@swc/core": true,
|
|
84
|
+
"esbuild": true,
|
|
85
|
+
"unrs-resolver": true
|
|
80
86
|
}
|
|
81
87
|
}
|