import * as React from 'react' ; import { DefaultSplitter , Split , RenderSplitterProps } from '@geoffcox/react-splitter' ; import styled , { css } from 'styled-components' ; import { v4 as uuidv4 } from 'uuid' ; import { useRecoilCallback , useRecoilState , useRecoilValue } from 'recoil' ; import { createSplitOptions , splitStateFamily } from '../model/appModel' ; import { SplitNode } from '../model/types' ; import { VerticalStripedSplitter , HorizontalStripedSplitter , SolidSplitter } from './CustomSplitters' ; const fullDivCss = css `
  width: 100%;
  height: 100%;
  outline: none;
  overflow: hidden;
` ; const Root = styled . div `
  ${ fullDivCss }
  display: grid;
  grid-template-rows: 1fr;
  grid-template-columns: 1fr;
  grid-template-areas: 'content';
  user-select: none;
` ; const ActionsArea = styled . div `
  display: flex;
  flex-direction: column;
  justify-content: stretch;
  align-content: stretch;
  align-items: stretch;
  outline: none;
  overflow: hidden;
` ; const ActionButtons = styled . div `
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  justify-content: center;
  align-content: center;
  align-items: center;
  outline: none;
  overflow: hidden;
  margin: auto auto;
` ; const ActionButton = styled . button `
  padding: 5px;
  margin: 0 0 5px 5px;
  user-select: none;
` ; type Props = { id : string ; onRemove ? : ( childId : string ) => void ; onToggleParentSplit ? : ( ) => void ; } ; param props export const DynamicPane = ( props ) => { const { id , onRemove , onToggleParentSplit } = props ; const [ splitNode , setSplitNode ] = useRecoilState ( splitStateFamily ( id ) ) ; const { options , primaryId , secondaryId } = splitNode ; const createOptions = useRecoilValue ( createSplitOptions ) ; const onSplit = ( ) => { const primaryId = uuidv4 ( ) ; const secondaryId = uuidv4 ( ) ; const newNode = { ... splitNode , options : createOptions , primaryId , secondaryId , } ; setSplitNode ( newNode ) ; } ; const onRemoveChildPane = useRecoilCallback ( ( { snapshot , set , reset } ) => async ( childId ) => { const node = await snapshot . getPromise ( splitStateFamily ( id ) ) ; const remainingId = node ?. primaryId === childId ? node . secondaryId : node ?. secondaryId === childId ? node . primaryId : undefined ; if ( remainingId === undefined ) { return ; } const remainingNode = await snapshot . getPromise ( splitStateFamily ( remainingId ) ) ; set ( splitStateFamily ( id ) , { ... remainingNode , id : node . id , } ) ; reset ( splitStateFamily ( childId ) ) ; reset ( splitStateFamily ( remainingId ) ) ; } , [ id ] ) ; const onToggleSplit = ( ) => { const newNode = { ... splitNode , options : { ... createOptions , horizontal : ! splitNode . options ?. horizontal , } , } ; setSplitNode ( newNode ) ; } ; const renderActions = ( ) => { return ( < ActionsArea > < ActionButtons > < ActionButton onClick = { onSplit } > Split < /ActionButton> { onToggleParentSplit && ( < ActionButton onClick = { ( ) => onToggleParentSplit ?. ( ) } title = "Toggle Parent Split" > / < /ActionButton>)} { onRemove && ( < ActionButton onClick = { ( ) => onRemove ( id ) } title = "Remove Split" > X < /ActionButton>)} < /ActionButtons> < /ActionsArea>); } ; const renderSplitter = ( renderSplitterProps ) => { const { horizontal } = renderSplitterProps ; switch ( options ?. splitterType ) { case 'solid' : return < SolidSplitter />; case 'striped' : return horizontal ? < HorizontalStripedSplitter /> : <VerticalStripedSplitter / > ; default : return < DefaultSplitter { ... renderSplitterProps } color = "silver" hoverColor = "gray" / > ; } } ; const renderLeftRightSplit = ( ) => { return ( options && ( < Split initialPrimarySize = { options . initialPrimarySize } minPrimarySize = { options . minPrimarySize } minSecondarySize = { options . minSecondarySize } renderSplitter = { renderSplitter } splitterSize = { options . splitterSize } resetOnDoubleClick > { primaryId ? ( < DynamicPane id = { primaryId } onRemove = { onRemoveChildPane } onToggleParentSplit = { onToggleSplit } / > ) : ( < div > ERROR < / div > ) } { secondaryId ? ( < DynamicPane id = { secondaryId } onRemove = { onRemoveChildPane } onToggleParentSplit = { onToggleSplit } / > ) : ( < div > ERROR < /div>)} < /Split>)); } ; const renderTopBottomSplit = ( ) => { return ( < Split horizontal initialPrimarySize = { options ?. initialPrimarySize } minPrimarySize = { options ?. minPrimarySize } minSecondarySize = { options ?. minSecondarySize } renderSplitter = { renderSplitter } splitterSize = { options ?. splitterSize } resetOnDoubleClick > { primaryId ? ( < DynamicPane id = { primaryId } onRemove = { onRemoveChildPane } onToggleParentSplit = { onToggleSplit } / > ) : ( < div > ERROR < / div > ) } { secondaryId ? ( < DynamicPane id = { secondaryId } onRemove = { onRemoveChildPane } onToggleParentSplit = { onToggleSplit } / > ) : ( < div > ERROR < /div>)} < /Split>); } ; const renderLayout = ( ) => { return options ? ( options . horizontal ? renderTopBottomSplit ( ) : renderLeftRightSplit ( ) ) : renderActions ( ) ; } ; return < Root > { renderLayout ( ) } < /Root>; } ;