@ckeditor/ckeditor5-undo 41.3.1 → 41.4.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.
Files changed (138) hide show
  1. package/dist/index-content.css +4 -0
  2. package/dist/index-editor.css +4 -0
  3. package/dist/index.css +4 -0
  4. package/dist/index.js +410 -0
  5. package/dist/index.js.map +1 -0
  6. package/dist/translations/ar.d.ts +8 -0
  7. package/dist/translations/ar.js +5 -0
  8. package/dist/translations/ast.d.ts +8 -0
  9. package/dist/translations/ast.js +5 -0
  10. package/dist/translations/az.d.ts +8 -0
  11. package/dist/translations/az.js +5 -0
  12. package/dist/translations/bg.d.ts +8 -0
  13. package/dist/translations/bg.js +5 -0
  14. package/dist/translations/bn.d.ts +8 -0
  15. package/dist/translations/bn.js +5 -0
  16. package/dist/translations/ca.d.ts +8 -0
  17. package/dist/translations/ca.js +5 -0
  18. package/dist/translations/cs.d.ts +8 -0
  19. package/dist/translations/cs.js +5 -0
  20. package/dist/translations/da.d.ts +8 -0
  21. package/dist/translations/da.js +5 -0
  22. package/dist/translations/de-ch.d.ts +8 -0
  23. package/dist/translations/de-ch.js +5 -0
  24. package/dist/translations/de.d.ts +8 -0
  25. package/dist/translations/de.js +5 -0
  26. package/dist/translations/el.d.ts +8 -0
  27. package/dist/translations/el.js +5 -0
  28. package/dist/translations/en-au.d.ts +8 -0
  29. package/dist/translations/en-au.js +5 -0
  30. package/dist/translations/en-gb.d.ts +8 -0
  31. package/dist/translations/en-gb.js +5 -0
  32. package/dist/translations/en.d.ts +8 -0
  33. package/dist/translations/en.js +5 -0
  34. package/dist/translations/eo.d.ts +8 -0
  35. package/dist/translations/eo.js +5 -0
  36. package/dist/translations/es.d.ts +8 -0
  37. package/dist/translations/es.js +5 -0
  38. package/dist/translations/et.d.ts +8 -0
  39. package/dist/translations/et.js +5 -0
  40. package/dist/translations/eu.d.ts +8 -0
  41. package/dist/translations/eu.js +5 -0
  42. package/dist/translations/fa.d.ts +8 -0
  43. package/dist/translations/fa.js +5 -0
  44. package/dist/translations/fi.d.ts +8 -0
  45. package/dist/translations/fi.js +5 -0
  46. package/dist/translations/fr.d.ts +8 -0
  47. package/dist/translations/fr.js +5 -0
  48. package/dist/translations/gl.d.ts +8 -0
  49. package/dist/translations/gl.js +5 -0
  50. package/dist/translations/he.d.ts +8 -0
  51. package/dist/translations/he.js +5 -0
  52. package/dist/translations/hi.d.ts +8 -0
  53. package/dist/translations/hi.js +5 -0
  54. package/dist/translations/hr.d.ts +8 -0
  55. package/dist/translations/hr.js +5 -0
  56. package/dist/translations/hu.d.ts +8 -0
  57. package/dist/translations/hu.js +5 -0
  58. package/dist/translations/id.d.ts +8 -0
  59. package/dist/translations/id.js +5 -0
  60. package/dist/translations/it.d.ts +8 -0
  61. package/dist/translations/it.js +5 -0
  62. package/dist/translations/ja.d.ts +8 -0
  63. package/dist/translations/ja.js +5 -0
  64. package/dist/translations/km.d.ts +8 -0
  65. package/dist/translations/km.js +5 -0
  66. package/dist/translations/kn.d.ts +8 -0
  67. package/dist/translations/kn.js +5 -0
  68. package/dist/translations/ko.d.ts +8 -0
  69. package/dist/translations/ko.js +5 -0
  70. package/dist/translations/ku.d.ts +8 -0
  71. package/dist/translations/ku.js +5 -0
  72. package/dist/translations/lt.d.ts +8 -0
  73. package/dist/translations/lt.js +5 -0
  74. package/dist/translations/lv.d.ts +8 -0
  75. package/dist/translations/lv.js +5 -0
  76. package/dist/translations/ms.d.ts +8 -0
  77. package/dist/translations/ms.js +5 -0
  78. package/dist/translations/nb.d.ts +8 -0
  79. package/dist/translations/nb.js +5 -0
  80. package/dist/translations/ne.d.ts +8 -0
  81. package/dist/translations/ne.js +5 -0
  82. package/dist/translations/nl.d.ts +8 -0
  83. package/dist/translations/nl.js +5 -0
  84. package/dist/translations/no.d.ts +8 -0
  85. package/dist/translations/no.js +5 -0
  86. package/dist/translations/pl.d.ts +8 -0
  87. package/dist/translations/pl.js +5 -0
  88. package/dist/translations/pt-br.d.ts +8 -0
  89. package/dist/translations/pt-br.js +5 -0
  90. package/dist/translations/pt.d.ts +8 -0
  91. package/dist/translations/pt.js +5 -0
  92. package/dist/translations/ro.d.ts +8 -0
  93. package/dist/translations/ro.js +5 -0
  94. package/dist/translations/ru.d.ts +8 -0
  95. package/dist/translations/ru.js +5 -0
  96. package/dist/translations/si.d.ts +8 -0
  97. package/dist/translations/si.js +5 -0
  98. package/dist/translations/sk.d.ts +8 -0
  99. package/dist/translations/sk.js +5 -0
  100. package/dist/translations/sq.d.ts +8 -0
  101. package/dist/translations/sq.js +5 -0
  102. package/dist/translations/sr-latn.d.ts +8 -0
  103. package/dist/translations/sr-latn.js +5 -0
  104. package/dist/translations/sr.d.ts +8 -0
  105. package/dist/translations/sr.js +5 -0
  106. package/dist/translations/sv.d.ts +8 -0
  107. package/dist/translations/sv.js +5 -0
  108. package/dist/translations/th.d.ts +8 -0
  109. package/dist/translations/th.js +5 -0
  110. package/dist/translations/tk.d.ts +8 -0
  111. package/dist/translations/tk.js +5 -0
  112. package/dist/translations/tr.d.ts +8 -0
  113. package/dist/translations/tr.js +5 -0
  114. package/dist/translations/tt.d.ts +8 -0
  115. package/dist/translations/tt.js +5 -0
  116. package/dist/translations/ug.d.ts +8 -0
  117. package/dist/translations/ug.js +5 -0
  118. package/dist/translations/uk.d.ts +8 -0
  119. package/dist/translations/uk.js +5 -0
  120. package/dist/translations/ur.d.ts +8 -0
  121. package/dist/translations/ur.js +5 -0
  122. package/dist/translations/uz.d.ts +8 -0
  123. package/dist/translations/uz.js +5 -0
  124. package/dist/translations/vi.d.ts +8 -0
  125. package/dist/translations/vi.js +5 -0
  126. package/dist/translations/zh-cn.d.ts +8 -0
  127. package/dist/translations/zh-cn.js +5 -0
  128. package/dist/translations/zh.d.ts +8 -0
  129. package/dist/translations/zh.js +5 -0
  130. package/dist/types/augmentation.d.ts +20 -0
  131. package/dist/types/basecommand.d.ts +76 -0
  132. package/dist/types/index.d.ts +17 -0
  133. package/dist/types/redocommand.d.ts +31 -0
  134. package/dist/types/undo.d.ts +121 -0
  135. package/dist/types/undocommand.d.ts +41 -0
  136. package/dist/types/undoediting.d.ts +41 -0
  137. package/dist/types/undoui.d.ts +38 -0
  138. package/package.json +5 -4
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
package/dist/index.css ADDED
@@ -0,0 +1,4 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
package/dist/index.js ADDED
@@ -0,0 +1,410 @@
1
+ /**
2
+ * @license Copyright (c) 2003-2024, CKSource Holding sp. z o.o. All rights reserved.
3
+ * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license
4
+ */
5
+ import { Command, Plugin, icons } from '@ckeditor/ckeditor5-core/dist/index.js';
6
+ import { transformSets, NoOperation } from '@ckeditor/ckeditor5-engine/dist/index.js';
7
+ import { ButtonView, MenuBarMenuListItemButtonView } from '@ckeditor/ckeditor5-ui/dist/index.js';
8
+
9
+ class BaseCommand extends Command {
10
+ /**
11
+ * @inheritDoc
12
+ */ refresh() {
13
+ this.isEnabled = this._stack.length > 0;
14
+ }
15
+ /**
16
+ * Returns all batches created by this command.
17
+ */ get createdBatches() {
18
+ return this._createdBatches;
19
+ }
20
+ /**
21
+ * Stores a batch in the command, together with the selection state of the {@link module:engine/model/document~Document document}
22
+ * created by the editor which this command is registered to.
23
+ *
24
+ * @param batch The batch to add.
25
+ */ addBatch(batch) {
26
+ const docSelection = this.editor.model.document.selection;
27
+ const selection = {
28
+ ranges: docSelection.hasOwnRange ? Array.from(docSelection.getRanges()) : [],
29
+ isBackward: docSelection.isBackward
30
+ };
31
+ this._stack.push({
32
+ batch,
33
+ selection
34
+ });
35
+ this.refresh();
36
+ }
37
+ /**
38
+ * Removes all items from the stack.
39
+ */ clearStack() {
40
+ this._stack = [];
41
+ this.refresh();
42
+ }
43
+ /**
44
+ * Restores the {@link module:engine/model/document~Document#selection document selection} state after a batch was undone.
45
+ *
46
+ * @param ranges Ranges to be restored.
47
+ * @param isBackward A flag describing whether the restored range was selected forward or backward.
48
+ * @param operations Operations which has been applied since selection has been stored.
49
+ */ _restoreSelection(ranges, isBackward, operations) {
50
+ const model = this.editor.model;
51
+ const document = model.document;
52
+ // This will keep the transformed selection ranges.
53
+ const selectionRanges = [];
54
+ // Transform all ranges from the restored selection.
55
+ const transformedRangeGroups = ranges.map((range)=>range.getTransformedByOperations(operations));
56
+ const allRanges = transformedRangeGroups.flat();
57
+ for (const rangeGroup of transformedRangeGroups){
58
+ // While transforming there could appear ranges that are contained by other ranges, we shall ignore them.
59
+ const transformed = rangeGroup.filter((range)=>range.root != document.graveyard).filter((range)=>!isRangeContainedByAnyOtherRange(range, allRanges));
60
+ // All the transformed ranges ended up in graveyard.
61
+ if (!transformed.length) {
62
+ continue;
63
+ }
64
+ // After the range got transformed, we have an array of ranges. Some of those
65
+ // ranges may be "touching" -- they can be next to each other and could be merged.
66
+ normalizeRanges(transformed);
67
+ // For each `range` from `ranges`, we take only one transformed range.
68
+ // This is because we want to prevent situation where single-range selection
69
+ // got transformed to multi-range selection.
70
+ selectionRanges.push(transformed[0]);
71
+ }
72
+ // @if CK_DEBUG_ENGINE // console.log( `Restored selection by undo: ${ selectionRanges.join( ', ' ) }` );
73
+ // `selectionRanges` may be empty if all ranges ended up in graveyard. If that is the case, do not restore selection.
74
+ if (selectionRanges.length) {
75
+ model.change((writer)=>{
76
+ writer.setSelection(selectionRanges, {
77
+ backward: isBackward
78
+ });
79
+ });
80
+ }
81
+ }
82
+ /**
83
+ * Undoes a batch by reversing that batch, transforming reversed batch and finally applying it.
84
+ * This is a helper method for {@link #execute}.
85
+ *
86
+ * @param batchToUndo The batch to be undone.
87
+ * @param undoingBatch The batch that will contain undoing changes.
88
+ */ _undo(batchToUndo, undoingBatch) {
89
+ const model = this.editor.model;
90
+ const document = model.document;
91
+ // All changes done by the command execution will be saved as one batch.
92
+ this._createdBatches.add(undoingBatch);
93
+ const operationsToUndo = batchToUndo.operations.slice().filter((operation)=>operation.isDocumentOperation);
94
+ operationsToUndo.reverse();
95
+ // We will process each operation from `batchToUndo`, in reverse order. If there were operations A, B and C in undone batch,
96
+ // we need to revert them in reverse order, so first C' (reversed C), then B', then A'.
97
+ for (const operationToUndo of operationsToUndo){
98
+ const nextBaseVersion = operationToUndo.baseVersion + 1;
99
+ const historyOperations = Array.from(document.history.getOperations(nextBaseVersion));
100
+ const transformedSets = transformSets([
101
+ operationToUndo.getReversed()
102
+ ], historyOperations, {
103
+ useRelations: true,
104
+ document: this.editor.model.document,
105
+ padWithNoOps: false,
106
+ forceWeakRemove: true
107
+ });
108
+ const reversedOperations = transformedSets.operationsA;
109
+ // After reversed operation has been transformed by all history operations, apply it.
110
+ for (let operation of reversedOperations){
111
+ // Do not apply any operation on non-editable space.
112
+ const affectedSelectable = operation.affectedSelectable;
113
+ if (affectedSelectable && !model.canEditAt(affectedSelectable)) {
114
+ operation = new NoOperation(operation.baseVersion);
115
+ }
116
+ // Before applying, add the operation to the `undoingBatch`.
117
+ undoingBatch.addOperation(operation);
118
+ model.applyOperation(operation);
119
+ document.history.setOperationAsUndone(operationToUndo, operation);
120
+ }
121
+ }
122
+ }
123
+ /**
124
+ * @inheritDoc
125
+ */ constructor(editor){
126
+ super(editor);
127
+ /**
128
+ * Stack of items stored by the command. These are pairs of:
129
+ *
130
+ * * {@link module:engine/model/batch~Batch batch} saved by the command,
131
+ * * {@link module:engine/model/selection~Selection selection} state at the moment of saving the batch.
132
+ */ this._stack = [];
133
+ /**
134
+ * Stores all batches that were created by this command.
135
+ *
136
+ * @internal
137
+ */ this._createdBatches = new WeakSet();
138
+ // Refresh state, so the command is inactive right after initialization.
139
+ this.refresh();
140
+ // This command should not depend on selection change.
141
+ this._isEnabledBasedOnSelection = false;
142
+ // Set the transparent batch for the `editor.data.set()` call if the
143
+ // batch type is not set already.
144
+ this.listenTo(editor.data, 'set', (evt, data)=>{
145
+ // Create a shallow copy of the options to not change the original args.
146
+ // And make sure that an object is assigned to data[ 1 ].
147
+ data[1] = {
148
+ ...data[1]
149
+ };
150
+ const options = data[1];
151
+ // If batch type is not set, default to non-undoable batch.
152
+ if (!options.batchType) {
153
+ options.batchType = {
154
+ isUndoable: false
155
+ };
156
+ }
157
+ }, {
158
+ priority: 'high'
159
+ });
160
+ // Clear the stack for the `transparent` batches.
161
+ this.listenTo(editor.data, 'set', (evt, data)=>{
162
+ // We can assume that the object exists and it has a `batchType` property.
163
+ // It was ensured with a higher priority listener before.
164
+ const options = data[1];
165
+ if (!options.batchType.isUndoable) {
166
+ this.clearStack();
167
+ }
168
+ });
169
+ }
170
+ }
171
+ /**
172
+ * Normalizes list of ranges by joining intersecting or "touching" ranges.
173
+ *
174
+ * @param ranges Ranges to be normalized.
175
+ */ function normalizeRanges(ranges) {
176
+ ranges.sort((a, b)=>a.start.isBefore(b.start) ? -1 : 1);
177
+ for(let i = 1; i < ranges.length; i++){
178
+ const previousRange = ranges[i - 1];
179
+ const joinedRange = previousRange.getJoined(ranges[i], true);
180
+ if (joinedRange) {
181
+ // Replace the ranges on the list with the new joined range.
182
+ i--;
183
+ ranges.splice(i, 2, joinedRange);
184
+ }
185
+ }
186
+ }
187
+ function isRangeContainedByAnyOtherRange(range, ranges) {
188
+ return ranges.some((otherRange)=>otherRange !== range && otherRange.containsRange(range, true));
189
+ }
190
+
191
+ class UndoCommand extends BaseCommand {
192
+ /**
193
+ * Executes the command. This method reverts a {@link module:engine/model/batch~Batch batch} added to the command's stack, transforms
194
+ * and applies the reverted version on the {@link module:engine/model/document~Document document} and removes the batch from the stack.
195
+ * Then, it restores the {@link module:engine/model/document~Document#selection document selection}.
196
+ *
197
+ * @fires execute
198
+ * @fires revert
199
+ * @param batch A batch that should be undone. If not set, the last added batch will be undone.
200
+ */ execute(batch = null) {
201
+ // If batch is not given, set `batchIndex` to the last index in command stack.
202
+ const batchIndex = batch ? this._stack.findIndex((a)=>a.batch == batch) : this._stack.length - 1;
203
+ const item = this._stack.splice(batchIndex, 1)[0];
204
+ const undoingBatch = this.editor.model.createBatch({
205
+ isUndo: true
206
+ });
207
+ // All changes have to be done in one `enqueueChange` callback so other listeners will not
208
+ // step between consecutive operations, or won't do changes to the document before selection is properly restored.
209
+ this.editor.model.enqueueChange(undoingBatch, ()=>{
210
+ this._undo(item.batch, undoingBatch);
211
+ const operations = this.editor.model.document.history.getOperations(item.batch.baseVersion);
212
+ this._restoreSelection(item.selection.ranges, item.selection.isBackward, operations);
213
+ });
214
+ // Firing `revert` event after the change block to make sure that it includes all changes from post-fixers
215
+ // and make sure that the selection is "stabilized" (the selection range is saved after undo is executed and then
216
+ // restored on redo, so it is important that the selection range is saved after post-fixers are done).
217
+ this.fire('revert', item.batch, undoingBatch);
218
+ this.refresh();
219
+ }
220
+ }
221
+
222
+ class RedoCommand extends BaseCommand {
223
+ /**
224
+ * Executes the command. This method reverts the last {@link module:engine/model/batch~Batch batch} added to
225
+ * the command's stack, applies the reverted and transformed version on the
226
+ * {@link module:engine/model/document~Document document} and removes the batch from the stack.
227
+ * Then, it restores the {@link module:engine/model/document~Document#selection document selection}.
228
+ *
229
+ * @fires execute
230
+ */ execute() {
231
+ const item = this._stack.pop();
232
+ const redoingBatch = this.editor.model.createBatch({
233
+ isUndo: true
234
+ });
235
+ // All changes have to be done in one `enqueueChange` callback so other listeners will not step between consecutive
236
+ // operations, or won't do changes to the document before selection is properly restored.
237
+ this.editor.model.enqueueChange(redoingBatch, ()=>{
238
+ const lastOperation = item.batch.operations[item.batch.operations.length - 1];
239
+ const nextBaseVersion = lastOperation.baseVersion + 1;
240
+ const operations = this.editor.model.document.history.getOperations(nextBaseVersion);
241
+ this._restoreSelection(item.selection.ranges, item.selection.isBackward, operations);
242
+ this._undo(item.batch, redoingBatch);
243
+ });
244
+ this.refresh();
245
+ }
246
+ }
247
+
248
+ class UndoEditing extends Plugin {
249
+ /**
250
+ * @inheritDoc
251
+ */ static get pluginName() {
252
+ return 'UndoEditing';
253
+ }
254
+ /**
255
+ * @inheritDoc
256
+ */ init() {
257
+ const editor = this.editor;
258
+ const t = editor.t;
259
+ // Create commands.
260
+ this._undoCommand = new UndoCommand(editor);
261
+ this._redoCommand = new RedoCommand(editor);
262
+ // Register command to the editor.
263
+ editor.commands.add('undo', this._undoCommand);
264
+ editor.commands.add('redo', this._redoCommand);
265
+ this.listenTo(editor.model, 'applyOperation', (evt, args)=>{
266
+ const operation = args[0];
267
+ // Do not register batch if the operation is not a document operation.
268
+ // This prevents from creating empty undo steps, where all operations where non-document operations.
269
+ // Non-document operations creates and alters content in detached tree fragments (for example, document fragments).
270
+ // Most of time this is preparing data before it is inserted into actual tree (for example during copy & paste).
271
+ // Such operations should not be reversed.
272
+ if (!operation.isDocumentOperation) {
273
+ return;
274
+ }
275
+ const batch = operation.batch;
276
+ const isRedoBatch = this._redoCommand.createdBatches.has(batch);
277
+ const isUndoBatch = this._undoCommand.createdBatches.has(batch);
278
+ const wasProcessed = this._batchRegistry.has(batch);
279
+ // Skip the batch if it was already processed.
280
+ if (wasProcessed) {
281
+ return;
282
+ }
283
+ // Add the batch to the registry so it will not be processed again.
284
+ this._batchRegistry.add(batch);
285
+ if (!batch.isUndoable) {
286
+ return;
287
+ }
288
+ if (isRedoBatch) {
289
+ // If this batch comes from `redoCommand`, add it to the `undoCommand` stack.
290
+ this._undoCommand.addBatch(batch);
291
+ } else if (!isUndoBatch) {
292
+ // If the batch comes neither from `redoCommand` nor from `undoCommand` then it is a new, regular batch.
293
+ // Add the batch to the `undoCommand` stack and clear the `redoCommand` stack.
294
+ this._undoCommand.addBatch(batch);
295
+ this._redoCommand.clearStack();
296
+ }
297
+ }, {
298
+ priority: 'highest'
299
+ });
300
+ this.listenTo(this._undoCommand, 'revert', (evt, undoneBatch, undoingBatch)=>{
301
+ this._redoCommand.addBatch(undoingBatch);
302
+ });
303
+ editor.keystrokes.set('CTRL+Z', 'undo');
304
+ editor.keystrokes.set('CTRL+Y', 'redo');
305
+ editor.keystrokes.set('CTRL+SHIFT+Z', 'redo');
306
+ // Add the information about the keystrokes to the accessibility database.
307
+ editor.accessibility.addKeystrokeInfos({
308
+ keystrokes: [
309
+ {
310
+ label: t('Undo'),
311
+ keystroke: 'CTRL+Z'
312
+ },
313
+ {
314
+ label: t('Redo'),
315
+ keystroke: [
316
+ [
317
+ 'CTRL+Y'
318
+ ],
319
+ [
320
+ 'CTRL+SHIFT+Z'
321
+ ]
322
+ ]
323
+ }
324
+ ]
325
+ });
326
+ }
327
+ constructor(){
328
+ super(...arguments);
329
+ /**
330
+ * Keeps track of which batches were registered in undo.
331
+ */ this._batchRegistry = new WeakSet();
332
+ }
333
+ }
334
+
335
+ class UndoUI extends Plugin {
336
+ /**
337
+ * @inheritDoc
338
+ */ static get pluginName() {
339
+ return 'UndoUI';
340
+ }
341
+ /**
342
+ * @inheritDoc
343
+ */ init() {
344
+ const editor = this.editor;
345
+ const locale = editor.locale;
346
+ const t = editor.t;
347
+ const localizedUndoIcon = locale.uiLanguageDirection == 'ltr' ? icons.undo : icons.redo;
348
+ const localizedRedoIcon = locale.uiLanguageDirection == 'ltr' ? icons.redo : icons.undo;
349
+ this._addButtonsToFactory('undo', t('Undo'), 'CTRL+Z', localizedUndoIcon);
350
+ this._addButtonsToFactory('redo', t('Redo'), 'CTRL+Y', localizedRedoIcon);
351
+ }
352
+ /**
353
+ * Creates a button for the specified command.
354
+ *
355
+ * @param name Command name.
356
+ * @param label Button label.
357
+ * @param keystroke Command keystroke.
358
+ * @param Icon Source of the icon.
359
+ */ _addButtonsToFactory(name, label, keystroke, Icon) {
360
+ const editor = this.editor;
361
+ editor.ui.componentFactory.add(name, ()=>{
362
+ const buttonView = this._createButton(ButtonView, name, label, keystroke, Icon);
363
+ buttonView.set({
364
+ tooltip: true
365
+ });
366
+ return buttonView;
367
+ });
368
+ editor.ui.componentFactory.add('menuBar:' + name, ()=>{
369
+ return this._createButton(MenuBarMenuListItemButtonView, name, label, keystroke, Icon);
370
+ });
371
+ }
372
+ /**
373
+ * TODO
374
+ */ _createButton(ButtonClass, name, label, keystroke, Icon) {
375
+ const editor = this.editor;
376
+ const locale = editor.locale;
377
+ const command = editor.commands.get(name);
378
+ const view = new ButtonClass(locale);
379
+ view.set({
380
+ label,
381
+ icon: Icon,
382
+ keystroke
383
+ });
384
+ view.bind('isEnabled').to(command, 'isEnabled');
385
+ this.listenTo(view, 'execute', ()=>{
386
+ editor.execute(name);
387
+ editor.editing.view.focus();
388
+ });
389
+ return view;
390
+ }
391
+ }
392
+
393
+ class Undo extends Plugin {
394
+ /**
395
+ * @inheritDoc
396
+ */ static get requires() {
397
+ return [
398
+ UndoEditing,
399
+ UndoUI
400
+ ];
401
+ }
402
+ /**
403
+ * @inheritDoc
404
+ */ static get pluginName() {
405
+ return 'Undo';
406
+ }
407
+ }
408
+
409
+ export { Undo, UndoEditing, UndoUI };
410
+ //# sourceMappingURL=index.js.map