@tldraw/editor 3.15.0-canary.db14db4f5395 → 3.15.0-next.d30ed5ad740e
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 +42 -40
- package/dist-cjs/index.js +16 -16
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +7 -1
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +96 -101
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +7 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/primitives/intersect.js +4 -4
- package/dist-cjs/lib/primitives/intersect.js.map +2 -2
- package/dist-cjs/lib/primitives/utils.js +4 -0
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +0 -1
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.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 +42 -40
- package/dist-esm/index.mjs +41 -41
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +7 -1
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +96 -101
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +7 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/primitives/intersect.mjs +5 -5
- package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
- package/dist-esm/lib/primitives/utils.mjs +4 -0
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +0 -1
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +62 -62
- package/src/lib/config/TLUserPreferences.ts +7 -0
- package/src/lib/editor/managers/TextManager/TextManager.ts +108 -128
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +21 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +8 -0
- package/src/lib/license/LicenseManager.test.ts +1 -1
- package/src/lib/primitives/intersect.test.ts +946 -0
- package/src/lib/primitives/intersect.ts +12 -5
- package/src/lib/primitives/utils.ts +11 -0
- package/src/lib/utils/sync/TLLocalSyncClient.ts +0 -1
- package/src/version.ts +3 -3
package/src/index.ts
CHANGED
|
@@ -18,27 +18,6 @@ export * from '@tldraw/utils'
|
|
|
18
18
|
// eslint-disable-next-line local/no-export-star
|
|
19
19
|
export * from '@tldraw/validate'
|
|
20
20
|
|
|
21
|
-
export {
|
|
22
|
-
ErrorScreen,
|
|
23
|
-
LoadingScreen,
|
|
24
|
-
TldrawEditor,
|
|
25
|
-
useOnMount,
|
|
26
|
-
type LoadingScreenProps,
|
|
27
|
-
type TLOnMountHandler,
|
|
28
|
-
type TldrawEditorBaseProps,
|
|
29
|
-
type TldrawEditorProps,
|
|
30
|
-
type TldrawEditorStoreProps,
|
|
31
|
-
type TldrawEditorWithStoreProps,
|
|
32
|
-
type TldrawEditorWithoutStoreProps,
|
|
33
|
-
} from './lib/TldrawEditor'
|
|
34
|
-
export {
|
|
35
|
-
ErrorBoundary,
|
|
36
|
-
OptionalErrorBoundary,
|
|
37
|
-
type TLErrorBoundaryProps,
|
|
38
|
-
} from './lib/components/ErrorBoundary'
|
|
39
|
-
export { HTMLContainer, type HTMLContainerProps } from './lib/components/HTMLContainer'
|
|
40
|
-
export { MenuClickCapture } from './lib/components/MenuClickCapture'
|
|
41
|
-
export { SVGContainer, type SVGContainerProps } from './lib/components/SVGContainer'
|
|
42
21
|
export { DefaultBackground } from './lib/components/default-components/DefaultBackground'
|
|
43
22
|
export { DefaultBrush, type TLBrushProps } from './lib/components/default-components/DefaultBrush'
|
|
44
23
|
export {
|
|
@@ -94,6 +73,26 @@ export {
|
|
|
94
73
|
} from './lib/components/default-components/DefaultSnapIndictor'
|
|
95
74
|
export { DefaultSpinner } from './lib/components/default-components/DefaultSpinner'
|
|
96
75
|
export { DefaultSvgDefs } from './lib/components/default-components/DefaultSvgDefs'
|
|
76
|
+
export {
|
|
77
|
+
ErrorBoundary,
|
|
78
|
+
OptionalErrorBoundary,
|
|
79
|
+
type TLErrorBoundaryProps,
|
|
80
|
+
} from './lib/components/ErrorBoundary'
|
|
81
|
+
export { HTMLContainer, type HTMLContainerProps } from './lib/components/HTMLContainer'
|
|
82
|
+
export { MenuClickCapture } from './lib/components/MenuClickCapture'
|
|
83
|
+
export { SVGContainer, type SVGContainerProps } from './lib/components/SVGContainer'
|
|
84
|
+
export {
|
|
85
|
+
createTLSchemaFromUtils,
|
|
86
|
+
createTLStore,
|
|
87
|
+
inlineBase64AssetStore,
|
|
88
|
+
type TLStoreBaseOptions,
|
|
89
|
+
type TLStoreEventInfo,
|
|
90
|
+
type TLStoreOptions,
|
|
91
|
+
type TLStoreSchemaOptions,
|
|
92
|
+
} from './lib/config/createTLStore'
|
|
93
|
+
export { createTLUser, useTldrawUser, type TLUser } from './lib/config/createTLUser'
|
|
94
|
+
export { type TLAnyBindingUtilConstructor } from './lib/config/defaultBindings'
|
|
95
|
+
export { coreShapes, type TLAnyShapeUtilConstructor } from './lib/config/defaultShapes'
|
|
97
96
|
export {
|
|
98
97
|
getSnapshot,
|
|
99
98
|
loadSnapshot,
|
|
@@ -101,42 +100,23 @@ export {
|
|
|
101
100
|
type TLLoadSnapshotOptions,
|
|
102
101
|
} from './lib/config/TLEditorSnapshot'
|
|
103
102
|
export {
|
|
104
|
-
TAB_ID,
|
|
105
103
|
createSessionStateSnapshotSignal,
|
|
106
104
|
extractSessionStateFromLegacySnapshot,
|
|
107
105
|
loadSessionStateSnapshotIntoStore,
|
|
106
|
+
TAB_ID,
|
|
108
107
|
type TLLoadSessionStateSnapshotOptions,
|
|
109
108
|
type TLSessionStateSnapshot,
|
|
110
109
|
} from './lib/config/TLSessionStateSnapshot'
|
|
111
110
|
export {
|
|
112
|
-
USER_COLORS,
|
|
113
111
|
defaultUserPreferences,
|
|
114
112
|
getFreshUserPreferences,
|
|
115
113
|
getUserPreferences,
|
|
116
114
|
setUserPreferences,
|
|
115
|
+
USER_COLORS,
|
|
117
116
|
userTypeValidator,
|
|
118
117
|
type TLUserPreferences,
|
|
119
118
|
} from './lib/config/TLUserPreferences'
|
|
120
|
-
export {
|
|
121
|
-
createTLSchemaFromUtils,
|
|
122
|
-
createTLStore,
|
|
123
|
-
inlineBase64AssetStore,
|
|
124
|
-
type TLStoreBaseOptions,
|
|
125
|
-
type TLStoreEventInfo,
|
|
126
|
-
type TLStoreOptions,
|
|
127
|
-
type TLStoreSchemaOptions,
|
|
128
|
-
} from './lib/config/createTLStore'
|
|
129
|
-
export { createTLUser, useTldrawUser, type TLUser } from './lib/config/createTLUser'
|
|
130
|
-
export { type TLAnyBindingUtilConstructor } from './lib/config/defaultBindings'
|
|
131
|
-
export { coreShapes, type TLAnyShapeUtilConstructor } from './lib/config/defaultShapes'
|
|
132
119
|
export { DEFAULT_ANIMATION_OPTIONS, DEFAULT_CAMERA_OPTIONS, SIDES } from './lib/constants'
|
|
133
|
-
export {
|
|
134
|
-
Editor,
|
|
135
|
-
type TLEditorOptions,
|
|
136
|
-
type TLEditorRunOptions,
|
|
137
|
-
type TLRenderingShape,
|
|
138
|
-
type TLResizeShapeOptions,
|
|
139
|
-
} from './lib/editor/Editor'
|
|
140
120
|
export {
|
|
141
121
|
BindingUtil,
|
|
142
122
|
type BindingOnChangeOptions,
|
|
@@ -147,6 +127,13 @@ export {
|
|
|
147
127
|
type BindingOnShapeIsolateOptions,
|
|
148
128
|
type TLBindingUtilConstructor,
|
|
149
129
|
} from './lib/editor/bindings/BindingUtil'
|
|
130
|
+
export {
|
|
131
|
+
Editor,
|
|
132
|
+
type TLEditorOptions,
|
|
133
|
+
type TLEditorRunOptions,
|
|
134
|
+
type TLRenderingShape,
|
|
135
|
+
type TLResizeShapeOptions,
|
|
136
|
+
} from './lib/editor/Editor'
|
|
150
137
|
export { ClickManager, type TLClickState } from './lib/editor/managers/ClickManager/ClickManager'
|
|
151
138
|
export { EdgeScrollManager } from './lib/editor/managers/EdgeScrollManager/EdgeScrollManager'
|
|
152
139
|
export {
|
|
@@ -179,6 +166,7 @@ export {
|
|
|
179
166
|
} from './lib/editor/managers/TextManager/TextManager'
|
|
180
167
|
export { UserPreferencesManager } from './lib/editor/managers/UserPreferencesManager/UserPreferencesManager'
|
|
181
168
|
export { BaseBoxShapeUtil, type TLBaseBoxShape } from './lib/editor/shapes/BaseBoxShapeUtil'
|
|
169
|
+
export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
|
|
182
170
|
export {
|
|
183
171
|
ShapeUtil,
|
|
184
172
|
type TLCropInfo,
|
|
@@ -195,7 +183,6 @@ export {
|
|
|
195
183
|
type TLShapeUtilCanvasSvgDef,
|
|
196
184
|
type TLShapeUtilConstructor,
|
|
197
185
|
} from './lib/editor/shapes/ShapeUtil'
|
|
198
|
-
export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
|
|
199
186
|
export {
|
|
200
187
|
getPerfectDashProps,
|
|
201
188
|
type PerfectDashTerminal,
|
|
@@ -205,22 +192,16 @@ export { resizeScaled } from './lib/editor/shapes/shared/resizeScaled'
|
|
|
205
192
|
export { BaseBoxShapeTool } from './lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool'
|
|
206
193
|
export { maybeSnapToGrid } from './lib/editor/tools/BaseBoxShapeTool/children/Pointing'
|
|
207
194
|
export { StateNode, type TLStateNodeConstructor } from './lib/editor/tools/StateNode'
|
|
208
|
-
export {
|
|
209
|
-
useDelaySvgExport,
|
|
210
|
-
useSvgExportContext,
|
|
211
|
-
type SvgExportContext,
|
|
212
|
-
type SvgExportDef,
|
|
213
|
-
} from './lib/editor/types/SvgExportContext'
|
|
214
195
|
export { type TLContent } from './lib/editor/types/clipboard-types'
|
|
215
196
|
export { type TLEventMap, type TLEventMapHandler } from './lib/editor/types/emit-types'
|
|
216
197
|
export {
|
|
217
198
|
EVENT_NAME_MAP,
|
|
218
199
|
type TLBaseEventInfo,
|
|
219
|
-
type TLCLickEventName,
|
|
220
200
|
type TLCancelEvent,
|
|
221
201
|
type TLCancelEventInfo,
|
|
222
202
|
type TLClickEvent,
|
|
223
203
|
type TLClickEventInfo,
|
|
204
|
+
type TLCLickEventName,
|
|
224
205
|
type TLCompleteEvent,
|
|
225
206
|
type TLCompleteEventInfo,
|
|
226
207
|
type TLEnterEventHandler,
|
|
@@ -289,6 +270,12 @@ export {
|
|
|
289
270
|
type TLResizeHandle,
|
|
290
271
|
type TLSelectionHandle,
|
|
291
272
|
} from './lib/editor/types/selection-types'
|
|
273
|
+
export {
|
|
274
|
+
useDelaySvgExport,
|
|
275
|
+
useSvgExportContext,
|
|
276
|
+
type SvgExportContext,
|
|
277
|
+
type SvgExportDef,
|
|
278
|
+
} from './lib/editor/types/SvgExportContext'
|
|
292
279
|
export { getSvgAsImage } from './lib/exports/getSvgAsImage'
|
|
293
280
|
export { tlenv } from './lib/globals/environment'
|
|
294
281
|
export { tlmenus } from './lib/globals/menus'
|
|
@@ -352,8 +339,6 @@ export {
|
|
|
352
339
|
type SelectionEdge,
|
|
353
340
|
type SelectionHandle,
|
|
354
341
|
} from './lib/primitives/Box'
|
|
355
|
-
export { Mat, type MatLike, type MatModel } from './lib/primitives/Mat'
|
|
356
|
-
export { Vec, type VecLike } from './lib/primitives/Vec'
|
|
357
342
|
export { EASINGS } from './lib/primitives/easings'
|
|
358
343
|
export { Arc2d } from './lib/primitives/geometry/Arc2d'
|
|
359
344
|
export { Circle2d } from './lib/primitives/geometry/Circle2d'
|
|
@@ -388,11 +373,8 @@ export {
|
|
|
388
373
|
polygonIntersectsPolyline,
|
|
389
374
|
polygonsIntersect,
|
|
390
375
|
} from './lib/primitives/intersect'
|
|
376
|
+
export { Mat, type MatLike, type MatModel } from './lib/primitives/Mat'
|
|
391
377
|
export {
|
|
392
|
-
HALF_PI,
|
|
393
|
-
PI,
|
|
394
|
-
PI2,
|
|
395
|
-
SIN,
|
|
396
378
|
angleDistance,
|
|
397
379
|
approximately,
|
|
398
380
|
areAnglesCompatible,
|
|
@@ -409,23 +391,36 @@ export {
|
|
|
409
391
|
getPointOnCircle,
|
|
410
392
|
getPointsOnArc,
|
|
411
393
|
getPolygonVertices,
|
|
394
|
+
HALF_PI,
|
|
412
395
|
isSafeFloat,
|
|
413
396
|
perimeterOfEllipse,
|
|
397
|
+
PI,
|
|
398
|
+
PI2,
|
|
414
399
|
pointInPolygon,
|
|
415
400
|
precise,
|
|
416
401
|
radiansToDegrees,
|
|
417
402
|
rangeIntersection,
|
|
418
403
|
shortAngleDist,
|
|
404
|
+
SIN,
|
|
419
405
|
snapAngle,
|
|
420
406
|
toDomPrecision,
|
|
421
407
|
toFixed,
|
|
422
408
|
toPrecision,
|
|
423
409
|
} from './lib/primitives/utils'
|
|
410
|
+
export { Vec, type VecLike } from './lib/primitives/Vec'
|
|
424
411
|
export {
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
412
|
+
ErrorScreen,
|
|
413
|
+
LoadingScreen,
|
|
414
|
+
TldrawEditor,
|
|
415
|
+
useOnMount,
|
|
416
|
+
type LoadingScreenProps,
|
|
417
|
+
type TldrawEditorBaseProps,
|
|
418
|
+
type TldrawEditorProps,
|
|
419
|
+
type TldrawEditorStoreProps,
|
|
420
|
+
type TldrawEditorWithoutStoreProps,
|
|
421
|
+
type TldrawEditorWithStoreProps,
|
|
422
|
+
type TLOnMountHandler,
|
|
423
|
+
} from './lib/TldrawEditor'
|
|
429
424
|
export { dataUrlToFile, getDefaultCdnBaseUrl } from './lib/utils/assets'
|
|
430
425
|
export { clampToBrowserMaxCanvasSize, type CanvasMaxSize } from './lib/utils/browserCanvasMaxSize'
|
|
431
426
|
export {
|
|
@@ -461,9 +456,9 @@ export {
|
|
|
461
456
|
getFontsFromRichText,
|
|
462
457
|
type RichTextFontVisitor,
|
|
463
458
|
type RichTextFontVisitorState,
|
|
464
|
-
type TLTextOptions,
|
|
465
459
|
type TiptapEditor,
|
|
466
460
|
type TiptapNode,
|
|
461
|
+
type TLTextOptions,
|
|
467
462
|
} from './lib/utils/richText'
|
|
468
463
|
export {
|
|
469
464
|
applyRotationToSnapshotShapes,
|
|
@@ -471,9 +466,14 @@ export {
|
|
|
471
466
|
type TLRotationSnapshot,
|
|
472
467
|
} from './lib/utils/rotation'
|
|
473
468
|
export { runtime, setRuntimeOverrides } from './lib/utils/runtime'
|
|
469
|
+
export {
|
|
470
|
+
ReadonlySharedStyleMap,
|
|
471
|
+
SharedStyleMap,
|
|
472
|
+
type SharedStyle,
|
|
473
|
+
} from './lib/utils/SharedStylesMap'
|
|
474
|
+
export { hardReset } from './lib/utils/sync/hardReset'
|
|
474
475
|
export { LocalIndexedDb, Table, type StoreName } from './lib/utils/sync/LocalIndexedDb'
|
|
475
476
|
export { type TLStoreWithStatus } from './lib/utils/sync/StoreWithStatus'
|
|
476
|
-
export { hardReset } from './lib/utils/sync/hardReset'
|
|
477
477
|
export { uniq } from './lib/utils/uniq'
|
|
478
478
|
export { openWindow } from './lib/utils/window-open'
|
|
479
479
|
|
|
@@ -17,6 +17,7 @@ export interface TLUserPreferences {
|
|
|
17
17
|
// N.B. These are duplicated in TLdrawAppUser.
|
|
18
18
|
locale?: string | null
|
|
19
19
|
animationSpeed?: number | null
|
|
20
|
+
areKeyboardShortcutsEnabled?: boolean | null
|
|
20
21
|
edgeScrollSpeed?: number | null
|
|
21
22
|
colorScheme?: 'light' | 'dark' | 'system'
|
|
22
23
|
isSnapMode?: boolean | null
|
|
@@ -44,6 +45,7 @@ export const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUser
|
|
|
44
45
|
// N.B. These are duplicated in TLdrawAppUser.
|
|
45
46
|
locale: T.string.nullable().optional(),
|
|
46
47
|
animationSpeed: T.number.nullable().optional(),
|
|
48
|
+
areKeyboardShortcutsEnabled: T.boolean.nullable().optional(),
|
|
47
49
|
edgeScrollSpeed: T.number.nullable().optional(),
|
|
48
50
|
colorScheme: T.literalEnum('light', 'dark', 'system').optional(),
|
|
49
51
|
isSnapMode: T.boolean.nullable().optional(),
|
|
@@ -61,6 +63,7 @@ const Versions = {
|
|
|
61
63
|
AddDynamicSizeMode: 6,
|
|
62
64
|
AllowSystemColorScheme: 7,
|
|
63
65
|
AddPasteAtCursor: 8,
|
|
66
|
+
AddKeyboardShortcuts: 9,
|
|
64
67
|
} as const
|
|
65
68
|
|
|
66
69
|
const CURRENT_VERSION = Math.max(...Object.values(Versions))
|
|
@@ -96,6 +99,9 @@ function migrateSnapshot(data: { version: number; user: any }) {
|
|
|
96
99
|
if (data.version < Versions.AddPasteAtCursor) {
|
|
97
100
|
data.user.isPasteAtCursorMode = false
|
|
98
101
|
}
|
|
102
|
+
if (data.version < Versions.AddKeyboardShortcuts) {
|
|
103
|
+
data.user.areKeyboardShortcutsEnabled = true
|
|
104
|
+
}
|
|
99
105
|
|
|
100
106
|
// finally
|
|
101
107
|
data.version = CURRENT_VERSION
|
|
@@ -139,6 +145,7 @@ export const defaultUserPreferences = Object.freeze({
|
|
|
139
145
|
// N.B. These are duplicated in TLdrawAppUser.
|
|
140
146
|
edgeScrollSpeed: 1,
|
|
141
147
|
animationSpeed: userPrefersReducedMotion() ? 0 : 1,
|
|
148
|
+
areKeyboardShortcutsEnabled: true,
|
|
142
149
|
isSnapMode: false,
|
|
143
150
|
isWrapMode: false,
|
|
144
151
|
isDynamicSizeMode: false,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BoxModel, TLDefaultHorizontalAlignStyle } from '@tldraw/tlschema'
|
|
2
|
+
import { objectMapKeys } from '@tldraw/utils'
|
|
2
3
|
import { Editor } from '../../Editor'
|
|
3
4
|
|
|
4
5
|
const fixNewLines = /\r?\n|\r/g
|
|
@@ -60,10 +61,18 @@ export interface TLMeasureTextSpanOpts {
|
|
|
60
61
|
|
|
61
62
|
const spaceCharacterRegex = /\s/
|
|
62
63
|
|
|
64
|
+
const initialDefaultStyles = Object.freeze({
|
|
65
|
+
'overflow-wrap': 'break-word',
|
|
66
|
+
'word-break': 'auto',
|
|
67
|
+
width: null,
|
|
68
|
+
height: null,
|
|
69
|
+
'max-width': null,
|
|
70
|
+
'min-width': null,
|
|
71
|
+
})
|
|
72
|
+
|
|
63
73
|
/** @public */
|
|
64
74
|
export class TextManager {
|
|
65
75
|
private elm: HTMLDivElement
|
|
66
|
-
private defaultStyles: Record<string, string | null>
|
|
67
76
|
|
|
68
77
|
constructor(public editor: Editor) {
|
|
69
78
|
const elm = document.createElement('div')
|
|
@@ -73,31 +82,34 @@ export class TextManager {
|
|
|
73
82
|
elm.tabIndex = -1
|
|
74
83
|
this.editor.getContainer().appendChild(elm)
|
|
75
84
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
'word-break': 'auto',
|
|
81
|
-
width: null,
|
|
82
|
-
height: null,
|
|
83
|
-
'max-width': null,
|
|
84
|
-
'min-width': null,
|
|
85
|
+
this.elm = elm
|
|
86
|
+
|
|
87
|
+
for (const key of objectMapKeys(initialDefaultStyles)) {
|
|
88
|
+
elm.style.setProperty(key, initialDefaultStyles[key])
|
|
85
89
|
}
|
|
90
|
+
}
|
|
86
91
|
|
|
87
|
-
|
|
92
|
+
private setElementStyles(styles: Record<string, string | undefined>) {
|
|
93
|
+
const stylesToReinstate = {} as any
|
|
94
|
+
for (const key of objectMapKeys(styles)) {
|
|
95
|
+
if (typeof styles[key] === 'string') {
|
|
96
|
+
const oldValue = this.elm.style.getPropertyValue(key)
|
|
97
|
+
if (oldValue === styles[key]) continue
|
|
98
|
+
stylesToReinstate[key] = oldValue
|
|
99
|
+
this.elm.style.setProperty(key, styles[key])
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return () => {
|
|
103
|
+
for (const key of objectMapKeys(stylesToReinstate)) {
|
|
104
|
+
this.elm.style.setProperty(key, stylesToReinstate[key])
|
|
105
|
+
}
|
|
106
|
+
}
|
|
88
107
|
}
|
|
89
108
|
|
|
90
109
|
dispose() {
|
|
91
110
|
return this.elm.remove()
|
|
92
111
|
}
|
|
93
112
|
|
|
94
|
-
private resetElmStyles() {
|
|
95
|
-
const { elm, defaultStyles } = this
|
|
96
|
-
for (const key in defaultStyles) {
|
|
97
|
-
elm.style.setProperty(key, defaultStyles[key])
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
113
|
measureText(textToMeasure: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
|
|
102
114
|
const div = document.createElement('div')
|
|
103
115
|
div.textContent = normalizeTextForDom(textToMeasure)
|
|
@@ -107,54 +119,36 @@ export class TextManager {
|
|
|
107
119
|
measureHtml(html: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
|
|
108
120
|
const { elm } = this
|
|
109
121
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
const newStyles = {
|
|
123
|
+
'font-family': opts.fontFamily,
|
|
124
|
+
'font-style': opts.fontStyle,
|
|
125
|
+
'font-weight': opts.fontWeight,
|
|
126
|
+
'font-size': opts.fontSize + 'px',
|
|
127
|
+
'line-height': opts.lineHeight.toString(),
|
|
128
|
+
padding: opts.padding,
|
|
129
|
+
'max-width': opts.maxWidth ? opts.maxWidth + 'px' : undefined,
|
|
130
|
+
'min-width': opts.minWidth ? opts.minWidth + 'px' : undefined,
|
|
131
|
+
'overflow-wrap': opts.disableOverflowWrapBreaking ? 'normal' : undefined,
|
|
132
|
+
...opts.otherStyles,
|
|
117
133
|
}
|
|
118
134
|
|
|
119
|
-
|
|
135
|
+
const restoreStyles = this.setElementStyles(newStyles)
|
|
120
136
|
|
|
121
|
-
|
|
122
|
-
|
|
137
|
+
try {
|
|
138
|
+
elm.innerHTML = html
|
|
123
139
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
elm.style.setProperty('font-weight', opts.fontWeight)
|
|
127
|
-
elm.style.setProperty('font-size', opts.fontSize + 'px')
|
|
128
|
-
elm.style.setProperty('line-height', opts.lineHeight.toString())
|
|
129
|
-
elm.style.setProperty('padding', opts.padding)
|
|
140
|
+
const scrollWidth = opts.measureScrollWidth ? elm.scrollWidth : 0
|
|
141
|
+
const rect = elm.getBoundingClientRect()
|
|
130
142
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (opts.disableOverflowWrapBreaking) {
|
|
140
|
-
elm.style.setProperty('overflow-wrap', 'normal')
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (opts.otherStyles) {
|
|
144
|
-
for (const [key, value] of Object.entries(opts.otherStyles)) {
|
|
145
|
-
elm.style.setProperty(key, value)
|
|
143
|
+
return {
|
|
144
|
+
x: 0,
|
|
145
|
+
y: 0,
|
|
146
|
+
w: rect.width,
|
|
147
|
+
h: rect.height,
|
|
148
|
+
scrollWidth,
|
|
146
149
|
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const scrollWidth = opts.measureScrollWidth ? elm.scrollWidth : 0
|
|
150
|
-
const rect = elm.getBoundingClientRect()
|
|
151
|
-
|
|
152
|
-
return {
|
|
153
|
-
x: 0,
|
|
154
|
-
y: 0,
|
|
155
|
-
w: rect.width,
|
|
156
|
-
h: rect.height,
|
|
157
|
-
scrollWidth,
|
|
150
|
+
} finally {
|
|
151
|
+
restoreStyles()
|
|
158
152
|
}
|
|
159
153
|
}
|
|
160
154
|
|
|
@@ -274,82 +268,68 @@ export class TextManager {
|
|
|
274
268
|
|
|
275
269
|
const { elm } = this
|
|
276
270
|
|
|
277
|
-
if (opts.otherStyles) {
|
|
278
|
-
for (const key in opts.otherStyles) {
|
|
279
|
-
if (!this.defaultStyles[key]) {
|
|
280
|
-
// we need to save the original style so that we can restore it when we're done
|
|
281
|
-
this.defaultStyles[key] = elm.style.getPropertyValue(key)
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
this.resetElmStyles()
|
|
287
|
-
|
|
288
|
-
elm.style.setProperty('font-family', opts.fontFamily)
|
|
289
|
-
elm.style.setProperty('font-style', opts.fontStyle)
|
|
290
|
-
elm.style.setProperty('font-weight', opts.fontWeight)
|
|
291
|
-
elm.style.setProperty('font-size', opts.fontSize + 'px')
|
|
292
|
-
elm.style.setProperty('line-height', opts.lineHeight.toString())
|
|
293
|
-
|
|
294
|
-
const elementWidth = Math.ceil(opts.width - opts.padding * 2)
|
|
295
|
-
elm.style.setProperty('width', `${elementWidth}px`)
|
|
296
|
-
elm.style.setProperty('height', 'min-content')
|
|
297
|
-
elm.style.setProperty('text-align', textAlignmentsForLtr[opts.textAlign])
|
|
298
|
-
|
|
299
271
|
const shouldTruncateToFirstLine =
|
|
300
272
|
opts.overflow === 'truncate-ellipsis' || opts.overflow === 'truncate-clip'
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
273
|
+
const elementWidth = Math.ceil(opts.width - opts.padding * 2)
|
|
274
|
+
const newStyles = {
|
|
275
|
+
'font-family': opts.fontFamily,
|
|
276
|
+
'font-style': opts.fontStyle,
|
|
277
|
+
'font-weight': opts.fontWeight,
|
|
278
|
+
'font-size': opts.fontSize + 'px',
|
|
279
|
+
'line-height': opts.lineHeight.toString(),
|
|
280
|
+
width: `${elementWidth}px`,
|
|
281
|
+
height: 'min-content',
|
|
282
|
+
'text-align': textAlignmentsForLtr[opts.textAlign],
|
|
283
|
+
'overflow-wrap': shouldTruncateToFirstLine ? 'anywhere' : undefined,
|
|
284
|
+
'word-break': shouldTruncateToFirstLine ? 'break-all' : undefined,
|
|
285
|
+
...opts.otherStyles,
|
|
311
286
|
}
|
|
287
|
+
const restoreStyles = this.setElementStyles(newStyles)
|
|
312
288
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
// Render the text into the measurement element:
|
|
316
|
-
elm.textContent = normalizedText
|
|
317
|
-
|
|
318
|
-
// actually measure the text:
|
|
319
|
-
const { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {
|
|
320
|
-
shouldTruncateToFirstLine,
|
|
321
|
-
})
|
|
289
|
+
try {
|
|
290
|
+
const normalizedText = normalizeTextForDom(textToMeasure)
|
|
322
291
|
|
|
323
|
-
|
|
324
|
-
// we need to measure the ellipsis to know how much space it takes up
|
|
325
|
-
elm.textContent = '…'
|
|
326
|
-
const ellipsisWidth = Math.ceil(this.measureElementTextNodeSpans(elm).spans[0].box.w)
|
|
327
|
-
|
|
328
|
-
// then, we need to subtract that space from the width we have and measure again:
|
|
329
|
-
elm.style.setProperty('width', `${elementWidth - ellipsisWidth}px`)
|
|
292
|
+
// Render the text into the measurement element:
|
|
330
293
|
elm.textContent = normalizedText
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// Finally, we add in our ellipsis at the end of the last span. We
|
|
336
|
-
// have to do this after measuring, not before, because adding the
|
|
337
|
-
// ellipsis changes how whitespace might be getting collapsed by the
|
|
338
|
-
// browser.
|
|
339
|
-
const lastSpan = truncatedSpans[truncatedSpans.length - 1]!
|
|
340
|
-
truncatedSpans.push({
|
|
341
|
-
text: '…',
|
|
342
|
-
box: {
|
|
343
|
-
x: Math.min(lastSpan.box.x + lastSpan.box.w, opts.width - opts.padding - ellipsisWidth),
|
|
344
|
-
y: lastSpan.box.y,
|
|
345
|
-
w: ellipsisWidth,
|
|
346
|
-
h: lastSpan.box.h,
|
|
347
|
-
},
|
|
294
|
+
|
|
295
|
+
// actually measure the text:
|
|
296
|
+
const { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {
|
|
297
|
+
shouldTruncateToFirstLine,
|
|
348
298
|
})
|
|
349
299
|
|
|
350
|
-
|
|
351
|
-
|
|
300
|
+
if (opts.overflow === 'truncate-ellipsis' && didTruncate) {
|
|
301
|
+
// we need to measure the ellipsis to know how much space it takes up
|
|
302
|
+
elm.textContent = '…'
|
|
303
|
+
const ellipsisWidth = Math.ceil(this.measureElementTextNodeSpans(elm).spans[0].box.w)
|
|
304
|
+
|
|
305
|
+
// then, we need to subtract that space from the width we have and measure again:
|
|
306
|
+
elm.style.setProperty('width', `${elementWidth - ellipsisWidth}px`)
|
|
307
|
+
elm.textContent = normalizedText
|
|
308
|
+
const truncatedSpans = this.measureElementTextNodeSpans(elm, {
|
|
309
|
+
shouldTruncateToFirstLine: true,
|
|
310
|
+
}).spans
|
|
311
|
+
|
|
312
|
+
// Finally, we add in our ellipsis at the end of the last span. We
|
|
313
|
+
// have to do this after measuring, not before, because adding the
|
|
314
|
+
// ellipsis changes how whitespace might be getting collapsed by the
|
|
315
|
+
// browser.
|
|
316
|
+
const lastSpan = truncatedSpans[truncatedSpans.length - 1]!
|
|
317
|
+
truncatedSpans.push({
|
|
318
|
+
text: '…',
|
|
319
|
+
box: {
|
|
320
|
+
x: Math.min(lastSpan.box.x + lastSpan.box.w, opts.width - opts.padding - ellipsisWidth),
|
|
321
|
+
y: lastSpan.box.y,
|
|
322
|
+
w: ellipsisWidth,
|
|
323
|
+
h: lastSpan.box.h,
|
|
324
|
+
},
|
|
325
|
+
})
|
|
326
|
+
|
|
327
|
+
return truncatedSpans
|
|
328
|
+
}
|
|
352
329
|
|
|
353
|
-
|
|
330
|
+
return spans
|
|
331
|
+
} finally {
|
|
332
|
+
restoreStyles()
|
|
333
|
+
}
|
|
354
334
|
}
|
|
355
335
|
}
|
|
@@ -24,6 +24,7 @@ describe('UserPreferencesManager', () => {
|
|
|
24
24
|
color: '#FF802B',
|
|
25
25
|
locale: 'en',
|
|
26
26
|
animationSpeed: 1,
|
|
27
|
+
areKeyboardShortcutsEnabled: true,
|
|
27
28
|
edgeScrollSpeed: 1,
|
|
28
29
|
colorScheme: 'light',
|
|
29
30
|
isSnapMode: false,
|
|
@@ -229,6 +230,7 @@ describe('UserPreferencesManager', () => {
|
|
|
229
230
|
locale: mockUserPreferences.locale,
|
|
230
231
|
color: mockUserPreferences.color,
|
|
231
232
|
animationSpeed: mockUserPreferences.animationSpeed,
|
|
233
|
+
areKeyboardShortcutsEnabled: mockUserPreferences.areKeyboardShortcutsEnabled,
|
|
232
234
|
isSnapMode: mockUserPreferences.isSnapMode,
|
|
233
235
|
colorScheme: mockUserPreferences.colorScheme,
|
|
234
236
|
isDarkMode: false, // light mode
|
|
@@ -362,6 +364,21 @@ describe('UserPreferencesManager', () => {
|
|
|
362
364
|
})
|
|
363
365
|
})
|
|
364
366
|
|
|
367
|
+
describe('getAreKeyboardShortcutsEnabled', () => {
|
|
368
|
+
it('should return user keyboard shortcuts', () => {
|
|
369
|
+
expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
|
|
370
|
+
mockUserPreferences.areKeyboardShortcutsEnabled
|
|
371
|
+
)
|
|
372
|
+
})
|
|
373
|
+
|
|
374
|
+
it('should return default keyboard shortcuts when null', () => {
|
|
375
|
+
userPreferencesAtom.set({ ...mockUserPreferences, areKeyboardShortcutsEnabled: null })
|
|
376
|
+
expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
|
|
377
|
+
defaultUserPreferences.areKeyboardShortcutsEnabled
|
|
378
|
+
)
|
|
379
|
+
})
|
|
380
|
+
})
|
|
381
|
+
|
|
365
382
|
describe('getEdgeScrollSpeed', () => {
|
|
366
383
|
it('should return user edge scroll speed', () => {
|
|
367
384
|
expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
|
|
@@ -483,6 +500,7 @@ describe('UserPreferencesManager', () => {
|
|
|
483
500
|
color: null,
|
|
484
501
|
locale: null,
|
|
485
502
|
animationSpeed: null,
|
|
503
|
+
areKeyboardShortcutsEnabled: null,
|
|
486
504
|
edgeScrollSpeed: null,
|
|
487
505
|
isSnapMode: null,
|
|
488
506
|
isWrapMode: null,
|
|
@@ -496,6 +514,9 @@ describe('UserPreferencesManager', () => {
|
|
|
496
514
|
expect(userPreferencesManager.getColor()).toBe(defaultUserPreferences.color)
|
|
497
515
|
expect(userPreferencesManager.getLocale()).toBe(defaultUserPreferences.locale)
|
|
498
516
|
expect(userPreferencesManager.getAnimationSpeed()).toBe(defaultUserPreferences.animationSpeed)
|
|
517
|
+
expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
|
|
518
|
+
defaultUserPreferences.areKeyboardShortcutsEnabled
|
|
519
|
+
)
|
|
499
520
|
expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
|
|
500
521
|
defaultUserPreferences.edgeScrollSpeed
|
|
501
522
|
)
|
|
@@ -43,6 +43,7 @@ export class UserPreferencesManager {
|
|
|
43
43
|
locale: this.getLocale(),
|
|
44
44
|
color: this.getColor(),
|
|
45
45
|
animationSpeed: this.getAnimationSpeed(),
|
|
46
|
+
areKeyboardShortcutsEnabled: this.getAreKeyboardShortcutsEnabled(),
|
|
46
47
|
isSnapMode: this.getIsSnapMode(),
|
|
47
48
|
colorScheme: this.user.userPreferences.get().colorScheme,
|
|
48
49
|
isDarkMode: this.getIsDarkMode(),
|
|
@@ -75,6 +76,13 @@ export class UserPreferencesManager {
|
|
|
75
76
|
return this.user.userPreferences.get().animationSpeed ?? defaultUserPreferences.animationSpeed
|
|
76
77
|
}
|
|
77
78
|
|
|
79
|
+
@computed getAreKeyboardShortcutsEnabled() {
|
|
80
|
+
return (
|
|
81
|
+
this.user.userPreferences.get().areKeyboardShortcutsEnabled ??
|
|
82
|
+
defaultUserPreferences.areKeyboardShortcutsEnabled
|
|
83
|
+
)
|
|
84
|
+
}
|
|
85
|
+
|
|
78
86
|
@computed getId() {
|
|
79
87
|
return this.user.userPreferences.get().id
|
|
80
88
|
}
|
|
@@ -417,7 +417,7 @@ function importPrivateKey(pemContents: string) {
|
|
|
417
417
|
// base64 decode the string to get the binary data
|
|
418
418
|
const binaryDerString = atob(pemContents)
|
|
419
419
|
// convert from a binary string to an ArrayBuffer
|
|
420
|
-
const binaryDer = str2ab(binaryDerString)
|
|
420
|
+
const binaryDer = str2ab(binaryDerString)
|
|
421
421
|
|
|
422
422
|
return crypto.subtle.importKey(
|
|
423
423
|
'pkcs8',
|