Skip to content

Commit

Permalink
Revert "ref(js): Convert PageOverlay to a FC (#55168)"
Browse files Browse the repository at this point in the history
This reverts commit af2d0cd.

Co-authored-by: JoshFerge <1976777+JoshFerge@users.noreply.github.com>
  • Loading branch information
getsentry-bot and JoshFerge committed Aug 30, 2023
1 parent 8c5517b commit deda491
Showing 1 changed file with 98 additions and 83 deletions.
181 changes: 98 additions & 83 deletions static/app/components/pageOverlay.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {useEffect, useRef} from 'react';
import {Component, createRef} from 'react';
import {css} from '@emotion/react';
import styled from '@emotion/styled';
import {motion} from 'framer-motion';
Expand Down Expand Up @@ -105,6 +105,8 @@ type Props = {
customWrapper?: React.ComponentType;
};

type DefaultProps = Pick<Props, 'positioningStrategy'>;

/**
* When a background with a anchor is used and no positioningStrategy is
* provided, by default we'll align the top left of the container to the anchor
Expand All @@ -127,96 +129,109 @@ const defaultPositioning = ({mainRect, anchorRect}: PositioningStrategyOpts) =>
* wrapper to a safe space in the background to aid in alignment of the wrapper
* to a safe space in the background.
*/
function PageOverlay({
positioningStrategy = defaultPositioning,
text,
animateDelay,
background: BackgroundComponent,
customWrapper,
children,
}: Props) {
const contentRef = useRef<HTMLDivElement>(null);
const wrapperRef = useRef<HTMLDivElement>(null);
const anchorRef = useRef<SVGForeignObjectElement>(null);

useEffect(() => {
if (contentRef.current === null || anchorRef.current === null) {
return () => {};
class PageOverlay extends Component<Props> {
static defaultProps: DefaultProps = {
positioningStrategy: defaultPositioning,
};

componentDidMount() {
if (this.contentRef.current === null || this.anchorRef.current === null) {
return;
}

/**
* Align the wrapper component to the anchor by computing x/y values using
* the passed function. By default if no function is specified it will align
* to the top left of the anchor.
*/
function anchorWrapper() {
if (
contentRef.current === null ||
wrapperRef.current === null ||
anchorRef.current === null
) {
return;
}

// Absolute position the container, this avoids the browser having to reflow
// the component
wrapperRef.current.style.position = 'absolute';
wrapperRef.current.style.left = `0px`;
wrapperRef.current.style.top = `0px`;

const mainRect = contentRef.current.getBoundingClientRect();
const anchorRect = anchorRef.current.getBoundingClientRect();
const wrapperRect = wrapperRef.current.getBoundingClientRect();

// Compute the position of the wrapper
const {x, y} = positioningStrategy({mainRect, anchorRect, wrapperRect});

const transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`;
wrapperRef.current.style.transform = transform;
this.anchorWrapper();

// Observe changes to the upsell container to reanchor if available
if (window.ResizeObserver) {
this.bgResizeObserver = new ResizeObserver(this.anchorWrapper);
this.bgResizeObserver.observe(this.contentRef.current);
}
}

componentWillUnmount() {
this.bgResizeObserver?.disconnect();
}

anchorWrapper();
/**
* Used to re-anchor the text wrapper to the anchor point in the background when
* the size of the page changes.
*/
bgResizeObserver: ResizeObserver | null = null;

/**
* Used to re-anchor the text wrapper to the anchor point in the background when
* the size of the page changes.
*/
let bgResizeObserver: ResizeObserver | null = null;
contentRef = createRef<HTMLDivElement>();
wrapperRef = createRef<HTMLDivElement>();
anchorRef = createRef<SVGForeignObjectElement>();

// Observe changes to the upsell container to reanchor if available
if (window.ResizeObserver) {
bgResizeObserver = new ResizeObserver(anchorWrapper);
bgResizeObserver.observe(contentRef.current);
/**
* Align the wrapper component to the anchor by computing x/y values using
* the passed function. By default if no function is specified it will align
* to the top left of the anchor.
*/
anchorWrapper = () => {
if (
this.contentRef.current === null ||
this.wrapperRef.current === null ||
this.anchorRef.current === null
) {
return;
}

return () => bgResizeObserver?.disconnect();
}, [positioningStrategy]);

const Wrapper = customWrapper ?? DefaultWrapper;

const transition = testableTransition({
delay: 1,
duration: 1.2,
ease: 'easeInOut',
delayChildren: animateDelay ?? (BackgroundComponent ? 0.5 : 1.5),
staggerChildren: 0.15,
});

return (
<MaskedContent>
{children}
<ContentWrapper ref={contentRef} transition={transition} variants={{animate: {}}}>
{BackgroundComponent && (
<Background>
<BackgroundComponent anchorRef={anchorRef} />
</Background>
)}
<Wrapper ref={wrapperRef}>
<Text>{text({Body, Header})}</Text>
</Wrapper>
</ContentWrapper>
</MaskedContent>
);
// Absolute position the container, this avoids the browser having to reflow
// the component
this.wrapperRef.current.style.position = 'absolute';
this.wrapperRef.current.style.left = `0px`;
this.wrapperRef.current.style.top = `0px`;

const mainRect = this.contentRef.current.getBoundingClientRect();
const anchorRect = this.anchorRef.current.getBoundingClientRect();
const wrapperRect = this.wrapperRef.current.getBoundingClientRect();

// Compute the position of the wrapper
const {x, y} = this.props.positioningStrategy({mainRect, anchorRect, wrapperRect});

const transform = `translate(${Math.round(x)}px, ${Math.round(y)}px)`;
this.wrapperRef.current.style.transform = transform;
};

render() {
const {
text,
children,
animateDelay,
background: BackgroundComponent,
customWrapper,
...props
} = this.props;
const Wrapper = customWrapper ?? DefaultWrapper;

const transition = testableTransition({
delay: 1,
duration: 1.2,
ease: 'easeInOut',
delayChildren: animateDelay ?? (BackgroundComponent ? 0.5 : 1.5),
staggerChildren: 0.15,
});

return (
<MaskedContent {...props}>
{children}
<ContentWrapper
ref={this.contentRef}
transition={transition}
variants={{animate: {}}}
>
{BackgroundComponent && (
<Background>
<BackgroundComponent anchorRef={this.anchorRef} />
</Background>
)}
<Wrapper ref={this.wrapperRef}>
<Text>{text({Body, Header})}</Text>
</Wrapper>
</ContentWrapper>
</MaskedContent>
);
}
}

const absoluteFull = css`
Expand Down

0 comments on commit deda491

Please sign in to comment.