Adds button to copy state to clipboard
This commit is contained in:
parent
8180146eb3
commit
a315f8e9a6
2 changed files with 46 additions and 32 deletions
|
@ -7,8 +7,10 @@ import { breakpoints, IconButton, RowButton, IconWrapper } from '../shared'
|
||||||
import {
|
import {
|
||||||
Cross2Icon,
|
Cross2Icon,
|
||||||
PlayIcon,
|
PlayIcon,
|
||||||
|
DotIcon,
|
||||||
CrumpledPaperIcon,
|
CrumpledPaperIcon,
|
||||||
StopIcon,
|
StopIcon,
|
||||||
|
ClipboardIcon,
|
||||||
ClipboardCopyIcon,
|
ClipboardCopyIcon,
|
||||||
} from '@radix-ui/react-icons'
|
} from '@radix-ui/react-icons'
|
||||||
import logger from 'state/logger'
|
import logger from 'state/logger'
|
||||||
|
@ -16,6 +18,7 @@ import { useStateDesigner } from '@state-designer/react'
|
||||||
|
|
||||||
const stopPropagation = (e: React.KeyboardEvent) => e.stopPropagation()
|
const stopPropagation = (e: React.KeyboardEvent) => e.stopPropagation()
|
||||||
const toggleDebugPanel = () => state.send('TOGGLED_DEBUG_PANEL')
|
const toggleDebugPanel = () => state.send('TOGGLED_DEBUG_PANEL')
|
||||||
|
const handleStateCopy = () => state.send('COPIED_STATE_TO_CLIPBOARD')
|
||||||
|
|
||||||
export default function CodePanel(): JSX.Element {
|
export default function CodePanel(): JSX.Element {
|
||||||
const rContainer = useRef<HTMLDivElement>(null)
|
const rContainer = useRef<HTMLDivElement>(null)
|
||||||
|
@ -104,12 +107,19 @@ export default function CodePanel(): JSX.Element {
|
||||||
<div />
|
<div />
|
||||||
</Panel.Header>
|
</Panel.Header>
|
||||||
<Panel.Content>
|
<Panel.Content>
|
||||||
|
<hr />
|
||||||
|
<RowButton bp={breakpoints} onClick={handleStateCopy}>
|
||||||
|
<span>Copy State</span>
|
||||||
|
<IconWrapper size="small">
|
||||||
|
<ClipboardCopyIcon />
|
||||||
|
</IconWrapper>
|
||||||
|
</RowButton>
|
||||||
<hr />
|
<hr />
|
||||||
{local.isIn('stopped') ? (
|
{local.isIn('stopped') ? (
|
||||||
<RowButton bp={breakpoints} onClick={handleLoggingStart}>
|
<RowButton bp={breakpoints} onClick={handleLoggingStart}>
|
||||||
<span>Start Logger</span>
|
<span>Start Logger</span>
|
||||||
<IconWrapper size="small">
|
<IconWrapper size="small">
|
||||||
<PlayIcon />
|
<DotIcon />
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
) : (
|
) : (
|
||||||
|
@ -120,19 +130,15 @@ export default function CodePanel(): JSX.Element {
|
||||||
</IconWrapper>
|
</IconWrapper>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
)}
|
)}
|
||||||
{
|
<JSONTextAreaWrapper>
|
||||||
<RowButton
|
<IconButton
|
||||||
bp={breakpoints}
|
bp={breakpoints}
|
||||||
onClick={handleLoggingCopy}
|
onClick={handleLoggingCopy}
|
||||||
disabled={!local.can('COPIED_LOG')}
|
disabled={!local.can('COPIED_LOG')}
|
||||||
|
style={{ position: 'absolute', top: 2, right: 2 }}
|
||||||
>
|
>
|
||||||
<span>Copy Log</span>
|
<ClipboardIcon />
|
||||||
<IconWrapper size="small">
|
</IconButton>
|
||||||
<ClipboardCopyIcon />
|
|
||||||
</IconWrapper>
|
|
||||||
</RowButton>
|
|
||||||
}
|
|
||||||
<JSONTextAreaWrapper>
|
|
||||||
<JSONTextArea
|
<JSONTextArea
|
||||||
ref={rTextArea}
|
ref={rTextArea}
|
||||||
value={local.data.log}
|
value={local.data.log}
|
||||||
|
@ -147,6 +153,9 @@ export default function CodePanel(): JSX.Element {
|
||||||
disabled={!local.can('PLAYED_BACK_LOG')}
|
disabled={!local.can('PLAYED_BACK_LOG')}
|
||||||
>
|
>
|
||||||
<span>Play Back Log</span>
|
<span>Play Back Log</span>
|
||||||
|
<IconWrapper size="small">
|
||||||
|
<PlayIcon />
|
||||||
|
</IconWrapper>
|
||||||
</RowButton>
|
</RowButton>
|
||||||
</Panel.Content>
|
</Panel.Content>
|
||||||
</Panel.Layout>
|
</Panel.Layout>
|
||||||
|
@ -185,7 +194,8 @@ const StylePanelRoot = styled(Panel.Root, {
|
||||||
})
|
})
|
||||||
|
|
||||||
const JSONTextAreaWrapper = styled('div', {
|
const JSONTextAreaWrapper = styled('div', {
|
||||||
padding: '4px',
|
position: 'relative',
|
||||||
|
margin: '4px 0',
|
||||||
})
|
})
|
||||||
|
|
||||||
const JSONTextArea = styled('textarea', {
|
const JSONTextArea = styled('textarea', {
|
||||||
|
|
|
@ -119,30 +119,34 @@ class Clipboard {
|
||||||
}
|
}
|
||||||
|
|
||||||
copyStringToClipboard = (string: string) => {
|
copyStringToClipboard = (string: string) => {
|
||||||
const textarea = document.createElement('textarea')
|
|
||||||
textarea.setAttribute('position', 'fixed')
|
|
||||||
textarea.setAttribute('top', '0')
|
|
||||||
textarea.setAttribute('readonly', 'true')
|
|
||||||
textarea.setAttribute('contenteditable', 'true')
|
|
||||||
textarea.style.position = 'fixed'
|
|
||||||
textarea.value = string
|
|
||||||
document.body.appendChild(textarea)
|
|
||||||
textarea.focus()
|
|
||||||
textarea.select()
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const range = document.createRange()
|
navigator.clipboard.writeText(string)
|
||||||
range.selectNodeContents(textarea)
|
} catch (e) {
|
||||||
|
const textarea = document.createElement('textarea')
|
||||||
|
textarea.setAttribute('position', 'fixed')
|
||||||
|
textarea.setAttribute('top', '0')
|
||||||
|
textarea.setAttribute('readonly', 'true')
|
||||||
|
textarea.setAttribute('contenteditable', 'true')
|
||||||
|
textarea.style.position = 'fixed'
|
||||||
|
textarea.value = string
|
||||||
|
document.body.appendChild(textarea)
|
||||||
|
textarea.focus()
|
||||||
|
textarea.select()
|
||||||
|
|
||||||
const sel = window.getSelection()
|
try {
|
||||||
sel.removeAllRanges()
|
const range = document.createRange()
|
||||||
sel.addRange(range)
|
range.selectNodeContents(textarea)
|
||||||
|
|
||||||
textarea.setSelectionRange(0, textarea.value.length)
|
const sel = window.getSelection()
|
||||||
} catch (err) {
|
sel.removeAllRanges()
|
||||||
null // Could not copy to clipboard
|
sel.addRange(range)
|
||||||
} finally {
|
|
||||||
document.body.removeChild(textarea)
|
textarea.setSelectionRange(0, textarea.value.length)
|
||||||
|
} catch (err) {
|
||||||
|
null // Could not copy to clipboard
|
||||||
|
} finally {
|
||||||
|
document.body.removeChild(textarea)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return this
|
return this
|
||||||
|
|
Loading…
Reference in a new issue