@tldraw/editor 4.6.0-next.793daa9fe264 → 4.6.0-next.a31a8a6b83f2
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 +376 -98
- package/dist-cjs/index.js +12 -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/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 +200 -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/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 +9 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.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/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +376 -98
- package/dist-esm/index.mjs +13 -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/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 +200 -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/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 +9 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.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/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 +8 -6
- package/src/lib/TldrawEditor.tsx +90 -13
- 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 +285 -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/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 +26 -1
- 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/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'
|
|
@@ -156,6 +161,7 @@ import { ScribbleManager } from './managers/ScribbleManager/ScribbleManager'
|
|
|
156
161
|
import { SnapManager } from './managers/SnapManager/SnapManager'
|
|
157
162
|
import { SpatialIndexManager } from './managers/SpatialIndexManager/SpatialIndexManager'
|
|
158
163
|
import { TextManager } from './managers/TextManager/TextManager'
|
|
164
|
+
import { resolveThemes, ThemeManager } from './managers/ThemeManager/ThemeManager'
|
|
159
165
|
import { TickManager } from './managers/TickManager/TickManager'
|
|
160
166
|
import { UserPreferencesManager } from './managers/UserPreferencesManager/UserPreferencesManager'
|
|
161
167
|
import {
|
|
@@ -214,14 +220,13 @@ export interface TLEditorOptions {
|
|
|
214
220
|
*/
|
|
215
221
|
bindingUtils: readonly TLAnyBindingUtilConstructor[]
|
|
216
222
|
/**
|
|
217
|
-
* An array of
|
|
223
|
+
* An array of asset utils to use in the editor. These will be used to handle asset-type-specific behavior.
|
|
218
224
|
*/
|
|
219
|
-
|
|
225
|
+
assetUtils?: readonly TLAnyAssetUtilConstructor[]
|
|
220
226
|
/**
|
|
221
|
-
*
|
|
222
|
-
* given, the body element will be used.
|
|
227
|
+
* An array of tools to use in the editor. These will be used to handle events and manage user interactions in the editor.
|
|
223
228
|
*/
|
|
224
|
-
|
|
229
|
+
tools: readonly TLStateNodeConstructor[]
|
|
225
230
|
/**
|
|
226
231
|
* A user defined externally to replace the default user.
|
|
227
232
|
*/
|
|
@@ -234,25 +239,13 @@ export interface TLEditorOptions {
|
|
|
234
239
|
* Whether to automatically focus the editor when it mounts.
|
|
235
240
|
*/
|
|
236
241
|
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
242
|
licenseKey?: string
|
|
255
243
|
fontAssetUrls?: { [key: string]: string | undefined }
|
|
244
|
+
/**
|
|
245
|
+
* Should return a containing html element which has all the styles applied to the editor. If not
|
|
246
|
+
* given, the body element will be used.
|
|
247
|
+
*/
|
|
248
|
+
getContainer(): HTMLElement
|
|
256
249
|
/**
|
|
257
250
|
* Provides a way to hide shapes.
|
|
258
251
|
*
|
|
@@ -272,6 +265,41 @@ export interface TLEditorOptions {
|
|
|
272
265
|
shape: TLShape,
|
|
273
266
|
editor: Editor
|
|
274
267
|
): 'visible' | 'hidden' | 'inherit' | null | undefined
|
|
268
|
+
/**
|
|
269
|
+
* Named theme definitions for the editor. Each theme contains shared
|
|
270
|
+
* properties (font size, line height, stroke width) and color palettes
|
|
271
|
+
* for both light and dark modes.
|
|
272
|
+
*/
|
|
273
|
+
themes?: Partial<TLThemes>
|
|
274
|
+
/**
|
|
275
|
+
* The id of the initially active theme. Defaults to `'default'`.
|
|
276
|
+
*/
|
|
277
|
+
initialTheme?: TLThemeId
|
|
278
|
+
/**
|
|
279
|
+
* The editor's color scheme preference, controls the default color mode. Defaults to `'light'`.
|
|
280
|
+
*
|
|
281
|
+
* - `'light'` - Always use light mode.
|
|
282
|
+
* - `'dark'` - Always use dark mode.
|
|
283
|
+
* - `'system'` - Follow the OS color scheme preference.
|
|
284
|
+
*/
|
|
285
|
+
colorScheme?: 'light' | 'dark' | 'system'
|
|
286
|
+
/**
|
|
287
|
+
* Additional configuration options for the tldraw editor.
|
|
288
|
+
*/
|
|
289
|
+
options?: Partial<TldrawOptions>
|
|
290
|
+
// --- Deprecated ----
|
|
291
|
+
/**
|
|
292
|
+
* Options for the editor's camera.
|
|
293
|
+
*
|
|
294
|
+
* @deprecated Use `options.cameraOptions` instead. This will be removed in a future release.
|
|
295
|
+
*/
|
|
296
|
+
cameraOptions?: Partial<TLCameraOptions>
|
|
297
|
+
/**
|
|
298
|
+
* Text options for the editor.
|
|
299
|
+
*
|
|
300
|
+
* @deprecated Use `options.text` instead. This prop will be removed in a future release.
|
|
301
|
+
*/
|
|
302
|
+
textOptions?: TLTextOptions
|
|
275
303
|
}
|
|
276
304
|
|
|
277
305
|
/**
|
|
@@ -300,6 +328,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
300
328
|
user,
|
|
301
329
|
shapeUtils,
|
|
302
330
|
bindingUtils,
|
|
331
|
+
assetUtils: assetUtilConstructors,
|
|
303
332
|
tools,
|
|
304
333
|
getContainer,
|
|
305
334
|
// needs to be here for backwards compatibility with TldrawEditor
|
|
@@ -307,13 +336,15 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
307
336
|
cameraOptions,
|
|
308
337
|
initialState,
|
|
309
338
|
autoFocus,
|
|
310
|
-
inferDarkMode,
|
|
311
339
|
options: _options,
|
|
312
340
|
// needs to be here for backwards compatibility with TldrawEditor
|
|
313
341
|
// eslint-disable-next-line @typescript-eslint/no-deprecated
|
|
314
342
|
textOptions: _textOptions,
|
|
315
343
|
getShapeVisibility,
|
|
344
|
+
colorScheme,
|
|
316
345
|
fontAssetUrls,
|
|
346
|
+
themes,
|
|
347
|
+
initialTheme,
|
|
317
348
|
}: TLEditorOptions) {
|
|
318
349
|
super()
|
|
319
350
|
|
|
@@ -348,19 +379,24 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
348
379
|
...options?.camera,
|
|
349
380
|
})
|
|
350
381
|
|
|
382
|
+
this.getContainer = getContainer
|
|
383
|
+
|
|
351
384
|
this._textOptions = atom('text options', options?.text ?? null)
|
|
352
385
|
|
|
353
|
-
this.user = new UserPreferencesManager(user ?? createTLCurrentUser(),
|
|
386
|
+
this.user = new UserPreferencesManager(user ?? createTLCurrentUser(), colorScheme ?? 'light')
|
|
354
387
|
this.disposables.add(() => this.user.dispose())
|
|
355
388
|
|
|
356
|
-
this.getContainer = getContainer
|
|
357
|
-
|
|
358
389
|
this.textMeasure = new TextManager(this)
|
|
359
390
|
this.disposables.add(() => this.textMeasure.dispose())
|
|
360
391
|
|
|
361
|
-
this.
|
|
392
|
+
this._themeManager = new ThemeManager(this, {
|
|
393
|
+
themes: resolveThemes(themes),
|
|
394
|
+
initial: initialTheme ?? 'default',
|
|
395
|
+
})
|
|
396
|
+
this.disposables.add(() => this._themeManager.dispose())
|
|
362
397
|
|
|
363
398
|
this._tickManager = new TickManager(this)
|
|
399
|
+
this.disposables.add(() => this._tickManager.dispose())
|
|
364
400
|
this.disposables.add(() => {
|
|
365
401
|
// Reset camera state to 'idle' so the store isn't left stuck at 'moving'
|
|
366
402
|
// when tick events stop (e.g. React strict mode disposes while camera is moving)
|
|
@@ -368,6 +404,8 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
368
404
|
this._setCameraState('idle')
|
|
369
405
|
})
|
|
370
406
|
|
|
407
|
+
this.fonts = new FontManager(this, fontAssetUrls)
|
|
408
|
+
|
|
371
409
|
this.inputs = new InputsManager(this)
|
|
372
410
|
|
|
373
411
|
class NewRoot extends RootState {
|
|
@@ -406,6 +444,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
406
444
|
this.shapeUtils = _shapeUtils
|
|
407
445
|
this.styleProps = _styleProps
|
|
408
446
|
|
|
447
|
+
const _shapeUtilsByAssetType = {} as Record<string, ShapeUtil<any>>
|
|
448
|
+
for (const Util of allShapeUtils) {
|
|
449
|
+
const assetTypes = Util.handledAssetTypes
|
|
450
|
+
if (assetTypes) {
|
|
451
|
+
for (const assetType of assetTypes) {
|
|
452
|
+
_shapeUtilsByAssetType[assetType] = _shapeUtils[Util.type]
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
this._shapeUtilsByAssetType = _shapeUtilsByAssetType
|
|
457
|
+
|
|
409
458
|
const allBindingUtils = checkBindings(bindingUtils)
|
|
410
459
|
const _bindingUtils = {} as Record<string, BindingUtil<any>>
|
|
411
460
|
for (const Util of allBindingUtils) {
|
|
@@ -414,6 +463,17 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
414
463
|
}
|
|
415
464
|
this.bindingUtils = _bindingUtils
|
|
416
465
|
|
|
466
|
+
// Asset utils
|
|
467
|
+
if (assetUtilConstructors) {
|
|
468
|
+
const allAssetUtils = checkAssets(assetUtilConstructors)
|
|
469
|
+
const _assetUtils = {} as Record<string, AssetUtil<any>>
|
|
470
|
+
for (const Util of allAssetUtils) {
|
|
471
|
+
const util = new Util(this)
|
|
472
|
+
_assetUtils[Util.type] = util
|
|
473
|
+
}
|
|
474
|
+
this.assetUtils = _assetUtils
|
|
475
|
+
}
|
|
476
|
+
|
|
417
477
|
// Tools.
|
|
418
478
|
// Accept tools from constructor parameters which may not conflict with the root note's default or
|
|
419
479
|
// "baked in" tools, select and zoom.
|
|
@@ -948,6 +1008,11 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
948
1008
|
*/
|
|
949
1009
|
readonly snaps: SnapManager
|
|
950
1010
|
|
|
1011
|
+
/**
|
|
1012
|
+
* A manager for the spatial index, tracking where shapes exist on the canvas.
|
|
1013
|
+
*
|
|
1014
|
+
* @internal
|
|
1015
|
+
*/
|
|
951
1016
|
private readonly _spatialIndex: SpatialIndexManager
|
|
952
1017
|
|
|
953
1018
|
/**
|
|
@@ -965,6 +1030,13 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
965
1030
|
*/
|
|
966
1031
|
readonly user: UserPreferencesManager
|
|
967
1032
|
|
|
1033
|
+
/**
|
|
1034
|
+
* A manager for the editor's themes.
|
|
1035
|
+
*
|
|
1036
|
+
* @internal
|
|
1037
|
+
*/
|
|
1038
|
+
private readonly _themeManager: ThemeManager
|
|
1039
|
+
|
|
968
1040
|
/**
|
|
969
1041
|
* A helper for measuring text.
|
|
970
1042
|
*
|
|
@@ -1045,13 +1117,134 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1045
1117
|
* @public
|
|
1046
1118
|
*/
|
|
1047
1119
|
dispose() {
|
|
1120
|
+
// Stop any in-progress camera animations and following before
|
|
1121
|
+
// running disposables, so their cleanup listeners fire first
|
|
1122
|
+
this.stopCameraAnimation()
|
|
1123
|
+
if (this.getInstanceState().followingUserId) {
|
|
1124
|
+
this.stopFollowingUser()
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1048
1127
|
this.disposables.forEach((dispose) => dispose())
|
|
1049
1128
|
this.disposables.clear()
|
|
1129
|
+
|
|
1130
|
+
// Clear any open menus for this editor's context
|
|
1131
|
+
this.menus.clearOpenMenus()
|
|
1132
|
+
|
|
1050
1133
|
this.store.dispose()
|
|
1051
1134
|
this.isDisposed = true
|
|
1052
1135
|
this.emit('dispose')
|
|
1053
1136
|
}
|
|
1054
1137
|
|
|
1138
|
+
/* ------------------ Themes (shadowing the theme manager) ------------------ */
|
|
1139
|
+
|
|
1140
|
+
/**
|
|
1141
|
+
* Get the current color mode (`'light'` or `'dark'`), based on the user's dark mode preference.
|
|
1142
|
+
*
|
|
1143
|
+
* @public
|
|
1144
|
+
*/
|
|
1145
|
+
getColorMode(): 'light' | 'dark' {
|
|
1146
|
+
return this._themeManager.getColorMode()
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Set the color mode. Note that this is a convenience method that passes the mode to
|
|
1151
|
+
* `user.updateUserPreferences`, which is the source of truth for the user's color mode preference.
|
|
1152
|
+
*
|
|
1153
|
+
* @public
|
|
1154
|
+
*/
|
|
1155
|
+
setColorMode(mode: 'light' | 'dark') {
|
|
1156
|
+
this.user.updateUserPreferences({ colorScheme: mode })
|
|
1157
|
+
return this
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Get the id of the current theme.
|
|
1162
|
+
*
|
|
1163
|
+
* @public
|
|
1164
|
+
*/
|
|
1165
|
+
getCurrentThemeId(): TLThemeId {
|
|
1166
|
+
return this._themeManager.getCurrentThemeId()
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/**
|
|
1170
|
+
* Get the current theme definition.
|
|
1171
|
+
*
|
|
1172
|
+
* @public
|
|
1173
|
+
*/
|
|
1174
|
+
getCurrentTheme(): TLTheme {
|
|
1175
|
+
return this._themeManager.getCurrentTheme()
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* Set the current theme by id.
|
|
1180
|
+
*
|
|
1181
|
+
* @public
|
|
1182
|
+
*/
|
|
1183
|
+
setCurrentTheme(id: TLThemeId) {
|
|
1184
|
+
this._themeManager.setCurrentTheme(id)
|
|
1185
|
+
return this
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
/**
|
|
1189
|
+
* Get all registered theme definitions.
|
|
1190
|
+
*
|
|
1191
|
+
* @public
|
|
1192
|
+
*/
|
|
1193
|
+
getThemes(): TLThemes {
|
|
1194
|
+
return this._themeManager.getThemes()
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/**
|
|
1198
|
+
* Get a single theme definition by id.
|
|
1199
|
+
*
|
|
1200
|
+
* @public
|
|
1201
|
+
*/
|
|
1202
|
+
getTheme(id: TLThemeId): TLTheme | undefined {
|
|
1203
|
+
return this._themeManager.getTheme(id)
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
/**
|
|
1207
|
+
* Replace all theme definitions, or update them via a callback that receives a deep copy.
|
|
1208
|
+
* The `'default'` theme must always be present in the result.
|
|
1209
|
+
*
|
|
1210
|
+
* @example
|
|
1211
|
+
* ```ts
|
|
1212
|
+
* // Replace all themes
|
|
1213
|
+
* editor.updateThemes({ default: myDefaultTheme, ocean: myOceanTheme })
|
|
1214
|
+
*
|
|
1215
|
+
* // Update via callback
|
|
1216
|
+
* editor.updateThemes((themes) => {
|
|
1217
|
+
* delete themes.ocean
|
|
1218
|
+
* return themes
|
|
1219
|
+
* })
|
|
1220
|
+
* ```
|
|
1221
|
+
*
|
|
1222
|
+
* @public
|
|
1223
|
+
*/
|
|
1224
|
+
updateThemes(themes: TLThemes | ((themes: TLThemes) => TLThemes)) {
|
|
1225
|
+
this._themeManager.updateThemes(themes)
|
|
1226
|
+
return this
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
/**
|
|
1230
|
+
* Register or update a single theme definition. The theme is keyed by its `id` property.
|
|
1231
|
+
*
|
|
1232
|
+
* @example
|
|
1233
|
+
* ```ts
|
|
1234
|
+
* // Override a property on the default theme
|
|
1235
|
+
* editor.updateTheme({ ...editor.getTheme('default')!, fontSize: 24 })
|
|
1236
|
+
*
|
|
1237
|
+
* // Register a new theme
|
|
1238
|
+
* editor.updateTheme({ id: 'ocean', ...myOceanTheme })
|
|
1239
|
+
* ```
|
|
1240
|
+
*
|
|
1241
|
+
* @public
|
|
1242
|
+
*/
|
|
1243
|
+
updateTheme(theme: TLTheme) {
|
|
1244
|
+
this._themeManager.updateTheme(theme)
|
|
1245
|
+
return this
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1055
1248
|
/* ------------------- Shape Utils ------------------ */
|
|
1056
1249
|
|
|
1057
1250
|
/**
|
|
@@ -1061,6 +1254,9 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1061
1254
|
*/
|
|
1062
1255
|
shapeUtils: { readonly [K in string]?: ShapeUtil<TLShape> }
|
|
1063
1256
|
|
|
1257
|
+
/** @internal */
|
|
1258
|
+
private _shapeUtilsByAssetType: { readonly [K in string]?: ShapeUtil<TLShape> } = {}
|
|
1259
|
+
|
|
1064
1260
|
styleProps: { [key: string]: Map<StyleProp<any>, string> }
|
|
1065
1261
|
|
|
1066
1262
|
/**
|
|
@@ -1103,6 +1299,18 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1103
1299
|
return hasOwnProperty(this.shapeUtils, type)
|
|
1104
1300
|
}
|
|
1105
1301
|
|
|
1302
|
+
/**
|
|
1303
|
+
* Get the shape util that handles the given asset type.
|
|
1304
|
+
* Returns the shape util whose {@link ShapeUtil.handledAssetTypes} includes
|
|
1305
|
+
* the given asset type, or undefined if none matches.
|
|
1306
|
+
*
|
|
1307
|
+
* @param assetType - The asset type string.
|
|
1308
|
+
* @public
|
|
1309
|
+
*/
|
|
1310
|
+
getShapeUtilForAssetType(assetType: string): ShapeUtil | undefined {
|
|
1311
|
+
return getOwnProperty(this._shapeUtilsByAssetType, assetType)
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1106
1314
|
/* ------------------- Binding Utils ------------------ */
|
|
1107
1315
|
/**
|
|
1108
1316
|
* A map of shape utility classes (TLShapeUtils) by shape type.
|
|
@@ -1138,6 +1346,56 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
1138
1346
|
return bindingUtil
|
|
1139
1347
|
}
|
|
1140
1348
|
|
|
1349
|
+
/* ------------------- Asset Utils ------------------ */
|
|
1350
|
+
|
|
1351
|
+
/**
|
|
1352
|
+
* A map of asset utility classes by asset type.
|
|
1353
|
+
*
|
|
1354
|
+
* @public
|
|
1355
|
+
*/
|
|
1356
|
+
assetUtils: { readonly [K in string]?: AssetUtil<TLAsset> } = {}
|
|
1357
|
+
|
|
1358
|
+
/**
|
|
1359
|
+
* Get an asset util from an asset or asset type.
|
|
1360
|
+
*
|
|
1361
|
+
* @param arg - An asset, asset type string, or object with type.
|
|
1362
|
+
*
|
|
1363
|
+
* @public
|
|
1364
|
+
*/
|
|
1365
|
+
getAssetUtil<S extends TLAsset>(asset: S | { type: S['type'] }): AssetUtil<S>
|
|
1366
|
+
getAssetUtil(type: string): AssetUtil
|
|
1367
|
+
getAssetUtil(arg: string | { type: string }) {
|
|
1368
|
+
const type = typeof arg === 'string' ? arg : arg.type
|
|
1369
|
+
const assetUtil = getOwnProperty(this.assetUtils, type)
|
|
1370
|
+
assert(assetUtil, `No asset util found for type "${type}"`)
|
|
1371
|
+
return assetUtil
|
|
1372
|
+
}
|
|
1373
|
+
|
|
1374
|
+
/**
|
|
1375
|
+
* Returns true if the editor has an asset util for the given asset type.
|
|
1376
|
+
*
|
|
1377
|
+
* @public
|
|
1378
|
+
*/
|
|
1379
|
+
hasAssetUtil(arg: string | { type: string }): boolean {
|
|
1380
|
+
const type = typeof arg === 'string' ? arg : arg.type
|
|
1381
|
+
return hasOwnProperty(this.assetUtils, type)
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
/**
|
|
1385
|
+
* Get the asset util that accepts the given MIME type.
|
|
1386
|
+
* Returns null if no registered asset util accepts the MIME type.
|
|
1387
|
+
*
|
|
1388
|
+
* @public
|
|
1389
|
+
*/
|
|
1390
|
+
getAssetUtilForMimeType(mimeType: string): AssetUtil | null {
|
|
1391
|
+
for (const util of Object.values(this.assetUtils)) {
|
|
1392
|
+
if (util && util.acceptsMimeType(mimeType)) {
|
|
1393
|
+
return util
|
|
1394
|
+
}
|
|
1395
|
+
}
|
|
1396
|
+
return null
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1141
1399
|
/* --------------------- History -------------------- */
|
|
1142
1400
|
|
|
1143
1401
|
/**
|
|
@@ -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')
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { computed, EMPTY_ARRAY, transact } from '@tldraw/state'
|
|
2
2
|
import { AtomMap } from '@tldraw/store'
|
|
3
|
-
import { TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
3
|
+
import { TLFontFace, TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
4
4
|
import {
|
|
5
5
|
areArraysShallowEqual,
|
|
6
6
|
compact,
|
|
@@ -10,72 +10,6 @@ import {
|
|
|
10
10
|
} from '@tldraw/utils'
|
|
11
11
|
import type { Editor } from '../../Editor'
|
|
12
12
|
|
|
13
|
-
/**
|
|
14
|
-
* Represents the `src` property of a {@link TLFontFace}.
|
|
15
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src | `src`} for details of the properties here.
|
|
16
|
-
* @public
|
|
17
|
-
*/
|
|
18
|
-
export interface TLFontFaceSource {
|
|
19
|
-
/**
|
|
20
|
-
* A URL from which to load the font. If the value here is a key in
|
|
21
|
-
* {@link tldraw#TLEditorAssetUrls.fonts}, the value from there will be used instead.
|
|
22
|
-
*/
|
|
23
|
-
url: string
|
|
24
|
-
format?: string
|
|
25
|
-
tech?: string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* A font face that can be used in the editor. The properties of this are largely the same as the
|
|
30
|
-
* ones in the
|
|
31
|
-
* {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face | css `@font-face` rule}.
|
|
32
|
-
* @public
|
|
33
|
-
*/
|
|
34
|
-
export interface TLFontFace {
|
|
35
|
-
/**
|
|
36
|
-
* How this font can be referred to in CSS.
|
|
37
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family | `font-family`}.
|
|
38
|
-
*/
|
|
39
|
-
readonly family: string
|
|
40
|
-
/**
|
|
41
|
-
* The source of the font. This
|
|
42
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src | `src`}.
|
|
43
|
-
*/
|
|
44
|
-
readonly src: TLFontFaceSource
|
|
45
|
-
/**
|
|
46
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/ascent-override | `ascent-override`}.
|
|
47
|
-
*/
|
|
48
|
-
readonly ascentOverride?: string
|
|
49
|
-
/**
|
|
50
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/descent-override | `descent-override`}.
|
|
51
|
-
*/
|
|
52
|
-
readonly descentOverride?: string
|
|
53
|
-
/**
|
|
54
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch | `font-stretch`}.
|
|
55
|
-
*/
|
|
56
|
-
readonly stretch?: string
|
|
57
|
-
/**
|
|
58
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-style | `font-style`}.
|
|
59
|
-
*/
|
|
60
|
-
readonly style?: string
|
|
61
|
-
/**
|
|
62
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-weight | `font-weight`}.
|
|
63
|
-
*/
|
|
64
|
-
readonly weight?: string
|
|
65
|
-
/**
|
|
66
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings | `font-feature-settings`}.
|
|
67
|
-
*/
|
|
68
|
-
readonly featureSettings?: string
|
|
69
|
-
/**
|
|
70
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/line-gap-override | `line-gap-override`}.
|
|
71
|
-
*/
|
|
72
|
-
readonly lineGapOverride?: string
|
|
73
|
-
/**
|
|
74
|
-
* See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range | `unicode-range`}.
|
|
75
|
-
*/
|
|
76
|
-
readonly unicodeRange?: string
|
|
77
|
-
}
|
|
78
|
-
|
|
79
13
|
interface FontState {
|
|
80
14
|
readonly state: 'loading' | 'ready' | 'error'
|
|
81
15
|
readonly instance: FontFace
|