tldraw/components/style-panel/style-panel.tsx

146 lines
3.7 KiB
TypeScript
Raw Normal View History

2021-05-28 20:30:27 +00:00
import styled from 'styles'
import state, { useSelector } from 'state'
import * as Panel from 'components/panel'
import { useRef } from 'react'
import {
IconButton,
IconWrapper,
ButtonsRow,
RowButton,
2021-07-04 18:45:07 +00:00
breakpoints,
} from 'components/shared'
import ShapesFunctions from './shapes-functions'
2021-05-28 20:30:27 +00:00
import AlignDistribute from './align-distribute'
import QuickColorSelect from './quick-color-select'
import QuickSizeSelect from './quick-size-select'
2021-07-01 22:11:09 +00:00
import QuickDashSelect from './quick-dash-select'
import QuickFillSelect from './quick-fill-select'
2021-06-02 21:17:38 +00:00
import Tooltip from 'components/tooltip'
2021-07-01 22:11:09 +00:00
import { motion } from 'framer-motion'
import {
ClipboardCopyIcon,
ClipboardIcon,
2021-07-03 14:13:07 +00:00
DotsHorizontalIcon,
Share2Icon,
2021-07-03 14:13:07 +00:00
Cross2Icon,
} from '@radix-ui/react-icons'
2021-05-26 10:34:10 +00:00
const handleStylePanelOpen = () => state.send('TOGGLED_STYLE_PANEL_OPEN')
2021-07-04 18:45:07 +00:00
const handleCopy = () => state.send('COPIED')
const handlePaste = () => state.send('PASTED')
const handleCopyToSvg = () => state.send('COPIED_TO_SVG')
const handleSave = () => state.send('SAVED')
const handleLoad = () => state.send('LOADED_FROM_FILE_STSTEM')
2021-06-21 21:35:28 +00:00
export default function StylePanel(): JSX.Element {
2021-05-26 10:34:10 +00:00
const rContainer = useRef<HTMLDivElement>(null)
2021-05-26 10:34:10 +00:00
const isOpen = useSelector((s) => s.data.settings.isStyleOpen)
return (
<StylePanelRoot dir="ltr" ref={rContainer} isOpen={isOpen}>
2021-07-01 22:11:09 +00:00
<ButtonsRow>
<QuickColorSelect />
<QuickSizeSelect />
<QuickDashSelect />
<QuickFillSelect />
<IconButton
bp={breakpoints}
title="Style"
size="small"
onClick={handleStylePanelOpen}
>
2021-07-03 14:13:07 +00:00
<Tooltip label="More">
{isOpen ? <Cross2Icon /> : <DotsHorizontalIcon />}
</Tooltip>
2021-07-01 22:11:09 +00:00
</IconButton>
</ButtonsRow>
{isOpen && <SelectedShapeContent />}
2021-05-26 10:34:10 +00:00
</StylePanelRoot>
)
}
2021-07-01 22:11:09 +00:00
function SelectedShapeContent(): JSX.Element {
const selectedShapesCount = useSelector((s) => s.values.selectedIds.length)
2021-05-26 21:47:46 +00:00
2021-05-26 10:34:10 +00:00
return (
2021-07-01 22:11:09 +00:00
<>
<hr />
<ShapesFunctions />
2021-07-03 14:13:07 +00:00
<hr />
2021-07-01 22:11:09 +00:00
<AlignDistribute
hasTwoOrMore={selectedShapesCount > 1}
hasThreeOrMore={selectedShapesCount > 2}
/>
2021-07-03 14:13:07 +00:00
<hr />
<RowButton
bp={breakpoints}
disabled={selectedShapesCount === 0}
2021-07-04 18:45:07 +00:00
onClick={handleCopy}
>
<span>Copy</span>
<IconWrapper size="small">
<ClipboardCopyIcon />
</IconWrapper>
</RowButton>
2021-07-04 18:45:07 +00:00
<RowButton bp={breakpoints} onClick={handlePaste}>
<span>Paste</span>
<IconWrapper size="small">
<ClipboardIcon />
</IconWrapper>
</RowButton>
<RowButton
bp={breakpoints}
disabled={selectedShapesCount === 0}
2021-07-04 18:45:07 +00:00
onClick={handleCopyToSvg}
>
<span>Copy to SVG</span>
<IconWrapper size="small">
<Share2Icon />
</IconWrapper>
</RowButton>
<hr />
2021-07-04 18:45:07 +00:00
<RowButton bp={breakpoints} onClick={handleSave}>
<span>Save</span>
</RowButton>
2021-07-04 18:45:07 +00:00
<RowButton bp={breakpoints} onClick={handleLoad}>
<span>Load</span>
</RowButton>
2021-07-01 22:11:09 +00:00
</>
2021-05-26 10:34:10 +00:00
)
}
2021-07-01 22:11:09 +00:00
const StylePanelRoot = styled(motion(Panel.Root), {
2021-05-26 19:20:52 +00:00
minWidth: 1,
2021-07-01 22:11:09 +00:00
width: 'fit-content',
maxWidth: 'fit-content',
2021-05-28 20:30:27 +00:00
overflow: 'hidden',
position: 'relative',
2021-05-30 13:49:33 +00:00
border: '1px solid $panel',
boxShadow: '0px 2px 4px rgba(0,0,0,.2)',
2021-06-01 21:49:32 +00:00
display: 'flex',
2021-07-01 22:11:09 +00:00
flexDirection: 'column',
2021-06-01 21:49:32 +00:00
alignItems: 'center',
pointerEvents: 'all',
2021-07-01 22:11:09 +00:00
padding: 2,
'& hr': {
marginTop: 2,
marginBottom: 2,
marginLeft: '-2px',
border: 'none',
height: 1,
backgroundColor: '$brushFill',
width: 'calc(100% + 4px)',
},
2021-05-26 10:34:10 +00:00
variants: {
isOpen: {
2021-05-26 19:20:52 +00:00
true: {},
2021-05-26 10:34:10 +00:00
false: {
2021-06-01 21:49:32 +00:00
width: 'fit-content',
2021-05-26 10:34:10 +00:00
},
},
},
})