123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140 |
- import {ReactNode, useCallback} from 'react';
- import styled from '@emotion/styled';
- import debounce from 'lodash/debounce';
- import useSplitPanelTracking from 'sentry/utils/replays/hooks/useSplitPanelTracking';
- import {useResizableDrawer} from 'sentry/utils/useResizableDrawer';
- import SplitDivider from 'sentry/views/replays/detail/layout/splitDivider';
- type Side = {
- content: ReactNode;
- default: number;
- max: number;
- min: number;
- };
- type Props =
- | {
- availableSize: number;
- /**
- * Content on the right side of the split
- */
- left: Side;
- /**
- * Content on the left side of the split
- */
- right: ReactNode;
- }
- | {
- availableSize: number;
- /**
- * Content below the split
- */
- bottom: ReactNode;
- /**
- * Content above of the split
- */
- top: Side;
- };
- function SplitPanel(props: Props) {
- const isLeftRight = 'left' in props;
- const initialSize = isLeftRight ? props.left.default : props.top.default;
- const min = isLeftRight ? props.left.min : props.top.min;
- const max = isLeftRight ? props.left.max : props.top.max;
- const {setStartPosition, logEndPosition} = useSplitPanelTracking({
- slideDirection: isLeftRight ? 'leftright' : 'updown',
- });
- // eslint-disable-next-line react-hooks/exhaustive-deps
- const onResize = useCallback(
- debounce(newSize => logEndPosition(`${(newSize / props.availableSize) * 100}%`), 750),
- [debounce, logEndPosition, props.availableSize]
- );
- const {
- isHeld,
- onDoubleClick,
- onMouseDown: onDragStart,
- size: containerSize,
- } = useResizableDrawer({
- direction: isLeftRight ? 'left' : 'down',
- initialSize,
- min,
- onResize,
- });
- const sizePct = `${
- (Math.min(containerSize, max) / props.availableSize) * 100
- }%` as `${number}%`;
- const handleMouseDown = useCallback(
- event => {
- setStartPosition(sizePct);
- onDragStart(event);
- },
- [setStartPosition, onDragStart, sizePct]
- );
- if (isLeftRight) {
- const {left: a, right: b} = props;
- return (
- <SplitPanelContainer
- className={isHeld ? 'disable-iframe-pointer' : undefined}
- orientation="columns"
- size={sizePct}
- >
- <Panel>{a.content}</Panel>
- <SplitDivider
- data-is-held={isHeld}
- data-slide-direction="leftright"
- onDoubleClick={onDoubleClick}
- onMouseDown={handleMouseDown}
- />
- <Panel>{b}</Panel>
- </SplitPanelContainer>
- );
- }
- const {top: a, bottom: b} = props;
- return (
- <SplitPanelContainer
- orientation="rows"
- size={sizePct}
- className={isHeld ? 'disable-iframe-pointer' : undefined}
- >
- <Panel>{a.content}</Panel>
- <SplitDivider
- data-is-held={isHeld}
- data-slide-direction="updown"
- onDoubleClick={onDoubleClick}
- onMouseDown={handleMouseDown}
- />
- <Panel>{b}</Panel>
- </SplitPanelContainer>
- );
- }
- const SplitPanelContainer = styled('div')<{
- orientation: 'rows' | 'columns';
- size: `${number}px` | `${number}%`;
- }>`
- width: 100%;
- height: 100%;
- position: relative;
- display: grid;
- overflow: auto;
- grid-template-${p => p.orientation}: ${p => p.size} auto 1fr;
- &.disable-iframe-pointer iframe {
- pointer-events: none !important;
- }
- `;
- const Panel = styled('div')`
- overflow: hidden;
- `;
- export default SplitPanel;
|