diff --git a/src/bundle/Resources/encore/ibexa.js.config.js b/src/bundle/Resources/encore/ibexa.js.config.js index 072de90032..575ae162cf 100644 --- a/src/bundle/Resources/encore/ibexa.js.config.js +++ b/src/bundle/Resources/encore/ibexa.js.config.js @@ -54,6 +54,7 @@ const layout = [ path.resolve(__dirname, '../public/js/scripts/admin.form.autosubmit.js'), path.resolve(__dirname, '../public/js/scripts/admin.anchor.navigation'), path.resolve(__dirname, '../public/js/scripts/admin.context.menu'), + path.resolve(__dirname, '../public/js/scripts/admin.focus.mode.js'), path.resolve(__dirname, '../public/js/scripts/sidebar/main.menu.js'), path.resolve(__dirname, '../public/js/scripts/admin.input.text.js'), path.resolve(__dirname, '../public/js/scripts/admin.table.js'), diff --git a/src/bundle/Resources/public/js/scripts/admin.focus.mode.js b/src/bundle/Resources/public/js/scripts/admin.focus.mode.js new file mode 100644 index 0000000000..c26d125940 --- /dev/null +++ b/src/bundle/Resources/public/js/scripts/admin.focus.mode.js @@ -0,0 +1,71 @@ +(function (global, doc, ibexa) { + let activeFieldEdit = null; + const ENABLE_FOCUS_MODE_EVENT_NAME = 'ibexa-focus-mode:on'; + const DISABLE_FOCUS_MODE_EVENT_NAME = 'ibexa-focus-mode:off'; + const focusModeEnableBtns = doc.querySelectorAll('.ibexa-field-edit__focus-mode-control-btn--enable'); + const focusModeDisbaleBtns = doc.querySelectorAll('.ibexa-field-edit__focus-mode-control-btn--disable'); + const noticeContainers = doc.querySelectorAll('.ibexa-field-edit__focus-mode-notice-container') + const getEditorUiInstance = (editorContainer) => { + const editorSourceElement = editorContainer.querySelector('.ibexa-data-source__richtext'); + const editorInstance = editorSourceElement.ckeditorInstance; + + return editorInstance.ui; + }; + const changeFocusModeState = (enable) => { + if (!activeFieldEdit) { + return; + } + + const dispatchEventName = enable + ? ENABLE_FOCUS_MODE_EVENT_NAME + : DISABLE_FOCUS_MODE_EVENT_NAME; + const editorSourceElement = activeFieldEdit.querySelector('.ibexa-data-source__richtext'); + const editorInstance = editorSourceElement.ckeditorInstance; + + activeFieldEdit.classList.toggle('ibexa-field-edit--in-focus-mode', enable); + editorInstance.set('focusModeEnabled', enable); + + doc.body.dispatchEvent( + new CustomEvent(dispatchEventName, { + detail: { + activeFieldEdit + }, + }), + ); + + if (!enable) { + activeFieldEdit = null; + } + } + const watchDisableFocusModeByKeyboard = (event) => { + if (event.key === 'Escape' || event.keyCode === 27) { + changeFocusModeState(false) + } + } + + focusModeEnableBtns.forEach((btn) => { + btn.addEventListener('click', ({ currentTarget }) => { + activeFieldEdit = currentTarget.closest('.ibexa-field-edit') + changeFocusModeState(true) + }, false) + }); + focusModeDisbaleBtns.forEach((btn) => { + btn.addEventListener('click', () => changeFocusModeState(false), false) + }); + + noticeContainers.forEach((noticeContainer) => { + const alerts = noticeContainer.querySelectorAll('.ibexa-alert'); + + alerts.forEach((alert) => { + alert.addEventListener('closed.bs.alert', () => { + const container = noticeContainer.closest('.ibexa-field-edit'); + const editorUiInstance = getEditorUiInstance(container); + + editorUiInstance.fire('ibexa-rt-update-ui'); + }); + }) + }); + + doc.body.addEventListener(ENABLE_FOCUS_MODE_EVENT_NAME, () => doc.body.addEventListener('keydown', watchDisableFocusModeByKeyboard), false); + doc.body.addEventListener(DISABLE_FOCUS_MODE_EVENT_NAME, () => doc.body.removeEventListener('keydown', watchDisableFocusModeByKeyboard), false); +})(window, window.document, window.ibexa); \ No newline at end of file diff --git a/src/bundle/Resources/public/scss/_alerts.scss b/src/bundle/Resources/public/scss/_alerts.scss index 404ae487fc..11a93e814f 100644 --- a/src/bundle/Resources/public/scss/_alerts.scss +++ b/src/bundle/Resources/public/scss/_alerts.scss @@ -199,4 +199,14 @@ } } } + + &--complementary { + color: $ibexa-color-complementary-700; + background-color: $ibexa-color-complementary-100; + border-color: $ibexa-color-complementary; + + .ibexa-icon { + fill: $ibexa-color-complementary-700; + } + } } diff --git a/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss b/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss index 7ee540cd04..96ccb071bc 100644 --- a/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss +++ b/src/bundle/Resources/public/scss/fieldType/edit/_base-field.scss @@ -15,6 +15,35 @@ color: $ibexa-color-danger; } + &__focus-mode { + display: flex; + flex-direction: column; + height: auto; + background: $ibexa-color-white; + border-radius: $ibexa-border-radius $ibexa-border-radius 0 0; + } + + &__focus-mode-notice-container { + display: none; + } + + &__focus-mode-control-container { + display: flex; + align-self: flex-end; + } + + &__focus-mode-control-btn { + align-self: flex-end; + + &--enable { + display: inline-flex; + } + + &--disable { + display: none; + } + } + .ibexa-input-text-wrapper { width: auto; } @@ -59,6 +88,108 @@ } } } + + &--has-focus-mode { + display: flex; + flex-wrap: wrap; + + .ibexa-field-edit { + &__focus-mode { + margin: auto 0 0 0; + align-self: baseline; + } + + &__label-wrapper { + width: 80%; + } + + &__focus-mode { + width: 20%; + } + + &__data { + width: 100%; + } + } + } + + &--in-focus-mode { + position: fixed; + top: 0; + left: 0; + z-index: 1080; + flex-direction: column; + width: 100vw; + height: 100vh; + padding: calculateRem(16px); + background: $ibexa-color-black; + + .ibexa-field-edit { + &__label-wrapper { + display: none; + } + + &__focus-mode { + width: 100%; + height: fit-content; + padding: calculateRem(32px) calculateRem(32px) 0 calculateRem(32px); + } + + &__focus-mode-notice-container { + display: block; + width: 100%; + } + + &__focus-mode-control-container { + height: calculateRem(40px); + } + + &__focus-mode-control-btn { + margin: 0; + + &--enable { + display: none; + } + + &--disable { + display: inline-flex; + } + } + + &__data { + width: 100%; + overflow-y: auto; + align-self: stretch; + flex-grow: 1; + padding: calculateRem(8px) calculateRem(32px) calculateRem(32px) calculateRem(32px); + background: $ibexa-color-white; + border-radius: 0 0 $ibexa-border-radius $ibexa-border-radius; + + .ibexa-data-source { + height: 100%; + } + } + } + + .ibexa-alert { + margin-bottom: calculateRem(4px); + } + } + + &--in-focus-mode.is-invalid { + .ibexa-field-edit { + &__data { + border-radius: 0; + padding-bottom: 0; + } + } + + .ibexa-form-error { + padding: calculateRem(16px) calculateRem(32px); + background: $ibexa-color-white; + border-radius: 0 0 $ibexa-border-radius $ibexa-border-radius; + } + } } .ibexa-content-edit { diff --git a/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig b/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig index 44d7dfdb3f..c8209085e5 100644 --- a/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig +++ b/src/bundle/Resources/views/themes/admin/content/form_fields.html.twig @@ -80,9 +80,10 @@ {% set fieldtype_identifier = fieldtype.vars.value.fieldDefinition.fieldTypeIdentifier %} {% set translation_mode = fieldtype.vars.mainLanguageCode != fieldtype.vars.languageCode %} {% set fieldtype_is_not_translatable = translation_mode and not fieldtype.vars.value.fieldDefinition.isTranslatable %} + {% set has_focus_mode = fieldtype_identifier == 'ezrichtext' %} {% set widget_wrapper_attr = widget_wrapper_attr|default({})|merge({'class': (widget_wrapper_attr.class|default('') ~ ' ibexa-field-edit__data ibexa-field-edit__data')|trim}) %} - {% set wrapper_class = 'ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier ~ ' ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier %} + {% set wrapper_class = 'ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier ~ ' ibexa-field-edit ibexa-field-edit--' ~ fieldtype_identifier ~ (has_focus_mode ? ' ibexa-field-edit--has-focus-mode') %} {% if fieldtype.vars.disabled %} {% set wrapper_class = wrapper_class ~ ' ibexa-field-edit--disabled ibexa-field-edit--disabled' %} @@ -114,9 +115,13 @@
- {% with { 'compound': false } %}{{- block('form_label') }}{% endwith %} + {% with { 'compound': false } %}{{ block('form_label') }}{% endwith %}
+ {% if has_focus_mode %} + {{- block('focus_mode') }} + {% endif %} + {% if widget_container_block is defined %} {{ widget_container_block|raw }} {% else %} diff --git a/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig b/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig index a599b77d89..61d124552c 100644 --- a/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig +++ b/src/bundle/Resources/views/themes/admin/ui/form_fields.html.twig @@ -270,7 +270,6 @@ {%- block richtext_widget -%} {% set attr = attr|merge({ 'hidden': true }) %} -
@@ -500,3 +499,43 @@ {{- form_errors(form) -}}
{%- endblock %} + +{%- block focus_mode -%} + {%- set title_icon -%} + + + + {%- endset -%} + {%- set title -%} + {{ 'focus_mode.disbale_hint'|trans({ '%icon%': title_icon|raw })|desc('To exit distraction free mode, click the %icon% or press Esc')|raw }} + {%- endset -%} + +
+
+ {% include '@ibexadesign/ui/component/alert/alert.html.twig' with { + type: 'complementary', + title, + icon_path: ibexa_icon_path('system-information'), + show_close_btn: true + } only %} +
+
+ + +
+
+{%- endblock -%}