Skip to content

Commit

Permalink
feat: snap to grip
Browse files Browse the repository at this point in the history
  • Loading branch information
sprocketc authored and logseq-cldwalker committed Jun 20, 2023
1 parent 17d9e64 commit 4f00e32
Show file tree
Hide file tree
Showing 10 changed files with 73 additions and 9 deletions.
2 changes: 2 additions & 0 deletions src/resources/dicts/en.edn
Expand Up @@ -354,6 +354,8 @@
:whiteboard/search-only-pages "Search only pages"
:whiteboard/cache-outdated "Cache is outdated. Please click the 'Re-index' button in the graph's dropdown menu."
:whiteboard/shape-quick-links "Shape Quick Links"
:whiteboard/toggle-grid "Toggle grid"
:whiteboard/snap-to-grid "Snap to grid"
:page-search "Search in the current page"
:graph-search "Search graph"
:home "Home"
Expand Down
31 changes: 31 additions & 0 deletions tldraw/apps/tldraw-logseq/src/components/ActionBar/ActionBar.tsx
Expand Up @@ -6,6 +6,7 @@ import * as React from 'react'
import type { Shape } from '../../lib'
import { TablerIcon } from '../icons'
import { Button } from '../Button'
import { ToggleInput } from '../inputs/ToggleInput'
import { ZoomMenu } from '../ZoomMenu'
import * as Separator from '@radix-ui/react-separator'
import { LogseqContext } from '../../lib/logseq-context'
Expand All @@ -32,6 +33,14 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
app.api.zoomOut()
}, [app])

const toggleGrid = React.useCallback(() => {
app.api.toggleGrid()
}, [app])

const toggleSnapToGrid = React.useCallback(() => {
app.api.toggleSnapToGrid()
}, [app])

return (
<div className="tl-action-bar" data-html2canvas-ignore="true">
{!app.readOnly && (
Expand All @@ -55,6 +64,28 @@ export const ActionBar = observer(function ActionBar(): JSX.Element {
<Separator.Root className="tl-toolbar-separator" orientation="vertical" />
<ZoomMenu />
</div>

<div className={'tl-toolbar tl-grid-bar ml-4'}>
<ToggleInput
tooltip={t('whiteboard/toggle-grid')}
className="tl-button"
pressed={app.settings.showGrid}
id="tl-show-grid"
onPressedChange={toggleGrid}
>
<TablerIcon name="grid-dots" />
</ToggleInput>

<ToggleInput
tooltip={t('whiteboard/snap-to-grid')}
className="tl-button"
pressed={app.settings.snapToGrid}
id="tl-snap-to-grid"
onPressedChange={toggleSnapToGrid}
>
<TablerIcon name={app.settings.snapToGrid ? "magnet" : "magnet-off"} />
</ToggleInput>
</div>
</div>
)
})
@@ -1,4 +1,4 @@
import { TLApp, TLTargetType, TLToolState, uniqueId } from '@tldraw/core'
import { TLApp, TLTargetType, TLToolState, uniqueId, GRID_SIZE } from '@tldraw/core'
import type { TLReactEventMap, TLReactEvents } from '@tldraw/react'
import Vec from '@tldraw/vec'
import { transaction } from 'mobx'
Expand All @@ -20,10 +20,16 @@ export class CreatingState extends TLToolState<
onEnter = () => {
this.app.history.pause()
transaction(() => {
let point = Vec.sub(this.app.inputs.originPoint, this.offset)

if (this.app.settings.snapToGrid) {
point = Vec.snap(point, GRID_SIZE)
}

const shape = new LogseqPortalShape({
id: uniqueId(),
parentId: this.app.currentPage.id,
point: Vec.sub(this.app.inputs.originPoint, this.offset),
point: point,
size: LogseqPortalShape.defaultProps.size,
fill: this.app.settings.color,
stroke: this.app.settings.color,
Expand Down
6 changes: 6 additions & 0 deletions tldraw/packages/core/src/lib/TLApi/TLApi.ts
Expand Up @@ -172,6 +172,12 @@ export class TLApi<S extends TLShape = TLShape, K extends TLEventMap = TLEventMa
return this
}

toggleSnapToGrid = (): this => {
const { settings } = this.app
settings.update({ snapToGrid: !settings.snapToGrid })
return this
}

setColor = (color: string): this => {
const { settings } = this.app

Expand Down
1 change: 0 additions & 1 deletion tldraw/packages/core/src/lib/TLApp/TLApp.ts
Expand Up @@ -10,7 +10,6 @@ import type {
TLCallback,
TLEventMap,
TLEvents,
TLShortcut,
TLStateEvents,
TLSubscription,
TLSubscriptionEventInfo,
Expand Down
2 changes: 2 additions & 0 deletions tldraw/packages/core/src/lib/TLSettings.ts
Expand Up @@ -4,6 +4,7 @@ import { observable, makeObservable, action } from 'mobx'
export interface TLSettingsProps {
mode: 'light' | 'dark'
showGrid: boolean
snapToGrid: boolean
color: string
scaleLevel: string
}
Expand All @@ -15,6 +16,7 @@ export class TLSettings implements TLSettingsProps {

@observable mode: 'dark' | 'light' = 'light'
@observable showGrid = true
@observable snapToGrid = true
@observable scaleLevel = 'md'
@observable color = ''

Expand Down
2 changes: 1 addition & 1 deletion tldraw/packages/core/src/lib/TLViewport.ts
Expand Up @@ -51,7 +51,7 @@ export class TLViewport {
}

panToPointWhenNearBounds = (point: number[]) => {
const threshold = [TLViewport.panThreshold, TLViewport.panThreshold]
const threshold = Vec.div([TLViewport.panThreshold, TLViewport.panThreshold], this.camera.zoom)

const deltaMax = Vec.sub([this.currentView.maxX, this.currentView.maxY], Vec.add(point, threshold))
const deltaMin = Vec.sub([this.currentView.minX, this.currentView.minY], Vec.sub(point, threshold))
Expand Down
@@ -1,5 +1,6 @@
import type { TLBoxTool } from '../TLBoxTool'
import Vec from '@tldraw/vec'
import { GRID_SIZE } from '@tldraw/core'
import type { TLBounds } from '@tldraw/intersect'
import { type TLEventMap, TLCursor, type TLStateEvents, TLResizeCorner } from '../../../../types'
import { uniqueId, BoundsUtils } from '../../../../utils'
Expand Down Expand Up @@ -68,7 +69,7 @@ export class CreatingState<
if (!this.creatingShape) throw Error('Expected a creating shape.')
const { initialBounds } = this
const { currentPoint, originPoint, shiftKey } = this.app.inputs
const bounds = BoundsUtils.getTransformedBoundingBox(
let bounds = BoundsUtils.getTransformedBoundingBox(
initialBounds,
TLResizeCorner.BottomRight,
Vec.sub(currentPoint, originPoint),
Expand All @@ -78,6 +79,10 @@ export class CreatingState<
!this.creatingShape.canChangeAspectRatio
)

if (this.app.settings.snapToGrid) {
bounds = BoundsUtils.snapBoundsToGrid(bounds, GRID_SIZE)
}

this.creatingShape.update({
point: [bounds.minX, bounds.minY],
size: [bounds.width, bounds.height],
Expand Down
@@ -1,4 +1,5 @@
import type { TLBounds } from '@tldraw/intersect'
import { GRID_SIZE } from '@tldraw/core'
import { Vec } from '@tldraw/vec'
import {
type TLEventMap,
Expand Down Expand Up @@ -216,6 +217,11 @@ export class ResizingState<
// // Position the bounds at the center
// relativeBounds = BoundsUtils.centerBounds(relativeBounds, center)
// }

if (this.app.settings.snapToGrid) {
relativeBounds = BoundsUtils.snapBoundsToGrid(relativeBounds, GRID_SIZE)
}

shape.onResize(initialShapeProps, {
center,
rotation,
Expand Down
@@ -1,11 +1,12 @@
import { Vec } from '@tldraw/vec'
import { transaction } from 'mobx'
import { type TLEventMap, TLCursor, type TLEvents } from '../../../../types'
import { dedupe, uniqueId } from '../../../../utils'
import { uniqueId } from '../../../../utils'
import type { TLShape } from '../../../shapes'
import type { TLApp } from '../../../TLApp'
import { TLToolState } from '../../../TLToolState'
import type { TLSelectTool } from '../TLSelectTool'
import { GRID_SIZE } from '../../../../constants'

export class TranslatingState<
S extends TLShape,
Expand Down Expand Up @@ -46,9 +47,15 @@ export class TranslatingState<
}

transaction(() => {
this.app.allSelectedShapesArray.forEach(shape => {
if (!shape.props.isLocked) shape.update({ point: Vec.add(initialPoints[shape.id], delta) })
})
this.app.allSelectedShapesArray
.filter(s => !s.props.isLocked)
.forEach(shape => {
let position = Vec.add(initialPoints[shape.id], delta)
if (this.app.settings.snapToGrid) {
position = Vec.snap(position, GRID_SIZE)
}
shape.update({ point: position })
})
})
}

Expand Down

0 comments on commit 4f00e32

Please sign in to comment.