SEQSENSE OSS
PCDEditor React Example
import React, { useRef } from 'react'
import styled from '@emotion/styled'
import { IconButton, Paper } from '@mui/material'
import { useRouter } from 'next/router'

import FullscreenIcon from '@mui/icons-material/Fullscreen'
import FullscreenExitIcon from '@mui/icons-material/FullscreenExit'

import { fontFamily } from '@seqsense/www.seqsense.org/components/templates/Theme'

import PCDEditor from '@seqsense/pcdeditor/ReactPCDEditor'

/*
 * ## How to embed PCDEditor to your React app
 *
 * 1. Install @seqsense/pcdeditor from GitHub Package Regitry.
 *    ```
 *    echo '@seqsense:registry=https://npm.pkg.github.com' >> .npmrc
 *    npm install @seqsense/pcdeditor
 *    ```
 *
 * 2. Copy `pcdeditor.wasm` and `wasm_exec.js` under `./public` to
 *    host them statically.
 *    Files are installed under `./node_modules/@seqsense/pcdeditor/`,
 *    but not hosted statically by default.
 *
 * 3. Add React code like this file to your app.
 *    Note: replace the paths according to your configuration!
 *
 */

type Props = {
  onAttachedOuter?: (PCDEditor) => void
}

const PCDEditorWithFullscreen = ({ onAttachedOuter }: Props): JSX.Element => {
  const router = useRouter()
  const [state, setState] = React.useState({
    fullscreen: false,
  })

  const editorRef = useRef(null)

  // Handle fullscreen button.
  const toggleFullscreen = () => {
    if (!state.fullscreen) {
      editorRef.current.requestFullscreen({ navigationUI: 'hide' })
      editorRef.current.onfullscreenchange = () =>
        setState({ fullscreen: global.document.fullscreenElement != null })
    } else if (global.document.fullscreenElement != null) {
      global.document.exitFullscreen()
    }
    setState({ fullscreen: !state.fullscreen })
  }

  const onAttached = (editor) => {
    // Optional: Set initial conditions.
    const orthoCheck = document.querySelector<HTMLInputElement>('#ortho')
    if (orthoCheck) {
      orthoCheck.checked = false
      const e = new Event('change')
      orthoCheck.dispatchEvent(e)
    }
    editor.pcdeditor
      .command('view 2.473 -2.62 -2.3 0.785 12.38')
      .catch(editor.logger)

    // Load files. Replace the paths according to your configuration!
    const pcdPath = `${router.basePath}/assets/pcdeditor/samples/test/map.pcd`
    const yamlPath = `${router.basePath}/assets/pcdeditor/samples/test/map.yaml`
    const imgPath = `${router.basePath}/assets/pcdeditor/samples/test/map.png`
    editor.loadPCD(pcdPath).catch(editor.logger)
    editor.load2D(yamlPath, imgPath).catch(editor.logger)
    if (editor) {
      onAttachedOuter(editor)
    }
  }

  return (
    <EditorPaper
      ref={editorRef}
      className={state.fullscreen && 'editorFullscreen'}
    >
      <PCDEditor
        // Replace the path for according to configuration!
        wasmPath={`${router.basePath}/assets/pcdeditor/pcdeditor.wasm`}
        wasmExecPath={`${router.basePath}/assets/pcdeditor/wasm_exec.js`}
        onAttached={onAttached}
      />
      <FullscreenIconButton onClick={toggleFullscreen}>
        {(state.fullscreen && <FullscreenExitIcon />) || <FullscreenIcon />}
      </FullscreenIconButton>
    </EditorPaper>
  )
}

const FullscreenIconButton = styled(IconButton)`
  position: absolute !important;
  bottom: 0 !important;
  right: 0 !important;
`

const EditorPaper = styled(Paper)`
  width: 100% !important;
  height: 50vh !important;
  max-height: 1024px !important;
  padding: 0 !important;
  position: relative !important;
  color: #000 !important;
  background-color: #000 !important;
  border-radius: 5px !important;
  overflow: hidden;

  canvas:focus {
    outline: none;
  }

  &.editorFullscreen {
    position: fixed !important;
    width: 100% !important;
    height: 100vh !important;
    max-height: 100vh !important;
    top: 0 !important;
    left: 0 !important;
    border-radius: 0 !important;
    z-index: 3000 !important;
  }

  Button,
  input,
  a,
  span,
  label {
    font-family: '${fontFamily}', sans-serif;
    font-weight: 400;
    font-size: 0.875rem;
  }
`

export default PCDEditorWithFullscreen