@ckeditor/ckeditor5-widget 48.3.1 → 48.4.0-alpha.1

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/dist/index.js CHANGED
@@ -3,12 +3,12 @@
3
3
  * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-licensing-options
4
4
  */
5
5
  import { Plugin } from "@ckeditor/ckeditor5-core";
6
- import { ModelTreeWalker, MouseObserver, PointerObserver } from "@ckeditor/ckeditor5-engine";
6
+ import { ModelDocumentSelection, ModelTreeWalker, MouseObserver, PointerObserver } from "@ckeditor/ckeditor5-engine";
7
7
  import { Delete } from "@ckeditor/ckeditor5-typing";
8
8
  import { CKEditorError, DomEmitterMixin, EmitterMixin, ObservableMixin, Rect, compareArrays, env, getLocalizedArrowKeyCodeDirection, getRangeFromMouseEvent, global, isForwardArrowKeyCode, keyCodes, logWarning, toArray } from "@ckeditor/ckeditor5-utils";
9
9
  import { IconDragHandle, IconReturnArrow } from "@ckeditor/ckeditor5-icons";
10
10
  import { BalloonPanelView, ContextualBalloon, IconView, Template, ToolbarView, View } from "@ckeditor/ckeditor5-ui";
11
- import { Enter } from "@ckeditor/ckeditor5-enter";
11
+ import { Enter, _getCopyOnEnterAttributes } from "@ckeditor/ckeditor5-enter";
12
12
  import { throttle } from "es-toolkit/compat";
13
13
 
14
14
  /**
@@ -513,6 +513,59 @@ function getClosestWidgetViewElement(domElement, domConverter) {
513
513
  function getTypeAroundFakeCaretPosition(selection) {
514
514
  return selection.getAttribute(TYPE_AROUND_SELECTION_ATTRIBUTE);
515
515
  }
516
+ /**
517
+ * Looks for the `copyOnEnter` text formatting attributes (e.g. bold, font color) carried by the last piece
518
+ * of inline content on the sibling that directly precedes a run of one or more consecutive block widgets.
519
+ *
520
+ * Used when the user inserts a new paragraph next to a widget (e.g. an image or a table) via the type-around
521
+ * UI: the new, empty paragraph should continue whatever formatting was active right before the widget,
522
+ * instead of starting unformatted:
523
+ *
524
+ * ```
525
+ * <paragraph><$text bold="true">Bar</$text></paragraph><imageBlock></imageBlock>
526
+ * ```
527
+ *
528
+ * Only the attributes carried by the *last* inline child of that sibling are considered - whatever precedes
529
+ * it doesn't matter, because it's the last piece of content that reflects what the user was typing right
530
+ * before reaching the widget:
531
+ *
532
+ * ```
533
+ * // "bold" IS recovered here: "Bar", the last child, is bold. "Foo" not being bold is irrelevant.
534
+ * <paragraph>Foo<$text bold="true">Bar</$text></paragraph><imageBlock></imageBlock>
535
+ * ```
536
+ *
537
+ * If there is more than one widget in a row, the search continues past all of them until a sibling with
538
+ * actual content (or the boundary of the parent) is found:
539
+ *
540
+ * ```
541
+ * <paragraph><$text bold="true">Bar</$text></paragraph><imageBlock></imageBlock><imageBlock></imageBlock>
542
+ * ```
543
+ *
544
+ * @param schema Model's schema.
545
+ * @param widgetElement The widget model element.
546
+ * @internal
547
+ */
548
+ function getCopyOnEnterTextAttributesBeforeWidgets(schema, widgetElement) {
549
+ let sibling = widgetElement;
550
+ while (sibling && sibling.is("element") && schema.isObject(sibling)) sibling = sibling.previousSibling;
551
+ if (!sibling?.is("element")) return [];
552
+ if (sibling.isEmpty) {
553
+ const selectionAttributes = extractStoredSelectionAttributes(sibling.getAttributes());
554
+ return Array.from(_getCopyOnEnterAttributes(schema, selectionAttributes));
555
+ }
556
+ const lastChild = sibling.getChild(sibling.childCount - 1);
557
+ if (!schema.isInline(lastChild)) return [];
558
+ return Array.from(_getCopyOnEnterAttributes(schema, lastChild.getAttributes()));
559
+ }
560
+ /**
561
+ * Extracts the selection attributes stored on an empty block.
562
+ */
563
+ function* extractStoredSelectionAttributes(iterator) {
564
+ for (const [attributeKey, attributeValue] of iterator) {
565
+ if (!ModelDocumentSelection._isStoreAttributeKey(attributeKey)) continue;
566
+ yield [ModelDocumentSelection._dropStoreAttributeKeyPrefix(attributeKey), attributeValue];
567
+ }
568
+ }
516
569
 
517
570
  /**
518
571
  * @license Copyright (c) 2003-2026, CKSource Holding sp. z o.o. All rights reserved.
@@ -602,11 +655,16 @@ var WidgetTypeAround = class extends Plugin {
602
655
  */
603
656
  _insertParagraph(widgetModelElement, position) {
604
657
  const editor = this.editor;
658
+ const { model } = editor;
659
+ const { schema } = model;
605
660
  const editingView = editor.editing.view;
606
- const attributesToCopy = editor.model.schema.getAttributesWithProperty(widgetModelElement, "copyOnReplace", true);
607
- editor.execute("insertParagraph", {
608
- position: editor.model.createPositionAt(widgetModelElement, position),
609
- attributes: attributesToCopy
661
+ const attributesToCopy = schema.getAttributesWithProperty(widgetModelElement, "copyOnReplace", true);
662
+ const selectionAttributes = getCopyOnEnterTextAttributesBeforeWidgets(schema, widgetModelElement);
663
+ model.change((writer) => {
664
+ if (editor.execute("insertParagraph", {
665
+ position: editor.model.createPositionAt(widgetModelElement, position),
666
+ attributes: attributesToCopy
667
+ })) writer.setSelectionAttribute(selectionAttributes);
610
668
  });
611
669
  editingView.focus();
612
670
  editingView.scrollToTheSelection();
@@ -1694,7 +1752,7 @@ function findClosestEditableOrWidgetAncestor(element) {
1694
1752
  */
1695
1753
  function getElementFromMouseEvent(view, domEventData) {
1696
1754
  const domRange = getRangeFromMouseEvent(domEventData.domEvent);
1697
- let viewRange = null;
1755
+ let viewRange;
1698
1756
  if (domRange) viewRange = view.domConverter.domRangeToView(domRange);
1699
1757
  else viewRange = view.createRange(view.createPositionAt(domEventData.target, 0));
1700
1758
  if (!viewRange) return null;