@tldraw/editor 4.4.0-next.84d68f44c848 → 4.4.0-next.bde73a32273d
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 +277 -30
- package/dist-cjs/index.js +1 -6
- package/dist-cjs/index.js.map +3 -3
- package/dist-cjs/lib/TldrawEditor.js +20 -8
- package/dist-cjs/lib/TldrawEditor.js.map +2 -2
- package/dist-cjs/lib/components/LiveCollaborators.js +14 -24
- package/dist-cjs/lib/components/LiveCollaborators.js.map +2 -2
- package/dist-cjs/lib/components/Shape.js +12 -17
- package/dist-cjs/lib/components/Shape.js.map +2 -2
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js +226 -0
- package/dist-cjs/lib/components/default-components/CanvasShapeIndicators.js.map +7 -0
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js +45 -15
- package/dist-cjs/lib/components/default-components/DefaultCanvas.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js +3 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicator.js.map +2 -2
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js +13 -1
- package/dist-cjs/lib/components/default-components/DefaultShapeIndicators.js.map +2 -2
- package/dist-cjs/lib/config/TLUserPreferences.js +9 -3
- package/dist-cjs/lib/config/TLUserPreferences.js.map +2 -2
- package/dist-cjs/lib/config/createTLStore.js.map +1 -1
- package/dist-cjs/lib/editor/Editor.js +39 -18
- package/dist-cjs/lib/editor/Editor.js.map +2 -2
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js +32 -13
- package/dist-cjs/lib/editor/derivations/notVisibleShapes.js.map +2 -2
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js +2 -3
- package/dist-cjs/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js +13 -38
- package/dist-cjs/lib/editor/managers/HistoryManager/HistoryManager.js.map +3 -3
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js +378 -89
- package/dist-cjs/lib/editor/managers/ScribbleManager/ScribbleManager.js.map +2 -2
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js +8 -3
- package/dist-cjs/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.js.map +2 -2
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js +29 -0
- package/dist-cjs/lib/editor/shapes/ShapeUtil.js.map +2 -2
- package/dist-cjs/lib/editor/tools/RootState.js +0 -13
- package/dist-cjs/lib/editor/tools/RootState.js.map +2 -2
- package/dist-cjs/lib/hooks/usePeerIds.js +35 -0
- package/dist-cjs/lib/hooks/usePeerIds.js.map +2 -2
- package/dist-cjs/lib/hooks/useShapeCulling.js +75 -0
- package/dist-cjs/lib/hooks/useShapeCulling.js.map +7 -0
- package/dist-cjs/lib/license/LicenseManager.js +6 -6
- package/dist-cjs/lib/license/LicenseManager.js.map +2 -2
- package/dist-cjs/lib/options.js +7 -1
- package/dist-cjs/lib/options.js.map +2 -2
- package/dist-cjs/lib/utils/collaboratorState.js +42 -0
- package/dist-cjs/lib/utils/collaboratorState.js.map +7 -0
- package/dist-cjs/version.js +3 -3
- package/dist-cjs/version.js.map +1 -1
- package/dist-esm/index.d.mts +277 -30
- package/dist-esm/index.mjs +1 -6
- package/dist-esm/index.mjs.map +2 -2
- package/dist-esm/lib/TldrawEditor.mjs +20 -8
- package/dist-esm/lib/TldrawEditor.mjs.map +2 -2
- package/dist-esm/lib/components/LiveCollaborators.mjs +17 -24
- package/dist-esm/lib/components/LiveCollaborators.mjs.map +2 -2
- package/dist-esm/lib/components/Shape.mjs +12 -17
- package/dist-esm/lib/components/Shape.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs +206 -0
- package/dist-esm/lib/components/default-components/CanvasShapeIndicators.mjs.map +7 -0
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs +45 -15
- package/dist-esm/lib/components/default-components/DefaultCanvas.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs +3 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicator.mjs.map +2 -2
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs +13 -1
- package/dist-esm/lib/components/default-components/DefaultShapeIndicators.mjs.map +2 -2
- package/dist-esm/lib/config/TLUserPreferences.mjs +9 -3
- package/dist-esm/lib/config/TLUserPreferences.mjs.map +2 -2
- package/dist-esm/lib/config/createTLStore.mjs.map +1 -1
- package/dist-esm/lib/editor/Editor.mjs +39 -18
- package/dist-esm/lib/editor/Editor.mjs.map +2 -2
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs +32 -13
- package/dist-esm/lib/editor/derivations/notVisibleShapes.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs +2 -3
- package/dist-esm/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs +14 -39
- package/dist-esm/lib/editor/managers/HistoryManager/HistoryManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs +378 -89
- package/dist-esm/lib/editor/managers/ScribbleManager/ScribbleManager.mjs.map +2 -2
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs +8 -3
- package/dist-esm/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.mjs.map +2 -2
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs +29 -0
- package/dist-esm/lib/editor/shapes/ShapeUtil.mjs.map +2 -2
- package/dist-esm/lib/editor/tools/RootState.mjs +0 -13
- package/dist-esm/lib/editor/tools/RootState.mjs.map +2 -2
- package/dist-esm/lib/hooks/usePeerIds.mjs +39 -1
- package/dist-esm/lib/hooks/usePeerIds.mjs.map +2 -2
- package/dist-esm/lib/hooks/useShapeCulling.mjs +55 -0
- package/dist-esm/lib/hooks/useShapeCulling.mjs.map +7 -0
- package/dist-esm/lib/license/LicenseManager.mjs +6 -6
- package/dist-esm/lib/license/LicenseManager.mjs.map +2 -2
- package/dist-esm/lib/options.mjs +7 -1
- package/dist-esm/lib/options.mjs.map +2 -2
- package/dist-esm/lib/utils/collaboratorState.mjs +22 -0
- package/dist-esm/lib/utils/collaboratorState.mjs.map +7 -0
- package/dist-esm/version.mjs +3 -3
- package/dist-esm/version.mjs.map +1 -1
- package/editor.css +28 -11
- package/package.json +8 -11
- package/src/index.ts +2 -5
- package/src/lib/TldrawEditor.tsx +35 -13
- package/src/lib/components/LiveCollaborators.tsx +26 -37
- package/src/lib/components/Shape.tsx +15 -16
- package/src/lib/components/default-components/CanvasShapeIndicators.tsx +288 -0
- package/src/lib/components/default-components/DefaultCanvas.tsx +39 -3
- package/src/lib/components/default-components/DefaultShapeIndicator.tsx +6 -1
- package/src/lib/components/default-components/DefaultShapeIndicators.tsx +16 -1
- package/src/lib/config/TLUserPreferences.test.ts +1 -0
- package/src/lib/config/TLUserPreferences.ts +8 -0
- package/src/lib/config/createTLStore.ts +1 -1
- package/src/lib/editor/Editor.ts +72 -20
- package/src/lib/editor/derivations/notVisibleShapes.ts +39 -17
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.test.ts +0 -35
- package/src/lib/editor/managers/EdgeScrollManager/EdgeScrollManager.ts +4 -8
- package/src/lib/editor/managers/HistoryManager/HistoryManager.ts +19 -47
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.ts +491 -106
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.test.ts +24 -0
- package/src/lib/editor/managers/UserPreferencesManager/UserPreferencesManager.ts +8 -0
- package/src/lib/editor/shapes/ShapeUtil.ts +63 -5
- package/src/lib/editor/tools/RootState.ts +0 -16
- package/src/lib/hooks/usePeerIds.ts +53 -1
- package/src/lib/hooks/useShapeCulling.tsx +98 -0
- package/src/lib/license/LicenseManager.ts +6 -6
- package/src/lib/options.ts +48 -2
- package/src/lib/utils/collaboratorState.ts +54 -0
- package/src/version.ts +3 -3
- package/src/lib/editor/managers/ScribbleManager/ScribbleManager.test.ts +0 -621
|
@@ -4,13 +4,53 @@ class ScribbleManager {
|
|
|
4
4
|
constructor(editor) {
|
|
5
5
|
this.editor = editor;
|
|
6
6
|
}
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
7
|
+
sessions = /* @__PURE__ */ new Map();
|
|
8
|
+
// ==================== SESSION API ====================
|
|
9
|
+
/**
|
|
10
|
+
* Start a new session for grouping scribbles.
|
|
11
|
+
* Returns a session ID that can be used with other session methods.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Session configuration
|
|
14
|
+
* @returns Session ID
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
startSession(options = {}) {
|
|
18
|
+
const id = options.id ?? uniqueId();
|
|
19
|
+
const session = {
|
|
11
20
|
id,
|
|
21
|
+
items: [],
|
|
22
|
+
state: "active",
|
|
23
|
+
options: {
|
|
24
|
+
selfConsume: options.selfConsume ?? true,
|
|
25
|
+
idleTimeoutMs: options.idleTimeoutMs ?? 0,
|
|
26
|
+
fadeMode: options.fadeMode ?? "individual",
|
|
27
|
+
fadeEasing: options.fadeEasing ?? (options.fadeMode === "grouped" ? "ease-in" : "linear"),
|
|
28
|
+
fadeDurationMs: options.fadeDurationMs ?? this.editor.options.laserFadeoutMs
|
|
29
|
+
},
|
|
30
|
+
fadeElapsed: 0,
|
|
31
|
+
totalPointsAtFadeStart: 0
|
|
32
|
+
};
|
|
33
|
+
this.sessions.set(id, session);
|
|
34
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
35
|
+
this.resetIdleTimeout(session);
|
|
36
|
+
}
|
|
37
|
+
return id;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Add a scribble to a session.
|
|
41
|
+
*
|
|
42
|
+
* @param sessionId - The session ID
|
|
43
|
+
* @param scribble - Partial scribble properties
|
|
44
|
+
* @param scribbleId - Optional scribble ID
|
|
45
|
+
* @public
|
|
46
|
+
*/
|
|
47
|
+
addScribbleToSession(sessionId, scribble, scribbleId = uniqueId()) {
|
|
48
|
+
const session = this.sessions.get(sessionId);
|
|
49
|
+
if (!session) throw Error(`Session ${sessionId} not found`);
|
|
50
|
+
const item = {
|
|
51
|
+
id: scribbleId,
|
|
12
52
|
scribble: {
|
|
13
|
-
id,
|
|
53
|
+
id: scribbleId,
|
|
14
54
|
size: 20,
|
|
15
55
|
color: "accent",
|
|
16
56
|
opacity: 0.8,
|
|
@@ -26,43 +66,187 @@ class ScribbleManager {
|
|
|
26
66
|
prev: null,
|
|
27
67
|
next: null
|
|
28
68
|
};
|
|
29
|
-
|
|
69
|
+
session.items.push(item);
|
|
70
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
71
|
+
this.resetIdleTimeout(session);
|
|
72
|
+
}
|
|
30
73
|
return item;
|
|
31
74
|
}
|
|
32
|
-
reset() {
|
|
33
|
-
this.editor.updateInstanceState({ scribbles: [] });
|
|
34
|
-
this.scribbleItems.clear();
|
|
35
|
-
}
|
|
36
75
|
/**
|
|
37
|
-
*
|
|
76
|
+
* Add a point to a scribble in a session.
|
|
38
77
|
*
|
|
78
|
+
* @param sessionId - The session ID
|
|
79
|
+
* @param scribbleId - The scribble ID
|
|
80
|
+
* @param x - X coordinate
|
|
81
|
+
* @param y - Y coordinate
|
|
82
|
+
* @param z - Z coordinate (pressure)
|
|
39
83
|
* @public
|
|
40
84
|
*/
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
if (!
|
|
44
|
-
item
|
|
45
|
-
item
|
|
85
|
+
addPointToSession(sessionId, scribbleId, x, y, z = 0.5) {
|
|
86
|
+
const session = this.sessions.get(sessionId);
|
|
87
|
+
if (!session) throw Error(`Session ${sessionId} not found`);
|
|
88
|
+
const item = session.items.find((i) => i.id === scribbleId);
|
|
89
|
+
if (!item) throw Error(`Scribble ${scribbleId} not found in session ${sessionId}`);
|
|
90
|
+
const point = { x, y, z };
|
|
91
|
+
if (!item.prev || Vec.Dist(item.prev, point) >= 1) {
|
|
92
|
+
item.next = point;
|
|
93
|
+
}
|
|
94
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
95
|
+
this.resetIdleTimeout(session);
|
|
96
|
+
}
|
|
46
97
|
return item;
|
|
47
98
|
}
|
|
48
99
|
/**
|
|
49
|
-
*
|
|
100
|
+
* Extend a session, resetting its idle timeout.
|
|
50
101
|
*
|
|
51
|
-
* @param
|
|
52
|
-
* @
|
|
53
|
-
|
|
54
|
-
|
|
102
|
+
* @param sessionId - The session ID
|
|
103
|
+
* @public
|
|
104
|
+
*/
|
|
105
|
+
extendSession(sessionId) {
|
|
106
|
+
const session = this.sessions.get(sessionId);
|
|
107
|
+
if (!session) return;
|
|
108
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
109
|
+
this.resetIdleTimeout(session);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Stop a session, triggering fade-out.
|
|
114
|
+
*
|
|
115
|
+
* @param sessionId - The session ID
|
|
116
|
+
* @public
|
|
117
|
+
*/
|
|
118
|
+
stopSession(sessionId) {
|
|
119
|
+
const session = this.sessions.get(sessionId);
|
|
120
|
+
if (!session || session.state !== "active") return;
|
|
121
|
+
this.clearIdleTimeout(session);
|
|
122
|
+
session.state = "stopping";
|
|
123
|
+
if (session.options.fadeMode === "grouped") {
|
|
124
|
+
session.totalPointsAtFadeStart = session.items.reduce(
|
|
125
|
+
(sum, item) => sum + item.scribble.points.length,
|
|
126
|
+
0
|
|
127
|
+
);
|
|
128
|
+
session.fadeElapsed = 0;
|
|
129
|
+
for (const item of session.items) {
|
|
130
|
+
item.scribble.state = "stopping";
|
|
131
|
+
}
|
|
132
|
+
} else {
|
|
133
|
+
for (const item of session.items) {
|
|
134
|
+
item.delayRemaining = Math.min(item.delayRemaining, 200);
|
|
135
|
+
item.scribble.state = "stopping";
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Clear all scribbles in a session immediately.
|
|
141
|
+
*
|
|
142
|
+
* @param sessionId - The session ID
|
|
143
|
+
* @public
|
|
144
|
+
*/
|
|
145
|
+
clearSession(sessionId) {
|
|
146
|
+
const session = this.sessions.get(sessionId);
|
|
147
|
+
if (!session) return;
|
|
148
|
+
this.clearIdleTimeout(session);
|
|
149
|
+
for (const item of session.items) {
|
|
150
|
+
item.scribble.points.length = 0;
|
|
151
|
+
}
|
|
152
|
+
session.state = "complete";
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Check if a session is active.
|
|
156
|
+
*
|
|
157
|
+
* @param sessionId - The session ID
|
|
158
|
+
* @public
|
|
159
|
+
*/
|
|
160
|
+
isSessionActive(sessionId) {
|
|
161
|
+
const session = this.sessions.get(sessionId);
|
|
162
|
+
return session?.state === "active";
|
|
163
|
+
}
|
|
164
|
+
// ==================== SIMPLE API (for eraser, select, etc.) ====================
|
|
165
|
+
/**
|
|
166
|
+
* Add a scribble using the default self-consuming behavior.
|
|
167
|
+
* Creates an implicit session for the scribble.
|
|
168
|
+
*
|
|
169
|
+
* @param scribble - Partial scribble properties
|
|
170
|
+
* @param id - Optional scribble id
|
|
171
|
+
* @returns The created scribble item
|
|
172
|
+
* @public
|
|
173
|
+
*/
|
|
174
|
+
addScribble(scribble, id = uniqueId()) {
|
|
175
|
+
const sessionId = this.startSession();
|
|
176
|
+
return this.addScribbleToSession(sessionId, scribble, id);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Add a point to a scribble. Searches all sessions.
|
|
180
|
+
*
|
|
181
|
+
* @param id - The scribble id
|
|
182
|
+
* @param x - X coordinate
|
|
183
|
+
* @param y - Y coordinate
|
|
184
|
+
* @param z - Z coordinate (pressure)
|
|
55
185
|
* @public
|
|
56
186
|
*/
|
|
57
187
|
addPoint(id, x, y, z = 0.5) {
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
188
|
+
for (const session of this.sessions.values()) {
|
|
189
|
+
const item = session.items.find((i) => i.id === id);
|
|
190
|
+
if (item) {
|
|
191
|
+
const point = { x, y, z };
|
|
192
|
+
if (!item.prev || Vec.Dist(item.prev, point) >= 1) {
|
|
193
|
+
item.next = point;
|
|
194
|
+
}
|
|
195
|
+
if (session.options.idleTimeoutMs > 0) {
|
|
196
|
+
this.resetIdleTimeout(session);
|
|
197
|
+
}
|
|
198
|
+
return item;
|
|
199
|
+
}
|
|
64
200
|
}
|
|
65
|
-
|
|
201
|
+
throw Error(`Scribble with id ${id} not found`);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Mark a scribble as complete (done being drawn but not yet fading).
|
|
205
|
+
* Searches all sessions.
|
|
206
|
+
*
|
|
207
|
+
* @param id - The scribble id
|
|
208
|
+
* @public
|
|
209
|
+
*/
|
|
210
|
+
complete(id) {
|
|
211
|
+
for (const session of this.sessions.values()) {
|
|
212
|
+
const item = session.items.find((i) => i.id === id);
|
|
213
|
+
if (item) {
|
|
214
|
+
if (item.scribble.state === "starting" || item.scribble.state === "active") {
|
|
215
|
+
item.scribble.state = "complete";
|
|
216
|
+
}
|
|
217
|
+
return item;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
throw Error(`Scribble with id ${id} not found`);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Stop a scribble. Searches all sessions.
|
|
224
|
+
*
|
|
225
|
+
* @param id - The scribble id
|
|
226
|
+
* @public
|
|
227
|
+
*/
|
|
228
|
+
stop(id) {
|
|
229
|
+
for (const session of this.sessions.values()) {
|
|
230
|
+
const item = session.items.find((i) => i.id === id);
|
|
231
|
+
if (item) {
|
|
232
|
+
item.delayRemaining = Math.min(item.delayRemaining, 200);
|
|
233
|
+
item.scribble.state = "stopping";
|
|
234
|
+
return item;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
throw Error(`Scribble with id ${id} not found`);
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Stop and remove all sessions.
|
|
241
|
+
*
|
|
242
|
+
* @public
|
|
243
|
+
*/
|
|
244
|
+
reset() {
|
|
245
|
+
for (const session of this.sessions.values()) {
|
|
246
|
+
this.clearIdleTimeout(session);
|
|
247
|
+
}
|
|
248
|
+
this.sessions.clear();
|
|
249
|
+
this.editor.updateInstanceState({ scribbles: [] });
|
|
66
250
|
}
|
|
67
251
|
/**
|
|
68
252
|
* Update on each animation frame.
|
|
@@ -71,77 +255,182 @@ class ScribbleManager {
|
|
|
71
255
|
* @public
|
|
72
256
|
*/
|
|
73
257
|
tick(elapsed) {
|
|
74
|
-
|
|
258
|
+
const currentScribbles = this.editor.getInstanceState().scribbles;
|
|
259
|
+
if (this.sessions.size === 0 && currentScribbles.length === 0) return;
|
|
75
260
|
this.editor.run(() => {
|
|
76
|
-
this.
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (item.scribble.points.length > 8) {
|
|
84
|
-
item.scribble.state = "active";
|
|
85
|
-
}
|
|
86
|
-
return;
|
|
261
|
+
for (const session of this.sessions.values()) {
|
|
262
|
+
this.tickSession(session, elapsed);
|
|
263
|
+
}
|
|
264
|
+
for (const [id, session] of this.sessions) {
|
|
265
|
+
if (session.state === "complete") {
|
|
266
|
+
this.clearIdleTimeout(session);
|
|
267
|
+
this.sessions.delete(id);
|
|
87
268
|
}
|
|
88
|
-
|
|
89
|
-
|
|
269
|
+
}
|
|
270
|
+
const scribbles = [];
|
|
271
|
+
for (const session of this.sessions.values()) {
|
|
272
|
+
for (const item of session.items) {
|
|
273
|
+
if (item.scribble.points.length > 0) {
|
|
274
|
+
scribbles.push({
|
|
275
|
+
...item.scribble,
|
|
276
|
+
points: [...item.scribble.points]
|
|
277
|
+
});
|
|
278
|
+
}
|
|
90
279
|
}
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
280
|
+
}
|
|
281
|
+
this.editor.updateInstanceState({ scribbles });
|
|
282
|
+
});
|
|
283
|
+
}
|
|
284
|
+
// ==================== PRIVATE HELPERS ====================
|
|
285
|
+
resetIdleTimeout(session) {
|
|
286
|
+
this.clearIdleTimeout(session);
|
|
287
|
+
session.idleTimeoutHandle = this.editor.timers.setTimeout(() => {
|
|
288
|
+
this.stopSession(session.id);
|
|
289
|
+
}, session.options.idleTimeoutMs);
|
|
290
|
+
}
|
|
291
|
+
clearIdleTimeout(session) {
|
|
292
|
+
if (session.idleTimeoutHandle !== void 0) {
|
|
293
|
+
clearTimeout(session.idleTimeoutHandle);
|
|
294
|
+
session.idleTimeoutHandle = void 0;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
tickSession(session, elapsed) {
|
|
298
|
+
if (session.state === "complete") return;
|
|
299
|
+
if (session.state === "stopping" && session.options.fadeMode === "grouped") {
|
|
300
|
+
this.tickGroupedFade(session, elapsed);
|
|
301
|
+
} else {
|
|
302
|
+
this.tickSessionItems(session, elapsed);
|
|
303
|
+
}
|
|
304
|
+
const hasContent = session.items.some((item) => item.scribble.points.length > 0);
|
|
305
|
+
if (!hasContent && (session.state === "stopping" || session.items.length === 0)) {
|
|
306
|
+
session.state = "complete";
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
tickSessionItems(session, elapsed) {
|
|
310
|
+
for (const item of session.items) {
|
|
311
|
+
const shouldSelfConsume = session.options.selfConsume || session.state === "stopping" || item.scribble.state === "stopping";
|
|
312
|
+
if (shouldSelfConsume) {
|
|
313
|
+
this.tickSelfConsumingItem(item, elapsed);
|
|
314
|
+
} else {
|
|
315
|
+
this.tickPersistentItem(item);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
if (session.options.fadeMode === "individual") {
|
|
319
|
+
for (let i = session.items.length - 1; i >= 0; i--) {
|
|
320
|
+
if (session.items[i].scribble.points.length === 0) {
|
|
321
|
+
session.items.splice(i, 1);
|
|
94
322
|
}
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
tickPersistentItem(item) {
|
|
327
|
+
const { scribble } = item;
|
|
328
|
+
if (scribble.state === "starting") {
|
|
329
|
+
const { next, prev } = item;
|
|
330
|
+
if (next && next !== prev) {
|
|
331
|
+
item.prev = next;
|
|
332
|
+
scribble.points.push(next);
|
|
333
|
+
}
|
|
334
|
+
if (scribble.points.length > 8) {
|
|
335
|
+
scribble.state = "active";
|
|
336
|
+
}
|
|
337
|
+
return;
|
|
338
|
+
}
|
|
339
|
+
if (scribble.state === "active") {
|
|
340
|
+
const { next, prev } = item;
|
|
341
|
+
if (next && next !== prev) {
|
|
342
|
+
item.prev = next;
|
|
343
|
+
scribble.points.push(next);
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
tickSelfConsumingItem(item, elapsed) {
|
|
348
|
+
const { scribble } = item;
|
|
349
|
+
if (scribble.state === "starting") {
|
|
350
|
+
const { next: next2, prev: prev2 } = item;
|
|
351
|
+
if (next2 && next2 !== prev2) {
|
|
352
|
+
item.prev = next2;
|
|
353
|
+
scribble.points.push(next2);
|
|
354
|
+
}
|
|
355
|
+
if (scribble.points.length > 8) {
|
|
356
|
+
scribble.state = "active";
|
|
357
|
+
}
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if (item.delayRemaining > 0) {
|
|
361
|
+
item.delayRemaining = Math.max(0, item.delayRemaining - elapsed);
|
|
362
|
+
}
|
|
363
|
+
item.timeoutMs += elapsed;
|
|
364
|
+
if (item.timeoutMs >= 16) {
|
|
365
|
+
item.timeoutMs = 0;
|
|
366
|
+
}
|
|
367
|
+
const { delayRemaining, timeoutMs, prev, next } = item;
|
|
368
|
+
switch (scribble.state) {
|
|
369
|
+
case "active": {
|
|
370
|
+
if (next && next !== prev) {
|
|
371
|
+
item.prev = next;
|
|
372
|
+
scribble.points.push(next);
|
|
373
|
+
if (delayRemaining === 0 && scribble.points.length > 8) {
|
|
374
|
+
scribble.points.shift();
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
if (timeoutMs === 0) {
|
|
378
|
+
if (scribble.points.length > 1) {
|
|
379
|
+
scribble.points.shift();
|
|
106
380
|
} else {
|
|
107
|
-
|
|
108
|
-
if (scribble.points.length > 1) {
|
|
109
|
-
scribble.points.shift();
|
|
110
|
-
} else {
|
|
111
|
-
item.delayRemaining = scribble.delay;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
381
|
+
item.delayRemaining = scribble.delay;
|
|
114
382
|
}
|
|
115
|
-
break;
|
|
116
383
|
}
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
scribble.size = Math.max(1, scribble.size * (1 - scribble.shrink));
|
|
126
|
-
}
|
|
127
|
-
scribble.points.shift();
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
break;
|
|
384
|
+
}
|
|
385
|
+
break;
|
|
386
|
+
}
|
|
387
|
+
case "stopping": {
|
|
388
|
+
if (delayRemaining === 0 && timeoutMs === 0) {
|
|
389
|
+
if (scribble.points.length <= 1) {
|
|
390
|
+
scribble.points.length = 0;
|
|
391
|
+
return;
|
|
131
392
|
}
|
|
132
|
-
|
|
133
|
-
|
|
393
|
+
if (scribble.shrink) {
|
|
394
|
+
scribble.size = Math.max(1, scribble.size * (1 - scribble.shrink));
|
|
134
395
|
}
|
|
396
|
+
scribble.points.shift();
|
|
135
397
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
case "paused": {
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
tickGroupedFade(session, elapsed) {
|
|
406
|
+
session.fadeElapsed += elapsed;
|
|
407
|
+
let remainingPoints = 0;
|
|
408
|
+
for (const item of session.items) {
|
|
409
|
+
remainingPoints += item.scribble.points.length;
|
|
410
|
+
}
|
|
411
|
+
if (remainingPoints === 0) return;
|
|
412
|
+
if (session.fadeElapsed >= session.options.fadeDurationMs) {
|
|
413
|
+
for (const item of session.items) {
|
|
414
|
+
item.scribble.points.length = 0;
|
|
415
|
+
}
|
|
416
|
+
return;
|
|
417
|
+
}
|
|
418
|
+
const progress = session.fadeElapsed / session.options.fadeDurationMs;
|
|
419
|
+
const easedProgress = session.options.fadeEasing === "ease-in" ? progress * progress : progress;
|
|
420
|
+
const targetRemoved = Math.floor(easedProgress * session.totalPointsAtFadeStart);
|
|
421
|
+
const actuallyRemoved = session.totalPointsAtFadeStart - remainingPoints;
|
|
422
|
+
const pointsToRemove = Math.max(1, targetRemoved - actuallyRemoved);
|
|
423
|
+
let removed = 0;
|
|
424
|
+
let itemIndex = 0;
|
|
425
|
+
while (removed < pointsToRemove && itemIndex < session.items.length) {
|
|
426
|
+
const item = session.items[itemIndex];
|
|
427
|
+
if (item.scribble.points.length > 0) {
|
|
428
|
+
item.scribble.points.shift();
|
|
429
|
+
removed++;
|
|
430
|
+
} else {
|
|
431
|
+
itemIndex++;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
145
434
|
}
|
|
146
435
|
}
|
|
147
436
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/lib/editor/managers/ScribbleManager/ScribbleManager.ts"],
|
|
4
|
-
"sourcesContent": ["import { TLScribble, VecModel } from '@tldraw/tlschema'\nimport { uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport { Editor } from '../../Editor'\n\n/** @public */\nexport interface ScribbleItem {\n\tid: string\n\tscribble: TLScribble\n\ttimeoutMs: number\n\tdelayRemaining: number\n\tprev: null | VecModel\n\tnext: null | VecModel\n}\n\n/** @public */\nexport class ScribbleManager {\n\tscribbleItems = new Map<string, ScribbleItem>()\n\tstate = 'paused' as 'paused' | 'running'\n\n\tconstructor(private editor: Editor) {}\n\n\taddScribble(scribble: Partial<TLScribble>, id = uniqueId()) {\n\t\tconst item: ScribbleItem = {\n\t\t\tid,\n\t\t\tscribble: {\n\t\t\t\tid,\n\t\t\t\tsize: 20,\n\t\t\t\tcolor: 'accent',\n\t\t\t\topacity: 0.8,\n\t\t\t\tdelay: 0,\n\t\t\t\tpoints: [],\n\t\t\t\tshrink: 0.1,\n\t\t\t\ttaper: true,\n\t\t\t\t...scribble,\n\t\t\t\tstate: 'starting',\n\t\t\t},\n\t\t\ttimeoutMs: 0,\n\t\t\tdelayRemaining: scribble.delay ?? 0,\n\t\t\tprev: null,\n\t\t\tnext: null,\n\t\t}\n\t\tthis.scribbleItems.set(id, item)\n\t\treturn item\n\t}\n\n\treset() {\n\t\tthis.editor.updateInstanceState({ scribbles: [] })\n\t\tthis.scribbleItems.clear()\n\t}\n\n\t/**\n\t * Start stopping the scribble. The scribble won't be removed until its last point is cleared.\n\t *\n\t * @public\n\t */\n\tstop(id: ScribbleItem['id']) {\n\t\tconst item = this.scribbleItems.get(id)\n\t\tif (!item) throw Error(`Scribble with id ${id} not found`)\n\t\titem.delayRemaining = Math.min(item.delayRemaining, 200)\n\t\titem.scribble.state = 'stopping'\n\t\treturn item\n\t}\n\n\t/**\n\t * Set the scribble's next point.\n\t *\n\t * @param id - The id of the scribble to add a point to.\n\t * @param x - The x coordinate of the point.\n\t * @param y - The y coordinate of the point.\n\t * @param z - The z coordinate of the point.\n\t * @public\n\t */\n\taddPoint(id: ScribbleItem['id'], x: number, y: number, z = 0.5) {\n\t\tconst item = this.scribbleItems.get(id)\n\t\tif (!item) throw Error(`Scribble with id ${id} not found`)\n\t\tconst { prev } = item\n\t\tconst point = { x, y, z }\n\t\tif (!prev || Vec.Dist(prev, point) >= 1) {\n\t\t\titem.next = point\n\t\t}\n\t\treturn item\n\t}\n\n\t/**\n\t * Update on each animation frame.\n\t *\n\t * @param elapsed - The number of milliseconds since the last tick.\n\t * @public\n\t */\n\ttick(elapsed: number) {\n\t\tif (this.scribbleItems.size === 0) return\n\t\tthis.editor.run(() => {\n\t\t\tthis.scribbleItems.forEach((item) => {\n\t\t\t\t// let the item get at least eight points before\n\t\t\t\t// switching from starting to active\n\t\t\t\tif (item.scribble.state === 'starting') {\n\t\t\t\t\tconst { next, prev } = item\n\t\t\t\t\tif (next && next !== prev) {\n\t\t\t\t\t\titem.prev = next\n\t\t\t\t\t\titem.scribble.points.push(next)\n\t\t\t\t\t}\n\n\t\t\t\t\tif (item.scribble.points.length > 8) {\n\t\t\t\t\t\titem.scribble.state = 'active'\n\t\t\t\t\t}\n\t\t\t\t\treturn\n\t\t\t\t}\n\n\t\t\t\tif (item.delayRemaining > 0) {\n\t\t\t\t\titem.delayRemaining = Math.max(0, item.delayRemaining - elapsed)\n\t\t\t\t}\n\n\t\t\t\titem.timeoutMs += elapsed\n\t\t\t\tif (item.timeoutMs >= 16) {\n\t\t\t\t\titem.timeoutMs = 0\n\t\t\t\t}\n\n\t\t\t\tconst { delayRemaining, timeoutMs, prev, next, scribble } = item\n\n\t\t\t\tswitch (scribble.state) {\n\t\t\t\t\tcase 'active': {\n\t\t\t\t\t\tif (next && next !== prev) {\n\t\t\t\t\t\t\titem.prev = next\n\t\t\t\t\t\t\tscribble.points.push(next)\n\n\t\t\t\t\t\t\t// If we've run out of delay, then shrink the scribble from the start\n\t\t\t\t\t\t\tif (delayRemaining === 0) {\n\t\t\t\t\t\t\t\tif (scribble.points.length > 8) {\n\t\t\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t// While not moving, shrink the scribble from the start\n\t\t\t\t\t\t\tif (timeoutMs === 0) {\n\t\t\t\t\t\t\t\tif (scribble.points.length > 1) {\n\t\t\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t// Reset the item's delay\n\t\t\t\t\t\t\t\t\titem.delayRemaining = scribble.delay\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'stopping': {\n\t\t\t\t\t\tif (item.delayRemaining === 0) {\n\t\t\t\t\t\t\tif (timeoutMs === 0) {\n\t\t\t\t\t\t\t\t// If the scribble is down to one point, we're done!\n\t\t\t\t\t\t\t\tif (scribble.points.length === 1) {\n\t\t\t\t\t\t\t\t\tthis.scribbleItems.delete(item.id) // Remove the scribble\n\t\t\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif (scribble.shrink) {\n\t\t\t\t\t\t\t\t\t// Drop the scribble's size as it shrinks\n\t\t\t\t\t\t\t\t\tscribble.size = Math.max(1, scribble.size * (1 - scribble.shrink))\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Drop the scribble's first point (its tail)\n\t\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t\tcase 'paused': {\n\t\t\t\t\t\t// Nothing to do while paused.\n\t\t\t\t\t\tbreak\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t})\n\n\t\t\t// The object here will get frozen into the record, so we need to\n\t\t\t// create a copies of the parts that what we'll be mutating later.\n\t\t\tthis.editor.updateInstanceState({\n\t\t\t\tscribbles: Array.from(this.scribbleItems.values())\n\t\t\t\t\t.map(({ scribble }) => ({\n\t\t\t\t\t\t...scribble,\n\t\t\t\t\t\tpoints: [...scribble.points],\n\t\t\t\t\t}))\n\t\t\t\t\t.slice(-5), // limit to three as a minor sanity check\n\t\t\t})\n\t\t})\n\t}\n}\n"],
|
|
5
|
-
"mappings": "AACA,SAAS,gBAAgB;AACzB,SAAS,WAAW;
|
|
4
|
+
"sourcesContent": ["import { TLScribble, VecModel } from '@tldraw/tlschema'\nimport { uniqueId } from '@tldraw/utils'\nimport { Vec } from '../../../primitives/Vec'\nimport { Editor } from '../../Editor'\n\n/** @public */\nexport interface ScribbleItem {\n\tid: string\n\tscribble: TLScribble\n\ttimeoutMs: number\n\tdelayRemaining: number\n\tprev: null | VecModel\n\tnext: null | VecModel\n}\n\n/** @public */\nexport interface ScribbleSessionOptions {\n\t/** Session id. Auto-generated if not provided. */\n\tid?: string\n\t/**\n\t * Whether scribbles self-consume (shrink from start) while drawing.\n\t * - true: scribbles eat their own tail as you draw (default, used for eraser/select)\n\t * - false: scribbles persist until session stops (used for laser)\n\t */\n\tselfConsume?: boolean\n\t/**\n\t * How long to wait after last activity before auto-stopping the session.\n\t * Only applies when selfConsume is false.\n\t */\n\tidleTimeoutMs?: number\n\t/**\n\t * How scribbles fade when stopping.\n\t * - 'individual': each scribble fades on its own (default)\n\t * - 'grouped': all scribbles fade together as one sequence\n\t */\n\tfadeMode?: 'individual' | 'grouped'\n\t/**\n\t * Easing for grouped fade.\n\t */\n\tfadeEasing?: 'linear' | 'ease-in'\n\t/**\n\t * Duration of the fade in milliseconds.\n\t */\n\tfadeDurationMs?: number\n}\n\n// Internal session state (not exported)\ninterface Session {\n\tid: string\n\titems: ScribbleItem[]\n\tstate: 'active' | 'stopping' | 'complete'\n\toptions: Required<Omit<ScribbleSessionOptions, 'id'>>\n\tidleTimeoutHandle?: number\n\tfadeElapsed: number\n\ttotalPointsAtFadeStart: number\n}\n\n/** @public */\nexport class ScribbleManager {\n\tprivate sessions = new Map<string, Session>()\n\n\tconstructor(private editor: Editor) {}\n\n\t// ==================== SESSION API ====================\n\n\t/**\n\t * Start a new session for grouping scribbles.\n\t * Returns a session ID that can be used with other session methods.\n\t *\n\t * @param options - Session configuration\n\t * @returns Session ID\n\t * @public\n\t */\n\tstartSession(options: ScribbleSessionOptions = {}): string {\n\t\tconst id = options.id ?? uniqueId()\n\t\tconst session: Session = {\n\t\t\tid,\n\t\t\titems: [],\n\t\t\tstate: 'active',\n\t\t\toptions: {\n\t\t\t\tselfConsume: options.selfConsume ?? true,\n\t\t\t\tidleTimeoutMs: options.idleTimeoutMs ?? 0,\n\t\t\t\tfadeMode: options.fadeMode ?? 'individual',\n\t\t\t\tfadeEasing: options.fadeEasing ?? (options.fadeMode === 'grouped' ? 'ease-in' : 'linear'),\n\t\t\t\tfadeDurationMs: options.fadeDurationMs ?? this.editor.options.laserFadeoutMs,\n\t\t\t},\n\t\t\tfadeElapsed: 0,\n\t\t\ttotalPointsAtFadeStart: 0,\n\t\t}\n\n\t\tthis.sessions.set(id, session)\n\n\t\t// Set up idle timeout if configured\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\n\t\treturn id\n\t}\n\n\t/**\n\t * Add a scribble to a session.\n\t *\n\t * @param sessionId - The session ID\n\t * @param scribble - Partial scribble properties\n\t * @param scribbleId - Optional scribble ID\n\t * @public\n\t */\n\taddScribbleToSession(\n\t\tsessionId: string,\n\t\tscribble: Partial<TLScribble>,\n\t\tscribbleId = uniqueId()\n\t): ScribbleItem {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) throw Error(`Session ${sessionId} not found`)\n\n\t\tconst item: ScribbleItem = {\n\t\t\tid: scribbleId,\n\t\t\tscribble: {\n\t\t\t\tid: scribbleId,\n\t\t\t\tsize: 20,\n\t\t\t\tcolor: 'accent',\n\t\t\t\topacity: 0.8,\n\t\t\t\tdelay: 0,\n\t\t\t\tpoints: [],\n\t\t\t\tshrink: 0.1,\n\t\t\t\ttaper: true,\n\t\t\t\t...scribble,\n\t\t\t\tstate: 'starting',\n\t\t\t},\n\t\t\ttimeoutMs: 0,\n\t\t\tdelayRemaining: scribble.delay ?? 0,\n\t\t\tprev: null,\n\t\t\tnext: null,\n\t\t}\n\n\t\tsession.items.push(item)\n\n\t\t// Reset idle timeout on activity\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\n\t\treturn item\n\t}\n\n\t/**\n\t * Add a point to a scribble in a session.\n\t *\n\t * @param sessionId - The session ID\n\t * @param scribbleId - The scribble ID\n\t * @param x - X coordinate\n\t * @param y - Y coordinate\n\t * @param z - Z coordinate (pressure)\n\t * @public\n\t */\n\taddPointToSession(\n\t\tsessionId: string,\n\t\tscribbleId: string,\n\t\tx: number,\n\t\ty: number,\n\t\tz = 0.5\n\t): ScribbleItem {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) throw Error(`Session ${sessionId} not found`)\n\n\t\tconst item = session.items.find((i) => i.id === scribbleId)\n\t\tif (!item) throw Error(`Scribble ${scribbleId} not found in session ${sessionId}`)\n\n\t\tconst point = { x, y, z }\n\t\tif (!item.prev || Vec.Dist(item.prev, point) >= 1) {\n\t\t\titem.next = point\n\t\t}\n\n\t\t// Reset idle timeout on activity\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\n\t\treturn item\n\t}\n\n\t/**\n\t * Extend a session, resetting its idle timeout.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\textendSession(sessionId: string): void {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) return\n\n\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\tthis.resetIdleTimeout(session)\n\t\t}\n\t}\n\n\t/**\n\t * Stop a session, triggering fade-out.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\tstopSession(sessionId: string): void {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session || session.state !== 'active') return\n\n\t\tthis.clearIdleTimeout(session)\n\t\tsession.state = 'stopping'\n\n\t\tif (session.options.fadeMode === 'grouped') {\n\t\t\tsession.totalPointsAtFadeStart = session.items.reduce(\n\t\t\t\t(sum, item) => sum + item.scribble.points.length,\n\t\t\t\t0\n\t\t\t)\n\t\t\tsession.fadeElapsed = 0\n\t\t\tfor (const item of session.items) {\n\t\t\t\titem.scribble.state = 'stopping'\n\t\t\t}\n\t\t} else {\n\t\t\tfor (const item of session.items) {\n\t\t\t\titem.delayRemaining = Math.min(item.delayRemaining, 200)\n\t\t\t\titem.scribble.state = 'stopping'\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Clear all scribbles in a session immediately.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\tclearSession(sessionId: string): void {\n\t\tconst session = this.sessions.get(sessionId)\n\t\tif (!session) return\n\n\t\tthis.clearIdleTimeout(session)\n\t\tfor (const item of session.items) {\n\t\t\titem.scribble.points.length = 0\n\t\t}\n\t\tsession.state = 'complete'\n\t}\n\n\t/**\n\t * Check if a session is active.\n\t *\n\t * @param sessionId - The session ID\n\t * @public\n\t */\n\tisSessionActive(sessionId: string): boolean {\n\t\tconst session = this.sessions.get(sessionId)\n\t\treturn session?.state === 'active'\n\t}\n\n\t// ==================== SIMPLE API (for eraser, select, etc.) ====================\n\n\t/**\n\t * Add a scribble using the default self-consuming behavior.\n\t * Creates an implicit session for the scribble.\n\t *\n\t * @param scribble - Partial scribble properties\n\t * @param id - Optional scribble id\n\t * @returns The created scribble item\n\t * @public\n\t */\n\taddScribble(scribble: Partial<TLScribble>, id = uniqueId()): ScribbleItem {\n\t\tconst sessionId = this.startSession()\n\t\treturn this.addScribbleToSession(sessionId, scribble, id)\n\t}\n\n\t/**\n\t * Add a point to a scribble. Searches all sessions.\n\t *\n\t * @param id - The scribble id\n\t * @param x - X coordinate\n\t * @param y - Y coordinate\n\t * @param z - Z coordinate (pressure)\n\t * @public\n\t */\n\taddPoint(id: string, x: number, y: number, z = 0.5): ScribbleItem {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst item = session.items.find((i) => i.id === id)\n\t\t\tif (item) {\n\t\t\t\tconst point = { x, y, z }\n\t\t\t\tif (!item.prev || Vec.Dist(item.prev, point) >= 1) {\n\t\t\t\t\titem.next = point\n\t\t\t\t}\n\t\t\t\tif (session.options.idleTimeoutMs > 0) {\n\t\t\t\t\tthis.resetIdleTimeout(session)\n\t\t\t\t}\n\t\t\t\treturn item\n\t\t\t}\n\t\t}\n\t\tthrow Error(`Scribble with id ${id} not found`)\n\t}\n\n\t/**\n\t * Mark a scribble as complete (done being drawn but not yet fading).\n\t * Searches all sessions.\n\t *\n\t * @param id - The scribble id\n\t * @public\n\t */\n\tcomplete(id: string): ScribbleItem {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst item = session.items.find((i) => i.id === id)\n\t\t\tif (item) {\n\t\t\t\tif (item.scribble.state === 'starting' || item.scribble.state === 'active') {\n\t\t\t\t\titem.scribble.state = 'complete'\n\t\t\t\t}\n\t\t\t\treturn item\n\t\t\t}\n\t\t}\n\t\tthrow Error(`Scribble with id ${id} not found`)\n\t}\n\n\t/**\n\t * Stop a scribble. Searches all sessions.\n\t *\n\t * @param id - The scribble id\n\t * @public\n\t */\n\tstop(id: string): ScribbleItem {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tconst item = session.items.find((i) => i.id === id)\n\t\t\tif (item) {\n\t\t\t\titem.delayRemaining = Math.min(item.delayRemaining, 200)\n\t\t\t\titem.scribble.state = 'stopping'\n\t\t\t\treturn item\n\t\t\t}\n\t\t}\n\t\tthrow Error(`Scribble with id ${id} not found`)\n\t}\n\n\t/**\n\t * Stop and remove all sessions.\n\t *\n\t * @public\n\t */\n\treset(): void {\n\t\tfor (const session of this.sessions.values()) {\n\t\t\tthis.clearIdleTimeout(session)\n\t\t}\n\t\tthis.sessions.clear()\n\t\tthis.editor.updateInstanceState({ scribbles: [] })\n\t}\n\n\t/**\n\t * Update on each animation frame.\n\t *\n\t * @param elapsed - The number of milliseconds since the last tick.\n\t * @public\n\t */\n\ttick(elapsed: number): void {\n\t\tconst currentScribbles = this.editor.getInstanceState().scribbles\n\t\tif (this.sessions.size === 0 && currentScribbles.length === 0) return\n\n\t\tthis.editor.run(() => {\n\t\t\t// Tick all sessions\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tthis.tickSession(session, elapsed)\n\t\t\t}\n\n\t\t\t// Remove completed sessions\n\t\t\tfor (const [id, session] of this.sessions) {\n\t\t\t\tif (session.state === 'complete') {\n\t\t\t\t\tthis.clearIdleTimeout(session)\n\t\t\t\t\tthis.sessions.delete(id)\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Collect scribbles from all sessions\n\t\t\tconst scribbles: TLScribble[] = []\n\t\t\tfor (const session of this.sessions.values()) {\n\t\t\t\tfor (const item of session.items) {\n\t\t\t\t\tif (item.scribble.points.length > 0) {\n\t\t\t\t\t\tscribbles.push({\n\t\t\t\t\t\t\t...item.scribble,\n\t\t\t\t\t\t\tpoints: [...item.scribble.points],\n\t\t\t\t\t\t})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.editor.updateInstanceState({ scribbles })\n\t\t})\n\t}\n\n\t// ==================== PRIVATE HELPERS ====================\n\n\tprivate resetIdleTimeout(session: Session): void {\n\t\tthis.clearIdleTimeout(session)\n\t\tsession.idleTimeoutHandle = this.editor.timers.setTimeout(() => {\n\t\t\tthis.stopSession(session.id)\n\t\t}, session.options.idleTimeoutMs)\n\t}\n\n\tprivate clearIdleTimeout(session: Session): void {\n\t\tif (session.idleTimeoutHandle !== undefined) {\n\t\t\tclearTimeout(session.idleTimeoutHandle)\n\t\t\tsession.idleTimeoutHandle = undefined\n\t\t}\n\t}\n\n\tprivate tickSession(session: Session, elapsed: number): void {\n\t\tif (session.state === 'complete') return\n\n\t\tif (session.state === 'stopping' && session.options.fadeMode === 'grouped') {\n\t\t\tthis.tickGroupedFade(session, elapsed)\n\t\t} else {\n\t\t\tthis.tickSessionItems(session, elapsed)\n\t\t}\n\n\t\t// Check if session is complete\n\t\tconst hasContent = session.items.some((item) => item.scribble.points.length > 0)\n\t\tif (!hasContent && (session.state === 'stopping' || session.items.length === 0)) {\n\t\t\tsession.state = 'complete'\n\t\t}\n\t}\n\n\tprivate tickSessionItems(session: Session, elapsed: number): void {\n\t\tfor (const item of session.items) {\n\t\t\tconst shouldSelfConsume =\n\t\t\t\tsession.options.selfConsume ||\n\t\t\t\tsession.state === 'stopping' ||\n\t\t\t\titem.scribble.state === 'stopping'\n\n\t\t\tif (shouldSelfConsume) {\n\t\t\t\tthis.tickSelfConsumingItem(item, elapsed)\n\t\t\t} else {\n\t\t\t\tthis.tickPersistentItem(item)\n\t\t\t}\n\t\t}\n\n\t\t// Remove completed items in individual fade mode\n\t\tif (session.options.fadeMode === 'individual') {\n\t\t\tfor (let i = session.items.length - 1; i >= 0; i--) {\n\t\t\t\tif (session.items[i].scribble.points.length === 0) {\n\t\t\t\t\tsession.items.splice(i, 1)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate tickPersistentItem(item: ScribbleItem): void {\n\t\tconst { scribble } = item\n\n\t\tif (scribble.state === 'starting') {\n\t\t\tconst { next, prev } = item\n\t\t\tif (next && next !== prev) {\n\t\t\t\titem.prev = next\n\t\t\t\tscribble.points.push(next)\n\t\t\t}\n\t\t\tif (scribble.points.length > 8) {\n\t\t\t\tscribble.state = 'active'\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif (scribble.state === 'active') {\n\t\t\tconst { next, prev } = item\n\t\t\tif (next && next !== prev) {\n\t\t\t\titem.prev = next\n\t\t\t\tscribble.points.push(next)\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate tickSelfConsumingItem(item: ScribbleItem, elapsed: number): void {\n\t\tconst { scribble } = item\n\n\t\tif (scribble.state === 'starting') {\n\t\t\tconst { next, prev } = item\n\t\t\tif (next && next !== prev) {\n\t\t\t\titem.prev = next\n\t\t\t\tscribble.points.push(next)\n\t\t\t}\n\t\t\tif (scribble.points.length > 8) {\n\t\t\t\tscribble.state = 'active'\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tif (item.delayRemaining > 0) {\n\t\t\titem.delayRemaining = Math.max(0, item.delayRemaining - elapsed)\n\t\t}\n\n\t\titem.timeoutMs += elapsed\n\t\tif (item.timeoutMs >= 16) {\n\t\t\titem.timeoutMs = 0\n\t\t}\n\n\t\tconst { delayRemaining, timeoutMs, prev, next } = item\n\n\t\tswitch (scribble.state) {\n\t\t\tcase 'active': {\n\t\t\t\tif (next && next !== prev) {\n\t\t\t\t\titem.prev = next\n\t\t\t\t\tscribble.points.push(next)\n\t\t\t\t\tif (delayRemaining === 0 && scribble.points.length > 8) {\n\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif (timeoutMs === 0) {\n\t\t\t\t\t\tif (scribble.points.length > 1) {\n\t\t\t\t\t\t\tscribble.points.shift()\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\titem.delayRemaining = scribble.delay\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'stopping': {\n\t\t\t\tif (delayRemaining === 0 && timeoutMs === 0) {\n\t\t\t\t\tif (scribble.points.length <= 1) {\n\t\t\t\t\t\tscribble.points.length = 0\n\t\t\t\t\t\treturn\n\t\t\t\t\t}\n\t\t\t\t\tif (scribble.shrink) {\n\t\t\t\t\t\tscribble.size = Math.max(1, scribble.size * (1 - scribble.shrink))\n\t\t\t\t\t}\n\t\t\t\t\tscribble.points.shift()\n\t\t\t\t}\n\t\t\t\tbreak\n\t\t\t}\n\t\t\tcase 'paused': {\n\t\t\t\tbreak\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate tickGroupedFade(session: Session, elapsed: number): void {\n\t\tsession.fadeElapsed += elapsed\n\n\t\tlet remainingPoints = 0\n\t\tfor (const item of session.items) {\n\t\t\tremainingPoints += item.scribble.points.length\n\t\t}\n\n\t\tif (remainingPoints === 0) return\n\n\t\tif (session.fadeElapsed >= session.options.fadeDurationMs) {\n\t\t\tfor (const item of session.items) {\n\t\t\t\titem.scribble.points.length = 0\n\t\t\t}\n\t\t\treturn\n\t\t}\n\n\t\tconst progress = session.fadeElapsed / session.options.fadeDurationMs\n\t\tconst easedProgress = session.options.fadeEasing === 'ease-in' ? progress * progress : progress\n\n\t\tconst targetRemoved = Math.floor(easedProgress * session.totalPointsAtFadeStart)\n\t\tconst actuallyRemoved = session.totalPointsAtFadeStart - remainingPoints\n\t\tconst pointsToRemove = Math.max(1, targetRemoved - actuallyRemoved)\n\n\t\tlet removed = 0\n\t\tlet itemIndex = 0\n\t\twhile (removed < pointsToRemove && itemIndex < session.items.length) {\n\t\t\tconst item = session.items[itemIndex]\n\t\t\tif (item.scribble.points.length > 0) {\n\t\t\t\titem.scribble.points.shift()\n\t\t\t\tremoved++\n\t\t\t} else {\n\t\t\t\titemIndex++\n\t\t\t}\n\t\t}\n\t}\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["next", "prev"]
|
|
7
7
|
}
|
|
@@ -46,10 +46,10 @@ var __privateIn = (member, obj) => Object(obj) !== obj ? __typeError('Cannot use
|
|
|
46
46
|
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
47
47
|
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
48
48
|
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
49
|
-
var _getInputMode_dec, _getEnhancedA11yMode_dec, _getIsPasteAtCursorMode_dec, _getIsDynamicResizeMode_dec, _getIsWrapMode_dec, _getIsSnapMode_dec, _getColor_dec, _getLocale_dec, _getName_dec, _getId_dec, _getAreKeyboardShortcutsEnabled_dec, _getAnimationSpeed_dec, _getEdgeScrollSpeed_dec, _getIsDarkMode_dec, _getUserPreferences_dec, _init;
|
|
49
|
+
var _getIsZoomDirectionInverted_dec, _getInputMode_dec, _getEnhancedA11yMode_dec, _getIsPasteAtCursorMode_dec, _getIsDynamicResizeMode_dec, _getIsWrapMode_dec, _getIsSnapMode_dec, _getColor_dec, _getLocale_dec, _getName_dec, _getId_dec, _getAreKeyboardShortcutsEnabled_dec, _getAnimationSpeed_dec, _getEdgeScrollSpeed_dec, _getIsDarkMode_dec, _getUserPreferences_dec, _init;
|
|
50
50
|
import { atom, computed } from "@tldraw/state";
|
|
51
51
|
import { defaultUserPreferences } from "../../../config/TLUserPreferences.mjs";
|
|
52
|
-
_getUserPreferences_dec = [computed], _getIsDarkMode_dec = [computed], _getEdgeScrollSpeed_dec = [computed], _getAnimationSpeed_dec = [computed], _getAreKeyboardShortcutsEnabled_dec = [computed], _getId_dec = [computed], _getName_dec = [computed], _getLocale_dec = [computed], _getColor_dec = [computed], _getIsSnapMode_dec = [computed], _getIsWrapMode_dec = [computed], _getIsDynamicResizeMode_dec = [computed], _getIsPasteAtCursorMode_dec = [computed], _getEnhancedA11yMode_dec = [computed], _getInputMode_dec = [computed];
|
|
52
|
+
_getUserPreferences_dec = [computed], _getIsDarkMode_dec = [computed], _getEdgeScrollSpeed_dec = [computed], _getAnimationSpeed_dec = [computed], _getAreKeyboardShortcutsEnabled_dec = [computed], _getId_dec = [computed], _getName_dec = [computed], _getLocale_dec = [computed], _getColor_dec = [computed], _getIsSnapMode_dec = [computed], _getIsWrapMode_dec = [computed], _getIsDynamicResizeMode_dec = [computed], _getIsPasteAtCursorMode_dec = [computed], _getEnhancedA11yMode_dec = [computed], _getInputMode_dec = [computed], _getIsZoomDirectionInverted_dec = [computed];
|
|
53
53
|
class UserPreferencesManager {
|
|
54
54
|
constructor(user, inferDarkMode) {
|
|
55
55
|
this.user = user;
|
|
@@ -95,7 +95,8 @@ class UserPreferencesManager {
|
|
|
95
95
|
isWrapMode: this.getIsWrapMode(),
|
|
96
96
|
isDynamicResizeMode: this.getIsDynamicResizeMode(),
|
|
97
97
|
enhancedA11yMode: this.getEnhancedA11yMode(),
|
|
98
|
-
inputMode: this.getInputMode()
|
|
98
|
+
inputMode: this.getInputMode(),
|
|
99
|
+
isZoomDirectionInverted: this.getIsZoomDirectionInverted()
|
|
99
100
|
};
|
|
100
101
|
}
|
|
101
102
|
getIsDarkMode() {
|
|
@@ -149,6 +150,9 @@ class UserPreferencesManager {
|
|
|
149
150
|
getInputMode() {
|
|
150
151
|
return this.user.userPreferences.get().inputMode ?? defaultUserPreferences.inputMode;
|
|
151
152
|
}
|
|
153
|
+
getIsZoomDirectionInverted() {
|
|
154
|
+
return this.user.userPreferences.get().isZoomDirectionInverted ?? defaultUserPreferences.isZoomDirectionInverted;
|
|
155
|
+
}
|
|
152
156
|
}
|
|
153
157
|
_init = __decoratorStart(null);
|
|
154
158
|
__decorateElement(_init, 1, "getUserPreferences", _getUserPreferences_dec, UserPreferencesManager);
|
|
@@ -166,6 +170,7 @@ __decorateElement(_init, 1, "getIsDynamicResizeMode", _getIsDynamicResizeMode_de
|
|
|
166
170
|
__decorateElement(_init, 1, "getIsPasteAtCursorMode", _getIsPasteAtCursorMode_dec, UserPreferencesManager);
|
|
167
171
|
__decorateElement(_init, 1, "getEnhancedA11yMode", _getEnhancedA11yMode_dec, UserPreferencesManager);
|
|
168
172
|
__decorateElement(_init, 1, "getInputMode", _getInputMode_dec, UserPreferencesManager);
|
|
173
|
+
__decorateElement(_init, 1, "getIsZoomDirectionInverted", _getIsZoomDirectionInverted_dec, UserPreferencesManager);
|
|
169
174
|
__decoratorMetadata(_init, UserPreferencesManager);
|
|
170
175
|
export {
|
|
171
176
|
UserPreferencesManager
|