@tldraw/editor 4.6.0-next.fe1474dc57d8 → 5.0.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/dist-cjs/index.d.ts +412 -179
- package/dist-cjs/index.js +12 -23
- package/dist-cjs/index.js.map +2 -2
- package/dist-cjs/lib/TldrawEditor.js +3 -0
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js +180 -0
- package/dist-cjs/lib/components/default-components/CanvasOverlays.js.map +7 -0
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +44 -249
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +3 -3
- package/dist-cjs/lib/editor/Editor.js +78 -28
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js +98 -0
- package/dist-cjs/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.js.map +7 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js +14 -0
- package/dist-cjs/lib/editor/managers/ThemeManager/defaultThemes.js.map +2 -2
- package/dist-cjs/lib/editor/overlays/OverlayManager.js +154 -0
- package/dist-cjs/lib/editor/overlays/OverlayManager.js.map +7 -0
- package/dist-cjs/lib/editor/overlays/OverlayUtil.js +92 -0
- package/dist-cjs/lib/editor/overlays/OverlayUtil.js.map +7 -0
- package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js +161 -0
- package/dist-cjs/lib/editor/overlays/ShapeIndicatorOverlayUtil.js.map +7 -0
- package/dist-cjs/lib/editor/overlays/getOverlayDisplayValues.js +39 -0
- package/dist-cjs/lib/editor/overlays/getOverlayDisplayValues.js.map +7 -0
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js +3 -0
- package/dist-cjs/lib/editor/shapes/BaseFrameLikeShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +25 -23
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js +32 -2
- package/dist-cjs/lib/editor/shapes/group/GroupShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/types/event-types.js.map +2 -2
- package/dist-cjs/lib/exports/fetchCache.js +1 -1
- package/dist-cjs/lib/exports/fetchCache.js.map +2 -2
- package/dist-cjs/lib/hooks/EditorComponentsContext.js.map +2 -2
- package/dist-cjs/lib/hooks/useCanvasEvents.js +3 -3
- package/dist-cjs/lib/hooks/useCanvasEvents.js.map +2 -2
- package/dist-cjs/lib/hooks/useEditorComponents.js +0 -28
- package/dist-cjs/lib/hooks/useEditorComponents.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +1 -36
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/hooks/useShapeCulling.js +2 -1
- package/dist-cjs/lib/hooks/useShapeCulling.js.map +2 -2
- package/dist-cjs/lib/options.js +0 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/utils/reparenting.js +20 -7
- package/dist-cjs/lib/utils/reparenting.js.map +2 -2
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js +3 -0
- package/dist-cjs/lib/utils/sync/TLLocalSyncClient.js.map +2 -2
- package/dist-cjs/version.js +4 -4
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +412 -179
- package/dist-esm/index.mjs +19 -41
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +3 -0
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs +160 -0
- package/dist-esm/lib/components/default-components/CanvasOverlays.mjs.map +7 -0
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +45 -250
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +3 -3
- package/dist-esm/lib/editor/Editor.mjs +78 -29
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs +83 -0
- package/dist-esm/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.mjs.map +7 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs +14 -0
- package/dist-esm/lib/editor/managers/ThemeManager/defaultThemes.mjs.map +2 -2
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs +136 -0
- package/dist-esm/lib/editor/overlays/OverlayManager.mjs.map +7 -0
- package/dist-esm/lib/editor/overlays/OverlayUtil.mjs +72 -0
- package/dist-esm/lib/editor/overlays/OverlayUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs +141 -0
- package/dist-esm/lib/editor/overlays/ShapeIndicatorOverlayUtil.mjs.map +7 -0
- package/dist-esm/lib/editor/overlays/getOverlayDisplayValues.mjs +19 -0
- package/dist-esm/lib/editor/overlays/getOverlayDisplayValues.mjs.map +7 -0
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs +3 -0
- package/dist-esm/lib/editor/shapes/BaseFrameLikeShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +25 -23
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs +32 -2
- package/dist-esm/lib/editor/shapes/group/GroupShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/types/event-types.mjs.map +2 -2
- package/dist-esm/lib/exports/fetchCache.mjs +2 -2
- package/dist-esm/lib/exports/fetchCache.mjs.map +2 -2
- package/dist-esm/lib/hooks/EditorComponentsContext.mjs.map +2 -2
- package/dist-esm/lib/hooks/useCanvasEvents.mjs +3 -3
- package/dist-esm/lib/hooks/useCanvasEvents.mjs.map +2 -2
- package/dist-esm/lib/hooks/useEditorComponents.mjs +0 -28
- package/dist-esm/lib/hooks/useEditorComponents.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +2 -40
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useShapeCulling.mjs +2 -1
- package/dist-esm/lib/hooks/useShapeCulling.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +0 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/utils/reparenting.mjs +20 -7
- package/dist-esm/lib/utils/reparenting.mjs.map +2 -2
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs +3 -0
- package/dist-esm/lib/utils/sync/TLLocalSyncClient.mjs.map +2 -2
- package/dist-esm/version.mjs +4 -4
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +4 -239
- package/package.json +7 -7
- package/src/index.ts +17 -39
- package/src/lib/TldrawEditor.tsx +9 -0
- package/src/lib/components/default-components/CanvasOverlays.tsx +208 -0
- package/src/lib/components/default-components/DefaultCanvas.tsx +49 -324
- package/src/lib/editor/Editor.test.ts +3 -1
- package/src/lib/editor/Editor.ts +80 -24
- package/src/lib/editor/managers/CollaboratorsManager/CollaboratorsManager.ts +98 -0
- package/src/lib/editor/managers/ThemeManager/defaultThemes.ts +14 -0
- package/src/lib/editor/overlays/OverlayManager.ts +183 -0
- package/src/lib/editor/overlays/OverlayUtil.ts +143 -0
- package/src/lib/editor/overlays/ShapeIndicatorOverlayUtil.ts +216 -0
- package/src/lib/editor/overlays/getOverlayDisplayValues.ts +51 -0
- package/src/lib/editor/shapes/BaseFrameLikeShapeUtil.tsx +9 -2
- package/src/lib/editor/shapes/ShapeUtil.ts +34 -26
- package/src/lib/editor/shapes/group/GroupShapeUtil.tsx +40 -3
- package/src/lib/editor/types/event-types.ts +2 -0
- package/src/lib/exports/fetchCache.ts +2 -4
- package/src/lib/exports/getSvgJsx.test.ts +3 -1
- package/src/lib/hooks/EditorComponentsContext.tsx +0 -27
- package/src/lib/hooks/useCanvasEvents.ts +13 -8
- package/src/lib/hooks/useEditorComponents.tsx +0 -28
- package/src/lib/hooks/usePeerIds.ts +6 -55
- package/src/lib/hooks/useShapeCulling.tsx +3 -1
- package/src/lib/options.ts +0 -7
- package/src/lib/utils/reparenting.ts +22 -9
- package/src/lib/utils/sync/TLLocalSyncClient.ts +3 -0
- package/src/version.ts +4 -4
- package/dist-cjs/lib/components/GeometryDebuggingView.js +0 -115
- package/dist-cjs/lib/components/GeometryDebuggingView.js.map +0 -7
- package/dist-cjs/lib/components/LiveCollaborators.js +0 -152
- package/dist-cjs/lib/components/LiveCollaborators.js.map +0 -7
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +0 -234
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultBrush.js +0 -38
- package/dist-cjs/lib/components/default-components/DefaultBrush.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js +0 -71
- package/dist-cjs/lib/components/default-components/DefaultCollaboratorHint.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultCursor.js +0 -59
- package/dist-cjs/lib/components/default-components/DefaultCursor.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultHandle.js +0 -56
- package/dist-cjs/lib/components/default-components/DefaultHandle.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultHandles.js +0 -28
- package/dist-cjs/lib/components/default-components/DefaultHandles.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultScribble.js +0 -51
- package/dist-cjs/lib/components/default-components/DefaultScribble.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultSelectionForeground.js +0 -69
- package/dist-cjs/lib/components/default-components/DefaultSelectionForeground.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +0 -107
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicatorErrorFallback.js +0 -28
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicatorErrorFallback.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +0 -102
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +0 -7
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js +0 -170
- package/dist-cjs/lib/components/default-components/DefaultSnapIndictor.js.map +0 -7
- package/dist-cjs/lib/hooks/useHandleEvents.js +0 -100
- package/dist-cjs/lib/hooks/useHandleEvents.js.map +0 -7
- package/dist-cjs/lib/hooks/useSelectionEvents.js +0 -98
- package/dist-cjs/lib/hooks/useSelectionEvents.js.map +0 -7
- package/dist-esm/lib/components/GeometryDebuggingView.mjs +0 -95
- package/dist-esm/lib/components/GeometryDebuggingView.mjs.map +0 -7
- package/dist-esm/lib/components/LiveCollaborators.mjs +0 -135
- package/dist-esm/lib/components/LiveCollaborators.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +0 -214
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs +0 -18
- package/dist-esm/lib/components/default-components/DefaultBrush.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs +0 -41
- package/dist-esm/lib/components/default-components/DefaultCollaboratorHint.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs +0 -29
- package/dist-esm/lib/components/default-components/DefaultCursor.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultHandle.mjs +0 -26
- package/dist-esm/lib/components/default-components/DefaultHandle.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs +0 -8
- package/dist-esm/lib/components/default-components/DefaultHandles.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs +0 -21
- package/dist-esm/lib/components/default-components/DefaultScribble.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultSelectionForeground.mjs +0 -39
- package/dist-esm/lib/components/default-components/DefaultSelectionForeground.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +0 -77
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeIndicatorErrorFallback.mjs +0 -8
- package/dist-esm/lib/components/default-components/DefaultShapeIndicatorErrorFallback.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +0 -82
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +0 -7
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs +0 -142
- package/dist-esm/lib/components/default-components/DefaultSnapIndictor.mjs.map +0 -7
- package/dist-esm/lib/hooks/useHandleEvents.mjs +0 -70
- package/dist-esm/lib/hooks/useHandleEvents.mjs.map +0 -7
- package/dist-esm/lib/hooks/useSelectionEvents.mjs +0 -78
- package/dist-esm/lib/hooks/useSelectionEvents.mjs.map +0 -7
- package/src/lib/components/GeometryDebuggingView.tsx +0 -108
- package/src/lib/components/LiveCollaborators.tsx +0 -180
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +0 -300
- package/src/lib/components/default-components/DefaultBrush.tsx +0 -35
- package/src/lib/components/default-components/DefaultCollaboratorHint.tsx +0 -52
- package/src/lib/components/default-components/DefaultCursor.tsx +0 -59
- package/src/lib/components/default-components/DefaultHandle.tsx +0 -42
- package/src/lib/components/default-components/DefaultHandles.tsx +0 -15
- package/src/lib/components/default-components/DefaultScribble.tsx +0 -31
- package/src/lib/components/default-components/DefaultSelectionForeground.tsx +0 -50
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +0 -104
- package/src/lib/components/default-components/DefaultShapeIndicatorErrorFallback.tsx +0 -9
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +0 -118
- package/src/lib/components/default-components/DefaultSnapIndictor.tsx +0 -174
- package/src/lib/hooks/useHandleEvents.ts +0 -88
- package/src/lib/hooks/useSelectionEvents.ts +0 -97
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { computed } from '@tldraw/state'
|
|
2
|
+
import { createComputedCache } from '@tldraw/store'
|
|
3
|
+
import { TLShape, TLShapeId } from '@tldraw/tlschema'
|
|
4
|
+
import type { Editor } from '../Editor'
|
|
5
|
+
import { OverlayUtil, TLOverlay } from './OverlayUtil'
|
|
6
|
+
|
|
7
|
+
interface RelevantInstanceFlags {
|
|
8
|
+
isChangingStyle: boolean
|
|
9
|
+
isHoveringCanvas: boolean | null
|
|
10
|
+
isCoarsePointer: boolean
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/** @public */
|
|
14
|
+
export interface TLShapeIndicatorOverlay extends TLOverlay {
|
|
15
|
+
props: {
|
|
16
|
+
idsToDisplay: TLShapeId[]
|
|
17
|
+
hintingShapeIds: TLShapeId[]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const indicatorPathCache = createComputedCache(
|
|
22
|
+
'shapeIndicatorPath',
|
|
23
|
+
(editor: Editor, shape: TLShape) => {
|
|
24
|
+
const util = editor.getShapeUtil(shape)
|
|
25
|
+
return util.getIndicatorPath(shape)
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
areRecordsEqual(a, b) {
|
|
29
|
+
return a.props === b.props
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Combine every batchable shape indicator into a single page-space `Path2D` and
|
|
36
|
+
* emit one stroke call. Shapes whose indicator needs an evenodd clip (e.g.
|
|
37
|
+
* arrows with labels or complex arrowheads) can't be batched — they still
|
|
38
|
+
* stroke individually inside a save/restore with `ctx.clip` applied.
|
|
39
|
+
*
|
|
40
|
+
* Shared by {@link ShapeIndicatorOverlayUtil} and any overlay util that paints
|
|
41
|
+
* shape indicators (e.g. collaborator selections).
|
|
42
|
+
*
|
|
43
|
+
* @public
|
|
44
|
+
*/
|
|
45
|
+
export function strokeShapeIndicators(
|
|
46
|
+
editor: Editor,
|
|
47
|
+
ctx: CanvasRenderingContext2D,
|
|
48
|
+
shapeIds: TLShapeId[]
|
|
49
|
+
): void {
|
|
50
|
+
if (shapeIds.length === 0) return
|
|
51
|
+
|
|
52
|
+
const batched = new Path2D()
|
|
53
|
+
|
|
54
|
+
for (const shapeId of shapeIds) {
|
|
55
|
+
const shape = editor.getShape(shapeId)
|
|
56
|
+
if (!shape || shape.isLocked) continue
|
|
57
|
+
|
|
58
|
+
const pageTransform = editor.getShapePageTransform(shape)
|
|
59
|
+
if (!pageTransform) continue
|
|
60
|
+
|
|
61
|
+
const indicatorPath = indicatorPathCache.get(editor, shape.id)
|
|
62
|
+
if (!indicatorPath) continue
|
|
63
|
+
|
|
64
|
+
if (indicatorPath instanceof Path2D) {
|
|
65
|
+
batched.addPath(indicatorPath, pageTransform)
|
|
66
|
+
continue
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const { path, clipPath, additionalPaths } = indicatorPath
|
|
70
|
+
|
|
71
|
+
if (!clipPath) {
|
|
72
|
+
batched.addPath(path, pageTransform)
|
|
73
|
+
if (additionalPaths) {
|
|
74
|
+
for (const p of additionalPaths) batched.addPath(p, pageTransform)
|
|
75
|
+
}
|
|
76
|
+
continue
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Clipped case: fall back to an individual stroke. Rare (arrows with
|
|
80
|
+
// labels / complex arrowheads), so the extra save/restore/stroke
|
|
81
|
+
// pair per such shape isn't worth batching away.
|
|
82
|
+
ctx.save()
|
|
83
|
+
ctx.transform(
|
|
84
|
+
pageTransform.a,
|
|
85
|
+
pageTransform.b,
|
|
86
|
+
pageTransform.c,
|
|
87
|
+
pageTransform.d,
|
|
88
|
+
pageTransform.e,
|
|
89
|
+
pageTransform.f
|
|
90
|
+
)
|
|
91
|
+
ctx.save()
|
|
92
|
+
ctx.clip(clipPath, 'evenodd')
|
|
93
|
+
ctx.stroke(path)
|
|
94
|
+
ctx.restore()
|
|
95
|
+
if (additionalPaths) {
|
|
96
|
+
for (const p of additionalPaths) ctx.stroke(p)
|
|
97
|
+
}
|
|
98
|
+
ctx.restore()
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
ctx.stroke(batched)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Overlay util for shape indicators — the selection / hover / hint outlines drawn
|
|
106
|
+
* under the selection foreground. Paints local indicators in the theme's
|
|
107
|
+
* selection color.
|
|
108
|
+
*
|
|
109
|
+
* Remote collaborator selection indicators are drawn by a separate overlay util
|
|
110
|
+
* (e.g. `CollaboratorShapeIndicatorOverlayUtil` from `tldraw`) that runs at a
|
|
111
|
+
* lower z-index so peer selections appear under the local indicators.
|
|
112
|
+
*
|
|
113
|
+
* Non-interactive: contributes no hit-test geometry.
|
|
114
|
+
*
|
|
115
|
+
* @public
|
|
116
|
+
*/
|
|
117
|
+
export class ShapeIndicatorOverlayUtil extends OverlayUtil<TLShapeIndicatorOverlay> {
|
|
118
|
+
static override type = 'shape_indicator'
|
|
119
|
+
override options = { zIndex: 50, lineWidth: 1.5, hintedLineWidth: 2.5 }
|
|
120
|
+
|
|
121
|
+
// Narrow projection of instance state. Reading the full record would
|
|
122
|
+
// re-fire getOverlays on every cursor move / brush update; gating on these
|
|
123
|
+
// three booleans means we only re-fire when one of them actually flips.
|
|
124
|
+
private _instanceFlags$ = computed<RelevantInstanceFlags>(
|
|
125
|
+
'shape indicator instance flags',
|
|
126
|
+
() => {
|
|
127
|
+
const i = this.editor.getInstanceState()
|
|
128
|
+
return {
|
|
129
|
+
isChangingStyle: i.isChangingStyle,
|
|
130
|
+
isHoveringCanvas: i.isHoveringCanvas,
|
|
131
|
+
isCoarsePointer: i.isCoarsePointer,
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
isEqual: (a, b) =>
|
|
136
|
+
a.isChangingStyle === b.isChangingStyle &&
|
|
137
|
+
a.isHoveringCanvas === b.isHoveringCanvas &&
|
|
138
|
+
a.isCoarsePointer === b.isCoarsePointer,
|
|
139
|
+
}
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
override isActive(): boolean {
|
|
143
|
+
return true
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
override getOverlays(): TLShapeIndicatorOverlay[] {
|
|
147
|
+
const editor = this.editor
|
|
148
|
+
const renderingShapeIds = new Set(editor.getRenderingShapes().map((s) => s.id))
|
|
149
|
+
|
|
150
|
+
// Local selected / hovered indicators.
|
|
151
|
+
const idsToDisplay: TLShapeId[] = []
|
|
152
|
+
const { isChangingStyle, isHoveringCanvas, isCoarsePointer } = this._instanceFlags$.get()
|
|
153
|
+
const isIdleOrEditing = editor.isInAny('select.idle', 'select.editing_shape')
|
|
154
|
+
const isInSelectState = editor.isInAny(
|
|
155
|
+
'select.brushing',
|
|
156
|
+
'select.scribble_brushing',
|
|
157
|
+
'select.pointing_shape',
|
|
158
|
+
'select.pointing_selection',
|
|
159
|
+
'select.pointing_handle'
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if (!isChangingStyle && (isIdleOrEditing || isInSelectState)) {
|
|
163
|
+
for (const id of editor.getSelectedShapeIds()) {
|
|
164
|
+
if (renderingShapeIds.has(id)) idsToDisplay.push(id)
|
|
165
|
+
}
|
|
166
|
+
if (isIdleOrEditing && isHoveringCanvas && !isCoarsePointer) {
|
|
167
|
+
const hovered = editor.getHoveredShapeId()
|
|
168
|
+
if (hovered && renderingShapeIds.has(hovered) && !idsToDisplay.includes(hovered)) {
|
|
169
|
+
idsToDisplay.push(hovered)
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Hinted shapes (drawn thicker). Already deduped at write time in
|
|
175
|
+
// `updateHintingShapeIds`, so no need to dedupe again here.
|
|
176
|
+
const hintingShapeIds: TLShapeId[] = []
|
|
177
|
+
for (const id of editor.getHintingShapeIds()) {
|
|
178
|
+
if (renderingShapeIds.has(id)) hintingShapeIds.push(id)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (idsToDisplay.length === 0 && hintingShapeIds.length === 0) {
|
|
182
|
+
return []
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return [
|
|
186
|
+
{
|
|
187
|
+
id: 'shape_indicator',
|
|
188
|
+
type: 'shape_indicator',
|
|
189
|
+
props: { idsToDisplay, hintingShapeIds },
|
|
190
|
+
},
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
override render(ctx: CanvasRenderingContext2D, overlays: TLShapeIndicatorOverlay[]): void {
|
|
195
|
+
const overlay = overlays[0]
|
|
196
|
+
if (!overlay) return
|
|
197
|
+
|
|
198
|
+
const editor = this.editor
|
|
199
|
+
const zoom = editor.getZoomLevel()
|
|
200
|
+
const { idsToDisplay, hintingShapeIds } = overlay.props
|
|
201
|
+
|
|
202
|
+
ctx.lineCap = 'round'
|
|
203
|
+
ctx.lineJoin = 'round'
|
|
204
|
+
|
|
205
|
+
// Local selected / hovered indicators — one stroke call for the whole batch.
|
|
206
|
+
ctx.strokeStyle = editor.getCurrentTheme().colors[editor.getColorMode()].selectionStroke
|
|
207
|
+
ctx.lineWidth = this.options.lineWidth / zoom
|
|
208
|
+
strokeShapeIndicators(editor, ctx, idsToDisplay)
|
|
209
|
+
|
|
210
|
+
// Hinted shapes — thicker stroke, one call for the whole batch.
|
|
211
|
+
if (hintingShapeIds.length > 0) {
|
|
212
|
+
ctx.lineWidth = this.options.hintedLineWidth / zoom
|
|
213
|
+
strokeShapeIndicators(editor, ctx, hintingShapeIds)
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { TLTheme } from '@tldraw/tlschema'
|
|
2
|
+
import type { Editor } from '../Editor'
|
|
3
|
+
import { TLOverlay } from './OverlayUtil'
|
|
4
|
+
|
|
5
|
+
/** @public */
|
|
6
|
+
export interface OverlayOptionsWithDisplayValues<
|
|
7
|
+
Overlay extends TLOverlay,
|
|
8
|
+
DisplayValues extends object,
|
|
9
|
+
> {
|
|
10
|
+
getDefaultDisplayValues(
|
|
11
|
+
editor: Editor,
|
|
12
|
+
overlay: Overlay,
|
|
13
|
+
theme: TLTheme,
|
|
14
|
+
colorMode: 'light' | 'dark'
|
|
15
|
+
): DisplayValues
|
|
16
|
+
getCustomDisplayValues(
|
|
17
|
+
editor: Editor,
|
|
18
|
+
overlay: Overlay,
|
|
19
|
+
theme: TLTheme,
|
|
20
|
+
colorMode: 'light' | 'dark'
|
|
21
|
+
): Partial<DisplayValues>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const dvCache = new WeakMap<
|
|
25
|
+
TLOverlay,
|
|
26
|
+
{ theme: TLTheme; colorMode: 'light' | 'dark'; values: object }
|
|
27
|
+
>()
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Get the resolved display values for an overlay, merging the base values with any overrides.
|
|
31
|
+
*
|
|
32
|
+
* @public
|
|
33
|
+
*/
|
|
34
|
+
export function getOverlayDisplayValues<Overlay extends TLOverlay, DisplayValues extends object>(
|
|
35
|
+
util: { editor: Editor; options: OverlayOptionsWithDisplayValues<Overlay, DisplayValues> },
|
|
36
|
+
overlay: Overlay,
|
|
37
|
+
colorMode?: 'light' | 'dark'
|
|
38
|
+
): DisplayValues {
|
|
39
|
+
const theme = util.editor.getCurrentTheme()
|
|
40
|
+
const resolvedColorMode = colorMode ?? util.editor.getColorMode()
|
|
41
|
+
const cached = dvCache.get(overlay)
|
|
42
|
+
if (cached && cached.theme === theme && cached.colorMode === resolvedColorMode) {
|
|
43
|
+
return cached.values as DisplayValues
|
|
44
|
+
}
|
|
45
|
+
const values = {
|
|
46
|
+
...util.options.getDefaultDisplayValues(util.editor, overlay, theme, resolvedColorMode),
|
|
47
|
+
...util.options.getCustomDisplayValues(util.editor, overlay, theme, resolvedColorMode),
|
|
48
|
+
}
|
|
49
|
+
dvCache.set(overlay, { theme, colorMode: resolvedColorMode, values })
|
|
50
|
+
return values
|
|
51
|
+
}
|
|
@@ -15,6 +15,7 @@ import { TLDragShapesInInfo, TLDragShapesOutInfo } from './ShapeUtil'
|
|
|
15
15
|
* - `isFrameLike()` returns `true`
|
|
16
16
|
* - `providesBackgroundForChildren()` returns `true`
|
|
17
17
|
* - `canReceiveNewChildrenOfType()` returns `true` unless the container is locked
|
|
18
|
+
* - `canRemoveChildrenOfType()` returns `true` unless the container is locked
|
|
18
19
|
* - `getClipPath()` returns the shape geometry's vertices
|
|
19
20
|
* - `onDragShapesIn()` reparents shapes into the frame (with index restoration)
|
|
20
21
|
* - `onDragShapesOut()` reparents shapes back to the page
|
|
@@ -35,8 +36,10 @@ import { TLDragShapesInInfo, TLDragShapesOutInfo } from './ShapeUtil'
|
|
|
35
36
|
* return <SVGContainer>...</SVGContainer>
|
|
36
37
|
* }
|
|
37
38
|
*
|
|
38
|
-
* override
|
|
39
|
-
*
|
|
39
|
+
* override getIndicatorPath(shape: MyContainerShape) {
|
|
40
|
+
* const path = new Path2D()
|
|
41
|
+
* path.rect(0, 0, shape.props.w, shape.props.h)
|
|
42
|
+
* return path
|
|
40
43
|
* }
|
|
41
44
|
* }
|
|
42
45
|
* ```
|
|
@@ -58,6 +61,10 @@ export abstract class BaseFrameLikeShapeUtil<
|
|
|
58
61
|
return !shape.isLocked
|
|
59
62
|
}
|
|
60
63
|
|
|
64
|
+
override canRemoveChildrenOfType(shape: Shape, _type: TLShape['type']): boolean {
|
|
65
|
+
return !shape.isLocked
|
|
66
|
+
}
|
|
67
|
+
|
|
61
68
|
override getClipPath(shape: Shape): Vec[] | undefined {
|
|
62
69
|
return this.editor.getShapeGeometry(shape.id).vertices
|
|
63
70
|
}
|
|
@@ -218,42 +218,32 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
218
218
|
abstract component(shape: Shape): any
|
|
219
219
|
|
|
220
220
|
/**
|
|
221
|
-
* Get
|
|
222
|
-
*
|
|
223
|
-
*
|
|
224
|
-
* @public
|
|
225
|
-
*/
|
|
226
|
-
abstract indicator(shape: Shape): any
|
|
227
|
-
|
|
228
|
-
/**
|
|
229
|
-
* Whether to use the legacy React-based indicator rendering.
|
|
221
|
+
* Get a Path2D (or a richer object with clip/additional paths) for rendering the
|
|
222
|
+
* shape's indicator on the canvas. Shapes that return `undefined` will not render
|
|
223
|
+
* an indicator.
|
|
230
224
|
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
225
|
+
* For complex indicators that need clipping (e.g., arrows with labels), return an
|
|
226
|
+
* object with `path`, `clipPath`, and `additionalPaths` properties.
|
|
233
227
|
*
|
|
234
|
-
* @
|
|
228
|
+
* @param shape - The shape.
|
|
229
|
+
* @returns A Path2D to stroke, or an object with clipping info, or undefined to skip.
|
|
235
230
|
* @public
|
|
236
231
|
*/
|
|
237
|
-
|
|
238
|
-
return true
|
|
239
|
-
}
|
|
232
|
+
abstract getIndicatorPath(shape: Shape): TLIndicatorPath | undefined
|
|
240
233
|
|
|
241
234
|
/**
|
|
242
|
-
* Get
|
|
243
|
-
*
|
|
244
|
-
* When implemented, this is used instead of {@link ShapeUtil.indicator} for more
|
|
245
|
-
* efficient canvas-based indicator rendering. Shapes that return `undefined` will
|
|
246
|
-
* fall back to SVG-based rendering via {@link ShapeUtil.indicator}.
|
|
235
|
+
* Get JSX describing the shape's indicator (as an SVG element).
|
|
247
236
|
*
|
|
248
|
-
*
|
|
249
|
-
*
|
|
237
|
+
* @deprecated SVG indicators are no longer rendered. Override
|
|
238
|
+
* {@link ShapeUtil.getIndicatorPath} instead. This stub is retained so legacy
|
|
239
|
+
* subclasses that still call `super.indicator()` keep type-checking; new shapes
|
|
240
|
+
* should not implement it.
|
|
250
241
|
*
|
|
251
242
|
* @param shape - The shape.
|
|
252
|
-
* @returns A Path2D to stroke, or an object with clipping info, or undefined to use SVG fallback.
|
|
253
243
|
* @public
|
|
254
244
|
*/
|
|
255
|
-
|
|
256
|
-
return
|
|
245
|
+
indicator(_shape: Shape): any {
|
|
246
|
+
return null
|
|
257
247
|
}
|
|
258
248
|
|
|
259
249
|
/**
|
|
@@ -556,7 +546,9 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
556
546
|
getHandles?(shape: Shape): TLHandle[]
|
|
557
547
|
|
|
558
548
|
/**
|
|
559
|
-
* Get whether the shape can receive children of a given type.
|
|
549
|
+
* Get whether the shape can receive children of a given type. Used by the drag and drop system
|
|
550
|
+
* to decide whether {@link ShapeUtil.onDragShapesIn} should fire when a shape of the given type
|
|
551
|
+
* is dragged over this one.
|
|
560
552
|
*
|
|
561
553
|
* @param shape - The shape.
|
|
562
554
|
* @param type - The shape type.
|
|
@@ -566,6 +558,22 @@ export abstract class ShapeUtil<Shape extends TLShape = TLShape> {
|
|
|
566
558
|
return false
|
|
567
559
|
}
|
|
568
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Get whether children of a given type can be removed from this shape. Used by the drag and
|
|
563
|
+
* drop system to decide whether {@link ShapeUtil.onDragShapesOut} should fire when a child of
|
|
564
|
+
* the given type is dragged out of this shape, and by `kickoutOccludedShapes` to decide
|
|
565
|
+
* whether to auto-reparent a child of the given type when it has moved outside this shape's
|
|
566
|
+
* geometry. Returning `false` therefore "pins" matching children — they stay parented to this
|
|
567
|
+
* shape even when dragged or moved outside it. Defaults to `true`.
|
|
568
|
+
*
|
|
569
|
+
* @param shape - The shape.
|
|
570
|
+
* @param type - The shape type.
|
|
571
|
+
* @public
|
|
572
|
+
*/
|
|
573
|
+
canRemoveChildrenOfType(shape: Shape, type: TLShape['type']) {
|
|
574
|
+
return true
|
|
575
|
+
}
|
|
576
|
+
|
|
569
577
|
/**
|
|
570
578
|
* Get the shape as an SVG object.
|
|
571
579
|
*
|
|
@@ -4,6 +4,7 @@ import { Geometry2d } from '../../../primitives/geometry/Geometry2d'
|
|
|
4
4
|
import { Group2d } from '../../../primitives/geometry/Group2d'
|
|
5
5
|
import { Rectangle2d } from '../../../primitives/geometry/Rectangle2d'
|
|
6
6
|
import { ShapeUtil } from '../ShapeUtil'
|
|
7
|
+
import { getPerfectDashProps } from '../shared/getPerfectDashProps'
|
|
7
8
|
import { DashedOutlineBox } from './DashedOutlineBox'
|
|
8
9
|
|
|
9
10
|
/** @public */
|
|
@@ -78,10 +79,46 @@ export class GroupShapeUtil extends ShapeUtil<TLGroupShape> {
|
|
|
78
79
|
)
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
|
|
82
|
-
// Not a class component, but eslint can't tell that :(
|
|
82
|
+
override getIndicatorPath(shape: TLGroupShape): Path2D {
|
|
83
83
|
const bounds = this.editor.getShapeGeometry(shape).bounds
|
|
84
|
-
|
|
84
|
+
const zoomLevel = this.editor.getEfficientZoomLevel()
|
|
85
|
+
const path = new Path2D()
|
|
86
|
+
|
|
87
|
+
for (const side of bounds.sides) {
|
|
88
|
+
const [start, end] = side
|
|
89
|
+
const length = start.dist(end)
|
|
90
|
+
if (length <= 0) continue
|
|
91
|
+
|
|
92
|
+
const { strokeDasharray, strokeDashoffset } = getPerfectDashProps(length, 1 / zoomLevel, {
|
|
93
|
+
style: 'dashed',
|
|
94
|
+
lengthRatio: 4,
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (strokeDasharray === 'none') {
|
|
98
|
+
path.moveTo(start.x, start.y)
|
|
99
|
+
path.lineTo(end.x, end.y)
|
|
100
|
+
continue
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
const [dashLength, gapLength] = strokeDasharray.split(' ').map(Number)
|
|
104
|
+
const dashOffset = Number(strokeDashoffset)
|
|
105
|
+
const period = dashLength + gapLength
|
|
106
|
+
if (!Number.isFinite(period) || period <= 0) continue
|
|
107
|
+
|
|
108
|
+
const dx = (end.x - start.x) / length
|
|
109
|
+
const dy = (end.y - start.y) / length
|
|
110
|
+
|
|
111
|
+
for (let dashStart = -dashOffset; dashStart < length; dashStart += period) {
|
|
112
|
+
const dashEnd = Math.min(length, dashStart + dashLength)
|
|
113
|
+
const clippedDashStart = Math.max(0, dashStart)
|
|
114
|
+
if (dashEnd <= clippedDashStart) continue
|
|
115
|
+
|
|
116
|
+
path.moveTo(start.x + dx * clippedDashStart, start.y + dy * clippedDashStart)
|
|
117
|
+
path.lineTo(start.x + dx * dashEnd, start.y + dy * dashEnd)
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return path
|
|
85
122
|
}
|
|
86
123
|
|
|
87
124
|
override onChildrenChange(group: TLGroupShape) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { TLHandle, TLShape, VecModel } from '@tldraw/tlschema'
|
|
2
2
|
import { VecLike } from '../../primitives/Vec'
|
|
3
|
+
import { TLOverlay } from '../overlays/OverlayUtil'
|
|
3
4
|
import { TLSelectionHandle } from './selection-types'
|
|
4
5
|
|
|
5
6
|
/** @public */
|
|
@@ -11,6 +12,7 @@ export type TLPointerEventTarget =
|
|
|
11
12
|
| { target: 'selection'; handle?: TLSelectionHandle; shape?: undefined }
|
|
12
13
|
| { target: 'shape'; shape: TLShape }
|
|
13
14
|
| { target: 'handle'; shape: TLShape; handle: TLHandle }
|
|
15
|
+
| { target: 'overlay'; overlay: TLOverlay; shape?: undefined }
|
|
14
16
|
|
|
15
17
|
/** @public */
|
|
16
18
|
export type TLPointerEventName =
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
import { FileHelpers, assert, fetch } from '@tldraw/utils'
|
|
1
|
+
import { FileHelpers, LruCache, assert, fetch } from '@tldraw/utils'
|
|
2
2
|
|
|
3
|
-
// TODO(alex): currently, this cache will grow unbounded. we should come up with a better strategy
|
|
4
|
-
// for clearing items from the cache over time.
|
|
5
3
|
export function fetchCache<T>(cb: (response: Response) => Promise<T>, init?: RequestInit) {
|
|
6
|
-
const cache = new
|
|
4
|
+
const cache = new LruCache<string, Promise<T | null>>(100)
|
|
7
5
|
|
|
8
6
|
return async function fetchCached(url: string): Promise<T | null> {
|
|
9
7
|
const existing = cache.get(url)
|
|
@@ -1,54 +1,27 @@
|
|
|
1
1
|
import { ComponentType, RefAttributes, createContext, useContext } from 'react'
|
|
2
|
-
import type { TLBrushProps } from '../components/default-components/DefaultBrush'
|
|
3
2
|
import type { TLCanvasComponentProps } from '../components/default-components/DefaultCanvas'
|
|
4
|
-
import type { TLCollaboratorHintProps } from '../components/default-components/DefaultCollaboratorHint'
|
|
5
|
-
import type { TLCursorProps } from '../components/default-components/DefaultCursor'
|
|
6
3
|
import type { TLErrorFallbackComponent } from '../components/default-components/DefaultErrorFallback'
|
|
7
4
|
import type { TLGridProps } from '../components/default-components/DefaultGrid'
|
|
8
|
-
import type { TLHandleProps } from '../components/default-components/DefaultHandle'
|
|
9
|
-
import type { TLHandlesProps } from '../components/default-components/DefaultHandles'
|
|
10
|
-
import type { TLScribbleProps } from '../components/default-components/DefaultScribble'
|
|
11
5
|
import type { TLSelectionBackgroundProps } from '../components/default-components/DefaultSelectionBackground'
|
|
12
|
-
import type { TLSelectionForegroundProps } from '../components/default-components/DefaultSelectionForeground'
|
|
13
6
|
import type { TLShapeErrorFallbackComponent } from '../components/default-components/DefaultShapeErrorFallback'
|
|
14
|
-
import type { TLShapeIndicatorProps } from '../components/default-components/DefaultShapeIndicator'
|
|
15
|
-
import type { TLShapeIndicatorErrorFallbackComponent } from '../components/default-components/DefaultShapeIndicatorErrorFallback'
|
|
16
7
|
import type { TLShapeWrapperProps } from '../components/default-components/DefaultShapeWrapper'
|
|
17
|
-
import type { TLSnapIndicatorProps } from '../components/default-components/DefaultSnapIndictor'
|
|
18
8
|
|
|
19
9
|
/** @public */
|
|
20
10
|
export interface TLEditorComponents {
|
|
21
11
|
Background?: ComponentType | null
|
|
22
|
-
Brush?: ComponentType<TLBrushProps> | null
|
|
23
12
|
Canvas?: ComponentType<TLCanvasComponentProps> | null
|
|
24
|
-
CollaboratorBrush?: ComponentType<TLBrushProps> | null
|
|
25
|
-
CollaboratorCursor?: ComponentType<TLCursorProps> | null
|
|
26
|
-
CollaboratorHint?: ComponentType<TLCollaboratorHintProps> | null
|
|
27
|
-
CollaboratorScribble?: ComponentType<TLScribbleProps> | null
|
|
28
|
-
CollaboratorShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null
|
|
29
|
-
Cursor?: ComponentType<TLCursorProps> | null
|
|
30
13
|
Grid?: ComponentType<TLGridProps> | null
|
|
31
|
-
Handle?: ComponentType<TLHandleProps> | null
|
|
32
|
-
Handles?: ComponentType<TLHandlesProps> | null
|
|
33
14
|
InFrontOfTheCanvas?: ComponentType | null
|
|
34
15
|
LoadingScreen?: ComponentType | null
|
|
35
16
|
OnTheCanvas?: ComponentType | null
|
|
36
|
-
Overlays?: ComponentType | null
|
|
37
|
-
Scribble?: ComponentType<TLScribbleProps> | null
|
|
38
17
|
SelectionBackground?: ComponentType<TLSelectionBackgroundProps> | null
|
|
39
|
-
SelectionForeground?: ComponentType<TLSelectionForegroundProps> | null
|
|
40
|
-
ShapeIndicator?: ComponentType<TLShapeIndicatorProps> | null
|
|
41
|
-
ShapeIndicators?: ComponentType | null
|
|
42
18
|
ShapeWrapper?: ComponentType<TLShapeWrapperProps & RefAttributes<HTMLDivElement>> | null
|
|
43
|
-
SnapIndicator?: ComponentType<TLSnapIndicatorProps> | null
|
|
44
19
|
Spinner?: ComponentType<React.SVGProps<SVGSVGElement>> | null
|
|
45
20
|
SvgDefs?: ComponentType | null
|
|
46
|
-
ZoomBrush?: ComponentType<TLBrushProps> | null
|
|
47
21
|
|
|
48
22
|
// These will always have defaults
|
|
49
23
|
ErrorFallback?: TLErrorFallbackComponent
|
|
50
24
|
ShapeErrorFallback?: TLShapeErrorFallbackComponent
|
|
51
|
-
ShapeIndicatorErrorFallback?: TLShapeIndicatorErrorFallbackComponent
|
|
52
25
|
}
|
|
53
26
|
|
|
54
27
|
export const EditorComponentsContext = createContext<null | Required<TLEditorComponents>>(null)
|
|
@@ -169,14 +169,19 @@ export function useCanvasEvents() {
|
|
|
169
169
|
// menu opens on press.
|
|
170
170
|
if (!editor.options.rightClickPanning) return
|
|
171
171
|
// Synthetic events — our own dispatch from onPointerUp, or tests using
|
|
172
|
-
// fireEvent.contextMenu — pass through so Radix can open the menu.
|
|
173
|
-
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
172
|
+
// fireEvent.contextMenu — pass through so Radix can open the menu.
|
|
173
|
+
if (!e.nativeEvent.isTrusted) return
|
|
174
|
+
// Only suppress the native browser contextmenu when it follows a real
|
|
175
|
+
// right-click (button=2 with no ctrl modifier). For those, our pointer
|
|
176
|
+
// handling has already decided what to do (either we'll dispatch a
|
|
177
|
+
// synthetic contextmenu on pointerup to open the menu at the release
|
|
178
|
+
// position, or we panned and don't want a menu at all).
|
|
179
|
+
//
|
|
180
|
+
// Other contextmenu sources must reach Radix so the menu opens:
|
|
181
|
+
// - ctrl+click on macOS (button=0, or button=2 with ctrlKey=true)
|
|
182
|
+
// - long-press on touch devices (button=0, pointerType=touch)
|
|
183
|
+
if (e.button !== 2 || e.ctrlKey) return
|
|
184
|
+
preventDefault(e)
|
|
180
185
|
}
|
|
181
186
|
|
|
182
187
|
return {
|
|
@@ -1,22 +1,11 @@
|
|
|
1
1
|
import { ReactNode, useMemo } from 'react'
|
|
2
2
|
import { DefaultBackground } from '../components/default-components/DefaultBackground'
|
|
3
|
-
import { DefaultBrush } from '../components/default-components/DefaultBrush'
|
|
4
3
|
import { DefaultCanvas } from '../components/default-components/DefaultCanvas'
|
|
5
|
-
import { DefaultCollaboratorHint } from '../components/default-components/DefaultCollaboratorHint'
|
|
6
|
-
import { DefaultCursor } from '../components/default-components/DefaultCursor'
|
|
7
4
|
import { DefaultErrorFallback } from '../components/default-components/DefaultErrorFallback'
|
|
8
5
|
import { DefaultGrid } from '../components/default-components/DefaultGrid'
|
|
9
|
-
import { DefaultHandle } from '../components/default-components/DefaultHandle'
|
|
10
|
-
import { DefaultHandles } from '../components/default-components/DefaultHandles'
|
|
11
6
|
import { DefaultLoadingScreen } from '../components/default-components/DefaultLoadingScreen'
|
|
12
|
-
import { DefaultScribble } from '../components/default-components/DefaultScribble'
|
|
13
|
-
import { DefaultSelectionForeground } from '../components/default-components/DefaultSelectionForeground'
|
|
14
7
|
import { DefaultShapeErrorFallback } from '../components/default-components/DefaultShapeErrorFallback'
|
|
15
|
-
import { DefaultShapeIndicator } from '../components/default-components/DefaultShapeIndicator'
|
|
16
|
-
import { DefaultShapeIndicatorErrorFallback } from '../components/default-components/DefaultShapeIndicatorErrorFallback'
|
|
17
|
-
import { DefaultShapeIndicators } from '../components/default-components/DefaultShapeIndicators'
|
|
18
8
|
import { DefaultShapeWrapper } from '../components/default-components/DefaultShapeWrapper'
|
|
19
|
-
import { DefaultSnapIndicator } from '../components/default-components/DefaultSnapIndictor'
|
|
20
9
|
import { DefaultSpinner } from '../components/default-components/DefaultSpinner'
|
|
21
10
|
import { DefaultSvgDefs } from '../components/default-components/DefaultSvgDefs'
|
|
22
11
|
import { EditorComponentsContext } from './EditorComponentsContext'
|
|
@@ -39,35 +28,18 @@ export function EditorComponentsProvider({
|
|
|
39
28
|
const value = useMemo(
|
|
40
29
|
(): Required<TLEditorComponents> => ({
|
|
41
30
|
Background: DefaultBackground,
|
|
42
|
-
Brush: DefaultBrush,
|
|
43
31
|
Canvas: DefaultCanvas,
|
|
44
|
-
CollaboratorBrush: DefaultBrush,
|
|
45
|
-
CollaboratorCursor: DefaultCursor,
|
|
46
|
-
CollaboratorHint: DefaultCollaboratorHint,
|
|
47
|
-
CollaboratorScribble: DefaultScribble,
|
|
48
|
-
CollaboratorShapeIndicator: DefaultShapeIndicator,
|
|
49
|
-
Cursor: DefaultCursor,
|
|
50
32
|
Grid: DefaultGrid,
|
|
51
|
-
Handle: DefaultHandle,
|
|
52
|
-
Handles: DefaultHandles,
|
|
53
33
|
InFrontOfTheCanvas: null,
|
|
54
34
|
LoadingScreen: DefaultLoadingScreen,
|
|
55
35
|
OnTheCanvas: null,
|
|
56
|
-
Overlays: null,
|
|
57
|
-
Scribble: DefaultScribble,
|
|
58
36
|
SelectionBackground: null,
|
|
59
|
-
SelectionForeground: DefaultSelectionForeground,
|
|
60
|
-
ShapeIndicator: DefaultShapeIndicator,
|
|
61
|
-
ShapeIndicators: DefaultShapeIndicators,
|
|
62
37
|
ShapeWrapper: DefaultShapeWrapper,
|
|
63
|
-
SnapIndicator: DefaultSnapIndicator,
|
|
64
38
|
Spinner: DefaultSpinner,
|
|
65
39
|
SvgDefs: DefaultSvgDefs,
|
|
66
|
-
ZoomBrush: DefaultBrush,
|
|
67
40
|
|
|
68
41
|
ErrorFallback: DefaultErrorFallback,
|
|
69
42
|
ShapeErrorFallback: DefaultShapeErrorFallback,
|
|
70
|
-
ShapeIndicatorErrorFallback: DefaultShapeIndicatorErrorFallback,
|
|
71
43
|
|
|
72
44
|
..._overrides,
|
|
73
45
|
}),
|