@ckeditor/ckeditor5-editor-decoupled 48.8.1-alpha.3 → 49.0.0-alpha.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/dist/index.js CHANGED
@@ -2,277 +2,266 @@
2
2
  * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
4
  */
5
- import { ElementApiMixin, Editor, normalizeSingleRootEditorConstructorParams, normalizeRootsConfig, secureSourceElement, registerAndInitializeRootConfigAttributes, verifyRootElements } from '@ckeditor/ckeditor5-core/dist/index.js';
6
- import { CKEditorError } from '@ckeditor/ckeditor5-utils/dist/index.js';
7
- import { EditorUI, EditorUIView, ToolbarView, MenuBarView, InlineEditableUIView } from '@ckeditor/ckeditor5-ui/dist/index.js';
8
- import { enableViewPlaceholder } from '@ckeditor/ckeditor5-engine/dist/index.js';
9
- import { isElement as isElement$1 } from 'es-toolkit/compat';
5
+ import { Editor, ElementApiMixin, normalizeRootsConfig, normalizeSingleRootEditorConstructorParams, registerAndInitializeRootConfigAttributes, rootAcceptsBlocks, secureSourceElement, verifyRootElements } from "@ckeditor/ckeditor5-core";
6
+ import { EditorUI, EditorUIView, InlineEditableUIView, MenuBarView, ToolbarView } from "@ckeditor/ckeditor5-ui";
7
+ import { enableViewPlaceholder } from "@ckeditor/ckeditor5-engine";
8
+ import { isElement } from "es-toolkit/compat";
10
9
 
11
10
  /**
12
- * The decoupled editor UI class.
13
- */ class DecoupledEditorUI extends EditorUI {
14
- /**
15
- * The main (top–most) view of the editor UI.
16
- */ view;
17
- /**
18
- * Creates an instance of the decoupled editor UI class.
19
- *
20
- * @param editor The editor instance.
21
- * @param view The view of the UI.
22
- */ constructor(editor, view){
23
- super(editor);
24
- this.view = view;
25
- }
26
- /**
27
- * Initializes the UI.
28
- */ init() {
29
- const editor = this.editor;
30
- const view = this.view;
31
- const editingView = editor.editing.view;
32
- const editable = view.editable;
33
- const editingRoot = editingView.document.getRoot();
34
- // The editable UI and editing root should share the same name. Then name is used
35
- // to recognize the particular editable, for instance in ARIA attributes.
36
- editable.name = editingRoot.rootName;
37
- view.render();
38
- // The editable UI element in DOM is available for sure only after the editor UI view has been rendered.
39
- // But it can be available earlier if a DOM element has been passed to DecoupledEditor.create().
40
- const editableElement = editable.element;
41
- // Register the editable UI view in the editor. A single editor instance can aggregate multiple
42
- // editable areas (roots) but the decoupled editor has only one.
43
- this.setEditableElement(editable.name, editableElement);
44
- // Let the editable UI element respond to the changes in the global editor focus
45
- // tracker. It has been added to the same tracker a few lines above but, in reality, there are
46
- // many focusable areas in the editor, like balloons, toolbars or dropdowns and as long
47
- // as they have focus, the editable should act like it is focused too (although technically
48
- // it isn't), e.g. by setting the proper CSS class, visually announcing focus to the user.
49
- // Doing otherwise will result in editable focus styles disappearing, once e.g. the
50
- // toolbar gets focused.
51
- view.editable.bind('isFocused').to(this.focusTracker);
52
- // Bind the editable UI element to the editing view, making it an end– and entry–point
53
- // of the editor's engine. This is where the engine meets the UI.
54
- editingView.attachDomRoot(editableElement);
55
- this._initPlaceholder();
56
- this._initToolbar();
57
- this.initMenuBar(this.view.menuBarView);
58
- this.fire('ready');
59
- }
60
- /**
61
- * @inheritDoc
62
- */ destroy() {
63
- super.destroy();
64
- const view = this.view;
65
- const editingView = this.editor.editing.view;
66
- if (editingView.getDomRoot(view.editable.name)) {
67
- editingView.detachDomRoot(view.editable.name);
68
- }
69
- view.destroy();
70
- }
71
- /**
72
- * Initializes the inline editor toolbar and its panel.
73
- */ _initToolbar() {
74
- const editor = this.editor;
75
- const view = this.view;
76
- const toolbar = view.toolbar;
77
- toolbar.fillFromConfig(editor.config.get('toolbar'), this.componentFactory);
78
- // Register the toolbar so it becomes available for Alt+F10 and Esc navigation.
79
- this.addToolbar(view.toolbar);
80
- }
81
- /**
82
- * Enable the placeholder text on the editing root.
83
- */ _initPlaceholder() {
84
- const editor = this.editor;
85
- const editingView = editor.editing.view;
86
- const editingRoot = editingView.document.getRoot();
87
- const placeholder = editor.config.get('roots')[editingRoot.rootName].placeholder;
88
- if (placeholder) {
89
- editingRoot.placeholder = placeholder;
90
- }
91
- enableViewPlaceholder({
92
- view: editingView,
93
- element: editingRoot,
94
- isDirectHost: false,
95
- keepOnFocus: true
96
- });
97
- }
98
- }
11
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
12
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
13
+ */
14
+ /**
15
+ * @module editor-decoupled/decouplededitorui
16
+ */
17
+ /**
18
+ * The decoupled editor UI class.
19
+ */
20
+ var DecoupledEditorUI = class extends EditorUI {
21
+ /**
22
+ * The main (top–most) view of the editor UI.
23
+ */
24
+ view;
25
+ /**
26
+ * Creates an instance of the decoupled editor UI class.
27
+ *
28
+ * @param editor The editor instance.
29
+ * @param view The view of the UI.
30
+ */
31
+ constructor(editor, view) {
32
+ super(editor);
33
+ this.view = view;
34
+ }
35
+ /**
36
+ * Initializes the UI.
37
+ */
38
+ init() {
39
+ const editor = this.editor;
40
+ const view = this.view;
41
+ const editingView = editor.editing.view;
42
+ const editable = view.editable;
43
+ const editingRoot = editingView.document.getRoot();
44
+ editable.name = editingRoot.rootName;
45
+ editable.isInlineRoot = !rootAcceptsBlocks(editor, editingRoot.rootName);
46
+ view.render();
47
+ const editableElement = editable.element;
48
+ this.setEditableElement(editable.name, editableElement);
49
+ view.editable.bind("isFocused").to(this.focusTracker);
50
+ editingView.attachDomRoot(editableElement);
51
+ this._initPlaceholder();
52
+ this._initToolbar();
53
+ this.initMenuBar(this.view.menuBarView);
54
+ this.fire("ready");
55
+ }
56
+ /**
57
+ * @inheritDoc
58
+ */
59
+ destroy() {
60
+ super.destroy();
61
+ const view = this.view;
62
+ const editingView = this.editor.editing.view;
63
+ if (editingView.getDomRoot(view.editable.name)) editingView.detachDomRoot(view.editable.name);
64
+ view.destroy();
65
+ }
66
+ /**
67
+ * Initializes the inline editor toolbar and its panel.
68
+ */
69
+ _initToolbar() {
70
+ const editor = this.editor;
71
+ const view = this.view;
72
+ view.toolbar.fillFromConfig(editor.config.get("toolbar"), this.componentFactory);
73
+ this.addToolbar(view.toolbar);
74
+ }
75
+ /**
76
+ * Enable the placeholder text on the editing root.
77
+ */
78
+ _initPlaceholder() {
79
+ const editor = this.editor;
80
+ const editingView = editor.editing.view;
81
+ const editingRoot = editingView.document.getRoot();
82
+ const placeholder = editor.config.get("roots")[editingRoot.rootName].placeholder;
83
+ if (placeholder) editingRoot.placeholder = placeholder;
84
+ enableViewPlaceholder({
85
+ view: editingView,
86
+ element: editingRoot,
87
+ isDirectHost: this.view.editable.isInlineRoot,
88
+ keepOnFocus: true
89
+ });
90
+ }
91
+ };
99
92
 
100
93
  /**
101
- * The decoupled editor UI view. It is a virtual view providing an inline
102
- * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#editable},
103
- * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#toolbar}, and a
104
- * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#menuBarView} but without any
105
- * specific arrangement of the components in the DOM.
106
- *
107
- * See {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`}
108
- * to learn more about this view.
109
- */ class DecoupledEditorUIView extends EditorUIView {
110
- /**
111
- * The main toolbar of the decoupled editor UI.
112
- */ toolbar;
113
- /**
114
- * The editable of the decoupled editor UI.
115
- */ editable;
116
- /**
117
- * Menu bar view instance.
118
- */ menuBarView;
119
- /**
120
- * Creates an instance of the decoupled editor UI view.
121
- *
122
- * @param locale The {@link module:core/editor/editor~Editor#locale} instance.
123
- * @param editingView The editing view instance this view is related to.
124
- * @param options Configuration options for the view instance.
125
- * @param options.editableElement The editable element. If not specified, it will be automatically created by
126
- * {@link module:ui/editableui/editableuiview~EditableUIView}. Otherwise, the given element will be used.
127
- * @param options.shouldToolbarGroupWhenFull When set `true` enables automatic items grouping
128
- * in the main {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#toolbar toolbar}.
129
- * See {@link module:ui/toolbar/toolbarview~ToolbarOptions#shouldGroupWhenFull} to learn more.
130
- * @param options.label When set, this value will be used as an accessible `aria-label` of the
131
- * {@link module:ui/editableui/editableuiview~EditableUIView editable view}.
132
- */ constructor(locale, editingView, options = {}){
133
- super(locale);
134
- this.toolbar = new ToolbarView(locale, {
135
- shouldGroupWhenFull: options.shouldToolbarGroupWhenFull
136
- });
137
- this.menuBarView = new MenuBarView(locale);
138
- this.editable = new InlineEditableUIView(locale, editingView, options.editableElement, {
139
- label: options.label
140
- });
141
- // This toolbar may be placed anywhere in the page so things like font size need to be reset in it.
142
- // Because of the above, make sure the toolbar supports rounded corners.
143
- // Also, make sure the toolbar has the proper dir attribute because its ancestor may not have one
144
- // and some toolbar item styles depend on this attribute.
145
- this.toolbar.extendTemplate({
146
- attributes: {
147
- class: [
148
- 'ck-reset_all',
149
- 'ck-rounded-corners'
150
- ],
151
- dir: locale.uiLanguageDirection
152
- }
153
- });
154
- this.menuBarView.extendTemplate({
155
- attributes: {
156
- class: [
157
- 'ck-reset_all',
158
- 'ck-rounded-corners'
159
- ],
160
- dir: locale.uiLanguageDirection
161
- }
162
- });
163
- }
164
- /**
165
- * @inheritDoc
166
- */ render() {
167
- super.render();
168
- this.registerChild([
169
- this.menuBarView,
170
- this.toolbar,
171
- this.editable
172
- ]);
173
- }
174
- }
94
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
95
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
96
+ */
97
+ /**
98
+ * @module editor-decoupled/decouplededitoruiview
99
+ */
100
+ /**
101
+ * The decoupled editor UI view. It is a virtual view providing an inline
102
+ * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#editable},
103
+ * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#toolbar}, and a
104
+ * {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#menuBarView} but without any
105
+ * specific arrangement of the components in the DOM.
106
+ *
107
+ * See {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`}
108
+ * to learn more about this view.
109
+ */
110
+ var DecoupledEditorUIView = class extends EditorUIView {
111
+ /**
112
+ * The main toolbar of the decoupled editor UI.
113
+ */
114
+ toolbar;
115
+ /**
116
+ * The editable of the decoupled editor UI.
117
+ */
118
+ editable;
119
+ /**
120
+ * Menu bar view instance.
121
+ */
122
+ menuBarView;
123
+ /**
124
+ * Creates an instance of the decoupled editor UI view.
125
+ *
126
+ * @param locale The {@link module:core/editor/editor~Editor#locale} instance.
127
+ * @param editingView The editing view instance this view is related to.
128
+ * @param options Configuration options for the view instance.
129
+ * @param options.editableElement The editable element. If not specified, it will be automatically created by
130
+ * {@link module:ui/editableui/editableuiview~EditableUIView}. Otherwise, the given element will be used.
131
+ * @param options.shouldToolbarGroupWhenFull When set `true` enables automatic items grouping
132
+ * in the main {@link module:editor-decoupled/decouplededitoruiview~DecoupledEditorUIView#toolbar toolbar}.
133
+ * See {@link module:ui/toolbar/toolbarview~ToolbarOptions#shouldGroupWhenFull} to learn more.
134
+ * @param options.label When set, this value will be used as an accessible `aria-label` of the
135
+ * {@link module:ui/editableui/editableuiview~EditableUIView editable view}.
136
+ */
137
+ constructor(locale, editingView, options = {}) {
138
+ super(locale);
139
+ this.toolbar = new ToolbarView(locale, { shouldGroupWhenFull: options.shouldToolbarGroupWhenFull });
140
+ this.menuBarView = new MenuBarView(locale);
141
+ this.editable = new InlineEditableUIView(locale, editingView, options.editableElement, { label: options.label });
142
+ this.toolbar.extendTemplate({ attributes: {
143
+ class: ["ck-reset_all", "ck-rounded-corners"],
144
+ dir: locale.uiLanguageDirection
145
+ } });
146
+ this.menuBarView.extendTemplate({ attributes: {
147
+ class: ["ck-reset_all", "ck-rounded-corners"],
148
+ dir: locale.uiLanguageDirection
149
+ } });
150
+ }
151
+ /**
152
+ * @inheritDoc
153
+ */
154
+ render() {
155
+ super.render();
156
+ this.registerChild([
157
+ this.menuBarView,
158
+ this.toolbar,
159
+ this.editable
160
+ ]);
161
+ }
162
+ };
175
163
 
176
164
  /**
177
- * The decoupled editor implementation. It provides an inline editable and a toolbar. However, unlike other editors,
178
- * it does not render these components anywhere in the DOM unless configured.
179
- *
180
- * This type of an editor is dedicated to integrations which require a customized UI with an open
181
- * structure, allowing developers to specify the exact location of the interface.
182
- *
183
- * See the document editor {@glink examples/builds/document-editor demo} to learn about possible use cases
184
- * for the decoupled editor.
185
- *
186
- * In order to create a decoupled editor instance, use the static
187
- * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`} method.
188
- *
189
- * Note that you will need to attach the editor toolbar and menu bar to your web page manually, in a desired place,
190
- * after the editor is initialized.
191
- */ class DecoupledEditor extends /* #__PURE__ */ ElementApiMixin(Editor) {
192
- /**
193
- * @inheritDoc
194
- */ static get editorName() {
195
- return 'DecoupledEditor';
196
- }
197
- /**
198
- * @inheritDoc
199
- */ ui;
200
- constructor(sourceElementOrDataOrConfig, config = {}){
201
- const { sourceElementOrData, editorConfig } = normalizeSingleRootEditorConstructorParams(sourceElementOrDataOrConfig, config);
202
- super(editorConfig);
203
- normalizeRootsConfig(sourceElementOrData, this.config);
204
- // From this point use only normalized `roots.main.element`.
205
- const sourceElement = this.config.get('roots').main.element;
206
- if (isElement(sourceElement)) {
207
- if (sourceElement.tagName === 'TEXTAREA') {
208
- // Documented in core/editor/editor.js
209
- // eslint-disable-next-line ckeditor5-rules/ckeditor-error-message
210
- throw new CKEditorError('editor-wrong-element', null);
211
- }
212
- this.sourceElement = sourceElement;
213
- secureSourceElement(this, sourceElement);
214
- }
215
- this.model.document.createRoot(this.config.get('roots').main.modelElement);
216
- registerAndInitializeRootConfigAttributes(this);
217
- const shouldToolbarGroupWhenFull = !this.config.get('toolbar.shouldNotGroupWhenFull');
218
- const view = new DecoupledEditorUIView(this.locale, this.editing.view, {
219
- editableElement: this.sourceElement,
220
- shouldToolbarGroupWhenFull,
221
- label: this.config.get('roots').main.label
222
- });
223
- this.ui = new DecoupledEditorUI(this, view);
224
- }
225
- /**
226
- * Destroys the editor instance, releasing all resources used by it.
227
- *
228
- * Updates the original editor element with the data if the
229
- * {@link module:core/editor/editorconfig~EditorConfig#updateSourceElementOnDestroy `updateSourceElementOnDestroy`}
230
- * configuration option is set to `true`.
231
- *
232
- * **Note**: The decoupled editor does not remove the toolbar and editable when destroyed. You can
233
- * do that yourself in the destruction chain:
234
- *
235
- * ```ts
236
- * editor.destroy()
237
- * .then( () => {
238
- * // Remove the toolbar from DOM.
239
- * editor.ui.view.toolbar.element.remove();
240
- *
241
- * // Remove the editable from DOM.
242
- * editor.ui.view.editable.element.remove();
243
- *
244
- * console.log( 'Editor was destroyed' );
245
- * } );
246
- * ```
247
- */ async destroy() {
248
- // Cache the data, then destroy.
249
- // It's safe to assume that the model->view conversion will not work after super.destroy().
250
- const data = this.getData();
251
- this.ui.destroy();
252
- await super.destroy();
253
- if (this.sourceElement) {
254
- this.updateSourceElement(data);
255
- }
256
- // To satisfy the return type and to keep it backward compatible.
257
- // eslint-disable-next-line no-useless-return
258
- return;
259
- }
260
- static async create(sourceElementOrDataOrConfig, config = {}) {
261
- const editor = new this(sourceElementOrDataOrConfig, config);
262
- await editor.initPlugins();
263
- // Roots are created in the editor constructor (before plugins are loaded), but the schema is only fully
264
- // built after plugins register their items during init(). Custom root element names (e.g. registered by a
265
- // plugin) may not exist in the schema at construction time, so we defer this check until here.
266
- verifyRootElements(editor);
267
- await editor.ui.init();
268
- await editor.data.init(editor.config.get('roots').main.initialData);
269
- editor.fire('ready');
270
- return editor;
271
- }
272
- }
273
- function isElement(value) {
274
- return isElement$1(value);
165
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
166
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
167
+ */
168
+ /**
169
+ * @module editor-decoupled/decouplededitor
170
+ */
171
+ const DecoupledEditorBase = /* #__PURE__ */ ElementApiMixin(Editor);
172
+ /**
173
+ * The decoupled editor implementation. It provides an inline editable and a toolbar. However, unlike other editors,
174
+ * it does not render these components anywhere in the DOM unless configured.
175
+ *
176
+ * This type of an editor is dedicated to integrations which require a customized UI with an open
177
+ * structure, allowing developers to specify the exact location of the interface.
178
+ *
179
+ * See the document editor {@glink examples/builds/document-editor demo} to learn about possible use cases
180
+ * for the decoupled editor.
181
+ *
182
+ * In order to create a decoupled editor instance, use the static
183
+ * {@link module:editor-decoupled/decouplededitor~DecoupledEditor.create `DecoupledEditor.create()`} method.
184
+ *
185
+ * Note that you will need to attach the editor toolbar and menu bar to your web page manually, in a desired place,
186
+ * after the editor is initialized.
187
+ */
188
+ var DecoupledEditor = class extends DecoupledEditorBase {
189
+ /**
190
+ * @inheritDoc
191
+ */
192
+ static get editorName() {
193
+ return "DecoupledEditor";
194
+ }
195
+ /**
196
+ * @inheritDoc
197
+ */
198
+ ui;
199
+ constructor(sourceElementOrDataOrConfig, config = {}) {
200
+ const { sourceElementOrData, editorConfig } = normalizeSingleRootEditorConstructorParams(sourceElementOrDataOrConfig, config);
201
+ super(editorConfig);
202
+ normalizeRootsConfig(sourceElementOrData, this.config);
203
+ const editableElement = this.config.get("roots").main.element;
204
+ if (isElement$1(editableElement)) {
205
+ this.sourceElement = editableElement;
206
+ secureSourceElement(this, editableElement);
207
+ }
208
+ this.model.document.createRoot(this.config.get("roots").main.modelElement);
209
+ registerAndInitializeRootConfigAttributes(this);
210
+ const shouldToolbarGroupWhenFull = !this.config.get("toolbar.shouldNotGroupWhenFull");
211
+ const view = new DecoupledEditorUIView(this.locale, this.editing.view, {
212
+ editableElement,
213
+ shouldToolbarGroupWhenFull,
214
+ label: this.config.get("roots").main.label
215
+ });
216
+ this.ui = new DecoupledEditorUI(this, view);
217
+ }
218
+ /**
219
+ * Destroys the editor instance, releasing all resources used by it.
220
+ *
221
+ * Updates the original editor element with the data if the
222
+ * {@link module:core/editor/editorconfig~EditorConfig#updateSourceElementOnDestroy `updateSourceElementOnDestroy`}
223
+ * configuration option is set to `true`.
224
+ *
225
+ * **Note**: The decoupled editor does not remove the toolbar and editable when destroyed. You can
226
+ * do that yourself in the destruction chain:
227
+ *
228
+ * ```ts
229
+ * editor.destroy()
230
+ * .then( () => {
231
+ * // Remove the toolbar from DOM.
232
+ * editor.ui.view.toolbar.element.remove();
233
+ *
234
+ * // Remove the editable from DOM.
235
+ * editor.ui.view.editable.element.remove();
236
+ *
237
+ * console.log( 'Editor was destroyed' );
238
+ * } );
239
+ * ```
240
+ */
241
+ async destroy() {
242
+ const data = this.getData();
243
+ this.ui.destroy();
244
+ await super.destroy();
245
+ if (this.sourceElement) this.updateSourceElement(data);
246
+ }
247
+ static async create(sourceElementOrDataOrConfig, config = {}) {
248
+ const editor = new this(sourceElementOrDataOrConfig, config);
249
+ await editor.initPlugins();
250
+ verifyRootElements(editor);
251
+ await editor.ui.init();
252
+ await editor.data.init(editor.config.get("roots").main.initialData);
253
+ editor.fire("ready");
254
+ return editor;
255
+ }
256
+ };
257
+ function isElement$1(value) {
258
+ return isElement(value);
275
259
  }
276
260
 
261
+ /**
262
+ * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
263
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
264
+ */
265
+
277
266
  export { DecoupledEditor, DecoupledEditorUI, DecoupledEditorUIView };
278
- //# sourceMappingURL=index.js.map
267
+ //# sourceMappingURL=index.js.map