Merge branch 'main' of https://github.com/tldraw/tldraw
This commit is contained in:
commit
d1fb7d1115
32 changed files with 158 additions and 29 deletions
|
@ -201,6 +201,7 @@ export default function App({ onMount }: AppProps): JSX.Element {
|
||||||
shapeUtils={shapeUtils} // Required
|
shapeUtils={shapeUtils} // Required
|
||||||
page={appState.data.page} // Required
|
page={appState.data.page} // Required
|
||||||
pageState={appState.data.pageState} // Required
|
pageState={appState.data.pageState} // Required
|
||||||
|
performanceMode={appState.data.performanceMode}
|
||||||
meta={appState.data.meta}
|
meta={appState.data.meta}
|
||||||
snapLines={appState.data.overlays.snapLines}
|
snapLines={appState.data.overlays.snapLines}
|
||||||
onPointShape={onPointShape}
|
onPointShape={onPointShape}
|
||||||
|
|
|
@ -11,3 +11,4 @@ export * from './snaps'
|
||||||
export * from './transform'
|
export * from './transform'
|
||||||
export * from './translate'
|
export * from './translate'
|
||||||
export * from './mutables'
|
export * from './mutables'
|
||||||
|
export * from './performance'
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import type { Action } from 'state/constants'
|
||||||
|
|
||||||
|
export const clearPerformanceMode: Action = (data) => {
|
||||||
|
data.performanceMode = undefined
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
export * from './clearPerformanceMode'
|
||||||
|
export * from './setTranslatePerformanceMode'
|
||||||
|
export * from './setTransformPerformanceMode'
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { TLPerformanceMode } from '@tldraw/core'
|
||||||
|
import type { Action } from 'state/constants'
|
||||||
|
|
||||||
|
export const setTransformPerformanceMode: Action = (data) => {
|
||||||
|
data.performanceMode = TLPerformanceMode.TransformSelected
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
import { TLPerformanceMode } from '@tldraw/core'
|
||||||
|
import type { Action } from 'state/constants'
|
||||||
|
|
||||||
|
export const setTranslatePerformanceMode: Action = (data) => {
|
||||||
|
data.performanceMode = TLPerformanceMode.TranslateSelected
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
import type { TLBinding, TLPage, TLPageState, TLSnapLine } from '@tldraw/core'
|
import type { TLBinding, TLPage, TLPageState, TLPerformanceMode, TLSnapLine } from '@tldraw/core'
|
||||||
import type { Shape } from '../shapes'
|
import type { Shape } from '../shapes'
|
||||||
import type { S } from '@state-designer/react'
|
import type { S } from '@state-designer/react'
|
||||||
|
|
||||||
|
@ -104,6 +104,7 @@ export const INITIAL_DATA = {
|
||||||
meta: {
|
meta: {
|
||||||
isDarkMode: false,
|
isDarkMode: false,
|
||||||
},
|
},
|
||||||
|
performanceMode: undefined as TLPerformanceMode | undefined,
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AppDocument = {
|
export type AppDocument = {
|
||||||
|
|
|
@ -2,7 +2,6 @@ import { createState } from '@state-designer/react'
|
||||||
import type { TLPointerInfo } from '@tldraw/core'
|
import type { TLPointerInfo } from '@tldraw/core'
|
||||||
import { INITIAL_DATA } from './constants'
|
import { INITIAL_DATA } from './constants'
|
||||||
import Vec from '@tldraw/vec'
|
import Vec from '@tldraw/vec'
|
||||||
import { getPagePoint } from './helpers'
|
|
||||||
import * as actions from './actions'
|
import * as actions from './actions'
|
||||||
import { mutables } from './mutables'
|
import { mutables } from './mutables'
|
||||||
|
|
||||||
|
@ -42,7 +41,7 @@ export const machine = createState({
|
||||||
initial: 'idle',
|
initial: 'idle',
|
||||||
states: {
|
states: {
|
||||||
idle: {
|
idle: {
|
||||||
onEnter: ['clearPointedShape'],
|
onEnter: ['clearPointedShape', 'clearPerformanceMode'],
|
||||||
on: {
|
on: {
|
||||||
SELECTED_ALL: 'selectAllShapes',
|
SELECTED_ALL: 'selectAllShapes',
|
||||||
DESELECTED_ALL: 'deselectAllShapes',
|
DESELECTED_ALL: 'deselectAllShapes',
|
||||||
|
@ -149,7 +148,7 @@ export const machine = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
translating: {
|
translating: {
|
||||||
onEnter: 'setSnapInfo',
|
onEnter: ['setSnapInfo', 'setTranslatePerformanceMode'],
|
||||||
onExit: ['clearSnapInfo', 'clearSnapLines', 'clearIsCloning'],
|
onExit: ['clearSnapInfo', 'clearSnapLines', 'clearIsCloning'],
|
||||||
on: {
|
on: {
|
||||||
CANCELLED: {
|
CANCELLED: {
|
||||||
|
@ -181,7 +180,7 @@ export const machine = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
transforming: {
|
transforming: {
|
||||||
onEnter: ['setSnapInfo', 'setInitialCommonBounds'],
|
onEnter: ['setSnapInfo', 'setInitialCommonBounds', 'setTransformPerformanceMode'],
|
||||||
onExit: ['clearSnapInfo', 'clearSnapLines', 'clearPointedBoundsHandle'],
|
onExit: ['clearSnapInfo', 'clearSnapLines', 'clearPointedBoundsHandle'],
|
||||||
on: {
|
on: {
|
||||||
TOGGLED_MODIFIER: ['transformSelectedShapes', 'updateBoundShapes'],
|
TOGGLED_MODIFIER: ['transformSelectedShapes', 'updateBoundShapes'],
|
||||||
|
@ -260,6 +259,7 @@ export const machine = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
pencil: {
|
pencil: {
|
||||||
|
onEnter: 'setTransformPerformanceMode',
|
||||||
initial: 'idle',
|
initial: 'idle',
|
||||||
states: {
|
states: {
|
||||||
idle: {
|
idle: {
|
||||||
|
@ -294,6 +294,7 @@ export const machine = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
box: {
|
box: {
|
||||||
|
onEnter: 'setTransformPerformanceMode',
|
||||||
initial: 'idle',
|
initial: 'idle',
|
||||||
states: {
|
states: {
|
||||||
idle: {
|
idle: {
|
||||||
|
@ -334,6 +335,7 @@ export const machine = createState({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
arrow: {
|
arrow: {
|
||||||
|
onEnter: 'setTransformPerformanceMode',
|
||||||
initial: 'idle',
|
initial: 'idle',
|
||||||
states: {
|
states: {
|
||||||
idle: {
|
idle: {
|
||||||
|
|
|
@ -2,12 +2,13 @@
|
||||||
import { observer } from 'mobx-react-lite'
|
import { observer } from 'mobx-react-lite'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import {
|
import {
|
||||||
usePreventNavigation,
|
usePreventNavigationCss,
|
||||||
useZoomEvents,
|
useZoomEvents,
|
||||||
useSafariFocusOutFix,
|
useSafariFocusOutFix,
|
||||||
useCanvasEvents,
|
useCanvasEvents,
|
||||||
useCameraCss,
|
useCameraCss,
|
||||||
useKeyEvents,
|
useKeyEvents,
|
||||||
|
usePerformanceCss,
|
||||||
} from '~hooks'
|
} from '~hooks'
|
||||||
import type {
|
import type {
|
||||||
TLAssets,
|
TLAssets,
|
||||||
|
@ -15,6 +16,7 @@ import type {
|
||||||
TLBounds,
|
TLBounds,
|
||||||
TLPage,
|
TLPage,
|
||||||
TLPageState,
|
TLPageState,
|
||||||
|
TLPerformanceMode,
|
||||||
TLShape,
|
TLShape,
|
||||||
TLSnapLine,
|
TLSnapLine,
|
||||||
TLUsers,
|
TLUsers,
|
||||||
|
@ -46,6 +48,7 @@ interface CanvasProps<T extends TLShape, M extends Record<string, unknown>> {
|
||||||
hideRotateHandle: boolean
|
hideRotateHandle: boolean
|
||||||
hideGrid: boolean
|
hideGrid: boolean
|
||||||
externalContainerRef?: React.RefObject<HTMLElement>
|
externalContainerRef?: React.RefObject<HTMLElement>
|
||||||
|
performanceMode?: TLPerformanceMode
|
||||||
meta?: M
|
meta?: M
|
||||||
id?: string
|
id?: string
|
||||||
onBoundsChange: (bounds: TLBounds) => void
|
onBoundsChange: (bounds: TLBounds) => void
|
||||||
|
@ -64,6 +67,7 @@ export const Canvas = observer(function _Canvas<
|
||||||
users,
|
users,
|
||||||
userId,
|
userId,
|
||||||
meta,
|
meta,
|
||||||
|
performanceMode,
|
||||||
externalContainerRef,
|
externalContainerRef,
|
||||||
hideHandles,
|
hideHandles,
|
||||||
hideBounds,
|
hideBounds,
|
||||||
|
@ -87,10 +91,12 @@ export const Canvas = observer(function _Canvas<
|
||||||
|
|
||||||
useSafariFocusOutFix()
|
useSafariFocusOutFix()
|
||||||
|
|
||||||
usePreventNavigation(rCanvas)
|
usePreventNavigationCss(rCanvas)
|
||||||
|
|
||||||
useCameraCss(rLayer, rContainer, pageState)
|
useCameraCss(rLayer, rContainer, pageState)
|
||||||
|
|
||||||
|
usePerformanceCss(performanceMode, rContainer)
|
||||||
|
|
||||||
useKeyEvents()
|
useKeyEvents()
|
||||||
|
|
||||||
const events = useCanvasEvents()
|
const events = useCanvasEvents()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { observer } from 'mobx-react-lite'
|
import { observer } from 'mobx-react-lite'
|
||||||
import type {HTMLProps} from 'react'
|
import type { HTMLProps } from 'react'
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import type { TLBounds } from '~types'
|
import type { TLBounds } from '~types'
|
||||||
import { usePosition } from '~hooks'
|
import { usePosition } from '~hooks'
|
||||||
|
@ -7,8 +7,9 @@ import { usePosition } from '~hooks'
|
||||||
interface ContainerProps extends HTMLProps<HTMLDivElement> {
|
interface ContainerProps extends HTMLProps<HTMLDivElement> {
|
||||||
id?: string
|
id?: string
|
||||||
bounds: TLBounds
|
bounds: TLBounds
|
||||||
isGhost?: boolean
|
|
||||||
rotation?: number
|
rotation?: number
|
||||||
|
isGhost?: boolean
|
||||||
|
isSelected?: boolean
|
||||||
children: React.ReactNode
|
children: React.ReactNode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ export const Container = observer<ContainerProps>(function Container({
|
||||||
bounds,
|
bounds,
|
||||||
rotation = 0,
|
rotation = 0,
|
||||||
isGhost = false,
|
isGhost = false,
|
||||||
|
isSelected = false,
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
}) {
|
}) {
|
||||||
|
@ -26,7 +28,9 @@ export const Container = observer<ContainerProps>(function Container({
|
||||||
<div
|
<div
|
||||||
id={id}
|
id={id}
|
||||||
ref={rPositioned}
|
ref={rPositioned}
|
||||||
className={isGhost ? 'tl-positioned tl-ghost' : 'tl-positioned'}
|
className={`tl-positioned${isGhost ? ' tl-ghost' : ''}${
|
||||||
|
isSelected ? ` tl-positioned-selected` : ''
|
||||||
|
}`}
|
||||||
aria-label="container"
|
aria-label="container"
|
||||||
data-testid="container"
|
data-testid="container"
|
||||||
{...props}
|
{...props}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import type {
|
||||||
TLSnapLine,
|
TLSnapLine,
|
||||||
TLUsers,
|
TLUsers,
|
||||||
TLAssets,
|
TLAssets,
|
||||||
|
TLPerformanceMode,
|
||||||
} from '../../types'
|
} from '../../types'
|
||||||
import { Canvas } from '../Canvas'
|
import { Canvas } from '../Canvas'
|
||||||
import { Inputs } from '../../inputs'
|
import { Inputs } from '../../inputs'
|
||||||
|
@ -34,7 +35,7 @@ export interface RendererProps<T extends TLShape, M = any> extends Partial<TLCal
|
||||||
/**
|
/**
|
||||||
* A map of assets to be used in the renderer.
|
* A map of assets to be used in the renderer.
|
||||||
*/
|
*/
|
||||||
assets: TLAssets
|
assets?: TLAssets
|
||||||
/**
|
/**
|
||||||
* (optional) A unique id to be applied to the renderer element, used to scope styles.
|
* (optional) A unique id to be applied to the renderer element, used to scope styles.
|
||||||
*/
|
*/
|
||||||
|
@ -100,6 +101,10 @@ export interface RendererProps<T extends TLShape, M = any> extends Partial<TLCal
|
||||||
* (optional) The size of the grid step.
|
* (optional) The size of the grid step.
|
||||||
*/
|
*/
|
||||||
grid?: number
|
grid?: number
|
||||||
|
/**
|
||||||
|
* (optional) Use a performance mode.
|
||||||
|
*/
|
||||||
|
performanceMode?: TLPerformanceMode
|
||||||
/**
|
/**
|
||||||
* (optional) A callback that receives the renderer's inputs manager.
|
* (optional) A callback that receives the renderer's inputs manager.
|
||||||
*/
|
*/
|
||||||
|
@ -126,7 +131,7 @@ export const Renderer = observer(function _Renderer<
|
||||||
shapeUtils,
|
shapeUtils,
|
||||||
page,
|
page,
|
||||||
pageState,
|
pageState,
|
||||||
assets,
|
assets = EMPTY_OBJECT,
|
||||||
users,
|
users,
|
||||||
userId,
|
userId,
|
||||||
theme,
|
theme,
|
||||||
|
@ -134,6 +139,7 @@ export const Renderer = observer(function _Renderer<
|
||||||
snapLines,
|
snapLines,
|
||||||
grid,
|
grid,
|
||||||
containerRef,
|
containerRef,
|
||||||
|
performanceMode,
|
||||||
hideHandles = false,
|
hideHandles = false,
|
||||||
hideIndicators = false,
|
hideIndicators = false,
|
||||||
hideCloneHandles = false,
|
hideCloneHandles = false,
|
||||||
|
@ -198,8 +204,11 @@ export const Renderer = observer(function _Renderer<
|
||||||
hideResizeHandles={hideResizeHandles}
|
hideResizeHandles={hideResizeHandles}
|
||||||
hideGrid={hideGrid}
|
hideGrid={hideGrid}
|
||||||
onBoundsChange={onBoundsChange}
|
onBoundsChange={onBoundsChange}
|
||||||
|
performanceMode={performanceMode}
|
||||||
meta={meta}
|
meta={meta}
|
||||||
/>
|
/>
|
||||||
</TLContext.Provider>
|
</TLContext.Provider>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const EMPTY_OBJECT = {} as TLAssets
|
||||||
|
|
|
@ -22,7 +22,14 @@ export const Shape = observer(function Shape<T extends TLShape, E extends Elemen
|
||||||
const events = useShapeEvents(shape.id)
|
const events = useShapeEvents(shape.id)
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container id={shape.id} bounds={bounds} rotation={shape.rotation} data-shape={shape.type}>
|
<Container
|
||||||
|
id={shape.id}
|
||||||
|
bounds={bounds}
|
||||||
|
rotation={shape.rotation}
|
||||||
|
data-shape={shape.type}
|
||||||
|
isGhost={rest.isGhost}
|
||||||
|
isSelected={rest.isSelected}
|
||||||
|
>
|
||||||
<RenderedShape
|
<RenderedShape
|
||||||
shape={shape}
|
shape={shape}
|
||||||
utils={utils as any}
|
utils={utils as any}
|
||||||
|
|
|
@ -11,8 +11,9 @@ export * from './useCameraCss'
|
||||||
export * from './useSelection'
|
export * from './useSelection'
|
||||||
export * from './useHandleEvents'
|
export * from './useHandleEvents'
|
||||||
export * from './useHandles'
|
export * from './useHandles'
|
||||||
export * from './usePreventNavigation'
|
export * from './usePreventNavigationCss'
|
||||||
export * from './useBoundsEvents'
|
export * from './useBoundsEvents'
|
||||||
export * from './usePosition'
|
export * from './usePosition'
|
||||||
export * from './useKeyEvents'
|
export * from './useKeyEvents'
|
||||||
export * from './useCursorAnimation'
|
export * from './useCursorAnimation'
|
||||||
|
export * from './usePerformanceCss'
|
||||||
|
|
40
packages/core/src/hooks/usePerformanceCss.ts
Normal file
40
packages/core/src/hooks/usePerformanceCss.ts
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import * as React from 'react'
|
||||||
|
import { TLPerformanceMode } from '~types'
|
||||||
|
|
||||||
|
export function usePerformanceCss(
|
||||||
|
performanceMode: TLPerformanceMode | undefined,
|
||||||
|
rContainer: React.ForwardedRef<HTMLDivElement>
|
||||||
|
) {
|
||||||
|
React.useLayoutEffect(() => {
|
||||||
|
if (rContainer && 'current' in rContainer) {
|
||||||
|
const container = rContainer?.current
|
||||||
|
if (!container) return
|
||||||
|
switch (performanceMode) {
|
||||||
|
case TLPerformanceMode.TransformSelected: {
|
||||||
|
container.style.setProperty('--tl-performance-all', 'auto')
|
||||||
|
container.style.setProperty('--tl-performance-selected', 'transform, contents')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case TLPerformanceMode.TransformAll: {
|
||||||
|
container.style.setProperty('--tl-performance-all', 'transform, contents')
|
||||||
|
container.style.setProperty('--tl-performance-selected', 'transform, contents')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case TLPerformanceMode.TranslateSelected: {
|
||||||
|
container.style.setProperty('--tl-performance-all', 'auto')
|
||||||
|
container.style.setProperty('--tl-performance-selected', 'transform')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
case TLPerformanceMode.TranslateAll: {
|
||||||
|
container.style.setProperty('--tl-performance-all', 'transform')
|
||||||
|
container.style.setProperty('--tl-performance-selected', 'transform')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
container.style.setProperty('--tl-performance-all', 'auto')
|
||||||
|
container.style.setProperty('--tl-performance-selected', 'auto')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [performanceMode])
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
import * as React from 'react'
|
import * as React from 'react'
|
||||||
import { useTLContext } from './useTLContext'
|
import { useTLContext } from './useTLContext'
|
||||||
|
|
||||||
export function usePreventNavigation(rCanvas: React.RefObject<HTMLDivElement>): void {
|
export function usePreventNavigationCss(rCanvas: React.RefObject<HTMLDivElement>): void {
|
||||||
const { bounds } = useTLContext()
|
const { bounds } = useTLContext()
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
|
@ -115,6 +115,8 @@ const tlcss = css`
|
||||||
--tl-zoom: 1;
|
--tl-zoom: 1;
|
||||||
--tl-scale: calc(1 / var(--tl-zoom));
|
--tl-scale: calc(1 / var(--tl-zoom));
|
||||||
--tl-padding: calc(64px * max(1, var(--tl-scale)));
|
--tl-padding: calc(64px * max(1, var(--tl-scale)));
|
||||||
|
--tl-performance-all: auto;
|
||||||
|
--tl-performance-selected: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
left: 0px;
|
left: 0px;
|
||||||
|
@ -200,6 +202,7 @@ const tlcss = css`
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
contain: layout style size;
|
contain: layout style size;
|
||||||
|
will-change: var(--tl-performance-all);
|
||||||
}
|
}
|
||||||
|
|
||||||
.tl-positioned-svg {
|
.tl-positioned-svg {
|
||||||
|
@ -219,6 +222,10 @@ const tlcss = css`
|
||||||
contain: layout style size;
|
contain: layout style size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tl-positioned-selected {
|
||||||
|
will-change: var(--tl-performance-selected);
|
||||||
|
}
|
||||||
|
|
||||||
.tl-inner-div {
|
.tl-inner-div {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -327,6 +334,10 @@ const tlcss = css`
|
||||||
stroke-width: calc(2.5px * min(5, var(--tl-scale)));
|
stroke-width: calc(2.5px * min(5, var(--tl-scale)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tl-performance {
|
||||||
|
will-change: transform, contents;
|
||||||
|
}
|
||||||
|
|
||||||
.tl-clone-target {
|
.tl-clone-target {
|
||||||
pointer-events: all;
|
pointer-events: all;
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,7 @@ export class Inputs {
|
||||||
|
|
||||||
this.pointer = info
|
this.pointer = info
|
||||||
|
|
||||||
this.pointerUpTime = Date.now()
|
this.pointerUpTime = performance.now()
|
||||||
|
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
@ -300,7 +300,7 @@ export class Inputs {
|
||||||
const { origin, point } = this.pointer
|
const { origin, point } = this.pointer
|
||||||
|
|
||||||
const isDoubleClick =
|
const isDoubleClick =
|
||||||
Date.now() - this.pointerUpTime < DOUBLE_CLICK_DURATION && Vec.dist(origin, point) < 4
|
performance.now() - this.pointerUpTime < DOUBLE_CLICK_DURATION && Vec.dist(origin, point) < 4
|
||||||
|
|
||||||
// Reset the active pointer, in case it got stuck
|
// Reset the active pointer, in case it got stuck
|
||||||
if (isDoubleClick) this.activePointer = undefined
|
if (isDoubleClick) this.activePointer = undefined
|
||||||
|
|
|
@ -4,6 +4,13 @@
|
||||||
|
|
||||||
import type React from 'react'
|
import type React from 'react'
|
||||||
|
|
||||||
|
export enum TLPerformanceMode {
|
||||||
|
TransformSelected = 'transform_selected',
|
||||||
|
TranslateSelected = 'translate_selected',
|
||||||
|
TransformAll = 'transform_all',
|
||||||
|
TranslateAll = 'translate_all',
|
||||||
|
}
|
||||||
|
|
||||||
export type TLAssets = Record<string, TLAsset>
|
export type TLAssets = Record<string, TLAsset>
|
||||||
|
|
||||||
export interface TLAsset {
|
export interface TLAsset {
|
||||||
|
|
|
@ -473,6 +473,7 @@ const InnerTldraw = React.memo(function InnerTldraw({
|
||||||
hideCloneHandles={hideCloneHandles}
|
hideCloneHandles={hideCloneHandles}
|
||||||
hideRotateHandles={!settings.showRotateHandles}
|
hideRotateHandles={!settings.showRotateHandles}
|
||||||
hideGrid={!settings.showGrid}
|
hideGrid={!settings.showGrid}
|
||||||
|
performanceMode={app.session?.performanceMode}
|
||||||
onPinchStart={app.onPinchStart}
|
onPinchStart={app.onPinchStart}
|
||||||
onPinchEnd={app.onPinchEnd}
|
onPinchEnd={app.onPinchEnd}
|
||||||
onPinch={app.onPinch}
|
onPinch={app.onPinch}
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
Utils,
|
Utils,
|
||||||
TLBounds,
|
TLBounds,
|
||||||
TLDropEventHandler,
|
TLDropEventHandler,
|
||||||
|
TLPerformanceMode,
|
||||||
} from '@tldraw/core'
|
} from '@tldraw/core'
|
||||||
import {
|
import {
|
||||||
FlipType,
|
FlipType,
|
||||||
|
@ -858,7 +859,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
|
||||||
setEditingId = (id?: string) => {
|
setEditingId = (id?: string) => {
|
||||||
if (this.readOnly) return
|
if (this.readOnly) return
|
||||||
|
|
||||||
this.editingStartTime = Date.now()
|
this.editingStartTime = performance.now()
|
||||||
this.patchState(
|
this.patchState(
|
||||||
{
|
{
|
||||||
document: {
|
document: {
|
||||||
|
@ -3266,7 +3267,7 @@ export class TldrawApp extends StateManager<TDSnapshot> {
|
||||||
|
|
||||||
onShapeBlur = () => {
|
onShapeBlur = () => {
|
||||||
// This prevents an auto-blur event from Safari
|
// This prevents an auto-blur event from Safari
|
||||||
if (Date.now() - this.editingStartTime < 50) return
|
if (performance.now() - this.editingStartTime < 50) return
|
||||||
|
|
||||||
const { editingId } = this.pageState
|
const { editingId } = this.pageState
|
||||||
const { isToolLocked } = this.getAppState()
|
const { isToolLocked } = this.getAppState()
|
||||||
|
|
|
@ -13,6 +13,7 @@ const checkPermissions = async (handle: FileSystemHandle) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function loadFileHandle() {
|
export async function loadFileHandle() {
|
||||||
|
if (typeof Window === 'undefined' || !('_location' in Window)) return
|
||||||
const fileHandle = await getFromIdb(`Tldraw_file_handle_${window.location.origin}`)
|
const fileHandle = await getFromIdb(`Tldraw_file_handle_${window.location.origin}`)
|
||||||
if (!fileHandle) return null
|
if (!fileHandle) return null
|
||||||
return fileHandle
|
return fileHandle
|
||||||
|
|
|
@ -14,10 +14,11 @@ import { TLDR } from '~state/TLDR'
|
||||||
import { shapeUtils } from '~state/shapes'
|
import { shapeUtils } from '~state/shapes'
|
||||||
import { BaseSession } from '../BaseSession'
|
import { BaseSession } from '../BaseSession'
|
||||||
import type { TldrawApp } from '../../internal'
|
import type { TldrawApp } from '../../internal'
|
||||||
import { Utils } from '@tldraw/core'
|
import { TLPerformanceMode, Utils } from '@tldraw/core'
|
||||||
|
|
||||||
export class ArrowSession extends BaseSession {
|
export class ArrowSession extends BaseSession {
|
||||||
type = SessionType.Arrow
|
type = SessionType.Arrow
|
||||||
|
performanceMode = TLPerformanceMode.TransformSelected
|
||||||
status = TDStatus.TranslatingHandle
|
status = TDStatus.TranslatingHandle
|
||||||
newStartBindingId = Utils.uniqueId()
|
newStartBindingId = Utils.uniqueId()
|
||||||
draggedBindingId = Utils.uniqueId()
|
draggedBindingId = Utils.uniqueId()
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
|
import type { TLPerformanceMode } from '@tldraw/core'
|
||||||
import type { SessionType, TldrawCommand, TldrawPatch } from '~types'
|
import type { SessionType, TldrawCommand, TldrawPatch } from '~types'
|
||||||
import type { TldrawApp } from '../internal'
|
import type { TldrawApp } from '../internal'
|
||||||
|
|
||||||
export abstract class BaseSession {
|
export abstract class BaseSession {
|
||||||
abstract type: SessionType
|
abstract type: SessionType
|
||||||
|
abstract performanceMode: TLPerformanceMode | undefined
|
||||||
constructor(public app: TldrawApp) {}
|
constructor(public app: TldrawApp) {}
|
||||||
|
|
||||||
abstract start: () => TldrawPatch | undefined
|
abstract start: () => TldrawPatch | undefined
|
||||||
|
|
||||||
abstract update: () => TldrawPatch | undefined
|
abstract update: () => TldrawPatch | undefined
|
||||||
|
|
||||||
abstract complete: () => TldrawPatch | TldrawCommand | undefined
|
abstract complete: () => TldrawPatch | TldrawCommand | undefined
|
||||||
|
|
||||||
abstract cancel: () => TldrawPatch | undefined
|
abstract cancel: () => TldrawPatch | undefined
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { BaseSession } from '../BaseSession'
|
||||||
|
|
||||||
export class BrushSession extends BaseSession {
|
export class BrushSession extends BaseSession {
|
||||||
type = SessionType.Brush
|
type = SessionType.Brush
|
||||||
|
performanceMode = undefined
|
||||||
status = TDStatus.Brushing
|
status = TDStatus.Brushing
|
||||||
initialSelectedIds: Set<string>
|
initialSelectedIds: Set<string>
|
||||||
shapesToTest: {
|
shapesToTest: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Utils } from '@tldraw/core'
|
import { TLPerformanceMode, Utils } from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import { SessionType, TDStatus, TldrawPatch, TldrawCommand, DrawShape } from '~types'
|
import { SessionType, TDStatus, TldrawPatch, TldrawCommand, DrawShape } from '~types'
|
||||||
import type { TldrawApp } from '../../internal'
|
import type { TldrawApp } from '../../internal'
|
||||||
|
@ -6,6 +6,7 @@ import { BaseSession } from '../BaseSession'
|
||||||
|
|
||||||
export class DrawSession extends BaseSession {
|
export class DrawSession extends BaseSession {
|
||||||
type = SessionType.Draw
|
type = SessionType.Draw
|
||||||
|
performanceMode = TLPerformanceMode.TransformSelected
|
||||||
status = TDStatus.Creating
|
status = TDStatus.Creating
|
||||||
topLeft: number[]
|
topLeft: number[]
|
||||||
points: number[][]
|
points: number[][]
|
||||||
|
|
|
@ -13,6 +13,7 @@ import { BaseSession } from '../BaseSession'
|
||||||
|
|
||||||
export class EraseSession extends BaseSession {
|
export class EraseSession extends BaseSession {
|
||||||
type = SessionType.Draw
|
type = SessionType.Draw
|
||||||
|
performanceMode = undefined
|
||||||
status = TDStatus.Creating
|
status = TDStatus.Creating
|
||||||
isLocked?: boolean
|
isLocked?: boolean
|
||||||
lockedDirection?: 'horizontal' | 'vertical'
|
lockedDirection?: 'horizontal' | 'vertical'
|
||||||
|
|
|
@ -15,6 +15,7 @@ import type { TldrawApp } from '../../internal'
|
||||||
|
|
||||||
export class GridSession extends BaseSession {
|
export class GridSession extends BaseSession {
|
||||||
type = SessionType.Grid
|
type = SessionType.Grid
|
||||||
|
performanceMode = undefined
|
||||||
status = TDStatus.Translating
|
status = TDStatus.Translating
|
||||||
shape: TDShape
|
shape: TDShape
|
||||||
bounds: TLBounds
|
bounds: TLBounds
|
||||||
|
|
|
@ -3,9 +3,11 @@ import { SessionType, ShapesWithProp, TldrawCommand, TldrawPatch, TDStatus } fro
|
||||||
import { TLDR } from '~state/TLDR'
|
import { TLDR } from '~state/TLDR'
|
||||||
import { BaseSession } from '../BaseSession'
|
import { BaseSession } from '../BaseSession'
|
||||||
import type { TldrawApp } from '../../internal'
|
import type { TldrawApp } from '../../internal'
|
||||||
|
import { TLPerformanceMode } from '@tldraw/core'
|
||||||
|
|
||||||
export class HandleSession extends BaseSession {
|
export class HandleSession extends BaseSession {
|
||||||
type = SessionType.Handle
|
type = SessionType.Handle
|
||||||
|
performanceMode = TLPerformanceMode.TransformSelected
|
||||||
status = TDStatus.TranslatingHandle
|
status = TDStatus.TranslatingHandle
|
||||||
commandId: string
|
commandId: string
|
||||||
topLeft: number[]
|
topLeft: number[]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Utils } from '@tldraw/core'
|
import { TLPerformanceMode, Utils } from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import { SessionType, TldrawCommand, TldrawPatch, TDShape, TDStatus } from '~types'
|
import { SessionType, TldrawCommand, TldrawPatch, TDShape, TDStatus } from '~types'
|
||||||
import { TLDR } from '~state/TLDR'
|
import { TLDR } from '~state/TLDR'
|
||||||
|
@ -8,6 +8,7 @@ import type { TldrawApp } from '../../internal'
|
||||||
export class RotateSession extends BaseSession {
|
export class RotateSession extends BaseSession {
|
||||||
type = SessionType.Rotate
|
type = SessionType.Rotate
|
||||||
status = TDStatus.Transforming
|
status = TDStatus.Transforming
|
||||||
|
performanceMode = TLPerformanceMode.TranslateSelected
|
||||||
delta = [0, 0]
|
delta = [0, 0]
|
||||||
commonBoundsCenter: number[]
|
commonBoundsCenter: number[]
|
||||||
initialAngle: number
|
initialAngle: number
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { TLBounds, TLBoundsCorner, TLBoundsEdge, Utils } from '@tldraw/core'
|
import { TLBounds, TLBoundsCorner, TLBoundsEdge, TLPerformanceMode, Utils } from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import type { TLSnapLine, TLBoundsWithCenter } from '@tldraw/core'
|
import type { TLSnapLine, TLBoundsWithCenter } from '@tldraw/core'
|
||||||
import { SessionType, TldrawCommand, TldrawPatch, TDShape, TDStatus } from '~types'
|
import { SessionType, TldrawCommand, TldrawPatch, TDShape, TDStatus } from '~types'
|
||||||
|
@ -18,6 +18,7 @@ type SnapInfo =
|
||||||
|
|
||||||
export class TransformSession extends BaseSession {
|
export class TransformSession extends BaseSession {
|
||||||
type = SessionType.Transform
|
type = SessionType.Transform
|
||||||
|
performanceMode = TLPerformanceMode.TransformSelected
|
||||||
status = TDStatus.Transforming
|
status = TDStatus.Transforming
|
||||||
scaleX = 1
|
scaleX = 1
|
||||||
scaleY = 1
|
scaleY = 1
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
Utils,
|
Utils,
|
||||||
TLBoundsWithCenter,
|
TLBoundsWithCenter,
|
||||||
TLBounds,
|
TLBounds,
|
||||||
|
TLPerformanceMode,
|
||||||
} from '@tldraw/core'
|
} from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import { SessionType, TldrawCommand, TldrawPatch, TDShape, TDStatus } from '~types'
|
import { SessionType, TldrawCommand, TldrawPatch, TDShape, TDStatus } from '~types'
|
||||||
|
@ -25,6 +26,7 @@ type SnapInfo =
|
||||||
export class TransformSingleSession extends BaseSession {
|
export class TransformSingleSession extends BaseSession {
|
||||||
type = SessionType.TransformSingle
|
type = SessionType.TransformSingle
|
||||||
status = TDStatus.Transforming
|
status = TDStatus.Transforming
|
||||||
|
performanceMode = TLPerformanceMode.TransformSelected
|
||||||
transformType: TLBoundsEdge | TLBoundsCorner
|
transformType: TLBoundsEdge | TLBoundsCorner
|
||||||
scaleX = 1
|
scaleX = 1
|
||||||
scaleY = 1
|
scaleY = 1
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||||
import { TLPageState, Utils, TLBoundsWithCenter, TLSnapLine, TLBounds } from '@tldraw/core'
|
import {
|
||||||
|
TLPageState,
|
||||||
|
Utils,
|
||||||
|
TLBoundsWithCenter,
|
||||||
|
TLSnapLine,
|
||||||
|
TLBounds,
|
||||||
|
TLPerformanceMode,
|
||||||
|
} from '@tldraw/core'
|
||||||
import { Vec } from '@tldraw/vec'
|
import { Vec } from '@tldraw/vec'
|
||||||
import {
|
import {
|
||||||
TDShape,
|
TDShape,
|
||||||
|
@ -41,6 +48,7 @@ type SnapInfo =
|
||||||
}
|
}
|
||||||
|
|
||||||
export class TranslateSession extends BaseSession {
|
export class TranslateSession extends BaseSession {
|
||||||
|
performanceMode = TLPerformanceMode.TranslateSelected
|
||||||
type = SessionType.Translate
|
type = SessionType.Translate
|
||||||
status = TDStatus.Translating
|
status = TDStatus.Translating
|
||||||
delta = [0, 0]
|
delta = [0, 0]
|
||||||
|
|
Loading…
Reference in a new issue