mirror of https://github.com/logseq/logseq
chore: handle tool shortcuts
parent
23e250537f
commit
956211bb71
|
@ -78,7 +78,8 @@
|
|||
|
||||
(rum/defc keyboard-shortcut
|
||||
[props]
|
||||
[(ui/render-keyboard-shortcut (shortcut-helper/gen-shortcut-seq (keyword (gobj/get props "action"))))])
|
||||
(let [shortcut (shortcut-helper/gen-shortcut-seq (keyword (gobj/get props "action")))]
|
||||
(ui/render-keyboard-shortcut shortcut)))
|
||||
|
||||
(def tldraw-renderers {:Page page-cp
|
||||
:Block block-cp
|
||||
|
|
|
@ -71,6 +71,36 @@
|
|||
:pdf/find {:binding "alt+f"
|
||||
:fn pdf-utils/open-finder}
|
||||
|
||||
:whiteboard/select {:binding ["1" "s"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "select")}
|
||||
|
||||
:whiteboard/pan {:binding ["2" "p"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "move")}
|
||||
|
||||
:whiteboard/portal {:binding "3"
|
||||
:fn #(.selectTool (state/active-tldraw-app) "logseq-portal")}
|
||||
|
||||
:whiteboard/pencil {:binding ["4" "d"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "pencil")}
|
||||
|
||||
:whiteboard/highlighter {:binding ["5" "h"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "highlighter")}
|
||||
|
||||
:whiteboard/eraser {:binding ["6" "e"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "erase")}
|
||||
|
||||
:whiteboard/connector {:binding ["7" "c"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "line")}
|
||||
|
||||
:whiteboard/text {:binding ["8" "t"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "text")}
|
||||
|
||||
:whiteboard/rectangle {:binding ["9" "r"]
|
||||
:fn #(.selectTool (state/active-tldraw-app) "box")}
|
||||
|
||||
:whiteboard/ellipse {:binding "o"
|
||||
:fn #(.selectTool (state/active-tldraw-app) "ellipse")}
|
||||
|
||||
:whiteboard/reset-zoom {:binding "shift+0"
|
||||
:fn #(.resetZoom (.-api ^js (state/active-tldraw-app)))}
|
||||
|
||||
|
@ -550,7 +580,17 @@
|
|||
(with-meta {:before m/enable-when-not-editing-mode!}))
|
||||
|
||||
:shortcut.handler/whiteboard
|
||||
(-> (build-category-map [:whiteboard/reset-zoom
|
||||
(-> (build-category-map [:whiteboard/select
|
||||
:whiteboard/pan
|
||||
:whiteboard/portal
|
||||
:whiteboard/pencil
|
||||
:whiteboard/highlighter
|
||||
:whiteboard/eraser
|
||||
:whiteboard/connector
|
||||
:whiteboard/text
|
||||
:whiteboard/rectangle
|
||||
:whiteboard/ellipse
|
||||
:whiteboard/reset-zoom
|
||||
:whiteboard/zoom-to-fit
|
||||
:whiteboard/zoom-to-selection
|
||||
:whiteboard/zoom-out
|
||||
|
@ -818,7 +858,17 @@
|
|||
:ui/toggle-contents]
|
||||
|
||||
:shortcut.category/whiteboard
|
||||
[:whiteboard/reset-zoom
|
||||
[:whiteboard/select
|
||||
:whiteboard/pan
|
||||
:whiteboard/portal
|
||||
:whiteboard/pencil
|
||||
:whiteboard/highlighter
|
||||
:whiteboard/eraser
|
||||
:whiteboard/connector
|
||||
:whiteboard/text
|
||||
:whiteboard/rectangle
|
||||
:whiteboard/ellipse
|
||||
:whiteboard/reset-zoom
|
||||
:whiteboard/zoom-to-fit
|
||||
:whiteboard/zoom-to-selection
|
||||
:whiteboard/zoom-out
|
||||
|
|
|
@ -79,6 +79,16 @@
|
|||
:editor/zoom-in "Zoom in editing block / Forwards otherwise"
|
||||
:editor/zoom-out "Zoom out editing block / Backwards otherwise"
|
||||
:editor/toggle-undo-redo-mode "Toggle undo redo mode (global or page only)"
|
||||
:whiteboard/select "Select tool"
|
||||
:whiteboard/pan "Pan tool"
|
||||
:whiteboard/portal "Portal tool"
|
||||
:whiteboard/pencil "Pencil tool"
|
||||
:whiteboard/highlighter "Highlighter tool"
|
||||
:whiteboard/eraser "Eraser tool"
|
||||
:whiteboard/connector "Connector tool"
|
||||
:whiteboard/text "Text tool"
|
||||
:whiteboard/rectangle "Rectangle tool"
|
||||
:whiteboard/ellipse "Ellipse tool"
|
||||
:whiteboard/reset-zoom "Reset zoom"
|
||||
:whiteboard/zoom-to-fit "Zoom to drawing"
|
||||
:whiteboard/zoom-to-selection "Zoom to fit selection"
|
||||
|
|
|
@ -40,12 +40,12 @@ export const PrimaryTools = observer(function PrimaryTools() {
|
|||
<ToolButton handleClick={() =>app.selectTool("select")} tooltip="Select" id="select" icon="select-cursor" />
|
||||
<ToolButton
|
||||
handleClick={() =>app.selectTool("move")}
|
||||
tooltip="Move"
|
||||
tooltip="Pan"
|
||||
id="move"
|
||||
icon={app.isIn('move.panning') ? 'hand-grab' : 'hand-stop'}
|
||||
/>
|
||||
<Separator.Root className="tl-toolbar-separator" orientation="horizontal" />
|
||||
<ToolButton handleClick={() =>app.selectTool("logseq-portal")} tooltip="Add block or page" id="logseq-portal" icon="circle-plus" />
|
||||
<ToolButton handleClick={() =>app.selectTool("`logseq-portal")} tooltip="Add block or page" id="logseq-portal" icon="circle-plus" />
|
||||
<ToolButton handleClick={() =>app.selectTool("pencil")} tooltip="Draw" id="pencil" icon="ballpen" />
|
||||
<ToolButton handleClick={() =>app.selectTool("highlighter")} tooltip="Highlight" id="highlighter" icon="highlight" />
|
||||
<ToolButton handleClick={() =>app.selectTool("erase")} tooltip="Eraser" id="erase" icon="eraser" />
|
||||
|
|
|
@ -5,6 +5,7 @@ import { observer } from 'mobx-react-lite'
|
|||
import type * as React from 'react'
|
||||
import { Button } from '../Button'
|
||||
import { TablerIcon } from '../icons'
|
||||
import { KeyboardShortcut } from '../KeyboardShortcut'
|
||||
|
||||
export interface ToolButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
id: string
|
||||
|
@ -23,14 +24,10 @@ export const ToolButton = observer(({ id, icon, tooltip, tooltipSide = "left", h
|
|||
const shortcuts = (Tool as any)?.['shortcut']
|
||||
|
||||
const tooltipContent = shortcuts && tooltip ? (
|
||||
<>
|
||||
<div className="flex">
|
||||
{tooltip}
|
||||
<span className="ml-2 keyboard-shortcut">
|
||||
{shortcuts
|
||||
.map((shortcut: string, idx: number) => <code key={idx}>{shortcut.toUpperCase()}</code>)
|
||||
.reduce((prev: React.ReactNode, curr: React.ReactNode) => [prev, ' | ', curr])}
|
||||
</span>
|
||||
</>
|
||||
<KeyboardShortcut action={shortcuts}/>
|
||||
</div>
|
||||
) : (
|
||||
tooltip
|
||||
)
|
||||
|
|
|
@ -4,6 +4,6 @@ import { BoxShape, type Shape } from '../shapes'
|
|||
|
||||
export class BoxTool extends TLBoxTool<BoxShape, Shape, TLReactEventMap> {
|
||||
static id = 'box'
|
||||
static shortcut = ['9', 'r']
|
||||
static shortcut = 'whiteboard/rectangle'
|
||||
Shape = BoxShape
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import { EllipseShape, type Shape } from '../shapes'
|
|||
|
||||
export class EllipseTool extends TLBoxTool<EllipseShape, Shape, TLReactEventMap> {
|
||||
static id = 'ellipse'
|
||||
static shortcut = ['o']
|
||||
static shortcut = 'whiteboard/ellipse'
|
||||
Shape = EllipseShape
|
||||
}
|
||||
|
|
|
@ -4,5 +4,5 @@ import type { Shape } from '../shapes'
|
|||
|
||||
export class NuEraseTool extends TLEraseTool<Shape, TLReactEventMap> {
|
||||
static id = 'erase'
|
||||
static shortcut = ['6', 'e']
|
||||
static shortcut = 'whiteboard/eraser'
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { HighlighterShape, type Shape } from '../shapes'
|
|||
|
||||
export class HighlighterTool extends TLDrawTool<HighlighterShape, Shape, TLReactEventMap> {
|
||||
static id = 'highlighter'
|
||||
static shortcut = ['5', 'h']
|
||||
static shortcut = 'whiteboard/highlighter'
|
||||
Shape = HighlighterShape
|
||||
simplify = true
|
||||
simplifyTolerance = 0.618
|
||||
|
|
|
@ -5,6 +5,6 @@ import { LineShape, type Shape } from '../shapes'
|
|||
// @ts-expect-error maybe later
|
||||
export class LineTool extends TLLineTool<LineShape, Shape, TLReactEventMap> {
|
||||
static id = 'line'
|
||||
static shortcut = ['7', 'c']
|
||||
static shortcut = 'whiteboard/connector'
|
||||
Shape = LineShape
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ export class LogseqPortalTool extends TLTool<
|
|||
TLApp<Shape, TLReactEventMap>
|
||||
> {
|
||||
static id = 'logseq-portal'
|
||||
static shortcut = ['3']
|
||||
static shortcut = 'whiteboard/portal'
|
||||
static states = [IdleState, CreatingState]
|
||||
static initial = 'idle'
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { PencilShape, type Shape } from '../shapes'
|
|||
|
||||
export class PencilTool extends TLDrawTool<PencilShape, Shape, TLReactEventMap> {
|
||||
static id = 'pencil'
|
||||
static shortcut = ['4', 'd']
|
||||
static shortcut = 'whiteboard/pencil'
|
||||
Shape = PencilShape
|
||||
simplify = false
|
||||
}
|
||||
|
|
|
@ -4,6 +4,6 @@ import { TextShape, type Shape } from '../shapes'
|
|||
|
||||
export class TextTool extends TLTextTool<TextShape, Shape, TLReactEventMap> {
|
||||
static id = 'text'
|
||||
static shortcut = ['8', 't']
|
||||
static shortcut = 'whiteboard/text'
|
||||
Shape = TextShape
|
||||
}
|
||||
|
|
|
@ -147,7 +147,7 @@ html[data-theme='light'] {
|
|||
|
||||
.tl-menu-right-slot {
|
||||
margin-left: auto;
|
||||
padding-left: 40px;
|
||||
padding-left: 20px;
|
||||
|
||||
.keyboard-shortcut > code {
|
||||
padding: 4px !important;
|
||||
|
|
|
@ -9,7 +9,6 @@ import type {
|
|||
TLShortcut,
|
||||
TLEvents,
|
||||
} from '../types'
|
||||
import { KeyUtils } from '../utils'
|
||||
import type { TLShape } from './shapes'
|
||||
|
||||
export interface TLStateClass<
|
||||
|
@ -120,7 +119,6 @@ export abstract class TLRootState<S extends TLShape, K extends TLEventMap>
|
|||
if (this.currentState) {
|
||||
prevState._events.onExit({ ...data, toId: id })
|
||||
prevState.dispose()
|
||||
nextState.registerKeyboardShortcuts()
|
||||
this.setCurrentState(nextState)
|
||||
this._events.onTransition({ ...data, fromId: prevState.id, toId: id })
|
||||
nextState._events.onEnter({ ...data, fromId: prevState.id })
|
||||
|
@ -404,34 +402,15 @@ export abstract class TLState<
|
|||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
// @ts-ignore
|
||||
const shortcuts = this.constructor['shortcuts'] as TLShortcut<S, K>[]
|
||||
this._shortcuts = shortcuts
|
||||
|
||||
makeObservable(this)
|
||||
}
|
||||
|
||||
static cursor?: TLCursor
|
||||
|
||||
registerKeyboardShortcuts = (): void => {
|
||||
if (!this._shortcuts?.length) return
|
||||
|
||||
this._disposables.push(
|
||||
...this._shortcuts.map(({ keys, fn }) => {
|
||||
return KeyUtils.registerShortcut(keys, event => {
|
||||
if (!this.isActive) return
|
||||
fn(this.root, this, event)
|
||||
})
|
||||
})
|
||||
)
|
||||
}
|
||||
|
||||
/* --------------------- States --------------------- */
|
||||
|
||||
protected _root: R
|
||||
protected _parent: P
|
||||
private _shortcuts: TLShortcut<S, K>[] = []
|
||||
|
||||
get root() {
|
||||
return this._root
|
||||
|
|
|
@ -10,7 +10,7 @@ export class TLMoveTool<
|
|||
R extends TLApp<S, K> = TLApp<S, K>
|
||||
> extends TLTool<S, K, R> {
|
||||
static id = 'move'
|
||||
static shortcut = ['2', 'm']
|
||||
static shortcut = 'whiteboard/pan'
|
||||
|
||||
static states = [IdleState, IdleHoldState, PanningState, PinchingState]
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ export class TLSelectTool<
|
|||
|
||||
static initial = 'idle'
|
||||
|
||||
static shortcut = ['1', 's']
|
||||
static shortcut = 'whiteboard/select'
|
||||
|
||||
static states = [
|
||||
IdleState,
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
import Mousetrap from 'mousetrap'
|
||||
|
||||
type AvailableTags = 'INPUT' | 'TEXTAREA' | 'SELECT'
|
||||
|
||||
const tagFilter = ({ target }: KeyboardEvent, enableOnTags?: AvailableTags[]) => {
|
||||
const targetTagName = target && (target as HTMLElement).tagName
|
||||
return Boolean(
|
||||
targetTagName && enableOnTags && enableOnTags.includes(targetTagName as AvailableTags)
|
||||
)
|
||||
}
|
||||
|
||||
export class KeyUtils {
|
||||
static registerShortcut(
|
||||
keys: string | string[],
|
||||
callback: (keyboardEvent: Mousetrap.ExtendedKeyboardEvent, combo: string) => void
|
||||
) {
|
||||
const fn = (keyboardEvent: Mousetrap.ExtendedKeyboardEvent, combo: string): void => {
|
||||
keyboardEvent.preventDefault()
|
||||
if (
|
||||
tagFilter(keyboardEvent, ['INPUT', 'TEXTAREA', 'SELECT']) ||
|
||||
(keyboardEvent.target as HTMLElement)?.isContentEditable
|
||||
) {
|
||||
return
|
||||
}
|
||||
callback(keyboardEvent, combo)
|
||||
}
|
||||
Mousetrap.bind(keys, fn, 'keydown')
|
||||
return () => {
|
||||
Mousetrap.unbind(keys, 'keydown')
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,6 @@
|
|||
import * as uuid from 'uuid'
|
||||
export * from './BoundsUtils'
|
||||
export * from './PointUtils'
|
||||
export * from './KeyUtils'
|
||||
export * from './GeomUtils'
|
||||
export * from './PolygonUtils'
|
||||
export * from './SvgPathUtils'
|
||||
|
|
Loading…
Reference in New Issue