@tldraw/editor 4.6.0-internal.e29318c66fb0 → 4.6.0-next.0eb36d65eec3
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 +124 -6
- package/dist-cjs/index.js +1 -1
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +1 -1
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js +1 -1
- package/dist-cjs/lib/config/createTLStore.js.map +2 -2
- package/dist-cjs/lib/config/defaultShapes.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +4 -4
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +1 -1
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js +1 -1
- package/dist-cjs/lib/editor/managers/SnapManager/BoundsSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SnapManager/HandleSnaps.js.map +2 -2
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js +4 -4
- package/dist-cjs/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js +102 -30
- package/dist-cjs/lib/editor/managers/TextManager/TextManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js +1 -1
- package/dist-cjs/lib/exports/StyleEmbedder.js.map +2 -2
- package/dist-cjs/lib/exports/getSvgJsx.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/hooks/useLocalStore.js.map +2 -2
- package/dist-cjs/lib/options.js +3 -0
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/primitives/Box.js +1 -1
- package/dist-cjs/lib/primitives/Box.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js +2 -2
- package/dist-cjs/lib/primitives/geometry/Arc2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js +2 -2
- package/dist-cjs/lib/primitives/geometry/Circle2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js +2 -2
- package/dist-cjs/lib/primitives/geometry/Ellipse2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js +4 -3
- package/dist-cjs/lib/primitives/geometry/Geometry2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Polyline2d.js.map +2 -2
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js +1 -1
- package/dist-cjs/lib/primitives/geometry/Stadium2d.js.map +2 -2
- package/dist-cjs/lib/utils/getSvgPathFromPoints.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +1 -1
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +124 -6
- package/dist-esm/index.mjs +4 -2
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +1 -1
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs +1 -1
- package/dist-esm/lib/config/createTLStore.mjs.map +2 -2
- package/dist-esm/lib/config/defaultShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +6 -6
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +1 -1
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs +1 -1
- package/dist-esm/lib/editor/managers/SnapManager/BoundsSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SnapManager/HandleSnaps.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs +4 -4
- package/dist-esm/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs +102 -30
- package/dist-esm/lib/editor/managers/TextManager/TextManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs +1 -1
- package/dist-esm/lib/exports/StyleEmbedder.mjs.map +2 -2
- package/dist-esm/lib/exports/getSvgJsx.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useLocalStore.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +3 -0
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/primitives/Box.mjs +1 -1
- package/dist-esm/lib/primitives/Box.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Arc2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Circle2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs +2 -2
- package/dist-esm/lib/primitives/geometry/Ellipse2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs +4 -3
- package/dist-esm/lib/primitives/geometry/Geometry2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Polyline2d.mjs.map +2 -2
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs +1 -1
- package/dist-esm/lib/primitives/geometry/Stadium2d.mjs.map +2 -2
- package/dist-esm/lib/utils/getSvgPathFromPoints.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +1 -1
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/package.json +7 -7
- package/src/index.ts +8 -1
- package/src/lib/TldrawEditor.tsx +1 -1
- package/src/lib/components/default-components/DefaultCanvas.tsx +1 -1
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +1 -1
- package/src/lib/config/TLEditorSnapshot.test.ts +1 -1
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/config/defaultShapes.ts +1 -1
- package/src/lib/editor/Editor.ts +9 -8
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +1 -1
- package/src/lib/editor/managers/SnapManager/BoundsSnaps.ts +1 -1
- package/src/lib/editor/managers/SnapManager/HandleSnaps.ts +1 -1
- package/src/lib/editor/managers/SpatialIndexManager/SpatialIndexManager.ts +5 -5
- package/src/lib/editor/managers/TextManager/TextManager.test.ts +18 -4
- package/src/lib/editor/managers/TextManager/TextManager.ts +140 -34
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +1 -1
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +1 -1
- package/src/lib/editor/shapes/ShapeUtil.ts +2 -2
- package/src/lib/exports/StyleEmbedder.ts +1 -1
- package/src/lib/exports/getSvgJsx.tsx +1 -1
- package/src/lib/hooks/useEditorComponents.tsx +1 -1
- package/src/lib/hooks/useLocalStore.ts +1 -1
- package/src/lib/options.ts +108 -0
- package/src/lib/primitives/Box.ts +1 -1
- package/src/lib/primitives/geometry/Arc2d.ts +2 -2
- package/src/lib/primitives/geometry/Circle2d.ts +2 -2
- package/src/lib/primitives/geometry/Ellipse2d.ts +2 -2
- package/src/lib/primitives/geometry/Geometry2d.ts +4 -3
- package/src/lib/primitives/geometry/Polyline2d.ts +1 -1
- package/src/lib/primitives/geometry/Stadium2d.ts +1 -1
- package/src/lib/utils/getSvgPathFromPoints.ts +1 -1
- package/src/lib/utils/sync/TLLocalSyncClient.test.ts +1 -1
- package/src/lib/utils/sync/TLLocalSyncClient.ts +1 -1
- package/src/version.ts +3 -3
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -10,10 +10,10 @@ import {
|
|
|
10
10
|
import {
|
|
11
11
|
ComputedCache,
|
|
12
12
|
RecordType,
|
|
13
|
-
StoreSideEffects,
|
|
14
|
-
StoreSnapshot,
|
|
15
13
|
UnknownRecord,
|
|
16
14
|
reverseRecordsDiff,
|
|
15
|
+
StoreSnapshot,
|
|
16
|
+
StoreSideEffects,
|
|
17
17
|
} from '@tldraw/store'
|
|
18
18
|
import {
|
|
19
19
|
CameraRecordType,
|
|
@@ -90,15 +90,15 @@ import {
|
|
|
90
90
|
uniqueId,
|
|
91
91
|
} from '@tldraw/utils'
|
|
92
92
|
import EventEmitter from 'eventemitter3'
|
|
93
|
+
import { TLUser, createTLUser } from '../config/createTLUser'
|
|
94
|
+
import { TLAnyBindingUtilConstructor, checkBindings } from '../config/defaultBindings'
|
|
95
|
+
import { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from '../config/defaultShapes'
|
|
93
96
|
import {
|
|
94
97
|
TLEditorSnapshot,
|
|
95
98
|
TLLoadSnapshotOptions,
|
|
96
99
|
getSnapshot,
|
|
97
100
|
loadSnapshot,
|
|
98
101
|
} from '../config/TLEditorSnapshot'
|
|
99
|
-
import { TLUser, createTLUser } from '../config/createTLUser'
|
|
100
|
-
import { TLAnyBindingUtilConstructor, checkBindings } from '../config/defaultBindings'
|
|
101
|
-
import { TLAnyShapeUtilConstructor, checkShapesAndAddCore } from '../config/defaultShapes'
|
|
102
102
|
import {
|
|
103
103
|
DEFAULT_ANIMATION_OPTIONS,
|
|
104
104
|
DEFAULT_CAMERA_OPTIONS,
|
|
@@ -115,14 +115,13 @@ import { tlmenus } from '../globals/menus'
|
|
|
115
115
|
import { tltime } from '../globals/time'
|
|
116
116
|
import { TldrawOptions, defaultTldrawOptions } from '../options'
|
|
117
117
|
import { Box, BoxLike } from '../primitives/Box'
|
|
118
|
-
import { Mat, MatLike } from '../primitives/Mat'
|
|
119
|
-
import { Vec, VecLike } from '../primitives/Vec'
|
|
120
118
|
import { EASINGS } from '../primitives/easings'
|
|
121
119
|
import { Geometry2d } from '../primitives/geometry/Geometry2d'
|
|
122
120
|
import { Group2d } from '../primitives/geometry/Group2d'
|
|
123
121
|
import { intersectPolygonPolygon } from '../primitives/intersect'
|
|
122
|
+
import { Mat, MatLike } from '../primitives/Mat'
|
|
124
123
|
import { PI, approximately, areAnglesCompatible, clamp, pointInPolygon } from '../primitives/utils'
|
|
125
|
-
import {
|
|
124
|
+
import { Vec, VecLike } from '../primitives/Vec'
|
|
126
125
|
import { areShapesContentEqual } from '../utils/areShapesContentEqual'
|
|
127
126
|
import { dataUrlToFile } from '../utils/assets'
|
|
128
127
|
import { debugFlags } from '../utils/debug-flags'
|
|
@@ -137,6 +136,7 @@ import { getReorderingShapesChanges } from '../utils/reorderShapes'
|
|
|
137
136
|
import { getDroppedShapesToNewParents, kickoutOccludedShapes } from '../utils/reparenting'
|
|
138
137
|
import { TLTextOptions, TiptapEditor } from '../utils/richText'
|
|
139
138
|
import { applyRotationToSnapshotShapes, getRotationSnapshot } from '../utils/rotation'
|
|
139
|
+
import { ReadonlySharedStyleMap, SharedStyle, SharedStyleMap } from '../utils/SharedStylesMap'
|
|
140
140
|
import { BindingOnDeleteOptions, BindingUtil } from './bindings/BindingUtil'
|
|
141
141
|
import { bindingsIndex } from './derivations/bindingsIndex'
|
|
142
142
|
import { notVisibleShapes } from './derivations/notVisibleShapes'
|
|
@@ -9071,6 +9071,7 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
9071
9071
|
opts = {} as { force?: boolean }
|
|
9072
9072
|
): Promise<void> {
|
|
9073
9073
|
if (!opts.force && this.getIsReadonly()) return
|
|
9074
|
+
|
|
9074
9075
|
return this.externalContentHandlers[info.type]?.(info as any)
|
|
9075
9076
|
}
|
|
9076
9077
|
|
|
@@ -10,8 +10,8 @@ import {
|
|
|
10
10
|
isSelectionCorner,
|
|
11
11
|
} from '../../../primitives/Box'
|
|
12
12
|
import { Mat } from '../../../primitives/Mat'
|
|
13
|
-
import { Vec } from '../../../primitives/Vec'
|
|
14
13
|
import { rangeIntersection, rangesOverlap } from '../../../primitives/utils'
|
|
14
|
+
import { Vec } from '../../../primitives/Vec'
|
|
15
15
|
import type { Editor } from '../../Editor'
|
|
16
16
|
import type {
|
|
17
17
|
GapsSnapIndicator,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { computed } from '@tldraw/state'
|
|
2
2
|
import { TLHandle, TLShape, TLShapeId, VecModel } from '@tldraw/tlschema'
|
|
3
3
|
import { assertExists, uniqueId } from '@tldraw/utils'
|
|
4
|
-
import { Vec } from '../../../primitives/Vec'
|
|
5
4
|
import { Geometry2d } from '../../../primitives/geometry/Geometry2d'
|
|
5
|
+
import { Vec } from '../../../primitives/Vec'
|
|
6
6
|
import type { Editor } from '../../Editor'
|
|
7
7
|
import type { PointsSnapIndicator, SnapData, SnapManager } from './SnapManager'
|
|
8
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Computed, RESET_VALUE, computed, isUninitialized } from '@tldraw/state'
|
|
2
2
|
import type { RecordsDiff } from '@tldraw/store'
|
|
3
|
-
import type { TLRecord } from '@tldraw/tlschema'
|
|
4
3
|
import { TLPageId, TLShape, TLShapeId, isShape } from '@tldraw/tlschema'
|
|
4
|
+
import type { TLRecord } from '@tldraw/tlschema'
|
|
5
5
|
import { objectMapValues } from '@tldraw/utils'
|
|
6
6
|
import { Box } from '../../../primitives/Box'
|
|
7
7
|
import type { Editor } from '../../Editor'
|
|
@@ -74,7 +74,7 @@ export class SpatialIndexManager {
|
|
|
74
74
|
// Collect all shape elements for bulk loading
|
|
75
75
|
for (const shape of shapes) {
|
|
76
76
|
const bounds = this.editor.getShapePageBounds(shape.id)
|
|
77
|
-
if (bounds) {
|
|
77
|
+
if (bounds && bounds.isValid()) {
|
|
78
78
|
elements.push({
|
|
79
79
|
minX: bounds.minX,
|
|
80
80
|
minY: bounds.minY,
|
|
@@ -101,7 +101,7 @@ export class SpatialIndexManager {
|
|
|
101
101
|
for (const shape of objectMapValues(changes.added) as TLShape[]) {
|
|
102
102
|
if (isShape(shape) && this.editor.getAncestorPageId(shape) === this.lastPageId) {
|
|
103
103
|
const bounds = this.editor.getShapePageBounds(shape.id)
|
|
104
|
-
if (bounds) {
|
|
104
|
+
if (bounds && bounds.isValid()) {
|
|
105
105
|
this.rbush.upsert(shape.id, bounds)
|
|
106
106
|
}
|
|
107
107
|
processedShapeIds.add(shape.id)
|
|
@@ -125,7 +125,7 @@ export class SpatialIndexManager {
|
|
|
125
125
|
|
|
126
126
|
if (isOnPage) {
|
|
127
127
|
const bounds = this.editor.getShapePageBounds(to.id)
|
|
128
|
-
if (bounds) {
|
|
128
|
+
if (bounds && bounds.isValid()) {
|
|
129
129
|
this.rbush.upsert(to.id, bounds)
|
|
130
130
|
}
|
|
131
131
|
} else {
|
|
@@ -145,7 +145,7 @@ export class SpatialIndexManager {
|
|
|
145
145
|
const indexedBounds = this.rbush.getBounds(shapeId)
|
|
146
146
|
|
|
147
147
|
if (!this.areBoundsEqual(currentBounds, indexedBounds)) {
|
|
148
|
-
if (currentBounds) {
|
|
148
|
+
if (currentBounds && currentBounds.isValid()) {
|
|
149
149
|
this.rbush.upsert(shapeId, currentBounds)
|
|
150
150
|
} else {
|
|
151
151
|
this.rbush.remove(shapeId)
|
|
@@ -3,6 +3,22 @@ import { Editor } from '../../Editor'
|
|
|
3
3
|
import { TextManager, TLMeasureTextSpanOpts } from './TextManager'
|
|
4
4
|
|
|
5
5
|
// Create a simple mock DOM environment
|
|
6
|
+
function createMockStyle() {
|
|
7
|
+
const properties = new Map<string, string>()
|
|
8
|
+
|
|
9
|
+
return {
|
|
10
|
+
setProperty: vi.fn((key: string, value: string) => {
|
|
11
|
+
properties.set(key, value)
|
|
12
|
+
}),
|
|
13
|
+
getPropertyValue: vi.fn((key: string) => properties.get(key) ?? ''),
|
|
14
|
+
removeProperty: vi.fn((key: string) => {
|
|
15
|
+
const previous = properties.get(key) ?? ''
|
|
16
|
+
properties.delete(key)
|
|
17
|
+
return previous
|
|
18
|
+
}),
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
6
22
|
const mockElement = {
|
|
7
23
|
classList: { add: vi.fn() },
|
|
8
24
|
tabIndex: -1,
|
|
@@ -10,10 +26,7 @@ const mockElement = {
|
|
|
10
26
|
innerHTML: '',
|
|
11
27
|
textContent: '',
|
|
12
28
|
setAttribute: vi.fn(),
|
|
13
|
-
style:
|
|
14
|
-
setProperty: vi.fn(),
|
|
15
|
-
getPropertyValue: vi.fn(() => ''),
|
|
16
|
-
},
|
|
29
|
+
style: createMockStyle(),
|
|
17
30
|
scrollWidth: 100,
|
|
18
31
|
getBoundingClientRect: vi.fn(() => ({
|
|
19
32
|
width: 100,
|
|
@@ -31,6 +44,7 @@ const mockElement = {
|
|
|
31
44
|
// Mock document.createElement to return our mock element
|
|
32
45
|
const mockCreateElement = vi.fn(() => {
|
|
33
46
|
const element = { ...mockElement }
|
|
47
|
+
element.style = createMockStyle()
|
|
34
48
|
element.cloneNode = vi.fn(() => ({ ...element }))
|
|
35
49
|
|
|
36
50
|
// Make textContent and innerHTML reactive like real DOM elements
|
|
@@ -21,6 +21,23 @@ const textAlignmentsForLtr = {
|
|
|
21
21
|
'end-legacy': 'right',
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
interface PoolItem {
|
|
25
|
+
el: HTMLDivElement
|
|
26
|
+
html: string
|
|
27
|
+
appliedStyleKeys: string[]
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** @public */
|
|
31
|
+
export interface BatchMeasurementRequest {
|
|
32
|
+
html: string
|
|
33
|
+
opts: TLMeasureTextOpts
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/** @public */
|
|
37
|
+
export type TLMeasuredTextSize = BoxModel & {
|
|
38
|
+
scrollWidth: number
|
|
39
|
+
}
|
|
40
|
+
|
|
24
41
|
/** @public */
|
|
25
42
|
export interface TLMeasureTextOpts {
|
|
26
43
|
fontStyle: string
|
|
@@ -73,53 +90,66 @@ const initialDefaultStyles = Object.freeze({
|
|
|
73
90
|
/** @public */
|
|
74
91
|
export class TextManager {
|
|
75
92
|
private elm: HTMLDivElement
|
|
93
|
+
private poolElms: PoolItem[] = []
|
|
76
94
|
|
|
77
95
|
constructor(public editor: Editor) {
|
|
78
|
-
|
|
96
|
+
this.elm = this.createMeasurementEl()
|
|
97
|
+
this.editor.getContainer().appendChild(this.elm)
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private createMeasurementEl(): HTMLDivElement {
|
|
101
|
+
const elm = this.editor.getContainerDocument().createElement('div')
|
|
79
102
|
elm.classList.add('tl-text')
|
|
80
103
|
elm.classList.add('tl-text-measure')
|
|
81
104
|
elm.setAttribute('dir', 'auto')
|
|
82
105
|
elm.tabIndex = -1
|
|
83
|
-
this.editor.getContainer().appendChild(elm)
|
|
84
|
-
|
|
85
|
-
this.elm = elm
|
|
86
|
-
|
|
87
106
|
for (const key of objectMapKeys(initialDefaultStyles)) {
|
|
88
107
|
elm.style.setProperty(key, initialDefaultStyles[key])
|
|
89
108
|
}
|
|
109
|
+
|
|
110
|
+
return elm
|
|
90
111
|
}
|
|
91
112
|
|
|
92
|
-
private
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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])
|
|
113
|
+
private resetElementStyles(el: HTMLElement, appliedStyleKeys: string[]) {
|
|
114
|
+
for (const key of appliedStyleKeys) {
|
|
115
|
+
if (key in initialDefaultStyles) {
|
|
116
|
+
el.style.setProperty(key, initialDefaultStyles[key as keyof typeof initialDefaultStyles])
|
|
117
|
+
} else {
|
|
118
|
+
el.style.removeProperty(key)
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
121
|
}
|
|
108
122
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
private setElementStyles(el: HTMLElement, styles: Record<string, string | undefined | null>) {
|
|
124
|
+
type StyleValue = string | null
|
|
125
|
+
type RestoreEntry = [prop: string, value: StyleValue]
|
|
112
126
|
|
|
113
|
-
|
|
114
|
-
const div = this.editor.getContainerDocument().createElement('div')
|
|
115
|
-
div.textContent = normalizeTextForDom(textToMeasure)
|
|
116
|
-
return this.measureHtml(div.innerHTML, opts)
|
|
117
|
-
}
|
|
127
|
+
const restore: RestoreEntry[] = []
|
|
118
128
|
|
|
119
|
-
|
|
120
|
-
|
|
129
|
+
for (const [key, nextValue] of Object.entries(styles)) {
|
|
130
|
+
const oldValue = el.style.getPropertyValue(key)
|
|
121
131
|
|
|
122
|
-
|
|
132
|
+
if (typeof nextValue === 'string') {
|
|
133
|
+
if (oldValue === nextValue) continue
|
|
134
|
+
restore.push([key, oldValue || null])
|
|
135
|
+
el.style.setProperty(key, nextValue)
|
|
136
|
+
} else {
|
|
137
|
+
if (!oldValue) continue
|
|
138
|
+
restore.push([key, oldValue])
|
|
139
|
+
el.style.removeProperty(key)
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return () => {
|
|
144
|
+
for (const [key, value] of restore) {
|
|
145
|
+
if (value === null || value === '') el.style.removeProperty(key)
|
|
146
|
+
else el.style.setProperty(key, value)
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
private getMeasureStyles(opts: TLMeasureTextOpts): Record<string, string | undefined> {
|
|
152
|
+
return {
|
|
123
153
|
'font-family': opts.fontFamily,
|
|
124
154
|
'font-style': opts.fontStyle,
|
|
125
155
|
'font-weight': opts.fontWeight,
|
|
@@ -128,11 +158,87 @@ export class TextManager {
|
|
|
128
158
|
padding: opts.padding,
|
|
129
159
|
'max-width': opts.maxWidth ? opts.maxWidth + 'px' : undefined,
|
|
130
160
|
'min-width': opts.minWidth ? opts.minWidth + 'px' : undefined,
|
|
131
|
-
'overflow-wrap': opts.disableOverflowWrapBreaking ? 'normal' :
|
|
161
|
+
'overflow-wrap': opts.disableOverflowWrapBreaking ? 'normal' : 'break-word',
|
|
132
162
|
...opts.otherStyles,
|
|
133
163
|
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
dispose() {
|
|
167
|
+
this.elm.remove()
|
|
168
|
+
for (const { el } of this.poolElms) {
|
|
169
|
+
el.remove()
|
|
170
|
+
}
|
|
171
|
+
this.poolElms.length = 0
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
private ensurePoolSize(size: number) {
|
|
175
|
+
if (this.poolElms.length >= size) return
|
|
176
|
+
|
|
177
|
+
const fragment = this.editor.getContainerDocument().createDocumentFragment()
|
|
178
|
+
while (this.poolElms.length < size) {
|
|
179
|
+
const el = this.createMeasurementEl()
|
|
180
|
+
this.poolElms.push({ el, html: '', appliedStyleKeys: [] })
|
|
181
|
+
fragment.appendChild(el)
|
|
182
|
+
}
|
|
183
|
+
this.editor.getContainer().appendChild(fragment)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private getPoolItem(index: number): PoolItem {
|
|
187
|
+
this.ensurePoolSize(index + 1)
|
|
188
|
+
return this.poolElms[index]
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
measureHtmlBatch(requests: BatchMeasurementRequest[]): TLMeasuredTextSize[] {
|
|
192
|
+
if (requests.length === 0) return []
|
|
193
|
+
|
|
194
|
+
while (this.poolElms.length > requests.length) {
|
|
195
|
+
const { el } = this.poolElms.pop()!
|
|
196
|
+
el.remove()
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
for (let i = 0; i < requests.length; i++) {
|
|
200
|
+
const { html, opts } = requests[i]
|
|
201
|
+
const poolItem = this.getPoolItem(i)
|
|
202
|
+
|
|
203
|
+
const { el } = poolItem
|
|
204
|
+
this.resetElementStyles(el, poolItem.appliedStyleKeys)
|
|
205
|
+
const styles = this.getMeasureStyles(opts)
|
|
206
|
+
this.setElementStyles(el, styles)
|
|
207
|
+
poolItem.appliedStyleKeys = Object.keys(styles)
|
|
208
|
+
// Skip innerHTML parsing if the content hasn't changed
|
|
209
|
+
if (poolItem.html !== html) {
|
|
210
|
+
el.innerHTML = html
|
|
211
|
+
poolItem.html = html
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const results: TLMeasuredTextSize[] = []
|
|
216
|
+
for (let i = 0; i < requests.length; i++) {
|
|
217
|
+
const el = this.getPoolItem(i).el
|
|
218
|
+
const scrollWidth = requests[i].opts.measureScrollWidth ? el.scrollWidth : 0
|
|
219
|
+
const rect = el.getBoundingClientRect()
|
|
220
|
+
results.push({
|
|
221
|
+
x: 0,
|
|
222
|
+
y: 0,
|
|
223
|
+
w: rect.width,
|
|
224
|
+
h: rect.height,
|
|
225
|
+
scrollWidth,
|
|
226
|
+
})
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return results
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
measureText(textToMeasure: string, opts: TLMeasureTextOpts): TLMeasuredTextSize {
|
|
233
|
+
const div = this.editor.getContainerDocument().createElement('div')
|
|
234
|
+
div.textContent = normalizeTextForDom(textToMeasure)
|
|
235
|
+
return this.measureHtml(div.innerHTML, opts)
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
measureHtml(html: string, opts: TLMeasureTextOpts): TLMeasuredTextSize {
|
|
239
|
+
const { elm } = this
|
|
134
240
|
|
|
135
|
-
const restoreStyles = this.setElementStyles(
|
|
241
|
+
const restoreStyles = this.setElementStyles(elm, this.getMeasureStyles(opts))
|
|
136
242
|
|
|
137
243
|
try {
|
|
138
244
|
elm.innerHTML = html
|
|
@@ -280,11 +386,11 @@ export class TextManager {
|
|
|
280
386
|
width: `${elementWidth}px`,
|
|
281
387
|
height: 'min-content',
|
|
282
388
|
'text-align': textAlignmentsForLtr[opts.textAlign],
|
|
283
|
-
'overflow-wrap': shouldTruncateToFirstLine ? 'anywhere' :
|
|
284
|
-
'word-break': shouldTruncateToFirstLine ? 'break-all' :
|
|
389
|
+
'overflow-wrap': shouldTruncateToFirstLine ? 'anywhere' : 'break-word',
|
|
390
|
+
'word-break': shouldTruncateToFirstLine ? 'break-all' : 'normal',
|
|
285
391
|
...opts.otherStyles,
|
|
286
392
|
}
|
|
287
|
-
const restoreStyles = this.setElementStyles(newStyles)
|
|
393
|
+
const restoreStyles = this.setElementStyles(elm, newStyles)
|
|
288
394
|
|
|
289
395
|
try {
|
|
290
396
|
const normalizedText = normalizeTextForDom(textToMeasure)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { atom } from '@tldraw/state'
|
|
2
2
|
import { Mocked, vi } from 'vitest'
|
|
3
|
-
import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
|
|
4
3
|
import { TLUser } from '../../../config/createTLUser'
|
|
4
|
+
import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
|
|
5
5
|
import { UserPreferencesManager } from './UserPreferencesManager'
|
|
6
6
|
|
|
7
7
|
// Mock window.matchMedia
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { atom, computed } from '@tldraw/state'
|
|
2
|
-
import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
|
|
3
2
|
import { TLUser } from '../../../config/createTLUser'
|
|
3
|
+
import { TLUserPreferences, defaultUserPreferences } from '../../../config/TLUserPreferences'
|
|
4
4
|
import { getGlobalWindow } from '../../../utils/dom'
|
|
5
5
|
|
|
6
6
|
/** @public */
|
|
@@ -15,15 +15,15 @@ import {
|
|
|
15
15
|
import { IndexKey } from '@tldraw/utils'
|
|
16
16
|
import { ReactElement } from 'react'
|
|
17
17
|
import { Box, SelectionHandle } from '../../primitives/Box'
|
|
18
|
-
import { Vec } from '../../primitives/Vec'
|
|
19
18
|
import { Geometry2d } from '../../primitives/geometry/Geometry2d'
|
|
19
|
+
import { Vec } from '../../primitives/Vec'
|
|
20
20
|
import type { Editor } from '../Editor'
|
|
21
21
|
import { TLFontFace } from '../managers/FontManager/FontManager'
|
|
22
22
|
import { BoundsSnapGeometry } from '../managers/SnapManager/BoundsSnaps'
|
|
23
23
|
import { HandleSnapGeometry } from '../managers/SnapManager/HandleSnaps'
|
|
24
|
-
import { SvgExportContext } from '../types/SvgExportContext'
|
|
25
24
|
import { TLClickEventInfo } from '../types/event-types'
|
|
26
25
|
import { TLResizeHandle } from '../types/selection-types'
|
|
26
|
+
import { SvgExportContext } from '../types/SvgExportContext'
|
|
27
27
|
|
|
28
28
|
/** @public */
|
|
29
29
|
export interface TLShapeUtilConstructor<T extends TLShape, U extends ShapeUtil<T> = ShapeUtil<T>> {
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { assertExists, getOwnProperty, objectMapValues, uniqueId } from '@tldraw/utils'
|
|
2
|
-
import { FontEmbedder } from './FontEmbedder'
|
|
3
2
|
import { ReadonlyStyles, Styles, cssRules } from './cssRules'
|
|
4
3
|
import {
|
|
5
4
|
elementStyle,
|
|
@@ -9,6 +8,7 @@ import {
|
|
|
9
8
|
isElement,
|
|
10
9
|
} from './domUtils'
|
|
11
10
|
import { resourceToDataUrl } from './fetchCache'
|
|
11
|
+
import { FontEmbedder } from './FontEmbedder'
|
|
12
12
|
import { parseCssValueUrls, shouldIncludeCssProperty } from './parseCss'
|
|
13
13
|
|
|
14
14
|
const NO_STYLES = {} as const
|
|
@@ -23,12 +23,12 @@ import { InnerShape, InnerShapeBackground } from '../components/Shape'
|
|
|
23
23
|
import type { Editor, TLRenderingShape } from '../editor/Editor'
|
|
24
24
|
import { TLFontFace } from '../editor/managers/FontManager/FontManager'
|
|
25
25
|
import { ShapeUtil } from '../editor/shapes/ShapeUtil'
|
|
26
|
+
import { TLImageExportOptions } from '../editor/types/misc-types'
|
|
26
27
|
import {
|
|
27
28
|
SvgExportContext,
|
|
28
29
|
SvgExportContextProvider,
|
|
29
30
|
SvgExportDef,
|
|
30
31
|
} from '../editor/types/SvgExportContext'
|
|
31
|
-
import { TLImageExportOptions } from '../editor/types/misc-types'
|
|
32
32
|
import { useEditor } from '../hooks/useEditor'
|
|
33
33
|
import { useEvent } from '../hooks/useEvent'
|
|
34
34
|
import { suffixSafeId, useUniqueSafeId } from '../hooks/useSafeId'
|
|
@@ -19,8 +19,8 @@ import { DefaultShapeWrapper } from '../components/default-components/DefaultSha
|
|
|
19
19
|
import { DefaultSnapIndicator } from '../components/default-components/DefaultSnapIndictor'
|
|
20
20
|
import { DefaultSpinner } from '../components/default-components/DefaultSpinner'
|
|
21
21
|
import { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'
|
|
22
|
-
import type { TLEditorComponents } from './EditorComponentsContext'
|
|
23
22
|
import { EditorComponentsContext } from './EditorComponentsContext'
|
|
23
|
+
import type { TLEditorComponents } from './EditorComponentsContext'
|
|
24
24
|
import { useShallowObjectIdentity } from './useIdentity'
|
|
25
25
|
|
|
26
26
|
export { useEditorComponents } from './EditorComponentsContext'
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { TLAsset, TLAssetStore, TLStoreSnapshot } from '@tldraw/tlschema'
|
|
2
2
|
import { WeakCache } from '@tldraw/utils'
|
|
3
3
|
import { useEffect } from 'react'
|
|
4
|
-
import { TLEditorSnapshot } from '../config/TLEditorSnapshot'
|
|
5
4
|
import { TLStoreOptions, createTLStore } from '../config/createTLStore'
|
|
5
|
+
import { TLEditorSnapshot } from '../config/TLEditorSnapshot'
|
|
6
6
|
import { TLStoreWithStatus } from '../utils/sync/StoreWithStatus'
|
|
7
7
|
import { TLLocalSyncClient } from '../utils/sync/TLLocalSyncClient'
|
|
8
8
|
import { useShallowObjectIdentity } from './useIdentity'
|
package/src/lib/options.ts
CHANGED
|
@@ -1,10 +1,50 @@
|
|
|
1
|
+
import { Awaitable } from '@tldraw/utils'
|
|
1
2
|
import { ComponentType, Fragment } from 'react'
|
|
2
3
|
import { DEFAULT_CAMERA_OPTIONS } from './constants'
|
|
4
|
+
import type { Editor } from './editor/Editor'
|
|
5
|
+
import { TLContent } from './editor/types/clipboard-types'
|
|
6
|
+
import { TLExternalContent } from './editor/types/external-content'
|
|
3
7
|
import { TLCameraOptions } from './editor/types/misc-types'
|
|
4
8
|
import { VecLike } from './primitives/Vec'
|
|
5
9
|
import { TLDeepLinkOptions } from './utils/deepLinks'
|
|
6
10
|
import { TLTextOptions } from './utils/richText'
|
|
7
11
|
|
|
12
|
+
/**
|
|
13
|
+
* Identifies how a clipboard write was triggered (copy vs cut, keyboard vs menu).
|
|
14
|
+
*
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export interface TLClipboardWriteInfo {
|
|
18
|
+
readonly operation: 'copy' | 'cut'
|
|
19
|
+
readonly source: 'native' | 'menu'
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Raw clipboard paste payload, before tldraw parses clipboard contents into {@link TLExternalContent}.
|
|
24
|
+
*
|
|
25
|
+
* - `native-event`: from the `paste` event — `clipboardData` is available synchronously (unlike async
|
|
26
|
+
* `navigator.clipboard.read()`).
|
|
27
|
+
* - `clipboard-read`: from an explicit `navigator.clipboard.read()` call — only `ClipboardItem[]`
|
|
28
|
+
* exists
|
|
29
|
+
* (no `DataTransfer`).
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export type TLClipboardPasteRawInfo =
|
|
34
|
+
| {
|
|
35
|
+
readonly editor: Editor
|
|
36
|
+
readonly source: 'native-event'
|
|
37
|
+
readonly event: ClipboardEvent
|
|
38
|
+
readonly clipboardData: DataTransfer | null
|
|
39
|
+
readonly point: VecLike | undefined
|
|
40
|
+
}
|
|
41
|
+
| {
|
|
42
|
+
readonly editor: Editor
|
|
43
|
+
readonly source: 'clipboard-read'
|
|
44
|
+
readonly clipboardItems: readonly ClipboardItem[]
|
|
45
|
+
readonly point: VecLike | undefined
|
|
46
|
+
}
|
|
47
|
+
|
|
8
48
|
/**
|
|
9
49
|
* Options for configuring tldraw. For defaults, see {@link defaultTldrawOptions}.
|
|
10
50
|
*
|
|
@@ -156,6 +196,71 @@ export interface TldrawOptions {
|
|
|
156
196
|
* viewport's page dimensions regardless of overview zoom changes.
|
|
157
197
|
*/
|
|
158
198
|
readonly quickZoomPreservesScreenBounds: boolean
|
|
199
|
+
/**
|
|
200
|
+
* Called before content is written to the clipboard during a copy or cut operation.
|
|
201
|
+
* Receives the serialized content (shapes, bindings, assets) and can filter or transform
|
|
202
|
+
* it before it reaches the clipboard.
|
|
203
|
+
*
|
|
204
|
+
* Return a modified `TLContent` object to change what is copied or cut. Return `false` to
|
|
205
|
+
* cancel the clipboard write (for cut, the selected shapes are not removed). Return `void`
|
|
206
|
+
* (or `undefined`) to pass through unchanged. You may return a `Promise` of those values if
|
|
207
|
+
* the hook is async.
|
|
208
|
+
*
|
|
209
|
+
* @example
|
|
210
|
+
* ```tsx
|
|
211
|
+
* // Filter out "locked" shapes from copy
|
|
212
|
+
* onBeforeCopyToClipboard({ content, operation }) {
|
|
213
|
+
* return {
|
|
214
|
+
* ...content,
|
|
215
|
+
* shapes: content.shapes.filter(s => !s.meta.locked),
|
|
216
|
+
* rootShapeIds: content.rootShapeIds.filter(id =>
|
|
217
|
+
* content.shapes.find(s => s.id === id && !s.meta.locked)
|
|
218
|
+
* ),
|
|
219
|
+
* }
|
|
220
|
+
* }
|
|
221
|
+
* ```
|
|
222
|
+
*/
|
|
223
|
+
onBeforeCopyToClipboard?(
|
|
224
|
+
info: { editor: Editor; content: TLContent } & TLClipboardWriteInfo
|
|
225
|
+
): Awaitable<TLContent | false | void>
|
|
226
|
+
/**
|
|
227
|
+
* Called before pasted content is processed and shapes are created. Receives the parsed
|
|
228
|
+
* external content from the clipboard and can filter, transform, or cancel it.
|
|
229
|
+
*
|
|
230
|
+
* Return `false` to cancel the paste. Return a modified content object to transform it.
|
|
231
|
+
* Return `void` (or `undefined`) to pass through unchanged. You may return a `Promise` of
|
|
232
|
+
* those values if the hook is async.
|
|
233
|
+
*
|
|
234
|
+
* This only fires for clipboard paste operations (keyboard shortcuts and menu actions),
|
|
235
|
+
* not for file drops or programmatic `putExternalContent` calls.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```tsx
|
|
239
|
+
* // Block pasting of image files
|
|
240
|
+
* onBeforePasteFromClipboard({ content }) {
|
|
241
|
+
* if (content.type === 'files') {
|
|
242
|
+
* const nonImages = content.files.filter(f => !f.type.startsWith('image/'))
|
|
243
|
+
* if (nonImages.length === 0) return false
|
|
244
|
+
* return { ...content, files: nonImages }
|
|
245
|
+
* }
|
|
246
|
+
* }
|
|
247
|
+
* ```
|
|
248
|
+
*/
|
|
249
|
+
onBeforePasteFromClipboard?(info: {
|
|
250
|
+
editor: Editor
|
|
251
|
+
content: TLExternalContent<unknown>
|
|
252
|
+
source: 'native-event' | 'clipboard-read'
|
|
253
|
+
point?: VecLike
|
|
254
|
+
}): Awaitable<TLExternalContent<unknown> | false | void>
|
|
255
|
+
/**
|
|
256
|
+
* Called first for keyboard and menu paste, **before** tldraw handles or parses clipboard data
|
|
257
|
+
* (and before {@link TldrawOptions.onBeforePasteFromClipboard}).
|
|
258
|
+
*
|
|
259
|
+
* Return `false` to cancel tldraw's default paste handling for this gesture (same convention as
|
|
260
|
+
* {@link TldrawOptions.onBeforePasteFromClipboard}). Use this when you handle paste yourself from
|
|
261
|
+
* raw clipboard data, or to block the gesture entirely. Return `void` (or `undefined`) to continue.
|
|
262
|
+
*/
|
|
263
|
+
onClipboardPasteRaw?(info: TLClipboardPasteRawInfo): false | void
|
|
159
264
|
/**
|
|
160
265
|
* Called when content is dropped on the canvas. Provides the page position
|
|
161
266
|
* where the drop occurred and the underlying drag event object.
|
|
@@ -227,5 +332,8 @@ export const defaultTldrawOptions = {
|
|
|
227
332
|
text: {},
|
|
228
333
|
deepLinks: undefined,
|
|
229
334
|
quickZoomPreservesScreenBounds: true,
|
|
335
|
+
onBeforeCopyToClipboard: undefined,
|
|
336
|
+
onBeforePasteFromClipboard: undefined,
|
|
337
|
+
onClipboardPasteRaw: undefined,
|
|
230
338
|
experimental__onDropOnCanvas: undefined,
|
|
231
339
|
} as const satisfies TldrawOptions
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Vec, VecLike } from '../Vec'
|
|
2
1
|
import { intersectLineSegmentCircle } from '../intersect'
|
|
3
2
|
import { getArcMeasure, getPointInArcT, getPointOnCircle } from '../utils'
|
|
4
|
-
import {
|
|
3
|
+
import { Vec, VecLike } from '../Vec'
|
|
5
4
|
import { getVerticesCountForArcLength } from './geometry-constants'
|
|
5
|
+
import { Geometry2d, Geometry2dOptions } from './Geometry2d'
|
|
6
6
|
|
|
7
7
|
/** @public */
|
|
8
8
|
export class Arc2d extends Geometry2d {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { Box } from '../Box'
|
|
2
|
-
import { Vec, VecLike } from '../Vec'
|
|
3
2
|
import { intersectLineSegmentCircle } from '../intersect'
|
|
4
3
|
import { PI2, getPointOnCircle } from '../utils'
|
|
5
|
-
import {
|
|
4
|
+
import { Vec, VecLike } from '../Vec'
|
|
6
5
|
import { getVerticesCountForArcLength } from './geometry-constants'
|
|
6
|
+
import { Geometry2d, Geometry2dOptions } from './Geometry2d'
|
|
7
7
|
|
|
8
8
|
/** @public */
|
|
9
9
|
export class Circle2d extends Geometry2d {
|