argous 1.2.206 → 1.2.208

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.
@@ -1,11 +1,3 @@
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
1
  import { Editor as TinyMCEEditor, EditorEvent, Events } from './tinymce/tinymce';
10
2
 
11
3
  export type EventHandler<A> = (a: EditorEvent<A>, editor: TinyMCEEditor) => unknown;
@@ -53,6 +45,7 @@ export interface ITinyEvents {
53
45
  onBeforeSetContent: EEventHandler<'BeforeSetContent'>;
54
46
  onChange: EventHandler<unknown>;
55
47
  onClearUndos: EEventHandler<'ClearUndos'>;
48
+ onCommentChange: EventHandler<unknown>;
56
49
  onDeactivate: EEventHandler<'deactivate'>;
57
50
  onDirty: EventHandler<unknown>;
58
51
  onExecCommand: EEventHandler<'ExecCommand'>;
@@ -78,6 +71,14 @@ export interface ITinyEvents {
78
71
  onSubmit: EventHandler<unknown>;
79
72
  onUndo: EEventHandler<'Undo'>;
80
73
  onVisualAid: EventHandler<unknown>;
74
+ onSkinLoadError: EEventHandler<'SkinLoadError'>;
75
+ onThemeLoadError: EEventHandler<'ThemeLoadError'>;
76
+ onModelLoadError: EEventHandler<'ModelLoadError'>;
77
+ onPluginLoadError: EEventHandler<'PluginLoadError'>;
78
+ onIconsLoadError: EEventHandler<'IconsLoadError'>;
79
+ onLanguageLoadError: EEventHandler<'LanguageLoadError'>;
80
+ onScriptsLoad: () => void;
81
+ onScriptsLoadError: (err: unknown) => void;
81
82
  }
82
83
 
83
84
  export interface IEvents extends INativeEvents, ITinyEvents {}
@@ -0,0 +1,161 @@
1
+ import { uuid } from './Utils';
2
+
3
+ export type CallbackFn = () => void;
4
+
5
+ export interface ScriptItem {
6
+ src: string;
7
+ async?: boolean;
8
+ defer?: boolean;
9
+ }
10
+
11
+ interface Id {
12
+ id: string;
13
+ }
14
+
15
+ const injectScriptTag = (doc: Document, item: ScriptItem & Id, handler: (id: string, err?: unknown) => void) => {
16
+ const scriptTag = doc.createElement('script');
17
+ scriptTag.referrerPolicy = 'origin';
18
+ scriptTag.type = 'application/javascript';
19
+ scriptTag.id = item.id;
20
+ scriptTag.src = item.src;
21
+ scriptTag.async = item.async ?? false;
22
+ scriptTag.defer = item.defer ?? false;
23
+
24
+ const loadHandler = () => {
25
+ scriptTag.removeEventListener('load', loadHandler);
26
+ scriptTag.removeEventListener('error', errorHandler);
27
+ handler(item.src);
28
+ };
29
+ const errorHandler = (err: unknown) => {
30
+ scriptTag.removeEventListener('load', loadHandler);
31
+ scriptTag.removeEventListener('error', errorHandler);
32
+ handler(item.src, err);
33
+ };
34
+
35
+ scriptTag.addEventListener('load', loadHandler);
36
+ scriptTag.addEventListener('error', errorHandler);
37
+
38
+ if (doc.head) {
39
+ doc.head.appendChild(scriptTag);
40
+ }
41
+ };
42
+
43
+ interface ScriptState {
44
+ id: string;
45
+ src: string;
46
+ done: boolean;
47
+ error?: unknown;
48
+ handlers: ((src: string, err?: unknown) => void)[];
49
+ }
50
+
51
+ const createDocumentScriptLoader = (doc: Document) => {
52
+ let lookup: Record<string, ScriptState> = {};
53
+
54
+ const scriptLoadOrErrorHandler = (src: string, err?: unknown) => {
55
+ const item = lookup[src];
56
+ item.done = true;
57
+ item.error = err;
58
+ for (const h of item.handlers) {
59
+ h(src, err);
60
+ }
61
+ item.handlers = [];
62
+ };
63
+
64
+ const loadScripts = (items: ScriptItem[], success: () => void, failure?: (err: unknown) => void) => {
65
+ // eslint-disable-next-line no-console
66
+ const failureOrLog = (err: unknown) => failure !== undefined ? failure(err) : console.error(err);
67
+ if (items.length === 0) {
68
+ failureOrLog(new Error('At least one script must be provided'));
69
+ return;
70
+ }
71
+ let successCount = 0;
72
+ let failed = false;
73
+ const loaded = (_src: string, err?: unknown) => {
74
+ if (failed) {
75
+ return;
76
+ }
77
+ if (err) {
78
+ failed = true;
79
+ failureOrLog(err);
80
+ } else if (++successCount === items.length) {
81
+ success();
82
+ }
83
+ };
84
+ for (const item of items) {
85
+ const existing = lookup[item.src];
86
+ if (existing) {
87
+ if (existing.done) {
88
+ loaded(item.src, existing.error);
89
+ } else {
90
+ existing.handlers.push(loaded);
91
+ }
92
+ } else {
93
+ // create a new entry
94
+ const id = uuid('tiny-');
95
+ lookup[item.src] = {
96
+ id,
97
+ src: item.src,
98
+ done: false,
99
+ error: null,
100
+ handlers: [loaded],
101
+ };
102
+ injectScriptTag(doc, { id, ...item }, scriptLoadOrErrorHandler);
103
+ }
104
+ }
105
+ };
106
+
107
+ const deleteScripts = () => {
108
+ for (const item of Object.values(lookup)) {
109
+ const scriptTag = doc.getElementById(item.id);
110
+ if (scriptTag != null && scriptTag.tagName === 'SCRIPT') {
111
+ scriptTag.parentNode?.removeChild(scriptTag);
112
+ }
113
+ }
114
+ lookup = {};
115
+ };
116
+
117
+ const getDocument = () => doc;
118
+
119
+ return {
120
+ loadScripts,
121
+ deleteScripts,
122
+ getDocument
123
+ };
124
+ };
125
+
126
+ type DocumentScriptLoader = ReturnType<typeof createDocumentScriptLoader>;
127
+
128
+ const createScriptLoader = () => {
129
+ const cache: DocumentScriptLoader[] = [];
130
+
131
+ const getDocumentScriptLoader = (doc: Document) => {
132
+ let loader = cache.find((l) => l.getDocument() === doc);
133
+ if (loader === undefined) {
134
+ loader = createDocumentScriptLoader(doc);
135
+ cache.push(loader);
136
+ }
137
+ return loader;
138
+ };
139
+
140
+ const loadList = (doc: Document, items: ScriptItem[], delay: number, success: () => void, failure?: (err: unknown) => void) => {
141
+ const doLoad = () => getDocumentScriptLoader(doc).loadScripts(items, success, failure);
142
+ if (delay > 0) {
143
+ setTimeout(doLoad, delay);
144
+ } else {
145
+ doLoad();
146
+ }
147
+ };
148
+
149
+ const reinitialize = () => {
150
+ for (let loader = cache.pop(); loader != null; loader = cache.pop()) {
151
+ loader.deleteScripts();
152
+ }
153
+ };
154
+
155
+ return {
156
+ loadList,
157
+ reinitialize
158
+ };
159
+ };
160
+
161
+ export const ScriptLoader = createScriptLoader();
@@ -1,17 +1,7 @@
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
1
  import { TinyMCE as TinyMCEGlobal } from './tinymce/tinymce';
10
2
 
11
- const getGlobal = (): any => (typeof window !== 'undefined' ? window : global);
12
-
13
- const getTinymce = (): TinyMCEGlobal | null => {
14
- const global = getGlobal();
3
+ const getTinymce = (view: Window): TinyMCEGlobal | null => {
4
+ const global = view as any;
15
5
 
16
6
  return global && global.tinymce ? global.tinymce : null;
17
7
  };
@@ -1,11 +1,3 @@
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
1
  import { IAllProps } from './components/Editor';
10
2
  import { eventPropTypes, IEventPropTypes } from './components/EditorPropTypes';
11
3
  import { Editor as TinyMCEEditor, EditorEvent } from './tinymce/tinymce';
@@ -60,6 +52,7 @@ export const configHandlers = (
60
52
  lookup,
61
53
  editor.on.bind(editor),
62
54
  editor.off.bind(editor),
55
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
63
56
  (handlerLookup, key) => (e) => handlerLookup(key)?.(e, editor),
64
57
  prevProps,
65
58
  props,
@@ -93,3 +86,27 @@ export const mergePlugins = (initPlugins: string | string[] | undefined, inputPl
93
86
 
94
87
  export const isBeforeInputEventAvailable = () => window.InputEvent && typeof (InputEvent.prototype as any).getTargetRanges === 'function';
95
88
 
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,20 +1,13 @@
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
1
  import { EditorPropTypes, IEditorPropTypes } from './EditorPropTypes';
10
2
  import { IEvents } from '../Events';
11
- import { ScriptLoader } from '../ScriptLoader';
3
+ import { ScriptItem, ScriptLoader } from '../ScriptLoader2';
12
4
  import { getTinymce } from '../TinyMCE';
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';
5
+ import { Bookmark, Editor as TinyMCEEditor, EditorEvent, TinyMCE } from '../tinymce/tinymce';
6
+ import { isFunction, isTextareaOrInput, mergePlugins, uuid, configHandlers, isBeforeInputEventAvailable, isInDoc, setMode } from '../Utils';
16
7
  import * as React from 'react';
17
8
 
9
+ type EditorOptions = Parameters<TinyMCE['init']>[0];
10
+
18
11
  export interface IProps {
19
12
  apiKey: string;
20
13
  id: string;
@@ -22,16 +15,15 @@ export interface IProps {
22
15
  initialValue: string;
23
16
  onEditorChange: (a: string, editor: TinyMCEEditor) => void;
24
17
  value: string;
25
- init: RawEditorOptions & { selector?: undefined; target?: undefined };
26
- /** @deprecated use `editor.getContent({format: 'text' })` in `onEditorChange` prop instead */
27
- outputFormat: 'html' | 'text';
18
+ init: EditorOptions & { selector?: undefined; target?: undefined };
28
19
  tagName: string;
29
20
  cloudChannel: string;
30
- plugins: NonNullable<RawEditorOptions['plugins']>;
31
- toolbar: NonNullable<RawEditorOptions['toolbar']>;
21
+ plugins: NonNullable<EditorOptions['plugins']>;
22
+ toolbar: NonNullable<EditorOptions['toolbar']>;
32
23
  disabled: boolean;
33
24
  textareaName: string;
34
- tinymceScriptSrc: string;
25
+ tinymceScriptSrc: string | string[] | ScriptItem[];
26
+ rollback: number | false;
35
27
  scriptLoading: {
36
28
  async?: boolean;
37
29
  defer?: boolean;
@@ -41,14 +33,11 @@ export interface IProps {
41
33
 
42
34
  export interface IAllProps extends Partial<IProps>, Partial<IEvents> { }
43
35
 
44
- const changeEvents = () => getTinymce()?.Env?.browser?.isIE() ? 'change keyup compositionend setcontent' : 'change input compositionend setcontent';
45
- const beforeInputEvent = () => isBeforeInputEventAvailable() ? 'beforeinput SelectionChange' : 'SelectionChange';
46
-
47
36
  export class Editor extends React.Component<IAllProps> {
48
37
  public static propTypes: IEditorPropTypes = EditorPropTypes;
49
38
 
50
39
  public static defaultProps: Partial<IAllProps> = {
51
- cloudChannel: '5'
40
+ cloudChannel: '6'
52
41
  };
53
42
 
54
43
  public editor?: TinyMCEEditor;
@@ -69,6 +58,10 @@ export class Editor extends React.Component<IAllProps> {
69
58
  this.boundHandlers = {};
70
59
  }
71
60
 
61
+ private get view() {
62
+ return this.elementRef.current?.ownerDocument.defaultView ?? window;
63
+ }
64
+
72
65
  public componentDidUpdate(prevProps: Partial<IAllProps>) {
73
66
  if (this.rollbackTimer) {
74
67
  clearTimeout(this.rollbackTimer);
@@ -114,23 +107,31 @@ export class Editor extends React.Component<IAllProps> {
114
107
  }
115
108
  if (this.props.disabled !== prevProps.disabled) {
116
109
  const disabled = this.props.disabled ?? false;
117
- this.editor.mode.set(disabled ? 'readonly' : 'design');
110
+ setMode(this.editor, disabled ? 'readonly' : 'design');
118
111
  }
119
112
  }
120
113
  }
121
114
  }
122
115
 
123
116
  public componentDidMount() {
124
- if (getTinymce() !== null) {
117
+ if (getTinymce(this.view) !== null) {
125
118
  this.initialise();
126
- } else if (this.elementRef.current && this.elementRef.current.ownerDocument) {
127
- ScriptLoader.load(
119
+ } else if (Array.isArray(this.props.tinymceScriptSrc) && this.props.tinymceScriptSrc.length === 0) {
120
+ this.props.onScriptsLoadError?.(new Error('No `tinymce` global is present but the `tinymceScriptSrc` prop was an empty array.'));
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(
128
130
  this.elementRef.current.ownerDocument,
129
- this.getScriptSrc(),
130
- this.props.scriptLoading?.async ?? false,
131
- this.props.scriptLoading?.defer ?? false,
131
+ this.getScriptSources(),
132
132
  this.props.scriptLoading?.delay ?? 0,
133
- this.initialise
133
+ successHandler,
134
+ errorHandler
134
135
  );
135
136
  }
136
137
  }
@@ -138,8 +139,8 @@ export class Editor extends React.Component<IAllProps> {
138
139
  public componentWillUnmount() {
139
140
  const editor = this.editor;
140
141
  if (editor) {
141
- editor.off(changeEvents(), this.handleEditorChange);
142
- editor.off(beforeInputEvent(), this.handleBeforeInput);
142
+ editor.off(this.changeEvents(), this.handleEditorChange);
143
+ editor.off(this.beforeInputEvent(), this.handleBeforeInput);
143
144
  editor.off('keypress', this.handleEditorChangeSpecial);
144
145
  editor.off('keydown', this.handleBeforeInputSpecial);
145
146
  editor.off('NewBlock', this.handleEditorChange);
@@ -153,11 +154,19 @@ export class Editor extends React.Component<IAllProps> {
153
154
  }
154
155
 
155
156
  public render() {
156
- return <>
157
- <Tema>
158
- {this.inline ? this.renderInline() : this.renderIframe()}
159
- </Tema>
160
- </>;
157
+ return this.inline ? this.renderInline() : this.renderIframe();
158
+ }
159
+
160
+ private changeEvents() {
161
+ const isIE = getTinymce(this.view)?.Env?.browser?.isIE();
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';
161
170
  }
162
171
 
163
172
  private renderInline() {
@@ -178,15 +187,29 @@ export class Editor extends React.Component<IAllProps> {
178
187
  });
179
188
  }
180
189
 
181
- private getScriptSrc() {
182
- if (typeof this.props.tinymceScriptSrc === 'string') {
183
- return this.props.tinymceScriptSrc;
190
+ private getScriptSources(): ScriptItem[] {
191
+ const async = this.props.scriptLoading?.async;
192
+ const defer = this.props.scriptLoading?.defer;
193
+ if (this.props.tinymceScriptSrc !== undefined) {
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
+ });
184
207
  }
185
-
208
+ // fallback to the cloud when the tinymceScriptSrc is not specified
186
209
  const channel = this.props.cloudChannel;
187
210
  const apiKey = this.props.apiKey ? this.props.apiKey : 'no-api-key';
188
-
189
- return `https://cdn.tiny.cloud/1/${apiKey}/tinymce/${channel}/tinymce.min.js`;
211
+ const cloudTinyJs = `https://cdn.tiny.cloud/1/${apiKey}/tinymce/${channel}/tinymce.min.js`;
212
+ return [{ src: cloudTinyJs, async, defer }];
190
213
  }
191
214
 
192
215
  private getInitialValue() {
@@ -202,20 +225,20 @@ export class Editor extends React.Component<IAllProps> {
202
225
  private bindHandlers(prevProps: Partial<IAllProps>) {
203
226
  if (this.editor !== undefined) {
204
227
  // typescript chokes trying to understand the type of the lookup function
205
- configHandlers(this.editor as any, prevProps, this.props, this.boundHandlers, (key) => this.props[key] as any);
228
+ configHandlers(this.editor, prevProps, this.props, this.boundHandlers, (key) => this.props[key] as any);
206
229
  // check if we should monitor editor changes
207
230
  const isValueControlled = (p: Partial<IAllProps>) => p.onEditorChange !== undefined || p.value !== undefined;
208
231
  const wasControlled = isValueControlled(prevProps);
209
232
  const nowControlled = isValueControlled(this.props);
210
233
  if (!wasControlled && nowControlled) {
211
- this.editor.on(changeEvents(), this.handleEditorChange);
212
- this.editor.on(beforeInputEvent(), this.handleBeforeInput);
234
+ this.editor.on(this.changeEvents(), this.handleEditorChange);
235
+ this.editor.on(this.beforeInputEvent(), this.handleBeforeInput);
213
236
  this.editor.on('keydown', this.handleBeforeInputSpecial);
214
237
  this.editor.on('keyup', this.handleEditorChangeSpecial);
215
238
  this.editor.on('NewBlock', this.handleEditorChange);
216
239
  } else if (wasControlled && !nowControlled) {
217
- this.editor.off(changeEvents(), this.handleEditorChange);
218
- this.editor.off(beforeInputEvent(), this.handleBeforeInput);
240
+ this.editor.off(this.changeEvents(), this.handleEditorChange);
241
+ this.editor.off(this.beforeInputEvent(), this.handleBeforeInput);
219
242
  this.editor.off('keydown', this.handleBeforeInputSpecial);
220
243
  this.editor.off('keyup', this.handleEditorChangeSpecial);
221
244
  this.editor.off('NewBlock', this.handleEditorChange);
@@ -263,19 +286,20 @@ export class Editor extends React.Component<IAllProps> {
263
286
  const editor = this.editor;
264
287
  if (editor && editor.initialized) {
265
288
  const newContent = editor.getContent();
266
- if (this.props.value !== undefined && this.props.value !== newContent) {
289
+ if (this.props.value !== undefined && this.props.value !== newContent && this.props.rollback !== false) {
267
290
  // start a timer and revert to the value if not applied in time
268
291
  if (!this.rollbackTimer) {
269
- this.rollbackTimer = window.setTimeout(this.rollbackChange, 200);
292
+ this.rollbackTimer = window.setTimeout(
293
+ this.rollbackChange,
294
+ typeof this.props.rollback === 'number' ? this.props.rollback : 200
295
+ );
270
296
  }
271
297
  }
272
298
 
273
299
  if (newContent !== this.currentContent) {
274
300
  this.currentContent = newContent;
275
301
  if (isFunction(this.props.onEditorChange)) {
276
- const format = this.props.outputFormat;
277
- const out = format === 'html' ? newContent : editor.getContent({ format });
278
- this.props.onEditorChange(out, editor);
302
+ this.props.onEditorChange(newContent, editor);
279
303
  }
280
304
  }
281
305
  }
@@ -287,25 +311,41 @@ export class Editor extends React.Component<IAllProps> {
287
311
  }
288
312
  };
289
313
 
290
- private initialise = () => {
314
+ private initialise = (attempts = 0) => {
291
315
  const target = this.elementRef.current;
292
316
  if (!target) {
293
317
  return; // Editor has been unmounted
294
318
  }
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
+ }
295
335
 
296
- const tinymce = getTinymce();
336
+ const tinymce = getTinymce(this.view);
297
337
  if (!tinymce) {
298
338
  throw new Error('tinymce should have been loaded into global scope');
299
339
  }
300
340
 
301
- const finalInit: RawEditorOptions = {
341
+ const finalInit: EditorOptions = {
302
342
  ...this.props.init,
303
343
  selector: undefined,
304
344
  target,
305
345
  readonly: this.props.disabled,
306
346
  inline: this.inline,
307
- plugins: mergePlugins(this.props.init && this.props.init.plugins, this.props.plugins),
308
- toolbar: this.props.toolbar || (this.props.init && this.props.init.toolbar),
347
+ plugins: mergePlugins(this.props.init?.plugins, this.props.plugins),
348
+ toolbar: this.props.toolbar ?? this.props.init?.toolbar,
309
349
  setup: (editor) => {
310
350
  this.editor = editor;
311
351
  this.bindHandlers({});
@@ -339,7 +379,7 @@ export class Editor extends React.Component<IAllProps> {
339
379
  editor.setDirty(false);
340
380
  }
341
381
  const disabled = this.props.disabled ?? false;
342
- editor.mode.set(disabled ? 'readonly' : 'design');
382
+ setMode(this.editor, disabled ? 'readonly' : 'design');
343
383
  // ensure existing init_instance_callback is called
344
384
  if (this.props.init && isFunction(this.props.init.init_instance_callback)) {
345
385
  this.props.init.init_instance_callback(editor);
@@ -353,24 +393,6 @@ export class Editor extends React.Component<IAllProps> {
353
393
  target.value = this.getInitialValue();
354
394
  }
355
395
 
356
- tinymce.init(finalInit as any);
396
+ tinymce.init(finalInit);
357
397
  };
358
398
  }
359
-
360
- const Tema = ({ children }) => {
361
-
362
- const theme = useTheme().palette.type;
363
-
364
- return (
365
- <div>
366
- {theme === 'dark' ? <>
367
- <link rel='stylesheet' href='./skins/ui/dark/skin.min.css' />
368
- <link rel='stylesheet' href='./skins/ui/dark/content.min.css' />
369
- </> : <>
370
- <link rel='stylesheet' href='./skins/ui/default/content.min.css' />
371
- <link rel='stylesheet' href='./skins/ui/default/skin.min.css' />
372
- </>}
373
- {children}
374
- </div>
375
- );
376
- };
@@ -1,16 +1,8 @@
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
1
  import { IProps } from './Editor';
10
2
  import { IEvents } from '../Events';
11
3
  import * as PropTypes from 'prop-types';
12
4
 
13
- export type CopyProps<T> = { [P in keyof T]: PropTypes.Requireable<P | unknown> };
5
+ export type CopyProps<T> = { [P in keyof T]: PropTypes.Requireable<unknown> };
14
6
 
15
7
  export type IEventPropTypes = CopyProps<IEvents>;
16
8
 
@@ -30,6 +22,7 @@ export const eventPropTypes: IEventPropTypes = {
30
22
  onClearUndos: PropTypes.func,
31
23
  onClick: PropTypes.func,
32
24
  onContextMenu: PropTypes.func,
25
+ onCommentChange: PropTypes.func,
33
26
  onCopy: PropTypes.func,
34
27
  onCut: PropTypes.func,
35
28
  onDblclick: PropTypes.func,
@@ -78,7 +71,15 @@ export const eventPropTypes: IEventPropTypes = {
78
71
  onShow: PropTypes.func,
79
72
  onSubmit: PropTypes.func,
80
73
  onUndo: PropTypes.func,
81
- onVisualAid: 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,
82
83
  };
83
84
 
84
85
  export const EditorPropTypes: IEditorPropTypes = {
@@ -88,7 +89,6 @@ export const EditorPropTypes: IEditorPropTypes = {
88
89
  init: PropTypes.object,
89
90
  initialValue: PropTypes.string,
90
91
  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,7 +96,16 @@ 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.string,
99
+ tinymceScriptSrc: PropTypes.oneOfType([
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])]),
100
109
  scriptLoading: PropTypes.shape({
101
110
  async: PropTypes.bool,
102
111
  defer: PropTypes.bool,
@@ -1,11 +1,3 @@
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
- */
1
+ import { Editor, IAllProps } from './components/Editor';
8
2
 
9
- import { Editor } from './components/Editor';
10
-
11
- export { Editor };
3
+ export { Editor, IAllProps };
package/lib/utils/api.ts CHANGED
@@ -56,7 +56,7 @@ export const enableDebugger = () => {
56
56
  debuging = true;
57
57
  };
58
58
 
59
- export const serverAction = async (metodo:string, dados = {}, pgCode?:string|boolean, tratarErro?:string|boolean) => {
59
+ export const serverAction = async (metodo:string, dados = {}, pgCode?:string|boolean, tratarErro?:string|boolean, token?:string) => {
60
60
 
61
61
  const code = typeof pgCode === 'string' ? pgCode : typeof tratarErro === 'string' ? tratarErro : undefined;
62
62
  const tErro = typeof tratarErro === 'boolean' ? tratarErro : typeof pgCode === 'boolean' ? pgCode : false;
@@ -66,7 +66,8 @@ export const serverAction = async (metodo:string, dados = {}, pgCode?:string|boo
66
66
  const data = {
67
67
  pgCode: currentProgram,
68
68
  action: metodo,
69
- dados
69
+ dados,
70
+ token
70
71
  };
71
72
 
72
73
  const res = await action(data);