@tldraw/editor 3.15.0-canary.2fa0050cd4a6 → 3.15.0-canary.30a6212789b4
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 +41 -45
- package/dist-cjs/index.js +16 -16
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +1 -7
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +2 -20
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +101 -96
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +2 -7
- 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 +0 -4
- package/dist-cjs/lib/primitives/utils.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +1 -0
- 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 +41 -45
- package/dist-esm/index.mjs +41 -41
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +1 -7
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +2 -20
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +101 -96
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +2 -7
- 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 +0 -4
- package/dist-esm/lib/primitives/utils.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +1 -0
- 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 +0 -7
- package/src/lib/editor/Editor.test.ts +0 -407
- package/src/lib/editor/Editor.ts +4 -29
- package/src/lib/editor/managers/TextManager/TextManager.ts +128 -108
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +0 -21
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +0 -8
- package/src/lib/license/LicenseManager.test.ts +1 -1
- package/src/lib/primitives/intersect.ts +5 -12
- package/src/lib/primitives/utils.ts +0 -11
- package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -0
- package/src/version.ts +3 -3
- package/src/lib/primitives/intersect.test.ts +0 -946
|
@@ -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
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
119
|
+
elm.innerHTML = html
|
|
136
120
|
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
141
|
-
|
|
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
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
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
|
-
}
|
|
151
|
-
|
|
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
|
-
|
|
274
|
-
|
|
275
|
-
'
|
|
276
|
-
'
|
|
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
|
-
|
|
290
|
-
const
|
|
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
|
-
|
|
293
|
-
elm.textContent = normalizedText
|
|
313
|
+
const normalizedText = normalizeTextForDom(textToMeasure)
|
|
294
314
|
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
shouldTruncateToFirstLine,
|
|
298
|
-
})
|
|
315
|
+
// Render the text into the measurement element:
|
|
316
|
+
elm.textContent = normalizedText
|
|
299
317
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
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
|
-
|
|
331
|
-
|
|
332
|
-
|
|
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',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Box } from './Box'
|
|
2
|
-
import {
|
|
2
|
+
import { pointInPolygon } from './utils'
|
|
3
3
|
import { Vec, VecLike } from './Vec'
|
|
4
4
|
|
|
5
5
|
// need even more intersections? See https://gist.github.com/steveruizok/35c02d526c707003a5c79761bfb89a52
|
|
@@ -17,8 +17,7 @@ export function intersectLineSegmentLineSegment(
|
|
|
17
17
|
a1: VecLike,
|
|
18
18
|
a2: VecLike,
|
|
19
19
|
b1: VecLike,
|
|
20
|
-
b2: VecLike
|
|
21
|
-
precision = 1e-10
|
|
20
|
+
b2: VecLike
|
|
22
21
|
) {
|
|
23
22
|
const ABx = a1.x - b1.x
|
|
24
23
|
const ABy = a1.y - b1.y
|
|
@@ -30,19 +29,14 @@ export function intersectLineSegmentLineSegment(
|
|
|
30
29
|
const ub_t = AVx * ABy - AVy * ABx
|
|
31
30
|
const u_b = BVy * AVx - BVx * AVy
|
|
32
31
|
|
|
33
|
-
if (
|
|
32
|
+
if (ua_t === 0 || ub_t === 0) return null // coincident
|
|
34
33
|
|
|
35
|
-
if (
|
|
34
|
+
if (u_b === 0) return null // parallel
|
|
36
35
|
|
|
37
36
|
if (u_b !== 0) {
|
|
38
37
|
const ua = ua_t / u_b
|
|
39
38
|
const ub = ub_t / u_b
|
|
40
|
-
if (
|
|
41
|
-
approximatelyLte(0, ua, precision) &&
|
|
42
|
-
approximatelyLte(ua, 1, precision) &&
|
|
43
|
-
approximatelyLte(0, ub, precision) &&
|
|
44
|
-
approximatelyLte(ub, 1, precision)
|
|
45
|
-
) {
|
|
39
|
+
if (0 <= ua && ua <= 1 && 0 <= ub && ub <= 1) {
|
|
46
40
|
return Vec.AddXY(a1, ua * AVx, ua * AVy)
|
|
47
41
|
}
|
|
48
42
|
}
|
|
@@ -131,7 +125,6 @@ export function intersectLineSegmentPolygon(a1: VecLike, a2: VecLike, points: Ve
|
|
|
131
125
|
points[i - 1],
|
|
132
126
|
points[i % points.length]
|
|
133
127
|
)
|
|
134
|
-
|
|
135
128
|
if (segmentIntersection) result.push(segmentIntersection)
|
|
136
129
|
}
|
|
137
130
|
|
|
@@ -77,17 +77,6 @@ export function approximately(a: number, b: number, precision = 0.000001) {
|
|
|
77
77
|
return Math.abs(a - b) <= precision
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
/**
|
|
81
|
-
* Whether a number is approximately less than or equal to another number.
|
|
82
|
-
*
|
|
83
|
-
* @param a - The first number.
|
|
84
|
-
* @param b - The second number.
|
|
85
|
-
* @public
|
|
86
|
-
*/
|
|
87
|
-
export function approximatelyLte(a: number, b: number, precision = 0.000001) {
|
|
88
|
-
return a < b || approximately(a, b, precision)
|
|
89
|
-
}
|
|
90
|
-
|
|
91
80
|
/**
|
|
92
81
|
* Find the approximate perimeter of an ellipse.
|
|
93
82
|
*
|
|
@@ -266,6 +266,7 @@ export class TLLocalSyncClient {
|
|
|
266
266
|
|
|
267
267
|
private isPersisting = false
|
|
268
268
|
private didLastWriteError = false
|
|
269
|
+
// eslint-disable-next-line no-restricted-globals
|
|
269
270
|
private scheduledPersistTimeout: ReturnType<typeof setTimeout> | null = null
|
|
270
271
|
|
|
271
272
|
/**
|
package/src/version.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// This file is automatically generated by internal/scripts/refresh-assets.ts.
|
|
2
2
|
// Do not edit manually. Or do, I'm a comment, not a cop.
|
|
3
3
|
|
|
4
|
-
export const version = '3.15.0-canary.
|
|
4
|
+
export const version = '3.15.0-canary.30a6212789b4'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-07-
|
|
8
|
-
patch: '2025-07-
|
|
7
|
+
minor: '2025-07-03T09:11:17.820Z',
|
|
8
|
+
patch: '2025-07-03T09:11:17.820Z',
|
|
9
9
|
}
|