@tldraw/editor 3.15.0-next.39f008bfb627 → 3.15.0-next.f1dfcef63951

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.
Files changed (46) hide show
  1. package/dist-cjs/index.d.ts +40 -42
  2. package/dist-cjs/index.js +16 -16
  3. package/dist-cjs/index.js.map +2 -2
  4. package/dist-cjs/lib/config/TLUserPreferences.js +1 -7
  5. package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
  6. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +101 -96
  7. package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
  8. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +2 -7
  9. package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
  10. package/dist-cjs/lib/primitives/intersect.js +4 -4
  11. package/dist-cjs/lib/primitives/intersect.js.map +2 -2
  12. package/dist-cjs/lib/primitives/utils.js +0 -4
  13. package/dist-cjs/lib/primitives/utils.js.map +2 -2
  14. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +1 -0
  15. package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
  16. package/dist-cjs/version.js +3 -3
  17. package/dist-cjs/version.js.map +1 -1
  18. package/dist-esm/index.d.mts +40 -42
  19. package/dist-esm/index.mjs +41 -41
  20. package/dist-esm/index.mjs.map +2 -2
  21. package/dist-esm/lib/config/TLUserPreferences.mjs +1 -7
  22. package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
  23. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +101 -96
  24. package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
  25. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +2 -7
  26. package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
  27. package/dist-esm/lib/primitives/intersect.mjs +5 -5
  28. package/dist-esm/lib/primitives/intersect.mjs.map +2 -2
  29. package/dist-esm/lib/primitives/utils.mjs +0 -4
  30. package/dist-esm/lib/primitives/utils.mjs.map +2 -2
  31. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +1 -0
  32. package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
  33. package/dist-esm/version.mjs +3 -3
  34. package/dist-esm/version.mjs.map +1 -1
  35. package/package.json +7 -7
  36. package/src/index.ts +62 -62
  37. package/src/lib/config/TLUserPreferences.ts +0 -7
  38. package/src/lib/editor/managers/TextManager/TextManager.ts +128 -108
  39. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +0 -21
  40. package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +0 -8
  41. package/src/lib/license/LicenseManager.test.ts +1 -1
  42. package/src/lib/primitives/intersect.ts +5 -12
  43. package/src/lib/primitives/utils.ts +0 -11
  44. package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -0
  45. package/src/version.ts +3 -3
  46. package/src/lib/primitives/intersect.test.ts +0 -946
package/src/index.ts CHANGED
@@ -18,6 +18,27 @@ 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'
21
42
  export { DefaultBackground } from './lib/components/default-components/DefaultBackground'
22
43
  export { DefaultBrush, type TLBrushProps } from './lib/components/default-components/DefaultBrush'
23
44
  export {
@@ -73,26 +94,6 @@ export {
73
94
  } from './lib/components/default-components/DefaultSnapIndictor'
74
95
  export { DefaultSpinner } from './lib/components/default-components/DefaultSpinner'
75
96
  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'
96
97
  export {
97
98
  getSnapshot,
98
99
  loadSnapshot,
@@ -100,23 +101,42 @@ export {
100
101
  type TLLoadSnapshotOptions,
101
102
  } from './lib/config/TLEditorSnapshot'
102
103
  export {
104
+ TAB_ID,
103
105
  createSessionStateSnapshotSignal,
104
106
  extractSessionStateFromLegacySnapshot,
105
107
  loadSessionStateSnapshotIntoStore,
106
- TAB_ID,
107
108
  type TLLoadSessionStateSnapshotOptions,
108
109
  type TLSessionStateSnapshot,
109
110
  } from './lib/config/TLSessionStateSnapshot'
110
111
  export {
112
+ USER_COLORS,
111
113
  defaultUserPreferences,
112
114
  getFreshUserPreferences,
113
115
  getUserPreferences,
114
116
  setUserPreferences,
115
- USER_COLORS,
116
117
  userTypeValidator,
117
118
  type TLUserPreferences,
118
119
  } 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'
119
132
  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'
120
140
  export {
121
141
  BindingUtil,
122
142
  type BindingOnChangeOptions,
@@ -127,13 +147,6 @@ export {
127
147
  type BindingOnShapeIsolateOptions,
128
148
  type TLBindingUtilConstructor,
129
149
  } 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'
137
150
  export { ClickManager, type TLClickState } from './lib/editor/managers/ClickManager/ClickManager'
138
151
  export { EdgeScrollManager } from './lib/editor/managers/EdgeScrollManager/EdgeScrollManager'
139
152
  export {
@@ -166,7 +179,6 @@ export {
166
179
  } from './lib/editor/managers/TextManager/TextManager'
167
180
  export { UserPreferencesManager } from './lib/editor/managers/UserPreferencesManager/UserPreferencesManager'
168
181
  export { BaseBoxShapeUtil, type TLBaseBoxShape } from './lib/editor/shapes/BaseBoxShapeUtil'
169
- export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
170
182
  export {
171
183
  ShapeUtil,
172
184
  type TLCropInfo,
@@ -183,6 +195,7 @@ export {
183
195
  type TLShapeUtilCanvasSvgDef,
184
196
  type TLShapeUtilConstructor,
185
197
  } from './lib/editor/shapes/ShapeUtil'
198
+ export { GroupShapeUtil } from './lib/editor/shapes/group/GroupShapeUtil'
186
199
  export {
187
200
  getPerfectDashProps,
188
201
  type PerfectDashTerminal,
@@ -192,16 +205,22 @@ export { resizeScaled } from './lib/editor/shapes/shared/resizeScaled'
192
205
  export { BaseBoxShapeTool } from './lib/editor/tools/BaseBoxShapeTool/BaseBoxShapeTool'
193
206
  export { maybeSnapToGrid } from './lib/editor/tools/BaseBoxShapeTool/children/Pointing'
194
207
  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'
195
214
  export { type TLContent } from './lib/editor/types/clipboard-types'
196
215
  export { type TLEventMap, type TLEventMapHandler } from './lib/editor/types/emit-types'
197
216
  export {
198
217
  EVENT_NAME_MAP,
199
218
  type TLBaseEventInfo,
219
+ type TLCLickEventName,
200
220
  type TLCancelEvent,
201
221
  type TLCancelEventInfo,
202
222
  type TLClickEvent,
203
223
  type TLClickEventInfo,
204
- type TLCLickEventName,
205
224
  type TLCompleteEvent,
206
225
  type TLCompleteEventInfo,
207
226
  type TLEnterEventHandler,
@@ -270,12 +289,6 @@ export {
270
289
  type TLResizeHandle,
271
290
  type TLSelectionHandle,
272
291
  } from './lib/editor/types/selection-types'
273
- export {
274
- useDelaySvgExport,
275
- useSvgExportContext,
276
- type SvgExportContext,
277
- type SvgExportDef,
278
- } from './lib/editor/types/SvgExportContext'
279
292
  export { getSvgAsImage } from './lib/exports/getSvgAsImage'
280
293
  export { tlenv } from './lib/globals/environment'
281
294
  export { tlmenus } from './lib/globals/menus'
@@ -339,6 +352,8 @@ export {
339
352
  type SelectionEdge,
340
353
  type SelectionHandle,
341
354
  } from './lib/primitives/Box'
355
+ export { Mat, type MatLike, type MatModel } from './lib/primitives/Mat'
356
+ export { Vec, type VecLike } from './lib/primitives/Vec'
342
357
  export { EASINGS } from './lib/primitives/easings'
343
358
  export { Arc2d } from './lib/primitives/geometry/Arc2d'
344
359
  export { Circle2d } from './lib/primitives/geometry/Circle2d'
@@ -373,8 +388,11 @@ export {
373
388
  polygonIntersectsPolyline,
374
389
  polygonsIntersect,
375
390
  } from './lib/primitives/intersect'
376
- export { Mat, type MatLike, type MatModel } from './lib/primitives/Mat'
377
391
  export {
392
+ HALF_PI,
393
+ PI,
394
+ PI2,
395
+ SIN,
378
396
  angleDistance,
379
397
  approximately,
380
398
  areAnglesCompatible,
@@ -391,36 +409,23 @@ export {
391
409
  getPointOnCircle,
392
410
  getPointsOnArc,
393
411
  getPolygonVertices,
394
- HALF_PI,
395
412
  isSafeFloat,
396
413
  perimeterOfEllipse,
397
- PI,
398
- PI2,
399
414
  pointInPolygon,
400
415
  precise,
401
416
  radiansToDegrees,
402
417
  rangeIntersection,
403
418
  shortAngleDist,
404
- SIN,
405
419
  snapAngle,
406
420
  toDomPrecision,
407
421
  toFixed,
408
422
  toPrecision,
409
423
  } from './lib/primitives/utils'
410
- export { Vec, type VecLike } from './lib/primitives/Vec'
411
424
  export {
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'
425
+ ReadonlySharedStyleMap,
426
+ SharedStyleMap,
427
+ type SharedStyle,
428
+ } from './lib/utils/SharedStylesMap'
424
429
  export { dataUrlToFile, getDefaultCdnBaseUrl } from './lib/utils/assets'
425
430
  export { clampToBrowserMaxCanvasSize, type CanvasMaxSize } from './lib/utils/browserCanvasMaxSize'
426
431
  export {
@@ -456,9 +461,9 @@ export {
456
461
  getFontsFromRichText,
457
462
  type RichTextFontVisitor,
458
463
  type RichTextFontVisitorState,
464
+ type TLTextOptions,
459
465
  type TiptapEditor,
460
466
  type TiptapNode,
461
- type TLTextOptions,
462
467
  } from './lib/utils/richText'
463
468
  export {
464
469
  applyRotationToSnapshotShapes,
@@ -466,14 +471,9 @@ export {
466
471
  type TLRotationSnapshot,
467
472
  } from './lib/utils/rotation'
468
473
  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'
475
474
  export { LocalIndexedDb, Table, type StoreName } from './lib/utils/sync/LocalIndexedDb'
476
475
  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,7 +17,6 @@ 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
21
20
  edgeScrollSpeed?: number | null
22
21
  colorScheme?: 'light' | 'dark' | 'system'
23
22
  isSnapMode?: boolean | null
@@ -45,7 +44,6 @@ export const userTypeValidator: T.Validator<TLUserPreferences> = T.object<TLUser
45
44
  // N.B. These are duplicated in TLdrawAppUser.
46
45
  locale: T.string.nullable().optional(),
47
46
  animationSpeed: T.number.nullable().optional(),
48
- areKeyboardShortcutsEnabled: T.boolean.nullable().optional(),
49
47
  edgeScrollSpeed: T.number.nullable().optional(),
50
48
  colorScheme: T.literalEnum('light', 'dark', 'system').optional(),
51
49
  isSnapMode: T.boolean.nullable().optional(),
@@ -63,7 +61,6 @@ const Versions = {
63
61
  AddDynamicSizeMode: 6,
64
62
  AllowSystemColorScheme: 7,
65
63
  AddPasteAtCursor: 8,
66
- AddKeyboardShortcuts: 9,
67
64
  } as const
68
65
 
69
66
  const CURRENT_VERSION = Math.max(...Object.values(Versions))
@@ -99,9 +96,6 @@ function migrateSnapshot(data: { version: number; user: any }) {
99
96
  if (data.version < Versions.AddPasteAtCursor) {
100
97
  data.user.isPasteAtCursorMode = false
101
98
  }
102
- if (data.version < Versions.AddKeyboardShortcuts) {
103
- data.user.areKeyboardShortcutsEnabled = true
104
- }
105
99
 
106
100
  // finally
107
101
  data.version = CURRENT_VERSION
@@ -145,7 +139,6 @@ export const defaultUserPreferences = Object.freeze({
145
139
  // N.B. These are duplicated in TLdrawAppUser.
146
140
  edgeScrollSpeed: 1,
147
141
  animationSpeed: userPrefersReducedMotion() ? 0 : 1,
148
- areKeyboardShortcutsEnabled: true,
149
142
  isSnapMode: false,
150
143
  isWrapMode: false,
151
144
  isDynamicSizeMode: false,
@@ -1,5 +1,4 @@
1
1
  import { BoxModel, TLDefaultHorizontalAlignStyle } from '@tldraw/tlschema'
2
- import { objectMapKeys } from '@tldraw/utils'
3
2
  import { Editor } from '../../Editor'
4
3
 
5
4
  const fixNewLines = /\r?\n|\r/g
@@ -61,18 +60,10 @@ export interface TLMeasureTextSpanOpts {
61
60
 
62
61
  const spaceCharacterRegex = /\s/
63
62
 
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
-
73
63
  /** @public */
74
64
  export class TextManager {
75
65
  private elm: HTMLDivElement
66
+ private defaultStyles: Record<string, string | null>
76
67
 
77
68
  constructor(public editor: Editor) {
78
69
  const elm = document.createElement('div')
@@ -82,34 +73,31 @@ export class TextManager {
82
73
  elm.tabIndex = -1
83
74
  this.editor.getContainer().appendChild(elm)
84
75
 
85
- this.elm = elm
86
-
87
- for (const key of objectMapKeys(initialDefaultStyles)) {
88
- elm.style.setProperty(key, initialDefaultStyles[key])
76
+ // we need to save the default styles so that we can restore them when we're done
77
+ // these must be the css names, not the js names for the styles
78
+ this.defaultStyles = {
79
+ 'overflow-wrap': 'break-word',
80
+ 'word-break': 'auto',
81
+ width: null,
82
+ height: null,
83
+ 'max-width': null,
84
+ 'min-width': null,
89
85
  }
90
- }
91
86
 
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
- }
87
+ this.elm = elm
107
88
  }
108
89
 
109
90
  dispose() {
110
91
  return this.elm.remove()
111
92
  }
112
93
 
94
+ private resetElmStyles() {
95
+ const { elm, defaultStyles } = this
96
+ for (const key in defaultStyles) {
97
+ elm.style.setProperty(key, defaultStyles[key])
98
+ }
99
+ }
100
+
113
101
  measureText(textToMeasure: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
114
102
  const div = document.createElement('div')
115
103
  div.textContent = normalizeTextForDom(textToMeasure)
@@ -119,36 +107,54 @@ export class TextManager {
119
107
  measureHtml(html: string, opts: TLMeasureTextOpts): BoxModel & { scrollWidth: number } {
120
108
  const { elm } = this
121
109
 
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,
110
+ if (opts.otherStyles) {
111
+ for (const key in opts.otherStyles) {
112
+ if (!this.defaultStyles[key]) {
113
+ // we need to save the original style so that we can restore it when we're done
114
+ this.defaultStyles[key] = elm.style.getPropertyValue(key)
115
+ }
116
+ }
133
117
  }
134
118
 
135
- const restoreStyles = this.setElementStyles(newStyles)
119
+ elm.innerHTML = html
136
120
 
137
- try {
138
- elm.innerHTML = html
121
+ // Apply the default styles to the element (for all styles here or that were ever seen in opts.otherStyles)
122
+ this.resetElmStyles()
139
123
 
140
- const scrollWidth = opts.measureScrollWidth ? elm.scrollWidth : 0
141
- const rect = elm.getBoundingClientRect()
124
+ elm.style.setProperty('font-family', opts.fontFamily)
125
+ elm.style.setProperty('font-style', opts.fontStyle)
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)
142
130
 
143
- return {
144
- x: 0,
145
- y: 0,
146
- w: rect.width,
147
- h: rect.height,
148
- scrollWidth,
131
+ if (opts.maxWidth) {
132
+ elm.style.setProperty('max-width', opts.maxWidth + 'px')
133
+ }
134
+
135
+ if (opts.minWidth) {
136
+ elm.style.setProperty('min-width', opts.minWidth + 'px')
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)
149
146
  }
150
- } finally {
151
- restoreStyles()
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,
152
158
  }
153
159
  }
154
160
 
@@ -268,68 +274,82 @@ export class TextManager {
268
274
 
269
275
  const { elm } = this
270
276
 
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
+
271
299
  const shouldTruncateToFirstLine =
272
300
  opts.overflow === 'truncate-ellipsis' || opts.overflow === 'truncate-clip'
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,
301
+
302
+ if (shouldTruncateToFirstLine) {
303
+ elm.style.setProperty('overflow-wrap', 'anywhere')
304
+ elm.style.setProperty('word-break', 'break-all')
286
305
  }
287
- const restoreStyles = this.setElementStyles(newStyles)
288
306
 
289
- try {
290
- const normalizedText = normalizeTextForDom(textToMeasure)
307
+ if (opts.otherStyles) {
308
+ for (const [key, value] of Object.entries(opts.otherStyles)) {
309
+ elm.style.setProperty(key, value)
310
+ }
311
+ }
291
312
 
292
- // Render the text into the measurement element:
293
- elm.textContent = normalizedText
313
+ const normalizedText = normalizeTextForDom(textToMeasure)
294
314
 
295
- // actually measure the text:
296
- const { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {
297
- shouldTruncateToFirstLine,
298
- })
315
+ // Render the text into the measurement element:
316
+ elm.textContent = normalizedText
299
317
 
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
- }
318
+ // actually measure the text:
319
+ const { spans, didTruncate } = this.measureElementTextNodeSpans(elm, {
320
+ shouldTruncateToFirstLine,
321
+ })
329
322
 
330
- return spans
331
- } finally {
332
- restoreStyles()
323
+ if (opts.overflow === 'truncate-ellipsis' && didTruncate) {
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`)
330
+ elm.textContent = normalizedText
331
+ const truncatedSpans = this.measureElementTextNodeSpans(elm, {
332
+ shouldTruncateToFirstLine: true,
333
+ }).spans
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
+ },
348
+ })
349
+
350
+ return truncatedSpans
333
351
  }
352
+
353
+ return spans
334
354
  }
335
355
  }
@@ -24,7 +24,6 @@ describe('UserPreferencesManager', () => {
24
24
  color: '#FF802B',
25
25
  locale: 'en',
26
26
  animationSpeed: 1,
27
- areKeyboardShortcutsEnabled: true,
28
27
  edgeScrollSpeed: 1,
29
28
  colorScheme: 'light',
30
29
  isSnapMode: false,
@@ -230,7 +229,6 @@ describe('UserPreferencesManager', () => {
230
229
  locale: mockUserPreferences.locale,
231
230
  color: mockUserPreferences.color,
232
231
  animationSpeed: mockUserPreferences.animationSpeed,
233
- areKeyboardShortcutsEnabled: mockUserPreferences.areKeyboardShortcutsEnabled,
234
232
  isSnapMode: mockUserPreferences.isSnapMode,
235
233
  colorScheme: mockUserPreferences.colorScheme,
236
234
  isDarkMode: false, // light mode
@@ -364,21 +362,6 @@ describe('UserPreferencesManager', () => {
364
362
  })
365
363
  })
366
364
 
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
-
382
365
  describe('getEdgeScrollSpeed', () => {
383
366
  it('should return user edge scroll speed', () => {
384
367
  expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
@@ -500,7 +483,6 @@ describe('UserPreferencesManager', () => {
500
483
  color: null,
501
484
  locale: null,
502
485
  animationSpeed: null,
503
- areKeyboardShortcutsEnabled: null,
504
486
  edgeScrollSpeed: null,
505
487
  isSnapMode: null,
506
488
  isWrapMode: null,
@@ -514,9 +496,6 @@ describe('UserPreferencesManager', () => {
514
496
  expect(userPreferencesManager.getColor()).toBe(defaultUserPreferences.color)
515
497
  expect(userPreferencesManager.getLocale()).toBe(defaultUserPreferences.locale)
516
498
  expect(userPreferencesManager.getAnimationSpeed()).toBe(defaultUserPreferences.animationSpeed)
517
- expect(userPreferencesManager.getAreKeyboardShortcutsEnabled()).toBe(
518
- defaultUserPreferences.areKeyboardShortcutsEnabled
519
- )
520
499
  expect(userPreferencesManager.getEdgeScrollSpeed()).toBe(
521
500
  defaultUserPreferences.edgeScrollSpeed
522
501
  )
@@ -43,7 +43,6 @@ export class UserPreferencesManager {
43
43
  locale: this.getLocale(),
44
44
  color: this.getColor(),
45
45
  animationSpeed: this.getAnimationSpeed(),
46
- areKeyboardShortcutsEnabled: this.getAreKeyboardShortcutsEnabled(),
47
46
  isSnapMode: this.getIsSnapMode(),
48
47
  colorScheme: this.user.userPreferences.get().colorScheme,
49
48
  isDarkMode: this.getIsDarkMode(),
@@ -76,13 +75,6 @@ export class UserPreferencesManager {
76
75
  return this.user.userPreferences.get().animationSpeed ?? defaultUserPreferences.animationSpeed
77
76
  }
78
77
 
79
- @computed getAreKeyboardShortcutsEnabled() {
80
- return (
81
- this.user.userPreferences.get().areKeyboardShortcutsEnabled ??
82
- defaultUserPreferences.areKeyboardShortcutsEnabled
83
- )
84
- }
85
-
86
78
  @computed getId() {
87
79
  return this.user.userPreferences.get().id
88
80
  }
@@ -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) as Uint8Array
421
421
 
422
422
  return crypto.subtle.importKey(
423
423
  'pkcs8',