@tldraw/editor 5.2.0-canary.cfef7b16ad41 → 5.2.0-canary.d28cf4347708
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 +8 -13
- package/dist-cjs/index.js +1 -5
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +1 -16
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/editor/Editor.js +3 -1
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/types/event-types.js.map +2 -2
- package/dist-cjs/lib/globals/environment.js +6 -1
- package/dist-cjs/lib/globals/environment.js.map +2 -2
- package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +3 -1
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js +0 -1
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/hooks/useScreenBounds.js +1 -0
- package/dist-cjs/lib/hooks/useScreenBounds.js.map +2 -2
- package/dist-cjs/lib/primitives/Vec.js +3 -2
- package/dist-cjs/lib/primitives/Vec.js.map +2 -2
- package/dist-cjs/lib/utils/pointer.js +5 -0
- package/dist-cjs/lib/utils/pointer.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 +8 -13
- package/dist-esm/index.mjs +1 -7
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +1 -16
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/editor/Editor.mjs +3 -1
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/types/event-types.mjs.map +2 -2
- package/dist-esm/lib/globals/environment.mjs +6 -1
- package/dist-esm/lib/globals/environment.mjs.map +2 -2
- package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +4 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -1
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useScreenBounds.mjs +1 -0
- package/dist-esm/lib/hooks/useScreenBounds.mjs.map +2 -2
- package/dist-esm/lib/primitives/Vec.mjs +3 -2
- package/dist-esm/lib/primitives/Vec.mjs.map +2 -2
- package/dist-esm/lib/utils/pointer.mjs +5 -0
- package/dist-esm/lib/utils/pointer.mjs.map +2 -2
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +1 -0
- package/package.json +7 -7
- package/src/index.ts +0 -5
- package/src/lib/components/default-components/DefaultCanvas.tsx +1 -17
- package/src/lib/editor/Editor.test.ts +36 -0
- package/src/lib/editor/Editor.ts +14 -2
- package/src/lib/editor/types/event-types.ts +7 -0
- package/src/lib/globals/environment.ts +7 -0
- package/src/lib/hooks/EditorComponentsContext.tsx +0 -2
- package/src/lib/hooks/useCanvasEvents.ts +6 -1
- package/src/lib/hooks/useEditorComponents.tsx +0 -1
- package/src/lib/hooks/useScreenBounds.ts +3 -0
- package/src/lib/primitives/Vec.ts +5 -2
- package/src/lib/utils/pointer.test.ts +29 -1
- package/src/lib/utils/pointer.ts +24 -0
- package/src/version.ts +3 -3
- package/dist-cjs/lib/components/default-components/DefaultSelectionBackground.js +0 -49
- package/dist-cjs/lib/components/default-components/DefaultSelectionBackground.js.map +0 -7
- package/dist-cjs/lib/hooks/useTransform.js +0 -43
- package/dist-cjs/lib/hooks/useTransform.js.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultSelectionBackground.mjs +0 -19
- package/dist-esm/lib/components/default-components/DefaultSelectionBackground.mjs.map +0 -7
- package/dist-esm/lib/hooks/useTransform.mjs +0 -23
- package/dist-esm/lib/hooks/useTransform.mjs.map +0 -7
- package/src/lib/components/default-components/DefaultSelectionBackground.tsx +0 -25
- package/src/lib/hooks/useTransform.ts +0 -30
|
@@ -32,7 +32,7 @@ export interface TLCanvasComponentProps {
|
|
|
32
32
|
export function DefaultCanvas({ className }: TLCanvasComponentProps) {
|
|
33
33
|
const editor = useEditor()
|
|
34
34
|
|
|
35
|
-
const {
|
|
35
|
+
const { Background, SvgDefs } = useEditorComponents()
|
|
36
36
|
|
|
37
37
|
const rCanvas = useRef<HTMLDivElement>(null)
|
|
38
38
|
const rHtmlLayer = useRef<HTMLDivElement>(null)
|
|
@@ -160,7 +160,6 @@ export function DefaultCanvas({ className }: TLCanvasComponentProps) {
|
|
|
160
160
|
{isGridMode && Grid && <GridWrapper />}
|
|
161
161
|
<div ref={rHtmlLayer} className="tl-html-layer tl-shapes" draggable={false}>
|
|
162
162
|
<OnTheCanvasWrapper />
|
|
163
|
-
{SelectionBackground && <SelectionBackgroundWrapper />}
|
|
164
163
|
{hideShapes ? null : <ShapesLayer canvasRef={rCanvas} />}
|
|
165
164
|
</div>
|
|
166
165
|
<CanvasOverlays />
|
|
@@ -345,21 +344,6 @@ function DebugSvgCopy({ id, mode }: { id: TLShapeId; mode: 'img' | 'iframe' }) {
|
|
|
345
344
|
)
|
|
346
345
|
}
|
|
347
346
|
|
|
348
|
-
function SelectionBackgroundWrapper() {
|
|
349
|
-
const editor = useEditor()
|
|
350
|
-
const selectionRotation = useValue('selection rotation', () => editor.getSelectionRotation(), [
|
|
351
|
-
editor,
|
|
352
|
-
])
|
|
353
|
-
const selectionBounds = useValue(
|
|
354
|
-
'selection bounds',
|
|
355
|
-
() => editor.getSelectionRotatedPageBounds(),
|
|
356
|
-
[editor]
|
|
357
|
-
)
|
|
358
|
-
const { SelectionBackground } = useEditorComponents()
|
|
359
|
-
if (!selectionBounds || !SelectionBackground) return null
|
|
360
|
-
return <SelectionBackground bounds={selectionBounds} rotation={selectionRotation} />
|
|
361
|
-
}
|
|
362
|
-
|
|
363
347
|
function OnTheCanvasWrapper() {
|
|
364
348
|
const { OnTheCanvas } = useEditorComponents()
|
|
365
349
|
if (!OnTheCanvas) return null
|
|
@@ -96,6 +96,42 @@ describe('updateShape', () => {
|
|
|
96
96
|
})
|
|
97
97
|
})
|
|
98
98
|
|
|
99
|
+
describe('updateViewportScreenBounds', () => {
|
|
100
|
+
it('bails without crashing or updating bounds when the container document has no body', () => {
|
|
101
|
+
const documentSpy = vi
|
|
102
|
+
.spyOn(editor, 'getContainerDocument')
|
|
103
|
+
.mockReturnValue({ body: null } as unknown as Document)
|
|
104
|
+
|
|
105
|
+
const prevScreenBounds = editor.getInstanceState().screenBounds
|
|
106
|
+
const prevInsets = editor.getInstanceState().insets
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
expect(() => editor.updateViewportScreenBounds(new Box(10, 20, 100, 200))).not.toThrow()
|
|
110
|
+
// A torn-down document is not measurable, so the bounds are left untouched.
|
|
111
|
+
expect(editor.getInstanceState().screenBounds).toEqual(prevScreenBounds)
|
|
112
|
+
expect(editor.getInstanceState().insets).toEqual(prevInsets)
|
|
113
|
+
} finally {
|
|
114
|
+
documentSpy.mockRestore()
|
|
115
|
+
}
|
|
116
|
+
})
|
|
117
|
+
|
|
118
|
+
it('uses the container document body to calculate right and bottom insets', () => {
|
|
119
|
+
const documentSpy = vi.spyOn(editor, 'getContainerDocument').mockReturnValue({
|
|
120
|
+
body: {
|
|
121
|
+
scrollWidth: 500,
|
|
122
|
+
scrollHeight: 400,
|
|
123
|
+
},
|
|
124
|
+
} as unknown as Document)
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
editor.updateViewportScreenBounds(new Box(10, 20, 100, 200))
|
|
128
|
+
expect(editor.getInstanceState().insets).toEqual([true, true, true, true])
|
|
129
|
+
} finally {
|
|
130
|
+
documentSpy.mockRestore()
|
|
131
|
+
}
|
|
132
|
+
})
|
|
133
|
+
})
|
|
134
|
+
|
|
99
135
|
describe('zoomToFit', () => {
|
|
100
136
|
it('no-op when isLocked is set', () => {
|
|
101
137
|
editor.getCurrentPageShapeIds = vi.fn(() => new Set([createShapeId('box1')]))
|
package/src/lib/editor/Editor.ts
CHANGED
|
@@ -4165,6 +4165,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
4165
4165
|
}
|
|
4166
4166
|
|
|
4167
4167
|
const doc = this.getContainerDocument()
|
|
4168
|
+
// If the container's document has been torn down (e.g. an iframe being
|
|
4169
|
+
// removed), its body is null and there's nothing meaningful to measure.
|
|
4170
|
+
if (!doc.body) return this
|
|
4171
|
+
|
|
4168
4172
|
const insets = [
|
|
4169
4173
|
// top
|
|
4170
4174
|
screenBounds.minY !== 0,
|
|
@@ -10177,6 +10181,12 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
10177
10181
|
|
|
10178
10182
|
if (ids.length === 0) return undefined
|
|
10179
10183
|
|
|
10184
|
+
// Text geometry is measured from the loaded font, so the export's bounds - and the
|
|
10185
|
+
// layout of any text within it - depend on the right fonts having loaded. Wait for them
|
|
10186
|
+
// before we measure; otherwise an export taken before fonts finish loading (e.g. right
|
|
10187
|
+
// after the editor mounts) is sized and laid out with fallback-font metrics.
|
|
10188
|
+
await this.fonts.loadRequiredFontsForCurrentPage(this.options.maxFontsToLoadBeforeRender)
|
|
10189
|
+
|
|
10180
10190
|
return exportToSvg(this, ids, opts)
|
|
10181
10191
|
}
|
|
10182
10192
|
|
|
@@ -11223,8 +11233,10 @@ export class Editor extends EventEmitter<TLEventMap> {
|
|
|
11223
11233
|
inputs.setIsPointing(true)
|
|
11224
11234
|
inputs.setIsDragging(false)
|
|
11225
11235
|
|
|
11226
|
-
// If pen mode is off
|
|
11227
|
-
|
|
11236
|
+
// If pen mode is off, turn it on for direct-display pen input only (e.g. Apple
|
|
11237
|
+
// Pencil on an iPad or a Surface Pen on a touchscreen). Indirect desktop tablet
|
|
11238
|
+
// styluses still draw as pens, but should not auto-enable pen mode.
|
|
11239
|
+
if (!isPenMode && info.isPenDirect) {
|
|
11228
11240
|
this.updateInstanceState({ isPenMode: true })
|
|
11229
11241
|
// Once pen mode is on, touch input is ignored, so we discard the
|
|
11230
11242
|
// in-progress touch interaction .
|
|
@@ -63,6 +63,13 @@ export type TLPointerEventInfo = TLBaseEventInfo & {
|
|
|
63
63
|
pointerId: number
|
|
64
64
|
button: number
|
|
65
65
|
isPen: boolean
|
|
66
|
+
/**
|
|
67
|
+
* Whether this pen event appears to be direct manipulation on the display (e.g. Apple Pencil on
|
|
68
|
+
* an iPad or a Surface Pen on a touchscreen) rather than indirect input from a desktop graphics
|
|
69
|
+
* tablet (e.g. a Wacom Intuos). Only direct-display pens should auto-enable pen mode. Drawing and
|
|
70
|
+
* pressure behavior is driven by `isPen` and applies to all pens regardless of this flag.
|
|
71
|
+
*/
|
|
72
|
+
isPenDirect?: boolean
|
|
66
73
|
} & TLPointerEventTarget
|
|
67
74
|
|
|
68
75
|
/** @public */
|
|
@@ -17,6 +17,10 @@ const tlenv = {
|
|
|
17
17
|
isWebview: false,
|
|
18
18
|
isDarwin: false,
|
|
19
19
|
hasCanvasSupport: false,
|
|
20
|
+
// Whether the device has a touch screen (an integrated coarse pointer, e.g. an iPad or a
|
|
21
|
+
// touchscreen laptop). Unlike `isCoarsePointer`, this reflects the device's hardware rather than
|
|
22
|
+
// the pointer currently in use, so it stays stable when a pen or mouse is used.
|
|
23
|
+
isTouchDevice: false,
|
|
20
24
|
}
|
|
21
25
|
|
|
22
26
|
let isForcedFinePointer = false
|
|
@@ -32,6 +36,9 @@ if (typeof window !== 'undefined') {
|
|
|
32
36
|
}
|
|
33
37
|
tlenv.hasCanvasSupport = 'Promise' in window && 'HTMLCanvasElement' in window
|
|
34
38
|
isForcedFinePointer = tlenv.isFirefox && !tlenv.isAndroid && !tlenv.isIos
|
|
39
|
+
tlenv.isTouchDevice =
|
|
40
|
+
('navigator' in window && window.navigator.maxTouchPoints > 0) ||
|
|
41
|
+
(typeof window.matchMedia === 'function' && window.matchMedia('(any-pointer: coarse)').matches)
|
|
35
42
|
}
|
|
36
43
|
|
|
37
44
|
/**
|
|
@@ -2,7 +2,6 @@ import { ComponentType, RefAttributes, createContext, useContext } from 'react'
|
|
|
2
2
|
import type { TLCanvasComponentProps } from '../components/default-components/DefaultCanvas'
|
|
3
3
|
import type { TLErrorFallbackComponent } from '../components/default-components/DefaultErrorFallback'
|
|
4
4
|
import type { TLGridProps } from '../components/default-components/DefaultGrid'
|
|
5
|
-
import type { TLSelectionBackgroundProps } from '../components/default-components/DefaultSelectionBackground'
|
|
6
5
|
import type { TLShapeErrorFallbackComponent } from '../components/default-components/DefaultShapeErrorFallback'
|
|
7
6
|
import type { TLShapeWrapperProps } from '../components/default-components/DefaultShapeWrapper'
|
|
8
7
|
|
|
@@ -14,7 +13,6 @@ export interface TLEditorComponents {
|
|
|
14
13
|
InFrontOfTheCanvas?: ComponentType | null
|
|
15
14
|
LoadingScreen?: ComponentType | null
|
|
16
15
|
OnTheCanvas?: ComponentType | null
|
|
17
|
-
SelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null
|
|
18
16
|
ShapeWrapper?: ComponentType<TLShapeWrapperProps & RefAttributes<HTMLDivElement>> | null
|
|
19
17
|
Spinner?: ComponentType<React.SVGProps<SVGSVGElement>> | null
|
|
20
18
|
SvgDefs?: ComponentType | null
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
setPointerCapture,
|
|
9
9
|
} from '../utils/dom'
|
|
10
10
|
import { getPointerInfo } from '../utils/getPointerInfo'
|
|
11
|
-
import { getPointerEventButton, isSecondaryClickEvent } from '../utils/pointer'
|
|
11
|
+
import { getPointerEventButton, isDirectDisplayPen, isSecondaryClickEvent } from '../utils/pointer'
|
|
12
12
|
import { useEditor } from './useEditor'
|
|
13
13
|
|
|
14
14
|
export function useCanvasEvents() {
|
|
@@ -39,6 +39,10 @@ export function useCanvasEvents() {
|
|
|
39
39
|
|
|
40
40
|
if (button !== 0 && button !== 1 && button !== 2 && button !== 5) return
|
|
41
41
|
|
|
42
|
+
// Detect direct-display pen input (Apple Pencil, Surface Pen on a touchscreen) so we
|
|
43
|
+
// only auto-enable pen mode for it, not for an indirect desktop tablet stylus.
|
|
44
|
+
const isPenDirect = isDirectDisplayPen(e)
|
|
45
|
+
|
|
42
46
|
setPointerCapture(e.currentTarget, e)
|
|
43
47
|
|
|
44
48
|
editor.dispatch({
|
|
@@ -46,6 +50,7 @@ export function useCanvasEvents() {
|
|
|
46
50
|
target: 'canvas',
|
|
47
51
|
name: 'pointer_down',
|
|
48
52
|
...getPointerInfo(editor, e),
|
|
53
|
+
isPenDirect,
|
|
49
54
|
})
|
|
50
55
|
}
|
|
51
56
|
|
|
@@ -11,6 +11,9 @@ export function useScreenBounds(ref: React.RefObject<HTMLElement | null>) {
|
|
|
11
11
|
const updateBounds = throttle(
|
|
12
12
|
() => {
|
|
13
13
|
if (!ref.current) return
|
|
14
|
+
// If the container's document has been torn down (e.g. an iframe
|
|
15
|
+
// being removed), there's nothing to measure — bail.
|
|
16
|
+
if (!ref.current.ownerDocument.body) return
|
|
14
17
|
editor.updateViewportScreenBounds(ref.current)
|
|
15
18
|
},
|
|
16
19
|
200,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import { VecModel } from '@tldraw/tlschema'
|
|
2
2
|
import { EASINGS } from './easings'
|
|
3
|
+
|
|
4
|
+
const { easeInQuad, easeInOutQuad } = EASINGS
|
|
5
|
+
|
|
3
6
|
function clamp(n: number, min: number, max?: number): number {
|
|
4
7
|
return Math.max(min, typeof max !== 'undefined' ? Math.min(n, max) : n)
|
|
5
8
|
}
|
|
@@ -634,13 +637,13 @@ export class Vec {
|
|
|
634
637
|
* @param steps - The number of points to return.
|
|
635
638
|
* @param ease - The easing to use.
|
|
636
639
|
*/
|
|
637
|
-
static PointsBetween(A: VecModel, B: VecModel, steps = 6, ease =
|
|
640
|
+
static PointsBetween(A: VecModel, B: VecModel, steps = 6, ease = easeInQuad): Vec[] {
|
|
638
641
|
const results: Vec[] = []
|
|
639
642
|
|
|
640
643
|
for (let i = 0; i < steps; i++) {
|
|
641
644
|
const t = ease(i / (steps - 1))
|
|
642
645
|
const point = Vec.Lrp(A, B, t)
|
|
643
|
-
point.z = Math.min(1, 0.5 + Math.abs(0.5 -
|
|
646
|
+
point.z = Math.min(1, 0.5 + Math.abs(0.5 - easeInOutQuad(t)) * 0.65)
|
|
644
647
|
results.push(point)
|
|
645
648
|
}
|
|
646
649
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { tlenv } from '../globals/environment'
|
|
2
2
|
import { TestEditor } from '../test/TestEditor'
|
|
3
3
|
import { getPointerInfo } from './getPointerInfo'
|
|
4
|
-
import { isSecondaryClickEvent } from './pointer'
|
|
4
|
+
import { isDirectDisplayPen, isSecondaryClickEvent } from './pointer'
|
|
5
5
|
|
|
6
6
|
const originalIsDarwin = tlenv.isDarwin
|
|
7
7
|
|
|
@@ -21,6 +21,34 @@ describe('isSecondaryClickEvent', () => {
|
|
|
21
21
|
})
|
|
22
22
|
})
|
|
23
23
|
|
|
24
|
+
describe('isDirectDisplayPen', () => {
|
|
25
|
+
const originalIsTouchDevice = tlenv.isTouchDevice
|
|
26
|
+
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
tlenv.isTouchDevice = originalIsTouchDevice
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
function event(pointerType: string) {
|
|
32
|
+
return { pointerType, pointerId: 1 } as unknown as PointerEvent
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
it('treats a pen on a touch-capable device as a direct-display pen', () => {
|
|
36
|
+
tlenv.isTouchDevice = true
|
|
37
|
+
expect(isDirectDisplayPen(event('pen'))).toBe(true)
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('treats a pen on a non-touch device as indirect', () => {
|
|
41
|
+
tlenv.isTouchDevice = false
|
|
42
|
+
expect(isDirectDisplayPen(event('pen'))).toBe(false)
|
|
43
|
+
})
|
|
44
|
+
|
|
45
|
+
it('is never true for mouse or touch input, even on a touch-capable device', () => {
|
|
46
|
+
tlenv.isTouchDevice = true
|
|
47
|
+
expect(isDirectDisplayPen(event('mouse'))).toBe(false)
|
|
48
|
+
expect(isDirectDisplayPen(event('touch'))).toBe(false)
|
|
49
|
+
})
|
|
50
|
+
})
|
|
51
|
+
|
|
24
52
|
describe('ctrl + left-click on macOS fires as a right-click (regression)', () => {
|
|
25
53
|
// Regression test for https://github.com/tldraw/tldraw/issues/8217
|
|
26
54
|
// On macOS, a ctrl + left-click should be treated as a right-click
|
package/src/lib/utils/pointer.ts
CHANGED
|
@@ -1,5 +1,29 @@
|
|
|
1
|
+
import type React from 'react'
|
|
1
2
|
import { tlenv } from '../globals/environment'
|
|
2
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Decide whether a pen pointer event looks like direct manipulation on the display (e.g. Apple
|
|
6
|
+
* Pencil on an iPad or a Surface Pen on a touchscreen) rather than indirect input from a desktop
|
|
7
|
+
* graphics tablet (e.g. a Wacom Intuos).
|
|
8
|
+
*
|
|
9
|
+
* We can't tell the two apart from the pointer event itself: both report `pointerType: 'pen'`, and
|
|
10
|
+
* implicit pointer capture — which in theory distinguishes direct-manipulation pointers — isn't
|
|
11
|
+
* reliably observable across browsers (notably WebKit/iPad). Instead we key off the device: a
|
|
12
|
+
* direct-display pen draws on a touch-capable screen, while an indirect graphics tablet is used on
|
|
13
|
+
* a non-touch desktop alongside a mouse. A device with no touch input therefore can't host a
|
|
14
|
+
* direct-display pen.
|
|
15
|
+
*
|
|
16
|
+
* Note this uses {@link tlenv.isTouchDevice} — the device's fixed touch capability — not the
|
|
17
|
+
* editor's dynamic `isCoarsePointer` state, which a pen `pointerdown` flips to coarse regardless
|
|
18
|
+
* of device.
|
|
19
|
+
*
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
export function isDirectDisplayPen(e: React.PointerEvent | PointerEvent): boolean {
|
|
23
|
+
if (e.pointerType !== 'pen') return false
|
|
24
|
+
return tlenv.isTouchDevice
|
|
25
|
+
}
|
|
26
|
+
|
|
3
27
|
/** @internal */
|
|
4
28
|
interface PointerLike {
|
|
5
29
|
button: number
|
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 = '5.2.0-canary.
|
|
4
|
+
export const version = '5.2.0-canary.d28cf4347708'
|
|
5
5
|
export const publishDates = {
|
|
6
6
|
major: '2026-05-06T16:28:18.473Z',
|
|
7
|
-
minor: '2026-06-
|
|
8
|
-
patch: '2026-06-
|
|
7
|
+
minor: '2026-06-23T20:12:41.773Z',
|
|
8
|
+
patch: '2026-06-23T20:12:41.773Z',
|
|
9
9
|
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __export = (target, all) => {
|
|
9
|
-
for (var name in all)
|
|
10
|
-
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
-
};
|
|
12
|
-
var __copyProps = (to, from, except, desc) => {
|
|
13
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
-
for (let key of __getOwnPropNames(from))
|
|
15
|
-
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
-
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
-
}
|
|
18
|
-
return to;
|
|
19
|
-
};
|
|
20
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
-
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
-
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
-
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
-
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
-
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
-
mod
|
|
27
|
-
));
|
|
28
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var DefaultSelectionBackground_exports = {};
|
|
30
|
-
__export(DefaultSelectionBackground_exports, {
|
|
31
|
-
DefaultSelectionBackground: () => DefaultSelectionBackground
|
|
32
|
-
});
|
|
33
|
-
module.exports = __toCommonJS(DefaultSelectionBackground_exports);
|
|
34
|
-
var import_jsx_runtime = require("react/jsx-runtime");
|
|
35
|
-
var React = __toESM(require("react"), 1);
|
|
36
|
-
var import_useTransform = require("../../hooks/useTransform");
|
|
37
|
-
var import_utils = require("../../primitives/utils");
|
|
38
|
-
function DefaultSelectionBackground({ bounds, rotation }) {
|
|
39
|
-
const rDiv = React.useRef(null);
|
|
40
|
-
(0, import_useTransform.useTransform)(rDiv, bounds.x, bounds.y, 1, rotation);
|
|
41
|
-
React.useLayoutEffect(() => {
|
|
42
|
-
const div = rDiv.current;
|
|
43
|
-
if (!div) return;
|
|
44
|
-
div.style.width = (0, import_utils.toDomPrecision)(Math.max(1, bounds.width)) + "px";
|
|
45
|
-
div.style.height = (0, import_utils.toDomPrecision)(Math.max(1, bounds.height)) + "px";
|
|
46
|
-
}, [bounds.width, bounds.height]);
|
|
47
|
-
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ref: rDiv, className: "tl-selection__bg", draggable: false });
|
|
48
|
-
}
|
|
49
|
-
//# sourceMappingURL=DefaultSelectionBackground.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/lib/components/default-components/DefaultSelectionBackground.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react'\nimport { useTransform } from '../../hooks/useTransform'\nimport { Box } from '../../primitives/Box'\nimport { toDomPrecision } from '../../primitives/utils'\n\n/** @public */\nexport interface TLSelectionBackgroundProps {\n\tbounds: Box\n\trotation: number\n}\n\n/** @public @react */\nexport function DefaultSelectionBackground({ bounds, rotation }: TLSelectionBackgroundProps) {\n\tconst rDiv = React.useRef<HTMLDivElement>(null)\n\tuseTransform(rDiv, bounds.x, bounds.y, 1, rotation)\n\n\tReact.useLayoutEffect(() => {\n\t\tconst div = rDiv.current\n\t\tif (!div) return\n\t\tdiv.style.width = toDomPrecision(Math.max(1, bounds.width)) + 'px'\n\t\tdiv.style.height = toDomPrecision(Math.max(1, bounds.height)) + 'px'\n\t}, [bounds.width, bounds.height])\n\n\treturn <div ref={rDiv} className=\"tl-selection__bg\" draggable={false} />\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAuBQ;AAvBR,YAAuB;AACvB,0BAA6B;AAE7B,mBAA+B;AASxB,SAAS,2BAA2B,EAAE,QAAQ,SAAS,GAA+B;AAC5F,QAAM,OAAO,MAAM,OAAuB,IAAI;AAC9C,wCAAa,MAAM,OAAO,GAAG,OAAO,GAAG,GAAG,QAAQ;AAElD,QAAM,gBAAgB,MAAM;AAC3B,UAAM,MAAM,KAAK;AACjB,QAAI,CAAC,IAAK;AACV,QAAI,MAAM,YAAQ,6BAAe,KAAK,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI;AAC9D,QAAI,MAAM,aAAS,6BAAe,KAAK,IAAI,GAAG,OAAO,MAAM,CAAC,IAAI;AAAA,EACjE,GAAG,CAAC,OAAO,OAAO,OAAO,MAAM,CAAC;AAEhC,SAAO,4CAAC,SAAI,KAAK,MAAM,WAAU,oBAAmB,WAAW,OAAO;AACvE;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,43 +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 useTransform_exports = {};
|
|
20
|
-
__export(useTransform_exports, {
|
|
21
|
-
useTransform: () => useTransform
|
|
22
|
-
});
|
|
23
|
-
module.exports = __toCommonJS(useTransform_exports);
|
|
24
|
-
var import_react = require("react");
|
|
25
|
-
function useTransform(ref, x, y, scale, rotate, additionalOffset) {
|
|
26
|
-
(0, import_react.useLayoutEffect)(() => {
|
|
27
|
-
const elm = ref.current;
|
|
28
|
-
if (!elm) return;
|
|
29
|
-
if (x === void 0) return;
|
|
30
|
-
let trans = `translate(${x}px, ${y}px)`;
|
|
31
|
-
if (scale !== void 0) {
|
|
32
|
-
trans += ` scale(${scale})`;
|
|
33
|
-
}
|
|
34
|
-
if (rotate !== void 0) {
|
|
35
|
-
trans += ` rotate(${rotate}rad)`;
|
|
36
|
-
}
|
|
37
|
-
if (additionalOffset) {
|
|
38
|
-
trans += ` translate(${additionalOffset.x}px, ${additionalOffset.y}px)`;
|
|
39
|
-
}
|
|
40
|
-
elm.style.transform = trans;
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
//# sourceMappingURL=useTransform.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/lib/hooks/useTransform.ts"],
|
|
4
|
-
"sourcesContent": ["import { useLayoutEffect } from 'react'\nimport { VecLike } from '../primitives/Vec'\n\n/** @public */\nexport function useTransform(\n\tref: React.RefObject<HTMLElement | SVGElement | null>,\n\tx?: number,\n\ty?: number,\n\tscale?: number,\n\trotate?: number,\n\tadditionalOffset?: VecLike\n) {\n\tuseLayoutEffect(() => {\n\t\tconst elm = ref.current\n\t\tif (!elm) return\n\t\tif (x === undefined) return\n\n\t\tlet trans = `translate(${x}px, ${y}px)`\n\t\tif (scale !== undefined) {\n\t\t\ttrans += ` scale(${scale})`\n\t\t}\n\t\tif (rotate !== undefined) {\n\t\t\ttrans += ` rotate(${rotate}rad)`\n\t\t}\n\t\tif (additionalOffset) {\n\t\t\ttrans += ` translate(${additionalOffset.x}px, ${additionalOffset.y}px)`\n\t\t}\n\t\telm.style.transform = trans\n\t})\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAgC;AAIzB,SAAS,aACf,KACA,GACA,GACA,OACA,QACA,kBACC;AACD,oCAAgB,MAAM;AACrB,UAAM,MAAM,IAAI;AAChB,QAAI,CAAC,IAAK;AACV,QAAI,MAAM,OAAW;AAErB,QAAI,QAAQ,aAAa,CAAC,OAAO,CAAC;AAClC,QAAI,UAAU,QAAW;AACxB,eAAS,UAAU,KAAK;AAAA,IACzB;AACA,QAAI,WAAW,QAAW;AACzB,eAAS,WAAW,MAAM;AAAA,IAC3B;AACA,QAAI,kBAAkB;AACrB,eAAS,cAAc,iBAAiB,CAAC,OAAO,iBAAiB,CAAC;AAAA,IACnE;AACA,QAAI,MAAM,YAAY;AAAA,EACvB,CAAC;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import * as React from "react";
|
|
3
|
-
import { useTransform } from "../../hooks/useTransform.mjs";
|
|
4
|
-
import { toDomPrecision } from "../../primitives/utils.mjs";
|
|
5
|
-
function DefaultSelectionBackground({ bounds, rotation }) {
|
|
6
|
-
const rDiv = React.useRef(null);
|
|
7
|
-
useTransform(rDiv, bounds.x, bounds.y, 1, rotation);
|
|
8
|
-
React.useLayoutEffect(() => {
|
|
9
|
-
const div = rDiv.current;
|
|
10
|
-
if (!div) return;
|
|
11
|
-
div.style.width = toDomPrecision(Math.max(1, bounds.width)) + "px";
|
|
12
|
-
div.style.height = toDomPrecision(Math.max(1, bounds.height)) + "px";
|
|
13
|
-
}, [bounds.width, bounds.height]);
|
|
14
|
-
return /* @__PURE__ */ jsx("div", { ref: rDiv, className: "tl-selection__bg", draggable: false });
|
|
15
|
-
}
|
|
16
|
-
export {
|
|
17
|
-
DefaultSelectionBackground
|
|
18
|
-
};
|
|
19
|
-
//# sourceMappingURL=DefaultSelectionBackground.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../src/lib/components/default-components/DefaultSelectionBackground.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react'\nimport { useTransform } from '../../hooks/useTransform'\nimport { Box } from '../../primitives/Box'\nimport { toDomPrecision } from '../../primitives/utils'\n\n/** @public */\nexport interface TLSelectionBackgroundProps {\n\tbounds: Box\n\trotation: number\n}\n\n/** @public @react */\nexport function DefaultSelectionBackground({ bounds, rotation }: TLSelectionBackgroundProps) {\n\tconst rDiv = React.useRef<HTMLDivElement>(null)\n\tuseTransform(rDiv, bounds.x, bounds.y, 1, rotation)\n\n\tReact.useLayoutEffect(() => {\n\t\tconst div = rDiv.current\n\t\tif (!div) return\n\t\tdiv.style.width = toDomPrecision(Math.max(1, bounds.width)) + 'px'\n\t\tdiv.style.height = toDomPrecision(Math.max(1, bounds.height)) + 'px'\n\t}, [bounds.width, bounds.height])\n\n\treturn <div ref={rDiv} className=\"tl-selection__bg\" draggable={false} />\n}\n"],
|
|
5
|
-
"mappings": "AAuBQ;AAvBR,YAAY,WAAW;AACvB,SAAS,oBAAoB;AAE7B,SAAS,sBAAsB;AASxB,SAAS,2BAA2B,EAAE,QAAQ,SAAS,GAA+B;AAC5F,QAAM,OAAO,MAAM,OAAuB,IAAI;AAC9C,eAAa,MAAM,OAAO,GAAG,OAAO,GAAG,GAAG,QAAQ;AAElD,QAAM,gBAAgB,MAAM;AAC3B,UAAM,MAAM,KAAK;AACjB,QAAI,CAAC,IAAK;AACV,QAAI,MAAM,QAAQ,eAAe,KAAK,IAAI,GAAG,OAAO,KAAK,CAAC,IAAI;AAC9D,QAAI,MAAM,SAAS,eAAe,KAAK,IAAI,GAAG,OAAO,MAAM,CAAC,IAAI;AAAA,EACjE,GAAG,CAAC,OAAO,OAAO,OAAO,MAAM,CAAC;AAEhC,SAAO,oBAAC,SAAI,KAAK,MAAM,WAAU,oBAAmB,WAAW,OAAO;AACvE;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useLayoutEffect } from "react";
|
|
2
|
-
function useTransform(ref, x, y, scale, rotate, additionalOffset) {
|
|
3
|
-
useLayoutEffect(() => {
|
|
4
|
-
const elm = ref.current;
|
|
5
|
-
if (!elm) return;
|
|
6
|
-
if (x === void 0) return;
|
|
7
|
-
let trans = `translate(${x}px, ${y}px)`;
|
|
8
|
-
if (scale !== void 0) {
|
|
9
|
-
trans += ` scale(${scale})`;
|
|
10
|
-
}
|
|
11
|
-
if (rotate !== void 0) {
|
|
12
|
-
trans += ` rotate(${rotate}rad)`;
|
|
13
|
-
}
|
|
14
|
-
if (additionalOffset) {
|
|
15
|
-
trans += ` translate(${additionalOffset.x}px, ${additionalOffset.y}px)`;
|
|
16
|
-
}
|
|
17
|
-
elm.style.transform = trans;
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
export {
|
|
21
|
-
useTransform
|
|
22
|
-
};
|
|
23
|
-
//# sourceMappingURL=useTransform.mjs.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/lib/hooks/useTransform.ts"],
|
|
4
|
-
"sourcesContent": ["import { useLayoutEffect } from 'react'\nimport { VecLike } from '../primitives/Vec'\n\n/** @public */\nexport function useTransform(\n\tref: React.RefObject<HTMLElement | SVGElement | null>,\n\tx?: number,\n\ty?: number,\n\tscale?: number,\n\trotate?: number,\n\tadditionalOffset?: VecLike\n) {\n\tuseLayoutEffect(() => {\n\t\tconst elm = ref.current\n\t\tif (!elm) return\n\t\tif (x === undefined) return\n\n\t\tlet trans = `translate(${x}px, ${y}px)`\n\t\tif (scale !== undefined) {\n\t\t\ttrans += ` scale(${scale})`\n\t\t}\n\t\tif (rotate !== undefined) {\n\t\t\ttrans += ` rotate(${rotate}rad)`\n\t\t}\n\t\tif (additionalOffset) {\n\t\t\ttrans += ` translate(${additionalOffset.x}px, ${additionalOffset.y}px)`\n\t\t}\n\t\telm.style.transform = trans\n\t})\n}\n"],
|
|
5
|
-
"mappings": "AAAA,SAAS,uBAAuB;AAIzB,SAAS,aACf,KACA,GACA,GACA,OACA,QACA,kBACC;AACD,kBAAgB,MAAM;AACrB,UAAM,MAAM,IAAI;AAChB,QAAI,CAAC,IAAK;AACV,QAAI,MAAM,OAAW;AAErB,QAAI,QAAQ,aAAa,CAAC,OAAO,CAAC;AAClC,QAAI,UAAU,QAAW;AACxB,eAAS,UAAU,KAAK;AAAA,IACzB;AACA,QAAI,WAAW,QAAW;AACzB,eAAS,WAAW,MAAM;AAAA,IAC3B;AACA,QAAI,kBAAkB;AACrB,eAAS,cAAc,iBAAiB,CAAC,OAAO,iBAAiB,CAAC;AAAA,IACnE;AACA,QAAI,MAAM,YAAY;AAAA,EACvB,CAAC;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
import { useTransform } from '../../hooks/useTransform'
|
|
3
|
-
import { Box } from '../../primitives/Box'
|
|
4
|
-
import { toDomPrecision } from '../../primitives/utils'
|
|
5
|
-
|
|
6
|
-
/** @public */
|
|
7
|
-
export interface TLSelectionBackgroundProps {
|
|
8
|
-
bounds: Box
|
|
9
|
-
rotation: number
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
/** @public @react */
|
|
13
|
-
export function DefaultSelectionBackground({ bounds, rotation }: TLSelectionBackgroundProps) {
|
|
14
|
-
const rDiv = React.useRef<HTMLDivElement>(null)
|
|
15
|
-
useTransform(rDiv, bounds.x, bounds.y, 1, rotation)
|
|
16
|
-
|
|
17
|
-
React.useLayoutEffect(() => {
|
|
18
|
-
const div = rDiv.current
|
|
19
|
-
if (!div) return
|
|
20
|
-
div.style.width = toDomPrecision(Math.max(1, bounds.width)) + 'px'
|
|
21
|
-
div.style.height = toDomPrecision(Math.max(1, bounds.height)) + 'px'
|
|
22
|
-
}, [bounds.width, bounds.height])
|
|
23
|
-
|
|
24
|
-
return <div ref={rDiv} className="tl-selection__bg" draggable={false} />
|
|
25
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { useLayoutEffect } from 'react'
|
|
2
|
-
import { VecLike } from '../primitives/Vec'
|
|
3
|
-
|
|
4
|
-
/** @public */
|
|
5
|
-
export function useTransform(
|
|
6
|
-
ref: React.RefObject<HTMLElement | SVGElement | null>,
|
|
7
|
-
x?: number,
|
|
8
|
-
y?: number,
|
|
9
|
-
scale?: number,
|
|
10
|
-
rotate?: number,
|
|
11
|
-
additionalOffset?: VecLike
|
|
12
|
-
) {
|
|
13
|
-
useLayoutEffect(() => {
|
|
14
|
-
const elm = ref.current
|
|
15
|
-
if (!elm) return
|
|
16
|
-
if (x === undefined) return
|
|
17
|
-
|
|
18
|
-
let trans = `translate(${x}px, ${y}px)`
|
|
19
|
-
if (scale !== undefined) {
|
|
20
|
-
trans += ` scale(${scale})`
|
|
21
|
-
}
|
|
22
|
-
if (rotate !== undefined) {
|
|
23
|
-
trans += ` rotate(${rotate}rad)`
|
|
24
|
-
}
|
|
25
|
-
if (additionalOffset) {
|
|
26
|
-
trans += ` translate(${additionalOffset.x}px, ${additionalOffset.y}px)`
|
|
27
|
-
}
|
|
28
|
-
elm.style.transform = trans
|
|
29
|
-
})
|
|
30
|
-
}
|