[feature] Added LineTool functionality (#343)
* Added LineTool functionality * Fix Typo error * Create LineIcon * Update useKeyboardShortcuts.tsx Co-authored-by: Steve Ruiz <steveruizok@gmail.com>
This commit is contained in:
parent
588a023e0e
commit
dad6daf758
11 changed files with 82 additions and 7 deletions
|
@ -0,0 +1,9 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
|
||||||
|
export function LineIcon() {
|
||||||
|
return (
|
||||||
|
<svg width="15" height="15" viewBox="0 0 15 15" fill="black" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M3.64645 11.3536C3.45118 11.1583 3.45118 10.8417 3.64645 10.6465L11.1464 3.14645C11.3417 2.95118 11.6583 2.95118 11.8536 3.14645C12.0488 3.34171 12.0488 3.65829 11.8536 3.85355L4.35355 11.3536C4.15829 11.5488 3.84171 11.5488 3.64645 11.3536Z" />
|
||||||
|
</svg>
|
||||||
|
)
|
||||||
|
}
|
|
@ -14,3 +14,4 @@ export * from './SizeLargeIcon'
|
||||||
export * from './EraserIcon'
|
export * from './EraserIcon'
|
||||||
export * from './MultiplayerIcon'
|
export * from './MultiplayerIcon'
|
||||||
export * from './DiscordIcon'
|
export * from './DiscordIcon'
|
||||||
|
export * from './LineIcon'
|
||||||
|
|
|
@ -75,7 +75,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
<ShapesMenu activeTool={activeTool} isToolLocked={isToolLocked} />
|
<ShapesMenu activeTool={activeTool} isToolLocked={isToolLocked} />
|
||||||
<ToolButtonWithTooltip
|
<ToolButtonWithTooltip
|
||||||
kbd={'6'}
|
kbd={'7'}
|
||||||
label={TDShapeType.Arrow}
|
label={TDShapeType.Arrow}
|
||||||
onClick={selectArrowTool}
|
onClick={selectArrowTool}
|
||||||
isLocked={isToolLocked}
|
isLocked={isToolLocked}
|
||||||
|
@ -84,7 +84,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
<ArrowTopRightIcon />
|
<ArrowTopRightIcon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
<ToolButtonWithTooltip
|
<ToolButtonWithTooltip
|
||||||
kbd={'7'}
|
kbd={'8'}
|
||||||
label={TDShapeType.Text}
|
label={TDShapeType.Text}
|
||||||
onClick={selectTextTool}
|
onClick={selectTextTool}
|
||||||
isLocked={isToolLocked}
|
isLocked={isToolLocked}
|
||||||
|
@ -93,7 +93,7 @@ export const PrimaryTools = React.memo(function PrimaryTools(): JSX.Element {
|
||||||
<TextIcon />
|
<TextIcon />
|
||||||
</ToolButtonWithTooltip>
|
</ToolButtonWithTooltip>
|
||||||
<ToolButtonWithTooltip
|
<ToolButtonWithTooltip
|
||||||
kbd={'8'}
|
kbd={'9'}
|
||||||
label={TDShapeType.Sticky}
|
label={TDShapeType.Sticky}
|
||||||
onClick={selectStickyTool}
|
onClick={selectStickyTool}
|
||||||
isActive={activeTool === TDShapeType.Sticky}
|
isActive={activeTool === TDShapeType.Sticky}
|
||||||
|
|
|
@ -6,17 +6,19 @@ import { TDShapeType, TDToolType } from '~types'
|
||||||
import { useTldrawApp } from '~hooks'
|
import { useTldrawApp } from '~hooks'
|
||||||
import { SquareIcon, CircleIcon } from '@radix-ui/react-icons'
|
import { SquareIcon, CircleIcon } from '@radix-ui/react-icons'
|
||||||
import { Tooltip } from '~components/Primitives/Tooltip'
|
import { Tooltip } from '~components/Primitives/Tooltip'
|
||||||
|
import { LineIcon } from '~components/Primitives/icons'
|
||||||
|
|
||||||
interface ShapesMenuProps {
|
interface ShapesMenuProps {
|
||||||
activeTool: TDToolType
|
activeTool: TDToolType
|
||||||
isToolLocked: boolean
|
isToolLocked: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShapeShape = TDShapeType.Rectangle | TDShapeType.Ellipse
|
type ShapeShape = TDShapeType.Rectangle | TDShapeType.Ellipse | TDShapeType.Line
|
||||||
const shapeShapes: ShapeShape[] = [TDShapeType.Rectangle, TDShapeType.Ellipse]
|
const shapeShapes: ShapeShape[] = [TDShapeType.Rectangle, TDShapeType.Ellipse, TDShapeType.Line]
|
||||||
const shapeShapeIcons = {
|
const shapeShapeIcons = {
|
||||||
[TDShapeType.Rectangle]: <SquareIcon />,
|
[TDShapeType.Rectangle]: <SquareIcon />,
|
||||||
[TDShapeType.Ellipse]: <CircleIcon />,
|
[TDShapeType.Ellipse]: <CircleIcon />,
|
||||||
|
[TDShapeType.Line]: <LineIcon />,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const ShapesMenu = React.memo(function ShapesMenu({
|
export const ShapesMenu = React.memo(function ShapesMenu({
|
||||||
|
|
|
@ -66,7 +66,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
'a,6',
|
'a,6',
|
||||||
() => {
|
() => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
app.selectTool(TDShapeType.Arrow)
|
app.selectTool(TDShapeType.Line)
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
[app]
|
[app]
|
||||||
|
@ -76,7 +76,7 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
't,7',
|
't,7',
|
||||||
() => {
|
() => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
app.selectTool(TDShapeType.Text)
|
app.selectTool(TDShapeType.Arrow)
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
[app]
|
[app]
|
||||||
|
@ -84,6 +84,16 @@ export function useKeyboardShortcuts(ref: React.RefObject<HTMLDivElement>) {
|
||||||
|
|
||||||
useHotkeys(
|
useHotkeys(
|
||||||
'n,8',
|
'n,8',
|
||||||
|
() => {
|
||||||
|
if (!canHandleEvent()) return
|
||||||
|
app.selectTool(TDShapeType.Text)
|
||||||
|
},
|
||||||
|
undefined,
|
||||||
|
[app]
|
||||||
|
)
|
||||||
|
|
||||||
|
useHotkeys(
|
||||||
|
'n,9',
|
||||||
() => {
|
() => {
|
||||||
if (!canHandleEvent()) return
|
if (!canHandleEvent()) return
|
||||||
app.selectTool(TDShapeType.Sticky)
|
app.selectTool(TDShapeType.Sticky)
|
||||||
|
|
|
@ -56,6 +56,7 @@ import { TextTool } from './tools/TextTool'
|
||||||
import { DrawTool } from './tools/DrawTool'
|
import { DrawTool } from './tools/DrawTool'
|
||||||
import { EllipseTool } from './tools/EllipseTool'
|
import { EllipseTool } from './tools/EllipseTool'
|
||||||
import { RectangleTool } from './tools/RectangleTool'
|
import { RectangleTool } from './tools/RectangleTool'
|
||||||
|
import { LineTool } from './tools/LineTool'
|
||||||
import { ArrowTool } from './tools/ArrowTool'
|
import { ArrowTool } from './tools/ArrowTool'
|
||||||
import { StickyTool } from './tools/StickyTool'
|
import { StickyTool } from './tools/StickyTool'
|
||||||
|
|
||||||
|
@ -130,6 +131,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
|
||||||
[TDShapeType.Draw]: new DrawTool(this),
|
[TDShapeType.Draw]: new DrawTool(this),
|
||||||
[TDShapeType.Ellipse]: new EllipseTool(this),
|
[TDShapeType.Ellipse]: new EllipseTool(this),
|
||||||
[TDShapeType.Rectangle]: new RectangleTool(this),
|
[TDShapeType.Rectangle]: new RectangleTool(this),
|
||||||
|
[TDShapeType.Line]: new LineTool(this),
|
||||||
[TDShapeType.Arrow]: new ArrowTool(this),
|
[TDShapeType.Arrow]: new ArrowTool(this),
|
||||||
[TDShapeType.Sticky]: new StickyTool(this),
|
[TDShapeType.Sticky]: new StickyTool(this),
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { TldrawApp } from '~state'
|
||||||
|
import { LineTool } from '.'
|
||||||
|
|
||||||
|
describe('LineTool', () => {
|
||||||
|
it('creates tool', () => {
|
||||||
|
const app = new TldrawApp()
|
||||||
|
new LineTool(app)
|
||||||
|
})
|
||||||
|
})
|
36
packages/tldraw/src/state/tools/LineTool/LineTool.ts
Normal file
36
packages/tldraw/src/state/tools/LineTool/LineTool.ts
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
import { Utils, TLPointerEventHandler } from '@tldraw/core'
|
||||||
|
import { Arrow } from '~state/shapes'
|
||||||
|
import { SessionType, TDShapeType } from '~types'
|
||||||
|
import { BaseTool, Status } from '../BaseTool'
|
||||||
|
|
||||||
|
export class LineTool extends BaseTool {
|
||||||
|
type = TDShapeType.Line as const
|
||||||
|
|
||||||
|
/* ----------------- Event Handlers ----------------- */
|
||||||
|
|
||||||
|
onPointerDown: TLPointerEventHandler = () => {
|
||||||
|
const {
|
||||||
|
currentPoint,
|
||||||
|
appState: { currentPageId, currentStyle },
|
||||||
|
} = this.app
|
||||||
|
|
||||||
|
const childIndex = this.getNextChildIndex()
|
||||||
|
|
||||||
|
const id = Utils.uniqueId()
|
||||||
|
|
||||||
|
const newShape = Arrow.create({
|
||||||
|
id,
|
||||||
|
parentId: currentPageId,
|
||||||
|
childIndex,
|
||||||
|
point: currentPoint,
|
||||||
|
decorations: undefined,
|
||||||
|
style: { ...currentStyle },
|
||||||
|
})
|
||||||
|
|
||||||
|
this.app.patchCreate([newShape])
|
||||||
|
|
||||||
|
this.app.startSession(SessionType.Arrow, newShape.id, 'end', true)
|
||||||
|
|
||||||
|
this.setStatus(Status.Creating)
|
||||||
|
}
|
||||||
|
}
|
1
packages/tldraw/src/state/tools/LineTool/index.ts
Normal file
1
packages/tldraw/src/state/tools/LineTool/index.ts
Normal file
|
@ -0,0 +1 @@
|
||||||
|
export * from './LineTool'
|
|
@ -1,5 +1,6 @@
|
||||||
import { TDShapeType, TDToolType } from '~types'
|
import { TDShapeType, TDToolType } from '~types'
|
||||||
import { ArrowTool } from './ArrowTool'
|
import { ArrowTool } from './ArrowTool'
|
||||||
|
import { LineTool } from './LineTool'
|
||||||
import { DrawTool } from './DrawTool'
|
import { DrawTool } from './DrawTool'
|
||||||
import { EllipseTool } from './EllipseTool'
|
import { EllipseTool } from './EllipseTool'
|
||||||
import { RectangleTool } from './RectangleTool'
|
import { RectangleTool } from './RectangleTool'
|
||||||
|
@ -15,6 +16,7 @@ export interface ToolsMap {
|
||||||
[TDShapeType.Draw]: typeof DrawTool
|
[TDShapeType.Draw]: typeof DrawTool
|
||||||
[TDShapeType.Ellipse]: typeof EllipseTool
|
[TDShapeType.Ellipse]: typeof EllipseTool
|
||||||
[TDShapeType.Rectangle]: typeof RectangleTool
|
[TDShapeType.Rectangle]: typeof RectangleTool
|
||||||
|
[TDShapeType.Line]: typeof LineTool
|
||||||
[TDShapeType.Arrow]: typeof ArrowTool
|
[TDShapeType.Arrow]: typeof ArrowTool
|
||||||
[TDShapeType.Sticky]: typeof StickyTool
|
[TDShapeType.Sticky]: typeof StickyTool
|
||||||
}
|
}
|
||||||
|
@ -30,6 +32,7 @@ export const tools: { [K in TDToolType]: ToolsMap[K] } = {
|
||||||
[TDShapeType.Draw]: DrawTool,
|
[TDShapeType.Draw]: DrawTool,
|
||||||
[TDShapeType.Ellipse]: EllipseTool,
|
[TDShapeType.Ellipse]: EllipseTool,
|
||||||
[TDShapeType.Rectangle]: RectangleTool,
|
[TDShapeType.Rectangle]: RectangleTool,
|
||||||
|
[TDShapeType.Line]: LineTool,
|
||||||
[TDShapeType.Arrow]: ArrowTool,
|
[TDShapeType.Arrow]: ArrowTool,
|
||||||
[TDShapeType.Sticky]: StickyTool,
|
[TDShapeType.Sticky]: StickyTool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -205,6 +205,7 @@ export type TDToolType =
|
||||||
| TDShapeType.Draw
|
| TDShapeType.Draw
|
||||||
| TDShapeType.Ellipse
|
| TDShapeType.Ellipse
|
||||||
| TDShapeType.Rectangle
|
| TDShapeType.Rectangle
|
||||||
|
| TDShapeType.Line
|
||||||
| TDShapeType.Arrow
|
| TDShapeType.Arrow
|
||||||
| TDShapeType.Sticky
|
| TDShapeType.Sticky
|
||||||
|
|
||||||
|
@ -270,6 +271,7 @@ export enum TDShapeType {
|
||||||
Rectangle = 'rectangle',
|
Rectangle = 'rectangle',
|
||||||
Draw = 'draw',
|
Draw = 'draw',
|
||||||
Arrow = 'arrow',
|
Arrow = 'arrow',
|
||||||
|
Line = 'line',
|
||||||
Text = 'text',
|
Text = 'text',
|
||||||
Group = 'group',
|
Group = 'group',
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue