Adds double click to tool lock, replaces tool lock button with delete button (#266)
This commit is contained in:
parent
5a4c075894
commit
b3d0e7cceb
9 changed files with 78 additions and 26 deletions
|
@ -1,6 +1,7 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { breakpoints } from '~components/breakpoints'
|
import { breakpoints } from '~components/breakpoints'
|
||||||
import { Tooltip } from '~components/Tooltip'
|
import { Tooltip } from '~components/Tooltip'
|
||||||
|
import { useTLDrawContext } from '~hooks'
|
||||||
import { styled } from '~styles'
|
import { styled } from '~styles'
|
||||||
|
|
||||||
export interface ToolButtonProps {
|
export interface ToolButtonProps {
|
||||||
|
@ -39,9 +40,16 @@ interface ToolButtonWithTooltipProps extends ToolButtonProps {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ToolButtonWithTooltip({ label, kbd, ...rest }: ToolButtonWithTooltipProps) {
|
export function ToolButtonWithTooltip({ label, kbd, ...rest }: ToolButtonWithTooltipProps) {
|
||||||
|
const { state } = useTLDrawContext()
|
||||||
|
|
||||||
|
const handleDoubleClick = React.useCallback(() => {
|
||||||
|
console.log('double clicking')
|
||||||
|
state.toggleToolLock()
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Tooltip label={label[0].toUpperCase() + label.slice(1)} kbd={kbd}>
|
<Tooltip label={label[0].toUpperCase() + label.slice(1)} kbd={kbd}>
|
||||||
<ToolButton variant="primary" {...rest} />
|
<ToolButton {...rest} variant="primary" onDoubleClick={handleDoubleClick} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,10 @@ export function ActionButton(): JSX.Element {
|
||||||
<AspectRatioIcon opacity={isAllAspectLocked ? 1 : 0.4} />
|
<AspectRatioIcon opacity={isAllAspectLocked ? 1 : 0.4} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<IconButton disabled={!isAllGrouped && !hasMultipleSelection} onClick={handleGroup}>
|
<IconButton
|
||||||
|
disabled={!hasSelection || (!isAllGrouped && !hasMultipleSelection)}
|
||||||
|
onClick={handleGroup}
|
||||||
|
>
|
||||||
<Tooltip label="Group" kbd={`#G`}>
|
<Tooltip label="Group" kbd={`#G`}>
|
||||||
<GroupIcon opacity={isAllGrouped ? 1 : 0.4} />
|
<GroupIcon opacity={isAllGrouped ? 1 : 0.4} />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@ -212,7 +215,6 @@ export function ActionButton(): JSX.Element {
|
||||||
<PinBottomIcon />
|
<PinBottomIcon />
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|
||||||
<IconButton disabled={!hasSelection} onClick={handleMoveBackward}>
|
<IconButton disabled={!hasSelection} onClick={handleMoveBackward}>
|
||||||
<Tooltip label="Move Backward" kbd={`#[`}>
|
<Tooltip label="Move Backward" kbd={`#[`}>
|
||||||
<ArrowDownIcon />
|
<ArrowDownIcon />
|
||||||
|
|
21
packages/tldraw/src/components/ToolsPanel/DeleteButton.tsx
Normal file
21
packages/tldraw/src/components/ToolsPanel/DeleteButton.tsx
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
import { Tooltip } from '~components/Tooltip'
|
||||||
|
import { useTLDrawContext } from '~hooks'
|
||||||
|
import { ToolButton } from '~components/ToolButton'
|
||||||
|
import { TrashIcon } from '~components/icons'
|
||||||
|
|
||||||
|
export function DeleteButton(): JSX.Element {
|
||||||
|
const { state } = useTLDrawContext()
|
||||||
|
|
||||||
|
const handleDelete = React.useCallback(() => {
|
||||||
|
state.delete()
|
||||||
|
}, [state])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Tooltip label="Delete" kbd="7">
|
||||||
|
<ToolButton variant="circle" onSelect={handleDelete}>
|
||||||
|
<TrashIcon />
|
||||||
|
</ToolButton>
|
||||||
|
</Tooltip>
|
||||||
|
)
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import { BackToContent } from './BackToContent'
|
||||||
import { PrimaryTools } from './PrimaryTools'
|
import { PrimaryTools } from './PrimaryTools'
|
||||||
import { ActionButton } from './ActionButton'
|
import { ActionButton } from './ActionButton'
|
||||||
import { LockButton } from './LockButton'
|
import { LockButton } from './LockButton'
|
||||||
|
import { DeleteButton } from './DeleteButton'
|
||||||
|
|
||||||
const isDebugModeSelector = (s: TLDrawSnapshot) => s.settings.isDebugMode
|
const isDebugModeSelector = (s: TLDrawSnapshot) => s.settings.isDebugMode
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ export const ToolsPanel = React.memo(function ToolsPanel(): JSX.Element {
|
||||||
<StyledPrimaryTools>
|
<StyledPrimaryTools>
|
||||||
<ActionButton />
|
<ActionButton />
|
||||||
<PrimaryTools />
|
<PrimaryTools />
|
||||||
<LockButton />
|
<DeleteButton />
|
||||||
</StyledPrimaryTools>
|
</StyledPrimaryTools>
|
||||||
</StyledCenterWrap>
|
</StyledCenterWrap>
|
||||||
{isDebugMode && (
|
{isDebugMode && (
|
||||||
|
|
|
@ -38,6 +38,7 @@ import {
|
||||||
SessionType,
|
SessionType,
|
||||||
ExceptFirst,
|
ExceptFirst,
|
||||||
ExceptFirstTwo,
|
ExceptFirstTwo,
|
||||||
|
TLDrawToolType,
|
||||||
} from '~types'
|
} from '~types'
|
||||||
import {
|
import {
|
||||||
migrate,
|
migrate,
|
||||||
|
@ -51,7 +52,7 @@ import { shapeUtils } from '~state/shapes'
|
||||||
import { defaultStyle } from '~state/shapes/shape-styles'
|
import { defaultStyle } from '~state/shapes/shape-styles'
|
||||||
import * as Commands from './commands'
|
import * as Commands from './commands'
|
||||||
import { ArgsOfType, getSession } from './sessions'
|
import { ArgsOfType, getSession } from './sessions'
|
||||||
import { createTools, ToolType } from './tools'
|
import { createTools } from './tools'
|
||||||
import type { BaseTool } from './tools/BaseTool'
|
import type { BaseTool } from './tools/BaseTool'
|
||||||
import { USER_COLORS, FIT_TO_SCREEN_PADDING } from '~constants'
|
import { USER_COLORS, FIT_TO_SCREEN_PADDING } from '~constants'
|
||||||
|
|
||||||
|
@ -642,12 +643,21 @@ export class TLDrawState extends StateManager<TLDrawSnapshot> {
|
||||||
* Select a tool.
|
* Select a tool.
|
||||||
* @param tool The tool to select, or "select".
|
* @param tool The tool to select, or "select".
|
||||||
*/
|
*/
|
||||||
selectTool = (type: ToolType): this => {
|
selectTool = (type: TLDrawToolType): this => {
|
||||||
if (this.readOnly || this.session) return this
|
if (this.readOnly || this.session) return this
|
||||||
|
|
||||||
const tool = this.tools[type]
|
const tool = this.tools[type]
|
||||||
|
|
||||||
if (tool === this.currentTool) return this
|
if (tool === this.currentTool) {
|
||||||
|
console.log('hi')
|
||||||
|
|
||||||
|
this.patchState({
|
||||||
|
appState: {
|
||||||
|
isToolLocked: false,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
this.currentTool.onExit()
|
this.currentTool.onExit()
|
||||||
|
|
||||||
|
@ -659,6 +669,7 @@ export class TLDrawState extends StateManager<TLDrawSnapshot> {
|
||||||
{
|
{
|
||||||
appState: {
|
appState: {
|
||||||
activeTool: type,
|
activeTool: type,
|
||||||
|
isToolLocked: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
`selected_tool:${type}`
|
`selected_tool:${type}`
|
||||||
|
|
|
@ -12,7 +12,6 @@ import {
|
||||||
Utils,
|
Utils,
|
||||||
} from '@tldraw/core'
|
} from '@tldraw/core'
|
||||||
import type { TLDrawState } from '~state'
|
import type { TLDrawState } from '~state'
|
||||||
import type { TLDrawShapeType } from '~types'
|
|
||||||
|
|
||||||
export enum Status {
|
export enum Status {
|
||||||
Idle = 'idle',
|
Idle = 'idle',
|
||||||
|
@ -22,8 +21,6 @@ export enum Status {
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
export abstract class BaseTool<T extends string = any> {
|
export abstract class BaseTool<T extends string = any> {
|
||||||
abstract type: TLDrawShapeType | 'select'
|
|
||||||
|
|
||||||
state: TLDrawState
|
state: TLDrawState
|
||||||
|
|
||||||
status: Status | T = Status.Idle
|
status: Status | T = Status.Idle
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import type { TLDrawState } from '~state'
|
import type { TLDrawState } from '~state'
|
||||||
import { TLDrawShapeType } from '~types'
|
import { TLDrawShapeType, TLDrawToolType } from '~types'
|
||||||
|
import type { BaseTool } from './BaseTool'
|
||||||
import { ArrowTool } from './ArrowTool'
|
import { ArrowTool } from './ArrowTool'
|
||||||
import { DrawTool } from './DrawTool'
|
import { DrawTool } from './DrawTool'
|
||||||
import { EllipseTool } from './EllipseTool'
|
import { EllipseTool } from './EllipseTool'
|
||||||
|
@ -8,15 +9,6 @@ import { SelectTool } from './SelectTool'
|
||||||
import { StickyTool } from './StickyTool'
|
import { StickyTool } from './StickyTool'
|
||||||
import { TextTool } from './TextTool'
|
import { TextTool } from './TextTool'
|
||||||
|
|
||||||
export type ToolType =
|
|
||||||
| 'select'
|
|
||||||
| TLDrawShapeType.Text
|
|
||||||
| TLDrawShapeType.Draw
|
|
||||||
| TLDrawShapeType.Ellipse
|
|
||||||
| TLDrawShapeType.Rectangle
|
|
||||||
| TLDrawShapeType.Arrow
|
|
||||||
| TLDrawShapeType.Sticky
|
|
||||||
|
|
||||||
export interface ToolsMap {
|
export interface ToolsMap {
|
||||||
select: typeof SelectTool
|
select: typeof SelectTool
|
||||||
[TLDrawShapeType.Text]: typeof TextTool
|
[TLDrawShapeType.Text]: typeof TextTool
|
||||||
|
@ -27,11 +19,11 @@ export interface ToolsMap {
|
||||||
[TLDrawShapeType.Sticky]: typeof StickyTool
|
[TLDrawShapeType.Sticky]: typeof StickyTool
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ToolOfType<K extends ToolType> = ToolsMap[K]
|
export type ToolOfType<K extends TLDrawToolType> = ToolsMap[K]
|
||||||
|
|
||||||
export type ArgsOfType<K extends ToolType> = ConstructorParameters<ToolOfType<K>>
|
export type ArgsOfType<K extends TLDrawToolType> = ConstructorParameters<ToolOfType<K>>
|
||||||
|
|
||||||
export const tools: { [K in ToolType]: ToolsMap[K] } = {
|
export const tools: { [K in TLDrawToolType]: ToolsMap[K] } = {
|
||||||
select: SelectTool,
|
select: SelectTool,
|
||||||
[TLDrawShapeType.Text]: TextTool,
|
[TLDrawShapeType.Text]: TextTool,
|
||||||
[TLDrawShapeType.Draw]: DrawTool,
|
[TLDrawShapeType.Draw]: DrawTool,
|
||||||
|
@ -41,11 +33,11 @@ export const tools: { [K in ToolType]: ToolsMap[K] } = {
|
||||||
[TLDrawShapeType.Sticky]: StickyTool,
|
[TLDrawShapeType.Sticky]: StickyTool,
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getTool = <K extends ToolType>(type: K): ToolOfType<K> => {
|
export const getTool = <K extends TLDrawToolType>(type: K): ToolOfType<K> => {
|
||||||
return tools[type]
|
return tools[type]
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createTools(state: TLDrawState) {
|
export function createTools(state: TLDrawState): Record<TLDrawToolType, BaseTool> {
|
||||||
return {
|
return {
|
||||||
select: new SelectTool(state),
|
select: new SelectTool(state),
|
||||||
[TLDrawShapeType.Text]: new TextTool(state),
|
[TLDrawShapeType.Text]: new TextTool(state),
|
||||||
|
|
|
@ -401,6 +401,15 @@ export type Easing =
|
||||||
| 'easeOutExpo'
|
| 'easeOutExpo'
|
||||||
| 'easeInOutExpo'
|
| 'easeInOutExpo'
|
||||||
|
|
||||||
|
export type TLDrawToolType =
|
||||||
|
| 'select'
|
||||||
|
| TLDrawShapeType.Text
|
||||||
|
| TLDrawShapeType.Draw
|
||||||
|
| TLDrawShapeType.Ellipse
|
||||||
|
| TLDrawShapeType.Rectangle
|
||||||
|
| TLDrawShapeType.Arrow
|
||||||
|
| TLDrawShapeType.Sticky
|
||||||
|
|
||||||
/* ------------------- File System ------------------ */
|
/* ------------------- File System ------------------ */
|
||||||
|
|
||||||
export interface TLDrawFile {
|
export interface TLDrawFile {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { TLDraw, TLDrawState, useFileSystem } from '@tldraw/tldraw'
|
import { TLDraw, TLDrawState, useFileSystem } from '@tldraw/tldraw'
|
||||||
|
import { signIn, signOut } from 'next-auth/client'
|
||||||
import * as gtag from '-utils/gtag'
|
import * as gtag from '-utils/gtag'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
@ -26,13 +27,23 @@ export default function Editor({ id = 'home' }: EditorProps) {
|
||||||
|
|
||||||
const fileSystemEvents = useFileSystem()
|
const fileSystemEvents = useFileSystem()
|
||||||
|
|
||||||
|
const handleSignIn = React.useCallback(() => {
|
||||||
|
signIn()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const handleSignOut = React.useCallback(() => {
|
||||||
|
signOut()
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="tldraw">
|
<div className="tldraw">
|
||||||
<TLDraw
|
<TLDraw
|
||||||
id={id}
|
id={id}
|
||||||
|
autofocus
|
||||||
onMount={handleMount}
|
onMount={handleMount}
|
||||||
onPersist={handlePersist}
|
onPersist={handlePersist}
|
||||||
autofocus
|
onSignIn={handleSignIn}
|
||||||
|
onSignOut={handleSignOut}
|
||||||
{...fileSystemEvents}
|
{...fileSystemEvents}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in a new issue