jodit 4.12.21 → 4.12.23
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/CHANGELOG.md +46 -0
- package/es2015/jodit.css +1 -1
- package/es2015/jodit.fat.min.js +11 -11
- package/es2015/jodit.js +362 -101
- package/es2015/jodit.min.js +11 -11
- package/es2015/plugins/debug/debug.css +1 -1
- package/es2015/plugins/debug/debug.js +1 -1
- package/es2015/plugins/debug/debug.min.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2015/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2018/jodit.fat.min.js +11 -11
- package/es2018/jodit.min.js +25 -25
- package/es2018/plugins/debug/debug.min.js +1 -1
- package/es2018/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021/jodit.css +1 -1
- package/es2021/jodit.fat.min.js +13 -13
- package/es2021/jodit.js +352 -99
- package/es2021/jodit.min.js +23 -23
- package/es2021/plugins/debug/debug.css +1 -1
- package/es2021/plugins/debug/debug.js +1 -1
- package/es2021/plugins/debug/debug.min.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es2021.en/jodit.css +1 -1
- package/es2021.en/jodit.fat.min.js +14 -14
- package/es2021.en/jodit.js +330 -77
- package/es2021.en/jodit.min.js +14 -14
- package/es2021.en/plugins/debug/debug.css +1 -1
- package/es2021.en/plugins/debug/debug.js +1 -1
- package/es2021.en/plugins/debug/debug.min.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es2021.en/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/jodit.css +2 -2
- package/es5/jodit.fat.min.js +2 -2
- package/es5/jodit.js +415 -136
- package/es5/jodit.min.css +2 -2
- package/es5/jodit.min.js +2 -2
- package/es5/plugins/debug/debug.css +1 -1
- package/es5/plugins/debug/debug.js +1 -1
- package/es5/plugins/debug/debug.min.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.css +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.js +1 -1
- package/es5/plugins/speech-recognize/speech-recognize.min.js +1 -1
- package/es5/polyfills.fat.min.js +1 -1
- package/es5/polyfills.js +1 -1
- package/es5/polyfills.min.js +1 -1
- package/esm/core/component/view-component.js +8 -0
- package/esm/core/constants.js +1 -1
- package/esm/core/dom/dom.js +6 -4
- package/esm/core/helpers/checker/is-html-from-word.d.ts +1 -1
- package/esm/core/helpers/checker/is-html-from-word.js +12 -1
- package/esm/core/selection/style/api/wrap.js +18 -3
- package/esm/core/ui/popup/popup.js +4 -1
- package/esm/jodit.js +12 -0
- package/esm/langs/tr.js +1 -1
- package/esm/modules/dialog/dialog.d.ts +5 -0
- package/esm/modules/dialog/dialog.js +25 -2
- package/esm/modules/toolbar/button/content.d.ts +6 -0
- package/esm/modules/toolbar/button/content.js +26 -1
- package/esm/plugins/add-new-line/add-new-line.js +4 -1
- package/esm/plugins/ai-assistant/ai-assistant.js +7 -1
- package/esm/plugins/backspace/cases/check-join-neighbors.js +15 -1
- package/esm/plugins/clean-html/clean-html.js +8 -2
- package/esm/plugins/clean-html/helpers/visitor/filters/allow-attributes.js +9 -2
- package/esm/plugins/clipboard/clipboard.js +29 -1
- package/esm/plugins/color/color.js +21 -21
- package/esm/plugins/inline-popup/inline-popup.d.ts +15 -0
- package/esm/plugins/inline-popup/inline-popup.js +60 -3
- package/esm/plugins/limit/limit.js +7 -1
- package/esm/plugins/paste/config.js +11 -2
- package/esm/plugins/paste/paste.d.ts +1 -1
- package/esm/plugins/paste/paste.js +7 -5
- package/esm/plugins/resize-handler/resize-handler.js +13 -2
- package/esm/plugins/resizer/resizer.js +5 -1
- package/esm/plugins/search/ui/search.js +22 -12
- package/esm/plugins/select-cells/select-cells.js +10 -6
- package/esm/plugins/source/source.js +9 -0
- package/package.json +1 -1
- package/types/core/helpers/checker/is-html-from-word.d.ts +1 -1
- package/types/modules/dialog/dialog.d.ts +5 -0
- package/types/modules/toolbar/button/content.d.ts +6 -0
- package/types/plugins/inline-popup/inline-popup.d.ts +15 -0
- package/types/plugins/paste/paste.d.ts +1 -1
|
@@ -29,6 +29,12 @@ export class inlinePopup extends Plugin {
|
|
|
29
29
|
constructor() {
|
|
30
30
|
super(...arguments);
|
|
31
31
|
this.type = null;
|
|
32
|
+
/**
|
|
33
|
+
* The user pressed a button inside the selection toolbar — after the
|
|
34
|
+
* command fires `closeAllPopups`, the toolbar should be shown again
|
|
35
|
+
* while the selection is still there. See #1238
|
|
36
|
+
*/
|
|
37
|
+
this.__reopenSelectionPopup = false;
|
|
32
38
|
this.snapRange = null;
|
|
33
39
|
this.elmsList = keys(this.j.o.popup, false).filter(s => !this.isExcludedTarget(s));
|
|
34
40
|
}
|
|
@@ -144,9 +150,52 @@ export class inlinePopup extends Plugin {
|
|
|
144
150
|
this.previousTarget = undefined;
|
|
145
151
|
}
|
|
146
152
|
})
|
|
147
|
-
.on([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd)
|
|
153
|
+
.on([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd)
|
|
154
|
+
.on([this.j.ew, this.j.ow], 'mousedown touchstart', this.__onDocumentMouseDown)
|
|
155
|
+
.on('closeAllPopups', this.__onCloseAllPopups);
|
|
148
156
|
this.addListenersForElements();
|
|
149
157
|
}
|
|
158
|
+
__onDocumentMouseDown(e) {
|
|
159
|
+
if (this.popup.isOpened &&
|
|
160
|
+
this.type === 'selection' &&
|
|
161
|
+
e.target &&
|
|
162
|
+
UIElement.closestElement(e.target, Popup)) {
|
|
163
|
+
this.__reopenSelectionPopup = true;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
__onCloseAllPopups() {
|
|
167
|
+
if (!this.__reopenSelectionPopup) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
this.__reopenSelectionPopup = false;
|
|
171
|
+
if (!this.j.o.toolbarInlineForSelection) {
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// a zero timeout would run synchronously — before the popup's own
|
|
175
|
+
// `closeAllPopups` handler closes it; defer to the next macrotask
|
|
176
|
+
this.j.async.setTimeout(() => {
|
|
177
|
+
const sel = this.j.s.sel;
|
|
178
|
+
if (sel && !sel.isCollapsed) {
|
|
179
|
+
this.showPopup(() => this.__selectionBound(), 'selection');
|
|
180
|
+
}
|
|
181
|
+
}, 1);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* The selection rect comes from the editor document — in iframe mode its
|
|
185
|
+
* coordinates are iframe-local, while the popup lives in the host
|
|
186
|
+
* document, so the iframe offset must be added. See
|
|
187
|
+
* https://github.com/xdan/jodit/issues/1058
|
|
188
|
+
*/
|
|
189
|
+
__selectionBound() {
|
|
190
|
+
const rect = this.j.s.range.getBoundingClientRect();
|
|
191
|
+
let { left, top } = rect;
|
|
192
|
+
if (this.j.iframe) {
|
|
193
|
+
const offset = position(this.j.iframe, this.j, true);
|
|
194
|
+
left += offset.left;
|
|
195
|
+
top += offset.top;
|
|
196
|
+
}
|
|
197
|
+
return { left, top, width: rect.width, height: rect.height };
|
|
198
|
+
}
|
|
150
199
|
onSelectionStart() {
|
|
151
200
|
this.snapRange = this.j.s.range.cloneRange();
|
|
152
201
|
}
|
|
@@ -186,7 +235,7 @@ export class inlinePopup extends Plugin {
|
|
|
186
235
|
if (!node) {
|
|
187
236
|
return;
|
|
188
237
|
}
|
|
189
|
-
this.showPopup(() =>
|
|
238
|
+
this.showPopup(() => this.__selectionBound(), type);
|
|
190
239
|
}
|
|
191
240
|
/**
|
|
192
241
|
* In not collapsed selection - only one image
|
|
@@ -208,7 +257,9 @@ export class inlinePopup extends Plugin {
|
|
|
208
257
|
beforeDestruct(jodit) {
|
|
209
258
|
jodit.e
|
|
210
259
|
.off('showPopup')
|
|
211
|
-
.off([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd)
|
|
260
|
+
.off([this.j.ew, this.j.ow], 'mouseup keyup', this.onSelectionEnd)
|
|
261
|
+
.off([this.j.ew, this.j.ow], 'mousedown touchstart', this.__onDocumentMouseDown)
|
|
262
|
+
.off('closeAllPopups', this.__onCloseAllPopups);
|
|
212
263
|
this.removeListenersForElements();
|
|
213
264
|
}
|
|
214
265
|
_eventsList() {
|
|
@@ -257,6 +308,12 @@ __decorate([
|
|
|
257
308
|
__decorate([
|
|
258
309
|
watch(':outsideClick')
|
|
259
310
|
], inlinePopup.prototype, "onOutsideClick", null);
|
|
311
|
+
__decorate([
|
|
312
|
+
autobind
|
|
313
|
+
], inlinePopup.prototype, "__onDocumentMouseDown", null);
|
|
314
|
+
__decorate([
|
|
315
|
+
autobind
|
|
316
|
+
], inlinePopup.prototype, "__onCloseAllPopups", null);
|
|
260
317
|
__decorate([
|
|
261
318
|
autobind
|
|
262
319
|
], inlinePopup.prototype, "onSelectionStart", null);
|
|
@@ -62,7 +62,13 @@ export class limit extends Plugin {
|
|
|
62
62
|
jodit.e.fire('denyWords.limit limit.limit');
|
|
63
63
|
return true;
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
// with `countTextSpaces` enabled the limiter counts characters the
|
|
66
|
+
// same way as the `stat` plugin's counter — including spaces. See #1144
|
|
67
|
+
const charsCount = jodit.o.countTextSpaces
|
|
68
|
+
? text.replace(INVISIBLE_SPACE_REG_EXP(), '').replace(/[\r\n]/g, '')
|
|
69
|
+
.length
|
|
70
|
+
: words.join('').length;
|
|
71
|
+
const should = Boolean(limitChars && isGt(charsCount, limitChars, strict));
|
|
66
72
|
if (should) {
|
|
67
73
|
jodit.e.fire('denyChars.limit limit.limit');
|
|
68
74
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Released under MIT see LICENSE.txt in the project root for license information.
|
|
4
4
|
* Copyright (c) 2013-2026 Valerii Chupurnov. All rights reserved. https://xdsoft.net
|
|
5
5
|
*/
|
|
6
|
-
import { CLIPBOARD_ID, INSERT_AS_HTML, INSERT_AS_TEXT, INSERT_ONLY_TEXT, IS_PROD, TEXT_PLAIN } from "../../core/constants.js";
|
|
6
|
+
import { CLIPBOARD_ID, INSERT_AS_HTML, INSERT_AS_TEXT, INSERT_ONLY_TEXT, IS_PROD, TEXT_HTML, TEXT_PLAIN } from "../../core/constants.js";
|
|
7
7
|
import { Config } from "../../config.js";
|
|
8
8
|
import { pasteInsertHtml } from "./helpers.js";
|
|
9
9
|
Config.prototype.askBeforePasteHTML = true;
|
|
@@ -21,6 +21,7 @@ const psKey = 'pasteStorage';
|
|
|
21
21
|
Config.prototype.controls.paste = {
|
|
22
22
|
tooltip: 'Paste from clipboard',
|
|
23
23
|
async exec(editor, _, { control }) {
|
|
24
|
+
var _a;
|
|
24
25
|
if (control.name === psKey) {
|
|
25
26
|
editor.execCommand('showPasteStorage');
|
|
26
27
|
return;
|
|
@@ -31,7 +32,15 @@ Config.prototype.controls.paste = {
|
|
|
31
32
|
try {
|
|
32
33
|
const items = await navigator.clipboard.read();
|
|
33
34
|
if (items && items.length) {
|
|
34
|
-
const
|
|
35
|
+
const item = items[0];
|
|
36
|
+
// Prefer the HTML flavor so the button behaves like the
|
|
37
|
+
// Ctrl+V shortcut (which receives text/html from the
|
|
38
|
+
// native paste event). See
|
|
39
|
+
// https://github.com/xdan/jodit/issues/1061
|
|
40
|
+
const type = ((_a = item.types) === null || _a === void 0 ? void 0 : _a.includes(TEXT_HTML))
|
|
41
|
+
? TEXT_HTML
|
|
42
|
+
: TEXT_PLAIN;
|
|
43
|
+
const textBlob = await item.getType(type);
|
|
35
44
|
text = await new Response(textBlob).text();
|
|
36
45
|
}
|
|
37
46
|
error = false;
|
|
@@ -38,9 +38,7 @@ export class paste extends Plugin {
|
|
|
38
38
|
jodit.e
|
|
39
39
|
.on('paste.paste', this.onPaste)
|
|
40
40
|
.on('pasteStack.paste', (item) => this.pasteStack.push(item));
|
|
41
|
-
|
|
42
|
-
this.j.e.on('processPaste.paste', this.onProcessPasteReplaceNl2Br);
|
|
43
|
-
}
|
|
41
|
+
this.j.e.on('processPaste.paste', this.onProcessPasteReplaceNl2Br);
|
|
44
42
|
}
|
|
45
43
|
/** @override **/
|
|
46
44
|
beforeDestruct(jodit) {
|
|
@@ -169,11 +167,15 @@ export class paste extends Plugin {
|
|
|
169
167
|
pasteInsertHtml(e, this.j, html);
|
|
170
168
|
}
|
|
171
169
|
/**
|
|
172
|
-
*
|
|
170
|
+
* Escape plain text and replace all \\n chars with br
|
|
173
171
|
*/
|
|
174
172
|
onProcessPasteReplaceNl2Br(ignore, text, type) {
|
|
175
173
|
if (type === TEXT_PLAIN + ';' && !isHTML(text)) {
|
|
176
|
-
|
|
174
|
+
// the clipboard contains only plain text — escape special chars
|
|
175
|
+
// so a stray `<` is not parsed as an unclosed tag and does not
|
|
176
|
+
// swallow the rest of the string. See #1227
|
|
177
|
+
const escaped = htmlspecialchars(text);
|
|
178
|
+
return this.j.o.nl2brInPlainText ? nl2br(escaped) : escaped;
|
|
177
179
|
}
|
|
178
180
|
}
|
|
179
181
|
}
|
|
@@ -16,6 +16,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
16
16
|
import { autobind } from "../../core/decorators/index.js";
|
|
17
17
|
import { Dom } from "../../core/dom/index.js";
|
|
18
18
|
import { pluginSystem } from "../../core/global.js";
|
|
19
|
+
import { offset } from "../../core/helpers/index.js";
|
|
19
20
|
import { Plugin } from "../../core/plugin/index.js";
|
|
20
21
|
import { Icon } from "../../core/ui/index.js";
|
|
21
22
|
import "./config.js";
|
|
@@ -82,11 +83,21 @@ export class resizeHandler extends Plugin {
|
|
|
82
83
|
if (!this.isResized) {
|
|
83
84
|
return;
|
|
84
85
|
}
|
|
86
|
+
let { clientX, clientY } = e;
|
|
87
|
+
if (e.view === this.j.ew && this.j.ew !== this.j.ow) {
|
|
88
|
+
// the event was proxied from the editor's iframe — its client
|
|
89
|
+
// coordinates are relative to the iframe viewport, while the
|
|
90
|
+
// start point was captured on the host-document handle;
|
|
91
|
+
// shift them into the host coordinate space
|
|
92
|
+
const workplacePosition = offset(this.j.workplace, this.j, this.j.od, true);
|
|
93
|
+
clientX += workplacePosition.left;
|
|
94
|
+
clientY += workplacePosition.top;
|
|
95
|
+
}
|
|
85
96
|
if (this.j.o.allowResizeY) {
|
|
86
|
-
this.j.e.fire('setHeight', this.start.h +
|
|
97
|
+
this.j.e.fire('setHeight', this.start.h + clientY - this.start.y);
|
|
87
98
|
}
|
|
88
99
|
if (this.j.o.allowResizeX) {
|
|
89
|
-
this.j.e.fire('setWidth', this.start.w +
|
|
100
|
+
this.j.e.fire('setWidth', this.start.w + clientX - this.start.x);
|
|
90
101
|
}
|
|
91
102
|
this.j.e.fire('resize');
|
|
92
103
|
}
|
|
@@ -202,7 +202,11 @@ export class resizer extends Plugin {
|
|
|
202
202
|
this.pointerX = e.clientX;
|
|
203
203
|
this.pointerY = e.clientY;
|
|
204
204
|
let diff_x, diff_y;
|
|
205
|
-
if (this.j.options.iframe) {
|
|
205
|
+
if (this.j.options.iframe && e.view === this.j.ew) {
|
|
206
|
+
// the event was proxied from the editor's iframe — its client
|
|
207
|
+
// coordinates are relative to the iframe viewport, while
|
|
208
|
+
// `startX/startY` were captured on a host-document handle;
|
|
209
|
+
// shift them into the host coordinate space
|
|
206
210
|
const workplacePosition = this.getWorkplacePosition();
|
|
207
211
|
diff_x = e.clientX + workplacePosition.left - this.startX;
|
|
208
212
|
diff_y = e.clientY + workplacePosition.top - this.startY;
|
|
@@ -101,20 +101,30 @@ let UISearch = class UISearch extends UIElement {
|
|
|
101
101
|
.on(this.queryInput, 'input', () => {
|
|
102
102
|
this.setMod('empty-query', !trim(this.queryInput.value).length);
|
|
103
103
|
})
|
|
104
|
-
.on(this.queryInput, 'keydown',
|
|
105
|
-
|
|
106
|
-
|
|
104
|
+
.on(this.queryInput, 'keydown', (() => {
|
|
105
|
+
const debounced = this.j.async.debounce(async (e) => {
|
|
106
|
+
switch (e.key) {
|
|
107
|
+
case consts.KEY_ENTER:
|
|
108
|
+
if (await jodit.e.fire('searchNext')) {
|
|
109
|
+
this.close();
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
default:
|
|
113
|
+
jodit.e.fire(this, 'needUpdateCounters');
|
|
114
|
+
break;
|
|
115
|
+
}
|
|
116
|
+
}, this.j.defaultTimeout);
|
|
117
|
+
return (e) => {
|
|
118
|
+
// Must be canceled synchronously — inside the debounced
|
|
119
|
+
// handler the browser has already submitted the parent
|
|
120
|
+
// form. See https://github.com/xdan/jodit/issues/918
|
|
121
|
+
if (e.key === consts.KEY_ENTER) {
|
|
107
122
|
e.preventDefault();
|
|
108
123
|
e.stopImmediatePropagation();
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
default:
|
|
114
|
-
jodit.e.fire(this, 'needUpdateCounters');
|
|
115
|
-
break;
|
|
116
|
-
}
|
|
117
|
-
}, this.j.defaultTimeout));
|
|
124
|
+
}
|
|
125
|
+
debounced(e);
|
|
126
|
+
};
|
|
127
|
+
})());
|
|
118
128
|
}
|
|
119
129
|
onEditorKeyDown(e) {
|
|
120
130
|
if (!this.isOpened) {
|
|
@@ -120,14 +120,16 @@ export class selectCells extends Plugin {
|
|
|
120
120
|
* Mouse move inside the table
|
|
121
121
|
*/
|
|
122
122
|
__onMove(table, e) {
|
|
123
|
-
var _a;
|
|
123
|
+
var _a, _b;
|
|
124
124
|
if (this.j.o.readonly && !this.j.isLocked) {
|
|
125
125
|
return;
|
|
126
126
|
}
|
|
127
127
|
if (this.j.isLockedNotBy(key)) {
|
|
128
128
|
return;
|
|
129
129
|
}
|
|
130
|
-
|
|
130
|
+
// Inside Shadow DOM `document.elementFromPoint` returns the shadow
|
|
131
|
+
// host, so the lookup must start from the shadow root
|
|
132
|
+
const node = ((_a = this.j.o.shadowRoot) !== null && _a !== void 0 ? _a : this.j.ed).elementFromPoint(e.clientX, e.clientY);
|
|
131
133
|
if (!node) {
|
|
132
134
|
return;
|
|
133
135
|
}
|
|
@@ -150,7 +152,7 @@ export class selectCells extends Plugin {
|
|
|
150
152
|
}
|
|
151
153
|
const cellsCount = this.__tableModule.getAllSelectedCells().length;
|
|
152
154
|
if (cellsCount > 1) {
|
|
153
|
-
(
|
|
155
|
+
(_b = this.j.s.sel) === null || _b === void 0 ? void 0 : _b.removeAllRanges();
|
|
154
156
|
}
|
|
155
157
|
this.j.e.fire('hidePopup');
|
|
156
158
|
e.stopPropagation();
|
|
@@ -184,13 +186,15 @@ export class selectCells extends Plugin {
|
|
|
184
186
|
* Stop a selection process
|
|
185
187
|
*/
|
|
186
188
|
__onStopSelection(table, e) {
|
|
187
|
-
var _a, _b;
|
|
189
|
+
var _a, _b, _c;
|
|
188
190
|
if (!this.__selectedCell) {
|
|
189
191
|
return;
|
|
190
192
|
}
|
|
191
193
|
this.__isSelectionMode = false;
|
|
192
194
|
this.j.unlock();
|
|
193
|
-
|
|
195
|
+
// Inside Shadow DOM `document.elementFromPoint` returns the shadow
|
|
196
|
+
// host, so the lookup must start from the shadow root
|
|
197
|
+
const node = ((_a = this.j.o.shadowRoot) !== null && _a !== void 0 ? _a : this.j.ed).elementFromPoint(e.clientX, e.clientY);
|
|
194
198
|
if (!node) {
|
|
195
199
|
return;
|
|
196
200
|
}
|
|
@@ -206,7 +210,7 @@ export class selectCells extends Plugin {
|
|
|
206
210
|
cell,
|
|
207
211
|
this.__selectedCell
|
|
208
212
|
]), box = this.__tableModule.formalMatrix(table);
|
|
209
|
-
const max = (
|
|
213
|
+
const max = (_b = box[bound[1][0]]) === null || _b === void 0 ? void 0 : _b[bound[1][1]], min = (_c = box[bound[0][0]]) === null || _c === void 0 ? void 0 : _c[bound[0][1]];
|
|
210
214
|
// `getSelectedBound` keeps its `Infinity` sentinel when none of the
|
|
211
215
|
// selected cells belong to this table's matrix — e.g. after a
|
|
212
216
|
// drag-and-drop that moved/removed the cells, leaving a stale anchor and
|
|
@@ -134,6 +134,15 @@ export class source extends Plugin {
|
|
|
134
134
|
}
|
|
135
135
|
setFocusToMirror() {
|
|
136
136
|
var _a;
|
|
137
|
+
const active = this.j.od.activeElement;
|
|
138
|
+
// do not steal focus from another editor or control — e.g. when the
|
|
139
|
+
// mode is switched programmatically (a Vue/React wrapper re-render)
|
|
140
|
+
// while the user is already typing elsewhere. See #1356
|
|
141
|
+
if (active &&
|
|
142
|
+
active !== this.j.od.body &&
|
|
143
|
+
!this.j.container.contains(active)) {
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
137
146
|
(_a = this.sourceEditor) === null || _a === void 0 ? void 0 : _a.focus();
|
|
138
147
|
}
|
|
139
148
|
saveSelection() {
|
package/package.json
CHANGED
|
@@ -42,6 +42,11 @@ export declare class Dialog extends ViewWithToolbar implements IDialog {
|
|
|
42
42
|
private __onMouseMove;
|
|
43
43
|
private __onEsc;
|
|
44
44
|
private __onResize;
|
|
45
|
+
/**
|
|
46
|
+
* Minimal size the dialog can be resized to — the header and the footer
|
|
47
|
+
* (with its buttons) must always stay inside the panel
|
|
48
|
+
*/
|
|
49
|
+
private minSize;
|
|
45
50
|
private __onResizerMouseDown;
|
|
46
51
|
private __addGlobalResizeListeners;
|
|
47
52
|
private __removeGlobalResizeListeners;
|
|
@@ -15,6 +15,12 @@ export declare class ToolbarContent<T extends IViewBased = IViewBased> extends U
|
|
|
15
15
|
className(): string;
|
|
16
16
|
/** @override */
|
|
17
17
|
update(): void;
|
|
18
|
+
/**
|
|
19
|
+
* The content is arbitrary HTML — propagate the disabled state to the
|
|
20
|
+
* nested form controls (e.g. the file input of the Upload button),
|
|
21
|
+
* otherwise they stay interactive.
|
|
22
|
+
*/
|
|
23
|
+
protected onChangeDisabled(): void;
|
|
18
24
|
/** @override */
|
|
19
25
|
protected createContainer(): HTMLElement;
|
|
20
26
|
constructor(jodit: T, control: IControlTypeContent, target?: Nullable<HTMLElement>);
|
|
@@ -42,6 +42,21 @@ export declare class inlinePopup extends Plugin {
|
|
|
42
42
|
private isExcludedTarget;
|
|
43
43
|
/** @override **/
|
|
44
44
|
protected afterInit(jodit: IJodit): void;
|
|
45
|
+
/**
|
|
46
|
+
* The user pressed a button inside the selection toolbar — after the
|
|
47
|
+
* command fires `closeAllPopups`, the toolbar should be shown again
|
|
48
|
+
* while the selection is still there. See #1238
|
|
49
|
+
*/
|
|
50
|
+
private __reopenSelectionPopup;
|
|
51
|
+
private __onDocumentMouseDown;
|
|
52
|
+
private __onCloseAllPopups;
|
|
53
|
+
/**
|
|
54
|
+
* The selection rect comes from the editor document — in iframe mode its
|
|
55
|
+
* coordinates are iframe-local, while the popup lives in the host
|
|
56
|
+
* document, so the iframe offset must be added. See
|
|
57
|
+
* https://github.com/xdan/jodit/issues/1058
|
|
58
|
+
*/
|
|
59
|
+
private __selectionBound;
|
|
45
60
|
private snapRange;
|
|
46
61
|
private onSelectionStart;
|
|
47
62
|
private onSelectionEnd;
|