import React from 'react' ; import { ControlledEditor } from '@monaco-editor/react' ; import DesignToolsApp from '../components/DesignToolsApp' ; import RehypeComponent from '../components/RehypeComponent' ; import { DesignToolsProvider } from '../lib/contexts/design-tools-context' ; import { TargetEvent } from '../types' ; import { getAncestorsIndexes , getSelectedElement , } from '../lib/babel-dom-utils' ; import useWindowSize from '../lib/hooks/use-window-size' ; import { parseCode , updateNodeClass } from '../lib/rehype-utils' ; const defaultCode = `<div id="hello"><strong class="uppercase">Hello World!</strong><p>Some text</p>
  <div><p>Deep text</p></div>
  </div>` ; const LivePage = ( ) => { const [ selectedNodes , setSelectedNodes ] = React . useState ( [ ] ) ; const [ code , setCode ] = React . useState ( defaultCode ) ; const [ ancestorIndexes , setAncestorIndexes ] = React . useState < number [ ] > ( ) ; const highlightElement = React . useRef < HTMLDivElement > ( ) ; const previewElement = typeof window === 'undefined' ? null : document . getElementById ( 'preview' ) ; const rootRehypeNode = parseCode ( code ) ; console . log ( rootRehypeNode ) ; React . useEffect ( ( ) => { const element = getSelectedElement ( previewElement , ancestorIndexes ) ; if ( element ) { const { top , left , width , height } = element . getBoundingClientRect ( ) ; updateHighlightElement ( highlightElement . current , { top , left , width , height , } ) ; } } , [ rootRehypeNode ] ) ; useWindowSize ( ( ) => { const element = getSelectedElement ( previewElement , ancestorIndexes ) ; if ( element ) { const { top , left , width , height } = element . getBoundingClientRect ( ) ; updateHighlightElement ( highlightElement . current , { top , left , width , height , } ) ; } } ) ; const handleDesignToolsSubmit = ( events ) => { const event = events [ 0 ] ; const { node , type , className } = event ; if ( node && type === 'UPDATE_FILE_CLASS_NAME' ) { const newCode = updateNodeClass ( code , ancestorIndexes , className ) ; setCode ( newCode ) ; } } ; return ( < DesignToolsProvider > < div className = "livePage h-screen overflow-hidden" > < div className = "fixed" ref = { highlightElement } > < /div> < div id = "preview" className = "preview flex flex-col items-center justify-center" onClick = { ( event ) => { event . preventDefault ( ) ; const { target , currentTarget } = event ; const element = target ; const indexes = getAncestorsIndexes ( target , currentTarget ) ; setAncestorIndexes ( indexes ) ; const { top , left , width , height , } = element . getBoundingClientRect ( ) ; updateHighlightElement ( highlightElement . current , { top , left , width , height , } ) ; setSelectedNodes ( [ event . _targetInst ] ) ; } } > < RehypeComponent children = { rootRehypeNode . children } /> < /div> < div className = "editor border-t-4" > < ControlledEditor language = "html" value = { code } options = { { minimap : { enabled : false , } , } } onChange = { ( event , value ) => { console . log ( event , value ) ; setCode ( value ) ; } } /> < /div> < DesignToolsApp selectedNodes = { selectedNodes } className = { [ 'designTools' , 'max-h-full h-screen overflow-auto border-r-4' , ] . join ( ' ' ) } onNodeChange = { handleDesignToolsSubmit } / > < /div> < style > { `
      .livePage {
        display: grid;
        grid-template-areas: 
          "designTools preview"
          "designTools editor";
        grid-template-rows: 1fr 1fr;
        grid-template-columns: auto 1fr;
      }

      .preview {
        grid-area: preview;
      }

      .editor {
        grid-area: editor;
      }

      .designTools {
        grid-area: designTools;
      }
      ` } < /style> < /DesignToolsProvider>); } ; function updateHighlightElement ( element , { top , left , width , height } ) { element . style . outline = `1px solid cyan` ; element . style . top = `${ top }px` ; element . style . left = `${ left }px` ; element . style . width = `${ width }px` ; element . style . height = `${ height }px` ; element . style . pointerEvents = `none` ; } export default LivePage ;