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

Sign up to get free protection for your applications and to get access to all the features.
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@
5
5
  import { Plugin } from '@ckeditor/ckeditor5-core/dist/index.js';
6
6
  import { MouseObserver, TreeWalker } from '@ckeditor/ckeditor5-engine/dist/index.js';
7
7
  import { Delete } from '@ckeditor/ckeditor5-typing/dist/index.js';
8
- import { EmitterMixin, CKEditorError, Rect, toArray, isForwardArrowKeyCode, env, keyCodes, getLocalizedArrowKeyCodeDirection, logWarning, ObservableMixin, compareArrays, global, DomEmitterMixin } from '@ckeditor/ckeditor5-utils/dist/index.js';
8
+ import { EmitterMixin, CKEditorError, Rect, toArray, isForwardArrowKeyCode, env, keyCodes, getLocalizedArrowKeyCodeDirection, getRangeFromMouseEvent, logWarning, ObservableMixin, compareArrays, global, DomEmitterMixin } from '@ckeditor/ckeditor5-utils/dist/index.js';
9
9
  import { IconView, Template, ContextualBalloon, ToolbarView, BalloonPanelView, View } from '@ckeditor/ckeditor5-ui/dist/index.js';
10
10
  import { Enter } from '@ckeditor/ckeditor5-enter/dist/index.js';
11
11
  import { throttle } from 'lodash-es';
@@ -1702,16 +1702,23 @@ function selectionWillShrink(selection, isForward) {
1702
1702
  }
1703
1703
  return;
1704
1704
  }
1705
- // Do nothing for single or double click inside nested editable.
1706
- if (isInsideNestedEditable(element)) {
1707
- return;
1708
- }
1709
1705
  // If target is not a widget element - check if one of the ancestors is.
1710
1706
  if (!isWidget(element)) {
1711
- element = element.findAncestor(isWidget);
1712
- if (!element) {
1707
+ const editableOrWidgetElement = findClosestEditableOrWidgetAncestor(element);
1708
+ if (!editableOrWidgetElement) {
1713
1709
  return;
1714
1710
  }
1711
+ if (isWidget(editableOrWidgetElement)) {
1712
+ element = editableOrWidgetElement;
1713
+ } else {
1714
+ // Pick view range from the point where the mouse was clicked.
1715
+ const clickTargetFromPoint = getElementFromMouseEvent(view, domEventData);
1716
+ if (clickTargetFromPoint && isWidget(clickTargetFromPoint)) {
1717
+ element = clickTargetFromPoint;
1718
+ } else {
1719
+ return;
1720
+ }
1721
+ }
1715
1722
  }
1716
1723
  // On Android selection would jump to the first table cell, on other devices
1717
1724
  // we can't block it (and don't need to) because of drag and drop support.
@@ -1944,20 +1951,46 @@ function selectionWillShrink(selection, isForward) {
1944
1951
  }
1945
1952
  }
1946
1953
  /**
1947
- * Returns `true` when element is a nested editable or is placed inside one.
1948
- */ function isInsideNestedEditable(element) {
1954
+ * Finds the closest ancestor element that is either an editable element or a widget.
1955
+ *
1956
+ * @param element The element from which to start searching.
1957
+ * @returns The closest ancestor element that is either an editable element or a widget, or null if none is found.
1958
+ */ function findClosestEditableOrWidgetAncestor(element) {
1949
1959
  let currentElement = element;
1950
1960
  while(currentElement){
1951
- if (currentElement.is('editableElement') && !currentElement.is('rootElement')) {
1952
- return true;
1953
- }
1954
- // Click on nested widget should select it.
1955
- if (isWidget(currentElement)) {
1956
- return false;
1961
+ if (currentElement.is('editableElement') || isWidget(currentElement)) {
1962
+ return currentElement;
1957
1963
  }
1958
1964
  currentElement = currentElement.parent;
1959
1965
  }
1960
- return false;
1966
+ return null;
1967
+ }
1968
+ /**
1969
+ * Retrieves the ViewElement associated with a mouse event in the editing view.
1970
+ *
1971
+ * @param view The editing view.
1972
+ * @param domEventData The DOM event data containing the mouse event.
1973
+ * @returns The ViewElement associated with the mouse event, or null if not found.
1974
+ */ function getElementFromMouseEvent(view, domEventData) {
1975
+ const domRange = getRangeFromMouseEvent(domEventData.domEvent);
1976
+ if (!domRange) {
1977
+ return null;
1978
+ }
1979
+ const viewRange = view.domConverter.domRangeToView(domRange);
1980
+ if (!viewRange) {
1981
+ return null;
1982
+ }
1983
+ const viewPosition = viewRange.start;
1984
+ if (!viewPosition.parent) {
1985
+ return null;
1986
+ }
1987
+ // Click after a widget tend to return position at the end of the editable element
1988
+ // so use the node before it if range is at the end of a parent.
1989
+ const viewNode = viewPosition.parent.is('editableElement') && viewPosition.isAtEnd && viewPosition.nodeBefore || viewPosition.parent;
1990
+ if (viewNode.is('$text')) {
1991
+ return viewNode.parent;
1992
+ }
1993
+ return viewNode;
1961
1994
  }
1962
1995
  /**
1963
1996
  * Checks whether the specified `element` is a child of the `parent` element.