@tldraw/editor 3.9.0-internal.7f0e15f4f7d9 → 3.9.0
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/CHANGELOG.md +90 -0
- package/README.md +1 -1
- package/dist-cjs/index.d.ts +36 -229
- package/dist-cjs/index.js +1 -9
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +6 -33
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +0 -7
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultErrorFallback.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +435 -308
- package/dist-cjs/lib/editor/Editor.js.map +3 -3
- package/dist-cjs/lib/editor/managers/TextManager.js +17 -23
- package/dist-cjs/lib/editor/managers/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +7 -13
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/types/emit-types.js.map +1 -1
- package/dist-cjs/lib/editor/types/external-content.js.map +1 -1
- package/dist-cjs/lib/exports/FontEmbedder.js +2 -7
- package/dist-cjs/lib/exports/FontEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/StyleEmbedder.js +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/exportToSvg.js +2 -3
- package/dist-cjs/lib/exports/exportToSvg.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js +1 -18
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/exports/parseCss.js +0 -1
- package/dist-cjs/lib/exports/parseCss.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js +1 -1
- package/dist-cjs/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePassThroughWheelEvents.js.map +2 -2
- package/dist-cjs/lib/options.js +1 -2
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/utils/dom.js +1 -1
- package/dist-cjs/lib/utils/dom.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 +36 -229
- package/dist-esm/index.mjs +1 -13
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +7 -34
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +1 -8
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultErrorFallback.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +432 -312
- package/dist-esm/lib/editor/Editor.mjs.map +3 -3
- package/dist-esm/lib/editor/managers/TextManager.mjs +17 -23
- package/dist-esm/lib/editor/managers/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +7 -13
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/exports/FontEmbedder.mjs +2 -7
- package/dist-esm/lib/exports/FontEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/exportToSvg.mjs +2 -3
- package/dist-esm/lib/exports/exportToSvg.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs +2 -19
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/exports/parseCss.mjs +0 -1
- package/dist-esm/lib/exports/parseCss.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs +1 -1
- package/dist-esm/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePassThroughWheelEvents.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +1 -2
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/utils/dom.mjs +1 -1
- package/dist-esm/lib/utils/dom.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +13 -127
- package/package.json +7 -10
- package/src/index.ts +2 -15
- package/src/lib/TldrawEditor.tsx +4 -52
- package/src/lib/components/Shape.tsx +1 -9
- package/src/lib/components/default-components/DefaultErrorFallback.tsx +5 -3
- package/src/lib/editor/Editor.ts +561 -362
- package/src/lib/editor/managers/TextManager.ts +17 -42
- package/src/lib/editor/shapes/ShapeUtil.ts +32 -18
- package/src/lib/editor/types/emit-types.ts +0 -1
- package/src/lib/editor/types/external-content.ts +0 -1
- package/src/lib/exports/FontEmbedder.ts +1 -13
- package/src/lib/exports/StyleEmbedder.ts +1 -1
- package/src/lib/exports/exportToSvg.tsx +3 -4
- package/src/lib/exports/getSvgJsx.tsx +3 -22
- package/src/lib/exports/parseCss.ts +0 -1
- package/src/lib/hooks/useCanvasEvents.ts +1 -2
- package/src/lib/hooks/useFixSafariDoubleTapZoomPencilEvents.ts +0 -1
- package/src/lib/hooks/usePassThroughWheelEvents.ts +1 -0
- package/src/lib/options.ts +0 -7
- package/src/lib/utils/dom.ts +1 -1
- package/src/version.ts +3 -3
- package/dist-cjs/lib/editor/managers/FontManager.js +0 -167
- package/dist-cjs/lib/editor/managers/FontManager.js.map +0 -7
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js +0 -48
- package/dist-cjs/lib/hooks/usePassThroughMouseOverEvents.js.map +0 -7
- package/dist-cjs/lib/hooks/useViewportHeight.js +0 -56
- package/dist-cjs/lib/hooks/useViewportHeight.js.map +0 -7
- package/dist-cjs/lib/utils/richText.js +0 -46
- package/dist-cjs/lib/utils/richText.js.map +0 -7
- package/dist-esm/lib/editor/managers/FontManager.mjs +0 -153
- package/dist-esm/lib/editor/managers/FontManager.mjs.map +0 -7
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs +0 -28
- package/dist-esm/lib/hooks/usePassThroughMouseOverEvents.mjs.map +0 -7
- package/dist-esm/lib/hooks/useViewportHeight.mjs +0 -36
- package/dist-esm/lib/hooks/useViewportHeight.mjs.map +0 -7
- package/dist-esm/lib/utils/richText.mjs +0 -26
- package/dist-esm/lib/utils/richText.mjs.map +0 -7
- package/src/lib/editor/managers/FontManager.ts +0 -252
- package/src/lib/hooks/usePassThroughMouseOverEvents.ts +0 -29
- package/src/lib/hooks/useViewportHeight.ts +0 -37
- package/src/lib/utils/richText.ts +0 -72
|
@@ -65,57 +65,32 @@ export class TextManager {
|
|
|
65
65
|
padding: string
|
|
66
66
|
disableOverflowWrapBreaking?: boolean
|
|
67
67
|
}
|
|
68
|
-
): BoxModel & { scrollWidth: number } {
|
|
69
|
-
const div = document.createElement('div')
|
|
70
|
-
div.textContent = normalizeTextForDom(textToMeasure)
|
|
71
|
-
return this.measureHtml(div.innerHTML, opts)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
measureHtml(
|
|
75
|
-
html: string,
|
|
76
|
-
opts: {
|
|
77
|
-
fontStyle: string
|
|
78
|
-
fontWeight: string
|
|
79
|
-
fontFamily: string
|
|
80
|
-
fontSize: number
|
|
81
|
-
lineHeight: number
|
|
82
|
-
/**
|
|
83
|
-
* When maxWidth is a number, the text will be wrapped to that maxWidth. When maxWidth
|
|
84
|
-
* is null, the text will be measured without wrapping, but explicit line breaks and
|
|
85
|
-
* space are preserved.
|
|
86
|
-
*/
|
|
87
|
-
maxWidth: null | number
|
|
88
|
-
minWidth?: null | number
|
|
89
|
-
padding: string
|
|
90
|
-
disableOverflowWrapBreaking?: boolean
|
|
91
|
-
}
|
|
92
68
|
): BoxModel & { scrollWidth: number } {
|
|
93
69
|
// Duplicate our base element; we don't need to clone deep
|
|
94
|
-
const
|
|
95
|
-
this.editor.getContainer().appendChild(
|
|
96
|
-
wrapperElm.innerHTML = html
|
|
97
|
-
this.baseElem.insertAdjacentElement('afterend', wrapperElm)
|
|
70
|
+
const elm = this.baseElem.cloneNode() as HTMLDivElement
|
|
71
|
+
this.editor.getContainer().appendChild(elm)
|
|
98
72
|
|
|
99
|
-
|
|
73
|
+
elm.setAttribute('dir', 'auto')
|
|
100
74
|
// N.B. This property, while discouraged ("intended for Document Type Definition (DTD) designers")
|
|
101
75
|
// is necessary for ensuring correct mixed RTL/LTR behavior when exporting SVGs.
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
76
|
+
elm.style.setProperty('unicode-bidi', 'plaintext')
|
|
77
|
+
elm.style.setProperty('font-family', opts.fontFamily)
|
|
78
|
+
elm.style.setProperty('font-style', opts.fontStyle)
|
|
79
|
+
elm.style.setProperty('font-weight', opts.fontWeight)
|
|
80
|
+
elm.style.setProperty('font-size', opts.fontSize + 'px')
|
|
81
|
+
elm.style.setProperty('line-height', opts.lineHeight * opts.fontSize + 'px')
|
|
82
|
+
elm.style.setProperty('max-width', opts.maxWidth === null ? null : opts.maxWidth + 'px')
|
|
83
|
+
elm.style.setProperty('min-width', opts.minWidth === null ? null : opts.minWidth + 'px')
|
|
84
|
+
elm.style.setProperty('padding', opts.padding)
|
|
85
|
+
elm.style.setProperty(
|
|
112
86
|
'overflow-wrap',
|
|
113
87
|
opts.disableOverflowWrapBreaking ? 'normal' : 'break-word'
|
|
114
88
|
)
|
|
115
89
|
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
90
|
+
elm.textContent = normalizeTextForDom(textToMeasure)
|
|
91
|
+
const scrollWidth = elm.scrollWidth
|
|
92
|
+
const rect = elm.getBoundingClientRect()
|
|
93
|
+
elm.remove()
|
|
119
94
|
|
|
120
95
|
return {
|
|
121
96
|
x: 0,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
import { EMPTY_ARRAY } from '@tldraw/state'
|
|
3
2
|
import { LegacyMigrations, MigrationSequence } from '@tldraw/store'
|
|
4
3
|
import {
|
|
5
4
|
RecordProps,
|
|
@@ -15,7 +14,6 @@ import { Box, SelectionHandle } from '../../primitives/Box'
|
|
|
15
14
|
import { Vec } from '../../primitives/Vec'
|
|
16
15
|
import { Geometry2d } from '../../primitives/geometry/Geometry2d'
|
|
17
16
|
import type { Editor } from '../Editor'
|
|
18
|
-
import { TLFontFace } from '../managers/FontManager'
|
|
19
17
|
import { BoundsSnapGeometry } from '../managers/SnapManager/BoundsSnaps'
|
|
20
18
|
import { HandleSnapGeometry } from '../managers/SnapManager/HandleSnaps'
|
|
21
19
|
import { SvgExportContext } from '../types/SvgExportContext'
|
|
@@ -38,7 +36,7 @@ export interface TLShapeUtilConstructor<
|
|
|
38
36
|
*
|
|
39
37
|
* @public
|
|
40
38
|
*/
|
|
41
|
-
export interface TLShapeUtilCanBindOpts<Shape extends TLUnknownShape =
|
|
39
|
+
export interface TLShapeUtilCanBindOpts<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
42
40
|
/** The type of shape referenced by the `fromId` of the binding. */
|
|
43
41
|
fromShapeType: string
|
|
44
42
|
/** The type of shape referenced by the `toId` of the binding. */
|
|
@@ -47,6 +45,27 @@ export interface TLShapeUtilCanBindOpts<Shape extends TLUnknownShape = TLShape>
|
|
|
47
45
|
bindingType: string
|
|
48
46
|
}
|
|
49
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Options passed to {@link ShapeUtil.canBeLaidOut}.
|
|
50
|
+
*
|
|
51
|
+
* @public
|
|
52
|
+
*/
|
|
53
|
+
export interface TLShapeUtilCanBeLaidOutOpts {
|
|
54
|
+
/** The type of action causing the layout. */
|
|
55
|
+
type?: 'align' | 'distribute' | 'pack' | 'stack' | 'flip' | 'stretch'
|
|
56
|
+
/** The other shapes being laid out */
|
|
57
|
+
shapes?: TLShape[]
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/** Additional options for the {@link ShapeUtil.getGeometry} method.
|
|
61
|
+
*
|
|
62
|
+
* @public
|
|
63
|
+
*/
|
|
64
|
+
export interface TLGeometryOpts {
|
|
65
|
+
/** The context in which the geometry is being requested. */
|
|
66
|
+
context?: string
|
|
67
|
+
}
|
|
68
|
+
|
|
50
69
|
/** @public */
|
|
51
70
|
export interface TLShapeUtilCanvasSvgDef {
|
|
52
71
|
key: string
|
|
@@ -130,9 +149,10 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
130
149
|
* Get the shape's geometry.
|
|
131
150
|
*
|
|
132
151
|
* @param shape - The shape.
|
|
152
|
+
* @param opts - Additional options for the request.
|
|
133
153
|
* @public
|
|
134
154
|
*/
|
|
135
|
-
abstract getGeometry(shape: Shape): Geometry2d
|
|
155
|
+
abstract getGeometry(shape: Shape, opts?: TLGeometryOpts): Geometry2d
|
|
136
156
|
|
|
137
157
|
/**
|
|
138
158
|
* Get a JSX element for the shape (as an HTML element).
|
|
@@ -150,20 +170,10 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
150
170
|
*/
|
|
151
171
|
abstract indicator(shape: Shape): any
|
|
152
172
|
|
|
153
|
-
/**
|
|
154
|
-
* Get the font faces that should be rendered in the document in order for this shape to render
|
|
155
|
-
* correctly.
|
|
156
|
-
*
|
|
157
|
-
* @param shape - The shape.
|
|
158
|
-
* @public
|
|
159
|
-
*/
|
|
160
|
-
getFontFaces(shape: Shape): TLFontFace[] {
|
|
161
|
-
return EMPTY_ARRAY
|
|
162
|
-
}
|
|
163
|
-
|
|
164
173
|
/**
|
|
165
174
|
* Whether the shape can be snapped to by another shape.
|
|
166
175
|
*
|
|
176
|
+
* @param shape - The shape.
|
|
167
177
|
* @public
|
|
168
178
|
*/
|
|
169
179
|
canSnap(_shape: Shape): boolean {
|
|
@@ -184,7 +194,7 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
184
194
|
*
|
|
185
195
|
* @public
|
|
186
196
|
*/
|
|
187
|
-
canBind(_opts: TLShapeUtilCanBindOpts
|
|
197
|
+
canBind(_opts: TLShapeUtilCanBindOpts): boolean {
|
|
188
198
|
return true
|
|
189
199
|
}
|
|
190
200
|
|
|
@@ -225,11 +235,15 @@ export abstract class ShapeUtil<Shape extends TLUnknownShape = TLUnknownShape> {
|
|
|
225
235
|
}
|
|
226
236
|
|
|
227
237
|
/**
|
|
228
|
-
* Whether the shape
|
|
238
|
+
* Whether the shape can participate in layout functions such as alignment or distribution.
|
|
239
|
+
*
|
|
240
|
+
* @param shape - The shape.
|
|
241
|
+
* @param info - Additional context information: the type of action causing the layout and the
|
|
242
|
+
* @public
|
|
229
243
|
*
|
|
230
244
|
* @public
|
|
231
245
|
*/
|
|
232
|
-
canBeLaidOut(_shape: Shape): boolean {
|
|
246
|
+
canBeLaidOut(_shape: Shape, _info: TLShapeUtilCanBeLaidOutOpts): boolean {
|
|
233
247
|
return true
|
|
234
248
|
}
|
|
235
249
|
|
|
@@ -2,8 +2,6 @@ import { assert, bind, compact } from '@tldraw/utils'
|
|
|
2
2
|
import { fetchCache, resourceToDataUrl } from './fetchCache'
|
|
3
3
|
import { ParsedFontFace, parseCss, parseCssFontFaces, parseCssFontFamilyValue } from './parseCss'
|
|
4
4
|
|
|
5
|
-
export const SVG_EXPORT_CLASSNAME = 'tldraw-svg-export'
|
|
6
|
-
|
|
7
5
|
/**
|
|
8
6
|
* Because SVGs cannot refer to external CSS/font resources, any web fonts used in the SVG must be
|
|
9
7
|
* embedded as data URLs in inlined @font-face declarations. This class is responsible for
|
|
@@ -83,17 +81,7 @@ export class FontEmbedder {
|
|
|
83
81
|
async function getCurrentDocumentFontFaces() {
|
|
84
82
|
const fontFaces: (ParsedFontFace[] | Promise<ParsedFontFace[] | null>)[] = []
|
|
85
83
|
|
|
86
|
-
|
|
87
|
-
// Because of this, and because we do a setTimeout to delay removing that node from the
|
|
88
|
-
// DOM, when looking at document.styleSheets the number of nodes and stylesheets
|
|
89
|
-
// can grow unbounded (especially when using "Debug svg" and moving shapes around).
|
|
90
|
-
// To avoid this, we filter out the stylesheets that are part of the SVG export.
|
|
91
|
-
const styleSheetsWithoutSvgExports = Array.from(document.styleSheets).filter(
|
|
92
|
-
(styleSheet) =>
|
|
93
|
-
!(styleSheet.ownerNode as HTMLElement | null)?.closest(`.${SVG_EXPORT_CLASSNAME}`)
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
for (const styleSheet of styleSheetsWithoutSvgExports) {
|
|
84
|
+
for (const styleSheet of document.styleSheets) {
|
|
97
85
|
let cssRules
|
|
98
86
|
try {
|
|
99
87
|
cssRules = styleSheet.cssRules
|
|
@@ -242,7 +242,7 @@ function styleFromComputedStyle(
|
|
|
242
242
|
{ defaultStyles, parentStyles }: ReadStyleOpts
|
|
243
243
|
) {
|
|
244
244
|
const styles: Record<string, string> = {}
|
|
245
|
-
for (const
|
|
245
|
+
for (const property of style) {
|
|
246
246
|
if (!shouldIncludeCssProperty(property)) continue
|
|
247
247
|
|
|
248
248
|
const value = style.getPropertyValue(property)
|
|
@@ -4,7 +4,6 @@ import { flushSync } from 'react-dom'
|
|
|
4
4
|
import { createRoot } from 'react-dom/client'
|
|
5
5
|
import { Editor } from '../editor/Editor'
|
|
6
6
|
import { TLSvgExportOptions } from '../editor/types/misc-types'
|
|
7
|
-
import { SVG_EXPORT_CLASSNAME } from './FontEmbedder'
|
|
8
7
|
import { StyleEmbedder } from './StyleEmbedder'
|
|
9
8
|
import { embedMedia } from './embedMedia'
|
|
10
9
|
import { getSvgJsx } from './getSvgJsx'
|
|
@@ -27,7 +26,7 @@ export async function exportToSvg(
|
|
|
27
26
|
// <foreignObject> elements have their styles and content inlined correctly.
|
|
28
27
|
const container = editor.getContainer()
|
|
29
28
|
const renderTarget = document.createElement('div')
|
|
30
|
-
renderTarget.className =
|
|
29
|
+
renderTarget.className = 'tldraw-svg-export'
|
|
31
30
|
// we hide the element visually, but we don't want it to be focusable or interactive in any way either
|
|
32
31
|
renderTarget.inert = true
|
|
33
32
|
renderTarget.tabIndex = -1
|
|
@@ -84,9 +83,9 @@ export async function exportToSvg(
|
|
|
84
83
|
|
|
85
84
|
async function applyChangesToForeignObjects(svg: SVGSVGElement) {
|
|
86
85
|
// If any shapes have their own <foreignObject> elements, we don't want to mess with them. Our
|
|
87
|
-
// ones that we need to embed will have a class of `tl-
|
|
86
|
+
// ones that we need to embed will have a class of `tl-shape-foreign-object`.
|
|
88
87
|
const foreignObjectChildren = [
|
|
89
|
-
...svg.querySelectorAll('foreignObject.tl-
|
|
88
|
+
...svg.querySelectorAll('foreignObject.tl-shape-foreign-object > *'),
|
|
90
89
|
]
|
|
91
90
|
if (!foreignObjectChildren.length) return
|
|
92
91
|
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
TLShapeId,
|
|
7
7
|
getDefaultColorTheme,
|
|
8
8
|
} from '@tldraw/tlschema'
|
|
9
|
-
import { hasOwnProperty, promiseWithResolve
|
|
9
|
+
import { hasOwnProperty, promiseWithResolve } from '@tldraw/utils'
|
|
10
10
|
import {
|
|
11
11
|
ComponentType,
|
|
12
12
|
Fragment,
|
|
@@ -21,7 +21,6 @@ import { flushSync } from 'react-dom'
|
|
|
21
21
|
import { ErrorBoundary } from '../components/ErrorBoundary'
|
|
22
22
|
import { InnerShape, InnerShapeBackground } from '../components/Shape'
|
|
23
23
|
import { Editor, TLRenderingShape } from '../editor/Editor'
|
|
24
|
-
import { TLFontFace } from '../editor/managers/FontManager'
|
|
25
24
|
import { ShapeUtil } from '../editor/shapes/ShapeUtil'
|
|
26
25
|
import {
|
|
27
26
|
SvgExportContext,
|
|
@@ -206,6 +205,7 @@ function SvgExport({
|
|
|
206
205
|
;(async () => {
|
|
207
206
|
const shapeDefs: Record<string, { pending: false; element: ReactElement }> = {}
|
|
208
207
|
|
|
208
|
+
// Then render everything. The shapes with assets should all hit the cache
|
|
209
209
|
const unorderedShapeElementPromises = renderingShapes.map(
|
|
210
210
|
async ({ id, opacity, index, backgroundIndex }) => {
|
|
211
211
|
// Don't render the frame if we're only exporting a single frame and it's children
|
|
@@ -340,25 +340,6 @@ function SvgExport({
|
|
|
340
340
|
})()
|
|
341
341
|
}, [bbox, editor, exportContext, masksId, renderingShapes, singleFrameShapeId, stateAtom])
|
|
342
342
|
|
|
343
|
-
useEffect(() => {
|
|
344
|
-
const fontsInUse = new Set<TLFontFace>()
|
|
345
|
-
for (const { id } of renderingShapes) {
|
|
346
|
-
for (const font of editor.fonts.getShapeFontFaces(id)) {
|
|
347
|
-
fontsInUse.add(font)
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
for (const font of fontsInUse) {
|
|
352
|
-
addExportDef({
|
|
353
|
-
key: uniqueId(),
|
|
354
|
-
getElement: async () => {
|
|
355
|
-
const declaration = await editor.fonts.toEmbeddedCssDeclaration(font)
|
|
356
|
-
return <style>{declaration}</style>
|
|
357
|
-
},
|
|
358
|
-
})
|
|
359
|
-
}
|
|
360
|
-
}, [editor, renderingShapes, addExportDef])
|
|
361
|
-
|
|
362
343
|
useEffect(() => {
|
|
363
344
|
if (shapeElements === null) return
|
|
364
345
|
onMount()
|
|
@@ -427,7 +408,7 @@ function ForeignObjectShape({
|
|
|
427
408
|
y={bbox.minY}
|
|
428
409
|
width={bbox.w}
|
|
429
410
|
height={bbox.h}
|
|
430
|
-
className="tl-shape-foreign-object
|
|
411
|
+
className="tl-shape-foreign-object"
|
|
431
412
|
>
|
|
432
413
|
<div
|
|
433
414
|
className={className}
|
|
@@ -100,9 +100,8 @@ export function useCanvasEvents() {
|
|
|
100
100
|
if (
|
|
101
101
|
e.target.tagName !== 'A' &&
|
|
102
102
|
e.target.tagName !== 'TEXTAREA' &&
|
|
103
|
-
e.target.isContentEditable &&
|
|
104
103
|
// When in EditingShape state, we are actually clicking on a 'DIV'
|
|
105
|
-
// not A/TEXTAREA
|
|
104
|
+
// not A/TEXTAREA element yet. So, to preserve cursor position
|
|
106
105
|
// for edit mode on mobile we need to not preventDefault.
|
|
107
106
|
// TODO: Find out if we still need this preventDefault in general though.
|
|
108
107
|
!(editor.getEditingShape() && e.target.className.includes('tl-text-content'))
|
|
@@ -25,7 +25,6 @@ export function useFixSafariDoubleTapZoomPencilEvents(ref: React.RefObject<HTMLE
|
|
|
25
25
|
// Allow events to propagate if the app is editing a shape, or if the event is occurring in a text area or input
|
|
26
26
|
if (
|
|
27
27
|
IGNORED_TAGS.includes((target as Element).tagName?.toLocaleLowerCase()) ||
|
|
28
|
-
(target as HTMLElement).isContentEditable ||
|
|
29
28
|
editor.isIn('select.editing_shape')
|
|
30
29
|
) {
|
|
31
30
|
return
|
|
@@ -5,6 +5,7 @@ import { useContainer } from './useContainer'
|
|
|
5
5
|
/** @public */
|
|
6
6
|
export function usePassThroughWheelEvents(ref: RefObject<HTMLElement>) {
|
|
7
7
|
if (!ref) throw Error('usePassThroughWheelEvents must be passed a ref')
|
|
8
|
+
|
|
8
9
|
const container = useContainer()
|
|
9
10
|
|
|
10
11
|
useEffect(() => {
|
package/src/lib/options.ts
CHANGED
|
@@ -69,12 +69,6 @@ export interface TldrawOptions {
|
|
|
69
69
|
* By default, the toolbar items are accessible via number shortcuts according to their order. To disable this, set this option to false.
|
|
70
70
|
*/
|
|
71
71
|
readonly enableToolbarKeyboardShortcuts: boolean
|
|
72
|
-
/**
|
|
73
|
-
* The maximum number of fonts that will be loaded while blocking the main rendering of the
|
|
74
|
-
* canvas. If there are more than this number of fonts needed, we'll just show the canvas right
|
|
75
|
-
* away and let the fonts load in in the background.
|
|
76
|
-
*/
|
|
77
|
-
readonly maxFontsToLoadBeforeRender: number
|
|
78
72
|
}
|
|
79
73
|
|
|
80
74
|
/** @public */
|
|
@@ -120,5 +114,4 @@ export const defaultTldrawOptions = {
|
|
|
120
114
|
createTextOnCanvasDoubleClick: true,
|
|
121
115
|
exportProvider: Fragment,
|
|
122
116
|
enableToolbarKeyboardShortcuts: true,
|
|
123
|
-
maxFontsToLoadBeforeRender: Infinity,
|
|
124
117
|
} as const satisfies TldrawOptions
|
package/src/lib/utils/dom.ts
CHANGED
|
@@ -98,7 +98,7 @@ export function activeElementShouldCaptureKeys() {
|
|
|
98
98
|
const { activeElement } = document
|
|
99
99
|
return !!(
|
|
100
100
|
activeElement &&
|
|
101
|
-
((
|
|
101
|
+
(activeElement.getAttribute('contenteditable') ||
|
|
102
102
|
INPUTS.indexOf(activeElement.tagName.toLowerCase()) > -1)
|
|
103
103
|
)
|
|
104
104
|
}
|
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.9.0
|
|
4
|
+
export const version = '3.9.0'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2024-09-13T14:36:29.063Z',
|
|
7
|
-
minor: '2025-
|
|
8
|
-
patch: '2025-
|
|
7
|
+
minor: '2025-03-03T11:42:22.746Z',
|
|
8
|
+
patch: '2025-03-03T11:42:22.746Z',
|
|
9
9
|
}
|
|
@@ -1,167 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var FontManager_exports = {};
|
|
20
|
-
__export(FontManager_exports, {
|
|
21
|
-
FontManager: () => FontManager
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(FontManager_exports);
|
|
24
|
-
var import_state = require("@tldraw/state");
|
|
25
|
-
var import_utils = require("@tldraw/utils");
|
|
26
|
-
class FontManager {
|
|
27
|
-
constructor(editor, assetUrls) {
|
|
28
|
-
this.editor = editor;
|
|
29
|
-
this.assetUrls = assetUrls;
|
|
30
|
-
this.shapeFontFacesCache = editor.store.createComputedCache(
|
|
31
|
-
"shape font faces",
|
|
32
|
-
(shape) => {
|
|
33
|
-
const shapeUtil = this.editor.getShapeUtil(shape);
|
|
34
|
-
return shapeUtil.getFontFaces(shape);
|
|
35
|
-
},
|
|
36
|
-
{ areResultsEqual: import_utils.areArraysShallowEqual }
|
|
37
|
-
);
|
|
38
|
-
this.shapeFontLoadStateCache = editor.store.createComputedCache(
|
|
39
|
-
"shape font load state",
|
|
40
|
-
(shape) => {
|
|
41
|
-
const states = this.getShapeFontFaces(shape).map((face) => this.getFontState(face));
|
|
42
|
-
return states;
|
|
43
|
-
},
|
|
44
|
-
{ areResultsEqual: import_utils.areArraysShallowEqual }
|
|
45
|
-
);
|
|
46
|
-
}
|
|
47
|
-
shapeFontFacesCache;
|
|
48
|
-
shapeFontLoadStateCache;
|
|
49
|
-
getShapeFontFaces(shape) {
|
|
50
|
-
const shapeId = typeof shape === "string" ? shape : shape.id;
|
|
51
|
-
return this.shapeFontFacesCache.get(shapeId) ?? import_state.EMPTY_ARRAY;
|
|
52
|
-
}
|
|
53
|
-
trackFontsForShape(shape) {
|
|
54
|
-
const shapeId = typeof shape === "string" ? shape : shape.id;
|
|
55
|
-
this.shapeFontLoadStateCache.get(shapeId);
|
|
56
|
-
}
|
|
57
|
-
async loadRequiredFontsForCurrentPage(limit = Infinity) {
|
|
58
|
-
const neededFonts = /* @__PURE__ */ new Set();
|
|
59
|
-
for (const shapeId of this.editor.getCurrentPageShapeIds()) {
|
|
60
|
-
for (const font of this.getShapeFontFaces(this.editor.getShape(shapeId))) {
|
|
61
|
-
neededFonts.add(font);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
if (neededFonts.size > limit) {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
const promises = Array.from(neededFonts, (font) => this.ensureFontIsLoaded(font));
|
|
68
|
-
await Promise.all(promises);
|
|
69
|
-
}
|
|
70
|
-
fontStates = (0, import_state.atom)(
|
|
71
|
-
"font states",
|
|
72
|
-
/* @__PURE__ */ new Map()
|
|
73
|
-
);
|
|
74
|
-
getFontState(font) {
|
|
75
|
-
return this.fontStates.get().get(font)?.get() ?? null;
|
|
76
|
-
}
|
|
77
|
-
ensureFontIsLoaded(font) {
|
|
78
|
-
const state = this.getFontState(font);
|
|
79
|
-
if (state) return state.loadingPromise;
|
|
80
|
-
const instance = this.findOrCreateFontFace(font);
|
|
81
|
-
const stateAtom = (0, import_state.atom)("font state", {
|
|
82
|
-
state: "loading",
|
|
83
|
-
instance,
|
|
84
|
-
loadingPromise: instance.load().then(() => {
|
|
85
|
-
document.fonts.add(instance);
|
|
86
|
-
stateAtom.update((s) => ({ ...s, state: "ready" }));
|
|
87
|
-
}).catch((err) => {
|
|
88
|
-
console.error(err);
|
|
89
|
-
stateAtom.update((s) => ({ ...s, state: "error" }));
|
|
90
|
-
})
|
|
91
|
-
});
|
|
92
|
-
this.fontStates.update((map) => {
|
|
93
|
-
const newMap = new Map(map);
|
|
94
|
-
newMap.set(font, stateAtom);
|
|
95
|
-
return newMap;
|
|
96
|
-
});
|
|
97
|
-
return stateAtom.get().loadingPromise;
|
|
98
|
-
}
|
|
99
|
-
fontsToLoad = /* @__PURE__ */ new Set();
|
|
100
|
-
requestFonts(fonts) {
|
|
101
|
-
if (!this.fontsToLoad.size) {
|
|
102
|
-
queueMicrotask(() => {
|
|
103
|
-
if (this.editor.isDisposed) return;
|
|
104
|
-
const toLoad = this.fontsToLoad;
|
|
105
|
-
this.fontsToLoad = /* @__PURE__ */ new Set();
|
|
106
|
-
(0, import_state.transact)(() => {
|
|
107
|
-
for (const font of toLoad) {
|
|
108
|
-
this.ensureFontIsLoaded(font);
|
|
109
|
-
}
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
for (const font of fonts) {
|
|
114
|
-
this.fontsToLoad.add(font);
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
findOrCreateFontFace(font) {
|
|
118
|
-
for (const existing of document.fonts) {
|
|
119
|
-
if (existing.family === font.family && (0, import_utils.objectMapEntries)(defaultFontFaceDescriptors).every(
|
|
120
|
-
([key, defaultValue]) => existing[key] === (font[key] ?? defaultValue)
|
|
121
|
-
)) {
|
|
122
|
-
return existing;
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
const url = this.assetUrls?.[font.src.url] ?? font.src.url;
|
|
126
|
-
const instance = new FontFace(font.family, `url(${JSON.stringify(url)})`, {
|
|
127
|
-
...(0, import_utils.mapObjectMapValues)(defaultFontFaceDescriptors, (key) => font[key]),
|
|
128
|
-
display: "swap"
|
|
129
|
-
});
|
|
130
|
-
document.fonts.add(instance);
|
|
131
|
-
return instance;
|
|
132
|
-
}
|
|
133
|
-
async toEmbeddedCssDeclaration(font) {
|
|
134
|
-
const url = this.assetUrls?.[font.src.url] ?? font.src.url;
|
|
135
|
-
const dataUrl = await import_utils.FileHelpers.urlToDataUrl(url);
|
|
136
|
-
const src = (0, import_utils.compact)([
|
|
137
|
-
`url("${dataUrl}")`,
|
|
138
|
-
font.src.format ? `format(${font.src.format})` : null,
|
|
139
|
-
font.src.tech ? `tech(${font.src.tech})` : null
|
|
140
|
-
]).join(" ");
|
|
141
|
-
return (0, import_utils.compact)([
|
|
142
|
-
`@font-face {`,
|
|
143
|
-
` font-family: ${font.family};`,
|
|
144
|
-
` src: ${src};`,
|
|
145
|
-
font.ascentOverride ? ` ascent-override: ${font.ascentOverride};` : null,
|
|
146
|
-
font.descentOverride ? ` descent-override: ${font.descentOverride};` : null,
|
|
147
|
-
font.stretch ? ` font-stretch: ${font.stretch};` : null,
|
|
148
|
-
font.style ? ` font-style: ${font.style};` : null,
|
|
149
|
-
font.weight ? ` font-weight: ${font.weight};` : null,
|
|
150
|
-
font.featureSettings ? ` font-feature-settings: ${font.featureSettings};` : null,
|
|
151
|
-
font.lineGapOverride ? ` line-gap-override: ${font.lineGapOverride};` : null,
|
|
152
|
-
font.unicodeRange ? ` unicode-range: ${font.unicodeRange};` : null,
|
|
153
|
-
`}`
|
|
154
|
-
]).join("\n");
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
const defaultFontFaceDescriptors = {
|
|
158
|
-
style: "normal",
|
|
159
|
-
weight: "normal",
|
|
160
|
-
stretch: "normal",
|
|
161
|
-
unicodeRange: "U+0-10FFFF",
|
|
162
|
-
featureSettings: "normal",
|
|
163
|
-
ascentOverride: "normal",
|
|
164
|
-
descentOverride: "normal",
|
|
165
|
-
lineGapOverride: "normal"
|
|
166
|
-
};
|
|
167
|
-
//# sourceMappingURL=FontManager.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/lib/editor/managers/FontManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { atom, Atom, EMPTY_ARRAY, transact } from '@tldraw/state'\nimport { TLShape, TLShapeId } from '@tldraw/tlschema'\nimport {\n\tareArraysShallowEqual,\n\tcompact,\n\tFileHelpers,\n\tmapObjectMapValues,\n\tobjectMapEntries,\n} from '@tldraw/utils'\nimport { Editor } from '../Editor'\n\n/**\n * Represents the `src` property of a {@link TLFontFace}.\n * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src | `src`} for details of the properties here.\n * @public\n */\nexport interface TLFontFaceSource {\n\t/**\n\t * A URL from which to load the font. If the value here is a key in\n\t * {@link tldraw#TLEditorAssetUrls.fonts}, the value from there will be used instead.\n\t */\n\turl: string\n\tformat?: string\n\ttech?: string\n}\n\n/**\n * A font face that can be used in the editor. The properties of this are largely the same as the\n * ones in the\n * {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face | css `@font-face` rule}.\n * @public\n */\nexport interface TLFontFace {\n\t/**\n\t * How this font can be referred to in CSS.\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-family | `font-family`}.\n\t */\n\treadonly family: string\n\t/**\n\t * The source of the font. This\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/src | `src`}.\n\t */\n\treadonly src: TLFontFaceSource\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/ascent-override | `ascent-override`}.\n\t */\n\treadonly ascentOverride?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/descent-override | `descent-override`}.\n\t */\n\treadonly descentOverride?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-stretch | `font-stretch`}.\n\t */\n\treadonly stretch?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-style | `font-style`}.\n\t */\n\treadonly style?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-weight | `font-weight`}.\n\t */\n\treadonly weight?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/font-feature-settings | `font-feature-settings`}.\n\t */\n\treadonly featureSettings?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/line-gap-override | `line-gap-override`}.\n\t */\n\treadonly lineGapOverride?: string\n\t/**\n\t * See {@link https://developer.mozilla.org/en-US/docs/Web/CSS/@font-face/unicode-range | `unicode-range`}.\n\t */\n\treadonly unicodeRange?: string\n}\n\ninterface FontState {\n\treadonly state: 'loading' | 'ready' | 'error'\n\treadonly instance: FontFace\n\treadonly loadingPromise: Promise<void>\n}\n\n/** @public */\nexport class FontManager {\n\tconstructor(\n\t\tprivate readonly editor: Editor,\n\t\tprivate readonly assetUrls?: { [key: string]: string | undefined }\n\t) {\n\t\tthis.shapeFontFacesCache = editor.store.createComputedCache(\n\t\t\t'shape font faces',\n\t\t\t(shape: TLShape) => {\n\t\t\t\tconst shapeUtil = this.editor.getShapeUtil(shape)\n\t\t\t\treturn shapeUtil.getFontFaces(shape)\n\t\t\t},\n\t\t\t{ areResultsEqual: areArraysShallowEqual }\n\t\t)\n\n\t\tthis.shapeFontLoadStateCache = editor.store.createComputedCache(\n\t\t\t'shape font load state',\n\t\t\t(shape: TLShape) => {\n\t\t\t\tconst states = this.getShapeFontFaces(shape).map((face) => this.getFontState(face))\n\t\t\t\treturn states\n\t\t\t},\n\t\t\t{ areResultsEqual: areArraysShallowEqual }\n\t\t)\n\t}\n\n\tprivate readonly shapeFontFacesCache\n\tprivate readonly shapeFontLoadStateCache\n\n\tgetShapeFontFaces(shape: TLShape | TLShapeId): TLFontFace[] {\n\t\tconst shapeId = typeof shape === 'string' ? shape : shape.id\n\t\treturn this.shapeFontFacesCache.get(shapeId) ?? EMPTY_ARRAY\n\t}\n\n\ttrackFontsForShape(shape: TLShape | TLShapeId) {\n\t\tconst shapeId = typeof shape === 'string' ? shape : shape.id\n\t\tthis.shapeFontLoadStateCache.get(shapeId)\n\t}\n\n\tasync loadRequiredFontsForCurrentPage(limit = Infinity) {\n\t\tconst neededFonts = new Set<TLFontFace>()\n\t\tfor (const shapeId of this.editor.getCurrentPageShapeIds()) {\n\t\t\tfor (const font of this.getShapeFontFaces(this.editor.getShape(shapeId)!)) {\n\t\t\t\tneededFonts.add(font)\n\t\t\t}\n\t\t}\n\n\t\tif (neededFonts.size > limit) {\n\t\t\treturn\n\t\t}\n\n\t\tconst promises = Array.from(neededFonts, (font) => this.ensureFontIsLoaded(font))\n\t\tawait Promise.all(promises)\n\t}\n\n\tprivate readonly fontStates = atom<ReadonlyMap<TLFontFace, Atom<FontState>>>(\n\t\t'font states',\n\t\tnew Map()\n\t)\n\tprivate getFontState(font: TLFontFace): FontState | null {\n\t\treturn this.fontStates.get().get(font)?.get() ?? null\n\t}\n\n\tensureFontIsLoaded(font: TLFontFace): Promise<void> {\n\t\tconst state = this.getFontState(font)\n\t\tif (state) return state.loadingPromise\n\n\t\tconst instance = this.findOrCreateFontFace(font)\n\t\tconst stateAtom = atom<FontState>('font state', {\n\t\t\tstate: 'loading',\n\t\t\tinstance,\n\t\t\tloadingPromise: instance\n\t\t\t\t.load()\n\t\t\t\t.then(() => {\n\t\t\t\t\tdocument.fonts.add(instance)\n\t\t\t\t\tstateAtom.update((s) => ({ ...s, state: 'ready' }))\n\t\t\t\t})\n\t\t\t\t.catch((err) => {\n\t\t\t\t\tconsole.error(err)\n\t\t\t\t\tstateAtom.update((s) => ({ ...s, state: 'error' }))\n\t\t\t\t}),\n\t\t})\n\t\tthis.fontStates.update((map) => {\n\t\t\tconst newMap = new Map(map)\n\t\t\tnewMap.set(font, stateAtom)\n\t\t\treturn newMap\n\t\t})\n\n\t\treturn stateAtom.get().loadingPromise\n\t}\n\n\tprivate fontsToLoad = new Set<TLFontFace>()\n\trequestFonts(fonts: TLFontFace[]) {\n\t\tif (!this.fontsToLoad.size) {\n\t\t\tqueueMicrotask(() => {\n\t\t\t\tif (this.editor.isDisposed) return\n\t\t\t\tconst toLoad = this.fontsToLoad\n\t\t\t\tthis.fontsToLoad = new Set()\n\t\t\t\ttransact(() => {\n\t\t\t\t\tfor (const font of toLoad) {\n\t\t\t\t\t\tthis.ensureFontIsLoaded(font)\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t})\n\t\t}\n\t\tfor (const font of fonts) {\n\t\t\tthis.fontsToLoad.add(font)\n\t\t}\n\t}\n\n\tprivate findOrCreateFontFace(font: TLFontFace) {\n\t\tfor (const existing of document.fonts) {\n\t\t\tif (\n\t\t\t\texisting.family === font.family &&\n\t\t\t\tobjectMapEntries(defaultFontFaceDescriptors).every(\n\t\t\t\t\t([key, defaultValue]) => existing[key] === (font[key] ?? defaultValue)\n\t\t\t\t)\n\t\t\t) {\n\t\t\t\treturn existing\n\t\t\t}\n\t\t}\n\n\t\tconst url = this.assetUrls?.[font.src.url] ?? font.src.url\n\t\tconst instance = new FontFace(font.family, `url(${JSON.stringify(url)})`, {\n\t\t\t...mapObjectMapValues(defaultFontFaceDescriptors, (key) => font[key]),\n\t\t\tdisplay: 'swap',\n\t\t})\n\n\t\tdocument.fonts.add(instance)\n\n\t\treturn instance\n\t}\n\n\tasync toEmbeddedCssDeclaration(font: TLFontFace) {\n\t\tconst url = this.assetUrls?.[font.src.url] ?? font.src.url\n\t\tconst dataUrl = await FileHelpers.urlToDataUrl(url)\n\n\t\tconst src = compact([\n\t\t\t`url(\"${dataUrl}\")`,\n\t\t\tfont.src.format ? `format(${font.src.format})` : null,\n\t\t\tfont.src.tech ? `tech(${font.src.tech})` : null,\n\t\t]).join(' ')\n\t\treturn compact([\n\t\t\t`@font-face {`,\n\t\t\t` font-family: ${font.family};`,\n\t\t\t` src: ${src};`,\n\t\t\tfont.ascentOverride ? ` ascent-override: ${font.ascentOverride};` : null,\n\t\t\tfont.descentOverride ? ` descent-override: ${font.descentOverride};` : null,\n\t\t\tfont.stretch ? ` font-stretch: ${font.stretch};` : null,\n\t\t\tfont.style ? ` font-style: ${font.style};` : null,\n\t\t\tfont.weight ? ` font-weight: ${font.weight};` : null,\n\t\t\tfont.featureSettings ? ` font-feature-settings: ${font.featureSettings};` : null,\n\t\t\tfont.lineGapOverride ? ` line-gap-override: ${font.lineGapOverride};` : null,\n\t\t\tfont.unicodeRange ? ` unicode-range: ${font.unicodeRange};` : null,\n\t\t\t`}`,\n\t\t]).join('\\n')\n\t}\n}\n\n// From https://drafts.csswg.org/css-font-loading/#fontface-interface\nconst defaultFontFaceDescriptors = {\n\tstyle: 'normal',\n\tweight: 'normal',\n\tstretch: 'normal',\n\tunicodeRange: 'U+0-10FFFF',\n\tfeatureSettings: 'normal',\n\tascentOverride: 'normal',\n\tdescentOverride: 'normal',\n\tlineGapOverride: 'normal',\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
-
var __export = (target, all) => {
|
|
7
|
-
for (var name in all)
|
|
8
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
-
};
|
|
10
|
-
var __copyProps = (to, from, except, desc) => {
|
|
11
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
-
for (let key of __getOwnPropNames(from))
|
|
13
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
var usePassThroughMouseOverEvents_exports = {};
|
|
20
|
-
__export(usePassThroughMouseOverEvents_exports, {
|
|
21
|
-
usePassThroughMouseOverEvents: () => usePassThroughMouseOverEvents
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(usePassThroughMouseOverEvents_exports);
|
|
24
|
-
var import_react = require("react");
|
|
25
|
-
var import_dom = require("../utils/dom");
|
|
26
|
-
var import_useContainer = require("./useContainer");
|
|
27
|
-
function usePassThroughMouseOverEvents(ref) {
|
|
28
|
-
if (!ref) throw Error("usePassThroughWheelEvents must be passed a ref");
|
|
29
|
-
const container = (0, import_useContainer.useContainer)();
|
|
30
|
-
(0, import_react.useEffect)(() => {
|
|
31
|
-
function onMouseOver(e) {
|
|
32
|
-
if (e.isSpecialRedispatchedEvent) return;
|
|
33
|
-
(0, import_dom.preventDefault)(e);
|
|
34
|
-
const cvs = container.querySelector(".tl-canvas");
|
|
35
|
-
if (!cvs) return;
|
|
36
|
-
const newEvent = new PointerEvent(e.type, e);
|
|
37
|
-
newEvent.isSpecialRedispatchedEvent = true;
|
|
38
|
-
cvs.dispatchEvent(newEvent);
|
|
39
|
-
}
|
|
40
|
-
const elm = ref.current;
|
|
41
|
-
if (!elm) return;
|
|
42
|
-
elm.addEventListener("mouseover", onMouseOver, { passive: false });
|
|
43
|
-
return () => {
|
|
44
|
-
elm.removeEventListener("mouseover", onMouseOver);
|
|
45
|
-
};
|
|
46
|
-
}, [container, ref]);
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=usePassThroughMouseOverEvents.js.map
|