@tldraw/editor 4.6.0-next.20de11b7e238 → 4.6.0-next.241e87d4700a
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 +668 -96
- package/dist-cjs/index.js +16 -3
- package/dist-cjs/index.js.map +3 -3
- package/dist-cjs/lib/TldrawEditor.js +55 -12
- package/dist-cjs/lib/TldrawEditor.js.map +3 -3
- package/dist-cjs/lib/components/MenuClickCapture.js +16 -1
- package/dist-cjs/lib/components/MenuClickCapture.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +3 -3
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +7 -0
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/config/defaultAssets.js +36 -0
- package/dist-cjs/lib/config/defaultAssets.js.map +7 -0
- package/dist-cjs/lib/editor/Editor.js +215 -5
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/assets/AssetUtil.js +66 -0
- package/dist-cjs/lib/editor/assets/AssetUtil.js.map +7 -0
- package/dist-cjs/lib/editor/managers/FontManager/FontManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js +80 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.js.map +7 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js +466 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/PerformanceManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js +17 -0
- package/dist-cjs/lib/editor/managers/PerformanceManager/perf-types.js.map +7 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js +106 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/ThemeManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +586 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +7 -0
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +6 -4
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +11 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +1 -1
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js +6 -0
- package/dist-cjs/lib/editor/shapes/shared/getPerfectDashProps.js.map +2 -2
- package/dist-cjs/lib/editor/tools/StateNode.js +14 -17
- package/dist-cjs/lib/editor/tools/StateNode.js.map +2 -2
- package/dist-cjs/lib/editor/types/SvgExportContext.js.map +2 -2
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/getSvgJsx.js +12 -7
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +18 -1
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/{useIsDarkMode.js → useColorMode.js} +14 -10
- package/dist-cjs/lib/hooks/useColorMode.js.map +7 -0
- package/dist-cjs/lib/hooks/useCursor.js +3 -7
- package/dist-cjs/lib/hooks/useCursor.js.map +2 -2
- package/dist-cjs/lib/hooks/useDarkMode.js +4 -4
- package/dist-cjs/lib/hooks/useDarkMode.js.map +2 -2
- package/dist-cjs/lib/utils/reparenting.js +2 -1
- package/dist-cjs/lib/utils/reparenting.js.map +2 -2
- package/dist-cjs/lib/utils/richText.js.map +2 -2
- package/dist-cjs/lib/utils/runtime.js +2 -1
- package/dist-cjs/lib/utils/runtime.js.map +2 -2
- package/dist-cjs/lib/utils/sync/hardReset.js +0 -8
- package/dist-cjs/lib/utils/sync/hardReset.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 +668 -96
- package/dist-esm/index.mjs +17 -6
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +58 -12
- package/dist-esm/lib/TldrawEditor.mjs.map +3 -3
- package/dist-esm/lib/components/MenuClickCapture.mjs +16 -1
- package/dist-esm/lib/components/MenuClickCapture.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +3 -3
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +10 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/config/defaultAssets.mjs +16 -0
- package/dist-esm/lib/config/defaultAssets.mjs.map +7 -0
- package/dist-esm/lib/editor/Editor.mjs +215 -5
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/assets/AssetUtil.mjs +46 -0
- package/dist-esm/lib/editor/assets/AssetUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/FontManager/FontManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs +60 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs +438 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/PerformanceManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs +1 -0
- package/dist-esm/lib/editor/managers/PerformanceManager/perf-types.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs +88 -0
- package/dist-esm/lib/editor/managers/ThemeManager/ThemeManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +568 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +6 -4
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +11 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +1 -1
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs +6 -0
- package/dist-esm/lib/editor/shapes/shared/getPerfectDashProps.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/StateNode.mjs +14 -17
- package/dist-esm/lib/editor/tools/StateNode.mjs.map +2 -2
- package/dist-esm/lib/editor/types/SvgExportContext.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +12 -10
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +18 -1
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/useColorMode.mjs +19 -0
- package/dist-esm/lib/hooks/useColorMode.mjs.map +7 -0
- package/dist-esm/lib/hooks/useCursor.mjs +3 -7
- package/dist-esm/lib/hooks/useCursor.mjs.map +2 -2
- package/dist-esm/lib/hooks/useDarkMode.mjs +4 -4
- package/dist-esm/lib/hooks/useDarkMode.mjs.map +2 -2
- package/dist-esm/lib/utils/reparenting.mjs +2 -1
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/lib/utils/richText.mjs.map +2 -2
- package/dist-esm/lib/utils/runtime.mjs +2 -1
- package/dist-esm/lib/utils/runtime.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/hardReset.mjs +0 -8
- package/dist-esm/lib/utils/sync/hardReset.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +0 -33
- package/package.json +7 -7
- package/src/index.ts +23 -6
- package/src/lib/TldrawEditor.tsx +90 -13
- package/src/lib/components/MenuClickCapture.tsx +20 -0
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +3 -3
- package/src/lib/config/createTLStore.ts +22 -1
- package/src/lib/config/defaultAssets.ts +19 -0
- package/src/lib/editor/Editor.ts +301 -27
- package/src/lib/editor/assets/AssetUtil.ts +85 -0
- package/src/lib/editor/managers/FontManager/FontManager.test.ts +9 -2
- package/src/lib/editor/managers/FontManager/FontManager.ts +1 -67
- package/src/lib/editor/managers/PerformanceManager/PerformanceApiAdapter.ts +82 -0
- package/src/lib/editor/managers/PerformanceManager/PerformanceManager.test.ts +522 -0
- package/src/lib/editor/managers/PerformanceManager/PerformanceManager.ts +583 -0
- package/src/lib/editor/managers/PerformanceManager/perf-types.ts +196 -0
- package/src/lib/editor/managers/ThemeManager/ThemeManager.ts +116 -0
- package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +605 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +23 -29
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +5 -3
- package/src/lib/editor/shapes/ShapeUtil.ts +28 -3
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +1 -1
- package/src/lib/editor/shapes/shared/getPerfectDashProps.ts +7 -0
- package/src/lib/editor/tools/StateNode.ts +16 -18
- package/src/lib/editor/types/SvgExportContext.tsx +5 -0
- package/src/lib/editor/types/external-content.ts +1 -0
- package/src/lib/exports/getSvgJsx.tsx +21 -15
- package/src/lib/globals/environment.ts +18 -0
- package/src/lib/hooks/{useIsDarkMode.ts → useColorMode.ts} +9 -5
- package/src/lib/hooks/useCursor.ts +3 -7
- package/src/lib/hooks/useDarkMode.ts +4 -4
- package/src/lib/utils/reparenting.ts +6 -2
- package/src/lib/utils/richText.ts +1 -1
- package/src/lib/utils/runtime.ts +3 -1
- package/src/lib/utils/sync/hardReset.ts +0 -8
- package/src/version.ts +3 -3
- package/dist-cjs/lib/hooks/useIsDarkMode.js.map +0 -7
- package/dist-esm/lib/hooks/useIsDarkMode.mjs +0 -15
- package/dist-esm/lib/hooks/useIsDarkMode.mjs.map +0 -7
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -50,6 +50,9 @@ import {
|
|
|
50
50
|
TLShapePartial,
|
|
51
51
|
TLStore,
|
|
52
52
|
TLStoreSnapshot,
|
|
53
|
+
TLTheme,
|
|
54
|
+
TLThemeId,
|
|
55
|
+
TLThemes,
|
|
53
56
|
TLUser,
|
|
54
57
|
TLUserId,
|
|
55
58
|
TLVideoAsset,
|
|
@@ -95,6 +98,7 @@ import {
|
|
|
95
98
|
} from '@tldraw/utils'
|
|
96
99
|
import EventEmitter from 'eventemitter3'
|
|
97
100
|
import { TLCurrentUser, createTLCurrentUser } from '../config/createTLCurrentUser'
|
|
101
|
+
import { TLAnyAssetUtilConstructor, checkAssets } from '../config/defaultAssets'
|
|
98
102
|
import { TLAnyBindingUtilConstructor, checkBindings } from '../config/defaultBindings'
|
|
99
103
|
import { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from '../config/defaultShapes'
|
|
100
104
|
import {
|
|
@@ -141,6 +145,7 @@ import { getDroppedShapesToNewParents, kickoutOccludedShapes } from '../utils/re
|
|
|
141
145
|
import { TLTextOptions, TiptapEditor } from '../utils/richText'
|
|
142
146
|
import { applyRotationToSnapshotShapes, getRotationSnapshot } from '../utils/rotation'
|
|
143
147
|
import { ReadonlySharedStyleMap, SharedStyle, SharedStyleMap } from '../utils/SharedStylesMap'
|
|
148
|
+
import { AssetUtil } from './assets/AssetUtil'
|
|
144
149
|
import { BindingOnDeleteOptions, BindingUtil } from './bindings/BindingUtil'
|
|
145
150
|
import { bindingsIndex } from './derivations/bindingsIndex'
|
|
146
151
|
import { notVisibleShapes } from './derivations/notVisibleShapes'
|
|
@@ -152,10 +157,12 @@ import { FocusManager } from './managers/FocusManager/FocusManager'
|
|
|
152
157
|
import { FontManager } from './managers/FontManager/FontManager'
|
|
153
158
|
import { HistoryManager } from './managers/HistoryManager/HistoryManager'
|
|
154
159
|
import { InputsManager } from './managers/InputsManager/InputsManager'
|
|
160
|
+
import { PerformanceManager } from './managers/PerformanceManager/PerformanceManager'
|
|
155
161
|
import { ScribbleManager } from './managers/ScribbleManager/ScribbleManager'
|
|
156
162
|
import { SnapManager } from './managers/SnapManager/SnapManager'
|
|
157
163
|
import { SpatialIndexManager } from './managers/SpatialIndexManager/SpatialIndexManager'
|
|
158
164
|
import { TextManager } from './managers/TextManager/TextManager'
|
|
165
|
+
import { resolveThemes, ThemeManager } from './managers/ThemeManager/ThemeManager'
|
|
159
166
|
import { TickManager } from './managers/TickManager/TickManager'
|
|
160
167
|
import { UserPreferencesManager } from './managers/UserPreferencesManager/UserPreferencesManager'
|
|
161
168
|
import {
|
|
@@ -214,14 +221,13 @@ export interface TLEditorOptions {
|
|
|
214
221
|
*/
|
|
215
222
|
bindingUtils: readonly TLAnyBindingUtilConstructor[]
|
|
216
223
|
/**
|
|
217
|
-
* An array of
|
|
224
|
+
* An array of asset utils to use in the editor. These will be used to handle asset-type-specific behavior.
|
|
218
225
|
*/
|
|
219
|
-
|
|
226
|
+
assetUtils?: readonly TLAnyAssetUtilConstructor[]
|
|
220
227
|
/**
|
|
221
|
-
*
|
|
222
|
-
* given, the body element will be used.
|
|
228
|
+
* An array of tools to use in the editor. These will be used to handle events and manage user interactions in the editor.
|
|
223
229
|
*/
|
|
224
|
-
|
|
230
|
+
tools: readonly TLStateNodeConstructor[]
|
|
225
231
|
/**
|
|
226
232
|
* A user defined externally to replace the default user.
|
|
227
233
|
*/
|
|
@@ -234,25 +240,13 @@ export interface TLEditorOptions {
|
|
|
234
240
|
* Whether to automatically focus the editor when it mounts.
|
|
235
241
|
*/
|
|
236
242
|
autoFocus?: boolean
|
|
237
|
-
/**
|
|
238
|
-
* Whether to infer dark mode from the user's system preferences. Defaults to false.
|
|
239
|
-
*/
|
|
240
|
-
inferDarkMode?: boolean
|
|
241
|
-
/**
|
|
242
|
-
* Options for the editor's camera.
|
|
243
|
-
*
|
|
244
|
-
* @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.
|
|
245
|
-
*/
|
|
246
|
-
cameraOptions?: Partial<TLCameraOptions>
|
|
247
|
-
options?: Partial<TldrawOptions>
|
|
248
|
-
/**
|
|
249
|
-
* Text options for the editor.
|
|
250
|
-
*
|
|
251
|
-
* @deprecated Use `options.text` instead. This prop will be removed in a future release.
|
|
252
|
-
*/
|
|
253
|
-
textOptions?: TLTextOptions
|
|
254
243
|
licenseKey?: string
|
|
255
244
|
fontAssetUrls?: { [key: string]: string | undefined }
|
|
245
|
+
/**
|
|
246
|
+
* Should return a containing html element which has all the styles applied to the editor. If not
|
|
247
|
+
* given, the body element will be used.
|
|
248
|
+
*/
|
|
249
|
+
getContainer(): HTMLElement
|
|
256
250
|
/**
|
|
257
251
|
* Provides a way to hide shapes.
|
|
258
252
|
*
|
|
@@ -272,6 +266,41 @@ export interface TLEditorOptions {
|
|
|
272
266
|
shape: TLShape,
|
|
273
267
|
editor: Editor
|
|
274
268
|
): 'visible' | 'hidden' | 'inherit' | null | undefined
|
|
269
|
+
/**
|
|
270
|
+
* Named theme definitions for the editor. Each theme contains shared
|
|
271
|
+
* properties (font size, line height, stroke width) and color palettes
|
|
272
|
+
* for both light and dark modes.
|
|
273
|
+
*/
|
|
274
|
+
themes?: Partial<TLThemes>
|
|
275
|
+
/**
|
|
276
|
+
* The id of the initially active theme. Defaults to `'default'`.
|
|
277
|
+
*/
|
|
278
|
+
initialTheme?: TLThemeId
|
|
279
|
+
/**
|
|
280
|
+
* The editor's color scheme preference, controls the default color mode. Defaults to `'light'`.
|
|
281
|
+
*
|
|
282
|
+
* - `'light'` - Always use light mode.
|
|
283
|
+
* - `'dark'` - Always use dark mode.
|
|
284
|
+
* - `'system'` - Follow the OS color scheme preference.
|
|
285
|
+
*/
|
|
286
|
+
colorScheme?: 'light' | 'dark' | 'system'
|
|
287
|
+
/**
|
|
288
|
+
* Additional configuration options for the tldraw editor.
|
|
289
|
+
*/
|
|
290
|
+
options?: Partial<TldrawOptions>
|
|
291
|
+
// --- Deprecated ----
|
|
292
|
+
/**
|
|
293
|
+
* Options for the editor's camera.
|
|
294
|
+
*
|
|
295
|
+
* @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.
|
|
296
|
+
*/
|
|
297
|
+
cameraOptions?: Partial<TLCameraOptions>
|
|
298
|
+
/**
|
|
299
|
+
* Text options for the editor.
|
|
300
|
+
*
|
|
301
|
+
* @deprecated Use `options.text` instead. This prop will be removed in a future release.
|
|
302
|
+
*/
|
|
303
|
+
textOptions?: TLTextOptions
|
|
275
304
|
}
|
|
276
305
|
|
|
277
306
|
/**
|
|
@@ -300,6 +329,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
300
329
|
user,
|
|
301
330
|
shapeUtils,
|
|
302
331
|
bindingUtils,
|
|
332
|
+
assetUtils: assetUtilConstructors,
|
|
303
333
|
tools,
|
|
304
334
|
getContainer,
|
|
305
335
|
// needs to be here for backwards compatibility with TldrawEditor
|
|
@@ -307,13 +337,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
307
337
|
cameraOptions,
|
|
308
338
|
initialState,
|
|
309
339
|
autoFocus,
|
|
310
|
-
inferDarkMode,
|
|
311
340
|
options: _options,
|
|
312
341
|
// needs to be here for backwards compatibility with TldrawEditor
|
|
313
342
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
314
343
|
textOptions: _textOptions,
|
|
315
344
|
getShapeVisibility,
|
|
345
|
+
colorScheme,
|
|
316
346
|
fontAssetUrls,
|
|
347
|
+
themes,
|
|
348
|
+
initialTheme,
|
|
317
349
|
}: TLEditorOptions) {
|
|
318
350
|
super()
|
|
319
351
|
|
|
@@ -348,19 +380,24 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
348
380
|
...options?.camera,
|
|
349
381
|
})
|
|
350
382
|
|
|
383
|
+
this.getContainer = getContainer
|
|
384
|
+
|
|
351
385
|
this._textOptions = atom('text options', options?.text ?? null)
|
|
352
386
|
|
|
353
|
-
this.user = new UserPreferencesManager(user ?? createTLCurrentUser(),
|
|
387
|
+
this.user = new UserPreferencesManager(user ?? createTLCurrentUser(), colorScheme ?? 'light')
|
|
354
388
|
this.disposables.add(() => this.user.dispose())
|
|
355
389
|
|
|
356
|
-
this.getContainer = getContainer
|
|
357
|
-
|
|
358
390
|
this.textMeasure = new TextManager(this)
|
|
359
391
|
this.disposables.add(() => this.textMeasure.dispose())
|
|
360
392
|
|
|
361
|
-
this.
|
|
393
|
+
this._themeManager = new ThemeManager(this, {
|
|
394
|
+
themes: resolveThemes(themes),
|
|
395
|
+
initial: initialTheme ?? 'default',
|
|
396
|
+
})
|
|
397
|
+
this.disposables.add(() => this._themeManager.dispose())
|
|
362
398
|
|
|
363
399
|
this._tickManager = new TickManager(this)
|
|
400
|
+
this.disposables.add(() => this._tickManager.dispose())
|
|
364
401
|
this.disposables.add(() => {
|
|
365
402
|
// Reset camera state to 'idle' so the store isn't left stuck at 'moving'
|
|
366
403
|
// when tick events stop (e.g. React strict mode disposes while camera is moving)
|
|
@@ -368,7 +405,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
368
405
|
this._setCameraState('idle')
|
|
369
406
|
})
|
|
370
407
|
|
|
408
|
+
this.fonts = new FontManager(this, fontAssetUrls)
|
|
409
|
+
|
|
371
410
|
this.inputs = new InputsManager(this)
|
|
411
|
+
this.performance = new PerformanceManager(this)
|
|
412
|
+
this.disposables.add(() => this.performance.dispose())
|
|
372
413
|
|
|
373
414
|
class NewRoot extends RootState {
|
|
374
415
|
static override initial = initialState ?? ''
|
|
@@ -406,6 +447,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
406
447
|
this.shapeUtils = _shapeUtils
|
|
407
448
|
this.styleProps = _styleProps
|
|
408
449
|
|
|
450
|
+
const _shapeUtilsByAssetType = {} as Record<string, ShapeUtil<any>>
|
|
451
|
+
for (const Util of allShapeUtils) {
|
|
452
|
+
const assetTypes = Util.handledAssetTypes
|
|
453
|
+
if (assetTypes) {
|
|
454
|
+
for (const assetType of assetTypes) {
|
|
455
|
+
_shapeUtilsByAssetType[assetType] = _shapeUtils[Util.type]
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
this._shapeUtilsByAssetType = _shapeUtilsByAssetType
|
|
460
|
+
|
|
409
461
|
const allBindingUtils = checkBindings(bindingUtils)
|
|
410
462
|
const _bindingUtils = {} as Record<string, BindingUtil<any>>
|
|
411
463
|
for (const Util of allBindingUtils) {
|
|
@@ -414,6 +466,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
414
466
|
}
|
|
415
467
|
this.bindingUtils = _bindingUtils
|
|
416
468
|
|
|
469
|
+
// Asset utils
|
|
470
|
+
if (assetUtilConstructors) {
|
|
471
|
+
const allAssetUtils = checkAssets(assetUtilConstructors)
|
|
472
|
+
const _assetUtils = {} as Record<string, AssetUtil<any>>
|
|
473
|
+
for (const Util of allAssetUtils) {
|
|
474
|
+
const util = new Util(this)
|
|
475
|
+
_assetUtils[Util.type] = util
|
|
476
|
+
}
|
|
477
|
+
this.assetUtils = _assetUtils
|
|
478
|
+
}
|
|
479
|
+
|
|
417
480
|
// Tools.
|
|
418
481
|
// Accept tools from constructor parameters which may not conflict with the root note's default or
|
|
419
482
|
// "baked in" tools, select and zoom.
|
|
@@ -948,6 +1011,18 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
948
1011
|
*/
|
|
949
1012
|
readonly snaps: SnapManager
|
|
950
1013
|
|
|
1014
|
+
/**
|
|
1015
|
+
* A manager for performance measurement hooks.
|
|
1016
|
+
*
|
|
1017
|
+
* @public
|
|
1018
|
+
*/
|
|
1019
|
+
readonly performance: PerformanceManager
|
|
1020
|
+
|
|
1021
|
+
/**
|
|
1022
|
+
* A manager for the spatial index, tracking where shapes exist on the canvas.
|
|
1023
|
+
*
|
|
1024
|
+
* @internal
|
|
1025
|
+
*/
|
|
951
1026
|
private readonly _spatialIndex: SpatialIndexManager
|
|
952
1027
|
|
|
953
1028
|
/**
|
|
@@ -965,6 +1040,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
965
1040
|
*/
|
|
966
1041
|
readonly user: UserPreferencesManager
|
|
967
1042
|
|
|
1043
|
+
/**
|
|
1044
|
+
* A manager for the editor's themes.
|
|
1045
|
+
*
|
|
1046
|
+
* @internal
|
|
1047
|
+
*/
|
|
1048
|
+
private readonly _themeManager: ThemeManager
|
|
1049
|
+
|
|
968
1050
|
/**
|
|
969
1051
|
* A helper for measuring text.
|
|
970
1052
|
*
|
|
@@ -1045,13 +1127,134 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1045
1127
|
* @public
|
|
1046
1128
|
*/
|
|
1047
1129
|
dispose() {
|
|
1130
|
+
// Stop any in-progress camera animations and following before
|
|
1131
|
+
// running disposables, so their cleanup listeners fire first
|
|
1132
|
+
this.stopCameraAnimation()
|
|
1133
|
+
if (this.getInstanceState().followingUserId) {
|
|
1134
|
+
this.stopFollowingUser()
|
|
1135
|
+
}
|
|
1136
|
+
|
|
1048
1137
|
this.disposables.forEach((dispose) => dispose())
|
|
1049
1138
|
this.disposables.clear()
|
|
1139
|
+
|
|
1140
|
+
// Clear any open menus for this editor's context
|
|
1141
|
+
this.menus.clearOpenMenus()
|
|
1142
|
+
|
|
1050
1143
|
this.store.dispose()
|
|
1051
1144
|
this.isDisposed = true
|
|
1052
1145
|
this.emit('dispose')
|
|
1053
1146
|
}
|
|
1054
1147
|
|
|
1148
|
+
/* ------------------ Themes (shadowing the theme manager) ------------------ */
|
|
1149
|
+
|
|
1150
|
+
/**
|
|
1151
|
+
* Get the current color mode (`'light'` or `'dark'`), based on the user's dark mode preference.
|
|
1152
|
+
*
|
|
1153
|
+
* @public
|
|
1154
|
+
*/
|
|
1155
|
+
getColorMode(): 'light' | 'dark' {
|
|
1156
|
+
return this._themeManager.getColorMode()
|
|
1157
|
+
}
|
|
1158
|
+
|
|
1159
|
+
/**
|
|
1160
|
+
* Set the color mode. Note that this is a convenience method that passes the mode to
|
|
1161
|
+
* `user.updateUserPreferences`, which is the source of truth for the user's color mode preference.
|
|
1162
|
+
*
|
|
1163
|
+
* @public
|
|
1164
|
+
*/
|
|
1165
|
+
setColorMode(mode: 'light' | 'dark') {
|
|
1166
|
+
this.user.updateUserPreferences({ colorScheme: mode })
|
|
1167
|
+
return this
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Get the id of the current theme.
|
|
1172
|
+
*
|
|
1173
|
+
* @public
|
|
1174
|
+
*/
|
|
1175
|
+
getCurrentThemeId(): TLThemeId {
|
|
1176
|
+
return this._themeManager.getCurrentThemeId()
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
/**
|
|
1180
|
+
* Get the current theme definition.
|
|
1181
|
+
*
|
|
1182
|
+
* @public
|
|
1183
|
+
*/
|
|
1184
|
+
getCurrentTheme(): TLTheme {
|
|
1185
|
+
return this._themeManager.getCurrentTheme()
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Set the current theme by id.
|
|
1190
|
+
*
|
|
1191
|
+
* @public
|
|
1192
|
+
*/
|
|
1193
|
+
setCurrentTheme(id: TLThemeId) {
|
|
1194
|
+
this._themeManager.setCurrentTheme(id)
|
|
1195
|
+
return this
|
|
1196
|
+
}
|
|
1197
|
+
|
|
1198
|
+
/**
|
|
1199
|
+
* Get all registered theme definitions.
|
|
1200
|
+
*
|
|
1201
|
+
* @public
|
|
1202
|
+
*/
|
|
1203
|
+
getThemes(): TLThemes {
|
|
1204
|
+
return this._themeManager.getThemes()
|
|
1205
|
+
}
|
|
1206
|
+
|
|
1207
|
+
/**
|
|
1208
|
+
* Get a single theme definition by id.
|
|
1209
|
+
*
|
|
1210
|
+
* @public
|
|
1211
|
+
*/
|
|
1212
|
+
getTheme(id: TLThemeId): TLTheme | undefined {
|
|
1213
|
+
return this._themeManager.getTheme(id)
|
|
1214
|
+
}
|
|
1215
|
+
|
|
1216
|
+
/**
|
|
1217
|
+
* Replace all theme definitions, or update them via a callback that receives a deep copy.
|
|
1218
|
+
* The `'default'` theme must always be present in the result.
|
|
1219
|
+
*
|
|
1220
|
+
* @example
|
|
1221
|
+
* ```ts
|
|
1222
|
+
* // Replace all themes
|
|
1223
|
+
* editor.updateThemes({ default: myDefaultTheme, ocean: myOceanTheme })
|
|
1224
|
+
*
|
|
1225
|
+
* // Update via callback
|
|
1226
|
+
* editor.updateThemes((themes) => {
|
|
1227
|
+
* delete themes.ocean
|
|
1228
|
+
* return themes
|
|
1229
|
+
* })
|
|
1230
|
+
* ```
|
|
1231
|
+
*
|
|
1232
|
+
* @public
|
|
1233
|
+
*/
|
|
1234
|
+
updateThemes(themes: TLThemes | ((themes: TLThemes) => TLThemes)) {
|
|
1235
|
+
this._themeManager.updateThemes(themes)
|
|
1236
|
+
return this
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
/**
|
|
1240
|
+
* Register or update a single theme definition. The theme is keyed by its `id` property.
|
|
1241
|
+
*
|
|
1242
|
+
* @example
|
|
1243
|
+
* ```ts
|
|
1244
|
+
* // Override a property on the default theme
|
|
1245
|
+
* editor.updateTheme({ ...editor.getTheme('default')!, fontSize: 24 })
|
|
1246
|
+
*
|
|
1247
|
+
* // Register a new theme
|
|
1248
|
+
* editor.updateTheme({ id: 'ocean', ...myOceanTheme })
|
|
1249
|
+
* ```
|
|
1250
|
+
*
|
|
1251
|
+
* @public
|
|
1252
|
+
*/
|
|
1253
|
+
updateTheme(theme: TLTheme) {
|
|
1254
|
+
this._themeManager.updateTheme(theme)
|
|
1255
|
+
return this
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1055
1258
|
/* ------------------- Shape Utils ------------------ */
|
|
1056
1259
|
|
|
1057
1260
|
/**
|
|
@@ -1061,6 +1264,9 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1061
1264
|
*/
|
|
1062
1265
|
shapeUtils: { readonly [K in string]?: ShapeUtil<TLShape> }
|
|
1063
1266
|
|
|
1267
|
+
/** @internal */
|
|
1268
|
+
private _shapeUtilsByAssetType: { readonly [K in string]?: ShapeUtil<TLShape> } = {}
|
|
1269
|
+
|
|
1064
1270
|
styleProps: { [key: string]: Map<StyleProp<any>, string> }
|
|
1065
1271
|
|
|
1066
1272
|
/**
|
|
@@ -1103,6 +1309,18 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1103
1309
|
return hasOwnProperty(this.shapeUtils, type)
|
|
1104
1310
|
}
|
|
1105
1311
|
|
|
1312
|
+
/**
|
|
1313
|
+
* Get the shape util that handles the given asset type.
|
|
1314
|
+
* Returns the shape util whose {@link ShapeUtil.handledAssetTypes} includes
|
|
1315
|
+
* the given asset type, or undefined if none matches.
|
|
1316
|
+
*
|
|
1317
|
+
* @param assetType - The asset type string.
|
|
1318
|
+
* @public
|
|
1319
|
+
*/
|
|
1320
|
+
getShapeUtilForAssetType(assetType: string): ShapeUtil | undefined {
|
|
1321
|
+
return getOwnProperty(this._shapeUtilsByAssetType, assetType)
|
|
1322
|
+
}
|
|
1323
|
+
|
|
1106
1324
|
/* ------------------- Binding Utils ------------------ */
|
|
1107
1325
|
/**
|
|
1108
1326
|
* A map of shape utility classes (TLShapeUtils) by shape type.
|
|
@@ -1138,6 +1356,56 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1138
1356
|
return bindingUtil
|
|
1139
1357
|
}
|
|
1140
1358
|
|
|
1359
|
+
/* ------------------- Asset Utils ------------------ */
|
|
1360
|
+
|
|
1361
|
+
/**
|
|
1362
|
+
* A map of asset utility classes by asset type.
|
|
1363
|
+
*
|
|
1364
|
+
* @public
|
|
1365
|
+
*/
|
|
1366
|
+
assetUtils: { readonly [K in string]?: AssetUtil<TLAsset> } = {}
|
|
1367
|
+
|
|
1368
|
+
/**
|
|
1369
|
+
* Get an asset util from an asset or asset type.
|
|
1370
|
+
*
|
|
1371
|
+
* @param arg - An asset, asset type string, or object with type.
|
|
1372
|
+
*
|
|
1373
|
+
* @public
|
|
1374
|
+
*/
|
|
1375
|
+
getAssetUtil<S extends TLAsset>(asset: S | { type: S['type'] }): AssetUtil<S>
|
|
1376
|
+
getAssetUtil(type: string): AssetUtil
|
|
1377
|
+
getAssetUtil(arg: string | { type: string }) {
|
|
1378
|
+
const type = typeof arg === 'string' ? arg : arg.type
|
|
1379
|
+
const assetUtil = getOwnProperty(this.assetUtils, type)
|
|
1380
|
+
assert(assetUtil, `No asset util found for type "${type}"`)
|
|
1381
|
+
return assetUtil
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* Returns true if the editor has an asset util for the given asset type.
|
|
1386
|
+
*
|
|
1387
|
+
* @public
|
|
1388
|
+
*/
|
|
1389
|
+
hasAssetUtil(arg: string | { type: string }): boolean {
|
|
1390
|
+
const type = typeof arg === 'string' ? arg : arg.type
|
|
1391
|
+
return hasOwnProperty(this.assetUtils, type)
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1394
|
+
/**
|
|
1395
|
+
* Get the asset util that accepts the given MIME type.
|
|
1396
|
+
* Returns null if no registered asset util accepts the MIME type.
|
|
1397
|
+
*
|
|
1398
|
+
* @public
|
|
1399
|
+
*/
|
|
1400
|
+
getAssetUtilForMimeType(mimeType: string): AssetUtil | null {
|
|
1401
|
+
for (const util of Object.values(this.assetUtils)) {
|
|
1402
|
+
if (util && util.acceptsMimeType(mimeType)) {
|
|
1403
|
+
return util
|
|
1404
|
+
}
|
|
1405
|
+
}
|
|
1406
|
+
return null
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1141
1409
|
/* --------------------- History -------------------- */
|
|
1142
1410
|
|
|
1143
1411
|
/**
|
|
@@ -1161,6 +1429,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1161
1429
|
this._flushEventsForTick(0)
|
|
1162
1430
|
this.complete()
|
|
1163
1431
|
this.history.undo()
|
|
1432
|
+
this.performance._notifyUndoRedo('undo', this.history.getNumUndos(), this.history.getNumRedos())
|
|
1164
1433
|
return this
|
|
1165
1434
|
}
|
|
1166
1435
|
|
|
@@ -1191,6 +1460,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1191
1460
|
this._flushEventsForTick(0)
|
|
1192
1461
|
this.complete()
|
|
1193
1462
|
this.history.redo()
|
|
1463
|
+
this.performance._notifyUndoRedo('redo', this.history.getNumUndos(), this.history.getNumRedos())
|
|
1194
1464
|
return this
|
|
1195
1465
|
}
|
|
1196
1466
|
|
|
@@ -10595,6 +10865,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10595
10865
|
{ immediate: true }
|
|
10596
10866
|
)
|
|
10597
10867
|
|
|
10868
|
+
this.performance._notifyCameraOperation('zooming')
|
|
10598
10869
|
this.emit('event', info)
|
|
10599
10870
|
return // Stop here!
|
|
10600
10871
|
}
|
|
@@ -10687,6 +10958,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10687
10958
|
immediate: true,
|
|
10688
10959
|
})
|
|
10689
10960
|
this.maybeTrackPerformance('Zooming')
|
|
10961
|
+
this.performance._notifyCameraOperation('zooming')
|
|
10690
10962
|
this.root.handleEvent(info)
|
|
10691
10963
|
this.emit('event', info)
|
|
10692
10964
|
return
|
|
@@ -10697,6 +10969,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10697
10969
|
immediate: true,
|
|
10698
10970
|
})
|
|
10699
10971
|
this.maybeTrackPerformance('Panning')
|
|
10972
|
+
this.performance._notifyCameraOperation('panning')
|
|
10700
10973
|
this.root.handleEvent(info)
|
|
10701
10974
|
this.emit('event', info)
|
|
10702
10975
|
return
|
|
@@ -10791,6 +11064,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10791
11064
|
immediate: true,
|
|
10792
11065
|
})
|
|
10793
11066
|
this.maybeTrackPerformance('Panning')
|
|
11067
|
+
this.performance._notifyCameraOperation('panning')
|
|
10794
11068
|
return
|
|
10795
11069
|
}
|
|
10796
11070
|
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { LegacyMigrations, MigrationSequence } from '@tldraw/store'
|
|
2
|
+
import {
|
|
3
|
+
RecordProps,
|
|
4
|
+
TLAsset,
|
|
5
|
+
TLAssetId,
|
|
6
|
+
TLPropsMigrations,
|
|
7
|
+
TLUnknownAsset,
|
|
8
|
+
} from '@tldraw/tlschema'
|
|
9
|
+
import type { Editor } from '../Editor'
|
|
10
|
+
|
|
11
|
+
/** @public */
|
|
12
|
+
export interface TLAssetUtilConstructor<
|
|
13
|
+
T extends TLAsset = TLAsset,
|
|
14
|
+
U extends AssetUtil<T> = AssetUtil<T>,
|
|
15
|
+
> {
|
|
16
|
+
new (editor: Editor): U
|
|
17
|
+
type: T['type']
|
|
18
|
+
props?: RecordProps<T>
|
|
19
|
+
migrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Abstract base class for defining asset-type-specific behavior.
|
|
24
|
+
*
|
|
25
|
+
* Each asset type (image, video, bookmark, etc.) has a corresponding AssetUtil that handles
|
|
26
|
+
* type-specific operations like determining supported MIME types and creating assets from files.
|
|
27
|
+
*
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
export abstract class AssetUtil<Asset extends TLAsset = TLAsset> {
|
|
31
|
+
/** Configure this asset util's {@link AssetUtil.options | `options`}. */
|
|
32
|
+
static configure<T extends TLAssetUtilConstructor<any, any>>(
|
|
33
|
+
this: T,
|
|
34
|
+
options: T extends new (...args: any[]) => { options: infer Options } ? Partial<Options> : never
|
|
35
|
+
): T {
|
|
36
|
+
// @ts-expect-error -- typescript has no idea what's going on here but it's fine
|
|
37
|
+
return class extends this {
|
|
38
|
+
// @ts-expect-error
|
|
39
|
+
options = { ...this.options, ...options }
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
constructor(public editor: Editor) {}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Options for this asset util. Override this to provide customization options for your asset.
|
|
47
|
+
* Use {@link AssetUtil.configure} to customize existing asset utils.
|
|
48
|
+
*/
|
|
49
|
+
options = {}
|
|
50
|
+
|
|
51
|
+
static props?: RecordProps<TLUnknownAsset>
|
|
52
|
+
static migrations?: LegacyMigrations | TLPropsMigrations | MigrationSequence
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The type of the asset util, which should match the asset's type.
|
|
56
|
+
*/
|
|
57
|
+
static type: string
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Get the default props for an asset of this type.
|
|
61
|
+
*/
|
|
62
|
+
abstract getDefaultProps(): Asset['props']
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Get the MIME types that this asset type supports.
|
|
66
|
+
* Return an empty array if this asset type doesn't support files (e.g. bookmarks).
|
|
67
|
+
*/
|
|
68
|
+
getSupportedMimeTypes(): readonly string[] {
|
|
69
|
+
return []
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Check whether this asset type accepts a given MIME type.
|
|
74
|
+
*/
|
|
75
|
+
acceptsMimeType(mimeType: string): boolean {
|
|
76
|
+
return this.getSupportedMimeTypes().includes(mimeType)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Create an asset from a file. Return null if this asset type can't handle the file.
|
|
81
|
+
*/
|
|
82
|
+
async getAssetFromFile(_file: File, _assetId: TLAssetId): Promise<Asset | null> {
|
|
83
|
+
return null
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -1,8 +1,15 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
TLFontFace,
|
|
3
|
+
TLParentId,
|
|
4
|
+
TLShape,
|
|
5
|
+
TLShapeId,
|
|
6
|
+
createShapeId,
|
|
7
|
+
toRichText,
|
|
8
|
+
} from '@tldraw/tlschema'
|
|
2
9
|
import { IndexKey } from '@tldraw/utils'
|
|
3
10
|
import { Mock, Mocked, vi } from 'vitest'
|
|
4
11
|
import { Editor } from '../../Editor'
|
|
5
|
-
import { FontManager
|
|
12
|
+
import { FontManager } from './FontManager'
|
|
6
13
|
|
|
7
14
|
// Mock the Editor class
|
|
8
15
|
vi.mock('../../Editor')
|