Refactors tool panel
This commit is contained in:
parent
f9c688056e
commit
4efa1092f1
19 changed files with 580 additions and 261 deletions
4
components/icons/Redo.svg
Normal file
4
components/icons/Redo.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 2.49538C12.2239 2.49538 12 2.71923 12 2.99538V5.49559H9.49979C9.22364 5.49559 8.99979 5.71945 8.99979 5.99559C8.99979 6.27173 9.22364 6.49559 9.49979 6.49559H12.5C12.7761 6.49559 13 6.27173 13 5.99559V2.99538C13 2.71923 12.7761 2.49538 12.5 2.49538Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.69698 2.04877C6.62345 1.89773 5.52991 2.09968 4.58113 2.62417C3.63236 3.14867 2.87973 3.9673 2.43667 4.95673C1.99361 5.94616 1.8841 7.05278 2.12465 8.10985C2.3652 9.16693 2.94278 10.1172 3.77036 10.8175C4.59794 11.5177 5.63069 11.9301 6.713 11.9924C7.79531 12.0547 8.86855 11.7635 9.77101 11.1628C10.6735 10.5621 11.3563 9.68441 11.7165 8.66191C11.8083 8.40146 11.6715 8.11593 11.4111 8.02417C11.1506 7.93241 10.8651 8.06916 10.7733 8.32961C10.4851 9.14762 9.93888 9.84981 9.21691 10.3304C8.49493 10.811 7.63632 11.0439 6.77046 10.994C5.9046 10.9442 5.07839 10.6143 4.41631 10.0541C3.75424 9.49386 3.29217 8.73363 3.09972 7.88796C2.90728 7.04229 2.99488 6.15698 3.34934 5.36542C3.7038 4.57387 4.30591 3.91895 5.06494 3.49935C5.82398 3.07974 6.69882 2.91819 7.55765 3.03902C8.41649 3.15985 9.21279 3.55653 9.82658 4.16928L9.83745 4.17981L12.1576 6.35996C12.3588 6.54906 12.6753 6.53921 12.8644 6.33797C13.0535 6.13673 13.0436 5.8203 12.8424 5.63121L10.5276 3.4561C9.76111 2.69329 8.76794 2.19945 7.69698 2.04877Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
6
components/icons/Trash.svg
Normal file
6
components/icons/Trash.svg
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4.65555C2 4.37941 2.22386 4.15555 2.5 4.15555H12.2C12.4761 4.15555 12.7 4.37941 12.7 4.65555C12.7 4.93169 12.4761 5.15555 12.2 5.15555H2.5C2.22386 5.15555 2 4.93169 2 4.65555Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27208 3C6.11885 3 5.97189 3.06087 5.86353 3.16923C5.75518 3.27758 5.6943 3.42454 5.6943 3.57778V4.15556H9.00542V3.57778C9.00542 3.42454 8.94454 3.27758 8.83619 3.16923C8.72783 3.06087 8.58087 3 8.42764 3H6.27208ZM10.0054 4.15556V3.57778C10.0054 3.15933 9.83919 2.75801 9.54329 2.46212C9.2474 2.16623 8.84609 2 8.42764 2H6.27208C5.85363 2 5.45232 2.16623 5.15642 2.46212C4.86053 2.75801 4.6943 3.15933 4.6943 3.57778V4.15556H3.57764C3.30149 4.15556 3.07764 4.37941 3.07764 4.65556V12.2C3.07764 12.6185 3.24387 13.0198 3.53976 13.3157C3.83565 13.6115 4.23696 13.7778 4.65541 13.7778H10.0443C10.4628 13.7778 10.8641 13.6115 11.16 13.3157C11.4559 13.0198 11.6221 12.6185 11.6221 12.2V4.65556C11.6221 4.37941 11.3982 4.15556 11.1221 4.15556H10.0054ZM4.07764 5.15556V12.2C4.07764 12.3532 4.13851 12.5002 4.24686 12.6086C4.35522 12.7169 4.50218 12.7778 4.65541 12.7778H10.0443C10.1975 12.7778 10.3445 12.7169 10.4529 12.6086C10.5612 12.5002 10.6221 12.3532 10.6221 12.2V5.15556H4.07764Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27246 6.85001C6.5486 6.85001 6.77246 7.07386 6.77246 7.35001V10.5833C6.77246 10.8595 6.5486 11.0833 6.27246 11.0833C5.99632 11.0833 5.77246 10.8595 5.77246 10.5833V7.35001C5.77246 7.07386 5.99632 6.85001 6.27246 6.85001Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.42773 6.85001C8.70388 6.85001 8.92773 7.07386 8.92773 7.35001V10.5833C8.92773 10.8595 8.70388 11.0833 8.42773 11.0833C8.15159 11.0833 7.92773 10.8595 7.92773 10.5833V7.35001C7.92773 7.07386 8.15159 6.85001 8.42773 6.85001Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
4
components/icons/Undo.svg
Normal file
4
components/icons/Undo.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5 2.49538C2.77614 2.49538 3 2.71923 3 2.99538V5.49559H5.50021C5.77636 5.49559 6.00021 5.71945 6.00021 5.99559C6.00021 6.27173 5.77636 6.49559 5.50021 6.49559H2.5C2.22386 6.49559 2 6.27173 2 5.99559V2.99538C2 2.71923 2.22386 2.49538 2.5 2.49538Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.30302 2.04877C8.37655 1.89773 9.47009 2.09968 10.4189 2.62417C11.3676 3.14867 12.1203 3.9673 12.5633 4.95673C13.0064 5.94616 13.1159 7.05278 12.8753 8.10985C12.6348 9.16693 12.0572 10.1172 11.2296 10.8175C10.4021 11.5177 9.36931 11.9301 8.287 11.9924C7.20469 12.0547 6.13145 11.7635 5.22899 11.1628C4.32653 10.5621 3.64374 9.68441 3.2835 8.66191C3.19174 8.40146 3.32849 8.11593 3.58894 8.02417C3.84939 7.93241 4.13492 8.06916 4.22668 8.32961C4.51488 9.14762 5.06112 9.84981 5.78309 10.3304C6.50507 10.811 7.36368 11.0439 8.22954 10.994C9.0954 10.9442 9.92161 10.6143 10.5837 10.0541C11.2458 9.49386 11.7078 8.73363 11.9003 7.88796C12.0927 7.04229 12.0051 6.15698 11.6507 5.36542C11.2962 4.57387 10.6941 3.91895 9.93506 3.49935C9.17602 3.07974 8.30118 2.91819 7.44235 3.03902C6.58351 3.15985 5.78721 3.55653 5.17342 4.16928L5.16255 4.17981L2.84239 6.35996C2.64115 6.54906 2.32472 6.53921 2.13562 6.33797C1.94653 6.13673 1.95637 5.8203 2.15761 5.63121L4.47241 3.4561C5.23889 2.69329 6.23206 2.19945 7.30302 2.04877Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
3
components/icons/index.tsx
Normal file
3
components/icons/index.tsx
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
export { default as Redo } from './redo'
|
||||||
|
export { default as Trash } from './trash'
|
||||||
|
export { default as Undo } from './undo'
|
28
components/icons/redo.tsx
Normal file
28
components/icons/redo.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
function SvgRedo(props: React.SVGProps<SVGSVGElement>): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={15}
|
||||||
|
height={15}
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M12.5 2.495a.5.5 0 00-.5.5v2.5H9.5a.5.5 0 100 1h3a.5.5 0 00.5-.5v-3a.5.5 0 00-.5-.5z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M7.697 2.049a5 5 0 104.02 6.613.5.5 0 10-.944-.332 4 4 0 11-.946-4.16l.01.01 2.32 2.18a.5.5 0 00.685-.729l-2.314-2.175A5 5 0 007.697 2.05z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SvgRedo
|
34
components/icons/trash.tsx
Normal file
34
components/icons/trash.tsx
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
function SvgTrash(props: React.SVGProps<SVGSVGElement>): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={15}
|
||||||
|
height={15}
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M2 4.656a.5.5 0 01.5-.5h9.7a.5.5 0 010 1H2.5a.5.5 0 01-.5-.5z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M6.272 3a.578.578 0 00-.578.578v.578h3.311v-.578A.578.578 0 008.428 3H6.272zm3.733 1.156v-.578A1.578 1.578 0 008.428 2H6.272a1.578 1.578 0 00-1.578 1.578v.578H3.578a.5.5 0 00-.5.5V12.2a1.578 1.578 0 001.577 1.578h5.39a1.578 1.578 0 001.577-1.578V4.656a.5.5 0 00-.5-.5h-1.117zm-5.927 1V12.2a.578.578 0 00.577.578h5.39a.578.578 0 00.577-.578V5.156H4.078z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M6.272 6.85a.5.5 0 01.5.5v3.233a.5.5 0 11-1 0V7.35a.5.5 0 01.5-.5zM8.428 6.85a.5.5 0 01.5.5v3.233a.5.5 0 11-1 0V7.35a.5.5 0 01.5-.5z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SvgTrash
|
28
components/icons/undo.tsx
Normal file
28
components/icons/undo.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
function SvgUndo(props: React.SVGProps<SVGSVGElement>): JSX.Element {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width={15}
|
||||||
|
height={15}
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M2.5 2.495a.5.5 0 01.5.5v2.5h2.5a.5.5 0 110 1h-3a.5.5 0 01-.5-.5v-3a.5.5 0 01.5-.5z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
clipRule="evenodd"
|
||||||
|
d="M7.303 2.049a5 5 0 11-4.02 6.613.5.5 0 01.944-.332 4 4 0 10.946-4.16l-.01.01-2.32 2.18a.5.5 0 01-.685-.729l2.314-2.175A5 5 0 017.303 2.05z"
|
||||||
|
fill="#000"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default SvgUndo
|
|
@ -7,6 +7,7 @@ import { forwardRef } from 'react'
|
||||||
export const breakpoints: any = { '@initial': 'mobile', '@sm': 'small' }
|
export const breakpoints: any = { '@initial': 'mobile', '@sm': 'small' }
|
||||||
|
|
||||||
export const IconButton = styled('button', {
|
export const IconButton = styled('button', {
|
||||||
|
position: 'relative',
|
||||||
height: '32px',
|
height: '32px',
|
||||||
width: '32px',
|
width: '32px',
|
||||||
backgroundColor: '$panel',
|
backgroundColor: '$panel',
|
||||||
|
@ -19,6 +20,7 @@ export const IconButton = styled('button', {
|
||||||
outline: 'none',
|
outline: 'none',
|
||||||
border: 'none',
|
border: 'none',
|
||||||
pointerEvents: 'all',
|
pointerEvents: 'all',
|
||||||
|
fontSize: '$0',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|
||||||
'& > *': {
|
'& > *': {
|
||||||
|
@ -48,7 +50,9 @@ export const IconButton = styled('button', {
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
small: {
|
small: {
|
||||||
'& svg': {
|
height: 32,
|
||||||
|
width: 32,
|
||||||
|
'& svg:nth-of-type(1)': {
|
||||||
height: '16px',
|
height: '16px',
|
||||||
width: '16px',
|
width: '16px',
|
||||||
},
|
},
|
||||||
|
@ -56,17 +60,17 @@ export const IconButton = styled('button', {
|
||||||
medium: {
|
medium: {
|
||||||
height: 44,
|
height: 44,
|
||||||
width: 44,
|
width: 44,
|
||||||
'& svg': {
|
'& svg:nth-of-type(1)': {
|
||||||
height: '20px',
|
height: '18px',
|
||||||
width: '20px',
|
width: '18px',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
large: {
|
large: {
|
||||||
height: 44,
|
height: 44,
|
||||||
width: 44,
|
width: 44,
|
||||||
'& svg': {
|
'& svg:nth-of-type(1)': {
|
||||||
height: '24px',
|
height: '20px',
|
||||||
width: '24px',
|
width: '20px',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -404,3 +408,10 @@ export const ButtonsRow = styled('div', {
|
||||||
justifyContent: 'flex-start',
|
justifyContent: 'flex-start',
|
||||||
padding: 0,
|
padding: 0,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const VerticalDivider = styled('hr', {
|
||||||
|
width: '1px',
|
||||||
|
margin: '-2px 3px',
|
||||||
|
border: 'none',
|
||||||
|
backgroundColor: '$brushFill',
|
||||||
|
})
|
||||||
|
|
|
@ -123,6 +123,7 @@ const StylePanelRoot = styled(motion(Panel.Root), {
|
||||||
alignItems: 'center',
|
alignItems: 'center',
|
||||||
pointerEvents: 'all',
|
pointerEvents: 'all',
|
||||||
padding: 2,
|
padding: 2,
|
||||||
|
zIndex: 300,
|
||||||
|
|
||||||
'& hr': {
|
'& hr': {
|
||||||
marginTop: 2,
|
marginTop: 2,
|
||||||
|
|
273
components/tools-panel/shared.tsx
Normal file
273
components/tools-panel/shared.tsx
Normal file
|
@ -0,0 +1,273 @@
|
||||||
|
import Tooltip from 'components/tooltip'
|
||||||
|
import styled from 'styles'
|
||||||
|
|
||||||
|
// small: {
|
||||||
|
// height: 32,
|
||||||
|
// width: 32,
|
||||||
|
// '& svg:nth-of-type(1)': {
|
||||||
|
// height: '16px',
|
||||||
|
// width: '16px',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// medium: {
|
||||||
|
// height: 44,
|
||||||
|
// width: 44,
|
||||||
|
// '& svg:nth-of-type(1)': {
|
||||||
|
// height: '18px',
|
||||||
|
// width: '18px',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// large: {
|
||||||
|
// height: 44,
|
||||||
|
// width: 44,
|
||||||
|
// '& svg:nth-of-type(1)': {
|
||||||
|
// height: '20px',
|
||||||
|
// width: '20px',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// tertiary: {
|
||||||
|
// height: 32,
|
||||||
|
// width: 44,
|
||||||
|
// '& svg:nth-of-type(1)': {
|
||||||
|
// height: '16px',
|
||||||
|
// width: '16px',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
|
||||||
|
export const ToolButton = styled('button', {
|
||||||
|
position: 'relative',
|
||||||
|
height: '32px',
|
||||||
|
width: '32px',
|
||||||
|
backgroundColor: '$panel',
|
||||||
|
borderRadius: '4px',
|
||||||
|
padding: '0',
|
||||||
|
margin: '0',
|
||||||
|
display: 'grid',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
outline: 'none',
|
||||||
|
border: 'none',
|
||||||
|
pointerEvents: 'all',
|
||||||
|
fontSize: '$0',
|
||||||
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
'& > *': {
|
||||||
|
gridRow: 1,
|
||||||
|
gridColumn: 1,
|
||||||
|
},
|
||||||
|
|
||||||
|
'&:disabled': {
|
||||||
|
opacity: '0.5',
|
||||||
|
},
|
||||||
|
|
||||||
|
'& > span': {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const PrimaryToolButton = styled(ToolButton, {
|
||||||
|
variants: {
|
||||||
|
bp: {
|
||||||
|
mobile: {
|
||||||
|
height: 44,
|
||||||
|
width: 44,
|
||||||
|
'& svg:nth-of-type(1)': {
|
||||||
|
height: '20px',
|
||||||
|
width: '20px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
small: {
|
||||||
|
'&:hover:not(:disabled)': {
|
||||||
|
backgroundColor: '$hover',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
medium: {},
|
||||||
|
large: {},
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
true: {
|
||||||
|
color: '$selected',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const SecondaryToolButton = styled(ToolButton, {
|
||||||
|
variants: {
|
||||||
|
bp: {
|
||||||
|
mobile: {
|
||||||
|
height: 44,
|
||||||
|
width: 44,
|
||||||
|
'& svg:nth-of-type(1)': {
|
||||||
|
height: '18px',
|
||||||
|
width: '18px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
small: {
|
||||||
|
'&:hover:not(:disabled)': {
|
||||||
|
backgroundColor: '$hover',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
medium: {},
|
||||||
|
large: {},
|
||||||
|
},
|
||||||
|
isActive: {
|
||||||
|
true: {
|
||||||
|
color: '$selected',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
export const TertiaryToolButton = styled(ToolButton, {
|
||||||
|
variants: {
|
||||||
|
bp: {
|
||||||
|
mobile: {
|
||||||
|
height: 32,
|
||||||
|
width: 44,
|
||||||
|
'& svg:nth-of-type(1)': {
|
||||||
|
height: '16px',
|
||||||
|
width: '16px',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
small: {
|
||||||
|
height: 40,
|
||||||
|
width: 40,
|
||||||
|
'& svg:nth-of-type(1)': {
|
||||||
|
height: '18px',
|
||||||
|
width: '18px',
|
||||||
|
},
|
||||||
|
'&:hover:not(:disabled)': {
|
||||||
|
backgroundColor: '$hover',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
medium: {},
|
||||||
|
large: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
interface PrimaryToolButtonProps {
|
||||||
|
label: string
|
||||||
|
onClick: () => void
|
||||||
|
onDoubleClick?: () => void
|
||||||
|
isActive: boolean
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function PrimaryButton({
|
||||||
|
label,
|
||||||
|
onClick,
|
||||||
|
onDoubleClick,
|
||||||
|
isActive,
|
||||||
|
children,
|
||||||
|
}: PrimaryToolButtonProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Tooltip label={label}>
|
||||||
|
<PrimaryToolButton
|
||||||
|
name={label}
|
||||||
|
bp={{
|
||||||
|
'@initial': 'mobile',
|
||||||
|
'@sm': 'small',
|
||||||
|
'@md': 'medium',
|
||||||
|
'@lg': 'large',
|
||||||
|
}}
|
||||||
|
onClick={onClick}
|
||||||
|
onDoubleClick={onDoubleClick}
|
||||||
|
isActive={isActive}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</PrimaryToolButton>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SecondaryToolButtonProps {
|
||||||
|
label: string
|
||||||
|
onClick: () => void
|
||||||
|
onDoubleClick?: () => void
|
||||||
|
isActive: boolean
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SecondaryButton({
|
||||||
|
label,
|
||||||
|
onClick,
|
||||||
|
onDoubleClick,
|
||||||
|
isActive,
|
||||||
|
children,
|
||||||
|
}: SecondaryToolButtonProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Tooltip label={label}>
|
||||||
|
<SecondaryToolButton
|
||||||
|
name={label}
|
||||||
|
bp={{
|
||||||
|
'@initial': 'mobile',
|
||||||
|
'@sm': 'small',
|
||||||
|
'@md': 'medium',
|
||||||
|
'@lg': 'large',
|
||||||
|
}}
|
||||||
|
onClick={onClick}
|
||||||
|
onDoubleClick={onDoubleClick}
|
||||||
|
isActive={isActive}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</SecondaryToolButton>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TertiaryToolProps {
|
||||||
|
label: string
|
||||||
|
onClick: () => void
|
||||||
|
onDoubleClick?: () => void
|
||||||
|
children: React.ReactNode
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TertiaryButton({
|
||||||
|
label,
|
||||||
|
onClick,
|
||||||
|
onDoubleClick,
|
||||||
|
children,
|
||||||
|
}: TertiaryToolProps): JSX.Element {
|
||||||
|
return (
|
||||||
|
<Tooltip label={label}>
|
||||||
|
<TertiaryToolButton
|
||||||
|
name={label}
|
||||||
|
bp={{
|
||||||
|
'@initial': 'mobile',
|
||||||
|
'@sm': 'small',
|
||||||
|
'@md': 'medium',
|
||||||
|
'@lg': 'large',
|
||||||
|
}}
|
||||||
|
onClick={onClick}
|
||||||
|
onDoubleClick={onDoubleClick}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</TertiaryToolButton>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TertiaryButtonsContainer = styled('div', {
|
||||||
|
backgroundColor: '$panel',
|
||||||
|
borderRadius: '4px',
|
||||||
|
overflow: 'hidden',
|
||||||
|
pointerEvents: 'all',
|
||||||
|
userSelect: 'none',
|
||||||
|
zIndex: 200,
|
||||||
|
minWidth: 36,
|
||||||
|
border: '1px solid $panel',
|
||||||
|
boxShadow: '0px 2px 4px rgba(0,0,0,.10)',
|
||||||
|
padding: 2,
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
alignItems: 'center',
|
||||||
|
|
||||||
|
'& svg': {
|
||||||
|
strokeWidth: 0,
|
||||||
|
},
|
||||||
|
})
|
|
@ -5,18 +5,16 @@ import {
|
||||||
LockClosedIcon,
|
LockClosedIcon,
|
||||||
LockOpen1Icon,
|
LockOpen1Icon,
|
||||||
Pencil1Icon,
|
Pencil1Icon,
|
||||||
Pencil2Icon,
|
|
||||||
SquareIcon,
|
SquareIcon,
|
||||||
TextIcon,
|
TextIcon,
|
||||||
} from '@radix-ui/react-icons'
|
} from '@radix-ui/react-icons'
|
||||||
import { IconButton } from 'components/shared'
|
import { PrimaryButton, SecondaryButton } from './shared'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import state, { useSelector } from 'state'
|
import state, { useSelector } from 'state'
|
||||||
import styled from 'styles'
|
import styled from 'styles'
|
||||||
import { ShapeType } from 'types'
|
import { ShapeType } from 'types'
|
||||||
import UndoRedo from './undo-redo'
|
import UndoRedo from './undo-redo'
|
||||||
import Zoom from './zoom'
|
import Zoom from './zoom'
|
||||||
import Tooltip from '../tooltip'
|
|
||||||
|
|
||||||
const selectArrowTool = () => state.send('SELECTED_ARROW_TOOL')
|
const selectArrowTool = () => state.send('SELECTED_ARROW_TOOL')
|
||||||
const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
|
const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
|
||||||
|
@ -24,167 +22,167 @@ const selectEllipseTool = () => state.send('SELECTED_ELLIPSE_TOOL')
|
||||||
const selectTextTool = () => state.send('SELECTED_TEXT_TOOL')
|
const selectTextTool = () => state.send('SELECTED_TEXT_TOOL')
|
||||||
const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_TOOL')
|
const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_TOOL')
|
||||||
const selectSelectTool = () => state.send('SELECTED_SELECT_TOOL')
|
const selectSelectTool = () => state.send('SELECTED_SELECT_TOOL')
|
||||||
const selectToolLock = () => state.send('TOGGLED_TOOL_LOCK')
|
const toggleToolLock = () => state.send('TOGGLED_TOOL_LOCK')
|
||||||
|
|
||||||
export default function ToolsPanel(): JSX.Element {
|
export default function ToolsPanel(): JSX.Element {
|
||||||
const activeTool = useSelector((s) => s.data.activeTool)
|
const activeTool = useSelector((s) => s.data.activeTool)
|
||||||
|
|
||||||
const isToolLocked = useSelector((s) => s.data.settings.isToolLocked)
|
const isToolLocked = useSelector((s) => s.data.settings.isToolLocked)
|
||||||
|
|
||||||
const isPenLocked = useSelector((s) => s.data.settings.isPenLocked)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<OuterContainer>
|
<ToolsPanelContainer>
|
||||||
<Zoom />
|
<LeftWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
|
||||||
<Flex size={{ '@sm': 'small' }}>
|
<Zoom />
|
||||||
<Container>
|
<Container>
|
||||||
<Tooltip label="Select">
|
<SecondaryButton
|
||||||
<IconButton
|
label={'Select'}
|
||||||
name="select"
|
onClick={selectSelectTool}
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
isActive={activeTool === 'select'}
|
||||||
size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
|
>
|
||||||
onClick={selectSelectTool}
|
<CursorArrowIcon />
|
||||||
isActive={activeTool === 'select'}
|
</SecondaryButton>
|
||||||
>
|
|
||||||
<CursorArrowIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</Container>
|
</Container>
|
||||||
|
</LeftWrap>
|
||||||
|
<CenterWrap>
|
||||||
<Container>
|
<Container>
|
||||||
<Tooltip label="Draw">
|
<PrimaryButton
|
||||||
<IconButton
|
label={ShapeType.Draw}
|
||||||
name={ShapeType.Draw}
|
onClick={selectDrawTool}
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
isActive={activeTool === ShapeType.Draw}
|
||||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
>
|
||||||
onClick={selectDrawTool}
|
<Pencil1Icon />
|
||||||
isActive={activeTool === ShapeType.Draw}
|
</PrimaryButton>
|
||||||
>
|
<PrimaryButton
|
||||||
<Pencil1Icon />
|
label={ShapeType.Rectangle}
|
||||||
</IconButton>
|
onClick={selectRectangleTool}
|
||||||
</Tooltip>
|
isActive={activeTool === ShapeType.Rectangle}
|
||||||
<Tooltip label="Rectangle">
|
>
|
||||||
<IconButton
|
<SquareIcon />
|
||||||
name={ShapeType.Rectangle}
|
</PrimaryButton>
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
<PrimaryButton
|
||||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
label={ShapeType.Ellipse}
|
||||||
onClick={selectRectangleTool}
|
onClick={selectEllipseTool}
|
||||||
isActive={activeTool === ShapeType.Rectangle}
|
isActive={activeTool === ShapeType.Ellipse}
|
||||||
>
|
>
|
||||||
<SquareIcon />
|
<CircleIcon />
|
||||||
</IconButton>
|
</PrimaryButton>
|
||||||
</Tooltip>
|
<PrimaryButton
|
||||||
<Tooltip label="Ellipse">
|
label={ShapeType.Arrow}
|
||||||
<IconButton
|
onClick={selectArrowTool}
|
||||||
name={ShapeType.Ellipse}
|
isActive={activeTool === ShapeType.Arrow}
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
>
|
||||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
<ArrowTopRightIcon />
|
||||||
onClick={selectEllipseTool}
|
</PrimaryButton>
|
||||||
isActive={activeTool === ShapeType.Ellipse}
|
<PrimaryButton
|
||||||
>
|
label={ShapeType.Text}
|
||||||
<CircleIcon />
|
onClick={selectTextTool}
|
||||||
</IconButton>
|
isActive={activeTool === ShapeType.Text}
|
||||||
</Tooltip>
|
>
|
||||||
<Tooltip label="Arrow">
|
<TextIcon />
|
||||||
<IconButton
|
</PrimaryButton>
|
||||||
name={ShapeType.Arrow}
|
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
|
||||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
|
||||||
onClick={selectArrowTool}
|
|
||||||
isActive={activeTool === ShapeType.Arrow}
|
|
||||||
>
|
|
||||||
<ArrowTopRightIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip label="Text">
|
|
||||||
<IconButton
|
|
||||||
name={ShapeType.Text}
|
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
|
||||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
|
||||||
onClick={selectTextTool}
|
|
||||||
isActive={activeTool === ShapeType.Text}
|
|
||||||
>
|
|
||||||
<TextIcon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</Container>
|
</Container>
|
||||||
|
</CenterWrap>
|
||||||
|
<RightWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
|
||||||
<Container>
|
<Container>
|
||||||
<Tooltip label="Lock Tool">
|
<SecondaryButton
|
||||||
<IconButton
|
label={'Lock Tool'}
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
onClick={toggleToolLock}
|
||||||
size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
|
isActive={isToolLocked}
|
||||||
onClick={selectToolLock}
|
>
|
||||||
>
|
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
||||||
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
</SecondaryButton>
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
{isPenLocked && (
|
|
||||||
<Tooltip label="Unlock Pen">
|
|
||||||
<IconButton
|
|
||||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
|
||||||
size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
|
|
||||||
onClick={selectToolLock}
|
|
||||||
>
|
|
||||||
<Pencil2Icon />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</Container>
|
</Container>
|
||||||
</Flex>
|
<UndoRedo />
|
||||||
<UndoRedo />
|
</RightWrap>
|
||||||
</OuterContainer>
|
</ToolsPanelContainer>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const OuterContainer = styled('div', {
|
const ToolsPanelContainer = styled('div', {
|
||||||
position: 'fixed',
|
position: 'fixed',
|
||||||
bottom: 44,
|
bottom: 44,
|
||||||
left: 0,
|
left: 0,
|
||||||
right: 0,
|
right: 0,
|
||||||
|
width: '100%',
|
||||||
|
minWidth: 0,
|
||||||
|
maxWidth: '100%',
|
||||||
|
display: 'grid',
|
||||||
|
gridTemplateColumns: '1fr auto 1fr',
|
||||||
padding: '0 8px 12px 8px',
|
padding: '0 8px 12px 8px',
|
||||||
width: '100%',
|
|
||||||
display: 'flex',
|
|
||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
justifyContent: 'center',
|
|
||||||
flexWrap: 'wrap',
|
|
||||||
gap: 16,
|
|
||||||
zIndex: 200,
|
zIndex: 200,
|
||||||
})
|
gap: 8,
|
||||||
|
|
||||||
const Flex = styled('div', {
|
|
||||||
display: 'flex',
|
|
||||||
width: '100%',
|
|
||||||
padding: '0 4px',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
alignItems: 'flex-end',
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
size: {
|
|
||||||
small: {
|
|
||||||
width: 'auto',
|
|
||||||
padding: '0',
|
|
||||||
justifyContent: 'center',
|
|
||||||
'& > *:nth-child(n+2)': {
|
|
||||||
marginLeft: 16,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
})
|
||||||
|
|
||||||
const Container = styled('div', {
|
const Container = styled('div', {
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
backgroundColor: '$panel',
|
backgroundColor: '$panel',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
overflow: 'hidden',
|
|
||||||
border: '1px solid $panel',
|
border: '1px solid $panel',
|
||||||
pointerEvents: 'all',
|
pointerEvents: 'all',
|
||||||
userSelect: 'none',
|
userSelect: 'none',
|
||||||
height: '100%',
|
height: 'fit-content',
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
padding: 4,
|
padding: 2,
|
||||||
boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
|
boxShadow: '0px 2px 4px rgba(0,0,0,.16)',
|
||||||
|
})
|
||||||
|
|
||||||
'& svg': {
|
const CenterWrap = styled('div', {
|
||||||
strokeWidth: 0,
|
gridRow: 1,
|
||||||
|
gridColumn: 2,
|
||||||
|
display: 'flex',
|
||||||
|
width: 'fit-content',
|
||||||
|
justifyContent: 'center',
|
||||||
|
})
|
||||||
|
|
||||||
|
const LeftWrap = styled('div', {
|
||||||
|
gridRow: 1,
|
||||||
|
gridColumn: 1,
|
||||||
|
display: 'flex',
|
||||||
|
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',
|
||||||
|
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',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { IconButton } from 'components/shared'
|
import { TertiaryButton, TertiaryButtonsContainer } from './shared'
|
||||||
import { RotateCcw, RotateCw, Trash2 } from 'react-feather'
|
import { Undo, Redo, Trash } from 'components/icons'
|
||||||
import state from 'state'
|
import state from 'state'
|
||||||
import styled from 'styles'
|
|
||||||
import Tooltip from '../tooltip'
|
|
||||||
|
|
||||||
const undo = () => state.send('UNDO')
|
const undo = () => state.send('UNDO')
|
||||||
const redo = () => state.send('REDO')
|
const redo = () => state.send('REDO')
|
||||||
|
@ -10,55 +8,16 @@ const clear = () => state.send('CLEARED_PAGE')
|
||||||
|
|
||||||
export default function UndoRedo(): JSX.Element {
|
export default function UndoRedo(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Container size={{ '@sm': 'small' }}>
|
<TertiaryButtonsContainer>
|
||||||
<Tooltip label="Undo">
|
<TertiaryButton label="Undo" onClick={undo}>
|
||||||
<IconButton onClick={undo}>
|
<Undo />
|
||||||
<RotateCcw />
|
</TertiaryButton>
|
||||||
</IconButton>
|
<TertiaryButton label="Redo" onClick={redo}>
|
||||||
</Tooltip>
|
<Redo />
|
||||||
<Tooltip label="Redo">
|
</TertiaryButton>
|
||||||
<IconButton onClick={redo}>
|
<TertiaryButton label="Delete" onClick={clear}>
|
||||||
<RotateCw />
|
<Trash />
|
||||||
</IconButton>
|
</TertiaryButton>
|
||||||
</Tooltip>
|
</TertiaryButtonsContainer>
|
||||||
<Tooltip label="Clear Canvas">
|
|
||||||
<IconButton onClick={clear}>
|
|
||||||
<Trash2 />
|
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
</Container>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const Container = styled('div', {
|
|
||||||
position: 'absolute',
|
|
||||||
bottom: 64,
|
|
||||||
right: 12,
|
|
||||||
backgroundColor: '$panel',
|
|
||||||
borderRadius: '4px',
|
|
||||||
overflow: 'hidden',
|
|
||||||
alignSelf: 'flex-end',
|
|
||||||
pointerEvents: 'all',
|
|
||||||
userSelect: 'none',
|
|
||||||
zIndex: 200,
|
|
||||||
border: '1px solid $panel',
|
|
||||||
boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
|
|
||||||
display: 'flex',
|
|
||||||
padding: 4,
|
|
||||||
flexDirection: 'column',
|
|
||||||
|
|
||||||
'& svg': {
|
|
||||||
height: 13,
|
|
||||||
width: 13,
|
|
||||||
},
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
size: {
|
|
||||||
small: {
|
|
||||||
bottom: 12,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
import { ZoomInIcon, ZoomOutIcon } from '@radix-ui/react-icons'
|
import { ZoomInIcon, ZoomOutIcon } from '@radix-ui/react-icons'
|
||||||
import { IconButton } from 'components/shared'
|
import { TertiaryButton, TertiaryButtonsContainer } from './shared'
|
||||||
import state, { useSelector } from 'state'
|
import state, { useSelector } from 'state'
|
||||||
import styled from 'styles'
|
|
||||||
import Tooltip from '../tooltip'
|
|
||||||
import tld from 'utils/tld'
|
import tld from 'utils/tld'
|
||||||
|
|
||||||
const zoomIn = () => state.send('ZOOMED_IN')
|
const zoomIn = () => state.send('ZOOMED_IN')
|
||||||
|
@ -12,21 +10,15 @@ const zoomToActual = () => state.send('ZOOMED_TO_ACTUAL')
|
||||||
|
|
||||||
export default function Zoom(): JSX.Element {
|
export default function Zoom(): JSX.Element {
|
||||||
return (
|
return (
|
||||||
<Container size={{ '@sm': 'small' }}>
|
<TertiaryButtonsContainer>
|
||||||
<Tooltip label="Zoom Out">
|
<TertiaryButton label="Zoom Out" onClick={zoomOut}>
|
||||||
<IconButton onClick={zoomOut}>
|
<ZoomOutIcon />
|
||||||
<ZoomOutIcon />
|
</TertiaryButton>
|
||||||
</IconButton>
|
<TertiaryButton label="Zoom In" onClick={zoomIn}>
|
||||||
</Tooltip>
|
<ZoomInIcon />
|
||||||
<Tooltip label="Zoom In">
|
</TertiaryButton>
|
||||||
<IconButton onClick={zoomIn}>
|
<ZoomCounter />
|
||||||
<ZoomInIcon />
|
</TertiaryButtonsContainer>
|
||||||
</IconButton>
|
|
||||||
</Tooltip>
|
|
||||||
<Tooltip label="Reset Zoom">
|
|
||||||
<ZoomCounter />
|
|
||||||
</Tooltip>
|
|
||||||
</Container>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,50 +26,12 @@ function ZoomCounter() {
|
||||||
const zoom = useSelector((s) => tld.getCurrentCamera(s.data).zoom)
|
const zoom = useSelector((s) => tld.getCurrentCamera(s.data).zoom)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ZoomButton
|
<TertiaryButton
|
||||||
|
label="Reset Zoom"
|
||||||
onClick={zoomToActual}
|
onClick={zoomToActual}
|
||||||
onDoubleClick={zoomToFit}
|
onDoubleClick={zoomToFit}
|
||||||
style={{ width: '44px' }}
|
|
||||||
>
|
>
|
||||||
{Math.round(zoom * 100)}%
|
{Math.round(zoom * 100)}%
|
||||||
</ZoomButton>
|
</TertiaryButton>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ZoomButton = styled(IconButton, {
|
|
||||||
fontSize: '$0',
|
|
||||||
padding: 8,
|
|
||||||
})
|
|
||||||
|
|
||||||
const Container = styled('div', {
|
|
||||||
position: 'absolute',
|
|
||||||
left: 12,
|
|
||||||
bottom: 64,
|
|
||||||
backgroundColor: '$panel',
|
|
||||||
borderRadius: '4px',
|
|
||||||
overflow: 'hidden',
|
|
||||||
alignSelf: 'flex-end',
|
|
||||||
pointerEvents: 'all',
|
|
||||||
userSelect: 'none',
|
|
||||||
zIndex: 200,
|
|
||||||
border: '1px solid $panel',
|
|
||||||
boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
|
|
||||||
display: 'flex',
|
|
||||||
padding: 4,
|
|
||||||
flexDirection: 'column',
|
|
||||||
alignItems: 'center',
|
|
||||||
|
|
||||||
'& svg': {
|
|
||||||
strokeWidth: 0,
|
|
||||||
},
|
|
||||||
|
|
||||||
variants: {
|
|
||||||
size: {
|
|
||||||
small: {
|
|
||||||
bottom: 12,
|
|
||||||
flexDirection: 'row',
|
|
||||||
alignItems: 'center',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
|
@ -8,8 +8,13 @@ import {
|
||||||
fastTranslate,
|
fastTranslate,
|
||||||
} from 'state/hacks'
|
} from 'state/hacks'
|
||||||
import inputs from 'state/inputs'
|
import inputs from 'state/inputs'
|
||||||
|
import { isMobile } from 'utils'
|
||||||
import Vec from 'utils/vec'
|
import Vec from 'utils/vec'
|
||||||
|
|
||||||
|
function handleFocusOut() {
|
||||||
|
state.send('BLURRED_EDITING_SHAPE')
|
||||||
|
}
|
||||||
|
|
||||||
export default function useCanvasEvents(
|
export default function useCanvasEvents(
|
||||||
rCanvas: MutableRefObject<SVGGElement>
|
rCanvas: MutableRefObject<SVGGElement>
|
||||||
) {
|
) {
|
||||||
|
@ -76,14 +81,12 @@ export default function useCanvasEvents(
|
||||||
|
|
||||||
// Send event on iOS when a user presses the "Done" key while editing a text element
|
// Send event on iOS when a user presses the "Done" key while editing a text element
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleFocusOut() {
|
if (isMobile()) {
|
||||||
state.send('BLURRED_EDITING_SHAPE')
|
document.addEventListener('focusout', handleFocusOut)
|
||||||
}
|
|
||||||
|
|
||||||
document.addEventListener('focusout', handleFocusOut)
|
return () => {
|
||||||
|
document.removeEventListener('focusout', handleFocusOut)
|
||||||
return () => {
|
}
|
||||||
document.removeEventListener('focusout', handleFocusOut)
|
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import state from 'state'
|
import state from 'state'
|
||||||
import coopState from 'state/coop/coop-state'
|
// import coopState from 'state/coop/coop-state'
|
||||||
|
|
||||||
export default function useLoadOnMount(roomId?: string) {
|
export default function useLoadOnMount(roomId?: string) {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
@ -21,7 +21,7 @@ export default function useLoadOnMount(roomId?: string) {
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
state.send('UNMOUNTED', { roomId })
|
state.send('UNMOUNTED', { roomId })
|
||||||
coopState.send('LEFT_ROOM', { id: roomId })
|
// coopState.send('LEFT_ROOM', { id: roomId })
|
||||||
}
|
}
|
||||||
}, [roomId])
|
}, [roomId])
|
||||||
}
|
}
|
||||||
|
|
4
public/icons/Redo.svg
Normal file
4
public/icons/Redo.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.5 2.49538C12.2239 2.49538 12 2.71923 12 2.99538V5.49559H9.49979C9.22364 5.49559 8.99979 5.71945 8.99979 5.99559C8.99979 6.27173 9.22364 6.49559 9.49979 6.49559H12.5C12.7761 6.49559 13 6.27173 13 5.99559V2.99538C13 2.71923 12.7761 2.49538 12.5 2.49538Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.69698 2.04877C6.62345 1.89773 5.52991 2.09968 4.58113 2.62417C3.63236 3.14867 2.87973 3.9673 2.43667 4.95673C1.99361 5.94616 1.8841 7.05278 2.12465 8.10985C2.3652 9.16693 2.94278 10.1172 3.77036 10.8175C4.59794 11.5177 5.63069 11.9301 6.713 11.9924C7.79531 12.0547 8.86855 11.7635 9.77101 11.1628C10.6735 10.5621 11.3563 9.68441 11.7165 8.66191C11.8083 8.40146 11.6715 8.11593 11.4111 8.02417C11.1506 7.93241 10.8651 8.06916 10.7733 8.32961C10.4851 9.14762 9.93888 9.84981 9.21691 10.3304C8.49493 10.811 7.63632 11.0439 6.77046 10.994C5.9046 10.9442 5.07839 10.6143 4.41631 10.0541C3.75424 9.49386 3.29217 8.73363 3.09972 7.88796C2.90728 7.04229 2.99488 6.15698 3.34934 5.36542C3.7038 4.57387 4.30591 3.91895 5.06494 3.49935C5.82398 3.07974 6.69882 2.91819 7.55765 3.03902C8.41649 3.15985 9.21279 3.55653 9.82658 4.16928L9.83745 4.17981L12.1576 6.35996C12.3588 6.54906 12.6753 6.53921 12.8644 6.33797C13.0535 6.13673 13.0436 5.8203 12.8424 5.63121L10.5276 3.4561C9.76111 2.69329 8.76794 2.19945 7.69698 2.04877Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
6
public/icons/Trash.svg
Normal file
6
public/icons/Trash.svg
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2 4.65555C2 4.37941 2.22386 4.15555 2.5 4.15555H12.2C12.4761 4.15555 12.7 4.37941 12.7 4.65555C12.7 4.93169 12.4761 5.15555 12.2 5.15555H2.5C2.22386 5.15555 2 4.93169 2 4.65555Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27208 3C6.11885 3 5.97189 3.06087 5.86353 3.16923C5.75518 3.27758 5.6943 3.42454 5.6943 3.57778V4.15556H9.00542V3.57778C9.00542 3.42454 8.94454 3.27758 8.83619 3.16923C8.72783 3.06087 8.58087 3 8.42764 3H6.27208ZM10.0054 4.15556V3.57778C10.0054 3.15933 9.83919 2.75801 9.54329 2.46212C9.2474 2.16623 8.84609 2 8.42764 2H6.27208C5.85363 2 5.45232 2.16623 5.15642 2.46212C4.86053 2.75801 4.6943 3.15933 4.6943 3.57778V4.15556H3.57764C3.30149 4.15556 3.07764 4.37941 3.07764 4.65556V12.2C3.07764 12.6185 3.24387 13.0198 3.53976 13.3157C3.83565 13.6115 4.23696 13.7778 4.65541 13.7778H10.0443C10.4628 13.7778 10.8641 13.6115 11.16 13.3157C11.4559 13.0198 11.6221 12.6185 11.6221 12.2V4.65556C11.6221 4.37941 11.3982 4.15556 11.1221 4.15556H10.0054ZM4.07764 5.15556V12.2C4.07764 12.3532 4.13851 12.5002 4.24686 12.6086C4.35522 12.7169 4.50218 12.7778 4.65541 12.7778H10.0443C10.1975 12.7778 10.3445 12.7169 10.4529 12.6086C10.5612 12.5002 10.6221 12.3532 10.6221 12.2V5.15556H4.07764Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.27246 6.85001C6.5486 6.85001 6.77246 7.07386 6.77246 7.35001V10.5833C6.77246 10.8595 6.5486 11.0833 6.27246 11.0833C5.99632 11.0833 5.77246 10.8595 5.77246 10.5833V7.35001C5.77246 7.07386 5.99632 6.85001 6.27246 6.85001Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.42773 6.85001C8.70388 6.85001 8.92773 7.07386 8.92773 7.35001V10.5833C8.92773 10.8595 8.70388 11.0833 8.42773 11.0833C8.15159 11.0833 7.92773 10.8595 7.92773 10.5833V7.35001C7.92773 7.07386 8.15159 6.85001 8.42773 6.85001Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.9 KiB |
4
public/icons/Undo.svg
Normal file
4
public/icons/Undo.svg
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.5 2.49538C2.77614 2.49538 3 2.71923 3 2.99538V5.49559H5.50021C5.77636 5.49559 6.00021 5.71945 6.00021 5.99559C6.00021 6.27173 5.77636 6.49559 5.50021 6.49559H2.5C2.22386 6.49559 2 6.27173 2 5.99559V2.99538C2 2.71923 2.22386 2.49538 2.5 2.49538Z" fill="black"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.30302 2.04877C8.37655 1.89773 9.47009 2.09968 10.4189 2.62417C11.3676 3.14867 12.1203 3.9673 12.5633 4.95673C13.0064 5.94616 13.1159 7.05278 12.8753 8.10985C12.6348 9.16693 12.0572 10.1172 11.2296 10.8175C10.4021 11.5177 9.36931 11.9301 8.287 11.9924C7.20469 12.0547 6.13145 11.7635 5.22899 11.1628C4.32653 10.5621 3.64374 9.68441 3.2835 8.66191C3.19174 8.40146 3.32849 8.11593 3.58894 8.02417C3.84939 7.93241 4.13492 8.06916 4.22668 8.32961C4.51488 9.14762 5.06112 9.84981 5.78309 10.3304C6.50507 10.811 7.36368 11.0439 8.22954 10.994C9.0954 10.9442 9.92161 10.6143 10.5837 10.0541C11.2458 9.49386 11.7078 8.73363 11.9003 7.88796C12.0927 7.04229 12.0051 6.15698 11.6507 5.36542C11.2962 4.57387 10.6941 3.91895 9.93506 3.49935C9.17602 3.07974 8.30118 2.91819 7.44235 3.03902C6.58351 3.15985 5.78721 3.55653 5.17342 4.16928L5.16255 4.17981L2.84239 6.35996C2.64115 6.54906 2.32472 6.53921 2.13562 6.33797C1.94653 6.13673 1.95637 5.8203 2.15761 5.63121L4.47241 3.4561C5.23889 2.69329 6.23206 2.19945 7.30302 2.04877Z" fill="black"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
|
@ -734,7 +734,6 @@ const state = createState({
|
||||||
do: 'breakSession',
|
do: 'breakSession',
|
||||||
to: 'pinching.toolPinching',
|
to: 'pinching.toolPinching',
|
||||||
},
|
},
|
||||||
TOGGLED_TOOL_LOCK: 'toggleToolLock',
|
|
||||||
},
|
},
|
||||||
states: {
|
states: {
|
||||||
draw: {
|
draw: {
|
||||||
|
|
Loading…
Reference in a new issue