{"version":3,"sources":["webpack:///./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/enabletoolbarkeyboardfocus.js","webpack:///./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/block/blockbuttonview.js","webpack:///./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/block/blocktoolbar.js","webpack:///./node_modules/@ckeditor/ckeditor5-ui/src/toolbar/balloon/balloontoolbar.js"],"names":["enableToolbarKeyboardFocus","_ref","origin","originKeystrokeHandler","originFocusTracker","toolbar","beforeFocus","afterBlur","add","element","set","data","cancel","isFocused","focusTracker","focus","keystrokes","__webpack_require__","d","__webpack_exports__","toPx","toUnit","BlockButtonView","locale","_this","Object","classCallCheck","this","_super","call","bind","bindTemplate","isVisible","isToggleable","extendTemplate","attributes","class","style","top","to","val","left","ButtonView","Plugin","getBalloonPositions","isBackward","defaultPositions","BalloonPanelView","northWestArrowSouth","northWestArrowSouthWest","northWestArrowSouthEast","northWestArrowSouthMiddleEast","northWestArrowSouthMiddleWest","southWestArrowNorth","southWestArrowNorthWest","southWestArrowNorthEast","southWestArrowNorthMiddleWest","southWestArrowNorthMiddleEast","southEastArrowNorth","southEastArrowNorthEast","southEastArrowNorthWest","southEastArrowNorthMiddleEast","southEastArrowNorthMiddleWest","northEastArrowSouth","northEastArrowSouthEast","northEastArrowSouthWest","northEastArrowSouthMiddleEast","northEastArrowSouthMiddleWest","selectionContainsOnlyMultipleSelectables","selection","schema","rangeCount","D_Projects_UA_repo_Source_Client_UA_User_Web_node_modules_babel_runtime_helpers_esm_toConsumableArray_js__WEBPACK_IMPORTED_MODULE_1__","getRanges","every","range","getContainedElement","isSelectable"],"mappings":";;;;;AA0Be,SAASA,EAATC,GAOX,IANHC,EAMGD,EANHC,OACAC,EAKGF,EALHE,uBACAC,EAIGH,EAJHG,mBACAC,EAGGJ,EAHHI,QACAC,EAEGL,EAFHK,YACAC,EACGN,EADHM,UAIAH,EAAmBI,IAAKH,EAAQI,SAGhCN,EAAuBO,IAAK,UAAW,SAAEC,EAAMC,GACzCR,EAAmBS,YAAcR,EAAQS,aAAaD,YACrDP,GACJA,IAGDD,EAAQU,QAERH,OAKFP,EAAQW,WAAWN,IAAK,MAAO,SAAEC,EAAMC,GACjCP,EAAQS,aAAaD,YACzBX,EAAOa,QAEFR,GACJA,IAGDK,OA5DHK,EAAAC,EAAAC,EAAA,sBAAAnB;;;;GCaA,IAAMoB,EAAOC,eAAQ,MAWAC,6CAIpB,SAAAA,EAAaC,GAAS,IAAAC,EAAAC,OAAAC,EAAA,KAAAD,CAAAE,KAAAL,GACrBE,EAAAI,EAAAC,KAAAF,KAAOJ,GAEP,IAAMO,EAAON,EAAKO,aAHG,OAMrBP,EAAKQ,WAAY,EAEjBR,EAAKS,cAAe,EAOpBT,EAAKd,IAAK,MAAO,GAOjBc,EAAKd,IAAK,OAAQ,GAElBc,EAAKU,gBACJC,YACCC,MAAO,0BACPC,OACCC,IAAKR,EAAKS,GAAI,MAAO,SAAAC,GAAG,OAAIpB,EAAMoB,KAClCC,KAAMX,EAAKS,GAAI,OAAQ,SAAAC,GAAG,OAAIpB,EAAMoB,SA7BlBhB,YAJsBkB;;;;GCG7C,IAAMtB,EAAOC,eAAQ,MA2CqBsB;;;;GClD1C,IAAMvB,EAAOC,eAAQ,MASuBsB,OAqU5C,SAASC,EAAqBC,GAC7B,IAAMC,EAAmBC,OAAiBD,iBAE1C,OAAOD,GACNC,EAAiBE,oBACjBF,EAAiBG,wBACjBH,EAAiBI,wBACjBJ,EAAiBK,8BACjBL,EAAiBM,8BACjBN,EAAiBO,oBACjBP,EAAiBQ,wBACjBR,EAAiBS,wBACjBT,EAAiBU,8BACjBV,EAAiBW,gCAEjBX,EAAiBY,oBACjBZ,EAAiBa,wBACjBb,EAAiBc,wBACjBd,EAAiBe,8BACjBf,EAAiBgB,8BACjBhB,EAAiBiB,oBACjBjB,EAAiBkB,wBACjBlB,EAAiBmB,wBACjBnB,EAAiBoB,8BACjBpB,EAAiBqB,+BAWnB,SAASC,EAA0CC,EAAWC,GAE7D,OAA8B,IAAzBD,EAAUE,YAIR9C,OAAA+C,EAAA,KAAA/C,CAAK4C,EAAUI,aAAcC,MAAO,SAAAC,GAC1C,IAAMlE,EAAUkE,EAAMC,sBAEtB,OAAOnE,GAAW6D,EAAOO,aAAcpE","file":"js/chunk-fb9ed26e.e1b28640.js","sourcesContent":["/**\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 ui/toolbar/enabletoolbarkeyboardfocus\n */\n\n/**\n * Enables focus/blur toolbar navigation using `Alt+F10` and `Esc` keystrokes.\n *\n * @param {Object} options Options of the utility.\n * @param {*} options.origin A view to which the focus will return when `Esc` is pressed and\n * `options.toolbar` is focused.\n * @param {module:utils/keystrokehandler~KeystrokeHandler} options.originKeystrokeHandler A keystroke\n * handler to register `Alt+F10` keystroke.\n * @param {module:utils/focustracker~FocusTracker} options.originFocusTracker A focus tracker\n * for `options.origin`.\n * @param {module:ui/toolbar/toolbarview~ToolbarView} options.toolbar A toolbar which is to gain\n * focus when `Alt+F10` is pressed.\n * @param {Function} [options.beforeFocus] A callback executed before the `options.toolbar` gains focus\n * upon the `Alt+F10` keystroke.\n * @param {Function} [options.afterBlur] A callback executed after `options.toolbar` loses focus upon\n * `Esc` keystroke but before the focus goes back to `options.origin`.\n */\nexport default function enableToolbarKeyboardFocus( {\n\torigin,\n\toriginKeystrokeHandler,\n\toriginFocusTracker,\n\ttoolbar,\n\tbeforeFocus,\n\tafterBlur\n} ) {\n\t// Because toolbar items can get focus, the overall state of the toolbar must\n\t// also be tracked.\n\toriginFocusTracker.add( toolbar.element );\n\n\t// Focus the toolbar on the keystroke, if not already focused.\n\toriginKeystrokeHandler.set( 'Alt+F10', ( data, cancel ) => {\n\t\tif ( originFocusTracker.isFocused && !toolbar.focusTracker.isFocused ) {\n\t\t\tif ( beforeFocus ) {\n\t\t\t\tbeforeFocus();\n\t\t\t}\n\n\t\t\ttoolbar.focus();\n\n\t\t\tcancel();\n\t\t}\n\t} );\n\n\t// Blur the toolbar and bring the focus back to origin.\n\ttoolbar.keystrokes.set( 'Esc', ( data, cancel ) => {\n\t\tif ( toolbar.focusTracker.isFocused ) {\n\t\t\torigin.focus();\n\n\t\t\tif ( afterBlur ) {\n\t\t\t\tafterBlur();\n\t\t\t}\n\n\t\t\tcancel();\n\t\t}\n\t} );\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 ui/toolbar/block/blockbuttonview\n */\n\nimport ButtonView from '../../button/buttonview';\nimport toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';\nimport '../../../theme/components/toolbar/blocktoolbar.css';\n\nconst toPx = toUnit( 'px' );\n\n/**\n * The block button view class.\n *\n * This view represents a button attached next to block element where the selection is anchored.\n *\n * See {@link module:ui/toolbar/block/blocktoolbar~BlockToolbar}.\n *\n * @extends {module:ui/button/buttonview~ButtonView}\n */\nexport default class BlockButtonView extends ButtonView {\n\t/**\n\t * @inheritDoc\n\t */\n\tconstructor( locale ) {\n\t\tsuper( locale );\n\n\t\tconst bind = this.bindTemplate;\n\n\t\t// Hide button on init.\n\t\tthis.isVisible = false;\n\n\t\tthis.isToggleable = true;\n\n\t\t/**\n\t\t * Top offset.\n\t\t *\n\t\t * @member {Number} #top\n\t\t */\n\t\tthis.set( 'top', 0 );\n\n\t\t/**\n\t\t * Left offset.\n\t\t *\n\t\t * @member {Number} #left\n\t\t */\n\t\tthis.set( 'left', 0 );\n\n\t\tthis.extendTemplate( {\n\t\t\tattributes: {\n\t\t\t\tclass: 'ck-block-toolbar-button',\n\t\t\t\tstyle: {\n\t\t\t\t\ttop: bind.to( 'top', val => toPx( val ) ),\n\t\t\t\t\tleft: bind.to( 'left', val => toPx( val ) )\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t}\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 ui/toolbar/block/blocktoolbar\n */\n\n/* global window */\n\nimport { Plugin, icons } from 'ckeditor5/src/core';\n\nimport BlockButtonView from './blockbuttonview';\nimport BalloonPanelView from '../../panel/balloon/balloonpanelview';\nimport ToolbarView from '../toolbarview';\n\nimport clickOutsideHandler from '../../bindings/clickoutsidehandler';\n\nimport { getOptimalPosition } from '@ckeditor/ckeditor5-utils/src/dom/position';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport normalizeToolbarConfig from '../normalizetoolbarconfig';\n\nimport ResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/resizeobserver';\n\nimport toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';\n\nconst toPx = toUnit( 'px' );\n\n/**\n * The block toolbar plugin.\n *\n * This plugin provides a button positioned next to the block of content where the selection is anchored.\n * Upon clicking the button, a dropdown providing access to editor features shows up, as configured in\n * {@link module:core/editor/editorconfig~EditorConfig#blockToolbar}.\n *\n * By default, the button is displayed next to all elements marked in {@link module:engine/model/schema~Schema}\n * as `$block` for which the toolbar provides at least one option.\n *\n * By default, the button is attached so its right boundary is touching the\n * {@link module:engine/view/editableelement~EditableElement}:\n *\n * \t\t __ |\n * \t\t| || This is a block of content that the\n * \t\t ¯¯ | button is attached to. This is a\n * \t\t | block of content that the button is\n * \t\t | attached to.\n *\n * The position of the button can be adjusted using the CSS `transform` property:\n *\n * \t\t.ck-block-toolbar-button {\n * \t\t\ttransform: translateX( -10px );\n * \t\t}\n *\n * \t\t __ |\n * \t\t| | | This is a block of content that the\n * \t\t ¯¯ | button is attached to. This is a\n * \t\t | block of content that the button is\n * \t\t | attached to.\n *\n * **Note**: If you plan to run the editor in a right–to–left (RTL) language, keep in mind the button\n * will be attached to the **right** boundary of the editable area. In that case, make sure the\n * CSS position adjustment works properly by adding the following styles:\n *\n * \t\t.ck[dir=\"rtl\"] .ck-block-toolbar-button {\n * \t\t\ttransform: translateX( 10px );\n * \t\t}\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BlockToolbar extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'BlockToolbar';\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 cached and normalized `config.blockToolbar` object.\n\t\t *\n\t\t * @type {module:core/editor/editorconfig~EditorConfig#blockToolbar}\n\t\t * @private\n\t\t */\n\t\tthis._blockToolbarConfig = normalizeToolbarConfig( this.editor.config.get( 'blockToolbar' ) );\n\n\t\t/**\n\t\t * The toolbar view.\n\t\t *\n\t\t * @type {module:ui/toolbar/toolbarview~ToolbarView}\n\t\t */\n\t\tthis.toolbarView = this._createToolbarView();\n\n\t\t/**\n\t\t * The balloon panel view, containing the {@link #toolbarView}.\n\t\t *\n\t\t * @type {module:ui/panel/balloon/balloonpanelview~BalloonPanelView}\n\t\t */\n\t\tthis.panelView = this._createPanelView();\n\n\t\t/**\n\t\t * The button view that opens the {@link #toolbarView}.\n\t\t *\n\t\t * @type {module:ui/toolbar/block/blockbuttonview~BlockButtonView}\n\t\t */\n\t\tthis.buttonView = this._createButtonView();\n\n\t\t/**\n\t\t * An instance of the resize observer that allows to respond to changes in editable's geometry\n\t\t * so the toolbar can stay within its boundaries (and group toolbar items that do not fit).\n\t\t *\n\t\t * **Note**: Used only when `shouldNotGroupWhenFull` was **not** set in the\n\t\t * {@link module:core/editor/editorconfig~EditorConfig#blockToolbar configuration}.\n\t\t *\n\t\t * **Note:** Created in {@link #afterInit}.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:utils/dom/resizeobserver~ResizeObserver}\n\t\t */\n\t\tthis._resizeObserver = null;\n\n\t\t// Close the #panelView upon clicking outside of the plugin UI.\n\t\tclickOutsideHandler( {\n\t\t\temitter: this.panelView,\n\t\t\tcontextElements: [ this.panelView.element, this.buttonView.element ],\n\t\t\tactivator: () => this.panelView.isVisible,\n\t\t\tcallback: () => this._hidePanel()\n\t\t} );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\n\t\t// Hides panel on a direct selection change.\n\t\tthis.listenTo( editor.model.document.selection, 'change:range', ( evt, data ) => {\n\t\t\tif ( data.directChange ) {\n\t\t\t\tthis._hidePanel();\n\t\t\t}\n\t\t} );\n\n\t\tthis.listenTo( editor.ui, 'update', () => this._updateButton() );\n\t\t// `low` priority is used because of https://github.com/ckeditor/ckeditor5-core/issues/133.\n\t\tthis.listenTo( editor, 'change:isReadOnly', () => this._updateButton(), { priority: 'low' } );\n\t\tthis.listenTo( editor.ui.focusTracker, 'change:isFocused', () => this._updateButton() );\n\n\t\t// Reposition button on resize.\n\t\tthis.listenTo( this.buttonView, 'change:isVisible', ( evt, name, isVisible ) => {\n\t\t\tif ( isVisible ) {\n\t\t\t\t// Keep correct position of button and panel on window#resize.\n\t\t\t\tthis.buttonView.listenTo( window, 'resize', () => this._updateButton() );\n\t\t\t} else {\n\t\t\t\t// Stop repositioning button when is hidden.\n\t\t\t\tthis.buttonView.stopListening( window, 'resize' );\n\n\t\t\t\t// Hide the panel when the button disappears.\n\t\t\t\tthis._hidePanel();\n\t\t\t}\n\t\t} );\n\t}\n\n\t/**\n\t * Fills the toolbar with its items based on the configuration.\n\t *\n\t * **Note:** This needs to be done after all plugins are ready.\n\t *\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tconst factory = this.editor.ui.componentFactory;\n\t\tconst config = this._blockToolbarConfig;\n\n\t\tthis.toolbarView.fillFromConfig( config, factory );\n\n\t\t// Hide panel before executing each button in the panel.\n\t\tfor ( const item of this.toolbarView.items ) {\n\t\t\titem.on( 'execute', () => this._hidePanel( true ), { priority: 'high' } );\n\t\t}\n\n\t\tif ( !config.shouldNotGroupWhenFull ) {\n\t\t\tthis.listenTo( this.editor, 'ready', () => {\n\t\t\t\tconst editableElement = this.editor.ui.view.editable.element;\n\n\t\t\t\t// Set #toolbarView's max-width just after the initialization and update it on the editable resize.\n\t\t\t\tthis._resizeObserver = new ResizeObserver( editableElement, () => {\n\t\t\t\t\tthis.toolbarView.maxWidth = this._getToolbarMaxWidth();\n\t\t\t\t} );\n\t\t\t} );\n\t\t}\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\t// Destroy created UI components as they are not automatically destroyed (see ckeditor5#1341).\n\t\tthis.panelView.destroy();\n\t\tthis.buttonView.destroy();\n\t\tthis.toolbarView.destroy();\n\n\t\tif ( this._resizeObserver ) {\n\t\t\tthis._resizeObserver.destroy();\n\t\t}\n\t}\n\n\t/**\n\t * Creates the {@link #toolbarView}.\n\t *\n\t * @private\n\t * @returns {module:ui/toolbar/toolbarview~ToolbarView}\n\t */\n\t_createToolbarView() {\n\t\tconst shouldGroupWhenFull = !this._blockToolbarConfig.shouldNotGroupWhenFull;\n\t\tconst toolbarView = new ToolbarView( this.editor.locale, {\n\t\t\tshouldGroupWhenFull,\n\t\t\tisFloating: true\n\t\t} );\n\n\t\t// When toolbar lost focus then panel should hide.\n\t\ttoolbarView.focusTracker.on( 'change:isFocused', ( evt, name, is ) => {\n\t\t\tif ( !is ) {\n\t\t\t\tthis._hidePanel();\n\t\t\t}\n\t\t} );\n\n\t\treturn toolbarView;\n\t}\n\n\t/**\n\t * Creates the {@link #panelView}.\n\t *\n\t * @private\n\t * @returns {module:ui/panel/balloon/balloonpanelview~BalloonPanelView}\n\t */\n\t_createPanelView() {\n\t\tconst editor = this.editor;\n\t\tconst panelView = new BalloonPanelView( editor.locale );\n\n\t\tpanelView.content.add( this.toolbarView );\n\t\tpanelView.class = 'ck-toolbar-container';\n\t\teditor.ui.view.body.add( panelView );\n\t\teditor.ui.focusTracker.add( panelView.element );\n\n\t\t// Close #panelView on `Esc` press.\n\t\tthis.toolbarView.keystrokes.set( 'Esc', ( evt, cancel ) => {\n\t\t\tthis._hidePanel( true );\n\t\t\tcancel();\n\t\t} );\n\n\t\treturn panelView;\n\t}\n\n\t/**\n\t * Creates the {@link #buttonView}.\n\t *\n\t * @private\n\t * @returns {module:ui/toolbar/block/blockbuttonview~BlockButtonView}\n\t */\n\t_createButtonView() {\n\t\tconst editor = this.editor;\n\t\tconst t = editor.t;\n\t\tconst buttonView = new BlockButtonView( editor.locale );\n\n\t\tbuttonView.set( {\n\t\t\tlabel: t( 'Edit block' ),\n\t\t\ticon: icons.pilcrow,\n\t\t\twithText: false\n\t\t} );\n\n\t\t// Bind the panelView observable properties to the buttonView.\n\t\tbuttonView.bind( 'isOn' ).to( this.panelView, 'isVisible' );\n\t\tbuttonView.bind( 'tooltip' ).to( this.panelView, 'isVisible', isVisible => !isVisible );\n\n\t\t// Toggle the panelView upon buttonView#execute.\n\t\tthis.listenTo( buttonView, 'execute', () => {\n\t\t\tif ( !this.panelView.isVisible ) {\n\t\t\t\tthis._showPanel();\n\t\t\t} else {\n\t\t\t\tthis._hidePanel( true );\n\t\t\t}\n\t\t} );\n\n\t\teditor.ui.view.body.add( buttonView );\n\t\teditor.ui.focusTracker.add( buttonView.element );\n\n\t\treturn buttonView;\n\t}\n\n\t/**\n\t * Shows or hides the button.\n\t * When all the conditions for displaying the button are matched, it shows the button. Hides otherwise.\n\t *\n\t * @private\n\t */\n\t_updateButton() {\n\t\tconst editor = this.editor;\n\t\tconst model = editor.model;\n\t\tconst view = editor.editing.view;\n\n\t\t// Hides the button when the editor is not focused.\n\t\tif ( !editor.ui.focusTracker.isFocused ) {\n\t\t\tthis._hideButton();\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Hides the button when the editor switches to the read-only mode.\n\t\tif ( editor.isReadOnly ) {\n\t\t\tthis._hideButton();\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the first selected block, button will be attached to this element.\n\t\tconst modelTarget = Array.from( model.document.selection.getSelectedBlocks() )[ 0 ];\n\n\t\t// Hides the button when there is no enabled item in toolbar for the current block element.\n\t\tif ( !modelTarget || Array.from( this.toolbarView.items ).every( item => !item.isEnabled ) ) {\n\t\t\tthis._hideButton();\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Get DOM target element.\n\t\tconst domTarget = view.domConverter.mapViewToDom( editor.editing.mapper.toViewElement( modelTarget ) );\n\n\t\t// Show block button.\n\t\tthis.buttonView.isVisible = true;\n\n\t\t// Attach block button to target DOM element.\n\t\tthis._attachButtonToElement( domTarget );\n\n\t\t// When panel is opened then refresh it position to be properly aligned with block button.\n\t\tif ( this.panelView.isVisible ) {\n\t\t\tthis._showPanel();\n\t\t}\n\t}\n\n\t/**\n\t * Hides the button.\n\t *\n\t * @private\n\t */\n\t_hideButton() {\n\t\tthis.buttonView.isVisible = false;\n\t}\n\n\t/**\n\t * Shows the {@link #toolbarView} attached to the {@link #buttonView}.\n\t * If the toolbar is already visible, then it simply repositions it.\n\t *\n\t * @private\n\t */\n\t_showPanel() {\n\t\tconst wasVisible = this.panelView.isVisible;\n\n\t\t// So here's the thing: If there was no initial panelView#show() or these two were in different order, the toolbar\n\t\t// positioning will break in RTL editors. Weird, right? What you show know is that the toolbar\n\t\t// grouping works thanks to:\n\t\t//\n\t\t// * the ResizeObserver, which kicks in as soon as the toolbar shows up in DOM (becomes visible again).\n\t\t// * the observable ToolbarView#maxWidth, which triggers re-grouping when changed.\n\t\t//\n\t\t// Here are the possible scenarios:\n\t\t//\n\t\t// 1. (WRONG ❌) If the #maxWidth is set when the toolbar is invisible, it won't affect item grouping (no DOMRects, no grouping).\n\t\t// Then, when panelView.pin() is called, the position of the toolbar will be calculated for the old\n\t\t// items grouping state, and when finally ResizeObserver kicks in (hey, the toolbar is visible now, right?)\n\t\t// it will group/ungroup some items and the length of the toolbar will change. But since in RTL the toolbar\n\t\t// is attached on the right side and the positioning uses CSS \"left\", it will result in the toolbar shifting\n\t\t// to the left and being displayed in the wrong place.\n\t\t// 2. (WRONG ❌) If the panelView.pin() is called first and #maxWidth set next, then basically the story repeats. The balloon\n\t\t// calculates the position for the old toolbar grouping state, then the toolbar re-groups items and because\n\t\t// it is positioned using CSS \"left\" it will move.\n\t\t// 3. (RIGHT ✅) We show the panel first (the toolbar does re-grouping but it does not matter), then the #maxWidth\n\t\t// is set allowing the toolbar to re-group again and finally panelView.pin() does the positioning when the\n\t\t// items grouping state is stable and final.\n\t\t//\n\t\t// https://github.com/ckeditor/ckeditor5/issues/6449, https://github.com/ckeditor/ckeditor5/issues/6575\n\t\tthis.panelView.show();\n\t\tthis.toolbarView.maxWidth = this._getToolbarMaxWidth();\n\n\t\tthis.panelView.pin( {\n\t\t\ttarget: this.buttonView.element,\n\t\t\tlimiter: this.editor.ui.getEditableElement()\n\t\t} );\n\n\t\tif ( !wasVisible ) {\n\t\t\tthis.toolbarView.items.get( 0 ).focus();\n\t\t}\n\t}\n\n\t/**\n\t * Hides the {@link #toolbarView}.\n\t *\n\t * @private\n\t * @param {Boolean} [focusEditable=false] When `true`, the editable will be focused after hiding the panel.\n\t */\n\t_hidePanel( focusEditable ) {\n\t\tthis.panelView.isVisible = false;\n\n\t\tif ( focusEditable ) {\n\t\t\tthis.editor.editing.view.focus();\n\t\t}\n\t}\n\n\t/**\n\t * Attaches the {@link #buttonView} to the target block of content.\n\t *\n\t * @protected\n\t * @param {HTMLElement} targetElement Target element.\n\t */\n\t_attachButtonToElement( targetElement ) {\n\t\tconst contentStyles = window.getComputedStyle( targetElement );\n\n\t\tconst editableRect = new Rect( this.editor.ui.getEditableElement() );\n\t\tconst contentPaddingTop = parseInt( contentStyles.paddingTop, 10 );\n\t\t// When line height is not an integer then thread it as \"normal\".\n\t\t// MDN says that 'normal' == ~1.2 on desktop browsers.\n\t\tconst contentLineHeight = parseInt( contentStyles.lineHeight, 10 ) || parseInt( contentStyles.fontSize, 10 ) * 1.2;\n\n\t\tconst position = getOptimalPosition( {\n\t\t\telement: this.buttonView.element,\n\t\t\ttarget: targetElement,\n\t\t\tpositions: [\n\t\t\t\t( contentRect, buttonRect ) => {\n\t\t\t\t\tlet left;\n\n\t\t\t\t\tif ( this.editor.locale.uiLanguageDirection === 'ltr' ) {\n\t\t\t\t\t\tleft = editableRect.left - buttonRect.width;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tleft = editableRect.right;\n\t\t\t\t\t}\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttop: contentRect.top + contentPaddingTop + ( contentLineHeight - buttonRect.height ) / 2,\n\t\t\t\t\t\tleft\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t]\n\t\t} );\n\n\t\tthis.buttonView.top = position.top;\n\t\tthis.buttonView.left = position.left;\n\t}\n\n\t/**\n\t * Gets the {@link #toolbarView} max-width, based on\n\t * editable width plus distance between farthest edge of the {@link #buttonView} and the editable.\n\t *\n\t * @private\n\t * @returns {String} maxWidth A maximum width that toolbar can have, in pixels.\n\t */\n\t_getToolbarMaxWidth() {\n\t\tconst editableElement = this.editor.ui.view.editable.element;\n\t\tconst editableRect = new Rect( editableElement );\n\t\tconst buttonRect = new Rect( this.buttonView.element );\n\t\tconst isRTL = this.editor.locale.uiLanguageDirection === 'rtl';\n\t\tconst offset = isRTL ? ( buttonRect.left - editableRect.right ) + buttonRect.width : editableRect.left - buttonRect.left;\n\n\t\treturn toPx( editableRect.width + offset );\n\t}\n}\n\n/**\n * The block toolbar configuration. Used by the {@link module:ui/toolbar/block/blocktoolbar~BlockToolbar}\n * feature.\n *\n *\t\tconst config = {\n *\t\t\tblockToolbar: [ 'paragraph', 'heading1', 'heading2', 'bulletedList', 'numberedList' ]\n *\t\t};\n *\n * You can also use `'|'` to create a separator between groups of items:\n *\n *\t\tconst config = {\n *\t\t\tblockToolbar: [ 'paragraph', 'heading1', 'heading2', '|', 'bulletedList', 'numberedList' ]\n *\t\t};\n *\n * ## Configuring items grouping\n *\n * You can prevent automatic items grouping by setting the `shouldNotGroupWhenFull` option:\n *\n *\t\tconst config = {\n *\t\t\tblockToolbar: {\n *\t\t\t\titems: [ 'paragraph', 'heading1', 'heading2', '|', 'bulletedList', 'numberedList' ],\n *\t\t\t\tshouldNotGroupWhenFull: true\n *\t\t\t},\n *\t\t};\n *\n * Read more about configuring the main editor toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.\n *\n * @member {Array.|Object} module:core/editor/editorconfig~EditorConfig#blockToolbar\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 ui/toolbar/balloon/balloontoolbar\n */\n\nimport { Plugin } from 'ckeditor5/src/core';\nimport ContextualBalloon from '../../panel/balloon/contextualballoon';\nimport ToolbarView from '../toolbarview';\nimport BalloonPanelView from '../../panel/balloon/balloonpanelview.js';\nimport FocusTracker from '@ckeditor/ckeditor5-utils/src/focustracker';\nimport Rect from '@ckeditor/ckeditor5-utils/src/dom/rect';\nimport normalizeToolbarConfig from '../normalizetoolbarconfig';\nimport { debounce } from 'lodash-es';\nimport ResizeObserver from '@ckeditor/ckeditor5-utils/src/dom/resizeobserver';\nimport toUnit from '@ckeditor/ckeditor5-utils/src/dom/tounit';\n\nconst toPx = toUnit( 'px' );\n\n/**\n * The contextual toolbar.\n *\n * It uses the {@link module:ui/panel/balloon/contextualballoon~ContextualBalloon contextual balloon plugin}.\n *\n * @extends module:core/plugin~Plugin\n */\nexport default class BalloonToolbar extends Plugin {\n\t/**\n\t * @inheritDoc\n\t */\n\tstatic get pluginName() {\n\t\treturn 'BalloonToolbar';\n\t}\n\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\tconstructor( editor ) {\n\t\tsuper( editor );\n\n\t\t/**\n\t\t * A cached and normalized `config.balloonToolbar` object.\n\t\t *\n\t\t * @type {module:core/editor/editorconfig~EditorConfig#balloonToolbar}\n\t\t * @private\n\t\t */\n\t\tthis._balloonConfig = normalizeToolbarConfig( editor.config.get( 'balloonToolbar' ) );\n\n\t\t/**\n\t\t * The toolbar view displayed in the balloon.\n\t\t *\n\t\t * @type {module:ui/toolbar/toolbarview~ToolbarView}\n\t\t */\n\t\tthis.toolbarView = this._createToolbarView();\n\n\t\t/**\n\t\t * Tracks the focus of the {@link module:core/editor/editorui~EditorUI#getEditableElement editable element}\n\t\t * and the {@link #toolbarView}. When both are blurred then the toolbar should hide.\n\t\t *\n\t\t * @readonly\n\t\t * @type {module:utils:focustracker~FocusTracker}\n\t\t */\n\t\tthis.focusTracker = new FocusTracker();\n\n\t\t// Wait for the EditorUI#init. EditableElement is not available before.\n\t\teditor.ui.once( 'ready', () => {\n\t\t\tthis.focusTracker.add( editor.ui.getEditableElement() );\n\t\t\tthis.focusTracker.add( this.toolbarView.element );\n\t\t} );\n\n\t\t/**\n\t\t * An instance of the resize observer that allows to respond to changes in editable's geometry\n\t\t * so the toolbar can stay within its boundaries (and group toolbar items that do not fit).\n\t\t *\n\t\t * **Note**: Used only when `shouldNotGroupWhenFull` was **not** set in the\n\t\t * {@link module:core/editor/editorconfig~EditorConfig#balloonToolbar configuration}.\n\t\t *\n\t\t * **Note:** Created in {@link #init}.\n\t\t *\n\t\t * @protected\n\t\t * @member {module:utils/dom/resizeobserver~ResizeObserver}\n\t\t */\n\t\tthis._resizeObserver = null;\n\n\t\t/**\n\t\t * The contextual balloon plugin instance.\n\t\t *\n\t\t * @private\n\t\t * @type {module:ui/panel/balloon/contextualballoon~ContextualBalloon}\n\t\t */\n\t\tthis._balloon = editor.plugins.get( ContextualBalloon );\n\n\t\t/**\n\t\t * Fires {@link #event:_selectionChangeDebounced} event using `lodash#debounce`.\n\t\t *\n\t\t * This function is stored as a plugin property to make possible to cancel\n\t\t * trailing debounced invocation on destroy.\n\t\t *\n\t\t * @private\n\t\t * @type {Function}\n\t\t */\n\t\tthis._fireSelectionChangeDebounced = debounce( () => this.fire( '_selectionChangeDebounced' ), 200 );\n\n\t\t// The appearance of the BalloonToolbar method is event–driven.\n\t\t// It is possible to stop the #show event and this prevent the toolbar from showing up.\n\t\tthis.decorate( 'show' );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tinit() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\n\t\t// Show/hide the toolbar on editable focus/blur.\n\t\tthis.listenTo( this.focusTracker, 'change:isFocused', ( evt, name, isFocused ) => {\n\t\t\tconst isToolbarVisible = this._balloon.visibleView === this.toolbarView;\n\n\t\t\tif ( !isFocused && isToolbarVisible ) {\n\t\t\t\tthis.hide();\n\t\t\t} else if ( isFocused ) {\n\t\t\t\tthis.show();\n\t\t\t}\n\t\t} );\n\n\t\t// Hide the toolbar when the selection is changed by a direct change or has changed to collapsed.\n\t\tthis.listenTo( selection, 'change:range', ( evt, data ) => {\n\t\t\tif ( data.directChange || selection.isCollapsed ) {\n\t\t\t\tthis.hide();\n\t\t\t}\n\n\t\t\t// Fire internal `_selectionChangeDebounced` event to use it for showing\n\t\t\t// the toolbar after the selection stops changing.\n\t\t\tthis._fireSelectionChangeDebounced();\n\t\t} );\n\n\t\t// Show the toolbar when the selection stops changing.\n\t\tthis.listenTo( this, '_selectionChangeDebounced', () => {\n\t\t\tif ( this.editor.editing.view.document.isFocused ) {\n\t\t\t\tthis.show();\n\t\t\t}\n\t\t} );\n\n\t\tif ( !this._balloonConfig.shouldNotGroupWhenFull ) {\n\t\t\tthis.listenTo( editor, 'ready', () => {\n\t\t\t\tconst editableElement = editor.ui.view.editable.element;\n\n\t\t\t\t// Set #toolbarView's max-width on the initialization and update it on the editable resize.\n\t\t\t\tthis._resizeObserver = new ResizeObserver( editableElement, () => {\n\t\t\t\t\t// The max-width equals 90% of the editable's width for the best user experience.\n\t\t\t\t\t// The value keeps the balloon very close to the boundaries of the editable and limits the cases\n\t\t\t\t\t// when the balloon juts out from the editable element it belongs to.\n\t\t\t\t\tthis.toolbarView.maxWidth = toPx( new Rect( editableElement ).width * .9 );\n\t\t\t\t} );\n\t\t\t} );\n\t\t}\n\n\t\t// Listen to the toolbar view and whenever it changes its geometry due to some items being\n\t\t// grouped or ungrouped, update the position of the balloon because a shorter/longer toolbar\n\t\t// means the balloon could be pointing at the wrong place. Once updated, the balloon will point\n\t\t// at the right selection in the content again.\n\t\t// https://github.com/ckeditor/ckeditor5/issues/6444\n\t\tthis.listenTo( this.toolbarView, 'groupedItemsUpdate', () => {\n\t\t\tthis._updatePosition();\n\t\t} );\n\t}\n\n\t/**\n\t * Creates toolbar components based on given configuration.\n\t * This needs to be done when all plugins are ready.\n\t *\n\t * @inheritDoc\n\t */\n\tafterInit() {\n\t\tconst factory = this.editor.ui.componentFactory;\n\n\t\tthis.toolbarView.fillFromConfig( this._balloonConfig, factory );\n\t}\n\n\t/**\n\t * Creates the toolbar view instance.\n\t *\n\t * @private\n\t * @returns {module:ui/toolbar/toolbarview~ToolbarView}\n\t */\n\t_createToolbarView() {\n\t\tconst shouldGroupWhenFull = !this._balloonConfig.shouldNotGroupWhenFull;\n\t\tconst toolbarView = new ToolbarView( this.editor.locale, {\n\t\t\tshouldGroupWhenFull,\n\t\t\tisFloating: true\n\t\t} );\n\n\t\ttoolbarView.render();\n\n\t\treturn toolbarView;\n\t}\n\n\t/**\n\t * Shows the toolbar and attaches it to the selection.\n\t *\n\t * Fires {@link #event:show} event which can be stopped to prevent the toolbar from showing up.\n\t */\n\tshow() {\n\t\tconst editor = this.editor;\n\t\tconst selection = editor.model.document.selection;\n\t\tconst schema = editor.model.schema;\n\n\t\t// Do not add the toolbar to the balloon stack twice.\n\t\tif ( this._balloon.hasView( this.toolbarView ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Do not show the toolbar when the selection is collapsed.\n\t\tif ( selection.isCollapsed ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Do not show the toolbar when there is more than one range in the selection and they fully contain selectable elements.\n\t\t// See https://github.com/ckeditor/ckeditor5/issues/6443.\n\t\tif ( selectionContainsOnlyMultipleSelectables( selection, schema ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Don not show the toolbar when all components inside are disabled\n\t\t// see https://github.com/ckeditor/ckeditor5-ui/issues/269.\n\t\tif ( Array.from( this.toolbarView.items ).every( item => item.isEnabled !== undefined && !item.isEnabled ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Update the toolbar position when the editor ui should be refreshed.\n\t\tthis.listenTo( this.editor.ui, 'update', () => {\n\t\t\tthis._updatePosition();\n\t\t} );\n\n\t\t// Add the toolbar to the common editor contextual balloon.\n\t\tthis._balloon.add( {\n\t\t\tview: this.toolbarView,\n\t\t\tposition: this._getBalloonPositionData(),\n\t\t\tballoonClassName: 'ck-toolbar-container'\n\t\t} );\n\t}\n\n\t/**\n\t * Hides the toolbar.\n\t */\n\thide() {\n\t\tif ( this._balloon.hasView( this.toolbarView ) ) {\n\t\t\tthis.stopListening( this.editor.ui, 'update' );\n\t\t\tthis._balloon.remove( this.toolbarView );\n\t\t}\n\t}\n\n\t/**\n\t * Returns positioning options for the {@link #_balloon}. They control the way balloon is attached\n\t * to the selection.\n\t *\n\t * @private\n\t * @returns {module:utils/dom/position~Options}\n\t */\n\t_getBalloonPositionData() {\n\t\tconst editor = this.editor;\n\t\tconst view = editor.editing.view;\n\t\tconst viewDocument = view.document;\n\t\tconst viewSelection = viewDocument.selection;\n\n\t\t// Get direction of the selection.\n\t\tconst isBackward = viewDocument.selection.isBackward;\n\n\t\treturn {\n\t\t\t// Because the target for BalloonPanelView is a Rect (not DOMRange), it's geometry will stay fixed\n\t\t\t// as the window scrolls. To let the BalloonPanelView follow such Rect, is must be continuously\n\t\t\t// computed and hence, the target is defined as a function instead of a static value.\n\t\t\t// https://github.com/ckeditor/ckeditor5-ui/issues/195\n\t\t\ttarget: () => {\n\t\t\t\tconst range = isBackward ? viewSelection.getFirstRange() : viewSelection.getLastRange();\n\t\t\t\tconst rangeRects = Rect.getDomRangeRects( view.domConverter.viewRangeToDom( range ) );\n\n\t\t\t\t// Select the proper range rect depending on the direction of the selection.\n\t\t\t\tif ( isBackward ) {\n\t\t\t\t\treturn rangeRects[ 0 ];\n\t\t\t\t} else {\n\t\t\t\t\t// Ditch the zero-width \"orphan\" rect in the next line for the forward selection if there's\n\t\t\t\t\t// another one preceding it. It is not rendered as a selection by the web browser anyway.\n\t\t\t\t\t// https://github.com/ckeditor/ckeditor5-ui/issues/308\n\t\t\t\t\tif ( rangeRects.length > 1 && rangeRects[ rangeRects.length - 1 ].width === 0 ) {\n\t\t\t\t\t\trangeRects.pop();\n\t\t\t\t\t}\n\n\t\t\t\t\treturn rangeRects[ rangeRects.length - 1 ];\n\t\t\t\t}\n\t\t\t},\n\t\t\tpositions: getBalloonPositions( isBackward )\n\t\t};\n\t}\n\n\t/**\n\t * Updates the position of the {@link #_balloon} to make up for changes:\n\t *\n\t * * in the geometry of the selection it is attached to (e.g. the selection moved in the viewport or expanded or shrunk),\n\t * * or the geometry of the balloon toolbar itself (e.g. the toolbar has grouped or ungrouped some items and it is shorter or longer).\n\t *\n\t * @private\n\t */\n\t_updatePosition() {\n\t\tthis._balloon.updatePosition( this._getBalloonPositionData() );\n\t}\n\n\t/**\n\t * @inheritDoc\n\t */\n\tdestroy() {\n\t\tsuper.destroy();\n\n\t\tthis.stopListening();\n\t\tthis._fireSelectionChangeDebounced.cancel();\n\t\tthis.toolbarView.destroy();\n\t\tthis.focusTracker.destroy();\n\n\t\tif ( this._resizeObserver ) {\n\t\t\tthis._resizeObserver.destroy();\n\t\t}\n\t}\n\n\t/**\n\t * This event is fired just before the toolbar shows up. Stopping this event will prevent this.\n\t *\n\t * @event show\n\t */\n\n\t/**\n\t * This is internal plugin event which is fired 200 ms after model selection last change.\n\t * This is to makes easy test debounced action without need to use `setTimeout`.\n\t *\n\t * @protected\n\t * @event _selectionChangeDebounced\n\t */\n}\n\n// Returns toolbar positions for the given direction of the selection.\n//\n// @private\n// @param {Boolean} isBackward\n// @returns {Array.}\nfunction getBalloonPositions( isBackward ) {\n\tconst defaultPositions = BalloonPanelView.defaultPositions;\n\n\treturn isBackward ? [\n\t\tdefaultPositions.northWestArrowSouth,\n\t\tdefaultPositions.northWestArrowSouthWest,\n\t\tdefaultPositions.northWestArrowSouthEast,\n\t\tdefaultPositions.northWestArrowSouthMiddleEast,\n\t\tdefaultPositions.northWestArrowSouthMiddleWest,\n\t\tdefaultPositions.southWestArrowNorth,\n\t\tdefaultPositions.southWestArrowNorthWest,\n\t\tdefaultPositions.southWestArrowNorthEast,\n\t\tdefaultPositions.southWestArrowNorthMiddleWest,\n\t\tdefaultPositions.southWestArrowNorthMiddleEast\n\t] : [\n\t\tdefaultPositions.southEastArrowNorth,\n\t\tdefaultPositions.southEastArrowNorthEast,\n\t\tdefaultPositions.southEastArrowNorthWest,\n\t\tdefaultPositions.southEastArrowNorthMiddleEast,\n\t\tdefaultPositions.southEastArrowNorthMiddleWest,\n\t\tdefaultPositions.northEastArrowSouth,\n\t\tdefaultPositions.northEastArrowSouthEast,\n\t\tdefaultPositions.northEastArrowSouthWest,\n\t\tdefaultPositions.northEastArrowSouthMiddleEast,\n\t\tdefaultPositions.northEastArrowSouthMiddleWest\n\t];\n}\n\n// Returns \"true\" when the selection has multiple ranges and each range contains a selectable element\n// and nothing else.\n//\n// @private\n// @param {module:engine/model/selection~Selection} selection\n// @param {module:engine/model/schema~Schema} schema\n// @returns {Boolean}\nfunction selectionContainsOnlyMultipleSelectables( selection, schema ) {\n\t// It doesn't contain multiple objects if there is only one range.\n\tif ( selection.rangeCount === 1 ) {\n\t\treturn false;\n\t}\n\n\treturn [ ...selection.getRanges() ].every( range => {\n\t\tconst element = range.getContainedElement();\n\n\t\treturn element && schema.isSelectable( element );\n\t} );\n}\n\n/**\n * Contextual toolbar configuration. Used by the {@link module:ui/toolbar/balloon/balloontoolbar~BalloonToolbar}\n * feature.\n *\n * ## Configuring toolbar items\n *\n *\t\tconst config = {\n *\t\t\tballoonToolbar: [ 'bold', 'italic', 'undo', 'redo' ]\n *\t\t};\n *\n * You can also use `'|'` to create a separator between groups of items:\n *\n *\t\tconst config = {\n *\t\t\tballoonToolbar: [ 'bold', 'italic', | 'undo', 'redo' ]\n *\t\t};\n *\n * Read also about configuring the main editor toolbar in {@link module:core/editor/editorconfig~EditorConfig#toolbar}.\n *\n * ## Configuring items grouping\n *\n * You can prevent automatic items grouping by setting the `shouldNotGroupWhenFull` option:\n *\n *\t\tconst config = {\n *\t\t\tballoonToolbar: {\n *\t\t\t\titems: [ 'bold', 'italic', 'undo', 'redo' ],\n *\t\t\t\tshouldNotGroupWhenFull: true\n *\t\t\t},\n *\t\t};\n *\n * @member {Array.|Object} module:core/editor/editorconfig~EditorConfig#balloonToolbar\n */\n"],"sourceRoot":""}