{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-widget/theme/icons/drag-handle.svg","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/highlightstack.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/utils.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widgettypearound/utils.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widgettypearound/widgettypearound.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/verticalnavigation.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widget.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widgettoolbarrepository.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widgetresize/resizerstate.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widgetresize/resizer.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/widgetresize.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/src/index.js","webpack:///./node_modules/@ckeditor/ckeditor5-widget/theme/icons/return-arrow.svg"],"names":["module","exports","HighlightStack","this","_stack","descriptor","writer","stack","oldTop","_insertDescriptor","newTop","compareDescriptors","fire","oldDescriptor","newDescriptor","id","_removeDescriptor","index","findIndex","item","splice","i","shouldABeBeforeB","a","b","priority","classesToString","classes","Array","isArray","sort","join","mix","EmitterMixin","WIDGET_CLASS_NAME","WIDGET_SELECTED_CLASS_NAME","isWidget","node","is","getCustomProperty","toWidget","element","options","CKEditorError","setAttribute","addClass","setCustomProperty","getFillerOffset","label","setLabel","hasSelectionHandle","addSelectionHandle","setHighlightHandling","toArray","removeClass","add","remove","on","evt","data","labelOrCreator","getLabel","labelCreator","toWidgetEditable","editable","isReadOnly","property","findOptimalInsertionPosition","selection","model","selectedElement","getSelectedElement","typeAroundFakeCaretPosition","getTypeAroundFakeCaretPosition","createPositionAt","schema","isBlock","createPositionAfter","firstBlock","getSelectedBlocks","next","value","isEmpty","positionAfter","focus","isTouching","createPositionBefore","checkSelectionOnObject","isObject","centeredBalloonPositionForLongWidgets","widgetRect","balloonRect","viewportRect","Rect","global","window","viewportWidgetInsersectionRect","getIntersection","balloonTotalHeight","height","BalloonPanelView","arrowVerticalOffset","top","bottom","targetRect","left","width","Math","max","name","widgetElement","selectionHandle","createUIElement","class","domDocument","domElement","toDomElement","icon","IconView","set","dragHandleIcon","render","appendChild","insert","TYPE_AROUND_SELECTION_ATTRIBUTE","isTypeAroundWidget","viewElement","modelElement","isInline","getClosestTypeAroundDomButton","closest","getTypeAroundButtonPosition","classList","contains","getClosestWidgetViewElement","domConverter","widgetDomElement","mapDomToView","getAttribute","POSSIBLE_INSERTION_POSITIONS","RETURN_ARROW_ICON_ELEMENT","DOMParser","parseFromString","returnIcon","firstChild","PLUGIN_DISABLED_EDITING_ROOT_CLASS","WidgetTypeAround","editor","_currentFakeCaretModelElement","editingView","editing","view","isEnabled","change","document","roots","root","removeSelectionAttribute","_enableTypeAroundUIInjection","_enableInsertingParagraphsOnButtonClick","_enableInsertingParagraphsOnEnterKeypress","_enableInsertingParagraphsOnTypingKeystroke","_enableTypeAroundFakeCaretActivationUsingKeyboardArrows","_enableDeleteIntegration","_enableInsertContentIntegration","widgetModelElement","position","execute","scrollToTheSelection","emitter","event","callback","listenTo","modelSelection","selectedModelElement","_insertParagraph","t","locale","buttonTitles","before","after","downcastDispatcher","conversionApi","mapper","toViewElement","injectUIIntoWidget","positionToWidgetCssClass","_listenToIfEnabled","domEventData","isArrowKeyCode","keyCode","_handleArrowKeyPress","priorities","get","directChange","selectedViewElement","map","ui","focusTracker","isFocused","shouldStopAndPreventDefault","isForward","isForwardArrowKeyCode","contentLanguageDirection","toModelElement","_handleArrowKeyPressOnSelectedWidget","isCollapsed","_handleArrowKeyPressWhenSelectionNextToAWidget","preventDefault","stop","setSelectionAttribute","isLeavingWidget","widgetPlugin","plugins","modelElementNextToSelection","_getObjectElementNextToSelection","viewElementNextToSelection","_setSelectionOverElement","button","domTarget","buttonPosition","widgetViewElement","wasHandled","_insertParagraphAccordingToFakeCaretPosition","isSoft","keyCodesHandledSomewhereElse","keyCodes","enter","delete","backspace","includes","isNonTypingKeystroke","direction","selectedModelWidget","isFakeCaretBefore","isDeleteForward","shouldDeleteEntireWidget","createSelection","range","getNearestSelectionRange","probe","start","modifySelection","isEqual","deepestEmptyRangeAncestor","getDeepestEmptyElementAncestor","parent","deleteContent","doNotAutoparagraph","setSelection","documentSelection","content","selectable","result","insertContent","Plugin","viewWriter","typeAroundWrapper","wrapperDomElement","injectButtons","injectFakeCaret","buttonTemplate","Template","tag","attributes","title","children","ownerDocument","importNode","caretTemplate","deepestEmptyAncestor","getAncestors","parentFirst","ancestor","childCount","isLimit","verticalNavigationHandler","arrowUpPressed","arrowup","arrowDownPressed","arrowdown","expandSelection","shiftKey","selectionWillShrink","findTextRangeFromSelection","isSingleLineRange","newPosition","end","newSelection","anchor","setFocus","stopPropagation","startPosition","getLastPosition","endPosition","getNearestNonInlineLimit","createRange","lastRangePosition","getNearestTextPosition","isBefore","getFirstPosition","firstRangePosition","isAfter","createRangeIn","walkerValueType","getWalker","previousPosition","type","checkChild","nextPosition","modelRange","isAtEnd","boundaryVerticalPosition","viewRange","toViewRange","domRange","viewRangeToDom","rects","getDomRangeRects","rect","undefined","round","isBackward","Widget","viewDocument","_previouslySelected","Set","_clearPreviouslySelectedWidgets","viewSelection","lastMarked","getRanges","isChild","fake","addObserver","MouseObserver","_onMousedown","_handleSelectionChangeOnArrowKeyPress","_preventDefaultOnArrowKeyPress","_handleDelete","eventInfo","target","isInsideNestedEditable","env","isSafari","isGecko","domEvent","detail","findAncestor","objectElement","newRange","objectElementNextToSelection","modelDocument","previousNode","nodeToRemove","createRangeOn","forward","nodeBefore","nodeAfter","widget","clear","from","WidgetToolbarRepository","has","balloonToolbar","isWidgetSelected","_toolbarDefinitions","Map","_balloon","_updateToolbarsVisibility","values","toolbarConfig","destroy","toolbarId","ariaLabel","items","getRelatedElement","balloonClassName","length","toolbarView","ToolbarView","fillFromConfig","componentFactory","logWarning","maxRelatedElementDepth","deepestRelatedElement","deepestToolbarDefinition","definition","relatedElement","relatedElementDepth","_isToolbarVisible","_hideToolbar","_isToolbarInBalloon","_showToolbar","toolbarDefinition","stopListening","repositionContextualBalloon","getBalloonPositionData","toolbar","visibleView","hasView","ContextualBalloon","balloon","updatePosition","defaultPositions","mapViewToDom","positions","northArrowSouth","northArrowSouthWest","northArrowSouthEast","southArrowNorth","southArrowNorthWest","southArrowNorthEast","ResizeState","_options","_referenceCoordinates","domResizeHandle","domHandleHost","domResizeHost","clientRect","activeHandlePosition","getHandlePosition","getAbsoluteBoundaryPoint","getOppositePosition","originalWidth","originalHeight","aspectRatio","widthStyle","style","match","originalWidthPercents","parseFloat","calculateHostPercentageWidth","newSize","proposedWidth","proposedHeight","proposedWidthPercents","widthPercents","proposedHandleHostWidth","handleHostWidth","proposedHandleHostHeight","handleHostHeight","resizeHostRect","domResizeHostParent","parentElement","parentWidth","defaultView","getComputedStyle","resizerPosition","elementRect","positionParts","split","ret","x","right","y","scrollX","scrollY","getResizerHandleClass","domHandle","resizerPositions","parts","replacements","ObservableMixin","Resizer","_domResizerWrapper","_viewResizerWrapper","decorate","state","_cleanup","redraw","that","viewResizerWrapper","_appendHandles","_appendSizeUI","propName","newValue","display","_sizeUI","bindToState","_initialViewWidth","getStyle","begin","_getHandleHost","_getResizeHost","_proposeNewSize","unit","newWidth","setStyle","domHandleHostRect","domResizeHostRect","update","onCommit","cancel","handleHostRect","domWrapper","existsInDom","newDimensions","widgetWrapper","handleHost","resizerWrapper","currentDimensions","isSameNode","offsetWidth","offsetHeight","offsetLeft","offsetTop","compareArrays","dismiss","isVisible","currentCoordinates","extractCoordinates","isCentered","enlargement","endsWith","proposedSize","abs","dominant","targetSize","min","getResizeHost","getHandleHost","currentPosition","getResizerClass","sizeUI","SizeView","bind","bindTemplate","setTemplate","to","if","visible","text","resizerState","unbind","View","pageX","pageY","WidgetResize","_resizers","setAttributeProperties","isFormatting","_observer","Object","create","DomEmitterMixin","_mouseDownListener","_mouseMoveListener","_mouseUpListener","redrawFocusedResizer","visibleResizer","redrawFocusedResizerThrottled","throttle","getResizerByViewElement","resizer","attach","widgetToolbarRepository","forceDisabled","clearForceDisabled","containsHandle","resizeHandle","isResizeHandle","_activeResizer","_getResizerByHandle","updateSize","commit"],"mappings":"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","file":"js/chunk-vendors~1611e805.53674c7d.js","sourcesContent":["module.exports = \"\"","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/highlightstack\n */\n\nimport EmitterMixin from '@ckeditor/ckeditor5-utils/src/emittermixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Class used to handle correct order of highlights on elements.\n *\n * When different highlights are applied to same element correct order should be preserved:\n *\n * * highlight with highest priority should be applied,\n * * if two highlights have same priority - sort by CSS class provided in\n * {@link module:engine/conversion/downcasthelpers~HighlightDescriptor}.\n *\n * This way, highlight will be applied with the same rules it is applied on texts.\n */\nexport default class HighlightStack {\n\t/**\n\t * Creates class instance.\n\t */\n\tconstructor() {\n\t\tthis._stack = [];\n\t}\n\n\t/**\n\t * Adds highlight descriptor to the stack.\n\t *\n\t * @fires change:top\n\t * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\tadd( descriptor, writer ) {\n\t\tconst stack = this._stack;\n\n\t\t// Save top descriptor and insert new one. If top is changed - fire event.\n\t\tconst oldTop = stack[ 0 ];\n\t\tthis._insertDescriptor( descriptor );\n\t\tconst newTop = stack[ 0 ];\n\n\t\t// When new object is at the top and stores different information.\n\t\tif ( oldTop !== newTop && !compareDescriptors( oldTop, newTop ) ) {\n\t\t\tthis.fire( 'change:top', {\n\t\t\t\toldDescriptor: oldTop,\n\t\t\t\tnewDescriptor: newTop,\n\t\t\t\twriter\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Removes highlight descriptor from the stack.\n\t *\n\t * @fires change:top\n\t * @param {String} id Id of the descriptor to remove.\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\tremove( id, writer ) {\n\t\tconst stack = this._stack;\n\n\t\tconst oldTop = stack[ 0 ];\n\t\tthis._removeDescriptor( id );\n\t\tconst newTop = stack[ 0 ];\n\n\t\t// When new object is at the top and stores different information.\n\t\tif ( oldTop !== newTop && !compareDescriptors( oldTop, newTop ) ) {\n\t\t\tthis.fire( 'change:top', {\n\t\t\t\toldDescriptor: oldTop,\n\t\t\t\tnewDescriptor: newTop,\n\t\t\t\twriter\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * Inserts given descriptor in correct place in the stack. It also takes care about updating information when\n\t * descriptor with same id is already present.\n\t *\n\t * @private\n\t * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} descriptor\n\t */\n\t_insertDescriptor( descriptor ) {\n\t\tconst stack = this._stack;\n\t\tconst index = stack.findIndex( item => item.id === descriptor.id );\n\n\t\t// Inserting exact same descriptor - do nothing.\n\t\tif ( compareDescriptors( descriptor, stack[ index ] ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If descriptor with same id but with different information is on the stack - remove it.\n\t\tif ( index > -1 ) {\n\t\t\tstack.splice( index, 1 );\n\t\t}\n\n\t\t// Find correct place to insert descriptor in the stack.\n\t\t// It have different information (for example priority) so it must be re-inserted in correct place.\n\t\tlet i = 0;\n\n\t\twhile ( stack[ i ] && shouldABeBeforeB( stack[ i ], descriptor ) ) {\n\t\t\ti++;\n\t\t}\n\n\t\tstack.splice( i, 0, descriptor );\n\t}\n\n\t/**\n\t * Removes descriptor with given id from the stack.\n\t *\n\t * @private\n\t * @param {String} id Descriptor's id.\n\t */\n\t_removeDescriptor( id ) {\n\t\tconst stack = this._stack;\n\t\tconst index = stack.findIndex( item => item.id === id );\n\n\t\t// If descriptor with same id is on the list - remove it.\n\t\tif ( index > -1 ) {\n\t\t\tstack.splice( index, 1 );\n\t\t}\n\t}\n}\n\nmix( HighlightStack, EmitterMixin );\n\n// Compares two descriptors by checking their priority and class list.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} a\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} b\n// @returns {Boolean} Returns true if both descriptors are defined and have same priority and classes.\nfunction compareDescriptors( a, b ) {\n\treturn a && b && a.priority == b.priority && classesToString( a.classes ) == classesToString( b.classes );\n}\n\n// Checks whenever first descriptor should be placed in the stack before second one.\n//\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} a\n// @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} b\n// @returns {Boolean}\nfunction shouldABeBeforeB( a, b ) {\n\tif ( a.priority > b.priority ) {\n\t\treturn true;\n\t} else if ( a.priority < b.priority ) {\n\t\treturn false;\n\t}\n\n\t// When priorities are equal and names are different - use classes to compare.\n\treturn classesToString( a.classes ) > classesToString( b.classes );\n}\n\n// Converts CSS classes passed with {@link module:engine/conversion/downcasthelpers~HighlightDescriptor} to\n// sorted string.\n//\n// @param {String|Array} descriptor\n// @returns {String}\nfunction classesToString( classes ) {\n\treturn Array.isArray( classes ) ? classes.sort().join( ',' ) : classes;\n}\n\n/**\n * Fired when top element on {@link module:widget/highlightstack~HighlightStack} has been changed\n *\n * @event change:top\n * @param {Object} data Additional information about the change.\n * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} [data.newDescriptor] New highlight\n * descriptor. It will be `undefined` when last descriptor is removed from the stack.\n * @param {module:engine/conversion/downcasthelpers~HighlightDescriptor} [data.oldDescriptor] Old highlight\n * descriptor. It will be `undefined` when first descriptor is added to the stack.\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer View writer that can be used to modify element.\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/utils\n */\n\nimport BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';\n\nimport global from '@ckeditor/ckeditor5-utils/src/dom/global';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport CKEditorError from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\nimport toArray from '@ckeditor/ckeditor5-utils/src/toarray';\n\nimport HighlightStack from './highlightstack';\nimport { getTypeAroundFakeCaretPosition } from './widgettypearound/utils';\n\nimport IconView from '@ckeditor/ckeditor5-ui/src/icon/iconview';\nimport dragHandleIcon from '../theme/icons/drag-handle.svg';\n\n/**\n * CSS class added to each widget element.\n *\n * @const {String}\n */\nexport const WIDGET_CLASS_NAME = 'ck-widget';\n\n/**\n * CSS class added to currently selected widget element.\n *\n * @const {String}\n */\nexport const WIDGET_SELECTED_CLASS_NAME = 'ck-widget_selected';\n\n/**\n * Returns `true` if given {@link module:engine/view/node~Node} is an {@link module:engine/view/element~Element} and a widget.\n *\n * @param {module:engine/view/node~Node} node\n * @returns {Boolean}\n */\nexport function isWidget( node ) {\n\tif ( !node.is( 'element' ) ) {\n\t\treturn false;\n\t}\n\n\treturn !!node.getCustomProperty( 'widget' );\n}\n\n/**\n * Converts the given {@link module:engine/view/element~Element} to a widget in the following way:\n *\n * * sets the `contenteditable` attribute to `\"false\"`,\n * * adds the `ck-widget` CSS class,\n * * adds a custom {@link module:engine/view/element~Element#getFillerOffset `getFillerOffset()`} method returning `null`,\n * * adds a custom property allowing to recognize widget elements by using {@link ~isWidget `isWidget()`},\n * * implements the {@link ~setHighlightHandling view highlight on widgets}.\n *\n * This function needs to be used in conjunction with\n * {@link module:engine/conversion/downcasthelpers~DowncastHelpers downcast conversion helpers}\n * like {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.\n * Moreover, typically you will want to use `toWidget()` only for `editingDowncast`, while keeping the `dataDowncast` clean.\n *\n * For example, in order to convert a `` model element to `
` in the view, you can define\n * such converters:\n *\n *\t\teditor.conversion.for( 'editingDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'widget',\n *\t\t\t\tview: ( modelItem, { writer } ) => {\n *\t\t\t\t\tconst div = writer.createContainerElement( 'div', { class: 'widget' } );\n *\n *\t\t\t\t\treturn toWidget( div, writer, { label: 'some widget' } );\n *\t\t\t\t}\n *\t\t\t} );\n *\n *\t\teditor.conversion.for( 'dataDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'widget',\n *\t\t\t\tview: ( modelItem, { writer } ) => {\n *\t\t\t\t\treturn writer.createContainerElement( 'div', { class: 'widget' } );\n *\t\t\t\t}\n *\t\t\t} );\n *\n * See the full source code of the widget (with a nested editable) schema definition and converters in\n * [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).\n *\n * @param {module:engine/view/element~Element} element\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @param {Object} [options={}]\n * @param {String|Function} [options.label] Element's label provided to the {@link ~setLabel} function. It can be passed as\n * a plain string or a function returning a string. It represents the widget for assistive technologies (like screen readers).\n * @param {Boolean} [options.hasSelectionHandle=false] If `true`, the widget will have a selection handle added.\n * @returns {module:engine/view/element~Element} Returns the same element.\n */\nexport function toWidget( element, writer, options = {} ) {\n\tif ( !element.is( 'containerElement' ) ) {\n\t\t/**\n\t\t * The element passed to `toWidget()` must be a {@link module:engine/view/containerelement~ContainerElement}\n\t\t * instance.\n\t\t *\n\t\t * @error widget-to-widget-wrong-element-type\n\t\t * @param {String} element The view element passed to `toWidget()`.\n\t\t */\n\t\tthrow new CKEditorError(\n\t\t\t'widget-to-widget-wrong-element-type',\n\t\t\tnull,\n\t\t\t{ element }\n\t\t);\n\t}\n\n\twriter.setAttribute( 'contenteditable', 'false', element );\n\n\twriter.addClass( WIDGET_CLASS_NAME, element );\n\twriter.setCustomProperty( 'widget', true, element );\n\telement.getFillerOffset = getFillerOffset;\n\n\tif ( options.label ) {\n\t\tsetLabel( element, options.label, writer );\n\t}\n\n\tif ( options.hasSelectionHandle ) {\n\t\taddSelectionHandle( element, writer );\n\t}\n\n\tsetHighlightHandling(\n\t\telement,\n\t\twriter,\n\t\t( element, descriptor, writer ) => writer.addClass( toArray( descriptor.classes ), element ),\n\t\t( element, descriptor, writer ) => writer.removeClass( toArray( descriptor.classes ), element )\n\t);\n\n\treturn element;\n}\n\n/**\n * Sets highlight handling methods. Uses {@link module:widget/highlightstack~HighlightStack} to\n * properly determine which highlight descriptor should be used at given time.\n *\n * @param {module:engine/view/element~Element} element\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @param {Function} add\n * @param {Function} remove\n */\nexport function setHighlightHandling( element, writer, add, remove ) {\n\tconst stack = new HighlightStack();\n\n\tstack.on( 'change:top', ( evt, data ) => {\n\t\tif ( data.oldDescriptor ) {\n\t\t\tremove( element, data.oldDescriptor, data.writer );\n\t\t}\n\n\t\tif ( data.newDescriptor ) {\n\t\t\tadd( element, data.newDescriptor, data.writer );\n\t\t}\n\t} );\n\n\twriter.setCustomProperty( 'addHighlight', ( element, descriptor, writer ) => stack.add( descriptor, writer ), element );\n\twriter.setCustomProperty( 'removeHighlight', ( element, id, writer ) => stack.remove( id, writer ), element );\n}\n\n/**\n * Sets label for given element.\n * It can be passed as a plain string or a function returning a string. Function will be called each time label is retrieved by\n * {@link ~getLabel `getLabel()`}.\n *\n * @param {module:engine/view/element~Element} element\n * @param {String|Function} labelOrCreator\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n */\nexport function setLabel( element, labelOrCreator, writer ) {\n\twriter.setCustomProperty( 'widgetLabel', labelOrCreator, element );\n}\n\n/**\n * Returns the label of the provided element.\n *\n * @param {module:engine/view/element~Element} element\n * @returns {String}\n */\nexport function getLabel( element ) {\n\tconst labelCreator = element.getCustomProperty( 'widgetLabel' );\n\n\tif ( !labelCreator ) {\n\t\treturn '';\n\t}\n\n\treturn typeof labelCreator == 'function' ? labelCreator() : labelCreator;\n}\n\n/**\n * Adds functionality to the provided {@link module:engine/view/editableelement~EditableElement} to act as a widget's editable:\n *\n * * sets the `contenteditable` attribute to `true` when {@link module:engine/view/editableelement~EditableElement#isReadOnly} is `false`,\n * otherwise sets it to `false`,\n * * adds the `ck-editor__editable` and `ck-editor__nested-editable` CSS classes,\n * * adds the `ck-editor__nested-editable_focused` CSS class when the editable is focused and removes it when it is blurred.\n *\n * Similarly to {@link ~toWidget `toWidget()`} this function should be used in `editingDowncast` only and it is usually\n * used together with {@link module:engine/conversion/downcasthelpers~DowncastHelpers#elementToElement `elementToElement()`}.\n *\n * For example, in order to convert a `` model element to `
` in the view, you can define\n * such converters:\n *\n *\t\teditor.conversion.for( 'editingDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'nested',\n *\t\t\t\tview: ( modelItem, { writer } ) => {\n *\t\t\t\t\tconst div = writer.createEditableElement( 'div', { class: 'nested' } );\n *\n *\t\t\t\t\treturn toWidgetEditable( nested, writer );\n *\t\t\t\t}\n *\t\t\t} );\n *\n *\t\teditor.conversion.for( 'dataDowncast' )\n *\t\t\t.elementToElement( {\n *\t\t\t\tmodel: 'nested',\n *\t\t\t\tview: ( modelItem, { writer } ) => {\n *\t\t\t\t\treturn writer.createContainerElement( 'div', { class: 'nested' } );\n *\t\t\t\t}\n *\t\t\t} );\n *\n * See the full source code of the widget (with nested editable) schema definition and converters in\n * [this sample](https://github.com/ckeditor/ckeditor5-widget/blob/master/tests/manual/widget-with-nestededitable.js).\n *\n * @param {module:engine/view/editableelement~EditableElement} editable\n * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n * @returns {module:engine/view/editableelement~EditableElement} Returns the same element that was provided in the `editable` parameter\n */\nexport function toWidgetEditable( editable, writer ) {\n\twriter.addClass( [ 'ck-editor__editable', 'ck-editor__nested-editable' ], editable );\n\n\t// Set initial contenteditable value.\n\twriter.setAttribute( 'contenteditable', editable.isReadOnly ? 'false' : 'true', editable );\n\n\t// Bind the contenteditable property to element#isReadOnly.\n\teditable.on( 'change:isReadOnly', ( evt, property, is ) => {\n\t\twriter.setAttribute( 'contenteditable', is ? 'false' : 'true', editable );\n\t} );\n\n\teditable.on( 'change:isFocused', ( evt, property, is ) => {\n\t\tif ( is ) {\n\t\t\twriter.addClass( 'ck-editor__nested-editable_focused', editable );\n\t\t} else {\n\t\t\twriter.removeClass( 'ck-editor__nested-editable_focused', editable );\n\t\t}\n\t} );\n\n\treturn editable;\n}\n\n/**\n * Returns a model position which is optimal (in terms of UX) for inserting a widget block.\n *\n * For instance, if a selection is in the middle of a paragraph, the position before this paragraph\n * will be returned so that it is not split. If the selection is at the end of a paragraph,\n * the position after this paragraph will be returned.\n *\n * Note: If the selection is placed in an empty block, that block will be returned. If that position\n * is then passed to {@link module:engine/model/model~Model#insertContent},\n * the block will be fully replaced by the image.\n *\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * The selection based on which the insertion position should be calculated.\n * @param {module:engine/model/model~Model} model Model instance.\n * @returns {module:engine/model/position~Position} The optimal position.\n */\nexport function findOptimalInsertionPosition( selection, model ) {\n\tconst selectedElement = selection.getSelectedElement();\n\n\tif ( selectedElement ) {\n\t\tconst typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition( selection );\n\n\t\t// If the WidgetTypeAround \"fake caret\" is displayed, use its position for the insertion\n\t\t// to provide the most predictable UX (https://github.com/ckeditor/ckeditor5/issues/7438).\n\t\tif ( typeAroundFakeCaretPosition ) {\n\t\t\treturn model.createPositionAt( selectedElement, typeAroundFakeCaretPosition );\n\t\t}\n\n\t\tif ( model.schema.isBlock( selectedElement ) ) {\n\t\t\treturn model.createPositionAfter( selectedElement );\n\t\t}\n\t}\n\n\tconst firstBlock = selection.getSelectedBlocks().next().value;\n\n\tif ( firstBlock ) {\n\t\t// If inserting into an empty block – return position in that block. It will get\n\t\t// replaced with the image by insertContent(). #42.\n\t\tif ( firstBlock.isEmpty ) {\n\t\t\treturn model.createPositionAt( firstBlock, 0 );\n\t\t}\n\n\t\tconst positionAfter = model.createPositionAfter( firstBlock );\n\n\t\t// If selection is at the end of the block - return position after the block.\n\t\tif ( selection.focus.isTouching( positionAfter ) ) {\n\t\t\treturn positionAfter;\n\t\t}\n\n\t\t// Otherwise return position before the block.\n\t\treturn model.createPositionBefore( firstBlock );\n\t}\n\n\treturn selection.focus;\n}\n\n/**\n * Checks if the selection is on an object.\n *\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * @param {module:engine/model/schema~Schema} schema\n * @returns {Boolean}\n*/\nexport function checkSelectionOnObject( selection, schema ) {\n\tconst selectedElement = selection.getSelectedElement();\n\n\treturn !!selectedElement && schema.isObject( selectedElement );\n}\n\n/**\n * A util to be used in order to map view positions to correct model positions when implementing a widget\n * which renders non-empty view element for an empty model element.\n *\n * For example:\n *\n *\t\t// Model:\n *\t\t\n *\n *\t\t// View:\n *\t\tname\n *\n * In such case, view positions inside `` cannot be correct mapped to the model (because the model element is empty).\n * To handle mapping positions inside `` to the model use this util as follows:\n *\n *\t\teditor.editing.mapper.on(\n *\t\t\t'viewToModelPosition',\n *\t\t\tviewToModelPositionOutsideModelElement( model, viewElement => viewElement.hasClass( 'placeholder' ) )\n *\t\t);\n *\n * The callback will try to map the view offset of selection to an expected model position.\n *\n * 1. When the position is at the end (or in the middle) of the inline widget:\n *\n *\t\t// View:\n *\t\t

foo name| bar

\n *\n *\t\t// Model:\n *\t\tfoo | bar\n *\n * 2. When the position is at the beginning of the inline widget:\n *\n *\t\t// View:\n *\t\t

foo |name bar

\n *\n *\t\t// Model:\n *\t\tfoo | bar\n *\n * @param {module:engine/model/model~Model} model Model instance on which the callback operates.\n * @param {Function} viewElementMatcher Function that is passed a view element and should return `true` if the custom mapping\n * should be applied to the given view element.\n * @return {Function}\n */\nexport function viewToModelPositionOutsideModelElement( model, viewElementMatcher ) {\n\treturn ( evt, data ) => {\n\t\tconst { mapper, viewPosition } = data;\n\n\t\tconst viewParent = mapper.findMappedViewAncestor( viewPosition );\n\n\t\tif ( !viewElementMatcher( viewParent ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelParent = mapper.toModelElement( viewParent );\n\n\t\tdata.modelPosition = model.createPositionAt( modelParent, viewPosition.isAtStart ? 'before' : 'after' );\n\t};\n}\n\n/**\n * A positioning function passed to the {@link module:utils/dom/position~getOptimalPosition} helper as a last resort\n * when attaching {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView balloon UI} to widgets.\n * It comes in handy when a widget is longer than the visual viewport of the web browser and/or upper/lower boundaries\n * of a widget are off screen because of the web page scroll.\n *\n *\t ┌─┄┄┄┄┄┄┄┄┄Widget┄┄┄┄┄┄┄┄┄┐\n *\t ┊ ┊\n *\t┌────────────Viewport───────────┐ ┌──╁─────────Viewport────────╁──┐\n *\t│ ┏━━━━━━━━━━Widget━━━━━━━━━┓ │ │ ┃ ^ ┃ │\n *\t│ ┃ ^ ┃ │ │ ┃ ╭───────/ \\───────╮ ┃ │\n *\t│ ┃ ╭───────/ \\───────╮ ┃ │ │ ┃ │ Balloon │ ┃ │\n *\t│ ┃ │ Balloon │ ┃ │ │ ┃ ╰─────────────────╯ ┃ │\n *\t│ ┃ ╰─────────────────╯ ┃ │ │ ┃ ┃ │\n *\t│ ┃ ┃ │ │ ┃ ┃ │\n *\t│ ┃ ┃ │ │ ┃ ┃ │\n *\t│ ┃ ┃ │ │ ┃ ┃ │\n *\t│ ┃ ┃ │ │ ┃ ┃ │\n *\t│ ┃ ┃ │ │ ┃ ┃ │\n *\t│ ┃ ┃ │ │ ┃ ┃ │\n *\t└──╀─────────────────────────╀──┘ └──╀─────────────────────────╀──┘\n *\t ┊ ┊ ┊ ┊\n *\t ┊ ┊ └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘\n *\t ┊ ┊\n *\t └┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄┘\n *\n * **Note**: Works best if used together with\n * {@link module:ui/panel/balloon/balloonpanelview~BalloonPanelView.defaultPositions default `BalloonPanelView` positions}\n * like `northArrowSouth` and `southArrowNorth`; the transition between these two and this position is smooth.\n *\n * @param {module:utils/dom/rect~Rect} widgetRect A rect of the widget.\n * @param {module:utils/dom/rect~Rect} balloonRect A rect of the balloon.\n * @returns {module:utils/dom/position~Position|null}\n */\nexport function centeredBalloonPositionForLongWidgets( widgetRect, balloonRect ) {\n\tconst viewportRect = new Rect( global.window );\n\tconst viewportWidgetInsersectionRect = viewportRect.getIntersection( widgetRect );\n\n\tconst balloonTotalHeight = balloonRect.height + BalloonPanelView.arrowVerticalOffset;\n\n\t// If there is enough space above or below the widget then this position should not be used.\n\tif ( widgetRect.top - balloonTotalHeight > viewportRect.top || widgetRect.bottom + balloonTotalHeight < viewportRect.bottom ) {\n\t\treturn null;\n\t}\n\n\t// Because this is a last resort positioning, to keep things simple we're not playing with positions of the arrow\n\t// like, for instance, \"south west\" or whatever. Just try to keep the balloon in the middle of the visible area of\n\t// the widget for as long as it is possible. If the widgets becomes invisible (because cropped by the viewport),\n\t// just... place the balloon in the middle of it (because why not?).\n\tconst targetRect = viewportWidgetInsersectionRect || widgetRect;\n\tconst left = targetRect.left + targetRect.width / 2 - balloonRect.width / 2;\n\n\treturn {\n\t\ttop: Math.max( widgetRect.top, 0 ) + BalloonPanelView.arrowVerticalOffset,\n\t\tleft,\n\t\tname: 'arrow_n'\n\t};\n}\n\n// Default filler offset function applied to all widget elements.\n//\n// @returns {null}\nfunction getFillerOffset() {\n\treturn null;\n}\n\n// Adds a drag handle to the widget.\n//\n// @param {module:engine/view/containerelement~ContainerElement}\n// @param {module:engine/view/downcastwriter~DowncastWriter} writer\nfunction addSelectionHandle( widgetElement, writer ) {\n\tconst selectionHandle = writer.createUIElement( 'div', { class: 'ck ck-widget__selection-handle' }, function( domDocument ) {\n\t\tconst domElement = this.toDomElement( domDocument );\n\n\t\t// Use the IconView from the ui library.\n\t\tconst icon = new IconView();\n\t\ticon.set( 'content', dragHandleIcon );\n\n\t\t// Render the icon view right away to append its #element to the selectionHandle DOM element.\n\t\ticon.render();\n\n\t\tdomElement.appendChild( icon.element );\n\n\t\treturn domElement;\n\t} );\n\n\t// Append the selection handle into the widget wrapper.\n\twriter.insert( writer.createPositionAt( widgetElement, 0 ), selectionHandle );\n\twriter.addClass( [ 'ck-widget_with-selection-handle' ], widgetElement );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/widgettypearound/utils\n */\n\nimport { isWidget } from '../utils';\n\n/**\n * The name of the type around model selection attribute responsible for\n * displaying a fake caret next to a selected widget.\n */\nexport const TYPE_AROUND_SELECTION_ATTRIBUTE = 'widget-type-around';\n\n/**\n * Checks if an element is a widget that qualifies to get the widget type around UI.\n *\n * @param {module:engine/view/element~Element} viewElement\n * @param {module:engine/model/element~Element} modelElement\n * @param {module:engine/model/schema~Schema} schema\n * @returns {Boolean}\n */\nexport function isTypeAroundWidget( viewElement, modelElement, schema ) {\n\treturn viewElement && isWidget( viewElement ) && !schema.isInline( modelElement );\n}\n\n/**\n * For the passed HTML element, this helper finds the closest widget type around button ancestor.\n *\n * @param {HTMLElement} domElement\n * @returns {HTMLElement|null}\n */\nexport function getClosestTypeAroundDomButton( domElement ) {\n\treturn domElement.closest( '.ck-widget__type-around__button' );\n}\n\n/**\n * For the passed widget type around button element, this helper determines at which position\n * the paragraph would be inserted into the content if, for instance, the button was\n * clicked by the user.\n *\n * @param {HTMLElement} domElement\n * @returns {'before'|'after'} The position of the button.\n */\nexport function getTypeAroundButtonPosition( domElement ) {\n\treturn domElement.classList.contains( 'ck-widget__type-around__button_before' ) ? 'before' : 'after';\n}\n\n/**\n * For the passed HTML element, this helper returns the closest view widget ancestor.\n *\n * @param {HTMLElement} domElement\n * @param {module:engine/view/domconverter~DomConverter} domConverter\n * @returns {module:engine/view/element~Element}\n */\nexport function getClosestWidgetViewElement( domElement, domConverter ) {\n\tconst widgetDomElement = domElement.closest( '.ck-widget' );\n\n\treturn domConverter.mapDomToView( widgetDomElement );\n}\n\n/**\n * For the passed selection instance, it returns the position of the fake caret displayed next to a widget.\n *\n * **Note**: If the fake caret is not currently displayed, `null` is returned.\n *\n * @param {module:engine/model/selection~Selection|module:engine/model/documentselection~DocumentSelection} selection\n * @returns {'before'|'after'|null} The position of the fake caret or `null` when none is present.\n */\nexport function getTypeAroundFakeCaretPosition( selection ) {\n\treturn selection.getAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/* global DOMParser */\n\n/**\n * @module widget/widgettypearound\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Template from '@ckeditor/ckeditor5-ui/src/template';\nimport {\n\tisArrowKeyCode,\n\tisForwardArrowKeyCode,\n\tkeyCodes\n} from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport priorities from '@ckeditor/ckeditor5-utils/src/priorities';\n\nimport {\n\tisTypeAroundWidget,\n\tgetClosestTypeAroundDomButton,\n\tgetTypeAroundButtonPosition,\n\tgetClosestWidgetViewElement,\n\tgetTypeAroundFakeCaretPosition,\n\tTYPE_AROUND_SELECTION_ATTRIBUTE\n} from './utils';\n\nimport {\n\tisNonTypingKeystroke\n} from '@ckeditor/ckeditor5-typing/src/utils/injectunsafekeystrokeshandling';\n\nimport returnIcon from '../../theme/icons/return-arrow.svg';\nimport '../../theme/widgettypearound.css';\n\nconst POSSIBLE_INSERTION_POSITIONS = [ 'before', 'after' ];\n\n// Do the SVG parsing once and then clone the result DOM element for each new button.\nconst RETURN_ARROW_ICON_ELEMENT = new DOMParser().parseFromString( returnIcon, 'image/svg+xml' ).firstChild;\n\nconst PLUGIN_DISABLED_EDITING_ROOT_CLASS = 'ck-widget__type-around_disabled';\n\n/**\n * A plugin that allows users to type around widgets where normally it is impossible to place the caret due\n * to limitations of web browsers. These \"tight spots\" occur, for instance, before (or after) a widget being\n * the first (or last) child of its parent or between two block widgets.\n *\n * This plugin extends the {@link module:widget/widget~Widget `Widget`} plugin and injects the user interface\n * with two buttons into each widget instance in the editor. Each of the buttons can be clicked by the\n * user if the widget is next to the \"tight spot\". Once clicked, a paragraph is created with the selection anchored\n * in it so that users can type (or insert content, paste, etc.) straight away.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class WidgetTypeAround extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'WidgetTypeAround';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * A reference to the model widget element that has the fake caret active\n\t\t * on either side of it. It is later used to remove CSS classes associated with the fake caret\n\t\t * when the widget no longer needs it.\n\t\t *\n\t\t * @private\n\t\t * @member {module:engine/model/element~Element|null}\n\t\t */\n\t\tthis._currentFakeCaretModelElement = null;\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\n\t\t// Set a CSS class on the view editing root when the plugin is disabled so all the buttons\n\t\t// and lines visually disappear. All the interactions are disabled in individual plugin methods.\n\t\tthis.on( 'change:isEnabled', ( evt, data, isEnabled ) => {\n\t\t\teditingView.change( writer => {\n\t\t\t\tfor ( const root of editingView.document.roots ) {\n\t\t\t\t\tif ( isEnabled ) {\n\t\t\t\t\t\twriter.removeClass( PLUGIN_DISABLED_EDITING_ROOT_CLASS, root );\n\t\t\t\t\t} else {\n\t\t\t\t\t\twriter.addClass( PLUGIN_DISABLED_EDITING_ROOT_CLASS, root );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tif ( !isEnabled ) {\n\t\t\t\teditor.model.change( writer => {\n\t\t\t\t\twriter.removeSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE );\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tthis._enableTypeAroundUIInjection();\n\t\tthis._enableInsertingParagraphsOnButtonClick();\n\t\tthis._enableInsertingParagraphsOnEnterKeypress();\n\t\tthis._enableInsertingParagraphsOnTypingKeystroke();\n\t\tthis._enableTypeAroundFakeCaretActivationUsingKeyboardArrows();\n\t\tthis._enableDeleteIntegration();\n\t\tthis._enableInsertContentIntegration();\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tthis._currentFakeCaretModelElement = null;\n\t}\n\n\t/**\n\t * Inserts a new paragraph next to a widget element with the selection anchored in it.\n\t *\n\t * **Note**: This method is heavily user-oriented and will both focus the editing view and scroll\n\t * the viewport to the selection in the inserted paragraph.\n\t *\n\t * @protected\n\t * @param {module:engine/model/element~Element} widgetModelElement The model widget element next to which a paragraph is inserted.\n\t * @param {'before'|'after'} position The position where the paragraph is inserted. Either `'before'` or `'after'` the widget.\n\t */\n\t_insertParagraph( widgetModelElement, position ) {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\n\t\teditor.execute( 'insertParagraph', {\n\t\t\tposition: editor.model.createPositionAt( widgetModelElement, position )\n\t\t} );\n\n\t\teditingView.focus();\n\t\teditingView.scrollToTheSelection();\n\t}\n\n\t/**\n\t * A wrapper for the {@link module:utils/emittermixin~EmitterMixin#listenTo} method that executes the callbacks only\n\t * when the plugin {@link #isEnabled is enabled}.\n\t *\n\t * @private\n\t * @param {module:utils/emittermixin~Emitter} emitter The object that fires the event.\n\t * @param {String} event The name of the event.\n\t * @param {Function} callback The function to be called on event.\n\t * @param {Object} [options={}] Additional options.\n\t * @param {module:utils/priorities~PriorityString|Number} [options.priority='normal'] The priority of this event callback. The higher\n\t * the priority value the sooner the callback will be fired. Events having the same priority are called in the\n\t * order they were added.\n\t */\n\t_listenToIfEnabled( emitter, event, callback, options ) {\n\t\tthis.listenTo( emitter, event, ( ...args ) => {\n\t\t\t// Do not respond if the plugin is disabled.\n\t\t\tif ( this.isEnabled ) {\n\t\t\t\tcallback( ...args );\n\t\t\t}\n\t\t}, options );\n\t}\n\n\t/**\n\t * Similar to {@link #_insertParagraph}, this method inserts a paragraph except that it\n\t * does not expect a position. Instead, it performs the insertion next to a selected widget\n\t * according to the `widget-type-around` model selection attribute value (fake caret position).\n\t *\n\t * Because this method requires the `widget-type-around` attribute to be set,\n\t * the insertion can only happen when the widget's fake caret is active (e.g. activated\n\t * using the keyboard).\n\t *\n\t * @private\n\t * @returns {Boolean} Returns `true` when the paragraph was inserted (the attribute was present) and `false` otherwise.\n\t */\n\t_insertParagraphAccordingToFakeCaretPosition() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst modelSelection = model.document.selection;\n\t\tconst typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition( modelSelection );\n\n\t\tif ( !typeAroundFakeCaretPosition ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst selectedModelElement = modelSelection.getSelectedElement();\n\n\t\tthis._insertParagraph( selectedModelElement, typeAroundFakeCaretPosition );\n\n\t\treturn true;\n\t}\n\n\t/**\n\t * Creates a listener in the editing conversion pipeline that injects the widget type around\n\t * UI into every single widget instance created in the editor.\n\t *\n\t * The UI is delivered as a {@link module:engine/view/uielement~UIElement}\n\t * wrapper which renders DOM buttons that users can use to insert paragraphs.\n\t *\n\t * @private\n\t */\n\t_enableTypeAroundUIInjection() {\n\t\tconst editor = this.editor;\n\t\tconst schema = editor.model.schema;\n\t\tconst t = editor.locale.t;\n\t\tconst buttonTitles = {\n\t\t\tbefore: t( 'Insert paragraph before block' ),\n\t\t\tafter: t( 'Insert paragraph after block' )\n\t\t};\n\n\t\teditor.editing.downcastDispatcher.on( 'insert', ( evt, data, conversionApi ) => {\n\t\t\tconst viewElement = conversionApi.mapper.toViewElement( data.item );\n\n\t\t\t// Filter out non-widgets and inline widgets.\n\t\t\tif ( isTypeAroundWidget( viewElement, data.item, schema ) ) {\n\t\t\t\tinjectUIIntoWidget( conversionApi.writer, buttonTitles, viewElement );\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\t}\n\n\t/**\n\t * Brings support for the fake caret that appears when either:\n\t *\n\t * * the selection moves to a widget from a position next to it using arrow keys,\n\t * * the arrow key is pressed when the widget is already selected.\n\t *\n\t * The fake caret lets the user know that they can start typing or just press\n\t * Enter to insert a paragraph at the position next to a widget as suggested by the fake caret.\n\t *\n\t * The fake caret disappears when the user changes the selection or the editor\n\t * gets blurred.\n\t *\n\t * The whole idea is as follows:\n\t *\n\t * 1. A user does one of the 2 scenarios described at the beginning.\n\t * 2. The \"keydown\" listener is executed and the decision is made whether to show or hide the fake caret.\n\t * 3. If it should show up, the `widget-type-around` model selection attribute is set indicating\n\t * on which side of the widget it should appear.\n\t * 4. The selection dispatcher reacts to the selection attribute and sets CSS classes responsible for the\n\t * fake caret on the view widget.\n\t * 5. If the fake caret should disappear, the selection attribute is removed and the dispatcher\n\t * does the CSS class clean-up in the view.\n\t * 6. Additionally, `change:range` and `FocusTracker#isFocused` listeners also remove the selection\n\t * attribute (the former also removes widget CSS classes).\n\t *\n\t * @private\n\t */\n\t_enableTypeAroundFakeCaretActivationUsingKeyboardArrows() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst modelSelection = model.document.selection;\n\t\tconst schema = model.schema;\n\t\tconst editingView = editor.editing.view;\n\n\t\t// This is the main listener responsible for the fake caret.\n\t\t// Note: The priority must precede the default Widget class keydown handler (\"high\") and the\n\t\t// TableKeyboard keydown handler (\"high-10\").\n\t\tthis._listenToIfEnabled( editingView.document, 'keydown', ( evt, domEventData ) => {\n\t\t\tif ( isArrowKeyCode( domEventData.keyCode ) ) {\n\t\t\t\tthis._handleArrowKeyPress( evt, domEventData );\n\t\t\t}\n\t\t}, { priority: priorities.get( 'high' ) + 10 } );\n\n\t\t// This listener makes sure the widget type around selection attribute will be gone from the model\n\t\t// selection as soon as the model range changes. This attribute only makes sense when a widget is selected\n\t\t// (and the \"fake horizontal caret\" is visible) so whenever the range changes (e.g. selection moved somewhere else),\n\t\t// let's get rid of the attribute so that the selection downcast dispatcher isn't even bothered.\n\t\tthis._listenToIfEnabled( modelSelection, 'change:range', ( evt, data ) => {\n\t\t\t// Do not reset the selection attribute when the change was indirect.\n\t\t\tif ( !data.directChange ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Get rid of the widget type around attribute of the selection on every change:range.\n\t\t\t// If the range changes, it means for sure, the user is no longer in the active (\"fake horizontal caret\") mode.\n\t\t\teditor.model.change( writer => {\n\t\t\t\twriter.removeSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE );\n\t\t\t} );\n\t\t} );\n\n\t\t// Get rid of the widget type around attribute of the selection on every document change\n\t\t// that makes widget not selected any more (i.e. widget was removed).\n\t\tthis._listenToIfEnabled( model.document, 'change:data', () => {\n\t\t\tconst selectedModelElement = modelSelection.getSelectedElement();\n\n\t\t\tif ( selectedModelElement ) {\n\t\t\t\tconst selectedViewElement = editor.editing.mapper.toViewElement( selectedModelElement );\n\n\t\t\t\tif ( isTypeAroundWidget( selectedViewElement, selectedModelElement, schema ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\teditor.model.change( writer => {\n\t\t\t\twriter.removeSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE );\n\t\t\t} );\n\t\t} );\n\n\t\t// React to changes of the model selection attribute made by the arrow keys listener.\n\t\t// If the block widget is selected and the attribute changes, downcast the attribute to special\n\t\t// CSS classes associated with the active (\"fake horizontal caret\") mode of the widget.\n\t\tthis._listenToIfEnabled( editor.editing.downcastDispatcher, 'selection', ( evt, data, conversionApi ) => {\n\t\t\tconst writer = conversionApi.writer;\n\n\t\t\tif ( this._currentFakeCaretModelElement ) {\n\t\t\t\tconst selectedViewElement = conversionApi.mapper.toViewElement( this._currentFakeCaretModelElement );\n\n\t\t\t\tif ( selectedViewElement ) {\n\t\t\t\t\t// Get rid of CSS classes associated with the active (\"fake horizontal caret\") mode from the view widget.\n\t\t\t\t\twriter.removeClass( POSSIBLE_INSERTION_POSITIONS.map( positionToWidgetCssClass ), selectedViewElement );\n\n\t\t\t\t\tthis._currentFakeCaretModelElement = null;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst selectedModelElement = data.selection.getSelectedElement();\n\n\t\t\tif ( !selectedModelElement ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst selectedViewElement = conversionApi.mapper.toViewElement( selectedModelElement );\n\n\t\t\tif ( !isTypeAroundWidget( selectedViewElement, selectedModelElement, schema ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition( data.selection );\n\n\t\t\tif ( !typeAroundFakeCaretPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\twriter.addClass( positionToWidgetCssClass( typeAroundFakeCaretPosition ), selectedViewElement );\n\n\t\t\t// Remember the view widget that got the \"fake-caret\" CSS class. This class should be removed ASAP when the\n\t\t\t// selection changes\n\t\t\tthis._currentFakeCaretModelElement = selectedModelElement;\n\t\t} );\n\n\t\tthis._listenToIfEnabled( editor.ui.focusTracker, 'change:isFocused', ( evt, name, isFocused ) => {\n\t\t\tif ( !isFocused ) {\n\t\t\t\teditor.model.change( writer => {\n\t\t\t\t\twriter.removeSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE );\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tfunction positionToWidgetCssClass( position ) {\n\t\t\treturn `ck-widget_type-around_show-fake-caret_${ position }`;\n\t\t}\n\t}\n\n\t/**\n\t * A listener executed on each \"keydown\" in the view document, a part of\n\t * {@link #_enableTypeAroundFakeCaretActivationUsingKeyboardArrows}.\n\t *\n\t * It decides whether the arrow keypress should activate the fake caret or not (also whether it should\n\t * be deactivated).\n\t *\n\t * The fake caret activation is done by setting the `widget-type-around` model selection attribute\n\t * in this listener, and stopping and preventing the event that would normally be handled by the widget\n\t * plugin that is responsible for the regular keyboard navigation near/across all widgets (that\n\t * includes inline widgets, which are ignored by the widget type around plugin).\n\t *\n\t * @private\n\t */\n\t_handleArrowKeyPress( evt, domEventData ) {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst modelSelection = model.document.selection;\n\t\tconst schema = model.schema;\n\t\tconst editingView = editor.editing.view;\n\n\t\tconst keyCode = domEventData.keyCode;\n\t\tconst isForward = isForwardArrowKeyCode( keyCode, editor.locale.contentLanguageDirection );\n\t\tconst selectedViewElement = editingView.document.selection.getSelectedElement();\n\t\tconst selectedModelElement = editor.editing.mapper.toModelElement( selectedViewElement );\n\t\tlet shouldStopAndPreventDefault;\n\n\t\t// Handle keyboard navigation when a type-around-compatible widget is currently selected.\n\t\tif ( isTypeAroundWidget( selectedViewElement, selectedModelElement, schema ) ) {\n\t\t\tshouldStopAndPreventDefault = this._handleArrowKeyPressOnSelectedWidget( isForward );\n\t\t}\n\t\t// Handle keyboard arrow navigation when the selection is next to a type-around-compatible widget\n\t\t// and the widget is about to be selected.\n\t\telse if ( modelSelection.isCollapsed ) {\n\t\t\tshouldStopAndPreventDefault = this._handleArrowKeyPressWhenSelectionNextToAWidget( isForward );\n\t\t}\n\n\t\tif ( shouldStopAndPreventDefault ) {\n\t\t\tdomEventData.preventDefault();\n\t\t\tevt.stop();\n\t\t}\n\t}\n\n\t/**\n\t * Handles the keyboard navigation on \"keydown\" when a widget is currently selected and activates or deactivates\n\t * the fake caret for that widget, depending on the current value of the `widget-type-around` model\n\t * selection attribute and the direction of the pressed arrow key.\n\t *\n\t * @private\n\t * @param {Boolean} isForward `true` when the pressed arrow key was responsible for the forward model selection movement\n\t * as in {@link module:utils/keyboard~isForwardArrowKeyCode}.\n\t * @returns {Boolean} Returns `true` when the keypress was handled and no other keydown listener of the editor should\n\t * process the event any further. Returns `false` otherwise.\n\t */\n\t_handleArrowKeyPressOnSelectedWidget( isForward ) {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst modelSelection = model.document.selection;\n\t\tconst typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition( modelSelection );\n\n\t\treturn model.change( writer => {\n\t\t\t// If the fake caret is displayed...\n\t\t\tif ( typeAroundFakeCaretPosition ) {\n\t\t\t\tconst isLeavingWidget = typeAroundFakeCaretPosition === ( isForward ? 'after' : 'before' );\n\n\t\t\t\t// If the keyboard arrow works against the value of the selection attribute...\n\t\t\t\t// then remove the selection attribute but prevent default DOM actions\n\t\t\t\t// and do not let the Widget plugin listener move the selection. This brings\n\t\t\t\t// the widget back to the state, for instance, like if was selected using the mouse.\n\t\t\t\t//\n\t\t\t\t// **Note**: If leaving the widget when the fake caret is active, then the default\n\t\t\t\t// Widget handler will change the selection and, in turn, this will automatically discard\n\t\t\t\t// the selection attribute.\n\t\t\t\tif ( !isLeavingWidget ) {\n\t\t\t\t\twriter.removeSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE );\n\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t}\n\t\t\t// If the fake caret wasn't displayed, let's set it now according to the direction of the arrow\n\t\t\t// key press. This also means we cannot let the Widget plugin listener move the selection.\n\t\t\telse {\n\t\t\t\twriter.setSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE, isForward ? 'after' : 'before' );\n\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t} );\n\t}\n\n\t/**\n\t * Handles the keyboard navigation on \"keydown\" when **no** widget is selected but the selection is **directly** next\n\t * to one and upon the fake caret should become active for this widget upon arrow keypress\n\t * (AKA entering/selecting the widget).\n\t *\n\t * **Note**: This code mirrors the implementation from the widget plugin but also adds the selection attribute.\n\t * Unfortunately, there is no safe way to let the widget plugin do the selection part first and then just set the\n\t * selection attribute here in the widget type around plugin. This is why this code must duplicate some from the widget plugin.\n\t *\n\t * @private\n\t * @param {Boolean} isForward `true` when the pressed arrow key was responsible for the forward model selection movement\n\t * as in {@link module:utils/keyboard~isForwardArrowKeyCode}.\n\t * @returns {Boolean} Returns `true` when the keypress was handled and no other keydown listener of the editor should\n\t * process the event any further. Returns `false` otherwise.\n\t */\n\t_handleArrowKeyPressWhenSelectionNextToAWidget( isForward ) {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst schema = model.schema;\n\t\tconst widgetPlugin = editor.plugins.get( 'Widget' );\n\n\t\t// This is the widget the selection is about to be set on.\n\t\tconst modelElementNextToSelection = widgetPlugin._getObjectElementNextToSelection( isForward );\n\t\tconst viewElementNextToSelection = editor.editing.mapper.toViewElement( modelElementNextToSelection );\n\n\t\tif ( isTypeAroundWidget( viewElementNextToSelection, modelElementNextToSelection, schema ) ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\twidgetPlugin._setSelectionOverElement( modelElementNextToSelection );\n\t\t\t\twriter.setSelectionAttribute( TYPE_AROUND_SELECTION_ATTRIBUTE, isForward ? 'before' : 'after' );\n\t\t\t} );\n\n\t\t\t// The change() block above does the same job as the Widget plugin. The event can\n\t\t\t// be safely canceled.\n\t\t\treturn true;\n\t\t}\n\n\t\treturn false;\n\t}\n\n\t/**\n\t * Registers a `mousedown` listener for the view document which intercepts events\n\t * coming from the widget type around UI, which happens when a user clicks one of the buttons\n\t * that insert a paragraph next to a widget.\n\t *\n\t * @private\n\t */\n\t_enableInsertingParagraphsOnButtonClick() {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\n\t\tthis._listenToIfEnabled( editingView.document, 'mousedown', ( evt, domEventData ) => {\n\t\t\tconst button = getClosestTypeAroundDomButton( domEventData.domTarget );\n\n\t\t\tif ( !button ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst buttonPosition = getTypeAroundButtonPosition( button );\n\t\t\tconst widgetViewElement = getClosestWidgetViewElement( button, editingView.domConverter );\n\t\t\tconst widgetModelElement = editor.editing.mapper.toModelElement( widgetViewElement );\n\n\t\t\tthis._insertParagraph( widgetModelElement, buttonPosition );\n\n\t\t\tdomEventData.preventDefault();\n\t\t\tevt.stop();\n\t\t} );\n\t}\n\n\t/**\n\t * Creates the Enter key listener on the view document that allows the user to insert a paragraph\n\t * near the widget when either:\n\t *\n\t * * The fake caret was first activated using the arrow keys,\n\t * * The entire widget is selected in the model.\n\t *\n\t * In the first case, the new paragraph is inserted according to the `widget-type-around` selection\n\t * attribute (see {@link #_handleArrowKeyPress}).\n\t *\n\t * In the second case, the new paragraph is inserted based on whether a soft (Shift+Enter) keystroke\n\t * was pressed or not.\n\t *\n\t * @private\n\t */\n\t_enableInsertingParagraphsOnEnterKeypress() {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\n\t\tthis._listenToIfEnabled( editingView.document, 'enter', ( evt, domEventData ) => {\n\t\t\tconst selectedViewElement = editingView.document.selection.getSelectedElement();\n\t\t\tconst selectedModelElement = editor.editing.mapper.toModelElement( selectedViewElement );\n\t\t\tconst schema = editor.model.schema;\n\t\t\tlet wasHandled;\n\n\t\t\t// First check if the widget is selected and there's a type around selection attribute associated\n\t\t\t// with the fake caret that would tell where to insert a new paragraph.\n\t\t\tif ( this._insertParagraphAccordingToFakeCaretPosition() ) {\n\t\t\t\twasHandled = true;\n\t\t\t}\n\t\t\t// Then, if there is no selection attribute associated with the fake caret, check if the widget\n\t\t\t// simply is selected and create a new paragraph according to the keystroke (Shift+)Enter.\n\t\t\telse if ( isTypeAroundWidget( selectedViewElement, selectedModelElement, schema ) ) {\n\t\t\t\tthis._insertParagraph( selectedModelElement, domEventData.isSoft ? 'before' : 'after' );\n\n\t\t\t\twasHandled = true;\n\t\t\t}\n\n\t\t\tif ( wasHandled ) {\n\t\t\t\tdomEventData.preventDefault();\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Similar to the {@link #_enableInsertingParagraphsOnEnterKeypress}, it allows the user\n\t * to insert a paragraph next to a widget when the fake caret was activated using arrow\n\t * keys but it responds to typing keystrokes instead of Enter.\n\t *\n\t * \"Typing keystrokes\" are keystrokes that insert new content into the document,\n\t * for instance, letters (\"a\") or numbers (\"4\"). The \"keydown\" listener enabled by this method\n\t * will insert a new paragraph according to the `widget-type-around` model selection attribute\n\t * as the user simply starts typing, which creates the impression that the fake caret\n\t * behaves like a real one rendered by the browser (AKA your text appears where the caret was).\n\t *\n\t * **Note**: At the moment this listener creates 2 undo steps: one for the `insertParagraph` command\n\t * and another one for actual typing. It is not a disaster but this may need to be fixed\n\t * sooner or later.\n\t *\n\t * Learn more in {@link module:typing/utils/injectunsafekeystrokeshandling}.\n\t *\n\t * @private\n\t */\n\t_enableInsertingParagraphsOnTypingKeystroke() {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\t\tconst keyCodesHandledSomewhereElse = [\n\t\t\tkeyCodes.enter,\n\t\t\tkeyCodes.delete,\n\t\t\tkeyCodes.backspace\n\t\t];\n\n\t\t// Note: The priority must precede the default Widget class keydown handler (\"high\") and the\n\t\t// TableKeyboard keydown handler (\"high + 1\").\n\t\tthis._listenToIfEnabled( editingView.document, 'keydown', ( evt, domEventData ) => {\n\t\t\t// Don't handle enter/backspace/delete here. They are handled in dedicated listeners.\n\t\t\tif ( !keyCodesHandledSomewhereElse.includes( domEventData.keyCode ) && !isNonTypingKeystroke( domEventData ) ) {\n\t\t\t\tthis._insertParagraphAccordingToFakeCaretPosition();\n\t\t\t}\n\t\t}, { priority: priorities.get( 'high' ) + 1 } );\n\t}\n\n\t/**\n\t * It creates a \"delete\" event listener on the view document to handle cases when the Delete or Backspace\n\t * is pressed and the fake caret is currently active.\n\t *\n\t * The fake caret should create an illusion of a real browser caret so that when it appears before or after\n\t * a widget, pressing Delete or Backspace should remove a widget or delete the content\n\t * before or after a widget (depending on the content surrounding the widget).\n\t *\n\t * @private\n\t */\n\t_enableDeleteIntegration() {\n\t\tconst editor = this.editor;\n\t\tconst editingView = editor.editing.view;\n\t\tconst model = editor.model;\n\t\tconst schema = model.schema;\n\n\t\t// Note: The priority must precede the default Widget class delete handler.\n\t\tthis._listenToIfEnabled( editingView.document, 'delete', ( evt, domEventData ) => {\n\t\t\tconst typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition( model.document.selection );\n\n\t\t\t// This listener handles only these cases when the fake caret is active.\n\t\t\tif ( !typeAroundFakeCaretPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst direction = domEventData.direction;\n\t\t\tconst selectedModelWidget = model.document.selection.getSelectedElement();\n\n\t\t\tconst isFakeCaretBefore = typeAroundFakeCaretPosition === 'before';\n\t\t\tconst isDeleteForward = direction == 'forward';\n\t\t\tconst shouldDeleteEntireWidget = isFakeCaretBefore === isDeleteForward;\n\n\t\t\tif ( shouldDeleteEntireWidget ) {\n\t\t\t\teditor.execute( 'delete', {\n\t\t\t\t\tselection: model.createSelection( selectedModelWidget, 'on' )\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\tconst range = schema.getNearestSelectionRange(\n\t\t\t\t\tmodel.createPositionAt( selectedModelWidget, typeAroundFakeCaretPosition ),\n\t\t\t\t\tdirection\n\t\t\t\t);\n\n\t\t\t\t// If there is somewhere to move selection to, then there will be something to delete.\n\t\t\t\tif ( range ) {\n\t\t\t\t\t// If the range is NOT collapsed, then we know that the range contains an object (see getNearestSelectionRange() docs).\n\t\t\t\t\tif ( !range.isCollapsed ) {\n\t\t\t\t\t\tmodel.change( writer => {\n\t\t\t\t\t\t\twriter.setSelection( range );\n\t\t\t\t\t\t\teditor.execute( isDeleteForward ? 'deleteForward' : 'delete' );\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst probe = model.createSelection( range.start );\n\t\t\t\t\t\tmodel.modifySelection( probe, { direction } );\n\n\t\t\t\t\t\t// If the range is collapsed, let's see if a non-collapsed range exists that can could be deleted.\n\t\t\t\t\t\t// If such range exists, use the editor command because it it safe for collaboration (it merges where it can).\n\t\t\t\t\t\tif ( !probe.focus.isEqual( range.start ) ) {\n\t\t\t\t\t\t\tmodel.change( writer => {\n\t\t\t\t\t\t\t\twriter.setSelection( range );\n\t\t\t\t\t\t\t\teditor.execute( isDeleteForward ? 'deleteForward' : 'delete' );\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t// If there is no non-collapsed range to be deleted then we are sure that there is an empty element\n\t\t\t\t\t\t// next to a widget that should be removed. \"delete\" and \"deleteForward\" commands cannot get rid of it\n\t\t\t\t\t\t// so calling Model#deleteContent here manually.\n\t\t\t\t\t\telse {\n\t\t\t\t\t\t\tconst deepestEmptyRangeAncestor = getDeepestEmptyElementAncestor( schema, range.start.parent );\n\n\t\t\t\t\t\t\tmodel.deleteContent( model.createSelection( deepestEmptyRangeAncestor, 'on' ), {\n\t\t\t\t\t\t\t\tdoNotAutoparagraph: true\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If some content was deleted, don't let the handler from the Widget plugin kick in.\n\t\t\t// If nothing was deleted, then the default handler will have nothing to do anyway.\n\t\t\tdomEventData.preventDefault();\n\t\t\tevt.stop();\n\t\t}, { priority: priorities.get( 'high' ) + 1 } );\n\t}\n\n\t/**\n\t * Attaches the {@link module:engine/model/model~Model#event:insertContent} event listener that, for instance, allows the user to paste\n\t * content near a widget when the fake caret is first activated using the arrow keys.\n\t *\n\t * The content is inserted according to the `widget-type-around` selection attribute (see {@link #_handleArrowKeyPress}).\n\t *\n\t * @private\n\t */\n\t_enableInsertContentIntegration() {\n\t\tconst editor = this.editor;\n\t\tconst model = this.editor.model;\n\t\tconst documentSelection = model.document.selection;\n\n\t\tthis._listenToIfEnabled( editor.model, 'insertContent', ( evt, [ content, selectable ] ) => {\n\t\t\tif ( selectable && !selectable.is( 'documentSelection' ) ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tconst typeAroundFakeCaretPosition = getTypeAroundFakeCaretPosition( documentSelection );\n\n\t\t\tif ( !typeAroundFakeCaretPosition ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tevt.stop();\n\n\t\t\treturn model.change( writer => {\n\t\t\t\tconst selectedElement = documentSelection.getSelectedElement();\n\t\t\t\tconst position = model.createPositionAt( selectedElement, typeAroundFakeCaretPosition );\n\t\t\t\tconst selection = writer.createSelection( position );\n\n\t\t\t\tconst result = model.insertContent( content, selection );\n\n\t\t\t\twriter.setSelection( selection );\n\n\t\t\t\treturn result;\n\t\t\t} );\n\t\t}, { priority: 'high' } );\n\t}\n}\n\n// Injects the type around UI into a view widget instance.\n//\n// @param {module:engine/view/downcastwriter~DowncastWriter} viewWriter\n// @param {Object.} buttonTitles\n// @param {module:engine/view/element~Element} widgetViewElement\nfunction injectUIIntoWidget( viewWriter, buttonTitles, widgetViewElement ) {\n\tconst typeAroundWrapper = viewWriter.createUIElement( 'div', {\n\t\tclass: 'ck ck-reset_all ck-widget__type-around'\n\t}, function( domDocument ) {\n\t\tconst wrapperDomElement = this.toDomElement( domDocument );\n\n\t\tinjectButtons( wrapperDomElement, buttonTitles );\n\t\tinjectFakeCaret( wrapperDomElement );\n\n\t\treturn wrapperDomElement;\n\t} );\n\n\t// Inject the type around wrapper into the widget's wrapper.\n\tviewWriter.insert( viewWriter.createPositionAt( widgetViewElement, 'end' ), typeAroundWrapper );\n}\n\n// FYI: Not using the IconView class because each instance would need to be destroyed to avoid memory leaks\n// and it's pretty hard to figure out when a view (widget) is gone for good so it's cheaper to use raw\n// here.\n//\n// @param {HTMLElement} wrapperDomElement\n// @param {Object.} buttonTitles\nfunction injectButtons( wrapperDomElement, buttonTitles ) {\n\tfor ( const position of POSSIBLE_INSERTION_POSITIONS ) {\n\t\tconst buttonTemplate = new Template( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-widget__type-around__button',\n\t\t\t\t\t`ck-widget__type-around__button_${ position }`\n\t\t\t\t],\n\t\t\t\ttitle: buttonTitles[ position ]\n\t\t\t},\n\t\t\tchildren: [\n\t\t\t\twrapperDomElement.ownerDocument.importNode( RETURN_ARROW_ICON_ELEMENT, true )\n\t\t\t]\n\t\t} );\n\n\t\twrapperDomElement.appendChild( buttonTemplate.render() );\n\t}\n}\n\n// @param {HTMLElement} wrapperDomElement\nfunction injectFakeCaret( wrapperDomElement ) {\n\tconst caretTemplate = new Template( {\n\t\ttag: 'div',\n\t\tattributes: {\n\t\t\tclass: [\n\t\t\t\t'ck',\n\t\t\t\t'ck-widget__type-around__fake-caret'\n\t\t\t]\n\t\t}\n\t} );\n\n\twrapperDomElement.appendChild( caretTemplate.render() );\n}\n\n// Returns the ancestor of an element closest to the root which is empty. For instance,\n// for ``:\n//\n//\t\tabc\n//\n// it returns ``.\n//\n// @param {module:engine/model/schema~Schema} schema\n// @param {module:engine/model/element~Element} element\n// @returns {module:engine/model/element~Element|null}\nfunction getDeepestEmptyElementAncestor( schema, element ) {\n\tlet deepestEmptyAncestor = element;\n\n\tfor ( const ancestor of element.getAncestors( { parentFirst: true } ) ) {\n\t\tif ( ancestor.childCount > 1 || schema.isLimit( ancestor ) ) {\n\t\t\tbreak;\n\t\t}\n\n\t\tdeepestEmptyAncestor = ancestor;\n\t}\n\n\treturn deepestEmptyAncestor;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nimport { keyCodes } from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\n\n/**\n * @module widget/verticalnavigationhandler\n */\n\n/**\n * Returns 'keydown' handler for up/down arrow keys that modifies the caret movement if it's in a text line next to an object.\n *\n * @param {module:engine/controller/editingcontroller~EditingController} editing The editing controller.\n * @returns {Function}\n */\nexport default function verticalNavigationHandler( editing ) {\n\tconst model = editing.model;\n\n\treturn ( evt, data ) => {\n\t\tconst arrowUpPressed = data.keyCode == keyCodes.arrowup;\n\t\tconst arrowDownPressed = data.keyCode == keyCodes.arrowdown;\n\t\tconst expandSelection = data.shiftKey;\n\t\tconst selection = model.document.selection;\n\n\t\tif ( !arrowUpPressed && !arrowDownPressed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst isForward = arrowDownPressed;\n\n\t\t// Navigation is in the opposite direction than the selection direction so this is shrinking of the selection.\n\t\t// Selection for sure will not approach any object.\n\t\tif ( expandSelection && selectionWillShrink( selection, isForward ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Find a range between selection and closest limit element.\n\t\tconst range = findTextRangeFromSelection( editing, selection, isForward );\n\n\t\tif ( !range || range.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// If the range is a single line (there is no word wrapping) then move the selection to the position closest to the limit element.\n\t\t//\n\t\t// We can't move the selection directly to the isObject element (eg. table cell) because of dual position at the end/beginning\n\t\t// of wrapped line (it's at the same time at the end of one line and at the start of the next line).\n\t\tif ( isSingleLineRange( editing, range, isForward ) ) {\n\t\t\tmodel.change( writer => {\n\t\t\t\tconst newPosition = isForward ? range.end : range.start;\n\n\t\t\t\tif ( expandSelection ) {\n\t\t\t\t\tconst newSelection = model.createSelection( selection.anchor );\n\t\t\t\t\tnewSelection.setFocus( newPosition );\n\n\t\t\t\t\twriter.setSelection( newSelection );\n\t\t\t\t} else {\n\t\t\t\t\twriter.setSelection( newPosition );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tevt.stop();\n\t\t\tdata.preventDefault();\n\t\t\tdata.stopPropagation();\n\t\t}\n\t};\n}\n\n// Finds the range between selection and closest limit element (in the direction of navigation).\n// The position next to limit element is adjusted to the closest allowed `$text` position.\n//\n// Returns `null` if, according to the schema, the resulting range cannot contain a `$text` element.\n//\n// @param {module:engine/controller/editingcontroller~EditingController} editing The editing controller.\n// @param {module:engine/model/selection~Selection} selection The current selection.\n// @param {Boolean} isForward The expected navigation direction.\n// @returns {module:engine/model/range~Range|null}\n//\nfunction findTextRangeFromSelection( editing, selection, isForward ) {\n\tconst model = editing.model;\n\n\tif ( isForward ) {\n\t\tconst startPosition = selection.isCollapsed ? selection.focus : selection.getLastPosition();\n\t\tconst endPosition = getNearestNonInlineLimit( model, startPosition, 'forward' );\n\n\t\t// There is no limit element, browser should handle this.\n\t\tif ( !endPosition ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst range = model.createRange( startPosition, endPosition );\n\t\tconst lastRangePosition = getNearestTextPosition( model.schema, range, 'backward' );\n\n\t\tif ( lastRangePosition && startPosition.isBefore( lastRangePosition ) ) {\n\t\t\treturn model.createRange( startPosition, lastRangePosition );\n\t\t}\n\n\t\treturn null;\n\t} else {\n\t\tconst endPosition = selection.isCollapsed ? selection.focus : selection.getFirstPosition();\n\t\tconst startPosition = getNearestNonInlineLimit( model, endPosition, 'backward' );\n\n\t\t// There is no limit element, browser should handle this.\n\t\tif ( !startPosition ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst range = model.createRange( startPosition, endPosition );\n\t\tconst firstRangePosition = getNearestTextPosition( model.schema, range, 'forward' );\n\n\t\tif ( firstRangePosition && endPosition.isAfter( firstRangePosition ) ) {\n\t\t\treturn model.createRange( firstRangePosition, endPosition );\n\t\t}\n\n\t\treturn null;\n\t}\n}\n\n// Finds the limit element position that is closest to startPosition.\n//\n// @param {module:engine/model/model~Model} model\n// @param {} startPosition\n// @param {'forward'|'backward'} direction Search direction.\n// @returns {|null}\n//\nfunction getNearestNonInlineLimit( model, startPosition, direction ) {\n\tconst schema = model.schema;\n\tconst range = model.createRangeIn( startPosition.root );\n\n\tconst walkerValueType = direction == 'forward' ? 'elementStart' : 'elementEnd';\n\n\tfor ( const { previousPosition, item, type } of range.getWalker( { startPosition, direction } ) ) {\n\t\tif ( schema.isLimit( item ) && !schema.isInline( item ) ) {\n\t\t\treturn previousPosition;\n\t\t}\n\n\t\t// Stop looking for isLimit element if the next element is a block element (it is for sure not single line).\n\t\tif ( type == walkerValueType && schema.isBlock( item ) ) {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\treturn null;\n}\n\n// Basing on the provided range, finds the first or last (depending on `direction`) position inside the range\n// that can contain `$text` (according to schema).\n//\n// @param {module:engine/model/schema~Schema} schema The schema.\n// @param {module:engine/model/range~Range} range The range to find the position in.\n// @param {'forward'|'backward'} direction Search direction.\n// @returns {module:engine/model/position~Position} The nearest selection range.\n//\nfunction getNearestTextPosition( schema, range, direction ) {\n\tconst position = direction == 'backward' ? range.end : range.start;\n\n\tif ( schema.checkChild( position, '$text' ) ) {\n\t\treturn position;\n\t}\n\n\tfor ( const { nextPosition } of range.getWalker( { direction } ) ) {\n\t\tif ( schema.checkChild( nextPosition, '$text' ) ) {\n\t\t\treturn nextPosition;\n\t\t}\n\t}\n}\n\n// Checks if the DOM range corresponding to the provided model range renders as a single line by analyzing DOMRects\n// (verifying if they visually wrap content to the next line).\n//\n// @param {module:engine/controller/editingcontroller~EditingController} editing The editing controller.\n// @param {module:engine/model/range~Range} modelRange The current table cell content range.\n// @param {Boolean} isForward The expected navigation direction.\n// @returns {Boolean}\n//\nfunction isSingleLineRange( editing, modelRange, isForward ) {\n\tconst model = editing.model;\n\tconst domConverter = editing.view.domConverter;\n\n\t// Wrapped lines contain exactly the same position at the end of current line\n\t// and at the beginning of next line. That position's client rect is at the end\n\t// of current line. In case of caret at first position of the last line that 'dual'\n\t// position would be detected as it's not the last line.\n\tif ( isForward ) {\n\t\tconst probe = model.createSelection( modelRange.start );\n\n\t\tmodel.modifySelection( probe );\n\n\t\t// If the new position is at the end of the container then we can't use this position\n\t\t// because it would provide incorrect result for eg caption of image and selection\n\t\t// just before end of it. Also in this case there is no \"dual\" position.\n\t\tif ( !probe.focus.isAtEnd && !modelRange.start.isEqual( probe.focus ) ) {\n\t\t\tmodelRange = model.createRange( probe.focus, modelRange.end );\n\t\t}\n\t}\n\n\tconst viewRange = editing.mapper.toViewRange( modelRange );\n\tconst domRange = domConverter.viewRangeToDom( viewRange );\n\tconst rects = Rect.getDomRangeRects( domRange );\n\n\tlet boundaryVerticalPosition;\n\n\tfor ( const rect of rects ) {\n\t\tif ( boundaryVerticalPosition === undefined ) {\n\t\t\tboundaryVerticalPosition = Math.round( rect.bottom );\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Let's check if this rect is in new line.\n\t\tif ( Math.round( rect.top ) >= boundaryVerticalPosition ) {\n\t\t\treturn false;\n\t\t}\n\n\t\tboundaryVerticalPosition = Math.max( boundaryVerticalPosition, Math.round( rect.bottom ) );\n\t}\n\n\treturn true;\n}\n\nfunction selectionWillShrink( selection, isForward ) {\n\treturn !selection.isCollapsed && selection.isBackward == isForward;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/widget\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport MouseObserver from '@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver';\nimport WidgetTypeAround from './widgettypearound/widgettypearound';\nimport { getLabel, isWidget, WIDGET_SELECTED_CLASS_NAME } from './utils';\nimport {\n\tisArrowKeyCode,\n\tisForwardArrowKeyCode\n} from '@ckeditor/ckeditor5-utils/src/keyboard';\nimport env from '@ckeditor/ckeditor5-utils/src/env';\n\nimport '../theme/widget.css';\nimport priorities from '@ckeditor/ckeditor5-utils/src/priorities';\nimport verticalNavigationHandler from './verticalnavigation';\n\n/**\n * The widget plugin. It enables base support for widgets.\n *\n * See {@glink api/widget package page} for more details and documentation.\n *\n * This plugin enables multiple behaviors required by widgets:\n *\n * * The model to view selection converter for the editing pipeline (it handles widget custom selection rendering).\n * If a converted selection wraps around a widget element, that selection is marked as\n * {@link module:engine/view/selection~Selection#isFake fake}. Additionally, the `ck-widget_selected` CSS class\n * is added to indicate that widget has been selected.\n * * The mouse and keyboard events handling on and around widget elements.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class Widget extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'Widget';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ WidgetTypeAround ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst view = this.editor.editing.view;\n\t\tconst viewDocument = view.document;\n\n\t\t/**\n\t\t * Holds previously selected widgets.\n\t\t *\n\t\t * @private\n\t\t * @type {Set.}\n\t\t */\n\t\tthis._previouslySelected = new Set();\n\n\t\t// Model to view selection converter.\n\t\t// Converts selection placed over widget element to fake selection\n\t\tthis.editor.editing.downcastDispatcher.on( 'selection', ( evt, data, conversionApi ) => {\n\t\t\t// Remove selected class from previously selected widgets.\n\t\t\tthis._clearPreviouslySelectedWidgets( conversionApi.writer );\n\n\t\t\tconst viewWriter = conversionApi.writer;\n\t\t\tconst viewSelection = viewWriter.document.selection;\n\t\t\tconst selectedElement = viewSelection.getSelectedElement();\n\t\t\tlet lastMarked = null;\n\n\t\t\tfor ( const range of viewSelection.getRanges() ) {\n\t\t\t\tfor ( const value of range ) {\n\t\t\t\t\tconst node = value.item;\n\n\t\t\t\t\t// Do not mark nested widgets in selected one. See: #57.\n\t\t\t\t\tif ( isWidget( node ) && !isChild( node, lastMarked ) ) {\n\t\t\t\t\t\tviewWriter.addClass( WIDGET_SELECTED_CLASS_NAME, node );\n\n\t\t\t\t\t\tthis._previouslySelected.add( node );\n\t\t\t\t\t\tlastMarked = node;\n\n\t\t\t\t\t\t// Check if widget is a single element selected.\n\t\t\t\t\t\tif ( node == selectedElement ) {\n\t\t\t\t\t\t\tviewWriter.setSelection( viewSelection.getRanges(), { fake: true, label: getLabel( selectedElement ) } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}, { priority: 'low' } );\n\n\t\t// If mouse down is pressed on widget - create selection over whole widget.\n\t\tview.addObserver( MouseObserver );\n\t\tthis.listenTo( viewDocument, 'mousedown', ( ...args ) => this._onMousedown( ...args ) );\n\n\t\t// There are two keydown listeners working on different priorities. This allows other\n\t\t// features such as WidgetTypeAround or TableKeyboard to attach their listeners in between\n\t\t// and customize the behavior even further in different content/selection scenarios.\n\t\t//\n\t\t// * The first listener handles changing the selection on arrow key press\n\t\t// if the widget is selected or if the selection is next to a widget and the widget\n\t\t// should become selected upon the arrow key press.\n\t\t//\n\t\t// * The second (late) listener makes sure the default browser action on arrow key press is\n\t\t// prevented when a widget is selected. This prevents the selection from being moved\n\t\t// from a fake selection container.\n\t\tthis.listenTo( viewDocument, 'keydown', ( ...args ) => {\n\t\t\tthis._handleSelectionChangeOnArrowKeyPress( ...args );\n\t\t}, { priority: 'high' } );\n\n\t\tthis.listenTo( viewDocument, 'keydown', ( ...args ) => {\n\t\t\tthis._preventDefaultOnArrowKeyPress( ...args );\n\t\t}, { priority: priorities.get( 'high' ) - 20 } );\n\n\t\tthis.listenTo( viewDocument, 'keydown', verticalNavigationHandler( this.editor.editing ) );\n\n\t\t// Handle custom delete behaviour.\n\t\tthis.listenTo( viewDocument, 'delete', ( evt, data ) => {\n\t\t\tif ( this._handleDelete( data.direction == 'forward' ) ) {\n\t\t\t\tdata.preventDefault();\n\t\t\t\tevt.stop();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\t}\n\n\t/**\n\t * Handles {@link module:engine/view/document~Document#event:mousedown mousedown} events on widget elements.\n\t *\n\t * @private\n\t * @param {module:utils/eventinfo~EventInfo} eventInfo\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData\n\t */\n\t_onMousedown( eventInfo, domEventData ) {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\t\tlet element = domEventData.target;\n\n\t\t// Do nothing for single or double click inside nested editable.\n\t\tif ( isInsideNestedEditable( element ) ) {\n\t\t\t// But at least triple click inside nested editable causes broken selection in Safari.\n\t\t\t// For such event, we select the entire nested editable element.\n\t\t\t// See: https://github.com/ckeditor/ckeditor5/issues/1463.\n\t\t\tif ( ( env.isSafari || env.isGecko ) && domEventData.domEvent.detail >= 3 ) {\n\t\t\t\tconst mapper = editor.editing.mapper;\n\t\t\t\tconst viewElement = element.is( 'attributeElement' ) ?\n\t\t\t\t\telement.findAncestor( element => !element.is( 'attributeElement' ) ) : element;\n\t\t\t\tconst modelElement = mapper.toModelElement( viewElement );\n\n\t\t\t\tdomEventData.preventDefault();\n\n\t\t\t\tthis.editor.model.change( writer => {\n\t\t\t\t\twriter.setSelection( modelElement, 'in' );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If target is not a widget element - check if one of the ancestors is.\n\t\tif ( !isWidget( element ) ) {\n\t\t\telement = element.findAncestor( isWidget );\n\n\t\t\tif ( !element ) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tdomEventData.preventDefault();\n\n\t\t// Focus editor if is not focused already.\n\t\tif ( !viewDocument.isFocused ) {\n\t\t\tview.focus();\n\t\t}\n\n\t\t// Create model selection over widget.\n\t\tconst modelElement = editor.editing.mapper.toModelElement( element );\n\n\t\tthis._setSelectionOverElement( modelElement );\n\t}\n\n\t/**\n\t * Handles {@link module:engine/view/document~Document#event:keydown keydown} events and changes\n\t * the model selection when:\n\t *\n\t * * arrow key is pressed when the widget is selected,\n\t * * the selection is next to a widget and the widget should become selected upon the arrow key press.\n\t *\n\t * See {@link #_preventDefaultOnArrowKeyPress}.\n\t *\n\t * @private\n\t * @param {module:utils/eventinfo~EventInfo} eventInfo\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData\n\t */\n\t_handleSelectionChangeOnArrowKeyPress( eventInfo, domEventData ) {\n\t\tconst keyCode = domEventData.keyCode;\n\n\t\t// Checks if the keys were handled and then prevents the default event behaviour and stops\n\t\t// the propagation.\n\t\tif ( !isArrowKeyCode( keyCode ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst modelSelection = model.document.selection;\n\t\tconst objectElement = modelSelection.getSelectedElement();\n\t\tconst isForward = isForwardArrowKeyCode( keyCode, this.editor.locale.contentLanguageDirection );\n\n\t\t// If object element is selected.\n\t\tif ( objectElement && schema.isObject( objectElement ) ) {\n\t\t\tconst position = isForward ? modelSelection.getLastPosition() : modelSelection.getFirstPosition();\n\t\t\tconst newRange = schema.getNearestSelectionRange( position, isForward ? 'forward' : 'backward' );\n\n\t\t\tif ( newRange ) {\n\t\t\t\tmodel.change( writer => {\n\t\t\t\t\twriter.setSelection( newRange );\n\t\t\t\t} );\n\n\t\t\t\tdomEventData.preventDefault();\n\t\t\t\teventInfo.stop();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\t// If selection is next to object element.\n\t\t// Return if not collapsed.\n\t\tif ( !modelSelection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst objectElementNextToSelection = this._getObjectElementNextToSelection( isForward );\n\n\t\tif ( objectElementNextToSelection && schema.isObject( objectElementNextToSelection ) ) {\n\t\t\tthis._setSelectionOverElement( objectElementNextToSelection );\n\n\t\t\tdomEventData.preventDefault();\n\t\t\teventInfo.stop();\n\t\t}\n\t}\n\n\t/**\n\t * Handles {@link module:engine/view/document~Document#event:keydown keydown} events and prevents\n\t * the default browser behavior to make sure the fake selection is not being moved from a fake selection\n\t * container.\n\t *\n\t * See {@link #_handleSelectionChangeOnArrowKeyPress}.\n\t *\n\t * @private\n\t * @param {module:utils/eventinfo~EventInfo} eventInfo\n\t * @param {module:engine/view/observer/domeventdata~DomEventData} domEventData\n\t */\n\t_preventDefaultOnArrowKeyPress( eventInfo, domEventData ) {\n\t\tconst keyCode = domEventData.keyCode;\n\n\t\t// Checks if the keys were handled and then prevents the default event behaviour and stops\n\t\t// the propagation.\n\t\tif ( !isArrowKeyCode( keyCode ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst objectElement = model.document.selection.getSelectedElement();\n\n\t\t// If object element is selected.\n\t\tif ( objectElement && schema.isObject( objectElement ) ) {\n\t\t\tdomEventData.preventDefault();\n\t\t\teventInfo.stop();\n\t\t}\n\t}\n\n\t/**\n\t * Handles delete keys: backspace and delete.\n\t *\n\t * @private\n\t * @param {Boolean} isForward Set to true if delete was performed in forward direction.\n\t * @returns {Boolean|undefined} Returns `true` if keys were handled correctly.\n\t */\n\t_handleDelete( isForward ) {\n\t\t// Do nothing when the read only mode is enabled.\n\t\tif ( this.editor.isReadOnly ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst modelDocument = this.editor.model.document;\n\t\tconst modelSelection = modelDocument.selection;\n\n\t\t// Do nothing on non-collapsed selection.\n\t\tif ( !modelSelection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst objectElement = this._getObjectElementNextToSelection( isForward );\n\n\t\tif ( objectElement ) {\n\t\t\tthis.editor.model.change( writer => {\n\t\t\t\tlet previousNode = modelSelection.anchor.parent;\n\n\t\t\t\t// Remove previous element if empty.\n\t\t\t\twhile ( previousNode.isEmpty ) {\n\t\t\t\t\tconst nodeToRemove = previousNode;\n\t\t\t\t\tpreviousNode = nodeToRemove.parent;\n\n\t\t\t\t\twriter.remove( nodeToRemove );\n\t\t\t\t}\n\n\t\t\t\tthis._setSelectionOverElement( objectElement );\n\t\t\t} );\n\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t/**\n\t * Sets {@link module:engine/model/selection~Selection document's selection} over given element.\n\t *\n\t * @protected\n\t * @param {module:engine/model/element~Element} element\n\t */\n\t_setSelectionOverElement( element ) {\n\t\tthis.editor.model.change( writer => {\n\t\t\twriter.setSelection( writer.createRangeOn( element ) );\n\t\t} );\n\t}\n\n\t/**\n\t * Checks if {@link module:engine/model/element~Element element} placed next to the current\n\t * {@link module:engine/model/selection~Selection model selection} exists and is marked in\n\t * {@link module:engine/model/schema~Schema schema} as `object`.\n\t *\n\t * @protected\n\t * @param {Boolean} forward Direction of checking.\n\t * @returns {module:engine/model/element~Element|null}\n\t */\n\t_getObjectElementNextToSelection( forward ) {\n\t\tconst model = this.editor.model;\n\t\tconst schema = model.schema;\n\t\tconst modelSelection = model.document.selection;\n\n\t\t// Clone current selection to use it as a probe. We must leave default selection as it is so it can return\n\t\t// to its current state after undo.\n\t\tconst probe = model.createSelection( modelSelection );\n\t\tmodel.modifySelection( probe, { direction: forward ? 'forward' : 'backward' } );\n\t\tconst objectElement = forward ? probe.focus.nodeBefore : probe.focus.nodeAfter;\n\n\t\tif ( !!objectElement && schema.isObject( objectElement ) ) {\n\t\t\treturn objectElement;\n\t\t}\n\n\t\treturn null;\n\t}\n\n\t/**\n\t * Removes CSS class from previously selected widgets.\n\t *\n\t * @private\n\t * @param {module:engine/view/downcastwriter~DowncastWriter} writer\n\t */\n\t_clearPreviouslySelectedWidgets( writer ) {\n\t\tfor ( const widget of this._previouslySelected ) {\n\t\t\twriter.removeClass( WIDGET_SELECTED_CLASS_NAME, widget );\n\t\t}\n\n\t\tthis._previouslySelected.clear();\n\t}\n}\n\n// Returns `true` when element is a nested editable or is placed inside one.\n//\n// @param {module:engine/view/element~Element}\n// @returns {Boolean}\nfunction isInsideNestedEditable( element ) {\n\twhile ( element ) {\n\t\tif ( element.is( 'editableElement' ) && !element.is( 'rootElement' ) ) {\n\t\t\treturn true;\n\t\t}\n\n\t\t// Click on nested widget should select it.\n\t\tif ( isWidget( element ) ) {\n\t\t\treturn false;\n\t\t}\n\n\t\telement = element.parent;\n\t}\n\n\treturn false;\n}\n\n// Checks whether the specified `element` is a child of the `parent` element.\n//\n// @param {module:engine/view/element~Element} element An element to check.\n// @param {module:engine/view/element~Element|null} parent A parent for the element.\n// @returns {Boolean}\nfunction isChild( element, parent ) {\n\tif ( !parent ) {\n\t\treturn false;\n\t}\n\n\treturn Array.from( element.getAncestors() ).includes( parent );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/widgettoolbarrepository\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon';\nimport ToolbarView from '@ckeditor/ckeditor5-ui/src/toolbar/toolbarview';\nimport BalloonPanelView from '@ckeditor/ckeditor5-ui/src/panel/balloon/balloonpanelview';\nimport {\n\tisWidget,\n\tcenteredBalloonPositionForLongWidgets\n} from './utils';\nimport CKEditorError, { logWarning } from '@ckeditor/ckeditor5-utils/src/ckeditorerror';\n\n/**\n * Widget toolbar repository plugin. A central point for registering widget toolbars. This plugin handles the whole\n * toolbar rendering process and exposes a concise API.\n *\n * To add a toolbar for your widget use the {@link ~WidgetToolbarRepository#register `WidgetToolbarRepository#register()`} method.\n *\n * The following example comes from the {@link module:image/imagetoolbar~ImageToolbar} plugin:\n *\n * \t\tclass ImageToolbar extends Plugin {\n *\t\t\tstatic get requires() {\n *\t\t\t\treturn [ WidgetToolbarRepository ];\n *\t\t\t}\n *\n *\t\t\tafterInit() {\n *\t\t\t\tconst editor = this.editor;\n *\t\t\t\tconst widgetToolbarRepository = editor.plugins.get( WidgetToolbarRepository );\n *\n *\t\t\t\twidgetToolbarRepository.register( 'image', {\n *\t\t\t\t\titems: editor.config.get( 'image.toolbar' ),\n *\t\t\t\t\tgetRelatedElement: getSelectedImageWidget\n *\t\t\t\t} );\n *\t\t\t}\n *\t\t}\n */\nexport default class WidgetToolbarRepository extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get requires() {\n\t\treturn [ ContextualBalloon ];\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'WidgetToolbarRepository';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Disables the default balloon toolbar for all widgets.\n\t\tif ( editor.plugins.has( 'BalloonToolbar' ) ) {\n\t\t\tconst balloonToolbar = editor.plugins.get( 'BalloonToolbar' );\n\n\t\t\tthis.listenTo( balloonToolbar, 'show', evt => {\n\t\t\t\tif ( isWidgetSelected( editor.editing.view.document.selection ) ) {\n\t\t\t\t\tevt.stop();\n\t\t\t\t}\n\t\t\t}, { priority: 'high' } );\n\t\t}\n\n\t\t/**\n\t\t * A map of toolbar definitions.\n\t\t *\n\t\t * @protected\n\t\t * @member {Map.} #_toolbarDefinitions\n\t\t */\n\t\tthis._toolbarDefinitions = new Map();\n\n\t\t/**\n\t\t * @private\n\t\t */\n\t\tthis._balloon = this.editor.plugins.get( 'ContextualBalloon' );\n\n\t\tthis.on( 'change:isEnabled', () => {\n\t\t\tthis._updateToolbarsVisibility();\n\t\t} );\n\n\t\tthis.listenTo( editor.ui, 'update', () => {\n\t\t\tthis._updateToolbarsVisibility();\n\t\t} );\n\n\t\t// UI#update is not fired after focus is back in editor, we need to check if balloon panel should be visible.\n\t\tthis.listenTo( editor.ui.focusTracker, 'change:isFocused', () => {\n\t\t\tthis._updateToolbarsVisibility();\n\t\t}, { priority: 'low' } );\n\t}\n\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tfor ( const toolbarConfig of this._toolbarDefinitions.values() ) {\n\t\t\ttoolbarConfig.view.destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Registers toolbar in the WidgetToolbarRepository. It renders it in the `ContextualBalloon` based on the value of the invoked\n\t * `getRelatedElement` function. Toolbar items are gathered from `items` array.\n\t * The balloon's CSS class is by default `ck-toolbar-container` and may be override with the `balloonClassName` option.\n\t *\n\t * Note: This method should be called in the {@link module:core/plugin~PluginInterface#afterInit `Plugin#afterInit()`}\n\t * callback (or later) to make sure that the given toolbar items were already registered by other plugins.\n\t *\n\t * @param {String} toolbarId An id for the toolbar. Used to\n\t * @param {Object} options\n\t * @param {String} [options.ariaLabel] Label used by assistive technologies to describe this toolbar element.\n\t * @param {Array.} options.items Array of toolbar items.\n\t * @param {Function} options.getRelatedElement Callback which returns an element the toolbar should be attached to.\n\t * @param {String} [options.balloonClassName='ck-toolbar-container'] CSS class for the widget balloon.\n\t */\n\tregister( toolbarId, { ariaLabel, items, getRelatedElement, balloonClassName = 'ck-toolbar-container' } ) {\n\t\t// Trying to register a toolbar without any item.\n\t\tif ( !items.length ) {\n\t\t\t/**\n\t\t\t * When {@link #register} a new toolbar, you need to provide a non-empty array with\n\t\t\t * the items that will be inserted into the toolbar.\n\t\t\t *\n\t\t\t * @error widget-toolbar-no-items\n\t\t\t */\n\t\t\tlogWarning( 'widget-toolbar-no-items', { toolbarId } );\n\n\t\t\treturn;\n\t\t}\n\n\t\tconst editor = this.editor;\n\t\tconst t = editor.t;\n\t\tconst toolbarView = new ToolbarView( editor.locale );\n\n\t\ttoolbarView.ariaLabel = ariaLabel || t( 'Widget toolbar' );\n\n\t\tif ( this._toolbarDefinitions.has( toolbarId ) ) {\n\t\t\t/**\n\t\t\t * Toolbar with the given id was already added.\n\t\t\t *\n\t\t\t * @error widget-toolbar-duplicated\n\t\t\t * @param toolbarId Toolbar id.\n\t\t\t */\n\t\t\tthrow new CKEditorError( 'widget-toolbar-duplicated', this, { toolbarId } );\n\t\t}\n\n\t\ttoolbarView.fillFromConfig( items, editor.ui.componentFactory );\n\n\t\tthis._toolbarDefinitions.set( toolbarId, {\n\t\t\tview: toolbarView,\n\t\t\tgetRelatedElement,\n\t\t\tballoonClassName\n\t\t} );\n\t}\n\n\t/**\n\t * Iterates over stored toolbars and makes them visible or hidden.\n\t *\n\t * @private\n\t */\n\t_updateToolbarsVisibility() {\n\t\tlet maxRelatedElementDepth = 0;\n\t\tlet deepestRelatedElement = null;\n\t\tlet deepestToolbarDefinition = null;\n\n\t\tfor ( const definition of this._toolbarDefinitions.values() ) {\n\t\t\tconst relatedElement = definition.getRelatedElement( this.editor.editing.view.document.selection );\n\n\t\t\tif ( !this.isEnabled || !relatedElement ) {\n\t\t\t\tif ( this._isToolbarInBalloon( definition ) ) {\n\t\t\t\t\tthis._hideToolbar( definition );\n\t\t\t\t}\n\t\t\t} else if ( !this.editor.ui.focusTracker.isFocused ) {\n\t\t\t\tif ( this._isToolbarVisible( definition ) ) {\n\t\t\t\t\tthis._hideToolbar( definition );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tconst relatedElementDepth = relatedElement.getAncestors().length;\n\n\t\t\t\t// Many toolbars can express willingness to be displayed but they do not know about\n\t\t\t\t// each other. Figure out which toolbar is deepest in the view tree to decide which\n\t\t\t\t// should be displayed. For instance, if a selected image is inside a table cell, display\n\t\t\t\t// the ImageToolbar rather than the TableToolbar (#60).\n\t\t\t\tif ( relatedElementDepth > maxRelatedElementDepth ) {\n\t\t\t\t\tmaxRelatedElementDepth = relatedElementDepth;\n\t\t\t\t\tdeepestRelatedElement = relatedElement;\n\t\t\t\t\tdeepestToolbarDefinition = definition;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( deepestToolbarDefinition ) {\n\t\t\tthis._showToolbar( deepestToolbarDefinition, deepestRelatedElement );\n\t\t}\n\t}\n\n\t/**\n\t * Hides the given toolbar.\n\t *\n\t * @private\n\t * @param {module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition} toolbarDefinition\n\t */\n\t_hideToolbar( toolbarDefinition ) {\n\t\tthis._balloon.remove( toolbarDefinition.view );\n\t\tthis.stopListening( this._balloon, 'change:visibleView' );\n\t}\n\n\t/**\n\t * Shows up the toolbar if the toolbar is not visible.\n\t * Otherwise, repositions the toolbar's balloon when toolbar's view is the most top view in balloon stack.\n\t *\n\t * It might happen here that the toolbar's view is under another view. Then do nothing as the other toolbar view\n\t * should be still visible after the {@link module:core/editor/editorui~EditorUI#event:update}.\n\t *\n\t * @private\n\t * @param {module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition} toolbarDefinition\n\t * @param {module:engine/view/element~Element} relatedElement\n\t */\n\t_showToolbar( toolbarDefinition, relatedElement ) {\n\t\tif ( this._isToolbarVisible( toolbarDefinition ) ) {\n\t\t\trepositionContextualBalloon( this.editor, relatedElement );\n\t\t} else if ( !this._isToolbarInBalloon( toolbarDefinition ) ) {\n\t\t\tthis._balloon.add( {\n\t\t\t\tview: toolbarDefinition.view,\n\t\t\t\tposition: getBalloonPositionData( this.editor, relatedElement ),\n\t\t\t\tballoonClassName: toolbarDefinition.balloonClassName\n\t\t\t} );\n\n\t\t\t// Update toolbar position each time stack with toolbar view is switched to visible.\n\t\t\t// This is in a case target element has changed when toolbar was in invisible stack\n\t\t\t// e.g. target image was wrapped by a block quote.\n\t\t\t// See https://github.com/ckeditor/ckeditor5-widget/issues/92.\n\t\t\tthis.listenTo( this._balloon, 'change:visibleView', () => {\n\t\t\t\tfor ( const definition of this._toolbarDefinitions.values() ) {\n\t\t\t\t\tif ( this._isToolbarVisible( definition ) ) {\n\t\t\t\t\t\tconst relatedElement = definition.getRelatedElement( this.editor.editing.view.document.selection );\n\t\t\t\t\t\trepositionContextualBalloon( this.editor, relatedElement );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * @private\n\t * @param {Object} toolbar\n\t * @returns {Boolean}\n\t */\n\t_isToolbarVisible( toolbar ) {\n\t\treturn this._balloon.visibleView === toolbar.view;\n\t}\n\n\t/**\n\t * @private\n\t * @param {Object} toolbar\n\t * @returns {Boolean}\n\t */\n\t_isToolbarInBalloon( toolbar ) {\n\t\treturn this._balloon.hasView( toolbar.view );\n\t}\n}\n\nfunction repositionContextualBalloon( editor, relatedElement ) {\n\tconst balloon = editor.plugins.get( 'ContextualBalloon' );\n\tconst position = getBalloonPositionData( editor, relatedElement );\n\n\tballoon.updatePosition( position );\n}\n\nfunction getBalloonPositionData( editor, relatedElement ) {\n\tconst editingView = editor.editing.view;\n\tconst defaultPositions = BalloonPanelView.defaultPositions;\n\n\treturn {\n\t\ttarget: editingView.domConverter.mapViewToDom( relatedElement ),\n\t\tpositions: [\n\t\t\tdefaultPositions.northArrowSouth,\n\t\t\tdefaultPositions.northArrowSouthWest,\n\t\t\tdefaultPositions.northArrowSouthEast,\n\t\t\tdefaultPositions.southArrowNorth,\n\t\t\tdefaultPositions.southArrowNorthWest,\n\t\t\tdefaultPositions.southArrowNorthEast,\n\t\t\tcenteredBalloonPositionForLongWidgets\n\t\t]\n\t};\n}\n\nfunction isWidgetSelected( selection ) {\n\tconst viewElement = selection.getSelectedElement();\n\n\treturn !!( viewElement && isWidget( viewElement ) );\n}\n\n/**\n * The toolbar definition object used by the toolbar repository to manage toolbars.\n * It contains information necessary to display the toolbar in the\n * {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon} and\n * update it during its life (display) cycle.\n *\n * @typedef {Object} module:widget/widgettoolbarrepository~WidgetRepositoryToolbarDefinition\n *\n * @property {module:ui/view~View} view The UI view of the toolbar.\n * @property {Function} getRelatedElement A function that returns an engine {@link module:engine/view/view~View}\n * element the toolbar is to be attached to. For instance, an image widget or a table widget (or `null` when\n * there is no such element). The function accepts an instance of {@link module:engine/view/selection~Selection}.\n * @property {String} balloonClassName CSS class for the widget balloon when a toolbar is displayed.\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/widgetresize/resizerstate\n */\n\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\n/**\n * Stores the internal state of a single resizable object.\n *\n */\nexport default class ResizeState {\n\t/**\n\t * @param {module:widget/widgetresize~ResizerOptions} options Resizer options.\n\t */\n\tconstructor( options ) {\n\t\t/**\n\t\t * The original width (pixels) of the resized object when the resize process was started.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #originalWidth\n\t\t */\n\n\t\t/**\n\t\t * The original height (pixels) of the resized object when the resize process was started.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #originalHeight\n\t\t */\n\n\t\t/**\n\t\t * The original width (percents) of the resized object when the resize process was started.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #originalWidthPercents\n\t\t */\n\n\t\t/**\n\t\t * The position of the handle that initiated the resizing. E.g. `\"top-left\"`, `\"bottom-right\"` etc. or `null`\n\t\t * if unknown.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {String|null} #activeHandlePosition\n\t\t */\n\t\tthis.set( 'activeHandlePosition', null );\n\n\t\t/**\n\t\t * The width (percents) proposed, but not committed yet, in the current resize process.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #proposedWidthPercents\n\t\t */\n\t\tthis.set( 'proposedWidthPercents', null );\n\n\t\t/**\n\t\t * The width (pixels) proposed, but not committed yet, in the current resize process.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #proposedWidthPixels\n\t\t */\n\t\tthis.set( 'proposedWidth', null );\n\n\t\t/**\n\t\t * The height (pixels) proposed, but not committed yet, in the current resize process.\n\t\t *\n\t\t * @readonly\n\t\t * @observable\n\t\t * @member {Number|null} #proposedHeightPixels\n\t\t */\n\t\tthis.set( 'proposedHeight', null );\n\n\t\tthis.set( 'proposedHandleHostWidth', null );\n\t\tthis.set( 'proposedHandleHostHeight', null );\n\n\t\t/**\n\t\t * A width to height ratio of the resized image.\n\t\t *\n\t\t * @readonly\n\t\t * @member {Number} #aspectRatio\n\t\t */\n\n\t\t/**\n\t\t * @private\n\t\t * @type {module:widget/widgetresize~ResizerOptions}\n\t\t */\n\t\tthis._options = options;\n\n\t\t/**\n\t\t * The reference point of the resizer where the dragging started. It is used to measure the distance the user cursor\n\t\t * traveled, so how much the image should be enlarged.\n\t\t * This information is only known after the DOM was rendered, so it will be updated later.\n\t\t *\n\t\t * @private\n\t\t * @type {Object}\n\t\t */\n\t\tthis._referenceCoordinates = null;\n\t}\n\n\t/**\n\t *\n\t * @param {HTMLElement} domResizeHandle The handle used to calculate the reference point.\n\t * @param {HTMLElement} domHandleHost\n\t * @param {HTMLElement} domResizeHost\n\t */\n\tbegin( domResizeHandle, domHandleHost, domResizeHost ) {\n\t\tconst clientRect = new Rect( domHandleHost );\n\n\t\tthis.activeHandlePosition = getHandlePosition( domResizeHandle );\n\n\t\tthis._referenceCoordinates = getAbsoluteBoundaryPoint( domHandleHost, getOppositePosition( this.activeHandlePosition ) );\n\n\t\tthis.originalWidth = clientRect.width;\n\t\tthis.originalHeight = clientRect.height;\n\n\t\tthis.aspectRatio = clientRect.width / clientRect.height;\n\n\t\tconst widthStyle = domResizeHost.style.width;\n\n\t\tif ( widthStyle && widthStyle.match( /^\\d+\\.?\\d*%$/ ) ) {\n\t\t\tthis.originalWidthPercents = parseFloat( widthStyle );\n\t\t} else {\n\t\t\tthis.originalWidthPercents = calculateHostPercentageWidth( domResizeHost, clientRect );\n\t\t}\n\t}\n\n\tupdate( newSize ) {\n\t\tthis.proposedWidth = newSize.width;\n\t\tthis.proposedHeight = newSize.height;\n\t\tthis.proposedWidthPercents = newSize.widthPercents;\n\n\t\tthis.proposedHandleHostWidth = newSize.handleHostWidth;\n\t\tthis.proposedHandleHostHeight = newSize.handleHostHeight;\n\t}\n}\n\nmix( ResizeState, ObservableMixin );\n\n// Calculates a relative width of a `domResizeHost` compared to it's parent in percents.\n//\n// @private\n// @param {HTMLElement} domResizeHost\n// @param {module:utils/dom/rect~Rect} resizeHostRect\n// @returns {Number}\nfunction calculateHostPercentageWidth( domResizeHost, resizeHostRect ) {\n\tconst domResizeHostParent = domResizeHost.parentElement;\n\t// Need to use computed style as it properly excludes parent's paddings from the returned value.\n\tconst parentWidth = parseFloat( domResizeHostParent.ownerDocument.defaultView.getComputedStyle( domResizeHostParent ).width );\n\n\treturn resizeHostRect.width / parentWidth * 100;\n}\n\n// Returns coordinates of the top-left corner of an element, relative to the document's top-left corner.\n//\n// @private\n// @param {HTMLElement} element\n// @param {String} resizerPosition The position of the resize handle, e.g. `\"top-left\"`, `\"bottom-right\"`.\n// @returns {Object} return\n// @returns {Number} return.x\n// @returns {Number} return.y\nfunction getAbsoluteBoundaryPoint( element, resizerPosition ) {\n\tconst elementRect = new Rect( element );\n\tconst positionParts = resizerPosition.split( '-' );\n\tconst ret = {\n\t\tx: positionParts[ 1 ] == 'right' ? elementRect.right : elementRect.left,\n\t\ty: positionParts[ 0 ] == 'bottom' ? elementRect.bottom : elementRect.top\n\t};\n\n\tret.x += element.ownerDocument.defaultView.scrollX;\n\tret.y += element.ownerDocument.defaultView.scrollY;\n\n\treturn ret;\n}\n\n// @private\n// @param {String} resizerPosition The expected resizer position, like `\"top-left\"`, `\"bottom-right\"`.\n// @returns {String} A prefixed HTML class name for the resizer element.\nfunction getResizerHandleClass( resizerPosition ) {\n\treturn `ck-widget__resizer__handle-${ resizerPosition }`;\n}\n\n// Determines the position of a given resize handle.\n//\n// @private\n// @param {HTMLElement} domHandle Handle used to calculate the reference point.\n// @returns {String|undefined} Returns a string like `\"top-left\"` or `undefined` if not matched.\nfunction getHandlePosition( domHandle ) {\n\tconst resizerPositions = [ 'top-left', 'top-right', 'bottom-right', 'bottom-left' ];\n\n\tfor ( const position of resizerPositions ) {\n\t\tif ( domHandle.classList.contains( getResizerHandleClass( position ) ) ) {\n\t\t\treturn position;\n\t\t}\n\t}\n}\n\n// @private\n// @param {String} position Like `\"top-left\"`.\n// @returns {String} Inverted `position`, e.g. it returns `\"bottom-right\"` if `\"top-left\"` was given as `position`.\nfunction getOppositePosition( position ) {\n\tconst parts = position.split( '-' );\n\tconst replacements = {\n\t\ttop: 'bottom',\n\t\tbottom: 'top',\n\t\tleft: 'right',\n\t\tright: 'left'\n\t};\n\n\treturn `${ replacements[ parts[ 0 ] ] }-${ replacements[ parts[ 1 ] ] }`;\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/widgetresize/resizer\n */\n\nimport View from '@ckeditor/ckeditor5-ui/src/view';\nimport Template from '@ckeditor/ckeditor5-ui/src/template';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport compareArrays from '@ckeditor/ckeditor5-utils/src/comparearrays';\n\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\n\nimport ResizeState from './resizerstate';\n\n/**\n * Represents a resizer for a single resizable object.\n *\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class Resizer {\n\t/**\n\t * @param {module:widget/widgetresize~ResizerOptions} options Resizer options.\n\t */\n\tconstructor( options ) {\n\t\t/**\n\t\t * Stores the state of the resizable host geometry, such as the original width, the currently proposed height, etc.\n\t\t *\n\t\t * Note that a new state is created for each resize transaction.\n\t\t *\n\t\t * @readonly\n\t\t * @member {module:widget/widgetresize/resizerstate~ResizerState} #state\n\t\t */\n\n\t\t/**\n\t\t * A view displaying the proposed new element size during the resizing.\n\t\t *\n\t\t * @protected\n\t\t * @readonly\n\t\t * @member {module:widget/widgetresize/resizer~SizeView} #_sizeUI\n\t\t */\n\n\t\t/**\n\t\t * Options passed to the {@link #constructor}.\n\t\t *\n\t\t * @private\n\t\t * @type {module:widget/widgetresize~ResizerOptions}\n\t\t */\n\t\tthis._options = options;\n\n\t\t/**\n\t\t * Container of the entire resize UI.\n\t\t *\n\t\t * Note that this property is initialized only after the element bound with the resizer is drawn\n\t\t * so it will be a `null` when uninitialized.\n\t\t *\n\t\t * @private\n\t\t * @type {HTMLElement|null}\n\t\t */\n\t\tthis._domResizerWrapper = null;\n\n\t\t/**\n\t\t * A wrapper that is controlled by the resizer. This is usually a widget element.\n\t\t *\n\t\t * @private\n\t\t * @type {module:engine/view/element~Element|null}\n\t\t */\n\t\tthis._viewResizerWrapper = null;\n\n\t\t/**\n\t\t * The width of the resized {@link module:widget/widgetresize~ResizerOptions#viewElement viewElement} before the resizing started.\n\t\t *\n\t\t * @private\n\t\t * @member {Number|String|undefined} #_initialViewWidth\n\t\t */\n\n\t\t/**\n\t\t * @observable\n\t\t */\n\t\tthis.set( 'isEnabled', true );\n\n\t\tthis.decorate( 'begin' );\n\t\tthis.decorate( 'cancel' );\n\t\tthis.decorate( 'commit' );\n\t\tthis.decorate( 'updateSize' );\n\n\t\tthis.on( 'commit', event => {\n\t\t\t// State might not be initialized yet. In this case, prevent further handling and make sure that the resizer is\n\t\t\t// cleaned up (#5195).\n\t\t\tif ( !this.state.proposedWidth && !this.state.proposedWidthPercents ) {\n\t\t\t\tthis._cleanup();\n\t\t\t\tevent.stop();\n\t\t\t}\n\t\t}, { priority: 'high' } );\n\n\t\tthis.on( 'change:isEnabled', () => {\n\t\t\t// We should redraw the resize handles when the plugin is enabled again.\n\t\t\t// Otherwise they won't show up.\n\t\t\tif ( this.isEnabled ) {\n\t\t\t\tthis.redraw();\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Attaches the resizer to the DOM.\n\t */\n\tattach() {\n\t\tconst that = this;\n\t\tconst widgetElement = this._options.viewElement;\n\t\tconst editingView = this._options.editor.editing.view;\n\n\t\teditingView.change( writer => {\n\t\t\tconst viewResizerWrapper = writer.createUIElement( 'div', {\n\t\t\t\tclass: 'ck ck-reset_all ck-widget__resizer'\n\t\t\t}, function( domDocument ) {\n\t\t\t\tconst domElement = this.toDomElement( domDocument );\n\n\t\t\t\tthat._appendHandles( domElement );\n\t\t\t\tthat._appendSizeUI( domElement );\n\n\t\t\t\tthat._domResizerWrapper = domElement;\n\n\t\t\t\tthat.on( 'change:isEnabled', ( evt, propName, newValue ) => {\n\t\t\t\t\tdomElement.style.display = newValue ? '' : 'none';\n\t\t\t\t} );\n\n\t\t\t\tdomElement.style.display = that.isEnabled ? '' : 'none';\n\n\t\t\t\treturn domElement;\n\t\t\t} );\n\n\t\t\t// Append the resizer wrapper to the widget's wrapper.\n\t\t\twriter.insert( writer.createPositionAt( widgetElement, 'end' ), viewResizerWrapper );\n\t\t\twriter.addClass( 'ck-widget_with-resizer', widgetElement );\n\n\t\t\tthis._viewResizerWrapper = viewResizerWrapper;\n\t\t} );\n\t}\n\n\t/**\n\t * Starts the resizing process.\n\t *\n\t * Creates a new {@link #state} for the current process.\n\t *\n\t * @fires begin\n\t * @param {HTMLElement} domResizeHandle Clicked handle.\n\t */\n\tbegin( domResizeHandle ) {\n\t\tthis.state = new ResizeState( this._options );\n\n\t\tthis._sizeUI.bindToState( this._options, this.state );\n\n\t\tthis._initialViewWidth = this._options.viewElement.getStyle( 'width' );\n\n\t\tthis.state.begin( domResizeHandle, this._getHandleHost(), this._getResizeHost() );\n\t}\n\n\t/**\n\t * Updates the proposed size based on `domEventData`.\n\t *\n\t * @fires updateSize\n\t * @param {Event} domEventData\n\t */\n\tupdateSize( domEventData ) {\n\t\tconst newSize = this._proposeNewSize( domEventData );\n\t\tconst editingView = this._options.editor.editing.view;\n\n\t\teditingView.change( writer => {\n\t\t\tconst unit = this._options.unit || '%';\n\t\t\tconst newWidth = ( unit === '%' ? newSize.widthPercents : newSize.width ) + unit;\n\n\t\t\twriter.setStyle( 'width', newWidth, this._options.viewElement );\n\t\t} );\n\n\t\t// Get an actual image width, and:\n\t\t// * reflect this size to the resize wrapper\n\t\t// * apply this **real** size to the state\n\t\tconst domHandleHost = this._getHandleHost();\n\t\tconst domHandleHostRect = new Rect( domHandleHost );\n\n\t\tnewSize.handleHostWidth = Math.round( domHandleHostRect.width );\n\t\tnewSize.handleHostHeight = Math.round( domHandleHostRect.height );\n\n\t\t// Handle max-width limitation.\n\t\tconst domResizeHostRect = new Rect( domHandleHost );\n\n\t\tnewSize.width = Math.round( domResizeHostRect.width );\n\t\tnewSize.height = Math.round( domResizeHostRect.height );\n\n\t\tthis.redraw( domHandleHostRect );\n\n\t\tthis.state.update( newSize );\n\t}\n\n\t/**\n\t * Applies the geometry proposed with the resizer.\n\t *\n\t * @fires commit\n\t */\n\tcommit() {\n\t\tconst unit = this._options.unit || '%';\n\t\tconst newValue = ( unit === '%' ? this.state.proposedWidthPercents : this.state.proposedWidth ) + unit;\n\n\t\t// Both cleanup and onCommit callback are very likely to make view changes. Ensure that it is made in a single step.\n\t\tthis._options.editor.editing.view.change( () => {\n\t\t\tthis._cleanup();\n\t\t\tthis._options.onCommit( newValue );\n\t\t} );\n\t}\n\n\t/**\n\t * Cancels and rejects the proposed resize dimensions, hiding the UI.\n\t *\n\t * @fires cancel\n\t */\n\tcancel() {\n\t\tthis._cleanup();\n\t}\n\n\t/**\n\t * Destroys the resizer.\n\t */\n\tdestroy() {\n\t\tthis.cancel();\n\t}\n\n\t/**\n\t * Redraws the resizer.\n\t *\n\t * @param {module:utils/dom/rect~Rect} [handleHostRect] Handle host rectangle might be given to improve performance.\n\t */\n\tredraw( handleHostRect ) {\n\t\tconst domWrapper = this._domResizerWrapper;\n\n\t\t// Refresh only if resizer exists in the DOM.\n\t\tif ( !existsInDom( domWrapper ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst widgetWrapper = domWrapper.parentElement;\n\t\tconst handleHost = this._getHandleHost();\n\t\tconst resizerWrapper = this._viewResizerWrapper;\n\t\tconst currentDimensions = [\n\t\t\tresizerWrapper.getStyle( 'width' ),\n\t\t\tresizerWrapper.getStyle( 'height' ),\n\t\t\tresizerWrapper.getStyle( 'left' ),\n\t\t\tresizerWrapper.getStyle( 'top' )\n\t\t];\n\t\tlet newDimensions;\n\n\t\tif ( widgetWrapper.isSameNode( handleHost ) ) {\n\t\t\tconst clientRect = handleHostRect || new Rect( handleHost );\n\n\t\t\tnewDimensions = [\n\t\t\t\tclientRect.width + 'px',\n\t\t\t\tclientRect.height + 'px',\n\t\t\t\tundefined,\n\t\t\t\tundefined\n\t\t\t];\n\t\t}\n\t\t// In case a resizing host is not a widget wrapper, we need to compensate\n\t\t// for any additional offsets the resize host might have. E.g. wrapper padding\n\t\t// or simply another editable. By doing that the border and resizers are shown\n\t\t// only around the resize host.\n\t\telse {\n\t\t\tnewDimensions = [\n\t\t\t\thandleHost.offsetWidth + 'px',\n\t\t\t\thandleHost.offsetHeight + 'px',\n\t\t\t\thandleHost.offsetLeft + 'px',\n\t\t\t\thandleHost.offsetTop + 'px'\n\t\t\t];\n\t\t}\n\n\t\t// Make changes to the view only if the resizer should actually get new dimensions.\n\t\t// Otherwise, if View#change() was always called, this would cause EditorUI#update\n\t\t// loops because the WidgetResize plugin listens to EditorUI#update and updates\n\t\t// the resizer.\n\t\t// https://github.com/ckeditor/ckeditor5/issues/7633\n\t\tif ( compareArrays( currentDimensions, newDimensions ) !== 'same' ) {\n\t\t\tthis._options.editor.editing.view.change( writer => {\n\t\t\t\twriter.setStyle( {\n\t\t\t\t\twidth: newDimensions[ 0 ],\n\t\t\t\t\theight: newDimensions[ 1 ],\n\t\t\t\t\tleft: newDimensions[ 2 ],\n\t\t\t\t\ttop: newDimensions[ 3 ]\n\t\t\t\t}, resizerWrapper );\n\t\t\t} );\n\t\t}\n\t}\n\n\tcontainsHandle( domElement ) {\n\t\treturn this._domResizerWrapper.contains( domElement );\n\t}\n\n\tstatic isResizeHandle( domElement ) {\n\t\treturn domElement.classList.contains( 'ck-widget__resizer__handle' );\n\t}\n\n\t/**\n\t * Cleans up the context state.\n\t *\n\t * @protected\n\t */\n\t_cleanup() {\n\t\tthis._sizeUI.dismiss();\n\t\tthis._sizeUI.isVisible = false;\n\n\t\tconst editingView = this._options.editor.editing.view;\n\n\t\teditingView.change( writer => {\n\t\t\twriter.setStyle( 'width', this._initialViewWidth, this._options.viewElement );\n\t\t} );\n\t}\n\n\t/**\n\t * Calculates the proposed size as the resize handles are dragged.\n\t *\n\t * @private\n\t * @param {Event} domEventData Event data that caused the size update request. It should be used to calculate the proposed size.\n\t * @returns {Object} return\n\t * @returns {Number} return.width Proposed width.\n\t * @returns {Number} return.height Proposed height.\n\t */\n\t_proposeNewSize( domEventData ) {\n\t\tconst state = this.state;\n\t\tconst currentCoordinates = extractCoordinates( domEventData );\n\t\tconst isCentered = this._options.isCentered ? this._options.isCentered( this ) : true;\n\n\t\t// Enlargement defines how much the resize host has changed in a given axis. Naturally it could be a negative number\n\t\t// meaning that it has been shrunk.\n\t\t//\n\t\t// +----------------+--+\n\t\t// | | |\n\t\t// | img | |\n\t\t// | /handle host | |\n\t\t// +----------------+ | ^\n\t\t// | | | - enlarge y\n\t\t// +-------------------+ v\n\t\t// \t\t\t\t\t<-->\n\t\t// \t\t\t\t\t enlarge x\n\t\tconst enlargement = {\n\t\t\tx: state._referenceCoordinates.x - ( currentCoordinates.x + state.originalWidth ),\n\t\t\ty: ( currentCoordinates.y - state.originalHeight ) - state._referenceCoordinates.y\n\t\t};\n\n\t\tif ( isCentered && state.activeHandlePosition.endsWith( '-right' ) ) {\n\t\t\tenlargement.x = currentCoordinates.x - ( state._referenceCoordinates.x + state.originalWidth );\n\t\t}\n\n\t\t// Objects needs to be resized twice as much in horizontal axis if centered, since enlargement is counted from\n\t\t// one resized corner to your cursor. It needs to be duplicated to compensate for the other side too.\n\t\tif ( isCentered ) {\n\t\t\tenlargement.x *= 2;\n\t\t}\n\n\t\t// const resizeHost = this._getResizeHost();\n\n\t\t// The size proposed by the user. It does not consider the aspect ratio.\n\t\tconst proposedSize = {\n\t\t\twidth: Math.abs( state.originalWidth + enlargement.x ),\n\t\t\theight: Math.abs( state.originalHeight + enlargement.y )\n\t\t};\n\n\t\t// Dominant determination must take the ratio into account.\n\t\tproposedSize.dominant = proposedSize.width / state.aspectRatio > proposedSize.height ? 'width' : 'height';\n\t\tproposedSize.max = proposedSize[ proposedSize.dominant ];\n\n\t\t// Proposed size, respecting the aspect ratio.\n\t\tconst targetSize = {\n\t\t\twidth: proposedSize.width,\n\t\t\theight: proposedSize.height\n\t\t};\n\n\t\tif ( proposedSize.dominant == 'width' ) {\n\t\t\ttargetSize.height = targetSize.width / state.aspectRatio;\n\t\t} else {\n\t\t\ttargetSize.width = targetSize.height * state.aspectRatio;\n\t\t}\n\n\t\treturn {\n\t\t\twidth: Math.round( targetSize.width ),\n\t\t\theight: Math.round( targetSize.height ),\n\t\t\twidthPercents: Math.min( Math.round( state.originalWidthPercents / state.originalWidth * targetSize.width * 100 ) / 100, 100 )\n\t\t};\n\t}\n\n\t/**\n\t * Obtains the resize host.\n\t *\n\t * Resize host is an object that receives dimensions which are the result of resizing.\n\t *\n\t * @protected\n\t * @returns {HTMLElement}\n\t */\n\t_getResizeHost() {\n\t\tconst widgetWrapper = this._domResizerWrapper.parentElement;\n\n\t\treturn this._options.getResizeHost( widgetWrapper );\n\t}\n\n\t/**\n\t * Obtains the handle host.\n\t *\n\t * Handle host is an object that the handles are aligned to.\n\t *\n\t * Handle host will not always be an entire widget itself. Take an image as an example. The image widget\n\t * contains an image and a caption. Only the image should be surrounded with handles.\n\t *\n\t * @protected\n\t * @returns {HTMLElement}\n\t */\n\t_getHandleHost() {\n\t\tconst widgetWrapper = this._domResizerWrapper.parentElement;\n\n\t\treturn this._options.getHandleHost( widgetWrapper );\n\t}\n\n\t/**\n\t * Renders the resize handles in the DOM.\n\t *\n\t * @private\n\t * @param {HTMLElement} domElement The resizer wrapper.\n\t */\n\t_appendHandles( domElement ) {\n\t\tconst resizerPositions = [ 'top-left', 'top-right', 'bottom-right', 'bottom-left' ];\n\n\t\tfor ( const currentPosition of resizerPositions ) {\n\t\t\tdomElement.appendChild( ( new Template( {\n\t\t\t\ttag: 'div',\n\t\t\t\tattributes: {\n\t\t\t\t\tclass: `ck-widget__resizer__handle ${ getResizerClass( currentPosition ) }`\n\t\t\t\t}\n\t\t\t} ).render() ) );\n\t\t}\n\t}\n\n\t/**\n\t * Sets up the {@link #_sizeUI} property and adds it to the passed `domElement`.\n\t *\n\t * @private\n\t * @param {HTMLElement} domElement\n\t */\n\t_appendSizeUI( domElement ) {\n\t\tconst sizeUI = new SizeView();\n\n\t\t// Make sure icon#element is rendered before passing to appendChild().\n\t\tsizeUI.render();\n\n\t\tthis._sizeUI = sizeUI;\n\n\t\tdomElement.appendChild( sizeUI.element );\n\t}\n\n\t/**\n\t * @event begin\n\t */\n\n\t/**\n\t * @event updateSize\n\t */\n\n\t/**\n\t * @event commit\n\t */\n\n\t/**\n\t * @event cancel\n\t */\n}\n\nmix( Resizer, ObservableMixin );\n\n/**\n * A view displaying the proposed new element size during the resizing.\n *\n * @extends {module:ui/view~View}\n */\nclass SizeView extends View {\n\tconstructor() {\n\t\tsuper();\n\n\t\tconst bind = this.bindTemplate;\n\n\t\tthis.setTemplate( {\n\t\t\ttag: 'div',\n\t\t\tattributes: {\n\t\t\t\tclass: [\n\t\t\t\t\t'ck',\n\t\t\t\t\t'ck-size-view',\n\t\t\t\t\tbind.to( 'activeHandlePosition', value => value ? `ck-orientation-${ value }` : '' )\n\t\t\t\t],\n\t\t\t\tstyle: {\n\t\t\t\t\tdisplay: bind.if( 'isVisible', 'none', visible => !visible )\n\t\t\t\t}\n\t\t\t},\n\t\t\tchildren: [ {\n\t\t\t\ttext: bind.to( 'label' )\n\t\t\t} ]\n\t\t} );\n\t}\n\n\tbindToState( options, resizerState ) {\n\t\tthis.bind( 'isVisible' ).to( resizerState, 'proposedWidth', resizerState, 'proposedHeight', ( width, height ) =>\n\t\t\twidth !== null && height !== null );\n\n\t\tthis.bind( 'label' ).to(\n\t\t\tresizerState, 'proposedHandleHostWidth',\n\t\t\tresizerState, 'proposedHandleHostHeight',\n\t\t\tresizerState, 'proposedWidthPercents',\n\t\t\t( width, height, widthPercents ) => {\n\t\t\t\tif ( options.unit === 'px' ) {\n\t\t\t\t\treturn `${ width }×${ height }`;\n\t\t\t\t} else {\n\t\t\t\t\treturn `${ widthPercents }%`;\n\t\t\t\t}\n\t\t\t}\n\t\t);\n\n\t\tthis.bind( 'activeHandlePosition' ).to( resizerState );\n\t}\n\n\tdismiss() {\n\t\tthis.unbind();\n\t\tthis.isVisible = false;\n\t}\n}\n\n// @private\n// @param {String} resizerPosition Expected resizer position like `\"top-left\"`, `\"bottom-right\"`.\n// @returns {String} A prefixed HTML class name for the resizer element\nfunction getResizerClass( resizerPosition ) {\n\treturn `ck-widget__resizer__handle-${ resizerPosition }`;\n}\n\nfunction extractCoordinates( event ) {\n\treturn {\n\t\tx: event.pageX,\n\t\ty: event.pageY\n\t};\n}\n\nfunction existsInDom( element ) {\n\treturn element && element.ownerDocument && element.ownerDocument.contains( element );\n}\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\n/**\n * @module widget/widgetresize\n */\n\nimport Plugin from '@ckeditor/ckeditor5-core/src/plugin';\nimport Resizer from './widgetresize/resizer';\nimport DomEmitterMixin from '@ckeditor/ckeditor5-utils/src/dom/emittermixin';\nimport global from '@ckeditor/ckeditor5-utils/src/dom/global';\nimport ObservableMixin from '@ckeditor/ckeditor5-utils/src/observablemixin';\nimport MouseObserver from '@ckeditor/ckeditor5-engine/src/view/observer/mouseobserver';\nimport mix from '@ckeditor/ckeditor5-utils/src/mix';\nimport { throttle } from 'lodash-es';\n\nimport '../theme/widgetresize.css';\n\n/**\n * The widget resize feature plugin.\n *\n * Use the {@link module:widget/widgetresize~WidgetResize#attachTo} method to create a resizer for the specified widget.\n *\n * @extends module:core/plugin~Plugin\n * @mixes module:utils/observablemixin~ObservableMixin\n */\nexport default class WidgetResize extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'WidgetResize';\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\t/**\n\t\t * The currently visible resizer.\n\t\t *\n\t\t * @observable\n\t\t * @member {module:widget/widgetresize/resizer~Resizer|null} #visibleResizer\n\t\t */\n\t\tthis.set( 'visibleResizer', null );\n\n\t\t/**\n\t\t * References an active resizer.\n\t\t *\n\t\t * Active resizer means a resizer which handle is actively used by the end user.\n\t\t *\n\t\t * @protected\n\t\t * @observable\n\t\t * @member {module:widget/widgetresize/resizer~Resizer|null} #_activeResizer\n\t\t */\n\t\tthis.set( '_activeResizer', null );\n\n\t\t/**\n\t\t * A map of resizers created using this plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @type {Map.}\n\t\t */\n\t\tthis._resizers = new Map();\n\n\t\tconst domDocument = global.window.document;\n\n\t\tthis.editor.model.schema.setAttributeProperties( 'width', {\n\t\t\tisFormatting: true\n\t\t} );\n\n\t\tthis.editor.editing.view.addObserver( MouseObserver );\n\n\t\tthis._observer = Object.create( DomEmitterMixin );\n\n\t\tthis.listenTo( this.editor.editing.view.document, 'mousedown', this._mouseDownListener.bind( this ), { priority: 'high' } );\n\n\t\tthis._observer.listenTo( domDocument, 'mousemove', this._mouseMoveListener.bind( this ) );\n\t\tthis._observer.listenTo( domDocument, 'mouseup', this._mouseUpListener.bind( this ) );\n\n\t\tconst redrawFocusedResizer = () => {\n\t\t\tif ( this.visibleResizer ) {\n\t\t\t\tthis.visibleResizer.redraw();\n\t\t\t}\n\t\t};\n\n\t\tconst redrawFocusedResizerThrottled = throttle( redrawFocusedResizer, 200 );\n\n\t\t// Redraws occurring upon a change of visible resizer must not be throttled, as it is crucial for the initial\n\t\t// render. Without it the resizer frame would be misaligned with resizing host for a fraction of second.\n\t\tthis.on( 'change:visibleResizer', redrawFocusedResizer );\n\n\t\t// Redrawing on any change of the UI of the editor (including content changes).\n\t\tthis.editor.ui.on( 'update', redrawFocusedResizerThrottled );\n\n\t\t// Resizers need to be redrawn upon window resize, because new window might shrink resize host.\n\t\tthis._observer.listenTo( global.window, 'resize', redrawFocusedResizerThrottled );\n\n\t\tconst viewSelection = this.editor.editing.view.document.selection;\n\n\t\tviewSelection.on( 'change', () => {\n\t\t\tconst selectedElement = viewSelection.getSelectedElement();\n\n\t\t\tthis.visibleResizer = this.getResizerByViewElement( selectedElement ) || null;\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tthis._observer.stopListening();\n\n\t\tfor ( const resizer of this._resizers.values() ) {\n\t\t\tresizer.destroy();\n\t\t}\n\t}\n\n\t/**\n\t * @param {module:widget/widgetresize~ResizerOptions} [options] Resizer options.\n\t * @returns {module:widget/widgetresize/resizer~Resizer}\n\t */\n\tattachTo( options ) {\n\t\tconst resizer = new Resizer( options );\n\t\tconst plugins = this.editor.plugins;\n\n\t\tresizer.attach();\n\n\t\tif ( plugins.has( 'WidgetToolbarRepository' ) ) {\n\t\t\t// Hiding widget toolbar to improve the performance\n\t\t\t// (https://github.com/ckeditor/ckeditor5-widget/pull/112#issuecomment-564528765).\n\t\t\tconst widgetToolbarRepository = plugins.get( 'WidgetToolbarRepository' );\n\n\t\t\tresizer.on( 'begin', () => {\n\t\t\t\twidgetToolbarRepository.forceDisabled( 'resize' );\n\t\t\t}, { priority: 'lowest' } );\n\n\t\t\tresizer.on( 'cancel', () => {\n\t\t\t\twidgetToolbarRepository.clearForceDisabled( 'resize' );\n\t\t\t}, { priority: 'highest' } );\n\n\t\t\tresizer.on( 'commit', () => {\n\t\t\t\twidgetToolbarRepository.clearForceDisabled( 'resize' );\n\t\t\t}, { priority: 'highest' } );\n\t\t}\n\n\t\tthis._resizers.set( options.viewElement, resizer );\n\n\t\tconst viewSelection = this.editor.editing.view.document.selection;\n\t\tconst selectedElement = viewSelection.getSelectedElement();\n\n\t\t// If the element the resizer is created for is currently focused, it should become visible.\n\t\tif ( this.getResizerByViewElement( selectedElement ) == resizer ) {\n\t\t\tthis.visibleResizer = resizer;\n\t\t}\n\n\t\treturn resizer;\n\t}\n\n\t/**\n\t * Returns a resizer created for a given view element (widget element).\n\t *\n\t * @param {module:engine/view/containerelement~ContainerElement} viewElement View element associated with the resizer.\n\t * @returns {module:widget/widgetresize/resizer~Resizer|undefined}\n\t */\n\tgetResizerByViewElement( viewElement ) {\n\t\treturn this._resizers.get( viewElement );\n\t}\n\n\t/**\n\t * Returns a resizer that contains a given resize handle.\n\t *\n\t * @protected\n\t * @param {HTMLElement} domResizeHandle\n\t * @returns {module:widget/widgetresize/resizer~Resizer}\n\t */\n\t_getResizerByHandle( domResizeHandle ) {\n\t\tfor ( const resizer of this._resizers.values() ) {\n\t\t\tif ( resizer.containsHandle( domResizeHandle ) ) {\n\t\t\t\treturn resizer;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * @protected\n\t * @param {module:utils/eventinfo~EventInfo} event\n\t * @param {Event} domEventData Native DOM event.\n\t */\n\t_mouseDownListener( event, domEventData ) {\n\t\tconst resizeHandle = domEventData.domTarget;\n\n\t\tif ( !Resizer.isResizeHandle( resizeHandle ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis._activeResizer = this._getResizerByHandle( resizeHandle );\n\n\t\tif ( this._activeResizer ) {\n\t\t\tthis._activeResizer.begin( resizeHandle );\n\n\t\t\t// Do not call other events when resizing. See: #6755.\n\t\t\tevent.stop();\n\t\t\tdomEventData.preventDefault();\n\t\t}\n\t}\n\n\t/**\n\t * @protected\n\t * @param {module:utils/eventinfo~EventInfo} event\n\t * @param {Event} domEventData Native DOM event.\n\t */\n\t_mouseMoveListener( event, domEventData ) {\n\t\tif ( this._activeResizer ) {\n\t\t\tthis._activeResizer.updateSize( domEventData );\n\t\t}\n\t}\n\n\t/**\n\t * @protected\n\t */\n\t_mouseUpListener() {\n\t\tif ( this._activeResizer ) {\n\t\t\tthis._activeResizer.commit();\n\t\t\tthis._activeResizer = null;\n\t\t}\n\t}\n}\n\nmix( WidgetResize, ObservableMixin );\n\n/**\n * Interface describing a resizer. It allows to specify the resizing host, custom logic for calculating aspect ratio, etc.\n *\n * @interface ResizerOptions\n */\n\n/**\n * Editor instance associated with the resizer.\n *\n * @member {module:core/editor/editor~Editor} module:widget/widgetresize~ResizerOptions#editor\n */\n\n/**\n * @member {module:engine/model/element~Element} module:widget/widgetresize~ResizerOptions#modelElement\n */\n\n/**\n * A view of an element to be resized. Typically it's the main widget's view instance.\n *\n * @member {module:engine/view/containerelement~ContainerElement} module:widget/widgetresize~ResizerOptions#viewElement\n */\n\n/**\n * A callback to be executed once the resizing process is done.\n *\n * It receives a `Number` (`newValue`) as a parameter.\n *\n * For example, {@link module:image/imageresize~ImageResize} uses it to execute the resize image command\n * which puts the new value into the model.\n *\n * ```js\n * {\n *\teditor,\n *\tmodelElement: data.item,\n *\tviewElement: widget,\n *\n *\tonCommit( newValue ) {\n *\t\teditor.execute( 'resizeImage', { width: newValue } );\n *\t}\n * };\n * ```\n *\n *\n * @member {Function} module:widget/widgetresize~ResizerOptions#onCommit\n */\n\n/**\n * @member {Function} module:widget/widgetresize~ResizerOptions#getResizeHost\n */\n\n/**\n * @member {Function} module:widget/widgetresize~ResizerOptions#isCentered\n */\n","/**\n * @license Copyright (c) 2003-2021, CKSource - Frederico Knabben. All rights reserved.\n * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license\n */\n\nexport { default as Widget } from './widget';\nexport { default as WidgetToolbarRepository } from './widgettoolbarrepository';\nexport { default as WidgetResize } from './widgetresize';\nexport { default as WidgetTypeAround } from './widgettypearound/widgettypearound';\nexport * from './utils';\n","module.exports = \"\""],"sourceRoot":""}