@tldraw/editor 4.4.0-canary.afdcafe834b3 → 4.4.0-canary.b56b70f6a630
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-cjs/index.d.ts +127 -26
- package/dist-cjs/index.js +4 -7
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +20 -8
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
- package/dist-cjs/lib/components/Shape.js +12 -17
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +26 -1
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +31 -16
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +5 -6
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultLoadingScreen.js +2 -2
- package/dist-cjs/lib/components/default-components/DefaultLoadingScreen.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +44 -15
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/bindings/BindingUtil.js.map +1 -1
- package/dist-cjs/lib/editor/derivations/bindingsIndex.js.map +1 -1
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +32 -13
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +2 -3
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +1 -1
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +1 -1
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +1 -1
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/resizeBox.js.map +1 -1
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +1 -1
- package/dist-cjs/lib/editor/types/SvgExportContext.js.map +1 -1
- package/dist-cjs/lib/exports/exportToSvg.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js.map +1 -1
- package/dist-cjs/lib/{utils/hardResetEditor.js → hooks/EditorComponentsContext.js} +14 -8
- package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +7 -0
- package/dist-cjs/lib/hooks/useCanvasEvents.js +10 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditor.js.map +1 -1
- package/dist-cjs/lib/hooks/useEditorComponents.js +4 -10
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +3 -3
- package/dist-cjs/lib/hooks/usePeerIds.js +8 -2
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/hooks/useShapeCulling.js +75 -0
- package/dist-cjs/lib/hooks/useShapeCulling.js.map +7 -0
- package/dist-cjs/lib/license/LicenseManager.js +6 -6
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/options.js +7 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +10 -5
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/utils/areShapesContentEqual.js +3 -1
- package/dist-cjs/lib/utils/areShapesContentEqual.js.map +2 -2
- package/dist-cjs/lib/utils/assets.js +4 -6
- package/dist-cjs/lib/utils/assets.js.map +2 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js +1 -2
- package/dist-cjs/lib/utils/browserCanvasMaxSize.js.map +2 -2
- package/dist-cjs/lib/utils/debug-flags.js.map +2 -2
- package/dist-cjs/lib/utils/deepLinks.js.map +1 -1
- package/dist-cjs/lib/utils/dom.js +3 -3
- package/dist-cjs/lib/utils/dom.js.map +2 -2
- package/dist-cjs/lib/utils/getIncrementedName.js +1 -1
- package/dist-cjs/lib/utils/getIncrementedName.js.map +2 -2
- package/dist-cjs/lib/utils/getPointerInfo.js.map +2 -2
- package/dist-cjs/lib/utils/getSvgPathFromPoints.js.map +1 -1
- package/dist-cjs/lib/utils/keyboard.js +2 -2
- package/dist-cjs/lib/utils/keyboard.js.map +2 -2
- package/dist-cjs/lib/utils/normalizeWheel.js +2 -5
- package/dist-cjs/lib/utils/normalizeWheel.js.map +2 -2
- package/dist-cjs/lib/utils/reorderShapes.js +6 -6
- package/dist-cjs/lib/utils/reorderShapes.js.map +2 -2
- package/dist-cjs/lib/utils/reparenting.js +3 -4
- package/dist-cjs/lib/utils/reparenting.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js.map +1 -1
- package/dist-cjs/lib/utils/rotation.js.map +1 -1
- package/dist-cjs/lib/utils/runtime.js +12 -0
- package/dist-cjs/lib/utils/runtime.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +127 -26
- package/dist-esm/index.mjs +8 -5
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +20 -8
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
- package/dist-esm/lib/components/Shape.mjs +12 -17
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +27 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +17 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +2 -3
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultLoadingScreen.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultLoadingScreen.mjs.map +1 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +44 -15
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/bindings/BindingUtil.mjs.map +1 -1
- package/dist-esm/lib/editor/derivations/bindingsIndex.mjs.map +1 -1
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +32 -13
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +2 -3
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +1 -1
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +1 -1
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/resizeBox.mjs.map +1 -1
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +1 -1
- package/dist-esm/lib/editor/types/SvgExportContext.mjs.map +1 -1
- package/dist-esm/lib/exports/exportToSvg.mjs.map +1 -1
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +1 -1
- package/dist-esm/lib/hooks/EditorComponentsContext.mjs +14 -0
- package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +7 -0
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +10 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditor.mjs.map +1 -1
- package/dist-esm/lib/hooks/useEditorComponents.mjs +12 -36
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +8 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useShapeCulling.mjs +55 -0
- package/dist-esm/lib/hooks/useShapeCulling.mjs.map +7 -0
- package/dist-esm/lib/license/LicenseManager.mjs +6 -6
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +7 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +6 -1
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/utils/areShapesContentEqual.mjs +3 -1
- package/dist-esm/lib/utils/areShapesContentEqual.mjs.map +2 -2
- package/dist-esm/lib/utils/assets.mjs +4 -6
- package/dist-esm/lib/utils/assets.mjs.map +2 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs +1 -2
- package/dist-esm/lib/utils/browserCanvasMaxSize.mjs.map +2 -2
- package/dist-esm/lib/utils/debug-flags.mjs.map +2 -2
- package/dist-esm/lib/utils/deepLinks.mjs.map +1 -1
- package/dist-esm/lib/utils/dom.mjs +3 -3
- package/dist-esm/lib/utils/dom.mjs.map +2 -2
- package/dist-esm/lib/utils/getIncrementedName.mjs +1 -1
- package/dist-esm/lib/utils/getIncrementedName.mjs.map +2 -2
- package/dist-esm/lib/utils/getPointerInfo.mjs.map +2 -2
- package/dist-esm/lib/utils/getSvgPathFromPoints.mjs.map +1 -1
- package/dist-esm/lib/utils/keyboard.mjs +2 -2
- package/dist-esm/lib/utils/keyboard.mjs.map +2 -2
- package/dist-esm/lib/utils/normalizeWheel.mjs +2 -5
- package/dist-esm/lib/utils/normalizeWheel.mjs.map +2 -2
- package/dist-esm/lib/utils/reorderShapes.mjs +6 -6
- package/dist-esm/lib/utils/reorderShapes.mjs.map +2 -2
- package/dist-esm/lib/utils/reparenting.mjs +3 -4
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs.map +1 -1
- package/dist-esm/lib/utils/rotation.mjs.map +1 -1
- package/dist-esm/lib/utils/runtime.mjs +12 -0
- package/dist-esm/lib/utils/runtime.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +22 -2
- package/package.json +10 -11
- package/src/index.ts +7 -4
- package/src/lib/TldrawEditor.tsx +34 -12
- package/src/lib/components/ErrorBoundary.tsx +1 -1
- package/src/lib/components/Shape.tsx +15 -16
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +46 -2
- package/src/lib/components/default-components/DefaultCanvas.tsx +25 -3
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +2 -3
- package/src/lib/components/default-components/DefaultLoadingScreen.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +1 -1
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +1 -1
- package/src/lib/editor/Editor.ts +74 -16
- package/src/lib/editor/bindings/BindingUtil.ts +1 -1
- package/src/lib/editor/derivations/bindingsIndex.ts +1 -1
- package/src/lib/editor/derivations/notVisibleShapes.ts +40 -18
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +0 -35
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +5 -9
- package/src/lib/editor/managers/FontManager/FontManager.ts +1 -1
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +1 -1
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +1 -1
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +2 -2
- package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +2 -2
- package/src/lib/editor/managers/TextManager/TextManager.ts +1 -1
- package/src/lib/editor/managers/TickManager/TickManager.ts +1 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +19 -5
- package/src/lib/editor/shapes/shared/resizeBox.ts +1 -1
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +2 -2
- package/src/lib/editor/types/SvgExportContext.tsx +1 -1
- package/src/lib/exports/exportToSvg.tsx +1 -1
- package/src/lib/exports/getSvgJsx.tsx +1 -1
- package/src/lib/hooks/EditorComponentsContext.tsx +63 -0
- package/src/lib/hooks/useCanvasEvents.ts +13 -2
- package/src/lib/hooks/useEditor.tsx +1 -1
- package/src/lib/hooks/useEditorComponents.tsx +20 -89
- package/src/lib/hooks/usePeerIds.ts +9 -2
- package/src/lib/hooks/useShapeCulling.tsx +98 -0
- package/src/lib/license/LicenseManager.ts +6 -6
- package/src/lib/options.ts +52 -2
- package/src/lib/primitives/Vec.ts +7 -1
- package/src/lib/utils/areShapesContentEqual.ts +9 -2
- package/src/lib/utils/assets.ts +15 -10
- package/src/lib/utils/browserCanvasMaxSize.ts +4 -2
- package/src/lib/utils/debug-flags.ts +0 -20
- package/src/lib/utils/deepLinks.ts +1 -1
- package/src/lib/utils/dom.ts +6 -7
- package/src/lib/utils/getIncrementedName.ts +1 -1
- package/src/lib/utils/getPointerInfo.ts +1 -0
- package/src/lib/utils/getSvgPathFromPoints.ts +1 -1
- package/src/lib/utils/keyboard.ts +6 -4
- package/src/lib/utils/normalizeWheel.ts +8 -8
- package/src/lib/utils/reorderShapes.ts +17 -8
- package/src/lib/utils/reparenting.ts +5 -10
- package/src/lib/utils/richText.ts +1 -1
- package/src/lib/utils/rotation.ts +1 -1
- package/src/lib/utils/runtime.ts +26 -1
- package/src/version.ts +3 -3
- package/dist-cjs/lib/utils/hardResetEditor.js.map +0 -7
- package/dist-cjs/lib/utils/refreshPage.js +0 -28
- package/dist-cjs/lib/utils/refreshPage.js.map +0 -7
- package/dist-cjs/lib/utils/window-open.js +0 -28
- package/dist-cjs/lib/utils/window-open.js.map +0 -7
- package/dist-esm/lib/utils/hardResetEditor.mjs +0 -8
- package/dist-esm/lib/utils/hardResetEditor.mjs.map +0 -7
- package/dist-esm/lib/utils/refreshPage.mjs +0 -8
- package/dist-esm/lib/utils/refreshPage.mjs.map +0 -7
- package/dist-esm/lib/utils/window-open.mjs +0 -8
- package/dist-esm/lib/utils/window-open.mjs.map +0 -7
- package/src/lib/utils/hardResetEditor.ts +0 -6
- package/src/lib/utils/refreshPage.ts +0 -6
- package/src/lib/utils/window-open.ts +0 -16
|
@@ -5,6 +5,7 @@ import { memo, useCallback, useEffect, useLayoutEffect, useRef } from 'react'
|
|
|
5
5
|
import { ShapeUtil } from '../editor/shapes/ShapeUtil'
|
|
6
6
|
import { useEditor } from '../hooks/useEditor'
|
|
7
7
|
import { useEditorComponents } from '../hooks/useEditorComponents'
|
|
8
|
+
import { useShapeCulling } from '../hooks/useShapeCulling'
|
|
8
9
|
import { Mat } from '../primitives/Mat'
|
|
9
10
|
import { areShapesContentEqual } from '../utils/areShapesContentEqual'
|
|
10
11
|
import { setStyleProperty } from '../utils/dom'
|
|
@@ -57,7 +58,6 @@ export const Shape = memo(function Shape({
|
|
|
57
58
|
height: 0,
|
|
58
59
|
x: 0,
|
|
59
60
|
y: 0,
|
|
60
|
-
isCulled: false,
|
|
61
61
|
})
|
|
62
62
|
|
|
63
63
|
useQuickReactor(
|
|
@@ -118,22 +118,21 @@ export const Shape = memo(function Shape({
|
|
|
118
118
|
setStyleProperty(bgContainer, 'z-index', backgroundIndex)
|
|
119
119
|
}, [opacity, index, backgroundIndex])
|
|
120
120
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
121
|
+
// Register container refs with the centralized culling context.
|
|
122
|
+
// This runs on mount and handles initial display state.
|
|
123
|
+
const { register, unregister } = useShapeCulling()
|
|
124
|
+
useLayoutEffect(() => {
|
|
125
|
+
const container = containerRef.current
|
|
126
|
+
if (!container) return
|
|
126
127
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
[editor]
|
|
136
|
-
)
|
|
128
|
+
// Check initial culling state and register with the context
|
|
129
|
+
const isCulled = editor.getCulledShapes().has(id)
|
|
130
|
+
register(id, container, bgContainerRef.current, isCulled)
|
|
131
|
+
|
|
132
|
+
return () => {
|
|
133
|
+
unregister(id)
|
|
134
|
+
}
|
|
135
|
+
}, [editor, id, register, unregister])
|
|
137
136
|
const annotateError = useCallback(
|
|
138
137
|
(error: any) => editor.annotateError(error, { origin: 'shape', willCrashApp: false }),
|
|
139
138
|
[editor]
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useComputed, useQuickReactor } from '@tldraw/state-react'
|
|
2
2
|
import { createComputedCache } from '@tldraw/store'
|
|
3
3
|
import { TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
4
|
-
import { dedupe
|
|
4
|
+
import { dedupe } from '@tldraw/utils'
|
|
5
5
|
import { memo, useEffect, useRef } from 'react'
|
|
6
6
|
import { Editor } from '../../editor/Editor'
|
|
7
7
|
import { TLIndicatorPath } from '../../editor/shapes/ShapeUtil'
|
|
@@ -14,6 +14,50 @@ interface CollaboratorIndicatorData {
|
|
|
14
14
|
shapeIds: TLShapeId[]
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
interface RenderData {
|
|
18
|
+
idsToDisplay: Set<TLShapeId>
|
|
19
|
+
renderingShapeIds: Set<TLShapeId>
|
|
20
|
+
hintingShapeIds: TLShapeId[]
|
|
21
|
+
collaboratorIndicators: CollaboratorIndicatorData[]
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function setsEqual<T>(a: Set<T>, b: Set<T>): boolean {
|
|
25
|
+
if (a.size !== b.size) return false
|
|
26
|
+
for (const item of a) {
|
|
27
|
+
if (!b.has(item)) return false
|
|
28
|
+
}
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function arraysEqual<T>(a: readonly T[], b: readonly T[]): boolean {
|
|
33
|
+
if (a.length !== b.length) return false
|
|
34
|
+
for (let i = 0; i < a.length; i++) {
|
|
35
|
+
if (a[i] !== b[i]) return false
|
|
36
|
+
}
|
|
37
|
+
return true
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function collaboratorIndicatorsEqual(
|
|
41
|
+
a: CollaboratorIndicatorData[],
|
|
42
|
+
b: CollaboratorIndicatorData[]
|
|
43
|
+
): boolean {
|
|
44
|
+
if (a.length !== b.length) return false
|
|
45
|
+
for (let i = 0; i < a.length; i++) {
|
|
46
|
+
if (a[i].color !== b[i].color) return false
|
|
47
|
+
if (!arraysEqual(a[i].shapeIds, b[i].shapeIds)) return false
|
|
48
|
+
}
|
|
49
|
+
return true
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function renderDataEqual(a: RenderData, b: RenderData): boolean {
|
|
53
|
+
return (
|
|
54
|
+
setsEqual(a.idsToDisplay, b.idsToDisplay) &&
|
|
55
|
+
setsEqual(a.renderingShapeIds, b.renderingShapeIds) &&
|
|
56
|
+
arraysEqual(a.hintingShapeIds, b.hintingShapeIds) &&
|
|
57
|
+
collaboratorIndicatorsEqual(a.collaboratorIndicators, b.collaboratorIndicators)
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
17
61
|
const indicatorPathCache = createComputedCache(
|
|
18
62
|
'indicatorPath',
|
|
19
63
|
(editor: Editor, shape: TLShape) => {
|
|
@@ -162,7 +206,7 @@ export const CanvasShapeIndicators = memo(function CanvasShapeIndicators() {
|
|
|
162
206
|
collaboratorIndicators,
|
|
163
207
|
}
|
|
164
208
|
},
|
|
165
|
-
{ isEqual:
|
|
209
|
+
{ isEqual: renderDataEqual },
|
|
166
210
|
[editor, activePeerIds$]
|
|
167
211
|
)
|
|
168
212
|
|
|
@@ -5,17 +5,18 @@ import { dedupe, modulate, objectMapValues } from '@tldraw/utils'
|
|
|
5
5
|
import classNames from 'classnames'
|
|
6
6
|
import { Fragment, JSX, useEffect, useRef, useState } from 'react'
|
|
7
7
|
import { tlenv } from '../../globals/environment'
|
|
8
|
+
import { useEditorComponents } from '../../hooks/EditorComponentsContext'
|
|
8
9
|
import { useCanvasEvents } from '../../hooks/useCanvasEvents'
|
|
9
10
|
import { useCoarsePointer } from '../../hooks/useCoarsePointer'
|
|
10
11
|
import { useContainer } from '../../hooks/useContainer'
|
|
11
12
|
import { useDocumentEvents } from '../../hooks/useDocumentEvents'
|
|
12
13
|
import { useEditor } from '../../hooks/useEditor'
|
|
13
|
-
import { useEditorComponents } from '../../hooks/useEditorComponents'
|
|
14
14
|
import { useFixSafariDoubleTapZoomPencilEvents } from '../../hooks/useFixSafariDoubleTapZoomPencilEvents'
|
|
15
15
|
import { useGestureEvents } from '../../hooks/useGestureEvents'
|
|
16
16
|
import { useHandleEvents } from '../../hooks/useHandleEvents'
|
|
17
17
|
import { useSharedSafeId } from '../../hooks/useSafeId'
|
|
18
18
|
import { useScreenBounds } from '../../hooks/useScreenBounds'
|
|
19
|
+
import { ShapeCullingProvider, useShapeCulling } from '../../hooks/useShapeCulling'
|
|
19
20
|
import { Box } from '../../primitives/Box'
|
|
20
21
|
import { Mat } from '../../primitives/Mat'
|
|
21
22
|
import { Vec } from '../../primitives/Vec'
|
|
@@ -428,18 +429,39 @@ function ReflowIfNeeded() {
|
|
|
428
429
|
return null
|
|
429
430
|
}
|
|
430
431
|
|
|
432
|
+
/**
|
|
433
|
+
* Centralized culling controller that updates shape container visibility.
|
|
434
|
+
* This single reactor replaces per-shape subscriptions for O(1) instead of O(N) subscriptions.
|
|
435
|
+
*/
|
|
436
|
+
function CullingController() {
|
|
437
|
+
const editor = useEditor()
|
|
438
|
+
const { updateCulling } = useShapeCulling()
|
|
439
|
+
|
|
440
|
+
useQuickReactor(
|
|
441
|
+
'update shape culling',
|
|
442
|
+
() => {
|
|
443
|
+
const culledShapes = editor.getCulledShapes()
|
|
444
|
+
updateCulling(culledShapes)
|
|
445
|
+
},
|
|
446
|
+
[editor, updateCulling]
|
|
447
|
+
)
|
|
448
|
+
|
|
449
|
+
return null
|
|
450
|
+
}
|
|
451
|
+
|
|
431
452
|
function ShapesToDisplay() {
|
|
432
453
|
const editor = useEditor()
|
|
433
454
|
|
|
434
455
|
const renderingShapes = useValue('rendering shapes', () => editor.getRenderingShapes(), [editor])
|
|
435
456
|
|
|
436
457
|
return (
|
|
437
|
-
|
|
458
|
+
<ShapeCullingProvider>
|
|
438
459
|
{renderingShapes.map((result) => (
|
|
439
460
|
<Shape key={result.id + '_shape'} {...result} />
|
|
440
461
|
))}
|
|
462
|
+
<CullingController />
|
|
441
463
|
{tlenv.isSafari && <ReflowIfNeeded />}
|
|
442
|
-
|
|
464
|
+
</ShapeCullingProvider>
|
|
443
465
|
)
|
|
444
466
|
}
|
|
445
467
|
|
|
@@ -3,10 +3,9 @@ import { noop } from '@tldraw/utils'
|
|
|
3
3
|
import classNames from 'classnames'
|
|
4
4
|
import { ComponentType, useEffect, useLayoutEffect, useRef, useState } from 'react'
|
|
5
5
|
import { Editor } from '../../editor/Editor'
|
|
6
|
+
import { useEditorComponents } from '../../hooks/EditorComponentsContext'
|
|
6
7
|
import { EditorProvider } from '../../hooks/useEditor'
|
|
7
|
-
import {
|
|
8
|
-
import { hardResetEditor } from '../../utils/hardResetEditor'
|
|
9
|
-
import { refreshPage } from '../../utils/refreshPage'
|
|
8
|
+
import { hardResetEditor, refreshPage } from '../../utils/runtime'
|
|
10
9
|
import { ErrorBoundary } from '../ErrorBoundary'
|
|
11
10
|
|
|
12
11
|
const BASE_ERROR_URL = 'https://github.com/tldraw/tldraw/issues/new'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { LoadingScreen } from '../../TldrawEditor'
|
|
2
|
-
import { useEditorComponents } from '../../hooks/
|
|
2
|
+
import { useEditorComponents } from '../../hooks/EditorComponentsContext'
|
|
3
3
|
|
|
4
4
|
/** @public @react */
|
|
5
5
|
export const DefaultLoadingScreen = () => {
|
|
@@ -4,8 +4,8 @@ import classNames from 'classnames'
|
|
|
4
4
|
import { memo, useLayoutEffect, useRef } from 'react'
|
|
5
5
|
import type { Editor } from '../../editor/Editor'
|
|
6
6
|
import { ShapeUtil } from '../../editor/shapes/ShapeUtil'
|
|
7
|
+
import { useEditorComponents } from '../../hooks/EditorComponentsContext'
|
|
7
8
|
import { useEditor } from '../../hooks/useEditor'
|
|
8
|
-
import { useEditorComponents } from '../../hooks/useEditorComponents'
|
|
9
9
|
import { OptionalErrorBoundary } from '../ErrorBoundary'
|
|
10
10
|
|
|
11
11
|
// need an extra layer of indirection here to allow hooks to be used inside the indicator render
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { useValue } from '@tldraw/state-react'
|
|
2
2
|
import { TLShapeId } from '@tldraw/tlschema'
|
|
3
3
|
import { memo, useRef } from 'react'
|
|
4
|
+
import { useEditorComponents } from '../../hooks/EditorComponentsContext'
|
|
4
5
|
import { useEditor } from '../../hooks/useEditor'
|
|
5
|
-
import { useEditorComponents } from '../../hooks/useEditorComponents'
|
|
6
6
|
|
|
7
7
|
/** @public */
|
|
8
8
|
export interface TLShapeIndicatorsProps {
|
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -134,6 +134,7 @@ import {
|
|
|
134
134
|
} from '../utils/deepLinks'
|
|
135
135
|
import { getIncrementedName } from '../utils/getIncrementedName'
|
|
136
136
|
import { getReorderingShapesChanges } from '../utils/reorderShapes'
|
|
137
|
+
import { getDroppedShapesToNewParents } from '../utils/reparenting'
|
|
137
138
|
import { TLTextOptions, TiptapEditor } from '../utils/richText'
|
|
138
139
|
import { applyRotationToSnapshotShapes, getRotationSnapshot } from '../utils/rotation'
|
|
139
140
|
import { BindingOnDeleteOptions, BindingUtil } from './bindings/BindingUtil'
|
|
@@ -153,7 +154,13 @@ import { SpatialIndexManager } from './managers/SpatialIndexManager/SpatialIndex
|
|
|
153
154
|
import { TextManager } from './managers/TextManager/TextManager'
|
|
154
155
|
import { TickManager } from './managers/TickManager/TickManager'
|
|
155
156
|
import { UserPreferencesManager } from './managers/UserPreferencesManager/UserPreferencesManager'
|
|
156
|
-
import {
|
|
157
|
+
import {
|
|
158
|
+
ShapeUtil,
|
|
159
|
+
TLEditStartInfo,
|
|
160
|
+
TLGeometryOpts,
|
|
161
|
+
TLResizeMode,
|
|
162
|
+
TLShapeUtilCanBindOpts,
|
|
163
|
+
} from './shapes/ShapeUtil'
|
|
157
164
|
import { RootState } from './tools/RootState'
|
|
158
165
|
import { StateNode, TLStateNodeConstructor } from './tools/StateNode'
|
|
159
166
|
import { TLContent } from './types/clipboard-types'
|
|
@@ -228,10 +235,17 @@ export interface TLEditorOptions {
|
|
|
228
235
|
inferDarkMode?: boolean
|
|
229
236
|
/**
|
|
230
237
|
* Options for the editor's camera.
|
|
238
|
+
*
|
|
239
|
+
* @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.
|
|
231
240
|
*/
|
|
232
241
|
cameraOptions?: Partial<TLCameraOptions>
|
|
233
|
-
textOptions?: TLTextOptions
|
|
234
242
|
options?: Partial<TldrawOptions>
|
|
243
|
+
/**
|
|
244
|
+
* Text options for the editor.
|
|
245
|
+
*
|
|
246
|
+
* @deprecated Use `options.text` instead. This prop will be removed in a future release.
|
|
247
|
+
*/
|
|
248
|
+
textOptions?: TLTextOptions
|
|
235
249
|
licenseKey?: string
|
|
236
250
|
fontAssetUrls?: { [key: string]: string | undefined }
|
|
237
251
|
/**
|
|
@@ -283,12 +297,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
283
297
|
bindingUtils,
|
|
284
298
|
tools,
|
|
285
299
|
getContainer,
|
|
300
|
+
// needs to be here for backwards compatibility with TldrawEditor
|
|
301
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
286
302
|
cameraOptions,
|
|
287
|
-
textOptions,
|
|
288
303
|
initialState,
|
|
289
304
|
autoFocus,
|
|
290
305
|
inferDarkMode,
|
|
291
|
-
options,
|
|
306
|
+
options: _options,
|
|
307
|
+
// needs to be here for backwards compatibility with TldrawEditor
|
|
308
|
+
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
309
|
+
textOptions: _textOptions,
|
|
292
310
|
getShapeVisibility,
|
|
293
311
|
fontAssetUrls,
|
|
294
312
|
}: TLEditorOptions) {
|
|
@@ -296,6 +314,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
296
314
|
|
|
297
315
|
this._getShapeVisibility = getShapeVisibility
|
|
298
316
|
|
|
317
|
+
// Merge deprecated textOptions prop with options.text
|
|
318
|
+
// options.text takes precedence over the deprecated textOptions prop
|
|
319
|
+
const options = _textOptions ? { ..._options, text: _options?.text ?? _textOptions } : _options
|
|
320
|
+
|
|
299
321
|
this.options = { ...defaultTldrawOptions, ...options }
|
|
300
322
|
|
|
301
323
|
this.store = store
|
|
@@ -314,9 +336,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
314
336
|
|
|
315
337
|
this.disposables.add(this.timers.dispose)
|
|
316
338
|
|
|
317
|
-
|
|
339
|
+
// Merge camera options: options.cameraOptions takes precedence over deprecated cameraOptions prop
|
|
340
|
+
this._cameraOptions.set({
|
|
341
|
+
...DEFAULT_CAMERA_OPTIONS,
|
|
342
|
+
...cameraOptions,
|
|
343
|
+
...options?.camera,
|
|
344
|
+
})
|
|
318
345
|
|
|
319
|
-
this._textOptions = atom('text options',
|
|
346
|
+
this._textOptions = atom('text options', options?.text ?? null)
|
|
320
347
|
|
|
321
348
|
this.user = new UserPreferencesManager(user ?? createTLUser(), inferDarkMode ?? false)
|
|
322
349
|
this.disposables.add(() => this.user.dispose())
|
|
@@ -443,6 +470,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
443
470
|
const deletedShapeIds = new Set<TLShapeId>()
|
|
444
471
|
const invalidParents = new Set<TLShapeId>()
|
|
445
472
|
let invalidBindingTypes = new Set<TLBinding['type']>()
|
|
473
|
+
|
|
446
474
|
this.disposables.add(
|
|
447
475
|
this.sideEffects.registerOperationCompleteHandler(() => {
|
|
448
476
|
// this needs to be cleared here because further effects may delete more shapes
|
|
@@ -794,6 +822,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
794
822
|
}
|
|
795
823
|
|
|
796
824
|
private readonly _getShapeVisibility?: TLEditorOptions['getShapeVisibility']
|
|
825
|
+
|
|
797
826
|
@computed
|
|
798
827
|
private getIsShapeHiddenCache() {
|
|
799
828
|
if (!this._getShapeVisibility) return null
|
|
@@ -4180,23 +4209,25 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4180
4209
|
// unmount / remount in the DOM, which is expensive; and computing visibility is
|
|
4181
4210
|
// also expensive in large projects. For this reason, we use a second bounding
|
|
4182
4211
|
// box just for rendering, and we only update after the camera stops moving.
|
|
4183
|
-
private _cameraState = atom('camera state', 'idle' as 'idle' | 'moving')
|
|
4184
4212
|
private _cameraStateTimeoutRemaining = 0
|
|
4185
4213
|
private _decayCameraStateTimeout(elapsed: number) {
|
|
4186
4214
|
this._cameraStateTimeoutRemaining -= elapsed
|
|
4187
4215
|
if (this._cameraStateTimeoutRemaining > 0) return
|
|
4188
4216
|
this.off('tick', this._decayCameraStateTimeout)
|
|
4189
|
-
this.
|
|
4217
|
+
this._setCameraState('idle')
|
|
4190
4218
|
}
|
|
4191
4219
|
private _tickCameraState() {
|
|
4192
4220
|
// always reset the timeout
|
|
4193
4221
|
this._cameraStateTimeoutRemaining = this.options.cameraMovingTimeoutMs
|
|
4194
4222
|
// If the state is idle, then start the tick
|
|
4195
|
-
if (this.
|
|
4196
|
-
this.
|
|
4223
|
+
if (this.getInstanceState().cameraState !== 'idle') return
|
|
4224
|
+
this._setCameraState('moving')
|
|
4197
4225
|
this._debouncedZoomLevel.set(unsafe__withoutCapture(() => this.getCamera().z))
|
|
4198
4226
|
this.on('tick', this._decayCameraStateTimeout)
|
|
4199
4227
|
}
|
|
4228
|
+
private _setCameraState(cameraState: 'idle' | 'moving') {
|
|
4229
|
+
this.updateInstanceState({ cameraState }, { history: 'ignore' })
|
|
4230
|
+
}
|
|
4200
4231
|
|
|
4201
4232
|
/**
|
|
4202
4233
|
* Whether the camera is moving or idle.
|
|
@@ -4209,7 +4240,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4209
4240
|
* @public
|
|
4210
4241
|
*/
|
|
4211
4242
|
getCameraState() {
|
|
4212
|
-
return this.
|
|
4243
|
+
return this.getInstanceState().cameraState
|
|
4213
4244
|
}
|
|
4214
4245
|
|
|
4215
4246
|
/**
|
|
@@ -5481,7 +5512,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
5481
5512
|
* @param bounds - The bounds to search within.
|
|
5482
5513
|
* @returns Unordered set of shape IDs within the given bounds.
|
|
5483
5514
|
*
|
|
5484
|
-
* @
|
|
5515
|
+
* @public
|
|
5485
5516
|
*/
|
|
5486
5517
|
getShapeIdsInsideBounds(bounds: Box): Set<TLShapeId> {
|
|
5487
5518
|
return this._spatialIndex.getShapeIdsInsideBounds(bounds)
|
|
@@ -6246,7 +6277,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
6246
6277
|
const toShapeType = typeof toShape === 'string' ? toShape : toShape.type
|
|
6247
6278
|
const bindingType = typeof binding === 'string' ? binding : binding.type
|
|
6248
6279
|
|
|
6249
|
-
const canBindOpts = {
|
|
6280
|
+
const canBindOpts: TLShapeUtilCanBindOpts = {
|
|
6281
|
+
fromShape: typeof fromShape === 'string' ? { type: fromShape } : fromShape,
|
|
6282
|
+
toShape: typeof toShape === 'string' ? { type: toShape } : toShape,
|
|
6283
|
+
bindingType,
|
|
6284
|
+
fromShapeType,
|
|
6285
|
+
toShapeType,
|
|
6286
|
+
}
|
|
6250
6287
|
|
|
6251
6288
|
if (fromShapeType === toShapeType) {
|
|
6252
6289
|
return this.getShapeUtil(fromShapeType).canBind(canBindOpts)
|
|
@@ -7839,6 +7876,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7839
7876
|
initialShape: options.initialShape,
|
|
7840
7877
|
initialBounds: options.initialBounds,
|
|
7841
7878
|
isAspectRatioLocked: options.isAspectRatioLocked,
|
|
7879
|
+
initialPageTransform: options.initialPageTransform,
|
|
7842
7880
|
})
|
|
7843
7881
|
|
|
7844
7882
|
// then if the shape is flipped in one axis only, we need to apply an extra rotation
|
|
@@ -9595,6 +9633,20 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9595
9633
|
return { id: s.id, type: s.type, x: s.x + localDelta.x, y: s.y + localDelta.y }
|
|
9596
9634
|
})
|
|
9597
9635
|
)
|
|
9636
|
+
|
|
9637
|
+
// If shapes were pasted onto the page (not into a specific parent),
|
|
9638
|
+
// check whether they landed inside a frame and reparent if so.
|
|
9639
|
+
if (isPageId(pasteParentId)) {
|
|
9640
|
+
const currentRootShapes = compact(rootShapes.map((s) => this.getShape(s.id)))
|
|
9641
|
+
const { reparenting } = getDroppedShapesToNewParents(this, currentRootShapes)
|
|
9642
|
+
reparenting.forEach((childrenToReparent, newParentId) => {
|
|
9643
|
+
if (childrenToReparent.length === 0) return
|
|
9644
|
+
this.reparentShapes(
|
|
9645
|
+
childrenToReparent.map((s) => s.id),
|
|
9646
|
+
newParentId
|
|
9647
|
+
)
|
|
9648
|
+
})
|
|
9649
|
+
}
|
|
9598
9650
|
})
|
|
9599
9651
|
|
|
9600
9652
|
return this
|
|
@@ -10421,9 +10473,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10421
10473
|
if (inputs.getIsPinching()) return
|
|
10422
10474
|
|
|
10423
10475
|
if (!inputs.getIsEditing()) {
|
|
10424
|
-
|
|
10425
|
-
|
|
10426
|
-
|
|
10476
|
+
// Always capture the current selection when pinch starts.
|
|
10477
|
+
// This ensures Safari (which uses gesture events instead of wheel)
|
|
10478
|
+
// doesn't restore a stale selection from an earlier pointer_down.
|
|
10479
|
+
this._selectedShapeIdsAtPointerDown = [...pageState.selectedShapeIds]
|
|
10427
10480
|
|
|
10428
10481
|
this._didPinch = true
|
|
10429
10482
|
|
|
@@ -10734,6 +10787,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10734
10787
|
this.setCurrentTool(this._restoreToolId)
|
|
10735
10788
|
}
|
|
10736
10789
|
}
|
|
10790
|
+
|
|
10791
|
+
// Clear the stashed selection so the next pinch captures fresh state.
|
|
10792
|
+
// This fixes Safari pinch zoom restoring outdated selections.
|
|
10793
|
+
this._selectedShapeIdsAtPointerDown = []
|
|
10794
|
+
|
|
10737
10795
|
break
|
|
10738
10796
|
}
|
|
10739
10797
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'
|
|
2
2
|
import { TLBinding, TLShapeId } from '@tldraw/tlschema'
|
|
3
3
|
import { objectMapValues } from '@tldraw/utils'
|
|
4
|
-
import { Editor } from '../Editor'
|
|
4
|
+
import type { Editor } from '../Editor'
|
|
5
5
|
|
|
6
6
|
type TLBindingsIndex = Map<TLShapeId, TLBinding[]>
|
|
7
7
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, isUninitialized } from '@tldraw/state'
|
|
2
|
-
import { TLShapeId } from '@tldraw/tlschema'
|
|
3
|
-
import { Editor } from '../Editor'
|
|
2
|
+
import { TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
3
|
+
import type { Editor } from '../Editor'
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Non visible shapes are shapes outside of the viewport page bounds.
|
|
@@ -9,34 +9,56 @@ import { Editor } from '../Editor'
|
|
|
9
9
|
* @returns Incremental derivation of non visible shapes.
|
|
10
10
|
*/
|
|
11
11
|
export function notVisibleShapes(editor: Editor) {
|
|
12
|
+
const emptySet = new Set<TLShapeId>()
|
|
13
|
+
|
|
12
14
|
return computed<Set<TLShapeId>>('notVisibleShapes', function (prevValue) {
|
|
13
|
-
const
|
|
15
|
+
const allShapes = editor.getCurrentPageShapes()
|
|
14
16
|
const viewportPageBounds = editor.getViewportPageBounds()
|
|
15
17
|
const visibleIds = editor.getShapeIdsInsideBounds(viewportPageBounds)
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
// Non-visible shapes are all shapes minus visible shapes
|
|
20
|
-
for (const id of allShapeIds) {
|
|
21
|
-
if (!visibleIds.has(id)) {
|
|
22
|
-
const shape = editor.getShape(id)
|
|
23
|
-
if (!shape) continue
|
|
19
|
+
let shape: TLShape | undefined
|
|
24
20
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
// Fast path: if all shapes are visible, return empty set
|
|
22
|
+
if (visibleIds.size === allShapes.length) {
|
|
23
|
+
if (isUninitialized(prevValue) || prevValue.size > 0) {
|
|
24
|
+
return emptySet
|
|
29
25
|
}
|
|
26
|
+
return prevValue
|
|
30
27
|
}
|
|
31
28
|
|
|
32
|
-
|
|
29
|
+
// First run: compute from scratch
|
|
30
|
+
if (isUninitialized(prevValue)) {
|
|
31
|
+
const nextValue = new Set<TLShapeId>()
|
|
32
|
+
for (let i = 0; i < allShapes.length; i++) {
|
|
33
|
+
shape = allShapes[i]
|
|
34
|
+
if (visibleIds.has(shape.id)) continue
|
|
35
|
+
if (!editor.getShapeUtil(shape.type).canCull(shape)) continue
|
|
36
|
+
nextValue.add(shape.id)
|
|
37
|
+
}
|
|
33
38
|
return nextValue
|
|
34
39
|
}
|
|
35
40
|
|
|
36
|
-
|
|
37
|
-
|
|
41
|
+
// Subsequent runs: single pass to collect IDs and detect changes
|
|
42
|
+
const notVisibleIds: TLShapeId[] = []
|
|
43
|
+
for (let i = 0; i < allShapes.length; i++) {
|
|
44
|
+
shape = allShapes[i]
|
|
45
|
+
if (visibleIds.has(shape.id)) continue
|
|
46
|
+
if (!editor.getShapeUtil(shape.type).canCull(shape)) continue
|
|
47
|
+
notVisibleIds.push(shape.id)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check if the result changed
|
|
51
|
+
if (notVisibleIds.length === prevValue.size) {
|
|
52
|
+
let same = true
|
|
53
|
+
for (let i = 0; i < notVisibleIds.length; i++) {
|
|
54
|
+
if (!prevValue.has(notVisibleIds[i])) {
|
|
55
|
+
same = false
|
|
56
|
+
break
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (same) return prevValue
|
|
38
60
|
}
|
|
39
61
|
|
|
40
|
-
return
|
|
62
|
+
return new Set(notVisibleIds)
|
|
41
63
|
})
|
|
42
64
|
}
|
|
@@ -240,41 +240,6 @@ describe('EdgeScrollManager', () => {
|
|
|
240
240
|
})
|
|
241
241
|
})
|
|
242
242
|
|
|
243
|
-
describe('camera movement conditions', () => {
|
|
244
|
-
it('should not move camera when not dragging', () => {
|
|
245
|
-
editor.inputs.setIsDragging(false)
|
|
246
|
-
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
247
|
-
|
|
248
|
-
edgeScrollManager.updateEdgeScrolling(300)
|
|
249
|
-
|
|
250
|
-
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
251
|
-
})
|
|
252
|
-
|
|
253
|
-
it('should not move camera when panning', () => {
|
|
254
|
-
editor.inputs.setIsPanning(true)
|
|
255
|
-
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
256
|
-
|
|
257
|
-
edgeScrollManager.updateEdgeScrolling(300)
|
|
258
|
-
|
|
259
|
-
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
260
|
-
})
|
|
261
|
-
|
|
262
|
-
it('should not move camera when camera is locked', () => {
|
|
263
|
-
editor.getCameraOptions.mockReturnValue({
|
|
264
|
-
isLocked: true,
|
|
265
|
-
panSpeed: 1,
|
|
266
|
-
zoomSpeed: 1,
|
|
267
|
-
zoomSteps: [1],
|
|
268
|
-
wheelBehavior: 'pan' as const,
|
|
269
|
-
})
|
|
270
|
-
mockInputs.setCurrentScreenPoint(new Vec(5, 300))
|
|
271
|
-
|
|
272
|
-
edgeScrollManager.updateEdgeScrolling(300)
|
|
273
|
-
|
|
274
|
-
expect(editor.setCamera).not.toHaveBeenCalled()
|
|
275
|
-
})
|
|
276
|
-
})
|
|
277
|
-
|
|
278
243
|
describe('camera movement calculation', () => {
|
|
279
244
|
it('should calculate scroll speed based on user preference', () => {
|
|
280
245
|
editor.user.getEdgeScrollSpeed.mockReturnValue(2)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Vec } from '../../../primitives/Vec'
|
|
2
2
|
import { EASINGS } from '../../../primitives/easings'
|
|
3
|
-
import { Editor } from '../../Editor'
|
|
3
|
+
import type { Editor } from '../../Editor'
|
|
4
4
|
|
|
5
5
|
/** @public */
|
|
6
6
|
export class EdgeScrollManager {
|
|
@@ -21,6 +21,9 @@ export class EdgeScrollManager {
|
|
|
21
21
|
*/
|
|
22
22
|
updateEdgeScrolling(elapsed: number) {
|
|
23
23
|
const { editor } = this
|
|
24
|
+
|
|
25
|
+
if (editor.getCameraOptions().isLocked) return
|
|
26
|
+
|
|
24
27
|
const edgeScrollProximityFactor = this.getEdgeScroll()
|
|
25
28
|
if (edgeScrollProximityFactor.x === 0 && edgeScrollProximityFactor.y === 0) {
|
|
26
29
|
if (this._isEdgeScrolling) {
|
|
@@ -106,15 +109,8 @@ export class EdgeScrollManager {
|
|
|
106
109
|
* @public
|
|
107
110
|
*/
|
|
108
111
|
private moveCameraWhenCloseToEdge(proximityFactor: { x: number; y: number }) {
|
|
109
|
-
const { editor } = this
|
|
110
|
-
if (
|
|
111
|
-
!editor.inputs.getIsDragging() ||
|
|
112
|
-
editor.inputs.getIsPanning() ||
|
|
113
|
-
editor.getCameraOptions().isLocked
|
|
114
|
-
)
|
|
115
|
-
return
|
|
116
|
-
|
|
117
112
|
if (proximityFactor.x === 0 && proximityFactor.y === 0) return
|
|
113
|
+
const { editor } = this
|
|
118
114
|
|
|
119
115
|
const screenBounds = editor.getViewportScreenBounds()
|
|
120
116
|
|
|
@@ -4,7 +4,7 @@ import { TLINSTANCE_ID, TLPOINTER_ID } from '@tldraw/tlschema'
|
|
|
4
4
|
import { INTERNAL_POINTER_IDS } from '../../../constants'
|
|
5
5
|
import { Vec } from '../../../primitives/Vec'
|
|
6
6
|
import { isAccelKey } from '../../../utils/keyboard'
|
|
7
|
-
import { Editor } from '../../Editor'
|
|
7
|
+
import type { Editor } from '../../Editor'
|
|
8
8
|
import { TLPinchEventInfo, TLPointerEventInfo, TLWheelEventInfo } from '../../types/event-types'
|
|
9
9
|
|
|
10
10
|
/** @public */
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TLScribble, VecModel } from '@tldraw/tlschema'
|
|
2
2
|
import { uniqueId } from '@tldraw/utils'
|
|
3
3
|
import { Vec } from '../../../primitives/Vec'
|
|
4
|
-
import { Editor } from '../../Editor'
|
|
4
|
+
import type { Editor } from '../../Editor'
|
|
5
5
|
|
|
6
6
|
/** @public */
|
|
7
7
|
export interface ScribbleItem {
|
|
@@ -12,8 +12,8 @@ import {
|
|
|
12
12
|
import { Mat } from '../../../primitives/Mat'
|
|
13
13
|
import { Vec } from '../../../primitives/Vec'
|
|
14
14
|
import { rangeIntersection, rangesOverlap } from '../../../primitives/utils'
|
|
15
|
-
import { Editor } from '../../Editor'
|
|
16
|
-
import {
|
|
15
|
+
import type { Editor } from '../../Editor'
|
|
16
|
+
import type {
|
|
17
17
|
GapsSnapIndicator,
|
|
18
18
|
PointsSnapIndicator,
|
|
19
19
|
SnapData,
|