123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224 |
- /* eslint-disable @typescript-eslint/ban-ts-comment */
- import styled from 'styles'
- import React, { useRef } from 'react'
- import state, { useSelector } from 'state'
- import * as Panel from 'components/panel'
- import {
- breakpoints,
- IconButton,
- RowButton,
- IconWrapper,
- } from 'components/shared'
- import {
- Cross2Icon,
- PlayIcon,
- DotIcon,
- CrumpledPaperIcon,
- StopIcon,
- ClipboardIcon,
- ClipboardCopyIcon,
- TrashIcon,
- } from '@radix-ui/react-icons'
- import logger from 'state/logger'
- import { useStateDesigner } from '@state-designer/react'
-
- const stopPropagation = (e: React.KeyboardEvent) => e.stopPropagation()
- const toggleDebugPanel = () => state.send('TOGGLED_DEBUG_PANEL')
- const handleStateCopy = () => state.send('COPIED_STATE_TO_CLIPBOARD')
- const handleError = () => {
- throw Error('Error!')
- }
-
- export default function CodePanel(): JSX.Element {
- const rContainer = useRef<HTMLDivElement>(null)
- const isDebugging = useSelector((s) => s.data.settings.isDebugMode)
- const isOpen = useSelector((s) => s.data.settings.isDebugOpen)
-
- const rTextArea = useRef<HTMLTextAreaElement>(null)
-
- const local = useStateDesigner({
- initial: 'stopped',
- data: {
- log: '',
- },
- states: {
- stopped: {
- on: {
- CHANGED_LOG: 'setLog',
- COPIED_LOG: { if: 'hasLog', do: 'copyLog' },
- PLAYED_BACK_LOG: { if: 'hasLog', do: 'playbackLog' },
- STARTED_LOGGING: { do: 'startLogger', to: 'logging' },
- },
- },
- logging: {
- on: {
- STOPPED_LOGGING: { do: 'stopLogger', to: 'stopped' },
- },
- },
- },
- conditions: {
- hasLog(data) {
- return data.log !== ''
- },
- },
- actions: {
- setLog(data, payload: { value: string }) {
- data.log = payload.value
- },
- startLogger(data) {
- logger.start(state.data)
- data.log = ''
- },
- stopLogger(data) {
- logger.stop(state.data)
- data.log = logger.copyToJson()
- },
- playbackLog(data) {
- logger.playback(state.data, data.log)
- },
- copyLog() {
- logger.copyToJson()
- },
- },
- })
-
- if (!isDebugging) return null
-
- const handleLoggingStop = () => local.send('STOPPED_LOGGING')
-
- const handlePlayback = () =>
- local.send('PLAYED_BACK_LOG', { log: rTextArea.current?.value })
-
- const handleLoggingStart = () => local.send('STARTED_LOGGING')
-
- const handleLoggingCopy = () => local.send('COPIED_DEBUG_LOG')
-
- return (
- <StylePanelRoot
- dir="ltr"
- bp={breakpoints}
- data-bp-desktop
- ref={rContainer}
- variant="code"
- onWheel={(e) => e.stopPropagation()}
- >
- {isOpen ? (
- <Panel.Layout onKeyDown={stopPropagation}>
- <Panel.Header side="left">
- <IconButton
- bp={breakpoints}
- size="small"
- onClick={toggleDebugPanel}
- >
- <Cross2Icon />
- </IconButton>
- <span>Debugging</span>
- <div />
- </Panel.Header>
- <Panel.Content>
- <hr />
- <RowButton bp={breakpoints} onClick={handleStateCopy}>
- <span>Copy State</span>
- <IconWrapper size="small">
- <ClipboardCopyIcon />
- </IconWrapper>
- </RowButton>
- <RowButton bp={breakpoints} onClick={handleError}>
- <span>Create Error</span>
- <IconWrapper size="small">
- <TrashIcon />
- </IconWrapper>
- </RowButton>
- <hr />
- {local.isIn('stopped') ? (
- <RowButton bp={breakpoints} onClick={handleLoggingStart}>
- <span>Start Logger</span>
- <IconWrapper size="small">
- <DotIcon />
- </IconWrapper>
- </RowButton>
- ) : (
- <RowButton bp={breakpoints} onClick={handleLoggingStop}>
- <span>Stop Logger</span>
- <IconWrapper size="small">
- <StopIcon />
- </IconWrapper>
- </RowButton>
- )}
- <JSONTextAreaWrapper>
- <IconButton
- bp={breakpoints}
- onClick={handleLoggingCopy}
- disabled={!local.can('COPIED_LOG')}
- style={{ position: 'absolute', top: 2, right: 2 }}
- >
- <ClipboardIcon />
- </IconButton>
- <JSONTextArea
- ref={rTextArea}
- value={local.data.log}
- onChange={(e) =>
- local.send('CHANGED_LOG', { value: e.currentTarget.value })
- }
- />
- </JSONTextAreaWrapper>
- <RowButton
- bp={breakpoints}
- onClick={handlePlayback}
- disabled={!local.can('PLAYED_BACK_LOG')}
- >
- <span>Play Back Log</span>
- <IconWrapper size="small">
- <PlayIcon />
- </IconWrapper>
- </RowButton>
- </Panel.Content>
- </Panel.Layout>
- ) : (
- <IconButton bp={breakpoints} size="small" onClick={toggleDebugPanel}>
- <CrumpledPaperIcon />
- </IconButton>
- )}
- </StylePanelRoot>
- )
- }
-
- const StylePanelRoot = styled(Panel.Root, {
- width: 'fit-content',
- maxWidth: 'fit-content',
- overflow: 'hidden',
- position: 'relative',
- border: '1px solid $panel',
- boxShadow: '$4',
- display: 'flex',
- flexDirection: 'column',
- alignItems: 'center',
- pointerEvents: 'all',
- padding: '$0',
-
- '& hr': {
- marginTop: 2,
- marginBottom: 2,
- marginLeft: '-$0',
- border: 'none',
- height: 1,
- backgroundColor: '$brushFill',
- width: 'calc(100% + 4px)',
- },
- })
-
- const JSONTextAreaWrapper = styled('div', {
- position: 'relative',
- margin: '4px 0',
- })
-
- const JSONTextArea = styled('textarea', {
- minHeight: '100px',
- width: '100%',
- font: '$mono',
- backgroundColor: '$panel',
- border: '1px solid $border',
- borderRadius: '4px',
- padding: '4px',
- outline: 'none',
- })
|