@ckeditor/ckeditor5-widget 43.0.0 → 43.1.0-alpha.0

Sign up to get free protection for your applications and to get access to all the features.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ckeditor/ckeditor5-widget",
3
- "version": "43.0.0",
3
+ "version": "43.1.0-alpha.0",
4
4
  "description": "Widget API for CKEditor 5.",
5
5
  "keywords": [
6
6
  "ckeditor",
@@ -12,12 +12,12 @@
12
12
  "type": "module",
13
13
  "main": "src/index.js",
14
14
  "dependencies": {
15
- "@ckeditor/ckeditor5-core": "43.0.0",
16
- "@ckeditor/ckeditor5-engine": "43.0.0",
17
- "@ckeditor/ckeditor5-enter": "43.0.0",
18
- "@ckeditor/ckeditor5-ui": "43.0.0",
19
- "@ckeditor/ckeditor5-utils": "43.0.0",
20
- "@ckeditor/ckeditor5-typing": "43.0.0",
15
+ "@ckeditor/ckeditor5-core": "43.1.0-alpha.0",
16
+ "@ckeditor/ckeditor5-engine": "43.1.0-alpha.0",
17
+ "@ckeditor/ckeditor5-enter": "43.1.0-alpha.0",
18
+ "@ckeditor/ckeditor5-ui": "43.1.0-alpha.0",
19
+ "@ckeditor/ckeditor5-utils": "43.1.0-alpha.0",
20
+ "@ckeditor/ckeditor5-typing": "43.1.0-alpha.0",
21
21
  "lodash-es": "4.17.21"
22
22
  },
23
23
  "author": "CKSource (http://cksource.com/)",
package/src/widget.js CHANGED
@@ -8,7 +8,7 @@
8
8
  import { Plugin } from '@ckeditor/ckeditor5-core';
9
9
  import { MouseObserver, TreeWalker } from '@ckeditor/ckeditor5-engine';
10
10
  import { Delete } from '@ckeditor/ckeditor5-typing';
11
- import { env, keyCodes, getLocalizedArrowKeyCodeDirection } from '@ckeditor/ckeditor5-utils';
11
+ import { env, keyCodes, getLocalizedArrowKeyCodeDirection, getRangeFromMouseEvent } from '@ckeditor/ckeditor5-utils';
12
12
  import WidgetTypeAround from './widgettypearound/widgettypearound.js';
13
13
  import verticalNavigationHandler from './verticalnavigation.js';
14
14
  import { getLabel, isWidget, WIDGET_SELECTED_CLASS_NAME } from './utils.js';
@@ -224,16 +224,25 @@ export default class Widget extends Plugin {
224
224
  }
225
225
  return;
226
226
  }
227
- // Do nothing for single or double click inside nested editable.
228
- if (isInsideNestedEditable(element)) {
229
- return;
230
- }
231
227
  // If target is not a widget element - check if one of the ancestors is.
232
228
  if (!isWidget(element)) {
233
- element = element.findAncestor(isWidget);
234
- if (!element) {
229
+ const editableOrWidgetElement = findClosestEditableOrWidgetAncestor(element);
230
+ if (!editableOrWidgetElement) {
235
231
  return;
236
232
  }
233
+ if (isWidget(editableOrWidgetElement)) {
234
+ element = editableOrWidgetElement;
235
+ }
236
+ else {
237
+ // Pick view range from the point where the mouse was clicked.
238
+ const clickTargetFromPoint = getElementFromMouseEvent(view, domEventData);
239
+ if (clickTargetFromPoint && isWidget(clickTargetFromPoint)) {
240
+ element = clickTargetFromPoint;
241
+ }
242
+ else {
243
+ return;
244
+ }
245
+ }
237
246
  }
238
247
  // On Android selection would jump to the first table cell, on other devices
239
248
  // we can't block it (and don't need to) because of drag and drop support.
@@ -481,21 +490,48 @@ export default class Widget extends Plugin {
481
490
  }
482
491
  }
483
492
  /**
484
- * Returns `true` when element is a nested editable or is placed inside one.
493
+ * Finds the closest ancestor element that is either an editable element or a widget.
494
+ *
495
+ * @param element The element from which to start searching.
496
+ * @returns The closest ancestor element that is either an editable element or a widget, or null if none is found.
485
497
  */
486
- function isInsideNestedEditable(element) {
498
+ function findClosestEditableOrWidgetAncestor(element) {
487
499
  let currentElement = element;
488
500
  while (currentElement) {
489
- if (currentElement.is('editableElement') && !currentElement.is('rootElement')) {
490
- return true;
491
- }
492
- // Click on nested widget should select it.
493
- if (isWidget(currentElement)) {
494
- return false;
501
+ if (currentElement.is('editableElement') || isWidget(currentElement)) {
502
+ return currentElement;
495
503
  }
496
504
  currentElement = currentElement.parent;
497
505
  }
498
- return false;
506
+ return null;
507
+ }
508
+ /**
509
+ * Retrieves the ViewElement associated with a mouse event in the editing view.
510
+ *
511
+ * @param view The editing view.
512
+ * @param domEventData The DOM event data containing the mouse event.
513
+ * @returns The ViewElement associated with the mouse event, or null if not found.
514
+ */
515
+ function getElementFromMouseEvent(view, domEventData) {
516
+ const domRange = getRangeFromMouseEvent(domEventData.domEvent);
517
+ if (!domRange) {
518
+ return null;
519
+ }
520
+ const viewRange = view.domConverter.domRangeToView(domRange);
521
+ if (!viewRange) {
522
+ return null;
523
+ }
524
+ const viewPosition = viewRange.start;
525
+ if (!viewPosition.parent) {
526
+ return null;
527
+ }
528
+ // Click after a widget tend to return position at the end of the editable element
529
+ // so use the node before it if range is at the end of a parent.
530
+ const viewNode = viewPosition.parent.is('editableElement') && viewPosition.isAtEnd && viewPosition.nodeBefore || viewPosition.parent;
531
+ if (viewNode.is('$text')) {
532
+ return viewNode.parent;
533
+ }
534
+ return viewNode;
499
535
  }
500
536
  /**
501
537
  * Checks whether the specified `element` is a child of the `parent` element.