kopia lustrzana https://github.com/Tldraw/Tldraw
232 wiersze
5.8 KiB
TypeScript
232 wiersze
5.8 KiB
TypeScript
import * as React from 'react'
|
|
import {
|
|
ArrowTopRightIcon,
|
|
CircleIcon,
|
|
CursorArrowIcon,
|
|
LockClosedIcon,
|
|
LockOpen1Icon,
|
|
Pencil1Icon,
|
|
SquareIcon,
|
|
TextIcon,
|
|
} from '@radix-ui/react-icons'
|
|
import styled from '~styles'
|
|
import { Data, TLDrawShapeType } from '~types'
|
|
import { useTLDrawContext } from '~hooks'
|
|
import { StatusBar } from './status-bar'
|
|
import { FloatingContainer } from '../shared'
|
|
import { PrimaryButton, SecondaryButton } from './styled'
|
|
import { UndoRedo } from './undo-redo'
|
|
import { Zoom } from './zoom'
|
|
import { BackToContent } from './back-to-content'
|
|
|
|
const activeToolSelector = (s: Data) => s.appState.activeTool
|
|
const isToolLockedSelector = (s: Data) => s.appState.isToolLocked
|
|
const isDebugModeSelector = (s: Data) => s.settings.isDebugMode
|
|
|
|
export const ToolsPanel = React.memo((): JSX.Element => {
|
|
const { tlstate, useSelector } = useTLDrawContext()
|
|
|
|
const activeTool = useSelector(activeToolSelector)
|
|
|
|
const isToolLocked = useSelector(isToolLockedSelector)
|
|
|
|
const isDebugMode = useSelector(isDebugModeSelector)
|
|
|
|
const selectSelectTool = React.useCallback(() => {
|
|
tlstate.selectTool('select')
|
|
}, [tlstate])
|
|
|
|
const selectDrawTool = React.useCallback(() => {
|
|
tlstate.selectTool(TLDrawShapeType.Draw)
|
|
}, [tlstate])
|
|
|
|
const selectRectangleTool = React.useCallback(() => {
|
|
tlstate.selectTool(TLDrawShapeType.Rectangle)
|
|
}, [tlstate])
|
|
|
|
const selectEllipseTool = React.useCallback(() => {
|
|
tlstate.selectTool(TLDrawShapeType.Ellipse)
|
|
}, [tlstate])
|
|
|
|
const selectArrowTool = React.useCallback(() => {
|
|
tlstate.selectTool(TLDrawShapeType.Arrow)
|
|
}, [tlstate])
|
|
|
|
const selectTextTool = React.useCallback(() => {
|
|
tlstate.selectTool(TLDrawShapeType.Text)
|
|
}, [tlstate])
|
|
|
|
return (
|
|
<ToolsPanelContainer>
|
|
<LeftWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
|
|
<Zoom />
|
|
<FloatingContainer>
|
|
<SecondaryButton
|
|
label={'Select'}
|
|
kbd={'1'}
|
|
onClick={selectSelectTool}
|
|
isActive={activeTool === 'select'}
|
|
>
|
|
<CursorArrowIcon />
|
|
</SecondaryButton>
|
|
</FloatingContainer>
|
|
</LeftWrap>
|
|
<CenterWrap>
|
|
<BackToContent />
|
|
<FloatingContainer>
|
|
<PrimaryButton
|
|
kbd={'2'}
|
|
label={TLDrawShapeType.Draw}
|
|
onClick={selectDrawTool}
|
|
isActive={activeTool === TLDrawShapeType.Draw}
|
|
>
|
|
<Pencil1Icon />
|
|
</PrimaryButton>
|
|
<PrimaryButton
|
|
kbd={'3'}
|
|
label={TLDrawShapeType.Rectangle}
|
|
onClick={selectRectangleTool}
|
|
isActive={activeTool === TLDrawShapeType.Rectangle}
|
|
>
|
|
<SquareIcon />
|
|
</PrimaryButton>
|
|
<PrimaryButton
|
|
kbd={'4'}
|
|
label={TLDrawShapeType.Draw}
|
|
onClick={selectEllipseTool}
|
|
isActive={activeTool === TLDrawShapeType.Ellipse}
|
|
>
|
|
<CircleIcon />
|
|
</PrimaryButton>
|
|
<PrimaryButton
|
|
kbd={'5'}
|
|
label={TLDrawShapeType.Arrow}
|
|
onClick={selectArrowTool}
|
|
isActive={activeTool === TLDrawShapeType.Arrow}
|
|
>
|
|
<ArrowTopRightIcon />
|
|
</PrimaryButton>
|
|
<PrimaryButton
|
|
kbd={'6'}
|
|
label={TLDrawShapeType.Text}
|
|
onClick={selectTextTool}
|
|
isActive={activeTool === TLDrawShapeType.Text}
|
|
>
|
|
<TextIcon />
|
|
</PrimaryButton>
|
|
</FloatingContainer>
|
|
</CenterWrap>
|
|
<RightWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
|
|
<FloatingContainer>
|
|
<SecondaryButton
|
|
kbd={'7'}
|
|
label={'Lock Tool'}
|
|
onClick={tlstate.toggleToolLock}
|
|
isActive={isToolLocked}
|
|
>
|
|
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
|
</SecondaryButton>
|
|
</FloatingContainer>
|
|
<UndoRedo />
|
|
</RightWrap>
|
|
{isDebugMode && (
|
|
<StatusWrap>
|
|
<StatusBar />
|
|
</StatusWrap>
|
|
)}
|
|
</ToolsPanelContainer>
|
|
)
|
|
})
|
|
|
|
const ToolsPanelContainer = styled('div', {
|
|
position: 'absolute',
|
|
bottom: 0,
|
|
left: 0,
|
|
right: 0,
|
|
width: '100%',
|
|
minWidth: 0,
|
|
maxWidth: '100%',
|
|
display: 'grid',
|
|
gridTemplateColumns: '1fr auto 1fr',
|
|
gridTemplateRows: 'auto auto',
|
|
padding: '0',
|
|
alignItems: 'flex-end',
|
|
zIndex: 200,
|
|
gridGap: '$4',
|
|
gridRowGap: '$4',
|
|
pointerEvents: 'none',
|
|
'& > div > *': {
|
|
pointerEvents: 'all',
|
|
},
|
|
})
|
|
|
|
const CenterWrap = styled('div', {
|
|
gridRow: 1,
|
|
gridColumn: 2,
|
|
display: 'flex',
|
|
width: 'fit-content',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
flexDirection: 'column',
|
|
gap: 12,
|
|
})
|
|
|
|
const LeftWrap = styled('div', {
|
|
gridRow: 1,
|
|
gridColumn: 1,
|
|
display: 'flex',
|
|
paddingLeft: '$3',
|
|
variants: {
|
|
size: {
|
|
mobile: {
|
|
flexDirection: 'column',
|
|
justifyContent: 'flex-end',
|
|
alignItems: 'flex-start',
|
|
'& > *:nth-of-type(1)': {
|
|
marginBottom: '8px',
|
|
},
|
|
},
|
|
small: {
|
|
flexDirection: 'row',
|
|
alignItems: 'flex-end',
|
|
justifyContent: 'space-between',
|
|
'& > *:nth-of-type(1)': {
|
|
marginBottom: '0px',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
const RightWrap = styled('div', {
|
|
gridRow: 1,
|
|
gridColumn: 3,
|
|
display: 'flex',
|
|
paddingRight: '$3',
|
|
variants: {
|
|
size: {
|
|
mobile: {
|
|
flexDirection: 'column-reverse',
|
|
justifyContent: 'flex-end',
|
|
alignItems: 'flex-end',
|
|
'& > *:nth-of-type(2)': {
|
|
marginBottom: '8px',
|
|
},
|
|
},
|
|
small: {
|
|
flexDirection: 'row',
|
|
alignItems: 'flex-end',
|
|
justifyContent: 'space-between',
|
|
'& > *:nth-of-type(2)': {
|
|
marginBottom: '0px',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
})
|
|
|
|
const StatusWrap = styled('div', {
|
|
gridRow: 2,
|
|
gridColumn: '1 / span 3',
|
|
})
|