From 4aceef184e9268e9f9202ae0ae542b4424d95592 Mon Sep 17 00:00:00 2001 From: Justin Toupin <justin@atendesigngroup.com> Date: Tue, 18 Mar 2025 09:36:48 -0600 Subject: [PATCH] Mark horizontal regions. Use appropriate indicators for left/right drag and drop. --- css/builder.css | 29 ++++++++++++++---- js/builder.js | 80 +++++++++++++++++++++++++++++++++++-------------- 2 files changed, 82 insertions(+), 27 deletions(-) diff --git a/css/builder.css b/css/builder.css index 8719660..3a9b842 100644 --- a/css/builder.css +++ b/css/builder.css @@ -263,10 +263,21 @@ top: 0; transform: translate(-50%, calc(-50% - 1.5px)); } +.lpb-horizontal-region .lpb-btn--add.before { + top: 50%; + left: 0; + transform: translate(calc(-50% - 1.5px), -50%); +} .lpb-btn--add.after { bottom: 0; transform: translate(-50%, calc(50% + 1.5px)); } +.lpb-horizontal-region .lpb-btn--add.after { + top: 50%; + left: 100%; + bottom: auto; + transform: translate(calc(-50% + 1.5px), -50%); +} /* - Sortable Drag States - */ @@ -280,22 +291,30 @@ outline: none !important; } .sortable-target--region { - box-shadow: inset 0 3px 0 blue; + box-shadow: inset 0 6px 0 blue; } .sortable-target--before { - box-shadow: 0 -3px 0 blue; + box-shadow: 0 -6px 0 blue; +} +.lpb-horizontal-region .sortable-target--before { + box-shadow: -6px 0 0 blue; } .sortable-target--after { - box-shadow: 0 3px 0 blue; + box-shadow: 0 6px 0 blue; +} +.lpb-horizontal-region .sortable-target--after { + box-shadow: 6px 0 0 blue; } -.js-lpb-component.is-dragging:not(.sortable-ghost) { +.js-lpb-component.is-dragging { cursor: grabbing; - background: #fff; } .js-lpb-component.is-dragging .js-lpb-region, .js-lpb-component.is-dragging .js-lpb-component { outline: none; } +.js-lpb-component.is-dragging .js-lpb-ui { + display: none; +} /* - Formatter Widget - */ diff --git a/js/builder.js b/js/builder.js index 604f799..a60f75f 100644 --- a/js/builder.js +++ b/js/builder.js @@ -482,18 +482,13 @@ /** * Initializes Sortable.js for drag-and-drop. - * @param {HTMLElement} element The builder element. + * @param {String} id The layout ID. + * @param {Array} containers The builder containers. * @param {Object} settings The builder settings. */ - function initSortable(element, settings) { - // Find all containers that should support drag-and-drop. - const containers = once( - 'is-sortable-enabled', - '.js-lpb-region, .js-lpb-component-list', - element, - ); - const id = element.getAttribute('data-lpb-id'); + function initSortable(id, containers, settings) { containers.forEach((container) => { + const element = container.closest(`[${idAttr}]`); Drupal.LPSortableInstances.add( id, new Sortable(container, { @@ -596,6 +591,42 @@ }); } + /** + * Adds a class to regions whose components flow horizontally. + * @param {Element} regions Region elements to check for horizontal flow. + */ + function markHorizontalRegions(regions) { + regions.forEach((region) => { + const components = Array.from( + region.querySelectorAll('.js-lpb-component'), + ); + if (components.length === 0) { + return; + } + const computedStyle = window.getComputedStyle(region); + const firstComponentStyle = window.getComputedStyle(components[0]); + // Check if the container is using flexbox + if (computedStyle.display.includes('flex')) { + const { flexDirection } = computedStyle; // row, column, etc. + if (flexDirection.includes('row')) { + region.classList.add('lpb-horizontal-region'); + } + } + // Check if the container is using grid + else if (computedStyle.display.includes('grid')) { + const gridTemplateColumns = + computedStyle.gridTemplateColumns.split(' ').length; + if (gridTemplateColumns > 1) { + region.classList.add('lpb-horizontal-region'); + } + } + // Check if float is applied to child elements + else if (firstComponentStyle.float !== 'none') { + region.classList.add('lpb-horizontal-region'); + } + }); + } + // An object with arrays for "accepts" and "moves" Sortable callback functions. Drupal._lpbMoveErrors = { accepts: [], @@ -708,11 +739,21 @@ } // Initialize Sortable.js for drag-and-drop. - selectAll('[data-lpb-id]').forEach((container) => { - const id = container.getAttribute('data-lpb-id'); - initSortable(container, settings.lpBuilder[id]); + selectAll('[data-lpb-id]').forEach((layoutElement) => { + const id = layoutElement.getAttribute('data-lpb-id'); + const containers = once( + 'is-sortable-enabled', + '.js-lpb-region, .js-lpb-component-list', + layoutElement, + ); + initSortable(id, containers, settings.lpBuilder[id]); }); + // Add classes to regions whose components flow horizontally. + markHorizontalRegions( + once('lpb-horizontal-regions', '.js-lpb-region:has(.js-lpb-component)'), + ); + // Dispatch lpb-init event on all layout paragraphs builders. once('lpb-init', '[data-lpb-id]', context).forEach((el) => { dispatch(el, 'lpb-init', { @@ -805,15 +846,8 @@ */ listen(document, 'dragstart', (event) => { if (event.target.classList.contains('js-lpb-component')) { - const clone = event.target.cloneNode(true); - Array.from(clone.querySelectorAll('.js-lpb-ui')).forEach((uiElement) => { - uiElement.remove(); - }); - clone.classList.add('is-dragging'); - clone.style.width = `${event.target.offsetWidth}px`; - clone.style.height = `${event.target.offsetHeight}px`; - document.body.append(clone); - event.dataTransfer.setDragImage(clone, event.layerX, event.layerY); + event.target.classList.add('is-dragging'); + event.dataTransfer.setDragImage(event.target, event.layerX, event.layerY); } }); @@ -821,7 +855,9 @@ * Removes the custom drag image when dragging has ended. */ listen(document, 'dragend', () => { - document.querySelector('.js-lpb-component.is-dragging')?.remove(); + document + .querySelector('.js-lpb-component.is-dragging') + ?.classList?.remove('is-dragging'); }); /** -- GitLab