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