argous 1.2.204 → 1.2.205
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/dist/components/Editor/Events.d.ts +7 -9
- package/dist/components/Editor/Events.js +7 -0
- package/dist/components/Editor/TinyMCE.d.ts +8 -1
- package/dist/components/Editor/TinyMCE.js +10 -2
- package/dist/components/Editor/Utils.d.ts +7 -2
- package/dist/components/Editor/Utils.js +9 -29
- package/dist/components/Editor/components/Editor.d.ts +16 -17
- package/dist/components/Editor/components/Editor.js +50 -93
- package/dist/components/Editor/components/EditorPropTypes.d.ts +8 -1
- package/dist/components/Editor/components/EditorPropTypes.js +9 -19
- package/dist/components/Editor/index.d.ts +9 -2
- package/dist/components/Editor/index.js +7 -0
- package/lib/components/Editor/Events.ts +8 -9
- package/lib/components/Editor/ScriptLoader.ts +96 -0
- package/lib/components/Editor/TinyMCE.ts +12 -2
- package/lib/components/Editor/Utils.ts +8 -25
- package/lib/components/Editor/components/Editor.tsx +78 -101
- package/lib/components/Editor/components/EditorPropTypes.ts +12 -21
- package/lib/components/Editor/index.tsx +10 -2
- package/package.json +1 -1
- package/lib/components/Editor/ScriptLoader2.ts +0 -161
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Ephox, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache 2 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { uuid } from './Utils';
|
|
10
|
+
|
|
11
|
+
export type callbackFn = () => void;
|
|
12
|
+
export interface IStateObj {
|
|
13
|
+
listeners: callbackFn[];
|
|
14
|
+
scriptId: string;
|
|
15
|
+
scriptLoading: boolean;
|
|
16
|
+
scriptLoaded: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const createState = (): IStateObj => ({
|
|
20
|
+
listeners: [],
|
|
21
|
+
scriptId: uuid('tiny-script'),
|
|
22
|
+
scriptLoading: false,
|
|
23
|
+
scriptLoaded: false
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
interface ScriptLoaderInterface {
|
|
27
|
+
load: (doc: Document, url: string, async: boolean, defer: boolean, delay: number, callback: callbackFn) => void;
|
|
28
|
+
reinitialize: () => void;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const CreateScriptLoader = (): ScriptLoaderInterface => {
|
|
32
|
+
let state: IStateObj = createState();
|
|
33
|
+
|
|
34
|
+
const injectScriptTag = (scriptId: string, doc: Document, url: string, async: boolean, defer: boolean, callback: callbackFn) => {
|
|
35
|
+
const scriptTag = doc.createElement('script');
|
|
36
|
+
scriptTag.referrerPolicy = 'origin';
|
|
37
|
+
scriptTag.type = 'application/javascript';
|
|
38
|
+
scriptTag.id = scriptId;
|
|
39
|
+
scriptTag.src = url;
|
|
40
|
+
scriptTag.async = async;
|
|
41
|
+
scriptTag.defer = defer;
|
|
42
|
+
|
|
43
|
+
// scriptTag.appendChild(document.createTextNode(url));
|
|
44
|
+
|
|
45
|
+
const handler = () => {
|
|
46
|
+
scriptTag.removeEventListener('load', handler);
|
|
47
|
+
callback();
|
|
48
|
+
};
|
|
49
|
+
scriptTag.addEventListener('load', handler);
|
|
50
|
+
if (doc.head) {
|
|
51
|
+
doc.head.appendChild(scriptTag);
|
|
52
|
+
}
|
|
53
|
+
// document.body.appendChild(scriptTag);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const load = (doc: Document, url: string, async: boolean, defer: boolean, delay: number, callback: callbackFn) => {
|
|
57
|
+
|
|
58
|
+
const scriptTagInjection = () => injectScriptTag(
|
|
59
|
+
state.scriptId, doc, url, async, defer,
|
|
60
|
+
() => {
|
|
61
|
+
state.listeners.forEach((fn) => fn());
|
|
62
|
+
state.scriptLoaded = true;
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
if (state.scriptLoaded) {
|
|
67
|
+
callback();
|
|
68
|
+
} else {
|
|
69
|
+
state.listeners.push(callback);
|
|
70
|
+
if (!state.scriptLoading) {
|
|
71
|
+
state.scriptLoading = true;
|
|
72
|
+
if (delay > 0) {
|
|
73
|
+
setTimeout(scriptTagInjection, delay);
|
|
74
|
+
} else {
|
|
75
|
+
scriptTagInjection();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
// Only to be used by tests.
|
|
82
|
+
const reinitialize = () => {
|
|
83
|
+
state = createState();
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
load,
|
|
88
|
+
reinitialize
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const ScriptLoader = CreateScriptLoader();
|
|
93
|
+
|
|
94
|
+
export {
|
|
95
|
+
ScriptLoader
|
|
96
|
+
};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Ephox, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache 2 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { TinyMCE as TinyMCEGlobal } from './tinymce/tinymce';
|
|
2
10
|
|
|
3
|
-
const
|
|
4
|
-
|
|
11
|
+
const getGlobal = (): any => (typeof window !== 'undefined' ? window : global);
|
|
12
|
+
|
|
13
|
+
const getTinymce = (): TinyMCEGlobal | null => {
|
|
14
|
+
const global = getGlobal();
|
|
5
15
|
|
|
6
16
|
return global && global.tinymce ? global.tinymce : null;
|
|
7
17
|
};
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Ephox, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache 2 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { IAllProps } from './components/Editor';
|
|
2
10
|
import { eventPropTypes, IEventPropTypes } from './components/EditorPropTypes';
|
|
3
11
|
import { Editor as TinyMCEEditor, EditorEvent } from './tinymce/tinymce';
|
|
@@ -52,7 +60,6 @@ export const configHandlers = (
|
|
|
52
60
|
lookup,
|
|
53
61
|
editor.on.bind(editor),
|
|
54
62
|
editor.off.bind(editor),
|
|
55
|
-
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
56
63
|
(handlerLookup, key) => (e) => handlerLookup(key)?.(e, editor),
|
|
57
64
|
prevProps,
|
|
58
65
|
props,
|
|
@@ -86,27 +93,3 @@ export const mergePlugins = (initPlugins: string | string[] | undefined, inputPl
|
|
|
86
93
|
|
|
87
94
|
export const isBeforeInputEventAvailable = () => window.InputEvent && typeof (InputEvent.prototype as any).getTargetRanges === 'function';
|
|
88
95
|
|
|
89
|
-
export const isInDoc = (elem: Node) => {
|
|
90
|
-
if (!('isConnected' in Node.prototype)) {
|
|
91
|
-
// Fallback for IE and old Edge
|
|
92
|
-
let current = elem;
|
|
93
|
-
let parent = elem.parentNode;
|
|
94
|
-
while (parent != null) {
|
|
95
|
-
current = parent;
|
|
96
|
-
parent = current.parentNode;
|
|
97
|
-
}
|
|
98
|
-
return current === elem.ownerDocument;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return elem.isConnected;
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
export const setMode = (editor: TinyMCEEditor | undefined, mode: 'readonly' | 'design') => {
|
|
105
|
-
if (editor !== undefined) {
|
|
106
|
-
if (editor.mode != null && typeof editor.mode === 'object' && typeof editor.mode.set === 'function') {
|
|
107
|
-
editor.mode.set(mode);
|
|
108
|
-
} else { // support TinyMCE 4
|
|
109
|
-
(editor as any).setMode(mode);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
};
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Ephox, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache 2 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { EditorPropTypes, IEditorPropTypes } from './EditorPropTypes';
|
|
2
10
|
import { IEvents } from '../Events';
|
|
3
|
-
import {
|
|
11
|
+
import { ScriptLoader } from '../ScriptLoader';
|
|
4
12
|
import { getTinymce } from '../TinyMCE';
|
|
5
|
-
import { Bookmark, Editor as TinyMCEEditor, EditorEvent,
|
|
6
|
-
import { isFunction, isTextareaOrInput, mergePlugins, uuid, configHandlers, isBeforeInputEventAvailable
|
|
13
|
+
import { Bookmark, Editor as TinyMCEEditor, EditorEvent, RawEditorOptions } from '../tinymce/tinymce';
|
|
14
|
+
import { isFunction, isTextareaOrInput, mergePlugins, uuid, configHandlers, isBeforeInputEventAvailable } from '../Utils';
|
|
15
|
+
import { useTheme } from '@material-ui/core';
|
|
7
16
|
import * as React from 'react';
|
|
8
17
|
|
|
9
|
-
type EditorOptions = Parameters<TinyMCE['init']>[0];
|
|
10
|
-
|
|
11
18
|
export interface IProps {
|
|
12
19
|
apiKey: string;
|
|
13
20
|
id: string;
|
|
@@ -15,15 +22,16 @@ export interface IProps {
|
|
|
15
22
|
initialValue: string;
|
|
16
23
|
onEditorChange: (a: string, editor: TinyMCEEditor) => void;
|
|
17
24
|
value: string;
|
|
18
|
-
init:
|
|
25
|
+
init: RawEditorOptions & { selector?: undefined; target?: undefined };
|
|
26
|
+
/** @deprecated use `editor.getContent({format: 'text' })` in `onEditorChange` prop instead */
|
|
27
|
+
outputFormat: 'html' | 'text';
|
|
19
28
|
tagName: string;
|
|
20
29
|
cloudChannel: string;
|
|
21
|
-
plugins: NonNullable<
|
|
22
|
-
toolbar: NonNullable<
|
|
30
|
+
plugins: NonNullable<RawEditorOptions['plugins']>;
|
|
31
|
+
toolbar: NonNullable<RawEditorOptions['toolbar']>;
|
|
23
32
|
disabled: boolean;
|
|
24
33
|
textareaName: string;
|
|
25
|
-
tinymceScriptSrc: string
|
|
26
|
-
rollback: number | false;
|
|
34
|
+
tinymceScriptSrc: string;
|
|
27
35
|
scriptLoading: {
|
|
28
36
|
async?: boolean;
|
|
29
37
|
defer?: boolean;
|
|
@@ -33,11 +41,14 @@ export interface IProps {
|
|
|
33
41
|
|
|
34
42
|
export interface IAllProps extends Partial<IProps>, Partial<IEvents> { }
|
|
35
43
|
|
|
44
|
+
const changeEvents = () => getTinymce()?.Env?.browser?.isIE() ? 'change keyup compositionend setcontent' : 'change input compositionend setcontent';
|
|
45
|
+
const beforeInputEvent = () => isBeforeInputEventAvailable() ? 'beforeinput SelectionChange' : 'SelectionChange';
|
|
46
|
+
|
|
36
47
|
export class Editor extends React.Component<IAllProps> {
|
|
37
48
|
public static propTypes: IEditorPropTypes = EditorPropTypes;
|
|
38
49
|
|
|
39
50
|
public static defaultProps: Partial<IAllProps> = {
|
|
40
|
-
cloudChannel: '
|
|
51
|
+
cloudChannel: '5'
|
|
41
52
|
};
|
|
42
53
|
|
|
43
54
|
public editor?: TinyMCEEditor;
|
|
@@ -58,10 +69,6 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
58
69
|
this.boundHandlers = {};
|
|
59
70
|
}
|
|
60
71
|
|
|
61
|
-
private get view() {
|
|
62
|
-
return this.elementRef.current?.ownerDocument.defaultView ?? window;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
72
|
public componentDidUpdate(prevProps: Partial<IAllProps>) {
|
|
66
73
|
if (this.rollbackTimer) {
|
|
67
74
|
clearTimeout(this.rollbackTimer);
|
|
@@ -107,31 +114,23 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
107
114
|
}
|
|
108
115
|
if (this.props.disabled !== prevProps.disabled) {
|
|
109
116
|
const disabled = this.props.disabled ?? false;
|
|
110
|
-
|
|
117
|
+
this.editor.mode.set(disabled ? 'readonly' : 'design');
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
120
|
}
|
|
114
121
|
}
|
|
115
122
|
|
|
116
123
|
public componentDidMount() {
|
|
117
|
-
if (getTinymce(
|
|
124
|
+
if (getTinymce() !== null) {
|
|
118
125
|
this.initialise();
|
|
119
|
-
} else if (
|
|
120
|
-
|
|
121
|
-
} else if (this.elementRef.current?.ownerDocument) {
|
|
122
|
-
const successHandler = () => {
|
|
123
|
-
this.props.onScriptsLoad?.();
|
|
124
|
-
this.initialise();
|
|
125
|
-
};
|
|
126
|
-
const errorHandler = (err: unknown) => {
|
|
127
|
-
this.props.onScriptsLoadError?.(err);
|
|
128
|
-
};
|
|
129
|
-
ScriptLoader.loadList(
|
|
126
|
+
} else if (this.elementRef.current && this.elementRef.current.ownerDocument) {
|
|
127
|
+
ScriptLoader.load(
|
|
130
128
|
this.elementRef.current.ownerDocument,
|
|
131
|
-
this.
|
|
129
|
+
this.getScriptSrc(),
|
|
130
|
+
this.props.scriptLoading?.async ?? false,
|
|
131
|
+
this.props.scriptLoading?.defer ?? false,
|
|
132
132
|
this.props.scriptLoading?.delay ?? 0,
|
|
133
|
-
|
|
134
|
-
errorHandler
|
|
133
|
+
this.initialise
|
|
135
134
|
);
|
|
136
135
|
}
|
|
137
136
|
}
|
|
@@ -139,8 +138,8 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
139
138
|
public componentWillUnmount() {
|
|
140
139
|
const editor = this.editor;
|
|
141
140
|
if (editor) {
|
|
142
|
-
editor.off(
|
|
143
|
-
editor.off(
|
|
141
|
+
editor.off(changeEvents(), this.handleEditorChange);
|
|
142
|
+
editor.off(beforeInputEvent(), this.handleBeforeInput);
|
|
144
143
|
editor.off('keypress', this.handleEditorChangeSpecial);
|
|
145
144
|
editor.off('keydown', this.handleBeforeInputSpecial);
|
|
146
145
|
editor.off('NewBlock', this.handleEditorChange);
|
|
@@ -154,19 +153,11 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
154
153
|
}
|
|
155
154
|
|
|
156
155
|
public render() {
|
|
157
|
-
return
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
return (isIE
|
|
163
|
-
? 'change keyup compositionend setcontent CommentChange'
|
|
164
|
-
: 'change input compositionend setcontent CommentChange'
|
|
165
|
-
);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
private beforeInputEvent() {
|
|
169
|
-
return isBeforeInputEventAvailable() ? 'beforeinput SelectionChange' : 'SelectionChange';
|
|
156
|
+
return <>
|
|
157
|
+
<Tema>
|
|
158
|
+
{this.inline ? this.renderInline() : this.renderIframe()}
|
|
159
|
+
</Tema>
|
|
160
|
+
</>;
|
|
170
161
|
}
|
|
171
162
|
|
|
172
163
|
private renderInline() {
|
|
@@ -187,29 +178,14 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
187
178
|
});
|
|
188
179
|
}
|
|
189
180
|
|
|
190
|
-
private
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
if (typeof this.props.tinymceScriptSrc === 'string') {
|
|
195
|
-
return [{ src: this.props.tinymceScriptSrc, async, defer }];
|
|
196
|
-
}
|
|
197
|
-
// multiple scripts can be specified which allows for hybrid mode
|
|
198
|
-
return this.props.tinymceScriptSrc.map((item) => {
|
|
199
|
-
if (typeof item === 'string') {
|
|
200
|
-
// async does not make sense for multiple items unless
|
|
201
|
-
// they are not dependent (which will be unlikely)
|
|
202
|
-
return { src: item, async, defer };
|
|
203
|
-
}
|
|
204
|
-
return item;
|
|
205
|
-
|
|
206
|
-
});
|
|
207
|
-
}
|
|
208
|
-
// fallback to the cloud when the tinymceScriptSrc is not specified
|
|
181
|
+
private getScriptSrc() {
|
|
182
|
+
// if (typeof this.props.tinymceScriptSrc === 'string') {
|
|
183
|
+
// return this.props.tinymceScriptSrc;
|
|
184
|
+
// }
|
|
209
185
|
const channel = this.props.cloudChannel;
|
|
210
186
|
const apiKey = this.props.apiKey ? this.props.apiKey : 'no-api-key';
|
|
211
|
-
|
|
212
|
-
return
|
|
187
|
+
|
|
188
|
+
return `https://cdn.tiny.cloud/1/${apiKey}/tinymce/${channel}/tinymce.min.js`;
|
|
213
189
|
}
|
|
214
190
|
|
|
215
191
|
private getInitialValue() {
|
|
@@ -225,20 +201,20 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
225
201
|
private bindHandlers(prevProps: Partial<IAllProps>) {
|
|
226
202
|
if (this.editor !== undefined) {
|
|
227
203
|
// typescript chokes trying to understand the type of the lookup function
|
|
228
|
-
configHandlers(this.editor, prevProps, this.props, this.boundHandlers, (key) => this.props[key] as any);
|
|
204
|
+
configHandlers(this.editor as any, prevProps, this.props, this.boundHandlers, (key) => this.props[key] as any);
|
|
229
205
|
// check if we should monitor editor changes
|
|
230
206
|
const isValueControlled = (p: Partial<IAllProps>) => p.onEditorChange !== undefined || p.value !== undefined;
|
|
231
207
|
const wasControlled = isValueControlled(prevProps);
|
|
232
208
|
const nowControlled = isValueControlled(this.props);
|
|
233
209
|
if (!wasControlled && nowControlled) {
|
|
234
|
-
this.editor.on(
|
|
235
|
-
this.editor.on(
|
|
210
|
+
this.editor.on(changeEvents(), this.handleEditorChange);
|
|
211
|
+
this.editor.on(beforeInputEvent(), this.handleBeforeInput);
|
|
236
212
|
this.editor.on('keydown', this.handleBeforeInputSpecial);
|
|
237
213
|
this.editor.on('keyup', this.handleEditorChangeSpecial);
|
|
238
214
|
this.editor.on('NewBlock', this.handleEditorChange);
|
|
239
215
|
} else if (wasControlled && !nowControlled) {
|
|
240
|
-
this.editor.off(
|
|
241
|
-
this.editor.off(
|
|
216
|
+
this.editor.off(changeEvents(), this.handleEditorChange);
|
|
217
|
+
this.editor.off(beforeInputEvent(), this.handleBeforeInput);
|
|
242
218
|
this.editor.off('keydown', this.handleBeforeInputSpecial);
|
|
243
219
|
this.editor.off('keyup', this.handleEditorChangeSpecial);
|
|
244
220
|
this.editor.off('NewBlock', this.handleEditorChange);
|
|
@@ -286,20 +262,19 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
286
262
|
const editor = this.editor;
|
|
287
263
|
if (editor && editor.initialized) {
|
|
288
264
|
const newContent = editor.getContent();
|
|
289
|
-
if (this.props.value !== undefined && this.props.value !== newContent
|
|
265
|
+
if (this.props.value !== undefined && this.props.value !== newContent) {
|
|
290
266
|
// start a timer and revert to the value if not applied in time
|
|
291
267
|
if (!this.rollbackTimer) {
|
|
292
|
-
this.rollbackTimer = window.setTimeout(
|
|
293
|
-
this.rollbackChange,
|
|
294
|
-
typeof this.props.rollback === 'number' ? this.props.rollback : 200
|
|
295
|
-
);
|
|
268
|
+
this.rollbackTimer = window.setTimeout(this.rollbackChange, 200);
|
|
296
269
|
}
|
|
297
270
|
}
|
|
298
271
|
|
|
299
272
|
if (newContent !== this.currentContent) {
|
|
300
273
|
this.currentContent = newContent;
|
|
301
274
|
if (isFunction(this.props.onEditorChange)) {
|
|
302
|
-
this.props.
|
|
275
|
+
const format = this.props.outputFormat;
|
|
276
|
+
const out = format === 'html' ? newContent : editor.getContent({ format });
|
|
277
|
+
this.props.onEditorChange(out, editor);
|
|
303
278
|
}
|
|
304
279
|
}
|
|
305
280
|
}
|
|
@@ -311,41 +286,25 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
311
286
|
}
|
|
312
287
|
};
|
|
313
288
|
|
|
314
|
-
private initialise = (
|
|
289
|
+
private initialise = () => {
|
|
315
290
|
const target = this.elementRef.current;
|
|
316
291
|
if (!target) {
|
|
317
292
|
return; // Editor has been unmounted
|
|
318
293
|
}
|
|
319
|
-
if (!isInDoc(target)) {
|
|
320
|
-
// this is probably someone trying to help by rendering us offscreen
|
|
321
|
-
// but we can't do that because the editor iframe must be in the document
|
|
322
|
-
// in order to have state
|
|
323
|
-
if (attempts === 0) {
|
|
324
|
-
// we probably just need to wait for the current events to be processed
|
|
325
|
-
setTimeout(() => this.initialise(1), 1);
|
|
326
|
-
} else if (attempts < 100) {
|
|
327
|
-
// wait for ten seconds, polling every tenth of a second
|
|
328
|
-
setTimeout(() => this.initialise(attempts + 1), 100);
|
|
329
|
-
} else {
|
|
330
|
-
// give up, at this point it seems that more polling is unlikely to help
|
|
331
|
-
throw new Error('tinymce can only be initialised when in a document');
|
|
332
|
-
}
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
294
|
|
|
336
|
-
const tinymce = getTinymce(
|
|
295
|
+
const tinymce = getTinymce();
|
|
337
296
|
if (!tinymce) {
|
|
338
297
|
throw new Error('tinymce should have been loaded into global scope');
|
|
339
298
|
}
|
|
340
299
|
|
|
341
|
-
const finalInit:
|
|
300
|
+
const finalInit: RawEditorOptions = {
|
|
342
301
|
...this.props.init,
|
|
343
302
|
selector: undefined,
|
|
344
303
|
target,
|
|
345
304
|
readonly: this.props.disabled,
|
|
346
305
|
inline: this.inline,
|
|
347
|
-
plugins: mergePlugins(this.props.init
|
|
348
|
-
toolbar: this.props.toolbar
|
|
306
|
+
plugins: mergePlugins(this.props.init && this.props.init.plugins, this.props.plugins),
|
|
307
|
+
toolbar: this.props.toolbar || (this.props.init && this.props.init.toolbar),
|
|
349
308
|
setup: (editor) => {
|
|
350
309
|
this.editor = editor;
|
|
351
310
|
this.bindHandlers({});
|
|
@@ -379,7 +338,7 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
379
338
|
editor.setDirty(false);
|
|
380
339
|
}
|
|
381
340
|
const disabled = this.props.disabled ?? false;
|
|
382
|
-
|
|
341
|
+
editor.mode.set(disabled ? 'readonly' : 'design');
|
|
383
342
|
// ensure existing init_instance_callback is called
|
|
384
343
|
if (this.props.init && isFunction(this.props.init.init_instance_callback)) {
|
|
385
344
|
this.props.init.init_instance_callback(editor);
|
|
@@ -393,6 +352,24 @@ export class Editor extends React.Component<IAllProps> {
|
|
|
393
352
|
target.value = this.getInitialValue();
|
|
394
353
|
}
|
|
395
354
|
|
|
396
|
-
tinymce.init(finalInit);
|
|
355
|
+
tinymce.init(finalInit as any);
|
|
397
356
|
};
|
|
398
357
|
}
|
|
358
|
+
|
|
359
|
+
const Tema = ({ children }) => {
|
|
360
|
+
|
|
361
|
+
const theme = useTheme().palette.type;
|
|
362
|
+
|
|
363
|
+
return (
|
|
364
|
+
<div>
|
|
365
|
+
{theme === 'dark' ? <>
|
|
366
|
+
<link rel='stylesheet' href='./skins/ui/dark/skin.min.css' />
|
|
367
|
+
<link rel='stylesheet' href='./skins/ui/dark/content.min.css' />
|
|
368
|
+
</> : <>
|
|
369
|
+
<link rel='stylesheet' href='./skins/ui/default/content.min.css' />
|
|
370
|
+
<link rel='stylesheet' href='./skins/ui/default/skin.min.css' />
|
|
371
|
+
</>}
|
|
372
|
+
{children}
|
|
373
|
+
</div>
|
|
374
|
+
);
|
|
375
|
+
};
|
|
@@ -1,8 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Ephox, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache 2 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
8
|
+
|
|
1
9
|
import { IProps } from './Editor';
|
|
2
10
|
import { IEvents } from '../Events';
|
|
3
11
|
import * as PropTypes from 'prop-types';
|
|
4
12
|
|
|
5
|
-
export type CopyProps<T> = { [P in keyof T]: PropTypes.Requireable<unknown> };
|
|
13
|
+
export type CopyProps<T> = { [P in keyof T]: PropTypes.Requireable<P | unknown> };
|
|
6
14
|
|
|
7
15
|
export type IEventPropTypes = CopyProps<IEvents>;
|
|
8
16
|
|
|
@@ -22,7 +30,6 @@ export const eventPropTypes: IEventPropTypes = {
|
|
|
22
30
|
onClearUndos: PropTypes.func,
|
|
23
31
|
onClick: PropTypes.func,
|
|
24
32
|
onContextMenu: PropTypes.func,
|
|
25
|
-
onCommentChange: PropTypes.func,
|
|
26
33
|
onCopy: PropTypes.func,
|
|
27
34
|
onCut: PropTypes.func,
|
|
28
35
|
onDblclick: PropTypes.func,
|
|
@@ -71,15 +78,7 @@ export const eventPropTypes: IEventPropTypes = {
|
|
|
71
78
|
onShow: PropTypes.func,
|
|
72
79
|
onSubmit: PropTypes.func,
|
|
73
80
|
onUndo: PropTypes.func,
|
|
74
|
-
onVisualAid: PropTypes.func
|
|
75
|
-
onSkinLoadError: PropTypes.func,
|
|
76
|
-
onThemeLoadError: PropTypes.func,
|
|
77
|
-
onModelLoadError: PropTypes.func,
|
|
78
|
-
onPluginLoadError: PropTypes.func,
|
|
79
|
-
onIconsLoadError: PropTypes.func,
|
|
80
|
-
onLanguageLoadError: PropTypes.func,
|
|
81
|
-
onScriptsLoad: PropTypes.func,
|
|
82
|
-
onScriptsLoadError: PropTypes.func,
|
|
81
|
+
onVisualAid: PropTypes.func
|
|
83
82
|
};
|
|
84
83
|
|
|
85
84
|
export const EditorPropTypes: IEditorPropTypes = {
|
|
@@ -89,6 +88,7 @@ export const EditorPropTypes: IEditorPropTypes = {
|
|
|
89
88
|
init: PropTypes.object,
|
|
90
89
|
initialValue: PropTypes.string,
|
|
91
90
|
onEditorChange: PropTypes.func,
|
|
91
|
+
outputFormat: PropTypes.oneOf(['html', 'text']),
|
|
92
92
|
value: PropTypes.string,
|
|
93
93
|
tagName: PropTypes.string,
|
|
94
94
|
cloudChannel: PropTypes.string,
|
|
@@ -96,16 +96,7 @@ export const EditorPropTypes: IEditorPropTypes = {
|
|
|
96
96
|
toolbar: PropTypes.oneOfType([PropTypes.string, PropTypes.array]),
|
|
97
97
|
disabled: PropTypes.bool,
|
|
98
98
|
textareaName: PropTypes.string,
|
|
99
|
-
tinymceScriptSrc: PropTypes.
|
|
100
|
-
PropTypes.string,
|
|
101
|
-
PropTypes.arrayOf(PropTypes.string),
|
|
102
|
-
PropTypes.arrayOf(PropTypes.shape({
|
|
103
|
-
src: PropTypes.string,
|
|
104
|
-
async: PropTypes.bool,
|
|
105
|
-
defer: PropTypes.bool
|
|
106
|
-
}))
|
|
107
|
-
]),
|
|
108
|
-
rollback: PropTypes.oneOfType([PropTypes.number, PropTypes.oneOf([false])]),
|
|
99
|
+
tinymceScriptSrc: PropTypes.string,
|
|
109
100
|
scriptLoading: PropTypes.shape({
|
|
110
101
|
async: PropTypes.bool,
|
|
111
102
|
defer: PropTypes.bool,
|
|
@@ -1,3 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2017-present, Ephox, Inc.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the Apache 2 license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
2
8
|
|
|
3
|
-
|
|
9
|
+
import { Editor } from './components/Editor';
|
|
10
|
+
|
|
11
|
+
export { Editor };
|