commit
83c6fce2bd
19 changed files with 537 additions and 258 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'
|
27
components/icons/redo.tsx
Normal file
27
components/icons/redo.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import * as React from 'react'
|
||||
|
||||
function SvgRedo(props: React.SVGProps<SVGSVGElement>): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 15 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
|
33
components/icons/trash.tsx
Normal file
33
components/icons/trash.tsx
Normal file
|
@ -0,0 +1,33 @@
|
|||
import * as React from 'react'
|
||||
|
||||
function SvgTrash(props: React.SVGProps<SVGSVGElement>): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 15 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
|
27
components/icons/undo.tsx
Normal file
27
components/icons/undo.tsx
Normal file
|
@ -0,0 +1,27 @@
|
|||
import * as React from 'react'
|
||||
|
||||
function SvgUndo(props: React.SVGProps<SVGSVGElement>): JSX.Element {
|
||||
return (
|
||||
<svg
|
||||
viewBox="0 0 15 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 IconButton = styled('button', {
|
||||
position: 'relative',
|
||||
height: '32px',
|
||||
width: '32px',
|
||||
backgroundColor: '$panel',
|
||||
|
@ -19,6 +20,7 @@ export const IconButton = styled('button', {
|
|||
outline: 'none',
|
||||
border: 'none',
|
||||
pointerEvents: 'all',
|
||||
fontSize: '$0',
|
||||
cursor: 'pointer',
|
||||
|
||||
'& > *': {
|
||||
|
@ -48,7 +50,9 @@ export const IconButton = styled('button', {
|
|||
},
|
||||
size: {
|
||||
small: {
|
||||
'& svg': {
|
||||
height: 32,
|
||||
width: 32,
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '16px',
|
||||
width: '16px',
|
||||
},
|
||||
|
@ -56,17 +60,17 @@ export const IconButton = styled('button', {
|
|||
medium: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
'& svg': {
|
||||
height: '20px',
|
||||
width: '20px',
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '18px',
|
||||
width: '18px',
|
||||
},
|
||||
},
|
||||
large: {
|
||||
height: 44,
|
||||
width: 44,
|
||||
'& svg': {
|
||||
height: '24px',
|
||||
width: '24px',
|
||||
'& svg:nth-of-type(1)': {
|
||||
height: '20px',
|
||||
width: '20px',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -404,3 +408,10 @@ export const ButtonsRow = styled('div', {
|
|||
justifyContent: 'flex-start',
|
||||
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',
|
||||
pointerEvents: 'all',
|
||||
padding: 2,
|
||||
zIndex: 300,
|
||||
|
||||
'& hr': {
|
||||
marginTop: 2,
|
||||
|
|
249
components/tools-panel/shared.tsx
Normal file
249
components/tools-panel/shared.tsx
Normal file
|
@ -0,0 +1,249 @@
|
|||
import Tooltip from 'components/tooltip'
|
||||
import styled from 'styles'
|
||||
|
||||
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 Container = styled('div', {
|
||||
backgroundColor: '$panel',
|
||||
border: '1px solid $panel',
|
||||
borderRadius: '4px',
|
||||
boxShadow: '0px 2px 4px rgba(0,0,0,.16)',
|
||||
display: 'flex',
|
||||
height: 'fit-content',
|
||||
padding: 2,
|
||||
pointerEvents: 'all',
|
||||
position: 'relative',
|
||||
userSelect: 'none',
|
||||
zIndex: 200,
|
||||
})
|
||||
|
||||
export const TertiaryButtonsContainer = styled(Container, {
|
||||
variants: {
|
||||
bp: {
|
||||
mobile: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'column',
|
||||
},
|
||||
small: {
|
||||
alignItems: 'center',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
|
@ -5,18 +5,16 @@ import {
|
|||
LockClosedIcon,
|
||||
LockOpen1Icon,
|
||||
Pencil1Icon,
|
||||
Pencil2Icon,
|
||||
SquareIcon,
|
||||
TextIcon,
|
||||
} from '@radix-ui/react-icons'
|
||||
import { IconButton } from 'components/shared'
|
||||
import { PrimaryButton, SecondaryButton, Container } from './shared'
|
||||
import React from 'react'
|
||||
import state, { useSelector } from 'state'
|
||||
import styled from 'styles'
|
||||
import { ShapeType } from 'types'
|
||||
import UndoRedo from './undo-redo'
|
||||
import Zoom from './zoom'
|
||||
import Tooltip from '../tooltip'
|
||||
|
||||
const selectArrowTool = () => state.send('SELECTED_ARROW_TOOL')
|
||||
const selectDrawTool = () => state.send('SELECTED_DRAW_TOOL')
|
||||
|
@ -24,167 +22,154 @@ const selectEllipseTool = () => state.send('SELECTED_ELLIPSE_TOOL')
|
|||
const selectTextTool = () => state.send('SELECTED_TEXT_TOOL')
|
||||
const selectRectangleTool = () => state.send('SELECTED_RECTANGLE_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 {
|
||||
const activeTool = useSelector((s) => s.data.activeTool)
|
||||
|
||||
const isToolLocked = useSelector((s) => s.data.settings.isToolLocked)
|
||||
|
||||
const isPenLocked = useSelector((s) => s.data.settings.isPenLocked)
|
||||
|
||||
return (
|
||||
<OuterContainer>
|
||||
<Zoom />
|
||||
<Flex size={{ '@sm': 'small' }}>
|
||||
<ToolsPanelContainer>
|
||||
<LeftWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
|
||||
<Zoom />
|
||||
<Container>
|
||||
<Tooltip label="Select">
|
||||
<IconButton
|
||||
name="select"
|
||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
||||
size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
|
||||
onClick={selectSelectTool}
|
||||
isActive={activeTool === 'select'}
|
||||
>
|
||||
<CursorArrowIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<SecondaryButton
|
||||
label={'Select'}
|
||||
onClick={selectSelectTool}
|
||||
isActive={activeTool === 'select'}
|
||||
>
|
||||
<CursorArrowIcon />
|
||||
</SecondaryButton>
|
||||
</Container>
|
||||
</LeftWrap>
|
||||
<CenterWrap>
|
||||
<Container>
|
||||
<Tooltip label="Draw">
|
||||
<IconButton
|
||||
name={ShapeType.Draw}
|
||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
||||
onClick={selectDrawTool}
|
||||
isActive={activeTool === ShapeType.Draw}
|
||||
>
|
||||
<Pencil1Icon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Rectangle">
|
||||
<IconButton
|
||||
name={ShapeType.Rectangle}
|
||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
||||
onClick={selectRectangleTool}
|
||||
isActive={activeTool === ShapeType.Rectangle}
|
||||
>
|
||||
<SquareIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Ellipse">
|
||||
<IconButton
|
||||
name={ShapeType.Ellipse}
|
||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
||||
size={{ '@initial': 'medium', '@sm': 'small', '@md': 'large' }}
|
||||
onClick={selectEllipseTool}
|
||||
isActive={activeTool === ShapeType.Ellipse}
|
||||
>
|
||||
<CircleIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Arrow">
|
||||
<IconButton
|
||||
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>
|
||||
<PrimaryButton
|
||||
label={ShapeType.Draw}
|
||||
onClick={selectDrawTool}
|
||||
isActive={activeTool === ShapeType.Draw}
|
||||
>
|
||||
<Pencil1Icon />
|
||||
</PrimaryButton>
|
||||
<PrimaryButton
|
||||
label={ShapeType.Rectangle}
|
||||
onClick={selectRectangleTool}
|
||||
isActive={activeTool === ShapeType.Rectangle}
|
||||
>
|
||||
<SquareIcon />
|
||||
</PrimaryButton>
|
||||
<PrimaryButton
|
||||
label={ShapeType.Ellipse}
|
||||
onClick={selectEllipseTool}
|
||||
isActive={activeTool === ShapeType.Ellipse}
|
||||
>
|
||||
<CircleIcon />
|
||||
</PrimaryButton>
|
||||
<PrimaryButton
|
||||
label={ShapeType.Arrow}
|
||||
onClick={selectArrowTool}
|
||||
isActive={activeTool === ShapeType.Arrow}
|
||||
>
|
||||
<ArrowTopRightIcon />
|
||||
</PrimaryButton>
|
||||
<PrimaryButton
|
||||
label={ShapeType.Text}
|
||||
onClick={selectTextTool}
|
||||
isActive={activeTool === ShapeType.Text}
|
||||
>
|
||||
<TextIcon />
|
||||
</PrimaryButton>
|
||||
</Container>
|
||||
</CenterWrap>
|
||||
<RightWrap size={{ '@initial': 'mobile', '@sm': 'small' }}>
|
||||
<Container>
|
||||
<Tooltip label="Lock Tool">
|
||||
<IconButton
|
||||
bp={{ '@initial': 'mobile', '@sm': 'small' }}
|
||||
size={{ '@initial': 'small', '@sm': 'small', '@md': 'medium' }}
|
||||
onClick={selectToolLock}
|
||||
>
|
||||
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
||||
</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>
|
||||
)}
|
||||
<SecondaryButton
|
||||
label={'Lock Tool'}
|
||||
onClick={toggleToolLock}
|
||||
isActive={isToolLocked}
|
||||
>
|
||||
{isToolLocked ? <LockClosedIcon /> : <LockOpen1Icon />}
|
||||
</SecondaryButton>
|
||||
</Container>
|
||||
</Flex>
|
||||
<UndoRedo />
|
||||
</OuterContainer>
|
||||
<UndoRedo />
|
||||
</RightWrap>
|
||||
</ToolsPanelContainer>
|
||||
)
|
||||
}
|
||||
|
||||
const OuterContainer = styled('div', {
|
||||
const ToolsPanelContainer = styled('div', {
|
||||
position: 'fixed',
|
||||
bottom: 44,
|
||||
left: 0,
|
||||
right: 0,
|
||||
padding: '0 8px 12px 8px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
minWidth: 0,
|
||||
maxWidth: '100%',
|
||||
display: 'grid',
|
||||
gridTemplateColumns: '1fr auto 1fr',
|
||||
padding: '0 8px 12px 8px',
|
||||
alignItems: 'flex-end',
|
||||
justifyContent: 'center',
|
||||
flexWrap: 'wrap',
|
||||
gap: 16,
|
||||
zIndex: 200,
|
||||
gap: 12,
|
||||
})
|
||||
|
||||
const Flex = styled('div', {
|
||||
const CenterWrap = styled('div', {
|
||||
gridRow: 1,
|
||||
gridColumn: 2,
|
||||
display: 'flex',
|
||||
width: '100%',
|
||||
padding: '0 4px',
|
||||
justifyContent: 'space-between',
|
||||
alignItems: 'flex-end',
|
||||
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: {
|
||||
width: 'auto',
|
||||
padding: '0',
|
||||
justifyContent: 'center',
|
||||
'& > *:nth-child(n+2)': {
|
||||
marginLeft: 16,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-end',
|
||||
justifyContent: 'space-between',
|
||||
'& > *:nth-of-type(1)': {
|
||||
marginBottom: '0px',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
const Container = styled('div', {
|
||||
position: 'relative',
|
||||
backgroundColor: '$panel',
|
||||
borderRadius: '4px',
|
||||
overflow: 'hidden',
|
||||
border: '1px solid $panel',
|
||||
pointerEvents: 'all',
|
||||
userSelect: 'none',
|
||||
height: '100%',
|
||||
const RightWrap = styled('div', {
|
||||
gridRow: 1,
|
||||
gridColumn: 3,
|
||||
display: 'flex',
|
||||
padding: 4,
|
||||
boxShadow: '0px 2px 4px rgba(0,0,0,.12)',
|
||||
|
||||
'& svg': {
|
||||
strokeWidth: 0,
|
||||
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 { RotateCcw, RotateCw, Trash2 } from 'react-feather'
|
||||
import { TertiaryButton, TertiaryButtonsContainer } from './shared'
|
||||
import { Undo, Redo, Trash } from 'components/icons'
|
||||
import state from 'state'
|
||||
import styled from 'styles'
|
||||
import Tooltip from '../tooltip'
|
||||
|
||||
const undo = () => state.send('UNDO')
|
||||
const redo = () => state.send('REDO')
|
||||
|
@ -10,55 +8,16 @@ const clear = () => state.send('CLEARED_PAGE')
|
|||
|
||||
export default function UndoRedo(): JSX.Element {
|
||||
return (
|
||||
<Container size={{ '@sm': 'small' }}>
|
||||
<Tooltip label="Undo">
|
||||
<IconButton onClick={undo}>
|
||||
<RotateCcw />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Redo">
|
||||
<IconButton onClick={redo}>
|
||||
<RotateCw />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Clear Canvas">
|
||||
<IconButton onClick={clear}>
|
||||
<Trash2 />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Container>
|
||||
<TertiaryButtonsContainer bp={{ '@initial': 'mobile', '@sm': 'small' }}>
|
||||
<TertiaryButton label="Undo" onClick={undo}>
|
||||
<Undo />
|
||||
</TertiaryButton>
|
||||
<TertiaryButton label="Redo" onClick={redo}>
|
||||
<Redo />
|
||||
</TertiaryButton>
|
||||
<TertiaryButton label="Delete" onClick={clear}>
|
||||
<Trash />
|
||||
</TertiaryButton>
|
||||
</TertiaryButtonsContainer>
|
||||
)
|
||||
}
|
||||
|
||||
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 { IconButton } from 'components/shared'
|
||||
import { TertiaryButton, TertiaryButtonsContainer } from './shared'
|
||||
import state, { useSelector } from 'state'
|
||||
import styled from 'styles'
|
||||
import Tooltip from '../tooltip'
|
||||
import tld from 'utils/tld'
|
||||
|
||||
const zoomIn = () => state.send('ZOOMED_IN')
|
||||
|
@ -12,21 +10,15 @@ const zoomToActual = () => state.send('ZOOMED_TO_ACTUAL')
|
|||
|
||||
export default function Zoom(): JSX.Element {
|
||||
return (
|
||||
<Container size={{ '@sm': 'small' }}>
|
||||
<Tooltip label="Zoom Out">
|
||||
<IconButton onClick={zoomOut}>
|
||||
<ZoomOutIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Zoom In">
|
||||
<IconButton onClick={zoomIn}>
|
||||
<ZoomInIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
<Tooltip label="Reset Zoom">
|
||||
<ZoomCounter />
|
||||
</Tooltip>
|
||||
</Container>
|
||||
<TertiaryButtonsContainer bp={{ '@initial': 'mobile', '@sm': 'small' }}>
|
||||
<TertiaryButton label="Zoom Out" onClick={zoomOut}>
|
||||
<ZoomOutIcon />
|
||||
</TertiaryButton>
|
||||
<TertiaryButton label="Zoom In" onClick={zoomIn}>
|
||||
<ZoomInIcon />
|
||||
</TertiaryButton>
|
||||
<ZoomCounter />
|
||||
</TertiaryButtonsContainer>
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -34,50 +26,12 @@ function ZoomCounter() {
|
|||
const zoom = useSelector((s) => tld.getCurrentCamera(s.data).zoom)
|
||||
|
||||
return (
|
||||
<ZoomButton
|
||||
<TertiaryButton
|
||||
label="Reset Zoom"
|
||||
onClick={zoomToActual}
|
||||
onDoubleClick={zoomToFit}
|
||||
style={{ width: '44px' }}
|
||||
>
|
||||
{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,
|
||||
} from 'state/hacks'
|
||||
import inputs from 'state/inputs'
|
||||
import { isMobile } from 'utils'
|
||||
import Vec from 'utils/vec'
|
||||
|
||||
function handleFocusOut() {
|
||||
state.send('BLURRED_EDITING_SHAPE')
|
||||
}
|
||||
|
||||
export default function useCanvasEvents(
|
||||
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
|
||||
useEffect(() => {
|
||||
function handleFocusOut() {
|
||||
state.send('BLURRED_EDITING_SHAPE')
|
||||
}
|
||||
if (isMobile()) {
|
||||
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 */
|
||||
import { useEffect } from 'react'
|
||||
import state from 'state'
|
||||
import coopState from 'state/coop/coop-state'
|
||||
// import coopState from 'state/coop/coop-state'
|
||||
|
||||
export default function useLoadOnMount(roomId?: string) {
|
||||
useEffect(() => {
|
||||
|
@ -21,7 +21,7 @@ export default function useLoadOnMount(roomId?: string) {
|
|||
|
||||
return () => {
|
||||
state.send('UNMOUNTED', { roomId })
|
||||
coopState.send('LEFT_ROOM', { id: roomId })
|
||||
// coopState.send('LEFT_ROOM', { id: 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',
|
||||
to: 'pinching.toolPinching',
|
||||
},
|
||||
TOGGLED_TOOL_LOCK: 'toggleToolLock',
|
||||
},
|
||||
states: {
|
||||
draw: {
|
||||
|
|
Loading…
Reference in a new issue