mirror of https://github.com/logseq/logseq
Merge pull request #6534 from logseq/enhance/whiteboards
commit
273c8563ed
|
@ -2,6 +2,7 @@
|
||||||
/* eslint-disable no-undef */
|
/* eslint-disable no-undef */
|
||||||
import 'zx/globals'
|
import 'zx/globals'
|
||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
|
import path from 'path'
|
||||||
|
|
||||||
// Build with [tsup](https://tsup.egoist.sh)
|
// Build with [tsup](https://tsup.egoist.sh)
|
||||||
await $`tsup`
|
await $`tsup`
|
||||||
|
@ -16,4 +17,7 @@ Object.assign(glob, {
|
||||||
|
|
||||||
fs.writeFileSync('dist/package.json', JSON.stringify(glob, null, 2))
|
fs.writeFileSync('dist/package.json', JSON.stringify(glob, null, 2))
|
||||||
|
|
||||||
await $`ln -f ${__dirname}/dist/index.js ${__dirname}/../../../src/js/tldraw-logseq.js`
|
const dest = path.join(__dirname, '/../../../src/js/tldraw-logseq.js')
|
||||||
|
|
||||||
|
fs.unlinkSync(dest)
|
||||||
|
fs.linkSync(path.join(__dirname, '/dist/index.js'), dest)
|
||||||
|
|
|
@ -43,7 +43,10 @@ const _ContextBar: TLContextBarComponent<Shape> = ({ shapes, offsets, hidden })
|
||||||
<div
|
<div
|
||||||
ref={rContextBar}
|
ref={rContextBar}
|
||||||
className="tl-contextbar"
|
className="tl-contextbar"
|
||||||
style={{ pointerEvents: hidden ? 'none' : 'all' }}
|
style={{
|
||||||
|
visibility: hidden ? 'hidden' : 'visible',
|
||||||
|
pointerEvents: hidden ? 'none' : 'all'
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{Actions.map((Action, idx) => (
|
{Actions.map((Action, idx) => (
|
||||||
<React.Fragment key={idx}>
|
<React.Fragment key={idx}>
|
||||||
|
|
|
@ -19,17 +19,18 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
const app = useApp()
|
const app = useApp()
|
||||||
const rContent = React.useRef<HTMLDivElement>(null)
|
const rContent = React.useRef<HTMLDivElement>(null)
|
||||||
|
|
||||||
|
const runAndTransition = (f: Function) => {
|
||||||
|
f()
|
||||||
|
app.transition('select')
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ReactContextMenu.Root
|
<ReactContextMenu.Root>
|
||||||
onOpenChange={state => {
|
|
||||||
if (!state) app.transition('select')
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<ReactContextMenu.Trigger>{children}</ReactContextMenu.Trigger>
|
<ReactContextMenu.Trigger>{children}</ReactContextMenu.Trigger>
|
||||||
<ReactContextMenu.Content
|
<ReactContextMenu.Content
|
||||||
className="tl-context-menu"
|
className="tl-context-menu"
|
||||||
ref={rContent}
|
ref={rContent}
|
||||||
onEscapeKeyDown={preventDefault}
|
onEscapeKeyDown={() => app.transition('select')}
|
||||||
collisionBoundary={collisionRef.current}
|
collisionBoundary={collisionRef.current}
|
||||||
asChild
|
asChild
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
|
@ -37,7 +38,21 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
<div>
|
<div>
|
||||||
{app.selectedShapes?.size > 0 && (
|
{app.selectedShapes?.size > 0 && (
|
||||||
<>
|
<>
|
||||||
<ReactContextMenu.Item className="tl-context-menu-button" onClick={() => app.copy()}>
|
<ReactContextMenu.Item
|
||||||
|
className="tl-context-menu-button"
|
||||||
|
onClick={() => runAndTransition(app.cut)}
|
||||||
|
>
|
||||||
|
Cut
|
||||||
|
<div className="tl-context-menu-right-slot">
|
||||||
|
<span className="keyboard-shortcut">
|
||||||
|
<code>{MOD_KEY}</code> <code>X</code>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</ReactContextMenu.Item>
|
||||||
|
<ReactContextMenu.Item
|
||||||
|
className="tl-context-menu-button"
|
||||||
|
onClick={() => runAndTransition(app.copy)}
|
||||||
|
>
|
||||||
Copy
|
Copy
|
||||||
<div className="tl-context-menu-right-slot">
|
<div className="tl-context-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
|
@ -47,7 +62,10 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
</ReactContextMenu.Item>
|
</ReactContextMenu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ReactContextMenu.Item className="tl-context-menu-button" onClick={() => app.paste()}>
|
<ReactContextMenu.Item
|
||||||
|
className="tl-context-menu-button"
|
||||||
|
onClick={() => runAndTransition(app.paste)}
|
||||||
|
>
|
||||||
Paste
|
Paste
|
||||||
<div className="tl-context-menu-right-slot">
|
<div className="tl-context-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
|
@ -58,9 +76,9 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
<ReactContextMenu.Separator className="menu-separator" />
|
<ReactContextMenu.Separator className="menu-separator" />
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.api.selectAll()}
|
onClick={() => runAndTransition(app.api.selectAll)}
|
||||||
>
|
>
|
||||||
Select All
|
Select all
|
||||||
<div className="tl-context-menu-right-slot">
|
<div className="tl-context-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
<code>{MOD_KEY}</code> <code>A</code>
|
<code>{MOD_KEY}</code> <code>A</code>
|
||||||
|
@ -70,16 +88,16 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
{app.selectedShapes?.size > 1 && (
|
{app.selectedShapes?.size > 1 && (
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.api.deselectAll()}
|
onClick={() => runAndTransition(app.api.deselectAll)}
|
||||||
>
|
>
|
||||||
Deselect All
|
Deselect all
|
||||||
</ReactContextMenu.Item>
|
</ReactContextMenu.Item>
|
||||||
)}
|
)}
|
||||||
{app.selectedShapes?.size > 0 && (
|
{app.selectedShapes?.size > 0 && (
|
||||||
<>
|
<>
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.api.deleteShapes()}
|
onClick={() => runAndTransition(app.api.deleteShapes)}
|
||||||
>
|
>
|
||||||
Delete
|
Delete
|
||||||
<div className="tl-context-menu-right-slot">
|
<div className="tl-context-menu-right-slot">
|
||||||
|
@ -93,24 +111,24 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
<ReactContextMenu.Separator className="menu-separator" />
|
<ReactContextMenu.Separator className="menu-separator" />
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.flipHorizontal()}
|
onClick={() => runAndTransition(app.flipHorizontal)}
|
||||||
>
|
>
|
||||||
Flip Horizontally
|
Flip horizontally
|
||||||
</ReactContextMenu.Item>
|
</ReactContextMenu.Item>
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.flipVertical()}
|
onClick={() => runAndTransition(app.flipVertical)}
|
||||||
>
|
>
|
||||||
Flip Vertically
|
Flip vertically
|
||||||
</ReactContextMenu.Item>
|
</ReactContextMenu.Item>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
<ReactContextMenu.Separator className="menu-separator" />
|
<ReactContextMenu.Separator className="menu-separator" />
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.bringToFront()}
|
onClick={() => runAndTransition(app.bringToFront)}
|
||||||
>
|
>
|
||||||
Move to Front
|
Move to front
|
||||||
<div className="tl-context-menu-right-slot">
|
<div className="tl-context-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
<code>⇧</code> <code>]</code>
|
<code>⇧</code> <code>]</code>
|
||||||
|
@ -119,7 +137,7 @@ export const ContextMenu = observer(function ContextMenu({
|
||||||
</ReactContextMenu.Item>
|
</ReactContextMenu.Item>
|
||||||
<ReactContextMenu.Item
|
<ReactContextMenu.Item
|
||||||
className="tl-context-menu-button"
|
className="tl-context-menu-button"
|
||||||
onClick={() => app.sendToBack()}
|
onClick={() => runAndTransition(app.sendToBack)}
|
||||||
>
|
>
|
||||||
Move to back
|
Move to back
|
||||||
<div className="tl-context-menu-right-slot">
|
<div className="tl-context-menu-right-slot">
|
||||||
|
|
|
@ -24,17 +24,22 @@ export const ZoomMenu = observer(function ZoomMenu(): JSX.Element {
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
onClick={app.api.zoomToFit}
|
onClick={app.api.zoomToFit}
|
||||||
>
|
>
|
||||||
Zoom to Fit <div className="tl-zoom-menu-right-slot"></div>
|
Zoom to fit
|
||||||
|
<div className="tl-zoom-menu-right-slot">
|
||||||
|
<span className="keyboard-shortcut">
|
||||||
|
<code>1</code>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</DropdownMenuPrimitive.Item>
|
</DropdownMenuPrimitive.Item>
|
||||||
<DropdownMenuPrimitive.Item
|
<DropdownMenuPrimitive.Item
|
||||||
className="menu-link tl-zoom-menu-dropdown-item"
|
className="menu-link tl-zoom-menu-dropdown-item"
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
onClick={app.api.zoomToSelection}
|
onClick={app.api.zoomToSelection}
|
||||||
>
|
>
|
||||||
Zoom to Selection{' '}
|
Zoom to selection
|
||||||
<div className="tl-zoom-menu-right-slot">
|
<div className="tl-zoom-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
<code>{MOD_KEY}</code> <code>-</code>
|
<code>⇧</code> <code>1</code>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</DropdownMenuPrimitive.Item>
|
</DropdownMenuPrimitive.Item>
|
||||||
|
@ -43,7 +48,7 @@ export const ZoomMenu = observer(function ZoomMenu(): JSX.Element {
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
onClick={app.api.zoomIn}
|
onClick={app.api.zoomIn}
|
||||||
>
|
>
|
||||||
Zoom In{' '}
|
Zoom in
|
||||||
<div className="tl-zoom-menu-right-slot">
|
<div className="tl-zoom-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
<code>{MOD_KEY}</code> <code>+</code>
|
<code>{MOD_KEY}</code> <code>+</code>
|
||||||
|
@ -55,7 +60,7 @@ export const ZoomMenu = observer(function ZoomMenu(): JSX.Element {
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
onClick={app.api.zoomOut}
|
onClick={app.api.zoomOut}
|
||||||
>
|
>
|
||||||
Zoom Out{' '}
|
Zoom out
|
||||||
<div className="tl-zoom-menu-right-slot">
|
<div className="tl-zoom-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
<code>{MOD_KEY}</code> <code>-</code>
|
<code>{MOD_KEY}</code> <code>-</code>
|
||||||
|
@ -67,7 +72,7 @@ export const ZoomMenu = observer(function ZoomMenu(): JSX.Element {
|
||||||
onSelect={preventEvent}
|
onSelect={preventEvent}
|
||||||
onClick={app.api.resetZoom}
|
onClick={app.api.resetZoom}
|
||||||
>
|
>
|
||||||
Reset Zoom{' '}
|
Reset zoom
|
||||||
<div className="tl-zoom-menu-right-slot">
|
<div className="tl-zoom-menu-right-slot">
|
||||||
<span className="keyboard-shortcut">
|
<span className="keyboard-shortcut">
|
||||||
<code>⇧</code> <code>0</code>
|
<code>⇧</code> <code>0</code>
|
||||||
|
|
|
@ -96,7 +96,11 @@ export class TLApp<
|
||||||
fn: () => this.api.resetZoom(),
|
fn: () => this.api.resetZoom(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
keys: 'mod+-',
|
keys: '1',
|
||||||
|
fn: () => this.api.zoomToFit(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
keys: 'shift+1',
|
||||||
fn: () => this.api.zoomToSelection(),
|
fn: () => this.api.zoomToSelection(),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -111,6 +115,10 @@ export class TLApp<
|
||||||
keys: 'mod+z',
|
keys: 'mod+z',
|
||||||
fn: () => this.undo(),
|
fn: () => this.undo(),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
keys: 'mod+x',
|
||||||
|
fn: () => this.cut(),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
keys: 'mod+shift+z',
|
keys: 'mod+shift+z',
|
||||||
fn: () => this.redo(),
|
fn: () => this.redo(),
|
||||||
|
@ -437,6 +445,11 @@ export class TLApp<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cut = () => {
|
||||||
|
this.copy()
|
||||||
|
this.api.deleteShapes()
|
||||||
|
}
|
||||||
|
|
||||||
dropFiles = (files: FileList, point?: number[]) => {
|
dropFiles = (files: FileList, point?: number[]) => {
|
||||||
this.notify('drop-files', {
|
this.notify('drop-files', {
|
||||||
files: Array.from(files),
|
files: Array.from(files),
|
||||||
|
@ -708,6 +721,7 @@ export class TLApp<
|
||||||
return (
|
return (
|
||||||
!ctrlKey &&
|
!ctrlKey &&
|
||||||
this.isInAny('select.idle', 'select.hoveringSelectionHandle') &&
|
this.isInAny('select.idle', 'select.hoveringSelectionHandle') &&
|
||||||
|
!this.isIn('select.contextMenu') &&
|
||||||
selectedShapesArray.length > 0 &&
|
selectedShapesArray.length > 0 &&
|
||||||
!selectedShapesArray.every(shape => shape.hideContextBar)
|
!selectedShapesArray.every(shape => shape.hideContextBar)
|
||||||
)
|
)
|
||||||
|
@ -819,7 +833,7 @@ export class TLApp<
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly onWheel: TLEvents<S, K>['wheel'] = (info, e) => {
|
readonly onWheel: TLEvents<S, K>['wheel'] = (info, e) => {
|
||||||
if (e.ctrlKey) {
|
if (e.ctrlKey || this.isIn('select.contextMenu')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,10 +52,6 @@ export const ContextBarContainer = observer(function ContextBarContainer<S exten
|
||||||
height: screenBounds.height,
|
height: screenBounds.height,
|
||||||
}
|
}
|
||||||
|
|
||||||
const inView =
|
|
||||||
BoundsUtils.boundsContain(vpBounds, screenBounds) ||
|
|
||||||
BoundsUtils.boundsCollide(vpBounds, screenBounds)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
ref={rBounds}
|
ref={rBounds}
|
||||||
|
|
Loading…
Reference in New Issue