Merge pull request #48 from tldraw/tool-keyboard-shortcuts
Tool keyboard shortcuts
This commit is contained in:
commit
77403941f8
9 changed files with 190 additions and 99 deletions
|
@ -216,13 +216,12 @@ export const Item = styled('button', {
|
||||||
pointerEvents: 'all',
|
pointerEvents: 'all',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
|
|
||||||
|
'&:focus': {
|
||||||
|
backgroundColor: '$hover',
|
||||||
|
},
|
||||||
|
|
||||||
'&:hover:not(:disabled)': {
|
'&:hover:not(:disabled)': {
|
||||||
backgroundColor: '$hover',
|
backgroundColor: '$hover',
|
||||||
'& svg': {
|
|
||||||
stroke: '$text',
|
|
||||||
fill: '$text',
|
|
||||||
strokeWidth: '0',
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
'&:disabled': {
|
'&:disabled': {
|
||||||
|
@ -247,6 +246,16 @@ export const Item = styled('button', {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
export const ShortcutKey = styled('span', {
|
||||||
|
fontSize: '$0',
|
||||||
|
width: '16px',
|
||||||
|
height: '16px',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
boxShadow: '1px 1px 0px rgba(0,0,0,.5)',
|
||||||
|
})
|
||||||
|
|
||||||
export const IconWrapper = styled('div', {
|
export const IconWrapper = styled('div', {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
borderRadius: '4px',
|
borderRadius: '4px',
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
import { IconButton } from 'components/shared'
|
|
||||||
import { strokes } from 'state/shape-styles'
|
|
||||||
import { ColorStyle } from 'types'
|
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
|
||||||
import { Square } from 'react-feather'
|
|
||||||
import { DropdownContent } from '../shared'
|
|
||||||
import { memo } from 'react'
|
|
||||||
import state from 'state'
|
|
||||||
import useTheme from 'hooks/useTheme'
|
|
||||||
|
|
||||||
function handleColorChange(
|
|
||||||
e: Event & { currentTarget: { value: ColorStyle } }
|
|
||||||
): void {
|
|
||||||
state.send('CHANGED_STYLE', { color: e.currentTarget.value })
|
|
||||||
}
|
|
||||||
|
|
||||||
function ColorContent(): JSX.Element {
|
|
||||||
const { theme } = useTheme()
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DropdownContent sideOffset={8} side="bottom">
|
|
||||||
{Object.keys(strokes[theme]).map((color: ColorStyle) => (
|
|
||||||
<DropdownMenu.DropdownMenuItem
|
|
||||||
as={IconButton}
|
|
||||||
key={color}
|
|
||||||
title={color}
|
|
||||||
value={color}
|
|
||||||
onSelect={handleColorChange}
|
|
||||||
>
|
|
||||||
<Square fill={strokes[theme][color]} stroke="none" size="22" />
|
|
||||||
</DropdownMenu.DropdownMenuItem>
|
|
||||||
))}
|
|
||||||
</DropdownContent>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default memo(ColorContent)
|
|
|
@ -1,11 +1,15 @@
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||||
import { breakpoints, IconButton } from 'components/shared'
|
import { breakpoints, IconButton } from 'components/shared'
|
||||||
import Tooltip from 'components/tooltip'
|
import Tooltip from 'components/tooltip'
|
||||||
import { fills, strokes } from 'state/shape-styles'
|
import { strokes } from 'state/shape-styles'
|
||||||
import { useSelector } from 'state'
|
import state, { useSelector } from 'state'
|
||||||
import ColorContent from './color-content'
|
import { BoxIcon, Item, DropdownContent } from '../shared'
|
||||||
import { BoxIcon } from '../shared'
|
|
||||||
import useTheme from 'hooks/useTheme'
|
import useTheme from 'hooks/useTheme'
|
||||||
|
import { ColorStyle } from 'types'
|
||||||
|
|
||||||
|
function handleColorChange(color: ColorStyle): void {
|
||||||
|
state.send('CHANGED_STYLE', { color })
|
||||||
|
}
|
||||||
|
|
||||||
export default function QuickColorSelect(): JSX.Element {
|
export default function QuickColorSelect(): JSX.Element {
|
||||||
const color = useSelector((s) => s.values.selectedStyle.color)
|
const color = useSelector((s) => s.values.selectedStyle.color)
|
||||||
|
@ -15,10 +19,33 @@ export default function QuickColorSelect(): JSX.Element {
|
||||||
<DropdownMenu.Root dir="ltr">
|
<DropdownMenu.Root dir="ltr">
|
||||||
<DropdownMenu.Trigger as={IconButton} bp={breakpoints}>
|
<DropdownMenu.Trigger as={IconButton} bp={breakpoints}>
|
||||||
<Tooltip label="Color">
|
<Tooltip label="Color">
|
||||||
<BoxIcon fill={fills[theme][color]} stroke={strokes[theme][color]} />
|
<BoxIcon
|
||||||
|
fill={strokes[theme][color]}
|
||||||
|
stroke={strokes[theme][color]}
|
||||||
|
/>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<ColorContent />
|
|
||||||
|
<DropdownMenu.DropdownMenuRadioGroup
|
||||||
|
value={color}
|
||||||
|
as={DropdownContent}
|
||||||
|
onValueChange={handleColorChange}
|
||||||
|
sideOffset={8}
|
||||||
|
>
|
||||||
|
{Object.keys(strokes[theme]).map((colorStyle: ColorStyle) => (
|
||||||
|
<DropdownMenu.DropdownMenuRadioItem
|
||||||
|
as={Item}
|
||||||
|
key={colorStyle}
|
||||||
|
title={colorStyle}
|
||||||
|
value={colorStyle}
|
||||||
|
>
|
||||||
|
<BoxIcon
|
||||||
|
fill={strokes[theme][colorStyle]}
|
||||||
|
stroke={strokes[theme][colorStyle]}
|
||||||
|
/>
|
||||||
|
</DropdownMenu.DropdownMenuRadioItem>
|
||||||
|
))}
|
||||||
|
</DropdownMenu.DropdownMenuRadioGroup>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
import * as DropdownMenu from '@radix-ui/react-dropdown-menu'
|
||||||
import { breakpoints, IconButton } from 'components/shared'
|
import { breakpoints, IconButton } from 'components/shared'
|
||||||
import Tooltip from 'components/tooltip'
|
import Tooltip from 'components/tooltip'
|
||||||
import { memo } from 'react'
|
import React, { memo } from 'react'
|
||||||
import state, { useSelector } from 'state'
|
import state, { useSelector } from 'state'
|
||||||
import { DashStyle } from 'types'
|
import { DashStyle } from 'types'
|
||||||
import {
|
import {
|
||||||
|
@ -20,10 +20,8 @@ const dashes = {
|
||||||
[DashStyle.Dotted]: <DashDottedIcon />,
|
[DashStyle.Dotted]: <DashDottedIcon />,
|
||||||
}
|
}
|
||||||
|
|
||||||
function changeDashStyle(
|
function changeDashStyle(dash: DashStyle): void {
|
||||||
e: Event & { currentTarget: { value: DashStyle } }
|
state.send('CHANGED_STYLE', { dash })
|
||||||
): void {
|
|
||||||
state.send('CHANGED_STYLE', { dash: e.currentTarget.value })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function QuickdashSelect(): JSX.Element {
|
function QuickdashSelect(): JSX.Element {
|
||||||
|
@ -34,19 +32,24 @@ function QuickdashSelect(): JSX.Element {
|
||||||
<DropdownMenu.Trigger as={IconButton} bp={breakpoints}>
|
<DropdownMenu.Trigger as={IconButton} bp={breakpoints}>
|
||||||
<Tooltip label="Dash">{dashes[dash]}</Tooltip>
|
<Tooltip label="Dash">{dashes[dash]}</Tooltip>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownContent sideOffset={8} direction="vertical">
|
<DropdownMenu.DropdownMenuRadioGroup
|
||||||
|
as={DropdownContent}
|
||||||
|
sideOffset={8}
|
||||||
|
direction="vertical"
|
||||||
|
value={dash}
|
||||||
|
onValueChange={changeDashStyle}
|
||||||
|
>
|
||||||
{Object.keys(DashStyle).map((dashStyle: DashStyle) => (
|
{Object.keys(DashStyle).map((dashStyle: DashStyle) => (
|
||||||
<DropdownMenu.DropdownMenuItem
|
<DropdownMenu.DropdownMenuRadioItem
|
||||||
as={Item}
|
as={Item}
|
||||||
key={dashStyle}
|
key={dashStyle}
|
||||||
isActive={dash === dashStyle}
|
isActive={dash === dashStyle}
|
||||||
onSelect={changeDashStyle}
|
|
||||||
value={dashStyle}
|
value={dashStyle}
|
||||||
>
|
>
|
||||||
{dashes[dashStyle]}
|
{dashes[dashStyle]}
|
||||||
</DropdownMenu.DropdownMenuItem>
|
</DropdownMenu.DropdownMenuRadioItem>
|
||||||
))}
|
))}
|
||||||
</DropdownContent>
|
</DropdownMenu.DropdownMenuRadioGroup>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,10 +13,8 @@ const sizes = {
|
||||||
[SizeStyle.Large]: 22,
|
[SizeStyle.Large]: 22,
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSizeChange(
|
function changeSizeStyle(size: SizeStyle): void {
|
||||||
e: Event & { currentTarget: { value: SizeStyle } }
|
state.send('CHANGED_STYLE', { size })
|
||||||
): void {
|
|
||||||
state.send('CHANGED_STYLE', { size: e.currentTarget.value })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function QuickSizeSelect(): JSX.Element {
|
function QuickSizeSelect(): JSX.Element {
|
||||||
|
@ -29,19 +27,24 @@ function QuickSizeSelect(): JSX.Element {
|
||||||
<Circle size={sizes[size]} stroke="none" fill="currentColor" />
|
<Circle size={sizes[size]} stroke="none" fill="currentColor" />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</DropdownMenu.Trigger>
|
</DropdownMenu.Trigger>
|
||||||
<DropdownContent sideOffset={8} direction="vertical">
|
<DropdownMenu.DropdownMenuRadioGroup
|
||||||
|
as={DropdownContent}
|
||||||
|
sideOffset={8}
|
||||||
|
direction="vertical"
|
||||||
|
value={size}
|
||||||
|
onValueChange={changeSizeStyle}
|
||||||
|
>
|
||||||
{Object.keys(SizeStyle).map((sizeStyle: SizeStyle) => (
|
{Object.keys(SizeStyle).map((sizeStyle: SizeStyle) => (
|
||||||
<DropdownMenu.DropdownMenuItem
|
<DropdownMenu.DropdownMenuRadioItem
|
||||||
key={sizeStyle}
|
key={sizeStyle}
|
||||||
as={Item}
|
as={Item}
|
||||||
isActive={size === sizeStyle}
|
isActive={size === sizeStyle}
|
||||||
value={sizeStyle}
|
value={sizeStyle}
|
||||||
onSelect={handleSizeChange}
|
|
||||||
>
|
>
|
||||||
<Circle size={sizes[sizeStyle]} />
|
<Circle size={sizes[sizeStyle]} />
|
||||||
</DropdownMenu.DropdownMenuItem>
|
</DropdownMenu.DropdownMenuRadioItem>
|
||||||
))}
|
))}
|
||||||
</DropdownContent>
|
</DropdownMenu.DropdownMenuRadioGroup>
|
||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,14 +2,17 @@
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import state from 'state'
|
import state from 'state'
|
||||||
import inputs from 'state/inputs'
|
import inputs from 'state/inputs'
|
||||||
import { MoveType } from 'types'
|
import { ColorStyle, MoveType, SizeStyle } from 'types'
|
||||||
import { metaKey } from 'utils'
|
import { metaKey } from 'utils'
|
||||||
|
|
||||||
export default function useKeyboardEvents() {
|
export default function useKeyboardEvents() {
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
function handleKeyDown(e: KeyboardEvent) {
|
function handleKeyDown(e: KeyboardEvent) {
|
||||||
|
const info = inputs.keydown(e)
|
||||||
|
const meta = metaKey(e)
|
||||||
|
|
||||||
if (
|
if (
|
||||||
metaKey(e) &&
|
meta &&
|
||||||
![
|
![
|
||||||
'a',
|
'a',
|
||||||
'i',
|
'i',
|
||||||
|
@ -25,9 +28,88 @@ export default function useKeyboardEvents() {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
}
|
}
|
||||||
|
|
||||||
const info = inputs.keydown(e)
|
|
||||||
|
|
||||||
switch (e.key) {
|
switch (e.key) {
|
||||||
|
case '1': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Black })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (e.altKey) {
|
||||||
|
state.send('CHANGED_STYLE', { size: SizeStyle.Small })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
state.send('SELECTED_SELECT_TOOL', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '2': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.White })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (e.altKey) {
|
||||||
|
state.send('CHANGED_STYLE', { size: SizeStyle.Medium })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
state.send('SELECTED_DRAW_TOOL', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '3': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Green })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if (e.altKey) {
|
||||||
|
state.send('CHANGED_STYLE', { size: SizeStyle.Large })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
state.send('SELECTED_RECTANGLE_TOOL', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '4': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Blue })
|
||||||
|
}
|
||||||
|
state.send('SELECTED_ELLIPSE_TOOL', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '5': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Indigo })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
state.send('SELECTED_ARROW_TOOL', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '6': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Violet })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
state.send('SELECTED_TEXT_TOOL', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '7': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Red })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
state.send('TOGGLED_TOOL_LOCK', info)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '8': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Orange })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case '9': {
|
||||||
|
if (meta) {
|
||||||
|
state.send('CHANGED_STYLE', { color: ColorStyle.Yellow })
|
||||||
|
break
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
case 'ArrowUp': {
|
case 'ArrowUp': {
|
||||||
state.send('NUDGED', { delta: [0, -1], ...info })
|
state.send('NUDGED', { delta: [0, -1], ...info })
|
||||||
break
|
break
|
||||||
|
@ -82,7 +164,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'z': {
|
case 'z': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
state.send('REDO', info)
|
state.send('REDO', info)
|
||||||
} else {
|
} else {
|
||||||
|
@ -92,7 +174,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case '‘': {
|
case '‘': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('MOVED', {
|
state.send('MOVED', {
|
||||||
...info,
|
...info,
|
||||||
type: MoveType.ToFront,
|
type: MoveType.ToFront,
|
||||||
|
@ -101,7 +183,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case '“': {
|
case '“': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('MOVED', {
|
state.send('MOVED', {
|
||||||
...info,
|
...info,
|
||||||
type: MoveType.ToBack,
|
type: MoveType.ToBack,
|
||||||
|
@ -110,7 +192,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case ']': {
|
case ']': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('MOVED', {
|
state.send('MOVED', {
|
||||||
...info,
|
...info,
|
||||||
type: MoveType.Forward,
|
type: MoveType.Forward,
|
||||||
|
@ -119,7 +201,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case '[': {
|
case '[': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('MOVED', {
|
state.send('MOVED', {
|
||||||
...info,
|
...info,
|
||||||
type: MoveType.Backward,
|
type: MoveType.Backward,
|
||||||
|
@ -136,7 +218,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'Backspace': {
|
case 'Backspace': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
if (window.confirm('Reset document and state?')) {
|
if (window.confirm('Reset document and state?')) {
|
||||||
state.send('RESET_DOCUMENT_STATE', info)
|
state.send('RESET_DOCUMENT_STATE', info)
|
||||||
|
@ -150,7 +232,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'g': {
|
case 'g': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
state.send('UNGROUPED', info)
|
state.send('UNGROUPED', info)
|
||||||
} else {
|
} else {
|
||||||
|
@ -160,7 +242,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 's': {
|
case 's': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
state.send('SAVED_AS_TO_FILESYSTEM', info)
|
state.send('SAVED_AS_TO_FILESYSTEM', info)
|
||||||
} else {
|
} else {
|
||||||
|
@ -170,7 +252,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'o': {
|
case 'o': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_DOT_TOOL', info)
|
state.send('SELECTED_DOT_TOOL', info)
|
||||||
|
@ -178,7 +260,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'v': {
|
case 'v': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('PASTED', info)
|
state.send('PASTED', info)
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_SELECT_TOOL', info)
|
state.send('SELECTED_SELECT_TOOL', info)
|
||||||
|
@ -186,7 +268,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'a': {
|
case 'a': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('SELECTED_ALL', info)
|
state.send('SELECTED_ALL', info)
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_ARROW_TOOL', info)
|
state.send('SELECTED_ARROW_TOOL', info)
|
||||||
|
@ -194,7 +276,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'd': {
|
case 'd': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
state.send('DUPLICATED', info)
|
state.send('DUPLICATED', info)
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_DRAW_TOOL', info)
|
state.send('SELECTED_DRAW_TOOL', info)
|
||||||
|
@ -206,7 +288,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'c': {
|
case 'c': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
state.send('COPIED_TO_SVG', info)
|
state.send('COPIED_TO_SVG', info)
|
||||||
} else {
|
} else {
|
||||||
|
@ -218,7 +300,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'i': {
|
case 'i': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_CIRCLE_TOOL', info)
|
state.send('SELECTED_CIRCLE_TOOL', info)
|
||||||
|
@ -226,7 +308,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'l': {
|
case 'l': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
if (e.shiftKey) {
|
if (e.shiftKey) {
|
||||||
state.send('TOGGLED_LOGGER')
|
state.send('TOGGLED_LOGGER')
|
||||||
} else {
|
} else {
|
||||||
|
@ -238,7 +320,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'y': {
|
case 'y': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_RAY_TOOL', info)
|
state.send('SELECTED_RAY_TOOL', info)
|
||||||
|
@ -246,7 +328,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'p': {
|
case 'p': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_POLYLINE_TOOL', info)
|
state.send('SELECTED_POLYLINE_TOOL', info)
|
||||||
|
@ -254,7 +336,7 @@ export default function useKeyboardEvents() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'r': {
|
case 'r': {
|
||||||
if (metaKey(e)) {
|
if (meta) {
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
state.send('SELECTED_RECTANGLE_TOOL', info)
|
state.send('SELECTED_RECTANGLE_TOOL', info)
|
||||||
|
|
|
@ -6,10 +6,10 @@ const canvasLight = '#fafafa'
|
||||||
const canvasDark = '#343d45'
|
const canvasDark = '#343d45'
|
||||||
|
|
||||||
const colors = {
|
const colors = {
|
||||||
|
[ColorStyle.Black]: '#212528',
|
||||||
[ColorStyle.White]: '#f0f1f3',
|
[ColorStyle.White]: '#f0f1f3',
|
||||||
[ColorStyle.LightGray]: '#c6cbd1',
|
[ColorStyle.LightGray]: '#c6cbd1',
|
||||||
[ColorStyle.Gray]: '#788492',
|
[ColorStyle.Gray]: '#788492',
|
||||||
[ColorStyle.Black]: '#212528',
|
|
||||||
[ColorStyle.Green]: '#36b24d',
|
[ColorStyle.Green]: '#36b24d',
|
||||||
[ColorStyle.Cyan]: '#0e98ad',
|
[ColorStyle.Cyan]: '#0e98ad',
|
||||||
[ColorStyle.Blue]: '#1c7ed6',
|
[ColorStyle.Blue]: '#1c7ed6',
|
||||||
|
|
|
@ -108,7 +108,7 @@ const dark = theme({
|
||||||
border: '#202529',
|
border: '#202529',
|
||||||
canvas: '#343d45',
|
canvas: '#343d45',
|
||||||
panel: '#49555f',
|
panel: '#49555f',
|
||||||
inactive: '#cccccf',
|
inactive: '#aaaaad',
|
||||||
hover: '#343d45',
|
hover: '#343d45',
|
||||||
text: '#f8f9fa',
|
text: '#f8f9fa',
|
||||||
muted: '#e0e2e6',
|
muted: '#e0e2e6',
|
||||||
|
|
|
@ -1586,17 +1586,21 @@ export function getFromCache<V, I extends object>(
|
||||||
return value
|
return value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const byteToHex = []
|
||||||
|
|
||||||
|
for (let i = 0; i < 256; ++i) {
|
||||||
|
byteToHex.push((i + 0x100).toString(16).substr(1))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a unique string id.
|
* Get a unique string id.
|
||||||
*/
|
*/
|
||||||
export function uniqueId(): string {
|
|
||||||
const array = new Uint32Array(8)
|
export function uniqueId(a = ''): string {
|
||||||
window.crypto.getRandomValues(array)
|
return a
|
||||||
let str = ''
|
? /* eslint-disable no-bitwise */
|
||||||
for (let i = 0; i < array.length; i++) {
|
((Number(a) ^ (Math.random() * 16)) >> (Number(a) / 4)).toString(16)
|
||||||
str += (i < 2 || i > 5 ? '' : '-') + array[i].toString(16).slice(-4)
|
: `${1e7}-${1e3}-${4e3}-${8e3}-${1e11}`.replace(/[018]/g, uniqueId)
|
||||||
}
|
|
||||||
return str
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue