diff --git a/src/bundle/Resources/public/js/CKEditor/core/base-ckeditor.js b/src/bundle/Resources/public/js/CKEditor/core/base-ckeditor.js index 0a84d96d..7ea99a98 100644 --- a/src/bundle/Resources/public/js/CKEditor/core/base-ckeditor.js +++ b/src/bundle/Resources/public/js/CKEditor/core/base-ckeditor.js @@ -31,6 +31,7 @@ import BlockQuote from '@ckeditor/ckeditor5-block-quote/src/blockquote'; import ContextualBalloon from '@ckeditor/ckeditor5-ui/src/panel/balloon/contextualballoon'; const VIEWPORT_TOP_OFFSET = 102; +const VIEWPORT_TOP_OFFSET_FOCUS_MODE = 0; (function (global, doc, ibexa) { class BaseRichText { @@ -40,9 +41,11 @@ const VIEWPORT_TOP_OFFSET = 102; this.editor = null; this.viewportTopOffset = config?.viewportTopOffset ?? VIEWPORT_TOP_OFFSET; + this.initialData = config?.initialData; this.xhtmlify = this.xhtmlify.bind(this); this.getData = this.getData.bind(this); + this.getHTMLDocumentFragment = this.getHTMLDocumentFragment.bind(this); } getData() { @@ -180,6 +183,7 @@ const VIEWPORT_TOP_OFFSET = 102; ], toolbar: { items: toolbar, + shouldNotGroupWhenFull: true, }, ui: { viewportOffset: { @@ -216,6 +220,9 @@ const VIEWPORT_TOP_OFFSET = 102; ...extraConfig, }).then((editor) => { this.editor = editor; + + const editableElement = this.editor.editing.view.getDomRoot(); + const editorToolbarPanelInstance = this.editor.ui.view.panel; const initialData = this.getData(); const updateInput = (data, shouldFireInputEvent = true) => { const textarea = container.closest('.ibexa-data-source').querySelector('textarea'); @@ -226,6 +233,29 @@ const VIEWPORT_TOP_OFFSET = 102; textarea.dispatchEvent(new Event('input')); } }; + const setDataSourceHeight = (toolbarNode, fieldEditNode) => { + const dataSourceNode = fieldEditNode.querySelector('.ibexa-data-source'); + const toolbarNodeRect = toolbarNode.getBoundingClientRect(); + const dataSourceNodeRect = dataSourceNode.getBoundingClientRect(); + const { height: toolbarHeight } = toolbarNodeRect; + const { top: dataSourceTop } = dataSourceNodeRect; + + if (toolbarHeight > dataSourceTop) { + const positionDiff = toolbarHeight - dataSourceTop; + + dataSourceNode.style.height = `calc(100% - ${positionDiff}px)`; + dataSourceNode.style.marginTop = `${positionDiff}px`; + } + }; + const setToolbarMaxWidth = (toolbarNode, fieldEditNode) => { + const focusModeControlNode = fieldEditNode.querySelector('.ibexa-field-edit__focus-mode-control-container'); + const dataSourceNode = fieldEditNode.querySelector('.ibexa-data-source'); + const { offsetWidth: focusModeControlNodeWidth } = focusModeControlNode; + const { offsetWidth: dataSourceNodeWidth } = dataSourceNode; + const toolbarNodeMaxWidth = dataSourceNodeWidth - focusModeControlNodeWidth; + + toolbarNode.style.maxWidth = `${toolbarNodeMaxWidth}px`; + }; updateInput(initialData, false); @@ -234,6 +264,33 @@ const VIEWPORT_TOP_OFFSET = 102; updateInput(data); }); + + this.editor.on('set:focusModeActive', ({ source: eventEditorInstance }, name, value) => { + const { ui: eventEditorUiInstance } = eventEditorInstance; + const { panel: eventEditorToolbarPanelInstance } = eventEditorUiInstance.view; + const toolbarPanelNode = eventEditorToolbarPanelInstance.element; + const toolbarPanelsContainer = toolbarPanelNode.closest('.ck-body'); + + eventEditorUiInstance.viewportOffset = { + top: value ? VIEWPORT_TOP_OFFSET_FOCUS_MODE : this.viewportTopOffset, + }; + + toolbarPanelsContainer.classList.toggle('ck-body--focus-mode-active'); + + if (!value) { + eventEditorToolbarPanelInstance.hide(); + } + }); + + editorToolbarPanelInstance.on('change:isVisible', ({ source: eventBalloonPanelViewInstance }) => { + const fieldEditNode = editableElement.closest('.ibexa-field-edit'); + + setToolbarMaxWidth(eventBalloonPanelViewInstance.element, fieldEditNode); + + if (editor?.focusModeActive) { + setDataSourceHeight(eventBalloonPanelViewInstance.element, fieldEditNode); + } + }); }); } } diff --git a/src/bundle/Resources/public/scss/_balloon-form.scss b/src/bundle/Resources/public/scss/_balloon-form.scss index 8e2d1aed..bdd6d7ca 100644 --- a/src/bundle/Resources/public/scss/_balloon-form.scss +++ b/src/bundle/Resources/public/scss/_balloon-form.scss @@ -138,5 +138,35 @@ &.ck-balloon-panel_with-arrow { z-index: calc(var(--ck-z-modal) + 1); } + + &.ck-balloon-panel { + box-shadow: calculateRem(0px) calculateRem(2px) calculateRem(8px) 0 rgba($ibexa-color-light, 0.15); + + .ck.ck-toolbar { + padding: calculateRem(4px); + } + + .ck-toolbar__items { + .ck-button { + padding: calculateRem(8px); + margin: 0; + } + + .ck-dropdown { + padding: 0; + margin: 0; + } + } + } + } + + &.ck-body--focus-mode-active { + .ck-balloon-panel_visible { + z-index: 1080; + } + + .ck-balloon-panel_with-arrow { + z-index: 1081; + } } } diff --git a/src/bundle/Resources/public/scss/_general.scss b/src/bundle/Resources/public/scss/_general.scss index 237fea23..42fb8409 100644 --- a/src/bundle/Resources/public/scss/_general.scss +++ b/src/bundle/Resources/public/scss/_general.scss @@ -253,6 +253,16 @@ } } +.ibexa-field-edit { + &--focus-mode-active { + .ibexa-data-source { + &__richtext { + height: calc(100% - #{calculateRem(32px)}); + } + } + } +} + .ck { &.ck-editor__editable_inline { border: none;