@progress/kendo-angular-editor 2.5.0 → 3.0.0-dev.202201191455

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 (104) hide show
  1. package/LICENSE.md +1 -1
  2. package/NOTICE.txt +119 -79
  3. package/README.md +1 -1
  4. package/dist/cdn/js/kendo-angular-editor.js +2 -2
  5. package/dist/cdn/main.js +1 -1
  6. package/dist/es/common/error-messages.js +4 -3
  7. package/dist/es/config/command-icons.js +1 -0
  8. package/dist/es/config/commands.js +18 -17
  9. package/dist/es/config/schema.js +2 -4
  10. package/dist/es/config/table-commands.js +1 -363
  11. package/dist/es/dialogs/colorpicker-dialog.component.js +1 -1
  12. package/dist/es/dialogs/file-link-dialog.component.js +1 -1
  13. package/dist/es/dialogs/image-dialog.component.js +1 -1
  14. package/dist/es/editor-toolbar-state.js +12 -2
  15. package/dist/es/editor.component.js +103 -75
  16. package/dist/es/editor.module.js +6 -3
  17. package/dist/es/index.js +2 -0
  18. package/dist/es/localization/messages.js +4 -0
  19. package/dist/es/main.js +1 -0
  20. package/dist/es/package-metadata.js +1 -1
  21. package/dist/{es2015/config/table-nodes.d.ts → es/preventable-events/paste-event-data.js} +0 -5
  22. package/dist/es/preventable-events/paste-event.js +25 -0
  23. package/dist/es/tools/blockquote/editor-blockquote-button.directive.js +48 -0
  24. package/dist/es/tools/colorpicker/editor-colorpicker.component.js +24 -7
  25. package/dist/es/tools/format/editor-format-dropdownlist.component.js +1 -1
  26. package/dist/es/tools/format/editor-format.component.js +0 -1
  27. package/dist/es/tools/tables/popup-table-grid.component.js +1 -1
  28. package/dist/es2015/common/commands.d.ts +1 -1
  29. package/dist/es2015/common/error-messages.js +4 -3
  30. package/dist/es2015/common/format-item.interface.d.ts +1 -1
  31. package/dist/es2015/common/paste-cleanup-settings.d.ts +14 -0
  32. package/dist/es2015/config/command-icons.js +1 -0
  33. package/dist/es2015/config/commands.js +18 -17
  34. package/dist/es2015/config/schema.d.ts +1 -1
  35. package/dist/es2015/config/schema.js +2 -3
  36. package/dist/es2015/config/table-commands.d.ts +0 -36
  37. package/dist/es2015/config/table-commands.js +1 -357
  38. package/dist/es2015/dialogs/colorpicker-dialog.component.js +1 -1
  39. package/dist/es2015/dialogs/file-link-dialog.component.js +4 -4
  40. package/dist/es2015/dialogs/image-dialog.component.js +4 -4
  41. package/dist/es2015/editor-toolbar-state.js +12 -2
  42. package/dist/es2015/editor.component.d.ts +16 -11
  43. package/dist/es2015/editor.component.js +105 -75
  44. package/dist/es2015/editor.module.js +6 -3
  45. package/dist/es2015/index.d.ts +2 -0
  46. package/dist/es2015/index.js +2 -0
  47. package/dist/es2015/index.metadata.json +1 -1
  48. package/dist/es2015/localization/messages.d.ts +4 -0
  49. package/dist/es2015/localization/messages.js +4 -0
  50. package/dist/es2015/main.d.ts +2 -0
  51. package/dist/es2015/main.js +1 -0
  52. package/dist/es2015/package-metadata.js +1 -1
  53. package/dist/es2015/preventable-events/paste-event-data.d.ts +21 -0
  54. package/dist/es2015/preventable-events/paste-event-data.js +4 -0
  55. package/dist/es2015/preventable-events/paste-event.d.ts +27 -0
  56. package/dist/es2015/preventable-events/paste-event.js +20 -0
  57. package/dist/es2015/tools/blockquote/editor-blockquote-button.directive.d.ts +30 -0
  58. package/dist/es2015/tools/blockquote/editor-blockquote-button.directive.js +45 -0
  59. package/dist/es2015/tools/colorpicker/editor-colorpicker.component.d.ts +8 -2
  60. package/dist/es2015/tools/colorpicker/editor-colorpicker.component.js +20 -7
  61. package/dist/es2015/tools/format/editor-format-dropdownlist.component.js +0 -4
  62. package/dist/es2015/tools/format/editor-format.component.js +0 -1
  63. package/dist/es2015/tools/tables/popup-table-grid.component.js +2 -2
  64. package/dist/fesm2015/index.js +354 -1624
  65. package/dist/fesm5/index.js +365 -1649
  66. package/dist/npm/common/error-messages.js +4 -2
  67. package/dist/npm/config/command-icons.js +1 -0
  68. package/dist/npm/config/commands.js +16 -14
  69. package/dist/npm/config/schema.js +2 -4
  70. package/dist/npm/config/table-commands.js +1 -368
  71. package/dist/npm/dialogs/colorpicker-dialog.component.js +1 -1
  72. package/dist/npm/dialogs/file-link-dialog.component.js +1 -1
  73. package/dist/npm/dialogs/image-dialog.component.js +1 -1
  74. package/dist/npm/editor-toolbar-state.js +11 -1
  75. package/dist/npm/editor.component.js +99 -71
  76. package/dist/npm/editor.module.js +7 -4
  77. package/dist/npm/index.js +5 -0
  78. package/dist/npm/localization/messages.js +4 -0
  79. package/dist/npm/main.js +2 -0
  80. package/dist/npm/package-metadata.js +1 -1
  81. package/dist/npm/preventable-events/paste-event-data.js +6 -0
  82. package/dist/npm/preventable-events/paste-event.js +27 -0
  83. package/dist/npm/tools/blockquote/editor-blockquote-button.directive.js +50 -0
  84. package/dist/npm/tools/colorpicker/editor-colorpicker.component.js +24 -7
  85. package/dist/npm/tools/format/editor-format-dropdownlist.component.js +1 -1
  86. package/dist/npm/tools/format/editor-format.component.js +0 -1
  87. package/dist/npm/tools/tables/popup-table-grid.component.js +1 -1
  88. package/dist/systemjs/kendo-angular-editor.js +1 -1
  89. package/package.json +18 -18
  90. package/dist/es/config/table-nodes.js +0 -146
  91. package/dist/es/config/tables/CellSelection.js +0 -268
  92. package/dist/es/config/tables/TableMap.js +0 -333
  93. package/dist/es/config/tables/table-utils.js +0 -302
  94. package/dist/es2015/config/table-nodes.js +0 -145
  95. package/dist/es2015/config/tables/CellSelection.d.ts +0 -35
  96. package/dist/es2015/config/tables/CellSelection.js +0 -256
  97. package/dist/es2015/config/tables/TableMap.d.ts +0 -35
  98. package/dist/es2015/config/tables/TableMap.js +0 -329
  99. package/dist/es2015/config/tables/table-utils.d.ts +0 -77
  100. package/dist/es2015/config/tables/table-utils.js +0 -299
  101. package/dist/npm/config/table-nodes.js +0 -157
  102. package/dist/npm/config/tables/CellSelection.js +0 -270
  103. package/dist/npm/config/tables/TableMap.js +0 -338
  104. package/dist/npm/config/tables/table-utils.js +0 -307
@@ -66,7 +66,7 @@ ColorPickerDialogComponent = tslib_1.__decorate([
66
66
  <div class="k-edit-form-container k-window-content" style="text-align: center;">
67
67
  <kendo-colorpicker
68
68
  #colorpicker
69
- [view]="view"
69
+ [views]="['palette']"
70
70
  [format]="'hex'"
71
71
  [attr.title]="title"
72
72
  [icon]="icon"
@@ -123,26 +123,26 @@ FileLinkDialogComponent = tslib_1.__decorate([
123
123
  <label (click)="hrefInput.focus()">{{ textForWithPrefix('WebAddress') }}</label>
124
124
  </div>
125
125
  <div class="k-edit-field">
126
- <input #hrefInput formControlName="href" type="text" class="k-textbox" />
126
+ <input #hrefInput formControlName="href" type="text" class="k-textbox k-input k-rounded-md" />
127
127
  </div>
128
128
 
129
129
  <div class="k-edit-label">
130
130
  <label (click)="textInput.focus()">{{ textForWithPrefix('Text') }}</label>
131
131
  </div>
132
132
  <div class="k-edit-field">
133
- <input #textInput formControlName="text" type="text" class="k-textbox" />
133
+ <input #textInput formControlName="text" type="text" class="k-textbox k-input k-rounded-md" />
134
134
  </div>
135
135
 
136
136
  <div class="k-edit-label">
137
137
  <label (click)="titleInput.focus()">{{ textForWithPrefix('Title') }}</label>
138
138
  </div>
139
139
  <div class="k-edit-field">
140
- <input #titleInput formControlName="title" type="text" class="k-textbox" />
140
+ <input #titleInput formControlName="title" type="text" class="k-textbox k-input k-rounded-md" />
141
141
  </div>
142
142
  <ng-container *ngIf="command === 'createLink'">
143
143
  <div class="k-edit-label"></div>
144
144
  <div class="k-edit-field">
145
- <input type="checkbox" id="k-target-blank" class="k-checkbox" formControlName="target" />
145
+ <input type="checkbox" id="k-target-blank" kendoCheckBox formControlName="target" />
146
146
  <label class="k-checkbox-label" for="k-target-blank">{{ textForWithPrefix('OpenInNewWindow') }}</label>
147
147
  </div>
148
148
  </ng-container>
@@ -101,25 +101,25 @@ ImageDialogComponent = tslib_1.__decorate([
101
101
  <label [for]="srcInputId">{{ textFor('imageWebAddress') }}</label>
102
102
  </div>
103
103
  <div class="k-edit-field">
104
- <input [id]="srcInputId" #srcInput [formControl]="src" type="text" class="k-textbox" />
104
+ <input [id]="srcInputId" #srcInput [formControl]="src" type="text" class="k-textbox k-input k-rounded-md" />
105
105
  </div>
106
106
  <div class="k-edit-label">
107
107
  <label [for]="altTextInputId">{{ textFor('imageAltText') }}</label>
108
108
  </div>
109
109
  <div class="k-edit-field">
110
- <input [id]="altTextInputId" [formControl]="alt" type="text" class="k-textbox" />
110
+ <input [id]="altTextInputId" [formControl]="alt" type="text" class="k-textbox k-input k-rounded-md" />
111
111
  </div>
112
112
  <div class="k-edit-label">
113
113
  <label [for]="widthInputId">{{ textFor('imageWidth') }}</label>
114
114
  </div>
115
115
  <div class="k-edit-field">
116
- <input [id]="widthInputId" [formControl]="width" type="text" class="k-textbox" />
116
+ <input [id]="widthInputId" [formControl]="width" type="text" class="k-textbox k-input k-rounded-md" />
117
117
  </div>
118
118
  <div class="k-edit-label">
119
119
  <label [for]="heightInputId">{{ textFor('imageHeight') }}</label>
120
120
  </div>
121
121
  <div class="k-edit-field">
122
- <input [id]="heightInputId" [formControl]="height" type="text" class="k-textbox" />
122
+ <input [id]="heightInputId" [formControl]="height" type="text" class="k-textbox k-input k-rounded-md" />
123
123
  </div>
124
124
  </div>
125
125
  </div>
@@ -2,7 +2,7 @@
2
2
  * Copyright © 2021 Progress Software Corporation. All rights reserved.
3
3
  * Licensed under commercial license. See LICENSE.md in the project root for more information
4
4
  *-------------------------------------------------------------------------------------------*/
5
- import { cleanFormatting } from '@progress/kendo-editor-common';
5
+ import { blockquote, cleanFormatting, isIndented } from '@progress/kendo-editor-common';
6
6
  import { alignRightRules, alignCenterRules, alignLeftRules, alignJustifyRules, isAligned, bold, italic, underline, strikethrough, subscript, superscript, link, activeNode, hasNode, getActiveMarks, hasMark, expandSelection, indentRules, outdentRules, canIndentAsListItem, canOutdentAsListItem, canBeIndented, undo, redo, addRowBefore, addRowAfter, addColumnBefore, addColumnAfter, deleteRow, deleteColumn, deleteTable, mergeCells, splitCell } from '@progress/kendo-editor-common';
7
7
  /**
8
8
  * @hidden
@@ -36,6 +36,10 @@ export const getToolbarState = (state, options) => ({
36
36
  selected: activeNode(state),
37
37
  disabled: false
38
38
  },
39
+ blockquote: {
40
+ selected: false,
41
+ disabled: !blockquote(state)
42
+ },
39
43
  indent: {
40
44
  selected: false,
41
45
  disabled: !(canIndentAsListItem(state, state.schema.nodes.list_item) || canBeIndented(state, indentRules))
@@ -58,7 +62,11 @@ export const getToolbarState = (state, options) => ({
58
62
  },
59
63
  outdent: {
60
64
  selected: false,
61
- disabled: !(canOutdentAsListItem(state, outdentRules) || canBeIndented(state, outdentRules))
65
+ get disabled() {
66
+ return !(hasNode(state, state.schema.nodes.blockquote) ||
67
+ canOutdentAsListItem(state, outdentRules) ||
68
+ isIndented(state, outdentRules.nodes));
69
+ }
62
70
  },
63
71
  redo: {
64
72
  selected: false,
@@ -184,6 +192,7 @@ export const initialToolBarState = {
184
192
  format: { selected: { text: 'Format', tag: null }, disabled: false },
185
193
  style: { selected: { marks: [], hasNodesWithoutMarks: false }, disabled: false },
186
194
  cleanFormatting: { selected: false, disabled: true },
195
+ blockquote: { selected: false, disabled: false },
187
196
  //indent
188
197
  indent: { selected: false, disabled: false },
189
198
  outdent: { selected: false, disabled: false },
@@ -236,6 +245,7 @@ export const disabledToolBarState = {
236
245
  format: { selected: { text: 'Format', tag: null }, disabled: true },
237
246
  style: { selected: { marks: [], hasNodesWithoutMarks: false }, disabled: true },
238
247
  cleanFormatting: { selected: false, disabled: true },
248
+ blockquote: { selected: false, disabled: true },
239
249
  //indent
240
250
  indent: { selected: false, disabled: true },
241
251
  outdent: { selected: false, disabled: true },
@@ -16,6 +16,7 @@ import { PluginsFn } from './common/plugins-function';
16
16
  import { ApplyToWordOptions } from './common/apply-to-word-options';
17
17
  import { EditorResizableOptions } from './common/resizable-options.interface';
18
18
  import { EditorToolsService } from './tools/tools.service';
19
+ import { EditorPasteEvent } from './preventable-events/paste-event';
19
20
  /**
20
21
  * Represents the [Kendo UI Editor component for Angular]({% slug overview_editor %}).
21
22
  */
@@ -70,14 +71,6 @@ export declare class EditorComponent implements AfterViewInit, ControlValueAcces
70
71
  * The hint, which is displayed when the component is empty.
71
72
  */
72
73
  placeholder: string;
73
- /**
74
- * By design, the Editor emits `valueChange`, updates the model and the ToolBar state on each keystroke.
75
- * When you are interested in ignoring the new values for a given amout of time and take only the most recent one, you can use the `updateInterval` property.
76
- * A possible use case is to get the new values and to update the ToolBar state at a maximum rate per second in order to speed up your application.
77
- * The specified interval (in milliseconds) should be a positive number.
78
- * By default the `updateInterval` is set to 100 miliseconds. If set to zero the delay will be disabled entirely.
79
- */
80
- updateInterval: number;
81
74
  /**
82
75
  * By default, whitespace is collapsed as per HTML's rules.
83
76
  * Set to `true` to preserve whitespace, but normalize newlines to spaces.
@@ -107,6 +100,11 @@ export declare class EditorComponent implements AfterViewInit, ControlValueAcces
107
100
  * Fires when the content area of the Editor is focused ([see example]({% slug overview_editor %}#toc-events)).
108
101
  */
109
102
  onFocus: EventEmitter<undefined>;
103
+ /**
104
+ * Fires when the user performs paste in the content area of the Editor ([see example]({% slug overview_editor %}#toc-events)).
105
+ * The event is preventable. If you cancel it, the Editor content will not change.
106
+ */
107
+ paste: EventEmitter<EditorPasteEvent>;
110
108
  /**
111
109
  * Fires when the content area of the Editor is blurred ([see example]({% slug overview_editor %}#toc-events)).
112
110
  */
@@ -159,13 +157,16 @@ export declare class EditorComponent implements AfterViewInit, ControlValueAcces
159
157
  private subs;
160
158
  private _view;
161
159
  private _value;
162
- private _previousValue;
163
160
  private _disabled;
164
161
  private _readonly;
165
162
  private _schema;
166
163
  private _plugins;
167
164
  private _placeholder;
168
165
  private _styleObserver;
166
+ private trOnChange;
167
+ private htmlOnChange;
168
+ private inForm;
169
+ private _pasteEvent;
169
170
  private afterViewInit;
170
171
  private contentAreaLoaded;
171
172
  constructor(dialogService: DialogService, localization: LocalizationService, cdr: ChangeDetectorRef, ngZone: NgZone, element: ElementRef, toolsService: EditorToolsService);
@@ -188,7 +189,7 @@ export declare class EditorComponent implements AfterViewInit, ControlValueAcces
188
189
  * @param {any} attr - Optional parameters for the command. Apart from the following list,
189
190
  * the parameters do not expect specific attributes when you call them:
190
191
  * - `format` - Accepts an object with the `tag` property.
191
- * The supported tags are `p`, `blockquote`, and any of the `h1` to `h6` heading tags.
192
+ * The supported tags are `p` and any of the `h1` to `h6` heading tags.
192
193
  * - `createLink` - Accepts an object with the `href`, `title`, and `target` properties. The `href` property is mandatory.
193
194
  * - `setHTML` - Accepts a `string` parameter.
194
195
  * - `insertTable` - Accepts an object with the `rows` and `cols` properties. The number values are zero based.
@@ -279,8 +280,12 @@ export declare class EditorComponent implements AfterViewInit, ControlValueAcces
279
280
  */
280
281
  isEmpty(): boolean;
281
282
  private initialize;
283
+ private dispatchTransaction;
284
+ private transformPastedHTML;
285
+ private changeValue;
286
+ private onChangeCallback;
282
287
  private normalizeSize;
283
288
  private normalizeProperties;
284
- private onChangeCallback;
285
289
  private onTouchedCallback;
290
+ private onPaste;
286
291
  }
@@ -6,12 +6,12 @@ import * as tslib_1 from "tslib";
6
6
  var EditorComponent_1;
7
7
  import { Component, HostBinding, ViewChild, ContentChild, ViewContainerRef, Output, ElementRef, EventEmitter, forwardRef, Input, ChangeDetectorRef, NgZone, isDevMode } from '@angular/core';
8
8
  import { NG_VALUE_ACCESSOR } from '@angular/forms';
9
- import { BehaviorSubject, fromEvent, merge, Subject, zip } from 'rxjs';
10
- import { map, filter, auditTime, take } from 'rxjs/operators';
9
+ import { BehaviorSubject, fromEvent, Subject, zip } from 'rxjs';
10
+ import { map, filter, take } from 'rxjs/operators';
11
11
  import { ToolBarComponent } from '@progress/kendo-angular-toolbar';
12
12
  import { DialogService } from '@progress/kendo-angular-dialog';
13
- import { isDocumentAvailable, KendoInput } from '@progress/kendo-angular-common';
14
- import { buildKeymap, buildListKeymap, hasSameMarkup, getHtml, pasteCleanup, sanitize, removeComments, sanitizeClassAttr, sanitizeStyleAttr, removeAttribute, placeholder, EditorView, EditorState, baseKeymap, keymap, history, parseContent, Plugin, PluginKey, TextSelection, Schema, gapCursor, getSelectionText, imageResizing } from '@progress/kendo-editor-common';
13
+ import { hasObservers, isDocumentAvailable, KendoInput } from '@progress/kendo-angular-common';
14
+ import { buildKeymap, buildListKeymap, getHtml, pasteCleanup, sanitize, removeComments, sanitizeClassAttr, sanitizeStyleAttr, removeAttribute, placeholder, EditorView, EditorState, baseKeymap, keymap, history, parseContent, Plugin, PluginKey, TextSelection, Schema, AllSelection, gapCursor, getSelectionText, imageResizing, tableEditing } from '@progress/kendo-editor-common';
15
15
  import { validatePackage } from '@progress/kendo-licensing';
16
16
  import { packageMetadata } from './package-metadata';
17
17
  import { schema } from './config/schema';
@@ -26,15 +26,16 @@ import { EditorLocalizationService } from './localization/editor-localization.se
26
26
  import { defaultStyle, tablesStyles, rtlStyles } from './common/styles';
27
27
  import { EditorErrorMessages } from './common/error-messages';
28
28
  import { EditorToolsService } from './tools/tools.service';
29
+ import { EditorPasteEvent } from './preventable-events/paste-event';
29
30
  const EMPTY_PARAGRAPH = '<p></p>';
30
31
  const defaultPasteCleanupSettings = {
31
32
  convertMsLists: false,
32
33
  removeAttributes: [],
33
34
  removeHtmlComments: false,
34
- removeInvalidHTML: false,
35
+ removeInvalidHTML: true,
35
36
  removeMsClasses: false,
36
37
  removeMsStyles: false,
37
- stripTags: ['']
38
+ stripTags: []
38
39
  };
39
40
  const removeCommentsIf = conditionallyExecute(removeComments);
40
41
  const removeInvalidHTMLIf = conditionallyExecute(sanitize);
@@ -71,14 +72,6 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
71
72
  * @default false
72
73
  */
73
74
  this.applyToWord = false;
74
- /**
75
- * By design, the Editor emits `valueChange`, updates the model and the ToolBar state on each keystroke.
76
- * When you are interested in ignoring the new values for a given amout of time and take only the most recent one, you can use the `updateInterval` property.
77
- * A possible use case is to get the new values and to update the ToolBar state at a maximum rate per second in order to speed up your application.
78
- * The specified interval (in milliseconds) should be a positive number.
79
- * By default the `updateInterval` is set to 100 miliseconds. If set to zero the delay will be disabled entirely.
80
- */
81
- this.updateInterval = 100;
82
75
  /**
83
76
  * By default, whitespace is collapsed as per HTML's rules.
84
77
  * Set to `true` to preserve whitespace, but normalize newlines to spaces.
@@ -104,6 +97,11 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
104
97
  * Fires when the content area of the Editor is focused ([see example]({% slug overview_editor %}#toc-events)).
105
98
  */
106
99
  this.onFocus = new EventEmitter();
100
+ /**
101
+ * Fires when the user performs paste in the content area of the Editor ([see example]({% slug overview_editor %}#toc-events)).
102
+ * The event is preventable. If you cancel it, the Editor content will not change.
103
+ */
104
+ this.paste = new EventEmitter();
107
105
  /**
108
106
  * Fires when the content area of the Editor is blurred ([see example]({% slug overview_editor %}#toc-events)).
109
107
  */
@@ -119,10 +117,76 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
119
117
  this.valueModified = new Subject();
120
118
  this._readonly = false;
121
119
  this._placeholder = '';
120
+ this.inForm = false;
122
121
  this.afterViewInit = new Subject();
123
122
  this.contentAreaLoaded = new Subject();
124
- this.onChangeCallback = (_) => { }; // tslint:disable-line:no-empty
123
+ this.dispatchTransaction = (tr) => {
124
+ const docChanged = tr.docChanged;
125
+ if (this.disabled || (this.readonly && docChanged)) {
126
+ return;
127
+ }
128
+ if (docChanged) {
129
+ const doc = tr.doc;
130
+ const html = getHtml({ doc });
131
+ this.trOnChange = tr;
132
+ this.htmlOnChange = html;
133
+ this.ngZone.run(() => {
134
+ this.valueModified.next(html);
135
+ });
136
+ }
137
+ if (!docChanged || this.inForm) {
138
+ this.view.updateState(this.view.state.apply(tr));
139
+ }
140
+ };
141
+ this.transformPastedHTML = (dirtyHtml) => {
142
+ const pasteCleanupSettings = Object.assign({}, defaultPasteCleanupSettings, this.pasteCleanupSettings);
143
+ const html = pipe(removeInvalidHTMLIf(pasteCleanupSettings.removeInvalidHTML), removeCommentsIf(pasteCleanupSettings.removeHtmlComments))(dirtyHtml);
144
+ const clean = pasteCleanup(html, {
145
+ convertMsLists: pasteCleanupSettings.convertMsLists,
146
+ stripTags: pasteCleanupSettings.stripTags.join('|'),
147
+ attributes: getPasteCleanupAttributes(pasteCleanupSettings)
148
+ });
149
+ if (hasObservers(this.paste)) {
150
+ const event = new EditorPasteEvent(clean, dirtyHtml, this._pasteEvent);
151
+ this.ngZone.run(() => this.paste.emit(event));
152
+ return event.isDefaultPrevented() ? '' : event.cleanedHtml;
153
+ }
154
+ return clean;
155
+ };
156
+ this.changeValue = (value) => {
157
+ const prev = this._value;
158
+ this._value = value;
159
+ if (!this._view) {
160
+ return;
161
+ }
162
+ if (this.htmlOnChange === value && this.trOnChange) {
163
+ this.view.updateState(this.view.state.apply(this.trOnChange));
164
+ }
165
+ else {
166
+ if ((prev || '') !== (value || '')) {
167
+ const iframeContentWindowNotPresent = this.iframe && !this.container.element.nativeElement.contentWindow;
168
+ if (iframeContentWindowNotPresent) {
169
+ return;
170
+ }
171
+ const state = this.view.state;
172
+ const nextDoc = parseContent(value || '', state.schema, { preserveWhitespace: this.preserveWhitespace });
173
+ const tr = state.tr
174
+ .setSelection(new AllSelection(state.doc))
175
+ .replaceSelectionWith(nextDoc);
176
+ this.view.updateState(state.apply(tr));
177
+ }
178
+ }
179
+ this.trOnChange = null;
180
+ this.htmlOnChange = null;
181
+ };
182
+ this.onChangeCallback = (value) => {
183
+ this.changeValue(value);
184
+ };
125
185
  this.onTouchedCallback = (_) => { }; // tslint:disable-line:no-empty
186
+ this.onPaste = (_view, nativeEvent) => {
187
+ this._pasteEvent = nativeEvent;
188
+ return false;
189
+ };
126
190
  validatePackage(packageMetadata);
127
191
  this.direction = localization.rtl ? 'rtl' : 'ltr';
128
192
  // https://stackoverflow.com/questions/56572483/chrome-is-synchronously-handling-iframe-loading-whereas-firefox-handles-it-asyn
@@ -132,25 +196,12 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
132
196
  * Sets the value of the Editor ([see example]({% slug overview_editor %}#toc-basic-usage)).
133
197
  */
134
198
  set value(value) {
135
- if (this._previousValue === value) {
136
- return;
137
- }
138
- this._value = value;
139
- this._previousValue = value;
140
- if (this._view) {
141
- const iframeContentWindowNotPresent = this.iframe && !this.container.element.nativeElement.contentWindow;
142
- if (iframeContentWindowNotPresent) {
143
- return;
144
- }
145
- this.exec('setHTML', {
146
- content: this._value || '',
147
- parseOptions: {
148
- preserveWhitespace: this.preserveWhitespace
149
- }
150
- });
151
- }
199
+ this.changeValue(value);
152
200
  }
153
201
  get value() {
202
+ if (this.trOnChange) {
203
+ return this.htmlOnChange;
204
+ }
154
205
  let value = this._view ? this.getSource() : this._value;
155
206
  if (value === EMPTY_PARAGRAPH) {
156
207
  return this._value ? '' : this._value;
@@ -340,6 +391,9 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
340
391
  }
341
392
  }
342
393
  ngOnChanges(changes) {
394
+ if (changes.value && this.view) {
395
+ this.changeValue(changes.value.currentValue);
396
+ }
343
397
  if (changes.iframe && !changes.iframe.isFirstChange()) {
344
398
  this.ngZone.onStable.pipe(take(1)).subscribe(() => this.initialize());
345
399
  }
@@ -367,7 +421,7 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
367
421
  * @param {any} attr - Optional parameters for the command. Apart from the following list,
368
422
  * the parameters do not expect specific attributes when you call them:
369
423
  * - `format` - Accepts an object with the `tag` property.
370
- * The supported tags are `p`, `blockquote`, and any of the `h1` to `h6` heading tags.
424
+ * The supported tags are `p` and any of the `h1` to `h6` heading tags.
371
425
  * - `createLink` - Accepts an object with the `href`, `title`, and `target` properties. The `href` property is mandatory.
372
426
  * - `setHTML` - Accepts a `string` parameter.
373
427
  * - `insertTable` - Accepts an object with the `rows` and `cols` properties. The number values are zero based.
@@ -425,8 +479,6 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
425
479
  const command = editorCommands[commandName](attr);
426
480
  // Executes a ProseMirror command.
427
481
  command(this._view.state, this._view.dispatch, this._view);
428
- // See the `dispatchTransaction` comments.
429
- // this.stateChange.emit(updateToolBar(this.view));
430
482
  }
431
483
  /**
432
484
  * Opens a dialog.
@@ -511,6 +563,7 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
511
563
  * @hidden
512
564
  */
513
565
  writeValue(value) {
566
+ this.inForm = true;
514
567
  // To avoid confusion, non-existent values are always undefined.
515
568
  this.value = value === null ? undefined : value;
516
569
  }
@@ -538,7 +591,6 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
538
591
  return;
539
592
  }
540
593
  const currentSchema = this.schema || schema;
541
- const that = this;
542
594
  const containerNativeElement = this.container.element.nativeElement;
543
595
  const contentNode = parseContent((this.value || '').trim(), currentSchema, { preserveWhitespace: this.preserveWhitespace });
544
596
  if (this.iframe) {
@@ -580,16 +632,13 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
580
632
  }
581
633
  })
582
634
  }),
583
- new Plugin({
584
- key: new PluginKey('editor-filter-disabled-state'),
585
- filterTransaction: () => !this.disabled
586
- }),
587
635
  history(),
588
636
  keymap(buildListKeymap(currentSchema)),
589
637
  keymap(buildKeymap(currentSchema, { applyToWord: this.applyToWord })),
590
638
  keymap(baseKeymap),
591
639
  gapCursor(),
592
- imageResizing()
640
+ imageResizing(),
641
+ tableEditing()
593
642
  ];
594
643
  if (this.placeholder) {
595
644
  defaultPlugins.push(placeholder(this.placeholder));
@@ -609,31 +658,10 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
609
658
  this._view = new EditorView({ mount: this.viewMountElement }, {
610
659
  state,
611
660
  editable: () => !this.readonly,
612
- dispatchTransaction: function (tr) {
613
- // `this` is bound to the view instance.
614
- this.updateState(this.state.apply(tr));
615
- // that.cdr.detectChanges();
616
- // When the user utilizes keyboard shortcuts&mdash;for example, `Ctrl`+`b`&mdash;
617
- // `tr.docChanged` is `true` and the toolbar is not updated.
618
- // A possible future solution is to move the keymaps to the service.
619
- // if (!tr.docChanged) {
620
- // that.stateChange.emit(updateToolBar(that.view));
621
- // }
622
- const value = that.value;
623
- if (!hasSameMarkup(value, that._previousValue, this.state.schema)) {
624
- that._previousValue = value;
625
- that.ngZone.run(() => that.valueModified.next(value));
626
- }
627
- },
628
- transformPastedHTML: (html) => {
629
- const pasteCleanupSettings = Object.assign({}, defaultPasteCleanupSettings, this.pasteCleanupSettings);
630
- const clean = pipe(removeCommentsIf(pasteCleanupSettings.removeHtmlComments), removeInvalidHTMLIf(pasteCleanupSettings.removeInvalidHTML))(html);
631
- const attributes = getPasteCleanupAttributes(pasteCleanupSettings);
632
- return pasteCleanup(clean, {
633
- convertMsLists: pasteCleanupSettings.convertMsLists,
634
- stripTags: pasteCleanupSettings.stripTags.join('|'),
635
- attributes
636
- });
661
+ dispatchTransaction: this.dispatchTransaction,
662
+ transformPastedHTML: this.transformPastedHTML,
663
+ handleDOMEvents: {
664
+ paste: this.onPaste
637
665
  }
638
666
  });
639
667
  });
@@ -649,7 +677,7 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
649
677
  this.subs.add(fromEvent(containerElement, 'focusin')
650
678
  .subscribe(() => {
651
679
  if (this.readonly) {
652
- contentAreaClasslist.add('k-state-focused');
680
+ contentAreaClasslist.add('k-focus');
653
681
  }
654
682
  if (!this.focusChangedProgrammatically || this.shouldEmitFocus) {
655
683
  this.ngZone.run(() => this.onFocus.emit());
@@ -659,7 +687,7 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
659
687
  this.subs.add(fromEvent(containerElement, 'focusout')
660
688
  .subscribe(() => {
661
689
  if (this.readonly) {
662
- contentAreaClasslist.remove('k-state-focused');
690
+ contentAreaClasslist.remove('k-focus');
663
691
  }
664
692
  if (!this.focusChangedProgrammatically) {
665
693
  this.ngZone.run(() => this.onBlur.emit());
@@ -674,7 +702,7 @@ let EditorComponent = EditorComponent_1 = class EditorComponent {
674
702
  this.cdr.detectChanges();
675
703
  }
676
704
  }));
677
- this.subs.add(merge(this.valueModified.pipe(filter(() => this.updateInterval > 0), auditTime(this.updateInterval)), this.valueModified.pipe(filter(() => this.updateInterval === 0))).subscribe((value) => {
705
+ this.subs.add(this.valueModified.subscribe((value) => {
678
706
  this.onChangeCallback(value);
679
707
  this.valueChange.emit(value);
680
708
  this.cdr.markForCheck();
@@ -767,10 +795,6 @@ tslib_1.__decorate([
767
795
  tslib_1.__metadata("design:type", String),
768
796
  tslib_1.__metadata("design:paramtypes", [String])
769
797
  ], EditorComponent.prototype, "placeholder", null);
770
- tslib_1.__decorate([
771
- Input(),
772
- tslib_1.__metadata("design:type", Number)
773
- ], EditorComponent.prototype, "updateInterval", void 0);
774
798
  tslib_1.__decorate([
775
799
  Input(),
776
800
  tslib_1.__metadata("design:type", Object)
@@ -791,6 +815,10 @@ tslib_1.__decorate([
791
815
  Output('focus'),
792
816
  tslib_1.__metadata("design:type", EventEmitter)
793
817
  ], EditorComponent.prototype, "onFocus", void 0);
818
+ tslib_1.__decorate([
819
+ Output(),
820
+ tslib_1.__metadata("design:type", EventEmitter)
821
+ ], EditorComponent.prototype, "paste", void 0);
794
822
  tslib_1.__decorate([
795
823
  Output('blur'),
796
824
  tslib_1.__metadata("design:type", EventEmitter)
@@ -805,7 +833,7 @@ tslib_1.__decorate([
805
833
  tslib_1.__metadata("design:paramtypes", [])
806
834
  ], EditorComponent.prototype, "resizableClass", null);
807
835
  tslib_1.__decorate([
808
- HostBinding('class.k-state-disabled'),
836
+ HostBinding('class.k-disabled'),
809
837
  tslib_1.__metadata("design:type", Boolean),
810
838
  tslib_1.__metadata("design:paramtypes", [])
811
839
  ], EditorComponent.prototype, "isDisabled", null);
@@ -911,6 +939,8 @@ EditorComponent = EditorComponent_1 = tslib_1.__decorate([
911
939
  alignRight="Align text right"
912
940
  i18n-backColor="kendo.editor.backColor|The title of the tool that changes the text background color."
913
941
  backColor="Background color"
942
+ i18n-blockquote="kendo.editor.blockquote|The title of the tool that wraps an element in a blockquote"
943
+ blockquote="Quotation"
914
944
  i18n-bold="kendo.editor.bold|The title of the tool that makes text bold."
915
945
  bold="Bold"
916
946
  i18n-cleanFormatting="kendo.editor.cleanFormatting|The title of the Clean Formatting tool."
@@ -1038,7 +1068,7 @@ EditorComponent = EditorComponent_1 = tslib_1.__decorate([
1038
1068
  <div *ngIf="!iframe" #content [attr.dir]="direction" class="k-editor-content"></div>
1039
1069
 
1040
1070
  <div class="k-editor-content" *ngIf="iframe">
1041
- <iframe #content frameborder="0" class="k-iframe" (load)="iframeOnLoad()"></iframe>
1071
+ <iframe #content srcdoc="<!DOCTYPE html>" frameborder="0" class="k-iframe" (load)="iframeOnLoad()"></iframe>
1042
1072
  </div>
1043
1073
 
1044
1074
  <ng-container #dialogsContainer></ng-container>
@@ -10,8 +10,7 @@ import { ToolBarModule } from '@progress/kendo-angular-toolbar';
10
10
  import { DropDownsModule } from '@progress/kendo-angular-dropdowns';
11
11
  import { DialogModule } from '@progress/kendo-angular-dialog';
12
12
  import { ButtonModule } from '@progress/kendo-angular-buttons';
13
- import { ColorPickerModule } from '@progress/kendo-angular-inputs';
14
- import { NumericTextBoxModule, TextBoxModule } from '@progress/kendo-angular-inputs';
13
+ import { NumericTextBoxModule, TextBoxModule, ColorPickerModule, CheckBoxModule } from '@progress/kendo-angular-inputs';
15
14
  import { EditorComponent } from './editor.component';
16
15
  import { ImageDialogComponent } from './dialogs/image-dialog.component';
17
16
  import { SourceDialogComponent } from './dialogs/source-dialog.component';
@@ -30,6 +29,7 @@ import { EditorAlignLeftButtonDirective } from './tools/alignment/editor-align-l
30
29
  import { EditorAlignCenterButtonDirective } from './tools/alignment/editor-align-center-button.directive';
31
30
  import { EditorAlignRightButtonDirective } from './tools/alignment/editor-align-right-button.directive';
32
31
  import { EditorAlignJustifyButtonDirective } from './tools/alignment/editor-align-justify-button.directive';
32
+ import { EditorBlockquoteDirective } from './tools/blockquote/editor-blockquote-button.directive';
33
33
  import { EditorRedoButtonDirective } from './tools/history/editor-redo-button.directive';
34
34
  import { EditorUndoButtonDirective } from './tools/history/editor-undo-button.directive';
35
35
  import { EditorInsertImageButtonDirective } from './tools/image/editor-insert-image-button.directive';
@@ -123,7 +123,9 @@ const COMPONENT_DIRECTIVES = [
123
123
  // print
124
124
  EditorPrintDirective,
125
125
  // select all
126
- EditorSelectAllButtonDirective
126
+ EditorSelectAllButtonDirective,
127
+ // blockquote
128
+ EditorBlockquoteDirective
127
129
  ];
128
130
  const TOOLBAR_TOOLS = [
129
131
  EditorFontSizeComponent,
@@ -227,6 +229,7 @@ EditorModule = tslib_1.__decorate([
227
229
  DialogModule,
228
230
  DropDownsModule,
229
231
  NumericTextBoxModule,
232
+ CheckBoxModule,
230
233
  ToolBarModule,
231
234
  TextBoxModule
232
235
  ]
@@ -7,6 +7,7 @@
7
7
  */
8
8
  export * from './main';
9
9
  export { DialogCommand, EditorCommand } from './common/commands';
10
+ export { semanticNodes, semanticTagNames } from './config/semantic-nodes';
10
11
  export { ColorPickerDialogComponent } from './dialogs/colorpicker-dialog.component';
11
12
  export { FileLinkDialogComponent } from './dialogs/file-link-dialog.component';
12
13
  export { FontFamilyDialogComponent } from './dialogs/font-family-dialog.component';
@@ -23,6 +24,7 @@ export { EditorAlignCenterButtonDirective } from './tools/alignment/editor-align
23
24
  export { EditorAlignJustifyButtonDirective } from './tools/alignment/editor-align-justify-button.directive';
24
25
  export { EditorAlignLeftButtonDirective } from './tools/alignment/editor-align-left-button.directive';
25
26
  export { EditorAlignRightButtonDirective } from './tools/alignment/editor-align-right-button.directive';
27
+ export { EditorBlockquoteDirective } from './tools/blockquote/editor-blockquote-button.directive';
26
28
  export { EditorBackColorDirective } from './tools/colorpicker/editor-back-color.directive';
27
29
  export { EditorColorPickerComponent } from './tools/colorpicker/editor-colorpicker.component';
28
30
  export { EditorForeColorDirective } from './tools/colorpicker/editor-fore-color.directive';
@@ -6,6 +6,7 @@
6
6
  * Generated bundle index. Do not edit.
7
7
  */
8
8
  export * from './main';
9
+ export { semanticNodes, semanticTagNames } from './config/semantic-nodes';
9
10
  export { ColorPickerDialogComponent } from './dialogs/colorpicker-dialog.component';
10
11
  export { FileLinkDialogComponent } from './dialogs/file-link-dialog.component';
11
12
  export { FontFamilyDialogComponent } from './dialogs/font-family-dialog.component';
@@ -22,6 +23,7 @@ export { EditorAlignCenterButtonDirective } from './tools/alignment/editor-align
22
23
  export { EditorAlignJustifyButtonDirective } from './tools/alignment/editor-align-justify-button.directive';
23
24
  export { EditorAlignLeftButtonDirective } from './tools/alignment/editor-align-left-button.directive';
24
25
  export { EditorAlignRightButtonDirective } from './tools/alignment/editor-align-right-button.directive';
26
+ export { EditorBlockquoteDirective } from './tools/blockquote/editor-blockquote-button.directive';
25
27
  export { EditorBackColorDirective } from './tools/colorpicker/editor-back-color.directive';
26
28
  export { EditorColorPickerComponent } from './tools/colorpicker/editor-colorpicker.component';
27
29
  export { EditorForeColorDirective } from './tools/colorpicker/editor-fore-color.directive';