<commit_before>import React from 'react';
import { Slot } from 'react-plugin';
import styled from 'styled-components';
import { useDrag } from '../../shared/ui';
import { NAV_WIDTH_DEFAULT, restrictNavWidth } from './shared';

type Props = {
  storageCacheReady: boolean;
  fullScreen: boolean;
  navWidth: number;
  setNavWidth: (width: number) => unknown;
};

// TODO: Create slot inside previewContainer for notifications
export function Layout({
  storageCacheReady,
  fullScreen,
  navWidth,
  setNavWidth
}: Props) {
  const handleNavWidthChange = React.useCallback(
    (newWidth: number) => setNavWidth(restrictNavWidth(newWidth)),
    [setNavWidth]
  );
  const { dragElRef, dragging } = useDrag({
    value: navWidth,
    onChange: handleNavWidthChange
  });

  if (!storageCacheReady) {
    return <Container />;
  }

  if (fullScreen) {
    return (
      <Container>
        <Center key="center" style={{ zIndex: 1 }}>
          <PreviewContainer key="previewContainer">
            <Slot name="rendererPreview" />
            <Slot name="contentOverlay" />
          </PreviewContainer>
        </Center>
        <div style={{ zIndex: 2 }}>
          <Slot name="global" />
        </div>
      </Container>
    );
  }

  // z indexes are set here on purpose to show the layer hierarchy at a glance
  return (
    <Container>
      <Left style={{ zIndex: 2, width: navWidth }}>
        <Slot name="left" />
        <DragHandle ref={dragElRef} />
      </Left>
      <Center key="center" style={{ zIndex: 1 }}>
        <Slot name="rendererHeader" />
        <PreviewContainer key="previewContainer">
          <Slot name="rendererPreview" />
          <Slot name="contentOverlay" />
        </PreviewContainer>
        {dragging && <CenterDragOverlay />}
      </Center>
      <div style={{ zIndex: 3 }}>
        <Slot name="right" />
      </div>
      <div style={{ zIndex: 4 }}>
        <Slot name="global" />
      </div>
    </Container>
  );
}

const Container = styled.div`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
`;

const Left = styled.div`
  flex-shrink: 0;
  position: relative;
  width: ${NAV_WIDTH_DEFAULT}px;
  border-right: 1px solid var(--darkest);
`;

const Center = styled.div`
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  background: var(--grey6);
  color: var(--grey2);
  overflow: hidden;
`;

const PreviewContainer = styled.div`
  flex: 1;
  display: flex;
  position: relative;
  overflow: hidden;
`;

// The purpose of CenterDragOverlay is to cover the content area, which can
// contain the renderer preview iframe, while dragging because document
// 'mousemove' events are no longer captured while hovering over an iframe
const CenterDragOverlay = styled.div`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
`;

const DragHandle = styled.div`
  position: absolute;
  top: 0;
  right: -3px;
  width: 5px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
`;<commit_msg>Keep steady cursor while dragging (#962)<commit_after>import React from 'react';
import { Slot } from 'react-plugin';
import styled from 'styled-components';
import { useDrag } from '../../shared/ui';
import { NAV_WIDTH_DEFAULT, restrictNavWidth } from './shared';

type Props = {
  storageCacheReady: boolean;
  fullScreen: boolean;
  navWidth: number;
  setNavWidth: (width: number) => unknown;
};

// TODO: Create slot inside previewContainer for notifications
export function Layout({
  storageCacheReady,
  fullScreen,
  navWidth,
  setNavWidth
}: Props) {
  const handleNavWidthChange = React.useCallback(
    (newWidth: number) => setNavWidth(restrictNavWidth(newWidth)),
    [setNavWidth]
  );
  const { dragElRef, dragging } = useDrag({
    value: navWidth,
    onChange: handleNavWidthChange
  });

  if (!storageCacheReady) {
    return <Container />;
  }

  if (fullScreen) {
    return (
      <Container>
        <Center key="center" style={{ zIndex: 1 }}>
          <PreviewContainer key="previewContainer">
            <Slot name="rendererPreview" />
            <Slot name="contentOverlay" />
          </PreviewContainer>
        </Center>
        <div style={{ zIndex: 2 }}>
          <Slot name="global" />
        </div>
      </Container>
    );
  }

  // z indexes are set here on purpose to show the layer hierarchy at a glance
  return (
    <Container draggingNav={dragging}>
      <Left style={{ zIndex: 2, width: navWidth }}>
        <Slot name="left" />
        {dragging && <DragOverlay />}
        <DragHandle ref={dragElRef} />
      </Left>
      <Center key="center" style={{ zIndex: 1 }}>
        <Slot name="rendererHeader" />
        <PreviewContainer key="previewContainer">
          <Slot name="rendererPreview" />
          <Slot name="contentOverlay" />
        </PreviewContainer>
        {dragging && <DragOverlay />}
      </Center>
      <div style={{ zIndex: 3 }}>
        <Slot name="right" />
      </div>
      <div style={{ zIndex: 4 }}>
        <Slot name="global" />
      </div>
    </Container>
  );
}

const Container = styled.div<{ draggingNav?: boolean }>`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  cursor: ${props => (props.draggingNav ? 'col-resize' : 'default')};
`;

const Left = styled.div`
  flex-shrink: 0;
  position: relative;
  width: ${NAV_WIDTH_DEFAULT}px;
  border-right: 1px solid var(--darkest);
`;

const Center = styled.div`
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  background: var(--grey6);
  color: var(--grey2);
  overflow: hidden;
`;

const PreviewContainer = styled.div`
  flex: 1;
  display: flex;
  position: relative;
  overflow: hidden;
`;

const DragHandle = styled.div`
  position: absolute;
  top: 0;
  right: -3px;
  width: 5px;
  height: 100%;
  cursor: col-resize;
  user-select: none;
`;

// The purpose of DragOverlay is to cover other elements while dragging, such
// as the renderer preview iframe, which sucks up `mousemove` events, or the
// links in the fixture tree view which change the mouse cursor.
const DragOverlay = styled.div`
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
`;
{'fraction_non_alphanumeric': 0.13875443691513392, 'fraction_numerical': 0.008873830267828332, 'mean_word_length': 2.896291640477687, 'pattern_counts': {'":': 0, '<': 69, '<?xml version=': 0, '>': 74, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5934859', 'n_tokens_mistral': 1997, 'n_tokens_neox': 1950, 'n_words': 558}