diff --git a/src/components/PlaygroundComponent.css b/src/components/PlaygroundComponent.css index 294d334..e2a312a 100644 --- a/src/components/PlaygroundComponent.css +++ b/src/components/PlaygroundComponent.css @@ -220,7 +220,7 @@ } @media only screen and (min-width: 1650px) { - .cfp-root:not(.cfp-open-preview) .gu-unselectable .fjs-children.fjs-drop-container-vertical { + .cfp-root:not(.cfp-open-preview).cfp-dragging .fjs-children.fjs-drop-container-vertical { border-color: var(--drag-container-border-color); } } \ No newline at end of file diff --git a/src/components/PlaygroundComponent.js b/src/components/PlaygroundComponent.js index 075f0ae..3dddb79 100644 --- a/src/components/PlaygroundComponent.js +++ b/src/components/PlaygroundComponent.js @@ -64,6 +64,8 @@ export function PlaygroundComponent(props) { const resultContainerRef = useRef(null); const propertiesContainerRef = useRef(null); + const rootRef = useRef(null); + // (1) initialize playground orchestrator useEffect(() => { playgroundRef.current = new FormPlayground({ @@ -195,10 +197,45 @@ export function PlaygroundComponent(props) { return setContainersLayout(containers, false); }; - // (5) render + // (5) listen on dragging events to provide drop feedback + useEffect(() => { + + const bindDropTargetListeners = () => { + const editor = playgroundRef.current.getEditor(); + editor.on('drag.hover', function(event) { + + const { container } = event; + + if ( + container.classList.contains('fjs-drop-container-horizontal') || + container.classList.contains('fjs-drop-container-vertical') + ) { + rootRef.current.classList.add('cfp-dragging'); + } + }); + + editor.on('drag.out', function(event) { + rootRef.current.classList.remove('cfp-dragging'); + }); + }; + + const playground = playgroundRef.current; + + if (playground) { + playground.on('formPlayground.rendered', bindDropTargetListeners); + } + + return () => { + if (playground) { + playground.off('formPlayground.rendered', bindDropTargetListeners); + } + }; + }); + + // (6) render return html` <${LayoutContext.Provider} value=${ layoutContext }> -
+
<${CollapsiblePanel} idx="${ FORM_DEFINITION_IDX }" title="Form Definition"> diff --git a/test/spec/CamundaFormPlayground.spec.js b/test/spec/CamundaFormPlayground.spec.js index c759ac0..28c3f4a 100644 --- a/test/spec/CamundaFormPlayground.spec.js +++ b/test/spec/CamundaFormPlayground.spec.js @@ -344,4 +344,61 @@ describe('CamundaFormPlayground', function() { }); + + describe('dragging behavior', function() { + + let playground; + + beforeEach(async function() { + await waitFor(async () => { + playground = await createCamundaFormPlayground({ + container, + schema + }); + }); + }); + + it('should add drop target styles on ', async function() { + + // given + const formEditor = playground.getEditor(); + formEditor.get('eventBus').fire('formEditor.rendered'); + + // when + formEditor.get('eventBus').fire('drag.hover', { + container: domQuery('.fjs-drop-container-horizontal', container) + }); + + // then + const root = domQuery('.cfp-root', container); + + expect(root.classList.contains('cfp-dragging')).to.be.true; + }); + + + it('should remove drop target styles on ', async function() { + + // given + const formEditor = playground.getEditor(); + formEditor.get('eventBus').fire('formEditor.rendered'); + + // when + formEditor.get('eventBus').fire('drag.hover', { + container: domQuery('.fjs-drop-container-horizontal', container) + }); + + const root = domQuery('.cfp-root', container); + + // assume + expect(root.classList.contains('cfp-dragging')).to.be.true; + + // and when + formEditor.get('eventBus').fire('drag.out'); + + // then + expect(root.classList.contains('cfp-dragging')).to.be.false; + }); + + }); + }); \ No newline at end of file