From 42c2d1a175a0b3b7f688203d435e498160a0d13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Grabowski?= Date: Thu, 7 Nov 2024 17:30:48 +0100 Subject: [PATCH] minor fixes --- .../ui/modules/common/_draggable.dialog.scss | 4 +++ .../scss/ui/modules/common/_popup.menu.scss | 6 ++-- .../themes/admin/ui/form_fields.html.twig | 5 ++++ .../draggable-dialog/draggable.dialog.js | 28 ++++++++++++++++--- .../modules/common/popup-menu/popup.menu.js | 21 +++++++------- 5 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/bundle/Resources/public/scss/ui/modules/common/_draggable.dialog.scss b/src/bundle/Resources/public/scss/ui/modules/common/_draggable.dialog.scss index 8aaf740a99..9398d4a219 100644 --- a/src/bundle/Resources/public/scss/ui/modules/common/_draggable.dialog.scss +++ b/src/bundle/Resources/public/scss/ui/modules/common/_draggable.dialog.scss @@ -2,6 +2,10 @@ position: fixed; z-index: 10000; + &--hidden { + visibility: hidden; + } + &__draggable { cursor: grab; user-select: none; diff --git a/src/bundle/Resources/public/scss/ui/modules/common/_popup.menu.scss b/src/bundle/Resources/public/scss/ui/modules/common/_popup.menu.scss index 773aeea498..72ca05fad2 100644 --- a/src/bundle/Resources/public/scss/ui/modules/common/_popup.menu.scss +++ b/src/bundle/Resources/public/scss/ui/modules/common/_popup.menu.scss @@ -1,5 +1,5 @@ .c-popup-menu { - display: none; + display: flex; flex-direction: column; gap: calculateRem(1px); padding: calculateRem(8px) 0; @@ -10,8 +10,8 @@ position: fixed; z-index: 1060; - &--visible { - display: flex; + &--hidden { + visibility: hidden; } &__search { 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 cc7adcf1ef..639a3ee78f 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 @@ -399,6 +399,11 @@ {% block content %} {{ input_html }} {% endblock %} + + {% block actions %} + {{ parent() }} + {{ extra_actions_after|default()}} + {% endblock %} {%- endembed -%} {%- else -%} {{ parent() }} diff --git a/src/bundle/ui-dev/src/modules/common/draggable-dialog/draggable.dialog.js b/src/bundle/ui-dev/src/modules/common/draggable-dialog/draggable.dialog.js index 2e6384992e..8f4f3a8afc 100644 --- a/src/bundle/ui-dev/src/modules/common/draggable-dialog/draggable.dialog.js +++ b/src/bundle/ui-dev/src/modules/common/draggable-dialog/draggable.dialog.js @@ -2,6 +2,7 @@ import React, { useRef, createContext, useState, useEffect } from 'react'; import PropTypes from 'prop-types'; import { getRootDOMElement } from '@ibexa-admin-ui/src/bundle/Resources/public/js/scripts/helpers/context.helper'; +import { createCssClassNames } from '@ibexa-admin-ui/src/bundle/ui-dev/src/modules/common/helpers/css.class.names'; export const DraggableContext = createContext(); @@ -11,10 +12,14 @@ const DraggableDialog = ({ children, referenceElement, positionOffset }) => { const dragOffsetPosition = useRef({ x: 0, y: 0 }); const containerSize = useRef({ width: 0, height: 0 }); const [isDragging, setIsDragging] = useState(false); - const [coords, setCoords] = useState({ x: 0, y: 0 }); + const [coords, setCoords] = useState({ x: null, y: null }); + const dialogClasses = createCssClassNames({ + 'c-draggable-dialog': true, + 'c-draggable-dialog--hidden': coords.x === null || coords.y === null, + }); const containerAttrs = { ref: containerRef, - className: 'c-draggable-dialog', + className: dialogClasses, style: { top: coords.y, left: coords.x, @@ -96,11 +101,26 @@ const DraggableDialog = ({ children, referenceElement, positionOffset }) => { useEffect(() => { const { top: referenceTop, left: referenceLeft } = referenceElement.getBoundingClientRect(); + const { width: containerWidth, height: containerHeight } = containerRef.current.getBoundingClientRect(); const { x: offsetX, y: offsetY } = positionOffset(referenceElement); + let x = referenceLeft + offsetX; + let y = referenceTop + offsetY; + + if (x < 0) { + x = 0; + } else if (x + containerWidth > window.innerWidth) { + x = window.innerWidth - containerWidth; + } + + if (y < 0) { + y = 0; + } else if (y + containerHeight > window.innerHeight) { + y = window.innerHeight - containerHeight; + } setCoords({ - top: referenceTop + offsetY, - left: referenceLeft + offsetX, + x, + y, }); }, [referenceElement]); diff --git a/src/bundle/ui-dev/src/modules/common/popup-menu/popup.menu.js b/src/bundle/ui-dev/src/modules/common/popup-menu/popup.menu.js index b172d79dd4..a774e29cc3 100644 --- a/src/bundle/ui-dev/src/modules/common/popup-menu/popup.menu.js +++ b/src/bundle/ui-dev/src/modules/common/popup-menu/popup.menu.js @@ -8,10 +8,10 @@ import Icon from '@ibexa-admin-ui/src/bundle/ui-dev/src/modules/common/icon/icon const MIN_SEARCH_ITEMS_DEFAULT = 5; const MIN_ITEMS_LIST_HEIGHT = 150; -const PopupMenu = ({ extraClasses, footer, items, onItemClick, positionOffset, referenceElement, scrollContainer }) => { +const PopupMenu = ({ extraClasses, footer, items, onItemClick, positionOffset, referenceElement, scrollContainer, onClose }) => { const Translator = getTranslator(); const containerRef = useRef(); - const [isVisible, setIsVisible] = useState(true); + const [isRendered, setIsRendered] = useState(false); const [itemsListStyles, setItemsListStyles] = useState({ left: 0, top: 0, @@ -20,7 +20,7 @@ const PopupMenu = ({ extraClasses, footer, items, onItemClick, positionOffset, r const numberOfItems = useMemo(() => items.reduce((sum, group) => sum + group.items.length, 0), [items]); const popupMenuClassName = createCssClassNames({ 'c-popup-menu': true, - 'c-popup-menu--visible': isVisible, + 'c-popup-menu--hidden': !isRendered, [extraClasses]: true, }); const searchPlaceholder = Translator.trans(/*@Desc("Search...")*/ 'ibexa_popup_menu.search.placeholder', {}, 'ibexa_popup_menu'); @@ -77,13 +77,13 @@ const PopupMenu = ({ extraClasses, footer, items, onItemClick, positionOffset, r itemsStyles.top = referenceTop + offsetY; itemsStyles.left = referenceLeft + offsetX; - itemsStyles.maxHeight = window.innerHeight - bottom; + itemsStyles.maxHeight = window.innerHeight - itemsStyles.top; } else { const { x: offsetX, y: offsetY } = positionOffset(referenceElement, 'top'); itemsStyles.top = referenceTop + offsetY; itemsStyles.left = referenceLeft + offsetX; - itemsStyles.maxHeight = referenceTop; + itemsStyles.maxHeight = itemsStyles.top; itemsStyles.transform = 'translateY(-100%)'; } @@ -135,17 +135,14 @@ const PopupMenu = ({ extraClasses, footer, items, onItemClick, positionOffset, r useEffect(() => { calculateAndSetItemsListStyles(); - - if (!isVisible) { - return; - } + setIsRendered(true); const onInteractionOutside = (event) => { if (containerRef.current.contains(event.target) || referenceElement.contains(event.target)) { return; } - setIsVisible(false); + onClose(); }; window.document.body.addEventListener('click', onInteractionOutside, false); @@ -157,7 +154,7 @@ const PopupMenu = ({ extraClasses, footer, items, onItemClick, positionOffset, r setItemsListStyles({}); }; - }, [isVisible]); + }, [onClose, scrollContainer]); return (
@@ -178,6 +175,7 @@ PopupMenu.propTypes = { label: PropTypes.string, }), }), + onClose: PropTypes.func, onItemClick: PropTypes.func, positionOffset: PropTypes.func, scrollContainer: PropTypes.node, @@ -187,6 +185,7 @@ PopupMenu.defaultProps = { extraClasses: '', footer: null, items: [], + onClose: () => {}, onItemClick: () => {}, positionOffset: () => ({ x: 0, y: 0 }), scrollContainer: window.document.body,