@tldraw/editor 4.3.0-canary.9c474ef3fad5 → 4.3.0-canary.a2419250444e
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 +387 -118
- package/dist-cjs/index.js +5 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/ErrorBoundary.js.map +1 -1
- package/dist-cjs/lib/components/GeometryDebuggingView.js +1 -17
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +2 -2
- package/dist-cjs/lib/constants.js +1 -3
- package/dist-cjs/lib/constants.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +247 -273
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +18 -17
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +3 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js +12 -3
- package/dist-cjs/lib/editor/derivations/parentsToChildren.js.map +2 -2
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js +1 -1
- package/dist-cjs/lib/editor/managers/ClickManager/ClickManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +5 -6
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js +591 -0
- package/dist-cjs/lib/editor/managers/InputsManager/InputsManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/SnapManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js +1 -22
- package/dist-cjs/lib/editor/managers/TickManager/TickManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +31 -23
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js +3 -3
- package/dist-cjs/lib/editor/tools/BaseBoxShapeTool/children/Pointing.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +1 -1
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/lib/hooks/useEvent.js +1 -1
- package/dist-cjs/lib/hooks/useEvent.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useGestureEvents.js +1 -1
- package/dist-cjs/lib/hooks/useGestureEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
- package/dist-cjs/lib/hooks/useStateAttribute.js +4 -1
- package/dist-cjs/lib/hooks/useStateAttribute.js.map +2 -2
- package/dist-cjs/lib/hooks/useTransform.js.map +1 -1
- package/dist-cjs/lib/options.js +4 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +3 -0
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +1 -0
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/utils/rotation.js +1 -1
- package/dist-cjs/lib/utils/rotation.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 +387 -118
- package/dist-esm/index.mjs +5 -1
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/ErrorBoundary.mjs.map +1 -1
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +1 -17
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +2 -2
- package/dist-esm/lib/constants.mjs +1 -3
- package/dist-esm/lib/constants.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +248 -276
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +18 -17
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +3 -3
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs +13 -4
- package/dist-esm/lib/editor/derivations/parentsToChildren.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/ClickManager/ClickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +5 -6
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs +573 -0
- package/dist-esm/lib/editor/managers/InputsManager/InputsManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/SnapManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs +1 -22
- package/dist-esm/lib/editor/managers/TickManager/TickManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +31 -23
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs +3 -3
- package/dist-esm/lib/editor/tools/BaseBoxShapeTool/children/Pointing.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +1 -1
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEvent.mjs +1 -1
- package/dist-esm/lib/hooks/useEvent.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useGestureEvents.mjs +1 -1
- package/dist-esm/lib/hooks/useGestureEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useStateAttribute.mjs +4 -1
- package/dist-esm/lib/hooks/useStateAttribute.mjs.map +2 -2
- package/dist-esm/lib/hooks/useTransform.mjs.map +1 -1
- package/dist-esm/lib/options.mjs +4 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +3 -0
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +1 -0
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/utils/rotation.mjs +1 -1
- package/dist-esm/lib/utils/rotation.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +6 -8
- package/package.json +18 -16
- package/src/index.ts +3 -0
- package/src/lib/components/ErrorBoundary.tsx +1 -1
- package/src/lib/components/GeometryDebuggingView.tsx +1 -19
- package/src/lib/config/TLUserPreferences.test.ts +40 -0
- package/src/lib/constants.ts +0 -2
- package/src/lib/editor/Editor.test.ts +140 -0
- package/src/lib/editor/Editor.ts +300 -316
- package/src/lib/editor/derivations/notVisibleShapes.ts +37 -23
- package/src/lib/editor/derivations/parentsToChildren.ts +18 -7
- package/src/lib/editor/managers/ClickManager/ClickManager.test.ts +17 -31
- package/src/lib/editor/managers/ClickManager/ClickManager.ts +1 -1
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +129 -79
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +10 -6
- package/src/lib/editor/managers/InputsManager/InputsManager.ts +566 -0
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -4
- package/src/lib/editor/managers/SnapManager/SnapManager.test.ts +12 -0
- package/src/lib/editor/managers/SnapManager/SnapManager.ts +1 -1
- package/src/lib/editor/managers/TickManager/TickManager.test.ts +40 -107
- package/src/lib/editor/managers/TickManager/TickManager.ts +2 -32
- package/src/lib/editor/shapes/ShapeUtil.ts +67 -24
- package/src/lib/editor/tools/BaseBoxShapeTool/children/Pointing.ts +3 -3
- package/src/lib/exports/parseCss.test.ts +1 -0
- package/src/lib/exports/parseCss.ts +1 -1
- package/src/lib/hooks/useEvent.tsx +1 -1
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +1 -1
- package/src/lib/hooks/useGestureEvents.ts +2 -2
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +1 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -1
- package/src/lib/hooks/useScreenBounds.ts +1 -1
- package/src/lib/hooks/useStateAttribute.ts +4 -1
- package/src/lib/hooks/useTransform.ts +1 -1
- package/src/lib/options.ts +19 -0
- package/src/lib/primitives/Box.ts +9 -0
- package/src/lib/primitives/geometry/Geometry2d.ts +1 -0
- package/src/lib/utils/rotation.ts +1 -1
- package/src/version.ts +3 -3
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -42,7 +42,6 @@ import {
|
|
|
42
42
|
TLInstance,
|
|
43
43
|
TLInstancePageState,
|
|
44
44
|
TLInstancePresence,
|
|
45
|
-
TLPOINTER_ID,
|
|
46
45
|
TLPage,
|
|
47
46
|
TLPageId,
|
|
48
47
|
TLParentId,
|
|
@@ -109,7 +108,6 @@ import {
|
|
|
109
108
|
MIDDLE_MOUSE_BUTTON,
|
|
110
109
|
RIGHT_MOUSE_BUTTON,
|
|
111
110
|
STYLUS_ERASER_BUTTON,
|
|
112
|
-
ZOOM_TO_FIT_PADDING,
|
|
113
111
|
} from '../constants'
|
|
114
112
|
import { exportToSvg } from '../exports/exportToSvg'
|
|
115
113
|
import { getSvgAsImage } from '../exports/getSvgAsImage'
|
|
@@ -135,7 +133,6 @@ import {
|
|
|
135
133
|
parseDeepLinkString,
|
|
136
134
|
} from '../utils/deepLinks'
|
|
137
135
|
import { getIncrementedName } from '../utils/getIncrementedName'
|
|
138
|
-
import { isAccelKey } from '../utils/keyboard'
|
|
139
136
|
import { getReorderingShapesChanges } from '../utils/reorderShapes'
|
|
140
137
|
import { TLTextOptions, TiptapEditor } from '../utils/richText'
|
|
141
138
|
import { applyRotationToSnapshotShapes, getRotationSnapshot } from '../utils/rotation'
|
|
@@ -149,22 +146,18 @@ import { EdgeScrollManager } from './managers/EdgeScrollManager/EdgeScrollManage
|
|
|
149
146
|
import { FocusManager } from './managers/FocusManager/FocusManager'
|
|
150
147
|
import { FontManager } from './managers/FontManager/FontManager'
|
|
151
148
|
import { HistoryManager } from './managers/HistoryManager/HistoryManager'
|
|
149
|
+
import { InputsManager } from './managers/InputsManager/InputsManager'
|
|
152
150
|
import { ScribbleManager } from './managers/ScribbleManager/ScribbleManager'
|
|
153
151
|
import { SnapManager } from './managers/SnapManager/SnapManager'
|
|
154
152
|
import { TextManager } from './managers/TextManager/TextManager'
|
|
155
153
|
import { TickManager } from './managers/TickManager/TickManager'
|
|
156
154
|
import { UserPreferencesManager } from './managers/UserPreferencesManager/UserPreferencesManager'
|
|
157
|
-
import { ShapeUtil, TLGeometryOpts, TLResizeMode } from './shapes/ShapeUtil'
|
|
155
|
+
import { ShapeUtil, TLEditStartInfo, TLGeometryOpts, TLResizeMode } from './shapes/ShapeUtil'
|
|
158
156
|
import { RootState } from './tools/RootState'
|
|
159
157
|
import { StateNode, TLStateNodeConstructor } from './tools/StateNode'
|
|
160
158
|
import { TLContent } from './types/clipboard-types'
|
|
161
159
|
import { TLEventMap } from './types/emit-types'
|
|
162
|
-
import {
|
|
163
|
-
TLEventInfo,
|
|
164
|
-
TLPinchEventInfo,
|
|
165
|
-
TLPointerEventInfo,
|
|
166
|
-
TLWheelEventInfo,
|
|
167
|
-
} from './types/event-types'
|
|
160
|
+
import { TLEventInfo, TLPointerEventInfo } from './types/event-types'
|
|
168
161
|
import { TLExternalAsset, TLExternalContent } from './types/external-content'
|
|
169
162
|
import { TLHistoryBatchOptions } from './types/history-types'
|
|
170
163
|
import {
|
|
@@ -195,7 +188,7 @@ export type TLResizeShapeOptions = Partial<{
|
|
|
195
188
|
/** @public */
|
|
196
189
|
export interface TLEditorOptions {
|
|
197
190
|
/**
|
|
198
|
-
* The Store instance to use for keeping the
|
|
191
|
+
* The Store instance to use for keeping the editor's data. This may be prepopulated, e.g. by loading
|
|
199
192
|
* from a server or database.
|
|
200
193
|
*/
|
|
201
194
|
store: TLStore
|
|
@@ -333,6 +326,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
333
326
|
|
|
334
327
|
this._tickManager = new TickManager(this)
|
|
335
328
|
|
|
329
|
+
this.inputs = new InputsManager(this)
|
|
330
|
+
|
|
336
331
|
class NewRoot extends RootState {
|
|
337
332
|
static override initial = initialState ?? ''
|
|
338
333
|
}
|
|
@@ -867,7 +862,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
867
862
|
}
|
|
868
863
|
|
|
869
864
|
/**
|
|
870
|
-
* A set of functions to call when the
|
|
865
|
+
* A set of functions to call when the editor is disposed.
|
|
871
866
|
*
|
|
872
867
|
* @public
|
|
873
868
|
*/
|
|
@@ -880,11 +875,21 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
880
875
|
*/
|
|
881
876
|
isDisposed = false
|
|
882
877
|
|
|
883
|
-
/**
|
|
884
|
-
|
|
878
|
+
/**
|
|
879
|
+
* A manager for the editor's tick events.
|
|
880
|
+
*
|
|
881
|
+
* @internal */
|
|
882
|
+
private readonly _tickManager: TickManager
|
|
885
883
|
|
|
886
884
|
/**
|
|
887
|
-
* A manager for the
|
|
885
|
+
* A manager for the editor's input state.
|
|
886
|
+
*
|
|
887
|
+
* @public
|
|
888
|
+
*/
|
|
889
|
+
readonly inputs: InputsManager
|
|
890
|
+
|
|
891
|
+
/**
|
|
892
|
+
* A manager for the editor's snapping feature.
|
|
888
893
|
*
|
|
889
894
|
* @public
|
|
890
895
|
*/
|
|
@@ -1061,7 +1066,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1061
1066
|
/* --------------------- History -------------------- */
|
|
1062
1067
|
|
|
1063
1068
|
/**
|
|
1064
|
-
* A manager for the
|
|
1069
|
+
* A manager for the editor's history.
|
|
1065
1070
|
*
|
|
1066
1071
|
* @readonly
|
|
1067
1072
|
*/
|
|
@@ -1085,14 +1090,18 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1085
1090
|
}
|
|
1086
1091
|
|
|
1087
1092
|
/**
|
|
1088
|
-
* Whether the
|
|
1093
|
+
* Whether the editor can undo.
|
|
1089
1094
|
*
|
|
1090
1095
|
* @public
|
|
1091
1096
|
*/
|
|
1092
|
-
@computed
|
|
1097
|
+
@computed canUndo(): boolean {
|
|
1093
1098
|
return this.history.getNumUndos() > 0
|
|
1094
1099
|
}
|
|
1095
1100
|
|
|
1101
|
+
getCanUndo() {
|
|
1102
|
+
return this.canUndo()
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1096
1105
|
/**
|
|
1097
1106
|
* Redo to the next mark.
|
|
1098
1107
|
*
|
|
@@ -1110,20 +1119,24 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1110
1119
|
return this
|
|
1111
1120
|
}
|
|
1112
1121
|
|
|
1113
|
-
clearHistory() {
|
|
1114
|
-
this.history.clear()
|
|
1115
|
-
return this
|
|
1116
|
-
}
|
|
1117
|
-
|
|
1118
1122
|
/**
|
|
1119
|
-
* Whether the
|
|
1123
|
+
* Whether the editor can redo.
|
|
1120
1124
|
*
|
|
1121
1125
|
* @public
|
|
1122
1126
|
*/
|
|
1123
|
-
@computed
|
|
1127
|
+
@computed canRedo(): boolean {
|
|
1124
1128
|
return this.history.getNumRedos() > 0
|
|
1125
1129
|
}
|
|
1126
1130
|
|
|
1131
|
+
getCanRedo() {
|
|
1132
|
+
return this.canRedo()
|
|
1133
|
+
}
|
|
1134
|
+
|
|
1135
|
+
clearHistory() {
|
|
1136
|
+
this.history.clear()
|
|
1137
|
+
return this
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1127
1140
|
/**
|
|
1128
1141
|
* Create a new "mark", or stopping point, in the undo redo history. Creating a mark will clear
|
|
1129
1142
|
* any redos. You typically want to do this just before a user interaction begins or is handled.
|
|
@@ -1297,7 +1310,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1297
1310
|
}),
|
|
1298
1311
|
selectionCount: this.getSelectedShapes().length,
|
|
1299
1312
|
editingShape: editingShapeId ? this.getShape(editingShapeId) : undefined,
|
|
1300
|
-
inputs: this.inputs,
|
|
1313
|
+
inputs: this.inputs.toJson(),
|
|
1301
1314
|
pageState: this.getCurrentPageState(),
|
|
1302
1315
|
instanceState: this.getInstanceState(),
|
|
1303
1316
|
collaboratorCount: this.getCollaboratorsOnCurrentPage().length,
|
|
@@ -1322,7 +1335,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1322
1335
|
* we're in a transaction that's about to be rolled back due to the same error we're currently
|
|
1323
1336
|
* reporting.
|
|
1324
1337
|
*
|
|
1325
|
-
* Instead, to listen to changes to this value, you need to listen to
|
|
1338
|
+
* Instead, to listen to changes to this value, you need to listen to editor's `crash` event.
|
|
1326
1339
|
*
|
|
1327
1340
|
* @internal
|
|
1328
1341
|
*/
|
|
@@ -2025,7 +2038,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2025
2038
|
}
|
|
2026
2039
|
|
|
2027
2040
|
/**
|
|
2028
|
-
* The id of the
|
|
2041
|
+
* The id of the editor's only selected shape.
|
|
2029
2042
|
*
|
|
2030
2043
|
* @returns Null if there is no shape or more than one selected shape, otherwise the selected shape's id.
|
|
2031
2044
|
*
|
|
@@ -2037,7 +2050,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2037
2050
|
}
|
|
2038
2051
|
|
|
2039
2052
|
/**
|
|
2040
|
-
* The
|
|
2053
|
+
* The editor's only selected shape.
|
|
2041
2054
|
*
|
|
2042
2055
|
* @returns Null if there is no shape or more than one selected shape, otherwise the selected shape.
|
|
2043
2056
|
*
|
|
@@ -2278,6 +2291,29 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2278
2291
|
return editingShapeId ? this.getShape(editingShapeId) : undefined
|
|
2279
2292
|
}
|
|
2280
2293
|
|
|
2294
|
+
/**
|
|
2295
|
+
* Whether the shape can be edited.
|
|
2296
|
+
*
|
|
2297
|
+
* @param shape - The shape (or shape id) to check if it can be edited.
|
|
2298
|
+
* @param info - The info about the edit start.
|
|
2299
|
+
*
|
|
2300
|
+
* @public
|
|
2301
|
+
* @returns true if the shape can be edited, false otherwise.
|
|
2302
|
+
*/
|
|
2303
|
+
canEditShape<T extends TLShape | TLShapeId>(shape: T | null, info?: TLEditStartInfo): shape is T {
|
|
2304
|
+
const id = typeof shape === 'string' ? shape : (shape?.id ?? null)
|
|
2305
|
+
if (!id) return false // no shape
|
|
2306
|
+
if (id === this.getEditingShapeId()) return false // already editing this shape
|
|
2307
|
+
const _shape = this.getShape(id)
|
|
2308
|
+
if (!_shape) return false // no shape
|
|
2309
|
+
const util = this.getShapeUtil(_shape)
|
|
2310
|
+
const _info: TLEditStartInfo = info ?? { type: 'unknown' }
|
|
2311
|
+
if (!util.canEdit(_shape, _info)) return false // shape is not editable
|
|
2312
|
+
if (this.getIsReadonly() && !util.canEditInReadonly(_shape)) return false // readonly and no exception
|
|
2313
|
+
if (this.isShapeOrAncestorLocked(_shape) && !util.canEditWhileLocked(_shape)) return false // locked and no exception. Note here: we're not distinguishing between a locked shape and a shape that is the descendant of a locked shape.
|
|
2314
|
+
return true // shape is editable
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2281
2317
|
/**
|
|
2282
2318
|
* Set the current editing shape.
|
|
2283
2319
|
*
|
|
@@ -2293,44 +2329,59 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2293
2329
|
*/
|
|
2294
2330
|
setEditingShape(shape: TLShapeId | TLShape | null): this {
|
|
2295
2331
|
const id = typeof shape === 'string' ? shape : (shape?.id ?? null)
|
|
2296
|
-
this.setRichTextEditor(null)
|
|
2297
|
-
const prevEditingShapeId = this.getEditingShapeId()
|
|
2298
|
-
if (id !== prevEditingShapeId) {
|
|
2299
|
-
if (id) {
|
|
2300
|
-
const shape = this.getShape(id)
|
|
2301
|
-
if (shape && this.getShapeUtil(shape).canEdit(shape)) {
|
|
2302
|
-
this.run(
|
|
2303
|
-
() => {
|
|
2304
|
-
this._updateCurrentPageState({ editingShapeId: id })
|
|
2305
|
-
if (prevEditingShapeId) {
|
|
2306
|
-
const prevEditingShape = this.getShape(prevEditingShapeId)
|
|
2307
|
-
if (prevEditingShape) {
|
|
2308
|
-
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape)
|
|
2309
|
-
}
|
|
2310
|
-
}
|
|
2311
|
-
this.getShapeUtil(shape).onEditStart?.(shape)
|
|
2312
|
-
},
|
|
2313
|
-
{ history: 'ignore' }
|
|
2314
|
-
)
|
|
2315
|
-
return this
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
2332
|
|
|
2319
|
-
|
|
2333
|
+
if (!id) {
|
|
2334
|
+
// setting the editing shape to null
|
|
2320
2335
|
this.run(
|
|
2321
2336
|
() => {
|
|
2322
|
-
|
|
2323
|
-
this.
|
|
2337
|
+
// Clean up the previous editing shape
|
|
2338
|
+
const prevEditingShapeId = this.getEditingShapeId()
|
|
2324
2339
|
if (prevEditingShapeId) {
|
|
2325
2340
|
const prevEditingShape = this.getShape(prevEditingShapeId)
|
|
2326
2341
|
if (prevEditingShape) {
|
|
2327
2342
|
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape)
|
|
2328
2343
|
}
|
|
2329
2344
|
}
|
|
2345
|
+
|
|
2346
|
+
// Clean up the editing shape state and rich text editor
|
|
2347
|
+
this._updateCurrentPageState({ editingShapeId: null })
|
|
2348
|
+
this._currentRichTextEditor.set(null)
|
|
2330
2349
|
},
|
|
2331
2350
|
{ history: 'ignore' }
|
|
2332
2351
|
)
|
|
2352
|
+
|
|
2353
|
+
return this
|
|
2333
2354
|
}
|
|
2355
|
+
|
|
2356
|
+
// id was provided but the next editing shape was not editable or didn't exist, so do nothing
|
|
2357
|
+
if (!this.canEditShape(id)) return this
|
|
2358
|
+
|
|
2359
|
+
// id was provided and the next editing shape is editable, so set the rich text editor to null
|
|
2360
|
+
this.run(
|
|
2361
|
+
() => {
|
|
2362
|
+
// Clean up the previous editing shape
|
|
2363
|
+
const prevEditingShapeId = this.getEditingShapeId()
|
|
2364
|
+
if (prevEditingShapeId) {
|
|
2365
|
+
const prevEditingShape = this.getShape(prevEditingShapeId)
|
|
2366
|
+
if (prevEditingShape) {
|
|
2367
|
+
this.getShapeUtil(prevEditingShape).onEditEnd?.(prevEditingShape)
|
|
2368
|
+
}
|
|
2369
|
+
}
|
|
2370
|
+
|
|
2371
|
+
// Clean up the editing shape state and rich text editor
|
|
2372
|
+
this._updateCurrentPageState({ editingShapeId: null })
|
|
2373
|
+
this._currentRichTextEditor.set(null)
|
|
2374
|
+
|
|
2375
|
+
// Set the new editing shape
|
|
2376
|
+
this.select(id)
|
|
2377
|
+
this._updateCurrentPageState({ editingShapeId: id })
|
|
2378
|
+
|
|
2379
|
+
const nextEditingShape = this.getShape(id)! // shape should be there because canEditShape checked it. Possible small chance that onEditEnd deleted it?
|
|
2380
|
+
this.getShapeUtil(nextEditingShape).onEditStart?.(nextEditingShape)
|
|
2381
|
+
},
|
|
2382
|
+
{ history: 'ignore' }
|
|
2383
|
+
)
|
|
2384
|
+
|
|
2334
2385
|
return this
|
|
2335
2386
|
}
|
|
2336
2387
|
|
|
@@ -2534,6 +2585,26 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2534
2585
|
return this.getCurrentPageState().croppingShapeId
|
|
2535
2586
|
}
|
|
2536
2587
|
|
|
2588
|
+
/**
|
|
2589
|
+
* Whether the shape can be cropped.
|
|
2590
|
+
*
|
|
2591
|
+
* @param shape - The shape (or shape id) to check if it can be cropped.
|
|
2592
|
+
*
|
|
2593
|
+
* @public
|
|
2594
|
+
* @returns true if the shape can be cropped, false otherwise.
|
|
2595
|
+
*/
|
|
2596
|
+
canCropShape<T extends TLShape | TLShapeId>(shape: T | null): shape is T {
|
|
2597
|
+
if (!shape) return false
|
|
2598
|
+
const id = typeof shape === 'string' ? shape : (shape?.id ?? null)
|
|
2599
|
+
if (!id) return false
|
|
2600
|
+
const _shape = this.getShape(id)
|
|
2601
|
+
if (!_shape) return false
|
|
2602
|
+
const util = this.getShapeUtil(_shape)
|
|
2603
|
+
if (!util.canCrop(_shape)) return false
|
|
2604
|
+
if (this.isShapeOrAncestorLocked(_shape)) return false
|
|
2605
|
+
return true
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2537
2608
|
/**
|
|
2538
2609
|
* Set the current cropping shape.
|
|
2539
2610
|
*
|
|
@@ -2555,12 +2626,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
2555
2626
|
() => {
|
|
2556
2627
|
if (!id) {
|
|
2557
2628
|
this.updateCurrentPageState({ croppingShapeId: null })
|
|
2558
|
-
} else {
|
|
2559
|
-
|
|
2560
|
-
const util = this.getShapeUtil(shape)
|
|
2561
|
-
if (shape && util.canCrop(shape)) {
|
|
2562
|
-
this.updateCurrentPageState({ croppingShapeId: id })
|
|
2563
|
-
}
|
|
2629
|
+
} else if (this.canCropShape(id)) {
|
|
2630
|
+
this.updateCurrentPageState({ croppingShapeId: id })
|
|
2564
2631
|
}
|
|
2565
2632
|
},
|
|
2566
2633
|
{ history: 'ignore' }
|
|
@@ -3042,7 +3109,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3042
3109
|
|
|
3043
3110
|
// Dispatch a new pointer move because the pointer's page will have changed
|
|
3044
3111
|
// (its screen position will compute to a new page position given the new camera position)
|
|
3045
|
-
const
|
|
3112
|
+
const currentScreenPoint = this.inputs.getCurrentScreenPoint()
|
|
3113
|
+
const currentPagePoint = this.inputs.getCurrentPagePoint()
|
|
3046
3114
|
|
|
3047
3115
|
// compare the next page point (derived from the current camera) to the current page point
|
|
3048
3116
|
if (
|
|
@@ -3206,7 +3274,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3206
3274
|
* ```ts
|
|
3207
3275
|
* editor.zoomIn()
|
|
3208
3276
|
* editor.zoomIn(editor.getViewportScreenCenter(), { animation: { duration: 200 } })
|
|
3209
|
-
* editor.zoomIn(editor.inputs.
|
|
3277
|
+
* editor.zoomIn(editor.inputs.getCurrentScreenPoint(), { animation: { duration: 200 } })
|
|
3210
3278
|
* ```
|
|
3211
3279
|
*
|
|
3212
3280
|
* @param point - The screen point to zoom in on. Defaults to the screen center
|
|
@@ -3251,7 +3319,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3251
3319
|
* ```ts
|
|
3252
3320
|
* editor.zoomOut()
|
|
3253
3321
|
* editor.zoomOut(editor.getViewportScreenCenter(), { animation: { duration: 120 } })
|
|
3254
|
-
* editor.zoomOut(editor.inputs.
|
|
3322
|
+
* editor.zoomOut(editor.inputs.getCurrentScreenPoint(), { animation: { duration: 120 } })
|
|
3255
3323
|
* ```
|
|
3256
3324
|
*
|
|
3257
3325
|
* @param point - The point to zoom out on. Defaults to the viewport screen center.
|
|
@@ -3308,10 +3376,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3308
3376
|
|
|
3309
3377
|
const selectionPageBounds = this.getSelectionPageBounds()
|
|
3310
3378
|
if (selectionPageBounds) {
|
|
3311
|
-
this.
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3379
|
+
const currentZoom = this.getZoomLevel()
|
|
3380
|
+
// If already at 100%, zoom to fit the selection in the viewport
|
|
3381
|
+
// Otherwise, zoom to 100% centered on the selection
|
|
3382
|
+
if (Math.abs(currentZoom - 1) < 0.01) {
|
|
3383
|
+
this.zoomToBounds(selectionPageBounds, opts)
|
|
3384
|
+
} else {
|
|
3385
|
+
this.zoomToBounds(selectionPageBounds, {
|
|
3386
|
+
targetZoom: 1,
|
|
3387
|
+
...opts,
|
|
3388
|
+
})
|
|
3389
|
+
}
|
|
3315
3390
|
}
|
|
3316
3391
|
return this
|
|
3317
3392
|
}
|
|
@@ -3368,7 +3443,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
3368
3443
|
|
|
3369
3444
|
const viewportScreenBounds = this.getViewportScreenBounds()
|
|
3370
3445
|
|
|
3371
|
-
const inset =
|
|
3446
|
+
const inset =
|
|
3447
|
+
opts?.inset ?? Math.min(this.options.zoomToFitPadding, viewportScreenBounds.width * 0.28)
|
|
3372
3448
|
|
|
3373
3449
|
const baseZoom = this.getBaseZoom()
|
|
3374
3450
|
const zoomMin = cameraOptions.zoomSteps[0]
|
|
@@ -7698,8 +7774,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7698
7774
|
// then if the shape is flipped in one axis only, we need to apply an extra rotation
|
|
7699
7775
|
// to make sure the shape is mirrored correctly
|
|
7700
7776
|
if (Math.sign(scale.x) * Math.sign(scale.y) < 0) {
|
|
7701
|
-
|
|
7702
|
-
rotation
|
|
7777
|
+
// We need to compute the new local rotation that will result in the negated page rotation.
|
|
7778
|
+
// For a shape with local rotation `localRot` and parent page rotation `parentRot`:
|
|
7779
|
+
// - pageRot = parentRot + localRot
|
|
7780
|
+
// - newPageRot = -pageRot (we want to negate the page rotation)
|
|
7781
|
+
// - newPageRot = parentRot + newLocalRot (parent hasn't changed)
|
|
7782
|
+
// - Therefore: newLocalRot = -pageRot - parentRot = -(parentRot + localRot) - parentRot = -localRot - 2*parentRot
|
|
7783
|
+
const parentRotation = this.getShapeParentTransform(id).rotation()
|
|
7784
|
+
const rotation = -options.initialShape.rotation - 2 * parentRotation
|
|
7703
7785
|
this.updateShapes([{ id, type, rotation }])
|
|
7704
7786
|
}
|
|
7705
7787
|
|
|
@@ -7719,9 +7801,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
7719
7801
|
)
|
|
7720
7802
|
|
|
7721
7803
|
// now calculate how far away the shape is from where it needs to be
|
|
7722
|
-
const pageBounds = this.getShapePageBounds(id)!
|
|
7723
7804
|
const pageTransform = this.getShapePageTransform(id)!
|
|
7724
|
-
|
|
7805
|
+
// We need to use the local bounds center transformed to page space, not the axis-aligned
|
|
7806
|
+
// page bounds center. This is because the page bounds are axis-aligned and their center
|
|
7807
|
+
// changes when the rotation changes, but we want to use the same reference point as
|
|
7808
|
+
// preScaleShapePageCenter (which used initialBounds.center transformed by the page transform).
|
|
7809
|
+
const currentLocalBounds = this.getShapeGeometry(id).bounds
|
|
7810
|
+
const currentPageCenter = Mat.applyToPoint(pageTransform, currentLocalBounds.center)
|
|
7725
7811
|
const shapePageTransformOrigin = pageTransform.point()
|
|
7726
7812
|
if (!currentPageCenter || !shapePageTransformOrigin) return this
|
|
7727
7813
|
const pageDelta = Vec.Sub(postScaleShapePageCenter, currentPageCenter)
|
|
@@ -8169,7 +8255,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
8169
8255
|
)
|
|
8170
8256
|
)
|
|
8171
8257
|
const sortedShapeIds = shapesToGroup.sort(sortByIndex).map((s) => s.id)
|
|
8172
|
-
const
|
|
8258
|
+
const childBounds = compact(shapesToGroup.map((shape) => this.getShapePageBounds(shape)))
|
|
8259
|
+
const pageBounds = Box.Common(childBounds)
|
|
8260
|
+
|
|
8261
|
+
if (!pageBounds.isValid()) {
|
|
8262
|
+
throw Error(`Editor.groupShapes: group bounds are invalid (NaN).`)
|
|
8263
|
+
}
|
|
8173
8264
|
|
|
8174
8265
|
const { x, y } = pageBounds.point
|
|
8175
8266
|
|
|
@@ -9555,126 +9646,6 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9555
9646
|
|
|
9556
9647
|
/* --------------------- Events --------------------- */
|
|
9557
9648
|
|
|
9558
|
-
/**
|
|
9559
|
-
* The app's current input state.
|
|
9560
|
-
*
|
|
9561
|
-
* @public
|
|
9562
|
-
*/
|
|
9563
|
-
inputs = {
|
|
9564
|
-
/** The most recent pointer down's position in the current page space. */
|
|
9565
|
-
originPagePoint: new Vec(),
|
|
9566
|
-
/** The most recent pointer down's position in screen space. */
|
|
9567
|
-
originScreenPoint: new Vec(),
|
|
9568
|
-
/** The previous pointer position in the current page space. */
|
|
9569
|
-
previousPagePoint: new Vec(),
|
|
9570
|
-
/** The previous pointer position in screen space. */
|
|
9571
|
-
previousScreenPoint: new Vec(),
|
|
9572
|
-
/** The most recent pointer position in the current page space. */
|
|
9573
|
-
currentPagePoint: new Vec(),
|
|
9574
|
-
/** The most recent pointer position in screen space. */
|
|
9575
|
-
currentScreenPoint: new Vec(),
|
|
9576
|
-
/** A set containing the currently pressed keys. */
|
|
9577
|
-
keys: new Set<string>(),
|
|
9578
|
-
/** A set containing the currently pressed buttons. */
|
|
9579
|
-
buttons: new Set<number>(),
|
|
9580
|
-
/** Whether the input is from a pe. */
|
|
9581
|
-
isPen: false,
|
|
9582
|
-
/** Whether the shift key is currently pressed. */
|
|
9583
|
-
shiftKey: false,
|
|
9584
|
-
/** Whether the meta key is currently pressed. */
|
|
9585
|
-
metaKey: false,
|
|
9586
|
-
/** Whether the control or command key is currently pressed. */
|
|
9587
|
-
ctrlKey: false,
|
|
9588
|
-
/** Whether the alt or option key is currently pressed. */
|
|
9589
|
-
altKey: false,
|
|
9590
|
-
/** Whether the user is dragging. */
|
|
9591
|
-
isDragging: false,
|
|
9592
|
-
/** Whether the user is pointing. */
|
|
9593
|
-
isPointing: false,
|
|
9594
|
-
/** Whether the user is pinching. */
|
|
9595
|
-
isPinching: false,
|
|
9596
|
-
/** Whether the user is editing. */
|
|
9597
|
-
isEditing: false,
|
|
9598
|
-
/** Whether the user is panning. */
|
|
9599
|
-
isPanning: false,
|
|
9600
|
-
/** Whether the user is spacebar panning. */
|
|
9601
|
-
isSpacebarPanning: false,
|
|
9602
|
-
/** Velocity of mouse pointer, in pixels per millisecond */
|
|
9603
|
-
pointerVelocity: new Vec(),
|
|
9604
|
-
}
|
|
9605
|
-
|
|
9606
|
-
/**
|
|
9607
|
-
* Update the input points from a pointer, pinch, or wheel event.
|
|
9608
|
-
*
|
|
9609
|
-
* @param info - The event info.
|
|
9610
|
-
*/
|
|
9611
|
-
private _updateInputsFromEvent(
|
|
9612
|
-
info: TLPointerEventInfo | TLPinchEventInfo | TLWheelEventInfo
|
|
9613
|
-
): void {
|
|
9614
|
-
const {
|
|
9615
|
-
pointerVelocity,
|
|
9616
|
-
previousScreenPoint,
|
|
9617
|
-
previousPagePoint,
|
|
9618
|
-
currentScreenPoint,
|
|
9619
|
-
currentPagePoint,
|
|
9620
|
-
originScreenPoint,
|
|
9621
|
-
originPagePoint,
|
|
9622
|
-
} = this.inputs
|
|
9623
|
-
|
|
9624
|
-
const { screenBounds } = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!
|
|
9625
|
-
const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera())
|
|
9626
|
-
|
|
9627
|
-
const sx = info.point.x - screenBounds.x
|
|
9628
|
-
const sy = info.point.y - screenBounds.y
|
|
9629
|
-
const sz = info.point.z ?? 0.5
|
|
9630
|
-
|
|
9631
|
-
previousScreenPoint.setTo(currentScreenPoint)
|
|
9632
|
-
previousPagePoint.setTo(currentPagePoint)
|
|
9633
|
-
|
|
9634
|
-
// The "screen bounds" is relative to the user's actual screen.
|
|
9635
|
-
// The "screen point" is relative to the "screen bounds";
|
|
9636
|
-
// it will be 0,0 when its actual screen position is equal
|
|
9637
|
-
// to screenBounds.point. This is confusing!
|
|
9638
|
-
currentScreenPoint.set(sx, sy)
|
|
9639
|
-
const nx = sx / cz - cx
|
|
9640
|
-
const ny = sy / cz - cy
|
|
9641
|
-
if (isFinite(nx) && isFinite(ny)) {
|
|
9642
|
-
currentPagePoint.set(nx, ny, sz)
|
|
9643
|
-
}
|
|
9644
|
-
|
|
9645
|
-
this.inputs.isPen = info.type === 'pointer' && info.isPen
|
|
9646
|
-
|
|
9647
|
-
// Reset velocity on pointer down, or when a pinch starts or ends
|
|
9648
|
-
if (info.name === 'pointer_down' || this.inputs.isPinching) {
|
|
9649
|
-
pointerVelocity.set(0, 0)
|
|
9650
|
-
originScreenPoint.setTo(currentScreenPoint)
|
|
9651
|
-
originPagePoint.setTo(currentPagePoint)
|
|
9652
|
-
}
|
|
9653
|
-
|
|
9654
|
-
// todo: We only have to do this if there are multiple users in the document
|
|
9655
|
-
this.run(
|
|
9656
|
-
() => {
|
|
9657
|
-
this.store.put([
|
|
9658
|
-
{
|
|
9659
|
-
id: TLPOINTER_ID,
|
|
9660
|
-
typeName: 'pointer',
|
|
9661
|
-
x: currentPagePoint.x,
|
|
9662
|
-
y: currentPagePoint.y,
|
|
9663
|
-
lastActivityTimestamp:
|
|
9664
|
-
// If our pointer moved only because we're following some other user, then don't
|
|
9665
|
-
// update our last activity timestamp; otherwise, update it to the current timestamp.
|
|
9666
|
-
info.type === 'pointer' && info.pointerId === INTERNAL_POINTER_IDS.CAMERA_MOVE
|
|
9667
|
-
? (this.store.unsafeGetWithoutCapture(TLPOINTER_ID)?.lastActivityTimestamp ??
|
|
9668
|
-
this._tickManager.now)
|
|
9669
|
-
: this._tickManager.now,
|
|
9670
|
-
meta: {},
|
|
9671
|
-
},
|
|
9672
|
-
])
|
|
9673
|
-
},
|
|
9674
|
-
{ history: 'ignore' }
|
|
9675
|
-
)
|
|
9676
|
-
}
|
|
9677
|
-
|
|
9678
9649
|
/**
|
|
9679
9650
|
* Dispatch a cancel event.
|
|
9680
9651
|
*
|
|
@@ -9744,19 +9715,22 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9744
9715
|
// weird but true: what `inputs` calls screen-space is actually viewport space. so
|
|
9745
9716
|
// we need to convert back into true screen space first. we should fix this...
|
|
9746
9717
|
Vec.Add(
|
|
9747
|
-
this.inputs.
|
|
9718
|
+
this.inputs.getCurrentScreenPoint(),
|
|
9748
9719
|
this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!.screenBounds
|
|
9749
9720
|
),
|
|
9750
9721
|
pointerId: options?.pointerId ?? 0,
|
|
9751
9722
|
button: options?.button ?? 0,
|
|
9752
|
-
isPen: options?.isPen ?? this.inputs.
|
|
9753
|
-
shiftKey: options?.shiftKey ?? this.inputs.
|
|
9754
|
-
altKey: options?.altKey ?? this.inputs.
|
|
9755
|
-
ctrlKey: options?.ctrlKey ?? this.inputs.
|
|
9756
|
-
metaKey: options?.metaKey ?? this.inputs.
|
|
9757
|
-
accelKey:
|
|
9723
|
+
isPen: options?.isPen ?? this.inputs.getIsPen(),
|
|
9724
|
+
shiftKey: options?.shiftKey ?? this.inputs.getShiftKey(),
|
|
9725
|
+
altKey: options?.altKey ?? this.inputs.getAltKey(),
|
|
9726
|
+
ctrlKey: options?.ctrlKey ?? this.inputs.getCtrlKey(),
|
|
9727
|
+
metaKey: options?.metaKey ?? this.inputs.getMetaKey(),
|
|
9728
|
+
accelKey: false,
|
|
9758
9729
|
}
|
|
9759
9730
|
|
|
9731
|
+
// needs to be calculated second
|
|
9732
|
+
event.accelKey = options?.accelKey ?? this.inputs.getAccelKey()
|
|
9733
|
+
|
|
9760
9734
|
if (options?.immediate) {
|
|
9761
9735
|
this._flushEventForTick(event)
|
|
9762
9736
|
} else {
|
|
@@ -10129,16 +10103,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10129
10103
|
/** @internal */
|
|
10130
10104
|
@bind
|
|
10131
10105
|
_setShiftKeyTimeout() {
|
|
10132
|
-
this.inputs.
|
|
10106
|
+
this.inputs.setShiftKey(false)
|
|
10133
10107
|
this.dispatch({
|
|
10134
10108
|
type: 'keyboard',
|
|
10135
10109
|
name: 'key_up',
|
|
10136
10110
|
key: 'Shift',
|
|
10137
|
-
shiftKey: this.inputs.
|
|
10138
|
-
ctrlKey: this.inputs.
|
|
10139
|
-
altKey: this.inputs.
|
|
10140
|
-
metaKey: this.inputs.
|
|
10141
|
-
accelKey:
|
|
10111
|
+
shiftKey: this.inputs.getShiftKey(),
|
|
10112
|
+
ctrlKey: this.inputs.getCtrlKey(),
|
|
10113
|
+
altKey: this.inputs.getAltKey(),
|
|
10114
|
+
metaKey: this.inputs.getMetaKey(),
|
|
10115
|
+
accelKey: this.inputs.getAccelKey(),
|
|
10142
10116
|
code: 'ShiftLeft',
|
|
10143
10117
|
})
|
|
10144
10118
|
}
|
|
@@ -10149,16 +10123,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10149
10123
|
/** @internal */
|
|
10150
10124
|
@bind
|
|
10151
10125
|
_setAltKeyTimeout() {
|
|
10152
|
-
this.inputs.
|
|
10126
|
+
this.inputs.setAltKey(false)
|
|
10153
10127
|
this.dispatch({
|
|
10154
10128
|
type: 'keyboard',
|
|
10155
10129
|
name: 'key_up',
|
|
10156
10130
|
key: 'Alt',
|
|
10157
|
-
shiftKey: this.inputs.
|
|
10158
|
-
ctrlKey: this.inputs.
|
|
10159
|
-
altKey: this.inputs.
|
|
10160
|
-
metaKey: this.inputs.
|
|
10161
|
-
accelKey:
|
|
10131
|
+
shiftKey: this.inputs.getShiftKey(),
|
|
10132
|
+
ctrlKey: this.inputs.getCtrlKey(),
|
|
10133
|
+
altKey: this.inputs.getAltKey(),
|
|
10134
|
+
metaKey: this.inputs.getMetaKey(),
|
|
10135
|
+
accelKey: this.inputs.getAccelKey(),
|
|
10162
10136
|
code: 'AltLeft',
|
|
10163
10137
|
})
|
|
10164
10138
|
}
|
|
@@ -10169,16 +10143,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10169
10143
|
/** @internal */
|
|
10170
10144
|
@bind
|
|
10171
10145
|
_setCtrlKeyTimeout() {
|
|
10172
|
-
this.inputs.
|
|
10146
|
+
this.inputs.setCtrlKey(false)
|
|
10173
10147
|
this.dispatch({
|
|
10174
10148
|
type: 'keyboard',
|
|
10175
10149
|
name: 'key_up',
|
|
10176
10150
|
key: 'Ctrl',
|
|
10177
|
-
shiftKey: this.inputs.
|
|
10178
|
-
ctrlKey: this.inputs.
|
|
10179
|
-
altKey: this.inputs.
|
|
10180
|
-
metaKey: this.inputs.
|
|
10181
|
-
accelKey:
|
|
10151
|
+
shiftKey: this.inputs.getShiftKey(),
|
|
10152
|
+
ctrlKey: this.inputs.getCtrlKey(),
|
|
10153
|
+
altKey: this.inputs.getAltKey(),
|
|
10154
|
+
metaKey: this.inputs.getMetaKey(),
|
|
10155
|
+
accelKey: this.inputs.getAccelKey(),
|
|
10182
10156
|
code: 'ControlLeft',
|
|
10183
10157
|
})
|
|
10184
10158
|
}
|
|
@@ -10189,16 +10163,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10189
10163
|
/** @internal */
|
|
10190
10164
|
@bind
|
|
10191
10165
|
_setMetaKeyTimeout() {
|
|
10192
|
-
this.inputs.
|
|
10166
|
+
this.inputs.setMetaKey(false)
|
|
10193
10167
|
this.dispatch({
|
|
10194
10168
|
type: 'keyboard',
|
|
10195
10169
|
name: 'key_up',
|
|
10196
10170
|
key: 'Meta',
|
|
10197
|
-
shiftKey: this.inputs.
|
|
10198
|
-
ctrlKey: this.inputs.
|
|
10199
|
-
altKey: this.inputs.
|
|
10200
|
-
metaKey: this.inputs.
|
|
10201
|
-
accelKey:
|
|
10171
|
+
shiftKey: this.inputs.getShiftKey(),
|
|
10172
|
+
ctrlKey: this.inputs.getCtrlKey(),
|
|
10173
|
+
altKey: this.inputs.getAltKey(),
|
|
10174
|
+
metaKey: this.inputs.getMetaKey(),
|
|
10175
|
+
accelKey: this.inputs.getAccelKey(),
|
|
10202
10176
|
code: 'MetaLeft',
|
|
10203
10177
|
})
|
|
10204
10178
|
}
|
|
@@ -10206,9 +10180,6 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10206
10180
|
/** @internal */
|
|
10207
10181
|
private _restoreToolId = 'select'
|
|
10208
10182
|
|
|
10209
|
-
/** @internal */
|
|
10210
|
-
private _pinchStart = 1
|
|
10211
|
-
|
|
10212
10183
|
/** @internal */
|
|
10213
10184
|
private _didPinch = false
|
|
10214
10185
|
|
|
@@ -10315,11 +10286,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10315
10286
|
if (info.type === 'misc') {
|
|
10316
10287
|
// stop panning if the interaction is cancelled or completed
|
|
10317
10288
|
if (info.name === 'cancel' || info.name === 'complete') {
|
|
10318
|
-
this.inputs.
|
|
10289
|
+
this.inputs.setIsDragging(false)
|
|
10319
10290
|
|
|
10320
|
-
if (this.inputs.
|
|
10321
|
-
this.inputs.
|
|
10322
|
-
this.inputs.
|
|
10291
|
+
if (this.inputs.getIsPanning()) {
|
|
10292
|
+
this.inputs.setIsPanning(false)
|
|
10293
|
+
this.inputs.setIsSpacebarPanning(false)
|
|
10323
10294
|
this.setCursor({ type: this._prevCursor, rotation: 0 })
|
|
10324
10295
|
}
|
|
10325
10296
|
}
|
|
@@ -10332,39 +10303,37 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10332
10303
|
if (info.shiftKey) {
|
|
10333
10304
|
clearTimeout(this._shiftKeyTimeout)
|
|
10334
10305
|
this._shiftKeyTimeout = -1
|
|
10335
|
-
inputs.
|
|
10336
|
-
} else if (!info.shiftKey && inputs.
|
|
10306
|
+
inputs.setShiftKey(true)
|
|
10307
|
+
} else if (!info.shiftKey && inputs.getShiftKey() && this._shiftKeyTimeout === -1) {
|
|
10337
10308
|
this._shiftKeyTimeout = this.timers.setTimeout(this._setShiftKeyTimeout, 150)
|
|
10338
10309
|
}
|
|
10339
10310
|
|
|
10340
10311
|
if (info.altKey) {
|
|
10341
10312
|
clearTimeout(this._altKeyTimeout)
|
|
10342
10313
|
this._altKeyTimeout = -1
|
|
10343
|
-
inputs.
|
|
10344
|
-
} else if (!info.altKey && inputs.
|
|
10314
|
+
inputs.setAltKey(true)
|
|
10315
|
+
} else if (!info.altKey && inputs.getAltKey() && this._altKeyTimeout === -1) {
|
|
10345
10316
|
this._altKeyTimeout = this.timers.setTimeout(this._setAltKeyTimeout, 150)
|
|
10346
10317
|
}
|
|
10347
10318
|
|
|
10348
10319
|
if (info.ctrlKey) {
|
|
10349
10320
|
clearTimeout(this._ctrlKeyTimeout)
|
|
10350
10321
|
this._ctrlKeyTimeout = -1
|
|
10351
|
-
inputs.
|
|
10352
|
-
} else if (!info.ctrlKey && inputs.
|
|
10322
|
+
inputs.setCtrlKey(true)
|
|
10323
|
+
} else if (!info.ctrlKey && inputs.getCtrlKey() && this._ctrlKeyTimeout === -1) {
|
|
10353
10324
|
this._ctrlKeyTimeout = this.timers.setTimeout(this._setCtrlKeyTimeout, 150)
|
|
10354
10325
|
}
|
|
10355
10326
|
|
|
10356
10327
|
if (info.metaKey) {
|
|
10357
10328
|
clearTimeout(this._metaKeyTimeout)
|
|
10358
10329
|
this._metaKeyTimeout = -1
|
|
10359
|
-
inputs.
|
|
10360
|
-
} else if (!info.metaKey && inputs.
|
|
10330
|
+
inputs.setMetaKey(true)
|
|
10331
|
+
} else if (!info.metaKey && inputs.getMetaKey() && this._metaKeyTimeout === -1) {
|
|
10361
10332
|
this._metaKeyTimeout = this.timers.setTimeout(this._setMetaKeyTimeout, 150)
|
|
10362
10333
|
}
|
|
10363
10334
|
|
|
10364
|
-
|
|
10365
|
-
|
|
10366
|
-
if (!inputs.isPointing) {
|
|
10367
|
-
inputs.isDragging = false
|
|
10335
|
+
if (!inputs.getIsPointing()) {
|
|
10336
|
+
inputs.setIsDragging(false)
|
|
10368
10337
|
}
|
|
10369
10338
|
|
|
10370
10339
|
const instanceState = this.store.unsafeGetWithoutCapture(TLINSTANCE_ID)!
|
|
@@ -10375,29 +10344,29 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10375
10344
|
case 'pinch': {
|
|
10376
10345
|
if (cameraOptions.isLocked) return
|
|
10377
10346
|
clearTimeout(this._longPressTimeout)
|
|
10378
|
-
this.
|
|
10347
|
+
this.inputs.updateFromEvent(info)
|
|
10379
10348
|
|
|
10380
10349
|
switch (info.name) {
|
|
10381
10350
|
case 'pinch_start': {
|
|
10382
|
-
if (inputs.
|
|
10351
|
+
if (inputs.getIsPinching()) return
|
|
10383
10352
|
|
|
10384
|
-
if (!inputs.
|
|
10385
|
-
this._pinchStart = this.getCamera().z
|
|
10353
|
+
if (!inputs.getIsEditing()) {
|
|
10386
10354
|
if (!this._selectedShapeIdsAtPointerDown.length) {
|
|
10387
10355
|
this._selectedShapeIdsAtPointerDown = [...pageState.selectedShapeIds]
|
|
10388
10356
|
}
|
|
10389
10357
|
|
|
10390
10358
|
this._didPinch = true
|
|
10391
10359
|
|
|
10392
|
-
inputs.
|
|
10360
|
+
inputs.setIsPinching(true)
|
|
10393
10361
|
|
|
10394
10362
|
this.interrupt()
|
|
10395
10363
|
}
|
|
10396
10364
|
|
|
10365
|
+
this.emit('event', info)
|
|
10397
10366
|
return // Stop here!
|
|
10398
10367
|
}
|
|
10399
10368
|
case 'pinch': {
|
|
10400
|
-
if (!inputs.
|
|
10369
|
+
if (!inputs.getIsPinching()) return
|
|
10401
10370
|
|
|
10402
10371
|
const {
|
|
10403
10372
|
point: { z = 1 },
|
|
@@ -10428,13 +10397,14 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10428
10397
|
{ immediate: true }
|
|
10429
10398
|
)
|
|
10430
10399
|
|
|
10400
|
+
this.emit('event', info)
|
|
10431
10401
|
return // Stop here!
|
|
10432
10402
|
}
|
|
10433
10403
|
case 'pinch_end': {
|
|
10434
|
-
if (!inputs.
|
|
10404
|
+
if (!inputs.getIsPinching()) return this
|
|
10435
10405
|
|
|
10436
10406
|
// Stop pinching
|
|
10437
|
-
inputs.
|
|
10407
|
+
inputs.setIsPinching(false)
|
|
10438
10408
|
|
|
10439
10409
|
// Stash and clear the shapes that were selected when the pinch started
|
|
10440
10410
|
const { _selectedShapeIdsAtPointerDown: shapesToReselect } = this
|
|
@@ -10454,6 +10424,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10454
10424
|
}
|
|
10455
10425
|
}
|
|
10456
10426
|
|
|
10427
|
+
this.emit('event', info)
|
|
10457
10428
|
return // Stop here!
|
|
10458
10429
|
}
|
|
10459
10430
|
}
|
|
@@ -10461,7 +10432,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10461
10432
|
case 'wheel': {
|
|
10462
10433
|
if (cameraOptions.isLocked) return
|
|
10463
10434
|
|
|
10464
|
-
this.
|
|
10435
|
+
this.inputs.updateFromEvent(info)
|
|
10465
10436
|
|
|
10466
10437
|
const { panSpeed, zoomSpeed } = cameraOptions
|
|
10467
10438
|
let wheelBehavior = cameraOptions.wheelBehavior
|
|
@@ -10492,7 +10463,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10492
10463
|
switch (behavior) {
|
|
10493
10464
|
case 'zoom': {
|
|
10494
10465
|
// Zoom in on current screen point using the wheel delta
|
|
10495
|
-
const { x, y } = this.inputs.
|
|
10466
|
+
const { x, y } = this.inputs.getCurrentScreenPoint()
|
|
10496
10467
|
let delta = dz
|
|
10497
10468
|
|
|
10498
10469
|
// If we're forcing zoom, then we need to do the wheel normalization math here
|
|
@@ -10509,6 +10480,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10509
10480
|
immediate: true,
|
|
10510
10481
|
})
|
|
10511
10482
|
this.maybeTrackPerformance('Zooming')
|
|
10483
|
+
this.root.handleEvent(info)
|
|
10484
|
+
this.emit('event', info)
|
|
10512
10485
|
return
|
|
10513
10486
|
}
|
|
10514
10487
|
case 'pan': {
|
|
@@ -10517,6 +10490,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10517
10490
|
immediate: true,
|
|
10518
10491
|
})
|
|
10519
10492
|
this.maybeTrackPerformance('Panning')
|
|
10493
|
+
this.root.handleEvent(info)
|
|
10494
|
+
this.emit('event', info)
|
|
10520
10495
|
return
|
|
10521
10496
|
}
|
|
10522
10497
|
}
|
|
@@ -10525,9 +10500,9 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10525
10500
|
}
|
|
10526
10501
|
case 'pointer': {
|
|
10527
10502
|
// Ignore pointer events while we're pinching
|
|
10528
|
-
if (inputs.
|
|
10503
|
+
if (inputs.getIsPinching()) return
|
|
10529
10504
|
|
|
10530
|
-
this.
|
|
10505
|
+
this.inputs.updateFromEvent(info)
|
|
10531
10506
|
const { isPen } = info
|
|
10532
10507
|
const { isPenMode } = instanceState
|
|
10533
10508
|
|
|
@@ -10536,7 +10511,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10536
10511
|
// If we're in pen mode and the input is not a pen type, then stop here
|
|
10537
10512
|
if (isPenMode && !isPen) return
|
|
10538
10513
|
|
|
10539
|
-
if (!this.inputs.
|
|
10514
|
+
if (!this.inputs.getIsPanning()) {
|
|
10540
10515
|
// Start a long press timeout
|
|
10541
10516
|
this._longPressTimeout = this.timers.setTimeout(() => {
|
|
10542
10517
|
const vsb = this.getViewportScreenBounds()
|
|
@@ -10546,7 +10521,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10546
10521
|
// viewport bounds, and will be again when this event is handled...
|
|
10547
10522
|
// so we need to counter-adjust from the stored value so that the
|
|
10548
10523
|
// new value is set correctly.
|
|
10549
|
-
point: this.inputs.
|
|
10524
|
+
point: this.inputs.getOriginScreenPoint().clone().addXY(vsb.x, vsb.y),
|
|
10550
10525
|
name: 'long_press',
|
|
10551
10526
|
})
|
|
10552
10527
|
}, this.options.longPressDurationMs)
|
|
@@ -10563,8 +10538,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10563
10538
|
inputs.buttons.add(info.button)
|
|
10564
10539
|
|
|
10565
10540
|
// Start pointing and stop dragging
|
|
10566
|
-
inputs.
|
|
10567
|
-
inputs.
|
|
10541
|
+
inputs.setIsPointing(true)
|
|
10542
|
+
inputs.setIsDragging(false)
|
|
10568
10543
|
|
|
10569
10544
|
// If pen mode is off but we're not already in pen mode, turn that on
|
|
10570
10545
|
if (!isPenMode && isPen) this.updateInstanceState({ isPenMode: true })
|
|
@@ -10576,16 +10551,16 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10576
10551
|
this.setCurrentTool('eraser')
|
|
10577
10552
|
} else if (info.button === MIDDLE_MOUSE_BUTTON) {
|
|
10578
10553
|
// Middle mouse pan activates panning unless we're already panning (with spacebar)
|
|
10579
|
-
if (!this.inputs.
|
|
10554
|
+
if (!this.inputs.getIsPanning()) {
|
|
10580
10555
|
this._prevCursor = this.getInstanceState().cursor.type
|
|
10581
10556
|
}
|
|
10582
|
-
this.inputs.
|
|
10557
|
+
this.inputs.setIsPanning(true)
|
|
10583
10558
|
clearTimeout(this._longPressTimeout)
|
|
10584
10559
|
}
|
|
10585
10560
|
|
|
10586
10561
|
// We might be panning because we did a middle mouse click, or because we're holding spacebar and started a regular click
|
|
10587
10562
|
// Also stop here, we don't want the state chart to receive the event
|
|
10588
|
-
if (this.inputs.
|
|
10563
|
+
if (this.inputs.getIsPanning()) {
|
|
10589
10564
|
this.stopCameraAnimation()
|
|
10590
10565
|
this.setCursor({ type: 'grabbing', rotation: 0 })
|
|
10591
10566
|
return this
|
|
@@ -10600,9 +10575,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10600
10575
|
const { x: cx, y: cy, z: cz } = unsafe__withoutCapture(() => this.getCamera())
|
|
10601
10576
|
|
|
10602
10577
|
// If we've started panning, then clear any long press timeout
|
|
10603
|
-
if (this.inputs.
|
|
10578
|
+
if (this.inputs.getIsPanning() && this.inputs.getIsPointing()) {
|
|
10604
10579
|
// Handle spacebar / middle mouse button panning
|
|
10605
|
-
const
|
|
10580
|
+
const currentScreenPoint = this.inputs.getCurrentScreenPoint()
|
|
10581
|
+
const previousScreenPoint = this.inputs.getPreviousScreenPoint()
|
|
10606
10582
|
const offset = Vec.Sub(currentScreenPoint, previousScreenPoint)
|
|
10607
10583
|
this.setCamera(new Vec(cx + offset.x / cz, cy + offset.y / cz, cz), {
|
|
10608
10584
|
immediate: true,
|
|
@@ -10612,24 +10588,25 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10612
10588
|
}
|
|
10613
10589
|
|
|
10614
10590
|
if (
|
|
10615
|
-
inputs.
|
|
10616
|
-
!inputs.
|
|
10617
|
-
Vec.Dist2(
|
|
10591
|
+
inputs.getIsPointing() &&
|
|
10592
|
+
!inputs.getIsDragging() &&
|
|
10593
|
+
Vec.Dist2(inputs.getOriginPagePoint(), inputs.getCurrentPagePoint()) *
|
|
10594
|
+
this.getZoomLevel() >
|
|
10618
10595
|
(instanceState.isCoarsePointer
|
|
10619
10596
|
? this.options.coarseDragDistanceSquared
|
|
10620
10597
|
: this.options.dragDistanceSquared) /
|
|
10621
10598
|
cz
|
|
10622
10599
|
) {
|
|
10623
10600
|
// Start dragging
|
|
10624
|
-
inputs.
|
|
10601
|
+
inputs.setIsDragging(true)
|
|
10625
10602
|
clearTimeout(this._longPressTimeout)
|
|
10626
10603
|
}
|
|
10627
10604
|
break
|
|
10628
10605
|
}
|
|
10629
10606
|
case 'pointer_up': {
|
|
10630
10607
|
// Stop dragging / pointing
|
|
10631
|
-
inputs.
|
|
10632
|
-
inputs.
|
|
10608
|
+
inputs.setIsDragging(false)
|
|
10609
|
+
inputs.setIsPointing(false)
|
|
10633
10610
|
clearTimeout(this._longPressTimeout)
|
|
10634
10611
|
|
|
10635
10612
|
// Remove the button from the buttons set
|
|
@@ -10646,12 +10623,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10646
10623
|
info.button = 0
|
|
10647
10624
|
}
|
|
10648
10625
|
|
|
10649
|
-
if (inputs.
|
|
10626
|
+
if (inputs.getIsPanning()) {
|
|
10650
10627
|
if (!inputs.keys.has('Space')) {
|
|
10651
|
-
inputs.
|
|
10652
|
-
inputs.
|
|
10628
|
+
inputs.setIsPanning(false)
|
|
10629
|
+
inputs.setIsSpacebarPanning(false)
|
|
10653
10630
|
}
|
|
10654
|
-
const slideDirection = this.inputs.
|
|
10631
|
+
const slideDirection = this.inputs.getPointerVelocity()
|
|
10655
10632
|
const slideSpeed = Math.min(2, slideDirection.len())
|
|
10656
10633
|
|
|
10657
10634
|
switch (info.button) {
|
|
@@ -10695,43 +10672,48 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10695
10672
|
// Add the key from the keys set
|
|
10696
10673
|
inputs.keys.add(info.code)
|
|
10697
10674
|
|
|
10698
|
-
|
|
10699
|
-
|
|
10700
|
-
if (!
|
|
10701
|
-
this.
|
|
10702
|
-
|
|
10675
|
+
if (this.options.spacebarPanning) {
|
|
10676
|
+
// If the space key is pressed (but meta / control isn't!) activate panning
|
|
10677
|
+
if (info.code === 'Space' && !info.ctrlKey) {
|
|
10678
|
+
if (!this.inputs.getIsPanning()) {
|
|
10679
|
+
this._prevCursor = instanceState.cursor.type
|
|
10680
|
+
}
|
|
10703
10681
|
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10682
|
+
this.inputs.setIsPanning(true)
|
|
10683
|
+
this.inputs.setIsSpacebarPanning(true)
|
|
10684
|
+
clearTimeout(this._longPressTimeout)
|
|
10685
|
+
this.setCursor({
|
|
10686
|
+
type: this.inputs.getIsPointing() ? 'grabbing' : 'grab',
|
|
10687
|
+
rotation: 0,
|
|
10688
|
+
})
|
|
10689
|
+
}
|
|
10709
10690
|
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10691
|
+
if (this.inputs.getIsSpacebarPanning()) {
|
|
10692
|
+
let offset: Vec | undefined
|
|
10693
|
+
switch (info.code) {
|
|
10694
|
+
case 'ArrowUp': {
|
|
10695
|
+
offset = new Vec(0, -1)
|
|
10696
|
+
break
|
|
10697
|
+
}
|
|
10698
|
+
case 'ArrowRight': {
|
|
10699
|
+
offset = new Vec(1, 0)
|
|
10700
|
+
break
|
|
10701
|
+
}
|
|
10702
|
+
case 'ArrowDown': {
|
|
10703
|
+
offset = new Vec(0, 1)
|
|
10704
|
+
break
|
|
10705
|
+
}
|
|
10706
|
+
case 'ArrowLeft': {
|
|
10707
|
+
offset = new Vec(-1, 0)
|
|
10708
|
+
break
|
|
10709
|
+
}
|
|
10728
10710
|
}
|
|
10729
|
-
}
|
|
10730
10711
|
|
|
10731
|
-
|
|
10732
|
-
|
|
10733
|
-
|
|
10734
|
-
|
|
10712
|
+
if (offset) {
|
|
10713
|
+
const bounds = this.getViewportPageBounds()
|
|
10714
|
+
const next = bounds.clone().translate(offset.mulV({ x: bounds.w, y: bounds.h }))
|
|
10715
|
+
this._animateToViewport(next, { animation: { duration: 320 } })
|
|
10716
|
+
}
|
|
10735
10717
|
}
|
|
10736
10718
|
}
|
|
10737
10719
|
|
|
@@ -10741,15 +10723,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10741
10723
|
// Remove the key from the keys set
|
|
10742
10724
|
inputs.keys.delete(info.code)
|
|
10743
10725
|
|
|
10744
|
-
|
|
10745
|
-
|
|
10746
|
-
if (
|
|
10747
|
-
|
|
10748
|
-
|
|
10749
|
-
|
|
10750
|
-
|
|
10751
|
-
|
|
10752
|
-
|
|
10726
|
+
if (this.options.spacebarPanning) {
|
|
10727
|
+
// If we've lifted the space key,
|
|
10728
|
+
if (info.code === 'Space') {
|
|
10729
|
+
if (this.inputs.buttons.has(MIDDLE_MOUSE_BUTTON)) {
|
|
10730
|
+
// If we're still middle dragging, continue panning
|
|
10731
|
+
} else {
|
|
10732
|
+
// otherwise, stop panning
|
|
10733
|
+
this.inputs.setIsPanning(false)
|
|
10734
|
+
this.inputs.setIsSpacebarPanning(false)
|
|
10735
|
+
this.setCursor({ type: this._prevCursor, rotation: 0 })
|
|
10736
|
+
}
|
|
10753
10737
|
}
|
|
10754
10738
|
}
|
|
10755
10739
|
break
|