Skip to content

Commit

Permalink
Renames and cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
stokesman committed Jul 21, 2021
1 parent f1463db commit 8236655
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 41 deletions.
21 changes: 12 additions & 9 deletions packages/widgets/src/blocks/legacy-widget/edit/form.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { closeSmall } from '@wordpress/icons';
* Internal dependencies
*/
import Control from './control';
import { useBudgeTopBy } from './utils';
import { useAlignTopWithinViewport } from './utils';

export default function Form( {
title,
Expand Down Expand Up @@ -109,7 +109,7 @@ export default function Form( {

if ( isWide ) {
return (
<WideFormDialog isVisible={ isVisible }>
<WideFormDialog isVisible={ isVisible } onClose={ onClose }>
{ formCore }
</WideFormDialog>
);
Expand All @@ -125,24 +125,27 @@ export default function Form( {
);
}

function WideFormDialog( { isVisible, children } ) {
const containerRef = useRef();
const [ dialogRef, dialogProps ] = useDialog( { focusOnMount: false } );
function WideFormDialog( { isVisible, onClose, children } ) {
const ref = useRef();
const [ dialogRef, dialogProps ] = useDialog( {
focusOnMount: false,
onClose,
} );
const {
ref: budgeRef,
ref: alignTopRef,
resizeObserver,
} = useBudgeTopBy( containerRef.current, { isEnabled: isVisible } );
} = useAlignTopWithinViewport( ref.current, { isEnabled: isVisible } );
return (
<div
ref={ containerRef }
ref={ ref }
className={ classnames( 'wp-block-legacy-widget__container', {
'is-visible': isVisible,
} ) }
>
<Fill name="Popover">
<div
className="wp-block-legacy-widget__edit-form is-wide"
ref={ useMergeRefs( [ dialogRef, budgeRef ] ) }
ref={ useMergeRefs( [ dialogRef, alignTopRef ] ) }
{ ...dialogProps }
hidden={ ! isVisible }
>
Expand Down
61 changes: 30 additions & 31 deletions packages/widgets/src/blocks/legacy-widget/edit/utils.js
Original file line number Diff line number Diff line change
@@ -1,104 +1,103 @@
/**
* WordPress dependencies
*/
import { useRef, useLayoutEffect, useState } from '@wordpress/element';
import { useResizeObserver } from '@wordpress/compose';
import { useRef, useLayoutEffect, useState } from '@wordpress/element';

/**
* Positions an element by the top of an objective element if it can fit or
* Positions an element by the top of an anchor element if it can fit or
* otherwise as close as possible within the window.
*
* @param {Element} objective Element to take position from.
* @param {Element} anchor Element to take position from.
* @param {Object} $1 Options.
* @param {boolean} $1.isEnabled Whether to apply the hook or not.
*
* @return {Object} A ref and resize observer element.
*/
export function useBudgeTopBy( objective, { isEnabled } ) {
const subjectRef = useRef();
const objectiveRef = useRef();
export function useAlignTopWithinViewport( anchor, { isEnabled } ) {
const ref = useRef();
const anchorRef = useRef();
const [
{ start: boundsStart, end: boundsEnd } = {},
setBounds,
] = useState();
const boundsUpdaterRef = useRef();

const hasSubject = !! subjectRef.current;
const hasObjective = !! objective;
const objectiveHasChanged = objectiveRef.current !== objective;
objectiveRef.current = objective;
const hasRef = !! ref.current;
const hasAnchor = !! anchor;
const anchorHasChanged = anchorRef.current !== anchor;
anchorRef.current = anchor;

// Defines the bounds updating function a single time
if ( ! boundsUpdaterRef.current ) {
boundsUpdaterRef.current = () => {
const { defaultView } = subjectRef.current.ownerDocument;
const { defaultView } = ref.current.ownerDocument;
setBounds( { start: 0, end: defaultView.innerHeight } );
};
}

// Sets the bounds height and handles window resizes to update it
useLayoutEffect( () => {
if ( ! hasSubject || ! hasObjective || ! isEnabled ) {
if ( ! hasRef || ! isEnabled ) {
return;
}
boundsUpdaterRef.current();
const { defaultView } = objective.ownerDocument;
const { defaultView } = ref.current.ownerDocument;
const updateBounds = boundsUpdaterRef.current;
defaultView.addEventListener( 'resize', updateBounds );
return () => defaultView.removeEventListener( 'resize', updateBounds );
}, [ hasObjective, hasSubject, isEnabled ] );
}, [ hasRef, isEnabled ] );

const [ resizeObserver, contentSize ] = useResizeObserver();

// Handles scrolling, if needed, to update subject position
// Handles scrolling, if needed, to update positioning
useLayoutEffect( () => {
if ( ! isEnabled || ! hasSubject || ! hasObjective ) {
if ( ! isEnabled || ! hasRef || ! hasAnchor ) {
return;
}
// The subject fills the bounds so scroll handling is not needed.
// Positions subject at the top of bounds and returns.
// The element fills the bounds so scroll handling is not needed.
// Positions it at the top of bounds and returns.
if ( contentSize.height >= boundsEnd ) {
// subjectRef.current.style.top = '0px';
subjectRef.current.style.setProperty( '--budge-top', '0px' );
ref.current.style.setProperty( '--align-top', '0px' );
return;
}
const layout = () => {
const objectiveRect = objectiveRef.current.getBoundingClientRect();
let { top } = objectiveRect;
const anchorRect = anchorRef.current.getBoundingClientRect();
let { top } = anchorRect;
const height = contentSize.height;
const bottom = top + height;
if ( top < boundsStart || bottom > boundsEnd ) {
const fromTop = Math.abs( boundsStart - top );
const fromBottom = Math.abs( boundsEnd - bottom );
top = fromTop < fromBottom ? boundsStart : boundsEnd - height;
}
subjectRef.current.style.setProperty( '--budge-top', top + 'px' );
ref.current.style.setProperty( '--align-top', top + 'px' );
};
layout();
const { defaultView } = objective.ownerDocument;
const { defaultView } = anchor.ownerDocument;
const options = { capture: true, passive: true };
defaultView.addEventListener( 'scroll', layout, options );
return () => {
defaultView.removeEventListener( 'scroll', layout, options );
};
}, [
hasSubject,
objectiveHasChanged,
hasRef,
anchorHasChanged,
contentSize.height,
boundsStart,
boundsEnd,
isEnabled,
] );

// Cleans up subject styles when not enabled
// Cleans up styles when not enabled
useLayoutEffect( () => {
if ( isEnabled && !! subjectRef.current ) {
const subject = subjectRef.current;
if ( isEnabled && !! ref.current ) {
const element = ref.current;
return () => {
subject.style.removeProperty( '--budge-top' );
element.style.removeProperty( '--align-top' );
};
}
}, [ isEnabled ] );

return { ref: subjectRef, resizeObserver };
return { ref, resizeObserver };
}
2 changes: 1 addition & 1 deletion packages/widgets/src/blocks/legacy-widget/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ $wide-header-height: 46px;
&.is-wide {
flex-direction: column;
position: fixed;
top: max(#{$wide-header-height}, var(--budge-top, 0));
top: max(#{$wide-header-height}, var(--align-top, 0));
left: 299px;
min-width: 300px;
width: calc(100vw - 299px);
Expand Down

0 comments on commit 8236655

Please sign in to comment.